git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@1037 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1540 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1540 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*++
 | |
| 
 | |
| Copyright (c) 2006, 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        
 | |
| http://opensource.org/licenses/bsd-license.php                                            
 | |
|                                                                                           
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
 | |
| 
 | |
| Module Name:
 | |
| 
 | |
|     Ehchlp.c
 | |
|     
 | |
| Abstract: 
 | |
|     
 | |
| 
 | |
| Revision History
 | |
| --*/
 | |
| 
 | |
| #include "Ehci.h"
 | |
| 
 | |
| 
 | |
| EFI_STATUS
 | |
| ReadEhcCapabiltiyReg (
 | |
|   IN USB2_HC_DEV             *HcDev,
 | |
|   IN UINT32                  CapabiltiyRegAddr,
 | |
|   IN OUT UINT32              *Data
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Read  Ehc Capabitlity register
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev              - USB2_HC_DEV 
 | |
|   CapabiltiyRegAddr  - Ehc Capability register address
 | |
|   Data               - A pointer to data read from register
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS        Success
 | |
|   EFI_DEVICE_ERROR   Fail
 | |
|     
 | |
| --*/
 | |
| {
 | |
|   return HcDev->PciIo->Mem.Read (
 | |
|                              HcDev->PciIo,
 | |
|                              EfiPciIoWidthUint32,
 | |
|                              USB_BAR_INDEX,
 | |
|                              (UINT64) CapabiltiyRegAddr,
 | |
|                              1,
 | |
|                              Data
 | |
|                              );
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| ReadEhcOperationalReg (
 | |
|   IN USB2_HC_DEV             *HcDev,
 | |
|   IN UINT32                  OperationalRegAddr,
 | |
|   IN OUT UINT32              *Data
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Read  Ehc Operation register
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev                - USB2_HC_DEV 
 | |
|   OperationalRegAddr   - Ehc Operation register address
 | |
|   Data                 - A pointer to data read from register
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS        Success
 | |
|   EFI_DEVICE_ERROR   Fail
 | |
|     
 | |
| --*/
 | |
| {
 | |
|   ASSERT (mUsbCapabilityLen);
 | |
|   return HcDev->PciIo->Mem.Read (
 | |
|                              HcDev->PciIo,
 | |
|                              EfiPciIoWidthUint32,
 | |
|                              USB_BAR_INDEX,
 | |
|                              (UINT64) (OperationalRegAddr + mUsbCapabilityLen),
 | |
|                              1,
 | |
|                              Data
 | |
|                              );
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| WriteEhcOperationalReg (
 | |
|   IN USB2_HC_DEV             *HcDev,
 | |
|   IN UINT32                  OperationalRegAddr,
 | |
|   IN UINT32                  Data
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Write  Ehc Operation register
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev                - USB2_HC_DEV 
 | |
|   OperationalRegAddr   - Ehc Operation register address
 | |
|   Data                 - 32bit write to register
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS        Success
 | |
|   EFI_DEVICE_ERROR   Fail
 | |
|   
 | |
| --*/
 | |
| {
 | |
|   ASSERT (mUsbCapabilityLen);
 | |
|   return HcDev->PciIo->Mem.Write (
 | |
|                              HcDev->PciIo,
 | |
|                              EfiPciIoWidthUint32,
 | |
|                              USB_BAR_INDEX,
 | |
|                              (UINT64) (OperationalRegAddr + mUsbCapabilityLen),
 | |
|                              1,
 | |
|                              &Data
 | |
|                              );
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| GetCapabilityLen (
 | |
|   IN USB2_HC_DEV     *HcDev
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Get the length of capability register
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev - USB2_HC_DEV 
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS       Success
 | |
|   EFI_DEVICE_ERROR  Fail
 | |
|     
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINT32      CapabilityLenAddr;
 | |
| 
 | |
|   CapabilityLenAddr = CAPLENGTH;
 | |
| 
 | |
|   Status = ReadEhcCapabiltiyReg (
 | |
|              HcDev,
 | |
|              CapabilityLenAddr,
 | |
|              &mUsbCapabilityLen
 | |
|              );
 | |
|   mUsbCapabilityLen = (UINT8) mUsbCapabilityLen;
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| SetFrameListLen (
 | |
|   IN USB2_HC_DEV     *HcDev,
 | |
|   IN UINTN           Length
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Set the length of Frame List
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev    - USB2_HC_DEV 
 | |
|   Length   - the required length of frame list
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS            Success
 | |
|   EFI_INVALID_PARAMETER  Invalid parameter
 | |
|   EFI_DEVICE_ERROR       Fail
 | |
|   
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINT32      UsbCommandAddr;
 | |
|   UINT32      UsbCommandReg;
 | |
| 
 | |
|   UsbCommandAddr = USBCMD;
 | |
| 
 | |
|   if (256 != Length && 512 != Length) {
 | |
|     Status = EFI_INVALID_PARAMETER;
 | |
|     goto exit;
 | |
|   }
 | |
| 
 | |
|   Status = ReadEhcOperationalReg (
 | |
|              HcDev,
 | |
|              UsbCommandAddr,
 | |
|              &UsbCommandReg
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Status = EFI_DEVICE_ERROR;
 | |
|     goto exit;
 | |
|   }
 | |
| 
 | |
|   if (256 == Length) {
 | |
|     UsbCommandReg |= USBCMD_FLS_256;
 | |
|   } else {
 | |
|     UsbCommandReg |= USBCMD_FLS_512;
 | |
|   }
 | |
| 
 | |
|   Status = WriteEhcOperationalReg (
 | |
|              HcDev,
 | |
|              UsbCommandAddr,
 | |
|              UsbCommandReg
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Status = EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
| exit:
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| SetFrameListBaseAddr (
 | |
|   IN USB2_HC_DEV     *HcDev,
 | |
|   IN UINT32          FrameBuffer
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Set base address of frame list first entry
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev        - USB2_HC_DEV 
 | |
|   FrameBuffer  - base address of first entry of frame list
 | |
|   
 | |
| Returns:
 | |
|   
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINT32      PeriodicListBaseAddr;
 | |
|   UINT32      PeriodicListBaseReg;
 | |
| 
 | |
|   Status                = EFI_SUCCESS;
 | |
|   PeriodicListBaseAddr  = PERIODICLISTBASE;
 | |
|   PeriodicListBaseReg   = FrameBuffer & 0xfffff000;
 | |
| 
 | |
|   if (IsEhcHalted (HcDev)) {
 | |
| 
 | |
|     Status = WriteEhcOperationalReg (
 | |
|                HcDev,
 | |
|                PeriodicListBaseAddr,
 | |
|                PeriodicListBaseReg
 | |
|                );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       Status = EFI_DEVICE_ERROR;
 | |
|       goto exit;
 | |
|     }
 | |
| 
 | |
|   }
 | |
| 
 | |
| exit:
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| SetAsyncListAddr (
 | |
|   IN USB2_HC_DEV        *HcDev,
 | |
|   IN EHCI_QH_ENTITY     *QhPtr
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Set address of first Async schedule Qh
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev   - USB2_HC_DEV 
 | |
|   QhPtr   - A pointer to first Qh in the Async schedule
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS       Success
 | |
|   EFI_DEVICE_ERROR  Fail
 | |
|     
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINT32      AsyncListAddr;
 | |
|   UINT32      AsyncListReg;
 | |
| 
 | |
|   AsyncListAddr = ASYNCLISTADDR;
 | |
|   AsyncListReg  = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh));
 | |
| 
 | |
|   Status = WriteEhcOperationalReg (
 | |
|              HcDev,
 | |
|              AsyncListAddr,
 | |
|              AsyncListReg
 | |
|              );
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| SetCtrlDataStructSeg (
 | |
|   IN USB2_HC_DEV     *HcDev
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Set register of control and data structure segment
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev  - USB2_HC_DEV 
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS       Success
 | |
|   EFI_DEVICE_ERROR  Fail
 | |
|   
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINT32      CtrlDsSegmentAddr;
 | |
|   UINT32      CtrlDsSegmentReg;
 | |
| 
 | |
|   CtrlDsSegmentAddr = CTRLDSSGMENT;
 | |
|   CtrlDsSegmentReg  = HcDev->High32BitAddr;
 | |
| 
 | |
|   Status = WriteEhcOperationalReg (
 | |
|              HcDev,
 | |
|              CtrlDsSegmentAddr,
 | |
|              CtrlDsSegmentReg
 | |
|              );
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| SetPortRoutingEhc (
 | |
|   IN USB2_HC_DEV     *HcDev
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Set Ehc port routing bit
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev - USB2_HC_DEV 
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS       Success
 | |
|   EFI_DEVICE_ERROR  Fail
 | |
|     
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINT32      ConfigFlagAddr;
 | |
|   UINT32      ConfigFlagReg;
 | |
| 
 | |
|   ConfigFlagAddr = CONFIGFLAG;
 | |
| 
 | |
|   Status = ReadEhcOperationalReg (
 | |
|              HcDev,
 | |
|              ConfigFlagAddr,
 | |
|              &ConfigFlagReg
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Status = EFI_DEVICE_ERROR;
 | |
|     goto exit;
 | |
|   }
 | |
| 
 | |
|   ConfigFlagReg |= CONFIGFLAG_CF;
 | |
|   Status = WriteEhcOperationalReg (
 | |
|              HcDev,
 | |
|              ConfigFlagAddr,
 | |
|              ConfigFlagReg
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Status = EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
| exit:
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| SetEhcDoorbell (
 | |
|   IN  USB2_HC_DEV     *HcDev
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Set Ehc door bell bit
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev - USB2_HC_DEV 
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS       Success
 | |
|   EFI_DEVICE_ERROR  Fail
 | |
|      
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINT32      UsbCommandAddr;
 | |
|   UINT32      UsbCommandReg;
 | |
| 
 | |
|   UsbCommandAddr = USBCMD;
 | |
| 
 | |
|   Status = ReadEhcOperationalReg (
 | |
|              HcDev,
 | |
|              UsbCommandAddr,
 | |
|              &UsbCommandReg
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Status = EFI_DEVICE_ERROR;
 | |
|     goto exit;
 | |
|   }
 | |
| 
 | |
|   UsbCommandReg |= USBCMD_IAAD;
 | |
|   Status = WriteEhcOperationalReg (
 | |
|              HcDev,
 | |
|              UsbCommandAddr,
 | |
|              UsbCommandReg
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Status = EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
| exit:
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| ClearEhcAllStatus (
 | |
|   IN  USB2_HC_DEV     *HcDev
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Clear Ehc all status bits
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev - USB2_HC_DEV 
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS       Success
 | |
|   EFI_DEVICE_ERROR  Fail
 | |
|      
 | |
| --*/
 | |
| {
 | |
|   UINT32  UsbStatusAddr;
 | |
| 
 | |
|   UsbStatusAddr = USBSTS;
 | |
| 
 | |
|   return WriteEhcOperationalReg (
 | |
|            HcDev,
 | |
|            UsbStatusAddr,
 | |
|            0x003F
 | |
|            );
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EnablePeriodicSchedule (
 | |
|   IN  USB2_HC_DEV     *HcDev
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Enable periodic schedule
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev - USB2_HC_DEV 
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS       Success
 | |
|   EFI_DEVICE_ERROR  Fail
 | |
|    
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINT32      UsbCommandAddr;
 | |
|   UINT32      UsbCommandReg;
 | |
| 
 | |
|   UsbCommandAddr = USBCMD;
 | |
| 
 | |
|   Status = ReadEhcOperationalReg (
 | |
|              HcDev,
 | |
|              UsbCommandAddr,
 | |
|              &UsbCommandReg
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Status = EFI_DEVICE_ERROR;
 | |
|     goto exit;
 | |
|   }
 | |
| 
 | |
|   UsbCommandReg |= USBCMD_PSE;
 | |
|   Status = WriteEhcOperationalReg (
 | |
|              HcDev,
 | |
|              UsbCommandAddr,
 | |
|              UsbCommandReg
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Status = EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
| exit:
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| DisablePeriodicSchedule (
 | |
|   IN  USB2_HC_DEV     *HcDev
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Disable periodic schedule
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev - USB2_HC_DEV 
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS       Success
 | |
|   EFI_DEVICE_ERROR  Fail
 | |
|    
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINT32      UsbCommandAddr;
 | |
|   UINT32      UsbCommandReg;
 | |
| 
 | |
|   UsbCommandAddr = USBCMD;
 | |
| 
 | |
|   Status = ReadEhcOperationalReg (
 | |
|              HcDev,
 | |
|              UsbCommandAddr,
 | |
|              &UsbCommandReg
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   UsbCommandReg &= ~USBCMD_PSE;
 | |
|   Status = WriteEhcOperationalReg (
 | |
|              HcDev,
 | |
|              UsbCommandAddr,
 | |
|              UsbCommandReg
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EnableAsynchronousSchedule (
 | |
|   IN  USB2_HC_DEV     *HcDev
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Enable asynchrounous schedule
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev - USB2_HC_DEV 
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS       Success
 | |
|   EFI_DEVICE_ERROR  Fail
 | |
|     
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINT32      UsbCommandAddr;
 | |
|   UINT32      UsbCommandReg;
 | |
| 
 | |
|   UsbCommandAddr = USBCMD;
 | |
| 
 | |
|   Status = ReadEhcOperationalReg (
 | |
|              HcDev,
 | |
|              UsbCommandAddr,
 | |
|              &UsbCommandReg
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Status = EFI_DEVICE_ERROR;
 | |
|     goto exit;
 | |
|   }
 | |
| 
 | |
|   UsbCommandReg |= USBCMD_ASE;
 | |
|   Status = WriteEhcOperationalReg (
 | |
|              HcDev,
 | |
|              UsbCommandAddr,
 | |
|              UsbCommandReg
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Status = EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
| exit:
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| DisableAsynchronousSchedule (
 | |
|   IN  USB2_HC_DEV     *HcDev
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Disable asynchrounous schedule
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev - USB2_HC_DEV 
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS       Success
 | |
|   EFI_DEVICE_ERROR  Fail
 | |
|    
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINT32      UsbCommandAddr;
 | |
|   UINT32      UsbCommandReg;
 | |
| 
 | |
|   UsbCommandAddr = USBCMD;
 | |
| 
 | |
|   Status = ReadEhcOperationalReg (
 | |
|              HcDev,
 | |
|              UsbCommandAddr,
 | |
|              &UsbCommandReg
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   UsbCommandReg &= ~USBCMD_ASE;
 | |
|   Status = WriteEhcOperationalReg (
 | |
|              HcDev,
 | |
|              UsbCommandAddr,
 | |
|              UsbCommandReg
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| ResetEhc (
 | |
|   IN  USB2_HC_DEV     *HcDev
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Reset Ehc
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev - USB2_HC_DEV 
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS       Success
 | |
|   EFI_DEVICE_ERROR  Fail
 | |
|    
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINT32      UsbCommandAddr;
 | |
|   UINT32      UsbCommandReg;
 | |
| 
 | |
|   UsbCommandAddr = USBCMD;
 | |
| 
 | |
|   Status = ReadEhcOperationalReg (
 | |
|              HcDev,
 | |
|              UsbCommandAddr,
 | |
|              &UsbCommandReg
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Status = EFI_DEVICE_ERROR;
 | |
|     goto exit;
 | |
|   }
 | |
| 
 | |
|   UsbCommandReg |= USBCMD_HCRESET;
 | |
|   Status = WriteEhcOperationalReg (
 | |
|              HcDev,
 | |
|              UsbCommandAddr,
 | |
|              UsbCommandReg
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Status = EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
| exit:
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| StartScheduleExecution (
 | |
|   IN  USB2_HC_DEV     *HcDev
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Start Ehc schedule execution
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev - USB2_HC_DEV 
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS       Success
 | |
|   EFI_DEVICE_ERROR  Fail
 | |
|    
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINT32      UsbCommandAddr;
 | |
|   UINT32      UsbCommandReg;
 | |
| 
 | |
|   UsbCommandAddr = USBCMD;
 | |
| 
 | |
|   Status = ReadEhcOperationalReg (
 | |
|              HcDev,
 | |
|              UsbCommandAddr,
 | |
|              &UsbCommandReg
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Status = EFI_DEVICE_ERROR;
 | |
|     goto exit;
 | |
|   }
 | |
| 
 | |
|   UsbCommandReg |= USBCMD_RS;
 | |
|   Status = WriteEhcOperationalReg (
 | |
|              HcDev,
 | |
|              UsbCommandAddr,
 | |
|              UsbCommandReg
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Status = EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
| exit:
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| BOOLEAN
 | |
| IsFrameListProgrammable (
 | |
|   IN  USB2_HC_DEV     *HcDev
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Whether frame list is programmable
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev - USB2_HC_DEV 
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   TRUE   Programmable
 | |
|   FALSE  Unprogrammable
 | |
|   
 | |
| --*/
 | |
| {
 | |
|   BOOLEAN Value;
 | |
|   UINT32  HcCapParamsAddr;
 | |
|   UINT32  HcCapParamsReg;
 | |
| 
 | |
|   HcCapParamsAddr = HCCPARAMS;
 | |
| 
 | |
|   ReadEhcOperationalReg (
 | |
|     HcDev,
 | |
|     HcCapParamsAddr,
 | |
|     &HcCapParamsReg
 | |
|     );
 | |
| 
 | |
|   if (HcCapParamsReg & HCCP_PFLF) {
 | |
|     Value = TRUE;
 | |
|   } else {
 | |
|     Value = FALSE;
 | |
|   }
 | |
| 
 | |
|   return Value;
 | |
| }
 | |
| 
 | |
| BOOLEAN
 | |
| IsPeriodicScheduleEnabled (
 | |
|   IN  USB2_HC_DEV     *HcDev
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Whether periodic schedule is enabled
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev - USB2_HC_DEV 
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   TRUE    Enabled
 | |
|   FALSE   Disabled
 | |
|   
 | |
| --*/
 | |
| {
 | |
|   BOOLEAN Value;
 | |
|   UINT32  UsbStatusAddr;
 | |
|   UINT32  UsbStatusReg;
 | |
| 
 | |
|   UsbStatusAddr = USBSTS;
 | |
| 
 | |
|   ReadEhcOperationalReg (
 | |
|     HcDev,
 | |
|     UsbStatusAddr,
 | |
|     &UsbStatusReg
 | |
|     );
 | |
| 
 | |
|   if (UsbStatusReg & USBSTS_PSS) {
 | |
|     Value = TRUE;
 | |
|   } else {
 | |
|     Value = FALSE;
 | |
|   }
 | |
| 
 | |
|   return Value;
 | |
| }
 | |
| 
 | |
| BOOLEAN
 | |
| IsAsyncScheduleEnabled (
 | |
|   IN  USB2_HC_DEV     *HcDev
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Whether asynchronous schedule is enabled
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev - USB2_HC_DEV 
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   TRUE   Enabled
 | |
|   FALSE  Disabled
 | |
|   
 | |
| --*/
 | |
| {
 | |
|   BOOLEAN Value;
 | |
|   UINT32  UsbStatusAddr;
 | |
|   UINT32  UsbStatusReg;
 | |
| 
 | |
|   UsbStatusAddr = USBSTS;
 | |
| 
 | |
|   ReadEhcOperationalReg (
 | |
|     HcDev,
 | |
|     UsbStatusAddr,
 | |
|     &UsbStatusReg
 | |
|     );
 | |
| 
 | |
|   if (UsbStatusReg & USBSTS_ASS) {
 | |
|     Value = TRUE;
 | |
|   } else {
 | |
|     Value = FALSE;
 | |
|   }
 | |
| 
 | |
|   return Value;
 | |
| }
 | |
| 
 | |
| BOOLEAN
 | |
| IsEhcPortEnabled (
 | |
|   IN  USB2_HC_DEV     *HcDev,
 | |
|   IN  UINT8           PortNum
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Whether port is enabled
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev - USB2_HC_DEV 
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   TRUE   Enabled
 | |
|   FALSE  Disabled
 | |
|   
 | |
| --*/
 | |
| {
 | |
|   UINT32  PortStatusControlAddr;
 | |
|   UINT32  PortStatusControlReg;
 | |
| 
 | |
|   PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNum));
 | |
| 
 | |
|   ReadEhcOperationalReg (
 | |
|     HcDev,
 | |
|     PortStatusControlAddr,
 | |
|     &PortStatusControlReg
 | |
|     );
 | |
| 
 | |
|   return ((PortStatusControlReg & PORTSC_PED) ? TRUE : FALSE);
 | |
| }
 | |
| 
 | |
| BOOLEAN
 | |
| IsEhcReseted (
 | |
|   IN  USB2_HC_DEV     *HcDev
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Whether Ehc is reseted
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev - USB2_HC_DEV 
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   TRUE   Reseted
 | |
|   FALSE  Unreseted
 | |
|   
 | |
| --*/
 | |
| {
 | |
|   BOOLEAN Value;
 | |
|   UINT32  UsbCommandAddr;
 | |
|   UINT32  UsbCommandReg;
 | |
| 
 | |
|   UsbCommandAddr = USBCMD;
 | |
| 
 | |
|   ReadEhcOperationalReg (
 | |
|     HcDev,
 | |
|     UsbCommandAddr,
 | |
|     &UsbCommandReg
 | |
|     );
 | |
| 
 | |
|   if (UsbCommandReg & USBCMD_HCRESET) {
 | |
|     Value = FALSE;
 | |
|   } else {
 | |
|     Value = TRUE;
 | |
|   }
 | |
| 
 | |
|   return Value;
 | |
| }
 | |
| 
 | |
| BOOLEAN
 | |
| IsEhcHalted (
 | |
|   IN  USB2_HC_DEV     *HcDev
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Whether Ehc is halted
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev - USB2_HC_DEV 
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   TRUE   Halted
 | |
|   FALSE  Not halted
 | |
|   
 | |
| --*/
 | |
| {
 | |
|   BOOLEAN Value;
 | |
|   UINT32  UsbStatusAddr;
 | |
|   UINT32  UsbStatusReg;
 | |
| 
 | |
|   UsbStatusAddr = USBSTS;
 | |
| 
 | |
|   ReadEhcOperationalReg (
 | |
|     HcDev,
 | |
|     UsbStatusAddr,
 | |
|     &UsbStatusReg
 | |
|     );
 | |
| 
 | |
|   if (UsbStatusReg & USBSTS_HCH) {
 | |
|     Value = TRUE;
 | |
|   } else {
 | |
|     Value = FALSE;
 | |
|   }
 | |
| 
 | |
|   return Value;
 | |
| }
 | |
| 
 | |
| BOOLEAN
 | |
| IsEhcSysError (
 | |
|   IN  USB2_HC_DEV     *HcDev
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Whether Ehc is system error
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev - USB2_HC_DEV 
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   TRUE   System error
 | |
|   FALSE  No system error
 | |
|   
 | |
| --*/
 | |
| {
 | |
|   BOOLEAN Value;
 | |
|   UINT32  UsbStatusAddr;
 | |
|   UINT32  UsbStatusReg;
 | |
| 
 | |
|   UsbStatusAddr = USBSTS;
 | |
| 
 | |
|   ReadEhcOperationalReg (
 | |
|     HcDev,
 | |
|     UsbStatusAddr,
 | |
|     &UsbStatusReg
 | |
|     );
 | |
| 
 | |
|   if (UsbStatusReg & USBSTS_HSE) {
 | |
|     Value = TRUE;
 | |
|   } else {
 | |
|     Value = FALSE;
 | |
|   }
 | |
| 
 | |
|   return Value;
 | |
| }
 | |
| 
 | |
| BOOLEAN
 | |
| IsHighSpeedDevice (
 | |
|   IN EFI_USB2_HC_PROTOCOL *This,
 | |
|   IN UINT8                PortNum 
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Whether high speed device attached
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev - USB2_HC_DEV 
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   TRUE   High speed
 | |
|   FALSE  Full speed
 | |
|   
 | |
| --*/
 | |
| {
 | |
|   USB2_HC_DEV          *HcDev;
 | |
|   UINT32               PortStatusControlAddr;
 | |
|   UINT32               PortStatusControlReg;
 | |
|   
 | |
|   HcDev = USB2_HC_DEV_FROM_THIS (This);
 | |
|   PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNum));
 | |
| 
 | |
|   //
 | |
|   // Set port reset bit
 | |
|   //
 | |
|   ReadEhcOperationalReg (
 | |
|     HcDev,
 | |
|     PortStatusControlAddr,
 | |
|     &PortStatusControlReg
 | |
|     );
 | |
|   //
 | |
|   // Make sure Host Controller not halt before reset it
 | |
|   //
 | |
|   if (IsEhcHalted (HcDev)) {
 | |
|     StartScheduleExecution (HcDev);
 | |
|     WaitForEhcNotHalt (HcDev, EHCI_GENERIC_TIMEOUT);
 | |
|   }
 | |
|   PortStatusControlReg &= 0xffffffd5;
 | |
|   PortStatusControlReg |= PORTSC_PR;
 | |
|   //
 | |
|   // Set one to PortReset bit must also set zero to PortEnable bit
 | |
|   //
 | |
|   PortStatusControlReg &= ~PORTSC_PED;
 | |
|   WriteEhcOperationalReg (
 | |
|     HcDev,
 | |
|     PortStatusControlAddr,
 | |
|     PortStatusControlReg
 | |
|     );
 | |
| 
 | |
|   //
 | |
|   // Set Port reset recovery time
 | |
|   //
 | |
|   gBS->Stall (EHCI_SET_PORT_RESET_RECOVERY_TIME);
 | |
| 
 | |
|   //
 | |
|   // Clear port reset bit
 | |
|   //
 | |
|   ReadEhcOperationalReg (
 | |
|     HcDev,
 | |
|     PortStatusControlAddr,
 | |
|     &PortStatusControlReg
 | |
|     );
 | |
|   PortStatusControlReg &= 0xffffffd5;
 | |
|   PortStatusControlReg &= ~PORTSC_PR;
 | |
|   WriteEhcOperationalReg (
 | |
|     HcDev,
 | |
|     PortStatusControlAddr,
 | |
|     PortStatusControlReg
 | |
|     );
 | |
| 
 | |
|   //
 | |
|   // Clear port reset recovery time
 | |
|   //
 | |
|   gBS->Stall (EHCI_CLEAR_PORT_RESET_RECOVERY_TIME);
 | |
| 
 | |
|   return (IsEhcPortEnabled (HcDev, PortNum) ? TRUE : FALSE);
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| WaitForEhcReset (
 | |
|   IN USB2_HC_DEV             *HcDev,
 | |
|   IN UINTN                   Timeout
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   wait for Ehc reset or timeout
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev   - USB2_HC_DEV 
 | |
|   Timeout - timeout threshold
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS    Success
 | |
|   EFI_TIMEOUT    Timeout
 | |
|   
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINTN       Delay;
 | |
| 
 | |
|   //
 | |
|   // Timeout is in US unit
 | |
|   //
 | |
|   Delay = (Timeout / 50) + 1;
 | |
|   do {
 | |
| 
 | |
|     if (IsEhcReseted (HcDev)) {
 | |
|       Status = EFI_SUCCESS;
 | |
|       goto exit;
 | |
|     }
 | |
|     gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);
 | |
| 
 | |
|   } while (Delay--);
 | |
| 
 | |
|   Status = EFI_TIMEOUT;
 | |
| 
 | |
| exit:
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| WaitForEhcHalt (
 | |
|   IN USB2_HC_DEV             *HcDev,
 | |
|   IN UINTN                   Timeout
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   wait for Ehc halt or timeout
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev   - USB2_HC_DEV 
 | |
|   Timeout - timeout threshold
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS    Success
 | |
|   EFI_TIMEOUT    Timeout
 | |
|   
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINTN       Delay;
 | |
| 
 | |
|   //
 | |
|   // Timeout is in US unit
 | |
|   //
 | |
|   Delay = (Timeout / 50) + 1;
 | |
|   do {
 | |
| 
 | |
|     if (IsEhcHalted (HcDev)) {
 | |
|       Status = EFI_SUCCESS;
 | |
|       goto exit;
 | |
|     }
 | |
|     gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);
 | |
| 
 | |
|   } while (Delay--);
 | |
| 
 | |
|   Status = EFI_TIMEOUT;
 | |
| 
 | |
| exit:
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| WaitForEhcNotHalt (
 | |
|   IN USB2_HC_DEV             *HcDev,
 | |
|   IN UINTN                   Timeout
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   wait for Ehc not halt or timeout
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev   - USB2_HC_DEV 
 | |
|   Timeout - timeout threshold
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS    Success
 | |
|   EFI_TIMEOUT    Timeout
 | |
|   
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINTN       Delay;
 | |
| 
 | |
|   //
 | |
|   // Timeout is in US unit
 | |
|   //
 | |
|   Delay = (Timeout / 50) + 1;
 | |
|   do {
 | |
| 
 | |
|     if (!IsEhcHalted (HcDev)) {
 | |
|       Status = EFI_SUCCESS;
 | |
|       goto exit;
 | |
|     }
 | |
|     gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);
 | |
| 
 | |
|   } while (Delay--);
 | |
| 
 | |
|   Status = EFI_TIMEOUT;
 | |
| 
 | |
| exit:
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| WaitForAsyncScheduleEnable (
 | |
|   IN  USB2_HC_DEV            *HcDev,
 | |
|   IN UINTN                   Timeout
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Wait for Ehc asynchronous schedule enable or timeout
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev   - USB2_HC_DEV 
 | |
|   Timeout - timeout threshold
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS    Success
 | |
|   EFI_TIMEOUT    Timeout
 | |
|   
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINTN       Delay;
 | |
| 
 | |
|   //
 | |
|   // Timeout is in US unit
 | |
|   //
 | |
|   Delay = (Timeout / 50) + 1;
 | |
|   do {
 | |
| 
 | |
|     if (IsAsyncScheduleEnabled (HcDev)) {
 | |
|       Status = EFI_SUCCESS;
 | |
|       goto exit;
 | |
|     }
 | |
|     gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);
 | |
| 
 | |
|   } while (Delay--);
 | |
| 
 | |
|   Status = EFI_TIMEOUT;
 | |
| 
 | |
| exit:
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| WaitForAsyncScheduleDisable (
 | |
|   IN USB2_HC_DEV             *HcDev,
 | |
|   IN UINTN                   Timeout
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Wait for Ehc asynchronous schedule disable or timeout
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev   - USB2_HC_DEV 
 | |
|   Timeout - timeout threshold
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS    Success
 | |
|   EFI_TIMEOUT    Timeout
 | |
|   
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINTN       Delay;
 | |
| 
 | |
|   //
 | |
|   // Timeout is in US unit
 | |
|   //
 | |
|   Delay = (Timeout / 50) + 1;
 | |
|   do {
 | |
| 
 | |
|     if (!IsAsyncScheduleEnabled (HcDev)) {
 | |
|       Status = EFI_SUCCESS;
 | |
|       goto exit;
 | |
|     }
 | |
|     gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);
 | |
| 
 | |
|   } while (Delay--);
 | |
| 
 | |
|   Status = EFI_TIMEOUT;
 | |
| 
 | |
| exit:
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| WaitForPeriodicScheduleEnable (
 | |
|   IN USB2_HC_DEV             *HcDev,
 | |
|   IN UINTN                   Timeout
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Wait for Ehc periodic schedule enable or timeout
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev   - USB2_HC_DEV 
 | |
|   Timeout - timeout threshold
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS    Success
 | |
|   EFI_TIMEOUT    Timeout
 | |
|   
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINTN       Delay;
 | |
| 
 | |
|   //
 | |
|   // Timeout is in US unit
 | |
|   //
 | |
|   Delay = (Timeout / 50) + 1;
 | |
|   do {
 | |
| 
 | |
|     if (IsPeriodicScheduleEnabled (HcDev)) {
 | |
|       Status = EFI_SUCCESS;
 | |
|       goto exit;
 | |
|     }
 | |
|     gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);
 | |
| 
 | |
|   } while (Delay--);
 | |
| 
 | |
|   Status = EFI_TIMEOUT;
 | |
| 
 | |
| exit:
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| WaitForPeriodicScheduleDisable (
 | |
|   IN USB2_HC_DEV             *HcDev,
 | |
|   IN UINTN                   Timeout
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Wait for periodic schedule disable or timeout
 | |
|   
 | |
| Arguments:
 | |
| 
 | |
|   HcDev   - USB2_HC_DEV 
 | |
|   Timeout - timeout threshold
 | |
|   
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS    Success
 | |
|   EFI_TIMEOUT    Timeout
 | |
|   
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINTN       Delay;
 | |
| 
 | |
|   //
 | |
|   // Timeout is in US unit
 | |
|   //
 | |
|   Delay = (Timeout / 50) + 1;
 | |
|   do {
 | |
| 
 | |
|     if (!IsPeriodicScheduleEnabled (HcDev)) {
 | |
|       Status = EFI_SUCCESS;
 | |
|       goto exit;
 | |
|     }
 | |
|     gBS->Stall (EHCI_GENERIC_RECOVERY_TIME);
 | |
| 
 | |
|   } while (Delay--);
 | |
| 
 | |
|   Status = EFI_TIMEOUT;
 | |
| 
 | |
| exit:
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| WaitForEhcDoorbell (
 | |
|   IN USB2_HC_DEV             *HcDev,
 | |
|   IN UINTN                   Timeout
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Wait for periodic schedule disable or timeout
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   HcDev   - USB2_HC_DEV 
 | |
|   Timeout - timeout threshold
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS    Success
 | |
|   EFI_TIMEOUT    Timeout
 | |
|   
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINT32      UsbCommandAddr;
 | |
|   UINT32      UsbCommandReg;
 | |
|   UINTN       Delay;
 | |
| 
 | |
|   UsbCommandAddr  = USBCMD;
 | |
|   Delay           = (Timeout / 50) + 1;
 | |
|   
 | |
|   do {
 | |
|     Status = ReadEhcOperationalReg (
 | |
|                HcDev,
 | |
|                UsbCommandAddr,
 | |
|                &UsbCommandReg
 | |
|                );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       Status = EFI_DEVICE_ERROR;
 | |
|       goto exit;
 | |
|     }
 | |
|     if (!(UsbCommandReg & USBCMD_IAAD)) {
 | |
|       break;
 | |
|     }
 | |
| 	
 | |
|   } while (--Delay);
 | |
| 
 | |
|   if (0 == Delay) {
 | |
|     Status = EFI_TIMEOUT;
 | |
|   }
 | |
| 
 | |
| exit:
 | |
|   return Status;
 | |
| }
 |