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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since fe5db713 was 7bd99bf, checked in by Michal Staruch <salmelu@…>, 8 years ago

Added roothub communication for adding devices.

  • Property mode set to 100644
File size: 18.6 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 PADD32[36 * 4 + 1];
378
379 /*
380 * Individual ports register sets
381 */
382 xhci_port_regs_t portrs[256];
383} xhci_op_regs_t;
384
385#define XHCI_OP_RS usbcmd, 32, FLAG, 0
386#define XHCI_OP_HCRST usbcmd, 32, FLAG, 1
387#define XHCI_OP_INTE usbcmd, 32, FLAG, 2
388#define XHCI_OP_HSEE usbcmd, 32, FLAG, 3
389#define XHCI_OP_LHCRST usbcmd, 32, FLAG, 7
390#define XHCI_OP_CSS usbcmd, 32, FLAG, 8
391#define XHCI_OP_CRS usbcmd, 32, FLAG, 9
392#define XHCI_OP_EWE usbcmd, 32, FLAG, 10
393#define XHCI_OP_EU3S usbcmd, 32, FLAG, 11
394#define XHCI_OP_CME usbcmd, 32, FLAG, 13
395#define XHCI_OP_HCH usbsts, 32, FLAG, 0
396#define XHCI_OP_HSE usbsts, 32, FLAG, 2
397#define XHCI_OP_EINT usbsts, 32, FLAG, 3
398#define XHCI_OP_PCD usbsts, 32, FLAG, 4
399#define XHCI_OP_SSS usbsts, 32, FLAG, 8
400#define XHCI_OP_RSS usbsts, 32, FLAG, 9
401#define XHCI_OP_SRE usbsts, 32, FLAG, 10
402#define XHCI_OP_CNR usbsts, 32, FLAG, 11
403#define XHCI_OP_HCE usbsts, 32, FLAG, 12
404#define XHCI_OP_PAGESIZE pagesize, 32, FIELD
405#define XHCI_OP_NOTIFICATION dnctrl, 32, RANGE, 15, 0
406#define XHCI_OP_RCS crcr_lo, 32, FLAG, 0
407#define XHCI_OP_CS crcr_lo, 32, FLAG, 1
408#define XHCI_OP_CA crcr_lo, 32, FLAG, 2
409#define XHCI_OP_CRR crcr_lo, 32, FLAG, 3
410#define XHCI_OP_CRCR_LO crcr_lo, 32, RANGE, 31, 6
411#define XHCI_OP_CRCR_HI crcr_lo, 32, FIELD
412#define XHCI_OP_DCBAAP_LO dcbaap_lo, 32, FIELD
413#define XHCI_OP_DCBAAP_HI dcbaap_lo, 32, FIELD
414#define XHCI_OP_MAX_SLOTS_EN config, 32, RANGE, 7, 0
415#define XHCI_OP_U3E config, 32, FLAG, 8
416#define XHCI_OP_CIE config, 32, FLAG, 9
417
418/* Aggregating field to read & write whole status at once */
419#define XHCI_OP_STATUS usbsts, 32, RANGE, 12, 0
420
421/* RW1C fields in usbsts */
422#define XHCI_STATUS_ACK_MASK 0x41C
423
424/**
425 * Interrupter Register Set: section 5.5.2
426 */
427typedef struct xhci_interrupter_regs {
428 /*
429 * 0 - Interrupt Pending
430 * 1 - Interrupt Enable
431 */
432 ioport32_t iman;
433
434 /*
435 * 15:0 - Interrupt Moderation Interval
436 * 31:16 - Interrupt Moderation Counter
437 */
438 ioport32_t imod;
439
440 ioport32_t erstsz;
441
442 PADD32;
443
444 ioport32_t erstba_lo;
445 ioport32_t erstba_hi;
446
447 /*
448 * 2:0 - Dequeue ERST Segment Index
449 * 3 - Event Handler Busy
450 * 63:4 - Event Ring Dequeue Pointer
451 */
452 ioport32_t erdp_lo;
453 ioport32_t erdp_hi;
454} xhci_interrupter_regs_t;
455
456#define XHCI_INTR_IP iman, 32, FLAG, 0
457#define XHCI_INTR_IE iman, 32, FLAG, 1
458#define XHCI_INTR_IMI imod, 32, RANGE, 15, 0
459#define XHCI_INTR_IMC imod, 32, RANGE, 31, 16
460#define XHCI_INTR_ERSTSZ erstsz, 32, FIELD
461#define XHCI_INTR_ERSTBA_LO erstba_lo, 32, FIELD
462#define XHCI_INTR_ERSTBA_HI erstba_hi, 32, FIELD
463#define XHCI_INTR_ERDP_LO erdp_lo, 32, FIELD
464#define XHCI_INTR_ERDP_HI erdp_hi, 32, FIELD
465
466/**
467 * XHCI Runtime registers: section 5.5
468 */
469typedef struct xhci_rt_regs {
470 ioport32_t mfindex;
471
472 PADD32 [7];
473
474 xhci_interrupter_regs_t ir [];
475} xhci_rt_regs_t;
476
477#define XHCI_RT_MFINDEX mfindex, 32, FIELD
478
479/**
480 * XHCI Doorbell Registers: section 5.6
481 *
482 * These registers are to be written as a whole field.
483 */
484typedef ioport32_t xhci_doorbell_t;
485
486enum xhci_plt {
487 XHCI_PSI_PLT_SYMM,
488 XHCI_PSI_PLT_RSVD,
489 XHCI_PSI_PLT_RX,
490 XHCI_PSI_PLT_TX
491};
492
493/**
494 * Protocol speed ID: section 7.2.1
495 */
496typedef struct xhci_psi {
497 xhci_dword_t psi;
498} xhci_psi_t;
499
500#define XHCI_PSI_PSIV psi, 32, RANGE, 3, 0
501#define XHCI_PSI_PSIE psi, 32, RANGE, 5, 4
502#define XHCI_PSI_PLT psi, 32, RANGE, 7, 6
503#define XHCI_PSI_PFD psi, 32, FLAG, 8
504#define XHCI_PSI_PSIM psi, 32, RANGE, 31, 16
505
506enum xhci_extcap_type {
507 XHCI_EC_RESERVED = 0,
508 XHCI_EC_USB_LEGACY,
509 XHCI_EC_SUPPORTED_PROTOCOL,
510 XHCI_EC_EXTENDED_POWER_MANAGEMENT,
511 XHCI_EC_IOV,
512 XHCI_EC_MSI,
513 XHCI_EC_LOCALMEM,
514 XHCI_EC_DEBUG = 10,
515 XHCI_EC_MSIX = 17,
516 XHCI_EC_MAX = 255
517};
518
519/**
520 * xHCI Extended Capability: section 7
521 */
522typedef struct xhci_extcap {
523 xhci_dword_t header;
524 xhci_dword_t cap_specific[];
525} xhci_extcap_t;
526
527#define XHCI_EC_CAP_ID header, 32, RANGE, 7, 0
528#define XHCI_EC_SIZE header, 32, RANGE, 15, 8
529
530/* Supported protocol */
531#define XHCI_EC_SP_MINOR header, 32, RANGE, 23, 16
532#define XHCI_EC_SP_MAJOR header, 32, RANGE, 31, 24
533#define XHCI_EC_SP_NAME cap_specific[0], 32, FIELD
534#define XHCI_EC_SP_CP_OFF cap_specific[1], 32, RANGE, 7, 0
535#define XHCI_EC_SP_CP_COUNT cap_specific[1], 32, RANGE, 15, 8
536#define XHCI_EC_SP_PSIC cap_specific[1], 32, RANGE, 31, 28
537#define XHCI_EC_SP_SLOT_TYPE cap_specific[2], 32, RANGE, 4, 0
538
539typedef union {
540 char str [4];
541 uint32_t packed;
542} xhci_sp_name_t;
543
544static inline xhci_extcap_t *xhci_extcap_next(const xhci_extcap_t *cur)
545{
546 unsigned dword_offset = XHCI_REG_RD(cur, XHCI_EC_SIZE);
547 if (!dword_offset)
548 return NULL;
549 return (xhci_extcap_t *) (((xhci_dword_t *) cur) + dword_offset);
550}
551
552static inline xhci_psi_t *xhci_extcap_psi(const xhci_extcap_t *ec, unsigned psid)
553{
554 assert(XHCI_REG_RD(ec, XHCI_EC_CAP_ID) == XHCI_EC_SUPPORTED_PROTOCOL);
555 assert(XHCI_REG_RD(ec, XHCI_EC_SP_PSIC) > psid);
556
557 unsigned dword_offset = 4 + psid;
558 return (xhci_psi_t *) (((xhci_dword_t *) ec) + dword_offset);
559}
560
561/**
562 * USB Legacy Support: section 7.1
563 *
564 * Legacy support have an exception from dword-access, because it needs to be
565 * byte-accessed.
566 */
567typedef struct xhci_extcap_legsup {
568 ioport8_t cap_id;
569 ioport8_t size; /**< Next Capability Pointer */
570 ioport8_t sem_bios;
571 ioport8_t sem_os;
572
573 xhci_dword_t usblegctlsts; /**< USB Legacy Support Control/Status - RW for BIOS, RO for OS */
574} xhci_legsup_t;
575
576#define XHCI_LEGSUP_SEM_BIOS sem_bios, 8, FLAG, 0
577#define XHCI_LEGSUP_SEM_OS sem_os, 8, FLAG, 0
578
579#endif
580/**
581 * @}
582 */
Note: See TracBrowser for help on using the repository browser.