xref: /openbmc/qemu/hw/usb/hcd-ohci.c (revision 00b01793)
1f1ae32a1SGerd Hoffmann /*
2f1ae32a1SGerd Hoffmann  * QEMU USB OHCI Emulation
3f1ae32a1SGerd Hoffmann  * Copyright (c) 2004 Gianni Tedesco
4f1ae32a1SGerd Hoffmann  * Copyright (c) 2006 CodeSourcery
5f1ae32a1SGerd Hoffmann  * Copyright (c) 2006 Openedhand Ltd.
6f1ae32a1SGerd Hoffmann  *
7f1ae32a1SGerd Hoffmann  * This library is free software; you can redistribute it and/or
8f1ae32a1SGerd Hoffmann  * modify it under the terms of the GNU Lesser General Public
9f1ae32a1SGerd Hoffmann  * License as published by the Free Software Foundation; either
10f1ae32a1SGerd Hoffmann  * version 2 of the License, or (at your option) any later version.
11f1ae32a1SGerd Hoffmann  *
12f1ae32a1SGerd Hoffmann  * This library is distributed in the hope that it will be useful,
13f1ae32a1SGerd Hoffmann  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14f1ae32a1SGerd Hoffmann  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15f1ae32a1SGerd Hoffmann  * Lesser General Public License for more details.
16f1ae32a1SGerd Hoffmann  *
17f1ae32a1SGerd Hoffmann  * You should have received a copy of the GNU Lesser General Public
18f1ae32a1SGerd Hoffmann  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19f1ae32a1SGerd Hoffmann  *
20f1ae32a1SGerd Hoffmann  * TODO:
21f1ae32a1SGerd Hoffmann  *  o Isochronous transfers
22f1ae32a1SGerd Hoffmann  *  o Allocate bandwidth in frames properly
23f1ae32a1SGerd Hoffmann  *  o Disable timers when nothing needs to be done, or remove timer usage
24f1ae32a1SGerd Hoffmann  *    all together.
25f1ae32a1SGerd Hoffmann  *  o BIOS work to boot from USB storage
26f1ae32a1SGerd Hoffmann */
27f1ae32a1SGerd Hoffmann 
28f1ae32a1SGerd Hoffmann #include "hw/hw.h"
291de7afc9SPaolo Bonzini #include "qemu/timer.h"
30f1ae32a1SGerd Hoffmann #include "hw/usb.h"
31a2cb15b0SMichael S. Tsirkin #include "hw/pci/pci.h"
32f1ae32a1SGerd Hoffmann #include "hw/sysbus.h"
339ac6a217SDavid Gibson #include "hw/qdev-dma.h"
34f1ae32a1SGerd Hoffmann 
35f1ae32a1SGerd Hoffmann //#define DEBUG_OHCI
36f1ae32a1SGerd Hoffmann /* Dump packet contents.  */
37f1ae32a1SGerd Hoffmann //#define DEBUG_PACKET
38f1ae32a1SGerd Hoffmann //#define DEBUG_ISOCH
39f1ae32a1SGerd Hoffmann /* This causes frames to occur 1000x slower */
40f1ae32a1SGerd Hoffmann //#define OHCI_TIME_WARP 1
41f1ae32a1SGerd Hoffmann 
42f1ae32a1SGerd Hoffmann #ifdef DEBUG_OHCI
43f1ae32a1SGerd Hoffmann #define DPRINTF printf
44f1ae32a1SGerd Hoffmann #else
45f1ae32a1SGerd Hoffmann #define DPRINTF(...)
46f1ae32a1SGerd Hoffmann #endif
47f1ae32a1SGerd Hoffmann 
48f1ae32a1SGerd Hoffmann /* Number of Downstream Ports on the root hub.  */
49f1ae32a1SGerd Hoffmann 
50f1ae32a1SGerd Hoffmann #define OHCI_MAX_PORTS 15
51f1ae32a1SGerd Hoffmann 
52f1ae32a1SGerd Hoffmann static int64_t usb_frame_time;
53f1ae32a1SGerd Hoffmann static int64_t usb_bit_time;
54f1ae32a1SGerd Hoffmann 
55f1ae32a1SGerd Hoffmann typedef struct OHCIPort {
56f1ae32a1SGerd Hoffmann     USBPort port;
57f1ae32a1SGerd Hoffmann     uint32_t ctrl;
58f1ae32a1SGerd Hoffmann } OHCIPort;
59f1ae32a1SGerd Hoffmann 
60f1ae32a1SGerd Hoffmann typedef struct {
61f1ae32a1SGerd Hoffmann     USBBus bus;
62f1ae32a1SGerd Hoffmann     qemu_irq irq;
63f1ae32a1SGerd Hoffmann     MemoryRegion mem;
64df32fd1cSPaolo Bonzini     AddressSpace *as;
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 */
1079ac6a217SDavid Gibson     dma_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 };
12486e18caeSWei Yang #define HCCA_WRITEBACK_OFFSET   offsetof(struct ohci_hcca, frame)
12586e18caeSWei Yang #define HCCA_WRITEBACK_SIZE     8 /* frame, pad, done */
12686e18caeSWei Yang 
12786e18caeSWei Yang #define ED_WBACK_OFFSET offsetof(struct ohci_ed, head)
12886e18caeSWei 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 
237*00b01793SPeter Maydell #define OHCI_INTR_SO          (1U<<0) /* Scheduling overrun */
238*00b01793SPeter Maydell #define OHCI_INTR_WD          (1U<<1) /* HcDoneHead writeback */
239*00b01793SPeter Maydell #define OHCI_INTR_SF          (1U<<2) /* Start of frame */
240*00b01793SPeter Maydell #define OHCI_INTR_RD          (1U<<3) /* Resume detect */
241*00b01793SPeter Maydell #define OHCI_INTR_UE          (1U<<4) /* Unrecoverable error */
242*00b01793SPeter Maydell #define OHCI_INTR_FNO         (1U<<5) /* Frame number overflow */
243*00b01793SPeter Maydell #define OHCI_INTR_RHSC        (1U<<6) /* Root hub status change */
244*00b01793SPeter Maydell #define OHCI_INTR_OC          (1U<<30) /* Ownership change */
245*00b01793SPeter Maydell #define OHCI_INTR_MIE         (1U<<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 
256*00b01793SPeter Maydell #define OHCI_FR_RT            (1U<<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 
268*00b01793SPeter Maydell #define OHCI_RHS_LPS          (1U<<0)
269*00b01793SPeter Maydell #define OHCI_RHS_OCI          (1U<<1)
270*00b01793SPeter Maydell #define OHCI_RHS_DRWE         (1U<<15)
271*00b01793SPeter Maydell #define OHCI_RHS_LPSC         (1U<<16)
272*00b01793SPeter Maydell #define OHCI_RHS_OCIC         (1U<<17)
273*00b01793SPeter Maydell #define OHCI_RHS_CRWE         (1U<<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 
310cf66ee8eSAlexey Kardashevskiy static void ohci_die(OHCIState *ohci);
311cf66ee8eSAlexey Kardashevskiy 
312f1ae32a1SGerd Hoffmann /* Update IRQ levels */
313f1ae32a1SGerd Hoffmann static inline void ohci_intr_update(OHCIState *ohci)
314f1ae32a1SGerd Hoffmann {
315f1ae32a1SGerd Hoffmann     int level = 0;
316f1ae32a1SGerd Hoffmann 
317f1ae32a1SGerd Hoffmann     if ((ohci->intr & OHCI_INTR_MIE) &&
318f1ae32a1SGerd Hoffmann         (ohci->intr_status & ohci->intr))
319f1ae32a1SGerd Hoffmann         level = 1;
320f1ae32a1SGerd Hoffmann 
321f1ae32a1SGerd Hoffmann     qemu_set_irq(ohci->irq, level);
322f1ae32a1SGerd Hoffmann }
323f1ae32a1SGerd Hoffmann 
324f1ae32a1SGerd Hoffmann /* Set an interrupt */
325f1ae32a1SGerd Hoffmann static inline void ohci_set_interrupt(OHCIState *ohci, uint32_t intr)
326f1ae32a1SGerd Hoffmann {
327f1ae32a1SGerd Hoffmann     ohci->intr_status |= intr;
328f1ae32a1SGerd Hoffmann     ohci_intr_update(ohci);
329f1ae32a1SGerd Hoffmann }
330f1ae32a1SGerd Hoffmann 
331f1ae32a1SGerd Hoffmann /* Attach or detach a device on a root hub port.  */
332f1ae32a1SGerd Hoffmann static void ohci_attach(USBPort *port1)
333f1ae32a1SGerd Hoffmann {
334f1ae32a1SGerd Hoffmann     OHCIState *s = port1->opaque;
335f1ae32a1SGerd Hoffmann     OHCIPort *port = &s->rhport[port1->index];
336f1ae32a1SGerd Hoffmann     uint32_t old_state = port->ctrl;
337f1ae32a1SGerd Hoffmann 
338f1ae32a1SGerd Hoffmann     /* set connect status */
339f1ae32a1SGerd Hoffmann     port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;
340f1ae32a1SGerd Hoffmann 
341f1ae32a1SGerd Hoffmann     /* update speed */
342f1ae32a1SGerd Hoffmann     if (port->port.dev->speed == USB_SPEED_LOW) {
343f1ae32a1SGerd Hoffmann         port->ctrl |= OHCI_PORT_LSDA;
344f1ae32a1SGerd Hoffmann     } else {
345f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_LSDA;
346f1ae32a1SGerd Hoffmann     }
347f1ae32a1SGerd Hoffmann 
348f1ae32a1SGerd Hoffmann     /* notify of remote-wakeup */
349f1ae32a1SGerd Hoffmann     if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
350f1ae32a1SGerd Hoffmann         ohci_set_interrupt(s, OHCI_INTR_RD);
351f1ae32a1SGerd Hoffmann     }
352f1ae32a1SGerd Hoffmann 
353f1ae32a1SGerd Hoffmann     DPRINTF("usb-ohci: Attached port %d\n", port1->index);
354f1ae32a1SGerd Hoffmann 
355f1ae32a1SGerd Hoffmann     if (old_state != port->ctrl) {
356f1ae32a1SGerd Hoffmann         ohci_set_interrupt(s, OHCI_INTR_RHSC);
357f1ae32a1SGerd Hoffmann     }
358f1ae32a1SGerd Hoffmann }
359f1ae32a1SGerd Hoffmann 
360f1ae32a1SGerd Hoffmann static void ohci_detach(USBPort *port1)
361f1ae32a1SGerd Hoffmann {
362f1ae32a1SGerd Hoffmann     OHCIState *s = port1->opaque;
363f1ae32a1SGerd Hoffmann     OHCIPort *port = &s->rhport[port1->index];
364f1ae32a1SGerd Hoffmann     uint32_t old_state = port->ctrl;
365f1ae32a1SGerd Hoffmann 
366f1ae32a1SGerd Hoffmann     ohci_async_cancel_device(s, port1->dev);
367f1ae32a1SGerd Hoffmann 
368f1ae32a1SGerd Hoffmann     /* set connect status */
369f1ae32a1SGerd Hoffmann     if (port->ctrl & OHCI_PORT_CCS) {
370f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_CCS;
371f1ae32a1SGerd Hoffmann         port->ctrl |= OHCI_PORT_CSC;
372f1ae32a1SGerd Hoffmann     }
373f1ae32a1SGerd Hoffmann     /* disable port */
374f1ae32a1SGerd Hoffmann     if (port->ctrl & OHCI_PORT_PES) {
375f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_PES;
376f1ae32a1SGerd Hoffmann         port->ctrl |= OHCI_PORT_PESC;
377f1ae32a1SGerd Hoffmann     }
378f1ae32a1SGerd Hoffmann     DPRINTF("usb-ohci: Detached port %d\n", port1->index);
379f1ae32a1SGerd Hoffmann 
380f1ae32a1SGerd Hoffmann     if (old_state != port->ctrl) {
381f1ae32a1SGerd Hoffmann         ohci_set_interrupt(s, OHCI_INTR_RHSC);
382f1ae32a1SGerd Hoffmann     }
383f1ae32a1SGerd Hoffmann }
384f1ae32a1SGerd Hoffmann 
385f1ae32a1SGerd Hoffmann static void ohci_wakeup(USBPort *port1)
386f1ae32a1SGerd Hoffmann {
387f1ae32a1SGerd Hoffmann     OHCIState *s = port1->opaque;
388f1ae32a1SGerd Hoffmann     OHCIPort *port = &s->rhport[port1->index];
389f1ae32a1SGerd Hoffmann     uint32_t intr = 0;
390f1ae32a1SGerd Hoffmann     if (port->ctrl & OHCI_PORT_PSS) {
391f1ae32a1SGerd Hoffmann         DPRINTF("usb-ohci: port %d: wakeup\n", port1->index);
392f1ae32a1SGerd Hoffmann         port->ctrl |= OHCI_PORT_PSSC;
393f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_PSS;
394f1ae32a1SGerd Hoffmann         intr = OHCI_INTR_RHSC;
395f1ae32a1SGerd Hoffmann     }
396f1ae32a1SGerd Hoffmann     /* Note that the controller can be suspended even if this port is not */
397f1ae32a1SGerd Hoffmann     if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
398f1ae32a1SGerd Hoffmann         DPRINTF("usb-ohci: remote-wakeup: SUSPEND->RESUME\n");
399f1ae32a1SGerd Hoffmann         /* This is the one state transition the controller can do by itself */
400f1ae32a1SGerd Hoffmann         s->ctl &= ~OHCI_CTL_HCFS;
401f1ae32a1SGerd Hoffmann         s->ctl |= OHCI_USB_RESUME;
402f1ae32a1SGerd Hoffmann         /* In suspend mode only ResumeDetected is possible, not RHSC:
403f1ae32a1SGerd Hoffmann          * see the OHCI spec 5.1.2.3.
404f1ae32a1SGerd Hoffmann          */
405f1ae32a1SGerd Hoffmann         intr = OHCI_INTR_RD;
406f1ae32a1SGerd Hoffmann     }
407f1ae32a1SGerd Hoffmann     ohci_set_interrupt(s, intr);
408f1ae32a1SGerd Hoffmann }
409f1ae32a1SGerd Hoffmann 
410f1ae32a1SGerd Hoffmann static void ohci_child_detach(USBPort *port1, USBDevice *child)
411f1ae32a1SGerd Hoffmann {
412f1ae32a1SGerd Hoffmann     OHCIState *s = port1->opaque;
413f1ae32a1SGerd Hoffmann 
414f1ae32a1SGerd Hoffmann     ohci_async_cancel_device(s, child);
415f1ae32a1SGerd Hoffmann }
416f1ae32a1SGerd Hoffmann 
417f1ae32a1SGerd Hoffmann static USBDevice *ohci_find_device(OHCIState *ohci, uint8_t addr)
418f1ae32a1SGerd Hoffmann {
419f1ae32a1SGerd Hoffmann     USBDevice *dev;
420f1ae32a1SGerd Hoffmann     int i;
421f1ae32a1SGerd Hoffmann 
422f1ae32a1SGerd Hoffmann     for (i = 0; i < ohci->num_ports; i++) {
423f1ae32a1SGerd Hoffmann         if ((ohci->rhport[i].ctrl & OHCI_PORT_PES) == 0) {
424f1ae32a1SGerd Hoffmann             continue;
425f1ae32a1SGerd Hoffmann         }
426f1ae32a1SGerd Hoffmann         dev = usb_find_device(&ohci->rhport[i].port, addr);
427f1ae32a1SGerd Hoffmann         if (dev != NULL) {
428f1ae32a1SGerd Hoffmann             return dev;
429f1ae32a1SGerd Hoffmann         }
430f1ae32a1SGerd Hoffmann     }
431f1ae32a1SGerd Hoffmann     return NULL;
432f1ae32a1SGerd Hoffmann }
433f1ae32a1SGerd Hoffmann 
434f79738b0SHans de Goede static void ohci_stop_endpoints(OHCIState *ohci)
435f79738b0SHans de Goede {
436f79738b0SHans de Goede     USBDevice *dev;
437f79738b0SHans de Goede     int i, j;
438f79738b0SHans de Goede 
439f79738b0SHans de Goede     for (i = 0; i < ohci->num_ports; i++) {
440f79738b0SHans de Goede         dev = ohci->rhport[i].port.dev;
441f79738b0SHans de Goede         if (dev && dev->attached) {
442f79738b0SHans de Goede             usb_device_ep_stopped(dev, &dev->ep_ctl);
443f79738b0SHans de Goede             for (j = 0; j < USB_MAX_ENDPOINTS; j++) {
444f79738b0SHans de Goede                 usb_device_ep_stopped(dev, &dev->ep_in[j]);
445f79738b0SHans de Goede                 usb_device_ep_stopped(dev, &dev->ep_out[j]);
446f79738b0SHans de Goede             }
447f79738b0SHans de Goede         }
448f79738b0SHans de Goede     }
449f79738b0SHans de Goede }
450f79738b0SHans de Goede 
451f1ae32a1SGerd Hoffmann /* Reset the controller */
452f1ae32a1SGerd Hoffmann static void ohci_reset(void *opaque)
453f1ae32a1SGerd Hoffmann {
454f1ae32a1SGerd Hoffmann     OHCIState *ohci = opaque;
455f1ae32a1SGerd Hoffmann     OHCIPort *port;
456f1ae32a1SGerd Hoffmann     int i;
457f1ae32a1SGerd Hoffmann 
458f1ae32a1SGerd Hoffmann     ohci_bus_stop(ohci);
459f1ae32a1SGerd Hoffmann     ohci->ctl = 0;
460f1ae32a1SGerd Hoffmann     ohci->old_ctl = 0;
461f1ae32a1SGerd Hoffmann     ohci->status = 0;
462f1ae32a1SGerd Hoffmann     ohci->intr_status = 0;
463f1ae32a1SGerd Hoffmann     ohci->intr = OHCI_INTR_MIE;
464f1ae32a1SGerd Hoffmann 
465f1ae32a1SGerd Hoffmann     ohci->hcca = 0;
466f1ae32a1SGerd Hoffmann     ohci->ctrl_head = ohci->ctrl_cur = 0;
467f1ae32a1SGerd Hoffmann     ohci->bulk_head = ohci->bulk_cur = 0;
468f1ae32a1SGerd Hoffmann     ohci->per_cur = 0;
469f1ae32a1SGerd Hoffmann     ohci->done = 0;
470f1ae32a1SGerd Hoffmann     ohci->done_count = 7;
471f1ae32a1SGerd Hoffmann 
472f1ae32a1SGerd Hoffmann     /* FSMPS is marked TBD in OCHI 1.0, what gives ffs?
473f1ae32a1SGerd Hoffmann      * I took the value linux sets ...
474f1ae32a1SGerd Hoffmann      */
475f1ae32a1SGerd Hoffmann     ohci->fsmps = 0x2778;
476f1ae32a1SGerd Hoffmann     ohci->fi = 0x2edf;
477f1ae32a1SGerd Hoffmann     ohci->fit = 0;
478f1ae32a1SGerd Hoffmann     ohci->frt = 0;
479f1ae32a1SGerd Hoffmann     ohci->frame_number = 0;
480f1ae32a1SGerd Hoffmann     ohci->pstart = 0;
481f1ae32a1SGerd Hoffmann     ohci->lst = OHCI_LS_THRESH;
482f1ae32a1SGerd Hoffmann 
483f1ae32a1SGerd Hoffmann     ohci->rhdesc_a = OHCI_RHA_NPS | ohci->num_ports;
484f1ae32a1SGerd Hoffmann     ohci->rhdesc_b = 0x0; /* Impl. specific */
485f1ae32a1SGerd Hoffmann     ohci->rhstatus = 0;
486f1ae32a1SGerd Hoffmann 
487f1ae32a1SGerd Hoffmann     for (i = 0; i < ohci->num_ports; i++)
488f1ae32a1SGerd Hoffmann       {
489f1ae32a1SGerd Hoffmann         port = &ohci->rhport[i];
490f1ae32a1SGerd Hoffmann         port->ctrl = 0;
491f1ae32a1SGerd Hoffmann         if (port->port.dev && port->port.dev->attached) {
492f1ae32a1SGerd Hoffmann             usb_port_reset(&port->port);
493f1ae32a1SGerd Hoffmann         }
494f1ae32a1SGerd Hoffmann       }
495f1ae32a1SGerd Hoffmann     if (ohci->async_td) {
496f1ae32a1SGerd Hoffmann         usb_cancel_packet(&ohci->usb_packet);
497f1ae32a1SGerd Hoffmann         ohci->async_td = 0;
498f1ae32a1SGerd Hoffmann     }
499f79738b0SHans de Goede     ohci_stop_endpoints(ohci);
500f1ae32a1SGerd Hoffmann     DPRINTF("usb-ohci: Reset %s\n", ohci->name);
501f1ae32a1SGerd Hoffmann }
502f1ae32a1SGerd Hoffmann 
503f1ae32a1SGerd Hoffmann /* Get an array of dwords from main memory */
504f1ae32a1SGerd Hoffmann static inline int get_dwords(OHCIState *ohci,
5059ac6a217SDavid Gibson                              dma_addr_t addr, uint32_t *buf, int num)
506f1ae32a1SGerd Hoffmann {
507f1ae32a1SGerd Hoffmann     int i;
508f1ae32a1SGerd Hoffmann 
509f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
510f1ae32a1SGerd Hoffmann 
511f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
512cf66ee8eSAlexey Kardashevskiy         if (dma_memory_read(ohci->as, addr, buf, sizeof(*buf))) {
513cf66ee8eSAlexey Kardashevskiy             return -1;
514cf66ee8eSAlexey Kardashevskiy         }
515f1ae32a1SGerd Hoffmann         *buf = le32_to_cpu(*buf);
516f1ae32a1SGerd Hoffmann     }
517f1ae32a1SGerd Hoffmann 
518cf66ee8eSAlexey Kardashevskiy     return 0;
519f1ae32a1SGerd Hoffmann }
520f1ae32a1SGerd Hoffmann 
521f1ae32a1SGerd Hoffmann /* Put an array of dwords in to main memory */
522f1ae32a1SGerd Hoffmann static inline int put_dwords(OHCIState *ohci,
5239ac6a217SDavid Gibson                              dma_addr_t addr, uint32_t *buf, int num)
524f1ae32a1SGerd Hoffmann {
525f1ae32a1SGerd Hoffmann     int i;
526f1ae32a1SGerd Hoffmann 
527f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
528f1ae32a1SGerd Hoffmann 
529f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
530f1ae32a1SGerd Hoffmann         uint32_t tmp = cpu_to_le32(*buf);
531cf66ee8eSAlexey Kardashevskiy         if (dma_memory_write(ohci->as, addr, &tmp, sizeof(tmp))) {
532cf66ee8eSAlexey Kardashevskiy             return -1;
533cf66ee8eSAlexey Kardashevskiy         }
534f1ae32a1SGerd Hoffmann     }
535f1ae32a1SGerd Hoffmann 
536cf66ee8eSAlexey Kardashevskiy     return 0;
537f1ae32a1SGerd Hoffmann }
538f1ae32a1SGerd Hoffmann 
539f1ae32a1SGerd Hoffmann /* Get an array of words from main memory */
540f1ae32a1SGerd Hoffmann static inline int get_words(OHCIState *ohci,
5419ac6a217SDavid Gibson                             dma_addr_t addr, uint16_t *buf, int num)
542f1ae32a1SGerd Hoffmann {
543f1ae32a1SGerd Hoffmann     int i;
544f1ae32a1SGerd Hoffmann 
545f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
546f1ae32a1SGerd Hoffmann 
547f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
548cf66ee8eSAlexey Kardashevskiy         if (dma_memory_read(ohci->as, addr, buf, sizeof(*buf))) {
549cf66ee8eSAlexey Kardashevskiy             return -1;
550cf66ee8eSAlexey Kardashevskiy         }
551f1ae32a1SGerd Hoffmann         *buf = le16_to_cpu(*buf);
552f1ae32a1SGerd Hoffmann     }
553f1ae32a1SGerd Hoffmann 
554cf66ee8eSAlexey Kardashevskiy     return 0;
555f1ae32a1SGerd Hoffmann }
556f1ae32a1SGerd Hoffmann 
557f1ae32a1SGerd Hoffmann /* Put an array of words in to main memory */
558f1ae32a1SGerd Hoffmann static inline int put_words(OHCIState *ohci,
5599ac6a217SDavid Gibson                             dma_addr_t addr, uint16_t *buf, int num)
560f1ae32a1SGerd Hoffmann {
561f1ae32a1SGerd Hoffmann     int i;
562f1ae32a1SGerd Hoffmann 
563f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
564f1ae32a1SGerd Hoffmann 
565f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
566f1ae32a1SGerd Hoffmann         uint16_t tmp = cpu_to_le16(*buf);
567cf66ee8eSAlexey Kardashevskiy         if (dma_memory_write(ohci->as, addr, &tmp, sizeof(tmp))) {
568cf66ee8eSAlexey Kardashevskiy             return -1;
569cf66ee8eSAlexey Kardashevskiy         }
570f1ae32a1SGerd Hoffmann     }
571f1ae32a1SGerd Hoffmann 
572cf66ee8eSAlexey Kardashevskiy     return 0;
573f1ae32a1SGerd Hoffmann }
574f1ae32a1SGerd Hoffmann 
575f1ae32a1SGerd Hoffmann static inline int ohci_read_ed(OHCIState *ohci,
5769ac6a217SDavid Gibson                                dma_addr_t addr, struct ohci_ed *ed)
577f1ae32a1SGerd Hoffmann {
578f1ae32a1SGerd Hoffmann     return get_dwords(ohci, addr, (uint32_t *)ed, sizeof(*ed) >> 2);
579f1ae32a1SGerd Hoffmann }
580f1ae32a1SGerd Hoffmann 
581f1ae32a1SGerd Hoffmann static inline int ohci_read_td(OHCIState *ohci,
5829ac6a217SDavid Gibson                                dma_addr_t addr, struct ohci_td *td)
583f1ae32a1SGerd Hoffmann {
584f1ae32a1SGerd Hoffmann     return get_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2);
585f1ae32a1SGerd Hoffmann }
586f1ae32a1SGerd Hoffmann 
587f1ae32a1SGerd Hoffmann static inline int ohci_read_iso_td(OHCIState *ohci,
5889ac6a217SDavid Gibson                                    dma_addr_t addr, struct ohci_iso_td *td)
589f1ae32a1SGerd Hoffmann {
590cf66ee8eSAlexey Kardashevskiy     return get_dwords(ohci, addr, (uint32_t *)td, 4) ||
591cf66ee8eSAlexey Kardashevskiy            get_words(ohci, addr + 16, td->offset, 8);
592f1ae32a1SGerd Hoffmann }
593f1ae32a1SGerd Hoffmann 
594f1ae32a1SGerd Hoffmann static inline int ohci_read_hcca(OHCIState *ohci,
5959ac6a217SDavid Gibson                                  dma_addr_t addr, struct ohci_hcca *hcca)
596f1ae32a1SGerd Hoffmann {
597cf66ee8eSAlexey Kardashevskiy     return dma_memory_read(ohci->as, addr + ohci->localmem_base,
598cf66ee8eSAlexey Kardashevskiy                            hcca, sizeof(*hcca));
599f1ae32a1SGerd Hoffmann }
600f1ae32a1SGerd Hoffmann 
601f1ae32a1SGerd Hoffmann static inline int ohci_put_ed(OHCIState *ohci,
6029ac6a217SDavid Gibson                               dma_addr_t addr, struct ohci_ed *ed)
603f1ae32a1SGerd Hoffmann {
60486e18caeSWei Yang     /* ed->tail is under control of the HCD.
60586e18caeSWei Yang      * Since just ed->head is changed by HC, just write back this
60686e18caeSWei Yang      */
60786e18caeSWei Yang 
60886e18caeSWei Yang     return put_dwords(ohci, addr + ED_WBACK_OFFSET,
60986e18caeSWei Yang                       (uint32_t *)((char *)ed + ED_WBACK_OFFSET),
61086e18caeSWei Yang                       ED_WBACK_SIZE >> 2);
611f1ae32a1SGerd Hoffmann }
612f1ae32a1SGerd Hoffmann 
613f1ae32a1SGerd Hoffmann static inline int ohci_put_td(OHCIState *ohci,
6149ac6a217SDavid Gibson                               dma_addr_t addr, struct ohci_td *td)
615f1ae32a1SGerd Hoffmann {
616f1ae32a1SGerd Hoffmann     return put_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2);
617f1ae32a1SGerd Hoffmann }
618f1ae32a1SGerd Hoffmann 
619f1ae32a1SGerd Hoffmann static inline int ohci_put_iso_td(OHCIState *ohci,
6209ac6a217SDavid Gibson                                   dma_addr_t addr, struct ohci_iso_td *td)
621f1ae32a1SGerd Hoffmann {
622cf66ee8eSAlexey Kardashevskiy     return put_dwords(ohci, addr, (uint32_t *)td, 4 ||
623f1ae32a1SGerd Hoffmann            put_words(ohci, addr + 16, td->offset, 8));
624f1ae32a1SGerd Hoffmann }
625f1ae32a1SGerd Hoffmann 
626f1ae32a1SGerd Hoffmann static inline int ohci_put_hcca(OHCIState *ohci,
6279ac6a217SDavid Gibson                                 dma_addr_t addr, struct ohci_hcca *hcca)
628f1ae32a1SGerd Hoffmann {
629cf66ee8eSAlexey Kardashevskiy     return dma_memory_write(ohci->as,
6309ac6a217SDavid Gibson                             addr + ohci->localmem_base + HCCA_WRITEBACK_OFFSET,
63186e18caeSWei Yang                             (char *)hcca + HCCA_WRITEBACK_OFFSET,
63286e18caeSWei Yang                             HCCA_WRITEBACK_SIZE);
633f1ae32a1SGerd Hoffmann }
634f1ae32a1SGerd Hoffmann 
635f1ae32a1SGerd Hoffmann /* Read/Write the contents of a TD from/to main memory.  */
636cf66ee8eSAlexey Kardashevskiy static int ohci_copy_td(OHCIState *ohci, struct ohci_td *td,
6379ac6a217SDavid Gibson                         uint8_t *buf, int len, DMADirection dir)
638f1ae32a1SGerd Hoffmann {
6399ac6a217SDavid Gibson     dma_addr_t ptr, n;
640f1ae32a1SGerd Hoffmann 
641f1ae32a1SGerd Hoffmann     ptr = td->cbp;
642f1ae32a1SGerd Hoffmann     n = 0x1000 - (ptr & 0xfff);
643f1ae32a1SGerd Hoffmann     if (n > len)
644f1ae32a1SGerd Hoffmann         n = len;
645cf66ee8eSAlexey Kardashevskiy 
646cf66ee8eSAlexey Kardashevskiy     if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, n, dir)) {
647cf66ee8eSAlexey Kardashevskiy         return -1;
648cf66ee8eSAlexey Kardashevskiy     }
649cf66ee8eSAlexey Kardashevskiy     if (n == len) {
650cf66ee8eSAlexey Kardashevskiy         return 0;
651cf66ee8eSAlexey Kardashevskiy     }
652f1ae32a1SGerd Hoffmann     ptr = td->be & ~0xfffu;
653f1ae32a1SGerd Hoffmann     buf += n;
654cf66ee8eSAlexey Kardashevskiy     if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf,
655cf66ee8eSAlexey Kardashevskiy                       len - n, dir)) {
656cf66ee8eSAlexey Kardashevskiy         return -1;
657cf66ee8eSAlexey Kardashevskiy     }
658cf66ee8eSAlexey Kardashevskiy     return 0;
659f1ae32a1SGerd Hoffmann }
660f1ae32a1SGerd Hoffmann 
661f1ae32a1SGerd Hoffmann /* Read/Write the contents of an ISO TD from/to main memory.  */
662cf66ee8eSAlexey Kardashevskiy static int ohci_copy_iso_td(OHCIState *ohci,
663f1ae32a1SGerd Hoffmann                             uint32_t start_addr, uint32_t end_addr,
6649ac6a217SDavid Gibson                             uint8_t *buf, int len, DMADirection dir)
665f1ae32a1SGerd Hoffmann {
6669ac6a217SDavid Gibson     dma_addr_t ptr, n;
667f1ae32a1SGerd Hoffmann 
668f1ae32a1SGerd Hoffmann     ptr = start_addr;
669f1ae32a1SGerd Hoffmann     n = 0x1000 - (ptr & 0xfff);
670f1ae32a1SGerd Hoffmann     if (n > len)
671f1ae32a1SGerd Hoffmann         n = len;
672cf66ee8eSAlexey Kardashevskiy 
673cf66ee8eSAlexey Kardashevskiy     if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, n, dir)) {
674cf66ee8eSAlexey Kardashevskiy         return -1;
675cf66ee8eSAlexey Kardashevskiy     }
676cf66ee8eSAlexey Kardashevskiy     if (n == len) {
677cf66ee8eSAlexey Kardashevskiy         return 0;
678cf66ee8eSAlexey Kardashevskiy     }
679f1ae32a1SGerd Hoffmann     ptr = end_addr & ~0xfffu;
680f1ae32a1SGerd Hoffmann     buf += n;
681cf66ee8eSAlexey Kardashevskiy     if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf,
682cf66ee8eSAlexey Kardashevskiy                       len - n, dir)) {
683cf66ee8eSAlexey Kardashevskiy         return -1;
684cf66ee8eSAlexey Kardashevskiy     }
685cf66ee8eSAlexey Kardashevskiy     return 0;
686f1ae32a1SGerd Hoffmann }
687f1ae32a1SGerd Hoffmann 
688f1ae32a1SGerd Hoffmann static void ohci_process_lists(OHCIState *ohci, int completion);
689f1ae32a1SGerd Hoffmann 
690f1ae32a1SGerd Hoffmann static void ohci_async_complete_packet(USBPort *port, USBPacket *packet)
691f1ae32a1SGerd Hoffmann {
692f1ae32a1SGerd Hoffmann     OHCIState *ohci = container_of(packet, OHCIState, usb_packet);
693f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET
694f1ae32a1SGerd Hoffmann     DPRINTF("Async packet complete\n");
695f1ae32a1SGerd Hoffmann #endif
696f1ae32a1SGerd Hoffmann     ohci->async_complete = 1;
697f1ae32a1SGerd Hoffmann     ohci_process_lists(ohci, 1);
698f1ae32a1SGerd Hoffmann }
699f1ae32a1SGerd Hoffmann 
700f1ae32a1SGerd Hoffmann #define USUB(a, b) ((int16_t)((uint16_t)(a) - (uint16_t)(b)))
701f1ae32a1SGerd Hoffmann 
702f1ae32a1SGerd Hoffmann static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
703f1ae32a1SGerd Hoffmann                                int completion)
704f1ae32a1SGerd Hoffmann {
705f1ae32a1SGerd Hoffmann     int dir;
706f1ae32a1SGerd Hoffmann     size_t len = 0;
707f1ae32a1SGerd Hoffmann #ifdef DEBUG_ISOCH
708f1ae32a1SGerd Hoffmann     const char *str = NULL;
709f1ae32a1SGerd Hoffmann #endif
710f1ae32a1SGerd Hoffmann     int pid;
711f1ae32a1SGerd Hoffmann     int ret;
712f1ae32a1SGerd Hoffmann     int i;
713f1ae32a1SGerd Hoffmann     USBDevice *dev;
714f1ae32a1SGerd Hoffmann     USBEndpoint *ep;
715f1ae32a1SGerd Hoffmann     struct ohci_iso_td iso_td;
716f1ae32a1SGerd Hoffmann     uint32_t addr;
717f1ae32a1SGerd Hoffmann     uint16_t starting_frame;
718f1ae32a1SGerd Hoffmann     int16_t relative_frame_number;
719f1ae32a1SGerd Hoffmann     int frame_count;
720f1ae32a1SGerd Hoffmann     uint32_t start_offset, next_offset, end_offset = 0;
721f1ae32a1SGerd Hoffmann     uint32_t start_addr, end_addr;
722f1ae32a1SGerd Hoffmann 
723f1ae32a1SGerd Hoffmann     addr = ed->head & OHCI_DPTR_MASK;
724f1ae32a1SGerd Hoffmann 
725cf66ee8eSAlexey Kardashevskiy     if (ohci_read_iso_td(ohci, addr, &iso_td)) {
726f1ae32a1SGerd Hoffmann         printf("usb-ohci: ISO_TD read error at %x\n", addr);
727cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
728f1ae32a1SGerd Hoffmann         return 0;
729f1ae32a1SGerd Hoffmann     }
730f1ae32a1SGerd Hoffmann 
731f1ae32a1SGerd Hoffmann     starting_frame = OHCI_BM(iso_td.flags, TD_SF);
732f1ae32a1SGerd Hoffmann     frame_count = OHCI_BM(iso_td.flags, TD_FC);
733f1ae32a1SGerd Hoffmann     relative_frame_number = USUB(ohci->frame_number, starting_frame);
734f1ae32a1SGerd Hoffmann 
735f1ae32a1SGerd Hoffmann #ifdef DEBUG_ISOCH
736f1ae32a1SGerd Hoffmann     printf("--- ISO_TD ED head 0x%.8x tailp 0x%.8x\n"
737f1ae32a1SGerd Hoffmann            "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n"
738f1ae32a1SGerd Hoffmann            "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n"
739f1ae32a1SGerd Hoffmann            "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n"
740f1ae32a1SGerd Hoffmann            "frame_number 0x%.8x starting_frame 0x%.8x\n"
741f1ae32a1SGerd Hoffmann            "frame_count  0x%.8x relative %d\n"
742f1ae32a1SGerd Hoffmann            "di 0x%.8x cc 0x%.8x\n",
743f1ae32a1SGerd Hoffmann            ed->head & OHCI_DPTR_MASK, ed->tail & OHCI_DPTR_MASK,
744f1ae32a1SGerd Hoffmann            iso_td.flags, iso_td.bp, iso_td.next, iso_td.be,
745f1ae32a1SGerd Hoffmann            iso_td.offset[0], iso_td.offset[1], iso_td.offset[2], iso_td.offset[3],
746f1ae32a1SGerd Hoffmann            iso_td.offset[4], iso_td.offset[5], iso_td.offset[6], iso_td.offset[7],
747f1ae32a1SGerd Hoffmann            ohci->frame_number, starting_frame,
748f1ae32a1SGerd Hoffmann            frame_count, relative_frame_number,
749f1ae32a1SGerd Hoffmann            OHCI_BM(iso_td.flags, TD_DI), OHCI_BM(iso_td.flags, TD_CC));
750f1ae32a1SGerd Hoffmann #endif
751f1ae32a1SGerd Hoffmann 
752f1ae32a1SGerd Hoffmann     if (relative_frame_number < 0) {
753f1ae32a1SGerd Hoffmann         DPRINTF("usb-ohci: ISO_TD R=%d < 0\n", relative_frame_number);
754f1ae32a1SGerd Hoffmann         return 1;
755f1ae32a1SGerd Hoffmann     } else if (relative_frame_number > frame_count) {
756f1ae32a1SGerd Hoffmann         /* ISO TD expired - retire the TD to the Done Queue and continue with
757f1ae32a1SGerd Hoffmann            the next ISO TD of the same ED */
758f1ae32a1SGerd Hoffmann         DPRINTF("usb-ohci: ISO_TD R=%d > FC=%d\n", relative_frame_number,
759f1ae32a1SGerd Hoffmann                frame_count);
760f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_DATAOVERRUN);
761f1ae32a1SGerd Hoffmann         ed->head &= ~OHCI_DPTR_MASK;
762f1ae32a1SGerd Hoffmann         ed->head |= (iso_td.next & OHCI_DPTR_MASK);
763f1ae32a1SGerd Hoffmann         iso_td.next = ohci->done;
764f1ae32a1SGerd Hoffmann         ohci->done = addr;
765f1ae32a1SGerd Hoffmann         i = OHCI_BM(iso_td.flags, TD_DI);
766f1ae32a1SGerd Hoffmann         if (i < ohci->done_count)
767f1ae32a1SGerd Hoffmann             ohci->done_count = i;
768cf66ee8eSAlexey Kardashevskiy         if (ohci_put_iso_td(ohci, addr, &iso_td)) {
769cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
770cf66ee8eSAlexey Kardashevskiy             return 1;
771cf66ee8eSAlexey Kardashevskiy         }
772f1ae32a1SGerd Hoffmann         return 0;
773f1ae32a1SGerd Hoffmann     }
774f1ae32a1SGerd Hoffmann 
775f1ae32a1SGerd Hoffmann     dir = OHCI_BM(ed->flags, ED_D);
776f1ae32a1SGerd Hoffmann     switch (dir) {
777f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_IN:
778f1ae32a1SGerd Hoffmann #ifdef DEBUG_ISOCH
779f1ae32a1SGerd Hoffmann         str = "in";
780f1ae32a1SGerd Hoffmann #endif
781f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_IN;
782f1ae32a1SGerd Hoffmann         break;
783f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_OUT:
784f1ae32a1SGerd Hoffmann #ifdef DEBUG_ISOCH
785f1ae32a1SGerd Hoffmann         str = "out";
786f1ae32a1SGerd Hoffmann #endif
787f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_OUT;
788f1ae32a1SGerd Hoffmann         break;
789f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_SETUP:
790f1ae32a1SGerd Hoffmann #ifdef DEBUG_ISOCH
791f1ae32a1SGerd Hoffmann         str = "setup";
792f1ae32a1SGerd Hoffmann #endif
793f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_SETUP;
794f1ae32a1SGerd Hoffmann         break;
795f1ae32a1SGerd Hoffmann     default:
796f1ae32a1SGerd Hoffmann         printf("usb-ohci: Bad direction %d\n", dir);
797f1ae32a1SGerd Hoffmann         return 1;
798f1ae32a1SGerd Hoffmann     }
799f1ae32a1SGerd Hoffmann 
800f1ae32a1SGerd Hoffmann     if (!iso_td.bp || !iso_td.be) {
801f1ae32a1SGerd Hoffmann         printf("usb-ohci: ISO_TD bp 0x%.8x be 0x%.8x\n", iso_td.bp, iso_td.be);
802f1ae32a1SGerd Hoffmann         return 1;
803f1ae32a1SGerd Hoffmann     }
804f1ae32a1SGerd Hoffmann 
805f1ae32a1SGerd Hoffmann     start_offset = iso_td.offset[relative_frame_number];
806f1ae32a1SGerd Hoffmann     next_offset = iso_td.offset[relative_frame_number + 1];
807f1ae32a1SGerd Hoffmann 
808f1ae32a1SGerd Hoffmann     if (!(OHCI_BM(start_offset, TD_PSW_CC) & 0xe) ||
809f1ae32a1SGerd Hoffmann         ((relative_frame_number < frame_count) &&
810f1ae32a1SGerd Hoffmann          !(OHCI_BM(next_offset, TD_PSW_CC) & 0xe))) {
811f1ae32a1SGerd Hoffmann         printf("usb-ohci: ISO_TD cc != not accessed 0x%.8x 0x%.8x\n",
812f1ae32a1SGerd Hoffmann                start_offset, next_offset);
813f1ae32a1SGerd Hoffmann         return 1;
814f1ae32a1SGerd Hoffmann     }
815f1ae32a1SGerd Hoffmann 
816f1ae32a1SGerd Hoffmann     if ((relative_frame_number < frame_count) && (start_offset > next_offset)) {
817f1ae32a1SGerd Hoffmann         printf("usb-ohci: ISO_TD start_offset=0x%.8x > next_offset=0x%.8x\n",
818f1ae32a1SGerd Hoffmann                 start_offset, next_offset);
819f1ae32a1SGerd Hoffmann         return 1;
820f1ae32a1SGerd Hoffmann     }
821f1ae32a1SGerd Hoffmann 
822f1ae32a1SGerd Hoffmann     if ((start_offset & 0x1000) == 0) {
823f1ae32a1SGerd Hoffmann         start_addr = (iso_td.bp & OHCI_PAGE_MASK) |
824f1ae32a1SGerd Hoffmann             (start_offset & OHCI_OFFSET_MASK);
825f1ae32a1SGerd Hoffmann     } else {
826f1ae32a1SGerd Hoffmann         start_addr = (iso_td.be & OHCI_PAGE_MASK) |
827f1ae32a1SGerd Hoffmann             (start_offset & OHCI_OFFSET_MASK);
828f1ae32a1SGerd Hoffmann     }
829f1ae32a1SGerd Hoffmann 
830f1ae32a1SGerd Hoffmann     if (relative_frame_number < frame_count) {
831f1ae32a1SGerd Hoffmann         end_offset = next_offset - 1;
832f1ae32a1SGerd Hoffmann         if ((end_offset & 0x1000) == 0) {
833f1ae32a1SGerd Hoffmann             end_addr = (iso_td.bp & OHCI_PAGE_MASK) |
834f1ae32a1SGerd Hoffmann                 (end_offset & OHCI_OFFSET_MASK);
835f1ae32a1SGerd Hoffmann         } else {
836f1ae32a1SGerd Hoffmann             end_addr = (iso_td.be & OHCI_PAGE_MASK) |
837f1ae32a1SGerd Hoffmann                 (end_offset & OHCI_OFFSET_MASK);
838f1ae32a1SGerd Hoffmann         }
839f1ae32a1SGerd Hoffmann     } else {
840f1ae32a1SGerd Hoffmann         /* Last packet in the ISO TD */
841f1ae32a1SGerd Hoffmann         end_addr = iso_td.be;
842f1ae32a1SGerd Hoffmann     }
843f1ae32a1SGerd Hoffmann 
844f1ae32a1SGerd Hoffmann     if ((start_addr & OHCI_PAGE_MASK) != (end_addr & OHCI_PAGE_MASK)) {
845f1ae32a1SGerd Hoffmann         len = (end_addr & OHCI_OFFSET_MASK) + 0x1001
846f1ae32a1SGerd Hoffmann             - (start_addr & OHCI_OFFSET_MASK);
847f1ae32a1SGerd Hoffmann     } else {
848f1ae32a1SGerd Hoffmann         len = end_addr - start_addr + 1;
849f1ae32a1SGerd Hoffmann     }
850f1ae32a1SGerd Hoffmann 
851f1ae32a1SGerd Hoffmann     if (len && dir != OHCI_TD_DIR_IN) {
852cf66ee8eSAlexey Kardashevskiy         if (ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, len,
853cf66ee8eSAlexey Kardashevskiy                              DMA_DIRECTION_TO_DEVICE)) {
854cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
855cf66ee8eSAlexey Kardashevskiy             return 1;
856cf66ee8eSAlexey Kardashevskiy         }
857f1ae32a1SGerd Hoffmann     }
858f1ae32a1SGerd Hoffmann 
8599a77a0f5SHans de Goede     if (!completion) {
860a6fb2ddbSHans de Goede         bool int_req = relative_frame_number == frame_count &&
861a6fb2ddbSHans de Goede                        OHCI_BM(iso_td.flags, TD_DI) == 0;
862f1ae32a1SGerd Hoffmann         dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
863f1ae32a1SGerd Hoffmann         ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
8648550a02dSGerd Hoffmann         usb_packet_setup(&ohci->usb_packet, pid, ep, 0, addr, false, int_req);
865f1ae32a1SGerd Hoffmann         usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len);
8669a77a0f5SHans de Goede         usb_handle_packet(dev, &ohci->usb_packet);
8679a77a0f5SHans de Goede         if (ohci->usb_packet.status == USB_RET_ASYNC) {
86836dfe324SHans de Goede             usb_device_flush_ep_queue(dev, ep);
869f1ae32a1SGerd Hoffmann             return 1;
870f1ae32a1SGerd Hoffmann         }
871f1ae32a1SGerd Hoffmann     }
8729a77a0f5SHans de Goede     if (ohci->usb_packet.status == USB_RET_SUCCESS) {
8739a77a0f5SHans de Goede         ret = ohci->usb_packet.actual_length;
8749a77a0f5SHans de Goede     } else {
8759a77a0f5SHans de Goede         ret = ohci->usb_packet.status;
8769a77a0f5SHans de Goede     }
877f1ae32a1SGerd Hoffmann 
878f1ae32a1SGerd Hoffmann #ifdef DEBUG_ISOCH
879f1ae32a1SGerd Hoffmann     printf("so 0x%.8x eo 0x%.8x\nsa 0x%.8x ea 0x%.8x\ndir %s len %zu ret %d\n",
880f1ae32a1SGerd Hoffmann            start_offset, end_offset, start_addr, end_addr, str, len, ret);
881f1ae32a1SGerd Hoffmann #endif
882f1ae32a1SGerd Hoffmann 
883f1ae32a1SGerd Hoffmann     /* Writeback */
884f1ae32a1SGerd Hoffmann     if (dir == OHCI_TD_DIR_IN && ret >= 0 && ret <= len) {
885f1ae32a1SGerd Hoffmann         /* IN transfer succeeded */
886cf66ee8eSAlexey Kardashevskiy         if (ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, ret,
887cf66ee8eSAlexey Kardashevskiy                              DMA_DIRECTION_FROM_DEVICE)) {
888cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
889cf66ee8eSAlexey Kardashevskiy             return 1;
890cf66ee8eSAlexey Kardashevskiy         }
891f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
892f1ae32a1SGerd Hoffmann                     OHCI_CC_NOERROR);
893f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, ret);
894f1ae32a1SGerd Hoffmann     } else if (dir == OHCI_TD_DIR_OUT && ret == len) {
895f1ae32a1SGerd Hoffmann         /* OUT transfer succeeded */
896f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
897f1ae32a1SGerd Hoffmann                     OHCI_CC_NOERROR);
898f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 0);
899f1ae32a1SGerd Hoffmann     } else {
900f1ae32a1SGerd Hoffmann         if (ret > (ssize_t) len) {
901f1ae32a1SGerd Hoffmann             printf("usb-ohci: DataOverrun %d > %zu\n", ret, len);
902f1ae32a1SGerd Hoffmann             OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
903f1ae32a1SGerd Hoffmann                         OHCI_CC_DATAOVERRUN);
904f1ae32a1SGerd Hoffmann             OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
905f1ae32a1SGerd Hoffmann                         len);
906f1ae32a1SGerd Hoffmann         } else if (ret >= 0) {
907f1ae32a1SGerd Hoffmann             printf("usb-ohci: DataUnderrun %d\n", ret);
908f1ae32a1SGerd Hoffmann             OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
909f1ae32a1SGerd Hoffmann                         OHCI_CC_DATAUNDERRUN);
910f1ae32a1SGerd Hoffmann         } else {
911f1ae32a1SGerd Hoffmann             switch (ret) {
912f1ae32a1SGerd Hoffmann             case USB_RET_IOERROR:
913f1ae32a1SGerd Hoffmann             case USB_RET_NODEV:
914f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
915f1ae32a1SGerd Hoffmann                             OHCI_CC_DEVICENOTRESPONDING);
916f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
917f1ae32a1SGerd Hoffmann                             0);
918f1ae32a1SGerd Hoffmann                 break;
919f1ae32a1SGerd Hoffmann             case USB_RET_NAK:
920f1ae32a1SGerd Hoffmann             case USB_RET_STALL:
921f1ae32a1SGerd Hoffmann                 printf("usb-ohci: got NAK/STALL %d\n", ret);
922f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
923f1ae32a1SGerd Hoffmann                             OHCI_CC_STALL);
924f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
925f1ae32a1SGerd Hoffmann                             0);
926f1ae32a1SGerd Hoffmann                 break;
927f1ae32a1SGerd Hoffmann             default:
928f1ae32a1SGerd Hoffmann                 printf("usb-ohci: Bad device response %d\n", ret);
929f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
930f1ae32a1SGerd Hoffmann                             OHCI_CC_UNDEXPETEDPID);
931f1ae32a1SGerd Hoffmann                 break;
932f1ae32a1SGerd Hoffmann             }
933f1ae32a1SGerd Hoffmann         }
934f1ae32a1SGerd Hoffmann     }
935f1ae32a1SGerd Hoffmann 
936f1ae32a1SGerd Hoffmann     if (relative_frame_number == frame_count) {
937f1ae32a1SGerd Hoffmann         /* Last data packet of ISO TD - retire the TD to the Done Queue */
938f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_NOERROR);
939f1ae32a1SGerd Hoffmann         ed->head &= ~OHCI_DPTR_MASK;
940f1ae32a1SGerd Hoffmann         ed->head |= (iso_td.next & OHCI_DPTR_MASK);
941f1ae32a1SGerd Hoffmann         iso_td.next = ohci->done;
942f1ae32a1SGerd Hoffmann         ohci->done = addr;
943f1ae32a1SGerd Hoffmann         i = OHCI_BM(iso_td.flags, TD_DI);
944f1ae32a1SGerd Hoffmann         if (i < ohci->done_count)
945f1ae32a1SGerd Hoffmann             ohci->done_count = i;
946f1ae32a1SGerd Hoffmann     }
947cf66ee8eSAlexey Kardashevskiy     if (ohci_put_iso_td(ohci, addr, &iso_td)) {
948cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
949cf66ee8eSAlexey Kardashevskiy     }
950f1ae32a1SGerd Hoffmann     return 1;
951f1ae32a1SGerd Hoffmann }
952f1ae32a1SGerd Hoffmann 
953f1ae32a1SGerd Hoffmann /* Service a transport descriptor.
954f1ae32a1SGerd Hoffmann    Returns nonzero to terminate processing of this endpoint.  */
955f1ae32a1SGerd Hoffmann 
956f1ae32a1SGerd Hoffmann static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
957f1ae32a1SGerd Hoffmann {
958f1ae32a1SGerd Hoffmann     int dir;
959f1ae32a1SGerd Hoffmann     size_t len = 0, pktlen = 0;
960f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET
961f1ae32a1SGerd Hoffmann     const char *str = NULL;
962f1ae32a1SGerd Hoffmann #endif
963f1ae32a1SGerd Hoffmann     int pid;
964f1ae32a1SGerd Hoffmann     int ret;
965f1ae32a1SGerd Hoffmann     int i;
966f1ae32a1SGerd Hoffmann     USBDevice *dev;
967f1ae32a1SGerd Hoffmann     USBEndpoint *ep;
968f1ae32a1SGerd Hoffmann     struct ohci_td td;
969f1ae32a1SGerd Hoffmann     uint32_t addr;
970f1ae32a1SGerd Hoffmann     int flag_r;
971f1ae32a1SGerd Hoffmann     int completion;
972f1ae32a1SGerd Hoffmann 
973f1ae32a1SGerd Hoffmann     addr = ed->head & OHCI_DPTR_MASK;
974f1ae32a1SGerd Hoffmann     /* See if this TD has already been submitted to the device.  */
975f1ae32a1SGerd Hoffmann     completion = (addr == ohci->async_td);
976f1ae32a1SGerd Hoffmann     if (completion && !ohci->async_complete) {
977f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET
978f1ae32a1SGerd Hoffmann         DPRINTF("Skipping async TD\n");
979f1ae32a1SGerd Hoffmann #endif
980f1ae32a1SGerd Hoffmann         return 1;
981f1ae32a1SGerd Hoffmann     }
982cf66ee8eSAlexey Kardashevskiy     if (ohci_read_td(ohci, addr, &td)) {
983f1ae32a1SGerd Hoffmann         fprintf(stderr, "usb-ohci: TD read error at %x\n", addr);
984cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
985f1ae32a1SGerd Hoffmann         return 0;
986f1ae32a1SGerd Hoffmann     }
987f1ae32a1SGerd Hoffmann 
988f1ae32a1SGerd Hoffmann     dir = OHCI_BM(ed->flags, ED_D);
989f1ae32a1SGerd Hoffmann     switch (dir) {
990f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_OUT:
991f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_IN:
992f1ae32a1SGerd Hoffmann         /* Same value.  */
993f1ae32a1SGerd Hoffmann         break;
994f1ae32a1SGerd Hoffmann     default:
995f1ae32a1SGerd Hoffmann         dir = OHCI_BM(td.flags, TD_DP);
996f1ae32a1SGerd Hoffmann         break;
997f1ae32a1SGerd Hoffmann     }
998f1ae32a1SGerd Hoffmann 
999f1ae32a1SGerd Hoffmann     switch (dir) {
1000f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_IN:
1001f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET
1002f1ae32a1SGerd Hoffmann         str = "in";
1003f1ae32a1SGerd Hoffmann #endif
1004f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_IN;
1005f1ae32a1SGerd Hoffmann         break;
1006f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_OUT:
1007f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET
1008f1ae32a1SGerd Hoffmann         str = "out";
1009f1ae32a1SGerd Hoffmann #endif
1010f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_OUT;
1011f1ae32a1SGerd Hoffmann         break;
1012f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_SETUP:
1013f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET
1014f1ae32a1SGerd Hoffmann         str = "setup";
1015f1ae32a1SGerd Hoffmann #endif
1016f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_SETUP;
1017f1ae32a1SGerd Hoffmann         break;
1018f1ae32a1SGerd Hoffmann     default:
1019f1ae32a1SGerd Hoffmann         fprintf(stderr, "usb-ohci: Bad direction\n");
1020f1ae32a1SGerd Hoffmann         return 1;
1021f1ae32a1SGerd Hoffmann     }
1022f1ae32a1SGerd Hoffmann     if (td.cbp && td.be) {
1023f1ae32a1SGerd Hoffmann         if ((td.cbp & 0xfffff000) != (td.be & 0xfffff000)) {
1024f1ae32a1SGerd Hoffmann             len = (td.be & 0xfff) + 0x1001 - (td.cbp & 0xfff);
1025f1ae32a1SGerd Hoffmann         } else {
1026f1ae32a1SGerd Hoffmann             len = (td.be - td.cbp) + 1;
1027f1ae32a1SGerd Hoffmann         }
1028f1ae32a1SGerd Hoffmann 
1029f1ae32a1SGerd Hoffmann         pktlen = len;
1030f1ae32a1SGerd Hoffmann         if (len && dir != OHCI_TD_DIR_IN) {
1031f1ae32a1SGerd Hoffmann             /* The endpoint may not allow us to transfer it all now */
1032f1ae32a1SGerd Hoffmann             pktlen = (ed->flags & OHCI_ED_MPS_MASK) >> OHCI_ED_MPS_SHIFT;
1033f1ae32a1SGerd Hoffmann             if (pktlen > len) {
1034f1ae32a1SGerd Hoffmann                 pktlen = len;
1035f1ae32a1SGerd Hoffmann             }
1036f1ae32a1SGerd Hoffmann             if (!completion) {
1037cf66ee8eSAlexey Kardashevskiy                 if (ohci_copy_td(ohci, &td, ohci->usb_buf, pktlen,
1038cf66ee8eSAlexey Kardashevskiy                                  DMA_DIRECTION_TO_DEVICE)) {
1039cf66ee8eSAlexey Kardashevskiy                     ohci_die(ohci);
1040cf66ee8eSAlexey Kardashevskiy                 }
1041f1ae32a1SGerd Hoffmann             }
1042f1ae32a1SGerd Hoffmann         }
1043f1ae32a1SGerd Hoffmann     }
1044f1ae32a1SGerd Hoffmann 
1045f1ae32a1SGerd Hoffmann     flag_r = (td.flags & OHCI_TD_R) != 0;
1046f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET
1047f1ae32a1SGerd Hoffmann     DPRINTF(" TD @ 0x%.8x %" PRId64 " of %" PRId64
1048f1ae32a1SGerd Hoffmann             " bytes %s r=%d cbp=0x%.8x be=0x%.8x\n",
1049f1ae32a1SGerd Hoffmann             addr, (int64_t)pktlen, (int64_t)len, str, flag_r, td.cbp, td.be);
1050f1ae32a1SGerd Hoffmann 
1051f1ae32a1SGerd Hoffmann     if (pktlen > 0 && dir != OHCI_TD_DIR_IN) {
1052f1ae32a1SGerd Hoffmann         DPRINTF("  data:");
1053f1ae32a1SGerd Hoffmann         for (i = 0; i < pktlen; i++) {
1054f1ae32a1SGerd Hoffmann             printf(" %.2x", ohci->usb_buf[i]);
1055f1ae32a1SGerd Hoffmann         }
1056f1ae32a1SGerd Hoffmann         DPRINTF("\n");
1057f1ae32a1SGerd Hoffmann     }
1058f1ae32a1SGerd Hoffmann #endif
1059f1ae32a1SGerd Hoffmann     if (completion) {
1060f1ae32a1SGerd Hoffmann         ohci->async_td = 0;
1061f1ae32a1SGerd Hoffmann         ohci->async_complete = 0;
1062f1ae32a1SGerd Hoffmann     } else {
1063f1ae32a1SGerd Hoffmann         if (ohci->async_td) {
1064f1ae32a1SGerd Hoffmann             /* ??? The hardware should allow one active packet per
1065f1ae32a1SGerd Hoffmann                endpoint.  We only allow one active packet per controller.
1066f1ae32a1SGerd Hoffmann                This should be sufficient as long as devices respond in a
1067f1ae32a1SGerd Hoffmann                timely manner.
1068f1ae32a1SGerd Hoffmann             */
1069f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET
1070f1ae32a1SGerd Hoffmann             DPRINTF("Too many pending packets\n");
1071f1ae32a1SGerd Hoffmann #endif
1072f1ae32a1SGerd Hoffmann             return 1;
1073f1ae32a1SGerd Hoffmann         }
1074f1ae32a1SGerd Hoffmann         dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
1075f1ae32a1SGerd Hoffmann         ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
10768550a02dSGerd Hoffmann         usb_packet_setup(&ohci->usb_packet, pid, ep, 0, addr, !flag_r,
1077a6fb2ddbSHans de Goede                          OHCI_BM(td.flags, TD_DI) == 0);
1078f1ae32a1SGerd Hoffmann         usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen);
10799a77a0f5SHans de Goede         usb_handle_packet(dev, &ohci->usb_packet);
1080f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET
10819a77a0f5SHans de Goede         DPRINTF("status=%d\n", ohci->usb_packet.status);
1082f1ae32a1SGerd Hoffmann #endif
10839a77a0f5SHans de Goede         if (ohci->usb_packet.status == USB_RET_ASYNC) {
108436dfe324SHans de Goede             usb_device_flush_ep_queue(dev, ep);
1085f1ae32a1SGerd Hoffmann             ohci->async_td = addr;
1086f1ae32a1SGerd Hoffmann             return 1;
1087f1ae32a1SGerd Hoffmann         }
1088f1ae32a1SGerd Hoffmann     }
10899a77a0f5SHans de Goede     if (ohci->usb_packet.status == USB_RET_SUCCESS) {
10909a77a0f5SHans de Goede         ret = ohci->usb_packet.actual_length;
10919a77a0f5SHans de Goede     } else {
10929a77a0f5SHans de Goede         ret = ohci->usb_packet.status;
10939a77a0f5SHans de Goede     }
10949a77a0f5SHans de Goede 
1095f1ae32a1SGerd Hoffmann     if (ret >= 0) {
1096f1ae32a1SGerd Hoffmann         if (dir == OHCI_TD_DIR_IN) {
1097cf66ee8eSAlexey Kardashevskiy             if (ohci_copy_td(ohci, &td, ohci->usb_buf, ret,
1098cf66ee8eSAlexey Kardashevskiy                              DMA_DIRECTION_FROM_DEVICE)) {
1099cf66ee8eSAlexey Kardashevskiy                 ohci_die(ohci);
1100cf66ee8eSAlexey Kardashevskiy             }
1101f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET
1102f1ae32a1SGerd Hoffmann             DPRINTF("  data:");
1103f1ae32a1SGerd Hoffmann             for (i = 0; i < ret; i++)
1104f1ae32a1SGerd Hoffmann                 printf(" %.2x", ohci->usb_buf[i]);
1105f1ae32a1SGerd Hoffmann             DPRINTF("\n");
1106f1ae32a1SGerd Hoffmann #endif
1107f1ae32a1SGerd Hoffmann         } else {
1108f1ae32a1SGerd Hoffmann             ret = pktlen;
1109f1ae32a1SGerd Hoffmann         }
1110f1ae32a1SGerd Hoffmann     }
1111f1ae32a1SGerd Hoffmann 
1112f1ae32a1SGerd Hoffmann     /* Writeback */
1113f1ae32a1SGerd Hoffmann     if (ret == pktlen || (dir == OHCI_TD_DIR_IN && ret >= 0 && flag_r)) {
1114f1ae32a1SGerd Hoffmann         /* Transmission succeeded.  */
1115f1ae32a1SGerd Hoffmann         if (ret == len) {
1116f1ae32a1SGerd Hoffmann             td.cbp = 0;
1117f1ae32a1SGerd Hoffmann         } else {
1118f1ae32a1SGerd Hoffmann             if ((td.cbp & 0xfff) + ret > 0xfff) {
1119f1ae32a1SGerd Hoffmann                 td.cbp = (td.be & ~0xfff) + ((td.cbp + ret) & 0xfff);
1120f1ae32a1SGerd Hoffmann             } else {
1121f1ae32a1SGerd Hoffmann                 td.cbp += ret;
1122f1ae32a1SGerd Hoffmann             }
1123f1ae32a1SGerd Hoffmann         }
1124f1ae32a1SGerd Hoffmann         td.flags |= OHCI_TD_T1;
1125f1ae32a1SGerd Hoffmann         td.flags ^= OHCI_TD_T0;
1126f1ae32a1SGerd Hoffmann         OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_NOERROR);
1127f1ae32a1SGerd Hoffmann         OHCI_SET_BM(td.flags, TD_EC, 0);
1128f1ae32a1SGerd Hoffmann 
1129f1ae32a1SGerd Hoffmann         if ((dir != OHCI_TD_DIR_IN) && (ret != len)) {
1130f1ae32a1SGerd Hoffmann             /* Partial packet transfer: TD not ready to retire yet */
1131f1ae32a1SGerd Hoffmann             goto exit_no_retire;
1132f1ae32a1SGerd Hoffmann         }
1133f1ae32a1SGerd Hoffmann 
1134f1ae32a1SGerd Hoffmann         /* Setting ED_C is part of the TD retirement process */
1135f1ae32a1SGerd Hoffmann         ed->head &= ~OHCI_ED_C;
1136f1ae32a1SGerd Hoffmann         if (td.flags & OHCI_TD_T0)
1137f1ae32a1SGerd Hoffmann             ed->head |= OHCI_ED_C;
1138f1ae32a1SGerd Hoffmann     } else {
1139f1ae32a1SGerd Hoffmann         if (ret >= 0) {
1140f1ae32a1SGerd Hoffmann             DPRINTF("usb-ohci: Underrun\n");
1141f1ae32a1SGerd Hoffmann             OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAUNDERRUN);
1142f1ae32a1SGerd Hoffmann         } else {
1143f1ae32a1SGerd Hoffmann             switch (ret) {
1144f1ae32a1SGerd Hoffmann             case USB_RET_IOERROR:
1145f1ae32a1SGerd Hoffmann             case USB_RET_NODEV:
11464b351a0fSJán Veselý                 DPRINTF("usb-ohci: got DEV ERROR\n");
1147f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DEVICENOTRESPONDING);
11484b351a0fSJán Veselý                 break;
1149f1ae32a1SGerd Hoffmann             case USB_RET_NAK:
1150f1ae32a1SGerd Hoffmann                 DPRINTF("usb-ohci: got NAK\n");
1151f1ae32a1SGerd Hoffmann                 return 1;
1152f1ae32a1SGerd Hoffmann             case USB_RET_STALL:
1153f1ae32a1SGerd Hoffmann                 DPRINTF("usb-ohci: got STALL\n");
1154f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_STALL);
1155f1ae32a1SGerd Hoffmann                 break;
1156f1ae32a1SGerd Hoffmann             case USB_RET_BABBLE:
1157f1ae32a1SGerd Hoffmann                 DPRINTF("usb-ohci: got BABBLE\n");
1158f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAOVERRUN);
1159f1ae32a1SGerd Hoffmann                 break;
1160f1ae32a1SGerd Hoffmann             default:
1161f1ae32a1SGerd Hoffmann                 fprintf(stderr, "usb-ohci: Bad device response %d\n", ret);
1162f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_UNDEXPETEDPID);
1163f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_EC, 3);
1164f1ae32a1SGerd Hoffmann                 break;
1165f1ae32a1SGerd Hoffmann             }
1166f1ae32a1SGerd Hoffmann         }
1167f1ae32a1SGerd Hoffmann         ed->head |= OHCI_ED_H;
1168f1ae32a1SGerd Hoffmann     }
1169f1ae32a1SGerd Hoffmann 
1170f1ae32a1SGerd Hoffmann     /* Retire this TD */
1171f1ae32a1SGerd Hoffmann     ed->head &= ~OHCI_DPTR_MASK;
1172f1ae32a1SGerd Hoffmann     ed->head |= td.next & OHCI_DPTR_MASK;
1173f1ae32a1SGerd Hoffmann     td.next = ohci->done;
1174f1ae32a1SGerd Hoffmann     ohci->done = addr;
1175f1ae32a1SGerd Hoffmann     i = OHCI_BM(td.flags, TD_DI);
1176f1ae32a1SGerd Hoffmann     if (i < ohci->done_count)
1177f1ae32a1SGerd Hoffmann         ohci->done_count = i;
1178f1ae32a1SGerd Hoffmann exit_no_retire:
1179cf66ee8eSAlexey Kardashevskiy     if (ohci_put_td(ohci, addr, &td)) {
1180cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
1181cf66ee8eSAlexey Kardashevskiy         return 1;
1182cf66ee8eSAlexey Kardashevskiy     }
1183f1ae32a1SGerd Hoffmann     return OHCI_BM(td.flags, TD_CC) != OHCI_CC_NOERROR;
1184f1ae32a1SGerd Hoffmann }
1185f1ae32a1SGerd Hoffmann 
1186f1ae32a1SGerd Hoffmann /* Service an endpoint list.  Returns nonzero if active TD were found.  */
1187f1ae32a1SGerd Hoffmann static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion)
1188f1ae32a1SGerd Hoffmann {
1189f1ae32a1SGerd Hoffmann     struct ohci_ed ed;
1190f1ae32a1SGerd Hoffmann     uint32_t next_ed;
1191f1ae32a1SGerd Hoffmann     uint32_t cur;
1192f1ae32a1SGerd Hoffmann     int active;
1193f1ae32a1SGerd Hoffmann 
1194f1ae32a1SGerd Hoffmann     active = 0;
1195f1ae32a1SGerd Hoffmann 
1196f1ae32a1SGerd Hoffmann     if (head == 0)
1197f1ae32a1SGerd Hoffmann         return 0;
1198f1ae32a1SGerd Hoffmann 
1199f1ae32a1SGerd Hoffmann     for (cur = head; cur; cur = next_ed) {
1200cf66ee8eSAlexey Kardashevskiy         if (ohci_read_ed(ohci, cur, &ed)) {
1201f1ae32a1SGerd Hoffmann             fprintf(stderr, "usb-ohci: ED read error at %x\n", cur);
1202cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
1203f1ae32a1SGerd Hoffmann             return 0;
1204f1ae32a1SGerd Hoffmann         }
1205f1ae32a1SGerd Hoffmann 
1206f1ae32a1SGerd Hoffmann         next_ed = ed.next & OHCI_DPTR_MASK;
1207f1ae32a1SGerd Hoffmann 
1208f1ae32a1SGerd Hoffmann         if ((ed.head & OHCI_ED_H) || (ed.flags & OHCI_ED_K)) {
1209f1ae32a1SGerd Hoffmann             uint32_t addr;
1210f1ae32a1SGerd Hoffmann             /* Cancel pending packets for ED that have been paused.  */
1211f1ae32a1SGerd Hoffmann             addr = ed.head & OHCI_DPTR_MASK;
1212f1ae32a1SGerd Hoffmann             if (ohci->async_td && addr == ohci->async_td) {
1213f1ae32a1SGerd Hoffmann                 usb_cancel_packet(&ohci->usb_packet);
1214f1ae32a1SGerd Hoffmann                 ohci->async_td = 0;
1215f79738b0SHans de Goede                 usb_device_ep_stopped(ohci->usb_packet.ep->dev,
1216f79738b0SHans de Goede                                       ohci->usb_packet.ep);
1217f1ae32a1SGerd Hoffmann             }
1218f1ae32a1SGerd Hoffmann             continue;
1219f1ae32a1SGerd Hoffmann         }
1220f1ae32a1SGerd Hoffmann 
1221f1ae32a1SGerd Hoffmann         while ((ed.head & OHCI_DPTR_MASK) != ed.tail) {
1222f1ae32a1SGerd Hoffmann #ifdef DEBUG_PACKET
1223f1ae32a1SGerd Hoffmann             DPRINTF("ED @ 0x%.8x fa=%u en=%u d=%u s=%u k=%u f=%u mps=%u "
1224f1ae32a1SGerd Hoffmann                     "h=%u c=%u\n  head=0x%.8x tailp=0x%.8x next=0x%.8x\n", cur,
1225f1ae32a1SGerd Hoffmann                     OHCI_BM(ed.flags, ED_FA), OHCI_BM(ed.flags, ED_EN),
1226f1ae32a1SGerd Hoffmann                     OHCI_BM(ed.flags, ED_D), (ed.flags & OHCI_ED_S)!= 0,
1227f1ae32a1SGerd Hoffmann                     (ed.flags & OHCI_ED_K) != 0, (ed.flags & OHCI_ED_F) != 0,
1228f1ae32a1SGerd Hoffmann                     OHCI_BM(ed.flags, ED_MPS), (ed.head & OHCI_ED_H) != 0,
1229f1ae32a1SGerd Hoffmann                     (ed.head & OHCI_ED_C) != 0, ed.head & OHCI_DPTR_MASK,
1230f1ae32a1SGerd Hoffmann                     ed.tail & OHCI_DPTR_MASK, ed.next & OHCI_DPTR_MASK);
1231f1ae32a1SGerd Hoffmann #endif
1232f1ae32a1SGerd Hoffmann             active = 1;
1233f1ae32a1SGerd Hoffmann 
1234f1ae32a1SGerd Hoffmann             if ((ed.flags & OHCI_ED_F) == 0) {
1235f1ae32a1SGerd Hoffmann                 if (ohci_service_td(ohci, &ed))
1236f1ae32a1SGerd Hoffmann                     break;
1237f1ae32a1SGerd Hoffmann             } else {
1238f1ae32a1SGerd Hoffmann                 /* Handle isochronous endpoints */
1239f1ae32a1SGerd Hoffmann                 if (ohci_service_iso_td(ohci, &ed, completion))
1240f1ae32a1SGerd Hoffmann                     break;
1241f1ae32a1SGerd Hoffmann             }
1242f1ae32a1SGerd Hoffmann         }
1243f1ae32a1SGerd Hoffmann 
1244cf66ee8eSAlexey Kardashevskiy         if (ohci_put_ed(ohci, cur, &ed)) {
1245cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
1246cf66ee8eSAlexey Kardashevskiy             return 0;
1247cf66ee8eSAlexey Kardashevskiy         }
1248f1ae32a1SGerd Hoffmann     }
1249f1ae32a1SGerd Hoffmann 
1250f1ae32a1SGerd Hoffmann     return active;
1251f1ae32a1SGerd Hoffmann }
1252f1ae32a1SGerd Hoffmann 
1253f1ae32a1SGerd Hoffmann /* Generate a SOF event, and set a timer for EOF */
1254f1ae32a1SGerd Hoffmann static void ohci_sof(OHCIState *ohci)
1255f1ae32a1SGerd Hoffmann {
1256bc72ad67SAlex Bligh     ohci->sof_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
1257bc72ad67SAlex Bligh     timer_mod(ohci->eof_timer, ohci->sof_time + usb_frame_time);
1258f1ae32a1SGerd Hoffmann     ohci_set_interrupt(ohci, OHCI_INTR_SF);
1259f1ae32a1SGerd Hoffmann }
1260f1ae32a1SGerd Hoffmann 
1261f1ae32a1SGerd Hoffmann /* Process Control and Bulk lists.  */
1262f1ae32a1SGerd Hoffmann static void ohci_process_lists(OHCIState *ohci, int completion)
1263f1ae32a1SGerd Hoffmann {
1264f1ae32a1SGerd Hoffmann     if ((ohci->ctl & OHCI_CTL_CLE) && (ohci->status & OHCI_STATUS_CLF)) {
1265f1ae32a1SGerd Hoffmann         if (ohci->ctrl_cur && ohci->ctrl_cur != ohci->ctrl_head) {
1266f1ae32a1SGerd Hoffmann             DPRINTF("usb-ohci: head %x, cur %x\n",
1267f1ae32a1SGerd Hoffmann                     ohci->ctrl_head, ohci->ctrl_cur);
1268f1ae32a1SGerd Hoffmann         }
1269f1ae32a1SGerd Hoffmann         if (!ohci_service_ed_list(ohci, ohci->ctrl_head, completion)) {
1270f1ae32a1SGerd Hoffmann             ohci->ctrl_cur = 0;
1271f1ae32a1SGerd Hoffmann             ohci->status &= ~OHCI_STATUS_CLF;
1272f1ae32a1SGerd Hoffmann         }
1273f1ae32a1SGerd Hoffmann     }
1274f1ae32a1SGerd Hoffmann 
1275f1ae32a1SGerd Hoffmann     if ((ohci->ctl & OHCI_CTL_BLE) && (ohci->status & OHCI_STATUS_BLF)) {
1276f1ae32a1SGerd Hoffmann         if (!ohci_service_ed_list(ohci, ohci->bulk_head, completion)) {
1277f1ae32a1SGerd Hoffmann             ohci->bulk_cur = 0;
1278f1ae32a1SGerd Hoffmann             ohci->status &= ~OHCI_STATUS_BLF;
1279f1ae32a1SGerd Hoffmann         }
1280f1ae32a1SGerd Hoffmann     }
1281f1ae32a1SGerd Hoffmann }
1282f1ae32a1SGerd Hoffmann 
1283f1ae32a1SGerd Hoffmann /* Do frame processing on frame boundary */
1284f1ae32a1SGerd Hoffmann static void ohci_frame_boundary(void *opaque)
1285f1ae32a1SGerd Hoffmann {
1286f1ae32a1SGerd Hoffmann     OHCIState *ohci = opaque;
1287f1ae32a1SGerd Hoffmann     struct ohci_hcca hcca;
1288f1ae32a1SGerd Hoffmann 
1289cf66ee8eSAlexey Kardashevskiy     if (ohci_read_hcca(ohci, ohci->hcca, &hcca)) {
1290cf66ee8eSAlexey Kardashevskiy         fprintf(stderr, "usb-ohci: HCCA read error at %x\n", ohci->hcca);
1291cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
1292cf66ee8eSAlexey Kardashevskiy         return;
1293cf66ee8eSAlexey Kardashevskiy     }
1294f1ae32a1SGerd Hoffmann 
1295f1ae32a1SGerd Hoffmann     /* Process all the lists at the end of the frame */
1296f1ae32a1SGerd Hoffmann     if (ohci->ctl & OHCI_CTL_PLE) {
1297f1ae32a1SGerd Hoffmann         int n;
1298f1ae32a1SGerd Hoffmann 
1299f1ae32a1SGerd Hoffmann         n = ohci->frame_number & 0x1f;
1300f1ae32a1SGerd Hoffmann         ohci_service_ed_list(ohci, le32_to_cpu(hcca.intr[n]), 0);
1301f1ae32a1SGerd Hoffmann     }
1302f1ae32a1SGerd Hoffmann 
1303f1ae32a1SGerd Hoffmann     /* Cancel all pending packets if either of the lists has been disabled.  */
1304f79738b0SHans de Goede     if (ohci->old_ctl & (~ohci->ctl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) {
1305f79738b0SHans de Goede         if (ohci->async_td) {
1306f1ae32a1SGerd Hoffmann             usb_cancel_packet(&ohci->usb_packet);
1307f1ae32a1SGerd Hoffmann             ohci->async_td = 0;
1308f1ae32a1SGerd Hoffmann         }
1309f79738b0SHans de Goede         ohci_stop_endpoints(ohci);
1310f79738b0SHans de Goede     }
1311f1ae32a1SGerd Hoffmann     ohci->old_ctl = ohci->ctl;
1312f1ae32a1SGerd Hoffmann     ohci_process_lists(ohci, 0);
1313f1ae32a1SGerd Hoffmann 
1314cf66ee8eSAlexey Kardashevskiy     /* Stop if UnrecoverableError happened or ohci_sof will crash */
1315cf66ee8eSAlexey Kardashevskiy     if (ohci->intr_status & OHCI_INTR_UE) {
1316cf66ee8eSAlexey Kardashevskiy         return;
1317cf66ee8eSAlexey Kardashevskiy     }
1318cf66ee8eSAlexey Kardashevskiy 
1319f1ae32a1SGerd Hoffmann     /* Frame boundary, so do EOF stuf here */
1320f1ae32a1SGerd Hoffmann     ohci->frt = ohci->fit;
1321f1ae32a1SGerd Hoffmann 
1322f1ae32a1SGerd Hoffmann     /* Increment frame number and take care of endianness. */
1323f1ae32a1SGerd Hoffmann     ohci->frame_number = (ohci->frame_number + 1) & 0xffff;
1324f1ae32a1SGerd Hoffmann     hcca.frame = cpu_to_le16(ohci->frame_number);
1325f1ae32a1SGerd Hoffmann 
1326f1ae32a1SGerd Hoffmann     if (ohci->done_count == 0 && !(ohci->intr_status & OHCI_INTR_WD)) {
1327f1ae32a1SGerd Hoffmann         if (!ohci->done)
1328f1ae32a1SGerd Hoffmann             abort();
1329f1ae32a1SGerd Hoffmann         if (ohci->intr & ohci->intr_status)
1330f1ae32a1SGerd Hoffmann             ohci->done |= 1;
1331f1ae32a1SGerd Hoffmann         hcca.done = cpu_to_le32(ohci->done);
1332f1ae32a1SGerd Hoffmann         ohci->done = 0;
1333f1ae32a1SGerd Hoffmann         ohci->done_count = 7;
1334f1ae32a1SGerd Hoffmann         ohci_set_interrupt(ohci, OHCI_INTR_WD);
1335f1ae32a1SGerd Hoffmann     }
1336f1ae32a1SGerd Hoffmann 
1337f1ae32a1SGerd Hoffmann     if (ohci->done_count != 7 && ohci->done_count != 0)
1338f1ae32a1SGerd Hoffmann         ohci->done_count--;
1339f1ae32a1SGerd Hoffmann 
1340f1ae32a1SGerd Hoffmann     /* Do SOF stuff here */
1341f1ae32a1SGerd Hoffmann     ohci_sof(ohci);
1342f1ae32a1SGerd Hoffmann 
1343f1ae32a1SGerd Hoffmann     /* Writeback HCCA */
1344cf66ee8eSAlexey Kardashevskiy     if (ohci_put_hcca(ohci, ohci->hcca, &hcca)) {
1345cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
1346cf66ee8eSAlexey Kardashevskiy     }
1347f1ae32a1SGerd Hoffmann }
1348f1ae32a1SGerd Hoffmann 
1349f1ae32a1SGerd Hoffmann /* Start sending SOF tokens across the USB bus, lists are processed in
1350f1ae32a1SGerd Hoffmann  * next frame
1351f1ae32a1SGerd Hoffmann  */
1352f1ae32a1SGerd Hoffmann static int ohci_bus_start(OHCIState *ohci)
1353f1ae32a1SGerd Hoffmann {
1354bc72ad67SAlex Bligh     ohci->eof_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
1355f1ae32a1SGerd Hoffmann                     ohci_frame_boundary,
1356f1ae32a1SGerd Hoffmann                     ohci);
1357f1ae32a1SGerd Hoffmann 
1358f1ae32a1SGerd Hoffmann     if (ohci->eof_timer == NULL) {
1359bc72ad67SAlex Bligh         fprintf(stderr, "usb-ohci: %s: timer_new_ns failed\n", ohci->name);
1360cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
1361f1ae32a1SGerd Hoffmann         return 0;
1362f1ae32a1SGerd Hoffmann     }
1363f1ae32a1SGerd Hoffmann 
1364f1ae32a1SGerd Hoffmann     DPRINTF("usb-ohci: %s: USB Operational\n", ohci->name);
1365f1ae32a1SGerd Hoffmann 
1366f1ae32a1SGerd Hoffmann     ohci_sof(ohci);
1367f1ae32a1SGerd Hoffmann 
1368f1ae32a1SGerd Hoffmann     return 1;
1369f1ae32a1SGerd Hoffmann }
1370f1ae32a1SGerd Hoffmann 
1371f1ae32a1SGerd Hoffmann /* Stop sending SOF tokens on the bus */
1372f1ae32a1SGerd Hoffmann static void ohci_bus_stop(OHCIState *ohci)
1373f1ae32a1SGerd Hoffmann {
1374f1ae32a1SGerd Hoffmann     if (ohci->eof_timer)
1375bc72ad67SAlex Bligh         timer_del(ohci->eof_timer);
1376f1ae32a1SGerd Hoffmann     ohci->eof_timer = NULL;
1377f1ae32a1SGerd Hoffmann }
1378f1ae32a1SGerd Hoffmann 
1379f1ae32a1SGerd Hoffmann /* Sets a flag in a port status register but only set it if the port is
1380f1ae32a1SGerd Hoffmann  * connected, if not set ConnectStatusChange flag. If flag is enabled
1381f1ae32a1SGerd Hoffmann  * return 1.
1382f1ae32a1SGerd Hoffmann  */
1383f1ae32a1SGerd Hoffmann static int ohci_port_set_if_connected(OHCIState *ohci, int i, uint32_t val)
1384f1ae32a1SGerd Hoffmann {
1385f1ae32a1SGerd Hoffmann     int ret = 1;
1386f1ae32a1SGerd Hoffmann 
1387f1ae32a1SGerd Hoffmann     /* writing a 0 has no effect */
1388f1ae32a1SGerd Hoffmann     if (val == 0)
1389f1ae32a1SGerd Hoffmann         return 0;
1390f1ae32a1SGerd Hoffmann 
1391f1ae32a1SGerd Hoffmann     /* If CurrentConnectStatus is cleared we set
1392f1ae32a1SGerd Hoffmann      * ConnectStatusChange
1393f1ae32a1SGerd Hoffmann      */
1394f1ae32a1SGerd Hoffmann     if (!(ohci->rhport[i].ctrl & OHCI_PORT_CCS)) {
1395f1ae32a1SGerd Hoffmann         ohci->rhport[i].ctrl |= OHCI_PORT_CSC;
1396f1ae32a1SGerd Hoffmann         if (ohci->rhstatus & OHCI_RHS_DRWE) {
1397f1ae32a1SGerd Hoffmann             /* TODO: CSC is a wakeup event */
1398f1ae32a1SGerd Hoffmann         }
1399f1ae32a1SGerd Hoffmann         return 0;
1400f1ae32a1SGerd Hoffmann     }
1401f1ae32a1SGerd Hoffmann 
1402f1ae32a1SGerd Hoffmann     if (ohci->rhport[i].ctrl & val)
1403f1ae32a1SGerd Hoffmann         ret = 0;
1404f1ae32a1SGerd Hoffmann 
1405f1ae32a1SGerd Hoffmann     /* set the bit */
1406f1ae32a1SGerd Hoffmann     ohci->rhport[i].ctrl |= val;
1407f1ae32a1SGerd Hoffmann 
1408f1ae32a1SGerd Hoffmann     return ret;
1409f1ae32a1SGerd Hoffmann }
1410f1ae32a1SGerd Hoffmann 
1411f1ae32a1SGerd Hoffmann /* Set the frame interval - frame interval toggle is manipulated by the hcd only */
1412f1ae32a1SGerd Hoffmann static void ohci_set_frame_interval(OHCIState *ohci, uint16_t val)
1413f1ae32a1SGerd Hoffmann {
1414f1ae32a1SGerd Hoffmann     val &= OHCI_FMI_FI;
1415f1ae32a1SGerd Hoffmann 
1416f1ae32a1SGerd Hoffmann     if (val != ohci->fi) {
1417f1ae32a1SGerd Hoffmann         DPRINTF("usb-ohci: %s: FrameInterval = 0x%x (%u)\n",
1418f1ae32a1SGerd Hoffmann             ohci->name, ohci->fi, ohci->fi);
1419f1ae32a1SGerd Hoffmann     }
1420f1ae32a1SGerd Hoffmann 
1421f1ae32a1SGerd Hoffmann     ohci->fi = val;
1422f1ae32a1SGerd Hoffmann }
1423f1ae32a1SGerd Hoffmann 
1424f1ae32a1SGerd Hoffmann static void ohci_port_power(OHCIState *ohci, int i, int p)
1425f1ae32a1SGerd Hoffmann {
1426f1ae32a1SGerd Hoffmann     if (p) {
1427f1ae32a1SGerd Hoffmann         ohci->rhport[i].ctrl |= OHCI_PORT_PPS;
1428f1ae32a1SGerd Hoffmann     } else {
1429f1ae32a1SGerd Hoffmann         ohci->rhport[i].ctrl &= ~(OHCI_PORT_PPS|
1430f1ae32a1SGerd Hoffmann                     OHCI_PORT_CCS|
1431f1ae32a1SGerd Hoffmann                     OHCI_PORT_PSS|
1432f1ae32a1SGerd Hoffmann                     OHCI_PORT_PRS);
1433f1ae32a1SGerd Hoffmann     }
1434f1ae32a1SGerd Hoffmann }
1435f1ae32a1SGerd Hoffmann 
1436f1ae32a1SGerd Hoffmann /* Set HcControlRegister */
1437f1ae32a1SGerd Hoffmann static void ohci_set_ctl(OHCIState *ohci, uint32_t val)
1438f1ae32a1SGerd Hoffmann {
1439f1ae32a1SGerd Hoffmann     uint32_t old_state;
1440f1ae32a1SGerd Hoffmann     uint32_t new_state;
1441f1ae32a1SGerd Hoffmann 
1442f1ae32a1SGerd Hoffmann     old_state = ohci->ctl & OHCI_CTL_HCFS;
1443f1ae32a1SGerd Hoffmann     ohci->ctl = val;
1444f1ae32a1SGerd Hoffmann     new_state = ohci->ctl & OHCI_CTL_HCFS;
1445f1ae32a1SGerd Hoffmann 
1446f1ae32a1SGerd Hoffmann     /* no state change */
1447f1ae32a1SGerd Hoffmann     if (old_state == new_state)
1448f1ae32a1SGerd Hoffmann         return;
1449f1ae32a1SGerd Hoffmann 
1450f1ae32a1SGerd Hoffmann     switch (new_state) {
1451f1ae32a1SGerd Hoffmann     case OHCI_USB_OPERATIONAL:
1452f1ae32a1SGerd Hoffmann         ohci_bus_start(ohci);
1453f1ae32a1SGerd Hoffmann         break;
1454f1ae32a1SGerd Hoffmann     case OHCI_USB_SUSPEND:
1455f1ae32a1SGerd Hoffmann         ohci_bus_stop(ohci);
1456f1ae32a1SGerd Hoffmann         DPRINTF("usb-ohci: %s: USB Suspended\n", ohci->name);
1457f1ae32a1SGerd Hoffmann         break;
1458f1ae32a1SGerd Hoffmann     case OHCI_USB_RESUME:
1459f1ae32a1SGerd Hoffmann         DPRINTF("usb-ohci: %s: USB Resume\n", ohci->name);
1460f1ae32a1SGerd Hoffmann         break;
1461f1ae32a1SGerd Hoffmann     case OHCI_USB_RESET:
1462f1ae32a1SGerd Hoffmann         ohci_reset(ohci);
1463f1ae32a1SGerd Hoffmann         DPRINTF("usb-ohci: %s: USB Reset\n", ohci->name);
1464f1ae32a1SGerd Hoffmann         break;
1465f1ae32a1SGerd Hoffmann     }
1466f1ae32a1SGerd Hoffmann }
1467f1ae32a1SGerd Hoffmann 
1468f1ae32a1SGerd Hoffmann static uint32_t ohci_get_frame_remaining(OHCIState *ohci)
1469f1ae32a1SGerd Hoffmann {
1470f1ae32a1SGerd Hoffmann     uint16_t fr;
1471f1ae32a1SGerd Hoffmann     int64_t tks;
1472f1ae32a1SGerd Hoffmann 
1473f1ae32a1SGerd Hoffmann     if ((ohci->ctl & OHCI_CTL_HCFS) != OHCI_USB_OPERATIONAL)
1474f1ae32a1SGerd Hoffmann         return (ohci->frt << 31);
1475f1ae32a1SGerd Hoffmann 
1476f1ae32a1SGerd Hoffmann     /* Being in USB operational state guarnatees sof_time was
1477f1ae32a1SGerd Hoffmann      * set already.
1478f1ae32a1SGerd Hoffmann      */
1479bc72ad67SAlex Bligh     tks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - ohci->sof_time;
1480f1ae32a1SGerd Hoffmann 
1481f1ae32a1SGerd Hoffmann     /* avoid muldiv if possible */
1482f1ae32a1SGerd Hoffmann     if (tks >= usb_frame_time)
1483f1ae32a1SGerd Hoffmann         return (ohci->frt << 31);
1484f1ae32a1SGerd Hoffmann 
1485f1ae32a1SGerd Hoffmann     tks = muldiv64(1, tks, usb_bit_time);
1486f1ae32a1SGerd Hoffmann     fr = (uint16_t)(ohci->fi - tks);
1487f1ae32a1SGerd Hoffmann 
1488f1ae32a1SGerd Hoffmann     return (ohci->frt << 31) | fr;
1489f1ae32a1SGerd Hoffmann }
1490f1ae32a1SGerd Hoffmann 
1491f1ae32a1SGerd Hoffmann 
1492f1ae32a1SGerd Hoffmann /* Set root hub status */
1493f1ae32a1SGerd Hoffmann static void ohci_set_hub_status(OHCIState *ohci, uint32_t val)
1494f1ae32a1SGerd Hoffmann {
1495f1ae32a1SGerd Hoffmann     uint32_t old_state;
1496f1ae32a1SGerd Hoffmann 
1497f1ae32a1SGerd Hoffmann     old_state = ohci->rhstatus;
1498f1ae32a1SGerd Hoffmann 
1499f1ae32a1SGerd Hoffmann     /* write 1 to clear OCIC */
1500f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_OCIC)
1501f1ae32a1SGerd Hoffmann         ohci->rhstatus &= ~OHCI_RHS_OCIC;
1502f1ae32a1SGerd Hoffmann 
1503f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_LPS) {
1504f1ae32a1SGerd Hoffmann         int i;
1505f1ae32a1SGerd Hoffmann 
1506f1ae32a1SGerd Hoffmann         for (i = 0; i < ohci->num_ports; i++)
1507f1ae32a1SGerd Hoffmann             ohci_port_power(ohci, i, 0);
1508f1ae32a1SGerd Hoffmann         DPRINTF("usb-ohci: powered down all ports\n");
1509f1ae32a1SGerd Hoffmann     }
1510f1ae32a1SGerd Hoffmann 
1511f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_LPSC) {
1512f1ae32a1SGerd Hoffmann         int i;
1513f1ae32a1SGerd Hoffmann 
1514f1ae32a1SGerd Hoffmann         for (i = 0; i < ohci->num_ports; i++)
1515f1ae32a1SGerd Hoffmann             ohci_port_power(ohci, i, 1);
1516f1ae32a1SGerd Hoffmann         DPRINTF("usb-ohci: powered up all ports\n");
1517f1ae32a1SGerd Hoffmann     }
1518f1ae32a1SGerd Hoffmann 
1519f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_DRWE)
1520f1ae32a1SGerd Hoffmann         ohci->rhstatus |= OHCI_RHS_DRWE;
1521f1ae32a1SGerd Hoffmann 
1522f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_CRWE)
1523f1ae32a1SGerd Hoffmann         ohci->rhstatus &= ~OHCI_RHS_DRWE;
1524f1ae32a1SGerd Hoffmann 
1525f1ae32a1SGerd Hoffmann     if (old_state != ohci->rhstatus)
1526f1ae32a1SGerd Hoffmann         ohci_set_interrupt(ohci, OHCI_INTR_RHSC);
1527f1ae32a1SGerd Hoffmann }
1528f1ae32a1SGerd Hoffmann 
1529f1ae32a1SGerd Hoffmann /* Set root hub port status */
1530f1ae32a1SGerd Hoffmann static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val)
1531f1ae32a1SGerd Hoffmann {
1532f1ae32a1SGerd Hoffmann     uint32_t old_state;
1533f1ae32a1SGerd Hoffmann     OHCIPort *port;
1534f1ae32a1SGerd Hoffmann 
1535f1ae32a1SGerd Hoffmann     port = &ohci->rhport[portnum];
1536f1ae32a1SGerd Hoffmann     old_state = port->ctrl;
1537f1ae32a1SGerd Hoffmann 
1538f1ae32a1SGerd Hoffmann     /* Write to clear CSC, PESC, PSSC, OCIC, PRSC */
1539f1ae32a1SGerd Hoffmann     if (val & OHCI_PORT_WTC)
1540f1ae32a1SGerd Hoffmann         port->ctrl &= ~(val & OHCI_PORT_WTC);
1541f1ae32a1SGerd Hoffmann 
1542f1ae32a1SGerd Hoffmann     if (val & OHCI_PORT_CCS)
1543f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_PES;
1544f1ae32a1SGerd Hoffmann 
1545f1ae32a1SGerd Hoffmann     ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PES);
1546f1ae32a1SGerd Hoffmann 
1547f1ae32a1SGerd Hoffmann     if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PSS)) {
1548f1ae32a1SGerd Hoffmann         DPRINTF("usb-ohci: port %d: SUSPEND\n", portnum);
1549f1ae32a1SGerd Hoffmann     }
1550f1ae32a1SGerd Hoffmann 
1551f1ae32a1SGerd Hoffmann     if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PRS)) {
1552f1ae32a1SGerd Hoffmann         DPRINTF("usb-ohci: port %d: RESET\n", portnum);
1553f1ae32a1SGerd Hoffmann         usb_device_reset(port->port.dev);
1554f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_PRS;
1555f1ae32a1SGerd Hoffmann         /* ??? Should this also set OHCI_PORT_PESC.  */
1556f1ae32a1SGerd Hoffmann         port->ctrl |= OHCI_PORT_PES | OHCI_PORT_PRSC;
1557f1ae32a1SGerd Hoffmann     }
1558f1ae32a1SGerd Hoffmann 
1559f1ae32a1SGerd Hoffmann     /* Invert order here to ensure in ambiguous case, device is
1560f1ae32a1SGerd Hoffmann      * powered up...
1561f1ae32a1SGerd Hoffmann      */
1562f1ae32a1SGerd Hoffmann     if (val & OHCI_PORT_LSDA)
1563f1ae32a1SGerd Hoffmann         ohci_port_power(ohci, portnum, 0);
1564f1ae32a1SGerd Hoffmann     if (val & OHCI_PORT_PPS)
1565f1ae32a1SGerd Hoffmann         ohci_port_power(ohci, portnum, 1);
1566f1ae32a1SGerd Hoffmann 
1567f1ae32a1SGerd Hoffmann     if (old_state != port->ctrl)
1568f1ae32a1SGerd Hoffmann         ohci_set_interrupt(ohci, OHCI_INTR_RHSC);
1569f1ae32a1SGerd Hoffmann }
1570f1ae32a1SGerd Hoffmann 
1571f1ae32a1SGerd Hoffmann static uint64_t ohci_mem_read(void *opaque,
1572a8170e5eSAvi Kivity                               hwaddr addr,
1573f1ae32a1SGerd Hoffmann                               unsigned size)
1574f1ae32a1SGerd Hoffmann {
1575f1ae32a1SGerd Hoffmann     OHCIState *ohci = opaque;
1576f1ae32a1SGerd Hoffmann     uint32_t retval;
1577f1ae32a1SGerd Hoffmann 
1578f1ae32a1SGerd Hoffmann     /* Only aligned reads are allowed on OHCI */
1579f1ae32a1SGerd Hoffmann     if (addr & 3) {
1580f1ae32a1SGerd Hoffmann         fprintf(stderr, "usb-ohci: Mis-aligned read\n");
1581f1ae32a1SGerd Hoffmann         return 0xffffffff;
1582f1ae32a1SGerd Hoffmann     } else if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) {
1583f1ae32a1SGerd Hoffmann         /* HcRhPortStatus */
1584f1ae32a1SGerd Hoffmann         retval = ohci->rhport[(addr - 0x54) >> 2].ctrl | OHCI_PORT_PPS;
1585f1ae32a1SGerd Hoffmann     } else {
1586f1ae32a1SGerd Hoffmann         switch (addr >> 2) {
1587f1ae32a1SGerd Hoffmann         case 0: /* HcRevision */
1588f1ae32a1SGerd Hoffmann             retval = 0x10;
1589f1ae32a1SGerd Hoffmann             break;
1590f1ae32a1SGerd Hoffmann 
1591f1ae32a1SGerd Hoffmann         case 1: /* HcControl */
1592f1ae32a1SGerd Hoffmann             retval = ohci->ctl;
1593f1ae32a1SGerd Hoffmann             break;
1594f1ae32a1SGerd Hoffmann 
1595f1ae32a1SGerd Hoffmann         case 2: /* HcCommandStatus */
1596f1ae32a1SGerd Hoffmann             retval = ohci->status;
1597f1ae32a1SGerd Hoffmann             break;
1598f1ae32a1SGerd Hoffmann 
1599f1ae32a1SGerd Hoffmann         case 3: /* HcInterruptStatus */
1600f1ae32a1SGerd Hoffmann             retval = ohci->intr_status;
1601f1ae32a1SGerd Hoffmann             break;
1602f1ae32a1SGerd Hoffmann 
1603f1ae32a1SGerd Hoffmann         case 4: /* HcInterruptEnable */
1604f1ae32a1SGerd Hoffmann         case 5: /* HcInterruptDisable */
1605f1ae32a1SGerd Hoffmann             retval = ohci->intr;
1606f1ae32a1SGerd Hoffmann             break;
1607f1ae32a1SGerd Hoffmann 
1608f1ae32a1SGerd Hoffmann         case 6: /* HcHCCA */
1609f1ae32a1SGerd Hoffmann             retval = ohci->hcca;
1610f1ae32a1SGerd Hoffmann             break;
1611f1ae32a1SGerd Hoffmann 
1612f1ae32a1SGerd Hoffmann         case 7: /* HcPeriodCurrentED */
1613f1ae32a1SGerd Hoffmann             retval = ohci->per_cur;
1614f1ae32a1SGerd Hoffmann             break;
1615f1ae32a1SGerd Hoffmann 
1616f1ae32a1SGerd Hoffmann         case 8: /* HcControlHeadED */
1617f1ae32a1SGerd Hoffmann             retval = ohci->ctrl_head;
1618f1ae32a1SGerd Hoffmann             break;
1619f1ae32a1SGerd Hoffmann 
1620f1ae32a1SGerd Hoffmann         case 9: /* HcControlCurrentED */
1621f1ae32a1SGerd Hoffmann             retval = ohci->ctrl_cur;
1622f1ae32a1SGerd Hoffmann             break;
1623f1ae32a1SGerd Hoffmann 
1624f1ae32a1SGerd Hoffmann         case 10: /* HcBulkHeadED */
1625f1ae32a1SGerd Hoffmann             retval = ohci->bulk_head;
1626f1ae32a1SGerd Hoffmann             break;
1627f1ae32a1SGerd Hoffmann 
1628f1ae32a1SGerd Hoffmann         case 11: /* HcBulkCurrentED */
1629f1ae32a1SGerd Hoffmann             retval = ohci->bulk_cur;
1630f1ae32a1SGerd Hoffmann             break;
1631f1ae32a1SGerd Hoffmann 
1632f1ae32a1SGerd Hoffmann         case 12: /* HcDoneHead */
1633f1ae32a1SGerd Hoffmann             retval = ohci->done;
1634f1ae32a1SGerd Hoffmann             break;
1635f1ae32a1SGerd Hoffmann 
1636f1ae32a1SGerd Hoffmann         case 13: /* HcFmInterretval */
1637f1ae32a1SGerd Hoffmann             retval = (ohci->fit << 31) | (ohci->fsmps << 16) | (ohci->fi);
1638f1ae32a1SGerd Hoffmann             break;
1639f1ae32a1SGerd Hoffmann 
1640f1ae32a1SGerd Hoffmann         case 14: /* HcFmRemaining */
1641f1ae32a1SGerd Hoffmann             retval = ohci_get_frame_remaining(ohci);
1642f1ae32a1SGerd Hoffmann             break;
1643f1ae32a1SGerd Hoffmann 
1644f1ae32a1SGerd Hoffmann         case 15: /* HcFmNumber */
1645f1ae32a1SGerd Hoffmann             retval = ohci->frame_number;
1646f1ae32a1SGerd Hoffmann             break;
1647f1ae32a1SGerd Hoffmann 
1648f1ae32a1SGerd Hoffmann         case 16: /* HcPeriodicStart */
1649f1ae32a1SGerd Hoffmann             retval = ohci->pstart;
1650f1ae32a1SGerd Hoffmann             break;
1651f1ae32a1SGerd Hoffmann 
1652f1ae32a1SGerd Hoffmann         case 17: /* HcLSThreshold */
1653f1ae32a1SGerd Hoffmann             retval = ohci->lst;
1654f1ae32a1SGerd Hoffmann             break;
1655f1ae32a1SGerd Hoffmann 
1656f1ae32a1SGerd Hoffmann         case 18: /* HcRhDescriptorA */
1657f1ae32a1SGerd Hoffmann             retval = ohci->rhdesc_a;
1658f1ae32a1SGerd Hoffmann             break;
1659f1ae32a1SGerd Hoffmann 
1660f1ae32a1SGerd Hoffmann         case 19: /* HcRhDescriptorB */
1661f1ae32a1SGerd Hoffmann             retval = ohci->rhdesc_b;
1662f1ae32a1SGerd Hoffmann             break;
1663f1ae32a1SGerd Hoffmann 
1664f1ae32a1SGerd Hoffmann         case 20: /* HcRhStatus */
1665f1ae32a1SGerd Hoffmann             retval = ohci->rhstatus;
1666f1ae32a1SGerd Hoffmann             break;
1667f1ae32a1SGerd Hoffmann 
1668f1ae32a1SGerd Hoffmann         /* PXA27x specific registers */
1669f1ae32a1SGerd Hoffmann         case 24: /* HcStatus */
1670f1ae32a1SGerd Hoffmann             retval = ohci->hstatus & ohci->hmask;
1671f1ae32a1SGerd Hoffmann             break;
1672f1ae32a1SGerd Hoffmann 
1673f1ae32a1SGerd Hoffmann         case 25: /* HcHReset */
1674f1ae32a1SGerd Hoffmann             retval = ohci->hreset;
1675f1ae32a1SGerd Hoffmann             break;
1676f1ae32a1SGerd Hoffmann 
1677f1ae32a1SGerd Hoffmann         case 26: /* HcHInterruptEnable */
1678f1ae32a1SGerd Hoffmann             retval = ohci->hmask;
1679f1ae32a1SGerd Hoffmann             break;
1680f1ae32a1SGerd Hoffmann 
1681f1ae32a1SGerd Hoffmann         case 27: /* HcHInterruptTest */
1682f1ae32a1SGerd Hoffmann             retval = ohci->htest;
1683f1ae32a1SGerd Hoffmann             break;
1684f1ae32a1SGerd Hoffmann 
1685f1ae32a1SGerd Hoffmann         default:
1686f1ae32a1SGerd Hoffmann             fprintf(stderr, "ohci_read: Bad offset %x\n", (int)addr);
1687f1ae32a1SGerd Hoffmann             retval = 0xffffffff;
1688f1ae32a1SGerd Hoffmann         }
1689f1ae32a1SGerd Hoffmann     }
1690f1ae32a1SGerd Hoffmann 
1691f1ae32a1SGerd Hoffmann     return retval;
1692f1ae32a1SGerd Hoffmann }
1693f1ae32a1SGerd Hoffmann 
1694f1ae32a1SGerd Hoffmann static void ohci_mem_write(void *opaque,
1695a8170e5eSAvi Kivity                            hwaddr addr,
1696f1ae32a1SGerd Hoffmann                            uint64_t val,
1697f1ae32a1SGerd Hoffmann                            unsigned size)
1698f1ae32a1SGerd Hoffmann {
1699f1ae32a1SGerd Hoffmann     OHCIState *ohci = opaque;
1700f1ae32a1SGerd Hoffmann 
1701f1ae32a1SGerd Hoffmann     /* Only aligned reads are allowed on OHCI */
1702f1ae32a1SGerd Hoffmann     if (addr & 3) {
1703f1ae32a1SGerd Hoffmann         fprintf(stderr, "usb-ohci: Mis-aligned write\n");
1704f1ae32a1SGerd Hoffmann         return;
1705f1ae32a1SGerd Hoffmann     }
1706f1ae32a1SGerd Hoffmann 
1707f1ae32a1SGerd Hoffmann     if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) {
1708f1ae32a1SGerd Hoffmann         /* HcRhPortStatus */
1709f1ae32a1SGerd Hoffmann         ohci_port_set_status(ohci, (addr - 0x54) >> 2, val);
1710f1ae32a1SGerd Hoffmann         return;
1711f1ae32a1SGerd Hoffmann     }
1712f1ae32a1SGerd Hoffmann 
1713f1ae32a1SGerd Hoffmann     switch (addr >> 2) {
1714f1ae32a1SGerd Hoffmann     case 1: /* HcControl */
1715f1ae32a1SGerd Hoffmann         ohci_set_ctl(ohci, val);
1716f1ae32a1SGerd Hoffmann         break;
1717f1ae32a1SGerd Hoffmann 
1718f1ae32a1SGerd Hoffmann     case 2: /* HcCommandStatus */
1719f1ae32a1SGerd Hoffmann         /* SOC is read-only */
1720f1ae32a1SGerd Hoffmann         val = (val & ~OHCI_STATUS_SOC);
1721f1ae32a1SGerd Hoffmann 
1722f1ae32a1SGerd Hoffmann         /* Bits written as '0' remain unchanged in the register */
1723f1ae32a1SGerd Hoffmann         ohci->status |= val;
1724f1ae32a1SGerd Hoffmann 
1725f1ae32a1SGerd Hoffmann         if (ohci->status & OHCI_STATUS_HCR)
1726f1ae32a1SGerd Hoffmann             ohci_reset(ohci);
1727f1ae32a1SGerd Hoffmann         break;
1728f1ae32a1SGerd Hoffmann 
1729f1ae32a1SGerd Hoffmann     case 3: /* HcInterruptStatus */
1730f1ae32a1SGerd Hoffmann         ohci->intr_status &= ~val;
1731f1ae32a1SGerd Hoffmann         ohci_intr_update(ohci);
1732f1ae32a1SGerd Hoffmann         break;
1733f1ae32a1SGerd Hoffmann 
1734f1ae32a1SGerd Hoffmann     case 4: /* HcInterruptEnable */
1735f1ae32a1SGerd Hoffmann         ohci->intr |= val;
1736f1ae32a1SGerd Hoffmann         ohci_intr_update(ohci);
1737f1ae32a1SGerd Hoffmann         break;
1738f1ae32a1SGerd Hoffmann 
1739f1ae32a1SGerd Hoffmann     case 5: /* HcInterruptDisable */
1740f1ae32a1SGerd Hoffmann         ohci->intr &= ~val;
1741f1ae32a1SGerd Hoffmann         ohci_intr_update(ohci);
1742f1ae32a1SGerd Hoffmann         break;
1743f1ae32a1SGerd Hoffmann 
1744f1ae32a1SGerd Hoffmann     case 6: /* HcHCCA */
1745f1ae32a1SGerd Hoffmann         ohci->hcca = val & OHCI_HCCA_MASK;
1746f1ae32a1SGerd Hoffmann         break;
1747f1ae32a1SGerd Hoffmann 
1748f1ae32a1SGerd Hoffmann     case 7: /* HcPeriodCurrentED */
1749f1ae32a1SGerd Hoffmann         /* Ignore writes to this read-only register, Linux does them */
1750f1ae32a1SGerd Hoffmann         break;
1751f1ae32a1SGerd Hoffmann 
1752f1ae32a1SGerd Hoffmann     case 8: /* HcControlHeadED */
1753f1ae32a1SGerd Hoffmann         ohci->ctrl_head = val & OHCI_EDPTR_MASK;
1754f1ae32a1SGerd Hoffmann         break;
1755f1ae32a1SGerd Hoffmann 
1756f1ae32a1SGerd Hoffmann     case 9: /* HcControlCurrentED */
1757f1ae32a1SGerd Hoffmann         ohci->ctrl_cur = val & OHCI_EDPTR_MASK;
1758f1ae32a1SGerd Hoffmann         break;
1759f1ae32a1SGerd Hoffmann 
1760f1ae32a1SGerd Hoffmann     case 10: /* HcBulkHeadED */
1761f1ae32a1SGerd Hoffmann         ohci->bulk_head = val & OHCI_EDPTR_MASK;
1762f1ae32a1SGerd Hoffmann         break;
1763f1ae32a1SGerd Hoffmann 
1764f1ae32a1SGerd Hoffmann     case 11: /* HcBulkCurrentED */
1765f1ae32a1SGerd Hoffmann         ohci->bulk_cur = val & OHCI_EDPTR_MASK;
1766f1ae32a1SGerd Hoffmann         break;
1767f1ae32a1SGerd Hoffmann 
1768f1ae32a1SGerd Hoffmann     case 13: /* HcFmInterval */
1769f1ae32a1SGerd Hoffmann         ohci->fsmps = (val & OHCI_FMI_FSMPS) >> 16;
1770f1ae32a1SGerd Hoffmann         ohci->fit = (val & OHCI_FMI_FIT) >> 31;
1771f1ae32a1SGerd Hoffmann         ohci_set_frame_interval(ohci, val);
1772f1ae32a1SGerd Hoffmann         break;
1773f1ae32a1SGerd Hoffmann 
1774f1ae32a1SGerd Hoffmann     case 15: /* HcFmNumber */
1775f1ae32a1SGerd Hoffmann         break;
1776f1ae32a1SGerd Hoffmann 
1777f1ae32a1SGerd Hoffmann     case 16: /* HcPeriodicStart */
1778f1ae32a1SGerd Hoffmann         ohci->pstart = val & 0xffff;
1779f1ae32a1SGerd Hoffmann         break;
1780f1ae32a1SGerd Hoffmann 
1781f1ae32a1SGerd Hoffmann     case 17: /* HcLSThreshold */
1782f1ae32a1SGerd Hoffmann         ohci->lst = val & 0xffff;
1783f1ae32a1SGerd Hoffmann         break;
1784f1ae32a1SGerd Hoffmann 
1785f1ae32a1SGerd Hoffmann     case 18: /* HcRhDescriptorA */
1786f1ae32a1SGerd Hoffmann         ohci->rhdesc_a &= ~OHCI_RHA_RW_MASK;
1787f1ae32a1SGerd Hoffmann         ohci->rhdesc_a |= val & OHCI_RHA_RW_MASK;
1788f1ae32a1SGerd Hoffmann         break;
1789f1ae32a1SGerd Hoffmann 
1790f1ae32a1SGerd Hoffmann     case 19: /* HcRhDescriptorB */
1791f1ae32a1SGerd Hoffmann         break;
1792f1ae32a1SGerd Hoffmann 
1793f1ae32a1SGerd Hoffmann     case 20: /* HcRhStatus */
1794f1ae32a1SGerd Hoffmann         ohci_set_hub_status(ohci, val);
1795f1ae32a1SGerd Hoffmann         break;
1796f1ae32a1SGerd Hoffmann 
1797f1ae32a1SGerd Hoffmann     /* PXA27x specific registers */
1798f1ae32a1SGerd Hoffmann     case 24: /* HcStatus */
1799f1ae32a1SGerd Hoffmann         ohci->hstatus &= ~(val & ohci->hmask);
18007fa96d73SGerd Hoffmann         break;
1801f1ae32a1SGerd Hoffmann 
1802f1ae32a1SGerd Hoffmann     case 25: /* HcHReset */
1803f1ae32a1SGerd Hoffmann         ohci->hreset = val & ~OHCI_HRESET_FSBIR;
1804f1ae32a1SGerd Hoffmann         if (val & OHCI_HRESET_FSBIR)
1805f1ae32a1SGerd Hoffmann             ohci_reset(ohci);
1806f1ae32a1SGerd Hoffmann         break;
1807f1ae32a1SGerd Hoffmann 
1808f1ae32a1SGerd Hoffmann     case 26: /* HcHInterruptEnable */
1809f1ae32a1SGerd Hoffmann         ohci->hmask = val;
1810f1ae32a1SGerd Hoffmann         break;
1811f1ae32a1SGerd Hoffmann 
1812f1ae32a1SGerd Hoffmann     case 27: /* HcHInterruptTest */
1813f1ae32a1SGerd Hoffmann         ohci->htest = val;
1814f1ae32a1SGerd Hoffmann         break;
1815f1ae32a1SGerd Hoffmann 
1816f1ae32a1SGerd Hoffmann     default:
1817f1ae32a1SGerd Hoffmann         fprintf(stderr, "ohci_write: Bad offset %x\n", (int)addr);
1818f1ae32a1SGerd Hoffmann         break;
1819f1ae32a1SGerd Hoffmann     }
1820f1ae32a1SGerd Hoffmann }
1821f1ae32a1SGerd Hoffmann 
1822f1ae32a1SGerd Hoffmann static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev)
1823f1ae32a1SGerd Hoffmann {
1824f1ae32a1SGerd Hoffmann     if (ohci->async_td &&
1825f1ae32a1SGerd Hoffmann         usb_packet_is_inflight(&ohci->usb_packet) &&
1826f1ae32a1SGerd Hoffmann         ohci->usb_packet.ep->dev == dev) {
1827f1ae32a1SGerd Hoffmann         usb_cancel_packet(&ohci->usb_packet);
1828f1ae32a1SGerd Hoffmann         ohci->async_td = 0;
1829f1ae32a1SGerd Hoffmann     }
1830f1ae32a1SGerd Hoffmann }
1831f1ae32a1SGerd Hoffmann 
1832f1ae32a1SGerd Hoffmann static const MemoryRegionOps ohci_mem_ops = {
1833f1ae32a1SGerd Hoffmann     .read = ohci_mem_read,
1834f1ae32a1SGerd Hoffmann     .write = ohci_mem_write,
1835f1ae32a1SGerd Hoffmann     .endianness = DEVICE_LITTLE_ENDIAN,
1836f1ae32a1SGerd Hoffmann };
1837f1ae32a1SGerd Hoffmann 
1838f1ae32a1SGerd Hoffmann static USBPortOps ohci_port_ops = {
1839f1ae32a1SGerd Hoffmann     .attach = ohci_attach,
1840f1ae32a1SGerd Hoffmann     .detach = ohci_detach,
1841f1ae32a1SGerd Hoffmann     .child_detach = ohci_child_detach,
1842f1ae32a1SGerd Hoffmann     .wakeup = ohci_wakeup,
1843f1ae32a1SGerd Hoffmann     .complete = ohci_async_complete_packet,
1844f1ae32a1SGerd Hoffmann };
1845f1ae32a1SGerd Hoffmann 
1846f1ae32a1SGerd Hoffmann static USBBusOps ohci_bus_ops = {
1847f1ae32a1SGerd Hoffmann };
1848f1ae32a1SGerd Hoffmann 
1849f1ae32a1SGerd Hoffmann static int usb_ohci_init(OHCIState *ohci, DeviceState *dev,
18509ac6a217SDavid Gibson                          int num_ports, dma_addr_t localmem_base,
18519ac6a217SDavid Gibson                          char *masterbus, uint32_t firstport,
1852df32fd1cSPaolo Bonzini                          AddressSpace *as)
1853f1ae32a1SGerd Hoffmann {
1854f1ae32a1SGerd Hoffmann     int i;
1855f1ae32a1SGerd Hoffmann 
1856df32fd1cSPaolo Bonzini     ohci->as = as;
18579ac6a217SDavid Gibson 
1858f1ae32a1SGerd Hoffmann     if (usb_frame_time == 0) {
1859f1ae32a1SGerd Hoffmann #ifdef OHCI_TIME_WARP
1860f1ae32a1SGerd Hoffmann         usb_frame_time = get_ticks_per_sec();
1861f1ae32a1SGerd Hoffmann         usb_bit_time = muldiv64(1, get_ticks_per_sec(), USB_HZ/1000);
1862f1ae32a1SGerd Hoffmann #else
1863f1ae32a1SGerd Hoffmann         usb_frame_time = muldiv64(1, get_ticks_per_sec(), 1000);
1864f1ae32a1SGerd Hoffmann         if (get_ticks_per_sec() >= USB_HZ) {
1865f1ae32a1SGerd Hoffmann             usb_bit_time = muldiv64(1, get_ticks_per_sec(), USB_HZ);
1866f1ae32a1SGerd Hoffmann         } else {
1867f1ae32a1SGerd Hoffmann             usb_bit_time = 1;
1868f1ae32a1SGerd Hoffmann         }
1869f1ae32a1SGerd Hoffmann #endif
1870f1ae32a1SGerd Hoffmann         DPRINTF("usb-ohci: usb_bit_time=%" PRId64 " usb_frame_time=%" PRId64 "\n",
1871f1ae32a1SGerd Hoffmann                 usb_frame_time, usb_bit_time);
1872f1ae32a1SGerd Hoffmann     }
1873f1ae32a1SGerd Hoffmann 
1874f1ae32a1SGerd Hoffmann     ohci->num_ports = num_ports;
1875f1ae32a1SGerd Hoffmann     if (masterbus) {
1876f1ae32a1SGerd Hoffmann         USBPort *ports[OHCI_MAX_PORTS];
1877f1ae32a1SGerd Hoffmann         for(i = 0; i < num_ports; i++) {
1878f1ae32a1SGerd Hoffmann             ports[i] = &ohci->rhport[i].port;
1879f1ae32a1SGerd Hoffmann         }
1880f1ae32a1SGerd Hoffmann         if (usb_register_companion(masterbus, ports, num_ports,
1881f1ae32a1SGerd Hoffmann                 firstport, ohci, &ohci_port_ops,
1882f1ae32a1SGerd Hoffmann                 USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL) != 0) {
1883f1ae32a1SGerd Hoffmann             return -1;
1884f1ae32a1SGerd Hoffmann         }
1885f1ae32a1SGerd Hoffmann     } else {
1886c889b3a5SAndreas Färber         usb_bus_new(&ohci->bus, sizeof(ohci->bus), &ohci_bus_ops, dev);
1887f1ae32a1SGerd Hoffmann         for (i = 0; i < num_ports; i++) {
1888f1ae32a1SGerd Hoffmann             usb_register_port(&ohci->bus, &ohci->rhport[i].port,
1889f1ae32a1SGerd Hoffmann                               ohci, i, &ohci_port_ops,
1890f1ae32a1SGerd Hoffmann                               USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
1891f1ae32a1SGerd Hoffmann         }
1892f1ae32a1SGerd Hoffmann     }
1893f1ae32a1SGerd Hoffmann 
189422fc860bSPaolo Bonzini     memory_region_init_io(&ohci->mem, OBJECT(dev), &ohci_mem_ops,
189522fc860bSPaolo Bonzini                           ohci, "ohci", 256);
1896f1ae32a1SGerd Hoffmann     ohci->localmem_base = localmem_base;
1897f1ae32a1SGerd Hoffmann 
1898f1ae32a1SGerd Hoffmann     ohci->name = object_get_typename(OBJECT(dev));
1899f1ae32a1SGerd Hoffmann     usb_packet_init(&ohci->usb_packet);
1900f1ae32a1SGerd Hoffmann 
1901f1ae32a1SGerd Hoffmann     ohci->async_td = 0;
1902f1ae32a1SGerd Hoffmann     qemu_register_reset(ohci_reset, ohci);
1903f1ae32a1SGerd Hoffmann 
1904f1ae32a1SGerd Hoffmann     return 0;
1905f1ae32a1SGerd Hoffmann }
1906f1ae32a1SGerd Hoffmann 
19071aa0c0c7SHu Tao #define TYPE_PCI_OHCI "pci-ohci"
19081aa0c0c7SHu Tao #define PCI_OHCI(obj) OBJECT_CHECK(OHCIPCIState, (obj), TYPE_PCI_OHCI)
19091aa0c0c7SHu Tao 
1910f1ae32a1SGerd Hoffmann typedef struct {
19111aa0c0c7SHu Tao     /*< private >*/
19121aa0c0c7SHu Tao     PCIDevice parent_obj;
19131aa0c0c7SHu Tao     /*< public >*/
19141aa0c0c7SHu Tao 
1915f1ae32a1SGerd Hoffmann     OHCIState state;
1916f1ae32a1SGerd Hoffmann     char *masterbus;
1917f1ae32a1SGerd Hoffmann     uint32_t num_ports;
1918f1ae32a1SGerd Hoffmann     uint32_t firstport;
1919f1ae32a1SGerd Hoffmann } OHCIPCIState;
1920f1ae32a1SGerd Hoffmann 
1921cf66ee8eSAlexey Kardashevskiy /** A typical O/EHCI will stop operating, set itself into error state
1922cf66ee8eSAlexey Kardashevskiy  * (which can be queried by MMIO) and will set PERR in its config
1923cf66ee8eSAlexey Kardashevskiy  * space to signal that it got an error
1924cf66ee8eSAlexey Kardashevskiy  */
1925cf66ee8eSAlexey Kardashevskiy static void ohci_die(OHCIState *ohci)
1926cf66ee8eSAlexey Kardashevskiy {
1927cf66ee8eSAlexey Kardashevskiy     OHCIPCIState *dev = container_of(ohci, OHCIPCIState, state);
1928cf66ee8eSAlexey Kardashevskiy 
1929cf66ee8eSAlexey Kardashevskiy     fprintf(stderr, "%s: DMA error\n", __func__);
1930cf66ee8eSAlexey Kardashevskiy 
1931cf66ee8eSAlexey Kardashevskiy     ohci_set_interrupt(ohci, OHCI_INTR_UE);
1932cf66ee8eSAlexey Kardashevskiy     ohci_bus_stop(ohci);
1933cf66ee8eSAlexey Kardashevskiy     pci_set_word(dev->parent_obj.config + PCI_STATUS,
1934cf66ee8eSAlexey Kardashevskiy                  PCI_STATUS_DETECTED_PARITY);
1935cf66ee8eSAlexey Kardashevskiy }
1936cf66ee8eSAlexey Kardashevskiy 
19371aa0c0c7SHu Tao static int usb_ohci_initfn_pci(PCIDevice *dev)
1938f1ae32a1SGerd Hoffmann {
19391aa0c0c7SHu Tao     OHCIPCIState *ohci = PCI_OHCI(dev);
1940f1ae32a1SGerd Hoffmann 
19411aa0c0c7SHu Tao     dev->config[PCI_CLASS_PROG] = 0x10; /* OHCI */
19421aa0c0c7SHu Tao     dev->config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */
1943f1ae32a1SGerd Hoffmann 
19441aa0c0c7SHu Tao     if (usb_ohci_init(&ohci->state, DEVICE(dev), ohci->num_ports, 0,
19459ac6a217SDavid Gibson                       ohci->masterbus, ohci->firstport,
1946df32fd1cSPaolo Bonzini                       pci_get_address_space(dev)) != 0) {
1947f1ae32a1SGerd Hoffmann         return -1;
1948f1ae32a1SGerd Hoffmann     }
19499e64f8a3SMarcel Apfelbaum     ohci->state.irq = pci_allocate_irq(dev);
1950f1ae32a1SGerd Hoffmann 
19511aa0c0c7SHu Tao     pci_register_bar(dev, 0, 0, &ohci->state.mem);
1952f1ae32a1SGerd Hoffmann     return 0;
1953f1ae32a1SGerd Hoffmann }
1954f1ae32a1SGerd Hoffmann 
19551aa0c0c7SHu Tao #define TYPE_SYSBUS_OHCI "sysbus-ohci"
19561aa0c0c7SHu Tao #define SYSBUS_OHCI(obj) OBJECT_CHECK(OHCISysBusState, (obj), TYPE_SYSBUS_OHCI)
19571aa0c0c7SHu Tao 
1958f1ae32a1SGerd Hoffmann typedef struct {
19591aa0c0c7SHu Tao     /*< private >*/
19601aa0c0c7SHu Tao     SysBusDevice parent_obj;
19611aa0c0c7SHu Tao     /*< public >*/
19621aa0c0c7SHu Tao 
1963f1ae32a1SGerd Hoffmann     OHCIState ohci;
1964f1ae32a1SGerd Hoffmann     uint32_t num_ports;
19659ac6a217SDavid Gibson     dma_addr_t dma_offset;
1966f1ae32a1SGerd Hoffmann } OHCISysBusState;
1967f1ae32a1SGerd Hoffmann 
1968457215ecSHu Tao static void ohci_realize_pxa(DeviceState *dev, Error **errp)
1969f1ae32a1SGerd Hoffmann {
19701aa0c0c7SHu Tao     OHCISysBusState *s = SYSBUS_OHCI(dev);
1971457215ecSHu Tao     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
1972f1ae32a1SGerd Hoffmann 
1973f1ae32a1SGerd Hoffmann     /* Cannot fail as we pass NULL for masterbus */
1974457215ecSHu Tao     usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset, NULL, 0,
1975df32fd1cSPaolo Bonzini                   &address_space_memory);
1976457215ecSHu Tao     sysbus_init_irq(sbd, &s->ohci.irq);
1977457215ecSHu Tao     sysbus_init_mmio(sbd, &s->ohci.mem);
1978f1ae32a1SGerd Hoffmann }
1979f1ae32a1SGerd Hoffmann 
1980f1ae32a1SGerd Hoffmann static Property ohci_pci_properties[] = {
1981f1ae32a1SGerd Hoffmann     DEFINE_PROP_STRING("masterbus", OHCIPCIState, masterbus),
1982f1ae32a1SGerd Hoffmann     DEFINE_PROP_UINT32("num-ports", OHCIPCIState, num_ports, 3),
1983f1ae32a1SGerd Hoffmann     DEFINE_PROP_UINT32("firstport", OHCIPCIState, firstport, 0),
1984f1ae32a1SGerd Hoffmann     DEFINE_PROP_END_OF_LIST(),
1985f1ae32a1SGerd Hoffmann };
1986f1ae32a1SGerd Hoffmann 
1987f1ae32a1SGerd Hoffmann static void ohci_pci_class_init(ObjectClass *klass, void *data)
1988f1ae32a1SGerd Hoffmann {
1989f1ae32a1SGerd Hoffmann     DeviceClass *dc = DEVICE_CLASS(klass);
1990f1ae32a1SGerd Hoffmann     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
1991f1ae32a1SGerd Hoffmann 
1992f1ae32a1SGerd Hoffmann     k->init = usb_ohci_initfn_pci;
1993f1ae32a1SGerd Hoffmann     k->vendor_id = PCI_VENDOR_ID_APPLE;
1994f1ae32a1SGerd Hoffmann     k->device_id = PCI_DEVICE_ID_APPLE_IPID_USB;
1995f1ae32a1SGerd Hoffmann     k->class_id = PCI_CLASS_SERIAL_USB;
1996125ee0edSMarcel Apfelbaum     set_bit(DEVICE_CATEGORY_USB, dc->categories);
1997f1ae32a1SGerd Hoffmann     dc->desc = "Apple USB Controller";
1998f1ae32a1SGerd Hoffmann     dc->props = ohci_pci_properties;
19992897ae02SIgor Mammedov     dc->hotpluggable = false;
2000f1ae32a1SGerd Hoffmann }
2001f1ae32a1SGerd Hoffmann 
20028c43a6f0SAndreas Färber static const TypeInfo ohci_pci_info = {
20031aa0c0c7SHu Tao     .name          = TYPE_PCI_OHCI,
2004f1ae32a1SGerd Hoffmann     .parent        = TYPE_PCI_DEVICE,
2005f1ae32a1SGerd Hoffmann     .instance_size = sizeof(OHCIPCIState),
2006f1ae32a1SGerd Hoffmann     .class_init    = ohci_pci_class_init,
2007f1ae32a1SGerd Hoffmann };
2008f1ae32a1SGerd Hoffmann 
2009f1ae32a1SGerd Hoffmann static Property ohci_sysbus_properties[] = {
2010f1ae32a1SGerd Hoffmann     DEFINE_PROP_UINT32("num-ports", OHCISysBusState, num_ports, 3),
20119ac6a217SDavid Gibson     DEFINE_PROP_DMAADDR("dma-offset", OHCISysBusState, dma_offset, 3),
2012f1ae32a1SGerd Hoffmann     DEFINE_PROP_END_OF_LIST(),
2013f1ae32a1SGerd Hoffmann };
2014f1ae32a1SGerd Hoffmann 
2015f1ae32a1SGerd Hoffmann static void ohci_sysbus_class_init(ObjectClass *klass, void *data)
2016f1ae32a1SGerd Hoffmann {
2017f1ae32a1SGerd Hoffmann     DeviceClass *dc = DEVICE_CLASS(klass);
2018f1ae32a1SGerd Hoffmann 
2019457215ecSHu Tao     dc->realize = ohci_realize_pxa;
2020125ee0edSMarcel Apfelbaum     set_bit(DEVICE_CATEGORY_USB, dc->categories);
2021f1ae32a1SGerd Hoffmann     dc->desc = "OHCI USB Controller";
2022f1ae32a1SGerd Hoffmann     dc->props = ohci_sysbus_properties;
2023f1ae32a1SGerd Hoffmann }
2024f1ae32a1SGerd Hoffmann 
20258c43a6f0SAndreas Färber static const TypeInfo ohci_sysbus_info = {
20261aa0c0c7SHu Tao     .name          = TYPE_SYSBUS_OHCI,
2027f1ae32a1SGerd Hoffmann     .parent        = TYPE_SYS_BUS_DEVICE,
2028f1ae32a1SGerd Hoffmann     .instance_size = sizeof(OHCISysBusState),
2029f1ae32a1SGerd Hoffmann     .class_init    = ohci_sysbus_class_init,
2030f1ae32a1SGerd Hoffmann };
2031f1ae32a1SGerd Hoffmann 
2032f1ae32a1SGerd Hoffmann static void ohci_register_types(void)
2033f1ae32a1SGerd Hoffmann {
2034f1ae32a1SGerd Hoffmann     type_register_static(&ohci_pci_info);
2035f1ae32a1SGerd Hoffmann     type_register_static(&ohci_sysbus_info);
2036f1ae32a1SGerd Hoffmann }
2037f1ae32a1SGerd Hoffmann 
2038f1ae32a1SGerd Hoffmann type_init(ohci_register_types)
2039