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