From 0bf96f9457cdaf620bb8195a971bbdcc732ba32b Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 30 Oct 2012 12:20:06 +0100 Subject: usb/ehci: split into multiple source files Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 426 +----------------------------------------------------- 1 file changed, 3 insertions(+), 423 deletions(-) (limited to 'hw/usb/hcd-ehci.c') diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index d3168c9..d9dc576 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -27,31 +27,11 @@ * along with this program; if not, see . */ -#include "hw/hw.h" -#include "qemu-timer.h" -#include "hw/usb.h" -#include "hw/pci.h" -#include "monitor.h" -#include "trace.h" -#include "dma.h" -#include "sysemu.h" - -#ifndef EHCI_DEBUG -#define EHCI_DEBUG 0 -#endif - -#if EHCI_DEBUG -#define DPRINTF printf -#else -#define DPRINTF(...) -#endif +#include "hw/usb/hcd-ehci.h" /* internal processing - reset HC to try and recover */ #define USB_RET_PROCERR (-99) -#define MMIO_SIZE 0x1000 -#define CAPA_SIZE 0x10 - /* Capability Registers Base Address - section 2.2 */ #define CAPLENGTH 0x0000 /* 1-byte, 0x0001 reserved */ #define HCIVERSION 0x0002 /* 2-bytes, i/f version # */ @@ -103,9 +83,6 @@ #define CONFIGFLAG 0x0040 -#define PORTSC 0x0044 -#define PORTSC_BEGIN PORTSC -#define PORTSC_END (PORTSC + 4 * NB_PORTS) /* * Bits that are reserved or are read-only are masked out of values * written to us by software @@ -137,7 +114,6 @@ #define FRAME_TIMER_NS (1000000000 / FRAME_TIMER_FREQ) #define NB_MAXINTRATE 8 // Max rate at which controller issues ints -#define NB_PORTS 6 // Number of downstream ports #define BUFF_SIZE 5*4096 // Max bytes to transfer per transaction #define MAX_QH 100 // Max allowable queue heads in a chain #define MIN_FR_PER_TICK 3 // Min frames to process when catching up @@ -174,285 +150,6 @@ typedef enum { #define NLPTR_TYPE_STITD 2 // split xaction, isoc xfer descriptor #define NLPTR_TYPE_FSTN 3 // frame span traversal node - -/* EHCI spec version 1.0 Section 3.3 - */ -typedef struct EHCIitd { - uint32_t next; - - uint32_t transact[8]; -#define ITD_XACT_ACTIVE (1 << 31) -#define ITD_XACT_DBERROR (1 << 30) -#define ITD_XACT_BABBLE (1 << 29) -#define ITD_XACT_XACTERR (1 << 28) -#define ITD_XACT_LENGTH_MASK 0x0fff0000 -#define ITD_XACT_LENGTH_SH 16 -#define ITD_XACT_IOC (1 << 15) -#define ITD_XACT_PGSEL_MASK 0x00007000 -#define ITD_XACT_PGSEL_SH 12 -#define ITD_XACT_OFFSET_MASK 0x00000fff - - uint32_t bufptr[7]; -#define ITD_BUFPTR_MASK 0xfffff000 -#define ITD_BUFPTR_SH 12 -#define ITD_BUFPTR_EP_MASK 0x00000f00 -#define ITD_BUFPTR_EP_SH 8 -#define ITD_BUFPTR_DEVADDR_MASK 0x0000007f -#define ITD_BUFPTR_DEVADDR_SH 0 -#define ITD_BUFPTR_DIRECTION (1 << 11) -#define ITD_BUFPTR_MAXPKT_MASK 0x000007ff -#define ITD_BUFPTR_MAXPKT_SH 0 -#define ITD_BUFPTR_MULT_MASK 0x00000003 -#define ITD_BUFPTR_MULT_SH 0 -} EHCIitd; - -/* EHCI spec version 1.0 Section 3.4 - */ -typedef struct EHCIsitd { - uint32_t next; // Standard next link pointer - uint32_t epchar; -#define SITD_EPCHAR_IO (1 << 31) -#define SITD_EPCHAR_PORTNUM_MASK 0x7f000000 -#define SITD_EPCHAR_PORTNUM_SH 24 -#define SITD_EPCHAR_HUBADD_MASK 0x007f0000 -#define SITD_EPCHAR_HUBADDR_SH 16 -#define SITD_EPCHAR_EPNUM_MASK 0x00000f00 -#define SITD_EPCHAR_EPNUM_SH 8 -#define SITD_EPCHAR_DEVADDR_MASK 0x0000007f - - uint32_t uframe; -#define SITD_UFRAME_CMASK_MASK 0x0000ff00 -#define SITD_UFRAME_CMASK_SH 8 -#define SITD_UFRAME_SMASK_MASK 0x000000ff - - uint32_t results; -#define SITD_RESULTS_IOC (1 << 31) -#define SITD_RESULTS_PGSEL (1 << 30) -#define SITD_RESULTS_TBYTES_MASK 0x03ff0000 -#define SITD_RESULTS_TYBYTES_SH 16 -#define SITD_RESULTS_CPROGMASK_MASK 0x0000ff00 -#define SITD_RESULTS_CPROGMASK_SH 8 -#define SITD_RESULTS_ACTIVE (1 << 7) -#define SITD_RESULTS_ERR (1 << 6) -#define SITD_RESULTS_DBERR (1 << 5) -#define SITD_RESULTS_BABBLE (1 << 4) -#define SITD_RESULTS_XACTERR (1 << 3) -#define SITD_RESULTS_MISSEDUF (1 << 2) -#define SITD_RESULTS_SPLITXSTATE (1 << 1) - - uint32_t bufptr[2]; -#define SITD_BUFPTR_MASK 0xfffff000 -#define SITD_BUFPTR_CURROFF_MASK 0x00000fff -#define SITD_BUFPTR_TPOS_MASK 0x00000018 -#define SITD_BUFPTR_TPOS_SH 3 -#define SITD_BUFPTR_TCNT_MASK 0x00000007 - - uint32_t backptr; // Standard next link pointer -} EHCIsitd; - -/* EHCI spec version 1.0 Section 3.5 - */ -typedef struct EHCIqtd { - uint32_t next; // Standard next link pointer - uint32_t altnext; // Standard next link pointer - uint32_t token; -#define QTD_TOKEN_DTOGGLE (1 << 31) -#define QTD_TOKEN_TBYTES_MASK 0x7fff0000 -#define QTD_TOKEN_TBYTES_SH 16 -#define QTD_TOKEN_IOC (1 << 15) -#define QTD_TOKEN_CPAGE_MASK 0x00007000 -#define QTD_TOKEN_CPAGE_SH 12 -#define QTD_TOKEN_CERR_MASK 0x00000c00 -#define QTD_TOKEN_CERR_SH 10 -#define QTD_TOKEN_PID_MASK 0x00000300 -#define QTD_TOKEN_PID_SH 8 -#define QTD_TOKEN_ACTIVE (1 << 7) -#define QTD_TOKEN_HALT (1 << 6) -#define QTD_TOKEN_DBERR (1 << 5) -#define QTD_TOKEN_BABBLE (1 << 4) -#define QTD_TOKEN_XACTERR (1 << 3) -#define QTD_TOKEN_MISSEDUF (1 << 2) -#define QTD_TOKEN_SPLITXSTATE (1 << 1) -#define QTD_TOKEN_PING (1 << 0) - - uint32_t bufptr[5]; // Standard buffer pointer -#define QTD_BUFPTR_MASK 0xfffff000 -#define QTD_BUFPTR_SH 12 -} EHCIqtd; - -/* EHCI spec version 1.0 Section 3.6 - */ -typedef struct EHCIqh { - uint32_t next; // Standard next link pointer - - /* endpoint characteristics */ - uint32_t epchar; -#define QH_EPCHAR_RL_MASK 0xf0000000 -#define QH_EPCHAR_RL_SH 28 -#define QH_EPCHAR_C (1 << 27) -#define QH_EPCHAR_MPLEN_MASK 0x07FF0000 -#define QH_EPCHAR_MPLEN_SH 16 -#define QH_EPCHAR_H (1 << 15) -#define QH_EPCHAR_DTC (1 << 14) -#define QH_EPCHAR_EPS_MASK 0x00003000 -#define QH_EPCHAR_EPS_SH 12 -#define EHCI_QH_EPS_FULL 0 -#define EHCI_QH_EPS_LOW 1 -#define EHCI_QH_EPS_HIGH 2 -#define EHCI_QH_EPS_RESERVED 3 - -#define QH_EPCHAR_EP_MASK 0x00000f00 -#define QH_EPCHAR_EP_SH 8 -#define QH_EPCHAR_I (1 << 7) -#define QH_EPCHAR_DEVADDR_MASK 0x0000007f -#define QH_EPCHAR_DEVADDR_SH 0 - - /* endpoint capabilities */ - uint32_t epcap; -#define QH_EPCAP_MULT_MASK 0xc0000000 -#define QH_EPCAP_MULT_SH 30 -#define QH_EPCAP_PORTNUM_MASK 0x3f800000 -#define QH_EPCAP_PORTNUM_SH 23 -#define QH_EPCAP_HUBADDR_MASK 0x007f0000 -#define QH_EPCAP_HUBADDR_SH 16 -#define QH_EPCAP_CMASK_MASK 0x0000ff00 -#define QH_EPCAP_CMASK_SH 8 -#define QH_EPCAP_SMASK_MASK 0x000000ff -#define QH_EPCAP_SMASK_SH 0 - - uint32_t current_qtd; // Standard next link pointer - uint32_t next_qtd; // Standard next link pointer - uint32_t altnext_qtd; -#define QH_ALTNEXT_NAKCNT_MASK 0x0000001e -#define QH_ALTNEXT_NAKCNT_SH 1 - - uint32_t token; // Same as QTD token - uint32_t bufptr[5]; // Standard buffer pointer -#define BUFPTR_CPROGMASK_MASK 0x000000ff -#define BUFPTR_FRAMETAG_MASK 0x0000001f -#define BUFPTR_SBYTES_MASK 0x00000fe0 -#define BUFPTR_SBYTES_SH 5 -} EHCIqh; - -/* EHCI spec version 1.0 Section 3.7 - */ -typedef struct EHCIfstn { - uint32_t next; // Standard next link pointer - uint32_t backptr; // Standard next link pointer -} EHCIfstn; - -typedef struct EHCIPacket EHCIPacket; -typedef struct EHCIQueue EHCIQueue; -typedef struct EHCIState EHCIState; - -enum async_state { - EHCI_ASYNC_NONE = 0, - EHCI_ASYNC_INITIALIZED, - EHCI_ASYNC_INFLIGHT, - EHCI_ASYNC_FINISHED, -}; - -struct EHCIPacket { - EHCIQueue *queue; - QTAILQ_ENTRY(EHCIPacket) next; - - EHCIqtd qtd; /* copy of current QTD (being worked on) */ - uint32_t qtdaddr; /* address QTD read from */ - - USBPacket packet; - QEMUSGList sgl; - int pid; - enum async_state async; - int usb_status; -}; - -struct EHCIQueue { - EHCIState *ehci; - QTAILQ_ENTRY(EHCIQueue) next; - uint32_t seen; - uint64_t ts; - int async; - int transact_ctr; - - /* cached data from guest - needs to be flushed - * when guest removes an entry (doorbell, handshake sequence) - */ - EHCIqh qh; /* copy of current QH (being worked on) */ - uint32_t qhaddr; /* address QH read from */ - uint32_t qtdaddr; /* address QTD read from */ - USBDevice *dev; - QTAILQ_HEAD(pkts_head, EHCIPacket) packets; -}; - -typedef QTAILQ_HEAD(EHCIQueueHead, EHCIQueue) EHCIQueueHead; - -struct EHCIState { - USBBus bus; - qemu_irq irq; - MemoryRegion mem; - DMAContext *dma; - MemoryRegion mem_caps; - MemoryRegion mem_opreg; - MemoryRegion mem_ports; - int companion_count; - uint16_t capsbase; - uint16_t opregbase; - - /* properties */ - uint32_t maxframes; - - /* - * EHCI spec version 1.0 Section 2.3 - * Host Controller Operational Registers - */ - uint8_t caps[CAPA_SIZE]; - union { - uint32_t opreg[PORTSC_BEGIN/sizeof(uint32_t)]; - struct { - uint32_t usbcmd; - uint32_t usbsts; - uint32_t usbintr; - uint32_t frindex; - uint32_t ctrldssegment; - uint32_t periodiclistbase; - uint32_t asynclistaddr; - uint32_t notused[9]; - uint32_t configflag; - }; - }; - uint32_t portsc[NB_PORTS]; - - /* - * Internal states, shadow registers, etc - */ - QEMUTimer *frame_timer; - QEMUBH *async_bh; - uint32_t astate; /* Current state in asynchronous schedule */ - uint32_t pstate; /* Current state in periodic schedule */ - USBPort ports[NB_PORTS]; - USBPort *companion_ports[NB_PORTS]; - uint32_t usbsts_pending; - uint32_t usbsts_frindex; - EHCIQueueHead aqueues; - EHCIQueueHead pqueues; - - /* which address to look at next */ - uint32_t a_fetch_addr; - uint32_t p_fetch_addr; - - USBPacket ipacket; - QEMUSGList isgl; - - uint64_t last_run_ns; - uint32_t async_stepdown; - bool int_req_by_async; -}; - -typedef struct EHCIPCIState { - PCIDevice pcidev; - EHCIState ehci; -} EHCIPCIState; - #define SET_LAST_RUN_CLOCK(s) \ (s)->last_run_ns = qemu_get_clock_ns(vm_clock); @@ -2559,8 +2256,6 @@ static const MemoryRegionOps ehci_mmio_port_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static int usb_ehci_pci_initfn(PCIDevice *dev); - static USBPortOps ehci_port_ops = { .attach = ehci_attach, .detach = ehci_detach, @@ -2619,7 +2314,7 @@ static void usb_ehci_vm_state_change(void *opaque, int running, RunState state) } } -static const VMStateDescription vmstate_ehci = { +const VMStateDescription vmstate_ehci = { .name = "ehci-core", .version_id = 2, .minimum_version_id = 1, @@ -2655,65 +2350,7 @@ static const VMStateDescription vmstate_ehci = { } }; -static const VMStateDescription vmstate_ehci_pci = { - .name = "ehci", - .version_id = 2, - .minimum_version_id = 1, - .post_load = usb_ehci_post_load, - .fields = (VMStateField[]) { - VMSTATE_PCI_DEVICE(pcidev, EHCIPCIState), - VMSTATE_STRUCT(ehci, EHCIPCIState, 2, vmstate_ehci, EHCIState), - } -}; - -static Property ehci_pci_properties[] = { - DEFINE_PROP_UINT32("maxframes", EHCIPCIState, ehci.maxframes, 128), - DEFINE_PROP_END_OF_LIST(), -}; - -static void ehci_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->init = usb_ehci_pci_initfn; - k->vendor_id = PCI_VENDOR_ID_INTEL; - k->device_id = PCI_DEVICE_ID_INTEL_82801D; /* ich4 */ - k->revision = 0x10; - k->class_id = PCI_CLASS_SERIAL_USB; - dc->vmsd = &vmstate_ehci; - dc->props = ehci_pci_properties; -} - -static TypeInfo ehci_info = { - .name = "usb-ehci", - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(EHCIState), - .class_init = ehci_class_init, -}; - -static void ich9_ehci_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->init = usb_ehci_pci_initfn; - k->vendor_id = PCI_VENDOR_ID_INTEL; - k->device_id = PCI_DEVICE_ID_INTEL_82801I_EHCI1; - k->revision = 0x03; - k->class_id = PCI_CLASS_SERIAL_USB; - dc->vmsd = &vmstate_ehci; - dc->props = ehci_pci_properties; -} - -static TypeInfo ich9_ehci_info = { - .name = "ich9-usb-ehci1", - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(EHCIState), - .class_init = ich9_ehci_class_init, -}; - -static void usb_ehci_initfn(EHCIState *s, DeviceState *dev) +void usb_ehci_initfn(EHCIState *s, DeviceState *dev) { int i; @@ -2760,63 +2397,6 @@ static void usb_ehci_initfn(EHCIState *s, DeviceState *dev) &s->mem_ports); } -static int usb_ehci_pci_initfn(PCIDevice *dev) -{ - EHCIPCIState *i = DO_UPCAST(EHCIPCIState, pcidev, dev); - EHCIState *s = &i->ehci; - uint8_t *pci_conf = dev->config; - - pci_set_byte(&pci_conf[PCI_CLASS_PROG], 0x20); - - /* capabilities pointer */ - pci_set_byte(&pci_conf[PCI_CAPABILITY_LIST], 0x00); - /* pci_set_byte(&pci_conf[PCI_CAPABILITY_LIST], 0x50); */ - - pci_set_byte(&pci_conf[PCI_INTERRUPT_PIN], 4); /* interrupt pin D */ - pci_set_byte(&pci_conf[PCI_MIN_GNT], 0); - pci_set_byte(&pci_conf[PCI_MAX_LAT], 0); - - /* pci_conf[0x50] = 0x01; *//* power management caps */ - - pci_set_byte(&pci_conf[USB_SBRN], USB_RELEASE_2); /* release # (2.1.4) */ - pci_set_byte(&pci_conf[0x61], 0x20); /* frame length adjustment (2.1.5) */ - pci_set_word(&pci_conf[0x62], 0x00); /* port wake up capability (2.1.6) */ - - pci_conf[0x64] = 0x00; - pci_conf[0x65] = 0x00; - pci_conf[0x66] = 0x00; - pci_conf[0x67] = 0x00; - pci_conf[0x68] = 0x01; - pci_conf[0x69] = 0x00; - pci_conf[0x6a] = 0x00; - pci_conf[0x6b] = 0x00; /* USBLEGSUP */ - pci_conf[0x6c] = 0x00; - pci_conf[0x6d] = 0x00; - pci_conf[0x6e] = 0x00; - pci_conf[0x6f] = 0xc0; /* USBLEFCTLSTS */ - - s->caps[0x09] = 0x68; /* EECP */ - - s->irq = dev->irq[3]; - s->dma = pci_dma_context(dev); - - s->capsbase = 0x00; - s->opregbase = 0x20; - - usb_ehci_initfn(s, DEVICE(dev)); - pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem); - - return 0; -} - -static void ehci_register_types(void) -{ - type_register_static(&ehci_info); - type_register_static(&ich9_ehci_info); -} - -type_init(ehci_register_types) - /* * vim: expandtab ts=4 */ -- cgit v1.1