]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Bus/Pci/UhciDxe/Uhci.c
Update the copyright notice format
[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 - 2010, Intel Corporation. All rights reserved.<BR>\r
6This 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 (UINT8*)Request,\r
711 RequestPhy,\r
712 (UINT8*)Data,\r
713 DataPhy,\r
714 TransferDataLength,\r
715 (UINT8) MaximumPacketLength,\r
716 IsSlowDevice\r
717 );\r
718\r
719 if (TDs == NULL) {\r
720 Status = EFI_OUT_OF_RESOURCES;\r
721 goto UNMAP_DATA;\r
722 }\r
723\r
724 //\r
725 // According to the speed of the end point, link\r
726 // the TD to corrosponding queue head, then check\r
727 // the execution result\r
728 //\r
729 UhciLinkTdToQh (Uhc, Uhc->CtrlQh, TDs);\r
730 Status = UhciExecuteTransfer (Uhc, Uhc->CtrlQh, TDs, TimeOut, IsSlowDevice, &QhResult);\r
731 UhciUnlinkTdFromQh (Uhc->CtrlQh, TDs);\r
732\r
733 Uhc->PciIo->Flush (Uhc->PciIo);\r
734\r
735 *TransferResult = QhResult.Result;\r
736\r
737 if (DataLength != NULL) {\r
738 *DataLength = QhResult.Complete;\r
739 }\r
740\r
741 UhciDestoryTds (Uhc, TDs);\r
742\r
743UNMAP_DATA:\r
744 Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
745 Uhc->PciIo->Unmap (Uhc->PciIo, RequestMap);\r
746\r
747ON_EXIT:\r
748 gBS->RestoreTPL (OldTpl);\r
749 return Status;\r
750}\r
751\r
752\r
753/**\r
754 Submits bulk transfer to a bulk endpoint of a USB device.\r
755\r
756 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
757 @param DeviceAddress Target device address.\r
758 @param EndPointAddress Endpoint number and direction.\r
759 @param DeviceSpeed Device speed.\r
760 @param MaximumPacketLength Maximum packet size of the target endpoint.\r
761 @param DataBuffersNumber Number of data buffers prepared for the transfer.\r
762 @param Data Array of pointers to the buffers of data.\r
763 @param DataLength On input, size of the data buffer, On output,\r
764 actually transferred data size.\r
765 @param DataToggle On input, data toggle to use; On output, next data toggle.\r
766 @param TimeOut Maximum time out, in microseconds.\r
767 @param Translator A pointr to the transaction translator data.\r
768 @param TransferResult Variable to receive transfer result.\r
769\r
770 @return EFI_SUCCESS The bulk transfer was completed successfully.\r
771 @return EFI_OUT_OF_RESOURCES Failed due to lack of resource.\r
772 @return EFI_INVALID_PARAMETER Some parameters are invalid.\r
773 @return EFI_TIMEOUT Failed due to timeout.\r
774 @return EFI_DEVICE_ERROR Failed due to host controller or device error.\r
775\r
776**/\r
777EFI_STATUS\r
778EFIAPI\r
779Uhci2BulkTransfer (\r
780 IN EFI_USB2_HC_PROTOCOL *This,\r
781 IN UINT8 DeviceAddress,\r
782 IN UINT8 EndPointAddress,\r
783 IN UINT8 DeviceSpeed,\r
784 IN UINTN MaximumPacketLength,\r
785 IN UINT8 DataBuffersNumber,\r
786 IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],\r
787 IN OUT UINTN *DataLength,\r
788 IN OUT UINT8 *DataToggle,\r
789 IN UINTN TimeOut,\r
790 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
791 OUT UINT32 *TransferResult\r
792 )\r
793{\r
794 EFI_USB_DATA_DIRECTION Direction;\r
795 EFI_TPL OldTpl;\r
796 USB_HC_DEV *Uhc;\r
797 UHCI_TD_SW *TDs;\r
798 UHCI_QH_SW *BulkQh;\r
799 UHCI_QH_RESULT QhResult;\r
800 EFI_STATUS Status;\r
801 UINT8 PktId;\r
802 UINT8 *DataPhy;\r
803 VOID *DataMap;\r
804\r
805 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
806 DataPhy = NULL;\r
807 DataMap = NULL;\r
808\r
809 if (DeviceSpeed == EFI_USB_SPEED_LOW) {\r
810 return EFI_INVALID_PARAMETER;\r
811 }\r
812\r
813 if ((DataLength == NULL) || (*DataLength == 0) || (Data == NULL) || (TransferResult == NULL)) {\r
814 return EFI_INVALID_PARAMETER;\r
815 }\r
816\r
817 if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
818 return EFI_INVALID_PARAMETER;\r
819 }\r
820\r
821 if ((MaximumPacketLength != 8) && (MaximumPacketLength != 16) &&\r
822 (MaximumPacketLength != 32) && (MaximumPacketLength != 64)) {\r
823 return EFI_INVALID_PARAMETER;\r
824 }\r
825\r
826 *TransferResult = EFI_USB_ERR_SYSTEM;\r
827 Status = EFI_OUT_OF_RESOURCES;\r
828\r
829 //\r
830 // If has errors that cause host controller halt,\r
831 // then return EFI_DEVICE_ERROR directly.\r
832 //\r
833 UhciAckAllInterrupt (Uhc);\r
834\r
835 if (!UhciIsHcWorking (Uhc->PciIo)) {\r
836 return EFI_DEVICE_ERROR;\r
837 }\r
838\r
839 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
840\r
841 //\r
842 // Map the source data buffer for bus master access,\r
843 // then create a list of TDs\r
844 //\r
845 if ((EndPointAddress & 0x80) != 0) {\r
846 Direction = EfiUsbDataIn;\r
847 } else {\r
848 Direction = EfiUsbDataOut;\r
849 }\r
850\r
851 Status = UhciMapUserData (Uhc, Direction, *Data, DataLength, &PktId, &DataPhy, &DataMap);\r
852\r
853 if (EFI_ERROR (Status)) {\r
854 goto ON_EXIT;\r
855 }\r
856\r
857 Status = EFI_OUT_OF_RESOURCES;\r
858 TDs = UhciCreateBulkOrIntTds (\r
859 Uhc,\r
860 DeviceAddress,\r
861 EndPointAddress,\r
862 PktId,\r
863 (UINT8 *)*Data,\r
864 DataPhy,\r
865 *DataLength,\r
866 DataToggle,\r
867 (UINT8) MaximumPacketLength,\r
868 FALSE\r
869 );\r
870\r
871 if (TDs == NULL) {\r
872 Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
873 goto ON_EXIT;\r
874 }\r
875\r
876\r
877 //\r
878 // Link the TDs to bulk queue head. According to the platfore\r
879 // defintion of UHCI_NO_BW_RECLAMATION, BulkQh is either configured\r
880 // to do full speed bandwidth reclamation or not.\r
881 //\r
882 BulkQh = Uhc->BulkQh;\r
883\r
884 UhciLinkTdToQh (Uhc, BulkQh, TDs);\r
885 Status = UhciExecuteTransfer (Uhc, BulkQh, TDs, TimeOut, FALSE, &QhResult);\r
886 UhciUnlinkTdFromQh (BulkQh, TDs);\r
887\r
888 Uhc->PciIo->Flush (Uhc->PciIo);\r
889\r
890 *TransferResult = QhResult.Result;\r
891 *DataToggle = QhResult.NextToggle;\r
892 *DataLength = QhResult.Complete;\r
893\r
894 UhciDestoryTds (Uhc, TDs);\r
895 Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
896\r
897ON_EXIT:\r
898 gBS->RestoreTPL (OldTpl);\r
899 return Status;\r
900}\r
901\r
902\r
903/**\r
904 Submits an asynchronous interrupt transfer to an\r
905 interrupt endpoint of a USB device according to UEFI 2.0 spec.\r
906\r
907 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
908 @param DeviceAddress Target device address.\r
909 @param EndPointAddress Endpoint number and direction.\r
910 @param DeviceSpeed Device speed.\r
911 @param MaximumPacketLength Maximum packet size of the target endpoint.\r
912 @param IsNewTransfer If TRUE, submit a new transfer, if FALSE cancel old transfer.\r
913 @param DataToggle On input, data toggle to use; On output, next data toggle.\r
914 @param PollingInterval Interrupt poll rate in milliseconds.\r
915 @param DataLength On input, size of the data buffer, On output,\r
916 actually transferred data size.\r
917 @param Translator A pointr to the transaction translator data.\r
918 @param CallBackFunction Function to call periodically.\r
919 @param Context User context.\r
920\r
921 @return EFI_SUCCESS Transfer was submitted.\r
922 @return EFI_INVALID_PARAMETER Some parameters are invalid.\r
923 @return EFI_OUT_OF_RESOURCES Failed due to a lack of resources.\r
924 @return EFI_DEVICE_ERROR Can't read register.\r
925\r
926**/\r
927EFI_STATUS\r
928EFIAPI\r
929Uhci2AsyncInterruptTransfer (\r
930 IN EFI_USB2_HC_PROTOCOL *This,\r
931 IN UINT8 DeviceAddress,\r
932 IN UINT8 EndPointAddress,\r
933 IN UINT8 DeviceSpeed,\r
934 IN UINTN MaximumPacketLength,\r
935 IN BOOLEAN IsNewTransfer,\r
936 IN OUT UINT8 *DataToggle,\r
937 IN UINTN PollingInterval,\r
938 IN UINTN DataLength,\r
939 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
940 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,\r
941 IN VOID *Context\r
942 )\r
943{\r
944 USB_HC_DEV *Uhc;\r
945 BOOLEAN IsSlowDevice;\r
946 UHCI_QH_SW *Qh;\r
947 UHCI_TD_SW *IntTds;\r
948 EFI_TPL OldTpl;\r
949 EFI_STATUS Status;\r
950 UINT8 *DataPtr;\r
951 UINT8 *DataPhy;\r
952 UINT8 PktId;\r
953\r
954 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
955 Qh = NULL;\r
956 IntTds = NULL;\r
957 DataPtr = NULL;\r
958 DataPhy = NULL;\r
959\r
960 IsSlowDevice = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);\r
961\r
962 if ((EndPointAddress & 0x80) == 0) {\r
963 return EFI_INVALID_PARAMETER;\r
964 }\r
965\r
966 //\r
967 // Delete Async interrupt transfer request\r
968 //\r
969 if (!IsNewTransfer) {\r
970 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
971 Status = UhciRemoveAsyncReq (Uhc, DeviceAddress, EndPointAddress, DataToggle);\r
972\r
973 gBS->RestoreTPL (OldTpl);\r
974 return Status;\r
975 }\r
976\r
977 if (PollingInterval < 1 || PollingInterval > 255) {\r
978 return EFI_INVALID_PARAMETER;\r
979 }\r
980\r
981 if (DataLength == 0) {\r
982 return EFI_INVALID_PARAMETER;\r
983 }\r
984\r
985 if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
986 return EFI_INVALID_PARAMETER;\r
987 }\r
988\r
989 //\r
990 // If has errors that cause host controller halt,\r
991 // then return EFI_DEVICE_ERROR directly.\r
992 //\r
993 UhciAckAllInterrupt (Uhc);\r
994\r
995 if (!UhciIsHcWorking (Uhc->PciIo)) {\r
996 return EFI_DEVICE_ERROR;\r
997 }\r
998\r
999 if ((EndPointAddress & 0x80) == 0) {\r
1000 PktId = OUTPUT_PACKET_ID;\r
1001 } else {\r
1002 PktId = INPUT_PACKET_ID;\r
1003 }\r
1004\r
1005 //\r
1006 // Allocate and map source data buffer for bus master access.\r
1007 //\r
1008 DataPtr = UsbHcAllocateMem (Uhc->MemPool, DataLength);\r
1009\r
1010 if (DataPtr == NULL) {\r
1011 return EFI_OUT_OF_RESOURCES;\r
1012 }\r
1013\r
1014 DataPhy = (UINT8 *) (UINTN) UsbHcGetPciAddressForHostMem (Uhc->MemPool, DataPtr, DataLength);\r
1015\r
1016 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
1017\r
1018 Qh = UhciCreateQh (Uhc, PollingInterval);\r
1019\r
1020 if (Qh == NULL) {\r
1021 Status = EFI_OUT_OF_RESOURCES;\r
1022 goto FREE_DATA;\r
1023 }\r
1024\r
1025 IntTds = UhciCreateBulkOrIntTds (\r
1026 Uhc,\r
1027 DeviceAddress,\r
1028 EndPointAddress,\r
1029 PktId,\r
1030 DataPtr,\r
1031 DataPhy,\r
1032 DataLength,\r
1033 DataToggle,\r
1034 (UINT8) MaximumPacketLength,\r
1035 IsSlowDevice\r
1036 );\r
1037\r
1038 if (IntTds == NULL) {\r
1039 Status = EFI_OUT_OF_RESOURCES;\r
1040 goto DESTORY_QH;\r
1041 }\r
1042\r
1043 UhciLinkTdToQh (Uhc, Qh, IntTds);\r
1044\r
1045 //\r
1046 // Save QH-TD structures to async Interrupt transfer list,\r
1047 // for monitor interrupt transfer execution routine use.\r
1048 //\r
1049 Status = UhciCreateAsyncReq (\r
1050 Uhc,\r
1051 Qh,\r
1052 IntTds,\r
1053 DeviceAddress,\r
1054 EndPointAddress,\r
1055 DataLength,\r
1056 PollingInterval,\r
1057 DataPtr,\r
1058 CallBackFunction,\r
1059 Context,\r
1060 IsSlowDevice\r
1061 );\r
1062\r
1063 if (EFI_ERROR (Status)) {\r
1064 goto DESTORY_QH;\r
1065 }\r
1066\r
1067 UhciLinkQhToFrameList (Uhc, Qh);\r
1068\r
1069 gBS->RestoreTPL (OldTpl);\r
1070 return EFI_SUCCESS;\r
1071\r
1072DESTORY_QH:\r
1073 UsbHcFreeMem (Uhc->MemPool, Qh, sizeof (UHCI_QH_SW));\r
1074\r
1075FREE_DATA:\r
1076 UsbHcFreeMem (Uhc->MemPool, DataPtr, DataLength);\r
1077 Uhc->PciIo->Flush (Uhc->PciIo);\r
1078\r
1079 gBS->RestoreTPL (OldTpl);\r
1080 return Status;\r
1081}\r
1082\r
1083/**\r
1084 Submits synchronous interrupt transfer to an interrupt endpoint\r
1085 of a USB device according to UEFI 2.0 spec.\r
1086\r
1087\r
1088 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1089 @param DeviceAddress Target device address.\r
1090 @param EndPointAddress Endpoint number and direction.\r
1091 @param DeviceSpeed Device speed.\r
1092 @param MaximumPacketLength Maximum packet size of the target endpoint.\r
1093 @param Data Array of pointers to the buffers of data.\r
1094 @param DataLength On input, size of the data buffer, On output,\r
1095 actually transferred data size.\r
1096 @param DataToggle On input, data toggle to use; On output, next data toggle.\r
1097 @param TimeOut Maximum time out, in microseconds.\r
1098 @param Translator A pointr to the transaction translator data.\r
1099 @param TransferResult Variable to receive transfer result.\r
1100\r
1101 @return EFI_SUCCESS The transfer was completed successfully.\r
1102 @return EFI_OUT_OF_RESOURCES Failed due to lack of resource.\r
1103 @return EFI_INVALID_PARAMETER Some parameters are invalid.\r
1104 @return EFI_TIMEOUT Failed due to timeout.\r
1105 @return EFI_DEVICE_ERROR Failed due to host controller or device error.\r
1106\r
1107**/\r
1108EFI_STATUS\r
1109EFIAPI\r
1110Uhci2SyncInterruptTransfer (\r
1111 IN EFI_USB2_HC_PROTOCOL *This,\r
1112 IN UINT8 DeviceAddress,\r
1113 IN UINT8 EndPointAddress,\r
1114 IN UINT8 DeviceSpeed,\r
1115 IN UINTN MaximumPacketLength,\r
1116 IN OUT VOID *Data,\r
1117 IN OUT UINTN *DataLength,\r
1118 IN OUT UINT8 *DataToggle,\r
1119 IN UINTN TimeOut,\r
1120 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1121 OUT UINT32 *TransferResult\r
1122 )\r
1123{\r
1124 EFI_STATUS Status;\r
1125 USB_HC_DEV *Uhc;\r
1126 UHCI_TD_SW *TDs;\r
1127 UHCI_QH_RESULT QhResult;\r
1128 EFI_TPL OldTpl;\r
1129 UINT8 *DataPhy;\r
1130 VOID *DataMap;\r
1131 UINT8 PktId;\r
1132 BOOLEAN IsSlowDevice;\r
1133\r
1134 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
1135 DataPhy = NULL;\r
1136 DataMap = NULL;\r
1137 TDs = NULL;\r
1138\r
1139 if (DeviceSpeed == EFI_USB_SPEED_HIGH) {\r
1140 return EFI_INVALID_PARAMETER;\r
1141 }\r
1142\r
1143 IsSlowDevice = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);\r
1144\r
1145 if ((DataLength == NULL) || (Data == NULL) || (TransferResult == NULL)) {\r
1146 return EFI_INVALID_PARAMETER;\r
1147 }\r
1148\r
1149 if ((EndPointAddress & 0x80) == 0) {\r
1150 return EFI_INVALID_PARAMETER;\r
1151 }\r
1152\r
1153 if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
1154 return EFI_INVALID_PARAMETER;\r
1155 }\r
1156\r
1157 if ((*DataLength == 0) || (MaximumPacketLength > 64)) {\r
1158 return EFI_INVALID_PARAMETER;\r
1159 }\r
1160\r
1161 if (IsSlowDevice && (MaximumPacketLength > 8)) {\r
1162 return EFI_INVALID_PARAMETER;\r
1163 }\r
1164\r
1165 *TransferResult = EFI_USB_ERR_SYSTEM;\r
1166 Status = EFI_DEVICE_ERROR;\r
1167\r
1168\r
1169 UhciAckAllInterrupt (Uhc);\r
1170\r
1171 if (!UhciIsHcWorking (Uhc->PciIo)) {\r
1172 return Status;\r
1173 }\r
1174\r
1175 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
1176\r
1177 //\r
1178 // Map the source data buffer for bus master access.\r
1179 // Create Tds list, then link it to the UHC's interrupt list\r
1180 //\r
1181 Status = UhciMapUserData (\r
1182 Uhc,\r
1183 EfiUsbDataIn,\r
1184 Data,\r
1185 DataLength,\r
1186 &PktId,\r
1187 &DataPhy,\r
1188 &DataMap\r
1189 );\r
1190\r
1191 if (EFI_ERROR (Status)) {\r
1192 goto ON_EXIT;\r
1193 }\r
1194\r
1195 TDs = UhciCreateBulkOrIntTds (\r
1196 Uhc,\r
1197 DeviceAddress,\r
1198 EndPointAddress,\r
1199 PktId,\r
1200 (UINT8 *)Data,\r
1201 DataPhy,\r
1202 *DataLength,\r
1203 DataToggle,\r
1204 (UINT8) MaximumPacketLength,\r
1205 IsSlowDevice\r
1206 );\r
1207\r
1208 if (TDs == NULL) {\r
1209 Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
1210\r
1211 Status = EFI_OUT_OF_RESOURCES;\r
1212 goto ON_EXIT;\r
1213 }\r
1214\r
1215\r
1216 UhciLinkTdToQh (Uhc, Uhc->SyncIntQh, TDs);\r
1217\r
1218 Status = UhciExecuteTransfer (Uhc, Uhc->SyncIntQh, TDs, TimeOut, IsSlowDevice, &QhResult);\r
1219\r
1220 UhciUnlinkTdFromQh (Uhc->SyncIntQh, TDs);\r
1221 Uhc->PciIo->Flush (Uhc->PciIo);\r
1222\r
1223 *TransferResult = QhResult.Result;\r
1224 *DataToggle = QhResult.NextToggle;\r
1225 *DataLength = QhResult.Complete;\r
1226\r
1227 UhciDestoryTds (Uhc, TDs);\r
1228 Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
1229\r
1230ON_EXIT:\r
1231 gBS->RestoreTPL (OldTpl);\r
1232 return Status;\r
1233}\r
1234\r
1235\r
1236/**\r
1237 Submits isochronous transfer to a target USB device according to UEFI 2.0 spec.\r
1238\r
1239 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1240 @param DeviceAddress Target device address.\r
1241 @param EndPointAddress Endpoint number and direction.\r
1242 @param DeviceSpeed Device speed.\r
1243 @param MaximumPacketLength Maximum packet size of the target endpoint.\r
1244 @param DataBuffersNumber Number of data buffers prepared for the transfer.\r
1245 @param Data Array of pointers to the buffers of data.\r
1246 @param DataLength On input, size of the data buffer, On output,\r
1247 actually transferred data size.\r
1248 @param Translator A pointr to the transaction translator data.\r
1249 @param TransferResult Variable to receive transfer result.\r
1250\r
1251 @return EFI_UNSUPPORTED\r
1252\r
1253**/\r
1254EFI_STATUS\r
1255EFIAPI\r
1256Uhci2IsochronousTransfer (\r
1257 IN EFI_USB2_HC_PROTOCOL *This,\r
1258 IN UINT8 DeviceAddress,\r
1259 IN UINT8 EndPointAddress,\r
1260 IN UINT8 DeviceSpeed,\r
1261 IN UINTN MaximumPacketLength,\r
1262 IN UINT8 DataBuffersNumber,\r
1263 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
1264 IN UINTN DataLength,\r
1265 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1266 OUT UINT32 *TransferResult\r
1267 )\r
1268{\r
1269 return EFI_UNSUPPORTED;\r
1270}\r
1271\r
1272\r
1273/**\r
1274 Submits Async isochronous transfer to a target USB device according to UEFI 2.0 spec.\r
1275\r
1276 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1277 @param DeviceAddress Target device address.\r
1278 @param EndPointAddress Endpoint number and direction.\r
1279 @param DeviceSpeed Device speed.\r
1280 @param MaximumPacketLength Maximum packet size of the target endpoint.\r
1281 @param DataBuffersNumber Number of data buffers prepared for the transfer.\r
1282 @param Data Array of pointers to the buffers of data.\r
1283 @param DataLength On input, size of the data buffer, On output,\r
1284 actually transferred data size.\r
1285 @param Translator A pointr to the transaction translator data.\r
1286 @param IsochronousCallBack Function to call when the transfer complete.\r
1287 @param Context Pass to the call back function as parameter.\r
1288\r
1289 @return EFI_UNSUPPORTED\r
1290\r
1291**/\r
1292EFI_STATUS\r
1293EFIAPI\r
1294Uhci2AsyncIsochronousTransfer (\r
1295 IN EFI_USB2_HC_PROTOCOL *This,\r
1296 IN UINT8 DeviceAddress,\r
1297 IN UINT8 EndPointAddress,\r
1298 IN UINT8 DeviceSpeed,\r
1299 IN UINTN MaximumPacketLength,\r
1300 IN UINT8 DataBuffersNumber,\r
1301 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
1302 IN UINTN DataLength,\r
1303 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1304 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,\r
1305 IN VOID *Context\r
1306 )\r
1307{\r
1308 return EFI_UNSUPPORTED;\r
1309}\r
1310\r
1311/**\r
1312 Entry point for EFI drivers.\r
1313\r
1314 @param ImageHandle EFI_HANDLE.\r
1315 @param SystemTable EFI_SYSTEM_TABLE.\r
1316\r
1317 @retval EFI_SUCCESS Driver is successfully loaded.\r
1318 @return Others Failed.\r
1319\r
1320**/\r
1321EFI_STATUS\r
1322EFIAPI\r
1323UhciDriverEntryPoint (\r
1324 IN EFI_HANDLE ImageHandle,\r
1325 IN EFI_SYSTEM_TABLE *SystemTable\r
1326 )\r
1327{\r
1328 return EfiLibInstallDriverBindingComponentName2 (\r
1329 ImageHandle,\r
1330 SystemTable,\r
1331 &gUhciDriverBinding,\r
1332 ImageHandle,\r
1333 &gUhciComponentName,\r
1334 &gUhciComponentName2\r
1335 );\r
1336}\r
1337\r
1338\r
1339/**\r
1340 Test to see if this driver supports ControllerHandle. Any\r
1341 ControllerHandle that has UsbHcProtocol installed will be supported.\r
1342\r
1343 @param This Protocol instance pointer.\r
1344 @param Controller Handle of device to test.\r
1345 @param RemainingDevicePath Not used.\r
1346\r
1347 @return EFI_SUCCESS This driver supports this device.\r
1348 @return EFI_UNSUPPORTED This driver does not support this device.\r
1349\r
1350**/\r
1351EFI_STATUS\r
1352EFIAPI\r
1353UhciDriverBindingSupported (\r
1354 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1355 IN EFI_HANDLE Controller,\r
1356 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
1357 )\r
1358{\r
1359 EFI_STATUS OpenStatus;\r
1360 EFI_STATUS Status;\r
1361 EFI_PCI_IO_PROTOCOL *PciIo;\r
1362 USB_CLASSC UsbClassCReg;\r
1363\r
1364 //\r
1365 // Test whether there is PCI IO Protocol attached on the controller handle.\r
1366 //\r
1367 OpenStatus = gBS->OpenProtocol (\r
1368 Controller,\r
1369 &gEfiPciIoProtocolGuid,\r
1370 (VOID **) &PciIo,\r
1371 This->DriverBindingHandle,\r
1372 Controller,\r
1373 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1374 );\r
1375\r
1376 if (EFI_ERROR (OpenStatus)) {\r
1377 return OpenStatus;\r
1378 }\r
1379\r
1380 Status = PciIo->Pci.Read (\r
1381 PciIo,\r
1382 EfiPciIoWidthUint8,\r
1383 PCI_CLASSCODE_OFFSET,\r
1384 sizeof (USB_CLASSC) / sizeof (UINT8),\r
1385 &UsbClassCReg\r
1386 );\r
1387\r
1388 if (EFI_ERROR (Status)) {\r
1389 Status = EFI_UNSUPPORTED;\r
1390 goto ON_EXIT;\r
1391 }\r
1392\r
1393 //\r
1394 // Test whether the controller belongs to UHCI type\r
1395 //\r
1396 if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||\r
1397 (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||\r
1398 (UsbClassCReg.ProgInterface != PCI_IF_UHCI)\r
1399 ) {\r
1400\r
1401 Status = EFI_UNSUPPORTED;\r
1402 }\r
1403\r
1404ON_EXIT:\r
1405 gBS->CloseProtocol (\r
1406 Controller,\r
1407 &gEfiPciIoProtocolGuid,\r
1408 This->DriverBindingHandle,\r
1409 Controller\r
1410 );\r
1411\r
1412 return Status;\r
1413\r
1414}\r
1415\r
1416\r
1417/**\r
1418 Allocate and initialize the empty UHCI device.\r
1419\r
1420 @param PciIo The PCIIO to use.\r
1421 @param OriginalPciAttributes The original PCI attributes.\r
1422\r
1423 @return Allocated UHCI device. If err, return NULL.\r
1424\r
1425**/\r
1426USB_HC_DEV *\r
1427UhciAllocateDev (\r
1428 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
1429 IN UINT64 OriginalPciAttributes\r
1430 )\r
1431{\r
1432 USB_HC_DEV *Uhc;\r
1433 EFI_STATUS Status;\r
1434\r
1435 Uhc = AllocateZeroPool (sizeof (USB_HC_DEV));\r
1436\r
1437 if (Uhc == NULL) {\r
1438 return NULL;\r
1439 }\r
1440\r
1441 //\r
1442 // This driver supports both USB_HC_PROTOCOL and USB2_HC_PROTOCOL.\r
1443 // USB_HC_PROTOCOL is for EFI 1.1 backward compability.\r
1444 //\r
1445 Uhc->Signature = USB_HC_DEV_SIGNATURE;\r
1446 Uhc->Usb2Hc.GetCapability = Uhci2GetCapability;\r
1447 Uhc->Usb2Hc.Reset = Uhci2Reset;\r
1448 Uhc->Usb2Hc.GetState = Uhci2GetState;\r
1449 Uhc->Usb2Hc.SetState = Uhci2SetState;\r
1450 Uhc->Usb2Hc.ControlTransfer = Uhci2ControlTransfer;\r
1451 Uhc->Usb2Hc.BulkTransfer = Uhci2BulkTransfer;\r
1452 Uhc->Usb2Hc.AsyncInterruptTransfer = Uhci2AsyncInterruptTransfer;\r
1453 Uhc->Usb2Hc.SyncInterruptTransfer = Uhci2SyncInterruptTransfer;\r
1454 Uhc->Usb2Hc.IsochronousTransfer = Uhci2IsochronousTransfer;\r
1455 Uhc->Usb2Hc.AsyncIsochronousTransfer = Uhci2AsyncIsochronousTransfer;\r
1456 Uhc->Usb2Hc.GetRootHubPortStatus = Uhci2GetRootHubPortStatus;\r
1457 Uhc->Usb2Hc.SetRootHubPortFeature = Uhci2SetRootHubPortFeature;\r
1458 Uhc->Usb2Hc.ClearRootHubPortFeature = Uhci2ClearRootHubPortFeature;\r
1459 Uhc->Usb2Hc.MajorRevision = 0x1;\r
1460 Uhc->Usb2Hc.MinorRevision = 0x1;\r
1461\r
1462 Uhc->PciIo = PciIo;\r
1463 Uhc->OriginalPciAttributes = OriginalPciAttributes;\r
1464 Uhc->MemPool = UsbHcInitMemPool (PciIo, TRUE, 0);\r
1465\r
1466 if (Uhc->MemPool == NULL) {\r
1467 Status = EFI_OUT_OF_RESOURCES;\r
1468 goto ON_ERROR;\r
1469 }\r
1470\r
1471 InitializeListHead (&Uhc->AsyncIntList);\r
1472\r
1473 Status = gBS->CreateEvent (\r
1474 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
1475 TPL_CALLBACK,\r
1476 UhciMonitorAsyncReqList,\r
1477 Uhc,\r
1478 &Uhc->AsyncIntMonitor\r
1479 );\r
1480\r
1481 if (EFI_ERROR (Status)) {\r
1482 UsbHcFreeMemPool (Uhc->MemPool);\r
1483 goto ON_ERROR;\r
1484 }\r
1485\r
1486 return Uhc;\r
1487\r
1488ON_ERROR:\r
1489 FreePool (Uhc);\r
1490 return NULL;\r
1491}\r
1492\r
1493\r
1494/**\r
1495 Free the UHCI device and release its associated resources.\r
1496\r
1497 @param Uhc The UHCI device to release.\r
1498\r
1499**/\r
1500VOID\r
1501UhciFreeDev (\r
1502 IN USB_HC_DEV *Uhc\r
1503 )\r
1504{\r
1505 if (Uhc->AsyncIntMonitor != NULL) {\r
1506 gBS->CloseEvent (Uhc->AsyncIntMonitor);\r
1507 }\r
1508\r
1509 if (Uhc->ExitBootServiceEvent != NULL) {\r
1510 gBS->CloseEvent (Uhc->ExitBootServiceEvent);\r
1511 }\r
1512 \r
1513 if (Uhc->MemPool != NULL) {\r
1514 UsbHcFreeMemPool (Uhc->MemPool);\r
1515 }\r
1516\r
1517 if (Uhc->CtrlNameTable != NULL) {\r
1518 FreeUnicodeStringTable (Uhc->CtrlNameTable);\r
1519 }\r
1520\r
1521 FreePool (Uhc);\r
1522}\r
1523\r
1524\r
1525/**\r
1526 Uninstall all Uhci Interface.\r
1527\r
1528 @param Controller Controller handle.\r
1529 @param This Protocol instance pointer.\r
1530\r
1531**/\r
1532VOID\r
1533UhciCleanDevUp (\r
1534 IN EFI_HANDLE Controller,\r
1535 IN EFI_USB2_HC_PROTOCOL *This\r
1536 )\r
1537{\r
1538 USB_HC_DEV *Uhc;\r
1539\r
1540 //\r
1541 // Uninstall the USB_HC and USB_HC2 protocol, then disable the controller\r
1542 //\r
1543 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
1544 UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT);\r
1545\r
1546 gBS->UninstallProtocolInterface (\r
1547 Controller,\r
1548 &gEfiUsb2HcProtocolGuid,\r
1549 &Uhc->Usb2Hc\r
1550 );\r
1551\r
1552 UhciFreeAllAsyncReq (Uhc);\r
1553 UhciDestoryFrameList (Uhc);\r
1554\r
1555 //\r
1556 // Restore original PCI attributes\r
1557 //\r
1558 Uhc->PciIo->Attributes (\r
1559 Uhc->PciIo,\r
1560 EfiPciIoAttributeOperationSet,\r
1561 Uhc->OriginalPciAttributes,\r
1562 NULL\r
1563 );\r
1564\r
1565 UhciFreeDev (Uhc);\r
1566}\r
1567\r
1568/**\r
1569 One notified function to stop the Host Controller when gBS->ExitBootServices() called.\r
1570\r
1571 @param Event Pointer to this event\r
1572 @param Context Event hanlder private data\r
1573\r
1574**/\r
1575VOID\r
1576EFIAPI\r
1577UhcExitBootService (\r
1578 EFI_EVENT Event,\r
1579 VOID *Context\r
1580 )\r
1581{\r
1582 USB_HC_DEV *Uhc;\r
1583\r
1584 Uhc = (USB_HC_DEV *) Context;\r
1585\r
1586 //\r
1587 // Stop the Host Controller\r
1588 //\r
1589 UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT);\r
1590\r
1591 return;\r
1592}\r
1593\r
1594/**\r
1595 Starting the Usb UHCI Driver.\r
1596\r
1597 @param This Protocol instance pointer.\r
1598 @param Controller Handle of device to test.\r
1599 @param RemainingDevicePath Not used.\r
1600\r
1601 @retval EFI_SUCCESS This driver supports this device.\r
1602 @retval EFI_UNSUPPORTED This driver does not support this device.\r
1603 @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.\r
1604 EFI_OUT_OF_RESOURCES- Failed due to resource shortage.\r
1605\r
1606**/\r
1607EFI_STATUS\r
1608EFIAPI\r
1609UhciDriverBindingStart (\r
1610 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1611 IN EFI_HANDLE Controller,\r
1612 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
1613 )\r
1614{\r
1615 EFI_STATUS Status;\r
1616 EFI_PCI_IO_PROTOCOL *PciIo;\r
1617 USB_HC_DEV *Uhc;\r
1618 UINT64 Supports;\r
1619 UINT64 OriginalPciAttributes;\r
1620 BOOLEAN PciAttributesSaved;\r
1621\r
1622 //\r
1623 // Open PCIIO, then enable the EHC device and turn off emulation\r
1624 //\r
1625 Uhc = NULL;\r
1626 Status = gBS->OpenProtocol (\r
1627 Controller,\r
1628 &gEfiPciIoProtocolGuid,\r
1629 (VOID **) &PciIo,\r
1630 This->DriverBindingHandle,\r
1631 Controller,\r
1632 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1633 );\r
1634\r
1635 if (EFI_ERROR (Status)) {\r
1636 return Status;\r
1637 }\r
1638\r
1639 PciAttributesSaved = FALSE;\r
1640 //\r
1641 // Save original PCI attributes\r
1642 //\r
1643 Status = PciIo->Attributes (\r
1644 PciIo,\r
1645 EfiPciIoAttributeOperationGet,\r
1646 0,\r
1647 &OriginalPciAttributes\r
1648 );\r
1649\r
1650 if (EFI_ERROR (Status)) {\r
1651 goto CLOSE_PCIIO;\r
1652 }\r
1653 PciAttributesSaved = TRUE;\r
1654\r
1655 //\r
1656 // Robustnesss improvement such as for UoL\r
1657 // Default is not required.\r
1658 //\r
1659 if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) {\r
1660 UhciTurnOffUsbEmulation (PciIo);\r
1661 }\r
1662\r
1663 Status = PciIo->Attributes (\r
1664 PciIo,\r
1665 EfiPciIoAttributeOperationSupported,\r
1666 0,\r
1667 &Supports\r
1668 );\r
1669 if (!EFI_ERROR (Status)) {\r
1670 Supports &= EFI_PCI_DEVICE_ENABLE;\r
1671 Status = PciIo->Attributes (\r
1672 PciIo,\r
1673 EfiPciIoAttributeOperationEnable,\r
1674 Supports,\r
1675 NULL\r
1676 );\r
1677 }\r
1678\r
1679 if (EFI_ERROR (Status)) {\r
1680 goto CLOSE_PCIIO;\r
1681 }\r
1682\r
1683 Uhc = UhciAllocateDev (PciIo, OriginalPciAttributes);\r
1684\r
1685 if (Uhc == NULL) {\r
1686 Status = EFI_OUT_OF_RESOURCES;\r
1687 goto CLOSE_PCIIO;\r
1688 }\r
1689\r
1690 //\r
1691 // Allocate and Init Host Controller's Frame List Entry\r
1692 //\r
1693 Status = UhciInitFrameList (Uhc);\r
1694\r
1695 if (EFI_ERROR (Status)) {\r
1696 Status = EFI_OUT_OF_RESOURCES;\r
1697 goto FREE_UHC;\r
1698 }\r
1699\r
1700 Status = gBS->SetTimer (\r
1701 Uhc->AsyncIntMonitor,\r
1702 TimerPeriodic,\r
1703 UHC_ASYNC_POLL_INTERVAL\r
1704 );\r
1705\r
1706 if (EFI_ERROR (Status)) {\r
1707 goto FREE_UHC;\r
1708 }\r
1709\r
1710 //\r
1711 // Install USB2_HC_PROTOCOL\r
1712 //\r
1713 Status = gBS->InstallMultipleProtocolInterfaces (\r
1714 &Controller,\r
1715 &gEfiUsb2HcProtocolGuid,\r
1716 &Uhc->Usb2Hc,\r
1717 NULL\r
1718 );\r
1719\r
1720 if (EFI_ERROR (Status)) {\r
1721 goto FREE_UHC;\r
1722 }\r
1723\r
1724 //\r
1725 // Create event to stop the HC when exit boot service.\r
1726 //\r
1727 Status = gBS->CreateEventEx (\r
1728 EVT_NOTIFY_SIGNAL,\r
1729 TPL_NOTIFY,\r
1730 UhcExitBootService,\r
1731 Uhc,\r
1732 &gEfiEventExitBootServicesGuid,\r
1733 &Uhc->ExitBootServiceEvent\r
1734 );\r
1735 if (EFI_ERROR (Status)) {\r
1736 goto UNINSTALL_USBHC;\r
1737 }\r
1738\r
1739 //\r
1740 // Install the component name protocol\r
1741 //\r
1742 Uhc->CtrlNameTable = NULL;\r
1743\r
1744 AddUnicodeString2 (\r
1745 "eng",\r
1746 gUhciComponentName.SupportedLanguages,\r
1747 &Uhc->CtrlNameTable,\r
1748 L"Usb Universal Host Controller",\r
1749 TRUE\r
1750 );\r
1751 AddUnicodeString2 (\r
1752 "en",\r
1753 gUhciComponentName2.SupportedLanguages,\r
1754 &Uhc->CtrlNameTable,\r
1755 L"Usb Universal Host Controller",\r
1756 FALSE\r
1757 );\r
1758\r
1759\r
1760 //\r
1761 // Start the UHCI hardware, also set its reclamation point to 64 bytes\r
1762 //\r
1763 UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, USBCMD_RS | USBCMD_MAXP);\r
1764\r
1765 return EFI_SUCCESS;\r
1766 \r
1767UNINSTALL_USBHC:\r
1768 gBS->UninstallMultipleProtocolInterfaces (\r
1769 Controller,\r
1770 &gEfiUsb2HcProtocolGuid,\r
1771 &Uhc->Usb2Hc,\r
1772 NULL\r
1773 );\r
1774\r
1775FREE_UHC:\r
1776 UhciFreeDev (Uhc);\r
1777\r
1778CLOSE_PCIIO:\r
1779 if (PciAttributesSaved) {\r
1780 //\r
1781 // Restore original PCI attributes\r
1782 //\r
1783 PciIo->Attributes (\r
1784 PciIo,\r
1785 EfiPciIoAttributeOperationSet,\r
1786 OriginalPciAttributes,\r
1787 NULL\r
1788 );\r
1789 }\r
1790\r
1791 gBS->CloseProtocol (\r
1792 Controller,\r
1793 &gEfiPciIoProtocolGuid,\r
1794 This->DriverBindingHandle,\r
1795 Controller\r
1796 );\r
1797\r
1798 return Status;\r
1799}\r
1800\r
1801\r
1802/**\r
1803 Stop this driver on ControllerHandle. Support stoping any child handles\r
1804 created by this driver.\r
1805\r
1806 @param This Protocol instance pointer.\r
1807 @param Controller Handle of device to stop driver on.\r
1808 @param NumberOfChildren Number of Children in the ChildHandleBuffer.\r
1809 @param ChildHandleBuffer List of handles for the children we need to stop.\r
1810\r
1811 @return EFI_SUCCESS\r
1812 @return others\r
1813\r
1814**/\r
1815EFI_STATUS\r
1816EFIAPI\r
1817UhciDriverBindingStop (\r
1818 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1819 IN EFI_HANDLE Controller,\r
1820 IN UINTN NumberOfChildren,\r
1821 IN EFI_HANDLE *ChildHandleBuffer\r
1822 )\r
1823{\r
1824 EFI_USB2_HC_PROTOCOL *Usb2Hc;\r
1825 EFI_STATUS Status;\r
1826\r
1827 Status = gBS->OpenProtocol (\r
1828 Controller,\r
1829 &gEfiUsb2HcProtocolGuid,\r
1830 (VOID **) &Usb2Hc,\r
1831 This->DriverBindingHandle,\r
1832 Controller,\r
1833 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1834 );\r
1835\r
1836 //\r
1837 // Test whether the Controller handler passed in is a valid\r
1838 // Usb controller handle that should be supported, if not,\r
1839 // return the error status directly\r
1840 //\r
1841 if (EFI_ERROR (Status)) {\r
1842 return Status;\r
1843 }\r
1844\r
1845 UhciCleanDevUp (Controller, Usb2Hc);\r
1846\r
1847 gBS->CloseProtocol (\r
1848 Controller,\r
1849 &gEfiPciIoProtocolGuid,\r
1850 This->DriverBindingHandle,\r
1851 Controller\r
1852 );\r
1853\r
1854 return EFI_SUCCESS;\r
1855}\r
1856\r