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