xref: /reactos/drivers/usb/usbohci/hardware.h (revision 1734f297)
1 /*
2  * PROJECT:     ReactOS USB OHCI Miniport Driver
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     USBOHCI hardware declarations
5  * COPYRIGHT:   Copyright 2017-2018 Vadim Galyant <vgal@rambler.ru>
6  */
7 
8 #define OHCI_NUMBER_OF_INTERRUPTS    32
9 #define OHCI_MAX_PORT_COUNT          15
10 #define ED_EOF                       -1
11 #define OHCI_MAXIMUM_OVERHEAD        210 // 5.4  FrameInterval Counter, in bit-times
12 #define OHCI_DEFAULT_FRAME_INTERVAL  11999 // 6.3.1  Frame Timing
13 #define OHCI_MINIMAL_POTPGT          25 // == 50 ms., PowerOnToPowerGoodTime (HcRhDescriptorA Register)
14 
15 /* Controller states */
16 #define OHCI_HC_STATE_RESET       0
17 #define OHCI_HC_STATE_RESUME      1
18 #define OHCI_HC_STATE_OPERATIONAL 2
19 #define OHCI_HC_STATE_SUSPEND     3
20 
21 /* Endpoint Descriptor Control */
22 #define OHCI_ED_DATA_FLOW_DIRECTION_FROM_TD 0
23 #define OHCI_ED_DATA_FLOW_DIRECTION_OUT     1
24 #define OHCI_ED_DATA_FLOW_DIRECTION_IN      2
25 
26 #define OHCI_ENDPOINT_FULL_SPEED 0
27 #define OHCI_ENDPOINT_LOW_SPEED  1
28 
29 #define OHCI_ENDPOINT_GENERAL_FORMAT     0
30 #define OHCI_ENDPOINT_ISOCHRONOUS_FORMAT 1
31 
32 /* Transfer Descriptor Control */
33 #define OHCI_TD_INTERRUPT_IMMEDIATE 0
34 #define OHCI_TD_INTERRUPT_NONE      7
35 
36 #define OHCI_TD_DIRECTION_PID_SETUP    0
37 #define OHCI_TD_DIRECTION_PID_OUT      1
38 #define OHCI_TD_DIRECTION_PID_IN       2
39 #define OHCI_TD_DIRECTION_PID_RESERVED 3
40 
41 #define OHCI_TD_DATA_TOGGLE_FROM_ED  0
42 #define OHCI_TD_DATA_TOGGLE_DATA0    2
43 #define OHCI_TD_DATA_TOGGLE_DATA1    3
44 
45 #define OHCI_TD_CONDITION_NO_ERROR          0x00
46 #define OHCI_TD_CONDITION_CRC_ERROR         0x01
47 #define OHCI_TD_CONDITION_BIT_STUFFING      0x02
48 #define OHCI_TD_CONDITION_TOGGLE_MISMATCH   0x03
49 #define OHCI_TD_CONDITION_STALL             0x04
50 #define OHCI_TD_CONDITION_NO_RESPONSE       0x05
51 #define OHCI_TD_CONDITION_PID_CHECK_FAILURE 0x06
52 #define OHCI_TD_CONDITION_UNEXPECTED_PID    0x07
53 #define OHCI_TD_CONDITION_DATA_OVERRUN      0x08
54 #define OHCI_TD_CONDITION_DATA_UNDERRUN     0x09
55 #define OHCI_TD_CONDITION_BUFFER_OVERRUN    0x0C
56 #define OHCI_TD_CONDITION_BUFFER_UNDERRUN   0x0D
57 #define OHCI_TD_CONDITION_NOT_ACCESSED      0x0E
58 
59 typedef union _OHCI_TRANSFER_CONTROL {
60   struct {
61     ULONG Reserved       : 18;
62     ULONG BufferRounding : 1;
63     ULONG DirectionPID   : 2;
64     ULONG DelayInterrupt : 3;
65     ULONG DataToggle     : 2;
66     ULONG ErrorCount     : 2;
67     ULONG ConditionCode  : 4;
68   };
69   ULONG  AsULONG;
70 } OHCI_TRANSFER_CONTROL, *POHCI_TRANSFER_CONTROL;
71 
72 C_ASSERT(sizeof(OHCI_TRANSFER_CONTROL) == sizeof(ULONG));
73 
74 typedef struct _OHCI_TRANSFER_DESCRIPTOR { // must be aligned to a 16-byte boundary
75   OHCI_TRANSFER_CONTROL Control;
76   ULONG CurrentBuffer; // physical address of the next memory location
77   ULONG NextTD; // pointer to the next TD on the list of TDs
78   ULONG BufferEnd; // physical address of the last byte
79 } OHCI_TRANSFER_DESCRIPTOR, *POHCI_TRANSFER_DESCRIPTOR;
80 
81 C_ASSERT(sizeof(OHCI_TRANSFER_DESCRIPTOR) == 16);
82 
83 typedef union _OHCI_ISO_TRANSFER_CONTROL {
84   struct {
85     ULONG StartingFrame  : 16;
86     ULONG Reserved1      : 5;
87     ULONG DelayInterrupt : 3;
88     ULONG FrameCount     : 3;
89     ULONG Reserved2      : 1;
90     ULONG ConditionCode  : 4;
91   };
92   ULONG  AsULONG;
93 } OHCI_ISO_TRANSFER_CONTROL, *POHCI_ISO_TRANSFER_CONTROL;
94 
95 C_ASSERT(sizeof(OHCI_ISO_TRANSFER_CONTROL) == sizeof(ULONG));
96 
97 typedef struct _OHCI_ISO_TRANSFER_DESCRIPTOR { // must be aligned to a 32-byte boundary
98   OHCI_ISO_TRANSFER_CONTROL Control;
99   ULONG BufferPage0; // physical page number of the 1 byte of the data buffer
100   ULONG NextTD; // pointer to the next Isochronous TD on the queue of Isochronous TDs
101   ULONG BufferEnd; // physical address of the last byte in the buffer
102   USHORT Offset[8]; // for determine size and start addr. iso packet | PacketStatusWord - completion code
103 } OHCI_ISO_TRANSFER_DESCRIPTOR, *POHCI_ISO_TRANSFER_DESCRIPTOR;
104 
105 C_ASSERT(sizeof(OHCI_ISO_TRANSFER_DESCRIPTOR) == 32);
106 
107 typedef union _OHCI_ENDPOINT_CONTROL {
108   struct {
109     ULONG FunctionAddress   : 7;
110     ULONG EndpointNumber    : 4;
111     ULONG Direction         : 2;
112     ULONG Speed             : 1;
113     ULONG sKip              : 1;
114     ULONG Format            : 1;
115     ULONG MaximumPacketSize : 11;
116     ULONG Reserved          : 5;
117   };
118   ULONG  AsULONG;
119 } OHCI_ENDPOINT_CONTROL, *POHCI_ENDPOINT_CONTROL;
120 
121 C_ASSERT(sizeof(OHCI_ENDPOINT_CONTROL) == sizeof(ULONG));
122 
123 /* Bit flags for HeadPointer member of the EP descriptor */
124 #define OHCI_ED_HEAD_POINTER_HALT        0x00000001 // hardware stopped bit
125 #define OHCI_ED_HEAD_POINTER_CARRY       0x00000002 // hardware toggle carry bit
126 #define OHCI_ED_HEAD_POINTER_MASK        0XFFFFFFF0 // mask physical pointer
127 #define OHCI_ED_HEAD_POINTER_FLAGS_MASK  0X0000000F // mask bit flags
128 
129 typedef struct _OHCI_ENDPOINT_DESCRIPTOR { // must be aligned to a 16-byte boundary
130   OHCI_ENDPOINT_CONTROL EndpointControl;
131   ULONG TailPointer; // if TailP and HeadP are different, then the list contains a TD to be processed
132   ULONG HeadPointer; // physical pointer to the next TD to be processed for this endpoint
133   ULONG NextED; // entry points to the next ED on the list
134 } OHCI_ENDPOINT_DESCRIPTOR, *POHCI_ENDPOINT_DESCRIPTOR;
135 
136 C_ASSERT(sizeof(OHCI_ENDPOINT_DESCRIPTOR) == 16);
137 
138 typedef struct _OHCI_HCCA { // must be located on a 256-byte boundary
139   ULONG InterrruptTable[OHCI_NUMBER_OF_INTERRUPTS];
140   USHORT FrameNumber;
141   USHORT Pad1;
142   ULONG DoneHead;
143   UCHAR reserved_hc[116];
144   UCHAR Pad[4];
145 } OHCI_HCCA, *POHCI_HCCA;
146 
147 C_ASSERT(sizeof(OHCI_HCCA) == 256);
148 
149 typedef union _OHCI_REG_CONTROL {
150   struct {
151     ULONG ControlBulkServiceRatio       : 2;
152     ULONG PeriodicListEnable            : 1;
153     ULONG IsochronousEnable             : 1;
154     ULONG ControlListEnable             : 1;
155     ULONG BulkListEnable                : 1;
156     ULONG HostControllerFunctionalState : 2;
157     ULONG InterruptRouting              : 1;
158     ULONG RemoteWakeupConnected         : 1;
159     ULONG RemoteWakeupEnable            : 1;
160     ULONG Reserved                      : 21;
161   };
162   ULONG AsULONG;
163 } OHCI_REG_CONTROL, *POHCI_REG_CONTROL;
164 
165 C_ASSERT(sizeof(OHCI_REG_CONTROL) == sizeof(ULONG));
166 
167 typedef union _OHCI_REG_COMMAND_STATUS {
168   struct {
169     ULONG HostControllerReset    : 1;
170     ULONG ControlListFilled      : 1;
171     ULONG BulkListFilled         : 1;
172     ULONG OwnershipChangeRequest : 1;
173     ULONG Reserved1              : 12;
174     ULONG SchedulingOverrunCount : 1;
175     ULONG Reserved2              : 15;
176   };
177   ULONG AsULONG;
178 } OHCI_REG_COMMAND_STATUS, *POHCI_REG_COMMAND_STATUS;
179 
180 C_ASSERT(sizeof(OHCI_REG_COMMAND_STATUS) == sizeof(ULONG));
181 
182 typedef union _OHCI_REG_INTERRUPT_STATUS {
183   struct {
184     ULONG SchedulingOverrun   : 1;
185     ULONG WritebackDoneHead   : 1;
186     ULONG StartofFrame        : 1;
187     ULONG ResumeDetected      : 1;
188     ULONG UnrecoverableError  : 1;
189     ULONG FrameNumberOverflow : 1;
190     ULONG RootHubStatusChange : 1;
191     ULONG Reserved1           : 23;
192     ULONG OwnershipChange     : 1;
193     ULONG Reserved2           : 1;
194   };
195   ULONG AsULONG;
196 } OHCI_REG_INTERRUPT_STATUS, *POHCI_REG_INTERRUPT_STATUS;
197 
198 C_ASSERT(sizeof(OHCI_REG_INTERRUPT_STATUS) == sizeof(ULONG));
199 
200 typedef union _OHCI_REG_INTERRUPT_ENABLE_DISABLE {
201   struct {
202     ULONG SchedulingOverrun     : 1;
203     ULONG WritebackDoneHead     : 1;
204     ULONG StartofFrame          : 1;
205     ULONG ResumeDetected        : 1;
206     ULONG UnrecoverableError    : 1;
207     ULONG FrameNumberOverflow   : 1;
208     ULONG RootHubStatusChange   : 1;
209     ULONG Reserved1             : 23;
210     ULONG OwnershipChange       : 1;
211     ULONG MasterInterruptEnable : 1;
212   };
213   ULONG AsULONG;
214 } OHCI_REG_INTERRUPT_ENABLE_DISABLE, *POHCI_REG_INTERRUPT_ENABLE_DISABLE;
215 
216 C_ASSERT(sizeof(OHCI_REG_INTERRUPT_ENABLE_DISABLE) == sizeof(ULONG));
217 
218 typedef union _OHCI_REG_FRAME_INTERVAL {
219   struct {
220     ULONG FrameInterval       : 14;
221     ULONG Reserved            : 2;
222     ULONG FSLargestDataPacket : 15;
223     ULONG FrameIntervalToggle : 1;
224   };
225   ULONG AsULONG;
226 } OHCI_REG_FRAME_INTERVAL, *POHCI_REG_FRAME_INTERVAL;
227 
228 C_ASSERT(sizeof(OHCI_REG_FRAME_INTERVAL) == sizeof(ULONG));
229 
230 typedef union _OHCI_REG_RH_DESCRIPTORA {
231   struct {
232     ULONG NumberDownstreamPorts     : 8;
233     ULONG PowerSwitchingMode        : 1;
234     ULONG NoPowerSwitching          : 1;
235     ULONG DeviceType                : 1;
236     ULONG OverCurrentProtectionMode : 1;
237     ULONG NoOverCurrentProtection   : 1;
238     ULONG Reserved                  : 11;
239     ULONG PowerOnToPowerGoodTime    : 8;
240   };
241   ULONG AsULONG;
242 } OHCI_REG_RH_DESCRIPTORA, *POHCI_REG_RH_DESCRIPTORA;
243 
244 C_ASSERT(sizeof(OHCI_REG_RH_DESCRIPTORA) == sizeof(ULONG));
245 
246 typedef union _OHCI_REG_RH_STATUS {
247   union {
248     struct { // read
249       ULONG LocalPowerStatus            : 1;
250       ULONG OverCurrentIndicator        : 1;
251       ULONG Reserved10                  : 13;
252       ULONG DeviceRemoteWakeupEnable    : 1;
253       ULONG LocalPowerStatusChange      : 1;
254       ULONG OverCurrentIndicatorChangeR : 1;
255       ULONG Reserved20                  : 14;
256     };
257     struct { // write
258       ULONG ClearGlobalPower            : 1;
259       ULONG Reserved11                  : 14;
260       ULONG SetRemoteWakeupEnable       : 1;
261       ULONG SetGlobalPower              : 1;
262       ULONG OverCurrentIndicatorChangeW : 1;
263       ULONG Reserved22                  : 13;
264       ULONG ClearRemoteWakeupEnable     : 1;
265     };
266   };
267   ULONG AsULONG;
268 } OHCI_REG_RH_STATUS, *POHCI_REG_RH_STATUS;
269 
270 C_ASSERT(sizeof(OHCI_REG_RH_STATUS) == sizeof(ULONG));
271 
272 typedef union _OHCI_REG_RH_PORT_STATUS {
273   struct {
274     union  {
275       struct { // read
276         USHORT  CurrentConnectStatus     : 1;
277         USHORT  PortEnableStatus         : 1;
278         USHORT  PortSuspendStatus        : 1;
279         USHORT  PortOverCurrentIndicator : 1;
280         USHORT  PortResetStatus          : 1;
281         USHORT  Reserved1r               : 3;
282         USHORT  PortPowerStatus          : 1;
283         USHORT  LowSpeedDeviceAttached   : 1;
284         USHORT  Reserved2r               : 6;
285       };
286       struct { // write
287         USHORT  ClearPortEnable    : 1;
288         USHORT  SetPortEnable      : 1;
289         USHORT  SetPortSuspend     : 1;
290         USHORT  ClearSuspendStatus : 1;
291         USHORT  SetPortReset       : 1;
292         USHORT  Reserved1w         : 3;
293         USHORT  SetPortPower       : 1;
294         USHORT  ClearPortPower     : 1;
295         USHORT  Reserved2w         : 6;
296       };
297     };
298     USHORT ConnectStatusChange            : 1;
299     USHORT PortEnableStatusChange         : 1;
300     USHORT PortSuspendStatusChange        : 1;
301     USHORT PortOverCurrentIndicatorChange : 1;
302     USHORT PortResetStatusChange          : 1;
303     USHORT Reserved3                      : 11;
304   };
305   ULONG  AsULONG;
306 } OHCI_REG_RH_PORT_STATUS, *POHCI_REG_RH_PORT_STATUS;
307 
308 C_ASSERT(sizeof(OHCI_REG_RH_PORT_STATUS) == sizeof(ULONG));
309 
310 typedef struct _OHCI_OPERATIONAL_REGISTERS {
311   ULONG HcRevision;
312   OHCI_REG_CONTROL HcControl;
313   OHCI_REG_COMMAND_STATUS HcCommandStatus;
314   OHCI_REG_INTERRUPT_STATUS HcInterruptStatus;
315   OHCI_REG_INTERRUPT_ENABLE_DISABLE HcInterruptEnable;
316   OHCI_REG_INTERRUPT_ENABLE_DISABLE HcInterruptDisable;
317   ULONG HcHCCA;
318   ULONG HcPeriodCurrentED;
319   ULONG HcControlHeadED;
320   ULONG HcControlCurrentED;
321   ULONG HcBulkHeadED;
322   ULONG HcBulkCurrentED;
323   ULONG HcDoneHead;
324   OHCI_REG_FRAME_INTERVAL HcFmInterval;
325   ULONG HcFmRemaining;
326   ULONG HcFmNumber;
327   ULONG HcPeriodicStart;
328   ULONG HcLSThreshold;
329   OHCI_REG_RH_DESCRIPTORA HcRhDescriptorA;
330   ULONG HcRhDescriptorB;
331   OHCI_REG_RH_STATUS HcRhStatus;
332   OHCI_REG_RH_PORT_STATUS HcRhPortStatus[OHCI_MAX_PORT_COUNT];
333 } OHCI_OPERATIONAL_REGISTERS, *POHCI_OPERATIONAL_REGISTERS;
334