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