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