summaryrefslogtreecommitdiffstats
path: root/qemu/roms/ipxe/src/drivers/usb/uhci.h
blob: ba4c28f7e2efd0f6137881637b457d3029235716 (plain)
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
#ifndef _IPXE_UHCI_H
#define _IPXE_UHCI_H

/** @file
 *
 * USB Universal Host Controller Interface (UHCI) driver
 *
 */

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );

#include <assert.h>
#include <ipxe/pci.h>
#include <ipxe/usb.h>

/** Minimum alignment required for data structures
 *
 * With the exception of the frame list (which is page-aligned), data
 * structures used by UHCI generally require 16-byte alignment.
 */
#define UHCI_ALIGN 16

/** Number of ports */
#define UHCI_PORTS 2

/** Maximum transfer size */
#define UHCI_MTU 1280

/** I/O BAR size */
#define UHCI_BAR_SIZE 0x14

/** USB command register */
#define UHCI_USBCMD 0x00

/** Max packet is 64 bytes */
#define UHCI_USBCMD_MAX64 0x0080

/** Host controller reset */
#define UHCI_USBCMD_HCRESET 0x0002

/** Run/stop */
#define UHCI_USBCMD_RUN 0x0001

/** USB status register */
#define UHCI_USBSTS 0x02

/** Host controller halted */
#define UHCI_USBSTS_HCHALTED 0x0020

/** USB interrupt */
#define UHCI_USBSTS_USBINT 0x0001

/** Frame list base address register */
#define UHCI_FLBASEADD 0x08

/** Port status and control register */
#define UHCI_PORTSC(port) ( 0x0e + ( (port) << 1 ) )

/** Port reset */
#define UHCI_PORTSC_PR 0x0200

/** Low-speed device attached */
#define UHCI_PORTSC_LS 0x0100

/** Port enabled/disabled change */
#define UHCI_PORTSC_PEC 0x0008

/** Port enabled */
#define UHCI_PORTSC_PED 0x0004

/** Connect status change */
#define UHCI_PORTSC_CSC 0x0002

/** Current connect status */
#define UHCI_PORTSC_CCS 0x0001

/** Port status change mask */
#define UHCI_PORTSC_CHANGE ( UHCI_PORTSC_CSC | UHCI_PORTSC_PEC )

/** Depth-first processing */
#define UHCI_LINK_DEPTH_FIRST 0x00000004UL

/** Queue head type */
#define UHCI_LINK_TYPE_QH 0x00000002UL

/** List terminator */
#define UHCI_LINK_TERMINATE 0x00000001UL

/** Number of frames in frame list */
#define UHCI_FRAMES 1024

/** A frame list */
struct uhci_frame_list {
	/** Link pointer */
	uint32_t link[UHCI_FRAMES];
} __attribute__ (( packed ));

/** A transfer descriptor */
struct uhci_transfer_descriptor {
	/** Link pointer */
	uint32_t link;
	/** Actual length */
	uint16_t actual;
	/** Status */
	uint8_t status;
	/** Flags */
	uint8_t flags;
	/** Control */
	uint32_t control;
	/** Buffer pointer */
	uint32_t data;
} __attribute__ (( packed ));

/** Length mask */
#define UHCI_LEN_MASK 0x7ff

/** Actual length */
#define UHCI_ACTUAL_LEN( actual ) ( ( (actual) + 1 ) & UHCI_LEN_MASK )

/** Active */
#define UHCI_STATUS_ACTIVE 0x80

/** Stalled */
#define UHCI_STATUS_STALLED 0x40

/** Data buffer error */
#define UHCI_STATUS_BUFFER 0x20

/** Babble detected */
#define UHCI_STATUS_BABBLE 0x10

/** NAK received */
#define UHCI_STATUS_NAK 0x08

/** CRC/timeout error */
#define UHCI_STATUS_CRC_TIMEOUT 0x04

/** Bitstuff error */
#define UHCI_STATUS_BITSTUFF 0x02

/** Short packet detect */
#define UHCI_FL_SPD 0x20

/** Error counter */
#define UHCI_FL_CERR( count ) ( (count) << 3 )

/** Error counter maximum value */
#define UHCI_FL_CERR_MAX UHCI_FL_CERR ( 3 )

/** Low speed device */
#define UHCI_FL_LS 0x04

/** Interrupt on completion */
#define UHCI_FL_IOC 0x01

/** Packet ID */
#define UHCI_CONTROL_PID( pid ) ( (pid) << 0 )

/** Packet ID mask */
#define UHCI_CONTROL_PID_MASK UHCI_CONTROL_PID ( 0xff )

/** Device address */
#define UHCI_CONTROL_DEVICE( address ) ( (address) << 8 )

/** Endpoint address */
#define UHCI_CONTROL_ENDPOINT( address ) ( (address) << 15 )

/** Data toggle */
#define UHCI_CONTROL_TOGGLE ( 1 << 19 )

/** Data length */
#define UHCI_CONTROL_LEN( len ) ( ( ( (len) - 1 ) & UHCI_LEN_MASK ) << 21 )

/** Check for data packet
 *
 * This check is based on the fact that only USB_PID_SETUP has bit 2
 * set.
 */
#define UHCI_DATA_PACKET( control ) ( ! ( control & 0x04 ) )

/** Check for short packet */
#define UHCI_SHORT_PACKET( control, actual ) \
	( ( ( (control) >> 21 ) ^ (actual) ) & UHCI_LEN_MASK )

/** USB legacy support register (in PCI configuration space) */
#define UHCI_USBLEGSUP 0xc0

/** USB legacy support default value */
#define UHCI_USBLEGSUP_DEFAULT 0x2000

/** A queue head */
struct uhci_queue_head {
	/** Horizontal link pointer */
	uint32_t link;
	/** Current transfer descriptor */
	uint32_t current;
} __attribute__ (( packed ));

/** A single UHCI transfer
 *
 * UHCI hardware is extremely simple, and requires software to build
 * the entire packet schedule (including manually handling all of the
 * data toggles).  The hardware requires at least 16 bytes of transfer
 * descriptors per 64 bytes of transmitted/received data.  We allocate
 * the transfer descriptors at the time that the transfer is enqueued,
 * to avoid the need to allocate unreasonably large blocks when the
 * endpoint is opened.
 */
struct uhci_transfer {
	/** Producer counter */
	unsigned int prod;
	/** Consumer counter */
	unsigned int cons;
	/** Completed data length */
	size_t len;

	/** Transfer descriptors */
	struct uhci_transfer_descriptor *desc;

	/** I/O buffer */
	struct io_buffer *iobuf;
};

/** Number of transfer descriptors in a ring
 *
 * This is a policy decision.
 */
#define UHCI_RING_COUNT 16

/** A transfer ring */
struct uhci_ring {
	/** Producer counter */
	unsigned int prod;
	/** Consumer counter */
	unsigned int cons;

	/** Maximum packet length */
	size_t mtu;
	/** Base flags
	 *
	 * This incorporates the CERR and LS bits
	 */
	uint8_t flags;
	/** Base control word
	 *
	 * This incorporates the device address, the endpoint address,
	 * and the data toggle for the next descriptor to be enqueued.
	 */
	uint32_t control;

	/** Transfers */
	struct uhci_transfer *xfer[UHCI_RING_COUNT];
	/** End of transfer ring (if non-empty) */
	struct uhci_transfer *end;

	/** Queue head */
	struct uhci_queue_head *head;
};

/**
 * Calculate space used in transfer ring
 *
 * @v ring		Transfer ring
 * @ret fill		Number of entries used
 */
static inline __attribute__ (( always_inline )) unsigned int
uhci_ring_fill ( struct uhci_ring *ring ) {
	unsigned int fill;

	fill = ( ring->prod - ring->cons );
	assert ( fill <= UHCI_RING_COUNT );
	return fill;
}

/**
 * Calculate space remaining in transfer ring
 *
 * @v ring		Transfer ring
 * @ret remaining	Number of entries remaining
 */
static inline __attribute__ (( always_inline )) unsigned int
uhci_ring_remaining ( struct uhci_ring *ring ) {
	unsigned int fill = uhci_ring_fill ( ring );

	return ( UHCI_RING_COUNT - fill );
}

/** Maximum time to wait for host controller to stop
 *
 * This is a policy decision.
 */
#define UHCI_STOP_MAX_WAIT_MS 100

/** Maximum time to wait for reset to complete
 *
 * This is a policy decision.
 */
#define UHCI_RESET_MAX_WAIT_MS 500

/** Maximum time to wait for a port to be enabled
 *
 * This is a policy decision.
 */
#define UHCI_PORT_ENABLE_MAX_WAIT_MS 500

/** A UHCI device */
struct uhci_device {
	/** Registers */
	unsigned long regs;
	/** Name */
	const char *name;

	/** EHCI companion controller bus:dev.fn address (if any) */
	unsigned int companion;

	/** Asynchronous queue head */
	struct uhci_queue_head *head;
	/** Frame list */
	struct uhci_frame_list *frame;

	/** List of all endpoints */
	struct list_head endpoints;
	/** Asynchronous schedule */
	struct list_head async;
	/** Periodic schedule
	 *
	 * Listed in decreasing order of endpoint interval.
	 */
	struct list_head periodic;

	/** USB bus */
	struct usb_bus *bus;
};

/** A UHCI endpoint */
struct uhci_endpoint {
	/** UHCI device */
	struct uhci_device *uhci;
	/** USB endpoint */
	struct usb_endpoint *ep;
	/** List of all endpoints */
	struct list_head list;
	/** Endpoint schedule */
	struct list_head schedule;

	/** Transfer ring */
	struct uhci_ring ring;
};

#endif /* _IPXE_UHCI_H */