]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/UhciDxe/Uhci.c
MdeModulePkg/Bus: Fix typos in comments
[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
c5fcd77f 5Copyright (c) 2004 - 2015, 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
363badad 599 Submits control transfer to a target USB device according to UEFI 2.0 spec.\r
ab6495ea 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
913cb9dc 1160 if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
1161 return EFI_INVALID_PARAMETER;\r
1162 }\r
1163\r
1164 if ((*DataLength == 0) || (MaximumPacketLength > 64)) {\r
1165 return EFI_INVALID_PARAMETER;\r
1166 }\r
1167\r
1168 if (IsSlowDevice && (MaximumPacketLength > 8)) {\r
1169 return EFI_INVALID_PARAMETER;\r
1170 }\r
1171\r
1172 *TransferResult = EFI_USB_ERR_SYSTEM;\r
1173 Status = EFI_DEVICE_ERROR;\r
1174\r
1175\r
1176 UhciAckAllInterrupt (Uhc);\r
1177\r
1178 if (!UhciIsHcWorking (Uhc->PciIo)) {\r
1179 return Status;\r
1180 }\r
1181\r
1182 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
1183\r
1184 //\r
1185 // Map the source data buffer for bus master access.\r
1186 // Create Tds list, then link it to the UHC's interrupt list\r
1187 //\r
1188 Status = UhciMapUserData (\r
1189 Uhc,\r
1190 EfiUsbDataIn,\r
1191 Data,\r
1192 DataLength,\r
1193 &PktId,\r
1194 &DataPhy,\r
1195 &DataMap\r
1196 );\r
1197\r
1198 if (EFI_ERROR (Status)) {\r
1199 goto ON_EXIT;\r
1200 }\r
1201\r
1202 TDs = UhciCreateBulkOrIntTds (\r
1203 Uhc,\r
1204 DeviceAddress,\r
1205 EndPointAddress,\r
1206 PktId,\r
3af875e2 1207 (UINT8 *)Data,\r
913cb9dc 1208 DataPhy,\r
1209 *DataLength,\r
1210 DataToggle,\r
ea5632e5 1211 (UINT8) MaximumPacketLength,\r
913cb9dc 1212 IsSlowDevice\r
1213 );\r
1214\r
1215 if (TDs == NULL) {\r
1216 Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
1217\r
1218 Status = EFI_OUT_OF_RESOURCES;\r
1219 goto ON_EXIT;\r
1220 }\r
1221\r
1222\r
3af875e2 1223 UhciLinkTdToQh (Uhc, Uhc->SyncIntQh, TDs);\r
913cb9dc 1224\r
1225 Status = UhciExecuteTransfer (Uhc, Uhc->SyncIntQh, TDs, TimeOut, IsSlowDevice, &QhResult);\r
1226\r
1227 UhciUnlinkTdFromQh (Uhc->SyncIntQh, TDs);\r
1228 Uhc->PciIo->Flush (Uhc->PciIo);\r
1229\r
1230 *TransferResult = QhResult.Result;\r
1231 *DataToggle = QhResult.NextToggle;\r
1232 *DataLength = QhResult.Complete;\r
1233\r
1234 UhciDestoryTds (Uhc, TDs);\r
1235 Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
1236\r
1237ON_EXIT:\r
1238 gBS->RestoreTPL (OldTpl);\r
1239 return Status;\r
1240}\r
1241\r
1242\r
1243/**\r
ea5632e5 1244 Submits isochronous transfer to a target USB device according to UEFI 2.0 spec.\r
913cb9dc 1245\r
ab6495ea 1246 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1247 @param DeviceAddress Target device address.\r
1248 @param EndPointAddress Endpoint number and direction.\r
1249 @param DeviceSpeed Device speed.\r
1250 @param MaximumPacketLength Maximum packet size of the target endpoint.\r
1251 @param DataBuffersNumber Number of data buffers prepared for the transfer.\r
1252 @param Data Array of pointers to the buffers of data.\r
1253 @param DataLength On input, size of the data buffer, On output,\r
1254 actually transferred data size.\r
1255 @param Translator A pointr to the transaction translator data.\r
1256 @param TransferResult Variable to receive transfer result.\r
913cb9dc 1257\r
1258 @return EFI_UNSUPPORTED\r
1259\r
1260**/\r
913cb9dc 1261EFI_STATUS\r
1262EFIAPI\r
ea5632e5 1263Uhci2IsochronousTransfer (\r
1264 IN EFI_USB2_HC_PROTOCOL *This,\r
1265 IN UINT8 DeviceAddress,\r
1266 IN UINT8 EndPointAddress,\r
1267 IN UINT8 DeviceSpeed,\r
1268 IN UINTN MaximumPacketLength,\r
1269 IN UINT8 DataBuffersNumber,\r
1270 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
1271 IN UINTN DataLength,\r
1272 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1273 OUT UINT32 *TransferResult\r
913cb9dc 1274 )\r
1275{\r
1276 return EFI_UNSUPPORTED;\r
1277}\r
1278\r
1279\r
1280/**\r
ea5632e5 1281 Submits Async isochronous transfer to a target USB device according to UEFI 2.0 spec.\r
913cb9dc 1282\r
ab6495ea 1283 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1284 @param DeviceAddress Target device address.\r
1285 @param EndPointAddress Endpoint number and direction.\r
1286 @param DeviceSpeed Device speed.\r
1287 @param MaximumPacketLength Maximum packet size of the target endpoint.\r
1288 @param DataBuffersNumber Number of data buffers prepared for the transfer.\r
1289 @param Data Array of pointers to the buffers of data.\r
1290 @param DataLength On input, size of the data buffer, On output,\r
1291 actually transferred data size.\r
1292 @param Translator A pointr to the transaction translator data.\r
1293 @param IsochronousCallBack Function to call when the transfer complete.\r
1294 @param Context Pass to the call back function as parameter.\r
913cb9dc 1295\r
1296 @return EFI_UNSUPPORTED\r
1297\r
1298**/\r
913cb9dc 1299EFI_STATUS\r
1300EFIAPI\r
ea5632e5 1301Uhci2AsyncIsochronousTransfer (\r
1302 IN EFI_USB2_HC_PROTOCOL *This,\r
1303 IN UINT8 DeviceAddress,\r
1304 IN UINT8 EndPointAddress,\r
1305 IN UINT8 DeviceSpeed,\r
1306 IN UINTN MaximumPacketLength,\r
1307 IN UINT8 DataBuffersNumber,\r
1308 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
1309 IN UINTN DataLength,\r
1310 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1311 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,\r
1312 IN VOID *Context\r
913cb9dc 1313 )\r
1314{\r
1315 return EFI_UNSUPPORTED;\r
1316}\r
1317\r
ab6495ea 1318/**\r
1319 Entry point for EFI drivers.\r
1320\r
1321 @param ImageHandle EFI_HANDLE.\r
1322 @param SystemTable EFI_SYSTEM_TABLE.\r
1323\r
1324 @retval EFI_SUCCESS Driver is successfully loaded.\r
1325 @return Others Failed.\r
1326\r
1327**/\r
913cb9dc 1328EFI_STATUS\r
1329EFIAPI\r
1330UhciDriverEntryPoint (\r
1331 IN EFI_HANDLE ImageHandle,\r
1332 IN EFI_SYSTEM_TABLE *SystemTable\r
1333 )\r
913cb9dc 1334{\r
f527bce3 1335 return EfiLibInstallDriverBindingComponentName2 (\r
913cb9dc 1336 ImageHandle,\r
1337 SystemTable,\r
1338 &gUhciDriverBinding,\r
1339 ImageHandle,\r
1340 &gUhciComponentName,\r
f527bce3 1341 &gUhciComponentName2\r
913cb9dc 1342 );\r
1343}\r
1344\r
1345\r
1346/**\r
1347 Test to see if this driver supports ControllerHandle. Any\r
1348 ControllerHandle that has UsbHcProtocol installed will be supported.\r
1349\r
1350 @param This Protocol instance pointer.\r
ab6495ea 1351 @param Controller Handle of device to test.\r
1352 @param RemainingDevicePath Not used.\r
913cb9dc 1353\r
ab6495ea 1354 @return EFI_SUCCESS This driver supports this device.\r
1355 @return EFI_UNSUPPORTED This driver does not support this device.\r
913cb9dc 1356\r
1357**/\r
1358EFI_STATUS\r
1359EFIAPI\r
1360UhciDriverBindingSupported (\r
1361 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1362 IN EFI_HANDLE Controller,\r
1363 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
1364 )\r
1365{\r
1366 EFI_STATUS OpenStatus;\r
1367 EFI_STATUS Status;\r
1368 EFI_PCI_IO_PROTOCOL *PciIo;\r
1369 USB_CLASSC UsbClassCReg;\r
1370\r
1371 //\r
1372 // Test whether there is PCI IO Protocol attached on the controller handle.\r
1373 //\r
1374 OpenStatus = gBS->OpenProtocol (\r
1375 Controller,\r
1376 &gEfiPciIoProtocolGuid,\r
c52fa98c 1377 (VOID **) &PciIo,\r
913cb9dc 1378 This->DriverBindingHandle,\r
1379 Controller,\r
1380 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1381 );\r
1382\r
1383 if (EFI_ERROR (OpenStatus)) {\r
1384 return OpenStatus;\r
1385 }\r
1386\r
1387 Status = PciIo->Pci.Read (\r
1388 PciIo,\r
1389 EfiPciIoWidthUint8,\r
a261044c 1390 PCI_CLASSCODE_OFFSET,\r
913cb9dc 1391 sizeof (USB_CLASSC) / sizeof (UINT8),\r
1392 &UsbClassCReg\r
1393 );\r
1394\r
1395 if (EFI_ERROR (Status)) {\r
1396 Status = EFI_UNSUPPORTED;\r
1397 goto ON_EXIT;\r
1398 }\r
1399\r
1400 //\r
1401 // Test whether the controller belongs to UHCI type\r
1402 //\r
1403 if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||\r
1404 (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||\r
1ccdbf2a 1405 (UsbClassCReg.ProgInterface != PCI_IF_UHCI)\r
913cb9dc 1406 ) {\r
1407\r
1408 Status = EFI_UNSUPPORTED;\r
1409 }\r
1410\r
1411ON_EXIT:\r
1412 gBS->CloseProtocol (\r
1413 Controller,\r
1414 &gEfiPciIoProtocolGuid,\r
1415 This->DriverBindingHandle,\r
1416 Controller\r
1417 );\r
1418\r
1419 return Status;\r
1420\r
1421}\r
1422\r
1423\r
1424/**\r
ab6495ea 1425 Allocate and initialize the empty UHCI device.\r
913cb9dc 1426\r
ab6495ea 1427 @param PciIo The PCIIO to use.\r
44c56530 1428 @param DevicePath The device path of host controller.\r
ab6495ea 1429 @param OriginalPciAttributes The original PCI attributes.\r
913cb9dc 1430\r
ab6495ea 1431 @return Allocated UHCI device. If err, return NULL.\r
913cb9dc 1432\r
1433**/\r
913cb9dc 1434USB_HC_DEV *\r
1435UhciAllocateDev (\r
37623a5c 1436 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
1437 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
1438 IN UINT64 OriginalPciAttributes\r
913cb9dc 1439 )\r
1440{\r
1441 USB_HC_DEV *Uhc;\r
1442 EFI_STATUS Status;\r
1443\r
1444 Uhc = AllocateZeroPool (sizeof (USB_HC_DEV));\r
1445\r
1446 if (Uhc == NULL) {\r
1447 return NULL;\r
1448 }\r
1449\r
1450 //\r
1451 // This driver supports both USB_HC_PROTOCOL and USB2_HC_PROTOCOL.\r
1452 // USB_HC_PROTOCOL is for EFI 1.1 backward compability.\r
1453 //\r
1454 Uhc->Signature = USB_HC_DEV_SIGNATURE;\r
913cb9dc 1455 Uhc->Usb2Hc.GetCapability = Uhci2GetCapability;\r
1456 Uhc->Usb2Hc.Reset = Uhci2Reset;\r
1457 Uhc->Usb2Hc.GetState = Uhci2GetState;\r
1458 Uhc->Usb2Hc.SetState = Uhci2SetState;\r
1459 Uhc->Usb2Hc.ControlTransfer = Uhci2ControlTransfer;\r
1460 Uhc->Usb2Hc.BulkTransfer = Uhci2BulkTransfer;\r
1461 Uhc->Usb2Hc.AsyncInterruptTransfer = Uhci2AsyncInterruptTransfer;\r
1462 Uhc->Usb2Hc.SyncInterruptTransfer = Uhci2SyncInterruptTransfer;\r
1463 Uhc->Usb2Hc.IsochronousTransfer = Uhci2IsochronousTransfer;\r
1464 Uhc->Usb2Hc.AsyncIsochronousTransfer = Uhci2AsyncIsochronousTransfer;\r
1465 Uhc->Usb2Hc.GetRootHubPortStatus = Uhci2GetRootHubPortStatus;\r
1466 Uhc->Usb2Hc.SetRootHubPortFeature = Uhci2SetRootHubPortFeature;\r
1467 Uhc->Usb2Hc.ClearRootHubPortFeature = Uhci2ClearRootHubPortFeature;\r
1468 Uhc->Usb2Hc.MajorRevision = 0x1;\r
1469 Uhc->Usb2Hc.MinorRevision = 0x1;\r
1470\r
68246fa8 1471 Uhc->PciIo = PciIo;\r
37623a5c 1472 Uhc->DevicePath = DevicePath;\r
68246fa8 1473 Uhc->OriginalPciAttributes = OriginalPciAttributes;\r
1474 Uhc->MemPool = UsbHcInitMemPool (PciIo, TRUE, 0);\r
913cb9dc 1475\r
1476 if (Uhc->MemPool == NULL) {\r
1477 Status = EFI_OUT_OF_RESOURCES;\r
1478 goto ON_ERROR;\r
1479 }\r
1480\r
1481 InitializeListHead (&Uhc->AsyncIntList);\r
1482\r
1483 Status = gBS->CreateEvent (\r
1484 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
3cf6450e 1485 TPL_NOTIFY,\r
913cb9dc 1486 UhciMonitorAsyncReqList,\r
1487 Uhc,\r
1488 &Uhc->AsyncIntMonitor\r
1489 );\r
1490\r
1491 if (EFI_ERROR (Status)) {\r
1492 UsbHcFreeMemPool (Uhc->MemPool);\r
1493 goto ON_ERROR;\r
1494 }\r
1495\r
1496 return Uhc;\r
1497\r
1498ON_ERROR:\r
7351070b 1499 FreePool (Uhc);\r
913cb9dc 1500 return NULL;\r
1501}\r
1502\r
1503\r
1504/**\r
ab6495ea 1505 Free the UHCI device and release its associated resources.\r
913cb9dc 1506\r
ab6495ea 1507 @param Uhc The UHCI device to release.\r
913cb9dc 1508\r
913cb9dc 1509**/\r
913cb9dc 1510VOID\r
1511UhciFreeDev (\r
1512 IN USB_HC_DEV *Uhc\r
1513 )\r
1514{\r
1515 if (Uhc->AsyncIntMonitor != NULL) {\r
1516 gBS->CloseEvent (Uhc->AsyncIntMonitor);\r
1517 }\r
1518\r
0428a6cb 1519 if (Uhc->ExitBootServiceEvent != NULL) {\r
1520 gBS->CloseEvent (Uhc->ExitBootServiceEvent);\r
1521 }\r
1522 \r
913cb9dc 1523 if (Uhc->MemPool != NULL) {\r
1524 UsbHcFreeMemPool (Uhc->MemPool);\r
1525 }\r
1526\r
ab6495ea 1527 if (Uhc->CtrlNameTable != NULL) {\r
913cb9dc 1528 FreeUnicodeStringTable (Uhc->CtrlNameTable);\r
1529 }\r
1530\r
7351070b 1531 FreePool (Uhc);\r
913cb9dc 1532}\r
1533\r
1534\r
1535/**\r
ab6495ea 1536 Uninstall all Uhci Interface.\r
913cb9dc 1537\r
ab6495ea 1538 @param Controller Controller handle.\r
913cb9dc 1539 @param This Protocol instance pointer.\r
1540\r
913cb9dc 1541**/\r
913cb9dc 1542VOID\r
1543UhciCleanDevUp (\r
ea5632e5 1544 IN EFI_HANDLE Controller,\r
1545 IN EFI_USB2_HC_PROTOCOL *This\r
913cb9dc 1546 )\r
1547{\r
1548 USB_HC_DEV *Uhc;\r
0f58371b 1549 EFI_STATUS Status;\r
913cb9dc 1550\r
1551 //\r
1552 // Uninstall the USB_HC and USB_HC2 protocol, then disable the controller\r
1553 //\r
ea5632e5 1554 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
913cb9dc 1555\r
913cb9dc 1556\r
0f58371b
FT
1557 Status = gBS->UninstallProtocolInterface (\r
1558 Controller,\r
1559 &gEfiUsb2HcProtocolGuid,\r
1560 &Uhc->Usb2Hc\r
1561 );\r
1562 if (EFI_ERROR (Status)) {\r
1563 return ;\r
1564 }\r
1565\r
1566 UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT);\r
913cb9dc 1567 UhciFreeAllAsyncReq (Uhc);\r
1568 UhciDestoryFrameList (Uhc);\r
68246fa8 1569\r
1570 //\r
1571 // Restore original PCI attributes\r
1572 //\r
913cb9dc 1573 Uhc->PciIo->Attributes (\r
68246fa8 1574 Uhc->PciIo,\r
1575 EfiPciIoAttributeOperationSet,\r
1576 Uhc->OriginalPciAttributes,\r
1577 NULL\r
1578 );\r
913cb9dc 1579\r
1580 UhciFreeDev (Uhc);\r
1581}\r
1582\r
0428a6cb 1583/**\r
1584 One notified function to stop the Host Controller when gBS->ExitBootServices() called.\r
1585\r
1586 @param Event Pointer to this event\r
e3644786 1587 @param Context Event handler private data\r
0428a6cb 1588\r
1589**/\r
1590VOID\r
1591EFIAPI\r
1592UhcExitBootService (\r
1593 EFI_EVENT Event,\r
1594 VOID *Context\r
1595 )\r
1596{\r
1597 USB_HC_DEV *Uhc;\r
1598\r
1599 Uhc = (USB_HC_DEV *) Context;\r
1600\r
1601 //\r
1602 // Stop the Host Controller\r
1603 //\r
1604 UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT);\r
1605\r
2dda77a6 1606 //\r
1607 // Reset the Host Controller\r
1608 //\r
1609 UhciSetRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_HCRESET);\r
1610 gBS->Stall (UHC_ROOT_PORT_RECOVERY_STALL);\r
0428a6cb 1611}\r
913cb9dc 1612\r
1613/**\r
ab6495ea 1614 Starting the Usb UHCI Driver.\r
913cb9dc 1615\r
1616 @param This Protocol instance pointer.\r
ab6495ea 1617 @param Controller Handle of device to test.\r
1618 @param RemainingDevicePath Not used.\r
913cb9dc 1619\r
1620 @retval EFI_SUCCESS This driver supports this device.\r
1621 @retval EFI_UNSUPPORTED This driver does not support this device.\r
ab6495ea 1622 @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.\r
1623 EFI_OUT_OF_RESOURCES- Failed due to resource shortage.\r
913cb9dc 1624\r
1625**/\r
1626EFI_STATUS\r
1627EFIAPI\r
1628UhciDriverBindingStart (\r
1629 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1630 IN EFI_HANDLE Controller,\r
1631 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
1632 )\r
1633{\r
1634 EFI_STATUS Status;\r
1635 EFI_PCI_IO_PROTOCOL *PciIo;\r
1636 USB_HC_DEV *Uhc;\r
96f6af14 1637 UINT64 Supports;\r
68246fa8 1638 UINT64 OriginalPciAttributes;\r
6a6d955c 1639 BOOLEAN PciAttributesSaved;\r
37623a5c 1640 EFI_DEVICE_PATH_PROTOCOL *HcDevicePath;\r
913cb9dc 1641\r
1642 //\r
1643 // Open PCIIO, then enable the EHC device and turn off emulation\r
1644 //\r
1645 Uhc = NULL;\r
1646 Status = gBS->OpenProtocol (\r
1647 Controller,\r
1648 &gEfiPciIoProtocolGuid,\r
c52fa98c 1649 (VOID **) &PciIo,\r
913cb9dc 1650 This->DriverBindingHandle,\r
1651 Controller,\r
1652 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1653 );\r
1654\r
1655 if (EFI_ERROR (Status)) {\r
1656 return Status;\r
1657 }\r
1658\r
37623a5c 1659 //\r
1660 // Open Device Path Protocol for on USB host controller\r
1661 //\r
1662 HcDevicePath = NULL;\r
1663 Status = gBS->OpenProtocol (\r
1664 Controller,\r
1665 &gEfiDevicePathProtocolGuid,\r
1666 (VOID **) &HcDevicePath,\r
1667 This->DriverBindingHandle,\r
1668 Controller,\r
1669 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1670 );\r
1671\r
6a6d955c 1672 PciAttributesSaved = FALSE;\r
68246fa8 1673 //\r
1674 // Save original PCI attributes\r
1675 //\r
1676 Status = PciIo->Attributes (\r
1677 PciIo,\r
1678 EfiPciIoAttributeOperationGet,\r
1679 0,\r
1680 &OriginalPciAttributes\r
1681 );\r
1682\r
1683 if (EFI_ERROR (Status)) {\r
6a6d955c 1684 goto CLOSE_PCIIO;\r
68246fa8 1685 }\r
6a6d955c 1686 PciAttributesSaved = TRUE;\r
68246fa8 1687\r
f0a83bb3
LG
1688 //\r
1689 // Robustnesss improvement such as for UoL\r
1690 // Default is not required.\r
1691 //\r
cc582cff 1692 if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) {\r
dd4047a5 1693 UhciTurnOffUsbEmulation (PciIo);\r
1694 }\r
913cb9dc 1695\r
1696 Status = PciIo->Attributes (\r
1697 PciIo,\r
96f6af14
LG
1698 EfiPciIoAttributeOperationSupported,\r
1699 0,\r
1700 &Supports\r
913cb9dc 1701 );\r
96f6af14 1702 if (!EFI_ERROR (Status)) {\r
6e1e5405 1703 Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;\r
96f6af14
LG
1704 Status = PciIo->Attributes (\r
1705 PciIo,\r
1706 EfiPciIoAttributeOperationEnable,\r
1707 Supports,\r
1708 NULL\r
1709 );\r
1710 }\r
913cb9dc 1711\r
1712 if (EFI_ERROR (Status)) {\r
1713 goto CLOSE_PCIIO;\r
1714 }\r
1715\r
37623a5c 1716 Uhc = UhciAllocateDev (PciIo, HcDevicePath, OriginalPciAttributes);\r
913cb9dc 1717\r
1718 if (Uhc == NULL) {\r
1719 Status = EFI_OUT_OF_RESOURCES;\r
1720 goto CLOSE_PCIIO;\r
1721 }\r
1722\r
1723 //\r
1724 // Allocate and Init Host Controller's Frame List Entry\r
1725 //\r
1726 Status = UhciInitFrameList (Uhc);\r
1727\r
1728 if (EFI_ERROR (Status)) {\r
1729 Status = EFI_OUT_OF_RESOURCES;\r
1730 goto FREE_UHC;\r
1731 }\r
1732\r
1733 Status = gBS->SetTimer (\r
1734 Uhc->AsyncIntMonitor,\r
1735 TimerPeriodic,\r
41e8ff27 1736 UHC_ASYNC_POLL_INTERVAL\r
913cb9dc 1737 );\r
1738\r
1739 if (EFI_ERROR (Status)) {\r
1740 goto FREE_UHC;\r
1741 }\r
1742\r
1743 //\r
ea5632e5 1744 // Install USB2_HC_PROTOCOL\r
913cb9dc 1745 //\r
1746 Status = gBS->InstallMultipleProtocolInterfaces (\r
1747 &Controller,\r
913cb9dc 1748 &gEfiUsb2HcProtocolGuid,\r
1749 &Uhc->Usb2Hc,\r
1750 NULL\r
1751 );\r
1752\r
1753 if (EFI_ERROR (Status)) {\r
1754 goto FREE_UHC;\r
1755 }\r
1756\r
0428a6cb 1757 //\r
1758 // Create event to stop the HC when exit boot service.\r
1759 //\r
1760 Status = gBS->CreateEventEx (\r
1761 EVT_NOTIFY_SIGNAL,\r
1762 TPL_NOTIFY,\r
1763 UhcExitBootService,\r
1764 Uhc,\r
1765 &gEfiEventExitBootServicesGuid,\r
1766 &Uhc->ExitBootServiceEvent\r
1767 );\r
1768 if (EFI_ERROR (Status)) {\r
1769 goto UNINSTALL_USBHC;\r
1770 }\r
1771\r
913cb9dc 1772 //\r
1773 // Install the component name protocol\r
1774 //\r
1775 Uhc->CtrlNameTable = NULL;\r
1776\r
f527bce3 1777 AddUnicodeString2 (\r
913cb9dc 1778 "eng",\r
1779 gUhciComponentName.SupportedLanguages,\r
1780 &Uhc->CtrlNameTable,\r
f527bce3 1781 L"Usb Universal Host Controller",\r
1782 TRUE\r
913cb9dc 1783 );\r
f527bce3 1784 AddUnicodeString2 (\r
1785 "en",\r
1786 gUhciComponentName2.SupportedLanguages,\r
1787 &Uhc->CtrlNameTable,\r
1788 L"Usb Universal Host Controller",\r
1789 FALSE\r
1790 );\r
1791\r
913cb9dc 1792\r
1793 //\r
1794 // Start the UHCI hardware, also set its reclamation point to 64 bytes\r
1795 //\r
1796 UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, USBCMD_RS | USBCMD_MAXP);\r
1797\r
1798 return EFI_SUCCESS;\r
0428a6cb 1799 \r
1800UNINSTALL_USBHC:\r
1801 gBS->UninstallMultipleProtocolInterfaces (\r
1802 Controller,\r
1803 &gEfiUsb2HcProtocolGuid,\r
1804 &Uhc->Usb2Hc,\r
1805 NULL\r
1806 );\r
913cb9dc 1807\r
1808FREE_UHC:\r
1809 UhciFreeDev (Uhc);\r
1810\r
1811CLOSE_PCIIO:\r
a92d4e8a 1812 if (PciAttributesSaved) {\r
6a6d955c 1813 //\r
1814 // Restore original PCI attributes\r
1815 //\r
1816 PciIo->Attributes (\r
1817 PciIo,\r
1818 EfiPciIoAttributeOperationSet,\r
1819 OriginalPciAttributes,\r
1820 NULL\r
1821 );\r
1822 }\r
68246fa8 1823\r
913cb9dc 1824 gBS->CloseProtocol (\r
1825 Controller,\r
1826 &gEfiPciIoProtocolGuid,\r
1827 This->DriverBindingHandle,\r
1828 Controller\r
1829 );\r
1830\r
1831 return Status;\r
1832}\r
1833\r
1834\r
1835/**\r
ed356b9e 1836 Stop this driver on ControllerHandle. Support stopping any child handles\r
913cb9dc 1837 created by this driver.\r
1838\r
1839 @param This Protocol instance pointer.\r
ab6495ea 1840 @param Controller Handle of device to stop driver on.\r
1841 @param NumberOfChildren Number of Children in the ChildHandleBuffer.\r
913cb9dc 1842 @param ChildHandleBuffer List of handles for the children we need to stop.\r
1843\r
1844 @return EFI_SUCCESS\r
1845 @return others\r
1846\r
1847**/\r
1848EFI_STATUS\r
1849EFIAPI\r
1850UhciDriverBindingStop (\r
1851 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1852 IN EFI_HANDLE Controller,\r
1853 IN UINTN NumberOfChildren,\r
1854 IN EFI_HANDLE *ChildHandleBuffer\r
1855 )\r
1856{\r
913cb9dc 1857 EFI_USB2_HC_PROTOCOL *Usb2Hc;\r
1858 EFI_STATUS Status;\r
1859\r
ea5632e5 1860 Status = gBS->OpenProtocol (\r
913cb9dc 1861 Controller,\r
1862 &gEfiUsb2HcProtocolGuid,\r
c52fa98c 1863 (VOID **) &Usb2Hc,\r
913cb9dc 1864 This->DriverBindingHandle,\r
1865 Controller,\r
1866 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1867 );\r
1868\r
1869 //\r
1870 // Test whether the Controller handler passed in is a valid\r
1871 // Usb controller handle that should be supported, if not,\r
1872 // return the error status directly\r
1873 //\r
1874 if (EFI_ERROR (Status)) {\r
1875 return Status;\r
1876 }\r
1877\r
ea5632e5 1878 UhciCleanDevUp (Controller, Usb2Hc);\r
913cb9dc 1879\r
1880 gBS->CloseProtocol (\r
1881 Controller,\r
1882 &gEfiPciIoProtocolGuid,\r
1883 This->DriverBindingHandle,\r
1884 Controller\r
1885 );\r
1886\r
1887 return EFI_SUCCESS;\r
1888}\r
1889\r