xref: /openbmc/qemu/hw/usb/hcd-ohci.c (revision 37bf0654)
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
10bee41971SChetan Pant  * version 2.1 of the License, or (at your option) any later version.
11f1ae32a1SGerd Hoffmann  *
12f1ae32a1SGerd Hoffmann  * This library is distributed in the hope that it will be useful,
13f1ae32a1SGerd Hoffmann  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14f1ae32a1SGerd Hoffmann  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15f1ae32a1SGerd Hoffmann  * Lesser General Public License for more details.
16f1ae32a1SGerd Hoffmann  *
17f1ae32a1SGerd Hoffmann  * You should have received a copy of the GNU Lesser General Public
18f1ae32a1SGerd Hoffmann  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19f1ae32a1SGerd Hoffmann  *
20f1ae32a1SGerd Hoffmann  * TODO:
21f1ae32a1SGerd Hoffmann  *  o Isochronous transfers
22f1ae32a1SGerd Hoffmann  *  o Allocate bandwidth in frames properly
23f1ae32a1SGerd Hoffmann  *  o Disable timers when nothing needs to be done, or remove timer usage
24f1ae32a1SGerd Hoffmann  *    all together.
25f1ae32a1SGerd Hoffmann  *  o BIOS work to boot from USB storage
26f1ae32a1SGerd Hoffmann */
27f1ae32a1SGerd Hoffmann 
28e532b2e0SPeter Maydell #include "qemu/osdep.h"
2964552b6bSMarkus Armbruster #include "hw/irq.h"
30da34e65cSMarkus Armbruster #include "qapi/error.h"
310b8fa32fSMarkus Armbruster #include "qemu/module.h"
321de7afc9SPaolo Bonzini #include "qemu/timer.h"
33f1ae32a1SGerd Hoffmann #include "hw/usb.h"
34d6454270SMarkus Armbruster #include "migration/vmstate.h"
35f1ae32a1SGerd Hoffmann #include "hw/sysbus.h"
369ac6a217SDavid Gibson #include "hw/qdev-dma.h"
37a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
38dc1f5988SAlexey Kardashevskiy #include "trace.h"
3934d97308SThomas Huth #include "hcd-ohci.h"
40f1ae32a1SGerd Hoffmann 
41f1ae32a1SGerd Hoffmann /* This causes frames to occur 1000x slower */
42f1ae32a1SGerd Hoffmann //#define OHCI_TIME_WARP 1
43f1ae32a1SGerd Hoffmann 
44ab6b1105SGerd Hoffmann #define ED_LINK_LIMIT 32
4595ed5693SLi Qiang 
46f1ae32a1SGerd Hoffmann static int64_t usb_frame_time;
47f1ae32a1SGerd Hoffmann static int64_t usb_bit_time;
48f1ae32a1SGerd Hoffmann 
49f1ae32a1SGerd Hoffmann /* Host Controller Communications Area */
50f1ae32a1SGerd Hoffmann struct ohci_hcca {
51f1ae32a1SGerd Hoffmann     uint32_t intr[32];
52f1ae32a1SGerd Hoffmann     uint16_t frame, pad;
53f1ae32a1SGerd Hoffmann     uint32_t done;
54f1ae32a1SGerd Hoffmann };
5586e18caeSWei Yang #define HCCA_WRITEBACK_OFFSET   offsetof(struct ohci_hcca, frame)
5686e18caeSWei Yang #define HCCA_WRITEBACK_SIZE     8 /* frame, pad, done */
5786e18caeSWei Yang 
5886e18caeSWei Yang #define ED_WBACK_OFFSET offsetof(struct ohci_ed, head)
5986e18caeSWei Yang #define ED_WBACK_SIZE   4
60f1ae32a1SGerd Hoffmann 
61f1ae32a1SGerd Hoffmann /* Bitfields for the first word of an Endpoint Desciptor.  */
62f1ae32a1SGerd Hoffmann #define OHCI_ED_FA_SHIFT  0
63f1ae32a1SGerd Hoffmann #define OHCI_ED_FA_MASK   (0x7f<<OHCI_ED_FA_SHIFT)
64f1ae32a1SGerd Hoffmann #define OHCI_ED_EN_SHIFT  7
65f1ae32a1SGerd Hoffmann #define OHCI_ED_EN_MASK   (0xf<<OHCI_ED_EN_SHIFT)
66f1ae32a1SGerd Hoffmann #define OHCI_ED_D_SHIFT   11
67f1ae32a1SGerd Hoffmann #define OHCI_ED_D_MASK    (3<<OHCI_ED_D_SHIFT)
68f1ae32a1SGerd Hoffmann #define OHCI_ED_S         (1<<13)
69f1ae32a1SGerd Hoffmann #define OHCI_ED_K         (1<<14)
70f1ae32a1SGerd Hoffmann #define OHCI_ED_F         (1<<15)
71f1ae32a1SGerd Hoffmann #define OHCI_ED_MPS_SHIFT 16
72f1ae32a1SGerd Hoffmann #define OHCI_ED_MPS_MASK  (0x7ff<<OHCI_ED_MPS_SHIFT)
73f1ae32a1SGerd Hoffmann 
74f1ae32a1SGerd Hoffmann /* Flags in the head field of an Endpoint Desciptor.  */
75f1ae32a1SGerd Hoffmann #define OHCI_ED_H         1
76f1ae32a1SGerd Hoffmann #define OHCI_ED_C         2
77f1ae32a1SGerd Hoffmann 
78f1ae32a1SGerd Hoffmann /* Bitfields for the first word of a Transfer Desciptor.  */
79f1ae32a1SGerd Hoffmann #define OHCI_TD_R         (1<<18)
80f1ae32a1SGerd Hoffmann #define OHCI_TD_DP_SHIFT  19
81f1ae32a1SGerd Hoffmann #define OHCI_TD_DP_MASK   (3<<OHCI_TD_DP_SHIFT)
82f1ae32a1SGerd Hoffmann #define OHCI_TD_DI_SHIFT  21
83f1ae32a1SGerd Hoffmann #define OHCI_TD_DI_MASK   (7<<OHCI_TD_DI_SHIFT)
84f1ae32a1SGerd Hoffmann #define OHCI_TD_T0        (1<<24)
85f1ae32a1SGerd Hoffmann #define OHCI_TD_T1        (1<<25)
86f1ae32a1SGerd Hoffmann #define OHCI_TD_EC_SHIFT  26
87f1ae32a1SGerd Hoffmann #define OHCI_TD_EC_MASK   (3<<OHCI_TD_EC_SHIFT)
88f1ae32a1SGerd Hoffmann #define OHCI_TD_CC_SHIFT  28
89f1ae32a1SGerd Hoffmann #define OHCI_TD_CC_MASK   (0xf<<OHCI_TD_CC_SHIFT)
90f1ae32a1SGerd Hoffmann 
91f1ae32a1SGerd Hoffmann /* Bitfields for the first word of an Isochronous Transfer Desciptor.  */
92f1ae32a1SGerd Hoffmann /* CC & DI - same as in the General Transfer Desciptor */
93f1ae32a1SGerd Hoffmann #define OHCI_TD_SF_SHIFT  0
94f1ae32a1SGerd Hoffmann #define OHCI_TD_SF_MASK   (0xffff<<OHCI_TD_SF_SHIFT)
95f1ae32a1SGerd Hoffmann #define OHCI_TD_FC_SHIFT  24
96f1ae32a1SGerd Hoffmann #define OHCI_TD_FC_MASK   (7<<OHCI_TD_FC_SHIFT)
97f1ae32a1SGerd Hoffmann 
98f1ae32a1SGerd Hoffmann /* Isochronous Transfer Desciptor - Offset / PacketStatusWord */
99f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_CC_SHIFT 12
100f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_CC_MASK  (0xf<<OHCI_TD_PSW_CC_SHIFT)
101f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_SIZE_SHIFT 0
102f1ae32a1SGerd Hoffmann #define OHCI_TD_PSW_SIZE_MASK  (0xfff<<OHCI_TD_PSW_SIZE_SHIFT)
103f1ae32a1SGerd Hoffmann 
104f1ae32a1SGerd Hoffmann #define OHCI_PAGE_MASK    0xfffff000
105f1ae32a1SGerd Hoffmann #define OHCI_OFFSET_MASK  0xfff
106f1ae32a1SGerd Hoffmann 
107f1ae32a1SGerd Hoffmann #define OHCI_DPTR_MASK    0xfffffff0
108f1ae32a1SGerd Hoffmann 
109f1ae32a1SGerd Hoffmann #define OHCI_BM(val, field) \
110f1ae32a1SGerd Hoffmann   (((val) & OHCI_##field##_MASK) >> OHCI_##field##_SHIFT)
111f1ae32a1SGerd Hoffmann 
112f1ae32a1SGerd Hoffmann #define OHCI_SET_BM(val, field, newval) do { \
113f1ae32a1SGerd Hoffmann     val &= ~OHCI_##field##_MASK; \
114f1ae32a1SGerd Hoffmann     val |= ((newval) << OHCI_##field##_SHIFT) & OHCI_##field##_MASK; \
115f1ae32a1SGerd Hoffmann     } while(0)
116f1ae32a1SGerd Hoffmann 
117f1ae32a1SGerd Hoffmann /* endpoint descriptor */
118f1ae32a1SGerd Hoffmann struct ohci_ed {
119f1ae32a1SGerd Hoffmann     uint32_t flags;
120f1ae32a1SGerd Hoffmann     uint32_t tail;
121f1ae32a1SGerd Hoffmann     uint32_t head;
122f1ae32a1SGerd Hoffmann     uint32_t next;
123f1ae32a1SGerd Hoffmann };
124f1ae32a1SGerd Hoffmann 
125f1ae32a1SGerd Hoffmann /* General transfer descriptor */
126f1ae32a1SGerd Hoffmann struct ohci_td {
127f1ae32a1SGerd Hoffmann     uint32_t flags;
128f1ae32a1SGerd Hoffmann     uint32_t cbp;
129f1ae32a1SGerd Hoffmann     uint32_t next;
130f1ae32a1SGerd Hoffmann     uint32_t be;
131f1ae32a1SGerd Hoffmann };
132f1ae32a1SGerd Hoffmann 
133f1ae32a1SGerd Hoffmann /* Isochronous transfer descriptor */
134f1ae32a1SGerd Hoffmann struct ohci_iso_td {
135f1ae32a1SGerd Hoffmann     uint32_t flags;
136f1ae32a1SGerd Hoffmann     uint32_t bp;
137f1ae32a1SGerd Hoffmann     uint32_t next;
138f1ae32a1SGerd Hoffmann     uint32_t be;
139f1ae32a1SGerd Hoffmann     uint16_t offset[8];
140f1ae32a1SGerd Hoffmann };
141f1ae32a1SGerd Hoffmann 
142f1ae32a1SGerd Hoffmann #define USB_HZ                      12000000
143f1ae32a1SGerd Hoffmann 
144f1ae32a1SGerd Hoffmann /* OHCI Local stuff */
145f1ae32a1SGerd Hoffmann #define OHCI_CTL_CBSR         ((1<<0)|(1<<1))
146f1ae32a1SGerd Hoffmann #define OHCI_CTL_PLE          (1<<2)
147f1ae32a1SGerd Hoffmann #define OHCI_CTL_IE           (1<<3)
148f1ae32a1SGerd Hoffmann #define OHCI_CTL_CLE          (1<<4)
149f1ae32a1SGerd Hoffmann #define OHCI_CTL_BLE          (1<<5)
150f1ae32a1SGerd Hoffmann #define OHCI_CTL_HCFS         ((1<<6)|(1<<7))
151f1ae32a1SGerd Hoffmann #define  OHCI_USB_RESET       0x00
152f1ae32a1SGerd Hoffmann #define  OHCI_USB_RESUME      0x40
153f1ae32a1SGerd Hoffmann #define  OHCI_USB_OPERATIONAL 0x80
154f1ae32a1SGerd Hoffmann #define  OHCI_USB_SUSPEND     0xc0
155f1ae32a1SGerd Hoffmann #define OHCI_CTL_IR           (1<<8)
156f1ae32a1SGerd Hoffmann #define OHCI_CTL_RWC          (1<<9)
157f1ae32a1SGerd Hoffmann #define OHCI_CTL_RWE          (1<<10)
158f1ae32a1SGerd Hoffmann 
159f1ae32a1SGerd Hoffmann #define OHCI_STATUS_HCR       (1<<0)
160f1ae32a1SGerd Hoffmann #define OHCI_STATUS_CLF       (1<<1)
161f1ae32a1SGerd Hoffmann #define OHCI_STATUS_BLF       (1<<2)
162f1ae32a1SGerd Hoffmann #define OHCI_STATUS_OCR       (1<<3)
163f1ae32a1SGerd Hoffmann #define OHCI_STATUS_SOC       ((1<<6)|(1<<7))
164f1ae32a1SGerd Hoffmann 
16500b01793SPeter Maydell #define OHCI_INTR_SO          (1U<<0) /* Scheduling overrun */
16600b01793SPeter Maydell #define OHCI_INTR_WD          (1U<<1) /* HcDoneHead writeback */
16700b01793SPeter Maydell #define OHCI_INTR_SF          (1U<<2) /* Start of frame */
16800b01793SPeter Maydell #define OHCI_INTR_RD          (1U<<3) /* Resume detect */
16900b01793SPeter Maydell #define OHCI_INTR_UE          (1U<<4) /* Unrecoverable error */
17000b01793SPeter Maydell #define OHCI_INTR_FNO         (1U<<5) /* Frame number overflow */
17100b01793SPeter Maydell #define OHCI_INTR_RHSC        (1U<<6) /* Root hub status change */
17200b01793SPeter Maydell #define OHCI_INTR_OC          (1U<<30) /* Ownership change */
17300b01793SPeter Maydell #define OHCI_INTR_MIE         (1U<<31) /* Master Interrupt Enable */
174f1ae32a1SGerd Hoffmann 
175f1ae32a1SGerd Hoffmann #define OHCI_HCCA_SIZE        0x100
176f1ae32a1SGerd Hoffmann #define OHCI_HCCA_MASK        0xffffff00
177f1ae32a1SGerd Hoffmann 
178f1ae32a1SGerd Hoffmann #define OHCI_EDPTR_MASK       0xfffffff0
179f1ae32a1SGerd Hoffmann 
180f1ae32a1SGerd Hoffmann #define OHCI_FMI_FI           0x00003fff
181f1ae32a1SGerd Hoffmann #define OHCI_FMI_FSMPS        0xffff0000
182f1ae32a1SGerd Hoffmann #define OHCI_FMI_FIT          0x80000000
183f1ae32a1SGerd Hoffmann 
18400b01793SPeter Maydell #define OHCI_FR_RT            (1U<<31)
185f1ae32a1SGerd Hoffmann 
186f1ae32a1SGerd Hoffmann #define OHCI_LS_THRESH        0x628
187f1ae32a1SGerd Hoffmann 
188f1ae32a1SGerd Hoffmann #define OHCI_RHA_RW_MASK      0x00000000 /* Mask of supported features.  */
189f1ae32a1SGerd Hoffmann #define OHCI_RHA_PSM          (1<<8)
190f1ae32a1SGerd Hoffmann #define OHCI_RHA_NPS          (1<<9)
191f1ae32a1SGerd Hoffmann #define OHCI_RHA_DT           (1<<10)
192f1ae32a1SGerd Hoffmann #define OHCI_RHA_OCPM         (1<<11)
193f1ae32a1SGerd Hoffmann #define OHCI_RHA_NOCP         (1<<12)
194f1ae32a1SGerd Hoffmann #define OHCI_RHA_POTPGT_MASK  0xff000000
195f1ae32a1SGerd Hoffmann 
19600b01793SPeter Maydell #define OHCI_RHS_LPS          (1U<<0)
19700b01793SPeter Maydell #define OHCI_RHS_OCI          (1U<<1)
19800b01793SPeter Maydell #define OHCI_RHS_DRWE         (1U<<15)
19900b01793SPeter Maydell #define OHCI_RHS_LPSC         (1U<<16)
20000b01793SPeter Maydell #define OHCI_RHS_OCIC         (1U<<17)
20100b01793SPeter Maydell #define OHCI_RHS_CRWE         (1U<<31)
202f1ae32a1SGerd Hoffmann 
203f1ae32a1SGerd Hoffmann #define OHCI_PORT_CCS         (1<<0)
204f1ae32a1SGerd Hoffmann #define OHCI_PORT_PES         (1<<1)
205f1ae32a1SGerd Hoffmann #define OHCI_PORT_PSS         (1<<2)
206f1ae32a1SGerd Hoffmann #define OHCI_PORT_POCI        (1<<3)
207f1ae32a1SGerd Hoffmann #define OHCI_PORT_PRS         (1<<4)
208f1ae32a1SGerd Hoffmann #define OHCI_PORT_PPS         (1<<8)
209f1ae32a1SGerd Hoffmann #define OHCI_PORT_LSDA        (1<<9)
210f1ae32a1SGerd Hoffmann #define OHCI_PORT_CSC         (1<<16)
211f1ae32a1SGerd Hoffmann #define OHCI_PORT_PESC        (1<<17)
212f1ae32a1SGerd Hoffmann #define OHCI_PORT_PSSC        (1<<18)
213f1ae32a1SGerd Hoffmann #define OHCI_PORT_OCIC        (1<<19)
214f1ae32a1SGerd Hoffmann #define OHCI_PORT_PRSC        (1<<20)
215f1ae32a1SGerd Hoffmann #define OHCI_PORT_WTC         (OHCI_PORT_CSC|OHCI_PORT_PESC|OHCI_PORT_PSSC \
216f1ae32a1SGerd Hoffmann                                |OHCI_PORT_OCIC|OHCI_PORT_PRSC)
217f1ae32a1SGerd Hoffmann 
218f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_SETUP     0x0
219f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_OUT       0x1
220f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_IN        0x2
221f1ae32a1SGerd Hoffmann #define OHCI_TD_DIR_RESERVED  0x3
222f1ae32a1SGerd Hoffmann 
223f1ae32a1SGerd Hoffmann #define OHCI_CC_NOERROR             0x0
224f1ae32a1SGerd Hoffmann #define OHCI_CC_CRC                 0x1
225f1ae32a1SGerd Hoffmann #define OHCI_CC_BITSTUFFING         0x2
226f1ae32a1SGerd Hoffmann #define OHCI_CC_DATATOGGLEMISMATCH  0x3
227f1ae32a1SGerd Hoffmann #define OHCI_CC_STALL               0x4
228f1ae32a1SGerd Hoffmann #define OHCI_CC_DEVICENOTRESPONDING 0x5
229f1ae32a1SGerd Hoffmann #define OHCI_CC_PIDCHECKFAILURE     0x6
230f1ae32a1SGerd Hoffmann #define OHCI_CC_UNDEXPETEDPID       0x7
231f1ae32a1SGerd Hoffmann #define OHCI_CC_DATAOVERRUN         0x8
232f1ae32a1SGerd Hoffmann #define OHCI_CC_DATAUNDERRUN        0x9
233f1ae32a1SGerd Hoffmann #define OHCI_CC_BUFFEROVERRUN       0xc
234f1ae32a1SGerd Hoffmann #define OHCI_CC_BUFFERUNDERRUN      0xd
235f1ae32a1SGerd Hoffmann 
236f1ae32a1SGerd Hoffmann #define OHCI_HRESET_FSBIR       (1 << 0)
237f1ae32a1SGerd Hoffmann 
23872e0c127SThomas Huth static void ohci_die(OHCIState *ohci)
23972e0c127SThomas Huth {
24072e0c127SThomas Huth     ohci->ohci_die(ohci);
24172e0c127SThomas Huth }
242cf66ee8eSAlexey Kardashevskiy 
243f1ae32a1SGerd Hoffmann /* Update IRQ levels */
244f1ae32a1SGerd Hoffmann static inline void ohci_intr_update(OHCIState *ohci)
245f1ae32a1SGerd Hoffmann {
246f1ae32a1SGerd Hoffmann     int level = 0;
247f1ae32a1SGerd Hoffmann 
248f1ae32a1SGerd Hoffmann     if ((ohci->intr & OHCI_INTR_MIE) &&
249f1ae32a1SGerd Hoffmann         (ohci->intr_status & ohci->intr))
250f1ae32a1SGerd Hoffmann         level = 1;
251f1ae32a1SGerd Hoffmann 
252f1ae32a1SGerd Hoffmann     qemu_set_irq(ohci->irq, level);
253f1ae32a1SGerd Hoffmann }
254f1ae32a1SGerd Hoffmann 
255f1ae32a1SGerd Hoffmann /* Set an interrupt */
256f1ae32a1SGerd Hoffmann static inline void ohci_set_interrupt(OHCIState *ohci, uint32_t intr)
257f1ae32a1SGerd Hoffmann {
258f1ae32a1SGerd Hoffmann     ohci->intr_status |= intr;
259f1ae32a1SGerd Hoffmann     ohci_intr_update(ohci);
260f1ae32a1SGerd Hoffmann }
261f1ae32a1SGerd Hoffmann 
262f1ae32a1SGerd Hoffmann static USBDevice *ohci_find_device(OHCIState *ohci, uint8_t addr)
263f1ae32a1SGerd Hoffmann {
264f1ae32a1SGerd Hoffmann     USBDevice *dev;
265f1ae32a1SGerd Hoffmann     int i;
266f1ae32a1SGerd Hoffmann 
267f1ae32a1SGerd Hoffmann     for (i = 0; i < ohci->num_ports; i++) {
268f1ae32a1SGerd Hoffmann         if ((ohci->rhport[i].ctrl & OHCI_PORT_PES) == 0) {
269f1ae32a1SGerd Hoffmann             continue;
270f1ae32a1SGerd Hoffmann         }
271f1ae32a1SGerd Hoffmann         dev = usb_find_device(&ohci->rhport[i].port, addr);
272f1ae32a1SGerd Hoffmann         if (dev != NULL) {
273f1ae32a1SGerd Hoffmann             return dev;
274f1ae32a1SGerd Hoffmann         }
275f1ae32a1SGerd Hoffmann     }
276f1ae32a1SGerd Hoffmann     return NULL;
277f1ae32a1SGerd Hoffmann }
278f1ae32a1SGerd Hoffmann 
27934d97308SThomas Huth void ohci_stop_endpoints(OHCIState *ohci)
280f79738b0SHans de Goede {
281f79738b0SHans de Goede     USBDevice *dev;
282f79738b0SHans de Goede     int i, j;
283f79738b0SHans de Goede 
284ae310557SBALATON Zoltan     if (ohci->async_td) {
285ae310557SBALATON Zoltan         usb_cancel_packet(&ohci->usb_packet);
286ae310557SBALATON Zoltan         ohci->async_td = 0;
287ae310557SBALATON Zoltan     }
288f79738b0SHans de Goede     for (i = 0; i < ohci->num_ports; i++) {
289f79738b0SHans de Goede         dev = ohci->rhport[i].port.dev;
290f79738b0SHans de Goede         if (dev && dev->attached) {
291f79738b0SHans de Goede             usb_device_ep_stopped(dev, &dev->ep_ctl);
292f79738b0SHans de Goede             for (j = 0; j < USB_MAX_ENDPOINTS; j++) {
293f79738b0SHans de Goede                 usb_device_ep_stopped(dev, &dev->ep_in[j]);
294f79738b0SHans de Goede                 usb_device_ep_stopped(dev, &dev->ep_out[j]);
295f79738b0SHans de Goede             }
296f79738b0SHans de Goede         }
297f79738b0SHans de Goede     }
298f79738b0SHans de Goede }
299f79738b0SHans de Goede 
30084d04e21SHervé Poussineau static void ohci_roothub_reset(OHCIState *ohci)
301f1ae32a1SGerd Hoffmann {
302f1ae32a1SGerd Hoffmann     OHCIPort *port;
303f1ae32a1SGerd Hoffmann     int i;
304f1ae32a1SGerd Hoffmann 
305f1ae32a1SGerd Hoffmann     ohci_bus_stop(ohci);
30684d04e21SHervé Poussineau     ohci->rhdesc_a = OHCI_RHA_NPS | ohci->num_ports;
30784d04e21SHervé Poussineau     ohci->rhdesc_b = 0x0; /* Impl. specific */
30884d04e21SHervé Poussineau     ohci->rhstatus = 0;
30984d04e21SHervé Poussineau 
31084d04e21SHervé Poussineau     for (i = 0; i < ohci->num_ports; i++) {
31184d04e21SHervé Poussineau         port = &ohci->rhport[i];
31284d04e21SHervé Poussineau         port->ctrl = 0;
31384d04e21SHervé Poussineau         if (port->port.dev && port->port.dev->attached) {
31484d04e21SHervé Poussineau             usb_port_reset(&port->port);
31584d04e21SHervé Poussineau         }
31684d04e21SHervé Poussineau     }
31784d04e21SHervé Poussineau     ohci_stop_endpoints(ohci);
31884d04e21SHervé Poussineau }
31984d04e21SHervé Poussineau 
32084d04e21SHervé Poussineau /* Reset the controller */
32184d04e21SHervé Poussineau static void ohci_soft_reset(OHCIState *ohci)
32284d04e21SHervé Poussineau {
32384d04e21SHervé Poussineau     trace_usb_ohci_reset(ohci->name);
32484d04e21SHervé Poussineau 
32584d04e21SHervé Poussineau     ohci_bus_stop(ohci);
32684d04e21SHervé Poussineau     ohci->ctl = (ohci->ctl & OHCI_CTL_IR) | OHCI_USB_SUSPEND;
327f1ae32a1SGerd Hoffmann     ohci->old_ctl = 0;
328f1ae32a1SGerd Hoffmann     ohci->status = 0;
329f1ae32a1SGerd Hoffmann     ohci->intr_status = 0;
330f1ae32a1SGerd Hoffmann     ohci->intr = OHCI_INTR_MIE;
331f1ae32a1SGerd Hoffmann 
332f1ae32a1SGerd Hoffmann     ohci->hcca = 0;
333f1ae32a1SGerd Hoffmann     ohci->ctrl_head = ohci->ctrl_cur = 0;
334f1ae32a1SGerd Hoffmann     ohci->bulk_head = ohci->bulk_cur = 0;
335f1ae32a1SGerd Hoffmann     ohci->per_cur = 0;
336f1ae32a1SGerd Hoffmann     ohci->done = 0;
337f1ae32a1SGerd Hoffmann     ohci->done_count = 7;
338f1ae32a1SGerd Hoffmann 
339f1ae32a1SGerd Hoffmann     /* FSMPS is marked TBD in OCHI 1.0, what gives ffs?
340f1ae32a1SGerd Hoffmann      * I took the value linux sets ...
341f1ae32a1SGerd Hoffmann      */
342f1ae32a1SGerd Hoffmann     ohci->fsmps = 0x2778;
343f1ae32a1SGerd Hoffmann     ohci->fi = 0x2edf;
344f1ae32a1SGerd Hoffmann     ohci->fit = 0;
345f1ae32a1SGerd Hoffmann     ohci->frt = 0;
346f1ae32a1SGerd Hoffmann     ohci->frame_number = 0;
347f1ae32a1SGerd Hoffmann     ohci->pstart = 0;
348f1ae32a1SGerd Hoffmann     ohci->lst = OHCI_LS_THRESH;
34984d04e21SHervé Poussineau }
350f1ae32a1SGerd Hoffmann 
35134d97308SThomas Huth void ohci_hard_reset(OHCIState *ohci)
352f1ae32a1SGerd Hoffmann {
35384d04e21SHervé Poussineau     ohci_soft_reset(ohci);
35484d04e21SHervé Poussineau     ohci->ctl = 0;
35584d04e21SHervé Poussineau     ohci_roothub_reset(ohci);
356f1ae32a1SGerd Hoffmann }
357f1ae32a1SGerd Hoffmann 
358f1ae32a1SGerd Hoffmann /* Get an array of dwords from main memory */
359f1ae32a1SGerd Hoffmann static inline int get_dwords(OHCIState *ohci,
3609ac6a217SDavid Gibson                              dma_addr_t addr, uint32_t *buf, int num)
361f1ae32a1SGerd Hoffmann {
362f1ae32a1SGerd Hoffmann     int i;
363f1ae32a1SGerd Hoffmann 
364f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
365f1ae32a1SGerd Hoffmann 
366f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
367ba06fe8aSPhilippe Mathieu-Daudé         if (dma_memory_read(ohci->as, addr,
368ba06fe8aSPhilippe Mathieu-Daudé                             buf, sizeof(*buf), MEMTXATTRS_UNSPECIFIED)) {
369cf66ee8eSAlexey Kardashevskiy             return -1;
370cf66ee8eSAlexey Kardashevskiy         }
371f1ae32a1SGerd Hoffmann         *buf = le32_to_cpu(*buf);
372f1ae32a1SGerd Hoffmann     }
373f1ae32a1SGerd Hoffmann 
374cf66ee8eSAlexey Kardashevskiy     return 0;
375f1ae32a1SGerd Hoffmann }
376f1ae32a1SGerd Hoffmann 
377f1ae32a1SGerd Hoffmann /* Put an array of dwords in to main memory */
378f1ae32a1SGerd Hoffmann static inline int put_dwords(OHCIState *ohci,
3799ac6a217SDavid Gibson                              dma_addr_t addr, uint32_t *buf, int num)
380f1ae32a1SGerd Hoffmann {
381f1ae32a1SGerd Hoffmann     int i;
382f1ae32a1SGerd Hoffmann 
383f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
384f1ae32a1SGerd Hoffmann 
385f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
386f1ae32a1SGerd Hoffmann         uint32_t tmp = cpu_to_le32(*buf);
387ba06fe8aSPhilippe Mathieu-Daudé         if (dma_memory_write(ohci->as, addr,
388ba06fe8aSPhilippe Mathieu-Daudé                              &tmp, sizeof(tmp), MEMTXATTRS_UNSPECIFIED)) {
389cf66ee8eSAlexey Kardashevskiy             return -1;
390cf66ee8eSAlexey Kardashevskiy         }
391f1ae32a1SGerd Hoffmann     }
392f1ae32a1SGerd Hoffmann 
393cf66ee8eSAlexey Kardashevskiy     return 0;
394f1ae32a1SGerd Hoffmann }
395f1ae32a1SGerd Hoffmann 
396f1ae32a1SGerd Hoffmann /* Get an array of words from main memory */
397f1ae32a1SGerd Hoffmann static inline int get_words(OHCIState *ohci,
3989ac6a217SDavid Gibson                             dma_addr_t addr, uint16_t *buf, int num)
399f1ae32a1SGerd Hoffmann {
400f1ae32a1SGerd Hoffmann     int i;
401f1ae32a1SGerd Hoffmann 
402f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
403f1ae32a1SGerd Hoffmann 
404f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
405ba06fe8aSPhilippe Mathieu-Daudé         if (dma_memory_read(ohci->as, addr,
406ba06fe8aSPhilippe Mathieu-Daudé                             buf, sizeof(*buf), MEMTXATTRS_UNSPECIFIED)) {
407cf66ee8eSAlexey Kardashevskiy             return -1;
408cf66ee8eSAlexey Kardashevskiy         }
409f1ae32a1SGerd Hoffmann         *buf = le16_to_cpu(*buf);
410f1ae32a1SGerd Hoffmann     }
411f1ae32a1SGerd Hoffmann 
412cf66ee8eSAlexey Kardashevskiy     return 0;
413f1ae32a1SGerd Hoffmann }
414f1ae32a1SGerd Hoffmann 
415f1ae32a1SGerd Hoffmann /* Put an array of words in to main memory */
416f1ae32a1SGerd Hoffmann static inline int put_words(OHCIState *ohci,
4179ac6a217SDavid Gibson                             dma_addr_t addr, uint16_t *buf, int num)
418f1ae32a1SGerd Hoffmann {
419f1ae32a1SGerd Hoffmann     int i;
420f1ae32a1SGerd Hoffmann 
421f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
422f1ae32a1SGerd Hoffmann 
423f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
424f1ae32a1SGerd Hoffmann         uint16_t tmp = cpu_to_le16(*buf);
425ba06fe8aSPhilippe Mathieu-Daudé         if (dma_memory_write(ohci->as, addr,
426ba06fe8aSPhilippe Mathieu-Daudé                              &tmp, sizeof(tmp), MEMTXATTRS_UNSPECIFIED)) {
427cf66ee8eSAlexey Kardashevskiy             return -1;
428cf66ee8eSAlexey Kardashevskiy         }
429f1ae32a1SGerd Hoffmann     }
430f1ae32a1SGerd Hoffmann 
431cf66ee8eSAlexey Kardashevskiy     return 0;
432f1ae32a1SGerd Hoffmann }
433f1ae32a1SGerd Hoffmann 
434f1ae32a1SGerd Hoffmann static inline int ohci_read_ed(OHCIState *ohci,
4359ac6a217SDavid Gibson                                dma_addr_t addr, struct ohci_ed *ed)
436f1ae32a1SGerd Hoffmann {
437f1ae32a1SGerd Hoffmann     return get_dwords(ohci, addr, (uint32_t *)ed, sizeof(*ed) >> 2);
438f1ae32a1SGerd Hoffmann }
439f1ae32a1SGerd Hoffmann 
440f1ae32a1SGerd Hoffmann static inline int ohci_read_td(OHCIState *ohci,
4419ac6a217SDavid Gibson                                dma_addr_t addr, struct ohci_td *td)
442f1ae32a1SGerd Hoffmann {
443f1ae32a1SGerd Hoffmann     return get_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2);
444f1ae32a1SGerd Hoffmann }
445f1ae32a1SGerd Hoffmann 
446f1ae32a1SGerd Hoffmann static inline int ohci_read_iso_td(OHCIState *ohci,
4479ac6a217SDavid Gibson                                    dma_addr_t addr, struct ohci_iso_td *td)
448f1ae32a1SGerd Hoffmann {
449cf66ee8eSAlexey Kardashevskiy     return get_dwords(ohci, addr, (uint32_t *)td, 4) ||
450cf66ee8eSAlexey Kardashevskiy            get_words(ohci, addr + 16, td->offset, 8);
451f1ae32a1SGerd Hoffmann }
452f1ae32a1SGerd Hoffmann 
453f1ae32a1SGerd Hoffmann static inline int ohci_read_hcca(OHCIState *ohci,
4549ac6a217SDavid Gibson                                  dma_addr_t addr, struct ohci_hcca *hcca)
455f1ae32a1SGerd Hoffmann {
456ba06fe8aSPhilippe Mathieu-Daudé     return dma_memory_read(ohci->as, addr + ohci->localmem_base, hcca,
457ba06fe8aSPhilippe Mathieu-Daudé                            sizeof(*hcca), MEMTXATTRS_UNSPECIFIED);
458f1ae32a1SGerd Hoffmann }
459f1ae32a1SGerd Hoffmann 
460f1ae32a1SGerd Hoffmann static inline int ohci_put_ed(OHCIState *ohci,
4619ac6a217SDavid Gibson                               dma_addr_t addr, struct ohci_ed *ed)
462f1ae32a1SGerd Hoffmann {
46386e18caeSWei Yang     /* ed->tail is under control of the HCD.
46486e18caeSWei Yang      * Since just ed->head is changed by HC, just write back this
46586e18caeSWei Yang      */
46686e18caeSWei Yang 
46786e18caeSWei Yang     return put_dwords(ohci, addr + ED_WBACK_OFFSET,
46886e18caeSWei Yang                       (uint32_t *)((char *)ed + ED_WBACK_OFFSET),
46986e18caeSWei Yang                       ED_WBACK_SIZE >> 2);
470f1ae32a1SGerd Hoffmann }
471f1ae32a1SGerd Hoffmann 
472f1ae32a1SGerd Hoffmann static inline int ohci_put_td(OHCIState *ohci,
4739ac6a217SDavid Gibson                               dma_addr_t addr, struct ohci_td *td)
474f1ae32a1SGerd Hoffmann {
475f1ae32a1SGerd Hoffmann     return put_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2);
476f1ae32a1SGerd Hoffmann }
477f1ae32a1SGerd Hoffmann 
478f1ae32a1SGerd Hoffmann static inline int ohci_put_iso_td(OHCIState *ohci,
4799ac6a217SDavid Gibson                                   dma_addr_t addr, struct ohci_iso_td *td)
480f1ae32a1SGerd Hoffmann {
481cae7f29cSJack Un     return put_dwords(ohci, addr, (uint32_t *)td, 4) ||
482cae7f29cSJack Un            put_words(ohci, addr + 16, td->offset, 8);
483f1ae32a1SGerd Hoffmann }
484f1ae32a1SGerd Hoffmann 
485f1ae32a1SGerd Hoffmann static inline int ohci_put_hcca(OHCIState *ohci,
4869ac6a217SDavid Gibson                                 dma_addr_t addr, struct ohci_hcca *hcca)
487f1ae32a1SGerd Hoffmann {
488cf66ee8eSAlexey Kardashevskiy     return dma_memory_write(ohci->as,
4899ac6a217SDavid Gibson                             addr + ohci->localmem_base + HCCA_WRITEBACK_OFFSET,
49086e18caeSWei Yang                             (char *)hcca + HCCA_WRITEBACK_OFFSET,
491ba06fe8aSPhilippe Mathieu-Daudé                             HCCA_WRITEBACK_SIZE, MEMTXATTRS_UNSPECIFIED);
492f1ae32a1SGerd Hoffmann }
493f1ae32a1SGerd Hoffmann 
494f1ae32a1SGerd Hoffmann /* Read/Write the contents of a TD from/to main memory.  */
495cf66ee8eSAlexey Kardashevskiy static int ohci_copy_td(OHCIState *ohci, struct ohci_td *td,
4969ac6a217SDavid Gibson                         uint8_t *buf, int len, DMADirection dir)
497f1ae32a1SGerd Hoffmann {
4989ac6a217SDavid Gibson     dma_addr_t ptr, n;
499f1ae32a1SGerd Hoffmann 
500f1ae32a1SGerd Hoffmann     ptr = td->cbp;
501f1ae32a1SGerd Hoffmann     n = 0x1000 - (ptr & 0xfff);
502f1ae32a1SGerd Hoffmann     if (n > len)
503f1ae32a1SGerd Hoffmann         n = len;
504cf66ee8eSAlexey Kardashevskiy 
50523faf569SPhilippe Mathieu-Daudé     if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf,
50623faf569SPhilippe Mathieu-Daudé                       n, dir, MEMTXATTRS_UNSPECIFIED)) {
507cf66ee8eSAlexey Kardashevskiy         return -1;
508cf66ee8eSAlexey Kardashevskiy     }
509cf66ee8eSAlexey Kardashevskiy     if (n == len) {
510cf66ee8eSAlexey Kardashevskiy         return 0;
511cf66ee8eSAlexey Kardashevskiy     }
512f1ae32a1SGerd Hoffmann     ptr = td->be & ~0xfffu;
513f1ae32a1SGerd Hoffmann     buf += n;
514cf66ee8eSAlexey Kardashevskiy     if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf,
51523faf569SPhilippe Mathieu-Daudé                       len - n, dir, MEMTXATTRS_UNSPECIFIED)) {
516cf66ee8eSAlexey Kardashevskiy         return -1;
517cf66ee8eSAlexey Kardashevskiy     }
518cf66ee8eSAlexey Kardashevskiy     return 0;
519f1ae32a1SGerd Hoffmann }
520f1ae32a1SGerd Hoffmann 
521f1ae32a1SGerd Hoffmann /* Read/Write the contents of an ISO TD from/to main memory.  */
522cf66ee8eSAlexey Kardashevskiy static int ohci_copy_iso_td(OHCIState *ohci,
523f1ae32a1SGerd Hoffmann                             uint32_t start_addr, uint32_t end_addr,
5249ac6a217SDavid Gibson                             uint8_t *buf, int len, DMADirection dir)
525f1ae32a1SGerd Hoffmann {
5269ac6a217SDavid Gibson     dma_addr_t ptr, n;
527f1ae32a1SGerd Hoffmann 
528f1ae32a1SGerd Hoffmann     ptr = start_addr;
529f1ae32a1SGerd Hoffmann     n = 0x1000 - (ptr & 0xfff);
530f1ae32a1SGerd Hoffmann     if (n > len)
531f1ae32a1SGerd Hoffmann         n = len;
532cf66ee8eSAlexey Kardashevskiy 
53323faf569SPhilippe Mathieu-Daudé     if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf,
53423faf569SPhilippe Mathieu-Daudé                       n, dir, MEMTXATTRS_UNSPECIFIED)) {
535cf66ee8eSAlexey Kardashevskiy         return -1;
536cf66ee8eSAlexey Kardashevskiy     }
537cf66ee8eSAlexey Kardashevskiy     if (n == len) {
538cf66ee8eSAlexey Kardashevskiy         return 0;
539cf66ee8eSAlexey Kardashevskiy     }
540f1ae32a1SGerd Hoffmann     ptr = end_addr & ~0xfffu;
541f1ae32a1SGerd Hoffmann     buf += n;
542cf66ee8eSAlexey Kardashevskiy     if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf,
54323faf569SPhilippe Mathieu-Daudé                       len - n, dir, MEMTXATTRS_UNSPECIFIED)) {
544cf66ee8eSAlexey Kardashevskiy         return -1;
545cf66ee8eSAlexey Kardashevskiy     }
546cf66ee8eSAlexey Kardashevskiy     return 0;
547f1ae32a1SGerd Hoffmann }
548f1ae32a1SGerd Hoffmann 
549f1ae32a1SGerd Hoffmann #define USUB(a, b) ((int16_t)((uint16_t)(a) - (uint16_t)(b)))
550f1ae32a1SGerd Hoffmann 
551f1ae32a1SGerd Hoffmann static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
552f1ae32a1SGerd Hoffmann                                int completion)
553f1ae32a1SGerd Hoffmann {
554f1ae32a1SGerd Hoffmann     int dir;
555f1ae32a1SGerd Hoffmann     size_t len = 0;
556f1ae32a1SGerd Hoffmann     const char *str = NULL;
557f1ae32a1SGerd Hoffmann     int pid;
558f1ae32a1SGerd Hoffmann     int ret;
559f1ae32a1SGerd Hoffmann     int i;
560f1ae32a1SGerd Hoffmann     USBDevice *dev;
561f1ae32a1SGerd Hoffmann     USBEndpoint *ep;
562f1ae32a1SGerd Hoffmann     struct ohci_iso_td iso_td;
563f1ae32a1SGerd Hoffmann     uint32_t addr;
564f1ae32a1SGerd Hoffmann     uint16_t starting_frame;
565f1ae32a1SGerd Hoffmann     int16_t relative_frame_number;
566f1ae32a1SGerd Hoffmann     int frame_count;
567f1ae32a1SGerd Hoffmann     uint32_t start_offset, next_offset, end_offset = 0;
568f1ae32a1SGerd Hoffmann     uint32_t start_addr, end_addr;
569f1ae32a1SGerd Hoffmann 
570f1ae32a1SGerd Hoffmann     addr = ed->head & OHCI_DPTR_MASK;
571f1ae32a1SGerd Hoffmann 
572cf66ee8eSAlexey Kardashevskiy     if (ohci_read_iso_td(ohci, addr, &iso_td)) {
573dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_read_failed(addr);
574cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
57526f670a2SLi Qiang         return 1;
576f1ae32a1SGerd Hoffmann     }
577f1ae32a1SGerd Hoffmann 
578f1ae32a1SGerd Hoffmann     starting_frame = OHCI_BM(iso_td.flags, TD_SF);
579f1ae32a1SGerd Hoffmann     frame_count = OHCI_BM(iso_td.flags, TD_FC);
580f1ae32a1SGerd Hoffmann     relative_frame_number = USUB(ohci->frame_number, starting_frame);
581f1ae32a1SGerd Hoffmann 
582dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_iso_td_head(
583f1ae32a1SGerd Hoffmann            ed->head & OHCI_DPTR_MASK, ed->tail & OHCI_DPTR_MASK,
584f1ae32a1SGerd Hoffmann            iso_td.flags, iso_td.bp, iso_td.next, iso_td.be,
585f1ae32a1SGerd Hoffmann            ohci->frame_number, starting_frame,
586bc0d104cSAlex Bennée            frame_count, relative_frame_number);
5873af8f177SAlexey Kardashevskiy     trace_usb_ohci_iso_td_head_offset(
5883af8f177SAlexey Kardashevskiy            iso_td.offset[0], iso_td.offset[1],
5893af8f177SAlexey Kardashevskiy            iso_td.offset[2], iso_td.offset[3],
5903af8f177SAlexey Kardashevskiy            iso_td.offset[4], iso_td.offset[5],
5913af8f177SAlexey Kardashevskiy            iso_td.offset[6], iso_td.offset[7]);
592f1ae32a1SGerd Hoffmann 
593f1ae32a1SGerd Hoffmann     if (relative_frame_number < 0) {
594dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_relative_frame_number_neg(relative_frame_number);
595f1ae32a1SGerd Hoffmann         return 1;
596f1ae32a1SGerd Hoffmann     } else if (relative_frame_number > frame_count) {
597f1ae32a1SGerd Hoffmann         /* ISO TD expired - retire the TD to the Done Queue and continue with
598f1ae32a1SGerd Hoffmann            the next ISO TD of the same ED */
599dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_relative_frame_number_big(relative_frame_number,
600f1ae32a1SGerd Hoffmann                                                         frame_count);
6011be90ebeSPrasad J Pandit         if (OHCI_CC_DATAOVERRUN == OHCI_BM(iso_td.flags, TD_CC)) {
6021be90ebeSPrasad J Pandit             /* avoid infinite loop */
6031be90ebeSPrasad J Pandit             return 1;
6041be90ebeSPrasad J Pandit         }
605f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_DATAOVERRUN);
606f1ae32a1SGerd Hoffmann         ed->head &= ~OHCI_DPTR_MASK;
607f1ae32a1SGerd Hoffmann         ed->head |= (iso_td.next & OHCI_DPTR_MASK);
608f1ae32a1SGerd Hoffmann         iso_td.next = ohci->done;
609f1ae32a1SGerd Hoffmann         ohci->done = addr;
610f1ae32a1SGerd Hoffmann         i = OHCI_BM(iso_td.flags, TD_DI);
611f1ae32a1SGerd Hoffmann         if (i < ohci->done_count)
612f1ae32a1SGerd Hoffmann             ohci->done_count = i;
613cf66ee8eSAlexey Kardashevskiy         if (ohci_put_iso_td(ohci, addr, &iso_td)) {
614cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
615cf66ee8eSAlexey Kardashevskiy             return 1;
616cf66ee8eSAlexey Kardashevskiy         }
617f1ae32a1SGerd Hoffmann         return 0;
618f1ae32a1SGerd Hoffmann     }
619f1ae32a1SGerd Hoffmann 
620f1ae32a1SGerd Hoffmann     dir = OHCI_BM(ed->flags, ED_D);
621f1ae32a1SGerd Hoffmann     switch (dir) {
622f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_IN:
623f1ae32a1SGerd Hoffmann         str = "in";
624f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_IN;
625f1ae32a1SGerd Hoffmann         break;
626f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_OUT:
627f1ae32a1SGerd Hoffmann         str = "out";
628f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_OUT;
629f1ae32a1SGerd Hoffmann         break;
630f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_SETUP:
631f1ae32a1SGerd Hoffmann         str = "setup";
632f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_SETUP;
633f1ae32a1SGerd Hoffmann         break;
634f1ae32a1SGerd Hoffmann     default:
635dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_bad_direction(dir);
636f1ae32a1SGerd Hoffmann         return 1;
637f1ae32a1SGerd Hoffmann     }
638f1ae32a1SGerd Hoffmann 
639f1ae32a1SGerd Hoffmann     if (!iso_td.bp || !iso_td.be) {
640dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_bad_bp_be(iso_td.bp, iso_td.be);
641f1ae32a1SGerd Hoffmann         return 1;
642f1ae32a1SGerd Hoffmann     }
643f1ae32a1SGerd Hoffmann 
644f1ae32a1SGerd Hoffmann     start_offset = iso_td.offset[relative_frame_number];
6451328fe0cSPrasad J Pandit     if (relative_frame_number < frame_count) {
646f1ae32a1SGerd Hoffmann         next_offset = iso_td.offset[relative_frame_number + 1];
6471328fe0cSPrasad J Pandit     } else {
6481328fe0cSPrasad J Pandit         next_offset = iso_td.be;
6491328fe0cSPrasad J Pandit     }
650f1ae32a1SGerd Hoffmann 
651f1ae32a1SGerd Hoffmann     if (!(OHCI_BM(start_offset, TD_PSW_CC) & 0xe) ||
652f1ae32a1SGerd Hoffmann         ((relative_frame_number < frame_count) &&
653f1ae32a1SGerd Hoffmann          !(OHCI_BM(next_offset, TD_PSW_CC) & 0xe))) {
654dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_bad_cc_not_accessed(start_offset, next_offset);
655f1ae32a1SGerd Hoffmann         return 1;
656f1ae32a1SGerd Hoffmann     }
657f1ae32a1SGerd Hoffmann 
658f1ae32a1SGerd Hoffmann     if ((relative_frame_number < frame_count) && (start_offset > next_offset)) {
659dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_bad_cc_overrun(start_offset, next_offset);
660f1ae32a1SGerd Hoffmann         return 1;
661f1ae32a1SGerd Hoffmann     }
662f1ae32a1SGerd Hoffmann 
663f1ae32a1SGerd Hoffmann     if ((start_offset & 0x1000) == 0) {
664f1ae32a1SGerd Hoffmann         start_addr = (iso_td.bp & OHCI_PAGE_MASK) |
665f1ae32a1SGerd Hoffmann             (start_offset & OHCI_OFFSET_MASK);
666f1ae32a1SGerd Hoffmann     } else {
667f1ae32a1SGerd Hoffmann         start_addr = (iso_td.be & OHCI_PAGE_MASK) |
668f1ae32a1SGerd Hoffmann             (start_offset & OHCI_OFFSET_MASK);
669f1ae32a1SGerd Hoffmann     }
670f1ae32a1SGerd Hoffmann 
671f1ae32a1SGerd Hoffmann     if (relative_frame_number < frame_count) {
672f1ae32a1SGerd Hoffmann         end_offset = next_offset - 1;
673f1ae32a1SGerd Hoffmann         if ((end_offset & 0x1000) == 0) {
674f1ae32a1SGerd Hoffmann             end_addr = (iso_td.bp & OHCI_PAGE_MASK) |
675f1ae32a1SGerd Hoffmann                 (end_offset & OHCI_OFFSET_MASK);
676f1ae32a1SGerd Hoffmann         } else {
677f1ae32a1SGerd Hoffmann             end_addr = (iso_td.be & OHCI_PAGE_MASK) |
678f1ae32a1SGerd Hoffmann                 (end_offset & OHCI_OFFSET_MASK);
679f1ae32a1SGerd Hoffmann         }
680f1ae32a1SGerd Hoffmann     } else {
681f1ae32a1SGerd Hoffmann         /* Last packet in the ISO TD */
6821328fe0cSPrasad J Pandit         end_addr = next_offset;
6831328fe0cSPrasad J Pandit     }
6841328fe0cSPrasad J Pandit 
6851328fe0cSPrasad J Pandit     if (start_addr > end_addr) {
6861328fe0cSPrasad J Pandit         trace_usb_ohci_iso_td_bad_cc_overrun(start_addr, end_addr);
6871328fe0cSPrasad J Pandit         return 1;
688f1ae32a1SGerd Hoffmann     }
689f1ae32a1SGerd Hoffmann 
690f1ae32a1SGerd Hoffmann     if ((start_addr & OHCI_PAGE_MASK) != (end_addr & OHCI_PAGE_MASK)) {
691f1ae32a1SGerd Hoffmann         len = (end_addr & OHCI_OFFSET_MASK) + 0x1001
692f1ae32a1SGerd Hoffmann             - (start_addr & OHCI_OFFSET_MASK);
693f1ae32a1SGerd Hoffmann     } else {
694f1ae32a1SGerd Hoffmann         len = end_addr - start_addr + 1;
695f1ae32a1SGerd Hoffmann     }
6961328fe0cSPrasad J Pandit     if (len > sizeof(ohci->usb_buf)) {
6971328fe0cSPrasad J Pandit         len = sizeof(ohci->usb_buf);
6981328fe0cSPrasad J Pandit     }
699f1ae32a1SGerd Hoffmann 
700f1ae32a1SGerd Hoffmann     if (len && dir != OHCI_TD_DIR_IN) {
701cf66ee8eSAlexey Kardashevskiy         if (ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, len,
702cf66ee8eSAlexey Kardashevskiy                              DMA_DIRECTION_TO_DEVICE)) {
703cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
704cf66ee8eSAlexey Kardashevskiy             return 1;
705cf66ee8eSAlexey Kardashevskiy         }
706f1ae32a1SGerd Hoffmann     }
707f1ae32a1SGerd Hoffmann 
7089a77a0f5SHans de Goede     if (!completion) {
709a6fb2ddbSHans de Goede         bool int_req = relative_frame_number == frame_count &&
710a6fb2ddbSHans de Goede                        OHCI_BM(iso_td.flags, TD_DI) == 0;
711f1ae32a1SGerd Hoffmann         dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
71242340fc3SLiam Merwick         if (dev == NULL) {
71342340fc3SLiam Merwick             trace_usb_ohci_td_dev_error();
71442340fc3SLiam Merwick             return 1;
71542340fc3SLiam Merwick         }
716f1ae32a1SGerd Hoffmann         ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
7178550a02dSGerd Hoffmann         usb_packet_setup(&ohci->usb_packet, pid, ep, 0, addr, false, int_req);
718f1ae32a1SGerd Hoffmann         usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len);
7199a77a0f5SHans de Goede         usb_handle_packet(dev, &ohci->usb_packet);
7209a77a0f5SHans de Goede         if (ohci->usb_packet.status == USB_RET_ASYNC) {
72136dfe324SHans de Goede             usb_device_flush_ep_queue(dev, ep);
722f1ae32a1SGerd Hoffmann             return 1;
723f1ae32a1SGerd Hoffmann         }
724f1ae32a1SGerd Hoffmann     }
7259a77a0f5SHans de Goede     if (ohci->usb_packet.status == USB_RET_SUCCESS) {
7269a77a0f5SHans de Goede         ret = ohci->usb_packet.actual_length;
7279a77a0f5SHans de Goede     } else {
7289a77a0f5SHans de Goede         ret = ohci->usb_packet.status;
7299a77a0f5SHans de Goede     }
730f1ae32a1SGerd Hoffmann 
731dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_iso_td_so(start_offset, end_offset, start_addr, end_addr,
732dc1f5988SAlexey Kardashevskiy                              str, len, ret);
733f1ae32a1SGerd Hoffmann 
734f1ae32a1SGerd Hoffmann     /* Writeback */
735f1ae32a1SGerd Hoffmann     if (dir == OHCI_TD_DIR_IN && ret >= 0 && ret <= len) {
736f1ae32a1SGerd Hoffmann         /* IN transfer succeeded */
737cf66ee8eSAlexey Kardashevskiy         if (ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, ret,
738cf66ee8eSAlexey Kardashevskiy                              DMA_DIRECTION_FROM_DEVICE)) {
739cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
740cf66ee8eSAlexey Kardashevskiy             return 1;
741cf66ee8eSAlexey Kardashevskiy         }
742f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
743f1ae32a1SGerd Hoffmann                     OHCI_CC_NOERROR);
744f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, ret);
745f1ae32a1SGerd Hoffmann     } else if (dir == OHCI_TD_DIR_OUT && ret == len) {
746f1ae32a1SGerd Hoffmann         /* OUT transfer succeeded */
747f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
748f1ae32a1SGerd Hoffmann                     OHCI_CC_NOERROR);
749f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 0);
750f1ae32a1SGerd Hoffmann     } else {
751f1ae32a1SGerd Hoffmann         if (ret > (ssize_t) len) {
752dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_iso_td_data_overrun(ret, len);
753f1ae32a1SGerd Hoffmann             OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
754f1ae32a1SGerd Hoffmann                         OHCI_CC_DATAOVERRUN);
755f1ae32a1SGerd Hoffmann             OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
756f1ae32a1SGerd Hoffmann                         len);
757f1ae32a1SGerd Hoffmann         } else if (ret >= 0) {
758dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_iso_td_data_underrun(ret);
759f1ae32a1SGerd Hoffmann             OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
760f1ae32a1SGerd Hoffmann                         OHCI_CC_DATAUNDERRUN);
761f1ae32a1SGerd Hoffmann         } else {
762f1ae32a1SGerd Hoffmann             switch (ret) {
763f1ae32a1SGerd Hoffmann             case USB_RET_IOERROR:
764f1ae32a1SGerd Hoffmann             case USB_RET_NODEV:
765f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
766f1ae32a1SGerd Hoffmann                             OHCI_CC_DEVICENOTRESPONDING);
767f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
768f1ae32a1SGerd Hoffmann                             0);
769f1ae32a1SGerd Hoffmann                 break;
770f1ae32a1SGerd Hoffmann             case USB_RET_NAK:
771f1ae32a1SGerd Hoffmann             case USB_RET_STALL:
772dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_iso_td_nak(ret);
773f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
774f1ae32a1SGerd Hoffmann                             OHCI_CC_STALL);
775f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
776f1ae32a1SGerd Hoffmann                             0);
777f1ae32a1SGerd Hoffmann                 break;
778f1ae32a1SGerd Hoffmann             default:
779dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_iso_td_bad_response(ret);
780f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
781f1ae32a1SGerd Hoffmann                             OHCI_CC_UNDEXPETEDPID);
782f1ae32a1SGerd Hoffmann                 break;
783f1ae32a1SGerd Hoffmann             }
784f1ae32a1SGerd Hoffmann         }
785f1ae32a1SGerd Hoffmann     }
786f1ae32a1SGerd Hoffmann 
787f1ae32a1SGerd Hoffmann     if (relative_frame_number == frame_count) {
788f1ae32a1SGerd Hoffmann         /* Last data packet of ISO TD - retire the TD to the Done Queue */
789f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_NOERROR);
790f1ae32a1SGerd Hoffmann         ed->head &= ~OHCI_DPTR_MASK;
791f1ae32a1SGerd Hoffmann         ed->head |= (iso_td.next & OHCI_DPTR_MASK);
792f1ae32a1SGerd Hoffmann         iso_td.next = ohci->done;
793f1ae32a1SGerd Hoffmann         ohci->done = addr;
794f1ae32a1SGerd Hoffmann         i = OHCI_BM(iso_td.flags, TD_DI);
795f1ae32a1SGerd Hoffmann         if (i < ohci->done_count)
796f1ae32a1SGerd Hoffmann             ohci->done_count = i;
797f1ae32a1SGerd Hoffmann     }
798cf66ee8eSAlexey Kardashevskiy     if (ohci_put_iso_td(ohci, addr, &iso_td)) {
799cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
800cf66ee8eSAlexey Kardashevskiy     }
801f1ae32a1SGerd Hoffmann     return 1;
802f1ae32a1SGerd Hoffmann }
803f1ae32a1SGerd Hoffmann 
804dc1f5988SAlexey Kardashevskiy static void ohci_td_pkt(const char *msg, const uint8_t *buf, size_t len)
805dc1f5988SAlexey Kardashevskiy {
806d87aa138SStefan Hajnoczi     bool print16;
807d87aa138SStefan Hajnoczi     bool printall;
808dc1f5988SAlexey Kardashevskiy     const int width = 16;
809dc1f5988SAlexey Kardashevskiy     int i;
810dc1f5988SAlexey Kardashevskiy     char tmp[3 * width + 1];
811dc1f5988SAlexey Kardashevskiy     char *p = tmp;
812dc1f5988SAlexey Kardashevskiy 
813d87aa138SStefan Hajnoczi     print16 = !!trace_event_get_state_backends(TRACE_USB_OHCI_TD_PKT_SHORT);
814d87aa138SStefan Hajnoczi     printall = !!trace_event_get_state_backends(TRACE_USB_OHCI_TD_PKT_FULL);
815d87aa138SStefan Hajnoczi 
816dc1f5988SAlexey Kardashevskiy     if (!printall && !print16) {
817dc1f5988SAlexey Kardashevskiy         return;
818dc1f5988SAlexey Kardashevskiy     }
819dc1f5988SAlexey Kardashevskiy 
820dc1f5988SAlexey Kardashevskiy     for (i = 0; ; i++) {
821dc1f5988SAlexey Kardashevskiy         if (i && (!(i % width) || (i == len))) {
822dc1f5988SAlexey Kardashevskiy             if (!printall) {
823dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_pkt_short(msg, tmp);
824dc1f5988SAlexey Kardashevskiy                 break;
825dc1f5988SAlexey Kardashevskiy             }
826dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_td_pkt_full(msg, tmp);
827dc1f5988SAlexey Kardashevskiy             p = tmp;
828dc1f5988SAlexey Kardashevskiy             *p = 0;
829dc1f5988SAlexey Kardashevskiy         }
830dc1f5988SAlexey Kardashevskiy         if (i == len) {
831dc1f5988SAlexey Kardashevskiy             break;
832dc1f5988SAlexey Kardashevskiy         }
833dc1f5988SAlexey Kardashevskiy 
834dc1f5988SAlexey Kardashevskiy         p += sprintf(p, " %.2x", buf[i]);
835dc1f5988SAlexey Kardashevskiy     }
836dc1f5988SAlexey Kardashevskiy }
837dc1f5988SAlexey Kardashevskiy 
838f1ae32a1SGerd Hoffmann /* Service a transport descriptor.
839f1ae32a1SGerd Hoffmann    Returns nonzero to terminate processing of this endpoint.  */
840f1ae32a1SGerd Hoffmann 
841f1ae32a1SGerd Hoffmann static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
842f1ae32a1SGerd Hoffmann {
843f1ae32a1SGerd Hoffmann     int dir;
844f1ae32a1SGerd Hoffmann     size_t len = 0, pktlen = 0;
845f1ae32a1SGerd Hoffmann     const char *str = NULL;
846f1ae32a1SGerd Hoffmann     int pid;
847f1ae32a1SGerd Hoffmann     int ret;
848f1ae32a1SGerd Hoffmann     int i;
849f1ae32a1SGerd Hoffmann     USBDevice *dev;
850f1ae32a1SGerd Hoffmann     USBEndpoint *ep;
851f1ae32a1SGerd Hoffmann     struct ohci_td td;
852f1ae32a1SGerd Hoffmann     uint32_t addr;
853f1ae32a1SGerd Hoffmann     int flag_r;
854f1ae32a1SGerd Hoffmann     int completion;
855f1ae32a1SGerd Hoffmann 
856f1ae32a1SGerd Hoffmann     addr = ed->head & OHCI_DPTR_MASK;
857f1ae32a1SGerd Hoffmann     /* See if this TD has already been submitted to the device.  */
858f1ae32a1SGerd Hoffmann     completion = (addr == ohci->async_td);
859f1ae32a1SGerd Hoffmann     if (completion && !ohci->async_complete) {
860dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_td_skip_async();
861f1ae32a1SGerd Hoffmann         return 1;
862f1ae32a1SGerd Hoffmann     }
863cf66ee8eSAlexey Kardashevskiy     if (ohci_read_td(ohci, addr, &td)) {
864dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_td_read_error(addr);
865cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
8666ebc069dSLi Qiang         return 1;
867f1ae32a1SGerd Hoffmann     }
868f1ae32a1SGerd Hoffmann 
869f1ae32a1SGerd Hoffmann     dir = OHCI_BM(ed->flags, ED_D);
870f1ae32a1SGerd Hoffmann     switch (dir) {
871f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_OUT:
872f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_IN:
873f1ae32a1SGerd Hoffmann         /* Same value.  */
874f1ae32a1SGerd Hoffmann         break;
875f1ae32a1SGerd Hoffmann     default:
876f1ae32a1SGerd Hoffmann         dir = OHCI_BM(td.flags, TD_DP);
877f1ae32a1SGerd Hoffmann         break;
878f1ae32a1SGerd Hoffmann     }
879f1ae32a1SGerd Hoffmann 
880f1ae32a1SGerd Hoffmann     switch (dir) {
881f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_IN:
882f1ae32a1SGerd Hoffmann         str = "in";
883f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_IN;
884f1ae32a1SGerd Hoffmann         break;
885f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_OUT:
886f1ae32a1SGerd Hoffmann         str = "out";
887f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_OUT;
888f1ae32a1SGerd Hoffmann         break;
889f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_SETUP:
890f1ae32a1SGerd Hoffmann         str = "setup";
891f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_SETUP;
892f1ae32a1SGerd Hoffmann         break;
893f1ae32a1SGerd Hoffmann     default:
894dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_td_bad_direction(dir);
895f1ae32a1SGerd Hoffmann         return 1;
896f1ae32a1SGerd Hoffmann     }
897f1ae32a1SGerd Hoffmann     if (td.cbp && td.be) {
898f1ae32a1SGerd Hoffmann         if ((td.cbp & 0xfffff000) != (td.be & 0xfffff000)) {
899f1ae32a1SGerd Hoffmann             len = (td.be & 0xfff) + 0x1001 - (td.cbp & 0xfff);
900f1ae32a1SGerd Hoffmann         } else {
9011328fe0cSPrasad J Pandit             if (td.cbp > td.be) {
9021328fe0cSPrasad J Pandit                 trace_usb_ohci_iso_td_bad_cc_overrun(td.cbp, td.be);
9031328fe0cSPrasad J Pandit                 ohci_die(ohci);
9041328fe0cSPrasad J Pandit                 return 1;
9051328fe0cSPrasad J Pandit             }
906f1ae32a1SGerd Hoffmann             len = (td.be - td.cbp) + 1;
907f1ae32a1SGerd Hoffmann         }
9081328fe0cSPrasad J Pandit         if (len > sizeof(ohci->usb_buf)) {
9091328fe0cSPrasad J Pandit             len = sizeof(ohci->usb_buf);
9101328fe0cSPrasad J Pandit         }
911f1ae32a1SGerd Hoffmann 
912f1ae32a1SGerd Hoffmann         pktlen = len;
913f1ae32a1SGerd Hoffmann         if (len && dir != OHCI_TD_DIR_IN) {
914f1ae32a1SGerd Hoffmann             /* The endpoint may not allow us to transfer it all now */
915f1ae32a1SGerd Hoffmann             pktlen = (ed->flags & OHCI_ED_MPS_MASK) >> OHCI_ED_MPS_SHIFT;
916f1ae32a1SGerd Hoffmann             if (pktlen > len) {
917f1ae32a1SGerd Hoffmann                 pktlen = len;
918f1ae32a1SGerd Hoffmann             }
919f1ae32a1SGerd Hoffmann             if (!completion) {
920cf66ee8eSAlexey Kardashevskiy                 if (ohci_copy_td(ohci, &td, ohci->usb_buf, pktlen,
921cf66ee8eSAlexey Kardashevskiy                                  DMA_DIRECTION_TO_DEVICE)) {
922cf66ee8eSAlexey Kardashevskiy                     ohci_die(ohci);
923cf66ee8eSAlexey Kardashevskiy                 }
924f1ae32a1SGerd Hoffmann             }
925f1ae32a1SGerd Hoffmann         }
926f1ae32a1SGerd Hoffmann     }
927f1ae32a1SGerd Hoffmann 
928f1ae32a1SGerd Hoffmann     flag_r = (td.flags & OHCI_TD_R) != 0;
929dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_td_pkt_hdr(addr, (int64_t)pktlen, (int64_t)len, str,
930dc1f5988SAlexey Kardashevskiy                               flag_r, td.cbp, td.be);
931dc1f5988SAlexey Kardashevskiy     ohci_td_pkt("OUT", ohci->usb_buf, pktlen);
932f1ae32a1SGerd Hoffmann 
933f1ae32a1SGerd Hoffmann     if (completion) {
934f1ae32a1SGerd Hoffmann         ohci->async_td = 0;
93569e25d26SAlexey Kardashevskiy         ohci->async_complete = false;
936f1ae32a1SGerd Hoffmann     } else {
937f1ae32a1SGerd Hoffmann         dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
93842340fc3SLiam Merwick         if (dev == NULL) {
93942340fc3SLiam Merwick             trace_usb_ohci_td_dev_error();
94042340fc3SLiam Merwick             return 1;
94142340fc3SLiam Merwick         }
942f1ae32a1SGerd Hoffmann         ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
9436e821e50SBALATON Zoltan         if (ohci->async_td) {
9446e821e50SBALATON Zoltan             /* ??? The hardware should allow one active packet per
9456e821e50SBALATON Zoltan                endpoint.  We only allow one active packet per controller.
9466e821e50SBALATON Zoltan                This should be sufficient as long as devices respond in a
9476e821e50SBALATON Zoltan                timely manner.
9486e821e50SBALATON Zoltan             */
9496e821e50SBALATON Zoltan             trace_usb_ohci_td_too_many_pending(ep->nr);
9506e821e50SBALATON Zoltan             return 1;
9516e821e50SBALATON Zoltan         }
9528550a02dSGerd Hoffmann         usb_packet_setup(&ohci->usb_packet, pid, ep, 0, addr, !flag_r,
953a6fb2ddbSHans de Goede                          OHCI_BM(td.flags, TD_DI) == 0);
954f1ae32a1SGerd Hoffmann         usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen);
9559a77a0f5SHans de Goede         usb_handle_packet(dev, &ohci->usb_packet);
956dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_td_packet_status(ohci->usb_packet.status);
957dc1f5988SAlexey Kardashevskiy 
9589a77a0f5SHans de Goede         if (ohci->usb_packet.status == USB_RET_ASYNC) {
95936dfe324SHans de Goede             usb_device_flush_ep_queue(dev, ep);
960f1ae32a1SGerd Hoffmann             ohci->async_td = addr;
961f1ae32a1SGerd Hoffmann             return 1;
962f1ae32a1SGerd Hoffmann         }
963f1ae32a1SGerd Hoffmann     }
9649a77a0f5SHans de Goede     if (ohci->usb_packet.status == USB_RET_SUCCESS) {
9659a77a0f5SHans de Goede         ret = ohci->usb_packet.actual_length;
9669a77a0f5SHans de Goede     } else {
9679a77a0f5SHans de Goede         ret = ohci->usb_packet.status;
9689a77a0f5SHans de Goede     }
9699a77a0f5SHans de Goede 
970f1ae32a1SGerd Hoffmann     if (ret >= 0) {
971f1ae32a1SGerd Hoffmann         if (dir == OHCI_TD_DIR_IN) {
972cf66ee8eSAlexey Kardashevskiy             if (ohci_copy_td(ohci, &td, ohci->usb_buf, ret,
973cf66ee8eSAlexey Kardashevskiy                              DMA_DIRECTION_FROM_DEVICE)) {
974cf66ee8eSAlexey Kardashevskiy                 ohci_die(ohci);
975cf66ee8eSAlexey Kardashevskiy             }
976dc1f5988SAlexey Kardashevskiy             ohci_td_pkt("IN", ohci->usb_buf, pktlen);
977f1ae32a1SGerd Hoffmann         } else {
978f1ae32a1SGerd Hoffmann             ret = pktlen;
979f1ae32a1SGerd Hoffmann         }
980f1ae32a1SGerd Hoffmann     }
981f1ae32a1SGerd Hoffmann 
982f1ae32a1SGerd Hoffmann     /* Writeback */
983f1ae32a1SGerd Hoffmann     if (ret == pktlen || (dir == OHCI_TD_DIR_IN && ret >= 0 && flag_r)) {
984f1ae32a1SGerd Hoffmann         /* Transmission succeeded.  */
985f1ae32a1SGerd Hoffmann         if (ret == len) {
986f1ae32a1SGerd Hoffmann             td.cbp = 0;
987f1ae32a1SGerd Hoffmann         } else {
988f1ae32a1SGerd Hoffmann             if ((td.cbp & 0xfff) + ret > 0xfff) {
989f1ae32a1SGerd Hoffmann                 td.cbp = (td.be & ~0xfff) + ((td.cbp + ret) & 0xfff);
990f1ae32a1SGerd Hoffmann             } else {
991f1ae32a1SGerd Hoffmann                 td.cbp += ret;
992f1ae32a1SGerd Hoffmann             }
993f1ae32a1SGerd Hoffmann         }
994f1ae32a1SGerd Hoffmann         td.flags |= OHCI_TD_T1;
995f1ae32a1SGerd Hoffmann         td.flags ^= OHCI_TD_T0;
996f1ae32a1SGerd Hoffmann         OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_NOERROR);
997f1ae32a1SGerd Hoffmann         OHCI_SET_BM(td.flags, TD_EC, 0);
998f1ae32a1SGerd Hoffmann 
999f1ae32a1SGerd Hoffmann         if ((dir != OHCI_TD_DIR_IN) && (ret != len)) {
1000f1ae32a1SGerd Hoffmann             /* Partial packet transfer: TD not ready to retire yet */
1001f1ae32a1SGerd Hoffmann             goto exit_no_retire;
1002f1ae32a1SGerd Hoffmann         }
1003f1ae32a1SGerd Hoffmann 
1004f1ae32a1SGerd Hoffmann         /* Setting ED_C is part of the TD retirement process */
1005f1ae32a1SGerd Hoffmann         ed->head &= ~OHCI_ED_C;
1006f1ae32a1SGerd Hoffmann         if (td.flags & OHCI_TD_T0)
1007f1ae32a1SGerd Hoffmann             ed->head |= OHCI_ED_C;
1008f1ae32a1SGerd Hoffmann     } else {
1009f1ae32a1SGerd Hoffmann         if (ret >= 0) {
1010dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_td_underrun();
1011f1ae32a1SGerd Hoffmann             OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAUNDERRUN);
1012f1ae32a1SGerd Hoffmann         } else {
1013f1ae32a1SGerd Hoffmann             switch (ret) {
1014f1ae32a1SGerd Hoffmann             case USB_RET_IOERROR:
1015f1ae32a1SGerd Hoffmann             case USB_RET_NODEV:
1016dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_dev_error();
1017f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DEVICENOTRESPONDING);
10184b351a0fSJán Veselý                 break;
1019f1ae32a1SGerd Hoffmann             case USB_RET_NAK:
1020dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_nak();
1021f1ae32a1SGerd Hoffmann                 return 1;
1022f1ae32a1SGerd Hoffmann             case USB_RET_STALL:
1023dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_stall();
1024f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_STALL);
1025f1ae32a1SGerd Hoffmann                 break;
1026f1ae32a1SGerd Hoffmann             case USB_RET_BABBLE:
1027dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_babble();
1028f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAOVERRUN);
1029f1ae32a1SGerd Hoffmann                 break;
1030f1ae32a1SGerd Hoffmann             default:
1031dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_bad_device_response(ret);
1032f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_UNDEXPETEDPID);
1033f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_EC, 3);
1034f1ae32a1SGerd Hoffmann                 break;
1035f1ae32a1SGerd Hoffmann             }
1036cba42d61SMichael Tokarev             /* An error occurred so we have to clear the interrupt counter. See
10377c48b95dSSebastian Bauer              * spec at 6.4.4 on page 104 */
10387c48b95dSSebastian Bauer             ohci->done_count = 0;
1039f1ae32a1SGerd Hoffmann         }
1040f1ae32a1SGerd Hoffmann         ed->head |= OHCI_ED_H;
1041f1ae32a1SGerd Hoffmann     }
1042f1ae32a1SGerd Hoffmann 
1043f1ae32a1SGerd Hoffmann     /* Retire this TD */
1044f1ae32a1SGerd Hoffmann     ed->head &= ~OHCI_DPTR_MASK;
1045f1ae32a1SGerd Hoffmann     ed->head |= td.next & OHCI_DPTR_MASK;
1046f1ae32a1SGerd Hoffmann     td.next = ohci->done;
1047f1ae32a1SGerd Hoffmann     ohci->done = addr;
1048f1ae32a1SGerd Hoffmann     i = OHCI_BM(td.flags, TD_DI);
1049f1ae32a1SGerd Hoffmann     if (i < ohci->done_count)
1050f1ae32a1SGerd Hoffmann         ohci->done_count = i;
1051f1ae32a1SGerd Hoffmann exit_no_retire:
1052cf66ee8eSAlexey Kardashevskiy     if (ohci_put_td(ohci, addr, &td)) {
1053cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
1054cf66ee8eSAlexey Kardashevskiy         return 1;
1055cf66ee8eSAlexey Kardashevskiy     }
1056f1ae32a1SGerd Hoffmann     return OHCI_BM(td.flags, TD_CC) != OHCI_CC_NOERROR;
1057f1ae32a1SGerd Hoffmann }
1058f1ae32a1SGerd Hoffmann 
1059f1ae32a1SGerd Hoffmann /* Service an endpoint list.  Returns nonzero if active TD were found.  */
1060f1ae32a1SGerd Hoffmann static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion)
1061f1ae32a1SGerd Hoffmann {
1062f1ae32a1SGerd Hoffmann     struct ohci_ed ed;
1063f1ae32a1SGerd Hoffmann     uint32_t next_ed;
1064f1ae32a1SGerd Hoffmann     uint32_t cur;
1065f1ae32a1SGerd Hoffmann     int active;
106695ed5693SLi Qiang     uint32_t link_cnt = 0;
1067f1ae32a1SGerd Hoffmann     active = 0;
1068f1ae32a1SGerd Hoffmann 
1069f1ae32a1SGerd Hoffmann     if (head == 0)
1070f1ae32a1SGerd Hoffmann         return 0;
1071f1ae32a1SGerd Hoffmann 
1072ab878998SLaurent Vivier     for (cur = head; cur && link_cnt++ < ED_LINK_LIMIT; cur = next_ed) {
1073cf66ee8eSAlexey Kardashevskiy         if (ohci_read_ed(ohci, cur, &ed)) {
1074dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_ed_read_error(cur);
1075cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
1076f1ae32a1SGerd Hoffmann             return 0;
1077f1ae32a1SGerd Hoffmann         }
1078f1ae32a1SGerd Hoffmann 
1079f1ae32a1SGerd Hoffmann         next_ed = ed.next & OHCI_DPTR_MASK;
1080f1ae32a1SGerd Hoffmann 
1081f1ae32a1SGerd Hoffmann         if ((ed.head & OHCI_ED_H) || (ed.flags & OHCI_ED_K)) {
1082f1ae32a1SGerd Hoffmann             uint32_t addr;
1083f1ae32a1SGerd Hoffmann             /* Cancel pending packets for ED that have been paused.  */
1084f1ae32a1SGerd Hoffmann             addr = ed.head & OHCI_DPTR_MASK;
1085f1ae32a1SGerd Hoffmann             if (ohci->async_td && addr == ohci->async_td) {
1086f1ae32a1SGerd Hoffmann                 usb_cancel_packet(&ohci->usb_packet);
1087f1ae32a1SGerd Hoffmann                 ohci->async_td = 0;
1088f79738b0SHans de Goede                 usb_device_ep_stopped(ohci->usb_packet.ep->dev,
1089f79738b0SHans de Goede                                       ohci->usb_packet.ep);
1090f1ae32a1SGerd Hoffmann             }
1091f1ae32a1SGerd Hoffmann             continue;
1092f1ae32a1SGerd Hoffmann         }
1093f1ae32a1SGerd Hoffmann 
1094f1ae32a1SGerd Hoffmann         while ((ed.head & OHCI_DPTR_MASK) != ed.tail) {
10953af8f177SAlexey Kardashevskiy             trace_usb_ohci_ed_pkt(cur, (ed.head & OHCI_ED_H) != 0,
10963af8f177SAlexey Kardashevskiy                     (ed.head & OHCI_ED_C) != 0, ed.head & OHCI_DPTR_MASK,
10973af8f177SAlexey Kardashevskiy                     ed.tail & OHCI_DPTR_MASK, ed.next & OHCI_DPTR_MASK);
10983af8f177SAlexey Kardashevskiy             trace_usb_ohci_ed_pkt_flags(
1099f1ae32a1SGerd Hoffmann                     OHCI_BM(ed.flags, ED_FA), OHCI_BM(ed.flags, ED_EN),
1100f1ae32a1SGerd Hoffmann                     OHCI_BM(ed.flags, ED_D), (ed.flags & OHCI_ED_S)!= 0,
1101f1ae32a1SGerd Hoffmann                     (ed.flags & OHCI_ED_K) != 0, (ed.flags & OHCI_ED_F) != 0,
11023af8f177SAlexey Kardashevskiy                     OHCI_BM(ed.flags, ED_MPS));
1103dc1f5988SAlexey Kardashevskiy 
1104f1ae32a1SGerd Hoffmann             active = 1;
1105f1ae32a1SGerd Hoffmann 
1106f1ae32a1SGerd Hoffmann             if ((ed.flags & OHCI_ED_F) == 0) {
1107f1ae32a1SGerd Hoffmann                 if (ohci_service_td(ohci, &ed))
1108f1ae32a1SGerd Hoffmann                     break;
1109f1ae32a1SGerd Hoffmann             } else {
1110f1ae32a1SGerd Hoffmann                 /* Handle isochronous endpoints */
1111f1ae32a1SGerd Hoffmann                 if (ohci_service_iso_td(ohci, &ed, completion))
1112f1ae32a1SGerd Hoffmann                     break;
1113f1ae32a1SGerd Hoffmann             }
1114f1ae32a1SGerd Hoffmann         }
1115f1ae32a1SGerd Hoffmann 
1116cf66ee8eSAlexey Kardashevskiy         if (ohci_put_ed(ohci, cur, &ed)) {
1117cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
1118cf66ee8eSAlexey Kardashevskiy             return 0;
1119cf66ee8eSAlexey Kardashevskiy         }
1120f1ae32a1SGerd Hoffmann     }
1121f1ae32a1SGerd Hoffmann 
1122f1ae32a1SGerd Hoffmann     return active;
1123f1ae32a1SGerd Hoffmann }
1124f1ae32a1SGerd Hoffmann 
1125fd0a10cdSLaurent Vivier /* set a timer for EOF */
1126fd0a10cdSLaurent Vivier static void ohci_eof_timer(OHCIState *ohci)
1127f1ae32a1SGerd Hoffmann {
1128bc72ad67SAlex Bligh     timer_mod(ohci->eof_timer, ohci->sof_time + usb_frame_time);
1129fd0a10cdSLaurent Vivier }
1130fd0a10cdSLaurent Vivier /* Set a timer for EOF and generate a SOF event */
1131fd0a10cdSLaurent Vivier static void ohci_sof(OHCIState *ohci)
1132fd0a10cdSLaurent Vivier {
1133a60f39a4SMiguel GAIO     ohci->sof_time += usb_frame_time;
1134fd0a10cdSLaurent Vivier     ohci_eof_timer(ohci);
1135f1ae32a1SGerd Hoffmann     ohci_set_interrupt(ohci, OHCI_INTR_SF);
1136f1ae32a1SGerd Hoffmann }
1137f1ae32a1SGerd Hoffmann 
1138f1ae32a1SGerd Hoffmann /* Process Control and Bulk lists.  */
1139f1ae32a1SGerd Hoffmann static void ohci_process_lists(OHCIState *ohci, int completion)
1140f1ae32a1SGerd Hoffmann {
1141f1ae32a1SGerd Hoffmann     if ((ohci->ctl & OHCI_CTL_CLE) && (ohci->status & OHCI_STATUS_CLF)) {
1142f1ae32a1SGerd Hoffmann         if (ohci->ctrl_cur && ohci->ctrl_cur != ohci->ctrl_head) {
1143dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_process_lists(ohci->ctrl_head, ohci->ctrl_cur);
1144f1ae32a1SGerd Hoffmann         }
1145f1ae32a1SGerd Hoffmann         if (!ohci_service_ed_list(ohci, ohci->ctrl_head, completion)) {
1146f1ae32a1SGerd Hoffmann             ohci->ctrl_cur = 0;
1147f1ae32a1SGerd Hoffmann             ohci->status &= ~OHCI_STATUS_CLF;
1148f1ae32a1SGerd Hoffmann         }
1149f1ae32a1SGerd Hoffmann     }
1150f1ae32a1SGerd Hoffmann 
1151f1ae32a1SGerd Hoffmann     if ((ohci->ctl & OHCI_CTL_BLE) && (ohci->status & OHCI_STATUS_BLF)) {
1152f1ae32a1SGerd Hoffmann         if (!ohci_service_ed_list(ohci, ohci->bulk_head, completion)) {
1153f1ae32a1SGerd Hoffmann             ohci->bulk_cur = 0;
1154f1ae32a1SGerd Hoffmann             ohci->status &= ~OHCI_STATUS_BLF;
1155f1ae32a1SGerd Hoffmann         }
1156f1ae32a1SGerd Hoffmann     }
1157f1ae32a1SGerd Hoffmann }
1158f1ae32a1SGerd Hoffmann 
1159f1ae32a1SGerd Hoffmann /* Do frame processing on frame boundary */
1160f1ae32a1SGerd Hoffmann static void ohci_frame_boundary(void *opaque)
1161f1ae32a1SGerd Hoffmann {
1162f1ae32a1SGerd Hoffmann     OHCIState *ohci = opaque;
1163f1ae32a1SGerd Hoffmann     struct ohci_hcca hcca;
1164f1ae32a1SGerd Hoffmann 
1165cf66ee8eSAlexey Kardashevskiy     if (ohci_read_hcca(ohci, ohci->hcca, &hcca)) {
1166dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_hcca_read_error(ohci->hcca);
1167cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
1168cf66ee8eSAlexey Kardashevskiy         return;
1169cf66ee8eSAlexey Kardashevskiy     }
1170f1ae32a1SGerd Hoffmann 
1171f1ae32a1SGerd Hoffmann     /* Process all the lists at the end of the frame */
1172f1ae32a1SGerd Hoffmann     if (ohci->ctl & OHCI_CTL_PLE) {
1173f1ae32a1SGerd Hoffmann         int n;
1174f1ae32a1SGerd Hoffmann 
1175f1ae32a1SGerd Hoffmann         n = ohci->frame_number & 0x1f;
1176f1ae32a1SGerd Hoffmann         ohci_service_ed_list(ohci, le32_to_cpu(hcca.intr[n]), 0);
1177f1ae32a1SGerd Hoffmann     }
1178f1ae32a1SGerd Hoffmann 
1179f1ae32a1SGerd Hoffmann     /* Cancel all pending packets if either of the lists has been disabled.  */
1180f79738b0SHans de Goede     if (ohci->old_ctl & (~ohci->ctl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) {
1181f79738b0SHans de Goede         ohci_stop_endpoints(ohci);
1182f79738b0SHans de Goede     }
1183f1ae32a1SGerd Hoffmann     ohci->old_ctl = ohci->ctl;
1184f1ae32a1SGerd Hoffmann     ohci_process_lists(ohci, 0);
1185f1ae32a1SGerd Hoffmann 
1186cf66ee8eSAlexey Kardashevskiy     /* Stop if UnrecoverableError happened or ohci_sof will crash */
1187cf66ee8eSAlexey Kardashevskiy     if (ohci->intr_status & OHCI_INTR_UE) {
1188cf66ee8eSAlexey Kardashevskiy         return;
1189cf66ee8eSAlexey Kardashevskiy     }
1190cf66ee8eSAlexey Kardashevskiy 
1191f1ae32a1SGerd Hoffmann     /* Frame boundary, so do EOF stuf here */
1192f1ae32a1SGerd Hoffmann     ohci->frt = ohci->fit;
1193f1ae32a1SGerd Hoffmann 
1194f1ae32a1SGerd Hoffmann     /* Increment frame number and take care of endianness. */
1195f1ae32a1SGerd Hoffmann     ohci->frame_number = (ohci->frame_number + 1) & 0xffff;
1196f1ae32a1SGerd Hoffmann     hcca.frame = cpu_to_le16(ohci->frame_number);
1197f1ae32a1SGerd Hoffmann 
1198f1ae32a1SGerd Hoffmann     if (ohci->done_count == 0 && !(ohci->intr_status & OHCI_INTR_WD)) {
1199f1ae32a1SGerd Hoffmann         if (!ohci->done)
1200f1ae32a1SGerd Hoffmann             abort();
1201f1ae32a1SGerd Hoffmann         if (ohci->intr & ohci->intr_status)
1202f1ae32a1SGerd Hoffmann             ohci->done |= 1;
1203f1ae32a1SGerd Hoffmann         hcca.done = cpu_to_le32(ohci->done);
1204f1ae32a1SGerd Hoffmann         ohci->done = 0;
1205f1ae32a1SGerd Hoffmann         ohci->done_count = 7;
1206f1ae32a1SGerd Hoffmann         ohci_set_interrupt(ohci, OHCI_INTR_WD);
1207f1ae32a1SGerd Hoffmann     }
1208f1ae32a1SGerd Hoffmann 
1209f1ae32a1SGerd Hoffmann     if (ohci->done_count != 7 && ohci->done_count != 0)
1210f1ae32a1SGerd Hoffmann         ohci->done_count--;
1211f1ae32a1SGerd Hoffmann 
1212f1ae32a1SGerd Hoffmann     /* Do SOF stuff here */
1213f1ae32a1SGerd Hoffmann     ohci_sof(ohci);
1214f1ae32a1SGerd Hoffmann 
1215f1ae32a1SGerd Hoffmann     /* Writeback HCCA */
1216cf66ee8eSAlexey Kardashevskiy     if (ohci_put_hcca(ohci, ohci->hcca, &hcca)) {
1217cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
1218cf66ee8eSAlexey Kardashevskiy     }
1219f1ae32a1SGerd Hoffmann }
1220f1ae32a1SGerd Hoffmann 
1221f1ae32a1SGerd Hoffmann /* Start sending SOF tokens across the USB bus, lists are processed in
1222f1ae32a1SGerd Hoffmann  * next frame
1223f1ae32a1SGerd Hoffmann  */
1224f1ae32a1SGerd Hoffmann static int ohci_bus_start(OHCIState *ohci)
1225f1ae32a1SGerd Hoffmann {
1226dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_start(ohci->name);
1227f1ae32a1SGerd Hoffmann 
1228fd0a10cdSLaurent Vivier     /* Delay the first SOF event by one frame time as
1229fd0a10cdSLaurent Vivier      * linux driver is not ready to receive it and
1230fd0a10cdSLaurent Vivier      * can meet some race conditions
1231fd0a10cdSLaurent Vivier      */
1232fd0a10cdSLaurent Vivier 
1233a60f39a4SMiguel GAIO     ohci->sof_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
1234fd0a10cdSLaurent Vivier     ohci_eof_timer(ohci);
1235f1ae32a1SGerd Hoffmann 
1236f1ae32a1SGerd Hoffmann     return 1;
1237f1ae32a1SGerd Hoffmann }
1238f1ae32a1SGerd Hoffmann 
1239f1ae32a1SGerd Hoffmann /* Stop sending SOF tokens on the bus */
124034d97308SThomas Huth void ohci_bus_stop(OHCIState *ohci)
1241f1ae32a1SGerd Hoffmann {
1242dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_stop(ohci->name);
1243bc72ad67SAlex Bligh     timer_del(ohci->eof_timer);
1244f1ae32a1SGerd Hoffmann }
1245f1ae32a1SGerd Hoffmann 
1246f1ae32a1SGerd Hoffmann /* Sets a flag in a port status register but only set it if the port is
1247f1ae32a1SGerd Hoffmann  * connected, if not set ConnectStatusChange flag. If flag is enabled
1248f1ae32a1SGerd Hoffmann  * return 1.
1249f1ae32a1SGerd Hoffmann  */
1250f1ae32a1SGerd Hoffmann static int ohci_port_set_if_connected(OHCIState *ohci, int i, uint32_t val)
1251f1ae32a1SGerd Hoffmann {
1252f1ae32a1SGerd Hoffmann     int ret = 1;
1253f1ae32a1SGerd Hoffmann 
1254f1ae32a1SGerd Hoffmann     /* writing a 0 has no effect */
1255f1ae32a1SGerd Hoffmann     if (val == 0)
1256f1ae32a1SGerd Hoffmann         return 0;
1257f1ae32a1SGerd Hoffmann 
1258f1ae32a1SGerd Hoffmann     /* If CurrentConnectStatus is cleared we set
1259f1ae32a1SGerd Hoffmann      * ConnectStatusChange
1260f1ae32a1SGerd Hoffmann      */
1261f1ae32a1SGerd Hoffmann     if (!(ohci->rhport[i].ctrl & OHCI_PORT_CCS)) {
1262f1ae32a1SGerd Hoffmann         ohci->rhport[i].ctrl |= OHCI_PORT_CSC;
1263f1ae32a1SGerd Hoffmann         if (ohci->rhstatus & OHCI_RHS_DRWE) {
1264f1ae32a1SGerd Hoffmann             /* TODO: CSC is a wakeup event */
1265f1ae32a1SGerd Hoffmann         }
1266f1ae32a1SGerd Hoffmann         return 0;
1267f1ae32a1SGerd Hoffmann     }
1268f1ae32a1SGerd Hoffmann 
1269f1ae32a1SGerd Hoffmann     if (ohci->rhport[i].ctrl & val)
1270f1ae32a1SGerd Hoffmann         ret = 0;
1271f1ae32a1SGerd Hoffmann 
1272f1ae32a1SGerd Hoffmann     /* set the bit */
1273f1ae32a1SGerd Hoffmann     ohci->rhport[i].ctrl |= val;
1274f1ae32a1SGerd Hoffmann 
1275f1ae32a1SGerd Hoffmann     return ret;
1276f1ae32a1SGerd Hoffmann }
1277f1ae32a1SGerd Hoffmann 
1278f1ae32a1SGerd Hoffmann /* Set the frame interval - frame interval toggle is manipulated by the hcd only */
1279f1ae32a1SGerd Hoffmann static void ohci_set_frame_interval(OHCIState *ohci, uint16_t val)
1280f1ae32a1SGerd Hoffmann {
1281f1ae32a1SGerd Hoffmann     val &= OHCI_FMI_FI;
1282f1ae32a1SGerd Hoffmann 
1283f1ae32a1SGerd Hoffmann     if (val != ohci->fi) {
1284dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_set_frame_interval(ohci->name, ohci->fi, ohci->fi);
1285f1ae32a1SGerd Hoffmann     }
1286f1ae32a1SGerd Hoffmann 
1287f1ae32a1SGerd Hoffmann     ohci->fi = val;
1288f1ae32a1SGerd Hoffmann }
1289f1ae32a1SGerd Hoffmann 
1290f1ae32a1SGerd Hoffmann static void ohci_port_power(OHCIState *ohci, int i, int p)
1291f1ae32a1SGerd Hoffmann {
1292f1ae32a1SGerd Hoffmann     if (p) {
1293f1ae32a1SGerd Hoffmann         ohci->rhport[i].ctrl |= OHCI_PORT_PPS;
1294f1ae32a1SGerd Hoffmann     } else {
1295f1ae32a1SGerd Hoffmann         ohci->rhport[i].ctrl &= ~(OHCI_PORT_PPS|
1296f1ae32a1SGerd Hoffmann                     OHCI_PORT_CCS|
1297f1ae32a1SGerd Hoffmann                     OHCI_PORT_PSS|
1298f1ae32a1SGerd Hoffmann                     OHCI_PORT_PRS);
1299f1ae32a1SGerd Hoffmann     }
1300f1ae32a1SGerd Hoffmann }
1301f1ae32a1SGerd Hoffmann 
1302f1ae32a1SGerd Hoffmann /* Set HcControlRegister */
1303f1ae32a1SGerd Hoffmann static void ohci_set_ctl(OHCIState *ohci, uint32_t val)
1304f1ae32a1SGerd Hoffmann {
1305f1ae32a1SGerd Hoffmann     uint32_t old_state;
1306f1ae32a1SGerd Hoffmann     uint32_t new_state;
1307f1ae32a1SGerd Hoffmann 
1308f1ae32a1SGerd Hoffmann     old_state = ohci->ctl & OHCI_CTL_HCFS;
1309f1ae32a1SGerd Hoffmann     ohci->ctl = val;
1310f1ae32a1SGerd Hoffmann     new_state = ohci->ctl & OHCI_CTL_HCFS;
1311f1ae32a1SGerd Hoffmann 
1312f1ae32a1SGerd Hoffmann     /* no state change */
1313f1ae32a1SGerd Hoffmann     if (old_state == new_state)
1314f1ae32a1SGerd Hoffmann         return;
1315f1ae32a1SGerd Hoffmann 
1316dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_set_ctl(ohci->name, new_state);
1317f1ae32a1SGerd Hoffmann     switch (new_state) {
1318f1ae32a1SGerd Hoffmann     case OHCI_USB_OPERATIONAL:
1319f1ae32a1SGerd Hoffmann         ohci_bus_start(ohci);
1320f1ae32a1SGerd Hoffmann         break;
1321f1ae32a1SGerd Hoffmann     case OHCI_USB_SUSPEND:
1322f1ae32a1SGerd Hoffmann         ohci_bus_stop(ohci);
1323087462c7SLaurent Vivier         /* clear pending SF otherwise linux driver loops in ohci_irq() */
1324087462c7SLaurent Vivier         ohci->intr_status &= ~OHCI_INTR_SF;
1325087462c7SLaurent Vivier         ohci_intr_update(ohci);
1326f1ae32a1SGerd Hoffmann         break;
1327f1ae32a1SGerd Hoffmann     case OHCI_USB_RESUME:
1328dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_resume(ohci->name);
1329f1ae32a1SGerd Hoffmann         break;
1330f1ae32a1SGerd Hoffmann     case OHCI_USB_RESET:
13317d938fd1SHervé Poussineau         ohci_roothub_reset(ohci);
1332f1ae32a1SGerd Hoffmann         break;
1333f1ae32a1SGerd Hoffmann     }
1334f1ae32a1SGerd Hoffmann }
1335f1ae32a1SGerd Hoffmann 
1336f1ae32a1SGerd Hoffmann static uint32_t ohci_get_frame_remaining(OHCIState *ohci)
1337f1ae32a1SGerd Hoffmann {
1338f1ae32a1SGerd Hoffmann     uint16_t fr;
1339f1ae32a1SGerd Hoffmann     int64_t tks;
1340f1ae32a1SGerd Hoffmann 
1341f1ae32a1SGerd Hoffmann     if ((ohci->ctl & OHCI_CTL_HCFS) != OHCI_USB_OPERATIONAL)
1342f1ae32a1SGerd Hoffmann         return (ohci->frt << 31);
1343f1ae32a1SGerd Hoffmann 
1344f1ae32a1SGerd Hoffmann     /* Being in USB operational state guarnatees sof_time was
1345f1ae32a1SGerd Hoffmann      * set already.
1346f1ae32a1SGerd Hoffmann      */
1347bc72ad67SAlex Bligh     tks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - ohci->sof_time;
1348a60f39a4SMiguel GAIO     if (tks < 0) {
1349a60f39a4SMiguel GAIO         tks = 0;
1350a60f39a4SMiguel GAIO     }
1351f1ae32a1SGerd Hoffmann 
1352f1ae32a1SGerd Hoffmann     /* avoid muldiv if possible */
1353f1ae32a1SGerd Hoffmann     if (tks >= usb_frame_time)
1354f1ae32a1SGerd Hoffmann         return (ohci->frt << 31);
1355f1ae32a1SGerd Hoffmann 
1356cd1f16f9SLaurent Vivier     tks = tks / usb_bit_time;
1357f1ae32a1SGerd Hoffmann     fr = (uint16_t)(ohci->fi - tks);
1358f1ae32a1SGerd Hoffmann 
1359f1ae32a1SGerd Hoffmann     return (ohci->frt << 31) | fr;
1360f1ae32a1SGerd Hoffmann }
1361f1ae32a1SGerd Hoffmann 
1362f1ae32a1SGerd Hoffmann 
1363f1ae32a1SGerd Hoffmann /* Set root hub status */
1364f1ae32a1SGerd Hoffmann static void ohci_set_hub_status(OHCIState *ohci, uint32_t val)
1365f1ae32a1SGerd Hoffmann {
1366f1ae32a1SGerd Hoffmann     uint32_t old_state;
1367f1ae32a1SGerd Hoffmann 
1368f1ae32a1SGerd Hoffmann     old_state = ohci->rhstatus;
1369f1ae32a1SGerd Hoffmann 
1370f1ae32a1SGerd Hoffmann     /* write 1 to clear OCIC */
1371f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_OCIC)
1372f1ae32a1SGerd Hoffmann         ohci->rhstatus &= ~OHCI_RHS_OCIC;
1373f1ae32a1SGerd Hoffmann 
1374f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_LPS) {
1375f1ae32a1SGerd Hoffmann         int i;
1376f1ae32a1SGerd Hoffmann 
1377f1ae32a1SGerd Hoffmann         for (i = 0; i < ohci->num_ports; i++)
1378f1ae32a1SGerd Hoffmann             ohci_port_power(ohci, i, 0);
1379dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_hub_power_down();
1380f1ae32a1SGerd Hoffmann     }
1381f1ae32a1SGerd Hoffmann 
1382f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_LPSC) {
1383f1ae32a1SGerd Hoffmann         int i;
1384f1ae32a1SGerd Hoffmann 
1385f1ae32a1SGerd Hoffmann         for (i = 0; i < ohci->num_ports; i++)
1386f1ae32a1SGerd Hoffmann             ohci_port_power(ohci, i, 1);
1387dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_hub_power_up();
1388f1ae32a1SGerd Hoffmann     }
1389f1ae32a1SGerd Hoffmann 
1390f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_DRWE)
1391f1ae32a1SGerd Hoffmann         ohci->rhstatus |= OHCI_RHS_DRWE;
1392f1ae32a1SGerd Hoffmann 
1393f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_CRWE)
1394f1ae32a1SGerd Hoffmann         ohci->rhstatus &= ~OHCI_RHS_DRWE;
1395f1ae32a1SGerd Hoffmann 
1396f1ae32a1SGerd Hoffmann     if (old_state != ohci->rhstatus)
1397f1ae32a1SGerd Hoffmann         ohci_set_interrupt(ohci, OHCI_INTR_RHSC);
1398f1ae32a1SGerd Hoffmann }
1399f1ae32a1SGerd Hoffmann 
1400f1ae32a1SGerd Hoffmann /* Set root hub port status */
1401f1ae32a1SGerd Hoffmann static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val)
1402f1ae32a1SGerd Hoffmann {
1403f1ae32a1SGerd Hoffmann     uint32_t old_state;
1404f1ae32a1SGerd Hoffmann     OHCIPort *port;
1405f1ae32a1SGerd Hoffmann 
1406f1ae32a1SGerd Hoffmann     port = &ohci->rhport[portnum];
1407f1ae32a1SGerd Hoffmann     old_state = port->ctrl;
1408f1ae32a1SGerd Hoffmann 
1409f1ae32a1SGerd Hoffmann     /* Write to clear CSC, PESC, PSSC, OCIC, PRSC */
1410f1ae32a1SGerd Hoffmann     if (val & OHCI_PORT_WTC)
1411f1ae32a1SGerd Hoffmann         port->ctrl &= ~(val & OHCI_PORT_WTC);
1412f1ae32a1SGerd Hoffmann 
1413f1ae32a1SGerd Hoffmann     if (val & OHCI_PORT_CCS)
1414f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_PES;
1415f1ae32a1SGerd Hoffmann 
1416f1ae32a1SGerd Hoffmann     ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PES);
1417f1ae32a1SGerd Hoffmann 
1418f1ae32a1SGerd Hoffmann     if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PSS)) {
1419dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_port_suspend(portnum);
1420f1ae32a1SGerd Hoffmann     }
1421f1ae32a1SGerd Hoffmann 
1422f1ae32a1SGerd Hoffmann     if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PRS)) {
1423dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_port_reset(portnum);
1424f1ae32a1SGerd Hoffmann         usb_device_reset(port->port.dev);
1425f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_PRS;
1426f1ae32a1SGerd Hoffmann         /* ??? Should this also set OHCI_PORT_PESC.  */
1427f1ae32a1SGerd Hoffmann         port->ctrl |= OHCI_PORT_PES | OHCI_PORT_PRSC;
1428f1ae32a1SGerd Hoffmann     }
1429f1ae32a1SGerd Hoffmann 
1430f1ae32a1SGerd Hoffmann     /* Invert order here to ensure in ambiguous case, device is
1431f1ae32a1SGerd Hoffmann      * powered up...
1432f1ae32a1SGerd Hoffmann      */
1433f1ae32a1SGerd Hoffmann     if (val & OHCI_PORT_LSDA)
1434f1ae32a1SGerd Hoffmann         ohci_port_power(ohci, portnum, 0);
1435f1ae32a1SGerd Hoffmann     if (val & OHCI_PORT_PPS)
1436f1ae32a1SGerd Hoffmann         ohci_port_power(ohci, portnum, 1);
1437f1ae32a1SGerd Hoffmann 
1438f1ae32a1SGerd Hoffmann     if (old_state != port->ctrl)
1439f1ae32a1SGerd Hoffmann         ohci_set_interrupt(ohci, OHCI_INTR_RHSC);
1440f1ae32a1SGerd Hoffmann }
1441f1ae32a1SGerd Hoffmann 
1442f1ae32a1SGerd Hoffmann static uint64_t ohci_mem_read(void *opaque,
1443a8170e5eSAvi Kivity                               hwaddr addr,
1444f1ae32a1SGerd Hoffmann                               unsigned size)
1445f1ae32a1SGerd Hoffmann {
1446f1ae32a1SGerd Hoffmann     OHCIState *ohci = opaque;
1447f1ae32a1SGerd Hoffmann     uint32_t retval;
1448f1ae32a1SGerd Hoffmann 
1449f1ae32a1SGerd Hoffmann     /* Only aligned reads are allowed on OHCI */
1450f1ae32a1SGerd Hoffmann     if (addr & 3) {
1451dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_mem_read_unaligned(addr);
1452f1ae32a1SGerd Hoffmann         return 0xffffffff;
1453f1ae32a1SGerd Hoffmann     } else if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) {
1454f1ae32a1SGerd Hoffmann         /* HcRhPortStatus */
1455f1ae32a1SGerd Hoffmann         retval = ohci->rhport[(addr - 0x54) >> 2].ctrl | OHCI_PORT_PPS;
1456f1ae32a1SGerd Hoffmann     } else {
1457f1ae32a1SGerd Hoffmann         switch (addr >> 2) {
1458f1ae32a1SGerd Hoffmann         case 0: /* HcRevision */
1459f1ae32a1SGerd Hoffmann             retval = 0x10;
1460f1ae32a1SGerd Hoffmann             break;
1461f1ae32a1SGerd Hoffmann 
1462f1ae32a1SGerd Hoffmann         case 1: /* HcControl */
1463f1ae32a1SGerd Hoffmann             retval = ohci->ctl;
1464f1ae32a1SGerd Hoffmann             break;
1465f1ae32a1SGerd Hoffmann 
1466f1ae32a1SGerd Hoffmann         case 2: /* HcCommandStatus */
1467f1ae32a1SGerd Hoffmann             retval = ohci->status;
1468f1ae32a1SGerd Hoffmann             break;
1469f1ae32a1SGerd Hoffmann 
1470f1ae32a1SGerd Hoffmann         case 3: /* HcInterruptStatus */
1471f1ae32a1SGerd Hoffmann             retval = ohci->intr_status;
1472f1ae32a1SGerd Hoffmann             break;
1473f1ae32a1SGerd Hoffmann 
1474f1ae32a1SGerd Hoffmann         case 4: /* HcInterruptEnable */
1475f1ae32a1SGerd Hoffmann         case 5: /* HcInterruptDisable */
1476f1ae32a1SGerd Hoffmann             retval = ohci->intr;
1477f1ae32a1SGerd Hoffmann             break;
1478f1ae32a1SGerd Hoffmann 
1479f1ae32a1SGerd Hoffmann         case 6: /* HcHCCA */
1480f1ae32a1SGerd Hoffmann             retval = ohci->hcca;
1481f1ae32a1SGerd Hoffmann             break;
1482f1ae32a1SGerd Hoffmann 
1483f1ae32a1SGerd Hoffmann         case 7: /* HcPeriodCurrentED */
1484f1ae32a1SGerd Hoffmann             retval = ohci->per_cur;
1485f1ae32a1SGerd Hoffmann             break;
1486f1ae32a1SGerd Hoffmann 
1487f1ae32a1SGerd Hoffmann         case 8: /* HcControlHeadED */
1488f1ae32a1SGerd Hoffmann             retval = ohci->ctrl_head;
1489f1ae32a1SGerd Hoffmann             break;
1490f1ae32a1SGerd Hoffmann 
1491f1ae32a1SGerd Hoffmann         case 9: /* HcControlCurrentED */
1492f1ae32a1SGerd Hoffmann             retval = ohci->ctrl_cur;
1493f1ae32a1SGerd Hoffmann             break;
1494f1ae32a1SGerd Hoffmann 
1495f1ae32a1SGerd Hoffmann         case 10: /* HcBulkHeadED */
1496f1ae32a1SGerd Hoffmann             retval = ohci->bulk_head;
1497f1ae32a1SGerd Hoffmann             break;
1498f1ae32a1SGerd Hoffmann 
1499f1ae32a1SGerd Hoffmann         case 11: /* HcBulkCurrentED */
1500f1ae32a1SGerd Hoffmann             retval = ohci->bulk_cur;
1501f1ae32a1SGerd Hoffmann             break;
1502f1ae32a1SGerd Hoffmann 
1503f1ae32a1SGerd Hoffmann         case 12: /* HcDoneHead */
1504f1ae32a1SGerd Hoffmann             retval = ohci->done;
1505f1ae32a1SGerd Hoffmann             break;
1506f1ae32a1SGerd Hoffmann 
1507f1ae32a1SGerd Hoffmann         case 13: /* HcFmInterretval */
1508f1ae32a1SGerd Hoffmann             retval = (ohci->fit << 31) | (ohci->fsmps << 16) | (ohci->fi);
1509f1ae32a1SGerd Hoffmann             break;
1510f1ae32a1SGerd Hoffmann 
1511f1ae32a1SGerd Hoffmann         case 14: /* HcFmRemaining */
1512f1ae32a1SGerd Hoffmann             retval = ohci_get_frame_remaining(ohci);
1513f1ae32a1SGerd Hoffmann             break;
1514f1ae32a1SGerd Hoffmann 
1515f1ae32a1SGerd Hoffmann         case 15: /* HcFmNumber */
1516f1ae32a1SGerd Hoffmann             retval = ohci->frame_number;
1517f1ae32a1SGerd Hoffmann             break;
1518f1ae32a1SGerd Hoffmann 
1519f1ae32a1SGerd Hoffmann         case 16: /* HcPeriodicStart */
1520f1ae32a1SGerd Hoffmann             retval = ohci->pstart;
1521f1ae32a1SGerd Hoffmann             break;
1522f1ae32a1SGerd Hoffmann 
1523f1ae32a1SGerd Hoffmann         case 17: /* HcLSThreshold */
1524f1ae32a1SGerd Hoffmann             retval = ohci->lst;
1525f1ae32a1SGerd Hoffmann             break;
1526f1ae32a1SGerd Hoffmann 
1527f1ae32a1SGerd Hoffmann         case 18: /* HcRhDescriptorA */
1528f1ae32a1SGerd Hoffmann             retval = ohci->rhdesc_a;
1529f1ae32a1SGerd Hoffmann             break;
1530f1ae32a1SGerd Hoffmann 
1531f1ae32a1SGerd Hoffmann         case 19: /* HcRhDescriptorB */
1532f1ae32a1SGerd Hoffmann             retval = ohci->rhdesc_b;
1533f1ae32a1SGerd Hoffmann             break;
1534f1ae32a1SGerd Hoffmann 
1535f1ae32a1SGerd Hoffmann         case 20: /* HcRhStatus */
1536f1ae32a1SGerd Hoffmann             retval = ohci->rhstatus;
1537f1ae32a1SGerd Hoffmann             break;
1538f1ae32a1SGerd Hoffmann 
1539f1ae32a1SGerd Hoffmann         /* PXA27x specific registers */
1540f1ae32a1SGerd Hoffmann         case 24: /* HcStatus */
1541f1ae32a1SGerd Hoffmann             retval = ohci->hstatus & ohci->hmask;
1542f1ae32a1SGerd Hoffmann             break;
1543f1ae32a1SGerd Hoffmann 
1544f1ae32a1SGerd Hoffmann         case 25: /* HcHReset */
1545f1ae32a1SGerd Hoffmann             retval = ohci->hreset;
1546f1ae32a1SGerd Hoffmann             break;
1547f1ae32a1SGerd Hoffmann 
1548f1ae32a1SGerd Hoffmann         case 26: /* HcHInterruptEnable */
1549f1ae32a1SGerd Hoffmann             retval = ohci->hmask;
1550f1ae32a1SGerd Hoffmann             break;
1551f1ae32a1SGerd Hoffmann 
1552f1ae32a1SGerd Hoffmann         case 27: /* HcHInterruptTest */
1553f1ae32a1SGerd Hoffmann             retval = ohci->htest;
1554f1ae32a1SGerd Hoffmann             break;
1555f1ae32a1SGerd Hoffmann 
1556f1ae32a1SGerd Hoffmann         default:
1557dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_mem_read_bad_offset(addr);
1558f1ae32a1SGerd Hoffmann             retval = 0xffffffff;
1559f1ae32a1SGerd Hoffmann         }
1560f1ae32a1SGerd Hoffmann     }
1561f1ae32a1SGerd Hoffmann 
1562f1ae32a1SGerd Hoffmann     return retval;
1563f1ae32a1SGerd Hoffmann }
1564f1ae32a1SGerd Hoffmann 
1565f1ae32a1SGerd Hoffmann static void ohci_mem_write(void *opaque,
1566a8170e5eSAvi Kivity                            hwaddr addr,
1567f1ae32a1SGerd Hoffmann                            uint64_t val,
1568f1ae32a1SGerd Hoffmann                            unsigned size)
1569f1ae32a1SGerd Hoffmann {
1570f1ae32a1SGerd Hoffmann     OHCIState *ohci = opaque;
1571f1ae32a1SGerd Hoffmann 
1572f1ae32a1SGerd Hoffmann     /* Only aligned reads are allowed on OHCI */
1573f1ae32a1SGerd Hoffmann     if (addr & 3) {
1574dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_mem_write_unaligned(addr);
1575f1ae32a1SGerd Hoffmann         return;
1576f1ae32a1SGerd Hoffmann     }
1577f1ae32a1SGerd Hoffmann 
1578f1ae32a1SGerd Hoffmann     if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) {
1579f1ae32a1SGerd Hoffmann         /* HcRhPortStatus */
1580f1ae32a1SGerd Hoffmann         ohci_port_set_status(ohci, (addr - 0x54) >> 2, val);
1581f1ae32a1SGerd Hoffmann         return;
1582f1ae32a1SGerd Hoffmann     }
1583f1ae32a1SGerd Hoffmann 
1584f1ae32a1SGerd Hoffmann     switch (addr >> 2) {
1585f1ae32a1SGerd Hoffmann     case 1: /* HcControl */
1586f1ae32a1SGerd Hoffmann         ohci_set_ctl(ohci, val);
1587f1ae32a1SGerd Hoffmann         break;
1588f1ae32a1SGerd Hoffmann 
1589f1ae32a1SGerd Hoffmann     case 2: /* HcCommandStatus */
1590f1ae32a1SGerd Hoffmann         /* SOC is read-only */
1591f1ae32a1SGerd Hoffmann         val = (val & ~OHCI_STATUS_SOC);
1592f1ae32a1SGerd Hoffmann 
1593f1ae32a1SGerd Hoffmann         /* Bits written as '0' remain unchanged in the register */
1594f1ae32a1SGerd Hoffmann         ohci->status |= val;
1595f1ae32a1SGerd Hoffmann 
1596f1ae32a1SGerd Hoffmann         if (ohci->status & OHCI_STATUS_HCR)
15970922c3f6SHervé Poussineau             ohci_soft_reset(ohci);
1598f1ae32a1SGerd Hoffmann         break;
1599f1ae32a1SGerd Hoffmann 
1600f1ae32a1SGerd Hoffmann     case 3: /* HcInterruptStatus */
1601f1ae32a1SGerd Hoffmann         ohci->intr_status &= ~val;
1602f1ae32a1SGerd Hoffmann         ohci_intr_update(ohci);
1603f1ae32a1SGerd Hoffmann         break;
1604f1ae32a1SGerd Hoffmann 
1605f1ae32a1SGerd Hoffmann     case 4: /* HcInterruptEnable */
1606f1ae32a1SGerd Hoffmann         ohci->intr |= val;
1607f1ae32a1SGerd Hoffmann         ohci_intr_update(ohci);
1608f1ae32a1SGerd Hoffmann         break;
1609f1ae32a1SGerd Hoffmann 
1610f1ae32a1SGerd Hoffmann     case 5: /* HcInterruptDisable */
1611f1ae32a1SGerd Hoffmann         ohci->intr &= ~val;
1612f1ae32a1SGerd Hoffmann         ohci_intr_update(ohci);
1613f1ae32a1SGerd Hoffmann         break;
1614f1ae32a1SGerd Hoffmann 
1615f1ae32a1SGerd Hoffmann     case 6: /* HcHCCA */
1616f1ae32a1SGerd Hoffmann         ohci->hcca = val & OHCI_HCCA_MASK;
1617f1ae32a1SGerd Hoffmann         break;
1618f1ae32a1SGerd Hoffmann 
1619f1ae32a1SGerd Hoffmann     case 7: /* HcPeriodCurrentED */
1620f1ae32a1SGerd Hoffmann         /* Ignore writes to this read-only register, Linux does them */
1621f1ae32a1SGerd Hoffmann         break;
1622f1ae32a1SGerd Hoffmann 
1623f1ae32a1SGerd Hoffmann     case 8: /* HcControlHeadED */
1624f1ae32a1SGerd Hoffmann         ohci->ctrl_head = val & OHCI_EDPTR_MASK;
1625f1ae32a1SGerd Hoffmann         break;
1626f1ae32a1SGerd Hoffmann 
1627f1ae32a1SGerd Hoffmann     case 9: /* HcControlCurrentED */
1628f1ae32a1SGerd Hoffmann         ohci->ctrl_cur = val & OHCI_EDPTR_MASK;
1629f1ae32a1SGerd Hoffmann         break;
1630f1ae32a1SGerd Hoffmann 
1631f1ae32a1SGerd Hoffmann     case 10: /* HcBulkHeadED */
1632f1ae32a1SGerd Hoffmann         ohci->bulk_head = val & OHCI_EDPTR_MASK;
1633f1ae32a1SGerd Hoffmann         break;
1634f1ae32a1SGerd Hoffmann 
1635f1ae32a1SGerd Hoffmann     case 11: /* HcBulkCurrentED */
1636f1ae32a1SGerd Hoffmann         ohci->bulk_cur = val & OHCI_EDPTR_MASK;
1637f1ae32a1SGerd Hoffmann         break;
1638f1ae32a1SGerd Hoffmann 
1639f1ae32a1SGerd Hoffmann     case 13: /* HcFmInterval */
1640f1ae32a1SGerd Hoffmann         ohci->fsmps = (val & OHCI_FMI_FSMPS) >> 16;
1641f1ae32a1SGerd Hoffmann         ohci->fit = (val & OHCI_FMI_FIT) >> 31;
1642f1ae32a1SGerd Hoffmann         ohci_set_frame_interval(ohci, val);
1643f1ae32a1SGerd Hoffmann         break;
1644f1ae32a1SGerd Hoffmann 
1645f1ae32a1SGerd Hoffmann     case 15: /* HcFmNumber */
1646f1ae32a1SGerd Hoffmann         break;
1647f1ae32a1SGerd Hoffmann 
1648f1ae32a1SGerd Hoffmann     case 16: /* HcPeriodicStart */
1649f1ae32a1SGerd Hoffmann         ohci->pstart = val & 0xffff;
1650f1ae32a1SGerd Hoffmann         break;
1651f1ae32a1SGerd Hoffmann 
1652f1ae32a1SGerd Hoffmann     case 17: /* HcLSThreshold */
1653f1ae32a1SGerd Hoffmann         ohci->lst = val & 0xffff;
1654f1ae32a1SGerd Hoffmann         break;
1655f1ae32a1SGerd Hoffmann 
1656f1ae32a1SGerd Hoffmann     case 18: /* HcRhDescriptorA */
1657f1ae32a1SGerd Hoffmann         ohci->rhdesc_a &= ~OHCI_RHA_RW_MASK;
1658f1ae32a1SGerd Hoffmann         ohci->rhdesc_a |= val & OHCI_RHA_RW_MASK;
1659f1ae32a1SGerd Hoffmann         break;
1660f1ae32a1SGerd Hoffmann 
1661f1ae32a1SGerd Hoffmann     case 19: /* HcRhDescriptorB */
1662f1ae32a1SGerd Hoffmann         break;
1663f1ae32a1SGerd Hoffmann 
1664f1ae32a1SGerd Hoffmann     case 20: /* HcRhStatus */
1665f1ae32a1SGerd Hoffmann         ohci_set_hub_status(ohci, val);
1666f1ae32a1SGerd Hoffmann         break;
1667f1ae32a1SGerd Hoffmann 
1668f1ae32a1SGerd Hoffmann     /* PXA27x specific registers */
1669f1ae32a1SGerd Hoffmann     case 24: /* HcStatus */
1670f1ae32a1SGerd Hoffmann         ohci->hstatus &= ~(val & ohci->hmask);
16717fa96d73SGerd Hoffmann         break;
1672f1ae32a1SGerd Hoffmann 
1673f1ae32a1SGerd Hoffmann     case 25: /* HcHReset */
1674f1ae32a1SGerd Hoffmann         ohci->hreset = val & ~OHCI_HRESET_FSBIR;
1675f1ae32a1SGerd Hoffmann         if (val & OHCI_HRESET_FSBIR)
167684d04e21SHervé Poussineau             ohci_hard_reset(ohci);
1677f1ae32a1SGerd Hoffmann         break;
1678f1ae32a1SGerd Hoffmann 
1679f1ae32a1SGerd Hoffmann     case 26: /* HcHInterruptEnable */
1680f1ae32a1SGerd Hoffmann         ohci->hmask = val;
1681f1ae32a1SGerd Hoffmann         break;
1682f1ae32a1SGerd Hoffmann 
1683f1ae32a1SGerd Hoffmann     case 27: /* HcHInterruptTest */
1684f1ae32a1SGerd Hoffmann         ohci->htest = val;
1685f1ae32a1SGerd Hoffmann         break;
1686f1ae32a1SGerd Hoffmann 
1687f1ae32a1SGerd Hoffmann     default:
1688dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_mem_write_bad_offset(addr);
1689f1ae32a1SGerd Hoffmann         break;
1690f1ae32a1SGerd Hoffmann     }
1691f1ae32a1SGerd Hoffmann }
1692f1ae32a1SGerd Hoffmann 
1693*37bf0654SBALATON Zoltan static const MemoryRegionOps ohci_mem_ops = {
1694*37bf0654SBALATON Zoltan     .read = ohci_mem_read,
1695*37bf0654SBALATON Zoltan     .write = ohci_mem_write,
1696*37bf0654SBALATON Zoltan     .endianness = DEVICE_LITTLE_ENDIAN,
1697*37bf0654SBALATON Zoltan };
1698*37bf0654SBALATON Zoltan 
1699*37bf0654SBALATON Zoltan /* USBPortOps */
1700*37bf0654SBALATON Zoltan static void ohci_attach(USBPort *port1)
1701*37bf0654SBALATON Zoltan {
1702*37bf0654SBALATON Zoltan     OHCIState *s = port1->opaque;
1703*37bf0654SBALATON Zoltan     OHCIPort *port = &s->rhport[port1->index];
1704*37bf0654SBALATON Zoltan     uint32_t old_state = port->ctrl;
1705*37bf0654SBALATON Zoltan 
1706*37bf0654SBALATON Zoltan     /* set connect status */
1707*37bf0654SBALATON Zoltan     port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;
1708*37bf0654SBALATON Zoltan 
1709*37bf0654SBALATON Zoltan     /* update speed */
1710*37bf0654SBALATON Zoltan     if (port->port.dev->speed == USB_SPEED_LOW) {
1711*37bf0654SBALATON Zoltan         port->ctrl |= OHCI_PORT_LSDA;
1712*37bf0654SBALATON Zoltan     } else {
1713*37bf0654SBALATON Zoltan         port->ctrl &= ~OHCI_PORT_LSDA;
1714*37bf0654SBALATON Zoltan     }
1715*37bf0654SBALATON Zoltan 
1716*37bf0654SBALATON Zoltan     /* notify of remote-wakeup */
1717*37bf0654SBALATON Zoltan     if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
1718*37bf0654SBALATON Zoltan         ohci_set_interrupt(s, OHCI_INTR_RD);
1719*37bf0654SBALATON Zoltan     }
1720*37bf0654SBALATON Zoltan 
1721*37bf0654SBALATON Zoltan     trace_usb_ohci_port_attach(port1->index);
1722*37bf0654SBALATON Zoltan 
1723*37bf0654SBALATON Zoltan     if (old_state != port->ctrl) {
1724*37bf0654SBALATON Zoltan         ohci_set_interrupt(s, OHCI_INTR_RHSC);
1725*37bf0654SBALATON Zoltan     }
1726*37bf0654SBALATON Zoltan }
1727*37bf0654SBALATON Zoltan 
1728f1ae32a1SGerd Hoffmann static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev)
1729f1ae32a1SGerd Hoffmann {
1730f1ae32a1SGerd Hoffmann     if (ohci->async_td &&
1731f1ae32a1SGerd Hoffmann         usb_packet_is_inflight(&ohci->usb_packet) &&
1732f1ae32a1SGerd Hoffmann         ohci->usb_packet.ep->dev == dev) {
1733f1ae32a1SGerd Hoffmann         usb_cancel_packet(&ohci->usb_packet);
1734f1ae32a1SGerd Hoffmann         ohci->async_td = 0;
1735f1ae32a1SGerd Hoffmann     }
1736f1ae32a1SGerd Hoffmann }
1737f1ae32a1SGerd Hoffmann 
1738*37bf0654SBALATON Zoltan static void ohci_child_detach(USBPort *port1, USBDevice *child)
1739*37bf0654SBALATON Zoltan {
1740*37bf0654SBALATON Zoltan     OHCIState *s = port1->opaque;
1741*37bf0654SBALATON Zoltan 
1742*37bf0654SBALATON Zoltan     ohci_async_cancel_device(s, child);
1743*37bf0654SBALATON Zoltan }
1744*37bf0654SBALATON Zoltan 
1745*37bf0654SBALATON Zoltan static void ohci_detach(USBPort *port1)
1746*37bf0654SBALATON Zoltan {
1747*37bf0654SBALATON Zoltan     OHCIState *s = port1->opaque;
1748*37bf0654SBALATON Zoltan     OHCIPort *port = &s->rhport[port1->index];
1749*37bf0654SBALATON Zoltan     uint32_t old_state = port->ctrl;
1750*37bf0654SBALATON Zoltan 
1751*37bf0654SBALATON Zoltan     ohci_async_cancel_device(s, port1->dev);
1752*37bf0654SBALATON Zoltan 
1753*37bf0654SBALATON Zoltan     /* set connect status */
1754*37bf0654SBALATON Zoltan     if (port->ctrl & OHCI_PORT_CCS) {
1755*37bf0654SBALATON Zoltan         port->ctrl &= ~OHCI_PORT_CCS;
1756*37bf0654SBALATON Zoltan         port->ctrl |= OHCI_PORT_CSC;
1757*37bf0654SBALATON Zoltan     }
1758*37bf0654SBALATON Zoltan     /* disable port */
1759*37bf0654SBALATON Zoltan     if (port->ctrl & OHCI_PORT_PES) {
1760*37bf0654SBALATON Zoltan         port->ctrl &= ~OHCI_PORT_PES;
1761*37bf0654SBALATON Zoltan         port->ctrl |= OHCI_PORT_PESC;
1762*37bf0654SBALATON Zoltan     }
1763*37bf0654SBALATON Zoltan     trace_usb_ohci_port_detach(port1->index);
1764*37bf0654SBALATON Zoltan 
1765*37bf0654SBALATON Zoltan     if (old_state != port->ctrl) {
1766*37bf0654SBALATON Zoltan         ohci_set_interrupt(s, OHCI_INTR_RHSC);
1767*37bf0654SBALATON Zoltan     }
1768*37bf0654SBALATON Zoltan }
1769*37bf0654SBALATON Zoltan 
1770*37bf0654SBALATON Zoltan static void ohci_wakeup(USBPort *port1)
1771*37bf0654SBALATON Zoltan {
1772*37bf0654SBALATON Zoltan     OHCIState *s = port1->opaque;
1773*37bf0654SBALATON Zoltan     OHCIPort *port = &s->rhport[port1->index];
1774*37bf0654SBALATON Zoltan     uint32_t intr = 0;
1775*37bf0654SBALATON Zoltan     if (port->ctrl & OHCI_PORT_PSS) {
1776*37bf0654SBALATON Zoltan         trace_usb_ohci_port_wakeup(port1->index);
1777*37bf0654SBALATON Zoltan         port->ctrl |= OHCI_PORT_PSSC;
1778*37bf0654SBALATON Zoltan         port->ctrl &= ~OHCI_PORT_PSS;
1779*37bf0654SBALATON Zoltan         intr = OHCI_INTR_RHSC;
1780*37bf0654SBALATON Zoltan     }
1781*37bf0654SBALATON Zoltan     /* Note that the controller can be suspended even if this port is not */
1782*37bf0654SBALATON Zoltan     if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
1783*37bf0654SBALATON Zoltan         trace_usb_ohci_remote_wakeup(s->name);
1784*37bf0654SBALATON Zoltan         /* This is the one state transition the controller can do by itself */
1785*37bf0654SBALATON Zoltan         s->ctl &= ~OHCI_CTL_HCFS;
1786*37bf0654SBALATON Zoltan         s->ctl |= OHCI_USB_RESUME;
1787*37bf0654SBALATON Zoltan         /*
1788*37bf0654SBALATON Zoltan          * In suspend mode only ResumeDetected is possible, not RHSC:
1789*37bf0654SBALATON Zoltan          * see the OHCI spec 5.1.2.3.
1790*37bf0654SBALATON Zoltan          */
1791*37bf0654SBALATON Zoltan         intr = OHCI_INTR_RD;
1792*37bf0654SBALATON Zoltan     }
1793*37bf0654SBALATON Zoltan     ohci_set_interrupt(s, intr);
1794*37bf0654SBALATON Zoltan }
1795*37bf0654SBALATON Zoltan 
1796*37bf0654SBALATON Zoltan static void ohci_async_complete_packet(USBPort *port, USBPacket *packet)
1797*37bf0654SBALATON Zoltan {
1798*37bf0654SBALATON Zoltan     OHCIState *ohci = container_of(packet, OHCIState, usb_packet);
1799*37bf0654SBALATON Zoltan 
1800*37bf0654SBALATON Zoltan     trace_usb_ohci_async_complete();
1801*37bf0654SBALATON Zoltan     ohci->async_complete = true;
1802*37bf0654SBALATON Zoltan     ohci_process_lists(ohci, 1);
1803*37bf0654SBALATON Zoltan }
1804f1ae32a1SGerd Hoffmann 
1805f1ae32a1SGerd Hoffmann static USBPortOps ohci_port_ops = {
1806f1ae32a1SGerd Hoffmann     .attach = ohci_attach,
1807f1ae32a1SGerd Hoffmann     .detach = ohci_detach,
1808f1ae32a1SGerd Hoffmann     .child_detach = ohci_child_detach,
1809f1ae32a1SGerd Hoffmann     .wakeup = ohci_wakeup,
1810f1ae32a1SGerd Hoffmann     .complete = ohci_async_complete_packet,
1811f1ae32a1SGerd Hoffmann };
1812f1ae32a1SGerd Hoffmann 
1813f1ae32a1SGerd Hoffmann static USBBusOps ohci_bus_ops = {
1814f1ae32a1SGerd Hoffmann };
1815f1ae32a1SGerd Hoffmann 
181634d97308SThomas Huth void usb_ohci_init(OHCIState *ohci, DeviceState *dev, uint32_t num_ports,
181734d97308SThomas Huth                    dma_addr_t localmem_base, char *masterbus,
181834d97308SThomas Huth                    uint32_t firstport, AddressSpace *as,
181972e0c127SThomas Huth                    void (*ohci_die_fn)(struct OHCIState *), Error **errp)
1820f1ae32a1SGerd Hoffmann {
1821f4bbaaf5SMarkus Armbruster     Error *err = NULL;
1822f1ae32a1SGerd Hoffmann     int i;
1823f1ae32a1SGerd Hoffmann 
1824df32fd1cSPaolo Bonzini     ohci->as = as;
182572e0c127SThomas Huth     ohci->ohci_die = ohci_die_fn;
18269ac6a217SDavid Gibson 
1827d400fc01SThomas Huth     if (num_ports > OHCI_MAX_PORTS) {
1828b9a3a4f2SLi Qiang         error_setg(errp, "OHCI num-ports=%u is too big (limit is %u ports)",
1829d400fc01SThomas Huth                    num_ports, OHCI_MAX_PORTS);
1830d400fc01SThomas Huth         return;
1831d400fc01SThomas Huth     }
1832d400fc01SThomas Huth 
1833f1ae32a1SGerd Hoffmann     if (usb_frame_time == 0) {
1834f1ae32a1SGerd Hoffmann #ifdef OHCI_TIME_WARP
183573bcb24dSRutuja Shah         usb_frame_time = NANOSECONDS_PER_SECOND;
183673bcb24dSRutuja Shah         usb_bit_time = NANOSECONDS_PER_SECOND / (USB_HZ / 1000);
1837f1ae32a1SGerd Hoffmann #else
183873bcb24dSRutuja Shah         usb_frame_time = NANOSECONDS_PER_SECOND / 1000;
183973bcb24dSRutuja Shah         if (NANOSECONDS_PER_SECOND >= USB_HZ) {
184073bcb24dSRutuja Shah             usb_bit_time = NANOSECONDS_PER_SECOND / USB_HZ;
1841f1ae32a1SGerd Hoffmann         } else {
1842f1ae32a1SGerd Hoffmann             usb_bit_time = 1;
1843f1ae32a1SGerd Hoffmann         }
1844f1ae32a1SGerd Hoffmann #endif
1845dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_init_time(usb_frame_time, usb_bit_time);
1846f1ae32a1SGerd Hoffmann     }
1847f1ae32a1SGerd Hoffmann 
1848f1ae32a1SGerd Hoffmann     ohci->num_ports = num_ports;
1849f1ae32a1SGerd Hoffmann     if (masterbus) {
1850f1ae32a1SGerd Hoffmann         USBPort *ports[OHCI_MAX_PORTS];
1851f1ae32a1SGerd Hoffmann         for(i = 0; i < num_ports; i++) {
1852f1ae32a1SGerd Hoffmann             ports[i] = &ohci->rhport[i].port;
1853f1ae32a1SGerd Hoffmann         }
1854f4bbaaf5SMarkus Armbruster         usb_register_companion(masterbus, ports, num_ports,
1855f1ae32a1SGerd Hoffmann                                firstport, ohci, &ohci_port_ops,
1856f4bbaaf5SMarkus Armbruster                                USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL,
1857f4bbaaf5SMarkus Armbruster                                &err);
1858f4bbaaf5SMarkus Armbruster         if (err) {
185987581feaSMarkus Armbruster             error_propagate(errp, err);
186087581feaSMarkus Armbruster             return;
1861f1ae32a1SGerd Hoffmann         }
1862f1ae32a1SGerd Hoffmann     } else {
1863c889b3a5SAndreas Färber         usb_bus_new(&ohci->bus, sizeof(ohci->bus), &ohci_bus_ops, dev);
1864f1ae32a1SGerd Hoffmann         for (i = 0; i < num_ports; i++) {
1865f1ae32a1SGerd Hoffmann             usb_register_port(&ohci->bus, &ohci->rhport[i].port,
1866f1ae32a1SGerd Hoffmann                               ohci, i, &ohci_port_ops,
1867f1ae32a1SGerd Hoffmann                               USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
1868f1ae32a1SGerd Hoffmann         }
1869f1ae32a1SGerd Hoffmann     }
1870f1ae32a1SGerd Hoffmann 
187122fc860bSPaolo Bonzini     memory_region_init_io(&ohci->mem, OBJECT(dev), &ohci_mem_ops,
187222fc860bSPaolo Bonzini                           ohci, "ohci", 256);
1873f1ae32a1SGerd Hoffmann     ohci->localmem_base = localmem_base;
1874f1ae32a1SGerd Hoffmann 
1875f1ae32a1SGerd Hoffmann     ohci->name = object_get_typename(OBJECT(dev));
1876f1ae32a1SGerd Hoffmann     usb_packet_init(&ohci->usb_packet);
1877f1ae32a1SGerd Hoffmann 
1878f1ae32a1SGerd Hoffmann     ohci->async_td = 0;
1879fa1298c2SGerd Hoffmann 
1880fa1298c2SGerd Hoffmann     ohci->eof_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
1881fa1298c2SGerd Hoffmann                                    ohci_frame_boundary, ohci);
1882f1ae32a1SGerd Hoffmann }
1883f1ae32a1SGerd Hoffmann 
188472e0c127SThomas Huth /**
188572e0c127SThomas Huth  * A typical OHCI will stop operating and set itself into error state
188672e0c127SThomas Huth  * (which can be queried by MMIO) to signal that it got an error.
1887cf66ee8eSAlexey Kardashevskiy  */
188834d97308SThomas Huth void ohci_sysbus_die(struct OHCIState *ohci)
1889cf66ee8eSAlexey Kardashevskiy {
1890dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_die();
1891cf66ee8eSAlexey Kardashevskiy 
1892cf66ee8eSAlexey Kardashevskiy     ohci_set_interrupt(ohci, OHCI_INTR_UE);
1893cf66ee8eSAlexey Kardashevskiy     ohci_bus_stop(ohci);
189472e0c127SThomas Huth }
189572e0c127SThomas Huth 
1896457215ecSHu Tao static void ohci_realize_pxa(DeviceState *dev, Error **errp)
1897f1ae32a1SGerd Hoffmann {
18981aa0c0c7SHu Tao     OHCISysBusState *s = SYSBUS_OHCI(dev);
1899457215ecSHu Tao     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
1900d7145b66SBALATON Zoltan     Error *err = NULL;
1901f1ae32a1SGerd Hoffmann 
1902d7145b66SBALATON Zoltan     usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset,
1903d7145b66SBALATON Zoltan                   s->masterbus, s->firstport,
190472e0c127SThomas Huth                   &address_space_memory, ohci_sysbus_die, &err);
1905d7145b66SBALATON Zoltan     if (err) {
1906d7145b66SBALATON Zoltan         error_propagate(errp, err);
1907d7145b66SBALATON Zoltan         return;
1908d7145b66SBALATON Zoltan     }
1909457215ecSHu Tao     sysbus_init_irq(sbd, &s->ohci.irq);
1910457215ecSHu Tao     sysbus_init_mmio(sbd, &s->ohci.mem);
1911f1ae32a1SGerd Hoffmann }
1912f1ae32a1SGerd Hoffmann 
191388dd1b8dSGonglei static void usb_ohci_reset_sysbus(DeviceState *dev)
191488dd1b8dSGonglei {
191588dd1b8dSGonglei     OHCISysBusState *s = SYSBUS_OHCI(dev);
191688dd1b8dSGonglei     OHCIState *ohci = &s->ohci;
191788dd1b8dSGonglei 
191884d04e21SHervé Poussineau     ohci_hard_reset(ohci);
191988dd1b8dSGonglei }
192088dd1b8dSGonglei 
192169e25d26SAlexey Kardashevskiy static const VMStateDescription vmstate_ohci_state_port = {
192269e25d26SAlexey Kardashevskiy     .name = "ohci-core/port",
192369e25d26SAlexey Kardashevskiy     .version_id = 1,
192469e25d26SAlexey Kardashevskiy     .minimum_version_id = 1,
192569e25d26SAlexey Kardashevskiy     .fields = (VMStateField[]) {
192669e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(ctrl, OHCIPort),
192769e25d26SAlexey Kardashevskiy         VMSTATE_END_OF_LIST()
192869e25d26SAlexey Kardashevskiy     },
192969e25d26SAlexey Kardashevskiy };
193069e25d26SAlexey Kardashevskiy 
193169e25d26SAlexey Kardashevskiy static bool ohci_eof_timer_needed(void *opaque)
193269e25d26SAlexey Kardashevskiy {
193369e25d26SAlexey Kardashevskiy     OHCIState *ohci = opaque;
193469e25d26SAlexey Kardashevskiy 
1935fa1298c2SGerd Hoffmann     return timer_pending(ohci->eof_timer);
193669e25d26SAlexey Kardashevskiy }
193769e25d26SAlexey Kardashevskiy 
193869e25d26SAlexey Kardashevskiy static const VMStateDescription vmstate_ohci_eof_timer = {
193969e25d26SAlexey Kardashevskiy     .name = "ohci-core/eof-timer",
194069e25d26SAlexey Kardashevskiy     .version_id = 1,
194169e25d26SAlexey Kardashevskiy     .minimum_version_id = 1,
19425cd8cadaSJuan Quintela     .needed = ohci_eof_timer_needed,
194369e25d26SAlexey Kardashevskiy     .fields = (VMStateField[]) {
1944e720677eSPaolo Bonzini         VMSTATE_TIMER_PTR(eof_timer, OHCIState),
194569e25d26SAlexey Kardashevskiy         VMSTATE_END_OF_LIST()
194669e25d26SAlexey Kardashevskiy     },
194769e25d26SAlexey Kardashevskiy };
194869e25d26SAlexey Kardashevskiy 
194934d97308SThomas Huth const VMStateDescription vmstate_ohci_state = {
195069e25d26SAlexey Kardashevskiy     .name = "ohci-core",
195169e25d26SAlexey Kardashevskiy     .version_id = 1,
195269e25d26SAlexey Kardashevskiy     .minimum_version_id = 1,
195369e25d26SAlexey Kardashevskiy     .fields = (VMStateField[]) {
195469e25d26SAlexey Kardashevskiy         VMSTATE_INT64(sof_time, OHCIState),
195569e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(ctl, OHCIState),
195669e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(status, OHCIState),
195769e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(intr_status, OHCIState),
195869e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(intr, OHCIState),
195969e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(hcca, OHCIState),
196069e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(ctrl_head, OHCIState),
196169e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(ctrl_cur, OHCIState),
196269e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(bulk_head, OHCIState),
196369e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(bulk_cur, OHCIState),
196469e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(per_cur, OHCIState),
196569e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(done, OHCIState),
196669e25d26SAlexey Kardashevskiy         VMSTATE_INT32(done_count, OHCIState),
196769e25d26SAlexey Kardashevskiy         VMSTATE_UINT16(fsmps, OHCIState),
196869e25d26SAlexey Kardashevskiy         VMSTATE_UINT8(fit, OHCIState),
196969e25d26SAlexey Kardashevskiy         VMSTATE_UINT16(fi, OHCIState),
197069e25d26SAlexey Kardashevskiy         VMSTATE_UINT8(frt, OHCIState),
197169e25d26SAlexey Kardashevskiy         VMSTATE_UINT16(frame_number, OHCIState),
197269e25d26SAlexey Kardashevskiy         VMSTATE_UINT16(padding, OHCIState),
197369e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(pstart, OHCIState),
197469e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(lst, OHCIState),
197569e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(rhdesc_a, OHCIState),
197669e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(rhdesc_b, OHCIState),
197769e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(rhstatus, OHCIState),
197869e25d26SAlexey Kardashevskiy         VMSTATE_STRUCT_ARRAY(rhport, OHCIState, OHCI_MAX_PORTS, 0,
197969e25d26SAlexey Kardashevskiy                              vmstate_ohci_state_port, OHCIPort),
198069e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(hstatus, OHCIState),
198169e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(hmask, OHCIState),
198269e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(hreset, OHCIState),
198369e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(htest, OHCIState),
198469e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(old_ctl, OHCIState),
198569e25d26SAlexey Kardashevskiy         VMSTATE_UINT8_ARRAY(usb_buf, OHCIState, 8192),
198669e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(async_td, OHCIState),
198769e25d26SAlexey Kardashevskiy         VMSTATE_BOOL(async_complete, OHCIState),
198869e25d26SAlexey Kardashevskiy         VMSTATE_END_OF_LIST()
198969e25d26SAlexey Kardashevskiy     },
19905cd8cadaSJuan Quintela     .subsections = (const VMStateDescription*[]) {
19915cd8cadaSJuan Quintela         &vmstate_ohci_eof_timer,
19925cd8cadaSJuan Quintela         NULL
199369e25d26SAlexey Kardashevskiy     }
199469e25d26SAlexey Kardashevskiy };
199569e25d26SAlexey Kardashevskiy 
1996f1ae32a1SGerd Hoffmann static Property ohci_sysbus_properties[] = {
1997d7145b66SBALATON Zoltan     DEFINE_PROP_STRING("masterbus", OHCISysBusState, masterbus),
1998f1ae32a1SGerd Hoffmann     DEFINE_PROP_UINT32("num-ports", OHCISysBusState, num_ports, 3),
1999d7145b66SBALATON Zoltan     DEFINE_PROP_UINT32("firstport", OHCISysBusState, firstport, 0),
20006998b6c7SVijay Kumar B     DEFINE_PROP_DMAADDR("dma-offset", OHCISysBusState, dma_offset, 0),
2001f1ae32a1SGerd Hoffmann     DEFINE_PROP_END_OF_LIST(),
2002f1ae32a1SGerd Hoffmann };
2003f1ae32a1SGerd Hoffmann 
2004f1ae32a1SGerd Hoffmann static void ohci_sysbus_class_init(ObjectClass *klass, void *data)
2005f1ae32a1SGerd Hoffmann {
2006f1ae32a1SGerd Hoffmann     DeviceClass *dc = DEVICE_CLASS(klass);
2007f1ae32a1SGerd Hoffmann 
2008457215ecSHu Tao     dc->realize = ohci_realize_pxa;
2009125ee0edSMarcel Apfelbaum     set_bit(DEVICE_CATEGORY_USB, dc->categories);
2010f1ae32a1SGerd Hoffmann     dc->desc = "OHCI USB Controller";
20114f67d30bSMarc-André Lureau     device_class_set_props(dc, ohci_sysbus_properties);
201288dd1b8dSGonglei     dc->reset = usb_ohci_reset_sysbus;
2013f1ae32a1SGerd Hoffmann }
2014f1ae32a1SGerd Hoffmann 
20158c43a6f0SAndreas Färber static const TypeInfo ohci_sysbus_info = {
20161aa0c0c7SHu Tao     .name          = TYPE_SYSBUS_OHCI,
2017f1ae32a1SGerd Hoffmann     .parent        = TYPE_SYS_BUS_DEVICE,
2018f1ae32a1SGerd Hoffmann     .instance_size = sizeof(OHCISysBusState),
2019f1ae32a1SGerd Hoffmann     .class_init    = ohci_sysbus_class_init,
2020f1ae32a1SGerd Hoffmann };
2021f1ae32a1SGerd Hoffmann 
2022f1ae32a1SGerd Hoffmann static void ohci_register_types(void)
2023f1ae32a1SGerd Hoffmann {
2024f1ae32a1SGerd Hoffmann     type_register_static(&ohci_sysbus_info);
2025f1ae32a1SGerd Hoffmann }
2026f1ae32a1SGerd Hoffmann 
2027f1ae32a1SGerd Hoffmann type_init(ohci_register_types)
2028