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