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 10bee41971SChetan Pant * version 2.1 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 BIOS work to boot from USB storage 26f1ae32a1SGerd Hoffmann */ 27f1ae32a1SGerd Hoffmann 28e532b2e0SPeter Maydell #include "qemu/osdep.h" 2964552b6bSMarkus Armbruster #include "hw/irq.h" 30da34e65cSMarkus Armbruster #include "qapi/error.h" 310b8fa32fSMarkus Armbruster #include "qemu/module.h" 321de7afc9SPaolo Bonzini #include "qemu/timer.h" 33f1ae32a1SGerd Hoffmann #include "hw/usb.h" 34d6454270SMarkus Armbruster #include "migration/vmstate.h" 35f1ae32a1SGerd Hoffmann #include "hw/sysbus.h" 369ac6a217SDavid Gibson #include "hw/qdev-dma.h" 37a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 38dc1f5988SAlexey Kardashevskiy #include "trace.h" 3934d97308SThomas Huth #include "hcd-ohci.h" 40f1ae32a1SGerd Hoffmann 41f1ae32a1SGerd Hoffmann /* This causes frames to occur 1000x slower */ 42572a6732SBALATON Zoltan /*#define OHCI_TIME_WARP 1*/ 43f1ae32a1SGerd Hoffmann 44ab6b1105SGerd Hoffmann #define ED_LINK_LIMIT 32 4595ed5693SLi Qiang 46f1ae32a1SGerd Hoffmann static int64_t usb_frame_time; 47f1ae32a1SGerd Hoffmann static int64_t usb_bit_time; 48f1ae32a1SGerd Hoffmann 49f1ae32a1SGerd Hoffmann /* Host Controller Communications Area */ 50f1ae32a1SGerd Hoffmann struct ohci_hcca { 51f1ae32a1SGerd Hoffmann uint32_t intr[32]; 52f1ae32a1SGerd Hoffmann uint16_t frame, pad; 53f1ae32a1SGerd Hoffmann uint32_t done; 54f1ae32a1SGerd Hoffmann }; 5586e18caeSWei Yang #define HCCA_WRITEBACK_OFFSET offsetof(struct ohci_hcca, frame) 5686e18caeSWei Yang #define HCCA_WRITEBACK_SIZE 8 /* frame, pad, done */ 5786e18caeSWei Yang 5886e18caeSWei Yang #define ED_WBACK_OFFSET offsetof(struct ohci_ed, head) 5986e18caeSWei Yang #define ED_WBACK_SIZE 4 60f1ae32a1SGerd Hoffmann 6138019462SPhilippe Mathieu-Daudé /* Bitfields for the first word of an Endpoint Descriptor. */ 62f1ae32a1SGerd Hoffmann #define OHCI_ED_FA_SHIFT 0 63f1ae32a1SGerd Hoffmann #define OHCI_ED_FA_MASK (0x7f << OHCI_ED_FA_SHIFT) 64f1ae32a1SGerd Hoffmann #define OHCI_ED_EN_SHIFT 7 65f1ae32a1SGerd Hoffmann #define OHCI_ED_EN_MASK (0xf << OHCI_ED_EN_SHIFT) 66f1ae32a1SGerd Hoffmann #define OHCI_ED_D_SHIFT 11 67f1ae32a1SGerd Hoffmann #define OHCI_ED_D_MASK (3 << OHCI_ED_D_SHIFT) 68f1ae32a1SGerd Hoffmann #define OHCI_ED_S (1 << 13) 69f1ae32a1SGerd Hoffmann #define OHCI_ED_K (1 << 14) 70f1ae32a1SGerd Hoffmann #define OHCI_ED_F (1 << 15) 71f1ae32a1SGerd Hoffmann #define OHCI_ED_MPS_SHIFT 16 72f1ae32a1SGerd Hoffmann #define OHCI_ED_MPS_MASK (0x7ff << OHCI_ED_MPS_SHIFT) 73f1ae32a1SGerd Hoffmann 7438019462SPhilippe Mathieu-Daudé /* Flags in the head field of an Endpoint Descriptor. */ 75f1ae32a1SGerd Hoffmann #define OHCI_ED_H 1 76f1ae32a1SGerd Hoffmann #define OHCI_ED_C 2 77f1ae32a1SGerd Hoffmann 7838019462SPhilippe Mathieu-Daudé /* Bitfields for the first word of a Transfer Descriptor. */ 79f1ae32a1SGerd Hoffmann #define OHCI_TD_R (1 << 18) 80f1ae32a1SGerd Hoffmann #define OHCI_TD_DP_SHIFT 19 81f1ae32a1SGerd Hoffmann #define OHCI_TD_DP_MASK (3 << OHCI_TD_DP_SHIFT) 82f1ae32a1SGerd Hoffmann #define OHCI_TD_DI_SHIFT 21 83f1ae32a1SGerd Hoffmann #define OHCI_TD_DI_MASK (7 << OHCI_TD_DI_SHIFT) 84f1ae32a1SGerd Hoffmann #define OHCI_TD_T0 (1 << 24) 85f1ae32a1SGerd Hoffmann #define OHCI_TD_T1 (1 << 25) 86f1ae32a1SGerd Hoffmann #define OHCI_TD_EC_SHIFT 26 87f1ae32a1SGerd Hoffmann #define OHCI_TD_EC_MASK (3 << OHCI_TD_EC_SHIFT) 88f1ae32a1SGerd Hoffmann #define OHCI_TD_CC_SHIFT 28 89f1ae32a1SGerd Hoffmann #define OHCI_TD_CC_MASK (0xf << OHCI_TD_CC_SHIFT) 90f1ae32a1SGerd Hoffmann 9138019462SPhilippe Mathieu-Daudé /* Bitfields for the first word of an Isochronous Transfer Descriptor. */ 9238019462SPhilippe Mathieu-Daudé /* CC & DI - same as in the General Transfer Descriptor */ 93f1ae32a1SGerd Hoffmann #define OHCI_TD_SF_SHIFT 0 94f1ae32a1SGerd Hoffmann #define OHCI_TD_SF_MASK (0xffff << OHCI_TD_SF_SHIFT) 95f1ae32a1SGerd Hoffmann #define OHCI_TD_FC_SHIFT 24 96f1ae32a1SGerd Hoffmann #define OHCI_TD_FC_MASK (7 << OHCI_TD_FC_SHIFT) 97f1ae32a1SGerd Hoffmann 9838019462SPhilippe Mathieu-Daudé /* Isochronous Transfer Descriptor - Offset / PacketStatusWord */ 99f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_CC_SHIFT 12 100f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_CC_MASK (0xf << OHCI_TD_PSW_CC_SHIFT) 101f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_SIZE_SHIFT 0 102f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_SIZE_MASK (0xfff << OHCI_TD_PSW_SIZE_SHIFT) 103f1ae32a1SGerd Hoffmann 104f1ae32a1SGerd Hoffmann #define OHCI_PAGE_MASK 0xfffff000 105f1ae32a1SGerd Hoffmann #define OHCI_OFFSET_MASK 0xfff 106f1ae32a1SGerd Hoffmann 107f1ae32a1SGerd Hoffmann #define OHCI_DPTR_MASK 0xfffffff0 108f1ae32a1SGerd Hoffmann 109f1ae32a1SGerd Hoffmann #define OHCI_BM(val, field) \ 110f1ae32a1SGerd Hoffmann (((val) & OHCI_##field##_MASK) >> OHCI_##field##_SHIFT) 111f1ae32a1SGerd Hoffmann 112f1ae32a1SGerd Hoffmann #define OHCI_SET_BM(val, field, newval) do { \ 113f1ae32a1SGerd Hoffmann val &= ~OHCI_##field##_MASK; \ 114f1ae32a1SGerd Hoffmann val |= ((newval) << OHCI_##field##_SHIFT) & OHCI_##field##_MASK; \ 115f1ae32a1SGerd Hoffmann } while (0) 116f1ae32a1SGerd Hoffmann 117f1ae32a1SGerd Hoffmann /* endpoint descriptor */ 118f1ae32a1SGerd Hoffmann struct ohci_ed { 119f1ae32a1SGerd Hoffmann uint32_t flags; 120f1ae32a1SGerd Hoffmann uint32_t tail; 121f1ae32a1SGerd Hoffmann uint32_t head; 122f1ae32a1SGerd Hoffmann uint32_t next; 123f1ae32a1SGerd Hoffmann }; 124f1ae32a1SGerd Hoffmann 125f1ae32a1SGerd Hoffmann /* General transfer descriptor */ 126f1ae32a1SGerd Hoffmann struct ohci_td { 127f1ae32a1SGerd Hoffmann uint32_t flags; 128f1ae32a1SGerd Hoffmann uint32_t cbp; 129f1ae32a1SGerd Hoffmann uint32_t next; 130f1ae32a1SGerd Hoffmann uint32_t be; 131f1ae32a1SGerd Hoffmann }; 132f1ae32a1SGerd Hoffmann 133f1ae32a1SGerd Hoffmann /* Isochronous transfer descriptor */ 134f1ae32a1SGerd Hoffmann struct ohci_iso_td { 135f1ae32a1SGerd Hoffmann uint32_t flags; 136f1ae32a1SGerd Hoffmann uint32_t bp; 137f1ae32a1SGerd Hoffmann uint32_t next; 138f1ae32a1SGerd Hoffmann uint32_t be; 139f1ae32a1SGerd Hoffmann uint16_t offset[8]; 140f1ae32a1SGerd Hoffmann }; 141f1ae32a1SGerd Hoffmann 142f1ae32a1SGerd Hoffmann #define USB_HZ 12000000 143f1ae32a1SGerd Hoffmann 144f1ae32a1SGerd Hoffmann /* OHCI Local stuff */ 145f1ae32a1SGerd Hoffmann #define OHCI_CTL_CBSR ((1 << 0) | (1 << 1)) 146f1ae32a1SGerd Hoffmann #define OHCI_CTL_PLE (1 << 2) 147f1ae32a1SGerd Hoffmann #define OHCI_CTL_IE (1 << 3) 148f1ae32a1SGerd Hoffmann #define OHCI_CTL_CLE (1 << 4) 149f1ae32a1SGerd Hoffmann #define OHCI_CTL_BLE (1 << 5) 150f1ae32a1SGerd Hoffmann #define OHCI_CTL_HCFS ((1 << 6) | (1 << 7)) 151f1ae32a1SGerd Hoffmann #define OHCI_USB_RESET 0x00 152f1ae32a1SGerd Hoffmann #define OHCI_USB_RESUME 0x40 153f1ae32a1SGerd Hoffmann #define OHCI_USB_OPERATIONAL 0x80 154f1ae32a1SGerd Hoffmann #define OHCI_USB_SUSPEND 0xc0 155f1ae32a1SGerd Hoffmann #define OHCI_CTL_IR (1 << 8) 156f1ae32a1SGerd Hoffmann #define OHCI_CTL_RWC (1 << 9) 157f1ae32a1SGerd Hoffmann #define OHCI_CTL_RWE (1 << 10) 158f1ae32a1SGerd Hoffmann 159f1ae32a1SGerd Hoffmann #define OHCI_STATUS_HCR (1 << 0) 160f1ae32a1SGerd Hoffmann #define OHCI_STATUS_CLF (1 << 1) 161f1ae32a1SGerd Hoffmann #define OHCI_STATUS_BLF (1 << 2) 162f1ae32a1SGerd Hoffmann #define OHCI_STATUS_OCR (1 << 3) 163f1ae32a1SGerd Hoffmann #define OHCI_STATUS_SOC ((1 << 6) | (1 << 7)) 164f1ae32a1SGerd Hoffmann 16500b01793SPeter Maydell #define OHCI_INTR_SO (1U << 0) /* Scheduling overrun */ 16600b01793SPeter Maydell #define OHCI_INTR_WD (1U << 1) /* HcDoneHead writeback */ 16700b01793SPeter Maydell #define OHCI_INTR_SF (1U << 2) /* Start of frame */ 16800b01793SPeter Maydell #define OHCI_INTR_RD (1U << 3) /* Resume detect */ 16900b01793SPeter Maydell #define OHCI_INTR_UE (1U << 4) /* Unrecoverable error */ 17000b01793SPeter Maydell #define OHCI_INTR_FNO (1U << 5) /* Frame number overflow */ 17100b01793SPeter Maydell #define OHCI_INTR_RHSC (1U << 6) /* Root hub status change */ 17200b01793SPeter Maydell #define OHCI_INTR_OC (1U << 30) /* Ownership change */ 17300b01793SPeter Maydell #define OHCI_INTR_MIE (1U << 31) /* Master Interrupt Enable */ 174f1ae32a1SGerd Hoffmann 175f1ae32a1SGerd Hoffmann #define OHCI_HCCA_SIZE 0x100 176f1ae32a1SGerd Hoffmann #define OHCI_HCCA_MASK 0xffffff00 177f1ae32a1SGerd Hoffmann 178f1ae32a1SGerd Hoffmann #define OHCI_EDPTR_MASK 0xfffffff0 179f1ae32a1SGerd Hoffmann 180f1ae32a1SGerd Hoffmann #define OHCI_FMI_FI 0x00003fff 181f1ae32a1SGerd Hoffmann #define OHCI_FMI_FSMPS 0xffff0000 182f1ae32a1SGerd Hoffmann #define OHCI_FMI_FIT 0x80000000 183f1ae32a1SGerd Hoffmann 18400b01793SPeter Maydell #define OHCI_FR_RT (1U << 31) 185f1ae32a1SGerd Hoffmann 186f1ae32a1SGerd Hoffmann #define OHCI_LS_THRESH 0x628 187f1ae32a1SGerd Hoffmann 188f1ae32a1SGerd Hoffmann #define OHCI_RHA_RW_MASK 0x00000000 /* Mask of supported features. */ 189f1ae32a1SGerd Hoffmann #define OHCI_RHA_PSM (1 << 8) 190f1ae32a1SGerd Hoffmann #define OHCI_RHA_NPS (1 << 9) 191f1ae32a1SGerd Hoffmann #define OHCI_RHA_DT (1 << 10) 192f1ae32a1SGerd Hoffmann #define OHCI_RHA_OCPM (1 << 11) 193f1ae32a1SGerd Hoffmann #define OHCI_RHA_NOCP (1 << 12) 194f1ae32a1SGerd Hoffmann #define OHCI_RHA_POTPGT_MASK 0xff000000 195f1ae32a1SGerd Hoffmann 19600b01793SPeter Maydell #define OHCI_RHS_LPS (1U << 0) 19700b01793SPeter Maydell #define OHCI_RHS_OCI (1U << 1) 19800b01793SPeter Maydell #define OHCI_RHS_DRWE (1U << 15) 19900b01793SPeter Maydell #define OHCI_RHS_LPSC (1U << 16) 20000b01793SPeter Maydell #define OHCI_RHS_OCIC (1U << 17) 20100b01793SPeter Maydell #define OHCI_RHS_CRWE (1U << 31) 202f1ae32a1SGerd Hoffmann 203f1ae32a1SGerd Hoffmann #define OHCI_PORT_CCS (1 << 0) 204f1ae32a1SGerd Hoffmann #define OHCI_PORT_PES (1 << 1) 205f1ae32a1SGerd Hoffmann #define OHCI_PORT_PSS (1 << 2) 206f1ae32a1SGerd Hoffmann #define OHCI_PORT_POCI (1 << 3) 207f1ae32a1SGerd Hoffmann #define OHCI_PORT_PRS (1 << 4) 208f1ae32a1SGerd Hoffmann #define OHCI_PORT_PPS (1 << 8) 209f1ae32a1SGerd Hoffmann #define OHCI_PORT_LSDA (1 << 9) 210f1ae32a1SGerd Hoffmann #define OHCI_PORT_CSC (1 << 16) 211f1ae32a1SGerd Hoffmann #define OHCI_PORT_PESC (1 << 17) 212f1ae32a1SGerd Hoffmann #define OHCI_PORT_PSSC (1 << 18) 213f1ae32a1SGerd Hoffmann #define OHCI_PORT_OCIC (1 << 19) 214f1ae32a1SGerd Hoffmann #define OHCI_PORT_PRSC (1 << 20) 215978c93beSBALATON Zoltan #define OHCI_PORT_WTC (OHCI_PORT_CSC | OHCI_PORT_PESC | \ 216978c93beSBALATON Zoltan OHCI_PORT_PSSC | OHCI_PORT_OCIC | \ 217978c93beSBALATON Zoltan OHCI_PORT_PRSC) 218f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_SETUP 0x0 219f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_OUT 0x1 220f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_IN 0x2 221f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_RESERVED 0x3 222f1ae32a1SGerd Hoffmann 223f1ae32a1SGerd Hoffmann #define OHCI_CC_NOERROR 0x0 224f1ae32a1SGerd Hoffmann #define OHCI_CC_CRC 0x1 225f1ae32a1SGerd Hoffmann #define OHCI_CC_BITSTUFFING 0x2 226f1ae32a1SGerd Hoffmann #define OHCI_CC_DATATOGGLEMISMATCH 0x3 227f1ae32a1SGerd Hoffmann #define OHCI_CC_STALL 0x4 228f1ae32a1SGerd Hoffmann #define OHCI_CC_DEVICENOTRESPONDING 0x5 229f1ae32a1SGerd Hoffmann #define OHCI_CC_PIDCHECKFAILURE 0x6 230f1ae32a1SGerd Hoffmann #define OHCI_CC_UNDEXPETEDPID 0x7 231f1ae32a1SGerd Hoffmann #define OHCI_CC_DATAOVERRUN 0x8 232f1ae32a1SGerd Hoffmann #define OHCI_CC_DATAUNDERRUN 0x9 233f1ae32a1SGerd Hoffmann #define OHCI_CC_BUFFEROVERRUN 0xc 234f1ae32a1SGerd Hoffmann #define OHCI_CC_BUFFERUNDERRUN 0xd 235f1ae32a1SGerd Hoffmann 236f1ae32a1SGerd Hoffmann #define OHCI_HRESET_FSBIR (1 << 0) 237f1ae32a1SGerd Hoffmann 2389ae8d31dSBALATON Zoltan static const char *ohci_reg_names[] = { 2399ae8d31dSBALATON Zoltan "HcRevision", "HcControl", "HcCommandStatus", "HcInterruptStatus", 2409ae8d31dSBALATON Zoltan "HcInterruptEnable", "HcInterruptDisable", "HcHCCA", "HcPeriodCurrentED", 2419ae8d31dSBALATON Zoltan "HcControlHeadED", "HcControlCurrentED", "HcBulkHeadED", "HcBulkCurrentED", 2429ae8d31dSBALATON Zoltan "HcDoneHead", "HcFmInterval", "HcFmRemaining", "HcFmNumber", 2439ae8d31dSBALATON Zoltan "HcPeriodicStart", "HcLSThreshold", "HcRhDescriptorA", "HcRhDescriptorB", 2449ae8d31dSBALATON Zoltan "HcRhStatus" 2459ae8d31dSBALATON Zoltan }; 2469ae8d31dSBALATON Zoltan 2479ae8d31dSBALATON Zoltan static const char *ohci_reg_name(hwaddr addr) 2489ae8d31dSBALATON Zoltan { 2499ae8d31dSBALATON Zoltan if (addr >> 2 < ARRAY_SIZE(ohci_reg_names)) { 2509ae8d31dSBALATON Zoltan return ohci_reg_names[addr >> 2]; 2519ae8d31dSBALATON Zoltan } else { 2529ae8d31dSBALATON Zoltan return "<unknown>"; 2539ae8d31dSBALATON Zoltan } 2549ae8d31dSBALATON Zoltan } 2559ae8d31dSBALATON Zoltan 25672e0c127SThomas Huth static void ohci_die(OHCIState *ohci) 25772e0c127SThomas Huth { 25872e0c127SThomas Huth ohci->ohci_die(ohci); 25972e0c127SThomas Huth } 260cf66ee8eSAlexey Kardashevskiy 261f1ae32a1SGerd Hoffmann /* Update IRQ levels */ 262f1ae32a1SGerd Hoffmann static inline void ohci_intr_update(OHCIState *ohci) 263f1ae32a1SGerd Hoffmann { 264f1ae32a1SGerd Hoffmann int level = 0; 265f1ae32a1SGerd Hoffmann 266f1ae32a1SGerd Hoffmann if ((ohci->intr & OHCI_INTR_MIE) && 267f1ae32a1SGerd Hoffmann (ohci->intr_status & ohci->intr)) 268f1ae32a1SGerd Hoffmann level = 1; 269f1ae32a1SGerd Hoffmann 270f1ae32a1SGerd Hoffmann qemu_set_irq(ohci->irq, level); 271f1ae32a1SGerd Hoffmann } 272f1ae32a1SGerd Hoffmann 273f1ae32a1SGerd Hoffmann /* Set an interrupt */ 274f1ae32a1SGerd Hoffmann static inline void ohci_set_interrupt(OHCIState *ohci, uint32_t intr) 275f1ae32a1SGerd Hoffmann { 276f1ae32a1SGerd Hoffmann ohci->intr_status |= intr; 277f1ae32a1SGerd Hoffmann ohci_intr_update(ohci); 278f1ae32a1SGerd Hoffmann } 279f1ae32a1SGerd Hoffmann 280f1ae32a1SGerd Hoffmann static USBDevice *ohci_find_device(OHCIState *ohci, uint8_t addr) 281f1ae32a1SGerd Hoffmann { 282f1ae32a1SGerd Hoffmann USBDevice *dev; 283f1ae32a1SGerd Hoffmann int i; 284f1ae32a1SGerd Hoffmann 285f1ae32a1SGerd Hoffmann for (i = 0; i < ohci->num_ports; i++) { 286f1ae32a1SGerd Hoffmann if ((ohci->rhport[i].ctrl & OHCI_PORT_PES) == 0) { 287f1ae32a1SGerd Hoffmann continue; 288f1ae32a1SGerd Hoffmann } 289f1ae32a1SGerd Hoffmann dev = usb_find_device(&ohci->rhport[i].port, addr); 290f1ae32a1SGerd Hoffmann if (dev != NULL) { 291f1ae32a1SGerd Hoffmann return dev; 292f1ae32a1SGerd Hoffmann } 293f1ae32a1SGerd Hoffmann } 294f1ae32a1SGerd Hoffmann return NULL; 295f1ae32a1SGerd Hoffmann } 296f1ae32a1SGerd Hoffmann 29734d97308SThomas Huth void ohci_stop_endpoints(OHCIState *ohci) 298f79738b0SHans de Goede { 299f79738b0SHans de Goede USBDevice *dev; 300f79738b0SHans de Goede int i, j; 301f79738b0SHans de Goede 302ae310557SBALATON Zoltan if (ohci->async_td) { 303ae310557SBALATON Zoltan usb_cancel_packet(&ohci->usb_packet); 304ae310557SBALATON Zoltan ohci->async_td = 0; 305ae310557SBALATON Zoltan } 306f79738b0SHans de Goede for (i = 0; i < ohci->num_ports; i++) { 307f79738b0SHans de Goede dev = ohci->rhport[i].port.dev; 308f79738b0SHans de Goede if (dev && dev->attached) { 309f79738b0SHans de Goede usb_device_ep_stopped(dev, &dev->ep_ctl); 310f79738b0SHans de Goede for (j = 0; j < USB_MAX_ENDPOINTS; j++) { 311f79738b0SHans de Goede usb_device_ep_stopped(dev, &dev->ep_in[j]); 312f79738b0SHans de Goede usb_device_ep_stopped(dev, &dev->ep_out[j]); 313f79738b0SHans de Goede } 314f79738b0SHans de Goede } 315f79738b0SHans de Goede } 316f79738b0SHans de Goede } 317f79738b0SHans de Goede 31884d04e21SHervé Poussineau static void ohci_roothub_reset(OHCIState *ohci) 319f1ae32a1SGerd Hoffmann { 320f1ae32a1SGerd Hoffmann OHCIPort *port; 321f1ae32a1SGerd Hoffmann int i; 322f1ae32a1SGerd Hoffmann 323f1ae32a1SGerd Hoffmann ohci_bus_stop(ohci); 32484d04e21SHervé Poussineau ohci->rhdesc_a = OHCI_RHA_NPS | ohci->num_ports; 32584d04e21SHervé Poussineau ohci->rhdesc_b = 0x0; /* Impl. specific */ 32684d04e21SHervé Poussineau ohci->rhstatus = 0; 32784d04e21SHervé Poussineau 32884d04e21SHervé Poussineau for (i = 0; i < ohci->num_ports; i++) { 32984d04e21SHervé Poussineau port = &ohci->rhport[i]; 33084d04e21SHervé Poussineau port->ctrl = 0; 33184d04e21SHervé Poussineau if (port->port.dev && port->port.dev->attached) { 33284d04e21SHervé Poussineau usb_port_reset(&port->port); 33384d04e21SHervé Poussineau } 33484d04e21SHervé Poussineau } 33584d04e21SHervé Poussineau ohci_stop_endpoints(ohci); 33684d04e21SHervé Poussineau } 33784d04e21SHervé Poussineau 33884d04e21SHervé Poussineau /* Reset the controller */ 33984d04e21SHervé Poussineau static void ohci_soft_reset(OHCIState *ohci) 34084d04e21SHervé Poussineau { 34184d04e21SHervé Poussineau trace_usb_ohci_reset(ohci->name); 34284d04e21SHervé Poussineau 34384d04e21SHervé Poussineau ohci_bus_stop(ohci); 34484d04e21SHervé Poussineau ohci->ctl = (ohci->ctl & OHCI_CTL_IR) | OHCI_USB_SUSPEND; 345f1ae32a1SGerd Hoffmann ohci->old_ctl = 0; 346f1ae32a1SGerd Hoffmann ohci->status = 0; 347f1ae32a1SGerd Hoffmann ohci->intr_status = 0; 348f1ae32a1SGerd Hoffmann ohci->intr = OHCI_INTR_MIE; 349f1ae32a1SGerd Hoffmann 350f1ae32a1SGerd Hoffmann ohci->hcca = 0; 351f1ae32a1SGerd Hoffmann ohci->ctrl_head = ohci->ctrl_cur = 0; 352f1ae32a1SGerd Hoffmann ohci->bulk_head = ohci->bulk_cur = 0; 353f1ae32a1SGerd Hoffmann ohci->per_cur = 0; 354f1ae32a1SGerd Hoffmann ohci->done = 0; 355f1ae32a1SGerd Hoffmann ohci->done_count = 7; 356572a6732SBALATON Zoltan /* 357572a6732SBALATON Zoltan * FSMPS is marked TBD in OCHI 1.0, what gives ffs? 358f1ae32a1SGerd Hoffmann * I took the value linux sets ... 359f1ae32a1SGerd Hoffmann */ 360f1ae32a1SGerd Hoffmann ohci->fsmps = 0x2778; 361f1ae32a1SGerd Hoffmann ohci->fi = 0x2edf; 362f1ae32a1SGerd Hoffmann ohci->fit = 0; 363f1ae32a1SGerd Hoffmann ohci->frt = 0; 364f1ae32a1SGerd Hoffmann ohci->frame_number = 0; 365f1ae32a1SGerd Hoffmann ohci->pstart = 0; 366f1ae32a1SGerd Hoffmann ohci->lst = OHCI_LS_THRESH; 36784d04e21SHervé Poussineau } 368f1ae32a1SGerd Hoffmann 36934d97308SThomas Huth void ohci_hard_reset(OHCIState *ohci) 370f1ae32a1SGerd Hoffmann { 37184d04e21SHervé Poussineau ohci_soft_reset(ohci); 37284d04e21SHervé Poussineau ohci->ctl = 0; 37384d04e21SHervé Poussineau ohci_roothub_reset(ohci); 374f1ae32a1SGerd Hoffmann } 375f1ae32a1SGerd Hoffmann 376f1ae32a1SGerd Hoffmann /* Get an array of dwords from main memory */ 377f1ae32a1SGerd Hoffmann static inline int get_dwords(OHCIState *ohci, 3789ac6a217SDavid Gibson dma_addr_t addr, uint32_t *buf, int num) 379f1ae32a1SGerd Hoffmann { 380f1ae32a1SGerd Hoffmann int i; 381f1ae32a1SGerd Hoffmann 382f1ae32a1SGerd Hoffmann addr += ohci->localmem_base; 383f1ae32a1SGerd Hoffmann 384f1ae32a1SGerd Hoffmann for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { 385ba06fe8aSPhilippe Mathieu-Daudé if (dma_memory_read(ohci->as, addr, 386ba06fe8aSPhilippe Mathieu-Daudé buf, sizeof(*buf), MEMTXATTRS_UNSPECIFIED)) { 387cf66ee8eSAlexey Kardashevskiy return -1; 388cf66ee8eSAlexey Kardashevskiy } 389f1ae32a1SGerd Hoffmann *buf = le32_to_cpu(*buf); 390f1ae32a1SGerd Hoffmann } 391f1ae32a1SGerd Hoffmann 392cf66ee8eSAlexey Kardashevskiy return 0; 393f1ae32a1SGerd Hoffmann } 394f1ae32a1SGerd Hoffmann 395f1ae32a1SGerd Hoffmann /* Put an array of dwords in to main memory */ 396f1ae32a1SGerd Hoffmann static inline int put_dwords(OHCIState *ohci, 3979ac6a217SDavid Gibson dma_addr_t addr, uint32_t *buf, int num) 398f1ae32a1SGerd Hoffmann { 399f1ae32a1SGerd Hoffmann int i; 400f1ae32a1SGerd Hoffmann 401f1ae32a1SGerd Hoffmann addr += ohci->localmem_base; 402f1ae32a1SGerd Hoffmann 403f1ae32a1SGerd Hoffmann for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { 404f1ae32a1SGerd Hoffmann uint32_t tmp = cpu_to_le32(*buf); 405ba06fe8aSPhilippe Mathieu-Daudé if (dma_memory_write(ohci->as, addr, 406ba06fe8aSPhilippe Mathieu-Daudé &tmp, sizeof(tmp), MEMTXATTRS_UNSPECIFIED)) { 407cf66ee8eSAlexey Kardashevskiy return -1; 408cf66ee8eSAlexey Kardashevskiy } 409f1ae32a1SGerd Hoffmann } 410f1ae32a1SGerd Hoffmann 411cf66ee8eSAlexey Kardashevskiy return 0; 412f1ae32a1SGerd Hoffmann } 413f1ae32a1SGerd Hoffmann 414f1ae32a1SGerd Hoffmann /* Get an array of words from main memory */ 415f1ae32a1SGerd Hoffmann static inline int get_words(OHCIState *ohci, 4169ac6a217SDavid Gibson dma_addr_t addr, uint16_t *buf, int num) 417f1ae32a1SGerd Hoffmann { 418f1ae32a1SGerd Hoffmann int i; 419f1ae32a1SGerd Hoffmann 420f1ae32a1SGerd Hoffmann addr += ohci->localmem_base; 421f1ae32a1SGerd Hoffmann 422f1ae32a1SGerd Hoffmann for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { 423ba06fe8aSPhilippe Mathieu-Daudé if (dma_memory_read(ohci->as, addr, 424ba06fe8aSPhilippe Mathieu-Daudé buf, sizeof(*buf), MEMTXATTRS_UNSPECIFIED)) { 425cf66ee8eSAlexey Kardashevskiy return -1; 426cf66ee8eSAlexey Kardashevskiy } 427f1ae32a1SGerd Hoffmann *buf = le16_to_cpu(*buf); 428f1ae32a1SGerd Hoffmann } 429f1ae32a1SGerd Hoffmann 430cf66ee8eSAlexey Kardashevskiy return 0; 431f1ae32a1SGerd Hoffmann } 432f1ae32a1SGerd Hoffmann 433f1ae32a1SGerd Hoffmann /* Put an array of words in to main memory */ 434f1ae32a1SGerd Hoffmann static inline int put_words(OHCIState *ohci, 4359ac6a217SDavid Gibson dma_addr_t addr, uint16_t *buf, int num) 436f1ae32a1SGerd Hoffmann { 437f1ae32a1SGerd Hoffmann int i; 438f1ae32a1SGerd Hoffmann 439f1ae32a1SGerd Hoffmann addr += ohci->localmem_base; 440f1ae32a1SGerd Hoffmann 441f1ae32a1SGerd Hoffmann for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { 442f1ae32a1SGerd Hoffmann uint16_t tmp = cpu_to_le16(*buf); 443ba06fe8aSPhilippe Mathieu-Daudé if (dma_memory_write(ohci->as, addr, 444ba06fe8aSPhilippe Mathieu-Daudé &tmp, sizeof(tmp), MEMTXATTRS_UNSPECIFIED)) { 445cf66ee8eSAlexey Kardashevskiy return -1; 446cf66ee8eSAlexey Kardashevskiy } 447f1ae32a1SGerd Hoffmann } 448f1ae32a1SGerd Hoffmann 449cf66ee8eSAlexey Kardashevskiy return 0; 450f1ae32a1SGerd Hoffmann } 451f1ae32a1SGerd Hoffmann 452f1ae32a1SGerd Hoffmann static inline int ohci_read_ed(OHCIState *ohci, 4539ac6a217SDavid Gibson dma_addr_t addr, struct ohci_ed *ed) 454f1ae32a1SGerd Hoffmann { 455f1ae32a1SGerd Hoffmann return get_dwords(ohci, addr, (uint32_t *)ed, sizeof(*ed) >> 2); 456f1ae32a1SGerd Hoffmann } 457f1ae32a1SGerd Hoffmann 458f1ae32a1SGerd Hoffmann static inline int ohci_read_td(OHCIState *ohci, 4599ac6a217SDavid Gibson dma_addr_t addr, struct ohci_td *td) 460f1ae32a1SGerd Hoffmann { 461f1ae32a1SGerd Hoffmann return get_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2); 462f1ae32a1SGerd Hoffmann } 463f1ae32a1SGerd Hoffmann 464f1ae32a1SGerd Hoffmann static inline int ohci_read_iso_td(OHCIState *ohci, 4659ac6a217SDavid Gibson dma_addr_t addr, struct ohci_iso_td *td) 466f1ae32a1SGerd Hoffmann { 467cf66ee8eSAlexey Kardashevskiy return get_dwords(ohci, addr, (uint32_t *)td, 4) || 468cf66ee8eSAlexey Kardashevskiy get_words(ohci, addr + 16, td->offset, 8); 469f1ae32a1SGerd Hoffmann } 470f1ae32a1SGerd Hoffmann 471f1ae32a1SGerd Hoffmann static inline int ohci_read_hcca(OHCIState *ohci, 4729ac6a217SDavid Gibson dma_addr_t addr, struct ohci_hcca *hcca) 473f1ae32a1SGerd Hoffmann { 474ba06fe8aSPhilippe Mathieu-Daudé return dma_memory_read(ohci->as, addr + ohci->localmem_base, hcca, 475ba06fe8aSPhilippe Mathieu-Daudé sizeof(*hcca), MEMTXATTRS_UNSPECIFIED); 476f1ae32a1SGerd Hoffmann } 477f1ae32a1SGerd Hoffmann 478f1ae32a1SGerd Hoffmann static inline int ohci_put_ed(OHCIState *ohci, 4799ac6a217SDavid Gibson dma_addr_t addr, struct ohci_ed *ed) 480f1ae32a1SGerd Hoffmann { 481572a6732SBALATON Zoltan /* 482572a6732SBALATON Zoltan * ed->tail is under control of the HCD. 48386e18caeSWei Yang * Since just ed->head is changed by HC, just write back this 48486e18caeSWei Yang */ 48586e18caeSWei Yang return put_dwords(ohci, addr + ED_WBACK_OFFSET, 48686e18caeSWei Yang (uint32_t *)((char *)ed + ED_WBACK_OFFSET), 48786e18caeSWei Yang ED_WBACK_SIZE >> 2); 488f1ae32a1SGerd Hoffmann } 489f1ae32a1SGerd Hoffmann 490f1ae32a1SGerd Hoffmann static inline int ohci_put_td(OHCIState *ohci, 4919ac6a217SDavid Gibson dma_addr_t addr, struct ohci_td *td) 492f1ae32a1SGerd Hoffmann { 493f1ae32a1SGerd Hoffmann return put_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2); 494f1ae32a1SGerd Hoffmann } 495f1ae32a1SGerd Hoffmann 496f1ae32a1SGerd Hoffmann static inline int ohci_put_iso_td(OHCIState *ohci, 4979ac6a217SDavid Gibson dma_addr_t addr, struct ohci_iso_td *td) 498f1ae32a1SGerd Hoffmann { 499cae7f29cSJack Un return put_dwords(ohci, addr, (uint32_t *)td, 4) || 500cae7f29cSJack Un put_words(ohci, addr + 16, td->offset, 8); 501f1ae32a1SGerd Hoffmann } 502f1ae32a1SGerd Hoffmann 503f1ae32a1SGerd Hoffmann static inline int ohci_put_hcca(OHCIState *ohci, 5049ac6a217SDavid Gibson dma_addr_t addr, struct ohci_hcca *hcca) 505f1ae32a1SGerd Hoffmann { 506cf66ee8eSAlexey Kardashevskiy return dma_memory_write(ohci->as, 5079ac6a217SDavid Gibson addr + ohci->localmem_base + HCCA_WRITEBACK_OFFSET, 50886e18caeSWei Yang (char *)hcca + HCCA_WRITEBACK_OFFSET, 509ba06fe8aSPhilippe Mathieu-Daudé HCCA_WRITEBACK_SIZE, MEMTXATTRS_UNSPECIFIED); 510f1ae32a1SGerd Hoffmann } 511f1ae32a1SGerd Hoffmann 512f1ae32a1SGerd Hoffmann /* Read/Write the contents of a TD from/to main memory. */ 513cf66ee8eSAlexey Kardashevskiy static int ohci_copy_td(OHCIState *ohci, struct ohci_td *td, 5149ac6a217SDavid Gibson uint8_t *buf, int len, DMADirection dir) 515f1ae32a1SGerd Hoffmann { 5169ac6a217SDavid Gibson dma_addr_t ptr, n; 517f1ae32a1SGerd Hoffmann 518f1ae32a1SGerd Hoffmann ptr = td->cbp; 519f1ae32a1SGerd Hoffmann n = 0x1000 - (ptr & 0xfff); 5201e58e7a0SBALATON Zoltan if (n > len) { 521f1ae32a1SGerd Hoffmann n = len; 5221e58e7a0SBALATON Zoltan } 52323faf569SPhilippe Mathieu-Daudé if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, 52423faf569SPhilippe Mathieu-Daudé n, dir, MEMTXATTRS_UNSPECIFIED)) { 525cf66ee8eSAlexey Kardashevskiy return -1; 526cf66ee8eSAlexey Kardashevskiy } 527cf66ee8eSAlexey Kardashevskiy if (n == len) { 528cf66ee8eSAlexey Kardashevskiy return 0; 529cf66ee8eSAlexey Kardashevskiy } 530f1ae32a1SGerd Hoffmann ptr = td->be & ~0xfffu; 531f1ae32a1SGerd Hoffmann buf += n; 532cf66ee8eSAlexey Kardashevskiy if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, 53323faf569SPhilippe Mathieu-Daudé len - n, dir, MEMTXATTRS_UNSPECIFIED)) { 534cf66ee8eSAlexey Kardashevskiy return -1; 535cf66ee8eSAlexey Kardashevskiy } 536cf66ee8eSAlexey Kardashevskiy return 0; 537f1ae32a1SGerd Hoffmann } 538f1ae32a1SGerd Hoffmann 539f1ae32a1SGerd Hoffmann /* Read/Write the contents of an ISO TD from/to main memory. */ 540cf66ee8eSAlexey Kardashevskiy static int ohci_copy_iso_td(OHCIState *ohci, 541f1ae32a1SGerd Hoffmann uint32_t start_addr, uint32_t end_addr, 5429ac6a217SDavid Gibson uint8_t *buf, int len, DMADirection dir) 543f1ae32a1SGerd Hoffmann { 5449ac6a217SDavid Gibson dma_addr_t ptr, n; 545f1ae32a1SGerd Hoffmann 546f1ae32a1SGerd Hoffmann ptr = start_addr; 547f1ae32a1SGerd Hoffmann n = 0x1000 - (ptr & 0xfff); 5481e58e7a0SBALATON Zoltan if (n > len) { 549f1ae32a1SGerd Hoffmann n = len; 5501e58e7a0SBALATON Zoltan } 55123faf569SPhilippe Mathieu-Daudé if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, 55223faf569SPhilippe Mathieu-Daudé n, dir, MEMTXATTRS_UNSPECIFIED)) { 553cf66ee8eSAlexey Kardashevskiy return -1; 554cf66ee8eSAlexey Kardashevskiy } 555cf66ee8eSAlexey Kardashevskiy if (n == len) { 556cf66ee8eSAlexey Kardashevskiy return 0; 557cf66ee8eSAlexey Kardashevskiy } 558f1ae32a1SGerd Hoffmann ptr = end_addr & ~0xfffu; 559f1ae32a1SGerd Hoffmann buf += n; 560cf66ee8eSAlexey Kardashevskiy if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, 56123faf569SPhilippe Mathieu-Daudé len - n, dir, MEMTXATTRS_UNSPECIFIED)) { 562cf66ee8eSAlexey Kardashevskiy return -1; 563cf66ee8eSAlexey Kardashevskiy } 564cf66ee8eSAlexey Kardashevskiy return 0; 565f1ae32a1SGerd Hoffmann } 566f1ae32a1SGerd Hoffmann 567f1ae32a1SGerd Hoffmann #define USUB(a, b) ((int16_t)((uint16_t)(a) - (uint16_t)(b))) 568f1ae32a1SGerd Hoffmann 5693a4d06f2SBALATON Zoltan static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed) 570f1ae32a1SGerd Hoffmann { 571f1ae32a1SGerd Hoffmann int dir; 572f1ae32a1SGerd Hoffmann size_t len = 0; 573f1ae32a1SGerd Hoffmann const char *str = NULL; 574f1ae32a1SGerd Hoffmann int pid; 575f1ae32a1SGerd Hoffmann int ret; 576f1ae32a1SGerd Hoffmann int i; 577f1ae32a1SGerd Hoffmann USBDevice *dev; 578f1ae32a1SGerd Hoffmann USBEndpoint *ep; 5793a4d06f2SBALATON Zoltan USBPacket *pkt; 5803a4d06f2SBALATON Zoltan uint8_t buf[8192]; 5813a4d06f2SBALATON Zoltan bool int_req; 582f1ae32a1SGerd Hoffmann struct ohci_iso_td iso_td; 583f1ae32a1SGerd Hoffmann uint32_t addr; 584f1ae32a1SGerd Hoffmann uint16_t starting_frame; 585f1ae32a1SGerd Hoffmann int16_t relative_frame_number; 586f1ae32a1SGerd Hoffmann int frame_count; 587f1ae32a1SGerd Hoffmann uint32_t start_offset, next_offset, end_offset = 0; 588f1ae32a1SGerd Hoffmann uint32_t start_addr, end_addr; 589f1ae32a1SGerd Hoffmann 590f1ae32a1SGerd Hoffmann addr = ed->head & OHCI_DPTR_MASK; 591f1ae32a1SGerd Hoffmann 592d8c2e6f2SQiang Liu if (addr == 0) { 593d8c2e6f2SQiang Liu ohci_die(ohci); 594d8c2e6f2SQiang Liu return 1; 595d8c2e6f2SQiang Liu } 596d8c2e6f2SQiang Liu 597cf66ee8eSAlexey Kardashevskiy if (ohci_read_iso_td(ohci, addr, &iso_td)) { 598dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_read_failed(addr); 599cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 60026f670a2SLi Qiang return 1; 601f1ae32a1SGerd Hoffmann } 602f1ae32a1SGerd Hoffmann 603f1ae32a1SGerd Hoffmann starting_frame = OHCI_BM(iso_td.flags, TD_SF); 604f1ae32a1SGerd Hoffmann frame_count = OHCI_BM(iso_td.flags, TD_FC); 605f1ae32a1SGerd Hoffmann relative_frame_number = USUB(ohci->frame_number, starting_frame); 606f1ae32a1SGerd Hoffmann 607dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_head( 608f1ae32a1SGerd Hoffmann ed->head & OHCI_DPTR_MASK, ed->tail & OHCI_DPTR_MASK, 609f1ae32a1SGerd Hoffmann iso_td.flags, iso_td.bp, iso_td.next, iso_td.be, 610f1ae32a1SGerd Hoffmann ohci->frame_number, starting_frame, 611bc0d104cSAlex Bennée frame_count, relative_frame_number); 6123af8f177SAlexey Kardashevskiy trace_usb_ohci_iso_td_head_offset( 6133af8f177SAlexey Kardashevskiy iso_td.offset[0], iso_td.offset[1], 6143af8f177SAlexey Kardashevskiy iso_td.offset[2], iso_td.offset[3], 6153af8f177SAlexey Kardashevskiy iso_td.offset[4], iso_td.offset[5], 6163af8f177SAlexey Kardashevskiy iso_td.offset[6], iso_td.offset[7]); 617f1ae32a1SGerd Hoffmann 618f1ae32a1SGerd Hoffmann if (relative_frame_number < 0) { 619dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_relative_frame_number_neg(relative_frame_number); 620f1ae32a1SGerd Hoffmann return 1; 621f1ae32a1SGerd Hoffmann } else if (relative_frame_number > frame_count) { 622572a6732SBALATON Zoltan /* 623572a6732SBALATON Zoltan * ISO TD expired - retire the TD to the Done Queue and continue with 624572a6732SBALATON Zoltan * the next ISO TD of the same ED 625572a6732SBALATON Zoltan */ 626dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_relative_frame_number_big(relative_frame_number, 627f1ae32a1SGerd Hoffmann frame_count); 6281be90ebeSPrasad J Pandit if (OHCI_CC_DATAOVERRUN == OHCI_BM(iso_td.flags, TD_CC)) { 6291be90ebeSPrasad J Pandit /* avoid infinite loop */ 6301be90ebeSPrasad J Pandit return 1; 6311be90ebeSPrasad J Pandit } 632f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_DATAOVERRUN); 633f1ae32a1SGerd Hoffmann ed->head &= ~OHCI_DPTR_MASK; 634f1ae32a1SGerd Hoffmann ed->head |= (iso_td.next & OHCI_DPTR_MASK); 635f1ae32a1SGerd Hoffmann iso_td.next = ohci->done; 636f1ae32a1SGerd Hoffmann ohci->done = addr; 637f1ae32a1SGerd Hoffmann i = OHCI_BM(iso_td.flags, TD_DI); 6381e58e7a0SBALATON Zoltan if (i < ohci->done_count) { 639f1ae32a1SGerd Hoffmann ohci->done_count = i; 6401e58e7a0SBALATON Zoltan } 641cf66ee8eSAlexey Kardashevskiy if (ohci_put_iso_td(ohci, addr, &iso_td)) { 642cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 643cf66ee8eSAlexey Kardashevskiy return 1; 644cf66ee8eSAlexey Kardashevskiy } 645f1ae32a1SGerd Hoffmann return 0; 646f1ae32a1SGerd Hoffmann } 647f1ae32a1SGerd Hoffmann 648f1ae32a1SGerd Hoffmann dir = OHCI_BM(ed->flags, ED_D); 649f1ae32a1SGerd Hoffmann switch (dir) { 650f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_IN: 651f1ae32a1SGerd Hoffmann str = "in"; 652f1ae32a1SGerd Hoffmann pid = USB_TOKEN_IN; 653f1ae32a1SGerd Hoffmann break; 654f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_OUT: 655f1ae32a1SGerd Hoffmann str = "out"; 656f1ae32a1SGerd Hoffmann pid = USB_TOKEN_OUT; 657f1ae32a1SGerd Hoffmann break; 658f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_SETUP: 659f1ae32a1SGerd Hoffmann str = "setup"; 660f1ae32a1SGerd Hoffmann pid = USB_TOKEN_SETUP; 661f1ae32a1SGerd Hoffmann break; 662f1ae32a1SGerd Hoffmann default: 663dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_bad_direction(dir); 664f1ae32a1SGerd Hoffmann return 1; 665f1ae32a1SGerd Hoffmann } 666f1ae32a1SGerd Hoffmann 667f1ae32a1SGerd Hoffmann if (!iso_td.bp || !iso_td.be) { 668dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_bad_bp_be(iso_td.bp, iso_td.be); 669f1ae32a1SGerd Hoffmann return 1; 670f1ae32a1SGerd Hoffmann } 671f1ae32a1SGerd Hoffmann 672f1ae32a1SGerd Hoffmann start_offset = iso_td.offset[relative_frame_number]; 6731328fe0cSPrasad J Pandit if (relative_frame_number < frame_count) { 674f1ae32a1SGerd Hoffmann next_offset = iso_td.offset[relative_frame_number + 1]; 6751328fe0cSPrasad J Pandit } else { 6761328fe0cSPrasad J Pandit next_offset = iso_td.be; 6771328fe0cSPrasad J Pandit } 678f1ae32a1SGerd Hoffmann 679f1ae32a1SGerd Hoffmann if (!(OHCI_BM(start_offset, TD_PSW_CC) & 0xe) || 680f1ae32a1SGerd Hoffmann ((relative_frame_number < frame_count) && 681f1ae32a1SGerd Hoffmann !(OHCI_BM(next_offset, TD_PSW_CC) & 0xe))) { 682dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_bad_cc_not_accessed(start_offset, next_offset); 683f1ae32a1SGerd Hoffmann return 1; 684f1ae32a1SGerd Hoffmann } 685f1ae32a1SGerd Hoffmann 686f1ae32a1SGerd Hoffmann if ((relative_frame_number < frame_count) && (start_offset > next_offset)) { 687dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_bad_cc_overrun(start_offset, next_offset); 688f1ae32a1SGerd Hoffmann return 1; 689f1ae32a1SGerd Hoffmann } 690f1ae32a1SGerd Hoffmann 691f1ae32a1SGerd Hoffmann if ((start_offset & 0x1000) == 0) { 692f1ae32a1SGerd Hoffmann start_addr = (iso_td.bp & OHCI_PAGE_MASK) | 693f1ae32a1SGerd Hoffmann (start_offset & OHCI_OFFSET_MASK); 694f1ae32a1SGerd Hoffmann } else { 695f1ae32a1SGerd Hoffmann start_addr = (iso_td.be & OHCI_PAGE_MASK) | 696f1ae32a1SGerd Hoffmann (start_offset & OHCI_OFFSET_MASK); 697f1ae32a1SGerd Hoffmann } 698f1ae32a1SGerd Hoffmann 699f1ae32a1SGerd Hoffmann if (relative_frame_number < frame_count) { 700f1ae32a1SGerd Hoffmann end_offset = next_offset - 1; 701f1ae32a1SGerd Hoffmann if ((end_offset & 0x1000) == 0) { 702f1ae32a1SGerd Hoffmann end_addr = (iso_td.bp & OHCI_PAGE_MASK) | 703f1ae32a1SGerd Hoffmann (end_offset & OHCI_OFFSET_MASK); 704f1ae32a1SGerd Hoffmann } else { 705f1ae32a1SGerd Hoffmann end_addr = (iso_td.be & OHCI_PAGE_MASK) | 706f1ae32a1SGerd Hoffmann (end_offset & OHCI_OFFSET_MASK); 707f1ae32a1SGerd Hoffmann } 708f1ae32a1SGerd Hoffmann } else { 709f1ae32a1SGerd Hoffmann /* Last packet in the ISO TD */ 7101328fe0cSPrasad J Pandit end_addr = next_offset; 7111328fe0cSPrasad J Pandit } 7121328fe0cSPrasad J Pandit 7131328fe0cSPrasad J Pandit if (start_addr > end_addr) { 7141328fe0cSPrasad J Pandit trace_usb_ohci_iso_td_bad_cc_overrun(start_addr, end_addr); 7151328fe0cSPrasad J Pandit return 1; 716f1ae32a1SGerd Hoffmann } 717f1ae32a1SGerd Hoffmann 718f1ae32a1SGerd Hoffmann if ((start_addr & OHCI_PAGE_MASK) != (end_addr & OHCI_PAGE_MASK)) { 719f1ae32a1SGerd Hoffmann len = (end_addr & OHCI_OFFSET_MASK) + 0x1001 720f1ae32a1SGerd Hoffmann - (start_addr & OHCI_OFFSET_MASK); 721f1ae32a1SGerd Hoffmann } else { 722f1ae32a1SGerd Hoffmann len = end_addr - start_addr + 1; 723f1ae32a1SGerd Hoffmann } 7243a4d06f2SBALATON Zoltan if (len > sizeof(buf)) { 7253a4d06f2SBALATON Zoltan len = sizeof(buf); 7261328fe0cSPrasad J Pandit } 727f1ae32a1SGerd Hoffmann 728f1ae32a1SGerd Hoffmann if (len && dir != OHCI_TD_DIR_IN) { 7293a4d06f2SBALATON Zoltan if (ohci_copy_iso_td(ohci, start_addr, end_addr, buf, len, 730cf66ee8eSAlexey Kardashevskiy DMA_DIRECTION_TO_DEVICE)) { 731cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 732cf66ee8eSAlexey Kardashevskiy return 1; 733cf66ee8eSAlexey Kardashevskiy } 734f1ae32a1SGerd Hoffmann } 735f1ae32a1SGerd Hoffmann 736f1ae32a1SGerd Hoffmann dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA)); 73742340fc3SLiam Merwick if (dev == NULL) { 73842340fc3SLiam Merwick trace_usb_ohci_td_dev_error(); 73942340fc3SLiam Merwick return 1; 74042340fc3SLiam Merwick } 741f1ae32a1SGerd Hoffmann ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN)); 7423a4d06f2SBALATON Zoltan pkt = g_new0(USBPacket, 1); 7433a4d06f2SBALATON Zoltan usb_packet_init(pkt); 7443a4d06f2SBALATON Zoltan int_req = relative_frame_number == frame_count && 7453a4d06f2SBALATON Zoltan OHCI_BM(iso_td.flags, TD_DI) == 0; 7463a4d06f2SBALATON Zoltan usb_packet_setup(pkt, pid, ep, 0, addr, false, int_req); 7473a4d06f2SBALATON Zoltan usb_packet_addbuf(pkt, buf, len); 7483a4d06f2SBALATON Zoltan usb_handle_packet(dev, pkt); 7493a4d06f2SBALATON Zoltan if (pkt->status == USB_RET_ASYNC) { 75036dfe324SHans de Goede usb_device_flush_ep_queue(dev, ep); 7513a4d06f2SBALATON Zoltan g_free(pkt); 752f1ae32a1SGerd Hoffmann return 1; 753f1ae32a1SGerd Hoffmann } 7543a4d06f2SBALATON Zoltan if (pkt->status == USB_RET_SUCCESS) { 7553a4d06f2SBALATON Zoltan ret = pkt->actual_length; 7569a77a0f5SHans de Goede } else { 7573a4d06f2SBALATON Zoltan ret = pkt->status; 7589a77a0f5SHans de Goede } 7593a4d06f2SBALATON Zoltan g_free(pkt); 760f1ae32a1SGerd Hoffmann 761dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_so(start_offset, end_offset, start_addr, end_addr, 762dc1f5988SAlexey Kardashevskiy str, len, ret); 763f1ae32a1SGerd Hoffmann 764f1ae32a1SGerd Hoffmann /* Writeback */ 765f1ae32a1SGerd Hoffmann if (dir == OHCI_TD_DIR_IN && ret >= 0 && ret <= len) { 766f1ae32a1SGerd Hoffmann /* IN transfer succeeded */ 7673a4d06f2SBALATON Zoltan if (ohci_copy_iso_td(ohci, start_addr, end_addr, buf, ret, 768cf66ee8eSAlexey Kardashevskiy DMA_DIRECTION_FROM_DEVICE)) { 769cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 770cf66ee8eSAlexey Kardashevskiy return 1; 771cf66ee8eSAlexey Kardashevskiy } 772f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 773f1ae32a1SGerd Hoffmann OHCI_CC_NOERROR); 774f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, ret); 775f1ae32a1SGerd Hoffmann } else if (dir == OHCI_TD_DIR_OUT && ret == len) { 776f1ae32a1SGerd Hoffmann /* OUT transfer succeeded */ 777f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 778f1ae32a1SGerd Hoffmann OHCI_CC_NOERROR); 779f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 0); 780f1ae32a1SGerd Hoffmann } else { 781f1ae32a1SGerd Hoffmann if (ret > (ssize_t) len) { 782dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_data_overrun(ret, len); 783f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 784f1ae32a1SGerd Hoffmann OHCI_CC_DATAOVERRUN); 785f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 786f1ae32a1SGerd Hoffmann len); 787f1ae32a1SGerd Hoffmann } else if (ret >= 0) { 788dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_data_underrun(ret); 789f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 790f1ae32a1SGerd Hoffmann OHCI_CC_DATAUNDERRUN); 791f1ae32a1SGerd Hoffmann } else { 792f1ae32a1SGerd Hoffmann switch (ret) { 793f1ae32a1SGerd Hoffmann case USB_RET_IOERROR: 794f1ae32a1SGerd Hoffmann case USB_RET_NODEV: 795f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 796f1ae32a1SGerd Hoffmann OHCI_CC_DEVICENOTRESPONDING); 797f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 798f1ae32a1SGerd Hoffmann 0); 799f1ae32a1SGerd Hoffmann break; 800f1ae32a1SGerd Hoffmann case USB_RET_NAK: 801f1ae32a1SGerd Hoffmann case USB_RET_STALL: 802dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_nak(ret); 803f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 804f1ae32a1SGerd Hoffmann OHCI_CC_STALL); 805f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 806f1ae32a1SGerd Hoffmann 0); 807f1ae32a1SGerd Hoffmann break; 808f1ae32a1SGerd Hoffmann default: 809dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_bad_response(ret); 810f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 811f1ae32a1SGerd Hoffmann OHCI_CC_UNDEXPETEDPID); 812f1ae32a1SGerd Hoffmann break; 813f1ae32a1SGerd Hoffmann } 814f1ae32a1SGerd Hoffmann } 815f1ae32a1SGerd Hoffmann } 816f1ae32a1SGerd Hoffmann 817f1ae32a1SGerd Hoffmann if (relative_frame_number == frame_count) { 818f1ae32a1SGerd Hoffmann /* Last data packet of ISO TD - retire the TD to the Done Queue */ 819f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_NOERROR); 820f1ae32a1SGerd Hoffmann ed->head &= ~OHCI_DPTR_MASK; 821f1ae32a1SGerd Hoffmann ed->head |= (iso_td.next & OHCI_DPTR_MASK); 822f1ae32a1SGerd Hoffmann iso_td.next = ohci->done; 823f1ae32a1SGerd Hoffmann ohci->done = addr; 824f1ae32a1SGerd Hoffmann i = OHCI_BM(iso_td.flags, TD_DI); 8251e58e7a0SBALATON Zoltan if (i < ohci->done_count) { 826f1ae32a1SGerd Hoffmann ohci->done_count = i; 827f1ae32a1SGerd Hoffmann } 8281e58e7a0SBALATON Zoltan } 829cf66ee8eSAlexey Kardashevskiy if (ohci_put_iso_td(ohci, addr, &iso_td)) { 830cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 831cf66ee8eSAlexey Kardashevskiy } 832f1ae32a1SGerd Hoffmann return 1; 833f1ae32a1SGerd Hoffmann } 834f1ae32a1SGerd Hoffmann 83529d81e42SPhilippe Mathieu-Daudé #define HEX_CHAR_PER_LINE 16 83629d81e42SPhilippe Mathieu-Daudé 837dc1f5988SAlexey Kardashevskiy static void ohci_td_pkt(const char *msg, const uint8_t *buf, size_t len) 838dc1f5988SAlexey Kardashevskiy { 839d87aa138SStefan Hajnoczi bool print16; 840d87aa138SStefan Hajnoczi bool printall; 841dc1f5988SAlexey Kardashevskiy int i; 84229d81e42SPhilippe Mathieu-Daudé char tmp[3 * HEX_CHAR_PER_LINE + 1]; 843dc1f5988SAlexey Kardashevskiy char *p = tmp; 844dc1f5988SAlexey Kardashevskiy 845d87aa138SStefan Hajnoczi print16 = !!trace_event_get_state_backends(TRACE_USB_OHCI_TD_PKT_SHORT); 846d87aa138SStefan Hajnoczi printall = !!trace_event_get_state_backends(TRACE_USB_OHCI_TD_PKT_FULL); 847d87aa138SStefan Hajnoczi 848dc1f5988SAlexey Kardashevskiy if (!printall && !print16) { 849dc1f5988SAlexey Kardashevskiy return; 850dc1f5988SAlexey Kardashevskiy } 851dc1f5988SAlexey Kardashevskiy 852dc1f5988SAlexey Kardashevskiy for (i = 0; ; i++) { 85329d81e42SPhilippe Mathieu-Daudé if (i && (!(i % HEX_CHAR_PER_LINE) || (i == len))) { 854dc1f5988SAlexey Kardashevskiy if (!printall) { 855dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_pkt_short(msg, tmp); 856dc1f5988SAlexey Kardashevskiy break; 857dc1f5988SAlexey Kardashevskiy } 858dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_pkt_full(msg, tmp); 859dc1f5988SAlexey Kardashevskiy p = tmp; 860dc1f5988SAlexey Kardashevskiy *p = 0; 861dc1f5988SAlexey Kardashevskiy } 862dc1f5988SAlexey Kardashevskiy if (i == len) { 863dc1f5988SAlexey Kardashevskiy break; 864dc1f5988SAlexey Kardashevskiy } 865dc1f5988SAlexey Kardashevskiy 866dc1f5988SAlexey Kardashevskiy p += sprintf(p, " %.2x", buf[i]); 867dc1f5988SAlexey Kardashevskiy } 868dc1f5988SAlexey Kardashevskiy } 869dc1f5988SAlexey Kardashevskiy 870572a6732SBALATON Zoltan /* 871572a6732SBALATON Zoltan * Service a transport descriptor. 872572a6732SBALATON Zoltan * Returns nonzero to terminate processing of this endpoint. 873572a6732SBALATON Zoltan */ 874f1ae32a1SGerd Hoffmann static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) 875f1ae32a1SGerd Hoffmann { 876f1ae32a1SGerd Hoffmann int dir; 877f1ae32a1SGerd Hoffmann size_t len = 0, pktlen = 0; 878f1ae32a1SGerd Hoffmann const char *str = NULL; 879f1ae32a1SGerd Hoffmann int pid; 880f1ae32a1SGerd Hoffmann int ret; 881f1ae32a1SGerd Hoffmann int i; 882f1ae32a1SGerd Hoffmann USBDevice *dev; 883f1ae32a1SGerd Hoffmann USBEndpoint *ep; 884f1ae32a1SGerd Hoffmann struct ohci_td td; 885f1ae32a1SGerd Hoffmann uint32_t addr; 886f1ae32a1SGerd Hoffmann int flag_r; 887f1ae32a1SGerd Hoffmann int completion; 888f1ae32a1SGerd Hoffmann 889f1ae32a1SGerd Hoffmann addr = ed->head & OHCI_DPTR_MASK; 890d8c2e6f2SQiang Liu if (addr == 0) { 891d8c2e6f2SQiang Liu ohci_die(ohci); 892d8c2e6f2SQiang Liu return 1; 893d8c2e6f2SQiang Liu } 894d8c2e6f2SQiang Liu 895f1ae32a1SGerd Hoffmann /* See if this TD has already been submitted to the device. */ 896f1ae32a1SGerd Hoffmann completion = (addr == ohci->async_td); 897f1ae32a1SGerd Hoffmann if (completion && !ohci->async_complete) { 898dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_skip_async(); 899f1ae32a1SGerd Hoffmann return 1; 900f1ae32a1SGerd Hoffmann } 901cf66ee8eSAlexey Kardashevskiy if (ohci_read_td(ohci, addr, &td)) { 902dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_read_error(addr); 903cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 9046ebc069dSLi Qiang return 1; 905f1ae32a1SGerd Hoffmann } 906f1ae32a1SGerd Hoffmann 907f1ae32a1SGerd Hoffmann dir = OHCI_BM(ed->flags, ED_D); 908f1ae32a1SGerd Hoffmann switch (dir) { 909f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_OUT: 910f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_IN: 911f1ae32a1SGerd Hoffmann /* Same value. */ 912f1ae32a1SGerd Hoffmann break; 913f1ae32a1SGerd Hoffmann default: 914f1ae32a1SGerd Hoffmann dir = OHCI_BM(td.flags, TD_DP); 915f1ae32a1SGerd Hoffmann break; 916f1ae32a1SGerd Hoffmann } 917f1ae32a1SGerd Hoffmann 918f1ae32a1SGerd Hoffmann switch (dir) { 919f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_IN: 920f1ae32a1SGerd Hoffmann str = "in"; 921f1ae32a1SGerd Hoffmann pid = USB_TOKEN_IN; 922f1ae32a1SGerd Hoffmann break; 923f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_OUT: 924f1ae32a1SGerd Hoffmann str = "out"; 925f1ae32a1SGerd Hoffmann pid = USB_TOKEN_OUT; 926f1ae32a1SGerd Hoffmann break; 927f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_SETUP: 928f1ae32a1SGerd Hoffmann str = "setup"; 929f1ae32a1SGerd Hoffmann pid = USB_TOKEN_SETUP; 930f1ae32a1SGerd Hoffmann break; 931f1ae32a1SGerd Hoffmann default: 932dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_bad_direction(dir); 933f1ae32a1SGerd Hoffmann return 1; 934f1ae32a1SGerd Hoffmann } 935f1ae32a1SGerd Hoffmann if (td.cbp && td.be) { 936f1ae32a1SGerd Hoffmann if ((td.cbp & 0xfffff000) != (td.be & 0xfffff000)) { 937f1ae32a1SGerd Hoffmann len = (td.be & 0xfff) + 0x1001 - (td.cbp & 0xfff); 938f1ae32a1SGerd Hoffmann } else { 9391328fe0cSPrasad J Pandit if (td.cbp > td.be) { 9401328fe0cSPrasad J Pandit trace_usb_ohci_iso_td_bad_cc_overrun(td.cbp, td.be); 9411328fe0cSPrasad J Pandit ohci_die(ohci); 9421328fe0cSPrasad J Pandit return 1; 9431328fe0cSPrasad J Pandit } 944f1ae32a1SGerd Hoffmann len = (td.be - td.cbp) + 1; 945f1ae32a1SGerd Hoffmann } 9461328fe0cSPrasad J Pandit if (len > sizeof(ohci->usb_buf)) { 9471328fe0cSPrasad J Pandit len = sizeof(ohci->usb_buf); 9481328fe0cSPrasad J Pandit } 949f1ae32a1SGerd Hoffmann 950f1ae32a1SGerd Hoffmann pktlen = len; 951f1ae32a1SGerd Hoffmann if (len && dir != OHCI_TD_DIR_IN) { 952f1ae32a1SGerd Hoffmann /* The endpoint may not allow us to transfer it all now */ 953f1ae32a1SGerd Hoffmann pktlen = (ed->flags & OHCI_ED_MPS_MASK) >> OHCI_ED_MPS_SHIFT; 954f1ae32a1SGerd Hoffmann if (pktlen > len) { 955f1ae32a1SGerd Hoffmann pktlen = len; 956f1ae32a1SGerd Hoffmann } 957f1ae32a1SGerd Hoffmann if (!completion) { 958cf66ee8eSAlexey Kardashevskiy if (ohci_copy_td(ohci, &td, ohci->usb_buf, pktlen, 959cf66ee8eSAlexey Kardashevskiy DMA_DIRECTION_TO_DEVICE)) { 960cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 961cf66ee8eSAlexey Kardashevskiy } 962f1ae32a1SGerd Hoffmann } 963f1ae32a1SGerd Hoffmann } 964f1ae32a1SGerd Hoffmann } 965f1ae32a1SGerd Hoffmann 966f1ae32a1SGerd Hoffmann flag_r = (td.flags & OHCI_TD_R) != 0; 967dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_pkt_hdr(addr, (int64_t)pktlen, (int64_t)len, str, 968dc1f5988SAlexey Kardashevskiy flag_r, td.cbp, td.be); 969dc1f5988SAlexey Kardashevskiy ohci_td_pkt("OUT", ohci->usb_buf, pktlen); 970f1ae32a1SGerd Hoffmann 971f1ae32a1SGerd Hoffmann if (completion) { 972f1ae32a1SGerd Hoffmann ohci->async_td = 0; 97369e25d26SAlexey Kardashevskiy ohci->async_complete = false; 974f1ae32a1SGerd Hoffmann } else { 975f1ae32a1SGerd Hoffmann dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA)); 97642340fc3SLiam Merwick if (dev == NULL) { 97742340fc3SLiam Merwick trace_usb_ohci_td_dev_error(); 97842340fc3SLiam Merwick return 1; 97942340fc3SLiam Merwick } 980f1ae32a1SGerd Hoffmann ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN)); 9816e821e50SBALATON Zoltan if (ohci->async_td) { 982572a6732SBALATON Zoltan /* 983572a6732SBALATON Zoltan * ??? The hardware should allow one active packet per 984572a6732SBALATON Zoltan * endpoint. We only allow one active packet per controller. 985572a6732SBALATON Zoltan * This should be sufficient as long as devices respond in a 986572a6732SBALATON Zoltan * timely manner. 9876e821e50SBALATON Zoltan */ 9886e821e50SBALATON Zoltan trace_usb_ohci_td_too_many_pending(ep->nr); 9896e821e50SBALATON Zoltan return 1; 9906e821e50SBALATON Zoltan } 9918550a02dSGerd Hoffmann usb_packet_setup(&ohci->usb_packet, pid, ep, 0, addr, !flag_r, 992a6fb2ddbSHans de Goede OHCI_BM(td.flags, TD_DI) == 0); 993f1ae32a1SGerd Hoffmann usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen); 9949a77a0f5SHans de Goede usb_handle_packet(dev, &ohci->usb_packet); 995dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_packet_status(ohci->usb_packet.status); 996dc1f5988SAlexey Kardashevskiy 9979a77a0f5SHans de Goede if (ohci->usb_packet.status == USB_RET_ASYNC) { 99836dfe324SHans de Goede usb_device_flush_ep_queue(dev, ep); 999f1ae32a1SGerd Hoffmann ohci->async_td = addr; 1000f1ae32a1SGerd Hoffmann return 1; 1001f1ae32a1SGerd Hoffmann } 1002f1ae32a1SGerd Hoffmann } 10039a77a0f5SHans de Goede if (ohci->usb_packet.status == USB_RET_SUCCESS) { 10049a77a0f5SHans de Goede ret = ohci->usb_packet.actual_length; 10059a77a0f5SHans de Goede } else { 10069a77a0f5SHans de Goede ret = ohci->usb_packet.status; 10079a77a0f5SHans de Goede } 10089a77a0f5SHans de Goede 1009f1ae32a1SGerd Hoffmann if (ret >= 0) { 1010f1ae32a1SGerd Hoffmann if (dir == OHCI_TD_DIR_IN) { 1011cf66ee8eSAlexey Kardashevskiy if (ohci_copy_td(ohci, &td, ohci->usb_buf, ret, 1012cf66ee8eSAlexey Kardashevskiy DMA_DIRECTION_FROM_DEVICE)) { 1013cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 1014cf66ee8eSAlexey Kardashevskiy } 1015dc1f5988SAlexey Kardashevskiy ohci_td_pkt("IN", ohci->usb_buf, pktlen); 1016f1ae32a1SGerd Hoffmann } else { 1017f1ae32a1SGerd Hoffmann ret = pktlen; 1018f1ae32a1SGerd Hoffmann } 1019f1ae32a1SGerd Hoffmann } 1020f1ae32a1SGerd Hoffmann 1021f1ae32a1SGerd Hoffmann /* Writeback */ 1022f1ae32a1SGerd Hoffmann if (ret == pktlen || (dir == OHCI_TD_DIR_IN && ret >= 0 && flag_r)) { 1023f1ae32a1SGerd Hoffmann /* Transmission succeeded. */ 1024f1ae32a1SGerd Hoffmann if (ret == len) { 1025f1ae32a1SGerd Hoffmann td.cbp = 0; 1026f1ae32a1SGerd Hoffmann } else { 1027f1ae32a1SGerd Hoffmann if ((td.cbp & 0xfff) + ret > 0xfff) { 1028f1ae32a1SGerd Hoffmann td.cbp = (td.be & ~0xfff) + ((td.cbp + ret) & 0xfff); 1029f1ae32a1SGerd Hoffmann } else { 1030f1ae32a1SGerd Hoffmann td.cbp += ret; 1031f1ae32a1SGerd Hoffmann } 1032f1ae32a1SGerd Hoffmann } 1033f1ae32a1SGerd Hoffmann td.flags |= OHCI_TD_T1; 1034f1ae32a1SGerd Hoffmann td.flags ^= OHCI_TD_T0; 1035f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_NOERROR); 1036f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_EC, 0); 1037f1ae32a1SGerd Hoffmann 1038f1ae32a1SGerd Hoffmann if ((dir != OHCI_TD_DIR_IN) && (ret != len)) { 1039f1ae32a1SGerd Hoffmann /* Partial packet transfer: TD not ready to retire yet */ 1040f1ae32a1SGerd Hoffmann goto exit_no_retire; 1041f1ae32a1SGerd Hoffmann } 1042f1ae32a1SGerd Hoffmann 1043f1ae32a1SGerd Hoffmann /* Setting ED_C is part of the TD retirement process */ 1044f1ae32a1SGerd Hoffmann ed->head &= ~OHCI_ED_C; 10451e58e7a0SBALATON Zoltan if (td.flags & OHCI_TD_T0) { 1046f1ae32a1SGerd Hoffmann ed->head |= OHCI_ED_C; 10471e58e7a0SBALATON Zoltan } 1048f1ae32a1SGerd Hoffmann } else { 1049f1ae32a1SGerd Hoffmann if (ret >= 0) { 1050dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_underrun(); 1051f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAUNDERRUN); 1052f1ae32a1SGerd Hoffmann } else { 1053f1ae32a1SGerd Hoffmann switch (ret) { 1054f1ae32a1SGerd Hoffmann case USB_RET_IOERROR: 1055f1ae32a1SGerd Hoffmann case USB_RET_NODEV: 1056dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_dev_error(); 1057f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DEVICENOTRESPONDING); 10584b351a0fSJán Veselý break; 1059f1ae32a1SGerd Hoffmann case USB_RET_NAK: 1060dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_nak(); 1061f1ae32a1SGerd Hoffmann return 1; 1062f1ae32a1SGerd Hoffmann case USB_RET_STALL: 1063dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_stall(); 1064f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_STALL); 1065f1ae32a1SGerd Hoffmann break; 1066f1ae32a1SGerd Hoffmann case USB_RET_BABBLE: 1067dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_babble(); 1068f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAOVERRUN); 1069f1ae32a1SGerd Hoffmann break; 1070f1ae32a1SGerd Hoffmann default: 1071dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_bad_device_response(ret); 1072f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_UNDEXPETEDPID); 1073f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_EC, 3); 1074f1ae32a1SGerd Hoffmann break; 1075f1ae32a1SGerd Hoffmann } 1076572a6732SBALATON Zoltan /* 1077572a6732SBALATON Zoltan * An error occurred so we have to clear the interrupt counter. 1078572a6732SBALATON Zoltan * See spec at 6.4.4 on page 104 1079572a6732SBALATON Zoltan */ 10807c48b95dSSebastian Bauer ohci->done_count = 0; 1081f1ae32a1SGerd Hoffmann } 1082f1ae32a1SGerd Hoffmann ed->head |= OHCI_ED_H; 1083f1ae32a1SGerd Hoffmann } 1084f1ae32a1SGerd Hoffmann 1085f1ae32a1SGerd Hoffmann /* Retire this TD */ 1086f1ae32a1SGerd Hoffmann ed->head &= ~OHCI_DPTR_MASK; 1087f1ae32a1SGerd Hoffmann ed->head |= td.next & OHCI_DPTR_MASK; 1088f1ae32a1SGerd Hoffmann td.next = ohci->done; 1089f1ae32a1SGerd Hoffmann ohci->done = addr; 1090f1ae32a1SGerd Hoffmann i = OHCI_BM(td.flags, TD_DI); 10911e58e7a0SBALATON Zoltan if (i < ohci->done_count) { 1092f1ae32a1SGerd Hoffmann ohci->done_count = i; 10931e58e7a0SBALATON Zoltan } 1094f1ae32a1SGerd Hoffmann exit_no_retire: 1095cf66ee8eSAlexey Kardashevskiy if (ohci_put_td(ohci, addr, &td)) { 1096cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 1097cf66ee8eSAlexey Kardashevskiy return 1; 1098cf66ee8eSAlexey Kardashevskiy } 1099f1ae32a1SGerd Hoffmann return OHCI_BM(td.flags, TD_CC) != OHCI_CC_NOERROR; 1100f1ae32a1SGerd Hoffmann } 1101f1ae32a1SGerd Hoffmann 1102f1ae32a1SGerd Hoffmann /* Service an endpoint list. Returns nonzero if active TD were found. */ 11033a4d06f2SBALATON Zoltan static int ohci_service_ed_list(OHCIState *ohci, uint32_t head) 1104f1ae32a1SGerd Hoffmann { 1105f1ae32a1SGerd Hoffmann struct ohci_ed ed; 1106f1ae32a1SGerd Hoffmann uint32_t next_ed; 1107f1ae32a1SGerd Hoffmann uint32_t cur; 1108f1ae32a1SGerd Hoffmann int active; 110995ed5693SLi Qiang uint32_t link_cnt = 0; 1110f1ae32a1SGerd Hoffmann active = 0; 1111f1ae32a1SGerd Hoffmann 11121e58e7a0SBALATON Zoltan if (head == 0) { 1113f1ae32a1SGerd Hoffmann return 0; 11141e58e7a0SBALATON Zoltan } 1115ab878998SLaurent Vivier for (cur = head; cur && link_cnt++ < ED_LINK_LIMIT; cur = next_ed) { 1116cf66ee8eSAlexey Kardashevskiy if (ohci_read_ed(ohci, cur, &ed)) { 1117dc1f5988SAlexey Kardashevskiy trace_usb_ohci_ed_read_error(cur); 1118cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 1119f1ae32a1SGerd Hoffmann return 0; 1120f1ae32a1SGerd Hoffmann } 1121f1ae32a1SGerd Hoffmann 1122f1ae32a1SGerd Hoffmann next_ed = ed.next & OHCI_DPTR_MASK; 1123f1ae32a1SGerd Hoffmann 1124f1ae32a1SGerd Hoffmann if ((ed.head & OHCI_ED_H) || (ed.flags & OHCI_ED_K)) { 1125f1ae32a1SGerd Hoffmann uint32_t addr; 1126f1ae32a1SGerd Hoffmann /* Cancel pending packets for ED that have been paused. */ 1127f1ae32a1SGerd Hoffmann addr = ed.head & OHCI_DPTR_MASK; 1128f1ae32a1SGerd Hoffmann if (ohci->async_td && addr == ohci->async_td) { 1129f1ae32a1SGerd Hoffmann usb_cancel_packet(&ohci->usb_packet); 1130f1ae32a1SGerd Hoffmann ohci->async_td = 0; 1131f79738b0SHans de Goede usb_device_ep_stopped(ohci->usb_packet.ep->dev, 1132f79738b0SHans de Goede ohci->usb_packet.ep); 1133f1ae32a1SGerd Hoffmann } 1134f1ae32a1SGerd Hoffmann continue; 1135f1ae32a1SGerd Hoffmann } 1136f1ae32a1SGerd Hoffmann 1137f1ae32a1SGerd Hoffmann while ((ed.head & OHCI_DPTR_MASK) != ed.tail) { 11383af8f177SAlexey Kardashevskiy trace_usb_ohci_ed_pkt(cur, (ed.head & OHCI_ED_H) != 0, 11393af8f177SAlexey Kardashevskiy (ed.head & OHCI_ED_C) != 0, ed.head & OHCI_DPTR_MASK, 11403af8f177SAlexey Kardashevskiy ed.tail & OHCI_DPTR_MASK, ed.next & OHCI_DPTR_MASK); 11413af8f177SAlexey Kardashevskiy trace_usb_ohci_ed_pkt_flags( 1142f1ae32a1SGerd Hoffmann OHCI_BM(ed.flags, ED_FA), OHCI_BM(ed.flags, ED_EN), 1143f1ae32a1SGerd Hoffmann OHCI_BM(ed.flags, ED_D), (ed.flags & OHCI_ED_S) != 0, 1144f1ae32a1SGerd Hoffmann (ed.flags & OHCI_ED_K) != 0, (ed.flags & OHCI_ED_F) != 0, 11453af8f177SAlexey Kardashevskiy OHCI_BM(ed.flags, ED_MPS)); 1146dc1f5988SAlexey Kardashevskiy 1147f1ae32a1SGerd Hoffmann active = 1; 1148f1ae32a1SGerd Hoffmann 1149f1ae32a1SGerd Hoffmann if ((ed.flags & OHCI_ED_F) == 0) { 11501e58e7a0SBALATON Zoltan if (ohci_service_td(ohci, &ed)) { 1151f1ae32a1SGerd Hoffmann break; 11521e58e7a0SBALATON Zoltan } 1153f1ae32a1SGerd Hoffmann } else { 1154f1ae32a1SGerd Hoffmann /* Handle isochronous endpoints */ 11553a4d06f2SBALATON Zoltan if (ohci_service_iso_td(ohci, &ed)) { 1156f1ae32a1SGerd Hoffmann break; 1157f1ae32a1SGerd Hoffmann } 1158f1ae32a1SGerd Hoffmann } 11593a4d06f2SBALATON Zoltan } 1160f1ae32a1SGerd Hoffmann 1161cf66ee8eSAlexey Kardashevskiy if (ohci_put_ed(ohci, cur, &ed)) { 1162cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 1163cf66ee8eSAlexey Kardashevskiy return 0; 1164cf66ee8eSAlexey Kardashevskiy } 1165f1ae32a1SGerd Hoffmann } 1166f1ae32a1SGerd Hoffmann 1167f1ae32a1SGerd Hoffmann return active; 1168f1ae32a1SGerd Hoffmann } 1169f1ae32a1SGerd Hoffmann 1170fd0a10cdSLaurent Vivier /* set a timer for EOF */ 1171fd0a10cdSLaurent Vivier static void ohci_eof_timer(OHCIState *ohci) 1172f1ae32a1SGerd Hoffmann { 1173bc72ad67SAlex Bligh timer_mod(ohci->eof_timer, ohci->sof_time + usb_frame_time); 1174fd0a10cdSLaurent Vivier } 1175fd0a10cdSLaurent Vivier /* Set a timer for EOF and generate a SOF event */ 1176fd0a10cdSLaurent Vivier static void ohci_sof(OHCIState *ohci) 1177fd0a10cdSLaurent Vivier { 1178a60f39a4SMiguel GAIO ohci->sof_time += usb_frame_time; 1179fd0a10cdSLaurent Vivier ohci_eof_timer(ohci); 1180f1ae32a1SGerd Hoffmann ohci_set_interrupt(ohci, OHCI_INTR_SF); 1181f1ae32a1SGerd Hoffmann } 1182f1ae32a1SGerd Hoffmann 1183f1ae32a1SGerd Hoffmann /* Process Control and Bulk lists. */ 11843a4d06f2SBALATON Zoltan static void ohci_process_lists(OHCIState *ohci) 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) { 1188dc1f5988SAlexey Kardashevskiy trace_usb_ohci_process_lists(ohci->ctrl_head, ohci->ctrl_cur); 1189f1ae32a1SGerd Hoffmann } 11903a4d06f2SBALATON Zoltan if (!ohci_service_ed_list(ohci, ohci->ctrl_head)) { 1191f1ae32a1SGerd Hoffmann ohci->ctrl_cur = 0; 1192f1ae32a1SGerd Hoffmann ohci->status &= ~OHCI_STATUS_CLF; 1193f1ae32a1SGerd Hoffmann } 1194f1ae32a1SGerd Hoffmann } 1195f1ae32a1SGerd Hoffmann 1196f1ae32a1SGerd Hoffmann if ((ohci->ctl & OHCI_CTL_BLE) && (ohci->status & OHCI_STATUS_BLF)) { 11973a4d06f2SBALATON Zoltan if (!ohci_service_ed_list(ohci, ohci->bulk_head)) { 1198f1ae32a1SGerd Hoffmann ohci->bulk_cur = 0; 1199f1ae32a1SGerd Hoffmann ohci->status &= ~OHCI_STATUS_BLF; 1200f1ae32a1SGerd Hoffmann } 1201f1ae32a1SGerd Hoffmann } 1202f1ae32a1SGerd Hoffmann } 1203f1ae32a1SGerd Hoffmann 1204f1ae32a1SGerd Hoffmann /* Do frame processing on frame boundary */ 1205f1ae32a1SGerd Hoffmann static void ohci_frame_boundary(void *opaque) 1206f1ae32a1SGerd Hoffmann { 1207f1ae32a1SGerd Hoffmann OHCIState *ohci = opaque; 1208f1ae32a1SGerd Hoffmann struct ohci_hcca hcca; 1209f1ae32a1SGerd Hoffmann 1210cf66ee8eSAlexey Kardashevskiy if (ohci_read_hcca(ohci, ohci->hcca, &hcca)) { 1211dc1f5988SAlexey Kardashevskiy trace_usb_ohci_hcca_read_error(ohci->hcca); 1212cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 1213cf66ee8eSAlexey Kardashevskiy return; 1214cf66ee8eSAlexey Kardashevskiy } 1215f1ae32a1SGerd Hoffmann 1216f1ae32a1SGerd Hoffmann /* Process all the lists at the end of the frame */ 1217f1ae32a1SGerd Hoffmann if (ohci->ctl & OHCI_CTL_PLE) { 1218f1ae32a1SGerd Hoffmann int n; 1219f1ae32a1SGerd Hoffmann 1220f1ae32a1SGerd Hoffmann n = ohci->frame_number & 0x1f; 12213a4d06f2SBALATON Zoltan ohci_service_ed_list(ohci, le32_to_cpu(hcca.intr[n])); 1222f1ae32a1SGerd Hoffmann } 1223f1ae32a1SGerd Hoffmann 1224f1ae32a1SGerd Hoffmann /* Cancel all pending packets if either of the lists has been disabled. */ 1225f79738b0SHans de Goede if (ohci->old_ctl & (~ohci->ctl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) { 1226f79738b0SHans de Goede ohci_stop_endpoints(ohci); 1227f79738b0SHans de Goede } 1228f1ae32a1SGerd Hoffmann ohci->old_ctl = ohci->ctl; 12293a4d06f2SBALATON Zoltan ohci_process_lists(ohci); 1230f1ae32a1SGerd Hoffmann 1231cf66ee8eSAlexey Kardashevskiy /* Stop if UnrecoverableError happened or ohci_sof will crash */ 1232cf66ee8eSAlexey Kardashevskiy if (ohci->intr_status & OHCI_INTR_UE) { 1233cf66ee8eSAlexey Kardashevskiy return; 1234cf66ee8eSAlexey Kardashevskiy } 1235cf66ee8eSAlexey Kardashevskiy 1236f1ae32a1SGerd Hoffmann /* Frame boundary, so do EOF stuf here */ 1237f1ae32a1SGerd Hoffmann ohci->frt = ohci->fit; 1238f1ae32a1SGerd Hoffmann 1239f1ae32a1SGerd Hoffmann /* Increment frame number and take care of endianness. */ 1240f1ae32a1SGerd Hoffmann ohci->frame_number = (ohci->frame_number + 1) & 0xffff; 1241f1ae32a1SGerd Hoffmann hcca.frame = cpu_to_le16(ohci->frame_number); 12426301460cSPaolo Bonzini /* When the HC updates frame number, set pad to 0. Ref OHCI Spec 4.4.1*/ 12436301460cSPaolo Bonzini hcca.pad = 0; 1244f1ae32a1SGerd Hoffmann 1245f1ae32a1SGerd Hoffmann if (ohci->done_count == 0 && !(ohci->intr_status & OHCI_INTR_WD)) { 12461e58e7a0SBALATON Zoltan if (!ohci->done) { 1247f1ae32a1SGerd Hoffmann abort(); 12481e58e7a0SBALATON Zoltan } 12491e58e7a0SBALATON Zoltan if (ohci->intr & ohci->intr_status) { 1250f1ae32a1SGerd Hoffmann ohci->done |= 1; 12511e58e7a0SBALATON Zoltan } 1252f1ae32a1SGerd Hoffmann hcca.done = cpu_to_le32(ohci->done); 1253f1ae32a1SGerd Hoffmann ohci->done = 0; 1254f1ae32a1SGerd Hoffmann ohci->done_count = 7; 1255f1ae32a1SGerd Hoffmann ohci_set_interrupt(ohci, OHCI_INTR_WD); 1256f1ae32a1SGerd Hoffmann } 1257f1ae32a1SGerd Hoffmann 12581e58e7a0SBALATON Zoltan if (ohci->done_count != 7 && ohci->done_count != 0) { 1259f1ae32a1SGerd Hoffmann ohci->done_count--; 12601e58e7a0SBALATON Zoltan } 1261f1ae32a1SGerd Hoffmann /* Do SOF stuff here */ 1262f1ae32a1SGerd Hoffmann ohci_sof(ohci); 1263f1ae32a1SGerd Hoffmann 1264f1ae32a1SGerd Hoffmann /* Writeback HCCA */ 1265cf66ee8eSAlexey Kardashevskiy if (ohci_put_hcca(ohci, ohci->hcca, &hcca)) { 1266cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 1267cf66ee8eSAlexey Kardashevskiy } 1268f1ae32a1SGerd Hoffmann } 1269f1ae32a1SGerd Hoffmann 1270572a6732SBALATON Zoltan /* 1271572a6732SBALATON Zoltan * Start sending SOF tokens across the USB bus, lists are processed in 1272f1ae32a1SGerd Hoffmann * next frame 1273f1ae32a1SGerd Hoffmann */ 1274f1ae32a1SGerd Hoffmann static int ohci_bus_start(OHCIState *ohci) 1275f1ae32a1SGerd Hoffmann { 1276dc1f5988SAlexey Kardashevskiy trace_usb_ohci_start(ohci->name); 1277572a6732SBALATON Zoltan /* 1278572a6732SBALATON Zoltan * Delay the first SOF event by one frame time as linux driver is 1279572a6732SBALATON Zoltan * not ready to receive it and can meet some race conditions 1280fd0a10cdSLaurent Vivier */ 1281a60f39a4SMiguel GAIO ohci->sof_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 1282fd0a10cdSLaurent Vivier ohci_eof_timer(ohci); 1283f1ae32a1SGerd Hoffmann 1284f1ae32a1SGerd Hoffmann return 1; 1285f1ae32a1SGerd Hoffmann } 1286f1ae32a1SGerd Hoffmann 1287f1ae32a1SGerd Hoffmann /* Stop sending SOF tokens on the bus */ 128834d97308SThomas Huth void ohci_bus_stop(OHCIState *ohci) 1289f1ae32a1SGerd Hoffmann { 1290dc1f5988SAlexey Kardashevskiy trace_usb_ohci_stop(ohci->name); 1291bc72ad67SAlex Bligh timer_del(ohci->eof_timer); 1292f1ae32a1SGerd Hoffmann } 1293f1ae32a1SGerd Hoffmann 1294572a6732SBALATON Zoltan /* Frame interval toggle is manipulated by the hcd only */ 1295f1ae32a1SGerd Hoffmann static void ohci_set_frame_interval(OHCIState *ohci, uint16_t val) 1296f1ae32a1SGerd Hoffmann { 1297f1ae32a1SGerd Hoffmann val &= OHCI_FMI_FI; 1298f1ae32a1SGerd Hoffmann 1299f1ae32a1SGerd Hoffmann if (val != ohci->fi) { 1300dc1f5988SAlexey Kardashevskiy trace_usb_ohci_set_frame_interval(ohci->name, ohci->fi, ohci->fi); 1301f1ae32a1SGerd Hoffmann } 1302f1ae32a1SGerd Hoffmann 1303f1ae32a1SGerd Hoffmann ohci->fi = val; 1304f1ae32a1SGerd Hoffmann } 1305f1ae32a1SGerd Hoffmann 1306f1ae32a1SGerd Hoffmann static void ohci_port_power(OHCIState *ohci, int i, int p) 1307f1ae32a1SGerd Hoffmann { 1308f1ae32a1SGerd Hoffmann if (p) { 1309f1ae32a1SGerd Hoffmann ohci->rhport[i].ctrl |= OHCI_PORT_PPS; 1310f1ae32a1SGerd Hoffmann } else { 1311978c93beSBALATON Zoltan ohci->rhport[i].ctrl &= ~(OHCI_PORT_PPS | OHCI_PORT_CCS | 1312978c93beSBALATON Zoltan OHCI_PORT_PSS | OHCI_PORT_PRS); 1313f1ae32a1SGerd Hoffmann } 1314f1ae32a1SGerd Hoffmann } 1315f1ae32a1SGerd Hoffmann 1316f1ae32a1SGerd Hoffmann /* Set HcControlRegister */ 1317f1ae32a1SGerd Hoffmann static void ohci_set_ctl(OHCIState *ohci, uint32_t val) 1318f1ae32a1SGerd Hoffmann { 1319f1ae32a1SGerd Hoffmann uint32_t old_state; 1320f1ae32a1SGerd Hoffmann uint32_t new_state; 1321f1ae32a1SGerd Hoffmann 1322f1ae32a1SGerd Hoffmann old_state = ohci->ctl & OHCI_CTL_HCFS; 1323f1ae32a1SGerd Hoffmann ohci->ctl = val; 1324f1ae32a1SGerd Hoffmann new_state = ohci->ctl & OHCI_CTL_HCFS; 1325f1ae32a1SGerd Hoffmann 1326f1ae32a1SGerd Hoffmann /* no state change */ 13271e58e7a0SBALATON Zoltan if (old_state == new_state) { 1328f1ae32a1SGerd Hoffmann return; 13291e58e7a0SBALATON Zoltan } 1330dc1f5988SAlexey Kardashevskiy trace_usb_ohci_set_ctl(ohci->name, new_state); 1331f1ae32a1SGerd Hoffmann switch (new_state) { 1332f1ae32a1SGerd Hoffmann case OHCI_USB_OPERATIONAL: 1333f1ae32a1SGerd Hoffmann ohci_bus_start(ohci); 1334f1ae32a1SGerd Hoffmann break; 1335f1ae32a1SGerd Hoffmann case OHCI_USB_SUSPEND: 1336f1ae32a1SGerd Hoffmann ohci_bus_stop(ohci); 1337087462c7SLaurent Vivier /* clear pending SF otherwise linux driver loops in ohci_irq() */ 1338087462c7SLaurent Vivier ohci->intr_status &= ~OHCI_INTR_SF; 1339087462c7SLaurent Vivier ohci_intr_update(ohci); 1340f1ae32a1SGerd Hoffmann break; 1341f1ae32a1SGerd Hoffmann case OHCI_USB_RESUME: 1342dc1f5988SAlexey Kardashevskiy trace_usb_ohci_resume(ohci->name); 1343f1ae32a1SGerd Hoffmann break; 1344f1ae32a1SGerd Hoffmann case OHCI_USB_RESET: 13457d938fd1SHervé Poussineau ohci_roothub_reset(ohci); 1346f1ae32a1SGerd Hoffmann break; 1347f1ae32a1SGerd Hoffmann } 1348f1ae32a1SGerd Hoffmann } 1349f1ae32a1SGerd Hoffmann 1350f1ae32a1SGerd Hoffmann static uint32_t ohci_get_frame_remaining(OHCIState *ohci) 1351f1ae32a1SGerd Hoffmann { 1352f1ae32a1SGerd Hoffmann uint16_t fr; 1353f1ae32a1SGerd Hoffmann int64_t tks; 1354f1ae32a1SGerd Hoffmann 13551e58e7a0SBALATON Zoltan if ((ohci->ctl & OHCI_CTL_HCFS) != OHCI_USB_OPERATIONAL) { 13561e58e7a0SBALATON Zoltan return ohci->frt << 31; 13571e58e7a0SBALATON Zoltan } 1358*2a8537cfSMichael Tokarev /* Being in USB operational state guarantees sof_time was set already. */ 1359bc72ad67SAlex Bligh tks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - ohci->sof_time; 1360a60f39a4SMiguel GAIO if (tks < 0) { 1361a60f39a4SMiguel GAIO tks = 0; 1362a60f39a4SMiguel GAIO } 1363f1ae32a1SGerd Hoffmann 1364f1ae32a1SGerd Hoffmann /* avoid muldiv if possible */ 13651e58e7a0SBALATON Zoltan if (tks >= usb_frame_time) { 13661e58e7a0SBALATON Zoltan return ohci->frt << 31; 13671e58e7a0SBALATON Zoltan } 1368cd1f16f9SLaurent Vivier tks = tks / usb_bit_time; 1369f1ae32a1SGerd Hoffmann fr = (uint16_t)(ohci->fi - tks); 1370f1ae32a1SGerd Hoffmann 1371f1ae32a1SGerd Hoffmann return (ohci->frt << 31) | fr; 1372f1ae32a1SGerd Hoffmann } 1373f1ae32a1SGerd Hoffmann 1374f1ae32a1SGerd Hoffmann 1375f1ae32a1SGerd Hoffmann /* Set root hub status */ 1376f1ae32a1SGerd Hoffmann static void ohci_set_hub_status(OHCIState *ohci, uint32_t val) 1377f1ae32a1SGerd Hoffmann { 1378f1ae32a1SGerd Hoffmann uint32_t old_state; 1379f1ae32a1SGerd Hoffmann 1380f1ae32a1SGerd Hoffmann old_state = ohci->rhstatus; 1381f1ae32a1SGerd Hoffmann 1382f1ae32a1SGerd Hoffmann /* write 1 to clear OCIC */ 13831e58e7a0SBALATON Zoltan if (val & OHCI_RHS_OCIC) { 1384f1ae32a1SGerd Hoffmann ohci->rhstatus &= ~OHCI_RHS_OCIC; 13851e58e7a0SBALATON Zoltan } 1386f1ae32a1SGerd Hoffmann if (val & OHCI_RHS_LPS) { 1387f1ae32a1SGerd Hoffmann int i; 1388f1ae32a1SGerd Hoffmann 13891e58e7a0SBALATON Zoltan for (i = 0; i < ohci->num_ports; i++) { 1390f1ae32a1SGerd Hoffmann ohci_port_power(ohci, i, 0); 13911e58e7a0SBALATON Zoltan } 1392dc1f5988SAlexey Kardashevskiy trace_usb_ohci_hub_power_down(); 1393f1ae32a1SGerd Hoffmann } 1394f1ae32a1SGerd Hoffmann 1395f1ae32a1SGerd Hoffmann if (val & OHCI_RHS_LPSC) { 1396f1ae32a1SGerd Hoffmann int i; 1397f1ae32a1SGerd Hoffmann 13981e58e7a0SBALATON Zoltan for (i = 0; i < ohci->num_ports; i++) { 1399f1ae32a1SGerd Hoffmann ohci_port_power(ohci, i, 1); 14001e58e7a0SBALATON Zoltan } 1401dc1f5988SAlexey Kardashevskiy trace_usb_ohci_hub_power_up(); 1402f1ae32a1SGerd Hoffmann } 1403f1ae32a1SGerd Hoffmann 14041e58e7a0SBALATON Zoltan if (val & OHCI_RHS_DRWE) { 1405f1ae32a1SGerd Hoffmann ohci->rhstatus |= OHCI_RHS_DRWE; 14061e58e7a0SBALATON Zoltan } 14071e58e7a0SBALATON Zoltan if (val & OHCI_RHS_CRWE) { 1408f1ae32a1SGerd Hoffmann ohci->rhstatus &= ~OHCI_RHS_DRWE; 14091e58e7a0SBALATON Zoltan } 14101e58e7a0SBALATON Zoltan if (old_state != ohci->rhstatus) { 1411f1ae32a1SGerd Hoffmann ohci_set_interrupt(ohci, OHCI_INTR_RHSC); 1412f1ae32a1SGerd Hoffmann } 14131e58e7a0SBALATON Zoltan } 1414f1ae32a1SGerd Hoffmann 14150c38e9ddSBALATON Zoltan /* This is the one state transition the controller can do by itself */ 14160c38e9ddSBALATON Zoltan static bool ohci_resume(OHCIState *s) 14170c38e9ddSBALATON Zoltan { 14180c38e9ddSBALATON Zoltan if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) { 14190c38e9ddSBALATON Zoltan trace_usb_ohci_remote_wakeup(s->name); 14200c38e9ddSBALATON Zoltan s->ctl &= ~OHCI_CTL_HCFS; 14210c38e9ddSBALATON Zoltan s->ctl |= OHCI_USB_RESUME; 14220c38e9ddSBALATON Zoltan return true; 14230c38e9ddSBALATON Zoltan } 14240c38e9ddSBALATON Zoltan return false; 14250c38e9ddSBALATON Zoltan } 14260c38e9ddSBALATON Zoltan 1427ef680088SBALATON Zoltan /* 1428ef680088SBALATON Zoltan * Sets a flag in a port status reg but only set it if the port is connected. 1429ef680088SBALATON Zoltan * If not set ConnectStatusChange flag. If flag is enabled return 1. 1430ef680088SBALATON Zoltan */ 1431ef680088SBALATON Zoltan static int ohci_port_set_if_connected(OHCIState *ohci, int i, uint32_t val) 1432ef680088SBALATON Zoltan { 1433ef680088SBALATON Zoltan int ret = 1; 1434ef680088SBALATON Zoltan 1435ef680088SBALATON Zoltan /* writing a 0 has no effect */ 1436ef680088SBALATON Zoltan if (val == 0) { 1437ef680088SBALATON Zoltan return 0; 1438ef680088SBALATON Zoltan } 1439ef680088SBALATON Zoltan /* If CurrentConnectStatus is cleared we set ConnectStatusChange */ 1440ef680088SBALATON Zoltan if (!(ohci->rhport[i].ctrl & OHCI_PORT_CCS)) { 1441ef680088SBALATON Zoltan ohci->rhport[i].ctrl |= OHCI_PORT_CSC; 1442ef680088SBALATON Zoltan if (ohci->rhstatus & OHCI_RHS_DRWE) { 14430c38e9ddSBALATON Zoltan /* CSC is a wakeup event */ 14440c38e9ddSBALATON Zoltan if (ohci_resume(ohci)) { 14450c38e9ddSBALATON Zoltan ohci_set_interrupt(ohci, OHCI_INTR_RD); 14460c38e9ddSBALATON Zoltan } 1447ef680088SBALATON Zoltan } 1448ef680088SBALATON Zoltan return 0; 1449ef680088SBALATON Zoltan } 1450ef680088SBALATON Zoltan 1451ef680088SBALATON Zoltan if (ohci->rhport[i].ctrl & val) { 1452ef680088SBALATON Zoltan ret = 0; 1453ef680088SBALATON Zoltan } 1454ef680088SBALATON Zoltan /* set the bit */ 1455ef680088SBALATON Zoltan ohci->rhport[i].ctrl |= val; 1456ef680088SBALATON Zoltan 1457ef680088SBALATON Zoltan return ret; 1458ef680088SBALATON Zoltan } 1459ef680088SBALATON Zoltan 1460f1ae32a1SGerd Hoffmann /* Set root hub port status */ 1461f1ae32a1SGerd Hoffmann static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val) 1462f1ae32a1SGerd Hoffmann { 1463f1ae32a1SGerd Hoffmann uint32_t old_state; 1464f1ae32a1SGerd Hoffmann OHCIPort *port; 1465f1ae32a1SGerd Hoffmann 1466f1ae32a1SGerd Hoffmann port = &ohci->rhport[portnum]; 1467f1ae32a1SGerd Hoffmann old_state = port->ctrl; 1468f1ae32a1SGerd Hoffmann 1469f1ae32a1SGerd Hoffmann /* Write to clear CSC, PESC, PSSC, OCIC, PRSC */ 14701e58e7a0SBALATON Zoltan if (val & OHCI_PORT_WTC) { 1471f1ae32a1SGerd Hoffmann port->ctrl &= ~(val & OHCI_PORT_WTC); 14721e58e7a0SBALATON Zoltan } 14731e58e7a0SBALATON Zoltan if (val & OHCI_PORT_CCS) { 1474f1ae32a1SGerd Hoffmann port->ctrl &= ~OHCI_PORT_PES; 14751e58e7a0SBALATON Zoltan } 1476f1ae32a1SGerd Hoffmann ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PES); 1477f1ae32a1SGerd Hoffmann 1478f1ae32a1SGerd Hoffmann if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PSS)) { 1479dc1f5988SAlexey Kardashevskiy trace_usb_ohci_port_suspend(portnum); 1480f1ae32a1SGerd Hoffmann } 1481f1ae32a1SGerd Hoffmann 1482f1ae32a1SGerd Hoffmann if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PRS)) { 1483dc1f5988SAlexey Kardashevskiy trace_usb_ohci_port_reset(portnum); 1484f1ae32a1SGerd Hoffmann usb_device_reset(port->port.dev); 1485f1ae32a1SGerd Hoffmann port->ctrl &= ~OHCI_PORT_PRS; 1486f1ae32a1SGerd Hoffmann /* ??? Should this also set OHCI_PORT_PESC. */ 1487f1ae32a1SGerd Hoffmann port->ctrl |= OHCI_PORT_PES | OHCI_PORT_PRSC; 1488f1ae32a1SGerd Hoffmann } 1489f1ae32a1SGerd Hoffmann 1490572a6732SBALATON Zoltan /* Invert order here to ensure in ambiguous case, device is powered up. */ 14911e58e7a0SBALATON Zoltan if (val & OHCI_PORT_LSDA) { 1492f1ae32a1SGerd Hoffmann ohci_port_power(ohci, portnum, 0); 14931e58e7a0SBALATON Zoltan } 14941e58e7a0SBALATON Zoltan if (val & OHCI_PORT_PPS) { 1495f1ae32a1SGerd Hoffmann ohci_port_power(ohci, portnum, 1); 14961e58e7a0SBALATON Zoltan } 14971e58e7a0SBALATON Zoltan if (old_state != port->ctrl) { 1498f1ae32a1SGerd Hoffmann ohci_set_interrupt(ohci, OHCI_INTR_RHSC); 1499f1ae32a1SGerd Hoffmann } 15001e58e7a0SBALATON Zoltan } 1501f1ae32a1SGerd Hoffmann 1502f1ae32a1SGerd Hoffmann static uint64_t ohci_mem_read(void *opaque, 1503a8170e5eSAvi Kivity hwaddr addr, 1504f1ae32a1SGerd Hoffmann unsigned size) 1505f1ae32a1SGerd Hoffmann { 1506f1ae32a1SGerd Hoffmann OHCIState *ohci = opaque; 1507f1ae32a1SGerd Hoffmann uint32_t retval; 1508f1ae32a1SGerd Hoffmann 1509f1ae32a1SGerd Hoffmann /* Only aligned reads are allowed on OHCI */ 1510f1ae32a1SGerd Hoffmann if (addr & 3) { 1511dc1f5988SAlexey Kardashevskiy trace_usb_ohci_mem_read_unaligned(addr); 1512f1ae32a1SGerd Hoffmann return 0xffffffff; 1513f1ae32a1SGerd Hoffmann } else if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) { 1514f1ae32a1SGerd Hoffmann /* HcRhPortStatus */ 1515f1ae32a1SGerd Hoffmann retval = ohci->rhport[(addr - 0x54) >> 2].ctrl | OHCI_PORT_PPS; 15169ae8d31dSBALATON Zoltan trace_usb_ohci_mem_port_read(size, "HcRhPortStatus", (addr - 0x50) >> 2, 15179ae8d31dSBALATON Zoltan addr, addr >> 2, retval); 1518f1ae32a1SGerd Hoffmann } else { 1519f1ae32a1SGerd Hoffmann switch (addr >> 2) { 1520f1ae32a1SGerd Hoffmann case 0: /* HcRevision */ 1521f1ae32a1SGerd Hoffmann retval = 0x10; 1522f1ae32a1SGerd Hoffmann break; 1523f1ae32a1SGerd Hoffmann 1524f1ae32a1SGerd Hoffmann case 1: /* HcControl */ 1525f1ae32a1SGerd Hoffmann retval = ohci->ctl; 1526f1ae32a1SGerd Hoffmann break; 1527f1ae32a1SGerd Hoffmann 1528f1ae32a1SGerd Hoffmann case 2: /* HcCommandStatus */ 1529f1ae32a1SGerd Hoffmann retval = ohci->status; 1530f1ae32a1SGerd Hoffmann break; 1531f1ae32a1SGerd Hoffmann 1532f1ae32a1SGerd Hoffmann case 3: /* HcInterruptStatus */ 1533f1ae32a1SGerd Hoffmann retval = ohci->intr_status; 1534f1ae32a1SGerd Hoffmann break; 1535f1ae32a1SGerd Hoffmann 1536f1ae32a1SGerd Hoffmann case 4: /* HcInterruptEnable */ 1537f1ae32a1SGerd Hoffmann case 5: /* HcInterruptDisable */ 1538f1ae32a1SGerd Hoffmann retval = ohci->intr; 1539f1ae32a1SGerd Hoffmann break; 1540f1ae32a1SGerd Hoffmann 1541f1ae32a1SGerd Hoffmann case 6: /* HcHCCA */ 1542f1ae32a1SGerd Hoffmann retval = ohci->hcca; 1543f1ae32a1SGerd Hoffmann break; 1544f1ae32a1SGerd Hoffmann 1545f1ae32a1SGerd Hoffmann case 7: /* HcPeriodCurrentED */ 1546f1ae32a1SGerd Hoffmann retval = ohci->per_cur; 1547f1ae32a1SGerd Hoffmann break; 1548f1ae32a1SGerd Hoffmann 1549f1ae32a1SGerd Hoffmann case 8: /* HcControlHeadED */ 1550f1ae32a1SGerd Hoffmann retval = ohci->ctrl_head; 1551f1ae32a1SGerd Hoffmann break; 1552f1ae32a1SGerd Hoffmann 1553f1ae32a1SGerd Hoffmann case 9: /* HcControlCurrentED */ 1554f1ae32a1SGerd Hoffmann retval = ohci->ctrl_cur; 1555f1ae32a1SGerd Hoffmann break; 1556f1ae32a1SGerd Hoffmann 1557f1ae32a1SGerd Hoffmann case 10: /* HcBulkHeadED */ 1558f1ae32a1SGerd Hoffmann retval = ohci->bulk_head; 1559f1ae32a1SGerd Hoffmann break; 1560f1ae32a1SGerd Hoffmann 1561f1ae32a1SGerd Hoffmann case 11: /* HcBulkCurrentED */ 1562f1ae32a1SGerd Hoffmann retval = ohci->bulk_cur; 1563f1ae32a1SGerd Hoffmann break; 1564f1ae32a1SGerd Hoffmann 1565f1ae32a1SGerd Hoffmann case 12: /* HcDoneHead */ 1566f1ae32a1SGerd Hoffmann retval = ohci->done; 1567f1ae32a1SGerd Hoffmann break; 1568f1ae32a1SGerd Hoffmann 1569f1ae32a1SGerd Hoffmann case 13: /* HcFmInterretval */ 1570f1ae32a1SGerd Hoffmann retval = (ohci->fit << 31) | (ohci->fsmps << 16) | (ohci->fi); 1571f1ae32a1SGerd Hoffmann break; 1572f1ae32a1SGerd Hoffmann 1573f1ae32a1SGerd Hoffmann case 14: /* HcFmRemaining */ 1574f1ae32a1SGerd Hoffmann retval = ohci_get_frame_remaining(ohci); 1575f1ae32a1SGerd Hoffmann break; 1576f1ae32a1SGerd Hoffmann 1577f1ae32a1SGerd Hoffmann case 15: /* HcFmNumber */ 1578f1ae32a1SGerd Hoffmann retval = ohci->frame_number; 1579f1ae32a1SGerd Hoffmann break; 1580f1ae32a1SGerd Hoffmann 1581f1ae32a1SGerd Hoffmann case 16: /* HcPeriodicStart */ 1582f1ae32a1SGerd Hoffmann retval = ohci->pstart; 1583f1ae32a1SGerd Hoffmann break; 1584f1ae32a1SGerd Hoffmann 1585f1ae32a1SGerd Hoffmann case 17: /* HcLSThreshold */ 1586f1ae32a1SGerd Hoffmann retval = ohci->lst; 1587f1ae32a1SGerd Hoffmann break; 1588f1ae32a1SGerd Hoffmann 1589f1ae32a1SGerd Hoffmann case 18: /* HcRhDescriptorA */ 1590f1ae32a1SGerd Hoffmann retval = ohci->rhdesc_a; 1591f1ae32a1SGerd Hoffmann break; 1592f1ae32a1SGerd Hoffmann 1593f1ae32a1SGerd Hoffmann case 19: /* HcRhDescriptorB */ 1594f1ae32a1SGerd Hoffmann retval = ohci->rhdesc_b; 1595f1ae32a1SGerd Hoffmann break; 1596f1ae32a1SGerd Hoffmann 1597f1ae32a1SGerd Hoffmann case 20: /* HcRhStatus */ 1598f1ae32a1SGerd Hoffmann retval = ohci->rhstatus; 1599f1ae32a1SGerd Hoffmann break; 1600f1ae32a1SGerd Hoffmann 1601f1ae32a1SGerd Hoffmann /* PXA27x specific registers */ 1602f1ae32a1SGerd Hoffmann case 24: /* HcStatus */ 1603f1ae32a1SGerd Hoffmann retval = ohci->hstatus & ohci->hmask; 1604f1ae32a1SGerd Hoffmann break; 1605f1ae32a1SGerd Hoffmann 1606f1ae32a1SGerd Hoffmann case 25: /* HcHReset */ 1607f1ae32a1SGerd Hoffmann retval = ohci->hreset; 1608f1ae32a1SGerd Hoffmann break; 1609f1ae32a1SGerd Hoffmann 1610f1ae32a1SGerd Hoffmann case 26: /* HcHInterruptEnable */ 1611f1ae32a1SGerd Hoffmann retval = ohci->hmask; 1612f1ae32a1SGerd Hoffmann break; 1613f1ae32a1SGerd Hoffmann 1614f1ae32a1SGerd Hoffmann case 27: /* HcHInterruptTest */ 1615f1ae32a1SGerd Hoffmann retval = ohci->htest; 1616f1ae32a1SGerd Hoffmann break; 1617f1ae32a1SGerd Hoffmann 1618f1ae32a1SGerd Hoffmann default: 1619dc1f5988SAlexey Kardashevskiy trace_usb_ohci_mem_read_bad_offset(addr); 1620f1ae32a1SGerd Hoffmann retval = 0xffffffff; 1621f1ae32a1SGerd Hoffmann } 16229ae8d31dSBALATON Zoltan if (addr != 0xc || retval) { 16239ae8d31dSBALATON Zoltan trace_usb_ohci_mem_read(size, ohci_reg_name(addr), addr, addr >> 2, 16249ae8d31dSBALATON Zoltan retval); 16259ae8d31dSBALATON Zoltan } 1626f1ae32a1SGerd Hoffmann } 1627f1ae32a1SGerd Hoffmann 1628f1ae32a1SGerd Hoffmann return retval; 1629f1ae32a1SGerd Hoffmann } 1630f1ae32a1SGerd Hoffmann 1631f1ae32a1SGerd Hoffmann static void ohci_mem_write(void *opaque, 1632a8170e5eSAvi Kivity hwaddr addr, 1633f1ae32a1SGerd Hoffmann uint64_t val, 1634f1ae32a1SGerd Hoffmann unsigned size) 1635f1ae32a1SGerd Hoffmann { 1636f1ae32a1SGerd Hoffmann OHCIState *ohci = opaque; 1637f1ae32a1SGerd Hoffmann 1638f1ae32a1SGerd Hoffmann /* Only aligned reads are allowed on OHCI */ 1639f1ae32a1SGerd Hoffmann if (addr & 3) { 1640dc1f5988SAlexey Kardashevskiy trace_usb_ohci_mem_write_unaligned(addr); 1641f1ae32a1SGerd Hoffmann return; 1642f1ae32a1SGerd Hoffmann } 1643f1ae32a1SGerd Hoffmann 1644f1ae32a1SGerd Hoffmann if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) { 1645f1ae32a1SGerd Hoffmann /* HcRhPortStatus */ 16469ae8d31dSBALATON Zoltan trace_usb_ohci_mem_port_write(size, "HcRhPortStatus", 16479ae8d31dSBALATON Zoltan (addr - 0x50) >> 2, addr, addr >> 2, val); 1648f1ae32a1SGerd Hoffmann ohci_port_set_status(ohci, (addr - 0x54) >> 2, val); 1649f1ae32a1SGerd Hoffmann return; 1650f1ae32a1SGerd Hoffmann } 1651f1ae32a1SGerd Hoffmann 16529ae8d31dSBALATON Zoltan trace_usb_ohci_mem_write(size, ohci_reg_name(addr), addr, addr >> 2, val); 1653f1ae32a1SGerd Hoffmann switch (addr >> 2) { 1654f1ae32a1SGerd Hoffmann case 1: /* HcControl */ 1655f1ae32a1SGerd Hoffmann ohci_set_ctl(ohci, val); 1656f1ae32a1SGerd Hoffmann break; 1657f1ae32a1SGerd Hoffmann 1658f1ae32a1SGerd Hoffmann case 2: /* HcCommandStatus */ 1659f1ae32a1SGerd Hoffmann /* SOC is read-only */ 1660f1ae32a1SGerd Hoffmann val = (val & ~OHCI_STATUS_SOC); 1661f1ae32a1SGerd Hoffmann 1662f1ae32a1SGerd Hoffmann /* Bits written as '0' remain unchanged in the register */ 1663f1ae32a1SGerd Hoffmann ohci->status |= val; 1664f1ae32a1SGerd Hoffmann 16651e58e7a0SBALATON Zoltan if (ohci->status & OHCI_STATUS_HCR) { 16660922c3f6SHervé Poussineau ohci_soft_reset(ohci); 16671e58e7a0SBALATON Zoltan } 1668f1ae32a1SGerd Hoffmann break; 1669f1ae32a1SGerd Hoffmann 1670f1ae32a1SGerd Hoffmann case 3: /* HcInterruptStatus */ 1671f1ae32a1SGerd Hoffmann ohci->intr_status &= ~val; 1672f1ae32a1SGerd Hoffmann ohci_intr_update(ohci); 1673f1ae32a1SGerd Hoffmann break; 1674f1ae32a1SGerd Hoffmann 1675f1ae32a1SGerd Hoffmann case 4: /* HcInterruptEnable */ 1676f1ae32a1SGerd Hoffmann ohci->intr |= val; 1677f1ae32a1SGerd Hoffmann ohci_intr_update(ohci); 1678f1ae32a1SGerd Hoffmann break; 1679f1ae32a1SGerd Hoffmann 1680f1ae32a1SGerd Hoffmann case 5: /* HcInterruptDisable */ 1681f1ae32a1SGerd Hoffmann ohci->intr &= ~val; 1682f1ae32a1SGerd Hoffmann ohci_intr_update(ohci); 1683f1ae32a1SGerd Hoffmann break; 1684f1ae32a1SGerd Hoffmann 1685f1ae32a1SGerd Hoffmann case 6: /* HcHCCA */ 1686f1ae32a1SGerd Hoffmann ohci->hcca = val & OHCI_HCCA_MASK; 1687f1ae32a1SGerd Hoffmann break; 1688f1ae32a1SGerd Hoffmann 1689f1ae32a1SGerd Hoffmann case 7: /* HcPeriodCurrentED */ 1690f1ae32a1SGerd Hoffmann /* Ignore writes to this read-only register, Linux does them */ 1691f1ae32a1SGerd Hoffmann break; 1692f1ae32a1SGerd Hoffmann 1693f1ae32a1SGerd Hoffmann case 8: /* HcControlHeadED */ 1694f1ae32a1SGerd Hoffmann ohci->ctrl_head = val & OHCI_EDPTR_MASK; 1695f1ae32a1SGerd Hoffmann break; 1696f1ae32a1SGerd Hoffmann 1697f1ae32a1SGerd Hoffmann case 9: /* HcControlCurrentED */ 1698f1ae32a1SGerd Hoffmann ohci->ctrl_cur = val & OHCI_EDPTR_MASK; 1699f1ae32a1SGerd Hoffmann break; 1700f1ae32a1SGerd Hoffmann 1701f1ae32a1SGerd Hoffmann case 10: /* HcBulkHeadED */ 1702f1ae32a1SGerd Hoffmann ohci->bulk_head = val & OHCI_EDPTR_MASK; 1703f1ae32a1SGerd Hoffmann break; 1704f1ae32a1SGerd Hoffmann 1705f1ae32a1SGerd Hoffmann case 11: /* HcBulkCurrentED */ 1706f1ae32a1SGerd Hoffmann ohci->bulk_cur = val & OHCI_EDPTR_MASK; 1707f1ae32a1SGerd Hoffmann break; 1708f1ae32a1SGerd Hoffmann 1709f1ae32a1SGerd Hoffmann case 13: /* HcFmInterval */ 1710f1ae32a1SGerd Hoffmann ohci->fsmps = (val & OHCI_FMI_FSMPS) >> 16; 1711f1ae32a1SGerd Hoffmann ohci->fit = (val & OHCI_FMI_FIT) >> 31; 1712f1ae32a1SGerd Hoffmann ohci_set_frame_interval(ohci, val); 1713f1ae32a1SGerd Hoffmann break; 1714f1ae32a1SGerd Hoffmann 1715f1ae32a1SGerd Hoffmann case 15: /* HcFmNumber */ 1716f1ae32a1SGerd Hoffmann break; 1717f1ae32a1SGerd Hoffmann 1718f1ae32a1SGerd Hoffmann case 16: /* HcPeriodicStart */ 1719f1ae32a1SGerd Hoffmann ohci->pstart = val & 0xffff; 1720f1ae32a1SGerd Hoffmann break; 1721f1ae32a1SGerd Hoffmann 1722f1ae32a1SGerd Hoffmann case 17: /* HcLSThreshold */ 1723f1ae32a1SGerd Hoffmann ohci->lst = val & 0xffff; 1724f1ae32a1SGerd Hoffmann break; 1725f1ae32a1SGerd Hoffmann 1726f1ae32a1SGerd Hoffmann case 18: /* HcRhDescriptorA */ 1727f1ae32a1SGerd Hoffmann ohci->rhdesc_a &= ~OHCI_RHA_RW_MASK; 1728f1ae32a1SGerd Hoffmann ohci->rhdesc_a |= val & OHCI_RHA_RW_MASK; 1729f1ae32a1SGerd Hoffmann break; 1730f1ae32a1SGerd Hoffmann 1731f1ae32a1SGerd Hoffmann case 19: /* HcRhDescriptorB */ 1732f1ae32a1SGerd Hoffmann break; 1733f1ae32a1SGerd Hoffmann 1734f1ae32a1SGerd Hoffmann case 20: /* HcRhStatus */ 1735f1ae32a1SGerd Hoffmann ohci_set_hub_status(ohci, val); 1736f1ae32a1SGerd Hoffmann break; 1737f1ae32a1SGerd Hoffmann 1738f1ae32a1SGerd Hoffmann /* PXA27x specific registers */ 1739f1ae32a1SGerd Hoffmann case 24: /* HcStatus */ 1740f1ae32a1SGerd Hoffmann ohci->hstatus &= ~(val & ohci->hmask); 17417fa96d73SGerd Hoffmann break; 1742f1ae32a1SGerd Hoffmann 1743f1ae32a1SGerd Hoffmann case 25: /* HcHReset */ 1744f1ae32a1SGerd Hoffmann ohci->hreset = val & ~OHCI_HRESET_FSBIR; 17451e58e7a0SBALATON Zoltan if (val & OHCI_HRESET_FSBIR) { 174684d04e21SHervé Poussineau ohci_hard_reset(ohci); 17471e58e7a0SBALATON Zoltan } 1748f1ae32a1SGerd Hoffmann break; 1749f1ae32a1SGerd Hoffmann 1750f1ae32a1SGerd Hoffmann case 26: /* HcHInterruptEnable */ 1751f1ae32a1SGerd Hoffmann ohci->hmask = val; 1752f1ae32a1SGerd Hoffmann break; 1753f1ae32a1SGerd Hoffmann 1754f1ae32a1SGerd Hoffmann case 27: /* HcHInterruptTest */ 1755f1ae32a1SGerd Hoffmann ohci->htest = val; 1756f1ae32a1SGerd Hoffmann break; 1757f1ae32a1SGerd Hoffmann 1758f1ae32a1SGerd Hoffmann default: 1759dc1f5988SAlexey Kardashevskiy trace_usb_ohci_mem_write_bad_offset(addr); 1760f1ae32a1SGerd Hoffmann break; 1761f1ae32a1SGerd Hoffmann } 1762f1ae32a1SGerd Hoffmann } 1763f1ae32a1SGerd Hoffmann 176437bf0654SBALATON Zoltan static const MemoryRegionOps ohci_mem_ops = { 176537bf0654SBALATON Zoltan .read = ohci_mem_read, 176637bf0654SBALATON Zoltan .write = ohci_mem_write, 176737bf0654SBALATON Zoltan .endianness = DEVICE_LITTLE_ENDIAN, 176837bf0654SBALATON Zoltan }; 176937bf0654SBALATON Zoltan 177037bf0654SBALATON Zoltan /* USBPortOps */ 177137bf0654SBALATON Zoltan static void ohci_attach(USBPort *port1) 177237bf0654SBALATON Zoltan { 177337bf0654SBALATON Zoltan OHCIState *s = port1->opaque; 177437bf0654SBALATON Zoltan OHCIPort *port = &s->rhport[port1->index]; 177537bf0654SBALATON Zoltan uint32_t old_state = port->ctrl; 177637bf0654SBALATON Zoltan 177737bf0654SBALATON Zoltan /* set connect status */ 177837bf0654SBALATON Zoltan port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC; 177937bf0654SBALATON Zoltan 178037bf0654SBALATON Zoltan /* update speed */ 178137bf0654SBALATON Zoltan if (port->port.dev->speed == USB_SPEED_LOW) { 178237bf0654SBALATON Zoltan port->ctrl |= OHCI_PORT_LSDA; 178337bf0654SBALATON Zoltan } else { 178437bf0654SBALATON Zoltan port->ctrl &= ~OHCI_PORT_LSDA; 178537bf0654SBALATON Zoltan } 178637bf0654SBALATON Zoltan 178737bf0654SBALATON Zoltan /* notify of remote-wakeup */ 178837bf0654SBALATON Zoltan if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) { 178937bf0654SBALATON Zoltan ohci_set_interrupt(s, OHCI_INTR_RD); 179037bf0654SBALATON Zoltan } 179137bf0654SBALATON Zoltan 179237bf0654SBALATON Zoltan trace_usb_ohci_port_attach(port1->index); 179337bf0654SBALATON Zoltan 179437bf0654SBALATON Zoltan if (old_state != port->ctrl) { 179537bf0654SBALATON Zoltan ohci_set_interrupt(s, OHCI_INTR_RHSC); 179637bf0654SBALATON Zoltan } 179737bf0654SBALATON Zoltan } 179837bf0654SBALATON Zoltan 1799b6b0c066SBALATON Zoltan static void ohci_child_detach(USBPort *port1, USBDevice *dev) 1800f1ae32a1SGerd Hoffmann { 1801b6b0c066SBALATON Zoltan OHCIState *ohci = port1->opaque; 1802b6b0c066SBALATON Zoltan 1803f1ae32a1SGerd Hoffmann if (ohci->async_td && 1804f1ae32a1SGerd Hoffmann usb_packet_is_inflight(&ohci->usb_packet) && 1805f1ae32a1SGerd Hoffmann ohci->usb_packet.ep->dev == dev) { 1806f1ae32a1SGerd Hoffmann usb_cancel_packet(&ohci->usb_packet); 1807f1ae32a1SGerd Hoffmann ohci->async_td = 0; 1808f1ae32a1SGerd Hoffmann } 1809f1ae32a1SGerd Hoffmann } 1810f1ae32a1SGerd Hoffmann 181137bf0654SBALATON Zoltan static void ohci_detach(USBPort *port1) 181237bf0654SBALATON Zoltan { 181337bf0654SBALATON Zoltan OHCIState *s = port1->opaque; 181437bf0654SBALATON Zoltan OHCIPort *port = &s->rhport[port1->index]; 181537bf0654SBALATON Zoltan uint32_t old_state = port->ctrl; 181637bf0654SBALATON Zoltan 1817b6b0c066SBALATON Zoltan ohci_child_detach(port1, port1->dev); 181837bf0654SBALATON Zoltan 181937bf0654SBALATON Zoltan /* set connect status */ 182037bf0654SBALATON Zoltan if (port->ctrl & OHCI_PORT_CCS) { 182137bf0654SBALATON Zoltan port->ctrl &= ~OHCI_PORT_CCS; 182237bf0654SBALATON Zoltan port->ctrl |= OHCI_PORT_CSC; 182337bf0654SBALATON Zoltan } 182437bf0654SBALATON Zoltan /* disable port */ 182537bf0654SBALATON Zoltan if (port->ctrl & OHCI_PORT_PES) { 182637bf0654SBALATON Zoltan port->ctrl &= ~OHCI_PORT_PES; 182737bf0654SBALATON Zoltan port->ctrl |= OHCI_PORT_PESC; 182837bf0654SBALATON Zoltan } 182937bf0654SBALATON Zoltan trace_usb_ohci_port_detach(port1->index); 183037bf0654SBALATON Zoltan 183137bf0654SBALATON Zoltan if (old_state != port->ctrl) { 183237bf0654SBALATON Zoltan ohci_set_interrupt(s, OHCI_INTR_RHSC); 183337bf0654SBALATON Zoltan } 183437bf0654SBALATON Zoltan } 183537bf0654SBALATON Zoltan 183637bf0654SBALATON Zoltan static void ohci_wakeup(USBPort *port1) 183737bf0654SBALATON Zoltan { 183837bf0654SBALATON Zoltan OHCIState *s = port1->opaque; 183937bf0654SBALATON Zoltan OHCIPort *port = &s->rhport[port1->index]; 184037bf0654SBALATON Zoltan uint32_t intr = 0; 184137bf0654SBALATON Zoltan if (port->ctrl & OHCI_PORT_PSS) { 184237bf0654SBALATON Zoltan trace_usb_ohci_port_wakeup(port1->index); 184337bf0654SBALATON Zoltan port->ctrl |= OHCI_PORT_PSSC; 184437bf0654SBALATON Zoltan port->ctrl &= ~OHCI_PORT_PSS; 184537bf0654SBALATON Zoltan intr = OHCI_INTR_RHSC; 184637bf0654SBALATON Zoltan } 184737bf0654SBALATON Zoltan /* Note that the controller can be suspended even if this port is not */ 18480c38e9ddSBALATON Zoltan if (ohci_resume(s)) { 184937bf0654SBALATON Zoltan /* 185037bf0654SBALATON Zoltan * In suspend mode only ResumeDetected is possible, not RHSC: 185137bf0654SBALATON Zoltan * see the OHCI spec 5.1.2.3. 185237bf0654SBALATON Zoltan */ 185337bf0654SBALATON Zoltan intr = OHCI_INTR_RD; 185437bf0654SBALATON Zoltan } 185537bf0654SBALATON Zoltan ohci_set_interrupt(s, intr); 185637bf0654SBALATON Zoltan } 185737bf0654SBALATON Zoltan 185837bf0654SBALATON Zoltan static void ohci_async_complete_packet(USBPort *port, USBPacket *packet) 185937bf0654SBALATON Zoltan { 186037bf0654SBALATON Zoltan OHCIState *ohci = container_of(packet, OHCIState, usb_packet); 186137bf0654SBALATON Zoltan 186237bf0654SBALATON Zoltan trace_usb_ohci_async_complete(); 186337bf0654SBALATON Zoltan ohci->async_complete = true; 18643a4d06f2SBALATON Zoltan ohci_process_lists(ohci); 186537bf0654SBALATON Zoltan } 1866f1ae32a1SGerd Hoffmann 1867f1ae32a1SGerd Hoffmann static USBPortOps ohci_port_ops = { 1868f1ae32a1SGerd Hoffmann .attach = ohci_attach, 1869f1ae32a1SGerd Hoffmann .detach = ohci_detach, 1870f1ae32a1SGerd Hoffmann .child_detach = ohci_child_detach, 1871f1ae32a1SGerd Hoffmann .wakeup = ohci_wakeup, 1872f1ae32a1SGerd Hoffmann .complete = ohci_async_complete_packet, 1873f1ae32a1SGerd Hoffmann }; 1874f1ae32a1SGerd Hoffmann 1875f1ae32a1SGerd Hoffmann static USBBusOps ohci_bus_ops = { 1876f1ae32a1SGerd Hoffmann }; 1877f1ae32a1SGerd Hoffmann 187834d97308SThomas Huth void usb_ohci_init(OHCIState *ohci, DeviceState *dev, uint32_t num_ports, 187934d97308SThomas Huth dma_addr_t localmem_base, char *masterbus, 188034d97308SThomas Huth uint32_t firstport, AddressSpace *as, 18814713720aSPhilippe Mathieu-Daudé void (*ohci_die_fn)(OHCIState *), Error **errp) 1882f1ae32a1SGerd Hoffmann { 1883f4bbaaf5SMarkus Armbruster Error *err = NULL; 1884f1ae32a1SGerd Hoffmann int i; 1885f1ae32a1SGerd Hoffmann 1886df32fd1cSPaolo Bonzini ohci->as = as; 188772e0c127SThomas Huth ohci->ohci_die = ohci_die_fn; 18889ac6a217SDavid Gibson 1889d400fc01SThomas Huth if (num_ports > OHCI_MAX_PORTS) { 1890b9a3a4f2SLi Qiang error_setg(errp, "OHCI num-ports=%u is too big (limit is %u ports)", 1891d400fc01SThomas Huth num_ports, OHCI_MAX_PORTS); 1892d400fc01SThomas Huth return; 1893d400fc01SThomas Huth } 1894d400fc01SThomas Huth 1895f1ae32a1SGerd Hoffmann if (usb_frame_time == 0) { 1896f1ae32a1SGerd Hoffmann #ifdef OHCI_TIME_WARP 189773bcb24dSRutuja Shah usb_frame_time = NANOSECONDS_PER_SECOND; 189873bcb24dSRutuja Shah usb_bit_time = NANOSECONDS_PER_SECOND / (USB_HZ / 1000); 1899f1ae32a1SGerd Hoffmann #else 190073bcb24dSRutuja Shah usb_frame_time = NANOSECONDS_PER_SECOND / 1000; 190173bcb24dSRutuja Shah if (NANOSECONDS_PER_SECOND >= USB_HZ) { 190273bcb24dSRutuja Shah usb_bit_time = NANOSECONDS_PER_SECOND / USB_HZ; 1903f1ae32a1SGerd Hoffmann } else { 1904f1ae32a1SGerd Hoffmann usb_bit_time = 1; 1905f1ae32a1SGerd Hoffmann } 1906f1ae32a1SGerd Hoffmann #endif 1907dc1f5988SAlexey Kardashevskiy trace_usb_ohci_init_time(usb_frame_time, usb_bit_time); 1908f1ae32a1SGerd Hoffmann } 1909f1ae32a1SGerd Hoffmann 1910f1ae32a1SGerd Hoffmann ohci->num_ports = num_ports; 1911f1ae32a1SGerd Hoffmann if (masterbus) { 1912f1ae32a1SGerd Hoffmann USBPort *ports[OHCI_MAX_PORTS]; 1913f1ae32a1SGerd Hoffmann for (i = 0; i < num_ports; i++) { 1914f1ae32a1SGerd Hoffmann ports[i] = &ohci->rhport[i].port; 1915f1ae32a1SGerd Hoffmann } 1916f4bbaaf5SMarkus Armbruster usb_register_companion(masterbus, ports, num_ports, 1917f1ae32a1SGerd Hoffmann firstport, ohci, &ohci_port_ops, 1918f4bbaaf5SMarkus Armbruster USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL, 1919f4bbaaf5SMarkus Armbruster &err); 1920f4bbaaf5SMarkus Armbruster if (err) { 192187581feaSMarkus Armbruster error_propagate(errp, err); 192287581feaSMarkus Armbruster return; 1923f1ae32a1SGerd Hoffmann } 1924f1ae32a1SGerd Hoffmann } else { 1925c889b3a5SAndreas Färber usb_bus_new(&ohci->bus, sizeof(ohci->bus), &ohci_bus_ops, dev); 1926f1ae32a1SGerd Hoffmann for (i = 0; i < num_ports; i++) { 1927f1ae32a1SGerd Hoffmann usb_register_port(&ohci->bus, &ohci->rhport[i].port, 1928f1ae32a1SGerd Hoffmann ohci, i, &ohci_port_ops, 1929f1ae32a1SGerd Hoffmann USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL); 1930f1ae32a1SGerd Hoffmann } 1931f1ae32a1SGerd Hoffmann } 1932f1ae32a1SGerd Hoffmann 193322fc860bSPaolo Bonzini memory_region_init_io(&ohci->mem, OBJECT(dev), &ohci_mem_ops, 193422fc860bSPaolo Bonzini ohci, "ohci", 256); 1935f1ae32a1SGerd Hoffmann ohci->localmem_base = localmem_base; 1936f1ae32a1SGerd Hoffmann 1937f1ae32a1SGerd Hoffmann ohci->name = object_get_typename(OBJECT(dev)); 1938f1ae32a1SGerd Hoffmann usb_packet_init(&ohci->usb_packet); 1939f1ae32a1SGerd Hoffmann 1940f1ae32a1SGerd Hoffmann ohci->async_td = 0; 1941fa1298c2SGerd Hoffmann 1942fa1298c2SGerd Hoffmann ohci->eof_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, 1943fa1298c2SGerd Hoffmann ohci_frame_boundary, ohci); 1944f1ae32a1SGerd Hoffmann } 1945f1ae32a1SGerd Hoffmann 1946572a6732SBALATON Zoltan /* 194772e0c127SThomas Huth * A typical OHCI will stop operating and set itself into error state 194872e0c127SThomas Huth * (which can be queried by MMIO) to signal that it got an error. 1949cf66ee8eSAlexey Kardashevskiy */ 195034d97308SThomas Huth void ohci_sysbus_die(struct OHCIState *ohci) 1951cf66ee8eSAlexey Kardashevskiy { 1952dc1f5988SAlexey Kardashevskiy trace_usb_ohci_die(); 1953cf66ee8eSAlexey Kardashevskiy 1954cf66ee8eSAlexey Kardashevskiy ohci_set_interrupt(ohci, OHCI_INTR_UE); 1955cf66ee8eSAlexey Kardashevskiy ohci_bus_stop(ohci); 195672e0c127SThomas Huth } 195772e0c127SThomas Huth 1958457215ecSHu Tao static void ohci_realize_pxa(DeviceState *dev, Error **errp) 1959f1ae32a1SGerd Hoffmann { 19601aa0c0c7SHu Tao OHCISysBusState *s = SYSBUS_OHCI(dev); 1961457215ecSHu Tao SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 1962d7145b66SBALATON Zoltan Error *err = NULL; 1963f1ae32a1SGerd Hoffmann 1964d7145b66SBALATON Zoltan usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset, 1965d7145b66SBALATON Zoltan s->masterbus, s->firstport, 196672e0c127SThomas Huth &address_space_memory, ohci_sysbus_die, &err); 1967d7145b66SBALATON Zoltan if (err) { 1968d7145b66SBALATON Zoltan error_propagate(errp, err); 1969d7145b66SBALATON Zoltan return; 1970d7145b66SBALATON Zoltan } 1971457215ecSHu Tao sysbus_init_irq(sbd, &s->ohci.irq); 1972457215ecSHu Tao sysbus_init_mmio(sbd, &s->ohci.mem); 1973f1ae32a1SGerd Hoffmann } 1974f1ae32a1SGerd Hoffmann 197588dd1b8dSGonglei static void usb_ohci_reset_sysbus(DeviceState *dev) 197688dd1b8dSGonglei { 197788dd1b8dSGonglei OHCISysBusState *s = SYSBUS_OHCI(dev); 197888dd1b8dSGonglei OHCIState *ohci = &s->ohci; 197988dd1b8dSGonglei 198084d04e21SHervé Poussineau ohci_hard_reset(ohci); 198188dd1b8dSGonglei } 198288dd1b8dSGonglei 198369e25d26SAlexey Kardashevskiy static const VMStateDescription vmstate_ohci_state_port = { 198469e25d26SAlexey Kardashevskiy .name = "ohci-core/port", 198569e25d26SAlexey Kardashevskiy .version_id = 1, 198669e25d26SAlexey Kardashevskiy .minimum_version_id = 1, 198769e25d26SAlexey Kardashevskiy .fields = (VMStateField[]) { 198869e25d26SAlexey Kardashevskiy VMSTATE_UINT32(ctrl, OHCIPort), 198969e25d26SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 199069e25d26SAlexey Kardashevskiy }, 199169e25d26SAlexey Kardashevskiy }; 199269e25d26SAlexey Kardashevskiy 199369e25d26SAlexey Kardashevskiy static bool ohci_eof_timer_needed(void *opaque) 199469e25d26SAlexey Kardashevskiy { 199569e25d26SAlexey Kardashevskiy OHCIState *ohci = opaque; 199669e25d26SAlexey Kardashevskiy 1997fa1298c2SGerd Hoffmann return timer_pending(ohci->eof_timer); 199869e25d26SAlexey Kardashevskiy } 199969e25d26SAlexey Kardashevskiy 200069e25d26SAlexey Kardashevskiy static const VMStateDescription vmstate_ohci_eof_timer = { 200169e25d26SAlexey Kardashevskiy .name = "ohci-core/eof-timer", 200269e25d26SAlexey Kardashevskiy .version_id = 1, 200369e25d26SAlexey Kardashevskiy .minimum_version_id = 1, 20045cd8cadaSJuan Quintela .needed = ohci_eof_timer_needed, 200569e25d26SAlexey Kardashevskiy .fields = (VMStateField[]) { 2006e720677eSPaolo Bonzini VMSTATE_TIMER_PTR(eof_timer, OHCIState), 200769e25d26SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 200869e25d26SAlexey Kardashevskiy }, 200969e25d26SAlexey Kardashevskiy }; 201069e25d26SAlexey Kardashevskiy 201134d97308SThomas Huth const VMStateDescription vmstate_ohci_state = { 201269e25d26SAlexey Kardashevskiy .name = "ohci-core", 201369e25d26SAlexey Kardashevskiy .version_id = 1, 201469e25d26SAlexey Kardashevskiy .minimum_version_id = 1, 201569e25d26SAlexey Kardashevskiy .fields = (VMStateField[]) { 201669e25d26SAlexey Kardashevskiy VMSTATE_INT64(sof_time, OHCIState), 201769e25d26SAlexey Kardashevskiy VMSTATE_UINT32(ctl, OHCIState), 201869e25d26SAlexey Kardashevskiy VMSTATE_UINT32(status, OHCIState), 201969e25d26SAlexey Kardashevskiy VMSTATE_UINT32(intr_status, OHCIState), 202069e25d26SAlexey Kardashevskiy VMSTATE_UINT32(intr, OHCIState), 202169e25d26SAlexey Kardashevskiy VMSTATE_UINT32(hcca, OHCIState), 202269e25d26SAlexey Kardashevskiy VMSTATE_UINT32(ctrl_head, OHCIState), 202369e25d26SAlexey Kardashevskiy VMSTATE_UINT32(ctrl_cur, OHCIState), 202469e25d26SAlexey Kardashevskiy VMSTATE_UINT32(bulk_head, OHCIState), 202569e25d26SAlexey Kardashevskiy VMSTATE_UINT32(bulk_cur, OHCIState), 202669e25d26SAlexey Kardashevskiy VMSTATE_UINT32(per_cur, OHCIState), 202769e25d26SAlexey Kardashevskiy VMSTATE_UINT32(done, OHCIState), 202869e25d26SAlexey Kardashevskiy VMSTATE_INT32(done_count, OHCIState), 202969e25d26SAlexey Kardashevskiy VMSTATE_UINT16(fsmps, OHCIState), 203069e25d26SAlexey Kardashevskiy VMSTATE_UINT8(fit, OHCIState), 203169e25d26SAlexey Kardashevskiy VMSTATE_UINT16(fi, OHCIState), 203269e25d26SAlexey Kardashevskiy VMSTATE_UINT8(frt, OHCIState), 203369e25d26SAlexey Kardashevskiy VMSTATE_UINT16(frame_number, OHCIState), 203469e25d26SAlexey Kardashevskiy VMSTATE_UINT16(padding, OHCIState), 203569e25d26SAlexey Kardashevskiy VMSTATE_UINT32(pstart, OHCIState), 203669e25d26SAlexey Kardashevskiy VMSTATE_UINT32(lst, OHCIState), 203769e25d26SAlexey Kardashevskiy VMSTATE_UINT32(rhdesc_a, OHCIState), 203869e25d26SAlexey Kardashevskiy VMSTATE_UINT32(rhdesc_b, OHCIState), 203969e25d26SAlexey Kardashevskiy VMSTATE_UINT32(rhstatus, OHCIState), 204069e25d26SAlexey Kardashevskiy VMSTATE_STRUCT_ARRAY(rhport, OHCIState, OHCI_MAX_PORTS, 0, 204169e25d26SAlexey Kardashevskiy vmstate_ohci_state_port, OHCIPort), 204269e25d26SAlexey Kardashevskiy VMSTATE_UINT32(hstatus, OHCIState), 204369e25d26SAlexey Kardashevskiy VMSTATE_UINT32(hmask, OHCIState), 204469e25d26SAlexey Kardashevskiy VMSTATE_UINT32(hreset, OHCIState), 204569e25d26SAlexey Kardashevskiy VMSTATE_UINT32(htest, OHCIState), 204669e25d26SAlexey Kardashevskiy VMSTATE_UINT32(old_ctl, OHCIState), 204769e25d26SAlexey Kardashevskiy VMSTATE_UINT8_ARRAY(usb_buf, OHCIState, 8192), 204869e25d26SAlexey Kardashevskiy VMSTATE_UINT32(async_td, OHCIState), 204969e25d26SAlexey Kardashevskiy VMSTATE_BOOL(async_complete, OHCIState), 205069e25d26SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 205169e25d26SAlexey Kardashevskiy }, 20525cd8cadaSJuan Quintela .subsections = (const VMStateDescription*[]) { 20535cd8cadaSJuan Quintela &vmstate_ohci_eof_timer, 20545cd8cadaSJuan Quintela NULL 205569e25d26SAlexey Kardashevskiy } 205669e25d26SAlexey Kardashevskiy }; 205769e25d26SAlexey Kardashevskiy 2058f1ae32a1SGerd Hoffmann static Property ohci_sysbus_properties[] = { 2059d7145b66SBALATON Zoltan DEFINE_PROP_STRING("masterbus", OHCISysBusState, masterbus), 2060f1ae32a1SGerd Hoffmann DEFINE_PROP_UINT32("num-ports", OHCISysBusState, num_ports, 3), 2061d7145b66SBALATON Zoltan DEFINE_PROP_UINT32("firstport", OHCISysBusState, firstport, 0), 20626998b6c7SVijay Kumar B DEFINE_PROP_DMAADDR("dma-offset", OHCISysBusState, dma_offset, 0), 2063f1ae32a1SGerd Hoffmann DEFINE_PROP_END_OF_LIST(), 2064f1ae32a1SGerd Hoffmann }; 2065f1ae32a1SGerd Hoffmann 2066f1ae32a1SGerd Hoffmann static void ohci_sysbus_class_init(ObjectClass *klass, void *data) 2067f1ae32a1SGerd Hoffmann { 2068f1ae32a1SGerd Hoffmann DeviceClass *dc = DEVICE_CLASS(klass); 2069f1ae32a1SGerd Hoffmann 2070457215ecSHu Tao dc->realize = ohci_realize_pxa; 2071125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_USB, dc->categories); 2072f1ae32a1SGerd Hoffmann dc->desc = "OHCI USB Controller"; 20734f67d30bSMarc-André Lureau device_class_set_props(dc, ohci_sysbus_properties); 207488dd1b8dSGonglei dc->reset = usb_ohci_reset_sysbus; 2075f1ae32a1SGerd Hoffmann } 2076f1ae32a1SGerd Hoffmann 20778c43a6f0SAndreas Färber static const TypeInfo ohci_sysbus_info = { 20781aa0c0c7SHu Tao .name = TYPE_SYSBUS_OHCI, 2079f1ae32a1SGerd Hoffmann .parent = TYPE_SYS_BUS_DEVICE, 2080f1ae32a1SGerd Hoffmann .instance_size = sizeof(OHCISysBusState), 2081f1ae32a1SGerd Hoffmann .class_init = ohci_sysbus_class_init, 2082f1ae32a1SGerd Hoffmann }; 2083f1ae32a1SGerd Hoffmann 2084f1ae32a1SGerd Hoffmann static void ohci_register_types(void) 2085f1ae32a1SGerd Hoffmann { 2086f1ae32a1SGerd Hoffmann type_register_static(&ohci_sysbus_info); 2087f1ae32a1SGerd Hoffmann } 2088f1ae32a1SGerd Hoffmann 2089f1ae32a1SGerd Hoffmann type_init(ohci_register_types) 2090