source: mainline/uspace/drv/bus/usb/xhci/hw_struct/regs.h@ 76d0981d

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

Modify PADDn macros so that their use is easier to parse.

  • 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 return XHCI_REG_RD(cap_regs, XHCI_CAP_MAX_SPBUF_HI) << 5
239 | XHCI_REG_RD(cap_regs, XHCI_CAP_MAX_SPBUF_LO);
240}
241
242/**
243 * XHCI Port Register Set: section 5.4, table 32
244 */
245typedef struct xhci_port_regs {
246 /*
247 * 4 3 2 1 0
248 * 4:0 - PR OCA Z PED CCS
249 * 8:5 - PLS
250 * 9 - PP
251 * 13:10 - Port Speed
252 * 15:14 - PIC
253 * 27 26 25 24 23 22 21 20 19 18 17 16
254 * 27:16 - WOE WDE WCE CAS CEC PLC PRC OCC WRC PEC CSC LWS
255 * 30 - DR
256 * 31 - WPR
257 */
258 ioport32_t portsc;
259
260 /*
261 * Contents of this fields depends on the protocol supported by the port.
262 * USB3:
263 * 7:0 - U1 Timeout
264 * 15:8 - U2 Timeout
265 * 16 - Force Link PM Accept
266 * USB2:
267 * 2:0 - L1S
268 * 3 - RWE
269 * 7:4 - BESL
270 * 15:8 - L1 Device Slot
271 * 16 - HLE
272 * 31:28 - Test Mode
273 */
274 ioport32_t portpmsc;
275
276 /*
277 * This field is valid only for USB3 ports.
278 * 15:0 - Link Error Count
279 * 19:16 - RLC
280 * 23:20 - TLC
281 */
282 ioport32_t portli;
283
284 /*
285 * This field is valid only for USB2 ports.
286 * 1:0 - HIRDM
287 * 9:2 - L1 Timeout
288 * 13:10 - BESLD
289 */
290 ioport32_t porthlpmc;
291} xhci_port_regs_t;
292
293#define XHCI_PORT_CCS portsc, 32, FLAG, 0
294#define XHCI_PORT_PED portsc, 32, FLAG, 1
295#define XHCI_PORT_OCA portsc, 32, FLAG, 3
296#define XHCI_PORT_PR portsc, 32, FLAG, 4
297#define XHCI_PORT_PLS portsc, 32, RANGE, 8, 5
298#define XHCI_PORT_PP portsc, 32, FLAG, 9
299#define XHCI_PORT_PS portsc, 32, RANGE, 13, 10
300#define XHCI_PORT_PIC portsc, 32, RANGE, 15, 14
301#define XHCI_PORT_LWS portsc, 32, FLAG, 16
302#define XHCI_PORT_CSC portsc, 32, FLAG, 17
303#define XHCI_PORT_PEC portsc, 32, FLAG, 18
304#define XHCI_PORT_WRC portsc, 32, FLAG, 19
305#define XHCI_PORT_OCC portsc, 32, FLAG, 20
306#define XHCI_PORT_PRC portsc, 32, FLAG, 21
307#define XHCI_PORT_PLC portsc, 32, FLAG, 22
308#define XHCI_PORT_CEC portsc, 32, FLAG, 23
309#define XHCI_PORT_CAS portsc, 32, FLAG, 24
310#define XHCI_PORT_WCE portsc, 32, FLAG, 25
311#define XHCI_PORT_WDE portsc, 32, FLAG, 26
312#define XHCI_PORT_WOE portsc, 32, FLAG, 27
313#define XHCI_PORT_DR portsc, 32, FLAG, 30
314#define XHCI_PORT_WPR portsc, 32, FLAG, 31
315
316#define XHCI_PORT_USB3_U1TO portpmsc, 32, RANGE, 7, 0
317#define XHCI_PORT_USB3_U2TO portpmsc, 32, RANGE, 15, 8
318#define XHCI_PORT_USB3_FLPMA portpmsc, 32, FLAG, 16
319#define XHCI_PORT_USB3_LEC portli, 32, RANGE, 15, 0
320#define XHCI_PORT_USB3_RLC portli, 32, RANGE, 19, 16
321#define XHCI_PORT_USB3_TLC portli, 32, RANGE, 23, 20
322
323#define XHCI_PORT_USB2_L1S portpmsc, 32, RANGE, 2, 0
324#define XHCI_PORT_USB2_RWE portpmsc, 32, FLAG, 3
325#define XHCI_PORT_USB2_BESL portpmsc, 32, RANGE, 7, 4
326#define XHCI_PORT_USB2_L1DS portpmsc, 32, RANGE, 15, 8
327#define XHCI_PORT_USB2_HLE portpmsc, 32, FLAG, 16
328#define XHCI_PORT_USB2_TM portpmsc, 32, RANGE, 31, 28
329#define XHCI_PORT_USB2_HIRDM porthlpmc, 32, RANGE, 1, 0
330#define XHCI_PORT_USB2_L1TO porthlpmc, 32, RANGE, 9, 2
331#define XHCI_PORT_USB2_BESLD porthlpmc, 32, RANGE, 13, 10
332
333/**
334 * XHCI Operational Registers: section 5.4
335 */
336typedef struct xhci_op_regs {
337
338 /*
339 * 3 2 1 0
340 * 3:0 - HSEE INTE HCRST R/S
341 *
342 * 11 10 9 8 7
343 * 11:7 - EU3S EWE CRS CSS LHCRST
344 * 13 - CME
345 */
346 ioport32_t usbcmd;
347
348 /*
349 * 4 3 2 1 0
350 * 4:0 - PCD EINT HSE _ HCH
351 *
352 * 12 11 10 9 8
353 * 12:8 - HCE CNR SRE RSS SSS
354 */
355 ioport32_t usbsts;
356
357 /*
358 * Bitmask of page sizes supported: 128M .. 4K
359 */
360 ioport32_t pagesize;
361
362 PADD32(2);
363
364 /*
365 * 15:0 - Notification enable
366 */
367 ioport32_t dnctrl;
368
369 /* 3 2 1 0
370 * 3:0 - CRR CA CS RCS
371 * 64:6 - Command Ring Pointer
372 */
373 ioport64_t crcr;
374
375 PADD32(4);
376
377 ioport64_t dcbaap;
378
379 /*
380 * 7:0 - MaxSlotsEn
381 * 8 - U3E
382 * 9 - CIE
383 */
384 ioport32_t config;
385
386 /* Offset of portrs from op_regs addr is 0x400. */
387 PADD32(241);
388
389 /*
390 * Individual ports register sets
391 */
392 xhci_port_regs_t portrs[256];
393} xhci_op_regs_t;
394
395#define XHCI_OP_RS usbcmd, 32, FLAG, 0
396#define XHCI_OP_HCRST usbcmd, 32, FLAG, 1
397#define XHCI_OP_INTE usbcmd, 32, FLAG, 2
398#define XHCI_OP_HSEE usbcmd, 32, FLAG, 3
399#define XHCI_OP_LHCRST usbcmd, 32, FLAG, 7
400#define XHCI_OP_CSS usbcmd, 32, FLAG, 8
401#define XHCI_OP_CRS usbcmd, 32, FLAG, 9
402#define XHCI_OP_EWE usbcmd, 32, FLAG, 10
403#define XHCI_OP_EU3S usbcmd, 32, FLAG, 11
404#define XHCI_OP_CME usbcmd, 32, FLAG, 13
405#define XHCI_OP_HCH usbsts, 32, FLAG, 0
406#define XHCI_OP_HSE usbsts, 32, FLAG, 2
407#define XHCI_OP_EINT usbsts, 32, FLAG, 3
408#define XHCI_OP_PCD usbsts, 32, FLAG, 4
409#define XHCI_OP_SSS usbsts, 32, FLAG, 8
410#define XHCI_OP_RSS usbsts, 32, FLAG, 9
411#define XHCI_OP_SRE usbsts, 32, FLAG, 10
412#define XHCI_OP_CNR usbsts, 32, FLAG, 11
413#define XHCI_OP_HCE usbsts, 32, FLAG, 12
414#define XHCI_OP_PAGESIZE pagesize, 32, FIELD
415#define XHCI_OP_NOTIFICATION dnctrl, 32, RANGE, 15, 0
416#define XHCI_OP_RCS crcr, 64, FLAG, 0
417#define XHCI_OP_CS crcr, 64, FLAG, 1
418#define XHCI_OP_CA crcr, 64, FLAG, 2
419#define XHCI_OP_CRR crcr, 64, FLAG, 3
420/*
421 * This shall be RANGE, 6, 0, but the value containing CR pointer and RCS flag
422 * must be written at once.
423 */
424#define XHCI_OP_CRCR crcr, 64, FIELD
425#define XHCI_OP_DCBAAP dcbaap, 64, FIELD
426#define XHCI_OP_MAX_SLOTS_EN config, 32, RANGE, 7, 0
427#define XHCI_OP_U3E config, 32, FLAG, 8
428#define XHCI_OP_CIE config, 32, FLAG, 9
429
430/* Aggregating field to read & write whole status at once */
431#define XHCI_OP_STATUS usbsts, 32, RANGE, 12, 0
432
433/* RW1C fields in usbsts */
434#define XHCI_STATUS_ACK_MASK 0x41C
435
436/**
437 * Interrupter Register Set: section 5.5.2
438 */
439typedef struct xhci_interrupter_regs {
440 /*
441 * 0 - Interrupt Pending
442 * 1 - Interrupt Enable
443 */
444 ioport32_t iman;
445
446 /*
447 * 15:0 - Interrupt Moderation Interval
448 * 31:16 - Interrupt Moderation Counter
449 */
450 ioport32_t imod;
451
452 ioport32_t erstsz;
453
454 PADD32(1);
455
456 ioport64_t erstba;
457
458 /*
459 * 2:0 - Dequeue ERST Segment Index
460 * 3 - Event Handler Busy
461 * 63:4 - Event Ring Dequeue Pointer
462 */
463 ioport64_t erdp;
464} xhci_interrupter_regs_t;
465
466#define XHCI_INTR_IP iman, 32, FLAG, 0
467#define XHCI_INTR_IE iman, 32, FLAG, 1
468#define XHCI_INTR_IMI imod, 32, RANGE, 15, 0
469#define XHCI_INTR_IMC imod, 32, RANGE, 31, 16
470#define XHCI_INTR_ERSTSZ erstsz, 32, FIELD
471#define XHCI_INTR_ERSTBA erstba, 64, FIELD
472#define XHCI_INTR_ERDP_ESI erdp, 64, RANGE, 2, 0
473#define XHCI_INTR_ERDP_EHB erdp, 64, FLAG, 3
474#define XHCI_INTR_ERDP erdp, 64, FIELD
475
476/**
477 * XHCI Runtime registers: section 5.5
478 */
479typedef struct xhci_rt_regs {
480 ioport32_t mfindex;
481
482 PADD32(7);
483
484 xhci_interrupter_regs_t ir [];
485} xhci_rt_regs_t;
486
487#define XHCI_RT_MFINDEX mfindex, 32, RANGE, 13, 0
488#define XHCI_MFINDEX_MAX (1 << 14)
489
490/**
491 * XHCI Doorbell Registers: section 5.6
492 *
493 * These registers are to be written as a whole field.
494 */
495typedef ioport32_t xhci_doorbell_t;
496
497enum xhci_plt {
498 XHCI_PSI_PLT_SYMM,
499 XHCI_PSI_PLT_RSVD,
500 XHCI_PSI_PLT_RX,
501 XHCI_PSI_PLT_TX
502};
503
504/**
505 * Protocol speed ID: section 7.2.1
506 */
507typedef struct xhci_psi {
508 xhci_dword_t psi;
509} xhci_psi_t;
510
511#define XHCI_PSI_PSIV psi, 32, RANGE, 3, 0
512#define XHCI_PSI_PSIE psi, 32, RANGE, 5, 4
513#define XHCI_PSI_PLT psi, 32, RANGE, 7, 6
514#define XHCI_PSI_PFD psi, 32, FLAG, 8
515#define XHCI_PSI_PSIM psi, 32, RANGE, 31, 16
516
517enum xhci_extcap_type {
518 XHCI_EC_RESERVED = 0,
519 XHCI_EC_USB_LEGACY,
520 XHCI_EC_SUPPORTED_PROTOCOL,
521 XHCI_EC_EXTENDED_POWER_MANAGEMENT,
522 XHCI_EC_IOV,
523 XHCI_EC_MSI,
524 XHCI_EC_LOCALMEM,
525 XHCI_EC_DEBUG = 10,
526 XHCI_EC_MSIX = 17,
527 XHCI_EC_MAX = 255
528};
529
530/**
531 * xHCI Extended Capability: section 7
532 */
533typedef struct xhci_extcap {
534 xhci_dword_t header;
535 xhci_dword_t cap_specific[];
536} xhci_extcap_t;
537
538#define XHCI_EC_CAP_ID header, 32, RANGE, 7, 0
539#define XHCI_EC_SIZE header, 32, RANGE, 15, 8
540
541/* Supported protocol */
542#define XHCI_EC_SP_MINOR header, 32, RANGE, 23, 16
543#define XHCI_EC_SP_MAJOR header, 32, RANGE, 31, 24
544#define XHCI_EC_SP_NAME cap_specific[0], 32, FIELD
545#define XHCI_EC_SP_CP_OFF cap_specific[1], 32, RANGE, 7, 0
546#define XHCI_EC_SP_CP_COUNT cap_specific[1], 32, RANGE, 15, 8
547#define XHCI_EC_SP_PSIC cap_specific[1], 32, RANGE, 31, 28
548#define XHCI_EC_SP_SLOT_TYPE cap_specific[2], 32, RANGE, 4, 0
549
550typedef union {
551 char str [4];
552 uint32_t packed;
553} xhci_sp_name_t;
554
555static const xhci_sp_name_t xhci_name_usb = {
556 .str = "USB "
557};
558
559static inline xhci_extcap_t *xhci_extcap_next(const xhci_extcap_t *cur)
560{
561 unsigned dword_offset = XHCI_REG_RD(cur, XHCI_EC_SIZE);
562 if (!dword_offset)
563 return NULL;
564 return (xhci_extcap_t *) (((xhci_dword_t *) cur) + dword_offset);
565}
566
567static inline xhci_psi_t *xhci_extcap_psi(const xhci_extcap_t *ec, unsigned psid)
568{
569 assert(XHCI_REG_RD(ec, XHCI_EC_CAP_ID) == XHCI_EC_SUPPORTED_PROTOCOL);
570 assert(XHCI_REG_RD(ec, XHCI_EC_SP_PSIC) > psid);
571
572 unsigned dword_offset = 4 + psid;
573 return (xhci_psi_t *) (((xhci_dword_t *) ec) + dword_offset);
574}
575
576/**
577 * USB Legacy Support: section 7.1
578 *
579 * Legacy support have an exception from dword-access, because it needs to be
580 * byte-accessed.
581 */
582typedef struct xhci_extcap_legsup {
583 ioport8_t cap_id;
584 ioport8_t size; /**< Next Capability Pointer */
585 ioport8_t sem_bios;
586 ioport8_t sem_os;
587
588 /** USB Legacy Support Control/Status - RW for BIOS, RO for OS */
589 xhci_dword_t usblegctlsts;
590} xhci_legsup_t;
591
592#define XHCI_LEGSUP_SEM_BIOS sem_bios, 8, FLAG, 0
593#define XHCI_LEGSUP_SEM_OS sem_os, 8, FLAG, 0
594
595/* 4.22.1 BIOS may take up to 1 second to release the device */
596#define XHCI_LEGSUP_BIOS_TIMEOUT_US 1000000
597#define XHCI_LEGSUP_POLLING_DELAY_1MS 1000
598
599#endif
600/**
601 * @}
602 */
Note: See TracBrowser for help on using the repository browser.