-/** @file
- Header file for ATA/ATAPI PASS THRU driver.
-
- Copyright (c) 2010 - 2012, 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 __ATA_ATAPI_PASS_THRU_H__
-#define __ATA_ATAPI_PASS_THRU_H__
-
-#include <Uefi.h>
-
-#include <IndustryStandard/Pci.h>
-#include <IndustryStandard/Atapi.h>
-#include <IndustryStandard/Scsi.h>
-
-#include <Protocol/PciIo.h>
-#include <Protocol/IdeControllerInit.h>
-#include <Protocol/AtaPassThru.h>
-#include <Protocol/ScsiPassThruExt.h>
-
-#include <Library/DebugLib.h>
-#include <Library/BaseLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/UefiDriverEntryPoint.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/UefiLib.h>
-#include <Library/PciLib.h>
-#include <Library/PcdLib.h>
-#include <Library/TimerLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/ReportStatusCodeLib.h>
-#include <Library/DevicePathLib.h>
-
-#include "IdeMode.h"
-#include "AhciMode.h"
-
-extern EFI_DRIVER_BINDING_PROTOCOL gAtaAtapiPassThruDriverBinding;
-extern EFI_COMPONENT_NAME_PROTOCOL gAtaAtapiPassThruComponentName;
-extern EFI_COMPONENT_NAME2_PROTOCOL gAtaAtapiPassThruComponentName2;
-
-#define ATA_ATAPI_PASS_THRU_SIGNATURE SIGNATURE_32 ('a', 'a', 'p', 't')
-#define ATA_ATAPI_DEVICE_SIGNATURE SIGNATURE_32 ('a', 'd', 'e', 'v')
-#define ATA_NONBLOCKING_TASK_SIGNATURE SIGNATURE_32 ('a', 't', 's', 'k')
-
-typedef struct _ATA_NONBLOCK_TASK ATA_NONBLOCK_TASK;
-
-typedef enum {
- EfiAtaIdeMode,
- EfiAtaAhciMode,
- EfiAtaRaidMode,
- EfiAtaUnknownMode
-} EFI_ATA_HC_WORK_MODE;
-
-typedef enum {
- EfiIdeCdrom, /* ATAPI CDROM */
- EfiIdeHarddisk, /* Hard Disk */
- EfiPortMultiplier, /* Port Multiplier */
- EfiIdeUnknown
-} EFI_ATA_DEVICE_TYPE;
-
-//
-// Ahci mode device info
-//
-typedef struct {
- UINT32 Signature;
- LIST_ENTRY Link;
-
- UINT16 Port;
- UINT16 PortMultiplier;
- EFI_ATA_DEVICE_TYPE Type;
-
- EFI_IDENTIFY_DATA *IdentifyData;
-} EFI_ATA_DEVICE_INFO;
-
-typedef struct {
- UINT32 Signature;
-
- EFI_HANDLE ControllerHandle;
- EFI_PCI_IO_PROTOCOL *PciIo;
- EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeControllerInit;
-
- EFI_ATA_PASS_THRU_MODE AtaPassThruMode;
- EFI_ATA_PASS_THRU_PROTOCOL AtaPassThru;
- EFI_EXT_SCSI_PASS_THRU_MODE ExtScsiPassThruMode;
- EFI_EXT_SCSI_PASS_THRU_PROTOCOL ExtScsiPassThru;
-
- EFI_ATA_HC_WORK_MODE Mode;
-
- EFI_IDE_REGISTERS IdeRegisters[EfiIdeMaxChannel];
- EFI_AHCI_REGISTERS AhciRegisters;
-
- //
- // The attached device list
- //
- LIST_ENTRY DeviceList;
- UINT64 OriginalPciAttributes;
-
- //
- // For AtaPassThru protocol, using the following bytes to record the previous call in
- // GetNextPort()/GetNextDevice().
- //
- UINT16 PreviousPort;
- UINT16 PreviousPortMultiplier;
- //
- // For ExtScsiPassThru protocol, using the following bytes to record the previous call in
- // GetNextTarget()/GetNextTargetLun().
- //
- UINT16 PreviousTargetId;
- UINT64 PreviousLun;
-
- //
- // For Non-blocking.
- //
- EFI_EVENT TimerEvent;
- LIST_ENTRY NonBlockingTaskList;
-} ATA_ATAPI_PASS_THRU_INSTANCE;
-
-//
-// Task for Non-blocking mode.
-//
-struct _ATA_NONBLOCK_TASK {
- UINT32 Signature;
- LIST_ENTRY Link;
-
- UINT16 Port;
- UINT16 PortMultiplier;
- EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet;
- BOOLEAN IsStart;
- EFI_EVENT Event;
- UINT64 RetryTimes;
- VOID *Map; // Pointer to map.
- VOID *TableMap;// Pointer to PRD table map.
- EFI_ATA_DMA_PRD *MapBaseAddress; // Pointer to range Base address for Map.
- UINTN PageCount; // The page numbers used by PCIO freebuffer.
-};
-
-//
-// Timeout value which uses 100ns as a unit.
-// It means 3 second span.
-//
-#define ATA_ATAPI_TIMEOUT EFI_TIMER_PERIOD_SECONDS(3)
-
-#define IS_ALIGNED(addr, size) (((UINTN) (addr) & (size - 1)) == 0)
-
-#define ATA_PASS_THRU_PRIVATE_DATA_FROM_THIS(a) \
- CR (a, \
- ATA_ATAPI_PASS_THRU_INSTANCE, \
- AtaPassThru, \
- ATA_ATAPI_PASS_THRU_SIGNATURE \
- )
-
-#define EXT_SCSI_PASS_THRU_PRIVATE_DATA_FROM_THIS(a) \
- CR (a, \
- ATA_ATAPI_PASS_THRU_INSTANCE, \
- ExtScsiPassThru, \
- ATA_ATAPI_PASS_THRU_SIGNATURE \
- )
-
-#define ATA_ATAPI_DEVICE_INFO_FROM_THIS(a) \
- CR (a, \
- EFI_ATA_DEVICE_INFO, \
- Link, \
- ATA_ATAPI_DEVICE_SIGNATURE \
- );
-
-#define ATA_NON_BLOCK_TASK_FROM_ENTRY(a) \
- CR (a, \
- ATA_NONBLOCK_TASK, \
- Link, \
- ATA_NONBLOCKING_TASK_SIGNATURE \
- );
-
-/**
- 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
-AtaAtapiPassThruComponentNameGetDriverName (
- 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 NULL.
-
- @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
-AtaAtapiPassThruComponentNameGetControllerName (
- IN EFI_COMPONENT_NAME_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN EFI_HANDLE ChildHandle OPTIONAL,
- IN CHAR8 *Language,
- OUT CHAR16 **ControllerName
- );
-
-/**
- Tests to see if this driver supports a given controller. If a child device is provided,
- it further tests to see if this driver supports creating a handle for the specified child device.
-
- This function checks to see if the driver specified by This supports the device specified by
- ControllerHandle. Drivers will typically use the device path attached to
- ControllerHandle and/or the services from the bus I/O abstraction attached to
- ControllerHandle to determine if the driver supports ControllerHandle. This function
- may be called many times during platform initialization. In order to reduce boot times, the tests
- performed by this function must be very small, and take as little time as possible to execute. This
- function must not change the state of any hardware devices, and this function must be aware that the
- device specified by ControllerHandle may already be managed by the same driver or a
- different driver. This function must match its calls to AllocatePages() with FreePages(),
- AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
- Because ControllerHandle may have been previously started by the same driver, if a protocol is
- already in the opened state, then it must not be closed with CloseProtocol(). This is required
- to guarantee the state of ControllerHandle is not modified by this function.
-
- @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
- @param[in] ControllerHandle The handle of the controller to test. This handle
- must support a protocol interface that supplies
- an I/O abstraction to the driver.
- @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
- parameter is ignored by device drivers, and is optional for bus
- drivers. For bus drivers, if this parameter is not NULL, then
- the bus driver must determine if the bus controller specified
- by ControllerHandle and the child controller specified
- by RemainingDevicePath are both supported by this
- bus driver.
-
- @retval EFI_SUCCESS The device specified by ControllerHandle and
- RemainingDevicePath is supported by the driver specified by This.
- @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
- RemainingDevicePath is already being managed by the driver
- specified by This.
- @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
- RemainingDevicePath is already being managed by a different
- driver or an application that requires exclusive access.
- Currently not implemented.
- @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
- RemainingDevicePath is not supported by the driver specified by This.
-**/
-EFI_STATUS
-EFIAPI
-AtaAtapiPassThruSupported (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE Controller,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
- );
-
-/**
- Starts a device controller or a bus controller.
-
- The Start() function is designed to be invoked from the EFI boot service ConnectController().
- As a result, much of the error checking on the parameters to Start() has been moved into this
- common boot service. It is legal to call Start() from other locations,
- but the following calling restrictions must be followed, or the system behavior will not be deterministic.
- 1. ControllerHandle must be a valid EFI_HANDLE.
- 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
- EFI_DEVICE_PATH_PROTOCOL.
- 3. Prior to calling Start(), the Supported() function for the driver specified by This must
- have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
-
- @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
- @param[in] ControllerHandle The handle of the controller to start. This handle
- must support a protocol interface that supplies
- an I/O abstraction to the driver.
- @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
- parameter is ignored by device drivers, and is optional for bus
- drivers. For a bus driver, if this parameter is NULL, then handles
- for all the children of Controller are created by this driver.
- If this parameter is not NULL and the first Device Path Node is
- not the End of Device Path Node, then only the handle for the
- child device specified by the first Device Path Node of
- RemainingDevicePath is created by this driver.
- If the first Device Path Node of RemainingDevicePath is
- the End of Device Path Node, no child handle is created by this
- driver.
-
- @retval EFI_SUCCESS The device was started.
- @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
- @retval Others The driver failded to start the device.
-
-**/
-EFI_STATUS
-EFIAPI
-AtaAtapiPassThruStart (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE Controller,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
- );
-
-/**
- Stops a device controller or a bus controller.
-
- The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
- As a result, much of the error checking on the parameters to Stop() has been moved
- into this common boot service. It is legal to call Stop() from other locations,
- but the following calling restrictions must be followed, or the system behavior will not be deterministic.
- 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
- same driver's Start() function.
- 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
- EFI_HANDLE. In addition, all of these handles must have been created in this driver's
- Start() function, and the Start() function must have called OpenProtocol() on
- ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
-
- @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
- @param[in] ControllerHandle A handle to the device being stopped. The handle must
- support a bus specific I/O protocol for the driver
- to use to stop the device.
- @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
- @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
- if NumberOfChildren is 0.
-
- @retval EFI_SUCCESS The device was stopped.
- @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
-
-**/
-EFI_STATUS
-EFIAPI
-AtaAtapiPassThruStop (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE Controller,
- IN UINTN NumberOfChildren,
- IN EFI_HANDLE *ChildHandleBuffer
- );
-
-/**
- Traverse the attached ATA devices list to find out the device to access.
-
- @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
- @param[in] Port The port number of the ATA device to send the command.
- @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.
- If there is no port multiplier, then specify 0.
- @param[in] DeviceType The device type of the ATA device.
-
- @retval The pointer to the data structure of the device info to access.
-
-**/
-LIST_ENTRY *
-EFIAPI
-SearchDeviceInfoList (
- IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,
- IN UINT16 Port,
- IN UINT16 PortMultiplier,
- IN EFI_ATA_DEVICE_TYPE DeviceType
- );
-
-/**
- Allocate device info data structure to contain device info.
- And insert the data structure to the tail of device list for tracing.
-
- @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
- @param[in] Port The port number of the ATA device to send the command.
- @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.
- If there is no port multiplier, then specify 0.
- @param[in] DeviceType The device type of the ATA device.
- @param[in] IdentifyData The data buffer to store the output of the IDENTIFY cmd.
-
- @retval EFI_SUCCESS Successfully insert the ata device to the tail of device list.
- @retval EFI_OUT_OF_RESOURCES Can not allocate enough resource for use.
-
-**/
-EFI_STATUS
-EFIAPI
-CreateNewDeviceInfo (
- IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,
- IN UINT16 Port,
- IN UINT16 PortMultiplier,
- IN EFI_ATA_DEVICE_TYPE DeviceType,
- IN EFI_IDENTIFY_DATA *IdentifyData
- );
-
-/**
- Destroy all attached ATA devices info.
-
- @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
-
-**/
-VOID
-EFIAPI
-DestroyDeviceInfoList (
- IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance
- );
-
-/**
- Destroy all pending non blocking tasks.
-
- @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
- @param[in] IsSigEvent Indicate whether signal the task event when remove the
- task.
-
-**/
-VOID
-EFIAPI
-DestroyAsynTaskList (
- IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,
- IN BOOLEAN IsSigEvent
- );
-
-/**
- Enumerate all attached ATA devices at IDE mode or AHCI mode separately.
-
- The function is designed to enumerate all attached ATA devices.
-
- @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
-
- @retval EFI_SUCCESS Successfully enumerate attached ATA devices.
- @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
-
-**/
-EFI_STATUS
-EFIAPI
-EnumerateAttachedDevice (
- IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance
- );
-
-/**
- Call back funtion when the timer event is signaled.
-
- @param[in] Event The Event this notify function registered to.
- @param[in] Context Pointer to the context data registered to the
- Event.
-
-**/
-VOID
-EFIAPI
-AsyncNonBlockingTransferRoutine (
- EFI_EVENT Event,
- VOID* Context
- );
-
-/**
- Sends an ATA command to an ATA device that is attached to the ATA controller. This function
- supports both blocking I/O and non-blocking I/O. The blocking I/O functionality is required,
- and the non-blocking I/O functionality is optional.
-
- @param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.
- @param[in] Port The port number of the ATA device to send the command.
- @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.
- If there is no port multiplier, then specify 0.
- @param[in, out] Packet A pointer to the ATA command to send to the ATA device specified by Port
- and PortMultiplierPort.
- @param[in] Event If non-blocking I/O is not supported then Event is ignored, and blocking
- I/O is performed. If Event is NULL, then blocking I/O is performed. If
- Event is not NULL and non blocking I/O is supported, then non-blocking
- I/O is performed, and Event will be signaled when the ATA command completes.
-
- @retval EFI_SUCCESS The ATA command was sent by the host. For bi-directional commands,
- InTransferLength bytes were transferred from InDataBuffer. For write and
- bi-directional commands, OutTransferLength bytes were transferred by OutDataBuffer.
- @retval EFI_BAD_BUFFER_SIZE The ATA command was not executed. The number of bytes that could be transferred
- is returned in InTransferLength. For write and bi-directional commands,
- OutTransferLength bytes were transferred by OutDataBuffer.
- @retval EFI_NOT_READY The ATA command could not be sent because there are too many ATA commands
- already queued. The caller may retry again later.
- @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the ATA command.
- @retval EFI_INVALID_PARAMETER Port, PortMultiplierPort, or the contents of Acb are invalid. The ATA
- command was not sent, so no additional status information is available.
-
-**/
-EFI_STATUS
-EFIAPI
-AtaPassThruPassThru (
- IN EFI_ATA_PASS_THRU_PROTOCOL *This,
- IN UINT16 Port,
- IN UINT16 PortMultiplierPort,
- IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet,
- IN EFI_EVENT Event OPTIONAL
- );
-
-/**
- Used to retrieve the list of legal port numbers for ATA devices on an ATA controller.
- These can either be the list of ports where ATA devices are actually present or the
- list of legal port numbers for the ATA controller. Regardless, the caller of this
- function must probe the port number returned to see if an ATA device is actually
- present at that location on the ATA controller.
-
- The GetNextPort() function retrieves the port number on an ATA controller. If on input
- Port is 0xFFFF, then the port number of the first port on the ATA controller is returned
- in Port and EFI_SUCCESS is returned.
-
- If Port is a port number that was returned on a previous call to GetNextPort(), then the
- port number of the next port on the ATA controller is returned in Port, and EFI_SUCCESS
- is returned. If Port is not 0xFFFF and Port was not returned on a previous call to
- GetNextPort(), then EFI_INVALID_PARAMETER is returned.
-
- If Port is the port number of the last port on the ATA controller, then EFI_NOT_FOUND is
- returned.
-
- @param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.
- @param[in, out] Port On input, a pointer to the port number on the ATA controller.
- On output, a pointer to the next port number on the ATA
- controller. An input value of 0xFFFF retrieves the first port
- number on the ATA controller.
-
- @retval EFI_SUCCESS The next port number on the ATA controller was returned in Port.
- @retval EFI_NOT_FOUND There are no more ports on this ATA controller.
- @retval EFI_INVALID_PARAMETER Port is not 0xFFFF and Port was not returned on a previous call
- to GetNextPort().
-
-**/
-EFI_STATUS
-EFIAPI
-AtaPassThruGetNextPort (
- IN EFI_ATA_PASS_THRU_PROTOCOL *This,
- IN OUT UINT16 *Port
- );
-
-/**
- Used to retrieve the list of legal port multiplier port numbers for ATA devices on a port of an ATA
- controller. These can either be the list of port multiplier ports where ATA devices are actually
- present on port or the list of legal port multiplier ports on that port. Regardless, the caller of this
- function must probe the port number and port multiplier port number returned to see if an ATA
- device is actually present.
-
- The GetNextDevice() function retrieves the port multiplier port number of an ATA device
- present on a port of an ATA controller.
-
- If PortMultiplierPort points to a port multiplier port number value that was returned on a
- previous call to GetNextDevice(), then the port multiplier port number of the next ATA device
- on the port of the ATA controller is returned in PortMultiplierPort, and EFI_SUCCESS is
- returned.
-
- If PortMultiplierPort points to 0xFFFF, then the port multiplier port number of the first
- ATA device on port of the ATA controller is returned in PortMultiplierPort and
- EFI_SUCCESS is returned.
-
- If PortMultiplierPort is not 0xFFFF and the value pointed to by PortMultiplierPort
- was not returned on a previous call to GetNextDevice(), then EFI_INVALID_PARAMETER
- is returned.
-
- If PortMultiplierPort is the port multiplier port number of the last ATA device on the port of
- the ATA controller, then EFI_NOT_FOUND is returned.
-
- @param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.
- @param[in] Port The port number present on the ATA controller.
- @param[in, out] PortMultiplierPort On input, a pointer to the port multiplier port number of an
- ATA device present on the ATA controller.
- If on input a PortMultiplierPort of 0xFFFF is specified,
- then the port multiplier port number of the first ATA device
- is returned. On output, a pointer to the port multiplier port
- number of the next ATA device present on an ATA controller.
-
- @retval EFI_SUCCESS The port multiplier port number of the next ATA device on the port
- of the ATA controller was returned in PortMultiplierPort.
- @retval EFI_NOT_FOUND There are no more ATA devices on this port of the ATA controller.
- @retval EFI_INVALID_PARAMETER PortMultiplierPort is not 0xFFFF, and PortMultiplierPort was not
- returned on a previous call to GetNextDevice().
-
-**/
-EFI_STATUS
-EFIAPI
-AtaPassThruGetNextDevice (
- IN EFI_ATA_PASS_THRU_PROTOCOL *This,
- IN UINT16 Port,
- IN OUT UINT16 *PortMultiplierPort
- );
-
-/**
- Used to allocate and build a device path node for an ATA device on an ATA controller.
-
- The BuildDevicePath() function allocates and builds a single device node for the ATA
- device specified by Port and PortMultiplierPort. If the ATA device specified by Port and
- PortMultiplierPort is not present on the ATA controller, then EFI_NOT_FOUND is returned.
- If DevicePath is NULL, then EFI_INVALID_PARAMETER is returned. If there are not enough
- resources to allocate the device path node, then EFI_OUT_OF_RESOURCES is returned.
-
- Otherwise, DevicePath is allocated with the boot service AllocatePool(), the contents of
- DevicePath are initialized to describe the ATA device specified by Port and PortMultiplierPort,
- and EFI_SUCCESS is returned.
-
- @param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.
- @param[in] Port Port specifies the port number of the ATA device for which a
- device path node is to be allocated and built.
- @param[in] PortMultiplierPort The port multiplier port number of the ATA device for which a
- device path node is to be allocated and built. If there is no
- port multiplier, then specify 0.
- @param[in, out] DevicePath A pointer to a single device path node that describes the ATA
- device specified by Port and PortMultiplierPort. This function
- is responsible for allocating the buffer DevicePath with the
- boot service AllocatePool(). It is the caller's responsibility
- to free DevicePath when the caller is finished with DevicePath.
- @retval EFI_SUCCESS The device path node that describes the ATA device specified by
- Port and PortMultiplierPort was allocated and returned in DevicePath.
- @retval EFI_NOT_FOUND The ATA device specified by Port and PortMultiplierPort does not
- exist on the ATA controller.
- @retval EFI_INVALID_PARAMETER DevicePath is NULL.
- @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate DevicePath.
-
-**/
-EFI_STATUS
-EFIAPI
-AtaPassThruBuildDevicePath (
- IN EFI_ATA_PASS_THRU_PROTOCOL *This,
- IN UINT16 Port,
- IN UINT16 PortMultiplierPort,
- IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
- );
-
-/**
- Used to translate a device path node to a port number and port multiplier port number.
-
- The GetDevice() function determines the port and port multiplier port number associated with
- the ATA device described by DevicePath. If DevicePath is a device path node type that the
- ATA Pass Thru driver supports, then the ATA Pass Thru driver will attempt to translate the contents
- DevicePath into a port number and port multiplier port number.
-
- If this translation is successful, then that port number and port multiplier port number are returned
- in Port and PortMultiplierPort, and EFI_SUCCESS is returned.
-
- If DevicePath, Port, or PortMultiplierPort are NULL, then EFI_INVALID_PARAMETER is returned.
-
- If DevicePath is not a device path node type that the ATA Pass Thru driver supports, then
- EFI_UNSUPPORTED is returned.
-
- If DevicePath is a device path node type that the ATA Pass Thru driver supports, but there is not
- a valid translation from DevicePath to a port number and port multiplier port number, then
- EFI_NOT_FOUND is returned.
-
- @param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.
- @param[in] DevicePath A pointer to the device path node that describes an ATA device on the
- ATA controller.
- @param[out] Port On return, points to the port number of an ATA device on the ATA controller.
- @param[out] PortMultiplierPort On return, points to the port multiplier port number of an ATA device
- on the ATA controller.
-
- @retval EFI_SUCCESS DevicePath was successfully translated to a port number and port multiplier
- port number, and they were returned in Port and PortMultiplierPort.
- @retval EFI_INVALID_PARAMETER DevicePath is NULL.
- @retval EFI_INVALID_PARAMETER Port is NULL.
- @retval EFI_INVALID_PARAMETER PortMultiplierPort is NULL.
- @retval EFI_UNSUPPORTED This driver does not support the device path node type in DevicePath.
- @retval EFI_NOT_FOUND A valid translation from DevicePath to a port number and port multiplier
- port number does not exist.
-
-**/
-EFI_STATUS
-EFIAPI
-AtaPassThruGetDevice (
- IN EFI_ATA_PASS_THRU_PROTOCOL *This,
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
- OUT UINT16 *Port,
- OUT UINT16 *PortMultiplierPort
- );
-
-/**
- Resets a specific port on the ATA controller. This operation also resets all the ATA devices
- connected to the port.
-
- The ResetChannel() function resets an a specific port on an ATA controller. This operation
- resets all the ATA devices connected to that port. If this ATA controller does not support
- a reset port operation, then EFI_UNSUPPORTED is returned.
-
- If a device error occurs while executing that port reset operation, then EFI_DEVICE_ERROR is
- returned.
-
- If a timeout occurs during the execution of the port reset operation, then EFI_TIMEOUT is returned.
-
- If the port reset operation is completed, then EFI_SUCCESS is returned.
-
- @param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.
- @param[in] Port The port number on the ATA controller.
-
- @retval EFI_SUCCESS The ATA controller port was reset.
- @retval EFI_UNSUPPORTED The ATA controller does not support a port reset operation.
- @retval EFI_DEVICE_ERROR A device error occurred while attempting to reset the ATA port.
- @retval EFI_TIMEOUT A timeout occurred while attempting to reset the ATA port.
-
-**/
-EFI_STATUS
-EFIAPI
-AtaPassThruResetPort (
- IN EFI_ATA_PASS_THRU_PROTOCOL *This,
- IN UINT16 Port
- );
-
-/**
- Resets an ATA device that is connected to an ATA controller.
-
- The ResetDevice() function resets the ATA device specified by Port and PortMultiplierPort.
- If this ATA controller does not support a device reset operation, then EFI_UNSUPPORTED is
- returned.
-
- If Port or PortMultiplierPort are not in a valid range for this ATA controller, then
- EFI_INVALID_PARAMETER is returned.
-
- If a device error occurs while executing that device reset operation, then EFI_DEVICE_ERROR
- is returned.
-
- If a timeout occurs during the execution of the device reset operation, then EFI_TIMEOUT is
- returned.
-
- If the device reset operation is completed, then EFI_SUCCESS is returned.
-
- @param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.
- @param[in] Port Port represents the port number of the ATA device to be reset.
- @param[in] PortMultiplierPort The port multiplier port number of the ATA device to reset.
- If there is no port multiplier, then specify 0.
- @retval EFI_SUCCESS The ATA device specified by Port and PortMultiplierPort was reset.
- @retval EFI_UNSUPPORTED The ATA controller does not support a device reset operation.
- @retval EFI_INVALID_PARAMETER Port or PortMultiplierPort are invalid.
- @retval EFI_DEVICE_ERROR A device error occurred while attempting to reset the ATA device
- specified by Port and PortMultiplierPort.
- @retval EFI_TIMEOUT A timeout occurred while attempting to reset the ATA device
- specified by Port and PortMultiplierPort.
-
-**/
-EFI_STATUS
-EFIAPI
-AtaPassThruResetDevice (
- IN EFI_ATA_PASS_THRU_PROTOCOL *This,
- IN UINT16 Port,
- IN UINT16 PortMultiplierPort
- );
-
-/**
- Sends a SCSI Request Packet to a SCSI device that is attached to the SCSI channel. This function
- supports both blocking I/O and nonblocking I/O. The blocking I/O functionality is required, and the
- nonblocking I/O functionality is optional.
-
- @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
- @param Target The Target is an array of size TARGET_MAX_BYTES and it represents
- the id of the SCSI device to send the SCSI Request Packet. Each
- transport driver may choose to utilize a subset of this size to suit the needs
- of transport target representation. For example, a Fibre Channel driver
- may use only 8 bytes (WWN) to represent an FC target.
- @param Lun The LUN of the SCSI device to send the SCSI Request Packet.
- @param Packet A pointer to the SCSI Request Packet to send to the SCSI device
- specified by Target and Lun.
- @param Event If nonblocking I/O is not supported then Event is ignored, and blocking
- I/O is performed. If Event is NULL, then blocking I/O is performed. If
- Event is not NULL and non blocking I/O is supported, then
- nonblocking I/O is performed, and Event will be signaled when the
- SCSI Request Packet completes.
-
- @retval EFI_SUCCESS The SCSI Request Packet was sent by the host. For bi-directional
- commands, InTransferLength bytes were transferred from
- InDataBuffer. For write and bi-directional commands,
- OutTransferLength bytes were transferred by
- OutDataBuffer.
- @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was not executed. The number of bytes that
- could be transferred is returned in InTransferLength. For write
- and bi-directional commands, OutTransferLength bytes were
- transferred by OutDataBuffer.
- @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
- SCSI Request Packets already queued. The caller may retry again later.
- @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the SCSI Request
- Packet.
- @retval EFI_INVALID_PARAMETER Target, Lun, or the contents of ScsiRequestPacket are invalid.
- @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported
- by the host adapter. This includes the case of Bi-directional SCSI
- commands not supported by the implementation. The SCSI Request
- Packet was not sent, so no additional status information is available.
- @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
-
-**/
-EFI_STATUS
-EFIAPI
-ExtScsiPassThruPassThru (
- IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
- IN UINT8 *Target,
- IN UINT64 Lun,
- IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
- IN EFI_EVENT Event OPTIONAL
- );
-
-/**
- Used to retrieve the list of legal Target IDs and LUNs for SCSI devices on a SCSI channel. These
- can either be the list SCSI devices that are actually present on the SCSI channel, or the list of legal
- Target Ids and LUNs for the SCSI channel. Regardless, the caller of this function must probe the
- Target ID and LUN returned to see if a SCSI device is actually present at that location on the SCSI
- channel.
-
- @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
- @param Target On input, a pointer to the Target ID (an array of size
- TARGET_MAX_BYTES) of a SCSI device present on the SCSI channel.
- On output, a pointer to the Target ID (an array of
- TARGET_MAX_BYTES) of the next SCSI device present on a SCSI
- channel. An input value of 0xF(all bytes in the array are 0xF) in the
- Target array retrieves the Target ID of the first SCSI device present on a
- SCSI channel.
- @param Lun On input, a pointer to the LUN of a SCSI device present on the SCSI
- channel. On output, a pointer to the LUN of the next SCSI device present
- on a SCSI channel.
-
- @retval EFI_SUCCESS The Target ID and LUN of the next SCSI device on the SCSI
- channel was returned in Target and Lun.
- @retval EFI_INVALID_PARAMETER Target array is not all 0xF, and Target and Lun were
- not returned on a previous call to GetNextTargetLun().
- @retval EFI_NOT_FOUND There are no more SCSI devices on this SCSI channel.
-
-**/
-EFI_STATUS
-EFIAPI
-ExtScsiPassThruGetNextTargetLun (
- IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
- IN OUT UINT8 **Target,
- IN OUT UINT64 *Lun
- );
-
-/**
- Used to allocate and build a device path node for a SCSI device on a SCSI channel.
-
- @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
- @param Target The Target is an array of size TARGET_MAX_BYTES and it specifies the
- Target ID of the SCSI device for which a device path node is to be
- allocated and built. Transport drivers may chose to utilize a subset of
- this size to suit the representation of targets. For example, a Fibre
- Channel driver may use only 8 bytes (WWN) in the array to represent a
- FC target.
- @param Lun The LUN of the SCSI device for which a device path node is to be
- allocated and built.
- @param DevicePath A pointer to a single device path node that describes the SCSI device
- specified by Target and Lun. This function is responsible for
- allocating the buffer DevicePath with the boot service
- AllocatePool(). It is the caller's responsibility to free
- DevicePath when the caller is finished with DevicePath.
-
- @retval EFI_SUCCESS The device path node that describes the SCSI device specified by
- Target and Lun was allocated and returned in
- DevicePath.
- @retval EFI_INVALID_PARAMETER DevicePath is NULL.
- @retval EFI_NOT_FOUND The SCSI devices specified by Target and Lun does not exist
- on the SCSI channel.
- @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate DevicePath.
-
-**/
-EFI_STATUS
-EFIAPI
-ExtScsiPassThruBuildDevicePath (
- IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
- IN UINT8 *Target,
- IN UINT64 Lun,
- IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
- );
-
-/**
- Used to translate a device path node to a Target ID and LUN.
-
- @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
- @param DevicePath A pointer to a single device path node that describes the SCSI device
- on the SCSI channel.
- @param Target A pointer to the Target Array which represents the ID of a SCSI device
- on the SCSI channel.
- @param Lun A pointer to the LUN of a SCSI device on the SCSI channel.
-
- @retval EFI_SUCCESS DevicePath was successfully translated to a Target ID and
- LUN, and they were returned in Target and Lun.
- @retval EFI_INVALID_PARAMETER DevicePath or Target or Lun is NULL.
- @retval EFI_NOT_FOUND A valid translation from DevicePath to a Target ID and LUN
- does not exist.
- @retval EFI_UNSUPPORTED This driver does not support the device path node type in
- DevicePath.
-
-**/
-EFI_STATUS
-EFIAPI
-ExtScsiPassThruGetTargetLun (
- IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
- OUT UINT8 **Target,
- OUT UINT64 *Lun
- );
-
-/**
- Resets a SCSI channel. This operation resets all the SCSI devices connected to the SCSI channel.
-
- @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
-
- @retval EFI_SUCCESS The SCSI channel was reset.
- @retval EFI_DEVICE_ERROR A device error occurred while attempting to reset the SCSI channel.
- @retval EFI_TIMEOUT A timeout occurred while attempting to reset the SCSI channel.
- @retval EFI_UNSUPPORTED The SCSI channel does not support a channel reset operation.
-
-**/
-EFI_STATUS
-EFIAPI
-ExtScsiPassThruResetChannel (
- IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This
- );
-
-/**
- Resets a SCSI logical unit that is connected to a SCSI channel.
-
- @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
- @param Target The Target is an array of size TARGET_MAX_BYTE and it represents the
- target port ID of the SCSI device containing the SCSI logical unit to
- reset. Transport drivers may chose to utilize a subset of this array to suit
- the representation of their targets.
- @param Lun The LUN of the SCSI device to reset.
-
- @retval EFI_SUCCESS The SCSI device specified by Target and Lun was reset.
- @retval EFI_INVALID_PARAMETER Target or Lun is NULL.
- @retval EFI_TIMEOUT A timeout occurred while attempting to reset the SCSI device
- specified by Target and Lun.
- @retval EFI_UNSUPPORTED The SCSI channel does not support a target reset operation.
- @retval EFI_DEVICE_ERROR A device error occurred while attempting to reset the SCSI device
- specified by Target and Lun.
-
-**/
-EFI_STATUS
-EFIAPI
-ExtScsiPassThruResetTargetLun (
- IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
- IN UINT8 *Target,
- IN UINT64 Lun
- );
-
-/**
- Used to retrieve the list of legal Target IDs for SCSI devices on a SCSI channel. These can either
- be the list SCSI devices that are actually present on the SCSI channel, or the list of legal Target IDs
- for the SCSI channel. Regardless, the caller of this function must probe the Target ID returned to
- see if a SCSI device is actually present at that location on the SCSI channel.
-
- @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
- @param Target (TARGET_MAX_BYTES) of a SCSI device present on the SCSI channel.
- On output, a pointer to the Target ID (an array of
- TARGET_MAX_BYTES) of the next SCSI device present on a SCSI
- channel. An input value of 0xF(all bytes in the array are 0xF) in the
- Target array retrieves the Target ID of the first SCSI device present on a
- SCSI channel.
-
- @retval EFI_SUCCESS The Target ID of the next SCSI device on the SCSI
- channel was returned in Target.
- @retval EFI_INVALID_PARAMETER Target or Lun is NULL.
- @retval EFI_TIMEOUT Target array is not all 0xF, and Target was not
- returned on a previous call to GetNextTarget().
- @retval EFI_NOT_FOUND There are no more SCSI devices on this SCSI channel.
-
-**/
-EFI_STATUS
-EFIAPI
-ExtScsiPassThruGetNextTarget (
- IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
- IN OUT UINT8 **Target
- );
-
-/**
- Initialize ATA host controller at IDE mode.
-
- The function is designed to initialize ATA host controller.
-
- @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
-
-**/
-EFI_STATUS
-EFIAPI
-IdeModeInitialization (
- IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance
- );
-
-/**
- Initialize ATA host controller at AHCI mode.
-
- The function is designed to initialize ATA host controller.
-
- @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
-
-**/
-EFI_STATUS
-EFIAPI
-AhciModeInitialization (
- IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance
- );
-
-/**
- Start a non data transfer on specific port.
-
- @param[in] PciIo The PCI IO protocol instance.
- @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
- @param[in] Port The number of port.
- @param[in] PortMultiplier The timeout value of stop.
- @param[in] AtapiCommand The atapi command will be used for the
- transfer.
- @param[in] AtapiCommandLength The length of the atapi command.
- @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
- @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
- @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
- @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
- used by non-blocking mode.
-
- @retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.
- @retval EFI_TIMEOUT The operation is time out.
- @retval EFI_UNSUPPORTED The device is not ready for transfer.
- @retval EFI_SUCCESS The non data transfer executes successfully.
-
-**/
-EFI_STATUS
-EFIAPI
-AhciNonDataTransfer (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN EFI_AHCI_REGISTERS *AhciRegisters,
- IN UINT8 Port,
- IN UINT8 PortMultiplier,
- IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,
- IN UINT8 AtapiCommandLength,
- IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
- IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
- IN UINT64 Timeout,
- IN ATA_NONBLOCK_TASK *Task
- );
-
-/**
- Start a DMA data transfer on specific port
-
- @param[in] Instance The ATA_ATAPI_PASS_THRU_INSTANCE protocol instance.
- @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
- @param[in] Port The number of port.
- @param[in] PortMultiplier The timeout value of stop.
- @param[in] AtapiCommand The atapi command will be used for the
- transfer.
- @param[in] AtapiCommandLength The length of the atapi command.
- @param[in] Read The transfer direction.
- @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
- @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
- @param[in, out] MemoryAddr The pointer to the data buffer.
- @param[in] DataCount The data count to be transferred.
- @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
- @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
- used by non-blocking mode.
-
- @retval EFI_DEVICE_ERROR The DMA data transfer abort with error occurs.
- @retval EFI_TIMEOUT The operation is time out.
- @retval EFI_UNSUPPORTED The device is not ready for transfer.
- @retval EFI_SUCCESS The DMA data transfer executes successfully.
-
-**/
-EFI_STATUS
-EFIAPI
-AhciDmaTransfer (
- IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,
- IN EFI_AHCI_REGISTERS *AhciRegisters,
- IN UINT8 Port,
- IN UINT8 PortMultiplier,
- IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,
- IN UINT8 AtapiCommandLength,
- IN BOOLEAN Read,
- IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
- IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
- IN OUT VOID *MemoryAddr,
- IN UINT32 DataCount,
- IN UINT64 Timeout,
- IN ATA_NONBLOCK_TASK *Task
- );
-
-/**
- Start a PIO data transfer on specific port.
-
- @param[in] PciIo The PCI IO protocol instance.
- @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
- @param[in] Port The number of port.
- @param[in] PortMultiplier The timeout value of stop.
- @param[in] AtapiCommand The atapi command will be used for the
- transfer.
- @param[in] AtapiCommandLength The length of the atapi command.
- @param[in] Read The transfer direction.
- @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
- @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
- @param[in, out] MemoryAddr The pointer to the data buffer.
- @param[in] DataCount The data count to be transferred.
- @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
- @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
- used by non-blocking mode.
-
- @retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs.
- @retval EFI_TIMEOUT The operation is time out.
- @retval EFI_UNSUPPORTED The device is not ready for transfer.
- @retval EFI_SUCCESS The PIO data transfer executes successfully.
-
-**/
-EFI_STATUS
-EFIAPI
-AhciPioTransfer (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN EFI_AHCI_REGISTERS *AhciRegisters,
- IN UINT8 Port,
- IN UINT8 PortMultiplier,
- IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,
- IN UINT8 AtapiCommandLength,
- IN BOOLEAN Read,
- IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
- IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
- IN OUT VOID *MemoryAddr,
- IN UINT32 DataCount,
- IN UINT64 Timeout,
- IN ATA_NONBLOCK_TASK *Task
- );
-
-/**
- Send ATA command into device with NON_DATA protocol
-
- @param[in] PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE
- data structure.
- @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.
- @param[in] AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data
- structure.
- @param[in, out] AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
- @param[in] Timeout The time to complete the command, uses 100ns as a unit.
- @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
- used by non-blocking mode.
-
- @retval EFI_SUCCESS Reading succeed
- @retval EFI_ABORTED Command failed
- @retval EFI_DEVICE_ERROR Device status error.
-
-**/
-EFI_STATUS
-EFIAPI
-AtaNonDataCommandIn (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN EFI_IDE_REGISTERS *IdeRegisters,
- IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
- IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
- IN UINT64 Timeout,
- IN ATA_NONBLOCK_TASK *Task
- );
-
-/**
- Perform an ATA Udma operation (Read, ReadExt, Write, WriteExt).
-
- @param[in] Instance A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data
- structure.
- @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.
- @param[in] Read Flag used to determine the data transfer
- direction. Read equals 1, means data transferred
- from device to host;Read equals 0, means data
- transferred from host to device.
- @param[in] DataBuffer A pointer to the source buffer for the data.
- @param[in] DataLength The length of the data.
- @param[in] AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.
- @param[in, out] AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
- @param[in] Timeout The time to complete the command, uses 100ns as a unit.
- @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
- used by non-blocking mode.
-
- @retval EFI_SUCCESS the operation is successful.
- @retval EFI_OUT_OF_RESOURCES Build PRD table failed
- @retval EFI_UNSUPPORTED Unknown channel or operations command
- @retval EFI_DEVICE_ERROR Ata command execute failed
-
-**/
-EFI_STATUS
-EFIAPI
-AtaUdmaInOut (
- IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,
- IN EFI_IDE_REGISTERS *IdeRegisters,
- IN BOOLEAN Read,
- IN VOID *DataBuffer,
- IN UINT64 DataLength,
- IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
- IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
- IN UINT64 Timeout,
- IN ATA_NONBLOCK_TASK *Task
- );
-
-/**
- This function is used to send out ATA commands conforms to the PIO Data In Protocol.
-
- @param[in] PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data
- structure.
- @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.
- @param[in, out] Buffer A pointer to the source buffer for the data.
- @param[in] ByteCount The length of the data.
- @param[in] Read Flag used to determine the data transfer direction.
- Read equals 1, means data transferred from device
- to host;Read equals 0, means data transferred
- from host to device.
- @param[in] AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.
- @param[in, out] AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
- @param[in] Timeout The time to complete the command, uses 100ns as a unit.
- @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
- used by non-blocking mode.
-
- @retval EFI_SUCCESS send out the ATA command and device send required data successfully.
- @retval EFI_DEVICE_ERROR command sent failed.
-
-**/
-EFI_STATUS
-EFIAPI
-AtaPioDataInOut (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN EFI_IDE_REGISTERS *IdeRegisters,
- IN OUT VOID *Buffer,
- IN UINT64 ByteCount,
- IN BOOLEAN Read,
- IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
- IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
- IN UINT64 Timeout,
- IN ATA_NONBLOCK_TASK *Task
- );
-
-#endif
-
+/** @file\r
+ Header file for ATA/ATAPI PASS THRU driver.\r
+\r
+ Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#ifndef __ATA_ATAPI_PASS_THRU_H__\r
+#define __ATA_ATAPI_PASS_THRU_H__\r
+\r
+#include <Uefi.h>\r
+\r
+#include <IndustryStandard/Pci.h>\r
+#include <IndustryStandard/Atapi.h>\r
+#include <IndustryStandard/Scsi.h>\r
+\r
+#include <Protocol/PciIo.h>\r
+#include <Protocol/IdeControllerInit.h>\r
+#include <Protocol/AtaPassThru.h>\r
+#include <Protocol/ScsiPassThruExt.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/PciLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/ReportStatusCodeLib.h>\r
+#include <Library/DevicePathLib.h>\r
+\r
+#include "IdeMode.h"\r
+#include "AhciMode.h"\r
+\r
+extern EFI_DRIVER_BINDING_PROTOCOL gAtaAtapiPassThruDriverBinding;\r
+extern EFI_COMPONENT_NAME_PROTOCOL gAtaAtapiPassThruComponentName;\r
+extern EFI_COMPONENT_NAME2_PROTOCOL gAtaAtapiPassThruComponentName2;\r
+\r
+#define ATA_ATAPI_PASS_THRU_SIGNATURE SIGNATURE_32 ('a', 'a', 'p', 't')\r
+#define ATA_ATAPI_DEVICE_SIGNATURE SIGNATURE_32 ('a', 'd', 'e', 'v')\r
+#define ATA_NONBLOCKING_TASK_SIGNATURE SIGNATURE_32 ('a', 't', 's', 'k')\r
+\r
+typedef struct _ATA_NONBLOCK_TASK ATA_NONBLOCK_TASK;\r
+\r
+typedef enum {\r
+ EfiAtaIdeMode,\r
+ EfiAtaAhciMode,\r
+ EfiAtaRaidMode,\r
+ EfiAtaUnknownMode\r
+} EFI_ATA_HC_WORK_MODE;\r
+\r
+typedef enum {\r
+ EfiIdeCdrom, /* ATAPI CDROM */\r
+ EfiIdeHarddisk, /* Hard Disk */\r
+ EfiPortMultiplier, /* Port Multiplier */\r
+ EfiIdeUnknown\r
+} EFI_ATA_DEVICE_TYPE;\r
+\r
+//\r
+// Ahci mode device info\r
+//\r
+typedef struct {\r
+ UINT32 Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ UINT16 Port;\r
+ UINT16 PortMultiplier;\r
+ EFI_ATA_DEVICE_TYPE Type;\r
+\r
+ EFI_IDENTIFY_DATA *IdentifyData;\r
+} EFI_ATA_DEVICE_INFO;\r
+\r
+typedef struct {\r
+ UINT32 Signature;\r
+\r
+ EFI_HANDLE ControllerHandle;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeControllerInit;\r
+\r
+ EFI_ATA_PASS_THRU_MODE AtaPassThruMode;\r
+ EFI_ATA_PASS_THRU_PROTOCOL AtaPassThru;\r
+ EFI_EXT_SCSI_PASS_THRU_MODE ExtScsiPassThruMode;\r
+ EFI_EXT_SCSI_PASS_THRU_PROTOCOL ExtScsiPassThru;\r
+\r
+ EFI_ATA_HC_WORK_MODE Mode;\r
+\r
+ EFI_IDE_REGISTERS IdeRegisters[EfiIdeMaxChannel];\r
+ EFI_AHCI_REGISTERS AhciRegisters;\r
+\r
+ //\r
+ // The attached device list\r
+ //\r
+ LIST_ENTRY DeviceList;\r
+ UINT64 OriginalPciAttributes;\r
+\r
+ //\r
+ // For AtaPassThru protocol, using the following bytes to record the previous call in\r
+ // GetNextPort()/GetNextDevice().\r
+ //\r
+ UINT16 PreviousPort;\r
+ UINT16 PreviousPortMultiplier;\r
+ //\r
+ // For ExtScsiPassThru protocol, using the following bytes to record the previous call in\r
+ // GetNextTarget()/GetNextTargetLun().\r
+ //\r
+ UINT16 PreviousTargetId;\r
+ UINT64 PreviousLun;\r
+\r
+ //\r
+ // For Non-blocking.\r
+ //\r
+ EFI_EVENT TimerEvent;\r
+ LIST_ENTRY NonBlockingTaskList;\r
+} ATA_ATAPI_PASS_THRU_INSTANCE;\r
+\r
+//\r
+// Task for Non-blocking mode.\r
+//\r
+struct _ATA_NONBLOCK_TASK {\r
+ UINT32 Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ UINT16 Port;\r
+ UINT16 PortMultiplier;\r
+ EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet;\r
+ BOOLEAN IsStart;\r
+ EFI_EVENT Event;\r
+ UINT64 RetryTimes;\r
+ VOID *Map; // Pointer to map.\r
+ VOID *TableMap;// Pointer to PRD table map.\r
+ EFI_ATA_DMA_PRD *MapBaseAddress; // Pointer to range Base address for Map.\r
+ UINTN PageCount; // The page numbers used by PCIO freebuffer.\r
+};\r
+\r
+//\r
+// Timeout value which uses 100ns as a unit.\r
+// It means 3 second span.\r
+//\r
+#define ATA_ATAPI_TIMEOUT EFI_TIMER_PERIOD_SECONDS(3)\r
+\r
+#define IS_ALIGNED(addr, size) (((UINTN) (addr) & (size - 1)) == 0)\r
+\r
+#define ATA_PASS_THRU_PRIVATE_DATA_FROM_THIS(a) \\r
+ CR (a, \\r
+ ATA_ATAPI_PASS_THRU_INSTANCE, \\r
+ AtaPassThru, \\r
+ ATA_ATAPI_PASS_THRU_SIGNATURE \\r
+ )\r
+\r
+#define EXT_SCSI_PASS_THRU_PRIVATE_DATA_FROM_THIS(a) \\r
+ CR (a, \\r
+ ATA_ATAPI_PASS_THRU_INSTANCE, \\r
+ ExtScsiPassThru, \\r
+ ATA_ATAPI_PASS_THRU_SIGNATURE \\r
+ )\r
+\r
+#define ATA_ATAPI_DEVICE_INFO_FROM_THIS(a) \\r
+ CR (a, \\r
+ EFI_ATA_DEVICE_INFO, \\r
+ Link, \\r
+ ATA_ATAPI_DEVICE_SIGNATURE \\r
+ );\r
+\r
+#define ATA_NON_BLOCK_TASK_FROM_ENTRY(a) \\r
+ CR (a, \\r
+ ATA_NONBLOCK_TASK, \\r
+ Link, \\r
+ ATA_NONBLOCKING_TASK_SIGNATURE \\r
+ );\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+ This function retrieves the user readable name of a driver in the form of a\r
+ Unicode string. If the driver specified by This has a user readable name in\r
+ the language specified by Language, then a pointer to the driver name is\r
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+ by This does not support the language specified by Language,\r
+ then EFI_UNSUPPORTED is returned.\r
+\r
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+ @param Language[in] A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified\r
+ in RFC 4646 or ISO 639-2 language code format.\r
+\r
+ @param DriverName[out] A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ driver specified by This in the language\r
+ specified by Language.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by\r
+ This and the language specified by Language was\r
+ returned in DriverName.\r
+\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AtaAtapiPassThruComponentNameGetDriverName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **DriverName\r
+ );\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the controller\r
+ that is being managed by a driver.\r
+\r
+ This function retrieves the user readable name of the controller specified by\r
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+ driver specified by This has a user readable name in the language specified by\r
+ Language, then a pointer to the controller name is returned in ControllerName,\r
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently\r
+ managing the controller specified by ControllerHandle and ChildHandle,\r
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not\r
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+ @param ControllerHandle[in] The handle of a controller that the driver\r
+ specified by This is managing. This handle\r
+ specifies the controller whose name is to be\r
+ returned.\r
+\r
+ @param ChildHandle[in] The handle of the child controller to retrieve\r
+ the name of. This is an optional parameter that\r
+ may be NULL. It will be NULL for device\r
+ drivers. It will also be NULL for a bus drivers\r
+ that wish to retrieve the name of the bus\r
+ controller. It will not be NULL for a bus\r
+ driver that wishes to retrieve the name of a\r
+ child controller.\r
+\r
+ @param Language[in] A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified in\r
+ RFC 4646 or ISO 639-2 language code format.\r
+\r
+ @param ControllerName[out] A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ controller specified by ControllerHandle and\r
+ ChildHandle in the language specified by\r
+ Language from the point of view of the driver\r
+ specified by This.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the user readable name in\r
+ the language specified by Language for the\r
+ driver specified by This was returned in\r
+ DriverName.\r
+\r
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.\r
+\r
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+ EFI_HANDLE.\r
+\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently\r
+ managing the controller specified by\r
+ ControllerHandle and ChildHandle.\r
+\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AtaAtapiPassThruComponentNameGetControllerName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle OPTIONAL,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **ControllerName\r
+ );\r
+\r
+/**\r
+ Tests to see if this driver supports a given controller. If a child device is provided,\r
+ it further tests to see if this driver supports creating a handle for the specified child device.\r
+\r
+ This function checks to see if the driver specified by This supports the device specified by\r
+ ControllerHandle. Drivers will typically use the device path attached to\r
+ ControllerHandle and/or the services from the bus I/O abstraction attached to\r
+ ControllerHandle to determine if the driver supports ControllerHandle. This function\r
+ may be called many times during platform initialization. In order to reduce boot times, the tests\r
+ performed by this function must be very small, and take as little time as possible to execute. This\r
+ function must not change the state of any hardware devices, and this function must be aware that the\r
+ device specified by ControllerHandle may already be managed by the same driver or a\r
+ different driver. This function must match its calls to AllocatePages() with FreePages(),\r
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().\r
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is\r
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required\r
+ to guarantee the state of ControllerHandle is not modified by this function.\r
+\r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle The handle of the controller to test. This handle\r
+ must support a protocol interface that supplies\r
+ an I/O abstraction to the driver.\r
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
+ parameter is ignored by device drivers, and is optional for bus\r
+ drivers. For bus drivers, if this parameter is not NULL, then\r
+ the bus driver must determine if the bus controller specified\r
+ by ControllerHandle and the child controller specified\r
+ by RemainingDevicePath are both supported by this\r
+ bus driver.\r
+\r
+ @retval EFI_SUCCESS The device specified by ControllerHandle and\r
+ RemainingDevicePath is supported by the driver specified by This.\r
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
+ RemainingDevicePath is already being managed by the driver\r
+ specified by This.\r
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
+ RemainingDevicePath is already being managed by a different\r
+ driver or an application that requires exclusive access.\r
+ Currently not implemented.\r
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
+ RemainingDevicePath is not supported by the driver specified by This.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AtaAtapiPassThruSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ );\r
+\r
+/**\r
+ Starts a device controller or a bus controller.\r
+\r
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().\r
+ As a result, much of the error checking on the parameters to Start() has been moved into this\r
+ common boot service. It is legal to call Start() from other locations,\r
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
+ 1. ControllerHandle must be a valid EFI_HANDLE.\r
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
+ EFI_DEVICE_PATH_PROTOCOL.\r
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.\r
+\r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle The handle of the controller to start. This handle\r
+ must support a protocol interface that supplies\r
+ an I/O abstraction to the driver.\r
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
+ parameter is ignored by device drivers, and is optional for bus\r
+ drivers. For a bus driver, if this parameter is NULL, then handles\r
+ for all the children of Controller are created by this driver.\r
+ If this parameter is not NULL and the first Device Path Node is\r
+ not the End of Device Path Node, then only the handle for the\r
+ child device specified by the first Device Path Node of\r
+ RemainingDevicePath is created by this driver.\r
+ If the first Device Path Node of RemainingDevicePath is\r
+ the End of Device Path Node, no child handle is created by this\r
+ driver.\r
+\r
+ @retval EFI_SUCCESS The device was started.\r
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ @retval Others The driver failded to start the device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AtaAtapiPassThruStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ );\r
+\r
+/**\r
+ Stops a device controller or a bus controller.\r
+\r
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().\r
+ As a result, much of the error checking on the parameters to Stop() has been moved\r
+ into this common boot service. It is legal to call Stop() from other locations,\r
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
+ same driver's Start() function.\r
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
+ Start() function, and the Start() function must have called OpenProtocol() on\r
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
+\r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must\r
+ support a bus specific I/O protocol for the driver\r
+ to use to stop the device.\r
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL\r
+ if NumberOfChildren is 0.\r
+\r
+ @retval EFI_SUCCESS The device was stopped.\r
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AtaAtapiPassThruStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer\r
+ );\r
+\r
+/**\r
+ Traverse the attached ATA devices list to find out the device to access.\r
+\r
+ @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.\r
+ @param[in] Port The port number of the ATA device to send the command.\r
+ @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.\r
+ If there is no port multiplier, then specify 0.\r
+ @param[in] DeviceType The device type of the ATA device.\r
+\r
+ @retval The pointer to the data structure of the device info to access.\r
+\r
+**/\r
+LIST_ENTRY *\r
+EFIAPI\r
+SearchDeviceInfoList (\r
+ IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,\r
+ IN UINT16 Port,\r
+ IN UINT16 PortMultiplier,\r
+ IN EFI_ATA_DEVICE_TYPE DeviceType\r
+ );\r
+\r
+/**\r
+ Allocate device info data structure to contain device info.\r
+ And insert the data structure to the tail of device list for tracing.\r
+\r
+ @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.\r
+ @param[in] Port The port number of the ATA device to send the command.\r
+ @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.\r
+ If there is no port multiplier, then specify 0.\r
+ @param[in] DeviceType The device type of the ATA device.\r
+ @param[in] IdentifyData The data buffer to store the output of the IDENTIFY cmd.\r
+\r
+ @retval EFI_SUCCESS Successfully insert the ata device to the tail of device list.\r
+ @retval EFI_OUT_OF_RESOURCES Can not allocate enough resource for use.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CreateNewDeviceInfo (\r
+ IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,\r
+ IN UINT16 Port,\r
+ IN UINT16 PortMultiplier,\r
+ IN EFI_ATA_DEVICE_TYPE DeviceType,\r
+ IN EFI_IDENTIFY_DATA *IdentifyData\r
+ );\r
+\r
+/**\r
+ Destroy all attached ATA devices info.\r
+\r
+ @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+DestroyDeviceInfoList (\r
+ IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance\r
+ );\r
+\r
+/**\r
+ Destroy all pending non blocking tasks.\r
+\r
+ @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.\r
+ @param[in] IsSigEvent Indicate whether signal the task event when remove the\r
+ task.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+DestroyAsynTaskList (\r
+ IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,\r
+ IN BOOLEAN IsSigEvent\r
+ );\r
+\r
+/**\r
+ Enumerate all attached ATA devices at IDE mode or AHCI mode separately.\r
+\r
+ The function is designed to enumerate all attached ATA devices.\r
+\r
+ @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.\r
+\r
+ @retval EFI_SUCCESS Successfully enumerate attached ATA devices.\r
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EnumerateAttachedDevice (\r
+ IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance\r
+ );\r
+\r
+/**\r
+ Call back funtion when the timer event is signaled.\r
+\r
+ @param[in] Event The Event this notify function registered to.\r
+ @param[in] Context Pointer to the context data registered to the\r
+ Event.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+AsyncNonBlockingTransferRoutine (\r
+ EFI_EVENT Event,\r
+ VOID* Context\r
+ );\r
+\r
+/**\r
+ Sends an ATA command to an ATA device that is attached to the ATA controller. This function\r
+ supports both blocking I/O and non-blocking I/O. The blocking I/O functionality is required,\r
+ and the non-blocking I/O functionality is optional.\r
+\r
+ @param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.\r
+ @param[in] Port The port number of the ATA device to send the command.\r
+ @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.\r
+ If there is no port multiplier, then specify 0.\r
+ @param[in, out] Packet A pointer to the ATA command to send to the ATA device specified by Port\r
+ and PortMultiplierPort.\r
+ @param[in] Event If non-blocking I/O is not supported then Event is ignored, and blocking\r
+ I/O is performed. If Event is NULL, then blocking I/O is performed. If\r
+ Event is not NULL and non blocking I/O is supported, then non-blocking\r
+ I/O is performed, and Event will be signaled when the ATA command completes.\r
+\r
+ @retval EFI_SUCCESS The ATA command was sent by the host. For bi-directional commands,\r
+ InTransferLength bytes were transferred from InDataBuffer. For write and\r
+ bi-directional commands, OutTransferLength bytes were transferred by OutDataBuffer.\r
+ @retval EFI_BAD_BUFFER_SIZE The ATA command was not executed. The number of bytes that could be transferred\r
+ is returned in InTransferLength. For write and bi-directional commands,\r
+ OutTransferLength bytes were transferred by OutDataBuffer.\r
+ @retval EFI_NOT_READY The ATA command could not be sent because there are too many ATA commands\r
+ already queued. The caller may retry again later.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the ATA command.\r
+ @retval EFI_INVALID_PARAMETER Port, PortMultiplierPort, or the contents of Acb are invalid. The ATA\r
+ command was not sent, so no additional status information is available.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AtaPassThruPassThru (\r
+ IN EFI_ATA_PASS_THRU_PROTOCOL *This,\r
+ IN UINT16 Port,\r
+ IN UINT16 PortMultiplierPort,\r
+ IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet,\r
+ IN EFI_EVENT Event OPTIONAL\r
+ );\r
+\r
+/**\r
+ Used to retrieve the list of legal port numbers for ATA devices on an ATA controller.\r
+ These can either be the list of ports where ATA devices are actually present or the\r
+ list of legal port numbers for the ATA controller. Regardless, the caller of this\r
+ function must probe the port number returned to see if an ATA device is actually\r
+ present at that location on the ATA controller.\r
+\r
+ The GetNextPort() function retrieves the port number on an ATA controller. If on input\r
+ Port is 0xFFFF, then the port number of the first port on the ATA controller is returned\r
+ in Port and EFI_SUCCESS is returned.\r
+\r
+ If Port is a port number that was returned on a previous call to GetNextPort(), then the\r
+ port number of the next port on the ATA controller is returned in Port, and EFI_SUCCESS\r
+ is returned. If Port is not 0xFFFF and Port was not returned on a previous call to\r
+ GetNextPort(), then EFI_INVALID_PARAMETER is returned.\r
+\r
+ If Port is the port number of the last port on the ATA controller, then EFI_NOT_FOUND is\r
+ returned.\r
+\r
+ @param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.\r
+ @param[in, out] Port On input, a pointer to the port number on the ATA controller.\r
+ On output, a pointer to the next port number on the ATA\r
+ controller. An input value of 0xFFFF retrieves the first port\r
+ number on the ATA controller.\r
+\r
+ @retval EFI_SUCCESS The next port number on the ATA controller was returned in Port.\r
+ @retval EFI_NOT_FOUND There are no more ports on this ATA controller.\r
+ @retval EFI_INVALID_PARAMETER Port is not 0xFFFF and Port was not returned on a previous call\r
+ to GetNextPort().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AtaPassThruGetNextPort (\r
+ IN EFI_ATA_PASS_THRU_PROTOCOL *This,\r
+ IN OUT UINT16 *Port\r
+ );\r
+\r
+/**\r
+ Used to retrieve the list of legal port multiplier port numbers for ATA devices on a port of an ATA\r
+ controller. These can either be the list of port multiplier ports where ATA devices are actually\r
+ present on port or the list of legal port multiplier ports on that port. Regardless, the caller of this\r
+ function must probe the port number and port multiplier port number returned to see if an ATA\r
+ device is actually present.\r
+\r
+ The GetNextDevice() function retrieves the port multiplier port number of an ATA device\r
+ present on a port of an ATA controller.\r
+\r
+ If PortMultiplierPort points to a port multiplier port number value that was returned on a\r
+ previous call to GetNextDevice(), then the port multiplier port number of the next ATA device\r
+ on the port of the ATA controller is returned in PortMultiplierPort, and EFI_SUCCESS is\r
+ returned.\r
+\r
+ If PortMultiplierPort points to 0xFFFF, then the port multiplier port number of the first\r
+ ATA device on port of the ATA controller is returned in PortMultiplierPort and\r
+ EFI_SUCCESS is returned.\r
+\r
+ If PortMultiplierPort is not 0xFFFF and the value pointed to by PortMultiplierPort\r
+ was not returned on a previous call to GetNextDevice(), then EFI_INVALID_PARAMETER\r
+ is returned.\r
+\r
+ If PortMultiplierPort is the port multiplier port number of the last ATA device on the port of\r
+ the ATA controller, then EFI_NOT_FOUND is returned.\r
+\r
+ @param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.\r
+ @param[in] Port The port number present on the ATA controller.\r
+ @param[in, out] PortMultiplierPort On input, a pointer to the port multiplier port number of an\r
+ ATA device present on the ATA controller.\r
+ If on input a PortMultiplierPort of 0xFFFF is specified,\r
+ then the port multiplier port number of the first ATA device\r
+ is returned. On output, a pointer to the port multiplier port\r
+ number of the next ATA device present on an ATA controller.\r
+\r
+ @retval EFI_SUCCESS The port multiplier port number of the next ATA device on the port\r
+ of the ATA controller was returned in PortMultiplierPort.\r
+ @retval EFI_NOT_FOUND There are no more ATA devices on this port of the ATA controller.\r
+ @retval EFI_INVALID_PARAMETER PortMultiplierPort is not 0xFFFF, and PortMultiplierPort was not\r
+ returned on a previous call to GetNextDevice().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AtaPassThruGetNextDevice (\r
+ IN EFI_ATA_PASS_THRU_PROTOCOL *This,\r
+ IN UINT16 Port,\r
+ IN OUT UINT16 *PortMultiplierPort\r
+ );\r
+\r
+/**\r
+ Used to allocate and build a device path node for an ATA device on an ATA controller.\r
+\r
+ The BuildDevicePath() function allocates and builds a single device node for the ATA\r
+ device specified by Port and PortMultiplierPort. If the ATA device specified by Port and\r
+ PortMultiplierPort is not present on the ATA controller, then EFI_NOT_FOUND is returned.\r
+ If DevicePath is NULL, then EFI_INVALID_PARAMETER is returned. If there are not enough\r
+ resources to allocate the device path node, then EFI_OUT_OF_RESOURCES is returned.\r
+\r
+ Otherwise, DevicePath is allocated with the boot service AllocatePool(), the contents of\r
+ DevicePath are initialized to describe the ATA device specified by Port and PortMultiplierPort,\r
+ and EFI_SUCCESS is returned.\r
+\r
+ @param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.\r
+ @param[in] Port Port specifies the port number of the ATA device for which a\r
+ device path node is to be allocated and built.\r
+ @param[in] PortMultiplierPort The port multiplier port number of the ATA device for which a\r
+ device path node is to be allocated and built. If there is no\r
+ port multiplier, then specify 0.\r
+ @param[in, out] DevicePath A pointer to a single device path node that describes the ATA\r
+ device specified by Port and PortMultiplierPort. This function\r
+ is responsible for allocating the buffer DevicePath with the\r
+ boot service AllocatePool(). It is the caller's responsibility\r
+ to free DevicePath when the caller is finished with DevicePath.\r
+ @retval EFI_SUCCESS The device path node that describes the ATA device specified by\r
+ Port and PortMultiplierPort was allocated and returned in DevicePath.\r
+ @retval EFI_NOT_FOUND The ATA device specified by Port and PortMultiplierPort does not\r
+ exist on the ATA controller.\r
+ @retval EFI_INVALID_PARAMETER DevicePath is NULL.\r
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate DevicePath.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AtaPassThruBuildDevicePath (\r
+ IN EFI_ATA_PASS_THRU_PROTOCOL *This,\r
+ IN UINT16 Port,\r
+ IN UINT16 PortMultiplierPort,\r
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath\r
+ );\r
+\r
+/**\r
+ Used to translate a device path node to a port number and port multiplier port number.\r
+\r
+ The GetDevice() function determines the port and port multiplier port number associated with\r
+ the ATA device described by DevicePath. If DevicePath is a device path node type that the\r
+ ATA Pass Thru driver supports, then the ATA Pass Thru driver will attempt to translate the contents\r
+ DevicePath into a port number and port multiplier port number.\r
+\r
+ If this translation is successful, then that port number and port multiplier port number are returned\r
+ in Port and PortMultiplierPort, and EFI_SUCCESS is returned.\r
+\r
+ If DevicePath, Port, or PortMultiplierPort are NULL, then EFI_INVALID_PARAMETER is returned.\r
+\r
+ If DevicePath is not a device path node type that the ATA Pass Thru driver supports, then\r
+ EFI_UNSUPPORTED is returned.\r
+\r
+ If DevicePath is a device path node type that the ATA Pass Thru driver supports, but there is not\r
+ a valid translation from DevicePath to a port number and port multiplier port number, then\r
+ EFI_NOT_FOUND is returned.\r
+\r
+ @param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.\r
+ @param[in] DevicePath A pointer to the device path node that describes an ATA device on the\r
+ ATA controller.\r
+ @param[out] Port On return, points to the port number of an ATA device on the ATA controller.\r
+ @param[out] PortMultiplierPort On return, points to the port multiplier port number of an ATA device\r
+ on the ATA controller.\r
+\r
+ @retval EFI_SUCCESS DevicePath was successfully translated to a port number and port multiplier\r
+ port number, and they were returned in Port and PortMultiplierPort.\r
+ @retval EFI_INVALID_PARAMETER DevicePath is NULL.\r
+ @retval EFI_INVALID_PARAMETER Port is NULL.\r
+ @retval EFI_INVALID_PARAMETER PortMultiplierPort is NULL.\r
+ @retval EFI_UNSUPPORTED This driver does not support the device path node type in DevicePath.\r
+ @retval EFI_NOT_FOUND A valid translation from DevicePath to a port number and port multiplier\r
+ port number does not exist.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AtaPassThruGetDevice (\r
+ IN EFI_ATA_PASS_THRU_PROTOCOL *This,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ OUT UINT16 *Port,\r
+ OUT UINT16 *PortMultiplierPort\r
+ );\r
+\r
+/**\r
+ Resets a specific port on the ATA controller. This operation also resets all the ATA devices\r
+ connected to the port.\r
+\r
+ The ResetChannel() function resets an a specific port on an ATA controller. This operation\r
+ resets all the ATA devices connected to that port. If this ATA controller does not support\r
+ a reset port operation, then EFI_UNSUPPORTED is returned.\r
+\r
+ If a device error occurs while executing that port reset operation, then EFI_DEVICE_ERROR is\r
+ returned.\r
+\r
+ If a timeout occurs during the execution of the port reset operation, then EFI_TIMEOUT is returned.\r
+\r
+ If the port reset operation is completed, then EFI_SUCCESS is returned.\r
+\r
+ @param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.\r
+ @param[in] Port The port number on the ATA controller.\r
+\r
+ @retval EFI_SUCCESS The ATA controller port was reset.\r
+ @retval EFI_UNSUPPORTED The ATA controller does not support a port reset operation.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to reset the ATA port.\r
+ @retval EFI_TIMEOUT A timeout occurred while attempting to reset the ATA port.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AtaPassThruResetPort (\r
+ IN EFI_ATA_PASS_THRU_PROTOCOL *This,\r
+ IN UINT16 Port\r
+ );\r
+\r
+/**\r
+ Resets an ATA device that is connected to an ATA controller.\r
+\r
+ The ResetDevice() function resets the ATA device specified by Port and PortMultiplierPort.\r
+ If this ATA controller does not support a device reset operation, then EFI_UNSUPPORTED is\r
+ returned.\r
+\r
+ If Port or PortMultiplierPort are not in a valid range for this ATA controller, then\r
+ EFI_INVALID_PARAMETER is returned.\r
+\r
+ If a device error occurs while executing that device reset operation, then EFI_DEVICE_ERROR\r
+ is returned.\r
+\r
+ If a timeout occurs during the execution of the device reset operation, then EFI_TIMEOUT is\r
+ returned.\r
+\r
+ If the device reset operation is completed, then EFI_SUCCESS is returned.\r
+\r
+ @param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.\r
+ @param[in] Port Port represents the port number of the ATA device to be reset.\r
+ @param[in] PortMultiplierPort The port multiplier port number of the ATA device to reset.\r
+ If there is no port multiplier, then specify 0.\r
+ @retval EFI_SUCCESS The ATA device specified by Port and PortMultiplierPort was reset.\r
+ @retval EFI_UNSUPPORTED The ATA controller does not support a device reset operation.\r
+ @retval EFI_INVALID_PARAMETER Port or PortMultiplierPort are invalid.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to reset the ATA device\r
+ specified by Port and PortMultiplierPort.\r
+ @retval EFI_TIMEOUT A timeout occurred while attempting to reset the ATA device\r
+ specified by Port and PortMultiplierPort.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AtaPassThruResetDevice (\r
+ IN EFI_ATA_PASS_THRU_PROTOCOL *This,\r
+ IN UINT16 Port,\r
+ IN UINT16 PortMultiplierPort\r
+ );\r
+\r
+/**\r
+ Sends a SCSI Request Packet to a SCSI device that is attached to the SCSI channel. This function\r
+ supports both blocking I/O and nonblocking I/O. The blocking I/O functionality is required, and the\r
+ nonblocking I/O functionality is optional.\r
+\r
+ @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.\r
+ @param Target The Target is an array of size TARGET_MAX_BYTES and it represents\r
+ the id of the SCSI device to send the SCSI Request Packet. Each\r
+ transport driver may choose to utilize a subset of this size to suit the needs\r
+ of transport target representation. For example, a Fibre Channel driver\r
+ may use only 8 bytes (WWN) to represent an FC target.\r
+ @param Lun The LUN of the SCSI device to send the SCSI Request Packet.\r
+ @param Packet A pointer to the SCSI Request Packet to send to the SCSI device\r
+ specified by Target and Lun.\r
+ @param Event If nonblocking I/O is not supported then Event is ignored, and blocking\r
+ I/O is performed. If Event is NULL, then blocking I/O is performed. If\r
+ Event is not NULL and non blocking I/O is supported, then\r
+ nonblocking I/O is performed, and Event will be signaled when the\r
+ SCSI Request Packet completes.\r
+\r
+ @retval EFI_SUCCESS The SCSI Request Packet was sent by the host. For bi-directional\r
+ commands, InTransferLength bytes were transferred from\r
+ InDataBuffer. For write and bi-directional commands,\r
+ OutTransferLength bytes were transferred by\r
+ OutDataBuffer.\r
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was not executed. The number of bytes that\r
+ could be transferred is returned in InTransferLength. For write\r
+ and bi-directional commands, OutTransferLength bytes were\r
+ transferred by OutDataBuffer.\r
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many\r
+ SCSI Request Packets already queued. The caller may retry again later.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the SCSI Request\r
+ Packet.\r
+ @retval EFI_INVALID_PARAMETER Target, Lun, or the contents of ScsiRequestPacket are invalid.\r
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported\r
+ by the host adapter. This includes the case of Bi-directional SCSI\r
+ commands not supported by the implementation. The SCSI Request\r
+ Packet was not sent, so no additional status information is available.\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ExtScsiPassThruPassThru (\r
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
+ IN UINT8 *Target,\r
+ IN UINT64 Lun,\r
+ IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,\r
+ IN EFI_EVENT Event OPTIONAL\r
+ );\r
+\r
+/**\r
+ Used to retrieve the list of legal Target IDs and LUNs for SCSI devices on a SCSI channel. These\r
+ can either be the list SCSI devices that are actually present on the SCSI channel, or the list of legal\r
+ Target Ids and LUNs for the SCSI channel. Regardless, the caller of this function must probe the\r
+ Target ID and LUN returned to see if a SCSI device is actually present at that location on the SCSI\r
+ channel.\r
+\r
+ @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.\r
+ @param Target On input, a pointer to the Target ID (an array of size\r
+ TARGET_MAX_BYTES) of a SCSI device present on the SCSI channel.\r
+ On output, a pointer to the Target ID (an array of\r
+ TARGET_MAX_BYTES) of the next SCSI device present on a SCSI\r
+ channel. An input value of 0xF(all bytes in the array are 0xF) in the\r
+ Target array retrieves the Target ID of the first SCSI device present on a\r
+ SCSI channel.\r
+ @param Lun On input, a pointer to the LUN of a SCSI device present on the SCSI\r
+ channel. On output, a pointer to the LUN of the next SCSI device present\r
+ on a SCSI channel.\r
+\r
+ @retval EFI_SUCCESS The Target ID and LUN of the next SCSI device on the SCSI\r
+ channel was returned in Target and Lun.\r
+ @retval EFI_INVALID_PARAMETER Target array is not all 0xF, and Target and Lun were\r
+ not returned on a previous call to GetNextTargetLun().\r
+ @retval EFI_NOT_FOUND There are no more SCSI devices on this SCSI channel.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ExtScsiPassThruGetNextTargetLun (\r
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
+ IN OUT UINT8 **Target,\r
+ IN OUT UINT64 *Lun\r
+ );\r
+\r
+/**\r
+ Used to allocate and build a device path node for a SCSI device on a SCSI channel.\r
+\r
+ @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.\r
+ @param Target The Target is an array of size TARGET_MAX_BYTES and it specifies the\r
+ Target ID of the SCSI device for which a device path node is to be\r
+ allocated and built. Transport drivers may chose to utilize a subset of\r
+ this size to suit the representation of targets. For example, a Fibre\r
+ Channel driver may use only 8 bytes (WWN) in the array to represent a\r
+ FC target.\r
+ @param Lun The LUN of the SCSI device for which a device path node is to be\r
+ allocated and built.\r
+ @param DevicePath A pointer to a single device path node that describes the SCSI device\r
+ specified by Target and Lun. This function is responsible for\r
+ allocating the buffer DevicePath with the boot service\r
+ AllocatePool(). It is the caller's responsibility to free\r
+ DevicePath when the caller is finished with DevicePath.\r
+\r
+ @retval EFI_SUCCESS The device path node that describes the SCSI device specified by\r
+ Target and Lun was allocated and returned in\r
+ DevicePath.\r
+ @retval EFI_INVALID_PARAMETER DevicePath is NULL.\r
+ @retval EFI_NOT_FOUND The SCSI devices specified by Target and Lun does not exist\r
+ on the SCSI channel.\r
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate DevicePath.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ExtScsiPassThruBuildDevicePath (\r
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
+ IN UINT8 *Target,\r
+ IN UINT64 Lun,\r
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath\r
+ );\r
+\r
+/**\r
+ Used to translate a device path node to a Target ID and LUN.\r
+\r
+ @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.\r
+ @param DevicePath A pointer to a single device path node that describes the SCSI device\r
+ on the SCSI channel.\r
+ @param Target A pointer to the Target Array which represents the ID of a SCSI device\r
+ on the SCSI channel.\r
+ @param Lun A pointer to the LUN of a SCSI device on the SCSI channel.\r
+\r
+ @retval EFI_SUCCESS DevicePath was successfully translated to a Target ID and\r
+ LUN, and they were returned in Target and Lun.\r
+ @retval EFI_INVALID_PARAMETER DevicePath or Target or Lun is NULL.\r
+ @retval EFI_NOT_FOUND A valid translation from DevicePath to a Target ID and LUN\r
+ does not exist.\r
+ @retval EFI_UNSUPPORTED This driver does not support the device path node type in\r
+ DevicePath.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ExtScsiPassThruGetTargetLun (\r
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ OUT UINT8 **Target,\r
+ OUT UINT64 *Lun\r
+ );\r
+\r
+/**\r
+ Resets a SCSI channel. This operation resets all the SCSI devices connected to the SCSI channel.\r
+\r
+ @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.\r
+\r
+ @retval EFI_SUCCESS The SCSI channel was reset.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to reset the SCSI channel.\r
+ @retval EFI_TIMEOUT A timeout occurred while attempting to reset the SCSI channel.\r
+ @retval EFI_UNSUPPORTED The SCSI channel does not support a channel reset operation.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ExtScsiPassThruResetChannel (\r
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This\r
+ );\r
+\r
+/**\r
+ Resets a SCSI logical unit that is connected to a SCSI channel.\r
+\r
+ @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.\r
+ @param Target The Target is an array of size TARGET_MAX_BYTE and it represents the\r
+ target port ID of the SCSI device containing the SCSI logical unit to\r
+ reset. Transport drivers may chose to utilize a subset of this array to suit\r
+ the representation of their targets.\r
+ @param Lun The LUN of the SCSI device to reset.\r
+\r
+ @retval EFI_SUCCESS The SCSI device specified by Target and Lun was reset.\r
+ @retval EFI_INVALID_PARAMETER Target or Lun is NULL.\r
+ @retval EFI_TIMEOUT A timeout occurred while attempting to reset the SCSI device\r
+ specified by Target and Lun.\r
+ @retval EFI_UNSUPPORTED The SCSI channel does not support a target reset operation.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to reset the SCSI device\r
+ specified by Target and Lun.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ExtScsiPassThruResetTargetLun (\r
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
+ IN UINT8 *Target,\r
+ IN UINT64 Lun\r
+ );\r
+\r
+/**\r
+ Used to retrieve the list of legal Target IDs for SCSI devices on a SCSI channel. These can either\r
+ be the list SCSI devices that are actually present on the SCSI channel, or the list of legal Target IDs\r
+ for the SCSI channel. Regardless, the caller of this function must probe the Target ID returned to\r
+ see if a SCSI device is actually present at that location on the SCSI channel.\r
+\r
+ @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.\r
+ @param Target (TARGET_MAX_BYTES) of a SCSI device present on the SCSI channel.\r
+ On output, a pointer to the Target ID (an array of\r
+ TARGET_MAX_BYTES) of the next SCSI device present on a SCSI\r
+ channel. An input value of 0xF(all bytes in the array are 0xF) in the\r
+ Target array retrieves the Target ID of the first SCSI device present on a\r
+ SCSI channel.\r
+\r
+ @retval EFI_SUCCESS The Target ID of the next SCSI device on the SCSI\r
+ channel was returned in Target.\r
+ @retval EFI_INVALID_PARAMETER Target or Lun is NULL.\r
+ @retval EFI_TIMEOUT Target array is not all 0xF, and Target was not\r
+ returned on a previous call to GetNextTarget().\r
+ @retval EFI_NOT_FOUND There are no more SCSI devices on this SCSI channel.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ExtScsiPassThruGetNextTarget (\r
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
+ IN OUT UINT8 **Target\r
+ );\r
+\r
+/**\r
+ Initialize ATA host controller at IDE mode.\r
+\r
+ The function is designed to initialize ATA host controller.\r
+\r
+ @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IdeModeInitialization (\r
+ IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance\r
+ );\r
+\r
+/**\r
+ Initialize ATA host controller at AHCI mode.\r
+\r
+ The function is designed to initialize ATA host controller.\r
+\r
+ @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AhciModeInitialization (\r
+ IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance\r
+ );\r
+\r
+/**\r
+ Start a non data transfer on specific port.\r
+\r
+ @param[in] PciIo The PCI IO protocol instance.\r
+ @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.\r
+ @param[in] Port The number of port.\r
+ @param[in] PortMultiplier The timeout value of stop.\r
+ @param[in] AtapiCommand The atapi command will be used for the\r
+ transfer.\r
+ @param[in] AtapiCommandLength The length of the atapi command.\r
+ @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.\r
+ @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.\r
+ @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.\r
+ @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK\r
+ used by non-blocking mode.\r
+\r
+ @retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.\r
+ @retval EFI_TIMEOUT The operation is time out.\r
+ @retval EFI_UNSUPPORTED The device is not ready for transfer.\r
+ @retval EFI_SUCCESS The non data transfer executes successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AhciNonDataTransfer (\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ IN EFI_AHCI_REGISTERS *AhciRegisters,\r
+ IN UINT8 Port,\r
+ IN UINT8 PortMultiplier,\r
+ IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,\r
+ IN UINT8 AtapiCommandLength,\r
+ IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,\r
+ IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,\r
+ IN UINT64 Timeout,\r
+ IN ATA_NONBLOCK_TASK *Task\r
+ );\r
+\r
+/**\r
+ Start a DMA data transfer on specific port\r
+\r
+ @param[in] Instance The ATA_ATAPI_PASS_THRU_INSTANCE protocol instance.\r
+ @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.\r
+ @param[in] Port The number of port.\r
+ @param[in] PortMultiplier The timeout value of stop.\r
+ @param[in] AtapiCommand The atapi command will be used for the\r
+ transfer.\r
+ @param[in] AtapiCommandLength The length of the atapi command.\r
+ @param[in] Read The transfer direction.\r
+ @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.\r
+ @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.\r
+ @param[in, out] MemoryAddr The pointer to the data buffer.\r
+ @param[in] DataCount The data count to be transferred.\r
+ @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.\r
+ @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK\r
+ used by non-blocking mode.\r
+\r
+ @retval EFI_DEVICE_ERROR The DMA data transfer abort with error occurs.\r
+ @retval EFI_TIMEOUT The operation is time out.\r
+ @retval EFI_UNSUPPORTED The device is not ready for transfer.\r
+ @retval EFI_SUCCESS The DMA data transfer executes successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AhciDmaTransfer (\r
+ IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,\r
+ IN EFI_AHCI_REGISTERS *AhciRegisters,\r
+ IN UINT8 Port,\r
+ IN UINT8 PortMultiplier,\r
+ IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,\r
+ IN UINT8 AtapiCommandLength,\r
+ IN BOOLEAN Read,\r
+ IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,\r
+ IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,\r
+ IN OUT VOID *MemoryAddr,\r
+ IN UINT32 DataCount,\r
+ IN UINT64 Timeout,\r
+ IN ATA_NONBLOCK_TASK *Task\r
+ );\r
+\r
+/**\r
+ Start a PIO data transfer on specific port.\r
+\r
+ @param[in] PciIo The PCI IO protocol instance.\r
+ @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.\r
+ @param[in] Port The number of port.\r
+ @param[in] PortMultiplier The timeout value of stop.\r
+ @param[in] AtapiCommand The atapi command will be used for the\r
+ transfer.\r
+ @param[in] AtapiCommandLength The length of the atapi command.\r
+ @param[in] Read The transfer direction.\r
+ @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.\r
+ @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.\r
+ @param[in, out] MemoryAddr The pointer to the data buffer.\r
+ @param[in] DataCount The data count to be transferred.\r
+ @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.\r
+ @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK\r
+ used by non-blocking mode.\r
+\r
+ @retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs.\r
+ @retval EFI_TIMEOUT The operation is time out.\r
+ @retval EFI_UNSUPPORTED The device is not ready for transfer.\r
+ @retval EFI_SUCCESS The PIO data transfer executes successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AhciPioTransfer (\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ IN EFI_AHCI_REGISTERS *AhciRegisters,\r
+ IN UINT8 Port,\r
+ IN UINT8 PortMultiplier,\r
+ IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,\r
+ IN UINT8 AtapiCommandLength,\r
+ IN BOOLEAN Read,\r
+ IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,\r
+ IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,\r
+ IN OUT VOID *MemoryAddr,\r
+ IN UINT32 DataCount,\r
+ IN UINT64 Timeout,\r
+ IN ATA_NONBLOCK_TASK *Task\r
+ );\r
+\r
+/**\r
+ Send ATA command into device with NON_DATA protocol\r
+\r
+ @param[in] PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE\r
+ data structure.\r
+ @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
+ @param[in] AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data\r
+ structure.\r
+ @param[in, out] AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
+ @param[in] Timeout The time to complete the command, uses 100ns as a unit.\r
+ @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK\r
+ used by non-blocking mode.\r
+\r
+ @retval EFI_SUCCESS Reading succeed\r
+ @retval EFI_ABORTED Command failed\r
+ @retval EFI_DEVICE_ERROR Device status error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AtaNonDataCommandIn (\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ IN EFI_IDE_REGISTERS *IdeRegisters,\r
+ IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,\r
+ IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,\r
+ IN UINT64 Timeout,\r
+ IN ATA_NONBLOCK_TASK *Task\r
+ );\r
+\r
+/**\r
+ Perform an ATA Udma operation (Read, ReadExt, Write, WriteExt).\r
+\r
+ @param[in] Instance A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data\r
+ structure.\r
+ @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
+ @param[in] Read Flag used to determine the data transfer\r
+ direction. Read equals 1, means data transferred\r
+ from device to host;Read equals 0, means data\r
+ transferred from host to device.\r
+ @param[in] DataBuffer A pointer to the source buffer for the data.\r
+ @param[in] DataLength The length of the data.\r
+ @param[in] AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.\r
+ @param[in, out] AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
+ @param[in] Timeout The time to complete the command, uses 100ns as a unit.\r
+ @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK\r
+ used by non-blocking mode.\r
+\r
+ @retval EFI_SUCCESS the operation is successful.\r
+ @retval EFI_OUT_OF_RESOURCES Build PRD table failed\r
+ @retval EFI_UNSUPPORTED Unknown channel or operations command\r
+ @retval EFI_DEVICE_ERROR Ata command execute failed\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AtaUdmaInOut (\r
+ IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,\r
+ IN EFI_IDE_REGISTERS *IdeRegisters,\r
+ IN BOOLEAN Read,\r
+ IN VOID *DataBuffer,\r
+ IN UINT64 DataLength,\r
+ IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,\r
+ IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,\r
+ IN UINT64 Timeout,\r
+ IN ATA_NONBLOCK_TASK *Task\r
+ );\r
+\r
+/**\r
+ This function is used to send out ATA commands conforms to the PIO Data In Protocol.\r
+\r
+ @param[in] PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data\r
+ structure.\r
+ @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
+ @param[in, out] Buffer A pointer to the source buffer for the data.\r
+ @param[in] ByteCount The length of the data.\r
+ @param[in] Read Flag used to determine the data transfer direction.\r
+ Read equals 1, means data transferred from device\r
+ to host;Read equals 0, means data transferred\r
+ from host to device.\r
+ @param[in] AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.\r
+ @param[in, out] AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
+ @param[in] Timeout The time to complete the command, uses 100ns as a unit.\r
+ @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK\r
+ used by non-blocking mode.\r
+\r
+ @retval EFI_SUCCESS send out the ATA command and device send required data successfully.\r
+ @retval EFI_DEVICE_ERROR command sent failed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AtaPioDataInOut (\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ IN EFI_IDE_REGISTERS *IdeRegisters,\r
+ IN OUT VOID *Buffer,\r
+ IN UINT64 ByteCount,\r
+ IN BOOLEAN Read,\r
+ IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,\r
+ IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,\r
+ IN UINT64 Timeout,\r
+ IN ATA_NONBLOCK_TASK *Task\r
+ );\r
+\r
+#endif\r
+\r
-/** @file
- This file is used to implement the EFI_DISK_INFO_PROTOCOL interface..
-
- Copyright (c) 2013, 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 "NvmExpress.h"
-
-EFI_DISK_INFO_PROTOCOL gNvmExpressDiskInfoProtocolTemplate = {
- EFI_DISK_INFO_NVME_INTERFACE_GUID,
- NvmExpressDiskInfoInquiry,
- NvmExpressDiskInfoIdentify,
- NvmExpressDiskInfoSenseData,
- NvmExpressDiskInfoWhichIde
-};
-
-/**
- Initialize the installation of DiskInfo protocol.
-
- This function prepares for the installation of DiskInfo protocol on the child handle.
- By default, it installs DiskInfo protocol with NVME interface GUID.
-
- @param[in] Device The pointer of NVME_DEVICE_PRIVATE_DATA.
-
-**/
-VOID
-InitializeDiskInfo (
- IN NVME_DEVICE_PRIVATE_DATA *Device
- )
-{
- CopyMem (&Device->DiskInfo, &gNvmExpressDiskInfoProtocolTemplate, sizeof (EFI_DISK_INFO_PROTOCOL));
-}
-
-
-/**
- Provides inquiry information for the controller type.
-
- This function is used to get inquiry data. Data format
- of Identify data is defined by the Interface GUID.
-
- @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
- @param[in, out] InquiryData Pointer to a buffer for the inquiry data.
- @param[in, out] InquiryDataSize Pointer to the value for the inquiry data size.
-
- @retval EFI_SUCCESS The command was accepted without any errors.
- @retval EFI_NOT_FOUND Device does not support this data class
- @retval EFI_DEVICE_ERROR Error reading InquiryData from device
- @retval EFI_BUFFER_TOO_SMALL InquiryDataSize not big enough
-
-**/
-EFI_STATUS
-EFIAPI
-NvmExpressDiskInfoInquiry (
- IN EFI_DISK_INFO_PROTOCOL *This,
- IN OUT VOID *InquiryData,
- IN OUT UINT32 *InquiryDataSize
- )
-{
- return EFI_NOT_FOUND;
-}
-
-
-/**
- Provides identify information for the controller type.
-
- This function is used to get identify data. Data format
- of Identify data is defined by the Interface GUID.
-
- @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL
- instance.
- @param[in, out] IdentifyData Pointer to a buffer for the identify data.
- @param[in, out] IdentifyDataSize Pointer to the value for the identify data
- size.
-
- @retval EFI_SUCCESS The command was accepted without any errors.
- @retval EFI_NOT_FOUND Device does not support this data class
- @retval EFI_DEVICE_ERROR Error reading IdentifyData from device
- @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough
-
-**/
-EFI_STATUS
-EFIAPI
-NvmExpressDiskInfoIdentify (
- IN EFI_DISK_INFO_PROTOCOL *This,
- IN OUT VOID *IdentifyData,
- IN OUT UINT32 *IdentifyDataSize
- )
-{
- EFI_STATUS Status;
- NVME_DEVICE_PRIVATE_DATA *Device;
-
- Device = NVME_DEVICE_PRIVATE_DATA_FROM_DISK_INFO (This);
-
- Status = EFI_BUFFER_TOO_SMALL;
- if (*IdentifyDataSize >= sizeof (Device->NamespaceData)) {
- Status = EFI_SUCCESS;
- CopyMem (IdentifyData, &Device->NamespaceData, sizeof (Device->NamespaceData));
- }
- *IdentifyDataSize = sizeof (Device->NamespaceData);
- return Status;
-}
-
-/**
- Provides sense data information for the controller type.
-
- This function is used to get sense data.
- Data format of Sense data is defined by the Interface GUID.
-
- @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
- @param[in, out] SenseData Pointer to the SenseData.
- @param[in, out] SenseDataSize Size of SenseData in bytes.
- @param[out] SenseDataNumber Pointer to the value for the sense data size.
-
- @retval EFI_SUCCESS The command was accepted without any errors.
- @retval EFI_NOT_FOUND Device does not support this data class.
- @retval EFI_DEVICE_ERROR Error reading SenseData from device.
- @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough.
-
-**/
-EFI_STATUS
-EFIAPI
-NvmExpressDiskInfoSenseData (
- IN EFI_DISK_INFO_PROTOCOL *This,
- IN OUT VOID *SenseData,
- IN OUT UINT32 *SenseDataSize,
- OUT UINT8 *SenseDataNumber
- )
-{
- return EFI_NOT_FOUND;
-}
-
-
-/**
- This function is used to get controller information.
-
- @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
- @param[out] IdeChannel Pointer to the Ide Channel number. Primary or secondary.
- @param[out] IdeDevice Pointer to the Ide Device number. Master or slave.
-
- @retval EFI_SUCCESS IdeChannel and IdeDevice are valid.
- @retval EFI_UNSUPPORTED This is not an IDE device.
-
-**/
-EFI_STATUS
-EFIAPI
-NvmExpressDiskInfoWhichIde (
- IN EFI_DISK_INFO_PROTOCOL *This,
- OUT UINT32 *IdeChannel,
- OUT UINT32 *IdeDevice
- )
-{
- return EFI_UNSUPPORTED;
-}
-
+/** @file\r
+ This file is used to implement the EFI_DISK_INFO_PROTOCOL interface..\r
+\r
+ Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "NvmExpress.h"\r
+\r
+EFI_DISK_INFO_PROTOCOL gNvmExpressDiskInfoProtocolTemplate = {\r
+ EFI_DISK_INFO_NVME_INTERFACE_GUID,\r
+ NvmExpressDiskInfoInquiry,\r
+ NvmExpressDiskInfoIdentify,\r
+ NvmExpressDiskInfoSenseData,\r
+ NvmExpressDiskInfoWhichIde\r
+};\r
+\r
+/**\r
+ Initialize the installation of DiskInfo protocol.\r
+\r
+ This function prepares for the installation of DiskInfo protocol on the child handle.\r
+ By default, it installs DiskInfo protocol with NVME interface GUID.\r
+\r
+ @param[in] Device The pointer of NVME_DEVICE_PRIVATE_DATA.\r
+\r
+**/\r
+VOID\r
+InitializeDiskInfo (\r
+ IN NVME_DEVICE_PRIVATE_DATA *Device\r
+ )\r
+{\r
+ CopyMem (&Device->DiskInfo, &gNvmExpressDiskInfoProtocolTemplate, sizeof (EFI_DISK_INFO_PROTOCOL));\r
+}\r
+\r
+\r
+/**\r
+ Provides inquiry information for the controller type.\r
+\r
+ This function is used to get inquiry data. Data format\r
+ of Identify data is defined by the Interface GUID.\r
+\r
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.\r
+ @param[in, out] InquiryData Pointer to a buffer for the inquiry data.\r
+ @param[in, out] InquiryDataSize Pointer to the value for the inquiry data size.\r
+\r
+ @retval EFI_SUCCESS The command was accepted without any errors.\r
+ @retval EFI_NOT_FOUND Device does not support this data class\r
+ @retval EFI_DEVICE_ERROR Error reading InquiryData from device\r
+ @retval EFI_BUFFER_TOO_SMALL InquiryDataSize not big enough\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NvmExpressDiskInfoInquiry (\r
+ IN EFI_DISK_INFO_PROTOCOL *This,\r
+ IN OUT VOID *InquiryData,\r
+ IN OUT UINT32 *InquiryDataSize\r
+ )\r
+{\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+ Provides identify information for the controller type.\r
+\r
+ This function is used to get identify data. Data format\r
+ of Identify data is defined by the Interface GUID.\r
+\r
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL\r
+ instance.\r
+ @param[in, out] IdentifyData Pointer to a buffer for the identify data.\r
+ @param[in, out] IdentifyDataSize Pointer to the value for the identify data\r
+ size.\r
+\r
+ @retval EFI_SUCCESS The command was accepted without any errors.\r
+ @retval EFI_NOT_FOUND Device does not support this data class\r
+ @retval EFI_DEVICE_ERROR Error reading IdentifyData from device\r
+ @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NvmExpressDiskInfoIdentify (\r
+ IN EFI_DISK_INFO_PROTOCOL *This,\r
+ IN OUT VOID *IdentifyData,\r
+ IN OUT UINT32 *IdentifyDataSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ NVME_DEVICE_PRIVATE_DATA *Device;\r
+\r
+ Device = NVME_DEVICE_PRIVATE_DATA_FROM_DISK_INFO (This);\r
+\r
+ Status = EFI_BUFFER_TOO_SMALL;\r
+ if (*IdentifyDataSize >= sizeof (Device->NamespaceData)) {\r
+ Status = EFI_SUCCESS;\r
+ CopyMem (IdentifyData, &Device->NamespaceData, sizeof (Device->NamespaceData));\r
+ }\r
+ *IdentifyDataSize = sizeof (Device->NamespaceData);\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Provides sense data information for the controller type.\r
+\r
+ This function is used to get sense data.\r
+ Data format of Sense data is defined by the Interface GUID.\r
+\r
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.\r
+ @param[in, out] SenseData Pointer to the SenseData.\r
+ @param[in, out] SenseDataSize Size of SenseData in bytes.\r
+ @param[out] SenseDataNumber Pointer to the value for the sense data size.\r
+\r
+ @retval EFI_SUCCESS The command was accepted without any errors.\r
+ @retval EFI_NOT_FOUND Device does not support this data class.\r
+ @retval EFI_DEVICE_ERROR Error reading SenseData from device.\r
+ @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NvmExpressDiskInfoSenseData (\r
+ IN EFI_DISK_INFO_PROTOCOL *This,\r
+ IN OUT VOID *SenseData,\r
+ IN OUT UINT32 *SenseDataSize,\r
+ OUT UINT8 *SenseDataNumber\r
+ )\r
+{\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+ This function is used to get controller information.\r
+\r
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.\r
+ @param[out] IdeChannel Pointer to the Ide Channel number. Primary or secondary.\r
+ @param[out] IdeDevice Pointer to the Ide Device number. Master or slave.\r
+\r
+ @retval EFI_SUCCESS IdeChannel and IdeDevice are valid.\r
+ @retval EFI_UNSUPPORTED This is not an IDE device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NvmExpressDiskInfoWhichIde (\r
+ IN EFI_DISK_INFO_PROTOCOL *This,\r
+ OUT UINT32 *IdeChannel,\r
+ OUT UINT32 *IdeDevice\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
-/** @file
- Header file for EFI_DISK_INFO_PROTOCOL interface.
-
-Copyright (c) 2013, 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 _NVME_DISKINFO_H_
-#define _NVME_DISKINFO_H_
-
-/**
- Initialize the installation of DiskInfo protocol.
-
- This function prepares for the installation of DiskInfo protocol on the child handle.
- By default, it installs DiskInfo protocol with NVME interface GUID.
-
- @param[in] Device The pointer of NVME_DEVICE_PRIVATE_DATA.
-
-**/
-VOID
-InitializeDiskInfo (
- IN NVME_DEVICE_PRIVATE_DATA *Device
- );
-
-
-/**
- Provides inquiry information for the controller type.
-
- This function is used to get inquiry data. Data format
- of Identify data is defined by the Interface GUID.
-
- @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
- @param[in, out] InquiryData Pointer to a buffer for the inquiry data.
- @param[in, out] InquiryDataSize Pointer to the value for the inquiry data size.
-
- @retval EFI_SUCCESS The command was accepted without any errors.
- @retval EFI_NOT_FOUND Device does not support this data class
- @retval EFI_DEVICE_ERROR Error reading InquiryData from device
- @retval EFI_BUFFER_TOO_SMALL InquiryDataSize not big enough
-
-**/
-EFI_STATUS
-EFIAPI
-NvmExpressDiskInfoInquiry (
- IN EFI_DISK_INFO_PROTOCOL *This,
- IN OUT VOID *InquiryData,
- IN OUT UINT32 *InquiryDataSize
- );
-
-/**
- Provides identify information for the controller type.
-
- This function is used to get identify data. Data format
- of Identify data is defined by the Interface GUID.
-
- @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL
- instance.
- @param[in, out] IdentifyData Pointer to a buffer for the identify data.
- @param[in, out] IdentifyDataSize Pointer to the value for the identify data
- size.
-
- @retval EFI_SUCCESS The command was accepted without any errors.
- @retval EFI_NOT_FOUND Device does not support this data class
- @retval EFI_DEVICE_ERROR Error reading IdentifyData from device
- @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough
-
-**/
-EFI_STATUS
-EFIAPI
-NvmExpressDiskInfoIdentify (
- IN EFI_DISK_INFO_PROTOCOL *This,
- IN OUT VOID *IdentifyData,
- IN OUT UINT32 *IdentifyDataSize
- );
-
-/**
- Provides sense data information for the controller type.
-
- This function is used to get sense data.
- Data format of Sense data is defined by the Interface GUID.
-
- @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
- @param[in, out] SenseData Pointer to the SenseData.
- @param[in, out] SenseDataSize Size of SenseData in bytes.
- @param[out] SenseDataNumber Pointer to the value for the sense data size.
-
- @retval EFI_SUCCESS The command was accepted without any errors.
- @retval EFI_NOT_FOUND Device does not support this data class.
- @retval EFI_DEVICE_ERROR Error reading SenseData from device.
- @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough.
-
-**/
-EFI_STATUS
-EFIAPI
-NvmExpressDiskInfoSenseData (
- IN EFI_DISK_INFO_PROTOCOL *This,
- IN OUT VOID *SenseData,
- IN OUT UINT32 *SenseDataSize,
- OUT UINT8 *SenseDataNumber
- );
-
-
-/**
- This function is used to get controller information.
-
- @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
- @param[out] IdeChannel Pointer to the Ide Channel number. Primary or secondary.
- @param[out] IdeDevice Pointer to the Ide Device number. Master or slave.
-
- @retval EFI_SUCCESS IdeChannel and IdeDevice are valid.
- @retval EFI_UNSUPPORTED This is not an IDE device.
-
-**/
-EFI_STATUS
-EFIAPI
-NvmExpressDiskInfoWhichIde (
- IN EFI_DISK_INFO_PROTOCOL *This,
- OUT UINT32 *IdeChannel,
- OUT UINT32 *IdeDevice
- );
-
-#endif
+/** @file\r
+ Header file for EFI_DISK_INFO_PROTOCOL interface.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _NVME_DISKINFO_H_\r
+#define _NVME_DISKINFO_H_\r
+\r
+/**\r
+ Initialize the installation of DiskInfo protocol.\r
+\r
+ This function prepares for the installation of DiskInfo protocol on the child handle.\r
+ By default, it installs DiskInfo protocol with NVME interface GUID.\r
+\r
+ @param[in] Device The pointer of NVME_DEVICE_PRIVATE_DATA.\r
+\r
+**/\r
+VOID\r
+InitializeDiskInfo (\r
+ IN NVME_DEVICE_PRIVATE_DATA *Device\r
+ );\r
+\r
+\r
+/**\r
+ Provides inquiry information for the controller type.\r
+\r
+ This function is used to get inquiry data. Data format\r
+ of Identify data is defined by the Interface GUID.\r
+\r
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.\r
+ @param[in, out] InquiryData Pointer to a buffer for the inquiry data.\r
+ @param[in, out] InquiryDataSize Pointer to the value for the inquiry data size.\r
+\r
+ @retval EFI_SUCCESS The command was accepted without any errors.\r
+ @retval EFI_NOT_FOUND Device does not support this data class\r
+ @retval EFI_DEVICE_ERROR Error reading InquiryData from device\r
+ @retval EFI_BUFFER_TOO_SMALL InquiryDataSize not big enough\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NvmExpressDiskInfoInquiry (\r
+ IN EFI_DISK_INFO_PROTOCOL *This,\r
+ IN OUT VOID *InquiryData,\r
+ IN OUT UINT32 *InquiryDataSize\r
+ );\r
+\r
+/**\r
+ Provides identify information for the controller type.\r
+\r
+ This function is used to get identify data. Data format\r
+ of Identify data is defined by the Interface GUID.\r
+\r
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL\r
+ instance.\r
+ @param[in, out] IdentifyData Pointer to a buffer for the identify data.\r
+ @param[in, out] IdentifyDataSize Pointer to the value for the identify data\r
+ size.\r
+\r
+ @retval EFI_SUCCESS The command was accepted without any errors.\r
+ @retval EFI_NOT_FOUND Device does not support this data class\r
+ @retval EFI_DEVICE_ERROR Error reading IdentifyData from device\r
+ @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NvmExpressDiskInfoIdentify (\r
+ IN EFI_DISK_INFO_PROTOCOL *This,\r
+ IN OUT VOID *IdentifyData,\r
+ IN OUT UINT32 *IdentifyDataSize\r
+ );\r
+\r
+/**\r
+ Provides sense data information for the controller type.\r
+\r
+ This function is used to get sense data.\r
+ Data format of Sense data is defined by the Interface GUID.\r
+\r
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.\r
+ @param[in, out] SenseData Pointer to the SenseData.\r
+ @param[in, out] SenseDataSize Size of SenseData in bytes.\r
+ @param[out] SenseDataNumber Pointer to the value for the sense data size.\r
+\r
+ @retval EFI_SUCCESS The command was accepted without any errors.\r
+ @retval EFI_NOT_FOUND Device does not support this data class.\r
+ @retval EFI_DEVICE_ERROR Error reading SenseData from device.\r
+ @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NvmExpressDiskInfoSenseData (\r
+ IN EFI_DISK_INFO_PROTOCOL *This,\r
+ IN OUT VOID *SenseData,\r
+ IN OUT UINT32 *SenseDataSize,\r
+ OUT UINT8 *SenseDataNumber\r
+ );\r
+\r
+\r
+/**\r
+ This function is used to get controller information.\r
+\r
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.\r
+ @param[out] IdeChannel Pointer to the Ide Channel number. Primary or secondary.\r
+ @param[out] IdeDevice Pointer to the Ide Device number. Master or slave.\r
+\r
+ @retval EFI_SUCCESS IdeChannel and IdeDevice are valid.\r
+ @retval EFI_UNSUPPORTED This is not an IDE device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NvmExpressDiskInfoWhichIde (\r
+ IN EFI_DISK_INFO_PROTOCOL *This,\r
+ OUT UINT32 *IdeChannel,\r
+ OUT UINT32 *IdeDevice\r
+ );\r
+\r
+#endif\r
-/** @file
- The XHCI controller driver.
-
-Copyright (c) 2011 - 2013, 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"
-
-//
-// Two arrays used to translate the XHCI port state (change)
-// to the UEFI protocol's port state (change).
-//
-USB_PORT_STATE_MAP mUsbPortStateMap[] = {
- {XHC_PORTSC_CCS, USB_PORT_STAT_CONNECTION},
- {XHC_PORTSC_PED, USB_PORT_STAT_ENABLE},
- {XHC_PORTSC_OCA, USB_PORT_STAT_OVERCURRENT},
- {XHC_PORTSC_RESET, USB_PORT_STAT_RESET}
-};
-
-USB_PORT_STATE_MAP mUsbPortChangeMap[] = {
- {XHC_PORTSC_CSC, USB_PORT_STAT_C_CONNECTION},
- {XHC_PORTSC_PEC, USB_PORT_STAT_C_ENABLE},
- {XHC_PORTSC_OCC, USB_PORT_STAT_C_OVERCURRENT},
- {XHC_PORTSC_PRC, USB_PORT_STAT_C_RESET}
-};
-
-USB_CLEAR_PORT_MAP mUsbClearPortChangeMap[] = {
- {XHC_PORTSC_CSC, EfiUsbPortConnectChange},
- {XHC_PORTSC_PEC, EfiUsbPortEnableChange},
- {XHC_PORTSC_OCC, EfiUsbPortOverCurrentChange},
- {XHC_PORTSC_PRC, EfiUsbPortResetChange}
-};
-
-USB_PORT_STATE_MAP mUsbHubPortStateMap[] = {
- {XHC_HUB_PORTSC_CCS, USB_PORT_STAT_CONNECTION},
- {XHC_HUB_PORTSC_PED, USB_PORT_STAT_ENABLE},
- {XHC_HUB_PORTSC_OCA, USB_PORT_STAT_OVERCURRENT},
- {XHC_HUB_PORTSC_RESET, USB_PORT_STAT_RESET}
-};
-
-USB_PORT_STATE_MAP mUsbHubPortChangeMap[] = {
- {XHC_HUB_PORTSC_CSC, USB_PORT_STAT_C_CONNECTION},
- {XHC_HUB_PORTSC_PEC, USB_PORT_STAT_C_ENABLE},
- {XHC_HUB_PORTSC_OCC, USB_PORT_STAT_C_OVERCURRENT},
- {XHC_HUB_PORTSC_PRC, USB_PORT_STAT_C_RESET}
-};
-
-USB_CLEAR_PORT_MAP mUsbHubClearPortChangeMap[] = {
- {XHC_HUB_PORTSC_CSC, EfiUsbPortConnectChange},
- {XHC_HUB_PORTSC_PEC, EfiUsbPortEnableChange},
- {XHC_HUB_PORTSC_OCC, EfiUsbPortOverCurrentChange},
- {XHC_HUB_PORTSC_PRC, EfiUsbPortResetChange},
- {XHC_HUB_PORTSC_BHRC, Usb3PortBHPortResetChange}
-};
-
-EFI_DRIVER_BINDING_PROTOCOL gXhciDriverBinding = {
- XhcDriverBindingSupported,
- XhcDriverBindingStart,
- XhcDriverBindingStop,
- 0x30,
- NULL,
- NULL
-};
-
-//
-// Template for Xhci's Usb2 Host Controller Protocol Instance.
-//
-EFI_USB2_HC_PROTOCOL gXhciUsb2HcTemplate = {
- XhcGetCapability,
- XhcReset,
- XhcGetState,
- XhcSetState,
- XhcControlTransfer,
- XhcBulkTransfer,
- XhcAsyncInterruptTransfer,
- XhcSyncInterruptTransfer,
- XhcIsochronousTransfer,
- XhcAsyncIsochronousTransfer,
- XhcGetRootHubPortStatus,
- XhcSetRootHubPortFeature,
- XhcClearRootHubPortFeature,
- 0x3,
- 0x0
-};
-
-/**
- Retrieves the capability of root hub ports.
-
- @param This The EFI_USB2_HC_PROTOCOL instance.
- @param MaxSpeed Max speed supported by the controller.
- @param PortNumber Number of the root hub ports.
- @param Is64BitCapable Whether the controller supports 64-bit memory
- addressing.
-
- @retval EFI_SUCCESS Host controller capability were retrieved successfully.
- @retval EFI_INVALID_PARAMETER Either of the three capability pointer is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-XhcGetCapability (
- IN EFI_USB2_HC_PROTOCOL *This,
- OUT UINT8 *MaxSpeed,
- OUT UINT8 *PortNumber,
- OUT UINT8 *Is64BitCapable
- )
-{
- USB_XHCI_INSTANCE *Xhc;
- EFI_TPL OldTpl;
-
- if ((MaxSpeed == NULL) || (PortNumber == NULL) || (Is64BitCapable == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- OldTpl = gBS->RaiseTPL (XHC_TPL);
-
- Xhc = XHC_FROM_THIS (This);
- *MaxSpeed = EFI_USB_SPEED_SUPER;
- *PortNumber = (UINT8) (Xhc->HcSParams1.Data.MaxPorts);
- *Is64BitCapable = (UINT8) (Xhc->HcCParams.Data.Ac64);
- DEBUG ((EFI_D_INFO, "XhcGetCapability: %d ports, 64 bit %d\n", *PortNumber, *Is64BitCapable));
-
- gBS->RestoreTPL (OldTpl);
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Provides software reset for the USB host controller.
-
- @param This This EFI_USB2_HC_PROTOCOL instance.
- @param Attributes A bit mask of the reset operation to perform.
-
- @retval EFI_SUCCESS The reset operation succeeded.
- @retval EFI_INVALID_PARAMETER Attributes is not valid.
- @retval EFI_UNSUPPOURTED The type of reset specified by Attributes is
- not currently supported by the host controller.
- @retval EFI_DEVICE_ERROR Host controller isn't halted to reset.
-
-**/
-EFI_STATUS
-EFIAPI
-XhcReset (
- IN EFI_USB2_HC_PROTOCOL *This,
- IN UINT16 Attributes
- )
-{
- USB_XHCI_INSTANCE *Xhc;
- EFI_STATUS Status;
- EFI_TPL OldTpl;
-
- Xhc = XHC_FROM_THIS (This);
-
- if (Xhc->DevicePath != NULL) {
- //
- // Report Status Code to indicate reset happens
- //
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (
- EFI_PROGRESS_CODE,
- (EFI_IO_BUS_USB | EFI_IOB_PC_RESET),
- Xhc->DevicePath
- );
- }
-
- OldTpl = gBS->RaiseTPL (XHC_TPL);
-
- switch (Attributes) {
- case EFI_USB_HC_RESET_GLOBAL:
- //
- // Flow through, same behavior as Host Controller Reset
- //
- case EFI_USB_HC_RESET_HOST_CONTROLLER:
- if ((Xhc->DebugCapSupOffset != 0xFFFFFFFF) && ((XhcReadExtCapReg (Xhc, Xhc->DebugCapSupOffset) & 0xFF) == XHC_CAP_USB_DEBUG) &&
- ((XhcReadExtCapReg (Xhc, Xhc->DebugCapSupOffset + XHC_DC_DCCTRL) & BIT0) != 0)) {
- Status = EFI_SUCCESS;
- goto ON_EXIT;
- }
- //
- // Host Controller must be Halt when Reset it
- //
- if (!XhcIsHalt (Xhc)) {
- Status = XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);
-
- if (EFI_ERROR (Status)) {
- Status = EFI_DEVICE_ERROR;
- goto ON_EXIT;
- }
- }
-
- Status = XhcResetHC (Xhc, XHC_RESET_TIMEOUT);
- ASSERT (!(XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_CNR)));
-
- if (EFI_ERROR (Status)) {
- goto ON_EXIT;
- }
- //
- // Clean up the asynchronous transfers, currently only
- // interrupt supports asynchronous operation.
- //
- XhciDelAllAsyncIntTransfers (Xhc);
- XhcFreeSched (Xhc);
-
- XhcInitSched (Xhc);
- break;
-
- case EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG:
- case EFI_USB_HC_RESET_HOST_WITH_DEBUG:
- Status = EFI_UNSUPPORTED;
- break;
-
- default:
- Status = EFI_INVALID_PARAMETER;
- }
-
-ON_EXIT:
- DEBUG ((EFI_D_INFO, "XhcReset: status %r\n", Status));
- gBS->RestoreTPL (OldTpl);
-
- return Status;
-}
-
-
-/**
- Retrieve the current state of the USB host controller.
-
- @param This This EFI_USB2_HC_PROTOCOL instance.
- @param State Variable to return the current host controller
- state.
-
- @retval EFI_SUCCESS Host controller state was returned in State.
- @retval EFI_INVALID_PARAMETER State is NULL.
- @retval EFI_DEVICE_ERROR An error was encountered while attempting to
- retrieve the host controller's current state.
-
-**/
-EFI_STATUS
-EFIAPI
-XhcGetState (
- IN EFI_USB2_HC_PROTOCOL *This,
- OUT EFI_USB_HC_STATE *State
- )
-{
- USB_XHCI_INSTANCE *Xhc;
- EFI_TPL OldTpl;
-
- if (State == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- OldTpl = gBS->RaiseTPL (XHC_TPL);
-
- Xhc = XHC_FROM_THIS (This);
-
- if (XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT)) {
- *State = EfiUsbHcStateHalt;
- } else {
- *State = EfiUsbHcStateOperational;
- }
-
- DEBUG ((EFI_D_INFO, "XhcGetState: current state %d\n", *State));
- gBS->RestoreTPL (OldTpl);
-
- return EFI_SUCCESS;
-}
-
-/**
- Sets the USB host controller to a specific state.
-
- @param This This EFI_USB2_HC_PROTOCOL instance.
- @param State The state of the host controller that will be set.
-
- @retval EFI_SUCCESS The USB host controller was successfully placed
- in the state specified by State.
- @retval EFI_INVALID_PARAMETER State is invalid.
- @retval EFI_DEVICE_ERROR Failed to set the state due to device error.
-
-**/
-EFI_STATUS
-EFIAPI
-XhcSetState (
- IN EFI_USB2_HC_PROTOCOL *This,
- IN EFI_USB_HC_STATE State
- )
-{
- USB_XHCI_INSTANCE *Xhc;
- EFI_STATUS Status;
- EFI_USB_HC_STATE CurState;
- EFI_TPL OldTpl;
-
- Status = XhcGetState (This, &CurState);
-
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
-
- if (CurState == State) {
- return EFI_SUCCESS;
- }
-
- OldTpl = gBS->RaiseTPL (XHC_TPL);
-
- Xhc = XHC_FROM_THIS (This);
-
- switch (State) {
- case EfiUsbHcStateHalt:
- Status = XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);
- break;
-
- case EfiUsbHcStateOperational:
- if (XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HSE)) {
- Status = EFI_DEVICE_ERROR;
- break;
- }
-
- //
- // Software must not write a one to this field unless the host controller
- // is in the Halted state. Doing so will yield undefined results.
- // refers to Spec[XHCI1.0-2.3.1]
- //
- if (!XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT)) {
- Status = EFI_DEVICE_ERROR;
- break;
- }
-
- Status = XhcRunHC (Xhc, XHC_GENERIC_TIMEOUT);
- break;
-
- case EfiUsbHcStateSuspend:
- Status = EFI_UNSUPPORTED;
- break;
-
- default:
- Status = EFI_INVALID_PARAMETER;
- }
-
- DEBUG ((EFI_D_INFO, "XhcSetState: status %r\n", Status));
- gBS->RestoreTPL (OldTpl);
-
- return Status;
-}
-
-/**
- Retrieves the current status of a USB root hub port.
-
- @param This This EFI_USB2_HC_PROTOCOL instance.
- @param PortNumber The root hub port to retrieve the state from.
- This value is zero-based.
- @param PortStatus Variable to receive the port state.
-
- @retval EFI_SUCCESS The status of the USB root hub port specified.
- by PortNumber was returned in PortStatus.
- @retval EFI_INVALID_PARAMETER PortNumber is invalid.
- @retval EFI_DEVICE_ERROR Can't read register.
-
-**/
-EFI_STATUS
-EFIAPI
-XhcGetRootHubPortStatus (
- IN EFI_USB2_HC_PROTOCOL *This,
- IN UINT8 PortNumber,
- OUT EFI_USB_PORT_STATUS *PortStatus
- )
-{
- USB_XHCI_INSTANCE *Xhc;
- UINT32 Offset;
- UINT32 State;
- UINT32 TotalPort;
- UINTN Index;
- UINTN MapSize;
- EFI_STATUS Status;
- USB_DEV_ROUTE ParentRouteChart;
- EFI_TPL OldTpl;
-
- if (PortStatus == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- OldTpl = gBS->RaiseTPL (XHC_TPL);
-
- Xhc = XHC_FROM_THIS (This);
- Status = EFI_SUCCESS;
-
- TotalPort = Xhc->HcSParams1.Data.MaxPorts;
-
- if (PortNumber >= TotalPort) {
- Status = EFI_INVALID_PARAMETER;
- goto ON_EXIT;
- }
-
- Offset = (UINT32) (XHC_PORTSC_OFFSET + (0x10 * PortNumber));
- PortStatus->PortStatus = 0;
- PortStatus->PortChangeStatus = 0;
-
- State = XhcReadOpReg (Xhc, Offset);
-
- //
- // According to XHCI 1.0 spec, bit 10~13 of the root port status register identifies the speed of the attached device.
- //
- switch ((State & XHC_PORTSC_PS) >> 10) {
- case 2:
- PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
- break;
-
- case 3:
- PortStatus->PortStatus |= USB_PORT_STAT_HIGH_SPEED;
- break;
-
- case 4:
- PortStatus->PortStatus |= USB_PORT_STAT_SUPER_SPEED;
- break;
-
- default:
- break;
- }
-
- //
- // Convert the XHCI port/port change state to UEFI status
- //
- MapSize = sizeof (mUsbPortStateMap) / sizeof (USB_PORT_STATE_MAP);
-
- for (Index = 0; Index < MapSize; Index++) {
- if (XHC_BIT_IS_SET (State, mUsbPortStateMap[Index].HwState)) {
- PortStatus->PortStatus = (UINT16) (PortStatus->PortStatus | mUsbPortStateMap[Index].UefiState);
- }
- }
- //
- // Bit5~8 reflects its current link state.
- //
- if ((State & XHC_PORTSC_PLS) >> 5 == 3) {
- PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;
- }
-
- MapSize = sizeof (mUsbPortChangeMap) / sizeof (USB_PORT_STATE_MAP);
-
- for (Index = 0; Index < MapSize; Index++) {
- if (XHC_BIT_IS_SET (State, mUsbPortChangeMap[Index].HwState)) {
- PortStatus->PortChangeStatus = (UINT16) (PortStatus->PortChangeStatus | mUsbPortChangeMap[Index].UefiState);
- }
- }
-
- MapSize = sizeof (mUsbClearPortChangeMap) / sizeof (USB_CLEAR_PORT_MAP);
-
- for (Index = 0; Index < MapSize; Index++) {
- if (XHC_BIT_IS_SET (State, mUsbClearPortChangeMap[Index].HwState)) {
- XhcClearRootHubPortFeature (This, PortNumber, (EFI_USB_PORT_FEATURE)mUsbClearPortChangeMap[Index].Selector);
- }
- }
-
- //
- // Poll the root port status register to enable/disable corresponding device slot if there is a device attached/detached.
- // For those devices behind hub, we get its attach/detach event by hooking Get_Port_Status request at control transfer for those hub.
- //
- ParentRouteChart.Dword = 0;
- XhcPollPortStatusChange (Xhc, ParentRouteChart, PortNumber, PortStatus);
-
-ON_EXIT:
- gBS->RestoreTPL (OldTpl);
- return Status;
-}
-
-
-/**
- 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
- )
-{
- USB_XHCI_INSTANCE *Xhc;
- UINT32 Offset;
- UINT32 State;
- UINT32 TotalPort;
- EFI_STATUS Status;
- EFI_TPL OldTpl;
-
- OldTpl = gBS->RaiseTPL (XHC_TPL);
-
- Xhc = XHC_FROM_THIS (This);
- Status = EFI_SUCCESS;
-
- TotalPort = (Xhc->HcSParams1.Data.MaxPorts);
-
- if (PortNumber >= TotalPort) {
- Status = EFI_INVALID_PARAMETER;
- goto ON_EXIT;
- }
-
- Offset = (UINT32) (XHC_PORTSC_OFFSET + (0x10 * PortNumber));
- State = XhcReadOpReg (Xhc, Offset);
-
- //
- // Mask off the port status change bits, these bits are
- // write clean bit
- //
- State &= ~ (BIT1 | BIT17 | BIT18 | BIT19 | BIT20 | BIT21 | BIT22 | BIT23);
-
- switch (PortFeature) {
- case EfiUsbPortEnable:
- //
- // Ports may only be enabled by the xHC. Software cannot enable a port by writing a '1' to this flag.
- // A port may be disabled by software writing a '1' to this flag.
- //
- Status = EFI_SUCCESS;
- break;
-
- case EfiUsbPortSuspend:
- State |= XHC_PORTSC_LWS;
- XhcWriteOpReg (Xhc, Offset, State);
- State &= ~XHC_PORTSC_PLS;
- State |= (3 << 5) ;
- XhcWriteOpReg (Xhc, Offset, State);
- break;
-
- case EfiUsbPortReset:
- DEBUG ((EFI_D_INFO, "XhcUsbPortReset!\n"));
- //
- // Make sure Host Controller not halt before reset it
- //
- if (XhcIsHalt (Xhc)) {
- Status = XhcRunHC (Xhc, XHC_GENERIC_TIMEOUT);
-
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_INFO, "XhcSetRootHubPortFeature :failed to start HC - %r\n", Status));
- break;
- }
- }
-
- //
- // 4.3.1 Resetting a Root Hub Port
- // 1) Write the PORTSC register with the Port Reset (PR) bit set to '1'.
- //
- State |= XHC_PORTSC_RESET;
- XhcWriteOpReg (Xhc, Offset, State);
- XhcWaitOpRegBit(Xhc, Offset, XHC_PORTSC_PRC, TRUE, XHC_GENERIC_TIMEOUT);
- break;
-
- case EfiUsbPortPower:
- //
- // Not supported, ignore the operation
- //
- Status = EFI_SUCCESS;
- break;
-
- case EfiUsbPortOwner:
- //
- // XHCI root hub port don't has the owner bit, ignore the operation
- //
- Status = EFI_SUCCESS;
- break;
-
- default:
- Status = EFI_INVALID_PARAMETER;
- }
-
-ON_EXIT:
- DEBUG ((EFI_D_INFO, "XhcSetRootHubPortFeature: status %r\n", Status));
- gBS->RestoreTPL (OldTpl);
-
- return Status;
-}
-
-
-/**
- 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
- )
-{
- USB_XHCI_INSTANCE *Xhc;
- UINT32 Offset;
- UINT32 State;
- UINT32 TotalPort;
- EFI_STATUS Status;
- EFI_TPL OldTpl;
-
- OldTpl = gBS->RaiseTPL (XHC_TPL);
-
- Xhc = XHC_FROM_THIS (This);
- Status = EFI_SUCCESS;
-
- TotalPort = (Xhc->HcSParams1.Data.MaxPorts);
-
- if (PortNumber >= TotalPort) {
- Status = EFI_INVALID_PARAMETER;
- goto ON_EXIT;
- }
-
- Offset = XHC_PORTSC_OFFSET + (0x10 * PortNumber);
-
- //
- // Mask off the port status change bits, these bits are
- // write clean bit
- //
- State = XhcReadOpReg (Xhc, Offset);
- State &= ~ (BIT1 | BIT17 | BIT18 | BIT19 | BIT20 | BIT21 | BIT22 | BIT23);
-
- switch (PortFeature) {
- case EfiUsbPortEnable:
- //
- // Ports may only be enabled by the xHC. Software cannot enable a port by writing a '1' to this flag.
- // A port may be disabled by software writing a '1' to this flag.
- //
- State |= XHC_PORTSC_PED;
- State &= ~XHC_PORTSC_RESET;
- XhcWriteOpReg (Xhc, Offset, State);
- break;
-
- case EfiUsbPortSuspend:
- State |= XHC_PORTSC_LWS;
- XhcWriteOpReg (Xhc, Offset, State);
- State &= ~XHC_PORTSC_PLS;
- XhcWriteOpReg (Xhc, Offset, State);
- break;
-
- case EfiUsbPortReset:
- //
- // PORTSC_RESET BIT(4) bit is RW1S attribute, which means Write-1-to-set status:
- // Register bits indicate status when read, a clear bit may be set by
- // writing a '1'. Writing a '0' to RW1S bits has no effect.
- //
- break;
-
- case EfiUsbPortOwner:
- //
- // XHCI root hub port don't has the owner bit, ignore the operation
- //
- break;
-
- case EfiUsbPortConnectChange:
- //
- // Clear connect status change
- //
- State |= XHC_PORTSC_CSC;
- XhcWriteOpReg (Xhc, Offset, State);
- break;
-
- case EfiUsbPortEnableChange:
- //
- // Clear enable status change
- //
- State |= XHC_PORTSC_PEC;
- XhcWriteOpReg (Xhc, Offset, State);
- break;
-
- case EfiUsbPortOverCurrentChange:
- //
- // Clear PortOverCurrent change
- //
- State |= XHC_PORTSC_OCC;
- XhcWriteOpReg (Xhc, Offset, State);
- break;
-
- case EfiUsbPortResetChange:
- //
- // Clear Port Reset change
- //
- State |= XHC_PORTSC_PRC;
- XhcWriteOpReg (Xhc, Offset, State);
- break;
-
- case EfiUsbPortPower:
- case EfiUsbPortSuspendChange:
- //
- // Not supported or not related operation
- //
- break;
-
- default:
- Status = EFI_INVALID_PARAMETER;
- break;
- }
-
-ON_EXIT:
- DEBUG ((EFI_D_INFO, "XhcClearRootHubPortFeature: status %r\n", Status));
- gBS->RestoreTPL (OldTpl);
-
- return Status;
-}
-
-
-/**
- Submits control transfer to a target USB device.
-
- @param This This EFI_USB2_HC_PROTOCOL instance.
- @param DeviceAddress The target device address.
- @param DeviceSpeed Target device speed.
- @param MaximumPacketLength Maximum packet size the default control transfer
- endpoint is capable of sending or receiving.
- @param Request USB device request to send.
- @param TransferDirection Specifies the data direction for the data stage
- @param Data Data buffer to be transmitted or received from USB
- device.
- @param DataLength The size (in bytes) of the data buffer.
- @param Timeout Indicates the maximum timeout, in millisecond.
- @param Translator Transaction translator to be used by this device.
- @param TransferResult Return the result of this control transfer.
-
- @retval EFI_SUCCESS Transfer was completed successfully.
- @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
- @retval EFI_INVALID_PARAMETER Some parameters are invalid.
- @retval EFI_TIMEOUT Transfer failed due to timeout.
- @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
-
-**/
-EFI_STATUS
-EFIAPI
-XhcControlTransfer (
- IN EFI_USB2_HC_PROTOCOL *This,
- IN UINT8 DeviceAddress,
- IN UINT8 DeviceSpeed,
- IN UINTN MaximumPacketLength,
- IN EFI_USB_DEVICE_REQUEST *Request,
- IN EFI_USB_DATA_DIRECTION TransferDirection,
- IN OUT VOID *Data,
- IN OUT UINTN *DataLength,
- IN UINTN Timeout,
- IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
- OUT UINT32 *TransferResult
- )
-{
- USB_XHCI_INSTANCE *Xhc;
- URB *Urb;
- UINT8 Endpoint;
- UINT8 Index;
- UINT8 DescriptorType;
- UINT8 SlotId;
- UINT8 TTT;
- UINT8 MTT;
- UINT32 MaxPacket0;
- EFI_USB_HUB_DESCRIPTOR *HubDesc;
- EFI_TPL OldTpl;
- EFI_STATUS Status;
- EFI_STATUS RecoveryStatus;
- UINTN MapSize;
- EFI_USB_PORT_STATUS PortStatus;
- UINT32 State;
- EFI_USB_DEVICE_REQUEST ClearPortRequest;
- UINTN Len;
-
- //
- // Validate parameters
- //
- if ((Request == NULL) || (TransferResult == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((TransferDirection != EfiUsbDataIn) &&
- (TransferDirection != EfiUsbDataOut) &&
- (TransferDirection != EfiUsbNoData)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((TransferDirection == EfiUsbNoData) &&
- ((Data != NULL) || (*DataLength != 0))) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((TransferDirection != EfiUsbNoData) &&
- ((Data == NULL) || (*DataLength == 0))) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((MaximumPacketLength != 8) && (MaximumPacketLength != 16) &&
- (MaximumPacketLength != 32) && (MaximumPacketLength != 64) &&
- (MaximumPacketLength != 512)
- ) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((DeviceSpeed == EFI_USB_SPEED_SUPER) && (MaximumPacketLength != 512)) {
- return EFI_INVALID_PARAMETER;
- }
-
- OldTpl = gBS->RaiseTPL (XHC_TPL);
-
- Xhc = XHC_FROM_THIS (This);
-
- Status = EFI_DEVICE_ERROR;
- *TransferResult = EFI_USB_ERR_SYSTEM;
- Len = 0;
-
- if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {
- DEBUG ((EFI_D_ERROR, "XhcControlTransfer: HC halted at entrance\n"));
- goto ON_EXIT;
- }
-
- //
- // Check if the device is still enabled before every transaction.
- //
- SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);
- if (SlotId == 0) {
- goto ON_EXIT;
- }
-
- //
- // Hook the Set_Address request from UsbBus.
- // According to XHCI 1.0 spec, the Set_Address request is replaced by XHCI's Address_Device cmd.
- //
- if ((Request->Request == USB_REQ_SET_ADDRESS) &&
- (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE))) {
- //
- // Reset the BusDevAddr field of all disabled entries in UsbDevContext array firstly.
- // This way is used to clean the history to avoid using wrong device address by XhcAsyncInterruptTransfer().
- //
- for (Index = 0; Index < 255; Index++) {
- if (!Xhc->UsbDevContext[Index + 1].Enabled &&
- (Xhc->UsbDevContext[Index + 1].SlotId == 0) &&
- (Xhc->UsbDevContext[Index + 1].BusDevAddr == (UINT8)Request->Value)) {
- Xhc->UsbDevContext[Index + 1].BusDevAddr = 0;
- }
- }
-
- if (Xhc->UsbDevContext[SlotId].XhciDevAddr == 0) {
- Status = EFI_DEVICE_ERROR;
- goto ON_EXIT;
- }
- //
- // The actual device address has been assigned by XHCI during initializing the device slot.
- // So we just need establish the mapping relationship between the device address requested from UsbBus
- // and the actual device address assigned by XHCI. The the following invocations through EFI_USB2_HC_PROTOCOL interface
- // can find out the actual device address by it.
- //
- Xhc->UsbDevContext[SlotId].BusDevAddr = (UINT8)Request->Value;
- Status = EFI_SUCCESS;
- goto ON_EXIT;
- }
-
- //
- // Create a new URB, insert it into the asynchronous
- // schedule list, then poll the execution status.
- // Note that we encode the direction in address although default control
- // endpoint is bidirectional. XhcCreateUrb expects this
- // combination of Ep addr and its direction.
- //
- Endpoint = (UINT8) (0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0));
- Urb = XhcCreateUrb (
- Xhc,
- DeviceAddress,
- Endpoint,
- DeviceSpeed,
- MaximumPacketLength,
- XHC_CTRL_TRANSFER,
- Request,
- Data,
- *DataLength,
- NULL,
- NULL
- );
-
- if (Urb == NULL) {
- DEBUG ((EFI_D_ERROR, "XhcControlTransfer: failed to create URB"));
- Status = EFI_OUT_OF_RESOURCES;
- goto ON_EXIT;
- }
-
- Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);
-
- //
- // Get the status from URB. The result is updated in XhcCheckUrbResult
- // which is called by XhcExecTransfer
- //
- *TransferResult = Urb->Result;
- *DataLength = Urb->Completed;
-
- if (*TransferResult == EFI_USB_NOERROR) {
- Status = EFI_SUCCESS;
- } else if (*TransferResult == EFI_USB_ERR_STALL) {
- RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
- if (EFI_ERROR (RecoveryStatus)) {
- DEBUG ((EFI_D_ERROR, "XhcControlTransfer: XhcRecoverHaltedEndpoint failed\n"));
- }
- Status = EFI_DEVICE_ERROR;
- goto FREE_URB;
- } else {
- goto FREE_URB;
- }
-
- Xhc->PciIo->Flush (Xhc->PciIo);
-
- if (Urb->DataMap != NULL) {
- Status = Xhc->PciIo->Unmap (Xhc->PciIo, Urb->DataMap);
- ASSERT_EFI_ERROR (Status);
- if (EFI_ERROR (Status)) {
- Status = EFI_DEVICE_ERROR;
- goto FREE_URB;
- }
- }
-
- //
- // Hook Get_Descriptor request from UsbBus as we need evaluate context and configure endpoint.
- // Hook Get_Status request form UsbBus as we need trace device attach/detach event happened at hub.
- // Hook Set_Config request from UsbBus as we need configure device endpoint.
- //
- if ((Request->Request == USB_REQ_GET_DESCRIPTOR) &&
- ((Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE)) ||
- ((Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_CLASS, USB_TARGET_DEVICE))))) {
- DescriptorType = (UINT8)(Request->Value >> 8);
- if ((DescriptorType == USB_DESC_TYPE_DEVICE) && ((*DataLength == sizeof (EFI_USB_DEVICE_DESCRIPTOR)) || ((DeviceSpeed == EFI_USB_SPEED_FULL) && (*DataLength == 8)))) {
- ASSERT (Data != NULL);
- //
- // Store a copy of device scriptor as hub device need this info to configure endpoint.
- //
- CopyMem (&Xhc->UsbDevContext[SlotId].DevDesc, Data, *DataLength);
- if (Xhc->UsbDevContext[SlotId].DevDesc.BcdUSB == 0x0300) {
- //
- // If it's a usb3.0 device, then its max packet size is a 2^n.
- //
- MaxPacket0 = 1 << Xhc->UsbDevContext[SlotId].DevDesc.MaxPacketSize0;
- } else {
- MaxPacket0 = Xhc->UsbDevContext[SlotId].DevDesc.MaxPacketSize0;
- }
- Xhc->UsbDevContext[SlotId].ConfDesc = AllocateZeroPool (Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations * sizeof (EFI_USB_CONFIG_DESCRIPTOR *));
- if (Xhc->HcCParams.Data.Csz == 0) {
- Status = XhcEvaluateContext (Xhc, SlotId, MaxPacket0);
- } else {
- Status = XhcEvaluateContext64 (Xhc, SlotId, MaxPacket0);
- }
- } else if (DescriptorType == USB_DESC_TYPE_CONFIG) {
- ASSERT (Data != NULL);
- if (*DataLength == ((UINT16 *)Data)[1]) {
- //
- // Get configuration value from request, Store the configuration descriptor for Configure_Endpoint cmd.
- //
- Index = (UINT8)Request->Value;
- ASSERT (Index < Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations);
- Xhc->UsbDevContext[SlotId].ConfDesc[Index] = AllocateZeroPool(*DataLength);
- CopyMem (Xhc->UsbDevContext[SlotId].ConfDesc[Index], Data, *DataLength);
- }
- } else if (((DescriptorType == USB_DESC_TYPE_HUB) ||
- (DescriptorType == USB_DESC_TYPE_HUB_SUPER_SPEED)) && (*DataLength > 2)) {
- ASSERT (Data != NULL);
- HubDesc = (EFI_USB_HUB_DESCRIPTOR *)Data;
- ASSERT (HubDesc->NumPorts <= 15);
- //
- // The bit 5,6 of HubCharacter field of Hub Descriptor is TTT.
- //
- TTT = (UINT8)((HubDesc->HubCharacter & (BIT5 | BIT6)) >> 5);
- if (Xhc->UsbDevContext[SlotId].DevDesc.DeviceProtocol == 2) {
- //
- // Don't support multi-TT feature for super speed hub now.
- //
- MTT = 0;
- DEBUG ((EFI_D_ERROR, "XHCI: Don't support multi-TT feature for Hub now. (force to disable MTT)\n"));
- } else {
- MTT = 0;
- }
-
- if (Xhc->HcCParams.Data.Csz == 0) {
- Status = XhcConfigHubContext (Xhc, SlotId, HubDesc->NumPorts, TTT, MTT);
- } else {
- Status = XhcConfigHubContext64 (Xhc, SlotId, HubDesc->NumPorts, TTT, MTT);
- }
- }
- } else if ((Request->Request == USB_REQ_SET_CONFIG) &&
- (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE))) {
- //
- // Hook Set_Config request from UsbBus as we need configure device endpoint.
- //
- for (Index = 0; Index < Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations; Index++) {
- if (Xhc->UsbDevContext[SlotId].ConfDesc[Index]->ConfigurationValue == (UINT8)Request->Value) {
- if (Xhc->HcCParams.Data.Csz == 0) {
- Status = XhcSetConfigCmd (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Index]);
- } else {
- Status = XhcSetConfigCmd64 (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Index]);
- }
- break;
- }
- }
- } else if ((Request->Request == USB_REQ_GET_STATUS) &&
- (Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER))) {
- ASSERT (Data != NULL);
- //
- // Hook Get_Status request from UsbBus to keep track of the port status change.
- //
- State = *(UINT32 *)Data;
- PortStatus.PortStatus = 0;
- PortStatus.PortChangeStatus = 0;
-
- if (DeviceSpeed == EFI_USB_SPEED_SUPER) {
- //
- // For super speed hub, its bit10~12 presents the attached device speed.
- //
- if ((State & XHC_PORTSC_PS) >> 10 == 0) {
- PortStatus.PortStatus |= USB_PORT_STAT_SUPER_SPEED;
- }
- } else {
- //
- // For high or full/low speed hub, its bit9~10 presents the attached device speed.
- //
- if (XHC_BIT_IS_SET (State, BIT9)) {
- PortStatus.PortStatus |= USB_PORT_STAT_LOW_SPEED;
- } else if (XHC_BIT_IS_SET (State, BIT10)) {
- PortStatus.PortStatus |= USB_PORT_STAT_HIGH_SPEED;
- }
- }
-
- //
- // Convert the XHCI port/port change state to UEFI status
- //
- MapSize = sizeof (mUsbHubPortStateMap) / sizeof (USB_PORT_STATE_MAP);
- for (Index = 0; Index < MapSize; Index++) {
- if (XHC_BIT_IS_SET (State, mUsbHubPortStateMap[Index].HwState)) {
- PortStatus.PortStatus = (UINT16) (PortStatus.PortStatus | mUsbHubPortStateMap[Index].UefiState);
- }
- }
-
- MapSize = sizeof (mUsbHubPortChangeMap) / sizeof (USB_PORT_STATE_MAP);
- for (Index = 0; Index < MapSize; Index++) {
- if (XHC_BIT_IS_SET (State, mUsbHubPortChangeMap[Index].HwState)) {
- PortStatus.PortChangeStatus = (UINT16) (PortStatus.PortChangeStatus | mUsbHubPortChangeMap[Index].UefiState);
- }
- }
-
- MapSize = sizeof (mUsbHubClearPortChangeMap) / sizeof (USB_CLEAR_PORT_MAP);
-
- for (Index = 0; Index < MapSize; Index++) {
- if (XHC_BIT_IS_SET (State, mUsbHubClearPortChangeMap[Index].HwState)) {
- ZeroMem (&ClearPortRequest, sizeof (EFI_USB_DEVICE_REQUEST));
- ClearPortRequest.RequestType = USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER);
- ClearPortRequest.Request = (UINT8) USB_REQ_CLEAR_FEATURE;
- ClearPortRequest.Value = mUsbHubClearPortChangeMap[Index].Selector;
- ClearPortRequest.Index = Request->Index;
- ClearPortRequest.Length = 0;
-
- XhcControlTransfer (
- This,
- DeviceAddress,
- DeviceSpeed,
- MaximumPacketLength,
- &ClearPortRequest,
- EfiUsbNoData,
- NULL,
- &Len,
- Timeout,
- Translator,
- TransferResult
- );
- }
- }
-
- XhcPollPortStatusChange (Xhc, Xhc->UsbDevContext[SlotId].RouteString, (UINT8)Request->Index, &PortStatus);
-
- *(UINT32 *)Data = *(UINT32*)&PortStatus;
- }
-
-FREE_URB:
- FreePool (Urb);
-
-ON_EXIT:
-
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "XhcControlTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
- }
-
- gBS->RestoreTPL (OldTpl);
-
- return Status;
-}
-
-
-/**
- Submits bulk transfer to a bulk endpoint of a USB device.
-
- @param This This EFI_USB2_HC_PROTOCOL instance.
- @param DeviceAddress Target device address.
- @param EndPointAddress Endpoint number and its direction in bit 7.
- @param DeviceSpeed Device speed, Low speed device doesn't support bulk
- transfer.
- @param MaximumPacketLength Maximum packet size the endpoint is capable of
- sending or receiving.
- @param DataBuffersNumber Number of data buffers prepared for the transfer.
- @param Data Array of pointers to the buffers of data to transmit
- from or receive into.
- @param DataLength The lenght of the data buffer.
- @param DataToggle On input, the initial data toggle for the transfer;
- On output, it is updated to to next data toggle to
- use of the subsequent bulk transfer.
- @param Timeout Indicates the maximum time, in millisecond, which
- the transfer is allowed to complete.
- @param Translator A pointr to the transaction translator data.
- @param TransferResult A pointer to the detailed result information of the
- bulk transfer.
-
- @retval EFI_SUCCESS The transfer was completed successfully.
- @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
- @retval EFI_INVALID_PARAMETER Some parameters are invalid.
- @retval EFI_TIMEOUT The transfer failed due to timeout.
- @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
-
-**/
-EFI_STATUS
-EFIAPI
-XhcBulkTransfer (
- IN EFI_USB2_HC_PROTOCOL *This,
- IN UINT8 DeviceAddress,
- IN UINT8 EndPointAddress,
- IN UINT8 DeviceSpeed,
- IN UINTN MaximumPacketLength,
- IN UINT8 DataBuffersNumber,
- IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
- IN OUT UINTN *DataLength,
- IN OUT UINT8 *DataToggle,
- IN UINTN Timeout,
- IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
- OUT UINT32 *TransferResult
- )
-{
- USB_XHCI_INSTANCE *Xhc;
- URB *Urb;
- UINT8 SlotId;
- EFI_STATUS Status;
- EFI_STATUS RecoveryStatus;
- EFI_TPL OldTpl;
-
- //
- // Validate the parameters
- //
- if ((DataLength == NULL) || (*DataLength == 0) ||
- (Data == NULL) || (Data[0] == NULL) || (TransferResult == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((*DataToggle != 0) && (*DataToggle != 1)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((DeviceSpeed == EFI_USB_SPEED_LOW) ||
- ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
- ((EFI_USB_SPEED_HIGH == DeviceSpeed) && (MaximumPacketLength > 512)) ||
- ((EFI_USB_SPEED_SUPER == DeviceSpeed) && (MaximumPacketLength > 1024))) {
- return EFI_INVALID_PARAMETER;
- }
-
- OldTpl = gBS->RaiseTPL (XHC_TPL);
-
- Xhc = XHC_FROM_THIS (This);
-
- *TransferResult = EFI_USB_ERR_SYSTEM;
- Status = EFI_DEVICE_ERROR;
-
- if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {
- DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: HC is halted\n"));
- goto ON_EXIT;
- }
-
- //
- // Check if the device is still enabled before every transaction.
- //
- SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);
- if (SlotId == 0) {
- goto ON_EXIT;
- }
-
- //
- // Create a new URB, insert it into the asynchronous
- // schedule list, then poll the execution status.
- //
- Urb = XhcCreateUrb (
- Xhc,
- DeviceAddress,
- EndPointAddress,
- DeviceSpeed,
- MaximumPacketLength,
- XHC_BULK_TRANSFER,
- NULL,
- Data[0],
- *DataLength,
- NULL,
- NULL
- );
-
- if (Urb == NULL) {
- DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: failed to create URB\n"));
- Status = EFI_OUT_OF_RESOURCES;
- goto ON_EXIT;
- }
-
- Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);
-
- *TransferResult = Urb->Result;
- *DataLength = Urb->Completed;
-
- if (*TransferResult == EFI_USB_NOERROR) {
- Status = EFI_SUCCESS;
- } else if (*TransferResult == EFI_USB_ERR_STALL) {
- RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
- if (EFI_ERROR (RecoveryStatus)) {
- DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: XhcRecoverHaltedEndpoint failed\n"));
- }
- Status = EFI_DEVICE_ERROR;
- }
-
- Xhc->PciIo->Flush (Xhc->PciIo);
- XhcFreeUrb (Xhc, Urb);
-
-ON_EXIT:
-
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
- }
- gBS->RestoreTPL (OldTpl);
-
- return Status;
-}
-
-/**
- Submits an asynchronous interrupt transfer to an
- interrupt endpoint of a USB device.
-
- @param This This EFI_USB2_HC_PROTOCOL instance.
- @param DeviceAddress Target device address.
- @param EndPointAddress Endpoint number and its direction encoded in bit 7
- @param DeviceSpeed Indicates device speed.
- @param MaximumPacketLength Maximum packet size the target endpoint is capable
- @param IsNewTransfer If TRUE, to submit an new asynchronous interrupt
- transfer If FALSE, to remove the specified
- asynchronous interrupt.
- @param DataToggle On input, the initial data toggle to use; on output,
- it is updated to indicate the next data toggle.
- @param PollingInterval The he interval, in milliseconds, that the transfer
- is polled.
- @param DataLength The length of data to receive at the rate specified
- by PollingInterval.
- @param Translator Transaction translator to use.
- @param CallBackFunction Function to call at the rate specified by
- PollingInterval.
- @param Context Context to CallBackFunction.
-
- @retval EFI_SUCCESS The request has been successfully submitted or canceled.
- @retval EFI_INVALID_PARAMETER Some parameters are invalid.
- @retval EFI_OUT_OF_RESOURCES The request failed due to a lack of resources.
- @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
-
-**/
-EFI_STATUS
-EFIAPI
-XhcAsyncInterruptTransfer (
- IN EFI_USB2_HC_PROTOCOL *This,
- IN UINT8 DeviceAddress,
- IN UINT8 EndPointAddress,
- IN UINT8 DeviceSpeed,
- IN UINTN MaximumPacketLength,
- IN BOOLEAN IsNewTransfer,
- IN OUT UINT8 *DataToggle,
- IN UINTN PollingInterval,
- IN UINTN DataLength,
- IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
- IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,
- IN VOID *Context OPTIONAL
- )
-{
- USB_XHCI_INSTANCE *Xhc;
- URB *Urb;
- EFI_STATUS Status;
- UINT8 SlotId;
- UINT8 Index;
- UINT8 *Data;
- EFI_TPL OldTpl;
-
- //
- // Validate parameters
- //
- if (!XHCI_IS_DATAIN (EndPointAddress)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (IsNewTransfer) {
- if (DataLength == 0) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((*DataToggle != 1) && (*DataToggle != 0)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((PollingInterval > 255) || (PollingInterval < 1)) {
- return EFI_INVALID_PARAMETER;
- }
- }
-
- OldTpl = gBS->RaiseTPL (XHC_TPL);
-
- Xhc = XHC_FROM_THIS (This);
-
- //
- // Delete Async interrupt transfer request.
- //
- if (!IsNewTransfer) {
- //
- // The delete request may happen after device is detached.
- //
- for (Index = 0; Index < 255; Index++) {
- if (Xhc->UsbDevContext[Index + 1].BusDevAddr == DeviceAddress) {
- break;
- }
- }
-
- if (Index == 255) {
- Status = EFI_INVALID_PARAMETER;
- goto ON_EXIT;
- }
-
- Status = XhciDelAsyncIntTransfer (Xhc, DeviceAddress, EndPointAddress);
- DEBUG ((EFI_D_INFO, "XhcAsyncInterruptTransfer: remove old transfer for addr %d, Status = %r\n", DeviceAddress, Status));
- goto ON_EXIT;
- }
-
- Status = EFI_SUCCESS;
-
- if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {
- DEBUG ((EFI_D_ERROR, "XhcAsyncInterruptTransfer: HC is halt\n"));
- Status = EFI_DEVICE_ERROR;
- goto ON_EXIT;
- }
-
- //
- // Check if the device is still enabled before every transaction.
- //
- SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);
- if (SlotId == 0) {
- goto ON_EXIT;
- }
-
- Data = AllocateZeroPool (DataLength);
-
- if (Data == NULL) {
- DEBUG ((EFI_D_ERROR, "XhcAsyncInterruptTransfer: failed to allocate buffer\n"));
- Status = EFI_OUT_OF_RESOURCES;
- goto ON_EXIT;
- }
-
- Urb = XhcCreateUrb (
- Xhc,
- DeviceAddress,
- EndPointAddress,
- DeviceSpeed,
- MaximumPacketLength,
- XHC_INT_TRANSFER_ASYNC,
- NULL,
- Data,
- DataLength,
- CallBackFunction,
- Context
- );
-
- if (Urb == NULL) {
- DEBUG ((EFI_D_ERROR, "XhcAsyncInterruptTransfer: failed to create URB\n"));
- FreePool (Data);
- Status = EFI_OUT_OF_RESOURCES;
- goto ON_EXIT;
- }
-
- InsertHeadList (&Xhc->AsyncIntTransfers, &Urb->UrbList);
- //
- // Ring the doorbell
- //
- Status = RingIntTransferDoorBell (Xhc, Urb);
-
-ON_EXIT:
- Xhc->PciIo->Flush (Xhc->PciIo);
- gBS->RestoreTPL (OldTpl);
-
- return Status;
-}
-
-
-/**
- Submits synchronous interrupt transfer to an interrupt endpoint
- of a USB device.
-
- @param This This EFI_USB2_HC_PROTOCOL instance.
- @param DeviceAddress Target device address.
- @param EndPointAddress Endpoint number and its direction encoded in bit 7
- @param DeviceSpeed Indicates device speed.
- @param MaximumPacketLength Maximum packet size the target endpoint is capable
- of sending or receiving.
- @param Data Buffer of data that will be transmitted to USB
- device or received from USB device.
- @param DataLength On input, the size, in bytes, of the data buffer; On
- output, the number of bytes transferred.
- @param DataToggle On input, the initial data toggle to use; on output,
- it is updated to indicate the next data toggle.
- @param Timeout Maximum time, in second, to complete.
- @param Translator Transaction translator to use.
- @param TransferResult Variable to receive the transfer result.
-
- @return EFI_SUCCESS The transfer was completed successfully.
- @return EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
- @return EFI_INVALID_PARAMETER Some parameters are invalid.
- @return EFI_TIMEOUT The transfer failed due to timeout.
- @return EFI_DEVICE_ERROR The failed due to host controller or device error
-
-**/
-EFI_STATUS
-EFIAPI
-XhcSyncInterruptTransfer (
- IN EFI_USB2_HC_PROTOCOL *This,
- IN UINT8 DeviceAddress,
- IN UINT8 EndPointAddress,
- IN UINT8 DeviceSpeed,
- IN UINTN MaximumPacketLength,
- IN OUT VOID *Data,
- IN OUT UINTN *DataLength,
- IN OUT UINT8 *DataToggle,
- IN UINTN Timeout,
- IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
- OUT UINT32 *TransferResult
- )
-{
- USB_XHCI_INSTANCE *Xhc;
- URB *Urb;
- UINT8 SlotId;
- EFI_STATUS Status;
- EFI_STATUS RecoveryStatus;
- EFI_TPL OldTpl;
-
- //
- // Validates parameters
- //
- if ((DataLength == NULL) || (*DataLength == 0) ||
- (Data == NULL) || (TransferResult == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (!XHCI_IS_DATAIN (EndPointAddress)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((*DataToggle != 1) && (*DataToggle != 0)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) ||
- ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
- ((DeviceSpeed == EFI_USB_SPEED_HIGH) && (MaximumPacketLength > 3072))) {
- return EFI_INVALID_PARAMETER;
- }
-
- OldTpl = gBS->RaiseTPL (XHC_TPL);
-
- Xhc = XHC_FROM_THIS (This);
-
- *TransferResult = EFI_USB_ERR_SYSTEM;
- Status = EFI_DEVICE_ERROR;
-
- if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {
- DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: HC is halt\n"));
- goto ON_EXIT;
- }
-
- //
- // Check if the device is still enabled before every transaction.
- //
- SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);
- if (SlotId == 0) {
- goto ON_EXIT;
- }
-
- Urb = XhcCreateUrb (
- Xhc,
- DeviceAddress,
- EndPointAddress,
- DeviceSpeed,
- MaximumPacketLength,
- XHC_INT_TRANSFER_SYNC,
- NULL,
- Data,
- *DataLength,
- NULL,
- NULL
- );
-
- if (Urb == NULL) {
- DEBUG ((EFI_D_ERROR, "XhcSyncInterruptTransfer: failed to create URB\n"));
- Status = EFI_OUT_OF_RESOURCES;
- goto ON_EXIT;
- }
-
- Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);
-
- *TransferResult = Urb->Result;
- *DataLength = Urb->Completed;
-
- if (*TransferResult == EFI_USB_NOERROR) {
- Status = EFI_SUCCESS;
- } else if (*TransferResult == EFI_USB_ERR_STALL) {
- RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
- if (EFI_ERROR (RecoveryStatus)) {
- DEBUG ((EFI_D_ERROR, "XhcSyncInterruptTransfer: XhcRecoverHaltedEndpoint failed\n"));
- }
- Status = EFI_DEVICE_ERROR;
- }
-
- Xhc->PciIo->Flush (Xhc->PciIo);
- XhcFreeUrb (Xhc, Urb);
-
-ON_EXIT:
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "XhcSyncInterruptTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
- }
- gBS->RestoreTPL (OldTpl);
-
- return Status;
-}
-
-
-/**
- Submits isochronous transfer to a target USB device.
-
- @param This This EFI_USB2_HC_PROTOCOL instance.
- @param DeviceAddress Target device address.
- @param EndPointAddress End point address with its direction.
- @param DeviceSpeed Device speed, Low speed device doesn't support this
- type.
- @param MaximumPacketLength Maximum packet size that the endpoint is capable of
- sending or receiving.
- @param DataBuffersNumber Number of data buffers prepared for the transfer.
- @param Data Array of pointers to the buffers of data that will
- be transmitted to USB device or received from USB
- device.
- @param DataLength The size, in bytes, of the data buffer.
- @param Translator Transaction translator to use.
- @param TransferResult Variable to receive the transfer result.
-
- @return EFI_UNSUPPORTED Isochronous transfer is unsupported.
-
-**/
-EFI_STATUS
-EFIAPI
-XhcIsochronousTransfer (
- IN EFI_USB2_HC_PROTOCOL *This,
- IN UINT8 DeviceAddress,
- IN UINT8 EndPointAddress,
- IN UINT8 DeviceSpeed,
- IN UINTN MaximumPacketLength,
- IN UINT8 DataBuffersNumber,
- IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
- IN UINTN DataLength,
- IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
- OUT UINT32 *TransferResult
- )
-{
- return EFI_UNSUPPORTED;
-}
-
-
-/**
- Submits Async isochronous transfer to a target USB device.
-
- @param This This EFI_USB2_HC_PROTOCOL instance.
- @param DeviceAddress Target device address.
- @param EndPointAddress End point address with its direction.
- @param DeviceSpeed Device speed, Low speed device doesn't support this
- type.
- @param MaximumPacketLength Maximum packet size that the endpoint is capable of
- sending or receiving.
- @param DataBuffersNumber Number of data buffers prepared for the transfer.
- @param Data Array of pointers to the buffers of data that will
- be transmitted to USB device or received from USB
- device.
- @param DataLength The size, in bytes, of the data buffer.
- @param Translator Transaction translator to use.
- @param IsochronousCallBack Function to be called when the transfer complete.
- @param Context Context passed to the call back function as
- parameter.
-
- @return EFI_UNSUPPORTED Isochronous transfer isn't supported.
-
-**/
-EFI_STATUS
-EFIAPI
-XhcAsyncIsochronousTransfer (
- IN EFI_USB2_HC_PROTOCOL *This,
- IN UINT8 DeviceAddress,
- IN UINT8 EndPointAddress,
- IN UINT8 DeviceSpeed,
- IN UINTN MaximumPacketLength,
- IN UINT8 DataBuffersNumber,
- IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
- IN UINTN DataLength,
- IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
- IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
- IN VOID *Context
- )
-{
- return EFI_UNSUPPORTED;
-}
-
-/**
- Entry point for EFI drivers.
-
- @param ImageHandle EFI_HANDLE.
- @param SystemTable EFI_SYSTEM_TABLE.
-
- @retval EFI_SUCCESS Success.
- @retval Others Fail.
-
-**/
-EFI_STATUS
-EFIAPI
-XhcDriverEntryPoint (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- return EfiLibInstallDriverBindingComponentName2 (
- ImageHandle,
- SystemTable,
- &gXhciDriverBinding,
- ImageHandle,
- &gXhciComponentName,
- &gXhciComponentName2
- );
-}
-
-
-/**
- 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
- )
-{
- EFI_STATUS Status;
- EFI_PCI_IO_PROTOCOL *PciIo;
- USB_CLASSC UsbClassCReg;
-
- //
- // Test whether there is PCI IO Protocol attached on the controller handle.
- //
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiPciIoProtocolGuid,
- (VOID **) &PciIo,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
-
- if (EFI_ERROR (Status)) {
- return EFI_UNSUPPORTED;
- }
-
- Status = PciIo->Pci.Read (
- PciIo,
- EfiPciIoWidthUint8,
- PCI_CLASSCODE_OFFSET,
- sizeof (USB_CLASSC) / sizeof (UINT8),
- &UsbClassCReg
- );
-
- if (EFI_ERROR (Status)) {
- Status = EFI_UNSUPPORTED;
- goto ON_EXIT;
- }
-
- //
- // Test whether the controller belongs to Xhci type
- //
- if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||
- (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||
- (UsbClassCReg.ProgInterface != PCI_IF_XHCI)) {
- Status = EFI_UNSUPPORTED;
- }
-
-ON_EXIT:
- gBS->CloseProtocol (
- Controller,
- &gEfiPciIoProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
-
- return Status;
-}
-
-/**
- Create and initialize a USB_XHCI_INSTANCE structure.
-
- @param PciIo The PciIo on this device.
- @param DevicePath The device path of host controller.
- @param OriginalPciAttributes Original PCI attributes.
-
- @return The allocated and initialized USB_XHCI_INSTANCE structure if created,
- otherwise NULL.
-
-**/
-USB_XHCI_INSTANCE*
-XhcCreateUsbHc (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
- IN UINT64 OriginalPciAttributes
- )
-{
- USB_XHCI_INSTANCE *Xhc;
- EFI_STATUS Status;
- UINT32 PageSize;
- UINT16 ExtCapReg;
-
- Xhc = AllocateZeroPool (sizeof (USB_XHCI_INSTANCE));
-
- if (Xhc == NULL) {
- return NULL;
- }
-
- //
- // Initialize private data structure
- //
- Xhc->Signature = XHCI_INSTANCE_SIG;
- Xhc->PciIo = PciIo;
- Xhc->DevicePath = DevicePath;
- Xhc->OriginalPciAttributes = OriginalPciAttributes;
- CopyMem (&Xhc->Usb2Hc, &gXhciUsb2HcTemplate, sizeof (EFI_USB2_HC_PROTOCOL));
-
- InitializeListHead (&Xhc->AsyncIntTransfers);
-
- //
- // Be caution that the Offset passed to XhcReadCapReg() should be Dword align
- //
- Xhc->CapLength = XhcReadCapReg8 (Xhc, XHC_CAPLENGTH_OFFSET);
- Xhc->HcSParams1.Dword = XhcReadCapReg (Xhc, XHC_HCSPARAMS1_OFFSET);
- Xhc->HcSParams2.Dword = XhcReadCapReg (Xhc, XHC_HCSPARAMS2_OFFSET);
- Xhc->HcCParams.Dword = XhcReadCapReg (Xhc, XHC_HCCPARAMS_OFFSET);
- Xhc->DBOff = XhcReadCapReg (Xhc, XHC_DBOFF_OFFSET);
- Xhc->RTSOff = XhcReadCapReg (Xhc, XHC_RTSOFF_OFFSET);
-
- //
- // This PageSize field defines the page size supported by the xHC implementation.
- // This xHC supports a page size of 2^(n+12) if bit n is Set. For example,
- // if bit 0 is Set, the xHC supports 4k byte page sizes.
- //
- PageSize = XhcReadOpReg(Xhc, XHC_PAGESIZE_OFFSET) & XHC_PAGESIZE_MASK;
- Xhc->PageSize = 1 << (HighBitSet32(PageSize) + 12);
-
- ExtCapReg = (UINT16) (Xhc->HcCParams.Data.ExtCapReg);
- Xhc->ExtCapRegBase = ExtCapReg << 2;
- Xhc->UsbLegSupOffset = XhcGetCapabilityAddr (Xhc, XHC_CAP_USB_LEGACY);
- Xhc->DebugCapSupOffset = XhcGetCapabilityAddr (Xhc, XHC_CAP_USB_DEBUG);
-
- DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: Capability length 0x%x\n", Xhc->CapLength));
- DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: HcSParams1 0x%x\n", Xhc->HcSParams1));
- DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: HcSParams2 0x%x\n", Xhc->HcSParams2));
- DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: HcCParams 0x%x\n", Xhc->HcCParams));
- DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: DBOff 0x%x\n", Xhc->DBOff));
- DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: RTSOff 0x%x\n", Xhc->RTSOff));
- DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: UsbLegSupOffset 0x%x\n", Xhc->UsbLegSupOffset));
- DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: DebugCapSupOffset 0x%x\n", Xhc->DebugCapSupOffset));
-
- //
- // Create AsyncRequest Polling Timer
- //
- Status = gBS->CreateEvent (
- EVT_TIMER | EVT_NOTIFY_SIGNAL,
- TPL_CALLBACK,
- XhcMonitorAsyncRequests,
- Xhc,
- &Xhc->PollTimer
- );
-
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
-
- return Xhc;
-
-ON_ERROR:
- FreePool (Xhc);
- return NULL;
-}
-
-/**
- One notified function to stop the Host Controller when gBS->ExitBootServices() called.
-
- @param Event Pointer to this event
- @param Context Event hanlder private data
-
-**/
-VOID
-EFIAPI
-XhcExitBootService (
- EFI_EVENT Event,
- VOID *Context
- )
-
-{
- USB_XHCI_INSTANCE *Xhc;
- EFI_PCI_IO_PROTOCOL *PciIo;
-
- Xhc = (USB_XHCI_INSTANCE*) Context;
- PciIo = Xhc->PciIo;
-
- //
- // Stop AsyncRequest Polling timer then stop the XHCI driver
- // and uninstall the XHCI protocl.
- //
- gBS->SetTimer (Xhc->PollTimer, TimerCancel, 0);
- XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);
-
- if (Xhc->PollTimer != NULL) {
- gBS->CloseEvent (Xhc->PollTimer);
- }
-
- XhcClearBiosOwnership (Xhc);
-
- //
- // Restore original PCI attributes
- //
- PciIo->Attributes (
- PciIo,
- EfiPciIoAttributeOperationSet,
- Xhc->OriginalPciAttributes,
- NULL
- );
-}
-
-/**
- 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
- )
-{
- EFI_STATUS Status;
- EFI_PCI_IO_PROTOCOL *PciIo;
- UINT64 Supports;
- UINT64 OriginalPciAttributes;
- BOOLEAN PciAttributesSaved;
- USB_XHCI_INSTANCE *Xhc;
- EFI_DEVICE_PATH_PROTOCOL *HcDevicePath;
-
- //
- // Open the PciIo Protocol, then enable the USB host controller
- //
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiPciIoProtocolGuid,
- (VOID **) &PciIo,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
-
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Open Device Path Protocol for on USB host controller
- //
- HcDevicePath = NULL;
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiDevicePathProtocolGuid,
- (VOID **) &HcDevicePath,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
-
- PciAttributesSaved = FALSE;
- //
- // Save original PCI attributes
- //
- Status = PciIo->Attributes (
- PciIo,
- EfiPciIoAttributeOperationGet,
- 0,
- &OriginalPciAttributes
- );
-
- if (EFI_ERROR (Status)) {
- goto CLOSE_PCIIO;
- }
- PciAttributesSaved = TRUE;
-
- Status = PciIo->Attributes (
- PciIo,
- EfiPciIoAttributeOperationSupported,
- 0,
- &Supports
- );
- if (!EFI_ERROR (Status)) {
- Supports &= EFI_PCI_DEVICE_ENABLE;
- Status = PciIo->Attributes (
- PciIo,
- EfiPciIoAttributeOperationEnable,
- Supports,
- NULL
- );
- }
-
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "XhcDriverBindingStart: failed to enable controller\n"));
- goto CLOSE_PCIIO;
- }
-
- //
- // Create then install USB2_HC_PROTOCOL
- //
- Xhc = XhcCreateUsbHc (PciIo, HcDevicePath, OriginalPciAttributes);
-
- if (Xhc == NULL) {
- DEBUG ((EFI_D_ERROR, "XhcDriverBindingStart: failed to create USB2_HC\n"));
- return EFI_OUT_OF_RESOURCES;
- }
-
- XhcSetBiosOwnership (Xhc);
-
- XhcResetHC (Xhc, XHC_RESET_TIMEOUT);
- ASSERT (XhcIsHalt (Xhc));
-
- //
- // After Chip Hardware Reset wait until the Controller Not Ready (CNR) flag
- // in the USBSTS is '0' before writing any xHC Operational or Runtime registers.
- //
- ASSERT (!(XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_CNR)));
-
- //
- // Initialize the schedule
- //
- XhcInitSched (Xhc);
-
- //
- // Start the Host Controller
- //
- XhcRunHC(Xhc, XHC_GENERIC_TIMEOUT);
-
- //
- // Start the asynchronous interrupt monitor
- //
- Status = gBS->SetTimer (Xhc->PollTimer, TimerPeriodic, XHC_ASYNC_TIMER_INTERVAL);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "XhcDriverBindingStart: failed to start async interrupt monitor\n"));
- XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);
- goto FREE_POOL;
- }
-
- //
- // Create event to stop the HC when exit boot service.
- //
- Status = gBS->CreateEventEx (
- EVT_NOTIFY_SIGNAL,
- TPL_NOTIFY,
- XhcExitBootService,
- Xhc,
- &gEfiEventExitBootServicesGuid,
- &Xhc->ExitBootServiceEvent
- );
- if (EFI_ERROR (Status)) {
- goto FREE_POOL;
- }
-
- //
- // Install the component name protocol, don't fail the start
- // because of something for display.
- //
- AddUnicodeString2 (
- "eng",
- gXhciComponentName.SupportedLanguages,
- &Xhc->ControllerNameTable,
- L"eXtensible Host Controller (USB 3.0)",
- TRUE
- );
- AddUnicodeString2 (
- "en",
- gXhciComponentName2.SupportedLanguages,
- &Xhc->ControllerNameTable,
- L"eXtensible Host Controller (USB 3.0)",
- FALSE
- );
-
- Status = gBS->InstallProtocolInterface (
- &Controller,
- &gEfiUsb2HcProtocolGuid,
- EFI_NATIVE_INTERFACE,
- &Xhc->Usb2Hc
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "XhcDriverBindingStart: failed to install USB2_HC Protocol\n"));
- goto FREE_POOL;
- }
-
- DEBUG ((EFI_D_INFO, "XhcDriverBindingStart: XHCI started for controller @ %x\n", Controller));
- return EFI_SUCCESS;
-
-FREE_POOL:
- gBS->CloseEvent (Xhc->PollTimer);
- XhcFreeSched (Xhc);
- FreePool (Xhc);
-
-CLOSE_PCIIO:
- if (PciAttributesSaved) {
- //
- // Restore original PCI attributes
- //
- PciIo->Attributes (
- PciIo,
- EfiPciIoAttributeOperationSet,
- OriginalPciAttributes,
- NULL
- );
- }
-
- gBS->CloseProtocol (
- Controller,
- &gEfiPciIoProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
-
- return Status;
-}
-
-
-/**
- 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
- )
-{
- EFI_STATUS Status;
- EFI_USB2_HC_PROTOCOL *Usb2Hc;
- EFI_PCI_IO_PROTOCOL *PciIo;
- USB_XHCI_INSTANCE *Xhc;
- UINT8 Index;
-
- //
- // Test whether the Controller handler passed in is a valid
- // Usb controller handle that should be supported, if not,
- // return the error status directly
- //
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiUsb2HcProtocolGuid,
- (VOID **) &Usb2Hc,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
-
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = gBS->UninstallProtocolInterface (
- Controller,
- &gEfiUsb2HcProtocolGuid,
- Usb2Hc
- );
-
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Xhc = XHC_FROM_THIS (Usb2Hc);
- PciIo = Xhc->PciIo;
-
- //
- // Stop AsyncRequest Polling timer then stop the XHCI driver
- // and uninstall the XHCI protocl.
- //
- gBS->SetTimer (Xhc->PollTimer, TimerCancel, 0);
-
- //
- // Disable the device slots occupied by these devices on its downstream ports.
- // Entry 0 is reserved.
- //
- for (Index = 0; Index < 255; Index++) {
- if (!Xhc->UsbDevContext[Index + 1].Enabled ||
- (Xhc->UsbDevContext[Index + 1].SlotId == 0)) {
- continue;
- }
- if (Xhc->HcCParams.Data.Csz == 0) {
- XhcDisableSlotCmd (Xhc, Xhc->UsbDevContext[Index + 1].SlotId);
- } else {
- XhcDisableSlotCmd64 (Xhc, Xhc->UsbDevContext[Index + 1].SlotId);
- }
- }
-
- if (Xhc->PollTimer != NULL) {
- gBS->CloseEvent (Xhc->PollTimer);
- }
-
- if (Xhc->ExitBootServiceEvent != NULL) {
- gBS->CloseEvent (Xhc->ExitBootServiceEvent);
- }
-
- XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);
- XhcClearBiosOwnership (Xhc);
- XhciDelAllAsyncIntTransfers (Xhc);
- XhcFreeSched (Xhc);
-
- if (Xhc->ControllerNameTable) {
- FreeUnicodeStringTable (Xhc->ControllerNameTable);
- }
-
- //
- // Restore original PCI attributes
- //
- PciIo->Attributes (
- PciIo,
- EfiPciIoAttributeOperationSet,
- Xhc->OriginalPciAttributes,
- NULL
- );
-
- gBS->CloseProtocol (
- Controller,
- &gEfiPciIoProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
-
- FreePool (Xhc);
-
- return EFI_SUCCESS;
-}
-
+/** @file\r
+ The XHCI controller driver.\r
+\r
+Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "Xhci.h"\r
+\r
+//\r
+// Two arrays used to translate the XHCI port state (change)\r
+// to the UEFI protocol's port state (change).\r
+//\r
+USB_PORT_STATE_MAP mUsbPortStateMap[] = {\r
+ {XHC_PORTSC_CCS, USB_PORT_STAT_CONNECTION},\r
+ {XHC_PORTSC_PED, USB_PORT_STAT_ENABLE},\r
+ {XHC_PORTSC_OCA, USB_PORT_STAT_OVERCURRENT},\r
+ {XHC_PORTSC_RESET, USB_PORT_STAT_RESET}\r
+};\r
+\r
+USB_PORT_STATE_MAP mUsbPortChangeMap[] = {\r
+ {XHC_PORTSC_CSC, USB_PORT_STAT_C_CONNECTION},\r
+ {XHC_PORTSC_PEC, USB_PORT_STAT_C_ENABLE},\r
+ {XHC_PORTSC_OCC, USB_PORT_STAT_C_OVERCURRENT},\r
+ {XHC_PORTSC_PRC, USB_PORT_STAT_C_RESET}\r
+};\r
+\r
+USB_CLEAR_PORT_MAP mUsbClearPortChangeMap[] = {\r
+ {XHC_PORTSC_CSC, EfiUsbPortConnectChange},\r
+ {XHC_PORTSC_PEC, EfiUsbPortEnableChange},\r
+ {XHC_PORTSC_OCC, EfiUsbPortOverCurrentChange},\r
+ {XHC_PORTSC_PRC, EfiUsbPortResetChange}\r
+};\r
+\r
+USB_PORT_STATE_MAP mUsbHubPortStateMap[] = {\r
+ {XHC_HUB_PORTSC_CCS, USB_PORT_STAT_CONNECTION},\r
+ {XHC_HUB_PORTSC_PED, USB_PORT_STAT_ENABLE},\r
+ {XHC_HUB_PORTSC_OCA, USB_PORT_STAT_OVERCURRENT},\r
+ {XHC_HUB_PORTSC_RESET, USB_PORT_STAT_RESET}\r
+};\r
+\r
+USB_PORT_STATE_MAP mUsbHubPortChangeMap[] = {\r
+ {XHC_HUB_PORTSC_CSC, USB_PORT_STAT_C_CONNECTION},\r
+ {XHC_HUB_PORTSC_PEC, USB_PORT_STAT_C_ENABLE},\r
+ {XHC_HUB_PORTSC_OCC, USB_PORT_STAT_C_OVERCURRENT},\r
+ {XHC_HUB_PORTSC_PRC, USB_PORT_STAT_C_RESET}\r
+};\r
+\r
+USB_CLEAR_PORT_MAP mUsbHubClearPortChangeMap[] = {\r
+ {XHC_HUB_PORTSC_CSC, EfiUsbPortConnectChange},\r
+ {XHC_HUB_PORTSC_PEC, EfiUsbPortEnableChange},\r
+ {XHC_HUB_PORTSC_OCC, EfiUsbPortOverCurrentChange},\r
+ {XHC_HUB_PORTSC_PRC, EfiUsbPortResetChange},\r
+ {XHC_HUB_PORTSC_BHRC, Usb3PortBHPortResetChange}\r
+};\r
+\r
+EFI_DRIVER_BINDING_PROTOCOL gXhciDriverBinding = {\r
+ XhcDriverBindingSupported,\r
+ XhcDriverBindingStart,\r
+ XhcDriverBindingStop,\r
+ 0x30,\r
+ NULL,\r
+ NULL\r
+};\r
+\r
+//\r
+// Template for Xhci's Usb2 Host Controller Protocol Instance.\r
+//\r
+EFI_USB2_HC_PROTOCOL gXhciUsb2HcTemplate = {\r
+ XhcGetCapability,\r
+ XhcReset,\r
+ XhcGetState,\r
+ XhcSetState,\r
+ XhcControlTransfer,\r
+ XhcBulkTransfer,\r
+ XhcAsyncInterruptTransfer,\r
+ XhcSyncInterruptTransfer,\r
+ XhcIsochronousTransfer,\r
+ XhcAsyncIsochronousTransfer,\r
+ XhcGetRootHubPortStatus,\r
+ XhcSetRootHubPortFeature,\r
+ XhcClearRootHubPortFeature,\r
+ 0x3,\r
+ 0x0\r
+};\r
+\r
+/**\r
+ Retrieves the capability of root hub ports.\r
+\r
+ @param This The EFI_USB2_HC_PROTOCOL instance.\r
+ @param MaxSpeed Max speed supported by the controller.\r
+ @param PortNumber Number of the root hub ports.\r
+ @param Is64BitCapable Whether the controller supports 64-bit memory\r
+ addressing.\r
+\r
+ @retval EFI_SUCCESS Host controller capability were retrieved successfully.\r
+ @retval EFI_INVALID_PARAMETER Either of the three capability pointer is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcGetCapability (\r
+ IN EFI_USB2_HC_PROTOCOL *This,\r
+ OUT UINT8 *MaxSpeed,\r
+ OUT UINT8 *PortNumber,\r
+ OUT UINT8 *Is64BitCapable\r
+ )\r
+{\r
+ USB_XHCI_INSTANCE *Xhc;\r
+ EFI_TPL OldTpl;\r
+\r
+ if ((MaxSpeed == NULL) || (PortNumber == NULL) || (Is64BitCapable == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ OldTpl = gBS->RaiseTPL (XHC_TPL);\r
+\r
+ Xhc = XHC_FROM_THIS (This);\r
+ *MaxSpeed = EFI_USB_SPEED_SUPER;\r
+ *PortNumber = (UINT8) (Xhc->HcSParams1.Data.MaxPorts);\r
+ *Is64BitCapable = (UINT8) (Xhc->HcCParams.Data.Ac64);\r
+ DEBUG ((EFI_D_INFO, "XhcGetCapability: %d ports, 64 bit %d\n", *PortNumber, *Is64BitCapable));\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Provides software reset for the USB host controller.\r
+\r
+ @param This This EFI_USB2_HC_PROTOCOL instance.\r
+ @param Attributes A bit mask of the reset operation to perform.\r
+\r
+ @retval EFI_SUCCESS The reset operation succeeded.\r
+ @retval EFI_INVALID_PARAMETER Attributes is not valid.\r
+ @retval EFI_UNSUPPOURTED The type of reset specified by Attributes is\r
+ not currently supported by the host controller.\r
+ @retval EFI_DEVICE_ERROR Host controller isn't halted to reset.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcReset (\r
+ IN EFI_USB2_HC_PROTOCOL *This,\r
+ IN UINT16 Attributes\r
+ )\r
+{\r
+ USB_XHCI_INSTANCE *Xhc;\r
+ EFI_STATUS Status;\r
+ EFI_TPL OldTpl;\r
+\r
+ Xhc = XHC_FROM_THIS (This);\r
+ \r
+ if (Xhc->DevicePath != NULL) {\r
+ //\r
+ // Report Status Code to indicate reset happens\r
+ //\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_PROGRESS_CODE,\r
+ (EFI_IO_BUS_USB | EFI_IOB_PC_RESET),\r
+ Xhc->DevicePath\r
+ );\r
+ } \r
+\r
+ OldTpl = gBS->RaiseTPL (XHC_TPL);\r
+\r
+ switch (Attributes) {\r
+ case EFI_USB_HC_RESET_GLOBAL:\r
+ //\r
+ // Flow through, same behavior as Host Controller Reset\r
+ //\r
+ case EFI_USB_HC_RESET_HOST_CONTROLLER:\r
+ if ((Xhc->DebugCapSupOffset != 0xFFFFFFFF) && ((XhcReadExtCapReg (Xhc, Xhc->DebugCapSupOffset) & 0xFF) == XHC_CAP_USB_DEBUG) &&\r
+ ((XhcReadExtCapReg (Xhc, Xhc->DebugCapSupOffset + XHC_DC_DCCTRL) & BIT0) != 0)) {\r
+ Status = EFI_SUCCESS;\r
+ goto ON_EXIT;\r
+ }\r
+ //\r
+ // Host Controller must be Halt when Reset it\r
+ //\r
+ if (!XhcIsHalt (Xhc)) {\r
+ Status = XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto ON_EXIT;\r
+ }\r
+ }\r
+\r
+ Status = XhcResetHC (Xhc, XHC_RESET_TIMEOUT);\r
+ ASSERT (!(XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_CNR)));\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+ //\r
+ // Clean up the asynchronous transfers, currently only\r
+ // interrupt supports asynchronous operation.\r
+ //\r
+ XhciDelAllAsyncIntTransfers (Xhc);\r
+ XhcFreeSched (Xhc);\r
+\r
+ XhcInitSched (Xhc);\r
+ break;\r
+\r
+ case EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG:\r
+ case EFI_USB_HC_RESET_HOST_WITH_DEBUG:\r
+ Status = EFI_UNSUPPORTED;\r
+ break;\r
+\r
+ default:\r
+ Status = EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ON_EXIT:\r
+ DEBUG ((EFI_D_INFO, "XhcReset: status %r\n", Status));\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Retrieve the current state of the USB host controller.\r
+\r
+ @param This This EFI_USB2_HC_PROTOCOL instance.\r
+ @param State Variable to return the current host controller\r
+ state.\r
+\r
+ @retval EFI_SUCCESS Host controller state was returned in State.\r
+ @retval EFI_INVALID_PARAMETER State is NULL.\r
+ @retval EFI_DEVICE_ERROR An error was encountered while attempting to\r
+ retrieve the host controller's current state.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcGetState (\r
+ IN EFI_USB2_HC_PROTOCOL *This,\r
+ OUT EFI_USB_HC_STATE *State\r
+ )\r
+{\r
+ USB_XHCI_INSTANCE *Xhc;\r
+ EFI_TPL OldTpl;\r
+\r
+ if (State == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ OldTpl = gBS->RaiseTPL (XHC_TPL);\r
+\r
+ Xhc = XHC_FROM_THIS (This);\r
+\r
+ if (XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT)) {\r
+ *State = EfiUsbHcStateHalt;\r
+ } else {\r
+ *State = EfiUsbHcStateOperational;\r
+ }\r
+\r
+ DEBUG ((EFI_D_INFO, "XhcGetState: current state %d\n", *State));\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Sets the USB host controller to a specific state.\r
+\r
+ @param This This EFI_USB2_HC_PROTOCOL instance.\r
+ @param State The state of the host controller that will be set.\r
+\r
+ @retval EFI_SUCCESS The USB host controller was successfully placed\r
+ in the state specified by State.\r
+ @retval EFI_INVALID_PARAMETER State is invalid.\r
+ @retval EFI_DEVICE_ERROR Failed to set the state due to device error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcSetState (\r
+ IN EFI_USB2_HC_PROTOCOL *This,\r
+ IN EFI_USB_HC_STATE State\r
+ )\r
+{\r
+ USB_XHCI_INSTANCE *Xhc;\r
+ EFI_STATUS Status;\r
+ EFI_USB_HC_STATE CurState;\r
+ EFI_TPL OldTpl;\r
+\r
+ Status = XhcGetState (This, &CurState);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ if (CurState == State) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ OldTpl = gBS->RaiseTPL (XHC_TPL);\r
+\r
+ Xhc = XHC_FROM_THIS (This);\r
+\r
+ switch (State) {\r
+ case EfiUsbHcStateHalt:\r
+ Status = XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);\r
+ break;\r
+\r
+ case EfiUsbHcStateOperational:\r
+ if (XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HSE)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Software must not write a one to this field unless the host controller\r
+ // is in the Halted state. Doing so will yield undefined results.\r
+ // refers to Spec[XHCI1.0-2.3.1]\r
+ //\r
+ if (!XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ break;\r
+ }\r
+\r
+ Status = XhcRunHC (Xhc, XHC_GENERIC_TIMEOUT);\r
+ break;\r
+\r
+ case EfiUsbHcStateSuspend:\r
+ Status = EFI_UNSUPPORTED;\r
+ break;\r
+\r
+ default:\r
+ Status = EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ DEBUG ((EFI_D_INFO, "XhcSetState: status %r\n", Status));\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Retrieves the current status of a USB root hub port.\r
+\r
+ @param This This EFI_USB2_HC_PROTOCOL instance.\r
+ @param PortNumber The root hub port to retrieve the state from.\r
+ This value is zero-based.\r
+ @param PortStatus Variable to receive the port state.\r
+\r
+ @retval EFI_SUCCESS The status of the USB root hub port specified.\r
+ by PortNumber was returned in PortStatus.\r
+ @retval EFI_INVALID_PARAMETER PortNumber is invalid.\r
+ @retval EFI_DEVICE_ERROR Can't read register.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcGetRootHubPortStatus (\r
+ IN EFI_USB2_HC_PROTOCOL *This,\r
+ IN UINT8 PortNumber,\r
+ OUT EFI_USB_PORT_STATUS *PortStatus\r
+ )\r
+{\r
+ USB_XHCI_INSTANCE *Xhc;\r
+ UINT32 Offset;\r
+ UINT32 State;\r
+ UINT32 TotalPort;\r
+ UINTN Index;\r
+ UINTN MapSize;\r
+ EFI_STATUS Status;\r
+ USB_DEV_ROUTE ParentRouteChart;\r
+ EFI_TPL OldTpl;\r
+\r
+ if (PortStatus == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ OldTpl = gBS->RaiseTPL (XHC_TPL);\r
+\r
+ Xhc = XHC_FROM_THIS (This);\r
+ Status = EFI_SUCCESS;\r
+\r
+ TotalPort = Xhc->HcSParams1.Data.MaxPorts;\r
+\r
+ if (PortNumber >= TotalPort) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Offset = (UINT32) (XHC_PORTSC_OFFSET + (0x10 * PortNumber));\r
+ PortStatus->PortStatus = 0;\r
+ PortStatus->PortChangeStatus = 0;\r
+\r
+ State = XhcReadOpReg (Xhc, Offset);\r
+\r
+ //\r
+ // According to XHCI 1.0 spec, bit 10~13 of the root port status register identifies the speed of the attached device.\r
+ //\r
+ switch ((State & XHC_PORTSC_PS) >> 10) {\r
+ case 2:\r
+ PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;\r
+ break;\r
+\r
+ case 3:\r
+ PortStatus->PortStatus |= USB_PORT_STAT_HIGH_SPEED;\r
+ break;\r
+\r
+ case 4:\r
+ PortStatus->PortStatus |= USB_PORT_STAT_SUPER_SPEED;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Convert the XHCI port/port change state to UEFI status\r
+ //\r
+ MapSize = sizeof (mUsbPortStateMap) / sizeof (USB_PORT_STATE_MAP);\r
+\r
+ for (Index = 0; Index < MapSize; Index++) {\r
+ if (XHC_BIT_IS_SET (State, mUsbPortStateMap[Index].HwState)) {\r
+ PortStatus->PortStatus = (UINT16) (PortStatus->PortStatus | mUsbPortStateMap[Index].UefiState);\r
+ }\r
+ }\r
+ //\r
+ // Bit5~8 reflects its current link state.\r
+ //\r
+ if ((State & XHC_PORTSC_PLS) >> 5 == 3) {\r
+ PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;\r
+ }\r
+\r
+ MapSize = sizeof (mUsbPortChangeMap) / sizeof (USB_PORT_STATE_MAP);\r
+\r
+ for (Index = 0; Index < MapSize; Index++) {\r
+ if (XHC_BIT_IS_SET (State, mUsbPortChangeMap[Index].HwState)) {\r
+ PortStatus->PortChangeStatus = (UINT16) (PortStatus->PortChangeStatus | mUsbPortChangeMap[Index].UefiState);\r
+ }\r
+ }\r
+\r
+ MapSize = sizeof (mUsbClearPortChangeMap) / sizeof (USB_CLEAR_PORT_MAP);\r
+\r
+ for (Index = 0; Index < MapSize; Index++) {\r
+ if (XHC_BIT_IS_SET (State, mUsbClearPortChangeMap[Index].HwState)) {\r
+ XhcClearRootHubPortFeature (This, PortNumber, (EFI_USB_PORT_FEATURE)mUsbClearPortChangeMap[Index].Selector);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Poll the root port status register to enable/disable corresponding device slot if there is a device attached/detached.\r
+ // For those devices behind hub, we get its attach/detach event by hooking Get_Port_Status request at control transfer for those hub.\r
+ //\r
+ ParentRouteChart.Dword = 0;\r
+ XhcPollPortStatusChange (Xhc, ParentRouteChart, PortNumber, PortStatus);\r
+\r
+ON_EXIT:\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Sets a feature for the specified root hub port.\r
+\r
+ @param This This EFI_USB2_HC_PROTOCOL instance.\r
+ @param PortNumber Root hub port to set.\r
+ @param PortFeature Feature to set.\r
+\r
+ @retval EFI_SUCCESS The feature specified by PortFeature was set.\r
+ @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.\r
+ @retval EFI_DEVICE_ERROR Can't read register.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcSetRootHubPortFeature (\r
+ IN EFI_USB2_HC_PROTOCOL *This,\r
+ IN UINT8 PortNumber,\r
+ IN EFI_USB_PORT_FEATURE PortFeature\r
+ )\r
+{\r
+ USB_XHCI_INSTANCE *Xhc;\r
+ UINT32 Offset;\r
+ UINT32 State;\r
+ UINT32 TotalPort;\r
+ EFI_STATUS Status;\r
+ EFI_TPL OldTpl;\r
+\r
+ OldTpl = gBS->RaiseTPL (XHC_TPL);\r
+\r
+ Xhc = XHC_FROM_THIS (This);\r
+ Status = EFI_SUCCESS;\r
+\r
+ TotalPort = (Xhc->HcSParams1.Data.MaxPorts);\r
+\r
+ if (PortNumber >= TotalPort) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Offset = (UINT32) (XHC_PORTSC_OFFSET + (0x10 * PortNumber));\r
+ State = XhcReadOpReg (Xhc, Offset);\r
+\r
+ //\r
+ // Mask off the port status change bits, these bits are\r
+ // write clean bit\r
+ //\r
+ State &= ~ (BIT1 | BIT17 | BIT18 | BIT19 | BIT20 | BIT21 | BIT22 | BIT23);\r
+\r
+ switch (PortFeature) {\r
+ case EfiUsbPortEnable:\r
+ //\r
+ // Ports may only be enabled by the xHC. Software cannot enable a port by writing a '1' to this flag.\r
+ // A port may be disabled by software writing a '1' to this flag.\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ break;\r
+\r
+ case EfiUsbPortSuspend:\r
+ State |= XHC_PORTSC_LWS;\r
+ XhcWriteOpReg (Xhc, Offset, State);\r
+ State &= ~XHC_PORTSC_PLS;\r
+ State |= (3 << 5) ;\r
+ XhcWriteOpReg (Xhc, Offset, State);\r
+ break;\r
+\r
+ case EfiUsbPortReset:\r
+ DEBUG ((EFI_D_INFO, "XhcUsbPortReset!\n"));\r
+ //\r
+ // Make sure Host Controller not halt before reset it\r
+ //\r
+ if (XhcIsHalt (Xhc)) {\r
+ Status = XhcRunHC (Xhc, XHC_GENERIC_TIMEOUT);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_INFO, "XhcSetRootHubPortFeature :failed to start HC - %r\n", Status));\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // 4.3.1 Resetting a Root Hub Port\r
+ // 1) Write the PORTSC register with the Port Reset (PR) bit set to '1'.\r
+ //\r
+ State |= XHC_PORTSC_RESET;\r
+ XhcWriteOpReg (Xhc, Offset, State);\r
+ XhcWaitOpRegBit(Xhc, Offset, XHC_PORTSC_PRC, TRUE, XHC_GENERIC_TIMEOUT);\r
+ break;\r
+\r
+ case EfiUsbPortPower:\r
+ //\r
+ // Not supported, ignore the operation\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ break;\r
+\r
+ case EfiUsbPortOwner:\r
+ //\r
+ // XHCI root hub port don't has the owner bit, ignore the operation\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ break;\r
+\r
+ default:\r
+ Status = EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ON_EXIT:\r
+ DEBUG ((EFI_D_INFO, "XhcSetRootHubPortFeature: status %r\n", Status));\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Clears a feature for the specified root hub port.\r
+\r
+ @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
+ @param PortNumber Specifies the root hub port whose feature is\r
+ requested to be cleared.\r
+ @param PortFeature Indicates the feature selector associated with the\r
+ feature clear request.\r
+\r
+ @retval EFI_SUCCESS The feature specified by PortFeature was cleared\r
+ for the USB root hub port specified by PortNumber.\r
+ @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.\r
+ @retval EFI_DEVICE_ERROR Can't read register.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcClearRootHubPortFeature (\r
+ IN EFI_USB2_HC_PROTOCOL *This,\r
+ IN UINT8 PortNumber,\r
+ IN EFI_USB_PORT_FEATURE PortFeature\r
+ )\r
+{\r
+ USB_XHCI_INSTANCE *Xhc;\r
+ UINT32 Offset;\r
+ UINT32 State;\r
+ UINT32 TotalPort;\r
+ EFI_STATUS Status;\r
+ EFI_TPL OldTpl;\r
+\r
+ OldTpl = gBS->RaiseTPL (XHC_TPL);\r
+\r
+ Xhc = XHC_FROM_THIS (This);\r
+ Status = EFI_SUCCESS;\r
+\r
+ TotalPort = (Xhc->HcSParams1.Data.MaxPorts);\r
+\r
+ if (PortNumber >= TotalPort) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Offset = XHC_PORTSC_OFFSET + (0x10 * PortNumber);\r
+\r
+ //\r
+ // Mask off the port status change bits, these bits are\r
+ // write clean bit\r
+ //\r
+ State = XhcReadOpReg (Xhc, Offset);\r
+ State &= ~ (BIT1 | BIT17 | BIT18 | BIT19 | BIT20 | BIT21 | BIT22 | BIT23);\r
+\r
+ switch (PortFeature) {\r
+ case EfiUsbPortEnable:\r
+ //\r
+ // Ports may only be enabled by the xHC. Software cannot enable a port by writing a '1' to this flag.\r
+ // A port may be disabled by software writing a '1' to this flag.\r
+ //\r
+ State |= XHC_PORTSC_PED;\r
+ State &= ~XHC_PORTSC_RESET;\r
+ XhcWriteOpReg (Xhc, Offset, State);\r
+ break;\r
+\r
+ case EfiUsbPortSuspend:\r
+ State |= XHC_PORTSC_LWS;\r
+ XhcWriteOpReg (Xhc, Offset, State);\r
+ State &= ~XHC_PORTSC_PLS;\r
+ XhcWriteOpReg (Xhc, Offset, State);\r
+ break;\r
+\r
+ case EfiUsbPortReset:\r
+ //\r
+ // PORTSC_RESET BIT(4) bit is RW1S attribute, which means Write-1-to-set status:\r
+ // Register bits indicate status when read, a clear bit may be set by\r
+ // writing a '1'. Writing a '0' to RW1S bits has no effect.\r
+ //\r
+ break;\r
+\r
+ case EfiUsbPortOwner:\r
+ //\r
+ // XHCI root hub port don't has the owner bit, ignore the operation\r
+ //\r
+ break;\r
+\r
+ case EfiUsbPortConnectChange:\r
+ //\r
+ // Clear connect status change\r
+ //\r
+ State |= XHC_PORTSC_CSC;\r
+ XhcWriteOpReg (Xhc, Offset, State);\r
+ break;\r
+\r
+ case EfiUsbPortEnableChange:\r
+ //\r
+ // Clear enable status change\r
+ //\r
+ State |= XHC_PORTSC_PEC;\r
+ XhcWriteOpReg (Xhc, Offset, State);\r
+ break;\r
+\r
+ case EfiUsbPortOverCurrentChange:\r
+ //\r
+ // Clear PortOverCurrent change\r
+ //\r
+ State |= XHC_PORTSC_OCC;\r
+ XhcWriteOpReg (Xhc, Offset, State);\r
+ break;\r
+\r
+ case EfiUsbPortResetChange:\r
+ //\r
+ // Clear Port Reset change\r
+ //\r
+ State |= XHC_PORTSC_PRC;\r
+ XhcWriteOpReg (Xhc, Offset, State);\r
+ break;\r
+\r
+ case EfiUsbPortPower:\r
+ case EfiUsbPortSuspendChange:\r
+ //\r
+ // Not supported or not related operation\r
+ //\r
+ break;\r
+\r
+ default:\r
+ Status = EFI_INVALID_PARAMETER;\r
+ break;\r
+ }\r
+\r
+ON_EXIT:\r
+ DEBUG ((EFI_D_INFO, "XhcClearRootHubPortFeature: status %r\n", Status));\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Submits control transfer to a target USB device.\r
+\r
+ @param This This EFI_USB2_HC_PROTOCOL instance.\r
+ @param DeviceAddress The target device address.\r
+ @param DeviceSpeed Target device speed.\r
+ @param MaximumPacketLength Maximum packet size the default control transfer\r
+ endpoint is capable of sending or receiving.\r
+ @param Request USB device request to send.\r
+ @param TransferDirection Specifies the data direction for the data stage\r
+ @param Data Data buffer to be transmitted or received from USB\r
+ device.\r
+ @param DataLength The size (in bytes) of the data buffer.\r
+ @param Timeout Indicates the maximum timeout, in millisecond.\r
+ @param Translator Transaction translator to be used by this device.\r
+ @param TransferResult Return the result of this control transfer.\r
+\r
+ @retval EFI_SUCCESS Transfer was completed successfully.\r
+ @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.\r
+ @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
+ @retval EFI_TIMEOUT Transfer failed due to timeout.\r
+ @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcControlTransfer (\r
+ IN EFI_USB2_HC_PROTOCOL *This,\r
+ IN UINT8 DeviceAddress,\r
+ IN UINT8 DeviceSpeed,\r
+ IN UINTN MaximumPacketLength,\r
+ IN EFI_USB_DEVICE_REQUEST *Request,\r
+ IN EFI_USB_DATA_DIRECTION TransferDirection,\r
+ IN OUT VOID *Data,\r
+ IN OUT UINTN *DataLength,\r
+ IN UINTN Timeout,\r
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
+ OUT UINT32 *TransferResult\r
+ )\r
+{\r
+ USB_XHCI_INSTANCE *Xhc;\r
+ URB *Urb;\r
+ UINT8 Endpoint;\r
+ UINT8 Index;\r
+ UINT8 DescriptorType;\r
+ UINT8 SlotId;\r
+ UINT8 TTT;\r
+ UINT8 MTT;\r
+ UINT32 MaxPacket0;\r
+ EFI_USB_HUB_DESCRIPTOR *HubDesc;\r
+ EFI_TPL OldTpl;\r
+ EFI_STATUS Status;\r
+ EFI_STATUS RecoveryStatus;\r
+ UINTN MapSize;\r
+ EFI_USB_PORT_STATUS PortStatus;\r
+ UINT32 State;\r
+ EFI_USB_DEVICE_REQUEST ClearPortRequest;\r
+ UINTN Len;\r
+\r
+ //\r
+ // Validate parameters\r
+ //\r
+ if ((Request == NULL) || (TransferResult == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((TransferDirection != EfiUsbDataIn) &&\r
+ (TransferDirection != EfiUsbDataOut) &&\r
+ (TransferDirection != EfiUsbNoData)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((TransferDirection == EfiUsbNoData) &&\r
+ ((Data != NULL) || (*DataLength != 0))) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((TransferDirection != EfiUsbNoData) &&\r
+ ((Data == NULL) || (*DataLength == 0))) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((MaximumPacketLength != 8) && (MaximumPacketLength != 16) &&\r
+ (MaximumPacketLength != 32) && (MaximumPacketLength != 64) &&\r
+ (MaximumPacketLength != 512)\r
+ ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((DeviceSpeed == EFI_USB_SPEED_SUPER) && (MaximumPacketLength != 512)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ OldTpl = gBS->RaiseTPL (XHC_TPL);\r
+\r
+ Xhc = XHC_FROM_THIS (This);\r
+\r
+ Status = EFI_DEVICE_ERROR;\r
+ *TransferResult = EFI_USB_ERR_SYSTEM;\r
+ Len = 0;\r
+\r
+ if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcControlTransfer: HC halted at entrance\n"));\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Check if the device is still enabled before every transaction.\r
+ //\r
+ SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);\r
+ if (SlotId == 0) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Hook the Set_Address request from UsbBus.\r
+ // According to XHCI 1.0 spec, the Set_Address request is replaced by XHCI's Address_Device cmd.\r
+ //\r
+ if ((Request->Request == USB_REQ_SET_ADDRESS) &&\r
+ (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE))) {\r
+ //\r
+ // Reset the BusDevAddr field of all disabled entries in UsbDevContext array firstly.\r
+ // This way is used to clean the history to avoid using wrong device address by XhcAsyncInterruptTransfer().\r
+ //\r
+ for (Index = 0; Index < 255; Index++) {\r
+ if (!Xhc->UsbDevContext[Index + 1].Enabled &&\r
+ (Xhc->UsbDevContext[Index + 1].SlotId == 0) &&\r
+ (Xhc->UsbDevContext[Index + 1].BusDevAddr == (UINT8)Request->Value)) {\r
+ Xhc->UsbDevContext[Index + 1].BusDevAddr = 0;\r
+ }\r
+ }\r
+\r
+ if (Xhc->UsbDevContext[SlotId].XhciDevAddr == 0) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto ON_EXIT;\r
+ }\r
+ //\r
+ // The actual device address has been assigned by XHCI during initializing the device slot.\r
+ // So we just need establish the mapping relationship between the device address requested from UsbBus\r
+ // and the actual device address assigned by XHCI. The the following invocations through EFI_USB2_HC_PROTOCOL interface\r
+ // can find out the actual device address by it.\r
+ //\r
+ Xhc->UsbDevContext[SlotId].BusDevAddr = (UINT8)Request->Value;\r
+ Status = EFI_SUCCESS;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Create a new URB, insert it into the asynchronous\r
+ // schedule list, then poll the execution status.\r
+ // Note that we encode the direction in address although default control\r
+ // endpoint is bidirectional. XhcCreateUrb expects this\r
+ // combination of Ep addr and its direction.\r
+ //\r
+ Endpoint = (UINT8) (0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0));\r
+ Urb = XhcCreateUrb (\r
+ Xhc,\r
+ DeviceAddress,\r
+ Endpoint,\r
+ DeviceSpeed,\r
+ MaximumPacketLength,\r
+ XHC_CTRL_TRANSFER,\r
+ Request,\r
+ Data,\r
+ *DataLength,\r
+ NULL,\r
+ NULL\r
+ );\r
+\r
+ if (Urb == NULL) {\r
+ DEBUG ((EFI_D_ERROR, "XhcControlTransfer: failed to create URB"));\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);\r
+\r
+ //\r
+ // Get the status from URB. The result is updated in XhcCheckUrbResult\r
+ // which is called by XhcExecTransfer\r
+ //\r
+ *TransferResult = Urb->Result;\r
+ *DataLength = Urb->Completed;\r
+\r
+ if (*TransferResult == EFI_USB_NOERROR) {\r
+ Status = EFI_SUCCESS;\r
+ } else if (*TransferResult == EFI_USB_ERR_STALL) {\r
+ RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);\r
+ if (EFI_ERROR (RecoveryStatus)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcControlTransfer: XhcRecoverHaltedEndpoint failed\n"));\r
+ }\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto FREE_URB;\r
+ } else {\r
+ goto FREE_URB;\r
+ }\r
+\r
+ Xhc->PciIo->Flush (Xhc->PciIo);\r
+ \r
+ if (Urb->DataMap != NULL) {\r
+ Status = Xhc->PciIo->Unmap (Xhc->PciIo, Urb->DataMap);\r
+ ASSERT_EFI_ERROR (Status);\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto FREE_URB;\r
+ } \r
+ }\r
+\r
+ //\r
+ // Hook Get_Descriptor request from UsbBus as we need evaluate context and configure endpoint.\r
+ // Hook Get_Status request form UsbBus as we need trace device attach/detach event happened at hub.\r
+ // Hook Set_Config request from UsbBus as we need configure device endpoint.\r
+ //\r
+ if ((Request->Request == USB_REQ_GET_DESCRIPTOR) &&\r
+ ((Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE)) || \r
+ ((Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_CLASS, USB_TARGET_DEVICE))))) {\r
+ DescriptorType = (UINT8)(Request->Value >> 8);\r
+ if ((DescriptorType == USB_DESC_TYPE_DEVICE) && ((*DataLength == sizeof (EFI_USB_DEVICE_DESCRIPTOR)) || ((DeviceSpeed == EFI_USB_SPEED_FULL) && (*DataLength == 8)))) {\r
+ ASSERT (Data != NULL);\r
+ //\r
+ // Store a copy of device scriptor as hub device need this info to configure endpoint.\r
+ //\r
+ CopyMem (&Xhc->UsbDevContext[SlotId].DevDesc, Data, *DataLength);\r
+ if (Xhc->UsbDevContext[SlotId].DevDesc.BcdUSB == 0x0300) {\r
+ //\r
+ // If it's a usb3.0 device, then its max packet size is a 2^n.\r
+ //\r
+ MaxPacket0 = 1 << Xhc->UsbDevContext[SlotId].DevDesc.MaxPacketSize0;\r
+ } else {\r
+ MaxPacket0 = Xhc->UsbDevContext[SlotId].DevDesc.MaxPacketSize0;\r
+ }\r
+ Xhc->UsbDevContext[SlotId].ConfDesc = AllocateZeroPool (Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations * sizeof (EFI_USB_CONFIG_DESCRIPTOR *));\r
+ if (Xhc->HcCParams.Data.Csz == 0) {\r
+ Status = XhcEvaluateContext (Xhc, SlotId, MaxPacket0);\r
+ } else {\r
+ Status = XhcEvaluateContext64 (Xhc, SlotId, MaxPacket0);\r
+ }\r
+ } else if (DescriptorType == USB_DESC_TYPE_CONFIG) {\r
+ ASSERT (Data != NULL);\r
+ if (*DataLength == ((UINT16 *)Data)[1]) {\r
+ //\r
+ // Get configuration value from request, Store the configuration descriptor for Configure_Endpoint cmd.\r
+ //\r
+ Index = (UINT8)Request->Value;\r
+ ASSERT (Index < Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations);\r
+ Xhc->UsbDevContext[SlotId].ConfDesc[Index] = AllocateZeroPool(*DataLength);\r
+ CopyMem (Xhc->UsbDevContext[SlotId].ConfDesc[Index], Data, *DataLength);\r
+ }\r
+ } else if (((DescriptorType == USB_DESC_TYPE_HUB) ||\r
+ (DescriptorType == USB_DESC_TYPE_HUB_SUPER_SPEED)) && (*DataLength > 2)) {\r
+ ASSERT (Data != NULL);\r
+ HubDesc = (EFI_USB_HUB_DESCRIPTOR *)Data;\r
+ ASSERT (HubDesc->NumPorts <= 15);\r
+ //\r
+ // The bit 5,6 of HubCharacter field of Hub Descriptor is TTT.\r
+ //\r
+ TTT = (UINT8)((HubDesc->HubCharacter & (BIT5 | BIT6)) >> 5);\r
+ if (Xhc->UsbDevContext[SlotId].DevDesc.DeviceProtocol == 2) {\r
+ //\r
+ // Don't support multi-TT feature for super speed hub now.\r
+ //\r
+ MTT = 0;\r
+ DEBUG ((EFI_D_ERROR, "XHCI: Don't support multi-TT feature for Hub now. (force to disable MTT)\n"));\r
+ } else {\r
+ MTT = 0;\r
+ }\r
+\r
+ if (Xhc->HcCParams.Data.Csz == 0) {\r
+ Status = XhcConfigHubContext (Xhc, SlotId, HubDesc->NumPorts, TTT, MTT);\r
+ } else {\r
+ Status = XhcConfigHubContext64 (Xhc, SlotId, HubDesc->NumPorts, TTT, MTT);\r
+ }\r
+ }\r
+ } else if ((Request->Request == USB_REQ_SET_CONFIG) &&\r
+ (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE))) {\r
+ //\r
+ // Hook Set_Config request from UsbBus as we need configure device endpoint.\r
+ //\r
+ for (Index = 0; Index < Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations; Index++) {\r
+ if (Xhc->UsbDevContext[SlotId].ConfDesc[Index]->ConfigurationValue == (UINT8)Request->Value) {\r
+ if (Xhc->HcCParams.Data.Csz == 0) {\r
+ Status = XhcSetConfigCmd (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Index]);\r
+ } else {\r
+ Status = XhcSetConfigCmd64 (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Index]);\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ } else if ((Request->Request == USB_REQ_GET_STATUS) &&\r
+ (Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER))) {\r
+ ASSERT (Data != NULL);\r
+ //\r
+ // Hook Get_Status request from UsbBus to keep track of the port status change.\r
+ //\r
+ State = *(UINT32 *)Data;\r
+ PortStatus.PortStatus = 0;\r
+ PortStatus.PortChangeStatus = 0;\r
+\r
+ if (DeviceSpeed == EFI_USB_SPEED_SUPER) {\r
+ //\r
+ // For super speed hub, its bit10~12 presents the attached device speed.\r
+ //\r
+ if ((State & XHC_PORTSC_PS) >> 10 == 0) {\r
+ PortStatus.PortStatus |= USB_PORT_STAT_SUPER_SPEED;\r
+ }\r
+ } else {\r
+ //\r
+ // For high or full/low speed hub, its bit9~10 presents the attached device speed.\r
+ //\r
+ if (XHC_BIT_IS_SET (State, BIT9)) {\r
+ PortStatus.PortStatus |= USB_PORT_STAT_LOW_SPEED;\r
+ } else if (XHC_BIT_IS_SET (State, BIT10)) {\r
+ PortStatus.PortStatus |= USB_PORT_STAT_HIGH_SPEED;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Convert the XHCI port/port change state to UEFI status\r
+ //\r
+ MapSize = sizeof (mUsbHubPortStateMap) / sizeof (USB_PORT_STATE_MAP);\r
+ for (Index = 0; Index < MapSize; Index++) {\r
+ if (XHC_BIT_IS_SET (State, mUsbHubPortStateMap[Index].HwState)) {\r
+ PortStatus.PortStatus = (UINT16) (PortStatus.PortStatus | mUsbHubPortStateMap[Index].UefiState);\r
+ }\r
+ }\r
+\r
+ MapSize = sizeof (mUsbHubPortChangeMap) / sizeof (USB_PORT_STATE_MAP);\r
+ for (Index = 0; Index < MapSize; Index++) {\r
+ if (XHC_BIT_IS_SET (State, mUsbHubPortChangeMap[Index].HwState)) {\r
+ PortStatus.PortChangeStatus = (UINT16) (PortStatus.PortChangeStatus | mUsbHubPortChangeMap[Index].UefiState);\r
+ }\r
+ }\r
+\r
+ MapSize = sizeof (mUsbHubClearPortChangeMap) / sizeof (USB_CLEAR_PORT_MAP);\r
+\r
+ for (Index = 0; Index < MapSize; Index++) {\r
+ if (XHC_BIT_IS_SET (State, mUsbHubClearPortChangeMap[Index].HwState)) {\r
+ ZeroMem (&ClearPortRequest, sizeof (EFI_USB_DEVICE_REQUEST));\r
+ ClearPortRequest.RequestType = USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER);\r
+ ClearPortRequest.Request = (UINT8) USB_REQ_CLEAR_FEATURE;\r
+ ClearPortRequest.Value = mUsbHubClearPortChangeMap[Index].Selector;\r
+ ClearPortRequest.Index = Request->Index;\r
+ ClearPortRequest.Length = 0;\r
+\r
+ XhcControlTransfer (\r
+ This, \r
+ DeviceAddress,\r
+ DeviceSpeed,\r
+ MaximumPacketLength,\r
+ &ClearPortRequest,\r
+ EfiUsbNoData,\r
+ NULL,\r
+ &Len,\r
+ Timeout,\r
+ Translator,\r
+ TransferResult\r
+ );\r
+ }\r
+ }\r
+\r
+ XhcPollPortStatusChange (Xhc, Xhc->UsbDevContext[SlotId].RouteString, (UINT8)Request->Index, &PortStatus);\r
+\r
+ *(UINT32 *)Data = *(UINT32*)&PortStatus;\r
+ }\r
+\r
+FREE_URB:\r
+ FreePool (Urb);\r
+\r
+ON_EXIT:\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcControlTransfer: error - %r, transfer - %x\n", Status, *TransferResult));\r
+ }\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Submits bulk transfer to a bulk endpoint of a USB device.\r
+\r
+ @param This This EFI_USB2_HC_PROTOCOL instance.\r
+ @param DeviceAddress Target device address.\r
+ @param EndPointAddress Endpoint number and its direction in bit 7.\r
+ @param DeviceSpeed Device speed, Low speed device doesn't support bulk\r
+ transfer.\r
+ @param MaximumPacketLength Maximum packet size the endpoint is capable of\r
+ sending or receiving.\r
+ @param DataBuffersNumber Number of data buffers prepared for the transfer.\r
+ @param Data Array of pointers to the buffers of data to transmit\r
+ from or receive into.\r
+ @param DataLength The lenght of the data buffer.\r
+ @param DataToggle On input, the initial data toggle for the transfer;\r
+ On output, it is updated to to next data toggle to\r
+ use of the subsequent bulk transfer.\r
+ @param Timeout Indicates the maximum time, in millisecond, which\r
+ the transfer is allowed to complete.\r
+ @param Translator A pointr to the transaction translator data.\r
+ @param TransferResult A pointer to the detailed result information of the\r
+ bulk transfer.\r
+\r
+ @retval EFI_SUCCESS The transfer was completed successfully.\r
+ @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.\r
+ @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
+ @retval EFI_TIMEOUT The transfer failed due to timeout.\r
+ @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcBulkTransfer (\r
+ IN EFI_USB2_HC_PROTOCOL *This,\r
+ IN UINT8 DeviceAddress,\r
+ IN UINT8 EndPointAddress,\r
+ IN UINT8 DeviceSpeed,\r
+ IN UINTN MaximumPacketLength,\r
+ IN UINT8 DataBuffersNumber,\r
+ IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],\r
+ IN OUT UINTN *DataLength,\r
+ IN OUT UINT8 *DataToggle,\r
+ IN UINTN Timeout,\r
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
+ OUT UINT32 *TransferResult\r
+ )\r
+{\r
+ USB_XHCI_INSTANCE *Xhc;\r
+ URB *Urb;\r
+ UINT8 SlotId;\r
+ EFI_STATUS Status;\r
+ EFI_STATUS RecoveryStatus;\r
+ EFI_TPL OldTpl;\r
+\r
+ //\r
+ // Validate the parameters\r
+ //\r
+ if ((DataLength == NULL) || (*DataLength == 0) ||\r
+ (Data == NULL) || (Data[0] == NULL) || (TransferResult == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((*DataToggle != 0) && (*DataToggle != 1)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((DeviceSpeed == EFI_USB_SPEED_LOW) ||\r
+ ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||\r
+ ((EFI_USB_SPEED_HIGH == DeviceSpeed) && (MaximumPacketLength > 512)) ||\r
+ ((EFI_USB_SPEED_SUPER == DeviceSpeed) && (MaximumPacketLength > 1024))) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ OldTpl = gBS->RaiseTPL (XHC_TPL);\r
+\r
+ Xhc = XHC_FROM_THIS (This);\r
+\r
+ *TransferResult = EFI_USB_ERR_SYSTEM;\r
+ Status = EFI_DEVICE_ERROR;\r
+\r
+ if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: HC is halted\n"));\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Check if the device is still enabled before every transaction.\r
+ //\r
+ SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);\r
+ if (SlotId == 0) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Create a new URB, insert it into the asynchronous\r
+ // schedule list, then poll the execution status.\r
+ //\r
+ Urb = XhcCreateUrb (\r
+ Xhc,\r
+ DeviceAddress,\r
+ EndPointAddress,\r
+ DeviceSpeed,\r
+ MaximumPacketLength,\r
+ XHC_BULK_TRANSFER,\r
+ NULL,\r
+ Data[0],\r
+ *DataLength,\r
+ NULL,\r
+ NULL\r
+ );\r
+\r
+ if (Urb == NULL) {\r
+ DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: failed to create URB\n"));\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);\r
+\r
+ *TransferResult = Urb->Result;\r
+ *DataLength = Urb->Completed;\r
+\r
+ if (*TransferResult == EFI_USB_NOERROR) {\r
+ Status = EFI_SUCCESS;\r
+ } else if (*TransferResult == EFI_USB_ERR_STALL) {\r
+ RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);\r
+ if (EFI_ERROR (RecoveryStatus)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: XhcRecoverHaltedEndpoint failed\n"));\r
+ }\r
+ Status = EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ Xhc->PciIo->Flush (Xhc->PciIo);\r
+ XhcFreeUrb (Xhc, Urb);\r
+\r
+ON_EXIT:\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: error - %r, transfer - %x\n", Status, *TransferResult));\r
+ }\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Submits an asynchronous interrupt transfer to an\r
+ interrupt endpoint of a USB device.\r
+\r
+ @param This This EFI_USB2_HC_PROTOCOL instance.\r
+ @param DeviceAddress Target device address.\r
+ @param EndPointAddress Endpoint number and its direction encoded in bit 7\r
+ @param DeviceSpeed Indicates device speed.\r
+ @param MaximumPacketLength Maximum packet size the target endpoint is capable\r
+ @param IsNewTransfer If TRUE, to submit an new asynchronous interrupt\r
+ transfer If FALSE, to remove the specified\r
+ asynchronous interrupt.\r
+ @param DataToggle On input, the initial data toggle to use; on output,\r
+ it is updated to indicate the next data toggle.\r
+ @param PollingInterval The he interval, in milliseconds, that the transfer\r
+ is polled.\r
+ @param DataLength The length of data to receive at the rate specified\r
+ by PollingInterval.\r
+ @param Translator Transaction translator to use.\r
+ @param CallBackFunction Function to call at the rate specified by\r
+ PollingInterval.\r
+ @param Context Context to CallBackFunction.\r
+\r
+ @retval EFI_SUCCESS The request has been successfully submitted or canceled.\r
+ @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
+ @retval EFI_OUT_OF_RESOURCES The request failed due to a lack of resources.\r
+ @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcAsyncInterruptTransfer (\r
+ IN EFI_USB2_HC_PROTOCOL *This,\r
+ IN UINT8 DeviceAddress,\r
+ IN UINT8 EndPointAddress,\r
+ IN UINT8 DeviceSpeed,\r
+ IN UINTN MaximumPacketLength,\r
+ IN BOOLEAN IsNewTransfer,\r
+ IN OUT UINT8 *DataToggle,\r
+ IN UINTN PollingInterval,\r
+ IN UINTN DataLength,\r
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,\r
+ IN VOID *Context OPTIONAL\r
+ )\r
+{\r
+ USB_XHCI_INSTANCE *Xhc;\r
+ URB *Urb;\r
+ EFI_STATUS Status;\r
+ UINT8 SlotId;\r
+ UINT8 Index;\r
+ UINT8 *Data;\r
+ EFI_TPL OldTpl;\r
+\r
+ //\r
+ // Validate parameters\r
+ //\r
+ if (!XHCI_IS_DATAIN (EndPointAddress)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (IsNewTransfer) {\r
+ if (DataLength == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((PollingInterval > 255) || (PollingInterval < 1)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+ OldTpl = gBS->RaiseTPL (XHC_TPL);\r
+\r
+ Xhc = XHC_FROM_THIS (This);\r
+\r
+ //\r
+ // Delete Async interrupt transfer request.\r
+ //\r
+ if (!IsNewTransfer) {\r
+ //\r
+ // The delete request may happen after device is detached.\r
+ //\r
+ for (Index = 0; Index < 255; Index++) {\r
+ if (Xhc->UsbDevContext[Index + 1].BusDevAddr == DeviceAddress) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Index == 255) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Status = XhciDelAsyncIntTransfer (Xhc, DeviceAddress, EndPointAddress);\r
+ DEBUG ((EFI_D_INFO, "XhcAsyncInterruptTransfer: remove old transfer for addr %d, Status = %r\n", DeviceAddress, Status));\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcAsyncInterruptTransfer: HC is halt\n"));\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Check if the device is still enabled before every transaction.\r
+ //\r
+ SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);\r
+ if (SlotId == 0) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Data = AllocateZeroPool (DataLength);\r
+\r
+ if (Data == NULL) {\r
+ DEBUG ((EFI_D_ERROR, "XhcAsyncInterruptTransfer: failed to allocate buffer\n"));\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Urb = XhcCreateUrb (\r
+ Xhc,\r
+ DeviceAddress,\r
+ EndPointAddress,\r
+ DeviceSpeed,\r
+ MaximumPacketLength,\r
+ XHC_INT_TRANSFER_ASYNC,\r
+ NULL,\r
+ Data,\r
+ DataLength,\r
+ CallBackFunction,\r
+ Context\r
+ );\r
+\r
+ if (Urb == NULL) {\r
+ DEBUG ((EFI_D_ERROR, "XhcAsyncInterruptTransfer: failed to create URB\n"));\r
+ FreePool (Data);\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ InsertHeadList (&Xhc->AsyncIntTransfers, &Urb->UrbList);\r
+ //\r
+ // Ring the doorbell\r
+ //\r
+ Status = RingIntTransferDoorBell (Xhc, Urb);\r
+\r
+ON_EXIT:\r
+ Xhc->PciIo->Flush (Xhc->PciIo);\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Submits synchronous interrupt transfer to an interrupt endpoint\r
+ of a USB device.\r
+\r
+ @param This This EFI_USB2_HC_PROTOCOL instance.\r
+ @param DeviceAddress Target device address.\r
+ @param EndPointAddress Endpoint number and its direction encoded in bit 7\r
+ @param DeviceSpeed Indicates device speed.\r
+ @param MaximumPacketLength Maximum packet size the target endpoint is capable\r
+ of sending or receiving.\r
+ @param Data Buffer of data that will be transmitted to USB\r
+ device or received from USB device.\r
+ @param DataLength On input, the size, in bytes, of the data buffer; On\r
+ output, the number of bytes transferred.\r
+ @param DataToggle On input, the initial data toggle to use; on output,\r
+ it is updated to indicate the next data toggle.\r
+ @param Timeout Maximum time, in second, to complete.\r
+ @param Translator Transaction translator to use.\r
+ @param TransferResult Variable to receive the transfer result.\r
+\r
+ @return EFI_SUCCESS The transfer was completed successfully.\r
+ @return EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.\r
+ @return EFI_INVALID_PARAMETER Some parameters are invalid.\r
+ @return EFI_TIMEOUT The transfer failed due to timeout.\r
+ @return EFI_DEVICE_ERROR The failed due to host controller or device error\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcSyncInterruptTransfer (\r
+ IN EFI_USB2_HC_PROTOCOL *This,\r
+ IN UINT8 DeviceAddress,\r
+ IN UINT8 EndPointAddress,\r
+ IN UINT8 DeviceSpeed,\r
+ IN UINTN MaximumPacketLength,\r
+ IN OUT VOID *Data,\r
+ IN OUT UINTN *DataLength,\r
+ IN OUT UINT8 *DataToggle,\r
+ IN UINTN Timeout,\r
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
+ OUT UINT32 *TransferResult\r
+ )\r
+{\r
+ USB_XHCI_INSTANCE *Xhc;\r
+ URB *Urb;\r
+ UINT8 SlotId;\r
+ EFI_STATUS Status;\r
+ EFI_STATUS RecoveryStatus;\r
+ EFI_TPL OldTpl;\r
+\r
+ //\r
+ // Validates parameters\r
+ //\r
+ if ((DataLength == NULL) || (*DataLength == 0) ||\r
+ (Data == NULL) || (TransferResult == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (!XHCI_IS_DATAIN (EndPointAddress)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) ||\r
+ ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||\r
+ ((DeviceSpeed == EFI_USB_SPEED_HIGH) && (MaximumPacketLength > 3072))) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ OldTpl = gBS->RaiseTPL (XHC_TPL);\r
+\r
+ Xhc = XHC_FROM_THIS (This);\r
+\r
+ *TransferResult = EFI_USB_ERR_SYSTEM;\r
+ Status = EFI_DEVICE_ERROR;\r
+\r
+ if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {\r
+ DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: HC is halt\n"));\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Check if the device is still enabled before every transaction.\r
+ //\r
+ SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);\r
+ if (SlotId == 0) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Urb = XhcCreateUrb (\r
+ Xhc,\r
+ DeviceAddress,\r
+ EndPointAddress,\r
+ DeviceSpeed,\r
+ MaximumPacketLength,\r
+ XHC_INT_TRANSFER_SYNC,\r
+ NULL,\r
+ Data,\r
+ *DataLength,\r
+ NULL,\r
+ NULL\r
+ );\r
+\r
+ if (Urb == NULL) {\r
+ DEBUG ((EFI_D_ERROR, "XhcSyncInterruptTransfer: failed to create URB\n"));\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);\r
+\r
+ *TransferResult = Urb->Result;\r
+ *DataLength = Urb->Completed;\r
+\r
+ if (*TransferResult == EFI_USB_NOERROR) {\r
+ Status = EFI_SUCCESS;\r
+ } else if (*TransferResult == EFI_USB_ERR_STALL) {\r
+ RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);\r
+ if (EFI_ERROR (RecoveryStatus)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcSyncInterruptTransfer: XhcRecoverHaltedEndpoint failed\n"));\r
+ }\r
+ Status = EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ Xhc->PciIo->Flush (Xhc->PciIo);\r
+ XhcFreeUrb (Xhc, Urb);\r
+\r
+ON_EXIT:\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcSyncInterruptTransfer: error - %r, transfer - %x\n", Status, *TransferResult));\r
+ }\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Submits isochronous transfer to a target USB device.\r
+\r
+ @param This This EFI_USB2_HC_PROTOCOL instance.\r
+ @param DeviceAddress Target device address.\r
+ @param EndPointAddress End point address with its direction.\r
+ @param DeviceSpeed Device speed, Low speed device doesn't support this\r
+ type.\r
+ @param MaximumPacketLength Maximum packet size that the endpoint is capable of\r
+ sending or receiving.\r
+ @param DataBuffersNumber Number of data buffers prepared for the transfer.\r
+ @param Data Array of pointers to the buffers of data that will\r
+ be transmitted to USB device or received from USB\r
+ device.\r
+ @param DataLength The size, in bytes, of the data buffer.\r
+ @param Translator Transaction translator to use.\r
+ @param TransferResult Variable to receive the transfer result.\r
+\r
+ @return EFI_UNSUPPORTED Isochronous transfer is unsupported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcIsochronousTransfer (\r
+ IN EFI_USB2_HC_PROTOCOL *This,\r
+ IN UINT8 DeviceAddress,\r
+ IN UINT8 EndPointAddress,\r
+ IN UINT8 DeviceSpeed,\r
+ IN UINTN MaximumPacketLength,\r
+ IN UINT8 DataBuffersNumber,\r
+ IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
+ IN UINTN DataLength,\r
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
+ OUT UINT32 *TransferResult\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+\r
+/**\r
+ Submits Async isochronous transfer to a target USB device.\r
+\r
+ @param This This EFI_USB2_HC_PROTOCOL instance.\r
+ @param DeviceAddress Target device address.\r
+ @param EndPointAddress End point address with its direction.\r
+ @param DeviceSpeed Device speed, Low speed device doesn't support this\r
+ type.\r
+ @param MaximumPacketLength Maximum packet size that the endpoint is capable of\r
+ sending or receiving.\r
+ @param DataBuffersNumber Number of data buffers prepared for the transfer.\r
+ @param Data Array of pointers to the buffers of data that will\r
+ be transmitted to USB device or received from USB\r
+ device.\r
+ @param DataLength The size, in bytes, of the data buffer.\r
+ @param Translator Transaction translator to use.\r
+ @param IsochronousCallBack Function to be called when the transfer complete.\r
+ @param Context Context passed to the call back function as\r
+ parameter.\r
+\r
+ @return EFI_UNSUPPORTED Isochronous transfer isn't supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcAsyncIsochronousTransfer (\r
+ IN EFI_USB2_HC_PROTOCOL *This,\r
+ IN UINT8 DeviceAddress,\r
+ IN UINT8 EndPointAddress,\r
+ IN UINT8 DeviceSpeed,\r
+ IN UINTN MaximumPacketLength,\r
+ IN UINT8 DataBuffersNumber,\r
+ IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
+ IN UINTN DataLength,\r
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+ Entry point for EFI drivers.\r
+\r
+ @param ImageHandle EFI_HANDLE.\r
+ @param SystemTable EFI_SYSTEM_TABLE.\r
+\r
+ @retval EFI_SUCCESS Success.\r
+ @retval Others Fail.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcDriverEntryPoint (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ return EfiLibInstallDriverBindingComponentName2 (\r
+ ImageHandle,\r
+ SystemTable,\r
+ &gXhciDriverBinding,\r
+ ImageHandle,\r
+ &gXhciComponentName,\r
+ &gXhciComponentName2\r
+ );\r
+}\r
+\r
+\r
+/**\r
+ Test to see if this driver supports ControllerHandle. Any\r
+ ControllerHandle that has Usb2HcProtocol installed will\r
+ be supported.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Controller Handle of device to test.\r
+ @param RemainingDevicePath Not used.\r
+\r
+ @return EFI_SUCCESS This driver supports this device.\r
+ @return EFI_UNSUPPORTED This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcDriverBindingSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ USB_CLASSC UsbClassCReg;\r
+\r
+ //\r
+ // Test whether there is PCI IO Protocol attached on the controller handle.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint8,\r
+ PCI_CLASSCODE_OFFSET,\r
+ sizeof (USB_CLASSC) / sizeof (UINT8),\r
+ &UsbClassCReg\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_UNSUPPORTED;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Test whether the controller belongs to Xhci type\r
+ //\r
+ if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||\r
+ (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||\r
+ (UsbClassCReg.ProgInterface != PCI_IF_XHCI)) {\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
+\r
+ON_EXIT:\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Create and initialize a USB_XHCI_INSTANCE structure.\r
+\r
+ @param PciIo The PciIo on this device.\r
+ @param DevicePath The device path of host controller.\r
+ @param OriginalPciAttributes Original PCI attributes.\r
+\r
+ @return The allocated and initialized USB_XHCI_INSTANCE structure if created,\r
+ otherwise NULL.\r
+\r
+**/\r
+USB_XHCI_INSTANCE*\r
+XhcCreateUsbHc (\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ IN UINT64 OriginalPciAttributes\r
+ )\r
+{\r
+ USB_XHCI_INSTANCE *Xhc;\r
+ EFI_STATUS Status;\r
+ UINT32 PageSize;\r
+ UINT16 ExtCapReg;\r
+\r
+ Xhc = AllocateZeroPool (sizeof (USB_XHCI_INSTANCE));\r
+\r
+ if (Xhc == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Initialize private data structure\r
+ //\r
+ Xhc->Signature = XHCI_INSTANCE_SIG;\r
+ Xhc->PciIo = PciIo;\r
+ Xhc->DevicePath = DevicePath;\r
+ Xhc->OriginalPciAttributes = OriginalPciAttributes;\r
+ CopyMem (&Xhc->Usb2Hc, &gXhciUsb2HcTemplate, sizeof (EFI_USB2_HC_PROTOCOL));\r
+\r
+ InitializeListHead (&Xhc->AsyncIntTransfers);\r
+\r
+ //\r
+ // Be caution that the Offset passed to XhcReadCapReg() should be Dword align\r
+ //\r
+ Xhc->CapLength = XhcReadCapReg8 (Xhc, XHC_CAPLENGTH_OFFSET);\r
+ Xhc->HcSParams1.Dword = XhcReadCapReg (Xhc, XHC_HCSPARAMS1_OFFSET);\r
+ Xhc->HcSParams2.Dword = XhcReadCapReg (Xhc, XHC_HCSPARAMS2_OFFSET);\r
+ Xhc->HcCParams.Dword = XhcReadCapReg (Xhc, XHC_HCCPARAMS_OFFSET);\r
+ Xhc->DBOff = XhcReadCapReg (Xhc, XHC_DBOFF_OFFSET);\r
+ Xhc->RTSOff = XhcReadCapReg (Xhc, XHC_RTSOFF_OFFSET);\r
+\r
+ //\r
+ // This PageSize field defines the page size supported by the xHC implementation.\r
+ // This xHC supports a page size of 2^(n+12) if bit n is Set. For example,\r
+ // if bit 0 is Set, the xHC supports 4k byte page sizes.\r
+ //\r
+ PageSize = XhcReadOpReg(Xhc, XHC_PAGESIZE_OFFSET) & XHC_PAGESIZE_MASK;\r
+ Xhc->PageSize = 1 << (HighBitSet32(PageSize) + 12);\r
+\r
+ ExtCapReg = (UINT16) (Xhc->HcCParams.Data.ExtCapReg);\r
+ Xhc->ExtCapRegBase = ExtCapReg << 2;\r
+ Xhc->UsbLegSupOffset = XhcGetCapabilityAddr (Xhc, XHC_CAP_USB_LEGACY);\r
+ Xhc->DebugCapSupOffset = XhcGetCapabilityAddr (Xhc, XHC_CAP_USB_DEBUG);\r
+\r
+ DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: Capability length 0x%x\n", Xhc->CapLength));\r
+ DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: HcSParams1 0x%x\n", Xhc->HcSParams1));\r
+ DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: HcSParams2 0x%x\n", Xhc->HcSParams2));\r
+ DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: HcCParams 0x%x\n", Xhc->HcCParams));\r
+ DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: DBOff 0x%x\n", Xhc->DBOff));\r
+ DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: RTSOff 0x%x\n", Xhc->RTSOff));\r
+ DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: UsbLegSupOffset 0x%x\n", Xhc->UsbLegSupOffset));\r
+ DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: DebugCapSupOffset 0x%x\n", Xhc->DebugCapSupOffset));\r
+\r
+ //\r
+ // Create AsyncRequest Polling Timer\r
+ //\r
+ Status = gBS->CreateEvent (\r
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
+ TPL_CALLBACK,\r
+ XhcMonitorAsyncRequests,\r
+ Xhc,\r
+ &Xhc->PollTimer\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ return Xhc;\r
+\r
+ON_ERROR:\r
+ FreePool (Xhc);\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ One notified function to stop the Host Controller when gBS->ExitBootServices() called.\r
+\r
+ @param Event Pointer to this event\r
+ @param Context Event hanlder private data\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+XhcExitBootService (\r
+ EFI_EVENT Event,\r
+ VOID *Context\r
+ )\r
+\r
+{\r
+ USB_XHCI_INSTANCE *Xhc;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+\r
+ Xhc = (USB_XHCI_INSTANCE*) Context;\r
+ PciIo = Xhc->PciIo;\r
+\r
+ //\r
+ // Stop AsyncRequest Polling timer then stop the XHCI driver\r
+ // and uninstall the XHCI protocl.\r
+ //\r
+ gBS->SetTimer (Xhc->PollTimer, TimerCancel, 0);\r
+ XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);\r
+\r
+ if (Xhc->PollTimer != NULL) {\r
+ gBS->CloseEvent (Xhc->PollTimer);\r
+ }\r
+\r
+ XhcClearBiosOwnership (Xhc);\r
+\r
+ //\r
+ // Restore original PCI attributes\r
+ //\r
+ PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationSet,\r
+ Xhc->OriginalPciAttributes,\r
+ NULL\r
+ );\r
+}\r
+\r
+/**\r
+ Starting the Usb XHCI Driver.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Controller Handle of device to test.\r
+ @param RemainingDevicePath Not used.\r
+\r
+ @return EFI_SUCCESS supports this device.\r
+ @return EFI_UNSUPPORTED do not support this device.\r
+ @return EFI_DEVICE_ERROR cannot be started due to device Error.\r
+ @return EFI_OUT_OF_RESOURCES cannot allocate resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcDriverBindingStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINT64 Supports;\r
+ UINT64 OriginalPciAttributes;\r
+ BOOLEAN PciAttributesSaved;\r
+ USB_XHCI_INSTANCE *Xhc;\r
+ EFI_DEVICE_PATH_PROTOCOL *HcDevicePath;\r
+\r
+ //\r
+ // Open the PciIo Protocol, then enable the USB host controller\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Open Device Path Protocol for on USB host controller\r
+ //\r
+ HcDevicePath = NULL;\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &HcDevicePath,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+\r
+ PciAttributesSaved = FALSE;\r
+ //\r
+ // Save original PCI attributes\r
+ //\r
+ Status = PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationGet,\r
+ 0,\r
+ &OriginalPciAttributes\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto CLOSE_PCIIO;\r
+ }\r
+ PciAttributesSaved = TRUE;\r
+\r
+ Status = PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationSupported,\r
+ 0,\r
+ &Supports\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Supports &= EFI_PCI_DEVICE_ENABLE;\r
+ Status = PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationEnable,\r
+ Supports,\r
+ NULL\r
+ );\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcDriverBindingStart: failed to enable controller\n"));\r
+ goto CLOSE_PCIIO;\r
+ }\r
+\r
+ //\r
+ // Create then install USB2_HC_PROTOCOL\r
+ //\r
+ Xhc = XhcCreateUsbHc (PciIo, HcDevicePath, OriginalPciAttributes);\r
+\r
+ if (Xhc == NULL) {\r
+ DEBUG ((EFI_D_ERROR, "XhcDriverBindingStart: failed to create USB2_HC\n"));\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ XhcSetBiosOwnership (Xhc);\r
+\r
+ XhcResetHC (Xhc, XHC_RESET_TIMEOUT);\r
+ ASSERT (XhcIsHalt (Xhc));\r
+\r
+ //\r
+ // After Chip Hardware Reset wait until the Controller Not Ready (CNR) flag\r
+ // in the USBSTS is '0' before writing any xHC Operational or Runtime registers.\r
+ //\r
+ ASSERT (!(XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_CNR)));\r
+\r
+ //\r
+ // Initialize the schedule\r
+ //\r
+ XhcInitSched (Xhc);\r
+\r
+ //\r
+ // Start the Host Controller\r
+ //\r
+ XhcRunHC(Xhc, XHC_GENERIC_TIMEOUT);\r
+\r
+ //\r
+ // Start the asynchronous interrupt monitor\r
+ //\r
+ Status = gBS->SetTimer (Xhc->PollTimer, TimerPeriodic, XHC_ASYNC_TIMER_INTERVAL);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcDriverBindingStart: failed to start async interrupt monitor\n"));\r
+ XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);\r
+ goto FREE_POOL;\r
+ }\r
+\r
+ //\r
+ // Create event to stop the HC when exit boot service.\r
+ //\r
+ Status = gBS->CreateEventEx (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ XhcExitBootService,\r
+ Xhc,\r
+ &gEfiEventExitBootServicesGuid,\r
+ &Xhc->ExitBootServiceEvent\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto FREE_POOL;\r
+ }\r
+\r
+ //\r
+ // Install the component name protocol, don't fail the start\r
+ // because of something for display.\r
+ //\r
+ AddUnicodeString2 (\r
+ "eng",\r
+ gXhciComponentName.SupportedLanguages,\r
+ &Xhc->ControllerNameTable,\r
+ L"eXtensible Host Controller (USB 3.0)",\r
+ TRUE\r
+ );\r
+ AddUnicodeString2 (\r
+ "en",\r
+ gXhciComponentName2.SupportedLanguages,\r
+ &Xhc->ControllerNameTable,\r
+ L"eXtensible Host Controller (USB 3.0)",\r
+ FALSE\r
+ );\r
+\r
+ Status = gBS->InstallProtocolInterface (\r
+ &Controller,\r
+ &gEfiUsb2HcProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &Xhc->Usb2Hc\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "XhcDriverBindingStart: failed to install USB2_HC Protocol\n"));\r
+ goto FREE_POOL;\r
+ }\r
+\r
+ DEBUG ((EFI_D_INFO, "XhcDriverBindingStart: XHCI started for controller @ %x\n", Controller));\r
+ return EFI_SUCCESS;\r
+\r
+FREE_POOL:\r
+ gBS->CloseEvent (Xhc->PollTimer);\r
+ XhcFreeSched (Xhc);\r
+ FreePool (Xhc);\r
+\r
+CLOSE_PCIIO:\r
+ if (PciAttributesSaved) {\r
+ //\r
+ // Restore original PCI attributes\r
+ //\r
+ PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationSet,\r
+ OriginalPciAttributes,\r
+ NULL\r
+ );\r
+ }\r
+\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Stop this driver on ControllerHandle. Support stoping any child handles\r
+ created by this driver.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Controller Handle of device to stop driver on.\r
+ @param NumberOfChildren Number of Children in the ChildHandleBuffer.\r
+ @param ChildHandleBuffer List of handles for the children we need to stop.\r
+\r
+ @return EFI_SUCCESS Success.\r
+ @return EFI_DEVICE_ERROR Fail.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XhcDriverBindingStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_USB2_HC_PROTOCOL *Usb2Hc;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ USB_XHCI_INSTANCE *Xhc;\r
+ UINT8 Index;\r
+\r
+ //\r
+ // Test whether the Controller handler passed in is a valid\r
+ // Usb controller handle that should be supported, if not,\r
+ // return the error status directly\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiUsb2HcProtocolGuid,\r
+ (VOID **) &Usb2Hc,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = gBS->UninstallProtocolInterface (\r
+ Controller,\r
+ &gEfiUsb2HcProtocolGuid,\r
+ Usb2Hc\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Xhc = XHC_FROM_THIS (Usb2Hc);\r
+ PciIo = Xhc->PciIo;\r
+\r
+ //\r
+ // Stop AsyncRequest Polling timer then stop the XHCI driver\r
+ // and uninstall the XHCI protocl.\r
+ //\r
+ gBS->SetTimer (Xhc->PollTimer, TimerCancel, 0);\r
+\r
+ //\r
+ // Disable the device slots occupied by these devices on its downstream ports.\r
+ // Entry 0 is reserved.\r
+ //\r
+ for (Index = 0; Index < 255; Index++) {\r
+ if (!Xhc->UsbDevContext[Index + 1].Enabled ||\r
+ (Xhc->UsbDevContext[Index + 1].SlotId == 0)) {\r
+ continue;\r
+ }\r
+ if (Xhc->HcCParams.Data.Csz == 0) {\r
+ XhcDisableSlotCmd (Xhc, Xhc->UsbDevContext[Index + 1].SlotId);\r
+ } else {\r
+ XhcDisableSlotCmd64 (Xhc, Xhc->UsbDevContext[Index + 1].SlotId);\r
+ }\r
+ }\r
+\r
+ if (Xhc->PollTimer != NULL) {\r
+ gBS->CloseEvent (Xhc->PollTimer);\r
+ }\r
+\r
+ if (Xhc->ExitBootServiceEvent != NULL) {\r
+ gBS->CloseEvent (Xhc->ExitBootServiceEvent);\r
+ }\r
+\r
+ XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);\r
+ XhcClearBiosOwnership (Xhc);\r
+ XhciDelAllAsyncIntTransfers (Xhc);\r
+ XhcFreeSched (Xhc);\r
+\r
+ if (Xhc->ControllerNameTable) {\r
+ FreeUnicodeStringTable (Xhc->ControllerNameTable);\r
+ }\r
+\r
+ //\r
+ // Restore original PCI attributes\r
+ //\r
+ PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationSet,\r
+ Xhc->OriginalPciAttributes,\r
+ NULL\r
+ );\r
+\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+\r
+ FreePool (Xhc);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
\r
-**/
-
-#ifndef _TCP_IO_H_
+**/\r
+\r
+#ifndef _TCP_IO_H_\r
#define _TCP_IO_H_\r
\r
\r
#include <Protocol/Tcp4.h>\r
#include <Protocol/Tcp6.h>\r
\r
-#include <Library/NetLib.h>
+#include <Library/NetLib.h>\r
\r
#define TCP_VERSION_4 IP_VERSION_4\r
#define TCP_VERSION_6 IP_VERSION_6\r
\r
-///
-/// 10 seconds
-///
+///\r
+/// 10 seconds\r
+///\r
#define TCP_GET_MAPPING_TIMEOUT 100000000U\r
\r
\r
EFI_IPv4_ADDRESS RemoteIp;\r
UINT16 RemotePort;\r
BOOLEAN ActiveFlag;\r
-} TCP4_IO_CONFIG_DATA;
+} TCP4_IO_CONFIG_DATA;\r
\r
-typedef struct {
+typedef struct {\r
UINT16 StationPort;\r
EFI_IPv6_ADDRESS RemoteIp;\r
- UINT16 RemotePort;
+ UINT16 RemotePort;\r
BOOLEAN ActiveFlag;\r
} TCP6_IO_CONFIG_DATA;\r
\r
\r
@retval EFI_SUCCESS The TCP socket is created and configured.\r
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
- @retval EFI_UNSUPPORTED One or more of the control options are not
+ @retval EFI_UNSUPPORTED One or more of the control options are not\r
supported in the implementation.\r
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
@retval Others Failed to create the TCP socket or configure it.\r
**/\r
EFI_STATUS\r
EFIAPI\r
-TcpIoCreateSocket (
- IN EFI_HANDLE Image,
+TcpIoCreateSocket (\r
+ IN EFI_HANDLE Image,\r
IN EFI_HANDLE Controller,\r
- IN UINT8 TcpVersion,
- IN TCP_IO_CONFIG_DATA *ConfigData,
- OUT TCP_IO *TcpIo
- );
-
-/**
- Destroy the socket.
-
- @param[in] TcpIo The TcpIo which wraps the socket to be destroyed.
-
-**/
-VOID
+ IN UINT8 TcpVersion,\r
+ IN TCP_IO_CONFIG_DATA *ConfigData,\r
+ OUT TCP_IO *TcpIo\r
+ );\r
+\r
+/**\r
+ Destroy the socket. \r
+\r
+ @param[in] TcpIo The TcpIo which wraps the socket to be destroyed.\r
+\r
+**/\r
+VOID\r
EFIAPI\r
-TcpIoDestroySocket (
- IN TCP_IO *TcpIo
- );
-
+TcpIoDestroySocket (\r
+ IN TCP_IO *TcpIo\r
+ );\r
+\r
/**\r
Connect to the other endpoint of the TCP socket.\r
\r
@retval Others Other errors as indicated.\r
\r
**/\r
-EFI_STATUS
+EFI_STATUS\r
EFIAPI\r
-TcpIoConnect (
- IN OUT TCP_IO *TcpIo,
- IN EFI_EVENT Timeout
- );
+TcpIoConnect (\r
+ IN OUT TCP_IO *TcpIo,\r
+ IN EFI_EVENT Timeout\r
+ );\r
\r
/**\r
Accept the incomding request from the other endpoint of the TCP socket.\r
IN OUT TCP_IO *TcpIo,\r
IN EFI_EVENT Timeout\r
);\r
-
-/**
- Reset the socket.
-
- @param[in, out] TcpIo The TcpIo wrapping the TCP socket.
-
-**/
-VOID
+ \r
+/**\r
+ Reset the socket.\r
+\r
+ @param[in, out] TcpIo The TcpIo wrapping the TCP socket.\r
+\r
+**/\r
+VOID\r
EFIAPI\r
-TcpIoReset (
- IN OUT TCP_IO *TcpIo
- );
-
+TcpIoReset (\r
+ IN OUT TCP_IO *TcpIo\r
+ );\r
+\r
/**\r
Transmit the Packet to the other endpoint of the socket.\r
\r
@retval Others Other errors as indicated.\r
\r
**/\r
-EFI_STATUS
+EFI_STATUS\r
EFIAPI\r
-TcpIoTransmit (
- IN TCP_IO *TcpIo,
- IN NET_BUF *Packet
- );
-
+TcpIoTransmit (\r
+ IN TCP_IO *TcpIo,\r
+ IN NET_BUF *Packet\r
+ );\r
+\r
/**\r
Receive data from the socket.\r
\r
@retval Others Other errors as indicated.\r
\r
**/\r
-EFI_STATUS
+EFI_STATUS\r
EFIAPI\r
-TcpIoReceive (
- IN OUT TCP_IO *TcpIo,
- IN NET_BUF *Packet,
- IN BOOLEAN AsyncMode,
- IN EFI_EVENT Timeout
- );
+TcpIoReceive (\r
+ IN OUT TCP_IO *TcpIo,\r
+ IN NET_BUF *Packet,\r
+ IN BOOLEAN AsyncMode,\r
+ IN EFI_EVENT Timeout\r
+ );\r
\r
#endif\r
\r
#include <Library/MemoryAllocationLib.h>\r
#include <Library/BaseMemoryLib.h>\r
\r
-/**
+/**\r
The common notify function associated with various TcpIo events. \r
-
- @param[in] Event The event signaled.
- @param[in] Context The context.
-
-**/
-VOID
-EFIAPI
+\r
+ @param[in] Event The event signaled.\r
+ @param[in] Context The context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
TcpIoCommonNotify (\r
- IN EFI_EVENT Event,
- IN VOID *Context
- )
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
{\r
if ((Event == NULL) || (Context == NULL)) {\r
return ;\r
}\r
\r
- *((BOOLEAN *) Context) = TRUE;
+ *((BOOLEAN *) Context) = TRUE;\r
}\r
\r
-/**
+/**\r
The internal function for delay configuring TCP6 when IP6 driver is still in DAD.\r
-
- @param[in] Tcp6 The EFI_TCP6_PROTOCOL protocol instance.
- @param[in] Tcp6ConfigData The Tcp6 configuration data.
-
- @retval EFI_SUCCESS The operational settings successfully
- completed.
+\r
+ @param[in] Tcp6 The EFI_TCP6_PROTOCOL protocol instance.\r
+ @param[in] Tcp6ConfigData The Tcp6 configuration data.\r
+\r
+ @retval EFI_SUCCESS The operational settings successfully\r
+ completed.\r
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
@retval Others Failed to finish the operation.\r
\r
-**/
-EFI_STATUS
+**/\r
+EFI_STATUS\r
TcpIoGetMapping (\r
- IN EFI_TCP6_PROTOCOL *Tcp6,
- IN EFI_TCP6_CONFIG_DATA *Tcp6ConfigData
- )
-{
- EFI_STATUS Status;
- EFI_EVENT Event;
+ IN EFI_TCP6_PROTOCOL *Tcp6,\r
+ IN EFI_TCP6_CONFIG_DATA *Tcp6ConfigData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_EVENT Event;\r
\r
if ((Tcp6 == NULL) || (Tcp6ConfigData == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- Event = NULL;
- Status = gBS->CreateEvent (
- EVT_TIMER,
- TPL_CALLBACK,
- NULL,
- NULL,
- &Event
- );
- if (EFI_ERROR (Status)) {
- goto ON_EXIT;
- }
-
- Status = gBS->SetTimer (
- Event,
- TimerRelative,
+ Event = NULL;\r
+ Status = gBS->CreateEvent (\r
+ EVT_TIMER,\r
+ TPL_CALLBACK,\r
+ NULL,\r
+ NULL,\r
+ &Event\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Status = gBS->SetTimer (\r
+ Event,\r
+ TimerRelative,\r
TCP_GET_MAPPING_TIMEOUT\r
- );
-
- if (EFI_ERROR (Status)) {
- goto ON_EXIT;
- }
-
- while (EFI_ERROR (gBS->CheckEvent (Event))) {
-
- Tcp6->Poll (Tcp6);
-
- Status = Tcp6->Configure (Tcp6, Tcp6ConfigData);
-
- if (!EFI_ERROR (Status)) {
- break;
- }
- }
-
-ON_EXIT:
-
- if (Event != NULL) {
- gBS->CloseEvent (Event);
- }
-
- return Status;
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ while (EFI_ERROR (gBS->CheckEvent (Event))) {\r
+\r
+ Tcp6->Poll (Tcp6);\r
+\r
+ Status = Tcp6->Configure (Tcp6, Tcp6ConfigData);\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ON_EXIT:\r
+\r
+ if (Event != NULL) {\r
+ gBS->CloseEvent (Event);\r
+ }\r
+\r
+ return Status;\r
}\r
\r
/**\r
\r
@retval EFI_SUCCESS The TCP socket is created and configured.\r
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
- @retval EFI_UNSUPPORTED One or more of the control options are not
+ @retval EFI_UNSUPPORTED One or more of the control options are not\r
supported in the implementation.\r
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
@retval Others Failed to create the TCP socket or configure it.\r
//\r
// Create the TCP child instance and get the TCP protocol.\r
// \r
- Status = NetLibCreateServiceChild (
- Controller,
- Image,
+ Status = NetLibCreateServiceChild (\r
+ Controller,\r
+ Image,\r
ServiceBindingGuid,\r
&TcpIo->Handle\r
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = gBS->OpenProtocol (
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
TcpIo->Handle,\r
ProtocolGuid,\r
Interface,\r
- Image,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
+ Image,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
if (EFI_ERROR (Status) || (*Interface == NULL)) {\r
- goto ON_ERROR;
+ goto ON_ERROR;\r
}\r
\r
if (TcpVersion == TCP_VERSION_4) {\r
} else {\r
Tcp6 = TcpIo->Tcp.Tcp6;\r
}\r
-
+\r
TcpIo->Image = Image;\r
TcpIo->Controller = Controller;\r
-
- //
- // Set the configuration parameters.
- //
- ControlOption.ReceiveBufferSize = 0x200000;
- ControlOption.SendBufferSize = 0x200000;
- ControlOption.MaxSynBackLog = 0;
- ControlOption.ConnectionTimeout = 0;
- ControlOption.DataRetries = 6;
- ControlOption.FinTimeout = 0;
- ControlOption.TimeWaitTimeout = 0;
- ControlOption.KeepAliveProbes = 4;
- ControlOption.KeepAliveTime = 0;
- ControlOption.KeepAliveInterval = 0;
- ControlOption.EnableNagle = FALSE;
- ControlOption.EnableTimeStamp = FALSE;
- ControlOption.EnableWindowScaling = TRUE;
- ControlOption.EnableSelectiveAck = FALSE;
- ControlOption.EnablePathMtuDiscovery = FALSE;
+\r
+ //\r
+ // Set the configuration parameters.\r
+ //\r
+ ControlOption.ReceiveBufferSize = 0x200000;\r
+ ControlOption.SendBufferSize = 0x200000;\r
+ ControlOption.MaxSynBackLog = 0;\r
+ ControlOption.ConnectionTimeout = 0;\r
+ ControlOption.DataRetries = 6;\r
+ ControlOption.FinTimeout = 0;\r
+ ControlOption.TimeWaitTimeout = 0;\r
+ ControlOption.KeepAliveProbes = 4;\r
+ ControlOption.KeepAliveTime = 0;\r
+ ControlOption.KeepAliveInterval = 0;\r
+ ControlOption.EnableNagle = FALSE;\r
+ ControlOption.EnableTimeStamp = FALSE;\r
+ ControlOption.EnableWindowScaling = TRUE;\r
+ ControlOption.EnableSelectiveAck = FALSE;\r
+ ControlOption.EnablePathMtuDiscovery = FALSE;\r
\r
if (TcpVersion == TCP_VERSION_4) {\r
Tcp4ConfigData.TypeOfService = 8;\r
}\r
}\r
\r
- //
- // Create events for variuos asynchronous operations.
+ //\r
+ // Create events for variuos asynchronous operations.\r
//\r
Status = gBS->CreateEvent (\r
- EVT_NOTIFY_SIGNAL,
- TPL_NOTIFY,
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
TcpIoCommonNotify,\r
&TcpIo->IsConnDone,\r
&Event\r
- );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
}\r
\r
TcpIo->ConnToken.Tcp4Token.CompletionToken.Event = Event;\r
\r
- Status = gBS->CreateEvent (
- EVT_NOTIFY_SIGNAL,
- TPL_NOTIFY,
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
TcpIoCommonNotify,\r
&TcpIo->IsListenDone,\r
&Event\r
- );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
}\r
\r
TcpIo->ListenToken.Tcp4Token.CompletionToken.Event = Event;\r
\r
- Status = gBS->CreateEvent (
- EVT_NOTIFY_SIGNAL,
- TPL_NOTIFY,
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
TcpIoCommonNotify,\r
&TcpIo->IsTxDone,\r
&Event\r
- );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
\r
TcpIo->TxToken.Tcp4Token.CompletionToken.Event = Event;\r
\r
\r
- Status = gBS->CreateEvent (
- EVT_NOTIFY_SIGNAL,
- TPL_NOTIFY,
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
TcpIoCommonNotify,\r
&TcpIo->IsRxDone,\r
&Event\r
- );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
\r
TcpIo->RxToken.Tcp4Token.CompletionToken.Event = Event;\r
\r
\r
TcpIo->RxToken.Tcp4Token.Packet.RxData = RxData;\r
\r
- Status = gBS->CreateEvent (
- EVT_NOTIFY_SIGNAL,
- TPL_NOTIFY,
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
TcpIoCommonNotify,\r
&TcpIo->IsCloseDone,\r
&Event\r
- );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
\r
TcpIo->CloseToken.Tcp4Token.CompletionToken.Event = Event;\r
\r
\r
return EFI_SUCCESS;\r
-
-ON_ERROR:
+\r
+ON_ERROR:\r
\r
TcpIoDestroySocket (TcpIo);\r
-
+\r
return Status;\r
}\r
\r
\r
if ((Tcp4 != NULL) || (Tcp6 != NULL)) {\r
\r
- gBS->CloseProtocol (
+ gBS->CloseProtocol (\r
TcpIo->Handle,\r
ProtocolGuid,\r
TcpIo->Image,\r
}\r
}\r
\r
- NetLibDestroyServiceChild (
+ NetLibDestroyServiceChild (\r
TcpIo->Controller,\r
TcpIo->Image,\r
ServiceBindingGuid,\r
return EFI_UNSUPPORTED;\r
}\r
\r
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
while (!TcpIo->IsConnDone && EFI_ERROR (gBS->CheckEvent (Timeout))) {\r
if (TcpIo->TcpVersion == TCP_VERSION_4) {\r
Tcp4->Poll (Tcp4);\r
} else {\r
Tcp6->Poll (Tcp6);\r
}\r
- }
-
+ }\r
+\r
if (!TcpIo->IsConnDone) {\r
- Status = EFI_TIMEOUT;
+ Status = EFI_TIMEOUT;\r
} else {\r
Status = TcpIo->ConnToken.Tcp4Token.CompletionToken.Status;\r
}\r
-
+\r
return Status;\r
}\r
\r
return EFI_UNSUPPORTED;\r
}\r
\r
- if (EFI_ERROR (Status)) {
- return Status;
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
}\r
\r
while (!TcpIo->IsListenDone && EFI_ERROR (gBS->CheckEvent (Timeout))) {\r
} else {\r
Tcp6->Poll (Tcp6);\r
}\r
- }
+ }\r
\r
if (!TcpIo->IsListenDone) {\r
- Status = EFI_TIMEOUT;
+ Status = EFI_TIMEOUT;\r
} else {\r
Status = TcpIo->ListenToken.Tcp4Token.CompletionToken.Status;\r
}\r
\r
- //
- // The new TCP instance handle created for the established connection is
- // in ListenToken.
- //
+ //\r
+ // The new TCP instance handle created for the established connection is \r
+ // in ListenToken.\r
+ //\r
if (!EFI_ERROR (Status)) {\r
if (TcpIo->TcpVersion == TCP_VERSION_4) {\r
ProtocolGuid = &gEfiTcp4ProtocolGuid;\r
ProtocolGuid = &gEfiTcp6ProtocolGuid;\r
}\r
\r
- Status = gBS->OpenProtocol (
+ Status = gBS->OpenProtocol (\r
TcpIo->ListenToken.Tcp4Token.NewChildHandle,\r
ProtocolGuid,\r
(VOID **) (&TcpIo->NewTcp.Tcp4),\r
TcpIo->Image,\r
TcpIo->Controller,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
-
- }
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+\r
+ }\r
\r
return Status;\r
}\r
return ;\r
}\r
\r
- if (EFI_ERROR (Status)) {
- return ;
- }
-
+ if (EFI_ERROR (Status)) {\r
+ return ;\r
+ }\r
+\r
while (!TcpIo->IsCloseDone) {\r
if (TcpIo->TcpVersion == TCP_VERSION_4) {\r
Tcp4->Poll (Tcp4);\r
\r
Data = AllocatePool (Size);\r
if (Data == NULL) {\r
- return EFI_OUT_OF_RESOURCES;
+ return EFI_OUT_OF_RESOURCES;\r
}\r
\r
((EFI_TCP4_TRANSMIT_DATA *) Data)->Push = TRUE;\r
((EFI_TCP4_TRANSMIT_DATA *) Data)->Urgent = FALSE;\r
((EFI_TCP4_TRANSMIT_DATA *) Data)->DataLength = Packet->TotalSize;\r
\r
- //
- // Build the fragment table.
- //
+ //\r
+ // Build the fragment table.\r
+ //\r
((EFI_TCP4_TRANSMIT_DATA *) Data)->FragmentCount = Packet->BlockOpNum;\r
\r
NetbufBuildExt (\r
Tcp6 = NULL;\r
Status = EFI_DEVICE_ERROR;\r
\r
- //
- // Trasnmit the packet.
+ //\r
+ // Trasnmit the packet.\r
//\r
if (TcpIo->TcpVersion == TCP_VERSION_4) {\r
TcpIo->TxToken.Tcp4Token.Packet.TxData = (EFI_TCP4_TRANSMIT_DATA *) Data;\r
Status = Tcp6->Transmit (Tcp6, &TcpIo->TxToken.Tcp6Token);\r
}\r
\r
- if (EFI_ERROR (Status)) {
- goto ON_EXIT;
- }
-
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
while (!TcpIo->IsTxDone) {\r
if (TcpIo->TcpVersion == TCP_VERSION_4) {\r
Tcp4->Poll (Tcp4);\r
} else {\r
Tcp6->Poll (Tcp6);\r
}\r
- }
-
+ }\r
+\r
TcpIo->IsTxDone = FALSE;\r
Status = TcpIo->TxToken.Tcp4Token.CompletionToken.Status;\r
\r
-ON_EXIT:
-
+ON_EXIT:\r
+\r
FreePool (Data);\r
-
+\r
return Status;\r
}\r
\r
return EFI_UNSUPPORTED;\r
}\r
\r
- FragmentCount = Packet->BlockOpNum;
- Fragment = AllocatePool (FragmentCount * sizeof (NET_FRAGMENT));
+ FragmentCount = Packet->BlockOpNum;\r
+ Fragment = AllocatePool (FragmentCount * sizeof (NET_FRAGMENT));\r
if (Fragment == NULL) {\r
Status = EFI_OUT_OF_RESOURCES;\r
goto ON_EXIT;\r
- }
- //
- // Build the fragment table.
- //
- NetbufBuildExt (Packet, Fragment, &FragmentCount);
+ }\r
+ //\r
+ // Build the fragment table.\r
+ //\r
+ NetbufBuildExt (Packet, Fragment, &FragmentCount);\r
\r
RxData->FragmentCount = 1;\r
CurrentFragment = 0;\r
- Status = EFI_SUCCESS;
-
- while (CurrentFragment < FragmentCount) {
+ Status = EFI_SUCCESS;\r
+\r
+ while (CurrentFragment < FragmentCount) {\r
RxData->DataLength = Fragment[CurrentFragment].Len;\r
RxData->FragmentTable[0].FragmentLength = Fragment[CurrentFragment].Len;\r
RxData->FragmentTable[0].FragmentBuffer = Fragment[CurrentFragment].Bulk;\r
Status = Tcp6->Receive (Tcp6, &TcpIo->RxToken.Tcp6Token);\r
}\r
\r
- if (EFI_ERROR (Status)) {
- goto ON_EXIT;
- }
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
\r
while (!TcpIo->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
//\r
Tcp6->Poll (Tcp6);\r
}\r
}\r
-
+\r
if (!TcpIo->IsRxDone) {\r
- //
- // Timeout occurs, cancel the receive request.
- //
+ //\r
+ // Timeout occurs, cancel the receive request.\r
+ //\r
if (TcpIo->TcpVersion == TCP_VERSION_4) {\r
Tcp4->Cancel (Tcp4, &TcpIo->RxToken.Tcp4Token.CompletionToken);\r
} else {\r
Tcp6->Cancel (Tcp6, &TcpIo->RxToken.Tcp6Token.CompletionToken);\r
}\r
-
- Status = EFI_TIMEOUT;
- goto ON_EXIT;
- } else {
+\r
+ Status = EFI_TIMEOUT;\r
+ goto ON_EXIT;\r
+ } else {\r
TcpIo->IsRxDone = FALSE;\r
}\r
\r
Status = TcpIo->RxToken.Tcp4Token.CompletionToken.Status;\r
\r
if (EFI_ERROR (Status)) {\r
- goto ON_EXIT;
- }
-
+ goto ON_EXIT;\r
+ }\r
+\r
Fragment[CurrentFragment].Len -= RxData->FragmentTable[0].FragmentLength;\r
- if (Fragment[CurrentFragment].Len == 0) {
- CurrentFragment++;
- } else {
+ if (Fragment[CurrentFragment].Len == 0) {\r
+ CurrentFragment++;\r
+ } else {\r
Fragment[CurrentFragment].Bulk += RxData->FragmentTable[0].FragmentLength;\r
- }
- }
-
-ON_EXIT:
+ }\r
+ }\r
+\r
+ON_EXIT:\r
\r
if (Fragment != NULL) {\r
FreePool (Fragment);\r
}\r
-
+\r
return Status;\r
}\r
-///**@file
-// Low leve x64 specific debug support functions.
-//
-// Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
-// Portions copyright (c) 2008 - 2009, Apple Inc. 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.
-//
-//**/
-
-ASM_GLOBAL ASM_PFX(OrigVector)
-ASM_GLOBAL ASM_PFX(InterruptEntryStub)
-ASM_GLOBAL ASM_PFX(StubSize)
-ASM_GLOBAL ASM_PFX(CommonIdtEntry)
-ASM_GLOBAL ASM_PFX(FxStorSupport)
-
-.data
-
-ASM_PFX(StubSize): .long ASM_PFX(InterruptEntryStubEnd) - ASM_PFX(InterruptEntryStub)
-ASM_PFX(AppRsp): .long 0x11111111 # ?
- .long 0x11111111 # ?
-ASM_PFX(DebugRsp): .long 0x22222222 # ?
- .long 0x22222222 # ?
-ASM_PFX(ExtraPush): .long 0x33333333 # ?
- .long 0x33333333 # ?
-ASM_PFX(ExceptData): .long 0x44444444 # ?
- .long 0x44444444 # ?
-ASM_PFX(Rflags): .long 0x55555555 # ?
- .long 0x55555555 # ?
-ASM_PFX(OrigVector): .long 0x66666666 # ?
- .long 0x66666666 # ?
-
-// The declarations below define the memory region that will be used for the debug stack.
-// The context record will be built by pushing register values onto this stack.
-// It is imparitive that alignment be carefully managed, since the FXSTOR and
-// FXRSTOR instructions will GP fault if their memory operand is not 16 byte aligned.
-//
-// The stub will switch stacks from the application stack to the debuger stack
-// and pushes the exception number.
-//
-// Then we building the context record on the stack. Since the stack grows down,
-// we push the fields of the context record from the back to the front. There
-// are 336 bytes of stack used prior allocating the 512 bytes of stack to be
-// used as the memory buffer for the fxstor instruction. Therefore address of
-// the buffer used for the FXSTOR instruction is &Eax - 336 - 512, which
-// must be 16 byte aligned.
-//
-// We carefully locate the stack to make this happen.
-//
-// For reference, the context structure looks like this:
-// struct {
-// UINT64 ExceptionData;
-// FX_SAVE_STATE_X64 FxSaveState; // 512 bytes, must be 16 byte aligned
-// UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
-// UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
-// UINT64 RFlags;
-// UINT64 Ldtr, Tr;
-// UINT64 Gdtr[2], Idtr[2];
-// UINT64 Rip;
-// UINT64 Gs, Fs, Es, Ds, Cs, Ss;
-// UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
-// UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
-// } SYSTEM_CONTEXT_X64; // 64 bit system context record
-
-.p2align 4
-DebugStackEnd : .ascii "DbgStkEnd >>>>>>" # 16 byte long string - must be 16 bytes to preserve alignment
- .fill 0x1ffc, 4, 0x00000000
- # 32K should be enough stack
- # This allocation is coocked to insure
- # that the the buffer for the FXSTORE instruction
- # will be 16 byte aligned also.
- #
-ASM_PFX(ExceptionNumber): .long 0x77777777 # first entry will be the vector number pushed by the stub
- .long 0x77777777 # ?
-
-DebugStackBegin : .ascii "<<<< DbgStkBegin" # initial debug ESP == DebugStackBegin, set in stub
-
-
-.text
-
-//------------------------------------------------------------------------------
-// BOOLEAN
-// FxStorSupport (
-// void
-// )
-//
-// Abstract: Returns TRUE if FxStor instructions are supported
-//
-ASM_GLOBAL ASM_PFX(FxStorSupport)
-ASM_PFX(FxStorSupport):
-//
-// cpuid corrupts rbx which must be preserved per the C calling convention
-//
- pushq %rbx
- movq $1, %rax
- cpuid
- movl %edx, %eax
- andq $0x01000000, %rax
- shrq $24, %rax
- popq %rbx
- ret
-//------------------------------------------------------------------------------
-// void
-// Vect2Desc (
-// IA32_IDT_GATE_DESCRIPTOR * DestDesc, // rcx
-// void (*Vector) (void) // rdx
-// )
-//
-// Abstract: Encodes an IDT descriptor with the given physical address
-//
-ASM_GLOBAL ASM_PFX(Vect2Desc)
-ASM_PFX(Vect2Desc):
- movq %rdx, %rax
- movw %ax, (%rcx) # write bits 15..0 of offset
- movw %cs, %dx
- movw %dx, 2(%rcx) # SYS_CODE_SEL from GDT
- movw $(0x0e00 | 0x8000), 4(%rcx) # type = 386 interrupt gate, present
- shrq $16, %rax
- movw %ax, 6(%rcx) # write bits 31..16 of offset
- shrq $16, %rax
- movl %eax, 8(%rcx) # write bits 63..32 of offset
-
- ret
-
-//------------------------------------------------------------------------------
-// InterruptEntryStub
-//
-// Abstract: This code is not a function, but is a small piece of code that is
-// copied and fixed up once for each IDT entry that is hooked.
-//
-ASM_GLOBAL ASM_PFX(InterruptEntryStub)
-ASM_PFX(InterruptEntryStub):
-
- pushq $0 # push vector number - will be modified before installed
- jmp ASM_PFX(CommonIdtEntry)
-
-ASM_GLOBAL ASM_PFX(InterruptEntryStubEnd)
-ASM_PFX(InterruptEntryStubEnd):
-
-//------------------------------------------------------------------------------
-// CommonIdtEntry
-//
-// Abstract: This code is not a function, but is the common part for all IDT
-// vectors.
-//
-ASM_GLOBAL ASM_PFX(CommonIdtEntry)
-//
-// At this point, the stub has saved the current application stack esp into AppRsp
-// and switched stacks to the debug stack, where it pushed the vector number
-//
-// The application stack looks like this:
-//
-// ...
-// (last application stack entry)
-// [16 bytes alignment, do not care it]
-// SS from interrupted task
-// RSP from interrupted task
-// rflags from interrupted task
-// CS from interrupted task
-// RIP from interrupted task
-// Error code <-------------------- Only present for some exeption types
-//
-// Vector Number <----------------- pushed in our IDT Entry
-//
-
-
-// The stub switched us to the debug stack and pushed the interrupt number.
-//
-// Next, construct the context record. It will be build on the debug stack by
-// pushing the registers in the correct order so as to create the context structure
-// on the debug stack. The context record must be built from the end back to the
-// beginning because the stack grows down...
-//
-// For reference, the context record looks like this:
-//
-// typedef
-// struct {
-// UINT64 ExceptionData;
-// FX_SAVE_STATE_X64 FxSaveState;
-// UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
-// UINT64 Cr0, Cr2, Cr3, Cr4, Cr8;
-// UINT64 RFlags;
-// UINT64 Ldtr, Tr;
-// UINT64 Gdtr[2], Idtr[2];
-// UINT64 Rip;
-// UINT64 Gs, Fs, Es, Ds, Cs, Ss;
-// UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
-// UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
-// } SYSTEM_CONTEXT_X64; // 64
-ASM_PFX(CommonIdtEntry):
-// NOTE: we save rsp here to prevent compiler put rip reference cause error AppRsp
- pushq %rax
- movq (8)(%rsp), %rax # save vector number
- movq %rax, ASM_PFX(ExceptionNumber)(%rip) # save vector number
- popq %rax
- addq $8, %rsp # pop vector number
- movq %rsp, ASM_PFX(AppRsp)(%rip) # save stack top
- movq DebugStackBegin(%rip), %rsp # switch to debugger stack
- subq $8, %rsp # leave space for vector number
-// UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
-// UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
- pushq %r15
- pushq %r14
- pushq %r13
- pushq %r12
- pushq %r11
- pushq %r10
- pushq %r9
- pushq %r8
- pushq %rax
- pushq %rcx
- pushq %rdx
- pushq %rbx
- pushq %rsp
- pushq %rbp
- pushq %rsi
- pushq %rdi
-// Save interrupt state rflags register...
- pushfq
- popq %rax
- movq %rax, ASM_PFX(Rflags)(%rip)
-// We need to determine if any extra data was pushed by the exception, and if so, save it
-// To do this, we check the exception number pushed by the stub, and cache the
-// result in a variable since we'll need this again.
- cmpl $0, ASM_PFX(ExceptionNumber)(%rip)
- jz ExtraPushOne
- cmpl $10, ASM_PFX(ExceptionNumber)(%rip)
- jz ExtraPushOne
- cmpl $11, ASM_PFX(ExceptionNumber)(%rip)
- jz ExtraPushOne
- cmpl $12, ASM_PFX(ExceptionNumber)(%rip)
- jz ExtraPushOne
- cmpl $13, ASM_PFX(ExceptionNumber)(%rip)
- jz ExtraPushOne
- cmpl $14, ASM_PFX(ExceptionNumber)(%rip)
- jz ExtraPushOne
- cmpl $17, ASM_PFX(ExceptionNumber)(%rip)
- jz ExtraPushOne
- movl $0, ASM_PFX(ExtraPush)(%rip)
- movl $0, ASM_PFX(ExceptData)(%rip)
- jmp ExtraPushDone
-ExtraPushOne:
- movl $1, ASM_PFX(ExtraPush)(%rip)
-
-// If there's some extra data, save it also, and modify the saved AppRsp to effectively
-// pop this value off the application's stack.
- movq ASM_PFX(AppRsp)(%rip), %rax
- movq (%rax), %rbx
- movq %rbx, ASM_PFX(ExceptData)(%rip)
- addq $8, %rax
- movq %rax, ASM_PFX(AppRsp)(%rip)
-
-ExtraPushDone:
-
-// The "push" above pushed the debug stack rsp. Since what we're actually doing
-// is building the context record on the debug stack, we need to save the pushed
-// debug RSP, and replace it with the application's last stack entry...
- movq 24(%rsp), %rax
- movq %rax, ASM_PFX(DebugRsp)(%rip)
- movq ASM_PFX(AppRsp)(%rip), %rax
- movq 24(%rax), %rax
- # application stack has ss, rsp, rflags, cs, & rip, so
- # last actual application stack entry is saved at offset
- # 24 bytes from stack top.
- movq %rax, 24(%rsp)
-
-// continue building context record
-// UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero
- mov %ss, %rax
- pushq %rax
- # CS from application is one entry back in application stack
- movq ASM_PFX(AppRsp)(%rip), %rax
- movzxw 8(%rax), %rax
- pushq %rax
-
- mov %ds, %rax
- pushq %rax
- movw %es, %rax
- pushq %rax
- mov %fs, %rax
- pushq %rax
- mov %gs, %rax
- pushq %rax
-// UINT64 Rip;
- # Rip from application is on top of application stack
- movq ASM_PFX(AppRsp)(%rip), %rax
- pushq (%rax)
-// UINT64 Gdtr[2], Idtr[2];
- push $0
- push $0
- sidtq (%rsp)
- push $0
- push $0
- sgdtq (%rsp)
-
-// UINT64 Ldtr, Tr;
- xorq %rax, %rax
- str %ax
- pushq %rax
- sldt %ax
- pushq %rax
-
-// UINT64 RFlags;
-// Rflags from application is two entries back in application stack
- movq ASM_PFX(AppRsp)(%rip), %rax
- pushq 16(%rax)
-// UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
-// insure FXSAVE/FXRSTOR is enabled in CR4...
-// ... while we're at it, make sure DE is also enabled...
- movq %cr8, %rax
- pushq %rax
- movq %cr4, %rax
- orq $0x208, %rax
- movq %rax, %cr4
- pushq %rax
- movq %cr3, %rax
- pushq %rax
- movq %cr2, %rax
- pushq %rax
- push $0
- movq %cr0, %rax
- pushq %rax
-// UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
- movq %dr7, %rax
- pushq %rax
-// clear Dr7 while executing debugger itself
- xorq %rax, %rax
- movq %rax, %dr7
-
- movq %dr6, %rax
- pushq %rax
-// insure all status bits in dr6 are clear...
- xorq %rax, %rax
- movq %rax, %dr6
-
- movq %dr3, %rax
- pushq %rax
- movq %dr2, %rax
- pushq %rax
- movq %dr1, %rax
- pushq %rax
- movq %dr0, %rax
- pushq %rax
-
-// FX_SAVE_STATE_X64 FxSaveState;
- subq $512, %rsp
- movq %rsp, %rdi
- # IMPORTANT!! The debug stack has been carefully constructed to
- # insure that rsp and rdi are 16 byte aligned when we get here.
- # They MUST be. If they are not, a GP fault will occur.
-
- # FXSTOR_RDI
- fxsave (%rdi)
-
-// UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear
- cld
-
-// UINT64 ExceptionData;
- movq ASM_PFX(ExceptData)(%rip), %rax
- pushq %rax
-
-// call to C code which will in turn call registered handler
-// pass in the vector number
- movq %rsp, %rdx
- movq ASM_PFX(ExceptionNumber)(%rip), %rcx
- subq $40, %rsp
- call ASM_PFX(InterruptDistrubutionHub)
- addq $40, %rsp
-// restore context...
-// UINT64 ExceptionData;
- addq $8, %rsp
-
-// FX_SAVE_STATE_X64 FxSaveState;
- movq %rsp, %rsi
-
- # FXRSTOR_RSI
- fxrstor (%rsi)
-
- addq $512, %rsp
-
-// UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
- popq %rax
- movq %rax, %dr0
- popq %rax
- movq %rax, %dr1
- popq %rax
- movq %rax, %dr2
- popq %rax
- movq %rax, %dr3
-
-// skip restore of dr6. We cleared dr6 during the context save.
- addq $8, %rsp
- popq %rax
- movq %rax, %dr7
-
-// UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
- popq %rax
- movq %rax, %cr0
- addq $8, %rsp
- popq %rax
- movq %rax, %cr2
- popq %rax
- movq %rax, %cr3
- popq %rax
- movq %rax, %cr4
- popq %rax
- movq %rax, %cr8
-// UINT64 RFlags;
- movq ASM_PFX(AppRsp)(%rip), %rax
- popq 16(%rax)
-// UINT64 Ldtr, Tr;
-// UINT64 Gdtr[2], Idtr[2];
-// Best not let anyone mess with these particular registers...
- addq $48, %rsp
-// UINT64 Rip;
- popq (%rax)
-
-// UINT64 Gs, Fs, Es, Ds, Cs, Ss;
-// NOTE - modified segment registers could hang the debugger... We
-// could attempt to insulate ourselves against this possibility,
-// but that poses risks as well.
-//
-
- popq %rax
- # mov %rax, %gs
- popq %rax
- # mov %rax, %fs
- popq %rax
- mov %rax, %es
- popq %rax
- mov %rax, %ds
- movq ASM_PFX(AppRsp)(%rip), %rax
- popq 8(%rax)
- popq %rax
- mov %rax, %ss
-## The next stuff to restore is the general purpose registers that were pushed
-## using the "push" instruction.
-##
-## The value of RSP as stored in the context record is the application RSP
-## including the 5 entries on the application stack caused by the exception
-## itself. It may have been modified by the debug agent, so we need to
-## determine if we need to relocate the application stack.
-
- movq 24(%rsp), %rbx # move the potentially modified AppRsp into rbx
- movq ASM_PFX(AppRsp)(%rip), %rax
- movq 24(%rax), %rax
- cmpq %rax, %rbx
- je NoAppStackMove
-
- movq ASM_PFX(AppRsp)(%rip), %rax
- movq (%rax), %rcx # RIP
- movq %rcx, (%rbx)
-
- movq 8(%rax), %rcx # CS
- movq %rcx, 8(%rbx)
-
- movq 16(%rax), %rcx # RFLAGS
- movq %rcx, 16(%rbx)
-
- movq 24(%rax), %rcx # RSP
- movq %rcx, 24(%rbx)
-
- movq 32(%rax), %rcx # SS
- movq %rcx, 32(%rbx)
-
- movq %rbx, %rax # modify the saved AppRsp to the new AppRsp
- movq %rax, ASM_PFX(AppRsp)(%rip)
-NoAppStackMove:
- movq ASM_PFX(DebugRsp)(%rip), %rax # restore the DebugRsp on the debug stack
- # so our "pop" will not cause a stack switch
- movq %rax, 24(%rsp)
-
- cmpl $0x068, ASM_PFX(ExceptionNumber)(%rip)
- jne NoChain
-
-Chain:
-
-// Restore rflags so when we chain, the flags will be exactly as if we were never here.
-// We gin up the stack to do an iretq so we can get ALL the flags.
- movq ASM_PFX(AppRsp)(%rip), %rax
- movq 40(%rax), %rbx
- pushq %rbx
- mov %ss, %rax
- pushq %rax
- movq %rsp, %rax
- addq $16, %rax
- pushq %rax
- movq ASM_PFX(AppRsp)(%rip), %rax
- movq 16(%rax), %rbx
- andq $0xfffffffffffffcff, %rbx # special handling for IF and TF
- pushq %rbx
- mov %cs, %rax
- pushq %rax
- movq PhonyIretq(%rip), %rax
- pushq %rax
- iretq
-PhonyIretq:
-
-// UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
-// UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
- popq %rdi
- popq %rsi
- popq %rbp
- popq %rsp
- popq %rbx
- popq %rdx
- popq %rcx
- popq %rax
- popq %r8
- popq %r9
- popq %r10
- popq %r11
- popq %r12
- popq %r13
- popq %r14
- popq %r15
-
-// Switch back to application stack
- movq ASM_PFX(AppRsp)(%rip), %rsp
-// Jump to original handler
- jmp ASM_PFX(OrigVector)
-NoChain:
-// UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
-// UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
- popq %rdi
- popq %rsi
- popq %rbp
- popq %rsp
- popq %rbx
- popq %rdx
- popq %rcx
- popq %rax
- popq %r8
- popq %r9
- popq %r10
- popq %r11
- popq %r12
- popq %r13
- popq %r14
- popq %r15
-
-// Switch back to application stack
- movq ASM_PFX(AppRsp)(%rip), %rsp
-
-// We're outa here...
- iret
+///**@file\r
+// Low leve x64 specific debug support functions.\r
+//\r
+// Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+// Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
+// This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions of the BSD License\r
+// which accompanies this distribution. The full text of the license may be found at\r
+// http://opensource.org/licenses/bsd-license.php\r
+//\r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+//\r
+//**/\r
+\r
+ASM_GLOBAL ASM_PFX(OrigVector)\r
+ASM_GLOBAL ASM_PFX(InterruptEntryStub)\r
+ASM_GLOBAL ASM_PFX(StubSize)\r
+ASM_GLOBAL ASM_PFX(CommonIdtEntry)\r
+ASM_GLOBAL ASM_PFX(FxStorSupport)\r
+\r
+.data\r
+\r
+ASM_PFX(StubSize): .long ASM_PFX(InterruptEntryStubEnd) - ASM_PFX(InterruptEntryStub)\r
+ASM_PFX(AppRsp): .long 0x11111111 # ?\r
+ .long 0x11111111 # ?\r
+ASM_PFX(DebugRsp): .long 0x22222222 # ?\r
+ .long 0x22222222 # ?\r
+ASM_PFX(ExtraPush): .long 0x33333333 # ?\r
+ .long 0x33333333 # ?\r
+ASM_PFX(ExceptData): .long 0x44444444 # ?\r
+ .long 0x44444444 # ?\r
+ASM_PFX(Rflags): .long 0x55555555 # ?\r
+ .long 0x55555555 # ?\r
+ASM_PFX(OrigVector): .long 0x66666666 # ?\r
+ .long 0x66666666 # ?\r
+\r
+// The declarations below define the memory region that will be used for the debug stack.\r
+// The context record will be built by pushing register values onto this stack.\r
+// It is imparitive that alignment be carefully managed, since the FXSTOR and\r
+// FXRSTOR instructions will GP fault if their memory operand is not 16 byte aligned.\r
+//\r
+// The stub will switch stacks from the application stack to the debuger stack\r
+// and pushes the exception number.\r
+//\r
+// Then we building the context record on the stack. Since the stack grows down,\r
+// we push the fields of the context record from the back to the front. There\r
+// are 336 bytes of stack used prior allocating the 512 bytes of stack to be\r
+// used as the memory buffer for the fxstor instruction. Therefore address of\r
+// the buffer used for the FXSTOR instruction is &Eax - 336 - 512, which\r
+// must be 16 byte aligned.\r
+//\r
+// We carefully locate the stack to make this happen.\r
+//\r
+// For reference, the context structure looks like this:\r
+// struct {\r
+// UINT64 ExceptionData;\r
+// FX_SAVE_STATE_X64 FxSaveState; // 512 bytes, must be 16 byte aligned\r
+// UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+// UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r
+// UINT64 RFlags;\r
+// UINT64 Ldtr, Tr;\r
+// UINT64 Gdtr[2], Idtr[2];\r
+// UINT64 Rip;\r
+// UINT64 Gs, Fs, Es, Ds, Cs, Ss;\r
+// UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
+// UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
+// } SYSTEM_CONTEXT_X64; // 64 bit system context record\r
+\r
+.p2align 4\r
+DebugStackEnd : .ascii "DbgStkEnd >>>>>>" # 16 byte long string - must be 16 bytes to preserve alignment\r
+ .fill 0x1ffc, 4, 0x00000000\r
+ # 32K should be enough stack\r
+ # This allocation is coocked to insure\r
+ # that the the buffer for the FXSTORE instruction\r
+ # will be 16 byte aligned also.\r
+ #\r
+ASM_PFX(ExceptionNumber): .long 0x77777777 # first entry will be the vector number pushed by the stub\r
+ .long 0x77777777 # ?\r
+\r
+DebugStackBegin : .ascii "<<<< DbgStkBegin" # initial debug ESP == DebugStackBegin, set in stub\r
+\r
+\r
+.text\r
+\r
+//------------------------------------------------------------------------------\r
+// BOOLEAN\r
+// FxStorSupport (\r
+// void\r
+// )\r
+//\r
+// Abstract: Returns TRUE if FxStor instructions are supported\r
+//\r
+ASM_GLOBAL ASM_PFX(FxStorSupport)\r
+ASM_PFX(FxStorSupport):\r
+//\r
+// cpuid corrupts rbx which must be preserved per the C calling convention\r
+//\r
+ pushq %rbx\r
+ movq $1, %rax\r
+ cpuid\r
+ movl %edx, %eax\r
+ andq $0x01000000, %rax\r
+ shrq $24, %rax\r
+ popq %rbx\r
+ ret\r
+//------------------------------------------------------------------------------\r
+// void\r
+// Vect2Desc (\r
+// IA32_IDT_GATE_DESCRIPTOR * DestDesc, // rcx\r
+// void (*Vector) (void) // rdx\r
+// )\r
+//\r
+// Abstract: Encodes an IDT descriptor with the given physical address\r
+//\r
+ASM_GLOBAL ASM_PFX(Vect2Desc)\r
+ASM_PFX(Vect2Desc):\r
+ movq %rdx, %rax\r
+ movw %ax, (%rcx) # write bits 15..0 of offset\r
+ movw %cs, %dx\r
+ movw %dx, 2(%rcx) # SYS_CODE_SEL from GDT\r
+ movw $(0x0e00 | 0x8000), 4(%rcx) # type = 386 interrupt gate, present\r
+ shrq $16, %rax\r
+ movw %ax, 6(%rcx) # write bits 31..16 of offset\r
+ shrq $16, %rax\r
+ movl %eax, 8(%rcx) # write bits 63..32 of offset\r
+\r
+ ret\r
+\r
+//------------------------------------------------------------------------------\r
+// InterruptEntryStub\r
+//\r
+// Abstract: This code is not a function, but is a small piece of code that is\r
+// copied and fixed up once for each IDT entry that is hooked.\r
+//\r
+ASM_GLOBAL ASM_PFX(InterruptEntryStub)\r
+ASM_PFX(InterruptEntryStub):\r
+\r
+ pushq $0 # push vector number - will be modified before installed\r
+ jmp ASM_PFX(CommonIdtEntry)\r
+\r
+ASM_GLOBAL ASM_PFX(InterruptEntryStubEnd)\r
+ASM_PFX(InterruptEntryStubEnd):\r
+\r
+//------------------------------------------------------------------------------\r
+// CommonIdtEntry\r
+//\r
+// Abstract: This code is not a function, but is the common part for all IDT\r
+// vectors.\r
+//\r
+ASM_GLOBAL ASM_PFX(CommonIdtEntry)\r
+//\r
+// At this point, the stub has saved the current application stack esp into AppRsp\r
+// and switched stacks to the debug stack, where it pushed the vector number\r
+//\r
+// The application stack looks like this:\r
+//\r
+// ...\r
+// (last application stack entry)\r
+// [16 bytes alignment, do not care it]\r
+// SS from interrupted task\r
+// RSP from interrupted task\r
+// rflags from interrupted task\r
+// CS from interrupted task\r
+// RIP from interrupted task\r
+// Error code <-------------------- Only present for some exeption types\r
+//\r
+// Vector Number <----------------- pushed in our IDT Entry\r
+//\r
+\r
+\r
+// The stub switched us to the debug stack and pushed the interrupt number.\r
+//\r
+// Next, construct the context record. It will be build on the debug stack by\r
+// pushing the registers in the correct order so as to create the context structure\r
+// on the debug stack. The context record must be built from the end back to the\r
+// beginning because the stack grows down...\r
+//\r
+// For reference, the context record looks like this:\r
+//\r
+// typedef\r
+// struct {\r
+// UINT64 ExceptionData;\r
+// FX_SAVE_STATE_X64 FxSaveState;\r
+// UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+// UINT64 Cr0, Cr2, Cr3, Cr4, Cr8;\r
+// UINT64 RFlags;\r
+// UINT64 Ldtr, Tr;\r
+// UINT64 Gdtr[2], Idtr[2];\r
+// UINT64 Rip;\r
+// UINT64 Gs, Fs, Es, Ds, Cs, Ss;\r
+// UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
+// UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
+// } SYSTEM_CONTEXT_X64; // 64\r
+ASM_PFX(CommonIdtEntry):\r
+// NOTE: we save rsp here to prevent compiler put rip reference cause error AppRsp\r
+ pushq %rax\r
+ movq (8)(%rsp), %rax # save vector number\r
+ movq %rax, ASM_PFX(ExceptionNumber)(%rip) # save vector number\r
+ popq %rax\r
+ addq $8, %rsp # pop vector number\r
+ movq %rsp, ASM_PFX(AppRsp)(%rip) # save stack top\r
+ movq DebugStackBegin(%rip), %rsp # switch to debugger stack\r
+ subq $8, %rsp # leave space for vector number\r
+// UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
+// UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
+ pushq %r15\r
+ pushq %r14\r
+ pushq %r13\r
+ pushq %r12\r
+ pushq %r11\r
+ pushq %r10\r
+ pushq %r9\r
+ pushq %r8\r
+ pushq %rax\r
+ pushq %rcx\r
+ pushq %rdx\r
+ pushq %rbx\r
+ pushq %rsp\r
+ pushq %rbp\r
+ pushq %rsi\r
+ pushq %rdi\r
+// Save interrupt state rflags register...\r
+ pushfq\r
+ popq %rax\r
+ movq %rax, ASM_PFX(Rflags)(%rip)\r
+// We need to determine if any extra data was pushed by the exception, and if so, save it\r
+// To do this, we check the exception number pushed by the stub, and cache the\r
+// result in a variable since we'll need this again.\r
+ cmpl $0, ASM_PFX(ExceptionNumber)(%rip)\r
+ jz ExtraPushOne\r
+ cmpl $10, ASM_PFX(ExceptionNumber)(%rip)\r
+ jz ExtraPushOne\r
+ cmpl $11, ASM_PFX(ExceptionNumber)(%rip)\r
+ jz ExtraPushOne\r
+ cmpl $12, ASM_PFX(ExceptionNumber)(%rip)\r
+ jz ExtraPushOne\r
+ cmpl $13, ASM_PFX(ExceptionNumber)(%rip)\r
+ jz ExtraPushOne\r
+ cmpl $14, ASM_PFX(ExceptionNumber)(%rip)\r
+ jz ExtraPushOne\r
+ cmpl $17, ASM_PFX(ExceptionNumber)(%rip)\r
+ jz ExtraPushOne\r
+ movl $0, ASM_PFX(ExtraPush)(%rip)\r
+ movl $0, ASM_PFX(ExceptData)(%rip)\r
+ jmp ExtraPushDone\r
+ExtraPushOne:\r
+ movl $1, ASM_PFX(ExtraPush)(%rip)\r
+\r
+// If there's some extra data, save it also, and modify the saved AppRsp to effectively\r
+// pop this value off the application's stack.\r
+ movq ASM_PFX(AppRsp)(%rip), %rax\r
+ movq (%rax), %rbx\r
+ movq %rbx, ASM_PFX(ExceptData)(%rip)\r
+ addq $8, %rax\r
+ movq %rax, ASM_PFX(AppRsp)(%rip)\r
+\r
+ExtraPushDone:\r
+\r
+// The "push" above pushed the debug stack rsp. Since what we're actually doing\r
+// is building the context record on the debug stack, we need to save the pushed\r
+// debug RSP, and replace it with the application's last stack entry...\r
+ movq 24(%rsp), %rax\r
+ movq %rax, ASM_PFX(DebugRsp)(%rip)\r
+ movq ASM_PFX(AppRsp)(%rip), %rax\r
+ movq 24(%rax), %rax\r
+ # application stack has ss, rsp, rflags, cs, & rip, so\r
+ # last actual application stack entry is saved at offset\r
+ # 24 bytes from stack top.\r
+ movq %rax, 24(%rsp)\r
+\r
+// continue building context record\r
+// UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero\r
+ mov %ss, %rax\r
+ pushq %rax\r
+ # CS from application is one entry back in application stack\r
+ movq ASM_PFX(AppRsp)(%rip), %rax\r
+ movzxw 8(%rax), %rax\r
+ pushq %rax\r
+\r
+ mov %ds, %rax\r
+ pushq %rax\r
+ movw %es, %rax\r
+ pushq %rax\r
+ mov %fs, %rax\r
+ pushq %rax\r
+ mov %gs, %rax\r
+ pushq %rax\r
+// UINT64 Rip;\r
+ # Rip from application is on top of application stack\r
+ movq ASM_PFX(AppRsp)(%rip), %rax\r
+ pushq (%rax)\r
+// UINT64 Gdtr[2], Idtr[2];\r
+ push $0\r
+ push $0\r
+ sidtq (%rsp)\r
+ push $0\r
+ push $0\r
+ sgdtq (%rsp)\r
+\r
+// UINT64 Ldtr, Tr;\r
+ xorq %rax, %rax\r
+ str %ax\r
+ pushq %rax\r
+ sldt %ax\r
+ pushq %rax\r
+\r
+// UINT64 RFlags;\r
+// Rflags from application is two entries back in application stack\r
+ movq ASM_PFX(AppRsp)(%rip), %rax\r
+ pushq 16(%rax)\r
+// UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r
+// insure FXSAVE/FXRSTOR is enabled in CR4...\r
+// ... while we're at it, make sure DE is also enabled...\r
+ movq %cr8, %rax\r
+ pushq %rax\r
+ movq %cr4, %rax\r
+ orq $0x208, %rax\r
+ movq %rax, %cr4\r
+ pushq %rax\r
+ movq %cr3, %rax\r
+ pushq %rax\r
+ movq %cr2, %rax\r
+ pushq %rax\r
+ push $0\r
+ movq %cr0, %rax\r
+ pushq %rax\r
+// UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+ movq %dr7, %rax\r
+ pushq %rax\r
+// clear Dr7 while executing debugger itself\r
+ xorq %rax, %rax\r
+ movq %rax, %dr7\r
+\r
+ movq %dr6, %rax\r
+ pushq %rax\r
+// insure all status bits in dr6 are clear...\r
+ xorq %rax, %rax\r
+ movq %rax, %dr6\r
+\r
+ movq %dr3, %rax\r
+ pushq %rax\r
+ movq %dr2, %rax\r
+ pushq %rax\r
+ movq %dr1, %rax\r
+ pushq %rax\r
+ movq %dr0, %rax\r
+ pushq %rax\r
+\r
+// FX_SAVE_STATE_X64 FxSaveState;\r
+ subq $512, %rsp\r
+ movq %rsp, %rdi\r
+ # IMPORTANT!! The debug stack has been carefully constructed to\r
+ # insure that rsp and rdi are 16 byte aligned when we get here.\r
+ # They MUST be. If they are not, a GP fault will occur.\r
+\r
+ # FXSTOR_RDI\r
+ fxsave (%rdi)\r
+\r
+// UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear\r
+ cld\r
+ \r
+// UINT64 ExceptionData;\r
+ movq ASM_PFX(ExceptData)(%rip), %rax\r
+ pushq %rax\r
+\r
+// call to C code which will in turn call registered handler\r
+// pass in the vector number\r
+ movq %rsp, %rdx\r
+ movq ASM_PFX(ExceptionNumber)(%rip), %rcx\r
+ subq $40, %rsp\r
+ call ASM_PFX(InterruptDistrubutionHub)\r
+ addq $40, %rsp\r
+// restore context...\r
+// UINT64 ExceptionData;\r
+ addq $8, %rsp\r
+\r
+// FX_SAVE_STATE_X64 FxSaveState;\r
+ movq %rsp, %rsi\r
+\r
+ # FXRSTOR_RSI\r
+ fxrstor (%rsi)\r
+\r
+ addq $512, %rsp\r
+\r
+// UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+ popq %rax\r
+ movq %rax, %dr0\r
+ popq %rax\r
+ movq %rax, %dr1\r
+ popq %rax\r
+ movq %rax, %dr2\r
+ popq %rax\r
+ movq %rax, %dr3\r
+\r
+// skip restore of dr6. We cleared dr6 during the context save.\r
+ addq $8, %rsp\r
+ popq %rax\r
+ movq %rax, %dr7\r
+\r
+// UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r
+ popq %rax\r
+ movq %rax, %cr0\r
+ addq $8, %rsp\r
+ popq %rax\r
+ movq %rax, %cr2\r
+ popq %rax\r
+ movq %rax, %cr3\r
+ popq %rax\r
+ movq %rax, %cr4\r
+ popq %rax\r
+ movq %rax, %cr8\r
+// UINT64 RFlags;\r
+ movq ASM_PFX(AppRsp)(%rip), %rax\r
+ popq 16(%rax)\r
+// UINT64 Ldtr, Tr;\r
+// UINT64 Gdtr[2], Idtr[2];\r
+// Best not let anyone mess with these particular registers...\r
+ addq $48, %rsp\r
+// UINT64 Rip;\r
+ popq (%rax)\r
+\r
+// UINT64 Gs, Fs, Es, Ds, Cs, Ss;\r
+// NOTE - modified segment registers could hang the debugger... We\r
+// could attempt to insulate ourselves against this possibility,\r
+// but that poses risks as well.\r
+//\r
+\r
+ popq %rax\r
+ # mov %rax, %gs\r
+ popq %rax\r
+ # mov %rax, %fs\r
+ popq %rax\r
+ mov %rax, %es\r
+ popq %rax\r
+ mov %rax, %ds\r
+ movq ASM_PFX(AppRsp)(%rip), %rax\r
+ popq 8(%rax)\r
+ popq %rax\r
+ mov %rax, %ss\r
+## The next stuff to restore is the general purpose registers that were pushed\r
+## using the "push" instruction.\r
+##\r
+## The value of RSP as stored in the context record is the application RSP\r
+## including the 5 entries on the application stack caused by the exception\r
+## itself. It may have been modified by the debug agent, so we need to\r
+## determine if we need to relocate the application stack.\r
+\r
+ movq 24(%rsp), %rbx # move the potentially modified AppRsp into rbx\r
+ movq ASM_PFX(AppRsp)(%rip), %rax\r
+ movq 24(%rax), %rax\r
+ cmpq %rax, %rbx\r
+ je NoAppStackMove\r
+\r
+ movq ASM_PFX(AppRsp)(%rip), %rax\r
+ movq (%rax), %rcx # RIP\r
+ movq %rcx, (%rbx)\r
+\r
+ movq 8(%rax), %rcx # CS\r
+ movq %rcx, 8(%rbx)\r
+\r
+ movq 16(%rax), %rcx # RFLAGS\r
+ movq %rcx, 16(%rbx)\r
+\r
+ movq 24(%rax), %rcx # RSP\r
+ movq %rcx, 24(%rbx)\r
+\r
+ movq 32(%rax), %rcx # SS\r
+ movq %rcx, 32(%rbx)\r
+\r
+ movq %rbx, %rax # modify the saved AppRsp to the new AppRsp\r
+ movq %rax, ASM_PFX(AppRsp)(%rip)\r
+NoAppStackMove:\r
+ movq ASM_PFX(DebugRsp)(%rip), %rax # restore the DebugRsp on the debug stack\r
+ # so our "pop" will not cause a stack switch\r
+ movq %rax, 24(%rsp)\r
+\r
+ cmpl $0x068, ASM_PFX(ExceptionNumber)(%rip)\r
+ jne NoChain\r
+\r
+Chain:\r
+\r
+// Restore rflags so when we chain, the flags will be exactly as if we were never here.\r
+// We gin up the stack to do an iretq so we can get ALL the flags.\r
+ movq ASM_PFX(AppRsp)(%rip), %rax\r
+ movq 40(%rax), %rbx\r
+ pushq %rbx\r
+ mov %ss, %rax\r
+ pushq %rax\r
+ movq %rsp, %rax\r
+ addq $16, %rax\r
+ pushq %rax\r
+ movq ASM_PFX(AppRsp)(%rip), %rax\r
+ movq 16(%rax), %rbx\r
+ andq $0xfffffffffffffcff, %rbx # special handling for IF and TF\r
+ pushq %rbx\r
+ mov %cs, %rax\r
+ pushq %rax\r
+ movq PhonyIretq(%rip), %rax\r
+ pushq %rax\r
+ iretq\r
+PhonyIretq:\r
+\r
+// UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
+// UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
+ popq %rdi\r
+ popq %rsi\r
+ popq %rbp\r
+ popq %rsp\r
+ popq %rbx\r
+ popq %rdx\r
+ popq %rcx\r
+ popq %rax\r
+ popq %r8\r
+ popq %r9\r
+ popq %r10\r
+ popq %r11\r
+ popq %r12\r
+ popq %r13\r
+ popq %r14\r
+ popq %r15\r
+\r
+// Switch back to application stack\r
+ movq ASM_PFX(AppRsp)(%rip), %rsp\r
+// Jump to original handler\r
+ jmp ASM_PFX(OrigVector)\r
+NoChain:\r
+// UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
+// UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
+ popq %rdi\r
+ popq %rsi\r
+ popq %rbp\r
+ popq %rsp\r
+ popq %rbx\r
+ popq %rdx\r
+ popq %rcx\r
+ popq %rax\r
+ popq %r8\r
+ popq %r9\r
+ popq %r10\r
+ popq %r11\r
+ popq %r12\r
+ popq %r13\r
+ popq %r14\r
+ popq %r15\r
+\r
+// Switch back to application stack\r
+ movq ASM_PFX(AppRsp)(%rip), %rsp\r
+\r
+// We're outa here...\r
+ iret\r
if (EFI_ERROR (Status)) {\r
goto ON_ERROR;\r
}\r
-
- //
+\r
+ //\r
// Get max packet size from Ip4 to calculate block size for Tftp later.\r
- //
- Status = Private->Ip4->GetModeData (Private->Ip4, &Ip4ModeData, NULL, NULL);
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
-
+ //\r
+ Status = Private->Ip4->GetModeData (Private->Ip4, &Ip4ModeData, NULL, NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
Private->Ip4MaxPacketSize = Ip4ModeData.MaxPacketSize;\r
\r
Status = NetLibCreateServiceChild (\r
#define PXEBC_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('P', 'X', 'E', 'P')\r
#define PXEBC_MTFTP_TIMEOUT 4\r
#define PXEBC_MTFTP_RETRIES 6\r
-#define PXEBC_DEFAULT_UDP_OVERHEAD_SIZE 8
+#define PXEBC_DEFAULT_UDP_OVERHEAD_SIZE 8\r
#define PXEBC_DEFAULT_TFTP_OVERHEAD_SIZE 4\r
#define PXEBC_DEFAULT_PACKET_SIZE 1480\r
#define PXEBC_DEFAULT_LIFETIME 50000 // 50ms, unit is microsecond\r
-## @file
-# Component description file for SMM Variable module.
-#
-# This module installs SMM variable protocol into SMM protocol database,
-# which can be used by SMM driver, and installs SMM variable protocol
-# into BS protocol database, which can be used to notify the SMM Runtime
-# Dxe driver that the SMM variable service is ready.
-# This module should be used with SMM Runtime DXE module together. The
-# SMM Runtime DXE module would install variable arch protocol and variable
-# write arch protocol based on SMM variable module.
-#
-# Caution: This module requires additional review when modified.
-# This driver will have external input - variable data and communicate buffer in SMM mode.
-# This external input must be validated carefully to avoid security issue like
-# buffer overflow, integer overflow.
-#
-# Copyright (c) 2010 - 2013, 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 = VariableSmm
- FILE_GUID = 23A089B3-EED5-4ac5-B2AB-43E3298C2343
- MODULE_TYPE = DXE_SMM_DRIVER
- VERSION_STRING = 1.0
- PI_SPECIFICATION_VERSION = 0x0001000A
- ENTRY_POINT = VariableServiceInitialize
-
-#
-# The following information is for reference only and not required by the build tools.
-#
-# VALID_ARCHITECTURES = IA32 X64
-#
-
-
-[Sources]
- Reclaim.c
- Variable.c
- VariableSmm.c
- Variable.h
-
-[Packages]
- MdePkg/MdePkg.dec
- MdeModulePkg/MdeModulePkg.dec
-
-[LibraryClasses]
- UefiDriverEntryPoint
- MemoryAllocationLib
- BaseLib
- SynchronizationLib
- UefiLib
- SmmServicesTableLib
- BaseMemoryLib
- DebugLib
- DxeServicesTableLib
- HobLib
- PcdLib
-
-[Protocols]
- gEfiSmmFirmwareVolumeBlockProtocolGuid ## SOMETIMES_CONSUMES
- gEfiSmmVariableProtocolGuid ## ALWAYS_PRODUCES
- gEfiSmmFaultTolerantWriteProtocolGuid ## SOMETIMES_CONSUMES
- gEfiSmmAccess2ProtocolGuid ## ALWAYS_CONSUMES
- gEfiSmmEndOfDxeProtocolGuid ## ALWAYS_CONSUMES
-
-[Guids]
- gEfiVariableGuid ## PRODUCES ## Configuration Table Guid
- gEfiGlobalVariableGuid ## PRODUCES ## Variable Guid
- gSmmVariableWriteGuid ## PRODUCES ## SMM Variable Write Guid
- gEfiSystemNvDataFvGuid ## CONSUMES
- gEfiHardwareErrorVariableGuid ## SOMETIMES_CONSUMES
- gEdkiiFaultTolerantWriteGuid ## CONSUMES
-
-[Pcd]
- gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
- gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
- gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64
- gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize
- gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize
- gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize
- gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize
-
-[FeaturePcd]
- gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics ## SOMETIME_CONSUMES (statistic the information of variable.)
-
-[Depex]
- TRUE
-
-
+## @file\r
+# Component description file for SMM Variable module.\r
+#\r
+# This module installs SMM variable protocol into SMM protocol database,\r
+# which can be used by SMM driver, and installs SMM variable protocol \r
+# into BS protocol database, which can be used to notify the SMM Runtime\r
+# Dxe driver that the SMM variable service is ready.\r
+# This module should be used with SMM Runtime DXE module together. The \r
+# SMM Runtime DXE module would install variable arch protocol and variable \r
+# write arch protocol based on SMM variable module.\r
+#\r
+# Caution: This module requires additional review when modified.\r
+# This driver will have external input - variable data and communicate buffer in SMM mode.\r
+# This external input must be validated carefully to avoid security issue like\r
+# buffer overflow, integer overflow.\r
+#\r
+# Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = VariableSmm\r
+ FILE_GUID = 23A089B3-EED5-4ac5-B2AB-43E3298C2343\r
+ MODULE_TYPE = DXE_SMM_DRIVER\r
+ VERSION_STRING = 1.0\r
+ PI_SPECIFICATION_VERSION = 0x0001000A\r
+ ENTRY_POINT = VariableServiceInitialize\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64\r
+#\r
+\r
+\r
+[Sources]\r
+ Reclaim.c\r
+ Variable.c\r
+ VariableSmm.c\r
+ Variable.h\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+\r
+[LibraryClasses]\r
+ UefiDriverEntryPoint\r
+ MemoryAllocationLib\r
+ BaseLib\r
+ SynchronizationLib\r
+ UefiLib\r
+ SmmServicesTableLib\r
+ BaseMemoryLib\r
+ DebugLib\r
+ DxeServicesTableLib\r
+ HobLib\r
+ PcdLib\r
+\r
+[Protocols]\r
+ gEfiSmmFirmwareVolumeBlockProtocolGuid ## SOMETIMES_CONSUMES\r
+ gEfiSmmVariableProtocolGuid ## ALWAYS_PRODUCES\r
+ gEfiSmmFaultTolerantWriteProtocolGuid ## SOMETIMES_CONSUMES\r
+ gEfiSmmAccess2ProtocolGuid ## ALWAYS_CONSUMES\r
+ gEfiSmmEndOfDxeProtocolGuid ## ALWAYS_CONSUMES\r
+\r
+[Guids]\r
+ gEfiVariableGuid ## PRODUCES ## Configuration Table Guid \r
+ gEfiGlobalVariableGuid ## PRODUCES ## Variable Guid\r
+ gSmmVariableWriteGuid ## PRODUCES ## SMM Variable Write Guid \r
+ gEfiSystemNvDataFvGuid ## CONSUMES\r
+ gEfiHardwareErrorVariableGuid ## SOMETIMES_CONSUMES\r
+ gEdkiiFaultTolerantWriteGuid ## CONSUMES\r
+\r
+[Pcd]\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize\r
+ \r
+[FeaturePcd]\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics ## SOMETIME_CONSUMES (statistic the information of variable.)\r
+\r
+[Depex]\r
+ TRUE\r
+\r
+ \r