瀏覽代碼

[ehci] Add support for EHCI host controllers

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 9 年之前
父節點
當前提交
8370f87745
共有 7 個文件被更改,包括 2370 次插入0 次删除
  1. 3
    0
      src/config/config_usb.c
  2. 1
    0
      src/config/defaults/pcbios.h
  3. 1
    0
      src/config/usb.h
  4. 1845
    0
      src/drivers/usb/ehci.c
  5. 516
    0
      src/drivers/usb/ehci.h
  6. 1
    0
      src/include/ipxe/errfile.h
  7. 3
    0
      src/include/ipxe/usb.h

+ 3
- 0
src/config/config_usb.c 查看文件

@@ -37,3 +37,6 @@ PROVIDE_REQUIRING_SYMBOL();
37 37
 #ifdef USB_HCD_XHCI
38 38
 REQUIRE_OBJECT ( xhci );
39 39
 #endif
40
+#ifdef USB_HCD_EHCI
41
+REQUIRE_OBJECT ( ehci );
42
+#endif

+ 1
- 0
src/config/defaults/pcbios.h 查看文件

@@ -37,6 +37,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
37 37
 #define	SANBOOT_PROTO_FCP	/* Fibre Channel protocol */
38 38
 
39 39
 #define	USB_HCD_XHCI		/* xHCI USB host controller */
40
+#define	USB_HCD_EHCI		/* EHCI USB host controller */
40 41
 
41 42
 #define	REBOOT_CMD		/* Reboot command */
42 43
 #define	CPUID_CMD		/* x86 CPU feature detection command */

+ 1
- 0
src/config/usb.h 查看文件

@@ -16,6 +16,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
16 16
  *
17 17
  */
18 18
 //#undef	USB_HCD_XHCI		/* xHCI USB host controller */
19
+//#undef	USB_HCD_EHCI		/* EHCI USB host controller */
19 20
 
20 21
 #include <config/named.h>
21 22
 #include NAMED_CONFIG(usb.h)

+ 1845
- 0
src/drivers/usb/ehci.c
文件差異過大導致無法顯示
查看文件


+ 516
- 0
src/drivers/usb/ehci.h 查看文件

@@ -0,0 +1,516 @@
1
+#ifndef _IPXE_EHCI_H
2
+#define _IPXE_EHCI_H
3
+
4
+/** @file
5
+ *
6
+ * USB Enhanced Host Controller Interface (EHCI) driver
7
+ *
8
+ */
9
+
10
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11
+
12
+#include <ipxe/pci.h>
13
+#include <ipxe/usb.h>
14
+
15
+/** Minimum alignment required for data structures
16
+ *
17
+ * With the exception of the periodic frame list (which is
18
+ * page-aligned), data structures used by EHCI generally require
19
+ * 32-byte alignment and must not cross a 4kB page boundary.  We
20
+ * simplify this requirement by aligning each structure on its own
21
+ * size, with a minimum of a 32 byte alignment.
22
+ */
23
+#define EHCI_MIN_ALIGN 32
24
+
25
+/** Maximum transfer size
26
+ *
27
+ * EHCI allows for transfers of up to 20kB with page-alignment, or
28
+ * 16kB with arbitrary alignment.
29
+ */
30
+#define EHCI_MTU 16384
31
+
32
+/** Page-alignment required for some data structures */
33
+#define EHCI_PAGE_ALIGN 4096
34
+
35
+/** EHCI PCI BAR */
36
+#define EHCI_BAR PCI_BASE_ADDRESS_0
37
+
38
+/** Capability register length */
39
+#define EHCI_CAP_CAPLENGTH 0x00
40
+
41
+/** Host controller interface version number */
42
+#define EHCI_CAP_HCIVERSION 0x02
43
+
44
+/** Structural parameters */
45
+#define EHCI_CAP_HCSPARAMS 0x04
46
+
47
+/** Number of ports */
48
+#define EHCI_HCSPARAMS_PORTS(params) ( ( (params) >> 0 ) & 0x0f )
49
+
50
+/** Capability parameters */
51
+#define EHCI_CAP_HCCPARAMS 0x08
52
+
53
+/** 64-bit addressing capability */
54
+#define EHCI_HCCPARAMS_ADDR64(params) ( ( (params) >> 0 ) & 0x1 )
55
+
56
+/** Programmable frame list flag */
57
+#define EHCI_HCCPARAMS_FLSIZE(params) ( ( (params) >> 1 ) & 0x1 )
58
+
59
+/** EHCI extended capabilities pointer */
60
+#define EHCI_HCCPARAMS_EECP(params) ( ( ( (params) >> 8 ) & 0xff ) )
61
+
62
+/** EHCI extended capability ID */
63
+#define EHCI_EECP_ID(eecp) ( ( (eecp) >> 0 ) & 0xff )
64
+
65
+/** Next EHCI extended capability pointer */
66
+#define EHCI_EECP_NEXT(eecp) ( ( ( (eecp) >> 8 ) & 0xff ) )
67
+
68
+/** USB legacy support extended capability */
69
+#define EHCI_EECP_ID_LEGACY 1
70
+
71
+/** USB legacy support BIOS owned semaphore */
72
+#define EHCI_USBLEGSUP_BIOS 0x02
73
+
74
+/** USB legacy support BIOS ownership flag */
75
+#define EHCI_USBLEGSUP_BIOS_OWNED 0x01
76
+
77
+/** USB legacy support OS owned semaphore */
78
+#define EHCI_USBLEGSUP_OS 0x03
79
+
80
+/** USB legacy support OS ownership flag */
81
+#define EHCI_USBLEGSUP_OS_OWNED 0x01
82
+
83
+/** USB legacy support control/status */
84
+#define EHCI_USBLEGSUP_CTLSTS 0x04
85
+
86
+/** USB command register */
87
+#define EHCI_OP_USBCMD 0x00
88
+
89
+/** Run/stop */
90
+#define EHCI_USBCMD_RUN 0x00000001UL
91
+
92
+/** Host controller reset */
93
+#define EHCI_USBCMD_HCRST 0x00000002UL
94
+
95
+/** Frame list size */
96
+#define EHCI_USBCMD_FLSIZE(flsize) ( (flsize) << 2 )
97
+
98
+/** Frame list size mask */
99
+#define EHCI_USBCMD_FLSIZE_MASK EHCI_USBCMD_FLSIZE ( 3 )
100
+
101
+/** Default frame list size */
102
+#define EHCI_FLSIZE_DEFAULT 0
103
+
104
+/** Smallest allowed frame list size */
105
+#define EHCI_FLSIZE_SMALL 2
106
+
107
+/** Number of elements in frame list */
108
+#define EHCI_PERIODIC_FRAMES(flsize) ( 1024 >> (flsize) )
109
+
110
+/** Periodic schedule enable */
111
+#define EHCI_USBCMD_PERIODIC 0x00000010UL
112
+
113
+/** Asynchronous schedule enable */
114
+#define EHCI_USBCMD_ASYNC 0x00000020UL
115
+
116
+/** Asyncchronous schedule advance doorbell */
117
+#define EHCI_USBCMD_ASYNC_ADVANCE 0x000040UL
118
+
119
+/** USB status register */
120
+#define EHCI_OP_USBSTS 0x04
121
+
122
+/** USB interrupt */
123
+#define EHCI_USBSTS_USBINT 0x00000001UL
124
+
125
+/** USB error interrupt */
126
+#define EHCI_USBSTS_USBERRINT 0x00000002UL
127
+
128
+/** Port change detect */
129
+#define EHCI_USBSTS_PORT 0x00000004UL
130
+
131
+/** Frame list rollover */
132
+#define EHCI_USBSTS_ROLLOVER 0x00000008UL
133
+
134
+/** Host system error */
135
+#define EHCI_USBSTS_SYSERR 0x00000010UL
136
+
137
+/** Asynchronous schedule advanced */
138
+#define EHCI_USBSTS_ASYNC_ADVANCE 0x00000020UL
139
+
140
+/** Periodic schedule enabled */
141
+#define EHCI_USBSTS_PERIODIC 0x00004000UL
142
+
143
+/** Asynchronous schedule enabled */
144
+#define EHCI_USBSTS_ASYNC 0x00008000UL
145
+
146
+/** Host controller halted */
147
+#define EHCI_USBSTS_HCH 0x00001000UL
148
+
149
+/** USB status change mask */
150
+#define EHCI_USBSTS_CHANGE						\
151
+	( EHCI_USBSTS_USBINT | EHCI_USBSTS_USBERRINT |			\
152
+	  EHCI_USBSTS_PORT | EHCI_USBSTS_ROLLOVER |			\
153
+	  EHCI_USBSTS_SYSERR | EHCI_USBSTS_ASYNC_ADVANCE )
154
+
155
+/** USB interrupt enable register */
156
+#define EHCI_OP_USBINTR 0x08
157
+
158
+/** Frame index register */
159
+#define EHCI_OP_FRINDEX 0x0c
160
+
161
+/** Control data structure segment register */
162
+#define EHCI_OP_CTRLDSSEGMENT 0x10
163
+
164
+/** Periodic frame list base address register */
165
+#define EHCI_OP_PERIODICLISTBASE 0x14
166
+
167
+/** Current asynchronous list address register */
168
+#define EHCI_OP_ASYNCLISTADDR 0x18
169
+
170
+/** Configure flag register */
171
+#define EHCI_OP_CONFIGFLAG 0x40
172
+
173
+/** Configure flag */
174
+#define EHCI_CONFIGFLAG_CF 0x00000001UL
175
+
176
+/** Port status and control register */
177
+#define EHCI_OP_PORTSC(port) ( 0x40 + ( (port) << 2 ) )
178
+
179
+/** Current connect status */
180
+#define EHCI_PORTSC_CCS 0x00000001UL
181
+
182
+/** Connect status change */
183
+#define EHCI_PORTSC_CSC 0x00000002UL
184
+
185
+/** Port enabled */
186
+#define EHCI_PORTSC_PED 0x00000004UL
187
+
188
+/** Port enabled/disabled change */
189
+#define EHCI_PORTSC_PEC 0x00000008UL
190
+
191
+/** Over-current change */
192
+#define EHCI_PORTSC_OCC 0x00000020UL
193
+
194
+/** Port reset */
195
+#define EHCI_PORTSC_PR 0x00000100UL
196
+
197
+/** Line status */
198
+#define EHCI_PORTSC_LINE_STATUS(portsc) ( ( (portsc) >> 10 ) & 0x3 )
199
+
200
+/** Line status: low-speed device */
201
+#define EHCI_PORTSC_LINE_STATUS_LOW 0x1
202
+
203
+/** Port power */
204
+#define EHCI_PORTSC_PP 0x00001000UL
205
+
206
+/** Port owner */
207
+#define EHCI_PORTSC_OWNER 0x00002000UL
208
+
209
+/** Port status change mask */
210
+#define EHCI_PORTSC_CHANGE \
211
+	( EHCI_PORTSC_CSC | EHCI_PORTSC_PEC | EHCI_PORTSC_OCC )
212
+
213
+/** List terminator */
214
+#define EHCI_LINK_TERMINATE 0x00000001UL
215
+
216
+/** Frame list type */
217
+#define EHCI_LINK_TYPE(type) ( (type) << 1 )
218
+
219
+/** Queue head type */
220
+#define EHCI_LINK_TYPE_QH EHCI_LINK_TYPE ( 1 )
221
+
222
+/** A periodic frame list entry */
223
+struct ehci_periodic_frame {
224
+	/** First queue head */
225
+	uint32_t link;
226
+} __attribute__ (( packed ));
227
+
228
+/** A transfer descriptor */
229
+struct ehci_transfer_descriptor {
230
+	/** Next transfer descriptor */
231
+	uint32_t next;
232
+	/** Alternate next transfer descriptor */
233
+	uint32_t alt;
234
+	/** Status */
235
+	uint8_t status;
236
+	/** Flags */
237
+	uint8_t flags;
238
+	/** Transfer length */
239
+	uint16_t len;
240
+	/** Buffer pointers (low 32 bits) */
241
+	uint32_t low[5];
242
+	/** Extended buffer pointers (high 32 bits) */
243
+	uint32_t high[5];
244
+
245
+	/** Immediate data buffer
246
+	 *
247
+	 * This is not part of the hardware data structure.  Transfer
248
+	 * descriptors must be aligned to a 32-byte boundary.  Create
249
+	 * an array of descriptors therefore requires 12 bytes of
250
+	 * padding at the end of each descriptor.
251
+	 *
252
+	 * We can use this padding as an immediate data buffer (for
253
+	 * setup packets).  This avoids the need for separate
254
+	 * allocations.  As a bonus, there is no need to check this
255
+	 * buffer for reachability, since it is contained within a
256
+	 * transfer descriptor which must already be reachable.
257
+	 */
258
+	uint8_t immediate[12];
259
+} __attribute__ (( packed ));
260
+
261
+/** Transaction error */
262
+#define EHCI_STATUS_XACT_ERR 0x08
263
+
264
+/** Babble detected */
265
+#define EHCI_STATUS_BABBLE 0x10
266
+
267
+/** Data buffer error */
268
+#define EHCI_STATUS_BUFFER 0x20
269
+
270
+/** Halted */
271
+#define EHCI_STATUS_HALTED 0x40
272
+
273
+/** Active */
274
+#define EHCI_STATUS_ACTIVE 0x80
275
+
276
+/** PID code */
277
+#define EHCI_FL_PID(code) ( (code) << 0 )
278
+
279
+/** OUT token */
280
+#define EHCI_FL_PID_OUT EHCI_FL_PID ( 0 )
281
+
282
+/** IN token */
283
+#define EHCI_FL_PID_IN EHCI_FL_PID ( 1 )
284
+
285
+/** SETUP token */
286
+#define EHCI_FL_PID_SETUP EHCI_FL_PID ( 2 )
287
+
288
+/** Interrupt on completion */
289
+#define EHCI_FL_IOC 0x80
290
+
291
+/** Length mask */
292
+#define EHCI_LEN_MASK 0x7fff
293
+
294
+/** Data toggle */
295
+#define EHCI_LEN_TOGGLE 0x8000
296
+
297
+/** A queue head */
298
+struct ehci_queue_head {
299
+	/** Horizontal link pointer */
300
+	uint32_t link;
301
+	/** Endpoint characteristics */
302
+	uint32_t chr;
303
+	/** Endpoint capabilities */
304
+	uint32_t cap;
305
+	/** Current transfer descriptor */
306
+	uint32_t current;
307
+	/** Transfer descriptor cache */
308
+	struct ehci_transfer_descriptor cache;
309
+} __attribute__ (( packed ));
310
+
311
+/** Device address */
312
+#define EHCI_CHR_ADDRESS( address ) ( (address) << 0 )
313
+
314
+/** Endpoint number */
315
+#define EHCI_CHR_ENDPOINT( address ) ( ( (address) & 0xf ) << 8 )
316
+
317
+/** Endpoint speed */
318
+#define EHCI_CHR_EPS( eps ) ( (eps) << 12 )
319
+
320
+/** Full-speed endpoint */
321
+#define EHCI_CHR_EPS_FULL EHCI_CHR_EPS ( 0 )
322
+
323
+/** Low-speed endpoint */
324
+#define EHCI_CHR_EPS_LOW EHCI_CHR_EPS ( 1 )
325
+
326
+/** High-speed endpoint */
327
+#define EHCI_CHR_EPS_HIGH EHCI_CHR_EPS ( 2 )
328
+
329
+/** Explicit data toggles */
330
+#define EHCI_CHR_TOGGLE 0x00004000UL
331
+
332
+/** Head of reclamation list flag */
333
+#define EHCI_CHR_HEAD 0x00008000UL
334
+
335
+/** Maximum packet length */
336
+#define EHCI_CHR_MAX_LEN( len ) ( (len) << 16 )
337
+
338
+/** Control endpoint flag */
339
+#define EHCI_CHR_CONTROL 0x08000000UL
340
+
341
+/** Interrupt schedule mask */
342
+#define EHCI_CAP_INTR_SCHED( uframe ) ( 1 << ( (uframe) + 0 ) )
343
+
344
+/** High-bandwidth pipe multiplier */
345
+#define EHCI_CAP_MULT( mult ) ( (mult) << 30 )
346
+
347
+/** A transfer descriptor ring */
348
+struct ehci_ring {
349
+	/** Producer counter */
350
+	unsigned int prod;
351
+	/** Consumer counter */
352
+	unsigned int cons;
353
+
354
+	/** Residual untransferred data */
355
+	size_t residual;
356
+
357
+	/** I/O buffers */
358
+	struct io_buffer **iobuf;
359
+
360
+	/** Queue head */
361
+	struct ehci_queue_head *head;
362
+	/** Transfer descriptors */
363
+	struct ehci_transfer_descriptor *desc;
364
+};
365
+
366
+/** Number of transfer descriptors in a ring
367
+ *
368
+ * This is a policy decision.
369
+ */
370
+#define EHCI_RING_COUNT 64
371
+
372
+/**
373
+ * Calculate space used in transfer descriptor ring
374
+ *
375
+ * @v ring		Transfer descriptor ring
376
+ * @ret fill		Number of entries used
377
+ */
378
+static inline __attribute__ (( always_inline )) unsigned int
379
+ehci_ring_fill ( struct ehci_ring *ring ) {
380
+	unsigned int fill;
381
+
382
+	fill = ( ring->prod - ring->cons );
383
+	assert ( fill <= EHCI_RING_COUNT );
384
+	return fill;
385
+}
386
+
387
+/**
388
+ * Calculate space remaining in transfer descriptor ring
389
+ *
390
+ * @v ring		Transfer descriptor ring
391
+ * @ret remaining	Number of entries remaining
392
+ */
393
+static inline __attribute__ (( always_inline )) unsigned int
394
+ehci_ring_remaining ( struct ehci_ring *ring ) {
395
+	unsigned int fill = ehci_ring_fill ( ring );
396
+
397
+	return ( EHCI_RING_COUNT - fill );
398
+}
399
+
400
+/** Time to delay after enabling power to a port
401
+ *
402
+ * This is not mandated by EHCI; we use the value given for xHCI.
403
+ */
404
+#define EHCI_PORT_POWER_DELAY_MS 20
405
+
406
+/** Maximum time to wait for BIOS to release ownership
407
+ *
408
+ * This is a policy decision.
409
+ */
410
+#define EHCI_USBLEGSUP_MAX_WAIT_MS 100
411
+
412
+/** Maximum time to wait for asynchronous schedule to advance
413
+ *
414
+ * This is a policy decision.
415
+ */
416
+#define EHCI_ASYNC_ADVANCE_MAX_WAIT_MS 100
417
+
418
+/** Maximum time to wait for host controller to stop
419
+ *
420
+ * This is a policy decision.
421
+ */
422
+#define EHCI_STOP_MAX_WAIT_MS 100
423
+
424
+/** Maximum time to wait for reset to complete
425
+ *
426
+ * This is a policy decision.
427
+ */
428
+#define EHCI_RESET_MAX_WAIT_MS 500
429
+
430
+/** Maximum time to wait for a port reset to complete
431
+ *
432
+ * This is a policy decision.
433
+ */
434
+#define EHCI_PORT_RESET_MAX_WAIT_MS 500
435
+
436
+/** An EHCI transfer */
437
+struct ehci_transfer {
438
+	/** Data buffer */
439
+	void *data;
440
+	/** Length */
441
+	size_t len;
442
+	/** Flags
443
+	 *
444
+	 * This is the bitwise OR of zero or more EHCI_FL_XXX values.
445
+	 * The low 8 bits are copied to the flags byte within the
446
+	 * transfer descriptor; the remaining bits hold flags
447
+	 * meaningful only to our driver code.
448
+	 */
449
+	unsigned int flags;
450
+};
451
+
452
+/** Copy data to immediate data buffer */
453
+#define EHCI_FL_IMMEDIATE 0x0100
454
+
455
+/** Set initial data toggle */
456
+#define EHCI_FL_TOGGLE 0x8000
457
+
458
+/** An EHCI device */
459
+struct ehci_device {
460
+	/** Registers */
461
+	void *regs;
462
+
463
+	/** Capability registers */
464
+	void *cap;
465
+	/** Operational registers */
466
+	void *op;
467
+
468
+	/** Number of ports */
469
+	unsigned int ports;
470
+	/** 64-bit addressing capability */
471
+	int addr64;
472
+	/** Frame list size */
473
+	unsigned int flsize;
474
+	/** EHCI extended capabilities offset */
475
+	unsigned int eecp;
476
+
477
+	/** USB legacy support capability (if present and enabled) */
478
+	unsigned int legacy;
479
+
480
+	/** Control data structure segment */
481
+	uint32_t ctrldssegment;
482
+	/** Asynchronous queue head */
483
+	struct ehci_queue_head *head;
484
+	/** Periodic frame list */
485
+	struct ehci_periodic_frame *frame;
486
+
487
+	/** List of all endpoints */
488
+	struct list_head endpoints;
489
+	/** Asynchronous schedule */
490
+	struct list_head async;
491
+	/** Periodic schedule
492
+	 *
493
+	 * Listed in decreasing order of endpoint interval.
494
+	 */
495
+	struct list_head periodic;
496
+
497
+	/** USB bus */
498
+	struct usb_bus *bus;
499
+};
500
+
501
+/** An EHCI endpoint */
502
+struct ehci_endpoint {
503
+	/** EHCI device */
504
+	struct ehci_device *ehci;
505
+	/** USB endpoint */
506
+	struct usb_endpoint *ep;
507
+	/** List of all endpoints */
508
+	struct list_head list;
509
+	/** Endpoint schedule */
510
+	struct list_head schedule;
511
+
512
+	/** Transfer descriptor ring */
513
+	struct ehci_ring ring;
514
+};
515
+
516
+#endif /* _IPXE_EHCI_H */

+ 1
- 0
src/include/ipxe/errfile.h 查看文件

@@ -79,6 +79,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
79 79
 #define ERRFILE_usb		     ( ERRFILE_DRIVER | 0x00070000 )
80 80
 #define ERRFILE_usbhub		     ( ERRFILE_DRIVER | 0x00080000 )
81 81
 #define ERRFILE_xhci		     ( ERRFILE_DRIVER | 0x00090000 )
82
+#define ERRFILE_ehci		     ( ERRFILE_DRIVER | 0x000a0000 )
82 83
 
83 84
 #define ERRFILE_nvs		     ( ERRFILE_DRIVER | 0x00100000 )
84 85
 #define ERRFILE_spi		     ( ERRFILE_DRIVER | 0x00110000 )

+ 3
- 0
src/include/ipxe/usb.h 查看文件

@@ -1178,6 +1178,9 @@ extern unsigned int usb_route_string ( struct usb_device *usb );
1178 1178
 extern unsigned int usb_depth ( struct usb_device *usb );
1179 1179
 extern struct usb_port * usb_root_hub_port ( struct usb_device *usb );
1180 1180
 
1181
+/** Minimum reset time */
1182
+#define USB_RESET_DELAY_MS 50
1183
+
1181 1184
 /** Maximum time to wait for a control transaction to complete
1182 1185
  *
1183 1186
  * This is a policy decision.

Loading…
取消
儲存