[USBEHCI_NEW] Bring-in the USB EHCI miniport driver created by Vadim Galyant. (#301)
[reactos.git] / drivers / usb / usbehci_new / hardware.h
1 /*
2 * PROJECT: ReactOS USB EHCI Miniport Driver
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: USBEHCI hardware declarations
5 * COPYRIGHT: Copyright 2017-2018 Vadim Galyant <vgal@rambler.ru>
6 */
7
8 #define EHCI_FRAME_LIST_MAX_ENTRIES 1024 // Number of frames in Frame List
9
10 /* EHCI hardware registers */
11 #define EHCI_USBCMD 0
12 #define EHCI_USBSTS 1
13 #define EHCI_USBINTR 2
14 #define EHCI_FRINDEX 3
15 #define EHCI_CTRLDSSEGMENT 4
16 #define EHCI_PERIODICLISTBASE 5
17 #define EHCI_ASYNCLISTBASE 6
18 #define EHCI_CONFIGFLAG 16
19 #define EHCI_PORTSC 17
20
21 #define EHCI_FLADJ_PCI_CONFIG_OFFSET 0x61
22
23 typedef union _EHCI_LEGACY_EXTENDED_CAPABILITY {
24 struct {
25 ULONG CapabilityID : 8;
26 ULONG NextCapabilityPointer : 8;
27 ULONG BiosOwnedSemaphore : 1;
28 ULONG Reserved1 : 7;
29 ULONG OsOwnedSemaphore : 1;
30 ULONG Reserved2 : 7;
31 };
32 ULONG AsULONG;
33 } EHCI_LEGACY_EXTENDED_CAPABILITY;
34
35 C_ASSERT(sizeof(EHCI_LEGACY_EXTENDED_CAPABILITY) == sizeof(ULONG));
36
37 typedef union _EHCI_HC_STRUCTURAL_PARAMS {
38 struct {
39 ULONG PortCount : 4;
40 ULONG PortPowerControl : 1;
41 ULONG Reserved1 : 2;
42 ULONG PortRouteRules : 1;
43 ULONG PortsPerCompanion : 4;
44 ULONG CompanionControllers : 4;
45 ULONG PortIndicators : 1;
46 ULONG Reserved2 : 3;
47 ULONG DebugPortNumber : 4; //Optional
48 ULONG Reserved3 : 8;
49 };
50 ULONG AsULONG;
51 } EHCI_HC_STRUCTURAL_PARAMS;
52
53 C_ASSERT(sizeof(EHCI_HC_STRUCTURAL_PARAMS) == sizeof(ULONG));
54
55 typedef union _EHCI_HC_CAPABILITY_PARAMS {
56 struct {
57 ULONG Addressing64bitCapability : 1;
58 ULONG IsProgrammableFrameList : 1;
59 ULONG IsScheduleParkSupport : 1;
60 ULONG Reserved1 : 1;
61 ULONG IsoSchedulingThreshold : 4;
62 ULONG ExtCapabilitiesPointer : 8; // (EECP)
63 ULONG Reserved2 : 16;
64 };
65 ULONG AsULONG;
66 } EHCI_HC_CAPABILITY_PARAMS;
67
68 C_ASSERT(sizeof(EHCI_HC_CAPABILITY_PARAMS) == sizeof(ULONG));
69
70 typedef struct _EHCI_HC_CAPABILITY_REGISTERS {
71 UCHAR RegistersLength; // RO
72 UCHAR Reserved; // RO
73 USHORT InterfaceVersion; // RO
74 EHCI_HC_STRUCTURAL_PARAMS StructParameters; // RO
75 EHCI_HC_CAPABILITY_PARAMS CapParameters; // RO
76 UCHAR CompanionPortRouteDesc[8]; // RO
77 } EHCI_HC_CAPABILITY_REGISTERS, *PEHCI_HC_CAPABILITY_REGISTERS;
78
79 typedef union _EHCI_USB_COMMAND {
80 struct {
81 ULONG Run : 1;
82 ULONG Reset : 1;
83 ULONG FrameListSize : 2;
84 ULONG PeriodicEnable : 1;
85 ULONG AsynchronousEnable : 1;
86 ULONG InterruptAdvanceDoorbell : 1;
87 ULONG LightResetHC : 1; // optional
88 ULONG AsynchronousParkModeCount : 2; // optional
89 ULONG Reserved1 : 1;
90 ULONG AsynchronousParkModeEnable : 1; // optional
91 ULONG Reserved2 : 4;
92 ULONG InterruptThreshold : 8;
93 ULONG Reserved3 : 8;
94 };
95 ULONG AsULONG;
96 } EHCI_USB_COMMAND;
97
98 C_ASSERT(sizeof(EHCI_USB_COMMAND) == sizeof(ULONG));
99
100 typedef union _EHCI_USB_STATUS {
101 struct {
102 ULONG Interrupt : 1;
103 ULONG ErrorInterrupt : 1;
104 ULONG PortChangeDetect : 1;
105 ULONG FrameListRollover : 1;
106 ULONG HostSystemError : 1;
107 ULONG InterruptOnAsyncAdvance : 1;
108 ULONG Reserved1 : 6;
109 ULONG HCHalted : 1;
110 ULONG Reclamation : 1;
111 ULONG PeriodicStatus : 1;
112 ULONG AsynchronousStatus : 1;
113 ULONG Reserved2 : 16;
114 };
115 ULONG AsULONG;
116 } EHCI_USB_STATUS;
117
118 C_ASSERT(sizeof(EHCI_USB_STATUS) == sizeof(ULONG));
119
120 #define EHCI_INTERRUPT_MASK 0x3F
121
122 typedef union _EHCI_INTERRUPT_ENABLE {
123 struct {
124 ULONG Interrupt : 1;
125 ULONG ErrorInterrupt : 1;
126 ULONG PortChangeInterrupt : 1;
127 ULONG FrameListRollover : 1;
128 ULONG HostSystemError : 1;
129 ULONG InterruptOnAsyncAdvance : 1;
130 ULONG Reserved : 26;
131 };
132 ULONG AsULONG;
133 } EHCI_INTERRUPT_ENABLE;
134
135 C_ASSERT(sizeof(EHCI_INTERRUPT_ENABLE) == sizeof(ULONG));
136
137 #define EHCI_LINE_STATUS_K_STATE_LOW_SPEED 1
138 #define EHCI_PORT_OWNER_COMPANION_CONTROLLER 1
139
140 typedef union _EHCI_PORT_STATUS_CONTROL {
141 struct {
142 ULONG CurrentConnectStatus : 1;
143 ULONG ConnectStatusChange : 1;
144 ULONG PortEnabledDisabled : 1;
145 ULONG PortEnableDisableChange : 1;
146 ULONG OverCurrentActive : 1;
147 ULONG OverCurrentChange : 1;
148 ULONG ForcePortResume : 1;
149 ULONG Suspend : 1;
150 ULONG PortReset : 1;
151 ULONG Reserved1 : 1;
152 ULONG LineStatus : 2;
153 ULONG PortPower : 1;
154 ULONG PortOwner : 1;
155 ULONG PortIndicatorControl : 2;
156 ULONG PortTestControl : 4;
157 ULONG WakeOnConnectEnable : 1;
158 ULONG WakeOnDisconnectEnable : 1;
159 ULONG WakeOnOverCurrentEnable : 1;
160 ULONG Reserved2 : 9;
161 };
162 ULONG AsULONG;
163 } EHCI_PORT_STATUS_CONTROL;
164
165 C_ASSERT(sizeof(EHCI_PORT_STATUS_CONTROL) == sizeof(ULONG));
166
167 /* FRINDEX Frame Index Register */
168 #define EHCI_FRINDEX_FRAME_MASK 0x7FF
169 #define EHCI_FRINDEX_INDEX_MASK 0x3FF
170
171 #define EHCI_CONFIG_FLAG_CONFIGURED 1
172
173 typedef struct _EHCI_HW_REGISTERS {
174 EHCI_USB_COMMAND HcCommand; // RO, R/W (field dependent), WO
175 EHCI_USB_STATUS HcStatus; // RO, R/W, R/WC, (field dependent)
176 EHCI_INTERRUPT_ENABLE HcInterruptEnable; // R/W
177 ULONG FrameIndex; // R/W (Writes must be DWord Writes)
178 ULONG SegmentSelector; // R/W (Writes must be DWord Writes)
179 ULONG PeriodicListBase; // R/W (Writes must be DWord Writes)
180 ULONG AsyncListBase; // Read/Write (Writes must be DWord Writes)
181 ULONG Reserved[9];
182 ULONG ConfigFlag; // R/W
183 EHCI_PORT_STATUS_CONTROL PortControl[15]; // (1-15) RO, R/W, R/WC (field dependent)
184 } EHCI_HW_REGISTERS, *PEHCI_HW_REGISTERS;
185
186 /* Link Pointer */
187 #define EHCI_LINK_TYPE_iTD 0 // isochronous transfer descriptor
188 #define EHCI_LINK_TYPE_QH 1 // queue head
189 #define EHCI_LINK_TYPE_siTD 2 // split transaction isochronous transfer
190 #define EHCI_LINK_TYPE_FSTN 3 // frame span traversal node
191
192 /* Used for QHs and qTDs to mark Pointers as the end */
193 #define TERMINATE_POINTER 1
194
195 #define LINK_POINTER_MASK 0xFFFFFFE0
196
197 typedef union _EHCI_LINK_POINTER {
198 struct {
199 ULONG Terminate : 1;
200 ULONG Type : 2;
201 ULONG Reserved : 2;
202 ULONG Address : 27;
203 };
204 ULONG AsULONG;
205 } EHCI_LINK_POINTER;
206
207 C_ASSERT(sizeof(EHCI_LINK_POINTER) == sizeof(ULONG));
208
209 /* Isochronous (High-Speed) Transfer Descriptor (iTD) */
210 typedef union _EHCI_TRANSACTION_CONTROL {
211 struct {
212 ULONG xOffset : 12;
213 ULONG PageSelect : 3;
214 ULONG InterruptOnComplete : 1;
215 ULONG xLength : 12;
216 ULONG Status : 4;
217 };
218 ULONG AsULONG;
219 } EHCI_TRANSACTION_CONTROL;
220
221 C_ASSERT(sizeof(EHCI_TRANSACTION_CONTROL) == sizeof(ULONG));
222
223 typedef union _EHCI_TRANSACTION_BUFFER {
224 struct {
225 ULONG DeviceAddress : 7;
226 ULONG Reserved1 : 1;
227 ULONG EndpointNumber : 4;
228 ULONG DataBuffer0 : 20;
229 };
230 struct {
231 ULONG MaximumPacketSize : 11;
232 ULONG Direction : 1;
233 ULONG DataBuffer1 : 20;
234 };
235 struct {
236 ULONG Multi : 2;
237 ULONG Reserved2 : 10;
238 ULONG DataBuffer2 : 20;
239 };
240 struct {
241 ULONG Reserved3 : 12;
242 ULONG DataBuffer : 20;
243 };
244 ULONG AsULONG;
245 } EHCI_TRANSACTION_BUFFER;
246
247 C_ASSERT(sizeof(EHCI_TRANSACTION_BUFFER) == sizeof(ULONG));
248
249 typedef struct _EHCI_ISOCHRONOUS_TD { // must be aligned on a 32-byte boundary
250 EHCI_LINK_POINTER NextLink;
251 EHCI_TRANSACTION_CONTROL Transaction[8];
252 EHCI_TRANSACTION_BUFFER Buffer[7];
253 ULONG ExtendedBuffer[7];
254 } EHCI_ISOCHRONOUS_TD, *PEHCI_ISOCHRONOUS_TD;
255
256 C_ASSERT(sizeof(EHCI_ISOCHRONOUS_TD) == 92);
257
258 /* Split Transaction Isochronous Transfer Descriptor (siTD) */
259 typedef union _EHCI_FS_ENDPOINT_PARAMS {
260 struct {
261 ULONG DeviceAddress : 7;
262 ULONG Reserved1 : 1;
263 ULONG EndpointNumber : 4;
264 ULONG Reserved2 : 4;
265 ULONG HubAddress : 7;
266 ULONG Reserved3 : 1;
267 ULONG PortNumber : 7;
268 ULONG Direction : 1;
269 };
270 ULONG AsULONG;
271 } EHCI_FS_ENDPOINT_PARAMS;
272
273 C_ASSERT(sizeof(EHCI_FS_ENDPOINT_PARAMS) == sizeof(ULONG));
274
275 typedef union _EHCI_MICROFRAME_CONTROL {
276 struct {
277 ULONG StartMask : 8;
278 ULONG CompletionMask : 8;
279 ULONG Reserved : 16;
280 };
281 ULONG AsULONG;
282 } EHCI_MICROFRAME_CONTROL;
283
284 C_ASSERT(sizeof(EHCI_MICROFRAME_CONTROL) == sizeof(ULONG));
285
286 typedef union _EHCI_SPLIT_TRANSFER_STATE {
287 struct {
288 ULONG Status : 8;
289 ULONG ProgressMask : 8;
290 ULONG TotalBytes : 10;
291 ULONG Reserved : 4;
292 ULONG PageSelect : 1;
293 ULONG InterruptOnComplete : 1;
294 };
295 ULONG AsULONG;
296 } EHCI_SPLIT_TRANSFER_STATE;
297
298 C_ASSERT(sizeof(EHCI_SPLIT_TRANSFER_STATE) == sizeof(ULONG));
299
300 typedef union _EHCI_SPLIT_BUFFER_POINTER {
301 struct {
302 ULONG CurrentOffset : 12;
303 ULONG DataBuffer0 : 20;
304 };
305 struct {
306 ULONG TransactionCount : 3;
307 ULONG TransactionPosition : 2;
308 ULONG Reserved : 7;
309 ULONG DataBuffer1 : 20;
310 };
311 ULONG AsULONG;
312 } EHCI_SPLIT_BUFFER_POINTER;
313
314 C_ASSERT(sizeof(EHCI_SPLIT_BUFFER_POINTER) == sizeof(ULONG));
315
316 typedef struct _EHCI_SPLIT_ISOCHRONOUS_TD { // must be aligned on a 32-byte boundary
317 EHCI_LINK_POINTER NextLink;
318 EHCI_FS_ENDPOINT_PARAMS EndpointCharacteristics;
319 EHCI_MICROFRAME_CONTROL MicroFrameControl;
320 EHCI_SPLIT_TRANSFER_STATE TransferState;
321 EHCI_SPLIT_BUFFER_POINTER Buffer[2];
322 ULONG BackPointer;
323 ULONG ExtendedBuffer[2];
324 } EHCI_SPLIT_ISOCHRONOUS_TD, *PEHCI_SPLIT_ISOCHRONOUS_TD;
325
326 C_ASSERT(sizeof(EHCI_SPLIT_ISOCHRONOUS_TD) == 36);
327
328 /* Queue Element Transfer Descriptor (qTD) */
329 #define EHCI_MAX_QTD_BUFFER_PAGES 5
330
331 #define EHCI_TOKEN_STATUS_ACTIVE (1 << 7)
332 #define EHCI_TOKEN_STATUS_HALTED (1 << 6)
333 #define EHCI_TOKEN_STATUS_DATA_BUFFER_ERROR (1 << 5)
334 #define EHCI_TOKEN_STATUS_BABBLE_DETECTED (1 << 4)
335 #define EHCI_TOKEN_STATUS_TRANSACTION_ERROR (1 << 3)
336 #define EHCI_TOKEN_STATUS_MISSED_MICROFRAME (1 << 2)
337 #define EHCI_TOKEN_STATUS_SPLIT_STATE (1 << 1)
338 #define EHCI_TOKEN_STATUS_PING_STATE (1 << 0)
339
340 #define EHCI_TD_TOKEN_PID_OUT 0
341 #define EHCI_TD_TOKEN_PID_IN 1
342 #define EHCI_TD_TOKEN_PID_SETUP 2
343 #define EHCI_TD_TOKEN_PID_RESERVED 3
344
345 typedef union _EHCI_TD_TOKEN {
346 struct {
347 ULONG Status : 8;
348 ULONG PIDCode : 2;
349 ULONG ErrorCounter : 2;
350 ULONG CurrentPage : 3;
351 ULONG InterruptOnComplete : 1;
352 ULONG TransferBytes : 15;
353 ULONG DataToggle : 1;
354 };
355 ULONG AsULONG;
356 } EHCI_TD_TOKEN, *PEHCI_TD_TOKEN;
357
358 C_ASSERT(sizeof(EHCI_TD_TOKEN) == sizeof(ULONG));
359
360 typedef struct _EHCI_QUEUE_TD { // must be aligned on 32-byte boundaries
361 ULONG NextTD;
362 ULONG AlternateNextTD;
363 EHCI_TD_TOKEN Token;
364 ULONG Buffer[5];
365 ULONG ExtendedBuffer[5];
366 } EHCI_QUEUE_TD, *PEHCI_QUEUE_TD;
367
368 C_ASSERT(sizeof(EHCI_QUEUE_TD) == 52);
369
370 /* Queue Head */
371 #define EHCI_QH_EP_FULL_SPEED 0
372 #define EHCI_QH_EP_LOW_SPEED 1
373 #define EHCI_QH_EP_HIGH_SPEED 2
374
375 typedef union _EHCI_QH_EP_PARAMS {
376 struct {
377 ULONG DeviceAddress : 7;
378 ULONG InactivateOnNextTransaction : 1;
379 ULONG EndpointNumber : 4;
380 ULONG EndpointSpeed : 2;
381 ULONG DataToggleControl : 1;
382 ULONG HeadReclamationListFlag : 1;
383 ULONG MaximumPacketLength : 11; // corresponds to the maximum packet size of the associated endpoint (wMaxPacketSize).
384 ULONG ControlEndpointFlag : 1;
385 ULONG NakCountReload : 4;
386 };
387 ULONG AsULONG;
388 } EHCI_QH_EP_PARAMS;
389
390 C_ASSERT(sizeof(EHCI_QH_EP_PARAMS) == sizeof(ULONG));
391
392 typedef union _EHCI_QH_EP_CAPS {
393 struct {
394 ULONG InterruptMask : 8;
395 ULONG SplitCompletionMask : 8;
396 ULONG HubAddr : 7;
397 ULONG PortNumber : 7;
398 ULONG PipeMultiplier : 2;
399 };
400 ULONG AsULONG;
401 } EHCI_QH_EP_CAPS;
402
403 C_ASSERT(sizeof(EHCI_QH_EP_CAPS) == sizeof(ULONG));
404
405 typedef struct _EHCI_QUEUE_HEAD { // must be aligned on 32-byte boundaries
406 EHCI_LINK_POINTER HorizontalLink;
407 EHCI_QH_EP_PARAMS EndpointParams;
408 EHCI_QH_EP_CAPS EndpointCaps;
409 ULONG CurrentTD;
410 ULONG NextTD;
411 ULONG AlternateNextTD;
412 EHCI_TD_TOKEN Token;
413 ULONG Buffer[5];
414 ULONG ExtendedBuffer[5];
415 } EHCI_QUEUE_HEAD, *PEHCI_QUEUE_HEAD;
416
417 C_ASSERT(sizeof(EHCI_QUEUE_HEAD) == 68);