]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Bus/Pci/UhciDxe/Uhci.c
Roll back the change in Partition driver. currently we enhance the EHCI driver to...
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / UhciDxe / Uhci.c
... / ...
CommitLineData
1/** @file\r
2\r
3 The UHCI driver model and HC protocol routines.\r
4\r
5Copyright (c) 2004 - 2009, Intel Corporation\r
6All rights reserved. This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "Uhci.h"\r
17\r
18\r
19EFI_DRIVER_BINDING_PROTOCOL gUhciDriverBinding = {\r
20 UhciDriverBindingSupported,\r
21 UhciDriverBindingStart,\r
22 UhciDriverBindingStop,\r
23 0x20,\r
24 NULL,\r
25 NULL\r
26};\r
27\r
28/**\r
29 Provides software reset for the USB host controller according to UEFI 2.0 spec.\r
30\r
31 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
32 @param Attributes A bit mask of the reset operation to perform. See\r
33 below for a list of the supported bit mask values.\r
34\r
35 @return EFI_SUCCESS The reset operation succeeded.\r
36 @return EFI_INVALID_PARAMETER Attributes is not valid.\r
37 @return EFI_UNSUPPORTED This type of reset is not currently supported.\r
38 @return EFI_DEVICE_ERROR Other errors.\r
39\r
40**/\r
41EFI_STATUS\r
42EFIAPI\r
43Uhci2Reset (\r
44 IN EFI_USB2_HC_PROTOCOL *This,\r
45 IN UINT16 Attributes\r
46 )\r
47{\r
48 USB_HC_DEV *Uhc;\r
49 EFI_TPL OldTpl;\r
50\r
51 if ((Attributes == EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG) ||\r
52 (Attributes == EFI_USB_HC_RESET_HOST_WITH_DEBUG)) {\r
53 return EFI_UNSUPPORTED;\r
54 }\r
55\r
56 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
57\r
58 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
59\r
60 switch (Attributes) {\r
61 case EFI_USB_HC_RESET_GLOBAL:\r
62 //\r
63 // Stop schedule and set the Global Reset bit in the command register\r
64 //\r
65 UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT);\r
66 UhciSetRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_GRESET);\r
67\r
68 gBS->Stall (UHC_ROOT_PORT_RESET_STALL);\r
69\r
70 //\r
71 // Clear the Global Reset bit to zero.\r
72 //\r
73 UhciClearRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_GRESET);\r
74\r
75 gBS->Stall (UHC_ROOT_PORT_RECOVERY_STALL);\r
76 break;\r
77\r
78 case EFI_USB_HC_RESET_HOST_CONTROLLER:\r
79 //\r
80 // Stop schedule and set Host Controller Reset bit to 1\r
81 //\r
82 UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT);\r
83 UhciSetRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_HCRESET);\r
84\r
85 gBS->Stall (UHC_ROOT_PORT_RECOVERY_STALL);\r
86 break;\r
87\r
88 default:\r
89 goto ON_INVAILD_PARAMETER;\r
90 }\r
91\r
92 //\r
93 // Delete all old transactions on the USB bus, then\r
94 // reinitialize the frame list\r
95 //\r
96 UhciFreeAllAsyncReq (Uhc);\r
97 UhciDestoryFrameList (Uhc);\r
98 UhciInitFrameList (Uhc);\r
99\r
100 gBS->RestoreTPL (OldTpl);\r
101\r
102 return EFI_SUCCESS;\r
103\r
104ON_INVAILD_PARAMETER:\r
105\r
106 gBS->RestoreTPL (OldTpl);\r
107\r
108 return EFI_INVALID_PARAMETER;\r
109}\r
110\r
111\r
112/**\r
113 Retrieves current state of the USB host controller according to UEFI 2.0 spec.\r
114\r
115 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
116 @param State Variable to receive current device state.\r
117\r
118 @return EFI_SUCCESS The state is returned.\r
119 @return EFI_INVALID_PARAMETER State is not valid.\r
120 @return EFI_DEVICE_ERROR Other errors.\r
121\r
122**/\r
123EFI_STATUS\r
124EFIAPI\r
125Uhci2GetState (\r
126 IN CONST EFI_USB2_HC_PROTOCOL *This,\r
127 OUT EFI_USB_HC_STATE *State\r
128 )\r
129{\r
130 USB_HC_DEV *Uhc;\r
131 UINT16 UsbSts;\r
132 UINT16 UsbCmd;\r
133\r
134 if (State == NULL) {\r
135 return EFI_INVALID_PARAMETER;\r
136 }\r
137\r
138 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
139\r
140 UsbCmd = UhciReadReg (Uhc->PciIo, USBCMD_OFFSET);\r
141 UsbSts = UhciReadReg (Uhc->PciIo, USBSTS_OFFSET);\r
142\r
143 if ((UsbCmd & USBCMD_EGSM) !=0 ) {\r
144 *State = EfiUsbHcStateSuspend;\r
145\r
146 } else if ((UsbSts & USBSTS_HCH) != 0) {\r
147 *State = EfiUsbHcStateHalt;\r
148\r
149 } else {\r
150 *State = EfiUsbHcStateOperational;\r
151 }\r
152\r
153 return EFI_SUCCESS;\r
154}\r
155\r
156\r
157/**\r
158 Sets the USB host controller to a specific state according to UEFI 2.0 spec.\r
159\r
160 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
161 @param State Indicates the state of the host controller that will\r
162 be set.\r
163\r
164 @return EFI_SUCCESS Host controller was successfully placed in the state.\r
165 @return EFI_INVALID_PARAMETER State is invalid.\r
166 @return EFI_DEVICE_ERROR Failed to set the state.\r
167\r
168**/\r
169EFI_STATUS\r
170EFIAPI\r
171Uhci2SetState (\r
172 IN EFI_USB2_HC_PROTOCOL *This,\r
173 IN EFI_USB_HC_STATE State\r
174 )\r
175{\r
176 EFI_USB_HC_STATE CurState;\r
177 USB_HC_DEV *Uhc;\r
178 EFI_TPL OldTpl;\r
179 EFI_STATUS Status;\r
180 UINT16 UsbCmd;\r
181\r
182 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
183 Status = Uhci2GetState (This, &CurState);\r
184\r
185 if (EFI_ERROR (Status)) {\r
186 return EFI_DEVICE_ERROR;\r
187 }\r
188\r
189 if (CurState == State) {\r
190 return EFI_SUCCESS;\r
191 }\r
192\r
193 Status = EFI_SUCCESS;\r
194 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
195\r
196 switch (State) {\r
197 case EfiUsbHcStateHalt:\r
198 Status = UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT);\r
199 break;\r
200\r
201 case EfiUsbHcStateOperational:\r
202 UsbCmd = UhciReadReg (Uhc->PciIo, USBCMD_OFFSET);\r
203\r
204 if (CurState == EfiUsbHcStateHalt) {\r
205 //\r
206 // Set Run/Stop bit to 1, also set the bandwidht reclamation\r
207 // point to 64 bytes\r
208 //\r
209 UsbCmd |= USBCMD_RS | USBCMD_MAXP;\r
210 UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, UsbCmd);\r
211\r
212 } else if (CurState == EfiUsbHcStateSuspend) {\r
213 //\r
214 // If FGR(Force Global Resume) bit is 0, set it\r
215 //\r
216 if ((UsbCmd & USBCMD_FGR) == 0) {\r
217 UsbCmd |= USBCMD_FGR;\r
218 UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, UsbCmd);\r
219 }\r
220\r
221 //\r
222 // wait 20ms to let resume complete (20ms is specified by UHCI spec)\r
223 //\r
224 gBS->Stall (UHC_FORCE_GLOBAL_RESUME_STALL);\r
225\r
226 //\r
227 // Write FGR bit to 0 and EGSM(Enter Global Suspend Mode) bit to 0\r
228 //\r
229 UsbCmd &= ~USBCMD_FGR;\r
230 UsbCmd &= ~USBCMD_EGSM;\r
231 UsbCmd |= USBCMD_RS;\r
232 UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, UsbCmd);\r
233 }\r
234\r
235 break;\r
236\r
237 case EfiUsbHcStateSuspend:\r
238 Status = Uhci2SetState (This, EfiUsbHcStateHalt);\r
239\r
240 if (EFI_ERROR (Status)) {\r
241 Status = EFI_DEVICE_ERROR;\r
242 goto ON_EXIT;\r
243 }\r
244\r
245 //\r
246 // Set Enter Global Suspend Mode bit to 1.\r
247 //\r
248 UsbCmd = UhciReadReg (Uhc->PciIo, USBCMD_OFFSET);\r
249 UsbCmd |= USBCMD_EGSM;\r
250 UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, UsbCmd);\r
251 break;\r
252\r
253 default:\r
254 Status = EFI_INVALID_PARAMETER;\r
255 break;\r
256 }\r
257\r
258ON_EXIT:\r
259 gBS->RestoreTPL (OldTpl);\r
260 return Status;\r
261}\r
262\r
263/**\r
264 Retrieves capabilities of USB host controller according to UEFI 2.0 spec.\r
265\r
266 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
267 @param MaxSpeed A pointer to the max speed USB host controller\r
268 supports.\r
269 @param PortNumber A pointer to the number of root hub ports.\r
270 @param Is64BitCapable A pointer to an integer to show whether USB host\r
271 controller supports 64-bit memory addressing.\r
272\r
273 @return EFI_SUCCESS capabilities were retrieved successfully.\r
274 @return EFI_INVALID_PARAMETER MaxSpeed or PortNumber or Is64BitCapable is NULL.\r
275 @return EFI_DEVICE_ERROR An error was encountered.\r
276\r
277**/\r
278EFI_STATUS\r
279EFIAPI\r
280Uhci2GetCapability (\r
281 IN EFI_USB2_HC_PROTOCOL *This,\r
282 OUT UINT8 *MaxSpeed,\r
283 OUT UINT8 *PortNumber,\r
284 OUT UINT8 *Is64BitCapable\r
285 )\r
286{\r
287 USB_HC_DEV *Uhc;\r
288 UINT32 Offset;\r
289 UINT16 PortSC;\r
290 UINT32 Index;\r
291\r
292 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
293\r
294 if ((NULL == MaxSpeed) || (NULL == PortNumber) || (NULL == Is64BitCapable)) {\r
295 return EFI_INVALID_PARAMETER;\r
296 }\r
297\r
298 *MaxSpeed = EFI_USB_SPEED_FULL;\r
299 *Is64BitCapable = (UINT8) FALSE;\r
300\r
301 *PortNumber = 0;\r
302\r
303 for (Index = 0; Index < USB_MAX_ROOTHUB_PORT; Index++) {\r
304 Offset = USBPORTSC_OFFSET + Index * 2;\r
305 PortSC = UhciReadReg (Uhc->PciIo, Offset);\r
306\r
307 //\r
308 // Port status's bit 7 is reserved and always returns 1 if\r
309 // the port number is valid. Intel's UHCI (in EHCI controller)\r
310 // returns 0 in this bit if port number is invalid. Also, if\r
311 // PciIo IoRead returns error, 0xFFFF is returned to caller.\r
312 //\r
313 if (((PortSC & 0x80) == 0) || (PortSC == 0xFFFF)) {\r
314 break;\r
315 }\r
316 (*PortNumber)++;\r
317 }\r
318\r
319 Uhc->RootPorts = *PortNumber;\r
320\r
321 DEBUG ((EFI_D_INFO, "Uhci2GetCapability: %d ports\n", (UINT32)Uhc->RootPorts));\r
322 return EFI_SUCCESS;\r
323}\r
324\r
325\r
326/**\r
327 Retrieves the current status of a USB root hub port according to UEFI 2.0 spec.\r
328\r
329 @param This A pointer to the EFI_USB2_HC_PROTOCOL.\r
330 @param PortNumber The port to get status.\r
331 @param PortStatus A pointer to the current port status bits and port\r
332 status change bits.\r
333\r
334 @return EFI_SUCCESS status of the USB root hub port was returned in PortStatus.\r
335 @return EFI_INVALID_PARAMETER PortNumber is invalid.\r
336 @return EFI_DEVICE_ERROR Can't read register.\r
337\r
338**/\r
339EFI_STATUS\r
340EFIAPI\r
341Uhci2GetRootHubPortStatus (\r
342 IN CONST EFI_USB2_HC_PROTOCOL *This,\r
343 IN CONST UINT8 PortNumber,\r
344 OUT EFI_USB_PORT_STATUS *PortStatus\r
345 )\r
346{\r
347 USB_HC_DEV *Uhc;\r
348 UINT32 Offset;\r
349 UINT16 PortSC;\r
350\r
351 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
352\r
353 if (PortStatus == NULL) {\r
354 return EFI_INVALID_PARAMETER;\r
355 }\r
356\r
357 if (PortNumber >= Uhc->RootPorts) {\r
358 return EFI_INVALID_PARAMETER;\r
359 }\r
360\r
361 Offset = USBPORTSC_OFFSET + PortNumber * 2;\r
362 PortStatus->PortStatus = 0;\r
363 PortStatus->PortChangeStatus = 0;\r
364\r
365 PortSC = UhciReadReg (Uhc->PciIo, Offset);\r
366\r
367 if ((PortSC & USBPORTSC_CCS) != 0) {\r
368 PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;\r
369 }\r
370\r
371 if ((PortSC & USBPORTSC_PED) != 0) {\r
372 PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;\r
373 }\r
374\r
375 if ((PortSC & USBPORTSC_SUSP) != 0) {\r
376 DEBUG ((EFI_D_INFO, "Uhci2GetRootHubPortStatus: port %d is suspended\n", PortNumber));\r
377 PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;\r
378 }\r
379\r
380 if ((PortSC & USBPORTSC_PR) != 0) {\r
381 PortStatus->PortStatus |= USB_PORT_STAT_RESET;\r
382 }\r
383\r
384 if ((PortSC & USBPORTSC_LSDA) != 0) {\r
385 PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;\r
386 }\r
387\r
388 //\r
389 // CHC will always return one in port owner bit\r
390 //\r
391 PortStatus->PortStatus |= USB_PORT_STAT_OWNER;\r
392\r
393 if ((PortSC & USBPORTSC_CSC) != 0) {\r
394 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;\r
395 }\r
396\r
397 if ((PortSC & USBPORTSC_PEDC) != 0) {\r
398 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;\r
399 }\r
400\r
401 return EFI_SUCCESS;\r
402}\r
403\r
404\r
405/**\r
406 Sets a feature for the specified root hub port according to UEFI 2.0 spec.\r
407\r
408 @param This A pointer to the EFI_USB2_HC_PROTOCOL.\r
409 @param PortNumber Specifies the root hub port whose feature is\r
410 requested to be set.\r
411 @param PortFeature Indicates the feature selector associated with the\r
412 feature set request.\r
413\r
414 @return EFI_SUCCESS PortFeature was set for the root port.\r
415 @return EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.\r
416 @return EFI_DEVICE_ERROR Can't read register.\r
417\r
418**/\r
419EFI_STATUS\r
420EFIAPI\r
421Uhci2SetRootHubPortFeature (\r
422 IN EFI_USB2_HC_PROTOCOL *This,\r
423 IN UINT8 PortNumber,\r
424 IN EFI_USB_PORT_FEATURE PortFeature\r
425 )\r
426{\r
427 USB_HC_DEV *Uhc;\r
428 EFI_TPL OldTpl;\r
429 UINT32 Offset;\r
430 UINT16 PortSC;\r
431 UINT16 Command;\r
432\r
433 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
434\r
435 if (PortNumber >= Uhc->RootPorts) {\r
436 return EFI_INVALID_PARAMETER;\r
437 }\r
438\r
439 Offset = USBPORTSC_OFFSET + PortNumber * 2;\r
440\r
441 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
442 PortSC = UhciReadReg (Uhc->PciIo, Offset);\r
443\r
444 switch (PortFeature) {\r
445 case EfiUsbPortSuspend:\r
446 Command = UhciReadReg (Uhc->PciIo, USBCMD_OFFSET);\r
447 if ((Command & USBCMD_EGSM) == 0) {\r
448 //\r
449 // if global suspend is not active, can set port suspend\r
450 //\r
451 PortSC &= 0xfff5;\r
452 PortSC |= USBPORTSC_SUSP;\r
453 }\r
454 break;\r
455\r
456 case EfiUsbPortReset:\r
457 PortSC &= 0xfff5;\r
458 PortSC |= USBPORTSC_PR;\r
459 break;\r
460\r
461 case EfiUsbPortPower:\r
462 //\r
463 // No action\r
464 //\r
465 break;\r
466\r
467 case EfiUsbPortEnable:\r
468 PortSC &= 0xfff5;\r
469 PortSC |= USBPORTSC_PED;\r
470 break;\r
471\r
472 default:\r
473 gBS->RestoreTPL (OldTpl);\r
474 return EFI_INVALID_PARAMETER;\r
475 }\r
476\r
477 UhciWriteReg (Uhc->PciIo, Offset, PortSC);\r
478 gBS->RestoreTPL (OldTpl);\r
479\r
480 return EFI_SUCCESS;\r
481}\r
482\r
483\r
484/**\r
485 Clears a feature for the specified root hub port according to Uefi 2.0 spec.\r
486\r
487 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
488 @param PortNumber Specifies the root hub port whose feature is\r
489 requested to be cleared.\r
490 @param PortFeature Indicates the feature selector associated with the\r
491 feature clear request.\r
492\r
493 @return EFI_SUCCESS PortFeature was cleared for the USB root hub port.\r
494 @return EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.\r
495 @return EFI_DEVICE_ERROR Can't read register.\r
496\r
497**/\r
498EFI_STATUS\r
499EFIAPI\r
500Uhci2ClearRootHubPortFeature (\r
501 IN EFI_USB2_HC_PROTOCOL *This,\r
502 IN UINT8 PortNumber,\r
503 IN EFI_USB_PORT_FEATURE PortFeature\r
504 )\r
505{\r
506 USB_HC_DEV *Uhc;\r
507 EFI_TPL OldTpl;\r
508 UINT32 Offset;\r
509 UINT16 PortSC;\r
510\r
511 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
512\r
513 if (PortNumber >= Uhc->RootPorts) {\r
514 return EFI_INVALID_PARAMETER;\r
515 }\r
516\r
517 Offset = USBPORTSC_OFFSET + PortNumber * 2;\r
518\r
519 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
520 PortSC = UhciReadReg (Uhc->PciIo, Offset);\r
521\r
522 switch (PortFeature) {\r
523 case EfiUsbPortEnable:\r
524 PortSC &= 0xfff5;\r
525 PortSC &= ~USBPORTSC_PED;\r
526 break;\r
527\r
528 case EfiUsbPortSuspend:\r
529 //\r
530 // Cause a resume on the specified port if in suspend mode.\r
531 //\r
532 PortSC &= 0xfff5;\r
533 PortSC &= ~USBPORTSC_SUSP;\r
534 break;\r
535\r
536 case EfiUsbPortPower:\r
537 //\r
538 // No action\r
539 //\r
540 break;\r
541\r
542 case EfiUsbPortReset:\r
543 PortSC &= 0xfff5;\r
544 PortSC &= ~USBPORTSC_PR;\r
545 break;\r
546\r
547 case EfiUsbPortConnectChange:\r
548 PortSC &= 0xfff5;\r
549 PortSC |= USBPORTSC_CSC;\r
550 break;\r
551\r
552 case EfiUsbPortEnableChange:\r
553 PortSC &= 0xfff5;\r
554 PortSC |= USBPORTSC_PEDC;\r
555 break;\r
556\r
557 case EfiUsbPortSuspendChange:\r
558 //\r
559 // Root hub does not support this\r
560 //\r
561 break;\r
562\r
563 case EfiUsbPortOverCurrentChange:\r
564 //\r
565 // Root hub does not support this\r
566 //\r
567 break;\r
568\r
569 case EfiUsbPortResetChange:\r
570 //\r
571 // Root hub does not support this\r
572 //\r
573 break;\r
574\r
575 default:\r
576 gBS->RestoreTPL (OldTpl);\r
577 return EFI_INVALID_PARAMETER;\r
578 }\r
579\r
580 UhciWriteReg (Uhc->PciIo, Offset, PortSC);\r
581 gBS->RestoreTPL (OldTpl);\r
582\r
583 return EFI_SUCCESS;\r
584}\r
585\r
586\r
587/**\r
588 Submits control transfer to a target USB device accroding to UEFI 2.0 spec.\r
589\r
590 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
591 @param DeviceAddress Target device address.\r
592 @param DeviceSpeed Device speed.\r
593 @param MaximumPacketLength Maximum packet size of the target endpoint.\r
594 @param Request USB device request to send.\r
595 @param TransferDirection Data direction of the Data stage in control transfer.\r
596 @param Data Data to transmit/receive in data stage.\r
597 @param DataLength Length of the data.\r
598 @param TimeOut Maximum time, in microseconds, for transfer to complete.\r
599 @param Translator Transaction translator to be used by this device.\r
600 @param TransferResult Variable to receive the transfer result.\r
601\r
602 @return EFI_SUCCESS The control transfer was completed successfully.\r
603 @return EFI_OUT_OF_RESOURCES Failed due to lack of resource.\r
604 @return EFI_INVALID_PARAMETER Some parameters are invalid.\r
605 @return EFI_TIMEOUT Failed due to timeout.\r
606 @return EFI_DEVICE_ERROR Failed due to host controller or device error.\r
607\r
608**/\r
609EFI_STATUS\r
610EFIAPI\r
611Uhci2ControlTransfer (\r
612 IN EFI_USB2_HC_PROTOCOL *This,\r
613 IN UINT8 DeviceAddress,\r
614 IN UINT8 DeviceSpeed,\r
615 IN UINTN MaximumPacketLength,\r
616 IN EFI_USB_DEVICE_REQUEST *Request,\r
617 IN EFI_USB_DATA_DIRECTION TransferDirection,\r
618 IN OUT VOID *Data,\r
619 IN OUT UINTN *DataLength,\r
620 IN UINTN TimeOut,\r
621 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
622 OUT UINT32 *TransferResult\r
623 )\r
624{\r
625 USB_HC_DEV *Uhc;\r
626 UHCI_TD_SW *TDs;\r
627 EFI_TPL OldTpl;\r
628 EFI_STATUS Status;\r
629 UHCI_QH_RESULT QhResult;\r
630 UINT8 PktId;\r
631 UINT8 *RequestPhy;\r
632 VOID *RequestMap;\r
633 UINT8 *DataPhy;\r
634 VOID *DataMap;\r
635 BOOLEAN IsSlowDevice;\r
636 UINTN TransferDataLength;\r
637\r
638 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
639 TDs = NULL;\r
640 DataPhy = NULL;\r
641 DataMap = NULL;\r
642 RequestPhy = NULL;\r
643 RequestMap = NULL;\r
644\r
645 IsSlowDevice = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);\r
646\r
647 //\r
648 // Parameters Checking\r
649 //\r
650 if (Request == NULL || TransferResult == NULL) {\r
651 return EFI_INVALID_PARAMETER;\r
652 }\r
653\r
654 if (IsSlowDevice && (MaximumPacketLength != 8)) {\r
655 return EFI_INVALID_PARAMETER;\r
656 }\r
657\r
658 if ((MaximumPacketLength != 8) && (MaximumPacketLength != 16) &&\r
659 (MaximumPacketLength != 32) && (MaximumPacketLength != 64)) {\r
660\r
661 return EFI_INVALID_PARAMETER;\r
662 }\r
663\r
664 if ((TransferDirection != EfiUsbNoData) && (Data == NULL || DataLength == NULL)) {\r
665 return EFI_INVALID_PARAMETER;\r
666 }\r
667\r
668 if (TransferDirection == EfiUsbNoData) {\r
669 TransferDataLength = 0;\r
670 } else {\r
671 TransferDataLength = *DataLength;\r
672 }\r
673\r
674 *TransferResult = EFI_USB_ERR_SYSTEM;\r
675 Status = EFI_DEVICE_ERROR;\r
676\r
677 //\r
678 // If errors exist that cause host controller halt,\r
679 // clear status then return EFI_DEVICE_ERROR.\r
680 //\r
681 UhciAckAllInterrupt (Uhc);\r
682\r
683 if (!UhciIsHcWorking (Uhc->PciIo)) {\r
684 return EFI_DEVICE_ERROR;\r
685 }\r
686\r
687 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
688\r
689 //\r
690 // Map the Request and data for bus master access,\r
691 // then create a list of TD for this transfer\r
692 //\r
693 Status = UhciMapUserRequest (Uhc, Request, &RequestPhy, &RequestMap);\r
694\r
695 if (EFI_ERROR (Status)) {\r
696 goto ON_EXIT;\r
697 }\r
698\r
699 Status = UhciMapUserData (Uhc, TransferDirection, Data, DataLength, &PktId, &DataPhy, &DataMap);\r
700\r
701 if (EFI_ERROR (Status)) {\r
702 Uhc->PciIo->Unmap (Uhc->PciIo, RequestMap);\r
703 goto ON_EXIT;\r
704 }\r
705\r
706 TDs = UhciCreateCtrlTds (\r
707 Uhc,\r
708 DeviceAddress,\r
709 PktId,\r
710 RequestPhy,\r
711 DataPhy,\r
712 TransferDataLength,\r
713 (UINT8) MaximumPacketLength,\r
714 IsSlowDevice\r
715 );\r
716\r
717 if (TDs == NULL) {\r
718 Status = EFI_OUT_OF_RESOURCES;\r
719 goto UNMAP_DATA;\r
720 }\r
721\r
722 //\r
723 // According to the speed of the end point, link\r
724 // the TD to corrosponding queue head, then check\r
725 // the execution result\r
726 //\r
727 UhciLinkTdToQh (Uhc->CtrlQh, TDs);\r
728 Status = UhciExecuteTransfer (Uhc, Uhc->CtrlQh, TDs, TimeOut, IsSlowDevice, &QhResult);\r
729 UhciUnlinkTdFromQh (Uhc->CtrlQh, TDs);\r
730\r
731 Uhc->PciIo->Flush (Uhc->PciIo);\r
732\r
733 *TransferResult = QhResult.Result;\r
734\r
735 if (DataLength != NULL) {\r
736 *DataLength = QhResult.Complete;\r
737 }\r
738\r
739 UhciDestoryTds (Uhc, TDs);\r
740\r
741UNMAP_DATA:\r
742 Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
743 Uhc->PciIo->Unmap (Uhc->PciIo, RequestMap);\r
744\r
745ON_EXIT:\r
746 gBS->RestoreTPL (OldTpl);\r
747 return Status;\r
748}\r
749\r
750\r
751/**\r
752 Submits bulk transfer to a bulk endpoint of a USB device.\r
753\r
754 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
755 @param DeviceAddress Target device address.\r
756 @param EndPointAddress Endpoint number and direction.\r
757 @param DeviceSpeed Device speed.\r
758 @param MaximumPacketLength Maximum packet size of the target endpoint.\r
759 @param DataBuffersNumber Number of data buffers prepared for the transfer.\r
760 @param Data Array of pointers to the buffers of data.\r
761 @param DataLength On input, size of the data buffer, On output,\r
762 actually transferred data size.\r
763 @param DataToggle On input, data toggle to use; On output, next data toggle.\r
764 @param TimeOut Maximum time out, in microseconds.\r
765 @param Translator A pointr to the transaction translator data.\r
766 @param TransferResult Variable to receive transfer result.\r
767\r
768 @return EFI_SUCCESS The bulk transfer was completed successfully.\r
769 @return EFI_OUT_OF_RESOURCES Failed due to lack of resource.\r
770 @return EFI_INVALID_PARAMETER Some parameters are invalid.\r
771 @return EFI_TIMEOUT Failed due to timeout.\r
772 @return EFI_DEVICE_ERROR Failed due to host controller or device error.\r
773\r
774**/\r
775EFI_STATUS\r
776EFIAPI\r
777Uhci2BulkTransfer (\r
778 IN EFI_USB2_HC_PROTOCOL *This,\r
779 IN UINT8 DeviceAddress,\r
780 IN UINT8 EndPointAddress,\r
781 IN UINT8 DeviceSpeed,\r
782 IN UINTN MaximumPacketLength,\r
783 IN UINT8 DataBuffersNumber,\r
784 IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],\r
785 IN OUT UINTN *DataLength,\r
786 IN OUT UINT8 *DataToggle,\r
787 IN UINTN TimeOut,\r
788 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
789 OUT UINT32 *TransferResult\r
790 )\r
791{\r
792 EFI_USB_DATA_DIRECTION Direction;\r
793 EFI_TPL OldTpl;\r
794 USB_HC_DEV *Uhc;\r
795 UHCI_TD_SW *TDs;\r
796 UHCI_QH_SW *BulkQh;\r
797 UHCI_QH_RESULT QhResult;\r
798 EFI_STATUS Status;\r
799 UINT8 PktId;\r
800 UINT8 *DataPhy;\r
801 VOID *DataMap;\r
802\r
803 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
804 DataPhy = NULL;\r
805 DataMap = NULL;\r
806\r
807 if (DeviceSpeed == EFI_USB_SPEED_LOW) {\r
808 return EFI_INVALID_PARAMETER;\r
809 }\r
810\r
811 if ((DataLength == NULL) || (*DataLength == 0) || (Data == NULL) || (TransferResult == NULL)) {\r
812 return EFI_INVALID_PARAMETER;\r
813 }\r
814\r
815 if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
816 return EFI_INVALID_PARAMETER;\r
817 }\r
818\r
819 if ((MaximumPacketLength != 8) && (MaximumPacketLength != 16) &&\r
820 (MaximumPacketLength != 32) && (MaximumPacketLength != 64)) {\r
821 return EFI_INVALID_PARAMETER;\r
822 }\r
823\r
824 *TransferResult = EFI_USB_ERR_SYSTEM;\r
825 Status = EFI_OUT_OF_RESOURCES;\r
826\r
827 //\r
828 // If has errors that cause host controller halt,\r
829 // then return EFI_DEVICE_ERROR directly.\r
830 //\r
831 UhciAckAllInterrupt (Uhc);\r
832\r
833 if (!UhciIsHcWorking (Uhc->PciIo)) {\r
834 return EFI_DEVICE_ERROR;\r
835 }\r
836\r
837 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
838\r
839 //\r
840 // Map the source data buffer for bus master access,\r
841 // then create a list of TDs\r
842 //\r
843 if ((EndPointAddress & 0x80) != 0) {\r
844 Direction = EfiUsbDataIn;\r
845 } else {\r
846 Direction = EfiUsbDataOut;\r
847 }\r
848\r
849 Status = UhciMapUserData (Uhc, Direction, *Data, DataLength, &PktId, &DataPhy, &DataMap);\r
850\r
851 if (EFI_ERROR (Status)) {\r
852 goto ON_EXIT;\r
853 }\r
854\r
855 Status = EFI_OUT_OF_RESOURCES;\r
856 TDs = UhciCreateBulkOrIntTds (\r
857 Uhc,\r
858 DeviceAddress,\r
859 EndPointAddress,\r
860 PktId,\r
861 DataPhy,\r
862 *DataLength,\r
863 DataToggle,\r
864 (UINT8) MaximumPacketLength,\r
865 FALSE\r
866 );\r
867\r
868 if (TDs == NULL) {\r
869 Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
870 goto ON_EXIT;\r
871 }\r
872\r
873\r
874 //\r
875 // Link the TDs to bulk queue head. According to the platfore\r
876 // defintion of UHCI_NO_BW_RECLAMATION, BulkQh is either configured\r
877 // to do full speed bandwidth reclamation or not.\r
878 //\r
879 BulkQh = Uhc->BulkQh;\r
880\r
881 UhciLinkTdToQh (BulkQh, TDs);\r
882 Status = UhciExecuteTransfer (Uhc, BulkQh, TDs, TimeOut, FALSE, &QhResult);\r
883 UhciUnlinkTdFromQh (BulkQh, TDs);\r
884\r
885 Uhc->PciIo->Flush (Uhc->PciIo);\r
886\r
887 *TransferResult = QhResult.Result;\r
888 *DataToggle = QhResult.NextToggle;\r
889 *DataLength = QhResult.Complete;\r
890\r
891 UhciDestoryTds (Uhc, TDs);\r
892 Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
893\r
894ON_EXIT:\r
895 gBS->RestoreTPL (OldTpl);\r
896 return Status;\r
897}\r
898\r
899\r
900/**\r
901 Submits an asynchronous interrupt transfer to an\r
902 interrupt endpoint of a USB device according to UEFI 2.0 spec.\r
903\r
904 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
905 @param DeviceAddress Target device address.\r
906 @param EndPointAddress Endpoint number and direction.\r
907 @param DeviceSpeed Device speed.\r
908 @param MaximumPacketLength Maximum packet size of the target endpoint.\r
909 @param IsNewTransfer If TRUE, submit a new transfer, if FALSE cancel old transfer.\r
910 @param DataToggle On input, data toggle to use; On output, next data toggle.\r
911 @param PollingInterval Interrupt poll rate in milliseconds.\r
912 @param DataLength On input, size of the data buffer, On output,\r
913 actually transferred data size.\r
914 @param Translator A pointr to the transaction translator data.\r
915 @param CallBackFunction Function to call periodically.\r
916 @param Context User context.\r
917\r
918 @return EFI_SUCCESS Transfer was submitted.\r
919 @return EFI_INVALID_PARAMETER Some parameters are invalid.\r
920 @return EFI_OUT_OF_RESOURCES Failed due to a lack of resources.\r
921 @return EFI_DEVICE_ERROR Can't read register.\r
922\r
923**/\r
924EFI_STATUS\r
925EFIAPI\r
926Uhci2AsyncInterruptTransfer (\r
927 IN EFI_USB2_HC_PROTOCOL *This,\r
928 IN UINT8 DeviceAddress,\r
929 IN UINT8 EndPointAddress,\r
930 IN UINT8 DeviceSpeed,\r
931 IN UINTN MaximumPacketLength,\r
932 IN BOOLEAN IsNewTransfer,\r
933 IN OUT UINT8 *DataToggle,\r
934 IN UINTN PollingInterval,\r
935 IN UINTN DataLength,\r
936 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
937 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,\r
938 IN VOID *Context\r
939 )\r
940{\r
941 USB_HC_DEV *Uhc;\r
942 BOOLEAN IsSlowDevice;\r
943 UHCI_QH_SW *Qh;\r
944 UHCI_TD_SW *IntTds;\r
945 EFI_TPL OldTpl;\r
946 EFI_STATUS Status;\r
947 UINT8 *DataPtr;\r
948 UINT8 *DataPhy;\r
949 VOID *DataMap;\r
950 UINT8 PktId;\r
951\r
952 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
953 Qh = NULL;\r
954 IntTds = NULL;\r
955 DataPtr = NULL;\r
956 DataPhy = NULL;\r
957 DataMap = NULL;\r
958\r
959 IsSlowDevice = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);\r
960\r
961 if ((EndPointAddress & 0x80) == 0) {\r
962 return EFI_INVALID_PARAMETER;\r
963 }\r
964\r
965 //\r
966 // Delete Async interrupt transfer request\r
967 //\r
968 if (!IsNewTransfer) {\r
969 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
970 Status = UhciRemoveAsyncReq (Uhc, DeviceAddress, EndPointAddress, DataToggle);\r
971\r
972 gBS->RestoreTPL (OldTpl);\r
973 return Status;\r
974 }\r
975\r
976 if (PollingInterval < 1 || PollingInterval > 255) {\r
977 return EFI_INVALID_PARAMETER;\r
978 }\r
979\r
980 if (DataLength == 0) {\r
981 return EFI_INVALID_PARAMETER;\r
982 }\r
983\r
984 if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
985 return EFI_INVALID_PARAMETER;\r
986 }\r
987\r
988 //\r
989 // If has errors that cause host controller halt,\r
990 // then return EFI_DEVICE_ERROR directly.\r
991 //\r
992 UhciAckAllInterrupt (Uhc);\r
993\r
994 if (!UhciIsHcWorking (Uhc->PciIo)) {\r
995 return EFI_DEVICE_ERROR;\r
996 }\r
997\r
998 //\r
999 // Allocate and map source data buffer for bus master access.\r
1000 //\r
1001 DataPtr = AllocatePool (DataLength);\r
1002\r
1003 if (DataPtr == NULL) {\r
1004 return EFI_OUT_OF_RESOURCES;\r
1005 }\r
1006\r
1007 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
1008\r
1009 //\r
1010 // Map the user data then create a queue head and\r
1011 // list of TD for it.\r
1012 //\r
1013 Status = UhciMapUserData (\r
1014 Uhc,\r
1015 EfiUsbDataIn,\r
1016 DataPtr,\r
1017 &DataLength,\r
1018 &PktId,\r
1019 &DataPhy,\r
1020 &DataMap\r
1021 );\r
1022\r
1023 if (EFI_ERROR (Status)) {\r
1024 goto FREE_DATA;\r
1025 }\r
1026\r
1027 Qh = UhciCreateQh (Uhc, PollingInterval);\r
1028\r
1029 if (Qh == NULL) {\r
1030 Status = EFI_OUT_OF_RESOURCES;\r
1031 goto UNMAP_DATA;\r
1032 }\r
1033\r
1034 IntTds = UhciCreateBulkOrIntTds (\r
1035 Uhc,\r
1036 DeviceAddress,\r
1037 EndPointAddress,\r
1038 PktId,\r
1039 DataPhy,\r
1040 DataLength,\r
1041 DataToggle,\r
1042 (UINT8) MaximumPacketLength,\r
1043 IsSlowDevice\r
1044 );\r
1045\r
1046 if (IntTds == NULL) {\r
1047 Status = EFI_OUT_OF_RESOURCES;\r
1048 goto DESTORY_QH;\r
1049 }\r
1050\r
1051 UhciLinkTdToQh (Qh, IntTds);\r
1052\r
1053 //\r
1054 // Save QH-TD structures to async Interrupt transfer list,\r
1055 // for monitor interrupt transfer execution routine use.\r
1056 //\r
1057 Status = UhciCreateAsyncReq (\r
1058 Uhc,\r
1059 Qh,\r
1060 IntTds,\r
1061 DeviceAddress,\r
1062 EndPointAddress,\r
1063 DataLength,\r
1064 PollingInterval,\r
1065 DataMap,\r
1066 DataPtr,\r
1067 CallBackFunction,\r
1068 Context,\r
1069 IsSlowDevice\r
1070 );\r
1071\r
1072 if (EFI_ERROR (Status)) {\r
1073 goto DESTORY_QH;\r
1074 }\r
1075\r
1076 UhciLinkQhToFrameList (Uhc->FrameBase, Qh);\r
1077\r
1078 gBS->RestoreTPL (OldTpl);\r
1079 return EFI_SUCCESS;\r
1080\r
1081DESTORY_QH:\r
1082 UsbHcFreeMem (Uhc->MemPool, Qh, sizeof (UHCI_QH_SW));\r
1083\r
1084UNMAP_DATA:\r
1085 Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
1086\r
1087FREE_DATA:\r
1088 gBS->FreePool (DataPtr);\r
1089 Uhc->PciIo->Flush (Uhc->PciIo);\r
1090\r
1091 gBS->RestoreTPL (OldTpl);\r
1092 return Status;\r
1093}\r
1094\r
1095/**\r
1096 Submits synchronous interrupt transfer to an interrupt endpoint\r
1097 of a USB device according to UEFI 2.0 spec.\r
1098\r
1099\r
1100 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1101 @param DeviceAddress Target device address.\r
1102 @param EndPointAddress Endpoint number and direction.\r
1103 @param DeviceSpeed Device speed.\r
1104 @param MaximumPacketLength Maximum packet size of the target endpoint.\r
1105 @param Data Array of pointers to the buffers of data.\r
1106 @param DataLength On input, size of the data buffer, On output,\r
1107 actually transferred data size.\r
1108 @param DataToggle On input, data toggle to use; On output, next data toggle.\r
1109 @param TimeOut Maximum time out, in microseconds.\r
1110 @param Translator A pointr to the transaction translator data.\r
1111 @param TransferResult Variable to receive transfer result.\r
1112\r
1113 @return EFI_SUCCESS The transfer was completed successfully.\r
1114 @return EFI_OUT_OF_RESOURCES Failed due to lack of resource.\r
1115 @return EFI_INVALID_PARAMETER Some parameters are invalid.\r
1116 @return EFI_TIMEOUT Failed due to timeout.\r
1117 @return EFI_DEVICE_ERROR Failed due to host controller or device error.\r
1118\r
1119**/\r
1120EFI_STATUS\r
1121EFIAPI\r
1122Uhci2SyncInterruptTransfer (\r
1123 IN EFI_USB2_HC_PROTOCOL *This,\r
1124 IN UINT8 DeviceAddress,\r
1125 IN UINT8 EndPointAddress,\r
1126 IN UINT8 DeviceSpeed,\r
1127 IN UINTN MaximumPacketLength,\r
1128 IN OUT VOID *Data,\r
1129 IN OUT UINTN *DataLength,\r
1130 IN OUT UINT8 *DataToggle,\r
1131 IN UINTN TimeOut,\r
1132 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1133 OUT UINT32 *TransferResult\r
1134 )\r
1135{\r
1136 EFI_STATUS Status;\r
1137 USB_HC_DEV *Uhc;\r
1138 UHCI_TD_SW *TDs;\r
1139 UHCI_QH_RESULT QhResult;\r
1140 EFI_TPL OldTpl;\r
1141 UINT8 *DataPhy;\r
1142 VOID *DataMap;\r
1143 UINT8 PktId;\r
1144 BOOLEAN IsSlowDevice;\r
1145\r
1146 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
1147 DataPhy = NULL;\r
1148 DataMap = NULL;\r
1149 TDs = NULL;\r
1150\r
1151 if (DeviceSpeed == EFI_USB_SPEED_HIGH) {\r
1152 return EFI_INVALID_PARAMETER;\r
1153 }\r
1154\r
1155 IsSlowDevice = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);\r
1156\r
1157 if ((DataLength == NULL) || (Data == NULL) || (TransferResult == NULL)) {\r
1158 return EFI_INVALID_PARAMETER;\r
1159 }\r
1160\r
1161 if ((EndPointAddress & 0x80) == 0) {\r
1162 return EFI_INVALID_PARAMETER;\r
1163 }\r
1164\r
1165 if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
1166 return EFI_INVALID_PARAMETER;\r
1167 }\r
1168\r
1169 if ((*DataLength == 0) || (MaximumPacketLength > 64)) {\r
1170 return EFI_INVALID_PARAMETER;\r
1171 }\r
1172\r
1173 if (IsSlowDevice && (MaximumPacketLength > 8)) {\r
1174 return EFI_INVALID_PARAMETER;\r
1175 }\r
1176\r
1177 *TransferResult = EFI_USB_ERR_SYSTEM;\r
1178 Status = EFI_DEVICE_ERROR;\r
1179\r
1180\r
1181 UhciAckAllInterrupt (Uhc);\r
1182\r
1183 if (!UhciIsHcWorking (Uhc->PciIo)) {\r
1184 return Status;\r
1185 }\r
1186\r
1187 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
1188\r
1189 //\r
1190 // Map the source data buffer for bus master access.\r
1191 // Create Tds list, then link it to the UHC's interrupt list\r
1192 //\r
1193 Status = UhciMapUserData (\r
1194 Uhc,\r
1195 EfiUsbDataIn,\r
1196 Data,\r
1197 DataLength,\r
1198 &PktId,\r
1199 &DataPhy,\r
1200 &DataMap\r
1201 );\r
1202\r
1203 if (EFI_ERROR (Status)) {\r
1204 goto ON_EXIT;\r
1205 }\r
1206\r
1207 TDs = UhciCreateBulkOrIntTds (\r
1208 Uhc,\r
1209 DeviceAddress,\r
1210 EndPointAddress,\r
1211 PktId,\r
1212 DataPhy,\r
1213 *DataLength,\r
1214 DataToggle,\r
1215 (UINT8) MaximumPacketLength,\r
1216 IsSlowDevice\r
1217 );\r
1218\r
1219 if (TDs == NULL) {\r
1220 Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
1221\r
1222 Status = EFI_OUT_OF_RESOURCES;\r
1223 goto ON_EXIT;\r
1224 }\r
1225\r
1226\r
1227 UhciLinkTdToQh (Uhc->SyncIntQh, TDs);\r
1228\r
1229 Status = UhciExecuteTransfer (Uhc, Uhc->SyncIntQh, TDs, TimeOut, IsSlowDevice, &QhResult);\r
1230\r
1231 UhciUnlinkTdFromQh (Uhc->SyncIntQh, TDs);\r
1232 Uhc->PciIo->Flush (Uhc->PciIo);\r
1233\r
1234 *TransferResult = QhResult.Result;\r
1235 *DataToggle = QhResult.NextToggle;\r
1236 *DataLength = QhResult.Complete;\r
1237\r
1238 UhciDestoryTds (Uhc, TDs);\r
1239 Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
1240\r
1241ON_EXIT:\r
1242 gBS->RestoreTPL (OldTpl);\r
1243 return Status;\r
1244}\r
1245\r
1246\r
1247/**\r
1248 Submits isochronous transfer to a target USB device according to UEFI 2.0 spec.\r
1249\r
1250 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1251 @param DeviceAddress Target device address.\r
1252 @param EndPointAddress Endpoint number and direction.\r
1253 @param DeviceSpeed Device speed.\r
1254 @param MaximumPacketLength Maximum packet size of the target endpoint.\r
1255 @param DataBuffersNumber Number of data buffers prepared for the transfer.\r
1256 @param Data Array of pointers to the buffers of data.\r
1257 @param DataLength On input, size of the data buffer, On output,\r
1258 actually transferred data size.\r
1259 @param Translator A pointr to the transaction translator data.\r
1260 @param TransferResult Variable to receive transfer result.\r
1261\r
1262 @return EFI_UNSUPPORTED\r
1263\r
1264**/\r
1265EFI_STATUS\r
1266EFIAPI\r
1267Uhci2IsochronousTransfer (\r
1268 IN EFI_USB2_HC_PROTOCOL *This,\r
1269 IN UINT8 DeviceAddress,\r
1270 IN UINT8 EndPointAddress,\r
1271 IN UINT8 DeviceSpeed,\r
1272 IN UINTN MaximumPacketLength,\r
1273 IN UINT8 DataBuffersNumber,\r
1274 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
1275 IN UINTN DataLength,\r
1276 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1277 OUT UINT32 *TransferResult\r
1278 )\r
1279{\r
1280 return EFI_UNSUPPORTED;\r
1281}\r
1282\r
1283\r
1284/**\r
1285 Submits Async isochronous transfer to a target USB device according to UEFI 2.0 spec.\r
1286\r
1287 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1288 @param DeviceAddress Target device address.\r
1289 @param EndPointAddress Endpoint number and direction.\r
1290 @param DeviceSpeed Device speed.\r
1291 @param MaximumPacketLength Maximum packet size of the target endpoint.\r
1292 @param DataBuffersNumber Number of data buffers prepared for the transfer.\r
1293 @param Data Array of pointers to the buffers of data.\r
1294 @param DataLength On input, size of the data buffer, On output,\r
1295 actually transferred data size.\r
1296 @param Translator A pointr to the transaction translator data.\r
1297 @param IsochronousCallBack Function to call when the transfer complete.\r
1298 @param Context Pass to the call back function as parameter.\r
1299\r
1300 @return EFI_UNSUPPORTED\r
1301\r
1302**/\r
1303EFI_STATUS\r
1304EFIAPI\r
1305Uhci2AsyncIsochronousTransfer (\r
1306 IN EFI_USB2_HC_PROTOCOL *This,\r
1307 IN UINT8 DeviceAddress,\r
1308 IN UINT8 EndPointAddress,\r
1309 IN UINT8 DeviceSpeed,\r
1310 IN UINTN MaximumPacketLength,\r
1311 IN UINT8 DataBuffersNumber,\r
1312 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
1313 IN UINTN DataLength,\r
1314 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1315 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,\r
1316 IN VOID *Context\r
1317 )\r
1318{\r
1319 return EFI_UNSUPPORTED;\r
1320}\r
1321\r
1322/**\r
1323 Entry point for EFI drivers.\r
1324\r
1325 @param ImageHandle EFI_HANDLE.\r
1326 @param SystemTable EFI_SYSTEM_TABLE.\r
1327\r
1328 @retval EFI_SUCCESS Driver is successfully loaded.\r
1329 @return Others Failed.\r
1330\r
1331**/\r
1332EFI_STATUS\r
1333EFIAPI\r
1334UhciDriverEntryPoint (\r
1335 IN EFI_HANDLE ImageHandle,\r
1336 IN EFI_SYSTEM_TABLE *SystemTable\r
1337 )\r
1338{\r
1339 return EfiLibInstallDriverBindingComponentName2 (\r
1340 ImageHandle,\r
1341 SystemTable,\r
1342 &gUhciDriverBinding,\r
1343 ImageHandle,\r
1344 &gUhciComponentName,\r
1345 &gUhciComponentName2\r
1346 );\r
1347}\r
1348\r
1349\r
1350/**\r
1351 Test to see if this driver supports ControllerHandle. Any\r
1352 ControllerHandle that has UsbHcProtocol installed will be supported.\r
1353\r
1354 @param This Protocol instance pointer.\r
1355 @param Controller Handle of device to test.\r
1356 @param RemainingDevicePath Not used.\r
1357\r
1358 @return EFI_SUCCESS This driver supports this device.\r
1359 @return EFI_UNSUPPORTED This driver does not support this device.\r
1360\r
1361**/\r
1362EFI_STATUS\r
1363EFIAPI\r
1364UhciDriverBindingSupported (\r
1365 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1366 IN EFI_HANDLE Controller,\r
1367 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
1368 )\r
1369{\r
1370 EFI_STATUS OpenStatus;\r
1371 EFI_STATUS Status;\r
1372 EFI_PCI_IO_PROTOCOL *PciIo;\r
1373 USB_CLASSC UsbClassCReg;\r
1374\r
1375 //\r
1376 // Test whether there is PCI IO Protocol attached on the controller handle.\r
1377 //\r
1378 OpenStatus = gBS->OpenProtocol (\r
1379 Controller,\r
1380 &gEfiPciIoProtocolGuid,\r
1381 (VOID **) &PciIo,\r
1382 This->DriverBindingHandle,\r
1383 Controller,\r
1384 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1385 );\r
1386\r
1387 if (EFI_ERROR (OpenStatus)) {\r
1388 return OpenStatus;\r
1389 }\r
1390\r
1391 Status = PciIo->Pci.Read (\r
1392 PciIo,\r
1393 EfiPciIoWidthUint8,\r
1394 CLASSC_OFFSET,\r
1395 sizeof (USB_CLASSC) / sizeof (UINT8),\r
1396 &UsbClassCReg\r
1397 );\r
1398\r
1399 if (EFI_ERROR (Status)) {\r
1400 Status = EFI_UNSUPPORTED;\r
1401 goto ON_EXIT;\r
1402 }\r
1403\r
1404 //\r
1405 // Test whether the controller belongs to UHCI type\r
1406 //\r
1407 if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||\r
1408 (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||\r
1409 (UsbClassCReg.PI != PCI_CLASSC_PI_UHCI)\r
1410 ) {\r
1411\r
1412 Status = EFI_UNSUPPORTED;\r
1413 }\r
1414\r
1415ON_EXIT:\r
1416 gBS->CloseProtocol (\r
1417 Controller,\r
1418 &gEfiPciIoProtocolGuid,\r
1419 This->DriverBindingHandle,\r
1420 Controller\r
1421 );\r
1422\r
1423 return Status;\r
1424\r
1425}\r
1426\r
1427\r
1428/**\r
1429 Allocate and initialize the empty UHCI device.\r
1430\r
1431 @param PciIo The PCIIO to use.\r
1432 @param OriginalPciAttributes The original PCI attributes.\r
1433\r
1434 @return Allocated UHCI device. If err, return NULL.\r
1435\r
1436**/\r
1437USB_HC_DEV *\r
1438UhciAllocateDev (\r
1439 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
1440 IN UINT64 OriginalPciAttributes\r
1441 )\r
1442{\r
1443 USB_HC_DEV *Uhc;\r
1444 EFI_STATUS Status;\r
1445\r
1446 Uhc = AllocateZeroPool (sizeof (USB_HC_DEV));\r
1447\r
1448 if (Uhc == NULL) {\r
1449 return NULL;\r
1450 }\r
1451\r
1452 //\r
1453 // This driver supports both USB_HC_PROTOCOL and USB2_HC_PROTOCOL.\r
1454 // USB_HC_PROTOCOL is for EFI 1.1 backward compability.\r
1455 //\r
1456 Uhc->Signature = USB_HC_DEV_SIGNATURE;\r
1457 Uhc->Usb2Hc.GetCapability = Uhci2GetCapability;\r
1458 Uhc->Usb2Hc.Reset = Uhci2Reset;\r
1459 Uhc->Usb2Hc.GetState = Uhci2GetState;\r
1460 Uhc->Usb2Hc.SetState = Uhci2SetState;\r
1461 Uhc->Usb2Hc.ControlTransfer = Uhci2ControlTransfer;\r
1462 Uhc->Usb2Hc.BulkTransfer = Uhci2BulkTransfer;\r
1463 Uhc->Usb2Hc.AsyncInterruptTransfer = Uhci2AsyncInterruptTransfer;\r
1464 Uhc->Usb2Hc.SyncInterruptTransfer = Uhci2SyncInterruptTransfer;\r
1465 Uhc->Usb2Hc.IsochronousTransfer = Uhci2IsochronousTransfer;\r
1466 Uhc->Usb2Hc.AsyncIsochronousTransfer = Uhci2AsyncIsochronousTransfer;\r
1467 Uhc->Usb2Hc.GetRootHubPortStatus = Uhci2GetRootHubPortStatus;\r
1468 Uhc->Usb2Hc.SetRootHubPortFeature = Uhci2SetRootHubPortFeature;\r
1469 Uhc->Usb2Hc.ClearRootHubPortFeature = Uhci2ClearRootHubPortFeature;\r
1470 Uhc->Usb2Hc.MajorRevision = 0x1;\r
1471 Uhc->Usb2Hc.MinorRevision = 0x1;\r
1472\r
1473 Uhc->PciIo = PciIo;\r
1474 Uhc->OriginalPciAttributes = OriginalPciAttributes;\r
1475 Uhc->MemPool = UsbHcInitMemPool (PciIo, TRUE, 0);\r
1476\r
1477 if (Uhc->MemPool == NULL) {\r
1478 Status = EFI_OUT_OF_RESOURCES;\r
1479 goto ON_ERROR;\r
1480 }\r
1481\r
1482 InitializeListHead (&Uhc->AsyncIntList);\r
1483\r
1484 Status = gBS->CreateEvent (\r
1485 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
1486 TPL_CALLBACK,\r
1487 UhciMonitorAsyncReqList,\r
1488 Uhc,\r
1489 &Uhc->AsyncIntMonitor\r
1490 );\r
1491\r
1492 if (EFI_ERROR (Status)) {\r
1493 UsbHcFreeMemPool (Uhc->MemPool);\r
1494 goto ON_ERROR;\r
1495 }\r
1496\r
1497 return Uhc;\r
1498\r
1499ON_ERROR:\r
1500 FreePool (Uhc);\r
1501 return NULL;\r
1502}\r
1503\r
1504\r
1505/**\r
1506 Free the UHCI device and release its associated resources.\r
1507\r
1508 @param Uhc The UHCI device to release.\r
1509\r
1510**/\r
1511VOID\r
1512UhciFreeDev (\r
1513 IN USB_HC_DEV *Uhc\r
1514 )\r
1515{\r
1516 if (Uhc->AsyncIntMonitor != NULL) {\r
1517 gBS->CloseEvent (Uhc->AsyncIntMonitor);\r
1518 }\r
1519\r
1520 if (Uhc->ExitBootServiceEvent != NULL) {\r
1521 gBS->CloseEvent (Uhc->ExitBootServiceEvent);\r
1522 }\r
1523 \r
1524 if (Uhc->MemPool != NULL) {\r
1525 UsbHcFreeMemPool (Uhc->MemPool);\r
1526 }\r
1527\r
1528 if (Uhc->CtrlNameTable != NULL) {\r
1529 FreeUnicodeStringTable (Uhc->CtrlNameTable);\r
1530 }\r
1531\r
1532 FreePool (Uhc);\r
1533}\r
1534\r
1535\r
1536/**\r
1537 Uninstall all Uhci Interface.\r
1538\r
1539 @param Controller Controller handle.\r
1540 @param This Protocol instance pointer.\r
1541\r
1542**/\r
1543VOID\r
1544UhciCleanDevUp (\r
1545 IN EFI_HANDLE Controller,\r
1546 IN EFI_USB2_HC_PROTOCOL *This\r
1547 )\r
1548{\r
1549 USB_HC_DEV *Uhc;\r
1550\r
1551 //\r
1552 // Uninstall the USB_HC and USB_HC2 protocol, then disable the controller\r
1553 //\r
1554 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
1555 UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT);\r
1556\r
1557 gBS->UninstallProtocolInterface (\r
1558 Controller,\r
1559 &gEfiUsb2HcProtocolGuid,\r
1560 &Uhc->Usb2Hc\r
1561 );\r
1562\r
1563 UhciFreeAllAsyncReq (Uhc);\r
1564 UhciDestoryFrameList (Uhc);\r
1565\r
1566 //\r
1567 // Restore original PCI attributes\r
1568 //\r
1569 Uhc->PciIo->Attributes (\r
1570 Uhc->PciIo,\r
1571 EfiPciIoAttributeOperationSet,\r
1572 Uhc->OriginalPciAttributes,\r
1573 NULL\r
1574 );\r
1575\r
1576 UhciFreeDev (Uhc);\r
1577}\r
1578\r
1579/**\r
1580 One notified function to stop the Host Controller when gBS->ExitBootServices() called.\r
1581\r
1582 @param Event Pointer to this event\r
1583 @param Context Event hanlder private data\r
1584\r
1585**/\r
1586VOID\r
1587EFIAPI\r
1588UhcExitBootService (\r
1589 EFI_EVENT Event,\r
1590 VOID *Context\r
1591 )\r
1592{\r
1593 USB_HC_DEV *Uhc;\r
1594\r
1595 Uhc = (USB_HC_DEV *) Context;\r
1596\r
1597 //\r
1598 // Stop the Host Controller\r
1599 //\r
1600 UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT);\r
1601\r
1602 return;\r
1603}\r
1604\r
1605/**\r
1606 Starting the Usb UHCI Driver.\r
1607\r
1608 @param This Protocol instance pointer.\r
1609 @param Controller Handle of device to test.\r
1610 @param RemainingDevicePath Not used.\r
1611\r
1612 @retval EFI_SUCCESS This driver supports this device.\r
1613 @retval EFI_UNSUPPORTED This driver does not support this device.\r
1614 @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.\r
1615 EFI_OUT_OF_RESOURCES- Failed due to resource shortage.\r
1616\r
1617**/\r
1618EFI_STATUS\r
1619EFIAPI\r
1620UhciDriverBindingStart (\r
1621 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1622 IN EFI_HANDLE Controller,\r
1623 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
1624 )\r
1625{\r
1626 EFI_STATUS Status;\r
1627 EFI_PCI_IO_PROTOCOL *PciIo;\r
1628 USB_HC_DEV *Uhc;\r
1629 UINT64 Supports;\r
1630 UINT64 OriginalPciAttributes;\r
1631 BOOLEAN PciAttributesSaved;\r
1632\r
1633 //\r
1634 // Open PCIIO, then enable the EHC device and turn off emulation\r
1635 //\r
1636 Uhc = NULL;\r
1637 Status = gBS->OpenProtocol (\r
1638 Controller,\r
1639 &gEfiPciIoProtocolGuid,\r
1640 (VOID **) &PciIo,\r
1641 This->DriverBindingHandle,\r
1642 Controller,\r
1643 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1644 );\r
1645\r
1646 if (EFI_ERROR (Status)) {\r
1647 return Status;\r
1648 }\r
1649\r
1650 PciAttributesSaved = FALSE;\r
1651 //\r
1652 // Save original PCI attributes\r
1653 //\r
1654 Status = PciIo->Attributes (\r
1655 PciIo,\r
1656 EfiPciIoAttributeOperationGet,\r
1657 0,\r
1658 &OriginalPciAttributes\r
1659 );\r
1660\r
1661 if (EFI_ERROR (Status)) {\r
1662 goto CLOSE_PCIIO;\r
1663 }\r
1664 PciAttributesSaved = TRUE;\r
1665\r
1666 //\r
1667 // Robustnesss improvement such as for UoL\r
1668 // Default is not required.\r
1669 //\r
1670 if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) {\r
1671 UhciTurnOffUsbEmulation (PciIo);\r
1672 }\r
1673\r
1674 Status = PciIo->Attributes (\r
1675 PciIo,\r
1676 EfiPciIoAttributeOperationSupported,\r
1677 0,\r
1678 &Supports\r
1679 );\r
1680 if (!EFI_ERROR (Status)) {\r
1681 Supports &= EFI_PCI_DEVICE_ENABLE;\r
1682 Status = PciIo->Attributes (\r
1683 PciIo,\r
1684 EfiPciIoAttributeOperationEnable,\r
1685 Supports,\r
1686 NULL\r
1687 );\r
1688 }\r
1689\r
1690 if (EFI_ERROR (Status)) {\r
1691 goto CLOSE_PCIIO;\r
1692 }\r
1693\r
1694 Uhc = UhciAllocateDev (PciIo, OriginalPciAttributes);\r
1695\r
1696 if (Uhc == NULL) {\r
1697 Status = EFI_OUT_OF_RESOURCES;\r
1698 goto CLOSE_PCIIO;\r
1699 }\r
1700\r
1701 //\r
1702 // Allocate and Init Host Controller's Frame List Entry\r
1703 //\r
1704 Status = UhciInitFrameList (Uhc);\r
1705\r
1706 if (EFI_ERROR (Status)) {\r
1707 Status = EFI_OUT_OF_RESOURCES;\r
1708 goto FREE_UHC;\r
1709 }\r
1710\r
1711 Status = gBS->SetTimer (\r
1712 Uhc->AsyncIntMonitor,\r
1713 TimerPeriodic,\r
1714 UHC_ASYNC_POLL_INTERVAL\r
1715 );\r
1716\r
1717 if (EFI_ERROR (Status)) {\r
1718 goto FREE_UHC;\r
1719 }\r
1720\r
1721 //\r
1722 // Install USB2_HC_PROTOCOL\r
1723 //\r
1724 Status = gBS->InstallMultipleProtocolInterfaces (\r
1725 &Controller,\r
1726 &gEfiUsb2HcProtocolGuid,\r
1727 &Uhc->Usb2Hc,\r
1728 NULL\r
1729 );\r
1730\r
1731 if (EFI_ERROR (Status)) {\r
1732 goto FREE_UHC;\r
1733 }\r
1734\r
1735 //\r
1736 // Create event to stop the HC when exit boot service.\r
1737 //\r
1738 Status = gBS->CreateEventEx (\r
1739 EVT_NOTIFY_SIGNAL,\r
1740 TPL_NOTIFY,\r
1741 UhcExitBootService,\r
1742 Uhc,\r
1743 &gEfiEventExitBootServicesGuid,\r
1744 &Uhc->ExitBootServiceEvent\r
1745 );\r
1746 if (EFI_ERROR (Status)) {\r
1747 goto UNINSTALL_USBHC;\r
1748 }\r
1749\r
1750 //\r
1751 // Install the component name protocol\r
1752 //\r
1753 Uhc->CtrlNameTable = NULL;\r
1754\r
1755 AddUnicodeString2 (\r
1756 "eng",\r
1757 gUhciComponentName.SupportedLanguages,\r
1758 &Uhc->CtrlNameTable,\r
1759 L"Usb Universal Host Controller",\r
1760 TRUE\r
1761 );\r
1762 AddUnicodeString2 (\r
1763 "en",\r
1764 gUhciComponentName2.SupportedLanguages,\r
1765 &Uhc->CtrlNameTable,\r
1766 L"Usb Universal Host Controller",\r
1767 FALSE\r
1768 );\r
1769\r
1770\r
1771 //\r
1772 // Start the UHCI hardware, also set its reclamation point to 64 bytes\r
1773 //\r
1774 UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, USBCMD_RS | USBCMD_MAXP);\r
1775\r
1776 return EFI_SUCCESS;\r
1777 \r
1778UNINSTALL_USBHC:\r
1779 gBS->UninstallMultipleProtocolInterfaces (\r
1780 Controller,\r
1781 &gEfiUsb2HcProtocolGuid,\r
1782 &Uhc->Usb2Hc,\r
1783 NULL\r
1784 );\r
1785\r
1786FREE_UHC:\r
1787 UhciFreeDev (Uhc);\r
1788\r
1789CLOSE_PCIIO:\r
1790 if (PciAttributesSaved) {\r
1791 //\r
1792 // Restore original PCI attributes\r
1793 //\r
1794 PciIo->Attributes (\r
1795 PciIo,\r
1796 EfiPciIoAttributeOperationSet,\r
1797 OriginalPciAttributes,\r
1798 NULL\r
1799 );\r
1800 }\r
1801\r
1802 gBS->CloseProtocol (\r
1803 Controller,\r
1804 &gEfiPciIoProtocolGuid,\r
1805 This->DriverBindingHandle,\r
1806 Controller\r
1807 );\r
1808\r
1809 return Status;\r
1810}\r
1811\r
1812\r
1813/**\r
1814 Stop this driver on ControllerHandle. Support stoping any child handles\r
1815 created by this driver.\r
1816\r
1817 @param This Protocol instance pointer.\r
1818 @param Controller Handle of device to stop driver on.\r
1819 @param NumberOfChildren Number of Children in the ChildHandleBuffer.\r
1820 @param ChildHandleBuffer List of handles for the children we need to stop.\r
1821\r
1822 @return EFI_SUCCESS\r
1823 @return others\r
1824\r
1825**/\r
1826EFI_STATUS\r
1827EFIAPI\r
1828UhciDriverBindingStop (\r
1829 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1830 IN EFI_HANDLE Controller,\r
1831 IN UINTN NumberOfChildren,\r
1832 IN EFI_HANDLE *ChildHandleBuffer\r
1833 )\r
1834{\r
1835 EFI_USB2_HC_PROTOCOL *Usb2Hc;\r
1836 EFI_STATUS Status;\r
1837\r
1838 Status = gBS->OpenProtocol (\r
1839 Controller,\r
1840 &gEfiUsb2HcProtocolGuid,\r
1841 (VOID **) &Usb2Hc,\r
1842 This->DriverBindingHandle,\r
1843 Controller,\r
1844 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1845 );\r
1846\r
1847 //\r
1848 // Test whether the Controller handler passed in is a valid\r
1849 // Usb controller handle that should be supported, if not,\r
1850 // return the error status directly\r
1851 //\r
1852 if (EFI_ERROR (Status)) {\r
1853 return Status;\r
1854 }\r
1855\r
1856 UhciCleanDevUp (Controller, Usb2Hc);\r
1857\r
1858 gBS->CloseProtocol (\r
1859 Controller,\r
1860 &gEfiPciIoProtocolGuid,\r
1861 This->DriverBindingHandle,\r
1862 Controller\r
1863 );\r
1864\r
1865 return EFI_SUCCESS;\r
1866}\r
1867\r