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 */ 42f1ae32a1SGerd Hoffmann //#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; 338f1ae32a1SGerd Hoffmann 339f1ae32a1SGerd Hoffmann /* 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 { 46386e18caeSWei Yang /* ed->tail is under control of the HCD. 46486e18caeSWei Yang * Since just ed->head is changed by HC, just write back this 46586e18caeSWei Yang */ 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) { 604f1ae32a1SGerd Hoffmann /* ISO TD expired - retire the TD to the Done Queue and continue with 605f1ae32a1SGerd Hoffmann the next ISO TD of the same ED */ 606dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_relative_frame_number_big(relative_frame_number, 607f1ae32a1SGerd Hoffmann frame_count); 6081be90ebeSPrasad J Pandit if (OHCI_CC_DATAOVERRUN == OHCI_BM(iso_td.flags, TD_CC)) { 6091be90ebeSPrasad J Pandit /* avoid infinite loop */ 6101be90ebeSPrasad J Pandit return 1; 6111be90ebeSPrasad J Pandit } 612f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_DATAOVERRUN); 613f1ae32a1SGerd Hoffmann ed->head &= ~OHCI_DPTR_MASK; 614f1ae32a1SGerd Hoffmann ed->head |= (iso_td.next & OHCI_DPTR_MASK); 615f1ae32a1SGerd Hoffmann iso_td.next = ohci->done; 616f1ae32a1SGerd Hoffmann ohci->done = addr; 617f1ae32a1SGerd Hoffmann i = OHCI_BM(iso_td.flags, TD_DI); 618f1ae32a1SGerd Hoffmann if (i < ohci->done_count) 619f1ae32a1SGerd Hoffmann ohci->done_count = i; 620cf66ee8eSAlexey Kardashevskiy if (ohci_put_iso_td(ohci, addr, &iso_td)) { 621cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 622cf66ee8eSAlexey Kardashevskiy return 1; 623cf66ee8eSAlexey Kardashevskiy } 624f1ae32a1SGerd Hoffmann return 0; 625f1ae32a1SGerd Hoffmann } 626f1ae32a1SGerd Hoffmann 627f1ae32a1SGerd Hoffmann dir = OHCI_BM(ed->flags, ED_D); 628f1ae32a1SGerd Hoffmann switch (dir) { 629f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_IN: 630f1ae32a1SGerd Hoffmann str = "in"; 631f1ae32a1SGerd Hoffmann pid = USB_TOKEN_IN; 632f1ae32a1SGerd Hoffmann break; 633f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_OUT: 634f1ae32a1SGerd Hoffmann str = "out"; 635f1ae32a1SGerd Hoffmann pid = USB_TOKEN_OUT; 636f1ae32a1SGerd Hoffmann break; 637f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_SETUP: 638f1ae32a1SGerd Hoffmann str = "setup"; 639f1ae32a1SGerd Hoffmann pid = USB_TOKEN_SETUP; 640f1ae32a1SGerd Hoffmann break; 641f1ae32a1SGerd Hoffmann default: 642dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_bad_direction(dir); 643f1ae32a1SGerd Hoffmann return 1; 644f1ae32a1SGerd Hoffmann } 645f1ae32a1SGerd Hoffmann 646f1ae32a1SGerd Hoffmann if (!iso_td.bp || !iso_td.be) { 647dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_bad_bp_be(iso_td.bp, iso_td.be); 648f1ae32a1SGerd Hoffmann return 1; 649f1ae32a1SGerd Hoffmann } 650f1ae32a1SGerd Hoffmann 651f1ae32a1SGerd Hoffmann start_offset = iso_td.offset[relative_frame_number]; 6521328fe0cSPrasad J Pandit if (relative_frame_number < frame_count) { 653f1ae32a1SGerd Hoffmann next_offset = iso_td.offset[relative_frame_number + 1]; 6541328fe0cSPrasad J Pandit } else { 6551328fe0cSPrasad J Pandit next_offset = iso_td.be; 6561328fe0cSPrasad J Pandit } 657f1ae32a1SGerd Hoffmann 658f1ae32a1SGerd Hoffmann if (!(OHCI_BM(start_offset, TD_PSW_CC) & 0xe) || 659f1ae32a1SGerd Hoffmann ((relative_frame_number < frame_count) && 660f1ae32a1SGerd Hoffmann !(OHCI_BM(next_offset, TD_PSW_CC) & 0xe))) { 661dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_bad_cc_not_accessed(start_offset, next_offset); 662f1ae32a1SGerd Hoffmann return 1; 663f1ae32a1SGerd Hoffmann } 664f1ae32a1SGerd Hoffmann 665f1ae32a1SGerd Hoffmann if ((relative_frame_number < frame_count) && (start_offset > next_offset)) { 666dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_bad_cc_overrun(start_offset, next_offset); 667f1ae32a1SGerd Hoffmann return 1; 668f1ae32a1SGerd Hoffmann } 669f1ae32a1SGerd Hoffmann 670f1ae32a1SGerd Hoffmann if ((start_offset & 0x1000) == 0) { 671f1ae32a1SGerd Hoffmann start_addr = (iso_td.bp & OHCI_PAGE_MASK) | 672f1ae32a1SGerd Hoffmann (start_offset & OHCI_OFFSET_MASK); 673f1ae32a1SGerd Hoffmann } else { 674f1ae32a1SGerd Hoffmann start_addr = (iso_td.be & OHCI_PAGE_MASK) | 675f1ae32a1SGerd Hoffmann (start_offset & OHCI_OFFSET_MASK); 676f1ae32a1SGerd Hoffmann } 677f1ae32a1SGerd Hoffmann 678f1ae32a1SGerd Hoffmann if (relative_frame_number < frame_count) { 679f1ae32a1SGerd Hoffmann end_offset = next_offset - 1; 680f1ae32a1SGerd Hoffmann if ((end_offset & 0x1000) == 0) { 681f1ae32a1SGerd Hoffmann end_addr = (iso_td.bp & OHCI_PAGE_MASK) | 682f1ae32a1SGerd Hoffmann (end_offset & OHCI_OFFSET_MASK); 683f1ae32a1SGerd Hoffmann } else { 684f1ae32a1SGerd Hoffmann end_addr = (iso_td.be & OHCI_PAGE_MASK) | 685f1ae32a1SGerd Hoffmann (end_offset & OHCI_OFFSET_MASK); 686f1ae32a1SGerd Hoffmann } 687f1ae32a1SGerd Hoffmann } else { 688f1ae32a1SGerd Hoffmann /* Last packet in the ISO TD */ 6891328fe0cSPrasad J Pandit end_addr = next_offset; 6901328fe0cSPrasad J Pandit } 6911328fe0cSPrasad J Pandit 6921328fe0cSPrasad J Pandit if (start_addr > end_addr) { 6931328fe0cSPrasad J Pandit trace_usb_ohci_iso_td_bad_cc_overrun(start_addr, end_addr); 6941328fe0cSPrasad J Pandit return 1; 695f1ae32a1SGerd Hoffmann } 696f1ae32a1SGerd Hoffmann 697f1ae32a1SGerd Hoffmann if ((start_addr & OHCI_PAGE_MASK) != (end_addr & OHCI_PAGE_MASK)) { 698f1ae32a1SGerd Hoffmann len = (end_addr & OHCI_OFFSET_MASK) + 0x1001 699f1ae32a1SGerd Hoffmann - (start_addr & OHCI_OFFSET_MASK); 700f1ae32a1SGerd Hoffmann } else { 701f1ae32a1SGerd Hoffmann len = end_addr - start_addr + 1; 702f1ae32a1SGerd Hoffmann } 7033a4d06f2SBALATON Zoltan if (len > sizeof(buf)) { 7043a4d06f2SBALATON Zoltan len = sizeof(buf); 7051328fe0cSPrasad J Pandit } 706f1ae32a1SGerd Hoffmann 707f1ae32a1SGerd Hoffmann if (len && dir != OHCI_TD_DIR_IN) { 7083a4d06f2SBALATON Zoltan if (ohci_copy_iso_td(ohci, start_addr, end_addr, buf, len, 709cf66ee8eSAlexey Kardashevskiy DMA_DIRECTION_TO_DEVICE)) { 710cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 711cf66ee8eSAlexey Kardashevskiy return 1; 712cf66ee8eSAlexey Kardashevskiy } 713f1ae32a1SGerd Hoffmann } 714f1ae32a1SGerd Hoffmann 715f1ae32a1SGerd Hoffmann dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA)); 71642340fc3SLiam Merwick if (dev == NULL) { 71742340fc3SLiam Merwick trace_usb_ohci_td_dev_error(); 71842340fc3SLiam Merwick return 1; 71942340fc3SLiam Merwick } 720f1ae32a1SGerd Hoffmann ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN)); 7213a4d06f2SBALATON Zoltan pkt = g_new0(USBPacket, 1); 7223a4d06f2SBALATON Zoltan usb_packet_init(pkt); 7233a4d06f2SBALATON Zoltan int_req = relative_frame_number == frame_count && 7243a4d06f2SBALATON Zoltan OHCI_BM(iso_td.flags, TD_DI) == 0; 7253a4d06f2SBALATON Zoltan usb_packet_setup(pkt, pid, ep, 0, addr, false, int_req); 7263a4d06f2SBALATON Zoltan usb_packet_addbuf(pkt, buf, len); 7273a4d06f2SBALATON Zoltan usb_handle_packet(dev, pkt); 7283a4d06f2SBALATON Zoltan if (pkt->status == USB_RET_ASYNC) { 72936dfe324SHans de Goede usb_device_flush_ep_queue(dev, ep); 7303a4d06f2SBALATON Zoltan g_free(pkt); 731f1ae32a1SGerd Hoffmann return 1; 732f1ae32a1SGerd Hoffmann } 7333a4d06f2SBALATON Zoltan if (pkt->status == USB_RET_SUCCESS) { 7343a4d06f2SBALATON Zoltan ret = pkt->actual_length; 7359a77a0f5SHans de Goede } else { 7363a4d06f2SBALATON Zoltan ret = pkt->status; 7379a77a0f5SHans de Goede } 7383a4d06f2SBALATON Zoltan g_free(pkt); 739f1ae32a1SGerd Hoffmann 740dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_so(start_offset, end_offset, start_addr, end_addr, 741dc1f5988SAlexey Kardashevskiy str, len, ret); 742f1ae32a1SGerd Hoffmann 743f1ae32a1SGerd Hoffmann /* Writeback */ 744f1ae32a1SGerd Hoffmann if (dir == OHCI_TD_DIR_IN && ret >= 0 && ret <= len) { 745f1ae32a1SGerd Hoffmann /* IN transfer succeeded */ 7463a4d06f2SBALATON Zoltan if (ohci_copy_iso_td(ohci, start_addr, end_addr, buf, ret, 747cf66ee8eSAlexey Kardashevskiy DMA_DIRECTION_FROM_DEVICE)) { 748cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 749cf66ee8eSAlexey Kardashevskiy return 1; 750cf66ee8eSAlexey Kardashevskiy } 751f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 752f1ae32a1SGerd Hoffmann OHCI_CC_NOERROR); 753f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, ret); 754f1ae32a1SGerd Hoffmann } else if (dir == OHCI_TD_DIR_OUT && ret == len) { 755f1ae32a1SGerd Hoffmann /* OUT transfer succeeded */ 756f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 757f1ae32a1SGerd Hoffmann OHCI_CC_NOERROR); 758f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 0); 759f1ae32a1SGerd Hoffmann } else { 760f1ae32a1SGerd Hoffmann if (ret > (ssize_t) len) { 761dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_data_overrun(ret, len); 762f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 763f1ae32a1SGerd Hoffmann OHCI_CC_DATAOVERRUN); 764f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 765f1ae32a1SGerd Hoffmann len); 766f1ae32a1SGerd Hoffmann } else if (ret >= 0) { 767dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_data_underrun(ret); 768f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 769f1ae32a1SGerd Hoffmann OHCI_CC_DATAUNDERRUN); 770f1ae32a1SGerd Hoffmann } else { 771f1ae32a1SGerd Hoffmann switch (ret) { 772f1ae32a1SGerd Hoffmann case USB_RET_IOERROR: 773f1ae32a1SGerd Hoffmann case USB_RET_NODEV: 774f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 775f1ae32a1SGerd Hoffmann OHCI_CC_DEVICENOTRESPONDING); 776f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 777f1ae32a1SGerd Hoffmann 0); 778f1ae32a1SGerd Hoffmann break; 779f1ae32a1SGerd Hoffmann case USB_RET_NAK: 780f1ae32a1SGerd Hoffmann case USB_RET_STALL: 781dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_nak(ret); 782f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 783f1ae32a1SGerd Hoffmann OHCI_CC_STALL); 784f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 785f1ae32a1SGerd Hoffmann 0); 786f1ae32a1SGerd Hoffmann break; 787f1ae32a1SGerd Hoffmann default: 788dc1f5988SAlexey Kardashevskiy trace_usb_ohci_iso_td_bad_response(ret); 789f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, 790f1ae32a1SGerd Hoffmann OHCI_CC_UNDEXPETEDPID); 791f1ae32a1SGerd Hoffmann break; 792f1ae32a1SGerd Hoffmann } 793f1ae32a1SGerd Hoffmann } 794f1ae32a1SGerd Hoffmann } 795f1ae32a1SGerd Hoffmann 796f1ae32a1SGerd Hoffmann if (relative_frame_number == frame_count) { 797f1ae32a1SGerd Hoffmann /* Last data packet of ISO TD - retire the TD to the Done Queue */ 798f1ae32a1SGerd Hoffmann OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_NOERROR); 799f1ae32a1SGerd Hoffmann ed->head &= ~OHCI_DPTR_MASK; 800f1ae32a1SGerd Hoffmann ed->head |= (iso_td.next & OHCI_DPTR_MASK); 801f1ae32a1SGerd Hoffmann iso_td.next = ohci->done; 802f1ae32a1SGerd Hoffmann ohci->done = addr; 803f1ae32a1SGerd Hoffmann i = OHCI_BM(iso_td.flags, TD_DI); 804f1ae32a1SGerd Hoffmann if (i < ohci->done_count) 805f1ae32a1SGerd Hoffmann ohci->done_count = i; 806f1ae32a1SGerd Hoffmann } 807cf66ee8eSAlexey Kardashevskiy if (ohci_put_iso_td(ohci, addr, &iso_td)) { 808cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 809cf66ee8eSAlexey Kardashevskiy } 810f1ae32a1SGerd Hoffmann return 1; 811f1ae32a1SGerd Hoffmann } 812f1ae32a1SGerd Hoffmann 81329d81e42SPhilippe Mathieu-Daudé #define HEX_CHAR_PER_LINE 16 81429d81e42SPhilippe Mathieu-Daudé 815dc1f5988SAlexey Kardashevskiy static void ohci_td_pkt(const char *msg, const uint8_t *buf, size_t len) 816dc1f5988SAlexey Kardashevskiy { 817d87aa138SStefan Hajnoczi bool print16; 818d87aa138SStefan Hajnoczi bool printall; 819dc1f5988SAlexey Kardashevskiy int i; 82029d81e42SPhilippe Mathieu-Daudé char tmp[3 * HEX_CHAR_PER_LINE + 1]; 821dc1f5988SAlexey Kardashevskiy char *p = tmp; 822dc1f5988SAlexey Kardashevskiy 823d87aa138SStefan Hajnoczi print16 = !!trace_event_get_state_backends(TRACE_USB_OHCI_TD_PKT_SHORT); 824d87aa138SStefan Hajnoczi printall = !!trace_event_get_state_backends(TRACE_USB_OHCI_TD_PKT_FULL); 825d87aa138SStefan Hajnoczi 826dc1f5988SAlexey Kardashevskiy if (!printall && !print16) { 827dc1f5988SAlexey Kardashevskiy return; 828dc1f5988SAlexey Kardashevskiy } 829dc1f5988SAlexey Kardashevskiy 830dc1f5988SAlexey Kardashevskiy for (i = 0; ; i++) { 83129d81e42SPhilippe Mathieu-Daudé if (i && (!(i % HEX_CHAR_PER_LINE) || (i == len))) { 832dc1f5988SAlexey Kardashevskiy if (!printall) { 833dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_pkt_short(msg, tmp); 834dc1f5988SAlexey Kardashevskiy break; 835dc1f5988SAlexey Kardashevskiy } 836dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_pkt_full(msg, tmp); 837dc1f5988SAlexey Kardashevskiy p = tmp; 838dc1f5988SAlexey Kardashevskiy *p = 0; 839dc1f5988SAlexey Kardashevskiy } 840dc1f5988SAlexey Kardashevskiy if (i == len) { 841dc1f5988SAlexey Kardashevskiy break; 842dc1f5988SAlexey Kardashevskiy } 843dc1f5988SAlexey Kardashevskiy 844dc1f5988SAlexey Kardashevskiy p += sprintf(p, " %.2x", buf[i]); 845dc1f5988SAlexey Kardashevskiy } 846dc1f5988SAlexey Kardashevskiy } 847dc1f5988SAlexey Kardashevskiy 848f1ae32a1SGerd Hoffmann /* Service a transport descriptor. 849f1ae32a1SGerd Hoffmann Returns nonzero to terminate processing of this endpoint. */ 850f1ae32a1SGerd Hoffmann 851f1ae32a1SGerd Hoffmann static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) 852f1ae32a1SGerd Hoffmann { 853f1ae32a1SGerd Hoffmann int dir; 854f1ae32a1SGerd Hoffmann size_t len = 0, pktlen = 0; 855f1ae32a1SGerd Hoffmann const char *str = NULL; 856f1ae32a1SGerd Hoffmann int pid; 857f1ae32a1SGerd Hoffmann int ret; 858f1ae32a1SGerd Hoffmann int i; 859f1ae32a1SGerd Hoffmann USBDevice *dev; 860f1ae32a1SGerd Hoffmann USBEndpoint *ep; 861f1ae32a1SGerd Hoffmann struct ohci_td td; 862f1ae32a1SGerd Hoffmann uint32_t addr; 863f1ae32a1SGerd Hoffmann int flag_r; 864f1ae32a1SGerd Hoffmann int completion; 865f1ae32a1SGerd Hoffmann 866f1ae32a1SGerd Hoffmann addr = ed->head & OHCI_DPTR_MASK; 867d8c2e6f2SQiang Liu if (addr == 0) { 868d8c2e6f2SQiang Liu ohci_die(ohci); 869d8c2e6f2SQiang Liu return 1; 870d8c2e6f2SQiang Liu } 871d8c2e6f2SQiang Liu 872f1ae32a1SGerd Hoffmann /* See if this TD has already been submitted to the device. */ 873f1ae32a1SGerd Hoffmann completion = (addr == ohci->async_td); 874f1ae32a1SGerd Hoffmann if (completion && !ohci->async_complete) { 875dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_skip_async(); 876f1ae32a1SGerd Hoffmann return 1; 877f1ae32a1SGerd Hoffmann } 878cf66ee8eSAlexey Kardashevskiy if (ohci_read_td(ohci, addr, &td)) { 879dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_read_error(addr); 880cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 8816ebc069dSLi Qiang return 1; 882f1ae32a1SGerd Hoffmann } 883f1ae32a1SGerd Hoffmann 884f1ae32a1SGerd Hoffmann dir = OHCI_BM(ed->flags, ED_D); 885f1ae32a1SGerd Hoffmann switch (dir) { 886f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_OUT: 887f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_IN: 888f1ae32a1SGerd Hoffmann /* Same value. */ 889f1ae32a1SGerd Hoffmann break; 890f1ae32a1SGerd Hoffmann default: 891f1ae32a1SGerd Hoffmann dir = OHCI_BM(td.flags, TD_DP); 892f1ae32a1SGerd Hoffmann break; 893f1ae32a1SGerd Hoffmann } 894f1ae32a1SGerd Hoffmann 895f1ae32a1SGerd Hoffmann switch (dir) { 896f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_IN: 897f1ae32a1SGerd Hoffmann str = "in"; 898f1ae32a1SGerd Hoffmann pid = USB_TOKEN_IN; 899f1ae32a1SGerd Hoffmann break; 900f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_OUT: 901f1ae32a1SGerd Hoffmann str = "out"; 902f1ae32a1SGerd Hoffmann pid = USB_TOKEN_OUT; 903f1ae32a1SGerd Hoffmann break; 904f1ae32a1SGerd Hoffmann case OHCI_TD_DIR_SETUP: 905f1ae32a1SGerd Hoffmann str = "setup"; 906f1ae32a1SGerd Hoffmann pid = USB_TOKEN_SETUP; 907f1ae32a1SGerd Hoffmann break; 908f1ae32a1SGerd Hoffmann default: 909dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_bad_direction(dir); 910f1ae32a1SGerd Hoffmann return 1; 911f1ae32a1SGerd Hoffmann } 912f1ae32a1SGerd Hoffmann if (td.cbp && td.be) { 913f1ae32a1SGerd Hoffmann if ((td.cbp & 0xfffff000) != (td.be & 0xfffff000)) { 914f1ae32a1SGerd Hoffmann len = (td.be & 0xfff) + 0x1001 - (td.cbp & 0xfff); 915f1ae32a1SGerd Hoffmann } else { 9161328fe0cSPrasad J Pandit if (td.cbp > td.be) { 9171328fe0cSPrasad J Pandit trace_usb_ohci_iso_td_bad_cc_overrun(td.cbp, td.be); 9181328fe0cSPrasad J Pandit ohci_die(ohci); 9191328fe0cSPrasad J Pandit return 1; 9201328fe0cSPrasad J Pandit } 921f1ae32a1SGerd Hoffmann len = (td.be - td.cbp) + 1; 922f1ae32a1SGerd Hoffmann } 9231328fe0cSPrasad J Pandit if (len > sizeof(ohci->usb_buf)) { 9241328fe0cSPrasad J Pandit len = sizeof(ohci->usb_buf); 9251328fe0cSPrasad J Pandit } 926f1ae32a1SGerd Hoffmann 927f1ae32a1SGerd Hoffmann pktlen = len; 928f1ae32a1SGerd Hoffmann if (len && dir != OHCI_TD_DIR_IN) { 929f1ae32a1SGerd Hoffmann /* The endpoint may not allow us to transfer it all now */ 930f1ae32a1SGerd Hoffmann pktlen = (ed->flags & OHCI_ED_MPS_MASK) >> OHCI_ED_MPS_SHIFT; 931f1ae32a1SGerd Hoffmann if (pktlen > len) { 932f1ae32a1SGerd Hoffmann pktlen = len; 933f1ae32a1SGerd Hoffmann } 934f1ae32a1SGerd Hoffmann if (!completion) { 935cf66ee8eSAlexey Kardashevskiy if (ohci_copy_td(ohci, &td, ohci->usb_buf, pktlen, 936cf66ee8eSAlexey Kardashevskiy DMA_DIRECTION_TO_DEVICE)) { 937cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 938cf66ee8eSAlexey Kardashevskiy } 939f1ae32a1SGerd Hoffmann } 940f1ae32a1SGerd Hoffmann } 941f1ae32a1SGerd Hoffmann } 942f1ae32a1SGerd Hoffmann 943f1ae32a1SGerd Hoffmann flag_r = (td.flags & OHCI_TD_R) != 0; 944dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_pkt_hdr(addr, (int64_t)pktlen, (int64_t)len, str, 945dc1f5988SAlexey Kardashevskiy flag_r, td.cbp, td.be); 946dc1f5988SAlexey Kardashevskiy ohci_td_pkt("OUT", ohci->usb_buf, pktlen); 947f1ae32a1SGerd Hoffmann 948f1ae32a1SGerd Hoffmann if (completion) { 949f1ae32a1SGerd Hoffmann ohci->async_td = 0; 95069e25d26SAlexey Kardashevskiy ohci->async_complete = false; 951f1ae32a1SGerd Hoffmann } else { 952f1ae32a1SGerd Hoffmann dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA)); 95342340fc3SLiam Merwick if (dev == NULL) { 95442340fc3SLiam Merwick trace_usb_ohci_td_dev_error(); 95542340fc3SLiam Merwick return 1; 95642340fc3SLiam Merwick } 957f1ae32a1SGerd Hoffmann ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN)); 9586e821e50SBALATON Zoltan if (ohci->async_td) { 9596e821e50SBALATON Zoltan /* ??? The hardware should allow one active packet per 9606e821e50SBALATON Zoltan endpoint. We only allow one active packet per controller. 9616e821e50SBALATON Zoltan This should be sufficient as long as devices respond in a 9626e821e50SBALATON Zoltan timely manner. 9636e821e50SBALATON Zoltan */ 9646e821e50SBALATON Zoltan trace_usb_ohci_td_too_many_pending(ep->nr); 9656e821e50SBALATON Zoltan return 1; 9666e821e50SBALATON Zoltan } 9678550a02dSGerd Hoffmann usb_packet_setup(&ohci->usb_packet, pid, ep, 0, addr, !flag_r, 968a6fb2ddbSHans de Goede OHCI_BM(td.flags, TD_DI) == 0); 969f1ae32a1SGerd Hoffmann usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen); 9709a77a0f5SHans de Goede usb_handle_packet(dev, &ohci->usb_packet); 971dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_packet_status(ohci->usb_packet.status); 972dc1f5988SAlexey Kardashevskiy 9739a77a0f5SHans de Goede if (ohci->usb_packet.status == USB_RET_ASYNC) { 97436dfe324SHans de Goede usb_device_flush_ep_queue(dev, ep); 975f1ae32a1SGerd Hoffmann ohci->async_td = addr; 976f1ae32a1SGerd Hoffmann return 1; 977f1ae32a1SGerd Hoffmann } 978f1ae32a1SGerd Hoffmann } 9799a77a0f5SHans de Goede if (ohci->usb_packet.status == USB_RET_SUCCESS) { 9809a77a0f5SHans de Goede ret = ohci->usb_packet.actual_length; 9819a77a0f5SHans de Goede } else { 9829a77a0f5SHans de Goede ret = ohci->usb_packet.status; 9839a77a0f5SHans de Goede } 9849a77a0f5SHans de Goede 985f1ae32a1SGerd Hoffmann if (ret >= 0) { 986f1ae32a1SGerd Hoffmann if (dir == OHCI_TD_DIR_IN) { 987cf66ee8eSAlexey Kardashevskiy if (ohci_copy_td(ohci, &td, ohci->usb_buf, ret, 988cf66ee8eSAlexey Kardashevskiy DMA_DIRECTION_FROM_DEVICE)) { 989cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 990cf66ee8eSAlexey Kardashevskiy } 991dc1f5988SAlexey Kardashevskiy ohci_td_pkt("IN", ohci->usb_buf, pktlen); 992f1ae32a1SGerd Hoffmann } else { 993f1ae32a1SGerd Hoffmann ret = pktlen; 994f1ae32a1SGerd Hoffmann } 995f1ae32a1SGerd Hoffmann } 996f1ae32a1SGerd Hoffmann 997f1ae32a1SGerd Hoffmann /* Writeback */ 998f1ae32a1SGerd Hoffmann if (ret == pktlen || (dir == OHCI_TD_DIR_IN && ret >= 0 && flag_r)) { 999f1ae32a1SGerd Hoffmann /* Transmission succeeded. */ 1000f1ae32a1SGerd Hoffmann if (ret == len) { 1001f1ae32a1SGerd Hoffmann td.cbp = 0; 1002f1ae32a1SGerd Hoffmann } else { 1003f1ae32a1SGerd Hoffmann if ((td.cbp & 0xfff) + ret > 0xfff) { 1004f1ae32a1SGerd Hoffmann td.cbp = (td.be & ~0xfff) + ((td.cbp + ret) & 0xfff); 1005f1ae32a1SGerd Hoffmann } else { 1006f1ae32a1SGerd Hoffmann td.cbp += ret; 1007f1ae32a1SGerd Hoffmann } 1008f1ae32a1SGerd Hoffmann } 1009f1ae32a1SGerd Hoffmann td.flags |= OHCI_TD_T1; 1010f1ae32a1SGerd Hoffmann td.flags ^= OHCI_TD_T0; 1011f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_NOERROR); 1012f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_EC, 0); 1013f1ae32a1SGerd Hoffmann 1014f1ae32a1SGerd Hoffmann if ((dir != OHCI_TD_DIR_IN) && (ret != len)) { 1015f1ae32a1SGerd Hoffmann /* Partial packet transfer: TD not ready to retire yet */ 1016f1ae32a1SGerd Hoffmann goto exit_no_retire; 1017f1ae32a1SGerd Hoffmann } 1018f1ae32a1SGerd Hoffmann 1019f1ae32a1SGerd Hoffmann /* Setting ED_C is part of the TD retirement process */ 1020f1ae32a1SGerd Hoffmann ed->head &= ~OHCI_ED_C; 1021f1ae32a1SGerd Hoffmann if (td.flags & OHCI_TD_T0) 1022f1ae32a1SGerd Hoffmann ed->head |= OHCI_ED_C; 1023f1ae32a1SGerd Hoffmann } else { 1024f1ae32a1SGerd Hoffmann if (ret >= 0) { 1025dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_underrun(); 1026f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAUNDERRUN); 1027f1ae32a1SGerd Hoffmann } else { 1028f1ae32a1SGerd Hoffmann switch (ret) { 1029f1ae32a1SGerd Hoffmann case USB_RET_IOERROR: 1030f1ae32a1SGerd Hoffmann case USB_RET_NODEV: 1031dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_dev_error(); 1032f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DEVICENOTRESPONDING); 10334b351a0fSJán Veselý break; 1034f1ae32a1SGerd Hoffmann case USB_RET_NAK: 1035dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_nak(); 1036f1ae32a1SGerd Hoffmann return 1; 1037f1ae32a1SGerd Hoffmann case USB_RET_STALL: 1038dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_stall(); 1039f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_STALL); 1040f1ae32a1SGerd Hoffmann break; 1041f1ae32a1SGerd Hoffmann case USB_RET_BABBLE: 1042dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_babble(); 1043f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAOVERRUN); 1044f1ae32a1SGerd Hoffmann break; 1045f1ae32a1SGerd Hoffmann default: 1046dc1f5988SAlexey Kardashevskiy trace_usb_ohci_td_bad_device_response(ret); 1047f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_UNDEXPETEDPID); 1048f1ae32a1SGerd Hoffmann OHCI_SET_BM(td.flags, TD_EC, 3); 1049f1ae32a1SGerd Hoffmann break; 1050f1ae32a1SGerd Hoffmann } 1051cba42d61SMichael Tokarev /* An error occurred so we have to clear the interrupt counter. See 10527c48b95dSSebastian Bauer * spec at 6.4.4 on page 104 */ 10537c48b95dSSebastian Bauer ohci->done_count = 0; 1054f1ae32a1SGerd Hoffmann } 1055f1ae32a1SGerd Hoffmann ed->head |= OHCI_ED_H; 1056f1ae32a1SGerd Hoffmann } 1057f1ae32a1SGerd Hoffmann 1058f1ae32a1SGerd Hoffmann /* Retire this TD */ 1059f1ae32a1SGerd Hoffmann ed->head &= ~OHCI_DPTR_MASK; 1060f1ae32a1SGerd Hoffmann ed->head |= td.next & OHCI_DPTR_MASK; 1061f1ae32a1SGerd Hoffmann td.next = ohci->done; 1062f1ae32a1SGerd Hoffmann ohci->done = addr; 1063f1ae32a1SGerd Hoffmann i = OHCI_BM(td.flags, TD_DI); 1064f1ae32a1SGerd Hoffmann if (i < ohci->done_count) 1065f1ae32a1SGerd Hoffmann ohci->done_count = i; 1066f1ae32a1SGerd Hoffmann exit_no_retire: 1067cf66ee8eSAlexey Kardashevskiy if (ohci_put_td(ohci, addr, &td)) { 1068cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 1069cf66ee8eSAlexey Kardashevskiy return 1; 1070cf66ee8eSAlexey Kardashevskiy } 1071f1ae32a1SGerd Hoffmann return OHCI_BM(td.flags, TD_CC) != OHCI_CC_NOERROR; 1072f1ae32a1SGerd Hoffmann } 1073f1ae32a1SGerd Hoffmann 1074f1ae32a1SGerd Hoffmann /* Service an endpoint list. Returns nonzero if active TD were found. */ 10753a4d06f2SBALATON Zoltan static int ohci_service_ed_list(OHCIState *ohci, uint32_t head) 1076f1ae32a1SGerd Hoffmann { 1077f1ae32a1SGerd Hoffmann struct ohci_ed ed; 1078f1ae32a1SGerd Hoffmann uint32_t next_ed; 1079f1ae32a1SGerd Hoffmann uint32_t cur; 1080f1ae32a1SGerd Hoffmann int active; 108195ed5693SLi Qiang uint32_t link_cnt = 0; 1082f1ae32a1SGerd Hoffmann active = 0; 1083f1ae32a1SGerd Hoffmann 1084f1ae32a1SGerd Hoffmann if (head == 0) 1085f1ae32a1SGerd Hoffmann return 0; 1086f1ae32a1SGerd Hoffmann 1087ab878998SLaurent Vivier for (cur = head; cur && link_cnt++ < ED_LINK_LIMIT; cur = next_ed) { 1088cf66ee8eSAlexey Kardashevskiy if (ohci_read_ed(ohci, cur, &ed)) { 1089dc1f5988SAlexey Kardashevskiy trace_usb_ohci_ed_read_error(cur); 1090cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 1091f1ae32a1SGerd Hoffmann return 0; 1092f1ae32a1SGerd Hoffmann } 1093f1ae32a1SGerd Hoffmann 1094f1ae32a1SGerd Hoffmann next_ed = ed.next & OHCI_DPTR_MASK; 1095f1ae32a1SGerd Hoffmann 1096f1ae32a1SGerd Hoffmann if ((ed.head & OHCI_ED_H) || (ed.flags & OHCI_ED_K)) { 1097f1ae32a1SGerd Hoffmann uint32_t addr; 1098f1ae32a1SGerd Hoffmann /* Cancel pending packets for ED that have been paused. */ 1099f1ae32a1SGerd Hoffmann addr = ed.head & OHCI_DPTR_MASK; 1100f1ae32a1SGerd Hoffmann if (ohci->async_td && addr == ohci->async_td) { 1101f1ae32a1SGerd Hoffmann usb_cancel_packet(&ohci->usb_packet); 1102f1ae32a1SGerd Hoffmann ohci->async_td = 0; 1103f79738b0SHans de Goede usb_device_ep_stopped(ohci->usb_packet.ep->dev, 1104f79738b0SHans de Goede ohci->usb_packet.ep); 1105f1ae32a1SGerd Hoffmann } 1106f1ae32a1SGerd Hoffmann continue; 1107f1ae32a1SGerd Hoffmann } 1108f1ae32a1SGerd Hoffmann 1109f1ae32a1SGerd Hoffmann while ((ed.head & OHCI_DPTR_MASK) != ed.tail) { 11103af8f177SAlexey Kardashevskiy trace_usb_ohci_ed_pkt(cur, (ed.head & OHCI_ED_H) != 0, 11113af8f177SAlexey Kardashevskiy (ed.head & OHCI_ED_C) != 0, ed.head & OHCI_DPTR_MASK, 11123af8f177SAlexey Kardashevskiy ed.tail & OHCI_DPTR_MASK, ed.next & OHCI_DPTR_MASK); 11133af8f177SAlexey Kardashevskiy trace_usb_ohci_ed_pkt_flags( 1114f1ae32a1SGerd Hoffmann OHCI_BM(ed.flags, ED_FA), OHCI_BM(ed.flags, ED_EN), 1115f1ae32a1SGerd Hoffmann OHCI_BM(ed.flags, ED_D), (ed.flags & OHCI_ED_S)!= 0, 1116f1ae32a1SGerd Hoffmann (ed.flags & OHCI_ED_K) != 0, (ed.flags & OHCI_ED_F) != 0, 11173af8f177SAlexey Kardashevskiy OHCI_BM(ed.flags, ED_MPS)); 1118dc1f5988SAlexey Kardashevskiy 1119f1ae32a1SGerd Hoffmann active = 1; 1120f1ae32a1SGerd Hoffmann 1121f1ae32a1SGerd Hoffmann if ((ed.flags & OHCI_ED_F) == 0) { 1122f1ae32a1SGerd Hoffmann if (ohci_service_td(ohci, &ed)) 1123f1ae32a1SGerd Hoffmann break; 1124f1ae32a1SGerd Hoffmann } else { 1125f1ae32a1SGerd Hoffmann /* Handle isochronous endpoints */ 11263a4d06f2SBALATON Zoltan if (ohci_service_iso_td(ohci, &ed)) { 1127f1ae32a1SGerd Hoffmann break; 1128f1ae32a1SGerd Hoffmann } 1129f1ae32a1SGerd Hoffmann } 11303a4d06f2SBALATON Zoltan } 1131f1ae32a1SGerd Hoffmann 1132cf66ee8eSAlexey Kardashevskiy if (ohci_put_ed(ohci, cur, &ed)) { 1133cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 1134cf66ee8eSAlexey Kardashevskiy return 0; 1135cf66ee8eSAlexey Kardashevskiy } 1136f1ae32a1SGerd Hoffmann } 1137f1ae32a1SGerd Hoffmann 1138f1ae32a1SGerd Hoffmann return active; 1139f1ae32a1SGerd Hoffmann } 1140f1ae32a1SGerd Hoffmann 1141fd0a10cdSLaurent Vivier /* set a timer for EOF */ 1142fd0a10cdSLaurent Vivier static void ohci_eof_timer(OHCIState *ohci) 1143f1ae32a1SGerd Hoffmann { 1144bc72ad67SAlex Bligh timer_mod(ohci->eof_timer, ohci->sof_time + usb_frame_time); 1145fd0a10cdSLaurent Vivier } 1146fd0a10cdSLaurent Vivier /* Set a timer for EOF and generate a SOF event */ 1147fd0a10cdSLaurent Vivier static void ohci_sof(OHCIState *ohci) 1148fd0a10cdSLaurent Vivier { 1149a60f39a4SMiguel GAIO ohci->sof_time += usb_frame_time; 1150fd0a10cdSLaurent Vivier ohci_eof_timer(ohci); 1151f1ae32a1SGerd Hoffmann ohci_set_interrupt(ohci, OHCI_INTR_SF); 1152f1ae32a1SGerd Hoffmann } 1153f1ae32a1SGerd Hoffmann 1154f1ae32a1SGerd Hoffmann /* Process Control and Bulk lists. */ 11553a4d06f2SBALATON Zoltan static void ohci_process_lists(OHCIState *ohci) 1156f1ae32a1SGerd Hoffmann { 1157f1ae32a1SGerd Hoffmann if ((ohci->ctl & OHCI_CTL_CLE) && (ohci->status & OHCI_STATUS_CLF)) { 1158f1ae32a1SGerd Hoffmann if (ohci->ctrl_cur && ohci->ctrl_cur != ohci->ctrl_head) { 1159dc1f5988SAlexey Kardashevskiy trace_usb_ohci_process_lists(ohci->ctrl_head, ohci->ctrl_cur); 1160f1ae32a1SGerd Hoffmann } 11613a4d06f2SBALATON Zoltan if (!ohci_service_ed_list(ohci, ohci->ctrl_head)) { 1162f1ae32a1SGerd Hoffmann ohci->ctrl_cur = 0; 1163f1ae32a1SGerd Hoffmann ohci->status &= ~OHCI_STATUS_CLF; 1164f1ae32a1SGerd Hoffmann } 1165f1ae32a1SGerd Hoffmann } 1166f1ae32a1SGerd Hoffmann 1167f1ae32a1SGerd Hoffmann if ((ohci->ctl & OHCI_CTL_BLE) && (ohci->status & OHCI_STATUS_BLF)) { 11683a4d06f2SBALATON Zoltan if (!ohci_service_ed_list(ohci, ohci->bulk_head)) { 1169f1ae32a1SGerd Hoffmann ohci->bulk_cur = 0; 1170f1ae32a1SGerd Hoffmann ohci->status &= ~OHCI_STATUS_BLF; 1171f1ae32a1SGerd Hoffmann } 1172f1ae32a1SGerd Hoffmann } 1173f1ae32a1SGerd Hoffmann } 1174f1ae32a1SGerd Hoffmann 1175f1ae32a1SGerd Hoffmann /* Do frame processing on frame boundary */ 1176f1ae32a1SGerd Hoffmann static void ohci_frame_boundary(void *opaque) 1177f1ae32a1SGerd Hoffmann { 1178f1ae32a1SGerd Hoffmann OHCIState *ohci = opaque; 1179f1ae32a1SGerd Hoffmann struct ohci_hcca hcca; 1180f1ae32a1SGerd Hoffmann 1181cf66ee8eSAlexey Kardashevskiy if (ohci_read_hcca(ohci, ohci->hcca, &hcca)) { 1182dc1f5988SAlexey Kardashevskiy trace_usb_ohci_hcca_read_error(ohci->hcca); 1183cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 1184cf66ee8eSAlexey Kardashevskiy return; 1185cf66ee8eSAlexey Kardashevskiy } 1186f1ae32a1SGerd Hoffmann 1187f1ae32a1SGerd Hoffmann /* Process all the lists at the end of the frame */ 1188f1ae32a1SGerd Hoffmann if (ohci->ctl & OHCI_CTL_PLE) { 1189f1ae32a1SGerd Hoffmann int n; 1190f1ae32a1SGerd Hoffmann 1191f1ae32a1SGerd Hoffmann n = ohci->frame_number & 0x1f; 11923a4d06f2SBALATON Zoltan ohci_service_ed_list(ohci, le32_to_cpu(hcca.intr[n])); 1193f1ae32a1SGerd Hoffmann } 1194f1ae32a1SGerd Hoffmann 1195f1ae32a1SGerd Hoffmann /* Cancel all pending packets if either of the lists has been disabled. */ 1196f79738b0SHans de Goede if (ohci->old_ctl & (~ohci->ctl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) { 1197f79738b0SHans de Goede ohci_stop_endpoints(ohci); 1198f79738b0SHans de Goede } 1199f1ae32a1SGerd Hoffmann ohci->old_ctl = ohci->ctl; 12003a4d06f2SBALATON Zoltan ohci_process_lists(ohci); 1201f1ae32a1SGerd Hoffmann 1202cf66ee8eSAlexey Kardashevskiy /* Stop if UnrecoverableError happened or ohci_sof will crash */ 1203cf66ee8eSAlexey Kardashevskiy if (ohci->intr_status & OHCI_INTR_UE) { 1204cf66ee8eSAlexey Kardashevskiy return; 1205cf66ee8eSAlexey Kardashevskiy } 1206cf66ee8eSAlexey Kardashevskiy 1207f1ae32a1SGerd Hoffmann /* Frame boundary, so do EOF stuf here */ 1208f1ae32a1SGerd Hoffmann ohci->frt = ohci->fit; 1209f1ae32a1SGerd Hoffmann 1210f1ae32a1SGerd Hoffmann /* Increment frame number and take care of endianness. */ 1211f1ae32a1SGerd Hoffmann ohci->frame_number = (ohci->frame_number + 1) & 0xffff; 1212f1ae32a1SGerd Hoffmann hcca.frame = cpu_to_le16(ohci->frame_number); 1213f1ae32a1SGerd Hoffmann 1214f1ae32a1SGerd Hoffmann if (ohci->done_count == 0 && !(ohci->intr_status & OHCI_INTR_WD)) { 1215f1ae32a1SGerd Hoffmann if (!ohci->done) 1216f1ae32a1SGerd Hoffmann abort(); 1217f1ae32a1SGerd Hoffmann if (ohci->intr & ohci->intr_status) 1218f1ae32a1SGerd Hoffmann ohci->done |= 1; 1219f1ae32a1SGerd Hoffmann hcca.done = cpu_to_le32(ohci->done); 1220f1ae32a1SGerd Hoffmann ohci->done = 0; 1221f1ae32a1SGerd Hoffmann ohci->done_count = 7; 1222f1ae32a1SGerd Hoffmann ohci_set_interrupt(ohci, OHCI_INTR_WD); 1223f1ae32a1SGerd Hoffmann } 1224f1ae32a1SGerd Hoffmann 1225f1ae32a1SGerd Hoffmann if (ohci->done_count != 7 && ohci->done_count != 0) 1226f1ae32a1SGerd Hoffmann ohci->done_count--; 1227f1ae32a1SGerd Hoffmann 1228f1ae32a1SGerd Hoffmann /* Do SOF stuff here */ 1229f1ae32a1SGerd Hoffmann ohci_sof(ohci); 1230f1ae32a1SGerd Hoffmann 1231f1ae32a1SGerd Hoffmann /* Writeback HCCA */ 1232cf66ee8eSAlexey Kardashevskiy if (ohci_put_hcca(ohci, ohci->hcca, &hcca)) { 1233cf66ee8eSAlexey Kardashevskiy ohci_die(ohci); 1234cf66ee8eSAlexey Kardashevskiy } 1235f1ae32a1SGerd Hoffmann } 1236f1ae32a1SGerd Hoffmann 1237f1ae32a1SGerd Hoffmann /* Start sending SOF tokens across the USB bus, lists are processed in 1238f1ae32a1SGerd Hoffmann * next frame 1239f1ae32a1SGerd Hoffmann */ 1240f1ae32a1SGerd Hoffmann static int ohci_bus_start(OHCIState *ohci) 1241f1ae32a1SGerd Hoffmann { 1242dc1f5988SAlexey Kardashevskiy trace_usb_ohci_start(ohci->name); 1243f1ae32a1SGerd Hoffmann 1244fd0a10cdSLaurent Vivier /* Delay the first SOF event by one frame time as 1245fd0a10cdSLaurent Vivier * linux driver is not ready to receive it and 1246fd0a10cdSLaurent Vivier * can meet some race conditions 1247fd0a10cdSLaurent Vivier */ 1248fd0a10cdSLaurent Vivier 1249a60f39a4SMiguel GAIO ohci->sof_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 1250fd0a10cdSLaurent Vivier ohci_eof_timer(ohci); 1251f1ae32a1SGerd Hoffmann 1252f1ae32a1SGerd Hoffmann return 1; 1253f1ae32a1SGerd Hoffmann } 1254f1ae32a1SGerd Hoffmann 1255f1ae32a1SGerd Hoffmann /* Stop sending SOF tokens on the bus */ 125634d97308SThomas Huth void ohci_bus_stop(OHCIState *ohci) 1257f1ae32a1SGerd Hoffmann { 1258dc1f5988SAlexey Kardashevskiy trace_usb_ohci_stop(ohci->name); 1259bc72ad67SAlex Bligh timer_del(ohci->eof_timer); 1260f1ae32a1SGerd Hoffmann } 1261f1ae32a1SGerd Hoffmann 1262f1ae32a1SGerd Hoffmann /* Sets a flag in a port status register but only set it if the port is 1263f1ae32a1SGerd Hoffmann * connected, if not set ConnectStatusChange flag. If flag is enabled 1264f1ae32a1SGerd Hoffmann * return 1. 1265f1ae32a1SGerd Hoffmann */ 1266f1ae32a1SGerd Hoffmann static int ohci_port_set_if_connected(OHCIState *ohci, int i, uint32_t val) 1267f1ae32a1SGerd Hoffmann { 1268f1ae32a1SGerd Hoffmann int ret = 1; 1269f1ae32a1SGerd Hoffmann 1270f1ae32a1SGerd Hoffmann /* writing a 0 has no effect */ 1271f1ae32a1SGerd Hoffmann if (val == 0) 1272f1ae32a1SGerd Hoffmann return 0; 1273f1ae32a1SGerd Hoffmann 1274f1ae32a1SGerd Hoffmann /* If CurrentConnectStatus is cleared we set 1275f1ae32a1SGerd Hoffmann * ConnectStatusChange 1276f1ae32a1SGerd Hoffmann */ 1277f1ae32a1SGerd Hoffmann if (!(ohci->rhport[i].ctrl & OHCI_PORT_CCS)) { 1278f1ae32a1SGerd Hoffmann ohci->rhport[i].ctrl |= OHCI_PORT_CSC; 1279f1ae32a1SGerd Hoffmann if (ohci->rhstatus & OHCI_RHS_DRWE) { 1280f1ae32a1SGerd Hoffmann /* TODO: CSC is a wakeup event */ 1281f1ae32a1SGerd Hoffmann } 1282f1ae32a1SGerd Hoffmann return 0; 1283f1ae32a1SGerd Hoffmann } 1284f1ae32a1SGerd Hoffmann 1285f1ae32a1SGerd Hoffmann if (ohci->rhport[i].ctrl & val) 1286f1ae32a1SGerd Hoffmann ret = 0; 1287f1ae32a1SGerd Hoffmann 1288f1ae32a1SGerd Hoffmann /* set the bit */ 1289f1ae32a1SGerd Hoffmann ohci->rhport[i].ctrl |= val; 1290f1ae32a1SGerd Hoffmann 1291f1ae32a1SGerd Hoffmann return ret; 1292f1ae32a1SGerd Hoffmann } 1293f1ae32a1SGerd Hoffmann 1294f1ae32a1SGerd Hoffmann /* Set the frame interval - frame interval toggle is manipulated by the hcd only */ 1295f1ae32a1SGerd Hoffmann static void ohci_set_frame_interval(OHCIState *ohci, uint16_t val) 1296f1ae32a1SGerd Hoffmann { 1297f1ae32a1SGerd Hoffmann val &= OHCI_FMI_FI; 1298f1ae32a1SGerd Hoffmann 1299f1ae32a1SGerd Hoffmann if (val != ohci->fi) { 1300dc1f5988SAlexey Kardashevskiy trace_usb_ohci_set_frame_interval(ohci->name, ohci->fi, ohci->fi); 1301f1ae32a1SGerd Hoffmann } 1302f1ae32a1SGerd Hoffmann 1303f1ae32a1SGerd Hoffmann ohci->fi = val; 1304f1ae32a1SGerd Hoffmann } 1305f1ae32a1SGerd Hoffmann 1306f1ae32a1SGerd Hoffmann static void ohci_port_power(OHCIState *ohci, int i, int p) 1307f1ae32a1SGerd Hoffmann { 1308f1ae32a1SGerd Hoffmann if (p) { 1309f1ae32a1SGerd Hoffmann ohci->rhport[i].ctrl |= OHCI_PORT_PPS; 1310f1ae32a1SGerd Hoffmann } else { 1311f1ae32a1SGerd Hoffmann ohci->rhport[i].ctrl &= ~(OHCI_PORT_PPS| 1312f1ae32a1SGerd Hoffmann OHCI_PORT_CCS| 1313f1ae32a1SGerd Hoffmann OHCI_PORT_PSS| 1314f1ae32a1SGerd Hoffmann OHCI_PORT_PRS); 1315f1ae32a1SGerd Hoffmann } 1316f1ae32a1SGerd Hoffmann } 1317f1ae32a1SGerd Hoffmann 1318f1ae32a1SGerd Hoffmann /* Set HcControlRegister */ 1319f1ae32a1SGerd Hoffmann static void ohci_set_ctl(OHCIState *ohci, uint32_t val) 1320f1ae32a1SGerd Hoffmann { 1321f1ae32a1SGerd Hoffmann uint32_t old_state; 1322f1ae32a1SGerd Hoffmann uint32_t new_state; 1323f1ae32a1SGerd Hoffmann 1324f1ae32a1SGerd Hoffmann old_state = ohci->ctl & OHCI_CTL_HCFS; 1325f1ae32a1SGerd Hoffmann ohci->ctl = val; 1326f1ae32a1SGerd Hoffmann new_state = ohci->ctl & OHCI_CTL_HCFS; 1327f1ae32a1SGerd Hoffmann 1328f1ae32a1SGerd Hoffmann /* no state change */ 1329f1ae32a1SGerd Hoffmann if (old_state == new_state) 1330f1ae32a1SGerd Hoffmann return; 1331f1ae32a1SGerd Hoffmann 1332dc1f5988SAlexey Kardashevskiy trace_usb_ohci_set_ctl(ohci->name, new_state); 1333f1ae32a1SGerd Hoffmann switch (new_state) { 1334f1ae32a1SGerd Hoffmann case OHCI_USB_OPERATIONAL: 1335f1ae32a1SGerd Hoffmann ohci_bus_start(ohci); 1336f1ae32a1SGerd Hoffmann break; 1337f1ae32a1SGerd Hoffmann case OHCI_USB_SUSPEND: 1338f1ae32a1SGerd Hoffmann ohci_bus_stop(ohci); 1339087462c7SLaurent Vivier /* clear pending SF otherwise linux driver loops in ohci_irq() */ 1340087462c7SLaurent Vivier ohci->intr_status &= ~OHCI_INTR_SF; 1341087462c7SLaurent Vivier ohci_intr_update(ohci); 1342f1ae32a1SGerd Hoffmann break; 1343f1ae32a1SGerd Hoffmann case OHCI_USB_RESUME: 1344dc1f5988SAlexey Kardashevskiy trace_usb_ohci_resume(ohci->name); 1345f1ae32a1SGerd Hoffmann break; 1346f1ae32a1SGerd Hoffmann case OHCI_USB_RESET: 13477d938fd1SHervé Poussineau ohci_roothub_reset(ohci); 1348f1ae32a1SGerd Hoffmann break; 1349f1ae32a1SGerd Hoffmann } 1350f1ae32a1SGerd Hoffmann } 1351f1ae32a1SGerd Hoffmann 1352f1ae32a1SGerd Hoffmann static uint32_t ohci_get_frame_remaining(OHCIState *ohci) 1353f1ae32a1SGerd Hoffmann { 1354f1ae32a1SGerd Hoffmann uint16_t fr; 1355f1ae32a1SGerd Hoffmann int64_t tks; 1356f1ae32a1SGerd Hoffmann 1357f1ae32a1SGerd Hoffmann if ((ohci->ctl & OHCI_CTL_HCFS) != OHCI_USB_OPERATIONAL) 1358f1ae32a1SGerd Hoffmann return (ohci->frt << 31); 1359f1ae32a1SGerd Hoffmann 1360f1ae32a1SGerd Hoffmann /* Being in USB operational state guarnatees sof_time was 1361f1ae32a1SGerd Hoffmann * set already. 1362f1ae32a1SGerd Hoffmann */ 1363bc72ad67SAlex Bligh tks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - ohci->sof_time; 1364a60f39a4SMiguel GAIO if (tks < 0) { 1365a60f39a4SMiguel GAIO tks = 0; 1366a60f39a4SMiguel GAIO } 1367f1ae32a1SGerd Hoffmann 1368f1ae32a1SGerd Hoffmann /* avoid muldiv if possible */ 1369f1ae32a1SGerd Hoffmann if (tks >= usb_frame_time) 1370f1ae32a1SGerd Hoffmann return (ohci->frt << 31); 1371f1ae32a1SGerd Hoffmann 1372cd1f16f9SLaurent Vivier tks = tks / usb_bit_time; 1373f1ae32a1SGerd Hoffmann fr = (uint16_t)(ohci->fi - tks); 1374f1ae32a1SGerd Hoffmann 1375f1ae32a1SGerd Hoffmann return (ohci->frt << 31) | fr; 1376f1ae32a1SGerd Hoffmann } 1377f1ae32a1SGerd Hoffmann 1378f1ae32a1SGerd Hoffmann 1379f1ae32a1SGerd Hoffmann /* Set root hub status */ 1380f1ae32a1SGerd Hoffmann static void ohci_set_hub_status(OHCIState *ohci, uint32_t val) 1381f1ae32a1SGerd Hoffmann { 1382f1ae32a1SGerd Hoffmann uint32_t old_state; 1383f1ae32a1SGerd Hoffmann 1384f1ae32a1SGerd Hoffmann old_state = ohci->rhstatus; 1385f1ae32a1SGerd Hoffmann 1386f1ae32a1SGerd Hoffmann /* write 1 to clear OCIC */ 1387f1ae32a1SGerd Hoffmann if (val & OHCI_RHS_OCIC) 1388f1ae32a1SGerd Hoffmann ohci->rhstatus &= ~OHCI_RHS_OCIC; 1389f1ae32a1SGerd Hoffmann 1390f1ae32a1SGerd Hoffmann if (val & OHCI_RHS_LPS) { 1391f1ae32a1SGerd Hoffmann int i; 1392f1ae32a1SGerd Hoffmann 1393f1ae32a1SGerd Hoffmann for (i = 0; i < ohci->num_ports; i++) 1394f1ae32a1SGerd Hoffmann ohci_port_power(ohci, i, 0); 1395dc1f5988SAlexey Kardashevskiy trace_usb_ohci_hub_power_down(); 1396f1ae32a1SGerd Hoffmann } 1397f1ae32a1SGerd Hoffmann 1398f1ae32a1SGerd Hoffmann if (val & OHCI_RHS_LPSC) { 1399f1ae32a1SGerd Hoffmann int i; 1400f1ae32a1SGerd Hoffmann 1401f1ae32a1SGerd Hoffmann for (i = 0; i < ohci->num_ports; i++) 1402f1ae32a1SGerd Hoffmann ohci_port_power(ohci, i, 1); 1403dc1f5988SAlexey Kardashevskiy trace_usb_ohci_hub_power_up(); 1404f1ae32a1SGerd Hoffmann } 1405f1ae32a1SGerd Hoffmann 1406f1ae32a1SGerd Hoffmann if (val & OHCI_RHS_DRWE) 1407f1ae32a1SGerd Hoffmann ohci->rhstatus |= OHCI_RHS_DRWE; 1408f1ae32a1SGerd Hoffmann 1409f1ae32a1SGerd Hoffmann if (val & OHCI_RHS_CRWE) 1410f1ae32a1SGerd Hoffmann ohci->rhstatus &= ~OHCI_RHS_DRWE; 1411f1ae32a1SGerd Hoffmann 1412f1ae32a1SGerd Hoffmann if (old_state != ohci->rhstatus) 1413f1ae32a1SGerd Hoffmann ohci_set_interrupt(ohci, OHCI_INTR_RHSC); 1414f1ae32a1SGerd Hoffmann } 1415f1ae32a1SGerd Hoffmann 1416f1ae32a1SGerd Hoffmann /* Set root hub port status */ 1417f1ae32a1SGerd Hoffmann static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val) 1418f1ae32a1SGerd Hoffmann { 1419f1ae32a1SGerd Hoffmann uint32_t old_state; 1420f1ae32a1SGerd Hoffmann OHCIPort *port; 1421f1ae32a1SGerd Hoffmann 1422f1ae32a1SGerd Hoffmann port = &ohci->rhport[portnum]; 1423f1ae32a1SGerd Hoffmann old_state = port->ctrl; 1424f1ae32a1SGerd Hoffmann 1425f1ae32a1SGerd Hoffmann /* Write to clear CSC, PESC, PSSC, OCIC, PRSC */ 1426f1ae32a1SGerd Hoffmann if (val & OHCI_PORT_WTC) 1427f1ae32a1SGerd Hoffmann port->ctrl &= ~(val & OHCI_PORT_WTC); 1428f1ae32a1SGerd Hoffmann 1429f1ae32a1SGerd Hoffmann if (val & OHCI_PORT_CCS) 1430f1ae32a1SGerd Hoffmann port->ctrl &= ~OHCI_PORT_PES; 1431f1ae32a1SGerd Hoffmann 1432f1ae32a1SGerd Hoffmann ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PES); 1433f1ae32a1SGerd Hoffmann 1434f1ae32a1SGerd Hoffmann if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PSS)) { 1435dc1f5988SAlexey Kardashevskiy trace_usb_ohci_port_suspend(portnum); 1436f1ae32a1SGerd Hoffmann } 1437f1ae32a1SGerd Hoffmann 1438f1ae32a1SGerd Hoffmann if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PRS)) { 1439dc1f5988SAlexey Kardashevskiy trace_usb_ohci_port_reset(portnum); 1440f1ae32a1SGerd Hoffmann usb_device_reset(port->port.dev); 1441f1ae32a1SGerd Hoffmann port->ctrl &= ~OHCI_PORT_PRS; 1442f1ae32a1SGerd Hoffmann /* ??? Should this also set OHCI_PORT_PESC. */ 1443f1ae32a1SGerd Hoffmann port->ctrl |= OHCI_PORT_PES | OHCI_PORT_PRSC; 1444f1ae32a1SGerd Hoffmann } 1445f1ae32a1SGerd Hoffmann 1446f1ae32a1SGerd Hoffmann /* Invert order here to ensure in ambiguous case, device is 1447f1ae32a1SGerd Hoffmann * powered up... 1448f1ae32a1SGerd Hoffmann */ 1449f1ae32a1SGerd Hoffmann if (val & OHCI_PORT_LSDA) 1450f1ae32a1SGerd Hoffmann ohci_port_power(ohci, portnum, 0); 1451f1ae32a1SGerd Hoffmann if (val & OHCI_PORT_PPS) 1452f1ae32a1SGerd Hoffmann ohci_port_power(ohci, portnum, 1); 1453f1ae32a1SGerd Hoffmann 1454f1ae32a1SGerd Hoffmann if (old_state != port->ctrl) 1455f1ae32a1SGerd Hoffmann ohci_set_interrupt(ohci, OHCI_INTR_RHSC); 1456f1ae32a1SGerd Hoffmann } 1457f1ae32a1SGerd Hoffmann 1458f1ae32a1SGerd Hoffmann static uint64_t ohci_mem_read(void *opaque, 1459a8170e5eSAvi Kivity hwaddr addr, 1460f1ae32a1SGerd Hoffmann unsigned size) 1461f1ae32a1SGerd Hoffmann { 1462f1ae32a1SGerd Hoffmann OHCIState *ohci = opaque; 1463f1ae32a1SGerd Hoffmann uint32_t retval; 1464f1ae32a1SGerd Hoffmann 1465f1ae32a1SGerd Hoffmann /* Only aligned reads are allowed on OHCI */ 1466f1ae32a1SGerd Hoffmann if (addr & 3) { 1467dc1f5988SAlexey Kardashevskiy trace_usb_ohci_mem_read_unaligned(addr); 1468f1ae32a1SGerd Hoffmann return 0xffffffff; 1469f1ae32a1SGerd Hoffmann } else if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) { 1470f1ae32a1SGerd Hoffmann /* HcRhPortStatus */ 1471f1ae32a1SGerd Hoffmann retval = ohci->rhport[(addr - 0x54) >> 2].ctrl | OHCI_PORT_PPS; 1472f1ae32a1SGerd Hoffmann } else { 1473f1ae32a1SGerd Hoffmann switch (addr >> 2) { 1474f1ae32a1SGerd Hoffmann case 0: /* HcRevision */ 1475f1ae32a1SGerd Hoffmann retval = 0x10; 1476f1ae32a1SGerd Hoffmann break; 1477f1ae32a1SGerd Hoffmann 1478f1ae32a1SGerd Hoffmann case 1: /* HcControl */ 1479f1ae32a1SGerd Hoffmann retval = ohci->ctl; 1480f1ae32a1SGerd Hoffmann break; 1481f1ae32a1SGerd Hoffmann 1482f1ae32a1SGerd Hoffmann case 2: /* HcCommandStatus */ 1483f1ae32a1SGerd Hoffmann retval = ohci->status; 1484f1ae32a1SGerd Hoffmann break; 1485f1ae32a1SGerd Hoffmann 1486f1ae32a1SGerd Hoffmann case 3: /* HcInterruptStatus */ 1487f1ae32a1SGerd Hoffmann retval = ohci->intr_status; 1488f1ae32a1SGerd Hoffmann break; 1489f1ae32a1SGerd Hoffmann 1490f1ae32a1SGerd Hoffmann case 4: /* HcInterruptEnable */ 1491f1ae32a1SGerd Hoffmann case 5: /* HcInterruptDisable */ 1492f1ae32a1SGerd Hoffmann retval = ohci->intr; 1493f1ae32a1SGerd Hoffmann break; 1494f1ae32a1SGerd Hoffmann 1495f1ae32a1SGerd Hoffmann case 6: /* HcHCCA */ 1496f1ae32a1SGerd Hoffmann retval = ohci->hcca; 1497f1ae32a1SGerd Hoffmann break; 1498f1ae32a1SGerd Hoffmann 1499f1ae32a1SGerd Hoffmann case 7: /* HcPeriodCurrentED */ 1500f1ae32a1SGerd Hoffmann retval = ohci->per_cur; 1501f1ae32a1SGerd Hoffmann break; 1502f1ae32a1SGerd Hoffmann 1503f1ae32a1SGerd Hoffmann case 8: /* HcControlHeadED */ 1504f1ae32a1SGerd Hoffmann retval = ohci->ctrl_head; 1505f1ae32a1SGerd Hoffmann break; 1506f1ae32a1SGerd Hoffmann 1507f1ae32a1SGerd Hoffmann case 9: /* HcControlCurrentED */ 1508f1ae32a1SGerd Hoffmann retval = ohci->ctrl_cur; 1509f1ae32a1SGerd Hoffmann break; 1510f1ae32a1SGerd Hoffmann 1511f1ae32a1SGerd Hoffmann case 10: /* HcBulkHeadED */ 1512f1ae32a1SGerd Hoffmann retval = ohci->bulk_head; 1513f1ae32a1SGerd Hoffmann break; 1514f1ae32a1SGerd Hoffmann 1515f1ae32a1SGerd Hoffmann case 11: /* HcBulkCurrentED */ 1516f1ae32a1SGerd Hoffmann retval = ohci->bulk_cur; 1517f1ae32a1SGerd Hoffmann break; 1518f1ae32a1SGerd Hoffmann 1519f1ae32a1SGerd Hoffmann case 12: /* HcDoneHead */ 1520f1ae32a1SGerd Hoffmann retval = ohci->done; 1521f1ae32a1SGerd Hoffmann break; 1522f1ae32a1SGerd Hoffmann 1523f1ae32a1SGerd Hoffmann case 13: /* HcFmInterretval */ 1524f1ae32a1SGerd Hoffmann retval = (ohci->fit << 31) | (ohci->fsmps << 16) | (ohci->fi); 1525f1ae32a1SGerd Hoffmann break; 1526f1ae32a1SGerd Hoffmann 1527f1ae32a1SGerd Hoffmann case 14: /* HcFmRemaining */ 1528f1ae32a1SGerd Hoffmann retval = ohci_get_frame_remaining(ohci); 1529f1ae32a1SGerd Hoffmann break; 1530f1ae32a1SGerd Hoffmann 1531f1ae32a1SGerd Hoffmann case 15: /* HcFmNumber */ 1532f1ae32a1SGerd Hoffmann retval = ohci->frame_number; 1533f1ae32a1SGerd Hoffmann break; 1534f1ae32a1SGerd Hoffmann 1535f1ae32a1SGerd Hoffmann case 16: /* HcPeriodicStart */ 1536f1ae32a1SGerd Hoffmann retval = ohci->pstart; 1537f1ae32a1SGerd Hoffmann break; 1538f1ae32a1SGerd Hoffmann 1539f1ae32a1SGerd Hoffmann case 17: /* HcLSThreshold */ 1540f1ae32a1SGerd Hoffmann retval = ohci->lst; 1541f1ae32a1SGerd Hoffmann break; 1542f1ae32a1SGerd Hoffmann 1543f1ae32a1SGerd Hoffmann case 18: /* HcRhDescriptorA */ 1544f1ae32a1SGerd Hoffmann retval = ohci->rhdesc_a; 1545f1ae32a1SGerd Hoffmann break; 1546f1ae32a1SGerd Hoffmann 1547f1ae32a1SGerd Hoffmann case 19: /* HcRhDescriptorB */ 1548f1ae32a1SGerd Hoffmann retval = ohci->rhdesc_b; 1549f1ae32a1SGerd Hoffmann break; 1550f1ae32a1SGerd Hoffmann 1551f1ae32a1SGerd Hoffmann case 20: /* HcRhStatus */ 1552f1ae32a1SGerd Hoffmann retval = ohci->rhstatus; 1553f1ae32a1SGerd Hoffmann break; 1554f1ae32a1SGerd Hoffmann 1555f1ae32a1SGerd Hoffmann /* PXA27x specific registers */ 1556f1ae32a1SGerd Hoffmann case 24: /* HcStatus */ 1557f1ae32a1SGerd Hoffmann retval = ohci->hstatus & ohci->hmask; 1558f1ae32a1SGerd Hoffmann break; 1559f1ae32a1SGerd Hoffmann 1560f1ae32a1SGerd Hoffmann case 25: /* HcHReset */ 1561f1ae32a1SGerd Hoffmann retval = ohci->hreset; 1562f1ae32a1SGerd Hoffmann break; 1563f1ae32a1SGerd Hoffmann 1564f1ae32a1SGerd Hoffmann case 26: /* HcHInterruptEnable */ 1565f1ae32a1SGerd Hoffmann retval = ohci->hmask; 1566f1ae32a1SGerd Hoffmann break; 1567f1ae32a1SGerd Hoffmann 1568f1ae32a1SGerd Hoffmann case 27: /* HcHInterruptTest */ 1569f1ae32a1SGerd Hoffmann retval = ohci->htest; 1570f1ae32a1SGerd Hoffmann break; 1571f1ae32a1SGerd Hoffmann 1572f1ae32a1SGerd Hoffmann default: 1573dc1f5988SAlexey Kardashevskiy trace_usb_ohci_mem_read_bad_offset(addr); 1574f1ae32a1SGerd Hoffmann retval = 0xffffffff; 1575f1ae32a1SGerd Hoffmann } 1576f1ae32a1SGerd Hoffmann } 1577f1ae32a1SGerd Hoffmann 1578f1ae32a1SGerd Hoffmann return retval; 1579f1ae32a1SGerd Hoffmann } 1580f1ae32a1SGerd Hoffmann 1581f1ae32a1SGerd Hoffmann static void ohci_mem_write(void *opaque, 1582a8170e5eSAvi Kivity hwaddr addr, 1583f1ae32a1SGerd Hoffmann uint64_t val, 1584f1ae32a1SGerd Hoffmann unsigned size) 1585f1ae32a1SGerd Hoffmann { 1586f1ae32a1SGerd Hoffmann OHCIState *ohci = opaque; 1587f1ae32a1SGerd Hoffmann 1588f1ae32a1SGerd Hoffmann /* Only aligned reads are allowed on OHCI */ 1589f1ae32a1SGerd Hoffmann if (addr & 3) { 1590dc1f5988SAlexey Kardashevskiy trace_usb_ohci_mem_write_unaligned(addr); 1591f1ae32a1SGerd Hoffmann return; 1592f1ae32a1SGerd Hoffmann } 1593f1ae32a1SGerd Hoffmann 1594f1ae32a1SGerd Hoffmann if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) { 1595f1ae32a1SGerd Hoffmann /* HcRhPortStatus */ 1596f1ae32a1SGerd Hoffmann ohci_port_set_status(ohci, (addr - 0x54) >> 2, val); 1597f1ae32a1SGerd Hoffmann return; 1598f1ae32a1SGerd Hoffmann } 1599f1ae32a1SGerd Hoffmann 1600f1ae32a1SGerd Hoffmann switch (addr >> 2) { 1601f1ae32a1SGerd Hoffmann case 1: /* HcControl */ 1602f1ae32a1SGerd Hoffmann ohci_set_ctl(ohci, val); 1603f1ae32a1SGerd Hoffmann break; 1604f1ae32a1SGerd Hoffmann 1605f1ae32a1SGerd Hoffmann case 2: /* HcCommandStatus */ 1606f1ae32a1SGerd Hoffmann /* SOC is read-only */ 1607f1ae32a1SGerd Hoffmann val = (val & ~OHCI_STATUS_SOC); 1608f1ae32a1SGerd Hoffmann 1609f1ae32a1SGerd Hoffmann /* Bits written as '0' remain unchanged in the register */ 1610f1ae32a1SGerd Hoffmann ohci->status |= val; 1611f1ae32a1SGerd Hoffmann 1612f1ae32a1SGerd Hoffmann if (ohci->status & OHCI_STATUS_HCR) 16130922c3f6SHervé Poussineau ohci_soft_reset(ohci); 1614f1ae32a1SGerd Hoffmann break; 1615f1ae32a1SGerd Hoffmann 1616f1ae32a1SGerd Hoffmann case 3: /* HcInterruptStatus */ 1617f1ae32a1SGerd Hoffmann ohci->intr_status &= ~val; 1618f1ae32a1SGerd Hoffmann ohci_intr_update(ohci); 1619f1ae32a1SGerd Hoffmann break; 1620f1ae32a1SGerd Hoffmann 1621f1ae32a1SGerd Hoffmann case 4: /* HcInterruptEnable */ 1622f1ae32a1SGerd Hoffmann ohci->intr |= val; 1623f1ae32a1SGerd Hoffmann ohci_intr_update(ohci); 1624f1ae32a1SGerd Hoffmann break; 1625f1ae32a1SGerd Hoffmann 1626f1ae32a1SGerd Hoffmann case 5: /* HcInterruptDisable */ 1627f1ae32a1SGerd Hoffmann ohci->intr &= ~val; 1628f1ae32a1SGerd Hoffmann ohci_intr_update(ohci); 1629f1ae32a1SGerd Hoffmann break; 1630f1ae32a1SGerd Hoffmann 1631f1ae32a1SGerd Hoffmann case 6: /* HcHCCA */ 1632f1ae32a1SGerd Hoffmann ohci->hcca = val & OHCI_HCCA_MASK; 1633f1ae32a1SGerd Hoffmann break; 1634f1ae32a1SGerd Hoffmann 1635f1ae32a1SGerd Hoffmann case 7: /* HcPeriodCurrentED */ 1636f1ae32a1SGerd Hoffmann /* Ignore writes to this read-only register, Linux does them */ 1637f1ae32a1SGerd Hoffmann break; 1638f1ae32a1SGerd Hoffmann 1639f1ae32a1SGerd Hoffmann case 8: /* HcControlHeadED */ 1640f1ae32a1SGerd Hoffmann ohci->ctrl_head = val & OHCI_EDPTR_MASK; 1641f1ae32a1SGerd Hoffmann break; 1642f1ae32a1SGerd Hoffmann 1643f1ae32a1SGerd Hoffmann case 9: /* HcControlCurrentED */ 1644f1ae32a1SGerd Hoffmann ohci->ctrl_cur = val & OHCI_EDPTR_MASK; 1645f1ae32a1SGerd Hoffmann break; 1646f1ae32a1SGerd Hoffmann 1647f1ae32a1SGerd Hoffmann case 10: /* HcBulkHeadED */ 1648f1ae32a1SGerd Hoffmann ohci->bulk_head = val & OHCI_EDPTR_MASK; 1649f1ae32a1SGerd Hoffmann break; 1650f1ae32a1SGerd Hoffmann 1651f1ae32a1SGerd Hoffmann case 11: /* HcBulkCurrentED */ 1652f1ae32a1SGerd Hoffmann ohci->bulk_cur = val & OHCI_EDPTR_MASK; 1653f1ae32a1SGerd Hoffmann break; 1654f1ae32a1SGerd Hoffmann 1655f1ae32a1SGerd Hoffmann case 13: /* HcFmInterval */ 1656f1ae32a1SGerd Hoffmann ohci->fsmps = (val & OHCI_FMI_FSMPS) >> 16; 1657f1ae32a1SGerd Hoffmann ohci->fit = (val & OHCI_FMI_FIT) >> 31; 1658f1ae32a1SGerd Hoffmann ohci_set_frame_interval(ohci, val); 1659f1ae32a1SGerd Hoffmann break; 1660f1ae32a1SGerd Hoffmann 1661f1ae32a1SGerd Hoffmann case 15: /* HcFmNumber */ 1662f1ae32a1SGerd Hoffmann break; 1663f1ae32a1SGerd Hoffmann 1664f1ae32a1SGerd Hoffmann case 16: /* HcPeriodicStart */ 1665f1ae32a1SGerd Hoffmann ohci->pstart = val & 0xffff; 1666f1ae32a1SGerd Hoffmann break; 1667f1ae32a1SGerd Hoffmann 1668f1ae32a1SGerd Hoffmann case 17: /* HcLSThreshold */ 1669f1ae32a1SGerd Hoffmann ohci->lst = val & 0xffff; 1670f1ae32a1SGerd Hoffmann break; 1671f1ae32a1SGerd Hoffmann 1672f1ae32a1SGerd Hoffmann case 18: /* HcRhDescriptorA */ 1673f1ae32a1SGerd Hoffmann ohci->rhdesc_a &= ~OHCI_RHA_RW_MASK; 1674f1ae32a1SGerd Hoffmann ohci->rhdesc_a |= val & OHCI_RHA_RW_MASK; 1675f1ae32a1SGerd Hoffmann break; 1676f1ae32a1SGerd Hoffmann 1677f1ae32a1SGerd Hoffmann case 19: /* HcRhDescriptorB */ 1678f1ae32a1SGerd Hoffmann break; 1679f1ae32a1SGerd Hoffmann 1680f1ae32a1SGerd Hoffmann case 20: /* HcRhStatus */ 1681f1ae32a1SGerd Hoffmann ohci_set_hub_status(ohci, val); 1682f1ae32a1SGerd Hoffmann break; 1683f1ae32a1SGerd Hoffmann 1684f1ae32a1SGerd Hoffmann /* PXA27x specific registers */ 1685f1ae32a1SGerd Hoffmann case 24: /* HcStatus */ 1686f1ae32a1SGerd Hoffmann ohci->hstatus &= ~(val & ohci->hmask); 16877fa96d73SGerd Hoffmann break; 1688f1ae32a1SGerd Hoffmann 1689f1ae32a1SGerd Hoffmann case 25: /* HcHReset */ 1690f1ae32a1SGerd Hoffmann ohci->hreset = val & ~OHCI_HRESET_FSBIR; 1691f1ae32a1SGerd Hoffmann if (val & OHCI_HRESET_FSBIR) 169284d04e21SHervé Poussineau ohci_hard_reset(ohci); 1693f1ae32a1SGerd Hoffmann break; 1694f1ae32a1SGerd Hoffmann 1695f1ae32a1SGerd Hoffmann case 26: /* HcHInterruptEnable */ 1696f1ae32a1SGerd Hoffmann ohci->hmask = val; 1697f1ae32a1SGerd Hoffmann break; 1698f1ae32a1SGerd Hoffmann 1699f1ae32a1SGerd Hoffmann case 27: /* HcHInterruptTest */ 1700f1ae32a1SGerd Hoffmann ohci->htest = val; 1701f1ae32a1SGerd Hoffmann break; 1702f1ae32a1SGerd Hoffmann 1703f1ae32a1SGerd Hoffmann default: 1704dc1f5988SAlexey Kardashevskiy trace_usb_ohci_mem_write_bad_offset(addr); 1705f1ae32a1SGerd Hoffmann break; 1706f1ae32a1SGerd Hoffmann } 1707f1ae32a1SGerd Hoffmann } 1708f1ae32a1SGerd Hoffmann 170937bf0654SBALATON Zoltan static const MemoryRegionOps ohci_mem_ops = { 171037bf0654SBALATON Zoltan .read = ohci_mem_read, 171137bf0654SBALATON Zoltan .write = ohci_mem_write, 171237bf0654SBALATON Zoltan .endianness = DEVICE_LITTLE_ENDIAN, 171337bf0654SBALATON Zoltan }; 171437bf0654SBALATON Zoltan 171537bf0654SBALATON Zoltan /* USBPortOps */ 171637bf0654SBALATON Zoltan static void ohci_attach(USBPort *port1) 171737bf0654SBALATON Zoltan { 171837bf0654SBALATON Zoltan OHCIState *s = port1->opaque; 171937bf0654SBALATON Zoltan OHCIPort *port = &s->rhport[port1->index]; 172037bf0654SBALATON Zoltan uint32_t old_state = port->ctrl; 172137bf0654SBALATON Zoltan 172237bf0654SBALATON Zoltan /* set connect status */ 172337bf0654SBALATON Zoltan port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC; 172437bf0654SBALATON Zoltan 172537bf0654SBALATON Zoltan /* update speed */ 172637bf0654SBALATON Zoltan if (port->port.dev->speed == USB_SPEED_LOW) { 172737bf0654SBALATON Zoltan port->ctrl |= OHCI_PORT_LSDA; 172837bf0654SBALATON Zoltan } else { 172937bf0654SBALATON Zoltan port->ctrl &= ~OHCI_PORT_LSDA; 173037bf0654SBALATON Zoltan } 173137bf0654SBALATON Zoltan 173237bf0654SBALATON Zoltan /* notify of remote-wakeup */ 173337bf0654SBALATON Zoltan if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) { 173437bf0654SBALATON Zoltan ohci_set_interrupt(s, OHCI_INTR_RD); 173537bf0654SBALATON Zoltan } 173637bf0654SBALATON Zoltan 173737bf0654SBALATON Zoltan trace_usb_ohci_port_attach(port1->index); 173837bf0654SBALATON Zoltan 173937bf0654SBALATON Zoltan if (old_state != port->ctrl) { 174037bf0654SBALATON Zoltan ohci_set_interrupt(s, OHCI_INTR_RHSC); 174137bf0654SBALATON Zoltan } 174237bf0654SBALATON Zoltan } 174337bf0654SBALATON Zoltan 1744b6b0c066SBALATON Zoltan static void ohci_child_detach(USBPort *port1, USBDevice *dev) 1745f1ae32a1SGerd Hoffmann { 1746b6b0c066SBALATON Zoltan OHCIState *ohci = port1->opaque; 1747b6b0c066SBALATON Zoltan 1748f1ae32a1SGerd Hoffmann if (ohci->async_td && 1749f1ae32a1SGerd Hoffmann usb_packet_is_inflight(&ohci->usb_packet) && 1750f1ae32a1SGerd Hoffmann ohci->usb_packet.ep->dev == dev) { 1751f1ae32a1SGerd Hoffmann usb_cancel_packet(&ohci->usb_packet); 1752f1ae32a1SGerd Hoffmann ohci->async_td = 0; 1753f1ae32a1SGerd Hoffmann } 1754f1ae32a1SGerd Hoffmann } 1755f1ae32a1SGerd Hoffmann 175637bf0654SBALATON Zoltan static void ohci_detach(USBPort *port1) 175737bf0654SBALATON Zoltan { 175837bf0654SBALATON Zoltan OHCIState *s = port1->opaque; 175937bf0654SBALATON Zoltan OHCIPort *port = &s->rhport[port1->index]; 176037bf0654SBALATON Zoltan uint32_t old_state = port->ctrl; 176137bf0654SBALATON Zoltan 1762b6b0c066SBALATON Zoltan ohci_child_detach(port1, port1->dev); 176337bf0654SBALATON Zoltan 176437bf0654SBALATON Zoltan /* set connect status */ 176537bf0654SBALATON Zoltan if (port->ctrl & OHCI_PORT_CCS) { 176637bf0654SBALATON Zoltan port->ctrl &= ~OHCI_PORT_CCS; 176737bf0654SBALATON Zoltan port->ctrl |= OHCI_PORT_CSC; 176837bf0654SBALATON Zoltan } 176937bf0654SBALATON Zoltan /* disable port */ 177037bf0654SBALATON Zoltan if (port->ctrl & OHCI_PORT_PES) { 177137bf0654SBALATON Zoltan port->ctrl &= ~OHCI_PORT_PES; 177237bf0654SBALATON Zoltan port->ctrl |= OHCI_PORT_PESC; 177337bf0654SBALATON Zoltan } 177437bf0654SBALATON Zoltan trace_usb_ohci_port_detach(port1->index); 177537bf0654SBALATON Zoltan 177637bf0654SBALATON Zoltan if (old_state != port->ctrl) { 177737bf0654SBALATON Zoltan ohci_set_interrupt(s, OHCI_INTR_RHSC); 177837bf0654SBALATON Zoltan } 177937bf0654SBALATON Zoltan } 178037bf0654SBALATON Zoltan 178137bf0654SBALATON Zoltan static void ohci_wakeup(USBPort *port1) 178237bf0654SBALATON Zoltan { 178337bf0654SBALATON Zoltan OHCIState *s = port1->opaque; 178437bf0654SBALATON Zoltan OHCIPort *port = &s->rhport[port1->index]; 178537bf0654SBALATON Zoltan uint32_t intr = 0; 178637bf0654SBALATON Zoltan if (port->ctrl & OHCI_PORT_PSS) { 178737bf0654SBALATON Zoltan trace_usb_ohci_port_wakeup(port1->index); 178837bf0654SBALATON Zoltan port->ctrl |= OHCI_PORT_PSSC; 178937bf0654SBALATON Zoltan port->ctrl &= ~OHCI_PORT_PSS; 179037bf0654SBALATON Zoltan intr = OHCI_INTR_RHSC; 179137bf0654SBALATON Zoltan } 179237bf0654SBALATON Zoltan /* Note that the controller can be suspended even if this port is not */ 179337bf0654SBALATON Zoltan if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) { 179437bf0654SBALATON Zoltan trace_usb_ohci_remote_wakeup(s->name); 179537bf0654SBALATON Zoltan /* This is the one state transition the controller can do by itself */ 179637bf0654SBALATON Zoltan s->ctl &= ~OHCI_CTL_HCFS; 179737bf0654SBALATON Zoltan s->ctl |= OHCI_USB_RESUME; 179837bf0654SBALATON Zoltan /* 179937bf0654SBALATON Zoltan * In suspend mode only ResumeDetected is possible, not RHSC: 180037bf0654SBALATON Zoltan * see the OHCI spec 5.1.2.3. 180137bf0654SBALATON Zoltan */ 180237bf0654SBALATON Zoltan intr = OHCI_INTR_RD; 180337bf0654SBALATON Zoltan } 180437bf0654SBALATON Zoltan ohci_set_interrupt(s, intr); 180537bf0654SBALATON Zoltan } 180637bf0654SBALATON Zoltan 180737bf0654SBALATON Zoltan static void ohci_async_complete_packet(USBPort *port, USBPacket *packet) 180837bf0654SBALATON Zoltan { 180937bf0654SBALATON Zoltan OHCIState *ohci = container_of(packet, OHCIState, usb_packet); 181037bf0654SBALATON Zoltan 181137bf0654SBALATON Zoltan trace_usb_ohci_async_complete(); 181237bf0654SBALATON Zoltan ohci->async_complete = true; 18133a4d06f2SBALATON Zoltan ohci_process_lists(ohci); 181437bf0654SBALATON Zoltan } 1815f1ae32a1SGerd Hoffmann 1816f1ae32a1SGerd Hoffmann static USBPortOps ohci_port_ops = { 1817f1ae32a1SGerd Hoffmann .attach = ohci_attach, 1818f1ae32a1SGerd Hoffmann .detach = ohci_detach, 1819f1ae32a1SGerd Hoffmann .child_detach = ohci_child_detach, 1820f1ae32a1SGerd Hoffmann .wakeup = ohci_wakeup, 1821f1ae32a1SGerd Hoffmann .complete = ohci_async_complete_packet, 1822f1ae32a1SGerd Hoffmann }; 1823f1ae32a1SGerd Hoffmann 1824f1ae32a1SGerd Hoffmann static USBBusOps ohci_bus_ops = { 1825f1ae32a1SGerd Hoffmann }; 1826f1ae32a1SGerd Hoffmann 182734d97308SThomas Huth void usb_ohci_init(OHCIState *ohci, DeviceState *dev, uint32_t num_ports, 182834d97308SThomas Huth dma_addr_t localmem_base, char *masterbus, 182934d97308SThomas Huth uint32_t firstport, AddressSpace *as, 1830*4713720aSPhilippe Mathieu-Daudé void (*ohci_die_fn)(OHCIState *), Error **errp) 1831f1ae32a1SGerd Hoffmann { 1832f4bbaaf5SMarkus Armbruster Error *err = NULL; 1833f1ae32a1SGerd Hoffmann int i; 1834f1ae32a1SGerd Hoffmann 1835df32fd1cSPaolo Bonzini ohci->as = as; 183672e0c127SThomas Huth ohci->ohci_die = ohci_die_fn; 18379ac6a217SDavid Gibson 1838d400fc01SThomas Huth if (num_ports > OHCI_MAX_PORTS) { 1839b9a3a4f2SLi Qiang error_setg(errp, "OHCI num-ports=%u is too big (limit is %u ports)", 1840d400fc01SThomas Huth num_ports, OHCI_MAX_PORTS); 1841d400fc01SThomas Huth return; 1842d400fc01SThomas Huth } 1843d400fc01SThomas Huth 1844f1ae32a1SGerd Hoffmann if (usb_frame_time == 0) { 1845f1ae32a1SGerd Hoffmann #ifdef OHCI_TIME_WARP 184673bcb24dSRutuja Shah usb_frame_time = NANOSECONDS_PER_SECOND; 184773bcb24dSRutuja Shah usb_bit_time = NANOSECONDS_PER_SECOND / (USB_HZ / 1000); 1848f1ae32a1SGerd Hoffmann #else 184973bcb24dSRutuja Shah usb_frame_time = NANOSECONDS_PER_SECOND / 1000; 185073bcb24dSRutuja Shah if (NANOSECONDS_PER_SECOND >= USB_HZ) { 185173bcb24dSRutuja Shah usb_bit_time = NANOSECONDS_PER_SECOND / USB_HZ; 1852f1ae32a1SGerd Hoffmann } else { 1853f1ae32a1SGerd Hoffmann usb_bit_time = 1; 1854f1ae32a1SGerd Hoffmann } 1855f1ae32a1SGerd Hoffmann #endif 1856dc1f5988SAlexey Kardashevskiy trace_usb_ohci_init_time(usb_frame_time, usb_bit_time); 1857f1ae32a1SGerd Hoffmann } 1858f1ae32a1SGerd Hoffmann 1859f1ae32a1SGerd Hoffmann ohci->num_ports = num_ports; 1860f1ae32a1SGerd Hoffmann if (masterbus) { 1861f1ae32a1SGerd Hoffmann USBPort *ports[OHCI_MAX_PORTS]; 1862f1ae32a1SGerd Hoffmann for(i = 0; i < num_ports; i++) { 1863f1ae32a1SGerd Hoffmann ports[i] = &ohci->rhport[i].port; 1864f1ae32a1SGerd Hoffmann } 1865f4bbaaf5SMarkus Armbruster usb_register_companion(masterbus, ports, num_ports, 1866f1ae32a1SGerd Hoffmann firstport, ohci, &ohci_port_ops, 1867f4bbaaf5SMarkus Armbruster USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL, 1868f4bbaaf5SMarkus Armbruster &err); 1869f4bbaaf5SMarkus Armbruster if (err) { 187087581feaSMarkus Armbruster error_propagate(errp, err); 187187581feaSMarkus Armbruster return; 1872f1ae32a1SGerd Hoffmann } 1873f1ae32a1SGerd Hoffmann } else { 1874c889b3a5SAndreas Färber usb_bus_new(&ohci->bus, sizeof(ohci->bus), &ohci_bus_ops, dev); 1875f1ae32a1SGerd Hoffmann for (i = 0; i < num_ports; i++) { 1876f1ae32a1SGerd Hoffmann usb_register_port(&ohci->bus, &ohci->rhport[i].port, 1877f1ae32a1SGerd Hoffmann ohci, i, &ohci_port_ops, 1878f1ae32a1SGerd Hoffmann USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL); 1879f1ae32a1SGerd Hoffmann } 1880f1ae32a1SGerd Hoffmann } 1881f1ae32a1SGerd Hoffmann 188222fc860bSPaolo Bonzini memory_region_init_io(&ohci->mem, OBJECT(dev), &ohci_mem_ops, 188322fc860bSPaolo Bonzini ohci, "ohci", 256); 1884f1ae32a1SGerd Hoffmann ohci->localmem_base = localmem_base; 1885f1ae32a1SGerd Hoffmann 1886f1ae32a1SGerd Hoffmann ohci->name = object_get_typename(OBJECT(dev)); 1887f1ae32a1SGerd Hoffmann usb_packet_init(&ohci->usb_packet); 1888f1ae32a1SGerd Hoffmann 1889f1ae32a1SGerd Hoffmann ohci->async_td = 0; 1890fa1298c2SGerd Hoffmann 1891fa1298c2SGerd Hoffmann ohci->eof_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, 1892fa1298c2SGerd Hoffmann ohci_frame_boundary, ohci); 1893f1ae32a1SGerd Hoffmann } 1894f1ae32a1SGerd Hoffmann 189572e0c127SThomas Huth /** 189672e0c127SThomas Huth * A typical OHCI will stop operating and set itself into error state 189772e0c127SThomas Huth * (which can be queried by MMIO) to signal that it got an error. 1898cf66ee8eSAlexey Kardashevskiy */ 189934d97308SThomas Huth void ohci_sysbus_die(struct OHCIState *ohci) 1900cf66ee8eSAlexey Kardashevskiy { 1901dc1f5988SAlexey Kardashevskiy trace_usb_ohci_die(); 1902cf66ee8eSAlexey Kardashevskiy 1903cf66ee8eSAlexey Kardashevskiy ohci_set_interrupt(ohci, OHCI_INTR_UE); 1904cf66ee8eSAlexey Kardashevskiy ohci_bus_stop(ohci); 190572e0c127SThomas Huth } 190672e0c127SThomas Huth 1907457215ecSHu Tao static void ohci_realize_pxa(DeviceState *dev, Error **errp) 1908f1ae32a1SGerd Hoffmann { 19091aa0c0c7SHu Tao OHCISysBusState *s = SYSBUS_OHCI(dev); 1910457215ecSHu Tao SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 1911d7145b66SBALATON Zoltan Error *err = NULL; 1912f1ae32a1SGerd Hoffmann 1913d7145b66SBALATON Zoltan usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset, 1914d7145b66SBALATON Zoltan s->masterbus, s->firstport, 191572e0c127SThomas Huth &address_space_memory, ohci_sysbus_die, &err); 1916d7145b66SBALATON Zoltan if (err) { 1917d7145b66SBALATON Zoltan error_propagate(errp, err); 1918d7145b66SBALATON Zoltan return; 1919d7145b66SBALATON Zoltan } 1920457215ecSHu Tao sysbus_init_irq(sbd, &s->ohci.irq); 1921457215ecSHu Tao sysbus_init_mmio(sbd, &s->ohci.mem); 1922f1ae32a1SGerd Hoffmann } 1923f1ae32a1SGerd Hoffmann 192488dd1b8dSGonglei static void usb_ohci_reset_sysbus(DeviceState *dev) 192588dd1b8dSGonglei { 192688dd1b8dSGonglei OHCISysBusState *s = SYSBUS_OHCI(dev); 192788dd1b8dSGonglei OHCIState *ohci = &s->ohci; 192888dd1b8dSGonglei 192984d04e21SHervé Poussineau ohci_hard_reset(ohci); 193088dd1b8dSGonglei } 193188dd1b8dSGonglei 193269e25d26SAlexey Kardashevskiy static const VMStateDescription vmstate_ohci_state_port = { 193369e25d26SAlexey Kardashevskiy .name = "ohci-core/port", 193469e25d26SAlexey Kardashevskiy .version_id = 1, 193569e25d26SAlexey Kardashevskiy .minimum_version_id = 1, 193669e25d26SAlexey Kardashevskiy .fields = (VMStateField[]) { 193769e25d26SAlexey Kardashevskiy VMSTATE_UINT32(ctrl, OHCIPort), 193869e25d26SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 193969e25d26SAlexey Kardashevskiy }, 194069e25d26SAlexey Kardashevskiy }; 194169e25d26SAlexey Kardashevskiy 194269e25d26SAlexey Kardashevskiy static bool ohci_eof_timer_needed(void *opaque) 194369e25d26SAlexey Kardashevskiy { 194469e25d26SAlexey Kardashevskiy OHCIState *ohci = opaque; 194569e25d26SAlexey Kardashevskiy 1946fa1298c2SGerd Hoffmann return timer_pending(ohci->eof_timer); 194769e25d26SAlexey Kardashevskiy } 194869e25d26SAlexey Kardashevskiy 194969e25d26SAlexey Kardashevskiy static const VMStateDescription vmstate_ohci_eof_timer = { 195069e25d26SAlexey Kardashevskiy .name = "ohci-core/eof-timer", 195169e25d26SAlexey Kardashevskiy .version_id = 1, 195269e25d26SAlexey Kardashevskiy .minimum_version_id = 1, 19535cd8cadaSJuan Quintela .needed = ohci_eof_timer_needed, 195469e25d26SAlexey Kardashevskiy .fields = (VMStateField[]) { 1955e720677eSPaolo Bonzini VMSTATE_TIMER_PTR(eof_timer, OHCIState), 195669e25d26SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 195769e25d26SAlexey Kardashevskiy }, 195869e25d26SAlexey Kardashevskiy }; 195969e25d26SAlexey Kardashevskiy 196034d97308SThomas Huth const VMStateDescription vmstate_ohci_state = { 196169e25d26SAlexey Kardashevskiy .name = "ohci-core", 196269e25d26SAlexey Kardashevskiy .version_id = 1, 196369e25d26SAlexey Kardashevskiy .minimum_version_id = 1, 196469e25d26SAlexey Kardashevskiy .fields = (VMStateField[]) { 196569e25d26SAlexey Kardashevskiy VMSTATE_INT64(sof_time, OHCIState), 196669e25d26SAlexey Kardashevskiy VMSTATE_UINT32(ctl, OHCIState), 196769e25d26SAlexey Kardashevskiy VMSTATE_UINT32(status, OHCIState), 196869e25d26SAlexey Kardashevskiy VMSTATE_UINT32(intr_status, OHCIState), 196969e25d26SAlexey Kardashevskiy VMSTATE_UINT32(intr, OHCIState), 197069e25d26SAlexey Kardashevskiy VMSTATE_UINT32(hcca, OHCIState), 197169e25d26SAlexey Kardashevskiy VMSTATE_UINT32(ctrl_head, OHCIState), 197269e25d26SAlexey Kardashevskiy VMSTATE_UINT32(ctrl_cur, OHCIState), 197369e25d26SAlexey Kardashevskiy VMSTATE_UINT32(bulk_head, OHCIState), 197469e25d26SAlexey Kardashevskiy VMSTATE_UINT32(bulk_cur, OHCIState), 197569e25d26SAlexey Kardashevskiy VMSTATE_UINT32(per_cur, OHCIState), 197669e25d26SAlexey Kardashevskiy VMSTATE_UINT32(done, OHCIState), 197769e25d26SAlexey Kardashevskiy VMSTATE_INT32(done_count, OHCIState), 197869e25d26SAlexey Kardashevskiy VMSTATE_UINT16(fsmps, OHCIState), 197969e25d26SAlexey Kardashevskiy VMSTATE_UINT8(fit, OHCIState), 198069e25d26SAlexey Kardashevskiy VMSTATE_UINT16(fi, OHCIState), 198169e25d26SAlexey Kardashevskiy VMSTATE_UINT8(frt, OHCIState), 198269e25d26SAlexey Kardashevskiy VMSTATE_UINT16(frame_number, OHCIState), 198369e25d26SAlexey Kardashevskiy VMSTATE_UINT16(padding, OHCIState), 198469e25d26SAlexey Kardashevskiy VMSTATE_UINT32(pstart, OHCIState), 198569e25d26SAlexey Kardashevskiy VMSTATE_UINT32(lst, OHCIState), 198669e25d26SAlexey Kardashevskiy VMSTATE_UINT32(rhdesc_a, OHCIState), 198769e25d26SAlexey Kardashevskiy VMSTATE_UINT32(rhdesc_b, OHCIState), 198869e25d26SAlexey Kardashevskiy VMSTATE_UINT32(rhstatus, OHCIState), 198969e25d26SAlexey Kardashevskiy VMSTATE_STRUCT_ARRAY(rhport, OHCIState, OHCI_MAX_PORTS, 0, 199069e25d26SAlexey Kardashevskiy vmstate_ohci_state_port, OHCIPort), 199169e25d26SAlexey Kardashevskiy VMSTATE_UINT32(hstatus, OHCIState), 199269e25d26SAlexey Kardashevskiy VMSTATE_UINT32(hmask, OHCIState), 199369e25d26SAlexey Kardashevskiy VMSTATE_UINT32(hreset, OHCIState), 199469e25d26SAlexey Kardashevskiy VMSTATE_UINT32(htest, OHCIState), 199569e25d26SAlexey Kardashevskiy VMSTATE_UINT32(old_ctl, OHCIState), 199669e25d26SAlexey Kardashevskiy VMSTATE_UINT8_ARRAY(usb_buf, OHCIState, 8192), 199769e25d26SAlexey Kardashevskiy VMSTATE_UINT32(async_td, OHCIState), 199869e25d26SAlexey Kardashevskiy VMSTATE_BOOL(async_complete, OHCIState), 199969e25d26SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 200069e25d26SAlexey Kardashevskiy }, 20015cd8cadaSJuan Quintela .subsections = (const VMStateDescription*[]) { 20025cd8cadaSJuan Quintela &vmstate_ohci_eof_timer, 20035cd8cadaSJuan Quintela NULL 200469e25d26SAlexey Kardashevskiy } 200569e25d26SAlexey Kardashevskiy }; 200669e25d26SAlexey Kardashevskiy 2007f1ae32a1SGerd Hoffmann static Property ohci_sysbus_properties[] = { 2008d7145b66SBALATON Zoltan DEFINE_PROP_STRING("masterbus", OHCISysBusState, masterbus), 2009f1ae32a1SGerd Hoffmann DEFINE_PROP_UINT32("num-ports", OHCISysBusState, num_ports, 3), 2010d7145b66SBALATON Zoltan DEFINE_PROP_UINT32("firstport", OHCISysBusState, firstport, 0), 20116998b6c7SVijay Kumar B DEFINE_PROP_DMAADDR("dma-offset", OHCISysBusState, dma_offset, 0), 2012f1ae32a1SGerd Hoffmann DEFINE_PROP_END_OF_LIST(), 2013f1ae32a1SGerd Hoffmann }; 2014f1ae32a1SGerd Hoffmann 2015f1ae32a1SGerd Hoffmann static void ohci_sysbus_class_init(ObjectClass *klass, void *data) 2016f1ae32a1SGerd Hoffmann { 2017f1ae32a1SGerd Hoffmann DeviceClass *dc = DEVICE_CLASS(klass); 2018f1ae32a1SGerd Hoffmann 2019457215ecSHu Tao dc->realize = ohci_realize_pxa; 2020125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_USB, dc->categories); 2021f1ae32a1SGerd Hoffmann dc->desc = "OHCI USB Controller"; 20224f67d30bSMarc-André Lureau device_class_set_props(dc, ohci_sysbus_properties); 202388dd1b8dSGonglei dc->reset = usb_ohci_reset_sysbus; 2024f1ae32a1SGerd Hoffmann } 2025f1ae32a1SGerd Hoffmann 20268c43a6f0SAndreas Färber static const TypeInfo ohci_sysbus_info = { 20271aa0c0c7SHu Tao .name = TYPE_SYSBUS_OHCI, 2028f1ae32a1SGerd Hoffmann .parent = TYPE_SYS_BUS_DEVICE, 2029f1ae32a1SGerd Hoffmann .instance_size = sizeof(OHCISysBusState), 2030f1ae32a1SGerd Hoffmann .class_init = ohci_sysbus_class_init, 2031f1ae32a1SGerd Hoffmann }; 2032f1ae32a1SGerd Hoffmann 2033f1ae32a1SGerd Hoffmann static void ohci_register_types(void) 2034f1ae32a1SGerd Hoffmann { 2035f1ae32a1SGerd Hoffmann type_register_static(&ohci_sysbus_info); 2036f1ae32a1SGerd Hoffmann } 2037f1ae32a1SGerd Hoffmann 2038f1ae32a1SGerd Hoffmann type_init(ohci_register_types) 2039