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 */ 42*572a6732SBALATON 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 61f1ae32a1SGerd Hoffmann /* Bitfields for the first word of an Endpoint Desciptor. */ 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 74f1ae32a1SGerd Hoffmann /* Flags in the head field of an Endpoint Desciptor. */ 75f1ae32a1SGerd Hoffmann #define OHCI_ED_H 1 76f1ae32a1SGerd Hoffmann #define OHCI_ED_C 2 77f1ae32a1SGerd Hoffmann 78f1ae32a1SGerd Hoffmann /* Bitfields for the first word of a Transfer Desciptor. */ 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 91f1ae32a1SGerd Hoffmann /* Bitfields for the first word of an Isochronous Transfer Desciptor. */ 92f1ae32a1SGerd Hoffmann /* CC & DI - same as in the General Transfer Desciptor */ 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 98f1ae32a1SGerd Hoffmann /* Isochronous Transfer Desciptor - 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) 215f1ae32a1SGerd Hoffmann #define OHCI_PORT_WTC (OHCI_PORT_CSC|OHCI_PORT_PESC|OHCI_PORT_PSSC \ 216f1ae32a1SGerd Hoffmann |OHCI_PORT_OCIC|OHCI_PORT_PRSC) 217f1ae32a1SGerd Hoffmann 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 23872e0c127SThomas Huth static void ohci_die(OHCIState *ohci) 23972e0c127SThomas Huth { 24072e0c127SThomas Huth ohci->ohci_die(ohci); 24172e0c127SThomas Huth } 242cf66ee8eSAlexey Kardashevskiy 243f1ae32a1SGerd Hoffmann /* Update IRQ levels */ 244f1ae32a1SGerd Hoffmann static inline void ohci_intr_update(OHCIState *ohci) 245f1ae32a1SGerd Hoffmann { 246f1ae32a1SGerd Hoffmann int level = 0; 247f1ae32a1SGerd Hoffmann 248f1ae32a1SGerd Hoffmann if ((ohci->intr & OHCI_INTR_MIE) && 249f1ae32a1SGerd Hoffmann (ohci->intr_status & ohci->intr)) 250f1ae32a1SGerd Hoffmann level = 1; 251f1ae32a1SGerd Hoffmann 252f1ae32a1SGerd Hoffmann qemu_set_irq(ohci->irq, level); 253f1ae32a1SGerd Hoffmann } 254f1ae32a1SGerd Hoffmann 255f1ae32a1SGerd Hoffmann /* Set an interrupt */ 256f1ae32a1SGerd Hoffmann static inline void ohci_set_interrupt(OHCIState *ohci, uint32_t intr) 257f1ae32a1SGerd Hoffmann { 258f1ae32a1SGerd Hoffmann ohci->intr_status |= intr; 259f1ae32a1SGerd Hoffmann ohci_intr_update(ohci); 260f1ae32a1SGerd Hoffmann } 261f1ae32a1SGerd Hoffmann 262f1ae32a1SGerd Hoffmann static USBDevice *ohci_find_device(OHCIState *ohci, uint8_t addr) 263f1ae32a1SGerd Hoffmann { 264f1ae32a1SGerd Hoffmann USBDevice *dev; 265f1ae32a1SGerd Hoffmann int i; 266f1ae32a1SGerd Hoffmann 267f1ae32a1SGerd Hoffmann for (i = 0; i < ohci->num_ports; i++) { 268f1ae32a1SGerd Hoffmann if ((ohci->rhport[i].ctrl & OHCI_PORT_PES) == 0) { 269f1ae32a1SGerd Hoffmann continue; 270f1ae32a1SGerd Hoffmann } 271f1ae32a1SGerd Hoffmann dev = usb_find_device(&ohci->rhport[i].port, addr); 272f1ae32a1SGerd Hoffmann if (dev != NULL) { 273f1ae32a1SGerd Hoffmann return dev; 274f1ae32a1SGerd Hoffmann } 275f1ae32a1SGerd Hoffmann } 276f1ae32a1SGerd Hoffmann return NULL; 277f1ae32a1SGerd Hoffmann } 278f1ae32a1SGerd Hoffmann 27934d97308SThomas Huth void ohci_stop_endpoints(OHCIState *ohci) 280f79738b0SHans de Goede { 281f79738b0SHans de Goede USBDevice *dev; 282f79738b0SHans de Goede int i, j; 283f79738b0SHans de Goede 284ae310557SBALATON Zoltan if (ohci->async_td) { 285ae310557SBALATON Zoltan usb_cancel_packet(&ohci->usb_packet); 286ae310557SBALATON Zoltan ohci->async_td = 0; 287ae310557SBALATON Zoltan } 288f79738b0SHans de Goede for (i = 0; i < ohci->num_ports; i++) { 289f79738b0SHans de Goede dev = ohci->rhport[i].port.dev; 290f79738b0SHans de Goede if (dev && dev->attached) { 291f79738b0SHans de Goede usb_device_ep_stopped(dev, &dev->ep_ctl); 292f79738b0SHans de Goede for (j = 0; j < USB_MAX_ENDPOINTS; j++) { 293f79738b0SHans de Goede usb_device_ep_stopped(dev, &dev->ep_in[j]); 294f79738b0SHans de Goede usb_device_ep_stopped(dev, &dev->ep_out[j]); 295f79738b0SHans de Goede } 296f79738b0SHans de Goede } 297f79738b0SHans de Goede } 298f79738b0SHans de Goede } 299f79738b0SHans de Goede 30084d04e21SHervé Poussineau static void ohci_roothub_reset(OHCIState *ohci) 301f1ae32a1SGerd Hoffmann { 302f1ae32a1SGerd Hoffmann OHCIPort *port; 303f1ae32a1SGerd Hoffmann int i; 304f1ae32a1SGerd Hoffmann 305f1ae32a1SGerd Hoffmann ohci_bus_stop(ohci); 30684d04e21SHervé Poussineau ohci->rhdesc_a = OHCI_RHA_NPS | ohci->num_ports; 30784d04e21SHervé Poussineau ohci->rhdesc_b = 0x0; /* Impl. specific */ 30884d04e21SHervé Poussineau ohci->rhstatus = 0; 30984d04e21SHervé Poussineau 31084d04e21SHervé Poussineau for (i = 0; i < ohci->num_ports; i++) { 31184d04e21SHervé Poussineau port = &ohci->rhport[i]; 31284d04e21SHervé Poussineau port->ctrl = 0; 31384d04e21SHervé Poussineau if (port->port.dev && port->port.dev->attached) { 31484d04e21SHervé Poussineau usb_port_reset(&port->port); 31584d04e21SHervé Poussineau } 31684d04e21SHervé Poussineau } 31784d04e21SHervé Poussineau ohci_stop_endpoints(ohci); 31884d04e21SHervé Poussineau } 31984d04e21SHervé Poussineau 32084d04e21SHervé Poussineau /* Reset the controller */ 32184d04e21SHervé Poussineau static void ohci_soft_reset(OHCIState *ohci) 32284d04e21SHervé Poussineau { 32384d04e21SHervé Poussineau trace_usb_ohci_reset(ohci->name); 32484d04e21SHervé Poussineau 32584d04e21SHervé Poussineau ohci_bus_stop(ohci); 32684d04e21SHervé Poussineau ohci->ctl = (ohci->ctl & OHCI_CTL_IR) | OHCI_USB_SUSPEND; 327f1ae32a1SGerd Hoffmann ohci->old_ctl = 0; 328f1ae32a1SGerd Hoffmann ohci->status = 0; 329f1ae32a1SGerd Hoffmann ohci->intr_status = 0; 330f1ae32a1SGerd Hoffmann ohci->intr = OHCI_INTR_MIE; 331f1ae32a1SGerd Hoffmann 332f1ae32a1SGerd Hoffmann ohci->hcca = 0; 333f1ae32a1SGerd Hoffmann ohci->ctrl_head = ohci->ctrl_cur = 0; 334f1ae32a1SGerd Hoffmann ohci->bulk_head = ohci->bulk_cur = 0; 335f1ae32a1SGerd Hoffmann ohci->per_cur = 0; 336f1ae32a1SGerd Hoffmann ohci->done = 0; 337f1ae32a1SGerd Hoffmann ohci->done_count = 7; 338*572a6732SBALATON Zoltan /* 339*572a6732SBALATON Zoltan * FSMPS is marked TBD in OCHI 1.0, what gives ffs? 340f1ae32a1SGerd Hoffmann * I took the value linux sets ... 341f1ae32a1SGerd Hoffmann */ 342f1ae32a1SGerd Hoffmann ohci->fsmps = 0x2778; 343f1ae32a1SGerd Hoffmann ohci->fi = 0x2edf; 344f1ae32a1SGerd Hoffmann ohci->fit = 0; 345f1ae32a1SGerd Hoffmann ohci->frt = 0; 346f1ae32a1SGerd Hoffmann ohci->frame_number = 0; 347f1ae32a1SGerd Hoffmann ohci->pstart = 0; 348f1ae32a1SGerd Hoffmann ohci->lst = OHCI_LS_THRESH; 34984d04e21SHervé Poussineau } 350f1ae32a1SGerd Hoffmann 35134d97308SThomas Huth void ohci_hard_reset(OHCIState *ohci) 352f1ae32a1SGerd Hoffmann { 35384d04e21SHervé Poussineau ohci_soft_reset(ohci); 35484d04e21SHervé Poussineau ohci->ctl = 0; 35584d04e21SHervé Poussineau ohci_roothub_reset(ohci); 356f1ae32a1SGerd Hoffmann } 357f1ae32a1SGerd Hoffmann 358f1ae32a1SGerd Hoffmann /* Get an array of dwords from main memory */ 359f1ae32a1SGerd Hoffmann static inline int get_dwords(OHCIState *ohci, 3609ac6a217SDavid Gibson dma_addr_t addr, uint32_t *buf, int num) 361f1ae32a1SGerd Hoffmann { 362f1ae32a1SGerd Hoffmann int i; 363f1ae32a1SGerd Hoffmann 364f1ae32a1SGerd Hoffmann addr += ohci->localmem_base; 365f1ae32a1SGerd Hoffmann 366f1ae32a1SGerd Hoffmann for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { 367ba06fe8aSPhilippe Mathieu-Daudé if (dma_memory_read(ohci->as, addr, 368ba06fe8aSPhilippe Mathieu-Daudé buf, sizeof(*buf), MEMTXATTRS_UNSPECIFIED)) { 369cf66ee8eSAlexey Kardashevskiy return -1; 370cf66ee8eSAlexey Kardashevskiy } 371f1ae32a1SGerd Hoffmann *buf = le32_to_cpu(*buf); 372f1ae32a1SGerd Hoffmann } 373f1ae32a1SGerd Hoffmann 374cf66ee8eSAlexey Kardashevskiy return 0; 375f1ae32a1SGerd Hoffmann } 376f1ae32a1SGerd Hoffmann 377f1ae32a1SGerd Hoffmann /* Put an array of dwords in to main memory */ 378f1ae32a1SGerd Hoffmann static inline int put_dwords(OHCIState *ohci, 3799ac6a217SDavid Gibson dma_addr_t addr, uint32_t *buf, int num) 380f1ae32a1SGerd Hoffmann { 381f1ae32a1SGerd Hoffmann int i; 382f1ae32a1SGerd Hoffmann 383f1ae32a1SGerd Hoffmann addr += ohci->localmem_base; 384f1ae32a1SGerd Hoffmann 385f1ae32a1SGerd Hoffmann for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { 386f1ae32a1SGerd Hoffmann uint32_t tmp = cpu_to_le32(*buf); 387ba06fe8aSPhilippe Mathieu-Daudé if (dma_memory_write(ohci->as, addr, 388ba06fe8aSPhilippe Mathieu-Daudé &tmp, sizeof(tmp), MEMTXATTRS_UNSPECIFIED)) { 389cf66ee8eSAlexey Kardashevskiy return -1; 390cf66ee8eSAlexey Kardashevskiy } 391f1ae32a1SGerd Hoffmann } 392f1ae32a1SGerd Hoffmann 393cf66ee8eSAlexey Kardashevskiy return 0; 394f1ae32a1SGerd Hoffmann } 395f1ae32a1SGerd Hoffmann 396f1ae32a1SGerd Hoffmann /* Get an array of words from main memory */ 397f1ae32a1SGerd Hoffmann static inline int get_words(OHCIState *ohci, 3989ac6a217SDavid Gibson dma_addr_t addr, uint16_t *buf, int num) 399f1ae32a1SGerd Hoffmann { 400f1ae32a1SGerd Hoffmann int i; 401f1ae32a1SGerd Hoffmann 402f1ae32a1SGerd Hoffmann addr += ohci->localmem_base; 403f1ae32a1SGerd Hoffmann 404f1ae32a1SGerd Hoffmann for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { 405ba06fe8aSPhilippe Mathieu-Daudé if (dma_memory_read(ohci->as, addr, 406ba06fe8aSPhilippe Mathieu-Daudé buf, sizeof(*buf), MEMTXATTRS_UNSPECIFIED)) { 407cf66ee8eSAlexey Kardashevskiy return -1; 408cf66ee8eSAlexey Kardashevskiy } 409f1ae32a1SGerd Hoffmann *buf = le16_to_cpu(*buf); 410f1ae32a1SGerd Hoffmann } 411f1ae32a1SGerd Hoffmann 412cf66ee8eSAlexey Kardashevskiy return 0; 413f1ae32a1SGerd Hoffmann } 414f1ae32a1SGerd Hoffmann 415f1ae32a1SGerd Hoffmann /* Put an array of words in to main memory */ 416f1ae32a1SGerd Hoffmann static inline int put_words(OHCIState *ohci, 4179ac6a217SDavid Gibson dma_addr_t addr, uint16_t *buf, int num) 418f1ae32a1SGerd Hoffmann { 419f1ae32a1SGerd Hoffmann int i; 420f1ae32a1SGerd Hoffmann 421f1ae32a1SGerd Hoffmann addr += ohci->localmem_base; 422f1ae32a1SGerd Hoffmann 423f1ae32a1SGerd Hoffmann for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { 424f1ae32a1SGerd Hoffmann uint16_t tmp = cpu_to_le16(*buf); 425ba06fe8aSPhilippe Mathieu-Daudé if (dma_memory_write(ohci->as, addr, 426ba06fe8aSPhilippe Mathieu-Daudé &tmp, sizeof(tmp), MEMTXATTRS_UNSPECIFIED)) { 427cf66ee8eSAlexey Kardashevskiy return -1; 428cf66ee8eSAlexey Kardashevskiy } 429f1ae32a1SGerd Hoffmann } 430f1ae32a1SGerd Hoffmann 431cf66ee8eSAlexey Kardashevskiy return 0; 432f1ae32a1SGerd Hoffmann } 433f1ae32a1SGerd Hoffmann 434f1ae32a1SGerd Hoffmann static inline int ohci_read_ed(OHCIState *ohci, 4359ac6a217SDavid Gibson dma_addr_t addr, struct ohci_ed *ed) 436f1ae32a1SGerd Hoffmann { 437f1ae32a1SGerd Hoffmann return get_dwords(ohci, addr, (uint32_t *)ed, sizeof(*ed) >> 2); 438f1ae32a1SGerd Hoffmann } 439f1ae32a1SGerd Hoffmann 440f1ae32a1SGerd Hoffmann static inline int ohci_read_td(OHCIState *ohci, 4419ac6a217SDavid Gibson dma_addr_t addr, struct ohci_td *td) 442f1ae32a1SGerd Hoffmann { 443f1ae32a1SGerd Hoffmann return get_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2); 444f1ae32a1SGerd Hoffmann } 445f1ae32a1SGerd Hoffmann 446f1ae32a1SGerd Hoffmann static inline int ohci_read_iso_td(OHCIState *ohci, 4479ac6a217SDavid Gibson dma_addr_t addr, struct ohci_iso_td *td) 448f1ae32a1SGerd Hoffmann { 449cf66ee8eSAlexey Kardashevskiy return get_dwords(ohci, addr, (uint32_t *)td, 4) || 450cf66ee8eSAlexey Kardashevskiy get_words(ohci, addr + 16, td->offset, 8); 451f1ae32a1SGerd Hoffmann } 452f1ae32a1SGerd Hoffmann 453f1ae32a1SGerd Hoffmann static inline int ohci_read_hcca(OHCIState *ohci, 4549ac6a217SDavid Gibson dma_addr_t addr, struct ohci_hcca *hcca) 455f1ae32a1SGerd Hoffmann { 456ba06fe8aSPhilippe Mathieu-Daudé return dma_memory_read(ohci->as, addr + ohci->localmem_base, hcca, 457ba06fe8aSPhilippe Mathieu-Daudé sizeof(*hcca), MEMTXATTRS_UNSPECIFIED); 458f1ae32a1SGerd Hoffmann } 459f1ae32a1SGerd Hoffmann 460f1ae32a1SGerd Hoffmann static inline int ohci_put_ed(OHCIState *ohci, 4619ac6a217SDavid Gibson dma_addr_t addr, struct ohci_ed *ed) 462f1ae32a1SGerd Hoffmann { 463*572a6732SBALATON Zoltan /* 464*572a6732SBALATON Zoltan * ed->tail is under control of the HCD. 46586e18caeSWei Yang * Since just ed->head is changed by HC, just write back this 46686e18caeSWei Yang */ 46786e18caeSWei Yang return put_dwords(ohci, addr + ED_WBACK_OFFSET, 46886e18caeSWei Yang (uint32_t *)((char *)ed + ED_WBACK_OFFSET), 46986e18caeSWei Yang ED_WBACK_SIZE >> 2); 470f1ae32a1SGerd Hoffmann } 471f1ae32a1SGerd Hoffmann 472f1ae32a1SGerd Hoffmann static inline int ohci_put_td(OHCIState *ohci, 4739ac6a217SDavid Gibson dma_addr_t addr, struct ohci_td *td) 474f1ae32a1SGerd Hoffmann { 475f1ae32a1SGerd Hoffmann return put_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2); 476f1ae32a1SGerd Hoffmann } 477f1ae32a1SGerd Hoffmann 478f1ae32a1SGerd Hoffmann static inline int ohci_put_iso_td(OHCIState *ohci, 4799ac6a217SDavid Gibson dma_addr_t addr, struct ohci_iso_td *td) 480f1ae32a1SGerd Hoffmann { 481cae7f29cSJack Un return put_dwords(ohci, addr, (uint32_t *)td, 4) || 482cae7f29cSJack Un put_words(ohci, addr + 16, td->offset, 8); 483f1ae32a1SGerd Hoffmann } 484f1ae32a1SGerd Hoffmann 485f1ae32a1SGerd Hoffmann static inline int ohci_put_hcca(OHCIState *ohci, 4869ac6a217SDavid Gibson dma_addr_t addr, struct ohci_hcca *hcca) 487f1ae32a1SGerd Hoffmann { 488cf66ee8eSAlexey Kardashevskiy return dma_memory_write(ohci->as, 4899ac6a217SDavid Gibson addr + ohci->localmem_base + HCCA_WRITEBACK_OFFSET, 49086e18caeSWei Yang (char *)hcca + HCCA_WRITEBACK_OFFSET, 491ba06fe8aSPhilippe Mathieu-Daudé HCCA_WRITEBACK_SIZE, MEMTXATTRS_UNSPECIFIED); 492f1ae32a1SGerd Hoffmann } 493f1ae32a1SGerd Hoffmann 494f1ae32a1SGerd Hoffmann /* Read/Write the contents of a TD from/to main memory. */ 495cf66ee8eSAlexey Kardashevskiy static int ohci_copy_td(OHCIState *ohci, struct ohci_td *td, 4969ac6a217SDavid Gibson uint8_t *buf, int len, DMADirection dir) 497f1ae32a1SGerd Hoffmann { 4989ac6a217SDavid Gibson dma_addr_t ptr, n; 499f1ae32a1SGerd Hoffmann 500f1ae32a1SGerd Hoffmann ptr = td->cbp; 501f1ae32a1SGerd Hoffmann n = 0x1000 - (ptr & 0xfff); 502f1ae32a1SGerd Hoffmann if (n > len) 503f1ae32a1SGerd Hoffmann n = len; 504cf66ee8eSAlexey Kardashevskiy 50523faf569SPhilippe Mathieu-Daudé if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, 50623faf569SPhilippe Mathieu-Daudé n, dir, MEMTXATTRS_UNSPECIFIED)) { 507cf66ee8eSAlexey Kardashevskiy return -1; 508cf66ee8eSAlexey Kardashevskiy } 509cf66ee8eSAlexey Kardashevskiy if (n == len) { 510cf66ee8eSAlexey Kardashevskiy return 0; 511cf66ee8eSAlexey Kardashevskiy } 512f1ae32a1SGerd Hoffmann ptr = td->be & ~0xfffu; 513f1ae32a1SGerd Hoffmann buf += n; 514cf66ee8eSAlexey Kardashevskiy if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, 51523faf569SPhilippe Mathieu-Daudé len - n, dir, MEMTXATTRS_UNSPECIFIED)) { 516cf66ee8eSAlexey Kardashevskiy return -1; 517cf66ee8eSAlexey Kardashevskiy } 518cf66ee8eSAlexey Kardashevskiy return 0; 519f1ae32a1SGerd Hoffmann } 520f1ae32a1SGerd Hoffmann 521f1ae32a1SGerd Hoffmann /* Read/Write the contents of an ISO TD from/to main memory. */ 522cf66ee8eSAlexey Kardashevskiy static int ohci_copy_iso_td(OHCIState *ohci, 523f1ae32a1SGerd Hoffmann uint32_t start_addr, uint32_t end_addr, 5249ac6a217SDavid Gibson uint8_t *buf, int len, DMADirection dir) 525f1ae32a1SGerd Hoffmann { 5269ac6a217SDavid Gibson dma_addr_t ptr, n; 527f1ae32a1SGerd Hoffmann 528f1ae32a1SGerd Hoffmann ptr = start_addr; 529f1ae32a1SGerd Hoffmann n = 0x1000 - (ptr & 0xfff); 530f1ae32a1SGerd Hoffmann if (n > len) 531f1ae32a1SGerd Hoffmann n = len; 532cf66ee8eSAlexey Kardashevskiy 53323faf569SPhilippe Mathieu-Daudé if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, 53423faf569SPhilippe Mathieu-Daudé n, dir, MEMTXATTRS_UNSPECIFIED)) { 535cf66ee8eSAlexey Kardashevskiy return -1; 536cf66ee8eSAlexey Kardashevskiy } 537cf66ee8eSAlexey Kardashevskiy if (n == len) { 538cf66ee8eSAlexey Kardashevskiy return 0; 539cf66ee8eSAlexey Kardashevskiy } 540f1ae32a1SGerd Hoffmann ptr = end_addr & ~0xfffu; 541f1ae32a1SGerd Hoffmann buf += n; 542cf66ee8eSAlexey Kardashevskiy if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, 54323faf569SPhilippe Mathieu-Daudé len - n, dir, MEMTXATTRS_UNSPECIFIED)) { 544cf66ee8eSAlexey Kardashevskiy return -1; 545cf66ee8eSAlexey Kardashevskiy } 546cf66ee8eSAlexey Kardashevskiy return 0; 547f1ae32a1SGerd Hoffmann } 548f1ae32a1SGerd Hoffmann 549f1ae32a1SGerd Hoffmann #define USUB(a, b) ((int16_t)((uint16_t)(a) - (uint16_t)(b))) 550f1ae32a1SGerd Hoffmann 5513a4d06f2SBALATON Zoltan static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed) 552f1ae32a1SGerd Hoffmann { 553f1ae32a1SGerd Hoffmann int dir; 554f1ae32a1SGerd Hoffmann size_t len = 0; 555f1ae32a1SGerd Hoffmann const char *str = NULL; 556f1ae32a1SGerd Hoffmann int pid; 557f1ae32a1SGerd Hoffmann int ret; 558f1ae32a1SGerd Hoffmann int i; 559f1ae32a1SGerd Hoffmann USBDevice *dev; 560f1ae32a1SGerd Hoffmann USBEndpoint *ep; 5613a4d06f2SBALATON Zoltan USBPacket *pkt; 5623a4d06f2SBALATON Zoltan uint8_t buf[8192]; 5633a4d06f2SBALATON Zoltan bool int_req; 564f1ae32a1SGerd Hoffmann struct ohci_iso_td iso_td; 565f1ae32a1SGerd Hoffmann uint32_t addr; 566f1ae32a1SGerd Hoffmann uint16_t starting_frame; 567f1ae32a1SGerd Hoffmann int16_t relative_frame_number; 568f1ae32a1SGerd Hoffmann int frame_count; 569f1ae32a1SGerd Hoffmann uint32_t start_offset, next_offset, end_offset = 0; 570f1ae32a1SGerd Hoffmann uint32_t start_addr, end_addr; 571f1ae32a1SGerd Hoffmann 572f1ae32a1SGerd Hoffmann addr = ed->head & OHCI_DPTR_MASK; 573f1ae32a1SGerd Hoffmann 574d8c2e6f2SQiang Liu if (addr == 0) { 575d8c2e6f2SQiang Liu ohci_die(ohci); 576d8c2e6f2SQiang Liu return 1; 577d8c2e6f2SQiang Liu } 578d8c2e6f2SQiang Liu 579cf66ee8eSAlexey Kardashevskiy if (ohci_read_iso_td(ohci, addr, &iso_td)) { 580dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_read_failed(addr); 581cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 58226f670a2SLi Qiang return 1; 583f1ae32a1SGerd Hoffmann } 584f1ae32a1SGerd Hoffmann 585f1ae32a1SGerd Hoffmann starting_frame = OHCI_BM(iso_td.flags, TD_SF); 586f1ae32a1SGerd Hoffmann frame_count = OHCI_BM(iso_td.flags, TD_FC); 587f1ae32a1SGerd Hoffmann relative_frame_number = USUB(ohci->frame_number, starting_frame); 588f1ae32a1SGerd Hoffmann 589dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_head( 590f1ae32a1SGerd Hoffmann ed->head & OHCI_DPTR_MASK, ed->tail & OHCI_DPTR_MASK, 591f1ae32a1SGerd Hoffmann iso_td.flags, iso_td.bp, iso_td.next, iso_td.be, 592f1ae32a1SGerd Hoffmann ohci->frame_number, starting_frame, 593bc0d104cSAlex Bennée frame_count, relative_frame_number); 5943af8f177SAlexey Kardashevskiy trace_usb_ohci_iso_td_head_offset( 5953af8f177SAlexey Kardashevskiy iso_td.offset[0], iso_td.offset[1], 5963af8f177SAlexey Kardashevskiy iso_td.offset[2], iso_td.offset[3], 5973af8f177SAlexey Kardashevskiy iso_td.offset[4], iso_td.offset[5], 5983af8f177SAlexey Kardashevskiy iso_td.offset[6], iso_td.offset[7]); 599f1ae32a1SGerd Hoffmann 600f1ae32a1SGerd Hoffmann if (relative_frame_number < 0) { 601dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_relative_frame_number_neg(relative_frame_number); 602f1ae32a1SGerd Hoffmann return 1; 603f1ae32a1SGerd Hoffmann } else if (relative_frame_number > frame_count) { 604*572a6732SBALATON Zoltan /* 605*572a6732SBALATON Zoltan * ISO TD expired - retire the TD to the Done Queue and continue with 606*572a6732SBALATON Zoltan * the next ISO TD of the same ED 607*572a6732SBALATON Zoltan */ 608dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_relative_frame_number_big(relative_frame_number, 609f1ae32a1SGerd Hoffmann frame_count); 6101be90ebeSPrasad J Pandit if (OHCI_CC_DATAOVERRUN == OHCI_BM(iso_td.flags, TD_CC)) { 6111be90ebeSPrasad J Pandit /* avoid infinite loop */ 6121be90ebeSPrasad J Pandit return 1; 6131be90ebeSPrasad J Pandit } 614f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_DATAOVERRUN); 615f1ae32a1SGerd Hoffmann ed->head &= ~OHCI_DPTR_MASK; 616f1ae32a1SGerd Hoffmann ed->head |= (iso_td.next & OHCI_DPTR_MASK); 617f1ae32a1SGerd Hoffmann iso_td.next = ohci->done; 618f1ae32a1SGerd Hoffmann ohci->done = addr; 619f1ae32a1SGerd Hoffmann i = OHCI_BM(iso_td.flags, TD_DI); 620f1ae32a1SGerd Hoffmann if (i < ohci->done_count) 621f1ae32a1SGerd Hoffmann ohci->done_count = i; 622cf66ee8eSAlexey Kardashevskiy if (ohci_put_iso_td(ohci, addr, &iso_td)) { 623cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 624cf66ee8eSAlexey Kardashevskiy return 1; 625cf66ee8eSAlexey Kardashevskiy } 626f1ae32a1SGerd Hoffmann return 0; 627f1ae32a1SGerd Hoffmann } 628f1ae32a1SGerd Hoffmann 629f1ae32a1SGerd Hoffmann dir = OHCI_BM(ed->flags, ED_D); 630f1ae32a1SGerd Hoffmann switch (dir) { 631f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_IN: 632f1ae32a1SGerd Hoffmann str = "in"; 633f1ae32a1SGerd Hoffmann pid = USB_TOKEN_IN; 634f1ae32a1SGerd Hoffmann break; 635f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_OUT: 636f1ae32a1SGerd Hoffmann str = "out"; 637f1ae32a1SGerd Hoffmann pid = USB_TOKEN_OUT; 638f1ae32a1SGerd Hoffmann break; 639f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_SETUP: 640f1ae32a1SGerd Hoffmann str = "setup"; 641f1ae32a1SGerd Hoffmann pid = USB_TOKEN_SETUP; 642f1ae32a1SGerd Hoffmann break; 643f1ae32a1SGerd Hoffmann default: 644dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_bad_direction(dir); 645f1ae32a1SGerd Hoffmann return 1; 646f1ae32a1SGerd Hoffmann } 647f1ae32a1SGerd Hoffmann 648f1ae32a1SGerd Hoffmann if (!iso_td.bp || !iso_td.be) { 649dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_bad_bp_be(iso_td.bp, iso_td.be); 650f1ae32a1SGerd Hoffmann return 1; 651f1ae32a1SGerd Hoffmann } 652f1ae32a1SGerd Hoffmann 653f1ae32a1SGerd Hoffmann start_offset = iso_td.offset[relative_frame_number]; 6541328fe0cSPrasad J Pandit if (relative_frame_number < frame_count) { 655f1ae32a1SGerd Hoffmann next_offset = iso_td.offset[relative_frame_number + 1]; 6561328fe0cSPrasad J Pandit } else { 6571328fe0cSPrasad J Pandit next_offset = iso_td.be; 6581328fe0cSPrasad J Pandit } 659f1ae32a1SGerd Hoffmann 660f1ae32a1SGerd Hoffmann if (!(OHCI_BM(start_offset, TD_PSW_CC) & 0xe) || 661f1ae32a1SGerd Hoffmann ((relative_frame_number < frame_count) && 662f1ae32a1SGerd Hoffmann !(OHCI_BM(next_offset, TD_PSW_CC) & 0xe))) { 663dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_bad_cc_not_accessed(start_offset, next_offset); 664f1ae32a1SGerd Hoffmann return 1; 665f1ae32a1SGerd Hoffmann } 666f1ae32a1SGerd Hoffmann 667f1ae32a1SGerd Hoffmann if ((relative_frame_number < frame_count) && (start_offset > next_offset)) { 668dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_bad_cc_overrun(start_offset, next_offset); 669f1ae32a1SGerd Hoffmann return 1; 670f1ae32a1SGerd Hoffmann } 671f1ae32a1SGerd Hoffmann 672f1ae32a1SGerd Hoffmann if ((start_offset & 0x1000) == 0) { 673f1ae32a1SGerd Hoffmann start_addr = (iso_td.bp & OHCI_PAGE_MASK) | 674f1ae32a1SGerd Hoffmann (start_offset & OHCI_OFFSET_MASK); 675f1ae32a1SGerd Hoffmann } else { 676f1ae32a1SGerd Hoffmann start_addr = (iso_td.be & OHCI_PAGE_MASK) | 677f1ae32a1SGerd Hoffmann (start_offset & OHCI_OFFSET_MASK); 678f1ae32a1SGerd Hoffmann } 679f1ae32a1SGerd Hoffmann 680f1ae32a1SGerd Hoffmann if (relative_frame_number < frame_count) { 681f1ae32a1SGerd Hoffmann end_offset = next_offset - 1; 682f1ae32a1SGerd Hoffmann if ((end_offset & 0x1000) == 0) { 683f1ae32a1SGerd Hoffmann end_addr = (iso_td.bp & OHCI_PAGE_MASK) | 684f1ae32a1SGerd Hoffmann (end_offset & OHCI_OFFSET_MASK); 685f1ae32a1SGerd Hoffmann } else { 686f1ae32a1SGerd Hoffmann end_addr = (iso_td.be & OHCI_PAGE_MASK) | 687f1ae32a1SGerd Hoffmann (end_offset & OHCI_OFFSET_MASK); 688f1ae32a1SGerd Hoffmann } 689f1ae32a1SGerd Hoffmann } else { 690f1ae32a1SGerd Hoffmann /* Last packet in the ISO TD */ 6911328fe0cSPrasad J Pandit end_addr = next_offset; 6921328fe0cSPrasad J Pandit } 6931328fe0cSPrasad J Pandit 6941328fe0cSPrasad J Pandit if (start_addr > end_addr) { 6951328fe0cSPrasad J Pandit trace_usb_ohci_iso_td_bad_cc_overrun(start_addr, end_addr); 6961328fe0cSPrasad J Pandit return 1; 697f1ae32a1SGerd Hoffmann } 698f1ae32a1SGerd Hoffmann 699f1ae32a1SGerd Hoffmann if ((start_addr & OHCI_PAGE_MASK) != (end_addr & OHCI_PAGE_MASK)) { 700f1ae32a1SGerd Hoffmann len = (end_addr & OHCI_OFFSET_MASK) + 0x1001 701f1ae32a1SGerd Hoffmann - (start_addr & OHCI_OFFSET_MASK); 702f1ae32a1SGerd Hoffmann } else { 703f1ae32a1SGerd Hoffmann len = end_addr - start_addr + 1; 704f1ae32a1SGerd Hoffmann } 7053a4d06f2SBALATON Zoltan if (len > sizeof(buf)) { 7063a4d06f2SBALATON Zoltan len = sizeof(buf); 7071328fe0cSPrasad J Pandit } 708f1ae32a1SGerd Hoffmann 709f1ae32a1SGerd Hoffmann if (len && dir != OHCI_TD_DIR_IN) { 7103a4d06f2SBALATON Zoltan if (ohci_copy_iso_td(ohci, start_addr, end_addr, buf, len, 711cf66ee8eSAlexey Kardashevskiy DMA_DIRECTION_TO_DEVICE)) { 712cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 713cf66ee8eSAlexey Kardashevskiy return 1; 714cf66ee8eSAlexey Kardashevskiy } 715f1ae32a1SGerd Hoffmann } 716f1ae32a1SGerd Hoffmann 717f1ae32a1SGerd Hoffmann dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA)); 71842340fc3SLiam Merwick if (dev == NULL) { 71942340fc3SLiam Merwick trace_usb_ohci_td_dev_error(); 72042340fc3SLiam Merwick return 1; 72142340fc3SLiam Merwick } 722f1ae32a1SGerd Hoffmann ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN)); 7233a4d06f2SBALATON Zoltan pkt = g_new0(USBPacket, 1); 7243a4d06f2SBALATON Zoltan usb_packet_init(pkt); 7253a4d06f2SBALATON Zoltan int_req = relative_frame_number == frame_count && 7263a4d06f2SBALATON Zoltan OHCI_BM(iso_td.flags, TD_DI) == 0; 7273a4d06f2SBALATON Zoltan usb_packet_setup(pkt, pid, ep, 0, addr, false, int_req); 7283a4d06f2SBALATON Zoltan usb_packet_addbuf(pkt, buf, len); 7293a4d06f2SBALATON Zoltan usb_handle_packet(dev, pkt); 7303a4d06f2SBALATON Zoltan if (pkt->status == USB_RET_ASYNC) { 73136dfe324SHans de Goede usb_device_flush_ep_queue(dev, ep); 7323a4d06f2SBALATON Zoltan g_free(pkt); 733f1ae32a1SGerd Hoffmann return 1; 734f1ae32a1SGerd Hoffmann } 7353a4d06f2SBALATON Zoltan if (pkt->status == USB_RET_SUCCESS) { 7363a4d06f2SBALATON Zoltan ret = pkt->actual_length; 7379a77a0f5SHans de Goede } else { 7383a4d06f2SBALATON Zoltan ret = pkt->status; 7399a77a0f5SHans de Goede } 7403a4d06f2SBALATON Zoltan g_free(pkt); 741f1ae32a1SGerd Hoffmann 742dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_so(start_offset, end_offset, start_addr, end_addr, 743dc1f5988SAlexey Kardashevskiy str, len, ret); 744f1ae32a1SGerd Hoffmann 745f1ae32a1SGerd Hoffmann /* Writeback */ 746f1ae32a1SGerd Hoffmann if (dir == OHCI_TD_DIR_IN && ret >= 0 && ret <= len) { 747f1ae32a1SGerd Hoffmann /* IN transfer succeeded */ 7483a4d06f2SBALATON Zoltan if (ohci_copy_iso_td(ohci, start_addr, end_addr, buf, ret, 749cf66ee8eSAlexey Kardashevskiy DMA_DIRECTION_FROM_DEVICE)) { 750cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 751cf66ee8eSAlexey Kardashevskiy return 1; 752cf66ee8eSAlexey Kardashevskiy } 753f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 754f1ae32a1SGerd Hoffmann OHCI_CC_NOERROR); 755f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, ret); 756f1ae32a1SGerd Hoffmann } else if (dir == OHCI_TD_DIR_OUT && ret == len) { 757f1ae32a1SGerd Hoffmann /* OUT transfer succeeded */ 758f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 759f1ae32a1SGerd Hoffmann OHCI_CC_NOERROR); 760f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 0); 761f1ae32a1SGerd Hoffmann } else { 762f1ae32a1SGerd Hoffmann if (ret > (ssize_t) len) { 763dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_data_overrun(ret, len); 764f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 765f1ae32a1SGerd Hoffmann OHCI_CC_DATAOVERRUN); 766f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 767f1ae32a1SGerd Hoffmann len); 768f1ae32a1SGerd Hoffmann } else if (ret >= 0) { 769dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_data_underrun(ret); 770f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 771f1ae32a1SGerd Hoffmann OHCI_CC_DATAUNDERRUN); 772f1ae32a1SGerd Hoffmann } else { 773f1ae32a1SGerd Hoffmann switch (ret) { 774f1ae32a1SGerd Hoffmann case USB_RET_IOERROR: 775f1ae32a1SGerd Hoffmann case USB_RET_NODEV: 776f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 777f1ae32a1SGerd Hoffmann OHCI_CC_DEVICENOTRESPONDING); 778f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 779f1ae32a1SGerd Hoffmann 0); 780f1ae32a1SGerd Hoffmann break; 781f1ae32a1SGerd Hoffmann case USB_RET_NAK: 782f1ae32a1SGerd Hoffmann case USB_RET_STALL: 783dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_nak(ret); 784f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 785f1ae32a1SGerd Hoffmann OHCI_CC_STALL); 786f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 787f1ae32a1SGerd Hoffmann 0); 788f1ae32a1SGerd Hoffmann break; 789f1ae32a1SGerd Hoffmann default: 790dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_bad_response(ret); 791f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 792f1ae32a1SGerd Hoffmann OHCI_CC_UNDEXPETEDPID); 793f1ae32a1SGerd Hoffmann break; 794f1ae32a1SGerd Hoffmann } 795f1ae32a1SGerd Hoffmann } 796f1ae32a1SGerd Hoffmann } 797f1ae32a1SGerd Hoffmann 798f1ae32a1SGerd Hoffmann if (relative_frame_number == frame_count) { 799f1ae32a1SGerd Hoffmann /* Last data packet of ISO TD - retire the TD to the Done Queue */ 800f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_NOERROR); 801f1ae32a1SGerd Hoffmann ed->head &= ~OHCI_DPTR_MASK; 802f1ae32a1SGerd Hoffmann ed->head |= (iso_td.next & OHCI_DPTR_MASK); 803f1ae32a1SGerd Hoffmann iso_td.next = ohci->done; 804f1ae32a1SGerd Hoffmann ohci->done = addr; 805f1ae32a1SGerd Hoffmann i = OHCI_BM(iso_td.flags, TD_DI); 806f1ae32a1SGerd Hoffmann if (i < ohci->done_count) 807f1ae32a1SGerd Hoffmann ohci->done_count = i; 808f1ae32a1SGerd Hoffmann } 809cf66ee8eSAlexey Kardashevskiy if (ohci_put_iso_td(ohci, addr, &iso_td)) { 810cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 811cf66ee8eSAlexey Kardashevskiy } 812f1ae32a1SGerd Hoffmann return 1; 813f1ae32a1SGerd Hoffmann } 814f1ae32a1SGerd Hoffmann 81529d81e42SPhilippe Mathieu-Daudé #define HEX_CHAR_PER_LINE 16 81629d81e42SPhilippe Mathieu-Daudé 817dc1f5988SAlexey Kardashevskiy static void ohci_td_pkt(const char *msg, const uint8_t *buf, size_t len) 818dc1f5988SAlexey Kardashevskiy { 819d87aa138SStefan Hajnoczi bool print16; 820d87aa138SStefan Hajnoczi bool printall; 821dc1f5988SAlexey Kardashevskiy int i; 82229d81e42SPhilippe Mathieu-Daudé char tmp[3 * HEX_CHAR_PER_LINE + 1]; 823dc1f5988SAlexey Kardashevskiy char *p = tmp; 824dc1f5988SAlexey Kardashevskiy 825d87aa138SStefan Hajnoczi print16 = !!trace_event_get_state_backends(TRACE_USB_OHCI_TD_PKT_SHORT); 826d87aa138SStefan Hajnoczi printall = !!trace_event_get_state_backends(TRACE_USB_OHCI_TD_PKT_FULL); 827d87aa138SStefan Hajnoczi 828dc1f5988SAlexey Kardashevskiy if (!printall && !print16) { 829dc1f5988SAlexey Kardashevskiy return; 830dc1f5988SAlexey Kardashevskiy } 831dc1f5988SAlexey Kardashevskiy 832dc1f5988SAlexey Kardashevskiy for (i = 0; ; i++) { 83329d81e42SPhilippe Mathieu-Daudé if (i && (!(i % HEX_CHAR_PER_LINE) || (i == len))) { 834dc1f5988SAlexey Kardashevskiy if (!printall) { 835dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_pkt_short(msg, tmp); 836dc1f5988SAlexey Kardashevskiy break; 837dc1f5988SAlexey Kardashevskiy } 838dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_pkt_full(msg, tmp); 839dc1f5988SAlexey Kardashevskiy p = tmp; 840dc1f5988SAlexey Kardashevskiy *p = 0; 841dc1f5988SAlexey Kardashevskiy } 842dc1f5988SAlexey Kardashevskiy if (i == len) { 843dc1f5988SAlexey Kardashevskiy break; 844dc1f5988SAlexey Kardashevskiy } 845dc1f5988SAlexey Kardashevskiy 846dc1f5988SAlexey Kardashevskiy p += sprintf(p, " %.2x", buf[i]); 847dc1f5988SAlexey Kardashevskiy } 848dc1f5988SAlexey Kardashevskiy } 849dc1f5988SAlexey Kardashevskiy 850*572a6732SBALATON Zoltan /* 851*572a6732SBALATON Zoltan * Service a transport descriptor. 852*572a6732SBALATON Zoltan * Returns nonzero to terminate processing of this endpoint. 853*572a6732SBALATON Zoltan */ 854f1ae32a1SGerd Hoffmann static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) 855f1ae32a1SGerd Hoffmann { 856f1ae32a1SGerd Hoffmann int dir; 857f1ae32a1SGerd Hoffmann size_t len = 0, pktlen = 0; 858f1ae32a1SGerd Hoffmann const char *str = NULL; 859f1ae32a1SGerd Hoffmann int pid; 860f1ae32a1SGerd Hoffmann int ret; 861f1ae32a1SGerd Hoffmann int i; 862f1ae32a1SGerd Hoffmann USBDevice *dev; 863f1ae32a1SGerd Hoffmann USBEndpoint *ep; 864f1ae32a1SGerd Hoffmann struct ohci_td td; 865f1ae32a1SGerd Hoffmann uint32_t addr; 866f1ae32a1SGerd Hoffmann int flag_r; 867f1ae32a1SGerd Hoffmann int completion; 868f1ae32a1SGerd Hoffmann 869f1ae32a1SGerd Hoffmann addr = ed->head & OHCI_DPTR_MASK; 870d8c2e6f2SQiang Liu if (addr == 0) { 871d8c2e6f2SQiang Liu ohci_die(ohci); 872d8c2e6f2SQiang Liu return 1; 873d8c2e6f2SQiang Liu } 874d8c2e6f2SQiang Liu 875f1ae32a1SGerd Hoffmann /* See if this TD has already been submitted to the device. */ 876f1ae32a1SGerd Hoffmann completion = (addr == ohci->async_td); 877f1ae32a1SGerd Hoffmann if (completion && !ohci->async_complete) { 878dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_skip_async(); 879f1ae32a1SGerd Hoffmann return 1; 880f1ae32a1SGerd Hoffmann } 881cf66ee8eSAlexey Kardashevskiy if (ohci_read_td(ohci, addr, &td)) { 882dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_read_error(addr); 883cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 8846ebc069dSLi Qiang return 1; 885f1ae32a1SGerd Hoffmann } 886f1ae32a1SGerd Hoffmann 887f1ae32a1SGerd Hoffmann dir = OHCI_BM(ed->flags, ED_D); 888f1ae32a1SGerd Hoffmann switch (dir) { 889f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_OUT: 890f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_IN: 891f1ae32a1SGerd Hoffmann /* Same value. */ 892f1ae32a1SGerd Hoffmann break; 893f1ae32a1SGerd Hoffmann default: 894f1ae32a1SGerd Hoffmann dir = OHCI_BM(td.flags, TD_DP); 895f1ae32a1SGerd Hoffmann break; 896f1ae32a1SGerd Hoffmann } 897f1ae32a1SGerd Hoffmann 898f1ae32a1SGerd Hoffmann switch (dir) { 899f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_IN: 900f1ae32a1SGerd Hoffmann str = "in"; 901f1ae32a1SGerd Hoffmann pid = USB_TOKEN_IN; 902f1ae32a1SGerd Hoffmann break; 903f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_OUT: 904f1ae32a1SGerd Hoffmann str = "out"; 905f1ae32a1SGerd Hoffmann pid = USB_TOKEN_OUT; 906f1ae32a1SGerd Hoffmann break; 907f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_SETUP: 908f1ae32a1SGerd Hoffmann str = "setup"; 909f1ae32a1SGerd Hoffmann pid = USB_TOKEN_SETUP; 910f1ae32a1SGerd Hoffmann break; 911f1ae32a1SGerd Hoffmann default: 912dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_bad_direction(dir); 913f1ae32a1SGerd Hoffmann return 1; 914f1ae32a1SGerd Hoffmann } 915f1ae32a1SGerd Hoffmann if (td.cbp && td.be) { 916f1ae32a1SGerd Hoffmann if ((td.cbp & 0xfffff000) != (td.be & 0xfffff000)) { 917f1ae32a1SGerd Hoffmann len = (td.be & 0xfff) + 0x1001 - (td.cbp & 0xfff); 918f1ae32a1SGerd Hoffmann } else { 9191328fe0cSPrasad J Pandit if (td.cbp > td.be) { 9201328fe0cSPrasad J Pandit trace_usb_ohci_iso_td_bad_cc_overrun(td.cbp, td.be); 9211328fe0cSPrasad J Pandit ohci_die(ohci); 9221328fe0cSPrasad J Pandit return 1; 9231328fe0cSPrasad J Pandit } 924f1ae32a1SGerd Hoffmann len = (td.be - td.cbp) + 1; 925f1ae32a1SGerd Hoffmann } 9261328fe0cSPrasad J Pandit if (len > sizeof(ohci->usb_buf)) { 9271328fe0cSPrasad J Pandit len = sizeof(ohci->usb_buf); 9281328fe0cSPrasad J Pandit } 929f1ae32a1SGerd Hoffmann 930f1ae32a1SGerd Hoffmann pktlen = len; 931f1ae32a1SGerd Hoffmann if (len && dir != OHCI_TD_DIR_IN) { 932f1ae32a1SGerd Hoffmann /* The endpoint may not allow us to transfer it all now */ 933f1ae32a1SGerd Hoffmann pktlen = (ed->flags & OHCI_ED_MPS_MASK) >> OHCI_ED_MPS_SHIFT; 934f1ae32a1SGerd Hoffmann if (pktlen > len) { 935f1ae32a1SGerd Hoffmann pktlen = len; 936f1ae32a1SGerd Hoffmann } 937f1ae32a1SGerd Hoffmann if (!completion) { 938cf66ee8eSAlexey Kardashevskiy if (ohci_copy_td(ohci, &td, ohci->usb_buf, pktlen, 939cf66ee8eSAlexey Kardashevskiy DMA_DIRECTION_TO_DEVICE)) { 940cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 941cf66ee8eSAlexey Kardashevskiy } 942f1ae32a1SGerd Hoffmann } 943f1ae32a1SGerd Hoffmann } 944f1ae32a1SGerd Hoffmann } 945f1ae32a1SGerd Hoffmann 946f1ae32a1SGerd Hoffmann flag_r = (td.flags & OHCI_TD_R) != 0; 947dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_pkt_hdr(addr, (int64_t)pktlen, (int64_t)len, str, 948dc1f5988SAlexey Kardashevskiy flag_r, td.cbp, td.be); 949dc1f5988SAlexey Kardashevskiy ohci_td_pkt("OUT", ohci->usb_buf, pktlen); 950f1ae32a1SGerd Hoffmann 951f1ae32a1SGerd Hoffmann if (completion) { 952f1ae32a1SGerd Hoffmann ohci->async_td = 0; 95369e25d26SAlexey Kardashevskiy ohci->async_complete = false; 954f1ae32a1SGerd Hoffmann } else { 955f1ae32a1SGerd Hoffmann dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA)); 95642340fc3SLiam Merwick if (dev == NULL) { 95742340fc3SLiam Merwick trace_usb_ohci_td_dev_error(); 95842340fc3SLiam Merwick return 1; 95942340fc3SLiam Merwick } 960f1ae32a1SGerd Hoffmann ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN)); 9616e821e50SBALATON Zoltan if (ohci->async_td) { 962*572a6732SBALATON Zoltan /* 963*572a6732SBALATON Zoltan * ??? The hardware should allow one active packet per 964*572a6732SBALATON Zoltan * endpoint. We only allow one active packet per controller. 965*572a6732SBALATON Zoltan * This should be sufficient as long as devices respond in a 966*572a6732SBALATON Zoltan * timely manner. 9676e821e50SBALATON Zoltan */ 9686e821e50SBALATON Zoltan trace_usb_ohci_td_too_many_pending(ep->nr); 9696e821e50SBALATON Zoltan return 1; 9706e821e50SBALATON Zoltan } 9718550a02dSGerd Hoffmann usb_packet_setup(&ohci->usb_packet, pid, ep, 0, addr, !flag_r, 972a6fb2ddbSHans de Goede OHCI_BM(td.flags, TD_DI) == 0); 973f1ae32a1SGerd Hoffmann usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen); 9749a77a0f5SHans de Goede usb_handle_packet(dev, &ohci->usb_packet); 975dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_packet_status(ohci->usb_packet.status); 976dc1f5988SAlexey Kardashevskiy 9779a77a0f5SHans de Goede if (ohci->usb_packet.status == USB_RET_ASYNC) { 97836dfe324SHans de Goede usb_device_flush_ep_queue(dev, ep); 979f1ae32a1SGerd Hoffmann ohci->async_td = addr; 980f1ae32a1SGerd Hoffmann return 1; 981f1ae32a1SGerd Hoffmann } 982f1ae32a1SGerd Hoffmann } 9839a77a0f5SHans de Goede if (ohci->usb_packet.status == USB_RET_SUCCESS) { 9849a77a0f5SHans de Goede ret = ohci->usb_packet.actual_length; 9859a77a0f5SHans de Goede } else { 9869a77a0f5SHans de Goede ret = ohci->usb_packet.status; 9879a77a0f5SHans de Goede } 9889a77a0f5SHans de Goede 989f1ae32a1SGerd Hoffmann if (ret >= 0) { 990f1ae32a1SGerd Hoffmann if (dir == OHCI_TD_DIR_IN) { 991cf66ee8eSAlexey Kardashevskiy if (ohci_copy_td(ohci, &td, ohci->usb_buf, ret, 992cf66ee8eSAlexey Kardashevskiy DMA_DIRECTION_FROM_DEVICE)) { 993cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 994cf66ee8eSAlexey Kardashevskiy } 995dc1f5988SAlexey Kardashevskiy ohci_td_pkt("IN", ohci->usb_buf, pktlen); 996f1ae32a1SGerd Hoffmann } else { 997f1ae32a1SGerd Hoffmann ret = pktlen; 998f1ae32a1SGerd Hoffmann } 999f1ae32a1SGerd Hoffmann } 1000f1ae32a1SGerd Hoffmann 1001f1ae32a1SGerd Hoffmann /* Writeback */ 1002f1ae32a1SGerd Hoffmann if (ret == pktlen || (dir == OHCI_TD_DIR_IN && ret >= 0 && flag_r)) { 1003f1ae32a1SGerd Hoffmann /* Transmission succeeded. */ 1004f1ae32a1SGerd Hoffmann if (ret == len) { 1005f1ae32a1SGerd Hoffmann td.cbp = 0; 1006f1ae32a1SGerd Hoffmann } else { 1007f1ae32a1SGerd Hoffmann if ((td.cbp & 0xfff) + ret > 0xfff) { 1008f1ae32a1SGerd Hoffmann td.cbp = (td.be & ~0xfff) + ((td.cbp + ret) & 0xfff); 1009f1ae32a1SGerd Hoffmann } else { 1010f1ae32a1SGerd Hoffmann td.cbp += ret; 1011f1ae32a1SGerd Hoffmann } 1012f1ae32a1SGerd Hoffmann } 1013f1ae32a1SGerd Hoffmann td.flags |= OHCI_TD_T1; 1014f1ae32a1SGerd Hoffmann td.flags ^= OHCI_TD_T0; 1015f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_NOERROR); 1016f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_EC, 0); 1017f1ae32a1SGerd Hoffmann 1018f1ae32a1SGerd Hoffmann if ((dir != OHCI_TD_DIR_IN) && (ret != len)) { 1019f1ae32a1SGerd Hoffmann /* Partial packet transfer: TD not ready to retire yet */ 1020f1ae32a1SGerd Hoffmann goto exit_no_retire; 1021f1ae32a1SGerd Hoffmann } 1022f1ae32a1SGerd Hoffmann 1023f1ae32a1SGerd Hoffmann /* Setting ED_C is part of the TD retirement process */ 1024f1ae32a1SGerd Hoffmann ed->head &= ~OHCI_ED_C; 1025f1ae32a1SGerd Hoffmann if (td.flags & OHCI_TD_T0) 1026f1ae32a1SGerd Hoffmann ed->head |= OHCI_ED_C; 1027f1ae32a1SGerd Hoffmann } else { 1028f1ae32a1SGerd Hoffmann if (ret >= 0) { 1029dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_underrun(); 1030f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAUNDERRUN); 1031f1ae32a1SGerd Hoffmann } else { 1032f1ae32a1SGerd Hoffmann switch (ret) { 1033f1ae32a1SGerd Hoffmann case USB_RET_IOERROR: 1034f1ae32a1SGerd Hoffmann case USB_RET_NODEV: 1035dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_dev_error(); 1036f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DEVICENOTRESPONDING); 10374b351a0fSJán Veselý break; 1038f1ae32a1SGerd Hoffmann case USB_RET_NAK: 1039dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_nak(); 1040f1ae32a1SGerd Hoffmann return 1; 1041f1ae32a1SGerd Hoffmann case USB_RET_STALL: 1042dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_stall(); 1043f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_STALL); 1044f1ae32a1SGerd Hoffmann break; 1045f1ae32a1SGerd Hoffmann case USB_RET_BABBLE: 1046dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_babble(); 1047f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAOVERRUN); 1048f1ae32a1SGerd Hoffmann break; 1049f1ae32a1SGerd Hoffmann default: 1050dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_bad_device_response(ret); 1051f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_UNDEXPETEDPID); 1052f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_EC, 3); 1053f1ae32a1SGerd Hoffmann break; 1054f1ae32a1SGerd Hoffmann } 1055*572a6732SBALATON Zoltan /* 1056*572a6732SBALATON Zoltan * An error occurred so we have to clear the interrupt counter. 1057*572a6732SBALATON Zoltan * See spec at 6.4.4 on page 104 1058*572a6732SBALATON Zoltan */ 10597c48b95dSSebastian Bauer ohci->done_count = 0; 1060f1ae32a1SGerd Hoffmann } 1061f1ae32a1SGerd Hoffmann ed->head |= OHCI_ED_H; 1062f1ae32a1SGerd Hoffmann } 1063f1ae32a1SGerd Hoffmann 1064f1ae32a1SGerd Hoffmann /* Retire this TD */ 1065f1ae32a1SGerd Hoffmann ed->head &= ~OHCI_DPTR_MASK; 1066f1ae32a1SGerd Hoffmann ed->head |= td.next & OHCI_DPTR_MASK; 1067f1ae32a1SGerd Hoffmann td.next = ohci->done; 1068f1ae32a1SGerd Hoffmann ohci->done = addr; 1069f1ae32a1SGerd Hoffmann i = OHCI_BM(td.flags, TD_DI); 1070f1ae32a1SGerd Hoffmann if (i < ohci->done_count) 1071f1ae32a1SGerd Hoffmann ohci->done_count = i; 1072f1ae32a1SGerd Hoffmann exit_no_retire: 1073cf66ee8eSAlexey Kardashevskiy if (ohci_put_td(ohci, addr, &td)) { 1074cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 1075cf66ee8eSAlexey Kardashevskiy return 1; 1076cf66ee8eSAlexey Kardashevskiy } 1077f1ae32a1SGerd Hoffmann return OHCI_BM(td.flags, TD_CC) != OHCI_CC_NOERROR; 1078f1ae32a1SGerd Hoffmann } 1079f1ae32a1SGerd Hoffmann 1080f1ae32a1SGerd Hoffmann /* Service an endpoint list. Returns nonzero if active TD were found. */ 10813a4d06f2SBALATON Zoltan static int ohci_service_ed_list(OHCIState *ohci, uint32_t head) 1082f1ae32a1SGerd Hoffmann { 1083f1ae32a1SGerd Hoffmann struct ohci_ed ed; 1084f1ae32a1SGerd Hoffmann uint32_t next_ed; 1085f1ae32a1SGerd Hoffmann uint32_t cur; 1086f1ae32a1SGerd Hoffmann int active; 108795ed5693SLi Qiang uint32_t link_cnt = 0; 1088f1ae32a1SGerd Hoffmann active = 0; 1089f1ae32a1SGerd Hoffmann 1090f1ae32a1SGerd Hoffmann if (head == 0) 1091f1ae32a1SGerd Hoffmann return 0; 1092f1ae32a1SGerd Hoffmann 1093ab878998SLaurent Vivier for (cur = head; cur && link_cnt++ < ED_LINK_LIMIT; cur = next_ed) { 1094cf66ee8eSAlexey Kardashevskiy if (ohci_read_ed(ohci, cur, &ed)) { 1095dc1f5988SAlexey Kardashevskiy trace_usb_ohci_ed_read_error(cur); 1096cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 1097f1ae32a1SGerd Hoffmann return 0; 1098f1ae32a1SGerd Hoffmann } 1099f1ae32a1SGerd Hoffmann 1100f1ae32a1SGerd Hoffmann next_ed = ed.next & OHCI_DPTR_MASK; 1101f1ae32a1SGerd Hoffmann 1102f1ae32a1SGerd Hoffmann if ((ed.head & OHCI_ED_H) || (ed.flags & OHCI_ED_K)) { 1103f1ae32a1SGerd Hoffmann uint32_t addr; 1104f1ae32a1SGerd Hoffmann /* Cancel pending packets for ED that have been paused. */ 1105f1ae32a1SGerd Hoffmann addr = ed.head & OHCI_DPTR_MASK; 1106f1ae32a1SGerd Hoffmann if (ohci->async_td && addr == ohci->async_td) { 1107f1ae32a1SGerd Hoffmann usb_cancel_packet(&ohci->usb_packet); 1108f1ae32a1SGerd Hoffmann ohci->async_td = 0; 1109f79738b0SHans de Goede usb_device_ep_stopped(ohci->usb_packet.ep->dev, 1110f79738b0SHans de Goede ohci->usb_packet.ep); 1111f1ae32a1SGerd Hoffmann } 1112f1ae32a1SGerd Hoffmann continue; 1113f1ae32a1SGerd Hoffmann } 1114f1ae32a1SGerd Hoffmann 1115f1ae32a1SGerd Hoffmann while ((ed.head & OHCI_DPTR_MASK) != ed.tail) { 11163af8f177SAlexey Kardashevskiy trace_usb_ohci_ed_pkt(cur, (ed.head & OHCI_ED_H) != 0, 11173af8f177SAlexey Kardashevskiy (ed.head & OHCI_ED_C) != 0, ed.head & OHCI_DPTR_MASK, 11183af8f177SAlexey Kardashevskiy ed.tail & OHCI_DPTR_MASK, ed.next & OHCI_DPTR_MASK); 11193af8f177SAlexey Kardashevskiy trace_usb_ohci_ed_pkt_flags( 1120f1ae32a1SGerd Hoffmann OHCI_BM(ed.flags, ED_FA), OHCI_BM(ed.flags, ED_EN), 1121f1ae32a1SGerd Hoffmann OHCI_BM(ed.flags, ED_D), (ed.flags & OHCI_ED_S)!= 0, 1122f1ae32a1SGerd Hoffmann (ed.flags & OHCI_ED_K) != 0, (ed.flags & OHCI_ED_F) != 0, 11233af8f177SAlexey Kardashevskiy OHCI_BM(ed.flags, ED_MPS)); 1124dc1f5988SAlexey Kardashevskiy 1125f1ae32a1SGerd Hoffmann active = 1; 1126f1ae32a1SGerd Hoffmann 1127f1ae32a1SGerd Hoffmann if ((ed.flags & OHCI_ED_F) == 0) { 1128f1ae32a1SGerd Hoffmann if (ohci_service_td(ohci, &ed)) 1129f1ae32a1SGerd Hoffmann break; 1130f1ae32a1SGerd Hoffmann } else { 1131f1ae32a1SGerd Hoffmann /* Handle isochronous endpoints */ 11323a4d06f2SBALATON Zoltan if (ohci_service_iso_td(ohci, &ed)) { 1133f1ae32a1SGerd Hoffmann break; 1134f1ae32a1SGerd Hoffmann } 1135f1ae32a1SGerd Hoffmann } 11363a4d06f2SBALATON Zoltan } 1137f1ae32a1SGerd Hoffmann 1138cf66ee8eSAlexey Kardashevskiy if (ohci_put_ed(ohci, cur, &ed)) { 1139cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 1140cf66ee8eSAlexey Kardashevskiy return 0; 1141cf66ee8eSAlexey Kardashevskiy } 1142f1ae32a1SGerd Hoffmann } 1143f1ae32a1SGerd Hoffmann 1144f1ae32a1SGerd Hoffmann return active; 1145f1ae32a1SGerd Hoffmann } 1146f1ae32a1SGerd Hoffmann 1147fd0a10cdSLaurent Vivier /* set a timer for EOF */ 1148fd0a10cdSLaurent Vivier static void ohci_eof_timer(OHCIState *ohci) 1149f1ae32a1SGerd Hoffmann { 1150bc72ad67SAlex Bligh timer_mod(ohci->eof_timer, ohci->sof_time + usb_frame_time); 1151fd0a10cdSLaurent Vivier } 1152fd0a10cdSLaurent Vivier /* Set a timer for EOF and generate a SOF event */ 1153fd0a10cdSLaurent Vivier static void ohci_sof(OHCIState *ohci) 1154fd0a10cdSLaurent Vivier { 1155a60f39a4SMiguel GAIO ohci->sof_time += usb_frame_time; 1156fd0a10cdSLaurent Vivier ohci_eof_timer(ohci); 1157f1ae32a1SGerd Hoffmann ohci_set_interrupt(ohci, OHCI_INTR_SF); 1158f1ae32a1SGerd Hoffmann } 1159f1ae32a1SGerd Hoffmann 1160f1ae32a1SGerd Hoffmann /* Process Control and Bulk lists. */ 11613a4d06f2SBALATON Zoltan static void ohci_process_lists(OHCIState *ohci) 1162f1ae32a1SGerd Hoffmann { 1163f1ae32a1SGerd Hoffmann if ((ohci->ctl & OHCI_CTL_CLE) && (ohci->status & OHCI_STATUS_CLF)) { 1164f1ae32a1SGerd Hoffmann if (ohci->ctrl_cur && ohci->ctrl_cur != ohci->ctrl_head) { 1165dc1f5988SAlexey Kardashevskiy trace_usb_ohci_process_lists(ohci->ctrl_head, ohci->ctrl_cur); 1166f1ae32a1SGerd Hoffmann } 11673a4d06f2SBALATON Zoltan if (!ohci_service_ed_list(ohci, ohci->ctrl_head)) { 1168f1ae32a1SGerd Hoffmann ohci->ctrl_cur = 0; 1169f1ae32a1SGerd Hoffmann ohci->status &= ~OHCI_STATUS_CLF; 1170f1ae32a1SGerd Hoffmann } 1171f1ae32a1SGerd Hoffmann } 1172f1ae32a1SGerd Hoffmann 1173f1ae32a1SGerd Hoffmann if ((ohci->ctl & OHCI_CTL_BLE) && (ohci->status & OHCI_STATUS_BLF)) { 11743a4d06f2SBALATON Zoltan if (!ohci_service_ed_list(ohci, ohci->bulk_head)) { 1175f1ae32a1SGerd Hoffmann ohci->bulk_cur = 0; 1176f1ae32a1SGerd Hoffmann ohci->status &= ~OHCI_STATUS_BLF; 1177f1ae32a1SGerd Hoffmann } 1178f1ae32a1SGerd Hoffmann } 1179f1ae32a1SGerd Hoffmann } 1180f1ae32a1SGerd Hoffmann 1181f1ae32a1SGerd Hoffmann /* Do frame processing on frame boundary */ 1182f1ae32a1SGerd Hoffmann static void ohci_frame_boundary(void *opaque) 1183f1ae32a1SGerd Hoffmann { 1184f1ae32a1SGerd Hoffmann OHCIState *ohci = opaque; 1185f1ae32a1SGerd Hoffmann struct ohci_hcca hcca; 1186f1ae32a1SGerd Hoffmann 1187cf66ee8eSAlexey Kardashevskiy if (ohci_read_hcca(ohci, ohci->hcca, &hcca)) { 1188dc1f5988SAlexey Kardashevskiy trace_usb_ohci_hcca_read_error(ohci->hcca); 1189cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 1190cf66ee8eSAlexey Kardashevskiy return; 1191cf66ee8eSAlexey Kardashevskiy } 1192f1ae32a1SGerd Hoffmann 1193f1ae32a1SGerd Hoffmann /* Process all the lists at the end of the frame */ 1194f1ae32a1SGerd Hoffmann if (ohci->ctl & OHCI_CTL_PLE) { 1195f1ae32a1SGerd Hoffmann int n; 1196f1ae32a1SGerd Hoffmann 1197f1ae32a1SGerd Hoffmann n = ohci->frame_number & 0x1f; 11983a4d06f2SBALATON Zoltan ohci_service_ed_list(ohci, le32_to_cpu(hcca.intr[n])); 1199f1ae32a1SGerd Hoffmann } 1200f1ae32a1SGerd Hoffmann 1201f1ae32a1SGerd Hoffmann /* Cancel all pending packets if either of the lists has been disabled. */ 1202f79738b0SHans de Goede if (ohci->old_ctl & (~ohci->ctl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) { 1203f79738b0SHans de Goede ohci_stop_endpoints(ohci); 1204f79738b0SHans de Goede } 1205f1ae32a1SGerd Hoffmann ohci->old_ctl = ohci->ctl; 12063a4d06f2SBALATON Zoltan ohci_process_lists(ohci); 1207f1ae32a1SGerd Hoffmann 1208cf66ee8eSAlexey Kardashevskiy /* Stop if UnrecoverableError happened or ohci_sof will crash */ 1209cf66ee8eSAlexey Kardashevskiy if (ohci->intr_status & OHCI_INTR_UE) { 1210cf66ee8eSAlexey Kardashevskiy return; 1211cf66ee8eSAlexey Kardashevskiy } 1212cf66ee8eSAlexey Kardashevskiy 1213f1ae32a1SGerd Hoffmann /* Frame boundary, so do EOF stuf here */ 1214f1ae32a1SGerd Hoffmann ohci->frt = ohci->fit; 1215f1ae32a1SGerd Hoffmann 1216f1ae32a1SGerd Hoffmann /* Increment frame number and take care of endianness. */ 1217f1ae32a1SGerd Hoffmann ohci->frame_number = (ohci->frame_number + 1) & 0xffff; 1218f1ae32a1SGerd Hoffmann hcca.frame = cpu_to_le16(ohci->frame_number); 1219f1ae32a1SGerd Hoffmann 1220f1ae32a1SGerd Hoffmann if (ohci->done_count == 0 && !(ohci->intr_status & OHCI_INTR_WD)) { 1221f1ae32a1SGerd Hoffmann if (!ohci->done) 1222f1ae32a1SGerd Hoffmann abort(); 1223f1ae32a1SGerd Hoffmann if (ohci->intr & ohci->intr_status) 1224f1ae32a1SGerd Hoffmann ohci->done |= 1; 1225f1ae32a1SGerd Hoffmann hcca.done = cpu_to_le32(ohci->done); 1226f1ae32a1SGerd Hoffmann ohci->done = 0; 1227f1ae32a1SGerd Hoffmann ohci->done_count = 7; 1228f1ae32a1SGerd Hoffmann ohci_set_interrupt(ohci, OHCI_INTR_WD); 1229f1ae32a1SGerd Hoffmann } 1230f1ae32a1SGerd Hoffmann 1231f1ae32a1SGerd Hoffmann if (ohci->done_count != 7 && ohci->done_count != 0) 1232f1ae32a1SGerd Hoffmann ohci->done_count--; 1233f1ae32a1SGerd Hoffmann 1234f1ae32a1SGerd Hoffmann /* Do SOF stuff here */ 1235f1ae32a1SGerd Hoffmann ohci_sof(ohci); 1236f1ae32a1SGerd Hoffmann 1237f1ae32a1SGerd Hoffmann /* Writeback HCCA */ 1238cf66ee8eSAlexey Kardashevskiy if (ohci_put_hcca(ohci, ohci->hcca, &hcca)) { 1239cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 1240cf66ee8eSAlexey Kardashevskiy } 1241f1ae32a1SGerd Hoffmann } 1242f1ae32a1SGerd Hoffmann 1243*572a6732SBALATON Zoltan /* 1244*572a6732SBALATON Zoltan * Start sending SOF tokens across the USB bus, lists are processed in 1245f1ae32a1SGerd Hoffmann * next frame 1246f1ae32a1SGerd Hoffmann */ 1247f1ae32a1SGerd Hoffmann static int ohci_bus_start(OHCIState *ohci) 1248f1ae32a1SGerd Hoffmann { 1249dc1f5988SAlexey Kardashevskiy trace_usb_ohci_start(ohci->name); 1250*572a6732SBALATON Zoltan /* 1251*572a6732SBALATON Zoltan * Delay the first SOF event by one frame time as linux driver is 1252*572a6732SBALATON Zoltan * not ready to receive it and can meet some race conditions 1253fd0a10cdSLaurent Vivier */ 1254a60f39a4SMiguel GAIO ohci->sof_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 1255fd0a10cdSLaurent Vivier ohci_eof_timer(ohci); 1256f1ae32a1SGerd Hoffmann 1257f1ae32a1SGerd Hoffmann return 1; 1258f1ae32a1SGerd Hoffmann } 1259f1ae32a1SGerd Hoffmann 1260f1ae32a1SGerd Hoffmann /* Stop sending SOF tokens on the bus */ 126134d97308SThomas Huth void ohci_bus_stop(OHCIState *ohci) 1262f1ae32a1SGerd Hoffmann { 1263dc1f5988SAlexey Kardashevskiy trace_usb_ohci_stop(ohci->name); 1264bc72ad67SAlex Bligh timer_del(ohci->eof_timer); 1265f1ae32a1SGerd Hoffmann } 1266f1ae32a1SGerd Hoffmann 1267*572a6732SBALATON Zoltan /* 1268*572a6732SBALATON Zoltan * Sets a flag in a port status reg but only set it if the port is connected. 1269*572a6732SBALATON Zoltan * If not set ConnectStatusChange flag. If flag is enabled return 1. 1270f1ae32a1SGerd Hoffmann */ 1271f1ae32a1SGerd Hoffmann static int ohci_port_set_if_connected(OHCIState *ohci, int i, uint32_t val) 1272f1ae32a1SGerd Hoffmann { 1273f1ae32a1SGerd Hoffmann int ret = 1; 1274f1ae32a1SGerd Hoffmann 1275f1ae32a1SGerd Hoffmann /* writing a 0 has no effect */ 1276f1ae32a1SGerd Hoffmann if (val == 0) 1277f1ae32a1SGerd Hoffmann return 0; 1278f1ae32a1SGerd Hoffmann 1279*572a6732SBALATON Zoltan /* If CurrentConnectStatus is cleared we set ConnectStatusChange */ 1280f1ae32a1SGerd Hoffmann if (!(ohci->rhport[i].ctrl & OHCI_PORT_CCS)) { 1281f1ae32a1SGerd Hoffmann ohci->rhport[i].ctrl |= OHCI_PORT_CSC; 1282f1ae32a1SGerd Hoffmann if (ohci->rhstatus & OHCI_RHS_DRWE) { 1283f1ae32a1SGerd Hoffmann /* TODO: CSC is a wakeup event */ 1284f1ae32a1SGerd Hoffmann } 1285f1ae32a1SGerd Hoffmann return 0; 1286f1ae32a1SGerd Hoffmann } 1287f1ae32a1SGerd Hoffmann 1288f1ae32a1SGerd Hoffmann if (ohci->rhport[i].ctrl & val) 1289f1ae32a1SGerd Hoffmann ret = 0; 1290f1ae32a1SGerd Hoffmann 1291f1ae32a1SGerd Hoffmann /* set the bit */ 1292f1ae32a1SGerd Hoffmann ohci->rhport[i].ctrl |= val; 1293f1ae32a1SGerd Hoffmann 1294f1ae32a1SGerd Hoffmann return ret; 1295f1ae32a1SGerd Hoffmann } 1296f1ae32a1SGerd Hoffmann 1297*572a6732SBALATON Zoltan /* Frame interval toggle is manipulated by the hcd only */ 1298f1ae32a1SGerd Hoffmann static void ohci_set_frame_interval(OHCIState *ohci, uint16_t val) 1299f1ae32a1SGerd Hoffmann { 1300f1ae32a1SGerd Hoffmann val &= OHCI_FMI_FI; 1301f1ae32a1SGerd Hoffmann 1302f1ae32a1SGerd Hoffmann if (val != ohci->fi) { 1303dc1f5988SAlexey Kardashevskiy trace_usb_ohci_set_frame_interval(ohci->name, ohci->fi, ohci->fi); 1304f1ae32a1SGerd Hoffmann } 1305f1ae32a1SGerd Hoffmann 1306f1ae32a1SGerd Hoffmann ohci->fi = val; 1307f1ae32a1SGerd Hoffmann } 1308f1ae32a1SGerd Hoffmann 1309f1ae32a1SGerd Hoffmann static void ohci_port_power(OHCIState *ohci, int i, int p) 1310f1ae32a1SGerd Hoffmann { 1311f1ae32a1SGerd Hoffmann if (p) { 1312f1ae32a1SGerd Hoffmann ohci->rhport[i].ctrl |= OHCI_PORT_PPS; 1313f1ae32a1SGerd Hoffmann } else { 1314f1ae32a1SGerd Hoffmann ohci->rhport[i].ctrl &= ~(OHCI_PORT_PPS| 1315f1ae32a1SGerd Hoffmann OHCI_PORT_CCS| 1316f1ae32a1SGerd Hoffmann OHCI_PORT_PSS| 1317f1ae32a1SGerd Hoffmann OHCI_PORT_PRS); 1318f1ae32a1SGerd Hoffmann } 1319f1ae32a1SGerd Hoffmann } 1320f1ae32a1SGerd Hoffmann 1321f1ae32a1SGerd Hoffmann /* Set HcControlRegister */ 1322f1ae32a1SGerd Hoffmann static void ohci_set_ctl(OHCIState *ohci, uint32_t val) 1323f1ae32a1SGerd Hoffmann { 1324f1ae32a1SGerd Hoffmann uint32_t old_state; 1325f1ae32a1SGerd Hoffmann uint32_t new_state; 1326f1ae32a1SGerd Hoffmann 1327f1ae32a1SGerd Hoffmann old_state = ohci->ctl & OHCI_CTL_HCFS; 1328f1ae32a1SGerd Hoffmann ohci->ctl = val; 1329f1ae32a1SGerd Hoffmann new_state = ohci->ctl & OHCI_CTL_HCFS; 1330f1ae32a1SGerd Hoffmann 1331f1ae32a1SGerd Hoffmann /* no state change */ 1332f1ae32a1SGerd Hoffmann if (old_state == new_state) 1333f1ae32a1SGerd Hoffmann return; 1334f1ae32a1SGerd Hoffmann 1335dc1f5988SAlexey Kardashevskiy trace_usb_ohci_set_ctl(ohci->name, new_state); 1336f1ae32a1SGerd Hoffmann switch (new_state) { 1337f1ae32a1SGerd Hoffmann case OHCI_USB_OPERATIONAL: 1338f1ae32a1SGerd Hoffmann ohci_bus_start(ohci); 1339f1ae32a1SGerd Hoffmann break; 1340f1ae32a1SGerd Hoffmann case OHCI_USB_SUSPEND: 1341f1ae32a1SGerd Hoffmann ohci_bus_stop(ohci); 1342087462c7SLaurent Vivier /* clear pending SF otherwise linux driver loops in ohci_irq() */ 1343087462c7SLaurent Vivier ohci->intr_status &= ~OHCI_INTR_SF; 1344087462c7SLaurent Vivier ohci_intr_update(ohci); 1345f1ae32a1SGerd Hoffmann break; 1346f1ae32a1SGerd Hoffmann case OHCI_USB_RESUME: 1347dc1f5988SAlexey Kardashevskiy trace_usb_ohci_resume(ohci->name); 1348f1ae32a1SGerd Hoffmann break; 1349f1ae32a1SGerd Hoffmann case OHCI_USB_RESET: 13507d938fd1SHervé Poussineau ohci_roothub_reset(ohci); 1351f1ae32a1SGerd Hoffmann break; 1352f1ae32a1SGerd Hoffmann } 1353f1ae32a1SGerd Hoffmann } 1354f1ae32a1SGerd Hoffmann 1355f1ae32a1SGerd Hoffmann static uint32_t ohci_get_frame_remaining(OHCIState *ohci) 1356f1ae32a1SGerd Hoffmann { 1357f1ae32a1SGerd Hoffmann uint16_t fr; 1358f1ae32a1SGerd Hoffmann int64_t tks; 1359f1ae32a1SGerd Hoffmann 1360f1ae32a1SGerd Hoffmann if ((ohci->ctl & OHCI_CTL_HCFS) != OHCI_USB_OPERATIONAL) 1361f1ae32a1SGerd Hoffmann return (ohci->frt << 31); 1362f1ae32a1SGerd Hoffmann 1363*572a6732SBALATON Zoltan /* Being in USB operational state guarnatees sof_time was set already. */ 1364bc72ad67SAlex Bligh tks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - ohci->sof_time; 1365a60f39a4SMiguel GAIO if (tks < 0) { 1366a60f39a4SMiguel GAIO tks = 0; 1367a60f39a4SMiguel GAIO } 1368f1ae32a1SGerd Hoffmann 1369f1ae32a1SGerd Hoffmann /* avoid muldiv if possible */ 1370f1ae32a1SGerd Hoffmann if (tks >= usb_frame_time) 1371f1ae32a1SGerd Hoffmann return (ohci->frt << 31); 1372f1ae32a1SGerd Hoffmann 1373cd1f16f9SLaurent Vivier tks = tks / usb_bit_time; 1374f1ae32a1SGerd Hoffmann fr = (uint16_t)(ohci->fi - tks); 1375f1ae32a1SGerd Hoffmann 1376f1ae32a1SGerd Hoffmann return (ohci->frt << 31) | fr; 1377f1ae32a1SGerd Hoffmann } 1378f1ae32a1SGerd Hoffmann 1379f1ae32a1SGerd Hoffmann 1380f1ae32a1SGerd Hoffmann /* Set root hub status */ 1381f1ae32a1SGerd Hoffmann static void ohci_set_hub_status(OHCIState *ohci, uint32_t val) 1382f1ae32a1SGerd Hoffmann { 1383f1ae32a1SGerd Hoffmann uint32_t old_state; 1384f1ae32a1SGerd Hoffmann 1385f1ae32a1SGerd Hoffmann old_state = ohci->rhstatus; 1386f1ae32a1SGerd Hoffmann 1387f1ae32a1SGerd Hoffmann /* write 1 to clear OCIC */ 1388f1ae32a1SGerd Hoffmann if (val & OHCI_RHS_OCIC) 1389f1ae32a1SGerd Hoffmann ohci->rhstatus &= ~OHCI_RHS_OCIC; 1390f1ae32a1SGerd Hoffmann 1391f1ae32a1SGerd Hoffmann if (val & OHCI_RHS_LPS) { 1392f1ae32a1SGerd Hoffmann int i; 1393f1ae32a1SGerd Hoffmann 1394f1ae32a1SGerd Hoffmann for (i = 0; i < ohci->num_ports; i++) 1395f1ae32a1SGerd Hoffmann ohci_port_power(ohci, i, 0); 1396dc1f5988SAlexey Kardashevskiy trace_usb_ohci_hub_power_down(); 1397f1ae32a1SGerd Hoffmann } 1398f1ae32a1SGerd Hoffmann 1399f1ae32a1SGerd Hoffmann if (val & OHCI_RHS_LPSC) { 1400f1ae32a1SGerd Hoffmann int i; 1401f1ae32a1SGerd Hoffmann 1402f1ae32a1SGerd Hoffmann for (i = 0; i < ohci->num_ports; i++) 1403f1ae32a1SGerd Hoffmann ohci_port_power(ohci, i, 1); 1404dc1f5988SAlexey Kardashevskiy trace_usb_ohci_hub_power_up(); 1405f1ae32a1SGerd Hoffmann } 1406f1ae32a1SGerd Hoffmann 1407f1ae32a1SGerd Hoffmann if (val & OHCI_RHS_DRWE) 1408f1ae32a1SGerd Hoffmann ohci->rhstatus |= OHCI_RHS_DRWE; 1409f1ae32a1SGerd Hoffmann 1410f1ae32a1SGerd Hoffmann if (val & OHCI_RHS_CRWE) 1411f1ae32a1SGerd Hoffmann ohci->rhstatus &= ~OHCI_RHS_DRWE; 1412f1ae32a1SGerd Hoffmann 1413f1ae32a1SGerd Hoffmann if (old_state != ohci->rhstatus) 1414f1ae32a1SGerd Hoffmann ohci_set_interrupt(ohci, OHCI_INTR_RHSC); 1415f1ae32a1SGerd Hoffmann } 1416f1ae32a1SGerd Hoffmann 1417f1ae32a1SGerd Hoffmann /* Set root hub port status */ 1418f1ae32a1SGerd Hoffmann static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val) 1419f1ae32a1SGerd Hoffmann { 1420f1ae32a1SGerd Hoffmann uint32_t old_state; 1421f1ae32a1SGerd Hoffmann OHCIPort *port; 1422f1ae32a1SGerd Hoffmann 1423f1ae32a1SGerd Hoffmann port = &ohci->rhport[portnum]; 1424f1ae32a1SGerd Hoffmann old_state = port->ctrl; 1425f1ae32a1SGerd Hoffmann 1426f1ae32a1SGerd Hoffmann /* Write to clear CSC, PESC, PSSC, OCIC, PRSC */ 1427f1ae32a1SGerd Hoffmann if (val & OHCI_PORT_WTC) 1428f1ae32a1SGerd Hoffmann port->ctrl &= ~(val & OHCI_PORT_WTC); 1429f1ae32a1SGerd Hoffmann 1430f1ae32a1SGerd Hoffmann if (val & OHCI_PORT_CCS) 1431f1ae32a1SGerd Hoffmann port->ctrl &= ~OHCI_PORT_PES; 1432f1ae32a1SGerd Hoffmann 1433f1ae32a1SGerd Hoffmann ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PES); 1434f1ae32a1SGerd Hoffmann 1435f1ae32a1SGerd Hoffmann if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PSS)) { 1436dc1f5988SAlexey Kardashevskiy trace_usb_ohci_port_suspend(portnum); 1437f1ae32a1SGerd Hoffmann } 1438f1ae32a1SGerd Hoffmann 1439f1ae32a1SGerd Hoffmann if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PRS)) { 1440dc1f5988SAlexey Kardashevskiy trace_usb_ohci_port_reset(portnum); 1441f1ae32a1SGerd Hoffmann usb_device_reset(port->port.dev); 1442f1ae32a1SGerd Hoffmann port->ctrl &= ~OHCI_PORT_PRS; 1443f1ae32a1SGerd Hoffmann /* ??? Should this also set OHCI_PORT_PESC. */ 1444f1ae32a1SGerd Hoffmann port->ctrl |= OHCI_PORT_PES | OHCI_PORT_PRSC; 1445f1ae32a1SGerd Hoffmann } 1446f1ae32a1SGerd Hoffmann 1447*572a6732SBALATON Zoltan /* Invert order here to ensure in ambiguous case, device is powered up. */ 1448f1ae32a1SGerd Hoffmann if (val & OHCI_PORT_LSDA) 1449f1ae32a1SGerd Hoffmann ohci_port_power(ohci, portnum, 0); 1450f1ae32a1SGerd Hoffmann if (val & OHCI_PORT_PPS) 1451f1ae32a1SGerd Hoffmann ohci_port_power(ohci, portnum, 1); 1452f1ae32a1SGerd Hoffmann 1453f1ae32a1SGerd Hoffmann if (old_state != port->ctrl) 1454f1ae32a1SGerd Hoffmann ohci_set_interrupt(ohci, OHCI_INTR_RHSC); 1455f1ae32a1SGerd Hoffmann } 1456f1ae32a1SGerd Hoffmann 1457f1ae32a1SGerd Hoffmann static uint64_t ohci_mem_read(void *opaque, 1458a8170e5eSAvi Kivity hwaddr addr, 1459f1ae32a1SGerd Hoffmann unsigned size) 1460f1ae32a1SGerd Hoffmann { 1461f1ae32a1SGerd Hoffmann OHCIState *ohci = opaque; 1462f1ae32a1SGerd Hoffmann uint32_t retval; 1463f1ae32a1SGerd Hoffmann 1464f1ae32a1SGerd Hoffmann /* Only aligned reads are allowed on OHCI */ 1465f1ae32a1SGerd Hoffmann if (addr & 3) { 1466dc1f5988SAlexey Kardashevskiy trace_usb_ohci_mem_read_unaligned(addr); 1467f1ae32a1SGerd Hoffmann return 0xffffffff; 1468f1ae32a1SGerd Hoffmann } else if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) { 1469f1ae32a1SGerd Hoffmann /* HcRhPortStatus */ 1470f1ae32a1SGerd Hoffmann retval = ohci->rhport[(addr - 0x54) >> 2].ctrl | OHCI_PORT_PPS; 1471f1ae32a1SGerd Hoffmann } else { 1472f1ae32a1SGerd Hoffmann switch (addr >> 2) { 1473f1ae32a1SGerd Hoffmann case 0: /* HcRevision */ 1474f1ae32a1SGerd Hoffmann retval = 0x10; 1475f1ae32a1SGerd Hoffmann break; 1476f1ae32a1SGerd Hoffmann 1477f1ae32a1SGerd Hoffmann case 1: /* HcControl */ 1478f1ae32a1SGerd Hoffmann retval = ohci->ctl; 1479f1ae32a1SGerd Hoffmann break; 1480f1ae32a1SGerd Hoffmann 1481f1ae32a1SGerd Hoffmann case 2: /* HcCommandStatus */ 1482f1ae32a1SGerd Hoffmann retval = ohci->status; 1483f1ae32a1SGerd Hoffmann break; 1484f1ae32a1SGerd Hoffmann 1485f1ae32a1SGerd Hoffmann case 3: /* HcInterruptStatus */ 1486f1ae32a1SGerd Hoffmann retval = ohci->intr_status; 1487f1ae32a1SGerd Hoffmann break; 1488f1ae32a1SGerd Hoffmann 1489f1ae32a1SGerd Hoffmann case 4: /* HcInterruptEnable */ 1490f1ae32a1SGerd Hoffmann case 5: /* HcInterruptDisable */ 1491f1ae32a1SGerd Hoffmann retval = ohci->intr; 1492f1ae32a1SGerd Hoffmann break; 1493f1ae32a1SGerd Hoffmann 1494f1ae32a1SGerd Hoffmann case 6: /* HcHCCA */ 1495f1ae32a1SGerd Hoffmann retval = ohci->hcca; 1496f1ae32a1SGerd Hoffmann break; 1497f1ae32a1SGerd Hoffmann 1498f1ae32a1SGerd Hoffmann case 7: /* HcPeriodCurrentED */ 1499f1ae32a1SGerd Hoffmann retval = ohci->per_cur; 1500f1ae32a1SGerd Hoffmann break; 1501f1ae32a1SGerd Hoffmann 1502f1ae32a1SGerd Hoffmann case 8: /* HcControlHeadED */ 1503f1ae32a1SGerd Hoffmann retval = ohci->ctrl_head; 1504f1ae32a1SGerd Hoffmann break; 1505f1ae32a1SGerd Hoffmann 1506f1ae32a1SGerd Hoffmann case 9: /* HcControlCurrentED */ 1507f1ae32a1SGerd Hoffmann retval = ohci->ctrl_cur; 1508f1ae32a1SGerd Hoffmann break; 1509f1ae32a1SGerd Hoffmann 1510f1ae32a1SGerd Hoffmann case 10: /* HcBulkHeadED */ 1511f1ae32a1SGerd Hoffmann retval = ohci->bulk_head; 1512f1ae32a1SGerd Hoffmann break; 1513f1ae32a1SGerd Hoffmann 1514f1ae32a1SGerd Hoffmann case 11: /* HcBulkCurrentED */ 1515f1ae32a1SGerd Hoffmann retval = ohci->bulk_cur; 1516f1ae32a1SGerd Hoffmann break; 1517f1ae32a1SGerd Hoffmann 1518f1ae32a1SGerd Hoffmann case 12: /* HcDoneHead */ 1519f1ae32a1SGerd Hoffmann retval = ohci->done; 1520f1ae32a1SGerd Hoffmann break; 1521f1ae32a1SGerd Hoffmann 1522f1ae32a1SGerd Hoffmann case 13: /* HcFmInterretval */ 1523f1ae32a1SGerd Hoffmann retval = (ohci->fit << 31) | (ohci->fsmps << 16) | (ohci->fi); 1524f1ae32a1SGerd Hoffmann break; 1525f1ae32a1SGerd Hoffmann 1526f1ae32a1SGerd Hoffmann case 14: /* HcFmRemaining */ 1527f1ae32a1SGerd Hoffmann retval = ohci_get_frame_remaining(ohci); 1528f1ae32a1SGerd Hoffmann break; 1529f1ae32a1SGerd Hoffmann 1530f1ae32a1SGerd Hoffmann case 15: /* HcFmNumber */ 1531f1ae32a1SGerd Hoffmann retval = ohci->frame_number; 1532f1ae32a1SGerd Hoffmann break; 1533f1ae32a1SGerd Hoffmann 1534f1ae32a1SGerd Hoffmann case 16: /* HcPeriodicStart */ 1535f1ae32a1SGerd Hoffmann retval = ohci->pstart; 1536f1ae32a1SGerd Hoffmann break; 1537f1ae32a1SGerd Hoffmann 1538f1ae32a1SGerd Hoffmann case 17: /* HcLSThreshold */ 1539f1ae32a1SGerd Hoffmann retval = ohci->lst; 1540f1ae32a1SGerd Hoffmann break; 1541f1ae32a1SGerd Hoffmann 1542f1ae32a1SGerd Hoffmann case 18: /* HcRhDescriptorA */ 1543f1ae32a1SGerd Hoffmann retval = ohci->rhdesc_a; 1544f1ae32a1SGerd Hoffmann break; 1545f1ae32a1SGerd Hoffmann 1546f1ae32a1SGerd Hoffmann case 19: /* HcRhDescriptorB */ 1547f1ae32a1SGerd Hoffmann retval = ohci->rhdesc_b; 1548f1ae32a1SGerd Hoffmann break; 1549f1ae32a1SGerd Hoffmann 1550f1ae32a1SGerd Hoffmann case 20: /* HcRhStatus */ 1551f1ae32a1SGerd Hoffmann retval = ohci->rhstatus; 1552f1ae32a1SGerd Hoffmann break; 1553f1ae32a1SGerd Hoffmann 1554f1ae32a1SGerd Hoffmann /* PXA27x specific registers */ 1555f1ae32a1SGerd Hoffmann case 24: /* HcStatus */ 1556f1ae32a1SGerd Hoffmann retval = ohci->hstatus & ohci->hmask; 1557f1ae32a1SGerd Hoffmann break; 1558f1ae32a1SGerd Hoffmann 1559f1ae32a1SGerd Hoffmann case 25: /* HcHReset */ 1560f1ae32a1SGerd Hoffmann retval = ohci->hreset; 1561f1ae32a1SGerd Hoffmann break; 1562f1ae32a1SGerd Hoffmann 1563f1ae32a1SGerd Hoffmann case 26: /* HcHInterruptEnable */ 1564f1ae32a1SGerd Hoffmann retval = ohci->hmask; 1565f1ae32a1SGerd Hoffmann break; 1566f1ae32a1SGerd Hoffmann 1567f1ae32a1SGerd Hoffmann case 27: /* HcHInterruptTest */ 1568f1ae32a1SGerd Hoffmann retval = ohci->htest; 1569f1ae32a1SGerd Hoffmann break; 1570f1ae32a1SGerd Hoffmann 1571f1ae32a1SGerd Hoffmann default: 1572dc1f5988SAlexey Kardashevskiy trace_usb_ohci_mem_read_bad_offset(addr); 1573f1ae32a1SGerd Hoffmann retval = 0xffffffff; 1574f1ae32a1SGerd Hoffmann } 1575f1ae32a1SGerd Hoffmann } 1576f1ae32a1SGerd Hoffmann 1577f1ae32a1SGerd Hoffmann return retval; 1578f1ae32a1SGerd Hoffmann } 1579f1ae32a1SGerd Hoffmann 1580f1ae32a1SGerd Hoffmann static void ohci_mem_write(void *opaque, 1581a8170e5eSAvi Kivity hwaddr addr, 1582f1ae32a1SGerd Hoffmann uint64_t val, 1583f1ae32a1SGerd Hoffmann unsigned size) 1584f1ae32a1SGerd Hoffmann { 1585f1ae32a1SGerd Hoffmann OHCIState *ohci = opaque; 1586f1ae32a1SGerd Hoffmann 1587f1ae32a1SGerd Hoffmann /* Only aligned reads are allowed on OHCI */ 1588f1ae32a1SGerd Hoffmann if (addr & 3) { 1589dc1f5988SAlexey Kardashevskiy trace_usb_ohci_mem_write_unaligned(addr); 1590f1ae32a1SGerd Hoffmann return; 1591f1ae32a1SGerd Hoffmann } 1592f1ae32a1SGerd Hoffmann 1593f1ae32a1SGerd Hoffmann if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) { 1594f1ae32a1SGerd Hoffmann /* HcRhPortStatus */ 1595f1ae32a1SGerd Hoffmann ohci_port_set_status(ohci, (addr - 0x54) >> 2, val); 1596f1ae32a1SGerd Hoffmann return; 1597f1ae32a1SGerd Hoffmann } 1598f1ae32a1SGerd Hoffmann 1599f1ae32a1SGerd Hoffmann switch (addr >> 2) { 1600f1ae32a1SGerd Hoffmann case 1: /* HcControl */ 1601f1ae32a1SGerd Hoffmann ohci_set_ctl(ohci, val); 1602f1ae32a1SGerd Hoffmann break; 1603f1ae32a1SGerd Hoffmann 1604f1ae32a1SGerd Hoffmann case 2: /* HcCommandStatus */ 1605f1ae32a1SGerd Hoffmann /* SOC is read-only */ 1606f1ae32a1SGerd Hoffmann val = (val & ~OHCI_STATUS_SOC); 1607f1ae32a1SGerd Hoffmann 1608f1ae32a1SGerd Hoffmann /* Bits written as '0' remain unchanged in the register */ 1609f1ae32a1SGerd Hoffmann ohci->status |= val; 1610f1ae32a1SGerd Hoffmann 1611f1ae32a1SGerd Hoffmann if (ohci->status & OHCI_STATUS_HCR) 16120922c3f6SHervé Poussineau ohci_soft_reset(ohci); 1613f1ae32a1SGerd Hoffmann break; 1614f1ae32a1SGerd Hoffmann 1615f1ae32a1SGerd Hoffmann case 3: /* HcInterruptStatus */ 1616f1ae32a1SGerd Hoffmann ohci->intr_status &= ~val; 1617f1ae32a1SGerd Hoffmann ohci_intr_update(ohci); 1618f1ae32a1SGerd Hoffmann break; 1619f1ae32a1SGerd Hoffmann 1620f1ae32a1SGerd Hoffmann case 4: /* HcInterruptEnable */ 1621f1ae32a1SGerd Hoffmann ohci->intr |= val; 1622f1ae32a1SGerd Hoffmann ohci_intr_update(ohci); 1623f1ae32a1SGerd Hoffmann break; 1624f1ae32a1SGerd Hoffmann 1625f1ae32a1SGerd Hoffmann case 5: /* HcInterruptDisable */ 1626f1ae32a1SGerd Hoffmann ohci->intr &= ~val; 1627f1ae32a1SGerd Hoffmann ohci_intr_update(ohci); 1628f1ae32a1SGerd Hoffmann break; 1629f1ae32a1SGerd Hoffmann 1630f1ae32a1SGerd Hoffmann case 6: /* HcHCCA */ 1631f1ae32a1SGerd Hoffmann ohci->hcca = val & OHCI_HCCA_MASK; 1632f1ae32a1SGerd Hoffmann break; 1633f1ae32a1SGerd Hoffmann 1634f1ae32a1SGerd Hoffmann case 7: /* HcPeriodCurrentED */ 1635f1ae32a1SGerd Hoffmann /* Ignore writes to this read-only register, Linux does them */ 1636f1ae32a1SGerd Hoffmann break; 1637f1ae32a1SGerd Hoffmann 1638f1ae32a1SGerd Hoffmann case 8: /* HcControlHeadED */ 1639f1ae32a1SGerd Hoffmann ohci->ctrl_head = val & OHCI_EDPTR_MASK; 1640f1ae32a1SGerd Hoffmann break; 1641f1ae32a1SGerd Hoffmann 1642f1ae32a1SGerd Hoffmann case 9: /* HcControlCurrentED */ 1643f1ae32a1SGerd Hoffmann ohci->ctrl_cur = val & OHCI_EDPTR_MASK; 1644f1ae32a1SGerd Hoffmann break; 1645f1ae32a1SGerd Hoffmann 1646f1ae32a1SGerd Hoffmann case 10: /* HcBulkHeadED */ 1647f1ae32a1SGerd Hoffmann ohci->bulk_head = val & OHCI_EDPTR_MASK; 1648f1ae32a1SGerd Hoffmann break; 1649f1ae32a1SGerd Hoffmann 1650f1ae32a1SGerd Hoffmann case 11: /* HcBulkCurrentED */ 1651f1ae32a1SGerd Hoffmann ohci->bulk_cur = val & OHCI_EDPTR_MASK; 1652f1ae32a1SGerd Hoffmann break; 1653f1ae32a1SGerd Hoffmann 1654f1ae32a1SGerd Hoffmann case 13: /* HcFmInterval */ 1655f1ae32a1SGerd Hoffmann ohci->fsmps = (val & OHCI_FMI_FSMPS) >> 16; 1656f1ae32a1SGerd Hoffmann ohci->fit = (val & OHCI_FMI_FIT) >> 31; 1657f1ae32a1SGerd Hoffmann ohci_set_frame_interval(ohci, val); 1658f1ae32a1SGerd Hoffmann break; 1659f1ae32a1SGerd Hoffmann 1660f1ae32a1SGerd Hoffmann case 15: /* HcFmNumber */ 1661f1ae32a1SGerd Hoffmann break; 1662f1ae32a1SGerd Hoffmann 1663f1ae32a1SGerd Hoffmann case 16: /* HcPeriodicStart */ 1664f1ae32a1SGerd Hoffmann ohci->pstart = val & 0xffff; 1665f1ae32a1SGerd Hoffmann break; 1666f1ae32a1SGerd Hoffmann 1667f1ae32a1SGerd Hoffmann case 17: /* HcLSThreshold */ 1668f1ae32a1SGerd Hoffmann ohci->lst = val & 0xffff; 1669f1ae32a1SGerd Hoffmann break; 1670f1ae32a1SGerd Hoffmann 1671f1ae32a1SGerd Hoffmann case 18: /* HcRhDescriptorA */ 1672f1ae32a1SGerd Hoffmann ohci->rhdesc_a &= ~OHCI_RHA_RW_MASK; 1673f1ae32a1SGerd Hoffmann ohci->rhdesc_a |= val & OHCI_RHA_RW_MASK; 1674f1ae32a1SGerd Hoffmann break; 1675f1ae32a1SGerd Hoffmann 1676f1ae32a1SGerd Hoffmann case 19: /* HcRhDescriptorB */ 1677f1ae32a1SGerd Hoffmann break; 1678f1ae32a1SGerd Hoffmann 1679f1ae32a1SGerd Hoffmann case 20: /* HcRhStatus */ 1680f1ae32a1SGerd Hoffmann ohci_set_hub_status(ohci, val); 1681f1ae32a1SGerd Hoffmann break; 1682f1ae32a1SGerd Hoffmann 1683f1ae32a1SGerd Hoffmann /* PXA27x specific registers */ 1684f1ae32a1SGerd Hoffmann case 24: /* HcStatus */ 1685f1ae32a1SGerd Hoffmann ohci->hstatus &= ~(val & ohci->hmask); 16867fa96d73SGerd Hoffmann break; 1687f1ae32a1SGerd Hoffmann 1688f1ae32a1SGerd Hoffmann case 25: /* HcHReset */ 1689f1ae32a1SGerd Hoffmann ohci->hreset = val & ~OHCI_HRESET_FSBIR; 1690f1ae32a1SGerd Hoffmann if (val & OHCI_HRESET_FSBIR) 169184d04e21SHervé Poussineau ohci_hard_reset(ohci); 1692f1ae32a1SGerd Hoffmann break; 1693f1ae32a1SGerd Hoffmann 1694f1ae32a1SGerd Hoffmann case 26: /* HcHInterruptEnable */ 1695f1ae32a1SGerd Hoffmann ohci->hmask = val; 1696f1ae32a1SGerd Hoffmann break; 1697f1ae32a1SGerd Hoffmann 1698f1ae32a1SGerd Hoffmann case 27: /* HcHInterruptTest */ 1699f1ae32a1SGerd Hoffmann ohci->htest = val; 1700f1ae32a1SGerd Hoffmann break; 1701f1ae32a1SGerd Hoffmann 1702f1ae32a1SGerd Hoffmann default: 1703dc1f5988SAlexey Kardashevskiy trace_usb_ohci_mem_write_bad_offset(addr); 1704f1ae32a1SGerd Hoffmann break; 1705f1ae32a1SGerd Hoffmann } 1706f1ae32a1SGerd Hoffmann } 1707f1ae32a1SGerd Hoffmann 170837bf0654SBALATON Zoltan static const MemoryRegionOps ohci_mem_ops = { 170937bf0654SBALATON Zoltan .read = ohci_mem_read, 171037bf0654SBALATON Zoltan .write = ohci_mem_write, 171137bf0654SBALATON Zoltan .endianness = DEVICE_LITTLE_ENDIAN, 171237bf0654SBALATON Zoltan }; 171337bf0654SBALATON Zoltan 171437bf0654SBALATON Zoltan /* USBPortOps */ 171537bf0654SBALATON Zoltan static void ohci_attach(USBPort *port1) 171637bf0654SBALATON Zoltan { 171737bf0654SBALATON Zoltan OHCIState *s = port1->opaque; 171837bf0654SBALATON Zoltan OHCIPort *port = &s->rhport[port1->index]; 171937bf0654SBALATON Zoltan uint32_t old_state = port->ctrl; 172037bf0654SBALATON Zoltan 172137bf0654SBALATON Zoltan /* set connect status */ 172237bf0654SBALATON Zoltan port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC; 172337bf0654SBALATON Zoltan 172437bf0654SBALATON Zoltan /* update speed */ 172537bf0654SBALATON Zoltan if (port->port.dev->speed == USB_SPEED_LOW) { 172637bf0654SBALATON Zoltan port->ctrl |= OHCI_PORT_LSDA; 172737bf0654SBALATON Zoltan } else { 172837bf0654SBALATON Zoltan port->ctrl &= ~OHCI_PORT_LSDA; 172937bf0654SBALATON Zoltan } 173037bf0654SBALATON Zoltan 173137bf0654SBALATON Zoltan /* notify of remote-wakeup */ 173237bf0654SBALATON Zoltan if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) { 173337bf0654SBALATON Zoltan ohci_set_interrupt(s, OHCI_INTR_RD); 173437bf0654SBALATON Zoltan } 173537bf0654SBALATON Zoltan 173637bf0654SBALATON Zoltan trace_usb_ohci_port_attach(port1->index); 173737bf0654SBALATON Zoltan 173837bf0654SBALATON Zoltan if (old_state != port->ctrl) { 173937bf0654SBALATON Zoltan ohci_set_interrupt(s, OHCI_INTR_RHSC); 174037bf0654SBALATON Zoltan } 174137bf0654SBALATON Zoltan } 174237bf0654SBALATON Zoltan 1743b6b0c066SBALATON Zoltan static void ohci_child_detach(USBPort *port1, USBDevice *dev) 1744f1ae32a1SGerd Hoffmann { 1745b6b0c066SBALATON Zoltan OHCIState *ohci = port1->opaque; 1746b6b0c066SBALATON Zoltan 1747f1ae32a1SGerd Hoffmann if (ohci->async_td && 1748f1ae32a1SGerd Hoffmann usb_packet_is_inflight(&ohci->usb_packet) && 1749f1ae32a1SGerd Hoffmann ohci->usb_packet.ep->dev == dev) { 1750f1ae32a1SGerd Hoffmann usb_cancel_packet(&ohci->usb_packet); 1751f1ae32a1SGerd Hoffmann ohci->async_td = 0; 1752f1ae32a1SGerd Hoffmann } 1753f1ae32a1SGerd Hoffmann } 1754f1ae32a1SGerd Hoffmann 175537bf0654SBALATON Zoltan static void ohci_detach(USBPort *port1) 175637bf0654SBALATON Zoltan { 175737bf0654SBALATON Zoltan OHCIState *s = port1->opaque; 175837bf0654SBALATON Zoltan OHCIPort *port = &s->rhport[port1->index]; 175937bf0654SBALATON Zoltan uint32_t old_state = port->ctrl; 176037bf0654SBALATON Zoltan 1761b6b0c066SBALATON Zoltan ohci_child_detach(port1, port1->dev); 176237bf0654SBALATON Zoltan 176337bf0654SBALATON Zoltan /* set connect status */ 176437bf0654SBALATON Zoltan if (port->ctrl & OHCI_PORT_CCS) { 176537bf0654SBALATON Zoltan port->ctrl &= ~OHCI_PORT_CCS; 176637bf0654SBALATON Zoltan port->ctrl |= OHCI_PORT_CSC; 176737bf0654SBALATON Zoltan } 176837bf0654SBALATON Zoltan /* disable port */ 176937bf0654SBALATON Zoltan if (port->ctrl & OHCI_PORT_PES) { 177037bf0654SBALATON Zoltan port->ctrl &= ~OHCI_PORT_PES; 177137bf0654SBALATON Zoltan port->ctrl |= OHCI_PORT_PESC; 177237bf0654SBALATON Zoltan } 177337bf0654SBALATON Zoltan trace_usb_ohci_port_detach(port1->index); 177437bf0654SBALATON Zoltan 177537bf0654SBALATON Zoltan if (old_state != port->ctrl) { 177637bf0654SBALATON Zoltan ohci_set_interrupt(s, OHCI_INTR_RHSC); 177737bf0654SBALATON Zoltan } 177837bf0654SBALATON Zoltan } 177937bf0654SBALATON Zoltan 178037bf0654SBALATON Zoltan static void ohci_wakeup(USBPort *port1) 178137bf0654SBALATON Zoltan { 178237bf0654SBALATON Zoltan OHCIState *s = port1->opaque; 178337bf0654SBALATON Zoltan OHCIPort *port = &s->rhport[port1->index]; 178437bf0654SBALATON Zoltan uint32_t intr = 0; 178537bf0654SBALATON Zoltan if (port->ctrl & OHCI_PORT_PSS) { 178637bf0654SBALATON Zoltan trace_usb_ohci_port_wakeup(port1->index); 178737bf0654SBALATON Zoltan port->ctrl |= OHCI_PORT_PSSC; 178837bf0654SBALATON Zoltan port->ctrl &= ~OHCI_PORT_PSS; 178937bf0654SBALATON Zoltan intr = OHCI_INTR_RHSC; 179037bf0654SBALATON Zoltan } 179137bf0654SBALATON Zoltan /* Note that the controller can be suspended even if this port is not */ 179237bf0654SBALATON Zoltan if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) { 179337bf0654SBALATON Zoltan trace_usb_ohci_remote_wakeup(s->name); 179437bf0654SBALATON Zoltan /* This is the one state transition the controller can do by itself */ 179537bf0654SBALATON Zoltan s->ctl &= ~OHCI_CTL_HCFS; 179637bf0654SBALATON Zoltan s->ctl |= OHCI_USB_RESUME; 179737bf0654SBALATON Zoltan /* 179837bf0654SBALATON Zoltan * In suspend mode only ResumeDetected is possible, not RHSC: 179937bf0654SBALATON Zoltan * see the OHCI spec 5.1.2.3. 180037bf0654SBALATON Zoltan */ 180137bf0654SBALATON Zoltan intr = OHCI_INTR_RD; 180237bf0654SBALATON Zoltan } 180337bf0654SBALATON Zoltan ohci_set_interrupt(s, intr); 180437bf0654SBALATON Zoltan } 180537bf0654SBALATON Zoltan 180637bf0654SBALATON Zoltan static void ohci_async_complete_packet(USBPort *port, USBPacket *packet) 180737bf0654SBALATON Zoltan { 180837bf0654SBALATON Zoltan OHCIState *ohci = container_of(packet, OHCIState, usb_packet); 180937bf0654SBALATON Zoltan 181037bf0654SBALATON Zoltan trace_usb_ohci_async_complete(); 181137bf0654SBALATON Zoltan ohci->async_complete = true; 18123a4d06f2SBALATON Zoltan ohci_process_lists(ohci); 181337bf0654SBALATON Zoltan } 1814f1ae32a1SGerd Hoffmann 1815f1ae32a1SGerd Hoffmann static USBPortOps ohci_port_ops = { 1816f1ae32a1SGerd Hoffmann .attach = ohci_attach, 1817f1ae32a1SGerd Hoffmann .detach = ohci_detach, 1818f1ae32a1SGerd Hoffmann .child_detach = ohci_child_detach, 1819f1ae32a1SGerd Hoffmann .wakeup = ohci_wakeup, 1820f1ae32a1SGerd Hoffmann .complete = ohci_async_complete_packet, 1821f1ae32a1SGerd Hoffmann }; 1822f1ae32a1SGerd Hoffmann 1823f1ae32a1SGerd Hoffmann static USBBusOps ohci_bus_ops = { 1824f1ae32a1SGerd Hoffmann }; 1825f1ae32a1SGerd Hoffmann 182634d97308SThomas Huth void usb_ohci_init(OHCIState *ohci, DeviceState *dev, uint32_t num_ports, 182734d97308SThomas Huth dma_addr_t localmem_base, char *masterbus, 182834d97308SThomas Huth uint32_t firstport, AddressSpace *as, 18294713720aSPhilippe Mathieu-Daudé void (*ohci_die_fn)(OHCIState *), Error **errp) 1830f1ae32a1SGerd Hoffmann { 1831f4bbaaf5SMarkus Armbruster Error *err = NULL; 1832f1ae32a1SGerd Hoffmann int i; 1833f1ae32a1SGerd Hoffmann 1834df32fd1cSPaolo Bonzini ohci->as = as; 183572e0c127SThomas Huth ohci->ohci_die = ohci_die_fn; 18369ac6a217SDavid Gibson 1837d400fc01SThomas Huth if (num_ports > OHCI_MAX_PORTS) { 1838b9a3a4f2SLi Qiang error_setg(errp, "OHCI num-ports=%u is too big (limit is %u ports)", 1839d400fc01SThomas Huth num_ports, OHCI_MAX_PORTS); 1840d400fc01SThomas Huth return; 1841d400fc01SThomas Huth } 1842d400fc01SThomas Huth 1843f1ae32a1SGerd Hoffmann if (usb_frame_time == 0) { 1844f1ae32a1SGerd Hoffmann #ifdef OHCI_TIME_WARP 184573bcb24dSRutuja Shah usb_frame_time = NANOSECONDS_PER_SECOND; 184673bcb24dSRutuja Shah usb_bit_time = NANOSECONDS_PER_SECOND / (USB_HZ / 1000); 1847f1ae32a1SGerd Hoffmann #else 184873bcb24dSRutuja Shah usb_frame_time = NANOSECONDS_PER_SECOND / 1000; 184973bcb24dSRutuja Shah if (NANOSECONDS_PER_SECOND >= USB_HZ) { 185073bcb24dSRutuja Shah usb_bit_time = NANOSECONDS_PER_SECOND / USB_HZ; 1851f1ae32a1SGerd Hoffmann } else { 1852f1ae32a1SGerd Hoffmann usb_bit_time = 1; 1853f1ae32a1SGerd Hoffmann } 1854f1ae32a1SGerd Hoffmann #endif 1855dc1f5988SAlexey Kardashevskiy trace_usb_ohci_init_time(usb_frame_time, usb_bit_time); 1856f1ae32a1SGerd Hoffmann } 1857f1ae32a1SGerd Hoffmann 1858f1ae32a1SGerd Hoffmann ohci->num_ports = num_ports; 1859f1ae32a1SGerd Hoffmann if (masterbus) { 1860f1ae32a1SGerd Hoffmann USBPort *ports[OHCI_MAX_PORTS]; 1861f1ae32a1SGerd Hoffmann for(i = 0; i < num_ports; i++) { 1862f1ae32a1SGerd Hoffmann ports[i] = &ohci->rhport[i].port; 1863f1ae32a1SGerd Hoffmann } 1864f4bbaaf5SMarkus Armbruster usb_register_companion(masterbus, ports, num_ports, 1865f1ae32a1SGerd Hoffmann firstport, ohci, &ohci_port_ops, 1866f4bbaaf5SMarkus Armbruster USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL, 1867f4bbaaf5SMarkus Armbruster &err); 1868f4bbaaf5SMarkus Armbruster if (err) { 186987581feaSMarkus Armbruster error_propagate(errp, err); 187087581feaSMarkus Armbruster return; 1871f1ae32a1SGerd Hoffmann } 1872f1ae32a1SGerd Hoffmann } else { 1873c889b3a5SAndreas Färber usb_bus_new(&ohci->bus, sizeof(ohci->bus), &ohci_bus_ops, dev); 1874f1ae32a1SGerd Hoffmann for (i = 0; i < num_ports; i++) { 1875f1ae32a1SGerd Hoffmann usb_register_port(&ohci->bus, &ohci->rhport[i].port, 1876f1ae32a1SGerd Hoffmann ohci, i, &ohci_port_ops, 1877f1ae32a1SGerd Hoffmann USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL); 1878f1ae32a1SGerd Hoffmann } 1879f1ae32a1SGerd Hoffmann } 1880f1ae32a1SGerd Hoffmann 188122fc860bSPaolo Bonzini memory_region_init_io(&ohci->mem, OBJECT(dev), &ohci_mem_ops, 188222fc860bSPaolo Bonzini ohci, "ohci", 256); 1883f1ae32a1SGerd Hoffmann ohci->localmem_base = localmem_base; 1884f1ae32a1SGerd Hoffmann 1885f1ae32a1SGerd Hoffmann ohci->name = object_get_typename(OBJECT(dev)); 1886f1ae32a1SGerd Hoffmann usb_packet_init(&ohci->usb_packet); 1887f1ae32a1SGerd Hoffmann 1888f1ae32a1SGerd Hoffmann ohci->async_td = 0; 1889fa1298c2SGerd Hoffmann 1890fa1298c2SGerd Hoffmann ohci->eof_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, 1891fa1298c2SGerd Hoffmann ohci_frame_boundary, ohci); 1892f1ae32a1SGerd Hoffmann } 1893f1ae32a1SGerd Hoffmann 1894*572a6732SBALATON Zoltan /* 189572e0c127SThomas Huth * A typical OHCI will stop operating and set itself into error state 189672e0c127SThomas Huth * (which can be queried by MMIO) to signal that it got an error. 1897cf66ee8eSAlexey Kardashevskiy */ 189834d97308SThomas Huth void ohci_sysbus_die(struct OHCIState *ohci) 1899cf66ee8eSAlexey Kardashevskiy { 1900dc1f5988SAlexey Kardashevskiy trace_usb_ohci_die(); 1901cf66ee8eSAlexey Kardashevskiy 1902cf66ee8eSAlexey Kardashevskiy ohci_set_interrupt(ohci, OHCI_INTR_UE); 1903cf66ee8eSAlexey Kardashevskiy ohci_bus_stop(ohci); 190472e0c127SThomas Huth } 190572e0c127SThomas Huth 1906457215ecSHu Tao static void ohci_realize_pxa(DeviceState *dev, Error **errp) 1907f1ae32a1SGerd Hoffmann { 19081aa0c0c7SHu Tao OHCISysBusState *s = SYSBUS_OHCI(dev); 1909457215ecSHu Tao SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 1910d7145b66SBALATON Zoltan Error *err = NULL; 1911f1ae32a1SGerd Hoffmann 1912d7145b66SBALATON Zoltan usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset, 1913d7145b66SBALATON Zoltan s->masterbus, s->firstport, 191472e0c127SThomas Huth &address_space_memory, ohci_sysbus_die, &err); 1915d7145b66SBALATON Zoltan if (err) { 1916d7145b66SBALATON Zoltan error_propagate(errp, err); 1917d7145b66SBALATON Zoltan return; 1918d7145b66SBALATON Zoltan } 1919457215ecSHu Tao sysbus_init_irq(sbd, &s->ohci.irq); 1920457215ecSHu Tao sysbus_init_mmio(sbd, &s->ohci.mem); 1921f1ae32a1SGerd Hoffmann } 1922f1ae32a1SGerd Hoffmann 192388dd1b8dSGonglei static void usb_ohci_reset_sysbus(DeviceState *dev) 192488dd1b8dSGonglei { 192588dd1b8dSGonglei OHCISysBusState *s = SYSBUS_OHCI(dev); 192688dd1b8dSGonglei OHCIState *ohci = &s->ohci; 192788dd1b8dSGonglei 192884d04e21SHervé Poussineau ohci_hard_reset(ohci); 192988dd1b8dSGonglei } 193088dd1b8dSGonglei 193169e25d26SAlexey Kardashevskiy static const VMStateDescription vmstate_ohci_state_port = { 193269e25d26SAlexey Kardashevskiy .name = "ohci-core/port", 193369e25d26SAlexey Kardashevskiy .version_id = 1, 193469e25d26SAlexey Kardashevskiy .minimum_version_id = 1, 193569e25d26SAlexey Kardashevskiy .fields = (VMStateField[]) { 193669e25d26SAlexey Kardashevskiy VMSTATE_UINT32(ctrl, OHCIPort), 193769e25d26SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 193869e25d26SAlexey Kardashevskiy }, 193969e25d26SAlexey Kardashevskiy }; 194069e25d26SAlexey Kardashevskiy 194169e25d26SAlexey Kardashevskiy static bool ohci_eof_timer_needed(void *opaque) 194269e25d26SAlexey Kardashevskiy { 194369e25d26SAlexey Kardashevskiy OHCIState *ohci = opaque; 194469e25d26SAlexey Kardashevskiy 1945fa1298c2SGerd Hoffmann return timer_pending(ohci->eof_timer); 194669e25d26SAlexey Kardashevskiy } 194769e25d26SAlexey Kardashevskiy 194869e25d26SAlexey Kardashevskiy static const VMStateDescription vmstate_ohci_eof_timer = { 194969e25d26SAlexey Kardashevskiy .name = "ohci-core/eof-timer", 195069e25d26SAlexey Kardashevskiy .version_id = 1, 195169e25d26SAlexey Kardashevskiy .minimum_version_id = 1, 19525cd8cadaSJuan Quintela .needed = ohci_eof_timer_needed, 195369e25d26SAlexey Kardashevskiy .fields = (VMStateField[]) { 1954e720677eSPaolo Bonzini VMSTATE_TIMER_PTR(eof_timer, OHCIState), 195569e25d26SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 195669e25d26SAlexey Kardashevskiy }, 195769e25d26SAlexey Kardashevskiy }; 195869e25d26SAlexey Kardashevskiy 195934d97308SThomas Huth const VMStateDescription vmstate_ohci_state = { 196069e25d26SAlexey Kardashevskiy .name = "ohci-core", 196169e25d26SAlexey Kardashevskiy .version_id = 1, 196269e25d26SAlexey Kardashevskiy .minimum_version_id = 1, 196369e25d26SAlexey Kardashevskiy .fields = (VMStateField[]) { 196469e25d26SAlexey Kardashevskiy VMSTATE_INT64(sof_time, OHCIState), 196569e25d26SAlexey Kardashevskiy VMSTATE_UINT32(ctl, OHCIState), 196669e25d26SAlexey Kardashevskiy VMSTATE_UINT32(status, OHCIState), 196769e25d26SAlexey Kardashevskiy VMSTATE_UINT32(intr_status, OHCIState), 196869e25d26SAlexey Kardashevskiy VMSTATE_UINT32(intr, OHCIState), 196969e25d26SAlexey Kardashevskiy VMSTATE_UINT32(hcca, OHCIState), 197069e25d26SAlexey Kardashevskiy VMSTATE_UINT32(ctrl_head, OHCIState), 197169e25d26SAlexey Kardashevskiy VMSTATE_UINT32(ctrl_cur, OHCIState), 197269e25d26SAlexey Kardashevskiy VMSTATE_UINT32(bulk_head, OHCIState), 197369e25d26SAlexey Kardashevskiy VMSTATE_UINT32(bulk_cur, OHCIState), 197469e25d26SAlexey Kardashevskiy VMSTATE_UINT32(per_cur, OHCIState), 197569e25d26SAlexey Kardashevskiy VMSTATE_UINT32(done, OHCIState), 197669e25d26SAlexey Kardashevskiy VMSTATE_INT32(done_count, OHCIState), 197769e25d26SAlexey Kardashevskiy VMSTATE_UINT16(fsmps, OHCIState), 197869e25d26SAlexey Kardashevskiy VMSTATE_UINT8(fit, OHCIState), 197969e25d26SAlexey Kardashevskiy VMSTATE_UINT16(fi, OHCIState), 198069e25d26SAlexey Kardashevskiy VMSTATE_UINT8(frt, OHCIState), 198169e25d26SAlexey Kardashevskiy VMSTATE_UINT16(frame_number, OHCIState), 198269e25d26SAlexey Kardashevskiy VMSTATE_UINT16(padding, OHCIState), 198369e25d26SAlexey Kardashevskiy VMSTATE_UINT32(pstart, OHCIState), 198469e25d26SAlexey Kardashevskiy VMSTATE_UINT32(lst, OHCIState), 198569e25d26SAlexey Kardashevskiy VMSTATE_UINT32(rhdesc_a, OHCIState), 198669e25d26SAlexey Kardashevskiy VMSTATE_UINT32(rhdesc_b, OHCIState), 198769e25d26SAlexey Kardashevskiy VMSTATE_UINT32(rhstatus, OHCIState), 198869e25d26SAlexey Kardashevskiy VMSTATE_STRUCT_ARRAY(rhport, OHCIState, OHCI_MAX_PORTS, 0, 198969e25d26SAlexey Kardashevskiy vmstate_ohci_state_port, OHCIPort), 199069e25d26SAlexey Kardashevskiy VMSTATE_UINT32(hstatus, OHCIState), 199169e25d26SAlexey Kardashevskiy VMSTATE_UINT32(hmask, OHCIState), 199269e25d26SAlexey Kardashevskiy VMSTATE_UINT32(hreset, OHCIState), 199369e25d26SAlexey Kardashevskiy VMSTATE_UINT32(htest, OHCIState), 199469e25d26SAlexey Kardashevskiy VMSTATE_UINT32(old_ctl, OHCIState), 199569e25d26SAlexey Kardashevskiy VMSTATE_UINT8_ARRAY(usb_buf, OHCIState, 8192), 199669e25d26SAlexey Kardashevskiy VMSTATE_UINT32(async_td, OHCIState), 199769e25d26SAlexey Kardashevskiy VMSTATE_BOOL(async_complete, OHCIState), 199869e25d26SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 199969e25d26SAlexey Kardashevskiy }, 20005cd8cadaSJuan Quintela .subsections = (const VMStateDescription*[]) { 20015cd8cadaSJuan Quintela &vmstate_ohci_eof_timer, 20025cd8cadaSJuan Quintela NULL 200369e25d26SAlexey Kardashevskiy } 200469e25d26SAlexey Kardashevskiy }; 200569e25d26SAlexey Kardashevskiy 2006f1ae32a1SGerd Hoffmann static Property ohci_sysbus_properties[] = { 2007d7145b66SBALATON Zoltan DEFINE_PROP_STRING("masterbus", OHCISysBusState, masterbus), 2008f1ae32a1SGerd Hoffmann DEFINE_PROP_UINT32("num-ports", OHCISysBusState, num_ports, 3), 2009d7145b66SBALATON Zoltan DEFINE_PROP_UINT32("firstport", OHCISysBusState, firstport, 0), 20106998b6c7SVijay Kumar B DEFINE_PROP_DMAADDR("dma-offset", OHCISysBusState, dma_offset, 0), 2011f1ae32a1SGerd Hoffmann DEFINE_PROP_END_OF_LIST(), 2012f1ae32a1SGerd Hoffmann }; 2013f1ae32a1SGerd Hoffmann 2014f1ae32a1SGerd Hoffmann static void ohci_sysbus_class_init(ObjectClass *klass, void *data) 2015f1ae32a1SGerd Hoffmann { 2016f1ae32a1SGerd Hoffmann DeviceClass *dc = DEVICE_CLASS(klass); 2017f1ae32a1SGerd Hoffmann 2018457215ecSHu Tao dc->realize = ohci_realize_pxa; 2019125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_USB, dc->categories); 2020f1ae32a1SGerd Hoffmann dc->desc = "OHCI USB Controller"; 20214f67d30bSMarc-André Lureau device_class_set_props(dc, ohci_sysbus_properties); 202288dd1b8dSGonglei dc->reset = usb_ohci_reset_sysbus; 2023f1ae32a1SGerd Hoffmann } 2024f1ae32a1SGerd Hoffmann 20258c43a6f0SAndreas Färber static const TypeInfo ohci_sysbus_info = { 20261aa0c0c7SHu Tao .name = TYPE_SYSBUS_OHCI, 2027f1ae32a1SGerd Hoffmann .parent = TYPE_SYS_BUS_DEVICE, 2028f1ae32a1SGerd Hoffmann .instance_size = sizeof(OHCISysBusState), 2029f1ae32a1SGerd Hoffmann .class_init = ohci_sysbus_class_init, 2030f1ae32a1SGerd Hoffmann }; 2031f1ae32a1SGerd Hoffmann 2032f1ae32a1SGerd Hoffmann static void ohci_register_types(void) 2033f1ae32a1SGerd Hoffmann { 2034f1ae32a1SGerd Hoffmann type_register_static(&ohci_sysbus_info); 2035f1ae32a1SGerd Hoffmann } 2036f1ae32a1SGerd Hoffmann 2037f1ae32a1SGerd Hoffmann type_init(ohci_register_types) 2038