source: mainline/uspace/drv/bus/usb/xhci/hw_struct/regs.h@ 0e7380f

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 0e7380f was 708d8fcd, checked in by Ondřej Hlavatý <aearsis@…>, 8 years ago

xhci: rewritten isochronous transfers

There was a fundamental problem with relying on hardware to send
RING_OVERRUN/UNDERRUN events, which QEMU (and possibly others) do not
send. That resulted in not knowing if the transfer is still on schedule,
and having to ring the doorbell every time. That is not feasible,
because then the transfer can be more frequent than it should be.
Furthermore, it ignored the fact that isochronous TRBs are to be
scheduled not too late, but also not too soon (see 4.11.2.5 of the xHCI
spec).

Now, scheduling the TRBs to hardware is called feeding, and can be
delayed by setting a timer. Ring overruns/underruns are detected also at
the end of handling an event.

  • Property mode set to 100644
File size: 19.1 KB
Line 
1/*
2 * Copyright (c) 2017 Ondrej Hlavaty
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup drvusbxhci
30 * @{
31 */
32/** @file
33 * Memory-mapped register structures of the xHC.
34 *
35 * The main pr
36 */
37
38#ifndef XHCI_REGS_H
39#define XHCI_REGS_H
40
41#include <macros.h>
42#include <ddi.h>
43#include "common.h"
44
45#define XHCI_PIO_CHANGE_UDELAY 5
46
47/*
48 * These four are the main macros to be used.
49 * Semantics is usual - READ reads value, WRITE changes value, SET sets
50 * selected bits, CLEAR clears selected bits to 0.
51 *
52 * The key thing here is the order of macro expansion, expanding the reg_spec
53 * argument as more arguments (comma delimited) for the inner macro.
54 */
55#define XHCI_REG_RD(reg_set, reg_spec) XHCI_REG_RD_INNER(reg_set, reg_spec)
56#define XHCI_REG_WR(reg_set, reg_spec, value) XHCI_REG_WR_INNER(reg_set, value, reg_spec)
57#define XHCI_REG_SET(reg_set, reg_spec, value) XHCI_REG_SET_INNER(reg_set, value, reg_spec)
58#define XHCI_REG_CLR(reg_set, reg_spec, value) XHCI_REG_CLR_INNER(reg_set, value, reg_spec)
59#define XHCI_REG_MASK(reg_spec) XHCI_REG_MASK_INNER(reg_spec)
60#define XHCI_REG_SHIFT(reg_spec) XHCI_REG_SHIFT_INNER(reg_spec)
61
62/*
63 * These take a pointer to the field, and selects the type-specific macro.
64 */
65#define XHCI_REG_RD_INNER(reg_set, field, size, type, ...) \
66 XHCI_REG_RD_##type(&((reg_set)->field), size, ##__VA_ARGS__)
67
68#define XHCI_REG_WR_INNER(reg_set, value, field, size, type, ...) \
69 XHCI_REG_WR_##type(&(reg_set)->field, value, size, ##__VA_ARGS__)
70
71#define XHCI_REG_SET_INNER(reg_set, value, field, size, type, ...) \
72 XHCI_REG_SET_##type(&(reg_set)->field, value, size, ##__VA_ARGS__)
73
74#define XHCI_REG_CLR_INNER(reg_set, value, field, size, type, ...) \
75 XHCI_REG_CLR_##type(&(reg_set)->field, value, size, ##__VA_ARGS__)
76
77#define XHCI_REG_MASK_INNER(field, size, type, ...) \
78 XHCI_REG_MASK_##type(size, ##__VA_ARGS__)
79
80#define XHCI_REG_SHIFT_INNER(field, size, type, ...) \
81 XHCI_REG_SHIFT_##type(size, ##__VA_ARGS__)
82
83/*
84 * Field handling is the easiest. Just do it with whole field.
85 */
86#define XHCI_REG_RD_FIELD(ptr, size) xhci2host(size, pio_read_##size((ptr)))
87#define XHCI_REG_WR_FIELD(ptr, value, size) pio_write_##size((ptr), host2xhci(size, value))
88#define XHCI_REG_SET_FIELD(ptr, value, size) pio_set_##size((ptr), host2xhci(size, value), XHCI_PIO_CHANGE_UDELAY);
89#define XHCI_REG_CLR_FIELD(ptr, value, size) pio_clear_##size((ptr), host2xhci(size, value), XHCI_PIO_CHANGE_UDELAY);
90#define XHCI_REG_MASK_FIELD(size) (~((uint##size##_t) 0))
91#define XHCI_REG_SHIFT_FIELD(size) (0)
92
93/*
94 * Flags are just trivial case of ranges.
95 */
96#define XHCI_REG_RD_FLAG(ptr, size, offset) XHCI_REG_RD_RANGE((ptr), size, (offset), (offset))
97#define XHCI_REG_WR_FLAG(ptr, value, size, offset) XHCI_REG_WR_RANGE((ptr), (value), size, (offset), (offset))
98#define XHCI_REG_SET_FLAG(ptr, value, size, offset) XHCI_REG_SET_RANGE((ptr), (value), size, (offset), (offset))
99#define XHCI_REG_CLR_FLAG(ptr, value, size, offset) XHCI_REG_CLR_RANGE((ptr), (value), size, (offset), (offset))
100#define XHCI_REG_MASK_FLAG(size, offset) BIT_V(uint##size##_t, offset)
101#define XHCI_REG_SHIFT_FLAG(size, offset) (offset)
102
103/*
104 * Ranges are the most difficult. We need to play around with bitmasks.
105 */
106#define XHCI_REG_RD_RANGE(ptr, size, hi, lo) \
107 BIT_RANGE_EXTRACT(uint##size##_t, (hi), (lo), XHCI_REG_RD_FIELD((ptr), size))
108
109#define XHCI_REG_WR_RANGE(ptr, value, size, hi, lo) \
110 pio_change_##size((ptr), host2xhci(size, BIT_RANGE_INSERT(uint##size##_t, (hi), (lo), (value))), \
111 host2xhci(size, BIT_RANGE(uint##size##_t, (hi), (lo))), \
112 XHCI_PIO_CHANGE_UDELAY);
113
114#define XHCI_REG_SET_RANGE(ptr, value, size, hi, lo) \
115 pio_set_##size((ptr), host2xhci(size, BIT_RANGE_INSERT(uint##size##_t, (hi), (lo), (value))), \
116 XHCI_PIO_CHANGE_UDELAY);
117
118#define XHCI_REG_CLR_RANGE(ptr, value, size, hi, lo) \
119 pio_clear_##size((ptr), host2xhci(size, BIT_RANGE_INSERT(uint##size##_t, (hi), (lo), (value))), \
120 XHCI_PIO_CHANGE_UDELAY);
121
122#define XHCI_REG_MASK_RANGE(size, hi, lo) BIT_RANGE(uint##size##_t, hi, lo)
123#define XHCI_REG_SHIFT_RANGE(size, hi, lo) (lo)
124
125/** HC capability registers: section 5.3 */
126typedef const struct xhci_cap_regs {
127
128 /* Size of this structure, offset for the operation registers */
129 const ioport8_t caplength;
130
131 const PADD8;
132
133 /* BCD of specification version */
134 const ioport16_t hciversion;
135
136 /*
137 * 7:0 - MaxSlots
138 * 18:8 - MaxIntrs
139 * 31:24 - MaxPorts
140 */
141 const ioport32_t hcsparams1;
142
143 /*
144 * 3:0 - IST
145 * 7:4 - ERST Max
146 * 25:21 - Max Scratchpad Bufs Hi
147 * 26 - SPR
148 * 31:27 - Max Scratchpad Bufs Lo
149 */
150 const ioport32_t hcsparams2;
151
152 /*
153 * 7:0 - U1 Device Exit Latency
154 * 31:16 - U2 Device Exit Latency
155 */
156 const ioport32_t hcsparams3;
157
158 /*
159 * 11 10 9 8 7 6 5 4 3 2 1 0
160 * 11:0 - CFC SEC SPC PAE NSS LTC C PIND PPC CSZ BNC AC64
161 * 15:12 - MaxPSASize
162 * 31:16 - xECP
163 */
164 const ioport32_t hccparams1;
165
166 /*
167 * 31:2 - Doorbell Array Offset
168 */
169 const ioport32_t dboff;
170
171 /*
172 * 31:5 - Runtime Register Space Offset
173 */
174 const ioport32_t rtsoff;
175
176 /*
177 * 5 4 3 2 1 0
178 * 5:0 - Flags: CIC LEC CTC FSC CMC U3C
179 */
180 const ioport32_t hccparams2;
181
182 // the rest to operational registers is reserved
183} xhci_cap_regs_t;
184
185/*
186 * The register specifiers are to be used as the reg_spec argument.
187 *
188 * The values are field, bitsize, type, (type specific args)
189 * When the type is RANGE: hi, lo
190 */
191#define XHCI_CAP_LENGTH caplength, 8, FIELD
192#define XHCI_CAP_VERSION hciversion, 16, FIELD
193#define XHCI_CAP_MAX_SLOTS hcsparams1, 32, RANGE, 7, 0
194#define XHCI_CAP_MAX_INTRS hcsparams1, 32, RANGE, 18, 8
195#define XHCI_CAP_MAX_PORTS hcsparams1, 32, RANGE, 31, 24
196#define XHCI_CAP_IST hcsparams2, 32, RANGE, 3, 0
197#define XHCI_CAP_ERST_MAX hcsparams2, 32, RANGE, 7, 4
198#define XHCI_CAP_MAX_SPBUF_HI hcsparams2, 32, RANGE, 25, 21
199#define XHCI_CAP_SPR hcsparams2, 32, FLAG, 26
200#define XHCI_CAP_MAX_SPBUF_LO hcsparams2, 32, RANGE, 31, 27
201#define XHCI_CAP_U1EL hcsparams3, 32, RANGE, 7, 0
202#define XHCI_CAP_U2EL hcsparams3, 32, RANGE, 31, 16
203#define XHCI_CAP_AC64 hccparams1, 32, FLAG, 0
204#define XHCI_CAP_BNC hccparams1, 32, FLAG, 1
205#define XHCI_CAP_CSZ hccparams1, 32, FLAG, 2
206#define XHCI_CAP_PPC hccparams1, 32, FLAG, 3
207#define XHCI_CAP_PIND hccparams1, 32, FLAG, 4
208#define XHCI_CAP_C hccparams1, 32, FLAG, 5
209#define XHCI_CAP_LTC hccparams1, 32, FLAG, 6
210#define XHCI_CAP_NSS hccparams1, 32, FLAG, 7
211#define XHCI_CAP_PAE hccparams1, 32, FLAG, 8
212#define XHCI_CAP_SPC hccparams1, 32, FLAG, 9
213#define XHCI_CAP_SEC hccparams1, 32, FLAG, 10
214#define XHCI_CAP_CFC hccparams1, 32, FLAG, 11
215#define XHCI_CAP_MAX_PSA_SIZE hccparams1, 32, RANGE, 15, 12
216#define XHCI_CAP_XECP hccparams1, 32, RANGE, 31, 16
217#define XHCI_CAP_DBOFF dboff, 32, FIELD
218#define XHCI_CAP_RTSOFF rtsoff, 32, FIELD
219#define XHCI_CAP_U3C hccparams2, 32, FLAG, 0
220#define XHCI_CAP_CMC hccparams2, 32, FLAG, 1
221#define XHCI_CAP_FSC hccparams2, 32, FLAG, 2
222#define XHCI_CAP_CTC hccparams2, 32, FLAG, 3
223#define XHCI_CAP_LEC hccparams2, 32, FLAG, 4
224#define XHCI_CAP_CIC hccparams2, 32, FLAG, 5
225
226static inline unsigned xhci_get_max_spbuf(xhci_cap_regs_t *cap_regs) {
227 return XHCI_REG_RD(cap_regs, XHCI_CAP_MAX_SPBUF_HI) << 5
228 | XHCI_REG_RD(cap_regs, XHCI_CAP_MAX_SPBUF_LO);
229}
230
231/**
232 * XHCI Port Register Set: section 5.4, table 32
233 */
234typedef struct xhci_port_regs {
235 /*
236 * 4 3 2 1 0
237 * 4:0 - PR OCA Z PED CCS
238 * 8:5 - PLS
239 * 9 - PP
240 * 13:10 - Port Speed
241 * 15:14 - PIC
242 * 27 26 25 24 23 22 21 20 19 18 17 16
243 * 27:16 - WOE WDE WCE CAS CEC PLC PRC OCC WRC PEC CSC LWS
244 * 30 - DR
245 * 31 - WPR
246 */
247 ioport32_t portsc;
248
249 /*
250 * Contents of this fields depends on the protocol supported by the port.
251 * USB3:
252 * 7:0 - U1 Timeout
253 * 15:8 - U2 Timeout
254 * 16 - Force Link PM Accept
255 * USB2:
256 * 2:0 - L1S
257 * 3 - RWE
258 * 7:4 - BESL
259 * 15:8 - L1 Device Slot
260 * 16 - HLE
261 * 31:28 - Test Mode
262 */
263 ioport32_t portpmsc;
264
265 /*
266 * This field is valid only for USB3 ports.
267 * 15:0 - Link Error Count
268 * 19:16 - RLC
269 * 23:20 - TLC
270 */
271 ioport32_t portli;
272
273 /*
274 * This field is valid only for USB2 ports.
275 * 1:0 - HIRDM
276 * 9:2 - L1 Timeout
277 * 13:10 - BESLD
278 */
279 ioport32_t porthlpmc;
280} xhci_port_regs_t;
281
282#define XHCI_PORT_CCS portsc, 32, FLAG, 0
283#define XHCI_PORT_PED portsc, 32, FLAG, 1
284#define XHCI_PORT_OCA portsc, 32, FLAG, 3
285#define XHCI_PORT_PR portsc, 32, FLAG, 4
286#define XHCI_PORT_PLS portsc, 32, RANGE, 8, 5
287#define XHCI_PORT_PP portsc, 32, FLAG, 9
288#define XHCI_PORT_PS portsc, 32, RANGE, 13, 10
289#define XHCI_PORT_PIC portsc, 32, RANGE, 15, 14
290#define XHCI_PORT_LWS portsc, 32, FLAG, 16
291#define XHCI_PORT_CSC portsc, 32, FLAG, 17
292#define XHCI_PORT_PEC portsc, 32, FLAG, 18
293#define XHCI_PORT_WRC portsc, 32, FLAG, 19
294#define XHCI_PORT_OCC portsc, 32, FLAG, 20
295#define XHCI_PORT_PRC portsc, 32, FLAG, 21
296#define XHCI_PORT_PLC portsc, 32, FLAG, 22
297#define XHCI_PORT_CEC portsc, 32, FLAG, 23
298#define XHCI_PORT_CAS portsc, 32, FLAG, 24
299#define XHCI_PORT_WCE portsc, 32, FLAG, 25
300#define XHCI_PORT_WDE portsc, 32, FLAG, 26
301#define XHCI_PORT_WOE portsc, 32, FLAG, 27
302#define XHCI_PORT_DR portsc, 32, FLAG, 28
303#define XHCI_PORT_WPR portsc, 32, FLAG, 29
304
305#define XHCI_PORT_USB3_U1TO portpmsc, 32, RANGE, 7, 0
306#define XHCI_PORT_USB3_U2TO portpmsc, 32, RANGE, 15, 8
307#define XHCI_PORT_USB3_FLPMA portpmsc, 32, FLAG, 16
308#define XHCI_PORT_USB3_LEC portli, 32, RANGE, 15, 0
309#define XHCI_PORT_USB3_RLC portli, 32, RANGE, 19, 16
310#define XHCI_PORT_USB3_TLC portli, 32, RANGE, 23, 20
311
312#define XHCI_PORT_USB2_L1S portpmsc, 32, RANGE, 2, 0
313#define XHCI_PORT_USB2_RWE portpmsc, 32, FLAG, 3
314#define XHCI_PORT_USB2_BESL portpmsc, 32, RANGE, 7, 4
315#define XHCI_PORT_USB2_L1DS portpmsc, 32, RANGE, 15, 8
316#define XHCI_PORT_USB2_HLE portpmsc, 32, FLAG, 16
317#define XHCI_PORT_USB2_TM portpmsc, 32, RANGE, 31, 28
318#define XHCI_PORT_USB2_HIRDM porthlmpc, 32, RANGE, 1, 0
319#define XHCI_PORT_USB2_L1TO porthlmpc, 32, RANGE, 9, 2
320#define XHCI_PORT_USB2_BESLD porthlmpc, 32, RANGE, 13, 10
321
322/**
323 * XHCI Operational Registers: section 5.4
324 */
325typedef struct xhci_op_regs {
326
327 /*
328 * 3 2 1 0
329 * 3:0 - HSEE INTE HCRST R/S
330 *
331 * 11 10 9 8 7
332 * 11:7 - EU3S EWE CRS CSS LHCRST
333 * 13 - CME
334 */
335 ioport32_t usbcmd;
336
337 /*
338 * 4 3 2 1 0
339 * 4:0 - PCD EINT HSE _ HCH
340 *
341 * 12 11 10 9 8
342 * 12:8 - HCE CNR SRE RSS SSS
343 */
344 ioport32_t usbsts;
345
346 /*
347 * Bitmask of page sizes supported: 128M .. 4K
348 */
349 ioport32_t pagesize;
350
351 PADD32[2];
352
353 /*
354 * 15:0 - Notification enable
355 */
356 ioport32_t dnctrl;
357
358 /* 3 2 1 0
359 * 3:0 - CRR CA CS RCS
360 * 64:6 - Command Ring Pointer
361 */
362 ioport32_t crcr_lo;
363 ioport32_t crcr_hi;
364
365 PADD32[4];
366
367 ioport32_t dcbaap_lo;
368 ioport32_t dcbaap_hi;
369
370 /*
371 * 7:0 - MaxSlotsEn
372 * 8 - U3E
373 * 9 - CIE
374 */
375 ioport32_t config;
376
377 /* Offset of portrs from op_regs addr is 0x400. */
378 PADD32[241];
379
380 /*
381 * Individual ports register sets
382 */
383 xhci_port_regs_t portrs[256];
384} xhci_op_regs_t;
385
386#define XHCI_OP_RS usbcmd, 32, FLAG, 0
387#define XHCI_OP_HCRST usbcmd, 32, FLAG, 1
388#define XHCI_OP_INTE usbcmd, 32, FLAG, 2
389#define XHCI_OP_HSEE usbcmd, 32, FLAG, 3
390#define XHCI_OP_LHCRST usbcmd, 32, FLAG, 7
391#define XHCI_OP_CSS usbcmd, 32, FLAG, 8
392#define XHCI_OP_CRS usbcmd, 32, FLAG, 9
393#define XHCI_OP_EWE usbcmd, 32, FLAG, 10
394#define XHCI_OP_EU3S usbcmd, 32, FLAG, 11
395#define XHCI_OP_CME usbcmd, 32, FLAG, 13
396#define XHCI_OP_HCH usbsts, 32, FLAG, 0
397#define XHCI_OP_HSE usbsts, 32, FLAG, 2
398#define XHCI_OP_EINT usbsts, 32, FLAG, 3
399#define XHCI_OP_PCD usbsts, 32, FLAG, 4
400#define XHCI_OP_SSS usbsts, 32, FLAG, 8
401#define XHCI_OP_RSS usbsts, 32, FLAG, 9
402#define XHCI_OP_SRE usbsts, 32, FLAG, 10
403#define XHCI_OP_CNR usbsts, 32, FLAG, 11
404#define XHCI_OP_HCE usbsts, 32, FLAG, 12
405#define XHCI_OP_PAGESIZE pagesize, 32, FIELD
406#define XHCI_OP_NOTIFICATION dnctrl, 32, RANGE, 15, 0
407#define XHCI_OP_RCS crcr_lo, 32, FLAG, 0
408#define XHCI_OP_CS crcr_lo, 32, FLAG, 1
409#define XHCI_OP_CA crcr_lo, 32, FLAG, 2
410#define XHCI_OP_CRR crcr_lo, 32, FLAG, 3
411/* This shall be RANGE, 6, 0, but the value containing CR pointer and RCS flag
412 * must be written at once. */
413#define XHCI_OP_CRCR_LO crcr_lo, 32, FIELD
414#define XHCI_OP_CRCR_HI crcr_hi, 32, FIELD
415#define XHCI_OP_DCBAAP_LO dcbaap_lo, 32, FIELD
416#define XHCI_OP_DCBAAP_HI dcbaap_hi, 32, FIELD
417#define XHCI_OP_MAX_SLOTS_EN config, 32, RANGE, 7, 0
418#define XHCI_OP_U3E config, 32, FLAG, 8
419#define XHCI_OP_CIE config, 32, FLAG, 9
420
421/* Aggregating field to read & write whole status at once */
422#define XHCI_OP_STATUS usbsts, 32, RANGE, 12, 0
423
424/* RW1C fields in usbsts */
425#define XHCI_STATUS_ACK_MASK 0x41C
426
427/**
428 * Interrupter Register Set: section 5.5.2
429 */
430typedef struct xhci_interrupter_regs {
431 /*
432 * 0 - Interrupt Pending
433 * 1 - Interrupt Enable
434 */
435 ioport32_t iman;
436
437 /*
438 * 15:0 - Interrupt Moderation Interval
439 * 31:16 - Interrupt Moderation Counter
440 */
441 ioport32_t imod;
442
443 ioport32_t erstsz;
444
445 PADD32;
446
447 ioport32_t erstba_lo;
448 ioport32_t erstba_hi;
449
450 /*
451 * 2:0 - Dequeue ERST Segment Index
452 * 3 - Event Handler Busy
453 * 63:4 - Event Ring Dequeue Pointer
454 */
455 ioport32_t erdp_lo;
456 ioport32_t erdp_hi;
457} xhci_interrupter_regs_t;
458
459#define XHCI_INTR_IP iman, 32, FLAG, 0
460#define XHCI_INTR_IE iman, 32, FLAG, 1
461#define XHCI_INTR_IMI imod, 32, RANGE, 15, 0
462#define XHCI_INTR_IMC imod, 32, RANGE, 31, 16
463#define XHCI_INTR_ERSTSZ erstsz, 32, FIELD
464#define XHCI_INTR_ERSTBA_LO erstba_lo, 32, FIELD
465#define XHCI_INTR_ERSTBA_HI erstba_hi, 32, FIELD
466#define XHCI_INTR_ERDP_ESI erdp_lo, 32, RANGE, 2, 0
467#define XHCI_INTR_ERDP_EHB erdp_lo, 32, FLAG, 3
468// TODO: ERDP_LO is supposed to be RANGE 31, 4 (section 5.5.2.3.3).
469#define XHCI_INTR_ERDP_LO erdp_lo, 32, FIELD
470#define XHCI_INTR_ERDP_HI erdp_hi, 32, FIELD
471
472/**
473 * XHCI Runtime registers: section 5.5
474 */
475typedef struct xhci_rt_regs {
476 ioport32_t mfindex;
477
478 PADD32 [7];
479
480 xhci_interrupter_regs_t ir [];
481} xhci_rt_regs_t;
482
483#define XHCI_RT_MFINDEX mfindex, 32, RANGE, 13, 0
484#define XHCI_MFINDEX_MAX (1 << 14)
485
486/**
487 * XHCI Doorbell Registers: section 5.6
488 *
489 * These registers are to be written as a whole field.
490 */
491typedef ioport32_t xhci_doorbell_t;
492
493enum xhci_plt {
494 XHCI_PSI_PLT_SYMM,
495 XHCI_PSI_PLT_RSVD,
496 XHCI_PSI_PLT_RX,
497 XHCI_PSI_PLT_TX
498};
499
500/**
501 * Protocol speed ID: section 7.2.1
502 */
503typedef struct xhci_psi {
504 xhci_dword_t psi;
505} xhci_psi_t;
506
507#define XHCI_PSI_PSIV psi, 32, RANGE, 3, 0
508#define XHCI_PSI_PSIE psi, 32, RANGE, 5, 4
509#define XHCI_PSI_PLT psi, 32, RANGE, 7, 6
510#define XHCI_PSI_PFD psi, 32, FLAG, 8
511#define XHCI_PSI_PSIM psi, 32, RANGE, 31, 16
512
513enum xhci_extcap_type {
514 XHCI_EC_RESERVED = 0,
515 XHCI_EC_USB_LEGACY,
516 XHCI_EC_SUPPORTED_PROTOCOL,
517 XHCI_EC_EXTENDED_POWER_MANAGEMENT,
518 XHCI_EC_IOV,
519 XHCI_EC_MSI,
520 XHCI_EC_LOCALMEM,
521 XHCI_EC_DEBUG = 10,
522 XHCI_EC_MSIX = 17,
523 XHCI_EC_MAX = 255
524};
525
526/**
527 * xHCI Extended Capability: section 7
528 */
529typedef struct xhci_extcap {
530 xhci_dword_t header;
531 xhci_dword_t cap_specific[];
532} xhci_extcap_t;
533
534#define XHCI_EC_CAP_ID header, 32, RANGE, 7, 0
535#define XHCI_EC_SIZE header, 32, RANGE, 15, 8
536
537/* Supported protocol */
538#define XHCI_EC_SP_MINOR header, 32, RANGE, 23, 16
539#define XHCI_EC_SP_MAJOR header, 32, RANGE, 31, 24
540#define XHCI_EC_SP_NAME cap_specific[0], 32, FIELD
541#define XHCI_EC_SP_CP_OFF cap_specific[1], 32, RANGE, 7, 0
542#define XHCI_EC_SP_CP_COUNT cap_specific[1], 32, RANGE, 15, 8
543#define XHCI_EC_SP_PSIC cap_specific[1], 32, RANGE, 31, 28
544#define XHCI_EC_SP_SLOT_TYPE cap_specific[2], 32, RANGE, 4, 0
545
546typedef union {
547 char str [4];
548 uint32_t packed;
549} xhci_sp_name_t;
550
551static const xhci_sp_name_t xhci_name_usb = {
552 .str = "USB "
553};
554
555static inline xhci_extcap_t *xhci_extcap_next(const xhci_extcap_t *cur)
556{
557 unsigned dword_offset = XHCI_REG_RD(cur, XHCI_EC_SIZE);
558 if (!dword_offset)
559 return NULL;
560 return (xhci_extcap_t *) (((xhci_dword_t *) cur) + dword_offset);
561}
562
563static inline xhci_psi_t *xhci_extcap_psi(const xhci_extcap_t *ec, unsigned psid)
564{
565 assert(XHCI_REG_RD(ec, XHCI_EC_CAP_ID) == XHCI_EC_SUPPORTED_PROTOCOL);
566 assert(XHCI_REG_RD(ec, XHCI_EC_SP_PSIC) > psid);
567
568 unsigned dword_offset = 4 + psid;
569 return (xhci_psi_t *) (((xhci_dword_t *) ec) + dword_offset);
570}
571
572/**
573 * USB Legacy Support: section 7.1
574 *
575 * Legacy support have an exception from dword-access, because it needs to be
576 * byte-accessed.
577 */
578typedef struct xhci_extcap_legsup {
579 ioport8_t cap_id;
580 ioport8_t size; /**< Next Capability Pointer */
581 ioport8_t sem_bios;
582 ioport8_t sem_os;
583
584 xhci_dword_t usblegctlsts; /**< USB Legacy Support Control/Status - RW for BIOS, RO for OS */
585} xhci_legsup_t;
586
587#define XHCI_LEGSUP_SEM_BIOS sem_bios, 8, FLAG, 0
588#define XHCI_LEGSUP_SEM_OS sem_os, 8, FLAG, 0
589
590#define XHCI_LEGSUP_POLLING_DELAY_1MS 1000
591#define XHCI_LEGSUP_BIOS_TIMEOUT_US 1000000 /* 4.22.1 BIOS may take up to 1 second to release the device */
592
593#endif
594/**
595 * @}
596 */
Note: See TracBrowser for help on using the repository browser.