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