From 437fd90c0250dee670290f9b714253671a990160 Mon Sep 17 00:00:00 2001 From: José Pekkarinen Date: Wed, 18 May 2016 13:18:31 +0300 Subject: These changes are the raw update to qemu-2.6. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Collission happened in the following patches: migration: do cleanup operation after completion(738df5b9) Bug fix.(1750c932f86) kvmclock: add a new function to update env->tsc.(b52baab2) The code provided by the patches was already in the upstreamed version. Change-Id: I3cc11841a6a76ae20887b2e245710199e1ea7f9a Signed-off-by: José Pekkarinen --- qemu/roms/ipxe/src/include/ipxe/usb.h | 1319 +++++++++++++++++++++++++++++++++ 1 file changed, 1319 insertions(+) create mode 100644 qemu/roms/ipxe/src/include/ipxe/usb.h (limited to 'qemu/roms/ipxe/src/include/ipxe/usb.h') diff --git a/qemu/roms/ipxe/src/include/ipxe/usb.h b/qemu/roms/ipxe/src/include/ipxe/usb.h new file mode 100644 index 000000000..ab060b8f4 --- /dev/null +++ b/qemu/roms/ipxe/src/include/ipxe/usb.h @@ -0,0 +1,1319 @@ +#ifndef _IPXE_USB_H +#define _IPXE_USB_H + +/** @file + * + * Universal Serial Bus (USB) + * + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +#include +#include +#include +#include +#include +#include + +/** USB protocols */ +enum usb_protocol { + /** USB 2.0 */ + USB_PROTO_2_0 = 0x0200, + /** USB 3.0 */ + USB_PROTO_3_0 = 0x0300, + /** USB 3.1 */ + USB_PROTO_3_1 = 0x0301, +}; + +/** Define a USB speed + * + * @v mantissa Mantissa + * @v exponent Exponent (in engineering terms: 1=k, 2=M, 3=G) + * @ret speed USB speed + */ +#define USB_SPEED( mantissa, exponent ) ( (exponent << 16) | (mantissa) ) + +/** Extract USB speed mantissa */ +#define USB_SPEED_MANTISSA(speed) ( (speed) & 0xffff ) + +/** Extract USB speed exponent */ +#define USB_SPEED_EXPONENT(speed) ( ( (speed) >> 16 ) & 0x3 ) + +/** USB device speeds */ +enum usb_speed { + /** Not connected */ + USB_SPEED_NONE = 0, + /** Low speed (1.5Mbps) */ + USB_SPEED_LOW = USB_SPEED ( 1500, 1 ), + /** Full speed (12Mbps) */ + USB_SPEED_FULL = USB_SPEED ( 12, 2 ), + /** High speed (480Mbps) */ + USB_SPEED_HIGH = USB_SPEED ( 480, 2 ), + /** Super speed (5Gbps) */ + USB_SPEED_SUPER = USB_SPEED ( 5, 3 ), +}; + +/** USB packet IDs */ +enum usb_pid { + /** IN PID */ + USB_PID_IN = 0x69, + /** OUT PID */ + USB_PID_OUT = 0xe1, + /** SETUP PID */ + USB_PID_SETUP = 0x2d, +}; + +/** A USB setup data packet */ +struct usb_setup_packet { + /** Request */ + uint16_t request; + /** Value paramer */ + uint16_t value; + /** Index parameter */ + uint16_t index; + /** Length of data stage */ + uint16_t len; +} __attribute__ (( packed )); + +/** Data transfer is from host to device */ +#define USB_DIR_OUT ( 0 << 7 ) + +/** Data transfer is from device to host */ +#define USB_DIR_IN ( 1 << 7 ) + +/** Standard request type */ +#define USB_TYPE_STANDARD ( 0 << 5 ) + +/** Class-specific request type */ +#define USB_TYPE_CLASS ( 1 << 5 ) + +/** Vendor-specific request type */ +#define USB_TYPE_VENDOR ( 2 << 5 ) + +/** Request recipient is the device */ +#define USB_RECIP_DEVICE ( 0 << 0 ) + +/** Request recipient is an interface */ +#define USB_RECIP_INTERFACE ( 1 << 0 ) + +/** Request recipient is an endpoint */ +#define USB_RECIP_ENDPOINT ( 2 << 0 ) + +/** Construct USB request type */ +#define USB_REQUEST_TYPE(type) ( (type) << 8 ) + +/** Get status */ +#define USB_GET_STATUS ( USB_DIR_IN | USB_REQUEST_TYPE ( 0 ) ) + +/** Clear feature */ +#define USB_CLEAR_FEATURE ( USB_DIR_OUT | USB_REQUEST_TYPE ( 1 ) ) + +/** Set feature */ +#define USB_SET_FEATURE ( USB_DIR_OUT | USB_REQUEST_TYPE ( 3 ) ) + +/** Set address */ +#define USB_SET_ADDRESS ( USB_DIR_OUT | USB_REQUEST_TYPE ( 5 ) ) + +/** Get descriptor */ +#define USB_GET_DESCRIPTOR ( USB_DIR_IN | USB_REQUEST_TYPE ( 6 ) ) + +/** Set descriptor */ +#define USB_SET_DESCRIPTOR ( USB_DIR_OUT | USB_REQUEST_TYPE ( 7 ) ) + +/** Get configuration */ +#define USB_GET_CONFIGURATION ( USB_DIR_IN | USB_REQUEST_TYPE ( 8 ) ) + +/** Set configuration */ +#define USB_SET_CONFIGURATION ( USB_DIR_OUT | USB_REQUEST_TYPE ( 9 ) ) + +/** Get interface */ +#define USB_GET_INTERFACE \ + ( USB_DIR_IN | USB_RECIP_INTERFACE | USB_REQUEST_TYPE ( 10 ) ) + +/** Set interface */ +#define USB_SET_INTERFACE \ + ( USB_DIR_OUT | USB_RECIP_INTERFACE | USB_REQUEST_TYPE ( 11 ) ) + +/** Endpoint halt feature */ +#define USB_ENDPOINT_HALT 0 + +/** A USB class code tuple */ +struct usb_class { + /** Class code */ + uint8_t class; + /** Subclass code */ + uint8_t subclass; + /** Protocol code */ + uint8_t protocol; +} __attribute__ (( packed )); + +/** Class code for USB hubs */ +#define USB_CLASS_HUB 9 + +/** A USB descriptor header */ +struct usb_descriptor_header { + /** Length of descriptor */ + uint8_t len; + /** Descriptor type */ + uint8_t type; +} __attribute__ (( packed )); + +/** A USB device descriptor */ +struct usb_device_descriptor { + /** Descriptor header */ + struct usb_descriptor_header header; + /** USB specification release number in BCD */ + uint16_t protocol; + /** Device class */ + struct usb_class class; + /** Maximum packet size for endpoint zero */ + uint8_t mtu; + /** Vendor ID */ + uint16_t vendor; + /** Product ID */ + uint16_t product; + /** Device release number in BCD */ + uint16_t release; + /** Manufacturer string */ + uint8_t manufacturer; + /** Product string */ + uint8_t name; + /** Serial number string */ + uint8_t serial; + /** Number of possible configurations */ + uint8_t configurations; +} __attribute__ (( packed )); + +/** A USB device descriptor */ +#define USB_DEVICE_DESCRIPTOR 1 + +/** A USB configuration descriptor */ +struct usb_configuration_descriptor { + /** Descriptor header */ + struct usb_descriptor_header header; + /** Total length */ + uint16_t len; + /** Number of interfaces */ + uint8_t interfaces; + /** Configuration value */ + uint8_t config; + /** Configuration string */ + uint8_t name; + /** Attributes */ + uint8_t attributes; + /** Maximum power consumption */ + uint8_t power; +} __attribute__ (( packed )); + +/** A USB configuration descriptor */ +#define USB_CONFIGURATION_DESCRIPTOR 2 + +/** A USB string descriptor */ +struct usb_string_descriptor { + /** Descriptor header */ + struct usb_descriptor_header header; + /** String */ + char string[0]; +} __attribute__ (( packed )); + +/** A USB string descriptor */ +#define USB_STRING_DESCRIPTOR 3 + +/** A USB interface descriptor */ +struct usb_interface_descriptor { + /** Descriptor header */ + struct usb_descriptor_header header; + /** Interface number */ + uint8_t interface; + /** Alternate setting */ + uint8_t alternate; + /** Number of endpoints */ + uint8_t endpoints; + /** Interface class */ + struct usb_class class; + /** Interface name */ + uint8_t name; +} __attribute__ (( packed )); + +/** A USB interface descriptor */ +#define USB_INTERFACE_DESCRIPTOR 4 + +/** A USB endpoint descriptor */ +struct usb_endpoint_descriptor { + /** Descriptor header */ + struct usb_descriptor_header header; + /** Endpoint address */ + uint8_t endpoint; + /** Attributes */ + uint8_t attributes; + /** Maximum packet size and burst size */ + uint16_t sizes; + /** Polling interval */ + uint8_t interval; +} __attribute__ (( packed )); + +/** A USB endpoint descriptor */ +#define USB_ENDPOINT_DESCRIPTOR 5 + +/** Endpoint attribute transfer type mask */ +#define USB_ENDPOINT_ATTR_TYPE_MASK 0x03 + +/** Endpoint periodic type */ +#define USB_ENDPOINT_ATTR_PERIODIC 0x01 + +/** Control endpoint transfer type */ +#define USB_ENDPOINT_ATTR_CONTROL 0x00 + +/** Bulk endpoint transfer type */ +#define USB_ENDPOINT_ATTR_BULK 0x02 + +/** Interrupt endpoint transfer type */ +#define USB_ENDPOINT_ATTR_INTERRUPT 0x03 + +/** Bulk OUT endpoint (internal) type */ +#define USB_BULK_OUT ( USB_ENDPOINT_ATTR_BULK | USB_DIR_OUT ) + +/** Bulk IN endpoint (internal) type */ +#define USB_BULK_IN ( USB_ENDPOINT_ATTR_BULK | USB_DIR_IN ) + +/** Interrupt IN endpoint (internal) type */ +#define USB_INTERRUPT_IN ( USB_ENDPOINT_ATTR_INTERRUPT | USB_DIR_IN ) + +/** Interrupt OUT endpoint (internal) type */ +#define USB_INTERRUPT_OUT ( USB_ENDPOINT_ATTR_INTERRUPT | USB_DIR_OUT ) + +/** USB endpoint MTU */ +#define USB_ENDPOINT_MTU(sizes) ( ( (sizes) >> 0 ) & 0x07ff ) + +/** USB endpoint maximum burst size */ +#define USB_ENDPOINT_BURST(sizes) ( ( (sizes) >> 11 ) & 0x0003 ) + +/** A USB endpoint companion descriptor */ +struct usb_endpoint_companion_descriptor { + /** Descriptor header */ + struct usb_descriptor_header header; + /** Maximum burst size */ + uint8_t burst; + /** Extended attributes */ + uint8_t extended; + /** Number of bytes per service interval */ + uint16_t periodic; +} __attribute__ (( packed )); + +/** A USB endpoint companion descriptor */ +#define USB_ENDPOINT_COMPANION_DESCRIPTOR 48 + +/** A USB interface association descriptor */ +struct usb_interface_association_descriptor { + /** Descriptor header */ + struct usb_descriptor_header header; + /** First interface number */ + uint8_t first; + /** Interface count */ + uint8_t count; + /** Association class */ + struct usb_class class; + /** Association name */ + uint8_t name; +} __attribute__ (( packed )); + +/** A USB interface association descriptor */ +#define USB_INTERFACE_ASSOCIATION_DESCRIPTOR 11 + +/** A class-specific interface descriptor */ +#define USB_CS_INTERFACE_DESCRIPTOR 36 + +/** A class-specific endpoint descriptor */ +#define USB_CS_ENDPOINT_DESCRIPTOR 37 + +/** + * Get next USB descriptor + * + * @v desc USB descriptor header + * @ret next Next USB descriptor header + */ +static inline __attribute__ (( always_inline )) struct usb_descriptor_header * +usb_next_descriptor ( struct usb_descriptor_header *desc ) { + + return ( ( ( void * ) desc ) + desc->len ); +} + +/** + * Check that descriptor lies within a configuration descriptor + * + * @v config Configuration descriptor + * @v desc Descriptor header + * @v is_within Descriptor is within the configuration descriptor + */ +static inline __attribute__ (( always_inline )) int +usb_is_within_config ( struct usb_configuration_descriptor *config, + struct usb_descriptor_header *desc ) { + struct usb_descriptor_header *end = + ( ( ( void * ) config ) + le16_to_cpu ( config->len ) ); + + /* Check that descriptor starts within the configuration + * descriptor, and that the length does not exceed the + * configuration descriptor. This relies on the fact that + * usb_next_descriptor() needs to access only the first byte + * of the descriptor in order to determine the length. + */ + return ( ( desc < end ) && ( usb_next_descriptor ( desc ) <= end ) ); +} + +/** Iterate over all configuration descriptors */ +#define for_each_config_descriptor( desc, config ) \ + for ( desc = container_of ( &(config)->header, \ + typeof ( *desc ), header ) ; \ + usb_is_within_config ( (config), &desc->header ) ; \ + desc = container_of ( usb_next_descriptor ( &desc->header ), \ + typeof ( *desc ), header ) ) + +/** Iterate over all configuration descriptors within an interface descriptor */ +#define for_each_interface_descriptor( desc, config, interface ) \ + for ( desc = container_of ( usb_next_descriptor ( &(interface)-> \ + header ), \ + typeof ( *desc ), header ) ; \ + ( usb_is_within_config ( (config), &desc->header ) && \ + ( desc->header.type != USB_INTERFACE_DESCRIPTOR ) ) ; \ + desc = container_of ( usb_next_descriptor ( &desc->header ), \ + typeof ( *desc ), header ) ) + +/** A USB endpoint */ +struct usb_endpoint { + /** USB device */ + struct usb_device *usb; + /** Endpoint address */ + unsigned int address; + /** Attributes */ + unsigned int attributes; + /** Maximum transfer size */ + size_t mtu; + /** Maximum burst size */ + unsigned int burst; + /** Interval (in microframes) */ + unsigned int interval; + + /** Endpoint is open */ + int open; + /** Buffer fill level */ + unsigned int fill; + + /** List of halted endpoints */ + struct list_head halted; + + /** Host controller operations */ + struct usb_endpoint_host_operations *host; + /** Host controller private data */ + void *priv; + /** Driver operations */ + struct usb_endpoint_driver_operations *driver; + + /** Recycled I/O buffer list */ + struct list_head recycled; + /** Refill buffer length */ + size_t len; + /** Maximum fill level */ + unsigned int max; +}; + +/** USB endpoint host controller operations */ +struct usb_endpoint_host_operations { + /** Open endpoint + * + * @v ep USB endpoint + * @ret rc Return status code + */ + int ( * open ) ( struct usb_endpoint *ep ); + /** Close endpoint + * + * @v ep USB endpoint + */ + void ( * close ) ( struct usb_endpoint *ep ); + /** + * Reset endpoint + * + * @v ep USB endpoint + * @ret rc Return status code + */ + int ( * reset ) ( struct usb_endpoint *ep ); + /** Update MTU + * + * @v ep USB endpoint + * @ret rc Return status code + */ + int ( * mtu ) ( struct usb_endpoint *ep ); + /** Enqueue message transfer + * + * @v ep USB endpoint + * @v iobuf I/O buffer + * @ret rc Return status code + */ + int ( * message ) ( struct usb_endpoint *ep, + struct io_buffer *iobuf ); + /** Enqueue stream transfer + * + * @v ep USB endpoint + * @v iobuf I/O buffer + * @v terminate Terminate using a short packet + * @ret rc Return status code + */ + int ( * stream ) ( struct usb_endpoint *ep, struct io_buffer *iobuf, + int terminate ); +}; + +/** USB endpoint driver operations */ +struct usb_endpoint_driver_operations { + /** Complete transfer + * + * @v ep USB endpoint + * @v iobuf I/O buffer + * @v rc Completion status code + */ + void ( * complete ) ( struct usb_endpoint *ep, + struct io_buffer *iobuf, int rc ); +}; + +/** Control endpoint address */ +#define USB_EP0_ADDRESS 0x00 + +/** Control endpoint attributes */ +#define USB_EP0_ATTRIBUTES 0x00 + +/** Calculate default MTU based on device speed + * + * @v speed Device speed + * @ret mtu Default MTU + */ +#define USB_EP0_DEFAULT_MTU(speed) \ + ( ( (speed) >= USB_SPEED_SUPER ) ? 512 : \ + ( ( (speed) >= USB_SPEED_FULL ) ? 64 : 8 ) ) + +/** Control endpoint maximum burst size */ +#define USB_EP0_BURST 0 + +/** Control endpoint interval */ +#define USB_EP0_INTERVAL 0 + +/** Maximum endpoint number */ +#define USB_ENDPOINT_MAX 0x0f + +/** Endpoint direction is in */ +#define USB_ENDPOINT_IN 0x80 + +/** Construct endpoint index from endpoint address */ +#define USB_ENDPOINT_IDX(address) \ + ( ( (address) & USB_ENDPOINT_MAX ) | \ + ( ( (address) & USB_ENDPOINT_IN ) >> 3 ) ) + +/** + * Initialise USB endpoint + * + * @v ep USB endpoint + * @v usb USB device + * @v driver Driver operations + */ +static inline __attribute__ (( always_inline )) void +usb_endpoint_init ( struct usb_endpoint *ep, struct usb_device *usb, + struct usb_endpoint_driver_operations *driver ) { + + ep->usb = usb; + ep->driver = driver; +} + +/** + * Describe USB endpoint + * + * @v ep USB endpoint + * @v address Endpoint address + * @v attributes Attributes + * @v mtu Maximum packet size + * @v burst Maximum burst size + * @v interval Interval (in microframes) + */ +static inline __attribute__ (( always_inline )) void +usb_endpoint_describe ( struct usb_endpoint *ep, unsigned int address, + unsigned int attributes, size_t mtu, + unsigned int burst, unsigned int interval ) { + + ep->address = address; + ep->attributes = attributes; + ep->mtu = mtu; + ep->burst = burst; + ep->interval = interval; +} + +/** + * Set USB endpoint host controller private data + * + * @v ep USB endpoint + * @v priv Host controller private data + */ +static inline __attribute__ (( always_inline )) void +usb_endpoint_set_hostdata ( struct usb_endpoint *ep, void *priv ) { + ep->priv = priv; +} + +/** + * Get USB endpoint host controller private data + * + * @v ep USB endpoint + * @ret priv Host controller private data + */ +static inline __attribute__ (( always_inline )) void * +usb_endpoint_get_hostdata ( struct usb_endpoint *ep ) { + return ep->priv; +} + +extern const char * usb_endpoint_name ( struct usb_endpoint *ep ); +extern int +usb_endpoint_described ( struct usb_endpoint *ep, + struct usb_configuration_descriptor *config, + struct usb_interface_descriptor *interface, + unsigned int type, unsigned int index ); +extern int usb_endpoint_open ( struct usb_endpoint *ep ); +extern void usb_endpoint_close ( struct usb_endpoint *ep ); +extern int usb_message ( struct usb_endpoint *ep, unsigned int request, + unsigned int value, unsigned int index, + struct io_buffer *iobuf ); +extern int usb_stream ( struct usb_endpoint *ep, struct io_buffer *iobuf, + int terminate ); +extern void usb_complete_err ( struct usb_endpoint *ep, + struct io_buffer *iobuf, int rc ); + +/** + * Initialise USB endpoint refill + * + * @v ep USB endpoint + * @v len Refill buffer length (or zero to use endpoint's MTU) + * @v max Maximum fill level + */ +static inline __attribute__ (( always_inline )) void +usb_refill_init ( struct usb_endpoint *ep, size_t len, unsigned int max ) { + + INIT_LIST_HEAD ( &ep->recycled ); + ep->len = len; + ep->max = max; +} + +/** + * Recycle I/O buffer + * + * @v ep USB endpoint + * @v iobuf I/O buffer + */ +static inline __attribute__ (( always_inline )) void +usb_recycle ( struct usb_endpoint *ep, struct io_buffer *iobuf ) { + + list_add_tail ( &iobuf->list, &ep->recycled ); +} + +extern int usb_prefill ( struct usb_endpoint *ep ); +extern int usb_refill ( struct usb_endpoint *ep ); +extern void usb_flush ( struct usb_endpoint *ep ); + +/** + * A USB function + * + * A USB function represents an association of interfaces within a USB + * device. + */ +struct usb_function { + /** Name */ + const char *name; + /** USB device */ + struct usb_device *usb; + /** Class */ + struct usb_class class; + /** Number of interfaces */ + unsigned int count; + /** Generic device */ + struct device dev; + /** List of functions within this USB device */ + struct list_head list; + + /** Driver */ + struct usb_driver *driver; + /** Driver private data */ + void *priv; + + /** List of interface numbers + * + * This must be the last field within the structure. + */ + uint8_t interface[0]; +}; + +/** + * Set USB function driver private data + * + * @v func USB function + * @v priv Driver private data + */ +static inline __attribute__ (( always_inline )) void +usb_func_set_drvdata ( struct usb_function *func, void *priv ) { + func->priv = priv; +} + +/** + * Get USB function driver private data + * + * @v function USB function + * @ret priv Driver private data + */ +static inline __attribute__ (( always_inline )) void * +usb_func_get_drvdata ( struct usb_function *func ) { + return func->priv; +} + +/** A USB device */ +struct usb_device { + /** Name */ + char name[32]; + /** USB port */ + struct usb_port *port; + /** List of devices on this bus */ + struct list_head list; + /** Device address, if assigned */ + unsigned int address; + /** Device descriptor */ + struct usb_device_descriptor device; + /** List of functions */ + struct list_head functions; + + /** Host controller operations */ + struct usb_device_host_operations *host; + /** Host controller private data */ + void *priv; + + /** Endpoint list */ + struct usb_endpoint *ep[32]; + + /** Control endpoint */ + struct usb_endpoint control; + /** Completed control transfers */ + struct list_head complete; +}; + +/** USB device host controller operations */ +struct usb_device_host_operations { + /** Open device + * + * @v usb USB device + * @ret rc Return status code + */ + int ( * open ) ( struct usb_device *usb ); + /** Close device + * + * @v usb USB device + */ + void ( * close ) ( struct usb_device *usb ); + /** Assign device address + * + * @v usb USB device + * @ret rc Return status code + */ + int ( * address ) ( struct usb_device *usb ); +}; + +/** + * Set USB device host controller private data + * + * @v usb USB device + * @v priv Host controller private data + */ +static inline __attribute__ (( always_inline )) void +usb_set_hostdata ( struct usb_device *usb, void *priv ) { + usb->priv = priv; +} + +/** + * Get USB device host controller private data + * + * @v usb USB device + * @ret priv Host controller private data + */ +static inline __attribute__ (( always_inline )) void * +usb_get_hostdata ( struct usb_device *usb ) { + return usb->priv; +} + +/** + * Get USB endpoint + * + * @v usb USB device + * @v address Endpoint address + * @ret ep USB endpoint, or NULL if not opened + */ +static inline struct usb_endpoint * usb_endpoint ( struct usb_device *usb, + unsigned int address ) { + + return usb->ep[ USB_ENDPOINT_IDX ( address ) ]; +} + +/** A USB port */ +struct usb_port { + /** USB hub */ + struct usb_hub *hub; + /** Port address */ + unsigned int address; + /** Port protocol */ + unsigned int protocol; + /** Port speed */ + unsigned int speed; + /** Port disconnection has been detected + * + * This should be set whenever the underlying hardware reports + * a connection status change. + */ + int disconnected; + /** Port has an attached device */ + int attached; + /** Currently attached device (if in use) + * + * Note that this field will be NULL if the attached device + * has been freed (e.g. because there were no drivers found). + */ + struct usb_device *usb; + /** List of changed ports */ + struct list_head changed; +}; + +/** A USB hub */ +struct usb_hub { + /** Name */ + const char *name; + /** USB bus */ + struct usb_bus *bus; + /** Underlying USB device, if any */ + struct usb_device *usb; + /** Hub protocol */ + unsigned int protocol; + /** Number of ports */ + unsigned int ports; + + /** List of hubs */ + struct list_head list; + + /** Host controller operations */ + struct usb_hub_host_operations *host; + /** Driver operations */ + struct usb_hub_driver_operations *driver; + /** Driver private data */ + void *priv; + + /** Port list + * + * This must be the last field within the structure. + */ + struct usb_port port[0]; +}; + +/** USB hub host controller operations */ +struct usb_hub_host_operations { + /** Open hub + * + * @v hub USB hub + * @ret rc Return status code + */ + int ( * open ) ( struct usb_hub *hub ); + /** Close hub + * + * @v hub USB hub + */ + void ( * close ) ( struct usb_hub *hub ); +}; + +/** USB hub driver operations */ +struct usb_hub_driver_operations { + /** Open hub + * + * @v hub USB hub + * @ret rc Return status code + */ + int ( * open ) ( struct usb_hub *hub ); + /** Close hub + * + * @v hub USB hub + */ + void ( * close ) ( struct usb_hub *hub ); + /** Enable port + * + * @v hub USB hub + * @v port USB port + * @ret rc Return status code + */ + int ( * enable ) ( struct usb_hub *hub, struct usb_port *port ); + /** Disable port + * + * @v hub USB hub + * @v port USB port + * @ret rc Return status code + */ + int ( * disable ) ( struct usb_hub *hub, struct usb_port *port ); + /** Update port speed + * + * @v hub USB hub + * @v port USB port + * @ret rc Return status code + */ + int ( * speed ) ( struct usb_hub *hub, struct usb_port *port ); + /** Clear transaction translator buffer + * + * @v hub USB hub + * @v port USB port + * @v ep USB endpoint + * @ret rc Return status code + */ + int ( * clear_tt ) ( struct usb_hub *hub, struct usb_port *port, + struct usb_endpoint *ep ); +}; + +/** + * Set USB hub driver private data + * + * @v hub USB hub + * @v priv Driver private data + */ +static inline __attribute__ (( always_inline )) void +usb_hub_set_drvdata ( struct usb_hub *hub, void *priv ) { + hub->priv = priv; +} + +/** + * Get USB hub driver private data + * + * @v hub USB hub + * @ret priv Driver private data + */ +static inline __attribute__ (( always_inline )) void * +usb_hub_get_drvdata ( struct usb_hub *hub ) { + return hub->priv; +} + +/** + * Get USB port + * + * @v hub USB hub + * @v address Port address + * @ret port USB port + */ +static inline __attribute__ (( always_inline )) struct usb_port * +usb_port ( struct usb_hub *hub, unsigned int address ) { + + return &hub->port[ address - 1 ]; +} + +/** A USB bus */ +struct usb_bus { + /** Name */ + const char *name; + /** Underlying hardware device */ + struct device *dev; + /** Host controller operations set */ + struct usb_host_operations *op; + + /** Largest transfer allowed on the bus */ + size_t mtu; + /** Address in-use mask + * + * This is used only by buses which perform manual address + * assignment. USB allows for addresses in the range [1,127]. + * We use a simple bitmask which restricts us to the range + * [1,64]; this is unlikely to be a problem in practice. For + * comparison: controllers which perform autonomous address + * assignment (such as xHCI) typically allow for only 32 + * devices per bus anyway. + */ + unsigned long long addresses; + + /** Root hub */ + struct usb_hub *hub; + + /** List of USB buses */ + struct list_head list; + /** List of devices */ + struct list_head devices; + /** List of hubs */ + struct list_head hubs; + + /** Host controller operations */ + struct usb_bus_host_operations *host; + /** Host controller private data */ + void *priv; +}; + +/** USB bus host controller operations */ +struct usb_bus_host_operations { + /** Open bus + * + * @v bus USB bus + * @ret rc Return status code + */ + int ( * open ) ( struct usb_bus *bus ); + /** Close bus + * + * @v bus USB bus + */ + void ( * close ) ( struct usb_bus *bus ); + /** Poll bus + * + * @v bus USB bus + */ + void ( * poll ) ( struct usb_bus *bus ); +}; + +/** USB host controller operations */ +struct usb_host_operations { + /** Endpoint operations */ + struct usb_endpoint_host_operations endpoint; + /** Device operations */ + struct usb_device_host_operations device; + /** Bus operations */ + struct usb_bus_host_operations bus; + /** Hub operations */ + struct usb_hub_host_operations hub; + /** Root hub operations */ + struct usb_hub_driver_operations root; +}; + +/** + * Set USB bus host controller private data + * + * @v bus USB bus + * @v priv Host controller private data + */ +static inline __attribute__ (( always_inline )) void +usb_bus_set_hostdata ( struct usb_bus *bus, void *priv ) { + bus->priv = priv; +} + +/** + * Get USB bus host controller private data + * + * @v bus USB bus + * @ret priv Host controller private data + */ +static inline __attribute__ (( always_inline )) void * +usb_bus_get_hostdata ( struct usb_bus *bus ) { + return bus->priv; +} + +/** + * Poll USB bus + * + * @v bus USB bus + */ +static inline __attribute__ (( always_inline )) void +usb_poll ( struct usb_bus *bus ) { + bus->host->poll ( bus ); +} + +/** Iterate over all USB buses */ +#define for_each_usb_bus( bus ) \ + list_for_each_entry ( (bus), &usb_buses, list ) + +/** + * Complete transfer (without error) + * + * @v ep USB endpoint + * @v iobuf I/O buffer + */ +static inline __attribute__ (( always_inline )) void +usb_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf ) { + usb_complete_err ( ep, iobuf, 0 ); +} + +extern int usb_control ( struct usb_device *usb, unsigned int request, + unsigned int value, unsigned int index, void *data, + size_t len ); +extern int usb_get_string_descriptor ( struct usb_device *usb, + unsigned int index, + unsigned int language, + char *buf, size_t len ); + +/** + * Get status + * + * @v usb USB device + * @v type Request type + * @v index Target index + * @v data Status to fill in + * @v len Length of status descriptor + * @ret rc Return status code + */ +static inline __attribute__ (( always_inline )) int +usb_get_status ( struct usb_device *usb, unsigned int type, unsigned int index, + void *data, size_t len ) { + + return usb_control ( usb, ( USB_GET_STATUS | type ), 0, index, + data, len ); +} + +/** + * Clear feature + * + * @v usb USB device + * @v type Request type + * @v feature Feature selector + * @v index Target index + * @ret rc Return status code + */ +static inline __attribute__ (( always_inline )) int +usb_clear_feature ( struct usb_device *usb, unsigned int type, + unsigned int feature, unsigned int index ) { + + return usb_control ( usb, ( USB_CLEAR_FEATURE | type ), + feature, index, NULL, 0 ); +} + +/** + * Set feature + * + * @v usb USB device + * @v type Request type + * @v feature Feature selector + * @v index Target index + * @ret rc Return status code + */ +static inline __attribute__ (( always_inline )) int +usb_set_feature ( struct usb_device *usb, unsigned int type, + unsigned int feature, unsigned int index ) { + + return usb_control ( usb, ( USB_SET_FEATURE | type ), + feature, index, NULL, 0 ); +} + +/** + * Set address + * + * @v usb USB device + * @v address Device address + * @ret rc Return status code + */ +static inline __attribute__ (( always_inline )) int +usb_set_address ( struct usb_device *usb, unsigned int address ) { + + return usb_control ( usb, USB_SET_ADDRESS, address, 0, NULL, 0 ); +} + +/** + * Get USB descriptor + * + * @v usb USB device + * @v type Request type + * @v desc Descriptor type + * @v index Descriptor index + * @v language Language ID (for string descriptors) + * @v data Descriptor to fill in + * @v len Maximum length of descriptor + * @ret rc Return status code + */ +static inline __attribute__ (( always_inline )) int +usb_get_descriptor ( struct usb_device *usb, unsigned int type, + unsigned int desc, unsigned int index, + unsigned int language, struct usb_descriptor_header *data, + size_t len ) { + + return usb_control ( usb, ( USB_GET_DESCRIPTOR | type ), + ( ( desc << 8 ) | index ), language, data, len ); +} + +/** + * Get first part of USB device descriptor (up to and including MTU) + * + * @v usb USB device + * @v data Device descriptor to (partially) fill in + * @ret rc Return status code + */ +static inline __attribute__ (( always_inline )) int +usb_get_mtu ( struct usb_device *usb, struct usb_device_descriptor *data ) { + + return usb_get_descriptor ( usb, 0, USB_DEVICE_DESCRIPTOR, 0, 0, + &data->header, + ( offsetof ( typeof ( *data ), mtu ) + + sizeof ( data->mtu ) ) ); +} + +/** + * Get USB device descriptor + * + * @v usb USB device + * @v data Device descriptor to fill in + * @ret rc Return status code + */ +static inline __attribute__ (( always_inline )) int +usb_get_device_descriptor ( struct usb_device *usb, + struct usb_device_descriptor *data ) { + + return usb_get_descriptor ( usb, 0, USB_DEVICE_DESCRIPTOR, 0, 0, + &data->header, sizeof ( *data ) ); +} + +/** + * Get USB configuration descriptor + * + * @v usb USB device + * @v index Configuration index + * @v data Configuration descriptor to fill in + * @ret rc Return status code + */ +static inline __attribute (( always_inline )) int +usb_get_config_descriptor ( struct usb_device *usb, unsigned int index, + struct usb_configuration_descriptor *data, + size_t len ) { + + return usb_get_descriptor ( usb, 0, USB_CONFIGURATION_DESCRIPTOR, index, + 0, &data->header, len ); +} + +/** + * Set USB configuration + * + * @v usb USB device + * @v index Configuration index + * @ret rc Return status code + */ +static inline __attribute__ (( always_inline )) int +usb_set_configuration ( struct usb_device *usb, unsigned int index ) { + + return usb_control ( usb, USB_SET_CONFIGURATION, index, 0, NULL, 0 ); +} + +/** + * Set USB interface alternate setting + * + * @v usb USB device + * @v interface Interface number + * @v alternate Alternate setting + * @ret rc Return status code + */ +static inline __attribute__ (( always_inline )) int +usb_set_interface ( struct usb_device *usb, unsigned int interface, + unsigned int alternate ) { + + return usb_control ( usb, USB_SET_INTERFACE, alternate, interface, + NULL, 0 ); +} + +extern struct list_head usb_buses; + +extern struct usb_interface_descriptor * +usb_interface_descriptor ( struct usb_configuration_descriptor *config, + unsigned int interface, unsigned int alternate ); +extern struct usb_endpoint_descriptor * +usb_endpoint_descriptor ( struct usb_configuration_descriptor *config, + struct usb_interface_descriptor *interface, + unsigned int type, unsigned int index ); +extern struct usb_endpoint_companion_descriptor * +usb_endpoint_companion_descriptor ( struct usb_configuration_descriptor *config, + struct usb_endpoint_descriptor *desc ); + +extern struct usb_hub * alloc_usb_hub ( struct usb_bus *bus, + struct usb_device *usb, + unsigned int ports, + struct usb_hub_driver_operations *op ); +extern int register_usb_hub ( struct usb_hub *hub ); +extern void unregister_usb_hub ( struct usb_hub *hub ); +extern void free_usb_hub ( struct usb_hub *hub ); + +extern void usb_port_changed ( struct usb_port *port ); + +extern struct usb_bus * alloc_usb_bus ( struct device *dev, + unsigned int ports, size_t mtu, + struct usb_host_operations *op ); +extern int register_usb_bus ( struct usb_bus *bus ); +extern void unregister_usb_bus ( struct usb_bus *bus ); +extern void free_usb_bus ( struct usb_bus *bus ); +extern struct usb_bus * find_usb_bus_by_location ( unsigned int bus_type, + unsigned int location ); + +extern int usb_alloc_address ( struct usb_bus *bus ); +extern void usb_free_address ( struct usb_bus *bus, unsigned int address ); +extern unsigned int usb_route_string ( struct usb_device *usb ); +extern unsigned int usb_depth ( struct usb_device *usb ); +extern struct usb_port * usb_root_hub_port ( struct usb_device *usb ); +extern struct usb_port * usb_transaction_translator ( struct usb_device *usb ); + +/** Minimum reset time + * + * Section 7.1.7.5 of the USB2 specification states that root hub + * ports should assert reset signalling for at least 50ms. + */ +#define USB_RESET_DELAY_MS 50 + +/** Reset recovery time + * + * Section 9.2.6.2 of the USB2 specification states that the + * "recovery" interval after a port reset is 10ms. + */ +#define USB_RESET_RECOVER_DELAY_MS 10 + +/** Maximum time to wait for a control transaction to complete + * + * Section 9.2.6.1 of the USB2 specification states that the upper + * limit for commands to be processed is 5 seconds. + */ +#define USB_CONTROL_MAX_WAIT_MS 5000 + +/** Set address recovery time + * + * Section 9.2.6.3 of the USB2 specification states that devices are + * allowed a 2ms recovery interval after receiving a new address. + */ +#define USB_SET_ADDRESS_RECOVER_DELAY_MS 2 + +/** Time to wait for ports to stabilise + * + * Section 7.1.7.3 of the USB specification states that we must allow + * 100ms for devices to signal attachment, and an additional 100ms for + * connection debouncing. (This delay is parallelised across all + * ports on a hub; we do not delay separately for each port.) + */ +#define USB_PORT_DELAY_MS 200 + +/** A USB device ID */ +struct usb_device_id { + /** Name */ + const char *name; + /** Vendor ID */ + uint16_t vendor; + /** Product ID */ + uint16_t product; + /** Class */ + struct usb_class class; +}; + +/** Match-anything ID */ +#define USB_ANY_ID 0xffff + +/** A USB driver */ +struct usb_driver { + /** USB ID table */ + struct usb_device_id *ids; + /** Number of entries in ID table */ + unsigned int id_count; + /** + * Probe device + * + * @v func USB function + * @v config Configuration descriptor + * @ret rc Return status code + */ + int ( * probe ) ( struct usb_function *func, + struct usb_configuration_descriptor *config ); + /** + * Remove device + * + * @v func USB function + */ + void ( * remove ) ( struct usb_function *func ); +}; + +/** USB driver table */ +#define USB_DRIVERS __table ( struct usb_driver, "usb_drivers" ) + +/** Declare a USB driver */ +#define __usb_driver __table_entry ( USB_DRIVERS, 01 ) + +#endif /* _IPXE_USB_H */ -- cgit 1.2.3-korg