Enabling usb3.0 XHCI support.

Signed-off-by: erictian
Reviewed-by: jshi19

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12185 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
erictian 2011-08-23 14:36:33 +00:00
parent da910a42c0
commit 92870c983c
16 changed files with 8055 additions and 97 deletions

View File

@ -0,0 +1,224 @@
/** @file
UEFI Component Name(2) protocol implementation for XHCI driver.
Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
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.
**/
#include "Xhci.h"
//
// EFI Component Name Protocol
//
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gXhciComponentName = {
XhciComponentNameGetDriverName,
XhciComponentNameGetControllerName,
"eng"
};
//
// EFI Component Name 2 Protocol
//
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gXhciComponentName2 = {
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME) XhciComponentNameGetDriverName,
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) XhciComponentNameGetControllerName,
"en"
};
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mXhciDriverNameTable[] = {
{ "eng;en", L"Usb Xhci Driver" },
{ NULL , NULL }
};
/**
Retrieves a Unicode string that is the user readable name of the driver.
This function retrieves the user readable name of a driver in the form of a
Unicode string. If the driver specified by This has a user readable name in
the language specified by Language, then a pointer to the driver name is
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
by This does not support the language specified by Language,
then EFI_UNSUPPORTED is returned.
@param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param Language[in] A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified
in RFC 4646 or ISO 639-2 language code format.
@param DriverName[out] A pointer to the Unicode string to return.
This Unicode string is the name of the
driver specified by This in the language
specified by Language.
@retval EFI_SUCCESS The Unicode string for the Driver specified by
This and the language specified by Language was
returned in DriverName.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER DriverName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
XhciComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
)
{
return LookupUnicodeString2 (
Language,
This->SupportedLanguages,
mXhciDriverNameTable,
DriverName,
(BOOLEAN)(This == &gXhciComponentName)
);
}
/**
Retrieves a Unicode string that is the user readable name of the controller
that is being managed by a driver.
This function retrieves the user readable name of the controller specified by
ControllerHandle and ChildHandle in the form of a Unicode string. If the
driver specified by This has a user readable name in the language specified by
Language, then a pointer to the controller name is returned in ControllerName,
and EFI_SUCCESS is returned. If the driver specified by This is not currently
managing the controller specified by ControllerHandle and ChildHandle,
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
support the language specified by Language, then EFI_UNSUPPORTED is returned.
@param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param ControllerHandle[in] The handle of a controller that the driver
specified by This is managing. This handle
specifies the controller whose name is to be
returned.
@param ChildHandle[in] The handle of the child controller to retrieve
the name of. This is an optional parameter that
may be NULL. It will be NULL for device
drivers. It will also be NULL for a bus drivers
that wish to retrieve the name of the bus
controller. It will not be NULL for a bus
driver that wishes to retrieve the name of a
child controller.
@param Language[in] A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified in
RFC 4646 or ISO 639-2 language code format.
@param ControllerName[out] A pointer to the Unicode string to return.
This Unicode string is the name of the
controller specified by ControllerHandle and
ChildHandle in the language specified by
Language from the point of view of the driver
specified by This.
@retval EFI_SUCCESS The Unicode string for the user readable name in
the language specified by Language for the
driver specified by This was returned in
DriverName.
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
EFI_HANDLE.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This is not currently
managing the controller specified by
ControllerHandle and ChildHandle.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
XhciComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
)
{
EFI_STATUS Status;
EFI_USB2_HC_PROTOCOL *Usb2Hc;
USB_XHCI_DEV *XhciDev;
//
// This is a device driver, so ChildHandle must be NULL.
//
if (ChildHandle != NULL) {
return EFI_UNSUPPORTED;
}
//
// Make sure this driver is currently managing ControllerHandle
//
Status = EfiTestManagedDevice (
ControllerHandle,
gXhciDriverBinding.DriverBindingHandle,
&gEfiPciIoProtocolGuid
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Get the device context
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiUsb2HcProtocolGuid,
(VOID **) &Usb2Hc,
gXhciDriverBinding.DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return Status;
}
XhciDev = XHC_FROM_THIS (Usb2Hc);
return LookupUnicodeString2 (
Language,
This->SupportedLanguages,
XhciDev->ControllerNameTable,
ControllerName,
(BOOLEAN)(This == &gXhciComponentName)
);
}

View File

@ -0,0 +1,146 @@
/** @file
This file contains the delarations for componet name routines.
Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
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.
**/
#ifndef _EFI_COMPONENT_NAME_H_
#define _EFI_COMPONENT_NAME_H_
/**
Retrieves a Unicode string that is the user readable name of the driver.
This function retrieves the user readable name of a driver in the form of a
Unicode string. If the driver specified by This has a user readable name in
the language specified by Language, then a pointer to the driver name is
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
by This does not support the language specified by Language,
then EFI_UNSUPPORTED is returned.
@param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param Language[in] A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified
in RFC 4646 or ISO 639-2 language code format.
@param DriverName[out] A pointer to the Unicode string to return.
This Unicode string is the name of the
driver specified by This in the language
specified by Language.
@retval EFI_SUCCESS The Unicode string for the Driver specified by
This and the language specified by Language was
returned in DriverName.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER DriverName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
XhciComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
);
/**
Retrieves a Unicode string that is the user readable name of the controller
that is being managed by a driver.
This function retrieves the user readable name of the controller specified by
ControllerHandle and ChildHandle in the form of a Unicode string. If the
driver specified by This has a user readable name in the language specified by
Language, then a pointer to the controller name is returned in ControllerName,
and EFI_SUCCESS is returned. If the driver specified by This is not currently
managing the controller specified by ControllerHandle and ChildHandle,
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
support the language specified by Language, then EFI_UNSUPPORTED is returned.
@param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param ControllerHandle[in] The handle of a controller that the driver
specified by This is managing. This handle
specifies the controller whose name is to be
returned.
@param ChildHandle[in] The handle of the child controller to retrieve
the name of. This is an optional parameter that
may be NULL. It will be NULL for device
drivers. It will also be NULL for a bus drivers
that wish to retrieve the name of the bus
controller. It will not be NULL for a bus
driver that wishes to retrieve the name of a
child controller.
@param Language[in] A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified in
RFC 4646 or ISO 639-2 language code format.
@param ControllerName[out] A pointer to the Unicode string to return.
This Unicode string is the name of the
controller specified by ControllerHandle and
ChildHandle in the language specified by
Language from the point of view of the driver
specified by This.
@retval EFI_SUCCESS The Unicode string for the user readable name in
the language specified by Language for the
driver specified by This was returned in
DriverName.
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
EFI_HANDLE.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This is not currently
managing the controller specified by
ControllerHandle and ChildHandle.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
XhciComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,362 @@
/** @file
Provides some data structure definitions used by the XHCI host controller driver.
Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
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.
**/
#ifndef _EFI_XHCI_H_
#define _EFI_XHCI_H_
#include <Uefi.h>
#include <Protocol/Usb2HostController.h>
#include <Protocol/PciIo.h>
#include <Guid/EventGroup.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiLib.h>
#include <Library/PcdLib.h>
#include <Library/DebugLib.h>
#include <IndustryStandard/Pci.h>
typedef struct _USB_XHCI_DEV USB_XHCI_DEV;
typedef struct _USB_DEV_CONTEXT USB_DEV_CONTEXT;
#include "XhciReg.h"
#include "XhciSched.h"
#include "ComponentName.h"
//
// XHC timeout experience values
//
#define XHC_1_MICROSECOND 1
#define XHC_1_MILLISECOND (1000 * XHC_1_MICROSECOND)
#define XHC_1_SECOND (1000 * XHC_1_MILLISECOND)
//
// XHCI register operation timeout, set by experience
//
#define XHC_RESET_TIMEOUT (1 * XHC_1_SECOND)
#define XHC_GENERIC_TIMEOUT (10 * XHC_1_MILLISECOND)
//
// Wait for roothub port power stable, refers to Spec[XHCI1.0-2.3.9]
//
#define XHC_ROOT_PORT_RECOVERY_STALL (20 * XHC_1_MILLISECOND)
//
// Sync and Async transfer polling interval, set by experience,
// and the unit of Async is 100us, means 50ms as interval.
//
#define XHC_SYNC_POLL_INTERVAL (20 * XHC_1_MILLISECOND)
#define XHC_ASYNC_POLL_INTERVAL (50 * 10000U)
//
// XHC raises TPL to TPL_NOTIFY to serialize all its operations
// to protect shared data structures.
//
#define XHC_TPL TPL_NOTIFY
#define CMD_RING_TRB_NUMBER 0x40
#define TR_RING_TRB_NUMBER 0x40
#define ERST_NUMBER 0x01
#define EVENT_RING_TRB_NUMBER 0x80
#define CMD_INTER 0
#define CTRL_INTER 1
#define BULK_INTER 2
#define INT_INTER 3
#define INT_INTER_ASYNC 4
//
// Iterate through the doule linked list. This is delete-safe.
// Don't touch NextEntry
//
#define EFI_LIST_FOR_EACH_SAFE(Entry, NextEntry, ListHead) \
for (Entry = (ListHead)->ForwardLink, NextEntry = Entry->ForwardLink;\
Entry != (ListHead); Entry = NextEntry, NextEntry = Entry->ForwardLink)
#define EFI_LIST_CONTAINER(Entry, Type, Field) BASE_CR(Entry, Type, Field)
#define XHC_LOW_32BIT(Addr64) ((UINT32)(((UINTN)(Addr64)) & 0xFFFFFFFF))
#define XHC_HIGH_32BIT(Addr64) ((UINT32)(RShiftU64((UINTN)(Addr64), 32) & 0xFFFFFFFF))
#define XHC_BIT_IS_SET(Data, Bit) ((BOOLEAN)(((Data) & (Bit)) == (Bit)))
#define XHC_REG_BIT_IS_SET(Xhc, Offset, Bit) \
(XHC_BIT_IS_SET(XhcReadOpReg ((Xhc), (Offset)), (Bit)))
#define XHCI_IS_DATAIN(EndpointAddr) XHC_BIT_IS_SET((EndpointAddr), 0x80)
#define USB_XHCI_DEV_SIGNATURE SIGNATURE_32 ('x', 'h', 'c', 'i')
#define XHC_FROM_THIS(a) CR(a, USB_XHCI_DEV, Usb2Hc, USB_XHCI_DEV_SIGNATURE)
#define USB_DESC_TYPE_HUB 0x29
#define USB_DESC_TYPE_HUB_SUPER_SPEED 0x2a
//
// Xhci Data and Ctrl Structures
//
#pragma pack(1)
typedef struct {
UINT8 ProgInterface;
UINT8 SubClassCode;
UINT8 BaseCode;
} USB_CLASSC;
typedef struct {
UINT8 Length;
UINT8 DescType;
UINT8 NumPorts;
UINT16 HubCharacter;
UINT8 PwrOn2PwrGood;
UINT8 HubContrCurrent;
UINT8 Filler[16];
} EFI_USB_HUB_DESCRIPTOR;
#pragma pack()
struct _USB_XHCI_DEV {
UINT32 Signature;
EFI_PCI_IO_PROTOCOL *PciIo;
UINT64 OriginalPciAttributes;
EFI_USB2_HC_PROTOCOL Usb2Hc;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
//
// ExitBootServicesEvent is used to set OS semaphore and
// stop the XHC DMA operation after exit boot service.
//
EFI_EVENT ExitBootServiceEvent;
EFI_EVENT PollTimer;
LIST_ENTRY AsyncIntTransfers;
UINT8 CapLength; ///< Capability Register Length
XHC_HCSPARAMS1 HcSParams1; ///< Structural Parameters 1
XHC_HCSPARAMS2 HcSParams2; ///< Structural Parameters 2
XHC_HCCPARAMS HcCParams; ///< Capability Parameters
UINT32 DBOff; ///< Doorbell Offset
UINT32 RTSOff; ///< Runtime Register Space Offset
UINT16 MaxInterrupt;
UINT32 PageSize;
UINT64 *ScratchBuf;
UINT32 MaxScratchpadBufs;
UINT32 ExtCapRegBase;
UINT32 UsbLegSupOffset;
UINT64 *DCBAA;
UINT32 MaxSlotsEn;
//
// Cmd Transfer Ring
//
TRANSFER_RING CmdRing;
//
// CmdEventRing
//
EVENT_RING CmdEventRing;
//
// ControlTREventRing
//
EVENT_RING CtrlTrEventRing;
//
// BulkTREventRing
//
EVENT_RING BulkTrEventRing;
//
// IntTREventRing
//
EVENT_RING IntTrEventRing;
//
// AsyncIntTREventRing
//
EVENT_RING AsynIntTrEventRing;
//
// Misc
//
EFI_UNICODE_STRING_TABLE *ControllerNameTable;
};
struct _USB_DEV_CONTEXT {
//
// Whether this entry in UsbDevContext array is used or not.
//
BOOLEAN Enabled;
//
// The slot id assigned to the new device through XHCI's Enable_Slot cmd.
//
UINT8 SlotId;
//
// The route string presented an attached usb device.
//
USB_DEV_ROUTE RouteString;
//
// The route string of parent device if it exists. Otherwise it's zero.
//
USB_DEV_ROUTE ParentRouteString;
//
// The actual device address assigned by XHCI through Address_Device command.
//
UINT8 XhciDevAddr;
//
// The requested device address from UsbBus driver through Set_Address standard usb request.
// As XHCI spec replaces this request with Address_Device command, we have to record the
// requested device address and establish a mapping relationship with the actual device address.
// Then UsbBus driver just need to be aware of the requested device address to access usb device
// through EFI_USB2_HC_PROTOCOL. Xhci driver would be responsible for translating it to actual
// device address and access the actual device.
//
UINT8 BusDevAddr;
//
// The pointer to the input device context.
//
VOID *InputContext;
//
// The pointer to the output device context.
//
VOID *OutputDevContxt;
//
// The transfer queue for every endpoint.
//
VOID *EndpointTransferRing[31];
//
// The device descriptor which is stored to support XHCI's Evaluate_Context cmd.
//
EFI_USB_DEVICE_DESCRIPTOR DevDesc;
//
// As a usb device may include multiple configuration descriptors, we dynamically allocate an array
// to store them.
// Note that every configuration descriptor stored here includes those lower level descriptors,
// such as Interface descriptor, Endpoint descriptor, and so on.
// These information is used to support XHCI's Config_Endpoint cmd.
//
EFI_USB_CONFIG_DESCRIPTOR **ConfDesc;
};
extern EFI_DRIVER_BINDING_PROTOCOL gXhciDriverBinding;
extern EFI_COMPONENT_NAME_PROTOCOL gXhciComponentName;
extern EFI_COMPONENT_NAME2_PROTOCOL gXhciComponentName2;
extern USB_DEV_CONTEXT UsbDevContext[];
/**
Test to see if this driver supports ControllerHandle. Any
ControllerHandle that has Usb2HcProtocol installed will
be supported.
@param This Protocol instance pointer.
@param Controller Handle of device to test.
@param RemainingDevicePath Not used.
@return EFI_SUCCESS This driver supports this device.
@return EFI_UNSUPPORTED This driver does not support this device.
**/
EFI_STATUS
EFIAPI
XhcDriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
);
/**
Starting the Usb XHCI Driver.
@param This Protocol instance pointer.
@param Controller Handle of device to test.
@param RemainingDevicePath Not used.
@return EFI_SUCCESS supports this device.
@return EFI_UNSUPPORTED do not support this device.
@return EFI_DEVICE_ERROR cannot be started due to device Error.
@return EFI_OUT_OF_RESOURCES cannot allocate resources.
**/
EFI_STATUS
EFIAPI
XhcDriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
);
/**
Stop this driver on ControllerHandle. Support stoping any child handles
created by this driver.
@param This Protocol instance pointer.
@param Controller Handle of device to stop driver on.
@param NumberOfChildren Number of Children in the ChildHandleBuffer.
@param ChildHandleBuffer List of handles for the children we need to stop.
@return EFI_SUCCESS Success.
@return EFI_DEVICE_ERROR Fail.
**/
EFI_STATUS
EFIAPI
XhcDriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
);
/**
Sets a feature for the specified root hub port.
@param This This EFI_USB2_HC_PROTOCOL instance.
@param PortNumber Root hub port to set.
@param PortFeature Feature to set.
@retval EFI_SUCCESS The feature specified by PortFeature was set.
@retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
@retval EFI_DEVICE_ERROR Can't read register.
**/
EFI_STATUS
EFIAPI
XhcSetRootHubPortFeature (
IN EFI_USB2_HC_PROTOCOL *This,
IN UINT8 PortNumber,
IN EFI_USB_PORT_FEATURE PortFeature
);
/**
Clears a feature for the specified root hub port.
@param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
@param PortNumber Specifies the root hub port whose feature is
requested to be cleared.
@param PortFeature Indicates the feature selector associated with the
feature clear request.
@retval EFI_SUCCESS The feature specified by PortFeature was cleared
for the USB root hub port specified by PortNumber.
@retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
@retval EFI_DEVICE_ERROR Can't read register.
**/
EFI_STATUS
EFIAPI
XhcClearRootHubPortFeature (
IN EFI_USB2_HC_PROTOCOL *This,
IN UINT8 PortNumber,
IN EFI_USB_PORT_FEATURE PortFeature
);
#endif

View File

@ -0,0 +1,77 @@
## @file
#
# Component Description File For XhciDxe Module.
#
# XhciDxe driver is responsible for managing the behavior of XHCI controller.
# It implements the interfaces of monitoring the status of all ports and transferring
# Control, Bulk, Interrupt and Isochronous requests to those attached usb LS/FS/HS/SS devices.
#
# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
#
# 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.
#
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = XhciDxe
FILE_GUID = B7F50E91-A759-412c-ADE4-DCD03E7F7C28
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = XhcDriverEntryPoint
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
# DRIVER_BINDING = gXhciDriverBinding
# COMPONENT_NAME = gXhciComponentName
# COMPONENT_NAME2 = gXhciComponentName2
#
[Sources]
Xhci.c
XhciReg.c
XhciSched.c
ComponentName.c
ComponentName.h
Xhci.h
XhciReg.h
XhciSched.h
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
MemoryAllocationLib
BaseLib
UefiLib
UefiBootServicesTableLib
UefiDriverEntryPoint
BaseMemoryLib
DebugLib
PcdLib
[Guids]
gEfiEventExitBootServicesGuid ## PRODUCES ## Event
[Protocols]
gEfiPciIoProtocolGuid ## TO_START
gEfiUsb2HcProtocolGuid ## BY_START
# [Event]
# ##
# # Periodic timer event for checking the result of interrupt transfer execution.
# #
# EVENT_TYPE_PERIODIC_TIMER ## PRODUCES
#

View File

@ -0,0 +1,827 @@
/** @file
The XHCI register operation routines.
Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
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.
**/
#include "Xhci.h"
/**
Read 1-byte width XHCI capability register.
@param Xhc The XHCI device.
@param Offset The offset of the 1-byte width capability register.
@return The register content read.
@retval If err, return 0xFF.
**/
UINT8
XhcReadCapReg8 (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset
)
{
UINT8 Data;
EFI_STATUS Status;
Status = Xhc->PciIo->Mem.Read (
Xhc->PciIo,
EfiPciIoWidthUint8,
XHC_BAR_INDEX,
(UINT64) Offset,
1,
&Data
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "XhcReadCapReg: Pci Io read error - %r at %d\n", Status, Offset));
Data = 0xFF;
}
return Data;
}
/**
Read 4-bytes width XHCI capability register.
@param Xhc The XHCI device.
@param Offset The offset of the 4-bytes width capability register.
@return The register content read.
@retval If err, return 0xFFFFFFFF.
**/
UINT32
XhcReadCapReg (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset
)
{
UINT32 Data;
EFI_STATUS Status;
Status = Xhc->PciIo->Mem.Read (
Xhc->PciIo,
EfiPciIoWidthUint32,
XHC_BAR_INDEX,
(UINT64) Offset,
1,
&Data
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "XhcReadCapReg: Pci Io read error - %r at %d\n", Status, Offset));
Data = 0xFFFFFFFF;
}
return Data;
}
/**
Read 4-bytes width XHCI Operational register.
@param Xhc The XHCI device.
@param Offset The offset of the 4-bytes width operational register.
@return The register content read.
@retval If err, return 0xFFFFFFFF.
**/
UINT32
XhcReadOpReg (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset
)
{
UINT32 Data;
EFI_STATUS Status;
ASSERT (Xhc->CapLength != 0);
Status = Xhc->PciIo->Mem.Read (
Xhc->PciIo,
EfiPciIoWidthUint32,
XHC_BAR_INDEX,
(UINT64) (Xhc->CapLength + Offset),
1,
&Data
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "XhcReadOpReg: Pci Io Read error - %r at %d\n", Status, Offset));
Data = 0xFFFFFFFF;
}
return Data;
}
/**
Write the data to the 4-bytes width XHCI operational register.
@param Xhc The XHCI device.
@param Offset The offset of the 4-bytes width operational register.
@param Data The data to write.
**/
VOID
XhcWriteOpReg (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset,
IN UINT32 Data
)
{
EFI_STATUS Status;
ASSERT (Xhc->CapLength != 0);
Status = Xhc->PciIo->Mem.Write (
Xhc->PciIo,
EfiPciIoWidthUint32,
XHC_BAR_INDEX,
(UINT64) (Xhc->CapLength + Offset),
1,
&Data
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "XhcWriteOpReg: Pci Io Write error: %r at %d\n", Status, Offset));
}
}
/**
Write the data to the 2-bytes width XHCI operational register.
@param Xhc The XHCI device.
@param Offset The offset of the 2-bytes width operational register.
@param Data The data to write.
**/
VOID
XhcWriteOpReg16 (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset,
IN UINT16 Data
)
{
EFI_STATUS Status;
ASSERT (Xhc->CapLength != 0);
Status = Xhc->PciIo->Mem.Write (
Xhc->PciIo,
EfiPciIoWidthUint16,
XHC_BAR_INDEX,
(UINT64) (Xhc->CapLength + Offset),
1,
&Data
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "XhcWriteOpReg16: Pci Io Write error: %r at %d\n", Status, Offset));
}
}
/**
Write the data to the 8-bytes width XHCI operational register.
@param Xhc The XHCI device.
@param Offset The offset of the 8-bytes width operational register.
@param Data The data to write.
**/
VOID
XhcWriteOpReg64 (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset,
IN UINT64 Data
)
{
EFI_STATUS Status;
ASSERT (Xhc->CapLength != 0);
Status = Xhc->PciIo->Mem.Write (
Xhc->PciIo,
EfiPciIoWidthUint64,
XHC_BAR_INDEX,
(UINT64) (Xhc->CapLength + Offset),
1,
&Data
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "XhcWriteOpReg64: Pci Io Write error: %r at %d\n", Status, Offset));
}
}
/**
Read XHCI door bell register.
@param Xhc The XHCI device.
@param Offset The offset of the door bell register.
@return The register content read
**/
UINT32
XhcReadDoorBellReg (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset
)
{
UINT32 Data;
EFI_STATUS Status;
ASSERT (Xhc->DBOff != 0);
Status = Xhc->PciIo->Mem.Read (
Xhc->PciIo,
EfiPciIoWidthUint32,
XHC_BAR_INDEX,
(UINT64) (Xhc->DBOff + Offset),
1,
&Data
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "XhcReadDoorBellReg: Pci Io Read error - %r at %d\n", Status, Offset));
Data = 0xFFFFFFFF;
}
return Data;
}
/**
Write the data to the XHCI door bell register.
@param Xhc The XHCI device.
@param Offset The offset of the door bell register.
@param Data The data to write.
**/
VOID
XhcWriteDoorBellReg (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset,
IN UINT32 Data
)
{
EFI_STATUS Status;
ASSERT (Xhc->DBOff != 0);
Status = Xhc->PciIo->Mem.Write (
Xhc->PciIo,
EfiPciIoWidthUint32,
XHC_BAR_INDEX,
(UINT64) (Xhc->DBOff + Offset),
1,
&Data
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "XhcWriteOpReg: Pci Io Write error: %r at %d\n", Status, Offset));
}
}
/**
Read XHCI runtime register.
@param Xhc The XHCI device.
@param Offset The offset of the runtime register.
@return The register content read
**/
UINT32
XhcReadRuntimeReg (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset
)
{
UINT32 Data;
EFI_STATUS Status;
ASSERT (Xhc->RTSOff != 0);
Status = Xhc->PciIo->Mem.Read (
Xhc->PciIo,
EfiPciIoWidthUint32,
XHC_BAR_INDEX,
(UINT64) (Xhc->RTSOff + Offset),
1,
&Data
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "XhcReadRuntimeReg: Pci Io Read error - %r at %d\n", Status, Offset));
Data = 0xFFFFFFFF;
}
return Data;
}
/**
Read 8-bytes width XHCI runtime register.
@param Xhc The XHCI device.
@param Offset The offset of the 8-bytes width runtime register.
@return The register content read
**/
UINT64
XhcReadRuntimeReg64 (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset
)
{
UINT64 Data;
EFI_STATUS Status;
ASSERT (Xhc->RTSOff != 0);
Status = Xhc->PciIo->Mem.Read (
Xhc->PciIo,
EfiPciIoWidthUint64,
XHC_BAR_INDEX,
(UINT64) (Xhc->RTSOff + Offset),
1,
&Data
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "XhcReadRuntimeReg64: Pci Io Read error - %r at %d\n", Status, Offset));
Data = 0xFFFFFFFFFFFFFFFF;
}
return Data;
}
/**
Write the data to the XHCI runtime register.
@param Xhc The XHCI device.
@param Offset The offset of the runtime register.
@param Data The data to write.
**/
VOID
XhcWriteRuntimeReg (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset,
IN UINT32 Data
)
{
EFI_STATUS Status;
ASSERT (Xhc->RTSOff != 0);
Status = Xhc->PciIo->Mem.Write (
Xhc->PciIo,
EfiPciIoWidthUint32,
XHC_BAR_INDEX,
(UINT64) (Xhc->RTSOff + Offset),
1,
&Data
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "XhcWriteRuntimeReg: Pci Io Write error: %r at %d\n", Status, Offset));
}
}
/**
Write the data to the 8-bytes width XHCI runtime register.
@param Xhc The XHCI device.
@param Offset The offset of the 8-bytes width runtime register.
@param Data The data to write.
**/
VOID
XhcWriteRuntimeReg64 (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset,
IN UINT64 Data
)
{
EFI_STATUS Status;
ASSERT (Xhc->RTSOff != 0);
Status = Xhc->PciIo->Mem.Write (
Xhc->PciIo,
EfiPciIoWidthUint64,
XHC_BAR_INDEX,
(UINT64) (Xhc->RTSOff + Offset),
1,
&Data
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "XhcWriteRuntimeReg64: Pci Io Write error: %r at %d\n", Status, Offset));
}
}
/**
Read XHCI extended capability register.
@param Xhc The XHCI device.
@param Offset The offset of the extended capability register.
@return The register content read
**/
UINT32
XhcReadExtCapReg (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset
)
{
UINT32 Data;
EFI_STATUS Status;
ASSERT (Xhc->ExtCapRegBase != 0);
Status = Xhc->PciIo->Mem.Read (
Xhc->PciIo,
EfiPciIoWidthUint32,
XHC_BAR_INDEX,
(UINT64) (Xhc->ExtCapRegBase + Offset),
1,
&Data
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "XhcReadExtCapReg: Pci Io Read error - %r at %d\n", Status, Offset));
Data = 0xFFFFFFFF;
}
return Data;
}
/**
Write the data to the XHCI extended capability register.
@param Xhc The XHCI device.
@param Offset The offset of the extended capability register.
@param Data The data to write.
**/
VOID
XhcWriteExtCapReg (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset,
IN UINT32 Data
)
{
EFI_STATUS Status;
ASSERT (Xhc->ExtCapRegBase != 0);
Status = Xhc->PciIo->Mem.Write (
Xhc->PciIo,
EfiPciIoWidthUint32,
XHC_BAR_INDEX,
(UINT64) (Xhc->ExtCapRegBase + Offset),
1,
&Data
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "XhcWriteExtCapReg: Pci Io Write error: %r at %d\n", Status, Offset));
}
}
/**
Set one bit of the runtime register while keeping other bits.
@param Xhc The XHCI device.
@param Offset The offset of the runtime register.
@param Bit The bit mask of the register to set.
**/
VOID
XhcSetRuntimeRegBit (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset,
IN UINT32 Bit
)
{
UINT32 Data;
Data = XhcReadRuntimeReg (Xhc, Offset);
Data |= Bit;
XhcWriteRuntimeReg (Xhc, Offset, Data);
}
/**
Clear one bit of the runtime register while keeping other bits.
@param Xhc The XHCI device.
@param Offset The offset of the runtime register.
@param Bit The bit mask of the register to set.
**/
VOID
XhcClearRuntimeRegBit (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset,
IN UINT32 Bit
)
{
UINT32 Data;
Data = XhcReadRuntimeReg (Xhc, Offset);
Data &= ~Bit;
XhcWriteRuntimeReg (Xhc, Offset, Data);
}
/**
Set one bit of the operational register while keeping other bits.
@param Xhc The XHCI device.
@param Offset The offset of the operational register.
@param Bit The bit mask of the register to set.
**/
VOID
XhcSetOpRegBit (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset,
IN UINT32 Bit
)
{
UINT32 Data;
Data = XhcReadOpReg (Xhc, Offset);
Data |= Bit;
XhcWriteOpReg (Xhc, Offset, Data);
}
/**
Clear one bit of the operational register while keeping other bits.
@param Xhc The XHCI device.
@param Offset The offset of the operational register.
@param Bit The bit mask of the register to clear.
**/
VOID
XhcClearOpRegBit (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset,
IN UINT32 Bit
)
{
UINT32 Data;
Data = XhcReadOpReg (Xhc, Offset);
Data &= ~Bit;
XhcWriteOpReg (Xhc, Offset, Data);
}
/**
Wait the operation register's bit as specified by Bit
to become set (or clear).
@param Xhc The XHCI device.
@param Offset The offset of the operation register.
@param Bit The bit of the register to wait for.
@param WaitToSet Wait the bit to set or clear.
@param Timeout The time to wait before abort (in millisecond, ms).
@retval EFI_SUCCESS The bit successfully changed by host controller.
@retval EFI_TIMEOUT The time out occurred.
**/
EFI_STATUS
XhcWaitOpRegBit (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset,
IN UINT32 Bit,
IN BOOLEAN WaitToSet,
IN UINT32 Timeout
)
{
UINT32 Index;
for (Index = 0; Index < Timeout / XHC_SYNC_POLL_INTERVAL + 1; Index++) {
if (XHC_REG_BIT_IS_SET (Xhc, Offset, Bit) == WaitToSet) {
return EFI_SUCCESS;
}
gBS->Stall (XHC_SYNC_POLL_INTERVAL);
}
return EFI_TIMEOUT;
}
/**
Set Bios Ownership
@param Xhc The XHCI device.
**/
VOID
XhcSetBiosOwnership (
IN USB_XHCI_DEV *Xhc
)
{
UINT32 Buffer;
DEBUG ((EFI_D_INFO, "XhcSetBiosOwnership: called to set BIOS ownership\n"));
Buffer = XhcReadExtCapReg (Xhc, Xhc->UsbLegSupOffset);
Buffer = ((Buffer & (~USBLEGSP_OS_SEMAPHORE)) | USBLEGSP_BIOS_SEMAPHORE);
XhcWriteExtCapReg (Xhc, Xhc->UsbLegSupOffset, Buffer);
}
/**
Clear Bios Ownership
@param Xhc The XHCI device.
**/
VOID
XhcClearBiosOwnership (
IN USB_XHCI_DEV *Xhc
)
{
UINT32 Buffer;
DEBUG ((EFI_D_INFO, "XhcClearBiosOwnership: called to clear BIOS ownership\n"));
Buffer = XhcReadExtCapReg (Xhc, Xhc->UsbLegSupOffset);
Buffer = ((Buffer & (~USBLEGSP_BIOS_SEMAPHORE)) | USBLEGSP_OS_SEMAPHORE);
XhcWriteExtCapReg (Xhc, Xhc->UsbLegSupOffset, Buffer);
}
/**
Calculate the XHCI legacy support capability register offset.
@param Xhc The XHCI device.
@return The offset of XHCI legacy support capability register.
**/
UINT32
XhcGetLegSupCapAddr (
IN USB_XHCI_DEV *Xhc
)
{
UINT32 ExtCapOffset;
UINT8 NextExtCapReg;
UINT32 Data;
ExtCapOffset = 0;
do {
//
// Check if the extended capability register's capability id is USB Legacy Support.
//
Data = XhcReadExtCapReg (Xhc, ExtCapOffset);
if ((Data & 0xFF) == 0x1) {
return ExtCapOffset;
}
//
// If not, then traverse all of the ext capability registers till finding out it.
//
NextExtCapReg = (Data >> 8) & 0xFF;
ExtCapOffset += (NextExtCapReg << 2);
} while (NextExtCapReg != 0);
return 0;
}
/**
Whether the XHCI host controller is halted.
@param Xhc The XHCI device.
@retval TRUE The controller is halted.
@retval FALSE It isn't halted.
**/
BOOLEAN
XhcIsHalt (
IN USB_XHCI_DEV *Xhc
)
{
return XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT);
}
/**
Whether system error occurred.
@param Xhc The XHCI device.
@retval TRUE System error happened.
@retval FALSE No system error.
**/
BOOLEAN
XhcIsSysError (
IN USB_XHCI_DEV *Xhc
)
{
return XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HSE);
}
/**
Reset the XHCI host controller.
@param Xhc The XHCI device.
@param Timeout Time to wait before abort (in millisecond, ms).
@retval EFI_SUCCESS The XHCI host controller is reset.
@return Others Failed to reset the XHCI before Timeout.
**/
EFI_STATUS
XhcResetHC (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Timeout
)
{
EFI_STATUS Status;
DEBUG ((EFI_D_INFO, "XhcResetHC!\n"));
//
// Host can only be reset when it is halt. If not so, halt it
//
if (!XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT)) {
Status = XhcHaltHC (Xhc, Timeout);
if (EFI_ERROR (Status)) {
return Status;
}
}
XhcSetOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RESET);
Status = XhcWaitOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RESET, FALSE, Timeout);
return Status;
}
/**
Halt the XHCI host controller.
@param Xhc The XHCI device.
@param Timeout Time to wait before abort (in millisecond, ms).
@return EFI_SUCCESS The XHCI host controller is halt.
@return EFI_TIMEOUT Failed to halt the XHCI before Timeout.
**/
EFI_STATUS
XhcHaltHC (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Timeout
)
{
EFI_STATUS Status;
XhcClearOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RUN);
Status = XhcWaitOpRegBit (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT, TRUE, Timeout);
return Status;
}
/**
Set the XHCI host controller to run.
@param Xhc The XHCI device.
@param Timeout Time to wait before abort (in millisecond, ms).
@return EFI_SUCCESS The XHCI host controller is running.
@return EFI_TIMEOUT Failed to set the XHCI to run before Timeout.
**/
EFI_STATUS
XhcRunHC (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Timeout
)
{
EFI_STATUS Status;
XhcSetOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RUN);
Status = XhcWaitOpRegBit (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT, FALSE, Timeout);
return Status;
}

View File

@ -0,0 +1,569 @@
/** @file
This file contains the register definition of XHCI host controller.
Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
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.
**/
#ifndef _EFI_XHCI_REG_H_
#define _EFI_XHCI_REG_H_
#define PCI_IF_XHCI 0x30
//
// PCI Configuration Registers
//
#define XHC_BAR_INDEX 0x00
#define XHC_PCI_BAR_OFFSET 0x10 // Memory Bar Register Offset
#define XHC_PCI_BAR_MASK 0xFFFF // Memory Base Address Mask
#define USB_HUB_CLASS_CODE 0x09
#define USB_HUB_SUBCLASS_CODE 0x00
//============================================//
// XHCI register offset //
//============================================//
//
// Capability registers offset
//
#define XHC_CAPLENGTH_OFFSET 0x00 // Capability register length offset
#define XHC_HCIVERSION_OFFSET 0x02 // Interface Version Number 02-03h
#define XHC_HCSPARAMS1_OFFSET 0x04 // Structural Parameters 1
#define XHC_HCSPARAMS2_OFFSET 0x08 // Structural Parameters 2
#define XHC_HCSPARAMS3_OFFSET 0x0c // Structural Parameters 3
#define XHC_HCCPARAMS_OFFSET 0x10 // Capability Parameters
#define XHC_DBOFF_OFFSET 0x14 // Doorbell Offset
#define XHC_RTSOFF_OFFSET 0x18 // Runtime Register Space Offset
//
// Operational registers offset
//
#define XHC_USBCMD_OFFSET 0x0000 // USB Command Register Offset
#define XHC_USBSTS_OFFSET 0x0004 // USB Status Register Offset
#define XHC_PAGESIZE_OFFSET 0x0008 // USB Page Size Register Offset
#define XHC_DNCTRL_OFFSET 0x0014 // Device Notification Control Register Offset
#define XHC_CRCR_OFFSET 0x0018 // Command Ring Control Register Offset
#define XHC_DCBAAP_OFFSET 0x0030 // Device Context Base Address Array Pointer Register Offset
#define XHC_CONFIG_OFFSET 0x0038 // Configure Register Offset
#define XHC_PORTSC_OFFSET 0x0400 // Port Status and Control Register Offset
//
// Runtime registers offset
//
#define XHC_MFINDEX_OFFSET 0x00 // Microframe Index Register Offset
#define XHC_IMAN_OFFSET 0x20 // Interrupter X Management Register Offset
#define XHC_IMOD_OFFSET 0x24 // Interrupter X Moderation Register Offset
#define XHC_ERSTSZ_OFFSET 0x28 // Event Ring Segment Table Size Register Offset
#define XHC_ERSTBA_OFFSET 0x30 // Event Ring Segment Table Base Address Register Offset
#define XHC_ERDP_OFFSET 0x38 // Event Ring Dequeue Pointer Register Offset
#define USBLEGSP_BIOS_SEMAPHORE BIT16 // HC BIOS Owned Semaphore
#define USBLEGSP_OS_SEMAPHORE BIT24 // HC OS Owned Semaphore
#pragma pack (1)
//
// Structural Parameters 1 Register Bitmap Definition
//
typedef union _XHC_HCSPARAMS1 {
UINT32 Dword;
struct {
UINT8 MaxSlots; // Number of Device Slots
UINT16 MaxIntrs:11; // Number of Interrupters
UINT16 Rsvd:5;
UINT8 MaxPorts; // Number of Ports
} Data;
} XHC_HCSPARAMS1;
//
// Structural Parameters 2 Register Bitmap Definition
//
typedef union _XHC_HCSPARAMS2 {
UINT32 Dword;
struct {
UINT32 Ist:4; // Isochronous Scheduling Threshold
UINT32 Erst:4; // Event Ring Segment Table Max
UINT32 Rsvd:13;
UINT32 ScratchBufHi:5; // Max Scratchpad Buffers Hi
UINT32 Spr:1; // Scratchpad Restore
UINT32 ScratchBufLo:5; // Max Scratchpad Buffers Lo
} Data;
} XHC_HCSPARAMS2;
//
// Capability Parameters Register Bitmap Definition
//
typedef union _XHC_HCCPARAMS {
UINT32 Dword;
struct {
UINT16 Ac64:1; // 64-bit Addressing Capability
UINT16 Bnc:1; // BW Negotiation Capability
UINT16 Csz:1; // Context Size
UINT16 Ppc:1; // Port Power Control
UINT16 Pind:1; // Port Indicators
UINT16 Lhrc:1; // Light HC Reset Capability
UINT16 Ltc:1; // Latency Tolerance Messaging Capability
UINT16 Nss:1; // No Secondary SID Support
UINT16 Pae:1; // Parse All Event Data
UINT16 Rsvd:3;
UINT16 MaxPsaSize:4; // Maximum Primary Stream Array Size
UINT16 ExtCapReg; // xHCI Extended Capabilities Pointer
} Data;
} XHC_HCCPARAMS;
#pragma pack ()
//
// Register Bit Definition
//
#define XHC_USBCMD_RUN BIT0 // Run/Stop
#define XHC_USBCMD_RESET BIT1 // Host Controller Reset
#define XHC_USBCMD_INTE BIT2 // Interrupter Enable
#define XHC_USBCMD_HSEE BIT3 // Host System Error Enable
#define XHC_USBSTS_HALT BIT0 // Host Controller Halted
#define XHC_USBSTS_HSE BIT2 // Host System Error
#define XHC_USBSTS_EINT BIT3 // Event Interrupt
#define XHC_USBSTS_PCD BIT4 // Port Change Detect
#define XHC_USBSTS_SSS BIT8 // Save State Status
#define XHC_USBSTS_RSS BIT9 // Restore State Status
#define XHC_USBSTS_SRE BIT10 // Save/Restore Error
#define XHC_USBSTS_CNR BIT11 // Host Controller Not Ready
#define XHC_USBSTS_HCE BIT12 // Host Controller Error
#define XHC_PAGESIZE_MASK 0xFFFF // Page Size
#define XHC_CRCR_RCS BIT0 // Ring Cycle State
#define XHC_CRCR_CS BIT1 // Command Stop
#define XHC_CRCR_CA BIT2 // Command Abort
#define XHC_CRCR_CRR BIT3 // Command Ring Running
#define XHC_CONFIG_MASK 0xFF // Command Ring Running
#define XHC_PORTSC_CCS BIT0 // Current Connect Status
#define XHC_PORTSC_PED BIT1 // Port Enabled/Disabled
#define XHC_PORTSC_OCA BIT3 // Over-current Active
#define XHC_PORTSC_RESET BIT4 // Port Reset
#define XHC_PORTSC_PLS (BIT5|BIT6|BIT7|BIT8) // Port Link State
#define XHC_PORTSC_PP BIT9 // Port Power
#define XHC_PORTSC_PS (BIT10|BIT11|BIT12|BIT13) // Port Speed
#define XHC_PORTSC_LWS BIT16 // Port Link State Write Strobe
#define XHC_PORTSC_CSC BIT17 // Connect Status Change
#define XHC_PORTSC_PEC BIT18 // Port Enabled/Disabled Change
#define XHC_PORTSC_WRC BIT19 // Warm Port Reset Change
#define XHC_PORTSC_OCC BIT20 // Over-Current Change
#define XHC_PORTSC_PRC BIT21 // Port Reset Change
#define XHC_PORTSC_PLC BIT22 // Port Link State Change
#define XHC_PORTSC_CEC BIT23 // Port Config Error Change
#define XHC_PORTSC_CAS BIT24 // Cold Attach Status
#define XHC_IMAN_IP BIT0 // Interrupt Pending
#define XHC_IMAN_IE BIT1 // Interrupt Enable
#define XHC_IMODI_MASK 0x0000FFFF // Interrupt Moderation Interval
#define XHC_IMODC_MASK 0xFFFF0000 // Interrupt Moderation Counter
//
// Structure to map the hardware port states to the
// UEFI's port states.
//
typedef struct {
UINT32 HwState;
UINT16 UefiState;
} USB_PORT_STATE_MAP;
/**
Read 1-byte width XHCI capability register.
@param Xhc The XHCI device.
@param Offset The offset of the 1-byte width capability register.
@return The register content read.
@retval If err, return 0xFFFF.
**/
UINT8
XhcReadCapReg8 (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset
);
/**
Read 4-bytes width XHCI capability register.
@param Xhc The XHCI device.
@param Offset The offset of the 4-bytes width capability register.
@return The register content read.
@retval If err, return 0xFFFFFFFF.
**/
UINT32
XhcReadCapReg (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset
);
/**
Read 4-bytes width XHCI Operational register.
@param Xhc The XHCI device.
@param Offset The offset of the 4-bytes width operational register.
@return The register content read.
@retval If err, return 0xFFFFFFFF.
**/
UINT32
XhcReadOpReg (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset
);
/**
Write the data to the 4-bytes width XHCI operational register.
@param Xhc The XHCI device.
@param Offset The offset of the 4-bytes width operational register.
@param Data The data to write.
**/
VOID
XhcWriteOpReg (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset,
IN UINT32 Data
);
/**
Write the data to the 2-bytes width XHCI operational register.
@param Xhc The XHCI device.
@param Offset The offset of the 2-bytes width operational register.
@param Data The data to write.
**/
VOID
XhcWriteOpReg16 (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset,
IN UINT16 Data
);
/**
Write the data to the 8-bytes width XHCI operational register.
@param Xhc The XHCI device.
@param Offset The offset of the 8-bytes width operational register.
@param Data The data to write.
**/
VOID
XhcWriteOpReg64 (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset,
IN UINT64 Data
);
/**
Read XHCI runtime register.
@param Xhc The XHCI device.
@param Offset The offset of the runtime register.
@return The register content read
**/
UINT32
XhcReadRuntimeReg (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset
);
/**
Read 8-bytes width XHCI runtime register.
@param Xhc The XHCI device.
@param Offset The offset of the 8-bytes width runtime register.
@return The register content read
**/
UINT64
XhcReadRuntimeReg64 (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset
);
/**
Write the data to the XHCI runtime register.
@param Xhc The XHCI device.
@param Offset The offset of the runtime register.
@param Data The data to write.
**/
VOID
XhcWriteRuntimeReg (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset,
IN UINT32 Data
);
/**
Write the data to the 8-bytes width XHCI runtime register.
@param Xhc The XHCI device.
@param Offset The offset of the 8-bytes width runtime register.
@param Data The data to write.
**/
VOID
XhcWriteRuntimeReg64 (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset,
IN UINT64 Data
);
/**
Read XHCI door bell register.
@param Xhc The XHCI device.
@param Offset The offset of the door bell register.
@return The register content read
**/
UINT32
XhcReadDoorBellReg (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset
);
/**
Write the data to the XHCI door bell register.
@param Xhc The XHCI device.
@param Offset The offset of the door bell register.
@param Data The data to write.
**/
VOID
XhcWriteDoorBellReg (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset,
IN UINT32 Data
);
/**
Set one bit of the operational register while keeping other bits.
@param Xhc The XHCI device.
@param Offset The offset of the operational register.
@param Bit The bit mask of the register to set.
**/
VOID
XhcSetOpRegBit (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset,
IN UINT32 Bit
);
/**
Clear one bit of the operational register while keeping other bits.
@param Xhc The XHCI device.
@param Offset The offset of the operational register.
@param Bit The bit mask of the register to clear.
**/
VOID
XhcClearOpRegBit (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset,
IN UINT32 Bit
);
/**
Wait the operation register's bit as specified by Bit
to be set (or clear).
@param Xhc The XHCI device.
@param Offset The offset of the operational register.
@param Bit The bit of the register to wait for.
@param WaitToSet Wait the bit to set or clear.
@param Timeout The time to wait before abort (in millisecond, ms).
@retval EFI_SUCCESS The bit successfully changed by host controller.
@retval EFI_TIMEOUT The time out occurred.
**/
EFI_STATUS
XhcWaitOpRegBit (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset,
IN UINT32 Bit,
IN BOOLEAN WaitToSet,
IN UINT32 Timeout
);
/**
Read XHCI runtime register.
@param Xhc The XHCI device.
@param Offset The offset of the runtime register.
@return The register content read
**/
UINT32
XhcReadRuntimeReg (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset
);
/**
Write the data to the XHCI runtime register.
@param Xhc The XHCI device.
@param Offset The offset of the runtime register.
@param Data The data to write.
**/
VOID
XhcWriteRuntimeReg (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset,
IN UINT32 Data
);
/**
Set one bit of the runtime register while keeping other bits.
@param Xhc The XHCI device.
@param Offset The offset of the runtime register.
@param Bit The bit mask of the register to set.
**/
VOID
XhcSetRuntimeRegBit (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset,
IN UINT32 Bit
);
/**
Clear one bit of the runtime register while keeping other bits.
@param Xhc The XHCI device.
@param Offset The offset of the runtime register.
@param Bit The bit mask of the register to set.
**/
VOID
XhcClearRuntimeRegBit (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Offset,
IN UINT32 Bit
);
/**
Whether the XHCI host controller is halted.
@param Xhc The XHCI device.
@retval TRUE The controller is halted.
@retval FALSE It isn't halted.
**/
BOOLEAN
XhcIsHalt (
IN USB_XHCI_DEV *Xhc
);
/**
Whether system error occurred.
@param Xhc The XHCI device.
@retval TRUE System error happened.
@retval FALSE No system error.
**/
BOOLEAN
XhcIsSysError (
IN USB_XHCI_DEV *Xhc
);
/**
Reset the XHCI host controller.
@param Xhc The XHCI device.
@param Timeout Time to wait before abort (in millisecond, ms).
@retval EFI_SUCCESS The XHCI host controller is reset.
@return Others Failed to reset the XHCI before Timeout.
**/
EFI_STATUS
XhcResetHC (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Timeout
);
/**
Halt the XHCI host controller.
@param Xhc The XHCI device.
@param Timeout Time to wait before abort (in millisecond, ms).
@return EFI_SUCCESS The XHCI host controller is halt.
@return EFI_TIMEOUT Failed to halt the XHCI before Timeout.
**/
EFI_STATUS
XhcHaltHC (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Timeout
);
/**
Set the XHCI host controller to run.
@param Xhc The XHCI device.
@param Timeout Time to wait before abort (in millisecond, ms).
@return EFI_SUCCESS The XHCI host controller is running.
@return EFI_TIMEOUT Failed to set the XHCI to run before Timeout.
**/
EFI_STATUS
XhcRunHC (
IN USB_XHCI_DEV *Xhc,
IN UINT32 Timeout
);
/**
Calculate the XHCI legacy support capability register offset.
@param Xhc The XHCI device.
@return The offset of XHCI legacy support capability register.
**/
UINT32
XhcGetLegSupCapAddr (
IN USB_XHCI_DEV *Xhc
);
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,7 @@ EFI_DRIVER_BINDING_PROTOCOL mUsbBusDriverBinding = {
NULL
};
UINT16 mMaxUsbDeviceNum = USB_MAX_DEVICES;
/**
USB_IO function to execute a control transfer. This
@ -111,7 +112,7 @@ UsbIoControlTransfer (
// Clear TT buffer when CTRL/BULK split transaction failes
// Clear the TRANSLATOR TT buffer, not parent's buffer
//
ASSERT (Dev->Translator.TranslatorHubAddress < USB_MAX_DEVICES);
ASSERT (Dev->Translator.TranslatorHubAddress < mMaxUsbDeviceNum);
if (Dev->Translator.TranslatorHubAddress != 0) {
UsbHubCtrlClearTTBuffer (
Dev->Bus->Devices[Dev->Translator.TranslatorHubAddress],
@ -284,7 +285,7 @@ UsbIoBulkTransfer (
// Clear TT buffer when CTRL/BULK split transaction failes.
// Clear the TRANSLATOR TT buffer, not parent's buffer
//
ASSERT (Dev->Translator.TranslatorHubAddress < USB_MAX_DEVICES);
ASSERT (Dev->Translator.TranslatorHubAddress < mMaxUsbDeviceNum);
if (Dev->Translator.TranslatorHubAddress != 0) {
UsbHubCtrlClearTTBuffer (
Dev->Bus->Devices[Dev->Translator.TranslatorHubAddress],
@ -966,6 +967,16 @@ UsbBusBuildProtocol (
goto CLOSE_HC;
}
if (!EFI_ERROR (Status)) {
if (UsbBus->Usb2Hc->MajorRevision == 0x3) {
//
// The EFI_USB2_HC_PROTOCOL is produced for XHCI support.
// Then its max supported devices are 256.
//
mMaxUsbDeviceNum = 256;
}
}
UsbHcReset (UsbBus, EFI_USB_HC_RESET_GLOBAL);
UsbHcSetState (UsbBus, EfiUsbHcStateOperational);
@ -1011,6 +1022,7 @@ UsbBusBuildProtocol (
RootHub->Bus = UsbBus;
RootHub->NumOfInterface = 1;
RootHub->Interfaces[0] = RootIf;
RootHub->Tier = 0;
RootIf->Signature = USB_INTERFACE_SIGNATURE;
RootIf->Device = RootHub;
RootIf->DevicePath = UsbBus->DevicePath;
@ -1434,7 +1446,7 @@ UsbBusControllerDriverStop (
mUsbRootHubApi.Release (RootIf);
for (Index = 1; Index < USB_MAX_DEVICES; Index++) {
for (Index = 1; Index < mMaxUsbDeviceNum; Index++) {
if (Bus->Devices[Index] != NULL) {
UsbRemoveDevice (Bus->Devices[Index]);
}

View File

@ -167,7 +167,7 @@ struct _USB_DEVICE {
//
UINT8 Speed;
UINT8 Address;
UINT8 MaxPacket0;
UINT32 MaxPacket0;
//
// The device's descriptors and its configuration
@ -189,6 +189,7 @@ struct _USB_DEVICE {
UINT8 ParentAddr;
USB_INTERFACE *ParentIf;
UINT8 ParentPort; // Start at 0
UINT8 Tier;
};
//
@ -249,7 +250,7 @@ struct _USB_BUS {
// An array of device that is on the bus. Devices[0] is
// for root hub. Device with address i is at Devices[i].
//
USB_DEVICE *Devices[USB_MAX_DEVICES];
USB_DEVICE *Devices[256];
//
// USB Bus driver need to control the recursive connect policy of the bus, only those wanted
@ -746,6 +747,7 @@ UsbBusControllerDriverStop (
IN EFI_HANDLE *ChildHandleBuffer
);
extern UINT16 mMaxUsbDeviceNum;
extern EFI_USB_IO_PROTOCOL mUsbIoProtocol;
extern EFI_DRIVER_BINDING_PROTOCOL mUsbBusDriverBinding;
extern EFI_COMPONENT_NAME_PROTOCOL mUsbBusComponentName;

View File

@ -527,12 +527,14 @@ UsbGetMaxPacketSize0 (
// Get the first 8 bytes of the device descriptor which contains
// max packet size for endpoint 0, which is at least 8.
//
UsbDev->MaxPacket0 = 8;
for (Index = 0; Index < 3; Index++) {
Status = UsbCtrlGetDesc (UsbDev, USB_DESC_TYPE_DEVICE, 0, 0, &DevDesc, 8);
if (!EFI_ERROR (Status)) {
if ((DevDesc.BcdUSB == 0x0300) && (DevDesc.MaxPacketSize0 == 9)) {
UsbDev->MaxPacket0 = 1 << 9;
return EFI_SUCCESS;
}
UsbDev->MaxPacket0 = DevDesc.MaxPacketSize0;
return EFI_SUCCESS;
}

View File

@ -2,7 +2,7 @@
Usb bus enumeration support.
Copyright (c) 2007 - 2008, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>
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
@ -15,7 +15,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "UsbBus.h"
/**
Return the endpoint descriptor in this interface.
@ -234,6 +233,7 @@ UsbCreateDevice (
Device->ParentAddr = ParentIf->Device->Address;
Device->ParentIf = ParentIf;
Device->ParentPort = ParentPort;
Device->Tier = ParentIf->Device->Tier + 1;
return Device;
}
@ -540,7 +540,7 @@ UsbRemoveDevice (
USB_BUS *Bus;
USB_DEVICE *Child;
EFI_STATUS Status;
UINT8 Index;
UINTN Index;
Bus = Device->Bus;
@ -548,7 +548,7 @@ UsbRemoveDevice (
// Remove all the devices on its downstream ports. Search from devices[1].
// Devices[0] is the root hub.
//
for (Index = 1; Index < USB_MAX_DEVICES; Index++) {
for (Index = 1; Index < mMaxUsbDeviceNum; Index++) {
Child = Bus->Devices[Index];
if ((Child == NULL) || (Child->ParentAddr != Device->Address)) {
@ -567,7 +567,7 @@ UsbRemoveDevice (
DEBUG (( EFI_D_INFO, "UsbRemoveDevice: device %d removed\n", Device->Address));
ASSERT (Device->Address < USB_MAX_DEVICES);
ASSERT (Device->Address < mMaxUsbDeviceNum);
Bus->Devices[Device->Address] = NULL;
UsbFreeDevice (Device);
@ -599,7 +599,7 @@ UsbFindChild (
//
// Start checking from device 1, device 0 is the root hub
//
for (Index = 1; Index < USB_MAX_DEVICES; Index++) {
for (Index = 1; Index < mMaxUsbDeviceNum; Index++) {
Device = Bus->Devices[Index];
if ((Device != NULL) && (Device->ParentAddr == HubIf->Device->Address) &&
@ -635,11 +635,11 @@ UsbEnumerateNewDev (
USB_DEVICE *Child;
USB_DEVICE *Parent;
EFI_USB_PORT_STATUS PortState;
UINT8 Address;
UINTN Address;
UINT8 Config;
EFI_STATUS Status;
Address = USB_MAX_DEVICES;
Address = mMaxUsbDeviceNum;
Parent = HubIf->Device;
Bus = Parent->Bus;
HubApi = HubIf->HubApi;
@ -679,14 +679,21 @@ UsbEnumerateNewDev (
goto ON_ERROR;
}
if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_LOW_SPEED)) {
Child->Speed = EFI_USB_SPEED_LOW;
if (!USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_CONNECTION)) {
DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: No device presented at port %d\n", Port));
goto ON_ERROR;
} else if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_SUPER_SPEED)){
Child->Speed = EFI_USB_SPEED_SUPER;
Child->MaxPacket0 = 512;
} else if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_HIGH_SPEED)) {
Child->Speed = EFI_USB_SPEED_HIGH;
Child->Speed = EFI_USB_SPEED_HIGH;
Child->MaxPacket0 = 64;
} else if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_LOW_SPEED)) {
Child->Speed = EFI_USB_SPEED_LOW;
Child->MaxPacket0 = 8;
} else {
Child->Speed = EFI_USB_SPEED_FULL;
Child->Speed = EFI_USB_SPEED_FULL;
Child->MaxPacket0 = 8;
}
DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: device is of %d speed\n", Child->Speed));
@ -719,6 +726,37 @@ UsbEnumerateNewDev (
// a time) , and ready to respond to control transfer at EP 0.
//
//
// Host assigns an address to the device. Device completes the
// status stage with default address, then switches to new address.
// ADDRESS state. Address zero is reserved for root hub.
//
for (Address = 1; Address < mMaxUsbDeviceNum; Address++) {
if (Bus->Devices[Address] == NULL) {
break;
}
}
if (Address == mMaxUsbDeviceNum) {
DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: address pool is full for port %d\n", Port));
Status = EFI_ACCESS_DENIED;
goto ON_ERROR;
}
Status = UsbSetAddress (Child, (UINT8)Address);
Child->Address = (UINT8)Address;
Bus->Devices[Address] = Child;
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to set device address - %r\n", Status));
goto ON_ERROR;
}
gBS->Stall (USB_SET_DEVICE_ADDRESS_STALL);
DEBUG ((EFI_D_INFO, "UsbEnumerateNewDev: device is now ADDRESSED at %d\n", Address));
//
// Host sends a Get_Descriptor request to learn the max packet
// size of default pipe (only part of the device's descriptor).
@ -732,37 +770,6 @@ UsbEnumerateNewDev (
DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: max packet size for EP 0 is %d\n", Child->MaxPacket0));
//
// Host assigns an address to the device. Device completes the
// status stage with default address, then switches to new address.
// ADDRESS state. Address zero is reserved for root hub.
//
for (Address = 1; Address < USB_MAX_DEVICES; Address++) {
if (Bus->Devices[Address] == NULL) {
break;
}
}
if (Address == USB_MAX_DEVICES) {
DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: address pool is full for port %d\n", Port));
Status = EFI_ACCESS_DENIED;
goto ON_ERROR;
}
Bus->Devices[Address] = Child;
Status = UsbSetAddress (Child, Address);
Child->Address = Address;
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to set device address - %r\n", Status));
goto ON_ERROR;
}
gBS->Stall (USB_SET_DEVICE_ADDRESS_STALL);
DEBUG ((EFI_D_INFO, "UsbEnumerateNewDev: device is now ADDRESSED at %d\n", Address));
//
// Host learns about the device's abilities by requesting device's
// entire descriptions.
@ -801,7 +808,7 @@ UsbEnumerateNewDev (
return EFI_SUCCESS;
ON_ERROR:
if (Address != USB_MAX_DEVICES) {
if (Address != mMaxUsbDeviceNum) {
Bus->Devices[Address] = NULL;
}
@ -848,12 +855,16 @@ UsbEnumeratePort (
return Status;
}
if (PortState.PortChangeStatus == 0) {
//
// Only handle connection/enable/overcurrent/reset change.
// Usb super speed hub may report other changes, such as warm reset change. Ignore them.
//
if ((PortState.PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) {
return EFI_SUCCESS;
}
DEBUG (( EFI_D_INFO, "UsbEnumeratePort: port %d state - %x, change - %x on %p\n",
Port, PortState.PortStatus, PortState.PortChangeStatus, HubIf));
DEBUG (( EFI_D_INFO, "UsbEnumeratePort: port %d state - %02x, change - %02x on %p\n",
Port, PortState.PortChangeStatus, PortState.PortStatus, HubIf));
//
// This driver only process two kinds of events now: over current and

View File

@ -22,19 +22,15 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
// bits determine whether hub will report the port in changed
// bit maps.
//
#define USB_HUB_MAP_SIZE 5
USB_CHANGE_FEATURE_MAP mHubFeatureMap[USB_HUB_MAP_SIZE] = {
USB_CHANGE_FEATURE_MAP mHubFeatureMap[] = {
{USB_PORT_STAT_C_CONNECTION, EfiUsbPortConnectChange},
{USB_PORT_STAT_C_ENABLE, EfiUsbPortEnableChange},
{USB_PORT_STAT_C_SUSPEND, EfiUsbPortSuspendChange},
{USB_PORT_STAT_C_OVERCURRENT, EfiUsbPortOverCurrentChange},
{USB_PORT_STAT_C_RESET, EfiUsbPortResetChange},
{USB_PORT_STAT_C_RESET, EfiUsbPortResetChange}
};
#define USB_ROOT_HUB_MAP_SIZE 5
USB_CHANGE_FEATURE_MAP mRootHubFeatureMap[USB_ROOT_HUB_MAP_SIZE] = {
USB_CHANGE_FEATURE_MAP mRootHubFeatureMap[] = {
{USB_PORT_STAT_C_CONNECTION, EfiUsbPortConnectChange},
{USB_PORT_STAT_C_ENABLE, EfiUsbPortEnableChange},
{USB_PORT_STAT_C_SUSPEND, EfiUsbPortSuspendChange},
@ -47,7 +43,38 @@ USB_CHANGE_FEATURE_MAP mRootHubFeatureMap[USB_ROOT_HUB_MAP_SIZE] = {
// is related to an interface, these requests are sent
// to the control endpoint of the device.
//
/**
USB hub control transfer to set the hub depth.
@param HubDev The device of the hub.
@param Depth The depth to set.
@retval EFI_SUCCESS Depth of the hub is set.
@retval Others Failed to set the depth.
**/
EFI_STATUS
UsbHubCtrlSetHubDepth (
IN USB_DEVICE *HubDev,
IN UINT16 Depth
)
{
EFI_STATUS Status;
Status = UsbCtrlRequest (
HubDev,
EfiUsbNoData,
USB_REQ_TYPE_CLASS,
USB_HUB_TARGET_HUB,
USB_HUB_REQ_SET_DEPTH,
Depth,
0,
NULL,
0
);
return Status;
}
/**
USB hub control transfer to clear the hub feature.
@ -173,6 +200,41 @@ UsbHubCtrlClearTTBuffer (
return Status;
}
/**
Usb hub control transfer to get the super speed hub descriptor.
@param HubDev The hub device.
@param Buf The buffer to hold the descriptor.
@param Len The length to retrieve.
@retval EFI_SUCCESS The hub descriptor is retrieved.
@retval Others Failed to retrieve the hub descriptor.
**/
EFI_STATUS
UsbHubCtrlGetSuperSpeedHubDesc (
IN USB_DEVICE *HubDev,
OUT VOID *Buf
)
{
EFI_STATUS Status;
Status = EFI_INVALID_PARAMETER;
Status = UsbCtrlRequest (
HubDev,
EfiUsbDataIn,
USB_REQ_TYPE_CLASS,
USB_HUB_TARGET_HUB,
USB_HUB_REQ_GET_DESC,
(UINT16) (USB_DESC_TYPE_HUB_SUPER_SPEED << 8),
0,
Buf,
32
);
return Status;
}
/**
Usb hub control transfer to get the hub descriptor.
@ -414,20 +476,28 @@ UsbHubReadDesc (
{
EFI_STATUS Status;
//
// First get the hub descriptor length
//
Status = UsbHubCtrlGetHubDesc (HubDev, HubDesc, 2);
if (HubDev->Speed == EFI_USB_SPEED_SUPER) {
//
// Get the super speed hub descriptor
//
Status = UsbHubCtrlGetSuperSpeedHubDesc (HubDev, HubDesc);
} else {
if (EFI_ERROR (Status)) {
return Status;
//
// First get the hub descriptor length
//
Status = UsbHubCtrlGetHubDesc (HubDev, HubDesc, 2);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Get the whole hub descriptor
//
Status = UsbHubCtrlGetHubDesc (HubDev, HubDesc, HubDesc->Length);
}
//
// Get the whole hub descriptor
//
Status = UsbHubCtrlGetHubDesc (HubDev, HubDesc, HubDesc->Length);
return Status;
}
@ -629,6 +699,7 @@ UsbHubInit (
EFI_STATUS Status;
UINT8 Index;
UINT8 NumEndpoints;
UINT16 Depth;
//
// Locate the interrupt endpoint for port change map
@ -666,6 +737,37 @@ UsbHubInit (
DEBUG (( EFI_D_INFO, "UsbHubInit: hub %d has %d ports\n", HubDev->Address,HubIf->NumOfPort));
//
// OK, set IsHub to TRUE. Now usb bus can handle this device
// as a working HUB. If failed eariler, bus driver will not
// recognize it as a hub. Other parts of the bus should be able
// to work.
//
HubIf->IsHub = TRUE;
HubIf->HubApi = &mUsbHubApi;
HubIf->HubEp = EpDesc;
if (HubIf->Device->Speed == EFI_USB_SPEED_SUPER) {
Depth = (UINT16)(HubIf->Device->Tier - 1);
DEBUG ((EFI_D_INFO, "UsbHubInit: Set Hub Depth as 0x%x\n", Depth));
UsbHubCtrlSetHubDepth (HubIf->Device, Depth);
for (Index = 0; Index < HubDesc.NumPorts; Index++) {
UsbHubCtrlSetPortFeature (HubIf->Device, Index, USB_HUB_PORT_REMOTE_WAKE_MASK);
}
} else {
//
// Feed power to all the hub ports. It should be ok
// for both gang/individual powered hubs.
//
for (Index = 0; Index < HubDesc.NumPorts; Index++) {
UsbHubCtrlSetPortFeature (HubIf->Device, Index, (EFI_USB_PORT_FEATURE) USB_HUB_PORT_POWER);
}
gBS->Stall (HubDesc.PwrOn2PwrGood * USB_SET_PORT_POWER_STALL);
UsbHubAckHubStatus (HubIf->Device);
}
//
// Create an event to enumerate the hub's port. On
//
@ -712,27 +814,6 @@ UsbHubInit (
return Status;
}
//
// OK, set IsHub to TRUE. Now usb bus can handle this device
// as a working HUB. If failed eariler, bus driver will not
// recognize it as a hub. Other parts of the bus should be able
// to work.
//
HubIf->IsHub = TRUE;
HubIf->HubApi = &mUsbHubApi;
HubIf->HubEp = EpDesc;
//
// Feed power to all the hub ports. It should be ok
// for both gang/individual powered hubs.
//
for (Index = 0; Index < HubDesc.NumPorts; Index++) {
UsbHubCtrlSetPortFeature (HubIf->Device, Index, (EFI_USB_PORT_FEATURE) USB_HUB_PORT_POWER);
}
gBS->Stall (HubDesc.PwrOn2PwrGood * USB_SET_PORT_POWER_STALL);
UsbHubAckHubStatus (HubIf->Device);
DEBUG (( EFI_D_INFO, "UsbHubInit: hub %d initialized\n", HubDev->Address));
return Status;
}
@ -764,6 +845,12 @@ UsbHubGetPortStatus (
Status = UsbHubCtrlGetPortStatus (HubIf->Device, Port, PortState);
//
// Mark the USB_PORT_STAT_SUPER_SPEED bit if SuperSpeed
//
if (HubIf->Device->Speed == EFI_USB_SPEED_SUPER) {
PortState->PortStatus |= USB_PORT_STAT_SUPER_SPEED;
}
return Status;
}
@ -799,7 +886,7 @@ UsbHubClearPortChange (
// It may lead to extra port state report. USB bus should
// be able to handle this.
//
for (Index = 0; Index < USB_HUB_MAP_SIZE; Index++) {
for (Index = 0; Index < sizeof (mHubFeatureMap) / sizeof (mHubFeatureMap[0]); Index++) {
Map = &mHubFeatureMap[Index];
if (USB_BIT_IS_SET (PortState.PortChangeStatus, Map->ChangedBit)) {
@ -1091,7 +1178,7 @@ UsbRootHubClearPortChange (
// It may lead to extra port state report. USB bus should
// be able to handle this.
//
for (Index = 0; Index < USB_ROOT_HUB_MAP_SIZE; Index++) {
for (Index = 0; Index < sizeof (mRootHubFeatureMap) / sizeof (mRootHubFeatureMap[0]); Index++) {
Map = &mRootHubFeatureMap[Index];
if (USB_BIT_IS_SET (PortState.PortChangeStatus, Map->ChangedBit)) {

View File

@ -23,6 +23,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#define USB_DESC_TYPE_HUB 0x29
#define USB_DESC_TYPE_HUB_SUPER_SPEED 0x2a
//
// Hub class control transfer target
//
@ -40,6 +43,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#define USB_HUB_REQ_RESET_TT 9
#define USB_HUB_REQ_GET_TT_STATE 10
#define USB_HUB_REQ_STOP_TT 11
#define USB_HUB_REQ_SET_DEPTH 12
//
// USB hub class feature selector
//
@ -50,6 +56,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#define USB_HUB_PORT_SUSPEND 2
#define USB_HUB_PORT_OVER_CURRENT 3
#define USB_HUB_PORT_RESET 4
#define USB_HUB_PORT_LINK_STATE 5
#define USB_HUB_PORT_POWER 8
#define USB_HUB_PORT_LOW_SPEED 9
#define USB_HUB_C_PORT_CONNECT 16
@ -59,6 +68,17 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#define USB_HUB_C_PORT_RESET 20
#define USB_HUB_PORT_TEST 21
#define USB_HUB_PORT_INDICATOR 22
#define USB_HUB_C_PORT_LINK_STATE 25
#define USB_HUB_PORT_REMOTE_WAKE_MASK 27
#define USB_HUB_BH_PORT_RESET 28
#define USB_HUB_C_BH_PORT_RESET 29
//
// Constant value for Port Status & Port Change Status of SuperSpeed port
//
#define USB_SS_PORT_STAT_C_BH_RESET 0x0020
#define USB_SS_PORT_STAT_C_PORT_LINK_STATE 0x0040
//
// USB hub power control method. In gang power control
//
@ -94,6 +114,19 @@ typedef struct {
UINT8 HubContrCurrent;
UINT8 Filler[16];
} EFI_USB_HUB_DESCRIPTOR;
typedef struct {
UINT8 Length;
UINT8 DescType;
UINT8 NumPorts;
UINT16 HubCharacter;
UINT8 PwrOn2PwrGood;
UINT8 HubContrCurrent;
UINT8 HubHdrDecLat;
UINT8 HubDelay;
UINT8 DeviceRemovable;
} EFI_USB_SUPER_SPEED_HUB_DESCRIPTOR;
#pragma pack()

View File

@ -190,6 +190,7 @@
MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupportDxe.inf
MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf
MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf
MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf
MdeModulePkg/Bus/Pci/UhciPei/UhciPei.inf