root / hw / usb / hcd-ehci.h @ 9c17d615
History | View | Annotate | Download (10.1 kB)
1 |
/*
|
---|---|
2 |
* QEMU USB EHCI Emulation
|
3 |
*
|
4 |
* This library is free software; you can redistribute it and/or
|
5 |
* modify it under the terms of the GNU Lesser General Public
|
6 |
* License as published by the Free Software Foundation; either
|
7 |
* version 2 of the License, or(at your option) any later version.
|
8 |
*
|
9 |
* This library is distributed in the hope that it will be useful,
|
10 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12 |
* Lesser General Public License for more details.
|
13 |
*
|
14 |
* You should have received a copy of the GNU General Public License
|
15 |
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
16 |
*/
|
17 |
#ifndef HW_USB_EHCI_H
|
18 |
#define HW_USB_EHCI_H 1 |
19 |
|
20 |
#include "hw/hw.h" |
21 |
#include "qemu/timer.h" |
22 |
#include "hw/usb.h" |
23 |
#include "monitor/monitor.h" |
24 |
#include "trace.h" |
25 |
#include "sysemu/dma.h" |
26 |
#include "sysemu/sysemu.h" |
27 |
|
28 |
#ifndef EHCI_DEBUG
|
29 |
#define EHCI_DEBUG 0 |
30 |
#endif
|
31 |
|
32 |
#if EHCI_DEBUG
|
33 |
#define DPRINTF printf
|
34 |
#else
|
35 |
#define DPRINTF(...)
|
36 |
#endif
|
37 |
|
38 |
#define MMIO_SIZE 0x1000 |
39 |
#define CAPA_SIZE 0x10 |
40 |
|
41 |
#define PORTSC 0x0044 |
42 |
#define PORTSC_BEGIN PORTSC
|
43 |
#define PORTSC_END (PORTSC + 4 * NB_PORTS) |
44 |
|
45 |
#define NB_PORTS 6 /* Number of downstream ports */ |
46 |
|
47 |
typedef struct EHCIPacket EHCIPacket; |
48 |
typedef struct EHCIQueue EHCIQueue; |
49 |
typedef struct EHCIState EHCIState; |
50 |
|
51 |
/* EHCI spec version 1.0 Section 3.3
|
52 |
*/
|
53 |
typedef struct EHCIitd { |
54 |
uint32_t next; |
55 |
|
56 |
uint32_t transact[8];
|
57 |
#define ITD_XACT_ACTIVE (1 << 31) |
58 |
#define ITD_XACT_DBERROR (1 << 30) |
59 |
#define ITD_XACT_BABBLE (1 << 29) |
60 |
#define ITD_XACT_XACTERR (1 << 28) |
61 |
#define ITD_XACT_LENGTH_MASK 0x0fff0000 |
62 |
#define ITD_XACT_LENGTH_SH 16 |
63 |
#define ITD_XACT_IOC (1 << 15) |
64 |
#define ITD_XACT_PGSEL_MASK 0x00007000 |
65 |
#define ITD_XACT_PGSEL_SH 12 |
66 |
#define ITD_XACT_OFFSET_MASK 0x00000fff |
67 |
|
68 |
uint32_t bufptr[7];
|
69 |
#define ITD_BUFPTR_MASK 0xfffff000 |
70 |
#define ITD_BUFPTR_SH 12 |
71 |
#define ITD_BUFPTR_EP_MASK 0x00000f00 |
72 |
#define ITD_BUFPTR_EP_SH 8 |
73 |
#define ITD_BUFPTR_DEVADDR_MASK 0x0000007f |
74 |
#define ITD_BUFPTR_DEVADDR_SH 0 |
75 |
#define ITD_BUFPTR_DIRECTION (1 << 11) |
76 |
#define ITD_BUFPTR_MAXPKT_MASK 0x000007ff |
77 |
#define ITD_BUFPTR_MAXPKT_SH 0 |
78 |
#define ITD_BUFPTR_MULT_MASK 0x00000003 |
79 |
#define ITD_BUFPTR_MULT_SH 0 |
80 |
} EHCIitd; |
81 |
|
82 |
/* EHCI spec version 1.0 Section 3.4
|
83 |
*/
|
84 |
typedef struct EHCIsitd { |
85 |
uint32_t next; /* Standard next link pointer */
|
86 |
uint32_t epchar; |
87 |
#define SITD_EPCHAR_IO (1 << 31) |
88 |
#define SITD_EPCHAR_PORTNUM_MASK 0x7f000000 |
89 |
#define SITD_EPCHAR_PORTNUM_SH 24 |
90 |
#define SITD_EPCHAR_HUBADD_MASK 0x007f0000 |
91 |
#define SITD_EPCHAR_HUBADDR_SH 16 |
92 |
#define SITD_EPCHAR_EPNUM_MASK 0x00000f00 |
93 |
#define SITD_EPCHAR_EPNUM_SH 8 |
94 |
#define SITD_EPCHAR_DEVADDR_MASK 0x0000007f |
95 |
|
96 |
uint32_t uframe; |
97 |
#define SITD_UFRAME_CMASK_MASK 0x0000ff00 |
98 |
#define SITD_UFRAME_CMASK_SH 8 |
99 |
#define SITD_UFRAME_SMASK_MASK 0x000000ff |
100 |
|
101 |
uint32_t results; |
102 |
#define SITD_RESULTS_IOC (1 << 31) |
103 |
#define SITD_RESULTS_PGSEL (1 << 30) |
104 |
#define SITD_RESULTS_TBYTES_MASK 0x03ff0000 |
105 |
#define SITD_RESULTS_TYBYTES_SH 16 |
106 |
#define SITD_RESULTS_CPROGMASK_MASK 0x0000ff00 |
107 |
#define SITD_RESULTS_CPROGMASK_SH 8 |
108 |
#define SITD_RESULTS_ACTIVE (1 << 7) |
109 |
#define SITD_RESULTS_ERR (1 << 6) |
110 |
#define SITD_RESULTS_DBERR (1 << 5) |
111 |
#define SITD_RESULTS_BABBLE (1 << 4) |
112 |
#define SITD_RESULTS_XACTERR (1 << 3) |
113 |
#define SITD_RESULTS_MISSEDUF (1 << 2) |
114 |
#define SITD_RESULTS_SPLITXSTATE (1 << 1) |
115 |
|
116 |
uint32_t bufptr[2];
|
117 |
#define SITD_BUFPTR_MASK 0xfffff000 |
118 |
#define SITD_BUFPTR_CURROFF_MASK 0x00000fff |
119 |
#define SITD_BUFPTR_TPOS_MASK 0x00000018 |
120 |
#define SITD_BUFPTR_TPOS_SH 3 |
121 |
#define SITD_BUFPTR_TCNT_MASK 0x00000007 |
122 |
|
123 |
uint32_t backptr; /* Standard next link pointer */
|
124 |
} EHCIsitd; |
125 |
|
126 |
/* EHCI spec version 1.0 Section 3.5
|
127 |
*/
|
128 |
typedef struct EHCIqtd { |
129 |
uint32_t next; /* Standard next link pointer */
|
130 |
uint32_t altnext; /* Standard next link pointer */
|
131 |
uint32_t token; |
132 |
#define QTD_TOKEN_DTOGGLE (1 << 31) |
133 |
#define QTD_TOKEN_TBYTES_MASK 0x7fff0000 |
134 |
#define QTD_TOKEN_TBYTES_SH 16 |
135 |
#define QTD_TOKEN_IOC (1 << 15) |
136 |
#define QTD_TOKEN_CPAGE_MASK 0x00007000 |
137 |
#define QTD_TOKEN_CPAGE_SH 12 |
138 |
#define QTD_TOKEN_CERR_MASK 0x00000c00 |
139 |
#define QTD_TOKEN_CERR_SH 10 |
140 |
#define QTD_TOKEN_PID_MASK 0x00000300 |
141 |
#define QTD_TOKEN_PID_SH 8 |
142 |
#define QTD_TOKEN_ACTIVE (1 << 7) |
143 |
#define QTD_TOKEN_HALT (1 << 6) |
144 |
#define QTD_TOKEN_DBERR (1 << 5) |
145 |
#define QTD_TOKEN_BABBLE (1 << 4) |
146 |
#define QTD_TOKEN_XACTERR (1 << 3) |
147 |
#define QTD_TOKEN_MISSEDUF (1 << 2) |
148 |
#define QTD_TOKEN_SPLITXSTATE (1 << 1) |
149 |
#define QTD_TOKEN_PING (1 << 0) |
150 |
|
151 |
uint32_t bufptr[5]; /* Standard buffer pointer */ |
152 |
#define QTD_BUFPTR_MASK 0xfffff000 |
153 |
#define QTD_BUFPTR_SH 12 |
154 |
} EHCIqtd; |
155 |
|
156 |
/* EHCI spec version 1.0 Section 3.6
|
157 |
*/
|
158 |
typedef struct EHCIqh { |
159 |
uint32_t next; /* Standard next link pointer */
|
160 |
|
161 |
/* endpoint characteristics */
|
162 |
uint32_t epchar; |
163 |
#define QH_EPCHAR_RL_MASK 0xf0000000 |
164 |
#define QH_EPCHAR_RL_SH 28 |
165 |
#define QH_EPCHAR_C (1 << 27) |
166 |
#define QH_EPCHAR_MPLEN_MASK 0x07FF0000 |
167 |
#define QH_EPCHAR_MPLEN_SH 16 |
168 |
#define QH_EPCHAR_H (1 << 15) |
169 |
#define QH_EPCHAR_DTC (1 << 14) |
170 |
#define QH_EPCHAR_EPS_MASK 0x00003000 |
171 |
#define QH_EPCHAR_EPS_SH 12 |
172 |
#define EHCI_QH_EPS_FULL 0 |
173 |
#define EHCI_QH_EPS_LOW 1 |
174 |
#define EHCI_QH_EPS_HIGH 2 |
175 |
#define EHCI_QH_EPS_RESERVED 3 |
176 |
|
177 |
#define QH_EPCHAR_EP_MASK 0x00000f00 |
178 |
#define QH_EPCHAR_EP_SH 8 |
179 |
#define QH_EPCHAR_I (1 << 7) |
180 |
#define QH_EPCHAR_DEVADDR_MASK 0x0000007f |
181 |
#define QH_EPCHAR_DEVADDR_SH 0 |
182 |
|
183 |
/* endpoint capabilities */
|
184 |
uint32_t epcap; |
185 |
#define QH_EPCAP_MULT_MASK 0xc0000000 |
186 |
#define QH_EPCAP_MULT_SH 30 |
187 |
#define QH_EPCAP_PORTNUM_MASK 0x3f800000 |
188 |
#define QH_EPCAP_PORTNUM_SH 23 |
189 |
#define QH_EPCAP_HUBADDR_MASK 0x007f0000 |
190 |
#define QH_EPCAP_HUBADDR_SH 16 |
191 |
#define QH_EPCAP_CMASK_MASK 0x0000ff00 |
192 |
#define QH_EPCAP_CMASK_SH 8 |
193 |
#define QH_EPCAP_SMASK_MASK 0x000000ff |
194 |
#define QH_EPCAP_SMASK_SH 0 |
195 |
|
196 |
uint32_t current_qtd; /* Standard next link pointer */
|
197 |
uint32_t next_qtd; /* Standard next link pointer */
|
198 |
uint32_t altnext_qtd; |
199 |
#define QH_ALTNEXT_NAKCNT_MASK 0x0000001e |
200 |
#define QH_ALTNEXT_NAKCNT_SH 1 |
201 |
|
202 |
uint32_t token; /* Same as QTD token */
|
203 |
uint32_t bufptr[5]; /* Standard buffer pointer */ |
204 |
#define BUFPTR_CPROGMASK_MASK 0x000000ff |
205 |
#define BUFPTR_FRAMETAG_MASK 0x0000001f |
206 |
#define BUFPTR_SBYTES_MASK 0x00000fe0 |
207 |
#define BUFPTR_SBYTES_SH 5 |
208 |
} EHCIqh; |
209 |
|
210 |
/* EHCI spec version 1.0 Section 3.7
|
211 |
*/
|
212 |
typedef struct EHCIfstn { |
213 |
uint32_t next; /* Standard next link pointer */
|
214 |
uint32_t backptr; /* Standard next link pointer */
|
215 |
} EHCIfstn; |
216 |
|
217 |
enum async_state {
|
218 |
EHCI_ASYNC_NONE = 0,
|
219 |
EHCI_ASYNC_INITIALIZED, |
220 |
EHCI_ASYNC_INFLIGHT, |
221 |
EHCI_ASYNC_FINISHED, |
222 |
}; |
223 |
|
224 |
struct EHCIPacket {
|
225 |
EHCIQueue *queue; |
226 |
QTAILQ_ENTRY(EHCIPacket) next; |
227 |
|
228 |
EHCIqtd qtd; /* copy of current QTD (being worked on) */
|
229 |
uint32_t qtdaddr; /* address QTD read from */
|
230 |
|
231 |
USBPacket packet; |
232 |
QEMUSGList sgl; |
233 |
int pid;
|
234 |
enum async_state async;
|
235 |
}; |
236 |
|
237 |
struct EHCIQueue {
|
238 |
EHCIState *ehci; |
239 |
QTAILQ_ENTRY(EHCIQueue) next; |
240 |
uint32_t seen; |
241 |
uint64_t ts; |
242 |
int async;
|
243 |
int transact_ctr;
|
244 |
|
245 |
/* cached data from guest - needs to be flushed
|
246 |
* when guest removes an entry (doorbell, handshake sequence)
|
247 |
*/
|
248 |
EHCIqh qh; /* copy of current QH (being worked on) */
|
249 |
uint32_t qhaddr; /* address QH read from */
|
250 |
uint32_t qtdaddr; /* address QTD read from */
|
251 |
USBDevice *dev; |
252 |
QTAILQ_HEAD(pkts_head, EHCIPacket) packets; |
253 |
}; |
254 |
|
255 |
typedef QTAILQ_HEAD(EHCIQueueHead, EHCIQueue) EHCIQueueHead;
|
256 |
|
257 |
struct EHCIState {
|
258 |
USBBus bus; |
259 |
qemu_irq irq; |
260 |
MemoryRegion mem; |
261 |
DMAContext *dma; |
262 |
MemoryRegion mem_caps; |
263 |
MemoryRegion mem_opreg; |
264 |
MemoryRegion mem_ports; |
265 |
int companion_count;
|
266 |
uint16_t capsbase; |
267 |
uint16_t opregbase; |
268 |
|
269 |
/* properties */
|
270 |
uint32_t maxframes; |
271 |
|
272 |
/*
|
273 |
* EHCI spec version 1.0 Section 2.3
|
274 |
* Host Controller Operational Registers
|
275 |
*/
|
276 |
uint8_t caps[CAPA_SIZE]; |
277 |
union {
|
278 |
uint32_t opreg[PORTSC_BEGIN/sizeof(uint32_t)];
|
279 |
struct {
|
280 |
uint32_t usbcmd; |
281 |
uint32_t usbsts; |
282 |
uint32_t usbintr; |
283 |
uint32_t frindex; |
284 |
uint32_t ctrldssegment; |
285 |
uint32_t periodiclistbase; |
286 |
uint32_t asynclistaddr; |
287 |
uint32_t notused[9];
|
288 |
uint32_t configflag; |
289 |
}; |
290 |
}; |
291 |
uint32_t portsc[NB_PORTS]; |
292 |
|
293 |
/*
|
294 |
* Internal states, shadow registers, etc
|
295 |
*/
|
296 |
QEMUTimer *frame_timer; |
297 |
QEMUBH *async_bh; |
298 |
uint32_t astate; /* Current state in asynchronous schedule */
|
299 |
uint32_t pstate; /* Current state in periodic schedule */
|
300 |
USBPort ports[NB_PORTS]; |
301 |
USBPort *companion_ports[NB_PORTS]; |
302 |
uint32_t usbsts_pending; |
303 |
uint32_t usbsts_frindex; |
304 |
EHCIQueueHead aqueues; |
305 |
EHCIQueueHead pqueues; |
306 |
|
307 |
/* which address to look at next */
|
308 |
uint32_t a_fetch_addr; |
309 |
uint32_t p_fetch_addr; |
310 |
|
311 |
USBPacket ipacket; |
312 |
QEMUSGList isgl; |
313 |
|
314 |
uint64_t last_run_ns; |
315 |
uint32_t async_stepdown; |
316 |
uint32_t periodic_sched_active; |
317 |
bool int_req_by_async;
|
318 |
}; |
319 |
|
320 |
extern const VMStateDescription vmstate_ehci; |
321 |
|
322 |
void usb_ehci_initfn(EHCIState *s, DeviceState *dev);
|
323 |
|
324 |
#endif
|