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;
 | |
| 
 | |
| }
 |