xref: /openbmc/qemu/hw/usb/hcd-ohci.c (revision ab878998)
1f1ae32a1SGerd Hoffmann /*
2f1ae32a1SGerd Hoffmann  * QEMU USB OHCI Emulation
3f1ae32a1SGerd Hoffmann  * Copyright (c) 2004 Gianni Tedesco
4f1ae32a1SGerd Hoffmann  * Copyright (c) 2006 CodeSourcery
5f1ae32a1SGerd Hoffmann  * Copyright (c) 2006 Openedhand Ltd.
6f1ae32a1SGerd Hoffmann  *
7f1ae32a1SGerd Hoffmann  * This library is free software; you can redistribute it and/or
8f1ae32a1SGerd Hoffmann  * modify it under the terms of the GNU Lesser General Public
9f1ae32a1SGerd Hoffmann  * License as published by the Free Software Foundation; either
10f1ae32a1SGerd Hoffmann  * version 2 of the License, or (at your option) any later version.
11f1ae32a1SGerd Hoffmann  *
12f1ae32a1SGerd Hoffmann  * This library is distributed in the hope that it will be useful,
13f1ae32a1SGerd Hoffmann  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14f1ae32a1SGerd Hoffmann  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15f1ae32a1SGerd Hoffmann  * Lesser General Public License for more details.
16f1ae32a1SGerd Hoffmann  *
17f1ae32a1SGerd Hoffmann  * You should have received a copy of the GNU Lesser General Public
18f1ae32a1SGerd Hoffmann  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19f1ae32a1SGerd Hoffmann  *
20f1ae32a1SGerd Hoffmann  * TODO:
21f1ae32a1SGerd Hoffmann  *  o Isochronous transfers
22f1ae32a1SGerd Hoffmann  *  o Allocate bandwidth in frames properly
23f1ae32a1SGerd Hoffmann  *  o Disable timers when nothing needs to be done, or remove timer usage
24f1ae32a1SGerd Hoffmann  *    all together.
25f1ae32a1SGerd Hoffmann  *  o BIOS work to boot from USB storage
26f1ae32a1SGerd Hoffmann */
27f1ae32a1SGerd Hoffmann 
28e532b2e0SPeter Maydell #include "qemu/osdep.h"
29f1ae32a1SGerd Hoffmann #include "hw/hw.h"
30da34e65cSMarkus Armbruster #include "qapi/error.h"
311de7afc9SPaolo Bonzini #include "qemu/timer.h"
32f1ae32a1SGerd Hoffmann #include "hw/usb.h"
33a2cb15b0SMichael S. Tsirkin #include "hw/pci/pci.h"
34f1ae32a1SGerd Hoffmann #include "hw/sysbus.h"
359ac6a217SDavid Gibson #include "hw/qdev-dma.h"
36dc1f5988SAlexey Kardashevskiy #include "trace.h"
37f1ae32a1SGerd Hoffmann 
38f1ae32a1SGerd Hoffmann /* This causes frames to occur 1000x slower */
39f1ae32a1SGerd Hoffmann //#define OHCI_TIME_WARP 1
40f1ae32a1SGerd Hoffmann 
41f1ae32a1SGerd Hoffmann /* Number of Downstream Ports on the root hub.  */
42f1ae32a1SGerd Hoffmann 
43f1ae32a1SGerd Hoffmann #define OHCI_MAX_PORTS 15
44f1ae32a1SGerd Hoffmann 
45ab6b1105SGerd Hoffmann #define ED_LINK_LIMIT 32
4695ed5693SLi Qiang 
47f1ae32a1SGerd Hoffmann static int64_t usb_frame_time;
48f1ae32a1SGerd Hoffmann static int64_t usb_bit_time;
49f1ae32a1SGerd Hoffmann 
50f1ae32a1SGerd Hoffmann typedef struct OHCIPort {
51f1ae32a1SGerd Hoffmann     USBPort port;
52f1ae32a1SGerd Hoffmann     uint32_t ctrl;
53f1ae32a1SGerd Hoffmann } OHCIPort;
54f1ae32a1SGerd Hoffmann 
55f1ae32a1SGerd Hoffmann typedef struct {
56f1ae32a1SGerd Hoffmann     USBBus bus;
57f1ae32a1SGerd Hoffmann     qemu_irq irq;
58f1ae32a1SGerd Hoffmann     MemoryRegion mem;
59df32fd1cSPaolo Bonzini     AddressSpace *as;
60b9a3a4f2SLi Qiang     uint32_t num_ports;
61f1ae32a1SGerd Hoffmann     const char *name;
62f1ae32a1SGerd Hoffmann 
63f1ae32a1SGerd Hoffmann     QEMUTimer *eof_timer;
64f1ae32a1SGerd Hoffmann     int64_t sof_time;
65f1ae32a1SGerd Hoffmann 
66f1ae32a1SGerd Hoffmann     /* OHCI state */
67f1ae32a1SGerd Hoffmann     /* Control partition */
68f1ae32a1SGerd Hoffmann     uint32_t ctl, status;
69f1ae32a1SGerd Hoffmann     uint32_t intr_status;
70f1ae32a1SGerd Hoffmann     uint32_t intr;
71f1ae32a1SGerd Hoffmann 
72f1ae32a1SGerd Hoffmann     /* memory pointer partition */
73f1ae32a1SGerd Hoffmann     uint32_t hcca;
74f1ae32a1SGerd Hoffmann     uint32_t ctrl_head, ctrl_cur;
75f1ae32a1SGerd Hoffmann     uint32_t bulk_head, bulk_cur;
76f1ae32a1SGerd Hoffmann     uint32_t per_cur;
77f1ae32a1SGerd Hoffmann     uint32_t done;
7869e25d26SAlexey Kardashevskiy     int32_t done_count;
79f1ae32a1SGerd Hoffmann 
80f1ae32a1SGerd Hoffmann     /* Frame counter partition */
8169e25d26SAlexey Kardashevskiy     uint16_t fsmps;
8269e25d26SAlexey Kardashevskiy     uint8_t fit;
8369e25d26SAlexey Kardashevskiy     uint16_t fi;
8469e25d26SAlexey Kardashevskiy     uint8_t frt;
85f1ae32a1SGerd Hoffmann     uint16_t frame_number;
86f1ae32a1SGerd Hoffmann     uint16_t padding;
87f1ae32a1SGerd Hoffmann     uint32_t pstart;
88f1ae32a1SGerd Hoffmann     uint32_t lst;
89f1ae32a1SGerd Hoffmann 
90f1ae32a1SGerd Hoffmann     /* Root Hub partition */
91f1ae32a1SGerd Hoffmann     uint32_t rhdesc_a, rhdesc_b;
92f1ae32a1SGerd Hoffmann     uint32_t rhstatus;
93f1ae32a1SGerd Hoffmann     OHCIPort rhport[OHCI_MAX_PORTS];
94f1ae32a1SGerd Hoffmann 
95f1ae32a1SGerd Hoffmann     /* PXA27x Non-OHCI events */
96f1ae32a1SGerd Hoffmann     uint32_t hstatus;
97f1ae32a1SGerd Hoffmann     uint32_t hmask;
98f1ae32a1SGerd Hoffmann     uint32_t hreset;
99f1ae32a1SGerd Hoffmann     uint32_t htest;
100f1ae32a1SGerd Hoffmann 
101f1ae32a1SGerd Hoffmann     /* SM501 local memory offset */
1029ac6a217SDavid Gibson     dma_addr_t localmem_base;
103f1ae32a1SGerd Hoffmann 
104f1ae32a1SGerd Hoffmann     /* Active packets.  */
105f1ae32a1SGerd Hoffmann     uint32_t old_ctl;
106f1ae32a1SGerd Hoffmann     USBPacket usb_packet;
107f1ae32a1SGerd Hoffmann     uint8_t usb_buf[8192];
108f1ae32a1SGerd Hoffmann     uint32_t async_td;
10969e25d26SAlexey Kardashevskiy     bool async_complete;
110f1ae32a1SGerd Hoffmann 
111f1ae32a1SGerd Hoffmann } OHCIState;
112f1ae32a1SGerd Hoffmann 
113f1ae32a1SGerd Hoffmann /* Host Controller Communications Area */
114f1ae32a1SGerd Hoffmann struct ohci_hcca {
115f1ae32a1SGerd Hoffmann     uint32_t intr[32];
116f1ae32a1SGerd Hoffmann     uint16_t frame, pad;
117f1ae32a1SGerd Hoffmann     uint32_t done;
118f1ae32a1SGerd Hoffmann };
11986e18caeSWei Yang #define HCCA_WRITEBACK_OFFSET   offsetof(struct ohci_hcca, frame)
12086e18caeSWei Yang #define HCCA_WRITEBACK_SIZE     8 /* frame, pad, done */
12186e18caeSWei Yang 
12286e18caeSWei Yang #define ED_WBACK_OFFSET offsetof(struct ohci_ed, head)
12386e18caeSWei Yang #define ED_WBACK_SIZE   4
124f1ae32a1SGerd Hoffmann 
125f1ae32a1SGerd Hoffmann static void ohci_bus_stop(OHCIState *ohci);
126f1ae32a1SGerd Hoffmann static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev);
127f1ae32a1SGerd Hoffmann 
128f1ae32a1SGerd Hoffmann /* Bitfields for the first word of an Endpoint Desciptor.  */
129f1ae32a1SGerd Hoffmann #define OHCI_ED_FA_SHIFT  0
130f1ae32a1SGerd Hoffmann #define OHCI_ED_FA_MASK   (0x7f<<OHCI_ED_FA_SHIFT)
131f1ae32a1SGerd Hoffmann #define OHCI_ED_EN_SHIFT  7
132f1ae32a1SGerd Hoffmann #define OHCI_ED_EN_MASK   (0xf<<OHCI_ED_EN_SHIFT)
133f1ae32a1SGerd Hoffmann #define OHCI_ED_D_SHIFT   11
134f1ae32a1SGerd Hoffmann #define OHCI_ED_D_MASK    (3<<OHCI_ED_D_SHIFT)
135f1ae32a1SGerd Hoffmann #define OHCI_ED_S         (1<<13)
136f1ae32a1SGerd Hoffmann #define OHCI_ED_K         (1<<14)
137f1ae32a1SGerd Hoffmann #define OHCI_ED_F         (1<<15)
138f1ae32a1SGerd Hoffmann #define OHCI_ED_MPS_SHIFT 16
139f1ae32a1SGerd Hoffmann #define OHCI_ED_MPS_MASK  (0x7ff<<OHCI_ED_MPS_SHIFT)
140f1ae32a1SGerd Hoffmann 
141f1ae32a1SGerd Hoffmann /* Flags in the head field of an Endpoint Desciptor.  */
142f1ae32a1SGerd Hoffmann #define OHCI_ED_H         1
143f1ae32a1SGerd Hoffmann #define OHCI_ED_C         2
144f1ae32a1SGerd Hoffmann 
145f1ae32a1SGerd Hoffmann /* Bitfields for the first word of a Transfer Desciptor.  */
146f1ae32a1SGerd Hoffmann #define OHCI_TD_R         (1<<18)
147f1ae32a1SGerd Hoffmann #define OHCI_TD_DP_SHIFT  19
148f1ae32a1SGerd Hoffmann #define OHCI_TD_DP_MASK   (3<<OHCI_TD_DP_SHIFT)
149f1ae32a1SGerd Hoffmann #define OHCI_TD_DI_SHIFT  21
150f1ae32a1SGerd Hoffmann #define OHCI_TD_DI_MASK   (7<<OHCI_TD_DI_SHIFT)
151f1ae32a1SGerd Hoffmann #define OHCI_TD_T0        (1<<24)
152f1ae32a1SGerd Hoffmann #define OHCI_TD_T1        (1<<25)
153f1ae32a1SGerd Hoffmann #define OHCI_TD_EC_SHIFT  26
154f1ae32a1SGerd Hoffmann #define OHCI_TD_EC_MASK   (3<<OHCI_TD_EC_SHIFT)
155f1ae32a1SGerd Hoffmann #define OHCI_TD_CC_SHIFT  28
156f1ae32a1SGerd Hoffmann #define OHCI_TD_CC_MASK   (0xf<<OHCI_TD_CC_SHIFT)
157f1ae32a1SGerd Hoffmann 
158f1ae32a1SGerd Hoffmann /* Bitfields for the first word of an Isochronous Transfer Desciptor.  */
159f1ae32a1SGerd Hoffmann /* CC & DI - same as in the General Transfer Desciptor */
160f1ae32a1SGerd Hoffmann #define OHCI_TD_SF_SHIFT  0
161f1ae32a1SGerd Hoffmann #define OHCI_TD_SF_MASK   (0xffff<<OHCI_TD_SF_SHIFT)
162f1ae32a1SGerd Hoffmann #define OHCI_TD_FC_SHIFT  24
163f1ae32a1SGerd Hoffmann #define OHCI_TD_FC_MASK   (7<<OHCI_TD_FC_SHIFT)
164f1ae32a1SGerd Hoffmann 
165f1ae32a1SGerd Hoffmann /* Isochronous Transfer Desciptor - Offset / PacketStatusWord */
166f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_CC_SHIFT 12
167f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_CC_MASK  (0xf<<OHCI_TD_PSW_CC_SHIFT)
168f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_SIZE_SHIFT 0
169f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_SIZE_MASK  (0xfff<<OHCI_TD_PSW_SIZE_SHIFT)
170f1ae32a1SGerd Hoffmann 
171f1ae32a1SGerd Hoffmann #define OHCI_PAGE_MASK    0xfffff000
172f1ae32a1SGerd Hoffmann #define OHCI_OFFSET_MASK  0xfff
173f1ae32a1SGerd Hoffmann 
174f1ae32a1SGerd Hoffmann #define OHCI_DPTR_MASK    0xfffffff0
175f1ae32a1SGerd Hoffmann 
176f1ae32a1SGerd Hoffmann #define OHCI_BM(val, field) \
177f1ae32a1SGerd Hoffmann   (((val) & OHCI_##field##_MASK) >> OHCI_##field##_SHIFT)
178f1ae32a1SGerd Hoffmann 
179f1ae32a1SGerd Hoffmann #define OHCI_SET_BM(val, field, newval) do { \
180f1ae32a1SGerd Hoffmann     val &= ~OHCI_##field##_MASK; \
181f1ae32a1SGerd Hoffmann     val |= ((newval) << OHCI_##field##_SHIFT) & OHCI_##field##_MASK; \
182f1ae32a1SGerd Hoffmann     } while(0)
183f1ae32a1SGerd Hoffmann 
184f1ae32a1SGerd Hoffmann /* endpoint descriptor */
185f1ae32a1SGerd Hoffmann struct ohci_ed {
186f1ae32a1SGerd Hoffmann     uint32_t flags;
187f1ae32a1SGerd Hoffmann     uint32_t tail;
188f1ae32a1SGerd Hoffmann     uint32_t head;
189f1ae32a1SGerd Hoffmann     uint32_t next;
190f1ae32a1SGerd Hoffmann };
191f1ae32a1SGerd Hoffmann 
192f1ae32a1SGerd Hoffmann /* General transfer descriptor */
193f1ae32a1SGerd Hoffmann struct ohci_td {
194f1ae32a1SGerd Hoffmann     uint32_t flags;
195f1ae32a1SGerd Hoffmann     uint32_t cbp;
196f1ae32a1SGerd Hoffmann     uint32_t next;
197f1ae32a1SGerd Hoffmann     uint32_t be;
198f1ae32a1SGerd Hoffmann };
199f1ae32a1SGerd Hoffmann 
200f1ae32a1SGerd Hoffmann /* Isochronous transfer descriptor */
201f1ae32a1SGerd Hoffmann struct ohci_iso_td {
202f1ae32a1SGerd Hoffmann     uint32_t flags;
203f1ae32a1SGerd Hoffmann     uint32_t bp;
204f1ae32a1SGerd Hoffmann     uint32_t next;
205f1ae32a1SGerd Hoffmann     uint32_t be;
206f1ae32a1SGerd Hoffmann     uint16_t offset[8];
207f1ae32a1SGerd Hoffmann };
208f1ae32a1SGerd Hoffmann 
209f1ae32a1SGerd Hoffmann #define USB_HZ                      12000000
210f1ae32a1SGerd Hoffmann 
211f1ae32a1SGerd Hoffmann /* OHCI Local stuff */
212f1ae32a1SGerd Hoffmann #define OHCI_CTL_CBSR         ((1<<0)|(1<<1))
213f1ae32a1SGerd Hoffmann #define OHCI_CTL_PLE          (1<<2)
214f1ae32a1SGerd Hoffmann #define OHCI_CTL_IE           (1<<3)
215f1ae32a1SGerd Hoffmann #define OHCI_CTL_CLE          (1<<4)
216f1ae32a1SGerd Hoffmann #define OHCI_CTL_BLE          (1<<5)
217f1ae32a1SGerd Hoffmann #define OHCI_CTL_HCFS         ((1<<6)|(1<<7))
218f1ae32a1SGerd Hoffmann #define  OHCI_USB_RESET       0x00
219f1ae32a1SGerd Hoffmann #define  OHCI_USB_RESUME      0x40
220f1ae32a1SGerd Hoffmann #define  OHCI_USB_OPERATIONAL 0x80
221f1ae32a1SGerd Hoffmann #define  OHCI_USB_SUSPEND     0xc0
222f1ae32a1SGerd Hoffmann #define OHCI_CTL_IR           (1<<8)
223f1ae32a1SGerd Hoffmann #define OHCI_CTL_RWC          (1<<9)
224f1ae32a1SGerd Hoffmann #define OHCI_CTL_RWE          (1<<10)
225f1ae32a1SGerd Hoffmann 
226f1ae32a1SGerd Hoffmann #define OHCI_STATUS_HCR       (1<<0)
227f1ae32a1SGerd Hoffmann #define OHCI_STATUS_CLF       (1<<1)
228f1ae32a1SGerd Hoffmann #define OHCI_STATUS_BLF       (1<<2)
229f1ae32a1SGerd Hoffmann #define OHCI_STATUS_OCR       (1<<3)
230f1ae32a1SGerd Hoffmann #define OHCI_STATUS_SOC       ((1<<6)|(1<<7))
231f1ae32a1SGerd Hoffmann 
23200b01793SPeter Maydell #define OHCI_INTR_SO          (1U<<0) /* Scheduling overrun */
23300b01793SPeter Maydell #define OHCI_INTR_WD          (1U<<1) /* HcDoneHead writeback */
23400b01793SPeter Maydell #define OHCI_INTR_SF          (1U<<2) /* Start of frame */
23500b01793SPeter Maydell #define OHCI_INTR_RD          (1U<<3) /* Resume detect */
23600b01793SPeter Maydell #define OHCI_INTR_UE          (1U<<4) /* Unrecoverable error */
23700b01793SPeter Maydell #define OHCI_INTR_FNO         (1U<<5) /* Frame number overflow */
23800b01793SPeter Maydell #define OHCI_INTR_RHSC        (1U<<6) /* Root hub status change */
23900b01793SPeter Maydell #define OHCI_INTR_OC          (1U<<30) /* Ownership change */
24000b01793SPeter Maydell #define OHCI_INTR_MIE         (1U<<31) /* Master Interrupt Enable */
241f1ae32a1SGerd Hoffmann 
242f1ae32a1SGerd Hoffmann #define OHCI_HCCA_SIZE        0x100
243f1ae32a1SGerd Hoffmann #define OHCI_HCCA_MASK        0xffffff00
244f1ae32a1SGerd Hoffmann 
245f1ae32a1SGerd Hoffmann #define OHCI_EDPTR_MASK       0xfffffff0
246f1ae32a1SGerd Hoffmann 
247f1ae32a1SGerd Hoffmann #define OHCI_FMI_FI           0x00003fff
248f1ae32a1SGerd Hoffmann #define OHCI_FMI_FSMPS        0xffff0000
249f1ae32a1SGerd Hoffmann #define OHCI_FMI_FIT          0x80000000
250f1ae32a1SGerd Hoffmann 
25100b01793SPeter Maydell #define OHCI_FR_RT            (1U<<31)
252f1ae32a1SGerd Hoffmann 
253f1ae32a1SGerd Hoffmann #define OHCI_LS_THRESH        0x628
254f1ae32a1SGerd Hoffmann 
255f1ae32a1SGerd Hoffmann #define OHCI_RHA_RW_MASK      0x00000000 /* Mask of supported features.  */
256f1ae32a1SGerd Hoffmann #define OHCI_RHA_PSM          (1<<8)
257f1ae32a1SGerd Hoffmann #define OHCI_RHA_NPS          (1<<9)
258f1ae32a1SGerd Hoffmann #define OHCI_RHA_DT           (1<<10)
259f1ae32a1SGerd Hoffmann #define OHCI_RHA_OCPM         (1<<11)
260f1ae32a1SGerd Hoffmann #define OHCI_RHA_NOCP         (1<<12)
261f1ae32a1SGerd Hoffmann #define OHCI_RHA_POTPGT_MASK  0xff000000
262f1ae32a1SGerd Hoffmann 
26300b01793SPeter Maydell #define OHCI_RHS_LPS          (1U<<0)
26400b01793SPeter Maydell #define OHCI_RHS_OCI          (1U<<1)
26500b01793SPeter Maydell #define OHCI_RHS_DRWE         (1U<<15)
26600b01793SPeter Maydell #define OHCI_RHS_LPSC         (1U<<16)
26700b01793SPeter Maydell #define OHCI_RHS_OCIC         (1U<<17)
26800b01793SPeter Maydell #define OHCI_RHS_CRWE         (1U<<31)
269f1ae32a1SGerd Hoffmann 
270f1ae32a1SGerd Hoffmann #define OHCI_PORT_CCS         (1<<0)
271f1ae32a1SGerd Hoffmann #define OHCI_PORT_PES         (1<<1)
272f1ae32a1SGerd Hoffmann #define OHCI_PORT_PSS         (1<<2)
273f1ae32a1SGerd Hoffmann #define OHCI_PORT_POCI        (1<<3)
274f1ae32a1SGerd Hoffmann #define OHCI_PORT_PRS         (1<<4)
275f1ae32a1SGerd Hoffmann #define OHCI_PORT_PPS         (1<<8)
276f1ae32a1SGerd Hoffmann #define OHCI_PORT_LSDA        (1<<9)
277f1ae32a1SGerd Hoffmann #define OHCI_PORT_CSC         (1<<16)
278f1ae32a1SGerd Hoffmann #define OHCI_PORT_PESC        (1<<17)
279f1ae32a1SGerd Hoffmann #define OHCI_PORT_PSSC        (1<<18)
280f1ae32a1SGerd Hoffmann #define OHCI_PORT_OCIC        (1<<19)
281f1ae32a1SGerd Hoffmann #define OHCI_PORT_PRSC        (1<<20)
282f1ae32a1SGerd Hoffmann #define OHCI_PORT_WTC         (OHCI_PORT_CSC|OHCI_PORT_PESC|OHCI_PORT_PSSC \
283f1ae32a1SGerd Hoffmann                                |OHCI_PORT_OCIC|OHCI_PORT_PRSC)
284f1ae32a1SGerd Hoffmann 
285f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_SETUP     0x0
286f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_OUT       0x1
287f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_IN        0x2
288f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_RESERVED  0x3
289f1ae32a1SGerd Hoffmann 
290f1ae32a1SGerd Hoffmann #define OHCI_CC_NOERROR             0x0
291f1ae32a1SGerd Hoffmann #define OHCI_CC_CRC                 0x1
292f1ae32a1SGerd Hoffmann #define OHCI_CC_BITSTUFFING         0x2
293f1ae32a1SGerd Hoffmann #define OHCI_CC_DATATOGGLEMISMATCH  0x3
294f1ae32a1SGerd Hoffmann #define OHCI_CC_STALL               0x4
295f1ae32a1SGerd Hoffmann #define OHCI_CC_DEVICENOTRESPONDING 0x5
296f1ae32a1SGerd Hoffmann #define OHCI_CC_PIDCHECKFAILURE     0x6
297f1ae32a1SGerd Hoffmann #define OHCI_CC_UNDEXPETEDPID       0x7
298f1ae32a1SGerd Hoffmann #define OHCI_CC_DATAOVERRUN         0x8
299f1ae32a1SGerd Hoffmann #define OHCI_CC_DATAUNDERRUN        0x9
300f1ae32a1SGerd Hoffmann #define OHCI_CC_BUFFEROVERRUN       0xc
301f1ae32a1SGerd Hoffmann #define OHCI_CC_BUFFERUNDERRUN      0xd
302f1ae32a1SGerd Hoffmann 
303f1ae32a1SGerd Hoffmann #define OHCI_HRESET_FSBIR       (1 << 0)
304f1ae32a1SGerd Hoffmann 
305cf66ee8eSAlexey Kardashevskiy static void ohci_die(OHCIState *ohci);
306cf66ee8eSAlexey Kardashevskiy 
307f1ae32a1SGerd Hoffmann /* Update IRQ levels */
308f1ae32a1SGerd Hoffmann static inline void ohci_intr_update(OHCIState *ohci)
309f1ae32a1SGerd Hoffmann {
310f1ae32a1SGerd Hoffmann     int level = 0;
311f1ae32a1SGerd Hoffmann 
312f1ae32a1SGerd Hoffmann     if ((ohci->intr & OHCI_INTR_MIE) &&
313f1ae32a1SGerd Hoffmann         (ohci->intr_status & ohci->intr))
314f1ae32a1SGerd Hoffmann         level = 1;
315f1ae32a1SGerd Hoffmann 
316f1ae32a1SGerd Hoffmann     qemu_set_irq(ohci->irq, level);
317f1ae32a1SGerd Hoffmann }
318f1ae32a1SGerd Hoffmann 
319f1ae32a1SGerd Hoffmann /* Set an interrupt */
320f1ae32a1SGerd Hoffmann static inline void ohci_set_interrupt(OHCIState *ohci, uint32_t intr)
321f1ae32a1SGerd Hoffmann {
322f1ae32a1SGerd Hoffmann     ohci->intr_status |= intr;
323f1ae32a1SGerd Hoffmann     ohci_intr_update(ohci);
324f1ae32a1SGerd Hoffmann }
325f1ae32a1SGerd Hoffmann 
326f1ae32a1SGerd Hoffmann /* Attach or detach a device on a root hub port.  */
327f1ae32a1SGerd Hoffmann static void ohci_attach(USBPort *port1)
328f1ae32a1SGerd Hoffmann {
329f1ae32a1SGerd Hoffmann     OHCIState *s = port1->opaque;
330f1ae32a1SGerd Hoffmann     OHCIPort *port = &s->rhport[port1->index];
331f1ae32a1SGerd Hoffmann     uint32_t old_state = port->ctrl;
332f1ae32a1SGerd Hoffmann 
333f1ae32a1SGerd Hoffmann     /* set connect status */
334f1ae32a1SGerd Hoffmann     port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;
335f1ae32a1SGerd Hoffmann 
336f1ae32a1SGerd Hoffmann     /* update speed */
337f1ae32a1SGerd Hoffmann     if (port->port.dev->speed == USB_SPEED_LOW) {
338f1ae32a1SGerd Hoffmann         port->ctrl |= OHCI_PORT_LSDA;
339f1ae32a1SGerd Hoffmann     } else {
340f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_LSDA;
341f1ae32a1SGerd Hoffmann     }
342f1ae32a1SGerd Hoffmann 
343f1ae32a1SGerd Hoffmann     /* notify of remote-wakeup */
344f1ae32a1SGerd Hoffmann     if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
345f1ae32a1SGerd Hoffmann         ohci_set_interrupt(s, OHCI_INTR_RD);
346f1ae32a1SGerd Hoffmann     }
347f1ae32a1SGerd Hoffmann 
348dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_port_attach(port1->index);
349f1ae32a1SGerd Hoffmann 
350f1ae32a1SGerd Hoffmann     if (old_state != port->ctrl) {
351f1ae32a1SGerd Hoffmann         ohci_set_interrupt(s, OHCI_INTR_RHSC);
352f1ae32a1SGerd Hoffmann     }
353f1ae32a1SGerd Hoffmann }
354f1ae32a1SGerd Hoffmann 
355f1ae32a1SGerd Hoffmann static void ohci_detach(USBPort *port1)
356f1ae32a1SGerd Hoffmann {
357f1ae32a1SGerd Hoffmann     OHCIState *s = port1->opaque;
358f1ae32a1SGerd Hoffmann     OHCIPort *port = &s->rhport[port1->index];
359f1ae32a1SGerd Hoffmann     uint32_t old_state = port->ctrl;
360f1ae32a1SGerd Hoffmann 
361f1ae32a1SGerd Hoffmann     ohci_async_cancel_device(s, port1->dev);
362f1ae32a1SGerd Hoffmann 
363f1ae32a1SGerd Hoffmann     /* set connect status */
364f1ae32a1SGerd Hoffmann     if (port->ctrl & OHCI_PORT_CCS) {
365f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_CCS;
366f1ae32a1SGerd Hoffmann         port->ctrl |= OHCI_PORT_CSC;
367f1ae32a1SGerd Hoffmann     }
368f1ae32a1SGerd Hoffmann     /* disable port */
369f1ae32a1SGerd Hoffmann     if (port->ctrl & OHCI_PORT_PES) {
370f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_PES;
371f1ae32a1SGerd Hoffmann         port->ctrl |= OHCI_PORT_PESC;
372f1ae32a1SGerd Hoffmann     }
373dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_port_detach(port1->index);
374f1ae32a1SGerd Hoffmann 
375f1ae32a1SGerd Hoffmann     if (old_state != port->ctrl) {
376f1ae32a1SGerd Hoffmann         ohci_set_interrupt(s, OHCI_INTR_RHSC);
377f1ae32a1SGerd Hoffmann     }
378f1ae32a1SGerd Hoffmann }
379f1ae32a1SGerd Hoffmann 
380f1ae32a1SGerd Hoffmann static void ohci_wakeup(USBPort *port1)
381f1ae32a1SGerd Hoffmann {
382f1ae32a1SGerd Hoffmann     OHCIState *s = port1->opaque;
383f1ae32a1SGerd Hoffmann     OHCIPort *port = &s->rhport[port1->index];
384f1ae32a1SGerd Hoffmann     uint32_t intr = 0;
385f1ae32a1SGerd Hoffmann     if (port->ctrl & OHCI_PORT_PSS) {
386dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_port_wakeup(port1->index);
387f1ae32a1SGerd Hoffmann         port->ctrl |= OHCI_PORT_PSSC;
388f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_PSS;
389f1ae32a1SGerd Hoffmann         intr = OHCI_INTR_RHSC;
390f1ae32a1SGerd Hoffmann     }
391f1ae32a1SGerd Hoffmann     /* Note that the controller can be suspended even if this port is not */
392f1ae32a1SGerd Hoffmann     if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
393dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_remote_wakeup(s->name);
394f1ae32a1SGerd Hoffmann         /* This is the one state transition the controller can do by itself */
395f1ae32a1SGerd Hoffmann         s->ctl &= ~OHCI_CTL_HCFS;
396f1ae32a1SGerd Hoffmann         s->ctl |= OHCI_USB_RESUME;
397f1ae32a1SGerd Hoffmann         /* In suspend mode only ResumeDetected is possible, not RHSC:
398f1ae32a1SGerd Hoffmann          * see the OHCI spec 5.1.2.3.
399f1ae32a1SGerd Hoffmann          */
400f1ae32a1SGerd Hoffmann         intr = OHCI_INTR_RD;
401f1ae32a1SGerd Hoffmann     }
402f1ae32a1SGerd Hoffmann     ohci_set_interrupt(s, intr);
403f1ae32a1SGerd Hoffmann }
404f1ae32a1SGerd Hoffmann 
405f1ae32a1SGerd Hoffmann static void ohci_child_detach(USBPort *port1, USBDevice *child)
406f1ae32a1SGerd Hoffmann {
407f1ae32a1SGerd Hoffmann     OHCIState *s = port1->opaque;
408f1ae32a1SGerd Hoffmann 
409f1ae32a1SGerd Hoffmann     ohci_async_cancel_device(s, child);
410f1ae32a1SGerd Hoffmann }
411f1ae32a1SGerd Hoffmann 
412f1ae32a1SGerd Hoffmann static USBDevice *ohci_find_device(OHCIState *ohci, uint8_t addr)
413f1ae32a1SGerd Hoffmann {
414f1ae32a1SGerd Hoffmann     USBDevice *dev;
415f1ae32a1SGerd Hoffmann     int i;
416f1ae32a1SGerd Hoffmann 
417f1ae32a1SGerd Hoffmann     for (i = 0; i < ohci->num_ports; i++) {
418f1ae32a1SGerd Hoffmann         if ((ohci->rhport[i].ctrl & OHCI_PORT_PES) == 0) {
419f1ae32a1SGerd Hoffmann             continue;
420f1ae32a1SGerd Hoffmann         }
421f1ae32a1SGerd Hoffmann         dev = usb_find_device(&ohci->rhport[i].port, addr);
422f1ae32a1SGerd Hoffmann         if (dev != NULL) {
423f1ae32a1SGerd Hoffmann             return dev;
424f1ae32a1SGerd Hoffmann         }
425f1ae32a1SGerd Hoffmann     }
426f1ae32a1SGerd Hoffmann     return NULL;
427f1ae32a1SGerd Hoffmann }
428f1ae32a1SGerd Hoffmann 
429f79738b0SHans de Goede static void ohci_stop_endpoints(OHCIState *ohci)
430f79738b0SHans de Goede {
431f79738b0SHans de Goede     USBDevice *dev;
432f79738b0SHans de Goede     int i, j;
433f79738b0SHans de Goede 
434f79738b0SHans de Goede     for (i = 0; i < ohci->num_ports; i++) {
435f79738b0SHans de Goede         dev = ohci->rhport[i].port.dev;
436f79738b0SHans de Goede         if (dev && dev->attached) {
437f79738b0SHans de Goede             usb_device_ep_stopped(dev, &dev->ep_ctl);
438f79738b0SHans de Goede             for (j = 0; j < USB_MAX_ENDPOINTS; j++) {
439f79738b0SHans de Goede                 usb_device_ep_stopped(dev, &dev->ep_in[j]);
440f79738b0SHans de Goede                 usb_device_ep_stopped(dev, &dev->ep_out[j]);
441f79738b0SHans de Goede             }
442f79738b0SHans de Goede         }
443f79738b0SHans de Goede     }
444f79738b0SHans de Goede }
445f79738b0SHans de Goede 
44684d04e21SHervé Poussineau static void ohci_roothub_reset(OHCIState *ohci)
447f1ae32a1SGerd Hoffmann {
448f1ae32a1SGerd Hoffmann     OHCIPort *port;
449f1ae32a1SGerd Hoffmann     int i;
450f1ae32a1SGerd Hoffmann 
451f1ae32a1SGerd Hoffmann     ohci_bus_stop(ohci);
45284d04e21SHervé Poussineau     ohci->rhdesc_a = OHCI_RHA_NPS | ohci->num_ports;
45384d04e21SHervé Poussineau     ohci->rhdesc_b = 0x0; /* Impl. specific */
45484d04e21SHervé Poussineau     ohci->rhstatus = 0;
45584d04e21SHervé Poussineau 
45684d04e21SHervé Poussineau     for (i = 0; i < ohci->num_ports; i++) {
45784d04e21SHervé Poussineau         port = &ohci->rhport[i];
45884d04e21SHervé Poussineau         port->ctrl = 0;
45984d04e21SHervé Poussineau         if (port->port.dev && port->port.dev->attached) {
46084d04e21SHervé Poussineau             usb_port_reset(&port->port);
46184d04e21SHervé Poussineau         }
46284d04e21SHervé Poussineau     }
46384d04e21SHervé Poussineau     if (ohci->async_td) {
46484d04e21SHervé Poussineau         usb_cancel_packet(&ohci->usb_packet);
46584d04e21SHervé Poussineau         ohci->async_td = 0;
46684d04e21SHervé Poussineau     }
46784d04e21SHervé Poussineau     ohci_stop_endpoints(ohci);
46884d04e21SHervé Poussineau }
46984d04e21SHervé Poussineau 
47084d04e21SHervé Poussineau /* Reset the controller */
47184d04e21SHervé Poussineau static void ohci_soft_reset(OHCIState *ohci)
47284d04e21SHervé Poussineau {
47384d04e21SHervé Poussineau     trace_usb_ohci_reset(ohci->name);
47484d04e21SHervé Poussineau 
47584d04e21SHervé Poussineau     ohci_bus_stop(ohci);
47684d04e21SHervé Poussineau     ohci->ctl = (ohci->ctl & OHCI_CTL_IR) | OHCI_USB_SUSPEND;
477f1ae32a1SGerd Hoffmann     ohci->old_ctl = 0;
478f1ae32a1SGerd Hoffmann     ohci->status = 0;
479f1ae32a1SGerd Hoffmann     ohci->intr_status = 0;
480f1ae32a1SGerd Hoffmann     ohci->intr = OHCI_INTR_MIE;
481f1ae32a1SGerd Hoffmann 
482f1ae32a1SGerd Hoffmann     ohci->hcca = 0;
483f1ae32a1SGerd Hoffmann     ohci->ctrl_head = ohci->ctrl_cur = 0;
484f1ae32a1SGerd Hoffmann     ohci->bulk_head = ohci->bulk_cur = 0;
485f1ae32a1SGerd Hoffmann     ohci->per_cur = 0;
486f1ae32a1SGerd Hoffmann     ohci->done = 0;
487f1ae32a1SGerd Hoffmann     ohci->done_count = 7;
488f1ae32a1SGerd Hoffmann 
489f1ae32a1SGerd Hoffmann     /* FSMPS is marked TBD in OCHI 1.0, what gives ffs?
490f1ae32a1SGerd Hoffmann      * I took the value linux sets ...
491f1ae32a1SGerd Hoffmann      */
492f1ae32a1SGerd Hoffmann     ohci->fsmps = 0x2778;
493f1ae32a1SGerd Hoffmann     ohci->fi = 0x2edf;
494f1ae32a1SGerd Hoffmann     ohci->fit = 0;
495f1ae32a1SGerd Hoffmann     ohci->frt = 0;
496f1ae32a1SGerd Hoffmann     ohci->frame_number = 0;
497f1ae32a1SGerd Hoffmann     ohci->pstart = 0;
498f1ae32a1SGerd Hoffmann     ohci->lst = OHCI_LS_THRESH;
49984d04e21SHervé Poussineau }
500f1ae32a1SGerd Hoffmann 
50184d04e21SHervé Poussineau static void ohci_hard_reset(OHCIState *ohci)
502f1ae32a1SGerd Hoffmann {
50384d04e21SHervé Poussineau     ohci_soft_reset(ohci);
50484d04e21SHervé Poussineau     ohci->ctl = 0;
50584d04e21SHervé Poussineau     ohci_roothub_reset(ohci);
506f1ae32a1SGerd Hoffmann }
507f1ae32a1SGerd Hoffmann 
508f1ae32a1SGerd Hoffmann /* Get an array of dwords from main memory */
509f1ae32a1SGerd Hoffmann static inline int get_dwords(OHCIState *ohci,
5109ac6a217SDavid Gibson                              dma_addr_t addr, uint32_t *buf, int num)
511f1ae32a1SGerd Hoffmann {
512f1ae32a1SGerd Hoffmann     int i;
513f1ae32a1SGerd Hoffmann 
514f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
515f1ae32a1SGerd Hoffmann 
516f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
517cf66ee8eSAlexey Kardashevskiy         if (dma_memory_read(ohci->as, addr, buf, sizeof(*buf))) {
518cf66ee8eSAlexey Kardashevskiy             return -1;
519cf66ee8eSAlexey Kardashevskiy         }
520f1ae32a1SGerd Hoffmann         *buf = le32_to_cpu(*buf);
521f1ae32a1SGerd Hoffmann     }
522f1ae32a1SGerd Hoffmann 
523cf66ee8eSAlexey Kardashevskiy     return 0;
524f1ae32a1SGerd Hoffmann }
525f1ae32a1SGerd Hoffmann 
526f1ae32a1SGerd Hoffmann /* Put an array of dwords in to main memory */
527f1ae32a1SGerd Hoffmann static inline int put_dwords(OHCIState *ohci,
5289ac6a217SDavid Gibson                              dma_addr_t addr, uint32_t *buf, int num)
529f1ae32a1SGerd Hoffmann {
530f1ae32a1SGerd Hoffmann     int i;
531f1ae32a1SGerd Hoffmann 
532f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
533f1ae32a1SGerd Hoffmann 
534f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
535f1ae32a1SGerd Hoffmann         uint32_t tmp = cpu_to_le32(*buf);
536cf66ee8eSAlexey Kardashevskiy         if (dma_memory_write(ohci->as, addr, &tmp, sizeof(tmp))) {
537cf66ee8eSAlexey Kardashevskiy             return -1;
538cf66ee8eSAlexey Kardashevskiy         }
539f1ae32a1SGerd Hoffmann     }
540f1ae32a1SGerd Hoffmann 
541cf66ee8eSAlexey Kardashevskiy     return 0;
542f1ae32a1SGerd Hoffmann }
543f1ae32a1SGerd Hoffmann 
544f1ae32a1SGerd Hoffmann /* Get an array of words from main memory */
545f1ae32a1SGerd Hoffmann static inline int get_words(OHCIState *ohci,
5469ac6a217SDavid Gibson                             dma_addr_t addr, uint16_t *buf, int num)
547f1ae32a1SGerd Hoffmann {
548f1ae32a1SGerd Hoffmann     int i;
549f1ae32a1SGerd Hoffmann 
550f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
551f1ae32a1SGerd Hoffmann 
552f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
553cf66ee8eSAlexey Kardashevskiy         if (dma_memory_read(ohci->as, addr, buf, sizeof(*buf))) {
554cf66ee8eSAlexey Kardashevskiy             return -1;
555cf66ee8eSAlexey Kardashevskiy         }
556f1ae32a1SGerd Hoffmann         *buf = le16_to_cpu(*buf);
557f1ae32a1SGerd Hoffmann     }
558f1ae32a1SGerd Hoffmann 
559cf66ee8eSAlexey Kardashevskiy     return 0;
560f1ae32a1SGerd Hoffmann }
561f1ae32a1SGerd Hoffmann 
562f1ae32a1SGerd Hoffmann /* Put an array of words in to main memory */
563f1ae32a1SGerd Hoffmann static inline int put_words(OHCIState *ohci,
5649ac6a217SDavid Gibson                             dma_addr_t addr, uint16_t *buf, int num)
565f1ae32a1SGerd Hoffmann {
566f1ae32a1SGerd Hoffmann     int i;
567f1ae32a1SGerd Hoffmann 
568f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
569f1ae32a1SGerd Hoffmann 
570f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
571f1ae32a1SGerd Hoffmann         uint16_t tmp = cpu_to_le16(*buf);
572cf66ee8eSAlexey Kardashevskiy         if (dma_memory_write(ohci->as, addr, &tmp, sizeof(tmp))) {
573cf66ee8eSAlexey Kardashevskiy             return -1;
574cf66ee8eSAlexey Kardashevskiy         }
575f1ae32a1SGerd Hoffmann     }
576f1ae32a1SGerd Hoffmann 
577cf66ee8eSAlexey Kardashevskiy     return 0;
578f1ae32a1SGerd Hoffmann }
579f1ae32a1SGerd Hoffmann 
580f1ae32a1SGerd Hoffmann static inline int ohci_read_ed(OHCIState *ohci,
5819ac6a217SDavid Gibson                                dma_addr_t addr, struct ohci_ed *ed)
582f1ae32a1SGerd Hoffmann {
583f1ae32a1SGerd Hoffmann     return get_dwords(ohci, addr, (uint32_t *)ed, sizeof(*ed) >> 2);
584f1ae32a1SGerd Hoffmann }
585f1ae32a1SGerd Hoffmann 
586f1ae32a1SGerd Hoffmann static inline int ohci_read_td(OHCIState *ohci,
5879ac6a217SDavid Gibson                                dma_addr_t addr, struct ohci_td *td)
588f1ae32a1SGerd Hoffmann {
589f1ae32a1SGerd Hoffmann     return get_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2);
590f1ae32a1SGerd Hoffmann }
591f1ae32a1SGerd Hoffmann 
592f1ae32a1SGerd Hoffmann static inline int ohci_read_iso_td(OHCIState *ohci,
5939ac6a217SDavid Gibson                                    dma_addr_t addr, struct ohci_iso_td *td)
594f1ae32a1SGerd Hoffmann {
595cf66ee8eSAlexey Kardashevskiy     return get_dwords(ohci, addr, (uint32_t *)td, 4) ||
596cf66ee8eSAlexey Kardashevskiy            get_words(ohci, addr + 16, td->offset, 8);
597f1ae32a1SGerd Hoffmann }
598f1ae32a1SGerd Hoffmann 
599f1ae32a1SGerd Hoffmann static inline int ohci_read_hcca(OHCIState *ohci,
6009ac6a217SDavid Gibson                                  dma_addr_t addr, struct ohci_hcca *hcca)
601f1ae32a1SGerd Hoffmann {
602cf66ee8eSAlexey Kardashevskiy     return dma_memory_read(ohci->as, addr + ohci->localmem_base,
603cf66ee8eSAlexey Kardashevskiy                            hcca, sizeof(*hcca));
604f1ae32a1SGerd Hoffmann }
605f1ae32a1SGerd Hoffmann 
606f1ae32a1SGerd Hoffmann static inline int ohci_put_ed(OHCIState *ohci,
6079ac6a217SDavid Gibson                               dma_addr_t addr, struct ohci_ed *ed)
608f1ae32a1SGerd Hoffmann {
60986e18caeSWei Yang     /* ed->tail is under control of the HCD.
61086e18caeSWei Yang      * Since just ed->head is changed by HC, just write back this
61186e18caeSWei Yang      */
61286e18caeSWei Yang 
61386e18caeSWei Yang     return put_dwords(ohci, addr + ED_WBACK_OFFSET,
61486e18caeSWei Yang                       (uint32_t *)((char *)ed + ED_WBACK_OFFSET),
61586e18caeSWei Yang                       ED_WBACK_SIZE >> 2);
616f1ae32a1SGerd Hoffmann }
617f1ae32a1SGerd Hoffmann 
618f1ae32a1SGerd Hoffmann static inline int ohci_put_td(OHCIState *ohci,
6199ac6a217SDavid Gibson                               dma_addr_t addr, struct ohci_td *td)
620f1ae32a1SGerd Hoffmann {
621f1ae32a1SGerd Hoffmann     return put_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2);
622f1ae32a1SGerd Hoffmann }
623f1ae32a1SGerd Hoffmann 
624f1ae32a1SGerd Hoffmann static inline int ohci_put_iso_td(OHCIState *ohci,
6259ac6a217SDavid Gibson                                   dma_addr_t addr, struct ohci_iso_td *td)
626f1ae32a1SGerd Hoffmann {
627cae7f29cSJack Un     return put_dwords(ohci, addr, (uint32_t *)td, 4) ||
628cae7f29cSJack Un            put_words(ohci, addr + 16, td->offset, 8);
629f1ae32a1SGerd Hoffmann }
630f1ae32a1SGerd Hoffmann 
631f1ae32a1SGerd Hoffmann static inline int ohci_put_hcca(OHCIState *ohci,
6329ac6a217SDavid Gibson                                 dma_addr_t addr, struct ohci_hcca *hcca)
633f1ae32a1SGerd Hoffmann {
634cf66ee8eSAlexey Kardashevskiy     return dma_memory_write(ohci->as,
6359ac6a217SDavid Gibson                             addr + ohci->localmem_base + HCCA_WRITEBACK_OFFSET,
63686e18caeSWei Yang                             (char *)hcca + HCCA_WRITEBACK_OFFSET,
63786e18caeSWei Yang                             HCCA_WRITEBACK_SIZE);
638f1ae32a1SGerd Hoffmann }
639f1ae32a1SGerd Hoffmann 
640f1ae32a1SGerd Hoffmann /* Read/Write the contents of a TD from/to main memory.  */
641cf66ee8eSAlexey Kardashevskiy static int ohci_copy_td(OHCIState *ohci, struct ohci_td *td,
6429ac6a217SDavid Gibson                         uint8_t *buf, int len, DMADirection dir)
643f1ae32a1SGerd Hoffmann {
6449ac6a217SDavid Gibson     dma_addr_t ptr, n;
645f1ae32a1SGerd Hoffmann 
646f1ae32a1SGerd Hoffmann     ptr = td->cbp;
647f1ae32a1SGerd Hoffmann     n = 0x1000 - (ptr & 0xfff);
648f1ae32a1SGerd Hoffmann     if (n > len)
649f1ae32a1SGerd Hoffmann         n = len;
650cf66ee8eSAlexey Kardashevskiy 
651cf66ee8eSAlexey Kardashevskiy     if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, n, dir)) {
652cf66ee8eSAlexey Kardashevskiy         return -1;
653cf66ee8eSAlexey Kardashevskiy     }
654cf66ee8eSAlexey Kardashevskiy     if (n == len) {
655cf66ee8eSAlexey Kardashevskiy         return 0;
656cf66ee8eSAlexey Kardashevskiy     }
657f1ae32a1SGerd Hoffmann     ptr = td->be & ~0xfffu;
658f1ae32a1SGerd Hoffmann     buf += n;
659cf66ee8eSAlexey Kardashevskiy     if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf,
660cf66ee8eSAlexey Kardashevskiy                       len - n, dir)) {
661cf66ee8eSAlexey Kardashevskiy         return -1;
662cf66ee8eSAlexey Kardashevskiy     }
663cf66ee8eSAlexey Kardashevskiy     return 0;
664f1ae32a1SGerd Hoffmann }
665f1ae32a1SGerd Hoffmann 
666f1ae32a1SGerd Hoffmann /* Read/Write the contents of an ISO TD from/to main memory.  */
667cf66ee8eSAlexey Kardashevskiy static int ohci_copy_iso_td(OHCIState *ohci,
668f1ae32a1SGerd Hoffmann                             uint32_t start_addr, uint32_t end_addr,
6699ac6a217SDavid Gibson                             uint8_t *buf, int len, DMADirection dir)
670f1ae32a1SGerd Hoffmann {
6719ac6a217SDavid Gibson     dma_addr_t ptr, n;
672f1ae32a1SGerd Hoffmann 
673f1ae32a1SGerd Hoffmann     ptr = start_addr;
674f1ae32a1SGerd Hoffmann     n = 0x1000 - (ptr & 0xfff);
675f1ae32a1SGerd Hoffmann     if (n > len)
676f1ae32a1SGerd Hoffmann         n = len;
677cf66ee8eSAlexey Kardashevskiy 
678cf66ee8eSAlexey Kardashevskiy     if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, n, dir)) {
679cf66ee8eSAlexey Kardashevskiy         return -1;
680cf66ee8eSAlexey Kardashevskiy     }
681cf66ee8eSAlexey Kardashevskiy     if (n == len) {
682cf66ee8eSAlexey Kardashevskiy         return 0;
683cf66ee8eSAlexey Kardashevskiy     }
684f1ae32a1SGerd Hoffmann     ptr = end_addr & ~0xfffu;
685f1ae32a1SGerd Hoffmann     buf += n;
686cf66ee8eSAlexey Kardashevskiy     if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf,
687cf66ee8eSAlexey Kardashevskiy                       len - n, dir)) {
688cf66ee8eSAlexey Kardashevskiy         return -1;
689cf66ee8eSAlexey Kardashevskiy     }
690cf66ee8eSAlexey Kardashevskiy     return 0;
691f1ae32a1SGerd Hoffmann }
692f1ae32a1SGerd Hoffmann 
693f1ae32a1SGerd Hoffmann static void ohci_process_lists(OHCIState *ohci, int completion);
694f1ae32a1SGerd Hoffmann 
695f1ae32a1SGerd Hoffmann static void ohci_async_complete_packet(USBPort *port, USBPacket *packet)
696f1ae32a1SGerd Hoffmann {
697f1ae32a1SGerd Hoffmann     OHCIState *ohci = container_of(packet, OHCIState, usb_packet);
698dc1f5988SAlexey Kardashevskiy 
699dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_async_complete();
70069e25d26SAlexey Kardashevskiy     ohci->async_complete = true;
701f1ae32a1SGerd Hoffmann     ohci_process_lists(ohci, 1);
702f1ae32a1SGerd Hoffmann }
703f1ae32a1SGerd Hoffmann 
704f1ae32a1SGerd Hoffmann #define USUB(a, b) ((int16_t)((uint16_t)(a) - (uint16_t)(b)))
705f1ae32a1SGerd Hoffmann 
706f1ae32a1SGerd Hoffmann static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
707f1ae32a1SGerd Hoffmann                                int completion)
708f1ae32a1SGerd Hoffmann {
709f1ae32a1SGerd Hoffmann     int dir;
710f1ae32a1SGerd Hoffmann     size_t len = 0;
711f1ae32a1SGerd Hoffmann     const char *str = NULL;
712f1ae32a1SGerd Hoffmann     int pid;
713f1ae32a1SGerd Hoffmann     int ret;
714f1ae32a1SGerd Hoffmann     int i;
715f1ae32a1SGerd Hoffmann     USBDevice *dev;
716f1ae32a1SGerd Hoffmann     USBEndpoint *ep;
717f1ae32a1SGerd Hoffmann     struct ohci_iso_td iso_td;
718f1ae32a1SGerd Hoffmann     uint32_t addr;
719f1ae32a1SGerd Hoffmann     uint16_t starting_frame;
720f1ae32a1SGerd Hoffmann     int16_t relative_frame_number;
721f1ae32a1SGerd Hoffmann     int frame_count;
722f1ae32a1SGerd Hoffmann     uint32_t start_offset, next_offset, end_offset = 0;
723f1ae32a1SGerd Hoffmann     uint32_t start_addr, end_addr;
724f1ae32a1SGerd Hoffmann 
725f1ae32a1SGerd Hoffmann     addr = ed->head & OHCI_DPTR_MASK;
726f1ae32a1SGerd Hoffmann 
727cf66ee8eSAlexey Kardashevskiy     if (ohci_read_iso_td(ohci, addr, &iso_td)) {
728dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_read_failed(addr);
729cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
73026f670a2SLi Qiang         return 1;
731f1ae32a1SGerd Hoffmann     }
732f1ae32a1SGerd Hoffmann 
733f1ae32a1SGerd Hoffmann     starting_frame = OHCI_BM(iso_td.flags, TD_SF);
734f1ae32a1SGerd Hoffmann     frame_count = OHCI_BM(iso_td.flags, TD_FC);
735f1ae32a1SGerd Hoffmann     relative_frame_number = USUB(ohci->frame_number, starting_frame);
736f1ae32a1SGerd Hoffmann 
737dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_iso_td_head(
738f1ae32a1SGerd Hoffmann            ed->head & OHCI_DPTR_MASK, ed->tail & OHCI_DPTR_MASK,
739f1ae32a1SGerd Hoffmann            iso_td.flags, iso_td.bp, iso_td.next, iso_td.be,
740f1ae32a1SGerd Hoffmann            ohci->frame_number, starting_frame,
741bc0d104cSAlex Bennée            frame_count, relative_frame_number);
7423af8f177SAlexey Kardashevskiy     trace_usb_ohci_iso_td_head_offset(
7433af8f177SAlexey Kardashevskiy            iso_td.offset[0], iso_td.offset[1],
7443af8f177SAlexey Kardashevskiy            iso_td.offset[2], iso_td.offset[3],
7453af8f177SAlexey Kardashevskiy            iso_td.offset[4], iso_td.offset[5],
7463af8f177SAlexey Kardashevskiy            iso_td.offset[6], iso_td.offset[7]);
747f1ae32a1SGerd Hoffmann 
748f1ae32a1SGerd Hoffmann     if (relative_frame_number < 0) {
749dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_relative_frame_number_neg(relative_frame_number);
750f1ae32a1SGerd Hoffmann         return 1;
751f1ae32a1SGerd Hoffmann     } else if (relative_frame_number > frame_count) {
752f1ae32a1SGerd Hoffmann         /* ISO TD expired - retire the TD to the Done Queue and continue with
753f1ae32a1SGerd Hoffmann            the next ISO TD of the same ED */
754dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_relative_frame_number_big(relative_frame_number,
755f1ae32a1SGerd Hoffmann                                                         frame_count);
756f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_DATAOVERRUN);
757f1ae32a1SGerd Hoffmann         ed->head &= ~OHCI_DPTR_MASK;
758f1ae32a1SGerd Hoffmann         ed->head |= (iso_td.next & OHCI_DPTR_MASK);
759f1ae32a1SGerd Hoffmann         iso_td.next = ohci->done;
760f1ae32a1SGerd Hoffmann         ohci->done = addr;
761f1ae32a1SGerd Hoffmann         i = OHCI_BM(iso_td.flags, TD_DI);
762f1ae32a1SGerd Hoffmann         if (i < ohci->done_count)
763f1ae32a1SGerd Hoffmann             ohci->done_count = i;
764cf66ee8eSAlexey Kardashevskiy         if (ohci_put_iso_td(ohci, addr, &iso_td)) {
765cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
766cf66ee8eSAlexey Kardashevskiy             return 1;
767cf66ee8eSAlexey Kardashevskiy         }
768f1ae32a1SGerd Hoffmann         return 0;
769f1ae32a1SGerd Hoffmann     }
770f1ae32a1SGerd Hoffmann 
771f1ae32a1SGerd Hoffmann     dir = OHCI_BM(ed->flags, ED_D);
772f1ae32a1SGerd Hoffmann     switch (dir) {
773f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_IN:
774f1ae32a1SGerd Hoffmann         str = "in";
775f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_IN;
776f1ae32a1SGerd Hoffmann         break;
777f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_OUT:
778f1ae32a1SGerd Hoffmann         str = "out";
779f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_OUT;
780f1ae32a1SGerd Hoffmann         break;
781f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_SETUP:
782f1ae32a1SGerd Hoffmann         str = "setup";
783f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_SETUP;
784f1ae32a1SGerd Hoffmann         break;
785f1ae32a1SGerd Hoffmann     default:
786dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_bad_direction(dir);
787f1ae32a1SGerd Hoffmann         return 1;
788f1ae32a1SGerd Hoffmann     }
789f1ae32a1SGerd Hoffmann 
790f1ae32a1SGerd Hoffmann     if (!iso_td.bp || !iso_td.be) {
791dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_bad_bp_be(iso_td.bp, iso_td.be);
792f1ae32a1SGerd Hoffmann         return 1;
793f1ae32a1SGerd Hoffmann     }
794f1ae32a1SGerd Hoffmann 
795f1ae32a1SGerd Hoffmann     start_offset = iso_td.offset[relative_frame_number];
796f1ae32a1SGerd Hoffmann     next_offset = iso_td.offset[relative_frame_number + 1];
797f1ae32a1SGerd Hoffmann 
798f1ae32a1SGerd Hoffmann     if (!(OHCI_BM(start_offset, TD_PSW_CC) & 0xe) ||
799f1ae32a1SGerd Hoffmann         ((relative_frame_number < frame_count) &&
800f1ae32a1SGerd Hoffmann          !(OHCI_BM(next_offset, TD_PSW_CC) & 0xe))) {
801dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_bad_cc_not_accessed(start_offset, next_offset);
802f1ae32a1SGerd Hoffmann         return 1;
803f1ae32a1SGerd Hoffmann     }
804f1ae32a1SGerd Hoffmann 
805f1ae32a1SGerd Hoffmann     if ((relative_frame_number < frame_count) && (start_offset > next_offset)) {
806dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_bad_cc_overrun(start_offset, next_offset);
807f1ae32a1SGerd Hoffmann         return 1;
808f1ae32a1SGerd Hoffmann     }
809f1ae32a1SGerd Hoffmann 
810f1ae32a1SGerd Hoffmann     if ((start_offset & 0x1000) == 0) {
811f1ae32a1SGerd Hoffmann         start_addr = (iso_td.bp & OHCI_PAGE_MASK) |
812f1ae32a1SGerd Hoffmann             (start_offset & OHCI_OFFSET_MASK);
813f1ae32a1SGerd Hoffmann     } else {
814f1ae32a1SGerd Hoffmann         start_addr = (iso_td.be & OHCI_PAGE_MASK) |
815f1ae32a1SGerd Hoffmann             (start_offset & OHCI_OFFSET_MASK);
816f1ae32a1SGerd Hoffmann     }
817f1ae32a1SGerd Hoffmann 
818f1ae32a1SGerd Hoffmann     if (relative_frame_number < frame_count) {
819f1ae32a1SGerd Hoffmann         end_offset = next_offset - 1;
820f1ae32a1SGerd Hoffmann         if ((end_offset & 0x1000) == 0) {
821f1ae32a1SGerd Hoffmann             end_addr = (iso_td.bp & OHCI_PAGE_MASK) |
822f1ae32a1SGerd Hoffmann                 (end_offset & OHCI_OFFSET_MASK);
823f1ae32a1SGerd Hoffmann         } else {
824f1ae32a1SGerd Hoffmann             end_addr = (iso_td.be & OHCI_PAGE_MASK) |
825f1ae32a1SGerd Hoffmann                 (end_offset & OHCI_OFFSET_MASK);
826f1ae32a1SGerd Hoffmann         }
827f1ae32a1SGerd Hoffmann     } else {
828f1ae32a1SGerd Hoffmann         /* Last packet in the ISO TD */
829f1ae32a1SGerd Hoffmann         end_addr = iso_td.be;
830f1ae32a1SGerd Hoffmann     }
831f1ae32a1SGerd Hoffmann 
832f1ae32a1SGerd Hoffmann     if ((start_addr & OHCI_PAGE_MASK) != (end_addr & OHCI_PAGE_MASK)) {
833f1ae32a1SGerd Hoffmann         len = (end_addr & OHCI_OFFSET_MASK) + 0x1001
834f1ae32a1SGerd Hoffmann             - (start_addr & OHCI_OFFSET_MASK);
835f1ae32a1SGerd Hoffmann     } else {
836f1ae32a1SGerd Hoffmann         len = end_addr - start_addr + 1;
837f1ae32a1SGerd Hoffmann     }
838f1ae32a1SGerd Hoffmann 
839f1ae32a1SGerd Hoffmann     if (len && dir != OHCI_TD_DIR_IN) {
840cf66ee8eSAlexey Kardashevskiy         if (ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, len,
841cf66ee8eSAlexey Kardashevskiy                              DMA_DIRECTION_TO_DEVICE)) {
842cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
843cf66ee8eSAlexey Kardashevskiy             return 1;
844cf66ee8eSAlexey Kardashevskiy         }
845f1ae32a1SGerd Hoffmann     }
846f1ae32a1SGerd Hoffmann 
8479a77a0f5SHans de Goede     if (!completion) {
848a6fb2ddbSHans de Goede         bool int_req = relative_frame_number == frame_count &&
849a6fb2ddbSHans de Goede                        OHCI_BM(iso_td.flags, TD_DI) == 0;
850f1ae32a1SGerd Hoffmann         dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
85142340fc3SLiam Merwick         if (dev == NULL) {
85242340fc3SLiam Merwick             trace_usb_ohci_td_dev_error();
85342340fc3SLiam Merwick             return 1;
85442340fc3SLiam Merwick         }
855f1ae32a1SGerd Hoffmann         ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
8568550a02dSGerd Hoffmann         usb_packet_setup(&ohci->usb_packet, pid, ep, 0, addr, false, int_req);
857f1ae32a1SGerd Hoffmann         usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len);
8589a77a0f5SHans de Goede         usb_handle_packet(dev, &ohci->usb_packet);
8599a77a0f5SHans de Goede         if (ohci->usb_packet.status == USB_RET_ASYNC) {
86036dfe324SHans de Goede             usb_device_flush_ep_queue(dev, ep);
861f1ae32a1SGerd Hoffmann             return 1;
862f1ae32a1SGerd Hoffmann         }
863f1ae32a1SGerd Hoffmann     }
8649a77a0f5SHans de Goede     if (ohci->usb_packet.status == USB_RET_SUCCESS) {
8659a77a0f5SHans de Goede         ret = ohci->usb_packet.actual_length;
8669a77a0f5SHans de Goede     } else {
8679a77a0f5SHans de Goede         ret = ohci->usb_packet.status;
8689a77a0f5SHans de Goede     }
869f1ae32a1SGerd Hoffmann 
870dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_iso_td_so(start_offset, end_offset, start_addr, end_addr,
871dc1f5988SAlexey Kardashevskiy                              str, len, ret);
872f1ae32a1SGerd Hoffmann 
873f1ae32a1SGerd Hoffmann     /* Writeback */
874f1ae32a1SGerd Hoffmann     if (dir == OHCI_TD_DIR_IN && ret >= 0 && ret <= len) {
875f1ae32a1SGerd Hoffmann         /* IN transfer succeeded */
876cf66ee8eSAlexey Kardashevskiy         if (ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, ret,
877cf66ee8eSAlexey Kardashevskiy                              DMA_DIRECTION_FROM_DEVICE)) {
878cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
879cf66ee8eSAlexey Kardashevskiy             return 1;
880cf66ee8eSAlexey Kardashevskiy         }
881f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
882f1ae32a1SGerd Hoffmann                     OHCI_CC_NOERROR);
883f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, ret);
884f1ae32a1SGerd Hoffmann     } else if (dir == OHCI_TD_DIR_OUT && ret == len) {
885f1ae32a1SGerd Hoffmann         /* OUT transfer succeeded */
886f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
887f1ae32a1SGerd Hoffmann                     OHCI_CC_NOERROR);
888f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 0);
889f1ae32a1SGerd Hoffmann     } else {
890f1ae32a1SGerd Hoffmann         if (ret > (ssize_t) len) {
891dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_iso_td_data_overrun(ret, len);
892f1ae32a1SGerd Hoffmann             OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
893f1ae32a1SGerd Hoffmann                         OHCI_CC_DATAOVERRUN);
894f1ae32a1SGerd Hoffmann             OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
895f1ae32a1SGerd Hoffmann                         len);
896f1ae32a1SGerd Hoffmann         } else if (ret >= 0) {
897dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_iso_td_data_underrun(ret);
898f1ae32a1SGerd Hoffmann             OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
899f1ae32a1SGerd Hoffmann                         OHCI_CC_DATAUNDERRUN);
900f1ae32a1SGerd Hoffmann         } else {
901f1ae32a1SGerd Hoffmann             switch (ret) {
902f1ae32a1SGerd Hoffmann             case USB_RET_IOERROR:
903f1ae32a1SGerd Hoffmann             case USB_RET_NODEV:
904f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
905f1ae32a1SGerd Hoffmann                             OHCI_CC_DEVICENOTRESPONDING);
906f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
907f1ae32a1SGerd Hoffmann                             0);
908f1ae32a1SGerd Hoffmann                 break;
909f1ae32a1SGerd Hoffmann             case USB_RET_NAK:
910f1ae32a1SGerd Hoffmann             case USB_RET_STALL:
911dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_iso_td_nak(ret);
912f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
913f1ae32a1SGerd Hoffmann                             OHCI_CC_STALL);
914f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
915f1ae32a1SGerd Hoffmann                             0);
916f1ae32a1SGerd Hoffmann                 break;
917f1ae32a1SGerd Hoffmann             default:
918dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_iso_td_bad_response(ret);
919f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
920f1ae32a1SGerd Hoffmann                             OHCI_CC_UNDEXPETEDPID);
921f1ae32a1SGerd Hoffmann                 break;
922f1ae32a1SGerd Hoffmann             }
923f1ae32a1SGerd Hoffmann         }
924f1ae32a1SGerd Hoffmann     }
925f1ae32a1SGerd Hoffmann 
926f1ae32a1SGerd Hoffmann     if (relative_frame_number == frame_count) {
927f1ae32a1SGerd Hoffmann         /* Last data packet of ISO TD - retire the TD to the Done Queue */
928f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_NOERROR);
929f1ae32a1SGerd Hoffmann         ed->head &= ~OHCI_DPTR_MASK;
930f1ae32a1SGerd Hoffmann         ed->head |= (iso_td.next & OHCI_DPTR_MASK);
931f1ae32a1SGerd Hoffmann         iso_td.next = ohci->done;
932f1ae32a1SGerd Hoffmann         ohci->done = addr;
933f1ae32a1SGerd Hoffmann         i = OHCI_BM(iso_td.flags, TD_DI);
934f1ae32a1SGerd Hoffmann         if (i < ohci->done_count)
935f1ae32a1SGerd Hoffmann             ohci->done_count = i;
936f1ae32a1SGerd Hoffmann     }
937cf66ee8eSAlexey Kardashevskiy     if (ohci_put_iso_td(ohci, addr, &iso_td)) {
938cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
939cf66ee8eSAlexey Kardashevskiy     }
940f1ae32a1SGerd Hoffmann     return 1;
941f1ae32a1SGerd Hoffmann }
942f1ae32a1SGerd Hoffmann 
943dc1f5988SAlexey Kardashevskiy static void ohci_td_pkt(const char *msg, const uint8_t *buf, size_t len)
944dc1f5988SAlexey Kardashevskiy {
945d87aa138SStefan Hajnoczi     bool print16;
946d87aa138SStefan Hajnoczi     bool printall;
947dc1f5988SAlexey Kardashevskiy     const int width = 16;
948dc1f5988SAlexey Kardashevskiy     int i;
949dc1f5988SAlexey Kardashevskiy     char tmp[3 * width + 1];
950dc1f5988SAlexey Kardashevskiy     char *p = tmp;
951dc1f5988SAlexey Kardashevskiy 
952d87aa138SStefan Hajnoczi     print16 = !!trace_event_get_state_backends(TRACE_USB_OHCI_TD_PKT_SHORT);
953d87aa138SStefan Hajnoczi     printall = !!trace_event_get_state_backends(TRACE_USB_OHCI_TD_PKT_FULL);
954d87aa138SStefan Hajnoczi 
955dc1f5988SAlexey Kardashevskiy     if (!printall && !print16) {
956dc1f5988SAlexey Kardashevskiy         return;
957dc1f5988SAlexey Kardashevskiy     }
958dc1f5988SAlexey Kardashevskiy 
959dc1f5988SAlexey Kardashevskiy     for (i = 0; ; i++) {
960dc1f5988SAlexey Kardashevskiy         if (i && (!(i % width) || (i == len))) {
961dc1f5988SAlexey Kardashevskiy             if (!printall) {
962dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_pkt_short(msg, tmp);
963dc1f5988SAlexey Kardashevskiy                 break;
964dc1f5988SAlexey Kardashevskiy             }
965dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_td_pkt_full(msg, tmp);
966dc1f5988SAlexey Kardashevskiy             p = tmp;
967dc1f5988SAlexey Kardashevskiy             *p = 0;
968dc1f5988SAlexey Kardashevskiy         }
969dc1f5988SAlexey Kardashevskiy         if (i == len) {
970dc1f5988SAlexey Kardashevskiy             break;
971dc1f5988SAlexey Kardashevskiy         }
972dc1f5988SAlexey Kardashevskiy 
973dc1f5988SAlexey Kardashevskiy         p += sprintf(p, " %.2x", buf[i]);
974dc1f5988SAlexey Kardashevskiy     }
975dc1f5988SAlexey Kardashevskiy }
976dc1f5988SAlexey Kardashevskiy 
977f1ae32a1SGerd Hoffmann /* Service a transport descriptor.
978f1ae32a1SGerd Hoffmann    Returns nonzero to terminate processing of this endpoint.  */
979f1ae32a1SGerd Hoffmann 
980f1ae32a1SGerd Hoffmann static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
981f1ae32a1SGerd Hoffmann {
982f1ae32a1SGerd Hoffmann     int dir;
983f1ae32a1SGerd Hoffmann     size_t len = 0, pktlen = 0;
984f1ae32a1SGerd Hoffmann     const char *str = NULL;
985f1ae32a1SGerd Hoffmann     int pid;
986f1ae32a1SGerd Hoffmann     int ret;
987f1ae32a1SGerd Hoffmann     int i;
988f1ae32a1SGerd Hoffmann     USBDevice *dev;
989f1ae32a1SGerd Hoffmann     USBEndpoint *ep;
990f1ae32a1SGerd Hoffmann     struct ohci_td td;
991f1ae32a1SGerd Hoffmann     uint32_t addr;
992f1ae32a1SGerd Hoffmann     int flag_r;
993f1ae32a1SGerd Hoffmann     int completion;
994f1ae32a1SGerd Hoffmann 
995f1ae32a1SGerd Hoffmann     addr = ed->head & OHCI_DPTR_MASK;
996f1ae32a1SGerd Hoffmann     /* See if this TD has already been submitted to the device.  */
997f1ae32a1SGerd Hoffmann     completion = (addr == ohci->async_td);
998f1ae32a1SGerd Hoffmann     if (completion && !ohci->async_complete) {
999dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_td_skip_async();
1000f1ae32a1SGerd Hoffmann         return 1;
1001f1ae32a1SGerd Hoffmann     }
1002cf66ee8eSAlexey Kardashevskiy     if (ohci_read_td(ohci, addr, &td)) {
1003dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_td_read_error(addr);
1004cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
10056ebc069dSLi Qiang         return 1;
1006f1ae32a1SGerd Hoffmann     }
1007f1ae32a1SGerd Hoffmann 
1008f1ae32a1SGerd Hoffmann     dir = OHCI_BM(ed->flags, ED_D);
1009f1ae32a1SGerd Hoffmann     switch (dir) {
1010f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_OUT:
1011f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_IN:
1012f1ae32a1SGerd Hoffmann         /* Same value.  */
1013f1ae32a1SGerd Hoffmann         break;
1014f1ae32a1SGerd Hoffmann     default:
1015f1ae32a1SGerd Hoffmann         dir = OHCI_BM(td.flags, TD_DP);
1016f1ae32a1SGerd Hoffmann         break;
1017f1ae32a1SGerd Hoffmann     }
1018f1ae32a1SGerd Hoffmann 
1019f1ae32a1SGerd Hoffmann     switch (dir) {
1020f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_IN:
1021f1ae32a1SGerd Hoffmann         str = "in";
1022f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_IN;
1023f1ae32a1SGerd Hoffmann         break;
1024f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_OUT:
1025f1ae32a1SGerd Hoffmann         str = "out";
1026f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_OUT;
1027f1ae32a1SGerd Hoffmann         break;
1028f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_SETUP:
1029f1ae32a1SGerd Hoffmann         str = "setup";
1030f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_SETUP;
1031f1ae32a1SGerd Hoffmann         break;
1032f1ae32a1SGerd Hoffmann     default:
1033dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_td_bad_direction(dir);
1034f1ae32a1SGerd Hoffmann         return 1;
1035f1ae32a1SGerd Hoffmann     }
1036f1ae32a1SGerd Hoffmann     if (td.cbp && td.be) {
1037f1ae32a1SGerd Hoffmann         if ((td.cbp & 0xfffff000) != (td.be & 0xfffff000)) {
1038f1ae32a1SGerd Hoffmann             len = (td.be & 0xfff) + 0x1001 - (td.cbp & 0xfff);
1039f1ae32a1SGerd Hoffmann         } else {
1040f1ae32a1SGerd Hoffmann             len = (td.be - td.cbp) + 1;
1041f1ae32a1SGerd Hoffmann         }
1042f1ae32a1SGerd Hoffmann 
1043f1ae32a1SGerd Hoffmann         pktlen = len;
1044f1ae32a1SGerd Hoffmann         if (len && dir != OHCI_TD_DIR_IN) {
1045f1ae32a1SGerd Hoffmann             /* The endpoint may not allow us to transfer it all now */
1046f1ae32a1SGerd Hoffmann             pktlen = (ed->flags & OHCI_ED_MPS_MASK) >> OHCI_ED_MPS_SHIFT;
1047f1ae32a1SGerd Hoffmann             if (pktlen > len) {
1048f1ae32a1SGerd Hoffmann                 pktlen = len;
1049f1ae32a1SGerd Hoffmann             }
1050f1ae32a1SGerd Hoffmann             if (!completion) {
1051cf66ee8eSAlexey Kardashevskiy                 if (ohci_copy_td(ohci, &td, ohci->usb_buf, pktlen,
1052cf66ee8eSAlexey Kardashevskiy                                  DMA_DIRECTION_TO_DEVICE)) {
1053cf66ee8eSAlexey Kardashevskiy                     ohci_die(ohci);
1054cf66ee8eSAlexey Kardashevskiy                 }
1055f1ae32a1SGerd Hoffmann             }
1056f1ae32a1SGerd Hoffmann         }
1057f1ae32a1SGerd Hoffmann     }
1058f1ae32a1SGerd Hoffmann 
1059f1ae32a1SGerd Hoffmann     flag_r = (td.flags & OHCI_TD_R) != 0;
1060dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_td_pkt_hdr(addr, (int64_t)pktlen, (int64_t)len, str,
1061dc1f5988SAlexey Kardashevskiy                               flag_r, td.cbp, td.be);
1062dc1f5988SAlexey Kardashevskiy     ohci_td_pkt("OUT", ohci->usb_buf, pktlen);
1063f1ae32a1SGerd Hoffmann 
1064f1ae32a1SGerd Hoffmann     if (completion) {
1065f1ae32a1SGerd Hoffmann         ohci->async_td = 0;
106669e25d26SAlexey Kardashevskiy         ohci->async_complete = false;
1067f1ae32a1SGerd Hoffmann     } else {
1068f1ae32a1SGerd Hoffmann         if (ohci->async_td) {
1069f1ae32a1SGerd Hoffmann             /* ??? The hardware should allow one active packet per
1070f1ae32a1SGerd Hoffmann                endpoint.  We only allow one active packet per controller.
1071f1ae32a1SGerd Hoffmann                This should be sufficient as long as devices respond in a
1072f1ae32a1SGerd Hoffmann                timely manner.
1073f1ae32a1SGerd Hoffmann             */
1074dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_td_too_many_pending();
1075f1ae32a1SGerd Hoffmann             return 1;
1076f1ae32a1SGerd Hoffmann         }
1077f1ae32a1SGerd Hoffmann         dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
107842340fc3SLiam Merwick         if (dev == NULL) {
107942340fc3SLiam Merwick             trace_usb_ohci_td_dev_error();
108042340fc3SLiam Merwick             return 1;
108142340fc3SLiam Merwick         }
1082f1ae32a1SGerd Hoffmann         ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
10838550a02dSGerd Hoffmann         usb_packet_setup(&ohci->usb_packet, pid, ep, 0, addr, !flag_r,
1084a6fb2ddbSHans de Goede                          OHCI_BM(td.flags, TD_DI) == 0);
1085f1ae32a1SGerd Hoffmann         usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen);
10869a77a0f5SHans de Goede         usb_handle_packet(dev, &ohci->usb_packet);
1087dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_td_packet_status(ohci->usb_packet.status);
1088dc1f5988SAlexey Kardashevskiy 
10899a77a0f5SHans de Goede         if (ohci->usb_packet.status == USB_RET_ASYNC) {
109036dfe324SHans de Goede             usb_device_flush_ep_queue(dev, ep);
1091f1ae32a1SGerd Hoffmann             ohci->async_td = addr;
1092f1ae32a1SGerd Hoffmann             return 1;
1093f1ae32a1SGerd Hoffmann         }
1094f1ae32a1SGerd Hoffmann     }
10959a77a0f5SHans de Goede     if (ohci->usb_packet.status == USB_RET_SUCCESS) {
10969a77a0f5SHans de Goede         ret = ohci->usb_packet.actual_length;
10979a77a0f5SHans de Goede     } else {
10989a77a0f5SHans de Goede         ret = ohci->usb_packet.status;
10999a77a0f5SHans de Goede     }
11009a77a0f5SHans de Goede 
1101f1ae32a1SGerd Hoffmann     if (ret >= 0) {
1102f1ae32a1SGerd Hoffmann         if (dir == OHCI_TD_DIR_IN) {
1103cf66ee8eSAlexey Kardashevskiy             if (ohci_copy_td(ohci, &td, ohci->usb_buf, ret,
1104cf66ee8eSAlexey Kardashevskiy                              DMA_DIRECTION_FROM_DEVICE)) {
1105cf66ee8eSAlexey Kardashevskiy                 ohci_die(ohci);
1106cf66ee8eSAlexey Kardashevskiy             }
1107dc1f5988SAlexey Kardashevskiy             ohci_td_pkt("IN", ohci->usb_buf, pktlen);
1108f1ae32a1SGerd Hoffmann         } else {
1109f1ae32a1SGerd Hoffmann             ret = pktlen;
1110f1ae32a1SGerd Hoffmann         }
1111f1ae32a1SGerd Hoffmann     }
1112f1ae32a1SGerd Hoffmann 
1113f1ae32a1SGerd Hoffmann     /* Writeback */
1114f1ae32a1SGerd Hoffmann     if (ret == pktlen || (dir == OHCI_TD_DIR_IN && ret >= 0 && flag_r)) {
1115f1ae32a1SGerd Hoffmann         /* Transmission succeeded.  */
1116f1ae32a1SGerd Hoffmann         if (ret == len) {
1117f1ae32a1SGerd Hoffmann             td.cbp = 0;
1118f1ae32a1SGerd Hoffmann         } else {
1119f1ae32a1SGerd Hoffmann             if ((td.cbp & 0xfff) + ret > 0xfff) {
1120f1ae32a1SGerd Hoffmann                 td.cbp = (td.be & ~0xfff) + ((td.cbp + ret) & 0xfff);
1121f1ae32a1SGerd Hoffmann             } else {
1122f1ae32a1SGerd Hoffmann                 td.cbp += ret;
1123f1ae32a1SGerd Hoffmann             }
1124f1ae32a1SGerd Hoffmann         }
1125f1ae32a1SGerd Hoffmann         td.flags |= OHCI_TD_T1;
1126f1ae32a1SGerd Hoffmann         td.flags ^= OHCI_TD_T0;
1127f1ae32a1SGerd Hoffmann         OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_NOERROR);
1128f1ae32a1SGerd Hoffmann         OHCI_SET_BM(td.flags, TD_EC, 0);
1129f1ae32a1SGerd Hoffmann 
1130f1ae32a1SGerd Hoffmann         if ((dir != OHCI_TD_DIR_IN) && (ret != len)) {
1131f1ae32a1SGerd Hoffmann             /* Partial packet transfer: TD not ready to retire yet */
1132f1ae32a1SGerd Hoffmann             goto exit_no_retire;
1133f1ae32a1SGerd Hoffmann         }
1134f1ae32a1SGerd Hoffmann 
1135f1ae32a1SGerd Hoffmann         /* Setting ED_C is part of the TD retirement process */
1136f1ae32a1SGerd Hoffmann         ed->head &= ~OHCI_ED_C;
1137f1ae32a1SGerd Hoffmann         if (td.flags & OHCI_TD_T0)
1138f1ae32a1SGerd Hoffmann             ed->head |= OHCI_ED_C;
1139f1ae32a1SGerd Hoffmann     } else {
1140f1ae32a1SGerd Hoffmann         if (ret >= 0) {
1141dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_td_underrun();
1142f1ae32a1SGerd Hoffmann             OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAUNDERRUN);
1143f1ae32a1SGerd Hoffmann         } else {
1144f1ae32a1SGerd Hoffmann             switch (ret) {
1145f1ae32a1SGerd Hoffmann             case USB_RET_IOERROR:
1146f1ae32a1SGerd Hoffmann             case USB_RET_NODEV:
1147dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_dev_error();
1148f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DEVICENOTRESPONDING);
11494b351a0fSJán Veselý                 break;
1150f1ae32a1SGerd Hoffmann             case USB_RET_NAK:
1151dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_nak();
1152f1ae32a1SGerd Hoffmann                 return 1;
1153f1ae32a1SGerd Hoffmann             case USB_RET_STALL:
1154dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_stall();
1155f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_STALL);
1156f1ae32a1SGerd Hoffmann                 break;
1157f1ae32a1SGerd Hoffmann             case USB_RET_BABBLE:
1158dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_babble();
1159f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAOVERRUN);
1160f1ae32a1SGerd Hoffmann                 break;
1161f1ae32a1SGerd Hoffmann             default:
1162dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_bad_device_response(ret);
1163f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_UNDEXPETEDPID);
1164f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_EC, 3);
1165f1ae32a1SGerd Hoffmann                 break;
1166f1ae32a1SGerd Hoffmann             }
11677c48b95dSSebastian Bauer             /* An error occured so we have to clear the interrupt counter. See
11687c48b95dSSebastian Bauer              * spec at 6.4.4 on page 104 */
11697c48b95dSSebastian Bauer             ohci->done_count = 0;
1170f1ae32a1SGerd Hoffmann         }
1171f1ae32a1SGerd Hoffmann         ed->head |= OHCI_ED_H;
1172f1ae32a1SGerd Hoffmann     }
1173f1ae32a1SGerd Hoffmann 
1174f1ae32a1SGerd Hoffmann     /* Retire this TD */
1175f1ae32a1SGerd Hoffmann     ed->head &= ~OHCI_DPTR_MASK;
1176f1ae32a1SGerd Hoffmann     ed->head |= td.next & OHCI_DPTR_MASK;
1177f1ae32a1SGerd Hoffmann     td.next = ohci->done;
1178f1ae32a1SGerd Hoffmann     ohci->done = addr;
1179f1ae32a1SGerd Hoffmann     i = OHCI_BM(td.flags, TD_DI);
1180f1ae32a1SGerd Hoffmann     if (i < ohci->done_count)
1181f1ae32a1SGerd Hoffmann         ohci->done_count = i;
1182f1ae32a1SGerd Hoffmann exit_no_retire:
1183cf66ee8eSAlexey Kardashevskiy     if (ohci_put_td(ohci, addr, &td)) {
1184cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
1185cf66ee8eSAlexey Kardashevskiy         return 1;
1186cf66ee8eSAlexey Kardashevskiy     }
1187f1ae32a1SGerd Hoffmann     return OHCI_BM(td.flags, TD_CC) != OHCI_CC_NOERROR;
1188f1ae32a1SGerd Hoffmann }
1189f1ae32a1SGerd Hoffmann 
1190f1ae32a1SGerd Hoffmann /* Service an endpoint list.  Returns nonzero if active TD were found.  */
1191f1ae32a1SGerd Hoffmann static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion)
1192f1ae32a1SGerd Hoffmann {
1193f1ae32a1SGerd Hoffmann     struct ohci_ed ed;
1194f1ae32a1SGerd Hoffmann     uint32_t next_ed;
1195f1ae32a1SGerd Hoffmann     uint32_t cur;
1196f1ae32a1SGerd Hoffmann     int active;
119795ed5693SLi Qiang     uint32_t link_cnt = 0;
1198f1ae32a1SGerd Hoffmann     active = 0;
1199f1ae32a1SGerd Hoffmann 
1200f1ae32a1SGerd Hoffmann     if (head == 0)
1201f1ae32a1SGerd Hoffmann         return 0;
1202f1ae32a1SGerd Hoffmann 
1203*ab878998SLaurent Vivier     for (cur = head; cur && link_cnt++ < ED_LINK_LIMIT; cur = next_ed) {
1204cf66ee8eSAlexey Kardashevskiy         if (ohci_read_ed(ohci, cur, &ed)) {
1205dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_ed_read_error(cur);
1206cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
1207f1ae32a1SGerd Hoffmann             return 0;
1208f1ae32a1SGerd Hoffmann         }
1209f1ae32a1SGerd Hoffmann 
1210f1ae32a1SGerd Hoffmann         next_ed = ed.next & OHCI_DPTR_MASK;
1211f1ae32a1SGerd Hoffmann 
1212f1ae32a1SGerd Hoffmann         if ((ed.head & OHCI_ED_H) || (ed.flags & OHCI_ED_K)) {
1213f1ae32a1SGerd Hoffmann             uint32_t addr;
1214f1ae32a1SGerd Hoffmann             /* Cancel pending packets for ED that have been paused.  */
1215f1ae32a1SGerd Hoffmann             addr = ed.head & OHCI_DPTR_MASK;
1216f1ae32a1SGerd Hoffmann             if (ohci->async_td && addr == ohci->async_td) {
1217f1ae32a1SGerd Hoffmann                 usb_cancel_packet(&ohci->usb_packet);
1218f1ae32a1SGerd Hoffmann                 ohci->async_td = 0;
1219f79738b0SHans de Goede                 usb_device_ep_stopped(ohci->usb_packet.ep->dev,
1220f79738b0SHans de Goede                                       ohci->usb_packet.ep);
1221f1ae32a1SGerd Hoffmann             }
1222f1ae32a1SGerd Hoffmann             continue;
1223f1ae32a1SGerd Hoffmann         }
1224f1ae32a1SGerd Hoffmann 
1225f1ae32a1SGerd Hoffmann         while ((ed.head & OHCI_DPTR_MASK) != ed.tail) {
12263af8f177SAlexey Kardashevskiy             trace_usb_ohci_ed_pkt(cur, (ed.head & OHCI_ED_H) != 0,
12273af8f177SAlexey Kardashevskiy                     (ed.head & OHCI_ED_C) != 0, ed.head & OHCI_DPTR_MASK,
12283af8f177SAlexey Kardashevskiy                     ed.tail & OHCI_DPTR_MASK, ed.next & OHCI_DPTR_MASK);
12293af8f177SAlexey Kardashevskiy             trace_usb_ohci_ed_pkt_flags(
1230f1ae32a1SGerd Hoffmann                     OHCI_BM(ed.flags, ED_FA), OHCI_BM(ed.flags, ED_EN),
1231f1ae32a1SGerd Hoffmann                     OHCI_BM(ed.flags, ED_D), (ed.flags & OHCI_ED_S)!= 0,
1232f1ae32a1SGerd Hoffmann                     (ed.flags & OHCI_ED_K) != 0, (ed.flags & OHCI_ED_F) != 0,
12333af8f177SAlexey Kardashevskiy                     OHCI_BM(ed.flags, ED_MPS));
1234dc1f5988SAlexey Kardashevskiy 
1235f1ae32a1SGerd Hoffmann             active = 1;
1236f1ae32a1SGerd Hoffmann 
1237f1ae32a1SGerd Hoffmann             if ((ed.flags & OHCI_ED_F) == 0) {
1238f1ae32a1SGerd Hoffmann                 if (ohci_service_td(ohci, &ed))
1239f1ae32a1SGerd Hoffmann                     break;
1240f1ae32a1SGerd Hoffmann             } else {
1241f1ae32a1SGerd Hoffmann                 /* Handle isochronous endpoints */
1242f1ae32a1SGerd Hoffmann                 if (ohci_service_iso_td(ohci, &ed, completion))
1243f1ae32a1SGerd Hoffmann                     break;
1244f1ae32a1SGerd Hoffmann             }
1245f1ae32a1SGerd Hoffmann         }
1246f1ae32a1SGerd Hoffmann 
1247cf66ee8eSAlexey Kardashevskiy         if (ohci_put_ed(ohci, cur, &ed)) {
1248cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
1249cf66ee8eSAlexey Kardashevskiy             return 0;
1250cf66ee8eSAlexey Kardashevskiy         }
1251f1ae32a1SGerd Hoffmann     }
1252f1ae32a1SGerd Hoffmann 
1253f1ae32a1SGerd Hoffmann     return active;
1254f1ae32a1SGerd Hoffmann }
1255f1ae32a1SGerd Hoffmann 
1256fd0a10cdSLaurent Vivier /* set a timer for EOF */
1257fd0a10cdSLaurent Vivier static void ohci_eof_timer(OHCIState *ohci)
1258f1ae32a1SGerd Hoffmann {
1259bc72ad67SAlex Bligh     timer_mod(ohci->eof_timer, ohci->sof_time + usb_frame_time);
1260fd0a10cdSLaurent Vivier }
1261fd0a10cdSLaurent Vivier /* Set a timer for EOF and generate a SOF event */
1262fd0a10cdSLaurent Vivier static void ohci_sof(OHCIState *ohci)
1263fd0a10cdSLaurent Vivier {
1264a60f39a4SMiguel GAIO     ohci->sof_time += usb_frame_time;
1265fd0a10cdSLaurent Vivier     ohci_eof_timer(ohci);
1266f1ae32a1SGerd Hoffmann     ohci_set_interrupt(ohci, OHCI_INTR_SF);
1267f1ae32a1SGerd Hoffmann }
1268f1ae32a1SGerd Hoffmann 
1269f1ae32a1SGerd Hoffmann /* Process Control and Bulk lists.  */
1270f1ae32a1SGerd Hoffmann static void ohci_process_lists(OHCIState *ohci, int completion)
1271f1ae32a1SGerd Hoffmann {
1272f1ae32a1SGerd Hoffmann     if ((ohci->ctl & OHCI_CTL_CLE) && (ohci->status & OHCI_STATUS_CLF)) {
1273f1ae32a1SGerd Hoffmann         if (ohci->ctrl_cur && ohci->ctrl_cur != ohci->ctrl_head) {
1274dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_process_lists(ohci->ctrl_head, ohci->ctrl_cur);
1275f1ae32a1SGerd Hoffmann         }
1276f1ae32a1SGerd Hoffmann         if (!ohci_service_ed_list(ohci, ohci->ctrl_head, completion)) {
1277f1ae32a1SGerd Hoffmann             ohci->ctrl_cur = 0;
1278f1ae32a1SGerd Hoffmann             ohci->status &= ~OHCI_STATUS_CLF;
1279f1ae32a1SGerd Hoffmann         }
1280f1ae32a1SGerd Hoffmann     }
1281f1ae32a1SGerd Hoffmann 
1282f1ae32a1SGerd Hoffmann     if ((ohci->ctl & OHCI_CTL_BLE) && (ohci->status & OHCI_STATUS_BLF)) {
1283f1ae32a1SGerd Hoffmann         if (!ohci_service_ed_list(ohci, ohci->bulk_head, completion)) {
1284f1ae32a1SGerd Hoffmann             ohci->bulk_cur = 0;
1285f1ae32a1SGerd Hoffmann             ohci->status &= ~OHCI_STATUS_BLF;
1286f1ae32a1SGerd Hoffmann         }
1287f1ae32a1SGerd Hoffmann     }
1288f1ae32a1SGerd Hoffmann }
1289f1ae32a1SGerd Hoffmann 
1290f1ae32a1SGerd Hoffmann /* Do frame processing on frame boundary */
1291f1ae32a1SGerd Hoffmann static void ohci_frame_boundary(void *opaque)
1292f1ae32a1SGerd Hoffmann {
1293f1ae32a1SGerd Hoffmann     OHCIState *ohci = opaque;
1294f1ae32a1SGerd Hoffmann     struct ohci_hcca hcca;
1295f1ae32a1SGerd Hoffmann 
1296cf66ee8eSAlexey Kardashevskiy     if (ohci_read_hcca(ohci, ohci->hcca, &hcca)) {
1297dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_hcca_read_error(ohci->hcca);
1298cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
1299cf66ee8eSAlexey Kardashevskiy         return;
1300cf66ee8eSAlexey Kardashevskiy     }
1301f1ae32a1SGerd Hoffmann 
1302f1ae32a1SGerd Hoffmann     /* Process all the lists at the end of the frame */
1303f1ae32a1SGerd Hoffmann     if (ohci->ctl & OHCI_CTL_PLE) {
1304f1ae32a1SGerd Hoffmann         int n;
1305f1ae32a1SGerd Hoffmann 
1306f1ae32a1SGerd Hoffmann         n = ohci->frame_number & 0x1f;
1307f1ae32a1SGerd Hoffmann         ohci_service_ed_list(ohci, le32_to_cpu(hcca.intr[n]), 0);
1308f1ae32a1SGerd Hoffmann     }
1309f1ae32a1SGerd Hoffmann 
1310f1ae32a1SGerd Hoffmann     /* Cancel all pending packets if either of the lists has been disabled.  */
1311f79738b0SHans de Goede     if (ohci->old_ctl & (~ohci->ctl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) {
1312f79738b0SHans de Goede         if (ohci->async_td) {
1313f1ae32a1SGerd Hoffmann             usb_cancel_packet(&ohci->usb_packet);
1314f1ae32a1SGerd Hoffmann             ohci->async_td = 0;
1315f1ae32a1SGerd Hoffmann         }
1316f79738b0SHans de Goede         ohci_stop_endpoints(ohci);
1317f79738b0SHans de Goede     }
1318f1ae32a1SGerd Hoffmann     ohci->old_ctl = ohci->ctl;
1319f1ae32a1SGerd Hoffmann     ohci_process_lists(ohci, 0);
1320f1ae32a1SGerd Hoffmann 
1321cf66ee8eSAlexey Kardashevskiy     /* Stop if UnrecoverableError happened or ohci_sof will crash */
1322cf66ee8eSAlexey Kardashevskiy     if (ohci->intr_status & OHCI_INTR_UE) {
1323cf66ee8eSAlexey Kardashevskiy         return;
1324cf66ee8eSAlexey Kardashevskiy     }
1325cf66ee8eSAlexey Kardashevskiy 
1326f1ae32a1SGerd Hoffmann     /* Frame boundary, so do EOF stuf here */
1327f1ae32a1SGerd Hoffmann     ohci->frt = ohci->fit;
1328f1ae32a1SGerd Hoffmann 
1329f1ae32a1SGerd Hoffmann     /* Increment frame number and take care of endianness. */
1330f1ae32a1SGerd Hoffmann     ohci->frame_number = (ohci->frame_number + 1) & 0xffff;
1331f1ae32a1SGerd Hoffmann     hcca.frame = cpu_to_le16(ohci->frame_number);
1332f1ae32a1SGerd Hoffmann 
1333f1ae32a1SGerd Hoffmann     if (ohci->done_count == 0 && !(ohci->intr_status & OHCI_INTR_WD)) {
1334f1ae32a1SGerd Hoffmann         if (!ohci->done)
1335f1ae32a1SGerd Hoffmann             abort();
1336f1ae32a1SGerd Hoffmann         if (ohci->intr & ohci->intr_status)
1337f1ae32a1SGerd Hoffmann             ohci->done |= 1;
1338f1ae32a1SGerd Hoffmann         hcca.done = cpu_to_le32(ohci->done);
1339f1ae32a1SGerd Hoffmann         ohci->done = 0;
1340f1ae32a1SGerd Hoffmann         ohci->done_count = 7;
1341f1ae32a1SGerd Hoffmann         ohci_set_interrupt(ohci, OHCI_INTR_WD);
1342f1ae32a1SGerd Hoffmann     }
1343f1ae32a1SGerd Hoffmann 
1344f1ae32a1SGerd Hoffmann     if (ohci->done_count != 7 && ohci->done_count != 0)
1345f1ae32a1SGerd Hoffmann         ohci->done_count--;
1346f1ae32a1SGerd Hoffmann 
1347f1ae32a1SGerd Hoffmann     /* Do SOF stuff here */
1348f1ae32a1SGerd Hoffmann     ohci_sof(ohci);
1349f1ae32a1SGerd Hoffmann 
1350f1ae32a1SGerd Hoffmann     /* Writeback HCCA */
1351cf66ee8eSAlexey Kardashevskiy     if (ohci_put_hcca(ohci, ohci->hcca, &hcca)) {
1352cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
1353cf66ee8eSAlexey Kardashevskiy     }
1354f1ae32a1SGerd Hoffmann }
1355f1ae32a1SGerd Hoffmann 
1356f1ae32a1SGerd Hoffmann /* Start sending SOF tokens across the USB bus, lists are processed in
1357f1ae32a1SGerd Hoffmann  * next frame
1358f1ae32a1SGerd Hoffmann  */
1359f1ae32a1SGerd Hoffmann static int ohci_bus_start(OHCIState *ohci)
1360f1ae32a1SGerd Hoffmann {
1361dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_start(ohci->name);
1362f1ae32a1SGerd Hoffmann 
1363fd0a10cdSLaurent Vivier     /* Delay the first SOF event by one frame time as
1364fd0a10cdSLaurent Vivier      * linux driver is not ready to receive it and
1365fd0a10cdSLaurent Vivier      * can meet some race conditions
1366fd0a10cdSLaurent Vivier      */
1367fd0a10cdSLaurent Vivier 
1368a60f39a4SMiguel GAIO     ohci->sof_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
1369fd0a10cdSLaurent Vivier     ohci_eof_timer(ohci);
1370f1ae32a1SGerd Hoffmann 
1371f1ae32a1SGerd Hoffmann     return 1;
1372f1ae32a1SGerd Hoffmann }
1373f1ae32a1SGerd Hoffmann 
1374f1ae32a1SGerd Hoffmann /* Stop sending SOF tokens on the bus */
1375f1ae32a1SGerd Hoffmann static void ohci_bus_stop(OHCIState *ohci)
1376f1ae32a1SGerd Hoffmann {
1377dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_stop(ohci->name);
1378bc72ad67SAlex Bligh     timer_del(ohci->eof_timer);
1379f1ae32a1SGerd Hoffmann }
1380f1ae32a1SGerd Hoffmann 
1381f1ae32a1SGerd Hoffmann /* Sets a flag in a port status register but only set it if the port is
1382f1ae32a1SGerd Hoffmann  * connected, if not set ConnectStatusChange flag. If flag is enabled
1383f1ae32a1SGerd Hoffmann  * return 1.
1384f1ae32a1SGerd Hoffmann  */
1385f1ae32a1SGerd Hoffmann static int ohci_port_set_if_connected(OHCIState *ohci, int i, uint32_t val)
1386f1ae32a1SGerd Hoffmann {
1387f1ae32a1SGerd Hoffmann     int ret = 1;
1388f1ae32a1SGerd Hoffmann 
1389f1ae32a1SGerd Hoffmann     /* writing a 0 has no effect */
1390f1ae32a1SGerd Hoffmann     if (val == 0)
1391f1ae32a1SGerd Hoffmann         return 0;
1392f1ae32a1SGerd Hoffmann 
1393f1ae32a1SGerd Hoffmann     /* If CurrentConnectStatus is cleared we set
1394f1ae32a1SGerd Hoffmann      * ConnectStatusChange
1395f1ae32a1SGerd Hoffmann      */
1396f1ae32a1SGerd Hoffmann     if (!(ohci->rhport[i].ctrl & OHCI_PORT_CCS)) {
1397f1ae32a1SGerd Hoffmann         ohci->rhport[i].ctrl |= OHCI_PORT_CSC;
1398f1ae32a1SGerd Hoffmann         if (ohci->rhstatus & OHCI_RHS_DRWE) {
1399f1ae32a1SGerd Hoffmann             /* TODO: CSC is a wakeup event */
1400f1ae32a1SGerd Hoffmann         }
1401f1ae32a1SGerd Hoffmann         return 0;
1402f1ae32a1SGerd Hoffmann     }
1403f1ae32a1SGerd Hoffmann 
1404f1ae32a1SGerd Hoffmann     if (ohci->rhport[i].ctrl & val)
1405f1ae32a1SGerd Hoffmann         ret = 0;
1406f1ae32a1SGerd Hoffmann 
1407f1ae32a1SGerd Hoffmann     /* set the bit */
1408f1ae32a1SGerd Hoffmann     ohci->rhport[i].ctrl |= val;
1409f1ae32a1SGerd Hoffmann 
1410f1ae32a1SGerd Hoffmann     return ret;
1411f1ae32a1SGerd Hoffmann }
1412f1ae32a1SGerd Hoffmann 
1413f1ae32a1SGerd Hoffmann /* Set the frame interval - frame interval toggle is manipulated by the hcd only */
1414f1ae32a1SGerd Hoffmann static void ohci_set_frame_interval(OHCIState *ohci, uint16_t val)
1415f1ae32a1SGerd Hoffmann {
1416f1ae32a1SGerd Hoffmann     val &= OHCI_FMI_FI;
1417f1ae32a1SGerd Hoffmann 
1418f1ae32a1SGerd Hoffmann     if (val != ohci->fi) {
1419dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_set_frame_interval(ohci->name, ohci->fi, ohci->fi);
1420f1ae32a1SGerd Hoffmann     }
1421f1ae32a1SGerd Hoffmann 
1422f1ae32a1SGerd Hoffmann     ohci->fi = val;
1423f1ae32a1SGerd Hoffmann }
1424f1ae32a1SGerd Hoffmann 
1425f1ae32a1SGerd Hoffmann static void ohci_port_power(OHCIState *ohci, int i, int p)
1426f1ae32a1SGerd Hoffmann {
1427f1ae32a1SGerd Hoffmann     if (p) {
1428f1ae32a1SGerd Hoffmann         ohci->rhport[i].ctrl |= OHCI_PORT_PPS;
1429f1ae32a1SGerd Hoffmann     } else {
1430f1ae32a1SGerd Hoffmann         ohci->rhport[i].ctrl &= ~(OHCI_PORT_PPS|
1431f1ae32a1SGerd Hoffmann                     OHCI_PORT_CCS|
1432f1ae32a1SGerd Hoffmann                     OHCI_PORT_PSS|
1433f1ae32a1SGerd Hoffmann                     OHCI_PORT_PRS);
1434f1ae32a1SGerd Hoffmann     }
1435f1ae32a1SGerd Hoffmann }
1436f1ae32a1SGerd Hoffmann 
1437f1ae32a1SGerd Hoffmann /* Set HcControlRegister */
1438f1ae32a1SGerd Hoffmann static void ohci_set_ctl(OHCIState *ohci, uint32_t val)
1439f1ae32a1SGerd Hoffmann {
1440f1ae32a1SGerd Hoffmann     uint32_t old_state;
1441f1ae32a1SGerd Hoffmann     uint32_t new_state;
1442f1ae32a1SGerd Hoffmann 
1443f1ae32a1SGerd Hoffmann     old_state = ohci->ctl & OHCI_CTL_HCFS;
1444f1ae32a1SGerd Hoffmann     ohci->ctl = val;
1445f1ae32a1SGerd Hoffmann     new_state = ohci->ctl & OHCI_CTL_HCFS;
1446f1ae32a1SGerd Hoffmann 
1447f1ae32a1SGerd Hoffmann     /* no state change */
1448f1ae32a1SGerd Hoffmann     if (old_state == new_state)
1449f1ae32a1SGerd Hoffmann         return;
1450f1ae32a1SGerd Hoffmann 
1451dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_set_ctl(ohci->name, new_state);
1452f1ae32a1SGerd Hoffmann     switch (new_state) {
1453f1ae32a1SGerd Hoffmann     case OHCI_USB_OPERATIONAL:
1454f1ae32a1SGerd Hoffmann         ohci_bus_start(ohci);
1455f1ae32a1SGerd Hoffmann         break;
1456f1ae32a1SGerd Hoffmann     case OHCI_USB_SUSPEND:
1457f1ae32a1SGerd Hoffmann         ohci_bus_stop(ohci);
1458087462c7SLaurent Vivier         /* clear pending SF otherwise linux driver loops in ohci_irq() */
1459087462c7SLaurent Vivier         ohci->intr_status &= ~OHCI_INTR_SF;
1460087462c7SLaurent Vivier         ohci_intr_update(ohci);
1461f1ae32a1SGerd Hoffmann         break;
1462f1ae32a1SGerd Hoffmann     case OHCI_USB_RESUME:
1463dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_resume(ohci->name);
1464f1ae32a1SGerd Hoffmann         break;
1465f1ae32a1SGerd Hoffmann     case OHCI_USB_RESET:
14667d938fd1SHervé Poussineau         ohci_roothub_reset(ohci);
1467f1ae32a1SGerd Hoffmann         break;
1468f1ae32a1SGerd Hoffmann     }
1469f1ae32a1SGerd Hoffmann }
1470f1ae32a1SGerd Hoffmann 
1471f1ae32a1SGerd Hoffmann static uint32_t ohci_get_frame_remaining(OHCIState *ohci)
1472f1ae32a1SGerd Hoffmann {
1473f1ae32a1SGerd Hoffmann     uint16_t fr;
1474f1ae32a1SGerd Hoffmann     int64_t tks;
1475f1ae32a1SGerd Hoffmann 
1476f1ae32a1SGerd Hoffmann     if ((ohci->ctl & OHCI_CTL_HCFS) != OHCI_USB_OPERATIONAL)
1477f1ae32a1SGerd Hoffmann         return (ohci->frt << 31);
1478f1ae32a1SGerd Hoffmann 
1479f1ae32a1SGerd Hoffmann     /* Being in USB operational state guarnatees sof_time was
1480f1ae32a1SGerd Hoffmann      * set already.
1481f1ae32a1SGerd Hoffmann      */
1482bc72ad67SAlex Bligh     tks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - ohci->sof_time;
1483a60f39a4SMiguel GAIO     if (tks < 0) {
1484a60f39a4SMiguel GAIO         tks = 0;
1485a60f39a4SMiguel GAIO     }
1486f1ae32a1SGerd Hoffmann 
1487f1ae32a1SGerd Hoffmann     /* avoid muldiv if possible */
1488f1ae32a1SGerd Hoffmann     if (tks >= usb_frame_time)
1489f1ae32a1SGerd Hoffmann         return (ohci->frt << 31);
1490f1ae32a1SGerd Hoffmann 
1491cd1f16f9SLaurent Vivier     tks = tks / usb_bit_time;
1492f1ae32a1SGerd Hoffmann     fr = (uint16_t)(ohci->fi - tks);
1493f1ae32a1SGerd Hoffmann 
1494f1ae32a1SGerd Hoffmann     return (ohci->frt << 31) | fr;
1495f1ae32a1SGerd Hoffmann }
1496f1ae32a1SGerd Hoffmann 
1497f1ae32a1SGerd Hoffmann 
1498f1ae32a1SGerd Hoffmann /* Set root hub status */
1499f1ae32a1SGerd Hoffmann static void ohci_set_hub_status(OHCIState *ohci, uint32_t val)
1500f1ae32a1SGerd Hoffmann {
1501f1ae32a1SGerd Hoffmann     uint32_t old_state;
1502f1ae32a1SGerd Hoffmann 
1503f1ae32a1SGerd Hoffmann     old_state = ohci->rhstatus;
1504f1ae32a1SGerd Hoffmann 
1505f1ae32a1SGerd Hoffmann     /* write 1 to clear OCIC */
1506f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_OCIC)
1507f1ae32a1SGerd Hoffmann         ohci->rhstatus &= ~OHCI_RHS_OCIC;
1508f1ae32a1SGerd Hoffmann 
1509f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_LPS) {
1510f1ae32a1SGerd Hoffmann         int i;
1511f1ae32a1SGerd Hoffmann 
1512f1ae32a1SGerd Hoffmann         for (i = 0; i < ohci->num_ports; i++)
1513f1ae32a1SGerd Hoffmann             ohci_port_power(ohci, i, 0);
1514dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_hub_power_down();
1515f1ae32a1SGerd Hoffmann     }
1516f1ae32a1SGerd Hoffmann 
1517f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_LPSC) {
1518f1ae32a1SGerd Hoffmann         int i;
1519f1ae32a1SGerd Hoffmann 
1520f1ae32a1SGerd Hoffmann         for (i = 0; i < ohci->num_ports; i++)
1521f1ae32a1SGerd Hoffmann             ohci_port_power(ohci, i, 1);
1522dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_hub_power_up();
1523f1ae32a1SGerd Hoffmann     }
1524f1ae32a1SGerd Hoffmann 
1525f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_DRWE)
1526f1ae32a1SGerd Hoffmann         ohci->rhstatus |= OHCI_RHS_DRWE;
1527f1ae32a1SGerd Hoffmann 
1528f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_CRWE)
1529f1ae32a1SGerd Hoffmann         ohci->rhstatus &= ~OHCI_RHS_DRWE;
1530f1ae32a1SGerd Hoffmann 
1531f1ae32a1SGerd Hoffmann     if (old_state != ohci->rhstatus)
1532f1ae32a1SGerd Hoffmann         ohci_set_interrupt(ohci, OHCI_INTR_RHSC);
1533f1ae32a1SGerd Hoffmann }
1534f1ae32a1SGerd Hoffmann 
1535f1ae32a1SGerd Hoffmann /* Set root hub port status */
1536f1ae32a1SGerd Hoffmann static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val)
1537f1ae32a1SGerd Hoffmann {
1538f1ae32a1SGerd Hoffmann     uint32_t old_state;
1539f1ae32a1SGerd Hoffmann     OHCIPort *port;
1540f1ae32a1SGerd Hoffmann 
1541f1ae32a1SGerd Hoffmann     port = &ohci->rhport[portnum];
1542f1ae32a1SGerd Hoffmann     old_state = port->ctrl;
1543f1ae32a1SGerd Hoffmann 
1544f1ae32a1SGerd Hoffmann     /* Write to clear CSC, PESC, PSSC, OCIC, PRSC */
1545f1ae32a1SGerd Hoffmann     if (val & OHCI_PORT_WTC)
1546f1ae32a1SGerd Hoffmann         port->ctrl &= ~(val & OHCI_PORT_WTC);
1547f1ae32a1SGerd Hoffmann 
1548f1ae32a1SGerd Hoffmann     if (val & OHCI_PORT_CCS)
1549f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_PES;
1550f1ae32a1SGerd Hoffmann 
1551f1ae32a1SGerd Hoffmann     ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PES);
1552f1ae32a1SGerd Hoffmann 
1553f1ae32a1SGerd Hoffmann     if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PSS)) {
1554dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_port_suspend(portnum);
1555f1ae32a1SGerd Hoffmann     }
1556f1ae32a1SGerd Hoffmann 
1557f1ae32a1SGerd Hoffmann     if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PRS)) {
1558dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_port_reset(portnum);
1559f1ae32a1SGerd Hoffmann         usb_device_reset(port->port.dev);
1560f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_PRS;
1561f1ae32a1SGerd Hoffmann         /* ??? Should this also set OHCI_PORT_PESC.  */
1562f1ae32a1SGerd Hoffmann         port->ctrl |= OHCI_PORT_PES | OHCI_PORT_PRSC;
1563f1ae32a1SGerd Hoffmann     }
1564f1ae32a1SGerd Hoffmann 
1565f1ae32a1SGerd Hoffmann     /* Invert order here to ensure in ambiguous case, device is
1566f1ae32a1SGerd Hoffmann      * powered up...
1567f1ae32a1SGerd Hoffmann      */
1568f1ae32a1SGerd Hoffmann     if (val & OHCI_PORT_LSDA)
1569f1ae32a1SGerd Hoffmann         ohci_port_power(ohci, portnum, 0);
1570f1ae32a1SGerd Hoffmann     if (val & OHCI_PORT_PPS)
1571f1ae32a1SGerd Hoffmann         ohci_port_power(ohci, portnum, 1);
1572f1ae32a1SGerd Hoffmann 
1573f1ae32a1SGerd Hoffmann     if (old_state != port->ctrl)
1574f1ae32a1SGerd Hoffmann         ohci_set_interrupt(ohci, OHCI_INTR_RHSC);
1575f1ae32a1SGerd Hoffmann }
1576f1ae32a1SGerd Hoffmann 
1577f1ae32a1SGerd Hoffmann static uint64_t ohci_mem_read(void *opaque,
1578a8170e5eSAvi Kivity                               hwaddr addr,
1579f1ae32a1SGerd Hoffmann                               unsigned size)
1580f1ae32a1SGerd Hoffmann {
1581f1ae32a1SGerd Hoffmann     OHCIState *ohci = opaque;
1582f1ae32a1SGerd Hoffmann     uint32_t retval;
1583f1ae32a1SGerd Hoffmann 
1584f1ae32a1SGerd Hoffmann     /* Only aligned reads are allowed on OHCI */
1585f1ae32a1SGerd Hoffmann     if (addr & 3) {
1586dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_mem_read_unaligned(addr);
1587f1ae32a1SGerd Hoffmann         return 0xffffffff;
1588f1ae32a1SGerd Hoffmann     } else if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) {
1589f1ae32a1SGerd Hoffmann         /* HcRhPortStatus */
1590f1ae32a1SGerd Hoffmann         retval = ohci->rhport[(addr - 0x54) >> 2].ctrl | OHCI_PORT_PPS;
1591f1ae32a1SGerd Hoffmann     } else {
1592f1ae32a1SGerd Hoffmann         switch (addr >> 2) {
1593f1ae32a1SGerd Hoffmann         case 0: /* HcRevision */
1594f1ae32a1SGerd Hoffmann             retval = 0x10;
1595f1ae32a1SGerd Hoffmann             break;
1596f1ae32a1SGerd Hoffmann 
1597f1ae32a1SGerd Hoffmann         case 1: /* HcControl */
1598f1ae32a1SGerd Hoffmann             retval = ohci->ctl;
1599f1ae32a1SGerd Hoffmann             break;
1600f1ae32a1SGerd Hoffmann 
1601f1ae32a1SGerd Hoffmann         case 2: /* HcCommandStatus */
1602f1ae32a1SGerd Hoffmann             retval = ohci->status;
1603f1ae32a1SGerd Hoffmann             break;
1604f1ae32a1SGerd Hoffmann 
1605f1ae32a1SGerd Hoffmann         case 3: /* HcInterruptStatus */
1606f1ae32a1SGerd Hoffmann             retval = ohci->intr_status;
1607f1ae32a1SGerd Hoffmann             break;
1608f1ae32a1SGerd Hoffmann 
1609f1ae32a1SGerd Hoffmann         case 4: /* HcInterruptEnable */
1610f1ae32a1SGerd Hoffmann         case 5: /* HcInterruptDisable */
1611f1ae32a1SGerd Hoffmann             retval = ohci->intr;
1612f1ae32a1SGerd Hoffmann             break;
1613f1ae32a1SGerd Hoffmann 
1614f1ae32a1SGerd Hoffmann         case 6: /* HcHCCA */
1615f1ae32a1SGerd Hoffmann             retval = ohci->hcca;
1616f1ae32a1SGerd Hoffmann             break;
1617f1ae32a1SGerd Hoffmann 
1618f1ae32a1SGerd Hoffmann         case 7: /* HcPeriodCurrentED */
1619f1ae32a1SGerd Hoffmann             retval = ohci->per_cur;
1620f1ae32a1SGerd Hoffmann             break;
1621f1ae32a1SGerd Hoffmann 
1622f1ae32a1SGerd Hoffmann         case 8: /* HcControlHeadED */
1623f1ae32a1SGerd Hoffmann             retval = ohci->ctrl_head;
1624f1ae32a1SGerd Hoffmann             break;
1625f1ae32a1SGerd Hoffmann 
1626f1ae32a1SGerd Hoffmann         case 9: /* HcControlCurrentED */
1627f1ae32a1SGerd Hoffmann             retval = ohci->ctrl_cur;
1628f1ae32a1SGerd Hoffmann             break;
1629f1ae32a1SGerd Hoffmann 
1630f1ae32a1SGerd Hoffmann         case 10: /* HcBulkHeadED */
1631f1ae32a1SGerd Hoffmann             retval = ohci->bulk_head;
1632f1ae32a1SGerd Hoffmann             break;
1633f1ae32a1SGerd Hoffmann 
1634f1ae32a1SGerd Hoffmann         case 11: /* HcBulkCurrentED */
1635f1ae32a1SGerd Hoffmann             retval = ohci->bulk_cur;
1636f1ae32a1SGerd Hoffmann             break;
1637f1ae32a1SGerd Hoffmann 
1638f1ae32a1SGerd Hoffmann         case 12: /* HcDoneHead */
1639f1ae32a1SGerd Hoffmann             retval = ohci->done;
1640f1ae32a1SGerd Hoffmann             break;
1641f1ae32a1SGerd Hoffmann 
1642f1ae32a1SGerd Hoffmann         case 13: /* HcFmInterretval */
1643f1ae32a1SGerd Hoffmann             retval = (ohci->fit << 31) | (ohci->fsmps << 16) | (ohci->fi);
1644f1ae32a1SGerd Hoffmann             break;
1645f1ae32a1SGerd Hoffmann 
1646f1ae32a1SGerd Hoffmann         case 14: /* HcFmRemaining */
1647f1ae32a1SGerd Hoffmann             retval = ohci_get_frame_remaining(ohci);
1648f1ae32a1SGerd Hoffmann             break;
1649f1ae32a1SGerd Hoffmann 
1650f1ae32a1SGerd Hoffmann         case 15: /* HcFmNumber */
1651f1ae32a1SGerd Hoffmann             retval = ohci->frame_number;
1652f1ae32a1SGerd Hoffmann             break;
1653f1ae32a1SGerd Hoffmann 
1654f1ae32a1SGerd Hoffmann         case 16: /* HcPeriodicStart */
1655f1ae32a1SGerd Hoffmann             retval = ohci->pstart;
1656f1ae32a1SGerd Hoffmann             break;
1657f1ae32a1SGerd Hoffmann 
1658f1ae32a1SGerd Hoffmann         case 17: /* HcLSThreshold */
1659f1ae32a1SGerd Hoffmann             retval = ohci->lst;
1660f1ae32a1SGerd Hoffmann             break;
1661f1ae32a1SGerd Hoffmann 
1662f1ae32a1SGerd Hoffmann         case 18: /* HcRhDescriptorA */
1663f1ae32a1SGerd Hoffmann             retval = ohci->rhdesc_a;
1664f1ae32a1SGerd Hoffmann             break;
1665f1ae32a1SGerd Hoffmann 
1666f1ae32a1SGerd Hoffmann         case 19: /* HcRhDescriptorB */
1667f1ae32a1SGerd Hoffmann             retval = ohci->rhdesc_b;
1668f1ae32a1SGerd Hoffmann             break;
1669f1ae32a1SGerd Hoffmann 
1670f1ae32a1SGerd Hoffmann         case 20: /* HcRhStatus */
1671f1ae32a1SGerd Hoffmann             retval = ohci->rhstatus;
1672f1ae32a1SGerd Hoffmann             break;
1673f1ae32a1SGerd Hoffmann 
1674f1ae32a1SGerd Hoffmann         /* PXA27x specific registers */
1675f1ae32a1SGerd Hoffmann         case 24: /* HcStatus */
1676f1ae32a1SGerd Hoffmann             retval = ohci->hstatus & ohci->hmask;
1677f1ae32a1SGerd Hoffmann             break;
1678f1ae32a1SGerd Hoffmann 
1679f1ae32a1SGerd Hoffmann         case 25: /* HcHReset */
1680f1ae32a1SGerd Hoffmann             retval = ohci->hreset;
1681f1ae32a1SGerd Hoffmann             break;
1682f1ae32a1SGerd Hoffmann 
1683f1ae32a1SGerd Hoffmann         case 26: /* HcHInterruptEnable */
1684f1ae32a1SGerd Hoffmann             retval = ohci->hmask;
1685f1ae32a1SGerd Hoffmann             break;
1686f1ae32a1SGerd Hoffmann 
1687f1ae32a1SGerd Hoffmann         case 27: /* HcHInterruptTest */
1688f1ae32a1SGerd Hoffmann             retval = ohci->htest;
1689f1ae32a1SGerd Hoffmann             break;
1690f1ae32a1SGerd Hoffmann 
1691f1ae32a1SGerd Hoffmann         default:
1692dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_mem_read_bad_offset(addr);
1693f1ae32a1SGerd Hoffmann             retval = 0xffffffff;
1694f1ae32a1SGerd Hoffmann         }
1695f1ae32a1SGerd Hoffmann     }
1696f1ae32a1SGerd Hoffmann 
1697f1ae32a1SGerd Hoffmann     return retval;
1698f1ae32a1SGerd Hoffmann }
1699f1ae32a1SGerd Hoffmann 
1700f1ae32a1SGerd Hoffmann static void ohci_mem_write(void *opaque,
1701a8170e5eSAvi Kivity                            hwaddr addr,
1702f1ae32a1SGerd Hoffmann                            uint64_t val,
1703f1ae32a1SGerd Hoffmann                            unsigned size)
1704f1ae32a1SGerd Hoffmann {
1705f1ae32a1SGerd Hoffmann     OHCIState *ohci = opaque;
1706f1ae32a1SGerd Hoffmann 
1707f1ae32a1SGerd Hoffmann     /* Only aligned reads are allowed on OHCI */
1708f1ae32a1SGerd Hoffmann     if (addr & 3) {
1709dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_mem_write_unaligned(addr);
1710f1ae32a1SGerd Hoffmann         return;
1711f1ae32a1SGerd Hoffmann     }
1712f1ae32a1SGerd Hoffmann 
1713f1ae32a1SGerd Hoffmann     if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) {
1714f1ae32a1SGerd Hoffmann         /* HcRhPortStatus */
1715f1ae32a1SGerd Hoffmann         ohci_port_set_status(ohci, (addr - 0x54) >> 2, val);
1716f1ae32a1SGerd Hoffmann         return;
1717f1ae32a1SGerd Hoffmann     }
1718f1ae32a1SGerd Hoffmann 
1719f1ae32a1SGerd Hoffmann     switch (addr >> 2) {
1720f1ae32a1SGerd Hoffmann     case 1: /* HcControl */
1721f1ae32a1SGerd Hoffmann         ohci_set_ctl(ohci, val);
1722f1ae32a1SGerd Hoffmann         break;
1723f1ae32a1SGerd Hoffmann 
1724f1ae32a1SGerd Hoffmann     case 2: /* HcCommandStatus */
1725f1ae32a1SGerd Hoffmann         /* SOC is read-only */
1726f1ae32a1SGerd Hoffmann         val = (val & ~OHCI_STATUS_SOC);
1727f1ae32a1SGerd Hoffmann 
1728f1ae32a1SGerd Hoffmann         /* Bits written as '0' remain unchanged in the register */
1729f1ae32a1SGerd Hoffmann         ohci->status |= val;
1730f1ae32a1SGerd Hoffmann 
1731f1ae32a1SGerd Hoffmann         if (ohci->status & OHCI_STATUS_HCR)
17320922c3f6SHervé Poussineau             ohci_soft_reset(ohci);
1733f1ae32a1SGerd Hoffmann         break;
1734f1ae32a1SGerd Hoffmann 
1735f1ae32a1SGerd Hoffmann     case 3: /* HcInterruptStatus */
1736f1ae32a1SGerd Hoffmann         ohci->intr_status &= ~val;
1737f1ae32a1SGerd Hoffmann         ohci_intr_update(ohci);
1738f1ae32a1SGerd Hoffmann         break;
1739f1ae32a1SGerd Hoffmann 
1740f1ae32a1SGerd Hoffmann     case 4: /* HcInterruptEnable */
1741f1ae32a1SGerd Hoffmann         ohci->intr |= val;
1742f1ae32a1SGerd Hoffmann         ohci_intr_update(ohci);
1743f1ae32a1SGerd Hoffmann         break;
1744f1ae32a1SGerd Hoffmann 
1745f1ae32a1SGerd Hoffmann     case 5: /* HcInterruptDisable */
1746f1ae32a1SGerd Hoffmann         ohci->intr &= ~val;
1747f1ae32a1SGerd Hoffmann         ohci_intr_update(ohci);
1748f1ae32a1SGerd Hoffmann         break;
1749f1ae32a1SGerd Hoffmann 
1750f1ae32a1SGerd Hoffmann     case 6: /* HcHCCA */
1751f1ae32a1SGerd Hoffmann         ohci->hcca = val & OHCI_HCCA_MASK;
1752f1ae32a1SGerd Hoffmann         break;
1753f1ae32a1SGerd Hoffmann 
1754f1ae32a1SGerd Hoffmann     case 7: /* HcPeriodCurrentED */
1755f1ae32a1SGerd Hoffmann         /* Ignore writes to this read-only register, Linux does them */
1756f1ae32a1SGerd Hoffmann         break;
1757f1ae32a1SGerd Hoffmann 
1758f1ae32a1SGerd Hoffmann     case 8: /* HcControlHeadED */
1759f1ae32a1SGerd Hoffmann         ohci->ctrl_head = val & OHCI_EDPTR_MASK;
1760f1ae32a1SGerd Hoffmann         break;
1761f1ae32a1SGerd Hoffmann 
1762f1ae32a1SGerd Hoffmann     case 9: /* HcControlCurrentED */
1763f1ae32a1SGerd Hoffmann         ohci->ctrl_cur = val & OHCI_EDPTR_MASK;
1764f1ae32a1SGerd Hoffmann         break;
1765f1ae32a1SGerd Hoffmann 
1766f1ae32a1SGerd Hoffmann     case 10: /* HcBulkHeadED */
1767f1ae32a1SGerd Hoffmann         ohci->bulk_head = val & OHCI_EDPTR_MASK;
1768f1ae32a1SGerd Hoffmann         break;
1769f1ae32a1SGerd Hoffmann 
1770f1ae32a1SGerd Hoffmann     case 11: /* HcBulkCurrentED */
1771f1ae32a1SGerd Hoffmann         ohci->bulk_cur = val & OHCI_EDPTR_MASK;
1772f1ae32a1SGerd Hoffmann         break;
1773f1ae32a1SGerd Hoffmann 
1774f1ae32a1SGerd Hoffmann     case 13: /* HcFmInterval */
1775f1ae32a1SGerd Hoffmann         ohci->fsmps = (val & OHCI_FMI_FSMPS) >> 16;
1776f1ae32a1SGerd Hoffmann         ohci->fit = (val & OHCI_FMI_FIT) >> 31;
1777f1ae32a1SGerd Hoffmann         ohci_set_frame_interval(ohci, val);
1778f1ae32a1SGerd Hoffmann         break;
1779f1ae32a1SGerd Hoffmann 
1780f1ae32a1SGerd Hoffmann     case 15: /* HcFmNumber */
1781f1ae32a1SGerd Hoffmann         break;
1782f1ae32a1SGerd Hoffmann 
1783f1ae32a1SGerd Hoffmann     case 16: /* HcPeriodicStart */
1784f1ae32a1SGerd Hoffmann         ohci->pstart = val & 0xffff;
1785f1ae32a1SGerd Hoffmann         break;
1786f1ae32a1SGerd Hoffmann 
1787f1ae32a1SGerd Hoffmann     case 17: /* HcLSThreshold */
1788f1ae32a1SGerd Hoffmann         ohci->lst = val & 0xffff;
1789f1ae32a1SGerd Hoffmann         break;
1790f1ae32a1SGerd Hoffmann 
1791f1ae32a1SGerd Hoffmann     case 18: /* HcRhDescriptorA */
1792f1ae32a1SGerd Hoffmann         ohci->rhdesc_a &= ~OHCI_RHA_RW_MASK;
1793f1ae32a1SGerd Hoffmann         ohci->rhdesc_a |= val & OHCI_RHA_RW_MASK;
1794f1ae32a1SGerd Hoffmann         break;
1795f1ae32a1SGerd Hoffmann 
1796f1ae32a1SGerd Hoffmann     case 19: /* HcRhDescriptorB */
1797f1ae32a1SGerd Hoffmann         break;
1798f1ae32a1SGerd Hoffmann 
1799f1ae32a1SGerd Hoffmann     case 20: /* HcRhStatus */
1800f1ae32a1SGerd Hoffmann         ohci_set_hub_status(ohci, val);
1801f1ae32a1SGerd Hoffmann         break;
1802f1ae32a1SGerd Hoffmann 
1803f1ae32a1SGerd Hoffmann     /* PXA27x specific registers */
1804f1ae32a1SGerd Hoffmann     case 24: /* HcStatus */
1805f1ae32a1SGerd Hoffmann         ohci->hstatus &= ~(val & ohci->hmask);
18067fa96d73SGerd Hoffmann         break;
1807f1ae32a1SGerd Hoffmann 
1808f1ae32a1SGerd Hoffmann     case 25: /* HcHReset */
1809f1ae32a1SGerd Hoffmann         ohci->hreset = val & ~OHCI_HRESET_FSBIR;
1810f1ae32a1SGerd Hoffmann         if (val & OHCI_HRESET_FSBIR)
181184d04e21SHervé Poussineau             ohci_hard_reset(ohci);
1812f1ae32a1SGerd Hoffmann         break;
1813f1ae32a1SGerd Hoffmann 
1814f1ae32a1SGerd Hoffmann     case 26: /* HcHInterruptEnable */
1815f1ae32a1SGerd Hoffmann         ohci->hmask = val;
1816f1ae32a1SGerd Hoffmann         break;
1817f1ae32a1SGerd Hoffmann 
1818f1ae32a1SGerd Hoffmann     case 27: /* HcHInterruptTest */
1819f1ae32a1SGerd Hoffmann         ohci->htest = val;
1820f1ae32a1SGerd Hoffmann         break;
1821f1ae32a1SGerd Hoffmann 
1822f1ae32a1SGerd Hoffmann     default:
1823dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_mem_write_bad_offset(addr);
1824f1ae32a1SGerd Hoffmann         break;
1825f1ae32a1SGerd Hoffmann     }
1826f1ae32a1SGerd Hoffmann }
1827f1ae32a1SGerd Hoffmann 
1828f1ae32a1SGerd Hoffmann static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev)
1829f1ae32a1SGerd Hoffmann {
1830f1ae32a1SGerd Hoffmann     if (ohci->async_td &&
1831f1ae32a1SGerd Hoffmann         usb_packet_is_inflight(&ohci->usb_packet) &&
1832f1ae32a1SGerd Hoffmann         ohci->usb_packet.ep->dev == dev) {
1833f1ae32a1SGerd Hoffmann         usb_cancel_packet(&ohci->usb_packet);
1834f1ae32a1SGerd Hoffmann         ohci->async_td = 0;
1835f1ae32a1SGerd Hoffmann     }
1836f1ae32a1SGerd Hoffmann }
1837f1ae32a1SGerd Hoffmann 
1838f1ae32a1SGerd Hoffmann static const MemoryRegionOps ohci_mem_ops = {
1839f1ae32a1SGerd Hoffmann     .read = ohci_mem_read,
1840f1ae32a1SGerd Hoffmann     .write = ohci_mem_write,
1841f1ae32a1SGerd Hoffmann     .endianness = DEVICE_LITTLE_ENDIAN,
1842f1ae32a1SGerd Hoffmann };
1843f1ae32a1SGerd Hoffmann 
1844f1ae32a1SGerd Hoffmann static USBPortOps ohci_port_ops = {
1845f1ae32a1SGerd Hoffmann     .attach = ohci_attach,
1846f1ae32a1SGerd Hoffmann     .detach = ohci_detach,
1847f1ae32a1SGerd Hoffmann     .child_detach = ohci_child_detach,
1848f1ae32a1SGerd Hoffmann     .wakeup = ohci_wakeup,
1849f1ae32a1SGerd Hoffmann     .complete = ohci_async_complete_packet,
1850f1ae32a1SGerd Hoffmann };
1851f1ae32a1SGerd Hoffmann 
1852f1ae32a1SGerd Hoffmann static USBBusOps ohci_bus_ops = {
1853f1ae32a1SGerd Hoffmann };
1854f1ae32a1SGerd Hoffmann 
185587581feaSMarkus Armbruster static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
1856b9a3a4f2SLi Qiang                           uint32_t num_ports, dma_addr_t localmem_base,
18579ac6a217SDavid Gibson                           char *masterbus, uint32_t firstport,
185887581feaSMarkus Armbruster                           AddressSpace *as, Error **errp)
1859f1ae32a1SGerd Hoffmann {
1860f4bbaaf5SMarkus Armbruster     Error *err = NULL;
1861f1ae32a1SGerd Hoffmann     int i;
1862f1ae32a1SGerd Hoffmann 
1863df32fd1cSPaolo Bonzini     ohci->as = as;
18649ac6a217SDavid Gibson 
1865d400fc01SThomas Huth     if (num_ports > OHCI_MAX_PORTS) {
1866b9a3a4f2SLi Qiang         error_setg(errp, "OHCI num-ports=%u is too big (limit is %u ports)",
1867d400fc01SThomas Huth                    num_ports, OHCI_MAX_PORTS);
1868d400fc01SThomas Huth         return;
1869d400fc01SThomas Huth     }
1870d400fc01SThomas Huth 
1871f1ae32a1SGerd Hoffmann     if (usb_frame_time == 0) {
1872f1ae32a1SGerd Hoffmann #ifdef OHCI_TIME_WARP
187373bcb24dSRutuja Shah         usb_frame_time = NANOSECONDS_PER_SECOND;
187473bcb24dSRutuja Shah         usb_bit_time = NANOSECONDS_PER_SECOND / (USB_HZ / 1000);
1875f1ae32a1SGerd Hoffmann #else
187673bcb24dSRutuja Shah         usb_frame_time = NANOSECONDS_PER_SECOND / 1000;
187773bcb24dSRutuja Shah         if (NANOSECONDS_PER_SECOND >= USB_HZ) {
187873bcb24dSRutuja Shah             usb_bit_time = NANOSECONDS_PER_SECOND / USB_HZ;
1879f1ae32a1SGerd Hoffmann         } else {
1880f1ae32a1SGerd Hoffmann             usb_bit_time = 1;
1881f1ae32a1SGerd Hoffmann         }
1882f1ae32a1SGerd Hoffmann #endif
1883dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_init_time(usb_frame_time, usb_bit_time);
1884f1ae32a1SGerd Hoffmann     }
1885f1ae32a1SGerd Hoffmann 
1886f1ae32a1SGerd Hoffmann     ohci->num_ports = num_ports;
1887f1ae32a1SGerd Hoffmann     if (masterbus) {
1888f1ae32a1SGerd Hoffmann         USBPort *ports[OHCI_MAX_PORTS];
1889f1ae32a1SGerd Hoffmann         for(i = 0; i < num_ports; i++) {
1890f1ae32a1SGerd Hoffmann             ports[i] = &ohci->rhport[i].port;
1891f1ae32a1SGerd Hoffmann         }
1892f4bbaaf5SMarkus Armbruster         usb_register_companion(masterbus, ports, num_ports,
1893f1ae32a1SGerd Hoffmann                                firstport, ohci, &ohci_port_ops,
1894f4bbaaf5SMarkus Armbruster                                USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL,
1895f4bbaaf5SMarkus Armbruster                                &err);
1896f4bbaaf5SMarkus Armbruster         if (err) {
189787581feaSMarkus Armbruster             error_propagate(errp, err);
189887581feaSMarkus Armbruster             return;
1899f1ae32a1SGerd Hoffmann         }
1900f1ae32a1SGerd Hoffmann     } else {
1901c889b3a5SAndreas Färber         usb_bus_new(&ohci->bus, sizeof(ohci->bus), &ohci_bus_ops, dev);
1902f1ae32a1SGerd Hoffmann         for (i = 0; i < num_ports; i++) {
1903f1ae32a1SGerd Hoffmann             usb_register_port(&ohci->bus, &ohci->rhport[i].port,
1904f1ae32a1SGerd Hoffmann                               ohci, i, &ohci_port_ops,
1905f1ae32a1SGerd Hoffmann                               USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
1906f1ae32a1SGerd Hoffmann         }
1907f1ae32a1SGerd Hoffmann     }
1908f1ae32a1SGerd Hoffmann 
190922fc860bSPaolo Bonzini     memory_region_init_io(&ohci->mem, OBJECT(dev), &ohci_mem_ops,
191022fc860bSPaolo Bonzini                           ohci, "ohci", 256);
1911f1ae32a1SGerd Hoffmann     ohci->localmem_base = localmem_base;
1912f1ae32a1SGerd Hoffmann 
1913f1ae32a1SGerd Hoffmann     ohci->name = object_get_typename(OBJECT(dev));
1914f1ae32a1SGerd Hoffmann     usb_packet_init(&ohci->usb_packet);
1915f1ae32a1SGerd Hoffmann 
1916f1ae32a1SGerd Hoffmann     ohci->async_td = 0;
1917fa1298c2SGerd Hoffmann 
1918fa1298c2SGerd Hoffmann     ohci->eof_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
1919fa1298c2SGerd Hoffmann                                    ohci_frame_boundary, ohci);
1920f1ae32a1SGerd Hoffmann }
1921f1ae32a1SGerd Hoffmann 
19221aa0c0c7SHu Tao #define TYPE_PCI_OHCI "pci-ohci"
19231aa0c0c7SHu Tao #define PCI_OHCI(obj) OBJECT_CHECK(OHCIPCIState, (obj), TYPE_PCI_OHCI)
19241aa0c0c7SHu Tao 
1925f1ae32a1SGerd Hoffmann typedef struct {
19261aa0c0c7SHu Tao     /*< private >*/
19271aa0c0c7SHu Tao     PCIDevice parent_obj;
19281aa0c0c7SHu Tao     /*< public >*/
19291aa0c0c7SHu Tao 
1930f1ae32a1SGerd Hoffmann     OHCIState state;
1931f1ae32a1SGerd Hoffmann     char *masterbus;
1932f1ae32a1SGerd Hoffmann     uint32_t num_ports;
1933f1ae32a1SGerd Hoffmann     uint32_t firstport;
1934f1ae32a1SGerd Hoffmann } OHCIPCIState;
1935f1ae32a1SGerd Hoffmann 
1936cf66ee8eSAlexey Kardashevskiy /** A typical O/EHCI will stop operating, set itself into error state
1937cf66ee8eSAlexey Kardashevskiy  * (which can be queried by MMIO) and will set PERR in its config
1938cf66ee8eSAlexey Kardashevskiy  * space to signal that it got an error
1939cf66ee8eSAlexey Kardashevskiy  */
1940cf66ee8eSAlexey Kardashevskiy static void ohci_die(OHCIState *ohci)
1941cf66ee8eSAlexey Kardashevskiy {
1942cf66ee8eSAlexey Kardashevskiy     OHCIPCIState *dev = container_of(ohci, OHCIPCIState, state);
1943cf66ee8eSAlexey Kardashevskiy 
1944dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_die();
1945cf66ee8eSAlexey Kardashevskiy 
1946cf66ee8eSAlexey Kardashevskiy     ohci_set_interrupt(ohci, OHCI_INTR_UE);
1947cf66ee8eSAlexey Kardashevskiy     ohci_bus_stop(ohci);
1948cf66ee8eSAlexey Kardashevskiy     pci_set_word(dev->parent_obj.config + PCI_STATUS,
1949cf66ee8eSAlexey Kardashevskiy                  PCI_STATUS_DETECTED_PARITY);
1950cf66ee8eSAlexey Kardashevskiy }
1951cf66ee8eSAlexey Kardashevskiy 
195287581feaSMarkus Armbruster static void usb_ohci_realize_pci(PCIDevice *dev, Error **errp)
1953f1ae32a1SGerd Hoffmann {
195487581feaSMarkus Armbruster     Error *err = NULL;
19551aa0c0c7SHu Tao     OHCIPCIState *ohci = PCI_OHCI(dev);
1956f1ae32a1SGerd Hoffmann 
19571aa0c0c7SHu Tao     dev->config[PCI_CLASS_PROG] = 0x10; /* OHCI */
19581aa0c0c7SHu Tao     dev->config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */
1959f1ae32a1SGerd Hoffmann 
196087581feaSMarkus Armbruster     usb_ohci_init(&ohci->state, DEVICE(dev), ohci->num_ports, 0,
19619ac6a217SDavid Gibson                   ohci->masterbus, ohci->firstport,
196287581feaSMarkus Armbruster                   pci_get_address_space(dev), &err);
196387581feaSMarkus Armbruster     if (err) {
196487581feaSMarkus Armbruster         error_propagate(errp, err);
196587581feaSMarkus Armbruster         return;
1966f1ae32a1SGerd Hoffmann     }
1967f1ae32a1SGerd Hoffmann 
196887581feaSMarkus Armbruster     ohci->state.irq = pci_allocate_irq(dev);
19691aa0c0c7SHu Tao     pci_register_bar(dev, 0, 0, &ohci->state.mem);
1970f1ae32a1SGerd Hoffmann }
1971f1ae32a1SGerd Hoffmann 
197207832c38SGonglei static void usb_ohci_exit(PCIDevice *dev)
197307832c38SGonglei {
197407832c38SGonglei     OHCIPCIState *ohci = PCI_OHCI(dev);
197507832c38SGonglei     OHCIState *s = &ohci->state;
197607832c38SGonglei 
1977dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_exit(s->name);
197807832c38SGonglei     ohci_bus_stop(s);
197907832c38SGonglei 
198007832c38SGonglei     if (s->async_td) {
198107832c38SGonglei         usb_cancel_packet(&s->usb_packet);
198207832c38SGonglei         s->async_td = 0;
198307832c38SGonglei     }
198407832c38SGonglei     ohci_stop_endpoints(s);
198507832c38SGonglei 
198607832c38SGonglei     if (!ohci->masterbus) {
198707832c38SGonglei         usb_bus_release(&s->bus);
198807832c38SGonglei     }
1989fa1298c2SGerd Hoffmann 
1990fa1298c2SGerd Hoffmann     timer_del(s->eof_timer);
1991fa1298c2SGerd Hoffmann     timer_free(s->eof_timer);
199207832c38SGonglei }
199307832c38SGonglei 
199488dd1b8dSGonglei static void usb_ohci_reset_pci(DeviceState *d)
199588dd1b8dSGonglei {
199688dd1b8dSGonglei     PCIDevice *dev = PCI_DEVICE(d);
199788dd1b8dSGonglei     OHCIPCIState *ohci = PCI_OHCI(dev);
199888dd1b8dSGonglei     OHCIState *s = &ohci->state;
199988dd1b8dSGonglei 
200084d04e21SHervé Poussineau     ohci_hard_reset(s);
200188dd1b8dSGonglei }
200288dd1b8dSGonglei 
20031aa0c0c7SHu Tao #define TYPE_SYSBUS_OHCI "sysbus-ohci"
20041aa0c0c7SHu Tao #define SYSBUS_OHCI(obj) OBJECT_CHECK(OHCISysBusState, (obj), TYPE_SYSBUS_OHCI)
20051aa0c0c7SHu Tao 
2006f1ae32a1SGerd Hoffmann typedef struct {
20071aa0c0c7SHu Tao     /*< private >*/
20081aa0c0c7SHu Tao     SysBusDevice parent_obj;
20091aa0c0c7SHu Tao     /*< public >*/
20101aa0c0c7SHu Tao 
2011f1ae32a1SGerd Hoffmann     OHCIState ohci;
2012d7145b66SBALATON Zoltan     char *masterbus;
2013f1ae32a1SGerd Hoffmann     uint32_t num_ports;
2014d7145b66SBALATON Zoltan     uint32_t firstport;
20159ac6a217SDavid Gibson     dma_addr_t dma_offset;
2016f1ae32a1SGerd Hoffmann } OHCISysBusState;
2017f1ae32a1SGerd Hoffmann 
2018457215ecSHu Tao static void ohci_realize_pxa(DeviceState *dev, Error **errp)
2019f1ae32a1SGerd Hoffmann {
20201aa0c0c7SHu Tao     OHCISysBusState *s = SYSBUS_OHCI(dev);
2021457215ecSHu Tao     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
2022d7145b66SBALATON Zoltan     Error *err = NULL;
2023f1ae32a1SGerd Hoffmann 
2024d7145b66SBALATON Zoltan     usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset,
2025d7145b66SBALATON Zoltan                   s->masterbus, s->firstport,
2026d7145b66SBALATON Zoltan                   &address_space_memory, &err);
2027d7145b66SBALATON Zoltan     if (err) {
2028d7145b66SBALATON Zoltan         error_propagate(errp, err);
2029d7145b66SBALATON Zoltan         return;
2030d7145b66SBALATON Zoltan     }
2031457215ecSHu Tao     sysbus_init_irq(sbd, &s->ohci.irq);
2032457215ecSHu Tao     sysbus_init_mmio(sbd, &s->ohci.mem);
2033f1ae32a1SGerd Hoffmann }
2034f1ae32a1SGerd Hoffmann 
203588dd1b8dSGonglei static void usb_ohci_reset_sysbus(DeviceState *dev)
203688dd1b8dSGonglei {
203788dd1b8dSGonglei     OHCISysBusState *s = SYSBUS_OHCI(dev);
203888dd1b8dSGonglei     OHCIState *ohci = &s->ohci;
203988dd1b8dSGonglei 
204084d04e21SHervé Poussineau     ohci_hard_reset(ohci);
204188dd1b8dSGonglei }
204288dd1b8dSGonglei 
2043f1ae32a1SGerd Hoffmann static Property ohci_pci_properties[] = {
2044f1ae32a1SGerd Hoffmann     DEFINE_PROP_STRING("masterbus", OHCIPCIState, masterbus),
2045f1ae32a1SGerd Hoffmann     DEFINE_PROP_UINT32("num-ports", OHCIPCIState, num_ports, 3),
2046f1ae32a1SGerd Hoffmann     DEFINE_PROP_UINT32("firstport", OHCIPCIState, firstport, 0),
2047f1ae32a1SGerd Hoffmann     DEFINE_PROP_END_OF_LIST(),
2048f1ae32a1SGerd Hoffmann };
2049f1ae32a1SGerd Hoffmann 
205069e25d26SAlexey Kardashevskiy static const VMStateDescription vmstate_ohci_state_port = {
205169e25d26SAlexey Kardashevskiy     .name = "ohci-core/port",
205269e25d26SAlexey Kardashevskiy     .version_id = 1,
205369e25d26SAlexey Kardashevskiy     .minimum_version_id = 1,
205469e25d26SAlexey Kardashevskiy     .fields = (VMStateField[]) {
205569e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(ctrl, OHCIPort),
205669e25d26SAlexey Kardashevskiy         VMSTATE_END_OF_LIST()
205769e25d26SAlexey Kardashevskiy     },
205869e25d26SAlexey Kardashevskiy };
205969e25d26SAlexey Kardashevskiy 
206069e25d26SAlexey Kardashevskiy static bool ohci_eof_timer_needed(void *opaque)
206169e25d26SAlexey Kardashevskiy {
206269e25d26SAlexey Kardashevskiy     OHCIState *ohci = opaque;
206369e25d26SAlexey Kardashevskiy 
2064fa1298c2SGerd Hoffmann     return timer_pending(ohci->eof_timer);
206569e25d26SAlexey Kardashevskiy }
206669e25d26SAlexey Kardashevskiy 
206769e25d26SAlexey Kardashevskiy static const VMStateDescription vmstate_ohci_eof_timer = {
206869e25d26SAlexey Kardashevskiy     .name = "ohci-core/eof-timer",
206969e25d26SAlexey Kardashevskiy     .version_id = 1,
207069e25d26SAlexey Kardashevskiy     .minimum_version_id = 1,
20715cd8cadaSJuan Quintela     .needed = ohci_eof_timer_needed,
207269e25d26SAlexey Kardashevskiy     .fields = (VMStateField[]) {
2073e720677eSPaolo Bonzini         VMSTATE_TIMER_PTR(eof_timer, OHCIState),
207469e25d26SAlexey Kardashevskiy         VMSTATE_END_OF_LIST()
207569e25d26SAlexey Kardashevskiy     },
207669e25d26SAlexey Kardashevskiy };
207769e25d26SAlexey Kardashevskiy 
2078b9b45b4aSStefan Weil static const VMStateDescription vmstate_ohci_state = {
207969e25d26SAlexey Kardashevskiy     .name = "ohci-core",
208069e25d26SAlexey Kardashevskiy     .version_id = 1,
208169e25d26SAlexey Kardashevskiy     .minimum_version_id = 1,
208269e25d26SAlexey Kardashevskiy     .fields = (VMStateField[]) {
208369e25d26SAlexey Kardashevskiy         VMSTATE_INT64(sof_time, OHCIState),
208469e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(ctl, OHCIState),
208569e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(status, OHCIState),
208669e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(intr_status, OHCIState),
208769e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(intr, OHCIState),
208869e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(hcca, OHCIState),
208969e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(ctrl_head, OHCIState),
209069e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(ctrl_cur, OHCIState),
209169e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(bulk_head, OHCIState),
209269e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(bulk_cur, OHCIState),
209369e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(per_cur, OHCIState),
209469e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(done, OHCIState),
209569e25d26SAlexey Kardashevskiy         VMSTATE_INT32(done_count, OHCIState),
209669e25d26SAlexey Kardashevskiy         VMSTATE_UINT16(fsmps, OHCIState),
209769e25d26SAlexey Kardashevskiy         VMSTATE_UINT8(fit, OHCIState),
209869e25d26SAlexey Kardashevskiy         VMSTATE_UINT16(fi, OHCIState),
209969e25d26SAlexey Kardashevskiy         VMSTATE_UINT8(frt, OHCIState),
210069e25d26SAlexey Kardashevskiy         VMSTATE_UINT16(frame_number, OHCIState),
210169e25d26SAlexey Kardashevskiy         VMSTATE_UINT16(padding, OHCIState),
210269e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(pstart, OHCIState),
210369e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(lst, OHCIState),
210469e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(rhdesc_a, OHCIState),
210569e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(rhdesc_b, OHCIState),
210669e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(rhstatus, OHCIState),
210769e25d26SAlexey Kardashevskiy         VMSTATE_STRUCT_ARRAY(rhport, OHCIState, OHCI_MAX_PORTS, 0,
210869e25d26SAlexey Kardashevskiy                              vmstate_ohci_state_port, OHCIPort),
210969e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(hstatus, OHCIState),
211069e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(hmask, OHCIState),
211169e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(hreset, OHCIState),
211269e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(htest, OHCIState),
211369e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(old_ctl, OHCIState),
211469e25d26SAlexey Kardashevskiy         VMSTATE_UINT8_ARRAY(usb_buf, OHCIState, 8192),
211569e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(async_td, OHCIState),
211669e25d26SAlexey Kardashevskiy         VMSTATE_BOOL(async_complete, OHCIState),
211769e25d26SAlexey Kardashevskiy         VMSTATE_END_OF_LIST()
211869e25d26SAlexey Kardashevskiy     },
21195cd8cadaSJuan Quintela     .subsections = (const VMStateDescription*[]) {
21205cd8cadaSJuan Quintela         &vmstate_ohci_eof_timer,
21215cd8cadaSJuan Quintela         NULL
212269e25d26SAlexey Kardashevskiy     }
212369e25d26SAlexey Kardashevskiy };
212469e25d26SAlexey Kardashevskiy 
212569e25d26SAlexey Kardashevskiy static const VMStateDescription vmstate_ohci = {
212669e25d26SAlexey Kardashevskiy     .name = "ohci",
212769e25d26SAlexey Kardashevskiy     .version_id = 1,
212869e25d26SAlexey Kardashevskiy     .minimum_version_id = 1,
212969e25d26SAlexey Kardashevskiy     .fields = (VMStateField[]) {
213069e25d26SAlexey Kardashevskiy         VMSTATE_PCI_DEVICE(parent_obj, OHCIPCIState),
213169e25d26SAlexey Kardashevskiy         VMSTATE_STRUCT(state, OHCIPCIState, 1, vmstate_ohci_state, OHCIState),
213269e25d26SAlexey Kardashevskiy         VMSTATE_END_OF_LIST()
213369e25d26SAlexey Kardashevskiy     }
213469e25d26SAlexey Kardashevskiy };
213569e25d26SAlexey Kardashevskiy 
2136f1ae32a1SGerd Hoffmann static void ohci_pci_class_init(ObjectClass *klass, void *data)
2137f1ae32a1SGerd Hoffmann {
2138f1ae32a1SGerd Hoffmann     DeviceClass *dc = DEVICE_CLASS(klass);
2139f1ae32a1SGerd Hoffmann     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
2140f1ae32a1SGerd Hoffmann 
214187581feaSMarkus Armbruster     k->realize = usb_ohci_realize_pci;
214207832c38SGonglei     k->exit = usb_ohci_exit;
2143f1ae32a1SGerd Hoffmann     k->vendor_id = PCI_VENDOR_ID_APPLE;
2144f1ae32a1SGerd Hoffmann     k->device_id = PCI_DEVICE_ID_APPLE_IPID_USB;
2145f1ae32a1SGerd Hoffmann     k->class_id = PCI_CLASS_SERIAL_USB;
2146125ee0edSMarcel Apfelbaum     set_bit(DEVICE_CATEGORY_USB, dc->categories);
2147f1ae32a1SGerd Hoffmann     dc->desc = "Apple USB Controller";
2148f1ae32a1SGerd Hoffmann     dc->props = ohci_pci_properties;
21492897ae02SIgor Mammedov     dc->hotpluggable = false;
215069e25d26SAlexey Kardashevskiy     dc->vmsd = &vmstate_ohci;
215188dd1b8dSGonglei     dc->reset = usb_ohci_reset_pci;
2152f1ae32a1SGerd Hoffmann }
2153f1ae32a1SGerd Hoffmann 
21548c43a6f0SAndreas Färber static const TypeInfo ohci_pci_info = {
21551aa0c0c7SHu Tao     .name          = TYPE_PCI_OHCI,
2156f1ae32a1SGerd Hoffmann     .parent        = TYPE_PCI_DEVICE,
2157f1ae32a1SGerd Hoffmann     .instance_size = sizeof(OHCIPCIState),
2158f1ae32a1SGerd Hoffmann     .class_init    = ohci_pci_class_init,
2159fd3b02c8SEduardo Habkost     .interfaces = (InterfaceInfo[]) {
2160fd3b02c8SEduardo Habkost         { INTERFACE_CONVENTIONAL_PCI_DEVICE },
2161fd3b02c8SEduardo Habkost         { },
2162fd3b02c8SEduardo Habkost     },
2163f1ae32a1SGerd Hoffmann };
2164f1ae32a1SGerd Hoffmann 
2165f1ae32a1SGerd Hoffmann static Property ohci_sysbus_properties[] = {
2166d7145b66SBALATON Zoltan     DEFINE_PROP_STRING("masterbus", OHCISysBusState, masterbus),
2167f1ae32a1SGerd Hoffmann     DEFINE_PROP_UINT32("num-ports", OHCISysBusState, num_ports, 3),
2168d7145b66SBALATON Zoltan     DEFINE_PROP_UINT32("firstport", OHCISysBusState, firstport, 0),
21696998b6c7SVijay Kumar B     DEFINE_PROP_DMAADDR("dma-offset", OHCISysBusState, dma_offset, 0),
2170f1ae32a1SGerd Hoffmann     DEFINE_PROP_END_OF_LIST(),
2171f1ae32a1SGerd Hoffmann };
2172f1ae32a1SGerd Hoffmann 
2173f1ae32a1SGerd Hoffmann static void ohci_sysbus_class_init(ObjectClass *klass, void *data)
2174f1ae32a1SGerd Hoffmann {
2175f1ae32a1SGerd Hoffmann     DeviceClass *dc = DEVICE_CLASS(klass);
2176f1ae32a1SGerd Hoffmann 
2177457215ecSHu Tao     dc->realize = ohci_realize_pxa;
2178125ee0edSMarcel Apfelbaum     set_bit(DEVICE_CATEGORY_USB, dc->categories);
2179f1ae32a1SGerd Hoffmann     dc->desc = "OHCI USB Controller";
2180f1ae32a1SGerd Hoffmann     dc->props = ohci_sysbus_properties;
218188dd1b8dSGonglei     dc->reset = usb_ohci_reset_sysbus;
2182f1ae32a1SGerd Hoffmann }
2183f1ae32a1SGerd Hoffmann 
21848c43a6f0SAndreas Färber static const TypeInfo ohci_sysbus_info = {
21851aa0c0c7SHu Tao     .name          = TYPE_SYSBUS_OHCI,
2186f1ae32a1SGerd Hoffmann     .parent        = TYPE_SYS_BUS_DEVICE,
2187f1ae32a1SGerd Hoffmann     .instance_size = sizeof(OHCISysBusState),
2188f1ae32a1SGerd Hoffmann     .class_init    = ohci_sysbus_class_init,
2189f1ae32a1SGerd Hoffmann };
2190f1ae32a1SGerd Hoffmann 
2191f1ae32a1SGerd Hoffmann static void ohci_register_types(void)
2192f1ae32a1SGerd Hoffmann {
2193f1ae32a1SGerd Hoffmann     type_register_static(&ohci_pci_info);
2194f1ae32a1SGerd Hoffmann     type_register_static(&ohci_sysbus_info);
2195f1ae32a1SGerd Hoffmann }
2196f1ae32a1SGerd Hoffmann 
2197f1ae32a1SGerd Hoffmann type_init(ohci_register_types)
2198