1f1ae32a1SGerd Hoffmann /* 2f1ae32a1SGerd Hoffmann * QEMU USB OHCI Emulation 3f1ae32a1SGerd Hoffmann * Copyright (c) 2004 Gianni Tedesco 4f1ae32a1SGerd Hoffmann * Copyright (c) 2006 CodeSourcery 5f1ae32a1SGerd Hoffmann * Copyright (c) 2006 Openedhand Ltd. 6f1ae32a1SGerd Hoffmann * 7f1ae32a1SGerd Hoffmann * This library is free software; you can redistribute it and/or 8f1ae32a1SGerd Hoffmann * modify it under the terms of the GNU Lesser General Public 9f1ae32a1SGerd Hoffmann * License as published by the Free Software Foundation; either 10f1ae32a1SGerd Hoffmann * version 2 of the License, or (at your option) any later version. 11f1ae32a1SGerd Hoffmann * 12f1ae32a1SGerd Hoffmann * This library is distributed in the hope that it will be useful, 13f1ae32a1SGerd Hoffmann * but WITHOUT ANY WARRANTY; without even the implied warranty of 14f1ae32a1SGerd Hoffmann * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15f1ae32a1SGerd Hoffmann * Lesser General Public License for more details. 16f1ae32a1SGerd Hoffmann * 17f1ae32a1SGerd Hoffmann * You should have received a copy of the GNU Lesser General Public 18f1ae32a1SGerd Hoffmann * License along with this library; if not, see <http://www.gnu.org/licenses/>. 19f1ae32a1SGerd Hoffmann * 20f1ae32a1SGerd Hoffmann * TODO: 21f1ae32a1SGerd Hoffmann * o Isochronous transfers 22f1ae32a1SGerd Hoffmann * o Allocate bandwidth in frames properly 23f1ae32a1SGerd Hoffmann * o Disable timers when nothing needs to be done, or remove timer usage 24f1ae32a1SGerd Hoffmann * all together. 25f1ae32a1SGerd Hoffmann * o Handle unrecoverable errors properly 26f1ae32a1SGerd Hoffmann * o BIOS work to boot from USB storage 27f1ae32a1SGerd Hoffmann */ 28f1ae32a1SGerd Hoffmann 29f1ae32a1SGerd Hoffmann #include "hw/hw.h" 30f1ae32a1SGerd Hoffmann #include "qemu-timer.h" 31f1ae32a1SGerd Hoffmann #include "hw/usb.h" 32f1ae32a1SGerd Hoffmann #include "hw/pci.h" 33f1ae32a1SGerd Hoffmann #include "hw/sysbus.h" 349ac6a217SDavid Gibson #include "hw/qdev-dma.h" 35f1ae32a1SGerd Hoffmann 36f1ae32a1SGerd Hoffmann //#define DEBUG_OHCI 37f1ae32a1SGerd Hoffmann /* Dump packet contents. */ 38f1ae32a1SGerd Hoffmann //#define DEBUG_PACKET 39f1ae32a1SGerd Hoffmann //#define DEBUG_ISOCH 40f1ae32a1SGerd Hoffmann /* This causes frames to occur 1000x slower */ 41f1ae32a1SGerd Hoffmann //#define OHCI_TIME_WARP 1 42f1ae32a1SGerd Hoffmann 43f1ae32a1SGerd Hoffmann #ifdef DEBUG_OHCI 44f1ae32a1SGerd Hoffmann #define DPRINTF printf 45f1ae32a1SGerd Hoffmann #else 46f1ae32a1SGerd Hoffmann #define DPRINTF(...) 47f1ae32a1SGerd Hoffmann #endif 48f1ae32a1SGerd Hoffmann 49f1ae32a1SGerd Hoffmann /* Number of Downstream Ports on the root hub. */ 50f1ae32a1SGerd Hoffmann 51f1ae32a1SGerd Hoffmann #define OHCI_MAX_PORTS 15 52f1ae32a1SGerd Hoffmann 53f1ae32a1SGerd Hoffmann static int64_t usb_frame_time; 54f1ae32a1SGerd Hoffmann static int64_t usb_bit_time; 55f1ae32a1SGerd Hoffmann 56f1ae32a1SGerd Hoffmann typedef struct OHCIPort { 57f1ae32a1SGerd Hoffmann USBPort port; 58f1ae32a1SGerd Hoffmann uint32_t ctrl; 59f1ae32a1SGerd Hoffmann } OHCIPort; 60f1ae32a1SGerd Hoffmann 61f1ae32a1SGerd Hoffmann typedef struct { 62f1ae32a1SGerd Hoffmann USBBus bus; 63f1ae32a1SGerd Hoffmann qemu_irq irq; 64f1ae32a1SGerd Hoffmann MemoryRegion mem; 659ac6a217SDavid Gibson DMAContext *dma; 66f1ae32a1SGerd Hoffmann int num_ports; 67f1ae32a1SGerd Hoffmann const char *name; 68f1ae32a1SGerd Hoffmann 69f1ae32a1SGerd Hoffmann QEMUTimer *eof_timer; 70f1ae32a1SGerd Hoffmann int64_t sof_time; 71f1ae32a1SGerd Hoffmann 72f1ae32a1SGerd Hoffmann /* OHCI state */ 73f1ae32a1SGerd Hoffmann /* Control partition */ 74f1ae32a1SGerd Hoffmann uint32_t ctl, status; 75f1ae32a1SGerd Hoffmann uint32_t intr_status; 76f1ae32a1SGerd Hoffmann uint32_t intr; 77f1ae32a1SGerd Hoffmann 78f1ae32a1SGerd Hoffmann /* memory pointer partition */ 79f1ae32a1SGerd Hoffmann uint32_t hcca; 80f1ae32a1SGerd Hoffmann uint32_t ctrl_head, ctrl_cur; 81f1ae32a1SGerd Hoffmann uint32_t bulk_head, bulk_cur; 82f1ae32a1SGerd Hoffmann uint32_t per_cur; 83f1ae32a1SGerd Hoffmann uint32_t done; 84f1ae32a1SGerd Hoffmann int done_count; 85f1ae32a1SGerd Hoffmann 86f1ae32a1SGerd Hoffmann /* Frame counter partition */ 87f1ae32a1SGerd Hoffmann uint32_t fsmps:15; 88f1ae32a1SGerd Hoffmann uint32_t fit:1; 89f1ae32a1SGerd Hoffmann uint32_t fi:14; 90f1ae32a1SGerd Hoffmann uint32_t frt:1; 91f1ae32a1SGerd Hoffmann uint16_t frame_number; 92f1ae32a1SGerd Hoffmann uint16_t padding; 93f1ae32a1SGerd Hoffmann uint32_t pstart; 94f1ae32a1SGerd Hoffmann uint32_t lst; 95f1ae32a1SGerd Hoffmann 96f1ae32a1SGerd Hoffmann /* Root Hub partition */ 97f1ae32a1SGerd Hoffmann uint32_t rhdesc_a, rhdesc_b; 98f1ae32a1SGerd Hoffmann uint32_t rhstatus; 99f1ae32a1SGerd Hoffmann OHCIPort rhport[OHCI_MAX_PORTS]; 100f1ae32a1SGerd Hoffmann 101f1ae32a1SGerd Hoffmann /* PXA27x Non-OHCI events */ 102f1ae32a1SGerd Hoffmann uint32_t hstatus; 103f1ae32a1SGerd Hoffmann uint32_t hmask; 104f1ae32a1SGerd Hoffmann uint32_t hreset; 105f1ae32a1SGerd Hoffmann uint32_t htest; 106f1ae32a1SGerd Hoffmann 107f1ae32a1SGerd Hoffmann /* SM501 local memory offset */ 1089ac6a217SDavid Gibson dma_addr_t localmem_base; 109f1ae32a1SGerd Hoffmann 110f1ae32a1SGerd Hoffmann /* Active packets. */ 111f1ae32a1SGerd Hoffmann uint32_t old_ctl; 112f1ae32a1SGerd Hoffmann USBPacket usb_packet; 113f1ae32a1SGerd Hoffmann uint8_t usb_buf[8192]; 114f1ae32a1SGerd Hoffmann uint32_t async_td; 115f1ae32a1SGerd Hoffmann int async_complete; 116f1ae32a1SGerd Hoffmann 117f1ae32a1SGerd Hoffmann } OHCIState; 118f1ae32a1SGerd Hoffmann 119f1ae32a1SGerd Hoffmann /* Host Controller Communications Area */ 120f1ae32a1SGerd Hoffmann struct ohci_hcca { 121f1ae32a1SGerd Hoffmann uint32_t intr[32]; 122f1ae32a1SGerd Hoffmann uint16_t frame, pad; 123f1ae32a1SGerd Hoffmann uint32_t done; 124f1ae32a1SGerd Hoffmann }; 12586e18caeSWei Yang #define HCCA_WRITEBACK_OFFSET offsetof(struct ohci_hcca, frame) 12686e18caeSWei Yang #define HCCA_WRITEBACK_SIZE 8 /* frame, pad, done */ 12786e18caeSWei Yang 12886e18caeSWei Yang #define ED_WBACK_OFFSET offsetof(struct ohci_ed, head) 12986e18caeSWei Yang #define ED_WBACK_SIZE 4 130f1ae32a1SGerd Hoffmann 131f1ae32a1SGerd Hoffmann static void ohci_bus_stop(OHCIState *ohci); 132f1ae32a1SGerd Hoffmann static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev); 133f1ae32a1SGerd Hoffmann 134f1ae32a1SGerd Hoffmann /* Bitfields for the first word of an Endpoint Desciptor. */ 135f1ae32a1SGerd Hoffmann #define OHCI_ED_FA_SHIFT 0 136f1ae32a1SGerd Hoffmann #define OHCI_ED_FA_MASK (0x7f<<OHCI_ED_FA_SHIFT) 137f1ae32a1SGerd Hoffmann #define OHCI_ED_EN_SHIFT 7 138f1ae32a1SGerd Hoffmann #define OHCI_ED_EN_MASK (0xf<<OHCI_ED_EN_SHIFT) 139f1ae32a1SGerd Hoffmann #define OHCI_ED_D_SHIFT 11 140f1ae32a1SGerd Hoffmann #define OHCI_ED_D_MASK (3<<OHCI_ED_D_SHIFT) 141f1ae32a1SGerd Hoffmann #define OHCI_ED_S (1<<13) 142f1ae32a1SGerd Hoffmann #define OHCI_ED_K (1<<14) 143f1ae32a1SGerd Hoffmann #define OHCI_ED_F (1<<15) 144f1ae32a1SGerd Hoffmann #define OHCI_ED_MPS_SHIFT 16 145f1ae32a1SGerd Hoffmann #define OHCI_ED_MPS_MASK (0x7ff<<OHCI_ED_MPS_SHIFT) 146f1ae32a1SGerd Hoffmann 147f1ae32a1SGerd Hoffmann /* Flags in the head field of an Endpoint Desciptor. */ 148f1ae32a1SGerd Hoffmann #define OHCI_ED_H 1 149f1ae32a1SGerd Hoffmann #define OHCI_ED_C 2 150f1ae32a1SGerd Hoffmann 151f1ae32a1SGerd Hoffmann /* Bitfields for the first word of a Transfer Desciptor. */ 152f1ae32a1SGerd Hoffmann #define OHCI_TD_R (1<<18) 153f1ae32a1SGerd Hoffmann #define OHCI_TD_DP_SHIFT 19 154f1ae32a1SGerd Hoffmann #define OHCI_TD_DP_MASK (3<<OHCI_TD_DP_SHIFT) 155f1ae32a1SGerd Hoffmann #define OHCI_TD_DI_SHIFT 21 156f1ae32a1SGerd Hoffmann #define OHCI_TD_DI_MASK (7<<OHCI_TD_DI_SHIFT) 157f1ae32a1SGerd Hoffmann #define OHCI_TD_T0 (1<<24) 158f1ae32a1SGerd Hoffmann #define OHCI_TD_T1 (1<<25) 159f1ae32a1SGerd Hoffmann #define OHCI_TD_EC_SHIFT 26 160f1ae32a1SGerd Hoffmann #define OHCI_TD_EC_MASK (3<<OHCI_TD_EC_SHIFT) 161f1ae32a1SGerd Hoffmann #define OHCI_TD_CC_SHIFT 28 162f1ae32a1SGerd Hoffmann #define OHCI_TD_CC_MASK (0xf<<OHCI_TD_CC_SHIFT) 163f1ae32a1SGerd Hoffmann 164f1ae32a1SGerd Hoffmann /* Bitfields for the first word of an Isochronous Transfer Desciptor. */ 165f1ae32a1SGerd Hoffmann /* CC & DI - same as in the General Transfer Desciptor */ 166f1ae32a1SGerd Hoffmann #define OHCI_TD_SF_SHIFT 0 167f1ae32a1SGerd Hoffmann #define OHCI_TD_SF_MASK (0xffff<<OHCI_TD_SF_SHIFT) 168f1ae32a1SGerd Hoffmann #define OHCI_TD_FC_SHIFT 24 169f1ae32a1SGerd Hoffmann #define OHCI_TD_FC_MASK (7<<OHCI_TD_FC_SHIFT) 170f1ae32a1SGerd Hoffmann 171f1ae32a1SGerd Hoffmann /* Isochronous Transfer Desciptor - Offset / PacketStatusWord */ 172f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_CC_SHIFT 12 173f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_CC_MASK (0xf<<OHCI_TD_PSW_CC_SHIFT) 174f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_SIZE_SHIFT 0 175f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_SIZE_MASK (0xfff<<OHCI_TD_PSW_SIZE_SHIFT) 176f1ae32a1SGerd Hoffmann 177f1ae32a1SGerd Hoffmann #define OHCI_PAGE_MASK 0xfffff000 178f1ae32a1SGerd Hoffmann #define OHCI_OFFSET_MASK 0xfff 179f1ae32a1SGerd Hoffmann 180f1ae32a1SGerd Hoffmann #define OHCI_DPTR_MASK 0xfffffff0 181f1ae32a1SGerd Hoffmann 182f1ae32a1SGerd Hoffmann #define OHCI_BM(val, field) \ 183f1ae32a1SGerd Hoffmann (((val) & OHCI_##field##_MASK) >> OHCI_##field##_SHIFT) 184f1ae32a1SGerd Hoffmann 185f1ae32a1SGerd Hoffmann #define OHCI_SET_BM(val, field, newval) do { \ 186f1ae32a1SGerd Hoffmann val &= ~OHCI_##field##_MASK; \ 187f1ae32a1SGerd Hoffmann val |= ((newval) << OHCI_##field##_SHIFT) & OHCI_##field##_MASK; \ 188f1ae32a1SGerd Hoffmann } while(0) 189f1ae32a1SGerd Hoffmann 190f1ae32a1SGerd Hoffmann /* endpoint descriptor */ 191f1ae32a1SGerd Hoffmann struct ohci_ed { 192f1ae32a1SGerd Hoffmann uint32_t flags; 193f1ae32a1SGerd Hoffmann uint32_t tail; 194f1ae32a1SGerd Hoffmann uint32_t head; 195f1ae32a1SGerd Hoffmann uint32_t next; 196f1ae32a1SGerd Hoffmann }; 197f1ae32a1SGerd Hoffmann 198f1ae32a1SGerd Hoffmann /* General transfer descriptor */ 199f1ae32a1SGerd Hoffmann struct ohci_td { 200f1ae32a1SGerd Hoffmann uint32_t flags; 201f1ae32a1SGerd Hoffmann uint32_t cbp; 202f1ae32a1SGerd Hoffmann uint32_t next; 203f1ae32a1SGerd Hoffmann uint32_t be; 204f1ae32a1SGerd Hoffmann }; 205f1ae32a1SGerd Hoffmann 206f1ae32a1SGerd Hoffmann /* Isochronous transfer descriptor */ 207f1ae32a1SGerd Hoffmann struct ohci_iso_td { 208f1ae32a1SGerd Hoffmann uint32_t flags; 209f1ae32a1SGerd Hoffmann uint32_t bp; 210f1ae32a1SGerd Hoffmann uint32_t next; 211f1ae32a1SGerd Hoffmann uint32_t be; 212f1ae32a1SGerd Hoffmann uint16_t offset[8]; 213f1ae32a1SGerd Hoffmann }; 214f1ae32a1SGerd Hoffmann 215f1ae32a1SGerd Hoffmann #define USB_HZ 12000000 216f1ae32a1SGerd Hoffmann 217f1ae32a1SGerd Hoffmann /* OHCI Local stuff */ 218f1ae32a1SGerd Hoffmann #define OHCI_CTL_CBSR ((1<<0)|(1<<1)) 219f1ae32a1SGerd Hoffmann #define OHCI_CTL_PLE (1<<2) 220f1ae32a1SGerd Hoffmann #define OHCI_CTL_IE (1<<3) 221f1ae32a1SGerd Hoffmann #define OHCI_CTL_CLE (1<<4) 222f1ae32a1SGerd Hoffmann #define OHCI_CTL_BLE (1<<5) 223f1ae32a1SGerd Hoffmann #define OHCI_CTL_HCFS ((1<<6)|(1<<7)) 224f1ae32a1SGerd Hoffmann #define OHCI_USB_RESET 0x00 225f1ae32a1SGerd Hoffmann #define OHCI_USB_RESUME 0x40 226f1ae32a1SGerd Hoffmann #define OHCI_USB_OPERATIONAL 0x80 227f1ae32a1SGerd Hoffmann #define OHCI_USB_SUSPEND 0xc0 228f1ae32a1SGerd Hoffmann #define OHCI_CTL_IR (1<<8) 229f1ae32a1SGerd Hoffmann #define OHCI_CTL_RWC (1<<9) 230f1ae32a1SGerd Hoffmann #define OHCI_CTL_RWE (1<<10) 231f1ae32a1SGerd Hoffmann 232f1ae32a1SGerd Hoffmann #define OHCI_STATUS_HCR (1<<0) 233f1ae32a1SGerd Hoffmann #define OHCI_STATUS_CLF (1<<1) 234f1ae32a1SGerd Hoffmann #define OHCI_STATUS_BLF (1<<2) 235f1ae32a1SGerd Hoffmann #define OHCI_STATUS_OCR (1<<3) 236f1ae32a1SGerd Hoffmann #define OHCI_STATUS_SOC ((1<<6)|(1<<7)) 237f1ae32a1SGerd Hoffmann 238f1ae32a1SGerd Hoffmann #define OHCI_INTR_SO (1<<0) /* Scheduling overrun */ 239f1ae32a1SGerd Hoffmann #define OHCI_INTR_WD (1<<1) /* HcDoneHead writeback */ 240f1ae32a1SGerd Hoffmann #define OHCI_INTR_SF (1<<2) /* Start of frame */ 241f1ae32a1SGerd Hoffmann #define OHCI_INTR_RD (1<<3) /* Resume detect */ 242f1ae32a1SGerd Hoffmann #define OHCI_INTR_UE (1<<4) /* Unrecoverable error */ 243f1ae32a1SGerd Hoffmann #define OHCI_INTR_FNO (1<<5) /* Frame number overflow */ 244f1ae32a1SGerd Hoffmann #define OHCI_INTR_RHSC (1<<6) /* Root hub status change */ 245f1ae32a1SGerd Hoffmann #define OHCI_INTR_OC (1<<30) /* Ownership change */ 246f1ae32a1SGerd Hoffmann #define OHCI_INTR_MIE (1<<31) /* Master Interrupt Enable */ 247f1ae32a1SGerd Hoffmann 248f1ae32a1SGerd Hoffmann #define OHCI_HCCA_SIZE 0x100 249f1ae32a1SGerd Hoffmann #define OHCI_HCCA_MASK 0xffffff00 250f1ae32a1SGerd Hoffmann 251f1ae32a1SGerd Hoffmann #define OHCI_EDPTR_MASK 0xfffffff0 252f1ae32a1SGerd Hoffmann 253f1ae32a1SGerd Hoffmann #define OHCI_FMI_FI 0x00003fff 254f1ae32a1SGerd Hoffmann #define OHCI_FMI_FSMPS 0xffff0000 255f1ae32a1SGerd Hoffmann #define OHCI_FMI_FIT 0x80000000 256f1ae32a1SGerd Hoffmann 257f1ae32a1SGerd Hoffmann #define OHCI_FR_RT (1<<31) 258f1ae32a1SGerd Hoffmann 259f1ae32a1SGerd Hoffmann #define OHCI_LS_THRESH 0x628 260f1ae32a1SGerd Hoffmann 261f1ae32a1SGerd Hoffmann #define OHCI_RHA_RW_MASK 0x00000000 /* Mask of supported features. */ 262f1ae32a1SGerd Hoffmann #define OHCI_RHA_PSM (1<<8) 263f1ae32a1SGerd Hoffmann #define OHCI_RHA_NPS (1<<9) 264f1ae32a1SGerd Hoffmann #define OHCI_RHA_DT (1<<10) 265f1ae32a1SGerd Hoffmann #define OHCI_RHA_OCPM (1<<11) 266f1ae32a1SGerd Hoffmann #define OHCI_RHA_NOCP (1<<12) 267f1ae32a1SGerd Hoffmann #define OHCI_RHA_POTPGT_MASK 0xff000000 268f1ae32a1SGerd Hoffmann 269f1ae32a1SGerd Hoffmann #define OHCI_RHS_LPS (1<<0) 270f1ae32a1SGerd Hoffmann #define OHCI_RHS_OCI (1<<1) 271f1ae32a1SGerd Hoffmann #define OHCI_RHS_DRWE (1<<15) 272f1ae32a1SGerd Hoffmann #define OHCI_RHS_LPSC (1<<16) 273f1ae32a1SGerd Hoffmann #define OHCI_RHS_OCIC (1<<17) 274f1ae32a1SGerd Hoffmann #define OHCI_RHS_CRWE (1<<31) 275f1ae32a1SGerd Hoffmann 276f1ae32a1SGerd Hoffmann #define OHCI_PORT_CCS (1<<0) 277f1ae32a1SGerd Hoffmann #define OHCI_PORT_PES (1<<1) 278f1ae32a1SGerd Hoffmann #define OHCI_PORT_PSS (1<<2) 279f1ae32a1SGerd Hoffmann #define OHCI_PORT_POCI (1<<3) 280f1ae32a1SGerd Hoffmann #define OHCI_PORT_PRS (1<<4) 281f1ae32a1SGerd Hoffmann #define OHCI_PORT_PPS (1<<8) 282f1ae32a1SGerd Hoffmann #define OHCI_PORT_LSDA (1<<9) 283f1ae32a1SGerd Hoffmann #define OHCI_PORT_CSC (1<<16) 284f1ae32a1SGerd Hoffmann #define OHCI_PORT_PESC (1<<17) 285f1ae32a1SGerd Hoffmann #define OHCI_PORT_PSSC (1<<18) 286f1ae32a1SGerd Hoffmann #define OHCI_PORT_OCIC (1<<19) 287f1ae32a1SGerd Hoffmann #define OHCI_PORT_PRSC (1<<20) 288f1ae32a1SGerd Hoffmann #define OHCI_PORT_WTC (OHCI_PORT_CSC|OHCI_PORT_PESC|OHCI_PORT_PSSC \ 289f1ae32a1SGerd Hoffmann |OHCI_PORT_OCIC|OHCI_PORT_PRSC) 290f1ae32a1SGerd Hoffmann 291f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_SETUP 0x0 292f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_OUT 0x1 293f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_IN 0x2 294f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_RESERVED 0x3 295f1ae32a1SGerd Hoffmann 296f1ae32a1SGerd Hoffmann #define OHCI_CC_NOERROR 0x0 297f1ae32a1SGerd Hoffmann #define OHCI_CC_CRC 0x1 298f1ae32a1SGerd Hoffmann #define OHCI_CC_BITSTUFFING 0x2 299f1ae32a1SGerd Hoffmann #define OHCI_CC_DATATOGGLEMISMATCH 0x3 300f1ae32a1SGerd Hoffmann #define OHCI_CC_STALL 0x4 301f1ae32a1SGerd Hoffmann #define OHCI_CC_DEVICENOTRESPONDING 0x5 302f1ae32a1SGerd Hoffmann #define OHCI_CC_PIDCHECKFAILURE 0x6 303f1ae32a1SGerd Hoffmann #define OHCI_CC_UNDEXPETEDPID 0x7 304f1ae32a1SGerd Hoffmann #define OHCI_CC_DATAOVERRUN 0x8 305f1ae32a1SGerd Hoffmann #define OHCI_CC_DATAUNDERRUN 0x9 306f1ae32a1SGerd Hoffmann #define OHCI_CC_BUFFEROVERRUN 0xc 307f1ae32a1SGerd Hoffmann #define OHCI_CC_BUFFERUNDERRUN 0xd 308f1ae32a1SGerd Hoffmann 309f1ae32a1SGerd Hoffmann #define OHCI_HRESET_FSBIR (1 << 0) 310f1ae32a1SGerd Hoffmann 311f1ae32a1SGerd Hoffmann /* Update IRQ levels */ 312f1ae32a1SGerd Hoffmann static inline void ohci_intr_update(OHCIState *ohci) 313f1ae32a1SGerd Hoffmann { 314f1ae32a1SGerd Hoffmann int level = 0; 315f1ae32a1SGerd Hoffmann 316f1ae32a1SGerd Hoffmann if ((ohci->intr & OHCI_INTR_MIE) && 317f1ae32a1SGerd Hoffmann (ohci->intr_status & ohci->intr)) 318f1ae32a1SGerd Hoffmann level = 1; 319f1ae32a1SGerd Hoffmann 320f1ae32a1SGerd Hoffmann qemu_set_irq(ohci->irq, level); 321f1ae32a1SGerd Hoffmann } 322f1ae32a1SGerd Hoffmann 323f1ae32a1SGerd Hoffmann /* Set an interrupt */ 324f1ae32a1SGerd Hoffmann static inline void ohci_set_interrupt(OHCIState *ohci, uint32_t intr) 325f1ae32a1SGerd Hoffmann { 326f1ae32a1SGerd Hoffmann ohci->intr_status |= intr; 327f1ae32a1SGerd Hoffmann ohci_intr_update(ohci); 328f1ae32a1SGerd Hoffmann } 329f1ae32a1SGerd Hoffmann 330f1ae32a1SGerd Hoffmann /* Attach or detach a device on a root hub port. */ 331f1ae32a1SGerd Hoffmann static void ohci_attach(USBPort *port1) 332f1ae32a1SGerd Hoffmann { 333f1ae32a1SGerd Hoffmann OHCIState *s = port1->opaque; 334f1ae32a1SGerd Hoffmann OHCIPort *port = &s->rhport[port1->index]; 335f1ae32a1SGerd Hoffmann uint32_t old_state = port->ctrl; 336f1ae32a1SGerd Hoffmann 337f1ae32a1SGerd Hoffmann /* set connect status */ 338f1ae32a1SGerd Hoffmann port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC; 339f1ae32a1SGerd Hoffmann 340f1ae32a1SGerd Hoffmann /* update speed */ 341f1ae32a1SGerd Hoffmann if (port->port.dev->speed == USB_SPEED_LOW) { 342f1ae32a1SGerd Hoffmann port->ctrl |= OHCI_PORT_LSDA; 343f1ae32a1SGerd Hoffmann } else { 344f1ae32a1SGerd Hoffmann port->ctrl &= ~OHCI_PORT_LSDA; 345f1ae32a1SGerd Hoffmann } 346f1ae32a1SGerd Hoffmann 347f1ae32a1SGerd Hoffmann /* notify of remote-wakeup */ 348f1ae32a1SGerd Hoffmann if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) { 349f1ae32a1SGerd Hoffmann ohci_set_interrupt(s, OHCI_INTR_RD); 350f1ae32a1SGerd Hoffmann } 351f1ae32a1SGerd Hoffmann 352f1ae32a1SGerd Hoffmann DPRINTF("usb-ohci: Attached port %d\n", port1->index); 353f1ae32a1SGerd Hoffmann 354f1ae32a1SGerd Hoffmann if (old_state != port->ctrl) { 355f1ae32a1SGerd Hoffmann ohci_set_interrupt(s, OHCI_INTR_RHSC); 356f1ae32a1SGerd Hoffmann } 357f1ae32a1SGerd Hoffmann } 358f1ae32a1SGerd Hoffmann 359f1ae32a1SGerd Hoffmann static void ohci_detach(USBPort *port1) 360f1ae32a1SGerd Hoffmann { 361f1ae32a1SGerd Hoffmann OHCIState *s = port1->opaque; 362f1ae32a1SGerd Hoffmann OHCIPort *port = &s->rhport[port1->index]; 363f1ae32a1SGerd Hoffmann uint32_t old_state = port->ctrl; 364f1ae32a1SGerd Hoffmann 365f1ae32a1SGerd Hoffmann ohci_async_cancel_device(s, port1->dev); 366f1ae32a1SGerd Hoffmann 367f1ae32a1SGerd Hoffmann /* set connect status */ 368f1ae32a1SGerd Hoffmann if (port->ctrl & OHCI_PORT_CCS) { 369f1ae32a1SGerd Hoffmann port->ctrl &= ~OHCI_PORT_CCS; 370f1ae32a1SGerd Hoffmann port->ctrl |= OHCI_PORT_CSC; 371f1ae32a1SGerd Hoffmann } 372f1ae32a1SGerd Hoffmann /* disable port */ 373f1ae32a1SGerd Hoffmann if (port->ctrl & OHCI_PORT_PES) { 374f1ae32a1SGerd Hoffmann port->ctrl &= ~OHCI_PORT_PES; 375f1ae32a1SGerd Hoffmann port->ctrl |= OHCI_PORT_PESC; 376f1ae32a1SGerd Hoffmann } 377f1ae32a1SGerd Hoffmann DPRINTF("usb-ohci: Detached port %d\n", port1->index); 378f1ae32a1SGerd Hoffmann 379f1ae32a1SGerd Hoffmann if (old_state != port->ctrl) { 380f1ae32a1SGerd Hoffmann ohci_set_interrupt(s, OHCI_INTR_RHSC); 381f1ae32a1SGerd Hoffmann } 382f1ae32a1SGerd Hoffmann } 383f1ae32a1SGerd Hoffmann 384f1ae32a1SGerd Hoffmann static void ohci_wakeup(USBPort *port1) 385f1ae32a1SGerd Hoffmann { 386f1ae32a1SGerd Hoffmann OHCIState *s = port1->opaque; 387f1ae32a1SGerd Hoffmann OHCIPort *port = &s->rhport[port1->index]; 388f1ae32a1SGerd Hoffmann uint32_t intr = 0; 389f1ae32a1SGerd Hoffmann if (port->ctrl & OHCI_PORT_PSS) { 390f1ae32a1SGerd Hoffmann DPRINTF("usb-ohci: port %d: wakeup\n", port1->index); 391f1ae32a1SGerd Hoffmann port->ctrl |= OHCI_PORT_PSSC; 392f1ae32a1SGerd Hoffmann port->ctrl &= ~OHCI_PORT_PSS; 393f1ae32a1SGerd Hoffmann intr = OHCI_INTR_RHSC; 394f1ae32a1SGerd Hoffmann } 395f1ae32a1SGerd Hoffmann /* Note that the controller can be suspended even if this port is not */ 396f1ae32a1SGerd Hoffmann if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) { 397f1ae32a1SGerd Hoffmann DPRINTF("usb-ohci: remote-wakeup: SUSPEND->RESUME\n"); 398f1ae32a1SGerd Hoffmann /* This is the one state transition the controller can do by itself */ 399f1ae32a1SGerd Hoffmann s->ctl &= ~OHCI_CTL_HCFS; 400f1ae32a1SGerd Hoffmann s->ctl |= OHCI_USB_RESUME; 401f1ae32a1SGerd Hoffmann /* In suspend mode only ResumeDetected is possible, not RHSC: 402f1ae32a1SGerd Hoffmann * see the OHCI spec 5.1.2.3. 403f1ae32a1SGerd Hoffmann */ 404f1ae32a1SGerd Hoffmann intr = OHCI_INTR_RD; 405f1ae32a1SGerd Hoffmann } 406f1ae32a1SGerd Hoffmann ohci_set_interrupt(s, intr); 407f1ae32a1SGerd Hoffmann } 408f1ae32a1SGerd Hoffmann 409f1ae32a1SGerd Hoffmann static void ohci_child_detach(USBPort *port1, USBDevice *child) 410f1ae32a1SGerd Hoffmann { 411f1ae32a1SGerd Hoffmann OHCIState *s = port1->opaque; 412f1ae32a1SGerd Hoffmann 413f1ae32a1SGerd Hoffmann ohci_async_cancel_device(s, child); 414f1ae32a1SGerd Hoffmann } 415f1ae32a1SGerd Hoffmann 416f1ae32a1SGerd Hoffmann static USBDevice *ohci_find_device(OHCIState *ohci, uint8_t addr) 417f1ae32a1SGerd Hoffmann { 418f1ae32a1SGerd Hoffmann USBDevice *dev; 419f1ae32a1SGerd Hoffmann int i; 420f1ae32a1SGerd Hoffmann 421f1ae32a1SGerd Hoffmann for (i = 0; i < ohci->num_ports; i++) { 422f1ae32a1SGerd Hoffmann if ((ohci->rhport[i].ctrl & OHCI_PORT_PES) == 0) { 423f1ae32a1SGerd Hoffmann continue; 424f1ae32a1SGerd Hoffmann } 425f1ae32a1SGerd Hoffmann dev = usb_find_device(&ohci->rhport[i].port, addr); 426f1ae32a1SGerd Hoffmann if (dev != NULL) { 427f1ae32a1SGerd Hoffmann return dev; 428f1ae32a1SGerd Hoffmann } 429f1ae32a1SGerd Hoffmann } 430f1ae32a1SGerd Hoffmann return NULL; 431f1ae32a1SGerd Hoffmann } 432f1ae32a1SGerd Hoffmann 433f1ae32a1SGerd Hoffmann /* Reset the controller */ 434f1ae32a1SGerd Hoffmann static void ohci_reset(void *opaque) 435f1ae32a1SGerd Hoffmann { 436f1ae32a1SGerd Hoffmann OHCIState *ohci = opaque; 437f1ae32a1SGerd Hoffmann OHCIPort *port; 438f1ae32a1SGerd Hoffmann int i; 439f1ae32a1SGerd Hoffmann 440f1ae32a1SGerd Hoffmann ohci_bus_stop(ohci); 441f1ae32a1SGerd Hoffmann ohci->ctl = 0; 442f1ae32a1SGerd Hoffmann ohci->old_ctl = 0; 443f1ae32a1SGerd Hoffmann ohci->status = 0; 444f1ae32a1SGerd Hoffmann ohci->intr_status = 0; 445f1ae32a1SGerd Hoffmann ohci->intr = OHCI_INTR_MIE; 446f1ae32a1SGerd Hoffmann 447f1ae32a1SGerd Hoffmann ohci->hcca = 0; 448f1ae32a1SGerd Hoffmann ohci->ctrl_head = ohci->ctrl_cur = 0; 449f1ae32a1SGerd Hoffmann ohci->bulk_head = ohci->bulk_cur = 0; 450f1ae32a1SGerd Hoffmann ohci->per_cur = 0; 451f1ae32a1SGerd Hoffmann ohci->done = 0; 452f1ae32a1SGerd Hoffmann ohci->done_count = 7; 453f1ae32a1SGerd Hoffmann 454f1ae32a1SGerd Hoffmann /* FSMPS is marked TBD in OCHI 1.0, what gives ffs? 455f1ae32a1SGerd Hoffmann * I took the value linux sets ... 456f1ae32a1SGerd Hoffmann */ 457f1ae32a1SGerd Hoffmann ohci->fsmps = 0x2778; 458f1ae32a1SGerd Hoffmann ohci->fi = 0x2edf; 459f1ae32a1SGerd Hoffmann ohci->fit = 0; 460f1ae32a1SGerd Hoffmann ohci->frt = 0; 461f1ae32a1SGerd Hoffmann ohci->frame_number = 0; 462f1ae32a1SGerd Hoffmann ohci->pstart = 0; 463f1ae32a1SGerd Hoffmann ohci->lst = OHCI_LS_THRESH; 464f1ae32a1SGerd Hoffmann 465f1ae32a1SGerd Hoffmann ohci->rhdesc_a = OHCI_RHA_NPS | ohci->num_ports; 466f1ae32a1SGerd Hoffmann ohci->rhdesc_b = 0x0; /* Impl. specific */ 467f1ae32a1SGerd Hoffmann ohci->rhstatus = 0; 468f1ae32a1SGerd Hoffmann 469f1ae32a1SGerd Hoffmann for (i = 0; i < ohci->num_ports; i++) 470f1ae32a1SGerd Hoffmann { 471f1ae32a1SGerd Hoffmann port = &ohci->rhport[i]; 472f1ae32a1SGerd Hoffmann port->ctrl = 0; 473f1ae32a1SGerd Hoffmann if (port->port.dev && port->port.dev->attached) { 474f1ae32a1SGerd Hoffmann usb_port_reset(&port->port); 475f1ae32a1SGerd Hoffmann } 476f1ae32a1SGerd Hoffmann } 477f1ae32a1SGerd Hoffmann if (ohci->async_td) { 478f1ae32a1SGerd Hoffmann usb_cancel_packet(&ohci->usb_packet); 479f1ae32a1SGerd Hoffmann ohci->async_td = 0; 480f1ae32a1SGerd Hoffmann } 481f1ae32a1SGerd Hoffmann DPRINTF("usb-ohci: Reset %s\n", ohci->name); 482f1ae32a1SGerd Hoffmann } 483f1ae32a1SGerd Hoffmann 484f1ae32a1SGerd Hoffmann /* Get an array of dwords from main memory */ 485f1ae32a1SGerd Hoffmann static inline int get_dwords(OHCIState *ohci, 4869ac6a217SDavid Gibson dma_addr_t addr, uint32_t *buf, int num) 487f1ae32a1SGerd Hoffmann { 488f1ae32a1SGerd Hoffmann int i; 489f1ae32a1SGerd Hoffmann 490f1ae32a1SGerd Hoffmann addr += ohci->localmem_base; 491f1ae32a1SGerd Hoffmann 492f1ae32a1SGerd Hoffmann for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { 4939ac6a217SDavid Gibson dma_memory_read(ohci->dma, addr, buf, sizeof(*buf)); 494f1ae32a1SGerd Hoffmann *buf = le32_to_cpu(*buf); 495f1ae32a1SGerd Hoffmann } 496f1ae32a1SGerd Hoffmann 497f1ae32a1SGerd Hoffmann return 1; 498f1ae32a1SGerd Hoffmann } 499f1ae32a1SGerd Hoffmann 500f1ae32a1SGerd Hoffmann /* Put an array of dwords in to main memory */ 501f1ae32a1SGerd Hoffmann static inline int put_dwords(OHCIState *ohci, 5029ac6a217SDavid Gibson dma_addr_t addr, uint32_t *buf, int num) 503f1ae32a1SGerd Hoffmann { 504f1ae32a1SGerd Hoffmann int i; 505f1ae32a1SGerd Hoffmann 506f1ae32a1SGerd Hoffmann addr += ohci->localmem_base; 507f1ae32a1SGerd Hoffmann 508f1ae32a1SGerd Hoffmann for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { 509f1ae32a1SGerd Hoffmann uint32_t tmp = cpu_to_le32(*buf); 5109ac6a217SDavid Gibson dma_memory_write(ohci->dma, addr, &tmp, sizeof(tmp)); 511f1ae32a1SGerd Hoffmann } 512f1ae32a1SGerd Hoffmann 513f1ae32a1SGerd Hoffmann return 1; 514f1ae32a1SGerd Hoffmann } 515f1ae32a1SGerd Hoffmann 516f1ae32a1SGerd Hoffmann /* Get an array of words from main memory */ 517f1ae32a1SGerd Hoffmann static inline int get_words(OHCIState *ohci, 5189ac6a217SDavid Gibson dma_addr_t addr, uint16_t *buf, int num) 519f1ae32a1SGerd Hoffmann { 520f1ae32a1SGerd Hoffmann int i; 521f1ae32a1SGerd Hoffmann 522f1ae32a1SGerd Hoffmann addr += ohci->localmem_base; 523f1ae32a1SGerd Hoffmann 524f1ae32a1SGerd Hoffmann for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { 5259ac6a217SDavid Gibson dma_memory_read(ohci->dma, addr, buf, sizeof(*buf)); 526f1ae32a1SGerd Hoffmann *buf = le16_to_cpu(*buf); 527f1ae32a1SGerd Hoffmann } 528f1ae32a1SGerd Hoffmann 529f1ae32a1SGerd Hoffmann return 1; 530f1ae32a1SGerd Hoffmann } 531f1ae32a1SGerd Hoffmann 532f1ae32a1SGerd Hoffmann /* Put an array of words in to main memory */ 533f1ae32a1SGerd Hoffmann static inline int put_words(OHCIState *ohci, 5349ac6a217SDavid Gibson dma_addr_t addr, uint16_t *buf, int num) 535f1ae32a1SGerd Hoffmann { 536f1ae32a1SGerd Hoffmann int i; 537f1ae32a1SGerd Hoffmann 538f1ae32a1SGerd Hoffmann addr += ohci->localmem_base; 539f1ae32a1SGerd Hoffmann 540f1ae32a1SGerd Hoffmann for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { 541f1ae32a1SGerd Hoffmann uint16_t tmp = cpu_to_le16(*buf); 5429ac6a217SDavid Gibson dma_memory_write(ohci->dma, addr, &tmp, sizeof(tmp)); 543f1ae32a1SGerd Hoffmann } 544f1ae32a1SGerd Hoffmann 545f1ae32a1SGerd Hoffmann return 1; 546f1ae32a1SGerd Hoffmann } 547f1ae32a1SGerd Hoffmann 548f1ae32a1SGerd Hoffmann static inline int ohci_read_ed(OHCIState *ohci, 5499ac6a217SDavid Gibson dma_addr_t addr, struct ohci_ed *ed) 550f1ae32a1SGerd Hoffmann { 551f1ae32a1SGerd Hoffmann return get_dwords(ohci, addr, (uint32_t *)ed, sizeof(*ed) >> 2); 552f1ae32a1SGerd Hoffmann } 553f1ae32a1SGerd Hoffmann 554f1ae32a1SGerd Hoffmann static inline int ohci_read_td(OHCIState *ohci, 5559ac6a217SDavid Gibson dma_addr_t addr, struct ohci_td *td) 556f1ae32a1SGerd Hoffmann { 557f1ae32a1SGerd Hoffmann return get_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2); 558f1ae32a1SGerd Hoffmann } 559f1ae32a1SGerd Hoffmann 560f1ae32a1SGerd Hoffmann static inline int ohci_read_iso_td(OHCIState *ohci, 5619ac6a217SDavid Gibson dma_addr_t addr, struct ohci_iso_td *td) 562f1ae32a1SGerd Hoffmann { 563f1ae32a1SGerd Hoffmann return (get_dwords(ohci, addr, (uint32_t *)td, 4) && 564f1ae32a1SGerd Hoffmann get_words(ohci, addr + 16, td->offset, 8)); 565f1ae32a1SGerd Hoffmann } 566f1ae32a1SGerd Hoffmann 567f1ae32a1SGerd Hoffmann static inline int ohci_read_hcca(OHCIState *ohci, 5689ac6a217SDavid Gibson dma_addr_t addr, struct ohci_hcca *hcca) 569f1ae32a1SGerd Hoffmann { 5709ac6a217SDavid Gibson dma_memory_read(ohci->dma, addr + ohci->localmem_base, hcca, sizeof(*hcca)); 571f1ae32a1SGerd Hoffmann return 1; 572f1ae32a1SGerd Hoffmann } 573f1ae32a1SGerd Hoffmann 574f1ae32a1SGerd Hoffmann static inline int ohci_put_ed(OHCIState *ohci, 5759ac6a217SDavid Gibson dma_addr_t addr, struct ohci_ed *ed) 576f1ae32a1SGerd Hoffmann { 57786e18caeSWei Yang /* ed->tail is under control of the HCD. 57886e18caeSWei Yang * Since just ed->head is changed by HC, just write back this 57986e18caeSWei Yang */ 58086e18caeSWei Yang 58186e18caeSWei Yang return put_dwords(ohci, addr + ED_WBACK_OFFSET, 58286e18caeSWei Yang (uint32_t *)((char *)ed + ED_WBACK_OFFSET), 58386e18caeSWei Yang ED_WBACK_SIZE >> 2); 584f1ae32a1SGerd Hoffmann } 585f1ae32a1SGerd Hoffmann 586f1ae32a1SGerd Hoffmann static inline int ohci_put_td(OHCIState *ohci, 5879ac6a217SDavid Gibson dma_addr_t addr, struct ohci_td *td) 588f1ae32a1SGerd Hoffmann { 589f1ae32a1SGerd Hoffmann return put_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2); 590f1ae32a1SGerd Hoffmann } 591f1ae32a1SGerd Hoffmann 592f1ae32a1SGerd Hoffmann static inline int ohci_put_iso_td(OHCIState *ohci, 5939ac6a217SDavid Gibson dma_addr_t addr, struct ohci_iso_td *td) 594f1ae32a1SGerd Hoffmann { 595f1ae32a1SGerd Hoffmann return (put_dwords(ohci, addr, (uint32_t *)td, 4) && 596f1ae32a1SGerd Hoffmann put_words(ohci, addr + 16, td->offset, 8)); 597f1ae32a1SGerd Hoffmann } 598f1ae32a1SGerd Hoffmann 599f1ae32a1SGerd Hoffmann static inline int ohci_put_hcca(OHCIState *ohci, 6009ac6a217SDavid Gibson dma_addr_t addr, struct ohci_hcca *hcca) 601f1ae32a1SGerd Hoffmann { 6029ac6a217SDavid Gibson dma_memory_write(ohci->dma, 6039ac6a217SDavid Gibson addr + ohci->localmem_base + HCCA_WRITEBACK_OFFSET, 60486e18caeSWei Yang (char *)hcca + HCCA_WRITEBACK_OFFSET, 60586e18caeSWei Yang HCCA_WRITEBACK_SIZE); 606f1ae32a1SGerd Hoffmann return 1; 607f1ae32a1SGerd Hoffmann } 608f1ae32a1SGerd Hoffmann 609f1ae32a1SGerd Hoffmann /* Read/Write the contents of a TD from/to main memory. */ 610f1ae32a1SGerd Hoffmann static void ohci_copy_td(OHCIState *ohci, struct ohci_td *td, 6119ac6a217SDavid Gibson uint8_t *buf, int len, DMADirection dir) 612f1ae32a1SGerd Hoffmann { 6139ac6a217SDavid Gibson dma_addr_t ptr, n; 614f1ae32a1SGerd Hoffmann 615f1ae32a1SGerd Hoffmann ptr = td->cbp; 616f1ae32a1SGerd Hoffmann n = 0x1000 - (ptr & 0xfff); 617f1ae32a1SGerd Hoffmann if (n > len) 618f1ae32a1SGerd Hoffmann n = len; 6199ac6a217SDavid Gibson dma_memory_rw(ohci->dma, ptr + ohci->localmem_base, buf, n, dir); 620f1ae32a1SGerd Hoffmann if (n == len) 621f1ae32a1SGerd Hoffmann return; 622f1ae32a1SGerd Hoffmann ptr = td->be & ~0xfffu; 623f1ae32a1SGerd Hoffmann buf += n; 6249ac6a217SDavid Gibson dma_memory_rw(ohci->dma, ptr + ohci->localmem_base, buf, len - n, dir); 625f1ae32a1SGerd Hoffmann } 626f1ae32a1SGerd Hoffmann 627f1ae32a1SGerd Hoffmann /* Read/Write the contents of an ISO TD from/to main memory. */ 628f1ae32a1SGerd Hoffmann static void ohci_copy_iso_td(OHCIState *ohci, 629f1ae32a1SGerd Hoffmann uint32_t start_addr, uint32_t end_addr, 6309ac6a217SDavid Gibson uint8_t *buf, int len, DMADirection dir) 631f1ae32a1SGerd Hoffmann { 6329ac6a217SDavid Gibson dma_addr_t ptr, n; 633f1ae32a1SGerd Hoffmann 634f1ae32a1SGerd Hoffmann ptr = start_addr; 635f1ae32a1SGerd Hoffmann n = 0x1000 - (ptr & 0xfff); 636f1ae32a1SGerd Hoffmann if (n > len) 637f1ae32a1SGerd Hoffmann n = len; 6389ac6a217SDavid Gibson dma_memory_rw(ohci->dma, ptr + ohci->localmem_base, buf, n, dir); 639f1ae32a1SGerd Hoffmann if (n == len) 640f1ae32a1SGerd Hoffmann return; 641f1ae32a1SGerd Hoffmann ptr = end_addr & ~0xfffu; 642f1ae32a1SGerd Hoffmann buf += n; 6439ac6a217SDavid Gibson dma_memory_rw(ohci->dma, ptr + ohci->localmem_base, buf, len - n, dir); 644f1ae32a1SGerd Hoffmann } 645f1ae32a1SGerd Hoffmann 646f1ae32a1SGerd Hoffmann static void ohci_process_lists(OHCIState *ohci, int completion); 647f1ae32a1SGerd Hoffmann 648f1ae32a1SGerd Hoffmann static void ohci_async_complete_packet(USBPort *port, USBPacket *packet) 649f1ae32a1SGerd Hoffmann { 650f1ae32a1SGerd Hoffmann OHCIState *ohci = container_of(packet, OHCIState, usb_packet); 651f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET 652f1ae32a1SGerd Hoffmann DPRINTF("Async packet complete\n"); 653f1ae32a1SGerd Hoffmann #endif 654f1ae32a1SGerd Hoffmann ohci->async_complete = 1; 655f1ae32a1SGerd Hoffmann ohci_process_lists(ohci, 1); 656f1ae32a1SGerd Hoffmann } 657f1ae32a1SGerd Hoffmann 658f1ae32a1SGerd Hoffmann #define USUB(a, b) ((int16_t)((uint16_t)(a) - (uint16_t)(b))) 659f1ae32a1SGerd Hoffmann 660f1ae32a1SGerd Hoffmann static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, 661f1ae32a1SGerd Hoffmann int completion) 662f1ae32a1SGerd Hoffmann { 663f1ae32a1SGerd Hoffmann int dir; 664f1ae32a1SGerd Hoffmann size_t len = 0; 665f1ae32a1SGerd Hoffmann #ifdef DEBUG_ISOCH 666f1ae32a1SGerd Hoffmann const char *str = NULL; 667f1ae32a1SGerd Hoffmann #endif 668f1ae32a1SGerd Hoffmann int pid; 669f1ae32a1SGerd Hoffmann int ret; 670f1ae32a1SGerd Hoffmann int i; 671f1ae32a1SGerd Hoffmann USBDevice *dev; 672f1ae32a1SGerd Hoffmann USBEndpoint *ep; 673f1ae32a1SGerd Hoffmann struct ohci_iso_td iso_td; 674f1ae32a1SGerd Hoffmann uint32_t addr; 675f1ae32a1SGerd Hoffmann uint16_t starting_frame; 676f1ae32a1SGerd Hoffmann int16_t relative_frame_number; 677f1ae32a1SGerd Hoffmann int frame_count; 678f1ae32a1SGerd Hoffmann uint32_t start_offset, next_offset, end_offset = 0; 679f1ae32a1SGerd Hoffmann uint32_t start_addr, end_addr; 680f1ae32a1SGerd Hoffmann 681f1ae32a1SGerd Hoffmann addr = ed->head & OHCI_DPTR_MASK; 682f1ae32a1SGerd Hoffmann 683f1ae32a1SGerd Hoffmann if (!ohci_read_iso_td(ohci, addr, &iso_td)) { 684f1ae32a1SGerd Hoffmann printf("usb-ohci: ISO_TD read error at %x\n", addr); 685f1ae32a1SGerd Hoffmann return 0; 686f1ae32a1SGerd Hoffmann } 687f1ae32a1SGerd Hoffmann 688f1ae32a1SGerd Hoffmann starting_frame = OHCI_BM(iso_td.flags, TD_SF); 689f1ae32a1SGerd Hoffmann frame_count = OHCI_BM(iso_td.flags, TD_FC); 690f1ae32a1SGerd Hoffmann relative_frame_number = USUB(ohci->frame_number, starting_frame); 691f1ae32a1SGerd Hoffmann 692f1ae32a1SGerd Hoffmann #ifdef DEBUG_ISOCH 693f1ae32a1SGerd Hoffmann printf("--- ISO_TD ED head 0x%.8x tailp 0x%.8x\n" 694f1ae32a1SGerd Hoffmann "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n" 695f1ae32a1SGerd Hoffmann "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n" 696f1ae32a1SGerd Hoffmann "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n" 697f1ae32a1SGerd Hoffmann "frame_number 0x%.8x starting_frame 0x%.8x\n" 698f1ae32a1SGerd Hoffmann "frame_count 0x%.8x relative %d\n" 699f1ae32a1SGerd Hoffmann "di 0x%.8x cc 0x%.8x\n", 700f1ae32a1SGerd Hoffmann ed->head & OHCI_DPTR_MASK, ed->tail & OHCI_DPTR_MASK, 701f1ae32a1SGerd Hoffmann iso_td.flags, iso_td.bp, iso_td.next, iso_td.be, 702f1ae32a1SGerd Hoffmann iso_td.offset[0], iso_td.offset[1], iso_td.offset[2], iso_td.offset[3], 703f1ae32a1SGerd Hoffmann iso_td.offset[4], iso_td.offset[5], iso_td.offset[6], iso_td.offset[7], 704f1ae32a1SGerd Hoffmann ohci->frame_number, starting_frame, 705f1ae32a1SGerd Hoffmann frame_count, relative_frame_number, 706f1ae32a1SGerd Hoffmann OHCI_BM(iso_td.flags, TD_DI), OHCI_BM(iso_td.flags, TD_CC)); 707f1ae32a1SGerd Hoffmann #endif 708f1ae32a1SGerd Hoffmann 709f1ae32a1SGerd Hoffmann if (relative_frame_number < 0) { 710f1ae32a1SGerd Hoffmann DPRINTF("usb-ohci: ISO_TD R=%d < 0\n", relative_frame_number); 711f1ae32a1SGerd Hoffmann return 1; 712f1ae32a1SGerd Hoffmann } else if (relative_frame_number > frame_count) { 713f1ae32a1SGerd Hoffmann /* ISO TD expired - retire the TD to the Done Queue and continue with 714f1ae32a1SGerd Hoffmann the next ISO TD of the same ED */ 715f1ae32a1SGerd Hoffmann DPRINTF("usb-ohci: ISO_TD R=%d > FC=%d\n", relative_frame_number, 716f1ae32a1SGerd Hoffmann frame_count); 717f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_DATAOVERRUN); 718f1ae32a1SGerd Hoffmann ed->head &= ~OHCI_DPTR_MASK; 719f1ae32a1SGerd Hoffmann ed->head |= (iso_td.next & OHCI_DPTR_MASK); 720f1ae32a1SGerd Hoffmann iso_td.next = ohci->done; 721f1ae32a1SGerd Hoffmann ohci->done = addr; 722f1ae32a1SGerd Hoffmann i = OHCI_BM(iso_td.flags, TD_DI); 723f1ae32a1SGerd Hoffmann if (i < ohci->done_count) 724f1ae32a1SGerd Hoffmann ohci->done_count = i; 725f1ae32a1SGerd Hoffmann ohci_put_iso_td(ohci, addr, &iso_td); 726f1ae32a1SGerd Hoffmann return 0; 727f1ae32a1SGerd Hoffmann } 728f1ae32a1SGerd Hoffmann 729f1ae32a1SGerd Hoffmann dir = OHCI_BM(ed->flags, ED_D); 730f1ae32a1SGerd Hoffmann switch (dir) { 731f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_IN: 732f1ae32a1SGerd Hoffmann #ifdef DEBUG_ISOCH 733f1ae32a1SGerd Hoffmann str = "in"; 734f1ae32a1SGerd Hoffmann #endif 735f1ae32a1SGerd Hoffmann pid = USB_TOKEN_IN; 736f1ae32a1SGerd Hoffmann break; 737f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_OUT: 738f1ae32a1SGerd Hoffmann #ifdef DEBUG_ISOCH 739f1ae32a1SGerd Hoffmann str = "out"; 740f1ae32a1SGerd Hoffmann #endif 741f1ae32a1SGerd Hoffmann pid = USB_TOKEN_OUT; 742f1ae32a1SGerd Hoffmann break; 743f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_SETUP: 744f1ae32a1SGerd Hoffmann #ifdef DEBUG_ISOCH 745f1ae32a1SGerd Hoffmann str = "setup"; 746f1ae32a1SGerd Hoffmann #endif 747f1ae32a1SGerd Hoffmann pid = USB_TOKEN_SETUP; 748f1ae32a1SGerd Hoffmann break; 749f1ae32a1SGerd Hoffmann default: 750f1ae32a1SGerd Hoffmann printf("usb-ohci: Bad direction %d\n", dir); 751f1ae32a1SGerd Hoffmann return 1; 752f1ae32a1SGerd Hoffmann } 753f1ae32a1SGerd Hoffmann 754f1ae32a1SGerd Hoffmann if (!iso_td.bp || !iso_td.be) { 755f1ae32a1SGerd Hoffmann printf("usb-ohci: ISO_TD bp 0x%.8x be 0x%.8x\n", iso_td.bp, iso_td.be); 756f1ae32a1SGerd Hoffmann return 1; 757f1ae32a1SGerd Hoffmann } 758f1ae32a1SGerd Hoffmann 759f1ae32a1SGerd Hoffmann start_offset = iso_td.offset[relative_frame_number]; 760f1ae32a1SGerd Hoffmann next_offset = iso_td.offset[relative_frame_number + 1]; 761f1ae32a1SGerd Hoffmann 762f1ae32a1SGerd Hoffmann if (!(OHCI_BM(start_offset, TD_PSW_CC) & 0xe) || 763f1ae32a1SGerd Hoffmann ((relative_frame_number < frame_count) && 764f1ae32a1SGerd Hoffmann !(OHCI_BM(next_offset, TD_PSW_CC) & 0xe))) { 765f1ae32a1SGerd Hoffmann printf("usb-ohci: ISO_TD cc != not accessed 0x%.8x 0x%.8x\n", 766f1ae32a1SGerd Hoffmann start_offset, next_offset); 767f1ae32a1SGerd Hoffmann return 1; 768f1ae32a1SGerd Hoffmann } 769f1ae32a1SGerd Hoffmann 770f1ae32a1SGerd Hoffmann if ((relative_frame_number < frame_count) && (start_offset > next_offset)) { 771f1ae32a1SGerd Hoffmann printf("usb-ohci: ISO_TD start_offset=0x%.8x > next_offset=0x%.8x\n", 772f1ae32a1SGerd Hoffmann start_offset, next_offset); 773f1ae32a1SGerd Hoffmann return 1; 774f1ae32a1SGerd Hoffmann } 775f1ae32a1SGerd Hoffmann 776f1ae32a1SGerd Hoffmann if ((start_offset & 0x1000) == 0) { 777f1ae32a1SGerd Hoffmann start_addr = (iso_td.bp & OHCI_PAGE_MASK) | 778f1ae32a1SGerd Hoffmann (start_offset & OHCI_OFFSET_MASK); 779f1ae32a1SGerd Hoffmann } else { 780f1ae32a1SGerd Hoffmann start_addr = (iso_td.be & OHCI_PAGE_MASK) | 781f1ae32a1SGerd Hoffmann (start_offset & OHCI_OFFSET_MASK); 782f1ae32a1SGerd Hoffmann } 783f1ae32a1SGerd Hoffmann 784f1ae32a1SGerd Hoffmann if (relative_frame_number < frame_count) { 785f1ae32a1SGerd Hoffmann end_offset = next_offset - 1; 786f1ae32a1SGerd Hoffmann if ((end_offset & 0x1000) == 0) { 787f1ae32a1SGerd Hoffmann end_addr = (iso_td.bp & OHCI_PAGE_MASK) | 788f1ae32a1SGerd Hoffmann (end_offset & OHCI_OFFSET_MASK); 789f1ae32a1SGerd Hoffmann } else { 790f1ae32a1SGerd Hoffmann end_addr = (iso_td.be & OHCI_PAGE_MASK) | 791f1ae32a1SGerd Hoffmann (end_offset & OHCI_OFFSET_MASK); 792f1ae32a1SGerd Hoffmann } 793f1ae32a1SGerd Hoffmann } else { 794f1ae32a1SGerd Hoffmann /* Last packet in the ISO TD */ 795f1ae32a1SGerd Hoffmann end_addr = iso_td.be; 796f1ae32a1SGerd Hoffmann } 797f1ae32a1SGerd Hoffmann 798f1ae32a1SGerd Hoffmann if ((start_addr & OHCI_PAGE_MASK) != (end_addr & OHCI_PAGE_MASK)) { 799f1ae32a1SGerd Hoffmann len = (end_addr & OHCI_OFFSET_MASK) + 0x1001 800f1ae32a1SGerd Hoffmann - (start_addr & OHCI_OFFSET_MASK); 801f1ae32a1SGerd Hoffmann } else { 802f1ae32a1SGerd Hoffmann len = end_addr - start_addr + 1; 803f1ae32a1SGerd Hoffmann } 804f1ae32a1SGerd Hoffmann 805f1ae32a1SGerd Hoffmann if (len && dir != OHCI_TD_DIR_IN) { 8069ac6a217SDavid Gibson ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, len, 8079ac6a217SDavid Gibson DMA_DIRECTION_TO_DEVICE); 808f1ae32a1SGerd Hoffmann } 809f1ae32a1SGerd Hoffmann 810f1ae32a1SGerd Hoffmann if (completion) { 811f1ae32a1SGerd Hoffmann ret = ohci->usb_packet.result; 812f1ae32a1SGerd Hoffmann } else { 813*a6fb2ddbSHans de Goede bool int_req = relative_frame_number == frame_count && 814*a6fb2ddbSHans de Goede OHCI_BM(iso_td.flags, TD_DI) == 0; 815f1ae32a1SGerd Hoffmann dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA)); 816f1ae32a1SGerd Hoffmann ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN)); 817*a6fb2ddbSHans de Goede usb_packet_setup(&ohci->usb_packet, pid, ep, addr, false, int_req); 818f1ae32a1SGerd Hoffmann usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len); 819f1ae32a1SGerd Hoffmann ret = usb_handle_packet(dev, &ohci->usb_packet); 820f1ae32a1SGerd Hoffmann if (ret == USB_RET_ASYNC) { 82136dfe324SHans de Goede usb_device_flush_ep_queue(dev, ep); 822f1ae32a1SGerd Hoffmann return 1; 823f1ae32a1SGerd Hoffmann } 824f1ae32a1SGerd Hoffmann } 825f1ae32a1SGerd Hoffmann 826f1ae32a1SGerd Hoffmann #ifdef DEBUG_ISOCH 827f1ae32a1SGerd Hoffmann printf("so 0x%.8x eo 0x%.8x\nsa 0x%.8x ea 0x%.8x\ndir %s len %zu ret %d\n", 828f1ae32a1SGerd Hoffmann start_offset, end_offset, start_addr, end_addr, str, len, ret); 829f1ae32a1SGerd Hoffmann #endif 830f1ae32a1SGerd Hoffmann 831f1ae32a1SGerd Hoffmann /* Writeback */ 832f1ae32a1SGerd Hoffmann if (dir == OHCI_TD_DIR_IN && ret >= 0 && ret <= len) { 833f1ae32a1SGerd Hoffmann /* IN transfer succeeded */ 8349ac6a217SDavid Gibson ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, ret, 8359ac6a217SDavid Gibson DMA_DIRECTION_FROM_DEVICE); 836f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 837f1ae32a1SGerd Hoffmann OHCI_CC_NOERROR); 838f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, ret); 839f1ae32a1SGerd Hoffmann } else if (dir == OHCI_TD_DIR_OUT && ret == len) { 840f1ae32a1SGerd Hoffmann /* OUT transfer succeeded */ 841f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 842f1ae32a1SGerd Hoffmann OHCI_CC_NOERROR); 843f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 0); 844f1ae32a1SGerd Hoffmann } else { 845f1ae32a1SGerd Hoffmann if (ret > (ssize_t) len) { 846f1ae32a1SGerd Hoffmann printf("usb-ohci: DataOverrun %d > %zu\n", ret, len); 847f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 848f1ae32a1SGerd Hoffmann OHCI_CC_DATAOVERRUN); 849f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 850f1ae32a1SGerd Hoffmann len); 851f1ae32a1SGerd Hoffmann } else if (ret >= 0) { 852f1ae32a1SGerd Hoffmann printf("usb-ohci: DataUnderrun %d\n", ret); 853f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 854f1ae32a1SGerd Hoffmann OHCI_CC_DATAUNDERRUN); 855f1ae32a1SGerd Hoffmann } else { 856f1ae32a1SGerd Hoffmann switch (ret) { 857f1ae32a1SGerd Hoffmann case USB_RET_IOERROR: 858f1ae32a1SGerd Hoffmann case USB_RET_NODEV: 859f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 860f1ae32a1SGerd Hoffmann OHCI_CC_DEVICENOTRESPONDING); 861f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 862f1ae32a1SGerd Hoffmann 0); 863f1ae32a1SGerd Hoffmann break; 864f1ae32a1SGerd Hoffmann case USB_RET_NAK: 865f1ae32a1SGerd Hoffmann case USB_RET_STALL: 866f1ae32a1SGerd Hoffmann printf("usb-ohci: got NAK/STALL %d\n", ret); 867f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 868f1ae32a1SGerd Hoffmann OHCI_CC_STALL); 869f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 870f1ae32a1SGerd Hoffmann 0); 871f1ae32a1SGerd Hoffmann break; 872f1ae32a1SGerd Hoffmann default: 873f1ae32a1SGerd Hoffmann printf("usb-ohci: Bad device response %d\n", ret); 874f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 875f1ae32a1SGerd Hoffmann OHCI_CC_UNDEXPETEDPID); 876f1ae32a1SGerd Hoffmann break; 877f1ae32a1SGerd Hoffmann } 878f1ae32a1SGerd Hoffmann } 879f1ae32a1SGerd Hoffmann } 880f1ae32a1SGerd Hoffmann 881f1ae32a1SGerd Hoffmann if (relative_frame_number == frame_count) { 882f1ae32a1SGerd Hoffmann /* Last data packet of ISO TD - retire the TD to the Done Queue */ 883f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_NOERROR); 884f1ae32a1SGerd Hoffmann ed->head &= ~OHCI_DPTR_MASK; 885f1ae32a1SGerd Hoffmann ed->head |= (iso_td.next & OHCI_DPTR_MASK); 886f1ae32a1SGerd Hoffmann iso_td.next = ohci->done; 887f1ae32a1SGerd Hoffmann ohci->done = addr; 888f1ae32a1SGerd Hoffmann i = OHCI_BM(iso_td.flags, TD_DI); 889f1ae32a1SGerd Hoffmann if (i < ohci->done_count) 890f1ae32a1SGerd Hoffmann ohci->done_count = i; 891f1ae32a1SGerd Hoffmann } 892f1ae32a1SGerd Hoffmann ohci_put_iso_td(ohci, addr, &iso_td); 893f1ae32a1SGerd Hoffmann return 1; 894f1ae32a1SGerd Hoffmann } 895f1ae32a1SGerd Hoffmann 896f1ae32a1SGerd Hoffmann /* Service a transport descriptor. 897f1ae32a1SGerd Hoffmann Returns nonzero to terminate processing of this endpoint. */ 898f1ae32a1SGerd Hoffmann 899f1ae32a1SGerd Hoffmann static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) 900f1ae32a1SGerd Hoffmann { 901f1ae32a1SGerd Hoffmann int dir; 902f1ae32a1SGerd Hoffmann size_t len = 0, pktlen = 0; 903f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET 904f1ae32a1SGerd Hoffmann const char *str = NULL; 905f1ae32a1SGerd Hoffmann #endif 906f1ae32a1SGerd Hoffmann int pid; 907f1ae32a1SGerd Hoffmann int ret; 908f1ae32a1SGerd Hoffmann int i; 909f1ae32a1SGerd Hoffmann USBDevice *dev; 910f1ae32a1SGerd Hoffmann USBEndpoint *ep; 911f1ae32a1SGerd Hoffmann struct ohci_td td; 912f1ae32a1SGerd Hoffmann uint32_t addr; 913f1ae32a1SGerd Hoffmann int flag_r; 914f1ae32a1SGerd Hoffmann int completion; 915f1ae32a1SGerd Hoffmann 916f1ae32a1SGerd Hoffmann addr = ed->head & OHCI_DPTR_MASK; 917f1ae32a1SGerd Hoffmann /* See if this TD has already been submitted to the device. */ 918f1ae32a1SGerd Hoffmann completion = (addr == ohci->async_td); 919f1ae32a1SGerd Hoffmann if (completion && !ohci->async_complete) { 920f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET 921f1ae32a1SGerd Hoffmann DPRINTF("Skipping async TD\n"); 922f1ae32a1SGerd Hoffmann #endif 923f1ae32a1SGerd Hoffmann return 1; 924f1ae32a1SGerd Hoffmann } 925f1ae32a1SGerd Hoffmann if (!ohci_read_td(ohci, addr, &td)) { 926f1ae32a1SGerd Hoffmann fprintf(stderr, "usb-ohci: TD read error at %x\n", addr); 927f1ae32a1SGerd Hoffmann return 0; 928f1ae32a1SGerd Hoffmann } 929f1ae32a1SGerd Hoffmann 930f1ae32a1SGerd Hoffmann dir = OHCI_BM(ed->flags, ED_D); 931f1ae32a1SGerd Hoffmann switch (dir) { 932f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_OUT: 933f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_IN: 934f1ae32a1SGerd Hoffmann /* Same value. */ 935f1ae32a1SGerd Hoffmann break; 936f1ae32a1SGerd Hoffmann default: 937f1ae32a1SGerd Hoffmann dir = OHCI_BM(td.flags, TD_DP); 938f1ae32a1SGerd Hoffmann break; 939f1ae32a1SGerd Hoffmann } 940f1ae32a1SGerd Hoffmann 941f1ae32a1SGerd Hoffmann switch (dir) { 942f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_IN: 943f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET 944f1ae32a1SGerd Hoffmann str = "in"; 945f1ae32a1SGerd Hoffmann #endif 946f1ae32a1SGerd Hoffmann pid = USB_TOKEN_IN; 947f1ae32a1SGerd Hoffmann break; 948f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_OUT: 949f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET 950f1ae32a1SGerd Hoffmann str = "out"; 951f1ae32a1SGerd Hoffmann #endif 952f1ae32a1SGerd Hoffmann pid = USB_TOKEN_OUT; 953f1ae32a1SGerd Hoffmann break; 954f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_SETUP: 955f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET 956f1ae32a1SGerd Hoffmann str = "setup"; 957f1ae32a1SGerd Hoffmann #endif 958f1ae32a1SGerd Hoffmann pid = USB_TOKEN_SETUP; 959f1ae32a1SGerd Hoffmann break; 960f1ae32a1SGerd Hoffmann default: 961f1ae32a1SGerd Hoffmann fprintf(stderr, "usb-ohci: Bad direction\n"); 962f1ae32a1SGerd Hoffmann return 1; 963f1ae32a1SGerd Hoffmann } 964f1ae32a1SGerd Hoffmann if (td.cbp && td.be) { 965f1ae32a1SGerd Hoffmann if ((td.cbp & 0xfffff000) != (td.be & 0xfffff000)) { 966f1ae32a1SGerd Hoffmann len = (td.be & 0xfff) + 0x1001 - (td.cbp & 0xfff); 967f1ae32a1SGerd Hoffmann } else { 968f1ae32a1SGerd Hoffmann len = (td.be - td.cbp) + 1; 969f1ae32a1SGerd Hoffmann } 970f1ae32a1SGerd Hoffmann 971f1ae32a1SGerd Hoffmann pktlen = len; 972f1ae32a1SGerd Hoffmann if (len && dir != OHCI_TD_DIR_IN) { 973f1ae32a1SGerd Hoffmann /* The endpoint may not allow us to transfer it all now */ 974f1ae32a1SGerd Hoffmann pktlen = (ed->flags & OHCI_ED_MPS_MASK) >> OHCI_ED_MPS_SHIFT; 975f1ae32a1SGerd Hoffmann if (pktlen > len) { 976f1ae32a1SGerd Hoffmann pktlen = len; 977f1ae32a1SGerd Hoffmann } 978f1ae32a1SGerd Hoffmann if (!completion) { 9799ac6a217SDavid Gibson ohci_copy_td(ohci, &td, ohci->usb_buf, pktlen, 9809ac6a217SDavid Gibson DMA_DIRECTION_TO_DEVICE); 981f1ae32a1SGerd Hoffmann } 982f1ae32a1SGerd Hoffmann } 983f1ae32a1SGerd Hoffmann } 984f1ae32a1SGerd Hoffmann 985f1ae32a1SGerd Hoffmann flag_r = (td.flags & OHCI_TD_R) != 0; 986f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET 987f1ae32a1SGerd Hoffmann DPRINTF(" TD @ 0x%.8x %" PRId64 " of %" PRId64 988f1ae32a1SGerd Hoffmann " bytes %s r=%d cbp=0x%.8x be=0x%.8x\n", 989f1ae32a1SGerd Hoffmann addr, (int64_t)pktlen, (int64_t)len, str, flag_r, td.cbp, td.be); 990f1ae32a1SGerd Hoffmann 991f1ae32a1SGerd Hoffmann if (pktlen > 0 && dir != OHCI_TD_DIR_IN) { 992f1ae32a1SGerd Hoffmann DPRINTF(" data:"); 993f1ae32a1SGerd Hoffmann for (i = 0; i < pktlen; i++) { 994f1ae32a1SGerd Hoffmann printf(" %.2x", ohci->usb_buf[i]); 995f1ae32a1SGerd Hoffmann } 996f1ae32a1SGerd Hoffmann DPRINTF("\n"); 997f1ae32a1SGerd Hoffmann } 998f1ae32a1SGerd Hoffmann #endif 999f1ae32a1SGerd Hoffmann if (completion) { 1000f1ae32a1SGerd Hoffmann ret = ohci->usb_packet.result; 1001f1ae32a1SGerd Hoffmann ohci->async_td = 0; 1002f1ae32a1SGerd Hoffmann ohci->async_complete = 0; 1003f1ae32a1SGerd Hoffmann } else { 1004f1ae32a1SGerd Hoffmann if (ohci->async_td) { 1005f1ae32a1SGerd Hoffmann /* ??? The hardware should allow one active packet per 1006f1ae32a1SGerd Hoffmann endpoint. We only allow one active packet per controller. 1007f1ae32a1SGerd Hoffmann This should be sufficient as long as devices respond in a 1008f1ae32a1SGerd Hoffmann timely manner. 1009f1ae32a1SGerd Hoffmann */ 1010f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET 1011f1ae32a1SGerd Hoffmann DPRINTF("Too many pending packets\n"); 1012f1ae32a1SGerd Hoffmann #endif 1013f1ae32a1SGerd Hoffmann return 1; 1014f1ae32a1SGerd Hoffmann } 1015f1ae32a1SGerd Hoffmann dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA)); 1016f1ae32a1SGerd Hoffmann ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN)); 1017*a6fb2ddbSHans de Goede usb_packet_setup(&ohci->usb_packet, pid, ep, addr, !flag_r, 1018*a6fb2ddbSHans de Goede OHCI_BM(td.flags, TD_DI) == 0); 1019f1ae32a1SGerd Hoffmann usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen); 1020f1ae32a1SGerd Hoffmann ret = usb_handle_packet(dev, &ohci->usb_packet); 1021f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET 1022f1ae32a1SGerd Hoffmann DPRINTF("ret=%d\n", ret); 1023f1ae32a1SGerd Hoffmann #endif 1024f1ae32a1SGerd Hoffmann if (ret == USB_RET_ASYNC) { 102536dfe324SHans de Goede usb_device_flush_ep_queue(dev, ep); 1026f1ae32a1SGerd Hoffmann ohci->async_td = addr; 1027f1ae32a1SGerd Hoffmann return 1; 1028f1ae32a1SGerd Hoffmann } 1029f1ae32a1SGerd Hoffmann } 1030f1ae32a1SGerd Hoffmann if (ret >= 0) { 1031f1ae32a1SGerd Hoffmann if (dir == OHCI_TD_DIR_IN) { 10329ac6a217SDavid Gibson ohci_copy_td(ohci, &td, ohci->usb_buf, ret, 10339ac6a217SDavid Gibson DMA_DIRECTION_FROM_DEVICE); 1034f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET 1035f1ae32a1SGerd Hoffmann DPRINTF(" data:"); 1036f1ae32a1SGerd Hoffmann for (i = 0; i < ret; i++) 1037f1ae32a1SGerd Hoffmann printf(" %.2x", ohci->usb_buf[i]); 1038f1ae32a1SGerd Hoffmann DPRINTF("\n"); 1039f1ae32a1SGerd Hoffmann #endif 1040f1ae32a1SGerd Hoffmann } else { 1041f1ae32a1SGerd Hoffmann ret = pktlen; 1042f1ae32a1SGerd Hoffmann } 1043f1ae32a1SGerd Hoffmann } 1044f1ae32a1SGerd Hoffmann 1045f1ae32a1SGerd Hoffmann /* Writeback */ 1046f1ae32a1SGerd Hoffmann if (ret == pktlen || (dir == OHCI_TD_DIR_IN && ret >= 0 && flag_r)) { 1047f1ae32a1SGerd Hoffmann /* Transmission succeeded. */ 1048f1ae32a1SGerd Hoffmann if (ret == len) { 1049f1ae32a1SGerd Hoffmann td.cbp = 0; 1050f1ae32a1SGerd Hoffmann } else { 1051f1ae32a1SGerd Hoffmann if ((td.cbp & 0xfff) + ret > 0xfff) { 1052f1ae32a1SGerd Hoffmann td.cbp = (td.be & ~0xfff) + ((td.cbp + ret) & 0xfff); 1053f1ae32a1SGerd Hoffmann } else { 1054f1ae32a1SGerd Hoffmann td.cbp += ret; 1055f1ae32a1SGerd Hoffmann } 1056f1ae32a1SGerd Hoffmann } 1057f1ae32a1SGerd Hoffmann td.flags |= OHCI_TD_T1; 1058f1ae32a1SGerd Hoffmann td.flags ^= OHCI_TD_T0; 1059f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_NOERROR); 1060f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_EC, 0); 1061f1ae32a1SGerd Hoffmann 1062f1ae32a1SGerd Hoffmann if ((dir != OHCI_TD_DIR_IN) && (ret != len)) { 1063f1ae32a1SGerd Hoffmann /* Partial packet transfer: TD not ready to retire yet */ 1064f1ae32a1SGerd Hoffmann goto exit_no_retire; 1065f1ae32a1SGerd Hoffmann } 1066f1ae32a1SGerd Hoffmann 1067f1ae32a1SGerd Hoffmann /* Setting ED_C is part of the TD retirement process */ 1068f1ae32a1SGerd Hoffmann ed->head &= ~OHCI_ED_C; 1069f1ae32a1SGerd Hoffmann if (td.flags & OHCI_TD_T0) 1070f1ae32a1SGerd Hoffmann ed->head |= OHCI_ED_C; 1071f1ae32a1SGerd Hoffmann } else { 1072f1ae32a1SGerd Hoffmann if (ret >= 0) { 1073f1ae32a1SGerd Hoffmann DPRINTF("usb-ohci: Underrun\n"); 1074f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAUNDERRUN); 1075f1ae32a1SGerd Hoffmann } else { 1076f1ae32a1SGerd Hoffmann switch (ret) { 1077f1ae32a1SGerd Hoffmann case USB_RET_IOERROR: 1078f1ae32a1SGerd Hoffmann case USB_RET_NODEV: 1079f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DEVICENOTRESPONDING); 1080f1ae32a1SGerd Hoffmann case USB_RET_NAK: 1081f1ae32a1SGerd Hoffmann DPRINTF("usb-ohci: got NAK\n"); 1082f1ae32a1SGerd Hoffmann return 1; 1083f1ae32a1SGerd Hoffmann case USB_RET_STALL: 1084f1ae32a1SGerd Hoffmann DPRINTF("usb-ohci: got STALL\n"); 1085f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_STALL); 1086f1ae32a1SGerd Hoffmann break; 1087f1ae32a1SGerd Hoffmann case USB_RET_BABBLE: 1088f1ae32a1SGerd Hoffmann DPRINTF("usb-ohci: got BABBLE\n"); 1089f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAOVERRUN); 1090f1ae32a1SGerd Hoffmann break; 1091f1ae32a1SGerd Hoffmann default: 1092f1ae32a1SGerd Hoffmann fprintf(stderr, "usb-ohci: Bad device response %d\n", ret); 1093f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_UNDEXPETEDPID); 1094f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_EC, 3); 1095f1ae32a1SGerd Hoffmann break; 1096f1ae32a1SGerd Hoffmann } 1097f1ae32a1SGerd Hoffmann } 1098f1ae32a1SGerd Hoffmann ed->head |= OHCI_ED_H; 1099f1ae32a1SGerd Hoffmann } 1100f1ae32a1SGerd Hoffmann 1101f1ae32a1SGerd Hoffmann /* Retire this TD */ 1102f1ae32a1SGerd Hoffmann ed->head &= ~OHCI_DPTR_MASK; 1103f1ae32a1SGerd Hoffmann ed->head |= td.next & OHCI_DPTR_MASK; 1104f1ae32a1SGerd Hoffmann td.next = ohci->done; 1105f1ae32a1SGerd Hoffmann ohci->done = addr; 1106f1ae32a1SGerd Hoffmann i = OHCI_BM(td.flags, TD_DI); 1107f1ae32a1SGerd Hoffmann if (i < ohci->done_count) 1108f1ae32a1SGerd Hoffmann ohci->done_count = i; 1109f1ae32a1SGerd Hoffmann exit_no_retire: 1110f1ae32a1SGerd Hoffmann ohci_put_td(ohci, addr, &td); 1111f1ae32a1SGerd Hoffmann return OHCI_BM(td.flags, TD_CC) != OHCI_CC_NOERROR; 1112f1ae32a1SGerd Hoffmann } 1113f1ae32a1SGerd Hoffmann 1114f1ae32a1SGerd Hoffmann /* Service an endpoint list. Returns nonzero if active TD were found. */ 1115f1ae32a1SGerd Hoffmann static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion) 1116f1ae32a1SGerd Hoffmann { 1117f1ae32a1SGerd Hoffmann struct ohci_ed ed; 1118f1ae32a1SGerd Hoffmann uint32_t next_ed; 1119f1ae32a1SGerd Hoffmann uint32_t cur; 1120f1ae32a1SGerd Hoffmann int active; 1121f1ae32a1SGerd Hoffmann 1122f1ae32a1SGerd Hoffmann active = 0; 1123f1ae32a1SGerd Hoffmann 1124f1ae32a1SGerd Hoffmann if (head == 0) 1125f1ae32a1SGerd Hoffmann return 0; 1126f1ae32a1SGerd Hoffmann 1127f1ae32a1SGerd Hoffmann for (cur = head; cur; cur = next_ed) { 1128f1ae32a1SGerd Hoffmann if (!ohci_read_ed(ohci, cur, &ed)) { 1129f1ae32a1SGerd Hoffmann fprintf(stderr, "usb-ohci: ED read error at %x\n", cur); 1130f1ae32a1SGerd Hoffmann return 0; 1131f1ae32a1SGerd Hoffmann } 1132f1ae32a1SGerd Hoffmann 1133f1ae32a1SGerd Hoffmann next_ed = ed.next & OHCI_DPTR_MASK; 1134f1ae32a1SGerd Hoffmann 1135f1ae32a1SGerd Hoffmann if ((ed.head & OHCI_ED_H) || (ed.flags & OHCI_ED_K)) { 1136f1ae32a1SGerd Hoffmann uint32_t addr; 1137f1ae32a1SGerd Hoffmann /* Cancel pending packets for ED that have been paused. */ 1138f1ae32a1SGerd Hoffmann addr = ed.head & OHCI_DPTR_MASK; 1139f1ae32a1SGerd Hoffmann if (ohci->async_td && addr == ohci->async_td) { 1140f1ae32a1SGerd Hoffmann usb_cancel_packet(&ohci->usb_packet); 1141f1ae32a1SGerd Hoffmann ohci->async_td = 0; 1142f1ae32a1SGerd Hoffmann } 1143f1ae32a1SGerd Hoffmann continue; 1144f1ae32a1SGerd Hoffmann } 1145f1ae32a1SGerd Hoffmann 1146f1ae32a1SGerd Hoffmann while ((ed.head & OHCI_DPTR_MASK) != ed.tail) { 1147f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET 1148f1ae32a1SGerd Hoffmann DPRINTF("ED @ 0x%.8x fa=%u en=%u d=%u s=%u k=%u f=%u mps=%u " 1149f1ae32a1SGerd Hoffmann "h=%u c=%u\n head=0x%.8x tailp=0x%.8x next=0x%.8x\n", cur, 1150f1ae32a1SGerd Hoffmann OHCI_BM(ed.flags, ED_FA), OHCI_BM(ed.flags, ED_EN), 1151f1ae32a1SGerd Hoffmann OHCI_BM(ed.flags, ED_D), (ed.flags & OHCI_ED_S)!= 0, 1152f1ae32a1SGerd Hoffmann (ed.flags & OHCI_ED_K) != 0, (ed.flags & OHCI_ED_F) != 0, 1153f1ae32a1SGerd Hoffmann OHCI_BM(ed.flags, ED_MPS), (ed.head & OHCI_ED_H) != 0, 1154f1ae32a1SGerd Hoffmann (ed.head & OHCI_ED_C) != 0, ed.head & OHCI_DPTR_MASK, 1155f1ae32a1SGerd Hoffmann ed.tail & OHCI_DPTR_MASK, ed.next & OHCI_DPTR_MASK); 1156f1ae32a1SGerd Hoffmann #endif 1157f1ae32a1SGerd Hoffmann active = 1; 1158f1ae32a1SGerd Hoffmann 1159f1ae32a1SGerd Hoffmann if ((ed.flags & OHCI_ED_F) == 0) { 1160f1ae32a1SGerd Hoffmann if (ohci_service_td(ohci, &ed)) 1161f1ae32a1SGerd Hoffmann break; 1162f1ae32a1SGerd Hoffmann } else { 1163f1ae32a1SGerd Hoffmann /* Handle isochronous endpoints */ 1164f1ae32a1SGerd Hoffmann if (ohci_service_iso_td(ohci, &ed, completion)) 1165f1ae32a1SGerd Hoffmann break; 1166f1ae32a1SGerd Hoffmann } 1167f1ae32a1SGerd Hoffmann } 1168f1ae32a1SGerd Hoffmann 1169f1ae32a1SGerd Hoffmann ohci_put_ed(ohci, cur, &ed); 1170f1ae32a1SGerd Hoffmann } 1171f1ae32a1SGerd Hoffmann 1172f1ae32a1SGerd Hoffmann return active; 1173f1ae32a1SGerd Hoffmann } 1174f1ae32a1SGerd Hoffmann 1175f1ae32a1SGerd Hoffmann /* Generate a SOF event, and set a timer for EOF */ 1176f1ae32a1SGerd Hoffmann static void ohci_sof(OHCIState *ohci) 1177f1ae32a1SGerd Hoffmann { 1178f1ae32a1SGerd Hoffmann ohci->sof_time = qemu_get_clock_ns(vm_clock); 1179f1ae32a1SGerd Hoffmann qemu_mod_timer(ohci->eof_timer, ohci->sof_time + usb_frame_time); 1180f1ae32a1SGerd Hoffmann ohci_set_interrupt(ohci, OHCI_INTR_SF); 1181f1ae32a1SGerd Hoffmann } 1182f1ae32a1SGerd Hoffmann 1183f1ae32a1SGerd Hoffmann /* Process Control and Bulk lists. */ 1184f1ae32a1SGerd Hoffmann static void ohci_process_lists(OHCIState *ohci, int completion) 1185f1ae32a1SGerd Hoffmann { 1186f1ae32a1SGerd Hoffmann if ((ohci->ctl & OHCI_CTL_CLE) && (ohci->status & OHCI_STATUS_CLF)) { 1187f1ae32a1SGerd Hoffmann if (ohci->ctrl_cur && ohci->ctrl_cur != ohci->ctrl_head) { 1188f1ae32a1SGerd Hoffmann DPRINTF("usb-ohci: head %x, cur %x\n", 1189f1ae32a1SGerd Hoffmann ohci->ctrl_head, ohci->ctrl_cur); 1190f1ae32a1SGerd Hoffmann } 1191f1ae32a1SGerd Hoffmann if (!ohci_service_ed_list(ohci, ohci->ctrl_head, completion)) { 1192f1ae32a1SGerd Hoffmann ohci->ctrl_cur = 0; 1193f1ae32a1SGerd Hoffmann ohci->status &= ~OHCI_STATUS_CLF; 1194f1ae32a1SGerd Hoffmann } 1195f1ae32a1SGerd Hoffmann } 1196f1ae32a1SGerd Hoffmann 1197f1ae32a1SGerd Hoffmann if ((ohci->ctl & OHCI_CTL_BLE) && (ohci->status & OHCI_STATUS_BLF)) { 1198f1ae32a1SGerd Hoffmann if (!ohci_service_ed_list(ohci, ohci->bulk_head, completion)) { 1199f1ae32a1SGerd Hoffmann ohci->bulk_cur = 0; 1200f1ae32a1SGerd Hoffmann ohci->status &= ~OHCI_STATUS_BLF; 1201f1ae32a1SGerd Hoffmann } 1202f1ae32a1SGerd Hoffmann } 1203f1ae32a1SGerd Hoffmann } 1204f1ae32a1SGerd Hoffmann 1205f1ae32a1SGerd Hoffmann /* Do frame processing on frame boundary */ 1206f1ae32a1SGerd Hoffmann static void ohci_frame_boundary(void *opaque) 1207f1ae32a1SGerd Hoffmann { 1208f1ae32a1SGerd Hoffmann OHCIState *ohci = opaque; 1209f1ae32a1SGerd Hoffmann struct ohci_hcca hcca; 1210f1ae32a1SGerd Hoffmann 1211f1ae32a1SGerd Hoffmann ohci_read_hcca(ohci, ohci->hcca, &hcca); 1212f1ae32a1SGerd Hoffmann 1213f1ae32a1SGerd Hoffmann /* Process all the lists at the end of the frame */ 1214f1ae32a1SGerd Hoffmann if (ohci->ctl & OHCI_CTL_PLE) { 1215f1ae32a1SGerd Hoffmann int n; 1216f1ae32a1SGerd Hoffmann 1217f1ae32a1SGerd Hoffmann n = ohci->frame_number & 0x1f; 1218f1ae32a1SGerd Hoffmann ohci_service_ed_list(ohci, le32_to_cpu(hcca.intr[n]), 0); 1219f1ae32a1SGerd Hoffmann } 1220f1ae32a1SGerd Hoffmann 1221f1ae32a1SGerd Hoffmann /* Cancel all pending packets if either of the lists has been disabled. */ 1222f1ae32a1SGerd Hoffmann if (ohci->async_td && 1223f1ae32a1SGerd Hoffmann ohci->old_ctl & (~ohci->ctl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) { 1224f1ae32a1SGerd Hoffmann usb_cancel_packet(&ohci->usb_packet); 1225f1ae32a1SGerd Hoffmann ohci->async_td = 0; 1226f1ae32a1SGerd Hoffmann } 1227f1ae32a1SGerd Hoffmann ohci->old_ctl = ohci->ctl; 1228f1ae32a1SGerd Hoffmann ohci_process_lists(ohci, 0); 1229f1ae32a1SGerd Hoffmann 1230f1ae32a1SGerd Hoffmann /* Frame boundary, so do EOF stuf here */ 1231f1ae32a1SGerd Hoffmann ohci->frt = ohci->fit; 1232f1ae32a1SGerd Hoffmann 1233f1ae32a1SGerd Hoffmann /* Increment frame number and take care of endianness. */ 1234f1ae32a1SGerd Hoffmann ohci->frame_number = (ohci->frame_number + 1) & 0xffff; 1235f1ae32a1SGerd Hoffmann hcca.frame = cpu_to_le16(ohci->frame_number); 1236f1ae32a1SGerd Hoffmann 1237f1ae32a1SGerd Hoffmann if (ohci->done_count == 0 && !(ohci->intr_status & OHCI_INTR_WD)) { 1238f1ae32a1SGerd Hoffmann if (!ohci->done) 1239f1ae32a1SGerd Hoffmann abort(); 1240f1ae32a1SGerd Hoffmann if (ohci->intr & ohci->intr_status) 1241f1ae32a1SGerd Hoffmann ohci->done |= 1; 1242f1ae32a1SGerd Hoffmann hcca.done = cpu_to_le32(ohci->done); 1243f1ae32a1SGerd Hoffmann ohci->done = 0; 1244f1ae32a1SGerd Hoffmann ohci->done_count = 7; 1245f1ae32a1SGerd Hoffmann ohci_set_interrupt(ohci, OHCI_INTR_WD); 1246f1ae32a1SGerd Hoffmann } 1247f1ae32a1SGerd Hoffmann 1248f1ae32a1SGerd Hoffmann if (ohci->done_count != 7 && ohci->done_count != 0) 1249f1ae32a1SGerd Hoffmann ohci->done_count--; 1250f1ae32a1SGerd Hoffmann 1251f1ae32a1SGerd Hoffmann /* Do SOF stuff here */ 1252f1ae32a1SGerd Hoffmann ohci_sof(ohci); 1253f1ae32a1SGerd Hoffmann 1254f1ae32a1SGerd Hoffmann /* Writeback HCCA */ 1255f1ae32a1SGerd Hoffmann ohci_put_hcca(ohci, ohci->hcca, &hcca); 1256f1ae32a1SGerd Hoffmann } 1257f1ae32a1SGerd Hoffmann 1258f1ae32a1SGerd Hoffmann /* Start sending SOF tokens across the USB bus, lists are processed in 1259f1ae32a1SGerd Hoffmann * next frame 1260f1ae32a1SGerd Hoffmann */ 1261f1ae32a1SGerd Hoffmann static int ohci_bus_start(OHCIState *ohci) 1262f1ae32a1SGerd Hoffmann { 1263f1ae32a1SGerd Hoffmann ohci->eof_timer = qemu_new_timer_ns(vm_clock, 1264f1ae32a1SGerd Hoffmann ohci_frame_boundary, 1265f1ae32a1SGerd Hoffmann ohci); 1266f1ae32a1SGerd Hoffmann 1267f1ae32a1SGerd Hoffmann if (ohci->eof_timer == NULL) { 1268f1ae32a1SGerd Hoffmann fprintf(stderr, "usb-ohci: %s: qemu_new_timer_ns failed\n", ohci->name); 1269f1ae32a1SGerd Hoffmann /* TODO: Signal unrecoverable error */ 1270f1ae32a1SGerd Hoffmann return 0; 1271f1ae32a1SGerd Hoffmann } 1272f1ae32a1SGerd Hoffmann 1273f1ae32a1SGerd Hoffmann DPRINTF("usb-ohci: %s: USB Operational\n", ohci->name); 1274f1ae32a1SGerd Hoffmann 1275f1ae32a1SGerd Hoffmann ohci_sof(ohci); 1276f1ae32a1SGerd Hoffmann 1277f1ae32a1SGerd Hoffmann return 1; 1278f1ae32a1SGerd Hoffmann } 1279f1ae32a1SGerd Hoffmann 1280f1ae32a1SGerd Hoffmann /* Stop sending SOF tokens on the bus */ 1281f1ae32a1SGerd Hoffmann static void ohci_bus_stop(OHCIState *ohci) 1282f1ae32a1SGerd Hoffmann { 1283f1ae32a1SGerd Hoffmann if (ohci->eof_timer) 1284f1ae32a1SGerd Hoffmann qemu_del_timer(ohci->eof_timer); 1285f1ae32a1SGerd Hoffmann ohci->eof_timer = NULL; 1286f1ae32a1SGerd Hoffmann } 1287f1ae32a1SGerd Hoffmann 1288f1ae32a1SGerd Hoffmann /* Sets a flag in a port status register but only set it if the port is 1289f1ae32a1SGerd Hoffmann * connected, if not set ConnectStatusChange flag. If flag is enabled 1290f1ae32a1SGerd Hoffmann * return 1. 1291f1ae32a1SGerd Hoffmann */ 1292f1ae32a1SGerd Hoffmann static int ohci_port_set_if_connected(OHCIState *ohci, int i, uint32_t val) 1293f1ae32a1SGerd Hoffmann { 1294f1ae32a1SGerd Hoffmann int ret = 1; 1295f1ae32a1SGerd Hoffmann 1296f1ae32a1SGerd Hoffmann /* writing a 0 has no effect */ 1297f1ae32a1SGerd Hoffmann if (val == 0) 1298f1ae32a1SGerd Hoffmann return 0; 1299f1ae32a1SGerd Hoffmann 1300f1ae32a1SGerd Hoffmann /* If CurrentConnectStatus is cleared we set 1301f1ae32a1SGerd Hoffmann * ConnectStatusChange 1302f1ae32a1SGerd Hoffmann */ 1303f1ae32a1SGerd Hoffmann if (!(ohci->rhport[i].ctrl & OHCI_PORT_CCS)) { 1304f1ae32a1SGerd Hoffmann ohci->rhport[i].ctrl |= OHCI_PORT_CSC; 1305f1ae32a1SGerd Hoffmann if (ohci->rhstatus & OHCI_RHS_DRWE) { 1306f1ae32a1SGerd Hoffmann /* TODO: CSC is a wakeup event */ 1307f1ae32a1SGerd Hoffmann } 1308f1ae32a1SGerd Hoffmann return 0; 1309f1ae32a1SGerd Hoffmann } 1310f1ae32a1SGerd Hoffmann 1311f1ae32a1SGerd Hoffmann if (ohci->rhport[i].ctrl & val) 1312f1ae32a1SGerd Hoffmann ret = 0; 1313f1ae32a1SGerd Hoffmann 1314f1ae32a1SGerd Hoffmann /* set the bit */ 1315f1ae32a1SGerd Hoffmann ohci->rhport[i].ctrl |= val; 1316f1ae32a1SGerd Hoffmann 1317f1ae32a1SGerd Hoffmann return ret; 1318f1ae32a1SGerd Hoffmann } 1319f1ae32a1SGerd Hoffmann 1320f1ae32a1SGerd Hoffmann /* Set the frame interval - frame interval toggle is manipulated by the hcd only */ 1321f1ae32a1SGerd Hoffmann static void ohci_set_frame_interval(OHCIState *ohci, uint16_t val) 1322f1ae32a1SGerd Hoffmann { 1323f1ae32a1SGerd Hoffmann val &= OHCI_FMI_FI; 1324f1ae32a1SGerd Hoffmann 1325f1ae32a1SGerd Hoffmann if (val != ohci->fi) { 1326f1ae32a1SGerd Hoffmann DPRINTF("usb-ohci: %s: FrameInterval = 0x%x (%u)\n", 1327f1ae32a1SGerd Hoffmann ohci->name, ohci->fi, ohci->fi); 1328f1ae32a1SGerd Hoffmann } 1329f1ae32a1SGerd Hoffmann 1330f1ae32a1SGerd Hoffmann ohci->fi = val; 1331f1ae32a1SGerd Hoffmann } 1332f1ae32a1SGerd Hoffmann 1333f1ae32a1SGerd Hoffmann static void ohci_port_power(OHCIState *ohci, int i, int p) 1334f1ae32a1SGerd Hoffmann { 1335f1ae32a1SGerd Hoffmann if (p) { 1336f1ae32a1SGerd Hoffmann ohci->rhport[i].ctrl |= OHCI_PORT_PPS; 1337f1ae32a1SGerd Hoffmann } else { 1338f1ae32a1SGerd Hoffmann ohci->rhport[i].ctrl &= ~(OHCI_PORT_PPS| 1339f1ae32a1SGerd Hoffmann OHCI_PORT_CCS| 1340f1ae32a1SGerd Hoffmann OHCI_PORT_PSS| 1341f1ae32a1SGerd Hoffmann OHCI_PORT_PRS); 1342f1ae32a1SGerd Hoffmann } 1343f1ae32a1SGerd Hoffmann } 1344f1ae32a1SGerd Hoffmann 1345f1ae32a1SGerd Hoffmann /* Set HcControlRegister */ 1346f1ae32a1SGerd Hoffmann static void ohci_set_ctl(OHCIState *ohci, uint32_t val) 1347f1ae32a1SGerd Hoffmann { 1348f1ae32a1SGerd Hoffmann uint32_t old_state; 1349f1ae32a1SGerd Hoffmann uint32_t new_state; 1350f1ae32a1SGerd Hoffmann 1351f1ae32a1SGerd Hoffmann old_state = ohci->ctl & OHCI_CTL_HCFS; 1352f1ae32a1SGerd Hoffmann ohci->ctl = val; 1353f1ae32a1SGerd Hoffmann new_state = ohci->ctl & OHCI_CTL_HCFS; 1354f1ae32a1SGerd Hoffmann 1355f1ae32a1SGerd Hoffmann /* no state change */ 1356f1ae32a1SGerd Hoffmann if (old_state == new_state) 1357f1ae32a1SGerd Hoffmann return; 1358f1ae32a1SGerd Hoffmann 1359f1ae32a1SGerd Hoffmann switch (new_state) { 1360f1ae32a1SGerd Hoffmann case OHCI_USB_OPERATIONAL: 1361f1ae32a1SGerd Hoffmann ohci_bus_start(ohci); 1362f1ae32a1SGerd Hoffmann break; 1363f1ae32a1SGerd Hoffmann case OHCI_USB_SUSPEND: 1364f1ae32a1SGerd Hoffmann ohci_bus_stop(ohci); 1365f1ae32a1SGerd Hoffmann DPRINTF("usb-ohci: %s: USB Suspended\n", ohci->name); 1366f1ae32a1SGerd Hoffmann break; 1367f1ae32a1SGerd Hoffmann case OHCI_USB_RESUME: 1368f1ae32a1SGerd Hoffmann DPRINTF("usb-ohci: %s: USB Resume\n", ohci->name); 1369f1ae32a1SGerd Hoffmann break; 1370f1ae32a1SGerd Hoffmann case OHCI_USB_RESET: 1371f1ae32a1SGerd Hoffmann ohci_reset(ohci); 1372f1ae32a1SGerd Hoffmann DPRINTF("usb-ohci: %s: USB Reset\n", ohci->name); 1373f1ae32a1SGerd Hoffmann break; 1374f1ae32a1SGerd Hoffmann } 1375f1ae32a1SGerd Hoffmann } 1376f1ae32a1SGerd Hoffmann 1377f1ae32a1SGerd Hoffmann static uint32_t ohci_get_frame_remaining(OHCIState *ohci) 1378f1ae32a1SGerd Hoffmann { 1379f1ae32a1SGerd Hoffmann uint16_t fr; 1380f1ae32a1SGerd Hoffmann int64_t tks; 1381f1ae32a1SGerd Hoffmann 1382f1ae32a1SGerd Hoffmann if ((ohci->ctl & OHCI_CTL_HCFS) != OHCI_USB_OPERATIONAL) 1383f1ae32a1SGerd Hoffmann return (ohci->frt << 31); 1384f1ae32a1SGerd Hoffmann 1385f1ae32a1SGerd Hoffmann /* Being in USB operational state guarnatees sof_time was 1386f1ae32a1SGerd Hoffmann * set already. 1387f1ae32a1SGerd Hoffmann */ 1388f1ae32a1SGerd Hoffmann tks = qemu_get_clock_ns(vm_clock) - ohci->sof_time; 1389f1ae32a1SGerd Hoffmann 1390f1ae32a1SGerd Hoffmann /* avoid muldiv if possible */ 1391f1ae32a1SGerd Hoffmann if (tks >= usb_frame_time) 1392f1ae32a1SGerd Hoffmann return (ohci->frt << 31); 1393f1ae32a1SGerd Hoffmann 1394f1ae32a1SGerd Hoffmann tks = muldiv64(1, tks, usb_bit_time); 1395f1ae32a1SGerd Hoffmann fr = (uint16_t)(ohci->fi - tks); 1396f1ae32a1SGerd Hoffmann 1397f1ae32a1SGerd Hoffmann return (ohci->frt << 31) | fr; 1398f1ae32a1SGerd Hoffmann } 1399f1ae32a1SGerd Hoffmann 1400f1ae32a1SGerd Hoffmann 1401f1ae32a1SGerd Hoffmann /* Set root hub status */ 1402f1ae32a1SGerd Hoffmann static void ohci_set_hub_status(OHCIState *ohci, uint32_t val) 1403f1ae32a1SGerd Hoffmann { 1404f1ae32a1SGerd Hoffmann uint32_t old_state; 1405f1ae32a1SGerd Hoffmann 1406f1ae32a1SGerd Hoffmann old_state = ohci->rhstatus; 1407f1ae32a1SGerd Hoffmann 1408f1ae32a1SGerd Hoffmann /* write 1 to clear OCIC */ 1409f1ae32a1SGerd Hoffmann if (val & OHCI_RHS_OCIC) 1410f1ae32a1SGerd Hoffmann ohci->rhstatus &= ~OHCI_RHS_OCIC; 1411f1ae32a1SGerd Hoffmann 1412f1ae32a1SGerd Hoffmann if (val & OHCI_RHS_LPS) { 1413f1ae32a1SGerd Hoffmann int i; 1414f1ae32a1SGerd Hoffmann 1415f1ae32a1SGerd Hoffmann for (i = 0; i < ohci->num_ports; i++) 1416f1ae32a1SGerd Hoffmann ohci_port_power(ohci, i, 0); 1417f1ae32a1SGerd Hoffmann DPRINTF("usb-ohci: powered down all ports\n"); 1418f1ae32a1SGerd Hoffmann } 1419f1ae32a1SGerd Hoffmann 1420f1ae32a1SGerd Hoffmann if (val & OHCI_RHS_LPSC) { 1421f1ae32a1SGerd Hoffmann int i; 1422f1ae32a1SGerd Hoffmann 1423f1ae32a1SGerd Hoffmann for (i = 0; i < ohci->num_ports; i++) 1424f1ae32a1SGerd Hoffmann ohci_port_power(ohci, i, 1); 1425f1ae32a1SGerd Hoffmann DPRINTF("usb-ohci: powered up all ports\n"); 1426f1ae32a1SGerd Hoffmann } 1427f1ae32a1SGerd Hoffmann 1428f1ae32a1SGerd Hoffmann if (val & OHCI_RHS_DRWE) 1429f1ae32a1SGerd Hoffmann ohci->rhstatus |= OHCI_RHS_DRWE; 1430f1ae32a1SGerd Hoffmann 1431f1ae32a1SGerd Hoffmann if (val & OHCI_RHS_CRWE) 1432f1ae32a1SGerd Hoffmann ohci->rhstatus &= ~OHCI_RHS_DRWE; 1433f1ae32a1SGerd Hoffmann 1434f1ae32a1SGerd Hoffmann if (old_state != ohci->rhstatus) 1435f1ae32a1SGerd Hoffmann ohci_set_interrupt(ohci, OHCI_INTR_RHSC); 1436f1ae32a1SGerd Hoffmann } 1437f1ae32a1SGerd Hoffmann 1438f1ae32a1SGerd Hoffmann /* Set root hub port status */ 1439f1ae32a1SGerd Hoffmann static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val) 1440f1ae32a1SGerd Hoffmann { 1441f1ae32a1SGerd Hoffmann uint32_t old_state; 1442f1ae32a1SGerd Hoffmann OHCIPort *port; 1443f1ae32a1SGerd Hoffmann 1444f1ae32a1SGerd Hoffmann port = &ohci->rhport[portnum]; 1445f1ae32a1SGerd Hoffmann old_state = port->ctrl; 1446f1ae32a1SGerd Hoffmann 1447f1ae32a1SGerd Hoffmann /* Write to clear CSC, PESC, PSSC, OCIC, PRSC */ 1448f1ae32a1SGerd Hoffmann if (val & OHCI_PORT_WTC) 1449f1ae32a1SGerd Hoffmann port->ctrl &= ~(val & OHCI_PORT_WTC); 1450f1ae32a1SGerd Hoffmann 1451f1ae32a1SGerd Hoffmann if (val & OHCI_PORT_CCS) 1452f1ae32a1SGerd Hoffmann port->ctrl &= ~OHCI_PORT_PES; 1453f1ae32a1SGerd Hoffmann 1454f1ae32a1SGerd Hoffmann ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PES); 1455f1ae32a1SGerd Hoffmann 1456f1ae32a1SGerd Hoffmann if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PSS)) { 1457f1ae32a1SGerd Hoffmann DPRINTF("usb-ohci: port %d: SUSPEND\n", portnum); 1458f1ae32a1SGerd Hoffmann } 1459f1ae32a1SGerd Hoffmann 1460f1ae32a1SGerd Hoffmann if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PRS)) { 1461f1ae32a1SGerd Hoffmann DPRINTF("usb-ohci: port %d: RESET\n", portnum); 1462f1ae32a1SGerd Hoffmann usb_device_reset(port->port.dev); 1463f1ae32a1SGerd Hoffmann port->ctrl &= ~OHCI_PORT_PRS; 1464f1ae32a1SGerd Hoffmann /* ??? Should this also set OHCI_PORT_PESC. */ 1465f1ae32a1SGerd Hoffmann port->ctrl |= OHCI_PORT_PES | OHCI_PORT_PRSC; 1466f1ae32a1SGerd Hoffmann } 1467f1ae32a1SGerd Hoffmann 1468f1ae32a1SGerd Hoffmann /* Invert order here to ensure in ambiguous case, device is 1469f1ae32a1SGerd Hoffmann * powered up... 1470f1ae32a1SGerd Hoffmann */ 1471f1ae32a1SGerd Hoffmann if (val & OHCI_PORT_LSDA) 1472f1ae32a1SGerd Hoffmann ohci_port_power(ohci, portnum, 0); 1473f1ae32a1SGerd Hoffmann if (val & OHCI_PORT_PPS) 1474f1ae32a1SGerd Hoffmann ohci_port_power(ohci, portnum, 1); 1475f1ae32a1SGerd Hoffmann 1476f1ae32a1SGerd Hoffmann if (old_state != port->ctrl) 1477f1ae32a1SGerd Hoffmann ohci_set_interrupt(ohci, OHCI_INTR_RHSC); 1478f1ae32a1SGerd Hoffmann } 1479f1ae32a1SGerd Hoffmann 1480f1ae32a1SGerd Hoffmann static uint64_t ohci_mem_read(void *opaque, 1481a8170e5eSAvi Kivity hwaddr addr, 1482f1ae32a1SGerd Hoffmann unsigned size) 1483f1ae32a1SGerd Hoffmann { 1484f1ae32a1SGerd Hoffmann OHCIState *ohci = opaque; 1485f1ae32a1SGerd Hoffmann uint32_t retval; 1486f1ae32a1SGerd Hoffmann 1487f1ae32a1SGerd Hoffmann /* Only aligned reads are allowed on OHCI */ 1488f1ae32a1SGerd Hoffmann if (addr & 3) { 1489f1ae32a1SGerd Hoffmann fprintf(stderr, "usb-ohci: Mis-aligned read\n"); 1490f1ae32a1SGerd Hoffmann return 0xffffffff; 1491f1ae32a1SGerd Hoffmann } else if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) { 1492f1ae32a1SGerd Hoffmann /* HcRhPortStatus */ 1493f1ae32a1SGerd Hoffmann retval = ohci->rhport[(addr - 0x54) >> 2].ctrl | OHCI_PORT_PPS; 1494f1ae32a1SGerd Hoffmann } else { 1495f1ae32a1SGerd Hoffmann switch (addr >> 2) { 1496f1ae32a1SGerd Hoffmann case 0: /* HcRevision */ 1497f1ae32a1SGerd Hoffmann retval = 0x10; 1498f1ae32a1SGerd Hoffmann break; 1499f1ae32a1SGerd Hoffmann 1500f1ae32a1SGerd Hoffmann case 1: /* HcControl */ 1501f1ae32a1SGerd Hoffmann retval = ohci->ctl; 1502f1ae32a1SGerd Hoffmann break; 1503f1ae32a1SGerd Hoffmann 1504f1ae32a1SGerd Hoffmann case 2: /* HcCommandStatus */ 1505f1ae32a1SGerd Hoffmann retval = ohci->status; 1506f1ae32a1SGerd Hoffmann break; 1507f1ae32a1SGerd Hoffmann 1508f1ae32a1SGerd Hoffmann case 3: /* HcInterruptStatus */ 1509f1ae32a1SGerd Hoffmann retval = ohci->intr_status; 1510f1ae32a1SGerd Hoffmann break; 1511f1ae32a1SGerd Hoffmann 1512f1ae32a1SGerd Hoffmann case 4: /* HcInterruptEnable */ 1513f1ae32a1SGerd Hoffmann case 5: /* HcInterruptDisable */ 1514f1ae32a1SGerd Hoffmann retval = ohci->intr; 1515f1ae32a1SGerd Hoffmann break; 1516f1ae32a1SGerd Hoffmann 1517f1ae32a1SGerd Hoffmann case 6: /* HcHCCA */ 1518f1ae32a1SGerd Hoffmann retval = ohci->hcca; 1519f1ae32a1SGerd Hoffmann break; 1520f1ae32a1SGerd Hoffmann 1521f1ae32a1SGerd Hoffmann case 7: /* HcPeriodCurrentED */ 1522f1ae32a1SGerd Hoffmann retval = ohci->per_cur; 1523f1ae32a1SGerd Hoffmann break; 1524f1ae32a1SGerd Hoffmann 1525f1ae32a1SGerd Hoffmann case 8: /* HcControlHeadED */ 1526f1ae32a1SGerd Hoffmann retval = ohci->ctrl_head; 1527f1ae32a1SGerd Hoffmann break; 1528f1ae32a1SGerd Hoffmann 1529f1ae32a1SGerd Hoffmann case 9: /* HcControlCurrentED */ 1530f1ae32a1SGerd Hoffmann retval = ohci->ctrl_cur; 1531f1ae32a1SGerd Hoffmann break; 1532f1ae32a1SGerd Hoffmann 1533f1ae32a1SGerd Hoffmann case 10: /* HcBulkHeadED */ 1534f1ae32a1SGerd Hoffmann retval = ohci->bulk_head; 1535f1ae32a1SGerd Hoffmann break; 1536f1ae32a1SGerd Hoffmann 1537f1ae32a1SGerd Hoffmann case 11: /* HcBulkCurrentED */ 1538f1ae32a1SGerd Hoffmann retval = ohci->bulk_cur; 1539f1ae32a1SGerd Hoffmann break; 1540f1ae32a1SGerd Hoffmann 1541f1ae32a1SGerd Hoffmann case 12: /* HcDoneHead */ 1542f1ae32a1SGerd Hoffmann retval = ohci->done; 1543f1ae32a1SGerd Hoffmann break; 1544f1ae32a1SGerd Hoffmann 1545f1ae32a1SGerd Hoffmann case 13: /* HcFmInterretval */ 1546f1ae32a1SGerd Hoffmann retval = (ohci->fit << 31) | (ohci->fsmps << 16) | (ohci->fi); 1547f1ae32a1SGerd Hoffmann break; 1548f1ae32a1SGerd Hoffmann 1549f1ae32a1SGerd Hoffmann case 14: /* HcFmRemaining */ 1550f1ae32a1SGerd Hoffmann retval = ohci_get_frame_remaining(ohci); 1551f1ae32a1SGerd Hoffmann break; 1552f1ae32a1SGerd Hoffmann 1553f1ae32a1SGerd Hoffmann case 15: /* HcFmNumber */ 1554f1ae32a1SGerd Hoffmann retval = ohci->frame_number; 1555f1ae32a1SGerd Hoffmann break; 1556f1ae32a1SGerd Hoffmann 1557f1ae32a1SGerd Hoffmann case 16: /* HcPeriodicStart */ 1558f1ae32a1SGerd Hoffmann retval = ohci->pstart; 1559f1ae32a1SGerd Hoffmann break; 1560f1ae32a1SGerd Hoffmann 1561f1ae32a1SGerd Hoffmann case 17: /* HcLSThreshold */ 1562f1ae32a1SGerd Hoffmann retval = ohci->lst; 1563f1ae32a1SGerd Hoffmann break; 1564f1ae32a1SGerd Hoffmann 1565f1ae32a1SGerd Hoffmann case 18: /* HcRhDescriptorA */ 1566f1ae32a1SGerd Hoffmann retval = ohci->rhdesc_a; 1567f1ae32a1SGerd Hoffmann break; 1568f1ae32a1SGerd Hoffmann 1569f1ae32a1SGerd Hoffmann case 19: /* HcRhDescriptorB */ 1570f1ae32a1SGerd Hoffmann retval = ohci->rhdesc_b; 1571f1ae32a1SGerd Hoffmann break; 1572f1ae32a1SGerd Hoffmann 1573f1ae32a1SGerd Hoffmann case 20: /* HcRhStatus */ 1574f1ae32a1SGerd Hoffmann retval = ohci->rhstatus; 1575f1ae32a1SGerd Hoffmann break; 1576f1ae32a1SGerd Hoffmann 1577f1ae32a1SGerd Hoffmann /* PXA27x specific registers */ 1578f1ae32a1SGerd Hoffmann case 24: /* HcStatus */ 1579f1ae32a1SGerd Hoffmann retval = ohci->hstatus & ohci->hmask; 1580f1ae32a1SGerd Hoffmann break; 1581f1ae32a1SGerd Hoffmann 1582f1ae32a1SGerd Hoffmann case 25: /* HcHReset */ 1583f1ae32a1SGerd Hoffmann retval = ohci->hreset; 1584f1ae32a1SGerd Hoffmann break; 1585f1ae32a1SGerd Hoffmann 1586f1ae32a1SGerd Hoffmann case 26: /* HcHInterruptEnable */ 1587f1ae32a1SGerd Hoffmann retval = ohci->hmask; 1588f1ae32a1SGerd Hoffmann break; 1589f1ae32a1SGerd Hoffmann 1590f1ae32a1SGerd Hoffmann case 27: /* HcHInterruptTest */ 1591f1ae32a1SGerd Hoffmann retval = ohci->htest; 1592f1ae32a1SGerd Hoffmann break; 1593f1ae32a1SGerd Hoffmann 1594f1ae32a1SGerd Hoffmann default: 1595f1ae32a1SGerd Hoffmann fprintf(stderr, "ohci_read: Bad offset %x\n", (int)addr); 1596f1ae32a1SGerd Hoffmann retval = 0xffffffff; 1597f1ae32a1SGerd Hoffmann } 1598f1ae32a1SGerd Hoffmann } 1599f1ae32a1SGerd Hoffmann 1600f1ae32a1SGerd Hoffmann return retval; 1601f1ae32a1SGerd Hoffmann } 1602f1ae32a1SGerd Hoffmann 1603f1ae32a1SGerd Hoffmann static void ohci_mem_write(void *opaque, 1604a8170e5eSAvi Kivity hwaddr addr, 1605f1ae32a1SGerd Hoffmann uint64_t val, 1606f1ae32a1SGerd Hoffmann unsigned size) 1607f1ae32a1SGerd Hoffmann { 1608f1ae32a1SGerd Hoffmann OHCIState *ohci = opaque; 1609f1ae32a1SGerd Hoffmann 1610f1ae32a1SGerd Hoffmann /* Only aligned reads are allowed on OHCI */ 1611f1ae32a1SGerd Hoffmann if (addr & 3) { 1612f1ae32a1SGerd Hoffmann fprintf(stderr, "usb-ohci: Mis-aligned write\n"); 1613f1ae32a1SGerd Hoffmann return; 1614f1ae32a1SGerd Hoffmann } 1615f1ae32a1SGerd Hoffmann 1616f1ae32a1SGerd Hoffmann if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) { 1617f1ae32a1SGerd Hoffmann /* HcRhPortStatus */ 1618f1ae32a1SGerd Hoffmann ohci_port_set_status(ohci, (addr - 0x54) >> 2, val); 1619f1ae32a1SGerd Hoffmann return; 1620f1ae32a1SGerd Hoffmann } 1621f1ae32a1SGerd Hoffmann 1622f1ae32a1SGerd Hoffmann switch (addr >> 2) { 1623f1ae32a1SGerd Hoffmann case 1: /* HcControl */ 1624f1ae32a1SGerd Hoffmann ohci_set_ctl(ohci, val); 1625f1ae32a1SGerd Hoffmann break; 1626f1ae32a1SGerd Hoffmann 1627f1ae32a1SGerd Hoffmann case 2: /* HcCommandStatus */ 1628f1ae32a1SGerd Hoffmann /* SOC is read-only */ 1629f1ae32a1SGerd Hoffmann val = (val & ~OHCI_STATUS_SOC); 1630f1ae32a1SGerd Hoffmann 1631f1ae32a1SGerd Hoffmann /* Bits written as '0' remain unchanged in the register */ 1632f1ae32a1SGerd Hoffmann ohci->status |= val; 1633f1ae32a1SGerd Hoffmann 1634f1ae32a1SGerd Hoffmann if (ohci->status & OHCI_STATUS_HCR) 1635f1ae32a1SGerd Hoffmann ohci_reset(ohci); 1636f1ae32a1SGerd Hoffmann break; 1637f1ae32a1SGerd Hoffmann 1638f1ae32a1SGerd Hoffmann case 3: /* HcInterruptStatus */ 1639f1ae32a1SGerd Hoffmann ohci->intr_status &= ~val; 1640f1ae32a1SGerd Hoffmann ohci_intr_update(ohci); 1641f1ae32a1SGerd Hoffmann break; 1642f1ae32a1SGerd Hoffmann 1643f1ae32a1SGerd Hoffmann case 4: /* HcInterruptEnable */ 1644f1ae32a1SGerd Hoffmann ohci->intr |= val; 1645f1ae32a1SGerd Hoffmann ohci_intr_update(ohci); 1646f1ae32a1SGerd Hoffmann break; 1647f1ae32a1SGerd Hoffmann 1648f1ae32a1SGerd Hoffmann case 5: /* HcInterruptDisable */ 1649f1ae32a1SGerd Hoffmann ohci->intr &= ~val; 1650f1ae32a1SGerd Hoffmann ohci_intr_update(ohci); 1651f1ae32a1SGerd Hoffmann break; 1652f1ae32a1SGerd Hoffmann 1653f1ae32a1SGerd Hoffmann case 6: /* HcHCCA */ 1654f1ae32a1SGerd Hoffmann ohci->hcca = val & OHCI_HCCA_MASK; 1655f1ae32a1SGerd Hoffmann break; 1656f1ae32a1SGerd Hoffmann 1657f1ae32a1SGerd Hoffmann case 7: /* HcPeriodCurrentED */ 1658f1ae32a1SGerd Hoffmann /* Ignore writes to this read-only register, Linux does them */ 1659f1ae32a1SGerd Hoffmann break; 1660f1ae32a1SGerd Hoffmann 1661f1ae32a1SGerd Hoffmann case 8: /* HcControlHeadED */ 1662f1ae32a1SGerd Hoffmann ohci->ctrl_head = val & OHCI_EDPTR_MASK; 1663f1ae32a1SGerd Hoffmann break; 1664f1ae32a1SGerd Hoffmann 1665f1ae32a1SGerd Hoffmann case 9: /* HcControlCurrentED */ 1666f1ae32a1SGerd Hoffmann ohci->ctrl_cur = val & OHCI_EDPTR_MASK; 1667f1ae32a1SGerd Hoffmann break; 1668f1ae32a1SGerd Hoffmann 1669f1ae32a1SGerd Hoffmann case 10: /* HcBulkHeadED */ 1670f1ae32a1SGerd Hoffmann ohci->bulk_head = val & OHCI_EDPTR_MASK; 1671f1ae32a1SGerd Hoffmann break; 1672f1ae32a1SGerd Hoffmann 1673f1ae32a1SGerd Hoffmann case 11: /* HcBulkCurrentED */ 1674f1ae32a1SGerd Hoffmann ohci->bulk_cur = val & OHCI_EDPTR_MASK; 1675f1ae32a1SGerd Hoffmann break; 1676f1ae32a1SGerd Hoffmann 1677f1ae32a1SGerd Hoffmann case 13: /* HcFmInterval */ 1678f1ae32a1SGerd Hoffmann ohci->fsmps = (val & OHCI_FMI_FSMPS) >> 16; 1679f1ae32a1SGerd Hoffmann ohci->fit = (val & OHCI_FMI_FIT) >> 31; 1680f1ae32a1SGerd Hoffmann ohci_set_frame_interval(ohci, val); 1681f1ae32a1SGerd Hoffmann break; 1682f1ae32a1SGerd Hoffmann 1683f1ae32a1SGerd Hoffmann case 15: /* HcFmNumber */ 1684f1ae32a1SGerd Hoffmann break; 1685f1ae32a1SGerd Hoffmann 1686f1ae32a1SGerd Hoffmann case 16: /* HcPeriodicStart */ 1687f1ae32a1SGerd Hoffmann ohci->pstart = val & 0xffff; 1688f1ae32a1SGerd Hoffmann break; 1689f1ae32a1SGerd Hoffmann 1690f1ae32a1SGerd Hoffmann case 17: /* HcLSThreshold */ 1691f1ae32a1SGerd Hoffmann ohci->lst = val & 0xffff; 1692f1ae32a1SGerd Hoffmann break; 1693f1ae32a1SGerd Hoffmann 1694f1ae32a1SGerd Hoffmann case 18: /* HcRhDescriptorA */ 1695f1ae32a1SGerd Hoffmann ohci->rhdesc_a &= ~OHCI_RHA_RW_MASK; 1696f1ae32a1SGerd Hoffmann ohci->rhdesc_a |= val & OHCI_RHA_RW_MASK; 1697f1ae32a1SGerd Hoffmann break; 1698f1ae32a1SGerd Hoffmann 1699f1ae32a1SGerd Hoffmann case 19: /* HcRhDescriptorB */ 1700f1ae32a1SGerd Hoffmann break; 1701f1ae32a1SGerd Hoffmann 1702f1ae32a1SGerd Hoffmann case 20: /* HcRhStatus */ 1703f1ae32a1SGerd Hoffmann ohci_set_hub_status(ohci, val); 1704f1ae32a1SGerd Hoffmann break; 1705f1ae32a1SGerd Hoffmann 1706f1ae32a1SGerd Hoffmann /* PXA27x specific registers */ 1707f1ae32a1SGerd Hoffmann case 24: /* HcStatus */ 1708f1ae32a1SGerd Hoffmann ohci->hstatus &= ~(val & ohci->hmask); 1709f1ae32a1SGerd Hoffmann 1710f1ae32a1SGerd Hoffmann case 25: /* HcHReset */ 1711f1ae32a1SGerd Hoffmann ohci->hreset = val & ~OHCI_HRESET_FSBIR; 1712f1ae32a1SGerd Hoffmann if (val & OHCI_HRESET_FSBIR) 1713f1ae32a1SGerd Hoffmann ohci_reset(ohci); 1714f1ae32a1SGerd Hoffmann break; 1715f1ae32a1SGerd Hoffmann 1716f1ae32a1SGerd Hoffmann case 26: /* HcHInterruptEnable */ 1717f1ae32a1SGerd Hoffmann ohci->hmask = val; 1718f1ae32a1SGerd Hoffmann break; 1719f1ae32a1SGerd Hoffmann 1720f1ae32a1SGerd Hoffmann case 27: /* HcHInterruptTest */ 1721f1ae32a1SGerd Hoffmann ohci->htest = val; 1722f1ae32a1SGerd Hoffmann break; 1723f1ae32a1SGerd Hoffmann 1724f1ae32a1SGerd Hoffmann default: 1725f1ae32a1SGerd Hoffmann fprintf(stderr, "ohci_write: Bad offset %x\n", (int)addr); 1726f1ae32a1SGerd Hoffmann break; 1727f1ae32a1SGerd Hoffmann } 1728f1ae32a1SGerd Hoffmann } 1729f1ae32a1SGerd Hoffmann 1730f1ae32a1SGerd Hoffmann static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev) 1731f1ae32a1SGerd Hoffmann { 1732f1ae32a1SGerd Hoffmann if (ohci->async_td && 1733f1ae32a1SGerd Hoffmann usb_packet_is_inflight(&ohci->usb_packet) && 1734f1ae32a1SGerd Hoffmann ohci->usb_packet.ep->dev == dev) { 1735f1ae32a1SGerd Hoffmann usb_cancel_packet(&ohci->usb_packet); 1736f1ae32a1SGerd Hoffmann ohci->async_td = 0; 1737f1ae32a1SGerd Hoffmann } 1738f1ae32a1SGerd Hoffmann } 1739f1ae32a1SGerd Hoffmann 1740f1ae32a1SGerd Hoffmann static const MemoryRegionOps ohci_mem_ops = { 1741f1ae32a1SGerd Hoffmann .read = ohci_mem_read, 1742f1ae32a1SGerd Hoffmann .write = ohci_mem_write, 1743f1ae32a1SGerd Hoffmann .endianness = DEVICE_LITTLE_ENDIAN, 1744f1ae32a1SGerd Hoffmann }; 1745f1ae32a1SGerd Hoffmann 1746f1ae32a1SGerd Hoffmann static USBPortOps ohci_port_ops = { 1747f1ae32a1SGerd Hoffmann .attach = ohci_attach, 1748f1ae32a1SGerd Hoffmann .detach = ohci_detach, 1749f1ae32a1SGerd Hoffmann .child_detach = ohci_child_detach, 1750f1ae32a1SGerd Hoffmann .wakeup = ohci_wakeup, 1751f1ae32a1SGerd Hoffmann .complete = ohci_async_complete_packet, 1752f1ae32a1SGerd Hoffmann }; 1753f1ae32a1SGerd Hoffmann 1754f1ae32a1SGerd Hoffmann static USBBusOps ohci_bus_ops = { 1755f1ae32a1SGerd Hoffmann }; 1756f1ae32a1SGerd Hoffmann 1757f1ae32a1SGerd Hoffmann static int usb_ohci_init(OHCIState *ohci, DeviceState *dev, 17589ac6a217SDavid Gibson int num_ports, dma_addr_t localmem_base, 17599ac6a217SDavid Gibson char *masterbus, uint32_t firstport, 17609ac6a217SDavid Gibson DMAContext *dma) 1761f1ae32a1SGerd Hoffmann { 1762f1ae32a1SGerd Hoffmann int i; 1763f1ae32a1SGerd Hoffmann 17649ac6a217SDavid Gibson ohci->dma = dma; 17659ac6a217SDavid Gibson 1766f1ae32a1SGerd Hoffmann if (usb_frame_time == 0) { 1767f1ae32a1SGerd Hoffmann #ifdef OHCI_TIME_WARP 1768f1ae32a1SGerd Hoffmann usb_frame_time = get_ticks_per_sec(); 1769f1ae32a1SGerd Hoffmann usb_bit_time = muldiv64(1, get_ticks_per_sec(), USB_HZ/1000); 1770f1ae32a1SGerd Hoffmann #else 1771f1ae32a1SGerd Hoffmann usb_frame_time = muldiv64(1, get_ticks_per_sec(), 1000); 1772f1ae32a1SGerd Hoffmann if (get_ticks_per_sec() >= USB_HZ) { 1773f1ae32a1SGerd Hoffmann usb_bit_time = muldiv64(1, get_ticks_per_sec(), USB_HZ); 1774f1ae32a1SGerd Hoffmann } else { 1775f1ae32a1SGerd Hoffmann usb_bit_time = 1; 1776f1ae32a1SGerd Hoffmann } 1777f1ae32a1SGerd Hoffmann #endif 1778f1ae32a1SGerd Hoffmann DPRINTF("usb-ohci: usb_bit_time=%" PRId64 " usb_frame_time=%" PRId64 "\n", 1779f1ae32a1SGerd Hoffmann usb_frame_time, usb_bit_time); 1780f1ae32a1SGerd Hoffmann } 1781f1ae32a1SGerd Hoffmann 1782f1ae32a1SGerd Hoffmann ohci->num_ports = num_ports; 1783f1ae32a1SGerd Hoffmann if (masterbus) { 1784f1ae32a1SGerd Hoffmann USBPort *ports[OHCI_MAX_PORTS]; 1785f1ae32a1SGerd Hoffmann for(i = 0; i < num_ports; i++) { 1786f1ae32a1SGerd Hoffmann ports[i] = &ohci->rhport[i].port; 1787f1ae32a1SGerd Hoffmann } 1788f1ae32a1SGerd Hoffmann if (usb_register_companion(masterbus, ports, num_ports, 1789f1ae32a1SGerd Hoffmann firstport, ohci, &ohci_port_ops, 1790f1ae32a1SGerd Hoffmann USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL) != 0) { 1791f1ae32a1SGerd Hoffmann return -1; 1792f1ae32a1SGerd Hoffmann } 1793f1ae32a1SGerd Hoffmann } else { 1794f1ae32a1SGerd Hoffmann usb_bus_new(&ohci->bus, &ohci_bus_ops, dev); 1795f1ae32a1SGerd Hoffmann for (i = 0; i < num_ports; i++) { 1796f1ae32a1SGerd Hoffmann usb_register_port(&ohci->bus, &ohci->rhport[i].port, 1797f1ae32a1SGerd Hoffmann ohci, i, &ohci_port_ops, 1798f1ae32a1SGerd Hoffmann USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL); 1799f1ae32a1SGerd Hoffmann } 1800f1ae32a1SGerd Hoffmann } 1801f1ae32a1SGerd Hoffmann 1802f1ae32a1SGerd Hoffmann memory_region_init_io(&ohci->mem, &ohci_mem_ops, ohci, "ohci", 256); 1803f1ae32a1SGerd Hoffmann ohci->localmem_base = localmem_base; 1804f1ae32a1SGerd Hoffmann 1805f1ae32a1SGerd Hoffmann ohci->name = object_get_typename(OBJECT(dev)); 1806f1ae32a1SGerd Hoffmann usb_packet_init(&ohci->usb_packet); 1807f1ae32a1SGerd Hoffmann 1808f1ae32a1SGerd Hoffmann ohci->async_td = 0; 1809f1ae32a1SGerd Hoffmann qemu_register_reset(ohci_reset, ohci); 1810f1ae32a1SGerd Hoffmann 1811f1ae32a1SGerd Hoffmann return 0; 1812f1ae32a1SGerd Hoffmann } 1813f1ae32a1SGerd Hoffmann 1814f1ae32a1SGerd Hoffmann typedef struct { 1815f1ae32a1SGerd Hoffmann PCIDevice pci_dev; 1816f1ae32a1SGerd Hoffmann OHCIState state; 1817f1ae32a1SGerd Hoffmann char *masterbus; 1818f1ae32a1SGerd Hoffmann uint32_t num_ports; 1819f1ae32a1SGerd Hoffmann uint32_t firstport; 1820f1ae32a1SGerd Hoffmann } OHCIPCIState; 1821f1ae32a1SGerd Hoffmann 1822f1ae32a1SGerd Hoffmann static int usb_ohci_initfn_pci(struct PCIDevice *dev) 1823f1ae32a1SGerd Hoffmann { 1824f1ae32a1SGerd Hoffmann OHCIPCIState *ohci = DO_UPCAST(OHCIPCIState, pci_dev, dev); 1825f1ae32a1SGerd Hoffmann 1826f1ae32a1SGerd Hoffmann ohci->pci_dev.config[PCI_CLASS_PROG] = 0x10; /* OHCI */ 1827f1ae32a1SGerd Hoffmann ohci->pci_dev.config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */ 1828f1ae32a1SGerd Hoffmann 1829f1ae32a1SGerd Hoffmann if (usb_ohci_init(&ohci->state, &dev->qdev, ohci->num_ports, 0, 18309ac6a217SDavid Gibson ohci->masterbus, ohci->firstport, 18319ac6a217SDavid Gibson pci_dma_context(dev)) != 0) { 1832f1ae32a1SGerd Hoffmann return -1; 1833f1ae32a1SGerd Hoffmann } 1834f1ae32a1SGerd Hoffmann ohci->state.irq = ohci->pci_dev.irq[0]; 1835f1ae32a1SGerd Hoffmann 1836f1ae32a1SGerd Hoffmann /* TODO: avoid cast below by using dev */ 1837f1ae32a1SGerd Hoffmann pci_register_bar(&ohci->pci_dev, 0, 0, &ohci->state.mem); 1838f1ae32a1SGerd Hoffmann return 0; 1839f1ae32a1SGerd Hoffmann } 1840f1ae32a1SGerd Hoffmann 1841f1ae32a1SGerd Hoffmann typedef struct { 1842f1ae32a1SGerd Hoffmann SysBusDevice busdev; 1843f1ae32a1SGerd Hoffmann OHCIState ohci; 1844f1ae32a1SGerd Hoffmann uint32_t num_ports; 18459ac6a217SDavid Gibson dma_addr_t dma_offset; 1846f1ae32a1SGerd Hoffmann } OHCISysBusState; 1847f1ae32a1SGerd Hoffmann 1848f1ae32a1SGerd Hoffmann static int ohci_init_pxa(SysBusDevice *dev) 1849f1ae32a1SGerd Hoffmann { 1850f1ae32a1SGerd Hoffmann OHCISysBusState *s = FROM_SYSBUS(OHCISysBusState, dev); 1851f1ae32a1SGerd Hoffmann 1852f1ae32a1SGerd Hoffmann /* Cannot fail as we pass NULL for masterbus */ 18539ac6a217SDavid Gibson usb_ohci_init(&s->ohci, &dev->qdev, s->num_ports, s->dma_offset, NULL, 0, 18549ac6a217SDavid Gibson NULL); 1855f1ae32a1SGerd Hoffmann sysbus_init_irq(dev, &s->ohci.irq); 1856f1ae32a1SGerd Hoffmann sysbus_init_mmio(dev, &s->ohci.mem); 1857f1ae32a1SGerd Hoffmann 1858f1ae32a1SGerd Hoffmann return 0; 1859f1ae32a1SGerd Hoffmann } 1860f1ae32a1SGerd Hoffmann 1861f1ae32a1SGerd Hoffmann static Property ohci_pci_properties[] = { 1862f1ae32a1SGerd Hoffmann DEFINE_PROP_STRING("masterbus", OHCIPCIState, masterbus), 1863f1ae32a1SGerd Hoffmann DEFINE_PROP_UINT32("num-ports", OHCIPCIState, num_ports, 3), 1864f1ae32a1SGerd Hoffmann DEFINE_PROP_UINT32("firstport", OHCIPCIState, firstport, 0), 1865f1ae32a1SGerd Hoffmann DEFINE_PROP_END_OF_LIST(), 1866f1ae32a1SGerd Hoffmann }; 1867f1ae32a1SGerd Hoffmann 1868f1ae32a1SGerd Hoffmann static void ohci_pci_class_init(ObjectClass *klass, void *data) 1869f1ae32a1SGerd Hoffmann { 1870f1ae32a1SGerd Hoffmann DeviceClass *dc = DEVICE_CLASS(klass); 1871f1ae32a1SGerd Hoffmann PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 1872f1ae32a1SGerd Hoffmann 1873f1ae32a1SGerd Hoffmann k->init = usb_ohci_initfn_pci; 1874f1ae32a1SGerd Hoffmann k->vendor_id = PCI_VENDOR_ID_APPLE; 1875f1ae32a1SGerd Hoffmann k->device_id = PCI_DEVICE_ID_APPLE_IPID_USB; 1876f1ae32a1SGerd Hoffmann k->class_id = PCI_CLASS_SERIAL_USB; 1877f1ae32a1SGerd Hoffmann dc->desc = "Apple USB Controller"; 1878f1ae32a1SGerd Hoffmann dc->props = ohci_pci_properties; 1879f1ae32a1SGerd Hoffmann } 1880f1ae32a1SGerd Hoffmann 1881f1ae32a1SGerd Hoffmann static TypeInfo ohci_pci_info = { 1882f1ae32a1SGerd Hoffmann .name = "pci-ohci", 1883f1ae32a1SGerd Hoffmann .parent = TYPE_PCI_DEVICE, 1884f1ae32a1SGerd Hoffmann .instance_size = sizeof(OHCIPCIState), 1885f1ae32a1SGerd Hoffmann .class_init = ohci_pci_class_init, 1886f1ae32a1SGerd Hoffmann }; 1887f1ae32a1SGerd Hoffmann 1888f1ae32a1SGerd Hoffmann static Property ohci_sysbus_properties[] = { 1889f1ae32a1SGerd Hoffmann DEFINE_PROP_UINT32("num-ports", OHCISysBusState, num_ports, 3), 18909ac6a217SDavid Gibson DEFINE_PROP_DMAADDR("dma-offset", OHCISysBusState, dma_offset, 3), 1891f1ae32a1SGerd Hoffmann DEFINE_PROP_END_OF_LIST(), 1892f1ae32a1SGerd Hoffmann }; 1893f1ae32a1SGerd Hoffmann 1894f1ae32a1SGerd Hoffmann static void ohci_sysbus_class_init(ObjectClass *klass, void *data) 1895f1ae32a1SGerd Hoffmann { 1896f1ae32a1SGerd Hoffmann DeviceClass *dc = DEVICE_CLASS(klass); 1897f1ae32a1SGerd Hoffmann SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass); 1898f1ae32a1SGerd Hoffmann 1899f1ae32a1SGerd Hoffmann sbc->init = ohci_init_pxa; 1900f1ae32a1SGerd Hoffmann dc->desc = "OHCI USB Controller"; 1901f1ae32a1SGerd Hoffmann dc->props = ohci_sysbus_properties; 1902f1ae32a1SGerd Hoffmann } 1903f1ae32a1SGerd Hoffmann 1904f1ae32a1SGerd Hoffmann static TypeInfo ohci_sysbus_info = { 1905f1ae32a1SGerd Hoffmann .name = "sysbus-ohci", 1906f1ae32a1SGerd Hoffmann .parent = TYPE_SYS_BUS_DEVICE, 1907f1ae32a1SGerd Hoffmann .instance_size = sizeof(OHCISysBusState), 1908f1ae32a1SGerd Hoffmann .class_init = ohci_sysbus_class_init, 1909f1ae32a1SGerd Hoffmann }; 1910f1ae32a1SGerd Hoffmann 1911f1ae32a1SGerd Hoffmann static void ohci_register_types(void) 1912f1ae32a1SGerd Hoffmann { 1913f1ae32a1SGerd Hoffmann type_register_static(&ohci_pci_info); 1914f1ae32a1SGerd Hoffmann type_register_static(&ohci_sysbus_info); 1915f1ae32a1SGerd Hoffmann } 1916f1ae32a1SGerd Hoffmann 1917f1ae32a1SGerd Hoffmann type_init(ohci_register_types) 1918