summaryrefslogtreecommitdiffstats
path: root/src/drivers/usb
diff options
context:
space:
mode:
authorSimon Rettberg2026-01-28 12:53:53 +0100
committerSimon Rettberg2026-01-28 12:53:53 +0100
commit8e82785c584dc13e20f9229decb95bd17bbe9cd1 (patch)
treea8b359e59196be5b2e3862bed189107f4bc9975f /src/drivers/usb
parentMerge branch 'master' into openslx (diff)
parent[prefix] Make unlzma.S compatible with 386 class CPUs (diff)
downloadipxe-openslx.tar.gz
ipxe-openslx.tar.xz
ipxe-openslx.zip
Merge branch 'master' into openslxopenslx
Diffstat (limited to 'src/drivers/usb')
-rw-r--r--src/drivers/usb/dwusb.c131
-rw-r--r--src/drivers/usb/dwusb.h23
-rw-r--r--src/drivers/usb/ehci.c1
-rw-r--r--src/drivers/usb/ehci.h1
-rw-r--r--src/drivers/usb/uhci.c1
-rw-r--r--src/drivers/usb/uhci.h1
-rw-r--r--src/drivers/usb/usbblk.c12
-rw-r--r--src/drivers/usb/usbblk.h1
-rw-r--r--src/drivers/usb/usbhub.c1
-rw-r--r--src/drivers/usb/usbhub.h1
-rw-r--r--src/drivers/usb/usbio.c148
-rw-r--r--src/drivers/usb/usbnet.c1
-rw-r--r--src/drivers/usb/xhci.c149
-rw-r--r--src/drivers/usb/xhci.h1179
14 files changed, 313 insertions, 1337 deletions
diff --git a/src/drivers/usb/dwusb.c b/src/drivers/usb/dwusb.c
new file mode 100644
index 000000000..1bae2ce74
--- /dev/null
+++ b/src/drivers/usb/dwusb.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2025 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program 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 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ipxe/timer.h>
+#include <ipxe/devtree.h>
+#include <ipxe/fdt.h>
+#include "dwusb.h"
+
+/** @file
+ *
+ * Synopsys DesignWare USB3 host controller driver
+ *
+ */
+
+/**
+ * Probe devicetree device
+ *
+ * @v dt Devicetree device
+ * @v offset Starting node offset
+ * @ret rc Return status code
+ */
+static int dwusb_probe ( struct dt_device *dt, unsigned int offset ) {
+ struct xhci_device *xhci;
+ uint32_t gctl;
+ int rc;
+
+ /* Allocate and initialise structure */
+ xhci = zalloc ( sizeof ( *xhci ) );
+ if ( ! xhci ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+ xhci->dev = &dt->dev;
+ xhci->dma = &dt->dma;
+
+ /* Map registers */
+ xhci->regs = dt_ioremap ( dt, offset, 0, 0 );
+ if ( ! xhci->regs ) {
+ rc = -ENODEV;
+ goto err_ioremap;
+ }
+
+ /* Reset via global core control register */
+ gctl = readl ( xhci->regs + DWUSB_GCTL );
+ writel ( ( gctl | DWUSB_GCTL_RESET ), ( xhci->regs + DWUSB_GCTL ) );
+ mdelay ( 100 );
+ writel ( gctl, ( xhci->regs + DWUSB_GCTL ) );
+
+ /* Configure as a host controller */
+ gctl &= ~DWUSB_GCTL_PRTDIR_MASK;
+ gctl |= DWUSB_GCTL_PRTDIR_HOST;
+ writel ( gctl, ( xhci->regs + DWUSB_GCTL ) );
+
+ /* Initialise xHCI device */
+ xhci_init ( xhci );
+
+ /* Register xHCI device */
+ if ( ( rc = xhci_register ( xhci ) ) != 0 ) {
+ DBGC ( xhci, "XHCI %s could not register: %s\n",
+ xhci->name, strerror ( rc ) );
+ goto err_register;
+ }
+
+ dt_set_drvdata ( dt, xhci );
+ return 0;
+
+ xhci_unregister ( xhci );
+ err_register:
+ iounmap ( xhci->regs );
+ err_ioremap:
+ free ( xhci );
+ err_alloc:
+ return rc;
+}
+
+/**
+ * Remove devicetree device
+ *
+ * @v dt Devicetree device
+ */
+static void dwusb_remove ( struct dt_device *dt ) {
+ struct xhci_device *xhci = dt_get_drvdata ( dt );
+
+ /* Unregister xHCI device */
+ xhci_unregister ( xhci );
+
+ /* Unmap registers */
+ iounmap ( xhci->regs );
+
+ /* Free device */
+ free ( xhci );
+}
+
+/** DesignWare USB3 compatible model identifiers */
+static const char * dwusb_ids[] = {
+ "snps,dwc3",
+};
+
+/** DesignWare USB3 devicetree driver */
+struct dt_driver dwusb_driver __dt_driver = {
+ .name = "dwusb",
+ .ids = dwusb_ids,
+ .id_count = ( sizeof ( dwusb_ids ) / sizeof ( dwusb_ids[0] ) ),
+ .probe = dwusb_probe,
+ .remove = dwusb_remove,
+};
diff --git a/src/drivers/usb/dwusb.h b/src/drivers/usb/dwusb.h
new file mode 100644
index 000000000..523f7ba81
--- /dev/null
+++ b/src/drivers/usb/dwusb.h
@@ -0,0 +1,23 @@
+#ifndef _DWUSB_H
+#define _DWUSB_H
+
+/** @file
+ *
+ * Synopsys DesignWare USB3 host controller driver
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <ipxe/xhci.h>
+
+/** Global core control register */
+#define DWUSB_GCTL 0xc110
+#define DWUSB_GCTL_PRTDIR( x ) ( (x) << 12 ) /**< Port direction */
+#define DWUSB_GCTL_PRTDIR_HOST \
+ DWUSB_GCTL_PRTDIR ( 1 ) /**< Operate as a host */
+#define DWUSB_GCTL_PRTDIR_MASK \
+ DWUSB_GCTL_PRTDIR ( 3 ) /**< Port direction mask */
+#define DWUSB_GCTL_RESET 0x00000800 /**< Core soft reset */
+
+#endif /* _DWUSB_H */
diff --git a/src/drivers/usb/ehci.c b/src/drivers/usb/ehci.c
index 77022a47d..9f9d94175 100644
--- a/src/drivers/usb/ehci.c
+++ b/src/drivers/usb/ehci.c
@@ -22,6 +22,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#include <stdlib.h>
#include <unistd.h>
diff --git a/src/drivers/usb/ehci.h b/src/drivers/usb/ehci.h
index 42e282e92..a0166bc63 100644
--- a/src/drivers/usb/ehci.h
+++ b/src/drivers/usb/ehci.h
@@ -8,6 +8,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#include <ipxe/pci.h>
#include <ipxe/usb.h>
diff --git a/src/drivers/usb/uhci.c b/src/drivers/usb/uhci.c
index 47474bdc7..2c70a11bd 100644
--- a/src/drivers/usb/uhci.c
+++ b/src/drivers/usb/uhci.c
@@ -22,6 +22,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#include <strings.h>
#include <unistd.h>
diff --git a/src/drivers/usb/uhci.h b/src/drivers/usb/uhci.h
index ba4c28f7e..629f6ae3b 100644
--- a/src/drivers/usb/uhci.h
+++ b/src/drivers/usb/uhci.h
@@ -8,6 +8,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#include <assert.h>
#include <ipxe/pci.h>
diff --git a/src/drivers/usb/usbblk.c b/src/drivers/usb/usbblk.c
index 5a086d3f8..b42c70645 100644
--- a/src/drivers/usb/usbblk.c
+++ b/src/drivers/usb/usbblk.c
@@ -22,9 +22,11 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#include <stdint.h>
#include <stdlib.h>
+#include <string.h>
#include <errno.h>
#include <ipxe/usb.h>
#include <ipxe/scsi.h>
@@ -205,7 +207,7 @@ static int usbblk_out_data ( struct usbblk_device *usbblk ) {
/* Calculate length */
assert ( cmd->tag );
- assert ( cmd->scsi.data_out != UNULL );
+ assert ( cmd->scsi.data_out != NULL );
assert ( cmd->offset < cmd->scsi.data_out_len );
len = ( cmd->scsi.data_out_len - cmd->offset );
if ( len > USBBLK_MAX_LEN )
@@ -220,8 +222,8 @@ static int usbblk_out_data ( struct usbblk_device *usbblk ) {
}
/* Populate I/O buffer */
- copy_from_user ( iob_put ( iobuf, len ), cmd->scsi.data_out,
- cmd->offset, len );
+ memcpy ( iob_put ( iobuf, len ),
+ ( cmd->scsi.data_out + cmd->offset ), len );
/* Send data */
if ( ( rc = usb_stream ( &usbblk->out, iobuf, 0 ) ) != 0 ) {
@@ -332,12 +334,12 @@ static int usbblk_in_data ( struct usbblk_device *usbblk, const void *data,
/* Sanity checks */
assert ( cmd->tag );
- assert ( cmd->scsi.data_in != UNULL );
+ assert ( cmd->scsi.data_in != NULL );
assert ( cmd->offset <= cmd->scsi.data_in_len );
assert ( len <= ( cmd->scsi.data_in_len - cmd->offset ) );
/* Store data */
- copy_to_user ( cmd->scsi.data_in, cmd->offset, data, len );
+ memcpy ( ( cmd->scsi.data_in + cmd->offset ), data, len );
cmd->offset += len;
return 0;
diff --git a/src/drivers/usb/usbblk.h b/src/drivers/usb/usbblk.h
index 65d0705e3..1fa0ebad8 100644
--- a/src/drivers/usb/usbblk.h
+++ b/src/drivers/usb/usbblk.h
@@ -8,6 +8,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#include <stdint.h>
#include <ipxe/usb.h>
diff --git a/src/drivers/usb/usbhub.c b/src/drivers/usb/usbhub.c
index 28d6cb33d..1d7b03e77 100644
--- a/src/drivers/usb/usbhub.c
+++ b/src/drivers/usb/usbhub.c
@@ -22,6 +22,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#include <stdlib.h>
#include <string.h>
diff --git a/src/drivers/usb/usbhub.h b/src/drivers/usb/usbhub.h
index a5f123acc..9768b81a9 100644
--- a/src/drivers/usb/usbhub.h
+++ b/src/drivers/usb/usbhub.h
@@ -8,6 +8,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#include <ipxe/usb.h>
#include <ipxe/list.h>
diff --git a/src/drivers/usb/usbio.c b/src/drivers/usb/usbio.c
index 278b43cd3..97860a281 100644
--- a/src/drivers/usb/usbio.c
+++ b/src/drivers/usb/usbio.c
@@ -187,10 +187,6 @@ static int usbio_open ( struct usbio_device *usbio, unsigned int interface ) {
EFI_DEVICE_PATH_PROTOCOL *path;
EFI_DEVICE_PATH_PROTOCOL *end;
USB_DEVICE_PATH *usbpath;
- union {
- void *interface;
- EFI_USB_IO_PROTOCOL *io;
- } u;
EFI_STATUS efirc;
int rc;
@@ -229,13 +225,9 @@ static int usbio_open ( struct usbio_device *usbio, unsigned int interface ) {
}
/* Open USB I/O protocol on this handle */
- if ( ( efirc = bs->OpenProtocol ( intf->handle,
- &efi_usb_io_protocol_guid,
- &u.interface, efi_image_handle,
- intf->handle,
- ( EFI_OPEN_PROTOCOL_BY_DRIVER |
- EFI_OPEN_PROTOCOL_EXCLUSIVE )))!=0){
- rc = -EEFI ( efirc );
+ if ( ( rc = efi_open_by_driver ( intf->handle,
+ &efi_usb_io_protocol_guid,
+ &intf->io ) ) != 0 ) {
DBGC ( usbio, "USBIO %s cannot open ",
efi_handle_name ( handle ) );
DBGC ( usbio, "%s: %s\n",
@@ -244,7 +236,6 @@ static int usbio_open ( struct usbio_device *usbio, unsigned int interface ) {
&efi_usb_io_protocol_guid );
return rc;
}
- intf->io = u.io;
/* Increment usage count */
intf->count++;
@@ -259,7 +250,6 @@ static int usbio_open ( struct usbio_device *usbio, unsigned int interface ) {
* @v interface Interface number
*/
static void usbio_close ( struct usbio_device *usbio, unsigned int interface ) {
- EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
struct usbio_interface *intf = &usbio->interface[interface];
/* Sanity checks */
@@ -274,8 +264,7 @@ static void usbio_close ( struct usbio_device *usbio, unsigned int interface ) {
return;
/* Close USB I/O protocol */
- bs->CloseProtocol ( intf->handle, &efi_usb_io_protocol_guid,
- efi_image_handle, intf->handle );
+ efi_close_by_driver ( intf->handle, &efi_usb_io_protocol_guid );
}
/******************************************************************************
@@ -1297,49 +1286,40 @@ static struct usb_host_operations usbio_operations = {
* @ret rc Return status code
*/
static int usbio_supported ( EFI_HANDLE handle ) {
- EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_USB_DEVICE_DESCRIPTOR device;
EFI_USB_INTERFACE_DESCRIPTOR interface;
struct usb_function_descriptor desc;
struct usb_driver *driver;
struct usb_device_id *id;
- union {
- void *interface;
- EFI_USB_IO_PROTOCOL *io;
- } usb;
+ EFI_USB_IO_PROTOCOL *io;
EFI_STATUS efirc;
int rc;
/* Get protocol */
- if ( ( efirc = bs->OpenProtocol ( handle, &efi_usb_io_protocol_guid,
- &usb.interface, efi_image_handle,
- handle,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){
- rc = -EEFI ( efirc );
+ if ( ( rc = efi_open ( handle, &efi_usb_io_protocol_guid,
+ &io ) ) != 0 ) {
DBGCP ( handle, "USB %s is not a USB device\n",
efi_handle_name ( handle ) );
- goto err_open_protocol;
+ return rc;
}
/* Get device descriptor */
- if ( ( efirc = usb.io->UsbGetDeviceDescriptor ( usb.io,
- &device ) ) != 0 ) {
+ if ( ( efirc = io->UsbGetDeviceDescriptor ( io, &device ) ) != 0 ) {
rc = -EEFI ( efirc );
DBGC ( handle, "USB %s could not get device descriptor: "
"%s\n", efi_handle_name ( handle ), strerror ( rc ) );
- goto err_get_device_descriptor;
+ return rc;
}
memset ( &desc, 0, sizeof ( desc ) );
desc.vendor = device.IdVendor;
desc.product = device.IdProduct;
/* Get interface descriptor */
- if ( ( efirc = usb.io->UsbGetInterfaceDescriptor ( usb.io,
- &interface ) ) !=0){
+ if ( ( efirc = io->UsbGetInterfaceDescriptor ( io, &interface ) ) != 0){
rc = -EEFI ( efirc );
DBGC ( handle, "USB %s could not get interface descriptor: "
"%s\n", efi_handle_name ( handle ), strerror ( rc ) );
- goto err_get_interface_descriptor;
+ return rc;
}
desc.class.class.class = interface.InterfaceClass;
desc.class.class.subclass = interface.InterfaceSubClass;
@@ -1347,21 +1327,10 @@ static int usbio_supported ( EFI_HANDLE handle ) {
/* Look for a driver for this interface */
driver = usb_find_driver ( &desc, &id );
- if ( ! driver ) {
- rc = -ENOTSUP;
- goto err_unsupported;
- }
-
- /* Success */
- rc = 0;
+ if ( ! driver )
+ return -ENOTSUP;
- err_unsupported:
- err_get_interface_descriptor:
- err_get_device_descriptor:
- bs->CloseProtocol ( handle, &efi_usb_io_protocol_guid,
- efi_image_handle, handle );
- err_open_protocol:
- return rc;
+ return 0;
}
/**
@@ -1477,39 +1446,27 @@ static int usbio_config ( struct usbio_device *usbio ) {
* @ret rc Return status code
*/
static int usbio_path ( struct usbio_device *usbio ) {
- EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_HANDLE handle = usbio->handle;
EFI_DEVICE_PATH_PROTOCOL *path;
EFI_DEVICE_PATH_PROTOCOL *end;
USB_DEVICE_PATH *usbpath;
- union {
- void *interface;
- EFI_DEVICE_PATH_PROTOCOL *path;
- } u;
size_t len;
- EFI_STATUS efirc;
int rc;
/* Open device path protocol */
- if ( ( efirc = bs->OpenProtocol ( handle,
- &efi_device_path_protocol_guid,
- &u.interface, efi_image_handle,
- handle,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){
- rc = -EEFI ( efirc );
+ if ( ( rc = efi_open ( handle, &efi_device_path_protocol_guid,
+ &path ) ) != 0 ) {
DBGC ( usbio, "USBIO %s cannot open device path protocol: "
"%s\n", efi_handle_name ( handle ), strerror ( rc ) );
- goto err_open_protocol;
+ return rc;
}
- path = u.interface;
/* Locate end of device path and sanity check */
len = efi_path_len ( path );
if ( len < sizeof ( *usbpath ) ) {
DBGC ( usbio, "USBIO %s underlength device path\n",
efi_handle_name ( handle ) );
- rc = -EINVAL;
- goto err_underlength;
+ return -EINVAL;
}
usbpath = ( ( ( void * ) path ) + len - sizeof ( *usbpath ) );
if ( ! ( ( usbpath->Header.Type == MESSAGING_DEVICE_PATH ) &&
@@ -1517,34 +1474,18 @@ static int usbio_path ( struct usbio_device *usbio ) {
DBGC ( usbio, "USBIO %s not a USB device path: ",
efi_handle_name ( handle ) );
DBGC ( usbio, "%s\n", efi_devpath_text ( path ) );
- rc = -EINVAL;
- goto err_non_usb;
+ return -EINVAL;
}
/* Allocate copy of device path */
usbio->path = malloc ( len + sizeof ( *end ) );
- if ( ! usbio->path ) {
- rc = -ENOMEM;
- goto err_alloc;
- }
+ if ( ! usbio->path )
+ return -ENOMEM;
memcpy ( usbio->path, path, ( len + sizeof ( *end ) ) );
usbio->usbpath = ( ( ( void * ) usbio->path ) + len -
sizeof ( *usbpath ) );
- /* Close protocol */
- bs->CloseProtocol ( handle, &efi_device_path_protocol_guid,
- efi_image_handle, handle );
-
return 0;
-
- free ( usbio->path );
- err_alloc:
- err_non_usb:
- err_underlength:
- bs->CloseProtocol ( handle, &efi_device_path_protocol_guid,
- efi_image_handle, handle );
- err_open_protocol:
- return rc;
}
/**
@@ -1602,21 +1543,35 @@ static int usbio_interfaces ( struct usbio_device *usbio ) {
}
/**
+ * Exclude existing drivers
+ *
+ * @v device EFI device handle
+ * @ret rc Return status code
+ */
+static int usbio_exclude ( EFI_HANDLE device ) {
+ EFI_GUID *protocol = &efi_usb_io_protocol_guid;
+ int rc;
+
+ /* Exclude existing USB I/O protocol drivers */
+ if ( ( rc = efi_driver_exclude ( device, protocol ) ) != 0 ) {
+ DBGC ( device, "USBIO %s could not exclude drivers: %s\n",
+ efi_handle_name ( device ), strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
* Attach driver to device
*
* @v efidev EFI device
* @ret rc Return status code
*/
static int usbio_start ( struct efi_device *efidev ) {
- EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_HANDLE handle = efidev->device;
struct usbio_device *usbio;
struct usb_port *port;
- union {
- void *interface;
- EFI_USB_IO_PROTOCOL *io;
- } u;
- EFI_STATUS efirc;
int rc;
/* Allocate and initialise structure */
@@ -1630,18 +1585,13 @@ static int usbio_start ( struct efi_device *efidev ) {
INIT_LIST_HEAD ( &usbio->endpoints );
/* Open USB I/O protocol */
- if ( ( efirc = bs->OpenProtocol ( handle, &efi_usb_io_protocol_guid,
- &u.interface, efi_image_handle,
- handle,
- ( EFI_OPEN_PROTOCOL_BY_DRIVER |
- EFI_OPEN_PROTOCOL_EXCLUSIVE )))!=0){
- rc = -EEFI ( efirc );
+ if ( ( rc = efi_open_by_driver ( handle, &efi_usb_io_protocol_guid,
+ &usbio->io ) ) != 0 ) {
DBGC ( usbio, "USBIO %s cannot open USB I/O protocol: %s\n",
efi_handle_name ( handle ), strerror ( rc ) );
DBGC_EFI_OPENERS ( usbio, handle, &efi_usb_io_protocol_guid );
goto err_open_usbio;
}
- usbio->io = u.io;
/* Describe generic device */
efi_device_info ( handle, "USB", &usbio->dev );
@@ -1692,8 +1642,7 @@ static int usbio_start ( struct efi_device *efidev ) {
free ( usbio->config );
err_config:
list_del ( &usbio->dev.siblings );
- bs->CloseProtocol ( handle, &efi_usb_io_protocol_guid,
- efi_image_handle, handle );
+ efi_close_by_driver ( handle, &efi_usb_io_protocol_guid );
err_open_usbio:
free ( usbio );
err_alloc:
@@ -1706,7 +1655,6 @@ static int usbio_start ( struct efi_device *efidev ) {
* @v efidev EFI device
*/
static void usbio_stop ( struct efi_device *efidev ) {
- EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_HANDLE handle = efidev->device;
struct usbio_device *usbio = efidev_get_drvdata ( efidev );
@@ -1716,15 +1664,15 @@ static void usbio_stop ( struct efi_device *efidev ) {
free ( usbio->path );
free ( usbio->config );
list_del ( &usbio->dev.siblings );
- bs->CloseProtocol ( handle, &efi_usb_io_protocol_guid,
- efi_image_handle, handle );
+ efi_close_by_driver ( handle, &efi_usb_io_protocol_guid );
free ( usbio );
}
/** EFI USB I/O driver */
-struct efi_driver usbio_driver __efi_driver ( EFI_DRIVER_NORMAL ) = {
+struct efi_driver usbio_driver __efi_driver ( EFI_DRIVER_HARDWARE ) = {
.name = "USBIO",
.supported = usbio_supported,
+ .exclude = usbio_exclude,
.start = usbio_start,
.stop = usbio_stop,
};
diff --git a/src/drivers/usb/usbnet.c b/src/drivers/usb/usbnet.c
index 0fac00b56..e773ab882 100644
--- a/src/drivers/usb/usbnet.c
+++ b/src/drivers/usb/usbnet.c
@@ -22,6 +22,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#include <string.h>
#include <errno.h>
diff --git a/src/drivers/usb/xhci.c b/src/drivers/usb/xhci.c
index 3247ee69c..f812ed338 100644
--- a/src/drivers/usb/xhci.c
+++ b/src/drivers/usb/xhci.c
@@ -22,6 +22,7 @@
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
#include <stdlib.h>
#include <stdio.h>
@@ -35,7 +36,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/usb.h>
#include <ipxe/init.h>
#include <ipxe/profile.h>
-#include "xhci.h"
+#include <ipxe/xhci.h>
/** @file
*
@@ -259,9 +260,8 @@ static struct profiler xhci_transfer_profiler __profiler =
* Initialise device
*
* @v xhci xHCI device
- * @v regs MMIO registers
*/
-static void xhci_init ( struct xhci_device *xhci, void *regs ) {
+void xhci_init ( struct xhci_device *xhci ) {
uint32_t hcsparams1;
uint32_t hcsparams2;
uint32_t hccparams1;
@@ -270,8 +270,11 @@ static void xhci_init ( struct xhci_device *xhci, void *regs ) {
size_t rtsoff;
size_t dboff;
+ /* Set device name */
+ xhci->name = xhci->dev->name;
+
/* Locate capability, operational, runtime, and doorbell registers */
- xhci->cap = regs;
+ xhci->cap = xhci->regs;
caplength = readb ( xhci->cap + XHCI_CAP_CAPLENGTH );
rtsoff = readl ( xhci->cap + XHCI_CAP_RTSOFF );
dboff = readl ( xhci->cap + XHCI_CAP_DBOFF );
@@ -310,6 +313,10 @@ static void xhci_init ( struct xhci_device *xhci, void *regs ) {
assert ( ( ( xhci->pagesize ) & ( xhci->pagesize - 1 ) ) == 0 );
DBGC2 ( xhci, "XHCI %s page size %zd bytes\n",
xhci->name, xhci->pagesize );
+
+ /* Configure DMA device */
+ if ( xhci->dma && xhci->addr64 )
+ dma_set_mask_64bit ( xhci->dma );
}
/**
@@ -1000,7 +1007,7 @@ static int xhci_scratchpad_alloc ( struct xhci_device *xhci ) {
rc = -ENOMEM;
goto err_alloc;
}
- memset_user ( scratch->buffer, 0, 0, buffer_len );
+ memset ( scratch->buffer, 0, buffer_len );
/* Allocate scratchpad array */
array_len = ( scratch->count * sizeof ( scratch->array[0] ) );
@@ -1014,8 +1021,7 @@ static int xhci_scratchpad_alloc ( struct xhci_device *xhci ) {
}
/* Populate scratchpad array */
- addr = dma_phys ( &scratch->buffer_map,
- user_to_phys ( scratch->buffer, 0 ) );
+ addr = dma ( &scratch->buffer_map, scratch->buffer );
for ( i = 0 ; i < scratch->count ; i++ ) {
scratch->array[i] = cpu_to_le64 ( addr );
addr += xhci->pagesize;
@@ -1027,8 +1033,8 @@ static int xhci_scratchpad_alloc ( struct xhci_device *xhci ) {
scratch->array ) );
DBGC2 ( xhci, "XHCI %s scratchpad [%08lx,%08lx) array [%08lx,%08lx)\n",
- xhci->name, user_to_phys ( scratch->buffer, 0 ),
- user_to_phys ( scratch->buffer, buffer_len ),
+ xhci->name, virt_to_phys ( scratch->buffer ),
+ ( virt_to_phys ( scratch->buffer ) + buffer_len ),
virt_to_phys ( scratch->array ),
( virt_to_phys ( scratch->array ) + array_len ) );
return 0;
@@ -2771,6 +2777,7 @@ static int xhci_endpoint_stream ( struct usb_endpoint *ep,
*/
static int xhci_device_open ( struct usb_device *usb ) {
struct xhci_device *xhci = usb_bus_get_hostdata ( usb->port->hub->bus );
+ struct usb_port *root_port = usb_root_hub_port ( usb );
struct usb_port *tt = usb_transaction_translator ( usb );
struct xhci_slot *slot;
struct xhci_slot *tt_slot;
@@ -2780,7 +2787,7 @@ static int xhci_device_open ( struct usb_device *usb ) {
int rc;
/* Determine applicable slot type */
- type = xhci_port_slot_type ( xhci, usb->port->address );
+ type = xhci_port_slot_type ( xhci, root_port->address );
if ( type < 0 ) {
rc = type;
DBGC ( xhci, "XHCI %s-%d has no slot type\n",
@@ -3264,7 +3271,7 @@ static int xhci_root_clear_tt ( struct usb_hub *hub, struct usb_port *port,
/******************************************************************************
*
- * PCI interface
+ * Hardware-independent interface
*
******************************************************************************
*/
@@ -3304,6 +3311,75 @@ static struct usb_host_operations xhci_operations = {
};
/**
+ * Register xHCI controller
+ *
+ * @v xhci xHCI device
+ * @ret rc Return status code
+ */
+int xhci_register ( struct xhci_device *xhci ) {
+ struct usb_port *port;
+ unsigned int i;
+ int rc;
+
+ /* Reset device */
+ if ( ( rc = xhci_reset ( xhci ) ) != 0 )
+ goto err_reset;
+
+ /* Allocate USB bus */
+ xhci->bus = alloc_usb_bus ( xhci->dev, xhci->ports, XHCI_MTU,
+ &xhci_operations );
+ if ( ! xhci->bus ) {
+ rc = -ENOMEM;
+ goto err_alloc_bus;
+ }
+ usb_bus_set_hostdata ( xhci->bus, xhci );
+ usb_hub_set_drvdata ( xhci->bus->hub, xhci );
+
+ /* Set port protocols */
+ for ( i = 1 ; i <= xhci->ports ; i++ ) {
+ port = usb_port ( xhci->bus->hub, i );
+ port->protocol = xhci_port_protocol ( xhci, i );
+ }
+
+ /* Register USB bus */
+ if ( ( rc = register_usb_bus ( xhci->bus ) ) != 0 )
+ goto err_register;
+
+ return 0;
+
+ unregister_usb_bus ( xhci->bus );
+ err_register:
+ free_usb_bus ( xhci->bus );
+ err_alloc_bus:
+ xhci_reset ( xhci );
+ err_reset:
+ return rc;
+}
+
+/**
+ * Unregister xHCI controller
+ *
+ * @v xhci xHCI device
+ */
+void xhci_unregister ( struct xhci_device *xhci ) {
+ struct usb_bus *bus = xhci->bus;
+
+ /* Unregister and free USB bus */
+ unregister_usb_bus ( bus );
+ free_usb_bus ( bus );
+
+ /* Reset device */
+ xhci_reset ( xhci );
+}
+
+/******************************************************************************
+ *
+ * PCI interface
+ *
+ ******************************************************************************
+ */
+
+/**
* Fix Intel PCH-specific quirks
*
* @v xhci xHCI device
@@ -3365,10 +3441,8 @@ static void xhci_pch_undo ( struct xhci_device *xhci, struct pci_device *pci ) {
*/
static int xhci_probe ( struct pci_device *pci ) {
struct xhci_device *xhci;
- struct usb_port *port;
unsigned long bar_start;
size_t bar_size;
- unsigned int i;
int rc;
/* Allocate and initialise structure */
@@ -3377,7 +3451,8 @@ static int xhci_probe ( struct pci_device *pci ) {
rc = -ENOMEM;
goto err_alloc;
}
- xhci->name = pci->dev.name;
+ xhci->dev = &pci->dev;
+ xhci->dma = &pci->dma;
xhci->quirks = pci->id->driver_data;
/* Fix up PCI device */
@@ -3393,12 +3468,7 @@ static int xhci_probe ( struct pci_device *pci ) {
}
/* Initialise xHCI device */
- xhci_init ( xhci, xhci->regs );
-
- /* Configure DMA device */
- xhci->dma = &pci->dma;
- if ( xhci->addr64 )
- dma_set_mask_64bit ( xhci->dma );
+ xhci_init ( xhci );
/* Initialise USB legacy support and claim ownership */
xhci_legacy_init ( xhci );
@@ -3408,39 +3478,15 @@ static int xhci_probe ( struct pci_device *pci ) {
if ( xhci->quirks & XHCI_PCH )
xhci_pch_fix ( xhci, pci );
- /* Reset device */
- if ( ( rc = xhci_reset ( xhci ) ) != 0 )
- goto err_reset;
-
- /* Allocate USB bus */
- xhci->bus = alloc_usb_bus ( &pci->dev, xhci->ports, XHCI_MTU,
- &xhci_operations );
- if ( ! xhci->bus ) {
- rc = -ENOMEM;
- goto err_alloc_bus;
- }
- usb_bus_set_hostdata ( xhci->bus, xhci );
- usb_hub_set_drvdata ( xhci->bus->hub, xhci );
-
- /* Set port protocols */
- for ( i = 1 ; i <= xhci->ports ; i++ ) {
- port = usb_port ( xhci->bus->hub, i );
- port->protocol = xhci_port_protocol ( xhci, i );
- }
-
- /* Register USB bus */
- if ( ( rc = register_usb_bus ( xhci->bus ) ) != 0 )
+ /* Register xHCI device */
+ if ( ( rc = xhci_register ( xhci ) ) != 0 )
goto err_register;
pci_set_drvdata ( pci, xhci );
return 0;
- unregister_usb_bus ( xhci->bus );
+ xhci_unregister ( xhci );
err_register:
- free_usb_bus ( xhci->bus );
- err_alloc_bus:
- xhci_reset ( xhci );
- err_reset:
if ( xhci->quirks & XHCI_PCH )
xhci_pch_undo ( xhci, pci );
xhci_legacy_release ( xhci );
@@ -3458,7 +3504,6 @@ static int xhci_probe ( struct pci_device *pci ) {
*/
static void xhci_remove ( struct pci_device *pci ) {
struct xhci_device *xhci = pci_get_drvdata ( pci );
- struct usb_bus *bus = xhci->bus;
uint16_t command;
/* Some systems are observed to disable bus mastering on
@@ -3473,12 +3518,10 @@ static void xhci_remove ( struct pci_device *pci ) {
xhci_fail ( xhci );
}
- /* Unregister and free USB bus */
- unregister_usb_bus ( bus );
- free_usb_bus ( bus );
+ /* Unregister xHCI controller */
+ xhci_unregister ( xhci );
- /* Reset device and undo any PCH-specific fixes */
- xhci_reset ( xhci );
+ /* Undo any PCH-specific fixes */
if ( xhci->quirks & XHCI_PCH )
xhci_pch_undo ( xhci, pci );
diff --git a/src/drivers/usb/xhci.h b/src/drivers/usb/xhci.h
deleted file mode 100644
index a3c8888af..000000000
--- a/src/drivers/usb/xhci.h
+++ /dev/null
@@ -1,1179 +0,0 @@
-#ifndef _IPXE_XHCI_H
-#define _IPXE_XHCI_H
-
-/** @file
- *
- * USB eXtensible Host Controller Interface (xHCI) driver
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#include <assert.h>
-#include <ipxe/pci.h>
-#include <ipxe/uaccess.h>
-#include <ipxe/usb.h>
-
-/** Minimum alignment required for data structures
- *
- * With the exception of the scratchpad buffer pages (which are
- * page-aligned), data structures used by xHCI generally require from
- * 16 to 64 byte alignment and must not cross an (xHCI) page boundary.
- * We simplify this requirement by aligning each structure on its own
- * size, with a minimum of a 64 byte alignment.
- */
-#define XHCI_MIN_ALIGN 64
-
-/** Maximum transfer size */
-#define XHCI_MTU 65536
-
-/** xHCI PCI BAR */
-#define XHCI_BAR PCI_BASE_ADDRESS_0
-
-/** Capability register length */
-#define XHCI_CAP_CAPLENGTH 0x00
-
-/** Host controller interface version number */
-#define XHCI_CAP_HCIVERSION 0x02
-
-/** Structural parameters 1 */
-#define XHCI_CAP_HCSPARAMS1 0x04
-
-/** Number of device slots */
-#define XHCI_HCSPARAMS1_SLOTS(params) ( ( (params) >> 0 ) & 0xff )
-
-/** Number of interrupters */
-#define XHCI_HCSPARAMS1_INTRS(params) ( ( (params) >> 8 ) & 0x3ff )
-
-/** Number of ports */
-#define XHCI_HCSPARAMS1_PORTS(params) ( ( (params) >> 24 ) & 0xff )
-
-/** Structural parameters 2 */
-#define XHCI_CAP_HCSPARAMS2 0x08
-
-/** Number of page-sized scratchpad buffers */
-#define XHCI_HCSPARAMS2_SCRATCHPADS(params) \
- ( ( ( (params) >> 16 ) & 0x3e0 ) | ( ( (params) >> 27 ) & 0x1f ) )
-
-/** Capability parameters */
-#define XHCI_CAP_HCCPARAMS1 0x10
-
-/** 64-bit addressing capability */
-#define XHCI_HCCPARAMS1_ADDR64(params) ( ( (params) >> 0 ) & 0x1 )
-
-/** Context size shift */
-#define XHCI_HCCPARAMS1_CSZ_SHIFT(params) ( 5 + ( ( (params) >> 2 ) & 0x1 ) )
-
-/** xHCI extended capabilities pointer */
-#define XHCI_HCCPARAMS1_XECP(params) ( ( ( (params) >> 16 ) & 0xffff ) << 2 )
-
-/** Doorbell offset */
-#define XHCI_CAP_DBOFF 0x14
-
-/** Runtime register space offset */
-#define XHCI_CAP_RTSOFF 0x18
-
-/** xHCI extended capability ID */
-#define XHCI_XECP_ID(xecp) ( ( (xecp) >> 0 ) & 0xff )
-
-/** Next xHCI extended capability pointer */
-#define XHCI_XECP_NEXT(xecp) ( ( ( (xecp) >> 8 ) & 0xff ) << 2 )
-
-/** USB legacy support extended capability */
-#define XHCI_XECP_ID_LEGACY 1
-
-/** USB legacy support BIOS owned semaphore */
-#define XHCI_USBLEGSUP_BIOS 0x02
-
-/** USB legacy support BIOS ownership flag */
-#define XHCI_USBLEGSUP_BIOS_OWNED 0x01
-
-/** USB legacy support OS owned semaphore */
-#define XHCI_USBLEGSUP_OS 0x03
-
-/** USB legacy support OS ownership flag */
-#define XHCI_USBLEGSUP_OS_OWNED 0x01
-
-/** USB legacy support control/status */
-#define XHCI_USBLEGSUP_CTLSTS 0x04
-
-/** Supported protocol extended capability */
-#define XHCI_XECP_ID_SUPPORTED 2
-
-/** Supported protocol revision */
-#define XHCI_SUPPORTED_REVISION 0x00
-
-/** Supported protocol minor revision */
-#define XHCI_SUPPORTED_REVISION_VER(revision) ( ( (revision) >> 16 ) & 0xffff )
-
-/** Supported protocol name */
-#define XHCI_SUPPORTED_NAME 0x04
-
-/** Supported protocol ports */
-#define XHCI_SUPPORTED_PORTS 0x08
-
-/** Supported protocol port offset */
-#define XHCI_SUPPORTED_PORTS_OFFSET(ports) ( ( (ports) >> 0 ) & 0xff )
-
-/** Supported protocol port count */
-#define XHCI_SUPPORTED_PORTS_COUNT(ports) ( ( (ports) >> 8 ) & 0xff )
-
-/** Supported protocol PSI count */
-#define XHCI_SUPPORTED_PORTS_PSIC(ports) ( ( (ports) >> 28 ) & 0x0f )
-
-/** Supported protocol slot */
-#define XHCI_SUPPORTED_SLOT 0x0c
-
-/** Supported protocol slot type */
-#define XHCI_SUPPORTED_SLOT_TYPE(slot) ( ( (slot) >> 0 ) & 0x1f )
-
-/** Supported protocol PSI */
-#define XHCI_SUPPORTED_PSI(index) ( 0x10 + ( (index) * 4 ) )
-
-/** Supported protocol PSI value */
-#define XHCI_SUPPORTED_PSI_VALUE(psi) ( ( (psi) >> 0 ) & 0x0f )
-
-/** Supported protocol PSI mantissa */
-#define XHCI_SUPPORTED_PSI_MANTISSA(psi) ( ( (psi) >> 16 ) & 0xffff )
-
-/** Supported protocol PSI exponent */
-#define XHCI_SUPPORTED_PSI_EXPONENT(psi) ( ( (psi) >> 4 ) & 0x03 )
-
-/** Default PSI values */
-enum xhci_default_psi_value {
- /** Full speed (12Mbps) */
- XHCI_SPEED_FULL = 1,
- /** Low speed (1.5Mbps) */
- XHCI_SPEED_LOW = 2,
- /** High speed (480Mbps) */
- XHCI_SPEED_HIGH = 3,
- /** Super speed */
- XHCI_SPEED_SUPER = 4,
-};
-
-/** USB command register */
-#define XHCI_OP_USBCMD 0x00
-
-/** Run/stop */
-#define XHCI_USBCMD_RUN 0x00000001UL
-
-/** Host controller reset */
-#define XHCI_USBCMD_HCRST 0x00000002UL
-
-/** USB status register */
-#define XHCI_OP_USBSTS 0x04
-
-/** Host controller halted */
-#define XHCI_USBSTS_HCH 0x00000001UL
-
-/** Page size register */
-#define XHCI_OP_PAGESIZE 0x08
-
-/** Page size */
-#define XHCI_PAGESIZE(pagesize) ( (pagesize) << 12 )
-
-/** Device notifcation control register */
-#define XHCI_OP_DNCTRL 0x14
-
-/** Command ring control register */
-#define XHCI_OP_CRCR 0x18
-
-/** Command ring cycle state */
-#define XHCI_CRCR_RCS 0x00000001UL
-
-/** Command abort */
-#define XHCI_CRCR_CA 0x00000004UL
-
-/** Command ring running */
-#define XHCI_CRCR_CRR 0x00000008UL
-
-/** Device context base address array pointer */
-#define XHCI_OP_DCBAAP 0x30
-
-/** Configure register */
-#define XHCI_OP_CONFIG 0x38
-
-/** Maximum device slots enabled */
-#define XHCI_CONFIG_MAX_SLOTS_EN(slots) ( (slots) << 0 )
-
-/** Maximum device slots enabled mask */
-#define XHCI_CONFIG_MAX_SLOTS_EN_MASK \
- XHCI_CONFIG_MAX_SLOTS_EN ( 0xff )
-
-/** Port status and control register */
-#define XHCI_OP_PORTSC(port) ( 0x400 - 0x10 + ( (port) << 4 ) )
-
-/** Current connect status */
-#define XHCI_PORTSC_CCS 0x00000001UL
-
-/** Port enabled */
-#define XHCI_PORTSC_PED 0x00000002UL
-
-/** Port reset */
-#define XHCI_PORTSC_PR 0x00000010UL
-
-/** Port link state */
-#define XHCI_PORTSC_PLS(pls) ( (pls) << 5 )
-
-/** Disabled port link state */
-#define XHCI_PORTSC_PLS_DISABLED XHCI_PORTSC_PLS ( 4 )
-
-/** RxDetect port link state */
-#define XHCI_PORTSC_PLS_RXDETECT XHCI_PORTSC_PLS ( 5 )
-
-/** Port link state mask */
-#define XHCI_PORTSC_PLS_MASK XHCI_PORTSC_PLS ( 0xf )
-
-/** Port power */
-#define XHCI_PORTSC_PP 0x00000200UL
-
-/** Time to delay after enabling power to a port */
-#define XHCI_PORT_POWER_DELAY_MS 20
-
-/** Port speed ID value */
-#define XHCI_PORTSC_PSIV(portsc) ( ( (portsc) >> 10 ) & 0xf )
-
-/** Port indicator control */
-#define XHCI_PORTSC_PIC(indicators) ( (indicators) << 14 )
-
-/** Port indicator control mask */
-#define XHCI_PORTSC_PIC_MASK XHCI_PORTSC_PIC ( 3 )
-
-/** Port link state write strobe */
-#define XHCI_PORTSC_LWS 0x00010000UL
-
-/** Time to delay after writing the port link state */
-#define XHCI_LINK_STATE_DELAY_MS 100
-
-/** Connect status change */
-#define XHCI_PORTSC_CSC 0x00020000UL
-
-/** Port enabled/disabled change */
-#define XHCI_PORTSC_PEC 0x00040000UL
-
-/** Warm port reset change */
-#define XHCI_PORTSC_WRC 0x00080000UL
-
-/** Over-current change */
-#define XHCI_PORTSC_OCC 0x00100000UL
-
-/** Port reset change */
-#define XHCI_PORTSC_PRC 0x00200000UL
-
-/** Port link state change */
-#define XHCI_PORTSC_PLC 0x00400000UL
-
-/** Port config error change */
-#define XHCI_PORTSC_CEC 0x00800000UL
-
-/** Port status change mask */
-#define XHCI_PORTSC_CHANGE \
- ( XHCI_PORTSC_CSC | XHCI_PORTSC_PEC | XHCI_PORTSC_WRC | \
- XHCI_PORTSC_OCC | XHCI_PORTSC_PRC | XHCI_PORTSC_PLC | \
- XHCI_PORTSC_CEC )
-
-/** Port status and control bits which should be preserved
- *
- * The port status and control register is a horrendous mix of
- * differing semantics. Some bits are written to only when a separate
- * write strobe bit is set. Some bits should be preserved when
- * modifying other bits. Some bits will be cleared if written back as
- * a one. Most excitingly, the "port enabled" bit has the semantics
- * that 1=enabled, 0=disabled, yet writing a 1 will disable the port.
- */
-#define XHCI_PORTSC_PRESERVE ( XHCI_PORTSC_PP | XHCI_PORTSC_PIC_MASK )
-
-/** Port power management status and control register */
-#define XHCI_OP_PORTPMSC(port) ( 0x404 - 0x10 + ( (port) << 4 ) )
-
-/** Port link info register */
-#define XHCI_OP_PORTLI(port) ( 0x408 - 0x10 + ( (port) << 4 ) )
-
-/** Port hardware link power management control register */
-#define XHCI_OP_PORTHLPMC(port) ( 0x40c - 0x10 + ( (port) << 4 ) )
-
-/** Event ring segment table size register */
-#define XHCI_RUN_ERSTSZ(intr) ( 0x28 + ( (intr) << 5 ) )
-
-/** Event ring segment table base address register */
-#define XHCI_RUN_ERSTBA(intr) ( 0x30 + ( (intr) << 5 ) )
-
-/** Event ring dequeue pointer register */
-#define XHCI_RUN_ERDP(intr) ( 0x38 + ( (intr) << 5 ) )
-
-/** A transfer request block template */
-struct xhci_trb_template {
- /** Parameter */
- uint64_t parameter;
- /** Status */
- uint32_t status;
- /** Control */
- uint32_t control;
-};
-
-/** A transfer request block */
-struct xhci_trb_common {
- /** Reserved */
- uint64_t reserved_a;
- /** Reserved */
- uint32_t reserved_b;
- /** Flags */
- uint8_t flags;
- /** Type */
- uint8_t type;
- /** Reserved */
- uint16_t reserved_c;
-} __attribute__ (( packed ));
-
-/** Transfer request block cycle bit flag */
-#define XHCI_TRB_C 0x01
-
-/** Transfer request block toggle cycle bit flag */
-#define XHCI_TRB_TC 0x02
-
-/** Transfer request block chain flag */
-#define XHCI_TRB_CH 0x10
-
-/** Transfer request block interrupt on completion flag */
-#define XHCI_TRB_IOC 0x20
-
-/** Transfer request block immediate data flag */
-#define XHCI_TRB_IDT 0x40
-
-/** Transfer request block type */
-#define XHCI_TRB_TYPE(type) ( (type) << 2 )
-
-/** Transfer request block type mask */
-#define XHCI_TRB_TYPE_MASK XHCI_TRB_TYPE ( 0x3f )
-
-/** A normal transfer request block */
-struct xhci_trb_normal {
- /** Data buffer */
- uint64_t data;
- /** Length */
- uint32_t len;
- /** Flags */
- uint8_t flags;
- /** Type */
- uint8_t type;
- /** Reserved */
- uint16_t reserved;
-} __attribute__ (( packed ));
-
-/** A normal transfer request block */
-#define XHCI_TRB_NORMAL XHCI_TRB_TYPE ( 1 )
-
-/** Construct TD size field */
-#define XHCI_TD_SIZE(remaining) \
- ( ( ( (remaining) <= 0xf ) ? remaining : 0xf ) << 17 )
-
-/** A setup stage transfer request block */
-struct xhci_trb_setup {
- /** Setup packet */
- struct usb_setup_packet packet;
- /** Length */
- uint32_t len;
- /** Flags */
- uint8_t flags;
- /** Type */
- uint8_t type;
- /** Transfer direction */
- uint8_t direction;
- /** Reserved */
- uint8_t reserved;
-} __attribute__ (( packed ));
-
-/** A setup stage transfer request block */
-#define XHCI_TRB_SETUP XHCI_TRB_TYPE ( 2 )
-
-/** Setup stage input data direction */
-#define XHCI_SETUP_IN 3
-
-/** Setup stage output data direction */
-#define XHCI_SETUP_OUT 2
-
-/** A data stage transfer request block */
-struct xhci_trb_data {
- /** Data buffer */
- uint64_t data;
- /** Length */
- uint32_t len;
- /** Flags */
- uint8_t flags;
- /** Type */
- uint8_t type;
- /** Transfer direction */
- uint8_t direction;
- /** Reserved */
- uint8_t reserved;
-} __attribute__ (( packed ));
-
-/** A data stage transfer request block */
-#define XHCI_TRB_DATA XHCI_TRB_TYPE ( 3 )
-
-/** Input data direction */
-#define XHCI_DATA_IN 0x01
-
-/** Output data direction */
-#define XHCI_DATA_OUT 0x00
-
-/** A status stage transfer request block */
-struct xhci_trb_status {
- /** Reserved */
- uint64_t reserved_a;
- /** Reserved */
- uint32_t reserved_b;
- /** Flags */
- uint8_t flags;
- /** Type */
- uint8_t type;
- /** Direction */
- uint8_t direction;
- /** Reserved */
- uint8_t reserved_c;
-} __attribute__ (( packed ));
-
-/** A status stage transfer request block */
-#define XHCI_TRB_STATUS XHCI_TRB_TYPE ( 4 )
-
-/** Input status direction */
-#define XHCI_STATUS_IN 0x01
-
-/** Output status direction */
-#define XHCI_STATUS_OUT 0x00
-
-/** A link transfer request block */
-struct xhci_trb_link {
- /** Next ring segment */
- uint64_t next;
- /** Reserved */
- uint32_t reserved_a;
- /** Flags */
- uint8_t flags;
- /** Type */
- uint8_t type;
- /** Reserved */
- uint16_t reserved_c;
-} __attribute__ (( packed ));
-
-/** A link transfer request block */
-#define XHCI_TRB_LINK XHCI_TRB_TYPE ( 6 )
-
-/** A no-op transfer request block */
-#define XHCI_TRB_NOP XHCI_TRB_TYPE ( 8 )
-
-/** An enable slot transfer request block */
-struct xhci_trb_enable_slot {
- /** Reserved */
- uint64_t reserved_a;
- /** Reserved */
- uint32_t reserved_b;
- /** Flags */
- uint8_t flags;
- /** Type */
- uint8_t type;
- /** Slot type */
- uint8_t slot;
- /** Reserved */
- uint8_t reserved_c;
-} __attribute__ (( packed ));
-
-/** An enable slot transfer request block */
-#define XHCI_TRB_ENABLE_SLOT XHCI_TRB_TYPE ( 9 )
-
-/** A disable slot transfer request block */
-struct xhci_trb_disable_slot {
- /** Reserved */
- uint64_t reserved_a;
- /** Reserved */
- uint32_t reserved_b;
- /** Flags */
- uint8_t flags;
- /** Type */
- uint8_t type;
- /** Reserved */
- uint8_t reserved_c;
- /** Slot ID */
- uint8_t slot;
-} __attribute__ (( packed ));
-
-/** A disable slot transfer request block */
-#define XHCI_TRB_DISABLE_SLOT XHCI_TRB_TYPE ( 10 )
-
-/** A context transfer request block */
-struct xhci_trb_context {
- /** Input context */
- uint64_t input;
- /** Reserved */
- uint32_t reserved_a;
- /** Flags */
- uint8_t flags;
- /** Type */
- uint8_t type;
- /** Reserved */
- uint8_t reserved_b;
- /** Slot ID */
- uint8_t slot;
-} __attribute__ (( packed ));
-
-/** An address device transfer request block */
-#define XHCI_TRB_ADDRESS_DEVICE XHCI_TRB_TYPE ( 11 )
-
-/** A configure endpoint transfer request block */
-#define XHCI_TRB_CONFIGURE_ENDPOINT XHCI_TRB_TYPE ( 12 )
-
-/** An evaluate context transfer request block */
-#define XHCI_TRB_EVALUATE_CONTEXT XHCI_TRB_TYPE ( 13 )
-
-/** A reset endpoint transfer request block */
-struct xhci_trb_reset_endpoint {
- /** Reserved */
- uint64_t reserved_a;
- /** Reserved */
- uint32_t reserved_b;
- /** Flags */
- uint8_t flags;
- /** Type */
- uint8_t type;
- /** Endpoint ID */
- uint8_t endpoint;
- /** Slot ID */
- uint8_t slot;
-} __attribute__ (( packed ));
-
-/** A reset endpoint transfer request block */
-#define XHCI_TRB_RESET_ENDPOINT XHCI_TRB_TYPE ( 14 )
-
-/** A stop endpoint transfer request block */
-struct xhci_trb_stop_endpoint {
- /** Reserved */
- uint64_t reserved_a;
- /** Reserved */
- uint32_t reserved_b;
- /** Flags */
- uint8_t flags;
- /** Type */
- uint8_t type;
- /** Endpoint ID */
- uint8_t endpoint;
- /** Slot ID */
- uint8_t slot;
-} __attribute__ (( packed ));
-
-/** A stop endpoint transfer request block */
-#define XHCI_TRB_STOP_ENDPOINT XHCI_TRB_TYPE ( 15 )
-
-/** A set transfer ring dequeue pointer transfer request block */
-struct xhci_trb_set_tr_dequeue_pointer {
- /** Dequeue pointer */
- uint64_t dequeue;
- /** Reserved */
- uint32_t reserved;
- /** Flags */
- uint8_t flags;
- /** Type */
- uint8_t type;
- /** Endpoint ID */
- uint8_t endpoint;
- /** Slot ID */
- uint8_t slot;
-} __attribute__ (( packed ));
-
-/** A set transfer ring dequeue pointer transfer request block */
-#define XHCI_TRB_SET_TR_DEQUEUE_POINTER XHCI_TRB_TYPE ( 16 )
-
-/** A no-op command transfer request block */
-#define XHCI_TRB_NOP_CMD XHCI_TRB_TYPE ( 23 )
-
-/** A transfer event transfer request block */
-struct xhci_trb_transfer {
- /** Transfer TRB pointer */
- uint64_t transfer;
- /** Residual transfer length */
- uint16_t residual;
- /** Reserved */
- uint8_t reserved;
- /** Completion code */
- uint8_t code;
- /** Flags */
- uint8_t flags;
- /** Type */
- uint8_t type;
- /** Endpoint ID */
- uint8_t endpoint;
- /** Slot ID */
- uint8_t slot;
-} __attribute__ (( packed ));
-
-/** A transfer event transfer request block */
-#define XHCI_TRB_TRANSFER XHCI_TRB_TYPE ( 32 )
-
-/** A command completion event transfer request block */
-struct xhci_trb_complete {
- /** Command TRB pointer */
- uint64_t command;
- /** Parameter */
- uint8_t parameter[3];
- /** Completion code */
- uint8_t code;
- /** Flags */
- uint8_t flags;
- /** Type */
- uint8_t type;
- /** Virtual function ID */
- uint8_t vf;
- /** Slot ID */
- uint8_t slot;
-} __attribute__ (( packed ));
-
-/** A command completion event transfer request block */
-#define XHCI_TRB_COMPLETE XHCI_TRB_TYPE ( 33 )
-
-/** xHCI completion codes */
-enum xhci_completion_code {
- /** Success */
- XHCI_CMPLT_SUCCESS = 1,
- /** Short packet */
- XHCI_CMPLT_SHORT = 13,
- /** Command ring stopped */
- XHCI_CMPLT_CMD_STOPPED = 24,
-};
-
-/** A port status change transfer request block */
-struct xhci_trb_port_status {
- /** Reserved */
- uint8_t reserved_a[3];
- /** Port ID */
- uint8_t port;
- /** Reserved */
- uint8_t reserved_b[7];
- /** Completion code */
- uint8_t code;
- /** Flags */
- uint8_t flags;
- /** Type */
- uint8_t type;
- /** Reserved */
- uint16_t reserved_c;
-} __attribute__ (( packed ));
-
-/** A port status change transfer request block */
-#define XHCI_TRB_PORT_STATUS XHCI_TRB_TYPE ( 34 )
-
-/** A port status change transfer request block */
-struct xhci_trb_host_controller {
- /** Reserved */
- uint64_t reserved_a;
- /** Reserved */
- uint8_t reserved_b[3];
- /** Completion code */
- uint8_t code;
- /** Flags */
- uint8_t flags;
- /** Type */
- uint8_t type;
- /** Reserved */
- uint16_t reserved_c;
-} __attribute__ (( packed ));
-
-/** A port status change transfer request block */
-#define XHCI_TRB_HOST_CONTROLLER XHCI_TRB_TYPE ( 37 )
-
-/** A transfer request block */
-union xhci_trb {
- /** Template */
- struct xhci_trb_template template;
- /** Common fields */
- struct xhci_trb_common common;
- /** Normal TRB */
- struct xhci_trb_normal normal;
- /** Setup stage TRB */
- struct xhci_trb_setup setup;
- /** Data stage TRB */
- struct xhci_trb_data data;
- /** Status stage TRB */
- struct xhci_trb_status status;
- /** Link TRB */
- struct xhci_trb_link link;
- /** Enable slot TRB */
- struct xhci_trb_enable_slot enable;
- /** Disable slot TRB */
- struct xhci_trb_disable_slot disable;
- /** Input context TRB */
- struct xhci_trb_context context;
- /** Reset endpoint TRB */
- struct xhci_trb_reset_endpoint reset;
- /** Stop endpoint TRB */
- struct xhci_trb_stop_endpoint stop;
- /** Set transfer ring dequeue pointer TRB */
- struct xhci_trb_set_tr_dequeue_pointer dequeue;
- /** Transfer event */
- struct xhci_trb_transfer transfer;
- /** Command completion event */
- struct xhci_trb_complete complete;
- /** Port status changed event */
- struct xhci_trb_port_status port;
- /** Host controller event */
- struct xhci_trb_host_controller host;
-} __attribute__ (( packed ));
-
-/** An input control context */
-struct xhci_control_context {
- /** Drop context flags */
- uint32_t drop;
- /** Add context flags */
- uint32_t add;
- /** Reserved */
- uint32_t reserved_a[5];
- /** Configuration value */
- uint8_t config;
- /** Interface number */
- uint8_t intf;
- /** Alternate setting */
- uint8_t alt;
- /** Reserved */
- uint8_t reserved_b;
-} __attribute__ (( packed ));
-
-/** A slot context */
-struct xhci_slot_context {
- /** Device info */
- uint32_t info;
- /** Maximum exit latency */
- uint16_t latency;
- /** Root hub port number */
- uint8_t port;
- /** Number of downstream ports */
- uint8_t ports;
- /** TT hub slot ID */
- uint8_t tt_id;
- /** TT port number */
- uint8_t tt_port;
- /** Interrupter target */
- uint16_t intr;
- /** USB address */
- uint8_t address;
- /** Reserved */
- uint16_t reserved_a;
- /** Slot state */
- uint8_t state;
- /** Reserved */
- uint32_t reserved_b[4];
-} __attribute__ (( packed ));
-
-/** Construct slot context device info */
-#define XHCI_SLOT_INFO( entries, hub, speed, route ) \
- ( ( (entries) << 27 ) | ( (hub) << 26 ) | ( (speed) << 20 ) | (route) )
-
-/** An endpoint context */
-struct xhci_endpoint_context {
- /** Endpoint state */
- uint8_t state;
- /** Stream configuration */
- uint8_t stream;
- /** Polling interval */
- uint8_t interval;
- /** Max ESIT payload high */
- uint8_t esit_high;
- /** Endpoint type */
- uint8_t type;
- /** Maximum burst size */
- uint8_t burst;
- /** Maximum packet size */
- uint16_t mtu;
- /** Transfer ring dequeue pointer */
- uint64_t dequeue;
- /** Average TRB length */
- uint16_t trb_len;
- /** Max ESIT payload low */
- uint16_t esit_low;
- /** Reserved */
- uint32_t reserved[3];
-} __attribute__ (( packed ));
-
-/** Endpoint states */
-enum xhci_endpoint_state {
- /** Endpoint is disabled */
- XHCI_ENDPOINT_DISABLED = 0,
- /** Endpoint is running */
- XHCI_ENDPOINT_RUNNING = 1,
- /** Endpoint is halted due to a USB Halt condition */
- XHCI_ENDPOINT_HALTED = 2,
- /** Endpoint is stopped */
- XHCI_ENDPOINT_STOPPED = 3,
- /** Endpoint is halted due to a TRB error */
- XHCI_ENDPOINT_ERROR = 4,
-};
-
-/** Endpoint state mask */
-#define XHCI_ENDPOINT_STATE_MASK 0x07
-
-/** Endpoint type */
-#define XHCI_EP_TYPE(type) ( (type) << 3 )
-
-/** Control endpoint type */
-#define XHCI_EP_TYPE_CONTROL XHCI_EP_TYPE ( 4 )
-
-/** Input endpoint type */
-#define XHCI_EP_TYPE_IN XHCI_EP_TYPE ( 4 )
-
-/** Periodic endpoint type */
-#define XHCI_EP_TYPE_PERIODIC XHCI_EP_TYPE ( 1 )
-
-/** Endpoint dequeue cycle state */
-#define XHCI_EP_DCS 0x00000001UL
-
-/** Control endpoint average TRB length */
-#define XHCI_EP0_TRB_LEN 8
-
-/** An event ring segment */
-struct xhci_event_ring_segment {
- /** Base address */
- uint64_t base;
- /** Number of TRBs */
- uint32_t count;
- /** Reserved */
- uint32_t reserved;
-} __attribute__ (( packed ));
-
-/** A transfer request block command/transfer ring */
-struct xhci_trb_ring {
- /** Producer counter */
- unsigned int prod;
- /** Consumer counter */
- unsigned int cons;
- /** Ring size (log2) */
- unsigned int shift;
- /** Ring counter mask */
- unsigned int mask;
-
- /** I/O buffers */
- struct io_buffer **iobuf;
-
- /** Transfer request blocks */
- union xhci_trb *trb;
- /** Length of transfer request blocks */
- size_t len;
- /** DMA mapping */
- struct dma_mapping map;
- /** Link TRB (if applicable) */
- struct xhci_trb_link *link;
-
- /** Doorbell register */
- void *db;
- /** Doorbell register value */
- uint32_t dbval;
-};
-
-/** An event ring */
-struct xhci_event_ring {
- /** Consumer counter */
- unsigned int cons;
- /** Event ring segment table */
- struct xhci_event_ring_segment *segment;
- /** Event ring segment table DMA mapping */
- struct dma_mapping segment_map;
- /** Transfer request blocks */
- union xhci_trb *trb;
- /** Transfer request blocks DMA mapping */
- struct dma_mapping trb_map;
-};
-
-/**
- * Calculate doorbell register value
- *
- * @v target Doorbell target
- * @v stream Doorbell stream ID
- * @ret dbval Doorbell register value
- */
-#define XHCI_DBVAL( target, stream ) ( (target) | ( (stream) << 16 ) )
-
-/**
- * Calculate space used in TRB ring
- *
- * @v ring TRB ring
- * @ret fill Number of entries used
- */
-static inline __attribute__ (( always_inline )) unsigned int
-xhci_ring_fill ( struct xhci_trb_ring *ring ) {
-
- return ( ring->prod - ring->cons );
-}
-
-/**
- * Calculate space remaining in TRB ring
- *
- * @v ring TRB ring
- * @ret remaining Number of entries remaining
- *
- * xHCI does not allow us to completely fill a ring; there must be at
- * least one free entry (excluding the Link TRB).
- */
-static inline __attribute__ (( always_inline )) unsigned int
-xhci_ring_remaining ( struct xhci_trb_ring *ring ) {
- unsigned int fill = xhci_ring_fill ( ring );
-
- /* We choose to utilise rings with ( 2^n + 1 ) entries, with
- * the final entry being a Link TRB. The maximum fill level
- * is therefore
- *
- * ( ( 2^n + 1 ) - 1 (Link TRB) - 1 (one slot always empty)
- * == ( 2^n - 1 )
- *
- * which is therefore equal to the ring mask.
- */
- assert ( fill <= ring->mask );
- return ( ring->mask - fill );
-}
-
-/**
- * Calculate physical address of most recently consumed TRB
- *
- * @v ring TRB ring
- * @ret trb TRB physical address
- */
-static inline __attribute__ (( always_inline )) physaddr_t
-xhci_ring_consumed ( struct xhci_trb_ring *ring ) {
- unsigned int index = ( ( ring->cons - 1 ) & ring->mask );
-
- return virt_to_phys ( &ring->trb[index] );
-}
-
-/** Slot context index */
-#define XHCI_CTX_SLOT 0
-
-/** Calculate context index from USB endpoint address */
-#define XHCI_CTX(address) \
- ( (address) ? ( ( ( (address) & 0x0f ) << 1 ) | \
- ( ( (address) & 0x80 ) >> 7 ) ) : 1 )
-
-/** Endpoint zero context index */
-#define XHCI_CTX_EP0 XHCI_CTX ( 0x00 )
-
-/** End of contexts */
-#define XHCI_CTX_END 32
-
-/** Device context index */
-#define XHCI_DCI(ctx) ( (ctx) + 0 )
-
-/** Input context index */
-#define XHCI_ICI(ctx) ( (ctx) + 1 )
-
-/** Number of TRBs (excluding Link TRB) in the command ring
- *
- * This is a policy decision.
- */
-#define XHCI_CMD_TRBS_LOG2 2
-
-/** Number of TRBs in the event ring
- *
- * This is a policy decision.
- */
-#define XHCI_EVENT_TRBS_LOG2 6
-
-/** Number of TRBs in a transfer ring
- *
- * This is a policy decision.
- */
-#define XHCI_TRANSFER_TRBS_LOG2 6
-
-/** Maximum time to wait for BIOS to release ownership
- *
- * This is a policy decision.
- */
-#define XHCI_USBLEGSUP_MAX_WAIT_MS 100
-
-/** Maximum time to wait for host controller to stop
- *
- * This is a policy decision.
- */
-#define XHCI_STOP_MAX_WAIT_MS 100
-
-/** Maximum time to wait for reset to complete
- *
- * This is a policy decision.
- */
-#define XHCI_RESET_MAX_WAIT_MS 500
-
-/** Maximum time to wait for a command to complete
- *
- * The "address device" command involves waiting for a response to a
- * USB control transaction, and so we must wait for up to the 5000ms
- * that USB allows for devices to respond to control transactions.
- */
-#define XHCI_COMMAND_MAX_WAIT_MS USB_CONTROL_MAX_WAIT_MS
-
-/** Time to delay after aborting a command
- *
- * This is a policy decision
- */
-#define XHCI_COMMAND_ABORT_DELAY_MS 500
-
-/** Maximum time to wait for a port reset to complete
- *
- * This is a policy decision.
- */
-#define XHCI_PORT_RESET_MAX_WAIT_MS 500
-
-/** Intel PCH quirk */
-struct xhci_pch {
- /** USB2 port routing register original value */
- uint32_t xusb2pr;
- /** USB3 port SuperSpeed enable register original value */
- uint32_t usb3pssen;
-};
-
-/** Intel PCH quirk flag */
-#define XHCI_PCH 0x0001
-
-/** Intel PCH USB2 port routing register */
-#define XHCI_PCH_XUSB2PR 0xd0
-
-/** Intel PCH USB2 port routing mask register */
-#define XHCI_PCH_XUSB2PRM 0xd4
-
-/** Intel PCH SuperSpeed enable register */
-#define XHCI_PCH_USB3PSSEN 0xd8
-
-/** Intel PCH USB3 port routing mask register */
-#define XHCI_PCH_USB3PRM 0xdc
-
-/** Invalid protocol speed ID values quirk */
-#define XHCI_BAD_PSIV 0x0002
-
-/** Device context base address array */
-struct xhci_dcbaa {
- /** Context base addresses */
- uint64_t *context;
- /** DMA mapping */
- struct dma_mapping map;
-};
-
-/** Scratchpad buffer */
-struct xhci_scratchpad {
- /** Number of page-sized scratchpad buffers */
- unsigned int count;
- /** Scratchpad buffer area */
- userptr_t buffer;
- /** Buffer DMA mapping */
- struct dma_mapping buffer_map;
- /** Scratchpad array */
- uint64_t *array;
- /** Array DMA mapping */
- struct dma_mapping array_map;
-};
-
-/** An xHCI device */
-struct xhci_device {
- /** Registers */
- void *regs;
- /** DMA device */
- struct dma_device *dma;
- /** Name */
- const char *name;
- /** Quirks */
- unsigned int quirks;
-
- /** Capability registers */
- void *cap;
- /** Operational registers */
- void *op;
- /** Runtime registers */
- void *run;
- /** Doorbell registers */
- void *db;
-
- /** Number of device slots */
- unsigned int slots;
- /** Number of interrupters */
- unsigned int intrs;
- /** Number of ports */
- unsigned int ports;
-
- /** 64-bit addressing capability */
- int addr64;
- /** Context size shift */
- unsigned int csz_shift;
- /** xHCI extended capabilities offset */
- unsigned int xecp;
-
- /** Page size */
- size_t pagesize;
-
- /** USB legacy support capability (if present and enabled) */
- unsigned int legacy;
-
- /** Device context base address array */
- struct xhci_dcbaa dcbaa;
-
- /** Scratchpad buffer */
- struct xhci_scratchpad scratch;
-
- /** Command ring */
- struct xhci_trb_ring command;
- /** Event ring */
- struct xhci_event_ring event;
- /** Current command (if any) */
- union xhci_trb *pending;
- /** Command mechanism has permanently failed */
- int failed;
-
- /** Device slots, indexed by slot ID */
- struct xhci_slot **slot;
-
- /** USB bus */
- struct usb_bus *bus;
-
- /** Intel PCH quirk */
- struct xhci_pch pch;
-};
-
-/** An xHCI device slot */
-struct xhci_slot {
- /** xHCI device */
- struct xhci_device *xhci;
- /** USB device */
- struct usb_device *usb;
- /** Slot ID */
- unsigned int id;
- /** Slot context */
- struct xhci_slot_context *context;
- /** DMA mapping */
- struct dma_mapping map;
- /** Route string */
- unsigned int route;
- /** Root hub port number */
- unsigned int port;
- /** Protocol speed ID */
- unsigned int psiv;
- /** Number of ports (if this device is a hub) */
- unsigned int ports;
- /** Transaction translator slot ID */
- unsigned int tt_id;
- /** Transaction translator port */
- unsigned int tt_port;
- /** Endpoints, indexed by context ID */
- struct xhci_endpoint *endpoint[XHCI_CTX_END];
-};
-
-/** An xHCI endpoint */
-struct xhci_endpoint {
- /** xHCI device */
- struct xhci_device *xhci;
- /** xHCI slot */
- struct xhci_slot *slot;
- /** USB endpoint */
- struct usb_endpoint *ep;
- /** Context index */
- unsigned int ctx;
- /** Endpoint type */
- unsigned int type;
- /** Endpoint interval */
- unsigned int interval;
- /** Endpoint context */
- struct xhci_endpoint_context *context;
- /** Transfer ring */
- struct xhci_trb_ring ring;
-};
-
-#endif /* _IPXE_XHCI_H */