--- /dev/null
+/*
+ * 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);