reactos/drivers/usb/usbohci/hardware.h
2020-01-06 21:16:08 +02:00

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;