xref: /openbmc/qemu/hw/usb/hcd-ohci.c (revision 2a8537cf)
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 */
42572a6732SBALATON Zoltan /*#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 
6138019462SPhilippe Mathieu-Daudé /* Bitfields for the first word of an Endpoint Descriptor. */
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 
7438019462SPhilippe Mathieu-Daudé /* Flags in the head field of an Endpoint Descriptor. */
75f1ae32a1SGerd Hoffmann #define OHCI_ED_H         1
76f1ae32a1SGerd Hoffmann #define OHCI_ED_C         2
77f1ae32a1SGerd Hoffmann 
7838019462SPhilippe Mathieu-Daudé /* Bitfields for the first word of a Transfer Descriptor. */
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 
9138019462SPhilippe Mathieu-Daudé /* Bitfields for the first word of an Isochronous Transfer Descriptor. */
9238019462SPhilippe Mathieu-Daudé /* CC & DI - same as in the General Transfer Descriptor */
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 
9838019462SPhilippe Mathieu-Daudé /* Isochronous Transfer Descriptor - 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)
215978c93beSBALATON Zoltan #define OHCI_PORT_WTC         (OHCI_PORT_CSC | OHCI_PORT_PESC | \
216978c93beSBALATON Zoltan                                OHCI_PORT_PSSC | OHCI_PORT_OCIC | \
217978c93beSBALATON Zoltan                                OHCI_PORT_PRSC)
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 
2389ae8d31dSBALATON Zoltan static const char *ohci_reg_names[] = {
2399ae8d31dSBALATON Zoltan     "HcRevision", "HcControl", "HcCommandStatus", "HcInterruptStatus",
2409ae8d31dSBALATON Zoltan     "HcInterruptEnable", "HcInterruptDisable", "HcHCCA", "HcPeriodCurrentED",
2419ae8d31dSBALATON Zoltan     "HcControlHeadED", "HcControlCurrentED", "HcBulkHeadED", "HcBulkCurrentED",
2429ae8d31dSBALATON Zoltan     "HcDoneHead", "HcFmInterval", "HcFmRemaining", "HcFmNumber",
2439ae8d31dSBALATON Zoltan     "HcPeriodicStart", "HcLSThreshold", "HcRhDescriptorA", "HcRhDescriptorB",
2449ae8d31dSBALATON Zoltan     "HcRhStatus"
2459ae8d31dSBALATON Zoltan };
2469ae8d31dSBALATON Zoltan 
ohci_reg_name(hwaddr addr)2479ae8d31dSBALATON Zoltan static const char *ohci_reg_name(hwaddr addr)
2489ae8d31dSBALATON Zoltan {
2499ae8d31dSBALATON Zoltan     if (addr >> 2 < ARRAY_SIZE(ohci_reg_names)) {
2509ae8d31dSBALATON Zoltan         return ohci_reg_names[addr >> 2];
2519ae8d31dSBALATON Zoltan     } else {
2529ae8d31dSBALATON Zoltan         return "<unknown>";
2539ae8d31dSBALATON Zoltan     }
2549ae8d31dSBALATON Zoltan }
2559ae8d31dSBALATON Zoltan 
ohci_die(OHCIState * ohci)25672e0c127SThomas Huth static void ohci_die(OHCIState *ohci)
25772e0c127SThomas Huth {
25872e0c127SThomas Huth     ohci->ohci_die(ohci);
25972e0c127SThomas Huth }
260cf66ee8eSAlexey Kardashevskiy 
261f1ae32a1SGerd Hoffmann /* Update IRQ levels */
ohci_intr_update(OHCIState * ohci)262f1ae32a1SGerd Hoffmann static inline void ohci_intr_update(OHCIState *ohci)
263f1ae32a1SGerd Hoffmann {
264f1ae32a1SGerd Hoffmann     int level = 0;
265f1ae32a1SGerd Hoffmann 
266f1ae32a1SGerd Hoffmann     if ((ohci->intr & OHCI_INTR_MIE) &&
267f1ae32a1SGerd Hoffmann         (ohci->intr_status & ohci->intr))
268f1ae32a1SGerd Hoffmann         level = 1;
269f1ae32a1SGerd Hoffmann 
270f1ae32a1SGerd Hoffmann     qemu_set_irq(ohci->irq, level);
271f1ae32a1SGerd Hoffmann }
272f1ae32a1SGerd Hoffmann 
273f1ae32a1SGerd Hoffmann /* Set an interrupt */
ohci_set_interrupt(OHCIState * ohci,uint32_t intr)274f1ae32a1SGerd Hoffmann static inline void ohci_set_interrupt(OHCIState *ohci, uint32_t intr)
275f1ae32a1SGerd Hoffmann {
276f1ae32a1SGerd Hoffmann     ohci->intr_status |= intr;
277f1ae32a1SGerd Hoffmann     ohci_intr_update(ohci);
278f1ae32a1SGerd Hoffmann }
279f1ae32a1SGerd Hoffmann 
ohci_find_device(OHCIState * ohci,uint8_t addr)280f1ae32a1SGerd Hoffmann static USBDevice *ohci_find_device(OHCIState *ohci, uint8_t addr)
281f1ae32a1SGerd Hoffmann {
282f1ae32a1SGerd Hoffmann     USBDevice *dev;
283f1ae32a1SGerd Hoffmann     int i;
284f1ae32a1SGerd Hoffmann 
285f1ae32a1SGerd Hoffmann     for (i = 0; i < ohci->num_ports; i++) {
286f1ae32a1SGerd Hoffmann         if ((ohci->rhport[i].ctrl & OHCI_PORT_PES) == 0) {
287f1ae32a1SGerd Hoffmann             continue;
288f1ae32a1SGerd Hoffmann         }
289f1ae32a1SGerd Hoffmann         dev = usb_find_device(&ohci->rhport[i].port, addr);
290f1ae32a1SGerd Hoffmann         if (dev != NULL) {
291f1ae32a1SGerd Hoffmann             return dev;
292f1ae32a1SGerd Hoffmann         }
293f1ae32a1SGerd Hoffmann     }
294f1ae32a1SGerd Hoffmann     return NULL;
295f1ae32a1SGerd Hoffmann }
296f1ae32a1SGerd Hoffmann 
ohci_stop_endpoints(OHCIState * ohci)29734d97308SThomas Huth void ohci_stop_endpoints(OHCIState *ohci)
298f79738b0SHans de Goede {
299f79738b0SHans de Goede     USBDevice *dev;
300f79738b0SHans de Goede     int i, j;
301f79738b0SHans de Goede 
302ae310557SBALATON Zoltan     if (ohci->async_td) {
303ae310557SBALATON Zoltan         usb_cancel_packet(&ohci->usb_packet);
304ae310557SBALATON Zoltan         ohci->async_td = 0;
305ae310557SBALATON Zoltan     }
306f79738b0SHans de Goede     for (i = 0; i < ohci->num_ports; i++) {
307f79738b0SHans de Goede         dev = ohci->rhport[i].port.dev;
308f79738b0SHans de Goede         if (dev && dev->attached) {
309f79738b0SHans de Goede             usb_device_ep_stopped(dev, &dev->ep_ctl);
310f79738b0SHans de Goede             for (j = 0; j < USB_MAX_ENDPOINTS; j++) {
311f79738b0SHans de Goede                 usb_device_ep_stopped(dev, &dev->ep_in[j]);
312f79738b0SHans de Goede                 usb_device_ep_stopped(dev, &dev->ep_out[j]);
313f79738b0SHans de Goede             }
314f79738b0SHans de Goede         }
315f79738b0SHans de Goede     }
316f79738b0SHans de Goede }
317f79738b0SHans de Goede 
ohci_roothub_reset(OHCIState * ohci)31884d04e21SHervé Poussineau static void ohci_roothub_reset(OHCIState *ohci)
319f1ae32a1SGerd Hoffmann {
320f1ae32a1SGerd Hoffmann     OHCIPort *port;
321f1ae32a1SGerd Hoffmann     int i;
322f1ae32a1SGerd Hoffmann 
323f1ae32a1SGerd Hoffmann     ohci_bus_stop(ohci);
32484d04e21SHervé Poussineau     ohci->rhdesc_a = OHCI_RHA_NPS | ohci->num_ports;
32584d04e21SHervé Poussineau     ohci->rhdesc_b = 0x0; /* Impl. specific */
32684d04e21SHervé Poussineau     ohci->rhstatus = 0;
32784d04e21SHervé Poussineau 
32884d04e21SHervé Poussineau     for (i = 0; i < ohci->num_ports; i++) {
32984d04e21SHervé Poussineau         port = &ohci->rhport[i];
33084d04e21SHervé Poussineau         port->ctrl = 0;
33184d04e21SHervé Poussineau         if (port->port.dev && port->port.dev->attached) {
33284d04e21SHervé Poussineau             usb_port_reset(&port->port);
33384d04e21SHervé Poussineau         }
33484d04e21SHervé Poussineau     }
33584d04e21SHervé Poussineau     ohci_stop_endpoints(ohci);
33684d04e21SHervé Poussineau }
33784d04e21SHervé Poussineau 
33884d04e21SHervé Poussineau /* Reset the controller */
ohci_soft_reset(OHCIState * ohci)33984d04e21SHervé Poussineau static void ohci_soft_reset(OHCIState *ohci)
34084d04e21SHervé Poussineau {
34184d04e21SHervé Poussineau     trace_usb_ohci_reset(ohci->name);
34284d04e21SHervé Poussineau 
34384d04e21SHervé Poussineau     ohci_bus_stop(ohci);
34484d04e21SHervé Poussineau     ohci->ctl = (ohci->ctl & OHCI_CTL_IR) | OHCI_USB_SUSPEND;
345f1ae32a1SGerd Hoffmann     ohci->old_ctl = 0;
346f1ae32a1SGerd Hoffmann     ohci->status = 0;
347f1ae32a1SGerd Hoffmann     ohci->intr_status = 0;
348f1ae32a1SGerd Hoffmann     ohci->intr = OHCI_INTR_MIE;
349f1ae32a1SGerd Hoffmann 
350f1ae32a1SGerd Hoffmann     ohci->hcca = 0;
351f1ae32a1SGerd Hoffmann     ohci->ctrl_head = ohci->ctrl_cur = 0;
352f1ae32a1SGerd Hoffmann     ohci->bulk_head = ohci->bulk_cur = 0;
353f1ae32a1SGerd Hoffmann     ohci->per_cur = 0;
354f1ae32a1SGerd Hoffmann     ohci->done = 0;
355f1ae32a1SGerd Hoffmann     ohci->done_count = 7;
356572a6732SBALATON Zoltan     /*
357572a6732SBALATON Zoltan      * FSMPS is marked TBD in OCHI 1.0, what gives ffs?
358f1ae32a1SGerd Hoffmann      * I took the value linux sets ...
359f1ae32a1SGerd Hoffmann      */
360f1ae32a1SGerd Hoffmann     ohci->fsmps = 0x2778;
361f1ae32a1SGerd Hoffmann     ohci->fi = 0x2edf;
362f1ae32a1SGerd Hoffmann     ohci->fit = 0;
363f1ae32a1SGerd Hoffmann     ohci->frt = 0;
364f1ae32a1SGerd Hoffmann     ohci->frame_number = 0;
365f1ae32a1SGerd Hoffmann     ohci->pstart = 0;
366f1ae32a1SGerd Hoffmann     ohci->lst = OHCI_LS_THRESH;
36784d04e21SHervé Poussineau }
368f1ae32a1SGerd Hoffmann 
ohci_hard_reset(OHCIState * ohci)36934d97308SThomas Huth void ohci_hard_reset(OHCIState *ohci)
370f1ae32a1SGerd Hoffmann {
37184d04e21SHervé Poussineau     ohci_soft_reset(ohci);
37284d04e21SHervé Poussineau     ohci->ctl = 0;
37384d04e21SHervé Poussineau     ohci_roothub_reset(ohci);
374f1ae32a1SGerd Hoffmann }
375f1ae32a1SGerd Hoffmann 
376f1ae32a1SGerd Hoffmann /* Get an array of dwords from main memory */
get_dwords(OHCIState * ohci,dma_addr_t addr,uint32_t * buf,int num)377f1ae32a1SGerd Hoffmann static inline int get_dwords(OHCIState *ohci,
3789ac6a217SDavid Gibson                              dma_addr_t addr, uint32_t *buf, int num)
379f1ae32a1SGerd Hoffmann {
380f1ae32a1SGerd Hoffmann     int i;
381f1ae32a1SGerd Hoffmann 
382f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
383f1ae32a1SGerd Hoffmann 
384f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
385ba06fe8aSPhilippe Mathieu-Daudé         if (dma_memory_read(ohci->as, addr,
386ba06fe8aSPhilippe Mathieu-Daudé                             buf, sizeof(*buf), MEMTXATTRS_UNSPECIFIED)) {
387cf66ee8eSAlexey Kardashevskiy             return -1;
388cf66ee8eSAlexey Kardashevskiy         }
389f1ae32a1SGerd Hoffmann         *buf = le32_to_cpu(*buf);
390f1ae32a1SGerd Hoffmann     }
391f1ae32a1SGerd Hoffmann 
392cf66ee8eSAlexey Kardashevskiy     return 0;
393f1ae32a1SGerd Hoffmann }
394f1ae32a1SGerd Hoffmann 
395f1ae32a1SGerd Hoffmann /* Put an array of dwords in to main memory */
put_dwords(OHCIState * ohci,dma_addr_t addr,uint32_t * buf,int num)396f1ae32a1SGerd Hoffmann static inline int put_dwords(OHCIState *ohci,
3979ac6a217SDavid Gibson                              dma_addr_t addr, uint32_t *buf, int num)
398f1ae32a1SGerd Hoffmann {
399f1ae32a1SGerd Hoffmann     int i;
400f1ae32a1SGerd Hoffmann 
401f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
402f1ae32a1SGerd Hoffmann 
403f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
404f1ae32a1SGerd Hoffmann         uint32_t tmp = cpu_to_le32(*buf);
405ba06fe8aSPhilippe Mathieu-Daudé         if (dma_memory_write(ohci->as, addr,
406ba06fe8aSPhilippe Mathieu-Daudé                              &tmp, sizeof(tmp), MEMTXATTRS_UNSPECIFIED)) {
407cf66ee8eSAlexey Kardashevskiy             return -1;
408cf66ee8eSAlexey Kardashevskiy         }
409f1ae32a1SGerd Hoffmann     }
410f1ae32a1SGerd Hoffmann 
411cf66ee8eSAlexey Kardashevskiy     return 0;
412f1ae32a1SGerd Hoffmann }
413f1ae32a1SGerd Hoffmann 
414f1ae32a1SGerd Hoffmann /* Get an array of words from main memory */
get_words(OHCIState * ohci,dma_addr_t addr,uint16_t * buf,int num)415f1ae32a1SGerd Hoffmann static inline int get_words(OHCIState *ohci,
4169ac6a217SDavid Gibson                             dma_addr_t addr, uint16_t *buf, int num)
417f1ae32a1SGerd Hoffmann {
418f1ae32a1SGerd Hoffmann     int i;
419f1ae32a1SGerd Hoffmann 
420f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
421f1ae32a1SGerd Hoffmann 
422f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
423ba06fe8aSPhilippe Mathieu-Daudé         if (dma_memory_read(ohci->as, addr,
424ba06fe8aSPhilippe Mathieu-Daudé                             buf, sizeof(*buf), MEMTXATTRS_UNSPECIFIED)) {
425cf66ee8eSAlexey Kardashevskiy             return -1;
426cf66ee8eSAlexey Kardashevskiy         }
427f1ae32a1SGerd Hoffmann         *buf = le16_to_cpu(*buf);
428f1ae32a1SGerd Hoffmann     }
429f1ae32a1SGerd Hoffmann 
430cf66ee8eSAlexey Kardashevskiy     return 0;
431f1ae32a1SGerd Hoffmann }
432f1ae32a1SGerd Hoffmann 
433f1ae32a1SGerd Hoffmann /* Put an array of words in to main memory */
put_words(OHCIState * ohci,dma_addr_t addr,uint16_t * buf,int num)434f1ae32a1SGerd Hoffmann static inline int put_words(OHCIState *ohci,
4359ac6a217SDavid Gibson                             dma_addr_t addr, uint16_t *buf, int num)
436f1ae32a1SGerd Hoffmann {
437f1ae32a1SGerd Hoffmann     int i;
438f1ae32a1SGerd Hoffmann 
439f1ae32a1SGerd Hoffmann     addr += ohci->localmem_base;
440f1ae32a1SGerd Hoffmann 
441f1ae32a1SGerd Hoffmann     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
442f1ae32a1SGerd Hoffmann         uint16_t tmp = cpu_to_le16(*buf);
443ba06fe8aSPhilippe Mathieu-Daudé         if (dma_memory_write(ohci->as, addr,
444ba06fe8aSPhilippe Mathieu-Daudé                              &tmp, sizeof(tmp), MEMTXATTRS_UNSPECIFIED)) {
445cf66ee8eSAlexey Kardashevskiy             return -1;
446cf66ee8eSAlexey Kardashevskiy         }
447f1ae32a1SGerd Hoffmann     }
448f1ae32a1SGerd Hoffmann 
449cf66ee8eSAlexey Kardashevskiy     return 0;
450f1ae32a1SGerd Hoffmann }
451f1ae32a1SGerd Hoffmann 
ohci_read_ed(OHCIState * ohci,dma_addr_t addr,struct ohci_ed * ed)452f1ae32a1SGerd Hoffmann static inline int ohci_read_ed(OHCIState *ohci,
4539ac6a217SDavid Gibson                                dma_addr_t addr, struct ohci_ed *ed)
454f1ae32a1SGerd Hoffmann {
455f1ae32a1SGerd Hoffmann     return get_dwords(ohci, addr, (uint32_t *)ed, sizeof(*ed) >> 2);
456f1ae32a1SGerd Hoffmann }
457f1ae32a1SGerd Hoffmann 
ohci_read_td(OHCIState * ohci,dma_addr_t addr,struct ohci_td * td)458f1ae32a1SGerd Hoffmann static inline int ohci_read_td(OHCIState *ohci,
4599ac6a217SDavid Gibson                                dma_addr_t addr, struct ohci_td *td)
460f1ae32a1SGerd Hoffmann {
461f1ae32a1SGerd Hoffmann     return get_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2);
462f1ae32a1SGerd Hoffmann }
463f1ae32a1SGerd Hoffmann 
ohci_read_iso_td(OHCIState * ohci,dma_addr_t addr,struct ohci_iso_td * td)464f1ae32a1SGerd Hoffmann static inline int ohci_read_iso_td(OHCIState *ohci,
4659ac6a217SDavid Gibson                                    dma_addr_t addr, struct ohci_iso_td *td)
466f1ae32a1SGerd Hoffmann {
467cf66ee8eSAlexey Kardashevskiy     return get_dwords(ohci, addr, (uint32_t *)td, 4) ||
468cf66ee8eSAlexey Kardashevskiy            get_words(ohci, addr + 16, td->offset, 8);
469f1ae32a1SGerd Hoffmann }
470f1ae32a1SGerd Hoffmann 
ohci_read_hcca(OHCIState * ohci,dma_addr_t addr,struct ohci_hcca * hcca)471f1ae32a1SGerd Hoffmann static inline int ohci_read_hcca(OHCIState *ohci,
4729ac6a217SDavid Gibson                                  dma_addr_t addr, struct ohci_hcca *hcca)
473f1ae32a1SGerd Hoffmann {
474ba06fe8aSPhilippe Mathieu-Daudé     return dma_memory_read(ohci->as, addr + ohci->localmem_base, hcca,
475ba06fe8aSPhilippe Mathieu-Daudé                            sizeof(*hcca), MEMTXATTRS_UNSPECIFIED);
476f1ae32a1SGerd Hoffmann }
477f1ae32a1SGerd Hoffmann 
ohci_put_ed(OHCIState * ohci,dma_addr_t addr,struct ohci_ed * ed)478f1ae32a1SGerd Hoffmann static inline int ohci_put_ed(OHCIState *ohci,
4799ac6a217SDavid Gibson                               dma_addr_t addr, struct ohci_ed *ed)
480f1ae32a1SGerd Hoffmann {
481572a6732SBALATON Zoltan     /*
482572a6732SBALATON Zoltan      * ed->tail is under control of the HCD.
48386e18caeSWei Yang      * Since just ed->head is changed by HC, just write back this
48486e18caeSWei Yang      */
48586e18caeSWei Yang     return put_dwords(ohci, addr + ED_WBACK_OFFSET,
48686e18caeSWei Yang                       (uint32_t *)((char *)ed + ED_WBACK_OFFSET),
48786e18caeSWei Yang                       ED_WBACK_SIZE >> 2);
488f1ae32a1SGerd Hoffmann }
489f1ae32a1SGerd Hoffmann 
ohci_put_td(OHCIState * ohci,dma_addr_t addr,struct ohci_td * td)490f1ae32a1SGerd Hoffmann static inline int ohci_put_td(OHCIState *ohci,
4919ac6a217SDavid Gibson                               dma_addr_t addr, struct ohci_td *td)
492f1ae32a1SGerd Hoffmann {
493f1ae32a1SGerd Hoffmann     return put_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2);
494f1ae32a1SGerd Hoffmann }
495f1ae32a1SGerd Hoffmann 
ohci_put_iso_td(OHCIState * ohci,dma_addr_t addr,struct ohci_iso_td * td)496f1ae32a1SGerd Hoffmann static inline int ohci_put_iso_td(OHCIState *ohci,
4979ac6a217SDavid Gibson                                   dma_addr_t addr, struct ohci_iso_td *td)
498f1ae32a1SGerd Hoffmann {
499cae7f29cSJack Un     return put_dwords(ohci, addr, (uint32_t *)td, 4) ||
500cae7f29cSJack Un            put_words(ohci, addr + 16, td->offset, 8);
501f1ae32a1SGerd Hoffmann }
502f1ae32a1SGerd Hoffmann 
ohci_put_hcca(OHCIState * ohci,dma_addr_t addr,struct ohci_hcca * hcca)503f1ae32a1SGerd Hoffmann static inline int ohci_put_hcca(OHCIState *ohci,
5049ac6a217SDavid Gibson                                 dma_addr_t addr, struct ohci_hcca *hcca)
505f1ae32a1SGerd Hoffmann {
506cf66ee8eSAlexey Kardashevskiy     return dma_memory_write(ohci->as,
5079ac6a217SDavid Gibson                             addr + ohci->localmem_base + HCCA_WRITEBACK_OFFSET,
50886e18caeSWei Yang                             (char *)hcca + HCCA_WRITEBACK_OFFSET,
509ba06fe8aSPhilippe Mathieu-Daudé                             HCCA_WRITEBACK_SIZE, MEMTXATTRS_UNSPECIFIED);
510f1ae32a1SGerd Hoffmann }
511f1ae32a1SGerd Hoffmann 
512f1ae32a1SGerd Hoffmann /* Read/Write the contents of a TD from/to main memory.  */
ohci_copy_td(OHCIState * ohci,struct ohci_td * td,uint8_t * buf,int len,DMADirection dir)513cf66ee8eSAlexey Kardashevskiy static int ohci_copy_td(OHCIState *ohci, struct ohci_td *td,
5149ac6a217SDavid Gibson                         uint8_t *buf, int len, DMADirection dir)
515f1ae32a1SGerd Hoffmann {
5169ac6a217SDavid Gibson     dma_addr_t ptr, n;
517f1ae32a1SGerd Hoffmann 
518f1ae32a1SGerd Hoffmann     ptr = td->cbp;
519f1ae32a1SGerd Hoffmann     n = 0x1000 - (ptr & 0xfff);
5201e58e7a0SBALATON Zoltan     if (n > len) {
521f1ae32a1SGerd Hoffmann         n = len;
5221e58e7a0SBALATON Zoltan     }
52323faf569SPhilippe Mathieu-Daudé     if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf,
52423faf569SPhilippe Mathieu-Daudé                       n, dir, MEMTXATTRS_UNSPECIFIED)) {
525cf66ee8eSAlexey Kardashevskiy         return -1;
526cf66ee8eSAlexey Kardashevskiy     }
527cf66ee8eSAlexey Kardashevskiy     if (n == len) {
528cf66ee8eSAlexey Kardashevskiy         return 0;
529cf66ee8eSAlexey Kardashevskiy     }
530f1ae32a1SGerd Hoffmann     ptr = td->be & ~0xfffu;
531f1ae32a1SGerd Hoffmann     buf += n;
532cf66ee8eSAlexey Kardashevskiy     if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf,
53323faf569SPhilippe Mathieu-Daudé                       len - n, dir, MEMTXATTRS_UNSPECIFIED)) {
534cf66ee8eSAlexey Kardashevskiy         return -1;
535cf66ee8eSAlexey Kardashevskiy     }
536cf66ee8eSAlexey Kardashevskiy     return 0;
537f1ae32a1SGerd Hoffmann }
538f1ae32a1SGerd Hoffmann 
539f1ae32a1SGerd Hoffmann /* Read/Write the contents of an ISO TD from/to main memory.  */
ohci_copy_iso_td(OHCIState * ohci,uint32_t start_addr,uint32_t end_addr,uint8_t * buf,int len,DMADirection dir)540cf66ee8eSAlexey Kardashevskiy static int ohci_copy_iso_td(OHCIState *ohci,
541f1ae32a1SGerd Hoffmann                             uint32_t start_addr, uint32_t end_addr,
5429ac6a217SDavid Gibson                             uint8_t *buf, int len, DMADirection dir)
543f1ae32a1SGerd Hoffmann {
5449ac6a217SDavid Gibson     dma_addr_t ptr, n;
545f1ae32a1SGerd Hoffmann 
546f1ae32a1SGerd Hoffmann     ptr = start_addr;
547f1ae32a1SGerd Hoffmann     n = 0x1000 - (ptr & 0xfff);
5481e58e7a0SBALATON Zoltan     if (n > len) {
549f1ae32a1SGerd Hoffmann         n = len;
5501e58e7a0SBALATON Zoltan     }
55123faf569SPhilippe Mathieu-Daudé     if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf,
55223faf569SPhilippe Mathieu-Daudé                       n, dir, MEMTXATTRS_UNSPECIFIED)) {
553cf66ee8eSAlexey Kardashevskiy         return -1;
554cf66ee8eSAlexey Kardashevskiy     }
555cf66ee8eSAlexey Kardashevskiy     if (n == len) {
556cf66ee8eSAlexey Kardashevskiy         return 0;
557cf66ee8eSAlexey Kardashevskiy     }
558f1ae32a1SGerd Hoffmann     ptr = end_addr & ~0xfffu;
559f1ae32a1SGerd Hoffmann     buf += n;
560cf66ee8eSAlexey Kardashevskiy     if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf,
56123faf569SPhilippe Mathieu-Daudé                       len - n, dir, MEMTXATTRS_UNSPECIFIED)) {
562cf66ee8eSAlexey Kardashevskiy         return -1;
563cf66ee8eSAlexey Kardashevskiy     }
564cf66ee8eSAlexey Kardashevskiy     return 0;
565f1ae32a1SGerd Hoffmann }
566f1ae32a1SGerd Hoffmann 
567f1ae32a1SGerd Hoffmann #define USUB(a, b) ((int16_t)((uint16_t)(a) - (uint16_t)(b)))
568f1ae32a1SGerd Hoffmann 
ohci_service_iso_td(OHCIState * ohci,struct ohci_ed * ed)5693a4d06f2SBALATON Zoltan static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed)
570f1ae32a1SGerd Hoffmann {
571f1ae32a1SGerd Hoffmann     int dir;
572f1ae32a1SGerd Hoffmann     size_t len = 0;
573f1ae32a1SGerd Hoffmann     const char *str = NULL;
574f1ae32a1SGerd Hoffmann     int pid;
575f1ae32a1SGerd Hoffmann     int ret;
576f1ae32a1SGerd Hoffmann     int i;
577f1ae32a1SGerd Hoffmann     USBDevice *dev;
578f1ae32a1SGerd Hoffmann     USBEndpoint *ep;
5793a4d06f2SBALATON Zoltan     USBPacket *pkt;
5803a4d06f2SBALATON Zoltan     uint8_t buf[8192];
5813a4d06f2SBALATON Zoltan     bool int_req;
582f1ae32a1SGerd Hoffmann     struct ohci_iso_td iso_td;
583f1ae32a1SGerd Hoffmann     uint32_t addr;
584f1ae32a1SGerd Hoffmann     uint16_t starting_frame;
585f1ae32a1SGerd Hoffmann     int16_t relative_frame_number;
586f1ae32a1SGerd Hoffmann     int frame_count;
587f1ae32a1SGerd Hoffmann     uint32_t start_offset, next_offset, end_offset = 0;
588f1ae32a1SGerd Hoffmann     uint32_t start_addr, end_addr;
589f1ae32a1SGerd Hoffmann 
590f1ae32a1SGerd Hoffmann     addr = ed->head & OHCI_DPTR_MASK;
591f1ae32a1SGerd Hoffmann 
592d8c2e6f2SQiang Liu     if (addr == 0) {
593d8c2e6f2SQiang Liu         ohci_die(ohci);
594d8c2e6f2SQiang Liu         return 1;
595d8c2e6f2SQiang Liu     }
596d8c2e6f2SQiang Liu 
597cf66ee8eSAlexey Kardashevskiy     if (ohci_read_iso_td(ohci, addr, &iso_td)) {
598dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_read_failed(addr);
599cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
60026f670a2SLi Qiang         return 1;
601f1ae32a1SGerd Hoffmann     }
602f1ae32a1SGerd Hoffmann 
603f1ae32a1SGerd Hoffmann     starting_frame = OHCI_BM(iso_td.flags, TD_SF);
604f1ae32a1SGerd Hoffmann     frame_count = OHCI_BM(iso_td.flags, TD_FC);
605f1ae32a1SGerd Hoffmann     relative_frame_number = USUB(ohci->frame_number, starting_frame);
606f1ae32a1SGerd Hoffmann 
607dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_iso_td_head(
608f1ae32a1SGerd Hoffmann            ed->head & OHCI_DPTR_MASK, ed->tail & OHCI_DPTR_MASK,
609f1ae32a1SGerd Hoffmann            iso_td.flags, iso_td.bp, iso_td.next, iso_td.be,
610f1ae32a1SGerd Hoffmann            ohci->frame_number, starting_frame,
611bc0d104cSAlex Bennée            frame_count, relative_frame_number);
6123af8f177SAlexey Kardashevskiy     trace_usb_ohci_iso_td_head_offset(
6133af8f177SAlexey Kardashevskiy            iso_td.offset[0], iso_td.offset[1],
6143af8f177SAlexey Kardashevskiy            iso_td.offset[2], iso_td.offset[3],
6153af8f177SAlexey Kardashevskiy            iso_td.offset[4], iso_td.offset[5],
6163af8f177SAlexey Kardashevskiy            iso_td.offset[6], iso_td.offset[7]);
617f1ae32a1SGerd Hoffmann 
618f1ae32a1SGerd Hoffmann     if (relative_frame_number < 0) {
619dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_relative_frame_number_neg(relative_frame_number);
620f1ae32a1SGerd Hoffmann         return 1;
621f1ae32a1SGerd Hoffmann     } else if (relative_frame_number > frame_count) {
622572a6732SBALATON Zoltan         /*
623572a6732SBALATON Zoltan          * ISO TD expired - retire the TD to the Done Queue and continue with
624572a6732SBALATON Zoltan          * the next ISO TD of the same ED
625572a6732SBALATON Zoltan          */
626dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_relative_frame_number_big(relative_frame_number,
627f1ae32a1SGerd Hoffmann                                                         frame_count);
6281be90ebeSPrasad J Pandit         if (OHCI_CC_DATAOVERRUN == OHCI_BM(iso_td.flags, TD_CC)) {
6291be90ebeSPrasad J Pandit             /* avoid infinite loop */
6301be90ebeSPrasad J Pandit             return 1;
6311be90ebeSPrasad J Pandit         }
632f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_DATAOVERRUN);
633f1ae32a1SGerd Hoffmann         ed->head &= ~OHCI_DPTR_MASK;
634f1ae32a1SGerd Hoffmann         ed->head |= (iso_td.next & OHCI_DPTR_MASK);
635f1ae32a1SGerd Hoffmann         iso_td.next = ohci->done;
636f1ae32a1SGerd Hoffmann         ohci->done = addr;
637f1ae32a1SGerd Hoffmann         i = OHCI_BM(iso_td.flags, TD_DI);
6381e58e7a0SBALATON Zoltan         if (i < ohci->done_count) {
639f1ae32a1SGerd Hoffmann             ohci->done_count = i;
6401e58e7a0SBALATON Zoltan         }
641cf66ee8eSAlexey Kardashevskiy         if (ohci_put_iso_td(ohci, addr, &iso_td)) {
642cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
643cf66ee8eSAlexey Kardashevskiy             return 1;
644cf66ee8eSAlexey Kardashevskiy         }
645f1ae32a1SGerd Hoffmann         return 0;
646f1ae32a1SGerd Hoffmann     }
647f1ae32a1SGerd Hoffmann 
648f1ae32a1SGerd Hoffmann     dir = OHCI_BM(ed->flags, ED_D);
649f1ae32a1SGerd Hoffmann     switch (dir) {
650f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_IN:
651f1ae32a1SGerd Hoffmann         str = "in";
652f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_IN;
653f1ae32a1SGerd Hoffmann         break;
654f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_OUT:
655f1ae32a1SGerd Hoffmann         str = "out";
656f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_OUT;
657f1ae32a1SGerd Hoffmann         break;
658f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_SETUP:
659f1ae32a1SGerd Hoffmann         str = "setup";
660f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_SETUP;
661f1ae32a1SGerd Hoffmann         break;
662f1ae32a1SGerd Hoffmann     default:
663dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_bad_direction(dir);
664f1ae32a1SGerd Hoffmann         return 1;
665f1ae32a1SGerd Hoffmann     }
666f1ae32a1SGerd Hoffmann 
667f1ae32a1SGerd Hoffmann     if (!iso_td.bp || !iso_td.be) {
668dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_bad_bp_be(iso_td.bp, iso_td.be);
669f1ae32a1SGerd Hoffmann         return 1;
670f1ae32a1SGerd Hoffmann     }
671f1ae32a1SGerd Hoffmann 
672f1ae32a1SGerd Hoffmann     start_offset = iso_td.offset[relative_frame_number];
6731328fe0cSPrasad J Pandit     if (relative_frame_number < frame_count) {
674f1ae32a1SGerd Hoffmann         next_offset = iso_td.offset[relative_frame_number + 1];
6751328fe0cSPrasad J Pandit     } else {
6761328fe0cSPrasad J Pandit         next_offset = iso_td.be;
6771328fe0cSPrasad J Pandit     }
678f1ae32a1SGerd Hoffmann 
679f1ae32a1SGerd Hoffmann     if (!(OHCI_BM(start_offset, TD_PSW_CC) & 0xe) ||
680f1ae32a1SGerd Hoffmann         ((relative_frame_number < frame_count) &&
681f1ae32a1SGerd Hoffmann          !(OHCI_BM(next_offset, TD_PSW_CC) & 0xe))) {
682dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_bad_cc_not_accessed(start_offset, next_offset);
683f1ae32a1SGerd Hoffmann         return 1;
684f1ae32a1SGerd Hoffmann     }
685f1ae32a1SGerd Hoffmann 
686f1ae32a1SGerd Hoffmann     if ((relative_frame_number < frame_count) && (start_offset > next_offset)) {
687dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_iso_td_bad_cc_overrun(start_offset, next_offset);
688f1ae32a1SGerd Hoffmann         return 1;
689f1ae32a1SGerd Hoffmann     }
690f1ae32a1SGerd Hoffmann 
691f1ae32a1SGerd Hoffmann     if ((start_offset & 0x1000) == 0) {
692f1ae32a1SGerd Hoffmann         start_addr = (iso_td.bp & OHCI_PAGE_MASK) |
693f1ae32a1SGerd Hoffmann             (start_offset & OHCI_OFFSET_MASK);
694f1ae32a1SGerd Hoffmann     } else {
695f1ae32a1SGerd Hoffmann         start_addr = (iso_td.be & OHCI_PAGE_MASK) |
696f1ae32a1SGerd Hoffmann             (start_offset & OHCI_OFFSET_MASK);
697f1ae32a1SGerd Hoffmann     }
698f1ae32a1SGerd Hoffmann 
699f1ae32a1SGerd Hoffmann     if (relative_frame_number < frame_count) {
700f1ae32a1SGerd Hoffmann         end_offset = next_offset - 1;
701f1ae32a1SGerd Hoffmann         if ((end_offset & 0x1000) == 0) {
702f1ae32a1SGerd Hoffmann             end_addr = (iso_td.bp & OHCI_PAGE_MASK) |
703f1ae32a1SGerd Hoffmann                 (end_offset & OHCI_OFFSET_MASK);
704f1ae32a1SGerd Hoffmann         } else {
705f1ae32a1SGerd Hoffmann             end_addr = (iso_td.be & OHCI_PAGE_MASK) |
706f1ae32a1SGerd Hoffmann                 (end_offset & OHCI_OFFSET_MASK);
707f1ae32a1SGerd Hoffmann         }
708f1ae32a1SGerd Hoffmann     } else {
709f1ae32a1SGerd Hoffmann         /* Last packet in the ISO TD */
7101328fe0cSPrasad J Pandit         end_addr = next_offset;
7111328fe0cSPrasad J Pandit     }
7121328fe0cSPrasad J Pandit 
7131328fe0cSPrasad J Pandit     if (start_addr > end_addr) {
7141328fe0cSPrasad J Pandit         trace_usb_ohci_iso_td_bad_cc_overrun(start_addr, end_addr);
7151328fe0cSPrasad J Pandit         return 1;
716f1ae32a1SGerd Hoffmann     }
717f1ae32a1SGerd Hoffmann 
718f1ae32a1SGerd Hoffmann     if ((start_addr & OHCI_PAGE_MASK) != (end_addr & OHCI_PAGE_MASK)) {
719f1ae32a1SGerd Hoffmann         len = (end_addr & OHCI_OFFSET_MASK) + 0x1001
720f1ae32a1SGerd Hoffmann             - (start_addr & OHCI_OFFSET_MASK);
721f1ae32a1SGerd Hoffmann     } else {
722f1ae32a1SGerd Hoffmann         len = end_addr - start_addr + 1;
723f1ae32a1SGerd Hoffmann     }
7243a4d06f2SBALATON Zoltan     if (len > sizeof(buf)) {
7253a4d06f2SBALATON Zoltan         len = sizeof(buf);
7261328fe0cSPrasad J Pandit     }
727f1ae32a1SGerd Hoffmann 
728f1ae32a1SGerd Hoffmann     if (len && dir != OHCI_TD_DIR_IN) {
7293a4d06f2SBALATON Zoltan         if (ohci_copy_iso_td(ohci, start_addr, end_addr, buf, len,
730cf66ee8eSAlexey Kardashevskiy                              DMA_DIRECTION_TO_DEVICE)) {
731cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
732cf66ee8eSAlexey Kardashevskiy             return 1;
733cf66ee8eSAlexey Kardashevskiy         }
734f1ae32a1SGerd Hoffmann     }
735f1ae32a1SGerd Hoffmann 
736f1ae32a1SGerd Hoffmann     dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
73742340fc3SLiam Merwick     if (dev == NULL) {
73842340fc3SLiam Merwick         trace_usb_ohci_td_dev_error();
73942340fc3SLiam Merwick         return 1;
74042340fc3SLiam Merwick     }
741f1ae32a1SGerd Hoffmann     ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
7423a4d06f2SBALATON Zoltan     pkt = g_new0(USBPacket, 1);
7433a4d06f2SBALATON Zoltan     usb_packet_init(pkt);
7443a4d06f2SBALATON Zoltan     int_req = relative_frame_number == frame_count &&
7453a4d06f2SBALATON Zoltan               OHCI_BM(iso_td.flags, TD_DI) == 0;
7463a4d06f2SBALATON Zoltan     usb_packet_setup(pkt, pid, ep, 0, addr, false, int_req);
7473a4d06f2SBALATON Zoltan     usb_packet_addbuf(pkt, buf, len);
7483a4d06f2SBALATON Zoltan     usb_handle_packet(dev, pkt);
7493a4d06f2SBALATON Zoltan     if (pkt->status == USB_RET_ASYNC) {
75036dfe324SHans de Goede         usb_device_flush_ep_queue(dev, ep);
7513a4d06f2SBALATON Zoltan         g_free(pkt);
752f1ae32a1SGerd Hoffmann         return 1;
753f1ae32a1SGerd Hoffmann     }
7543a4d06f2SBALATON Zoltan     if (pkt->status == USB_RET_SUCCESS) {
7553a4d06f2SBALATON Zoltan         ret = pkt->actual_length;
7569a77a0f5SHans de Goede     } else {
7573a4d06f2SBALATON Zoltan         ret = pkt->status;
7589a77a0f5SHans de Goede     }
7593a4d06f2SBALATON Zoltan     g_free(pkt);
760f1ae32a1SGerd Hoffmann 
761dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_iso_td_so(start_offset, end_offset, start_addr, end_addr,
762dc1f5988SAlexey Kardashevskiy                              str, len, ret);
763f1ae32a1SGerd Hoffmann 
764f1ae32a1SGerd Hoffmann     /* Writeback */
765f1ae32a1SGerd Hoffmann     if (dir == OHCI_TD_DIR_IN && ret >= 0 && ret <= len) {
766f1ae32a1SGerd Hoffmann         /* IN transfer succeeded */
7673a4d06f2SBALATON Zoltan         if (ohci_copy_iso_td(ohci, start_addr, end_addr, buf, ret,
768cf66ee8eSAlexey Kardashevskiy                              DMA_DIRECTION_FROM_DEVICE)) {
769cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
770cf66ee8eSAlexey Kardashevskiy             return 1;
771cf66ee8eSAlexey Kardashevskiy         }
772f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
773f1ae32a1SGerd Hoffmann                     OHCI_CC_NOERROR);
774f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, ret);
775f1ae32a1SGerd Hoffmann     } else if (dir == OHCI_TD_DIR_OUT && ret == len) {
776f1ae32a1SGerd Hoffmann         /* OUT transfer succeeded */
777f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
778f1ae32a1SGerd Hoffmann                     OHCI_CC_NOERROR);
779f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 0);
780f1ae32a1SGerd Hoffmann     } else {
781f1ae32a1SGerd Hoffmann         if (ret > (ssize_t) len) {
782dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_iso_td_data_overrun(ret, len);
783f1ae32a1SGerd Hoffmann             OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
784f1ae32a1SGerd Hoffmann                         OHCI_CC_DATAOVERRUN);
785f1ae32a1SGerd Hoffmann             OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
786f1ae32a1SGerd Hoffmann                         len);
787f1ae32a1SGerd Hoffmann         } else if (ret >= 0) {
788dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_iso_td_data_underrun(ret);
789f1ae32a1SGerd Hoffmann             OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
790f1ae32a1SGerd Hoffmann                         OHCI_CC_DATAUNDERRUN);
791f1ae32a1SGerd Hoffmann         } else {
792f1ae32a1SGerd Hoffmann             switch (ret) {
793f1ae32a1SGerd Hoffmann             case USB_RET_IOERROR:
794f1ae32a1SGerd Hoffmann             case USB_RET_NODEV:
795f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
796f1ae32a1SGerd Hoffmann                             OHCI_CC_DEVICENOTRESPONDING);
797f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
798f1ae32a1SGerd Hoffmann                             0);
799f1ae32a1SGerd Hoffmann                 break;
800f1ae32a1SGerd Hoffmann             case USB_RET_NAK:
801f1ae32a1SGerd Hoffmann             case USB_RET_STALL:
802dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_iso_td_nak(ret);
803f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
804f1ae32a1SGerd Hoffmann                             OHCI_CC_STALL);
805f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
806f1ae32a1SGerd Hoffmann                             0);
807f1ae32a1SGerd Hoffmann                 break;
808f1ae32a1SGerd Hoffmann             default:
809dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_iso_td_bad_response(ret);
810f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
811f1ae32a1SGerd Hoffmann                             OHCI_CC_UNDEXPETEDPID);
812f1ae32a1SGerd Hoffmann                 break;
813f1ae32a1SGerd Hoffmann             }
814f1ae32a1SGerd Hoffmann         }
815f1ae32a1SGerd Hoffmann     }
816f1ae32a1SGerd Hoffmann 
817f1ae32a1SGerd Hoffmann     if (relative_frame_number == frame_count) {
818f1ae32a1SGerd Hoffmann         /* Last data packet of ISO TD - retire the TD to the Done Queue */
819f1ae32a1SGerd Hoffmann         OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_NOERROR);
820f1ae32a1SGerd Hoffmann         ed->head &= ~OHCI_DPTR_MASK;
821f1ae32a1SGerd Hoffmann         ed->head |= (iso_td.next & OHCI_DPTR_MASK);
822f1ae32a1SGerd Hoffmann         iso_td.next = ohci->done;
823f1ae32a1SGerd Hoffmann         ohci->done = addr;
824f1ae32a1SGerd Hoffmann         i = OHCI_BM(iso_td.flags, TD_DI);
8251e58e7a0SBALATON Zoltan         if (i < ohci->done_count) {
826f1ae32a1SGerd Hoffmann             ohci->done_count = i;
827f1ae32a1SGerd Hoffmann         }
8281e58e7a0SBALATON Zoltan     }
829cf66ee8eSAlexey Kardashevskiy     if (ohci_put_iso_td(ohci, addr, &iso_td)) {
830cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
831cf66ee8eSAlexey Kardashevskiy     }
832f1ae32a1SGerd Hoffmann     return 1;
833f1ae32a1SGerd Hoffmann }
834f1ae32a1SGerd Hoffmann 
83529d81e42SPhilippe Mathieu-Daudé #define HEX_CHAR_PER_LINE 16
83629d81e42SPhilippe Mathieu-Daudé 
ohci_td_pkt(const char * msg,const uint8_t * buf,size_t len)837dc1f5988SAlexey Kardashevskiy static void ohci_td_pkt(const char *msg, const uint8_t *buf, size_t len)
838dc1f5988SAlexey Kardashevskiy {
839d87aa138SStefan Hajnoczi     bool print16;
840d87aa138SStefan Hajnoczi     bool printall;
841dc1f5988SAlexey Kardashevskiy     int i;
84229d81e42SPhilippe Mathieu-Daudé     char tmp[3 * HEX_CHAR_PER_LINE + 1];
843dc1f5988SAlexey Kardashevskiy     char *p = tmp;
844dc1f5988SAlexey Kardashevskiy 
845d87aa138SStefan Hajnoczi     print16 = !!trace_event_get_state_backends(TRACE_USB_OHCI_TD_PKT_SHORT);
846d87aa138SStefan Hajnoczi     printall = !!trace_event_get_state_backends(TRACE_USB_OHCI_TD_PKT_FULL);
847d87aa138SStefan Hajnoczi 
848dc1f5988SAlexey Kardashevskiy     if (!printall && !print16) {
849dc1f5988SAlexey Kardashevskiy         return;
850dc1f5988SAlexey Kardashevskiy     }
851dc1f5988SAlexey Kardashevskiy 
852dc1f5988SAlexey Kardashevskiy     for (i = 0; ; i++) {
85329d81e42SPhilippe Mathieu-Daudé         if (i && (!(i % HEX_CHAR_PER_LINE) || (i == len))) {
854dc1f5988SAlexey Kardashevskiy             if (!printall) {
855dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_pkt_short(msg, tmp);
856dc1f5988SAlexey Kardashevskiy                 break;
857dc1f5988SAlexey Kardashevskiy             }
858dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_td_pkt_full(msg, tmp);
859dc1f5988SAlexey Kardashevskiy             p = tmp;
860dc1f5988SAlexey Kardashevskiy             *p = 0;
861dc1f5988SAlexey Kardashevskiy         }
862dc1f5988SAlexey Kardashevskiy         if (i == len) {
863dc1f5988SAlexey Kardashevskiy             break;
864dc1f5988SAlexey Kardashevskiy         }
865dc1f5988SAlexey Kardashevskiy 
866dc1f5988SAlexey Kardashevskiy         p += sprintf(p, " %.2x", buf[i]);
867dc1f5988SAlexey Kardashevskiy     }
868dc1f5988SAlexey Kardashevskiy }
869dc1f5988SAlexey Kardashevskiy 
870572a6732SBALATON Zoltan /*
871572a6732SBALATON Zoltan  * Service a transport descriptor.
872572a6732SBALATON Zoltan  * Returns nonzero to terminate processing of this endpoint.
873572a6732SBALATON Zoltan  */
ohci_service_td(OHCIState * ohci,struct ohci_ed * ed)874f1ae32a1SGerd Hoffmann static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
875f1ae32a1SGerd Hoffmann {
876f1ae32a1SGerd Hoffmann     int dir;
877f1ae32a1SGerd Hoffmann     size_t len = 0, pktlen = 0;
878f1ae32a1SGerd Hoffmann     const char *str = NULL;
879f1ae32a1SGerd Hoffmann     int pid;
880f1ae32a1SGerd Hoffmann     int ret;
881f1ae32a1SGerd Hoffmann     int i;
882f1ae32a1SGerd Hoffmann     USBDevice *dev;
883f1ae32a1SGerd Hoffmann     USBEndpoint *ep;
884f1ae32a1SGerd Hoffmann     struct ohci_td td;
885f1ae32a1SGerd Hoffmann     uint32_t addr;
886f1ae32a1SGerd Hoffmann     int flag_r;
887f1ae32a1SGerd Hoffmann     int completion;
888f1ae32a1SGerd Hoffmann 
889f1ae32a1SGerd Hoffmann     addr = ed->head & OHCI_DPTR_MASK;
890d8c2e6f2SQiang Liu     if (addr == 0) {
891d8c2e6f2SQiang Liu         ohci_die(ohci);
892d8c2e6f2SQiang Liu         return 1;
893d8c2e6f2SQiang Liu     }
894d8c2e6f2SQiang Liu 
895f1ae32a1SGerd Hoffmann     /* See if this TD has already been submitted to the device. */
896f1ae32a1SGerd Hoffmann     completion = (addr == ohci->async_td);
897f1ae32a1SGerd Hoffmann     if (completion && !ohci->async_complete) {
898dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_td_skip_async();
899f1ae32a1SGerd Hoffmann         return 1;
900f1ae32a1SGerd Hoffmann     }
901cf66ee8eSAlexey Kardashevskiy     if (ohci_read_td(ohci, addr, &td)) {
902dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_td_read_error(addr);
903cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
9046ebc069dSLi Qiang         return 1;
905f1ae32a1SGerd Hoffmann     }
906f1ae32a1SGerd Hoffmann 
907f1ae32a1SGerd Hoffmann     dir = OHCI_BM(ed->flags, ED_D);
908f1ae32a1SGerd Hoffmann     switch (dir) {
909f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_OUT:
910f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_IN:
911f1ae32a1SGerd Hoffmann         /* Same value. */
912f1ae32a1SGerd Hoffmann         break;
913f1ae32a1SGerd Hoffmann     default:
914f1ae32a1SGerd Hoffmann         dir = OHCI_BM(td.flags, TD_DP);
915f1ae32a1SGerd Hoffmann         break;
916f1ae32a1SGerd Hoffmann     }
917f1ae32a1SGerd Hoffmann 
918f1ae32a1SGerd Hoffmann     switch (dir) {
919f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_IN:
920f1ae32a1SGerd Hoffmann         str = "in";
921f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_IN;
922f1ae32a1SGerd Hoffmann         break;
923f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_OUT:
924f1ae32a1SGerd Hoffmann         str = "out";
925f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_OUT;
926f1ae32a1SGerd Hoffmann         break;
927f1ae32a1SGerd Hoffmann     case OHCI_TD_DIR_SETUP:
928f1ae32a1SGerd Hoffmann         str = "setup";
929f1ae32a1SGerd Hoffmann         pid = USB_TOKEN_SETUP;
930f1ae32a1SGerd Hoffmann         break;
931f1ae32a1SGerd Hoffmann     default:
932dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_td_bad_direction(dir);
933f1ae32a1SGerd Hoffmann         return 1;
934f1ae32a1SGerd Hoffmann     }
935f1ae32a1SGerd Hoffmann     if (td.cbp && td.be) {
936f1ae32a1SGerd Hoffmann         if ((td.cbp & 0xfffff000) != (td.be & 0xfffff000)) {
937f1ae32a1SGerd Hoffmann             len = (td.be & 0xfff) + 0x1001 - (td.cbp & 0xfff);
938f1ae32a1SGerd Hoffmann         } else {
9391328fe0cSPrasad J Pandit             if (td.cbp > td.be) {
9401328fe0cSPrasad J Pandit                 trace_usb_ohci_iso_td_bad_cc_overrun(td.cbp, td.be);
9411328fe0cSPrasad J Pandit                 ohci_die(ohci);
9421328fe0cSPrasad J Pandit                 return 1;
9431328fe0cSPrasad J Pandit             }
944f1ae32a1SGerd Hoffmann             len = (td.be - td.cbp) + 1;
945f1ae32a1SGerd Hoffmann         }
9461328fe0cSPrasad J Pandit         if (len > sizeof(ohci->usb_buf)) {
9471328fe0cSPrasad J Pandit             len = sizeof(ohci->usb_buf);
9481328fe0cSPrasad J Pandit         }
949f1ae32a1SGerd Hoffmann 
950f1ae32a1SGerd Hoffmann         pktlen = len;
951f1ae32a1SGerd Hoffmann         if (len && dir != OHCI_TD_DIR_IN) {
952f1ae32a1SGerd Hoffmann             /* The endpoint may not allow us to transfer it all now */
953f1ae32a1SGerd Hoffmann             pktlen = (ed->flags & OHCI_ED_MPS_MASK) >> OHCI_ED_MPS_SHIFT;
954f1ae32a1SGerd Hoffmann             if (pktlen > len) {
955f1ae32a1SGerd Hoffmann                 pktlen = len;
956f1ae32a1SGerd Hoffmann             }
957f1ae32a1SGerd Hoffmann             if (!completion) {
958cf66ee8eSAlexey Kardashevskiy                 if (ohci_copy_td(ohci, &td, ohci->usb_buf, pktlen,
959cf66ee8eSAlexey Kardashevskiy                                  DMA_DIRECTION_TO_DEVICE)) {
960cf66ee8eSAlexey Kardashevskiy                     ohci_die(ohci);
961cf66ee8eSAlexey Kardashevskiy                 }
962f1ae32a1SGerd Hoffmann             }
963f1ae32a1SGerd Hoffmann         }
964f1ae32a1SGerd Hoffmann     }
965f1ae32a1SGerd Hoffmann 
966f1ae32a1SGerd Hoffmann     flag_r = (td.flags & OHCI_TD_R) != 0;
967dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_td_pkt_hdr(addr, (int64_t)pktlen, (int64_t)len, str,
968dc1f5988SAlexey Kardashevskiy                               flag_r, td.cbp, td.be);
969dc1f5988SAlexey Kardashevskiy     ohci_td_pkt("OUT", ohci->usb_buf, pktlen);
970f1ae32a1SGerd Hoffmann 
971f1ae32a1SGerd Hoffmann     if (completion) {
972f1ae32a1SGerd Hoffmann         ohci->async_td = 0;
97369e25d26SAlexey Kardashevskiy         ohci->async_complete = false;
974f1ae32a1SGerd Hoffmann     } else {
975f1ae32a1SGerd Hoffmann         dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
97642340fc3SLiam Merwick         if (dev == NULL) {
97742340fc3SLiam Merwick             trace_usb_ohci_td_dev_error();
97842340fc3SLiam Merwick             return 1;
97942340fc3SLiam Merwick         }
980f1ae32a1SGerd Hoffmann         ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
9816e821e50SBALATON Zoltan         if (ohci->async_td) {
982572a6732SBALATON Zoltan             /*
983572a6732SBALATON Zoltan              * ??? The hardware should allow one active packet per
984572a6732SBALATON Zoltan              * endpoint.  We only allow one active packet per controller.
985572a6732SBALATON Zoltan              * This should be sufficient as long as devices respond in a
986572a6732SBALATON Zoltan              * timely manner.
9876e821e50SBALATON Zoltan              */
9886e821e50SBALATON Zoltan             trace_usb_ohci_td_too_many_pending(ep->nr);
9896e821e50SBALATON Zoltan             return 1;
9906e821e50SBALATON Zoltan         }
9918550a02dSGerd Hoffmann         usb_packet_setup(&ohci->usb_packet, pid, ep, 0, addr, !flag_r,
992a6fb2ddbSHans de Goede                          OHCI_BM(td.flags, TD_DI) == 0);
993f1ae32a1SGerd Hoffmann         usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen);
9949a77a0f5SHans de Goede         usb_handle_packet(dev, &ohci->usb_packet);
995dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_td_packet_status(ohci->usb_packet.status);
996dc1f5988SAlexey Kardashevskiy 
9979a77a0f5SHans de Goede         if (ohci->usb_packet.status == USB_RET_ASYNC) {
99836dfe324SHans de Goede             usb_device_flush_ep_queue(dev, ep);
999f1ae32a1SGerd Hoffmann             ohci->async_td = addr;
1000f1ae32a1SGerd Hoffmann             return 1;
1001f1ae32a1SGerd Hoffmann         }
1002f1ae32a1SGerd Hoffmann     }
10039a77a0f5SHans de Goede     if (ohci->usb_packet.status == USB_RET_SUCCESS) {
10049a77a0f5SHans de Goede         ret = ohci->usb_packet.actual_length;
10059a77a0f5SHans de Goede     } else {
10069a77a0f5SHans de Goede         ret = ohci->usb_packet.status;
10079a77a0f5SHans de Goede     }
10089a77a0f5SHans de Goede 
1009f1ae32a1SGerd Hoffmann     if (ret >= 0) {
1010f1ae32a1SGerd Hoffmann         if (dir == OHCI_TD_DIR_IN) {
1011cf66ee8eSAlexey Kardashevskiy             if (ohci_copy_td(ohci, &td, ohci->usb_buf, ret,
1012cf66ee8eSAlexey Kardashevskiy                              DMA_DIRECTION_FROM_DEVICE)) {
1013cf66ee8eSAlexey Kardashevskiy                 ohci_die(ohci);
1014cf66ee8eSAlexey Kardashevskiy             }
1015dc1f5988SAlexey Kardashevskiy             ohci_td_pkt("IN", ohci->usb_buf, pktlen);
1016f1ae32a1SGerd Hoffmann         } else {
1017f1ae32a1SGerd Hoffmann             ret = pktlen;
1018f1ae32a1SGerd Hoffmann         }
1019f1ae32a1SGerd Hoffmann     }
1020f1ae32a1SGerd Hoffmann 
1021f1ae32a1SGerd Hoffmann     /* Writeback */
1022f1ae32a1SGerd Hoffmann     if (ret == pktlen || (dir == OHCI_TD_DIR_IN && ret >= 0 && flag_r)) {
1023f1ae32a1SGerd Hoffmann         /* Transmission succeeded. */
1024f1ae32a1SGerd Hoffmann         if (ret == len) {
1025f1ae32a1SGerd Hoffmann             td.cbp = 0;
1026f1ae32a1SGerd Hoffmann         } else {
1027f1ae32a1SGerd Hoffmann             if ((td.cbp & 0xfff) + ret > 0xfff) {
1028f1ae32a1SGerd Hoffmann                 td.cbp = (td.be & ~0xfff) + ((td.cbp + ret) & 0xfff);
1029f1ae32a1SGerd Hoffmann             } else {
1030f1ae32a1SGerd Hoffmann                 td.cbp += ret;
1031f1ae32a1SGerd Hoffmann             }
1032f1ae32a1SGerd Hoffmann         }
1033f1ae32a1SGerd Hoffmann         td.flags |= OHCI_TD_T1;
1034f1ae32a1SGerd Hoffmann         td.flags ^= OHCI_TD_T0;
1035f1ae32a1SGerd Hoffmann         OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_NOERROR);
1036f1ae32a1SGerd Hoffmann         OHCI_SET_BM(td.flags, TD_EC, 0);
1037f1ae32a1SGerd Hoffmann 
1038f1ae32a1SGerd Hoffmann         if ((dir != OHCI_TD_DIR_IN) && (ret != len)) {
1039f1ae32a1SGerd Hoffmann             /* Partial packet transfer: TD not ready to retire yet */
1040f1ae32a1SGerd Hoffmann             goto exit_no_retire;
1041f1ae32a1SGerd Hoffmann         }
1042f1ae32a1SGerd Hoffmann 
1043f1ae32a1SGerd Hoffmann         /* Setting ED_C is part of the TD retirement process */
1044f1ae32a1SGerd Hoffmann         ed->head &= ~OHCI_ED_C;
10451e58e7a0SBALATON Zoltan         if (td.flags & OHCI_TD_T0) {
1046f1ae32a1SGerd Hoffmann             ed->head |= OHCI_ED_C;
10471e58e7a0SBALATON Zoltan         }
1048f1ae32a1SGerd Hoffmann     } else {
1049f1ae32a1SGerd Hoffmann         if (ret >= 0) {
1050dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_td_underrun();
1051f1ae32a1SGerd Hoffmann             OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAUNDERRUN);
1052f1ae32a1SGerd Hoffmann         } else {
1053f1ae32a1SGerd Hoffmann             switch (ret) {
1054f1ae32a1SGerd Hoffmann             case USB_RET_IOERROR:
1055f1ae32a1SGerd Hoffmann             case USB_RET_NODEV:
1056dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_dev_error();
1057f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DEVICENOTRESPONDING);
10584b351a0fSJán Veselý                 break;
1059f1ae32a1SGerd Hoffmann             case USB_RET_NAK:
1060dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_nak();
1061f1ae32a1SGerd Hoffmann                 return 1;
1062f1ae32a1SGerd Hoffmann             case USB_RET_STALL:
1063dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_stall();
1064f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_STALL);
1065f1ae32a1SGerd Hoffmann                 break;
1066f1ae32a1SGerd Hoffmann             case USB_RET_BABBLE:
1067dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_babble();
1068f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAOVERRUN);
1069f1ae32a1SGerd Hoffmann                 break;
1070f1ae32a1SGerd Hoffmann             default:
1071dc1f5988SAlexey Kardashevskiy                 trace_usb_ohci_td_bad_device_response(ret);
1072f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_UNDEXPETEDPID);
1073f1ae32a1SGerd Hoffmann                 OHCI_SET_BM(td.flags, TD_EC, 3);
1074f1ae32a1SGerd Hoffmann                 break;
1075f1ae32a1SGerd Hoffmann             }
1076572a6732SBALATON Zoltan             /*
1077572a6732SBALATON Zoltan              * An error occurred so we have to clear the interrupt counter.
1078572a6732SBALATON Zoltan              * See spec at 6.4.4 on page 104
1079572a6732SBALATON Zoltan              */
10807c48b95dSSebastian Bauer             ohci->done_count = 0;
1081f1ae32a1SGerd Hoffmann         }
1082f1ae32a1SGerd Hoffmann         ed->head |= OHCI_ED_H;
1083f1ae32a1SGerd Hoffmann     }
1084f1ae32a1SGerd Hoffmann 
1085f1ae32a1SGerd Hoffmann     /* Retire this TD */
1086f1ae32a1SGerd Hoffmann     ed->head &= ~OHCI_DPTR_MASK;
1087f1ae32a1SGerd Hoffmann     ed->head |= td.next & OHCI_DPTR_MASK;
1088f1ae32a1SGerd Hoffmann     td.next = ohci->done;
1089f1ae32a1SGerd Hoffmann     ohci->done = addr;
1090f1ae32a1SGerd Hoffmann     i = OHCI_BM(td.flags, TD_DI);
10911e58e7a0SBALATON Zoltan     if (i < ohci->done_count) {
1092f1ae32a1SGerd Hoffmann         ohci->done_count = i;
10931e58e7a0SBALATON Zoltan     }
1094f1ae32a1SGerd Hoffmann exit_no_retire:
1095cf66ee8eSAlexey Kardashevskiy     if (ohci_put_td(ohci, addr, &td)) {
1096cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
1097cf66ee8eSAlexey Kardashevskiy         return 1;
1098cf66ee8eSAlexey Kardashevskiy     }
1099f1ae32a1SGerd Hoffmann     return OHCI_BM(td.flags, TD_CC) != OHCI_CC_NOERROR;
1100f1ae32a1SGerd Hoffmann }
1101f1ae32a1SGerd Hoffmann 
1102f1ae32a1SGerd Hoffmann /* Service an endpoint list.  Returns nonzero if active TD were found. */
ohci_service_ed_list(OHCIState * ohci,uint32_t head)11033a4d06f2SBALATON Zoltan static int ohci_service_ed_list(OHCIState *ohci, uint32_t head)
1104f1ae32a1SGerd Hoffmann {
1105f1ae32a1SGerd Hoffmann     struct ohci_ed ed;
1106f1ae32a1SGerd Hoffmann     uint32_t next_ed;
1107f1ae32a1SGerd Hoffmann     uint32_t cur;
1108f1ae32a1SGerd Hoffmann     int active;
110995ed5693SLi Qiang     uint32_t link_cnt = 0;
1110f1ae32a1SGerd Hoffmann     active = 0;
1111f1ae32a1SGerd Hoffmann 
11121e58e7a0SBALATON Zoltan     if (head == 0) {
1113f1ae32a1SGerd Hoffmann         return 0;
11141e58e7a0SBALATON Zoltan     }
1115ab878998SLaurent Vivier     for (cur = head; cur && link_cnt++ < ED_LINK_LIMIT; cur = next_ed) {
1116cf66ee8eSAlexey Kardashevskiy         if (ohci_read_ed(ohci, cur, &ed)) {
1117dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_ed_read_error(cur);
1118cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
1119f1ae32a1SGerd Hoffmann             return 0;
1120f1ae32a1SGerd Hoffmann         }
1121f1ae32a1SGerd Hoffmann 
1122f1ae32a1SGerd Hoffmann         next_ed = ed.next & OHCI_DPTR_MASK;
1123f1ae32a1SGerd Hoffmann 
1124f1ae32a1SGerd Hoffmann         if ((ed.head & OHCI_ED_H) || (ed.flags & OHCI_ED_K)) {
1125f1ae32a1SGerd Hoffmann             uint32_t addr;
1126f1ae32a1SGerd Hoffmann             /* Cancel pending packets for ED that have been paused. */
1127f1ae32a1SGerd Hoffmann             addr = ed.head & OHCI_DPTR_MASK;
1128f1ae32a1SGerd Hoffmann             if (ohci->async_td && addr == ohci->async_td) {
1129f1ae32a1SGerd Hoffmann                 usb_cancel_packet(&ohci->usb_packet);
1130f1ae32a1SGerd Hoffmann                 ohci->async_td = 0;
1131f79738b0SHans de Goede                 usb_device_ep_stopped(ohci->usb_packet.ep->dev,
1132f79738b0SHans de Goede                                       ohci->usb_packet.ep);
1133f1ae32a1SGerd Hoffmann             }
1134f1ae32a1SGerd Hoffmann             continue;
1135f1ae32a1SGerd Hoffmann         }
1136f1ae32a1SGerd Hoffmann 
1137f1ae32a1SGerd Hoffmann         while ((ed.head & OHCI_DPTR_MASK) != ed.tail) {
11383af8f177SAlexey Kardashevskiy             trace_usb_ohci_ed_pkt(cur, (ed.head & OHCI_ED_H) != 0,
11393af8f177SAlexey Kardashevskiy                     (ed.head & OHCI_ED_C) != 0, ed.head & OHCI_DPTR_MASK,
11403af8f177SAlexey Kardashevskiy                     ed.tail & OHCI_DPTR_MASK, ed.next & OHCI_DPTR_MASK);
11413af8f177SAlexey Kardashevskiy             trace_usb_ohci_ed_pkt_flags(
1142f1ae32a1SGerd Hoffmann                     OHCI_BM(ed.flags, ED_FA), OHCI_BM(ed.flags, ED_EN),
1143f1ae32a1SGerd Hoffmann                     OHCI_BM(ed.flags, ED_D), (ed.flags & OHCI_ED_S) != 0,
1144f1ae32a1SGerd Hoffmann                     (ed.flags & OHCI_ED_K) != 0, (ed.flags & OHCI_ED_F) != 0,
11453af8f177SAlexey Kardashevskiy                     OHCI_BM(ed.flags, ED_MPS));
1146dc1f5988SAlexey Kardashevskiy 
1147f1ae32a1SGerd Hoffmann             active = 1;
1148f1ae32a1SGerd Hoffmann 
1149f1ae32a1SGerd Hoffmann             if ((ed.flags & OHCI_ED_F) == 0) {
11501e58e7a0SBALATON Zoltan                 if (ohci_service_td(ohci, &ed)) {
1151f1ae32a1SGerd Hoffmann                     break;
11521e58e7a0SBALATON Zoltan                 }
1153f1ae32a1SGerd Hoffmann             } else {
1154f1ae32a1SGerd Hoffmann                 /* Handle isochronous endpoints */
11553a4d06f2SBALATON Zoltan                 if (ohci_service_iso_td(ohci, &ed)) {
1156f1ae32a1SGerd Hoffmann                     break;
1157f1ae32a1SGerd Hoffmann                 }
1158f1ae32a1SGerd Hoffmann             }
11593a4d06f2SBALATON Zoltan         }
1160f1ae32a1SGerd Hoffmann 
1161cf66ee8eSAlexey Kardashevskiy         if (ohci_put_ed(ohci, cur, &ed)) {
1162cf66ee8eSAlexey Kardashevskiy             ohci_die(ohci);
1163cf66ee8eSAlexey Kardashevskiy             return 0;
1164cf66ee8eSAlexey Kardashevskiy         }
1165f1ae32a1SGerd Hoffmann     }
1166f1ae32a1SGerd Hoffmann 
1167f1ae32a1SGerd Hoffmann     return active;
1168f1ae32a1SGerd Hoffmann }
1169f1ae32a1SGerd Hoffmann 
1170fd0a10cdSLaurent Vivier /* set a timer for EOF */
ohci_eof_timer(OHCIState * ohci)1171fd0a10cdSLaurent Vivier static void ohci_eof_timer(OHCIState *ohci)
1172f1ae32a1SGerd Hoffmann {
1173bc72ad67SAlex Bligh     timer_mod(ohci->eof_timer, ohci->sof_time + usb_frame_time);
1174fd0a10cdSLaurent Vivier }
1175fd0a10cdSLaurent Vivier /* Set a timer for EOF and generate a SOF event */
ohci_sof(OHCIState * ohci)1176fd0a10cdSLaurent Vivier static void ohci_sof(OHCIState *ohci)
1177fd0a10cdSLaurent Vivier {
1178a60f39a4SMiguel GAIO     ohci->sof_time += usb_frame_time;
1179fd0a10cdSLaurent Vivier     ohci_eof_timer(ohci);
1180f1ae32a1SGerd Hoffmann     ohci_set_interrupt(ohci, OHCI_INTR_SF);
1181f1ae32a1SGerd Hoffmann }
1182f1ae32a1SGerd Hoffmann 
1183f1ae32a1SGerd Hoffmann /* Process Control and Bulk lists. */
ohci_process_lists(OHCIState * ohci)11843a4d06f2SBALATON Zoltan static void ohci_process_lists(OHCIState *ohci)
1185f1ae32a1SGerd Hoffmann {
1186f1ae32a1SGerd Hoffmann     if ((ohci->ctl & OHCI_CTL_CLE) && (ohci->status & OHCI_STATUS_CLF)) {
1187f1ae32a1SGerd Hoffmann         if (ohci->ctrl_cur && ohci->ctrl_cur != ohci->ctrl_head) {
1188dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_process_lists(ohci->ctrl_head, ohci->ctrl_cur);
1189f1ae32a1SGerd Hoffmann         }
11903a4d06f2SBALATON Zoltan         if (!ohci_service_ed_list(ohci, ohci->ctrl_head)) {
1191f1ae32a1SGerd Hoffmann             ohci->ctrl_cur = 0;
1192f1ae32a1SGerd Hoffmann             ohci->status &= ~OHCI_STATUS_CLF;
1193f1ae32a1SGerd Hoffmann         }
1194f1ae32a1SGerd Hoffmann     }
1195f1ae32a1SGerd Hoffmann 
1196f1ae32a1SGerd Hoffmann     if ((ohci->ctl & OHCI_CTL_BLE) && (ohci->status & OHCI_STATUS_BLF)) {
11973a4d06f2SBALATON Zoltan         if (!ohci_service_ed_list(ohci, ohci->bulk_head)) {
1198f1ae32a1SGerd Hoffmann             ohci->bulk_cur = 0;
1199f1ae32a1SGerd Hoffmann             ohci->status &= ~OHCI_STATUS_BLF;
1200f1ae32a1SGerd Hoffmann         }
1201f1ae32a1SGerd Hoffmann     }
1202f1ae32a1SGerd Hoffmann }
1203f1ae32a1SGerd Hoffmann 
1204f1ae32a1SGerd Hoffmann /* Do frame processing on frame boundary */
ohci_frame_boundary(void * opaque)1205f1ae32a1SGerd Hoffmann static void ohci_frame_boundary(void *opaque)
1206f1ae32a1SGerd Hoffmann {
1207f1ae32a1SGerd Hoffmann     OHCIState *ohci = opaque;
1208f1ae32a1SGerd Hoffmann     struct ohci_hcca hcca;
1209f1ae32a1SGerd Hoffmann 
1210cf66ee8eSAlexey Kardashevskiy     if (ohci_read_hcca(ohci, ohci->hcca, &hcca)) {
1211dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_hcca_read_error(ohci->hcca);
1212cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
1213cf66ee8eSAlexey Kardashevskiy         return;
1214cf66ee8eSAlexey Kardashevskiy     }
1215f1ae32a1SGerd Hoffmann 
1216f1ae32a1SGerd Hoffmann     /* Process all the lists at the end of the frame */
1217f1ae32a1SGerd Hoffmann     if (ohci->ctl & OHCI_CTL_PLE) {
1218f1ae32a1SGerd Hoffmann         int n;
1219f1ae32a1SGerd Hoffmann 
1220f1ae32a1SGerd Hoffmann         n = ohci->frame_number & 0x1f;
12213a4d06f2SBALATON Zoltan         ohci_service_ed_list(ohci, le32_to_cpu(hcca.intr[n]));
1222f1ae32a1SGerd Hoffmann     }
1223f1ae32a1SGerd Hoffmann 
1224f1ae32a1SGerd Hoffmann     /* Cancel all pending packets if either of the lists has been disabled. */
1225f79738b0SHans de Goede     if (ohci->old_ctl & (~ohci->ctl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) {
1226f79738b0SHans de Goede         ohci_stop_endpoints(ohci);
1227f79738b0SHans de Goede     }
1228f1ae32a1SGerd Hoffmann     ohci->old_ctl = ohci->ctl;
12293a4d06f2SBALATON Zoltan     ohci_process_lists(ohci);
1230f1ae32a1SGerd Hoffmann 
1231cf66ee8eSAlexey Kardashevskiy     /* Stop if UnrecoverableError happened or ohci_sof will crash */
1232cf66ee8eSAlexey Kardashevskiy     if (ohci->intr_status & OHCI_INTR_UE) {
1233cf66ee8eSAlexey Kardashevskiy         return;
1234cf66ee8eSAlexey Kardashevskiy     }
1235cf66ee8eSAlexey Kardashevskiy 
1236f1ae32a1SGerd Hoffmann     /* Frame boundary, so do EOF stuf here */
1237f1ae32a1SGerd Hoffmann     ohci->frt = ohci->fit;
1238f1ae32a1SGerd Hoffmann 
1239f1ae32a1SGerd Hoffmann     /* Increment frame number and take care of endianness. */
1240f1ae32a1SGerd Hoffmann     ohci->frame_number = (ohci->frame_number + 1) & 0xffff;
1241f1ae32a1SGerd Hoffmann     hcca.frame = cpu_to_le16(ohci->frame_number);
12426301460cSPaolo Bonzini     /* When the HC updates frame number, set pad to 0. Ref OHCI Spec 4.4.1*/
12436301460cSPaolo Bonzini     hcca.pad = 0;
1244f1ae32a1SGerd Hoffmann 
1245f1ae32a1SGerd Hoffmann     if (ohci->done_count == 0 && !(ohci->intr_status & OHCI_INTR_WD)) {
12461e58e7a0SBALATON Zoltan         if (!ohci->done) {
1247f1ae32a1SGerd Hoffmann             abort();
12481e58e7a0SBALATON Zoltan         }
12491e58e7a0SBALATON Zoltan         if (ohci->intr & ohci->intr_status) {
1250f1ae32a1SGerd Hoffmann             ohci->done |= 1;
12511e58e7a0SBALATON Zoltan         }
1252f1ae32a1SGerd Hoffmann         hcca.done = cpu_to_le32(ohci->done);
1253f1ae32a1SGerd Hoffmann         ohci->done = 0;
1254f1ae32a1SGerd Hoffmann         ohci->done_count = 7;
1255f1ae32a1SGerd Hoffmann         ohci_set_interrupt(ohci, OHCI_INTR_WD);
1256f1ae32a1SGerd Hoffmann     }
1257f1ae32a1SGerd Hoffmann 
12581e58e7a0SBALATON Zoltan     if (ohci->done_count != 7 && ohci->done_count != 0) {
1259f1ae32a1SGerd Hoffmann         ohci->done_count--;
12601e58e7a0SBALATON Zoltan     }
1261f1ae32a1SGerd Hoffmann     /* Do SOF stuff here */
1262f1ae32a1SGerd Hoffmann     ohci_sof(ohci);
1263f1ae32a1SGerd Hoffmann 
1264f1ae32a1SGerd Hoffmann     /* Writeback HCCA */
1265cf66ee8eSAlexey Kardashevskiy     if (ohci_put_hcca(ohci, ohci->hcca, &hcca)) {
1266cf66ee8eSAlexey Kardashevskiy         ohci_die(ohci);
1267cf66ee8eSAlexey Kardashevskiy     }
1268f1ae32a1SGerd Hoffmann }
1269f1ae32a1SGerd Hoffmann 
1270572a6732SBALATON Zoltan /*
1271572a6732SBALATON Zoltan  * Start sending SOF tokens across the USB bus, lists are processed in
1272f1ae32a1SGerd Hoffmann  * next frame
1273f1ae32a1SGerd Hoffmann  */
ohci_bus_start(OHCIState * ohci)1274f1ae32a1SGerd Hoffmann static int ohci_bus_start(OHCIState *ohci)
1275f1ae32a1SGerd Hoffmann {
1276dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_start(ohci->name);
1277572a6732SBALATON Zoltan     /*
1278572a6732SBALATON Zoltan      * Delay the first SOF event by one frame time as linux driver is
1279572a6732SBALATON Zoltan      * not ready to receive it and can meet some race conditions
1280fd0a10cdSLaurent Vivier      */
1281a60f39a4SMiguel GAIO     ohci->sof_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
1282fd0a10cdSLaurent Vivier     ohci_eof_timer(ohci);
1283f1ae32a1SGerd Hoffmann 
1284f1ae32a1SGerd Hoffmann     return 1;
1285f1ae32a1SGerd Hoffmann }
1286f1ae32a1SGerd Hoffmann 
1287f1ae32a1SGerd Hoffmann /* Stop sending SOF tokens on the bus */
ohci_bus_stop(OHCIState * ohci)128834d97308SThomas Huth void ohci_bus_stop(OHCIState *ohci)
1289f1ae32a1SGerd Hoffmann {
1290dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_stop(ohci->name);
1291bc72ad67SAlex Bligh     timer_del(ohci->eof_timer);
1292f1ae32a1SGerd Hoffmann }
1293f1ae32a1SGerd Hoffmann 
1294572a6732SBALATON Zoltan /* Frame interval toggle is manipulated by the hcd only */
ohci_set_frame_interval(OHCIState * ohci,uint16_t val)1295f1ae32a1SGerd Hoffmann static void ohci_set_frame_interval(OHCIState *ohci, uint16_t val)
1296f1ae32a1SGerd Hoffmann {
1297f1ae32a1SGerd Hoffmann     val &= OHCI_FMI_FI;
1298f1ae32a1SGerd Hoffmann 
1299f1ae32a1SGerd Hoffmann     if (val != ohci->fi) {
1300dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_set_frame_interval(ohci->name, ohci->fi, ohci->fi);
1301f1ae32a1SGerd Hoffmann     }
1302f1ae32a1SGerd Hoffmann 
1303f1ae32a1SGerd Hoffmann     ohci->fi = val;
1304f1ae32a1SGerd Hoffmann }
1305f1ae32a1SGerd Hoffmann 
ohci_port_power(OHCIState * ohci,int i,int p)1306f1ae32a1SGerd Hoffmann static void ohci_port_power(OHCIState *ohci, int i, int p)
1307f1ae32a1SGerd Hoffmann {
1308f1ae32a1SGerd Hoffmann     if (p) {
1309f1ae32a1SGerd Hoffmann         ohci->rhport[i].ctrl |= OHCI_PORT_PPS;
1310f1ae32a1SGerd Hoffmann     } else {
1311978c93beSBALATON Zoltan         ohci->rhport[i].ctrl &= ~(OHCI_PORT_PPS | OHCI_PORT_CCS |
1312978c93beSBALATON Zoltan                                   OHCI_PORT_PSS | OHCI_PORT_PRS);
1313f1ae32a1SGerd Hoffmann     }
1314f1ae32a1SGerd Hoffmann }
1315f1ae32a1SGerd Hoffmann 
1316f1ae32a1SGerd Hoffmann /* Set HcControlRegister */
ohci_set_ctl(OHCIState * ohci,uint32_t val)1317f1ae32a1SGerd Hoffmann static void ohci_set_ctl(OHCIState *ohci, uint32_t val)
1318f1ae32a1SGerd Hoffmann {
1319f1ae32a1SGerd Hoffmann     uint32_t old_state;
1320f1ae32a1SGerd Hoffmann     uint32_t new_state;
1321f1ae32a1SGerd Hoffmann 
1322f1ae32a1SGerd Hoffmann     old_state = ohci->ctl & OHCI_CTL_HCFS;
1323f1ae32a1SGerd Hoffmann     ohci->ctl = val;
1324f1ae32a1SGerd Hoffmann     new_state = ohci->ctl & OHCI_CTL_HCFS;
1325f1ae32a1SGerd Hoffmann 
1326f1ae32a1SGerd Hoffmann     /* no state change */
13271e58e7a0SBALATON Zoltan     if (old_state == new_state) {
1328f1ae32a1SGerd Hoffmann         return;
13291e58e7a0SBALATON Zoltan     }
1330dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_set_ctl(ohci->name, new_state);
1331f1ae32a1SGerd Hoffmann     switch (new_state) {
1332f1ae32a1SGerd Hoffmann     case OHCI_USB_OPERATIONAL:
1333f1ae32a1SGerd Hoffmann         ohci_bus_start(ohci);
1334f1ae32a1SGerd Hoffmann         break;
1335f1ae32a1SGerd Hoffmann     case OHCI_USB_SUSPEND:
1336f1ae32a1SGerd Hoffmann         ohci_bus_stop(ohci);
1337087462c7SLaurent Vivier         /* clear pending SF otherwise linux driver loops in ohci_irq() */
1338087462c7SLaurent Vivier         ohci->intr_status &= ~OHCI_INTR_SF;
1339087462c7SLaurent Vivier         ohci_intr_update(ohci);
1340f1ae32a1SGerd Hoffmann         break;
1341f1ae32a1SGerd Hoffmann     case OHCI_USB_RESUME:
1342dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_resume(ohci->name);
1343f1ae32a1SGerd Hoffmann         break;
1344f1ae32a1SGerd Hoffmann     case OHCI_USB_RESET:
13457d938fd1SHervé Poussineau         ohci_roothub_reset(ohci);
1346f1ae32a1SGerd Hoffmann         break;
1347f1ae32a1SGerd Hoffmann     }
1348f1ae32a1SGerd Hoffmann }
1349f1ae32a1SGerd Hoffmann 
ohci_get_frame_remaining(OHCIState * ohci)1350f1ae32a1SGerd Hoffmann static uint32_t ohci_get_frame_remaining(OHCIState *ohci)
1351f1ae32a1SGerd Hoffmann {
1352f1ae32a1SGerd Hoffmann     uint16_t fr;
1353f1ae32a1SGerd Hoffmann     int64_t tks;
1354f1ae32a1SGerd Hoffmann 
13551e58e7a0SBALATON Zoltan     if ((ohci->ctl & OHCI_CTL_HCFS) != OHCI_USB_OPERATIONAL) {
13561e58e7a0SBALATON Zoltan         return ohci->frt << 31;
13571e58e7a0SBALATON Zoltan     }
1358*2a8537cfSMichael Tokarev     /* Being in USB operational state guarantees sof_time was set already. */
1359bc72ad67SAlex Bligh     tks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - ohci->sof_time;
1360a60f39a4SMiguel GAIO     if (tks < 0) {
1361a60f39a4SMiguel GAIO         tks = 0;
1362a60f39a4SMiguel GAIO     }
1363f1ae32a1SGerd Hoffmann 
1364f1ae32a1SGerd Hoffmann     /* avoid muldiv if possible */
13651e58e7a0SBALATON Zoltan     if (tks >= usb_frame_time) {
13661e58e7a0SBALATON Zoltan         return ohci->frt << 31;
13671e58e7a0SBALATON Zoltan     }
1368cd1f16f9SLaurent Vivier     tks = tks / usb_bit_time;
1369f1ae32a1SGerd Hoffmann     fr = (uint16_t)(ohci->fi - tks);
1370f1ae32a1SGerd Hoffmann 
1371f1ae32a1SGerd Hoffmann     return (ohci->frt << 31) | fr;
1372f1ae32a1SGerd Hoffmann }
1373f1ae32a1SGerd Hoffmann 
1374f1ae32a1SGerd Hoffmann 
1375f1ae32a1SGerd Hoffmann /* Set root hub status */
ohci_set_hub_status(OHCIState * ohci,uint32_t val)1376f1ae32a1SGerd Hoffmann static void ohci_set_hub_status(OHCIState *ohci, uint32_t val)
1377f1ae32a1SGerd Hoffmann {
1378f1ae32a1SGerd Hoffmann     uint32_t old_state;
1379f1ae32a1SGerd Hoffmann 
1380f1ae32a1SGerd Hoffmann     old_state = ohci->rhstatus;
1381f1ae32a1SGerd Hoffmann 
1382f1ae32a1SGerd Hoffmann     /* write 1 to clear OCIC */
13831e58e7a0SBALATON Zoltan     if (val & OHCI_RHS_OCIC) {
1384f1ae32a1SGerd Hoffmann         ohci->rhstatus &= ~OHCI_RHS_OCIC;
13851e58e7a0SBALATON Zoltan     }
1386f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_LPS) {
1387f1ae32a1SGerd Hoffmann         int i;
1388f1ae32a1SGerd Hoffmann 
13891e58e7a0SBALATON Zoltan         for (i = 0; i < ohci->num_ports; i++) {
1390f1ae32a1SGerd Hoffmann             ohci_port_power(ohci, i, 0);
13911e58e7a0SBALATON Zoltan         }
1392dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_hub_power_down();
1393f1ae32a1SGerd Hoffmann     }
1394f1ae32a1SGerd Hoffmann 
1395f1ae32a1SGerd Hoffmann     if (val & OHCI_RHS_LPSC) {
1396f1ae32a1SGerd Hoffmann         int i;
1397f1ae32a1SGerd Hoffmann 
13981e58e7a0SBALATON Zoltan         for (i = 0; i < ohci->num_ports; i++) {
1399f1ae32a1SGerd Hoffmann             ohci_port_power(ohci, i, 1);
14001e58e7a0SBALATON Zoltan         }
1401dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_hub_power_up();
1402f1ae32a1SGerd Hoffmann     }
1403f1ae32a1SGerd Hoffmann 
14041e58e7a0SBALATON Zoltan     if (val & OHCI_RHS_DRWE) {
1405f1ae32a1SGerd Hoffmann         ohci->rhstatus |= OHCI_RHS_DRWE;
14061e58e7a0SBALATON Zoltan     }
14071e58e7a0SBALATON Zoltan     if (val & OHCI_RHS_CRWE) {
1408f1ae32a1SGerd Hoffmann         ohci->rhstatus &= ~OHCI_RHS_DRWE;
14091e58e7a0SBALATON Zoltan     }
14101e58e7a0SBALATON Zoltan     if (old_state != ohci->rhstatus) {
1411f1ae32a1SGerd Hoffmann         ohci_set_interrupt(ohci, OHCI_INTR_RHSC);
1412f1ae32a1SGerd Hoffmann     }
14131e58e7a0SBALATON Zoltan }
1414f1ae32a1SGerd Hoffmann 
14150c38e9ddSBALATON Zoltan /* This is the one state transition the controller can do by itself */
ohci_resume(OHCIState * s)14160c38e9ddSBALATON Zoltan static bool ohci_resume(OHCIState *s)
14170c38e9ddSBALATON Zoltan {
14180c38e9ddSBALATON Zoltan     if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
14190c38e9ddSBALATON Zoltan         trace_usb_ohci_remote_wakeup(s->name);
14200c38e9ddSBALATON Zoltan         s->ctl &= ~OHCI_CTL_HCFS;
14210c38e9ddSBALATON Zoltan         s->ctl |= OHCI_USB_RESUME;
14220c38e9ddSBALATON Zoltan         return true;
14230c38e9ddSBALATON Zoltan     }
14240c38e9ddSBALATON Zoltan     return false;
14250c38e9ddSBALATON Zoltan }
14260c38e9ddSBALATON Zoltan 
1427ef680088SBALATON Zoltan /*
1428ef680088SBALATON Zoltan  * Sets a flag in a port status reg but only set it if the port is connected.
1429ef680088SBALATON Zoltan  * If not set ConnectStatusChange flag. If flag is enabled return 1.
1430ef680088SBALATON Zoltan  */
ohci_port_set_if_connected(OHCIState * ohci,int i,uint32_t val)1431ef680088SBALATON Zoltan static int ohci_port_set_if_connected(OHCIState *ohci, int i, uint32_t val)
1432ef680088SBALATON Zoltan {
1433ef680088SBALATON Zoltan     int ret = 1;
1434ef680088SBALATON Zoltan 
1435ef680088SBALATON Zoltan     /* writing a 0 has no effect */
1436ef680088SBALATON Zoltan     if (val == 0) {
1437ef680088SBALATON Zoltan         return 0;
1438ef680088SBALATON Zoltan     }
1439ef680088SBALATON Zoltan     /* If CurrentConnectStatus is cleared we set ConnectStatusChange */
1440ef680088SBALATON Zoltan     if (!(ohci->rhport[i].ctrl & OHCI_PORT_CCS)) {
1441ef680088SBALATON Zoltan         ohci->rhport[i].ctrl |= OHCI_PORT_CSC;
1442ef680088SBALATON Zoltan         if (ohci->rhstatus & OHCI_RHS_DRWE) {
14430c38e9ddSBALATON Zoltan             /* CSC is a wakeup event */
14440c38e9ddSBALATON Zoltan             if (ohci_resume(ohci)) {
14450c38e9ddSBALATON Zoltan                 ohci_set_interrupt(ohci, OHCI_INTR_RD);
14460c38e9ddSBALATON Zoltan             }
1447ef680088SBALATON Zoltan         }
1448ef680088SBALATON Zoltan         return 0;
1449ef680088SBALATON Zoltan     }
1450ef680088SBALATON Zoltan 
1451ef680088SBALATON Zoltan     if (ohci->rhport[i].ctrl & val) {
1452ef680088SBALATON Zoltan         ret = 0;
1453ef680088SBALATON Zoltan     }
1454ef680088SBALATON Zoltan     /* set the bit */
1455ef680088SBALATON Zoltan     ohci->rhport[i].ctrl |= val;
1456ef680088SBALATON Zoltan 
1457ef680088SBALATON Zoltan     return ret;
1458ef680088SBALATON Zoltan }
1459ef680088SBALATON Zoltan 
1460f1ae32a1SGerd Hoffmann /* Set root hub port status */
ohci_port_set_status(OHCIState * ohci,int portnum,uint32_t val)1461f1ae32a1SGerd Hoffmann static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val)
1462f1ae32a1SGerd Hoffmann {
1463f1ae32a1SGerd Hoffmann     uint32_t old_state;
1464f1ae32a1SGerd Hoffmann     OHCIPort *port;
1465f1ae32a1SGerd Hoffmann 
1466f1ae32a1SGerd Hoffmann     port = &ohci->rhport[portnum];
1467f1ae32a1SGerd Hoffmann     old_state = port->ctrl;
1468f1ae32a1SGerd Hoffmann 
1469f1ae32a1SGerd Hoffmann     /* Write to clear CSC, PESC, PSSC, OCIC, PRSC */
14701e58e7a0SBALATON Zoltan     if (val & OHCI_PORT_WTC) {
1471f1ae32a1SGerd Hoffmann         port->ctrl &= ~(val & OHCI_PORT_WTC);
14721e58e7a0SBALATON Zoltan     }
14731e58e7a0SBALATON Zoltan     if (val & OHCI_PORT_CCS) {
1474f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_PES;
14751e58e7a0SBALATON Zoltan     }
1476f1ae32a1SGerd Hoffmann     ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PES);
1477f1ae32a1SGerd Hoffmann 
1478f1ae32a1SGerd Hoffmann     if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PSS)) {
1479dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_port_suspend(portnum);
1480f1ae32a1SGerd Hoffmann     }
1481f1ae32a1SGerd Hoffmann 
1482f1ae32a1SGerd Hoffmann     if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PRS)) {
1483dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_port_reset(portnum);
1484f1ae32a1SGerd Hoffmann         usb_device_reset(port->port.dev);
1485f1ae32a1SGerd Hoffmann         port->ctrl &= ~OHCI_PORT_PRS;
1486f1ae32a1SGerd Hoffmann         /* ??? Should this also set OHCI_PORT_PESC. */
1487f1ae32a1SGerd Hoffmann         port->ctrl |= OHCI_PORT_PES | OHCI_PORT_PRSC;
1488f1ae32a1SGerd Hoffmann     }
1489f1ae32a1SGerd Hoffmann 
1490572a6732SBALATON Zoltan     /* Invert order here to ensure in ambiguous case, device is powered up. */
14911e58e7a0SBALATON Zoltan     if (val & OHCI_PORT_LSDA) {
1492f1ae32a1SGerd Hoffmann         ohci_port_power(ohci, portnum, 0);
14931e58e7a0SBALATON Zoltan     }
14941e58e7a0SBALATON Zoltan     if (val & OHCI_PORT_PPS) {
1495f1ae32a1SGerd Hoffmann         ohci_port_power(ohci, portnum, 1);
14961e58e7a0SBALATON Zoltan     }
14971e58e7a0SBALATON Zoltan     if (old_state != port->ctrl) {
1498f1ae32a1SGerd Hoffmann         ohci_set_interrupt(ohci, OHCI_INTR_RHSC);
1499f1ae32a1SGerd Hoffmann     }
15001e58e7a0SBALATON Zoltan }
1501f1ae32a1SGerd Hoffmann 
ohci_mem_read(void * opaque,hwaddr addr,unsigned size)1502f1ae32a1SGerd Hoffmann static uint64_t ohci_mem_read(void *opaque,
1503a8170e5eSAvi Kivity                               hwaddr addr,
1504f1ae32a1SGerd Hoffmann                               unsigned size)
1505f1ae32a1SGerd Hoffmann {
1506f1ae32a1SGerd Hoffmann     OHCIState *ohci = opaque;
1507f1ae32a1SGerd Hoffmann     uint32_t retval;
1508f1ae32a1SGerd Hoffmann 
1509f1ae32a1SGerd Hoffmann     /* Only aligned reads are allowed on OHCI */
1510f1ae32a1SGerd Hoffmann     if (addr & 3) {
1511dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_mem_read_unaligned(addr);
1512f1ae32a1SGerd Hoffmann         return 0xffffffff;
1513f1ae32a1SGerd Hoffmann     } else if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) {
1514f1ae32a1SGerd Hoffmann         /* HcRhPortStatus */
1515f1ae32a1SGerd Hoffmann         retval = ohci->rhport[(addr - 0x54) >> 2].ctrl | OHCI_PORT_PPS;
15169ae8d31dSBALATON Zoltan         trace_usb_ohci_mem_port_read(size, "HcRhPortStatus", (addr - 0x50) >> 2,
15179ae8d31dSBALATON Zoltan                                      addr, addr >> 2, retval);
1518f1ae32a1SGerd Hoffmann     } else {
1519f1ae32a1SGerd Hoffmann         switch (addr >> 2) {
1520f1ae32a1SGerd Hoffmann         case 0: /* HcRevision */
1521f1ae32a1SGerd Hoffmann             retval = 0x10;
1522f1ae32a1SGerd Hoffmann             break;
1523f1ae32a1SGerd Hoffmann 
1524f1ae32a1SGerd Hoffmann         case 1: /* HcControl */
1525f1ae32a1SGerd Hoffmann             retval = ohci->ctl;
1526f1ae32a1SGerd Hoffmann             break;
1527f1ae32a1SGerd Hoffmann 
1528f1ae32a1SGerd Hoffmann         case 2: /* HcCommandStatus */
1529f1ae32a1SGerd Hoffmann             retval = ohci->status;
1530f1ae32a1SGerd Hoffmann             break;
1531f1ae32a1SGerd Hoffmann 
1532f1ae32a1SGerd Hoffmann         case 3: /* HcInterruptStatus */
1533f1ae32a1SGerd Hoffmann             retval = ohci->intr_status;
1534f1ae32a1SGerd Hoffmann             break;
1535f1ae32a1SGerd Hoffmann 
1536f1ae32a1SGerd Hoffmann         case 4: /* HcInterruptEnable */
1537f1ae32a1SGerd Hoffmann         case 5: /* HcInterruptDisable */
1538f1ae32a1SGerd Hoffmann             retval = ohci->intr;
1539f1ae32a1SGerd Hoffmann             break;
1540f1ae32a1SGerd Hoffmann 
1541f1ae32a1SGerd Hoffmann         case 6: /* HcHCCA */
1542f1ae32a1SGerd Hoffmann             retval = ohci->hcca;
1543f1ae32a1SGerd Hoffmann             break;
1544f1ae32a1SGerd Hoffmann 
1545f1ae32a1SGerd Hoffmann         case 7: /* HcPeriodCurrentED */
1546f1ae32a1SGerd Hoffmann             retval = ohci->per_cur;
1547f1ae32a1SGerd Hoffmann             break;
1548f1ae32a1SGerd Hoffmann 
1549f1ae32a1SGerd Hoffmann         case 8: /* HcControlHeadED */
1550f1ae32a1SGerd Hoffmann             retval = ohci->ctrl_head;
1551f1ae32a1SGerd Hoffmann             break;
1552f1ae32a1SGerd Hoffmann 
1553f1ae32a1SGerd Hoffmann         case 9: /* HcControlCurrentED */
1554f1ae32a1SGerd Hoffmann             retval = ohci->ctrl_cur;
1555f1ae32a1SGerd Hoffmann             break;
1556f1ae32a1SGerd Hoffmann 
1557f1ae32a1SGerd Hoffmann         case 10: /* HcBulkHeadED */
1558f1ae32a1SGerd Hoffmann             retval = ohci->bulk_head;
1559f1ae32a1SGerd Hoffmann             break;
1560f1ae32a1SGerd Hoffmann 
1561f1ae32a1SGerd Hoffmann         case 11: /* HcBulkCurrentED */
1562f1ae32a1SGerd Hoffmann             retval = ohci->bulk_cur;
1563f1ae32a1SGerd Hoffmann             break;
1564f1ae32a1SGerd Hoffmann 
1565f1ae32a1SGerd Hoffmann         case 12: /* HcDoneHead */
1566f1ae32a1SGerd Hoffmann             retval = ohci->done;
1567f1ae32a1SGerd Hoffmann             break;
1568f1ae32a1SGerd Hoffmann 
1569f1ae32a1SGerd Hoffmann         case 13: /* HcFmInterretval */
1570f1ae32a1SGerd Hoffmann             retval = (ohci->fit << 31) | (ohci->fsmps << 16) | (ohci->fi);
1571f1ae32a1SGerd Hoffmann             break;
1572f1ae32a1SGerd Hoffmann 
1573f1ae32a1SGerd Hoffmann         case 14: /* HcFmRemaining */
1574f1ae32a1SGerd Hoffmann             retval = ohci_get_frame_remaining(ohci);
1575f1ae32a1SGerd Hoffmann             break;
1576f1ae32a1SGerd Hoffmann 
1577f1ae32a1SGerd Hoffmann         case 15: /* HcFmNumber */
1578f1ae32a1SGerd Hoffmann             retval = ohci->frame_number;
1579f1ae32a1SGerd Hoffmann             break;
1580f1ae32a1SGerd Hoffmann 
1581f1ae32a1SGerd Hoffmann         case 16: /* HcPeriodicStart */
1582f1ae32a1SGerd Hoffmann             retval = ohci->pstart;
1583f1ae32a1SGerd Hoffmann             break;
1584f1ae32a1SGerd Hoffmann 
1585f1ae32a1SGerd Hoffmann         case 17: /* HcLSThreshold */
1586f1ae32a1SGerd Hoffmann             retval = ohci->lst;
1587f1ae32a1SGerd Hoffmann             break;
1588f1ae32a1SGerd Hoffmann 
1589f1ae32a1SGerd Hoffmann         case 18: /* HcRhDescriptorA */
1590f1ae32a1SGerd Hoffmann             retval = ohci->rhdesc_a;
1591f1ae32a1SGerd Hoffmann             break;
1592f1ae32a1SGerd Hoffmann 
1593f1ae32a1SGerd Hoffmann         case 19: /* HcRhDescriptorB */
1594f1ae32a1SGerd Hoffmann             retval = ohci->rhdesc_b;
1595f1ae32a1SGerd Hoffmann             break;
1596f1ae32a1SGerd Hoffmann 
1597f1ae32a1SGerd Hoffmann         case 20: /* HcRhStatus */
1598f1ae32a1SGerd Hoffmann             retval = ohci->rhstatus;
1599f1ae32a1SGerd Hoffmann             break;
1600f1ae32a1SGerd Hoffmann 
1601f1ae32a1SGerd Hoffmann         /* PXA27x specific registers */
1602f1ae32a1SGerd Hoffmann         case 24: /* HcStatus */
1603f1ae32a1SGerd Hoffmann             retval = ohci->hstatus & ohci->hmask;
1604f1ae32a1SGerd Hoffmann             break;
1605f1ae32a1SGerd Hoffmann 
1606f1ae32a1SGerd Hoffmann         case 25: /* HcHReset */
1607f1ae32a1SGerd Hoffmann             retval = ohci->hreset;
1608f1ae32a1SGerd Hoffmann             break;
1609f1ae32a1SGerd Hoffmann 
1610f1ae32a1SGerd Hoffmann         case 26: /* HcHInterruptEnable */
1611f1ae32a1SGerd Hoffmann             retval = ohci->hmask;
1612f1ae32a1SGerd Hoffmann             break;
1613f1ae32a1SGerd Hoffmann 
1614f1ae32a1SGerd Hoffmann         case 27: /* HcHInterruptTest */
1615f1ae32a1SGerd Hoffmann             retval = ohci->htest;
1616f1ae32a1SGerd Hoffmann             break;
1617f1ae32a1SGerd Hoffmann 
1618f1ae32a1SGerd Hoffmann         default:
1619dc1f5988SAlexey Kardashevskiy             trace_usb_ohci_mem_read_bad_offset(addr);
1620f1ae32a1SGerd Hoffmann             retval = 0xffffffff;
1621f1ae32a1SGerd Hoffmann         }
16229ae8d31dSBALATON Zoltan         if (addr != 0xc || retval) {
16239ae8d31dSBALATON Zoltan             trace_usb_ohci_mem_read(size, ohci_reg_name(addr), addr, addr >> 2,
16249ae8d31dSBALATON Zoltan                                     retval);
16259ae8d31dSBALATON Zoltan         }
1626f1ae32a1SGerd Hoffmann     }
1627f1ae32a1SGerd Hoffmann 
1628f1ae32a1SGerd Hoffmann     return retval;
1629f1ae32a1SGerd Hoffmann }
1630f1ae32a1SGerd Hoffmann 
ohci_mem_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)1631f1ae32a1SGerd Hoffmann static void ohci_mem_write(void *opaque,
1632a8170e5eSAvi Kivity                            hwaddr addr,
1633f1ae32a1SGerd Hoffmann                            uint64_t val,
1634f1ae32a1SGerd Hoffmann                            unsigned size)
1635f1ae32a1SGerd Hoffmann {
1636f1ae32a1SGerd Hoffmann     OHCIState *ohci = opaque;
1637f1ae32a1SGerd Hoffmann 
1638f1ae32a1SGerd Hoffmann     /* Only aligned reads are allowed on OHCI */
1639f1ae32a1SGerd Hoffmann     if (addr & 3) {
1640dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_mem_write_unaligned(addr);
1641f1ae32a1SGerd Hoffmann         return;
1642f1ae32a1SGerd Hoffmann     }
1643f1ae32a1SGerd Hoffmann 
1644f1ae32a1SGerd Hoffmann     if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) {
1645f1ae32a1SGerd Hoffmann         /* HcRhPortStatus */
16469ae8d31dSBALATON Zoltan         trace_usb_ohci_mem_port_write(size, "HcRhPortStatus",
16479ae8d31dSBALATON Zoltan                                       (addr - 0x50) >> 2, addr, addr >> 2, val);
1648f1ae32a1SGerd Hoffmann         ohci_port_set_status(ohci, (addr - 0x54) >> 2, val);
1649f1ae32a1SGerd Hoffmann         return;
1650f1ae32a1SGerd Hoffmann     }
1651f1ae32a1SGerd Hoffmann 
16529ae8d31dSBALATON Zoltan     trace_usb_ohci_mem_write(size, ohci_reg_name(addr), addr, addr >> 2, val);
1653f1ae32a1SGerd Hoffmann     switch (addr >> 2) {
1654f1ae32a1SGerd Hoffmann     case 1: /* HcControl */
1655f1ae32a1SGerd Hoffmann         ohci_set_ctl(ohci, val);
1656f1ae32a1SGerd Hoffmann         break;
1657f1ae32a1SGerd Hoffmann 
1658f1ae32a1SGerd Hoffmann     case 2: /* HcCommandStatus */
1659f1ae32a1SGerd Hoffmann         /* SOC is read-only */
1660f1ae32a1SGerd Hoffmann         val = (val & ~OHCI_STATUS_SOC);
1661f1ae32a1SGerd Hoffmann 
1662f1ae32a1SGerd Hoffmann         /* Bits written as '0' remain unchanged in the register */
1663f1ae32a1SGerd Hoffmann         ohci->status |= val;
1664f1ae32a1SGerd Hoffmann 
16651e58e7a0SBALATON Zoltan         if (ohci->status & OHCI_STATUS_HCR) {
16660922c3f6SHervé Poussineau             ohci_soft_reset(ohci);
16671e58e7a0SBALATON Zoltan         }
1668f1ae32a1SGerd Hoffmann         break;
1669f1ae32a1SGerd Hoffmann 
1670f1ae32a1SGerd Hoffmann     case 3: /* HcInterruptStatus */
1671f1ae32a1SGerd Hoffmann         ohci->intr_status &= ~val;
1672f1ae32a1SGerd Hoffmann         ohci_intr_update(ohci);
1673f1ae32a1SGerd Hoffmann         break;
1674f1ae32a1SGerd Hoffmann 
1675f1ae32a1SGerd Hoffmann     case 4: /* HcInterruptEnable */
1676f1ae32a1SGerd Hoffmann         ohci->intr |= val;
1677f1ae32a1SGerd Hoffmann         ohci_intr_update(ohci);
1678f1ae32a1SGerd Hoffmann         break;
1679f1ae32a1SGerd Hoffmann 
1680f1ae32a1SGerd Hoffmann     case 5: /* HcInterruptDisable */
1681f1ae32a1SGerd Hoffmann         ohci->intr &= ~val;
1682f1ae32a1SGerd Hoffmann         ohci_intr_update(ohci);
1683f1ae32a1SGerd Hoffmann         break;
1684f1ae32a1SGerd Hoffmann 
1685f1ae32a1SGerd Hoffmann     case 6: /* HcHCCA */
1686f1ae32a1SGerd Hoffmann         ohci->hcca = val & OHCI_HCCA_MASK;
1687f1ae32a1SGerd Hoffmann         break;
1688f1ae32a1SGerd Hoffmann 
1689f1ae32a1SGerd Hoffmann     case 7: /* HcPeriodCurrentED */
1690f1ae32a1SGerd Hoffmann         /* Ignore writes to this read-only register, Linux does them */
1691f1ae32a1SGerd Hoffmann         break;
1692f1ae32a1SGerd Hoffmann 
1693f1ae32a1SGerd Hoffmann     case 8: /* HcControlHeadED */
1694f1ae32a1SGerd Hoffmann         ohci->ctrl_head = val & OHCI_EDPTR_MASK;
1695f1ae32a1SGerd Hoffmann         break;
1696f1ae32a1SGerd Hoffmann 
1697f1ae32a1SGerd Hoffmann     case 9: /* HcControlCurrentED */
1698f1ae32a1SGerd Hoffmann         ohci->ctrl_cur = val & OHCI_EDPTR_MASK;
1699f1ae32a1SGerd Hoffmann         break;
1700f1ae32a1SGerd Hoffmann 
1701f1ae32a1SGerd Hoffmann     case 10: /* HcBulkHeadED */
1702f1ae32a1SGerd Hoffmann         ohci->bulk_head = val & OHCI_EDPTR_MASK;
1703f1ae32a1SGerd Hoffmann         break;
1704f1ae32a1SGerd Hoffmann 
1705f1ae32a1SGerd Hoffmann     case 11: /* HcBulkCurrentED */
1706f1ae32a1SGerd Hoffmann         ohci->bulk_cur = val & OHCI_EDPTR_MASK;
1707f1ae32a1SGerd Hoffmann         break;
1708f1ae32a1SGerd Hoffmann 
1709f1ae32a1SGerd Hoffmann     case 13: /* HcFmInterval */
1710f1ae32a1SGerd Hoffmann         ohci->fsmps = (val & OHCI_FMI_FSMPS) >> 16;
1711f1ae32a1SGerd Hoffmann         ohci->fit = (val & OHCI_FMI_FIT) >> 31;
1712f1ae32a1SGerd Hoffmann         ohci_set_frame_interval(ohci, val);
1713f1ae32a1SGerd Hoffmann         break;
1714f1ae32a1SGerd Hoffmann 
1715f1ae32a1SGerd Hoffmann     case 15: /* HcFmNumber */
1716f1ae32a1SGerd Hoffmann         break;
1717f1ae32a1SGerd Hoffmann 
1718f1ae32a1SGerd Hoffmann     case 16: /* HcPeriodicStart */
1719f1ae32a1SGerd Hoffmann         ohci->pstart = val & 0xffff;
1720f1ae32a1SGerd Hoffmann         break;
1721f1ae32a1SGerd Hoffmann 
1722f1ae32a1SGerd Hoffmann     case 17: /* HcLSThreshold */
1723f1ae32a1SGerd Hoffmann         ohci->lst = val & 0xffff;
1724f1ae32a1SGerd Hoffmann         break;
1725f1ae32a1SGerd Hoffmann 
1726f1ae32a1SGerd Hoffmann     case 18: /* HcRhDescriptorA */
1727f1ae32a1SGerd Hoffmann         ohci->rhdesc_a &= ~OHCI_RHA_RW_MASK;
1728f1ae32a1SGerd Hoffmann         ohci->rhdesc_a |= val & OHCI_RHA_RW_MASK;
1729f1ae32a1SGerd Hoffmann         break;
1730f1ae32a1SGerd Hoffmann 
1731f1ae32a1SGerd Hoffmann     case 19: /* HcRhDescriptorB */
1732f1ae32a1SGerd Hoffmann         break;
1733f1ae32a1SGerd Hoffmann 
1734f1ae32a1SGerd Hoffmann     case 20: /* HcRhStatus */
1735f1ae32a1SGerd Hoffmann         ohci_set_hub_status(ohci, val);
1736f1ae32a1SGerd Hoffmann         break;
1737f1ae32a1SGerd Hoffmann 
1738f1ae32a1SGerd Hoffmann     /* PXA27x specific registers */
1739f1ae32a1SGerd Hoffmann     case 24: /* HcStatus */
1740f1ae32a1SGerd Hoffmann         ohci->hstatus &= ~(val & ohci->hmask);
17417fa96d73SGerd Hoffmann         break;
1742f1ae32a1SGerd Hoffmann 
1743f1ae32a1SGerd Hoffmann     case 25: /* HcHReset */
1744f1ae32a1SGerd Hoffmann         ohci->hreset = val & ~OHCI_HRESET_FSBIR;
17451e58e7a0SBALATON Zoltan         if (val & OHCI_HRESET_FSBIR) {
174684d04e21SHervé Poussineau             ohci_hard_reset(ohci);
17471e58e7a0SBALATON Zoltan         }
1748f1ae32a1SGerd Hoffmann         break;
1749f1ae32a1SGerd Hoffmann 
1750f1ae32a1SGerd Hoffmann     case 26: /* HcHInterruptEnable */
1751f1ae32a1SGerd Hoffmann         ohci->hmask = val;
1752f1ae32a1SGerd Hoffmann         break;
1753f1ae32a1SGerd Hoffmann 
1754f1ae32a1SGerd Hoffmann     case 27: /* HcHInterruptTest */
1755f1ae32a1SGerd Hoffmann         ohci->htest = val;
1756f1ae32a1SGerd Hoffmann         break;
1757f1ae32a1SGerd Hoffmann 
1758f1ae32a1SGerd Hoffmann     default:
1759dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_mem_write_bad_offset(addr);
1760f1ae32a1SGerd Hoffmann         break;
1761f1ae32a1SGerd Hoffmann     }
1762f1ae32a1SGerd Hoffmann }
1763f1ae32a1SGerd Hoffmann 
176437bf0654SBALATON Zoltan static const MemoryRegionOps ohci_mem_ops = {
176537bf0654SBALATON Zoltan     .read = ohci_mem_read,
176637bf0654SBALATON Zoltan     .write = ohci_mem_write,
176737bf0654SBALATON Zoltan     .endianness = DEVICE_LITTLE_ENDIAN,
176837bf0654SBALATON Zoltan };
176937bf0654SBALATON Zoltan 
177037bf0654SBALATON Zoltan /* USBPortOps */
ohci_attach(USBPort * port1)177137bf0654SBALATON Zoltan static void ohci_attach(USBPort *port1)
177237bf0654SBALATON Zoltan {
177337bf0654SBALATON Zoltan     OHCIState *s = port1->opaque;
177437bf0654SBALATON Zoltan     OHCIPort *port = &s->rhport[port1->index];
177537bf0654SBALATON Zoltan     uint32_t old_state = port->ctrl;
177637bf0654SBALATON Zoltan 
177737bf0654SBALATON Zoltan     /* set connect status */
177837bf0654SBALATON Zoltan     port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;
177937bf0654SBALATON Zoltan 
178037bf0654SBALATON Zoltan     /* update speed */
178137bf0654SBALATON Zoltan     if (port->port.dev->speed == USB_SPEED_LOW) {
178237bf0654SBALATON Zoltan         port->ctrl |= OHCI_PORT_LSDA;
178337bf0654SBALATON Zoltan     } else {
178437bf0654SBALATON Zoltan         port->ctrl &= ~OHCI_PORT_LSDA;
178537bf0654SBALATON Zoltan     }
178637bf0654SBALATON Zoltan 
178737bf0654SBALATON Zoltan     /* notify of remote-wakeup */
178837bf0654SBALATON Zoltan     if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
178937bf0654SBALATON Zoltan         ohci_set_interrupt(s, OHCI_INTR_RD);
179037bf0654SBALATON Zoltan     }
179137bf0654SBALATON Zoltan 
179237bf0654SBALATON Zoltan     trace_usb_ohci_port_attach(port1->index);
179337bf0654SBALATON Zoltan 
179437bf0654SBALATON Zoltan     if (old_state != port->ctrl) {
179537bf0654SBALATON Zoltan         ohci_set_interrupt(s, OHCI_INTR_RHSC);
179637bf0654SBALATON Zoltan     }
179737bf0654SBALATON Zoltan }
179837bf0654SBALATON Zoltan 
ohci_child_detach(USBPort * port1,USBDevice * dev)1799b6b0c066SBALATON Zoltan static void ohci_child_detach(USBPort *port1, USBDevice *dev)
1800f1ae32a1SGerd Hoffmann {
1801b6b0c066SBALATON Zoltan     OHCIState *ohci = port1->opaque;
1802b6b0c066SBALATON Zoltan 
1803f1ae32a1SGerd Hoffmann     if (ohci->async_td &&
1804f1ae32a1SGerd Hoffmann         usb_packet_is_inflight(&ohci->usb_packet) &&
1805f1ae32a1SGerd Hoffmann         ohci->usb_packet.ep->dev == dev) {
1806f1ae32a1SGerd Hoffmann         usb_cancel_packet(&ohci->usb_packet);
1807f1ae32a1SGerd Hoffmann         ohci->async_td = 0;
1808f1ae32a1SGerd Hoffmann     }
1809f1ae32a1SGerd Hoffmann }
1810f1ae32a1SGerd Hoffmann 
ohci_detach(USBPort * port1)181137bf0654SBALATON Zoltan static void ohci_detach(USBPort *port1)
181237bf0654SBALATON Zoltan {
181337bf0654SBALATON Zoltan     OHCIState *s = port1->opaque;
181437bf0654SBALATON Zoltan     OHCIPort *port = &s->rhport[port1->index];
181537bf0654SBALATON Zoltan     uint32_t old_state = port->ctrl;
181637bf0654SBALATON Zoltan 
1817b6b0c066SBALATON Zoltan     ohci_child_detach(port1, port1->dev);
181837bf0654SBALATON Zoltan 
181937bf0654SBALATON Zoltan     /* set connect status */
182037bf0654SBALATON Zoltan     if (port->ctrl & OHCI_PORT_CCS) {
182137bf0654SBALATON Zoltan         port->ctrl &= ~OHCI_PORT_CCS;
182237bf0654SBALATON Zoltan         port->ctrl |= OHCI_PORT_CSC;
182337bf0654SBALATON Zoltan     }
182437bf0654SBALATON Zoltan     /* disable port */
182537bf0654SBALATON Zoltan     if (port->ctrl & OHCI_PORT_PES) {
182637bf0654SBALATON Zoltan         port->ctrl &= ~OHCI_PORT_PES;
182737bf0654SBALATON Zoltan         port->ctrl |= OHCI_PORT_PESC;
182837bf0654SBALATON Zoltan     }
182937bf0654SBALATON Zoltan     trace_usb_ohci_port_detach(port1->index);
183037bf0654SBALATON Zoltan 
183137bf0654SBALATON Zoltan     if (old_state != port->ctrl) {
183237bf0654SBALATON Zoltan         ohci_set_interrupt(s, OHCI_INTR_RHSC);
183337bf0654SBALATON Zoltan     }
183437bf0654SBALATON Zoltan }
183537bf0654SBALATON Zoltan 
ohci_wakeup(USBPort * port1)183637bf0654SBALATON Zoltan static void ohci_wakeup(USBPort *port1)
183737bf0654SBALATON Zoltan {
183837bf0654SBALATON Zoltan     OHCIState *s = port1->opaque;
183937bf0654SBALATON Zoltan     OHCIPort *port = &s->rhport[port1->index];
184037bf0654SBALATON Zoltan     uint32_t intr = 0;
184137bf0654SBALATON Zoltan     if (port->ctrl & OHCI_PORT_PSS) {
184237bf0654SBALATON Zoltan         trace_usb_ohci_port_wakeup(port1->index);
184337bf0654SBALATON Zoltan         port->ctrl |= OHCI_PORT_PSSC;
184437bf0654SBALATON Zoltan         port->ctrl &= ~OHCI_PORT_PSS;
184537bf0654SBALATON Zoltan         intr = OHCI_INTR_RHSC;
184637bf0654SBALATON Zoltan     }
184737bf0654SBALATON Zoltan     /* Note that the controller can be suspended even if this port is not */
18480c38e9ddSBALATON Zoltan     if (ohci_resume(s)) {
184937bf0654SBALATON Zoltan         /*
185037bf0654SBALATON Zoltan          * In suspend mode only ResumeDetected is possible, not RHSC:
185137bf0654SBALATON Zoltan          * see the OHCI spec 5.1.2.3.
185237bf0654SBALATON Zoltan          */
185337bf0654SBALATON Zoltan         intr = OHCI_INTR_RD;
185437bf0654SBALATON Zoltan     }
185537bf0654SBALATON Zoltan     ohci_set_interrupt(s, intr);
185637bf0654SBALATON Zoltan }
185737bf0654SBALATON Zoltan 
ohci_async_complete_packet(USBPort * port,USBPacket * packet)185837bf0654SBALATON Zoltan static void ohci_async_complete_packet(USBPort *port, USBPacket *packet)
185937bf0654SBALATON Zoltan {
186037bf0654SBALATON Zoltan     OHCIState *ohci = container_of(packet, OHCIState, usb_packet);
186137bf0654SBALATON Zoltan 
186237bf0654SBALATON Zoltan     trace_usb_ohci_async_complete();
186337bf0654SBALATON Zoltan     ohci->async_complete = true;
18643a4d06f2SBALATON Zoltan     ohci_process_lists(ohci);
186537bf0654SBALATON Zoltan }
1866f1ae32a1SGerd Hoffmann 
1867f1ae32a1SGerd Hoffmann static USBPortOps ohci_port_ops = {
1868f1ae32a1SGerd Hoffmann     .attach = ohci_attach,
1869f1ae32a1SGerd Hoffmann     .detach = ohci_detach,
1870f1ae32a1SGerd Hoffmann     .child_detach = ohci_child_detach,
1871f1ae32a1SGerd Hoffmann     .wakeup = ohci_wakeup,
1872f1ae32a1SGerd Hoffmann     .complete = ohci_async_complete_packet,
1873f1ae32a1SGerd Hoffmann };
1874f1ae32a1SGerd Hoffmann 
1875f1ae32a1SGerd Hoffmann static USBBusOps ohci_bus_ops = {
1876f1ae32a1SGerd Hoffmann };
1877f1ae32a1SGerd Hoffmann 
usb_ohci_init(OHCIState * ohci,DeviceState * dev,uint32_t num_ports,dma_addr_t localmem_base,char * masterbus,uint32_t firstport,AddressSpace * as,void (* ohci_die_fn)(OHCIState *),Error ** errp)187834d97308SThomas Huth void usb_ohci_init(OHCIState *ohci, DeviceState *dev, uint32_t num_ports,
187934d97308SThomas Huth                    dma_addr_t localmem_base, char *masterbus,
188034d97308SThomas Huth                    uint32_t firstport, AddressSpace *as,
18814713720aSPhilippe Mathieu-Daudé                    void (*ohci_die_fn)(OHCIState *), Error **errp)
1882f1ae32a1SGerd Hoffmann {
1883f4bbaaf5SMarkus Armbruster     Error *err = NULL;
1884f1ae32a1SGerd Hoffmann     int i;
1885f1ae32a1SGerd Hoffmann 
1886df32fd1cSPaolo Bonzini     ohci->as = as;
188772e0c127SThomas Huth     ohci->ohci_die = ohci_die_fn;
18889ac6a217SDavid Gibson 
1889d400fc01SThomas Huth     if (num_ports > OHCI_MAX_PORTS) {
1890b9a3a4f2SLi Qiang         error_setg(errp, "OHCI num-ports=%u is too big (limit is %u ports)",
1891d400fc01SThomas Huth                    num_ports, OHCI_MAX_PORTS);
1892d400fc01SThomas Huth         return;
1893d400fc01SThomas Huth     }
1894d400fc01SThomas Huth 
1895f1ae32a1SGerd Hoffmann     if (usb_frame_time == 0) {
1896f1ae32a1SGerd Hoffmann #ifdef OHCI_TIME_WARP
189773bcb24dSRutuja Shah         usb_frame_time = NANOSECONDS_PER_SECOND;
189873bcb24dSRutuja Shah         usb_bit_time = NANOSECONDS_PER_SECOND / (USB_HZ / 1000);
1899f1ae32a1SGerd Hoffmann #else
190073bcb24dSRutuja Shah         usb_frame_time = NANOSECONDS_PER_SECOND / 1000;
190173bcb24dSRutuja Shah         if (NANOSECONDS_PER_SECOND >= USB_HZ) {
190273bcb24dSRutuja Shah             usb_bit_time = NANOSECONDS_PER_SECOND / USB_HZ;
1903f1ae32a1SGerd Hoffmann         } else {
1904f1ae32a1SGerd Hoffmann             usb_bit_time = 1;
1905f1ae32a1SGerd Hoffmann         }
1906f1ae32a1SGerd Hoffmann #endif
1907dc1f5988SAlexey Kardashevskiy         trace_usb_ohci_init_time(usb_frame_time, usb_bit_time);
1908f1ae32a1SGerd Hoffmann     }
1909f1ae32a1SGerd Hoffmann 
1910f1ae32a1SGerd Hoffmann     ohci->num_ports = num_ports;
1911f1ae32a1SGerd Hoffmann     if (masterbus) {
1912f1ae32a1SGerd Hoffmann         USBPort *ports[OHCI_MAX_PORTS];
1913f1ae32a1SGerd Hoffmann         for (i = 0; i < num_ports; i++) {
1914f1ae32a1SGerd Hoffmann             ports[i] = &ohci->rhport[i].port;
1915f1ae32a1SGerd Hoffmann         }
1916f4bbaaf5SMarkus Armbruster         usb_register_companion(masterbus, ports, num_ports,
1917f1ae32a1SGerd Hoffmann                                firstport, ohci, &ohci_port_ops,
1918f4bbaaf5SMarkus Armbruster                                USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL,
1919f4bbaaf5SMarkus Armbruster                                &err);
1920f4bbaaf5SMarkus Armbruster         if (err) {
192187581feaSMarkus Armbruster             error_propagate(errp, err);
192287581feaSMarkus Armbruster             return;
1923f1ae32a1SGerd Hoffmann         }
1924f1ae32a1SGerd Hoffmann     } else {
1925c889b3a5SAndreas Färber         usb_bus_new(&ohci->bus, sizeof(ohci->bus), &ohci_bus_ops, dev);
1926f1ae32a1SGerd Hoffmann         for (i = 0; i < num_ports; i++) {
1927f1ae32a1SGerd Hoffmann             usb_register_port(&ohci->bus, &ohci->rhport[i].port,
1928f1ae32a1SGerd Hoffmann                               ohci, i, &ohci_port_ops,
1929f1ae32a1SGerd Hoffmann                               USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
1930f1ae32a1SGerd Hoffmann         }
1931f1ae32a1SGerd Hoffmann     }
1932f1ae32a1SGerd Hoffmann 
193322fc860bSPaolo Bonzini     memory_region_init_io(&ohci->mem, OBJECT(dev), &ohci_mem_ops,
193422fc860bSPaolo Bonzini                           ohci, "ohci", 256);
1935f1ae32a1SGerd Hoffmann     ohci->localmem_base = localmem_base;
1936f1ae32a1SGerd Hoffmann 
1937f1ae32a1SGerd Hoffmann     ohci->name = object_get_typename(OBJECT(dev));
1938f1ae32a1SGerd Hoffmann     usb_packet_init(&ohci->usb_packet);
1939f1ae32a1SGerd Hoffmann 
1940f1ae32a1SGerd Hoffmann     ohci->async_td = 0;
1941fa1298c2SGerd Hoffmann 
1942fa1298c2SGerd Hoffmann     ohci->eof_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
1943fa1298c2SGerd Hoffmann                                    ohci_frame_boundary, ohci);
1944f1ae32a1SGerd Hoffmann }
1945f1ae32a1SGerd Hoffmann 
1946572a6732SBALATON Zoltan /*
194772e0c127SThomas Huth  * A typical OHCI will stop operating and set itself into error state
194872e0c127SThomas Huth  * (which can be queried by MMIO) to signal that it got an error.
1949cf66ee8eSAlexey Kardashevskiy  */
ohci_sysbus_die(struct OHCIState * ohci)195034d97308SThomas Huth void ohci_sysbus_die(struct OHCIState *ohci)
1951cf66ee8eSAlexey Kardashevskiy {
1952dc1f5988SAlexey Kardashevskiy     trace_usb_ohci_die();
1953cf66ee8eSAlexey Kardashevskiy 
1954cf66ee8eSAlexey Kardashevskiy     ohci_set_interrupt(ohci, OHCI_INTR_UE);
1955cf66ee8eSAlexey Kardashevskiy     ohci_bus_stop(ohci);
195672e0c127SThomas Huth }
195772e0c127SThomas Huth 
ohci_realize_pxa(DeviceState * dev,Error ** errp)1958457215ecSHu Tao static void ohci_realize_pxa(DeviceState *dev, Error **errp)
1959f1ae32a1SGerd Hoffmann {
19601aa0c0c7SHu Tao     OHCISysBusState *s = SYSBUS_OHCI(dev);
1961457215ecSHu Tao     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
1962d7145b66SBALATON Zoltan     Error *err = NULL;
1963f1ae32a1SGerd Hoffmann 
1964d7145b66SBALATON Zoltan     usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset,
1965d7145b66SBALATON Zoltan                   s->masterbus, s->firstport,
196672e0c127SThomas Huth                   &address_space_memory, ohci_sysbus_die, &err);
1967d7145b66SBALATON Zoltan     if (err) {
1968d7145b66SBALATON Zoltan         error_propagate(errp, err);
1969d7145b66SBALATON Zoltan         return;
1970d7145b66SBALATON Zoltan     }
1971457215ecSHu Tao     sysbus_init_irq(sbd, &s->ohci.irq);
1972457215ecSHu Tao     sysbus_init_mmio(sbd, &s->ohci.mem);
1973f1ae32a1SGerd Hoffmann }
1974f1ae32a1SGerd Hoffmann 
usb_ohci_reset_sysbus(DeviceState * dev)197588dd1b8dSGonglei static void usb_ohci_reset_sysbus(DeviceState *dev)
197688dd1b8dSGonglei {
197788dd1b8dSGonglei     OHCISysBusState *s = SYSBUS_OHCI(dev);
197888dd1b8dSGonglei     OHCIState *ohci = &s->ohci;
197988dd1b8dSGonglei 
198084d04e21SHervé Poussineau     ohci_hard_reset(ohci);
198188dd1b8dSGonglei }
198288dd1b8dSGonglei 
198369e25d26SAlexey Kardashevskiy static const VMStateDescription vmstate_ohci_state_port = {
198469e25d26SAlexey Kardashevskiy     .name = "ohci-core/port",
198569e25d26SAlexey Kardashevskiy     .version_id = 1,
198669e25d26SAlexey Kardashevskiy     .minimum_version_id = 1,
198769e25d26SAlexey Kardashevskiy     .fields = (VMStateField[]) {
198869e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(ctrl, OHCIPort),
198969e25d26SAlexey Kardashevskiy         VMSTATE_END_OF_LIST()
199069e25d26SAlexey Kardashevskiy     },
199169e25d26SAlexey Kardashevskiy };
199269e25d26SAlexey Kardashevskiy 
ohci_eof_timer_needed(void * opaque)199369e25d26SAlexey Kardashevskiy static bool ohci_eof_timer_needed(void *opaque)
199469e25d26SAlexey Kardashevskiy {
199569e25d26SAlexey Kardashevskiy     OHCIState *ohci = opaque;
199669e25d26SAlexey Kardashevskiy 
1997fa1298c2SGerd Hoffmann     return timer_pending(ohci->eof_timer);
199869e25d26SAlexey Kardashevskiy }
199969e25d26SAlexey Kardashevskiy 
200069e25d26SAlexey Kardashevskiy static const VMStateDescription vmstate_ohci_eof_timer = {
200169e25d26SAlexey Kardashevskiy     .name = "ohci-core/eof-timer",
200269e25d26SAlexey Kardashevskiy     .version_id = 1,
200369e25d26SAlexey Kardashevskiy     .minimum_version_id = 1,
20045cd8cadaSJuan Quintela     .needed = ohci_eof_timer_needed,
200569e25d26SAlexey Kardashevskiy     .fields = (VMStateField[]) {
2006e720677eSPaolo Bonzini         VMSTATE_TIMER_PTR(eof_timer, OHCIState),
200769e25d26SAlexey Kardashevskiy         VMSTATE_END_OF_LIST()
200869e25d26SAlexey Kardashevskiy     },
200969e25d26SAlexey Kardashevskiy };
201069e25d26SAlexey Kardashevskiy 
201134d97308SThomas Huth const VMStateDescription vmstate_ohci_state = {
201269e25d26SAlexey Kardashevskiy     .name = "ohci-core",
201369e25d26SAlexey Kardashevskiy     .version_id = 1,
201469e25d26SAlexey Kardashevskiy     .minimum_version_id = 1,
201569e25d26SAlexey Kardashevskiy     .fields = (VMStateField[]) {
201669e25d26SAlexey Kardashevskiy         VMSTATE_INT64(sof_time, OHCIState),
201769e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(ctl, OHCIState),
201869e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(status, OHCIState),
201969e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(intr_status, OHCIState),
202069e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(intr, OHCIState),
202169e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(hcca, OHCIState),
202269e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(ctrl_head, OHCIState),
202369e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(ctrl_cur, OHCIState),
202469e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(bulk_head, OHCIState),
202569e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(bulk_cur, OHCIState),
202669e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(per_cur, OHCIState),
202769e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(done, OHCIState),
202869e25d26SAlexey Kardashevskiy         VMSTATE_INT32(done_count, OHCIState),
202969e25d26SAlexey Kardashevskiy         VMSTATE_UINT16(fsmps, OHCIState),
203069e25d26SAlexey Kardashevskiy         VMSTATE_UINT8(fit, OHCIState),
203169e25d26SAlexey Kardashevskiy         VMSTATE_UINT16(fi, OHCIState),
203269e25d26SAlexey Kardashevskiy         VMSTATE_UINT8(frt, OHCIState),
203369e25d26SAlexey Kardashevskiy         VMSTATE_UINT16(frame_number, OHCIState),
203469e25d26SAlexey Kardashevskiy         VMSTATE_UINT16(padding, OHCIState),
203569e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(pstart, OHCIState),
203669e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(lst, OHCIState),
203769e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(rhdesc_a, OHCIState),
203869e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(rhdesc_b, OHCIState),
203969e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(rhstatus, OHCIState),
204069e25d26SAlexey Kardashevskiy         VMSTATE_STRUCT_ARRAY(rhport, OHCIState, OHCI_MAX_PORTS, 0,
204169e25d26SAlexey Kardashevskiy                              vmstate_ohci_state_port, OHCIPort),
204269e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(hstatus, OHCIState),
204369e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(hmask, OHCIState),
204469e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(hreset, OHCIState),
204569e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(htest, OHCIState),
204669e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(old_ctl, OHCIState),
204769e25d26SAlexey Kardashevskiy         VMSTATE_UINT8_ARRAY(usb_buf, OHCIState, 8192),
204869e25d26SAlexey Kardashevskiy         VMSTATE_UINT32(async_td, OHCIState),
204969e25d26SAlexey Kardashevskiy         VMSTATE_BOOL(async_complete, OHCIState),
205069e25d26SAlexey Kardashevskiy         VMSTATE_END_OF_LIST()
205169e25d26SAlexey Kardashevskiy     },
20525cd8cadaSJuan Quintela     .subsections = (const VMStateDescription*[]) {
20535cd8cadaSJuan Quintela         &vmstate_ohci_eof_timer,
20545cd8cadaSJuan Quintela         NULL
205569e25d26SAlexey Kardashevskiy     }
205669e25d26SAlexey Kardashevskiy };
205769e25d26SAlexey Kardashevskiy 
2058f1ae32a1SGerd Hoffmann static Property ohci_sysbus_properties[] = {
2059d7145b66SBALATON Zoltan     DEFINE_PROP_STRING("masterbus", OHCISysBusState, masterbus),
2060f1ae32a1SGerd Hoffmann     DEFINE_PROP_UINT32("num-ports", OHCISysBusState, num_ports, 3),
2061d7145b66SBALATON Zoltan     DEFINE_PROP_UINT32("firstport", OHCISysBusState, firstport, 0),
20626998b6c7SVijay Kumar B     DEFINE_PROP_DMAADDR("dma-offset", OHCISysBusState, dma_offset, 0),
2063f1ae32a1SGerd Hoffmann     DEFINE_PROP_END_OF_LIST(),
2064f1ae32a1SGerd Hoffmann };
2065f1ae32a1SGerd Hoffmann 
ohci_sysbus_class_init(ObjectClass * klass,void * data)2066f1ae32a1SGerd Hoffmann static void ohci_sysbus_class_init(ObjectClass *klass, void *data)
2067f1ae32a1SGerd Hoffmann {
2068f1ae32a1SGerd Hoffmann     DeviceClass *dc = DEVICE_CLASS(klass);
2069f1ae32a1SGerd Hoffmann 
2070457215ecSHu Tao     dc->realize = ohci_realize_pxa;
2071125ee0edSMarcel Apfelbaum     set_bit(DEVICE_CATEGORY_USB, dc->categories);
2072f1ae32a1SGerd Hoffmann     dc->desc = "OHCI USB Controller";
20734f67d30bSMarc-André Lureau     device_class_set_props(dc, ohci_sysbus_properties);
207488dd1b8dSGonglei     dc->reset = usb_ohci_reset_sysbus;
2075f1ae32a1SGerd Hoffmann }
2076f1ae32a1SGerd Hoffmann 
20778c43a6f0SAndreas Färber static const TypeInfo ohci_sysbus_info = {
20781aa0c0c7SHu Tao     .name          = TYPE_SYSBUS_OHCI,
2079f1ae32a1SGerd Hoffmann     .parent        = TYPE_SYS_BUS_DEVICE,
2080f1ae32a1SGerd Hoffmann     .instance_size = sizeof(OHCISysBusState),
2081f1ae32a1SGerd Hoffmann     .class_init    = ohci_sysbus_class_init,
2082f1ae32a1SGerd Hoffmann };
2083f1ae32a1SGerd Hoffmann 
ohci_register_types(void)2084f1ae32a1SGerd Hoffmann static void ohci_register_types(void)
2085f1ae32a1SGerd Hoffmann {
2086f1ae32a1SGerd Hoffmann     type_register_static(&ohci_sysbus_info);
2087f1ae32a1SGerd Hoffmann }
2088f1ae32a1SGerd Hoffmann 
2089f1ae32a1SGerd Hoffmann type_init(ohci_register_types)
2090