source: mainline/uspace/drv/bus/usb/xhci/hw_struct/regs.h@ 27b0ea0

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

xhci: whitespace fixes

  • Property mode set to 100644
File size: 19.0 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_LO hcsparams2, 32, RANGE, 25, 4
199#define XHCI_CAP_SPR hcsparams2, 32, FLAG, 26
200#define XHCI_CAP_MAX_SPBUF_HI 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#define XHCI_OP_CRCR_LO crcr_lo, 32, RANGE, 31, 6
412#define XHCI_OP_CRCR_HI crcr_hi, 32, FIELD
413#define XHCI_OP_DCBAAP_LO dcbaap_lo, 32, FIELD
414#define XHCI_OP_DCBAAP_HI dcbaap_hi, 32, FIELD
415#define XHCI_OP_MAX_SLOTS_EN config, 32, RANGE, 7, 0
416#define XHCI_OP_U3E config, 32, FLAG, 8
417#define XHCI_OP_CIE config, 32, FLAG, 9
418
419/* Aggregating field to read & write whole status at once */
420#define XHCI_OP_STATUS usbsts, 32, RANGE, 12, 0
421
422/* RW1C fields in usbsts */
423#define XHCI_STATUS_ACK_MASK 0x41C
424
425/**
426 * Interrupter Register Set: section 5.5.2
427 */
428typedef struct xhci_interrupter_regs {
429 /*
430 * 0 - Interrupt Pending
431 * 1 - Interrupt Enable
432 */
433 ioport32_t iman;
434
435 /*
436 * 15:0 - Interrupt Moderation Interval
437 * 31:16 - Interrupt Moderation Counter
438 */
439 ioport32_t imod;
440
441 ioport32_t erstsz;
442
443 PADD32;
444
445 ioport32_t erstba_lo;
446 ioport32_t erstba_hi;
447
448 /*
449 * 2:0 - Dequeue ERST Segment Index
450 * 3 - Event Handler Busy
451 * 63:4 - Event Ring Dequeue Pointer
452 */
453 ioport32_t erdp_lo;
454 ioport32_t erdp_hi;
455} xhci_interrupter_regs_t;
456
457#define XHCI_INTR_IP iman, 32, FLAG, 0
458#define XHCI_INTR_IE iman, 32, FLAG, 1
459#define XHCI_INTR_IMI imod, 32, RANGE, 15, 0
460#define XHCI_INTR_IMC imod, 32, RANGE, 31, 16
461#define XHCI_INTR_ERSTSZ erstsz, 32, FIELD
462#define XHCI_INTR_ERSTBA_LO erstba_lo, 32, FIELD
463#define XHCI_INTR_ERSTBA_HI erstba_hi, 32, FIELD
464#define XHCI_INTR_ERDP_ESI erdp_lo, 32, RANGE, 2, 0
465#define XHCI_INTR_ERDP_EHB erdp_lo, 32, FLAG, 3
466// TODO: ERDP_LO is supposed to be RANGE 31, 4 (section 5.5.2.3.3).
467#define XHCI_INTR_ERDP_LO erdp_lo, 32, FIELD
468#define XHCI_INTR_ERDP_HI erdp_hi, 32, FIELD
469
470/**
471 * XHCI Runtime registers: section 5.5
472 */
473typedef struct xhci_rt_regs {
474 ioport32_t mfindex;
475
476 PADD32 [7];
477
478 xhci_interrupter_regs_t ir [];
479} xhci_rt_regs_t;
480
481#define XHCI_RT_MFINDEX mfindex, 32, FIELD
482
483/**
484 * XHCI Doorbell Registers: section 5.6
485 *
486 * These registers are to be written as a whole field.
487 */
488typedef ioport32_t xhci_doorbell_t;
489
490enum xhci_plt {
491 XHCI_PSI_PLT_SYMM,
492 XHCI_PSI_PLT_RSVD,
493 XHCI_PSI_PLT_RX,
494 XHCI_PSI_PLT_TX
495};
496
497/**
498 * Protocol speed ID: section 7.2.1
499 */
500typedef struct xhci_psi {
501 xhci_dword_t psi;
502} xhci_psi_t;
503
504#define XHCI_PSI_PSIV psi, 32, RANGE, 3, 0
505#define XHCI_PSI_PSIE psi, 32, RANGE, 5, 4
506#define XHCI_PSI_PLT psi, 32, RANGE, 7, 6
507#define XHCI_PSI_PFD psi, 32, FLAG, 8
508#define XHCI_PSI_PSIM psi, 32, RANGE, 31, 16
509
510enum xhci_extcap_type {
511 XHCI_EC_RESERVED = 0,
512 XHCI_EC_USB_LEGACY,
513 XHCI_EC_SUPPORTED_PROTOCOL,
514 XHCI_EC_EXTENDED_POWER_MANAGEMENT,
515 XHCI_EC_IOV,
516 XHCI_EC_MSI,
517 XHCI_EC_LOCALMEM,
518 XHCI_EC_DEBUG = 10,
519 XHCI_EC_MSIX = 17,
520 XHCI_EC_MAX = 255
521};
522
523/**
524 * xHCI Extended Capability: section 7
525 */
526typedef struct xhci_extcap {
527 xhci_dword_t header;
528 xhci_dword_t cap_specific[];
529} xhci_extcap_t;
530
531#define XHCI_EC_CAP_ID header, 32, RANGE, 7, 0
532#define XHCI_EC_SIZE header, 32, RANGE, 15, 8
533
534/* Supported protocol */
535#define XHCI_EC_SP_MINOR header, 32, RANGE, 23, 16
536#define XHCI_EC_SP_MAJOR header, 32, RANGE, 31, 24
537#define XHCI_EC_SP_NAME cap_specific[0], 32, FIELD
538#define XHCI_EC_SP_CP_OFF cap_specific[1], 32, RANGE, 7, 0
539#define XHCI_EC_SP_CP_COUNT cap_specific[1], 32, RANGE, 15, 8
540#define XHCI_EC_SP_PSIC cap_specific[1], 32, RANGE, 31, 28
541#define XHCI_EC_SP_SLOT_TYPE cap_specific[2], 32, RANGE, 4, 0
542
543typedef union {
544 char str [4];
545 uint32_t packed;
546} xhci_sp_name_t;
547
548static const xhci_sp_name_t xhci_name_usb = {
549 .str = "USB "
550};
551
552static inline xhci_extcap_t *xhci_extcap_next(const xhci_extcap_t *cur)
553{
554 unsigned dword_offset = XHCI_REG_RD(cur, XHCI_EC_SIZE);
555 if (!dword_offset)
556 return NULL;
557 return (xhci_extcap_t *) (((xhci_dword_t *) cur) + dword_offset);
558}
559
560static inline xhci_psi_t *xhci_extcap_psi(const xhci_extcap_t *ec, unsigned psid)
561{
562 assert(XHCI_REG_RD(ec, XHCI_EC_CAP_ID) == XHCI_EC_SUPPORTED_PROTOCOL);
563 assert(XHCI_REG_RD(ec, XHCI_EC_SP_PSIC) > psid);
564
565 unsigned dword_offset = 4 + psid;
566 return (xhci_psi_t *) (((xhci_dword_t *) ec) + dword_offset);
567}
568
569/**
570 * USB Legacy Support: section 7.1
571 *
572 * Legacy support have an exception from dword-access, because it needs to be
573 * byte-accessed.
574 */
575typedef struct xhci_extcap_legsup {
576 ioport8_t cap_id;
577 ioport8_t size; /**< Next Capability Pointer */
578 ioport8_t sem_bios;
579 ioport8_t sem_os;
580
581 xhci_dword_t usblegctlsts; /**< USB Legacy Support Control/Status - RW for BIOS, RO for OS */
582} xhci_legsup_t;
583
584#define XHCI_LEGSUP_SEM_BIOS sem_bios, 8, FLAG, 0
585#define XHCI_LEGSUP_SEM_OS sem_os, 8, FLAG, 0
586
587#define XHCI_LEGSUP_POLLING_DELAY_1MS 1000
588#define XHCI_LEGSUP_BIOS_TIMEOUT_US 1000000 /* 4.22.1 BIOS may take up to 1 second to release the device */
589
590#endif
591/**
592 * @}
593 */
Note: See TracBrowser for help on using the repository browser.