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