Import EhciDxe and UhciDxe into MdeModulePkg.
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / UhciDxe / UhciReg.c
1 /** @file
2
3 Copyright (c) 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 UhciReg.c
15
16 Abstract:
17
18 The UHCI register operation routines.
19
20 Revision History
21
22
23 **/
24
25 #include "Uhci.h"
26
27
28 /**
29 Read a UHCI register
30
31 @param PciIo The EFI_PCI_IO_PROTOCOL to use
32 @param Offset Register offset to USB_BAR_INDEX
33
34 @return Content of register
35
36 **/
37 UINT16
38 UhciReadReg (
39 IN EFI_PCI_IO_PROTOCOL *PciIo,
40 IN UINT32 Offset
41 )
42 {
43 UINT16 Data;
44 EFI_STATUS Status;
45
46 Status = PciIo->Io.Read (
47 PciIo,
48 EfiPciIoWidthUint16,
49 USB_BAR_INDEX,
50 Offset,
51 1,
52 &Data
53 );
54
55 if (EFI_ERROR (Status)) {
56 UHCI_ERROR (("UhciReadReg: PciIo Io.Read error: %r at offset %d\n", Status, Offset));
57
58 Data = 0xFFFF;
59 }
60
61 return Data;
62 }
63
64
65 /**
66 Write data to UHCI register
67
68 @param PciIo The EFI_PCI_IO_PROTOCOL to use
69 @param Offset Register offset to USB_BAR_INDEX
70 @param Data Data to write
71
72 @return VOID
73
74 **/
75 VOID
76 UhciWriteReg (
77 IN EFI_PCI_IO_PROTOCOL *PciIo,
78 IN UINT32 Offset,
79 IN UINT16 Data
80 )
81 {
82 EFI_STATUS Status;
83
84 Status = PciIo->Io.Write (
85 PciIo,
86 EfiPciIoWidthUint16,
87 USB_BAR_INDEX,
88 Offset,
89 1,
90 &Data
91 );
92
93 if (EFI_ERROR (Status)) {
94 UHCI_ERROR (("UhciWriteReg: PciIo Io.Write error: %r at offset %d\n", Status, Offset));
95 }
96 }
97
98
99 /**
100 Set a bit of the UHCI Register
101
102 @param PciIo The EFI_PCI_IO_PROTOCOL to use
103 @param Offset Register offset to USB_BAR_INDEX
104 @param Bit The bit to set
105
106 @return None
107
108 **/
109 VOID
110 UhciSetRegBit (
111 IN EFI_PCI_IO_PROTOCOL *PciIo,
112 IN UINT32 Offset,
113 IN UINT16 Bit
114 )
115 {
116 UINT16 Data;
117
118 Data = UhciReadReg (PciIo, Offset);
119 Data |= Bit;
120 UhciWriteReg (PciIo, Offset, Data);
121 }
122
123
124 /**
125 Clear a bit of the UHCI Register
126
127 @param PciIo The PCI_IO protocol to access the PCI
128 @param Offset Register offset to USB_BAR_INDEX
129 @param Bit The bit to clear
130
131 @return None
132
133 **/
134 VOID
135 UhciClearRegBit (
136 IN EFI_PCI_IO_PROTOCOL *PciIo,
137 IN UINT32 Offset,
138 IN UINT16 Bit
139 )
140 {
141 UINT16 Data;
142
143 Data = UhciReadReg (PciIo, Offset);
144 Data &= ~Bit;
145 UhciWriteReg (PciIo, Offset, Data);
146 }
147
148
149 /**
150 Clear all the interrutp status bits, these bits
151 are Write-Clean
152
153 @param Uhc The UHCI device
154
155 @return None
156
157 **/
158 VOID
159 UhciAckAllInterrupt (
160 IN USB_HC_DEV *Uhc
161 )
162 {
163 UhciWriteReg (Uhc->PciIo, USBSTS_OFFSET, 0x3F);
164
165 //
166 // If current HC is halted, re-enable it. Host Controller Process Error
167 // is a temporary error status.
168 //
169 if (!UhciIsHcWorking (Uhc->PciIo)) {
170 UHCI_ERROR (("UhciAckAllInterrupt: re-enable the UHCI from system error\n"));
171 Uhc->UsbHc.SetState (&Uhc->UsbHc, EfiUsbHcStateOperational);
172 }
173 }
174
175
176
177 /**
178 Stop the host controller
179
180 @param Uhc The UHCI device
181 @param Timeout Max time allowed
182
183 @retval EFI_SUCCESS The host controller is stopped
184 @retval EFI_TIMEOUT Failed to stop the host controller
185
186 **/
187 EFI_STATUS
188 UhciStopHc (
189 IN USB_HC_DEV *Uhc,
190 IN UINTN Timeout
191 )
192 {
193 UINT16 UsbSts;
194 UINTN Index;
195
196 UhciClearRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_RS);
197
198 //
199 // ensure the HC is in halt status after send the stop command
200 // Timeout is in us unit.
201 //
202 for (Index = 0; Index < (Timeout / 50) + 1; Index++) {
203 UsbSts = UhciReadReg (Uhc->PciIo, USBSTS_OFFSET);
204
205 if ((UsbSts & USBSTS_HCH) == USBSTS_HCH) {
206 return EFI_SUCCESS;
207 }
208
209 gBS->Stall (50);
210 }
211
212 return EFI_TIMEOUT;
213 }
214
215
216 /**
217 Check whether the host controller operates well
218
219 @param PciIo The PCI_IO protocol to use
220
221 @retval TRUE Host controller is working
222 @retval FALSE Host controller is halted or system error
223
224 **/
225 BOOLEAN
226 UhciIsHcWorking (
227 IN EFI_PCI_IO_PROTOCOL *PciIo
228 )
229 {
230 UINT16 UsbSts;
231
232 UsbSts = UhciReadReg (PciIo, USBSTS_OFFSET);
233
234 if (UsbSts & (USBSTS_HCPE | USBSTS_HSE | USBSTS_HCH)) {
235 UHCI_ERROR (("UhciIsHcWorking: current USB state is %x\n", UsbSts));
236 return FALSE;
237 }
238
239 return TRUE;
240 }
241
242
243 /**
244 Set the UHCI frame list base address. It can't use
245 UhciWriteReg which access memory in UINT16.
246
247 @param PciIo The EFI_PCI_IO_PROTOCOL to use
248 @param Addr Address to set
249
250 @return VOID
251
252 **/
253 VOID
254 UhciSetFrameListBaseAddr (
255 IN EFI_PCI_IO_PROTOCOL *PciIo,
256 IN VOID *Addr
257 )
258 {
259 EFI_STATUS Status;
260 UINT32 Data;
261
262 Data = (UINT32) ((UINTN) Addr & 0xFFFFF000);
263
264 Status = PciIo->Io.Write (
265 PciIo,
266 EfiPciIoWidthUint32,
267 USB_BAR_INDEX,
268 (UINT64) USB_FRAME_BASE_OFFSET,
269 1,
270 &Data
271 );
272
273 if (EFI_ERROR (Status)) {
274 UHCI_ERROR (("UhciSetFrameListBaseAddr: PciIo Io.Write error: %r\n", Status));
275 }
276 }
277
278
279 /**
280 Disable USB Emulation
281
282 @param PciIo The EFI_PCI_IO_PROTOCOL protocol to use
283
284 @return VOID
285
286 **/
287 VOID
288 UhciTurnOffUsbEmulation (
289 IN EFI_PCI_IO_PROTOCOL *PciIo
290 )
291 {
292 UINT16 Command;
293
294 Command = 0;
295
296 PciIo->Pci.Write (
297 PciIo,
298 EfiPciIoWidthUint16,
299 USB_EMULATION_OFFSET,
300 1,
301 &Command
302 );
303 }