Statistics
| Branch: | Revision:

root / hw / usb-ohci.c @ d47e59b8

History | View | Annotate | Download (50.9 kB)

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