xref: /openbmc/qemu/hw/usb/hcd-ohci.c (revision 8c43a6f0)
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 Handle unrecoverable errors properly
26f1ae32a1SGerd Hoffmann  *  o BIOS work to boot from USB storage
27f1ae32a1SGerd Hoffmann */
28f1ae32a1SGerd Hoffmann 
29f1ae32a1SGerd Hoffmann #include "hw/hw.h"
301de7afc9SPaolo Bonzini #include "qemu/timer.h"
31f1ae32a1SGerd Hoffmann #include "hw/usb.h"
32a2cb15b0SMichael S. Tsirkin #include "hw/pci/pci.h"
33f1ae32a1SGerd Hoffmann #include "hw/sysbus.h"
349ac6a217SDavid Gibson #include "hw/qdev-dma.h"
35f1ae32a1SGerd Hoffmann 
36f1ae32a1SGerd Hoffmann //#define DEBUG_OHCI
37f1ae32a1SGerd Hoffmann /* Dump packet contents.  */
38f1ae32a1SGerd Hoffmann //#define DEBUG_PACKET
39f1ae32a1SGerd Hoffmann //#define DEBUG_ISOCH
40f1ae32a1SGerd Hoffmann /* This causes frames to occur 1000x slower */
41f1ae32a1SGerd Hoffmann //#define OHCI_TIME_WARP 1
42f1ae32a1SGerd Hoffmann 
43f1ae32a1SGerd Hoffmann #ifdef DEBUG_OHCI
44f1ae32a1SGerd Hoffmann #define DPRINTF printf
45f1ae32a1SGerd Hoffmann #else
46f1ae32a1SGerd Hoffmann #define DPRINTF(...)
47f1ae32a1SGerd Hoffmann #endif
48f1ae32a1SGerd Hoffmann 
49f1ae32a1SGerd Hoffmann /* Number of Downstream Ports on the root hub.  */
50f1ae32a1SGerd Hoffmann 
51f1ae32a1SGerd Hoffmann #define OHCI_MAX_PORTS 15
52f1ae32a1SGerd Hoffmann 
53f1ae32a1SGerd Hoffmann static int64_t usb_frame_time;
54f1ae32a1SGerd Hoffmann static int64_t usb_bit_time;
55f1ae32a1SGerd Hoffmann 
56f1ae32a1SGerd Hoffmann typedef struct OHCIPort {
57f1ae32a1SGerd Hoffmann     USBPort port;
58f1ae32a1SGerd Hoffmann     uint32_t ctrl;
59f1ae32a1SGerd Hoffmann } OHCIPort;
60f1ae32a1SGerd Hoffmann 
61f1ae32a1SGerd Hoffmann typedef struct {
62f1ae32a1SGerd Hoffmann     USBBus bus;
63f1ae32a1SGerd Hoffmann     qemu_irq irq;
64f1ae32a1SGerd Hoffmann     MemoryRegion mem;
659ac6a217SDavid Gibson     DMAContext *dma;
66f1ae32a1SGerd Hoffmann     int num_ports;
67f1ae32a1SGerd Hoffmann     const char *name;
68f1ae32a1SGerd Hoffmann 
69f1ae32a1SGerd Hoffmann     QEMUTimer *eof_timer;
70f1ae32a1SGerd Hoffmann     int64_t sof_time;
71f1ae32a1SGerd Hoffmann 
72f1ae32a1SGerd Hoffmann     /* OHCI state */
73f1ae32a1SGerd Hoffmann     /* Control partition */
74f1ae32a1SGerd Hoffmann     uint32_t ctl, status;
75f1ae32a1SGerd Hoffmann     uint32_t intr_status;
76f1ae32a1SGerd Hoffmann     uint32_t intr;
77f1ae32a1SGerd Hoffmann 
78f1ae32a1SGerd Hoffmann     /* memory pointer partition */
79f1ae32a1SGerd Hoffmann     uint32_t hcca;
80f1ae32a1SGerd Hoffmann     uint32_t ctrl_head, ctrl_cur;
81f1ae32a1SGerd Hoffmann     uint32_t bulk_head, bulk_cur;
82f1ae32a1SGerd Hoffmann     uint32_t per_cur;
83f1ae32a1SGerd Hoffmann     uint32_t done;
84f1ae32a1SGerd Hoffmann     int done_count;
85f1ae32a1SGerd Hoffmann 
86f1ae32a1SGerd Hoffmann     /* Frame counter partition */
87f1ae32a1SGerd Hoffmann     uint32_t fsmps:15;
88f1ae32a1SGerd Hoffmann     uint32_t fit:1;
89f1ae32a1SGerd Hoffmann     uint32_t fi:14;
90f1ae32a1SGerd Hoffmann     uint32_t frt:1;
91f1ae32a1SGerd Hoffmann     uint16_t frame_number;
92f1ae32a1SGerd Hoffmann     uint16_t padding;
93f1ae32a1SGerd Hoffmann     uint32_t pstart;
94f1ae32a1SGerd Hoffmann     uint32_t lst;
95f1ae32a1SGerd Hoffmann 
96f1ae32a1SGerd Hoffmann     /* Root Hub partition */
97f1ae32a1SGerd Hoffmann     uint32_t rhdesc_a, rhdesc_b;
98f1ae32a1SGerd Hoffmann     uint32_t rhstatus;
99f1ae32a1SGerd Hoffmann     OHCIPort rhport[OHCI_MAX_PORTS];
100f1ae32a1SGerd Hoffmann 
101f1ae32a1SGerd Hoffmann     /* PXA27x Non-OHCI events */
102f1ae32a1SGerd Hoffmann     uint32_t hstatus;
103f1ae32a1SGerd Hoffmann     uint32_t hmask;
104f1ae32a1SGerd Hoffmann     uint32_t hreset;
105f1ae32a1SGerd Hoffmann     uint32_t htest;
106f1ae32a1SGerd Hoffmann 
107f1ae32a1SGerd Hoffmann     /* SM501 local memory offset */
1089ac6a217SDavid Gibson     dma_addr_t localmem_base;
109f1ae32a1SGerd Hoffmann 
110f1ae32a1SGerd Hoffmann     /* Active packets.  */
111f1ae32a1SGerd Hoffmann     uint32_t old_ctl;
112f1ae32a1SGerd Hoffmann     USBPacket usb_packet;
113f1ae32a1SGerd Hoffmann     uint8_t usb_buf[8192];
114f1ae32a1SGerd Hoffmann     uint32_t async_td;
115f1ae32a1SGerd Hoffmann     int async_complete;
116f1ae32a1SGerd Hoffmann 
117f1ae32a1SGerd Hoffmann } OHCIState;
118f1ae32a1SGerd Hoffmann 
119f1ae32a1SGerd Hoffmann /* Host Controller Communications Area */
120f1ae32a1SGerd Hoffmann struct ohci_hcca {
121f1ae32a1SGerd Hoffmann     uint32_t intr[32];
122f1ae32a1SGerd Hoffmann     uint16_t frame, pad;
123f1ae32a1SGerd Hoffmann     uint32_t done;
124f1ae32a1SGerd Hoffmann };
12586e18caeSWei Yang #define HCCA_WRITEBACK_OFFSET   offsetof(struct ohci_hcca, frame)
12686e18caeSWei Yang #define HCCA_WRITEBACK_SIZE     8 /* frame, pad, done */
12786e18caeSWei Yang 
12886e18caeSWei Yang #define ED_WBACK_OFFSET offsetof(struct ohci_ed, head)
12986e18caeSWei Yang #define ED_WBACK_SIZE   4
130f1ae32a1SGerd Hoffmann 
131f1ae32a1SGerd Hoffmann static void ohci_bus_stop(OHCIState *ohci);
132f1ae32a1SGerd Hoffmann static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev);
133f1ae32a1SGerd Hoffmann 
134f1ae32a1SGerd Hoffmann /* Bitfields for the first word of an Endpoint Desciptor.  */
135f1ae32a1SGerd Hoffmann #define OHCI_ED_FA_SHIFT  0
136f1ae32a1SGerd Hoffmann #define OHCI_ED_FA_MASK   (0x7f<<OHCI_ED_FA_SHIFT)
137f1ae32a1SGerd Hoffmann #define OHCI_ED_EN_SHIFT  7
138f1ae32a1SGerd Hoffmann #define OHCI_ED_EN_MASK   (0xf<<OHCI_ED_EN_SHIFT)
139f1ae32a1SGerd Hoffmann #define OHCI_ED_D_SHIFT   11
140f1ae32a1SGerd Hoffmann #define OHCI_ED_D_MASK    (3<<OHCI_ED_D_SHIFT)
141f1ae32a1SGerd Hoffmann #define OHCI_ED_S         (1<<13)
142f1ae32a1SGerd Hoffmann #define OHCI_ED_K         (1<<14)
143f1ae32a1SGerd Hoffmann #define OHCI_ED_F         (1<<15)
144f1ae32a1SGerd Hoffmann #define OHCI_ED_MPS_SHIFT 16
145f1ae32a1SGerd Hoffmann #define OHCI_ED_MPS_MASK  (0x7ff<<OHCI_ED_MPS_SHIFT)
146f1ae32a1SGerd Hoffmann 
147f1ae32a1SGerd Hoffmann /* Flags in the head field of an Endpoint Desciptor.  */
148f1ae32a1SGerd Hoffmann #define OHCI_ED_H         1
149f1ae32a1SGerd Hoffmann #define OHCI_ED_C         2
150f1ae32a1SGerd Hoffmann 
151f1ae32a1SGerd Hoffmann /* Bitfields for the first word of a Transfer Desciptor.  */
152f1ae32a1SGerd Hoffmann #define OHCI_TD_R         (1<<18)
153f1ae32a1SGerd Hoffmann #define OHCI_TD_DP_SHIFT  19
154f1ae32a1SGerd Hoffmann #define OHCI_TD_DP_MASK   (3<<OHCI_TD_DP_SHIFT)
155f1ae32a1SGerd Hoffmann #define OHCI_TD_DI_SHIFT  21
156f1ae32a1SGerd Hoffmann #define OHCI_TD_DI_MASK   (7<<OHCI_TD_DI_SHIFT)
157f1ae32a1SGerd Hoffmann #define OHCI_TD_T0        (1<<24)
158f1ae32a1SGerd Hoffmann #define OHCI_TD_T1        (1<<25)
159f1ae32a1SGerd Hoffmann #define OHCI_TD_EC_SHIFT  26
160f1ae32a1SGerd Hoffmann #define OHCI_TD_EC_MASK   (3<<OHCI_TD_EC_SHIFT)
161f1ae32a1SGerd Hoffmann #define OHCI_TD_CC_SHIFT  28
162f1ae32a1SGerd Hoffmann #define OHCI_TD_CC_MASK   (0xf<<OHCI_TD_CC_SHIFT)
163f1ae32a1SGerd Hoffmann 
164f1ae32a1SGerd Hoffmann /* Bitfields for the first word of an Isochronous Transfer Desciptor.  */
165f1ae32a1SGerd Hoffmann /* CC & DI - same as in the General Transfer Desciptor */
166f1ae32a1SGerd Hoffmann #define OHCI_TD_SF_SHIFT  0
167f1ae32a1SGerd Hoffmann #define OHCI_TD_SF_MASK   (0xffff<<OHCI_TD_SF_SHIFT)
168f1ae32a1SGerd Hoffmann #define OHCI_TD_FC_SHIFT  24
169f1ae32a1SGerd Hoffmann #define OHCI_TD_FC_MASK   (7<<OHCI_TD_FC_SHIFT)
170f1ae32a1SGerd Hoffmann 
171f1ae32a1SGerd Hoffmann /* Isochronous Transfer Desciptor - Offset / PacketStatusWord */
172f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_CC_SHIFT 12
173f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_CC_MASK  (0xf<<OHCI_TD_PSW_CC_SHIFT)
174f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_SIZE_SHIFT 0
175f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_SIZE_MASK  (0xfff<<OHCI_TD_PSW_SIZE_SHIFT)
176f1ae32a1SGerd Hoffmann 
177f1ae32a1SGerd Hoffmann #define OHCI_PAGE_MASK    0xfffff000
178f1ae32a1SGerd Hoffmann #define OHCI_OFFSET_MASK  0xfff
179f1ae32a1SGerd Hoffmann 
180f1ae32a1SGerd Hoffmann #define OHCI_DPTR_MASK    0xfffffff0
181f1ae32a1SGerd Hoffmann 
182f1ae32a1SGerd Hoffmann #define OHCI_BM(val, field) \
183f1ae32a1SGerd Hoffmann   (((val) & OHCI_##field##_MASK) >> OHCI_##field##_SHIFT)
184f1ae32a1SGerd Hoffmann 
185f1ae32a1SGerd Hoffmann #define OHCI_SET_BM(val, field, newval) do { \
186f1ae32a1SGerd Hoffmann     val &= ~OHCI_##field##_MASK; \
187f1ae32a1SGerd Hoffmann     val |= ((newval) << OHCI_##field##_SHIFT) & OHCI_##field##_MASK; \
188f1ae32a1SGerd Hoffmann     } while(0)
189f1ae32a1SGerd Hoffmann 
190f1ae32a1SGerd Hoffmann /* endpoint descriptor */
191f1ae32a1SGerd Hoffmann struct ohci_ed {
192f1ae32a1SGerd Hoffmann     uint32_t flags;
193f1ae32a1SGerd Hoffmann     uint32_t tail;
194f1ae32a1SGerd Hoffmann     uint32_t head;
195f1ae32a1SGerd Hoffmann     uint32_t next;
196f1ae32a1SGerd Hoffmann };
197f1ae32a1SGerd Hoffmann 
198f1ae32a1SGerd Hoffmann /* General transfer descriptor */
199f1ae32a1SGerd Hoffmann struct ohci_td {
200f1ae32a1SGerd Hoffmann     uint32_t flags;
201f1ae32a1SGerd Hoffmann     uint32_t cbp;
202f1ae32a1SGerd Hoffmann     uint32_t next;
203f1ae32a1SGerd Hoffmann     uint32_t be;
204f1ae32a1SGerd Hoffmann };
205f1ae32a1SGerd Hoffmann 
206f1ae32a1SGerd Hoffmann /* Isochronous transfer descriptor */
207f1ae32a1SGerd Hoffmann struct ohci_iso_td {
208f1ae32a1SGerd Hoffmann     uint32_t flags;
209f1ae32a1SGerd Hoffmann     uint32_t bp;
210f1ae32a1SGerd Hoffmann     uint32_t next;
211f1ae32a1SGerd Hoffmann     uint32_t be;
212f1ae32a1SGerd Hoffmann     uint16_t offset[8];
213f1ae32a1SGerd Hoffmann };
214f1ae32a1SGerd Hoffmann 
215f1ae32a1SGerd Hoffmann #define USB_HZ                      12000000
216f1ae32a1SGerd Hoffmann 
217f1ae32a1SGerd Hoffmann /* OHCI Local stuff */
218f1ae32a1SGerd Hoffmann #define OHCI_CTL_CBSR         ((1<<0)|(1<<1))
219f1ae32a1SGerd Hoffmann #define OHCI_CTL_PLE          (1<<2)
220f1ae32a1SGerd Hoffmann #define OHCI_CTL_IE           (1<<3)
221f1ae32a1SGerd Hoffmann #define OHCI_CTL_CLE          (1<<4)
222f1ae32a1SGerd Hoffmann #define OHCI_CTL_BLE          (1<<5)
223f1ae32a1SGerd Hoffmann #define OHCI_CTL_HCFS         ((1<<6)|(1<<7))
224f1ae32a1SGerd Hoffmann #define  OHCI_USB_RESET       0x00
225f1ae32a1SGerd Hoffmann #define  OHCI_USB_RESUME      0x40
226f1ae32a1SGerd Hoffmann #define  OHCI_USB_OPERATIONAL 0x80
227f1ae32a1SGerd Hoffmann #define  OHCI_USB_SUSPEND     0xc0
228f1ae32a1SGerd Hoffmann #define OHCI_CTL_IR           (1<<8)
229f1ae32a1SGerd Hoffmann #define OHCI_CTL_RWC          (1<<9)
230f1ae32a1SGerd Hoffmann #define OHCI_CTL_RWE          (1<<10)
231f1ae32a1SGerd Hoffmann 
232f1ae32a1SGerd Hoffmann #define OHCI_STATUS_HCR       (1<<0)
233f1ae32a1SGerd Hoffmann #define OHCI_STATUS_CLF       (1<<1)
234f1ae32a1SGerd Hoffmann #define OHCI_STATUS_BLF       (1<<2)
235f1ae32a1SGerd Hoffmann #define OHCI_STATUS_OCR       (1<<3)
236f1ae32a1SGerd Hoffmann #define OHCI_STATUS_SOC       ((1<<6)|(1<<7))
237f1ae32a1SGerd Hoffmann 
238f1ae32a1SGerd Hoffmann #define OHCI_INTR_SO          (1<<0) /* Scheduling overrun */
239f1ae32a1SGerd Hoffmann #define OHCI_INTR_WD          (1<<1) /* HcDoneHead writeback */
240f1ae32a1SGerd Hoffmann #define OHCI_INTR_SF          (1<<2) /* Start of frame */
241f1ae32a1SGerd Hoffmann #define OHCI_INTR_RD          (1<<3) /* Resume detect */
242f1ae32a1SGerd Hoffmann #define OHCI_INTR_UE          (1<<4) /* Unrecoverable error */
243f1ae32a1SGerd Hoffmann #define OHCI_INTR_FNO         (1<<5) /* Frame number overflow */
244f1ae32a1SGerd Hoffmann #define OHCI_INTR_RHSC        (1<<6) /* Root hub status change */
245f1ae32a1SGerd Hoffmann #define OHCI_INTR_OC          (1<<30) /* Ownership change */
246f1ae32a1SGerd Hoffmann #define OHCI_INTR_MIE         (1<<31) /* Master Interrupt Enable */
247f1ae32a1SGerd Hoffmann 
248f1ae32a1SGerd Hoffmann #define OHCI_HCCA_SIZE        0x100
249f1ae32a1SGerd Hoffmann #define OHCI_HCCA_MASK        0xffffff00
250f1ae32a1SGerd Hoffmann 
251f1ae32a1SGerd Hoffmann #define OHCI_EDPTR_MASK       0xfffffff0
252f1ae32a1SGerd Hoffmann 
253f1ae32a1SGerd Hoffmann #define OHCI_FMI_FI           0x00003fff
254f1ae32a1SGerd Hoffmann #define OHCI_FMI_FSMPS        0xffff0000
255f1ae32a1SGerd Hoffmann #define OHCI_FMI_FIT          0x80000000
256f1ae32a1SGerd Hoffmann 
257f1ae32a1SGerd Hoffmann #define OHCI_FR_RT            (1<<31)
258f1ae32a1SGerd Hoffmann 
259f1ae32a1SGerd Hoffmann #define OHCI_LS_THRESH        0x628
260f1ae32a1SGerd Hoffmann 
261f1ae32a1SGerd Hoffmann #define OHCI_RHA_RW_MASK      0x00000000 /* Mask of supported features.  */
262f1ae32a1SGerd Hoffmann #define OHCI_RHA_PSM          (1<<8)
263f1ae32a1SGerd Hoffmann #define OHCI_RHA_NPS          (1<<9)
264f1ae32a1SGerd Hoffmann #define OHCI_RHA_DT           (1<<10)
265f1ae32a1SGerd Hoffmann #define OHCI_RHA_OCPM         (1<<11)
266f1ae32a1SGerd Hoffmann #define OHCI_RHA_NOCP         (1<<12)
267f1ae32a1SGerd Hoffmann #define OHCI_RHA_POTPGT_MASK  0xff000000
268f1ae32a1SGerd Hoffmann 
269f1ae32a1SGerd Hoffmann #define OHCI_RHS_LPS          (1<<0)
270f1ae32a1SGerd Hoffmann #define OHCI_RHS_OCI          (1<<1)
271f1ae32a1SGerd Hoffmann #define OHCI_RHS_DRWE         (1<<15)
272f1ae32a1SGerd Hoffmann #define OHCI_RHS_LPSC         (1<<16)
273f1ae32a1SGerd Hoffmann #define OHCI_RHS_OCIC         (1<<17)
274f1ae32a1SGerd Hoffmann #define OHCI_RHS_CRWE         (1<<31)
275f1ae32a1SGerd Hoffmann 
276f1ae32a1SGerd Hoffmann #define OHCI_PORT_CCS         (1<<0)
277f1ae32a1SGerd Hoffmann #define OHCI_PORT_PES         (1<<1)
278f1ae32a1SGerd Hoffmann #define OHCI_PORT_PSS         (1<<2)
279f1ae32a1SGerd Hoffmann #define OHCI_PORT_POCI        (1<<3)
280f1ae32a1SGerd Hoffmann #define OHCI_PORT_PRS         (1<<4)
281f1ae32a1SGerd Hoffmann #define OHCI_PORT_PPS         (1<<8)
282f1ae32a1SGerd Hoffmann #define OHCI_PORT_LSDA        (1<<9)
283f1ae32a1SGerd Hoffmann #define OHCI_PORT_CSC         (1<<16)
284f1ae32a1SGerd Hoffmann #define OHCI_PORT_PESC        (1<<17)
285f1ae32a1SGerd Hoffmann #define OHCI_PORT_PSSC        (1<<18)
286f1ae32a1SGerd Hoffmann #define OHCI_PORT_OCIC        (1<<19)
287f1ae32a1SGerd Hoffmann #define OHCI_PORT_PRSC        (1<<20)
288f1ae32a1SGerd Hoffmann #define OHCI_PORT_WTC         (OHCI_PORT_CSC|OHCI_PORT_PESC|OHCI_PORT_PSSC \
289f1ae32a1SGerd Hoffmann                                |OHCI_PORT_OCIC|OHCI_PORT_PRSC)
290f1ae32a1SGerd Hoffmann 
291f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_SETUP     0x0
292f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_OUT       0x1
293f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_IN        0x2
294f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_RESERVED  0x3
295f1ae32a1SGerd Hoffmann 
296f1ae32a1SGerd Hoffmann #define OHCI_CC_NOERROR             0x0
297f1ae32a1SGerd Hoffmann #define OHCI_CC_CRC                 0x1
298f1ae32a1SGerd Hoffmann #define OHCI_CC_BITSTUFFING         0x2
299f1ae32a1SGerd Hoffmann #define OHCI_CC_DATATOGGLEMISMATCH  0x3
300f1ae32a1SGerd Hoffmann #define OHCI_CC_STALL               0x4
301f1ae32a1SGerd Hoffmann #define OHCI_CC_DEVICENOTRESPONDING 0x5
302f1ae32a1SGerd Hoffmann #define OHCI_CC_PIDCHECKFAILURE     0x6
303f1ae32a1SGerd Hoffmann #define OHCI_CC_UNDEXPETEDPID       0x7
304f1ae32a1SGerd Hoffmann #define OHCI_CC_DATAOVERRUN         0x8
305f1ae32a1SGerd Hoffmann #define OHCI_CC_DATAUNDERRUN        0x9
306f1ae32a1SGerd Hoffmann #define OHCI_CC_BUFFEROVERRUN       0xc
307f1ae32a1SGerd Hoffmann #define OHCI_CC_BUFFERUNDERRUN      0xd
308f1ae32a1SGerd Hoffmann 
309f1ae32a1SGerd Hoffmann #define OHCI_HRESET_FSBIR       (1 << 0)
310f1ae32a1SGerd Hoffmann 
311f1ae32a1SGerd Hoffmann /* Update IRQ levels */
312f1ae32a1SGerd Hoffmann static inline void ohci_intr_update(OHCIState *ohci)
313f1ae32a1SGerd Hoffmann {
314f1ae32a1SGerd Hoffmann     int level = 0;
315f1ae32a1SGerd Hoffmann 
316f1ae32a1SGerd Hoffmann     if ((ohci->intr & OHCI_INTR_MIE) &&
317f1ae32a1SGerd Hoffmann         (ohci->intr_status & ohci->intr))
318f1ae32a1SGerd Hoffmann         level = 1;
319f1ae32a1SGerd Hoffmann 
320f1ae32a1SGerd Hoffmann     qemu_set_irq(ohci->irq, level);
321f1ae32a1SGerd Hoffmann }
322f1ae32a1SGerd Hoffmann 
323f1ae32a1SGerd Hoffmann /* Set an interrupt */
324f1ae32a1SGerd Hoffmann static inline void ohci_set_interrupt(OHCIState *ohci, uint32_t intr)
325f1ae32a1SGerd Hoffmann {
326f1ae32a1SGerd Hoffmann     ohci->intr_status |= intr;
327f1ae32a1SGerd Hoffmann     ohci_intr_update(ohci);
328f1ae32a1SGerd Hoffmann }
329f1ae32a1SGerd Hoffmann 
330f1ae32a1SGerd Hoffmann /* Attach or detach a device on a root hub port.  */
331f1ae32a1SGerd Hoffmann static void ohci_attach(USBPort *port1)
332f1ae32a1SGerd Hoffmann {
333f1ae32a1SGerd Hoffmann     OHCIState *s = port1->opaque;
334f1ae32a1SGerd Hoffmann     OHCIPort *port = &s->rhport[port1->index];
335f1ae32a1SGerd Hoffmann     uint32_t old_state = port->ctrl;
336f1ae32a1SGerd Hoffmann 
337f1ae32a1SGerd Hoffmann     /* set connect status */
338f1ae32a1SGerd Hoffmann     port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;
339f1ae32a1SGerd Hoffmann 
340f1ae32a1SGerd Hoffmann     /* update speed */
341f1ae32a1SGerd Hoffmann     if (port->port.dev->speed == USB_SPEED_LOW) {
342f1ae32a1SGerd Hoffmann         port->ctrl |= OHCI_PORT_LSDA;
343f1ae32a1SGerd Hoffmann     } else {
344f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_LSDA;
345f1ae32a1SGerd Hoffmann     }
346f1ae32a1SGerd Hoffmann 
347f1ae32a1SGerd Hoffmann     /* notify of remote-wakeup */
348f1ae32a1SGerd Hoffmann     if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
349f1ae32a1SGerd Hoffmann         ohci_set_interrupt(s, OHCI_INTR_RD);
350f1ae32a1SGerd Hoffmann     }
351f1ae32a1SGerd Hoffmann 
352f1ae32a1SGerd Hoffmann     DPRINTF("usb-ohci: Attached port %d\n", port1->index);
353f1ae32a1SGerd Hoffmann 
354f1ae32a1SGerd Hoffmann     if (old_state != port->ctrl) {
355f1ae32a1SGerd Hoffmann         ohci_set_interrupt(s, OHCI_INTR_RHSC);
356f1ae32a1SGerd Hoffmann     }
357f1ae32a1SGerd Hoffmann }
358f1ae32a1SGerd Hoffmann 
359f1ae32a1SGerd Hoffmann static void ohci_detach(USBPort *port1)
360f1ae32a1SGerd Hoffmann {
361f1ae32a1SGerd Hoffmann     OHCIState *s = port1->opaque;
362f1ae32a1SGerd Hoffmann     OHCIPort *port = &s->rhport[port1->index];
363f1ae32a1SGerd Hoffmann     uint32_t old_state = port->ctrl;
364f1ae32a1SGerd Hoffmann 
365f1ae32a1SGerd Hoffmann     ohci_async_cancel_device(s, port1->dev);
366f1ae32a1SGerd Hoffmann 
367f1ae32a1SGerd Hoffmann     /* set connect status */
368f1ae32a1SGerd Hoffmann     if (port->ctrl & OHCI_PORT_CCS) {
369f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_CCS;
370f1ae32a1SGerd Hoffmann         port->ctrl |= OHCI_PORT_CSC;
371f1ae32a1SGerd Hoffmann     }
372f1ae32a1SGerd Hoffmann     /* disable port */
373f1ae32a1SGerd Hoffmann     if (port->ctrl & OHCI_PORT_PES) {
374f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_PES;
375f1ae32a1SGerd Hoffmann         port->ctrl |= OHCI_PORT_PESC;
376f1ae32a1SGerd Hoffmann     }
377f1ae32a1SGerd Hoffmann     DPRINTF("usb-ohci: Detached port %d\n", port1->index);
378f1ae32a1SGerd Hoffmann 
379f1ae32a1SGerd Hoffmann     if (old_state != port->ctrl) {
380f1ae32a1SGerd Hoffmann         ohci_set_interrupt(s, OHCI_INTR_RHSC);
381f1ae32a1SGerd Hoffmann     }
382f1ae32a1SGerd Hoffmann }
383f1ae32a1SGerd Hoffmann 
384f1ae32a1SGerd Hoffmann static void ohci_wakeup(USBPort *port1)
385f1ae32a1SGerd Hoffmann {
386f1ae32a1SGerd Hoffmann     OHCIState *s = port1->opaque;
387f1ae32a1SGerd Hoffmann     OHCIPort *port = &s->rhport[port1->index];
388f1ae32a1SGerd Hoffmann     uint32_t intr = 0;
389f1ae32a1SGerd Hoffmann     if (port->ctrl & OHCI_PORT_PSS) {
390f1ae32a1SGerd Hoffmann         DPRINTF("usb-ohci: port %d: wakeup\n", port1->index);
391f1ae32a1SGerd Hoffmann         port->ctrl |= OHCI_PORT_PSSC;
392f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_PSS;
393f1ae32a1SGerd Hoffmann         intr = OHCI_INTR_RHSC;
394f1ae32a1SGerd Hoffmann     }
395f1ae32a1SGerd Hoffmann     /* Note that the controller can be suspended even if this port is not */
396f1ae32a1SGerd Hoffmann     if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
397f1ae32a1SGerd Hoffmann         DPRINTF("usb-ohci: remote-wakeup: SUSPEND->RESUME\n");
398f1ae32a1SGerd Hoffmann         /* This is the one state transition the controller can do by itself */
399f1ae32a1SGerd Hoffmann         s->ctl &= ~OHCI_CTL_HCFS;
400f1ae32a1SGerd Hoffmann         s->ctl |= OHCI_USB_RESUME;
401f1ae32a1SGerd Hoffmann         /* In suspend mode only ResumeDetected is possible, not RHSC:
402f1ae32a1SGerd Hoffmann          * see the OHCI spec 5.1.2.3.
403f1ae32a1SGerd Hoffmann          */
404f1ae32a1SGerd Hoffmann         intr = OHCI_INTR_RD;
405f1ae32a1SGerd Hoffmann     }
406f1ae32a1SGerd Hoffmann     ohci_set_interrupt(s, intr);
407f1ae32a1SGerd Hoffmann }
408f1ae32a1SGerd Hoffmann 
409f1ae32a1SGerd Hoffmann static void ohci_child_detach(USBPort *port1, USBDevice *child)
410f1ae32a1SGerd Hoffmann {
411f1ae32a1SGerd Hoffmann     OHCIState *s = port1->opaque;
412f1ae32a1SGerd Hoffmann 
413f1ae32a1SGerd Hoffmann     ohci_async_cancel_device(s, child);
414f1ae32a1SGerd Hoffmann }
415f1ae32a1SGerd Hoffmann 
416f1ae32a1SGerd Hoffmann static USBDevice *ohci_find_device(OHCIState *ohci, uint8_t addr)
417f1ae32a1SGerd Hoffmann {
418f1ae32a1SGerd Hoffmann     USBDevice *dev;
419f1ae32a1SGerd Hoffmann     int i;
420f1ae32a1SGerd Hoffmann 
421f1ae32a1SGerd Hoffmann     for (i = 0; i < ohci->num_ports; i++) {
422f1ae32a1SGerd Hoffmann         if ((ohci->rhport[i].ctrl & OHCI_PORT_PES) == 0) {
423f1ae32a1SGerd Hoffmann             continue;
424f1ae32a1SGerd Hoffmann         }
425f1ae32a1SGerd Hoffmann         dev = usb_find_device(&ohci->rhport[i].port, addr);
426f1ae32a1SGerd Hoffmann         if (dev != NULL) {
427f1ae32a1SGerd Hoffmann             return dev;
428f1ae32a1SGerd Hoffmann         }
429f1ae32a1SGerd Hoffmann     }
430f1ae32a1SGerd Hoffmann     return NULL;
431f1ae32a1SGerd Hoffmann }
432f1ae32a1SGerd Hoffmann 
433f79738b0SHans de Goede static void ohci_stop_endpoints(OHCIState *ohci)
434f79738b0SHans de Goede {
435f79738b0SHans de Goede     USBDevice *dev;
436f79738b0SHans de Goede     int i, j;
437f79738b0SHans de Goede 
438f79738b0SHans de Goede     for (i = 0; i < ohci->num_ports; i++) {
439f79738b0SHans de Goede         dev = ohci->rhport[i].port.dev;
440f79738b0SHans de Goede         if (dev && dev->attached) {
441f79738b0SHans de Goede             usb_device_ep_stopped(dev, &dev->ep_ctl);
442f79738b0SHans de Goede             for (j = 0; j < USB_MAX_ENDPOINTS; j++) {
443f79738b0SHans de Goede                 usb_device_ep_stopped(dev, &dev->ep_in[j]);
444f79738b0SHans de Goede                 usb_device_ep_stopped(dev, &dev->ep_out[j]);
445f79738b0SHans de Goede             }
446f79738b0SHans de Goede         }
447f79738b0SHans de Goede     }
448f79738b0SHans de Goede }
449f79738b0SHans de Goede 
450f1ae32a1SGerd Hoffmann /* Reset the controller */
451f1ae32a1SGerd Hoffmann static void ohci_reset(void *opaque)
452f1ae32a1SGerd Hoffmann {
453f1ae32a1SGerd Hoffmann     OHCIState *ohci = opaque;
454f1ae32a1SGerd Hoffmann     OHCIPort *port;
455f1ae32a1SGerd Hoffmann     int i;
456f1ae32a1SGerd Hoffmann 
457f1ae32a1SGerd Hoffmann     ohci_bus_stop(ohci);
458f1ae32a1SGerd Hoffmann     ohci->ctl = 0;
459f1ae32a1SGerd Hoffmann     ohci->old_ctl = 0;
460f1ae32a1SGerd Hoffmann     ohci->status = 0;
461f1ae32a1SGerd Hoffmann     ohci->intr_status = 0;
462f1ae32a1SGerd Hoffmann     ohci->intr = OHCI_INTR_MIE;
463f1ae32a1SGerd Hoffmann 
464f1ae32a1SGerd Hoffmann     ohci->hcca = 0;
465f1ae32a1SGerd Hoffmann     ohci->ctrl_head = ohci->ctrl_cur = 0;
466f1ae32a1SGerd Hoffmann     ohci->bulk_head = ohci->bulk_cur = 0;
467f1ae32a1SGerd Hoffmann     ohci->per_cur = 0;
468f1ae32a1SGerd Hoffmann     ohci->done = 0;
469f1ae32a1SGerd Hoffmann     ohci->done_count = 7;
470f1ae32a1SGerd Hoffmann 
471f1ae32a1SGerd Hoffmann     /* FSMPS is marked TBD in OCHI 1.0, what gives ffs?
472f1ae32a1SGerd Hoffmann      * I took the value linux sets ...
473f1ae32a1SGerd Hoffmann      */
474f1ae32a1SGerd Hoffmann     ohci->fsmps = 0x2778;
475f1ae32a1SGerd Hoffmann     ohci->fi = 0x2edf;
476f1ae32a1SGerd Hoffmann     ohci->fit = 0;
477f1ae32a1SGerd Hoffmann     ohci->frt = 0;
478f1ae32a1SGerd Hoffmann     ohci->frame_number = 0;
479f1ae32a1SGerd Hoffmann     ohci->pstart = 0;
480f1ae32a1SGerd Hoffmann     ohci->lst = OHCI_LS_THRESH;
481f1ae32a1SGerd Hoffmann 
482f1ae32a1SGerd Hoffmann     ohci->rhdesc_a = OHCI_RHA_NPS | ohci->num_ports;
483f1ae32a1SGerd Hoffmann     ohci->rhdesc_b = 0x0; /* Impl. specific */
484f1ae32a1SGerd Hoffmann     ohci->rhstatus = 0;
485f1ae32a1SGerd Hoffmann 
486f1ae32a1SGerd Hoffmann     for (i = 0; i < ohci->num_ports; i++)
487f1ae32a1SGerd Hoffmann       {
488f1ae32a1SGerd Hoffmann         port = &ohci->rhport[i];
489f1ae32a1SGerd Hoffmann         port->ctrl = 0;
490f1ae32a1SGerd Hoffmann         if (port->port.dev && port->port.dev->attached) {
491f1ae32a1SGerd Hoffmann             usb_port_reset(&port->port);
492f1ae32a1SGerd Hoffmann         }
493f1ae32a1SGerd Hoffmann       }
494f1ae32a1SGerd Hoffmann     if (ohci->async_td) {
495f1ae32a1SGerd Hoffmann         usb_cancel_packet(&ohci->usb_packet);
496f1ae32a1SGerd Hoffmann         ohci->async_td = 0;
497f1ae32a1SGerd Hoffmann     }
498f79738b0SHans de Goede     ohci_stop_endpoints(ohci);
499f1ae32a1SGerd Hoffmann     DPRINTF("usb-ohci: Reset %s\n", ohci->name);
500f1ae32a1SGerd Hoffmann }
501f1ae32a1SGerd Hoffmann 
502f1ae32a1SGerd Hoffmann /* Get an array of dwords from main memory */
503f1ae32a1SGerd Hoffmann static inline int get_dwords(OHCIState *ohci,
5049ac6a217SDavid Gibson                              dma_addr_t addr, uint32_t *buf, int num)
505f1ae32a1SGerd Hoffmann {
506f1ae32a1SGerd Hoffmann     int i;
507f1ae32a1SGerd Hoffmann 
508f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
509f1ae32a1SGerd Hoffmann 
510f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
5119ac6a217SDavid Gibson         dma_memory_read(ohci->dma, addr, buf, sizeof(*buf));
512f1ae32a1SGerd Hoffmann         *buf = le32_to_cpu(*buf);
513f1ae32a1SGerd Hoffmann     }
514f1ae32a1SGerd Hoffmann 
515f1ae32a1SGerd Hoffmann     return 1;
516f1ae32a1SGerd Hoffmann }
517f1ae32a1SGerd Hoffmann 
518f1ae32a1SGerd Hoffmann /* Put an array of dwords in to main memory */
519f1ae32a1SGerd Hoffmann static inline int put_dwords(OHCIState *ohci,
5209ac6a217SDavid Gibson                              dma_addr_t addr, uint32_t *buf, int num)
521f1ae32a1SGerd Hoffmann {
522f1ae32a1SGerd Hoffmann     int i;
523f1ae32a1SGerd Hoffmann 
524f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
525f1ae32a1SGerd Hoffmann 
526f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
527f1ae32a1SGerd Hoffmann         uint32_t tmp = cpu_to_le32(*buf);
5289ac6a217SDavid Gibson         dma_memory_write(ohci->dma, addr, &tmp, sizeof(tmp));
529f1ae32a1SGerd Hoffmann     }
530f1ae32a1SGerd Hoffmann 
531f1ae32a1SGerd Hoffmann     return 1;
532f1ae32a1SGerd Hoffmann }
533f1ae32a1SGerd Hoffmann 
534f1ae32a1SGerd Hoffmann /* Get an array of words from main memory */
535f1ae32a1SGerd Hoffmann static inline int get_words(OHCIState *ohci,
5369ac6a217SDavid Gibson                             dma_addr_t addr, uint16_t *buf, int num)
537f1ae32a1SGerd Hoffmann {
538f1ae32a1SGerd Hoffmann     int i;
539f1ae32a1SGerd Hoffmann 
540f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
541f1ae32a1SGerd Hoffmann 
542f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
5439ac6a217SDavid Gibson         dma_memory_read(ohci->dma, addr, buf, sizeof(*buf));
544f1ae32a1SGerd Hoffmann         *buf = le16_to_cpu(*buf);
545f1ae32a1SGerd Hoffmann     }
546f1ae32a1SGerd Hoffmann 
547f1ae32a1SGerd Hoffmann     return 1;
548f1ae32a1SGerd Hoffmann }
549f1ae32a1SGerd Hoffmann 
550f1ae32a1SGerd Hoffmann /* Put an array of words in to main memory */
551f1ae32a1SGerd Hoffmann static inline int put_words(OHCIState *ohci,
5529ac6a217SDavid Gibson                             dma_addr_t addr, uint16_t *buf, int num)
553f1ae32a1SGerd Hoffmann {
554f1ae32a1SGerd Hoffmann     int i;
555f1ae32a1SGerd Hoffmann 
556f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
557f1ae32a1SGerd Hoffmann 
558f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
559f1ae32a1SGerd Hoffmann         uint16_t tmp = cpu_to_le16(*buf);
5609ac6a217SDavid Gibson         dma_memory_write(ohci->dma, addr, &tmp, sizeof(tmp));
561f1ae32a1SGerd Hoffmann     }
562f1ae32a1SGerd Hoffmann 
563f1ae32a1SGerd Hoffmann     return 1;
564f1ae32a1SGerd Hoffmann }
565f1ae32a1SGerd Hoffmann 
566f1ae32a1SGerd Hoffmann static inline int ohci_read_ed(OHCIState *ohci,
5679ac6a217SDavid Gibson                                dma_addr_t addr, struct ohci_ed *ed)
568f1ae32a1SGerd Hoffmann {
569f1ae32a1SGerd Hoffmann     return get_dwords(ohci, addr, (uint32_t *)ed, sizeof(*ed) >> 2);
570f1ae32a1SGerd Hoffmann }
571f1ae32a1SGerd Hoffmann 
572f1ae32a1SGerd Hoffmann static inline int ohci_read_td(OHCIState *ohci,
5739ac6a217SDavid Gibson                                dma_addr_t addr, struct ohci_td *td)
574f1ae32a1SGerd Hoffmann {
575f1ae32a1SGerd Hoffmann     return get_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2);
576f1ae32a1SGerd Hoffmann }
577f1ae32a1SGerd Hoffmann 
578f1ae32a1SGerd Hoffmann static inline int ohci_read_iso_td(OHCIState *ohci,
5799ac6a217SDavid Gibson                                    dma_addr_t addr, struct ohci_iso_td *td)
580f1ae32a1SGerd Hoffmann {
581f1ae32a1SGerd Hoffmann     return (get_dwords(ohci, addr, (uint32_t *)td, 4) &&
582f1ae32a1SGerd Hoffmann             get_words(ohci, addr + 16, td->offset, 8));
583f1ae32a1SGerd Hoffmann }
584f1ae32a1SGerd Hoffmann 
585f1ae32a1SGerd Hoffmann static inline int ohci_read_hcca(OHCIState *ohci,
5869ac6a217SDavid Gibson                                  dma_addr_t addr, struct ohci_hcca *hcca)
587f1ae32a1SGerd Hoffmann {
5889ac6a217SDavid Gibson     dma_memory_read(ohci->dma, addr + ohci->localmem_base, hcca, sizeof(*hcca));
589f1ae32a1SGerd Hoffmann     return 1;
590f1ae32a1SGerd Hoffmann }
591f1ae32a1SGerd Hoffmann 
592f1ae32a1SGerd Hoffmann static inline int ohci_put_ed(OHCIState *ohci,
5939ac6a217SDavid Gibson                               dma_addr_t addr, struct ohci_ed *ed)
594f1ae32a1SGerd Hoffmann {
59586e18caeSWei Yang     /* ed->tail is under control of the HCD.
59686e18caeSWei Yang      * Since just ed->head is changed by HC, just write back this
59786e18caeSWei Yang      */
59886e18caeSWei Yang 
59986e18caeSWei Yang     return put_dwords(ohci, addr + ED_WBACK_OFFSET,
60086e18caeSWei Yang                       (uint32_t *)((char *)ed + ED_WBACK_OFFSET),
60186e18caeSWei Yang                       ED_WBACK_SIZE >> 2);
602f1ae32a1SGerd Hoffmann }
603f1ae32a1SGerd Hoffmann 
604f1ae32a1SGerd Hoffmann static inline int ohci_put_td(OHCIState *ohci,
6059ac6a217SDavid Gibson                               dma_addr_t addr, struct ohci_td *td)
606f1ae32a1SGerd Hoffmann {
607f1ae32a1SGerd Hoffmann     return put_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2);
608f1ae32a1SGerd Hoffmann }
609f1ae32a1SGerd Hoffmann 
610f1ae32a1SGerd Hoffmann static inline int ohci_put_iso_td(OHCIState *ohci,
6119ac6a217SDavid Gibson                                   dma_addr_t addr, struct ohci_iso_td *td)
612f1ae32a1SGerd Hoffmann {
613f1ae32a1SGerd Hoffmann     return (put_dwords(ohci, addr, (uint32_t *)td, 4) &&
614f1ae32a1SGerd Hoffmann             put_words(ohci, addr + 16, td->offset, 8));
615f1ae32a1SGerd Hoffmann }
616f1ae32a1SGerd Hoffmann 
617f1ae32a1SGerd Hoffmann static inline int ohci_put_hcca(OHCIState *ohci,
6189ac6a217SDavid Gibson                                 dma_addr_t addr, struct ohci_hcca *hcca)
619f1ae32a1SGerd Hoffmann {
6209ac6a217SDavid Gibson     dma_memory_write(ohci->dma,
6219ac6a217SDavid Gibson                      addr + ohci->localmem_base + HCCA_WRITEBACK_OFFSET,
62286e18caeSWei Yang                      (char *)hcca + HCCA_WRITEBACK_OFFSET,
62386e18caeSWei Yang                      HCCA_WRITEBACK_SIZE);
624f1ae32a1SGerd Hoffmann     return 1;
625f1ae32a1SGerd Hoffmann }
626f1ae32a1SGerd Hoffmann 
627f1ae32a1SGerd Hoffmann /* Read/Write the contents of a TD from/to main memory.  */
628f1ae32a1SGerd Hoffmann static void ohci_copy_td(OHCIState *ohci, struct ohci_td *td,
6299ac6a217SDavid Gibson                          uint8_t *buf, int len, DMADirection dir)
630f1ae32a1SGerd Hoffmann {
6319ac6a217SDavid Gibson     dma_addr_t ptr, n;
632f1ae32a1SGerd Hoffmann 
633f1ae32a1SGerd Hoffmann     ptr = td->cbp;
634f1ae32a1SGerd Hoffmann     n = 0x1000 - (ptr & 0xfff);
635f1ae32a1SGerd Hoffmann     if (n > len)
636f1ae32a1SGerd Hoffmann         n = len;
6379ac6a217SDavid Gibson     dma_memory_rw(ohci->dma, ptr + ohci->localmem_base, buf, n, dir);
638f1ae32a1SGerd Hoffmann     if (n == len)
639f1ae32a1SGerd Hoffmann         return;
640f1ae32a1SGerd Hoffmann     ptr = td->be & ~0xfffu;
641f1ae32a1SGerd Hoffmann     buf += n;
6429ac6a217SDavid Gibson     dma_memory_rw(ohci->dma, ptr + ohci->localmem_base, buf, len - n, dir);
643f1ae32a1SGerd Hoffmann }
644f1ae32a1SGerd Hoffmann 
645f1ae32a1SGerd Hoffmann /* Read/Write the contents of an ISO TD from/to main memory.  */
646f1ae32a1SGerd Hoffmann static void ohci_copy_iso_td(OHCIState *ohci,
647f1ae32a1SGerd Hoffmann                              uint32_t start_addr, uint32_t end_addr,
6489ac6a217SDavid Gibson                              uint8_t *buf, int len, DMADirection dir)
649f1ae32a1SGerd Hoffmann {
6509ac6a217SDavid Gibson     dma_addr_t ptr, n;
651f1ae32a1SGerd Hoffmann 
652f1ae32a1SGerd Hoffmann     ptr = start_addr;
653f1ae32a1SGerd Hoffmann     n = 0x1000 - (ptr & 0xfff);
654f1ae32a1SGerd Hoffmann     if (n > len)
655f1ae32a1SGerd Hoffmann         n = len;
6569ac6a217SDavid Gibson     dma_memory_rw(ohci->dma, ptr + ohci->localmem_base, buf, n, dir);
657f1ae32a1SGerd Hoffmann     if (n == len)
658f1ae32a1SGerd Hoffmann         return;
659f1ae32a1SGerd Hoffmann     ptr = end_addr & ~0xfffu;
660f1ae32a1SGerd Hoffmann     buf += n;
6619ac6a217SDavid Gibson     dma_memory_rw(ohci->dma, ptr + ohci->localmem_base, buf, len - n, dir);
662f1ae32a1SGerd Hoffmann }
663f1ae32a1SGerd Hoffmann 
664f1ae32a1SGerd Hoffmann static void ohci_process_lists(OHCIState *ohci, int completion);
665f1ae32a1SGerd Hoffmann 
666f1ae32a1SGerd Hoffmann static void ohci_async_complete_packet(USBPort *port, USBPacket *packet)
667f1ae32a1SGerd Hoffmann {
668f1ae32a1SGerd Hoffmann     OHCIState *ohci = container_of(packet, OHCIState, usb_packet);
669f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET
670f1ae32a1SGerd Hoffmann     DPRINTF("Async packet complete\n");
671f1ae32a1SGerd Hoffmann #endif
672f1ae32a1SGerd Hoffmann     ohci->async_complete = 1;
673f1ae32a1SGerd Hoffmann     ohci_process_lists(ohci, 1);
674f1ae32a1SGerd Hoffmann }
675f1ae32a1SGerd Hoffmann 
676f1ae32a1SGerd Hoffmann #define USUB(a, b) ((int16_t)((uint16_t)(a) - (uint16_t)(b)))
677f1ae32a1SGerd Hoffmann 
678f1ae32a1SGerd Hoffmann static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
679f1ae32a1SGerd Hoffmann                                int completion)
680f1ae32a1SGerd Hoffmann {
681f1ae32a1SGerd Hoffmann     int dir;
682f1ae32a1SGerd Hoffmann     size_t len = 0;
683f1ae32a1SGerd Hoffmann #ifdef DEBUG_ISOCH
684f1ae32a1SGerd Hoffmann     const char *str = NULL;
685f1ae32a1SGerd Hoffmann #endif
686f1ae32a1SGerd Hoffmann     int pid;
687f1ae32a1SGerd Hoffmann     int ret;
688f1ae32a1SGerd Hoffmann     int i;
689f1ae32a1SGerd Hoffmann     USBDevice *dev;
690f1ae32a1SGerd Hoffmann     USBEndpoint *ep;
691f1ae32a1SGerd Hoffmann     struct ohci_iso_td iso_td;
692f1ae32a1SGerd Hoffmann     uint32_t addr;
693f1ae32a1SGerd Hoffmann     uint16_t starting_frame;
694f1ae32a1SGerd Hoffmann     int16_t relative_frame_number;
695f1ae32a1SGerd Hoffmann     int frame_count;
696f1ae32a1SGerd Hoffmann     uint32_t start_offset, next_offset, end_offset = 0;
697f1ae32a1SGerd Hoffmann     uint32_t start_addr, end_addr;
698f1ae32a1SGerd Hoffmann 
699f1ae32a1SGerd Hoffmann     addr = ed->head & OHCI_DPTR_MASK;
700f1ae32a1SGerd Hoffmann 
701f1ae32a1SGerd Hoffmann     if (!ohci_read_iso_td(ohci, addr, &iso_td)) {
702f1ae32a1SGerd Hoffmann         printf("usb-ohci: ISO_TD read error at %x\n", addr);
703f1ae32a1SGerd Hoffmann         return 0;
704f1ae32a1SGerd Hoffmann     }
705f1ae32a1SGerd Hoffmann 
706f1ae32a1SGerd Hoffmann     starting_frame = OHCI_BM(iso_td.flags, TD_SF);
707f1ae32a1SGerd Hoffmann     frame_count = OHCI_BM(iso_td.flags, TD_FC);
708f1ae32a1SGerd Hoffmann     relative_frame_number = USUB(ohci->frame_number, starting_frame);
709f1ae32a1SGerd Hoffmann 
710f1ae32a1SGerd Hoffmann #ifdef DEBUG_ISOCH
711f1ae32a1SGerd Hoffmann     printf("--- ISO_TD ED head 0x%.8x tailp 0x%.8x\n"
712f1ae32a1SGerd Hoffmann            "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n"
713f1ae32a1SGerd Hoffmann            "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n"
714f1ae32a1SGerd Hoffmann            "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n"
715f1ae32a1SGerd Hoffmann            "frame_number 0x%.8x starting_frame 0x%.8x\n"
716f1ae32a1SGerd Hoffmann            "frame_count  0x%.8x relative %d\n"
717f1ae32a1SGerd Hoffmann            "di 0x%.8x cc 0x%.8x\n",
718f1ae32a1SGerd Hoffmann            ed->head & OHCI_DPTR_MASK, ed->tail & OHCI_DPTR_MASK,
719f1ae32a1SGerd Hoffmann            iso_td.flags, iso_td.bp, iso_td.next, iso_td.be,
720f1ae32a1SGerd Hoffmann            iso_td.offset[0], iso_td.offset[1], iso_td.offset[2], iso_td.offset[3],
721f1ae32a1SGerd Hoffmann            iso_td.offset[4], iso_td.offset[5], iso_td.offset[6], iso_td.offset[7],
722f1ae32a1SGerd Hoffmann            ohci->frame_number, starting_frame,
723f1ae32a1SGerd Hoffmann            frame_count, relative_frame_number,
724f1ae32a1SGerd Hoffmann            OHCI_BM(iso_td.flags, TD_DI), OHCI_BM(iso_td.flags, TD_CC));
725f1ae32a1SGerd Hoffmann #endif
726f1ae32a1SGerd Hoffmann 
727f1ae32a1SGerd Hoffmann     if (relative_frame_number < 0) {
728f1ae32a1SGerd Hoffmann         DPRINTF("usb-ohci: ISO_TD R=%d < 0\n", relative_frame_number);
729f1ae32a1SGerd Hoffmann         return 1;
730f1ae32a1SGerd Hoffmann     } else if (relative_frame_number > frame_count) {
731f1ae32a1SGerd Hoffmann         /* ISO TD expired - retire the TD to the Done Queue and continue with
732f1ae32a1SGerd Hoffmann            the next ISO TD of the same ED */
733f1ae32a1SGerd Hoffmann         DPRINTF("usb-ohci: ISO_TD R=%d > FC=%d\n", relative_frame_number,
734f1ae32a1SGerd Hoffmann                frame_count);
735f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_DATAOVERRUN);
736f1ae32a1SGerd Hoffmann         ed->head &= ~OHCI_DPTR_MASK;
737f1ae32a1SGerd Hoffmann         ed->head |= (iso_td.next & OHCI_DPTR_MASK);
738f1ae32a1SGerd Hoffmann         iso_td.next = ohci->done;
739f1ae32a1SGerd Hoffmann         ohci->done = addr;
740f1ae32a1SGerd Hoffmann         i = OHCI_BM(iso_td.flags, TD_DI);
741f1ae32a1SGerd Hoffmann         if (i < ohci->done_count)
742f1ae32a1SGerd Hoffmann             ohci->done_count = i;
743f1ae32a1SGerd Hoffmann         ohci_put_iso_td(ohci, addr, &iso_td);
744f1ae32a1SGerd Hoffmann         return 0;
745f1ae32a1SGerd Hoffmann     }
746f1ae32a1SGerd Hoffmann 
747f1ae32a1SGerd Hoffmann     dir = OHCI_BM(ed->flags, ED_D);
748f1ae32a1SGerd Hoffmann     switch (dir) {
749f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_IN:
750f1ae32a1SGerd Hoffmann #ifdef DEBUG_ISOCH
751f1ae32a1SGerd Hoffmann         str = "in";
752f1ae32a1SGerd Hoffmann #endif
753f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_IN;
754f1ae32a1SGerd Hoffmann         break;
755f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_OUT:
756f1ae32a1SGerd Hoffmann #ifdef DEBUG_ISOCH
757f1ae32a1SGerd Hoffmann         str = "out";
758f1ae32a1SGerd Hoffmann #endif
759f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_OUT;
760f1ae32a1SGerd Hoffmann         break;
761f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_SETUP:
762f1ae32a1SGerd Hoffmann #ifdef DEBUG_ISOCH
763f1ae32a1SGerd Hoffmann         str = "setup";
764f1ae32a1SGerd Hoffmann #endif
765f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_SETUP;
766f1ae32a1SGerd Hoffmann         break;
767f1ae32a1SGerd Hoffmann     default:
768f1ae32a1SGerd Hoffmann         printf("usb-ohci: Bad direction %d\n", dir);
769f1ae32a1SGerd Hoffmann         return 1;
770f1ae32a1SGerd Hoffmann     }
771f1ae32a1SGerd Hoffmann 
772f1ae32a1SGerd Hoffmann     if (!iso_td.bp || !iso_td.be) {
773f1ae32a1SGerd Hoffmann         printf("usb-ohci: ISO_TD bp 0x%.8x be 0x%.8x\n", iso_td.bp, iso_td.be);
774f1ae32a1SGerd Hoffmann         return 1;
775f1ae32a1SGerd Hoffmann     }
776f1ae32a1SGerd Hoffmann 
777f1ae32a1SGerd Hoffmann     start_offset = iso_td.offset[relative_frame_number];
778f1ae32a1SGerd Hoffmann     next_offset = iso_td.offset[relative_frame_number + 1];
779f1ae32a1SGerd Hoffmann 
780f1ae32a1SGerd Hoffmann     if (!(OHCI_BM(start_offset, TD_PSW_CC) & 0xe) ||
781f1ae32a1SGerd Hoffmann         ((relative_frame_number < frame_count) &&
782f1ae32a1SGerd Hoffmann          !(OHCI_BM(next_offset, TD_PSW_CC) & 0xe))) {
783f1ae32a1SGerd Hoffmann         printf("usb-ohci: ISO_TD cc != not accessed 0x%.8x 0x%.8x\n",
784f1ae32a1SGerd Hoffmann                start_offset, next_offset);
785f1ae32a1SGerd Hoffmann         return 1;
786f1ae32a1SGerd Hoffmann     }
787f1ae32a1SGerd Hoffmann 
788f1ae32a1SGerd Hoffmann     if ((relative_frame_number < frame_count) && (start_offset > next_offset)) {
789f1ae32a1SGerd Hoffmann         printf("usb-ohci: ISO_TD start_offset=0x%.8x > next_offset=0x%.8x\n",
790f1ae32a1SGerd Hoffmann                 start_offset, next_offset);
791f1ae32a1SGerd Hoffmann         return 1;
792f1ae32a1SGerd Hoffmann     }
793f1ae32a1SGerd Hoffmann 
794f1ae32a1SGerd Hoffmann     if ((start_offset & 0x1000) == 0) {
795f1ae32a1SGerd Hoffmann         start_addr = (iso_td.bp & OHCI_PAGE_MASK) |
796f1ae32a1SGerd Hoffmann             (start_offset & OHCI_OFFSET_MASK);
797f1ae32a1SGerd Hoffmann     } else {
798f1ae32a1SGerd Hoffmann         start_addr = (iso_td.be & OHCI_PAGE_MASK) |
799f1ae32a1SGerd Hoffmann             (start_offset & OHCI_OFFSET_MASK);
800f1ae32a1SGerd Hoffmann     }
801f1ae32a1SGerd Hoffmann 
802f1ae32a1SGerd Hoffmann     if (relative_frame_number < frame_count) {
803f1ae32a1SGerd Hoffmann         end_offset = next_offset - 1;
804f1ae32a1SGerd Hoffmann         if ((end_offset & 0x1000) == 0) {
805f1ae32a1SGerd Hoffmann             end_addr = (iso_td.bp & OHCI_PAGE_MASK) |
806f1ae32a1SGerd Hoffmann                 (end_offset & OHCI_OFFSET_MASK);
807f1ae32a1SGerd Hoffmann         } else {
808f1ae32a1SGerd Hoffmann             end_addr = (iso_td.be & OHCI_PAGE_MASK) |
809f1ae32a1SGerd Hoffmann                 (end_offset & OHCI_OFFSET_MASK);
810f1ae32a1SGerd Hoffmann         }
811f1ae32a1SGerd Hoffmann     } else {
812f1ae32a1SGerd Hoffmann         /* Last packet in the ISO TD */
813f1ae32a1SGerd Hoffmann         end_addr = iso_td.be;
814f1ae32a1SGerd Hoffmann     }
815f1ae32a1SGerd Hoffmann 
816f1ae32a1SGerd Hoffmann     if ((start_addr & OHCI_PAGE_MASK) != (end_addr & OHCI_PAGE_MASK)) {
817f1ae32a1SGerd Hoffmann         len = (end_addr & OHCI_OFFSET_MASK) + 0x1001
818f1ae32a1SGerd Hoffmann             - (start_addr & OHCI_OFFSET_MASK);
819f1ae32a1SGerd Hoffmann     } else {
820f1ae32a1SGerd Hoffmann         len = end_addr - start_addr + 1;
821f1ae32a1SGerd Hoffmann     }
822f1ae32a1SGerd Hoffmann 
823f1ae32a1SGerd Hoffmann     if (len && dir != OHCI_TD_DIR_IN) {
8249ac6a217SDavid Gibson         ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, len,
8259ac6a217SDavid Gibson                          DMA_DIRECTION_TO_DEVICE);
826f1ae32a1SGerd Hoffmann     }
827f1ae32a1SGerd Hoffmann 
8289a77a0f5SHans de Goede     if (!completion) {
829a6fb2ddbSHans de Goede         bool int_req = relative_frame_number == frame_count &&
830a6fb2ddbSHans de Goede                        OHCI_BM(iso_td.flags, TD_DI) == 0;
831f1ae32a1SGerd Hoffmann         dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
832f1ae32a1SGerd Hoffmann         ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
833a6fb2ddbSHans de Goede         usb_packet_setup(&ohci->usb_packet, pid, ep, addr, false, int_req);
834f1ae32a1SGerd Hoffmann         usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len);
8359a77a0f5SHans de Goede         usb_handle_packet(dev, &ohci->usb_packet);
8369a77a0f5SHans de Goede         if (ohci->usb_packet.status == USB_RET_ASYNC) {
83736dfe324SHans de Goede             usb_device_flush_ep_queue(dev, ep);
838f1ae32a1SGerd Hoffmann             return 1;
839f1ae32a1SGerd Hoffmann         }
840f1ae32a1SGerd Hoffmann     }
8419a77a0f5SHans de Goede     if (ohci->usb_packet.status == USB_RET_SUCCESS) {
8429a77a0f5SHans de Goede         ret = ohci->usb_packet.actual_length;
8439a77a0f5SHans de Goede     } else {
8449a77a0f5SHans de Goede         ret = ohci->usb_packet.status;
8459a77a0f5SHans de Goede     }
846f1ae32a1SGerd Hoffmann 
847f1ae32a1SGerd Hoffmann #ifdef DEBUG_ISOCH
848f1ae32a1SGerd Hoffmann     printf("so 0x%.8x eo 0x%.8x\nsa 0x%.8x ea 0x%.8x\ndir %s len %zu ret %d\n",
849f1ae32a1SGerd Hoffmann            start_offset, end_offset, start_addr, end_addr, str, len, ret);
850f1ae32a1SGerd Hoffmann #endif
851f1ae32a1SGerd Hoffmann 
852f1ae32a1SGerd Hoffmann     /* Writeback */
853f1ae32a1SGerd Hoffmann     if (dir == OHCI_TD_DIR_IN && ret >= 0 && ret <= len) {
854f1ae32a1SGerd Hoffmann         /* IN transfer succeeded */
8559ac6a217SDavid Gibson         ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, ret,
8569ac6a217SDavid Gibson                          DMA_DIRECTION_FROM_DEVICE);
857f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
858f1ae32a1SGerd Hoffmann                     OHCI_CC_NOERROR);
859f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, ret);
860f1ae32a1SGerd Hoffmann     } else if (dir == OHCI_TD_DIR_OUT && ret == len) {
861f1ae32a1SGerd Hoffmann         /* OUT transfer succeeded */
862f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
863f1ae32a1SGerd Hoffmann                     OHCI_CC_NOERROR);
864f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 0);
865f1ae32a1SGerd Hoffmann     } else {
866f1ae32a1SGerd Hoffmann         if (ret > (ssize_t) len) {
867f1ae32a1SGerd Hoffmann             printf("usb-ohci: DataOverrun %d > %zu\n", ret, len);
868f1ae32a1SGerd Hoffmann             OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
869f1ae32a1SGerd Hoffmann                         OHCI_CC_DATAOVERRUN);
870f1ae32a1SGerd Hoffmann             OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
871f1ae32a1SGerd Hoffmann                         len);
872f1ae32a1SGerd Hoffmann         } else if (ret >= 0) {
873f1ae32a1SGerd Hoffmann             printf("usb-ohci: DataUnderrun %d\n", ret);
874f1ae32a1SGerd Hoffmann             OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
875f1ae32a1SGerd Hoffmann                         OHCI_CC_DATAUNDERRUN);
876f1ae32a1SGerd Hoffmann         } else {
877f1ae32a1SGerd Hoffmann             switch (ret) {
878f1ae32a1SGerd Hoffmann             case USB_RET_IOERROR:
879f1ae32a1SGerd Hoffmann             case USB_RET_NODEV:
880f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
881f1ae32a1SGerd Hoffmann                             OHCI_CC_DEVICENOTRESPONDING);
882f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
883f1ae32a1SGerd Hoffmann                             0);
884f1ae32a1SGerd Hoffmann                 break;
885f1ae32a1SGerd Hoffmann             case USB_RET_NAK:
886f1ae32a1SGerd Hoffmann             case USB_RET_STALL:
887f1ae32a1SGerd Hoffmann                 printf("usb-ohci: got NAK/STALL %d\n", ret);
888f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
889f1ae32a1SGerd Hoffmann                             OHCI_CC_STALL);
890f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
891f1ae32a1SGerd Hoffmann                             0);
892f1ae32a1SGerd Hoffmann                 break;
893f1ae32a1SGerd Hoffmann             default:
894f1ae32a1SGerd Hoffmann                 printf("usb-ohci: Bad device response %d\n", ret);
895f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
896f1ae32a1SGerd Hoffmann                             OHCI_CC_UNDEXPETEDPID);
897f1ae32a1SGerd Hoffmann                 break;
898f1ae32a1SGerd Hoffmann             }
899f1ae32a1SGerd Hoffmann         }
900f1ae32a1SGerd Hoffmann     }
901f1ae32a1SGerd Hoffmann 
902f1ae32a1SGerd Hoffmann     if (relative_frame_number == frame_count) {
903f1ae32a1SGerd Hoffmann         /* Last data packet of ISO TD - retire the TD to the Done Queue */
904f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_NOERROR);
905f1ae32a1SGerd Hoffmann         ed->head &= ~OHCI_DPTR_MASK;
906f1ae32a1SGerd Hoffmann         ed->head |= (iso_td.next & OHCI_DPTR_MASK);
907f1ae32a1SGerd Hoffmann         iso_td.next = ohci->done;
908f1ae32a1SGerd Hoffmann         ohci->done = addr;
909f1ae32a1SGerd Hoffmann         i = OHCI_BM(iso_td.flags, TD_DI);
910f1ae32a1SGerd Hoffmann         if (i < ohci->done_count)
911f1ae32a1SGerd Hoffmann             ohci->done_count = i;
912f1ae32a1SGerd Hoffmann     }
913f1ae32a1SGerd Hoffmann     ohci_put_iso_td(ohci, addr, &iso_td);
914f1ae32a1SGerd Hoffmann     return 1;
915f1ae32a1SGerd Hoffmann }
916f1ae32a1SGerd Hoffmann 
917f1ae32a1SGerd Hoffmann /* Service a transport descriptor.
918f1ae32a1SGerd Hoffmann    Returns nonzero to terminate processing of this endpoint.  */
919f1ae32a1SGerd Hoffmann 
920f1ae32a1SGerd Hoffmann static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
921f1ae32a1SGerd Hoffmann {
922f1ae32a1SGerd Hoffmann     int dir;
923f1ae32a1SGerd Hoffmann     size_t len = 0, pktlen = 0;
924f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET
925f1ae32a1SGerd Hoffmann     const char *str = NULL;
926f1ae32a1SGerd Hoffmann #endif
927f1ae32a1SGerd Hoffmann     int pid;
928f1ae32a1SGerd Hoffmann     int ret;
929f1ae32a1SGerd Hoffmann     int i;
930f1ae32a1SGerd Hoffmann     USBDevice *dev;
931f1ae32a1SGerd Hoffmann     USBEndpoint *ep;
932f1ae32a1SGerd Hoffmann     struct ohci_td td;
933f1ae32a1SGerd Hoffmann     uint32_t addr;
934f1ae32a1SGerd Hoffmann     int flag_r;
935f1ae32a1SGerd Hoffmann     int completion;
936f1ae32a1SGerd Hoffmann 
937f1ae32a1SGerd Hoffmann     addr = ed->head & OHCI_DPTR_MASK;
938f1ae32a1SGerd Hoffmann     /* See if this TD has already been submitted to the device.  */
939f1ae32a1SGerd Hoffmann     completion = (addr == ohci->async_td);
940f1ae32a1SGerd Hoffmann     if (completion && !ohci->async_complete) {
941f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET
942f1ae32a1SGerd Hoffmann         DPRINTF("Skipping async TD\n");
943f1ae32a1SGerd Hoffmann #endif
944f1ae32a1SGerd Hoffmann         return 1;
945f1ae32a1SGerd Hoffmann     }
946f1ae32a1SGerd Hoffmann     if (!ohci_read_td(ohci, addr, &td)) {
947f1ae32a1SGerd Hoffmann         fprintf(stderr, "usb-ohci: TD read error at %x\n", addr);
948f1ae32a1SGerd Hoffmann         return 0;
949f1ae32a1SGerd Hoffmann     }
950f1ae32a1SGerd Hoffmann 
951f1ae32a1SGerd Hoffmann     dir = OHCI_BM(ed->flags, ED_D);
952f1ae32a1SGerd Hoffmann     switch (dir) {
953f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_OUT:
954f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_IN:
955f1ae32a1SGerd Hoffmann         /* Same value.  */
956f1ae32a1SGerd Hoffmann         break;
957f1ae32a1SGerd Hoffmann     default:
958f1ae32a1SGerd Hoffmann         dir = OHCI_BM(td.flags, TD_DP);
959f1ae32a1SGerd Hoffmann         break;
960f1ae32a1SGerd Hoffmann     }
961f1ae32a1SGerd Hoffmann 
962f1ae32a1SGerd Hoffmann     switch (dir) {
963f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_IN:
964f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET
965f1ae32a1SGerd Hoffmann         str = "in";
966f1ae32a1SGerd Hoffmann #endif
967f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_IN;
968f1ae32a1SGerd Hoffmann         break;
969f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_OUT:
970f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET
971f1ae32a1SGerd Hoffmann         str = "out";
972f1ae32a1SGerd Hoffmann #endif
973f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_OUT;
974f1ae32a1SGerd Hoffmann         break;
975f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_SETUP:
976f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET
977f1ae32a1SGerd Hoffmann         str = "setup";
978f1ae32a1SGerd Hoffmann #endif
979f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_SETUP;
980f1ae32a1SGerd Hoffmann         break;
981f1ae32a1SGerd Hoffmann     default:
982f1ae32a1SGerd Hoffmann         fprintf(stderr, "usb-ohci: Bad direction\n");
983f1ae32a1SGerd Hoffmann         return 1;
984f1ae32a1SGerd Hoffmann     }
985f1ae32a1SGerd Hoffmann     if (td.cbp && td.be) {
986f1ae32a1SGerd Hoffmann         if ((td.cbp & 0xfffff000) != (td.be & 0xfffff000)) {
987f1ae32a1SGerd Hoffmann             len = (td.be & 0xfff) + 0x1001 - (td.cbp & 0xfff);
988f1ae32a1SGerd Hoffmann         } else {
989f1ae32a1SGerd Hoffmann             len = (td.be - td.cbp) + 1;
990f1ae32a1SGerd Hoffmann         }
991f1ae32a1SGerd Hoffmann 
992f1ae32a1SGerd Hoffmann         pktlen = len;
993f1ae32a1SGerd Hoffmann         if (len && dir != OHCI_TD_DIR_IN) {
994f1ae32a1SGerd Hoffmann             /* The endpoint may not allow us to transfer it all now */
995f1ae32a1SGerd Hoffmann             pktlen = (ed->flags & OHCI_ED_MPS_MASK) >> OHCI_ED_MPS_SHIFT;
996f1ae32a1SGerd Hoffmann             if (pktlen > len) {
997f1ae32a1SGerd Hoffmann                 pktlen = len;
998f1ae32a1SGerd Hoffmann             }
999f1ae32a1SGerd Hoffmann             if (!completion) {
10009ac6a217SDavid Gibson                 ohci_copy_td(ohci, &td, ohci->usb_buf, pktlen,
10019ac6a217SDavid Gibson                              DMA_DIRECTION_TO_DEVICE);
1002f1ae32a1SGerd Hoffmann             }
1003f1ae32a1SGerd Hoffmann         }
1004f1ae32a1SGerd Hoffmann     }
1005f1ae32a1SGerd Hoffmann 
1006f1ae32a1SGerd Hoffmann     flag_r = (td.flags & OHCI_TD_R) != 0;
1007f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET
1008f1ae32a1SGerd Hoffmann     DPRINTF(" TD @ 0x%.8x %" PRId64 " of %" PRId64
1009f1ae32a1SGerd Hoffmann             " bytes %s r=%d cbp=0x%.8x be=0x%.8x\n",
1010f1ae32a1SGerd Hoffmann             addr, (int64_t)pktlen, (int64_t)len, str, flag_r, td.cbp, td.be);
1011f1ae32a1SGerd Hoffmann 
1012f1ae32a1SGerd Hoffmann     if (pktlen > 0 && dir != OHCI_TD_DIR_IN) {
1013f1ae32a1SGerd Hoffmann         DPRINTF("  data:");
1014f1ae32a1SGerd Hoffmann         for (i = 0; i < pktlen; i++) {
1015f1ae32a1SGerd Hoffmann             printf(" %.2x", ohci->usb_buf[i]);
1016f1ae32a1SGerd Hoffmann         }
1017f1ae32a1SGerd Hoffmann         DPRINTF("\n");
1018f1ae32a1SGerd Hoffmann     }
1019f1ae32a1SGerd Hoffmann #endif
1020f1ae32a1SGerd Hoffmann     if (completion) {
1021f1ae32a1SGerd Hoffmann         ohci->async_td = 0;
1022f1ae32a1SGerd Hoffmann         ohci->async_complete = 0;
1023f1ae32a1SGerd Hoffmann     } else {
1024f1ae32a1SGerd Hoffmann         if (ohci->async_td) {
1025f1ae32a1SGerd Hoffmann             /* ??? The hardware should allow one active packet per
1026f1ae32a1SGerd Hoffmann                endpoint.  We only allow one active packet per controller.
1027f1ae32a1SGerd Hoffmann                This should be sufficient as long as devices respond in a
1028f1ae32a1SGerd Hoffmann                timely manner.
1029f1ae32a1SGerd Hoffmann             */
1030f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET
1031f1ae32a1SGerd Hoffmann             DPRINTF("Too many pending packets\n");
1032f1ae32a1SGerd Hoffmann #endif
1033f1ae32a1SGerd Hoffmann             return 1;
1034f1ae32a1SGerd Hoffmann         }
1035f1ae32a1SGerd Hoffmann         dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
1036f1ae32a1SGerd Hoffmann         ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
1037a6fb2ddbSHans de Goede         usb_packet_setup(&ohci->usb_packet, pid, ep, addr, !flag_r,
1038a6fb2ddbSHans de Goede                          OHCI_BM(td.flags, TD_DI) == 0);
1039f1ae32a1SGerd Hoffmann         usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen);
10409a77a0f5SHans de Goede         usb_handle_packet(dev, &ohci->usb_packet);
1041f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET
10429a77a0f5SHans de Goede         DPRINTF("status=%d\n", ohci->usb_packet.status);
1043f1ae32a1SGerd Hoffmann #endif
10449a77a0f5SHans de Goede         if (ohci->usb_packet.status == USB_RET_ASYNC) {
104536dfe324SHans de Goede             usb_device_flush_ep_queue(dev, ep);
1046f1ae32a1SGerd Hoffmann             ohci->async_td = addr;
1047f1ae32a1SGerd Hoffmann             return 1;
1048f1ae32a1SGerd Hoffmann         }
1049f1ae32a1SGerd Hoffmann     }
10509a77a0f5SHans de Goede     if (ohci->usb_packet.status == USB_RET_SUCCESS) {
10519a77a0f5SHans de Goede         ret = ohci->usb_packet.actual_length;
10529a77a0f5SHans de Goede     } else {
10539a77a0f5SHans de Goede         ret = ohci->usb_packet.status;
10549a77a0f5SHans de Goede     }
10559a77a0f5SHans de Goede 
1056f1ae32a1SGerd Hoffmann     if (ret >= 0) {
1057f1ae32a1SGerd Hoffmann         if (dir == OHCI_TD_DIR_IN) {
10589ac6a217SDavid Gibson             ohci_copy_td(ohci, &td, ohci->usb_buf, ret,
10599ac6a217SDavid Gibson                          DMA_DIRECTION_FROM_DEVICE);
1060f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET
1061f1ae32a1SGerd Hoffmann             DPRINTF("  data:");
1062f1ae32a1SGerd Hoffmann             for (i = 0; i < ret; i++)
1063f1ae32a1SGerd Hoffmann                 printf(" %.2x", ohci->usb_buf[i]);
1064f1ae32a1SGerd Hoffmann             DPRINTF("\n");
1065f1ae32a1SGerd Hoffmann #endif
1066f1ae32a1SGerd Hoffmann         } else {
1067f1ae32a1SGerd Hoffmann             ret = pktlen;
1068f1ae32a1SGerd Hoffmann         }
1069f1ae32a1SGerd Hoffmann     }
1070f1ae32a1SGerd Hoffmann 
1071f1ae32a1SGerd Hoffmann     /* Writeback */
1072f1ae32a1SGerd Hoffmann     if (ret == pktlen || (dir == OHCI_TD_DIR_IN && ret >= 0 && flag_r)) {
1073f1ae32a1SGerd Hoffmann         /* Transmission succeeded.  */
1074f1ae32a1SGerd Hoffmann         if (ret == len) {
1075f1ae32a1SGerd Hoffmann             td.cbp = 0;
1076f1ae32a1SGerd Hoffmann         } else {
1077f1ae32a1SGerd Hoffmann             if ((td.cbp & 0xfff) + ret > 0xfff) {
1078f1ae32a1SGerd Hoffmann                 td.cbp = (td.be & ~0xfff) + ((td.cbp + ret) & 0xfff);
1079f1ae32a1SGerd Hoffmann             } else {
1080f1ae32a1SGerd Hoffmann                 td.cbp += ret;
1081f1ae32a1SGerd Hoffmann             }
1082f1ae32a1SGerd Hoffmann         }
1083f1ae32a1SGerd Hoffmann         td.flags |= OHCI_TD_T1;
1084f1ae32a1SGerd Hoffmann         td.flags ^= OHCI_TD_T0;
1085f1ae32a1SGerd Hoffmann         OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_NOERROR);
1086f1ae32a1SGerd Hoffmann         OHCI_SET_BM(td.flags, TD_EC, 0);
1087f1ae32a1SGerd Hoffmann 
1088f1ae32a1SGerd Hoffmann         if ((dir != OHCI_TD_DIR_IN) && (ret != len)) {
1089f1ae32a1SGerd Hoffmann             /* Partial packet transfer: TD not ready to retire yet */
1090f1ae32a1SGerd Hoffmann             goto exit_no_retire;
1091f1ae32a1SGerd Hoffmann         }
1092f1ae32a1SGerd Hoffmann 
1093f1ae32a1SGerd Hoffmann         /* Setting ED_C is part of the TD retirement process */
1094f1ae32a1SGerd Hoffmann         ed->head &= ~OHCI_ED_C;
1095f1ae32a1SGerd Hoffmann         if (td.flags & OHCI_TD_T0)
1096f1ae32a1SGerd Hoffmann             ed->head |= OHCI_ED_C;
1097f1ae32a1SGerd Hoffmann     } else {
1098f1ae32a1SGerd Hoffmann         if (ret >= 0) {
1099f1ae32a1SGerd Hoffmann             DPRINTF("usb-ohci: Underrun\n");
1100f1ae32a1SGerd Hoffmann             OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAUNDERRUN);
1101f1ae32a1SGerd Hoffmann         } else {
1102f1ae32a1SGerd Hoffmann             switch (ret) {
1103f1ae32a1SGerd Hoffmann             case USB_RET_IOERROR:
1104f1ae32a1SGerd Hoffmann             case USB_RET_NODEV:
1105f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DEVICENOTRESPONDING);
1106f1ae32a1SGerd Hoffmann             case USB_RET_NAK:
1107f1ae32a1SGerd Hoffmann                 DPRINTF("usb-ohci: got NAK\n");
1108f1ae32a1SGerd Hoffmann                 return 1;
1109f1ae32a1SGerd Hoffmann             case USB_RET_STALL:
1110f1ae32a1SGerd Hoffmann                 DPRINTF("usb-ohci: got STALL\n");
1111f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_STALL);
1112f1ae32a1SGerd Hoffmann                 break;
1113f1ae32a1SGerd Hoffmann             case USB_RET_BABBLE:
1114f1ae32a1SGerd Hoffmann                 DPRINTF("usb-ohci: got BABBLE\n");
1115f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAOVERRUN);
1116f1ae32a1SGerd Hoffmann                 break;
1117f1ae32a1SGerd Hoffmann             default:
1118f1ae32a1SGerd Hoffmann                 fprintf(stderr, "usb-ohci: Bad device response %d\n", ret);
1119f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_UNDEXPETEDPID);
1120f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_EC, 3);
1121f1ae32a1SGerd Hoffmann                 break;
1122f1ae32a1SGerd Hoffmann             }
1123f1ae32a1SGerd Hoffmann         }
1124f1ae32a1SGerd Hoffmann         ed->head |= OHCI_ED_H;
1125f1ae32a1SGerd Hoffmann     }
1126f1ae32a1SGerd Hoffmann 
1127f1ae32a1SGerd Hoffmann     /* Retire this TD */
1128f1ae32a1SGerd Hoffmann     ed->head &= ~OHCI_DPTR_MASK;
1129f1ae32a1SGerd Hoffmann     ed->head |= td.next & OHCI_DPTR_MASK;
1130f1ae32a1SGerd Hoffmann     td.next = ohci->done;
1131f1ae32a1SGerd Hoffmann     ohci->done = addr;
1132f1ae32a1SGerd Hoffmann     i = OHCI_BM(td.flags, TD_DI);
1133f1ae32a1SGerd Hoffmann     if (i < ohci->done_count)
1134f1ae32a1SGerd Hoffmann         ohci->done_count = i;
1135f1ae32a1SGerd Hoffmann exit_no_retire:
1136f1ae32a1SGerd Hoffmann     ohci_put_td(ohci, addr, &td);
1137f1ae32a1SGerd Hoffmann     return OHCI_BM(td.flags, TD_CC) != OHCI_CC_NOERROR;
1138f1ae32a1SGerd Hoffmann }
1139f1ae32a1SGerd Hoffmann 
1140f1ae32a1SGerd Hoffmann /* Service an endpoint list.  Returns nonzero if active TD were found.  */
1141f1ae32a1SGerd Hoffmann static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion)
1142f1ae32a1SGerd Hoffmann {
1143f1ae32a1SGerd Hoffmann     struct ohci_ed ed;
1144f1ae32a1SGerd Hoffmann     uint32_t next_ed;
1145f1ae32a1SGerd Hoffmann     uint32_t cur;
1146f1ae32a1SGerd Hoffmann     int active;
1147f1ae32a1SGerd Hoffmann 
1148f1ae32a1SGerd Hoffmann     active = 0;
1149f1ae32a1SGerd Hoffmann 
1150f1ae32a1SGerd Hoffmann     if (head == 0)
1151f1ae32a1SGerd Hoffmann         return 0;
1152f1ae32a1SGerd Hoffmann 
1153f1ae32a1SGerd Hoffmann     for (cur = head; cur; cur = next_ed) {
1154f1ae32a1SGerd Hoffmann         if (!ohci_read_ed(ohci, cur, &ed)) {
1155f1ae32a1SGerd Hoffmann             fprintf(stderr, "usb-ohci: ED read error at %x\n", cur);
1156f1ae32a1SGerd Hoffmann             return 0;
1157f1ae32a1SGerd Hoffmann         }
1158f1ae32a1SGerd Hoffmann 
1159f1ae32a1SGerd Hoffmann         next_ed = ed.next & OHCI_DPTR_MASK;
1160f1ae32a1SGerd Hoffmann 
1161f1ae32a1SGerd Hoffmann         if ((ed.head & OHCI_ED_H) || (ed.flags & OHCI_ED_K)) {
1162f1ae32a1SGerd Hoffmann             uint32_t addr;
1163f1ae32a1SGerd Hoffmann             /* Cancel pending packets for ED that have been paused.  */
1164f1ae32a1SGerd Hoffmann             addr = ed.head & OHCI_DPTR_MASK;
1165f1ae32a1SGerd Hoffmann             if (ohci->async_td && addr == ohci->async_td) {
1166f1ae32a1SGerd Hoffmann                 usb_cancel_packet(&ohci->usb_packet);
1167f1ae32a1SGerd Hoffmann                 ohci->async_td = 0;
1168f79738b0SHans de Goede                 usb_device_ep_stopped(ohci->usb_packet.ep->dev,
1169f79738b0SHans de Goede                                       ohci->usb_packet.ep);
1170f1ae32a1SGerd Hoffmann             }
1171f1ae32a1SGerd Hoffmann             continue;
1172f1ae32a1SGerd Hoffmann         }
1173f1ae32a1SGerd Hoffmann 
1174f1ae32a1SGerd Hoffmann         while ((ed.head & OHCI_DPTR_MASK) != ed.tail) {
1175f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET
1176f1ae32a1SGerd Hoffmann             DPRINTF("ED @ 0x%.8x fa=%u en=%u d=%u s=%u k=%u f=%u mps=%u "
1177f1ae32a1SGerd Hoffmann                     "h=%u c=%u\n  head=0x%.8x tailp=0x%.8x next=0x%.8x\n", cur,
1178f1ae32a1SGerd Hoffmann                     OHCI_BM(ed.flags, ED_FA), OHCI_BM(ed.flags, ED_EN),
1179f1ae32a1SGerd Hoffmann                     OHCI_BM(ed.flags, ED_D), (ed.flags & OHCI_ED_S)!= 0,
1180f1ae32a1SGerd Hoffmann                     (ed.flags & OHCI_ED_K) != 0, (ed.flags & OHCI_ED_F) != 0,
1181f1ae32a1SGerd Hoffmann                     OHCI_BM(ed.flags, ED_MPS), (ed.head & OHCI_ED_H) != 0,
1182f1ae32a1SGerd Hoffmann                     (ed.head & OHCI_ED_C) != 0, ed.head & OHCI_DPTR_MASK,
1183f1ae32a1SGerd Hoffmann                     ed.tail & OHCI_DPTR_MASK, ed.next & OHCI_DPTR_MASK);
1184f1ae32a1SGerd Hoffmann #endif
1185f1ae32a1SGerd Hoffmann             active = 1;
1186f1ae32a1SGerd Hoffmann 
1187f1ae32a1SGerd Hoffmann             if ((ed.flags & OHCI_ED_F) == 0) {
1188f1ae32a1SGerd Hoffmann                 if (ohci_service_td(ohci, &ed))
1189f1ae32a1SGerd Hoffmann                     break;
1190f1ae32a1SGerd Hoffmann             } else {
1191f1ae32a1SGerd Hoffmann                 /* Handle isochronous endpoints */
1192f1ae32a1SGerd Hoffmann                 if (ohci_service_iso_td(ohci, &ed, completion))
1193f1ae32a1SGerd Hoffmann                     break;
1194f1ae32a1SGerd Hoffmann             }
1195f1ae32a1SGerd Hoffmann         }
1196f1ae32a1SGerd Hoffmann 
1197f1ae32a1SGerd Hoffmann         ohci_put_ed(ohci, cur, &ed);
1198f1ae32a1SGerd Hoffmann     }
1199f1ae32a1SGerd Hoffmann 
1200f1ae32a1SGerd Hoffmann     return active;
1201f1ae32a1SGerd Hoffmann }
1202f1ae32a1SGerd Hoffmann 
1203f1ae32a1SGerd Hoffmann /* Generate a SOF event, and set a timer for EOF */
1204f1ae32a1SGerd Hoffmann static void ohci_sof(OHCIState *ohci)
1205f1ae32a1SGerd Hoffmann {
1206f1ae32a1SGerd Hoffmann     ohci->sof_time = qemu_get_clock_ns(vm_clock);
1207f1ae32a1SGerd Hoffmann     qemu_mod_timer(ohci->eof_timer, ohci->sof_time + usb_frame_time);
1208f1ae32a1SGerd Hoffmann     ohci_set_interrupt(ohci, OHCI_INTR_SF);
1209f1ae32a1SGerd Hoffmann }
1210f1ae32a1SGerd Hoffmann 
1211f1ae32a1SGerd Hoffmann /* Process Control and Bulk lists.  */
1212f1ae32a1SGerd Hoffmann static void ohci_process_lists(OHCIState *ohci, int completion)
1213f1ae32a1SGerd Hoffmann {
1214f1ae32a1SGerd Hoffmann     if ((ohci->ctl & OHCI_CTL_CLE) && (ohci->status & OHCI_STATUS_CLF)) {
1215f1ae32a1SGerd Hoffmann         if (ohci->ctrl_cur && ohci->ctrl_cur != ohci->ctrl_head) {
1216f1ae32a1SGerd Hoffmann             DPRINTF("usb-ohci: head %x, cur %x\n",
1217f1ae32a1SGerd Hoffmann                     ohci->ctrl_head, ohci->ctrl_cur);
1218f1ae32a1SGerd Hoffmann         }
1219f1ae32a1SGerd Hoffmann         if (!ohci_service_ed_list(ohci, ohci->ctrl_head, completion)) {
1220f1ae32a1SGerd Hoffmann             ohci->ctrl_cur = 0;
1221f1ae32a1SGerd Hoffmann             ohci->status &= ~OHCI_STATUS_CLF;
1222f1ae32a1SGerd Hoffmann         }
1223f1ae32a1SGerd Hoffmann     }
1224f1ae32a1SGerd Hoffmann 
1225f1ae32a1SGerd Hoffmann     if ((ohci->ctl & OHCI_CTL_BLE) && (ohci->status & OHCI_STATUS_BLF)) {
1226f1ae32a1SGerd Hoffmann         if (!ohci_service_ed_list(ohci, ohci->bulk_head, completion)) {
1227f1ae32a1SGerd Hoffmann             ohci->bulk_cur = 0;
1228f1ae32a1SGerd Hoffmann             ohci->status &= ~OHCI_STATUS_BLF;
1229f1ae32a1SGerd Hoffmann         }
1230f1ae32a1SGerd Hoffmann     }
1231f1ae32a1SGerd Hoffmann }
1232f1ae32a1SGerd Hoffmann 
1233f1ae32a1SGerd Hoffmann /* Do frame processing on frame boundary */
1234f1ae32a1SGerd Hoffmann static void ohci_frame_boundary(void *opaque)
1235f1ae32a1SGerd Hoffmann {
1236f1ae32a1SGerd Hoffmann     OHCIState *ohci = opaque;
1237f1ae32a1SGerd Hoffmann     struct ohci_hcca hcca;
1238f1ae32a1SGerd Hoffmann 
1239f1ae32a1SGerd Hoffmann     ohci_read_hcca(ohci, ohci->hcca, &hcca);
1240f1ae32a1SGerd Hoffmann 
1241f1ae32a1SGerd Hoffmann     /* Process all the lists at the end of the frame */
1242f1ae32a1SGerd Hoffmann     if (ohci->ctl & OHCI_CTL_PLE) {
1243f1ae32a1SGerd Hoffmann         int n;
1244f1ae32a1SGerd Hoffmann 
1245f1ae32a1SGerd Hoffmann         n = ohci->frame_number & 0x1f;
1246f1ae32a1SGerd Hoffmann         ohci_service_ed_list(ohci, le32_to_cpu(hcca.intr[n]), 0);
1247f1ae32a1SGerd Hoffmann     }
1248f1ae32a1SGerd Hoffmann 
1249f1ae32a1SGerd Hoffmann     /* Cancel all pending packets if either of the lists has been disabled.  */
1250f79738b0SHans de Goede     if (ohci->old_ctl & (~ohci->ctl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) {
1251f79738b0SHans de Goede         if (ohci->async_td) {
1252f1ae32a1SGerd Hoffmann             usb_cancel_packet(&ohci->usb_packet);
1253f1ae32a1SGerd Hoffmann             ohci->async_td = 0;
1254f1ae32a1SGerd Hoffmann         }
1255f79738b0SHans de Goede         ohci_stop_endpoints(ohci);
1256f79738b0SHans de Goede     }
1257f1ae32a1SGerd Hoffmann     ohci->old_ctl = ohci->ctl;
1258f1ae32a1SGerd Hoffmann     ohci_process_lists(ohci, 0);
1259f1ae32a1SGerd Hoffmann 
1260f1ae32a1SGerd Hoffmann     /* Frame boundary, so do EOF stuf here */
1261f1ae32a1SGerd Hoffmann     ohci->frt = ohci->fit;
1262f1ae32a1SGerd Hoffmann 
1263f1ae32a1SGerd Hoffmann     /* Increment frame number and take care of endianness. */
1264f1ae32a1SGerd Hoffmann     ohci->frame_number = (ohci->frame_number + 1) & 0xffff;
1265f1ae32a1SGerd Hoffmann     hcca.frame = cpu_to_le16(ohci->frame_number);
1266f1ae32a1SGerd Hoffmann 
1267f1ae32a1SGerd Hoffmann     if (ohci->done_count == 0 && !(ohci->intr_status & OHCI_INTR_WD)) {
1268f1ae32a1SGerd Hoffmann         if (!ohci->done)
1269f1ae32a1SGerd Hoffmann             abort();
1270f1ae32a1SGerd Hoffmann         if (ohci->intr & ohci->intr_status)
1271f1ae32a1SGerd Hoffmann             ohci->done |= 1;
1272f1ae32a1SGerd Hoffmann         hcca.done = cpu_to_le32(ohci->done);
1273f1ae32a1SGerd Hoffmann         ohci->done = 0;
1274f1ae32a1SGerd Hoffmann         ohci->done_count = 7;
1275f1ae32a1SGerd Hoffmann         ohci_set_interrupt(ohci, OHCI_INTR_WD);
1276f1ae32a1SGerd Hoffmann     }
1277f1ae32a1SGerd Hoffmann 
1278f1ae32a1SGerd Hoffmann     if (ohci->done_count != 7 && ohci->done_count != 0)
1279f1ae32a1SGerd Hoffmann         ohci->done_count--;
1280f1ae32a1SGerd Hoffmann 
1281f1ae32a1SGerd Hoffmann     /* Do SOF stuff here */
1282f1ae32a1SGerd Hoffmann     ohci_sof(ohci);
1283f1ae32a1SGerd Hoffmann 
1284f1ae32a1SGerd Hoffmann     /* Writeback HCCA */
1285f1ae32a1SGerd Hoffmann     ohci_put_hcca(ohci, ohci->hcca, &hcca);
1286f1ae32a1SGerd Hoffmann }
1287f1ae32a1SGerd Hoffmann 
1288f1ae32a1SGerd Hoffmann /* Start sending SOF tokens across the USB bus, lists are processed in
1289f1ae32a1SGerd Hoffmann  * next frame
1290f1ae32a1SGerd Hoffmann  */
1291f1ae32a1SGerd Hoffmann static int ohci_bus_start(OHCIState *ohci)
1292f1ae32a1SGerd Hoffmann {
1293f1ae32a1SGerd Hoffmann     ohci->eof_timer = qemu_new_timer_ns(vm_clock,
1294f1ae32a1SGerd Hoffmann                     ohci_frame_boundary,
1295f1ae32a1SGerd Hoffmann                     ohci);
1296f1ae32a1SGerd Hoffmann 
1297f1ae32a1SGerd Hoffmann     if (ohci->eof_timer == NULL) {
1298f1ae32a1SGerd Hoffmann         fprintf(stderr, "usb-ohci: %s: qemu_new_timer_ns failed\n", ohci->name);
1299f1ae32a1SGerd Hoffmann         /* TODO: Signal unrecoverable error */
1300f1ae32a1SGerd Hoffmann         return 0;
1301f1ae32a1SGerd Hoffmann     }
1302f1ae32a1SGerd Hoffmann 
1303f1ae32a1SGerd Hoffmann     DPRINTF("usb-ohci: %s: USB Operational\n", ohci->name);
1304f1ae32a1SGerd Hoffmann 
1305f1ae32a1SGerd Hoffmann     ohci_sof(ohci);
1306f1ae32a1SGerd Hoffmann 
1307f1ae32a1SGerd Hoffmann     return 1;
1308f1ae32a1SGerd Hoffmann }
1309f1ae32a1SGerd Hoffmann 
1310f1ae32a1SGerd Hoffmann /* Stop sending SOF tokens on the bus */
1311f1ae32a1SGerd Hoffmann static void ohci_bus_stop(OHCIState *ohci)
1312f1ae32a1SGerd Hoffmann {
1313f1ae32a1SGerd Hoffmann     if (ohci->eof_timer)
1314f1ae32a1SGerd Hoffmann         qemu_del_timer(ohci->eof_timer);
1315f1ae32a1SGerd Hoffmann     ohci->eof_timer = NULL;
1316f1ae32a1SGerd Hoffmann }
1317f1ae32a1SGerd Hoffmann 
1318f1ae32a1SGerd Hoffmann /* Sets a flag in a port status register but only set it if the port is
1319f1ae32a1SGerd Hoffmann  * connected, if not set ConnectStatusChange flag. If flag is enabled
1320f1ae32a1SGerd Hoffmann  * return 1.
1321f1ae32a1SGerd Hoffmann  */
1322f1ae32a1SGerd Hoffmann static int ohci_port_set_if_connected(OHCIState *ohci, int i, uint32_t val)
1323f1ae32a1SGerd Hoffmann {
1324f1ae32a1SGerd Hoffmann     int ret = 1;
1325f1ae32a1SGerd Hoffmann 
1326f1ae32a1SGerd Hoffmann     /* writing a 0 has no effect */
1327f1ae32a1SGerd Hoffmann     if (val == 0)
1328f1ae32a1SGerd Hoffmann         return 0;
1329f1ae32a1SGerd Hoffmann 
1330f1ae32a1SGerd Hoffmann     /* If CurrentConnectStatus is cleared we set
1331f1ae32a1SGerd Hoffmann      * ConnectStatusChange
1332f1ae32a1SGerd Hoffmann      */
1333f1ae32a1SGerd Hoffmann     if (!(ohci->rhport[i].ctrl & OHCI_PORT_CCS)) {
1334f1ae32a1SGerd Hoffmann         ohci->rhport[i].ctrl |= OHCI_PORT_CSC;
1335f1ae32a1SGerd Hoffmann         if (ohci->rhstatus & OHCI_RHS_DRWE) {
1336f1ae32a1SGerd Hoffmann             /* TODO: CSC is a wakeup event */
1337f1ae32a1SGerd Hoffmann         }
1338f1ae32a1SGerd Hoffmann         return 0;
1339f1ae32a1SGerd Hoffmann     }
1340f1ae32a1SGerd Hoffmann 
1341f1ae32a1SGerd Hoffmann     if (ohci->rhport[i].ctrl & val)
1342f1ae32a1SGerd Hoffmann         ret = 0;
1343f1ae32a1SGerd Hoffmann 
1344f1ae32a1SGerd Hoffmann     /* set the bit */
1345f1ae32a1SGerd Hoffmann     ohci->rhport[i].ctrl |= val;
1346f1ae32a1SGerd Hoffmann 
1347f1ae32a1SGerd Hoffmann     return ret;
1348f1ae32a1SGerd Hoffmann }
1349f1ae32a1SGerd Hoffmann 
1350f1ae32a1SGerd Hoffmann /* Set the frame interval - frame interval toggle is manipulated by the hcd only */
1351f1ae32a1SGerd Hoffmann static void ohci_set_frame_interval(OHCIState *ohci, uint16_t val)
1352f1ae32a1SGerd Hoffmann {
1353f1ae32a1SGerd Hoffmann     val &= OHCI_FMI_FI;
1354f1ae32a1SGerd Hoffmann 
1355f1ae32a1SGerd Hoffmann     if (val != ohci->fi) {
1356f1ae32a1SGerd Hoffmann         DPRINTF("usb-ohci: %s: FrameInterval = 0x%x (%u)\n",
1357f1ae32a1SGerd Hoffmann             ohci->name, ohci->fi, ohci->fi);
1358f1ae32a1SGerd Hoffmann     }
1359f1ae32a1SGerd Hoffmann 
1360f1ae32a1SGerd Hoffmann     ohci->fi = val;
1361f1ae32a1SGerd Hoffmann }
1362f1ae32a1SGerd Hoffmann 
1363f1ae32a1SGerd Hoffmann static void ohci_port_power(OHCIState *ohci, int i, int p)
1364f1ae32a1SGerd Hoffmann {
1365f1ae32a1SGerd Hoffmann     if (p) {
1366f1ae32a1SGerd Hoffmann         ohci->rhport[i].ctrl |= OHCI_PORT_PPS;
1367f1ae32a1SGerd Hoffmann     } else {
1368f1ae32a1SGerd Hoffmann         ohci->rhport[i].ctrl &= ~(OHCI_PORT_PPS|
1369f1ae32a1SGerd Hoffmann                     OHCI_PORT_CCS|
1370f1ae32a1SGerd Hoffmann                     OHCI_PORT_PSS|
1371f1ae32a1SGerd Hoffmann                     OHCI_PORT_PRS);
1372f1ae32a1SGerd Hoffmann     }
1373f1ae32a1SGerd Hoffmann }
1374f1ae32a1SGerd Hoffmann 
1375f1ae32a1SGerd Hoffmann /* Set HcControlRegister */
1376f1ae32a1SGerd Hoffmann static void ohci_set_ctl(OHCIState *ohci, uint32_t val)
1377f1ae32a1SGerd Hoffmann {
1378f1ae32a1SGerd Hoffmann     uint32_t old_state;
1379f1ae32a1SGerd Hoffmann     uint32_t new_state;
1380f1ae32a1SGerd Hoffmann 
1381f1ae32a1SGerd Hoffmann     old_state = ohci->ctl & OHCI_CTL_HCFS;
1382f1ae32a1SGerd Hoffmann     ohci->ctl = val;
1383f1ae32a1SGerd Hoffmann     new_state = ohci->ctl & OHCI_CTL_HCFS;
1384f1ae32a1SGerd Hoffmann 
1385f1ae32a1SGerd Hoffmann     /* no state change */
1386f1ae32a1SGerd Hoffmann     if (old_state == new_state)
1387f1ae32a1SGerd Hoffmann         return;
1388f1ae32a1SGerd Hoffmann 
1389f1ae32a1SGerd Hoffmann     switch (new_state) {
1390f1ae32a1SGerd Hoffmann     case OHCI_USB_OPERATIONAL:
1391f1ae32a1SGerd Hoffmann         ohci_bus_start(ohci);
1392f1ae32a1SGerd Hoffmann         break;
1393f1ae32a1SGerd Hoffmann     case OHCI_USB_SUSPEND:
1394f1ae32a1SGerd Hoffmann         ohci_bus_stop(ohci);
1395f1ae32a1SGerd Hoffmann         DPRINTF("usb-ohci: %s: USB Suspended\n", ohci->name);
1396f1ae32a1SGerd Hoffmann         break;
1397f1ae32a1SGerd Hoffmann     case OHCI_USB_RESUME:
1398f1ae32a1SGerd Hoffmann         DPRINTF("usb-ohci: %s: USB Resume\n", ohci->name);
1399f1ae32a1SGerd Hoffmann         break;
1400f1ae32a1SGerd Hoffmann     case OHCI_USB_RESET:
1401f1ae32a1SGerd Hoffmann         ohci_reset(ohci);
1402f1ae32a1SGerd Hoffmann         DPRINTF("usb-ohci: %s: USB Reset\n", ohci->name);
1403f1ae32a1SGerd Hoffmann         break;
1404f1ae32a1SGerd Hoffmann     }
1405f1ae32a1SGerd Hoffmann }
1406f1ae32a1SGerd Hoffmann 
1407f1ae32a1SGerd Hoffmann static uint32_t ohci_get_frame_remaining(OHCIState *ohci)
1408f1ae32a1SGerd Hoffmann {
1409f1ae32a1SGerd Hoffmann     uint16_t fr;
1410f1ae32a1SGerd Hoffmann     int64_t tks;
1411f1ae32a1SGerd Hoffmann 
1412f1ae32a1SGerd Hoffmann     if ((ohci->ctl & OHCI_CTL_HCFS) != OHCI_USB_OPERATIONAL)
1413f1ae32a1SGerd Hoffmann         return (ohci->frt << 31);
1414f1ae32a1SGerd Hoffmann 
1415f1ae32a1SGerd Hoffmann     /* Being in USB operational state guarnatees sof_time was
1416f1ae32a1SGerd Hoffmann      * set already.
1417f1ae32a1SGerd Hoffmann      */
1418f1ae32a1SGerd Hoffmann     tks = qemu_get_clock_ns(vm_clock) - ohci->sof_time;
1419f1ae32a1SGerd Hoffmann 
1420f1ae32a1SGerd Hoffmann     /* avoid muldiv if possible */
1421f1ae32a1SGerd Hoffmann     if (tks >= usb_frame_time)
1422f1ae32a1SGerd Hoffmann         return (ohci->frt << 31);
1423f1ae32a1SGerd Hoffmann 
1424f1ae32a1SGerd Hoffmann     tks = muldiv64(1, tks, usb_bit_time);
1425f1ae32a1SGerd Hoffmann     fr = (uint16_t)(ohci->fi - tks);
1426f1ae32a1SGerd Hoffmann 
1427f1ae32a1SGerd Hoffmann     return (ohci->frt << 31) | fr;
1428f1ae32a1SGerd Hoffmann }
1429f1ae32a1SGerd Hoffmann 
1430f1ae32a1SGerd Hoffmann 
1431f1ae32a1SGerd Hoffmann /* Set root hub status */
1432f1ae32a1SGerd Hoffmann static void ohci_set_hub_status(OHCIState *ohci, uint32_t val)
1433f1ae32a1SGerd Hoffmann {
1434f1ae32a1SGerd Hoffmann     uint32_t old_state;
1435f1ae32a1SGerd Hoffmann 
1436f1ae32a1SGerd Hoffmann     old_state = ohci->rhstatus;
1437f1ae32a1SGerd Hoffmann 
1438f1ae32a1SGerd Hoffmann     /* write 1 to clear OCIC */
1439f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_OCIC)
1440f1ae32a1SGerd Hoffmann         ohci->rhstatus &= ~OHCI_RHS_OCIC;
1441f1ae32a1SGerd Hoffmann 
1442f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_LPS) {
1443f1ae32a1SGerd Hoffmann         int i;
1444f1ae32a1SGerd Hoffmann 
1445f1ae32a1SGerd Hoffmann         for (i = 0; i < ohci->num_ports; i++)
1446f1ae32a1SGerd Hoffmann             ohci_port_power(ohci, i, 0);
1447f1ae32a1SGerd Hoffmann         DPRINTF("usb-ohci: powered down all ports\n");
1448f1ae32a1SGerd Hoffmann     }
1449f1ae32a1SGerd Hoffmann 
1450f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_LPSC) {
1451f1ae32a1SGerd Hoffmann         int i;
1452f1ae32a1SGerd Hoffmann 
1453f1ae32a1SGerd Hoffmann         for (i = 0; i < ohci->num_ports; i++)
1454f1ae32a1SGerd Hoffmann             ohci_port_power(ohci, i, 1);
1455f1ae32a1SGerd Hoffmann         DPRINTF("usb-ohci: powered up all ports\n");
1456f1ae32a1SGerd Hoffmann     }
1457f1ae32a1SGerd Hoffmann 
1458f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_DRWE)
1459f1ae32a1SGerd Hoffmann         ohci->rhstatus |= OHCI_RHS_DRWE;
1460f1ae32a1SGerd Hoffmann 
1461f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_CRWE)
1462f1ae32a1SGerd Hoffmann         ohci->rhstatus &= ~OHCI_RHS_DRWE;
1463f1ae32a1SGerd Hoffmann 
1464f1ae32a1SGerd Hoffmann     if (old_state != ohci->rhstatus)
1465f1ae32a1SGerd Hoffmann         ohci_set_interrupt(ohci, OHCI_INTR_RHSC);
1466f1ae32a1SGerd Hoffmann }
1467f1ae32a1SGerd Hoffmann 
1468f1ae32a1SGerd Hoffmann /* Set root hub port status */
1469f1ae32a1SGerd Hoffmann static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val)
1470f1ae32a1SGerd Hoffmann {
1471f1ae32a1SGerd Hoffmann     uint32_t old_state;
1472f1ae32a1SGerd Hoffmann     OHCIPort *port;
1473f1ae32a1SGerd Hoffmann 
1474f1ae32a1SGerd Hoffmann     port = &ohci->rhport[portnum];
1475f1ae32a1SGerd Hoffmann     old_state = port->ctrl;
1476f1ae32a1SGerd Hoffmann 
1477f1ae32a1SGerd Hoffmann     /* Write to clear CSC, PESC, PSSC, OCIC, PRSC */
1478f1ae32a1SGerd Hoffmann     if (val & OHCI_PORT_WTC)
1479f1ae32a1SGerd Hoffmann         port->ctrl &= ~(val & OHCI_PORT_WTC);
1480f1ae32a1SGerd Hoffmann 
1481f1ae32a1SGerd Hoffmann     if (val & OHCI_PORT_CCS)
1482f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_PES;
1483f1ae32a1SGerd Hoffmann 
1484f1ae32a1SGerd Hoffmann     ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PES);
1485f1ae32a1SGerd Hoffmann 
1486f1ae32a1SGerd Hoffmann     if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PSS)) {
1487f1ae32a1SGerd Hoffmann         DPRINTF("usb-ohci: port %d: SUSPEND\n", portnum);
1488f1ae32a1SGerd Hoffmann     }
1489f1ae32a1SGerd Hoffmann 
1490f1ae32a1SGerd Hoffmann     if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PRS)) {
1491f1ae32a1SGerd Hoffmann         DPRINTF("usb-ohci: port %d: RESET\n", portnum);
1492f1ae32a1SGerd Hoffmann         usb_device_reset(port->port.dev);
1493f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_PRS;
1494f1ae32a1SGerd Hoffmann         /* ??? Should this also set OHCI_PORT_PESC.  */
1495f1ae32a1SGerd Hoffmann         port->ctrl |= OHCI_PORT_PES | OHCI_PORT_PRSC;
1496f1ae32a1SGerd Hoffmann     }
1497f1ae32a1SGerd Hoffmann 
1498f1ae32a1SGerd Hoffmann     /* Invert order here to ensure in ambiguous case, device is
1499f1ae32a1SGerd Hoffmann      * powered up...
1500f1ae32a1SGerd Hoffmann      */
1501f1ae32a1SGerd Hoffmann     if (val & OHCI_PORT_LSDA)
1502f1ae32a1SGerd Hoffmann         ohci_port_power(ohci, portnum, 0);
1503f1ae32a1SGerd Hoffmann     if (val & OHCI_PORT_PPS)
1504f1ae32a1SGerd Hoffmann         ohci_port_power(ohci, portnum, 1);
1505f1ae32a1SGerd Hoffmann 
1506f1ae32a1SGerd Hoffmann     if (old_state != port->ctrl)
1507f1ae32a1SGerd Hoffmann         ohci_set_interrupt(ohci, OHCI_INTR_RHSC);
1508f1ae32a1SGerd Hoffmann }
1509f1ae32a1SGerd Hoffmann 
1510f1ae32a1SGerd Hoffmann static uint64_t ohci_mem_read(void *opaque,
1511a8170e5eSAvi Kivity                               hwaddr addr,
1512f1ae32a1SGerd Hoffmann                               unsigned size)
1513f1ae32a1SGerd Hoffmann {
1514f1ae32a1SGerd Hoffmann     OHCIState *ohci = opaque;
1515f1ae32a1SGerd Hoffmann     uint32_t retval;
1516f1ae32a1SGerd Hoffmann 
1517f1ae32a1SGerd Hoffmann     /* Only aligned reads are allowed on OHCI */
1518f1ae32a1SGerd Hoffmann     if (addr & 3) {
1519f1ae32a1SGerd Hoffmann         fprintf(stderr, "usb-ohci: Mis-aligned read\n");
1520f1ae32a1SGerd Hoffmann         return 0xffffffff;
1521f1ae32a1SGerd Hoffmann     } else if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) {
1522f1ae32a1SGerd Hoffmann         /* HcRhPortStatus */
1523f1ae32a1SGerd Hoffmann         retval = ohci->rhport[(addr - 0x54) >> 2].ctrl | OHCI_PORT_PPS;
1524f1ae32a1SGerd Hoffmann     } else {
1525f1ae32a1SGerd Hoffmann         switch (addr >> 2) {
1526f1ae32a1SGerd Hoffmann         case 0: /* HcRevision */
1527f1ae32a1SGerd Hoffmann             retval = 0x10;
1528f1ae32a1SGerd Hoffmann             break;
1529f1ae32a1SGerd Hoffmann 
1530f1ae32a1SGerd Hoffmann         case 1: /* HcControl */
1531f1ae32a1SGerd Hoffmann             retval = ohci->ctl;
1532f1ae32a1SGerd Hoffmann             break;
1533f1ae32a1SGerd Hoffmann 
1534f1ae32a1SGerd Hoffmann         case 2: /* HcCommandStatus */
1535f1ae32a1SGerd Hoffmann             retval = ohci->status;
1536f1ae32a1SGerd Hoffmann             break;
1537f1ae32a1SGerd Hoffmann 
1538f1ae32a1SGerd Hoffmann         case 3: /* HcInterruptStatus */
1539f1ae32a1SGerd Hoffmann             retval = ohci->intr_status;
1540f1ae32a1SGerd Hoffmann             break;
1541f1ae32a1SGerd Hoffmann 
1542f1ae32a1SGerd Hoffmann         case 4: /* HcInterruptEnable */
1543f1ae32a1SGerd Hoffmann         case 5: /* HcInterruptDisable */
1544f1ae32a1SGerd Hoffmann             retval = ohci->intr;
1545f1ae32a1SGerd Hoffmann             break;
1546f1ae32a1SGerd Hoffmann 
1547f1ae32a1SGerd Hoffmann         case 6: /* HcHCCA */
1548f1ae32a1SGerd Hoffmann             retval = ohci->hcca;
1549f1ae32a1SGerd Hoffmann             break;
1550f1ae32a1SGerd Hoffmann 
1551f1ae32a1SGerd Hoffmann         case 7: /* HcPeriodCurrentED */
1552f1ae32a1SGerd Hoffmann             retval = ohci->per_cur;
1553f1ae32a1SGerd Hoffmann             break;
1554f1ae32a1SGerd Hoffmann 
1555f1ae32a1SGerd Hoffmann         case 8: /* HcControlHeadED */
1556f1ae32a1SGerd Hoffmann             retval = ohci->ctrl_head;
1557f1ae32a1SGerd Hoffmann             break;
1558f1ae32a1SGerd Hoffmann 
1559f1ae32a1SGerd Hoffmann         case 9: /* HcControlCurrentED */
1560f1ae32a1SGerd Hoffmann             retval = ohci->ctrl_cur;
1561f1ae32a1SGerd Hoffmann             break;
1562f1ae32a1SGerd Hoffmann 
1563f1ae32a1SGerd Hoffmann         case 10: /* HcBulkHeadED */
1564f1ae32a1SGerd Hoffmann             retval = ohci->bulk_head;
1565f1ae32a1SGerd Hoffmann             break;
1566f1ae32a1SGerd Hoffmann 
1567f1ae32a1SGerd Hoffmann         case 11: /* HcBulkCurrentED */
1568f1ae32a1SGerd Hoffmann             retval = ohci->bulk_cur;
1569f1ae32a1SGerd Hoffmann             break;
1570f1ae32a1SGerd Hoffmann 
1571f1ae32a1SGerd Hoffmann         case 12: /* HcDoneHead */
1572f1ae32a1SGerd Hoffmann             retval = ohci->done;
1573f1ae32a1SGerd Hoffmann             break;
1574f1ae32a1SGerd Hoffmann 
1575f1ae32a1SGerd Hoffmann         case 13: /* HcFmInterretval */
1576f1ae32a1SGerd Hoffmann             retval = (ohci->fit << 31) | (ohci->fsmps << 16) | (ohci->fi);
1577f1ae32a1SGerd Hoffmann             break;
1578f1ae32a1SGerd Hoffmann 
1579f1ae32a1SGerd Hoffmann         case 14: /* HcFmRemaining */
1580f1ae32a1SGerd Hoffmann             retval = ohci_get_frame_remaining(ohci);
1581f1ae32a1SGerd Hoffmann             break;
1582f1ae32a1SGerd Hoffmann 
1583f1ae32a1SGerd Hoffmann         case 15: /* HcFmNumber */
1584f1ae32a1SGerd Hoffmann             retval = ohci->frame_number;
1585f1ae32a1SGerd Hoffmann             break;
1586f1ae32a1SGerd Hoffmann 
1587f1ae32a1SGerd Hoffmann         case 16: /* HcPeriodicStart */
1588f1ae32a1SGerd Hoffmann             retval = ohci->pstart;
1589f1ae32a1SGerd Hoffmann             break;
1590f1ae32a1SGerd Hoffmann 
1591f1ae32a1SGerd Hoffmann         case 17: /* HcLSThreshold */
1592f1ae32a1SGerd Hoffmann             retval = ohci->lst;
1593f1ae32a1SGerd Hoffmann             break;
1594f1ae32a1SGerd Hoffmann 
1595f1ae32a1SGerd Hoffmann         case 18: /* HcRhDescriptorA */
1596f1ae32a1SGerd Hoffmann             retval = ohci->rhdesc_a;
1597f1ae32a1SGerd Hoffmann             break;
1598f1ae32a1SGerd Hoffmann 
1599f1ae32a1SGerd Hoffmann         case 19: /* HcRhDescriptorB */
1600f1ae32a1SGerd Hoffmann             retval = ohci->rhdesc_b;
1601f1ae32a1SGerd Hoffmann             break;
1602f1ae32a1SGerd Hoffmann 
1603f1ae32a1SGerd Hoffmann         case 20: /* HcRhStatus */
1604f1ae32a1SGerd Hoffmann             retval = ohci->rhstatus;
1605f1ae32a1SGerd Hoffmann             break;
1606f1ae32a1SGerd Hoffmann 
1607f1ae32a1SGerd Hoffmann         /* PXA27x specific registers */
1608f1ae32a1SGerd Hoffmann         case 24: /* HcStatus */
1609f1ae32a1SGerd Hoffmann             retval = ohci->hstatus & ohci->hmask;
1610f1ae32a1SGerd Hoffmann             break;
1611f1ae32a1SGerd Hoffmann 
1612f1ae32a1SGerd Hoffmann         case 25: /* HcHReset */
1613f1ae32a1SGerd Hoffmann             retval = ohci->hreset;
1614f1ae32a1SGerd Hoffmann             break;
1615f1ae32a1SGerd Hoffmann 
1616f1ae32a1SGerd Hoffmann         case 26: /* HcHInterruptEnable */
1617f1ae32a1SGerd Hoffmann             retval = ohci->hmask;
1618f1ae32a1SGerd Hoffmann             break;
1619f1ae32a1SGerd Hoffmann 
1620f1ae32a1SGerd Hoffmann         case 27: /* HcHInterruptTest */
1621f1ae32a1SGerd Hoffmann             retval = ohci->htest;
1622f1ae32a1SGerd Hoffmann             break;
1623f1ae32a1SGerd Hoffmann 
1624f1ae32a1SGerd Hoffmann         default:
1625f1ae32a1SGerd Hoffmann             fprintf(stderr, "ohci_read: Bad offset %x\n", (int)addr);
1626f1ae32a1SGerd Hoffmann             retval = 0xffffffff;
1627f1ae32a1SGerd Hoffmann         }
1628f1ae32a1SGerd Hoffmann     }
1629f1ae32a1SGerd Hoffmann 
1630f1ae32a1SGerd Hoffmann     return retval;
1631f1ae32a1SGerd Hoffmann }
1632f1ae32a1SGerd Hoffmann 
1633f1ae32a1SGerd Hoffmann static void ohci_mem_write(void *opaque,
1634a8170e5eSAvi Kivity                            hwaddr addr,
1635f1ae32a1SGerd Hoffmann                            uint64_t val,
1636f1ae32a1SGerd Hoffmann                            unsigned size)
1637f1ae32a1SGerd Hoffmann {
1638f1ae32a1SGerd Hoffmann     OHCIState *ohci = opaque;
1639f1ae32a1SGerd Hoffmann 
1640f1ae32a1SGerd Hoffmann     /* Only aligned reads are allowed on OHCI */
1641f1ae32a1SGerd Hoffmann     if (addr & 3) {
1642f1ae32a1SGerd Hoffmann         fprintf(stderr, "usb-ohci: Mis-aligned write\n");
1643f1ae32a1SGerd Hoffmann         return;
1644f1ae32a1SGerd Hoffmann     }
1645f1ae32a1SGerd Hoffmann 
1646f1ae32a1SGerd Hoffmann     if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) {
1647f1ae32a1SGerd Hoffmann         /* HcRhPortStatus */
1648f1ae32a1SGerd Hoffmann         ohci_port_set_status(ohci, (addr - 0x54) >> 2, val);
1649f1ae32a1SGerd Hoffmann         return;
1650f1ae32a1SGerd Hoffmann     }
1651f1ae32a1SGerd Hoffmann 
1652f1ae32a1SGerd Hoffmann     switch (addr >> 2) {
1653f1ae32a1SGerd Hoffmann     case 1: /* HcControl */
1654f1ae32a1SGerd Hoffmann         ohci_set_ctl(ohci, val);
1655f1ae32a1SGerd Hoffmann         break;
1656f1ae32a1SGerd Hoffmann 
1657f1ae32a1SGerd Hoffmann     case 2: /* HcCommandStatus */
1658f1ae32a1SGerd Hoffmann         /* SOC is read-only */
1659f1ae32a1SGerd Hoffmann         val = (val & ~OHCI_STATUS_SOC);
1660f1ae32a1SGerd Hoffmann 
1661f1ae32a1SGerd Hoffmann         /* Bits written as '0' remain unchanged in the register */
1662f1ae32a1SGerd Hoffmann         ohci->status |= val;
1663f1ae32a1SGerd Hoffmann 
1664f1ae32a1SGerd Hoffmann         if (ohci->status & OHCI_STATUS_HCR)
1665f1ae32a1SGerd Hoffmann             ohci_reset(ohci);
1666f1ae32a1SGerd Hoffmann         break;
1667f1ae32a1SGerd Hoffmann 
1668f1ae32a1SGerd Hoffmann     case 3: /* HcInterruptStatus */
1669f1ae32a1SGerd Hoffmann         ohci->intr_status &= ~val;
1670f1ae32a1SGerd Hoffmann         ohci_intr_update(ohci);
1671f1ae32a1SGerd Hoffmann         break;
1672f1ae32a1SGerd Hoffmann 
1673f1ae32a1SGerd Hoffmann     case 4: /* HcInterruptEnable */
1674f1ae32a1SGerd Hoffmann         ohci->intr |= val;
1675f1ae32a1SGerd Hoffmann         ohci_intr_update(ohci);
1676f1ae32a1SGerd Hoffmann         break;
1677f1ae32a1SGerd Hoffmann 
1678f1ae32a1SGerd Hoffmann     case 5: /* HcInterruptDisable */
1679f1ae32a1SGerd Hoffmann         ohci->intr &= ~val;
1680f1ae32a1SGerd Hoffmann         ohci_intr_update(ohci);
1681f1ae32a1SGerd Hoffmann         break;
1682f1ae32a1SGerd Hoffmann 
1683f1ae32a1SGerd Hoffmann     case 6: /* HcHCCA */
1684f1ae32a1SGerd Hoffmann         ohci->hcca = val & OHCI_HCCA_MASK;
1685f1ae32a1SGerd Hoffmann         break;
1686f1ae32a1SGerd Hoffmann 
1687f1ae32a1SGerd Hoffmann     case 7: /* HcPeriodCurrentED */
1688f1ae32a1SGerd Hoffmann         /* Ignore writes to this read-only register, Linux does them */
1689f1ae32a1SGerd Hoffmann         break;
1690f1ae32a1SGerd Hoffmann 
1691f1ae32a1SGerd Hoffmann     case 8: /* HcControlHeadED */
1692f1ae32a1SGerd Hoffmann         ohci->ctrl_head = val & OHCI_EDPTR_MASK;
1693f1ae32a1SGerd Hoffmann         break;
1694f1ae32a1SGerd Hoffmann 
1695f1ae32a1SGerd Hoffmann     case 9: /* HcControlCurrentED */
1696f1ae32a1SGerd Hoffmann         ohci->ctrl_cur = val & OHCI_EDPTR_MASK;
1697f1ae32a1SGerd Hoffmann         break;
1698f1ae32a1SGerd Hoffmann 
1699f1ae32a1SGerd Hoffmann     case 10: /* HcBulkHeadED */
1700f1ae32a1SGerd Hoffmann         ohci->bulk_head = val & OHCI_EDPTR_MASK;
1701f1ae32a1SGerd Hoffmann         break;
1702f1ae32a1SGerd Hoffmann 
1703f1ae32a1SGerd Hoffmann     case 11: /* HcBulkCurrentED */
1704f1ae32a1SGerd Hoffmann         ohci->bulk_cur = val & OHCI_EDPTR_MASK;
1705f1ae32a1SGerd Hoffmann         break;
1706f1ae32a1SGerd Hoffmann 
1707f1ae32a1SGerd Hoffmann     case 13: /* HcFmInterval */
1708f1ae32a1SGerd Hoffmann         ohci->fsmps = (val & OHCI_FMI_FSMPS) >> 16;
1709f1ae32a1SGerd Hoffmann         ohci->fit = (val & OHCI_FMI_FIT) >> 31;
1710f1ae32a1SGerd Hoffmann         ohci_set_frame_interval(ohci, val);
1711f1ae32a1SGerd Hoffmann         break;
1712f1ae32a1SGerd Hoffmann 
1713f1ae32a1SGerd Hoffmann     case 15: /* HcFmNumber */
1714f1ae32a1SGerd Hoffmann         break;
1715f1ae32a1SGerd Hoffmann 
1716f1ae32a1SGerd Hoffmann     case 16: /* HcPeriodicStart */
1717f1ae32a1SGerd Hoffmann         ohci->pstart = val & 0xffff;
1718f1ae32a1SGerd Hoffmann         break;
1719f1ae32a1SGerd Hoffmann 
1720f1ae32a1SGerd Hoffmann     case 17: /* HcLSThreshold */
1721f1ae32a1SGerd Hoffmann         ohci->lst = val & 0xffff;
1722f1ae32a1SGerd Hoffmann         break;
1723f1ae32a1SGerd Hoffmann 
1724f1ae32a1SGerd Hoffmann     case 18: /* HcRhDescriptorA */
1725f1ae32a1SGerd Hoffmann         ohci->rhdesc_a &= ~OHCI_RHA_RW_MASK;
1726f1ae32a1SGerd Hoffmann         ohci->rhdesc_a |= val & OHCI_RHA_RW_MASK;
1727f1ae32a1SGerd Hoffmann         break;
1728f1ae32a1SGerd Hoffmann 
1729f1ae32a1SGerd Hoffmann     case 19: /* HcRhDescriptorB */
1730f1ae32a1SGerd Hoffmann         break;
1731f1ae32a1SGerd Hoffmann 
1732f1ae32a1SGerd Hoffmann     case 20: /* HcRhStatus */
1733f1ae32a1SGerd Hoffmann         ohci_set_hub_status(ohci, val);
1734f1ae32a1SGerd Hoffmann         break;
1735f1ae32a1SGerd Hoffmann 
1736f1ae32a1SGerd Hoffmann     /* PXA27x specific registers */
1737f1ae32a1SGerd Hoffmann     case 24: /* HcStatus */
1738f1ae32a1SGerd Hoffmann         ohci->hstatus &= ~(val & ohci->hmask);
1739f1ae32a1SGerd Hoffmann 
1740f1ae32a1SGerd Hoffmann     case 25: /* HcHReset */
1741f1ae32a1SGerd Hoffmann         ohci->hreset = val & ~OHCI_HRESET_FSBIR;
1742f1ae32a1SGerd Hoffmann         if (val & OHCI_HRESET_FSBIR)
1743f1ae32a1SGerd Hoffmann             ohci_reset(ohci);
1744f1ae32a1SGerd Hoffmann         break;
1745f1ae32a1SGerd Hoffmann 
1746f1ae32a1SGerd Hoffmann     case 26: /* HcHInterruptEnable */
1747f1ae32a1SGerd Hoffmann         ohci->hmask = val;
1748f1ae32a1SGerd Hoffmann         break;
1749f1ae32a1SGerd Hoffmann 
1750f1ae32a1SGerd Hoffmann     case 27: /* HcHInterruptTest */
1751f1ae32a1SGerd Hoffmann         ohci->htest = val;
1752f1ae32a1SGerd Hoffmann         break;
1753f1ae32a1SGerd Hoffmann 
1754f1ae32a1SGerd Hoffmann     default:
1755f1ae32a1SGerd Hoffmann         fprintf(stderr, "ohci_write: Bad offset %x\n", (int)addr);
1756f1ae32a1SGerd Hoffmann         break;
1757f1ae32a1SGerd Hoffmann     }
1758f1ae32a1SGerd Hoffmann }
1759f1ae32a1SGerd Hoffmann 
1760f1ae32a1SGerd Hoffmann static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev)
1761f1ae32a1SGerd Hoffmann {
1762f1ae32a1SGerd Hoffmann     if (ohci->async_td &&
1763f1ae32a1SGerd Hoffmann         usb_packet_is_inflight(&ohci->usb_packet) &&
1764f1ae32a1SGerd Hoffmann         ohci->usb_packet.ep->dev == dev) {
1765f1ae32a1SGerd Hoffmann         usb_cancel_packet(&ohci->usb_packet);
1766f1ae32a1SGerd Hoffmann         ohci->async_td = 0;
1767f1ae32a1SGerd Hoffmann     }
1768f1ae32a1SGerd Hoffmann }
1769f1ae32a1SGerd Hoffmann 
1770f1ae32a1SGerd Hoffmann static const MemoryRegionOps ohci_mem_ops = {
1771f1ae32a1SGerd Hoffmann     .read = ohci_mem_read,
1772f1ae32a1SGerd Hoffmann     .write = ohci_mem_write,
1773f1ae32a1SGerd Hoffmann     .endianness = DEVICE_LITTLE_ENDIAN,
1774f1ae32a1SGerd Hoffmann };
1775f1ae32a1SGerd Hoffmann 
1776f1ae32a1SGerd Hoffmann static USBPortOps ohci_port_ops = {
1777f1ae32a1SGerd Hoffmann     .attach = ohci_attach,
1778f1ae32a1SGerd Hoffmann     .detach = ohci_detach,
1779f1ae32a1SGerd Hoffmann     .child_detach = ohci_child_detach,
1780f1ae32a1SGerd Hoffmann     .wakeup = ohci_wakeup,
1781f1ae32a1SGerd Hoffmann     .complete = ohci_async_complete_packet,
1782f1ae32a1SGerd Hoffmann };
1783f1ae32a1SGerd Hoffmann 
1784f1ae32a1SGerd Hoffmann static USBBusOps ohci_bus_ops = {
1785f1ae32a1SGerd Hoffmann };
1786f1ae32a1SGerd Hoffmann 
1787f1ae32a1SGerd Hoffmann static int usb_ohci_init(OHCIState *ohci, DeviceState *dev,
17889ac6a217SDavid Gibson                          int num_ports, dma_addr_t localmem_base,
17899ac6a217SDavid Gibson                          char *masterbus, uint32_t firstport,
17909ac6a217SDavid Gibson                          DMAContext *dma)
1791f1ae32a1SGerd Hoffmann {
1792f1ae32a1SGerd Hoffmann     int i;
1793f1ae32a1SGerd Hoffmann 
17949ac6a217SDavid Gibson     ohci->dma = dma;
17959ac6a217SDavid Gibson 
1796f1ae32a1SGerd Hoffmann     if (usb_frame_time == 0) {
1797f1ae32a1SGerd Hoffmann #ifdef OHCI_TIME_WARP
1798f1ae32a1SGerd Hoffmann         usb_frame_time = get_ticks_per_sec();
1799f1ae32a1SGerd Hoffmann         usb_bit_time = muldiv64(1, get_ticks_per_sec(), USB_HZ/1000);
1800f1ae32a1SGerd Hoffmann #else
1801f1ae32a1SGerd Hoffmann         usb_frame_time = muldiv64(1, get_ticks_per_sec(), 1000);
1802f1ae32a1SGerd Hoffmann         if (get_ticks_per_sec() >= USB_HZ) {
1803f1ae32a1SGerd Hoffmann             usb_bit_time = muldiv64(1, get_ticks_per_sec(), USB_HZ);
1804f1ae32a1SGerd Hoffmann         } else {
1805f1ae32a1SGerd Hoffmann             usb_bit_time = 1;
1806f1ae32a1SGerd Hoffmann         }
1807f1ae32a1SGerd Hoffmann #endif
1808f1ae32a1SGerd Hoffmann         DPRINTF("usb-ohci: usb_bit_time=%" PRId64 " usb_frame_time=%" PRId64 "\n",
1809f1ae32a1SGerd Hoffmann                 usb_frame_time, usb_bit_time);
1810f1ae32a1SGerd Hoffmann     }
1811f1ae32a1SGerd Hoffmann 
1812f1ae32a1SGerd Hoffmann     ohci->num_ports = num_ports;
1813f1ae32a1SGerd Hoffmann     if (masterbus) {
1814f1ae32a1SGerd Hoffmann         USBPort *ports[OHCI_MAX_PORTS];
1815f1ae32a1SGerd Hoffmann         for(i = 0; i < num_ports; i++) {
1816f1ae32a1SGerd Hoffmann             ports[i] = &ohci->rhport[i].port;
1817f1ae32a1SGerd Hoffmann         }
1818f1ae32a1SGerd Hoffmann         if (usb_register_companion(masterbus, ports, num_ports,
1819f1ae32a1SGerd Hoffmann                 firstport, ohci, &ohci_port_ops,
1820f1ae32a1SGerd Hoffmann                 USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL) != 0) {
1821f1ae32a1SGerd Hoffmann             return -1;
1822f1ae32a1SGerd Hoffmann         }
1823f1ae32a1SGerd Hoffmann     } else {
1824f1ae32a1SGerd Hoffmann         usb_bus_new(&ohci->bus, &ohci_bus_ops, dev);
1825f1ae32a1SGerd Hoffmann         for (i = 0; i < num_ports; i++) {
1826f1ae32a1SGerd Hoffmann             usb_register_port(&ohci->bus, &ohci->rhport[i].port,
1827f1ae32a1SGerd Hoffmann                               ohci, i, &ohci_port_ops,
1828f1ae32a1SGerd Hoffmann                               USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
1829f1ae32a1SGerd Hoffmann         }
1830f1ae32a1SGerd Hoffmann     }
1831f1ae32a1SGerd Hoffmann 
1832f1ae32a1SGerd Hoffmann     memory_region_init_io(&ohci->mem, &ohci_mem_ops, ohci, "ohci", 256);
1833f1ae32a1SGerd Hoffmann     ohci->localmem_base = localmem_base;
1834f1ae32a1SGerd Hoffmann 
1835f1ae32a1SGerd Hoffmann     ohci->name = object_get_typename(OBJECT(dev));
1836f1ae32a1SGerd Hoffmann     usb_packet_init(&ohci->usb_packet);
1837f1ae32a1SGerd Hoffmann 
1838f1ae32a1SGerd Hoffmann     ohci->async_td = 0;
1839f1ae32a1SGerd Hoffmann     qemu_register_reset(ohci_reset, ohci);
1840f1ae32a1SGerd Hoffmann 
1841f1ae32a1SGerd Hoffmann     return 0;
1842f1ae32a1SGerd Hoffmann }
1843f1ae32a1SGerd Hoffmann 
1844f1ae32a1SGerd Hoffmann typedef struct {
1845f1ae32a1SGerd Hoffmann     PCIDevice pci_dev;
1846f1ae32a1SGerd Hoffmann     OHCIState state;
1847f1ae32a1SGerd Hoffmann     char *masterbus;
1848f1ae32a1SGerd Hoffmann     uint32_t num_ports;
1849f1ae32a1SGerd Hoffmann     uint32_t firstport;
1850f1ae32a1SGerd Hoffmann } OHCIPCIState;
1851f1ae32a1SGerd Hoffmann 
1852f1ae32a1SGerd Hoffmann static int usb_ohci_initfn_pci(struct PCIDevice *dev)
1853f1ae32a1SGerd Hoffmann {
1854f1ae32a1SGerd Hoffmann     OHCIPCIState *ohci = DO_UPCAST(OHCIPCIState, pci_dev, dev);
1855f1ae32a1SGerd Hoffmann 
1856f1ae32a1SGerd Hoffmann     ohci->pci_dev.config[PCI_CLASS_PROG] = 0x10; /* OHCI */
1857f1ae32a1SGerd Hoffmann     ohci->pci_dev.config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */
1858f1ae32a1SGerd Hoffmann 
1859f1ae32a1SGerd Hoffmann     if (usb_ohci_init(&ohci->state, &dev->qdev, ohci->num_ports, 0,
18609ac6a217SDavid Gibson                       ohci->masterbus, ohci->firstport,
18619ac6a217SDavid Gibson                       pci_dma_context(dev)) != 0) {
1862f1ae32a1SGerd Hoffmann         return -1;
1863f1ae32a1SGerd Hoffmann     }
1864f1ae32a1SGerd Hoffmann     ohci->state.irq = ohci->pci_dev.irq[0];
1865f1ae32a1SGerd Hoffmann 
1866f1ae32a1SGerd Hoffmann     /* TODO: avoid cast below by using dev */
1867f1ae32a1SGerd Hoffmann     pci_register_bar(&ohci->pci_dev, 0, 0, &ohci->state.mem);
1868f1ae32a1SGerd Hoffmann     return 0;
1869f1ae32a1SGerd Hoffmann }
1870f1ae32a1SGerd Hoffmann 
1871f1ae32a1SGerd Hoffmann typedef struct {
1872f1ae32a1SGerd Hoffmann     SysBusDevice busdev;
1873f1ae32a1SGerd Hoffmann     OHCIState ohci;
1874f1ae32a1SGerd Hoffmann     uint32_t num_ports;
18759ac6a217SDavid Gibson     dma_addr_t dma_offset;
1876f1ae32a1SGerd Hoffmann } OHCISysBusState;
1877f1ae32a1SGerd Hoffmann 
1878f1ae32a1SGerd Hoffmann static int ohci_init_pxa(SysBusDevice *dev)
1879f1ae32a1SGerd Hoffmann {
1880f1ae32a1SGerd Hoffmann     OHCISysBusState *s = FROM_SYSBUS(OHCISysBusState, dev);
1881f1ae32a1SGerd Hoffmann 
1882f1ae32a1SGerd Hoffmann     /* Cannot fail as we pass NULL for masterbus */
18839ac6a217SDavid Gibson     usb_ohci_init(&s->ohci, &dev->qdev, s->num_ports, s->dma_offset, NULL, 0,
18849e11908fSPeter Maydell                   &dma_context_memory);
1885f1ae32a1SGerd Hoffmann     sysbus_init_irq(dev, &s->ohci.irq);
1886f1ae32a1SGerd Hoffmann     sysbus_init_mmio(dev, &s->ohci.mem);
1887f1ae32a1SGerd Hoffmann 
1888f1ae32a1SGerd Hoffmann     return 0;
1889f1ae32a1SGerd Hoffmann }
1890f1ae32a1SGerd Hoffmann 
1891f1ae32a1SGerd Hoffmann static Property ohci_pci_properties[] = {
1892f1ae32a1SGerd Hoffmann     DEFINE_PROP_STRING("masterbus", OHCIPCIState, masterbus),
1893f1ae32a1SGerd Hoffmann     DEFINE_PROP_UINT32("num-ports", OHCIPCIState, num_ports, 3),
1894f1ae32a1SGerd Hoffmann     DEFINE_PROP_UINT32("firstport", OHCIPCIState, firstport, 0),
1895f1ae32a1SGerd Hoffmann     DEFINE_PROP_END_OF_LIST(),
1896f1ae32a1SGerd Hoffmann };
1897f1ae32a1SGerd Hoffmann 
1898f1ae32a1SGerd Hoffmann static void ohci_pci_class_init(ObjectClass *klass, void *data)
1899f1ae32a1SGerd Hoffmann {
1900f1ae32a1SGerd Hoffmann     DeviceClass *dc = DEVICE_CLASS(klass);
1901f1ae32a1SGerd Hoffmann     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
1902f1ae32a1SGerd Hoffmann 
1903f1ae32a1SGerd Hoffmann     k->init = usb_ohci_initfn_pci;
1904f1ae32a1SGerd Hoffmann     k->vendor_id = PCI_VENDOR_ID_APPLE;
1905f1ae32a1SGerd Hoffmann     k->device_id = PCI_DEVICE_ID_APPLE_IPID_USB;
1906f1ae32a1SGerd Hoffmann     k->class_id = PCI_CLASS_SERIAL_USB;
19076c2d1c32SGerd Hoffmann     k->no_hotplug = 1;
1908f1ae32a1SGerd Hoffmann     dc->desc = "Apple USB Controller";
1909f1ae32a1SGerd Hoffmann     dc->props = ohci_pci_properties;
1910f1ae32a1SGerd Hoffmann }
1911f1ae32a1SGerd Hoffmann 
1912*8c43a6f0SAndreas Färber static const TypeInfo ohci_pci_info = {
1913f1ae32a1SGerd Hoffmann     .name          = "pci-ohci",
1914f1ae32a1SGerd Hoffmann     .parent        = TYPE_PCI_DEVICE,
1915f1ae32a1SGerd Hoffmann     .instance_size = sizeof(OHCIPCIState),
1916f1ae32a1SGerd Hoffmann     .class_init    = ohci_pci_class_init,
1917f1ae32a1SGerd Hoffmann };
1918f1ae32a1SGerd Hoffmann 
1919f1ae32a1SGerd Hoffmann static Property ohci_sysbus_properties[] = {
1920f1ae32a1SGerd Hoffmann     DEFINE_PROP_UINT32("num-ports", OHCISysBusState, num_ports, 3),
19219ac6a217SDavid Gibson     DEFINE_PROP_DMAADDR("dma-offset", OHCISysBusState, dma_offset, 3),
1922f1ae32a1SGerd Hoffmann     DEFINE_PROP_END_OF_LIST(),
1923f1ae32a1SGerd Hoffmann };
1924f1ae32a1SGerd Hoffmann 
1925f1ae32a1SGerd Hoffmann static void ohci_sysbus_class_init(ObjectClass *klass, void *data)
1926f1ae32a1SGerd Hoffmann {
1927f1ae32a1SGerd Hoffmann     DeviceClass *dc = DEVICE_CLASS(klass);
1928f1ae32a1SGerd Hoffmann     SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
1929f1ae32a1SGerd Hoffmann 
1930f1ae32a1SGerd Hoffmann     sbc->init = ohci_init_pxa;
1931f1ae32a1SGerd Hoffmann     dc->desc = "OHCI USB Controller";
1932f1ae32a1SGerd Hoffmann     dc->props = ohci_sysbus_properties;
1933f1ae32a1SGerd Hoffmann }
1934f1ae32a1SGerd Hoffmann 
1935*8c43a6f0SAndreas Färber static const TypeInfo ohci_sysbus_info = {
1936f1ae32a1SGerd Hoffmann     .name          = "sysbus-ohci",
1937f1ae32a1SGerd Hoffmann     .parent        = TYPE_SYS_BUS_DEVICE,
1938f1ae32a1SGerd Hoffmann     .instance_size = sizeof(OHCISysBusState),
1939f1ae32a1SGerd Hoffmann     .class_init    = ohci_sysbus_class_init,
1940f1ae32a1SGerd Hoffmann };
1941f1ae32a1SGerd Hoffmann 
1942f1ae32a1SGerd Hoffmann static void ohci_register_types(void)
1943f1ae32a1SGerd Hoffmann {
1944f1ae32a1SGerd Hoffmann     type_register_static(&ohci_pci_info);
1945f1ae32a1SGerd Hoffmann     type_register_static(&ohci_sysbus_info);
1946f1ae32a1SGerd Hoffmann }
1947f1ae32a1SGerd Hoffmann 
1948f1ae32a1SGerd Hoffmann type_init(ohci_register_types)
1949