浏览代码

[usb] Clear transaction translator buffers when applicable

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 10 年前
父节点
当前提交
5486c947e2
共有 2 个文件被更改,包括 72 次插入4 次删除
  1. 68
    4
      src/drivers/bus/usb.c
  2. 4
    0
      src/include/ipxe/usb.h

+ 68
- 4
src/drivers/bus/usb.c 查看文件

@@ -321,6 +321,37 @@ int usb_endpoint_open ( struct usb_endpoint *ep ) {
321 321
 	return rc;
322 322
 }
323 323
 
324
+/**
325
+ * Clear transaction translator (if applicable)
326
+ *
327
+ * @v ep		USB endpoint
328
+ * @ret rc		Return status code
329
+ */
330
+static int usb_endpoint_clear_tt ( struct usb_endpoint *ep ) {
331
+	struct usb_device *usb = ep->usb;
332
+	struct usb_port *tt;
333
+	int rc;
334
+
335
+	/* Do nothing if this is a periodic endpoint */
336
+	if ( ep->attributes & USB_ENDPOINT_ATTR_PERIODIC )
337
+		return 0;
338
+
339
+	/* Do nothing if this endpoint is not behind a transaction translator */
340
+	tt = usb_transaction_translator ( usb );
341
+	if ( ! tt )
342
+		return 0;
343
+
344
+	/* Clear transaction translator buffer */
345
+	if ( ( rc = tt->hub->driver->clear_tt ( tt->hub, tt, ep ) ) != 0 ) {
346
+		DBGC ( usb, "USB %s %s could not clear transaction translator: "
347
+		       "%s\n", usb->name, usb_endpoint_name ( ep->address ),
348
+		       strerror ( rc ) );
349
+		return rc;
350
+	}
351
+
352
+	return 0;
353
+}
354
+
324 355
 /**
325 356
  * Close USB endpoint
326 357
  *
@@ -345,6 +376,9 @@ void usb_endpoint_close ( struct usb_endpoint *ep ) {
345 376
 	/* Discard any recycled buffers, if applicable */
346 377
 	if ( ep->max )
347 378
 		usb_flush ( ep );
379
+
380
+	/* Clear transaction translator, if applicable */
381
+	usb_endpoint_clear_tt ( ep );
348 382
 }
349 383
 
350 384
 /**
@@ -369,6 +403,10 @@ static int usb_endpoint_reset ( struct usb_endpoint *ep ) {
369 403
 		return rc;
370 404
 	}
371 405
 
406
+	/* Clear transaction translator, if applicable */
407
+	if ( ( rc = usb_endpoint_clear_tt ( ep ) ) != 0 )
408
+		return rc;
409
+
372 410
 	/* Clear endpoint halt, if applicable */
373 411
 	type = ( ep->attributes & USB_ENDPOINT_ATTR_TYPE_MASK );
374 412
 	if ( ( type != USB_ENDPOINT_ATTR_CONTROL ) &&
@@ -1949,14 +1987,16 @@ void usb_free_address ( struct usb_bus *bus, unsigned int address ) {
1949 1987
  * @ret route		USB route string
1950 1988
  */
1951 1989
 unsigned int usb_route_string ( struct usb_device *usb ) {
1990
+	struct usb_device *parent;
1952 1991
 	unsigned int route;
1953 1992
 
1954 1993
 	/* Navigate up to root hub, constructing route string as we go */
1955
-	for ( route = 0 ; usb->port->hub->usb ; usb = usb->port->hub->usb ) {
1994
+	for ( route = 0 ; ( parent = usb->port->hub->usb ) ; usb = parent ) {
1956 1995
 		route <<= 4;
1957 1996
 		route |= ( ( usb->port->address > 0xf ) ?
1958 1997
 			   0xf : usb->port->address );
1959 1998
 	}
1999
+
1960 2000
 	return route;
1961 2001
 }
1962 2002
 
@@ -1967,10 +2007,11 @@ unsigned int usb_route_string ( struct usb_device *usb ) {
1967 2007
  * @ret depth		Hub depth
1968 2008
  */
1969 2009
 unsigned int usb_depth ( struct usb_device *usb ) {
2010
+	struct usb_device *parent;
1970 2011
 	unsigned int depth;
1971 2012
 
1972 2013
 	/* Navigate up to root hub, constructing depth as we go */
1973
-	for ( depth = 0 ; usb->port->hub->usb ; usb = usb->port->hub->usb )
2014
+	for ( depth = 0 ; ( parent = usb->port->hub->usb ) ; usb = parent )
1974 2015
 		depth++;
1975 2016
 
1976 2017
 	return depth;
@@ -1983,14 +2024,37 @@ unsigned int usb_depth ( struct usb_device *usb ) {
1983 2024
  * @ret port		Root hub port
1984 2025
  */
1985 2026
 struct usb_port * usb_root_hub_port ( struct usb_device *usb ) {
2027
+	struct usb_device *parent;
1986 2028
 
1987 2029
 	/* Navigate up to root hub */
1988
-	while ( usb->port->hub->usb )
1989
-		usb = usb->port->hub->usb;
2030
+	while ( ( parent = usb->port->hub->usb ) )
2031
+		usb = parent;
1990 2032
 
1991 2033
 	return usb->port;
1992 2034
 }
1993 2035
 
2036
+/**
2037
+ * Get USB transaction translator
2038
+ *
2039
+ * @v usb		USB device
2040
+ * @ret port		Transaction translator port, or NULL
2041
+ */
2042
+struct usb_port * usb_transaction_translator ( struct usb_device *usb ) {
2043
+	struct usb_device *parent;
2044
+
2045
+	/* Navigate up to root hub.  If we find a low-speed or
2046
+	 * full-speed port with a higher-speed parent device, then
2047
+	 * that port is the transaction translator.
2048
+	 */
2049
+	for ( ; ( parent = usb->port->hub->usb ) ; usb = parent ) {
2050
+		if ( ( usb->port->speed <= USB_SPEED_FULL ) &&
2051
+		     ( parent->port->speed > USB_SPEED_FULL ) )
2052
+			return usb->port;
2053
+	}
2054
+
2055
+	return NULL;
2056
+}
2057
+
1994 2058
 /* Drag in objects via register_usb_bus() */
1995 2059
 REQUIRING_SYMBOL ( register_usb_bus );
1996 2060
 

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

@@ -249,6 +249,9 @@ struct usb_endpoint_descriptor {
249 249
 /** Endpoint attribute transfer type mask */
250 250
 #define USB_ENDPOINT_ATTR_TYPE_MASK 0x03
251 251
 
252
+/** Endpoint periodic type */
253
+#define USB_ENDPOINT_ATTR_PERIODIC 0x01
254
+
252 255
 /** Control endpoint transfer type */
253 256
 #define USB_ENDPOINT_ATTR_CONTROL 0x00
254 257
 
@@ -1189,6 +1192,7 @@ extern void usb_free_address ( struct usb_bus *bus, unsigned int address );
1189 1192
 extern unsigned int usb_route_string ( struct usb_device *usb );
1190 1193
 extern unsigned int usb_depth ( struct usb_device *usb );
1191 1194
 extern struct usb_port * usb_root_hub_port ( struct usb_device *usb );
1195
+extern struct usb_port * usb_transaction_translator ( struct usb_device *usb );
1192 1196
 
1193 1197
 /** Minimum reset time
1194 1198
  *

正在加载...
取消
保存