Browse Source

[efi] Add a USB host controller driver based on EFI_USB_IO_PROTOCOL

Allow iPXE to coexist with other USB device drivers, by attaching to
the EFI_USB_IO_PROTOCOL instances provided by the UEFI platform
firmware.

The EFI_USB_IO_PROTOCOL is an unsurprisingly badly designed
abstraction of a USB device.  The poor design choices intrinsic in the
UEFI specification prevent efficient operation as a network device,
with the result that devices operated using the EFI_USB_IO_PROTOCOL
operate approximately two orders of magnitude slower than devices
operated using our native EHCI or xHCI host controller drivers.

Since the performance is so abysmally slow, and since the underlying
problems are due to fundamental architectural mistakes in the UEFI
specification, support for the EFI_USB_IO_PROTOCOL host controller
driver is left as disabled by default.  Users are advised to use the
native iPXE host controller drivers instead.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 8 years ago
parent
commit
15a8800a98
6 changed files with 1884 additions and 1 deletions
  1. 3
    0
      src/config/config_usb.c
  2. 1
    0
      src/config/usb.h
  3. 1722
    0
      src/drivers/usb/usbio.c
  4. 153
    0
      src/drivers/usb/usbio.h
  5. 1
    0
      src/include/ipxe/errfile.h
  6. 4
    1
      src/include/ipxe/usb.h

+ 3
- 0
src/config/config_usb.c View File

@@ -43,6 +43,9 @@ REQUIRE_OBJECT ( ehci );
43 43
 #ifdef USB_HCD_UHCI
44 44
 REQUIRE_OBJECT ( uhci );
45 45
 #endif
46
+#ifdef USB_HCD_USBIO
47
+REQUIRE_OBJECT ( usbio );
48
+#endif
46 49
 
47 50
 /*
48 51
  * Drag in USB peripherals

+ 1
- 0
src/config/usb.h View File

@@ -18,6 +18,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
18 18
 //#undef	USB_HCD_XHCI		/* xHCI USB host controller */
19 19
 //#undef	USB_HCD_EHCI		/* EHCI USB host controller */
20 20
 //#undef	USB_HCD_UHCI		/* UHCI USB host controller */
21
+//#define	USB_HCD_USBIO		/* Very slow EFI USB host controller */
21 22
 
22 23
 /*
23 24
  * USB peripherals

+ 1722
- 0
src/drivers/usb/usbio.c
File diff suppressed because it is too large
View File


+ 153
- 0
src/drivers/usb/usbio.h View File

@@ -0,0 +1,153 @@
1
+#ifndef _USBIO_H
2
+#define _USBIO_H
3
+
4
+/** @file
5
+ *
6
+ * EFI_USB_IO_PROTOCOL pseudo Host Controller Interface driver
7
+ *
8
+ */
9
+
10
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11
+
12
+#include <ipxe/list.h>
13
+#include <ipxe/device.h>
14
+#include <ipxe/efi/efi.h>
15
+#include <ipxe/efi/Protocol/UsbIo.h>
16
+#include <ipxe/efi/Protocol/DevicePath.h>
17
+#include <ipxe/usb.h>
18
+
19
+/** USB I/O maximum transfer size
20
+ *
21
+ * The API provides no way to discover the maximum transfer size.
22
+ * Assume the 16kB supported by EHCI.
23
+ */
24
+#define USBIO_MTU 16384
25
+
26
+/** USB I/O interrupt ring buffer size
27
+ *
28
+ * This is a policy decision.
29
+ */
30
+#define USBIO_INTR_COUNT 4
31
+
32
+/** A USB interrupt ring buffer */
33
+struct usbio_interrupt_ring {
34
+	/** USB I/O endpoint */
35
+	struct usbio_endpoint *endpoint;
36
+	/** Producer counter */
37
+	unsigned int prod;
38
+	/** Consumer counter */
39
+	unsigned int cons;
40
+	/** Data buffers */
41
+	void *data[USBIO_INTR_COUNT];
42
+	/** Lengths */
43
+	size_t len[USBIO_INTR_COUNT];
44
+};
45
+
46
+/** USB I/O ring buffer size
47
+ *
48
+ * This is a policy decision.
49
+ */
50
+#define USBIO_RING_COUNT 64
51
+
52
+/** A USB I/O endpoint */
53
+struct usbio_endpoint {
54
+	/** USB I/O device */
55
+	struct usbio_device *usbio;
56
+	/** USB endpoint */
57
+	struct usb_endpoint *ep;
58
+	/** List of endpoints */
59
+	struct list_head list;
60
+	/** USB I/O endpoint operations */
61
+	struct usbio_operations *op;
62
+
63
+	/** Containing interface number */
64
+	unsigned int interface;
65
+	/** EFI handle */
66
+	EFI_HANDLE handle;
67
+	/** USB I/O protocol */
68
+	EFI_USB_IO_PROTOCOL *io;
69
+
70
+	/** Producer counter */
71
+	unsigned int prod;
72
+	/** Consumer counter */
73
+	unsigned int cons;
74
+	/** I/O buffers */
75
+	struct io_buffer *iobuf[USBIO_RING_COUNT];
76
+	/** Flags */
77
+	uint8_t flags[USBIO_RING_COUNT];
78
+
79
+	/** Interrupt ring buffer (if applicable) */
80
+	struct usbio_interrupt_ring *intr;
81
+};
82
+
83
+/** USB I/O transfer flags */
84
+enum usbio_flags {
85
+	/** This is a message transfer */
86
+	USBIO_MESSAGE = 0x01,
87
+	/** This transfer requires zero-length packet termination */
88
+	USBIO_ZLEN = 0x02,
89
+};
90
+
91
+/** USB I/O endpoint operations */
92
+struct usbio_operations {
93
+	/** Open endpoint
94
+	 *
95
+	 * @v endpoint		Endpoint
96
+	 * @ret rc		Return status code
97
+	 */
98
+	int ( * open ) ( struct usbio_endpoint *endpoint );
99
+	/** Close endpoint
100
+	 *
101
+	 * @v endpoint		Endpoint
102
+	 */
103
+	void ( * close ) ( struct usbio_endpoint *endpoint );
104
+	/** Poll endpoint
105
+	 *
106
+	 * @v endpoint		Endpoint
107
+	 */
108
+	void ( * poll ) ( struct usbio_endpoint *endpoint );
109
+};
110
+
111
+/** A USB I/O protocol interface */
112
+struct usbio_interface {
113
+	/** EFI device handle */
114
+	EFI_HANDLE handle;
115
+	/** USB I/O protocol */
116
+	EFI_USB_IO_PROTOCOL *io;
117
+	/** Usage count */
118
+	unsigned int count;
119
+};
120
+
121
+/** A USB I/O protocol device
122
+ *
123
+ * We model each externally-provided USB I/O protocol device as a host
124
+ * controller containing a root hub with a single port.
125
+ */
126
+struct usbio_device {
127
+	/** EFI device handle */
128
+	EFI_HANDLE handle;
129
+	/** USB I/O protocol */
130
+	EFI_USB_IO_PROTOCOL *io;
131
+	/** Generic device */
132
+	struct device dev;
133
+
134
+	/** Configuration descriptor */
135
+	struct usb_configuration_descriptor *config;
136
+
137
+	/** Device path */
138
+	EFI_DEVICE_PATH_PROTOCOL *path;
139
+	/** Final component of USB device path */
140
+	USB_DEVICE_PATH *usbpath;
141
+
142
+	/** First interface number */
143
+	uint8_t first;
144
+	/** USB I/O protocol interfaces */
145
+	struct usbio_interface *interface;
146
+
147
+	/** USB bus */
148
+	struct usb_bus *bus;
149
+	/** List of endpoints */
150
+	struct list_head endpoints;
151
+};
152
+
153
+#endif /* _USBIO_H */

+ 1
- 0
src/include/ipxe/errfile.h View File

@@ -85,6 +85,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
85 85
 #define ERRFILE_uhci		     ( ERRFILE_DRIVER | 0x000b0000 )
86 86
 #define ERRFILE_usbhid		     ( ERRFILE_DRIVER | 0x000c0000 )
87 87
 #define ERRFILE_usbkbd		     ( ERRFILE_DRIVER | 0x000d0000 )
88
+#define ERRFILE_usbio		     ( ERRFILE_DRIVER | 0x000e0000 )
88 89
 
89 90
 #define ERRFILE_nvs		     ( ERRFILE_DRIVER | 0x00100000 )
90 91
 #define ERRFILE_spi		     ( ERRFILE_DRIVER | 0x00110000 )

+ 4
- 1
src/include/ipxe/usb.h View File

@@ -68,7 +68,7 @@ enum usb_pid {
68 68
 struct usb_setup_packet {
69 69
 	/** Request */
70 70
 	uint16_t request;
71
-	/** Value paramer */
71
+	/** Value parameter */
72 72
 	uint16_t value;
73 73
 	/** Index parameter */
74 74
 	uint16_t index;
@@ -91,6 +91,9 @@ struct usb_setup_packet {
91 91
 /** Vendor-specific request type */
92 92
 #define USB_TYPE_VENDOR ( 2 << 5 )
93 93
 
94
+/** Request recipient mask */
95
+#define USB_RECIP_MASK ( 0x1f << 0 )
96
+
94 97
 /** Request recipient is the device */
95 98
 #define USB_RECIP_DEVICE ( 0 << 0 )
96 99
 

Loading…
Cancel
Save