1 /** @file 2 The Ehci controller driver. 3 4 EhciDxe driver is responsible for managing the behavior of EHCI controller. 5 It implements the interfaces of monitoring the status of all ports and transferring 6 Control, Bulk, Interrupt and Isochronous requests to Usb2.0 device. 7 8 Note that EhciDxe driver is enhanced to guarantee that the EHCI controller get attached 9 to the EHCI controller before a UHCI or OHCI driver attaches to the companion UHCI or 10 OHCI controller. This way avoids the control transfer on a shared port between EHCI 11 and companion host controller when UHCI or OHCI gets attached earlier than EHCI and a 12 USB 2.0 device inserts. 13 14 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR> 15 This program and the accompanying materials 16 are licensed and made available under the terms and conditions of the BSD License 17 which accompanies this distribution. The full text of the license may be found at 18 http://opensource.org/licenses/bsd-license.php 19 20 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 21 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 22 23 **/ 24 25 26 #include "Ehci.h" 27 28 // 29 // Two arrays used to translate the EHCI port state (change) 30 // to the UEFI protocol's port state (change). 31 // 32 USB_PORT_STATE_MAP mUsbPortStateMap[] = { 33 {PORTSC_CONN, USB_PORT_STAT_CONNECTION}, 34 {PORTSC_ENABLED, USB_PORT_STAT_ENABLE}, 35 {PORTSC_SUSPEND, USB_PORT_STAT_SUSPEND}, 36 {PORTSC_OVERCUR, USB_PORT_STAT_OVERCURRENT}, 37 {PORTSC_RESET, USB_PORT_STAT_RESET}, 38 {PORTSC_POWER, USB_PORT_STAT_POWER}, 39 {PORTSC_OWNER, USB_PORT_STAT_OWNER} 40 }; 41 42 USB_PORT_STATE_MAP mUsbPortChangeMap[] = { 43 {PORTSC_CONN_CHANGE, USB_PORT_STAT_C_CONNECTION}, 44 {PORTSC_ENABLE_CHANGE, USB_PORT_STAT_C_ENABLE}, 45 {PORTSC_OVERCUR_CHANGE, USB_PORT_STAT_C_OVERCURRENT} 46 }; 47 48 EFI_DRIVER_BINDING_PROTOCOL 49 gEhciDriverBinding = { 50 EhcDriverBindingSupported, 51 EhcDriverBindingStart, 52 EhcDriverBindingStop, 53 0x30, 54 NULL, 55 NULL 56 }; 57 58 /** 59 Retrieves the capability of root hub ports. 60 61 @param This This EFI_USB_HC_PROTOCOL instance. 62 @param MaxSpeed Max speed supported by the controller. 63 @param PortNumber Number of the root hub ports. 64 @param Is64BitCapable Whether the controller supports 64-bit memory 65 addressing. 66 67 @retval EFI_SUCCESS Host controller capability were retrieved successfully. 68 @retval EFI_INVALID_PARAMETER Either of the three capability pointer is NULL. 69 70 **/ 71 EFI_STATUS 72 EFIAPI 73 EhcGetCapability ( 74 IN EFI_USB2_HC_PROTOCOL *This, 75 OUT UINT8 *MaxSpeed, 76 OUT UINT8 *PortNumber, 77 OUT UINT8 *Is64BitCapable 78 ) 79 { 80 USB2_HC_DEV *Ehc; 81 EFI_TPL OldTpl; 82 83 if ((MaxSpeed == NULL) || (PortNumber == NULL) || (Is64BitCapable == NULL)) { 84 return EFI_INVALID_PARAMETER; 85 } 86 87 OldTpl = gBS->RaiseTPL (EHC_TPL); 88 Ehc = EHC_FROM_THIS (This); 89 90 *MaxSpeed = EFI_USB_SPEED_HIGH; 91 *PortNumber = (UINT8) (Ehc->HcStructParams & HCSP_NPORTS); 92 *Is64BitCapable = (UINT8) Ehc->Support64BitDma; 93 94 DEBUG ((EFI_D_INFO, "EhcGetCapability: %d ports, 64 bit %d\n", *PortNumber, *Is64BitCapable)); 95 96 gBS->RestoreTPL (OldTpl); 97 return EFI_SUCCESS; 98 } 99 100 101 /** 102 Provides software reset for the USB host controller. 103 104 @param This This EFI_USB2_HC_PROTOCOL instance. 105 @param Attributes A bit mask of the reset operation to perform. 106 107 @retval EFI_SUCCESS The reset operation succeeded. 108 @retval EFI_INVALID_PARAMETER Attributes is not valid. 109 @retval EFI_UNSUPPOURTED The type of reset specified by Attributes is 110 not currently supported by the host controller. 111 @retval EFI_DEVICE_ERROR Host controller isn't halted to reset. 112 113 **/ 114 EFI_STATUS 115 EFIAPI 116 EhcReset ( 117 IN EFI_USB2_HC_PROTOCOL *This, 118 IN UINT16 Attributes 119 ) 120 { 121 USB2_HC_DEV *Ehc; 122 EFI_TPL OldTpl; 123 EFI_STATUS Status; 124 UINT32 DbgCtrlStatus; 125 126 Ehc = EHC_FROM_THIS (This); 127 128 if (Ehc->DevicePath != NULL) { 129 // 130 // Report Status Code to indicate reset happens 131 // 132 REPORT_STATUS_CODE_WITH_DEVICE_PATH ( 133 EFI_PROGRESS_CODE, 134 (EFI_IO_BUS_USB | EFI_IOB_PC_RESET), 135 Ehc->DevicePath 136 ); 137 } 138 139 OldTpl = gBS->RaiseTPL (EHC_TPL); 140 141 switch (Attributes) { 142 case EFI_USB_HC_RESET_GLOBAL: 143 // 144 // Flow through, same behavior as Host Controller Reset 145 // 146 case EFI_USB_HC_RESET_HOST_CONTROLLER: 147 // 148 // Host Controller must be Halt when Reset it 149 // 150 if (Ehc->DebugPortNum != 0) { 151 DbgCtrlStatus = EhcReadDbgRegister(Ehc, 0); 152 if ((DbgCtrlStatus & (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) == (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) { 153 Status = EFI_SUCCESS; 154 goto ON_EXIT; 155 } 156 } 157 158 if (!EhcIsHalt (Ehc)) { 159 Status = EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT); 160 161 if (EFI_ERROR (Status)) { 162 Status = EFI_DEVICE_ERROR; 163 goto ON_EXIT; 164 } 165 } 166 167 // 168 // Clean up the asynchronous transfers, currently only 169 // interrupt supports asynchronous operation. 170 // 171 EhciDelAllAsyncIntTransfers (Ehc); 172 EhcAckAllInterrupt (Ehc); 173 EhcFreeSched (Ehc); 174 175 Status = EhcResetHC (Ehc, EHC_RESET_TIMEOUT); 176 177 if (EFI_ERROR (Status)) { 178 goto ON_EXIT; 179 } 180 181 Status = EhcInitHC (Ehc); 182 break; 183 184 case EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG: 185 case EFI_USB_HC_RESET_HOST_WITH_DEBUG: 186 Status = EFI_UNSUPPORTED; 187 break; 188 189 default: 190 Status = EFI_INVALID_PARAMETER; 191 } 192 193 ON_EXIT: 194 DEBUG ((EFI_D_INFO, "EhcReset: exit status %r\n", Status)); 195 gBS->RestoreTPL (OldTpl); 196 return Status; 197 } 198 199 200 /** 201 Retrieve the current state of the USB host controller. 202 203 @param This This EFI_USB2_HC_PROTOCOL instance. 204 @param State Variable to return the current host controller 205 state. 206 207 @retval EFI_SUCCESS Host controller state was returned in State. 208 @retval EFI_INVALID_PARAMETER State is NULL. 209 @retval EFI_DEVICE_ERROR An error was encountered while attempting to 210 retrieve the host controller's current state. 211 212 **/ 213 EFI_STATUS 214 EFIAPI 215 EhcGetState ( 216 IN EFI_USB2_HC_PROTOCOL *This, 217 OUT EFI_USB_HC_STATE *State 218 ) 219 { 220 EFI_TPL OldTpl; 221 USB2_HC_DEV *Ehc; 222 223 if (State == NULL) { 224 return EFI_INVALID_PARAMETER; 225 } 226 227 OldTpl = gBS->RaiseTPL (EHC_TPL); 228 Ehc = EHC_FROM_THIS (This); 229 230 if (EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) { 231 *State = EfiUsbHcStateHalt; 232 } else { 233 *State = EfiUsbHcStateOperational; 234 } 235 236 gBS->RestoreTPL (OldTpl); 237 238 DEBUG ((EFI_D_INFO, "EhcGetState: current state %d\n", *State)); 239 return EFI_SUCCESS; 240 } 241 242 243 /** 244 Sets the USB host controller to a specific state. 245 246 @param This This EFI_USB2_HC_PROTOCOL instance. 247 @param State The state of the host controller that will be set. 248 249 @retval EFI_SUCCESS The USB host controller was successfully placed 250 in the state specified by State. 251 @retval EFI_INVALID_PARAMETER State is invalid. 252 @retval EFI_DEVICE_ERROR Failed to set the state due to device error. 253 254 **/ 255 EFI_STATUS 256 EFIAPI 257 EhcSetState ( 258 IN EFI_USB2_HC_PROTOCOL *This, 259 IN EFI_USB_HC_STATE State 260 ) 261 { 262 USB2_HC_DEV *Ehc; 263 EFI_TPL OldTpl; 264 EFI_STATUS Status; 265 EFI_USB_HC_STATE CurState; 266 267 Status = EhcGetState (This, &CurState); 268 269 if (EFI_ERROR (Status)) { 270 return EFI_DEVICE_ERROR; 271 } 272 273 if (CurState == State) { 274 return EFI_SUCCESS; 275 } 276 277 OldTpl = gBS->RaiseTPL (EHC_TPL); 278 Ehc = EHC_FROM_THIS (This); 279 280 switch (State) { 281 case EfiUsbHcStateHalt: 282 Status = EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT); 283 break; 284 285 case EfiUsbHcStateOperational: 286 if (EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_SYS_ERROR)) { 287 Status = EFI_DEVICE_ERROR; 288 break; 289 } 290 291 // 292 // Software must not write a one to this field unless the host controller 293 // is in the Halted state. Doing so will yield undefined results. 294 // refers to Spec[EHCI1.0-2.3.1] 295 // 296 if (!EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) { 297 Status = EFI_DEVICE_ERROR; 298 break; 299 } 300 301 Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT); 302 break; 303 304 case EfiUsbHcStateSuspend: 305 Status = EFI_UNSUPPORTED; 306 break; 307 308 default: 309 Status = EFI_INVALID_PARAMETER; 310 } 311 312 DEBUG ((EFI_D_INFO, "EhcSetState: exit status %r\n", Status)); 313 gBS->RestoreTPL (OldTpl); 314 return Status; 315 } 316 317 318 /** 319 Retrieves the current status of a USB root hub port. 320 321 @param This This EFI_USB2_HC_PROTOCOL instance. 322 @param PortNumber The root hub port to retrieve the state from. 323 This value is zero-based. 324 @param PortStatus Variable to receive the port state. 325 326 @retval EFI_SUCCESS The status of the USB root hub port specified. 327 by PortNumber was returned in PortStatus. 328 @retval EFI_INVALID_PARAMETER PortNumber is invalid. 329 @retval EFI_DEVICE_ERROR Can't read register. 330 331 **/ 332 EFI_STATUS 333 EFIAPI 334 EhcGetRootHubPortStatus ( 335 IN EFI_USB2_HC_PROTOCOL *This, 336 IN UINT8 PortNumber, 337 OUT EFI_USB_PORT_STATUS *PortStatus 338 ) 339 { 340 USB2_HC_DEV *Ehc; 341 EFI_TPL OldTpl; 342 UINT32 Offset; 343 UINT32 State; 344 UINT32 TotalPort; 345 UINTN Index; 346 UINTN MapSize; 347 EFI_STATUS Status; 348 UINT32 DbgCtrlStatus; 349 350 if (PortStatus == NULL) { 351 return EFI_INVALID_PARAMETER; 352 } 353 354 OldTpl = gBS->RaiseTPL (EHC_TPL); 355 356 Ehc = EHC_FROM_THIS (This); 357 Status = EFI_SUCCESS; 358 359 TotalPort = (Ehc->HcStructParams & HCSP_NPORTS); 360 361 if (PortNumber >= TotalPort) { 362 Status = EFI_INVALID_PARAMETER; 363 goto ON_EXIT; 364 } 365 366 Offset = (UINT32) (EHC_PORT_STAT_OFFSET + (4 * PortNumber)); 367 PortStatus->PortStatus = 0; 368 PortStatus->PortChangeStatus = 0; 369 370 if ((Ehc->DebugPortNum != 0) && (PortNumber == (Ehc->DebugPortNum - 1))) { 371 DbgCtrlStatus = EhcReadDbgRegister(Ehc, 0); 372 if ((DbgCtrlStatus & (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) == (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) { 373 goto ON_EXIT; 374 } 375 } 376 377 State = EhcReadOpReg (Ehc, Offset); 378 379 // 380 // Identify device speed. If in K state, it is low speed. 381 // If the port is enabled after reset, the device is of 382 // high speed. The USB bus driver should retrieve the actual 383 // port speed after reset. 384 // 385 if (EHC_BIT_IS_SET (State, PORTSC_LINESTATE_K)) { 386 PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED; 387 388 } else if (EHC_BIT_IS_SET (State, PORTSC_ENABLED)) { 389 PortStatus->PortStatus |= USB_PORT_STAT_HIGH_SPEED; 390 } 391 392 // 393 // Convert the EHCI port/port change state to UEFI status 394 // 395 MapSize = sizeof (mUsbPortStateMap) / sizeof (USB_PORT_STATE_MAP); 396 397 for (Index = 0; Index < MapSize; Index++) { 398 if (EHC_BIT_IS_SET (State, mUsbPortStateMap[Index].HwState)) { 399 PortStatus->PortStatus = (UINT16) (PortStatus->PortStatus | mUsbPortStateMap[Index].UefiState); 400 } 401 } 402 403 MapSize = sizeof (mUsbPortChangeMap) / sizeof (USB_PORT_STATE_MAP); 404 405 for (Index = 0; Index < MapSize; Index++) { 406 if (EHC_BIT_IS_SET (State, mUsbPortChangeMap[Index].HwState)) { 407 PortStatus->PortChangeStatus = (UINT16) (PortStatus->PortChangeStatus | mUsbPortChangeMap[Index].UefiState); 408 } 409 } 410 411 ON_EXIT: 412 gBS->RestoreTPL (OldTpl); 413 return Status; 414 } 415 416 417 /** 418 Sets a feature for the specified root hub port. 419 420 @param This This EFI_USB2_HC_PROTOCOL instance. 421 @param PortNumber Root hub port to set. 422 @param PortFeature Feature to set. 423 424 @retval EFI_SUCCESS The feature specified by PortFeature was set. 425 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid. 426 @retval EFI_DEVICE_ERROR Can't read register. 427 428 **/ 429 EFI_STATUS 430 EFIAPI 431 EhcSetRootHubPortFeature ( 432 IN EFI_USB2_HC_PROTOCOL *This, 433 IN UINT8 PortNumber, 434 IN EFI_USB_PORT_FEATURE PortFeature 435 ) 436 { 437 USB2_HC_DEV *Ehc; 438 EFI_TPL OldTpl; 439 UINT32 Offset; 440 UINT32 State; 441 UINT32 TotalPort; 442 EFI_STATUS Status; 443 444 OldTpl = gBS->RaiseTPL (EHC_TPL); 445 Ehc = EHC_FROM_THIS (This); 446 Status = EFI_SUCCESS; 447 448 TotalPort = (Ehc->HcStructParams & HCSP_NPORTS); 449 450 if (PortNumber >= TotalPort) { 451 Status = EFI_INVALID_PARAMETER; 452 goto ON_EXIT; 453 } 454 455 Offset = (UINT32) (EHC_PORT_STAT_OFFSET + (4 * PortNumber)); 456 State = EhcReadOpReg (Ehc, Offset); 457 458 // 459 // Mask off the port status change bits, these bits are 460 // write clean bit 461 // 462 State &= ~PORTSC_CHANGE_MASK; 463 464 switch (PortFeature) { 465 case EfiUsbPortEnable: 466 // 467 // Sofeware can't set this bit, Port can only be enable by 468 // EHCI as a part of the reset and enable 469 // 470 State |= PORTSC_ENABLED; 471 EhcWriteOpReg (Ehc, Offset, State); 472 break; 473 474 case EfiUsbPortSuspend: 475 State |= PORTSC_SUSPEND; 476 EhcWriteOpReg (Ehc, Offset, State); 477 break; 478 479 case EfiUsbPortReset: 480 // 481 // Make sure Host Controller not halt before reset it 482 // 483 if (EhcIsHalt (Ehc)) { 484 Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT); 485 486 if (EFI_ERROR (Status)) { 487 DEBUG ((EFI_D_INFO, "EhcSetRootHubPortFeature :failed to start HC - %r\n", Status)); 488 break; 489 } 490 } 491 492 // 493 // Set one to PortReset bit must also set zero to PortEnable bit 494 // 495 State |= PORTSC_RESET; 496 State &= ~PORTSC_ENABLED; 497 EhcWriteOpReg (Ehc, Offset, State); 498 break; 499 500 case EfiUsbPortPower: 501 // 502 // Set port power bit when PPC is 1 503 // 504 if ((Ehc->HcCapParams & HCSP_PPC) == HCSP_PPC) { 505 State |= PORTSC_POWER; 506 EhcWriteOpReg (Ehc, Offset, State); 507 } 508 break; 509 510 case EfiUsbPortOwner: 511 State |= PORTSC_OWNER; 512 EhcWriteOpReg (Ehc, Offset, State); 513 break; 514 515 default: 516 Status = EFI_INVALID_PARAMETER; 517 } 518 519 ON_EXIT: 520 DEBUG ((EFI_D_INFO, "EhcSetRootHubPortFeature: exit status %r\n", Status)); 521 522 gBS->RestoreTPL (OldTpl); 523 return Status; 524 } 525 526 527 /** 528 Clears a feature for the specified root hub port. 529 530 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. 531 @param PortNumber Specifies the root hub port whose feature is 532 requested to be cleared. 533 @param PortFeature Indicates the feature selector associated with the 534 feature clear request. 535 536 @retval EFI_SUCCESS The feature specified by PortFeature was cleared 537 for the USB root hub port specified by PortNumber. 538 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid. 539 @retval EFI_DEVICE_ERROR Can't read register. 540 541 **/ 542 EFI_STATUS 543 EFIAPI 544 EhcClearRootHubPortFeature ( 545 IN EFI_USB2_HC_PROTOCOL *This, 546 IN UINT8 PortNumber, 547 IN EFI_USB_PORT_FEATURE PortFeature 548 ) 549 { 550 USB2_HC_DEV *Ehc; 551 EFI_TPL OldTpl; 552 UINT32 Offset; 553 UINT32 State; 554 UINT32 TotalPort; 555 EFI_STATUS Status; 556 557 OldTpl = gBS->RaiseTPL (EHC_TPL); 558 Ehc = EHC_FROM_THIS (This); 559 Status = EFI_SUCCESS; 560 561 TotalPort = (Ehc->HcStructParams & HCSP_NPORTS); 562 563 if (PortNumber >= TotalPort) { 564 Status = EFI_INVALID_PARAMETER; 565 goto ON_EXIT; 566 } 567 568 Offset = EHC_PORT_STAT_OFFSET + (4 * PortNumber); 569 State = EhcReadOpReg (Ehc, Offset); 570 State &= ~PORTSC_CHANGE_MASK; 571 572 switch (PortFeature) { 573 case EfiUsbPortEnable: 574 // 575 // Clear PORT_ENABLE feature means disable port. 576 // 577 State &= ~PORTSC_ENABLED; 578 EhcWriteOpReg (Ehc, Offset, State); 579 break; 580 581 case EfiUsbPortSuspend: 582 // 583 // A write of zero to this bit is ignored by the host 584 // controller. The host controller will unconditionally 585 // set this bit to a zero when: 586 // 1. software sets the Forct Port Resume bit to a zero from a one. 587 // 2. software sets the Port Reset bit to a one frome a zero. 588 // 589 State &= ~PORSTSC_RESUME; 590 EhcWriteOpReg (Ehc, Offset, State); 591 break; 592 593 case EfiUsbPortReset: 594 // 595 // Clear PORT_RESET means clear the reset signal. 596 // 597 State &= ~PORTSC_RESET; 598 EhcWriteOpReg (Ehc, Offset, State); 599 break; 600 601 case EfiUsbPortOwner: 602 // 603 // Clear port owner means this port owned by EHC 604 // 605 State &= ~PORTSC_OWNER; 606 EhcWriteOpReg (Ehc, Offset, State); 607 break; 608 609 case EfiUsbPortConnectChange: 610 // 611 // Clear connect status change 612 // 613 State |= PORTSC_CONN_CHANGE; 614 EhcWriteOpReg (Ehc, Offset, State); 615 break; 616 617 case EfiUsbPortEnableChange: 618 // 619 // Clear enable status change 620 // 621 State |= PORTSC_ENABLE_CHANGE; 622 EhcWriteOpReg (Ehc, Offset, State); 623 break; 624 625 case EfiUsbPortOverCurrentChange: 626 // 627 // Clear PortOverCurrent change 628 // 629 State |= PORTSC_OVERCUR_CHANGE; 630 EhcWriteOpReg (Ehc, Offset, State); 631 break; 632 633 case EfiUsbPortPower: 634 // 635 // Clear port power bit when PPC is 1 636 // 637 if ((Ehc->HcCapParams & HCSP_PPC) == HCSP_PPC) { 638 State &= ~PORTSC_POWER; 639 EhcWriteOpReg (Ehc, Offset, State); 640 } 641 break; 642 case EfiUsbPortSuspendChange: 643 case EfiUsbPortResetChange: 644 // 645 // Not supported or not related operation 646 // 647 break; 648 649 default: 650 Status = EFI_INVALID_PARAMETER; 651 break; 652 } 653 654 ON_EXIT: 655 DEBUG ((EFI_D_INFO, "EhcClearRootHubPortFeature: exit status %r\n", Status)); 656 gBS->RestoreTPL (OldTpl); 657 return Status; 658 } 659 660 661 /** 662 Submits control transfer to a target USB device. 663 664 @param This This EFI_USB2_HC_PROTOCOL instance. 665 @param DeviceAddress The target device address. 666 @param DeviceSpeed Target device speed. 667 @param MaximumPacketLength Maximum packet size the default control transfer 668 endpoint is capable of sending or receiving. 669 @param Request USB device request to send. 670 @param TransferDirection Specifies the data direction for the data stage 671 @param Data Data buffer to be transmitted or received from USB 672 device. 673 @param DataLength The size (in bytes) of the data buffer. 674 @param TimeOut Indicates the maximum timeout, in millisecond. 675 @param Translator Transaction translator to be used by this device. 676 @param TransferResult Return the result of this control transfer. 677 678 @retval EFI_SUCCESS Transfer was completed successfully. 679 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources. 680 @retval EFI_INVALID_PARAMETER Some parameters are invalid. 681 @retval EFI_TIMEOUT Transfer failed due to timeout. 682 @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error. 683 684 **/ 685 EFI_STATUS 686 EFIAPI 687 EhcControlTransfer ( 688 IN EFI_USB2_HC_PROTOCOL *This, 689 IN UINT8 DeviceAddress, 690 IN UINT8 DeviceSpeed, 691 IN UINTN MaximumPacketLength, 692 IN EFI_USB_DEVICE_REQUEST *Request, 693 IN EFI_USB_DATA_DIRECTION TransferDirection, 694 IN OUT VOID *Data, 695 IN OUT UINTN *DataLength, 696 IN UINTN TimeOut, 697 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, 698 OUT UINT32 *TransferResult 699 ) 700 { 701 USB2_HC_DEV *Ehc; 702 URB *Urb; 703 EFI_TPL OldTpl; 704 UINT8 Endpoint; 705 EFI_STATUS Status; 706 707 // 708 // Validate parameters 709 // 710 if ((Request == NULL) || (TransferResult == NULL)) { 711 return EFI_INVALID_PARAMETER; 712 } 713 714 if ((TransferDirection != EfiUsbDataIn) && 715 (TransferDirection != EfiUsbDataOut) && 716 (TransferDirection != EfiUsbNoData)) { 717 return EFI_INVALID_PARAMETER; 718 } 719 720 if ((TransferDirection == EfiUsbNoData) && 721 ((Data != NULL) || (*DataLength != 0))) { 722 return EFI_INVALID_PARAMETER; 723 } 724 725 if ((TransferDirection != EfiUsbNoData) && 726 ((Data == NULL) || (*DataLength == 0))) { 727 return EFI_INVALID_PARAMETER; 728 } 729 730 if ((MaximumPacketLength != 8) && (MaximumPacketLength != 16) && 731 (MaximumPacketLength != 32) && (MaximumPacketLength != 64)) { 732 return EFI_INVALID_PARAMETER; 733 } 734 735 if ((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) { 736 return EFI_INVALID_PARAMETER; 737 } 738 739 OldTpl = gBS->RaiseTPL (EHC_TPL); 740 Ehc = EHC_FROM_THIS (This); 741 742 Status = EFI_DEVICE_ERROR; 743 *TransferResult = EFI_USB_ERR_SYSTEM; 744 745 if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) { 746 DEBUG ((EFI_D_ERROR, "EhcControlTransfer: HC halted at entrance\n")); 747 748 EhcAckAllInterrupt (Ehc); 749 goto ON_EXIT; 750 } 751 752 EhcAckAllInterrupt (Ehc); 753 754 // 755 // Create a new URB, insert it into the asynchronous 756 // schedule list, then poll the execution status. 757 // 758 // 759 // Encode the direction in address, although default control 760 // endpoint is bidirectional. EhcCreateUrb expects this 761 // combination of Ep addr and its direction. 762 // 763 Endpoint = (UINT8) (0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0)); 764 Urb = EhcCreateUrb ( 765 Ehc, 766 DeviceAddress, 767 Endpoint, 768 DeviceSpeed, 769 0, 770 MaximumPacketLength, 771 Translator, 772 EHC_CTRL_TRANSFER, 773 Request, 774 Data, 775 *DataLength, 776 NULL, 777 NULL, 778 1 779 ); 780 781 if (Urb == NULL) { 782 DEBUG ((EFI_D_ERROR, "EhcControlTransfer: failed to create URB")); 783 784 Status = EFI_OUT_OF_RESOURCES; 785 goto ON_EXIT; 786 } 787 788 EhcLinkQhToAsync (Ehc, Urb->Qh); 789 Status = EhcExecTransfer (Ehc, Urb, TimeOut); 790 EhcUnlinkQhFromAsync (Ehc, Urb->Qh); 791 792 // 793 // Get the status from URB. The result is updated in EhcCheckUrbResult 794 // which is called by EhcExecTransfer 795 // 796 *TransferResult = Urb->Result; 797 *DataLength = Urb->Completed; 798 799 if (*TransferResult == EFI_USB_NOERROR) { 800 Status = EFI_SUCCESS; 801 } 802 803 EhcAckAllInterrupt (Ehc); 804 EhcFreeUrb (Ehc, Urb); 805 806 ON_EXIT: 807 Ehc->PciIo->Flush (Ehc->PciIo); 808 gBS->RestoreTPL (OldTpl); 809 810 if (EFI_ERROR (Status)) { 811 DEBUG ((EFI_D_ERROR, "EhcControlTransfer: error - %r, transfer - %x\n", Status, *TransferResult)); 812 } 813 814 return Status; 815 } 816 817 818 /** 819 Submits bulk transfer to a bulk endpoint of a USB device. 820 821 @param This This EFI_USB2_HC_PROTOCOL instance. 822 @param DeviceAddress Target device address. 823 @param EndPointAddress Endpoint number and its direction in bit 7. 824 @param DeviceSpeed Device speed, Low speed device doesn't support bulk 825 transfer. 826 @param MaximumPacketLength Maximum packet size the endpoint is capable of 827 sending or receiving. 828 @param DataBuffersNumber Number of data buffers prepared for the transfer. 829 @param Data Array of pointers to the buffers of data to transmit 830 from or receive into. 831 @param DataLength The lenght of the data buffer. 832 @param DataToggle On input, the initial data toggle for the transfer; 833 On output, it is updated to to next data toggle to 834 use of the subsequent bulk transfer. 835 @param TimeOut Indicates the maximum time, in millisecond, which 836 the transfer is allowed to complete. 837 @param Translator A pointr to the transaction translator data. 838 @param TransferResult A pointer to the detailed result information of the 839 bulk transfer. 840 841 @retval EFI_SUCCESS The transfer was completed successfully. 842 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource. 843 @retval EFI_INVALID_PARAMETER Some parameters are invalid. 844 @retval EFI_TIMEOUT The transfer failed due to timeout. 845 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error. 846 847 **/ 848 EFI_STATUS 849 EFIAPI 850 EhcBulkTransfer ( 851 IN EFI_USB2_HC_PROTOCOL *This, 852 IN UINT8 DeviceAddress, 853 IN UINT8 EndPointAddress, 854 IN UINT8 DeviceSpeed, 855 IN UINTN MaximumPacketLength, 856 IN UINT8 DataBuffersNumber, 857 IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM], 858 IN OUT UINTN *DataLength, 859 IN OUT UINT8 *DataToggle, 860 IN UINTN TimeOut, 861 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, 862 OUT UINT32 *TransferResult 863 ) 864 { 865 USB2_HC_DEV *Ehc; 866 URB *Urb; 867 EFI_TPL OldTpl; 868 EFI_STATUS Status; 869 870 // 871 // Validate the parameters 872 // 873 if ((DataLength == NULL) || (*DataLength == 0) || 874 (Data == NULL) || (Data[0] == NULL) || (TransferResult == NULL)) { 875 return EFI_INVALID_PARAMETER; 876 } 877 878 if ((*DataToggle != 0) && (*DataToggle != 1)) { 879 return EFI_INVALID_PARAMETER; 880 } 881 882 if ((DeviceSpeed == EFI_USB_SPEED_LOW) || 883 ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) || 884 ((EFI_USB_SPEED_HIGH == DeviceSpeed) && (MaximumPacketLength > 512))) { 885 return EFI_INVALID_PARAMETER; 886 } 887 888 OldTpl = gBS->RaiseTPL (EHC_TPL); 889 Ehc = EHC_FROM_THIS (This); 890 891 *TransferResult = EFI_USB_ERR_SYSTEM; 892 Status = EFI_DEVICE_ERROR; 893 894 if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) { 895 DEBUG ((EFI_D_ERROR, "EhcBulkTransfer: HC is halted\n")); 896 897 EhcAckAllInterrupt (Ehc); 898 goto ON_EXIT; 899 } 900 901 EhcAckAllInterrupt (Ehc); 902 903 // 904 // Create a new URB, insert it into the asynchronous 905 // schedule list, then poll the execution status. 906 // 907 Urb = EhcCreateUrb ( 908 Ehc, 909 DeviceAddress, 910 EndPointAddress, 911 DeviceSpeed, 912 *DataToggle, 913 MaximumPacketLength, 914 Translator, 915 EHC_BULK_TRANSFER, 916 NULL, 917 Data[0], 918 *DataLength, 919 NULL, 920 NULL, 921 1 922 ); 923 924 if (Urb == NULL) { 925 DEBUG ((EFI_D_ERROR, "EhcBulkTransfer: failed to create URB\n")); 926 927 Status = EFI_OUT_OF_RESOURCES; 928 goto ON_EXIT; 929 } 930 931 EhcLinkQhToAsync (Ehc, Urb->Qh); 932 Status = EhcExecTransfer (Ehc, Urb, TimeOut); 933 EhcUnlinkQhFromAsync (Ehc, Urb->Qh); 934 935 *TransferResult = Urb->Result; 936 *DataLength = Urb->Completed; 937 *DataToggle = Urb->DataToggle; 938 939 if (*TransferResult == EFI_USB_NOERROR) { 940 Status = EFI_SUCCESS; 941 } 942 943 EhcAckAllInterrupt (Ehc); 944 EhcFreeUrb (Ehc, Urb); 945 946 ON_EXIT: 947 Ehc->PciIo->Flush (Ehc->PciIo); 948 gBS->RestoreTPL (OldTpl); 949 950 if (EFI_ERROR (Status)) { 951 DEBUG ((EFI_D_ERROR, "EhcBulkTransfer: error - %r, transfer - %x\n", Status, *TransferResult)); 952 } 953 954 return Status; 955 } 956 957 958 /** 959 Submits an asynchronous interrupt transfer to an 960 interrupt endpoint of a USB device. 961 962 @param This This EFI_USB2_HC_PROTOCOL instance. 963 @param DeviceAddress Target device address. 964 @param EndPointAddress Endpoint number and its direction encoded in bit 7 965 @param DeviceSpeed Indicates device speed. 966 @param MaximumPacketLength Maximum packet size the target endpoint is capable 967 @param IsNewTransfer If TRUE, to submit an new asynchronous interrupt 968 transfer If FALSE, to remove the specified 969 asynchronous interrupt. 970 @param DataToggle On input, the initial data toggle to use; on output, 971 it is updated to indicate the next data toggle. 972 @param PollingInterval The he interval, in milliseconds, that the transfer 973 is polled. 974 @param DataLength The length of data to receive at the rate specified 975 by PollingInterval. 976 @param Translator Transaction translator to use. 977 @param CallBackFunction Function to call at the rate specified by 978 PollingInterval. 979 @param Context Context to CallBackFunction. 980 981 @retval EFI_SUCCESS The request has been successfully submitted or canceled. 982 @retval EFI_INVALID_PARAMETER Some parameters are invalid. 983 @retval EFI_OUT_OF_RESOURCES The request failed due to a lack of resources. 984 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error. 985 986 **/ 987 EFI_STATUS 988 EFIAPI 989 EhcAsyncInterruptTransfer ( 990 IN EFI_USB2_HC_PROTOCOL * This, 991 IN UINT8 DeviceAddress, 992 IN UINT8 EndPointAddress, 993 IN UINT8 DeviceSpeed, 994 IN UINTN MaximumPacketLength, 995 IN BOOLEAN IsNewTransfer, 996 IN OUT UINT8 *DataToggle, 997 IN UINTN PollingInterval, 998 IN UINTN DataLength, 999 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator, 1000 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction, 1001 IN VOID *Context OPTIONAL 1002 ) 1003 { 1004 USB2_HC_DEV *Ehc; 1005 URB *Urb; 1006 EFI_TPL OldTpl; 1007 EFI_STATUS Status; 1008 UINT8 *Data; 1009 1010 // 1011 // Validate parameters 1012 // 1013 if (!EHCI_IS_DATAIN (EndPointAddress)) { 1014 return EFI_INVALID_PARAMETER; 1015 } 1016 1017 if (IsNewTransfer) { 1018 if (DataLength == 0) { 1019 return EFI_INVALID_PARAMETER; 1020 } 1021 1022 if ((*DataToggle != 1) && (*DataToggle != 0)) { 1023 return EFI_INVALID_PARAMETER; 1024 } 1025 1026 if ((PollingInterval > 255) || (PollingInterval < 1)) { 1027 return EFI_INVALID_PARAMETER; 1028 } 1029 } 1030 1031 OldTpl = gBS->RaiseTPL (EHC_TPL); 1032 Ehc = EHC_FROM_THIS (This); 1033 1034 // 1035 // Delete Async interrupt transfer request. DataToggle will return 1036 // the next data toggle to use. 1037 // 1038 if (!IsNewTransfer) { 1039 Status = EhciDelAsyncIntTransfer (Ehc, DeviceAddress, EndPointAddress, DataToggle); 1040 1041 DEBUG ((EFI_D_INFO, "EhcAsyncInterruptTransfer: remove old transfer - %r\n", Status)); 1042 goto ON_EXIT; 1043 } 1044 1045 Status = EFI_SUCCESS; 1046 1047 if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) { 1048 DEBUG ((EFI_D_ERROR, "EhcAsyncInterruptTransfer: HC is halt\n")); 1049 EhcAckAllInterrupt (Ehc); 1050 1051 Status = EFI_DEVICE_ERROR; 1052 goto ON_EXIT; 1053 } 1054 1055 EhcAckAllInterrupt (Ehc); 1056 1057 Data = AllocatePool (DataLength); 1058 1059 if (Data == NULL) { 1060 DEBUG ((EFI_D_ERROR, "EhcAsyncInterruptTransfer: failed to allocate buffer\n")); 1061 1062 Status = EFI_OUT_OF_RESOURCES; 1063 goto ON_EXIT; 1064 } 1065 1066 Urb = EhcCreateUrb ( 1067 Ehc, 1068 DeviceAddress, 1069 EndPointAddress, 1070 DeviceSpeed, 1071 *DataToggle, 1072 MaximumPacketLength, 1073 Translator, 1074 EHC_INT_TRANSFER_ASYNC, 1075 NULL, 1076 Data, 1077 DataLength, 1078 CallBackFunction, 1079 Context, 1080 PollingInterval 1081 ); 1082 1083 if (Urb == NULL) { 1084 DEBUG ((EFI_D_ERROR, "EhcAsyncInterruptTransfer: failed to create URB\n")); 1085 1086 gBS->FreePool (Data); 1087 Status = EFI_OUT_OF_RESOURCES; 1088 goto ON_EXIT; 1089 } 1090 1091 // 1092 // New asynchronous transfer must inserted to the head. 1093 // Check the comments in EhcMoniteAsyncRequests 1094 // 1095 EhcLinkQhToPeriod (Ehc, Urb->Qh); 1096 InsertHeadList (&Ehc->AsyncIntTransfers, &Urb->UrbList); 1097 1098 ON_EXIT: 1099 Ehc->PciIo->Flush (Ehc->PciIo); 1100 gBS->RestoreTPL (OldTpl); 1101 1102 return Status; 1103 } 1104 1105 1106 /** 1107 Submits synchronous interrupt transfer to an interrupt endpoint 1108 of a USB device. 1109 1110 @param This This EFI_USB2_HC_PROTOCOL instance. 1111 @param DeviceAddress Target device address. 1112 @param EndPointAddress Endpoint number and its direction encoded in bit 7 1113 @param DeviceSpeed Indicates device speed. 1114 @param MaximumPacketLength Maximum packet size the target endpoint is capable 1115 of sending or receiving. 1116 @param Data Buffer of data that will be transmitted to USB 1117 device or received from USB device. 1118 @param DataLength On input, the size, in bytes, of the data buffer; On 1119 output, the number of bytes transferred. 1120 @param DataToggle On input, the initial data toggle to use; on output, 1121 it is updated to indicate the next data toggle. 1122 @param TimeOut Maximum time, in second, to complete. 1123 @param Translator Transaction translator to use. 1124 @param TransferResult Variable to receive the transfer result. 1125 1126 @return EFI_SUCCESS The transfer was completed successfully. 1127 @return EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource. 1128 @return EFI_INVALID_PARAMETER Some parameters are invalid. 1129 @return EFI_TIMEOUT The transfer failed due to timeout. 1130 @return EFI_DEVICE_ERROR The failed due to host controller or device error 1131 1132 **/ 1133 EFI_STATUS 1134 EFIAPI 1135 EhcSyncInterruptTransfer ( 1136 IN EFI_USB2_HC_PROTOCOL *This, 1137 IN UINT8 DeviceAddress, 1138 IN UINT8 EndPointAddress, 1139 IN UINT8 DeviceSpeed, 1140 IN UINTN MaximumPacketLength, 1141 IN OUT VOID *Data, 1142 IN OUT UINTN *DataLength, 1143 IN OUT UINT8 *DataToggle, 1144 IN UINTN TimeOut, 1145 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, 1146 OUT UINT32 *TransferResult 1147 ) 1148 { 1149 USB2_HC_DEV *Ehc; 1150 EFI_TPL OldTpl; 1151 URB *Urb; 1152 EFI_STATUS Status; 1153 1154 // 1155 // Validates parameters 1156 // 1157 if ((DataLength == NULL) || (*DataLength == 0) || 1158 (Data == NULL) || (TransferResult == NULL)) { 1159 return EFI_INVALID_PARAMETER; 1160 } 1161 1162 if ((*DataToggle != 1) && (*DataToggle != 0)) { 1163 return EFI_INVALID_PARAMETER; 1164 } 1165 1166 if (((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) || 1167 ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) || 1168 ((DeviceSpeed == EFI_USB_SPEED_HIGH) && (MaximumPacketLength > 3072))) { 1169 return EFI_INVALID_PARAMETER; 1170 } 1171 1172 OldTpl = gBS->RaiseTPL (EHC_TPL); 1173 Ehc = EHC_FROM_THIS (This); 1174 1175 *TransferResult = EFI_USB_ERR_SYSTEM; 1176 Status = EFI_DEVICE_ERROR; 1177 1178 if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) { 1179 DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: HC is halt\n")); 1180 1181 EhcAckAllInterrupt (Ehc); 1182 goto ON_EXIT; 1183 } 1184 1185 EhcAckAllInterrupt (Ehc); 1186 1187 Urb = EhcCreateUrb ( 1188 Ehc, 1189 DeviceAddress, 1190 EndPointAddress, 1191 DeviceSpeed, 1192 *DataToggle, 1193 MaximumPacketLength, 1194 Translator, 1195 EHC_INT_TRANSFER_SYNC, 1196 NULL, 1197 Data, 1198 *DataLength, 1199 NULL, 1200 NULL, 1201 1 1202 ); 1203 1204 if (Urb == NULL) { 1205 DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: failed to create URB\n")); 1206 1207 Status = EFI_OUT_OF_RESOURCES; 1208 goto ON_EXIT; 1209 } 1210 1211 EhcLinkQhToPeriod (Ehc, Urb->Qh); 1212 Status = EhcExecTransfer (Ehc, Urb, TimeOut); 1213 EhcUnlinkQhFromPeriod (Ehc, Urb->Qh); 1214 1215 *TransferResult = Urb->Result; 1216 *DataLength = Urb->Completed; 1217 *DataToggle = Urb->DataToggle; 1218 1219 if (*TransferResult == EFI_USB_NOERROR) { 1220 Status = EFI_SUCCESS; 1221 } 1222 1223 ON_EXIT: 1224 Ehc->PciIo->Flush (Ehc->PciIo); 1225 gBS->RestoreTPL (OldTpl); 1226 1227 if (EFI_ERROR (Status)) { 1228 DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: error - %r, transfer - %x\n", Status, *TransferResult)); 1229 } 1230 1231 return Status; 1232 } 1233 1234 1235 /** 1236 Submits isochronous transfer to a target USB device. 1237 1238 @param This This EFI_USB2_HC_PROTOCOL instance. 1239 @param DeviceAddress Target device address. 1240 @param EndPointAddress End point address with its direction. 1241 @param DeviceSpeed Device speed, Low speed device doesn't support this 1242 type. 1243 @param MaximumPacketLength Maximum packet size that the endpoint is capable of 1244 sending or receiving. 1245 @param DataBuffersNumber Number of data buffers prepared for the transfer. 1246 @param Data Array of pointers to the buffers of data that will 1247 be transmitted to USB device or received from USB 1248 device. 1249 @param DataLength The size, in bytes, of the data buffer. 1250 @param Translator Transaction translator to use. 1251 @param TransferResult Variable to receive the transfer result. 1252 1253 @return EFI_UNSUPPORTED Isochronous transfer is unsupported. 1254 1255 **/ 1256 EFI_STATUS 1257 EFIAPI 1258 EhcIsochronousTransfer ( 1259 IN EFI_USB2_HC_PROTOCOL *This, 1260 IN UINT8 DeviceAddress, 1261 IN UINT8 EndPointAddress, 1262 IN UINT8 DeviceSpeed, 1263 IN UINTN MaximumPacketLength, 1264 IN UINT8 DataBuffersNumber, 1265 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], 1266 IN UINTN DataLength, 1267 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, 1268 OUT UINT32 *TransferResult 1269 ) 1270 { 1271 return EFI_UNSUPPORTED; 1272 } 1273 1274 1275 /** 1276 Submits Async isochronous transfer to a target USB device. 1277 1278 @param This This EFI_USB2_HC_PROTOCOL instance. 1279 @param DeviceAddress Target device address. 1280 @param EndPointAddress End point address with its direction. 1281 @param DeviceSpeed Device speed, Low speed device doesn't support this 1282 type. 1283 @param MaximumPacketLength Maximum packet size that the endpoint is capable of 1284 sending or receiving. 1285 @param DataBuffersNumber Number of data buffers prepared for the transfer. 1286 @param Data Array of pointers to the buffers of data that will 1287 be transmitted to USB device or received from USB 1288 device. 1289 @param DataLength The size, in bytes, of the data buffer. 1290 @param Translator Transaction translator to use. 1291 @param IsochronousCallBack Function to be called when the transfer complete. 1292 @param Context Context passed to the call back function as 1293 parameter. 1294 1295 @return EFI_UNSUPPORTED Isochronous transfer isn't supported. 1296 1297 **/ 1298 EFI_STATUS 1299 EFIAPI 1300 EhcAsyncIsochronousTransfer ( 1301 IN EFI_USB2_HC_PROTOCOL *This, 1302 IN UINT8 DeviceAddress, 1303 IN UINT8 EndPointAddress, 1304 IN UINT8 DeviceSpeed, 1305 IN UINTN MaximumPacketLength, 1306 IN UINT8 DataBuffersNumber, 1307 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], 1308 IN UINTN DataLength, 1309 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, 1310 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack, 1311 IN VOID *Context 1312 ) 1313 { 1314 return EFI_UNSUPPORTED; 1315 } 1316 1317 /** 1318 Entry point for EFI drivers. 1319 1320 @param ImageHandle EFI_HANDLE. 1321 @param SystemTable EFI_SYSTEM_TABLE. 1322 1323 @return EFI_SUCCESS Success. 1324 EFI_DEVICE_ERROR Fail. 1325 1326 **/ 1327 EFI_STATUS 1328 EFIAPI 1329 EhcDriverEntryPoint ( 1330 IN EFI_HANDLE ImageHandle, 1331 IN EFI_SYSTEM_TABLE *SystemTable 1332 ) 1333 { 1334 return EfiLibInstallDriverBindingComponentName2 ( 1335 ImageHandle, 1336 SystemTable, 1337 &gEhciDriverBinding, 1338 ImageHandle, 1339 &gEhciComponentName, 1340 &gEhciComponentName2 1341 ); 1342 } 1343 1344 1345 /** 1346 Test to see if this driver supports ControllerHandle. Any 1347 ControllerHandle that has Usb2HcProtocol installed will 1348 be supported. 1349 1350 @param This Protocol instance pointer. 1351 @param Controller Handle of device to test. 1352 @param RemainingDevicePath Not used. 1353 1354 @return EFI_SUCCESS This driver supports this device. 1355 @return EFI_UNSUPPORTED This driver does not support this device. 1356 1357 **/ 1358 EFI_STATUS 1359 EFIAPI 1360 EhcDriverBindingSupported ( 1361 IN EFI_DRIVER_BINDING_PROTOCOL *This, 1362 IN EFI_HANDLE Controller, 1363 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 1364 ) 1365 { 1366 EFI_STATUS Status; 1367 EFI_PCI_IO_PROTOCOL *PciIo; 1368 USB_CLASSC UsbClassCReg; 1369 1370 // 1371 // Test whether there is PCI IO Protocol attached on the controller handle. 1372 // 1373 Status = gBS->OpenProtocol ( 1374 Controller, 1375 &gEfiPciIoProtocolGuid, 1376 (VOID **) &PciIo, 1377 This->DriverBindingHandle, 1378 Controller, 1379 EFI_OPEN_PROTOCOL_BY_DRIVER 1380 ); 1381 1382 if (EFI_ERROR (Status)) { 1383 return EFI_UNSUPPORTED; 1384 } 1385 1386 Status = PciIo->Pci.Read ( 1387 PciIo, 1388 EfiPciIoWidthUint8, 1389 PCI_CLASSCODE_OFFSET, 1390 sizeof (USB_CLASSC) / sizeof (UINT8), 1391 &UsbClassCReg 1392 ); 1393 1394 if (EFI_ERROR (Status)) { 1395 Status = EFI_UNSUPPORTED; 1396 goto ON_EXIT; 1397 } 1398 1399 // 1400 // Test whether the controller belongs to Ehci type 1401 // 1402 if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) || (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) 1403 || ((UsbClassCReg.ProgInterface != PCI_IF_EHCI) && (UsbClassCReg.ProgInterface != PCI_IF_UHCI) && (UsbClassCReg.ProgInterface != PCI_IF_OHCI))) { 1404 1405 Status = EFI_UNSUPPORTED; 1406 } 1407 1408 ON_EXIT: 1409 gBS->CloseProtocol ( 1410 Controller, 1411 &gEfiPciIoProtocolGuid, 1412 This->DriverBindingHandle, 1413 Controller 1414 ); 1415 1416 return Status; 1417 } 1418 1419 /** 1420 Get the usb debug port related information. 1421 1422 @param Ehc The EHCI device. 1423 1424 @retval RETURN_SUCCESS Get debug port number, bar and offset successfully. 1425 @retval Others The usb host controller does not supported usb debug port capability. 1426 1427 **/ 1428 EFI_STATUS 1429 EhcGetUsbDebugPortInfo ( 1430 IN USB2_HC_DEV *Ehc 1431 ) 1432 { 1433 EFI_PCI_IO_PROTOCOL *PciIo; 1434 UINT16 PciStatus; 1435 UINT8 CapabilityPtr; 1436 UINT8 CapabilityId; 1437 UINT16 DebugPort; 1438 EFI_STATUS Status; 1439 1440 ASSERT (Ehc->PciIo != NULL); 1441 PciIo = Ehc->PciIo; 1442 1443 // 1444 // Detect if the EHCI host controller support Capaility Pointer. 1445 // 1446 Status = PciIo->Pci.Read ( 1447 PciIo, 1448 EfiPciIoWidthUint8, 1449 PCI_PRIMARY_STATUS_OFFSET, 1450 sizeof (UINT16), 1451 &PciStatus 1452 ); 1453 1454 if (EFI_ERROR (Status)) { 1455 return Status; 1456 } 1457 1458 if ((PciStatus & EFI_PCI_STATUS_CAPABILITY) == 0) { 1459 // 1460 // The Pci Device Doesn't Support Capability Pointer. 1461 // 1462 return EFI_UNSUPPORTED; 1463 } 1464 1465 // 1466 // Get Pointer To Capability List 1467 // 1468 Status = PciIo->Pci.Read ( 1469 PciIo, 1470 EfiPciIoWidthUint8, 1471 PCI_CAPBILITY_POINTER_OFFSET, 1472 1, 1473 &CapabilityPtr 1474 ); 1475 1476 if (EFI_ERROR (Status)) { 1477 return Status; 1478 } 1479 1480 // 1481 // Find Capability ID 0xA, Which Is For Debug Port 1482 // 1483 while (CapabilityPtr != 0) { 1484 Status = PciIo->Pci.Read ( 1485 PciIo, 1486 EfiPciIoWidthUint8, 1487 CapabilityPtr, 1488 1, 1489 &CapabilityId 1490 ); 1491 1492 if (EFI_ERROR (Status)) { 1493 return Status; 1494 } 1495 1496 if (CapabilityId == EHC_DEBUG_PORT_CAP_ID) { 1497 break; 1498 } 1499 1500 Status = PciIo->Pci.Read ( 1501 PciIo, 1502 EfiPciIoWidthUint8, 1503 CapabilityPtr + 1, 1504 1, 1505 &CapabilityPtr 1506 ); 1507 1508 if (EFI_ERROR (Status)) { 1509 return Status; 1510 } 1511 } 1512 1513 // 1514 // No Debug Port Capability Found 1515 // 1516 if (CapabilityPtr == 0) { 1517 return EFI_UNSUPPORTED; 1518 } 1519 1520 // 1521 // Get The Base Address Of Debug Port Register In Debug Port Capability Register 1522 // 1523 Status = PciIo->Pci.Read ( 1524 Ehc->PciIo, 1525 EfiPciIoWidthUint8, 1526 CapabilityPtr + 2, 1527 sizeof (UINT16), 1528 &DebugPort 1529 ); 1530 1531 if (EFI_ERROR (Status)) { 1532 return Status; 1533 } 1534 1535 Ehc->DebugPortOffset = DebugPort & 0x1FFF; 1536 Ehc->DebugPortBarNum = (UINT8)((DebugPort >> 13) - 1); 1537 Ehc->DebugPortNum = (UINT8)((Ehc->HcStructParams & 0x00F00000) >> 20); 1538 1539 return EFI_SUCCESS; 1540 } 1541 1542 1543 /** 1544 Create and initialize a USB2_HC_DEV. 1545 1546 @param PciIo The PciIo on this device. 1547 @param DevicePath The device path of host controller. 1548 @param OriginalPciAttributes Original PCI attributes. 1549 1550 @return The allocated and initialized USB2_HC_DEV structure if created, 1551 otherwise NULL. 1552 1553 **/ 1554 USB2_HC_DEV * 1555 EhcCreateUsb2Hc ( 1556 IN EFI_PCI_IO_PROTOCOL *PciIo, 1557 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, 1558 IN UINT64 OriginalPciAttributes 1559 ) 1560 { 1561 USB2_HC_DEV *Ehc; 1562 EFI_STATUS Status; 1563 1564 Ehc = AllocateZeroPool (sizeof (USB2_HC_DEV)); 1565 1566 if (Ehc == NULL) { 1567 return NULL; 1568 } 1569 1570 // 1571 // Init EFI_USB2_HC_PROTOCOL interface and private data structure 1572 // 1573 Ehc->Signature = USB2_HC_DEV_SIGNATURE; 1574 1575 Ehc->Usb2Hc.GetCapability = EhcGetCapability; 1576 Ehc->Usb2Hc.Reset = EhcReset; 1577 Ehc->Usb2Hc.GetState = EhcGetState; 1578 Ehc->Usb2Hc.SetState = EhcSetState; 1579 Ehc->Usb2Hc.ControlTransfer = EhcControlTransfer; 1580 Ehc->Usb2Hc.BulkTransfer = EhcBulkTransfer; 1581 Ehc->Usb2Hc.AsyncInterruptTransfer = EhcAsyncInterruptTransfer; 1582 Ehc->Usb2Hc.SyncInterruptTransfer = EhcSyncInterruptTransfer; 1583 Ehc->Usb2Hc.IsochronousTransfer = EhcIsochronousTransfer; 1584 Ehc->Usb2Hc.AsyncIsochronousTransfer = EhcAsyncIsochronousTransfer; 1585 Ehc->Usb2Hc.GetRootHubPortStatus = EhcGetRootHubPortStatus; 1586 Ehc->Usb2Hc.SetRootHubPortFeature = EhcSetRootHubPortFeature; 1587 Ehc->Usb2Hc.ClearRootHubPortFeature = EhcClearRootHubPortFeature; 1588 Ehc->Usb2Hc.MajorRevision = 0x2; 1589 Ehc->Usb2Hc.MinorRevision = 0x0; 1590 1591 Ehc->PciIo = PciIo; 1592 Ehc->DevicePath = DevicePath; 1593 Ehc->OriginalPciAttributes = OriginalPciAttributes; 1594 1595 InitializeListHead (&Ehc->AsyncIntTransfers); 1596 1597 Ehc->HcStructParams = EhcReadCapRegister (Ehc, EHC_HCSPARAMS_OFFSET); 1598 Ehc->HcCapParams = EhcReadCapRegister (Ehc, EHC_HCCPARAMS_OFFSET); 1599 Ehc->CapLen = EhcReadCapRegister (Ehc, EHC_CAPLENGTH_OFFSET) & 0x0FF; 1600 1601 DEBUG ((EFI_D_INFO, "EhcCreateUsb2Hc: capability length %d\n", Ehc->CapLen)); 1602 1603 // 1604 // EHCI Controllers with a CapLen of 0 are ignored. 1605 // 1606 if (Ehc->CapLen == 0) { 1607 gBS->FreePool (Ehc); 1608 return NULL; 1609 } 1610 1611 EhcGetUsbDebugPortInfo (Ehc); 1612 1613 // 1614 // Create AsyncRequest Polling Timer 1615 // 1616 Status = gBS->CreateEvent ( 1617 EVT_TIMER | EVT_NOTIFY_SIGNAL, 1618 TPL_NOTIFY, 1619 EhcMonitorAsyncRequests, 1620 Ehc, 1621 &Ehc->PollTimer 1622 ); 1623 1624 if (EFI_ERROR (Status)) { 1625 gBS->FreePool (Ehc); 1626 return NULL; 1627 } 1628 1629 return Ehc; 1630 } 1631 1632 /** 1633 One notified function to stop the Host Controller when gBS->ExitBootServices() called. 1634 1635 @param Event Pointer to this event 1636 @param Context Event handler private data 1637 1638 **/ 1639 VOID 1640 EFIAPI 1641 EhcExitBootService ( 1642 EFI_EVENT Event, 1643 VOID *Context 1644 ) 1645 1646 { 1647 USB2_HC_DEV *Ehc; 1648 1649 Ehc = (USB2_HC_DEV *) Context; 1650 1651 // 1652 // Reset the Host Controller 1653 // 1654 EhcResetHC (Ehc, EHC_RESET_TIMEOUT); 1655 } 1656 1657 1658 /** 1659 Starting the Usb EHCI Driver. 1660 1661 @param This Protocol instance pointer. 1662 @param Controller Handle of device to test. 1663 @param RemainingDevicePath Not used. 1664 1665 @return EFI_SUCCESS supports this device. 1666 @return EFI_UNSUPPORTED do not support this device. 1667 @return EFI_DEVICE_ERROR cannot be started due to device Error. 1668 @return EFI_OUT_OF_RESOURCES cannot allocate resources. 1669 1670 **/ 1671 EFI_STATUS 1672 EFIAPI 1673 EhcDriverBindingStart ( 1674 IN EFI_DRIVER_BINDING_PROTOCOL *This, 1675 IN EFI_HANDLE Controller, 1676 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 1677 ) 1678 { 1679 EFI_STATUS Status; 1680 USB2_HC_DEV *Ehc; 1681 EFI_PCI_IO_PROTOCOL *PciIo; 1682 EFI_PCI_IO_PROTOCOL *Instance; 1683 UINT64 Supports; 1684 UINT64 OriginalPciAttributes; 1685 BOOLEAN PciAttributesSaved; 1686 USB_CLASSC UsbClassCReg; 1687 EFI_HANDLE *HandleBuffer; 1688 UINTN NumberOfHandles; 1689 UINTN Index; 1690 UINTN CompanionSegmentNumber; 1691 UINTN CompanionBusNumber; 1692 UINTN CompanionDeviceNumber; 1693 UINTN CompanionFunctionNumber; 1694 UINTN EhciSegmentNumber; 1695 UINTN EhciBusNumber; 1696 UINTN EhciDeviceNumber; 1697 UINTN EhciFunctionNumber; 1698 UINT32 State; 1699 EFI_DEVICE_PATH_PROTOCOL *HcDevicePath; 1700 1701 // 1702 // Open the PciIo Protocol, then enable the USB host controller 1703 // 1704 Status = gBS->OpenProtocol ( 1705 Controller, 1706 &gEfiPciIoProtocolGuid, 1707 (VOID **) &PciIo, 1708 This->DriverBindingHandle, 1709 Controller, 1710 EFI_OPEN_PROTOCOL_BY_DRIVER 1711 ); 1712 1713 if (EFI_ERROR (Status)) { 1714 return Status; 1715 } 1716 1717 // 1718 // Open Device Path Protocol for on USB host controller 1719 // 1720 HcDevicePath = NULL; 1721 Status = gBS->OpenProtocol ( 1722 Controller, 1723 &gEfiDevicePathProtocolGuid, 1724 (VOID **) &HcDevicePath, 1725 This->DriverBindingHandle, 1726 Controller, 1727 EFI_OPEN_PROTOCOL_GET_PROTOCOL 1728 ); 1729 1730 PciAttributesSaved = FALSE; 1731 // 1732 // Save original PCI attributes 1733 // 1734 Status = PciIo->Attributes ( 1735 PciIo, 1736 EfiPciIoAttributeOperationGet, 1737 0, 1738 &OriginalPciAttributes 1739 ); 1740 1741 if (EFI_ERROR (Status)) { 1742 goto CLOSE_PCIIO; 1743 } 1744 PciAttributesSaved = TRUE; 1745 1746 Status = PciIo->Attributes ( 1747 PciIo, 1748 EfiPciIoAttributeOperationSupported, 1749 0, 1750 &Supports 1751 ); 1752 if (!EFI_ERROR (Status)) { 1753 Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE; 1754 Status = PciIo->Attributes ( 1755 PciIo, 1756 EfiPciIoAttributeOperationEnable, 1757 Supports, 1758 NULL 1759 ); 1760 } 1761 1762 if (EFI_ERROR (Status)) { 1763 DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to enable controller\n")); 1764 goto CLOSE_PCIIO; 1765 } 1766 1767 // 1768 // Get the Pci device class code. 1769 // 1770 Status = PciIo->Pci.Read ( 1771 PciIo, 1772 EfiPciIoWidthUint8, 1773 PCI_CLASSCODE_OFFSET, 1774 sizeof (USB_CLASSC) / sizeof (UINT8), 1775 &UsbClassCReg 1776 ); 1777 1778 if (EFI_ERROR (Status)) { 1779 Status = EFI_UNSUPPORTED; 1780 goto CLOSE_PCIIO; 1781 } 1782 // 1783 // Determine if the device is UHCI or OHCI host controller or not. If yes, then find out the 1784 // companion usb ehci host controller and force EHCI driver get attached to it before 1785 // UHCI or OHCI driver attaches to UHCI or OHCI host controller. 1786 // 1787 if ((UsbClassCReg.ProgInterface == PCI_IF_UHCI || UsbClassCReg.ProgInterface == PCI_IF_OHCI) && 1788 (UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) && 1789 (UsbClassCReg.SubClassCode == PCI_CLASS_SERIAL_USB)) { 1790 Status = PciIo->GetLocation ( 1791 PciIo, 1792 &CompanionSegmentNumber, 1793 &CompanionBusNumber, 1794 &CompanionDeviceNumber, 1795 &CompanionFunctionNumber 1796 ); 1797 if (EFI_ERROR (Status)) { 1798 goto CLOSE_PCIIO; 1799 } 1800 1801 Status = gBS->LocateHandleBuffer ( 1802 ByProtocol, 1803 &gEfiPciIoProtocolGuid, 1804 NULL, 1805 &NumberOfHandles, 1806 &HandleBuffer 1807 ); 1808 if (EFI_ERROR (Status)) { 1809 goto CLOSE_PCIIO; 1810 } 1811 1812 for (Index = 0; Index < NumberOfHandles; Index++) { 1813 // 1814 // Get the device path on this handle 1815 // 1816 Status = gBS->HandleProtocol ( 1817 HandleBuffer[Index], 1818 &gEfiPciIoProtocolGuid, 1819 (VOID **)&Instance 1820 ); 1821 ASSERT_EFI_ERROR (Status); 1822 1823 Status = Instance->Pci.Read ( 1824 Instance, 1825 EfiPciIoWidthUint8, 1826 PCI_CLASSCODE_OFFSET, 1827 sizeof (USB_CLASSC) / sizeof (UINT8), 1828 &UsbClassCReg 1829 ); 1830 1831 if (EFI_ERROR (Status)) { 1832 Status = EFI_UNSUPPORTED; 1833 goto CLOSE_PCIIO; 1834 } 1835 1836 if ((UsbClassCReg.ProgInterface == PCI_IF_EHCI) && 1837 (UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) && 1838 (UsbClassCReg.SubClassCode == PCI_CLASS_SERIAL_USB)) { 1839 Status = Instance->GetLocation ( 1840 Instance, 1841 &EhciSegmentNumber, 1842 &EhciBusNumber, 1843 &EhciDeviceNumber, 1844 &EhciFunctionNumber 1845 ); 1846 if (EFI_ERROR (Status)) { 1847 goto CLOSE_PCIIO; 1848 } 1849 // 1850 // Currently, the judgment on the companion usb host controller is through the 1851 // same bus number, which may vary on different platform. 1852 // 1853 if (EhciBusNumber == CompanionBusNumber) { 1854 gBS->CloseProtocol ( 1855 Controller, 1856 &gEfiPciIoProtocolGuid, 1857 This->DriverBindingHandle, 1858 Controller 1859 ); 1860 EhcDriverBindingStart(This, HandleBuffer[Index], NULL); 1861 } 1862 } 1863 } 1864 Status = EFI_NOT_FOUND; 1865 goto CLOSE_PCIIO; 1866 } 1867 1868 // 1869 // Create then install USB2_HC_PROTOCOL 1870 // 1871 Ehc = EhcCreateUsb2Hc (PciIo, HcDevicePath, OriginalPciAttributes); 1872 1873 if (Ehc == NULL) { 1874 DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to create USB2_HC\n")); 1875 1876 Status = EFI_OUT_OF_RESOURCES; 1877 goto CLOSE_PCIIO; 1878 } 1879 1880 // 1881 // Enable 64-bit DMA support in the PCI layer if this controller 1882 // supports it. 1883 // 1884 if (EHC_BIT_IS_SET (Ehc->HcCapParams, HCCP_64BIT)) { 1885 Status = PciIo->Attributes ( 1886 PciIo, 1887 EfiPciIoAttributeOperationEnable, 1888 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE, 1889 NULL 1890 ); 1891 if (!EFI_ERROR (Status)) { 1892 Ehc->Support64BitDma = TRUE; 1893 } else { 1894 DEBUG ((EFI_D_WARN, 1895 "%a: failed to enable 64-bit DMA on 64-bit capable controller @ %p (%r)\n", 1896 __FUNCTION__, Controller, Status)); 1897 } 1898 } 1899 1900 Status = gBS->InstallProtocolInterface ( 1901 &Controller, 1902 &gEfiUsb2HcProtocolGuid, 1903 EFI_NATIVE_INTERFACE, 1904 &Ehc->Usb2Hc 1905 ); 1906 1907 if (EFI_ERROR (Status)) { 1908 DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to install USB2_HC Protocol\n")); 1909 goto FREE_POOL; 1910 } 1911 1912 // 1913 // Robustnesss improvement such as for Duet platform 1914 // Default is not required. 1915 // 1916 if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) { 1917 EhcClearLegacySupport (Ehc); 1918 } 1919 1920 if (Ehc->DebugPortNum != 0) { 1921 State = EhcReadDbgRegister(Ehc, 0); 1922 if ((State & (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) != (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) { 1923 EhcResetHC (Ehc, EHC_RESET_TIMEOUT); 1924 } 1925 } 1926 1927 Status = EhcInitHC (Ehc); 1928 1929 if (EFI_ERROR (Status)) { 1930 DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to init host controller\n")); 1931 goto UNINSTALL_USBHC; 1932 } 1933 1934 // 1935 // Start the asynchronous interrupt monitor 1936 // 1937 Status = gBS->SetTimer (Ehc->PollTimer, TimerPeriodic, EHC_ASYNC_POLL_INTERVAL); 1938 1939 if (EFI_ERROR (Status)) { 1940 DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to start async interrupt monitor\n")); 1941 1942 EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT); 1943 goto UNINSTALL_USBHC; 1944 } 1945 1946 // 1947 // Create event to stop the HC when exit boot service. 1948 // 1949 Status = gBS->CreateEventEx ( 1950 EVT_NOTIFY_SIGNAL, 1951 TPL_NOTIFY, 1952 EhcExitBootService, 1953 Ehc, 1954 &gEfiEventExitBootServicesGuid, 1955 &Ehc->ExitBootServiceEvent 1956 ); 1957 if (EFI_ERROR (Status)) { 1958 goto UNINSTALL_USBHC; 1959 } 1960 1961 // 1962 // Install the component name protocol, don't fail the start 1963 // because of something for display. 1964 // 1965 AddUnicodeString2 ( 1966 "eng", 1967 gEhciComponentName.SupportedLanguages, 1968 &Ehc->ControllerNameTable, 1969 L"Enhanced Host Controller (USB 2.0)", 1970 TRUE 1971 ); 1972 AddUnicodeString2 ( 1973 "en", 1974 gEhciComponentName2.SupportedLanguages, 1975 &Ehc->ControllerNameTable, 1976 L"Enhanced Host Controller (USB 2.0)", 1977 FALSE 1978 ); 1979 1980 1981 DEBUG ((EFI_D_INFO, "EhcDriverBindingStart: EHCI started for controller @ %p\n", Controller)); 1982 return EFI_SUCCESS; 1983 1984 UNINSTALL_USBHC: 1985 gBS->UninstallProtocolInterface ( 1986 Controller, 1987 &gEfiUsb2HcProtocolGuid, 1988 &Ehc->Usb2Hc 1989 ); 1990 1991 FREE_POOL: 1992 EhcFreeSched (Ehc); 1993 gBS->CloseEvent (Ehc->PollTimer); 1994 gBS->FreePool (Ehc); 1995 1996 CLOSE_PCIIO: 1997 if (PciAttributesSaved) { 1998 // 1999 // Restore original PCI attributes 2000 // 2001 PciIo->Attributes ( 2002 PciIo, 2003 EfiPciIoAttributeOperationSet, 2004 OriginalPciAttributes, 2005 NULL 2006 ); 2007 } 2008 2009 gBS->CloseProtocol ( 2010 Controller, 2011 &gEfiPciIoProtocolGuid, 2012 This->DriverBindingHandle, 2013 Controller 2014 ); 2015 2016 return Status; 2017 } 2018 2019 2020 /** 2021 Stop this driver on ControllerHandle. Support stopping any child handles 2022 created by this driver. 2023 2024 @param This Protocol instance pointer. 2025 @param Controller Handle of device to stop driver on. 2026 @param NumberOfChildren Number of Children in the ChildHandleBuffer. 2027 @param ChildHandleBuffer List of handles for the children we need to stop. 2028 2029 @return EFI_SUCCESS Success. 2030 @return EFI_DEVICE_ERROR Fail. 2031 2032 **/ 2033 EFI_STATUS 2034 EFIAPI 2035 EhcDriverBindingStop ( 2036 IN EFI_DRIVER_BINDING_PROTOCOL *This, 2037 IN EFI_HANDLE Controller, 2038 IN UINTN NumberOfChildren, 2039 IN EFI_HANDLE *ChildHandleBuffer 2040 ) 2041 { 2042 EFI_STATUS Status; 2043 EFI_USB2_HC_PROTOCOL *Usb2Hc; 2044 EFI_PCI_IO_PROTOCOL *PciIo; 2045 USB2_HC_DEV *Ehc; 2046 2047 // 2048 // Test whether the Controller handler passed in is a valid 2049 // Usb controller handle that should be supported, if not, 2050 // return the error status directly 2051 // 2052 Status = gBS->OpenProtocol ( 2053 Controller, 2054 &gEfiUsb2HcProtocolGuid, 2055 (VOID **) &Usb2Hc, 2056 This->DriverBindingHandle, 2057 Controller, 2058 EFI_OPEN_PROTOCOL_GET_PROTOCOL 2059 ); 2060 2061 if (EFI_ERROR (Status)) { 2062 return Status; 2063 } 2064 2065 Ehc = EHC_FROM_THIS (Usb2Hc); 2066 PciIo = Ehc->PciIo; 2067 2068 Status = gBS->UninstallProtocolInterface ( 2069 Controller, 2070 &gEfiUsb2HcProtocolGuid, 2071 Usb2Hc 2072 ); 2073 2074 if (EFI_ERROR (Status)) { 2075 return Status; 2076 } 2077 2078 // 2079 // Stop AsyncRequest Polling timer then stop the EHCI driver 2080 // and uninstall the EHCI protocl. 2081 // 2082 gBS->SetTimer (Ehc->PollTimer, TimerCancel, EHC_ASYNC_POLL_INTERVAL); 2083 EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT); 2084 2085 if (Ehc->PollTimer != NULL) { 2086 gBS->CloseEvent (Ehc->PollTimer); 2087 } 2088 2089 if (Ehc->ExitBootServiceEvent != NULL) { 2090 gBS->CloseEvent (Ehc->ExitBootServiceEvent); 2091 } 2092 2093 EhcFreeSched (Ehc); 2094 2095 if (Ehc->ControllerNameTable != NULL) { 2096 FreeUnicodeStringTable (Ehc->ControllerNameTable); 2097 } 2098 2099 // 2100 // Disable routing of all ports to EHCI controller, so all ports are 2101 // routed back to the UHCI or OHCI controller. 2102 // 2103 EhcClearOpRegBit (Ehc, EHC_CONFIG_FLAG_OFFSET, CONFIGFLAG_ROUTE_EHC); 2104 2105 // 2106 // Restore original PCI attributes 2107 // 2108 PciIo->Attributes ( 2109 PciIo, 2110 EfiPciIoAttributeOperationSet, 2111 Ehc->OriginalPciAttributes, 2112 NULL 2113 ); 2114 2115 gBS->CloseProtocol ( 2116 Controller, 2117 &gEfiPciIoProtocolGuid, 2118 This->DriverBindingHandle, 2119 Controller 2120 ); 2121 2122 FreePool (Ehc); 2123 2124 return EFI_SUCCESS; 2125 } 2126 2127