1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
/* $OpenBSD: xhcivar.h,v 1.14 2022/12/12 19:18:25 kettenis Exp $ */
/*
* Copyright (c) 2014 Martin Pieuchot
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _XHCIVAR_H_
#define _XHCIVAR_H_
/* Default command execution time (implementation defined). */
#define XHCI_CMD_TIMEOUT MSEC_TO_NSEC(500)
#define XHCI_MAX_CMDS (16 * 1)
#define XHCI_MAX_EVTS (16 * 13)
#define XHCI_MAX_XFER (16 * 16)
struct usbd_dma_info {
bus_dma_tag_t tag;
bus_dmamap_t map;
bus_dma_segment_t seg;
int nsegs;
bus_addr_t paddr;
caddr_t vaddr;
bus_size_t size;
};
struct xhci_xfer {
struct usbd_xfer xfer;
int index; /* Index of the last TRB */
size_t ntrb; /* Number of associated TRBs */
size_t zerotd; /* Is zero len TD required? */
};
struct xhci_ring {
struct xhci_trb *trbs;
size_t ntrb;
struct usbd_dma_info dma;
uint32_t index;
uint32_t toggle; /* Producer/Consumer bit */
};
struct xhci_soft_dev {
struct xhci_inctx *input_ctx; /* Input context */
struct xhci_sctx *slot_ctx;
struct xhci_epctx *ep_ctx[31];
struct usbd_dma_info ictx_dma;
struct usbd_dma_info octx_dma; /* Output context */
struct xhci_pipe *pipes[31];
};
/* Device context segment table. */
struct xhci_devctx {
uint64_t *segs; /* at most USB_MAX_DEVICES+1 */
struct usbd_dma_info dma;
};
/* Event ring segment table. */
struct xhci_erst {
struct xhci_erseg *segs; /* One segment per event ring */
struct usbd_dma_info dma;
};
struct xhci_scratchpad {
struct usbd_dma_info table_dma;
struct usbd_dma_info pages_dma;
int npage;
};
struct xhci_softc {
struct usbd_bus sc_bus;
bus_space_tag_t iot;
bus_space_handle_t ioh;
bus_size_t sc_size;
int sc_dead;
bus_size_t sc_oper_off; /* Operational Register space */
bus_size_t sc_runt_off; /* Runtime */
bus_size_t sc_door_off; /* Doorbell */
uint16_t sc_version; /* xHCI version */
uint32_t sc_pagesize; /* xHCI page size, minimum 4k */
uint32_t sc_ctxsize; /* 32/64 byte context structs */
int sc_noport; /* Maximum number of ports */
u_int8_t sc_conf; /* Device configuration */
struct usbd_xfer *sc_intrxfer; /* Root HUB interrupt xfer */
struct xhci_devctx sc_dcbaa; /* Device context base addr. */
struct xhci_ring sc_cmd_ring; /* Command ring */
struct rwlock sc_cmd_lock; /* Serialize commands */
struct xhci_erst sc_erst; /* Event ring segment table */
struct xhci_ring sc_evt_ring; /* Event ring */
struct xhci_scratchpad sc_spad; /* Optional scratchpad */
int sc_noslot; /* Maximum number of slots */
struct xhci_soft_dev sc_sdevs[USB_MAX_DEVICES];
struct xhci_trb *sc_cmd_trb;
struct xhci_trb sc_result_trb;
char sc_vendor[16]; /* Vendor string for root hub */
int sc_id_vendor; /* Vendor ID for root hub */
};
int xhci_init(struct xhci_softc *);
void xhci_config(struct xhci_softc *);
void xhci_reinit(struct xhci_softc *);
int xhci_intr(void *);
int xhci_detach(struct device *, int);
int xhci_activate(struct device *, int);
#define XREAD1(sc, a) bus_space_read_1((sc)->iot, (sc)->ioh, (a))
#define XREAD2(sc, a) bus_space_read_2((sc)->iot, (sc)->ioh, (a))
#define XREAD4(sc, a) bus_space_read_4((sc)->iot, (sc)->ioh, (a))
#define XWRITE1(sc, a, x) bus_space_write_1((sc)->iot, (sc)->ioh, (a), (x))
#define XWRITE2(sc, a, x) bus_space_write_2((sc)->iot, (sc)->ioh, (a), (x))
#define XWRITE4(sc, a, x) bus_space_write_4((sc)->iot, (sc)->ioh, (a), (x))
#define XOREAD4(sc, a) \
bus_space_read_4((sc)->iot, (sc)->ioh, (sc)->sc_oper_off + (a))
#define XOWRITE4(sc, a, x) \
bus_space_write_4((sc)->iot, (sc)->ioh, (sc)->sc_oper_off + (a), (x))
#define XRREAD4(sc, a) \
bus_space_read_4((sc)->iot, (sc)->ioh, (sc)->sc_runt_off + (a))
#define XRWRITE4(sc, a, x) \
bus_space_write_4((sc)->iot, (sc)->ioh, (sc)->sc_runt_off + (a), (x))
#define XDREAD4(sc, a) \
bus_space_read_4((sc)->iot, (sc)->ioh, (sc)->sc_door_off + (a))
#define XDWRITE4(sc, a, x) \
bus_space_write_4((sc)->iot, (sc)->ioh, (sc)->sc_door_off + (a), (x))
#endif /* _XHCIVAR_H_ */
|