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