/* * PROJECT: ReactOS USB OHCI Miniport Driver * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) * PURPOSE: USBOHCI hardware declarations * COPYRIGHT: Copyright 2017-2018 Vadim Galyant */ #define OHCI_NUMBER_OF_INTERRUPTS 32 #define OHCI_MAX_PORT_COUNT 15 #define ED_EOF -1 #define OHCI_MAXIMUM_OVERHEAD 210 // 5.4 FrameInterval Counter, in bit-times #define OHCI_DEFAULT_FRAME_INTERVAL 11999 // 6.3.1 Frame Timing #define OHCI_MINIMAL_POTPGT 25 // == 50 ms., PowerOnToPowerGoodTime (HcRhDescriptorA Register) /* Controller states */ #define OHCI_HC_STATE_RESET 0 #define OHCI_HC_STATE_RESUME 1 #define OHCI_HC_STATE_OPERATIONAL 2 #define OHCI_HC_STATE_SUSPEND 3 /* Endpoint Descriptor Control */ #define OHCI_ED_DATA_FLOW_DIRECTION_FROM_TD 0 #define OHCI_ED_DATA_FLOW_DIRECTION_OUT 1 #define OHCI_ED_DATA_FLOW_DIRECTION_IN 2 #define OHCI_ENDPOINT_FULL_SPEED 0 #define OHCI_ENDPOINT_LOW_SPEED 1 #define OHCI_ENDPOINT_GENERAL_FORMAT 0 #define OHCI_ENDPOINT_ISOCHRONOUS_FORMAT 1 /* Transfer Descriptor Control */ #define OHCI_TD_INTERRUPT_IMMEDIATE 0 #define OHCI_TD_INTERRUPT_NONE 7 #define OHCI_TD_DIRECTION_PID_SETUP 0 #define OHCI_TD_DIRECTION_PID_OUT 1 #define OHCI_TD_DIRECTION_PID_IN 2 #define OHCI_TD_DIRECTION_PID_RESERVED 3 #define OHCI_TD_DATA_TOGGLE_FROM_ED 0 #define OHCI_TD_DATA_TOGGLE_DATA0 2 #define OHCI_TD_DATA_TOGGLE_DATA1 3 #define OHCI_TD_CONDITION_NO_ERROR 0x00 #define OHCI_TD_CONDITION_CRC_ERROR 0x01 #define OHCI_TD_CONDITION_BIT_STUFFING 0x02 #define OHCI_TD_CONDITION_TOGGLE_MISMATCH 0x03 #define OHCI_TD_CONDITION_STALL 0x04 #define OHCI_TD_CONDITION_NO_RESPONSE 0x05 #define OHCI_TD_CONDITION_PID_CHECK_FAILURE 0x06 #define OHCI_TD_CONDITION_UNEXPECTED_PID 0x07 #define OHCI_TD_CONDITION_DATA_OVERRUN 0x08 #define OHCI_TD_CONDITION_DATA_UNDERRUN 0x09 #define OHCI_TD_CONDITION_BUFFER_OVERRUN 0x0C #define OHCI_TD_CONDITION_BUFFER_UNDERRUN 0x0D #define OHCI_TD_CONDITION_NOT_ACCESSED 0x0E typedef union _OHCI_TRANSFER_CONTROL { struct { ULONG Reserved : 18; ULONG BufferRounding : 1; ULONG DirectionPID : 2; ULONG DelayInterrupt : 3; ULONG DataToggle : 2; ULONG ErrorCount : 2; ULONG ConditionCode : 4; }; ULONG AsULONG; } OHCI_TRANSFER_CONTROL, *POHCI_TRANSFER_CONTROL; C_ASSERT(sizeof(OHCI_TRANSFER_CONTROL) == sizeof(ULONG)); typedef struct _OHCI_TRANSFER_DESCRIPTOR { // must be aligned to a 16-byte boundary OHCI_TRANSFER_CONTROL Control; ULONG CurrentBuffer; // physical address of the next memory location ULONG NextTD; // pointer to the next TD on the list of TDs ULONG BufferEnd; // physical address of the last byte } OHCI_TRANSFER_DESCRIPTOR, *POHCI_TRANSFER_DESCRIPTOR; C_ASSERT(sizeof(OHCI_TRANSFER_DESCRIPTOR) == 16); typedef union _OHCI_ISO_TRANSFER_CONTROL { struct { ULONG StartingFrame : 16; ULONG Reserved1 : 5; ULONG DelayInterrupt : 3; ULONG FrameCount : 3; ULONG Reserved2 : 1; ULONG ConditionCode : 4; }; ULONG AsULONG; } OHCI_ISO_TRANSFER_CONTROL, *POHCI_ISO_TRANSFER_CONTROL; C_ASSERT(sizeof(OHCI_ISO_TRANSFER_CONTROL) == sizeof(ULONG)); typedef struct _OHCI_ISO_TRANSFER_DESCRIPTOR { // must be aligned to a 32-byte boundary OHCI_ISO_TRANSFER_CONTROL Control; ULONG BufferPage0; // physical page number of the 1 byte of the data buffer ULONG NextTD; // pointer to the next Isochronous TD on the queue of Isochronous TDs ULONG BufferEnd; // physical address of the last byte in the buffer USHORT Offset[8]; // for determine size and start addr. iso packet | PacketStatusWord - completion code } OHCI_ISO_TRANSFER_DESCRIPTOR, *POHCI_ISO_TRANSFER_DESCRIPTOR; C_ASSERT(sizeof(OHCI_ISO_TRANSFER_DESCRIPTOR) == 32); typedef union _OHCI_ENDPOINT_CONTROL { struct { ULONG FunctionAddress : 7; ULONG EndpointNumber : 4; ULONG Direction : 2; ULONG Speed : 1; ULONG sKip : 1; ULONG Format : 1; ULONG MaximumPacketSize : 11; ULONG Reserved : 5; }; ULONG AsULONG; } OHCI_ENDPOINT_CONTROL, *POHCI_ENDPOINT_CONTROL; C_ASSERT(sizeof(OHCI_ENDPOINT_CONTROL) == sizeof(ULONG)); /* Bit flags for HeadPointer member of the EP descriptor */ #define OHCI_ED_HEAD_POINTER_HALT 0x00000001 // hardware stopped bit #define OHCI_ED_HEAD_POINTER_CARRY 0x00000002 // hardware toggle carry bit #define OHCI_ED_HEAD_POINTER_MASK 0XFFFFFFF0 // mask physical pointer #define OHCI_ED_HEAD_POINTER_FLAGS_MASK 0X0000000F // mask bit flags typedef struct _OHCI_ENDPOINT_DESCRIPTOR { // must be aligned to a 16-byte boundary OHCI_ENDPOINT_CONTROL EndpointControl; ULONG TailPointer; // if TailP and HeadP are different, then the list contains a TD to be processed ULONG HeadPointer; // physical pointer to the next TD to be processed for this endpoint ULONG NextED; // entry points to the next ED on the list } OHCI_ENDPOINT_DESCRIPTOR, *POHCI_ENDPOINT_DESCRIPTOR; C_ASSERT(sizeof(OHCI_ENDPOINT_DESCRIPTOR) == 16); typedef struct _OHCI_HCCA { // must be located on a 256-byte boundary ULONG InterrruptTable[OHCI_NUMBER_OF_INTERRUPTS]; USHORT FrameNumber; USHORT Pad1; ULONG DoneHead; UCHAR reserved_hc[116]; UCHAR Pad[4]; } OHCI_HCCA, *POHCI_HCCA; C_ASSERT(sizeof(OHCI_HCCA) == 256); typedef union _OHCI_REG_CONTROL { struct { ULONG ControlBulkServiceRatio : 2; ULONG PeriodicListEnable : 1; ULONG IsochronousEnable : 1; ULONG ControlListEnable : 1; ULONG BulkListEnable : 1; ULONG HostControllerFunctionalState : 2; ULONG InterruptRouting : 1; ULONG RemoteWakeupConnected : 1; ULONG RemoteWakeupEnable : 1; ULONG Reserved : 21; }; ULONG AsULONG; } OHCI_REG_CONTROL, *POHCI_REG_CONTROL; C_ASSERT(sizeof(OHCI_REG_CONTROL) == sizeof(ULONG)); typedef union _OHCI_REG_COMMAND_STATUS { struct { ULONG HostControllerReset : 1; ULONG ControlListFilled : 1; ULONG BulkListFilled : 1; ULONG OwnershipChangeRequest : 1; ULONG Reserved1 : 12; ULONG SchedulingOverrunCount : 1; ULONG Reserved2 : 15; }; ULONG AsULONG; } OHCI_REG_COMMAND_STATUS, *POHCI_REG_COMMAND_STATUS; C_ASSERT(sizeof(OHCI_REG_COMMAND_STATUS) == sizeof(ULONG)); typedef union _OHCI_REG_INTERRUPT_STATUS { struct { ULONG SchedulingOverrun : 1; ULONG WritebackDoneHead : 1; ULONG StartofFrame : 1; ULONG ResumeDetected : 1; ULONG UnrecoverableError : 1; ULONG FrameNumberOverflow : 1; ULONG RootHubStatusChange : 1; ULONG Reserved1 : 23; ULONG OwnershipChange : 1; ULONG Reserved2 : 1; }; ULONG AsULONG; } OHCI_REG_INTERRUPT_STATUS, *POHCI_REG_INTERRUPT_STATUS; C_ASSERT(sizeof(OHCI_REG_INTERRUPT_STATUS) == sizeof(ULONG)); typedef union _OHCI_REG_INTERRUPT_ENABLE_DISABLE { struct { ULONG SchedulingOverrun : 1; ULONG WritebackDoneHead : 1; ULONG StartofFrame : 1; ULONG ResumeDetected : 1; ULONG UnrecoverableError : 1; ULONG FrameNumberOverflow : 1; ULONG RootHubStatusChange : 1; ULONG Reserved1 : 23; ULONG OwnershipChange : 1; ULONG MasterInterruptEnable : 1; }; ULONG AsULONG; } OHCI_REG_INTERRUPT_ENABLE_DISABLE, *POHCI_REG_INTERRUPT_ENABLE_DISABLE; C_ASSERT(sizeof(OHCI_REG_INTERRUPT_ENABLE_DISABLE) == sizeof(ULONG)); typedef union _OHCI_REG_FRAME_INTERVAL { struct { ULONG FrameInterval : 14; ULONG Reserved : 2; ULONG FSLargestDataPacket : 15; ULONG FrameIntervalToggle : 1; }; ULONG AsULONG; } OHCI_REG_FRAME_INTERVAL, *POHCI_REG_FRAME_INTERVAL; C_ASSERT(sizeof(OHCI_REG_FRAME_INTERVAL) == sizeof(ULONG)); typedef union _OHCI_REG_RH_DESCRIPTORA { struct { ULONG NumberDownstreamPorts : 8; ULONG PowerSwitchingMode : 1; ULONG NoPowerSwitching : 1; ULONG DeviceType : 1; ULONG OverCurrentProtectionMode : 1; ULONG NoOverCurrentProtection : 1; ULONG Reserved : 11; ULONG PowerOnToPowerGoodTime : 8; }; ULONG AsULONG; } OHCI_REG_RH_DESCRIPTORA, *POHCI_REG_RH_DESCRIPTORA; C_ASSERT(sizeof(OHCI_REG_RH_DESCRIPTORA) == sizeof(ULONG)); typedef union _OHCI_REG_RH_STATUS { union { struct { // read ULONG LocalPowerStatus : 1; ULONG OverCurrentIndicator : 1; ULONG Reserved10 : 13; ULONG DeviceRemoteWakeupEnable : 1; ULONG LocalPowerStatusChange : 1; ULONG OverCurrentIndicatorChangeR : 1; ULONG Reserved20 : 14; }; struct { // write ULONG ClearGlobalPower : 1; ULONG Reserved11 : 14; ULONG SetRemoteWakeupEnable : 1; ULONG SetGlobalPower : 1; ULONG OverCurrentIndicatorChangeW : 1; ULONG Reserved22 : 13; ULONG ClearRemoteWakeupEnable : 1; }; }; ULONG AsULONG; } OHCI_REG_RH_STATUS, *POHCI_REG_RH_STATUS; C_ASSERT(sizeof(OHCI_REG_RH_STATUS) == sizeof(ULONG)); typedef union _OHCI_REG_RH_PORT_STATUS { struct { union { struct { // read USHORT CurrentConnectStatus : 1; USHORT PortEnableStatus : 1; USHORT PortSuspendStatus : 1; USHORT PortOverCurrentIndicator : 1; USHORT PortResetStatus : 1; USHORT Reserved1r : 3; USHORT PortPowerStatus : 1; USHORT LowSpeedDeviceAttached : 1; USHORT Reserved2r : 6; }; struct { // write USHORT ClearPortEnable : 1; USHORT SetPortEnable : 1; USHORT SetPortSuspend : 1; USHORT ClearSuspendStatus : 1; USHORT SetPortReset : 1; USHORT Reserved1w : 3; USHORT SetPortPower : 1; USHORT ClearPortPower : 1; USHORT Reserved2w : 6; }; }; USHORT ConnectStatusChange : 1; USHORT PortEnableStatusChange : 1; USHORT PortSuspendStatusChange : 1; USHORT PortOverCurrentIndicatorChange : 1; USHORT PortResetStatusChange : 1; USHORT Reserved3 : 11; }; ULONG AsULONG; } OHCI_REG_RH_PORT_STATUS, *POHCI_REG_RH_PORT_STATUS; C_ASSERT(sizeof(OHCI_REG_RH_PORT_STATUS) == sizeof(ULONG)); typedef struct _OHCI_OPERATIONAL_REGISTERS { ULONG HcRevision; OHCI_REG_CONTROL HcControl; OHCI_REG_COMMAND_STATUS HcCommandStatus; OHCI_REG_INTERRUPT_STATUS HcInterruptStatus; OHCI_REG_INTERRUPT_ENABLE_DISABLE HcInterruptEnable; OHCI_REG_INTERRUPT_ENABLE_DISABLE HcInterruptDisable; ULONG HcHCCA; ULONG HcPeriodCurrentED; ULONG HcControlHeadED; ULONG HcControlCurrentED; ULONG HcBulkHeadED; ULONG HcBulkCurrentED; ULONG HcDoneHead; OHCI_REG_FRAME_INTERVAL HcFmInterval; ULONG HcFmRemaining; ULONG HcFmNumber; ULONG HcPeriodicStart; ULONG HcLSThreshold; OHCI_REG_RH_DESCRIPTORA HcRhDescriptorA; ULONG HcRhDescriptorB; OHCI_REG_RH_STATUS HcRhStatus; OHCI_REG_RH_PORT_STATUS HcRhPortStatus[OHCI_MAX_PORT_COUNT]; } OHCI_OPERATIONAL_REGISTERS, *POHCI_OPERATIONAL_REGISTERS;