xref: /openbmc/qemu/hw/usb/hcd-ohci.c (revision ba06fe8a)
1f1ae32a1SGerd Hoffmann /*
2f1ae32a1SGerd Hoffmann  * QEMU USB OHCI Emulation
3f1ae32a1SGerd Hoffmann  * Copyright (c) 2004 Gianni Tedesco
4f1ae32a1SGerd Hoffmann  * Copyright (c) 2006 CodeSourcery
5f1ae32a1SGerd Hoffmann  * Copyright (c) 2006 Openedhand Ltd.
6f1ae32a1SGerd Hoffmann  *
7f1ae32a1SGerd Hoffmann  * This library is free software; you can redistribute it and/or
8f1ae32a1SGerd Hoffmann  * modify it under the terms of the GNU Lesser General Public
9f1ae32a1SGerd Hoffmann  * License as published by the Free Software Foundation; either
10bee41971SChetan Pant  * version 2.1 of the License, or (at your option) any later version.
11f1ae32a1SGerd Hoffmann  *
12f1ae32a1SGerd Hoffmann  * This library is distributed in the hope that it will be useful,
13f1ae32a1SGerd Hoffmann  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14f1ae32a1SGerd Hoffmann  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15f1ae32a1SGerd Hoffmann  * Lesser General Public License for more details.
16f1ae32a1SGerd Hoffmann  *
17f1ae32a1SGerd Hoffmann  * You should have received a copy of the GNU Lesser General Public
18f1ae32a1SGerd Hoffmann  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19f1ae32a1SGerd Hoffmann  *
20f1ae32a1SGerd Hoffmann  * TODO:
21f1ae32a1SGerd Hoffmann  *  o Isochronous transfers
22f1ae32a1SGerd Hoffmann  *  o Allocate bandwidth in frames properly
23f1ae32a1SGerd Hoffmann  *  o Disable timers when nothing needs to be done, or remove timer usage
24f1ae32a1SGerd Hoffmann  *    all together.
25f1ae32a1SGerd Hoffmann  *  o BIOS work to boot from USB storage
26f1ae32a1SGerd Hoffmann */
27f1ae32a1SGerd Hoffmann 
28e532b2e0SPeter Maydell #include "qemu/osdep.h"
2964552b6bSMarkus Armbruster #include "hw/irq.h"
30da34e65cSMarkus Armbruster #include "qapi/error.h"
310b8fa32fSMarkus Armbruster #include "qemu/module.h"
321de7afc9SPaolo Bonzini #include "qemu/timer.h"
33f1ae32a1SGerd Hoffmann #include "hw/usb.h"
34d6454270SMarkus Armbruster #include "migration/vmstate.h"
35f1ae32a1SGerd Hoffmann #include "hw/sysbus.h"
369ac6a217SDavid Gibson #include "hw/qdev-dma.h"
37a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
38dc1f5988SAlexey Kardashevskiy #include "trace.h"
3934d97308SThomas Huth #include "hcd-ohci.h"
40f1ae32a1SGerd Hoffmann 
41f1ae32a1SGerd Hoffmann /* This causes frames to occur 1000x slower */
42f1ae32a1SGerd Hoffmann //#define OHCI_TIME_WARP 1
43f1ae32a1SGerd Hoffmann 
44ab6b1105SGerd Hoffmann #define ED_LINK_LIMIT 32
4595ed5693SLi Qiang 
46f1ae32a1SGerd Hoffmann static int64_t usb_frame_time;
47f1ae32a1SGerd Hoffmann static int64_t usb_bit_time;
48f1ae32a1SGerd Hoffmann 
49f1ae32a1SGerd Hoffmann /* Host Controller Communications Area */
50f1ae32a1SGerd Hoffmann struct ohci_hcca {
51f1ae32a1SGerd Hoffmann     uint32_t intr[32];
52f1ae32a1SGerd Hoffmann     uint16_t frame, pad;
53f1ae32a1SGerd Hoffmann     uint32_t done;
54f1ae32a1SGerd Hoffmann };
5586e18caeSWei Yang #define HCCA_WRITEBACK_OFFSET   offsetof(struct ohci_hcca, frame)
5686e18caeSWei Yang #define HCCA_WRITEBACK_SIZE     8 /* frame, pad, done */
5786e18caeSWei Yang 
5886e18caeSWei Yang #define ED_WBACK_OFFSET offsetof(struct ohci_ed, head)
5986e18caeSWei Yang #define ED_WBACK_SIZE   4
60f1ae32a1SGerd Hoffmann 
61f1ae32a1SGerd Hoffmann static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev);
62f1ae32a1SGerd Hoffmann 
63f1ae32a1SGerd Hoffmann /* Bitfields for the first word of an Endpoint Desciptor.  */
64f1ae32a1SGerd Hoffmann #define OHCI_ED_FA_SHIFT  0
65f1ae32a1SGerd Hoffmann #define OHCI_ED_FA_MASK   (0x7f<<OHCI_ED_FA_SHIFT)
66f1ae32a1SGerd Hoffmann #define OHCI_ED_EN_SHIFT  7
67f1ae32a1SGerd Hoffmann #define OHCI_ED_EN_MASK   (0xf<<OHCI_ED_EN_SHIFT)
68f1ae32a1SGerd Hoffmann #define OHCI_ED_D_SHIFT   11
69f1ae32a1SGerd Hoffmann #define OHCI_ED_D_MASK    (3<<OHCI_ED_D_SHIFT)
70f1ae32a1SGerd Hoffmann #define OHCI_ED_S         (1<<13)
71f1ae32a1SGerd Hoffmann #define OHCI_ED_K         (1<<14)
72f1ae32a1SGerd Hoffmann #define OHCI_ED_F         (1<<15)
73f1ae32a1SGerd Hoffmann #define OHCI_ED_MPS_SHIFT 16
74f1ae32a1SGerd Hoffmann #define OHCI_ED_MPS_MASK  (0x7ff<<OHCI_ED_MPS_SHIFT)
75f1ae32a1SGerd Hoffmann 
76f1ae32a1SGerd Hoffmann /* Flags in the head field of an Endpoint Desciptor.  */
77f1ae32a1SGerd Hoffmann #define OHCI_ED_H         1
78f1ae32a1SGerd Hoffmann #define OHCI_ED_C         2
79f1ae32a1SGerd Hoffmann 
80f1ae32a1SGerd Hoffmann /* Bitfields for the first word of a Transfer Desciptor.  */
81f1ae32a1SGerd Hoffmann #define OHCI_TD_R         (1<<18)
82f1ae32a1SGerd Hoffmann #define OHCI_TD_DP_SHIFT  19
83f1ae32a1SGerd Hoffmann #define OHCI_TD_DP_MASK   (3<<OHCI_TD_DP_SHIFT)
84f1ae32a1SGerd Hoffmann #define OHCI_TD_DI_SHIFT  21
85f1ae32a1SGerd Hoffmann #define OHCI_TD_DI_MASK   (7<<OHCI_TD_DI_SHIFT)
86f1ae32a1SGerd Hoffmann #define OHCI_TD_T0        (1<<24)
87f1ae32a1SGerd Hoffmann #define OHCI_TD_T1        (1<<25)
88f1ae32a1SGerd Hoffmann #define OHCI_TD_EC_SHIFT  26
89f1ae32a1SGerd Hoffmann #define OHCI_TD_EC_MASK   (3<<OHCI_TD_EC_SHIFT)
90f1ae32a1SGerd Hoffmann #define OHCI_TD_CC_SHIFT  28
91f1ae32a1SGerd Hoffmann #define OHCI_TD_CC_MASK   (0xf<<OHCI_TD_CC_SHIFT)
92f1ae32a1SGerd Hoffmann 
93f1ae32a1SGerd Hoffmann /* Bitfields for the first word of an Isochronous Transfer Desciptor.  */
94f1ae32a1SGerd Hoffmann /* CC & DI - same as in the General Transfer Desciptor */
95f1ae32a1SGerd Hoffmann #define OHCI_TD_SF_SHIFT  0
96f1ae32a1SGerd Hoffmann #define OHCI_TD_SF_MASK   (0xffff<<OHCI_TD_SF_SHIFT)
97f1ae32a1SGerd Hoffmann #define OHCI_TD_FC_SHIFT  24
98f1ae32a1SGerd Hoffmann #define OHCI_TD_FC_MASK   (7<<OHCI_TD_FC_SHIFT)
99f1ae32a1SGerd Hoffmann 
100f1ae32a1SGerd Hoffmann /* Isochronous Transfer Desciptor - Offset / PacketStatusWord */
101f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_CC_SHIFT 12
102f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_CC_MASK  (0xf<<OHCI_TD_PSW_CC_SHIFT)
103f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_SIZE_SHIFT 0
104f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_SIZE_MASK  (0xfff<<OHCI_TD_PSW_SIZE_SHIFT)
105f1ae32a1SGerd Hoffmann 
106f1ae32a1SGerd Hoffmann #define OHCI_PAGE_MASK    0xfffff000
107f1ae32a1SGerd Hoffmann #define OHCI_OFFSET_MASK  0xfff
108f1ae32a1SGerd Hoffmann 
109f1ae32a1SGerd Hoffmann #define OHCI_DPTR_MASK    0xfffffff0
110f1ae32a1SGerd Hoffmann 
111f1ae32a1SGerd Hoffmann #define OHCI_BM(val, field) \
112f1ae32a1SGerd Hoffmann   (((val) & OHCI_##field##_MASK) >> OHCI_##field##_SHIFT)
113f1ae32a1SGerd Hoffmann 
114f1ae32a1SGerd Hoffmann #define OHCI_SET_BM(val, field, newval) do { \
115f1ae32a1SGerd Hoffmann     val &= ~OHCI_##field##_MASK; \
116f1ae32a1SGerd Hoffmann     val |= ((newval) << OHCI_##field##_SHIFT) & OHCI_##field##_MASK; \
117f1ae32a1SGerd Hoffmann     } while(0)
118f1ae32a1SGerd Hoffmann 
119f1ae32a1SGerd Hoffmann /* endpoint descriptor */
120f1ae32a1SGerd Hoffmann struct ohci_ed {
121f1ae32a1SGerd Hoffmann     uint32_t flags;
122f1ae32a1SGerd Hoffmann     uint32_t tail;
123f1ae32a1SGerd Hoffmann     uint32_t head;
124f1ae32a1SGerd Hoffmann     uint32_t next;
125f1ae32a1SGerd Hoffmann };
126f1ae32a1SGerd Hoffmann 
127f1ae32a1SGerd Hoffmann /* General transfer descriptor */
128f1ae32a1SGerd Hoffmann struct ohci_td {
129f1ae32a1SGerd Hoffmann     uint32_t flags;
130f1ae32a1SGerd Hoffmann     uint32_t cbp;
131f1ae32a1SGerd Hoffmann     uint32_t next;
132f1ae32a1SGerd Hoffmann     uint32_t be;
133f1ae32a1SGerd Hoffmann };
134f1ae32a1SGerd Hoffmann 
135f1ae32a1SGerd Hoffmann /* Isochronous transfer descriptor */
136f1ae32a1SGerd Hoffmann struct ohci_iso_td {
137f1ae32a1SGerd Hoffmann     uint32_t flags;
138f1ae32a1SGerd Hoffmann     uint32_t bp;
139f1ae32a1SGerd Hoffmann     uint32_t next;
140f1ae32a1SGerd Hoffmann     uint32_t be;
141f1ae32a1SGerd Hoffmann     uint16_t offset[8];
142f1ae32a1SGerd Hoffmann };
143f1ae32a1SGerd Hoffmann 
144f1ae32a1SGerd Hoffmann #define USB_HZ                      12000000
145f1ae32a1SGerd Hoffmann 
146f1ae32a1SGerd Hoffmann /* OHCI Local stuff */
147f1ae32a1SGerd Hoffmann #define OHCI_CTL_CBSR         ((1<<0)|(1<<1))
148f1ae32a1SGerd Hoffmann #define OHCI_CTL_PLE          (1<<2)
149f1ae32a1SGerd Hoffmann #define OHCI_CTL_IE           (1<<3)
150f1ae32a1SGerd Hoffmann #define OHCI_CTL_CLE          (1<<4)
151f1ae32a1SGerd Hoffmann #define OHCI_CTL_BLE          (1<<5)
152f1ae32a1SGerd Hoffmann #define OHCI_CTL_HCFS         ((1<<6)|(1<<7))
153f1ae32a1SGerd Hoffmann #define  OHCI_USB_RESET       0x00
154f1ae32a1SGerd Hoffmann #define  OHCI_USB_RESUME      0x40
155f1ae32a1SGerd Hoffmann #define  OHCI_USB_OPERATIONAL 0x80
156f1ae32a1SGerd Hoffmann #define  OHCI_USB_SUSPEND     0xc0
157f1ae32a1SGerd Hoffmann #define OHCI_CTL_IR           (1<<8)
158f1ae32a1SGerd Hoffmann #define OHCI_CTL_RWC          (1<<9)
159f1ae32a1SGerd Hoffmann #define OHCI_CTL_RWE          (1<<10)
160f1ae32a1SGerd Hoffmann 
161f1ae32a1SGerd Hoffmann #define OHCI_STATUS_HCR       (1<<0)
162f1ae32a1SGerd Hoffmann #define OHCI_STATUS_CLF       (1<<1)
163f1ae32a1SGerd Hoffmann #define OHCI_STATUS_BLF       (1<<2)
164f1ae32a1SGerd Hoffmann #define OHCI_STATUS_OCR       (1<<3)
165f1ae32a1SGerd Hoffmann #define OHCI_STATUS_SOC       ((1<<6)|(1<<7))
166f1ae32a1SGerd Hoffmann 
16700b01793SPeter Maydell #define OHCI_INTR_SO          (1U<<0) /* Scheduling overrun */
16800b01793SPeter Maydell #define OHCI_INTR_WD          (1U<<1) /* HcDoneHead writeback */
16900b01793SPeter Maydell #define OHCI_INTR_SF          (1U<<2) /* Start of frame */
17000b01793SPeter Maydell #define OHCI_INTR_RD          (1U<<3) /* Resume detect */
17100b01793SPeter Maydell #define OHCI_INTR_UE          (1U<<4) /* Unrecoverable error */
17200b01793SPeter Maydell #define OHCI_INTR_FNO         (1U<<5) /* Frame number overflow */
17300b01793SPeter Maydell #define OHCI_INTR_RHSC        (1U<<6) /* Root hub status change */
17400b01793SPeter Maydell #define OHCI_INTR_OC          (1U<<30) /* Ownership change */
17500b01793SPeter Maydell #define OHCI_INTR_MIE         (1U<<31) /* Master Interrupt Enable */
176f1ae32a1SGerd Hoffmann 
177f1ae32a1SGerd Hoffmann #define OHCI_HCCA_SIZE        0x100
178f1ae32a1SGerd Hoffmann #define OHCI_HCCA_MASK        0xffffff00
179f1ae32a1SGerd Hoffmann 
180f1ae32a1SGerd Hoffmann #define OHCI_EDPTR_MASK       0xfffffff0
181f1ae32a1SGerd Hoffmann 
182f1ae32a1SGerd Hoffmann #define OHCI_FMI_FI           0x00003fff
183f1ae32a1SGerd Hoffmann #define OHCI_FMI_FSMPS        0xffff0000
184f1ae32a1SGerd Hoffmann #define OHCI_FMI_FIT          0x80000000
185f1ae32a1SGerd Hoffmann 
18600b01793SPeter Maydell #define OHCI_FR_RT            (1U<<31)
187f1ae32a1SGerd Hoffmann 
188f1ae32a1SGerd Hoffmann #define OHCI_LS_THRESH        0x628
189f1ae32a1SGerd Hoffmann 
190f1ae32a1SGerd Hoffmann #define OHCI_RHA_RW_MASK      0x00000000 /* Mask of supported features.  */
191f1ae32a1SGerd Hoffmann #define OHCI_RHA_PSM          (1<<8)
192f1ae32a1SGerd Hoffmann #define OHCI_RHA_NPS          (1<<9)
193f1ae32a1SGerd Hoffmann #define OHCI_RHA_DT           (1<<10)
194f1ae32a1SGerd Hoffmann #define OHCI_RHA_OCPM         (1<<11)
195f1ae32a1SGerd Hoffmann #define OHCI_RHA_NOCP         (1<<12)
196f1ae32a1SGerd Hoffmann #define OHCI_RHA_POTPGT_MASK  0xff000000
197f1ae32a1SGerd Hoffmann 
19800b01793SPeter Maydell #define OHCI_RHS_LPS          (1U<<0)
19900b01793SPeter Maydell #define OHCI_RHS_OCI          (1U<<1)
20000b01793SPeter Maydell #define OHCI_RHS_DRWE         (1U<<15)
20100b01793SPeter Maydell #define OHCI_RHS_LPSC         (1U<<16)
20200b01793SPeter Maydell #define OHCI_RHS_OCIC         (1U<<17)
20300b01793SPeter Maydell #define OHCI_RHS_CRWE         (1U<<31)
204f1ae32a1SGerd Hoffmann 
205f1ae32a1SGerd Hoffmann #define OHCI_PORT_CCS         (1<<0)
206f1ae32a1SGerd Hoffmann #define OHCI_PORT_PES         (1<<1)
207f1ae32a1SGerd Hoffmann #define OHCI_PORT_PSS         (1<<2)
208f1ae32a1SGerd Hoffmann #define OHCI_PORT_POCI        (1<<3)
209f1ae32a1SGerd Hoffmann #define OHCI_PORT_PRS         (1<<4)
210f1ae32a1SGerd Hoffmann #define OHCI_PORT_PPS         (1<<8)
211f1ae32a1SGerd Hoffmann #define OHCI_PORT_LSDA        (1<<9)
212f1ae32a1SGerd Hoffmann #define OHCI_PORT_CSC         (1<<16)
213f1ae32a1SGerd Hoffmann #define OHCI_PORT_PESC        (1<<17)
214f1ae32a1SGerd Hoffmann #define OHCI_PORT_PSSC        (1<<18)
215f1ae32a1SGerd Hoffmann #define OHCI_PORT_OCIC        (1<<19)
216f1ae32a1SGerd Hoffmann #define OHCI_PORT_PRSC        (1<<20)
217f1ae32a1SGerd Hoffmann #define OHCI_PORT_WTC         (OHCI_PORT_CSC|OHCI_PORT_PESC|OHCI_PORT_PSSC \
218f1ae32a1SGerd Hoffmann                                |OHCI_PORT_OCIC|OHCI_PORT_PRSC)
219f1ae32a1SGerd Hoffmann 
220f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_SETUP     0x0
221f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_OUT       0x1
222f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_IN        0x2
223f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_RESERVED  0x3
224f1ae32a1SGerd Hoffmann 
225f1ae32a1SGerd Hoffmann #define OHCI_CC_NOERROR             0x0
226f1ae32a1SGerd Hoffmann #define OHCI_CC_CRC                 0x1
227f1ae32a1SGerd Hoffmann #define OHCI_CC_BITSTUFFING         0x2
228f1ae32a1SGerd Hoffmann #define OHCI_CC_DATATOGGLEMISMATCH  0x3
229f1ae32a1SGerd Hoffmann #define OHCI_CC_STALL               0x4
230f1ae32a1SGerd Hoffmann #define OHCI_CC_DEVICENOTRESPONDING 0x5
231f1ae32a1SGerd Hoffmann #define OHCI_CC_PIDCHECKFAILURE     0x6
232f1ae32a1SGerd Hoffmann #define OHCI_CC_UNDEXPETEDPID       0x7
233f1ae32a1SGerd Hoffmann #define OHCI_CC_DATAOVERRUN         0x8
234f1ae32a1SGerd Hoffmann #define OHCI_CC_DATAUNDERRUN        0x9
235f1ae32a1SGerd Hoffmann #define OHCI_CC_BUFFEROVERRUN       0xc
236f1ae32a1SGerd Hoffmann #define OHCI_CC_BUFFERUNDERRUN      0xd
237f1ae32a1SGerd Hoffmann 
238f1ae32a1SGerd Hoffmann #define OHCI_HRESET_FSBIR       (1 << 0)
239f1ae32a1SGerd Hoffmann 
24072e0c127SThomas Huth static void ohci_die(OHCIState *ohci)
24172e0c127SThomas Huth {
24272e0c127SThomas Huth     ohci->ohci_die(ohci);
24372e0c127SThomas Huth }
244cf66ee8eSAlexey Kardashevskiy 
245f1ae32a1SGerd Hoffmann /* Update IRQ levels */
246f1ae32a1SGerd Hoffmann static inline void ohci_intr_update(OHCIState *ohci)
247f1ae32a1SGerd Hoffmann {
248f1ae32a1SGerd Hoffmann     int level = 0;
249f1ae32a1SGerd Hoffmann 
250f1ae32a1SGerd Hoffmann     if ((ohci->intr & OHCI_INTR_MIE) &&
251f1ae32a1SGerd Hoffmann         (ohci->intr_status & ohci->intr))
252f1ae32a1SGerd Hoffmann         level = 1;
253f1ae32a1SGerd Hoffmann 
254f1ae32a1SGerd Hoffmann     qemu_set_irq(ohci->irq, level);
255f1ae32a1SGerd Hoffmann }
256f1ae32a1SGerd Hoffmann 
257f1ae32a1SGerd Hoffmann /* Set an interrupt */
258f1ae32a1SGerd Hoffmann static inline void ohci_set_interrupt(OHCIState *ohci, uint32_t intr)
259f1ae32a1SGerd Hoffmann {
260f1ae32a1SGerd Hoffmann     ohci->intr_status |= intr;
261f1ae32a1SGerd Hoffmann     ohci_intr_update(ohci);
262f1ae32a1SGerd Hoffmann }
263f1ae32a1SGerd Hoffmann 
264f1ae32a1SGerd Hoffmann /* Attach or detach a device on a root hub port.  */
265f1ae32a1SGerd Hoffmann static void ohci_attach(USBPort *port1)
266f1ae32a1SGerd Hoffmann {
267f1ae32a1SGerd Hoffmann     OHCIState *s = port1->opaque;
268f1ae32a1SGerd Hoffmann     OHCIPort *port = &s->rhport[port1->index];
269f1ae32a1SGerd Hoffmann     uint32_t old_state = port->ctrl;
270f1ae32a1SGerd Hoffmann 
271f1ae32a1SGerd Hoffmann     /* set connect status */
272f1ae32a1SGerd Hoffmann     port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;
273f1ae32a1SGerd Hoffmann 
274f1ae32a1SGerd Hoffmann     /* update speed */
275f1ae32a1SGerd Hoffmann     if (port->port.dev->speed == USB_SPEED_LOW) {
276f1ae32a1SGerd Hoffmann         port->ctrl |= OHCI_PORT_LSDA;
277f1ae32a1SGerd Hoffmann     } else {
278f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_LSDA;
279f1ae32a1SGerd Hoffmann     }
280f1ae32a1SGerd Hoffmann 
281f1ae32a1SGerd Hoffmann     /* notify of remote-wakeup */
282f1ae32a1SGerd Hoffmann     if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
283f1ae32a1SGerd Hoffmann         ohci_set_interrupt(s, OHCI_INTR_RD);
284f1ae32a1SGerd Hoffmann     }
285f1ae32a1SGerd Hoffmann 
286dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_port_attach(port1->index);
287f1ae32a1SGerd Hoffmann 
288f1ae32a1SGerd Hoffmann     if (old_state != port->ctrl) {
289f1ae32a1SGerd Hoffmann         ohci_set_interrupt(s, OHCI_INTR_RHSC);
290f1ae32a1SGerd Hoffmann     }
291f1ae32a1SGerd Hoffmann }
292f1ae32a1SGerd Hoffmann 
293f1ae32a1SGerd Hoffmann static void ohci_detach(USBPort *port1)
294f1ae32a1SGerd Hoffmann {
295f1ae32a1SGerd Hoffmann     OHCIState *s = port1->opaque;
296f1ae32a1SGerd Hoffmann     OHCIPort *port = &s->rhport[port1->index];
297f1ae32a1SGerd Hoffmann     uint32_t old_state = port->ctrl;
298f1ae32a1SGerd Hoffmann 
299f1ae32a1SGerd Hoffmann     ohci_async_cancel_device(s, port1->dev);
300f1ae32a1SGerd Hoffmann 
301f1ae32a1SGerd Hoffmann     /* set connect status */
302f1ae32a1SGerd Hoffmann     if (port->ctrl & OHCI_PORT_CCS) {
303f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_CCS;
304f1ae32a1SGerd Hoffmann         port->ctrl |= OHCI_PORT_CSC;
305f1ae32a1SGerd Hoffmann     }
306f1ae32a1SGerd Hoffmann     /* disable port */
307f1ae32a1SGerd Hoffmann     if (port->ctrl & OHCI_PORT_PES) {
308f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_PES;
309f1ae32a1SGerd Hoffmann         port->ctrl |= OHCI_PORT_PESC;
310f1ae32a1SGerd Hoffmann     }
311dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_port_detach(port1->index);
312f1ae32a1SGerd Hoffmann 
313f1ae32a1SGerd Hoffmann     if (old_state != port->ctrl) {
314f1ae32a1SGerd Hoffmann         ohci_set_interrupt(s, OHCI_INTR_RHSC);
315f1ae32a1SGerd Hoffmann     }
316f1ae32a1SGerd Hoffmann }
317f1ae32a1SGerd Hoffmann 
318f1ae32a1SGerd Hoffmann static void ohci_wakeup(USBPort *port1)
319f1ae32a1SGerd Hoffmann {
320f1ae32a1SGerd Hoffmann     OHCIState *s = port1->opaque;
321f1ae32a1SGerd Hoffmann     OHCIPort *port = &s->rhport[port1->index];
322f1ae32a1SGerd Hoffmann     uint32_t intr = 0;
323f1ae32a1SGerd Hoffmann     if (port->ctrl & OHCI_PORT_PSS) {
324dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_port_wakeup(port1->index);
325f1ae32a1SGerd Hoffmann         port->ctrl |= OHCI_PORT_PSSC;
326f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_PSS;
327f1ae32a1SGerd Hoffmann         intr = OHCI_INTR_RHSC;
328f1ae32a1SGerd Hoffmann     }
329f1ae32a1SGerd Hoffmann     /* Note that the controller can be suspended even if this port is not */
330f1ae32a1SGerd Hoffmann     if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
331dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_remote_wakeup(s->name);
332f1ae32a1SGerd Hoffmann         /* This is the one state transition the controller can do by itself */
333f1ae32a1SGerd Hoffmann         s->ctl &= ~OHCI_CTL_HCFS;
334f1ae32a1SGerd Hoffmann         s->ctl |= OHCI_USB_RESUME;
335f1ae32a1SGerd Hoffmann         /* In suspend mode only ResumeDetected is possible, not RHSC:
336f1ae32a1SGerd Hoffmann          * see the OHCI spec 5.1.2.3.
337f1ae32a1SGerd Hoffmann          */
338f1ae32a1SGerd Hoffmann         intr = OHCI_INTR_RD;
339f1ae32a1SGerd Hoffmann     }
340f1ae32a1SGerd Hoffmann     ohci_set_interrupt(s, intr);
341f1ae32a1SGerd Hoffmann }
342f1ae32a1SGerd Hoffmann 
343f1ae32a1SGerd Hoffmann static void ohci_child_detach(USBPort *port1, USBDevice *child)
344f1ae32a1SGerd Hoffmann {
345f1ae32a1SGerd Hoffmann     OHCIState *s = port1->opaque;
346f1ae32a1SGerd Hoffmann 
347f1ae32a1SGerd Hoffmann     ohci_async_cancel_device(s, child);
348f1ae32a1SGerd Hoffmann }
349f1ae32a1SGerd Hoffmann 
350f1ae32a1SGerd Hoffmann static USBDevice *ohci_find_device(OHCIState *ohci, uint8_t addr)
351f1ae32a1SGerd Hoffmann {
352f1ae32a1SGerd Hoffmann     USBDevice *dev;
353f1ae32a1SGerd Hoffmann     int i;
354f1ae32a1SGerd Hoffmann 
355f1ae32a1SGerd Hoffmann     for (i = 0; i < ohci->num_ports; i++) {
356f1ae32a1SGerd Hoffmann         if ((ohci->rhport[i].ctrl & OHCI_PORT_PES) == 0) {
357f1ae32a1SGerd Hoffmann             continue;
358f1ae32a1SGerd Hoffmann         }
359f1ae32a1SGerd Hoffmann         dev = usb_find_device(&ohci->rhport[i].port, addr);
360f1ae32a1SGerd Hoffmann         if (dev != NULL) {
361f1ae32a1SGerd Hoffmann             return dev;
362f1ae32a1SGerd Hoffmann         }
363f1ae32a1SGerd Hoffmann     }
364f1ae32a1SGerd Hoffmann     return NULL;
365f1ae32a1SGerd Hoffmann }
366f1ae32a1SGerd Hoffmann 
36734d97308SThomas Huth void ohci_stop_endpoints(OHCIState *ohci)
368f79738b0SHans de Goede {
369f79738b0SHans de Goede     USBDevice *dev;
370f79738b0SHans de Goede     int i, j;
371f79738b0SHans de Goede 
372f79738b0SHans de Goede     for (i = 0; i < ohci->num_ports; i++) {
373f79738b0SHans de Goede         dev = ohci->rhport[i].port.dev;
374f79738b0SHans de Goede         if (dev && dev->attached) {
375f79738b0SHans de Goede             usb_device_ep_stopped(dev, &dev->ep_ctl);
376f79738b0SHans de Goede             for (j = 0; j < USB_MAX_ENDPOINTS; j++) {
377f79738b0SHans de Goede                 usb_device_ep_stopped(dev, &dev->ep_in[j]);
378f79738b0SHans de Goede                 usb_device_ep_stopped(dev, &dev->ep_out[j]);
379f79738b0SHans de Goede             }
380f79738b0SHans de Goede         }
381f79738b0SHans de Goede     }
382f79738b0SHans de Goede }
383f79738b0SHans de Goede 
38484d04e21SHervé Poussineau static void ohci_roothub_reset(OHCIState *ohci)
385f1ae32a1SGerd Hoffmann {
386f1ae32a1SGerd Hoffmann     OHCIPort *port;
387f1ae32a1SGerd Hoffmann     int i;
388f1ae32a1SGerd Hoffmann 
389f1ae32a1SGerd Hoffmann     ohci_bus_stop(ohci);
39084d04e21SHervé Poussineau     ohci->rhdesc_a = OHCI_RHA_NPS | ohci->num_ports;
39184d04e21SHervé Poussineau     ohci->rhdesc_b = 0x0; /* Impl. specific */
39284d04e21SHervé Poussineau     ohci->rhstatus = 0;
39384d04e21SHervé Poussineau 
39484d04e21SHervé Poussineau     for (i = 0; i < ohci->num_ports; i++) {
39584d04e21SHervé Poussineau         port = &ohci->rhport[i];
39684d04e21SHervé Poussineau         port->ctrl = 0;
39784d04e21SHervé Poussineau         if (port->port.dev && port->port.dev->attached) {
39884d04e21SHervé Poussineau             usb_port_reset(&port->port);
39984d04e21SHervé Poussineau         }
40084d04e21SHervé Poussineau     }
40184d04e21SHervé Poussineau     if (ohci->async_td) {
40284d04e21SHervé Poussineau         usb_cancel_packet(&ohci->usb_packet);
40384d04e21SHervé Poussineau         ohci->async_td = 0;
40484d04e21SHervé Poussineau     }
40584d04e21SHervé Poussineau     ohci_stop_endpoints(ohci);
40684d04e21SHervé Poussineau }
40784d04e21SHervé Poussineau 
40884d04e21SHervé Poussineau /* Reset the controller */
40984d04e21SHervé Poussineau static void ohci_soft_reset(OHCIState *ohci)
41084d04e21SHervé Poussineau {
41184d04e21SHervé Poussineau     trace_usb_ohci_reset(ohci->name);
41284d04e21SHervé Poussineau 
41384d04e21SHervé Poussineau     ohci_bus_stop(ohci);
41484d04e21SHervé Poussineau     ohci->ctl = (ohci->ctl & OHCI_CTL_IR) | OHCI_USB_SUSPEND;
415f1ae32a1SGerd Hoffmann     ohci->old_ctl = 0;
416f1ae32a1SGerd Hoffmann     ohci->status = 0;
417f1ae32a1SGerd Hoffmann     ohci->intr_status = 0;
418f1ae32a1SGerd Hoffmann     ohci->intr = OHCI_INTR_MIE;
419f1ae32a1SGerd Hoffmann 
420f1ae32a1SGerd Hoffmann     ohci->hcca = 0;
421f1ae32a1SGerd Hoffmann     ohci->ctrl_head = ohci->ctrl_cur = 0;
422f1ae32a1SGerd Hoffmann     ohci->bulk_head = ohci->bulk_cur = 0;
423f1ae32a1SGerd Hoffmann     ohci->per_cur = 0;
424f1ae32a1SGerd Hoffmann     ohci->done = 0;
425f1ae32a1SGerd Hoffmann     ohci->done_count = 7;
426f1ae32a1SGerd Hoffmann 
427f1ae32a1SGerd Hoffmann     /* FSMPS is marked TBD in OCHI 1.0, what gives ffs?
428f1ae32a1SGerd Hoffmann      * I took the value linux sets ...
429f1ae32a1SGerd Hoffmann      */
430f1ae32a1SGerd Hoffmann     ohci->fsmps = 0x2778;
431f1ae32a1SGerd Hoffmann     ohci->fi = 0x2edf;
432f1ae32a1SGerd Hoffmann     ohci->fit = 0;
433f1ae32a1SGerd Hoffmann     ohci->frt = 0;
434f1ae32a1SGerd Hoffmann     ohci->frame_number = 0;
435f1ae32a1SGerd Hoffmann     ohci->pstart = 0;
436f1ae32a1SGerd Hoffmann     ohci->lst = OHCI_LS_THRESH;
43784d04e21SHervé Poussineau }
438f1ae32a1SGerd Hoffmann 
43934d97308SThomas Huth void ohci_hard_reset(OHCIState *ohci)
440f1ae32a1SGerd Hoffmann {
44184d04e21SHervé Poussineau     ohci_soft_reset(ohci);
44284d04e21SHervé Poussineau     ohci->ctl = 0;
44384d04e21SHervé Poussineau     ohci_roothub_reset(ohci);
444f1ae32a1SGerd Hoffmann }
445f1ae32a1SGerd Hoffmann 
446f1ae32a1SGerd Hoffmann /* Get an array of dwords from main memory */
447f1ae32a1SGerd Hoffmann static inline int get_dwords(OHCIState *ohci,
4489ac6a217SDavid Gibson                              dma_addr_t addr, uint32_t *buf, int num)
449f1ae32a1SGerd Hoffmann {
450f1ae32a1SGerd Hoffmann     int i;
451f1ae32a1SGerd Hoffmann 
452f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
453f1ae32a1SGerd Hoffmann 
454f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
455*ba06fe8aSPhilippe Mathieu-Daudé         if (dma_memory_read(ohci->as, addr,
456*ba06fe8aSPhilippe Mathieu-Daudé                             buf, sizeof(*buf), MEMTXATTRS_UNSPECIFIED)) {
457cf66ee8eSAlexey Kardashevskiy             return -1;
458cf66ee8eSAlexey Kardashevskiy         }
459f1ae32a1SGerd Hoffmann         *buf = le32_to_cpu(*buf);
460f1ae32a1SGerd Hoffmann     }
461f1ae32a1SGerd Hoffmann 
462cf66ee8eSAlexey Kardashevskiy     return 0;
463f1ae32a1SGerd Hoffmann }
464f1ae32a1SGerd Hoffmann 
465f1ae32a1SGerd Hoffmann /* Put an array of dwords in to main memory */
466f1ae32a1SGerd Hoffmann static inline int put_dwords(OHCIState *ohci,
4679ac6a217SDavid Gibson                              dma_addr_t addr, uint32_t *buf, int num)
468f1ae32a1SGerd Hoffmann {
469f1ae32a1SGerd Hoffmann     int i;
470f1ae32a1SGerd Hoffmann 
471f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
472f1ae32a1SGerd Hoffmann 
473f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
474f1ae32a1SGerd Hoffmann         uint32_t tmp = cpu_to_le32(*buf);
475*ba06fe8aSPhilippe Mathieu-Daudé         if (dma_memory_write(ohci->as, addr,
476*ba06fe8aSPhilippe Mathieu-Daudé                              &tmp, sizeof(tmp), MEMTXATTRS_UNSPECIFIED)) {
477cf66ee8eSAlexey Kardashevskiy             return -1;
478cf66ee8eSAlexey Kardashevskiy         }
479f1ae32a1SGerd Hoffmann     }
480f1ae32a1SGerd Hoffmann 
481cf66ee8eSAlexey Kardashevskiy     return 0;
482f1ae32a1SGerd Hoffmann }
483f1ae32a1SGerd Hoffmann 
484f1ae32a1SGerd Hoffmann /* Get an array of words from main memory */
485f1ae32a1SGerd Hoffmann static inline int get_words(OHCIState *ohci,
4869ac6a217SDavid Gibson                             dma_addr_t addr, uint16_t *buf, int num)
487f1ae32a1SGerd Hoffmann {
488f1ae32a1SGerd Hoffmann     int i;
489f1ae32a1SGerd Hoffmann 
490f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
491f1ae32a1SGerd Hoffmann 
492f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
493*ba06fe8aSPhilippe Mathieu-Daudé         if (dma_memory_read(ohci->as, addr,
494*ba06fe8aSPhilippe Mathieu-Daudé                             buf, sizeof(*buf), MEMTXATTRS_UNSPECIFIED)) {
495cf66ee8eSAlexey Kardashevskiy             return -1;
496cf66ee8eSAlexey Kardashevskiy         }
497f1ae32a1SGerd Hoffmann         *buf = le16_to_cpu(*buf);
498f1ae32a1SGerd Hoffmann     }
499f1ae32a1SGerd Hoffmann 
500cf66ee8eSAlexey Kardashevskiy     return 0;
501f1ae32a1SGerd Hoffmann }
502f1ae32a1SGerd Hoffmann 
503f1ae32a1SGerd Hoffmann /* Put an array of words in to main memory */
504f1ae32a1SGerd Hoffmann static inline int put_words(OHCIState *ohci,
5059ac6a217SDavid Gibson                             dma_addr_t addr, uint16_t *buf, int num)
506f1ae32a1SGerd Hoffmann {
507f1ae32a1SGerd Hoffmann     int i;
508f1ae32a1SGerd Hoffmann 
509f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
510f1ae32a1SGerd Hoffmann 
511f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
512f1ae32a1SGerd Hoffmann         uint16_t tmp = cpu_to_le16(*buf);
513*ba06fe8aSPhilippe Mathieu-Daudé         if (dma_memory_write(ohci->as, addr,
514*ba06fe8aSPhilippe Mathieu-Daudé                              &tmp, sizeof(tmp), MEMTXATTRS_UNSPECIFIED)) {
515cf66ee8eSAlexey Kardashevskiy             return -1;
516cf66ee8eSAlexey Kardashevskiy         }
517f1ae32a1SGerd Hoffmann     }
518f1ae32a1SGerd Hoffmann 
519cf66ee8eSAlexey Kardashevskiy     return 0;
520f1ae32a1SGerd Hoffmann }
521f1ae32a1SGerd Hoffmann 
522f1ae32a1SGerd Hoffmann static inline int ohci_read_ed(OHCIState *ohci,
5239ac6a217SDavid Gibson                                dma_addr_t addr, struct ohci_ed *ed)
524f1ae32a1SGerd Hoffmann {
525f1ae32a1SGerd Hoffmann     return get_dwords(ohci, addr, (uint32_t *)ed, sizeof(*ed) >> 2);
526f1ae32a1SGerd Hoffmann }
527f1ae32a1SGerd Hoffmann 
528f1ae32a1SGerd Hoffmann static inline int ohci_read_td(OHCIState *ohci,
5299ac6a217SDavid Gibson                                dma_addr_t addr, struct ohci_td *td)
530f1ae32a1SGerd Hoffmann {
531f1ae32a1SGerd Hoffmann     return get_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2);
532f1ae32a1SGerd Hoffmann }
533f1ae32a1SGerd Hoffmann 
534f1ae32a1SGerd Hoffmann static inline int ohci_read_iso_td(OHCIState *ohci,
5359ac6a217SDavid Gibson                                    dma_addr_t addr, struct ohci_iso_td *td)
536f1ae32a1SGerd Hoffmann {
537cf66ee8eSAlexey Kardashevskiy     return get_dwords(ohci, addr, (uint32_t *)td, 4) ||
538cf66ee8eSAlexey Kardashevskiy            get_words(ohci, addr + 16, td->offset, 8);
539f1ae32a1SGerd Hoffmann }
540f1ae32a1SGerd Hoffmann 
541f1ae32a1SGerd Hoffmann static inline int ohci_read_hcca(OHCIState *ohci,
5429ac6a217SDavid Gibson                                  dma_addr_t addr, struct ohci_hcca *hcca)
543f1ae32a1SGerd Hoffmann {
544*ba06fe8aSPhilippe Mathieu-Daudé     return dma_memory_read(ohci->as, addr + ohci->localmem_base, hcca,
545*ba06fe8aSPhilippe Mathieu-Daudé                            sizeof(*hcca), MEMTXATTRS_UNSPECIFIED);
546f1ae32a1SGerd Hoffmann }
547f1ae32a1SGerd Hoffmann 
548f1ae32a1SGerd Hoffmann static inline int ohci_put_ed(OHCIState *ohci,
5499ac6a217SDavid Gibson                               dma_addr_t addr, struct ohci_ed *ed)
550f1ae32a1SGerd Hoffmann {
55186e18caeSWei Yang     /* ed->tail is under control of the HCD.
55286e18caeSWei Yang      * Since just ed->head is changed by HC, just write back this
55386e18caeSWei Yang      */
55486e18caeSWei Yang 
55586e18caeSWei Yang     return put_dwords(ohci, addr + ED_WBACK_OFFSET,
55686e18caeSWei Yang                       (uint32_t *)((char *)ed + ED_WBACK_OFFSET),
55786e18caeSWei Yang                       ED_WBACK_SIZE >> 2);
558f1ae32a1SGerd Hoffmann }
559f1ae32a1SGerd Hoffmann 
560f1ae32a1SGerd Hoffmann static inline int ohci_put_td(OHCIState *ohci,
5619ac6a217SDavid Gibson                               dma_addr_t addr, struct ohci_td *td)
562f1ae32a1SGerd Hoffmann {
563f1ae32a1SGerd Hoffmann     return put_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2);
564f1ae32a1SGerd Hoffmann }
565f1ae32a1SGerd Hoffmann 
566f1ae32a1SGerd Hoffmann static inline int ohci_put_iso_td(OHCIState *ohci,
5679ac6a217SDavid Gibson                                   dma_addr_t addr, struct ohci_iso_td *td)
568f1ae32a1SGerd Hoffmann {
569cae7f29cSJack Un     return put_dwords(ohci, addr, (uint32_t *)td, 4) ||
570cae7f29cSJack Un            put_words(ohci, addr + 16, td->offset, 8);
571f1ae32a1SGerd Hoffmann }
572f1ae32a1SGerd Hoffmann 
573f1ae32a1SGerd Hoffmann static inline int ohci_put_hcca(OHCIState *ohci,
5749ac6a217SDavid Gibson                                 dma_addr_t addr, struct ohci_hcca *hcca)
575f1ae32a1SGerd Hoffmann {
576cf66ee8eSAlexey Kardashevskiy     return dma_memory_write(ohci->as,
5779ac6a217SDavid Gibson                             addr + ohci->localmem_base + HCCA_WRITEBACK_OFFSET,
57886e18caeSWei Yang                             (char *)hcca + HCCA_WRITEBACK_OFFSET,
579*ba06fe8aSPhilippe Mathieu-Daudé                             HCCA_WRITEBACK_SIZE, MEMTXATTRS_UNSPECIFIED);
580f1ae32a1SGerd Hoffmann }
581f1ae32a1SGerd Hoffmann 
582f1ae32a1SGerd Hoffmann /* Read/Write the contents of a TD from/to main memory.  */
583cf66ee8eSAlexey Kardashevskiy static int ohci_copy_td(OHCIState *ohci, struct ohci_td *td,
5849ac6a217SDavid Gibson                         uint8_t *buf, int len, DMADirection dir)
585f1ae32a1SGerd Hoffmann {
5869ac6a217SDavid Gibson     dma_addr_t ptr, n;
587f1ae32a1SGerd Hoffmann 
588f1ae32a1SGerd Hoffmann     ptr = td->cbp;
589f1ae32a1SGerd Hoffmann     n = 0x1000 - (ptr & 0xfff);
590f1ae32a1SGerd Hoffmann     if (n > len)
591f1ae32a1SGerd Hoffmann         n = len;
592cf66ee8eSAlexey Kardashevskiy 
59323faf569SPhilippe Mathieu-Daudé     if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf,
59423faf569SPhilippe Mathieu-Daudé                       n, dir, MEMTXATTRS_UNSPECIFIED)) {
595cf66ee8eSAlexey Kardashevskiy         return -1;
596cf66ee8eSAlexey Kardashevskiy     }
597cf66ee8eSAlexey Kardashevskiy     if (n == len) {
598cf66ee8eSAlexey Kardashevskiy         return 0;
599cf66ee8eSAlexey Kardashevskiy     }
600f1ae32a1SGerd Hoffmann     ptr = td->be & ~0xfffu;
601f1ae32a1SGerd Hoffmann     buf += n;
602cf66ee8eSAlexey Kardashevskiy     if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf,
60323faf569SPhilippe Mathieu-Daudé                       len - n, dir, MEMTXATTRS_UNSPECIFIED)) {
604cf66ee8eSAlexey Kardashevskiy         return -1;
605cf66ee8eSAlexey Kardashevskiy     }
606cf66ee8eSAlexey Kardashevskiy     return 0;
607f1ae32a1SGerd Hoffmann }
608f1ae32a1SGerd Hoffmann 
609f1ae32a1SGerd Hoffmann /* Read/Write the contents of an ISO TD from/to main memory.  */
610cf66ee8eSAlexey Kardashevskiy static int ohci_copy_iso_td(OHCIState *ohci,
611f1ae32a1SGerd Hoffmann                             uint32_t start_addr, uint32_t end_addr,
6129ac6a217SDavid Gibson                             uint8_t *buf, int len, DMADirection dir)
613f1ae32a1SGerd Hoffmann {
6149ac6a217SDavid Gibson     dma_addr_t ptr, n;
615f1ae32a1SGerd Hoffmann 
616f1ae32a1SGerd Hoffmann     ptr = start_addr;
617f1ae32a1SGerd Hoffmann     n = 0x1000 - (ptr & 0xfff);
618f1ae32a1SGerd Hoffmann     if (n > len)
619f1ae32a1SGerd Hoffmann         n = len;
620cf66ee8eSAlexey Kardashevskiy 
62123faf569SPhilippe Mathieu-Daudé     if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf,
62223faf569SPhilippe Mathieu-Daudé                       n, dir, MEMTXATTRS_UNSPECIFIED)) {
623cf66ee8eSAlexey Kardashevskiy         return -1;
624cf66ee8eSAlexey Kardashevskiy     }
625cf66ee8eSAlexey Kardashevskiy     if (n == len) {
626cf66ee8eSAlexey Kardashevskiy         return 0;
627cf66ee8eSAlexey Kardashevskiy     }
628f1ae32a1SGerd Hoffmann     ptr = end_addr & ~0xfffu;
629f1ae32a1SGerd Hoffmann     buf += n;
630cf66ee8eSAlexey Kardashevskiy     if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf,
63123faf569SPhilippe Mathieu-Daudé                       len - n, dir, MEMTXATTRS_UNSPECIFIED)) {
632cf66ee8eSAlexey Kardashevskiy         return -1;
633cf66ee8eSAlexey Kardashevskiy     }
634cf66ee8eSAlexey Kardashevskiy     return 0;
635f1ae32a1SGerd Hoffmann }
636f1ae32a1SGerd Hoffmann 
637f1ae32a1SGerd Hoffmann static void ohci_process_lists(OHCIState *ohci, int completion);
638f1ae32a1SGerd Hoffmann 
639f1ae32a1SGerd Hoffmann static void ohci_async_complete_packet(USBPort *port, USBPacket *packet)
640f1ae32a1SGerd Hoffmann {
641f1ae32a1SGerd Hoffmann     OHCIState *ohci = container_of(packet, OHCIState, usb_packet);
642dc1f5988SAlexey Kardashevskiy 
643dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_async_complete();
64469e25d26SAlexey Kardashevskiy     ohci->async_complete = true;
645f1ae32a1SGerd Hoffmann     ohci_process_lists(ohci, 1);
646f1ae32a1SGerd Hoffmann }
647f1ae32a1SGerd Hoffmann 
648f1ae32a1SGerd Hoffmann #define USUB(a, b) ((int16_t)((uint16_t)(a) - (uint16_t)(b)))
649f1ae32a1SGerd Hoffmann 
650f1ae32a1SGerd Hoffmann static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
651f1ae32a1SGerd Hoffmann                                int completion)
652f1ae32a1SGerd Hoffmann {
653f1ae32a1SGerd Hoffmann     int dir;
654f1ae32a1SGerd Hoffmann     size_t len = 0;
655f1ae32a1SGerd Hoffmann     const char *str = NULL;
656f1ae32a1SGerd Hoffmann     int pid;
657f1ae32a1SGerd Hoffmann     int ret;
658f1ae32a1SGerd Hoffmann     int i;
659f1ae32a1SGerd Hoffmann     USBDevice *dev;
660f1ae32a1SGerd Hoffmann     USBEndpoint *ep;
661f1ae32a1SGerd Hoffmann     struct ohci_iso_td iso_td;
662f1ae32a1SGerd Hoffmann     uint32_t addr;
663f1ae32a1SGerd Hoffmann     uint16_t starting_frame;
664f1ae32a1SGerd Hoffmann     int16_t relative_frame_number;
665f1ae32a1SGerd Hoffmann     int frame_count;
666f1ae32a1SGerd Hoffmann     uint32_t start_offset, next_offset, end_offset = 0;
667f1ae32a1SGerd Hoffmann     uint32_t start_addr, end_addr;
668f1ae32a1SGerd Hoffmann 
669f1ae32a1SGerd Hoffmann     addr = ed->head & OHCI_DPTR_MASK;
670f1ae32a1SGerd Hoffmann 
671cf66ee8eSAlexey Kardashevskiy     if (ohci_read_iso_td(ohci, addr, &iso_td)) {
672dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_read_failed(addr);
673cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
67426f670a2SLi Qiang         return 1;
675f1ae32a1SGerd Hoffmann     }
676f1ae32a1SGerd Hoffmann 
677f1ae32a1SGerd Hoffmann     starting_frame = OHCI_BM(iso_td.flags, TD_SF);
678f1ae32a1SGerd Hoffmann     frame_count = OHCI_BM(iso_td.flags, TD_FC);
679f1ae32a1SGerd Hoffmann     relative_frame_number = USUB(ohci->frame_number, starting_frame);
680f1ae32a1SGerd Hoffmann 
681dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_iso_td_head(
682f1ae32a1SGerd Hoffmann            ed->head & OHCI_DPTR_MASK, ed->tail & OHCI_DPTR_MASK,
683f1ae32a1SGerd Hoffmann            iso_td.flags, iso_td.bp, iso_td.next, iso_td.be,
684f1ae32a1SGerd Hoffmann            ohci->frame_number, starting_frame,
685bc0d104cSAlex Bennée            frame_count, relative_frame_number);
6863af8f177SAlexey Kardashevskiy     trace_usb_ohci_iso_td_head_offset(
6873af8f177SAlexey Kardashevskiy            iso_td.offset[0], iso_td.offset[1],
6883af8f177SAlexey Kardashevskiy            iso_td.offset[2], iso_td.offset[3],
6893af8f177SAlexey Kardashevskiy            iso_td.offset[4], iso_td.offset[5],
6903af8f177SAlexey Kardashevskiy            iso_td.offset[6], iso_td.offset[7]);
691f1ae32a1SGerd Hoffmann 
692f1ae32a1SGerd Hoffmann     if (relative_frame_number < 0) {
693dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_relative_frame_number_neg(relative_frame_number);
694f1ae32a1SGerd Hoffmann         return 1;
695f1ae32a1SGerd Hoffmann     } else if (relative_frame_number > frame_count) {
696f1ae32a1SGerd Hoffmann         /* ISO TD expired - retire the TD to the Done Queue and continue with
697f1ae32a1SGerd Hoffmann            the next ISO TD of the same ED */
698dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_relative_frame_number_big(relative_frame_number,
699f1ae32a1SGerd Hoffmann                                                         frame_count);
7001be90ebeSPrasad J Pandit         if (OHCI_CC_DATAOVERRUN == OHCI_BM(iso_td.flags, TD_CC)) {
7011be90ebeSPrasad J Pandit             /* avoid infinite loop */
7021be90ebeSPrasad J Pandit             return 1;
7031be90ebeSPrasad J Pandit         }
704f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_DATAOVERRUN);
705f1ae32a1SGerd Hoffmann         ed->head &= ~OHCI_DPTR_MASK;
706f1ae32a1SGerd Hoffmann         ed->head |= (iso_td.next & OHCI_DPTR_MASK);
707f1ae32a1SGerd Hoffmann         iso_td.next = ohci->done;
708f1ae32a1SGerd Hoffmann         ohci->done = addr;
709f1ae32a1SGerd Hoffmann         i = OHCI_BM(iso_td.flags, TD_DI);
710f1ae32a1SGerd Hoffmann         if (i < ohci->done_count)
711f1ae32a1SGerd Hoffmann             ohci->done_count = i;
712cf66ee8eSAlexey Kardashevskiy         if (ohci_put_iso_td(ohci, addr, &iso_td)) {
713cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
714cf66ee8eSAlexey Kardashevskiy             return 1;
715cf66ee8eSAlexey Kardashevskiy         }
716f1ae32a1SGerd Hoffmann         return 0;
717f1ae32a1SGerd Hoffmann     }
718f1ae32a1SGerd Hoffmann 
719f1ae32a1SGerd Hoffmann     dir = OHCI_BM(ed->flags, ED_D);
720f1ae32a1SGerd Hoffmann     switch (dir) {
721f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_IN:
722f1ae32a1SGerd Hoffmann         str = "in";
723f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_IN;
724f1ae32a1SGerd Hoffmann         break;
725f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_OUT:
726f1ae32a1SGerd Hoffmann         str = "out";
727f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_OUT;
728f1ae32a1SGerd Hoffmann         break;
729f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_SETUP:
730f1ae32a1SGerd Hoffmann         str = "setup";
731f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_SETUP;
732f1ae32a1SGerd Hoffmann         break;
733f1ae32a1SGerd Hoffmann     default:
734dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_bad_direction(dir);
735f1ae32a1SGerd Hoffmann         return 1;
736f1ae32a1SGerd Hoffmann     }
737f1ae32a1SGerd Hoffmann 
738f1ae32a1SGerd Hoffmann     if (!iso_td.bp || !iso_td.be) {
739dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_bad_bp_be(iso_td.bp, iso_td.be);
740f1ae32a1SGerd Hoffmann         return 1;
741f1ae32a1SGerd Hoffmann     }
742f1ae32a1SGerd Hoffmann 
743f1ae32a1SGerd Hoffmann     start_offset = iso_td.offset[relative_frame_number];
7441328fe0cSPrasad J Pandit     if (relative_frame_number < frame_count) {
745f1ae32a1SGerd Hoffmann         next_offset = iso_td.offset[relative_frame_number + 1];
7461328fe0cSPrasad J Pandit     } else {
7471328fe0cSPrasad J Pandit         next_offset = iso_td.be;
7481328fe0cSPrasad J Pandit     }
749f1ae32a1SGerd Hoffmann 
750f1ae32a1SGerd Hoffmann     if (!(OHCI_BM(start_offset, TD_PSW_CC) & 0xe) ||
751f1ae32a1SGerd Hoffmann         ((relative_frame_number < frame_count) &&
752f1ae32a1SGerd Hoffmann          !(OHCI_BM(next_offset, TD_PSW_CC) & 0xe))) {
753dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_bad_cc_not_accessed(start_offset, next_offset);
754f1ae32a1SGerd Hoffmann         return 1;
755f1ae32a1SGerd Hoffmann     }
756f1ae32a1SGerd Hoffmann 
757f1ae32a1SGerd Hoffmann     if ((relative_frame_number < frame_count) && (start_offset > next_offset)) {
758dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_bad_cc_overrun(start_offset, next_offset);
759f1ae32a1SGerd Hoffmann         return 1;
760f1ae32a1SGerd Hoffmann     }
761f1ae32a1SGerd Hoffmann 
762f1ae32a1SGerd Hoffmann     if ((start_offset & 0x1000) == 0) {
763f1ae32a1SGerd Hoffmann         start_addr = (iso_td.bp & OHCI_PAGE_MASK) |
764f1ae32a1SGerd Hoffmann             (start_offset & OHCI_OFFSET_MASK);
765f1ae32a1SGerd Hoffmann     } else {
766f1ae32a1SGerd Hoffmann         start_addr = (iso_td.be & OHCI_PAGE_MASK) |
767f1ae32a1SGerd Hoffmann             (start_offset & OHCI_OFFSET_MASK);
768f1ae32a1SGerd Hoffmann     }
769f1ae32a1SGerd Hoffmann 
770f1ae32a1SGerd Hoffmann     if (relative_frame_number < frame_count) {
771f1ae32a1SGerd Hoffmann         end_offset = next_offset - 1;
772f1ae32a1SGerd Hoffmann         if ((end_offset & 0x1000) == 0) {
773f1ae32a1SGerd Hoffmann             end_addr = (iso_td.bp & OHCI_PAGE_MASK) |
774f1ae32a1SGerd Hoffmann                 (end_offset & OHCI_OFFSET_MASK);
775f1ae32a1SGerd Hoffmann         } else {
776f1ae32a1SGerd Hoffmann             end_addr = (iso_td.be & OHCI_PAGE_MASK) |
777f1ae32a1SGerd Hoffmann                 (end_offset & OHCI_OFFSET_MASK);
778f1ae32a1SGerd Hoffmann         }
779f1ae32a1SGerd Hoffmann     } else {
780f1ae32a1SGerd Hoffmann         /* Last packet in the ISO TD */
7811328fe0cSPrasad J Pandit         end_addr = next_offset;
7821328fe0cSPrasad J Pandit     }
7831328fe0cSPrasad J Pandit 
7841328fe0cSPrasad J Pandit     if (start_addr > end_addr) {
7851328fe0cSPrasad J Pandit         trace_usb_ohci_iso_td_bad_cc_overrun(start_addr, end_addr);
7861328fe0cSPrasad J Pandit         return 1;
787f1ae32a1SGerd Hoffmann     }
788f1ae32a1SGerd Hoffmann 
789f1ae32a1SGerd Hoffmann     if ((start_addr & OHCI_PAGE_MASK) != (end_addr & OHCI_PAGE_MASK)) {
790f1ae32a1SGerd Hoffmann         len = (end_addr & OHCI_OFFSET_MASK) + 0x1001
791f1ae32a1SGerd Hoffmann             - (start_addr & OHCI_OFFSET_MASK);
792f1ae32a1SGerd Hoffmann     } else {
793f1ae32a1SGerd Hoffmann         len = end_addr - start_addr + 1;
794f1ae32a1SGerd Hoffmann     }
7951328fe0cSPrasad J Pandit     if (len > sizeof(ohci->usb_buf)) {
7961328fe0cSPrasad J Pandit         len = sizeof(ohci->usb_buf);
7971328fe0cSPrasad J Pandit     }
798f1ae32a1SGerd Hoffmann 
799f1ae32a1SGerd Hoffmann     if (len && dir != OHCI_TD_DIR_IN) {
800cf66ee8eSAlexey Kardashevskiy         if (ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, len,
801cf66ee8eSAlexey Kardashevskiy                              DMA_DIRECTION_TO_DEVICE)) {
802cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
803cf66ee8eSAlexey Kardashevskiy             return 1;
804cf66ee8eSAlexey Kardashevskiy         }
805f1ae32a1SGerd Hoffmann     }
806f1ae32a1SGerd Hoffmann 
8079a77a0f5SHans de Goede     if (!completion) {
808a6fb2ddbSHans de Goede         bool int_req = relative_frame_number == frame_count &&
809a6fb2ddbSHans de Goede                        OHCI_BM(iso_td.flags, TD_DI) == 0;
810f1ae32a1SGerd Hoffmann         dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
81142340fc3SLiam Merwick         if (dev == NULL) {
81242340fc3SLiam Merwick             trace_usb_ohci_td_dev_error();
81342340fc3SLiam Merwick             return 1;
81442340fc3SLiam Merwick         }
815f1ae32a1SGerd Hoffmann         ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
8168550a02dSGerd Hoffmann         usb_packet_setup(&ohci->usb_packet, pid, ep, 0, addr, false, int_req);
817f1ae32a1SGerd Hoffmann         usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len);
8189a77a0f5SHans de Goede         usb_handle_packet(dev, &ohci->usb_packet);
8199a77a0f5SHans de Goede         if (ohci->usb_packet.status == USB_RET_ASYNC) {
82036dfe324SHans de Goede             usb_device_flush_ep_queue(dev, ep);
821f1ae32a1SGerd Hoffmann             return 1;
822f1ae32a1SGerd Hoffmann         }
823f1ae32a1SGerd Hoffmann     }
8249a77a0f5SHans de Goede     if (ohci->usb_packet.status == USB_RET_SUCCESS) {
8259a77a0f5SHans de Goede         ret = ohci->usb_packet.actual_length;
8269a77a0f5SHans de Goede     } else {
8279a77a0f5SHans de Goede         ret = ohci->usb_packet.status;
8289a77a0f5SHans de Goede     }
829f1ae32a1SGerd Hoffmann 
830dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_iso_td_so(start_offset, end_offset, start_addr, end_addr,
831dc1f5988SAlexey Kardashevskiy                              str, len, ret);
832f1ae32a1SGerd Hoffmann 
833f1ae32a1SGerd Hoffmann     /* Writeback */
834f1ae32a1SGerd Hoffmann     if (dir == OHCI_TD_DIR_IN && ret >= 0 && ret <= len) {
835f1ae32a1SGerd Hoffmann         /* IN transfer succeeded */
836cf66ee8eSAlexey Kardashevskiy         if (ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, ret,
837cf66ee8eSAlexey Kardashevskiy                              DMA_DIRECTION_FROM_DEVICE)) {
838cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
839cf66ee8eSAlexey Kardashevskiy             return 1;
840cf66ee8eSAlexey Kardashevskiy         }
841f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
842f1ae32a1SGerd Hoffmann                     OHCI_CC_NOERROR);
843f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, ret);
844f1ae32a1SGerd Hoffmann     } else if (dir == OHCI_TD_DIR_OUT && ret == len) {
845f1ae32a1SGerd Hoffmann         /* OUT transfer succeeded */
846f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
847f1ae32a1SGerd Hoffmann                     OHCI_CC_NOERROR);
848f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 0);
849f1ae32a1SGerd Hoffmann     } else {
850f1ae32a1SGerd Hoffmann         if (ret > (ssize_t) len) {
851dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_iso_td_data_overrun(ret, len);
852f1ae32a1SGerd Hoffmann             OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
853f1ae32a1SGerd Hoffmann                         OHCI_CC_DATAOVERRUN);
854f1ae32a1SGerd Hoffmann             OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
855f1ae32a1SGerd Hoffmann                         len);
856f1ae32a1SGerd Hoffmann         } else if (ret >= 0) {
857dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_iso_td_data_underrun(ret);
858f1ae32a1SGerd Hoffmann             OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
859f1ae32a1SGerd Hoffmann                         OHCI_CC_DATAUNDERRUN);
860f1ae32a1SGerd Hoffmann         } else {
861f1ae32a1SGerd Hoffmann             switch (ret) {
862f1ae32a1SGerd Hoffmann             case USB_RET_IOERROR:
863f1ae32a1SGerd Hoffmann             case USB_RET_NODEV:
864f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
865f1ae32a1SGerd Hoffmann                             OHCI_CC_DEVICENOTRESPONDING);
866f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
867f1ae32a1SGerd Hoffmann                             0);
868f1ae32a1SGerd Hoffmann                 break;
869f1ae32a1SGerd Hoffmann             case USB_RET_NAK:
870f1ae32a1SGerd Hoffmann             case USB_RET_STALL:
871dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_iso_td_nak(ret);
872f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
873f1ae32a1SGerd Hoffmann                             OHCI_CC_STALL);
874f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
875f1ae32a1SGerd Hoffmann                             0);
876f1ae32a1SGerd Hoffmann                 break;
877f1ae32a1SGerd Hoffmann             default:
878dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_iso_td_bad_response(ret);
879f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
880f1ae32a1SGerd Hoffmann                             OHCI_CC_UNDEXPETEDPID);
881f1ae32a1SGerd Hoffmann                 break;
882f1ae32a1SGerd Hoffmann             }
883f1ae32a1SGerd Hoffmann         }
884f1ae32a1SGerd Hoffmann     }
885f1ae32a1SGerd Hoffmann 
886f1ae32a1SGerd Hoffmann     if (relative_frame_number == frame_count) {
887f1ae32a1SGerd Hoffmann         /* Last data packet of ISO TD - retire the TD to the Done Queue */
888f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_NOERROR);
889f1ae32a1SGerd Hoffmann         ed->head &= ~OHCI_DPTR_MASK;
890f1ae32a1SGerd Hoffmann         ed->head |= (iso_td.next & OHCI_DPTR_MASK);
891f1ae32a1SGerd Hoffmann         iso_td.next = ohci->done;
892f1ae32a1SGerd Hoffmann         ohci->done = addr;
893f1ae32a1SGerd Hoffmann         i = OHCI_BM(iso_td.flags, TD_DI);
894f1ae32a1SGerd Hoffmann         if (i < ohci->done_count)
895f1ae32a1SGerd Hoffmann             ohci->done_count = i;
896f1ae32a1SGerd Hoffmann     }
897cf66ee8eSAlexey Kardashevskiy     if (ohci_put_iso_td(ohci, addr, &iso_td)) {
898cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
899cf66ee8eSAlexey Kardashevskiy     }
900f1ae32a1SGerd Hoffmann     return 1;
901f1ae32a1SGerd Hoffmann }
902f1ae32a1SGerd Hoffmann 
903dc1f5988SAlexey Kardashevskiy static void ohci_td_pkt(const char *msg, const uint8_t *buf, size_t len)
904dc1f5988SAlexey Kardashevskiy {
905d87aa138SStefan Hajnoczi     bool print16;
906d87aa138SStefan Hajnoczi     bool printall;
907dc1f5988SAlexey Kardashevskiy     const int width = 16;
908dc1f5988SAlexey Kardashevskiy     int i;
909dc1f5988SAlexey Kardashevskiy     char tmp[3 * width + 1];
910dc1f5988SAlexey Kardashevskiy     char *p = tmp;
911dc1f5988SAlexey Kardashevskiy 
912d87aa138SStefan Hajnoczi     print16 = !!trace_event_get_state_backends(TRACE_USB_OHCI_TD_PKT_SHORT);
913d87aa138SStefan Hajnoczi     printall = !!trace_event_get_state_backends(TRACE_USB_OHCI_TD_PKT_FULL);
914d87aa138SStefan Hajnoczi 
915dc1f5988SAlexey Kardashevskiy     if (!printall && !print16) {
916dc1f5988SAlexey Kardashevskiy         return;
917dc1f5988SAlexey Kardashevskiy     }
918dc1f5988SAlexey Kardashevskiy 
919dc1f5988SAlexey Kardashevskiy     for (i = 0; ; i++) {
920dc1f5988SAlexey Kardashevskiy         if (i && (!(i % width) || (i == len))) {
921dc1f5988SAlexey Kardashevskiy             if (!printall) {
922dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_pkt_short(msg, tmp);
923dc1f5988SAlexey Kardashevskiy                 break;
924dc1f5988SAlexey Kardashevskiy             }
925dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_td_pkt_full(msg, tmp);
926dc1f5988SAlexey Kardashevskiy             p = tmp;
927dc1f5988SAlexey Kardashevskiy             *p = 0;
928dc1f5988SAlexey Kardashevskiy         }
929dc1f5988SAlexey Kardashevskiy         if (i == len) {
930dc1f5988SAlexey Kardashevskiy             break;
931dc1f5988SAlexey Kardashevskiy         }
932dc1f5988SAlexey Kardashevskiy 
933dc1f5988SAlexey Kardashevskiy         p += sprintf(p, " %.2x", buf[i]);
934dc1f5988SAlexey Kardashevskiy     }
935dc1f5988SAlexey Kardashevskiy }
936dc1f5988SAlexey Kardashevskiy 
937f1ae32a1SGerd Hoffmann /* Service a transport descriptor.
938f1ae32a1SGerd Hoffmann    Returns nonzero to terminate processing of this endpoint.  */
939f1ae32a1SGerd Hoffmann 
940f1ae32a1SGerd Hoffmann static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
941f1ae32a1SGerd Hoffmann {
942f1ae32a1SGerd Hoffmann     int dir;
943f1ae32a1SGerd Hoffmann     size_t len = 0, pktlen = 0;
944f1ae32a1SGerd Hoffmann     const char *str = NULL;
945f1ae32a1SGerd Hoffmann     int pid;
946f1ae32a1SGerd Hoffmann     int ret;
947f1ae32a1SGerd Hoffmann     int i;
948f1ae32a1SGerd Hoffmann     USBDevice *dev;
949f1ae32a1SGerd Hoffmann     USBEndpoint *ep;
950f1ae32a1SGerd Hoffmann     struct ohci_td td;
951f1ae32a1SGerd Hoffmann     uint32_t addr;
952f1ae32a1SGerd Hoffmann     int flag_r;
953f1ae32a1SGerd Hoffmann     int completion;
954f1ae32a1SGerd Hoffmann 
955f1ae32a1SGerd Hoffmann     addr = ed->head & OHCI_DPTR_MASK;
956f1ae32a1SGerd Hoffmann     /* See if this TD has already been submitted to the device.  */
957f1ae32a1SGerd Hoffmann     completion = (addr == ohci->async_td);
958f1ae32a1SGerd Hoffmann     if (completion && !ohci->async_complete) {
959dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_td_skip_async();
960f1ae32a1SGerd Hoffmann         return 1;
961f1ae32a1SGerd Hoffmann     }
962cf66ee8eSAlexey Kardashevskiy     if (ohci_read_td(ohci, addr, &td)) {
963dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_td_read_error(addr);
964cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
9656ebc069dSLi Qiang         return 1;
966f1ae32a1SGerd Hoffmann     }
967f1ae32a1SGerd Hoffmann 
968f1ae32a1SGerd Hoffmann     dir = OHCI_BM(ed->flags, ED_D);
969f1ae32a1SGerd Hoffmann     switch (dir) {
970f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_OUT:
971f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_IN:
972f1ae32a1SGerd Hoffmann         /* Same value.  */
973f1ae32a1SGerd Hoffmann         break;
974f1ae32a1SGerd Hoffmann     default:
975f1ae32a1SGerd Hoffmann         dir = OHCI_BM(td.flags, TD_DP);
976f1ae32a1SGerd Hoffmann         break;
977f1ae32a1SGerd Hoffmann     }
978f1ae32a1SGerd Hoffmann 
979f1ae32a1SGerd Hoffmann     switch (dir) {
980f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_IN:
981f1ae32a1SGerd Hoffmann         str = "in";
982f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_IN;
983f1ae32a1SGerd Hoffmann         break;
984f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_OUT:
985f1ae32a1SGerd Hoffmann         str = "out";
986f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_OUT;
987f1ae32a1SGerd Hoffmann         break;
988f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_SETUP:
989f1ae32a1SGerd Hoffmann         str = "setup";
990f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_SETUP;
991f1ae32a1SGerd Hoffmann         break;
992f1ae32a1SGerd Hoffmann     default:
993dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_td_bad_direction(dir);
994f1ae32a1SGerd Hoffmann         return 1;
995f1ae32a1SGerd Hoffmann     }
996f1ae32a1SGerd Hoffmann     if (td.cbp && td.be) {
997f1ae32a1SGerd Hoffmann         if ((td.cbp & 0xfffff000) != (td.be & 0xfffff000)) {
998f1ae32a1SGerd Hoffmann             len = (td.be & 0xfff) + 0x1001 - (td.cbp & 0xfff);
999f1ae32a1SGerd Hoffmann         } else {
10001328fe0cSPrasad J Pandit             if (td.cbp > td.be) {
10011328fe0cSPrasad J Pandit                 trace_usb_ohci_iso_td_bad_cc_overrun(td.cbp, td.be);
10021328fe0cSPrasad J Pandit                 ohci_die(ohci);
10031328fe0cSPrasad J Pandit                 return 1;
10041328fe0cSPrasad J Pandit             }
1005f1ae32a1SGerd Hoffmann             len = (td.be - td.cbp) + 1;
1006f1ae32a1SGerd Hoffmann         }
10071328fe0cSPrasad J Pandit         if (len > sizeof(ohci->usb_buf)) {
10081328fe0cSPrasad J Pandit             len = sizeof(ohci->usb_buf);
10091328fe0cSPrasad J Pandit         }
1010f1ae32a1SGerd Hoffmann 
1011f1ae32a1SGerd Hoffmann         pktlen = len;
1012f1ae32a1SGerd Hoffmann         if (len && dir != OHCI_TD_DIR_IN) {
1013f1ae32a1SGerd Hoffmann             /* The endpoint may not allow us to transfer it all now */
1014f1ae32a1SGerd Hoffmann             pktlen = (ed->flags & OHCI_ED_MPS_MASK) >> OHCI_ED_MPS_SHIFT;
1015f1ae32a1SGerd Hoffmann             if (pktlen > len) {
1016f1ae32a1SGerd Hoffmann                 pktlen = len;
1017f1ae32a1SGerd Hoffmann             }
1018f1ae32a1SGerd Hoffmann             if (!completion) {
1019cf66ee8eSAlexey Kardashevskiy                 if (ohci_copy_td(ohci, &td, ohci->usb_buf, pktlen,
1020cf66ee8eSAlexey Kardashevskiy                                  DMA_DIRECTION_TO_DEVICE)) {
1021cf66ee8eSAlexey Kardashevskiy                     ohci_die(ohci);
1022cf66ee8eSAlexey Kardashevskiy                 }
1023f1ae32a1SGerd Hoffmann             }
1024f1ae32a1SGerd Hoffmann         }
1025f1ae32a1SGerd Hoffmann     }
1026f1ae32a1SGerd Hoffmann 
1027f1ae32a1SGerd Hoffmann     flag_r = (td.flags & OHCI_TD_R) != 0;
1028dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_td_pkt_hdr(addr, (int64_t)pktlen, (int64_t)len, str,
1029dc1f5988SAlexey Kardashevskiy                               flag_r, td.cbp, td.be);
1030dc1f5988SAlexey Kardashevskiy     ohci_td_pkt("OUT", ohci->usb_buf, pktlen);
1031f1ae32a1SGerd Hoffmann 
1032f1ae32a1SGerd Hoffmann     if (completion) {
1033f1ae32a1SGerd Hoffmann         ohci->async_td = 0;
103469e25d26SAlexey Kardashevskiy         ohci->async_complete = false;
1035f1ae32a1SGerd Hoffmann     } else {
1036f1ae32a1SGerd Hoffmann         if (ohci->async_td) {
1037f1ae32a1SGerd Hoffmann             /* ??? The hardware should allow one active packet per
1038f1ae32a1SGerd Hoffmann                endpoint.  We only allow one active packet per controller.
1039f1ae32a1SGerd Hoffmann                This should be sufficient as long as devices respond in a
1040f1ae32a1SGerd Hoffmann                timely manner.
1041f1ae32a1SGerd Hoffmann             */
1042dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_td_too_many_pending();
1043f1ae32a1SGerd Hoffmann             return 1;
1044f1ae32a1SGerd Hoffmann         }
1045f1ae32a1SGerd Hoffmann         dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
104642340fc3SLiam Merwick         if (dev == NULL) {
104742340fc3SLiam Merwick             trace_usb_ohci_td_dev_error();
104842340fc3SLiam Merwick             return 1;
104942340fc3SLiam Merwick         }
1050f1ae32a1SGerd Hoffmann         ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
10518550a02dSGerd Hoffmann         usb_packet_setup(&ohci->usb_packet, pid, ep, 0, addr, !flag_r,
1052a6fb2ddbSHans de Goede                          OHCI_BM(td.flags, TD_DI) == 0);
1053f1ae32a1SGerd Hoffmann         usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen);
10549a77a0f5SHans de Goede         usb_handle_packet(dev, &ohci->usb_packet);
1055dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_td_packet_status(ohci->usb_packet.status);
1056dc1f5988SAlexey Kardashevskiy 
10579a77a0f5SHans de Goede         if (ohci->usb_packet.status == USB_RET_ASYNC) {
105836dfe324SHans de Goede             usb_device_flush_ep_queue(dev, ep);
1059f1ae32a1SGerd Hoffmann             ohci->async_td = addr;
1060f1ae32a1SGerd Hoffmann             return 1;
1061f1ae32a1SGerd Hoffmann         }
1062f1ae32a1SGerd Hoffmann     }
10639a77a0f5SHans de Goede     if (ohci->usb_packet.status == USB_RET_SUCCESS) {
10649a77a0f5SHans de Goede         ret = ohci->usb_packet.actual_length;
10659a77a0f5SHans de Goede     } else {
10669a77a0f5SHans de Goede         ret = ohci->usb_packet.status;
10679a77a0f5SHans de Goede     }
10689a77a0f5SHans de Goede 
1069f1ae32a1SGerd Hoffmann     if (ret >= 0) {
1070f1ae32a1SGerd Hoffmann         if (dir == OHCI_TD_DIR_IN) {
1071cf66ee8eSAlexey Kardashevskiy             if (ohci_copy_td(ohci, &td, ohci->usb_buf, ret,
1072cf66ee8eSAlexey Kardashevskiy                              DMA_DIRECTION_FROM_DEVICE)) {
1073cf66ee8eSAlexey Kardashevskiy                 ohci_die(ohci);
1074cf66ee8eSAlexey Kardashevskiy             }
1075dc1f5988SAlexey Kardashevskiy             ohci_td_pkt("IN", ohci->usb_buf, pktlen);
1076f1ae32a1SGerd Hoffmann         } else {
1077f1ae32a1SGerd Hoffmann             ret = pktlen;
1078f1ae32a1SGerd Hoffmann         }
1079f1ae32a1SGerd Hoffmann     }
1080f1ae32a1SGerd Hoffmann 
1081f1ae32a1SGerd Hoffmann     /* Writeback */
1082f1ae32a1SGerd Hoffmann     if (ret == pktlen || (dir == OHCI_TD_DIR_IN && ret >= 0 && flag_r)) {
1083f1ae32a1SGerd Hoffmann         /* Transmission succeeded.  */
1084f1ae32a1SGerd Hoffmann         if (ret == len) {
1085f1ae32a1SGerd Hoffmann             td.cbp = 0;
1086f1ae32a1SGerd Hoffmann         } else {
1087f1ae32a1SGerd Hoffmann             if ((td.cbp & 0xfff) + ret > 0xfff) {
1088f1ae32a1SGerd Hoffmann                 td.cbp = (td.be & ~0xfff) + ((td.cbp + ret) & 0xfff);
1089f1ae32a1SGerd Hoffmann             } else {
1090f1ae32a1SGerd Hoffmann                 td.cbp += ret;
1091f1ae32a1SGerd Hoffmann             }
1092f1ae32a1SGerd Hoffmann         }
1093f1ae32a1SGerd Hoffmann         td.flags |= OHCI_TD_T1;
1094f1ae32a1SGerd Hoffmann         td.flags ^= OHCI_TD_T0;
1095f1ae32a1SGerd Hoffmann         OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_NOERROR);
1096f1ae32a1SGerd Hoffmann         OHCI_SET_BM(td.flags, TD_EC, 0);
1097f1ae32a1SGerd Hoffmann 
1098f1ae32a1SGerd Hoffmann         if ((dir != OHCI_TD_DIR_IN) && (ret != len)) {
1099f1ae32a1SGerd Hoffmann             /* Partial packet transfer: TD not ready to retire yet */
1100f1ae32a1SGerd Hoffmann             goto exit_no_retire;
1101f1ae32a1SGerd Hoffmann         }
1102f1ae32a1SGerd Hoffmann 
1103f1ae32a1SGerd Hoffmann         /* Setting ED_C is part of the TD retirement process */
1104f1ae32a1SGerd Hoffmann         ed->head &= ~OHCI_ED_C;
1105f1ae32a1SGerd Hoffmann         if (td.flags & OHCI_TD_T0)
1106f1ae32a1SGerd Hoffmann             ed->head |= OHCI_ED_C;
1107f1ae32a1SGerd Hoffmann     } else {
1108f1ae32a1SGerd Hoffmann         if (ret >= 0) {
1109dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_td_underrun();
1110f1ae32a1SGerd Hoffmann             OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAUNDERRUN);
1111f1ae32a1SGerd Hoffmann         } else {
1112f1ae32a1SGerd Hoffmann             switch (ret) {
1113f1ae32a1SGerd Hoffmann             case USB_RET_IOERROR:
1114f1ae32a1SGerd Hoffmann             case USB_RET_NODEV:
1115dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_dev_error();
1116f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DEVICENOTRESPONDING);
11174b351a0fSJán Veselý                 break;
1118f1ae32a1SGerd Hoffmann             case USB_RET_NAK:
1119dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_nak();
1120f1ae32a1SGerd Hoffmann                 return 1;
1121f1ae32a1SGerd Hoffmann             case USB_RET_STALL:
1122dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_stall();
1123f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_STALL);
1124f1ae32a1SGerd Hoffmann                 break;
1125f1ae32a1SGerd Hoffmann             case USB_RET_BABBLE:
1126dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_babble();
1127f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAOVERRUN);
1128f1ae32a1SGerd Hoffmann                 break;
1129f1ae32a1SGerd Hoffmann             default:
1130dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_bad_device_response(ret);
1131f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_UNDEXPETEDPID);
1132f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_EC, 3);
1133f1ae32a1SGerd Hoffmann                 break;
1134f1ae32a1SGerd Hoffmann             }
1135cba42d61SMichael Tokarev             /* An error occurred so we have to clear the interrupt counter. See
11367c48b95dSSebastian Bauer              * spec at 6.4.4 on page 104 */
11377c48b95dSSebastian Bauer             ohci->done_count = 0;
1138f1ae32a1SGerd Hoffmann         }
1139f1ae32a1SGerd Hoffmann         ed->head |= OHCI_ED_H;
1140f1ae32a1SGerd Hoffmann     }
1141f1ae32a1SGerd Hoffmann 
1142f1ae32a1SGerd Hoffmann     /* Retire this TD */
1143f1ae32a1SGerd Hoffmann     ed->head &= ~OHCI_DPTR_MASK;
1144f1ae32a1SGerd Hoffmann     ed->head |= td.next & OHCI_DPTR_MASK;
1145f1ae32a1SGerd Hoffmann     td.next = ohci->done;
1146f1ae32a1SGerd Hoffmann     ohci->done = addr;
1147f1ae32a1SGerd Hoffmann     i = OHCI_BM(td.flags, TD_DI);
1148f1ae32a1SGerd Hoffmann     if (i < ohci->done_count)
1149f1ae32a1SGerd Hoffmann         ohci->done_count = i;
1150f1ae32a1SGerd Hoffmann exit_no_retire:
1151cf66ee8eSAlexey Kardashevskiy     if (ohci_put_td(ohci, addr, &td)) {
1152cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
1153cf66ee8eSAlexey Kardashevskiy         return 1;
1154cf66ee8eSAlexey Kardashevskiy     }
1155f1ae32a1SGerd Hoffmann     return OHCI_BM(td.flags, TD_CC) != OHCI_CC_NOERROR;
1156f1ae32a1SGerd Hoffmann }
1157f1ae32a1SGerd Hoffmann 
1158f1ae32a1SGerd Hoffmann /* Service an endpoint list.  Returns nonzero if active TD were found.  */
1159f1ae32a1SGerd Hoffmann static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion)
1160f1ae32a1SGerd Hoffmann {
1161f1ae32a1SGerd Hoffmann     struct ohci_ed ed;
1162f1ae32a1SGerd Hoffmann     uint32_t next_ed;
1163f1ae32a1SGerd Hoffmann     uint32_t cur;
1164f1ae32a1SGerd Hoffmann     int active;
116595ed5693SLi Qiang     uint32_t link_cnt = 0;
1166f1ae32a1SGerd Hoffmann     active = 0;
1167f1ae32a1SGerd Hoffmann 
1168f1ae32a1SGerd Hoffmann     if (head == 0)
1169f1ae32a1SGerd Hoffmann         return 0;
1170f1ae32a1SGerd Hoffmann 
1171ab878998SLaurent Vivier     for (cur = head; cur && link_cnt++ < ED_LINK_LIMIT; cur = next_ed) {
1172cf66ee8eSAlexey Kardashevskiy         if (ohci_read_ed(ohci, cur, &ed)) {
1173dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_ed_read_error(cur);
1174cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
1175f1ae32a1SGerd Hoffmann             return 0;
1176f1ae32a1SGerd Hoffmann         }
1177f1ae32a1SGerd Hoffmann 
1178f1ae32a1SGerd Hoffmann         next_ed = ed.next & OHCI_DPTR_MASK;
1179f1ae32a1SGerd Hoffmann 
1180f1ae32a1SGerd Hoffmann         if ((ed.head & OHCI_ED_H) || (ed.flags & OHCI_ED_K)) {
1181f1ae32a1SGerd Hoffmann             uint32_t addr;
1182f1ae32a1SGerd Hoffmann             /* Cancel pending packets for ED that have been paused.  */
1183f1ae32a1SGerd Hoffmann             addr = ed.head & OHCI_DPTR_MASK;
1184f1ae32a1SGerd Hoffmann             if (ohci->async_td && addr == ohci->async_td) {
1185f1ae32a1SGerd Hoffmann                 usb_cancel_packet(&ohci->usb_packet);
1186f1ae32a1SGerd Hoffmann                 ohci->async_td = 0;
1187f79738b0SHans de Goede                 usb_device_ep_stopped(ohci->usb_packet.ep->dev,
1188f79738b0SHans de Goede                                       ohci->usb_packet.ep);
1189f1ae32a1SGerd Hoffmann             }
1190f1ae32a1SGerd Hoffmann             continue;
1191f1ae32a1SGerd Hoffmann         }
1192f1ae32a1SGerd Hoffmann 
1193f1ae32a1SGerd Hoffmann         while ((ed.head & OHCI_DPTR_MASK) != ed.tail) {
11943af8f177SAlexey Kardashevskiy             trace_usb_ohci_ed_pkt(cur, (ed.head & OHCI_ED_H) != 0,
11953af8f177SAlexey Kardashevskiy                     (ed.head & OHCI_ED_C) != 0, ed.head & OHCI_DPTR_MASK,
11963af8f177SAlexey Kardashevskiy                     ed.tail & OHCI_DPTR_MASK, ed.next & OHCI_DPTR_MASK);
11973af8f177SAlexey Kardashevskiy             trace_usb_ohci_ed_pkt_flags(
1198f1ae32a1SGerd Hoffmann                     OHCI_BM(ed.flags, ED_FA), OHCI_BM(ed.flags, ED_EN),
1199f1ae32a1SGerd Hoffmann                     OHCI_BM(ed.flags, ED_D), (ed.flags & OHCI_ED_S)!= 0,
1200f1ae32a1SGerd Hoffmann                     (ed.flags & OHCI_ED_K) != 0, (ed.flags & OHCI_ED_F) != 0,
12013af8f177SAlexey Kardashevskiy                     OHCI_BM(ed.flags, ED_MPS));
1202dc1f5988SAlexey Kardashevskiy 
1203f1ae32a1SGerd Hoffmann             active = 1;
1204f1ae32a1SGerd Hoffmann 
1205f1ae32a1SGerd Hoffmann             if ((ed.flags & OHCI_ED_F) == 0) {
1206f1ae32a1SGerd Hoffmann                 if (ohci_service_td(ohci, &ed))
1207f1ae32a1SGerd Hoffmann                     break;
1208f1ae32a1SGerd Hoffmann             } else {
1209f1ae32a1SGerd Hoffmann                 /* Handle isochronous endpoints */
1210f1ae32a1SGerd Hoffmann                 if (ohci_service_iso_td(ohci, &ed, completion))
1211f1ae32a1SGerd Hoffmann                     break;
1212f1ae32a1SGerd Hoffmann             }
1213f1ae32a1SGerd Hoffmann         }
1214f1ae32a1SGerd Hoffmann 
1215cf66ee8eSAlexey Kardashevskiy         if (ohci_put_ed(ohci, cur, &ed)) {
1216cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
1217cf66ee8eSAlexey Kardashevskiy             return 0;
1218cf66ee8eSAlexey Kardashevskiy         }
1219f1ae32a1SGerd Hoffmann     }
1220f1ae32a1SGerd Hoffmann 
1221f1ae32a1SGerd Hoffmann     return active;
1222f1ae32a1SGerd Hoffmann }
1223f1ae32a1SGerd Hoffmann 
1224fd0a10cdSLaurent Vivier /* set a timer for EOF */
1225fd0a10cdSLaurent Vivier static void ohci_eof_timer(OHCIState *ohci)
1226f1ae32a1SGerd Hoffmann {
1227bc72ad67SAlex Bligh     timer_mod(ohci->eof_timer, ohci->sof_time + usb_frame_time);
1228fd0a10cdSLaurent Vivier }
1229fd0a10cdSLaurent Vivier /* Set a timer for EOF and generate a SOF event */
1230fd0a10cdSLaurent Vivier static void ohci_sof(OHCIState *ohci)
1231fd0a10cdSLaurent Vivier {
1232a60f39a4SMiguel GAIO     ohci->sof_time += usb_frame_time;
1233fd0a10cdSLaurent Vivier     ohci_eof_timer(ohci);
1234f1ae32a1SGerd Hoffmann     ohci_set_interrupt(ohci, OHCI_INTR_SF);
1235f1ae32a1SGerd Hoffmann }
1236f1ae32a1SGerd Hoffmann 
1237f1ae32a1SGerd Hoffmann /* Process Control and Bulk lists.  */
1238f1ae32a1SGerd Hoffmann static void ohci_process_lists(OHCIState *ohci, int completion)
1239f1ae32a1SGerd Hoffmann {
1240f1ae32a1SGerd Hoffmann     if ((ohci->ctl & OHCI_CTL_CLE) && (ohci->status & OHCI_STATUS_CLF)) {
1241f1ae32a1SGerd Hoffmann         if (ohci->ctrl_cur && ohci->ctrl_cur != ohci->ctrl_head) {
1242dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_process_lists(ohci->ctrl_head, ohci->ctrl_cur);
1243f1ae32a1SGerd Hoffmann         }
1244f1ae32a1SGerd Hoffmann         if (!ohci_service_ed_list(ohci, ohci->ctrl_head, completion)) {
1245f1ae32a1SGerd Hoffmann             ohci->ctrl_cur = 0;
1246f1ae32a1SGerd Hoffmann             ohci->status &= ~OHCI_STATUS_CLF;
1247f1ae32a1SGerd Hoffmann         }
1248f1ae32a1SGerd Hoffmann     }
1249f1ae32a1SGerd Hoffmann 
1250f1ae32a1SGerd Hoffmann     if ((ohci->ctl & OHCI_CTL_BLE) && (ohci->status & OHCI_STATUS_BLF)) {
1251f1ae32a1SGerd Hoffmann         if (!ohci_service_ed_list(ohci, ohci->bulk_head, completion)) {
1252f1ae32a1SGerd Hoffmann             ohci->bulk_cur = 0;
1253f1ae32a1SGerd Hoffmann             ohci->status &= ~OHCI_STATUS_BLF;
1254f1ae32a1SGerd Hoffmann         }
1255f1ae32a1SGerd Hoffmann     }
1256f1ae32a1SGerd Hoffmann }
1257f1ae32a1SGerd Hoffmann 
1258f1ae32a1SGerd Hoffmann /* Do frame processing on frame boundary */
1259f1ae32a1SGerd Hoffmann static void ohci_frame_boundary(void *opaque)
1260f1ae32a1SGerd Hoffmann {
1261f1ae32a1SGerd Hoffmann     OHCIState *ohci = opaque;
1262f1ae32a1SGerd Hoffmann     struct ohci_hcca hcca;
1263f1ae32a1SGerd Hoffmann 
1264cf66ee8eSAlexey Kardashevskiy     if (ohci_read_hcca(ohci, ohci->hcca, &hcca)) {
1265dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_hcca_read_error(ohci->hcca);
1266cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
1267cf66ee8eSAlexey Kardashevskiy         return;
1268cf66ee8eSAlexey Kardashevskiy     }
1269f1ae32a1SGerd Hoffmann 
1270f1ae32a1SGerd Hoffmann     /* Process all the lists at the end of the frame */
1271f1ae32a1SGerd Hoffmann     if (ohci->ctl & OHCI_CTL_PLE) {
1272f1ae32a1SGerd Hoffmann         int n;
1273f1ae32a1SGerd Hoffmann 
1274f1ae32a1SGerd Hoffmann         n = ohci->frame_number & 0x1f;
1275f1ae32a1SGerd Hoffmann         ohci_service_ed_list(ohci, le32_to_cpu(hcca.intr[n]), 0);
1276f1ae32a1SGerd Hoffmann     }
1277f1ae32a1SGerd Hoffmann 
1278f1ae32a1SGerd Hoffmann     /* Cancel all pending packets if either of the lists has been disabled.  */
1279f79738b0SHans de Goede     if (ohci->old_ctl & (~ohci->ctl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) {
1280f79738b0SHans de Goede         if (ohci->async_td) {
1281f1ae32a1SGerd Hoffmann             usb_cancel_packet(&ohci->usb_packet);
1282f1ae32a1SGerd Hoffmann             ohci->async_td = 0;
1283f1ae32a1SGerd Hoffmann         }
1284f79738b0SHans de Goede         ohci_stop_endpoints(ohci);
1285f79738b0SHans de Goede     }
1286f1ae32a1SGerd Hoffmann     ohci->old_ctl = ohci->ctl;
1287f1ae32a1SGerd Hoffmann     ohci_process_lists(ohci, 0);
1288f1ae32a1SGerd Hoffmann 
1289cf66ee8eSAlexey Kardashevskiy     /* Stop if UnrecoverableError happened or ohci_sof will crash */
1290cf66ee8eSAlexey Kardashevskiy     if (ohci->intr_status & OHCI_INTR_UE) {
1291cf66ee8eSAlexey Kardashevskiy         return;
1292cf66ee8eSAlexey Kardashevskiy     }
1293cf66ee8eSAlexey Kardashevskiy 
1294f1ae32a1SGerd Hoffmann     /* Frame boundary, so do EOF stuf here */
1295f1ae32a1SGerd Hoffmann     ohci->frt = ohci->fit;
1296f1ae32a1SGerd Hoffmann 
1297f1ae32a1SGerd Hoffmann     /* Increment frame number and take care of endianness. */
1298f1ae32a1SGerd Hoffmann     ohci->frame_number = (ohci->frame_number + 1) & 0xffff;
1299f1ae32a1SGerd Hoffmann     hcca.frame = cpu_to_le16(ohci->frame_number);
1300f1ae32a1SGerd Hoffmann 
1301f1ae32a1SGerd Hoffmann     if (ohci->done_count == 0 && !(ohci->intr_status & OHCI_INTR_WD)) {
1302f1ae32a1SGerd Hoffmann         if (!ohci->done)
1303f1ae32a1SGerd Hoffmann             abort();
1304f1ae32a1SGerd Hoffmann         if (ohci->intr & ohci->intr_status)
1305f1ae32a1SGerd Hoffmann             ohci->done |= 1;
1306f1ae32a1SGerd Hoffmann         hcca.done = cpu_to_le32(ohci->done);
1307f1ae32a1SGerd Hoffmann         ohci->done = 0;
1308f1ae32a1SGerd Hoffmann         ohci->done_count = 7;
1309f1ae32a1SGerd Hoffmann         ohci_set_interrupt(ohci, OHCI_INTR_WD);
1310f1ae32a1SGerd Hoffmann     }
1311f1ae32a1SGerd Hoffmann 
1312f1ae32a1SGerd Hoffmann     if (ohci->done_count != 7 && ohci->done_count != 0)
1313f1ae32a1SGerd Hoffmann         ohci->done_count--;
1314f1ae32a1SGerd Hoffmann 
1315f1ae32a1SGerd Hoffmann     /* Do SOF stuff here */
1316f1ae32a1SGerd Hoffmann     ohci_sof(ohci);
1317f1ae32a1SGerd Hoffmann 
1318f1ae32a1SGerd Hoffmann     /* Writeback HCCA */
1319cf66ee8eSAlexey Kardashevskiy     if (ohci_put_hcca(ohci, ohci->hcca, &hcca)) {
1320cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
1321cf66ee8eSAlexey Kardashevskiy     }
1322f1ae32a1SGerd Hoffmann }
1323f1ae32a1SGerd Hoffmann 
1324f1ae32a1SGerd Hoffmann /* Start sending SOF tokens across the USB bus, lists are processed in
1325f1ae32a1SGerd Hoffmann  * next frame
1326f1ae32a1SGerd Hoffmann  */
1327f1ae32a1SGerd Hoffmann static int ohci_bus_start(OHCIState *ohci)
1328f1ae32a1SGerd Hoffmann {
1329dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_start(ohci->name);
1330f1ae32a1SGerd Hoffmann 
1331fd0a10cdSLaurent Vivier     /* Delay the first SOF event by one frame time as
1332fd0a10cdSLaurent Vivier      * linux driver is not ready to receive it and
1333fd0a10cdSLaurent Vivier      * can meet some race conditions
1334fd0a10cdSLaurent Vivier      */
1335fd0a10cdSLaurent Vivier 
1336a60f39a4SMiguel GAIO     ohci->sof_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
1337fd0a10cdSLaurent Vivier     ohci_eof_timer(ohci);
1338f1ae32a1SGerd Hoffmann 
1339f1ae32a1SGerd Hoffmann     return 1;
1340f1ae32a1SGerd Hoffmann }
1341f1ae32a1SGerd Hoffmann 
1342f1ae32a1SGerd Hoffmann /* Stop sending SOF tokens on the bus */
134334d97308SThomas Huth void ohci_bus_stop(OHCIState *ohci)
1344f1ae32a1SGerd Hoffmann {
1345dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_stop(ohci->name);
1346bc72ad67SAlex Bligh     timer_del(ohci->eof_timer);
1347f1ae32a1SGerd Hoffmann }
1348f1ae32a1SGerd Hoffmann 
1349f1ae32a1SGerd Hoffmann /* Sets a flag in a port status register but only set it if the port is
1350f1ae32a1SGerd Hoffmann  * connected, if not set ConnectStatusChange flag. If flag is enabled
1351f1ae32a1SGerd Hoffmann  * return 1.
1352f1ae32a1SGerd Hoffmann  */
1353f1ae32a1SGerd Hoffmann static int ohci_port_set_if_connected(OHCIState *ohci, int i, uint32_t val)
1354f1ae32a1SGerd Hoffmann {
1355f1ae32a1SGerd Hoffmann     int ret = 1;
1356f1ae32a1SGerd Hoffmann 
1357f1ae32a1SGerd Hoffmann     /* writing a 0 has no effect */
1358f1ae32a1SGerd Hoffmann     if (val == 0)
1359f1ae32a1SGerd Hoffmann         return 0;
1360f1ae32a1SGerd Hoffmann 
1361f1ae32a1SGerd Hoffmann     /* If CurrentConnectStatus is cleared we set
1362f1ae32a1SGerd Hoffmann      * ConnectStatusChange
1363f1ae32a1SGerd Hoffmann      */
1364f1ae32a1SGerd Hoffmann     if (!(ohci->rhport[i].ctrl & OHCI_PORT_CCS)) {
1365f1ae32a1SGerd Hoffmann         ohci->rhport[i].ctrl |= OHCI_PORT_CSC;
1366f1ae32a1SGerd Hoffmann         if (ohci->rhstatus & OHCI_RHS_DRWE) {
1367f1ae32a1SGerd Hoffmann             /* TODO: CSC is a wakeup event */
1368f1ae32a1SGerd Hoffmann         }
1369f1ae32a1SGerd Hoffmann         return 0;
1370f1ae32a1SGerd Hoffmann     }
1371f1ae32a1SGerd Hoffmann 
1372f1ae32a1SGerd Hoffmann     if (ohci->rhport[i].ctrl & val)
1373f1ae32a1SGerd Hoffmann         ret = 0;
1374f1ae32a1SGerd Hoffmann 
1375f1ae32a1SGerd Hoffmann     /* set the bit */
1376f1ae32a1SGerd Hoffmann     ohci->rhport[i].ctrl |= val;
1377f1ae32a1SGerd Hoffmann 
1378f1ae32a1SGerd Hoffmann     return ret;
1379f1ae32a1SGerd Hoffmann }
1380f1ae32a1SGerd Hoffmann 
1381f1ae32a1SGerd Hoffmann /* Set the frame interval - frame interval toggle is manipulated by the hcd only */
1382f1ae32a1SGerd Hoffmann static void ohci_set_frame_interval(OHCIState *ohci, uint16_t val)
1383f1ae32a1SGerd Hoffmann {
1384f1ae32a1SGerd Hoffmann     val &= OHCI_FMI_FI;
1385f1ae32a1SGerd Hoffmann 
1386f1ae32a1SGerd Hoffmann     if (val != ohci->fi) {
1387dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_set_frame_interval(ohci->name, ohci->fi, ohci->fi);
1388f1ae32a1SGerd Hoffmann     }
1389f1ae32a1SGerd Hoffmann 
1390f1ae32a1SGerd Hoffmann     ohci->fi = val;
1391f1ae32a1SGerd Hoffmann }
1392f1ae32a1SGerd Hoffmann 
1393f1ae32a1SGerd Hoffmann static void ohci_port_power(OHCIState *ohci, int i, int p)
1394f1ae32a1SGerd Hoffmann {
1395f1ae32a1SGerd Hoffmann     if (p) {
1396f1ae32a1SGerd Hoffmann         ohci->rhport[i].ctrl |= OHCI_PORT_PPS;
1397f1ae32a1SGerd Hoffmann     } else {
1398f1ae32a1SGerd Hoffmann         ohci->rhport[i].ctrl &= ~(OHCI_PORT_PPS|
1399f1ae32a1SGerd Hoffmann                     OHCI_PORT_CCS|
1400f1ae32a1SGerd Hoffmann                     OHCI_PORT_PSS|
1401f1ae32a1SGerd Hoffmann                     OHCI_PORT_PRS);
1402f1ae32a1SGerd Hoffmann     }
1403f1ae32a1SGerd Hoffmann }
1404f1ae32a1SGerd Hoffmann 
1405f1ae32a1SGerd Hoffmann /* Set HcControlRegister */
1406f1ae32a1SGerd Hoffmann static void ohci_set_ctl(OHCIState *ohci, uint32_t val)
1407f1ae32a1SGerd Hoffmann {
1408f1ae32a1SGerd Hoffmann     uint32_t old_state;
1409f1ae32a1SGerd Hoffmann     uint32_t new_state;
1410f1ae32a1SGerd Hoffmann 
1411f1ae32a1SGerd Hoffmann     old_state = ohci->ctl & OHCI_CTL_HCFS;
1412f1ae32a1SGerd Hoffmann     ohci->ctl = val;
1413f1ae32a1SGerd Hoffmann     new_state = ohci->ctl & OHCI_CTL_HCFS;
1414f1ae32a1SGerd Hoffmann 
1415f1ae32a1SGerd Hoffmann     /* no state change */
1416f1ae32a1SGerd Hoffmann     if (old_state == new_state)
1417f1ae32a1SGerd Hoffmann         return;
1418f1ae32a1SGerd Hoffmann 
1419dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_set_ctl(ohci->name, new_state);
1420f1ae32a1SGerd Hoffmann     switch (new_state) {
1421f1ae32a1SGerd Hoffmann     case OHCI_USB_OPERATIONAL:
1422f1ae32a1SGerd Hoffmann         ohci_bus_start(ohci);
1423f1ae32a1SGerd Hoffmann         break;
1424f1ae32a1SGerd Hoffmann     case OHCI_USB_SUSPEND:
1425f1ae32a1SGerd Hoffmann         ohci_bus_stop(ohci);
1426087462c7SLaurent Vivier         /* clear pending SF otherwise linux driver loops in ohci_irq() */
1427087462c7SLaurent Vivier         ohci->intr_status &= ~OHCI_INTR_SF;
1428087462c7SLaurent Vivier         ohci_intr_update(ohci);
1429f1ae32a1SGerd Hoffmann         break;
1430f1ae32a1SGerd Hoffmann     case OHCI_USB_RESUME:
1431dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_resume(ohci->name);
1432f1ae32a1SGerd Hoffmann         break;
1433f1ae32a1SGerd Hoffmann     case OHCI_USB_RESET:
14347d938fd1SHervé Poussineau         ohci_roothub_reset(ohci);
1435f1ae32a1SGerd Hoffmann         break;
1436f1ae32a1SGerd Hoffmann     }
1437f1ae32a1SGerd Hoffmann }
1438f1ae32a1SGerd Hoffmann 
1439f1ae32a1SGerd Hoffmann static uint32_t ohci_get_frame_remaining(OHCIState *ohci)
1440f1ae32a1SGerd Hoffmann {
1441f1ae32a1SGerd Hoffmann     uint16_t fr;
1442f1ae32a1SGerd Hoffmann     int64_t tks;
1443f1ae32a1SGerd Hoffmann 
1444f1ae32a1SGerd Hoffmann     if ((ohci->ctl & OHCI_CTL_HCFS) != OHCI_USB_OPERATIONAL)
1445f1ae32a1SGerd Hoffmann         return (ohci->frt << 31);
1446f1ae32a1SGerd Hoffmann 
1447f1ae32a1SGerd Hoffmann     /* Being in USB operational state guarnatees sof_time was
1448f1ae32a1SGerd Hoffmann      * set already.
1449f1ae32a1SGerd Hoffmann      */
1450bc72ad67SAlex Bligh     tks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - ohci->sof_time;
1451a60f39a4SMiguel GAIO     if (tks < 0) {
1452a60f39a4SMiguel GAIO         tks = 0;
1453a60f39a4SMiguel GAIO     }
1454f1ae32a1SGerd Hoffmann 
1455f1ae32a1SGerd Hoffmann     /* avoid muldiv if possible */
1456f1ae32a1SGerd Hoffmann     if (tks >= usb_frame_time)
1457f1ae32a1SGerd Hoffmann         return (ohci->frt << 31);
1458f1ae32a1SGerd Hoffmann 
1459cd1f16f9SLaurent Vivier     tks = tks / usb_bit_time;
1460f1ae32a1SGerd Hoffmann     fr = (uint16_t)(ohci->fi - tks);
1461f1ae32a1SGerd Hoffmann 
1462f1ae32a1SGerd Hoffmann     return (ohci->frt << 31) | fr;
1463f1ae32a1SGerd Hoffmann }
1464f1ae32a1SGerd Hoffmann 
1465f1ae32a1SGerd Hoffmann 
1466f1ae32a1SGerd Hoffmann /* Set root hub status */
1467f1ae32a1SGerd Hoffmann static void ohci_set_hub_status(OHCIState *ohci, uint32_t val)
1468f1ae32a1SGerd Hoffmann {
1469f1ae32a1SGerd Hoffmann     uint32_t old_state;
1470f1ae32a1SGerd Hoffmann 
1471f1ae32a1SGerd Hoffmann     old_state = ohci->rhstatus;
1472f1ae32a1SGerd Hoffmann 
1473f1ae32a1SGerd Hoffmann     /* write 1 to clear OCIC */
1474f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_OCIC)
1475f1ae32a1SGerd Hoffmann         ohci->rhstatus &= ~OHCI_RHS_OCIC;
1476f1ae32a1SGerd Hoffmann 
1477f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_LPS) {
1478f1ae32a1SGerd Hoffmann         int i;
1479f1ae32a1SGerd Hoffmann 
1480f1ae32a1SGerd Hoffmann         for (i = 0; i < ohci->num_ports; i++)
1481f1ae32a1SGerd Hoffmann             ohci_port_power(ohci, i, 0);
1482dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_hub_power_down();
1483f1ae32a1SGerd Hoffmann     }
1484f1ae32a1SGerd Hoffmann 
1485f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_LPSC) {
1486f1ae32a1SGerd Hoffmann         int i;
1487f1ae32a1SGerd Hoffmann 
1488f1ae32a1SGerd Hoffmann         for (i = 0; i < ohci->num_ports; i++)
1489f1ae32a1SGerd Hoffmann             ohci_port_power(ohci, i, 1);
1490dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_hub_power_up();
1491f1ae32a1SGerd Hoffmann     }
1492f1ae32a1SGerd Hoffmann 
1493f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_DRWE)
1494f1ae32a1SGerd Hoffmann         ohci->rhstatus |= OHCI_RHS_DRWE;
1495f1ae32a1SGerd Hoffmann 
1496f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_CRWE)
1497f1ae32a1SGerd Hoffmann         ohci->rhstatus &= ~OHCI_RHS_DRWE;
1498f1ae32a1SGerd Hoffmann 
1499f1ae32a1SGerd Hoffmann     if (old_state != ohci->rhstatus)
1500f1ae32a1SGerd Hoffmann         ohci_set_interrupt(ohci, OHCI_INTR_RHSC);
1501f1ae32a1SGerd Hoffmann }
1502f1ae32a1SGerd Hoffmann 
1503f1ae32a1SGerd Hoffmann /* Set root hub port status */
1504f1ae32a1SGerd Hoffmann static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val)
1505f1ae32a1SGerd Hoffmann {
1506f1ae32a1SGerd Hoffmann     uint32_t old_state;
1507f1ae32a1SGerd Hoffmann     OHCIPort *port;
1508f1ae32a1SGerd Hoffmann 
1509f1ae32a1SGerd Hoffmann     port = &ohci->rhport[portnum];
1510f1ae32a1SGerd Hoffmann     old_state = port->ctrl;
1511f1ae32a1SGerd Hoffmann 
1512f1ae32a1SGerd Hoffmann     /* Write to clear CSC, PESC, PSSC, OCIC, PRSC */
1513f1ae32a1SGerd Hoffmann     if (val & OHCI_PORT_WTC)
1514f1ae32a1SGerd Hoffmann         port->ctrl &= ~(val & OHCI_PORT_WTC);
1515f1ae32a1SGerd Hoffmann 
1516f1ae32a1SGerd Hoffmann     if (val & OHCI_PORT_CCS)
1517f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_PES;
1518f1ae32a1SGerd Hoffmann 
1519f1ae32a1SGerd Hoffmann     ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PES);
1520f1ae32a1SGerd Hoffmann 
1521f1ae32a1SGerd Hoffmann     if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PSS)) {
1522dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_port_suspend(portnum);
1523f1ae32a1SGerd Hoffmann     }
1524f1ae32a1SGerd Hoffmann 
1525f1ae32a1SGerd Hoffmann     if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PRS)) {
1526dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_port_reset(portnum);
1527f1ae32a1SGerd Hoffmann         usb_device_reset(port->port.dev);
1528f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_PRS;
1529f1ae32a1SGerd Hoffmann         /* ??? Should this also set OHCI_PORT_PESC.  */
1530f1ae32a1SGerd Hoffmann         port->ctrl |= OHCI_PORT_PES | OHCI_PORT_PRSC;
1531f1ae32a1SGerd Hoffmann     }
1532f1ae32a1SGerd Hoffmann 
1533f1ae32a1SGerd Hoffmann     /* Invert order here to ensure in ambiguous case, device is
1534f1ae32a1SGerd Hoffmann      * powered up...
1535f1ae32a1SGerd Hoffmann      */
1536f1ae32a1SGerd Hoffmann     if (val & OHCI_PORT_LSDA)
1537f1ae32a1SGerd Hoffmann         ohci_port_power(ohci, portnum, 0);
1538f1ae32a1SGerd Hoffmann     if (val & OHCI_PORT_PPS)
1539f1ae32a1SGerd Hoffmann         ohci_port_power(ohci, portnum, 1);
1540f1ae32a1SGerd Hoffmann 
1541f1ae32a1SGerd Hoffmann     if (old_state != port->ctrl)
1542f1ae32a1SGerd Hoffmann         ohci_set_interrupt(ohci, OHCI_INTR_RHSC);
1543f1ae32a1SGerd Hoffmann }
1544f1ae32a1SGerd Hoffmann 
1545f1ae32a1SGerd Hoffmann static uint64_t ohci_mem_read(void *opaque,
1546a8170e5eSAvi Kivity                               hwaddr addr,
1547f1ae32a1SGerd Hoffmann                               unsigned size)
1548f1ae32a1SGerd Hoffmann {
1549f1ae32a1SGerd Hoffmann     OHCIState *ohci = opaque;
1550f1ae32a1SGerd Hoffmann     uint32_t retval;
1551f1ae32a1SGerd Hoffmann 
1552f1ae32a1SGerd Hoffmann     /* Only aligned reads are allowed on OHCI */
1553f1ae32a1SGerd Hoffmann     if (addr & 3) {
1554dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_mem_read_unaligned(addr);
1555f1ae32a1SGerd Hoffmann         return 0xffffffff;
1556f1ae32a1SGerd Hoffmann     } else if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) {
1557f1ae32a1SGerd Hoffmann         /* HcRhPortStatus */
1558f1ae32a1SGerd Hoffmann         retval = ohci->rhport[(addr - 0x54) >> 2].ctrl | OHCI_PORT_PPS;
1559f1ae32a1SGerd Hoffmann     } else {
1560f1ae32a1SGerd Hoffmann         switch (addr >> 2) {
1561f1ae32a1SGerd Hoffmann         case 0: /* HcRevision */
1562f1ae32a1SGerd Hoffmann             retval = 0x10;
1563f1ae32a1SGerd Hoffmann             break;
1564f1ae32a1SGerd Hoffmann 
1565f1ae32a1SGerd Hoffmann         case 1: /* HcControl */
1566f1ae32a1SGerd Hoffmann             retval = ohci->ctl;
1567f1ae32a1SGerd Hoffmann             break;
1568f1ae32a1SGerd Hoffmann 
1569f1ae32a1SGerd Hoffmann         case 2: /* HcCommandStatus */
1570f1ae32a1SGerd Hoffmann             retval = ohci->status;
1571f1ae32a1SGerd Hoffmann             break;
1572f1ae32a1SGerd Hoffmann 
1573f1ae32a1SGerd Hoffmann         case 3: /* HcInterruptStatus */
1574f1ae32a1SGerd Hoffmann             retval = ohci->intr_status;
1575f1ae32a1SGerd Hoffmann             break;
1576f1ae32a1SGerd Hoffmann 
1577f1ae32a1SGerd Hoffmann         case 4: /* HcInterruptEnable */
1578f1ae32a1SGerd Hoffmann         case 5: /* HcInterruptDisable */
1579f1ae32a1SGerd Hoffmann             retval = ohci->intr;
1580f1ae32a1SGerd Hoffmann             break;
1581f1ae32a1SGerd Hoffmann 
1582f1ae32a1SGerd Hoffmann         case 6: /* HcHCCA */
1583f1ae32a1SGerd Hoffmann             retval = ohci->hcca;
1584f1ae32a1SGerd Hoffmann             break;
1585f1ae32a1SGerd Hoffmann 
1586f1ae32a1SGerd Hoffmann         case 7: /* HcPeriodCurrentED */
1587f1ae32a1SGerd Hoffmann             retval = ohci->per_cur;
1588f1ae32a1SGerd Hoffmann             break;
1589f1ae32a1SGerd Hoffmann 
1590f1ae32a1SGerd Hoffmann         case 8: /* HcControlHeadED */
1591f1ae32a1SGerd Hoffmann             retval = ohci->ctrl_head;
1592f1ae32a1SGerd Hoffmann             break;
1593f1ae32a1SGerd Hoffmann 
1594f1ae32a1SGerd Hoffmann         case 9: /* HcControlCurrentED */
1595f1ae32a1SGerd Hoffmann             retval = ohci->ctrl_cur;
1596f1ae32a1SGerd Hoffmann             break;
1597f1ae32a1SGerd Hoffmann 
1598f1ae32a1SGerd Hoffmann         case 10: /* HcBulkHeadED */
1599f1ae32a1SGerd Hoffmann             retval = ohci->bulk_head;
1600f1ae32a1SGerd Hoffmann             break;
1601f1ae32a1SGerd Hoffmann 
1602f1ae32a1SGerd Hoffmann         case 11: /* HcBulkCurrentED */
1603f1ae32a1SGerd Hoffmann             retval = ohci->bulk_cur;
1604f1ae32a1SGerd Hoffmann             break;
1605f1ae32a1SGerd Hoffmann 
1606f1ae32a1SGerd Hoffmann         case 12: /* HcDoneHead */
1607f1ae32a1SGerd Hoffmann             retval = ohci->done;
1608f1ae32a1SGerd Hoffmann             break;
1609f1ae32a1SGerd Hoffmann 
1610f1ae32a1SGerd Hoffmann         case 13: /* HcFmInterretval */
1611f1ae32a1SGerd Hoffmann             retval = (ohci->fit << 31) | (ohci->fsmps << 16) | (ohci->fi);
1612f1ae32a1SGerd Hoffmann             break;
1613f1ae32a1SGerd Hoffmann 
1614f1ae32a1SGerd Hoffmann         case 14: /* HcFmRemaining */
1615f1ae32a1SGerd Hoffmann             retval = ohci_get_frame_remaining(ohci);
1616f1ae32a1SGerd Hoffmann             break;
1617f1ae32a1SGerd Hoffmann 
1618f1ae32a1SGerd Hoffmann         case 15: /* HcFmNumber */
1619f1ae32a1SGerd Hoffmann             retval = ohci->frame_number;
1620f1ae32a1SGerd Hoffmann             break;
1621f1ae32a1SGerd Hoffmann 
1622f1ae32a1SGerd Hoffmann         case 16: /* HcPeriodicStart */
1623f1ae32a1SGerd Hoffmann             retval = ohci->pstart;
1624f1ae32a1SGerd Hoffmann             break;
1625f1ae32a1SGerd Hoffmann 
1626f1ae32a1SGerd Hoffmann         case 17: /* HcLSThreshold */
1627f1ae32a1SGerd Hoffmann             retval = ohci->lst;
1628f1ae32a1SGerd Hoffmann             break;
1629f1ae32a1SGerd Hoffmann 
1630f1ae32a1SGerd Hoffmann         case 18: /* HcRhDescriptorA */
1631f1ae32a1SGerd Hoffmann             retval = ohci->rhdesc_a;
1632f1ae32a1SGerd Hoffmann             break;
1633f1ae32a1SGerd Hoffmann 
1634f1ae32a1SGerd Hoffmann         case 19: /* HcRhDescriptorB */
1635f1ae32a1SGerd Hoffmann             retval = ohci->rhdesc_b;
1636f1ae32a1SGerd Hoffmann             break;
1637f1ae32a1SGerd Hoffmann 
1638f1ae32a1SGerd Hoffmann         case 20: /* HcRhStatus */
1639f1ae32a1SGerd Hoffmann             retval = ohci->rhstatus;
1640f1ae32a1SGerd Hoffmann             break;
1641f1ae32a1SGerd Hoffmann 
1642f1ae32a1SGerd Hoffmann         /* PXA27x specific registers */
1643f1ae32a1SGerd Hoffmann         case 24: /* HcStatus */
1644f1ae32a1SGerd Hoffmann             retval = ohci->hstatus & ohci->hmask;
1645f1ae32a1SGerd Hoffmann             break;
1646f1ae32a1SGerd Hoffmann 
1647f1ae32a1SGerd Hoffmann         case 25: /* HcHReset */
1648f1ae32a1SGerd Hoffmann             retval = ohci->hreset;
1649f1ae32a1SGerd Hoffmann             break;
1650f1ae32a1SGerd Hoffmann 
1651f1ae32a1SGerd Hoffmann         case 26: /* HcHInterruptEnable */
1652f1ae32a1SGerd Hoffmann             retval = ohci->hmask;
1653f1ae32a1SGerd Hoffmann             break;
1654f1ae32a1SGerd Hoffmann 
1655f1ae32a1SGerd Hoffmann         case 27: /* HcHInterruptTest */
1656f1ae32a1SGerd Hoffmann             retval = ohci->htest;
1657f1ae32a1SGerd Hoffmann             break;
1658f1ae32a1SGerd Hoffmann 
1659f1ae32a1SGerd Hoffmann         default:
1660dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_mem_read_bad_offset(addr);
1661f1ae32a1SGerd Hoffmann             retval = 0xffffffff;
1662f1ae32a1SGerd Hoffmann         }
1663f1ae32a1SGerd Hoffmann     }
1664f1ae32a1SGerd Hoffmann 
1665f1ae32a1SGerd Hoffmann     return retval;
1666f1ae32a1SGerd Hoffmann }
1667f1ae32a1SGerd Hoffmann 
1668f1ae32a1SGerd Hoffmann static void ohci_mem_write(void *opaque,
1669a8170e5eSAvi Kivity                            hwaddr addr,
1670f1ae32a1SGerd Hoffmann                            uint64_t val,
1671f1ae32a1SGerd Hoffmann                            unsigned size)
1672f1ae32a1SGerd Hoffmann {
1673f1ae32a1SGerd Hoffmann     OHCIState *ohci = opaque;
1674f1ae32a1SGerd Hoffmann 
1675f1ae32a1SGerd Hoffmann     /* Only aligned reads are allowed on OHCI */
1676f1ae32a1SGerd Hoffmann     if (addr & 3) {
1677dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_mem_write_unaligned(addr);
1678f1ae32a1SGerd Hoffmann         return;
1679f1ae32a1SGerd Hoffmann     }
1680f1ae32a1SGerd Hoffmann 
1681f1ae32a1SGerd Hoffmann     if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) {
1682f1ae32a1SGerd Hoffmann         /* HcRhPortStatus */
1683f1ae32a1SGerd Hoffmann         ohci_port_set_status(ohci, (addr - 0x54) >> 2, val);
1684f1ae32a1SGerd Hoffmann         return;
1685f1ae32a1SGerd Hoffmann     }
1686f1ae32a1SGerd Hoffmann 
1687f1ae32a1SGerd Hoffmann     switch (addr >> 2) {
1688f1ae32a1SGerd Hoffmann     case 1: /* HcControl */
1689f1ae32a1SGerd Hoffmann         ohci_set_ctl(ohci, val);
1690f1ae32a1SGerd Hoffmann         break;
1691f1ae32a1SGerd Hoffmann 
1692f1ae32a1SGerd Hoffmann     case 2: /* HcCommandStatus */
1693f1ae32a1SGerd Hoffmann         /* SOC is read-only */
1694f1ae32a1SGerd Hoffmann         val = (val & ~OHCI_STATUS_SOC);
1695f1ae32a1SGerd Hoffmann 
1696f1ae32a1SGerd Hoffmann         /* Bits written as '0' remain unchanged in the register */
1697f1ae32a1SGerd Hoffmann         ohci->status |= val;
1698f1ae32a1SGerd Hoffmann 
1699f1ae32a1SGerd Hoffmann         if (ohci->status & OHCI_STATUS_HCR)
17000922c3f6SHervé Poussineau             ohci_soft_reset(ohci);
1701f1ae32a1SGerd Hoffmann         break;
1702f1ae32a1SGerd Hoffmann 
1703f1ae32a1SGerd Hoffmann     case 3: /* HcInterruptStatus */
1704f1ae32a1SGerd Hoffmann         ohci->intr_status &= ~val;
1705f1ae32a1SGerd Hoffmann         ohci_intr_update(ohci);
1706f1ae32a1SGerd Hoffmann         break;
1707f1ae32a1SGerd Hoffmann 
1708f1ae32a1SGerd Hoffmann     case 4: /* HcInterruptEnable */
1709f1ae32a1SGerd Hoffmann         ohci->intr |= val;
1710f1ae32a1SGerd Hoffmann         ohci_intr_update(ohci);
1711f1ae32a1SGerd Hoffmann         break;
1712f1ae32a1SGerd Hoffmann 
1713f1ae32a1SGerd Hoffmann     case 5: /* HcInterruptDisable */
1714f1ae32a1SGerd Hoffmann         ohci->intr &= ~val;
1715f1ae32a1SGerd Hoffmann         ohci_intr_update(ohci);
1716f1ae32a1SGerd Hoffmann         break;
1717f1ae32a1SGerd Hoffmann 
1718f1ae32a1SGerd Hoffmann     case 6: /* HcHCCA */
1719f1ae32a1SGerd Hoffmann         ohci->hcca = val & OHCI_HCCA_MASK;
1720f1ae32a1SGerd Hoffmann         break;
1721f1ae32a1SGerd Hoffmann 
1722f1ae32a1SGerd Hoffmann     case 7: /* HcPeriodCurrentED */
1723f1ae32a1SGerd Hoffmann         /* Ignore writes to this read-only register, Linux does them */
1724f1ae32a1SGerd Hoffmann         break;
1725f1ae32a1SGerd Hoffmann 
1726f1ae32a1SGerd Hoffmann     case 8: /* HcControlHeadED */
1727f1ae32a1SGerd Hoffmann         ohci->ctrl_head = val & OHCI_EDPTR_MASK;
1728f1ae32a1SGerd Hoffmann         break;
1729f1ae32a1SGerd Hoffmann 
1730f1ae32a1SGerd Hoffmann     case 9: /* HcControlCurrentED */
1731f1ae32a1SGerd Hoffmann         ohci->ctrl_cur = val & OHCI_EDPTR_MASK;
1732f1ae32a1SGerd Hoffmann         break;
1733f1ae32a1SGerd Hoffmann 
1734f1ae32a1SGerd Hoffmann     case 10: /* HcBulkHeadED */
1735f1ae32a1SGerd Hoffmann         ohci->bulk_head = val & OHCI_EDPTR_MASK;
1736f1ae32a1SGerd Hoffmann         break;
1737f1ae32a1SGerd Hoffmann 
1738f1ae32a1SGerd Hoffmann     case 11: /* HcBulkCurrentED */
1739f1ae32a1SGerd Hoffmann         ohci->bulk_cur = val & OHCI_EDPTR_MASK;
1740f1ae32a1SGerd Hoffmann         break;
1741f1ae32a1SGerd Hoffmann 
1742f1ae32a1SGerd Hoffmann     case 13: /* HcFmInterval */
1743f1ae32a1SGerd Hoffmann         ohci->fsmps = (val & OHCI_FMI_FSMPS) >> 16;
1744f1ae32a1SGerd Hoffmann         ohci->fit = (val & OHCI_FMI_FIT) >> 31;
1745f1ae32a1SGerd Hoffmann         ohci_set_frame_interval(ohci, val);
1746f1ae32a1SGerd Hoffmann         break;
1747f1ae32a1SGerd Hoffmann 
1748f1ae32a1SGerd Hoffmann     case 15: /* HcFmNumber */
1749f1ae32a1SGerd Hoffmann         break;
1750f1ae32a1SGerd Hoffmann 
1751f1ae32a1SGerd Hoffmann     case 16: /* HcPeriodicStart */
1752f1ae32a1SGerd Hoffmann         ohci->pstart = val & 0xffff;
1753f1ae32a1SGerd Hoffmann         break;
1754f1ae32a1SGerd Hoffmann 
1755f1ae32a1SGerd Hoffmann     case 17: /* HcLSThreshold */
1756f1ae32a1SGerd Hoffmann         ohci->lst = val & 0xffff;
1757f1ae32a1SGerd Hoffmann         break;
1758f1ae32a1SGerd Hoffmann 
1759f1ae32a1SGerd Hoffmann     case 18: /* HcRhDescriptorA */
1760f1ae32a1SGerd Hoffmann         ohci->rhdesc_a &= ~OHCI_RHA_RW_MASK;
1761f1ae32a1SGerd Hoffmann         ohci->rhdesc_a |= val & OHCI_RHA_RW_MASK;
1762f1ae32a1SGerd Hoffmann         break;
1763f1ae32a1SGerd Hoffmann 
1764f1ae32a1SGerd Hoffmann     case 19: /* HcRhDescriptorB */
1765f1ae32a1SGerd Hoffmann         break;
1766f1ae32a1SGerd Hoffmann 
1767f1ae32a1SGerd Hoffmann     case 20: /* HcRhStatus */
1768f1ae32a1SGerd Hoffmann         ohci_set_hub_status(ohci, val);
1769f1ae32a1SGerd Hoffmann         break;
1770f1ae32a1SGerd Hoffmann 
1771f1ae32a1SGerd Hoffmann     /* PXA27x specific registers */
1772f1ae32a1SGerd Hoffmann     case 24: /* HcStatus */
1773f1ae32a1SGerd Hoffmann         ohci->hstatus &= ~(val & ohci->hmask);
17747fa96d73SGerd Hoffmann         break;
1775f1ae32a1SGerd Hoffmann 
1776f1ae32a1SGerd Hoffmann     case 25: /* HcHReset */
1777f1ae32a1SGerd Hoffmann         ohci->hreset = val & ~OHCI_HRESET_FSBIR;
1778f1ae32a1SGerd Hoffmann         if (val & OHCI_HRESET_FSBIR)
177984d04e21SHervé Poussineau             ohci_hard_reset(ohci);
1780f1ae32a1SGerd Hoffmann         break;
1781f1ae32a1SGerd Hoffmann 
1782f1ae32a1SGerd Hoffmann     case 26: /* HcHInterruptEnable */
1783f1ae32a1SGerd Hoffmann         ohci->hmask = val;
1784f1ae32a1SGerd Hoffmann         break;
1785f1ae32a1SGerd Hoffmann 
1786f1ae32a1SGerd Hoffmann     case 27: /* HcHInterruptTest */
1787f1ae32a1SGerd Hoffmann         ohci->htest = val;
1788f1ae32a1SGerd Hoffmann         break;
1789f1ae32a1SGerd Hoffmann 
1790f1ae32a1SGerd Hoffmann     default:
1791dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_mem_write_bad_offset(addr);
1792f1ae32a1SGerd Hoffmann         break;
1793f1ae32a1SGerd Hoffmann     }
1794f1ae32a1SGerd Hoffmann }
1795f1ae32a1SGerd Hoffmann 
1796f1ae32a1SGerd Hoffmann static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev)
1797f1ae32a1SGerd Hoffmann {
1798f1ae32a1SGerd Hoffmann     if (ohci->async_td &&
1799f1ae32a1SGerd Hoffmann         usb_packet_is_inflight(&ohci->usb_packet) &&
1800f1ae32a1SGerd Hoffmann         ohci->usb_packet.ep->dev == dev) {
1801f1ae32a1SGerd Hoffmann         usb_cancel_packet(&ohci->usb_packet);
1802f1ae32a1SGerd Hoffmann         ohci->async_td = 0;
1803f1ae32a1SGerd Hoffmann     }
1804f1ae32a1SGerd Hoffmann }
1805f1ae32a1SGerd Hoffmann 
1806f1ae32a1SGerd Hoffmann static const MemoryRegionOps ohci_mem_ops = {
1807f1ae32a1SGerd Hoffmann     .read = ohci_mem_read,
1808f1ae32a1SGerd Hoffmann     .write = ohci_mem_write,
1809f1ae32a1SGerd Hoffmann     .endianness = DEVICE_LITTLE_ENDIAN,
1810f1ae32a1SGerd Hoffmann };
1811f1ae32a1SGerd Hoffmann 
1812f1ae32a1SGerd Hoffmann static USBPortOps ohci_port_ops = {
1813f1ae32a1SGerd Hoffmann     .attach = ohci_attach,
1814f1ae32a1SGerd Hoffmann     .detach = ohci_detach,
1815f1ae32a1SGerd Hoffmann     .child_detach = ohci_child_detach,
1816f1ae32a1SGerd Hoffmann     .wakeup = ohci_wakeup,
1817f1ae32a1SGerd Hoffmann     .complete = ohci_async_complete_packet,
1818f1ae32a1SGerd Hoffmann };
1819f1ae32a1SGerd Hoffmann 
1820f1ae32a1SGerd Hoffmann static USBBusOps ohci_bus_ops = {
1821f1ae32a1SGerd Hoffmann };
1822f1ae32a1SGerd Hoffmann 
182334d97308SThomas Huth void usb_ohci_init(OHCIState *ohci, DeviceState *dev, uint32_t num_ports,
182434d97308SThomas Huth                    dma_addr_t localmem_base, char *masterbus,
182534d97308SThomas Huth                    uint32_t firstport, AddressSpace *as,
182672e0c127SThomas Huth                    void (*ohci_die_fn)(struct OHCIState *), Error **errp)
1827f1ae32a1SGerd Hoffmann {
1828f4bbaaf5SMarkus Armbruster     Error *err = NULL;
1829f1ae32a1SGerd Hoffmann     int i;
1830f1ae32a1SGerd Hoffmann 
1831df32fd1cSPaolo Bonzini     ohci->as = as;
183272e0c127SThomas Huth     ohci->ohci_die = ohci_die_fn;
18339ac6a217SDavid Gibson 
1834d400fc01SThomas Huth     if (num_ports > OHCI_MAX_PORTS) {
1835b9a3a4f2SLi Qiang         error_setg(errp, "OHCI num-ports=%u is too big (limit is %u ports)",
1836d400fc01SThomas Huth                    num_ports, OHCI_MAX_PORTS);
1837d400fc01SThomas Huth         return;
1838d400fc01SThomas Huth     }
1839d400fc01SThomas Huth 
1840f1ae32a1SGerd Hoffmann     if (usb_frame_time == 0) {
1841f1ae32a1SGerd Hoffmann #ifdef OHCI_TIME_WARP
184273bcb24dSRutuja Shah         usb_frame_time = NANOSECONDS_PER_SECOND;
184373bcb24dSRutuja Shah         usb_bit_time = NANOSECONDS_PER_SECOND / (USB_HZ / 1000);
1844f1ae32a1SGerd Hoffmann #else
184573bcb24dSRutuja Shah         usb_frame_time = NANOSECONDS_PER_SECOND / 1000;
184673bcb24dSRutuja Shah         if (NANOSECONDS_PER_SECOND >= USB_HZ) {
184773bcb24dSRutuja Shah             usb_bit_time = NANOSECONDS_PER_SECOND / USB_HZ;
1848f1ae32a1SGerd Hoffmann         } else {
1849f1ae32a1SGerd Hoffmann             usb_bit_time = 1;
1850f1ae32a1SGerd Hoffmann         }
1851f1ae32a1SGerd Hoffmann #endif
1852dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_init_time(usb_frame_time, usb_bit_time);
1853f1ae32a1SGerd Hoffmann     }
1854f1ae32a1SGerd Hoffmann 
1855f1ae32a1SGerd Hoffmann     ohci->num_ports = num_ports;
1856f1ae32a1SGerd Hoffmann     if (masterbus) {
1857f1ae32a1SGerd Hoffmann         USBPort *ports[OHCI_MAX_PORTS];
1858f1ae32a1SGerd Hoffmann         for(i = 0; i < num_ports; i++) {
1859f1ae32a1SGerd Hoffmann             ports[i] = &ohci->rhport[i].port;
1860f1ae32a1SGerd Hoffmann         }
1861f4bbaaf5SMarkus Armbruster         usb_register_companion(masterbus, ports, num_ports,
1862f1ae32a1SGerd Hoffmann                                firstport, ohci, &ohci_port_ops,
1863f4bbaaf5SMarkus Armbruster                                USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL,
1864f4bbaaf5SMarkus Armbruster                                &err);
1865f4bbaaf5SMarkus Armbruster         if (err) {
186687581feaSMarkus Armbruster             error_propagate(errp, err);
186787581feaSMarkus Armbruster             return;
1868f1ae32a1SGerd Hoffmann         }
1869f1ae32a1SGerd Hoffmann     } else {
1870c889b3a5SAndreas Färber         usb_bus_new(&ohci->bus, sizeof(ohci->bus), &ohci_bus_ops, dev);
1871f1ae32a1SGerd Hoffmann         for (i = 0; i < num_ports; i++) {
1872f1ae32a1SGerd Hoffmann             usb_register_port(&ohci->bus, &ohci->rhport[i].port,
1873f1ae32a1SGerd Hoffmann                               ohci, i, &ohci_port_ops,
1874f1ae32a1SGerd Hoffmann                               USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
1875f1ae32a1SGerd Hoffmann         }
1876f1ae32a1SGerd Hoffmann     }
1877f1ae32a1SGerd Hoffmann 
187822fc860bSPaolo Bonzini     memory_region_init_io(&ohci->mem, OBJECT(dev), &ohci_mem_ops,
187922fc860bSPaolo Bonzini                           ohci, "ohci", 256);
1880f1ae32a1SGerd Hoffmann     ohci->localmem_base = localmem_base;
1881f1ae32a1SGerd Hoffmann 
1882f1ae32a1SGerd Hoffmann     ohci->name = object_get_typename(OBJECT(dev));
1883f1ae32a1SGerd Hoffmann     usb_packet_init(&ohci->usb_packet);
1884f1ae32a1SGerd Hoffmann 
1885f1ae32a1SGerd Hoffmann     ohci->async_td = 0;
1886fa1298c2SGerd Hoffmann 
1887fa1298c2SGerd Hoffmann     ohci->eof_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
1888fa1298c2SGerd Hoffmann                                    ohci_frame_boundary, ohci);
1889f1ae32a1SGerd Hoffmann }
1890f1ae32a1SGerd Hoffmann 
189172e0c127SThomas Huth /**
189272e0c127SThomas Huth  * A typical OHCI will stop operating and set itself into error state
189372e0c127SThomas Huth  * (which can be queried by MMIO) to signal that it got an error.
1894cf66ee8eSAlexey Kardashevskiy  */
189534d97308SThomas Huth void ohci_sysbus_die(struct OHCIState *ohci)
1896cf66ee8eSAlexey Kardashevskiy {
1897dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_die();
1898cf66ee8eSAlexey Kardashevskiy 
1899cf66ee8eSAlexey Kardashevskiy     ohci_set_interrupt(ohci, OHCI_INTR_UE);
1900cf66ee8eSAlexey Kardashevskiy     ohci_bus_stop(ohci);
190172e0c127SThomas Huth }
190272e0c127SThomas Huth 
1903457215ecSHu Tao static void ohci_realize_pxa(DeviceState *dev, Error **errp)
1904f1ae32a1SGerd Hoffmann {
19051aa0c0c7SHu Tao     OHCISysBusState *s = SYSBUS_OHCI(dev);
1906457215ecSHu Tao     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
1907d7145b66SBALATON Zoltan     Error *err = NULL;
1908f1ae32a1SGerd Hoffmann 
1909d7145b66SBALATON Zoltan     usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset,
1910d7145b66SBALATON Zoltan                   s->masterbus, s->firstport,
191172e0c127SThomas Huth                   &address_space_memory, ohci_sysbus_die, &err);
1912d7145b66SBALATON Zoltan     if (err) {
1913d7145b66SBALATON Zoltan         error_propagate(errp, err);
1914d7145b66SBALATON Zoltan         return;
1915d7145b66SBALATON Zoltan     }
1916457215ecSHu Tao     sysbus_init_irq(sbd, &s->ohci.irq);
1917457215ecSHu Tao     sysbus_init_mmio(sbd, &s->ohci.mem);
1918f1ae32a1SGerd Hoffmann }
1919f1ae32a1SGerd Hoffmann 
192088dd1b8dSGonglei static void usb_ohci_reset_sysbus(DeviceState *dev)
192188dd1b8dSGonglei {
192288dd1b8dSGonglei     OHCISysBusState *s = SYSBUS_OHCI(dev);
192388dd1b8dSGonglei     OHCIState *ohci = &s->ohci;
192488dd1b8dSGonglei 
192584d04e21SHervé Poussineau     ohci_hard_reset(ohci);
192688dd1b8dSGonglei }
192788dd1b8dSGonglei 
192869e25d26SAlexey Kardashevskiy static const VMStateDescription vmstate_ohci_state_port = {
192969e25d26SAlexey Kardashevskiy     .name = "ohci-core/port",
193069e25d26SAlexey Kardashevskiy     .version_id = 1,
193169e25d26SAlexey Kardashevskiy     .minimum_version_id = 1,
193269e25d26SAlexey Kardashevskiy     .fields = (VMStateField[]) {
193369e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(ctrl, OHCIPort),
193469e25d26SAlexey Kardashevskiy         VMSTATE_END_OF_LIST()
193569e25d26SAlexey Kardashevskiy     },
193669e25d26SAlexey Kardashevskiy };
193769e25d26SAlexey Kardashevskiy 
193869e25d26SAlexey Kardashevskiy static bool ohci_eof_timer_needed(void *opaque)
193969e25d26SAlexey Kardashevskiy {
194069e25d26SAlexey Kardashevskiy     OHCIState *ohci = opaque;
194169e25d26SAlexey Kardashevskiy 
1942fa1298c2SGerd Hoffmann     return timer_pending(ohci->eof_timer);
194369e25d26SAlexey Kardashevskiy }
194469e25d26SAlexey Kardashevskiy 
194569e25d26SAlexey Kardashevskiy static const VMStateDescription vmstate_ohci_eof_timer = {
194669e25d26SAlexey Kardashevskiy     .name = "ohci-core/eof-timer",
194769e25d26SAlexey Kardashevskiy     .version_id = 1,
194869e25d26SAlexey Kardashevskiy     .minimum_version_id = 1,
19495cd8cadaSJuan Quintela     .needed = ohci_eof_timer_needed,
195069e25d26SAlexey Kardashevskiy     .fields = (VMStateField[]) {
1951e720677eSPaolo Bonzini         VMSTATE_TIMER_PTR(eof_timer, OHCIState),
195269e25d26SAlexey Kardashevskiy         VMSTATE_END_OF_LIST()
195369e25d26SAlexey Kardashevskiy     },
195469e25d26SAlexey Kardashevskiy };
195569e25d26SAlexey Kardashevskiy 
195634d97308SThomas Huth const VMStateDescription vmstate_ohci_state = {
195769e25d26SAlexey Kardashevskiy     .name = "ohci-core",
195869e25d26SAlexey Kardashevskiy     .version_id = 1,
195969e25d26SAlexey Kardashevskiy     .minimum_version_id = 1,
196069e25d26SAlexey Kardashevskiy     .fields = (VMStateField[]) {
196169e25d26SAlexey Kardashevskiy         VMSTATE_INT64(sof_time, OHCIState),
196269e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(ctl, OHCIState),
196369e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(status, OHCIState),
196469e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(intr_status, OHCIState),
196569e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(intr, OHCIState),
196669e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(hcca, OHCIState),
196769e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(ctrl_head, OHCIState),
196869e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(ctrl_cur, OHCIState),
196969e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(bulk_head, OHCIState),
197069e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(bulk_cur, OHCIState),
197169e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(per_cur, OHCIState),
197269e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(done, OHCIState),
197369e25d26SAlexey Kardashevskiy         VMSTATE_INT32(done_count, OHCIState),
197469e25d26SAlexey Kardashevskiy         VMSTATE_UINT16(fsmps, OHCIState),
197569e25d26SAlexey Kardashevskiy         VMSTATE_UINT8(fit, OHCIState),
197669e25d26SAlexey Kardashevskiy         VMSTATE_UINT16(fi, OHCIState),
197769e25d26SAlexey Kardashevskiy         VMSTATE_UINT8(frt, OHCIState),
197869e25d26SAlexey Kardashevskiy         VMSTATE_UINT16(frame_number, OHCIState),
197969e25d26SAlexey Kardashevskiy         VMSTATE_UINT16(padding, OHCIState),
198069e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(pstart, OHCIState),
198169e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(lst, OHCIState),
198269e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(rhdesc_a, OHCIState),
198369e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(rhdesc_b, OHCIState),
198469e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(rhstatus, OHCIState),
198569e25d26SAlexey Kardashevskiy         VMSTATE_STRUCT_ARRAY(rhport, OHCIState, OHCI_MAX_PORTS, 0,
198669e25d26SAlexey Kardashevskiy                              vmstate_ohci_state_port, OHCIPort),
198769e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(hstatus, OHCIState),
198869e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(hmask, OHCIState),
198969e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(hreset, OHCIState),
199069e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(htest, OHCIState),
199169e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(old_ctl, OHCIState),
199269e25d26SAlexey Kardashevskiy         VMSTATE_UINT8_ARRAY(usb_buf, OHCIState, 8192),
199369e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(async_td, OHCIState),
199469e25d26SAlexey Kardashevskiy         VMSTATE_BOOL(async_complete, OHCIState),
199569e25d26SAlexey Kardashevskiy         VMSTATE_END_OF_LIST()
199669e25d26SAlexey Kardashevskiy     },
19975cd8cadaSJuan Quintela     .subsections = (const VMStateDescription*[]) {
19985cd8cadaSJuan Quintela         &vmstate_ohci_eof_timer,
19995cd8cadaSJuan Quintela         NULL
200069e25d26SAlexey Kardashevskiy     }
200169e25d26SAlexey Kardashevskiy };
200269e25d26SAlexey Kardashevskiy 
2003f1ae32a1SGerd Hoffmann static Property ohci_sysbus_properties[] = {
2004d7145b66SBALATON Zoltan     DEFINE_PROP_STRING("masterbus", OHCISysBusState, masterbus),
2005f1ae32a1SGerd Hoffmann     DEFINE_PROP_UINT32("num-ports", OHCISysBusState, num_ports, 3),
2006d7145b66SBALATON Zoltan     DEFINE_PROP_UINT32("firstport", OHCISysBusState, firstport, 0),
20076998b6c7SVijay Kumar B     DEFINE_PROP_DMAADDR("dma-offset", OHCISysBusState, dma_offset, 0),
2008f1ae32a1SGerd Hoffmann     DEFINE_PROP_END_OF_LIST(),
2009f1ae32a1SGerd Hoffmann };
2010f1ae32a1SGerd Hoffmann 
2011f1ae32a1SGerd Hoffmann static void ohci_sysbus_class_init(ObjectClass *klass, void *data)
2012f1ae32a1SGerd Hoffmann {
2013f1ae32a1SGerd Hoffmann     DeviceClass *dc = DEVICE_CLASS(klass);
2014f1ae32a1SGerd Hoffmann 
2015457215ecSHu Tao     dc->realize = ohci_realize_pxa;
2016125ee0edSMarcel Apfelbaum     set_bit(DEVICE_CATEGORY_USB, dc->categories);
2017f1ae32a1SGerd Hoffmann     dc->desc = "OHCI USB Controller";
20184f67d30bSMarc-André Lureau     device_class_set_props(dc, ohci_sysbus_properties);
201988dd1b8dSGonglei     dc->reset = usb_ohci_reset_sysbus;
2020f1ae32a1SGerd Hoffmann }
2021f1ae32a1SGerd Hoffmann 
20228c43a6f0SAndreas Färber static const TypeInfo ohci_sysbus_info = {
20231aa0c0c7SHu Tao     .name          = TYPE_SYSBUS_OHCI,
2024f1ae32a1SGerd Hoffmann     .parent        = TYPE_SYS_BUS_DEVICE,
2025f1ae32a1SGerd Hoffmann     .instance_size = sizeof(OHCISysBusState),
2026f1ae32a1SGerd Hoffmann     .class_init    = ohci_sysbus_class_init,
2027f1ae32a1SGerd Hoffmann };
2028f1ae32a1SGerd Hoffmann 
2029f1ae32a1SGerd Hoffmann static void ohci_register_types(void)
2030f1ae32a1SGerd Hoffmann {
2031f1ae32a1SGerd Hoffmann     type_register_static(&ohci_sysbus_info);
2032f1ae32a1SGerd Hoffmann }
2033f1ae32a1SGerd Hoffmann 
2034f1ae32a1SGerd Hoffmann type_init(ohci_register_types)
2035