xref: /reactos/drivers/usb/usbuhci/hardware.h (revision 34593d93)
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