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