1 /* 2 * PROJECT: ReactOS USB UHCI Miniport Driver 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: USBUHCI hardware declarations 5 * COPYRIGHT: Copyright 2017-2018 Vadim Galyant <vgal@rambler.ru> 6 */ 7 8 #define UHCI_FRAME_LIST_MAX_ENTRIES 1024 // Number of frames in Frame List 9 #define UHCI_NUM_ROOT_HUB_PORTS 2 10 11 /* UHCI HC I/O Registers offset (PUSHORT) */ 12 #define UHCI_USBCMD 0 // USB Command R/W 13 #define UHCI_USBSTS 1 // USB Status R/WC 14 #define UHCI_USBINTR 2 // USB Interrupt Enable R/W 15 #define UHCI_FRNUM 3 // Frame Number R/W WORD writeable only 16 #define UHCI_FRBASEADD 4 // Frame List Base Address R/W // 32 bit 17 #define UHCI_SOFMOD 6 // Start Of Frame Modify R/W // 8 bit 18 #define UHCI_PORTSC1 8 // Port 1 Status/Control R/WC WORD writeable only 19 #define UHCI_PORTSC2 9 // Port 2 Status/Control R/WC WORD writeable only 20 21 /* PCI Legacy Support */ 22 #define PCI_LEGSUP 0xC0 // Legacy Support register offset. R/WC 23 #define PCI_LEGSUP_USBPIRQDEN 0x2000 24 #define PCI_LEGSUP_CLEAR_SMI 0x8F00 25 26 /* LEGSUP Legacy support register (PCI Configuration - Function 2) */ 27 typedef union _UHCI_PCI_LEGSUP { 28 struct { 29 USHORT Smi60Read : 1; // (60REN) Trap/SMI On 60h Read Enable. R/W. 30 USHORT Smi60Write : 1; // (60WEN) Trap/SMI On 60h Write Enable. R/W. 31 USHORT Smi64Read : 1; // (64REN) Trap/SMI On 64h Read Enable. R/W. 32 USHORT Smi64Write : 1; // (64WEN) Trap/SMI On 64h Write Enable. R/W. 33 USHORT SmiIrq : 1; // (USBSMIEN) Trap/SMI ON IRQ Enable. R/W. 34 USHORT A20Gate : 1; // (A20PTEN) A20Gate Pass Through Enable. R/W. 35 USHORT PassThroughStatus : 1; // (PSS) Pass Through Status. RO. 36 USHORT SmiEndPassThrough : 1; // (SMIEPTE) SMI At End Of Pass Through Enable. R/W. 37 USHORT TrapBy60ReadStatus : 1; // (TBY60R) Trap By 60h Read Status. R/WC. 38 USHORT TrapBy60WriteStatus : 1; // (TBY60W) Trap By 60h Write Status. R/WC. 39 USHORT TrapBy64ReadStatus : 1; // (TBY64R) Trap By 64h Read Status. R/WC. 40 USHORT TrapBy64WriteStatus : 1; // (TBY64W) Trap By 64h Write Status. R/WC. 41 USHORT UsbIrqStatus : 1; // (USBIRQS) USB IRQ Status. RO. 42 USHORT UsbPIRQ : 1; // (USBPIRQDEN) USB PIRQ Enable. R/W. 43 USHORT Reserved : 1; 44 USHORT EndA20GateStatus : 1; // (A20PTS) End OF A20GATE Pass Through Status. R/WC. 45 }; 46 USHORT AsUSHORT; 47 } UHCI_PCI_LEGSUP; 48 49 C_ASSERT(sizeof(UHCI_PCI_LEGSUP) == sizeof(USHORT)); 50 51 /* USBCMD Command register */ 52 typedef union _UHCI_USB_COMMAND { 53 struct { 54 USHORT Run : 1; 55 USHORT HcReset : 1; 56 USHORT GlobalReset : 1; 57 USHORT GlobalSuspend : 1; 58 USHORT GlobalResume : 1; // Force Global Resume 59 USHORT SoftwareDebug : 1; // 0 - Normal Mode, 1 - Debug mode 60 USHORT ConfigureFlag : 1; // no effect on the hardware 61 USHORT MaxPacket : 1; // 0 = 32, 1 = 64 62 USHORT Reserved : 8; 63 }; 64 USHORT AsUSHORT; 65 } UHCI_USB_COMMAND; 66 67 C_ASSERT(sizeof(UHCI_USB_COMMAND) == sizeof(USHORT)); 68 69 /* USBSTS Status register */ 70 #define UHCI_USB_STATUS_MASK 0x3F 71 72 typedef union _UHCI_USB_STATUS { 73 struct { 74 USHORT Interrupt : 1; // due to IOC (Interrupt On Complete) 75 USHORT ErrorInterrupt : 1; // due to error 76 USHORT ResumeDetect : 1; 77 USHORT HostSystemError : 1; // PCI problems 78 USHORT HcProcessError : 1; // Schedule is buggy 79 USHORT HcHalted : 1; 80 USHORT Reserved : 10; 81 }; 82 USHORT AsUSHORT; 83 } UHCI_USB_STATUS; 84 85 C_ASSERT(sizeof(UHCI_USB_STATUS) == sizeof(USHORT)); 86 87 /* USBINTR Interrupt enable register */ 88 typedef union _UHCI_INTERRUPT_ENABLE { 89 struct { 90 USHORT TimeoutCRC : 1; // Timeout/CRC error enable 91 USHORT ResumeInterrupt : 1; 92 USHORT InterruptOnComplete : 1; 93 USHORT ShortPacket : 1; 94 USHORT Reserved : 12; 95 }; 96 USHORT AsUSHORT; 97 } UHCI_INTERRUPT_ENABLE; 98 99 C_ASSERT(sizeof(UHCI_INTERRUPT_ENABLE) == sizeof(USHORT)); 100 101 /* FRNUM Frame Number register */ 102 #define UHCI_FRNUM_FRAME_MASK 0x7FF 103 #define UHCI_FRNUM_INDEX_MASK 0x3FF 104 #define UHCI_FRNUM_OVERFLOW_LIST 0x400 105 106 /* PORTSC(1|2) USB port status and control registers */ 107 typedef union _UHCI_PORT_STATUS_CONTROL { 108 struct { 109 USHORT CurrentConnectStatus : 1; 110 USHORT ConnectStatusChange : 1; 111 USHORT PortEnabledDisabled : 1; 112 USHORT PortEnableDisableChange : 1; 113 USHORT LineStatus : 2; // D+ and D- 114 USHORT ResumeDetect : 1; 115 USHORT Reserved1 : 1; // always 1 116 USHORT LowSpeedDevice : 1; // LS device Attached 117 USHORT PortReset : 1; 118 USHORT Reserved2 : 2; // Intel use it (not UHCI 1.1d spec) 119 USHORT Suspend : 1; 120 USHORT Reserved3 : 3; // write zeroes 121 }; 122 USHORT AsUSHORT; 123 } UHCI_PORT_STATUS_CONTROL; 124 125 C_ASSERT(sizeof(UHCI_PORT_STATUS_CONTROL) == sizeof(USHORT)); 126 127 typedef struct _UHCI_HW_REGISTERS { 128 UHCI_USB_COMMAND HcCommand; // R/W 129 UHCI_USB_STATUS HcStatus; // R/WC 130 UHCI_INTERRUPT_ENABLE HcInterruptEnable; // R/W 131 USHORT FrameNumber; // R/W WORD writeable only 132 ULONG FrameAddress; // R/W 133 UCHAR SOF_Modify; // R/W 134 UCHAR Reserved[3]; 135 UHCI_PORT_STATUS_CONTROL PortControl[UHCI_NUM_ROOT_HUB_PORTS]; // R/WC WORD writeable only 136 } UHCI_HW_REGISTERS, *PUHCI_HW_REGISTERS; 137 138 /* Transfer Descriptor (TD) */ 139 #define UHCI_TD_STS_ACTIVE (1 << 7) 140 #define UHCI_TD_STS_STALLED (1 << 6) 141 #define UHCI_TD_STS_DATA_BUFFER_ERROR (1 << 5) 142 #define UHCI_TD_STS_BABBLE_DETECTED (1 << 4) 143 #define UHCI_TD_STS_NAK_RECEIVED (1 << 3) 144 #define UHCI_TD_STS_TIMEOUT_CRC_ERROR (1 << 2) 145 #define UHCI_TD_STS_BITSTUFF_ERROR (1 << 1) 146 //#define UHCI_TD_STS_Reserved (1 << 0) 147 148 #define UHCI_TD_VALID_LENGTH 0x4FF 149 #define UHCI_TD_LENGTH_INVALID 0x7FE 150 #define UHCI_TD_LENGTH_NULL 0x7FF 151 152 typedef union _UHCI_CONTROL_STATUS { 153 struct { 154 ULONG ActualLength : 11; // encoded as n - 1 155 ULONG Reserved1 : 5; 156 ULONG Status : 8; // UHCI_TD_STS_ xxx 157 ULONG InterruptOnComplete : 1; 158 ULONG IsochronousType : 1; 159 ULONG LowSpeedDevice : 1; 160 ULONG ErrorCounter : 2; 161 ULONG ShortPacketDetect : 1; 162 ULONG Reserved2 : 2; 163 }; 164 ULONG AsULONG; 165 } UHCI_CONTROL_STATUS; 166 167 C_ASSERT(sizeof(UHCI_CONTROL_STATUS) == sizeof(ULONG)); 168 169 #define UHCI_TD_PID_IN 0x69 170 #define UHCI_TD_PID_OUT 0xE1 171 #define UHCI_TD_PID_SETUP 0x2D 172 173 #define UHCI_TD_PID_DATA0 0 174 #define UHCI_TD_PID_DATA1 1 175 176 typedef union _UHCI_TD_TOKEN { 177 struct { 178 ULONG PIDCode : 8; 179 ULONG DeviceAddress : 7; 180 ULONG Endpoint : 4; 181 ULONG DataToggle : 1; 182 ULONG Reserved : 1; 183 ULONG MaximumLength : 11; 184 }; 185 ULONG AsULONG; 186 } UHCI_TD_TOKEN; 187 188 C_ASSERT(sizeof(UHCI_TD_TOKEN) == sizeof(ULONG)); 189 190 #define UHCI_TD_LINK_PTR_VALID (0 << 0) 191 #define UHCI_TD_LINK_PTR_TERMINATE (1 << 0) 192 #define UHCI_TD_LINK_PTR_TD (0 << 1) 193 #define UHCI_TD_LINK_PTR_QH (1 << 1) 194 #define UHCI_TD_LINK_PTR_BREADTH_FIRST (0 << 2) 195 #define UHCI_TD_LINK_PTR_DEPTH_FIRST (1 << 2) 196 #define UHCI_TD_LINK_POINTER_MASK 0xFFFFFFF0 197 198 typedef struct _UHCI_TD { // Transfer Descriptors always aligned on 16-byte boundaries 199 ULONG NextElement; 200 UHCI_CONTROL_STATUS ControlStatus; 201 UHCI_TD_TOKEN Token; 202 ULONG Buffer; 203 } UHCI_TD, *PUHCI_TD; 204 205 C_ASSERT(sizeof(UHCI_TD) == 16); 206 207 /* Queue Header (QH) */ 208 #define UHCI_QH_HEAD_LINK_PTR_VALID (0 << 0) 209 #define UHCI_QH_HEAD_LINK_PTR_TERMINATE (1 << 0) 210 #define UHCI_QH_HEAD_LINK_PTR_TD (0 << 1) 211 #define UHCI_QH_HEAD_LINK_PTR_QH (1 << 1) 212 #define UHCI_QH_HEAD_LINK_POINTER_MASK 0xFFFFFFF0 213 214 #define UHCI_QH_ELEMENT_LINK_PTR_VALID (0 << 0) 215 #define UHCI_QH_ELEMENT_LINK_PTR_TERMINATE (1 << 0) 216 #define UHCI_QH_ELEMENT_LINK_PTR_TD (0 << 1) 217 #define UHCI_QH_ELEMENT_LINK_PTR_QH (1 << 1) 218 #define UHCI_QH_ELEMENT_LINK_POINTER_MASK 0xFFFFFFF0 219 220 typedef struct _UHCI_QH { // Queue Heads must be aligned on a 16-byte boundary 221 ULONG NextQH; 222 ULONG NextElement; 223 } UHCI_QH, *PUHCI_QH; 224 225 C_ASSERT(sizeof(UHCI_QH) == 8); 226