123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350 |
- #ifndef _IPXE_UHCI_H
- #define _IPXE_UHCI_H
-
- /** @file
- *
- * USB Universal Host Controller Interface (UHCI) driver
- *
- */
-
- FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
- #include <assert.h>
- #include <ipxe/pci.h>
- #include <ipxe/usb.h>
-
- /** Minimum alignment required for data structures
- *
- * With the exception of the frame list (which is page-aligned), data
- * structures used by UHCI generally require 16-byte alignment.
- */
- #define UHCI_ALIGN 16
-
- /** Number of ports */
- #define UHCI_PORTS 2
-
- /** Maximum transfer size */
- #define UHCI_MTU 1280
-
- /** I/O BAR size */
- #define UHCI_BAR_SIZE 0x14
-
- /** USB command register */
- #define UHCI_USBCMD 0x00
-
- /** Max packet is 64 bytes */
- #define UHCI_USBCMD_MAX64 0x0080
-
- /** Host controller reset */
- #define UHCI_USBCMD_HCRESET 0x0002
-
- /** Run/stop */
- #define UHCI_USBCMD_RUN 0x0001
-
- /** USB status register */
- #define UHCI_USBSTS 0x02
-
- /** Host controller halted */
- #define UHCI_USBSTS_HCHALTED 0x0020
-
- /** USB interrupt */
- #define UHCI_USBSTS_USBINT 0x0001
-
- /** Frame list base address register */
- #define UHCI_FLBASEADD 0x08
-
- /** Port status and control register */
- #define UHCI_PORTSC(port) ( 0x0e + ( (port) << 1 ) )
-
- /** Port reset */
- #define UHCI_PORTSC_PR 0x0200
-
- /** Low-speed device attached */
- #define UHCI_PORTSC_LS 0x0100
-
- /** Port enabled/disabled change */
- #define UHCI_PORTSC_PEC 0x0008
-
- /** Port enabled */
- #define UHCI_PORTSC_PED 0x0004
-
- /** Connect status change */
- #define UHCI_PORTSC_CSC 0x0002
-
- /** Current connect status */
- #define UHCI_PORTSC_CCS 0x0001
-
- /** Port status change mask */
- #define UHCI_PORTSC_CHANGE ( UHCI_PORTSC_CSC | UHCI_PORTSC_PEC )
-
- /** Depth-first processing */
- #define UHCI_LINK_DEPTH_FIRST 0x00000004UL
-
- /** Queue head type */
- #define UHCI_LINK_TYPE_QH 0x00000002UL
-
- /** List terminator */
- #define UHCI_LINK_TERMINATE 0x00000001UL
-
- /** Number of frames in frame list */
- #define UHCI_FRAMES 1024
-
- /** A frame list */
- struct uhci_frame_list {
- /** Link pointer */
- uint32_t link[UHCI_FRAMES];
- } __attribute__ (( packed ));
-
- /** A transfer descriptor */
- struct uhci_transfer_descriptor {
- /** Link pointer */
- uint32_t link;
- /** Actual length */
- uint16_t actual;
- /** Status */
- uint8_t status;
- /** Flags */
- uint8_t flags;
- /** Control */
- uint32_t control;
- /** Buffer pointer */
- uint32_t data;
- } __attribute__ (( packed ));
-
- /** Length mask */
- #define UHCI_LEN_MASK 0x7ff
-
- /** Actual length */
- #define UHCI_ACTUAL_LEN( actual ) ( ( (actual) + 1 ) & UHCI_LEN_MASK )
-
- /** Active */
- #define UHCI_STATUS_ACTIVE 0x80
-
- /** Stalled */
- #define UHCI_STATUS_STALLED 0x40
-
- /** Data buffer error */
- #define UHCI_STATUS_BUFFER 0x20
-
- /** Babble detected */
- #define UHCI_STATUS_BABBLE 0x10
-
- /** NAK received */
- #define UHCI_STATUS_NAK 0x08
-
- /** CRC/timeout error */
- #define UHCI_STATUS_CRC_TIMEOUT 0x04
-
- /** Bitstuff error */
- #define UHCI_STATUS_BITSTUFF 0x02
-
- /** Short packet detect */
- #define UHCI_FL_SPD 0x20
-
- /** Error counter */
- #define UHCI_FL_CERR( count ) ( (count) << 3 )
-
- /** Error counter maximum value */
- #define UHCI_FL_CERR_MAX UHCI_FL_CERR ( 3 )
-
- /** Low speed device */
- #define UHCI_FL_LS 0x04
-
- /** Interrupt on completion */
- #define UHCI_FL_IOC 0x01
-
- /** Packet ID */
- #define UHCI_CONTROL_PID( pid ) ( (pid) << 0 )
-
- /** Packet ID mask */
- #define UHCI_CONTROL_PID_MASK UHCI_CONTROL_PID ( 0xff )
-
- /** Device address */
- #define UHCI_CONTROL_DEVICE( address ) ( (address) << 8 )
-
- /** Endpoint address */
- #define UHCI_CONTROL_ENDPOINT( address ) ( (address) << 15 )
-
- /** Data toggle */
- #define UHCI_CONTROL_TOGGLE ( 1 << 19 )
-
- /** Data length */
- #define UHCI_CONTROL_LEN( len ) ( ( ( (len) - 1 ) & UHCI_LEN_MASK ) << 21 )
-
- /** Check for data packet
- *
- * This check is based on the fact that only USB_PID_SETUP has bit 2
- * set.
- */
- #define UHCI_DATA_PACKET( control ) ( ! ( control & 0x04 ) )
-
- /** Check for short packet */
- #define UHCI_SHORT_PACKET( control, actual ) \
- ( ( ( (control) >> 21 ) ^ (actual) ) & UHCI_LEN_MASK )
-
- /** USB legacy support register (in PCI configuration space) */
- #define UHCI_USBLEGSUP 0xc0
-
- /** USB legacy support default value */
- #define UHCI_USBLEGSUP_DEFAULT 0x2000
-
- /** A queue head */
- struct uhci_queue_head {
- /** Horizontal link pointer */
- uint32_t link;
- /** Current transfer descriptor */
- uint32_t current;
- } __attribute__ (( packed ));
-
- /** A single UHCI transfer
- *
- * UHCI hardware is extremely simple, and requires software to build
- * the entire packet schedule (including manually handling all of the
- * data toggles). The hardware requires at least 16 bytes of transfer
- * descriptors per 64 bytes of transmitted/received data. We allocate
- * the transfer descriptors at the time that the transfer is enqueued,
- * to avoid the need to allocate unreasonably large blocks when the
- * endpoint is opened.
- */
- struct uhci_transfer {
- /** Producer counter */
- unsigned int prod;
- /** Consumer counter */
- unsigned int cons;
- /** Completed data length */
- size_t len;
-
- /** Transfer descriptors */
- struct uhci_transfer_descriptor *desc;
-
- /** I/O buffer */
- struct io_buffer *iobuf;
- };
-
- /** Number of transfer descriptors in a ring
- *
- * This is a policy decision.
- */
- #define UHCI_RING_COUNT 16
-
- /** A transfer ring */
- struct uhci_ring {
- /** Producer counter */
- unsigned int prod;
- /** Consumer counter */
- unsigned int cons;
-
- /** Maximum packet length */
- size_t mtu;
- /** Base flags
- *
- * This incorporates the CERR and LS bits
- */
- uint8_t flags;
- /** Base control word
- *
- * This incorporates the device address, the endpoint address,
- * and the data toggle for the next descriptor to be enqueued.
- */
- uint32_t control;
-
- /** Transfers */
- struct uhci_transfer *xfer[UHCI_RING_COUNT];
- /** End of transfer ring (if non-empty) */
- struct uhci_transfer *end;
-
- /** Queue head */
- struct uhci_queue_head *head;
- };
-
- /**
- * Calculate space used in transfer ring
- *
- * @v ring Transfer ring
- * @ret fill Number of entries used
- */
- static inline __attribute__ (( always_inline )) unsigned int
- uhci_ring_fill ( struct uhci_ring *ring ) {
- unsigned int fill;
-
- fill = ( ring->prod - ring->cons );
- assert ( fill <= UHCI_RING_COUNT );
- return fill;
- }
-
- /**
- * Calculate space remaining in transfer ring
- *
- * @v ring Transfer ring
- * @ret remaining Number of entries remaining
- */
- static inline __attribute__ (( always_inline )) unsigned int
- uhci_ring_remaining ( struct uhci_ring *ring ) {
- unsigned int fill = uhci_ring_fill ( ring );
-
- return ( UHCI_RING_COUNT - fill );
- }
-
- /** Maximum time to wait for host controller to stop
- *
- * This is a policy decision.
- */
- #define UHCI_STOP_MAX_WAIT_MS 100
-
- /** Maximum time to wait for reset to complete
- *
- * This is a policy decision.
- */
- #define UHCI_RESET_MAX_WAIT_MS 500
-
- /** Maximum time to wait for a port to be enabled
- *
- * This is a policy decision.
- */
- #define UHCI_PORT_ENABLE_MAX_WAIT_MS 500
-
- /** A UHCI device */
- struct uhci_device {
- /** Registers */
- unsigned long regs;
- /** Name */
- const char *name;
-
- /** EHCI companion controller bus:dev.fn address (if any) */
- unsigned int companion;
-
- /** Asynchronous queue head */
- struct uhci_queue_head *head;
- /** Frame list */
- struct uhci_frame_list *frame;
-
- /** List of all endpoints */
- struct list_head endpoints;
- /** Asynchronous schedule */
- struct list_head async;
- /** Periodic schedule
- *
- * Listed in decreasing order of endpoint interval.
- */
- struct list_head periodic;
-
- /** USB bus */
- struct usb_bus *bus;
- };
-
- /** A UHCI endpoint */
- struct uhci_endpoint {
- /** UHCI device */
- struct uhci_device *uhci;
- /** USB endpoint */
- struct usb_endpoint *ep;
- /** List of all endpoints */
- struct list_head list;
- /** Endpoint schedule */
- struct list_head schedule;
-
- /** Transfer ring */
- struct uhci_ring ring;
- };
-
- #endif /* _IPXE_UHCI_H */
|