From 09943f5ecc0fbc0c98c511c82703a0ba3b2b5819 Mon Sep 17 00:00:00 2001 From: erictian Date: Sat, 28 Apr 2012 05:02:54 +0000 Subject: [PATCH] MdeModulePkg: Skip to manage usb debug port in EDKII EHCI driver if it's used by usb debug port driver Signed-off-by: Feng Tian Reviewed-by: Jeff Fan git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13226 6f19259b-4bc3-4df7-8a09-765794883524 --- MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c | 151 ++++++++++++++++++++++++- MdeModulePkg/Bus/Pci/EhciDxe/Ehci.h | 18 ++- MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.c | 38 ++++++- MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.h | 22 +++- 4 files changed, 224 insertions(+), 5 deletions(-) diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c b/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c index c141803c38..64a0943ddc 100644 --- a/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c +++ b/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c @@ -120,6 +120,7 @@ EhcReset ( USB2_HC_DEV *Ehc; EFI_TPL OldTpl; EFI_STATUS Status; + UINT32 DbgCtrlStatus; OldTpl = gBS->RaiseTPL (EHC_TPL); Ehc = EHC_FROM_THIS (This); @@ -133,6 +134,14 @@ EhcReset ( // // Host Controller must be Halt when Reset it // + if (Ehc->DebugPortNum != 0) { + DbgCtrlStatus = EhcReadDbgRegister(Ehc, 0); + if ((DbgCtrlStatus & (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) == (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) { + Status = EFI_SUCCESS; + goto ON_EXIT; + } + } + if (!EhcIsHalt (Ehc)) { Status = EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT); @@ -323,6 +332,7 @@ EhcGetRootHubPortStatus ( UINTN Index; UINTN MapSize; EFI_STATUS Status; + UINT32 DbgCtrlStatus; if (PortStatus == NULL) { return EFI_INVALID_PARAMETER; @@ -344,6 +354,13 @@ EhcGetRootHubPortStatus ( PortStatus->PortStatus = 0; PortStatus->PortChangeStatus = 0; + if ((Ehc->DebugPortNum != 0) && (PortNumber == (Ehc->DebugPortNum - 1))) { + DbgCtrlStatus = EhcReadDbgRegister(Ehc, 0); + if ((DbgCtrlStatus & (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) == (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) { + goto ON_EXIT; + } + } + State = EhcReadOpReg (Ehc, Offset); // @@ -1390,6 +1407,129 @@ ON_EXIT: return Status; } +/** + Get the usb debug port related information. + + @param Ehc The EHCI device. + + @retval RETURN_SUCCESS Get debug port number, bar and offset successfully. + @retval Others The usb host controller does not supported usb debug port capability. + +**/ +EFI_STATUS +EhcGetUsbDebugPortInfo ( + IN USB2_HC_DEV *Ehc + ) +{ + EFI_PCI_IO_PROTOCOL *PciIo; + UINT16 PciStatus; + UINT8 CapabilityPtr; + UINT8 CapabilityId; + UINT16 DebugPort; + EFI_STATUS Status; + + ASSERT (Ehc->PciIo != NULL); + PciIo = Ehc->PciIo; + + // + // Detect if the EHCI host controller support Capaility Pointer. + // + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint8, + PCI_PRIMARY_STATUS_OFFSET, + sizeof (UINT16), + &PciStatus + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + if ((PciStatus & EFI_PCI_STATUS_CAPABILITY) == 0) { + // + // The Pci Device Doesn't Support Capability Pointer. + // + return EFI_UNSUPPORTED; + } + + // + // Get Pointer To Capability List + // + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint8, + PCI_CAPBILITY_POINTER_OFFSET, + 1, + &CapabilityPtr + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Find Capability ID 0xA, Which Is For Debug Port + // + while (CapabilityPtr != 0) { + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint8, + CapabilityPtr, + 1, + &CapabilityId + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + if (CapabilityId == EHC_DEBUG_PORT_CAP_ID) { + break; + } + + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint8, + CapabilityPtr + 1, + 1, + &CapabilityPtr + ); + + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // No Debug Port Capability Found + // + if (CapabilityPtr == 0) { + return EFI_UNSUPPORTED; + } + + // + // Get The Base Address Of Debug Port Register In Debug Port Capability Register + // + Status = PciIo->Pci.Read ( + Ehc->PciIo, + EfiPciIoWidthUint8, + CapabilityPtr + 2, + sizeof (UINT16), + &DebugPort + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Ehc->DebugPortOffset = DebugPort & 0x1FFF; + Ehc->DebugPortBarNum = (DebugPort >> 13) - 1; + Ehc->DebugPortNum = (UINT8)((Ehc->HcStructParams & 0x00F00000) >> 20); + + return EFI_SUCCESS; +} + /** Create and initialize a USB2_HC_DEV. @@ -1455,6 +1595,8 @@ EhcCreateUsb2Hc ( gBS->FreePool (Ehc); return NULL; } + + EhcGetUsbDebugPortInfo (Ehc); // // Create AsyncRequest Polling Timer @@ -1541,6 +1683,7 @@ EhcDriverBindingStart ( UINTN EhciBusNumber; UINTN EhciDeviceNumber; UINTN EhciFunctionNumber; + UINT32 State; // // Open the PciIo Protocol, then enable the USB host controller @@ -1727,7 +1870,13 @@ EhcDriverBindingStart ( if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) { EhcClearLegacySupport (Ehc); } - EhcResetHC (Ehc, EHC_RESET_TIMEOUT); + + if (Ehc->DebugPortNum != 0) { + State = EhcReadDbgRegister(Ehc, 0); + if ((State & (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) != (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) { + EhcResetHC (Ehc, EHC_RESET_TIMEOUT); + } + } Status = EhcInitHC (Ehc); diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.h b/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.h index f8d5444c38..42e4a6e6d9 100644 --- a/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.h +++ b/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.h @@ -2,7 +2,7 @@ Provides some data struct used by EHCI controller driver. -Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -70,11 +70,18 @@ typedef struct _USB2_HC_DEV USB2_HC_DEV; #define EHC_SYNC_POLL_INTERVAL (1 * EHC_1_MILLISECOND) #define EHC_ASYNC_POLL_INTERVAL (50 * 10000U) +// +// EHCI debug port control status register bit definition +// +#define USB_DEBUG_PORT_IN_USE BIT10 +#define USB_DEBUG_PORT_ENABLE BIT28 +#define USB_DEBUG_PORT_OWNER BIT30 + // // EHC raises TPL to TPL_NOTIFY to serialize all its operations // to protect shared data structures. // -#define EHC_TPL TPL_NOTIFY +#define EHC_TPL TPL_NOTIFY // //Iterate through the doule linked list. NOT delete safe @@ -157,6 +164,13 @@ struct _USB2_HC_DEV { // Misc // EFI_UNICODE_STRING_TABLE *ControllerNameTable; + + // + // EHCI debug port info + // + UINT16 DebugPortOffset; // The offset of debug port mmio register + UINT8 DebugPortBarNum; // The bar number of debug port mmio register + UINT8 DebugPortNum; // The port number of usb debug port }; diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.c b/MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.c index 252e3d5fa2..88a66aee71 100644 --- a/MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.c +++ b/MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.c @@ -2,7 +2,7 @@ The EHCI register operation routines. -Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.
+Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -53,6 +53,42 @@ EhcReadCapRegister ( return Data; } +/** + Read EHCI debug port register. + + @param Ehc The EHCI device. + @param Offset Debug port register offset. + + @return The register content read. + @retval If err, return 0xffff. + +**/ +UINT32 +EhcReadDbgRegister ( + IN USB2_HC_DEV *Ehc, + IN UINT32 Offset + ) +{ + UINT32 Data; + EFI_STATUS Status; + + Status = Ehc->PciIo->Mem.Read ( + Ehc->PciIo, + EfiPciIoWidthUint32, + Ehc->DebugPortBarNum, + (UINT64) (Ehc->DebugPortOffset + Offset), + 1, + &Data + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "EhcReadDbgRegister: Pci Io read error - %r at %d\n", Status, Offset)); + Data = 0xFFFF; + } + + return Data; +} + /** Read EHCI Operation register. diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.h b/MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.h index d1f38d38f0..2347ee125f 100644 --- a/MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.h +++ b/MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.h @@ -2,7 +2,7 @@ This file contains the definination for host controller register operation routines. -Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.
+Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -89,6 +89,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. // #define EHC_BAR_INDEX 0 // how many bytes away from USB_BASE to 0x10 +// +// Debug port capability id +// +#define EHC_DEBUG_PORT_CAP_ID 0x0A + #define EHC_LINK_TERMINATED(Link) (((Link) & 0x01) != 0) #define EHC_ADDR(High, QhHw32) \ @@ -131,6 +136,21 @@ EhcReadCapRegister ( IN UINT32 Offset ); +/** + Read EHCI debug port register. + + @param Ehc The EHCI device. + @param Offset Debug port register address. + + @return The register content read. + @retval If err, return 0xffff. + +**/ +UINT32 +EhcReadDbgRegister ( + IN USB2_HC_DEV *Ehc, + IN UINT32 Offset + ); /** Read EHCI Operation register.