reactos/drivers/usb/usbehci/hardware.h
2021-06-11 15:33:08 +03:00

418 lines
12 KiB
C

/*
* PROJECT: ReactOS USB EHCI Miniport Driver
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: USBEHCI hardware declarations
* COPYRIGHT: Copyright 2017-2018 Vadim Galyant <vgal@rambler.ru>
*/
#define EHCI_FRAME_LIST_MAX_ENTRIES 1024 // Number of frames in Frame List
/* EHCI hardware registers */
#define EHCI_USBCMD 0
#define EHCI_USBSTS 1
#define EHCI_USBINTR 2
#define EHCI_FRINDEX 3
#define EHCI_CTRLDSSEGMENT 4
#define EHCI_PERIODICLISTBASE 5
#define EHCI_ASYNCLISTBASE 6
#define EHCI_CONFIGFLAG 16
#define EHCI_PORTSC 17
#define EHCI_FLADJ_PCI_CONFIG_OFFSET 0x61
typedef union _EHCI_LEGACY_EXTENDED_CAPABILITY {
struct {
ULONG CapabilityID : 8;
ULONG NextCapabilityPointer : 8;
ULONG BiosOwnedSemaphore : 1;
ULONG Reserved1 : 7;
ULONG OsOwnedSemaphore : 1;
ULONG Reserved2 : 7;
};
ULONG AsULONG;
} EHCI_LEGACY_EXTENDED_CAPABILITY;
C_ASSERT(sizeof(EHCI_LEGACY_EXTENDED_CAPABILITY) == sizeof(ULONG));
typedef union _EHCI_HC_STRUCTURAL_PARAMS {
struct {
ULONG PortCount : 4;
ULONG PortPowerControl : 1;
ULONG Reserved1 : 2;
ULONG PortRouteRules : 1;
ULONG PortsPerCompanion : 4;
ULONG CompanionControllers : 4;
ULONG PortIndicators : 1;
ULONG Reserved2 : 3;
ULONG DebugPortNumber : 4; //Optional
ULONG Reserved3 : 8;
};
ULONG AsULONG;
} EHCI_HC_STRUCTURAL_PARAMS;
C_ASSERT(sizeof(EHCI_HC_STRUCTURAL_PARAMS) == sizeof(ULONG));
typedef union _EHCI_HC_CAPABILITY_PARAMS {
struct {
ULONG Addressing64bitCapability : 1;
ULONG IsProgrammableFrameList : 1;
ULONG IsScheduleParkSupport : 1;
ULONG Reserved1 : 1;
ULONG IsoSchedulingThreshold : 4;
ULONG ExtCapabilitiesPointer : 8; // (EECP)
ULONG Reserved2 : 16;
};
ULONG AsULONG;
} EHCI_HC_CAPABILITY_PARAMS;
C_ASSERT(sizeof(EHCI_HC_CAPABILITY_PARAMS) == sizeof(ULONG));
typedef struct _EHCI_HC_CAPABILITY_REGISTERS {
UCHAR RegistersLength; // RO
UCHAR Reserved; // RO
USHORT InterfaceVersion; // RO
EHCI_HC_STRUCTURAL_PARAMS StructParameters; // RO
EHCI_HC_CAPABILITY_PARAMS CapParameters; // RO
UCHAR CompanionPortRouteDesc[8]; // RO
} EHCI_HC_CAPABILITY_REGISTERS, *PEHCI_HC_CAPABILITY_REGISTERS;
typedef union _EHCI_USB_COMMAND {
struct {
ULONG Run : 1;
ULONG Reset : 1;
ULONG FrameListSize : 2;
ULONG PeriodicEnable : 1;
ULONG AsynchronousEnable : 1;
ULONG InterruptAdvanceDoorbell : 1;
ULONG LightResetHC : 1; // optional
ULONG AsynchronousParkModeCount : 2; // optional
ULONG Reserved1 : 1;
ULONG AsynchronousParkModeEnable : 1; // optional
ULONG Reserved2 : 4;
ULONG InterruptThreshold : 8;
ULONG Reserved3 : 8;
};
ULONG AsULONG;
} EHCI_USB_COMMAND;
C_ASSERT(sizeof(EHCI_USB_COMMAND) == sizeof(ULONG));
typedef union _EHCI_USB_STATUS {
struct {
ULONG Interrupt : 1;
ULONG ErrorInterrupt : 1;
ULONG PortChangeDetect : 1;
ULONG FrameListRollover : 1;
ULONG HostSystemError : 1;
ULONG InterruptOnAsyncAdvance : 1;
ULONG Reserved1 : 6;
ULONG HCHalted : 1;
ULONG Reclamation : 1;
ULONG PeriodicStatus : 1;
ULONG AsynchronousStatus : 1;
ULONG Reserved2 : 16;
};
ULONG AsULONG;
} EHCI_USB_STATUS;
C_ASSERT(sizeof(EHCI_USB_STATUS) == sizeof(ULONG));
#define EHCI_INTERRUPT_MASK 0x3F
typedef union _EHCI_INTERRUPT_ENABLE {
struct {
ULONG Interrupt : 1;
ULONG ErrorInterrupt : 1;
ULONG PortChangeInterrupt : 1;
ULONG FrameListRollover : 1;
ULONG HostSystemError : 1;
ULONG InterruptOnAsyncAdvance : 1;
ULONG Reserved : 26;
};
ULONG AsULONG;
} EHCI_INTERRUPT_ENABLE;
C_ASSERT(sizeof(EHCI_INTERRUPT_ENABLE) == sizeof(ULONG));
#define EHCI_LINE_STATUS_K_STATE_LOW_SPEED 1
#define EHCI_PORT_OWNER_COMPANION_CONTROLLER 1
typedef union _EHCI_PORT_STATUS_CONTROL {
struct {
ULONG CurrentConnectStatus : 1;
ULONG ConnectStatusChange : 1;
ULONG PortEnabledDisabled : 1;
ULONG PortEnableDisableChange : 1;
ULONG OverCurrentActive : 1;
ULONG OverCurrentChange : 1;
ULONG ForcePortResume : 1;
ULONG Suspend : 1;
ULONG PortReset : 1;
ULONG Reserved1 : 1;
ULONG LineStatus : 2;
ULONG PortPower : 1;
ULONG PortOwner : 1;
ULONG PortIndicatorControl : 2;
ULONG PortTestControl : 4;
ULONG WakeOnConnectEnable : 1;
ULONG WakeOnDisconnectEnable : 1;
ULONG WakeOnOverCurrentEnable : 1;
ULONG Reserved2 : 9;
};
ULONG AsULONG;
} EHCI_PORT_STATUS_CONTROL;
C_ASSERT(sizeof(EHCI_PORT_STATUS_CONTROL) == sizeof(ULONG));
/* FRINDEX Frame Index Register */
#define EHCI_FRINDEX_FRAME_MASK 0x7FF
#define EHCI_FRINDEX_INDEX_MASK 0x3FF
#define EHCI_CONFIG_FLAG_CONFIGURED 1
typedef struct _EHCI_HW_REGISTERS {
EHCI_USB_COMMAND HcCommand; // RO, R/W (field dependent), WO
EHCI_USB_STATUS HcStatus; // RO, R/W, R/WC, (field dependent)
EHCI_INTERRUPT_ENABLE HcInterruptEnable; // R/W
ULONG FrameIndex; // R/W (Writes must be DWord Writes)
ULONG SegmentSelector; // R/W (Writes must be DWord Writes)
ULONG PeriodicListBase; // R/W (Writes must be DWord Writes)
ULONG AsyncListBase; // Read/Write (Writes must be DWord Writes)
ULONG Reserved[9];
ULONG ConfigFlag; // R/W
EHCI_PORT_STATUS_CONTROL PortControl[15]; // (1-15) RO, R/W, R/WC (field dependent)
} EHCI_HW_REGISTERS, *PEHCI_HW_REGISTERS;
/* Link Pointer */
#define EHCI_LINK_TYPE_iTD 0 // isochronous transfer descriptor
#define EHCI_LINK_TYPE_QH 1 // queue head
#define EHCI_LINK_TYPE_siTD 2 // split transaction isochronous transfer
#define EHCI_LINK_TYPE_FSTN 3 // frame span traversal node
/* Used for QHs and qTDs to mark Pointers as the end */
#define TERMINATE_POINTER 1
#define LINK_POINTER_MASK 0xFFFFFFE0
typedef union _EHCI_LINK_POINTER {
struct {
ULONG Terminate : 1;
ULONG Type : 2;
ULONG Reserved : 2;
ULONG Address : 27;
};
ULONG AsULONG;
} EHCI_LINK_POINTER;
C_ASSERT(sizeof(EHCI_LINK_POINTER) == sizeof(ULONG));
/* Isochronous (High-Speed) Transfer Descriptor (iTD) */
typedef union _EHCI_TRANSACTION_CONTROL {
struct {
ULONG xOffset : 12;
ULONG PageSelect : 3;
ULONG InterruptOnComplete : 1;
ULONG xLength : 12;
ULONG Status : 4;
};
ULONG AsULONG;
} EHCI_TRANSACTION_CONTROL;
C_ASSERT(sizeof(EHCI_TRANSACTION_CONTROL) == sizeof(ULONG));
typedef union _EHCI_TRANSACTION_BUFFER {
struct {
ULONG DeviceAddress : 7;
ULONG Reserved1 : 1;
ULONG EndpointNumber : 4;
ULONG DataBuffer0 : 20;
};
struct {
ULONG MaximumPacketSize : 11;
ULONG Direction : 1;
ULONG DataBuffer1 : 20;
};
struct {
ULONG Multi : 2;
ULONG Reserved2 : 10;
ULONG DataBuffer2 : 20;
};
struct {
ULONG Reserved3 : 12;
ULONG DataBuffer : 20;
};
ULONG AsULONG;
} EHCI_TRANSACTION_BUFFER;
C_ASSERT(sizeof(EHCI_TRANSACTION_BUFFER) == sizeof(ULONG));
typedef struct _EHCI_ISOCHRONOUS_TD { // must be aligned on a 32-byte boundary
EHCI_LINK_POINTER NextLink;
EHCI_TRANSACTION_CONTROL Transaction[8];
EHCI_TRANSACTION_BUFFER Buffer[7];
ULONG ExtendedBuffer[7];
} EHCI_ISOCHRONOUS_TD, *PEHCI_ISOCHRONOUS_TD;
C_ASSERT(sizeof(EHCI_ISOCHRONOUS_TD) == 92);
/* Split Transaction Isochronous Transfer Descriptor (siTD) */
typedef union _EHCI_FS_ENDPOINT_PARAMS {
struct {
ULONG DeviceAddress : 7;
ULONG Reserved1 : 1;
ULONG EndpointNumber : 4;
ULONG Reserved2 : 4;
ULONG HubAddress : 7;
ULONG Reserved3 : 1;
ULONG PortNumber : 7;
ULONG Direction : 1;
};
ULONG AsULONG;
} EHCI_FS_ENDPOINT_PARAMS;
C_ASSERT(sizeof(EHCI_FS_ENDPOINT_PARAMS) == sizeof(ULONG));
typedef union _EHCI_MICROFRAME_CONTROL {
struct {
ULONG StartMask : 8;
ULONG CompletionMask : 8;
ULONG Reserved : 16;
};
ULONG AsULONG;
} EHCI_MICROFRAME_CONTROL;
C_ASSERT(sizeof(EHCI_MICROFRAME_CONTROL) == sizeof(ULONG));
typedef union _EHCI_SPLIT_TRANSFER_STATE {
struct {
ULONG Status : 8;
ULONG ProgressMask : 8;
ULONG TotalBytes : 10;
ULONG Reserved : 4;
ULONG PageSelect : 1;
ULONG InterruptOnComplete : 1;
};
ULONG AsULONG;
} EHCI_SPLIT_TRANSFER_STATE;
C_ASSERT(sizeof(EHCI_SPLIT_TRANSFER_STATE) == sizeof(ULONG));
typedef union _EHCI_SPLIT_BUFFER_POINTER {
struct {
ULONG CurrentOffset : 12;
ULONG DataBuffer0 : 20;
};
struct {
ULONG TransactionCount : 3;
ULONG TransactionPosition : 2;
ULONG Reserved : 7;
ULONG DataBuffer1 : 20;
};
ULONG AsULONG;
} EHCI_SPLIT_BUFFER_POINTER;
C_ASSERT(sizeof(EHCI_SPLIT_BUFFER_POINTER) == sizeof(ULONG));
typedef struct _EHCI_SPLIT_ISOCHRONOUS_TD { // must be aligned on a 32-byte boundary
EHCI_LINK_POINTER NextLink;
EHCI_FS_ENDPOINT_PARAMS EndpointCharacteristics;
EHCI_MICROFRAME_CONTROL MicroFrameControl;
EHCI_SPLIT_TRANSFER_STATE TransferState;
EHCI_SPLIT_BUFFER_POINTER Buffer[2];
ULONG BackPointer;
ULONG ExtendedBuffer[2];
} EHCI_SPLIT_ISOCHRONOUS_TD, *PEHCI_SPLIT_ISOCHRONOUS_TD;
C_ASSERT(sizeof(EHCI_SPLIT_ISOCHRONOUS_TD) == 36);
/* Queue Element Transfer Descriptor (qTD) */
#define EHCI_MAX_QTD_BUFFER_PAGES 5
#define EHCI_TOKEN_STATUS_ACTIVE (1 << 7)
#define EHCI_TOKEN_STATUS_HALTED (1 << 6)
#define EHCI_TOKEN_STATUS_DATA_BUFFER_ERROR (1 << 5)
#define EHCI_TOKEN_STATUS_BABBLE_DETECTED (1 << 4)
#define EHCI_TOKEN_STATUS_TRANSACTION_ERROR (1 << 3)
#define EHCI_TOKEN_STATUS_MISSED_MICROFRAME (1 << 2)
#define EHCI_TOKEN_STATUS_SPLIT_STATE (1 << 1)
#define EHCI_TOKEN_STATUS_PING_STATE (1 << 0)
#define EHCI_TD_TOKEN_PID_OUT 0
#define EHCI_TD_TOKEN_PID_IN 1
#define EHCI_TD_TOKEN_PID_SETUP 2
#define EHCI_TD_TOKEN_PID_RESERVED 3
typedef union _EHCI_TD_TOKEN {
struct {
ULONG Status : 8;
ULONG PIDCode : 2;
ULONG ErrorCounter : 2;
ULONG CurrentPage : 3;
ULONG InterruptOnComplete : 1;
ULONG TransferBytes : 15;
ULONG DataToggle : 1;
};
ULONG AsULONG;
} EHCI_TD_TOKEN, *PEHCI_TD_TOKEN;
C_ASSERT(sizeof(EHCI_TD_TOKEN) == sizeof(ULONG));
typedef struct _EHCI_QUEUE_TD { // must be aligned on 32-byte boundaries
ULONG NextTD;
ULONG AlternateNextTD;
EHCI_TD_TOKEN Token;
ULONG Buffer[5];
ULONG ExtendedBuffer[5];
} EHCI_QUEUE_TD, *PEHCI_QUEUE_TD;
C_ASSERT(sizeof(EHCI_QUEUE_TD) == 52);
/* Queue Head */
#define EHCI_QH_EP_FULL_SPEED 0
#define EHCI_QH_EP_LOW_SPEED 1
#define EHCI_QH_EP_HIGH_SPEED 2
typedef union _EHCI_QH_EP_PARAMS {
struct {
ULONG DeviceAddress : 7;
ULONG InactivateOnNextTransaction : 1;
ULONG EndpointNumber : 4;
ULONG EndpointSpeed : 2;
ULONG DataToggleControl : 1;
ULONG HeadReclamationListFlag : 1;
ULONG MaximumPacketLength : 11; // corresponds to the maximum packet size of the associated endpoint (wMaxPacketSize).
ULONG ControlEndpointFlag : 1;
ULONG NakCountReload : 4;
};
ULONG AsULONG;
} EHCI_QH_EP_PARAMS;
C_ASSERT(sizeof(EHCI_QH_EP_PARAMS) == sizeof(ULONG));
typedef union _EHCI_QH_EP_CAPS {
struct {
ULONG InterruptMask : 8;
ULONG SplitCompletionMask : 8;
ULONG HubAddr : 7;
ULONG PortNumber : 7;
ULONG PipeMultiplier : 2;
};
ULONG AsULONG;
} EHCI_QH_EP_CAPS;
C_ASSERT(sizeof(EHCI_QH_EP_CAPS) == sizeof(ULONG));
typedef struct _EHCI_QUEUE_HEAD { // must be aligned on 32-byte boundaries
EHCI_LINK_POINTER HorizontalLink;
EHCI_QH_EP_PARAMS EndpointParams;
EHCI_QH_EP_CAPS EndpointCaps;
ULONG CurrentTD;
ULONG NextTD;
ULONG AlternateNextTD;
EHCI_TD_TOKEN Token;
ULONG Buffer[5];
ULONG ExtendedBuffer[5];
} EHCI_QUEUE_HEAD, *PEHCI_QUEUE_HEAD;
C_ASSERT(sizeof(EHCI_QUEUE_HEAD) == 68);