/* * PROJECT: ReactOS USB UHCI Miniport Driver * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) * PURPOSE: USBUHCI hardware declarations * COPYRIGHT: Copyright 2017-2018 Vadim Galyant */ #define UHCI_FRAME_LIST_MAX_ENTRIES 1024 // Number of frames in Frame List #define UHCI_NUM_ROOT_HUB_PORTS 2 /* UHCI HC I/O Registers offset (PUSHORT) */ #define UHCI_USBCMD 0 // USB Command R/W #define UHCI_USBSTS 1 // USB Status R/WC #define UHCI_USBINTR 2 // USB Interrupt Enable R/W #define UHCI_FRNUM 3 // Frame Number R/W WORD writeable only #define UHCI_FRBASEADD 4 // Frame List Base Address R/W // 32 bit #define UHCI_SOFMOD 6 // Start Of Frame Modify R/W // 8 bit #define UHCI_PORTSC1 8 // Port 1 Status/Control R/WC WORD writeable only #define UHCI_PORTSC2 9 // Port 2 Status/Control R/WC WORD writeable only /* PCI Legacy Support */ #define PCI_LEGSUP 0xC0 // Legacy Support register offset. R/WC #define PCI_LEGSUP_USBPIRQDEN 0x2000 #define PCI_LEGSUP_CLEAR_SMI 0x8F00 /* LEGSUP Legacy support register (PCI Configuration - Function 2) */ typedef union _UHCI_PCI_LEGSUP { struct { USHORT Smi60Read : 1; // (60REN) Trap/SMI On 60h Read Enable. R/W. USHORT Smi60Write : 1; // (60WEN) Trap/SMI On 60h Write Enable. R/W. USHORT Smi64Read : 1; // (64REN) Trap/SMI On 64h Read Enable. R/W. USHORT Smi64Write : 1; // (64WEN) Trap/SMI On 64h Write Enable. R/W. USHORT SmiIrq : 1; // (USBSMIEN) Trap/SMI ON IRQ Enable. R/W. USHORT A20Gate : 1; // (A20PTEN) A20Gate Pass Through Enable. R/W. USHORT PassThroughStatus : 1; // (PSS) Pass Through Status. RO. USHORT SmiEndPassThrough : 1; // (SMIEPTE) SMI At End Of Pass Through Enable. R/W. USHORT TrapBy60ReadStatus : 1; // (TBY60R) Trap By 60h Read Status. R/WC. USHORT TrapBy60WriteStatus : 1; // (TBY60W) Trap By 60h Write Status. R/WC. USHORT TrapBy64ReadStatus : 1; // (TBY64R) Trap By 64h Read Status. R/WC. USHORT TrapBy64WriteStatus : 1; // (TBY64W) Trap By 64h Write Status. R/WC. USHORT UsbIrqStatus : 1; // (USBIRQS) USB IRQ Status. RO. USHORT UsbPIRQ : 1; // (USBPIRQDEN) USB PIRQ Enable. R/W. USHORT Reserved : 1; USHORT EndA20GateStatus : 1; // (A20PTS) End OF A20GATE Pass Through Status. R/WC. }; USHORT AsUSHORT; } UHCI_PCI_LEGSUP; C_ASSERT(sizeof(UHCI_PCI_LEGSUP) == sizeof(USHORT)); /* USBCMD Command register */ typedef union _UHCI_USB_COMMAND { struct { USHORT Run : 1; USHORT HcReset : 1; USHORT GlobalReset : 1; USHORT GlobalSuspend : 1; USHORT GlobalResume : 1; // Force Global Resume USHORT SoftwareDebug : 1; // 0 - Normal Mode, 1 - Debug mode USHORT ConfigureFlag : 1; // no effect on the hardware USHORT MaxPacket : 1; // 0 = 32, 1 = 64 USHORT Reserved : 8; }; USHORT AsUSHORT; } UHCI_USB_COMMAND; C_ASSERT(sizeof(UHCI_USB_COMMAND) == sizeof(USHORT)); /* USBSTS Status register */ #define UHCI_USB_STATUS_MASK 0x3F typedef union _UHCI_USB_STATUS { struct { USHORT Interrupt : 1; // due to IOC (Interrupt On Complete) USHORT ErrorInterrupt : 1; // due to error USHORT ResumeDetect : 1; USHORT HostSystemError : 1; // PCI problems USHORT HcProcessError : 1; // Schedule is buggy USHORT HcHalted : 1; USHORT Reserved : 10; }; USHORT AsUSHORT; } UHCI_USB_STATUS; C_ASSERT(sizeof(UHCI_USB_STATUS) == sizeof(USHORT)); /* USBINTR Interrupt enable register */ typedef union _UHCI_INTERRUPT_ENABLE { struct { USHORT TimeoutCRC : 1; // Timeout/CRC error enable USHORT ResumeInterrupt : 1; USHORT InterruptOnComplete : 1; USHORT ShortPacket : 1; USHORT Reserved : 12; }; USHORT AsUSHORT; } UHCI_INTERRUPT_ENABLE; C_ASSERT(sizeof(UHCI_INTERRUPT_ENABLE) == sizeof(USHORT)); /* FRNUM Frame Number register */ #define UHCI_FRNUM_FRAME_MASK 0x7FF #define UHCI_FRNUM_INDEX_MASK 0x3FF #define UHCI_FRNUM_OVERFLOW_LIST 0x400 /* PORTSC(1|2) USB port status and control registers */ typedef union _UHCI_PORT_STATUS_CONTROL { struct { USHORT CurrentConnectStatus : 1; USHORT ConnectStatusChange : 1; USHORT PortEnabledDisabled : 1; USHORT PortEnableDisableChange : 1; USHORT LineStatus : 2; // D+ and D- USHORT ResumeDetect : 1; USHORT Reserved1 : 1; // always 1 USHORT LowSpeedDevice : 1; // LS device Attached USHORT PortReset : 1; USHORT Reserved2 : 2; // Intel use it (not UHCI 1.1d spec) USHORT Suspend : 1; USHORT Reserved3 : 3; // write zeroes }; USHORT AsUSHORT; } UHCI_PORT_STATUS_CONTROL; C_ASSERT(sizeof(UHCI_PORT_STATUS_CONTROL) == sizeof(USHORT)); typedef struct _UHCI_HW_REGISTERS { UHCI_USB_COMMAND HcCommand; // R/W UHCI_USB_STATUS HcStatus; // R/WC UHCI_INTERRUPT_ENABLE HcInterruptEnable; // R/W USHORT FrameNumber; // R/W WORD writeable only ULONG FrameAddress; // R/W UCHAR SOF_Modify; // R/W UCHAR Reserved[3]; UHCI_PORT_STATUS_CONTROL PortControl[UHCI_NUM_ROOT_HUB_PORTS]; // R/WC WORD writeable only } UHCI_HW_REGISTERS, *PUHCI_HW_REGISTERS; /* Transfer Descriptor (TD) */ #define UHCI_TD_STS_ACTIVE (1 << 7) #define UHCI_TD_STS_STALLED (1 << 6) #define UHCI_TD_STS_DATA_BUFFER_ERROR (1 << 5) #define UHCI_TD_STS_BABBLE_DETECTED (1 << 4) #define UHCI_TD_STS_NAK_RECEIVED (1 << 3) #define UHCI_TD_STS_TIMEOUT_CRC_ERROR (1 << 2) #define UHCI_TD_STS_BITSTUFF_ERROR (1 << 1) //#define UHCI_TD_STS_Reserved (1 << 0) #define UHCI_TD_VALID_LENGTH 0x4FF #define UHCI_TD_LENGTH_INVALID 0x7FE #define UHCI_TD_LENGTH_NULL 0x7FF typedef union _UHCI_CONTROL_STATUS { struct { ULONG ActualLength : 11; // encoded as n - 1 ULONG Reserved1 : 5; ULONG Status : 8; // UHCI_TD_STS_ xxx ULONG InterruptOnComplete : 1; ULONG IsochronousType : 1; ULONG LowSpeedDevice : 1; ULONG ErrorCounter : 2; ULONG ShortPacketDetect : 1; ULONG Reserved2 : 2; }; ULONG AsULONG; } UHCI_CONTROL_STATUS; C_ASSERT(sizeof(UHCI_CONTROL_STATUS) == sizeof(ULONG)); #define UHCI_TD_PID_IN 0x69 #define UHCI_TD_PID_OUT 0xE1 #define UHCI_TD_PID_SETUP 0x2D #define UHCI_TD_PID_DATA0 0 #define UHCI_TD_PID_DATA1 1 typedef union _UHCI_TD_TOKEN { struct { ULONG PIDCode : 8; ULONG DeviceAddress : 7; ULONG Endpoint : 4; ULONG DataToggle : 1; ULONG Reserved : 1; ULONG MaximumLength : 11; }; ULONG AsULONG; } UHCI_TD_TOKEN; C_ASSERT(sizeof(UHCI_TD_TOKEN) == sizeof(ULONG)); #define UHCI_TD_LINK_PTR_VALID (0 << 0) #define UHCI_TD_LINK_PTR_TERMINATE (1 << 0) #define UHCI_TD_LINK_PTR_TD (0 << 1) #define UHCI_TD_LINK_PTR_QH (1 << 1) #define UHCI_TD_LINK_PTR_BREADTH_FIRST (0 << 2) #define UHCI_TD_LINK_PTR_DEPTH_FIRST (1 << 2) #define UHCI_TD_LINK_POINTER_MASK 0xFFFFFFF0 typedef struct _UHCI_TD { // Transfer Descriptors always aligned on 16-byte boundaries ULONG NextElement; UHCI_CONTROL_STATUS ControlStatus; UHCI_TD_TOKEN Token; ULONG Buffer; } UHCI_TD, *PUHCI_TD; C_ASSERT(sizeof(UHCI_TD) == 16); /* Queue Header (QH) */ #define UHCI_QH_HEAD_LINK_PTR_VALID (0 << 0) #define UHCI_QH_HEAD_LINK_PTR_TERMINATE (1 << 0) #define UHCI_QH_HEAD_LINK_PTR_TD (0 << 1) #define UHCI_QH_HEAD_LINK_PTR_QH (1 << 1) #define UHCI_QH_HEAD_LINK_POINTER_MASK 0xFFFFFFF0 #define UHCI_QH_ELEMENT_LINK_PTR_VALID (0 << 0) #define UHCI_QH_ELEMENT_LINK_PTR_TERMINATE (1 << 0) #define UHCI_QH_ELEMENT_LINK_PTR_TD (0 << 1) #define UHCI_QH_ELEMENT_LINK_PTR_QH (1 << 1) #define UHCI_QH_ELEMENT_LINK_POINTER_MASK 0xFFFFFFF0 typedef struct _UHCI_QH { // Queue Heads must be aligned on a 16-byte boundary ULONG NextQH; ULONG NextElement; } UHCI_QH, *PUHCI_QH; C_ASSERT(sizeof(UHCI_QH) == 8);