소스 검색

[ehci] Support USB1 devices attached via transaction translators

Support low-speed and full-speed devices attached to a USB2 hub.  Such
devices use a transaction translator (TT) within the USB2 hub, which
asynchronously initiates transactions on the lower-speed bus and
returns the result via a split completion on the high-speed bus.

We make the simplifying assumption that there will never be more than
sixteen active interrupt endpoints behind a single transaction
translator; this assumption allows us to schedule all periodic start
splits in microframe 0 and all periodic split completions in
microframes 2 and 3.  (We do not handle isochronous endpoints.)

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 10 년 전
부모
커밋
b418af26d9
2개의 변경된 파일53개의 추가작업 그리고 11개의 파일을 삭제
  1. 19
    11
      src/drivers/usb/ehci.c
  2. 34
    0
      src/drivers/usb/ehci.h

+ 19
- 11
src/drivers/usb/ehci.c 파일 보기

545
 		assert ( xfer->len <= EHCI_LEN_MASK );
545
 		assert ( xfer->len <= EHCI_LEN_MASK );
546
 		assert ( EHCI_FL_TOGGLE == EHCI_LEN_TOGGLE );
546
 		assert ( EHCI_FL_TOGGLE == EHCI_LEN_TOGGLE );
547
 		desc->len = cpu_to_le16 ( xfer->len | toggle );
547
 		desc->len = cpu_to_le16 ( xfer->len | toggle );
548
-		desc->flags = xfer->flags;
548
+		desc->flags = ( xfer->flags | EHCI_FL_CERR_MAX );
549
 
549
 
550
 		/* Copy data to immediate data buffer (if requested) */
550
 		/* Copy data to immediate data buffer (if requested) */
551
 		data = xfer->data;
551
 		data = xfer->data;
902
 		chr |= EHCI_CHR_TOGGLE;
902
 		chr |= EHCI_CHR_TOGGLE;
903
 
903
 
904
 	/* Determine endpoint speed */
904
 	/* Determine endpoint speed */
905
-	switch ( usb->port->speed ) {
906
-	case USB_SPEED_HIGH :
905
+	if ( usb->port->speed == USB_SPEED_HIGH ) {
907
 		chr |= EHCI_CHR_EPS_HIGH;
906
 		chr |= EHCI_CHR_EPS_HIGH;
908
-		break;
909
-	case USB_SPEED_FULL :
910
-		chr |= EHCI_CHR_EPS_FULL;
911
-		break;
912
-	default:
913
-		assert ( usb->port->speed == USB_SPEED_LOW );
914
-		chr |= EHCI_CHR_EPS_LOW;
907
+	} else {
908
+		if ( usb->port->speed == USB_SPEED_FULL ) {
909
+			chr |= EHCI_CHR_EPS_FULL;
910
+		} else {
911
+			chr |= EHCI_CHR_EPS_LOW;
912
+		}
915
 		if ( attr == USB_ENDPOINT_ATTR_CONTROL )
913
 		if ( attr == USB_ENDPOINT_ATTR_CONTROL )
916
 			chr |= EHCI_CHR_CONTROL;
914
 			chr |= EHCI_CHR_CONTROL;
917
-		break;
918
 	}
915
 	}
919
 
916
 
920
 	return chr;
917
 	return chr;
927
  * @ret cap		Endpoint capabilities
924
  * @ret cap		Endpoint capabilities
928
  */
925
  */
929
 static uint32_t ehci_endpoint_capabilities ( struct usb_endpoint *ep ) {
926
 static uint32_t ehci_endpoint_capabilities ( struct usb_endpoint *ep ) {
927
+	struct usb_device *usb = ep->usb;
928
+	struct usb_port *tt = usb_transaction_translator ( usb );
930
 	unsigned int attr = ( ep->attributes & USB_ENDPOINT_ATTR_TYPE_MASK );
929
 	unsigned int attr = ( ep->attributes & USB_ENDPOINT_ATTR_TYPE_MASK );
931
 	uint32_t cap;
930
 	uint32_t cap;
932
 	unsigned int i;
931
 	unsigned int i;
943
 		}
942
 		}
944
 	}
943
 	}
945
 
944
 
945
+	/* Set transaction translator hub address and port, if applicable */
946
+	if ( tt ) {
947
+		assert ( tt->hub->usb );
948
+		cap |= ( EHCI_CAP_TT_HUB ( tt->hub->usb->address ) |
949
+			 EHCI_CAP_TT_PORT ( tt->address ) );
950
+		if ( attr == USB_ENDPOINT_ATTR_INTERRUPT )
951
+			cap |= EHCI_CAP_SPLIT_SCHED_DEFAULT;
952
+	}
953
+
946
 	return cap;
954
 	return cap;
947
 }
955
 }
948
 
956
 

+ 34
- 0
src/drivers/usb/ehci.h 파일 보기

285
 /** SETUP token */
285
 /** SETUP token */
286
 #define EHCI_FL_PID_SETUP EHCI_FL_PID ( 2 )
286
 #define EHCI_FL_PID_SETUP EHCI_FL_PID ( 2 )
287
 
287
 
288
+/** Error counter */
289
+#define EHCI_FL_CERR( count ) ( (count) << 2 )
290
+
291
+/** Error counter maximum value */
292
+#define EHCI_FL_CERR_MAX EHCI_FL_CERR ( 3 )
293
+
288
 /** Interrupt on completion */
294
 /** Interrupt on completion */
289
 #define EHCI_FL_IOC 0x80
295
 #define EHCI_FL_IOC 0x80
290
 
296
 
341
 /** Interrupt schedule mask */
347
 /** Interrupt schedule mask */
342
 #define EHCI_CAP_INTR_SCHED( uframe ) ( 1 << ( (uframe) + 0 ) )
348
 #define EHCI_CAP_INTR_SCHED( uframe ) ( 1 << ( (uframe) + 0 ) )
343
 
349
 
350
+/** Split completion schedule mask */
351
+#define EHCI_CAP_SPLIT_SCHED( uframe ) ( 1 << ( (uframe) + 8 ) )
352
+
353
+/** Default split completion schedule mask
354
+ *
355
+ * We schedule all split starts in microframe 0, on the assumption
356
+ * that we will never have to deal with more than sixteen actively
357
+ * interrupting devices via the same transaction translator.  We
358
+ * schedule split completions for all remaining microframes after
359
+ * microframe 1 (in which the low-speed or full-speed transaction is
360
+ * assumed to execute).  This is a very crude approximation designed
361
+ * to avoid the need for calculating exactly when low-speed and
362
+ * full-speed transactions will execute.  Since we only ever deal with
363
+ * interrupt endpoints (rather than isochronous endpoints), the volume
364
+ * of periodic traffic is extremely low, and this approximation should
365
+ * remain valid.
366
+ */
367
+#define EHCI_CAP_SPLIT_SCHED_DEFAULT					\
368
+	( EHCI_CAP_SPLIT_SCHED ( 2 ) | EHCI_CAP_SPLIT_SCHED ( 3 ) |	\
369
+	  EHCI_CAP_SPLIT_SCHED ( 4 ) | EHCI_CAP_SPLIT_SCHED ( 5 ) |	\
370
+	  EHCI_CAP_SPLIT_SCHED ( 6 ) | EHCI_CAP_SPLIT_SCHED ( 7 ) )
371
+
372
+/** Transaction translator hub address */
373
+#define EHCI_CAP_TT_HUB( address ) ( (address) << 16 )
374
+
375
+/** Transaction translator port number */
376
+#define EHCI_CAP_TT_PORT( port ) ( (port) << 23 )
377
+
344
 /** High-bandwidth pipe multiplier */
378
 /** High-bandwidth pipe multiplier */
345
 #define EHCI_CAP_MULT( mult ) ( (mult) << 30 )
379
 #define EHCI_CAP_MULT( mult ) ( (mult) << 30 )
346
 
380
 

Loading…
취소
저장