1 #define UHCI_FRAME_LIST_MAX_ENTRIES 1024 // Number of frames in Frame List
2 #define UHCI_NUM_ROOT_HUB_PORTS 2
4 /* UHCI HC I/O Registers offset (PUSHORT) */
5 #define UHCI_USBCMD 0 // USB Command R/W
6 #define UHCI_USBSTS 1 // USB Status R/WC
7 #define UHCI_USBINTR 2 // USB Interrupt Enable R/W
8 #define UHCI_FRNUM 3 // Frame Number R/W WORD writeable only
9 #define UHCI_FRBASEADD 4 // Frame List Base Address R/W // 32 bit
10 #define UHCI_SOFMOD 6 // Start Of Frame Modify R/W // 8 bit
11 #define UHCI_PORTSC1 8 // Port 1 Status/Control R/WC WORD writeable only
12 #define UHCI_PORTSC2 9 // Port 2 Status/Control R/WC WORD writeable only
14 /* PCI Legacy Support */
15 #define PCI_LEGSUP 0xC0 // Legacy Support register offset. R/WC
16 #define PCI_LEGSUP_USBPIRQDEN 0x2000
17 #define PCI_LEGSUP_CLEAR_SMI 0x8F00
19 /* LEGSUP Legacy support register (PCI Configuration - Function 2) */
20 typedef union _UHCI_PCI_LEGSUP
{
22 USHORT Smi60Read
: 1; // (60REN) Trap/SMI On 60h Read Enable. R/W.
23 USHORT Smi60Write
: 1; // (60WEN) Trap/SMI On 60h Write Enable. R/W.
24 USHORT Smi64Read
: 1; // (64REN) Trap/SMI On 64h Read Enable. R/W.
25 USHORT Smi64Write
: 1; // (64WEN) Trap/SMI On 64h Write Enable. R/W.
26 USHORT SmiIrq
: 1; // (USBSMIEN) Trap/SMI ON IRQ Enable. R/W.
27 USHORT A20Gate
: 1; // (A20PTEN) A20Gate Pass Through Enable. R/W.
28 USHORT PassThroughStatus
: 1; // (PSS) Pass Through Status. RO.
29 USHORT SmiEndPassThrough
: 1; // (SMIEPTE) SMI At End Of Pass Through Enable. R/W.
30 USHORT TrapBy60ReadStatus
: 1; // (TBY60R) Trap By 60h Read Status. R/WC.
31 USHORT TrapBy60WriteStatus
: 1; // (TBY60W) Trap By 60h Write Status. R/WC.
32 USHORT TrapBy64ReadStatus
: 1; // (TBY64R) Trap By 64h Read Status. R/WC.
33 USHORT TrapBy64WriteStatus
: 1; // (TBY64W) Trap By 64h Write Status. R/WC.
34 USHORT UsbIrqStatus
: 1; // (USBIRQS) USB IRQ Status. RO.
35 USHORT UsbPIRQ
: 1; // (USBPIRQDEN) USB PIRQ Enable. R/W.
37 USHORT EndA20GateStatus
: 1; // (A20PTS) End OF A20GATE Pass Through Status. R/WC.
42 C_ASSERT(sizeof(UHCI_PCI_LEGSUP
) == sizeof(USHORT
));
44 /* USBCMD Command register */
45 typedef union _UHCI_USB_COMMAND
{
49 USHORT GlobalReset
: 1;
50 USHORT GlobalSuspend
: 1;
51 USHORT GlobalResume
: 1; // Force Global Resume
52 USHORT SoftwareDebug
: 1; // 0 - Normal Mode, 1 - Debug mode
53 USHORT ConfigureFlag
: 1; // no effect on the hardware
54 USHORT MaxPacket
: 1; // 0 = 32, 1 = 64
60 C_ASSERT(sizeof(UHCI_USB_COMMAND
) == sizeof(USHORT
));
62 /* USBSTS Status register */
63 #define UHCI_USB_STATUS_MASK 0x3F
65 typedef union _UHCI_USB_STATUS
{
67 USHORT Interrupt
: 1; // due to IOC (Interrupt On Complete)
68 USHORT ErrorInterrupt
: 1; // due to error
69 USHORT ResumeDetect
: 1;
70 USHORT HostSystemError
: 1; // PCI problems
71 USHORT HcProcessError
: 1; // Schedule is buggy
78 C_ASSERT(sizeof(UHCI_USB_STATUS
) == sizeof(USHORT
));
80 /* USBINTR Interrupt enable register */
81 typedef union _UHCI_INTERRUPT_ENABLE
{
83 USHORT TimeoutCRC
: 1; // Timeout/CRC error enable
84 USHORT ResumeInterrupt
: 1;
85 USHORT InterruptOnComplete
: 1;
86 USHORT ShortPacket
: 1;
90 } UHCI_INTERRUPT_ENABLE
;
92 C_ASSERT(sizeof(UHCI_INTERRUPT_ENABLE
) == sizeof(USHORT
));
94 /* FRNUM Frame Number register */
95 #define UHCI_FRNUM_FRAME_MASK 0x7FF
96 #define UHCI_FRNUM_INDEX_MASK 0x3FF
97 #define UHCI_FRNUM_OVERFLOW_LIST 0x400
99 /* PORTSC(1|2) USB port status and control registers */
100 typedef union _UHCI_PORT_STATUS_CONTROL
{
102 USHORT CurrentConnectStatus
: 1;
103 USHORT ConnectStatusChange
: 1;
104 USHORT PortEnabledDisabled
: 1;
105 USHORT PortEnableDisableChange
: 1;
106 USHORT LineStatus
: 2; // D+ and D-
107 USHORT ResumeDetect
: 1;
108 USHORT Reserved1
: 1; // always 1
109 USHORT LowSpeedDevice
: 1; // LS device Attached
110 USHORT PortReset
: 1;
111 USHORT Reserved2
: 2; // Intel use it (not UHCI 1.1d spec)
113 USHORT Reserved3
: 3; // write zeroes
116 } UHCI_PORT_STATUS_CONTROL
;
118 C_ASSERT(sizeof(UHCI_PORT_STATUS_CONTROL
) == sizeof(USHORT
));
120 typedef struct _UHCI_HW_REGISTERS
{
121 UHCI_USB_COMMAND HcCommand
; // R/W
122 UHCI_USB_STATUS HcStatus
; // R/WC
123 UHCI_INTERRUPT_ENABLE HcInterruptEnable
; // R/W
124 USHORT FrameNumber
; // R/W WORD writeable only
125 ULONG FrameAddress
; // R/W
126 UCHAR SOF_Modify
; // R/W
128 UHCI_PORT_STATUS_CONTROL PortControl
[UHCI_NUM_ROOT_HUB_PORTS
]; // R/WC WORD writeable only
129 } UHCI_HW_REGISTERS
, *PUHCI_HW_REGISTERS
;
131 /* Transfer Descriptor (TD) */
132 #define UHCI_TD_STS_ACTIVE (1 << 7)
133 #define UHCI_TD_STS_STALLED (1 << 6)
134 #define UHCI_TD_STS_DATA_BUFFER_ERROR (1 << 5)
135 #define UHCI_TD_STS_BABBLE_DETECTED (1 << 4)
136 #define UHCI_TD_STS_NAK_RECEIVED (1 << 3)
137 #define UHCI_TD_STS_TIMEOUT_CRC_ERROR (1 << 2)
138 #define UHCI_TD_STS_BITSTUFF_ERROR (1 << 1)
139 //#define UHCI_TD_STS_Reserved (1 << 0)
141 #define UHCI_TD_VALID_LENGTH 0x4FF
142 #define UHCI_TD_LENGTH_INVALID 0x7FE
143 #define UHCI_TD_LENGTH_NULL 0x7FF
145 typedef union _UHCI_CONTROL_STATUS
{
147 ULONG ActualLength
: 11; // encoded as n - 1
149 ULONG Status
: 8; // UHCI_TD_STS_ xxx
150 ULONG InterruptOnComplete
: 1;
151 ULONG IsochronousType
: 1;
152 ULONG LowSpeedDevice
: 1;
153 ULONG ErrorCounter
: 2;
154 ULONG ShortPacketDetect
: 1;
158 } UHCI_CONTROL_STATUS
;
160 C_ASSERT(sizeof(UHCI_CONTROL_STATUS
) == sizeof(ULONG
));
162 #define UHCI_TD_PID_IN 0x69
163 #define UHCI_TD_PID_OUT 0xE1
164 #define UHCI_TD_PID_SETUP 0x2D
166 #define UHCI_TD_PID_DATA0 0
167 #define UHCI_TD_PID_DATA1 1
169 typedef union _UHCI_TD_TOKEN
{
172 ULONG DeviceAddress
: 7;
174 ULONG DataToggle
: 1;
176 ULONG MaximumLength
: 11;
181 C_ASSERT(sizeof(UHCI_TD_TOKEN
) == sizeof(ULONG
));
183 #define UHCI_TD_LINK_PTR_VALID (0 << 0)
184 #define UHCI_TD_LINK_PTR_TERMINATE (1 << 0)
185 #define UHCI_TD_LINK_PTR_TD (0 << 1)
186 #define UHCI_TD_LINK_PTR_QH (1 << 1)
187 #define UHCI_TD_LINK_PTR_BREADTH_FIRST (0 << 2)
188 #define UHCI_TD_LINK_PTR_DEPTH_FIRST (1 << 2)
189 #define UHCI_TD_LINK_POINTER_MASK 0xFFFFFFF0
191 typedef struct _UHCI_TD
{ // Transfer Descriptors always aligned on 16-byte boundaries
193 UHCI_CONTROL_STATUS ControlStatus
;
196 } UHCI_TD
, *PUHCI_TD
;
198 C_ASSERT(sizeof(UHCI_TD
) == 16);
200 /* Queue Header (QH) */
201 #define UHCI_QH_HEAD_LINK_PTR_VALID (0 << 0)
202 #define UHCI_QH_HEAD_LINK_PTR_TERMINATE (1 << 0)
203 #define UHCI_QH_HEAD_LINK_PTR_TD (0 << 1)
204 #define UHCI_QH_HEAD_LINK_PTR_QH (1 << 1)
205 #define UHCI_QH_HEAD_LINK_POINTER_MASK 0xFFFFFFF0
207 #define UHCI_QH_ELEMENT_LINK_PTR_VALID (0 << 0)
208 #define UHCI_QH_ELEMENT_LINK_PTR_TERMINATE (1 << 0)
209 #define UHCI_QH_ELEMENT_LINK_PTR_TD (0 << 1)
210 #define UHCI_QH_ELEMENT_LINK_PTR_QH (1 << 1)
211 #define UHCI_QH_ELEMENT_LINK_POINTER_MASK 0xFFFFFFF0
213 typedef struct _UHCI_QH
{ // Queue Heads must be aligned on a 16-byte boundary
216 } UHCI_QH
, *PUHCI_QH
;
218 C_ASSERT(sizeof(UHCI_QH
) == 8);