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