mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
333 lines
11 KiB
C
333 lines
11 KiB
C
/*
|
|
* 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 <vgal@rambler.ru>
|
|
*/
|
|
|
|
#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;
|