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