git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			508 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			508 lines
		
	
	
		
			12 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:
 | 
						|
 | 
						|
    Hub.c
 | 
						|
    
 | 
						|
  Abstract:
 | 
						|
 | 
						|
    Usb Hub Request
 | 
						|
 | 
						|
  Revision History
 | 
						|
 | 
						|
--*/
 | 
						|
 | 
						|
#include "usbbus.h"
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
HubGetPortStatus (
 | 
						|
  IN  EFI_USB_IO_PROTOCOL     *UsbIo,
 | 
						|
  IN  UINT8                   Port,
 | 
						|
  OUT UINT32                  *PortStatus
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  
 | 
						|
  Routine Description:
 | 
						|
    Get a given hub port status
 | 
						|
  
 | 
						|
  Arguments:
 | 
						|
    UsbIo           -   EFI_USB_IO_PROTOCOL instance
 | 
						|
    Port            -   Usb hub port number (starting from 1).
 | 
						|
    PortStatus      -   Current Hub port status and change status.
 | 
						|
    
 | 
						|
  Returns:
 | 
						|
    EFI_SUCCESS
 | 
						|
    EFI_DEVICE
 | 
						|
    EFI_TIME_OUT
 | 
						|
    EFI_INVALID_PARAMETER
 | 
						|
    
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_USB_DEVICE_REQUEST  DevReq;
 | 
						|
  EFI_STATUS              EfiStatus;
 | 
						|
  UINT32                  UsbStatus;
 | 
						|
  UINT32                  Timeout;
 | 
						|
 | 
						|
  ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
 | 
						|
 | 
						|
  //
 | 
						|
  // Fill Device request packet
 | 
						|
  //
 | 
						|
  DevReq.RequestType  = HUB_GET_PORT_STATUS_REQ_TYPE;
 | 
						|
  DevReq.Request      = HUB_GET_PORT_STATUS;
 | 
						|
  DevReq.Value        = 0;
 | 
						|
  DevReq.Index        = Port;
 | 
						|
  DevReq.Length       = sizeof (UINT32);
 | 
						|
 | 
						|
  Timeout             = 3000;
 | 
						|
 | 
						|
  EfiStatus = UsbIo->UsbControlTransfer (
 | 
						|
                      UsbIo,
 | 
						|
                      &DevReq,
 | 
						|
                      EfiUsbDataIn,
 | 
						|
                      Timeout,
 | 
						|
                      PortStatus,
 | 
						|
                      sizeof (UINT32),
 | 
						|
                      &UsbStatus
 | 
						|
                      );
 | 
						|
 | 
						|
  return EfiStatus;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
HubSetPortFeature (
 | 
						|
  IN EFI_USB_IO_PROTOCOL     *UsbIo,
 | 
						|
  IN UINT8                   Port,
 | 
						|
  IN UINT8                   Value
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  
 | 
						|
  Routine Description:
 | 
						|
    Set specified feature to a give hub port
 | 
						|
  
 | 
						|
  Arguments:
 | 
						|
    UsbIo           -   EFI_USB_IO_PROTOCOL instance
 | 
						|
    Port            -   Usb hub port number (starting from 1).
 | 
						|
    Value           -   New feature value.
 | 
						|
  
 | 
						|
  Returns:
 | 
						|
    EFI_SUCCESS
 | 
						|
    EFI_DEVICE
 | 
						|
    EFI_TIME_OUT
 | 
						|
    EFI_INVALID_PARAMETER
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_USB_DEVICE_REQUEST  DevReq;
 | 
						|
  EFI_STATUS              EfiStatus;
 | 
						|
  UINT32                  UsbStatus;
 | 
						|
  UINT32                  Timeout;
 | 
						|
 | 
						|
  ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
 | 
						|
 | 
						|
  //
 | 
						|
  // Fill Device request packet
 | 
						|
  //
 | 
						|
  DevReq.RequestType  = HUB_SET_PORT_FEATURE_REQ_TYPE;
 | 
						|
  DevReq.Request      = HUB_SET_PORT_FEATURE;
 | 
						|
  DevReq.Value        = Value;
 | 
						|
  DevReq.Index        = Port;
 | 
						|
  DevReq.Length       = 0;
 | 
						|
 | 
						|
  Timeout             = 3000;
 | 
						|
  EfiStatus = UsbIo->UsbControlTransfer (
 | 
						|
                      UsbIo,
 | 
						|
                      &DevReq,
 | 
						|
                      EfiUsbNoData,
 | 
						|
                      Timeout,
 | 
						|
                      NULL,
 | 
						|
                      0,
 | 
						|
                      &UsbStatus
 | 
						|
                      );
 | 
						|
 | 
						|
  return EfiStatus;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
HubClearPortFeature (
 | 
						|
  IN EFI_USB_IO_PROTOCOL     *UsbIo,
 | 
						|
  IN UINT8                   Port,
 | 
						|
  IN UINT8                   Value
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  
 | 
						|
  Routine Description:
 | 
						|
    Clear a specified feature of a given hub port
 | 
						|
  
 | 
						|
  Arguments:
 | 
						|
    UsbIo           -   EFI_USB_IO_PROTOCOL instance
 | 
						|
    Port            -   Usb hub port number (starting from 1).
 | 
						|
    Value           -   Feature value that will be cleared from
 | 
						|
                        that hub port.
 | 
						|
  
 | 
						|
  Returns:
 | 
						|
    EFI_SUCCESS
 | 
						|
    EFI_DEVICE
 | 
						|
    EFI_TIME_OUT
 | 
						|
    EFI_INVALID_PARAMETER
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_USB_DEVICE_REQUEST  DevReq;
 | 
						|
  EFI_STATUS              EfiStatus;
 | 
						|
  UINT32                  UsbStatus;
 | 
						|
  UINT32                  Timeout;
 | 
						|
 | 
						|
  ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
 | 
						|
 | 
						|
  //
 | 
						|
  // Fill Device request packet
 | 
						|
  //
 | 
						|
  DevReq.RequestType  = HUB_CLEAR_FEATURE_PORT_REQ_TYPE;
 | 
						|
  DevReq.Request      = HUB_CLEAR_FEATURE_PORT;
 | 
						|
  DevReq.Value        = Value;
 | 
						|
  DevReq.Index        = Port;
 | 
						|
  DevReq.Length       = 0;
 | 
						|
 | 
						|
  Timeout             = 3000;
 | 
						|
  EfiStatus = UsbIo->UsbControlTransfer (
 | 
						|
                      UsbIo,
 | 
						|
                      &DevReq,
 | 
						|
                      EfiUsbNoData,
 | 
						|
                      Timeout,
 | 
						|
                      NULL,
 | 
						|
                      0,
 | 
						|
                      &UsbStatus
 | 
						|
                      );
 | 
						|
 | 
						|
  return EfiStatus;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
HubGetHubStatus (
 | 
						|
  IN  EFI_USB_IO_PROTOCOL     *UsbIo,
 | 
						|
  OUT UINT32                  *HubStatus
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  
 | 
						|
  Routine Description:
 | 
						|
    Get Hub Status
 | 
						|
  
 | 
						|
  Arguments:
 | 
						|
    UsbIo           -   EFI_USB_IO_PROTOCOL instance
 | 
						|
    HubStatus       -   Current Hub status and change status.
 | 
						|
  
 | 
						|
  Returns:
 | 
						|
    EFI_SUCCESS
 | 
						|
    EFI_DEVICE
 | 
						|
    EFI_TIME_OUT
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_USB_DEVICE_REQUEST  DevReq;
 | 
						|
  EFI_STATUS              EfiStatus;
 | 
						|
  UINT32                  UsbStatus;
 | 
						|
  UINT32                  Timeout;
 | 
						|
 | 
						|
  ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
 | 
						|
 | 
						|
  //
 | 
						|
  // Fill Device request packet
 | 
						|
  //
 | 
						|
  DevReq.RequestType  = HUB_GET_HUB_STATUS_REQ_TYPE;
 | 
						|
  DevReq.Request      = HUB_GET_HUB_STATUS;
 | 
						|
  DevReq.Value        = 0;
 | 
						|
  DevReq.Index        = 0;
 | 
						|
  DevReq.Length       = sizeof (UINT32);
 | 
						|
 | 
						|
  Timeout             = 3000;
 | 
						|
  EfiStatus = UsbIo->UsbControlTransfer (
 | 
						|
                      UsbIo,
 | 
						|
                      &DevReq,
 | 
						|
                      EfiUsbDataIn,
 | 
						|
                      Timeout,
 | 
						|
                      HubStatus,
 | 
						|
                      sizeof (UINT32),
 | 
						|
                      &UsbStatus
 | 
						|
                      );
 | 
						|
 | 
						|
  return EfiStatus;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
HubSetHubFeature (
 | 
						|
  IN EFI_USB_IO_PROTOCOL     *UsbIo,
 | 
						|
  IN UINT8                   Value
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  
 | 
						|
  Routine Description:
 | 
						|
    Set a specified feature to the hub
 | 
						|
  
 | 
						|
  Arguments:
 | 
						|
    UsbIo           -   EFI_USB_IO_PROTOCOL instance
 | 
						|
    Value           -   Feature value that will be set to the hub.
 | 
						|
  
 | 
						|
  Returns:
 | 
						|
    EFI_SUCCESS
 | 
						|
    EFI_DEVICE
 | 
						|
    EFI_TIME_OUT
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_USB_DEVICE_REQUEST  DevReq;
 | 
						|
  EFI_STATUS              EfiStatus;
 | 
						|
  UINT32                  UsbStatus;
 | 
						|
  UINT32                  Timeout;
 | 
						|
 | 
						|
  ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
 | 
						|
 | 
						|
  //
 | 
						|
  // Fill Device request packet
 | 
						|
  //
 | 
						|
  DevReq.RequestType  = HUB_SET_HUB_FEATURE_REQ_TYPE;
 | 
						|
  DevReq.Request      = HUB_SET_HUB_FEATURE;
 | 
						|
  DevReq.Value        = Value;
 | 
						|
  DevReq.Index        = 0;
 | 
						|
  DevReq.Length       = 0;
 | 
						|
 | 
						|
  Timeout             = 3000;
 | 
						|
  EfiStatus = UsbIo->UsbControlTransfer (
 | 
						|
                      UsbIo,
 | 
						|
                      &DevReq,
 | 
						|
                      EfiUsbNoData,
 | 
						|
                      Timeout,
 | 
						|
                      NULL,
 | 
						|
                      0,
 | 
						|
                      &UsbStatus
 | 
						|
                      );
 | 
						|
 | 
						|
  return EfiStatus;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
HubClearHubFeature (
 | 
						|
  IN EFI_USB_IO_PROTOCOL     *UsbIo,
 | 
						|
  IN UINT8                   Value
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  
 | 
						|
  Routine Description:
 | 
						|
    Set a specified feature to the hub
 | 
						|
  
 | 
						|
  Arguments:
 | 
						|
    UsbIo           -   EFI_USB_IO_PROTOCOL instance
 | 
						|
    Value           -   Feature value that will be cleared from the hub.
 | 
						|
  
 | 
						|
  Returns:
 | 
						|
    EFI_SUCCESS
 | 
						|
    EFI_DEVICE
 | 
						|
    EFI_TIME_OUT
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_USB_DEVICE_REQUEST  DevReq;
 | 
						|
  EFI_STATUS              EfiStatus;
 | 
						|
  UINT32                  UsbStatus;
 | 
						|
  UINT32                  Timeout;
 | 
						|
 | 
						|
  ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
 | 
						|
 | 
						|
  //
 | 
						|
  // Fill Device request packet
 | 
						|
  //
 | 
						|
  DevReq.RequestType  = HUB_CLEAR_FEATURE_REQ_TYPE;
 | 
						|
  DevReq.Request      = HUB_CLEAR_FEATURE;
 | 
						|
  DevReq.Value        = Value;
 | 
						|
  DevReq.Index        = 0;
 | 
						|
  DevReq.Length       = 0;
 | 
						|
 | 
						|
  Timeout             = 3000;
 | 
						|
  EfiStatus = UsbIo->UsbControlTransfer (
 | 
						|
                      UsbIo,
 | 
						|
                      &DevReq,
 | 
						|
                      EfiUsbNoData,
 | 
						|
                      Timeout,
 | 
						|
                      NULL,
 | 
						|
                      0,
 | 
						|
                      &UsbStatus
 | 
						|
                      );
 | 
						|
 | 
						|
  return EfiStatus;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
GetHubDescriptor (
 | 
						|
  IN  EFI_USB_IO_PROTOCOL        *UsbIo,
 | 
						|
  IN  UINTN                      DescriptorSize,
 | 
						|
  OUT EFI_USB_HUB_DESCRIPTOR     *HubDescriptor
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  
 | 
						|
  Routine Description:
 | 
						|
    Get the hub descriptor
 | 
						|
  
 | 
						|
  Arguments:
 | 
						|
    UsbIo           -   EFI_USB_IO_PROTOCOL instance
 | 
						|
    DescriptorSize  -   The length of Hub Descriptor buffer.
 | 
						|
    HubDescriptor   -   Caller allocated buffer to store the hub descriptor
 | 
						|
                        if successfully returned.
 | 
						|
                              
 | 
						|
  Returns:
 | 
						|
    EFI_SUCCESS
 | 
						|
    EFI_DEVICE
 | 
						|
    EFI_TIME_OUT
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_USB_DEVICE_REQUEST  DevReq;
 | 
						|
  EFI_STATUS              EfiStatus;
 | 
						|
  UINT32                  UsbStatus;
 | 
						|
  UINT32                  Timeout;
 | 
						|
 | 
						|
  ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
 | 
						|
 | 
						|
  //
 | 
						|
  // Fill Device request packet
 | 
						|
  //
 | 
						|
  DevReq.RequestType  = USB_RT_HUB | 0x80;
 | 
						|
  DevReq.Request      = HUB_GET_DESCRIPTOR;
 | 
						|
  DevReq.Value        = USB_DT_HUB << 8;
 | 
						|
  DevReq.Index        = 0;
 | 
						|
  DevReq.Length       = (UINT16) DescriptorSize;
 | 
						|
 | 
						|
  Timeout             = 3000;
 | 
						|
  EfiStatus = UsbIo->UsbControlTransfer (
 | 
						|
                      UsbIo,
 | 
						|
                      &DevReq,
 | 
						|
                      EfiUsbDataIn,
 | 
						|
                      Timeout,
 | 
						|
                      HubDescriptor,
 | 
						|
                      (UINT16) DescriptorSize,
 | 
						|
                      &UsbStatus
 | 
						|
                      );
 | 
						|
 | 
						|
  return EfiStatus;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
DoHubConfig (
 | 
						|
  IN USB_IO_CONTROLLER_DEVICE     *HubController
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  
 | 
						|
  Routine Description:
 | 
						|
    Configure the hub
 | 
						|
  
 | 
						|
  Arguments:
 | 
						|
    HubController         -   Indicating the hub controller device that
 | 
						|
                              will be configured
 | 
						|
                                
 | 
						|
  Returns:
 | 
						|
    EFI_SUCCESS
 | 
						|
    EFI_DEVICE_ERROR
 | 
						|
    
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_USB_IO_PROTOCOL     *UsbIo;
 | 
						|
  EFI_USB_HUB_DESCRIPTOR  HubDescriptor;
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  EFI_USB_HUB_STATUS      HubStatus;
 | 
						|
  UINTN                   Index;
 | 
						|
  UINT32                  PortStatus;
 | 
						|
 | 
						|
  UsbIo = &HubController->UsbIo;
 | 
						|
 | 
						|
  ZeroMem (&HubDescriptor, sizeof (HubDescriptor));
 | 
						|
 | 
						|
  //
 | 
						|
  // First get the hub descriptor length
 | 
						|
  //
 | 
						|
  Status = GetHubDescriptor (UsbIo, 2, &HubDescriptor);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
    
 | 
						|
  //
 | 
						|
  // First get the whole descriptor, then
 | 
						|
  // get the number of hub ports
 | 
						|
  //
 | 
						|
  Status = GetHubDescriptor (
 | 
						|
            UsbIo,
 | 
						|
            HubDescriptor.Length,
 | 
						|
            &HubDescriptor
 | 
						|
            );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((gUSBErrorLevel, "Get hub descriptor fail\n"));
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  HubController->DownstreamPorts  = HubDescriptor.NbrPorts;
 | 
						|
 | 
						|
  Status                          = HubGetHubStatus (UsbIo, (UINT32 *) &HubStatus);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((gUSBErrorLevel, "Get hub status fail when configure\n"));
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  //  Get all hub ports status
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < HubController->DownstreamPorts; Index++) {
 | 
						|
 | 
						|
    Status = HubGetPortStatus (UsbIo, (UINT8) (Index + 1), &PortStatus);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  //  Power all the hub ports
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < HubController->DownstreamPorts; Index++) {
 | 
						|
    Status = HubSetPortFeature (
 | 
						|
              UsbIo,
 | 
						|
              (UINT8) (Index + 1),
 | 
						|
              EfiUsbPortPower
 | 
						|
              );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Clear Hub Status Change
 | 
						|
  //
 | 
						|
  Status = HubGetHubStatus (UsbIo, (UINT32 *) &HubStatus);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((gUSBErrorLevel, "Get hub status fail\n"));
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Hub power supply change happens
 | 
						|
    //
 | 
						|
    if (HubStatus.HubChange & HUB_CHANGE_LOCAL_POWER) {
 | 
						|
      HubClearHubFeature (UsbIo, C_HUB_LOCAL_POWER);
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Hub change overcurrent happens
 | 
						|
    //
 | 
						|
    if (HubStatus.HubChange & HUB_CHANGE_OVERCURRENT) {
 | 
						|
      HubClearHubFeature (UsbIo, C_HUB_OVER_CURRENT);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
 | 
						|
}
 |