source: mainline/uspace/drv/bus/usb/xhci/hw_struct/regs.h@ 7c3fb9b

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 7c3fb9b was 7c3fb9b, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Fix block comment formatting (ccheck).

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