X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FBus%2FPci%2FEhciDxe%2FEhci.c;h=32ae6b6cdcfd040f2ef004ab95c55beaf0577535;hp=13ce7fdfb1f9f9f58b4e57f107e46d12a8103642;hb=68246fa809e4a8ab61ce7bbfdd1a0b31d03e83fb;hpb=f527bce3d07ff80c7fff9684b2c7cdc02805c32e diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c b/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c index 13ce7fdfb1..32ae6b6cdc 100644 --- a/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c +++ b/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c @@ -126,7 +126,7 @@ EhcReset ( // Host Controller must be Halt when Reset it // if (!EhcIsHalt (Ehc)) { - Status = EhcHaltHC (Ehc, EHC_GENERIC_TIME); + Status = EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT); if (EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; @@ -142,7 +142,7 @@ EhcReset ( EhcAckAllInterrupt (Ehc); EhcFreeSched (Ehc); - Status = EhcResetHC (Ehc, EHC_STALL_1_SECOND); + Status = EhcResetHC (Ehc, EHC_RESET_TIMEOUT); if (EFI_ERROR (Status)) { goto ON_EXIT; @@ -251,7 +251,7 @@ EhcSetState ( switch (State) { case EfiUsbHcStateHalt: - Status = EhcHaltHC (Ehc, EHC_GENERIC_TIME); + Status = EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT); break; case EfiUsbHcStateOperational: @@ -260,7 +260,17 @@ EhcSetState ( break; } - Status = EhcRunHC (Ehc, EHC_GENERIC_TIME); + // + // Software must not write a one to this field unless the host controller + // is in the Halted state. Doing so will yield undefined results. + // refers to Spec[EHCI1.0-2.3.1] + // + if (!EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) { + Status = EFI_DEVICE_ERROR; + break; + } + + Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT); break; case EfiUsbHcStateSuspend: @@ -437,7 +447,7 @@ EhcSetRootHubPortFeature ( // Make sure Host Controller not halt before reset it // if (EhcIsHalt (Ehc)) { - Status = EhcRunHC (Ehc, EHC_GENERIC_TIME); + Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT); if (EFI_ERROR (Status)) { EHC_DEBUG (("EhcSetRootHubPortFeature :failed to start HC - %r\n", Status)); @@ -1385,7 +1395,8 @@ ON_EXIT: /** Create and initialize a USB2_HC_DEV - @param PciIo The PciIo on this device + @param PciIo The PciIo on this device + @param OriginalPciAttributes Original PCI attributes @return The allocated and initialized USB2_HC_DEV structure @return if created, otherwise NULL. @@ -1394,7 +1405,8 @@ ON_EXIT: STATIC USB2_HC_DEV * EhcCreateUsb2Hc ( - IN EFI_PCI_IO_PROTOCOL *PciIo + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT64 OriginalPciAttributes ) { USB2_HC_DEV *Ehc; @@ -1427,7 +1439,8 @@ EhcCreateUsb2Hc ( Ehc->Usb2Hc.MajorRevision = 0x1; Ehc->Usb2Hc.MinorRevision = 0x1; - Ehc->PciIo = PciIo; + Ehc->PciIo = PciIo; + Ehc->OriginalPciAttributes = OriginalPciAttributes; InitializeListHead (&Ehc->AsyncIntTransfers); @@ -1481,6 +1494,8 @@ EhcDriverBindingStart ( EFI_STATUS Status; USB2_HC_DEV *Ehc; EFI_PCI_IO_PROTOCOL *PciIo; + UINT64 Supports; + UINT64 OriginalPciAttributes; // // Open the PciIo Protocol, then enable the USB host controller @@ -1499,12 +1514,35 @@ EhcDriverBindingStart ( return EFI_DEVICE_ERROR; } + // + // Save original PCI attributes + // + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationGet, + 0, + &OriginalPciAttributes + ); + + if (EFI_ERROR (Status)) { + return Status; + } + Status = PciIo->Attributes ( PciIo, - EfiPciIoAttributeOperationEnable, - EFI_PCI_DEVICE_ENABLE, - NULL + EfiPciIoAttributeOperationSupported, + 0, + &Supports ); + if (!EFI_ERROR (Status)) { + Supports &= EFI_PCI_DEVICE_ENABLE; + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + Supports, + NULL + ); + } if (EFI_ERROR (Status)) { EHC_ERROR (("EhcDriverBindingStart: failed to enable controller\n")); @@ -1514,7 +1552,7 @@ EhcDriverBindingStart ( // // Create then install USB2_HC_PROTOCOL // - Ehc = EhcCreateUsb2Hc (PciIo); + Ehc = EhcCreateUsb2Hc (PciIo, OriginalPciAttributes); if (Ehc == NULL) { EHC_ERROR (("EhcDriverBindingStart: failed to create USB2_HC\n")); @@ -1539,7 +1577,7 @@ EhcDriverBindingStart ( // Robustnesss improvement such as for UoL // EhcClearLegacySupport (Ehc); - EhcResetHC (Ehc, EHC_STALL_1_SECOND); + EhcResetHC (Ehc, EHC_RESET_TIMEOUT); Status = EhcInitHC (Ehc); @@ -1551,12 +1589,12 @@ EhcDriverBindingStart ( // // Start the asynchronous interrupt monitor // - Status = gBS->SetTimer (Ehc->PollTimer, TimerPeriodic, EHC_ASYNC_POLL_TIME); + Status = gBS->SetTimer (Ehc->PollTimer, TimerPeriodic, EHC_ASYNC_POLL_INTERVAL); if (EFI_ERROR (Status)) { EHC_ERROR (("EhcDriverBindingStart: failed to start async interrupt monitor\n")); - EhcHaltHC (Ehc, EHC_GENERIC_TIME); + EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT); goto UNINSTALL_USBHC; } @@ -1596,6 +1634,16 @@ FREE_POOL: gBS->FreePool (Ehc); CLOSE_PCIIO: + // + // Restore original PCI attributes + // + PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationSet, + OriginalPciAttributes, + NULL + ); + gBS->CloseProtocol ( Controller, &gEfiPciIoProtocolGuid, @@ -1659,8 +1707,8 @@ EhcDriverBindingStop ( // Stop AsyncRequest Polling timer then stop the EHCI driver // and uninstall the EHCI protocl. // - gBS->SetTimer (Ehc->PollTimer, TimerCancel, EHC_ASYNC_POLL_TIME); - EhcHaltHC (Ehc, EHC_GENERIC_TIME); + gBS->SetTimer (Ehc->PollTimer, TimerCancel, EHC_ASYNC_POLL_INTERVAL); + EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT); Status = gBS->UninstallProtocolInterface ( Controller, @@ -1683,14 +1731,14 @@ EhcDriverBindingStop ( } // - // Disable the USB Host Controller + // Restore original PCI attributes // PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationDisable, - EFI_PCI_DEVICE_ENABLE, - NULL - ); + PciIo, + EfiPciIoAttributeOperationSet, + Ehc->OriginalPciAttributes, + NULL + ); gBS->CloseProtocol ( Controller, @@ -1699,8 +1747,9 @@ EhcDriverBindingStop ( Controller ); - gBS->FreePool (Ehc); - return Status; + FreePool (Ehc); + + return EFI_SUCCESS; } EFI_DRIVER_BINDING_PROTOCOL