diff options
Diffstat (limited to 'qemu/roms/openbios/drivers/usb.c')
-rw-r--r-- | qemu/roms/openbios/drivers/usb.c | 587 |
1 files changed, 0 insertions, 587 deletions
diff --git a/qemu/roms/openbios/drivers/usb.c b/qemu/roms/openbios/drivers/usb.c deleted file mode 100644 index c6e37174e..000000000 --- a/qemu/roms/openbios/drivers/usb.c +++ /dev/null @@ -1,587 +0,0 @@ -/* - * Driver for USB ported from CoreBoot - * - * Copyright (C) 2014 BALATON Zoltan - * - * This file was part of the libpayload project. - * - * Copyright (C) 2008-2010 coresystems GmbH - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" -#include "drivers/usb.h" -#include "usb.h" -#include "timer.h" -#include "libc/byteorder.h" - -hci_t *usb_hcs = 0; - -static void usb_nop_init (usbdev_t *dev); - -static void -usb_nop_destroy (usbdev_t *dev) -{ - if (dev->descriptor != 0) - free (dev->descriptor); - usb_nop_init (dev); - dev->address = -1; - dev->hub = -1; - dev->port = -1; -} - -static void -usb_nop_poll (usbdev_t *dev) -{ - return; -} - -static void -usb_nop_init (usbdev_t *dev) -{ - dev->descriptor = 0; - dev->destroy = usb_nop_destroy; - dev->poll = usb_nop_poll; -} - -hci_t * -new_controller (void) -{ - hci_t *controller = malloc (sizeof (hci_t)); - - if (controller) { - /* atomic */ - controller->next = usb_hcs; - usb_hcs = controller; - /* atomic end */ - } - - return controller; -} - -void -detach_controller (hci_t *controller) -{ - if (controller == NULL) - return; - if (usb_hcs == controller) { - usb_hcs = controller->next; - } else { - hci_t *it = usb_hcs; - while (it != NULL) { - if (it->next == controller) { - it->next = controller->next; - return; - } - it = it->next; - } - } -} - -/** - * Shut down all controllers - */ -int -usb_exit (void) -{ - while (usb_hcs != NULL) { - usb_hcs->shutdown(usb_hcs); - } - return 0; -} - -/** - * Polls all hubs on all USB controllers, to find out about device changes - */ -void -usb_poll (void) -{ - if (usb_hcs == 0) - return; - hci_t *controller = usb_hcs; - while (controller != NULL) { - int i; - for (i = 0; i < 128; i++) { - if (controller->devices[i] != 0) { - controller->devices[i]->poll (controller->devices[i]); - } - } - controller = controller->next; - } -} - -void -init_device_entry (hci_t *controller, int i) -{ - if (controller->devices[i] != 0) - usb_debug("warning: device %d reassigned?\n", i); - controller->devices[i] = malloc(sizeof(usbdev_t)); - controller->devices[i]->controller = controller; - controller->devices[i]->address = -1; - controller->devices[i]->hub = -1; - controller->devices[i]->port = -1; - controller->devices[i]->init = usb_nop_init; - controller->devices[i]->init (controller->devices[i]); -} - -void -set_feature (usbdev_t *dev, int endp, int feature, int rtype) -{ - dev_req_t dr; - - dr.bmRequestType = rtype; - dr.data_dir = host_to_device; - dr.bRequest = SET_FEATURE; - dr.wValue = __cpu_to_le16(feature); - dr.wIndex = __cpu_to_le16(endp); - dr.wLength = 0; - dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0); -} - -void -get_status (usbdev_t *dev, int intf, int rtype, int len, void *data) -{ - dev_req_t dr; - - dr.bmRequestType = rtype; - dr.data_dir = device_to_host; - dr.bRequest = GET_STATUS; - dr.wValue = 0; - dr.wIndex = __cpu_to_le16(intf); - dr.wLength = __cpu_to_le16(len); - dev->controller->control (dev, IN, sizeof (dr), &dr, len, data); -} - -u8 * -get_descriptor (usbdev_t *dev, unsigned char bmRequestType, int descType, - int descIdx, int langID) -{ - u8 buf[8]; - u8 *result; - dev_req_t dr; - int size; - - dr.bmRequestType = bmRequestType; - dr.data_dir = device_to_host; // always like this for descriptors - dr.bRequest = GET_DESCRIPTOR; - dr.wValue = __cpu_to_le16((descType << 8) | descIdx); - dr.wIndex = __cpu_to_le16(langID); - dr.wLength = __cpu_to_le16(8); - if (dev->controller->control (dev, IN, sizeof (dr), &dr, 8, buf)) { - usb_debug ("getting descriptor size (type %x) failed\n", - descType); - } - - if (descType == 1) { - device_descriptor_t *dd = (device_descriptor_t *) buf; - usb_debug ("maxPacketSize0: %x\n", dd->bMaxPacketSize0); - if (dd->bMaxPacketSize0 != 0) - dev->endpoints[0].maxpacketsize = dd->bMaxPacketSize0; - } - - /* special case for configuration descriptors: they carry all their - subsequent descriptors with them, and keep the entire size at a - different location */ - size = buf[0]; - if (buf[1] == 2) { - int realsize = __le16_to_cpu(((unsigned short *) (buf + 2))[0]); - size = realsize; - } - result = malloc (size); - memset (result, 0, size); - dr.wLength = __cpu_to_le16(size); - if (dev->controller-> - control (dev, IN, sizeof (dr), &dr, size, result)) { - usb_debug ("getting descriptor (type %x, size %x) failed\n", - descType, size); - } - - return result; -} - -void -set_configuration (usbdev_t *dev) -{ - dev_req_t dr; - - dr.bmRequestType = 0; - dr.bRequest = SET_CONFIGURATION; - dr.wValue = __cpu_to_le16(dev->configuration[5]); - dr.wIndex = 0; - dr.wLength = 0; - dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0); -} - -int -clear_feature (usbdev_t *dev, int endp, int feature, int rtype) -{ - dev_req_t dr; - - dr.bmRequestType = rtype; - dr.data_dir = host_to_device; - dr.bRequest = CLEAR_FEATURE; - dr.wValue = __cpu_to_le16(feature); - dr.wIndex = __cpu_to_le16(endp); - dr.wLength = 0; - return dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0); -} - -int -clear_stall (endpoint_t *ep) -{ - usbdev_t *dev = ep->dev; - int endp = ep->endpoint; - int rtype = gen_bmRequestType (host_to_device, standard_type, - endp ? endp_recp : dev_recp); - - int ret = clear_feature (dev, endp, ENDPOINT_HALT, rtype); - ep->toggle = 0; - return ret; -} - -/* returns free address or -1 */ -static int -get_free_address (hci_t *controller) -{ - int i; - for (i = 1; i < 128; i++) { - if (controller->devices[i] == 0) - return i; - } - usb_debug ("no free address found\n"); - return -1; // no free address -} - -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; - - memset (&dr, 0, sizeof (dr)); - dr.data_dir = host_to_device; - dr.req_type = standard_type; - dr.req_recp = dev_recp; - dr.bRequest = SET_ADDRESS; - dr.wValue = __cpu_to_le16(adr); - dr.wIndex = 0; - dr.wLength = 0; - - init_device_entry(controller, adr); - usbdev_t *dev = controller->devices[adr]; - // dummy values for registering the address - dev->address = 0; - dev->hub = hubaddr; - dev->port = hubport; - dev->speed = speed; - dev->endpoints[0].dev = dev; - dev->endpoints[0].endpoint = 0; - dev->endpoints[0].maxpacketsize = 8; - dev->endpoints[0].toggle = 0; - dev->endpoints[0].direction = SETUP; - mdelay (50); - if (dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0)) { - return -1; - } - mdelay (50); - - return adr; -} - -/* Normalize bInterval to log2 of microframes */ -static int -usb_decode_interval(const int speed, const endpoint_type type, const unsigned char bInterval) -{ -#define LOG2(a) ((sizeof(unsigned) << 3) - __builtin_clz(a) - 1) - switch (speed) { - case LOW_SPEED: - switch (type) { - case ISOCHRONOUS: case INTERRUPT: - return LOG2(bInterval) + 3; - default: - return 0; - } - case FULL_SPEED: - switch (type) { - case ISOCHRONOUS: - return (bInterval - 1) + 3; - case INTERRUPT: - return LOG2(bInterval) + 3; - default: - return 0; - } - case HIGH_SPEED: - switch (type) { - case ISOCHRONOUS: case INTERRUPT: - return bInterval - 1; - default: - return LOG2(bInterval); - } - case SUPER_SPEED: - switch (type) { - case ISOCHRONOUS: case INTERRUPT: - return bInterval - 1; - default: - return 0; - } - default: - return 0; - } -#undef LOG2 -} - -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; - - usb_debug ("* found device (0x%04x:0x%04x, USB %x.%x)", - __le16_to_cpu(dd->idVendor), __le16_to_cpu(dd->idProduct), - __le16_to_cpu(dd->bcdUSB) >> 8, __le16_to_cpu(dd->bcdUSB) & 0xff); - dev->quirks = USB_QUIRK_NONE; - - usb_debug ("\ndevice has %x configurations\n", dd->bNumConfigurations); - if (dd->bNumConfigurations == 0) { - /* device isn't usable */ - usb_debug ("... no usable configuration!\n"); - dev->address = 0; - return -1; - } - - dev->configuration = get_descriptor (dev, gen_bmRequestType - (device_to_host, standard_type, dev_recp), 2, 0, 0); - cd = (configuration_descriptor_t *) dev->configuration; - interface_descriptor_t *interface = - (interface_descriptor_t *) (((char *) cd) + cd->bLength); - { - int i; - int num = cd->bNumInterfaces; - interface_descriptor_t *current = interface; - usb_debug ("device has %x interfaces\n", num); - if (num > 1) { - usb_debug ("\nNOTICE: This driver defaults to using the first interface.\n" - "This might be the wrong choice and lead to limited functionality\n" - "of the device.\n"); - /* we limit to the first interface, as there was no need to - * implement something else for the time being. If you need - * it, see the SetInterface and GetInterface functions in - * the USB specification, and adapt appropriately. - */ - num = (num > 1) ? 1 : num; - } - for (i = 0; i < num; i++) { - int j; - usb_debug (" #%x has %x endpoints, interface %x:%x, protocol %x\n", - current->bInterfaceNumber, current->bNumEndpoints, current->bInterfaceClass, current->bInterfaceSubClass, current->bInterfaceProtocol); - endpoint_descriptor_t *endp = - (endpoint_descriptor_t *) (((char *) current) - + current->bLength); - /* Skip any non-endpoint descriptor */ - if (endp->bDescriptorType != 0x05) - endp = (endpoint_descriptor_t *)(((char *)endp) + ((char *)endp)[0]); - - memset (dev->endpoints, 0, sizeof (dev->endpoints)); - dev->num_endp = 1; // 0 always exists - dev->endpoints[0].dev = dev; - dev->endpoints[0].maxpacketsize = dd->bMaxPacketSize0; - dev->endpoints[0].direction = SETUP; - dev->endpoints[0].type = CONTROL; - dev->endpoints[0].interval = usb_decode_interval(dev->speed, CONTROL, endp->bInterval); - for (j = 1; j <= current->bNumEndpoints; j++) { -#ifdef CONFIG_DEBUG_USB - static const char *transfertypes[4] = { - "control", "isochronous", "bulk", "interrupt" - }; - usb_debug (" #%x: Endpoint %x (%s), max packet size %x, type %s\n", j, endp->bEndpointAddress & 0x7f, ((endp->bEndpointAddress & 0x80) != 0) ? "in" : "out", __le16_to_cpu(endp->wMaxPacketSize), transfertypes[endp->bmAttributes]); -#endif - endpoint_t *ep = - &dev->endpoints[dev->num_endp++]; - ep->dev = dev; - ep->endpoint = endp->bEndpointAddress; - ep->toggle = 0; - ep->maxpacketsize = __le16_to_cpu(endp->wMaxPacketSize); - ep->direction = - ((endp->bEndpointAddress & 0x80) == - 0) ? OUT : IN; - ep->type = endp->bmAttributes; - ep->interval = usb_decode_interval(dev->speed, ep->type, endp->bInterval); - endp = (endpoint_descriptor_t - *) (((char *) endp) + endp->bLength); - } - current = (interface_descriptor_t *) endp; - } - } - - 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; - - usb_debug(", class: "); - switch (class) { - case audio_device: - usb_debug("audio\n"); - break; - case comm_device: - usb_debug("communication\n"); - break; - case hid_device: - usb_debug ("HID\n"); -#ifdef CONFIG_USB_HID - controller->devices[adr]->init = usb_hid_init; - return adr; -#else - usb_debug ("NOTICE: USB HID support not compiled in\n"); -#endif - break; - case physical_device: - usb_debug("physical\n"); - break; - case imaging_device: - usb_debug("camera\n"); - break; - case printer_device: - usb_debug("printer\n"); - break; - case msc_device: - usb_debug ("MSC\n"); -#ifdef CONFIG_USB_MSC - controller->devices[adr]->init = usb_msc_init; - return adr; -#else - usb_debug ("NOTICE: USB MSC support not compiled in\n"); -#endif - break; - case hub_device: - usb_debug ("hub\n"); -#ifdef CONFIG_USB_HUB - controller->devices[adr]->init = usb_hub_init; - return adr; -#else - usb_debug ("NOTICE: USB hub support not compiled in.\n"); -#endif - break; - case cdc_device: - usb_debug("CDC\n"); - break; - case ccid_device: - usb_debug("smartcard / CCID\n"); - break; - case security_device: - usb_debug("content security\n"); - break; - case video_device: - usb_debug("video\n"); - break; - case healthcare_device: - usb_debug("healthcare\n"); - break; - case diagnostic_device: - usb_debug("diagnostic\n"); - break; - case wireless_device: - usb_debug("wireless\n"); - break; - default: - usb_debug("unsupported class %x\n", class); - break; - } - controller->devices[adr]->init = usb_generic_init; - return adr; -} - -/* - * Should be called by the hub drivers whenever a physical detach occurs - * and can be called by usb class drivers if they are unsatisfied with a - * malfunctioning device. - */ -void -usb_detach_device(hci_t *controller, int devno) -{ - /* check if device exists, as we may have - been called yet by the usb class driver */ - if (controller->devices[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); - } -} - -int -usb_attach_device(hci_t *controller, int hubaddress, int port, int speed) -{ -#ifdef CONFIG_USB_DEBUG - static const char* speeds[] = { "full", "low", "high" }; - usb_debug ("%sspeed device\n", (speed <= 2) ? speeds[speed] : "invalid value - no"); -#endif - int newdev = set_address (controller, speed, port, hubaddress); - if (newdev == -1) - return -1; - usbdev_t *newdev_t = controller->devices[newdev]; - // determine responsible driver - current done in set_address - newdev_t->init (newdev_t); - /* init() may have called usb_detach_device() yet, so check */ - return controller->devices[newdev] ? newdev : -1; -} - -static void -usb_generic_destroy (usbdev_t *dev) -{ - if (usb_generic_remove) - usb_generic_remove(dev); -} - -void -usb_generic_init (usbdev_t *dev) -{ - dev->data = NULL; - dev->destroy = usb_generic_destroy; - - if (usb_generic_create) - usb_generic_create(dev); -} |