diff options
Diffstat (limited to 'qemu/roms/openbios/drivers/usb.h')
-rw-r--r-- | qemu/roms/openbios/drivers/usb.h | 357 |
1 files changed, 357 insertions, 0 deletions
diff --git a/qemu/roms/openbios/drivers/usb.h b/qemu/roms/openbios/drivers/usb.h new file mode 100644 index 000000000..2e23a1370 --- /dev/null +++ b/qemu/roms/openbios/drivers/usb.h @@ -0,0 +1,357 @@ +/* + * Driver for USB ported from CoreBoot + * + * Copyright (C) 2014 BALATON Zoltan + * + * This file was part of the libpayload project. + * + * Copyright (C) 2008 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. + */ + +#ifndef __USB_H +#define __USB_H +#include <drivers/pci.h> + +typedef enum { host_to_device = 0, device_to_host = 1 } dev_req_dir; +typedef enum { standard_type = 0, class_type = 1, vendor_type = + 2, reserved_type = 3 +} dev_req_type; +typedef enum { dev_recp = 0, iface_recp = 1, endp_recp = 2, other_recp = 3 +} dev_req_recp; + +typedef enum { + GET_STATUS = 0, + CLEAR_FEATURE = 1, + SET_FEATURE = 3, + SET_ADDRESS = 5, + GET_DESCRIPTOR = 6, + SET_DESCRIPTOR = 7, + GET_CONFIGURATION = 8, + SET_CONFIGURATION = 9, + GET_INTERFACE = 10, + SET_INTERFACE = 11, + SYNCH_FRAME = 12 +} bRequest_Codes; + +typedef enum { + ENDPOINT_HALT = 0, + DEVICE_REMOTE_WAKEUP = 1, + TEST_MODE = 2 +} feature_selectors; + +enum { + audio_device = 0x01, + comm_device = 0x02, + hid_device = 0x03, + physical_device = 0x05, + imaging_device = 0x06, + printer_device = 0x07, + msc_device = 0x08, + hub_device = 0x09, + cdc_device = 0x0a, + ccid_device = 0x0b, + security_device = 0x0d, + video_device = 0x0e, + healthcare_device = 0x0f, + diagnostic_device = 0xdc, + wireless_device = 0xe0, + misc_device = 0xef, +}; + +enum { hid_subclass_none = 0, hid_subclass_boot = 1 }; + +enum { + hid_boot_proto_none = 0, + hid_boot_proto_keyboard = 1, + hid_boot_proto_mouse = 2 +}; + +typedef struct { + union { + struct { +#ifdef CONFIG_BIG_ENDIAN + dev_req_dir data_dir:1; + dev_req_type req_type:2; + dev_req_recp req_recp:5; +#else + dev_req_recp req_recp:5; + dev_req_type req_type:2; + dev_req_dir data_dir:1; +#endif + } __attribute__ ((packed)); + unsigned char bmRequestType; + } __attribute__ ((packed)); + unsigned char bRequest; + unsigned short wValue; + unsigned short wIndex; + unsigned short wLength; +} __attribute__ ((packed)) dev_req_t; + +struct usbdev_hc; +typedef struct usbdev_hc hci_t; + +struct usbdev; +typedef struct usbdev usbdev_t; + +typedef enum { SETUP, IN, OUT } direction_t; +typedef enum { CONTROL = 0, ISOCHRONOUS = 1, BULK = 2, INTERRUPT = 3 +} endpoint_type; + +typedef struct { + usbdev_t *dev; + int endpoint; + direction_t direction; + int toggle; + int maxpacketsize; + endpoint_type type; + int interval; /* expressed as binary logarithm of the number + of microframes (i.e. t = 125us * 2^interval) */ +} endpoint_t; + +enum { FULL_SPEED = 0, LOW_SPEED = 1, HIGH_SPEED = 2, SUPER_SPEED = 3 }; + +struct usbdev { + hci_t *controller; + endpoint_t endpoints[32]; + int num_endp; + int address; // usb address + int hub; // hub, device is attached to + int port; // port where device is attached + int speed; // 1: lowspeed, 0: fullspeed, 2: highspeed + u32 quirks; // quirks field. got to love usb + void *data; + u8 *descriptor; + u8 *configuration; + void (*init) (usbdev_t *dev); + void (*destroy) (usbdev_t *dev); + void (*poll) (usbdev_t *dev); +}; + +typedef enum { OHCI = 0, UHCI = 1, EHCI = 2, XHCI = 3} hc_type; + +struct usbdev_hc { + hci_t *next; + u32 reg_base; + hc_type type; + usbdev_t *devices[128]; // dev 0 is root hub, 127 is last addressable + + /* start(): Resume operation. */ + void (*start) (hci_t *controller); + /* stop(): Stop operation but keep controller initialized. */ + void (*stop) (hci_t *controller); + /* reset(): Perform a controller reset. The controller needs to + be (re)initialized afterwards to work (again). */ + void (*reset) (hci_t *controller); + /* init(): Initialize a (previously reset) controller + to a working state. */ + void (*init) (hci_t *controller); + /* shutdown(): Stop operation, detach host controller and shutdown + this driver instance. After calling shutdown() any + other usage of this hci_t* is invalid. */ + void (*shutdown) (hci_t *controller); + + int (*bulk) (endpoint_t *ep, int size, u8 *data, int finalize); + int (*control) (usbdev_t *dev, direction_t pid, int dr_length, + void *devreq, int data_length, u8 *data); + void* (*create_intr_queue) (endpoint_t *ep, int reqsize, int reqcount, int reqtiming); + 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 { + unsigned char bDescLength; + unsigned char bDescriptorType; + unsigned char bNbrPorts; + union { + struct { +#ifdef CONFIG_BIG_ENDIAN + unsigned long:8; + unsigned long arePortIndicatorsSupported:1; + unsigned long ttThinkTime:2; + unsigned long overcurrentProtectionMode:2; + unsigned long isCompoundDevice:1; + unsigned long logicalPowerSwitchingMode:2; +#else + unsigned long logicalPowerSwitchingMode:2; + unsigned long isCompoundDevice:1; + unsigned long overcurrentProtectionMode:2; + unsigned long ttThinkTime:2; + unsigned long arePortIndicatorsSupported:1; + unsigned long:8; +#endif + } __attribute__ ((packed)); + unsigned short wHubCharacteristics; + } __attribute__ ((packed)); + unsigned char bPowerOn2PwrGood; + unsigned char bHubContrCurrent; + char DeviceRemovable[]; +} __attribute__ ((packed)) hub_descriptor_t; + +typedef struct { + unsigned char bLength; + unsigned char bDescriptorType; + unsigned short bcdUSB; + unsigned char bDeviceClass; + unsigned char bDeviceSubClass; + unsigned char bDeviceProtocol; + unsigned char bMaxPacketSize0; + unsigned short idVendor; + unsigned short idProduct; + unsigned short bcdDevice; + unsigned char iManufacturer; + unsigned char iProduct; + unsigned char iSerialNumber; + unsigned char bNumConfigurations; +} __attribute__ ((packed)) device_descriptor_t; + +typedef struct { + unsigned char bLength; + unsigned char bDescriptorType; + unsigned short wTotalLength; + unsigned char bNumInterfaces; + unsigned char bConfigurationValue; + unsigned char iConfiguration; + unsigned char bmAttributes; + unsigned char bMaxPower; +} __attribute__ ((packed)) configuration_descriptor_t; + +typedef struct { + unsigned char bLength; + unsigned char bDescriptorType; + unsigned char bInterfaceNumber; + unsigned char bAlternateSetting; + unsigned char bNumEndpoints; + unsigned char bInterfaceClass; + unsigned char bInterfaceSubClass; + unsigned char bInterfaceProtocol; + unsigned char iInterface; +} __attribute__ ((packed)) interface_descriptor_t; + +typedef struct { + unsigned char bLength; + unsigned char bDescriptorType; + unsigned char bEndpointAddress; + unsigned char bmAttributes; + unsigned short wMaxPacketSize; + unsigned char bInterval; +} __attribute__ ((packed)) endpoint_descriptor_t; + +typedef struct { + unsigned char bLength; + unsigned char bDescriptorType; + unsigned short bcdHID; + unsigned char bCountryCode; + unsigned char bNumDescriptors; + unsigned char bReportDescriptorType; + unsigned short wReportDescriptorLength; +} __attribute__ ((packed)) hid_descriptor_t; + +hci_t *new_controller (void); +void detach_controller (hci_t *controller); +void usb_poll (void); +void init_device_entry (hci_t *controller, int num); + +void set_feature (usbdev_t *dev, int endp, int feature, int rtype); +void get_status (usbdev_t *dev, int endp, int rtype, int len, void *data); +void set_configuration (usbdev_t *dev); +int clear_feature (usbdev_t *dev, int endp, int feature, int rtype); +int clear_stall (endpoint_t *ep); + +void usb_hub_init (usbdev_t *dev); +void usb_hid_init (usbdev_t *dev); +void usb_msc_init (usbdev_t *dev); +void usb_generic_init (usbdev_t *dev); + +u8 *get_descriptor (usbdev_t *dev, unsigned char bmRequestType, + int descType, int descIdx, int langID); + +static inline unsigned char +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); + +u32 usb_quirk_check(u16 vendor, u16 device); +int usb_interface_check(u16 vendor, u16 device); + +#define USB_QUIRK_MSC_FORCE_PROTO_SCSI (1 << 0) +#define USB_QUIRK_MSC_FORCE_PROTO_ATAPI (1 << 1) +#define USB_QUIRK_MSC_FORCE_PROTO_UFI (1 << 2) +#define USB_QUIRK_MSC_FORCE_PROTO_RBC (1 << 3) +#define USB_QUIRK_MSC_FORCE_TRANS_BBB (1 << 4) +#define USB_QUIRK_MSC_FORCE_TRANS_CBI (1 << 5) +#define USB_QUIRK_MSC_FORCE_TRANS_CBI_I (1 << 6) +#define USB_QUIRK_MSC_NO_TEST_UNIT_READY (1 << 7) +#define USB_QUIRK_MSC_SHORT_INQUIRY (1 << 8) +#define USB_QUIRK_TEST (1 << 31) +#define USB_QUIRK_NONE 0 + +#ifdef CONFIG_DEBUG_USB +#define usb_debug(fmt, args...) do { printk(fmt , ##args); } while (0) +#else +#define usb_debug(fmt, args...) +#endif + +/** + * To be implemented by libpayload-client. It's called by the USB stack + * when a new USB device is found which isn't claimed by a built in driver, + * so the client has the chance to know about it. + * + * @param dev descriptor for the USB device + */ +void __attribute__((weak)) usb_generic_create (usbdev_t *dev); + +/** + * To be implemented by libpayload-client. It's called by the USB stack + * when it finds out that a USB device is removed which wasn't claimed by a + * built in driver. + * + * @param dev descriptor for the USB device + */ +void __attribute__((weak)) usb_generic_remove (usbdev_t *dev); + +#endif |