xref: /reactos/drivers/usb/usbehci/hardware.h (revision 81db5e1d)
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);
418