source: mainline/uspace/drv/bus/usb/xhci/hw_struct/context.h@ a36c4aa

Last change on this file since a36c4aa was 590cb6d2, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 2 years ago

Remove some inappropriate uses of attribute((packed))

attribute((packed)) means "ignore all alignment requirements
on members of this structure". This is useful if one needs to
map onto a structure in memory that has misaligned fields on purpose,
but those cases are extremely rare.

The side effect of the attribute is that taking a pointer to any
field longer than a single byte, and dereferencing that pointer,
is unsound and may crash the program on architectures that care
about memory alignment when reading/writing multibyte values.

Newer GCC versions can detect some of those unsafe cases and
produce a warning for it. This commit only removes those cases.

However, most, if not all, uses of ((packed)) in HelenOS
are unnecessary and a product of misunderstanding what the
attribute actually does. A common misconception is that it is
needed to avoid compiler adding arbitrary padding into the
structure, but that is simply not true. There is exactly one
correct memory layout for any C structure, because there must
be one layout for binary interoperability to exist and the one
everyone uses (except perhaps some goblin who just wants to break
things for fun) is the trivial best layout possible with given
constraints.

  • Property mode set to 100644
File size: 10.5 KB
Line 
1/*
2 * Copyright (c) 2018 Ondrej Hlavaty, Michal Staruch, Jaroslav Jindrak, Jan Hrach
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 * Context data structures of the xHC.
34 *
35 * Most of them are to be initialized to zero and passed ownership to the HC,
36 * so they are mostly read-only.
37 *
38 * Feel free to write a setter when in need.
39 */
40
41#ifndef XHCI_CONTEXT_H
42#define XHCI_CONTEXT_H
43
44#include <stdint.h>
45#include "common.h"
46
47/**
48 * Endpoint context: section 6.2.3
49 */
50typedef struct xhci_endpoint_ctx {
51 xhci_dword_t data[2];
52 xhci_qword_t data2;
53 xhci_dword_t data3;
54 xhci_dword_t reserved[3];
55} xhci_ep_ctx_t;
56
57#define XHCI_EP_COUNT 31
58
59#define XHCI_EP_TYPE_ISOCH_OUT 1
60#define XHCI_EP_TYPE_BULK_OUT 2
61#define XHCI_EP_TYPE_INTERRUPT_OUT 3
62#define XHCI_EP_TYPE_CONTROL 4
63#define XHCI_EP_TYPE_ISOCH_IN 5
64#define XHCI_EP_TYPE_BULK_IN 6
65#define XHCI_EP_TYPE_INTERRUPT_IN 7
66
67#define XHCI_EP_TYPE_SET(ctx, val) \
68 xhci_dword_set_bits(&(ctx).data[1], val, 5, 3)
69#define XHCI_EP_MAX_PACKET_SIZE_SET(ctx, val) \
70 xhci_dword_set_bits(&(ctx).data[1], val, 31, 16)
71#define XHCI_EP_MAX_BURST_SIZE_SET(ctx, val) \
72 xhci_dword_set_bits(&(ctx).data[1], val, 15, 8)
73#define XHCI_EP_TR_DPTR_SET(ctx, val) \
74 xhci_qword_set_bits(&(ctx).data2, (val >> 4), 63, 4)
75#define XHCI_EP_DCS_SET(ctx, val) \
76 xhci_qword_set_bits(&(ctx).data2, val, 0, 0)
77#define XHCI_EP_MAX_ESIT_PAYLOAD_LO_SET(ctx, val) \
78 xhci_dword_set_bits(&(ctx).data3, val, 31, 16)
79#define XHCI_EP_MAX_ESIT_PAYLOAD_HI_SET(ctx, val) \
80 xhci_dword_set_bits(&(ctx).data[0], val, 31, 24)
81#define XHCI_EP_INTERVAL_SET(ctx, val) \
82 xhci_dword_set_bits(&(ctx).data[0], val, 23, 16)
83#define XHCI_EP_MAX_P_STREAMS_SET(ctx, val) \
84 xhci_dword_set_bits(&(ctx).data[0], val, 14, 10)
85#define XHCI_EP_LSA_SET(ctx, val) \
86 xhci_dword_set_bits(&(ctx).data[0], val, 15, 15)
87#define XHCI_EP_MULT_SET(ctx, val) \
88 xhci_dword_set_bits(&(ctx).data[0], val, 9, 8)
89#define XHCI_EP_ERROR_COUNT_SET(ctx, val) \
90 xhci_dword_set_bits(&(ctx).data[1], val, 2, 1)
91
92#define XHCI_EP_STATE(ctx) XHCI_DWORD_EXTRACT((ctx).data[0], 2, 0)
93#define XHCI_EP_MULT(ctx) XHCI_DWORD_EXTRACT((ctx).data[0], 9, 8)
94#define XHCI_EP_MAX_P_STREAMS(ctx) XHCI_DWORD_EXTRACT((ctx).data[0], 14, 10)
95#define XHCI_EP_LSA(ctx) XHCI_DWORD_EXTRACT((ctx).data[0], 15, 15)
96#define XHCI_EP_INTERVAL(ctx) XHCI_DWORD_EXTRACT((ctx).data[0], 23, 16)
97
98#define XHCI_EP_ERROR_COUNT(ctx) XHCI_DWORD_EXTRACT((ctx).data[1], 2, 1)
99#define XHCI_EP_TYPE(ctx) XHCI_DWORD_EXTRACT((ctx).data[1], 5, 3)
100#define XHCI_EP_HID(ctx) XHCI_DWORD_EXTRACT((ctx).data[1], 7, 7)
101#define XHCI_EP_MAX_BURST_SIZE(ctx) XHCI_DWORD_EXTRACT((ctx).data[1], 15, 8)
102#define XHCI_EP_MAX_PACKET_SIZE(ctx) XHCI_DWORD_EXTRACT((ctx).data[1], 31, 16)
103
104#define XHCI_EP_DCS(ctx) XHCI_QWORD_EXTRACT((ctx).data2, 0, 0)
105#define XHCI_EP_TR_DPTR(ctx) XHCI_QWORD_EXTRACT((ctx).data2, 63, 4)
106
107#define XHCI_EP_MAX_ESIT_PAYLOAD_LO(ctx) XHCI_DWORD_EXTRACT((ctx).data3, 31, 16)
108#define XHCI_EP_MAX_ESIT_PAYLOAD_HI(ctx) XHCI_DWORD_EXTRACT((ctx).data[0], 31, 24)
109
110enum {
111 EP_STATE_DISABLED = 0,
112 EP_STATE_RUNNING = 1,
113 EP_STATE_HALTED = 2,
114 EP_STATE_STOPPED = 3,
115 EP_STATE_ERROR = 4,
116};
117
118/**
119 * Slot context: section 6.2.2
120 */
121typedef struct xhci_slot_ctx {
122 xhci_dword_t data [4];
123 xhci_dword_t reserved [4];
124} xhci_slot_ctx_t;
125
126#define XHCI_SLOT_ROUTE_STRING_SET(ctx, val) \
127 xhci_dword_set_bits(&(ctx).data[0], (val & 0xFFFFF), 19, 0)
128#define XHCI_SLOT_SPEED_SET(ctx, val) \
129 xhci_dword_set_bits(&(ctx).data[0], (val & 0xF), 23, 20)
130#define XHCI_SLOT_MTT_SET(ctx, val) \
131 xhci_dword_set_bits(&(ctx).data[0], !!val, 25, 25)
132#define XHCI_SLOT_HUB_SET(ctx, val) \
133 xhci_dword_set_bits(&(ctx).data[0], !!val, 26, 26)
134#define XHCI_SLOT_CTX_ENTRIES_SET(ctx, val) \
135 xhci_dword_set_bits(&(ctx).data[0], val, 31, 27)
136
137#define XHCI_SLOT_ROOT_HUB_PORT_SET(ctx, val) \
138 xhci_dword_set_bits(&(ctx).data[1], val, 23, 16)
139#define XHCI_SLOT_NUM_PORTS_SET(ctx, val) \
140 xhci_dword_set_bits(&(ctx).data[1], val, 31, 24)
141
142#define XHCI_SLOT_TT_HUB_SLOT_ID_SET(ctx, val) \
143 xhci_dword_set_bits(&(ctx).data[2], (val & 0xFF), 7, 0)
144#define XHCI_SLOT_TT_HUB_PORT_SET(ctx, val) \
145 xhci_dword_set_bits(&(ctx).data[2], (val & 0xFF), 15, 8)
146#define XHCI_SLOT_TT_THINK_TIME_SET(ctx, val) \
147 xhci_dword_set_bits(&(ctx).data[2], (val & 0xFF), 17, 16)
148
149#define XHCI_SLOT_ROUTE_STRING(ctx) XHCI_DWORD_EXTRACT((ctx).data[0], 19, 0)
150#define XHCI_SLOT_SPEED(ctx) XHCI_DWORD_EXTRACT((ctx).data[0], 23, 20)
151#define XHCI_SLOT_MTT(ctx) XHCI_DWORD_EXTRACT((ctx).data[0], 25, 25)
152#define XHCI_SLOT_HUB(ctx) XHCI_DWORD_EXTRACT((ctx).data[0], 26, 26)
153#define XHCI_SLOT_CTX_ENTRIES(ctx) XHCI_DWORD_EXTRACT((ctx).data[0], 31, 27)
154
155#define XHCI_SLOT_MAX_EXIT_LATENCY(ctx) XHCI_DWORD_EXTRACT((ctx).data[1], 15, 0)
156#define XHCI_SLOT_ROOT_HUB_PORT(ctx) XHCI_DWORD_EXTRACT((ctx).data[1], 23, 16)
157#define XHCI_SLOT_NUM_PORTS(ctx) XHCI_DWORD_EXTRACT((ctx).data[1], 31, 24)
158
159#define XHCI_SLOT_TT_HUB_SLOT_ID(ctx) XHCI_DWORD_EXTRACT((ctx).data[2], 7, 0)
160#define XHCI_SLOT_TT_PORT_NUM(ctx) XHCI_DWORD_EXTRACT((ctx).data[2], 15, 8)
161#define XHCI_SLOT_TT_THINK_TIME(ctx) XHCI_DWORD_EXTRACT((ctx).data[2], 17, 16)
162#define XHCI_SLOT_INTERRUPTER(ctx) XHCI_DWORD_EXTRACT((ctx).data[2], 31, 22)
163
164#define XHCI_SLOT_DEVICE_ADDRESS(ctx) XHCI_DWORD_EXTRACT((ctx).data[3], 7, 0)
165#define XHCI_SLOT_STATE(ctx) XHCI_DWORD_EXTRACT((ctx).data[3], 31, 27)
166
167enum {
168 SLOT_STATE_DISABLED = 0,
169 SLOT_STATE_DEFAULT = 1,
170 SLOT_STATE_ADDRESS = 2,
171 SLOT_STATE_CONFIGURED = 3,
172};
173
174/**
175 * Handling HCs with 32 or 64-bytes context size (CSZ)
176 */
177#define XHCI_CTX_SIZE_SMALL 32
178#define XHCI_ONE_CTX_SIZE(hc) (XHCI_CTX_SIZE_SMALL << hc->csz)
179#define XHCI_GET_CTX_FIELD(type, ctx, hc, ci) \
180 (xhci_##type##_ctx_to_charptr(ctx) + (ci) * XHCI_ONE_CTX_SIZE(hc))
181
182/**
183 * Device context: section 6.2.1
184 */
185#define XHCI_DEVICE_CTX_SIZE(hc) ((1 + XHCI_EP_COUNT) * XHCI_ONE_CTX_SIZE(hc))
186#define XHCI_GET_EP_CTX(dev_ctx, hc, dci) \
187 ((xhci_ep_ctx_t *) XHCI_GET_CTX_FIELD(device, (dev_ctx), (hc), (dci)))
188#define XHCI_GET_SLOT_CTX(dev_ctx, hc) \
189 ((xhci_slot_ctx_t *) XHCI_GET_CTX_FIELD(device, (dev_ctx), (hc), 0))
190
191/**
192 * As control, slot and endpoint contexts differ in size on different HCs,
193 * we need to use macros to access them at the correct offsets. The following
194 * empty structs (xhci_device_ctx_t and xhci_input_ctx_t) are used only as
195 * void pointers for type-checking.
196 */
197typedef struct xhci_device_ctx {
198} xhci_device_ctx_t;
199
200/**
201 * Force type checking.
202 */
203static inline char *xhci_device_ctx_to_charptr(const xhci_device_ctx_t *ctx)
204{
205 return (char *) ctx;
206}
207
208/**
209 * Stream context: section 6.2.4 {
210 */
211typedef struct xhci_stream_ctx {
212 uint64_t data [2];
213} xhci_stream_ctx_t;
214
215#define XHCI_STREAM_DCS(ctx) XHCI_QWORD_EXTRACT((ctx).data[0], 0, 0)
216#define XHCI_STREAM_SCT(ctx) XHCI_QWORD_EXTRACT((ctx).data[0], 3, 1)
217#define XHCI_STREAM_DEQ_PTR(ctx) (XHCI_QWORD_EXTRACT((ctx).data[0], 63, 4) << 4)
218#define XHCI_STREAM_EDTLA(ctx) XHCI_QWORD_EXTRACT((ctx).data[1], 24, 0)
219
220#define XHCI_STREAM_SCT_SET(ctx, val) \
221 xhci_qword_set_bits(&(ctx).data[0], val, 3, 1)
222#define XHCI_STREAM_DEQ_PTR_SET(ctx, val) \
223 xhci_qword_set_bits(&(ctx).data[0], (val >> 4), 63, 4)
224
225/**
226 * Input control context: section 6.2.5.1
227 * Note: According to section 6.2.5.1 figure 78,
228 * the context size register value in hccparams1
229 * dictates whether input control context shall have
230 * 32 or 64 bytes, but in any case only dwords 0, 1 and 7
231 * are used, the rest are reserved.
232 */
233typedef struct xhci_input_ctrl_ctx {
234 uint32_t data [8];
235} __attribute__((packed)) xhci_input_ctrl_ctx_t;
236
237#define XHCI_INPUT_CTRL_CTX_DROP(ctx, idx) \
238 XHCI_DWORD_EXTRACT((ctx).data[0], (idx), (idx))
239
240#define XHCI_INPUT_CTRL_CTX_DROP_SET(ctx, idx) (ctx).data[0] |= (1 << (idx))
241#define XHCI_INPUT_CTRL_CTX_DROP_CLEAR(ctx, idx) (ctx).data[0] &= ~(1 << (idx))
242
243#define XHCI_INPUT_CTRL_CTX_ADD(ctx, idx) \
244 XHCI_DWORD_EXTRACT((ctx).data[1], (idx), (idx))
245
246#define XHCI_INPUT_CTRL_CTX_ADD_SET(ctx, idx) (ctx).data[1] |= (1 << (idx))
247#define XHCI_INPUT_CTRL_CTX_ADD_CLEAR(ctx, idx) (ctx).data[1] &= ~(1 << (idx))
248
249#define XHCI_INPUT_CTRL_CTX_CONFIG_VALUE(ctx) \
250 XHCI_DWORD_EXTRACT((ctx).data[7], 7, 0)
251#define XHCI_INPUT_CTRL_CTX_IFACE_NUMBER(ctx) \
252 XHCI_DWORD_EXTRACT((ctx).data[7], 15, 8)
253#define XHCI_INPUT_CTRL_CTX_ALTER_SETTING(ctx) \
254 XHCI_DWORD_EXTRACT((ctx).data[7], 23, 16)
255
256/**
257 * Input context: section 6.2.5
258 */
259#define XHCI_INPUT_CTX_SIZE(hc) (XHCI_ONE_CTX_SIZE(hc) + XHCI_DEVICE_CTX_SIZE(hc))
260#define XHCI_GET_CTRL_CTX(ictx, hc) \
261 ((xhci_input_ctrl_ctx_t *) XHCI_GET_CTX_FIELD(input, (ictx), (hc), 0))
262#define XHCI_GET_DEVICE_CTX(dev_ctx, hc) \
263 ((xhci_device_ctx_t *) XHCI_GET_CTX_FIELD(input, (ictx), (hc), 1))
264
265typedef struct xhci_input_ctx {
266} xhci_input_ctx_t;
267
268/**
269 * Force type checking.
270 */
271static inline char *xhci_input_ctx_to_charptr(const xhci_input_ctx_t *ctx)
272{
273 return (char *) ctx;
274}
275
276/**
277 * Port bandwidth context: section 6.2.6
278 * The number of ports depends on the amount of ports available to the hub.
279 */
280typedef struct xhci_port_bandwidth_ctx {
281 uint8_t reserved;
282 uint8_t ports [];
283} xhci_port_bandwidth_ctx_t;
284
285#endif
Note: See TracBrowser for help on using the repository browser.