[coreboot-gerrit] New patch to review for coreboot: 5bb1a9f libpayload: Redirect USB slave init through controller driver

Nico Huber (nico.huber@secunet.com) gerrit at coreboot.org
Thu Jun 13 14:46:31 CEST 2013


Nico Huber (nico.huber at secunet.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3447

-gerrit

commit 5bb1a9f6679dca7051cce0a7e949800cdb940937
Author: Patrick Georgi <patrick.georgi at secunet.com>
Date:   Fri May 24 15:48:56 2013 +0200

    libpayload: Redirect USB slave init through controller driver
    
    xHCI requires special treatment of set_address since it determines
    the device number itself (instead of the driver, as with the other
    controllers). The controller also wants to validate a chosen device
    configuration and we need to setup additional structures for the
    device and the endpoints.
    
    Therefore, we add three functions to the hci_t structure, namely:
      set_address()
      finish_device_config()
      destroy_device()
    Current implementation for the Set Address request moved into
    generic_set_address() which is set_address() for the UHCI, OCHI and
    EHCI drivers. The latter two are only provided as hooks for the xHCI
    driver.
    
    The Set Configuration request is moved after endpoint enumeration.
    For all other controller drivers nothing changes, as there is no other
    device communication between the lines where the set_configuration()
    call moved.
    
    Change-Id: I6127627b9367ef573aa1a1525782bc1304ea350d
    Signed-off-by: Nico Huber <nico.huber at secunet.com>
    Signed-off-by: Patrick Georgi <patrick.georgi at secunet.com>
---
 payloads/libpayload/drivers/usb/ehci.c |  3 +++
 payloads/libpayload/drivers/usb/ohci.c |  3 +++
 payloads/libpayload/drivers/usb/uhci.c |  3 +++
 payloads/libpayload/drivers/usb/usb.c  | 36 ++++++++++++++++++++++++++++------
 payloads/libpayload/include/usb/usb.h  | 19 +++++++++++++++++-
 5 files changed, 57 insertions(+), 7 deletions(-)

diff --git a/payloads/libpayload/drivers/usb/ehci.c b/payloads/libpayload/drivers/usb/ehci.c
index 5af99e0..f5c14d5 100644
--- a/payloads/libpayload/drivers/usb/ehci.c
+++ b/payloads/libpayload/drivers/usb/ehci.c
@@ -754,6 +754,9 @@ ehci_init (pcidev_t addr)
 	controller->shutdown = ehci_shutdown;
 	controller->bulk = ehci_bulk;
 	controller->control = ehci_control;
+	controller->set_address = generic_set_address;
+	controller->finish_device_config = NULL;
+	controller->destroy_device = NULL;
 	controller->create_intr_queue = ehci_create_intr_queue;
 	controller->destroy_intr_queue = ehci_destroy_intr_queue;
 	controller->poll_intr_queue = ehci_poll_intr_queue;
diff --git a/payloads/libpayload/drivers/usb/ohci.c b/payloads/libpayload/drivers/usb/ohci.c
index 44eba31..95db5f4 100644
--- a/payloads/libpayload/drivers/usb/ohci.c
+++ b/payloads/libpayload/drivers/usb/ohci.c
@@ -189,6 +189,9 @@ ohci_init (pcidev_t addr)
 	controller->shutdown = ohci_shutdown;
 	controller->bulk = ohci_bulk;
 	controller->control = ohci_control;
+	controller->set_address = generic_set_address;
+	controller->finish_device_config = NULL;
+	controller->destroy_device = NULL;
 	controller->create_intr_queue = ohci_create_intr_queue;
 	controller->destroy_intr_queue = ohci_destroy_intr_queue;
 	controller->poll_intr_queue = ohci_poll_intr_queue;
diff --git a/payloads/libpayload/drivers/usb/uhci.c b/payloads/libpayload/drivers/usb/uhci.c
index bfa1b57..f9c361d 100644
--- a/payloads/libpayload/drivers/usb/uhci.c
+++ b/payloads/libpayload/drivers/usb/uhci.c
@@ -170,6 +170,9 @@ uhci_init (pcidev_t addr)
 	controller->shutdown = uhci_shutdown;
 	controller->bulk = uhci_bulk;
 	controller->control = uhci_control;
+	controller->set_address = generic_set_address;
+	controller->finish_device_config = NULL;
+	controller->destroy_device = NULL;
 	controller->create_intr_queue = uhci_create_intr_queue;
 	controller->destroy_intr_queue = uhci_destroy_intr_queue;
 	controller->poll_intr_queue = uhci_poll_intr_queue;
diff --git a/payloads/libpayload/drivers/usb/usb.c b/payloads/libpayload/drivers/usb/usb.c
index 6dafd07..54a5935 100644
--- a/payloads/libpayload/drivers/usb/usb.c
+++ b/payloads/libpayload/drivers/usb/usb.c
@@ -242,13 +242,11 @@ get_free_address (hci_t *controller)
 	return -1;		// no free address
 }
 
-static int
-set_address (hci_t *controller, int speed, int hubport, int hubaddr)
+int
+generic_set_address (hci_t *controller, int speed, int hubport, int hubaddr)
 {
 	int adr = get_free_address (controller);	// address to set
 	dev_req_t dr;
-	configuration_descriptor_t *cd;
-	device_descriptor_t *dd;
 
 	memset (&dr, 0, sizeof (dr));
 	dr.data_dir = host_to_device;
@@ -273,11 +271,29 @@ set_address (hci_t *controller, int speed, int hubport, int hubaddr)
 	dev->endpoints[0].direction = SETUP;
 	mdelay (50);
 	if (dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0)) {
-		usb_debug ("set_address failed\n");
 		return -1;
 	}
 	mdelay (50);
+
+	return adr;
+}
+
+static int
+set_address (hci_t *controller, int speed, int hubport, int hubaddr)
+{
+	int adr = controller->set_address(controller, speed, hubport, hubaddr);
+	if (adr < 0 || !controller->devices[adr]) {
+		usb_debug ("set_address failed\n");
+		return -1;
+	}
+	configuration_descriptor_t *cd;
+	device_descriptor_t *dd;
+
+	usbdev_t *dev = controller->devices[adr];
 	dev->address = adr;
+	dev->hub = hubaddr;
+	dev->port = hubport;
+	dev->speed = speed;
 	dev->descriptor = get_descriptor (dev, gen_bmRequestType
 		(device_to_host, standard_type, dev_recp), 1, 0, 0);
 	dd = (device_descriptor_t *) dev->descriptor;
@@ -298,7 +314,6 @@ set_address (hci_t *controller, int speed, int hubport, int hubaddr)
 	dev->configuration = get_descriptor (dev, gen_bmRequestType
 		(device_to_host, standard_type, dev_recp), 2, 0, 0);
 	cd = (configuration_descriptor_t *) dev->configuration;
-	set_configuration (dev);
 	interface_descriptor_t *interface =
 		(interface_descriptor_t *) (((char *) cd) + cd->bLength);
 	{
@@ -366,6 +381,13 @@ set_address (hci_t *controller, int speed, int hubport, int hubaddr)
 		}
 	}
 
+	if (controller->finish_device_config &&
+			controller->finish_device_config(dev))
+		return adr; /* Device isn't configured correctly,
+			       only control transfers may work. */
+
+	set_configuration(dev);
+
 	int class = dd->bDeviceClass;
 	if (class == 0)
 		class = interface->bInterfaceClass;
@@ -475,6 +497,8 @@ usb_detach_device(hci_t *controller, int devno)
 		controller->devices[devno]->destroy (controller->devices[devno]);
 		free(controller->devices[devno]);
 		controller->devices[devno] = NULL;
+		if (controller->destroy_device)
+			controller->destroy_device(controller, devno);
 	}
 }
 
diff --git a/payloads/libpayload/include/usb/usb.h b/payloads/libpayload/include/usb/usb.h
index d82ce27..172a7cc 100644
--- a/payloads/libpayload/include/usb/usb.h
+++ b/payloads/libpayload/include/usb/usb.h
@@ -114,7 +114,7 @@ struct usbdev {
 typedef enum { OHCI = 0, UHCI = 1, EHCI = 2, XHCI = 3} hc_type;
 
 struct usbdev_hc {
-	struct usbdev_hc *next;
+	hci_t *next;
 	pcidev_t bus_address;
 	u32 reg_base;
 	hc_type type;
@@ -142,6 +142,20 @@ struct usbdev_hc {
 	void (*destroy_intr_queue) (endpoint_t *ep, void *queue);
 	u8* (*poll_intr_queue) (void *queue);
 	void *instance;
+
+	/* set_address():		Tell the usb device its address and
+					return it. xHCI controllers want to
+					do this by themself. Also, the usbdev
+					structure has to be allocated and
+					initialized. */
+	int (*set_address) (hci_t *controller, int speed, int hubport, int hubaddr);
+	/* finish_device_config():	Another hook for xHCI,
+					returns 0 on success. */
+	int (*finish_device_config) (usbdev_t *dev);
+	/* destroy_device():		Finally, destroy all structures that
+					were allocated during set_address()
+					and finish_device_config(). */
+	void (*destroy_device) (hci_t *controller, int devaddr);
 };
 
 typedef struct {
@@ -249,6 +263,9 @@ gen_bmRequestType (dev_req_dir dir, dev_req_type type, dev_req_recp recp)
 	return (dir << 7) | (type << 5) | recp;
 }
 
+/* default "set address" handler */
+int generic_set_address (hci_t *controller, int speed, int hubport, int hubaddr);
+
 void usb_detach_device(hci_t *controller, int devno);
 int usb_attach_device(hci_t *controller, int hubaddress, int port, int speed);
 



More information about the coreboot-gerrit mailing list