xref: /openbmc/qemu/hw/usb/hcd-ohci.c (revision fa1298c2)
1f1ae32a1SGerd Hoffmann /*
2f1ae32a1SGerd Hoffmann  * QEMU USB OHCI Emulation
3f1ae32a1SGerd Hoffmann  * Copyright (c) 2004 Gianni Tedesco
4f1ae32a1SGerd Hoffmann  * Copyright (c) 2006 CodeSourcery
5f1ae32a1SGerd Hoffmann  * Copyright (c) 2006 Openedhand Ltd.
6f1ae32a1SGerd Hoffmann  *
7f1ae32a1SGerd Hoffmann  * This library is free software; you can redistribute it and/or
8f1ae32a1SGerd Hoffmann  * modify it under the terms of the GNU Lesser General Public
9f1ae32a1SGerd Hoffmann  * License as published by the Free Software Foundation; either
10f1ae32a1SGerd Hoffmann  * version 2 of the License, or (at your option) any later version.
11f1ae32a1SGerd Hoffmann  *
12f1ae32a1SGerd Hoffmann  * This library is distributed in the hope that it will be useful,
13f1ae32a1SGerd Hoffmann  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14f1ae32a1SGerd Hoffmann  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15f1ae32a1SGerd Hoffmann  * Lesser General Public License for more details.
16f1ae32a1SGerd Hoffmann  *
17f1ae32a1SGerd Hoffmann  * You should have received a copy of the GNU Lesser General Public
18f1ae32a1SGerd Hoffmann  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19f1ae32a1SGerd Hoffmann  *
20f1ae32a1SGerd Hoffmann  * TODO:
21f1ae32a1SGerd Hoffmann  *  o Isochronous transfers
22f1ae32a1SGerd Hoffmann  *  o Allocate bandwidth in frames properly
23f1ae32a1SGerd Hoffmann  *  o Disable timers when nothing needs to be done, or remove timer usage
24f1ae32a1SGerd Hoffmann  *    all together.
25f1ae32a1SGerd Hoffmann  *  o BIOS work to boot from USB storage
26f1ae32a1SGerd Hoffmann */
27f1ae32a1SGerd Hoffmann 
28e532b2e0SPeter Maydell #include "qemu/osdep.h"
29f1ae32a1SGerd Hoffmann #include "hw/hw.h"
301de7afc9SPaolo Bonzini #include "qemu/timer.h"
31f1ae32a1SGerd Hoffmann #include "hw/usb.h"
32a2cb15b0SMichael S. Tsirkin #include "hw/pci/pci.h"
33f1ae32a1SGerd Hoffmann #include "hw/sysbus.h"
349ac6a217SDavid Gibson #include "hw/qdev-dma.h"
35dc1f5988SAlexey Kardashevskiy #include "trace.h"
36f1ae32a1SGerd Hoffmann 
37f1ae32a1SGerd Hoffmann /* This causes frames to occur 1000x slower */
38f1ae32a1SGerd Hoffmann //#define OHCI_TIME_WARP 1
39f1ae32a1SGerd Hoffmann 
40f1ae32a1SGerd Hoffmann /* Number of Downstream Ports on the root hub.  */
41f1ae32a1SGerd Hoffmann 
42f1ae32a1SGerd Hoffmann #define OHCI_MAX_PORTS 15
43f1ae32a1SGerd Hoffmann 
44f1ae32a1SGerd Hoffmann static int64_t usb_frame_time;
45f1ae32a1SGerd Hoffmann static int64_t usb_bit_time;
46f1ae32a1SGerd Hoffmann 
47f1ae32a1SGerd Hoffmann typedef struct OHCIPort {
48f1ae32a1SGerd Hoffmann     USBPort port;
49f1ae32a1SGerd Hoffmann     uint32_t ctrl;
50f1ae32a1SGerd Hoffmann } OHCIPort;
51f1ae32a1SGerd Hoffmann 
52f1ae32a1SGerd Hoffmann typedef struct {
53f1ae32a1SGerd Hoffmann     USBBus bus;
54f1ae32a1SGerd Hoffmann     qemu_irq irq;
55f1ae32a1SGerd Hoffmann     MemoryRegion mem;
56df32fd1cSPaolo Bonzini     AddressSpace *as;
57f1ae32a1SGerd Hoffmann     int num_ports;
58f1ae32a1SGerd Hoffmann     const char *name;
59f1ae32a1SGerd Hoffmann 
60f1ae32a1SGerd Hoffmann     QEMUTimer *eof_timer;
61f1ae32a1SGerd Hoffmann     int64_t sof_time;
62f1ae32a1SGerd Hoffmann 
63f1ae32a1SGerd Hoffmann     /* OHCI state */
64f1ae32a1SGerd Hoffmann     /* Control partition */
65f1ae32a1SGerd Hoffmann     uint32_t ctl, status;
66f1ae32a1SGerd Hoffmann     uint32_t intr_status;
67f1ae32a1SGerd Hoffmann     uint32_t intr;
68f1ae32a1SGerd Hoffmann 
69f1ae32a1SGerd Hoffmann     /* memory pointer partition */
70f1ae32a1SGerd Hoffmann     uint32_t hcca;
71f1ae32a1SGerd Hoffmann     uint32_t ctrl_head, ctrl_cur;
72f1ae32a1SGerd Hoffmann     uint32_t bulk_head, bulk_cur;
73f1ae32a1SGerd Hoffmann     uint32_t per_cur;
74f1ae32a1SGerd Hoffmann     uint32_t done;
7569e25d26SAlexey Kardashevskiy     int32_t done_count;
76f1ae32a1SGerd Hoffmann 
77f1ae32a1SGerd Hoffmann     /* Frame counter partition */
7869e25d26SAlexey Kardashevskiy     uint16_t fsmps;
7969e25d26SAlexey Kardashevskiy     uint8_t fit;
8069e25d26SAlexey Kardashevskiy     uint16_t fi;
8169e25d26SAlexey Kardashevskiy     uint8_t frt;
82f1ae32a1SGerd Hoffmann     uint16_t frame_number;
83f1ae32a1SGerd Hoffmann     uint16_t padding;
84f1ae32a1SGerd Hoffmann     uint32_t pstart;
85f1ae32a1SGerd Hoffmann     uint32_t lst;
86f1ae32a1SGerd Hoffmann 
87f1ae32a1SGerd Hoffmann     /* Root Hub partition */
88f1ae32a1SGerd Hoffmann     uint32_t rhdesc_a, rhdesc_b;
89f1ae32a1SGerd Hoffmann     uint32_t rhstatus;
90f1ae32a1SGerd Hoffmann     OHCIPort rhport[OHCI_MAX_PORTS];
91f1ae32a1SGerd Hoffmann 
92f1ae32a1SGerd Hoffmann     /* PXA27x Non-OHCI events */
93f1ae32a1SGerd Hoffmann     uint32_t hstatus;
94f1ae32a1SGerd Hoffmann     uint32_t hmask;
95f1ae32a1SGerd Hoffmann     uint32_t hreset;
96f1ae32a1SGerd Hoffmann     uint32_t htest;
97f1ae32a1SGerd Hoffmann 
98f1ae32a1SGerd Hoffmann     /* SM501 local memory offset */
999ac6a217SDavid Gibson     dma_addr_t localmem_base;
100f1ae32a1SGerd Hoffmann 
101f1ae32a1SGerd Hoffmann     /* Active packets.  */
102f1ae32a1SGerd Hoffmann     uint32_t old_ctl;
103f1ae32a1SGerd Hoffmann     USBPacket usb_packet;
104f1ae32a1SGerd Hoffmann     uint8_t usb_buf[8192];
105f1ae32a1SGerd Hoffmann     uint32_t async_td;
10669e25d26SAlexey Kardashevskiy     bool async_complete;
107f1ae32a1SGerd Hoffmann 
108f1ae32a1SGerd Hoffmann } OHCIState;
109f1ae32a1SGerd Hoffmann 
110f1ae32a1SGerd Hoffmann /* Host Controller Communications Area */
111f1ae32a1SGerd Hoffmann struct ohci_hcca {
112f1ae32a1SGerd Hoffmann     uint32_t intr[32];
113f1ae32a1SGerd Hoffmann     uint16_t frame, pad;
114f1ae32a1SGerd Hoffmann     uint32_t done;
115f1ae32a1SGerd Hoffmann };
11686e18caeSWei Yang #define HCCA_WRITEBACK_OFFSET   offsetof(struct ohci_hcca, frame)
11786e18caeSWei Yang #define HCCA_WRITEBACK_SIZE     8 /* frame, pad, done */
11886e18caeSWei Yang 
11986e18caeSWei Yang #define ED_WBACK_OFFSET offsetof(struct ohci_ed, head)
12086e18caeSWei Yang #define ED_WBACK_SIZE   4
121f1ae32a1SGerd Hoffmann 
122f1ae32a1SGerd Hoffmann static void ohci_bus_stop(OHCIState *ohci);
123f1ae32a1SGerd Hoffmann static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev);
124f1ae32a1SGerd Hoffmann 
125f1ae32a1SGerd Hoffmann /* Bitfields for the first word of an Endpoint Desciptor.  */
126f1ae32a1SGerd Hoffmann #define OHCI_ED_FA_SHIFT  0
127f1ae32a1SGerd Hoffmann #define OHCI_ED_FA_MASK   (0x7f<<OHCI_ED_FA_SHIFT)
128f1ae32a1SGerd Hoffmann #define OHCI_ED_EN_SHIFT  7
129f1ae32a1SGerd Hoffmann #define OHCI_ED_EN_MASK   (0xf<<OHCI_ED_EN_SHIFT)
130f1ae32a1SGerd Hoffmann #define OHCI_ED_D_SHIFT   11
131f1ae32a1SGerd Hoffmann #define OHCI_ED_D_MASK    (3<<OHCI_ED_D_SHIFT)
132f1ae32a1SGerd Hoffmann #define OHCI_ED_S         (1<<13)
133f1ae32a1SGerd Hoffmann #define OHCI_ED_K         (1<<14)
134f1ae32a1SGerd Hoffmann #define OHCI_ED_F         (1<<15)
135f1ae32a1SGerd Hoffmann #define OHCI_ED_MPS_SHIFT 16
136f1ae32a1SGerd Hoffmann #define OHCI_ED_MPS_MASK  (0x7ff<<OHCI_ED_MPS_SHIFT)
137f1ae32a1SGerd Hoffmann 
138f1ae32a1SGerd Hoffmann /* Flags in the head field of an Endpoint Desciptor.  */
139f1ae32a1SGerd Hoffmann #define OHCI_ED_H         1
140f1ae32a1SGerd Hoffmann #define OHCI_ED_C         2
141f1ae32a1SGerd Hoffmann 
142f1ae32a1SGerd Hoffmann /* Bitfields for the first word of a Transfer Desciptor.  */
143f1ae32a1SGerd Hoffmann #define OHCI_TD_R         (1<<18)
144f1ae32a1SGerd Hoffmann #define OHCI_TD_DP_SHIFT  19
145f1ae32a1SGerd Hoffmann #define OHCI_TD_DP_MASK   (3<<OHCI_TD_DP_SHIFT)
146f1ae32a1SGerd Hoffmann #define OHCI_TD_DI_SHIFT  21
147f1ae32a1SGerd Hoffmann #define OHCI_TD_DI_MASK   (7<<OHCI_TD_DI_SHIFT)
148f1ae32a1SGerd Hoffmann #define OHCI_TD_T0        (1<<24)
149f1ae32a1SGerd Hoffmann #define OHCI_TD_T1        (1<<25)
150f1ae32a1SGerd Hoffmann #define OHCI_TD_EC_SHIFT  26
151f1ae32a1SGerd Hoffmann #define OHCI_TD_EC_MASK   (3<<OHCI_TD_EC_SHIFT)
152f1ae32a1SGerd Hoffmann #define OHCI_TD_CC_SHIFT  28
153f1ae32a1SGerd Hoffmann #define OHCI_TD_CC_MASK   (0xf<<OHCI_TD_CC_SHIFT)
154f1ae32a1SGerd Hoffmann 
155f1ae32a1SGerd Hoffmann /* Bitfields for the first word of an Isochronous Transfer Desciptor.  */
156f1ae32a1SGerd Hoffmann /* CC & DI - same as in the General Transfer Desciptor */
157f1ae32a1SGerd Hoffmann #define OHCI_TD_SF_SHIFT  0
158f1ae32a1SGerd Hoffmann #define OHCI_TD_SF_MASK   (0xffff<<OHCI_TD_SF_SHIFT)
159f1ae32a1SGerd Hoffmann #define OHCI_TD_FC_SHIFT  24
160f1ae32a1SGerd Hoffmann #define OHCI_TD_FC_MASK   (7<<OHCI_TD_FC_SHIFT)
161f1ae32a1SGerd Hoffmann 
162f1ae32a1SGerd Hoffmann /* Isochronous Transfer Desciptor - Offset / PacketStatusWord */
163f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_CC_SHIFT 12
164f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_CC_MASK  (0xf<<OHCI_TD_PSW_CC_SHIFT)
165f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_SIZE_SHIFT 0
166f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_SIZE_MASK  (0xfff<<OHCI_TD_PSW_SIZE_SHIFT)
167f1ae32a1SGerd Hoffmann 
168f1ae32a1SGerd Hoffmann #define OHCI_PAGE_MASK    0xfffff000
169f1ae32a1SGerd Hoffmann #define OHCI_OFFSET_MASK  0xfff
170f1ae32a1SGerd Hoffmann 
171f1ae32a1SGerd Hoffmann #define OHCI_DPTR_MASK    0xfffffff0
172f1ae32a1SGerd Hoffmann 
173f1ae32a1SGerd Hoffmann #define OHCI_BM(val, field) \
174f1ae32a1SGerd Hoffmann   (((val) & OHCI_##field##_MASK) >> OHCI_##field##_SHIFT)
175f1ae32a1SGerd Hoffmann 
176f1ae32a1SGerd Hoffmann #define OHCI_SET_BM(val, field, newval) do { \
177f1ae32a1SGerd Hoffmann     val &= ~OHCI_##field##_MASK; \
178f1ae32a1SGerd Hoffmann     val |= ((newval) << OHCI_##field##_SHIFT) & OHCI_##field##_MASK; \
179f1ae32a1SGerd Hoffmann     } while(0)
180f1ae32a1SGerd Hoffmann 
181f1ae32a1SGerd Hoffmann /* endpoint descriptor */
182f1ae32a1SGerd Hoffmann struct ohci_ed {
183f1ae32a1SGerd Hoffmann     uint32_t flags;
184f1ae32a1SGerd Hoffmann     uint32_t tail;
185f1ae32a1SGerd Hoffmann     uint32_t head;
186f1ae32a1SGerd Hoffmann     uint32_t next;
187f1ae32a1SGerd Hoffmann };
188f1ae32a1SGerd Hoffmann 
189f1ae32a1SGerd Hoffmann /* General transfer descriptor */
190f1ae32a1SGerd Hoffmann struct ohci_td {
191f1ae32a1SGerd Hoffmann     uint32_t flags;
192f1ae32a1SGerd Hoffmann     uint32_t cbp;
193f1ae32a1SGerd Hoffmann     uint32_t next;
194f1ae32a1SGerd Hoffmann     uint32_t be;
195f1ae32a1SGerd Hoffmann };
196f1ae32a1SGerd Hoffmann 
197f1ae32a1SGerd Hoffmann /* Isochronous transfer descriptor */
198f1ae32a1SGerd Hoffmann struct ohci_iso_td {
199f1ae32a1SGerd Hoffmann     uint32_t flags;
200f1ae32a1SGerd Hoffmann     uint32_t bp;
201f1ae32a1SGerd Hoffmann     uint32_t next;
202f1ae32a1SGerd Hoffmann     uint32_t be;
203f1ae32a1SGerd Hoffmann     uint16_t offset[8];
204f1ae32a1SGerd Hoffmann };
205f1ae32a1SGerd Hoffmann 
206f1ae32a1SGerd Hoffmann #define USB_HZ                      12000000
207f1ae32a1SGerd Hoffmann 
208f1ae32a1SGerd Hoffmann /* OHCI Local stuff */
209f1ae32a1SGerd Hoffmann #define OHCI_CTL_CBSR         ((1<<0)|(1<<1))
210f1ae32a1SGerd Hoffmann #define OHCI_CTL_PLE          (1<<2)
211f1ae32a1SGerd Hoffmann #define OHCI_CTL_IE           (1<<3)
212f1ae32a1SGerd Hoffmann #define OHCI_CTL_CLE          (1<<4)
213f1ae32a1SGerd Hoffmann #define OHCI_CTL_BLE          (1<<5)
214f1ae32a1SGerd Hoffmann #define OHCI_CTL_HCFS         ((1<<6)|(1<<7))
215f1ae32a1SGerd Hoffmann #define  OHCI_USB_RESET       0x00
216f1ae32a1SGerd Hoffmann #define  OHCI_USB_RESUME      0x40
217f1ae32a1SGerd Hoffmann #define  OHCI_USB_OPERATIONAL 0x80
218f1ae32a1SGerd Hoffmann #define  OHCI_USB_SUSPEND     0xc0
219f1ae32a1SGerd Hoffmann #define OHCI_CTL_IR           (1<<8)
220f1ae32a1SGerd Hoffmann #define OHCI_CTL_RWC          (1<<9)
221f1ae32a1SGerd Hoffmann #define OHCI_CTL_RWE          (1<<10)
222f1ae32a1SGerd Hoffmann 
223f1ae32a1SGerd Hoffmann #define OHCI_STATUS_HCR       (1<<0)
224f1ae32a1SGerd Hoffmann #define OHCI_STATUS_CLF       (1<<1)
225f1ae32a1SGerd Hoffmann #define OHCI_STATUS_BLF       (1<<2)
226f1ae32a1SGerd Hoffmann #define OHCI_STATUS_OCR       (1<<3)
227f1ae32a1SGerd Hoffmann #define OHCI_STATUS_SOC       ((1<<6)|(1<<7))
228f1ae32a1SGerd Hoffmann 
22900b01793SPeter Maydell #define OHCI_INTR_SO          (1U<<0) /* Scheduling overrun */
23000b01793SPeter Maydell #define OHCI_INTR_WD          (1U<<1) /* HcDoneHead writeback */
23100b01793SPeter Maydell #define OHCI_INTR_SF          (1U<<2) /* Start of frame */
23200b01793SPeter Maydell #define OHCI_INTR_RD          (1U<<3) /* Resume detect */
23300b01793SPeter Maydell #define OHCI_INTR_UE          (1U<<4) /* Unrecoverable error */
23400b01793SPeter Maydell #define OHCI_INTR_FNO         (1U<<5) /* Frame number overflow */
23500b01793SPeter Maydell #define OHCI_INTR_RHSC        (1U<<6) /* Root hub status change */
23600b01793SPeter Maydell #define OHCI_INTR_OC          (1U<<30) /* Ownership change */
23700b01793SPeter Maydell #define OHCI_INTR_MIE         (1U<<31) /* Master Interrupt Enable */
238f1ae32a1SGerd Hoffmann 
239f1ae32a1SGerd Hoffmann #define OHCI_HCCA_SIZE        0x100
240f1ae32a1SGerd Hoffmann #define OHCI_HCCA_MASK        0xffffff00
241f1ae32a1SGerd Hoffmann 
242f1ae32a1SGerd Hoffmann #define OHCI_EDPTR_MASK       0xfffffff0
243f1ae32a1SGerd Hoffmann 
244f1ae32a1SGerd Hoffmann #define OHCI_FMI_FI           0x00003fff
245f1ae32a1SGerd Hoffmann #define OHCI_FMI_FSMPS        0xffff0000
246f1ae32a1SGerd Hoffmann #define OHCI_FMI_FIT          0x80000000
247f1ae32a1SGerd Hoffmann 
24800b01793SPeter Maydell #define OHCI_FR_RT            (1U<<31)
249f1ae32a1SGerd Hoffmann 
250f1ae32a1SGerd Hoffmann #define OHCI_LS_THRESH        0x628
251f1ae32a1SGerd Hoffmann 
252f1ae32a1SGerd Hoffmann #define OHCI_RHA_RW_MASK      0x00000000 /* Mask of supported features.  */
253f1ae32a1SGerd Hoffmann #define OHCI_RHA_PSM          (1<<8)
254f1ae32a1SGerd Hoffmann #define OHCI_RHA_NPS          (1<<9)
255f1ae32a1SGerd Hoffmann #define OHCI_RHA_DT           (1<<10)
256f1ae32a1SGerd Hoffmann #define OHCI_RHA_OCPM         (1<<11)
257f1ae32a1SGerd Hoffmann #define OHCI_RHA_NOCP         (1<<12)
258f1ae32a1SGerd Hoffmann #define OHCI_RHA_POTPGT_MASK  0xff000000
259f1ae32a1SGerd Hoffmann 
26000b01793SPeter Maydell #define OHCI_RHS_LPS          (1U<<0)
26100b01793SPeter Maydell #define OHCI_RHS_OCI          (1U<<1)
26200b01793SPeter Maydell #define OHCI_RHS_DRWE         (1U<<15)
26300b01793SPeter Maydell #define OHCI_RHS_LPSC         (1U<<16)
26400b01793SPeter Maydell #define OHCI_RHS_OCIC         (1U<<17)
26500b01793SPeter Maydell #define OHCI_RHS_CRWE         (1U<<31)
266f1ae32a1SGerd Hoffmann 
267f1ae32a1SGerd Hoffmann #define OHCI_PORT_CCS         (1<<0)
268f1ae32a1SGerd Hoffmann #define OHCI_PORT_PES         (1<<1)
269f1ae32a1SGerd Hoffmann #define OHCI_PORT_PSS         (1<<2)
270f1ae32a1SGerd Hoffmann #define OHCI_PORT_POCI        (1<<3)
271f1ae32a1SGerd Hoffmann #define OHCI_PORT_PRS         (1<<4)
272f1ae32a1SGerd Hoffmann #define OHCI_PORT_PPS         (1<<8)
273f1ae32a1SGerd Hoffmann #define OHCI_PORT_LSDA        (1<<9)
274f1ae32a1SGerd Hoffmann #define OHCI_PORT_CSC         (1<<16)
275f1ae32a1SGerd Hoffmann #define OHCI_PORT_PESC        (1<<17)
276f1ae32a1SGerd Hoffmann #define OHCI_PORT_PSSC        (1<<18)
277f1ae32a1SGerd Hoffmann #define OHCI_PORT_OCIC        (1<<19)
278f1ae32a1SGerd Hoffmann #define OHCI_PORT_PRSC        (1<<20)
279f1ae32a1SGerd Hoffmann #define OHCI_PORT_WTC         (OHCI_PORT_CSC|OHCI_PORT_PESC|OHCI_PORT_PSSC \
280f1ae32a1SGerd Hoffmann                                |OHCI_PORT_OCIC|OHCI_PORT_PRSC)
281f1ae32a1SGerd Hoffmann 
282f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_SETUP     0x0
283f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_OUT       0x1
284f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_IN        0x2
285f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_RESERVED  0x3
286f1ae32a1SGerd Hoffmann 
287f1ae32a1SGerd Hoffmann #define OHCI_CC_NOERROR             0x0
288f1ae32a1SGerd Hoffmann #define OHCI_CC_CRC                 0x1
289f1ae32a1SGerd Hoffmann #define OHCI_CC_BITSTUFFING         0x2
290f1ae32a1SGerd Hoffmann #define OHCI_CC_DATATOGGLEMISMATCH  0x3
291f1ae32a1SGerd Hoffmann #define OHCI_CC_STALL               0x4
292f1ae32a1SGerd Hoffmann #define OHCI_CC_DEVICENOTRESPONDING 0x5
293f1ae32a1SGerd Hoffmann #define OHCI_CC_PIDCHECKFAILURE     0x6
294f1ae32a1SGerd Hoffmann #define OHCI_CC_UNDEXPETEDPID       0x7
295f1ae32a1SGerd Hoffmann #define OHCI_CC_DATAOVERRUN         0x8
296f1ae32a1SGerd Hoffmann #define OHCI_CC_DATAUNDERRUN        0x9
297f1ae32a1SGerd Hoffmann #define OHCI_CC_BUFFEROVERRUN       0xc
298f1ae32a1SGerd Hoffmann #define OHCI_CC_BUFFERUNDERRUN      0xd
299f1ae32a1SGerd Hoffmann 
300f1ae32a1SGerd Hoffmann #define OHCI_HRESET_FSBIR       (1 << 0)
301f1ae32a1SGerd Hoffmann 
302cf66ee8eSAlexey Kardashevskiy static void ohci_die(OHCIState *ohci);
303cf66ee8eSAlexey Kardashevskiy 
304f1ae32a1SGerd Hoffmann /* Update IRQ levels */
305f1ae32a1SGerd Hoffmann static inline void ohci_intr_update(OHCIState *ohci)
306f1ae32a1SGerd Hoffmann {
307f1ae32a1SGerd Hoffmann     int level = 0;
308f1ae32a1SGerd Hoffmann 
309f1ae32a1SGerd Hoffmann     if ((ohci->intr & OHCI_INTR_MIE) &&
310f1ae32a1SGerd Hoffmann         (ohci->intr_status & ohci->intr))
311f1ae32a1SGerd Hoffmann         level = 1;
312f1ae32a1SGerd Hoffmann 
313f1ae32a1SGerd Hoffmann     qemu_set_irq(ohci->irq, level);
314f1ae32a1SGerd Hoffmann }
315f1ae32a1SGerd Hoffmann 
316f1ae32a1SGerd Hoffmann /* Set an interrupt */
317f1ae32a1SGerd Hoffmann static inline void ohci_set_interrupt(OHCIState *ohci, uint32_t intr)
318f1ae32a1SGerd Hoffmann {
319f1ae32a1SGerd Hoffmann     ohci->intr_status |= intr;
320f1ae32a1SGerd Hoffmann     ohci_intr_update(ohci);
321f1ae32a1SGerd Hoffmann }
322f1ae32a1SGerd Hoffmann 
323f1ae32a1SGerd Hoffmann /* Attach or detach a device on a root hub port.  */
324f1ae32a1SGerd Hoffmann static void ohci_attach(USBPort *port1)
325f1ae32a1SGerd Hoffmann {
326f1ae32a1SGerd Hoffmann     OHCIState *s = port1->opaque;
327f1ae32a1SGerd Hoffmann     OHCIPort *port = &s->rhport[port1->index];
328f1ae32a1SGerd Hoffmann     uint32_t old_state = port->ctrl;
329f1ae32a1SGerd Hoffmann 
330f1ae32a1SGerd Hoffmann     /* set connect status */
331f1ae32a1SGerd Hoffmann     port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;
332f1ae32a1SGerd Hoffmann 
333f1ae32a1SGerd Hoffmann     /* update speed */
334f1ae32a1SGerd Hoffmann     if (port->port.dev->speed == USB_SPEED_LOW) {
335f1ae32a1SGerd Hoffmann         port->ctrl |= OHCI_PORT_LSDA;
336f1ae32a1SGerd Hoffmann     } else {
337f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_LSDA;
338f1ae32a1SGerd Hoffmann     }
339f1ae32a1SGerd Hoffmann 
340f1ae32a1SGerd Hoffmann     /* notify of remote-wakeup */
341f1ae32a1SGerd Hoffmann     if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
342f1ae32a1SGerd Hoffmann         ohci_set_interrupt(s, OHCI_INTR_RD);
343f1ae32a1SGerd Hoffmann     }
344f1ae32a1SGerd Hoffmann 
345dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_port_attach(port1->index);
346f1ae32a1SGerd Hoffmann 
347f1ae32a1SGerd Hoffmann     if (old_state != port->ctrl) {
348f1ae32a1SGerd Hoffmann         ohci_set_interrupt(s, OHCI_INTR_RHSC);
349f1ae32a1SGerd Hoffmann     }
350f1ae32a1SGerd Hoffmann }
351f1ae32a1SGerd Hoffmann 
352f1ae32a1SGerd Hoffmann static void ohci_detach(USBPort *port1)
353f1ae32a1SGerd Hoffmann {
354f1ae32a1SGerd Hoffmann     OHCIState *s = port1->opaque;
355f1ae32a1SGerd Hoffmann     OHCIPort *port = &s->rhport[port1->index];
356f1ae32a1SGerd Hoffmann     uint32_t old_state = port->ctrl;
357f1ae32a1SGerd Hoffmann 
358f1ae32a1SGerd Hoffmann     ohci_async_cancel_device(s, port1->dev);
359f1ae32a1SGerd Hoffmann 
360f1ae32a1SGerd Hoffmann     /* set connect status */
361f1ae32a1SGerd Hoffmann     if (port->ctrl & OHCI_PORT_CCS) {
362f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_CCS;
363f1ae32a1SGerd Hoffmann         port->ctrl |= OHCI_PORT_CSC;
364f1ae32a1SGerd Hoffmann     }
365f1ae32a1SGerd Hoffmann     /* disable port */
366f1ae32a1SGerd Hoffmann     if (port->ctrl & OHCI_PORT_PES) {
367f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_PES;
368f1ae32a1SGerd Hoffmann         port->ctrl |= OHCI_PORT_PESC;
369f1ae32a1SGerd Hoffmann     }
370dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_port_detach(port1->index);
371f1ae32a1SGerd Hoffmann 
372f1ae32a1SGerd Hoffmann     if (old_state != port->ctrl) {
373f1ae32a1SGerd Hoffmann         ohci_set_interrupt(s, OHCI_INTR_RHSC);
374f1ae32a1SGerd Hoffmann     }
375f1ae32a1SGerd Hoffmann }
376f1ae32a1SGerd Hoffmann 
377f1ae32a1SGerd Hoffmann static void ohci_wakeup(USBPort *port1)
378f1ae32a1SGerd Hoffmann {
379f1ae32a1SGerd Hoffmann     OHCIState *s = port1->opaque;
380f1ae32a1SGerd Hoffmann     OHCIPort *port = &s->rhport[port1->index];
381f1ae32a1SGerd Hoffmann     uint32_t intr = 0;
382f1ae32a1SGerd Hoffmann     if (port->ctrl & OHCI_PORT_PSS) {
383dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_port_wakeup(port1->index);
384f1ae32a1SGerd Hoffmann         port->ctrl |= OHCI_PORT_PSSC;
385f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_PSS;
386f1ae32a1SGerd Hoffmann         intr = OHCI_INTR_RHSC;
387f1ae32a1SGerd Hoffmann     }
388f1ae32a1SGerd Hoffmann     /* Note that the controller can be suspended even if this port is not */
389f1ae32a1SGerd Hoffmann     if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
390dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_remote_wakeup(s->name);
391f1ae32a1SGerd Hoffmann         /* This is the one state transition the controller can do by itself */
392f1ae32a1SGerd Hoffmann         s->ctl &= ~OHCI_CTL_HCFS;
393f1ae32a1SGerd Hoffmann         s->ctl |= OHCI_USB_RESUME;
394f1ae32a1SGerd Hoffmann         /* In suspend mode only ResumeDetected is possible, not RHSC:
395f1ae32a1SGerd Hoffmann          * see the OHCI spec 5.1.2.3.
396f1ae32a1SGerd Hoffmann          */
397f1ae32a1SGerd Hoffmann         intr = OHCI_INTR_RD;
398f1ae32a1SGerd Hoffmann     }
399f1ae32a1SGerd Hoffmann     ohci_set_interrupt(s, intr);
400f1ae32a1SGerd Hoffmann }
401f1ae32a1SGerd Hoffmann 
402f1ae32a1SGerd Hoffmann static void ohci_child_detach(USBPort *port1, USBDevice *child)
403f1ae32a1SGerd Hoffmann {
404f1ae32a1SGerd Hoffmann     OHCIState *s = port1->opaque;
405f1ae32a1SGerd Hoffmann 
406f1ae32a1SGerd Hoffmann     ohci_async_cancel_device(s, child);
407f1ae32a1SGerd Hoffmann }
408f1ae32a1SGerd Hoffmann 
409f1ae32a1SGerd Hoffmann static USBDevice *ohci_find_device(OHCIState *ohci, uint8_t addr)
410f1ae32a1SGerd Hoffmann {
411f1ae32a1SGerd Hoffmann     USBDevice *dev;
412f1ae32a1SGerd Hoffmann     int i;
413f1ae32a1SGerd Hoffmann 
414f1ae32a1SGerd Hoffmann     for (i = 0; i < ohci->num_ports; i++) {
415f1ae32a1SGerd Hoffmann         if ((ohci->rhport[i].ctrl & OHCI_PORT_PES) == 0) {
416f1ae32a1SGerd Hoffmann             continue;
417f1ae32a1SGerd Hoffmann         }
418f1ae32a1SGerd Hoffmann         dev = usb_find_device(&ohci->rhport[i].port, addr);
419f1ae32a1SGerd Hoffmann         if (dev != NULL) {
420f1ae32a1SGerd Hoffmann             return dev;
421f1ae32a1SGerd Hoffmann         }
422f1ae32a1SGerd Hoffmann     }
423f1ae32a1SGerd Hoffmann     return NULL;
424f1ae32a1SGerd Hoffmann }
425f1ae32a1SGerd Hoffmann 
426f79738b0SHans de Goede static void ohci_stop_endpoints(OHCIState *ohci)
427f79738b0SHans de Goede {
428f79738b0SHans de Goede     USBDevice *dev;
429f79738b0SHans de Goede     int i, j;
430f79738b0SHans de Goede 
431f79738b0SHans de Goede     for (i = 0; i < ohci->num_ports; i++) {
432f79738b0SHans de Goede         dev = ohci->rhport[i].port.dev;
433f79738b0SHans de Goede         if (dev && dev->attached) {
434f79738b0SHans de Goede             usb_device_ep_stopped(dev, &dev->ep_ctl);
435f79738b0SHans de Goede             for (j = 0; j < USB_MAX_ENDPOINTS; j++) {
436f79738b0SHans de Goede                 usb_device_ep_stopped(dev, &dev->ep_in[j]);
437f79738b0SHans de Goede                 usb_device_ep_stopped(dev, &dev->ep_out[j]);
438f79738b0SHans de Goede             }
439f79738b0SHans de Goede         }
440f79738b0SHans de Goede     }
441f79738b0SHans de Goede }
442f79738b0SHans de Goede 
44384d04e21SHervé Poussineau static void ohci_roothub_reset(OHCIState *ohci)
444f1ae32a1SGerd Hoffmann {
445f1ae32a1SGerd Hoffmann     OHCIPort *port;
446f1ae32a1SGerd Hoffmann     int i;
447f1ae32a1SGerd Hoffmann 
448f1ae32a1SGerd Hoffmann     ohci_bus_stop(ohci);
44984d04e21SHervé Poussineau     ohci->rhdesc_a = OHCI_RHA_NPS | ohci->num_ports;
45084d04e21SHervé Poussineau     ohci->rhdesc_b = 0x0; /* Impl. specific */
45184d04e21SHervé Poussineau     ohci->rhstatus = 0;
45284d04e21SHervé Poussineau 
45384d04e21SHervé Poussineau     for (i = 0; i < ohci->num_ports; i++) {
45484d04e21SHervé Poussineau         port = &ohci->rhport[i];
45584d04e21SHervé Poussineau         port->ctrl = 0;
45684d04e21SHervé Poussineau         if (port->port.dev && port->port.dev->attached) {
45784d04e21SHervé Poussineau             usb_port_reset(&port->port);
45884d04e21SHervé Poussineau         }
45984d04e21SHervé Poussineau     }
46084d04e21SHervé Poussineau     if (ohci->async_td) {
46184d04e21SHervé Poussineau         usb_cancel_packet(&ohci->usb_packet);
46284d04e21SHervé Poussineau         ohci->async_td = 0;
46384d04e21SHervé Poussineau     }
46484d04e21SHervé Poussineau     ohci_stop_endpoints(ohci);
46584d04e21SHervé Poussineau }
46684d04e21SHervé Poussineau 
46784d04e21SHervé Poussineau /* Reset the controller */
46884d04e21SHervé Poussineau static void ohci_soft_reset(OHCIState *ohci)
46984d04e21SHervé Poussineau {
47084d04e21SHervé Poussineau     trace_usb_ohci_reset(ohci->name);
47184d04e21SHervé Poussineau 
47284d04e21SHervé Poussineau     ohci_bus_stop(ohci);
47384d04e21SHervé Poussineau     ohci->ctl = (ohci->ctl & OHCI_CTL_IR) | OHCI_USB_SUSPEND;
474f1ae32a1SGerd Hoffmann     ohci->old_ctl = 0;
475f1ae32a1SGerd Hoffmann     ohci->status = 0;
476f1ae32a1SGerd Hoffmann     ohci->intr_status = 0;
477f1ae32a1SGerd Hoffmann     ohci->intr = OHCI_INTR_MIE;
478f1ae32a1SGerd Hoffmann 
479f1ae32a1SGerd Hoffmann     ohci->hcca = 0;
480f1ae32a1SGerd Hoffmann     ohci->ctrl_head = ohci->ctrl_cur = 0;
481f1ae32a1SGerd Hoffmann     ohci->bulk_head = ohci->bulk_cur = 0;
482f1ae32a1SGerd Hoffmann     ohci->per_cur = 0;
483f1ae32a1SGerd Hoffmann     ohci->done = 0;
484f1ae32a1SGerd Hoffmann     ohci->done_count = 7;
485f1ae32a1SGerd Hoffmann 
486f1ae32a1SGerd Hoffmann     /* FSMPS is marked TBD in OCHI 1.0, what gives ffs?
487f1ae32a1SGerd Hoffmann      * I took the value linux sets ...
488f1ae32a1SGerd Hoffmann      */
489f1ae32a1SGerd Hoffmann     ohci->fsmps = 0x2778;
490f1ae32a1SGerd Hoffmann     ohci->fi = 0x2edf;
491f1ae32a1SGerd Hoffmann     ohci->fit = 0;
492f1ae32a1SGerd Hoffmann     ohci->frt = 0;
493f1ae32a1SGerd Hoffmann     ohci->frame_number = 0;
494f1ae32a1SGerd Hoffmann     ohci->pstart = 0;
495f1ae32a1SGerd Hoffmann     ohci->lst = OHCI_LS_THRESH;
49684d04e21SHervé Poussineau }
497f1ae32a1SGerd Hoffmann 
49884d04e21SHervé Poussineau static void ohci_hard_reset(OHCIState *ohci)
499f1ae32a1SGerd Hoffmann {
50084d04e21SHervé Poussineau     ohci_soft_reset(ohci);
50184d04e21SHervé Poussineau     ohci->ctl = 0;
50284d04e21SHervé Poussineau     ohci_roothub_reset(ohci);
503f1ae32a1SGerd Hoffmann }
504f1ae32a1SGerd Hoffmann 
505f1ae32a1SGerd Hoffmann /* Get an array of dwords from main memory */
506f1ae32a1SGerd Hoffmann static inline int get_dwords(OHCIState *ohci,
5079ac6a217SDavid Gibson                              dma_addr_t addr, uint32_t *buf, int num)
508f1ae32a1SGerd Hoffmann {
509f1ae32a1SGerd Hoffmann     int i;
510f1ae32a1SGerd Hoffmann 
511f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
512f1ae32a1SGerd Hoffmann 
513f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
514cf66ee8eSAlexey Kardashevskiy         if (dma_memory_read(ohci->as, addr, buf, sizeof(*buf))) {
515cf66ee8eSAlexey Kardashevskiy             return -1;
516cf66ee8eSAlexey Kardashevskiy         }
517f1ae32a1SGerd Hoffmann         *buf = le32_to_cpu(*buf);
518f1ae32a1SGerd Hoffmann     }
519f1ae32a1SGerd Hoffmann 
520cf66ee8eSAlexey Kardashevskiy     return 0;
521f1ae32a1SGerd Hoffmann }
522f1ae32a1SGerd Hoffmann 
523f1ae32a1SGerd Hoffmann /* Put an array of dwords in to main memory */
524f1ae32a1SGerd Hoffmann static inline int put_dwords(OHCIState *ohci,
5259ac6a217SDavid Gibson                              dma_addr_t addr, uint32_t *buf, int num)
526f1ae32a1SGerd Hoffmann {
527f1ae32a1SGerd Hoffmann     int i;
528f1ae32a1SGerd Hoffmann 
529f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
530f1ae32a1SGerd Hoffmann 
531f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
532f1ae32a1SGerd Hoffmann         uint32_t tmp = cpu_to_le32(*buf);
533cf66ee8eSAlexey Kardashevskiy         if (dma_memory_write(ohci->as, addr, &tmp, sizeof(tmp))) {
534cf66ee8eSAlexey Kardashevskiy             return -1;
535cf66ee8eSAlexey Kardashevskiy         }
536f1ae32a1SGerd Hoffmann     }
537f1ae32a1SGerd Hoffmann 
538cf66ee8eSAlexey Kardashevskiy     return 0;
539f1ae32a1SGerd Hoffmann }
540f1ae32a1SGerd Hoffmann 
541f1ae32a1SGerd Hoffmann /* Get an array of words from main memory */
542f1ae32a1SGerd Hoffmann static inline int get_words(OHCIState *ohci,
5439ac6a217SDavid Gibson                             dma_addr_t addr, uint16_t *buf, int num)
544f1ae32a1SGerd Hoffmann {
545f1ae32a1SGerd Hoffmann     int i;
546f1ae32a1SGerd Hoffmann 
547f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
548f1ae32a1SGerd Hoffmann 
549f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
550cf66ee8eSAlexey Kardashevskiy         if (dma_memory_read(ohci->as, addr, buf, sizeof(*buf))) {
551cf66ee8eSAlexey Kardashevskiy             return -1;
552cf66ee8eSAlexey Kardashevskiy         }
553f1ae32a1SGerd Hoffmann         *buf = le16_to_cpu(*buf);
554f1ae32a1SGerd Hoffmann     }
555f1ae32a1SGerd Hoffmann 
556cf66ee8eSAlexey Kardashevskiy     return 0;
557f1ae32a1SGerd Hoffmann }
558f1ae32a1SGerd Hoffmann 
559f1ae32a1SGerd Hoffmann /* Put an array of words in to main memory */
560f1ae32a1SGerd Hoffmann static inline int put_words(OHCIState *ohci,
5619ac6a217SDavid Gibson                             dma_addr_t addr, uint16_t *buf, int num)
562f1ae32a1SGerd Hoffmann {
563f1ae32a1SGerd Hoffmann     int i;
564f1ae32a1SGerd Hoffmann 
565f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
566f1ae32a1SGerd Hoffmann 
567f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
568f1ae32a1SGerd Hoffmann         uint16_t tmp = cpu_to_le16(*buf);
569cf66ee8eSAlexey Kardashevskiy         if (dma_memory_write(ohci->as, addr, &tmp, sizeof(tmp))) {
570cf66ee8eSAlexey Kardashevskiy             return -1;
571cf66ee8eSAlexey Kardashevskiy         }
572f1ae32a1SGerd Hoffmann     }
573f1ae32a1SGerd Hoffmann 
574cf66ee8eSAlexey Kardashevskiy     return 0;
575f1ae32a1SGerd Hoffmann }
576f1ae32a1SGerd Hoffmann 
577f1ae32a1SGerd Hoffmann static inline int ohci_read_ed(OHCIState *ohci,
5789ac6a217SDavid Gibson                                dma_addr_t addr, struct ohci_ed *ed)
579f1ae32a1SGerd Hoffmann {
580f1ae32a1SGerd Hoffmann     return get_dwords(ohci, addr, (uint32_t *)ed, sizeof(*ed) >> 2);
581f1ae32a1SGerd Hoffmann }
582f1ae32a1SGerd Hoffmann 
583f1ae32a1SGerd Hoffmann static inline int ohci_read_td(OHCIState *ohci,
5849ac6a217SDavid Gibson                                dma_addr_t addr, struct ohci_td *td)
585f1ae32a1SGerd Hoffmann {
586f1ae32a1SGerd Hoffmann     return get_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2);
587f1ae32a1SGerd Hoffmann }
588f1ae32a1SGerd Hoffmann 
589f1ae32a1SGerd Hoffmann static inline int ohci_read_iso_td(OHCIState *ohci,
5909ac6a217SDavid Gibson                                    dma_addr_t addr, struct ohci_iso_td *td)
591f1ae32a1SGerd Hoffmann {
592cf66ee8eSAlexey Kardashevskiy     return get_dwords(ohci, addr, (uint32_t *)td, 4) ||
593cf66ee8eSAlexey Kardashevskiy            get_words(ohci, addr + 16, td->offset, 8);
594f1ae32a1SGerd Hoffmann }
595f1ae32a1SGerd Hoffmann 
596f1ae32a1SGerd Hoffmann static inline int ohci_read_hcca(OHCIState *ohci,
5979ac6a217SDavid Gibson                                  dma_addr_t addr, struct ohci_hcca *hcca)
598f1ae32a1SGerd Hoffmann {
599cf66ee8eSAlexey Kardashevskiy     return dma_memory_read(ohci->as, addr + ohci->localmem_base,
600cf66ee8eSAlexey Kardashevskiy                            hcca, sizeof(*hcca));
601f1ae32a1SGerd Hoffmann }
602f1ae32a1SGerd Hoffmann 
603f1ae32a1SGerd Hoffmann static inline int ohci_put_ed(OHCIState *ohci,
6049ac6a217SDavid Gibson                               dma_addr_t addr, struct ohci_ed *ed)
605f1ae32a1SGerd Hoffmann {
60686e18caeSWei Yang     /* ed->tail is under control of the HCD.
60786e18caeSWei Yang      * Since just ed->head is changed by HC, just write back this
60886e18caeSWei Yang      */
60986e18caeSWei Yang 
61086e18caeSWei Yang     return put_dwords(ohci, addr + ED_WBACK_OFFSET,
61186e18caeSWei Yang                       (uint32_t *)((char *)ed + ED_WBACK_OFFSET),
61286e18caeSWei Yang                       ED_WBACK_SIZE >> 2);
613f1ae32a1SGerd Hoffmann }
614f1ae32a1SGerd Hoffmann 
615f1ae32a1SGerd Hoffmann static inline int ohci_put_td(OHCIState *ohci,
6169ac6a217SDavid Gibson                               dma_addr_t addr, struct ohci_td *td)
617f1ae32a1SGerd Hoffmann {
618f1ae32a1SGerd Hoffmann     return put_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2);
619f1ae32a1SGerd Hoffmann }
620f1ae32a1SGerd Hoffmann 
621f1ae32a1SGerd Hoffmann static inline int ohci_put_iso_td(OHCIState *ohci,
6229ac6a217SDavid Gibson                                   dma_addr_t addr, struct ohci_iso_td *td)
623f1ae32a1SGerd Hoffmann {
624cae7f29cSJack Un     return put_dwords(ohci, addr, (uint32_t *)td, 4) ||
625cae7f29cSJack Un            put_words(ohci, addr + 16, td->offset, 8);
626f1ae32a1SGerd Hoffmann }
627f1ae32a1SGerd Hoffmann 
628f1ae32a1SGerd Hoffmann static inline int ohci_put_hcca(OHCIState *ohci,
6299ac6a217SDavid Gibson                                 dma_addr_t addr, struct ohci_hcca *hcca)
630f1ae32a1SGerd Hoffmann {
631cf66ee8eSAlexey Kardashevskiy     return dma_memory_write(ohci->as,
6329ac6a217SDavid Gibson                             addr + ohci->localmem_base + HCCA_WRITEBACK_OFFSET,
63386e18caeSWei Yang                             (char *)hcca + HCCA_WRITEBACK_OFFSET,
63486e18caeSWei Yang                             HCCA_WRITEBACK_SIZE);
635f1ae32a1SGerd Hoffmann }
636f1ae32a1SGerd Hoffmann 
637f1ae32a1SGerd Hoffmann /* Read/Write the contents of a TD from/to main memory.  */
638cf66ee8eSAlexey Kardashevskiy static int ohci_copy_td(OHCIState *ohci, struct ohci_td *td,
6399ac6a217SDavid Gibson                         uint8_t *buf, int len, DMADirection dir)
640f1ae32a1SGerd Hoffmann {
6419ac6a217SDavid Gibson     dma_addr_t ptr, n;
642f1ae32a1SGerd Hoffmann 
643f1ae32a1SGerd Hoffmann     ptr = td->cbp;
644f1ae32a1SGerd Hoffmann     n = 0x1000 - (ptr & 0xfff);
645f1ae32a1SGerd Hoffmann     if (n > len)
646f1ae32a1SGerd Hoffmann         n = len;
647cf66ee8eSAlexey Kardashevskiy 
648cf66ee8eSAlexey Kardashevskiy     if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, n, dir)) {
649cf66ee8eSAlexey Kardashevskiy         return -1;
650cf66ee8eSAlexey Kardashevskiy     }
651cf66ee8eSAlexey Kardashevskiy     if (n == len) {
652cf66ee8eSAlexey Kardashevskiy         return 0;
653cf66ee8eSAlexey Kardashevskiy     }
654f1ae32a1SGerd Hoffmann     ptr = td->be & ~0xfffu;
655f1ae32a1SGerd Hoffmann     buf += n;
656cf66ee8eSAlexey Kardashevskiy     if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf,
657cf66ee8eSAlexey Kardashevskiy                       len - n, dir)) {
658cf66ee8eSAlexey Kardashevskiy         return -1;
659cf66ee8eSAlexey Kardashevskiy     }
660cf66ee8eSAlexey Kardashevskiy     return 0;
661f1ae32a1SGerd Hoffmann }
662f1ae32a1SGerd Hoffmann 
663f1ae32a1SGerd Hoffmann /* Read/Write the contents of an ISO TD from/to main memory.  */
664cf66ee8eSAlexey Kardashevskiy static int ohci_copy_iso_td(OHCIState *ohci,
665f1ae32a1SGerd Hoffmann                             uint32_t start_addr, uint32_t end_addr,
6669ac6a217SDavid Gibson                             uint8_t *buf, int len, DMADirection dir)
667f1ae32a1SGerd Hoffmann {
6689ac6a217SDavid Gibson     dma_addr_t ptr, n;
669f1ae32a1SGerd Hoffmann 
670f1ae32a1SGerd Hoffmann     ptr = start_addr;
671f1ae32a1SGerd Hoffmann     n = 0x1000 - (ptr & 0xfff);
672f1ae32a1SGerd Hoffmann     if (n > len)
673f1ae32a1SGerd Hoffmann         n = len;
674cf66ee8eSAlexey Kardashevskiy 
675cf66ee8eSAlexey Kardashevskiy     if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, n, dir)) {
676cf66ee8eSAlexey Kardashevskiy         return -1;
677cf66ee8eSAlexey Kardashevskiy     }
678cf66ee8eSAlexey Kardashevskiy     if (n == len) {
679cf66ee8eSAlexey Kardashevskiy         return 0;
680cf66ee8eSAlexey Kardashevskiy     }
681f1ae32a1SGerd Hoffmann     ptr = end_addr & ~0xfffu;
682f1ae32a1SGerd Hoffmann     buf += n;
683cf66ee8eSAlexey Kardashevskiy     if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf,
684cf66ee8eSAlexey Kardashevskiy                       len - n, dir)) {
685cf66ee8eSAlexey Kardashevskiy         return -1;
686cf66ee8eSAlexey Kardashevskiy     }
687cf66ee8eSAlexey Kardashevskiy     return 0;
688f1ae32a1SGerd Hoffmann }
689f1ae32a1SGerd Hoffmann 
690f1ae32a1SGerd Hoffmann static void ohci_process_lists(OHCIState *ohci, int completion);
691f1ae32a1SGerd Hoffmann 
692f1ae32a1SGerd Hoffmann static void ohci_async_complete_packet(USBPort *port, USBPacket *packet)
693f1ae32a1SGerd Hoffmann {
694f1ae32a1SGerd Hoffmann     OHCIState *ohci = container_of(packet, OHCIState, usb_packet);
695dc1f5988SAlexey Kardashevskiy 
696dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_async_complete();
69769e25d26SAlexey Kardashevskiy     ohci->async_complete = true;
698f1ae32a1SGerd Hoffmann     ohci_process_lists(ohci, 1);
699f1ae32a1SGerd Hoffmann }
700f1ae32a1SGerd Hoffmann 
701f1ae32a1SGerd Hoffmann #define USUB(a, b) ((int16_t)((uint16_t)(a) - (uint16_t)(b)))
702f1ae32a1SGerd Hoffmann 
703f1ae32a1SGerd Hoffmann static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
704f1ae32a1SGerd Hoffmann                                int completion)
705f1ae32a1SGerd Hoffmann {
706f1ae32a1SGerd Hoffmann     int dir;
707f1ae32a1SGerd Hoffmann     size_t len = 0;
708f1ae32a1SGerd Hoffmann     const char *str = NULL;
709f1ae32a1SGerd Hoffmann     int pid;
710f1ae32a1SGerd Hoffmann     int ret;
711f1ae32a1SGerd Hoffmann     int i;
712f1ae32a1SGerd Hoffmann     USBDevice *dev;
713f1ae32a1SGerd Hoffmann     USBEndpoint *ep;
714f1ae32a1SGerd Hoffmann     struct ohci_iso_td iso_td;
715f1ae32a1SGerd Hoffmann     uint32_t addr;
716f1ae32a1SGerd Hoffmann     uint16_t starting_frame;
717f1ae32a1SGerd Hoffmann     int16_t relative_frame_number;
718f1ae32a1SGerd Hoffmann     int frame_count;
719f1ae32a1SGerd Hoffmann     uint32_t start_offset, next_offset, end_offset = 0;
720f1ae32a1SGerd Hoffmann     uint32_t start_addr, end_addr;
721f1ae32a1SGerd Hoffmann 
722f1ae32a1SGerd Hoffmann     addr = ed->head & OHCI_DPTR_MASK;
723f1ae32a1SGerd Hoffmann 
724cf66ee8eSAlexey Kardashevskiy     if (ohci_read_iso_td(ohci, addr, &iso_td)) {
725dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_read_failed(addr);
726cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
727f1ae32a1SGerd Hoffmann         return 0;
728f1ae32a1SGerd Hoffmann     }
729f1ae32a1SGerd Hoffmann 
730f1ae32a1SGerd Hoffmann     starting_frame = OHCI_BM(iso_td.flags, TD_SF);
731f1ae32a1SGerd Hoffmann     frame_count = OHCI_BM(iso_td.flags, TD_FC);
732f1ae32a1SGerd Hoffmann     relative_frame_number = USUB(ohci->frame_number, starting_frame);
733f1ae32a1SGerd Hoffmann 
734dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_iso_td_head(
735f1ae32a1SGerd Hoffmann            ed->head & OHCI_DPTR_MASK, ed->tail & OHCI_DPTR_MASK,
736f1ae32a1SGerd Hoffmann            iso_td.flags, iso_td.bp, iso_td.next, iso_td.be,
737f1ae32a1SGerd Hoffmann            ohci->frame_number, starting_frame,
738bc0d104cSAlex Bennée            frame_count, relative_frame_number);
7393af8f177SAlexey Kardashevskiy     trace_usb_ohci_iso_td_head_offset(
7403af8f177SAlexey Kardashevskiy            iso_td.offset[0], iso_td.offset[1],
7413af8f177SAlexey Kardashevskiy            iso_td.offset[2], iso_td.offset[3],
7423af8f177SAlexey Kardashevskiy            iso_td.offset[4], iso_td.offset[5],
7433af8f177SAlexey Kardashevskiy            iso_td.offset[6], iso_td.offset[7]);
744f1ae32a1SGerd Hoffmann 
745f1ae32a1SGerd Hoffmann     if (relative_frame_number < 0) {
746dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_relative_frame_number_neg(relative_frame_number);
747f1ae32a1SGerd Hoffmann         return 1;
748f1ae32a1SGerd Hoffmann     } else if (relative_frame_number > frame_count) {
749f1ae32a1SGerd Hoffmann         /* ISO TD expired - retire the TD to the Done Queue and continue with
750f1ae32a1SGerd Hoffmann            the next ISO TD of the same ED */
751dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_relative_frame_number_big(relative_frame_number,
752f1ae32a1SGerd Hoffmann                                                         frame_count);
753f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_DATAOVERRUN);
754f1ae32a1SGerd Hoffmann         ed->head &= ~OHCI_DPTR_MASK;
755f1ae32a1SGerd Hoffmann         ed->head |= (iso_td.next & OHCI_DPTR_MASK);
756f1ae32a1SGerd Hoffmann         iso_td.next = ohci->done;
757f1ae32a1SGerd Hoffmann         ohci->done = addr;
758f1ae32a1SGerd Hoffmann         i = OHCI_BM(iso_td.flags, TD_DI);
759f1ae32a1SGerd Hoffmann         if (i < ohci->done_count)
760f1ae32a1SGerd Hoffmann             ohci->done_count = i;
761cf66ee8eSAlexey Kardashevskiy         if (ohci_put_iso_td(ohci, addr, &iso_td)) {
762cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
763cf66ee8eSAlexey Kardashevskiy             return 1;
764cf66ee8eSAlexey Kardashevskiy         }
765f1ae32a1SGerd Hoffmann         return 0;
766f1ae32a1SGerd Hoffmann     }
767f1ae32a1SGerd Hoffmann 
768f1ae32a1SGerd Hoffmann     dir = OHCI_BM(ed->flags, ED_D);
769f1ae32a1SGerd Hoffmann     switch (dir) {
770f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_IN:
771f1ae32a1SGerd Hoffmann         str = "in";
772f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_IN;
773f1ae32a1SGerd Hoffmann         break;
774f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_OUT:
775f1ae32a1SGerd Hoffmann         str = "out";
776f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_OUT;
777f1ae32a1SGerd Hoffmann         break;
778f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_SETUP:
779f1ae32a1SGerd Hoffmann         str = "setup";
780f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_SETUP;
781f1ae32a1SGerd Hoffmann         break;
782f1ae32a1SGerd Hoffmann     default:
783dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_bad_direction(dir);
784f1ae32a1SGerd Hoffmann         return 1;
785f1ae32a1SGerd Hoffmann     }
786f1ae32a1SGerd Hoffmann 
787f1ae32a1SGerd Hoffmann     if (!iso_td.bp || !iso_td.be) {
788dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_bad_bp_be(iso_td.bp, iso_td.be);
789f1ae32a1SGerd Hoffmann         return 1;
790f1ae32a1SGerd Hoffmann     }
791f1ae32a1SGerd Hoffmann 
792f1ae32a1SGerd Hoffmann     start_offset = iso_td.offset[relative_frame_number];
793f1ae32a1SGerd Hoffmann     next_offset = iso_td.offset[relative_frame_number + 1];
794f1ae32a1SGerd Hoffmann 
795f1ae32a1SGerd Hoffmann     if (!(OHCI_BM(start_offset, TD_PSW_CC) & 0xe) ||
796f1ae32a1SGerd Hoffmann         ((relative_frame_number < frame_count) &&
797f1ae32a1SGerd Hoffmann          !(OHCI_BM(next_offset, TD_PSW_CC) & 0xe))) {
798dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_bad_cc_not_accessed(start_offset, next_offset);
799f1ae32a1SGerd Hoffmann         return 1;
800f1ae32a1SGerd Hoffmann     }
801f1ae32a1SGerd Hoffmann 
802f1ae32a1SGerd Hoffmann     if ((relative_frame_number < frame_count) && (start_offset > next_offset)) {
803dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_bad_cc_overrun(start_offset, next_offset);
804f1ae32a1SGerd Hoffmann         return 1;
805f1ae32a1SGerd Hoffmann     }
806f1ae32a1SGerd Hoffmann 
807f1ae32a1SGerd Hoffmann     if ((start_offset & 0x1000) == 0) {
808f1ae32a1SGerd Hoffmann         start_addr = (iso_td.bp & OHCI_PAGE_MASK) |
809f1ae32a1SGerd Hoffmann             (start_offset & OHCI_OFFSET_MASK);
810f1ae32a1SGerd Hoffmann     } else {
811f1ae32a1SGerd Hoffmann         start_addr = (iso_td.be & OHCI_PAGE_MASK) |
812f1ae32a1SGerd Hoffmann             (start_offset & OHCI_OFFSET_MASK);
813f1ae32a1SGerd Hoffmann     }
814f1ae32a1SGerd Hoffmann 
815f1ae32a1SGerd Hoffmann     if (relative_frame_number < frame_count) {
816f1ae32a1SGerd Hoffmann         end_offset = next_offset - 1;
817f1ae32a1SGerd Hoffmann         if ((end_offset & 0x1000) == 0) {
818f1ae32a1SGerd Hoffmann             end_addr = (iso_td.bp & OHCI_PAGE_MASK) |
819f1ae32a1SGerd Hoffmann                 (end_offset & OHCI_OFFSET_MASK);
820f1ae32a1SGerd Hoffmann         } else {
821f1ae32a1SGerd Hoffmann             end_addr = (iso_td.be & OHCI_PAGE_MASK) |
822f1ae32a1SGerd Hoffmann                 (end_offset & OHCI_OFFSET_MASK);
823f1ae32a1SGerd Hoffmann         }
824f1ae32a1SGerd Hoffmann     } else {
825f1ae32a1SGerd Hoffmann         /* Last packet in the ISO TD */
826f1ae32a1SGerd Hoffmann         end_addr = iso_td.be;
827f1ae32a1SGerd Hoffmann     }
828f1ae32a1SGerd Hoffmann 
829f1ae32a1SGerd Hoffmann     if ((start_addr & OHCI_PAGE_MASK) != (end_addr & OHCI_PAGE_MASK)) {
830f1ae32a1SGerd Hoffmann         len = (end_addr & OHCI_OFFSET_MASK) + 0x1001
831f1ae32a1SGerd Hoffmann             - (start_addr & OHCI_OFFSET_MASK);
832f1ae32a1SGerd Hoffmann     } else {
833f1ae32a1SGerd Hoffmann         len = end_addr - start_addr + 1;
834f1ae32a1SGerd Hoffmann     }
835f1ae32a1SGerd Hoffmann 
836f1ae32a1SGerd Hoffmann     if (len && dir != OHCI_TD_DIR_IN) {
837cf66ee8eSAlexey Kardashevskiy         if (ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, len,
838cf66ee8eSAlexey Kardashevskiy                              DMA_DIRECTION_TO_DEVICE)) {
839cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
840cf66ee8eSAlexey Kardashevskiy             return 1;
841cf66ee8eSAlexey Kardashevskiy         }
842f1ae32a1SGerd Hoffmann     }
843f1ae32a1SGerd Hoffmann 
8449a77a0f5SHans de Goede     if (!completion) {
845a6fb2ddbSHans de Goede         bool int_req = relative_frame_number == frame_count &&
846a6fb2ddbSHans de Goede                        OHCI_BM(iso_td.flags, TD_DI) == 0;
847f1ae32a1SGerd Hoffmann         dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
848f1ae32a1SGerd Hoffmann         ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
8498550a02dSGerd Hoffmann         usb_packet_setup(&ohci->usb_packet, pid, ep, 0, addr, false, int_req);
850f1ae32a1SGerd Hoffmann         usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len);
8519a77a0f5SHans de Goede         usb_handle_packet(dev, &ohci->usb_packet);
8529a77a0f5SHans de Goede         if (ohci->usb_packet.status == USB_RET_ASYNC) {
85336dfe324SHans de Goede             usb_device_flush_ep_queue(dev, ep);
854f1ae32a1SGerd Hoffmann             return 1;
855f1ae32a1SGerd Hoffmann         }
856f1ae32a1SGerd Hoffmann     }
8579a77a0f5SHans de Goede     if (ohci->usb_packet.status == USB_RET_SUCCESS) {
8589a77a0f5SHans de Goede         ret = ohci->usb_packet.actual_length;
8599a77a0f5SHans de Goede     } else {
8609a77a0f5SHans de Goede         ret = ohci->usb_packet.status;
8619a77a0f5SHans de Goede     }
862f1ae32a1SGerd Hoffmann 
863dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_iso_td_so(start_offset, end_offset, start_addr, end_addr,
864dc1f5988SAlexey Kardashevskiy                              str, len, ret);
865f1ae32a1SGerd Hoffmann 
866f1ae32a1SGerd Hoffmann     /* Writeback */
867f1ae32a1SGerd Hoffmann     if (dir == OHCI_TD_DIR_IN && ret >= 0 && ret <= len) {
868f1ae32a1SGerd Hoffmann         /* IN transfer succeeded */
869cf66ee8eSAlexey Kardashevskiy         if (ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, ret,
870cf66ee8eSAlexey Kardashevskiy                              DMA_DIRECTION_FROM_DEVICE)) {
871cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
872cf66ee8eSAlexey Kardashevskiy             return 1;
873cf66ee8eSAlexey Kardashevskiy         }
874f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
875f1ae32a1SGerd Hoffmann                     OHCI_CC_NOERROR);
876f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, ret);
877f1ae32a1SGerd Hoffmann     } else if (dir == OHCI_TD_DIR_OUT && ret == len) {
878f1ae32a1SGerd Hoffmann         /* OUT transfer succeeded */
879f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
880f1ae32a1SGerd Hoffmann                     OHCI_CC_NOERROR);
881f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 0);
882f1ae32a1SGerd Hoffmann     } else {
883f1ae32a1SGerd Hoffmann         if (ret > (ssize_t) len) {
884dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_iso_td_data_overrun(ret, len);
885f1ae32a1SGerd Hoffmann             OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
886f1ae32a1SGerd Hoffmann                         OHCI_CC_DATAOVERRUN);
887f1ae32a1SGerd Hoffmann             OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
888f1ae32a1SGerd Hoffmann                         len);
889f1ae32a1SGerd Hoffmann         } else if (ret >= 0) {
890dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_iso_td_data_underrun(ret);
891f1ae32a1SGerd Hoffmann             OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
892f1ae32a1SGerd Hoffmann                         OHCI_CC_DATAUNDERRUN);
893f1ae32a1SGerd Hoffmann         } else {
894f1ae32a1SGerd Hoffmann             switch (ret) {
895f1ae32a1SGerd Hoffmann             case USB_RET_IOERROR:
896f1ae32a1SGerd Hoffmann             case USB_RET_NODEV:
897f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
898f1ae32a1SGerd Hoffmann                             OHCI_CC_DEVICENOTRESPONDING);
899f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
900f1ae32a1SGerd Hoffmann                             0);
901f1ae32a1SGerd Hoffmann                 break;
902f1ae32a1SGerd Hoffmann             case USB_RET_NAK:
903f1ae32a1SGerd Hoffmann             case USB_RET_STALL:
904dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_iso_td_nak(ret);
905f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
906f1ae32a1SGerd Hoffmann                             OHCI_CC_STALL);
907f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
908f1ae32a1SGerd Hoffmann                             0);
909f1ae32a1SGerd Hoffmann                 break;
910f1ae32a1SGerd Hoffmann             default:
911dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_iso_td_bad_response(ret);
912f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
913f1ae32a1SGerd Hoffmann                             OHCI_CC_UNDEXPETEDPID);
914f1ae32a1SGerd Hoffmann                 break;
915f1ae32a1SGerd Hoffmann             }
916f1ae32a1SGerd Hoffmann         }
917f1ae32a1SGerd Hoffmann     }
918f1ae32a1SGerd Hoffmann 
919f1ae32a1SGerd Hoffmann     if (relative_frame_number == frame_count) {
920f1ae32a1SGerd Hoffmann         /* Last data packet of ISO TD - retire the TD to the Done Queue */
921f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_NOERROR);
922f1ae32a1SGerd Hoffmann         ed->head &= ~OHCI_DPTR_MASK;
923f1ae32a1SGerd Hoffmann         ed->head |= (iso_td.next & OHCI_DPTR_MASK);
924f1ae32a1SGerd Hoffmann         iso_td.next = ohci->done;
925f1ae32a1SGerd Hoffmann         ohci->done = addr;
926f1ae32a1SGerd Hoffmann         i = OHCI_BM(iso_td.flags, TD_DI);
927f1ae32a1SGerd Hoffmann         if (i < ohci->done_count)
928f1ae32a1SGerd Hoffmann             ohci->done_count = i;
929f1ae32a1SGerd Hoffmann     }
930cf66ee8eSAlexey Kardashevskiy     if (ohci_put_iso_td(ohci, addr, &iso_td)) {
931cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
932cf66ee8eSAlexey Kardashevskiy     }
933f1ae32a1SGerd Hoffmann     return 1;
934f1ae32a1SGerd Hoffmann }
935f1ae32a1SGerd Hoffmann 
936dc1f5988SAlexey Kardashevskiy #ifdef trace_event_get_state
937dc1f5988SAlexey Kardashevskiy static void ohci_td_pkt(const char *msg, const uint8_t *buf, size_t len)
938dc1f5988SAlexey Kardashevskiy {
939dc1f5988SAlexey Kardashevskiy     bool print16 = !!trace_event_get_state(TRACE_USB_OHCI_TD_PKT_SHORT);
940dc1f5988SAlexey Kardashevskiy     bool printall = !!trace_event_get_state(TRACE_USB_OHCI_TD_PKT_FULL);
941dc1f5988SAlexey Kardashevskiy     const int width = 16;
942dc1f5988SAlexey Kardashevskiy     int i;
943dc1f5988SAlexey Kardashevskiy     char tmp[3 * width + 1];
944dc1f5988SAlexey Kardashevskiy     char *p = tmp;
945dc1f5988SAlexey Kardashevskiy 
946dc1f5988SAlexey Kardashevskiy     if (!printall && !print16) {
947dc1f5988SAlexey Kardashevskiy         return;
948dc1f5988SAlexey Kardashevskiy     }
949dc1f5988SAlexey Kardashevskiy 
950dc1f5988SAlexey Kardashevskiy     for (i = 0; ; i++) {
951dc1f5988SAlexey Kardashevskiy         if (i && (!(i % width) || (i == len))) {
952dc1f5988SAlexey Kardashevskiy             if (!printall) {
953dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_pkt_short(msg, tmp);
954dc1f5988SAlexey Kardashevskiy                 break;
955dc1f5988SAlexey Kardashevskiy             }
956dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_td_pkt_full(msg, tmp);
957dc1f5988SAlexey Kardashevskiy             p = tmp;
958dc1f5988SAlexey Kardashevskiy             *p = 0;
959dc1f5988SAlexey Kardashevskiy         }
960dc1f5988SAlexey Kardashevskiy         if (i == len) {
961dc1f5988SAlexey Kardashevskiy             break;
962dc1f5988SAlexey Kardashevskiy         }
963dc1f5988SAlexey Kardashevskiy 
964dc1f5988SAlexey Kardashevskiy         p += sprintf(p, " %.2x", buf[i]);
965dc1f5988SAlexey Kardashevskiy     }
966dc1f5988SAlexey Kardashevskiy }
967dc1f5988SAlexey Kardashevskiy #else
968dc1f5988SAlexey Kardashevskiy static void ohci_td_pkt(const char *msg, const uint8_t *buf, size_t len)
969dc1f5988SAlexey Kardashevskiy {
970dc1f5988SAlexey Kardashevskiy }
971dc1f5988SAlexey Kardashevskiy #endif
972dc1f5988SAlexey Kardashevskiy 
973f1ae32a1SGerd Hoffmann /* Service a transport descriptor.
974f1ae32a1SGerd Hoffmann    Returns nonzero to terminate processing of this endpoint.  */
975f1ae32a1SGerd Hoffmann 
976f1ae32a1SGerd Hoffmann static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
977f1ae32a1SGerd Hoffmann {
978f1ae32a1SGerd Hoffmann     int dir;
979f1ae32a1SGerd Hoffmann     size_t len = 0, pktlen = 0;
980f1ae32a1SGerd Hoffmann     const char *str = NULL;
981f1ae32a1SGerd Hoffmann     int pid;
982f1ae32a1SGerd Hoffmann     int ret;
983f1ae32a1SGerd Hoffmann     int i;
984f1ae32a1SGerd Hoffmann     USBDevice *dev;
985f1ae32a1SGerd Hoffmann     USBEndpoint *ep;
986f1ae32a1SGerd Hoffmann     struct ohci_td td;
987f1ae32a1SGerd Hoffmann     uint32_t addr;
988f1ae32a1SGerd Hoffmann     int flag_r;
989f1ae32a1SGerd Hoffmann     int completion;
990f1ae32a1SGerd Hoffmann 
991f1ae32a1SGerd Hoffmann     addr = ed->head & OHCI_DPTR_MASK;
992f1ae32a1SGerd Hoffmann     /* See if this TD has already been submitted to the device.  */
993f1ae32a1SGerd Hoffmann     completion = (addr == ohci->async_td);
994f1ae32a1SGerd Hoffmann     if (completion && !ohci->async_complete) {
995dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_td_skip_async();
996f1ae32a1SGerd Hoffmann         return 1;
997f1ae32a1SGerd Hoffmann     }
998cf66ee8eSAlexey Kardashevskiy     if (ohci_read_td(ohci, addr, &td)) {
999dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_td_read_error(addr);
1000cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
1001f1ae32a1SGerd Hoffmann         return 0;
1002f1ae32a1SGerd Hoffmann     }
1003f1ae32a1SGerd Hoffmann 
1004f1ae32a1SGerd Hoffmann     dir = OHCI_BM(ed->flags, ED_D);
1005f1ae32a1SGerd Hoffmann     switch (dir) {
1006f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_OUT:
1007f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_IN:
1008f1ae32a1SGerd Hoffmann         /* Same value.  */
1009f1ae32a1SGerd Hoffmann         break;
1010f1ae32a1SGerd Hoffmann     default:
1011f1ae32a1SGerd Hoffmann         dir = OHCI_BM(td.flags, TD_DP);
1012f1ae32a1SGerd Hoffmann         break;
1013f1ae32a1SGerd Hoffmann     }
1014f1ae32a1SGerd Hoffmann 
1015f1ae32a1SGerd Hoffmann     switch (dir) {
1016f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_IN:
1017f1ae32a1SGerd Hoffmann         str = "in";
1018f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_IN;
1019f1ae32a1SGerd Hoffmann         break;
1020f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_OUT:
1021f1ae32a1SGerd Hoffmann         str = "out";
1022f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_OUT;
1023f1ae32a1SGerd Hoffmann         break;
1024f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_SETUP:
1025f1ae32a1SGerd Hoffmann         str = "setup";
1026f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_SETUP;
1027f1ae32a1SGerd Hoffmann         break;
1028f1ae32a1SGerd Hoffmann     default:
1029dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_td_bad_direction(dir);
1030f1ae32a1SGerd Hoffmann         return 1;
1031f1ae32a1SGerd Hoffmann     }
1032f1ae32a1SGerd Hoffmann     if (td.cbp && td.be) {
1033f1ae32a1SGerd Hoffmann         if ((td.cbp & 0xfffff000) != (td.be & 0xfffff000)) {
1034f1ae32a1SGerd Hoffmann             len = (td.be & 0xfff) + 0x1001 - (td.cbp & 0xfff);
1035f1ae32a1SGerd Hoffmann         } else {
1036f1ae32a1SGerd Hoffmann             len = (td.be - td.cbp) + 1;
1037f1ae32a1SGerd Hoffmann         }
1038f1ae32a1SGerd Hoffmann 
1039f1ae32a1SGerd Hoffmann         pktlen = len;
1040f1ae32a1SGerd Hoffmann         if (len && dir != OHCI_TD_DIR_IN) {
1041f1ae32a1SGerd Hoffmann             /* The endpoint may not allow us to transfer it all now */
1042f1ae32a1SGerd Hoffmann             pktlen = (ed->flags & OHCI_ED_MPS_MASK) >> OHCI_ED_MPS_SHIFT;
1043f1ae32a1SGerd Hoffmann             if (pktlen > len) {
1044f1ae32a1SGerd Hoffmann                 pktlen = len;
1045f1ae32a1SGerd Hoffmann             }
1046f1ae32a1SGerd Hoffmann             if (!completion) {
1047cf66ee8eSAlexey Kardashevskiy                 if (ohci_copy_td(ohci, &td, ohci->usb_buf, pktlen,
1048cf66ee8eSAlexey Kardashevskiy                                  DMA_DIRECTION_TO_DEVICE)) {
1049cf66ee8eSAlexey Kardashevskiy                     ohci_die(ohci);
1050cf66ee8eSAlexey Kardashevskiy                 }
1051f1ae32a1SGerd Hoffmann             }
1052f1ae32a1SGerd Hoffmann         }
1053f1ae32a1SGerd Hoffmann     }
1054f1ae32a1SGerd Hoffmann 
1055f1ae32a1SGerd Hoffmann     flag_r = (td.flags & OHCI_TD_R) != 0;
1056dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_td_pkt_hdr(addr, (int64_t)pktlen, (int64_t)len, str,
1057dc1f5988SAlexey Kardashevskiy                               flag_r, td.cbp, td.be);
1058dc1f5988SAlexey Kardashevskiy     ohci_td_pkt("OUT", ohci->usb_buf, pktlen);
1059f1ae32a1SGerd Hoffmann 
1060f1ae32a1SGerd Hoffmann     if (completion) {
1061f1ae32a1SGerd Hoffmann         ohci->async_td = 0;
106269e25d26SAlexey Kardashevskiy         ohci->async_complete = false;
1063f1ae32a1SGerd Hoffmann     } else {
1064f1ae32a1SGerd Hoffmann         if (ohci->async_td) {
1065f1ae32a1SGerd Hoffmann             /* ??? The hardware should allow one active packet per
1066f1ae32a1SGerd Hoffmann                endpoint.  We only allow one active packet per controller.
1067f1ae32a1SGerd Hoffmann                This should be sufficient as long as devices respond in a
1068f1ae32a1SGerd Hoffmann                timely manner.
1069f1ae32a1SGerd Hoffmann             */
1070dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_td_too_many_pending();
1071f1ae32a1SGerd Hoffmann             return 1;
1072f1ae32a1SGerd Hoffmann         }
1073f1ae32a1SGerd Hoffmann         dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
1074f1ae32a1SGerd Hoffmann         ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
10758550a02dSGerd Hoffmann         usb_packet_setup(&ohci->usb_packet, pid, ep, 0, addr, !flag_r,
1076a6fb2ddbSHans de Goede                          OHCI_BM(td.flags, TD_DI) == 0);
1077f1ae32a1SGerd Hoffmann         usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen);
10789a77a0f5SHans de Goede         usb_handle_packet(dev, &ohci->usb_packet);
1079dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_td_packet_status(ohci->usb_packet.status);
1080dc1f5988SAlexey Kardashevskiy 
10819a77a0f5SHans de Goede         if (ohci->usb_packet.status == USB_RET_ASYNC) {
108236dfe324SHans de Goede             usb_device_flush_ep_queue(dev, ep);
1083f1ae32a1SGerd Hoffmann             ohci->async_td = addr;
1084f1ae32a1SGerd Hoffmann             return 1;
1085f1ae32a1SGerd Hoffmann         }
1086f1ae32a1SGerd Hoffmann     }
10879a77a0f5SHans de Goede     if (ohci->usb_packet.status == USB_RET_SUCCESS) {
10889a77a0f5SHans de Goede         ret = ohci->usb_packet.actual_length;
10899a77a0f5SHans de Goede     } else {
10909a77a0f5SHans de Goede         ret = ohci->usb_packet.status;
10919a77a0f5SHans de Goede     }
10929a77a0f5SHans de Goede 
1093f1ae32a1SGerd Hoffmann     if (ret >= 0) {
1094f1ae32a1SGerd Hoffmann         if (dir == OHCI_TD_DIR_IN) {
1095cf66ee8eSAlexey Kardashevskiy             if (ohci_copy_td(ohci, &td, ohci->usb_buf, ret,
1096cf66ee8eSAlexey Kardashevskiy                              DMA_DIRECTION_FROM_DEVICE)) {
1097cf66ee8eSAlexey Kardashevskiy                 ohci_die(ohci);
1098cf66ee8eSAlexey Kardashevskiy             }
1099dc1f5988SAlexey Kardashevskiy             ohci_td_pkt("IN", ohci->usb_buf, pktlen);
1100f1ae32a1SGerd Hoffmann         } else {
1101f1ae32a1SGerd Hoffmann             ret = pktlen;
1102f1ae32a1SGerd Hoffmann         }
1103f1ae32a1SGerd Hoffmann     }
1104f1ae32a1SGerd Hoffmann 
1105f1ae32a1SGerd Hoffmann     /* Writeback */
1106f1ae32a1SGerd Hoffmann     if (ret == pktlen || (dir == OHCI_TD_DIR_IN && ret >= 0 && flag_r)) {
1107f1ae32a1SGerd Hoffmann         /* Transmission succeeded.  */
1108f1ae32a1SGerd Hoffmann         if (ret == len) {
1109f1ae32a1SGerd Hoffmann             td.cbp = 0;
1110f1ae32a1SGerd Hoffmann         } else {
1111f1ae32a1SGerd Hoffmann             if ((td.cbp & 0xfff) + ret > 0xfff) {
1112f1ae32a1SGerd Hoffmann                 td.cbp = (td.be & ~0xfff) + ((td.cbp + ret) & 0xfff);
1113f1ae32a1SGerd Hoffmann             } else {
1114f1ae32a1SGerd Hoffmann                 td.cbp += ret;
1115f1ae32a1SGerd Hoffmann             }
1116f1ae32a1SGerd Hoffmann         }
1117f1ae32a1SGerd Hoffmann         td.flags |= OHCI_TD_T1;
1118f1ae32a1SGerd Hoffmann         td.flags ^= OHCI_TD_T0;
1119f1ae32a1SGerd Hoffmann         OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_NOERROR);
1120f1ae32a1SGerd Hoffmann         OHCI_SET_BM(td.flags, TD_EC, 0);
1121f1ae32a1SGerd Hoffmann 
1122f1ae32a1SGerd Hoffmann         if ((dir != OHCI_TD_DIR_IN) && (ret != len)) {
1123f1ae32a1SGerd Hoffmann             /* Partial packet transfer: TD not ready to retire yet */
1124f1ae32a1SGerd Hoffmann             goto exit_no_retire;
1125f1ae32a1SGerd Hoffmann         }
1126f1ae32a1SGerd Hoffmann 
1127f1ae32a1SGerd Hoffmann         /* Setting ED_C is part of the TD retirement process */
1128f1ae32a1SGerd Hoffmann         ed->head &= ~OHCI_ED_C;
1129f1ae32a1SGerd Hoffmann         if (td.flags & OHCI_TD_T0)
1130f1ae32a1SGerd Hoffmann             ed->head |= OHCI_ED_C;
1131f1ae32a1SGerd Hoffmann     } else {
1132f1ae32a1SGerd Hoffmann         if (ret >= 0) {
1133dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_td_underrun();
1134f1ae32a1SGerd Hoffmann             OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAUNDERRUN);
1135f1ae32a1SGerd Hoffmann         } else {
1136f1ae32a1SGerd Hoffmann             switch (ret) {
1137f1ae32a1SGerd Hoffmann             case USB_RET_IOERROR:
1138f1ae32a1SGerd Hoffmann             case USB_RET_NODEV:
1139dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_dev_error();
1140f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DEVICENOTRESPONDING);
11414b351a0fSJán Veselý                 break;
1142f1ae32a1SGerd Hoffmann             case USB_RET_NAK:
1143dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_nak();
1144f1ae32a1SGerd Hoffmann                 return 1;
1145f1ae32a1SGerd Hoffmann             case USB_RET_STALL:
1146dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_stall();
1147f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_STALL);
1148f1ae32a1SGerd Hoffmann                 break;
1149f1ae32a1SGerd Hoffmann             case USB_RET_BABBLE:
1150dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_babble();
1151f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAOVERRUN);
1152f1ae32a1SGerd Hoffmann                 break;
1153f1ae32a1SGerd Hoffmann             default:
1154dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_bad_device_response(ret);
1155f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_UNDEXPETEDPID);
1156f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_EC, 3);
1157f1ae32a1SGerd Hoffmann                 break;
1158f1ae32a1SGerd Hoffmann             }
1159f1ae32a1SGerd Hoffmann         }
1160f1ae32a1SGerd Hoffmann         ed->head |= OHCI_ED_H;
1161f1ae32a1SGerd Hoffmann     }
1162f1ae32a1SGerd Hoffmann 
1163f1ae32a1SGerd Hoffmann     /* Retire this TD */
1164f1ae32a1SGerd Hoffmann     ed->head &= ~OHCI_DPTR_MASK;
1165f1ae32a1SGerd Hoffmann     ed->head |= td.next & OHCI_DPTR_MASK;
1166f1ae32a1SGerd Hoffmann     td.next = ohci->done;
1167f1ae32a1SGerd Hoffmann     ohci->done = addr;
1168f1ae32a1SGerd Hoffmann     i = OHCI_BM(td.flags, TD_DI);
1169f1ae32a1SGerd Hoffmann     if (i < ohci->done_count)
1170f1ae32a1SGerd Hoffmann         ohci->done_count = i;
1171f1ae32a1SGerd Hoffmann exit_no_retire:
1172cf66ee8eSAlexey Kardashevskiy     if (ohci_put_td(ohci, addr, &td)) {
1173cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
1174cf66ee8eSAlexey Kardashevskiy         return 1;
1175cf66ee8eSAlexey Kardashevskiy     }
1176f1ae32a1SGerd Hoffmann     return OHCI_BM(td.flags, TD_CC) != OHCI_CC_NOERROR;
1177f1ae32a1SGerd Hoffmann }
1178f1ae32a1SGerd Hoffmann 
1179f1ae32a1SGerd Hoffmann /* Service an endpoint list.  Returns nonzero if active TD were found.  */
1180f1ae32a1SGerd Hoffmann static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion)
1181f1ae32a1SGerd Hoffmann {
1182f1ae32a1SGerd Hoffmann     struct ohci_ed ed;
1183f1ae32a1SGerd Hoffmann     uint32_t next_ed;
1184f1ae32a1SGerd Hoffmann     uint32_t cur;
1185f1ae32a1SGerd Hoffmann     int active;
1186f1ae32a1SGerd Hoffmann 
1187f1ae32a1SGerd Hoffmann     active = 0;
1188f1ae32a1SGerd Hoffmann 
1189f1ae32a1SGerd Hoffmann     if (head == 0)
1190f1ae32a1SGerd Hoffmann         return 0;
1191f1ae32a1SGerd Hoffmann 
1192f1ae32a1SGerd Hoffmann     for (cur = head; cur; cur = next_ed) {
1193cf66ee8eSAlexey Kardashevskiy         if (ohci_read_ed(ohci, cur, &ed)) {
1194dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_ed_read_error(cur);
1195cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
1196f1ae32a1SGerd Hoffmann             return 0;
1197f1ae32a1SGerd Hoffmann         }
1198f1ae32a1SGerd Hoffmann 
1199f1ae32a1SGerd Hoffmann         next_ed = ed.next & OHCI_DPTR_MASK;
1200f1ae32a1SGerd Hoffmann 
1201f1ae32a1SGerd Hoffmann         if ((ed.head & OHCI_ED_H) || (ed.flags & OHCI_ED_K)) {
1202f1ae32a1SGerd Hoffmann             uint32_t addr;
1203f1ae32a1SGerd Hoffmann             /* Cancel pending packets for ED that have been paused.  */
1204f1ae32a1SGerd Hoffmann             addr = ed.head & OHCI_DPTR_MASK;
1205f1ae32a1SGerd Hoffmann             if (ohci->async_td && addr == ohci->async_td) {
1206f1ae32a1SGerd Hoffmann                 usb_cancel_packet(&ohci->usb_packet);
1207f1ae32a1SGerd Hoffmann                 ohci->async_td = 0;
1208f79738b0SHans de Goede                 usb_device_ep_stopped(ohci->usb_packet.ep->dev,
1209f79738b0SHans de Goede                                       ohci->usb_packet.ep);
1210f1ae32a1SGerd Hoffmann             }
1211f1ae32a1SGerd Hoffmann             continue;
1212f1ae32a1SGerd Hoffmann         }
1213f1ae32a1SGerd Hoffmann 
1214f1ae32a1SGerd Hoffmann         while ((ed.head & OHCI_DPTR_MASK) != ed.tail) {
12153af8f177SAlexey Kardashevskiy             trace_usb_ohci_ed_pkt(cur, (ed.head & OHCI_ED_H) != 0,
12163af8f177SAlexey Kardashevskiy                     (ed.head & OHCI_ED_C) != 0, ed.head & OHCI_DPTR_MASK,
12173af8f177SAlexey Kardashevskiy                     ed.tail & OHCI_DPTR_MASK, ed.next & OHCI_DPTR_MASK);
12183af8f177SAlexey Kardashevskiy             trace_usb_ohci_ed_pkt_flags(
1219f1ae32a1SGerd Hoffmann                     OHCI_BM(ed.flags, ED_FA), OHCI_BM(ed.flags, ED_EN),
1220f1ae32a1SGerd Hoffmann                     OHCI_BM(ed.flags, ED_D), (ed.flags & OHCI_ED_S)!= 0,
1221f1ae32a1SGerd Hoffmann                     (ed.flags & OHCI_ED_K) != 0, (ed.flags & OHCI_ED_F) != 0,
12223af8f177SAlexey Kardashevskiy                     OHCI_BM(ed.flags, ED_MPS));
1223dc1f5988SAlexey Kardashevskiy 
1224f1ae32a1SGerd Hoffmann             active = 1;
1225f1ae32a1SGerd Hoffmann 
1226f1ae32a1SGerd Hoffmann             if ((ed.flags & OHCI_ED_F) == 0) {
1227f1ae32a1SGerd Hoffmann                 if (ohci_service_td(ohci, &ed))
1228f1ae32a1SGerd Hoffmann                     break;
1229f1ae32a1SGerd Hoffmann             } else {
1230f1ae32a1SGerd Hoffmann                 /* Handle isochronous endpoints */
1231f1ae32a1SGerd Hoffmann                 if (ohci_service_iso_td(ohci, &ed, completion))
1232f1ae32a1SGerd Hoffmann                     break;
1233f1ae32a1SGerd Hoffmann             }
1234f1ae32a1SGerd Hoffmann         }
1235f1ae32a1SGerd Hoffmann 
1236cf66ee8eSAlexey Kardashevskiy         if (ohci_put_ed(ohci, cur, &ed)) {
1237cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
1238cf66ee8eSAlexey Kardashevskiy             return 0;
1239cf66ee8eSAlexey Kardashevskiy         }
1240f1ae32a1SGerd Hoffmann     }
1241f1ae32a1SGerd Hoffmann 
1242f1ae32a1SGerd Hoffmann     return active;
1243f1ae32a1SGerd Hoffmann }
1244f1ae32a1SGerd Hoffmann 
1245fd0a10cdSLaurent Vivier /* set a timer for EOF */
1246fd0a10cdSLaurent Vivier static void ohci_eof_timer(OHCIState *ohci)
1247f1ae32a1SGerd Hoffmann {
1248bc72ad67SAlex Bligh     ohci->sof_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
1249bc72ad67SAlex Bligh     timer_mod(ohci->eof_timer, ohci->sof_time + usb_frame_time);
1250fd0a10cdSLaurent Vivier }
1251fd0a10cdSLaurent Vivier /* Set a timer for EOF and generate a SOF event */
1252fd0a10cdSLaurent Vivier static void ohci_sof(OHCIState *ohci)
1253fd0a10cdSLaurent Vivier {
1254fd0a10cdSLaurent Vivier     ohci_eof_timer(ohci);
1255f1ae32a1SGerd Hoffmann     ohci_set_interrupt(ohci, OHCI_INTR_SF);
1256f1ae32a1SGerd Hoffmann }
1257f1ae32a1SGerd Hoffmann 
1258f1ae32a1SGerd Hoffmann /* Process Control and Bulk lists.  */
1259f1ae32a1SGerd Hoffmann static void ohci_process_lists(OHCIState *ohci, int completion)
1260f1ae32a1SGerd Hoffmann {
1261f1ae32a1SGerd Hoffmann     if ((ohci->ctl & OHCI_CTL_CLE) && (ohci->status & OHCI_STATUS_CLF)) {
1262f1ae32a1SGerd Hoffmann         if (ohci->ctrl_cur && ohci->ctrl_cur != ohci->ctrl_head) {
1263dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_process_lists(ohci->ctrl_head, ohci->ctrl_cur);
1264f1ae32a1SGerd Hoffmann         }
1265f1ae32a1SGerd Hoffmann         if (!ohci_service_ed_list(ohci, ohci->ctrl_head, completion)) {
1266f1ae32a1SGerd Hoffmann             ohci->ctrl_cur = 0;
1267f1ae32a1SGerd Hoffmann             ohci->status &= ~OHCI_STATUS_CLF;
1268f1ae32a1SGerd Hoffmann         }
1269f1ae32a1SGerd Hoffmann     }
1270f1ae32a1SGerd Hoffmann 
1271f1ae32a1SGerd Hoffmann     if ((ohci->ctl & OHCI_CTL_BLE) && (ohci->status & OHCI_STATUS_BLF)) {
1272f1ae32a1SGerd Hoffmann         if (!ohci_service_ed_list(ohci, ohci->bulk_head, completion)) {
1273f1ae32a1SGerd Hoffmann             ohci->bulk_cur = 0;
1274f1ae32a1SGerd Hoffmann             ohci->status &= ~OHCI_STATUS_BLF;
1275f1ae32a1SGerd Hoffmann         }
1276f1ae32a1SGerd Hoffmann     }
1277f1ae32a1SGerd Hoffmann }
1278f1ae32a1SGerd Hoffmann 
1279f1ae32a1SGerd Hoffmann /* Do frame processing on frame boundary */
1280f1ae32a1SGerd Hoffmann static void ohci_frame_boundary(void *opaque)
1281f1ae32a1SGerd Hoffmann {
1282f1ae32a1SGerd Hoffmann     OHCIState *ohci = opaque;
1283f1ae32a1SGerd Hoffmann     struct ohci_hcca hcca;
1284f1ae32a1SGerd Hoffmann 
1285cf66ee8eSAlexey Kardashevskiy     if (ohci_read_hcca(ohci, ohci->hcca, &hcca)) {
1286dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_hcca_read_error(ohci->hcca);
1287cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
1288cf66ee8eSAlexey Kardashevskiy         return;
1289cf66ee8eSAlexey Kardashevskiy     }
1290f1ae32a1SGerd Hoffmann 
1291f1ae32a1SGerd Hoffmann     /* Process all the lists at the end of the frame */
1292f1ae32a1SGerd Hoffmann     if (ohci->ctl & OHCI_CTL_PLE) {
1293f1ae32a1SGerd Hoffmann         int n;
1294f1ae32a1SGerd Hoffmann 
1295f1ae32a1SGerd Hoffmann         n = ohci->frame_number & 0x1f;
1296f1ae32a1SGerd Hoffmann         ohci_service_ed_list(ohci, le32_to_cpu(hcca.intr[n]), 0);
1297f1ae32a1SGerd Hoffmann     }
1298f1ae32a1SGerd Hoffmann 
1299f1ae32a1SGerd Hoffmann     /* Cancel all pending packets if either of the lists has been disabled.  */
1300f79738b0SHans de Goede     if (ohci->old_ctl & (~ohci->ctl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) {
1301f79738b0SHans de Goede         if (ohci->async_td) {
1302f1ae32a1SGerd Hoffmann             usb_cancel_packet(&ohci->usb_packet);
1303f1ae32a1SGerd Hoffmann             ohci->async_td = 0;
1304f1ae32a1SGerd Hoffmann         }
1305f79738b0SHans de Goede         ohci_stop_endpoints(ohci);
1306f79738b0SHans de Goede     }
1307f1ae32a1SGerd Hoffmann     ohci->old_ctl = ohci->ctl;
1308f1ae32a1SGerd Hoffmann     ohci_process_lists(ohci, 0);
1309f1ae32a1SGerd Hoffmann 
1310cf66ee8eSAlexey Kardashevskiy     /* Stop if UnrecoverableError happened or ohci_sof will crash */
1311cf66ee8eSAlexey Kardashevskiy     if (ohci->intr_status & OHCI_INTR_UE) {
1312cf66ee8eSAlexey Kardashevskiy         return;
1313cf66ee8eSAlexey Kardashevskiy     }
1314cf66ee8eSAlexey Kardashevskiy 
1315f1ae32a1SGerd Hoffmann     /* Frame boundary, so do EOF stuf here */
1316f1ae32a1SGerd Hoffmann     ohci->frt = ohci->fit;
1317f1ae32a1SGerd Hoffmann 
1318f1ae32a1SGerd Hoffmann     /* Increment frame number and take care of endianness. */
1319f1ae32a1SGerd Hoffmann     ohci->frame_number = (ohci->frame_number + 1) & 0xffff;
1320f1ae32a1SGerd Hoffmann     hcca.frame = cpu_to_le16(ohci->frame_number);
1321f1ae32a1SGerd Hoffmann 
1322f1ae32a1SGerd Hoffmann     if (ohci->done_count == 0 && !(ohci->intr_status & OHCI_INTR_WD)) {
1323f1ae32a1SGerd Hoffmann         if (!ohci->done)
1324f1ae32a1SGerd Hoffmann             abort();
1325f1ae32a1SGerd Hoffmann         if (ohci->intr & ohci->intr_status)
1326f1ae32a1SGerd Hoffmann             ohci->done |= 1;
1327f1ae32a1SGerd Hoffmann         hcca.done = cpu_to_le32(ohci->done);
1328f1ae32a1SGerd Hoffmann         ohci->done = 0;
1329f1ae32a1SGerd Hoffmann         ohci->done_count = 7;
1330f1ae32a1SGerd Hoffmann         ohci_set_interrupt(ohci, OHCI_INTR_WD);
1331f1ae32a1SGerd Hoffmann     }
1332f1ae32a1SGerd Hoffmann 
1333f1ae32a1SGerd Hoffmann     if (ohci->done_count != 7 && ohci->done_count != 0)
1334f1ae32a1SGerd Hoffmann         ohci->done_count--;
1335f1ae32a1SGerd Hoffmann 
1336f1ae32a1SGerd Hoffmann     /* Do SOF stuff here */
1337f1ae32a1SGerd Hoffmann     ohci_sof(ohci);
1338f1ae32a1SGerd Hoffmann 
1339f1ae32a1SGerd Hoffmann     /* Writeback HCCA */
1340cf66ee8eSAlexey Kardashevskiy     if (ohci_put_hcca(ohci, ohci->hcca, &hcca)) {
1341cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
1342cf66ee8eSAlexey Kardashevskiy     }
1343f1ae32a1SGerd Hoffmann }
1344f1ae32a1SGerd Hoffmann 
1345f1ae32a1SGerd Hoffmann /* Start sending SOF tokens across the USB bus, lists are processed in
1346f1ae32a1SGerd Hoffmann  * next frame
1347f1ae32a1SGerd Hoffmann  */
1348f1ae32a1SGerd Hoffmann static int ohci_bus_start(OHCIState *ohci)
1349f1ae32a1SGerd Hoffmann {
1350dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_start(ohci->name);
1351f1ae32a1SGerd Hoffmann 
1352fd0a10cdSLaurent Vivier     /* Delay the first SOF event by one frame time as
1353fd0a10cdSLaurent Vivier      * linux driver is not ready to receive it and
1354fd0a10cdSLaurent Vivier      * can meet some race conditions
1355fd0a10cdSLaurent Vivier      */
1356fd0a10cdSLaurent Vivier 
1357fd0a10cdSLaurent Vivier     ohci_eof_timer(ohci);
1358f1ae32a1SGerd Hoffmann 
1359f1ae32a1SGerd Hoffmann     return 1;
1360f1ae32a1SGerd Hoffmann }
1361f1ae32a1SGerd Hoffmann 
1362f1ae32a1SGerd Hoffmann /* Stop sending SOF tokens on the bus */
1363f1ae32a1SGerd Hoffmann static void ohci_bus_stop(OHCIState *ohci)
1364f1ae32a1SGerd Hoffmann {
1365dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_stop(ohci->name);
1366bc72ad67SAlex Bligh     timer_del(ohci->eof_timer);
1367f1ae32a1SGerd Hoffmann }
1368f1ae32a1SGerd Hoffmann 
1369f1ae32a1SGerd Hoffmann /* Sets a flag in a port status register but only set it if the port is
1370f1ae32a1SGerd Hoffmann  * connected, if not set ConnectStatusChange flag. If flag is enabled
1371f1ae32a1SGerd Hoffmann  * return 1.
1372f1ae32a1SGerd Hoffmann  */
1373f1ae32a1SGerd Hoffmann static int ohci_port_set_if_connected(OHCIState *ohci, int i, uint32_t val)
1374f1ae32a1SGerd Hoffmann {
1375f1ae32a1SGerd Hoffmann     int ret = 1;
1376f1ae32a1SGerd Hoffmann 
1377f1ae32a1SGerd Hoffmann     /* writing a 0 has no effect */
1378f1ae32a1SGerd Hoffmann     if (val == 0)
1379f1ae32a1SGerd Hoffmann         return 0;
1380f1ae32a1SGerd Hoffmann 
1381f1ae32a1SGerd Hoffmann     /* If CurrentConnectStatus is cleared we set
1382f1ae32a1SGerd Hoffmann      * ConnectStatusChange
1383f1ae32a1SGerd Hoffmann      */
1384f1ae32a1SGerd Hoffmann     if (!(ohci->rhport[i].ctrl & OHCI_PORT_CCS)) {
1385f1ae32a1SGerd Hoffmann         ohci->rhport[i].ctrl |= OHCI_PORT_CSC;
1386f1ae32a1SGerd Hoffmann         if (ohci->rhstatus & OHCI_RHS_DRWE) {
1387f1ae32a1SGerd Hoffmann             /* TODO: CSC is a wakeup event */
1388f1ae32a1SGerd Hoffmann         }
1389f1ae32a1SGerd Hoffmann         return 0;
1390f1ae32a1SGerd Hoffmann     }
1391f1ae32a1SGerd Hoffmann 
1392f1ae32a1SGerd Hoffmann     if (ohci->rhport[i].ctrl & val)
1393f1ae32a1SGerd Hoffmann         ret = 0;
1394f1ae32a1SGerd Hoffmann 
1395f1ae32a1SGerd Hoffmann     /* set the bit */
1396f1ae32a1SGerd Hoffmann     ohci->rhport[i].ctrl |= val;
1397f1ae32a1SGerd Hoffmann 
1398f1ae32a1SGerd Hoffmann     return ret;
1399f1ae32a1SGerd Hoffmann }
1400f1ae32a1SGerd Hoffmann 
1401f1ae32a1SGerd Hoffmann /* Set the frame interval - frame interval toggle is manipulated by the hcd only */
1402f1ae32a1SGerd Hoffmann static void ohci_set_frame_interval(OHCIState *ohci, uint16_t val)
1403f1ae32a1SGerd Hoffmann {
1404f1ae32a1SGerd Hoffmann     val &= OHCI_FMI_FI;
1405f1ae32a1SGerd Hoffmann 
1406f1ae32a1SGerd Hoffmann     if (val != ohci->fi) {
1407dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_set_frame_interval(ohci->name, ohci->fi, ohci->fi);
1408f1ae32a1SGerd Hoffmann     }
1409f1ae32a1SGerd Hoffmann 
1410f1ae32a1SGerd Hoffmann     ohci->fi = val;
1411f1ae32a1SGerd Hoffmann }
1412f1ae32a1SGerd Hoffmann 
1413f1ae32a1SGerd Hoffmann static void ohci_port_power(OHCIState *ohci, int i, int p)
1414f1ae32a1SGerd Hoffmann {
1415f1ae32a1SGerd Hoffmann     if (p) {
1416f1ae32a1SGerd Hoffmann         ohci->rhport[i].ctrl |= OHCI_PORT_PPS;
1417f1ae32a1SGerd Hoffmann     } else {
1418f1ae32a1SGerd Hoffmann         ohci->rhport[i].ctrl &= ~(OHCI_PORT_PPS|
1419f1ae32a1SGerd Hoffmann                     OHCI_PORT_CCS|
1420f1ae32a1SGerd Hoffmann                     OHCI_PORT_PSS|
1421f1ae32a1SGerd Hoffmann                     OHCI_PORT_PRS);
1422f1ae32a1SGerd Hoffmann     }
1423f1ae32a1SGerd Hoffmann }
1424f1ae32a1SGerd Hoffmann 
1425f1ae32a1SGerd Hoffmann /* Set HcControlRegister */
1426f1ae32a1SGerd Hoffmann static void ohci_set_ctl(OHCIState *ohci, uint32_t val)
1427f1ae32a1SGerd Hoffmann {
1428f1ae32a1SGerd Hoffmann     uint32_t old_state;
1429f1ae32a1SGerd Hoffmann     uint32_t new_state;
1430f1ae32a1SGerd Hoffmann 
1431f1ae32a1SGerd Hoffmann     old_state = ohci->ctl & OHCI_CTL_HCFS;
1432f1ae32a1SGerd Hoffmann     ohci->ctl = val;
1433f1ae32a1SGerd Hoffmann     new_state = ohci->ctl & OHCI_CTL_HCFS;
1434f1ae32a1SGerd Hoffmann 
1435f1ae32a1SGerd Hoffmann     /* no state change */
1436f1ae32a1SGerd Hoffmann     if (old_state == new_state)
1437f1ae32a1SGerd Hoffmann         return;
1438f1ae32a1SGerd Hoffmann 
1439dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_set_ctl(ohci->name, new_state);
1440f1ae32a1SGerd Hoffmann     switch (new_state) {
1441f1ae32a1SGerd Hoffmann     case OHCI_USB_OPERATIONAL:
1442f1ae32a1SGerd Hoffmann         ohci_bus_start(ohci);
1443f1ae32a1SGerd Hoffmann         break;
1444f1ae32a1SGerd Hoffmann     case OHCI_USB_SUSPEND:
1445f1ae32a1SGerd Hoffmann         ohci_bus_stop(ohci);
1446087462c7SLaurent Vivier         /* clear pending SF otherwise linux driver loops in ohci_irq() */
1447087462c7SLaurent Vivier         ohci->intr_status &= ~OHCI_INTR_SF;
1448087462c7SLaurent Vivier         ohci_intr_update(ohci);
1449f1ae32a1SGerd Hoffmann         break;
1450f1ae32a1SGerd Hoffmann     case OHCI_USB_RESUME:
1451dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_resume(ohci->name);
1452f1ae32a1SGerd Hoffmann         break;
1453f1ae32a1SGerd Hoffmann     case OHCI_USB_RESET:
14547d938fd1SHervé Poussineau         ohci_roothub_reset(ohci);
1455f1ae32a1SGerd Hoffmann         break;
1456f1ae32a1SGerd Hoffmann     }
1457f1ae32a1SGerd Hoffmann }
1458f1ae32a1SGerd Hoffmann 
1459f1ae32a1SGerd Hoffmann static uint32_t ohci_get_frame_remaining(OHCIState *ohci)
1460f1ae32a1SGerd Hoffmann {
1461f1ae32a1SGerd Hoffmann     uint16_t fr;
1462f1ae32a1SGerd Hoffmann     int64_t tks;
1463f1ae32a1SGerd Hoffmann 
1464f1ae32a1SGerd Hoffmann     if ((ohci->ctl & OHCI_CTL_HCFS) != OHCI_USB_OPERATIONAL)
1465f1ae32a1SGerd Hoffmann         return (ohci->frt << 31);
1466f1ae32a1SGerd Hoffmann 
1467f1ae32a1SGerd Hoffmann     /* Being in USB operational state guarnatees sof_time was
1468f1ae32a1SGerd Hoffmann      * set already.
1469f1ae32a1SGerd Hoffmann      */
1470bc72ad67SAlex Bligh     tks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - ohci->sof_time;
1471f1ae32a1SGerd Hoffmann 
1472f1ae32a1SGerd Hoffmann     /* avoid muldiv if possible */
1473f1ae32a1SGerd Hoffmann     if (tks >= usb_frame_time)
1474f1ae32a1SGerd Hoffmann         return (ohci->frt << 31);
1475f1ae32a1SGerd Hoffmann 
1476f1ae32a1SGerd Hoffmann     tks = muldiv64(1, tks, usb_bit_time);
1477f1ae32a1SGerd Hoffmann     fr = (uint16_t)(ohci->fi - tks);
1478f1ae32a1SGerd Hoffmann 
1479f1ae32a1SGerd Hoffmann     return (ohci->frt << 31) | fr;
1480f1ae32a1SGerd Hoffmann }
1481f1ae32a1SGerd Hoffmann 
1482f1ae32a1SGerd Hoffmann 
1483f1ae32a1SGerd Hoffmann /* Set root hub status */
1484f1ae32a1SGerd Hoffmann static void ohci_set_hub_status(OHCIState *ohci, uint32_t val)
1485f1ae32a1SGerd Hoffmann {
1486f1ae32a1SGerd Hoffmann     uint32_t old_state;
1487f1ae32a1SGerd Hoffmann 
1488f1ae32a1SGerd Hoffmann     old_state = ohci->rhstatus;
1489f1ae32a1SGerd Hoffmann 
1490f1ae32a1SGerd Hoffmann     /* write 1 to clear OCIC */
1491f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_OCIC)
1492f1ae32a1SGerd Hoffmann         ohci->rhstatus &= ~OHCI_RHS_OCIC;
1493f1ae32a1SGerd Hoffmann 
1494f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_LPS) {
1495f1ae32a1SGerd Hoffmann         int i;
1496f1ae32a1SGerd Hoffmann 
1497f1ae32a1SGerd Hoffmann         for (i = 0; i < ohci->num_ports; i++)
1498f1ae32a1SGerd Hoffmann             ohci_port_power(ohci, i, 0);
1499dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_hub_power_down();
1500f1ae32a1SGerd Hoffmann     }
1501f1ae32a1SGerd Hoffmann 
1502f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_LPSC) {
1503f1ae32a1SGerd Hoffmann         int i;
1504f1ae32a1SGerd Hoffmann 
1505f1ae32a1SGerd Hoffmann         for (i = 0; i < ohci->num_ports; i++)
1506f1ae32a1SGerd Hoffmann             ohci_port_power(ohci, i, 1);
1507dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_hub_power_up();
1508f1ae32a1SGerd Hoffmann     }
1509f1ae32a1SGerd Hoffmann 
1510f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_DRWE)
1511f1ae32a1SGerd Hoffmann         ohci->rhstatus |= OHCI_RHS_DRWE;
1512f1ae32a1SGerd Hoffmann 
1513f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_CRWE)
1514f1ae32a1SGerd Hoffmann         ohci->rhstatus &= ~OHCI_RHS_DRWE;
1515f1ae32a1SGerd Hoffmann 
1516f1ae32a1SGerd Hoffmann     if (old_state != ohci->rhstatus)
1517f1ae32a1SGerd Hoffmann         ohci_set_interrupt(ohci, OHCI_INTR_RHSC);
1518f1ae32a1SGerd Hoffmann }
1519f1ae32a1SGerd Hoffmann 
1520f1ae32a1SGerd Hoffmann /* Set root hub port status */
1521f1ae32a1SGerd Hoffmann static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val)
1522f1ae32a1SGerd Hoffmann {
1523f1ae32a1SGerd Hoffmann     uint32_t old_state;
1524f1ae32a1SGerd Hoffmann     OHCIPort *port;
1525f1ae32a1SGerd Hoffmann 
1526f1ae32a1SGerd Hoffmann     port = &ohci->rhport[portnum];
1527f1ae32a1SGerd Hoffmann     old_state = port->ctrl;
1528f1ae32a1SGerd Hoffmann 
1529f1ae32a1SGerd Hoffmann     /* Write to clear CSC, PESC, PSSC, OCIC, PRSC */
1530f1ae32a1SGerd Hoffmann     if (val & OHCI_PORT_WTC)
1531f1ae32a1SGerd Hoffmann         port->ctrl &= ~(val & OHCI_PORT_WTC);
1532f1ae32a1SGerd Hoffmann 
1533f1ae32a1SGerd Hoffmann     if (val & OHCI_PORT_CCS)
1534f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_PES;
1535f1ae32a1SGerd Hoffmann 
1536f1ae32a1SGerd Hoffmann     ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PES);
1537f1ae32a1SGerd Hoffmann 
1538f1ae32a1SGerd Hoffmann     if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PSS)) {
1539dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_port_suspend(portnum);
1540f1ae32a1SGerd Hoffmann     }
1541f1ae32a1SGerd Hoffmann 
1542f1ae32a1SGerd Hoffmann     if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PRS)) {
1543dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_port_reset(portnum);
1544f1ae32a1SGerd Hoffmann         usb_device_reset(port->port.dev);
1545f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_PRS;
1546f1ae32a1SGerd Hoffmann         /* ??? Should this also set OHCI_PORT_PESC.  */
1547f1ae32a1SGerd Hoffmann         port->ctrl |= OHCI_PORT_PES | OHCI_PORT_PRSC;
1548f1ae32a1SGerd Hoffmann     }
1549f1ae32a1SGerd Hoffmann 
1550f1ae32a1SGerd Hoffmann     /* Invert order here to ensure in ambiguous case, device is
1551f1ae32a1SGerd Hoffmann      * powered up...
1552f1ae32a1SGerd Hoffmann      */
1553f1ae32a1SGerd Hoffmann     if (val & OHCI_PORT_LSDA)
1554f1ae32a1SGerd Hoffmann         ohci_port_power(ohci, portnum, 0);
1555f1ae32a1SGerd Hoffmann     if (val & OHCI_PORT_PPS)
1556f1ae32a1SGerd Hoffmann         ohci_port_power(ohci, portnum, 1);
1557f1ae32a1SGerd Hoffmann 
1558f1ae32a1SGerd Hoffmann     if (old_state != port->ctrl)
1559f1ae32a1SGerd Hoffmann         ohci_set_interrupt(ohci, OHCI_INTR_RHSC);
1560f1ae32a1SGerd Hoffmann }
1561f1ae32a1SGerd Hoffmann 
1562f1ae32a1SGerd Hoffmann static uint64_t ohci_mem_read(void *opaque,
1563a8170e5eSAvi Kivity                               hwaddr addr,
1564f1ae32a1SGerd Hoffmann                               unsigned size)
1565f1ae32a1SGerd Hoffmann {
1566f1ae32a1SGerd Hoffmann     OHCIState *ohci = opaque;
1567f1ae32a1SGerd Hoffmann     uint32_t retval;
1568f1ae32a1SGerd Hoffmann 
1569f1ae32a1SGerd Hoffmann     /* Only aligned reads are allowed on OHCI */
1570f1ae32a1SGerd Hoffmann     if (addr & 3) {
1571dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_mem_read_unaligned(addr);
1572f1ae32a1SGerd Hoffmann         return 0xffffffff;
1573f1ae32a1SGerd Hoffmann     } else if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) {
1574f1ae32a1SGerd Hoffmann         /* HcRhPortStatus */
1575f1ae32a1SGerd Hoffmann         retval = ohci->rhport[(addr - 0x54) >> 2].ctrl | OHCI_PORT_PPS;
1576f1ae32a1SGerd Hoffmann     } else {
1577f1ae32a1SGerd Hoffmann         switch (addr >> 2) {
1578f1ae32a1SGerd Hoffmann         case 0: /* HcRevision */
1579f1ae32a1SGerd Hoffmann             retval = 0x10;
1580f1ae32a1SGerd Hoffmann             break;
1581f1ae32a1SGerd Hoffmann 
1582f1ae32a1SGerd Hoffmann         case 1: /* HcControl */
1583f1ae32a1SGerd Hoffmann             retval = ohci->ctl;
1584f1ae32a1SGerd Hoffmann             break;
1585f1ae32a1SGerd Hoffmann 
1586f1ae32a1SGerd Hoffmann         case 2: /* HcCommandStatus */
1587f1ae32a1SGerd Hoffmann             retval = ohci->status;
1588f1ae32a1SGerd Hoffmann             break;
1589f1ae32a1SGerd Hoffmann 
1590f1ae32a1SGerd Hoffmann         case 3: /* HcInterruptStatus */
1591f1ae32a1SGerd Hoffmann             retval = ohci->intr_status;
1592f1ae32a1SGerd Hoffmann             break;
1593f1ae32a1SGerd Hoffmann 
1594f1ae32a1SGerd Hoffmann         case 4: /* HcInterruptEnable */
1595f1ae32a1SGerd Hoffmann         case 5: /* HcInterruptDisable */
1596f1ae32a1SGerd Hoffmann             retval = ohci->intr;
1597f1ae32a1SGerd Hoffmann             break;
1598f1ae32a1SGerd Hoffmann 
1599f1ae32a1SGerd Hoffmann         case 6: /* HcHCCA */
1600f1ae32a1SGerd Hoffmann             retval = ohci->hcca;
1601f1ae32a1SGerd Hoffmann             break;
1602f1ae32a1SGerd Hoffmann 
1603f1ae32a1SGerd Hoffmann         case 7: /* HcPeriodCurrentED */
1604f1ae32a1SGerd Hoffmann             retval = ohci->per_cur;
1605f1ae32a1SGerd Hoffmann             break;
1606f1ae32a1SGerd Hoffmann 
1607f1ae32a1SGerd Hoffmann         case 8: /* HcControlHeadED */
1608f1ae32a1SGerd Hoffmann             retval = ohci->ctrl_head;
1609f1ae32a1SGerd Hoffmann             break;
1610f1ae32a1SGerd Hoffmann 
1611f1ae32a1SGerd Hoffmann         case 9: /* HcControlCurrentED */
1612f1ae32a1SGerd Hoffmann             retval = ohci->ctrl_cur;
1613f1ae32a1SGerd Hoffmann             break;
1614f1ae32a1SGerd Hoffmann 
1615f1ae32a1SGerd Hoffmann         case 10: /* HcBulkHeadED */
1616f1ae32a1SGerd Hoffmann             retval = ohci->bulk_head;
1617f1ae32a1SGerd Hoffmann             break;
1618f1ae32a1SGerd Hoffmann 
1619f1ae32a1SGerd Hoffmann         case 11: /* HcBulkCurrentED */
1620f1ae32a1SGerd Hoffmann             retval = ohci->bulk_cur;
1621f1ae32a1SGerd Hoffmann             break;
1622f1ae32a1SGerd Hoffmann 
1623f1ae32a1SGerd Hoffmann         case 12: /* HcDoneHead */
1624f1ae32a1SGerd Hoffmann             retval = ohci->done;
1625f1ae32a1SGerd Hoffmann             break;
1626f1ae32a1SGerd Hoffmann 
1627f1ae32a1SGerd Hoffmann         case 13: /* HcFmInterretval */
1628f1ae32a1SGerd Hoffmann             retval = (ohci->fit << 31) | (ohci->fsmps << 16) | (ohci->fi);
1629f1ae32a1SGerd Hoffmann             break;
1630f1ae32a1SGerd Hoffmann 
1631f1ae32a1SGerd Hoffmann         case 14: /* HcFmRemaining */
1632f1ae32a1SGerd Hoffmann             retval = ohci_get_frame_remaining(ohci);
1633f1ae32a1SGerd Hoffmann             break;
1634f1ae32a1SGerd Hoffmann 
1635f1ae32a1SGerd Hoffmann         case 15: /* HcFmNumber */
1636f1ae32a1SGerd Hoffmann             retval = ohci->frame_number;
1637f1ae32a1SGerd Hoffmann             break;
1638f1ae32a1SGerd Hoffmann 
1639f1ae32a1SGerd Hoffmann         case 16: /* HcPeriodicStart */
1640f1ae32a1SGerd Hoffmann             retval = ohci->pstart;
1641f1ae32a1SGerd Hoffmann             break;
1642f1ae32a1SGerd Hoffmann 
1643f1ae32a1SGerd Hoffmann         case 17: /* HcLSThreshold */
1644f1ae32a1SGerd Hoffmann             retval = ohci->lst;
1645f1ae32a1SGerd Hoffmann             break;
1646f1ae32a1SGerd Hoffmann 
1647f1ae32a1SGerd Hoffmann         case 18: /* HcRhDescriptorA */
1648f1ae32a1SGerd Hoffmann             retval = ohci->rhdesc_a;
1649f1ae32a1SGerd Hoffmann             break;
1650f1ae32a1SGerd Hoffmann 
1651f1ae32a1SGerd Hoffmann         case 19: /* HcRhDescriptorB */
1652f1ae32a1SGerd Hoffmann             retval = ohci->rhdesc_b;
1653f1ae32a1SGerd Hoffmann             break;
1654f1ae32a1SGerd Hoffmann 
1655f1ae32a1SGerd Hoffmann         case 20: /* HcRhStatus */
1656f1ae32a1SGerd Hoffmann             retval = ohci->rhstatus;
1657f1ae32a1SGerd Hoffmann             break;
1658f1ae32a1SGerd Hoffmann 
1659f1ae32a1SGerd Hoffmann         /* PXA27x specific registers */
1660f1ae32a1SGerd Hoffmann         case 24: /* HcStatus */
1661f1ae32a1SGerd Hoffmann             retval = ohci->hstatus & ohci->hmask;
1662f1ae32a1SGerd Hoffmann             break;
1663f1ae32a1SGerd Hoffmann 
1664f1ae32a1SGerd Hoffmann         case 25: /* HcHReset */
1665f1ae32a1SGerd Hoffmann             retval = ohci->hreset;
1666f1ae32a1SGerd Hoffmann             break;
1667f1ae32a1SGerd Hoffmann 
1668f1ae32a1SGerd Hoffmann         case 26: /* HcHInterruptEnable */
1669f1ae32a1SGerd Hoffmann             retval = ohci->hmask;
1670f1ae32a1SGerd Hoffmann             break;
1671f1ae32a1SGerd Hoffmann 
1672f1ae32a1SGerd Hoffmann         case 27: /* HcHInterruptTest */
1673f1ae32a1SGerd Hoffmann             retval = ohci->htest;
1674f1ae32a1SGerd Hoffmann             break;
1675f1ae32a1SGerd Hoffmann 
1676f1ae32a1SGerd Hoffmann         default:
1677dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_mem_read_bad_offset(addr);
1678f1ae32a1SGerd Hoffmann             retval = 0xffffffff;
1679f1ae32a1SGerd Hoffmann         }
1680f1ae32a1SGerd Hoffmann     }
1681f1ae32a1SGerd Hoffmann 
1682f1ae32a1SGerd Hoffmann     return retval;
1683f1ae32a1SGerd Hoffmann }
1684f1ae32a1SGerd Hoffmann 
1685f1ae32a1SGerd Hoffmann static void ohci_mem_write(void *opaque,
1686a8170e5eSAvi Kivity                            hwaddr addr,
1687f1ae32a1SGerd Hoffmann                            uint64_t val,
1688f1ae32a1SGerd Hoffmann                            unsigned size)
1689f1ae32a1SGerd Hoffmann {
1690f1ae32a1SGerd Hoffmann     OHCIState *ohci = opaque;
1691f1ae32a1SGerd Hoffmann 
1692f1ae32a1SGerd Hoffmann     /* Only aligned reads are allowed on OHCI */
1693f1ae32a1SGerd Hoffmann     if (addr & 3) {
1694dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_mem_write_unaligned(addr);
1695f1ae32a1SGerd Hoffmann         return;
1696f1ae32a1SGerd Hoffmann     }
1697f1ae32a1SGerd Hoffmann 
1698f1ae32a1SGerd Hoffmann     if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) {
1699f1ae32a1SGerd Hoffmann         /* HcRhPortStatus */
1700f1ae32a1SGerd Hoffmann         ohci_port_set_status(ohci, (addr - 0x54) >> 2, val);
1701f1ae32a1SGerd Hoffmann         return;
1702f1ae32a1SGerd Hoffmann     }
1703f1ae32a1SGerd Hoffmann 
1704f1ae32a1SGerd Hoffmann     switch (addr >> 2) {
1705f1ae32a1SGerd Hoffmann     case 1: /* HcControl */
1706f1ae32a1SGerd Hoffmann         ohci_set_ctl(ohci, val);
1707f1ae32a1SGerd Hoffmann         break;
1708f1ae32a1SGerd Hoffmann 
1709f1ae32a1SGerd Hoffmann     case 2: /* HcCommandStatus */
1710f1ae32a1SGerd Hoffmann         /* SOC is read-only */
1711f1ae32a1SGerd Hoffmann         val = (val & ~OHCI_STATUS_SOC);
1712f1ae32a1SGerd Hoffmann 
1713f1ae32a1SGerd Hoffmann         /* Bits written as '0' remain unchanged in the register */
1714f1ae32a1SGerd Hoffmann         ohci->status |= val;
1715f1ae32a1SGerd Hoffmann 
1716f1ae32a1SGerd Hoffmann         if (ohci->status & OHCI_STATUS_HCR)
17170922c3f6SHervé Poussineau             ohci_soft_reset(ohci);
1718f1ae32a1SGerd Hoffmann         break;
1719f1ae32a1SGerd Hoffmann 
1720f1ae32a1SGerd Hoffmann     case 3: /* HcInterruptStatus */
1721f1ae32a1SGerd Hoffmann         ohci->intr_status &= ~val;
1722f1ae32a1SGerd Hoffmann         ohci_intr_update(ohci);
1723f1ae32a1SGerd Hoffmann         break;
1724f1ae32a1SGerd Hoffmann 
1725f1ae32a1SGerd Hoffmann     case 4: /* HcInterruptEnable */
1726f1ae32a1SGerd Hoffmann         ohci->intr |= val;
1727f1ae32a1SGerd Hoffmann         ohci_intr_update(ohci);
1728f1ae32a1SGerd Hoffmann         break;
1729f1ae32a1SGerd Hoffmann 
1730f1ae32a1SGerd Hoffmann     case 5: /* HcInterruptDisable */
1731f1ae32a1SGerd Hoffmann         ohci->intr &= ~val;
1732f1ae32a1SGerd Hoffmann         ohci_intr_update(ohci);
1733f1ae32a1SGerd Hoffmann         break;
1734f1ae32a1SGerd Hoffmann 
1735f1ae32a1SGerd Hoffmann     case 6: /* HcHCCA */
1736f1ae32a1SGerd Hoffmann         ohci->hcca = val & OHCI_HCCA_MASK;
1737f1ae32a1SGerd Hoffmann         break;
1738f1ae32a1SGerd Hoffmann 
1739f1ae32a1SGerd Hoffmann     case 7: /* HcPeriodCurrentED */
1740f1ae32a1SGerd Hoffmann         /* Ignore writes to this read-only register, Linux does them */
1741f1ae32a1SGerd Hoffmann         break;
1742f1ae32a1SGerd Hoffmann 
1743f1ae32a1SGerd Hoffmann     case 8: /* HcControlHeadED */
1744f1ae32a1SGerd Hoffmann         ohci->ctrl_head = val & OHCI_EDPTR_MASK;
1745f1ae32a1SGerd Hoffmann         break;
1746f1ae32a1SGerd Hoffmann 
1747f1ae32a1SGerd Hoffmann     case 9: /* HcControlCurrentED */
1748f1ae32a1SGerd Hoffmann         ohci->ctrl_cur = val & OHCI_EDPTR_MASK;
1749f1ae32a1SGerd Hoffmann         break;
1750f1ae32a1SGerd Hoffmann 
1751f1ae32a1SGerd Hoffmann     case 10: /* HcBulkHeadED */
1752f1ae32a1SGerd Hoffmann         ohci->bulk_head = val & OHCI_EDPTR_MASK;
1753f1ae32a1SGerd Hoffmann         break;
1754f1ae32a1SGerd Hoffmann 
1755f1ae32a1SGerd Hoffmann     case 11: /* HcBulkCurrentED */
1756f1ae32a1SGerd Hoffmann         ohci->bulk_cur = val & OHCI_EDPTR_MASK;
1757f1ae32a1SGerd Hoffmann         break;
1758f1ae32a1SGerd Hoffmann 
1759f1ae32a1SGerd Hoffmann     case 13: /* HcFmInterval */
1760f1ae32a1SGerd Hoffmann         ohci->fsmps = (val & OHCI_FMI_FSMPS) >> 16;
1761f1ae32a1SGerd Hoffmann         ohci->fit = (val & OHCI_FMI_FIT) >> 31;
1762f1ae32a1SGerd Hoffmann         ohci_set_frame_interval(ohci, val);
1763f1ae32a1SGerd Hoffmann         break;
1764f1ae32a1SGerd Hoffmann 
1765f1ae32a1SGerd Hoffmann     case 15: /* HcFmNumber */
1766f1ae32a1SGerd Hoffmann         break;
1767f1ae32a1SGerd Hoffmann 
1768f1ae32a1SGerd Hoffmann     case 16: /* HcPeriodicStart */
1769f1ae32a1SGerd Hoffmann         ohci->pstart = val & 0xffff;
1770f1ae32a1SGerd Hoffmann         break;
1771f1ae32a1SGerd Hoffmann 
1772f1ae32a1SGerd Hoffmann     case 17: /* HcLSThreshold */
1773f1ae32a1SGerd Hoffmann         ohci->lst = val & 0xffff;
1774f1ae32a1SGerd Hoffmann         break;
1775f1ae32a1SGerd Hoffmann 
1776f1ae32a1SGerd Hoffmann     case 18: /* HcRhDescriptorA */
1777f1ae32a1SGerd Hoffmann         ohci->rhdesc_a &= ~OHCI_RHA_RW_MASK;
1778f1ae32a1SGerd Hoffmann         ohci->rhdesc_a |= val & OHCI_RHA_RW_MASK;
1779f1ae32a1SGerd Hoffmann         break;
1780f1ae32a1SGerd Hoffmann 
1781f1ae32a1SGerd Hoffmann     case 19: /* HcRhDescriptorB */
1782f1ae32a1SGerd Hoffmann         break;
1783f1ae32a1SGerd Hoffmann 
1784f1ae32a1SGerd Hoffmann     case 20: /* HcRhStatus */
1785f1ae32a1SGerd Hoffmann         ohci_set_hub_status(ohci, val);
1786f1ae32a1SGerd Hoffmann         break;
1787f1ae32a1SGerd Hoffmann 
1788f1ae32a1SGerd Hoffmann     /* PXA27x specific registers */
1789f1ae32a1SGerd Hoffmann     case 24: /* HcStatus */
1790f1ae32a1SGerd Hoffmann         ohci->hstatus &= ~(val & ohci->hmask);
17917fa96d73SGerd Hoffmann         break;
1792f1ae32a1SGerd Hoffmann 
1793f1ae32a1SGerd Hoffmann     case 25: /* HcHReset */
1794f1ae32a1SGerd Hoffmann         ohci->hreset = val & ~OHCI_HRESET_FSBIR;
1795f1ae32a1SGerd Hoffmann         if (val & OHCI_HRESET_FSBIR)
179684d04e21SHervé Poussineau             ohci_hard_reset(ohci);
1797f1ae32a1SGerd Hoffmann         break;
1798f1ae32a1SGerd Hoffmann 
1799f1ae32a1SGerd Hoffmann     case 26: /* HcHInterruptEnable */
1800f1ae32a1SGerd Hoffmann         ohci->hmask = val;
1801f1ae32a1SGerd Hoffmann         break;
1802f1ae32a1SGerd Hoffmann 
1803f1ae32a1SGerd Hoffmann     case 27: /* HcHInterruptTest */
1804f1ae32a1SGerd Hoffmann         ohci->htest = val;
1805f1ae32a1SGerd Hoffmann         break;
1806f1ae32a1SGerd Hoffmann 
1807f1ae32a1SGerd Hoffmann     default:
1808dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_mem_write_bad_offset(addr);
1809f1ae32a1SGerd Hoffmann         break;
1810f1ae32a1SGerd Hoffmann     }
1811f1ae32a1SGerd Hoffmann }
1812f1ae32a1SGerd Hoffmann 
1813f1ae32a1SGerd Hoffmann static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev)
1814f1ae32a1SGerd Hoffmann {
1815f1ae32a1SGerd Hoffmann     if (ohci->async_td &&
1816f1ae32a1SGerd Hoffmann         usb_packet_is_inflight(&ohci->usb_packet) &&
1817f1ae32a1SGerd Hoffmann         ohci->usb_packet.ep->dev == dev) {
1818f1ae32a1SGerd Hoffmann         usb_cancel_packet(&ohci->usb_packet);
1819f1ae32a1SGerd Hoffmann         ohci->async_td = 0;
1820f1ae32a1SGerd Hoffmann     }
1821f1ae32a1SGerd Hoffmann }
1822f1ae32a1SGerd Hoffmann 
1823f1ae32a1SGerd Hoffmann static const MemoryRegionOps ohci_mem_ops = {
1824f1ae32a1SGerd Hoffmann     .read = ohci_mem_read,
1825f1ae32a1SGerd Hoffmann     .write = ohci_mem_write,
1826f1ae32a1SGerd Hoffmann     .endianness = DEVICE_LITTLE_ENDIAN,
1827f1ae32a1SGerd Hoffmann };
1828f1ae32a1SGerd Hoffmann 
1829f1ae32a1SGerd Hoffmann static USBPortOps ohci_port_ops = {
1830f1ae32a1SGerd Hoffmann     .attach = ohci_attach,
1831f1ae32a1SGerd Hoffmann     .detach = ohci_detach,
1832f1ae32a1SGerd Hoffmann     .child_detach = ohci_child_detach,
1833f1ae32a1SGerd Hoffmann     .wakeup = ohci_wakeup,
1834f1ae32a1SGerd Hoffmann     .complete = ohci_async_complete_packet,
1835f1ae32a1SGerd Hoffmann };
1836f1ae32a1SGerd Hoffmann 
1837f1ae32a1SGerd Hoffmann static USBBusOps ohci_bus_ops = {
1838f1ae32a1SGerd Hoffmann };
1839f1ae32a1SGerd Hoffmann 
184087581feaSMarkus Armbruster static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
18419ac6a217SDavid Gibson                           int num_ports, dma_addr_t localmem_base,
18429ac6a217SDavid Gibson                           char *masterbus, uint32_t firstport,
184387581feaSMarkus Armbruster                           AddressSpace *as, Error **errp)
1844f1ae32a1SGerd Hoffmann {
1845f4bbaaf5SMarkus Armbruster     Error *err = NULL;
1846f1ae32a1SGerd Hoffmann     int i;
1847f1ae32a1SGerd Hoffmann 
1848df32fd1cSPaolo Bonzini     ohci->as = as;
18499ac6a217SDavid Gibson 
1850f1ae32a1SGerd Hoffmann     if (usb_frame_time == 0) {
1851f1ae32a1SGerd Hoffmann #ifdef OHCI_TIME_WARP
1852f1ae32a1SGerd Hoffmann         usb_frame_time = get_ticks_per_sec();
1853f1ae32a1SGerd Hoffmann         usb_bit_time = muldiv64(1, get_ticks_per_sec(), USB_HZ/1000);
1854f1ae32a1SGerd Hoffmann #else
1855f1ae32a1SGerd Hoffmann         usb_frame_time = muldiv64(1, get_ticks_per_sec(), 1000);
1856f1ae32a1SGerd Hoffmann         if (get_ticks_per_sec() >= USB_HZ) {
1857f1ae32a1SGerd Hoffmann             usb_bit_time = muldiv64(1, get_ticks_per_sec(), USB_HZ);
1858f1ae32a1SGerd Hoffmann         } else {
1859f1ae32a1SGerd Hoffmann             usb_bit_time = 1;
1860f1ae32a1SGerd Hoffmann         }
1861f1ae32a1SGerd Hoffmann #endif
1862dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_init_time(usb_frame_time, usb_bit_time);
1863f1ae32a1SGerd Hoffmann     }
1864f1ae32a1SGerd Hoffmann 
1865f1ae32a1SGerd Hoffmann     ohci->num_ports = num_ports;
1866f1ae32a1SGerd Hoffmann     if (masterbus) {
1867f1ae32a1SGerd Hoffmann         USBPort *ports[OHCI_MAX_PORTS];
1868f1ae32a1SGerd Hoffmann         for(i = 0; i < num_ports; i++) {
1869f1ae32a1SGerd Hoffmann             ports[i] = &ohci->rhport[i].port;
1870f1ae32a1SGerd Hoffmann         }
1871f4bbaaf5SMarkus Armbruster         usb_register_companion(masterbus, ports, num_ports,
1872f1ae32a1SGerd Hoffmann                                firstport, ohci, &ohci_port_ops,
1873f4bbaaf5SMarkus Armbruster                                USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL,
1874f4bbaaf5SMarkus Armbruster                                &err);
1875f4bbaaf5SMarkus Armbruster         if (err) {
187687581feaSMarkus Armbruster             error_propagate(errp, err);
187787581feaSMarkus Armbruster             return;
1878f1ae32a1SGerd Hoffmann         }
1879f1ae32a1SGerd Hoffmann     } else {
1880c889b3a5SAndreas Färber         usb_bus_new(&ohci->bus, sizeof(ohci->bus), &ohci_bus_ops, dev);
1881f1ae32a1SGerd Hoffmann         for (i = 0; i < num_ports; i++) {
1882f1ae32a1SGerd Hoffmann             usb_register_port(&ohci->bus, &ohci->rhport[i].port,
1883f1ae32a1SGerd Hoffmann                               ohci, i, &ohci_port_ops,
1884f1ae32a1SGerd Hoffmann                               USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
1885f1ae32a1SGerd Hoffmann         }
1886f1ae32a1SGerd Hoffmann     }
1887f1ae32a1SGerd Hoffmann 
188822fc860bSPaolo Bonzini     memory_region_init_io(&ohci->mem, OBJECT(dev), &ohci_mem_ops,
188922fc860bSPaolo Bonzini                           ohci, "ohci", 256);
1890f1ae32a1SGerd Hoffmann     ohci->localmem_base = localmem_base;
1891f1ae32a1SGerd Hoffmann 
1892f1ae32a1SGerd Hoffmann     ohci->name = object_get_typename(OBJECT(dev));
1893f1ae32a1SGerd Hoffmann     usb_packet_init(&ohci->usb_packet);
1894f1ae32a1SGerd Hoffmann 
1895f1ae32a1SGerd Hoffmann     ohci->async_td = 0;
1896*fa1298c2SGerd Hoffmann 
1897*fa1298c2SGerd Hoffmann     ohci->eof_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
1898*fa1298c2SGerd Hoffmann                                    ohci_frame_boundary, ohci);
1899f1ae32a1SGerd Hoffmann }
1900f1ae32a1SGerd Hoffmann 
19011aa0c0c7SHu Tao #define TYPE_PCI_OHCI "pci-ohci"
19021aa0c0c7SHu Tao #define PCI_OHCI(obj) OBJECT_CHECK(OHCIPCIState, (obj), TYPE_PCI_OHCI)
19031aa0c0c7SHu Tao 
1904f1ae32a1SGerd Hoffmann typedef struct {
19051aa0c0c7SHu Tao     /*< private >*/
19061aa0c0c7SHu Tao     PCIDevice parent_obj;
19071aa0c0c7SHu Tao     /*< public >*/
19081aa0c0c7SHu Tao 
1909f1ae32a1SGerd Hoffmann     OHCIState state;
1910f1ae32a1SGerd Hoffmann     char *masterbus;
1911f1ae32a1SGerd Hoffmann     uint32_t num_ports;
1912f1ae32a1SGerd Hoffmann     uint32_t firstport;
1913f1ae32a1SGerd Hoffmann } OHCIPCIState;
1914f1ae32a1SGerd Hoffmann 
1915cf66ee8eSAlexey Kardashevskiy /** A typical O/EHCI will stop operating, set itself into error state
1916cf66ee8eSAlexey Kardashevskiy  * (which can be queried by MMIO) and will set PERR in its config
1917cf66ee8eSAlexey Kardashevskiy  * space to signal that it got an error
1918cf66ee8eSAlexey Kardashevskiy  */
1919cf66ee8eSAlexey Kardashevskiy static void ohci_die(OHCIState *ohci)
1920cf66ee8eSAlexey Kardashevskiy {
1921cf66ee8eSAlexey Kardashevskiy     OHCIPCIState *dev = container_of(ohci, OHCIPCIState, state);
1922cf66ee8eSAlexey Kardashevskiy 
1923dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_die();
1924cf66ee8eSAlexey Kardashevskiy 
1925cf66ee8eSAlexey Kardashevskiy     ohci_set_interrupt(ohci, OHCI_INTR_UE);
1926cf66ee8eSAlexey Kardashevskiy     ohci_bus_stop(ohci);
1927cf66ee8eSAlexey Kardashevskiy     pci_set_word(dev->parent_obj.config + PCI_STATUS,
1928cf66ee8eSAlexey Kardashevskiy                  PCI_STATUS_DETECTED_PARITY);
1929cf66ee8eSAlexey Kardashevskiy }
1930cf66ee8eSAlexey Kardashevskiy 
193187581feaSMarkus Armbruster static void usb_ohci_realize_pci(PCIDevice *dev, Error **errp)
1932f1ae32a1SGerd Hoffmann {
193387581feaSMarkus Armbruster     Error *err = NULL;
19341aa0c0c7SHu Tao     OHCIPCIState *ohci = PCI_OHCI(dev);
1935f1ae32a1SGerd Hoffmann 
19361aa0c0c7SHu Tao     dev->config[PCI_CLASS_PROG] = 0x10; /* OHCI */
19371aa0c0c7SHu Tao     dev->config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */
1938f1ae32a1SGerd Hoffmann 
193987581feaSMarkus Armbruster     usb_ohci_init(&ohci->state, DEVICE(dev), ohci->num_ports, 0,
19409ac6a217SDavid Gibson                   ohci->masterbus, ohci->firstport,
194187581feaSMarkus Armbruster                   pci_get_address_space(dev), &err);
194287581feaSMarkus Armbruster     if (err) {
194387581feaSMarkus Armbruster         error_propagate(errp, err);
194487581feaSMarkus Armbruster         return;
1945f1ae32a1SGerd Hoffmann     }
1946f1ae32a1SGerd Hoffmann 
194787581feaSMarkus Armbruster     ohci->state.irq = pci_allocate_irq(dev);
19481aa0c0c7SHu Tao     pci_register_bar(dev, 0, 0, &ohci->state.mem);
1949f1ae32a1SGerd Hoffmann }
1950f1ae32a1SGerd Hoffmann 
195107832c38SGonglei static void usb_ohci_exit(PCIDevice *dev)
195207832c38SGonglei {
195307832c38SGonglei     OHCIPCIState *ohci = PCI_OHCI(dev);
195407832c38SGonglei     OHCIState *s = &ohci->state;
195507832c38SGonglei 
1956dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_exit(s->name);
195707832c38SGonglei     ohci_bus_stop(s);
195807832c38SGonglei 
195907832c38SGonglei     if (s->async_td) {
196007832c38SGonglei         usb_cancel_packet(&s->usb_packet);
196107832c38SGonglei         s->async_td = 0;
196207832c38SGonglei     }
196307832c38SGonglei     ohci_stop_endpoints(s);
196407832c38SGonglei 
196507832c38SGonglei     if (!ohci->masterbus) {
196607832c38SGonglei         usb_bus_release(&s->bus);
196707832c38SGonglei     }
1968*fa1298c2SGerd Hoffmann 
1969*fa1298c2SGerd Hoffmann     timer_del(s->eof_timer);
1970*fa1298c2SGerd Hoffmann     timer_free(s->eof_timer);
197107832c38SGonglei }
197207832c38SGonglei 
197388dd1b8dSGonglei static void usb_ohci_reset_pci(DeviceState *d)
197488dd1b8dSGonglei {
197588dd1b8dSGonglei     PCIDevice *dev = PCI_DEVICE(d);
197688dd1b8dSGonglei     OHCIPCIState *ohci = PCI_OHCI(dev);
197788dd1b8dSGonglei     OHCIState *s = &ohci->state;
197888dd1b8dSGonglei 
197984d04e21SHervé Poussineau     ohci_hard_reset(s);
198088dd1b8dSGonglei }
198188dd1b8dSGonglei 
19821aa0c0c7SHu Tao #define TYPE_SYSBUS_OHCI "sysbus-ohci"
19831aa0c0c7SHu Tao #define SYSBUS_OHCI(obj) OBJECT_CHECK(OHCISysBusState, (obj), TYPE_SYSBUS_OHCI)
19841aa0c0c7SHu Tao 
1985f1ae32a1SGerd Hoffmann typedef struct {
19861aa0c0c7SHu Tao     /*< private >*/
19871aa0c0c7SHu Tao     SysBusDevice parent_obj;
19881aa0c0c7SHu Tao     /*< public >*/
19891aa0c0c7SHu Tao 
1990f1ae32a1SGerd Hoffmann     OHCIState ohci;
1991f1ae32a1SGerd Hoffmann     uint32_t num_ports;
19929ac6a217SDavid Gibson     dma_addr_t dma_offset;
1993f1ae32a1SGerd Hoffmann } OHCISysBusState;
1994f1ae32a1SGerd Hoffmann 
1995457215ecSHu Tao static void ohci_realize_pxa(DeviceState *dev, Error **errp)
1996f1ae32a1SGerd Hoffmann {
19971aa0c0c7SHu Tao     OHCISysBusState *s = SYSBUS_OHCI(dev);
1998457215ecSHu Tao     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
1999f1ae32a1SGerd Hoffmann 
2000f1ae32a1SGerd Hoffmann     /* Cannot fail as we pass NULL for masterbus */
2001457215ecSHu Tao     usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset, NULL, 0,
200287581feaSMarkus Armbruster                   &address_space_memory, &error_abort);
2003457215ecSHu Tao     sysbus_init_irq(sbd, &s->ohci.irq);
2004457215ecSHu Tao     sysbus_init_mmio(sbd, &s->ohci.mem);
2005f1ae32a1SGerd Hoffmann }
2006f1ae32a1SGerd Hoffmann 
200788dd1b8dSGonglei static void usb_ohci_reset_sysbus(DeviceState *dev)
200888dd1b8dSGonglei {
200988dd1b8dSGonglei     OHCISysBusState *s = SYSBUS_OHCI(dev);
201088dd1b8dSGonglei     OHCIState *ohci = &s->ohci;
201188dd1b8dSGonglei 
201284d04e21SHervé Poussineau     ohci_hard_reset(ohci);
201388dd1b8dSGonglei }
201488dd1b8dSGonglei 
2015f1ae32a1SGerd Hoffmann static Property ohci_pci_properties[] = {
2016f1ae32a1SGerd Hoffmann     DEFINE_PROP_STRING("masterbus", OHCIPCIState, masterbus),
2017f1ae32a1SGerd Hoffmann     DEFINE_PROP_UINT32("num-ports", OHCIPCIState, num_ports, 3),
2018f1ae32a1SGerd Hoffmann     DEFINE_PROP_UINT32("firstport", OHCIPCIState, firstport, 0),
2019f1ae32a1SGerd Hoffmann     DEFINE_PROP_END_OF_LIST(),
2020f1ae32a1SGerd Hoffmann };
2021f1ae32a1SGerd Hoffmann 
202269e25d26SAlexey Kardashevskiy static const VMStateDescription vmstate_ohci_state_port = {
202369e25d26SAlexey Kardashevskiy     .name = "ohci-core/port",
202469e25d26SAlexey Kardashevskiy     .version_id = 1,
202569e25d26SAlexey Kardashevskiy     .minimum_version_id = 1,
202669e25d26SAlexey Kardashevskiy     .fields = (VMStateField[]) {
202769e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(ctrl, OHCIPort),
202869e25d26SAlexey Kardashevskiy         VMSTATE_END_OF_LIST()
202969e25d26SAlexey Kardashevskiy     },
203069e25d26SAlexey Kardashevskiy };
203169e25d26SAlexey Kardashevskiy 
203269e25d26SAlexey Kardashevskiy static bool ohci_eof_timer_needed(void *opaque)
203369e25d26SAlexey Kardashevskiy {
203469e25d26SAlexey Kardashevskiy     OHCIState *ohci = opaque;
203569e25d26SAlexey Kardashevskiy 
2036*fa1298c2SGerd Hoffmann     return timer_pending(ohci->eof_timer);
203769e25d26SAlexey Kardashevskiy }
203869e25d26SAlexey Kardashevskiy 
203969e25d26SAlexey Kardashevskiy static const VMStateDescription vmstate_ohci_eof_timer = {
204069e25d26SAlexey Kardashevskiy     .name = "ohci-core/eof-timer",
204169e25d26SAlexey Kardashevskiy     .version_id = 1,
204269e25d26SAlexey Kardashevskiy     .minimum_version_id = 1,
20435cd8cadaSJuan Quintela     .needed = ohci_eof_timer_needed,
204469e25d26SAlexey Kardashevskiy     .fields = (VMStateField[]) {
2045e720677eSPaolo Bonzini         VMSTATE_TIMER_PTR(eof_timer, OHCIState),
204669e25d26SAlexey Kardashevskiy         VMSTATE_END_OF_LIST()
204769e25d26SAlexey Kardashevskiy     },
204869e25d26SAlexey Kardashevskiy };
204969e25d26SAlexey Kardashevskiy 
2050b9b45b4aSStefan Weil static const VMStateDescription vmstate_ohci_state = {
205169e25d26SAlexey Kardashevskiy     .name = "ohci-core",
205269e25d26SAlexey Kardashevskiy     .version_id = 1,
205369e25d26SAlexey Kardashevskiy     .minimum_version_id = 1,
205469e25d26SAlexey Kardashevskiy     .fields = (VMStateField[]) {
205569e25d26SAlexey Kardashevskiy         VMSTATE_INT64(sof_time, OHCIState),
205669e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(ctl, OHCIState),
205769e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(status, OHCIState),
205869e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(intr_status, OHCIState),
205969e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(intr, OHCIState),
206069e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(hcca, OHCIState),
206169e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(ctrl_head, OHCIState),
206269e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(ctrl_cur, OHCIState),
206369e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(bulk_head, OHCIState),
206469e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(bulk_cur, OHCIState),
206569e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(per_cur, OHCIState),
206669e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(done, OHCIState),
206769e25d26SAlexey Kardashevskiy         VMSTATE_INT32(done_count, OHCIState),
206869e25d26SAlexey Kardashevskiy         VMSTATE_UINT16(fsmps, OHCIState),
206969e25d26SAlexey Kardashevskiy         VMSTATE_UINT8(fit, OHCIState),
207069e25d26SAlexey Kardashevskiy         VMSTATE_UINT16(fi, OHCIState),
207169e25d26SAlexey Kardashevskiy         VMSTATE_UINT8(frt, OHCIState),
207269e25d26SAlexey Kardashevskiy         VMSTATE_UINT16(frame_number, OHCIState),
207369e25d26SAlexey Kardashevskiy         VMSTATE_UINT16(padding, OHCIState),
207469e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(pstart, OHCIState),
207569e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(lst, OHCIState),
207669e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(rhdesc_a, OHCIState),
207769e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(rhdesc_b, OHCIState),
207869e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(rhstatus, OHCIState),
207969e25d26SAlexey Kardashevskiy         VMSTATE_STRUCT_ARRAY(rhport, OHCIState, OHCI_MAX_PORTS, 0,
208069e25d26SAlexey Kardashevskiy                              vmstate_ohci_state_port, OHCIPort),
208169e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(hstatus, OHCIState),
208269e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(hmask, OHCIState),
208369e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(hreset, OHCIState),
208469e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(htest, OHCIState),
208569e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(old_ctl, OHCIState),
208669e25d26SAlexey Kardashevskiy         VMSTATE_UINT8_ARRAY(usb_buf, OHCIState, 8192),
208769e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(async_td, OHCIState),
208869e25d26SAlexey Kardashevskiy         VMSTATE_BOOL(async_complete, OHCIState),
208969e25d26SAlexey Kardashevskiy         VMSTATE_END_OF_LIST()
209069e25d26SAlexey Kardashevskiy     },
20915cd8cadaSJuan Quintela     .subsections = (const VMStateDescription*[]) {
20925cd8cadaSJuan Quintela         &vmstate_ohci_eof_timer,
20935cd8cadaSJuan Quintela         NULL
209469e25d26SAlexey Kardashevskiy     }
209569e25d26SAlexey Kardashevskiy };
209669e25d26SAlexey Kardashevskiy 
209769e25d26SAlexey Kardashevskiy static const VMStateDescription vmstate_ohci = {
209869e25d26SAlexey Kardashevskiy     .name = "ohci",
209969e25d26SAlexey Kardashevskiy     .version_id = 1,
210069e25d26SAlexey Kardashevskiy     .minimum_version_id = 1,
210169e25d26SAlexey Kardashevskiy     .fields = (VMStateField[]) {
210269e25d26SAlexey Kardashevskiy         VMSTATE_PCI_DEVICE(parent_obj, OHCIPCIState),
210369e25d26SAlexey Kardashevskiy         VMSTATE_STRUCT(state, OHCIPCIState, 1, vmstate_ohci_state, OHCIState),
210469e25d26SAlexey Kardashevskiy         VMSTATE_END_OF_LIST()
210569e25d26SAlexey Kardashevskiy     }
210669e25d26SAlexey Kardashevskiy };
210769e25d26SAlexey Kardashevskiy 
2108f1ae32a1SGerd Hoffmann static void ohci_pci_class_init(ObjectClass *klass, void *data)
2109f1ae32a1SGerd Hoffmann {
2110f1ae32a1SGerd Hoffmann     DeviceClass *dc = DEVICE_CLASS(klass);
2111f1ae32a1SGerd Hoffmann     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
2112f1ae32a1SGerd Hoffmann 
211387581feaSMarkus Armbruster     k->realize = usb_ohci_realize_pci;
211407832c38SGonglei     k->exit = usb_ohci_exit;
2115f1ae32a1SGerd Hoffmann     k->vendor_id = PCI_VENDOR_ID_APPLE;
2116f1ae32a1SGerd Hoffmann     k->device_id = PCI_DEVICE_ID_APPLE_IPID_USB;
2117f1ae32a1SGerd Hoffmann     k->class_id = PCI_CLASS_SERIAL_USB;
2118125ee0edSMarcel Apfelbaum     set_bit(DEVICE_CATEGORY_USB, dc->categories);
2119f1ae32a1SGerd Hoffmann     dc->desc = "Apple USB Controller";
2120f1ae32a1SGerd Hoffmann     dc->props = ohci_pci_properties;
21212897ae02SIgor Mammedov     dc->hotpluggable = false;
212269e25d26SAlexey Kardashevskiy     dc->vmsd = &vmstate_ohci;
212388dd1b8dSGonglei     dc->reset = usb_ohci_reset_pci;
2124f1ae32a1SGerd Hoffmann }
2125f1ae32a1SGerd Hoffmann 
21268c43a6f0SAndreas Färber static const TypeInfo ohci_pci_info = {
21271aa0c0c7SHu Tao     .name          = TYPE_PCI_OHCI,
2128f1ae32a1SGerd Hoffmann     .parent        = TYPE_PCI_DEVICE,
2129f1ae32a1SGerd Hoffmann     .instance_size = sizeof(OHCIPCIState),
2130f1ae32a1SGerd Hoffmann     .class_init    = ohci_pci_class_init,
2131f1ae32a1SGerd Hoffmann };
2132f1ae32a1SGerd Hoffmann 
2133f1ae32a1SGerd Hoffmann static Property ohci_sysbus_properties[] = {
2134f1ae32a1SGerd Hoffmann     DEFINE_PROP_UINT32("num-ports", OHCISysBusState, num_ports, 3),
21359ac6a217SDavid Gibson     DEFINE_PROP_DMAADDR("dma-offset", OHCISysBusState, dma_offset, 3),
2136f1ae32a1SGerd Hoffmann     DEFINE_PROP_END_OF_LIST(),
2137f1ae32a1SGerd Hoffmann };
2138f1ae32a1SGerd Hoffmann 
2139f1ae32a1SGerd Hoffmann static void ohci_sysbus_class_init(ObjectClass *klass, void *data)
2140f1ae32a1SGerd Hoffmann {
2141f1ae32a1SGerd Hoffmann     DeviceClass *dc = DEVICE_CLASS(klass);
2142f1ae32a1SGerd Hoffmann 
2143457215ecSHu Tao     dc->realize = ohci_realize_pxa;
2144125ee0edSMarcel Apfelbaum     set_bit(DEVICE_CATEGORY_USB, dc->categories);
2145f1ae32a1SGerd Hoffmann     dc->desc = "OHCI USB Controller";
2146f1ae32a1SGerd Hoffmann     dc->props = ohci_sysbus_properties;
214788dd1b8dSGonglei     dc->reset = usb_ohci_reset_sysbus;
2148f1ae32a1SGerd Hoffmann }
2149f1ae32a1SGerd Hoffmann 
21508c43a6f0SAndreas Färber static const TypeInfo ohci_sysbus_info = {
21511aa0c0c7SHu Tao     .name          = TYPE_SYSBUS_OHCI,
2152f1ae32a1SGerd Hoffmann     .parent        = TYPE_SYS_BUS_DEVICE,
2153f1ae32a1SGerd Hoffmann     .instance_size = sizeof(OHCISysBusState),
2154f1ae32a1SGerd Hoffmann     .class_init    = ohci_sysbus_class_init,
2155f1ae32a1SGerd Hoffmann };
2156f1ae32a1SGerd Hoffmann 
2157f1ae32a1SGerd Hoffmann static void ohci_register_types(void)
2158f1ae32a1SGerd Hoffmann {
2159f1ae32a1SGerd Hoffmann     type_register_static(&ohci_pci_info);
2160f1ae32a1SGerd Hoffmann     type_register_static(&ohci_sysbus_info);
2161f1ae32a1SGerd Hoffmann }
2162f1ae32a1SGerd Hoffmann 
2163f1ae32a1SGerd Hoffmann type_init(ohci_register_types)
2164