MdeModulePkg: Add PEI USB drivers and related PPIs

Signed-off-by: jljusten
Reviewed-by: mdkinney
Reviewed-by: geekboy15a

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11901 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
jljusten 2011-06-27 23:30:55 +00:00
parent 366f81a016
commit 4b1bf81c20
36 changed files with 15879 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,227 @@
/** @file
Private Header file for Usb Host Controller PEIM
Copyright (c) 2010, 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 _RECOVERY_EHC_H_
#define _RECOVERY_EHC_H_
#include <PiPei.h>
#include <Ppi/UsbController.h>
#include <Ppi/Usb2HostController.h>
#include <Library/DebugLib.h>
#include <Library/PeimEntryPoint.h>
#include <Library/PeiServicesLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/TimerLib.h>
#include <Library/IoLib.h>
typedef struct _PEI_USB2_HC_DEV PEI_USB2_HC_DEV;
#define EFI_LIST_ENTRY LIST_ENTRY
#include "UsbHcMem.h"
#include "EhciReg.h"
#include "EhciUrb.h"
#include "EhciSched.h"
#define EFI_USB_SPEED_FULL 0x0000
#define EFI_USB_SPEED_LOW 0x0001
#define EFI_USB_SPEED_HIGH 0x0002
#define PAGESIZE 4096
#define EHC_1_MICROSECOND 1
#define EHC_1_MILLISECOND (1000 * EHC_1_MICROSECOND)
#define EHC_1_SECOND (1000 * EHC_1_MILLISECOND)
//
// EHCI register operation timeout, set by experience
//
#define EHC_RESET_TIMEOUT (1 * EHC_1_SECOND)
#define EHC_GENERIC_TIMEOUT (10 * EHC_1_MILLISECOND)
//
// Wait for roothub port power stable, refers to Spec[EHCI1.0-2.3.9]
//
#define EHC_ROOT_PORT_RECOVERY_STALL (20 * EHC_1_MILLISECOND)
//
// Sync and Async transfer polling interval, set by experience,
// and the unit of Async is 100us, means 50ms as interval.
//
#define EHC_SYNC_POLL_INTERVAL (6 * EHC_1_MILLISECOND)
#define EHC_ASYNC_POLL_INTERVAL (50 * 10000U)
//
//Iterate through the doule linked list. NOT delete safe
//
#define EFI_LIST_FOR_EACH(Entry, ListHead) \
for(Entry = (ListHead)->ForwardLink; Entry != (ListHead); Entry = Entry->ForwardLink)
//
//Iterate through the doule linked list. This is delete-safe.
//Don't touch NextEntry
//
#define EFI_LIST_FOR_EACH_SAFE(Entry, NextEntry, ListHead) \
for(Entry = (ListHead)->ForwardLink, NextEntry = Entry->ForwardLink;\
Entry != (ListHead); Entry = NextEntry, NextEntry = Entry->ForwardLink)
#define EFI_LIST_CONTAINER(Entry, Type, Field) BASE_CR(Entry, Type, Field)
#define EHC_LOW_32BIT(Addr64) ((UINT32)(((UINTN)(Addr64)) & 0XFFFFFFFF))
#define EHC_HIGH_32BIT(Addr64) ((UINT32)(RShiftU64((UINTN)(Addr64), 32) & 0XFFFFFFFF))
#define EHC_BIT_IS_SET(Data, Bit) ((BOOLEAN)(((Data) & (Bit)) == (Bit)))
#define EHC_REG_BIT_IS_SET(Ehc, Offset, Bit) \
(EHC_BIT_IS_SET(EhcReadOpReg ((Ehc), (Offset)), (Bit)))
#define USB2_HC_DEV_SIGNATURE SIGNATURE_32 ('e', 'h', 'c', 'i')
struct _PEI_USB2_HC_DEV {
UINTN Signature;
PEI_USB2_HOST_CONTROLLER_PPI Usb2HostControllerPpi;
EFI_PEI_PPI_DESCRIPTOR PpiDescriptor;
UINT32 UsbHostControllerBaseAddress;
PEI_URB *Urb;
USBHC_MEM_POOL *MemPool;
//
// Schedule data shared between asynchronous and periodic
// transfers:
// ShortReadStop, as its name indicates, is used to terminate
// the short read except the control transfer. EHCI follows
// the alternative next QTD point when a short read happens.
// For control transfer, even the short read happens, try the
// status stage.
//
PEI_EHC_QTD *ShortReadStop;
EFI_EVENT PollTimer;
//
// Asynchronous(bulk and control) transfer schedule data:
// ReclaimHead is used as the head of the asynchronous transfer
// list. It acts as the reclamation header.
//
PEI_EHC_QH *ReclaimHead;
//
// Peroidic (interrupt) transfer schedule data:
//
VOID *PeriodFrame; // Mapped as common buffer
VOID *PeriodFrameHost;
VOID *PeriodFrameMap;
PEI_EHC_QH *PeriodOne;
EFI_LIST_ENTRY AsyncIntTransfers;
//
// EHCI configuration data
//
UINT32 HcStructParams; // Cache of HC structure parameter, EHC_HCSPARAMS_OFFSET
UINT32 HcCapParams; // Cache of HC capability parameter, HCCPARAMS
UINT32 CapLen; // Capability length
UINT32 High32bitAddr;
};
#define PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS(a) CR (a, PEI_USB2_HC_DEV, Usb2HostControllerPpi, USB2_HC_DEV_SIGNATURE)
/**
@param EhcDev EHCI Device.
@retval EFI_SUCCESS EHCI successfully initialized.
@retval EFI_ABORTED EHCI was failed to be initialized.
**/
EFI_STATUS
InitializeUsbHC (
IN PEI_USB2_HC_DEV *EhcDev
);
/**
Initialize the memory management pool for the host controller.
@param Ehc The EHCI device.
@param Check4G Whether the host controller requires allocated memory
from one 4G address space.
@param Which4G The 4G memory area each memory allocated should be from.
@retval EFI_SUCCESS The memory pool is initialized.
@retval EFI_OUT_OF_RESOURCE Fail to init the memory pool.
**/
USBHC_MEM_POOL *
UsbHcInitMemPool (
IN PEI_USB2_HC_DEV *Ehc,
IN BOOLEAN Check4G,
IN UINT32 Which4G
)
;
/**
Release the memory management pool.
@param Pool The USB memory pool to free.
@retval EFI_DEVICE_ERROR Fail to free the memory pool.
@retval EFI_SUCCESS The memory pool is freed.
**/
EFI_STATUS
UsbHcFreeMemPool (
IN USBHC_MEM_POOL *Pool
)
;
/**
Allocate some memory from the host controller's memory pool
which can be used to communicate with host controller.
@param Ehc The EHCI device.
@param Pool The host controller's memory pool.
@param Size Size of the memory to allocate.
@return The allocated memory or NULL.
**/
VOID *
UsbHcAllocateMem (
IN PEI_USB2_HC_DEV *Ehc,
IN USBHC_MEM_POOL *Pool,
IN UINTN Size
)
;
/**
Free the allocated memory back to the memory pool.
@param Pool The memory pool of the host controller.
@param Mem The memory to free.
@param Size The size of the memory to free.
**/
VOID
UsbHcFreeMem (
IN USBHC_MEM_POOL *Pool,
IN VOID *Mem,
IN UINTN Size
)
;
#endif

View File

@ -0,0 +1,66 @@
## @file
# Component description file for EhcPeim PEIM to produce gPeiUsb2HostControllerPpiGuid
# based on gPeiUsbControllerPpiGuid which is used to enable recovery function from USB Drivers.
#
# Copyright (c) 2010, 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 = EhciPei
FILE_GUID = BAB4F20F-0981-4b5f-A047-6EF83BEEAB3C
MODULE_TYPE = PEIM
VERSION_STRING = 1.0
ENTRY_POINT = EhcPeimEntry
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources]
EhcPeim.c
EhcPeim.h
EhciUrb.c
EhciSched.c
UsbHcMem.c
EhciReg.h
EhciSched.h
EhciUrb.h
UsbHcMem.h
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
IoLib
TimerLib
BaseMemoryLib
PeimEntryPoint
PeiServicesLib
[Ppis]
gPeiUsb2HostControllerPpiGuid # PPI ALWAYS_PRODUCED
gPeiUsbControllerPpiGuid # PPI ALWAYS_CONSUMED
[Depex]
gEfiPeiMemoryDiscoveredPpiGuid AND gPeiUsbControllerPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid

View File

@ -0,0 +1,310 @@
/** @file
Private Header file for Usb Host Controller PEIM
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions
of the BSD License which accompanies this distribution. The
full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _EFI_EHCI_REG_H_
#define _EFI_EHCI_REG_H_
//
// Capability register offset
//
#define EHC_CAPLENGTH_OFFSET 0 // Capability register length offset
#define EHC_HCSPARAMS_OFFSET 0x04 // Structural Parameters 04-07h
#define EHC_HCCPARAMS_OFFSET 0x08 // Capability parameters offset
//
// Capability register bit definition
//
#define HCSP_NPORTS 0x0F // Number of root hub port
#define HCCP_64BIT 0x01 // 64-bit addressing capability
//
// Operational register offset
//
#define EHC_USBCMD_OFFSET 0x0 // USB command register offset
#define EHC_USBSTS_OFFSET 0x04 // Statue register offset
#define EHC_USBINTR_OFFSET 0x08 // USB interrutp offset
#define EHC_FRINDEX_OFFSET 0x0C // Frame index offset
#define EHC_CTRLDSSEG_OFFSET 0x10 // Control data structure segment offset
#define EHC_FRAME_BASE_OFFSET 0x14 // Frame list base address offset
#define EHC_ASYNC_HEAD_OFFSET 0x18 // Next asynchronous list address offset
#define EHC_CONFIG_FLAG_OFFSET 0x40 // Configure flag register offset
#define EHC_PORT_STAT_OFFSET 0x44 // Port status/control offset
#define EHC_FRAME_LEN 1024
//
// Register bit definition
//
#define CONFIGFLAG_ROUTE_EHC 0x01 // Route port to EHC
#define USBCMD_RUN 0x01 // Run/stop
#define USBCMD_RESET 0x02 // Start the host controller reset
#define USBCMD_ENABLE_PERIOD 0x10 // Enable periodic schedule
#define USBCMD_ENABLE_ASYNC 0x20 // Enable asynchronous schedule
#define USBCMD_IAAD 0x40 // Interrupt on async advance doorbell
#define USBSTS_IAA 0x20 // Interrupt on async advance
#define USBSTS_PERIOD_ENABLED 0x4000 // Periodic schedule status
#define USBSTS_ASYNC_ENABLED 0x8000 // Asynchronous schedule status
#define USBSTS_HALT 0x1000 // Host controller halted
#define USBSTS_SYS_ERROR 0x10 // Host system error
#define USBSTS_INTACK_MASK 0x003F // Mask for the interrupt ACK, the WC
// (write clean) bits in USBSTS register
#define PORTSC_CONN 0x01 // Current Connect Status
#define PORTSC_CONN_CHANGE 0x02 // Connect Status Change
#define PORTSC_ENABLED 0x04 // Port Enable / Disable
#define PORTSC_ENABLE_CHANGE 0x08 // Port Enable / Disable Change
#define PORTSC_OVERCUR 0x10 // Over current Active
#define PORTSC_OVERCUR_CHANGE 0x20 // Over current Change
#define PORSTSC_RESUME 0x40 // Force Port Resume
#define PORTSC_SUSPEND 0x80 // Port Suspend State
#define PORTSC_RESET 0x100 // Port Reset
#define PORTSC_LINESTATE_K 0x400 // Line Status K-state
#define PORTSC_LINESTATE_J 0x800 // Line Status J-state
#define PORTSC_POWER 0x1000 // Port Power
#define PORTSC_OWNER 0x2000 // Port Owner
#define PORTSC_CHANGE_MASK 0x2A // Mask of the port change bits,
// they are WC (write clean)
//
// PCI Configuration Registers
//
#define EHC_BAR_INDEX 0 // how many bytes away from USB_BASE to 0x10
#define EHC_LINK_TERMINATED(Link) (((Link) & 0x01) != 0)
#define EHC_ADDR(High, QhHw32) \
((VOID *) (UINTN) (LShiftU64 ((High), 32) | ((QhHw32) & 0xFFFFFFF0)))
#define EHCI_IS_DATAIN(EndpointAddr) EHC_BIT_IS_SET((EndpointAddr), 0x80)
//
// Structure to map the hardware port states to the
// UEFI's port states.
//
typedef struct {
UINT16 HwState;
UINT16 UefiState;
} USB_PORT_STATE_MAP;
//
// Ehci Data and Ctrl Structures
//
#pragma pack(1)
typedef struct {
UINT8 Pi;
UINT8 SubClassCode;
UINT8 BaseCode;
} USB_CLASSC;
#pragma pack()
/**
Read EHCI capability register.
@param Ehc The EHCI device.
@param Offset Capability register address.
@retval the register content read.
**/
UINT32
EhcReadCapRegister (
IN PEI_USB2_HC_DEV *Ehc,
IN UINT32 Offset
)
;
/**
Read Ehc Operation register.
@param Ehc The EHCI device.
@param Offset The operation register offset.
@retval the register content read.
**/
UINT32
EhcReadOpReg (
IN PEI_USB2_HC_DEV *Ehc,
IN UINT32 Offset
)
;
/**
Write the data to the EHCI operation register.
@param Ehc The EHCI device.
@param Offset EHCI operation register offset.
@param Data The data to write.
**/
VOID
EhcWriteOpReg (
IN PEI_USB2_HC_DEV *Ehc,
IN UINT32 Offset,
IN UINT32 Data
)
;
/**
Stop the legacy USB SMI support.
@param Ehc The EHCI device.
**/
VOID
EhcClearLegacySupport (
IN PEI_USB2_HC_DEV *Ehc
)
;
/**
Set door bell and wait it to be ACKed by host controller.
This function is used to synchronize with the hardware.
@param Ehc The EHCI device.
@param Timeout The time to wait before abort (in millisecond, ms).
@retval EFI_TIMEOUT Time out happened while waiting door bell to set.
@retval EFI_SUCCESS Synchronized with the hardware.
**/
EFI_STATUS
EhcSetAndWaitDoorBell (
IN PEI_USB2_HC_DEV *Ehc,
IN UINT32 Timeout
)
;
/**
Clear all the interrutp status bits, these bits
are Write-Clean.
@param Ehc The EHCI device.
**/
VOID
EhcAckAllInterrupt (
IN PEI_USB2_HC_DEV *Ehc
)
;
/**
Check whether Ehc is halted.
@param Ehc The EHCI device.
@retval TRUE The controller is halted.
@retval FALSE The controller isn't halted.
**/
BOOLEAN
EhcIsHalt (
IN PEI_USB2_HC_DEV *Ehc
)
;
/**
Check whether system error occurred.
@param Ehc The EHCI device.
@retval TRUE System error happened.
@retval FALSE No system error.
**/
BOOLEAN
EhcIsSysError (
IN PEI_USB2_HC_DEV *Ehc
)
;
/**
Reset the host controller.
@param Ehc The EHCI device.
@param Timeout Time to wait before abort (in millisecond, ms).
@retval EFI_TIMEOUT The transfer failed due to time out.
@retval Others Failed to reset the host.
**/
EFI_STATUS
EhcResetHC (
IN PEI_USB2_HC_DEV *Ehc,
IN UINT32 Timeout
)
;
/**
Halt the host controller.
@param Ehc The EHCI device.
@param Timeout Time to wait before abort.
@retval EFI_TIMEOUT Failed to halt the controller before Timeout.
@retval EFI_SUCCESS The EHCI is halt.
**/
EFI_STATUS
EhcHaltHC (
IN PEI_USB2_HC_DEV *Ehc,
IN UINT32 Timeout
)
;
/**
Set the EHCI to run
@param Ehc The EHCI device.
@param Timeout Time to wait before abort.
@retval EFI_SUCCESS The EHCI is running.
@retval Others Failed to set the EHCI to run.
**/
EFI_STATUS
EhcRunHC (
IN PEI_USB2_HC_DEV *Ehc,
IN UINT32 Timeout
)
;
/**
Initialize the HC hardware.
EHCI spec lists the five things to do to initialize the hardware.
1. Program CTRLDSSEGMENT.
2. Set USBINTR to enable interrupts.
3. Set periodic list base.
4. Set USBCMD, interrupt threshold, frame list size etc.
5. Write 1 to CONFIGFLAG to route all ports to EHCI.
@param Ehc The EHCI device.
@retval EFI_SUCCESS The EHCI has come out of halt state.
@retval EFI_TIMEOUT Time out happened.
**/
EFI_STATUS
EhcInitHC (
IN PEI_USB2_HC_DEV *Ehc
)
;
#endif

View File

@ -0,0 +1,873 @@
/** @file
PEIM to produce gPeiUsb2HostControllerPpiGuid based on gPeiUsbControllerPpiGuid
which is used to enable recovery function from USB Drivers.
Copyright (c) 2010, 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 "EhcPeim.h"
/**
Create helper QTD/QH for the EHCI device.
@param Ehc The EHCI device.
@retval EFI_OUT_OF_RESOURCES Failed to allocate resource for helper QTD/QH.
@retval EFI_SUCCESS Helper QH/QTD are created.
**/
EFI_STATUS
EhcCreateHelpQ (
IN PEI_USB2_HC_DEV *Ehc
)
{
USB_ENDPOINT Ep;
PEI_EHC_QH *Qh;
QH_HW *QhHw;
PEI_EHC_QTD *Qtd;
//
// Create an inactive Qtd to terminate the short packet read.
//
Qtd = EhcCreateQtd (Ehc, NULL, 0, QTD_PID_INPUT, 0, 64);
if (Qtd == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Qtd->QtdHw.Status = QTD_STAT_HALTED;
Ehc->ShortReadStop = Qtd;
//
// Create a QH to act as the EHC reclamation header.
// Set the header to loopback to itself.
//
Ep.DevAddr = 0;
Ep.EpAddr = 1;
Ep.Direction = EfiUsbDataIn;
Ep.DevSpeed = EFI_USB_SPEED_HIGH;
Ep.MaxPacket = 64;
Ep.HubAddr = 0;
Ep.HubPort = 0;
Ep.Toggle = 0;
Ep.Type = EHC_BULK_TRANSFER;
Ep.PollRate = 1;
Qh = EhcCreateQh (Ehc, &Ep);
if (Qh == NULL) {
return EFI_OUT_OF_RESOURCES;
}
QhHw = &Qh->QhHw;
QhHw->HorizonLink = QH_LINK (QhHw, EHC_TYPE_QH, FALSE);
QhHw->Status = QTD_STAT_HALTED;
QhHw->ReclaimHead = 1;
Ehc->ReclaimHead = Qh;
//
// Create a dummy QH to act as the terminator for periodical schedule
//
Ep.EpAddr = 2;
Ep.Type = EHC_INT_TRANSFER_SYNC;
Qh = EhcCreateQh (Ehc, &Ep);
if (Qh == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Qh->QhHw.Status = QTD_STAT_HALTED;
Ehc->PeriodOne = Qh;
return EFI_SUCCESS;
}
/**
Initialize the schedule data structure such as frame list.
@param Ehc The EHCI device to init schedule data for.
@retval EFI_OUT_OF_RESOURCES Failed to allocate resource to init schedule data.
@retval EFI_SUCCESS The schedule data is initialized.
**/
EFI_STATUS
EhcInitSched (
IN PEI_USB2_HC_DEV *Ehc
)
{
EFI_PHYSICAL_ADDRESS PhyAddr;
VOID *Map;
UINTN Index;
UINT32 *Desc;
EFI_STATUS Status;
//
// First initialize the periodical schedule data:
// 1. Allocate and map the memory for the frame list
// 2. Create the help QTD/QH
// 3. Initialize the frame entries
// 4. Set the frame list register
//
//
// The Frame List ocupies 4K bytes,
// and must be aligned on 4-Kbyte boundaries.
//
Status = PeiServicesAllocatePages (
EfiBootServicesCode,
1,
&PhyAddr
);
Map = NULL;
Ehc->PeriodFrameHost = (VOID *)(UINTN)PhyAddr;
Ehc->PeriodFrame = (VOID *)(UINTN)PhyAddr;
Ehc->PeriodFrameMap = Map;
Ehc->High32bitAddr = EHC_HIGH_32BIT (PhyAddr);
//
// Init memory pool management then create the helper
// QTD/QH. If failed, previously allocated resources
// will be freed by EhcFreeSched
//
Ehc->MemPool = UsbHcInitMemPool (
Ehc,
EHC_BIT_IS_SET (Ehc->HcCapParams, HCCP_64BIT),
Ehc->High32bitAddr
);
if (Ehc->MemPool == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = EhcCreateHelpQ (Ehc);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Initialize the frame list entries then set the registers
//
Desc = (UINT32 *) Ehc->PeriodFrame;
for (Index = 0; Index < EHC_FRAME_LEN; Index++) {
Desc[Index] = QH_LINK (Ehc->PeriodOne, EHC_TYPE_QH, FALSE);
}
EhcWriteOpReg (Ehc, EHC_FRAME_BASE_OFFSET, EHC_LOW_32BIT (Ehc->PeriodFrame));
//
// Second initialize the asynchronous schedule:
// Only need to set the AsynListAddr register to
// the reclamation header
//
EhcWriteOpReg (Ehc, EHC_ASYNC_HEAD_OFFSET, EHC_LOW_32BIT (Ehc->ReclaimHead));
return EFI_SUCCESS;
}
/**
Free the schedule data. It may be partially initialized.
@param Ehc The EHCI device.
**/
VOID
EhcFreeSched (
IN PEI_USB2_HC_DEV *Ehc
)
{
EhcWriteOpReg (Ehc, EHC_FRAME_BASE_OFFSET, 0);
EhcWriteOpReg (Ehc, EHC_ASYNC_HEAD_OFFSET, 0);
if (Ehc->PeriodOne != NULL) {
UsbHcFreeMem (Ehc->MemPool, Ehc->PeriodOne, sizeof (PEI_EHC_QH));
Ehc->PeriodOne = NULL;
}
if (Ehc->ReclaimHead != NULL) {
UsbHcFreeMem (Ehc->MemPool, Ehc->ReclaimHead, sizeof (PEI_EHC_QH));
Ehc->ReclaimHead = NULL;
}
if (Ehc->ShortReadStop != NULL) {
UsbHcFreeMem (Ehc->MemPool, Ehc->ShortReadStop, sizeof (PEI_EHC_QTD));
Ehc->ShortReadStop = NULL;
}
if (Ehc->MemPool != NULL) {
UsbHcFreeMemPool (Ehc->MemPool);
Ehc->MemPool = NULL;
}
if (Ehc->PeriodFrame != NULL) {
Ehc->PeriodFrame = NULL;
}
}
/**
Link the queue head to the asynchronous schedule list.
UEFI only supports one CTRL/BULK transfer at a time
due to its interfaces. This simplifies the AsynList
management: A reclamation header is always linked to
the AsyncListAddr, the only active QH is appended to it.
@param Ehc The EHCI device.
@param Qh The queue head to link.
**/
VOID
EhcLinkQhToAsync (
IN PEI_USB2_HC_DEV *Ehc,
IN PEI_EHC_QH *Qh
)
{
PEI_EHC_QH *Head;
//
// Append the queue head after the reclaim header, then
// fix the hardware visiable parts (EHCI R1.0 page 72).
// ReclaimHead is always linked to the EHCI's AsynListAddr.
//
Head = Ehc->ReclaimHead;
Qh->NextQh = Head->NextQh;
Head->NextQh = Qh;
Qh->QhHw.HorizonLink = QH_LINK (Head, EHC_TYPE_QH, FALSE);;
Head->QhHw.HorizonLink = QH_LINK (Qh, EHC_TYPE_QH, FALSE);
}
/**
Unlink a queue head from the asynchronous schedule list.
Need to synchronize with hardware.
@param Ehc The EHCI device.
@param Qh The queue head to unlink.
**/
VOID
EhcUnlinkQhFromAsync (
IN PEI_USB2_HC_DEV *Ehc,
IN PEI_EHC_QH *Qh
)
{
PEI_EHC_QH *Head;
EFI_STATUS Status;
ASSERT (Ehc->ReclaimHead->NextQh == Qh);
//
// Remove the QH from reclamation head, then update the hardware
// visiable part: Only need to loopback the ReclaimHead. The Qh
// is pointing to ReclaimHead (which is staill in the list).
//
Head = Ehc->ReclaimHead;
Head->NextQh = Qh->NextQh;
Qh->NextQh = NULL;
Head->QhHw.HorizonLink = QH_LINK (Head, EHC_TYPE_QH, FALSE);
//
// Set and wait the door bell to synchronize with the hardware
//
Status = EhcSetAndWaitDoorBell (Ehc, EHC_GENERIC_TIMEOUT);
return;
}
/**
Link a queue head for interrupt transfer to the periodic
schedule frame list. This code is very much the same as
that in UHCI.
@param Ehc The EHCI device.
@param Qh The queue head to link.
**/
VOID
EhcLinkQhToPeriod (
IN PEI_USB2_HC_DEV *Ehc,
IN PEI_EHC_QH *Qh
)
{
UINT32 *Frames;
UINTN Index;
PEI_EHC_QH *Prev;
PEI_EHC_QH *Next;
Frames = Ehc->PeriodFrame;
for (Index = 0; Index < EHC_FRAME_LEN; Index += Qh->Interval) {
//
// First QH can't be NULL because we always keep PeriodOne
// heads on the frame list
//
ASSERT (!EHC_LINK_TERMINATED (Frames[Index]));
Next = EHC_ADDR (Ehc->High32bitAddr, Frames[Index]);
Prev = NULL;
//
// Now, insert the queue head (Qh) into this frame:
// 1. Find a queue head with the same poll interval, just insert
// Qh after this queue head, then we are done.
//
// 2. Find the position to insert the queue head into:
// Previous head's interval is bigger than Qh's
// Next head's interval is less than Qh's
// Then, insert the Qh between then
//
while (Next->Interval > Qh->Interval) {
Prev = Next;
Next = Next->NextQh;
}
ASSERT (Next != NULL);
//
// The entry may have been linked into the frame by early insertation.
// For example: if insert a Qh with Qh.Interval == 4, and there is a Qh
// with Qh.Interval == 8 on the frame. If so, we are done with this frame.
// It isn't necessary to compare all the QH with the same interval to
// Qh. This is because if there is other QH with the same interval, Qh
// should has been inserted after that at Frames[0] and at Frames[0] it is
// impossible for (Next == Qh)
//
if (Next == Qh) {
continue;
}
if (Next->Interval == Qh->Interval) {
//
// If there is a QH with the same interval, it locates at
// Frames[0], and we can simply insert it after this QH. We
// are all done.
//
ASSERT ((Index == 0) && (Qh->NextQh == NULL));
Prev = Next;
Next = Next->NextQh;
Qh->NextQh = Next;
Prev->NextQh = Qh;
Qh->QhHw.HorizonLink = Prev->QhHw.HorizonLink;
Prev->QhHw.HorizonLink = QH_LINK (Qh, EHC_TYPE_QH, FALSE);
break;
}
//
// OK, find the right position, insert it in. If Qh's next
// link has already been set, it is in position. This is
// guarranted by 2^n polling interval.
//
if (Qh->NextQh == NULL) {
Qh->NextQh = Next;
Qh->QhHw.HorizonLink = QH_LINK (Next, EHC_TYPE_QH, FALSE);
}
if (Prev == NULL) {
Frames[Index] = QH_LINK (Qh, EHC_TYPE_QH, FALSE);
} else {
Prev->NextQh = Qh;
Prev->QhHw.HorizonLink = QH_LINK (Qh, EHC_TYPE_QH, FALSE);
}
}
}
/**
Unlink an interrupt queue head from the periodic
schedule frame list.
@param Ehc The EHCI device.
@param Qh The queue head to unlink.
**/
VOID
EhcUnlinkQhFromPeriod (
IN PEI_USB2_HC_DEV *Ehc,
IN PEI_EHC_QH *Qh
)
{
UINT32 *Frames;
UINTN Index;
PEI_EHC_QH *Prev;
PEI_EHC_QH *This;
Frames = Ehc->PeriodFrame;
for (Index = 0; Index < EHC_FRAME_LEN; Index += Qh->Interval) {
//
// Frame link can't be NULL because we always keep PeroidOne
// on the frame list
//
ASSERT (!EHC_LINK_TERMINATED (Frames[Index]));
This = EHC_ADDR (Ehc->High32bitAddr, Frames[Index]);
Prev = NULL;
//
// Walk through the frame's QH list to find the
// queue head to remove
//
while ((This != NULL) && (This != Qh)) {
Prev = This;
This = This->NextQh;
}
//
// Qh may have already been unlinked from this frame
// by early action. See the comments in EhcLinkQhToPeriod.
//
if (This == NULL) {
continue;
}
if (Prev == NULL) {
//
// Qh is the first entry in the frame
//
Frames[Index] = Qh->QhHw.HorizonLink;
} else {
Prev->NextQh = Qh->NextQh;
Prev->QhHw.HorizonLink = Qh->QhHw.HorizonLink;
}
}
}
/**
Check the URB's execution result and update the URB's
result accordingly.
@param Ehc The EHCI device.
@param Urb The URB to check result.
@retval TRUE URB transfer is finialized.
@retval FALSE URB transfer is not finialized.
**/
BOOLEAN
EhcCheckUrbResult (
IN PEI_USB2_HC_DEV *Ehc,
IN PEI_URB *Urb
)
{
EFI_LIST_ENTRY *Entry;
PEI_EHC_QTD *Qtd;
QTD_HW *QtdHw;
UINT8 State;
BOOLEAN Finished;
ASSERT ((Ehc != NULL) && (Urb != NULL) && (Urb->Qh != NULL));
Finished = TRUE;
Urb->Completed = 0;
Urb->Result = EFI_USB_NOERROR;
if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
Urb->Result |= EFI_USB_ERR_SYSTEM;
goto ON_EXIT;
}
EFI_LIST_FOR_EACH (Entry, &Urb->Qh->Qtds) {
Qtd = EFI_LIST_CONTAINER (Entry, PEI_EHC_QTD, QtdList);
QtdHw = &Qtd->QtdHw;
State = (UINT8) QtdHw->Status;
if (EHC_BIT_IS_SET (State, QTD_STAT_HALTED)) {
//
// EHCI will halt the queue head when met some error.
// If it is halted, the result of URB is finialized.
//
if ((State & QTD_STAT_ERR_MASK) == 0) {
Urb->Result |= EFI_USB_ERR_STALL;
}
if (EHC_BIT_IS_SET (State, QTD_STAT_BABBLE_ERR)) {
Urb->Result |= EFI_USB_ERR_BABBLE;
}
if (EHC_BIT_IS_SET (State, QTD_STAT_BUFF_ERR)) {
Urb->Result |= EFI_USB_ERR_BUFFER;
}
if (EHC_BIT_IS_SET (State, QTD_STAT_TRANS_ERR) && (QtdHw->ErrCnt == 0)) {
Urb->Result |= EFI_USB_ERR_TIMEOUT;
}
Finished = TRUE;
goto ON_EXIT;
} else if (EHC_BIT_IS_SET (State, QTD_STAT_ACTIVE)) {
//
// The QTD is still active, no need to check furthur.
//
Urb->Result |= EFI_USB_ERR_NOTEXECUTE;
Finished = FALSE;
goto ON_EXIT;
} else {
//
// This QTD is finished OK or met short packet read. Update the
// transfer length if it isn't a setup.
//
if (QtdHw->Pid != QTD_PID_SETUP) {
Urb->Completed += Qtd->DataLen - QtdHw->TotalBytes;
}
if ((QtdHw->TotalBytes != 0) && (QtdHw->Pid == QTD_PID_INPUT)) {
//EHC_DUMP_QH ((Urb->Qh, "Short packet read", FALSE));
//
// Short packet read condition. If it isn't a setup transfer,
// no need to check furthur: the queue head will halt at the
// ShortReadStop. If it is a setup transfer, need to check the
// Status Stage of the setup transfer to get the finial result
//
if (QtdHw->AltNext == QTD_LINK (Ehc->ShortReadStop, FALSE)) {
Finished = TRUE;
goto ON_EXIT;
}
}
}
}
ON_EXIT:
//
// Return the data toggle set by EHCI hardware, bulk and interrupt
// transfer will use this to initialize the next transaction. For
// Control transfer, it always start a new data toggle sequence for
// new transfer.
//
// NOTICE: don't move DT update before the loop, otherwise there is
// a race condition that DT is wrong.
//
Urb->DataToggle = (UINT8) Urb->Qh->QhHw.DataToggle;
return Finished;
}
/**
Execute the transfer by polling the URB. This is a synchronous operation.
@param Ehc The EHCI device.
@param Urb The URB to execute.
@param TimeOut The time to wait before abort, in millisecond.
@retval EFI_DEVICE_ERROR The transfer failed due to transfer error.
@retval EFI_TIMEOUT The transfer failed due to time out.
@retval EFI_SUCCESS The transfer finished OK.
**/
EFI_STATUS
EhcExecTransfer (
IN PEI_USB2_HC_DEV *Ehc,
IN PEI_URB *Urb,
IN UINTN TimeOut
)
{
EFI_STATUS Status;
UINTN Index;
UINTN Loop;
BOOLEAN Finished;
Status = EFI_SUCCESS;
Loop = (TimeOut * EHC_1_MILLISECOND / EHC_SYNC_POLL_INTERVAL) + 1;
Finished = FALSE;
for (Index = 0; Index < Loop; Index++) {
Finished = EhcCheckUrbResult (Ehc, Urb);
if (Finished) {
break;
}
MicroSecondDelay (EHC_SYNC_POLL_INTERVAL);
}
if (!Finished) {
Status = EFI_TIMEOUT;
} else if (Urb->Result != EFI_USB_NOERROR) {
Status = EFI_DEVICE_ERROR;
}
return Status;
}
/**
Delete a single asynchronous interrupt transfer for
the device and endpoint.
@param Ehc The EHCI device.
@param DevAddr The address of the target device.
@param EpNum The endpoint of the target.
@param DataToggle Return the next data toggle to use.
@retval EFI_NOT_FOUND No transfer for the device is found.
@retval EFI_SUCCESS An asynchronous transfer is removed.
**/
EFI_STATUS
EhciDelAsyncIntTransfer (
IN PEI_USB2_HC_DEV *Ehc,
IN UINT8 DevAddr,
IN UINT8 EpNum,
OUT UINT8 *DataToggle
)
{
EFI_LIST_ENTRY *Entry;
EFI_LIST_ENTRY *Next;
PEI_URB *Urb;
EFI_USB_DATA_DIRECTION Direction;
Direction = (((EpNum & 0x80) != 0) ? EfiUsbDataIn : EfiUsbDataOut);
EpNum &= 0x0F;
EFI_LIST_FOR_EACH_SAFE (Entry, Next, &Ehc->AsyncIntTransfers) {
Urb = EFI_LIST_CONTAINER (Entry, PEI_URB, UrbList);
if ((Urb->Ep.DevAddr == DevAddr) && (Urb->Ep.EpAddr == EpNum) &&
(Urb->Ep.Direction == Direction)) {
//
// Check the URB status to retrieve the next data toggle
// from the associated queue head.
//
EhcCheckUrbResult (Ehc, Urb);
*DataToggle = Urb->DataToggle;
EhcUnlinkQhFromPeriod (Ehc, Urb->Qh);
RemoveEntryList (&Urb->UrbList);
EhcFreeUrb (Ehc, Urb);
return EFI_SUCCESS;
}
}
return EFI_NOT_FOUND;
}
/**
Remove all the asynchronous interrutp transfers.
@param Ehc The EHCI device.
**/
VOID
EhciDelAllAsyncIntTransfers (
IN PEI_USB2_HC_DEV *Ehc
)
{
EFI_LIST_ENTRY *Entry;
EFI_LIST_ENTRY *Next;
PEI_URB *Urb;
EFI_LIST_FOR_EACH_SAFE (Entry, Next, &Ehc->AsyncIntTransfers) {
Urb = EFI_LIST_CONTAINER (Entry, PEI_URB, UrbList);
EhcUnlinkQhFromPeriod (Ehc, Urb->Qh);
RemoveEntryList (&Urb->UrbList);
EhcFreeUrb (Ehc, Urb);
}
}
/**
Flush data from PCI controller specific address to mapped system
memory address.
@param Ehc The EHCI device.
@param Urb The URB to unmap.
@retval EFI_DEVICE_ERROR Fail to flush data to mapped system memory.
@retval EFI_SUCCESS Success to flush data to mapped system memory.
**/
EFI_STATUS
EhcFlushAsyncIntMap (
IN PEI_USB2_HC_DEV *Ehc,
IN PEI_URB *Urb
)
{
EFI_PHYSICAL_ADDRESS PhyAddr;
Urb->DataMap = NULL;
PhyAddr = (EFI_PHYSICAL_ADDRESS) (UINTN) Urb->Data;
Urb->DataPhy = (VOID *) ((UINTN) PhyAddr);
return EFI_SUCCESS;
}
/**
Update the queue head for next round of asynchronous transfer.
@param Urb The URB to update.
**/
VOID
EhcUpdateAsyncRequest (
IN PEI_URB *Urb
)
{
EFI_LIST_ENTRY *Entry;
PEI_EHC_QTD *FirstQtd;
QH_HW *QhHw;
PEI_EHC_QTD *Qtd;
QTD_HW *QtdHw;
UINTN Index;
Qtd = NULL;
if (Urb->Result == EFI_USB_NOERROR) {
FirstQtd = NULL;
EFI_LIST_FOR_EACH (Entry, &Urb->Qh->Qtds) {
Qtd = EFI_LIST_CONTAINER (Entry, PEI_EHC_QTD, QtdList);
if (FirstQtd == NULL) {
FirstQtd = Qtd;
}
//
// Update the QTD for next round of transfer. Host control
// may change dt/Total Bytes to Transfer/C_Page/Cerr/Status/
// Current Offset. These fields need to be updated. DT isn't
// used by interrupt transfer. It uses DT in queue head.
// Current Offset is in Page[0], only need to reset Page[0]
// to initial data buffer.
//
QtdHw = &Qtd->QtdHw;
QtdHw->Status = QTD_STAT_ACTIVE;
QtdHw->ErrCnt = QTD_MAX_ERR;
QtdHw->CurPage = 0;
QtdHw->TotalBytes = (UINT32) Qtd->DataLen;
QtdHw->Page[0] = EHC_LOW_32BIT (Qtd->Data);
}
//
// Update QH for next round of transfer. Host control only
// touch the fields in transfer overlay area. Only need to
// zero out the overlay area and set NextQtd to the first
// QTD. DateToggle bit is left untouched.
//
QhHw = &Urb->Qh->QhHw;
QhHw->CurQtd = QTD_LINK (0, TRUE);
QhHw->AltQtd = 0;
QhHw->Status = 0;
QhHw->Pid = 0;
QhHw->ErrCnt = 0;
QhHw->CurPage = 0;
QhHw->Ioc = 0;
QhHw->TotalBytes = 0;
for (Index = 0; Index < 5; Index++) {
QhHw->Page[Index] = 0;
QhHw->PageHigh[Index] = 0;
}
QhHw->NextQtd = QTD_LINK (FirstQtd, FALSE);
}
return ;
}
/**
Remove all the asynchronous interrutp transfers.
@param Event Interrupt event.
@param Context Pointer to PEI_USB2_HC_DEV.
**/
VOID
EFIAPI
EhcMoniteAsyncRequests (
IN EFI_EVENT Event,
IN VOID *Context
)
{
PEI_USB2_HC_DEV *Ehc;
EFI_LIST_ENTRY *Entry;
EFI_LIST_ENTRY *Next;
BOOLEAN Finished;
UINT8 *ProcBuf;
PEI_URB *Urb;
EFI_STATUS Status;
UINTN PageNumber;
Ehc = (PEI_USB2_HC_DEV *) Context;
EFI_LIST_FOR_EACH_SAFE (Entry, Next, &Ehc->AsyncIntTransfers) {
Urb = EFI_LIST_CONTAINER (Entry, PEI_URB, UrbList);
//
// Check the result of URB execution. If it is still
// active, check the next one.
//
Finished = EhcCheckUrbResult (Ehc, Urb);
if (!Finished) {
continue;
}
//
// Flush any PCI posted write transactions from a PCI host
// bridge to system memory.
//
Status = EhcFlushAsyncIntMap (Ehc, Urb);
//
// Allocate a buffer then copy the transferred data for user.
// If failed to allocate the buffer, update the URB for next
// round of transfer. Ignore the data of this round.
//
ProcBuf = NULL;
if (Urb->Result == EFI_USB_NOERROR) {
ASSERT (Urb->Completed <= Urb->DataLen);
PageNumber = Urb->Completed/PAGESIZE +1;
Status = PeiServicesAllocatePages (
EfiBootServicesCode,
PageNumber,
(EFI_PHYSICAL_ADDRESS *)ProcBuf
);
if (ProcBuf == NULL) {
EhcUpdateAsyncRequest (Urb);
continue;
}
CopyMem (ProcBuf, Urb->Data, Urb->Completed);
}
EhcUpdateAsyncRequest (Urb);
//
// Leave error recovery to its related device driver. A
// common case of the error recovery is to re-submit the
// interrupt transfer which is linked to the head of the
// list. This function scans from head to tail. So the
// re-submitted interrupt transfer's callback function
// will not be called again in this round. Don't touch this
// URB after the callback, it may have been removed by the
// callback.
//
if (Urb->Callback != NULL) {
(Urb->Callback) (ProcBuf, Urb->Completed, Urb->Context, Urb->Result);
}
if (ProcBuf != NULL) {
}
}
}

View File

@ -0,0 +1,180 @@
/** @file
Private Header file for Usb Host Controller PEIM
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions
of the BSD License which accompanies this distribution. The
full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _EFI_EHCI_SCHED_H_
#define _EFI_EHCI_SCHED_H_
/**
Initialize the schedule data structure such as frame list.
@param Ehc The EHCI device to init schedule data for.
@retval EFI_OUT_OF_RESOURCES Failed to allocate resource to init schedule data.
@retval EFI_SUCCESS The schedule data is initialized.
**/
EFI_STATUS
EhcInitSched (
IN PEI_USB2_HC_DEV *Ehc
)
;
/**
Free the schedule data. It may be partially initialized.
@param Ehc The EHCI device.
**/
VOID
EhcFreeSched (
IN PEI_USB2_HC_DEV *Ehc
)
;
/**
Link the queue head to the asynchronous schedule list.
UEFI only supports one CTRL/BULK transfer at a time
due to its interfaces. This simplifies the AsynList
management: A reclamation header is always linked to
the AsyncListAddr, the only active QH is appended to it.
@param Ehc The EHCI device.
@param Qh The queue head to link.
**/
VOID
EhcLinkQhToAsync (
IN PEI_USB2_HC_DEV *Ehc,
IN PEI_EHC_QH *Qh
)
;
/**
Unlink a queue head from the asynchronous schedule list.
Need to synchronize with hardware.
@param Ehc The EHCI device.
@param Qh The queue head to unlink.
**/
VOID
EhcUnlinkQhFromAsync (
IN PEI_USB2_HC_DEV *Ehc,
IN PEI_EHC_QH *Qh
)
;
/**
Link a queue head for interrupt transfer to the periodic
schedule frame list. This code is very much the same as
that in UHCI.
@param Ehc The EHCI device.
@param Qh The queue head to link.
**/
VOID
EhcLinkQhToPeriod (
IN PEI_USB2_HC_DEV *Ehc,
IN PEI_EHC_QH *Qh
)
;
/**
Unlink an interrupt queue head from the periodic
schedule frame list.
@param Ehc The EHCI device.
@param Qh The queue head to unlink.
**/
VOID
EhcUnlinkQhFromPeriod (
IN PEI_USB2_HC_DEV *Ehc,
IN PEI_EHC_QH *Qh
)
;
/**
Execute the transfer by polling the URB. This is a synchronous operation.
@param Ehc The EHCI device.
@param Urb The URB to execute.
@param TimeOut The time to wait before abort, in millisecond.
@retval EFI_DEVICE_ERROR The transfer failed due to transfer error.
@retval EFI_TIMEOUT The transfer failed due to time out.
@retval EFI_SUCCESS The transfer finished OK.
**/
EFI_STATUS
EhcExecTransfer (
IN PEI_USB2_HC_DEV *Ehc,
IN PEI_URB *Urb,
IN UINTN TimeOut
)
;
/**
Delete a single asynchronous interrupt transfer for
the device and endpoint.
@param Ehc The EHCI device.
@param DevAddr The address of the target device.
@param EpNum The endpoint of the target.
@param DataToggle Return the next data toggle to use.
@retval EFI_NOT_FOUND No transfer for the device is found.
@retval EFI_SUCCESS An asynchronous transfer is removed.
**/
EFI_STATUS
EhciDelAsyncIntTransfer (
IN PEI_USB2_HC_DEV *Ehc,
IN UINT8 DevAddr,
IN UINT8 EpNum,
OUT UINT8 *DataToggle
)
;
/**
Remove all the asynchronous interrutp transfers.
@param Ehc The EHCI device.
**/
VOID
EhciDelAllAsyncIntTransfers (
IN PEI_USB2_HC_DEV *Ehc
)
;
/**
Remove all the asynchronous interrutp transfers.
@param Event Interrupt event.
@param Context Pointer to PEI_USB2_HC_DEV.
**/
VOID
EFIAPI
EhcMoniteAsyncRequests (
IN EFI_EVENT Event,
IN VOID *Context
)
;
#endif

View File

@ -0,0 +1,610 @@
/** @file
PEIM to produce gPeiUsb2HostControllerPpiGuid based on gPeiUsbControllerPpiGuid
which is used to enable recovery function from USB Drivers.
Copyright (c) 2010, 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 "EhcPeim.h"
/**
Delete a single asynchronous interrupt transfer for
the device and endpoint.
@param Ehc The EHCI device.
@param Data Current data not associated with a QTD.
@param DataLen The length of the data.
@param PktId Packet ID to use in the QTD.
@param Toggle Data toggle to use in the QTD.
@param MaxPacket Maximu packet length of the endpoint.
@retval the pointer to the created QTD or NULL if failed to create one.
**/
PEI_EHC_QTD *
EhcCreateQtd (
IN PEI_USB2_HC_DEV *Ehc,
IN UINT8 *Data,
IN UINTN DataLen,
IN UINT8 PktId,
IN UINT8 Toggle,
IN UINTN MaxPacket
)
{
PEI_EHC_QTD *Qtd;
QTD_HW *QtdHw;
UINTN Index;
UINTN Len;
UINTN ThisBufLen;
ASSERT (Ehc != NULL);
Qtd = UsbHcAllocateMem (Ehc, Ehc->MemPool, sizeof (PEI_EHC_QTD));
if (Qtd == NULL) {
return NULL;
}
Qtd->Signature = EHC_QTD_SIG;
Qtd->Data = Data;
Qtd->DataLen = 0;
InitializeListHead (&Qtd->QtdList);
QtdHw = &Qtd->QtdHw;
QtdHw->NextQtd = QTD_LINK (NULL, TRUE);
QtdHw->AltNext = QTD_LINK (NULL, TRUE);
QtdHw->Status = QTD_STAT_ACTIVE;
QtdHw->Pid = PktId;
QtdHw->ErrCnt = QTD_MAX_ERR;
QtdHw->Ioc = 0;
QtdHw->TotalBytes = 0;
QtdHw->DataToggle = Toggle;
//
// Fill in the buffer points
//
if (Data != NULL) {
Len = 0;
for (Index = 0; Index <= QTD_MAX_BUFFER; Index++) {
//
// Set the buffer point (Check page 41 EHCI Spec 1.0). No need to
// compute the offset and clear Reserved fields. This is already
// done in the data point.
//
QtdHw->Page[Index] = EHC_LOW_32BIT (Data);
QtdHw->PageHigh[Index] = EHC_HIGH_32BIT (Data);
ThisBufLen = QTD_BUF_LEN - (EHC_LOW_32BIT (Data) & QTD_BUF_MASK);
if (Len + ThisBufLen >= DataLen) {
Len = DataLen;
break;
}
Len += ThisBufLen;
Data += ThisBufLen;
}
//
// Need to fix the last pointer if the Qtd can't hold all the
// user's data to make sure that the length is in the unit of
// max packets. If it can hold all the data, there is no such
// need.
//
if (Len < DataLen) {
Len = Len - Len % MaxPacket;
}
QtdHw->TotalBytes = (UINT32) Len;
Qtd->DataLen = Len;
}
return Qtd;
}
/**
Initialize the queue head for interrupt transfer,
that is, initialize the following three fields:
1. SplitXState in the Status field.
2. Microframe S-mask.
3. Microframe C-mask.
@param Ep The queue head's related endpoint.
@param QhHw The queue head to initialize.
**/
VOID
EhcInitIntQh (
IN USB_ENDPOINT *Ep,
IN QH_HW *QhHw
)
{
//
// Because UEFI interface can't utilitize an endpoint with
// poll rate faster than 1ms, only need to set one bit in
// the queue head. simple. But it may be changed later. If
// sub-1ms interrupt is supported, need to update the S-Mask
// here
//
if (Ep->DevSpeed == EFI_USB_SPEED_HIGH) {
QhHw->SMask = QH_MICROFRAME_0;
return ;
}
//
// For low/full speed device, the transfer must go through
// the split transaction. Need to update three fields
// 1. SplitXState in the status
// 2. Microframe S-Mask
// 3. Microframe C-Mask
// UEFI USB doesn't exercise admission control. It simplely
// schedule the high speed transactions in microframe 0, and
// full/low speed transactions at microframe 1. This also
// avoid the use of FSTN.
//
QhHw->SMask = QH_MICROFRAME_1;
QhHw->CMask = QH_MICROFRAME_3 | QH_MICROFRAME_4 | QH_MICROFRAME_5;
}
/**
Allocate and initialize a EHCI queue head.
@param Ehci The EHCI device.
@param Ep The endpoint to create queue head for.
@retval the pointer to the created queue head or NULL if failed to create one.
**/
PEI_EHC_QH *
EhcCreateQh (
IN PEI_USB2_HC_DEV *Ehci,
IN USB_ENDPOINT *Ep
)
{
PEI_EHC_QH *Qh;
QH_HW *QhHw;
Qh = UsbHcAllocateMem (Ehci, Ehci->MemPool, sizeof (PEI_EHC_QH));
if (Qh == NULL) {
return NULL;
}
Qh->Signature = EHC_QH_SIG;
Qh->NextQh = NULL;
Qh->Interval = Ep->PollRate;
InitializeListHead (&Qh->Qtds);
QhHw = &Qh->QhHw;
QhHw->HorizonLink = QH_LINK (NULL, 0, TRUE);
QhHw->DeviceAddr = Ep->DevAddr;
QhHw->Inactive = 0;
QhHw->EpNum = Ep->EpAddr;
QhHw->EpSpeed = Ep->DevSpeed;
QhHw->DtCtrl = 0;
QhHw->ReclaimHead = 0;
QhHw->MaxPacketLen = (UINT32) Ep->MaxPacket;
QhHw->CtrlEp = 0;
QhHw->NakReload = QH_NAK_RELOAD;
QhHw->HubAddr = Ep->HubAddr;
QhHw->PortNum = Ep->HubPort;
QhHw->Multiplier = 1;
QhHw->DataToggle = Ep->Toggle;
if (Ep->DevSpeed != EFI_USB_SPEED_HIGH) {
QhHw->Status |= QTD_STAT_DO_SS;
}
switch (Ep->Type) {
case EHC_CTRL_TRANSFER:
//
// Special initialization for the control transfer:
// 1. Control transfer initialize data toggle from each QTD
// 2. Set the Control Endpoint Flag (C) for low/full speed endpoint.
//
QhHw->DtCtrl = 1;
if (Ep->DevSpeed != EFI_USB_SPEED_HIGH) {
QhHw->CtrlEp = 1;
}
break;
case EHC_INT_TRANSFER_ASYNC:
case EHC_INT_TRANSFER_SYNC:
//
// Special initialization for the interrupt transfer
// to set the S-Mask and C-Mask
//
QhHw->NakReload = 0;
EhcInitIntQh (Ep, QhHw);
break;
case EHC_BULK_TRANSFER:
if ((Ep->DevSpeed == EFI_USB_SPEED_HIGH) && (Ep->Direction == EfiUsbDataOut)) {
QhHw->Status |= QTD_STAT_DO_PING;
}
break;
}
return Qh;
}
/**
Convert the poll interval from application to that
be used by EHCI interface data structure. Only need
to get the max 2^n that is less than interval. UEFI
can't support high speed endpoint with a interval less
than 8 microframe because interval is specified in
the unit of ms (millisecond).
@param Interval The interval to convert.
@retval The converted interval.
**/
UINTN
EhcConvertPollRate (
IN UINTN Interval
)
{
UINTN BitCount;
if (Interval == 0) {
return 1;
}
//
// Find the index (1 based) of the highest non-zero bit
//
BitCount = 0;
while (Interval != 0) {
Interval >>= 1;
BitCount++;
}
return (UINTN)1 << (BitCount - 1);
}
/**
Free a list of QTDs.
@param Ehc The EHCI device.
@param Qtds The list head of the QTD.
**/
VOID
EhcFreeQtds (
IN PEI_USB2_HC_DEV *Ehc,
IN EFI_LIST_ENTRY *Qtds
)
{
EFI_LIST_ENTRY *Entry;
EFI_LIST_ENTRY *Next;
PEI_EHC_QTD *Qtd;
EFI_LIST_FOR_EACH_SAFE (Entry, Next, Qtds) {
Qtd = EFI_LIST_CONTAINER (Entry, PEI_EHC_QTD, QtdList);
RemoveEntryList (&Qtd->QtdList);
UsbHcFreeMem (Ehc->MemPool, Qtd, sizeof (PEI_EHC_QTD));
}
}
/**
Free an allocated URB. It is possible for it to be partially inited.
@param Ehc The EHCI device.
@param Urb The URB to free.
**/
VOID
EhcFreeUrb (
IN PEI_USB2_HC_DEV *Ehc,
IN PEI_URB *Urb
)
{
if (Urb->Qh != NULL) {
//
// Ensure that this queue head has been unlinked from the
// schedule data structures. Free all the associated QTDs
//
EhcFreeQtds (Ehc, &Urb->Qh->Qtds);
UsbHcFreeMem (Ehc->MemPool, Urb->Qh, sizeof (PEI_EHC_QH));
}
}
/**
Create a list of QTDs for the URB.
@param Ehc The EHCI device.
@param Urb The URB to create QTDs for.
@retval EFI_OUT_OF_RESOURCES Failed to allocate resource for QTD.
@retval EFI_SUCCESS The QTDs are allocated for the URB.
**/
EFI_STATUS
EhcCreateQtds (
IN PEI_USB2_HC_DEV *Ehc,
IN PEI_URB *Urb
)
{
USB_ENDPOINT *Ep;
PEI_EHC_QH *Qh;
PEI_EHC_QTD *Qtd;
PEI_EHC_QTD *StatusQtd;
PEI_EHC_QTD *NextQtd;
EFI_LIST_ENTRY *Entry;
UINT32 AlterNext;
UINT8 Toggle;
UINTN Len;
UINT8 Pid;
ASSERT ((Urb != NULL) && (Urb->Qh != NULL));
//
// EHCI follows the alternet next QTD pointer if it meets
// a short read and the AlterNext pointer is valid. UEFI
// EHCI driver should terminate the transfer except the
// control transfer.
//
Toggle = 0;
Qh = Urb->Qh;
Ep = &Urb->Ep;
StatusQtd = NULL;
AlterNext = QTD_LINK (NULL, TRUE);
if (Ep->Direction == EfiUsbDataIn) {
AlterNext = QTD_LINK (Ehc->ShortReadStop, FALSE);
}
//
// Build the Setup and status packets for control transfer
//
if (Urb->Ep.Type == EHC_CTRL_TRANSFER) {
Len = sizeof (EFI_USB_DEVICE_REQUEST);
Qtd = EhcCreateQtd (Ehc, Urb->RequestPhy, Len, QTD_PID_SETUP, 0, Ep->MaxPacket);
if (Qtd == NULL) {
return EFI_OUT_OF_RESOURCES;
}
InsertTailList (&Qh->Qtds, &Qtd->QtdList);
//
// Create the status packet now. Set the AlterNext to it. So, when
// EHCI meets a short control read, it can resume at the status stage.
// Use the opposite direction of the data stage, or IN if there is
// no data stage.
//
if (Ep->Direction == EfiUsbDataIn) {
Pid = QTD_PID_OUTPUT;
} else {
Pid = QTD_PID_INPUT;
}
StatusQtd = EhcCreateQtd (Ehc, NULL, 0, Pid, 1, Ep->MaxPacket);
if (StatusQtd == NULL) {
goto ON_ERROR;
}
if (Ep->Direction == EfiUsbDataIn) {
AlterNext = QTD_LINK (StatusQtd, FALSE);
}
Toggle = 1;
}
//
// Build the data packets for all the transfers
//
if (Ep->Direction == EfiUsbDataIn) {
Pid = QTD_PID_INPUT;
} else {
Pid = QTD_PID_OUTPUT;
}
Qtd = NULL;
Len = 0;
while (Len < Urb->DataLen) {
Qtd = EhcCreateQtd (
Ehc,
(UINT8 *) Urb->DataPhy + Len,
Urb->DataLen - Len,
Pid,
Toggle,
Ep->MaxPacket
);
if (Qtd == NULL) {
goto ON_ERROR;
}
Qtd->QtdHw.AltNext = AlterNext;
InsertTailList (&Qh->Qtds, &Qtd->QtdList);
//
// Switch the Toggle bit if odd number of packets are included in the QTD.
//
if (((Qtd->DataLen + Ep->MaxPacket - 1) / Ep->MaxPacket) % 2) {
Toggle = (UINT8) (1 - Toggle);
}
Len += Qtd->DataLen;
}
//
// Insert the status packet for control transfer
//
if (Ep->Type == EHC_CTRL_TRANSFER) {
InsertTailList (&Qh->Qtds, &StatusQtd->QtdList);
}
//
// OK, all the QTDs needed are created. Now, fix the NextQtd point
//
EFI_LIST_FOR_EACH (Entry, &Qh->Qtds) {
Qtd = EFI_LIST_CONTAINER (Entry, PEI_EHC_QTD, QtdList);
//
// break if it is the last entry on the list
//
if (Entry->ForwardLink == &Qh->Qtds) {
break;
}
NextQtd = EFI_LIST_CONTAINER (Entry->ForwardLink, PEI_EHC_QTD, QtdList);
Qtd->QtdHw.NextQtd = QTD_LINK (NextQtd, FALSE);
}
//
// Link the QTDs to the queue head
//
NextQtd = EFI_LIST_CONTAINER (Qh->Qtds.ForwardLink, PEI_EHC_QTD, QtdList);
Qh->QhHw.NextQtd = QTD_LINK (NextQtd, FALSE);
return EFI_SUCCESS;
ON_ERROR:
EhcFreeQtds (Ehc, &Qh->Qtds);
return EFI_OUT_OF_RESOURCES;
}
/**
Create a new URB and its associated QTD.
@param Ehc The EHCI device.
@param DevAddr The device address.
@param EpAddr Endpoint addrress & its direction.
@param DevSpeed The device speed.
@param Toggle Initial data toggle to use.
@param MaxPacket The max packet length of the endpoint.
@param Hub The transaction translator to use.
@param Type The transaction type.
@param Request The standard USB request for control transfer.
@param Data The user data to transfer.
@param DataLen The length of data buffer.
@param Callback The function to call when data is transferred.
@param Context The context to the callback.
@param Interval The interval for interrupt transfer.
@retval the pointer to the created URB or NULL.
**/
PEI_URB *
EhcCreateUrb (
IN PEI_USB2_HC_DEV *Ehc,
IN UINT8 DevAddr,
IN UINT8 EpAddr,
IN UINT8 DevSpeed,
IN UINT8 Toggle,
IN UINTN MaxPacket,
IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Hub,
IN UINTN Type,
IN EFI_USB_DEVICE_REQUEST *Request,
IN VOID *Data,
IN UINTN DataLen,
IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback,
IN VOID *Context,
IN UINTN Interval
)
{
USB_ENDPOINT *Ep;
EFI_PHYSICAL_ADDRESS PhyAddr;
EFI_STATUS Status;
UINTN Len;
PEI_URB *Urb;
VOID *Map;
Map = NULL;
Urb = Ehc->Urb;
Urb->Signature = EHC_URB_SIG;
InitializeListHead (&Urb->UrbList);
Ep = &Urb->Ep;
Ep->DevAddr = DevAddr;
Ep->EpAddr = (UINT8) (EpAddr & 0x0F);
Ep->Direction = (((EpAddr & 0x80) != 0) ? EfiUsbDataIn : EfiUsbDataOut);
Ep->DevSpeed = DevSpeed;
Ep->MaxPacket = MaxPacket;
Ep->HubAddr = 0;
Ep->HubPort = 0;
if (DevSpeed != EFI_USB_SPEED_HIGH) {
ASSERT (Hub != NULL);
Ep->HubAddr = Hub->TranslatorHubAddress;
Ep->HubPort = Hub->TranslatorPortNumber;
}
Ep->Toggle = Toggle;
Ep->Type = Type;
Ep->PollRate = EhcConvertPollRate (Interval);
Urb->Request = Request;
Urb->Data = Data;
Urb->DataLen = DataLen;
Urb->Callback = Callback;
Urb->Context = Context;
Urb->Qh = EhcCreateQh (Ehc, &Urb->Ep);
if (Urb->Qh == NULL) {
goto ON_ERROR;
}
//
// Map the request and user data
//
if (Request != NULL) {
Len = sizeof (EFI_USB_DEVICE_REQUEST);
PhyAddr = (EFI_PHYSICAL_ADDRESS) (UINTN) Request ;
if ( (Len != sizeof (EFI_USB_DEVICE_REQUEST))) {
goto ON_ERROR;
}
Urb->RequestPhy = (VOID *) ((UINTN) PhyAddr);
Urb->RequestMap = Map;
}
if (Data != NULL) {
Len = DataLen;
PhyAddr = (EFI_PHYSICAL_ADDRESS) (UINTN) Data ;
if ( (Len != DataLen)) {
goto ON_ERROR;
}
Urb->DataPhy = (VOID *) ((UINTN) PhyAddr);
Urb->DataMap = Map;
}
Status = EhcCreateQtds (Ehc, Urb);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
return Urb;
ON_ERROR:
EhcFreeUrb (Ehc, Urb);
return NULL;
}

View File

@ -0,0 +1,331 @@
/** @file
Private Header file for Usb Host Controller PEIM
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions
of the BSD License which accompanies this distribution. The
full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _EFI_EHCI_URB_H_
#define _EFI_EHCI_URB_H_
typedef struct _PEI_EHC_QTD PEI_EHC_QTD;
typedef struct _PEI_EHC_QH PEI_EHC_QH;
typedef struct _PEI_URB PEI_URB;
#define EHC_CTRL_TRANSFER 0x01
#define EHC_BULK_TRANSFER 0x02
#define EHC_INT_TRANSFER_SYNC 0x04
#define EHC_INT_TRANSFER_ASYNC 0x08
#define EHC_QTD_SIG SIGNATURE_32 ('U', 'S', 'B', 'T')
#define EHC_QH_SIG SIGNATURE_32 ('U', 'S', 'B', 'H')
#define EHC_URB_SIG SIGNATURE_32 ('U', 'S', 'B', 'R')
//
// Hardware related bit definitions
//
#define EHC_TYPE_ITD 0x00
#define EHC_TYPE_QH 0x02
#define EHC_TYPE_SITD 0x04
#define EHC_TYPE_FSTN 0x06
#define QH_NAK_RELOAD 3
#define QH_HSHBW_MULTI 1
#define QTD_MAX_ERR 3
#define QTD_PID_OUTPUT 0x00
#define QTD_PID_INPUT 0x01
#define QTD_PID_SETUP 0x02
#define QTD_STAT_DO_OUT 0
#define QTD_STAT_DO_SS 0
#define QTD_STAT_DO_PING 0x01
#define QTD_STAT_DO_CS 0x02
#define QTD_STAT_TRANS_ERR 0x08
#define QTD_STAT_BABBLE_ERR 0x10
#define QTD_STAT_BUFF_ERR 0x20
#define QTD_STAT_HALTED 0x40
#define QTD_STAT_ACTIVE 0x80
#define QTD_STAT_ERR_MASK (QTD_STAT_TRANS_ERR | QTD_STAT_BABBLE_ERR | QTD_STAT_BUFF_ERR)
#define QTD_MAX_BUFFER 4
#define QTD_BUF_LEN 4096
#define QTD_BUF_MASK 0x0FFF
#define QH_MICROFRAME_0 0x01
#define QH_MICROFRAME_1 0x02
#define QH_MICROFRAME_2 0x04
#define QH_MICROFRAME_3 0x08
#define QH_MICROFRAME_4 0x10
#define QH_MICROFRAME_5 0x20
#define QH_MICROFRAME_6 0x40
#define QH_MICROFRAME_7 0x80
#define USB_ERR_SHORT_PACKET 0x200
//
// Fill in the hardware link point: pass in a EHC_QH/QH_HW
// pointer to QH_LINK; A EHC_QTD/QTD_HW pointer to QTD_LINK
//
#define QH_LINK(Addr, Type, Term) \
((UINT32) ((EHC_LOW_32BIT (Addr) & 0xFFFFFFE0) | (Type) | ((Term) ? 1 : 0)))
#define QTD_LINK(Addr, Term) QH_LINK((Addr), 0, (Term))
//
// The defination of EHCI hardware used data structure for
// little endian architecture. The QTD and QH structures
// are required to be 32 bytes aligned. Don't add members
// to the head of the associated software strucuture.
//
#pragma pack(1)
typedef struct {
UINT32 NextQtd;
UINT32 AltNext;
UINT32 Status : 8;
UINT32 Pid : 2;
UINT32 ErrCnt : 2;
UINT32 CurPage : 3;
UINT32 Ioc : 1;
UINT32 TotalBytes : 15;
UINT32 DataToggle : 1;
UINT32 Page[5];
UINT32 PageHigh[5];
} QTD_HW;
typedef struct {
UINT32 HorizonLink;
//
// Endpoint capabilities/Characteristics DWord 1 and DWord 2
//
UINT32 DeviceAddr : 7;
UINT32 Inactive : 1;
UINT32 EpNum : 4;
UINT32 EpSpeed : 2;
UINT32 DtCtrl : 1;
UINT32 ReclaimHead : 1;
UINT32 MaxPacketLen : 11;
UINT32 CtrlEp : 1;
UINT32 NakReload : 4;
UINT32 SMask : 8;
UINT32 CMask : 8;
UINT32 HubAddr : 7;
UINT32 PortNum : 7;
UINT32 Multiplier : 2;
//
// Transaction execution overlay area
//
UINT32 CurQtd;
UINT32 NextQtd;
UINT32 AltQtd;
UINT32 Status : 8;
UINT32 Pid : 2;
UINT32 ErrCnt : 2;
UINT32 CurPage : 3;
UINT32 Ioc : 1;
UINT32 TotalBytes : 15;
UINT32 DataToggle : 1;
UINT32 Page[5];
UINT32 PageHigh[5];
} QH_HW;
#pragma pack()
//
// Endpoint address and its capabilities
//
typedef struct _USB_ENDPOINT {
UINT8 DevAddr;
UINT8 EpAddr; // Endpoint address, no direction encoded in
EFI_USB_DATA_DIRECTION Direction;
UINT8 DevSpeed;
UINTN MaxPacket;
UINT8 HubAddr;
UINT8 HubPort;
UINT8 Toggle; // Data toggle, not used for control transfer
UINTN Type;
UINTN PollRate; // Polling interval used by EHCI
} USB_ENDPOINT;
//
// Software QTD strcture, this is used to manage all the
// QTD generated from a URB. Don't add fields before QtdHw.
//
struct _PEI_EHC_QTD {
QTD_HW QtdHw;
UINT32 Signature;
EFI_LIST_ENTRY QtdList; // The list of QTDs to one end point
UINT8 *Data; // Buffer of the original data
UINTN DataLen; // Original amount of data in this QTD
};
//
// Software QH structure. All three different transaction types
// supported by UEFI USB, that is the control/bulk/interrupt
// transfers use the queue head and queue token strcuture.
//
// Interrupt QHs are linked to periodic frame list in the reversed
// 2^N tree. Each interrupt QH is linked to the list starting at
// frame 0. There is a dummy interrupt QH linked to each frame as
// a sentinental whose polling interval is 1. Synchronous interrupt
// transfer is linked after this dummy QH.
//
// For control/bulk transfer, only synchronous (in the sense of UEFI)
// transfer is supported. A dummy QH is linked to EHCI AsyncListAddr
// as the reclamation header. New transfer is inserted after this QH.
//
struct _PEI_EHC_QH {
QH_HW QhHw;
UINT32 Signature;
PEI_EHC_QH *NextQh; // The queue head pointed to by horizontal link
EFI_LIST_ENTRY Qtds; // The list of QTDs to this queue head
UINTN Interval;
};
//
// URB (Usb Request Block) contains information for all kinds of
// usb requests.
//
struct _PEI_URB {
UINT32 Signature;
EFI_LIST_ENTRY UrbList;
//
// Transaction information
//
USB_ENDPOINT Ep;
EFI_USB_DEVICE_REQUEST *Request; // Control transfer only
VOID *RequestPhy; // Address of the mapped request
VOID *RequestMap;
VOID *Data;
UINTN DataLen;
VOID *DataPhy; // Address of the mapped user data
VOID *DataMap;
EFI_ASYNC_USB_TRANSFER_CALLBACK Callback;
VOID *Context;
//
// Schedule data
//
PEI_EHC_QH *Qh;
//
// Transaction result
//
UINT32 Result;
UINTN Completed; // completed data length
UINT8 DataToggle;
};
/**
Delete a single asynchronous interrupt transfer for
the device and endpoint.
@param Ehc The EHCI device.
@param Data Current data not associated with a QTD.
@param DataLen The length of the data.
@param PktId Packet ID to use in the QTD.
@param Toggle Data toggle to use in the QTD.
@param MaxPacket Maximu packet length of the endpoint.
@retval the pointer to the created QTD or NULL if failed to create one.
**/
PEI_EHC_QTD *
EhcCreateQtd (
IN PEI_USB2_HC_DEV *Ehc,
IN UINT8 *Data,
IN UINTN DataLen,
IN UINT8 PktId,
IN UINT8 Toggle,
IN UINTN MaxPacket
)
;
/**
Allocate and initialize a EHCI queue head.
@param Ehci The EHCI device.
@param Ep The endpoint to create queue head for.
@retval the pointer to the created queue head or NULL if failed to create one.
**/
PEI_EHC_QH *
EhcCreateQh (
IN PEI_USB2_HC_DEV *Ehci,
IN USB_ENDPOINT *Ep
)
;
/**
Free an allocated URB. It is possible for it to be partially inited.
@param Ehc The EHCI device.
@param Urb The URB to free.
**/
VOID
EhcFreeUrb (
IN PEI_USB2_HC_DEV *Ehc,
IN PEI_URB *Urb
)
;
/**
Create a new URB and its associated QTD.
@param Ehc The EHCI device.
@param DevAddr The device address.
@param EpAddr Endpoint addrress & its direction.
@param DevSpeed The device speed.
@param Toggle Initial data toggle to use.
@param MaxPacket The max packet length of the endpoint.
@param Hub The transaction translator to use.
@param Type The transaction type.
@param Request The standard USB request for control transfer.
@param Data The user data to transfer.
@param DataLen The length of data buffer.
@param Callback The function to call when data is transferred.
@param Context The context to the callback.
@param Interval The interval for interrupt transfer.
@retval the pointer to the created URB or NULL.
**/
PEI_URB *
EhcCreateUrb (
IN PEI_USB2_HC_DEV *Ehc,
IN UINT8 DevAddr,
IN UINT8 EpAddr,
IN UINT8 DevSpeed,
IN UINT8 Toggle,
IN UINTN MaxPacket,
IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Hub,
IN UINTN Type,
IN EFI_USB_DEVICE_REQUEST *Request,
IN VOID *Data,
IN UINTN DataLen,
IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback,
IN VOID *Context,
IN UINTN Interval
)
;
#endif

View File

@ -0,0 +1,493 @@
/** @file
PEIM to produce gPeiUsb2HostControllerPpiGuid based on gPeiUsbControllerPpiGuid
which is used to enable recovery function from USB Drivers.
Copyright (c) 2010, 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 "EhcPeim.h"
/**
Allocate a block of memory to be used by the buffer pool.
@param Ehc The EHCI device.
@param Pool The buffer pool to allocate memory for.
@param Pages How many pages to allocate.
@return The allocated memory block or NULL if failed.
**/
USBHC_MEM_BLOCK *
UsbHcAllocMemBlock (
IN PEI_USB2_HC_DEV *Ehc,
IN USBHC_MEM_POOL *Pool,
IN UINTN Pages
)
{
USBHC_MEM_BLOCK *Block;
VOID *BufHost;
VOID *Mapping;
EFI_PHYSICAL_ADDRESS MappedAddr;
EFI_STATUS Status;
UINTN PageNumber;
EFI_PHYSICAL_ADDRESS TempPtr;
Mapping = NULL;
PageNumber = sizeof(USBHC_MEM_BLOCK)/PAGESIZE +1;
Status = PeiServicesAllocatePages (
EfiBootServicesCode,
PageNumber,
&TempPtr
);
if (EFI_ERROR (Status)) {
return NULL;
}
ZeroMem ((VOID *)(UINTN)TempPtr, PageNumber*EFI_PAGE_SIZE);
//
// each bit in the bit array represents USBHC_MEM_UNIT
// bytes of memory in the memory block.
//
ASSERT (USBHC_MEM_UNIT * 8 <= EFI_PAGE_SIZE);
Block = (USBHC_MEM_BLOCK*)(UINTN)TempPtr;
Block->BufLen = EFI_PAGES_TO_SIZE (Pages);
Block->BitsLen = Block->BufLen / (USBHC_MEM_UNIT * 8);
PageNumber = (Block->BitsLen)/PAGESIZE +1;
Status = PeiServicesAllocatePages (
EfiBootServicesCode,
PageNumber,
&TempPtr
);
if (EFI_ERROR (Status)) {
return NULL;
}
ZeroMem ((VOID *)(UINTN)TempPtr, PageNumber*EFI_PAGE_SIZE);
Block->Bits = (UINT8 *)(UINTN)TempPtr;
Status = PeiServicesAllocatePages (
EfiBootServicesCode,
Pages,
&TempPtr
);
ZeroMem ((VOID *)(UINTN)TempPtr, Pages*EFI_PAGE_SIZE);
BufHost = (VOID *)(UINTN)TempPtr;
MappedAddr = (EFI_PHYSICAL_ADDRESS) (UINTN) BufHost;
//
// Check whether the data structure used by the host controller
// should be restricted into the same 4G
//
if (Pool->Check4G && (Pool->Which4G != USB_HC_HIGH_32BIT (MappedAddr))) {
return NULL;
}
Block->BufHost = BufHost;
Block->Buf = (UINT8 *) ((UINTN) MappedAddr);
Block->Mapping = Mapping;
Block->Next = NULL;
return Block;
}
/**
Free the memory block from the memory pool.
@param Pool The memory pool to free the block from.
@param Block The memory block to free.
**/
VOID
UsbHcFreeMemBlock (
IN USBHC_MEM_POOL *Pool,
IN USBHC_MEM_BLOCK *Block
)
{
ASSERT ((Pool != NULL) && (Block != NULL));
}
/**
Alloc some memory from the block.
@param Block The memory block to allocate memory from.
@param Units Number of memory units to allocate.
@return The pointer to the allocated memory. If couldn't allocate the needed memory,
the return value is NULL.
**/
VOID *
UsbHcAllocMemFromBlock (
IN USBHC_MEM_BLOCK *Block,
IN UINTN Units
)
{
UINTN Byte;
UINT8 Bit;
UINTN StartByte;
UINT8 StartBit;
UINTN Available;
UINTN Count;
ASSERT ((Block != 0) && (Units != 0));
StartByte = 0;
StartBit = 0;
Available = 0;
for (Byte = 0, Bit = 0; Byte < Block->BitsLen;) {
//
// If current bit is zero, the corresponding memory unit is
// available, otherwise we need to restart our searching.
// Available counts the consective number of zero bit.
//
if (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit)) {
Available++;
if (Available >= Units) {
break;
}
NEXT_BIT (Byte, Bit);
} else {
NEXT_BIT (Byte, Bit);
Available = 0;
StartByte = Byte;
StartBit = Bit;
}
}
if (Available < Units) {
return NULL;
}
//
// Mark the memory as allocated
//
Byte = StartByte;
Bit = StartBit;
for (Count = 0; Count < Units; Count++) {
ASSERT (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));
Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] | (UINT8) USB_HC_BIT (Bit));
NEXT_BIT (Byte, Bit);
}
return Block->Buf + (StartByte * 8 + StartBit) * USBHC_MEM_UNIT;
}
/**
Insert the memory block to the pool's list of the blocks.
@param Head The head of the memory pool's block list.
@param Block The memory block to insert.
**/
VOID
UsbHcInsertMemBlockToPool (
IN USBHC_MEM_BLOCK *Head,
IN USBHC_MEM_BLOCK *Block
)
{
ASSERT ((Head != NULL) && (Block != NULL));
Block->Next = Head->Next;
Head->Next = Block;
}
/**
Is the memory block empty?
@param Block The memory block to check.
@retval TRUE The memory block is empty.
@retval FALSE The memory block isn't empty.
**/
BOOLEAN
UsbHcIsMemBlockEmpty (
IN USBHC_MEM_BLOCK *Block
)
{
UINTN Index;
for (Index = 0; Index < Block->BitsLen; Index++) {
if (Block->Bits[Index] != 0) {
return FALSE;
}
}
return TRUE;
}
/**
Unlink the memory block from the pool's list.
@param Head The block list head of the memory's pool.
@param BlockToUnlink The memory block to unlink.
**/
VOID
UsbHcUnlinkMemBlock (
IN USBHC_MEM_BLOCK *Head,
IN USBHC_MEM_BLOCK *BlockToUnlink
)
{
USBHC_MEM_BLOCK *Block;
ASSERT ((Head != NULL) && (BlockToUnlink != NULL));
for (Block = Head; Block != NULL; Block = Block->Next) {
if (Block->Next == BlockToUnlink) {
Block->Next = BlockToUnlink->Next;
BlockToUnlink->Next = NULL;
break;
}
}
}
/**
Initialize the memory management pool for the host controller.
@param Ehc The EHCI device.
@param Check4G Whether the host controller requires allocated memory.
from one 4G address space.
@param Which4G The 4G memory area each memory allocated should be from.
@retval EFI_SUCCESS The memory pool is initialized.
@retval EFI_OUT_OF_RESOURCE Fail to init the memory pool.
**/
USBHC_MEM_POOL *
UsbHcInitMemPool (
IN PEI_USB2_HC_DEV *Ehc,
IN BOOLEAN Check4G,
IN UINT32 Which4G
)
{
USBHC_MEM_POOL *Pool;
UINTN PageNumber;
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS TempPtr;
PageNumber = sizeof(USBHC_MEM_POOL)/PAGESIZE +1;
Status = PeiServicesAllocatePages (
EfiBootServicesCode,
PageNumber,
&TempPtr
);
if (EFI_ERROR (Status)) {
return NULL;
}
ZeroMem ((VOID *)(UINTN)TempPtr, PageNumber*EFI_PAGE_SIZE);
Pool = (USBHC_MEM_POOL *) ((UINTN) TempPtr);
Pool->Check4G = Check4G;
Pool->Which4G = Which4G;
Pool->Head = UsbHcAllocMemBlock (Ehc, Pool, USBHC_MEM_DEFAULT_PAGES);
if (Pool->Head == NULL) {
Pool = NULL;
}
return Pool;
}
/**
Release the memory management pool.
@param Pool The USB memory pool to free.
@retval EFI_DEVICE_ERROR Fail to free the memory pool.
@retval EFI_SUCCESS The memory pool is freed.
**/
EFI_STATUS
UsbHcFreeMemPool (
IN USBHC_MEM_POOL *Pool
)
{
USBHC_MEM_BLOCK *Block;
ASSERT (Pool->Head != NULL);
//
// Unlink all the memory blocks from the pool, then free them.
// UsbHcUnlinkMemBlock can't be used to unlink and free the
// first block.
//
for (Block = Pool->Head->Next; Block != NULL; Block = Pool->Head->Next) {
UsbHcFreeMemBlock (Pool, Block);
}
UsbHcFreeMemBlock (Pool, Pool->Head);
return EFI_SUCCESS;
}
/**
Allocate some memory from the host controller's memory pool
which can be used to communicate with host controller.
@param Ehc The EHCI device.
@param Pool The host controller's memory pool.
@param Size Size of the memory to allocate.
@return The allocated memory or NULL.
**/
VOID *
UsbHcAllocateMem (
IN PEI_USB2_HC_DEV *Ehc,
IN USBHC_MEM_POOL *Pool,
IN UINTN Size
)
{
USBHC_MEM_BLOCK *Head;
USBHC_MEM_BLOCK *Block;
USBHC_MEM_BLOCK *NewBlock;
VOID *Mem;
UINTN AllocSize;
UINTN Pages;
Mem = NULL;
AllocSize = USBHC_MEM_ROUND (Size);
Head = Pool->Head;
ASSERT (Head != NULL);
//
// First check whether current memory blocks can satisfy the allocation.
//
for (Block = Head; Block != NULL; Block = Block->Next) {
Mem = UsbHcAllocMemFromBlock (Block, AllocSize / USBHC_MEM_UNIT);
if (Mem != NULL) {
ZeroMem (Mem, Size);
break;
}
}
if (Mem != NULL) {
return Mem;
}
//
// Create a new memory block if there is not enough memory
// in the pool. If the allocation size is larger than the
// default page number, just allocate a large enough memory
// block. Otherwise allocate default pages.
//
if (AllocSize > EFI_PAGES_TO_SIZE (USBHC_MEM_DEFAULT_PAGES)) {
Pages = EFI_SIZE_TO_PAGES (AllocSize) + 1;
} else {
Pages = USBHC_MEM_DEFAULT_PAGES;
}
NewBlock = UsbHcAllocMemBlock (Ehc,Pool, Pages);
if (NewBlock == NULL) {
return NULL;
}
//
// Add the new memory block to the pool, then allocate memory from it
//
UsbHcInsertMemBlockToPool (Head, NewBlock);
Mem = UsbHcAllocMemFromBlock (NewBlock, AllocSize / USBHC_MEM_UNIT);
if (Mem != NULL) {
ZeroMem (Mem, Size);
}
return Mem;
}
/**
Free the allocated memory back to the memory pool.
@param Pool The memory pool of the host controller.
@param Mem The memory to free.
@param Size The size of the memory to free.
**/
VOID
UsbHcFreeMem (
IN USBHC_MEM_POOL *Pool,
IN VOID *Mem,
IN UINTN Size
)
{
USBHC_MEM_BLOCK *Head;
USBHC_MEM_BLOCK *Block;
UINT8 *ToFree;
UINTN AllocSize;
UINTN Byte;
UINTN Bit;
UINTN Count;
Head = Pool->Head;
AllocSize = USBHC_MEM_ROUND (Size);
ToFree = (UINT8 *) Mem;
for (Block = Head; Block != NULL; Block = Block->Next) {
//
// scan the memory block list for the memory block that
// completely contains the memory to free.
//
if ((Block->Buf <= ToFree) && ((ToFree + AllocSize) <= (Block->Buf + Block->BufLen))) {
//
// compute the start byte and bit in the bit array
//
Byte = ((ToFree - Block->Buf) / USBHC_MEM_UNIT) / 8;
Bit = ((ToFree - Block->Buf) / USBHC_MEM_UNIT) % 8;
//
// reset associated bits in bit arry
//
for (Count = 0; Count < (AllocSize / USBHC_MEM_UNIT); Count++) {
ASSERT (USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));
Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] ^ USB_HC_BIT (Bit));
NEXT_BIT (Byte, Bit);
}
break;
}
}
//
// If Block == NULL, it means that the current memory isn't
// in the host controller's pool. This is critical because
// the caller has passed in a wrong memory point
//
ASSERT (Block != NULL);
//
// Release the current memory block if it is empty and not the head
//
if ((Block != Head) && UsbHcIsMemBlockEmpty (Block)) {
UsbHcFreeMemBlock (Pool, Block);
}
return ;
}

View File

@ -0,0 +1,77 @@
/** @file
Private Header file for Usb Host Controller PEIM
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions
of the BSD License which accompanies this distribution. The
full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _EFI_EHCI_MEM_H_
#define _EFI_EHCI_MEM_H_
#include <Uefi.h>
#include <IndustryStandard/Pci22.h>
#define USB_HC_BIT(a) ((UINTN)(1 << (a)))
#define USB_HC_BIT_IS_SET(Data, Bit) \
((BOOLEAN)(((Data) & USB_HC_BIT(Bit)) == USB_HC_BIT(Bit)))
#define USB_HC_HIGH_32BIT(Addr64) \
((UINT32)(RShiftU64((UINTN)(Addr64), 32) & 0XFFFFFFFF))
typedef struct _USBHC_MEM_BLOCK USBHC_MEM_BLOCK;
struct _USBHC_MEM_BLOCK {
UINT8 *Bits; // Bit array to record which unit is allocated
UINTN BitsLen;
UINT8 *Buf;
UINT8 *BufHost;
UINTN BufLen; // Memory size in bytes
VOID *Mapping;
USBHC_MEM_BLOCK *Next;
};
//
// USBHC_MEM_POOL is used to manage the memory used by USB
// host controller. EHCI requires the control memory and transfer
// data to be on the same 4G memory.
//
typedef struct _USBHC_MEM_POOL {
BOOLEAN Check4G;
UINT32 Which4G;
USBHC_MEM_BLOCK *Head;
} USBHC_MEM_POOL;
//
// Memory allocation unit, must be 2^n, n>4
//
#define USBHC_MEM_UNIT 64
#define USBHC_MEM_UNIT_MASK (USBHC_MEM_UNIT - 1)
#define USBHC_MEM_DEFAULT_PAGES 16
#define USBHC_MEM_ROUND(Len) (((Len) + USBHC_MEM_UNIT_MASK) & (~USBHC_MEM_UNIT_MASK))
//
// Advance the byte and bit to the next bit, adjust byte accordingly.
//
#define NEXT_BIT(Byte, Bit) \
do { \
(Bit)++; \
if ((Bit) > 7) { \
(Byte)++; \
(Bit) = 0; \
} \
} while (0)
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,62 @@
## @file
# Component description file for UhcPeim PEIM to produce gPeiUsbHostControllerPpiGuid based on gPeiUsbControllerPpiGuid
# which is used to enable recovery function from USB Drivers.
#
# Usb Host Controller PEIM to support recovery from USB device.
# Copyright (c) 2006 - 2010, 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 = UhciPei
FILE_GUID = C463CEAC-FC57-4f36-88B7-356C750C3BCA
MODULE_TYPE = PEIM
VERSION_STRING = 1.0
ENTRY_POINT = UhcPeimEntry
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources]
UhcPeim.c
UhcPeim.h
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
IoLib
TimerLib
BaseMemoryLib
PeiServicesLib
PeimEntryPoint
DebugLib
[Ppis]
gPeiUsbHostControllerPpiGuid # PPI ALWAYS_PRODUCED
gPeiUsbControllerPpiGuid # PPI ALWAYS_CONSUMED
[Depex]
gEfiPeiMemoryDiscoveredPpiGuid AND gPeiUsbControllerPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid

View File

@ -0,0 +1,401 @@
/** @file
BOT Transportation implementation.
Copyright (c) 2006, 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 "UsbBotPeim.h"
#include "BotPeim.h"
#include "PeiUsbLib.h"
/**
Reset the given usb device.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param PeiBotDev The instance to PEI_BOT_DEVICE.
@retval EFI_INVALID_PARAMETER Can not get usb io ppi.
@retval EFI_SUCCESS Failed to reset the given usb device.
**/
EFI_STATUS
BotRecoveryReset (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_BOT_DEVICE *PeiBotDev
)
{
EFI_USB_DEVICE_REQUEST DevReq;
UINT32 Timeout;
PEI_USB_IO_PPI *UsbIoPpi;
UINT8 EndpointAddr;
EFI_STATUS Status;
UsbIoPpi = PeiBotDev->UsbIoPpi;
if (UsbIoPpi == NULL) {
return EFI_INVALID_PARAMETER;
}
ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
DevReq.RequestType = 0x21;
DevReq.Request = 0xFF;
DevReq.Value = 0;
DevReq.Index = 0;
DevReq.Length = 0;
Timeout = 3000;
Status = UsbIoPpi->UsbControlTransfer (
PeiServices,
UsbIoPpi,
&DevReq,
EfiUsbNoData,
Timeout,
NULL,
0
);
//
// clear bulk in endpoint stall feature
//
EndpointAddr = (PeiBotDev->BulkInEndpoint)->EndpointAddress;
PeiUsbClearEndpointHalt (PeiServices, UsbIoPpi, EndpointAddr);
//
// clear bulk out endpoint stall feature
//
EndpointAddr = (PeiBotDev->BulkOutEndpoint)->EndpointAddress;
PeiUsbClearEndpointHalt (PeiServices, UsbIoPpi, EndpointAddr);
return Status;
}
/**
Send the command to the device using Bulk-Out endpoint.
This function sends the command to the device using Bulk-Out endpoint.
BOT transfer is composed of three phases: Command, Data, and Status.
This is the Command phase.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param PeiBotDev The instance to PEI_BOT_DEVICE.
@param Command The command to transfer to device.
@param CommandSize The length of the command.
@param DataTransferLength The expected length of the data.
@param Direction The direction of the data.
@param Timeout Indicates the maximum time, in millisecond, which the
transfer is allowed to complete.
@retval EFI_DEVICE_ERROR Successful to send the command to device.
@retval EFI_SUCCESS Failed to send the command to device.
**/
EFI_STATUS
BotCommandPhase (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_BOT_DEVICE *PeiBotDev,
IN VOID *Command,
IN UINT8 CommandSize,
IN UINT32 DataTransferLength,
IN EFI_USB_DATA_DIRECTION Direction,
IN UINT16 Timeout
)
{
CBW Cbw;
EFI_STATUS Status;
PEI_USB_IO_PPI *UsbIoPpi;
UINTN DataSize;
UsbIoPpi = PeiBotDev->UsbIoPpi;
ZeroMem (&Cbw, sizeof (CBW));
//
// Fill the command block, detailed see BOT spec
//
Cbw.Signature = CBWSIG;
Cbw.Tag = 0x01;
Cbw.DataTransferLength = DataTransferLength;
Cbw.Flags = (UINT8) ((Direction == EfiUsbDataIn) ? 0x80 : 0);
Cbw.Lun = 0;
Cbw.CmdLen = CommandSize;
CopyMem (Cbw.CmdBlock, Command, CommandSize);
DataSize = sizeof (CBW);
Status = UsbIoPpi->UsbBulkTransfer (
PeiServices,
UsbIoPpi,
(PeiBotDev->BulkOutEndpoint)->EndpointAddress,
(UINT8 *) &Cbw,
&DataSize,
Timeout
);
if (EFI_ERROR (Status)) {
//
// Command phase fail, we need to recovery reset this device
//
BotRecoveryReset (PeiServices, PeiBotDev);
return EFI_DEVICE_ERROR;
}
return EFI_SUCCESS;
}
/**
Transfer the data between the device and host.
This function transfers the data between the device and host.
BOT transfer is composed of three phases: Command, Data, and Status.
This is the Data phase.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param PeiBotDev The instance to PEI_BOT_DEVICE.
@param DataSize The length of the data.
@param DataBuffer The pointer to the data.
@param Direction The direction of the data.
@param Timeout Indicates the maximum time, in millisecond, which the
transfer is allowed to complete.
@retval EFI_DEVICE_ERROR Successful to send the data to device.
@retval EFI_SUCCESS Failed to send the data to device.
**/
EFI_STATUS
BotDataPhase (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_BOT_DEVICE *PeiBotDev,
IN UINT32 *DataSize,
IN OUT VOID *DataBuffer,
IN EFI_USB_DATA_DIRECTION Direction,
IN UINT16 Timeout
)
{
EFI_STATUS Status;
PEI_USB_IO_PPI *UsbIoPpi;
UINT8 EndpointAddr;
UINTN Remain;
UINTN Increment;
UINT32 MaxPacketLen;
UINT8 *BufferPtr;
UINTN TransferredSize;
UsbIoPpi = PeiBotDev->UsbIoPpi;
Remain = *DataSize;
BufferPtr = (UINT8 *) DataBuffer;
TransferredSize = 0;
//
// retrieve the the max packet length of the given endpoint
//
if (Direction == EfiUsbDataIn) {
MaxPacketLen = (PeiBotDev->BulkInEndpoint)->MaxPacketSize;
EndpointAddr = (PeiBotDev->BulkInEndpoint)->EndpointAddress;
} else {
MaxPacketLen = (PeiBotDev->BulkOutEndpoint)->MaxPacketSize;
EndpointAddr = (PeiBotDev->BulkOutEndpoint)->EndpointAddress;
}
while (Remain > 0) {
//
// Using 15 packets to avoid Bitstuff error
//
if (Remain > 16 * MaxPacketLen) {
Increment = 16 * MaxPacketLen;
} else {
Increment = Remain;
}
Status = UsbIoPpi->UsbBulkTransfer (
PeiServices,
UsbIoPpi,
EndpointAddr,
BufferPtr,
&Increment,
Timeout
);
TransferredSize += Increment;
if (EFI_ERROR (Status)) {
PeiUsbClearEndpointHalt (PeiServices, UsbIoPpi, EndpointAddr);
return Status;
}
BufferPtr += Increment;
Remain -= Increment;
}
*DataSize = (UINT32) TransferredSize;
return EFI_SUCCESS;
}
/**
Get the command execution status from device.
This function gets the command execution status from device.
BOT transfer is composed of three phases: Command, Data, and Status.
This is the Status phase.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param PeiBotDev The instance to PEI_BOT_DEVICE.
@param TransferStatus The status of the transaction.
@param Timeout Indicates the maximum time, in millisecond, which the
transfer is allowed to complete.
@retval EFI_DEVICE_ERROR Successful to get the status of device.
@retval EFI_SUCCESS Failed to get the status of device.
**/
EFI_STATUS
BotStatusPhase (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_BOT_DEVICE *PeiBotDev,
OUT UINT8 *TransferStatus,
IN UINT16 Timeout
)
{
CSW Csw;
EFI_STATUS Status;
PEI_USB_IO_PPI *UsbIoPpi;
UINT8 EndpointAddr;
UINTN DataSize;
UsbIoPpi = PeiBotDev->UsbIoPpi;
ZeroMem (&Csw, sizeof (CSW));
EndpointAddr = (PeiBotDev->BulkInEndpoint)->EndpointAddress;
DataSize = sizeof (CSW);
//
// Get the status field from bulk transfer
//
Status = UsbIoPpi->UsbBulkTransfer (
PeiServices,
UsbIoPpi,
EndpointAddr,
&Csw,
&DataSize,
Timeout
);
if (EFI_ERROR (Status)) {
return Status;
}
if (Csw.Signature == CSWSIG) {
*TransferStatus = Csw.Status;
} else {
return EFI_DEVICE_ERROR;
}
return EFI_SUCCESS;
}
/**
Send ATAPI command using BOT protocol.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param PeiBotDev The instance to PEI_BOT_DEVICE.
@param Command The command to be sent to ATAPI device.
@param CommandSize The length of the data to be sent.
@param DataBuffer The pointer to the data.
@param BufferLength The length of the data.
@param Direction The direction of the data.
@param TimeOutInMilliSeconds Indicates the maximum time, in millisecond, which the
transfer is allowed to complete.
@retval EFI_DEVICE_ERROR Successful to get the status of device.
@retval EFI_SUCCESS Failed to get the status of device.
**/
EFI_STATUS
PeiAtapiCommand (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_BOT_DEVICE *PeiBotDev,
IN VOID *Command,
IN UINT8 CommandSize,
IN VOID *DataBuffer,
IN UINT32 BufferLength,
IN EFI_USB_DATA_DIRECTION Direction,
IN UINT16 TimeOutInMilliSeconds
)
{
EFI_STATUS Status;
EFI_STATUS BotDataStatus;
UINT8 TransferStatus;
UINT32 BufferSize;
BotDataStatus = EFI_SUCCESS;
//
// First send ATAPI command through Bot
//
Status = BotCommandPhase (
PeiServices,
PeiBotDev,
Command,
CommandSize,
BufferLength,
Direction,
TimeOutInMilliSeconds
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
//
// Send/Get Data if there is a Data Stage
//
switch (Direction) {
case EfiUsbDataIn:
case EfiUsbDataOut:
BufferSize = BufferLength;
BotDataStatus = BotDataPhase (
PeiServices,
PeiBotDev,
&BufferSize,
DataBuffer,
Direction,
TimeOutInMilliSeconds
);
break;
case EfiUsbNoData:
break;
}
//
// Status Phase
//
Status = BotStatusPhase (
PeiServices,
PeiBotDev,
&TransferStatus,
TimeOutInMilliSeconds
);
if (EFI_ERROR (Status)) {
BotRecoveryReset (PeiServices, PeiBotDev);
return EFI_DEVICE_ERROR;
}
if (TransferStatus == 0x01) {
return EFI_DEVICE_ERROR;
}
return BotDataStatus;
}

View File

@ -0,0 +1,224 @@
/** @file
BOT Transportation implementation.
Copyright (c) 2006, 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 _PEI_BOT_PEIM_H_
#define _PEI_BOT_PEIM_H_
#include <PiPei.h>
#include <Ppi/UsbIo.h>
#include <Ppi/UsbHostController.h>
#include <Ppi/BlockIo.h>
//#include <Library/DebugLib.h>
#include <Library/PeimEntryPoint.h>
#include <Library/PeiServicesLib.h>
#include <Library/BaseMemoryLib.h>
#include <IndustryStandard/Atapi.h>
#pragma pack(1)
//
// Bulk Only device protocol
//
typedef struct {
UINT32 Signature;
UINT32 Tag;
UINT32 DataTransferLength;
UINT8 Flags;
UINT8 Lun;
UINT8 CmdLen;
UINT8 CmdBlock[16];
} CBW;
typedef struct {
UINT32 Signature;
UINT32 Tag;
UINT32 DataResidue;
UINT8 Status;
} CSW;
#pragma pack()
//
// Status code, see Usb Bot device spec
//
#define CSWSIG 0x53425355
#define CBWSIG 0x43425355
/**
Sends out ATAPI Inquiry Packet Command to the specified device. This command will
return INQUIRY data of the device.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
@retval EFI_SUCCESS Inquiry command completes successfully.
@retval EFI_DEVICE_ERROR Inquiry command failed.
**/
EFI_STATUS
PeiUsbInquiry (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_BOT_DEVICE *PeiBotDevice
);
/**
Sends out ATAPI Test Unit Ready Packet Command to the specified device
to find out whether device is accessible.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
@retval EFI_SUCCESS TestUnit command executed successfully.
@retval EFI_DEVICE_ERROR Device cannot be executed TestUnit command successfully.
**/
EFI_STATUS
PeiUsbTestUnitReady (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_BOT_DEVICE *PeiBotDevice
);
/**
Sends out ATAPI Request Sense Packet Command to the specified device.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
@param SenseCounts Length of sense buffer.
@param SenseKeyBuffer Pointer to sense buffer.
@retval EFI_SUCCESS Command executed successfully.
@retval EFI_DEVICE_ERROR Some device errors happen.
**/
EFI_STATUS
PeiUsbRequestSense (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_BOT_DEVICE *PeiBotDevice,
OUT UINTN *SenseCounts,
IN UINT8 *SenseKeyBuffer
);
/**
Sends out ATAPI Read Capacity Packet Command to the specified device.
This command will return the information regarding the capacity of the
media in the device.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
@retval EFI_SUCCESS Command executed successfully.
@retval EFI_DEVICE_ERROR Some device errors happen.
**/
EFI_STATUS
PeiUsbReadCapacity (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_BOT_DEVICE *PeiBotDevice
);
/**
Sends out ATAPI Read Format Capacity Data Command to the specified device.
This command will return the information regarding the capacity of the
media in the device.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
@retval EFI_SUCCESS Command executed successfully.
@retval EFI_DEVICE_ERROR Some device errors happen.
**/
EFI_STATUS
PeiUsbReadFormattedCapacity (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_BOT_DEVICE *PeiBotDevice
);
/**
Execute Read(10) ATAPI command on a specific SCSI target.
Executes the ATAPI Read(10) command on the ATAPI target specified by PeiBotDevice.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
@param Buffer The pointer to data buffer.
@param Lba The start logic block address of reading.
@param NumberOfBlocks The block number of reading.
@retval EFI_SUCCESS Command executed successfully.
@retval EFI_DEVICE_ERROR Some device errors happen.
**/
EFI_STATUS
PeiUsbRead10 (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_BOT_DEVICE *PeiBotDevice,
IN VOID *Buffer,
IN EFI_PEI_LBA Lba,
IN UINTN NumberOfBlocks
);
/**
Check if there is media according to sense data.
@param SenseData Pointer to sense data.
@param SenseCounts Count of sense data.
@retval TRUE No media
@retval FALSE Media exists
**/
BOOLEAN
IsNoMedia (
IN ATAPI_REQUEST_SENSE_DATA *SenseData,
IN UINTN SenseCounts
);
/**
Check if there is media error according to sense data.
@param SenseData Pointer to sense data.
@param SenseCounts Count of sense data.
@retval TRUE Media error
@retval FALSE No media error
**/
BOOLEAN
IsMediaError (
IN ATAPI_REQUEST_SENSE_DATA *SenseData,
IN UINTN SenseCounts
);
/**
Check if media is changed according to sense data.
@param SenseData Pointer to sense data.
@param SenseCounts Count of sense data.
@retval TRUE There is media change event.
@retval FALSE media is NOT changed.
**/
BOOLEAN
IsMediaChange (
IN ATAPI_REQUEST_SENSE_DATA *SenseData,
IN UINTN SenseCounts
);
#endif

View File

@ -0,0 +1,630 @@
/** @file
Pei USB ATATPI command implementations.
Copyright (c) 1999 - 2010, 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 "UsbBotPeim.h"
#include "BotPeim.h"
#define MAXSENSEKEY 5
/**
Sends out ATAPI Inquiry Packet Command to the specified device. This command will
return INQUIRY data of the device.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
@retval EFI_SUCCESS Inquiry command completes successfully.
@retval EFI_DEVICE_ERROR Inquiry command failed.
**/
EFI_STATUS
PeiUsbInquiry (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_BOT_DEVICE *PeiBotDevice
)
{
ATAPI_PACKET_COMMAND Packet;
EFI_STATUS Status;
ATAPI_INQUIRY_DATA Idata;
//
// fill command packet
//
ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
ZeroMem (&Idata, sizeof (ATAPI_INQUIRY_DATA));
Packet.Inquiry.opcode = ATA_CMD_INQUIRY;
Packet.Inquiry.page_code = 0;
Packet.Inquiry.allocation_length = 36;
//
// Send scsi INQUIRY command packet.
// According to SCSI Primary Commands-2 spec, host only needs to
// retrieve the first 36 bytes for standard INQUIRY data.
//
Status = PeiAtapiCommand (
PeiServices,
PeiBotDevice,
&Packet,
(UINT8) sizeof (ATAPI_PACKET_COMMAND),
&Idata,
36,
EfiUsbDataIn,
2000
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
if ((Idata.peripheral_type & 0x1f) == 0x05) {
PeiBotDevice->DeviceType = USBCDROM;
PeiBotDevice->Media.BlockSize = 0x800;
} else {
PeiBotDevice->DeviceType = USBFLOPPY;
PeiBotDevice->Media.BlockSize = 0x200;
}
return EFI_SUCCESS;
}
/**
Sends out ATAPI Test Unit Ready Packet Command to the specified device
to find out whether device is accessible.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
@retval EFI_SUCCESS TestUnit command executed successfully.
@retval EFI_DEVICE_ERROR Device cannot be executed TestUnit command successfully.
**/
EFI_STATUS
PeiUsbTestUnitReady (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_BOT_DEVICE *PeiBotDevice
)
{
ATAPI_PACKET_COMMAND Packet;
EFI_STATUS Status;
//
// fill command packet
//
ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
Packet.TestUnitReady.opcode = ATA_CMD_TEST_UNIT_READY;
//
// send command packet
//
Status = PeiAtapiCommand (
PeiServices,
PeiBotDevice,
&Packet,
(UINT8) sizeof (ATAPI_PACKET_COMMAND),
NULL,
0,
EfiUsbNoData,
2000
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
return EFI_SUCCESS;
}
/**
Sends out ATAPI Request Sense Packet Command to the specified device.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
@param SenseCounts Length of sense buffer.
@param SenseKeyBuffer Pointer to sense buffer.
@retval EFI_SUCCESS Command executed successfully.
@retval EFI_DEVICE_ERROR Some device errors happen.
**/
EFI_STATUS
PeiUsbRequestSense (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_BOT_DEVICE *PeiBotDevice,
OUT UINTN *SenseCounts,
IN UINT8 *SenseKeyBuffer
)
{
EFI_STATUS Status;
ATAPI_PACKET_COMMAND Packet;
UINT8 *Ptr;
BOOLEAN SenseReq;
ATAPI_REQUEST_SENSE_DATA *Sense;
*SenseCounts = 0;
//
// fill command packet for Request Sense Packet Command
//
ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
Packet.RequestSence.opcode = ATA_CMD_REQUEST_SENSE;
Packet.RequestSence.allocation_length = (UINT8) sizeof (ATAPI_REQUEST_SENSE_DATA);
Ptr = SenseKeyBuffer;
SenseReq = TRUE;
//
// request sense data from device continuously
// until no sense data exists in the device.
//
while (SenseReq) {
Sense = (ATAPI_REQUEST_SENSE_DATA *) Ptr;
//
// send out Request Sense Packet Command and get one Sense
// data form device.
//
Status = PeiAtapiCommand (
PeiServices,
PeiBotDevice,
&Packet,
(UINT8) sizeof (ATAPI_PACKET_COMMAND),
(VOID *) Ptr,
sizeof (ATAPI_REQUEST_SENSE_DATA),
EfiUsbDataIn,
2000
);
//
// failed to get Sense data
//
if (EFI_ERROR (Status)) {
if (*SenseCounts == 0) {
return EFI_DEVICE_ERROR;
} else {
return EFI_SUCCESS;
}
}
if (Sense->sense_key != ATA_SK_NO_SENSE) {
Ptr += sizeof (ATAPI_REQUEST_SENSE_DATA);
//
// Ptr is byte based pointer
//
(*SenseCounts)++;
if (*SenseCounts == MAXSENSEKEY) {
break;
}
} else {
//
// when no sense key, skip out the loop
//
SenseReq = FALSE;
}
}
return EFI_SUCCESS;
}
/**
Sends out ATAPI Read Capacity Packet Command to the specified device.
This command will return the information regarding the capacity of the
media in the device.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
@retval EFI_SUCCESS Command executed successfully.
@retval EFI_DEVICE_ERROR Some device errors happen.
**/
EFI_STATUS
PeiUsbReadCapacity (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_BOT_DEVICE *PeiBotDevice
)
{
EFI_STATUS Status;
ATAPI_PACKET_COMMAND Packet;
ATAPI_READ_CAPACITY_DATA Data;
ZeroMem (&Data, sizeof (ATAPI_READ_CAPACITY_DATA));
ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
Packet.Inquiry.opcode = ATA_CMD_READ_CAPACITY;
//
// send command packet
//
Status = PeiAtapiCommand (
PeiServices,
PeiBotDevice,
&Packet,
(UINT8) sizeof (ATAPI_PACKET_COMMAND),
(VOID *) &Data,
sizeof (ATAPI_READ_CAPACITY_DATA),
EfiUsbDataIn,
2000
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
PeiBotDevice->Media.LastBlock = (Data.LastLba3 << 24) | (Data.LastLba2 << 16) | (Data.LastLba1 << 8) | Data.LastLba0;
PeiBotDevice->Media.MediaPresent = TRUE;
return EFI_SUCCESS;
}
/**
Sends out ATAPI Read Format Capacity Data Command to the specified device.
This command will return the information regarding the capacity of the
media in the device.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
@retval EFI_SUCCESS Command executed successfully.
@retval EFI_DEVICE_ERROR Some device errors happen.
**/
EFI_STATUS
PeiUsbReadFormattedCapacity (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_BOT_DEVICE *PeiBotDevice
)
{
EFI_STATUS Status;
ATAPI_PACKET_COMMAND Packet;
ATAPI_READ_FORMAT_CAPACITY_DATA FormatData;
ZeroMem (&FormatData, sizeof (ATAPI_READ_FORMAT_CAPACITY_DATA));
ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
Packet.ReadFormatCapacity.opcode = ATA_CMD_READ_FORMAT_CAPACITY;
Packet.ReadFormatCapacity.allocation_length_lo = 12;
//
// send command packet
//
Status = PeiAtapiCommand (
PeiServices,
PeiBotDevice,
&Packet,
(UINT8) sizeof (ATAPI_PACKET_COMMAND),
(VOID *) &FormatData,
sizeof (ATAPI_READ_FORMAT_CAPACITY_DATA),
EfiUsbDataIn,
2000
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
if (FormatData.DesCode == 3) {
//
// Media is not present
//
PeiBotDevice->Media.MediaPresent = FALSE;
PeiBotDevice->Media.LastBlock = 0;
} else {
PeiBotDevice->Media.LastBlock = (FormatData.LastLba3 << 24) | (FormatData.LastLba2 << 16) | (FormatData.LastLba1 << 8) | FormatData.LastLba0;
PeiBotDevice->Media.LastBlock--;
PeiBotDevice->Media.MediaPresent = TRUE;
}
return EFI_SUCCESS;
}
/**
Execute Read(10) ATAPI command on a specific SCSI target.
Executes the ATAPI Read(10) command on the ATAPI target specified by PeiBotDevice.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
@param Buffer The pointer to data buffer.
@param Lba The start logic block address of reading.
@param NumberOfBlocks The block number of reading.
@retval EFI_SUCCESS Command executed successfully.
@retval EFI_DEVICE_ERROR Some device errors happen.
**/
EFI_STATUS
PeiUsbRead10 (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_BOT_DEVICE *PeiBotDevice,
IN VOID *Buffer,
IN EFI_PEI_LBA Lba,
IN UINTN NumberOfBlocks
)
{
ATAPI_PACKET_COMMAND Packet;
ATAPI_READ10_CMD *Read10Packet;
UINT16 MaxBlock;
UINT16 BlocksRemaining;
UINT16 SectorCount;
UINT32 Lba32;
UINT32 BlockSize;
UINT32 ByteCount;
VOID *PtrBuffer;
EFI_STATUS Status;
UINT16 TimeOut;
//
// prepare command packet for the Inquiry Packet Command.
//
ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
Read10Packet = &Packet.Read10;
Lba32 = (UINT32) Lba;
PtrBuffer = Buffer;
BlockSize = (UINT32) PeiBotDevice->Media.BlockSize;
MaxBlock = (UINT16) (65535 / BlockSize);
BlocksRemaining = (UINT16) NumberOfBlocks;
Status = EFI_SUCCESS;
while (BlocksRemaining > 0) {
if (BlocksRemaining <= MaxBlock) {
SectorCount = BlocksRemaining;
} else {
SectorCount = MaxBlock;
}
//
// fill the Packet data structure
//
Read10Packet->opcode = ATA_CMD_READ_10;
//
// Lba0 ~ Lba3 specify the start logical block address of the data transfer.
// Lba0 is MSB, Lba3 is LSB
//
Read10Packet->Lba3 = (UINT8) (Lba32 & 0xff);
Read10Packet->Lba2 = (UINT8) (Lba32 >> 8);
Read10Packet->Lba1 = (UINT8) (Lba32 >> 16);
Read10Packet->Lba0 = (UINT8) (Lba32 >> 24);
//
// TranLen0 ~ TranLen1 specify the transfer length in block unit.
// TranLen0 is MSB, TranLen is LSB
//
Read10Packet->TranLen1 = (UINT8) (SectorCount & 0xff);
Read10Packet->TranLen0 = (UINT8) (SectorCount >> 8);
ByteCount = SectorCount * BlockSize;
TimeOut = (UINT16) (SectorCount * 2000);
//
// send command packet
//
Status = PeiAtapiCommand (
PeiServices,
PeiBotDevice,
&Packet,
(UINT8) sizeof (ATAPI_PACKET_COMMAND),
(VOID *) PtrBuffer,
ByteCount,
EfiUsbDataIn,
TimeOut
);
if (Status != EFI_SUCCESS) {
return Status;
}
Lba32 += SectorCount;
PtrBuffer = (UINT8 *) PtrBuffer + SectorCount * BlockSize;
BlocksRemaining = (UINT16) (BlocksRemaining - SectorCount);
}
return Status;
}
/**
Check if there is media according to sense data.
@param SenseData Pointer to sense data.
@param SenseCounts Count of sense data.
@retval TRUE No media
@retval FALSE Media exists
**/
BOOLEAN
IsNoMedia (
IN ATAPI_REQUEST_SENSE_DATA *SenseData,
IN UINTN SenseCounts
)
{
ATAPI_REQUEST_SENSE_DATA *SensePtr;
UINTN Index;
BOOLEAN NoMedia;
NoMedia = FALSE;
SensePtr = SenseData;
for (Index = 0; Index < SenseCounts; Index++) {
switch (SensePtr->sense_key) {
case ATA_SK_NOT_READY:
switch (SensePtr->addnl_sense_code) {
//
// if no media, fill IdeDev parameter with specific info.
//
case ATA_ASC_NO_MEDIA:
NoMedia = TRUE;
break;
default:
break;
}
break;
default:
break;
}
SensePtr++;
}
return NoMedia;
}
/**
Check if there is media error according to sense data.
@param SenseData Pointer to sense data.
@param SenseCounts Count of sense data.
@retval TRUE Media error
@retval FALSE No media error
**/
BOOLEAN
IsMediaError (
IN ATAPI_REQUEST_SENSE_DATA *SenseData,
IN UINTN SenseCounts
)
{
ATAPI_REQUEST_SENSE_DATA *SensePtr;
UINTN Index;
BOOLEAN Error;
SensePtr = SenseData;
Error = FALSE;
for (Index = 0; Index < SenseCounts; Index++) {
switch (SensePtr->sense_key) {
//
// Medium error case
//
case ATA_SK_MEDIUM_ERROR:
switch (SensePtr->addnl_sense_code) {
case ATA_ASC_MEDIA_ERR1:
//
// fall through
//
case ATA_ASC_MEDIA_ERR2:
//
// fall through
//
case ATA_ASC_MEDIA_ERR3:
//
// fall through
//
case ATA_ASC_MEDIA_ERR4:
Error = TRUE;
break;
default:
break;
}
break;
//
// Medium upside-down case
//
case ATA_SK_NOT_READY:
switch (SensePtr->addnl_sense_code) {
case ATA_ASC_MEDIA_UPSIDE_DOWN:
Error = TRUE;
break;
default:
break;
}
break;
default:
break;
}
SensePtr++;
}
return Error;
}
/**
Check if media is changed according to sense data.
@param SenseData Pointer to sense data.
@param SenseCounts Count of sense data.
@retval TRUE There is media change event.
@retval FALSE media is NOT changed.
**/
BOOLEAN
IsMediaChange (
IN ATAPI_REQUEST_SENSE_DATA *SenseData,
IN UINTN SenseCounts
)
{
ATAPI_REQUEST_SENSE_DATA *SensePtr;
UINTN Index;
BOOLEAN MediaChange;
MediaChange = FALSE;
SensePtr = SenseData;
for (Index = 0; Index < SenseCounts; Index++) {
//
// catch media change sense key and addition sense data
//
switch (SensePtr->sense_key) {
case ATA_SK_UNIT_ATTENTION:
switch (SensePtr->addnl_sense_code) {
case ATA_ASC_MEDIA_CHANGE:
MediaChange = TRUE;
break;
default:
break;
}
break;
default:
break;
}
SensePtr++;
}
return MediaChange;
}

View File

@ -0,0 +1,331 @@
/** @file
Common Libarary for PEI USB.
Copyright (c) 2006, 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 "UsbPeim.h"
#include "PeiUsbLib.h"
/**
Get a given usb descriptor.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param Value Request Value.
@param Index Request Index.
@param DescriptorLength Request descriptor Length.
@param Descriptor Request descriptor.
@retval EFI_SUCCESS Usb descriptor is obtained successfully.
@retval EFI_DEVICE_ERROR Cannot get the usb descriptor due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiUsbGetDescriptor (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN UINT16 Value,
IN UINT16 Index,
IN UINT16 DescriptorLength,
OUT VOID *Descriptor
)
{
EFI_USB_DEVICE_REQUEST DevReq;
ASSERT (UsbIoPpi != NULL);
DevReq.RequestType = USB_DEV_GET_DESCRIPTOR_REQ_TYPE;
DevReq.Request = USB_DEV_GET_DESCRIPTOR;
DevReq.Value = Value;
DevReq.Index = Index;
DevReq.Length = DescriptorLength;
return UsbIoPpi->UsbControlTransfer (
PeiServices,
UsbIoPpi,
&DevReq,
EfiUsbDataIn,
PcdGet32 (PcdUsbTransferTimeoutValue),
Descriptor,
DescriptorLength
);
}
/**
Set a usb device with a specified address.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param AddressValue The address to assign.
@retval EFI_SUCCESS Usb device address is set successfully.
@retval EFI_DEVICE_ERROR Cannot set the usb address due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiUsbSetDeviceAddress (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN UINT16 AddressValue
)
{
EFI_USB_DEVICE_REQUEST DevReq;
ASSERT (UsbIoPpi != NULL);
DevReq.RequestType = USB_DEV_SET_ADDRESS_REQ_TYPE;
DevReq.Request = USB_DEV_SET_ADDRESS;
DevReq.Value = AddressValue;
DevReq.Index = 0;
DevReq.Length = 0;
return UsbIoPpi->UsbControlTransfer (
PeiServices,
UsbIoPpi,
&DevReq,
EfiUsbNoData,
PcdGet32 (PcdUsbTransferTimeoutValue),
NULL,
0
);
}
/**
Clear a given usb feature.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param Recipient The recipient of ClearFeature Request, should be one of Device/Interface/Endpoint.
@param Value Request Value.
@param Target Request Index.
@retval EFI_SUCCESS Usb feature is cleared successfully.
@retval EFI_DEVICE_ERROR Cannot clear the usb feature due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiUsbClearDeviceFeature (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN EFI_USB_RECIPIENT Recipient,
IN UINT16 Value,
IN UINT16 Target
)
{
EFI_USB_DEVICE_REQUEST DevReq;
ASSERT (UsbIoPpi != NULL);
switch (Recipient) {
case EfiUsbDevice:
DevReq.RequestType = USB_DEV_CLEAR_FEATURE_REQ_TYPE_D;
break;
case EfiUsbInterface:
DevReq.RequestType = USB_DEV_CLEAR_FEATURE_REQ_TYPE_I;
break;
case EfiUsbEndpoint:
DevReq.RequestType = USB_DEV_CLEAR_FEATURE_REQ_TYPE_E;
break;
}
DevReq.Request = USB_DEV_CLEAR_FEATURE;
DevReq.Value = Value;
DevReq.Index = Target;
DevReq.Length = 0;
return UsbIoPpi->UsbControlTransfer (
PeiServices,
UsbIoPpi,
&DevReq,
EfiUsbNoData,
PcdGet32 (PcdUsbTransferTimeoutValue),
NULL,
0
);
}
/**
Configure a usb device to Configuration 1.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@retval EFI_SUCCESS Usb device is set to use Configuration 1 successfully.
@retval EFI_DEVICE_ERROR Cannot set the usb device due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiUsbSetConfiguration (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi
)
{
EFI_USB_DEVICE_REQUEST DevReq;
ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
DevReq.RequestType = USB_DEV_SET_CONFIGURATION_REQ_TYPE;
DevReq.Request = USB_DEV_SET_CONFIGURATION;
DevReq.Value = 1;
return UsbIoPpi->UsbControlTransfer (
PeiServices,
UsbIoPpi,
&DevReq,
EfiUsbNoData,
PcdGet32 (PcdUsbTransferTimeoutValue),
NULL,
0
);
}
/**
Clear Endpoint Halt.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param EndpointAddress The endpoint address.
@retval EFI_SUCCESS Endpoint halt is cleared successfully.
@retval EFI_DEVICE_ERROR Cannot clear the endpoint halt status due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiUsbClearEndpointHalt (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN UINT8 EndpointAddress
)
{
EFI_STATUS Status;
PEI_USB_DEVICE *PeiUsbDev;
EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor;
UINT8 EndpointIndex;
EndpointIndex = 0;
PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (UsbIoPpi);
while (EndpointIndex < MAX_ENDPOINT) {
Status = UsbIoPpi->UsbGetEndpointDescriptor (PeiServices, UsbIoPpi, EndpointIndex, &EndpointDescriptor);
if (EFI_ERROR (Status)) {
return EFI_INVALID_PARAMETER;
}
if (EndpointDescriptor->EndpointAddress == EndpointAddress) {
break;
}
EndpointIndex++;
}
if (EndpointIndex == MAX_ENDPOINT) {
return EFI_INVALID_PARAMETER;
}
Status = PeiUsbClearDeviceFeature (
PeiServices,
UsbIoPpi,
EfiUsbEndpoint,
EfiUsbEndpointHalt,
EndpointAddress
);
//
// set data toggle to zero.
//
if ((PeiUsbDev->DataToggle & (1 << EndpointIndex)) != 0) {
PeiUsbDev->DataToggle = (UINT8) (PeiUsbDev->DataToggle ^ (1 << EndpointIndex));
}
return Status;
}
/**
Judge if the port is connected with a usb device or not.
@param PortStatus The usb port status gotten.
@retval TRUE A usb device is connected with the port.
@retval FALSE No usb device is connected with the port.
**/
BOOLEAN
IsPortConnect (
IN UINT16 PortStatus
)
{
//
// return the bit 0 value of PortStatus
//
if ((PortStatus & USB_PORT_STAT_CONNECTION) != 0) {
return TRUE;
} else {
return FALSE;
}
}
/**
Judge if the port is connected with a low-speed usb device or not.
@param PortStatus The usb port status gotten.
@retval TRUE A low-speed usb device is connected with the port.
@retval FALSE No low-speed usb device is connected with the port.
**/
BOOLEAN
IsPortLowSpeedDeviceAttached (
IN UINT16 PortStatus
)
{
//
// return the bit 9 value of PortStatus
//
if ((PortStatus & USB_PORT_STAT_LOW_SPEED) != 0) {
return TRUE;
} else {
return FALSE;
}
}
/**
Judge if the port is in "connection change" status or not.
@param PortChangeStatus The usb port change status gotten.
@retval TRUE The port is in "connection change" status.
@retval FALSE The port is NOT in "connection change" status.
**/
BOOLEAN
IsPortConnectChange (
IN UINT16 PortChangeStatus
)
{
//
// return the bit 0 value of PortChangeStatus
//
if ((PortChangeStatus & USB_PORT_STAT_C_CONNECTION) != 0) {
return TRUE;
} else {
return FALSE;
}
}

View File

@ -0,0 +1,248 @@
/** @file
Common Libarary for PEI USB.
Copyright (c) 1999 - 2010, 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 _PEI_USB_LIB_H_
#define _PEI_USB_LIB_H_
//
// Standard device request and request type
// By [Spec-USB20/Chapter-9.4]
//
#define USB_DEV_GET_STATUS 0x00
#define USB_DEV_GET_STATUS_REQ_TYPE_D 0x80 // Receiver : Device
#define USB_DEV_GET_STATUS_REQ_TYPE_I 0x81 // Receiver : Interface
#define USB_DEV_GET_STATUS_REQ_TYPE_E 0x82 // Receiver : Endpoint
#define USB_DEV_CLEAR_FEATURE 0x01
#define USB_DEV_CLEAR_FEATURE_REQ_TYPE_D 0x00 // Receiver : Device
#define USB_DEV_CLEAR_FEATURE_REQ_TYPE_I 0x01 // Receiver : Interface
#define USB_DEV_CLEAR_FEATURE_REQ_TYPE_E 0x02 // Receiver : Endpoint
#define USB_DEV_SET_FEATURE 0x03
#define USB_DEV_SET_FEATURE_REQ_TYPE_D 0x00 // Receiver : Device
#define USB_DEV_SET_FEATURE_REQ_TYPE_I 0x01 // Receiver : Interface
#define USB_DEV_SET_FEATURE_REQ_TYPE_E 0x02 // Receiver : Endpoint
#define USB_DEV_SET_ADDRESS 0x05
#define USB_DEV_SET_ADDRESS_REQ_TYPE 0x00
#define USB_DEV_GET_DESCRIPTOR 0x06
#define USB_DEV_GET_DESCRIPTOR_REQ_TYPE 0x80
#define USB_DEV_SET_DESCRIPTOR 0x07
#define USB_DEV_SET_DESCRIPTOR_REQ_TYPE 0x00
#define USB_DEV_GET_CONFIGURATION 0x08
#define USB_DEV_GET_CONFIGURATION_REQ_TYPE 0x80
#define USB_DEV_SET_CONFIGURATION 0x09
#define USB_DEV_SET_CONFIGURATION_REQ_TYPE 0x00
#define USB_DEV_GET_INTERFACE 0x0A
#define USB_DEV_GET_INTERFACE_REQ_TYPE 0x81
#define USB_DEV_SET_INTERFACE 0x0B
#define USB_DEV_SET_INTERFACE_REQ_TYPE 0x01
#define USB_DEV_SYNCH_FRAME 0x0C
#define USB_DEV_SYNCH_FRAME_REQ_TYPE 0x82
//
// USB Descriptor types
//
#define USB_DT_DEVICE 0x01
#define USB_DT_CONFIG 0x02
#define USB_DT_STRING 0x03
#define USB_DT_INTERFACE 0x04
#define USB_DT_ENDPOINT 0x05
#define USB_DT_HUB 0x29
#define USB_DT_HID 0x21
//
// USB request type
//
#define USB_TYPE_STANDARD (0x00 << 5)
#define USB_TYPE_CLASS (0x01 << 5)
#define USB_TYPE_VENDOR (0x02 << 5)
#define USB_TYPE_RESERVED (0x03 << 5)
//
// USB request targer device
//
#define USB_RECIP_DEVICE 0x00
#define USB_RECIP_INTERFACE 0x01
#define USB_RECIP_ENDPOINT 0x02
#define USB_RECIP_OTHER 0x03
typedef enum {
EfiUsbEndpointHalt,
EfiUsbDeviceRemoteWakeup
} EFI_USB_STANDARD_FEATURE_SELECTOR;
//
// Usb Data recipient type
//
typedef enum {
EfiUsbDevice,
EfiUsbInterface,
EfiUsbEndpoint
} EFI_USB_RECIPIENT;
/**
Get a given usb descriptor.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param Value Request Value.
@param Index Request Index.
@param DescriptorLength Request descriptor Length.
@param Descriptor Request descriptor.
@retval EFI_SUCCESS Usb descriptor is obtained successfully.
@retval EFI_DEVICE_ERROR Cannot get the usb descriptor due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiUsbGetDescriptor (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN UINT16 Value,
IN UINT16 Index,
IN UINT16 DescriptorLength,
OUT VOID *Descriptor
);
/**
Set a usb device with a specified address.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param AddressValue The address to assign.
@retval EFI_SUCCESS Usb device address is set successfully.
@retval EFI_DEVICE_ERROR Cannot set the usb address due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiUsbSetDeviceAddress (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN UINT16 AddressValue
);
/**
Clear a given usb feature.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param Recipient The recipient of ClearFeature Request, should be one of Device/Interface/Endpoint.
@param Value Request Value.
@param Target Request Index.
@retval EFI_SUCCESS Usb feature is cleared successfully.
@retval EFI_DEVICE_ERROR Cannot clear the usb feature due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiUsbClearDeviceFeature (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN EFI_USB_RECIPIENT Recipient,
IN UINT16 Value,
IN UINT16 Target
);
/**
Configure a usb device to Configuration 1.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@retval EFI_SUCCESS Usb device is set to use Configuration 1 successfully.
@retval EFI_DEVICE_ERROR Cannot set the usb device due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiUsbSetConfiguration (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi
);
/**
Clear Endpoint Halt.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param EndpointAddress The endpoint address.
@retval EFI_SUCCESS Endpoint halt is cleared successfully.
@retval EFI_DEVICE_ERROR Cannot clear the endpoint halt status due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiUsbClearEndpointHalt (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN UINT8 EndpointAddress
);
/**
Judge if the port is connected with a usb device or not.
@param PortStatus The usb port status gotten.
@retval TRUE A usb device is connected with the port.
@retval FALSE No usb device is connected with the port.
**/
BOOLEAN
IsPortConnect (
IN UINT16 PortStatus
);
/**
Judge if the port is connected with a low-speed usb device or not.
@param PortStatus The usb port status gotten.
@retval TRUE A low-speed usb device is connected with the port.
@retval FALSE No low-speed usb device is connected with the port.
**/
BOOLEAN
IsPortLowSpeedDeviceAttached (
IN UINT16 PortStatus
);
/**
Judge if the port is in "connection change" status or not.
@param PortChangeStatus The usb port change status gotten.
@retval TRUE The port is in "connection change" status.
@retval FALSE The port is NOT in "connection change" status.
**/
BOOLEAN
IsPortConnectChange (
IN UINT16 PortChangeStatus
);
#endif

View File

@ -0,0 +1,65 @@
## @file
# Component description file for UsbBotPei module.
#
# Usb mass storage device Peim driver to support recovery from USB device.
# Copyright (c) 2006 - 2010, 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 = UsbBotPei
FILE_GUID = 8401A046-6F70-4505-8471-7015B40355E3
MODULE_TYPE = PEIM
VERSION_STRING = 1.0
ENTRY_POINT = PeimInitializeUsbBot
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources]
PeiUsbLib.c
PeiAtapi.c
BotPeim.c
UsbBotPeim.c
UsbPeim.h
UsbBotPeim.h
PeiUsbLib.h
BotPeim.h
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
BaseMemoryLib
PeiServicesLib
PeimEntryPoint
DebugLib
PcdLib
[Pcd]
gEfiMdePkgTokenSpaceGuid.PcdUsbTransferTimeoutValue
[Ppis]
gEfiPeiVirtualBlockIoPpiGuid # PPI ALWAYS_PRODUCED
gPeiUsbIoPpiGuid # PPI ALWAYS_CONSUMED
[Depex]
gEfiPeiMemoryDiscoveredPpiGuid AND gPeiUsbIoPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid

View File

@ -0,0 +1,720 @@
/** @file
Copyright (c) 2006 - 2010, 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 "UsbBotPeim.h"
#include "BotPeim.h"
//
// Global function
//
EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList = {
EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
&gPeiUsbIoPpiGuid,
NotifyOnUsbIoPpi
};
EFI_PEI_RECOVERY_BLOCK_IO_PPI mRecoveryBlkIoPpi = {
BotGetNumberOfBlockDevices,
BotGetMediaInfo,
BotReadBlocks
};
EFI_PEI_PPI_DESCRIPTOR mPpiList = {
EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
&gEfiPeiVirtualBlockIoPpiGuid,
NULL
};
/**
Detect whether the removable media is present and whether it has changed.
@param[in] PeiServices General-purpose services that are available to every
PEIM.
@param[in] PeiBotDev Indicates the PEI_BOT_DEVICE instance.
@retval EFI_SUCCESS The media status is successfully checked.
@retval Other Failed to detect media.
**/
EFI_STATUS
PeiBotDetectMedia (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_BOT_DEVICE *PeiBotDev
);
/**
Initializes the Usb Bot.
@param FileHandle Handle of the file being invoked.
@param PeiServices Describes the list of possible PEI Services.
@retval EFI_SUCCESS Usb bot driver is successfully initialized.
@retval EFI_OUT_OF_RESOURCES Can't initialize the driver.
**/
EFI_STATUS
EFIAPI
PeimInitializeUsbBot (
IN EFI_PEI_FILE_HANDLE FileHandle,
IN CONST EFI_PEI_SERVICES **PeiServices
)
{
EFI_STATUS Status;
UINTN UsbIoPpiInstance;
EFI_PEI_PPI_DESCRIPTOR *TempPpiDescriptor;
PEI_USB_IO_PPI *UsbIoPpi;
//
// Shadow this PEIM to run from memory
//
if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {
return EFI_SUCCESS;
}
//
// locate all usb io PPIs
//
for (UsbIoPpiInstance = 0; UsbIoPpiInstance < PEI_FAT_MAX_USB_IO_PPI; UsbIoPpiInstance++) {
Status = PeiServicesLocatePpi (
&gPeiUsbIoPpiGuid,
UsbIoPpiInstance,
&TempPpiDescriptor,
(VOID **) &UsbIoPpi
);
if (EFI_ERROR (Status)) {
break;
}
}
//
// Register a notify function
//
return PeiServicesNotifyPpi (&mNotifyList);
}
/**
UsbIo installation notification function.
This function finds out all the current USB IO PPIs in the system and add them
into private data.
@param PeiServices Indirect reference to the PEI Services Table.
@param NotifyDesc Address of the notification descriptor data structure.
@param InvokePpi Address of the PPI that was invoked.
@retval EFI_SUCCESS The function completes successfully.
**/
EFI_STATUS
EFIAPI
NotifyOnUsbIoPpi (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
IN VOID *InvokePpi
)
{
PEI_USB_IO_PPI *UsbIoPpi;
UsbIoPpi = (PEI_USB_IO_PPI *) InvokePpi;
InitUsbBot (PeiServices, UsbIoPpi);
return EFI_SUCCESS;
}
/**
Initialize the usb bot device.
@param[in] PeiServices General-purpose services that are available to every
PEIM.
@param[in] UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@retval EFI_SUCCESS The usb bot device is initialized successfully.
@retval Other Failed to initialize media.
**/
EFI_STATUS
InitUsbBot (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi
)
{
PEI_BOT_DEVICE *PeiBotDevice;
EFI_STATUS Status;
EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDesc;
UINTN MemPages;
EFI_PHYSICAL_ADDRESS AllocateAddress;
EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDesc;
UINT8 Index;
//
// Check its interface
//
Status = UsbIoPpi->UsbGetInterfaceDescriptor (
PeiServices,
UsbIoPpi,
&InterfaceDesc
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Check if it is the BOT device we support
//
if ((InterfaceDesc->InterfaceClass != 0x08) || (InterfaceDesc->InterfaceProtocol != 0x50)) {
return EFI_NOT_FOUND;
}
MemPages = sizeof (PEI_BOT_DEVICE) / EFI_PAGE_SIZE + 1;
Status = PeiServicesAllocatePages (
EfiBootServicesCode,
MemPages,
&AllocateAddress
);
if (EFI_ERROR (Status)) {
return Status;
}
PeiBotDevice = (PEI_BOT_DEVICE *) ((UINTN) AllocateAddress);
PeiBotDevice->Signature = PEI_BOT_DEVICE_SIGNATURE;
PeiBotDevice->UsbIoPpi = UsbIoPpi;
PeiBotDevice->AllocateAddress = (UINTN) AllocateAddress;
PeiBotDevice->BotInterface = InterfaceDesc;
//
// Default value
//
PeiBotDevice->Media.DeviceType = UsbMassStorage;
PeiBotDevice->Media.BlockSize = 0x200;
//
// Check its Bulk-in/Bulk-out endpoint
//
for (Index = 0; Index < 2; Index++) {
Status = UsbIoPpi->UsbGetEndpointDescriptor (
PeiServices,
UsbIoPpi,
Index,
&EndpointDesc
);
if (EFI_ERROR (Status)) {
return Status;
}
if ((EndpointDesc->EndpointAddress & 0x80) != 0) {
PeiBotDevice->BulkInEndpoint = EndpointDesc;
} else {
PeiBotDevice->BulkOutEndpoint = EndpointDesc;
}
}
CopyMem (
&(PeiBotDevice->BlkIoPpi),
&mRecoveryBlkIoPpi,
sizeof (EFI_PEI_RECOVERY_BLOCK_IO_PPI)
);
CopyMem (
&(PeiBotDevice->BlkIoPpiList),
&mPpiList,
sizeof (EFI_PEI_PPI_DESCRIPTOR)
);
PeiBotDevice->BlkIoPpiList.Ppi = &PeiBotDevice->BlkIoPpi;
Status = PeiUsbInquiry (PeiServices, PeiBotDevice);
if (EFI_ERROR (Status)) {
return Status;
}
Status = PeiServicesAllocatePages (
EfiBootServicesCode,
1,
&AllocateAddress
);
if (EFI_ERROR (Status)) {
return Status;
}
PeiBotDevice->SensePtr = (ATAPI_REQUEST_SENSE_DATA *) ((UINTN) AllocateAddress);
Status = PeiServicesInstallPpi (&PeiBotDevice->BlkIoPpiList);
if (EFI_ERROR (Status)) {
return Status;
}
return EFI_SUCCESS;
}
/**
Gets the count of block I/O devices that one specific block driver detects.
This function is used for getting the count of block I/O devices that one
specific block driver detects. To the PEI ATAPI driver, it returns the number
of all the detected ATAPI devices it detects during the enumeration process.
To the PEI legacy floppy driver, it returns the number of all the legacy
devices it finds during its enumeration process. If no device is detected,
then the function will return zero.
@param[in] PeiServices General-purpose services that are available
to every PEIM.
@param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI
instance.
@param[out] NumberBlockDevices The number of block I/O devices discovered.
@retval EFI_SUCCESS Operation performed successfully.
**/
EFI_STATUS
EFIAPI
BotGetNumberOfBlockDevices (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
OUT UINTN *NumberBlockDevices
)
{
//
// For Usb devices, this value should be always 1
//
*NumberBlockDevices = 1;
return EFI_SUCCESS;
}
/**
Gets a block device's media information.
This function will provide the caller with the specified block device's media
information. If the media changes, calling this function will update the media
information accordingly.
@param[in] PeiServices General-purpose services that are available to every
PEIM
@param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.
@param[in] DeviceIndex Specifies the block device to which the function wants
to talk. Because the driver that implements Block I/O
PPIs will manage multiple block devices, the PPIs that
want to talk to a single device must specify the
device index that was assigned during the enumeration
process. This index is a number from one to
NumberBlockDevices.
@param[out] MediaInfo The media information of the specified block media.
The caller is responsible for the ownership of this
data structure.
@retval EFI_SUCCESS Media information about the specified block device
was obtained successfully.
@retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware
error.
**/
EFI_STATUS
EFIAPI
BotGetMediaInfo (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
IN UINTN DeviceIndex,
OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo
)
{
PEI_BOT_DEVICE *PeiBotDev;
EFI_STATUS Status;
PeiBotDev = PEI_BOT_DEVICE_FROM_THIS (This);
//
// First test unit ready
//
PeiUsbTestUnitReady (
PeiServices,
PeiBotDev
);
Status = PeiBotDetectMedia (
PeiServices,
PeiBotDev
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
CopyMem (
MediaInfo,
&(PeiBotDev->Media),
sizeof (EFI_PEI_BLOCK_IO_MEDIA)
);
return EFI_SUCCESS;
}
/**
Reads the requested number of blocks from the specified block device.
The function reads the requested number of blocks from the device. All the
blocks are read, or an error is returned. If there is no media in the device,
the function returns EFI_NO_MEDIA.
@param[in] PeiServices General-purpose services that are available to
every PEIM.
@param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.
@param[in] DeviceIndex Specifies the block device to which the function wants
to talk. Because the driver that implements Block I/O
PPIs will manage multiple block devices, the PPIs that
want to talk to a single device must specify the device
index that was assigned during the enumeration process.
This index is a number from one to NumberBlockDevices.
@param[in] StartLBA The starting logical block address (LBA) to read from
on the device
@param[in] BufferSize The size of the Buffer in bytes. This number must be
a multiple of the intrinsic block size of the device.
@param[out] Buffer A pointer to the destination buffer for the data.
The caller is responsible for the ownership of the
buffer.
@retval EFI_SUCCESS The data was read correctly from the device.
@retval EFI_DEVICE_ERROR The device reported an error while attempting
to perform the read operation.
@retval EFI_INVALID_PARAMETER The read request contains LBAs that are not
valid, or the buffer is not properly aligned.
@retval EFI_NO_MEDIA There is no media in the device.
@retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of
the intrinsic block size of the device.
**/
EFI_STATUS
EFIAPI
BotReadBlocks (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
IN UINTN DeviceIndex,
IN EFI_PEI_LBA StartLBA,
IN UINTN BufferSize,
OUT VOID *Buffer
)
{
PEI_BOT_DEVICE *PeiBotDev;
EFI_STATUS Status;
UINTN BlockSize;
UINTN NumberOfBlocks;
Status = EFI_SUCCESS;
PeiBotDev = PEI_BOT_DEVICE_FROM_THIS (This);
//
// Check parameters
//
if (Buffer == NULL) {
return EFI_INVALID_PARAMETER;
}
if (BufferSize == 0) {
return EFI_SUCCESS;
}
if (!PeiBotDev->Media.MediaPresent) {
return EFI_NO_MEDIA;
}
BlockSize = PeiBotDev->Media.BlockSize;
if (BufferSize % BlockSize != 0) {
Status = EFI_BAD_BUFFER_SIZE;
}
if (StartLBA > PeiBotDev->Media.LastBlock) {
Status = EFI_INVALID_PARAMETER;
}
NumberOfBlocks = BufferSize / (PeiBotDev->Media.BlockSize);
if (Status == EFI_SUCCESS) {
Status = PeiUsbTestUnitReady (
PeiServices,
PeiBotDev
);
if (Status == EFI_SUCCESS) {
Status = PeiUsbRead10 (
PeiServices,
PeiBotDev,
Buffer,
StartLBA,
1
);
}
} else {
//
// To generate sense data for DetectMedia use.
//
PeiUsbTestUnitReady (
PeiServices,
PeiBotDev
);
}
if (EFI_ERROR (Status)) {
//
// if any error encountered, detect what happened to the media and
// update the media info accordingly.
//
Status = PeiBotDetectMedia (
PeiServices,
PeiBotDev
);
if (Status != EFI_SUCCESS) {
return EFI_DEVICE_ERROR;
}
NumberOfBlocks = BufferSize / PeiBotDev->Media.BlockSize;
if (!(PeiBotDev->Media.MediaPresent)) {
return EFI_NO_MEDIA;
}
if (BufferSize % (PeiBotDev->Media.BlockSize) != 0) {
return EFI_BAD_BUFFER_SIZE;
}
if (StartLBA > PeiBotDev->Media.LastBlock) {
return EFI_INVALID_PARAMETER;
}
if ((StartLBA + NumberOfBlocks - 1) > PeiBotDev->Media.LastBlock) {
return EFI_INVALID_PARAMETER;
}
Status = PeiUsbRead10 (
PeiServices,
PeiBotDev,
Buffer,
StartLBA,
NumberOfBlocks
);
switch (Status) {
case EFI_SUCCESS:
return EFI_SUCCESS;
default:
return EFI_DEVICE_ERROR;
}
} else {
StartLBA += 1;
NumberOfBlocks -= 1;
Buffer = (UINT8 *) Buffer + PeiBotDev->Media.BlockSize;
if (NumberOfBlocks == 0) {
return EFI_SUCCESS;
}
Status = PeiUsbRead10 (
PeiServices,
PeiBotDev,
Buffer,
StartLBA,
NumberOfBlocks
);
switch (Status) {
case EFI_SUCCESS:
return EFI_SUCCESS;
default:
return EFI_DEVICE_ERROR;
}
}
}
/**
Detect whether the removable media is present and whether it has changed.
@param[in] PeiServices General-purpose services that are available to every
PEIM.
@param[in] PeiBotDev Indicates the PEI_BOT_DEVICE instance.
@retval EFI_SUCCESS The media status is successfully checked.
@retval Other Failed to detect media.
**/
EFI_STATUS
PeiBotDetectMedia (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_BOT_DEVICE *PeiBotDev
)
{
EFI_STATUS Status;
EFI_STATUS FloppyStatus;
UINTN SenseCounts;
BOOLEAN NeedReadCapacity;
EFI_PHYSICAL_ADDRESS AllocateAddress;
ATAPI_REQUEST_SENSE_DATA *SensePtr;
UINTN Retry;
//
// if there is no media present,or media not changed,
// the request sense command will detect faster than read capacity command.
// read capacity command can be bypassed, thus improve performance.
//
SenseCounts = 0;
NeedReadCapacity = TRUE;
Status = PeiServicesAllocatePages (
EfiBootServicesCode,
1,
&AllocateAddress
);
if (EFI_ERROR (Status)) {
return Status;
}
SensePtr = PeiBotDev->SensePtr;
ZeroMem (SensePtr, EFI_PAGE_SIZE);
Status = PeiUsbRequestSense (
PeiServices,
PeiBotDev,
&SenseCounts,
(UINT8 *) SensePtr
);
if (Status == EFI_SUCCESS) {
//
// No Media
//
if (IsNoMedia (SensePtr, SenseCounts)) {
NeedReadCapacity = FALSE;
PeiBotDev->Media.MediaPresent = FALSE;
PeiBotDev->Media.LastBlock = 0;
} else {
//
// Media Changed
//
if (IsMediaChange (SensePtr, SenseCounts)) {
PeiBotDev->Media.MediaPresent = TRUE;
}
//
// Media Error
//
if (IsMediaError (SensePtr, SenseCounts)) {
//
// if media error encountered, make it look like no media present.
//
PeiBotDev->Media.MediaPresent = FALSE;
PeiBotDev->Media.LastBlock = 0;
}
}
}
if (NeedReadCapacity) {
//
// Retry at most 4 times to detect media info
//
for (Retry = 0; Retry < 4; Retry++) {
switch (PeiBotDev->DeviceType) {
case USBCDROM:
Status = PeiUsbReadCapacity (
PeiServices,
PeiBotDev
);
break;
case USBFLOPPY2:
Status = PeiUsbReadFormattedCapacity (
PeiServices,
PeiBotDev
);
if (EFI_ERROR(Status)||
!PeiBotDev->Media.MediaPresent) {
//
// retry the ReadCapacity command
//
PeiBotDev->DeviceType = USBFLOPPY;
Status = EFI_DEVICE_ERROR;
}
break;
case USBFLOPPY:
Status = PeiUsbReadCapacity (
PeiServices,
PeiBotDev
);
//
// retry the ReadFormatCapacity command
//
PeiBotDev->DeviceType = USBFLOPPY2;
break;
default:
return EFI_INVALID_PARAMETER;
}
SenseCounts = 0;
ZeroMem (SensePtr, EFI_PAGE_SIZE);
if (Status == EFI_SUCCESS) {
break;
}
FloppyStatus = PeiUsbRequestSense (
PeiServices,
PeiBotDev,
&SenseCounts,
(UINT8 *) SensePtr
);
//
// If Request Sense data failed,retry.
//
if (EFI_ERROR (FloppyStatus)) {
continue;
}
//
// No Media
//
if (IsNoMedia (SensePtr, SenseCounts)) {
PeiBotDev->Media.MediaPresent = FALSE;
PeiBotDev->Media.LastBlock = 0;
break;
}
if (IsMediaError (SensePtr, SenseCounts)) {
//
// if media error encountered, make it look like no media present.
//
PeiBotDev->Media.MediaPresent = FALSE;
PeiBotDev->Media.LastBlock = 0;
break;
}
}
//
// ENDFOR
//
// tell whether the readcapacity process is successful or not
// ("Status" variable record the latest status returned
// by ReadCapacity )
//
if (Status != EFI_SUCCESS) {
return EFI_DEVICE_ERROR;
}
}
return EFI_SUCCESS;
}

View File

@ -0,0 +1,233 @@
/** @file
Usb BOT Peim definition.
Copyright (c) 2006, 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 _PEI_USB_BOT_PEIM_H_
#define _PEI_USB_BOT_PEIM_H_
#include <PiPei.h>
#include <Ppi/UsbIo.h>
#include <Ppi/UsbHostController.h>
#include <Ppi/BlockIo.h>
#include <Library/DebugLib.h>
#include <IndustryStandard/Usb.h>
#include <IndustryStandard/Atapi.h>
#define PEI_FAT_MAX_USB_IO_PPI 127
/**
Gets the count of block I/O devices that one specific block driver detects.
This function is used for getting the count of block I/O devices that one
specific block driver detects. To the PEI ATAPI driver, it returns the number
of all the detected ATAPI devices it detects during the enumeration process.
To the PEI legacy floppy driver, it returns the number of all the legacy
devices it finds during its enumeration process. If no device is detected,
then the function will return zero.
@param[in] PeiServices General-purpose services that are available
to every PEIM.
@param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI
instance.
@param[out] NumberBlockDevices The number of block I/O devices discovered.
@retval EFI_SUCCESS Operation performed successfully.
**/
EFI_STATUS
EFIAPI
BotGetNumberOfBlockDevices (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
OUT UINTN *NumberBlockDevices
);
/**
Gets a block device's media information.
This function will provide the caller with the specified block device's media
information. If the media changes, calling this function will update the media
information accordingly.
@param[in] PeiServices General-purpose services that are available to every
PEIM
@param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.
@param[in] DeviceIndex Specifies the block device to which the function wants
to talk. Because the driver that implements Block I/O
PPIs will manage multiple block devices, the PPIs that
want to talk to a single device must specify the
device index that was assigned during the enumeration
process. This index is a number from one to
NumberBlockDevices.
@param[out] MediaInfo The media information of the specified block media.
The caller is responsible for the ownership of this
data structure.
@retval EFI_SUCCESS Media information about the specified block device
was obtained successfully.
@retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware
error.
**/
EFI_STATUS
EFIAPI
BotGetMediaInfo (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
IN UINTN DeviceIndex,
OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo
);
/**
Reads the requested number of blocks from the specified block device.
The function reads the requested number of blocks from the device. All the
blocks are read, or an error is returned. If there is no media in the device,
the function returns EFI_NO_MEDIA.
@param[in] PeiServices General-purpose services that are available to
every PEIM.
@param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.
@param[in] DeviceIndex Specifies the block device to which the function wants
to talk. Because the driver that implements Block I/O
PPIs will manage multiple block devices, the PPIs that
want to talk to a single device must specify the device
index that was assigned during the enumeration process.
This index is a number from one to NumberBlockDevices.
@param[in] StartLBA The starting logical block address (LBA) to read from
on the device
@param[in] BufferSize The size of the Buffer in bytes. This number must be
a multiple of the intrinsic block size of the device.
@param[out] Buffer A pointer to the destination buffer for the data.
The caller is responsible for the ownership of the
buffer.
@retval EFI_SUCCESS The data was read correctly from the device.
@retval EFI_DEVICE_ERROR The device reported an error while attempting
to perform the read operation.
@retval EFI_INVALID_PARAMETER The read request contains LBAs that are not
valid, or the buffer is not properly aligned.
@retval EFI_NO_MEDIA There is no media in the device.
@retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of
the intrinsic block size of the device.
**/
EFI_STATUS
EFIAPI
BotReadBlocks (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
IN UINTN DeviceIndex,
IN EFI_PEI_LBA StartLBA,
IN UINTN BufferSize,
OUT VOID *Buffer
);
/**
UsbIo installation notification function.
This function finds out all the current USB IO PPIs in the system and add them
into private data.
@param PeiServices Indirect reference to the PEI Services Table.
@param NotifyDesc Address of the notification descriptor data structure.
@param InvokePpi Address of the PPI that was invoked.
@retval EFI_SUCCESS The function completes successfully.
**/
EFI_STATUS
EFIAPI
NotifyOnUsbIoPpi (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
IN VOID *InvokePpi
);
/**
Initialize the usb bot device.
@param[in] PeiServices General-purpose services that are available to every
PEIM.
@param[in] UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@retval EFI_SUCCESS The usb bot device is initialized successfully.
@retval Other Failed to initialize media.
**/
EFI_STATUS
InitUsbBot (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi
);
#define USBCDROM 1 // let the device type value equal to USBCDROM, which is defined by PI spec.
// Therefore the CdExpressPei module can do recovery on UsbCdrom.
#define USBFLOPPY 2 // for those that use ReadCapacity(0x25) command to retrieve media capacity
#define USBFLOPPY2 3 // for those that use ReadFormatCapacity(0x23) command to retrieve media capacity
//
// Bot device structure
//
#define PEI_BOT_DEVICE_SIGNATURE SIGNATURE_32 ('U', 'B', 'O', 'T')
typedef struct {
UINTN Signature;
EFI_PEI_RECOVERY_BLOCK_IO_PPI BlkIoPpi;
EFI_PEI_PPI_DESCRIPTOR BlkIoPpiList;
EFI_PEI_BLOCK_IO_MEDIA Media;
PEI_USB_IO_PPI *UsbIoPpi;
EFI_USB_INTERFACE_DESCRIPTOR *BotInterface;
EFI_USB_ENDPOINT_DESCRIPTOR *BulkInEndpoint;
EFI_USB_ENDPOINT_DESCRIPTOR *BulkOutEndpoint;
UINTN AllocateAddress;
UINTN DeviceType;
ATAPI_REQUEST_SENSE_DATA *SensePtr;
} PEI_BOT_DEVICE;
#define PEI_BOT_DEVICE_FROM_THIS(a) CR (a, PEI_BOT_DEVICE, BlkIoPpi, PEI_BOT_DEVICE_SIGNATURE)
/**
Send ATAPI command using BOT protocol.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param PeiBotDev The instance to PEI_BOT_DEVICE.
@param Command The command to be sent to ATAPI device.
@param CommandSize The length of the data to be sent.
@param DataBuffer The pointer to the data.
@param BufferLength The length of the data.
@param Direction The direction of the data.
@param TimeOutInMilliSeconds Indicates the maximum time, in millisecond, which the
transfer is allowed to complete.
@retval EFI_DEVICE_ERROR Successful to get the status of device.
@retval EFI_SUCCESS Failed to get the status of device.
**/
EFI_STATUS
PeiAtapiCommand (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_BOT_DEVICE *PeiBotDev,
IN VOID *Command,
IN UINT8 CommandSize,
IN VOID *DataBuffer,
IN UINT32 BufferLength,
IN EFI_USB_DATA_DIRECTION Direction,
IN UINT16 TimeOutInMilliSeconds
);
#endif

View File

@ -0,0 +1,179 @@
/** @file
Usb Peim definition.
Copyright (c) 2006, 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 _PEI_USB_PEIM_H_
#define _PEI_USB_PEIM_H_
#include <PiPei.h>
#include <Ppi/UsbIo.h>
#include <Ppi/UsbHostController.h>
#include <Ppi/BlockIo.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/PcdLib.h>
#include <IndustryStandard/Usb.h>
#define MAX_ROOT_PORT 2
#define MAX_ENDPOINT 16
#define USB_SLOW_SPEED_DEVICE 0x01
#define USB_FULL_SPEED_DEVICE 0x02
#define PEI_USB_DEVICE_SIGNATURE SIGNATURE_32 ('U', 's', 'b', 'D')
typedef struct {
UINTN Signature;
PEI_USB_IO_PPI UsbIoPpi;
EFI_PEI_PPI_DESCRIPTOR UsbIoPpiList;
UINT8 DeviceAddress;
UINT8 MaxPacketSize0;
UINT8 DeviceSpeed;
UINT8 DataToggle;
UINT8 IsHub;
UINT8 DownStreamPortNo;
UINT8 Reserved[2]; // Padding for IPF
UINTN AllocateAddress;
PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi;
UINT8 ConfigurationData[1024];
EFI_USB_CONFIG_DESCRIPTOR *ConfigDesc;
EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDesc;
EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDesc[MAX_ENDPOINT];
} PEI_USB_DEVICE;
#define PEI_USB_DEVICE_FROM_THIS(a) CR (a, PEI_USB_DEVICE, UsbIoPpi, PEI_USB_DEVICE_SIGNATURE)
/**
Submits control transfer to a target USB device.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param This The pointer of PEI_USB_IO_PPI.
@param Request USB device request to send.
@param Direction Specifies the data direction for the data stage.
@param Timeout Indicates the maximum timeout, in millisecond.
@param Data Data buffer to be transmitted or received from USB device.
@param DataLength The size (in bytes) of the data buffer.
@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
PeiUsbControlTransfer (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *This,
IN EFI_USB_DEVICE_REQUEST *Request,
IN EFI_USB_DATA_DIRECTION Direction,
IN UINT32 Timeout,
IN OUT VOID *Data, OPTIONAL
IN UINTN DataLength OPTIONAL
);
/**
Submits bulk transfer to a bulk endpoint of a USB device.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param This The pointer of PEI_USB_IO_PPI.
@param DeviceEndpoint Endpoint number and its direction in bit 7.
@param Data A pointer to the buffer of data to transmit
from or receive into.
@param DataLength The lenght of the data buffer.
@param Timeout Indicates the maximum time, in millisecond, which the
transfer is allowed to complete.
@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 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
PeiUsbBulkTransfer (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *This,
IN UINT8 DeviceEndpoint,
IN OUT VOID *Data,
IN OUT UINTN *DataLength,
IN UINTN Timeout
);
/**
Get the usb interface descriptor.
@param PeiServices General-purpose services that are available to every PEIM.
@param This Indicates the PEI_USB_IO_PPI instance.
@param InterfaceDescriptor Request interface descriptor.
@retval EFI_SUCCESS Usb interface descriptor is obtained successfully.
**/
EFI_STATUS
EFIAPI
PeiUsbGetInterfaceDescriptor (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *This,
OUT EFI_USB_INTERFACE_DESCRIPTOR **InterfaceDescriptor
);
/**
Get the usb endpoint descriptor.
@param PeiServices General-purpose services that are available to every PEIM.
@param This Indicates the PEI_USB_IO_PPI instance.
@param EndpointIndex The valid index of the specified endpoint.
@param EndpointDescriptor Request endpoint descriptor.
@retval EFI_SUCCESS Usb endpoint descriptor is obtained successfully.
@retval EFI_NOT_FOUND Usb endpoint descriptor is NOT found.
**/
EFI_STATUS
EFIAPI
PeiUsbGetEndpointDescriptor (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *This,
IN UINT8 EndpointIndex,
OUT EFI_USB_ENDPOINT_DESCRIPTOR **EndpointDescriptor
);
/**
Reset the port and re-configure the usb device.
@param PeiServices General-purpose services that are available to every PEIM.
@param This Indicates the PEI_USB_IO_PPI instance.
@retval EFI_SUCCESS Usb device is reset and configured successfully.
@retval Others Other failure occurs.
**/
EFI_STATUS
EFIAPI
PeiUsbPortReset (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *This
);
#endif

View File

@ -0,0 +1,537 @@
/** @file
Usb Hub Request Support In PEI Phase
Copyright (c) 2006 - 2010, 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 "UsbPeim.h"
#include "HubPeim.h"
#include "PeiUsbLib.h"
/**
Get a given hub port status.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param Port Usb hub port number (starting from 1).
@param PortStatus Current Hub port status and change status.
@retval EFI_SUCCESS Port status is obtained successfully.
@retval EFI_DEVICE_ERROR Cannot get the port status due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiHubGetPortStatus (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN UINT8 Port,
OUT UINT32 *PortStatus
)
{
EFI_USB_DEVICE_REQUEST DeviceRequest;
ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
//
// Fill Device request packet
//
DeviceRequest.RequestType = USB_HUB_GET_PORT_STATUS_REQ_TYPE;
DeviceRequest.Request = USB_HUB_GET_PORT_STATUS;
DeviceRequest.Index = Port;
DeviceRequest.Length = (UINT16) sizeof (UINT32);
return UsbIoPpi->UsbControlTransfer (
PeiServices,
UsbIoPpi,
&DeviceRequest,
EfiUsbDataIn,
PcdGet32 (PcdUsbTransferTimeoutValue),
PortStatus,
sizeof (UINT32)
);
}
/**
Set specified feature to a given hub port.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param Port Usb hub port number (starting from 1).
@param Value New feature value.
@retval EFI_SUCCESS Port feature is set successfully.
@retval EFI_DEVICE_ERROR Cannot set the port feature due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiHubSetPortFeature (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN UINT8 Port,
IN UINT8 Value
)
{
EFI_USB_DEVICE_REQUEST DeviceRequest;
ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
//
// Fill Device request packet
//
DeviceRequest.RequestType = USB_HUB_SET_PORT_FEATURE_REQ_TYPE;
DeviceRequest.Request = USB_HUB_SET_PORT_FEATURE;
DeviceRequest.Value = Value;
DeviceRequest.Index = Port;
return UsbIoPpi->UsbControlTransfer (
PeiServices,
UsbIoPpi,
&DeviceRequest,
EfiUsbNoData,
PcdGet32 (PcdUsbTransferTimeoutValue),
NULL,
0
);
}
/**
Clear specified feature on a given hub port.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param Port Usb hub port number (starting from 1).
@param Value Feature value that will be cleared from the hub port.
@retval EFI_SUCCESS Port feature is cleared successfully.
@retval EFI_DEVICE_ERROR Cannot clear the port feature due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiHubClearPortFeature (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN UINT8 Port,
IN UINT8 Value
)
{
EFI_USB_DEVICE_REQUEST DeviceRequest;
ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
//
// Fill Device request packet
//
DeviceRequest.RequestType = USB_HUB_CLEAR_FEATURE_PORT_REQ_TYPE;
DeviceRequest.Request = USB_HUB_CLEAR_FEATURE_PORT;
DeviceRequest.Value = Value;
DeviceRequest.Index = Port;
return UsbIoPpi->UsbControlTransfer (
PeiServices,
UsbIoPpi,
&DeviceRequest,
EfiUsbNoData,
PcdGet32 (PcdUsbTransferTimeoutValue),
NULL,
0
);
}
/**
Get a given hub status.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param HubStatus Current Hub status and change status.
@retval EFI_SUCCESS Hub status is obtained successfully.
@retval EFI_DEVICE_ERROR Cannot get the hub status due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiHubGetHubStatus (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
OUT UINT32 *HubStatus
)
{
EFI_USB_DEVICE_REQUEST DeviceRequest;
ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
//
// Fill Device request packet
//
DeviceRequest.RequestType = USB_HUB_GET_HUB_STATUS_REQ_TYPE;
DeviceRequest.Request = USB_HUB_GET_HUB_STATUS;
DeviceRequest.Length = (UINT16) sizeof (UINT32);
return UsbIoPpi->UsbControlTransfer (
PeiServices,
UsbIoPpi,
&DeviceRequest,
EfiUsbDataIn,
PcdGet32 (PcdUsbTransferTimeoutValue),
HubStatus,
sizeof (UINT32)
);
}
/**
Set specified feature to a given hub.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param Value New feature value.
@retval EFI_SUCCESS Port feature is set successfully.
@retval EFI_DEVICE_ERROR Cannot set the port feature due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiHubSetHubFeature (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN UINT8 Value
)
{
EFI_USB_DEVICE_REQUEST DeviceRequest;
ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
//
// Fill Device request packet
//
DeviceRequest.RequestType = USB_HUB_SET_HUB_FEATURE_REQ_TYPE;
DeviceRequest.Request = USB_HUB_SET_HUB_FEATURE;
DeviceRequest.Value = Value;
return UsbIoPpi->UsbControlTransfer (
PeiServices,
UsbIoPpi,
&DeviceRequest,
EfiUsbNoData,
PcdGet32 (PcdUsbTransferTimeoutValue),
NULL,
0
);
}
/**
Clear specified feature on a given hub.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param Value Feature value that will be cleared from the hub port.
@retval EFI_SUCCESS Hub feature is cleared successfully.
@retval EFI_DEVICE_ERROR Cannot clear the hub feature due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiHubClearHubFeature (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN UINT8 Value
)
{
EFI_USB_DEVICE_REQUEST DeviceRequest;
ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
//
// Fill Device request packet
//
DeviceRequest.RequestType = USB_HUB_CLEAR_FEATURE_REQ_TYPE;
DeviceRequest.Request = USB_HUB_CLEAR_FEATURE;
DeviceRequest.Value = Value;
return UsbIoPpi->UsbControlTransfer (
PeiServices,
UsbIoPpi,
&DeviceRequest,
EfiUsbNoData,
PcdGet32 (PcdUsbTransferTimeoutValue),
NULL,
0
);
}
/**
Get a given hub descriptor.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param DescriptorSize The length of Hub Descriptor buffer.
@param HubDescriptor Caller allocated buffer to store the hub descriptor if
successfully returned.
@retval EFI_SUCCESS Hub descriptor is obtained successfully.
@retval EFI_DEVICE_ERROR Cannot get the hub descriptor due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiGetHubDescriptor (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN UINTN DescriptorSize,
OUT EFI_USB_HUB_DESCRIPTOR *HubDescriptor
)
{
EFI_USB_DEVICE_REQUEST DevReq;
ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
//
// Fill Device request packet
//
DevReq.RequestType = USB_RT_HUB | 0x80;
DevReq.Request = USB_HUB_GET_DESCRIPTOR;
DevReq.Value = USB_DT_HUB << 8;
DevReq.Length = (UINT16)DescriptorSize;
return UsbIoPpi->UsbControlTransfer (
PeiServices,
UsbIoPpi,
&DevReq,
EfiUsbDataIn,
PcdGet32 (PcdUsbTransferTimeoutValue),
HubDescriptor,
(UINT16)DescriptorSize
);
}
/**
Configure a given hub.
@param PeiServices General-purpose services that are available to every PEIM.
@param PeiUsbDevice Indicating the hub controller device that will be configured
@retval EFI_SUCCESS Hub configuration is done successfully.
@retval EFI_DEVICE_ERROR Cannot configure the hub due to a hardware error.
**/
EFI_STATUS
PeiDoHubConfig (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_DEVICE *PeiUsbDevice
)
{
EFI_USB_HUB_DESCRIPTOR HubDescriptor;
EFI_STATUS Status;
EFI_USB_HUB_STATUS HubStatus;
UINTN Index;
UINT32 PortStatus;
PEI_USB_IO_PPI *UsbIoPpi;
ZeroMem (&HubDescriptor, sizeof (HubDescriptor));
UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
//
// First get the hub descriptor length
//
Status = PeiGetHubDescriptor (
PeiServices,
UsbIoPpi,
2,
&HubDescriptor
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
//
// First get the whole descriptor, then
// get the number of hub ports
//
Status = PeiGetHubDescriptor (
PeiServices,
UsbIoPpi,
HubDescriptor.Length,
&HubDescriptor
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
PeiUsbDevice->DownStreamPortNo = HubDescriptor.NbrPorts;
Status = PeiHubGetHubStatus (
PeiServices,
UsbIoPpi,
(UINT32 *) &HubStatus
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
//
// Get all hub ports status
//
for (Index = 0; Index < PeiUsbDevice->DownStreamPortNo; Index++) {
Status = PeiHubGetPortStatus (
PeiServices,
UsbIoPpi,
(UINT8) (Index + 1),
&PortStatus
);
if (EFI_ERROR (Status)) {
continue;
}
}
//
// Power all the hub ports
//
for (Index = 0; Index < PeiUsbDevice->DownStreamPortNo; Index++) {
Status = PeiHubSetPortFeature (
PeiServices,
UsbIoPpi,
(UINT8) (Index + 1),
EfiUsbPortPower
);
if (EFI_ERROR (Status)) {
continue;
}
}
//
// Clear Hub Status Change
//
Status = PeiHubGetHubStatus (
PeiServices,
UsbIoPpi,
(UINT32 *) &HubStatus
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
} else {
//
// Hub power supply change happens
//
if ((HubStatus.HubChangeStatus & HUB_CHANGE_LOCAL_POWER) != 0) {
PeiHubClearHubFeature (
PeiServices,
UsbIoPpi,
C_HUB_LOCAL_POWER
);
}
//
// Hub change overcurrent happens
//
if ((HubStatus.HubChangeStatus & HUB_CHANGE_OVERCURRENT) != 0) {
PeiHubClearHubFeature (
PeiServices,
UsbIoPpi,
C_HUB_OVER_CURRENT
);
}
}
return EFI_SUCCESS;
}
/**
Send reset signal over the given root hub port.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param PortNum Usb hub port number (starting from 1).
**/
VOID
PeiResetHubPort (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN UINT8 PortNum
)
{
UINT8 Try;
EFI_USB_PORT_STATUS HubPortStatus;
MicroSecondDelay (100 * 1000);
//
// reset root port
//
PeiHubSetPortFeature (
PeiServices,
UsbIoPpi,
PortNum,
EfiUsbPortReset
);
Try = 10;
do {
PeiHubGetPortStatus (
PeiServices,
UsbIoPpi,
PortNum,
(UINT32 *) &HubPortStatus
);
MicroSecondDelay (2 * 1000);
Try -= 1;
} while ((HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0 && Try > 0);
//
// clear reset root port
//
PeiHubClearPortFeature (
PeiServices,
UsbIoPpi,
PortNum,
EfiUsbPortReset
);
MicroSecondDelay (1 * 1000);
PeiHubClearPortFeature (
PeiServices,
UsbIoPpi,
PortNum,
EfiUsbPortConnectChange
);
//
// Set port enable
//
PeiHubSetPortFeature (
PeiServices,
UsbIoPpi,
PortNum,
EfiUsbPortEnable
);
//
// Clear any change status
//
PeiHubClearPortFeature (
PeiServices,
UsbIoPpi,
PortNum,
EfiUsbPortEnableChange
);
MicroSecondDelay (10 * 1000);
return;
}

View File

@ -0,0 +1,279 @@
/** @file
Constants definitions for Usb Hub Peim
Copyright (c) 2006, 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 _PEI_HUB_PEIM_H_
#define _PEI_HUB_PEIM_H_
//
// Hub feature numbers
//
#define C_HUB_LOCAL_POWER 0
#define C_HUB_OVER_CURRENT 1
//
// Hub class code & sub class code
//
#define CLASS_CODE_HUB 0x09
#define SUB_CLASS_CODE_HUB 0
//
// Hub Status & Hub Change bit masks
//
#define HUB_STATUS_LOCAL_POWER 0x0001
#define HUB_STATUS_OVERCURRENT 0x0002
#define HUB_CHANGE_LOCAL_POWER 0x0001
#define HUB_CHANGE_OVERCURRENT 0x0002
//
// Hub Characteristics
//
#define HUB_CHAR_LPSM 0x0003
#define HUB_CHAR_COMPOUND 0x0004
#define HUB_CHAR_OCPM 0x0018
//
// Standard hub request and request type
// By [Spec-USB20/Chapter-11.24]
//
#define USB_HUB_CLEAR_FEATURE 0x01
#define USB_HUB_CLEAR_FEATURE_REQ_TYPE 0x20
#define USB_HUB_CLEAR_FEATURE_PORT 0x01
#define USB_HUB_CLEAR_FEATURE_PORT_REQ_TYPE 0x23
#define USB_HUB_GET_BUS_STATE 0x02
#define USB_HUB_GET_BUS_STATE_REQ_TYPE 0xA3
#define USB_HUB_GET_DESCRIPTOR 0x06
#define USB_HUB_GET_DESCRIPTOR_REQ_TYPE 0xA0
#define USB_HUB_GET_HUB_STATUS 0x00
#define USB_HUB_GET_HUB_STATUS_REQ_TYPE 0xA0
#define USB_HUB_GET_PORT_STATUS 0x00
#define USB_HUB_GET_PORT_STATUS_REQ_TYPE 0xA3
#define USB_HUB_SET_DESCRIPTOR 0x07
#define USB_HUB_SET_DESCRIPTOR_REQ_TYPE 0x20
#define USB_HUB_SET_HUB_FEATURE 0x03
#define USB_HUB_SET_HUB_FEATURE_REQ_TYPE 0x20
#define USB_HUB_SET_PORT_FEATURE 0x03
#define USB_HUB_SET_PORT_FEATURE_REQ_TYPE 0x23
#define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE)
#define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER)
#define MAXBYTES 8
#pragma pack(1)
//
// Hub descriptor, the last two fields are of variable lenght.
//
typedef struct {
UINT8 Length;
UINT8 DescriptorType;
UINT8 NbrPorts;
UINT8 HubCharacteristics[2];
UINT8 PwrOn2PwrGood;
UINT8 HubContrCurrent;
UINT8 Filler[MAXBYTES];
} EFI_USB_HUB_DESCRIPTOR;
typedef struct {
UINT16 HubStatus;
UINT16 HubChangeStatus;
} EFI_USB_HUB_STATUS;
#pragma pack()
/**
Get a given hub port status.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param Port Usb hub port number (starting from 1).
@param PortStatus Current Hub port status and change status.
@retval EFI_SUCCESS Port status is obtained successfully.
@retval EFI_DEVICE_ERROR Cannot get the port status due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiHubGetPortStatus (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN UINT8 Port,
OUT UINT32 *PortStatus
);
/**
Set specified feature to a given hub port.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param Port Usb hub port number (starting from 1).
@param Value New feature value.
@retval EFI_SUCCESS Port feature is set successfully.
@retval EFI_DEVICE_ERROR Cannot set the port feature due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiHubSetPortFeature (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN UINT8 Port,
IN UINT8 Value
);
/**
Set specified feature to a given hub.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param Value New feature value.
@retval EFI_SUCCESS Port feature is set successfully.
@retval EFI_DEVICE_ERROR Cannot set the port feature due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiHubSetHubFeature (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN UINT8 Value
);
/**
Get a given hub status.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param HubStatus Current Hub status and change status.
@retval EFI_SUCCESS Hub status is obtained successfully.
@retval EFI_DEVICE_ERROR Cannot get the hub status due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiHubGetHubStatus (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
OUT UINT32 *HubStatus
);
/**
Clear specified feature on a given hub port.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param Port Usb hub port number (starting from 1).
@param Value Feature value that will be cleared from the hub port.
@retval EFI_SUCCESS Port feature is cleared successfully.
@retval EFI_DEVICE_ERROR Cannot clear the port feature due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiHubClearPortFeature (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN UINT8 Port,
IN UINT8 Value
);
/**
Clear specified feature on a given hub.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param Value Feature value that will be cleared from the hub port.
@retval EFI_SUCCESS Hub feature is cleared successfully.
@retval EFI_DEVICE_ERROR Cannot clear the hub feature due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiHubClearHubFeature (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN UINT8 Value
);
/**
Get a given hub descriptor.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param DescriptorSize The length of Hub Descriptor buffer.
@param HubDescriptor Caller allocated buffer to store the hub descriptor if
successfully returned.
@retval EFI_SUCCESS Hub descriptor is obtained successfully.
@retval EFI_DEVICE_ERROR Cannot get the hub descriptor due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiGetHubDescriptor (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN UINTN DescriptorSize,
OUT EFI_USB_HUB_DESCRIPTOR *HubDescriptor
);
/**
Configure a given hub.
@param PeiServices General-purpose services that are available to every PEIM.
@param PeiUsbDevice Indicating the hub controller device that will be configured
@retval EFI_SUCCESS Hub configuration is done successfully.
@retval EFI_DEVICE_ERROR Cannot configure the hub due to a hardware error.
**/
EFI_STATUS
PeiDoHubConfig (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_DEVICE *PeiUsbDevice
);
/**
Send reset signal over the given root hub port.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param PortNum Usb hub port number (starting from 1).
**/
VOID
PeiResetHubPort (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN UINT8 PortNum
);
#endif

View File

@ -0,0 +1,333 @@
/** @file
Common Libarary for PEI USB
Copyright (c) 2006 - 2010, 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 "UsbPeim.h"
#include "PeiUsbLib.h"
/**
Get a given usb descriptor.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param Value Request Value.
@param Index Request Index.
@param DescriptorLength Request descriptor Length.
@param Descriptor Request descriptor.
@retval EFI_SUCCESS Usb descriptor is obtained successfully.
@retval EFI_DEVICE_ERROR Cannot get the usb descriptor due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiUsbGetDescriptor (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN UINT16 Value,
IN UINT16 Index,
IN UINT16 DescriptorLength,
OUT VOID *Descriptor
)
{
EFI_USB_DEVICE_REQUEST DevReq;
ASSERT (UsbIoPpi != NULL);
DevReq.RequestType = USB_DEV_GET_DESCRIPTOR_REQ_TYPE;
DevReq.Request = USB_DEV_GET_DESCRIPTOR;
DevReq.Value = Value;
DevReq.Index = Index;
DevReq.Length = DescriptorLength;
return UsbIoPpi->UsbControlTransfer (
PeiServices,
UsbIoPpi,
&DevReq,
EfiUsbDataIn,
PcdGet32 (PcdUsbTransferTimeoutValue),
Descriptor,
DescriptorLength
);
}
/**
Set a usb device with a specified address.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param AddressValue The address to assign.
@retval EFI_SUCCESS Usb device address is set successfully.
@retval EFI_DEVICE_ERROR Cannot set the usb address due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiUsbSetDeviceAddress (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN UINT16 AddressValue
)
{
EFI_USB_DEVICE_REQUEST DevReq;
ASSERT (UsbIoPpi != NULL);
DevReq.RequestType = USB_DEV_SET_ADDRESS_REQ_TYPE;
DevReq.Request = USB_DEV_SET_ADDRESS;
DevReq.Value = AddressValue;
DevReq.Index = 0;
DevReq.Length = 0;
return UsbIoPpi->UsbControlTransfer (
PeiServices,
UsbIoPpi,
&DevReq,
EfiUsbNoData,
PcdGet32 (PcdUsbTransferTimeoutValue),
NULL,
0
);
}
/**
Clear a given usb feature.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param Recipient The recipient of ClearFeature Request, should be one of Device/Interface/Endpoint.
@param Value Request Value.
@param Target Request Index.
@retval EFI_SUCCESS Usb feature is cleared successfully.
@retval EFI_DEVICE_ERROR Cannot clear the usb feature due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiUsbClearDeviceFeature (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN EFI_USB_RECIPIENT Recipient,
IN UINT16 Value,
IN UINT16 Target
)
{
EFI_USB_DEVICE_REQUEST DevReq;
ASSERT (UsbIoPpi != NULL);
switch (Recipient) {
case EfiUsbDevice:
DevReq.RequestType = USB_DEV_CLEAR_FEATURE_REQ_TYPE_D;
break;
case EfiUsbInterface:
DevReq.RequestType = USB_DEV_CLEAR_FEATURE_REQ_TYPE_I;
break;
case EfiUsbEndpoint:
DevReq.RequestType = USB_DEV_CLEAR_FEATURE_REQ_TYPE_E;
break;
}
DevReq.Request = USB_DEV_CLEAR_FEATURE;
DevReq.Value = Value;
DevReq.Index = Target;
DevReq.Length = 0;
return UsbIoPpi->UsbControlTransfer (
PeiServices,
UsbIoPpi,
&DevReq,
EfiUsbNoData,
PcdGet32 (PcdUsbTransferTimeoutValue),
NULL,
0
);
}
/**
Configure a usb device to Configuration 1.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@retval EFI_SUCCESS Usb device is set to use Configuration 1 successfully.
@retval EFI_DEVICE_ERROR Cannot set the usb device due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiUsbSetConfiguration (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi
)
{
EFI_USB_DEVICE_REQUEST DevReq;
ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
DevReq.RequestType = USB_DEV_SET_CONFIGURATION_REQ_TYPE;
DevReq.Request = USB_DEV_SET_CONFIGURATION;
DevReq.Value = 1;
return UsbIoPpi->UsbControlTransfer (
PeiServices,
UsbIoPpi,
&DevReq,
EfiUsbNoData,
PcdGet32 (PcdUsbTransferTimeoutValue),
NULL,
0
);
}
/**
Clear Endpoint Halt.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param EndpointAddress The endpoint address.
@retval EFI_SUCCESS Endpoint halt is cleared successfully.
@retval EFI_DEVICE_ERROR Cannot clear the endpoint halt status due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiUsbClearEndpointHalt (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN UINT8 EndpointAddress
)
{
EFI_STATUS Status;
PEI_USB_DEVICE *PeiUsbDev;
EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor;
UINT8 EndpointIndex;
EndpointIndex = 0;
PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (UsbIoPpi);
while (EndpointIndex < MAX_ENDPOINT) {
Status = UsbIoPpi->UsbGetEndpointDescriptor (PeiServices, UsbIoPpi, EndpointIndex, &EndpointDescriptor);
if (EFI_ERROR (Status)) {
return EFI_INVALID_PARAMETER;
}
if (EndpointDescriptor->EndpointAddress == EndpointAddress) {
break;
}
EndpointIndex++;
}
if (EndpointIndex == MAX_ENDPOINT) {
return EFI_INVALID_PARAMETER;
}
Status = PeiUsbClearDeviceFeature (
PeiServices,
UsbIoPpi,
EfiUsbEndpoint,
EfiUsbEndpointHalt,
EndpointAddress
);
//
// set data toggle to zero.
//
if ((PeiUsbDev->DataToggle & (1 << EndpointIndex)) != 0) {
PeiUsbDev->DataToggle = (UINT8) (PeiUsbDev->DataToggle ^ (1 << EndpointIndex));
}
return Status;
}
/**
Judge if the port is connected with a usb device or not.
@param PortStatus The usb port status gotten.
@retval TRUE A usb device is connected with the port.
@retval FALSE No usb device is connected with the port.
**/
BOOLEAN
IsPortConnect (
IN UINT16 PortStatus
)
{
//
// return the bit 0 value of PortStatus
//
if ((PortStatus & USB_PORT_STAT_CONNECTION) != 0) {
return TRUE;
} else {
return FALSE;
}
}
/**
Judge if the port is connected with a low-speed usb device or not.
@param PortStatus The usb port status gotten.
@retval TRUE A low-speed usb device is connected with the port.
@retval FALSE No low-speed usb device is connected with the port.
**/
UINTN
IsPortLowSpeedDeviceAttached (
IN UINT16 PortStatus
)
{
//
// return the bit 9 value of PortStatus
//
if ((PortStatus & USB_PORT_STAT_LOW_SPEED) != 0) {
return EFI_USB_SPEED_LOW;
} else if ((PortStatus & USB_PORT_STAT_HIGH_SPEED) != 0){
return EFI_USB_SPEED_HIGH;
} else {
return EFI_USB_SPEED_FULL;
}
}
/**
Judge if the port is in "connection change" status or not.
@param PortChangeStatus The usb port change status gotten.
@retval TRUE The port is in "connection change" status.
@retval FALSE The port is NOT in "connection change" status.
**/
BOOLEAN
IsPortConnectChange (
IN UINT16 PortChangeStatus
)
{
//
// return the bit 0 value of PortChangeStatus
//
if ((PortChangeStatus & USB_PORT_STAT_C_CONNECTION) != 0) {
return TRUE;
} else {
return FALSE;
}
}

View File

@ -0,0 +1,250 @@
/** @file
Common Libarary for PEI USB
Copyright (c) 2006 - 2010, 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 _PEI_USB_LIB_H_
#define _PEI_USB_LIB_H_
//
// Standard device request and request type
// By [Spec-USB20/Chapter-9.4]
//
#define USB_DEV_GET_STATUS 0x00
#define USB_DEV_GET_STATUS_REQ_TYPE_D 0x80 // Receiver : Device
#define USB_DEV_GET_STATUS_REQ_TYPE_I 0x81 // Receiver : Interface
#define USB_DEV_GET_STATUS_REQ_TYPE_E 0x82 // Receiver : Endpoint
#define USB_DEV_CLEAR_FEATURE 0x01
#define USB_DEV_CLEAR_FEATURE_REQ_TYPE_D 0x00 // Receiver : Device
#define USB_DEV_CLEAR_FEATURE_REQ_TYPE_I 0x01 // Receiver : Interface
#define USB_DEV_CLEAR_FEATURE_REQ_TYPE_E 0x02 // Receiver : Endpoint
#define USB_DEV_SET_FEATURE 0x03
#define USB_DEV_SET_FEATURE_REQ_TYPE_D 0x00 // Receiver : Device
#define USB_DEV_SET_FEATURE_REQ_TYPE_I 0x01 // Receiver : Interface
#define USB_DEV_SET_FEATURE_REQ_TYPE_E 0x02 // Receiver : Endpoint
#define USB_DEV_SET_ADDRESS 0x05
#define USB_DEV_SET_ADDRESS_REQ_TYPE 0x00
#define USB_DEV_GET_DESCRIPTOR 0x06
#define USB_DEV_GET_DESCRIPTOR_REQ_TYPE 0x80
#define USB_DEV_SET_DESCRIPTOR 0x07
#define USB_DEV_SET_DESCRIPTOR_REQ_TYPE 0x00
#define USB_DEV_GET_CONFIGURATION 0x08
#define USB_DEV_GET_CONFIGURATION_REQ_TYPE 0x80
#define USB_DEV_SET_CONFIGURATION 0x09
#define USB_DEV_SET_CONFIGURATION_REQ_TYPE 0x00
#define USB_DEV_GET_INTERFACE 0x0A
#define USB_DEV_GET_INTERFACE_REQ_TYPE 0x81
#define USB_DEV_SET_INTERFACE 0x0B
#define USB_DEV_SET_INTERFACE_REQ_TYPE 0x01
#define USB_DEV_SYNCH_FRAME 0x0C
#define USB_DEV_SYNCH_FRAME_REQ_TYPE 0x82
//
// USB Descriptor types
//
#define USB_DT_DEVICE 0x01
#define USB_DT_CONFIG 0x02
#define USB_DT_STRING 0x03
#define USB_DT_INTERFACE 0x04
#define USB_DT_ENDPOINT 0x05
#define USB_DT_HUB 0x29
#define USB_DT_HID 0x21
//
// USB request type
//
#define USB_TYPE_STANDARD (0x00 << 5)
#define USB_TYPE_CLASS (0x01 << 5)
#define USB_TYPE_VENDOR (0x02 << 5)
#define USB_TYPE_RESERVED (0x03 << 5)
//
// USB request targer device
//
#define USB_RECIP_DEVICE 0x00
#define USB_RECIP_INTERFACE 0x01
#define USB_RECIP_ENDPOINT 0x02
#define USB_RECIP_OTHER 0x03
typedef enum {
EfiUsbEndpointHalt,
EfiUsbDeviceRemoteWakeup
} EFI_USB_STANDARD_FEATURE_SELECTOR;
//
// Usb Data recipient type
//
typedef enum {
EfiUsbDevice,
EfiUsbInterface,
EfiUsbEndpoint
} EFI_USB_RECIPIENT;
/**
Get a given usb descriptor.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param Value Request Value.
@param Index Request Index.
@param DescriptorLength Request descriptor Length.
@param Descriptor Request descriptor.
@retval EFI_SUCCESS Usb descriptor is obtained successfully.
@retval EFI_DEVICE_ERROR Cannot get the usb descriptor due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiUsbGetDescriptor (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN UINT16 Value,
IN UINT16 Index,
IN UINT16 DescriptorLength,
OUT VOID *Descriptor
);
/**
Set a usb device with a specified address.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param AddressValue The address to assign.
@retval EFI_SUCCESS Usb device address is set successfully.
@retval EFI_DEVICE_ERROR Cannot set the usb address due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiUsbSetDeviceAddress (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN UINT16 AddressValue
);
/**
Clear a given usb feature.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param Recipient The recipient of ClearFeature Request, should be one of Device/Interface/Endpoint.
@param Value Request Value.
@param Target Request Index.
@retval EFI_SUCCESS Usb feature is cleared successfully.
@retval EFI_DEVICE_ERROR Cannot clear the usb feature due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiUsbClearDeviceFeature (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN EFI_USB_RECIPIENT Recipient,
IN UINT16 Value,
IN UINT16 Target
);
/**
Configure a usb device to Configuration 1.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@retval EFI_SUCCESS Usb device is set to use Configuration 1 successfully.
@retval EFI_DEVICE_ERROR Cannot set the usb device due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiUsbSetConfiguration (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi
);
/**
Clear Endpoint Halt.
@param PeiServices General-purpose services that are available to every PEIM.
@param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
@param EndpointAddress The endpoint address.
@retval EFI_SUCCESS Endpoint halt is cleared successfully.
@retval EFI_DEVICE_ERROR Cannot clear the endpoint halt status due to a hardware error.
@retval Others Other failure occurs.
**/
EFI_STATUS
PeiUsbClearEndpointHalt (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *UsbIoPpi,
IN UINT8 EndpointAddress
);
/**
Judge if the port is connected with a usb device or not.
@param PortStatus The usb port status gotten.
@retval TRUE A usb device is connected with the port.
@retval FALSE No usb device is connected with the port.
**/
BOOLEAN
IsPortConnect (
IN UINT16 PortStatus
);
/**
Judge if the port is connected with a low-speed usb device or not.
@param PortStatus The usb port status gotten.
@retval TRUE A low-speed usb device is connected with the port.
@retval FALSE No low-speed usb device is connected with the port.
**/
UINTN
IsPortLowSpeedDeviceAttached (
IN UINT16 PortStatus
);
/**
Judge if the port is in "connection change" status or not.
@param PortChangeStatus The usb port change status gotten.
@retval TRUE The port is in "connection change" status.
@retval FALSE The port is NOT in "connection change" status.
**/
BOOLEAN
IsPortConnectChange (
IN UINT16 PortChangeStatus
);
#endif

View File

@ -0,0 +1,66 @@
## @file
# Component description file for UsbPeim module.
#
# Usb Bus Peim driver to support recovery from usb device.
# Copyright (c) 2006 - 2010, 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 = UsbBusPei
FILE_GUID = 8401A045-6F70-4505-8471-7015B40355E3
MODULE_TYPE = PEIM
VERSION_STRING = 1.0
ENTRY_POINT = PeimInitializeUsb
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources]
PeiUsbLib.c
HubPeim.c
UsbIoPeim.c
UsbPeim.c
UsbPeim.h
PeiUsbLib.h
HubPeim.h
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
TimerLib
BaseMemoryLib
PeiServicesLib
PeimEntryPoint
DebugLib
PcdLib
[Pcd]
gEfiMdePkgTokenSpaceGuid.PcdUsbTransferTimeoutValue
[Ppis]
gPeiUsbIoPpiGuid # PPI ALWAYS_PRODUCED
gPeiUsbHostControllerPpiGuid # PPI ALWAYS_CONSUMED
gPeiUsb2HostControllerPpiGuid # PPI ALWAYS_CONSUMED
[Depex]
gEfiPeiMemoryDiscoveredPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid AND gPeiUsb2HostControllerPpiGuid OR gPeiUsbHostControllerPpiGuid

View File

@ -0,0 +1,325 @@
/** @file
The module is used to implement Usb Io PPI interfaces.
Copyright (c) 2006 - 2010, 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 "UsbPeim.h"
#include "PeiUsbLib.h"
/**
Submits control transfer to a target USB device.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param This The pointer of PEI_USB_IO_PPI.
@param Request USB device request to send.
@param Direction Specifies the data direction for the data stage.
@param Timeout Indicates the maximum timeout, in millisecond.
@param Data Data buffer to be transmitted or received from USB device.
@param DataLength The size (in bytes) of the data buffer.
@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
PeiUsbControlTransfer (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *This,
IN EFI_USB_DEVICE_REQUEST *Request,
IN EFI_USB_DATA_DIRECTION Direction,
IN UINT32 Timeout,
IN OUT VOID *Data, OPTIONAL
IN UINTN DataLength OPTIONAL
)
{
EFI_STATUS Status;
PEI_USB_DEVICE *PeiUsbDev;
UINT32 TransferResult;
PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
if (PeiUsbDev->Usb2HcPpi != NULL) {
Status = PeiUsbDev->Usb2HcPpi->ControlTransfer (
PeiServices,
PeiUsbDev->Usb2HcPpi,
PeiUsbDev->DeviceAddress,
PeiUsbDev->DeviceSpeed,
PeiUsbDev->MaxPacketSize0,
Request,
Direction,
Data,
&DataLength,
Timeout,
&(PeiUsbDev->Translator),
&TransferResult
);
} else {
Status = PeiUsbDev->UsbHcPpi->ControlTransfer (
PeiServices,
PeiUsbDev->UsbHcPpi,
PeiUsbDev->DeviceAddress,
PeiUsbDev->DeviceSpeed,
PeiUsbDev->MaxPacketSize0,
Request,
Direction,
Data,
&DataLength,
Timeout,
&TransferResult
);
}
return Status;
}
/**
Submits bulk transfer to a bulk endpoint of a USB device.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param This The pointer of PEI_USB_IO_PPI.
@param DeviceEndpoint Endpoint number and its direction in bit 7.
@param Data A pointer to the buffer of data to transmit
from or receive into.
@param DataLength The lenght of the data buffer.
@param Timeout Indicates the maximum time, in millisecond, which the
transfer is allowed to complete.
@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 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
PeiUsbBulkTransfer (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *This,
IN UINT8 DeviceEndpoint,
IN OUT VOID *Data,
IN OUT UINTN *DataLength,
IN UINTN Timeout
)
{
EFI_STATUS Status;
PEI_USB_DEVICE *PeiUsbDev;
UINT32 TransferResult;
UINTN MaxPacketLength;
UINT8 DataToggle;
UINT8 OldToggle;
EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor;
UINT8 EndpointIndex;
VOID *Data2[EFI_USB_MAX_BULK_BUFFER_NUM];
PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
EndpointDescriptor = NULL;
EndpointIndex = 0;
Data2[0] = Data;
Data2[1] = NULL;
while (EndpointIndex < MAX_ENDPOINT) {
Status = PeiUsbGetEndpointDescriptor (PeiServices, This, EndpointIndex, &EndpointDescriptor);
if (EFI_ERROR (Status)) {
return EFI_INVALID_PARAMETER;
}
if (EndpointDescriptor->EndpointAddress == DeviceEndpoint) {
break;
}
EndpointIndex++;
}
if (EndpointIndex == MAX_ENDPOINT) {
return EFI_INVALID_PARAMETER;
}
MaxPacketLength = PeiUsbDev->EndpointDesc[EndpointIndex]->MaxPacketSize;
if ((PeiUsbDev->DataToggle & (1 << EndpointIndex)) != 0) {
DataToggle = 1;
} else {
DataToggle = 0;
}
OldToggle = DataToggle;
if (PeiUsbDev->Usb2HcPpi != NULL) {
Status = PeiUsbDev->Usb2HcPpi->BulkTransfer (
PeiServices,
PeiUsbDev->Usb2HcPpi,
PeiUsbDev->DeviceAddress,
DeviceEndpoint,
PeiUsbDev->DeviceSpeed,
MaxPacketLength,
Data2,
DataLength,
&DataToggle,
Timeout,
&(PeiUsbDev->Translator),
&TransferResult
);
} else {
Status = PeiUsbDev->UsbHcPpi->BulkTransfer (
PeiServices,
PeiUsbDev->UsbHcPpi,
PeiUsbDev->DeviceAddress,
DeviceEndpoint,
(UINT8) MaxPacketLength,
Data,
DataLength,
&DataToggle,
Timeout,
&TransferResult
);
}
if (OldToggle != DataToggle) {
PeiUsbDev->DataToggle = (UINT8) (PeiUsbDev->DataToggle ^ (1 << EndpointIndex));
}
return Status;
}
/**
Get the usb interface descriptor.
@param PeiServices General-purpose services that are available to every PEIM.
@param This Indicates the PEI_USB_IO_PPI instance.
@param InterfaceDescriptor Request interface descriptor.
@retval EFI_SUCCESS Usb interface descriptor is obtained successfully.
**/
EFI_STATUS
EFIAPI
PeiUsbGetInterfaceDescriptor (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *This,
OUT EFI_USB_INTERFACE_DESCRIPTOR **InterfaceDescriptor
)
{
PEI_USB_DEVICE *PeiUsbDev;
PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
*InterfaceDescriptor = PeiUsbDev->InterfaceDesc;
return EFI_SUCCESS;
}
/**
Get the usb endpoint descriptor.
@param PeiServices General-purpose services that are available to every PEIM.
@param This Indicates the PEI_USB_IO_PPI instance.
@param EndpointIndex The valid index of the specified endpoint.
@param EndpointDescriptor Request endpoint descriptor.
@retval EFI_SUCCESS Usb endpoint descriptor is obtained successfully.
@retval EFI_NOT_FOUND Usb endpoint descriptor is NOT found.
**/
EFI_STATUS
EFIAPI
PeiUsbGetEndpointDescriptor (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *This,
IN UINT8 EndpointIndex,
OUT EFI_USB_ENDPOINT_DESCRIPTOR **EndpointDescriptor
)
{
PEI_USB_DEVICE *PeiUsbDev;
PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
ASSERT (EndpointDescriptor != NULL);
//
// The valid range of EndpointIndex is 0..15
// If EndpointIndex is lesser than 15 but larger than the number of interfaces,
// a EFI_NOT_FOUND should be returned
//
ASSERT (EndpointIndex <= 15);
if (EndpointIndex >= PeiUsbDev->InterfaceDesc->NumEndpoints) {
return EFI_NOT_FOUND;
}
*EndpointDescriptor = PeiUsbDev->EndpointDesc[EndpointIndex];
return EFI_SUCCESS;
}
/**
Reset the port and re-configure the usb device.
@param PeiServices General-purpose services that are available to every PEIM.
@param This Indicates the PEI_USB_IO_PPI instance.
@retval EFI_SUCCESS Usb device is reset and configured successfully.
@retval Others Other failure occurs.
**/
EFI_STATUS
EFIAPI
PeiUsbPortReset (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *This
)
{
PEI_USB_DEVICE *PeiUsbDev;
EFI_STATUS Status;
UINT8 Address;
PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
ResetRootPort (
PeiServices,
PeiUsbDev->UsbHcPpi,
PeiUsbDev->Usb2HcPpi,
PeiUsbDev->DeviceAddress,
0
);
//
// Set address
//
Address = PeiUsbDev->DeviceAddress;
PeiUsbDev->DeviceAddress = 0;
Status = PeiUsbSetDeviceAddress (
PeiServices,
This,
Address
);
if (EFI_ERROR (Status)) {
return Status;
}
PeiUsbDev->DeviceAddress = Address;
//
// Set default configuration
//
Status = PeiUsbSetConfiguration (
PeiServices,
This
);
return Status;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,203 @@
/** @file
Usb Peim definition.
Copyright (c) 2006 - 2010, 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 _PEI_USB_PEIM_H_
#define _PEI_USB_PEIM_H_
#include <PiPei.h>
#include <Ppi/UsbHostController.h>
#include <Ppi/Usb2HostController.h>
#include <Ppi/UsbIo.h>
#include <Library/DebugLib.h>
#include <Library/PeimEntryPoint.h>
#include <Library/PeiServicesLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/TimerLib.h>
#include <Library/PcdLib.h>
#include <IndustryStandard/Usb.h>
#define MAX_ROOT_PORT 2
#define MAX_ENDPOINT 16
#define USB_SLOW_SPEED_DEVICE 0x01
#define USB_FULL_SPEED_DEVICE 0x02
#define PEI_USB_DEVICE_SIGNATURE SIGNATURE_32 ('U', 's', 'b', 'D')
typedef struct {
UINTN Signature;
PEI_USB_IO_PPI UsbIoPpi;
EFI_PEI_PPI_DESCRIPTOR UsbIoPpiList;
UINT8 DeviceAddress;
UINT8 MaxPacketSize0;
UINT8 DeviceSpeed;
UINT8 DataToggle;
UINT8 IsHub;
UINT8 DownStreamPortNo;
UINT8 Reserved[2]; // Padding for IPF
UINTN AllocateAddress;
PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi;
PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi;
UINT8 ConfigurationData[1024];
EFI_USB_CONFIG_DESCRIPTOR *ConfigDesc;
EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDesc;
EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDesc[MAX_ENDPOINT];
EFI_USB2_HC_TRANSACTION_TRANSLATOR Translator;
} PEI_USB_DEVICE;
#define PEI_USB_DEVICE_FROM_THIS(a) CR (a, PEI_USB_DEVICE, UsbIoPpi, PEI_USB_DEVICE_SIGNATURE)
/**
Submits control transfer to a target USB device.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param This The pointer of PEI_USB_IO_PPI.
@param Request USB device request to send.
@param Direction Specifies the data direction for the data stage.
@param Timeout Indicates the maximum timeout, in millisecond.
@param Data Data buffer to be transmitted or received from USB device.
@param DataLength The size (in bytes) of the data buffer.
@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
PeiUsbControlTransfer (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *This,
IN EFI_USB_DEVICE_REQUEST *Request,
IN EFI_USB_DATA_DIRECTION Direction,
IN UINT32 Timeout,
IN OUT VOID *Data, OPTIONAL
IN UINTN DataLength OPTIONAL
);
/**
Submits bulk transfer to a bulk endpoint of a USB device.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param This The pointer of PEI_USB_IO_PPI.
@param DeviceEndpoint Endpoint number and its direction in bit 7.
@param Data A pointer to the buffer of data to transmit
from or receive into.
@param DataLength The lenght of the data buffer.
@param Timeout Indicates the maximum time, in millisecond, which the
transfer is allowed to complete.
@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 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
PeiUsbBulkTransfer (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *This,
IN UINT8 DeviceEndpoint,
IN OUT VOID *Data,
IN OUT UINTN *DataLength,
IN UINTN Timeout
);
/**
Get the usb interface descriptor.
@param PeiServices General-purpose services that are available to every PEIM.
@param This Indicates the PEI_USB_IO_PPI instance.
@param InterfaceDescriptor Request interface descriptor.
@retval EFI_SUCCESS Usb interface descriptor is obtained successfully.
**/
EFI_STATUS
EFIAPI
PeiUsbGetInterfaceDescriptor (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *This,
OUT EFI_USB_INTERFACE_DESCRIPTOR **InterfaceDescriptor
);
/**
Get the usb endpoint descriptor.
@param PeiServices General-purpose services that are available to every PEIM.
@param This Indicates the PEI_USB_IO_PPI instance.
@param EndpointIndex The valid index of the specified endpoint.
@param EndpointDescriptor Request endpoint descriptor.
@retval EFI_SUCCESS Usb endpoint descriptor is obtained successfully.
@retval EFI_NOT_FOUND Usb endpoint descriptor is NOT found.
**/
EFI_STATUS
EFIAPI
PeiUsbGetEndpointDescriptor (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *This,
IN UINT8 EndpointIndex,
OUT EFI_USB_ENDPOINT_DESCRIPTOR **EndpointDescriptor
);
/**
Reset the port and re-configure the usb device.
@param PeiServices General-purpose services that are available to every PEIM.
@param This Indicates the PEI_USB_IO_PPI instance.
@retval EFI_SUCCESS Usb device is reset and configured successfully.
@retval Others Other failure occurs.
**/
EFI_STATUS
EFIAPI
PeiUsbPortReset (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *This
);
/**
Send reset signal over the given root hub port.
@param PeiServices Describes the list of possible PEI Services.
@param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.
@param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.
@param PortNum The port to be reset.
@param RetryIndex The retry times.
**/
VOID
ResetRootPort (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,
IN PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi,
IN UINT8 PortNum,
IN UINT8 RetryIndex
);
#endif

View File

@ -0,0 +1,263 @@
/** @file
Defines the USB Host Controller PPI that provides I/O services for a USB Host
Controller that may be used to access recovery devices. These interfaces are
modeled on the UEFI 2.3 specification EFI_USB2_HOST_CONTROLLER_PROTOCOL.
Refer to section 16.1 of the UEFI 2.3 Specification for more information on
these interfaces.
Copyright (c) 2010, 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 _PEI_USB2_HOST_CONTROLLER_PPI_H_
#define _PEI_USB2_HOST_CONTROLLER_PPI_H_
#include <Protocol/Usb2HostController.h>
///
/// Global ID for the PEI_USB2_HOST_CONTROLLER_PPI.
///
#define PEI_USB2_HOST_CONTROLLER_PPI_GUID \
{ \
0xa7d09fe1, 0x74d4, 0x4ba5, { 0x84, 0x7c, 0x12, 0xed, 0x5b, 0x19, 0xad, 0xe4 } \
}
///
/// Forward declaration for the PEI_USB2_HOST_CONTROLLER_PPI.
///
typedef struct _PEI_USB2_HOST_CONTROLLER_PPI PEI_USB2_HOST_CONTROLLER_PPI;
/**
Initiate a USB control transfer using a specific USB Host controller on the USB bus.
@param[in] PeiServices The pointer to the PEI Services Table.
@param[in] This The pointer to this instance of the
PEI_USB2_HOST_CONTROLLER_PPI.
@param[in] DeviceAddress Represents the address of the target device
on the USB.
@param[in] DeviceSpeed Indicates device speed.
@param[in] MaximumPacketLength Indicates the maximum packet size that the
default control transfer
endpoint is capable of sending or receiving.
@param[in] Request A pointer to the USB device request that
will be sent to the USB device.
@param[in] TransferDirection Specifies the data direction for the transfer.
There are three values available:
EfiUsbDataIn, EfiUsbDataOut and EfiUsbNoData.
@param[in,out] Data A pointer to the buffer of data that will
be transmitted to USB device or
received from USB device.
@param[in,out] DataLength On input, indicates the size, in bytes, of
the data buffer specified by Data.
On output, indicates the amount of data
actually transferred.
@param[in] TimeOut Indicates the maximum time, in milliseconds,
that the transfer is allowed to complete.
@param[in] Translator A pointer to the transaction translator data.
@param[out] TransferResult A pointer to the detailed result information
generated by this control transfer.
@retval EFI_SUCCESS The control transfer was completed successfully.
@retval EFI_DEVICE_ERROR The control transfer failed due to host controller
or device error.
@retval EFI_INVALID_PARAMETER Some parameters are invalid.
@retval EFI_OUT_OF_RESOURCES The control transfer could not be completed due to a lack of resources.
@retval EFI_TIMEOUT The control transfer failed due to timeout.
**/
typedef
EFI_STATUS
(EFIAPI *PEI_USB2_HOST_CONTROLLER_CONTROL_TRANSFER)(
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB2_HOST_CONTROLLER_PPI *This,
IN UINT8 DeviceAddress,
IN UINT8 DeviceSpeed,
IN UINTN MaximumPacketLength,
IN USB_DEVICE_REQUEST *Request,
IN EFI_USB_DATA_DIRECTION TransferDirection,
IN OUT VOID *Data OPTIONAL,
IN OUT UINTN *DataLength OPTIONAL,
IN UINTN TimeOut,
IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
OUT UINT32 *TransferResult
);
/**
Initiate a USB bulk transfer using a specific USB Host controller on the USB bus.
@param[in] PeiServices The pointer to the PEI Services Table.
@param[in] This The pointer to this instance of the
PEI_USB2_HOST_CONTROLLER_PPI.
@param[in] DeviceAddress Represents the address of the target device
on the USB.
@param[in] EndPointAddress The combination of an endpoint number and
an endpoint direction of the target USB device.
@param[in] DeviceSpeed Indicates device speed.
@param[in] MaximumPacketLength Indicates the maximum packet size the target
endpoint is capable of sending or receiving.
@param[in,out] Data Array of pointers to the buffers of data
that will be transmitted to USB device or
received from USB device.
@param[in,out] DataLength When input, indicates the size, in bytes, of
the data buffers specified by Data. When output,
indicates the data size actually transferred.
@param[in,out] DataToggle A pointer to the data toggle value.
@param[in] TimeOut Indicates the maximum time, in milliseconds,
in which the transfer is allowed to complete.
@param[in] Translator A pointer to the transaction translator data.
@param[out] TransferResult A pointer to the detailed result information
of the bulk transfer.
@retval EFI_SUCCESS The bulk transfer was completed successfully.
@retval EFI_DEVICE_ERROR The bulk transfer failed due to host controller or device error.
Caller should check TransferResult for detailed error information.
@retval EFI_INVALID_PARAMETER Some parameters are invalid.
@retval EFI_OUT_OF_RESOURCES The bulk transfer could not be submitted due to a lack of resources.
@retval EFI_TIMEOUT The bulk transfer failed due to timeout.
**/
typedef
EFI_STATUS
(EFIAPI *PEI_USB2_HOST_CONTROLLER_BULK_TRANSFER)(
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB2_HOST_CONTROLLER_PPI *This,
IN UINT8 DeviceAddress,
IN UINT8 EndPointAddress,
IN UINT8 DeviceSpeed,
IN UINTN MaximumPacketLength,
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
);
/**
Retrieves the number of root hub ports.
@param[in] PeiServices The pointer to the PEI Services Table.
@param[in] This The pointer to this instance of the
PEI_USB2_HOST_CONTROLLER_PPI.
@param[out] PortNumber The pointer to the number of the root hub ports.
@retval EFI_SUCCESS The port number was retrieved successfully.
@retval EFI_INVALID_PARAMETER PortNumber is NULL.
**/
typedef
EFI_STATUS
(EFIAPI *PEI_USB2_HOST_CONTROLLER_GET_ROOTHUB_PORT_NUMBER)(
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB2_HOST_CONTROLLER_PPI *This,
OUT UINT8 *PortNumber
);
/**
Retrieves the current status of a USB root hub port.
@param[in] PeiServices The pointer to the PEI Services Table.
@param[in] This The pointer to this instance of the
PEI_USB2_HOST_CONTROLLER_PPI.
@param[in] PortNumber Specifies the root hub port from which the status is
to be retrieved.
This value is zero based.
@param[out] PortStatus A pointer to the current port status bits and port
status change bits.
@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.
**/
typedef
EFI_STATUS
(EFIAPI *PEI_USB2_HOST_CONTROLLER_GET_ROOTHUB_PORT_STATUS)(
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB2_HOST_CONTROLLER_PPI *This,
IN UINT8 PortNumber,
OUT EFI_USB_PORT_STATUS *PortStatus
);
/**
Sets a feature for the specified root hub port.
@param[in] PeiServices The pointer to the PEI Services Table.
@param[in] This The pointer to this instance of the
PEI_USB2_HOST_CONTROLLER_PPI.
@param[in] PortNumber Specifies the root hub port whose feature is requested
to be set. This value is zero based.
@param[in] PortFeature Indicates the feature selector associated with the feature
set request.
@retval EFI_SUCCESS The feature specified by PortFeature was set for
the USB root hub port specified by PortNumber.
@retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid
for this function.
@retval EFI_TIMEOUT The time out occurred
**/
typedef
EFI_STATUS
(EFIAPI *PEI_USB2_HOST_CONTROLLER_SET_ROOTHUB_PORT_FEATURE)(
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB2_HOST_CONTROLLER_PPI *This,
IN UINT8 PortNumber,
IN EFI_USB_PORT_FEATURE PortFeature
);
/**
Clears a feature for the specified root hub port.
@param[in] PeiServices The pointer to the PEI Services Table.
@param[in] This The pointer to this instance of the
PEI_USB2_HOST_CONTROLLER_PPI.
@param[in] PortNumber Specifies the root hub port whose feature is
requested to be cleared.
@param[in] PortFeature Indicates the feature selector associated with the
feature clear request.
@return EFI_SUCCESS The feature specified by PortFeature was cleared
for the USB root hub port specified by PortNumber.
@return EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
**/
typedef
EFI_STATUS
(EFIAPI *PEI_USB2_HOST_CONTROLLER_CLEAR_ROOTHUB_PORT_FEATURE)(
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB2_HOST_CONTROLLER_PPI *This,
IN UINT8 PortNumber,
IN EFI_USB_PORT_FEATURE PortFeature
);
///
/// This PPI contains a set of services to interact with the USB host controller.
/// These interfaces are modeled on the UEFI 2.3 specification protocol
/// EFI_USB2_HOST_CONTROLLER_PROTOCOL. Refer to section 16.1 of the UEFI 2.3
/// Specification for more information on these interfaces.
///
struct _PEI_USB2_HOST_CONTROLLER_PPI {
PEI_USB2_HOST_CONTROLLER_CONTROL_TRANSFER ControlTransfer;
PEI_USB2_HOST_CONTROLLER_BULK_TRANSFER BulkTransfer;
PEI_USB2_HOST_CONTROLLER_GET_ROOTHUB_PORT_NUMBER GetRootHubPortNumber;
PEI_USB2_HOST_CONTROLLER_GET_ROOTHUB_PORT_STATUS GetRootHubPortStatus;
PEI_USB2_HOST_CONTROLLER_SET_ROOTHUB_PORT_FEATURE SetRootHubPortFeature;
PEI_USB2_HOST_CONTROLLER_CLEAR_ROOTHUB_PORT_FEATURE ClearRootHubPortFeature;
};
extern EFI_GUID gPeiUsb2HostControllerPpiGuid;
#endif

View File

@ -0,0 +1,88 @@
/** @file
Define APIs to retrieve USB Host Controller Info such as controller type and
I/O Port Base Address.
Copyright (c) 2006 - 2010, 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 _PEI_USB_CONTROLLER_PPI_H_
#define _PEI_USB_CONTROLLER_PPI_H_
///
/// Global ID for the PEI_USB_CONTROLLER_PPI.
///
#define PEI_USB_CONTROLLER_PPI_GUID \
{ \
0x3bc1f6de, 0x693e, 0x4547,{ 0xa3, 0x0, 0x21, 0x82, 0x3c, 0xa4, 0x20, 0xb2} \
}
///
/// Forward declaration for the PEI_USB_CONTROLLER_PPI.
///
typedef struct _PEI_USB_CONTROLLER_PPI PEI_USB_CONTROLLER_PPI;
///
/// This bit is used in the ControllerType return parameter of GetUsbController()
/// to identify the USB Host Controller type as UHCI
///
#define PEI_UHCI_CONTROLLER 0x01
///
/// This bit is used in the ControllerType return parameter of GetUsbController()
/// to identify the USB Host Controller type as OHCI
///
#define PEI_OHCI_CONTROLLER 0x02
///
/// This bit is used in the ControllerType return parameter of GetUsbController()
/// to identify the USB Host Controller type as EHCI
///
#define PEI_EHCI_CONTROLLER 0x03
/**
Retrieve USB Host Controller Info such as controller type and I/O Base Address.
@param[in] PeiServices The pointer to the PEI Services Table.
@param[in] This The pointer to this instance of the PEI_USB_CONTROLLER_PPI.
@param[in] ControllerId The ID of the USB controller.
@param[out] ControllerType On output, returns the type of the USB controller.
@param[out] BaseAddress On output, returns the base address of UHCI's I/O ports
if UHCI is enabled or the base address of EHCI's MMIO
if EHCI is enabled.
@retval EFI_SUCCESS USB controller attributes were returned successfully.
@retval EFI_INVALID_PARAMETER ControllerId is greater than the maximum number
of USB controller supported by this platform.
**/
typedef
EFI_STATUS
(EFIAPI *PEI_GET_USB_CONTROLLER)(
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_CONTROLLER_PPI *This,
IN UINT8 UsbControllerId,
OUT UINTN *ControllerType,
OUT UINTN *BaseAddress
);
///
/// This PPI contains a single service to retrieve the USB Host Controller type
/// and the base address of the I/O ports used to access the USB Host Controller.
///
struct _PEI_USB_CONTROLLER_PPI {
PEI_GET_USB_CONTROLLER GetUsbController;
};
extern EFI_GUID gPeiUsbControllerPpiGuid;
#endif

View File

@ -0,0 +1,251 @@
/** @file
Defines the USB Host Controller PPI that provides I/O services for a USB Host
Controller that may be used to access recovery devices. These interfaces are
modeled on the UEFI 2.3 specification EFI_USB2_HOST_CONTROLLER_PROTOCOL.
Refer to section 16.1 of the UEFI 2.3 Specification for more information on
these interfaces.
Copyright (c) 2006 - 2010, 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 _PEI_USB_HOST_CONTROLLER_PPI_H_
#define _PEI_USB_HOST_CONTROLLER_PPI_H_
#include <Protocol/Usb2HostController.h>
///
/// Global ID for the PEI_USB_HOST_CONTROLLER_PPI.
///
#define PEI_USB_HOST_CONTROLLER_PPI_GUID \
{ \
0x652b38a9, 0x77f4, 0x453f, { 0x89, 0xd5, 0xe7, 0xbd, 0xc3, 0x52, 0xfc, 0x53} \
}
///
/// Forward declaration for the PEI_USB_HOST_CONTROLLER_PPI.
///
typedef struct _PEI_USB_HOST_CONTROLLER_PPI PEI_USB_HOST_CONTROLLER_PPI;
/**
Initiate a USB control transfer using a specific USB Host controller on the USB bus.
@param[in] PeiServices The pointer to the PEI Services Table.
@param[in] This The pointer to this instance of the
PEI_USB_HOST_CONTROLLER_PPI.
@param[in] DeviceAddress Represents the address of the target device
on the USB.
@param[in] DeviceSpeed Indicates device speed.
@param[in] MaximumPacketLength Indicates the maximum packet size that the
default control transfer
endpoint is capable of sending or receiving.
@param[in] Request A pointer to the USB device request that
will be sent to the USB device.
@param[in] TransferDirection Specifies the data direction for the transfer.
There are three values available:
EfiUsbDataIn, EfiUsbDataOut and EfiUsbNoData.
@param[in,out] Data A pointer to the buffer of data that will
be transmitted to USB device or
received from USB device.
@param[in,out] DataLength On input, indicates the size, in bytes, of
the data buffer specified by Data.
On output, indicates the amount of data
actually transferred.
@param[in] TimeOut Indicates the maximum time, in milliseconds,
that the transfer is allowed to complete.
@param[out] TransferResult A pointer to the detailed result information
generated by this control transfer.
@retval EFI_DEVICE_ERROR The control transfer failed due to host controller
or device error.
@retval EFI_SUCCESS The control transfer was completed successfully.
**/
typedef
EFI_STATUS
(EFIAPI *PEI_USB_HOST_CONTROLLER_CONTROL_TRANSFER)(
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_HOST_CONTROLLER_PPI *This,
IN UINT8 DeviceAddress,
IN UINT8 DeviceSpeed,
IN UINT8 MaximumPacketLength,
IN USB_DEVICE_REQUEST *Request,
IN EFI_USB_DATA_DIRECTION TransferDirection,
IN OUT VOID *Data OPTIONAL,
IN OUT UINTN *DataLength OPTIONAL,
IN UINTN TimeOut,
OUT UINT32 *TransferResult
);
/**
Initiate a USB bulk transfer using a specific USB Host controller on the USB bus.
@param[in] PeiServices The pointer to the PEI Services Table.
@param[in] This The pointer to this instance of the
PEI_USB_HOST_CONTROLLER_PPI.
@param[in] DeviceAddress Represents the address of the target device
on the USB.
@param[in] EndPointAddress The combination of an endpoint number and
an endpoint direction of the target USB device.
@param[in] MaximumPacketLength Indicates the maximum packet size the target
endpoint is capable of sending or receiving.
@param[in,out] Data Array of pointers to the buffers of data
that will be transmitted to USB device or
received from USB device.
@param[in,out] DataLength When input, indicates the size, in bytes, of
the data buffers specified by Data. When output,
indicates the data size actually transferred.
@param[in,out] DataToggle A pointer to the data toggle value.
@param[in] TimeOut Indicates the maximum time, in milliseconds,
in which the transfer is allowed to complete.
@param[out] TransferResult A pointer to the detailed result information
of the bulk transfer.
@retval EFI_SUCCESS The bulk transfer was completed successfully.
@retval EFI_DEVICE_ERROR The bulk transfer failed due to host controller or device error.
Caller should check TransferResult for detailed error information.
**/
typedef
EFI_STATUS
(EFIAPI *PEI_USB_HOST_CONTROLLER_BULK_TRANSFER)(
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_HOST_CONTROLLER_PPI *This,
IN UINT8 DeviceAddress,
IN UINT8 EndPointAddress,
IN UINT8 MaximumPacketLength,
IN OUT VOID *Data,
IN OUT UINTN *DataLength,
IN OUT UINT8 *DataToggle,
IN UINTN TimeOut,
OUT UINT32 *TransferResult
);
/**
Retrieves the number of root hub ports.
@param[in] PeiServices The pointer to the PEI Services Table.
@param[in] This The pointer to this instance of the
PEI_USB_HOST_CONTROLLER_PPI.
@param[out] PortNumber The pointer to the number of the root hub ports.
@retval EFI_SUCCESS The port number was retrieved successfully.
@retval EFI_DEVICE_ERROR An error was encountered while attempting to retrieve
the port number.
@retval EFI_INVALID_PARAMETER PortNumber is NULL.
**/
typedef
EFI_STATUS
(EFIAPI *PEI_USB_HOST_CONTROLLER_GET_ROOTHUB_PORT_NUMBER)(
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_HOST_CONTROLLER_PPI *This,
OUT UINT8 *PortNumber
);
/**
Retrieves the current status of a USB root hub port.
@param[in] PeiServices The pointer to the PEI Services Table.
@param[in] This The pointer to this instance of the
PEI_USB_HOST_CONTROLLER_PPI.
@param[in] PortNumber Specifies the root hub port from which the status is
to be retrieved.
This value is zero based.
@param[out] PortStatus A pointer to the current port status bits and port
status change bits.
@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.
**/
typedef
EFI_STATUS
(EFIAPI *PEI_USB_HOST_CONTROLLER_GET_ROOTHUB_PORT_STATUS)(
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_HOST_CONTROLLER_PPI *This,
IN UINT8 PortNumber,
OUT EFI_USB_PORT_STATUS *PortStatus
);
/**
Sets a feature for the specified root hub port.
@param[in] PeiServices The pointer to the PEI Services Table.
@param[in] This The pointer to this instance of the
PEI_USB_HOST_CONTROLLER_PPI.
@param[in] PortNumber Specifies the root hub port whose feature is requested
to be set. This value is zero based.
@param[in] PortFeature Indicates the feature selector associated with the feature
set request.
@retval EFI_SUCCESS The feature specified by PortFeature was set for
the USB root hub port specified by PortNumber.
@retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid
for this function.
**/
typedef
EFI_STATUS
(EFIAPI *PEI_USB_HOST_CONTROLLER_SET_ROOTHUB_PORT_FEATURE)(
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_HOST_CONTROLLER_PPI *This,
IN UINT8 PortNumber,
IN EFI_USB_PORT_FEATURE PortFeature
);
/**
Clears a feature for the specified root hub port.
@param[in] PeiServices The pointer to the PEI Services Table.
@param[in] This The pointer to this instance of the
PEI_USB_HOST_CONTROLLER_PPI.
@param[in] PortNumber Specifies the root hub port whose feature is
requested to be cleared.
@param[in] PortFeature Indicates the feature selector associated with the
feature clear request.
@return EFI_SUCCESS The feature specified by PortFeature was cleared
for the USB root hub port specified by PortNumber.
@return EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
@return EFI_DEVICE_ERROR Can't read the register.
**/
typedef
EFI_STATUS
(EFIAPI *PEI_USB_HOST_CONTROLLER_CLEAR_ROOTHUB_PORT_FEATURE)(
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_HOST_CONTROLLER_PPI *This,
IN UINT8 PortNumber,
IN EFI_USB_PORT_FEATURE PortFeature
);
///
/// This PPI contains a set of services to interact with the USB host controller.
/// These interfaces are modeled on the UEFI 2.3 specification protocol
/// EFI_USB2_HOST_CONTROLLER_PROTOCOL. Refer to section 16.1 of the UEFI 2.3
/// Specification for more information on these interfaces.
///
struct _PEI_USB_HOST_CONTROLLER_PPI {
PEI_USB_HOST_CONTROLLER_CONTROL_TRANSFER ControlTransfer;
PEI_USB_HOST_CONTROLLER_BULK_TRANSFER BulkTransfer;
PEI_USB_HOST_CONTROLLER_GET_ROOTHUB_PORT_NUMBER GetRootHubPortNumber;
PEI_USB_HOST_CONTROLLER_GET_ROOTHUB_PORT_STATUS GetRootHubPortStatus;
PEI_USB_HOST_CONTROLLER_SET_ROOTHUB_PORT_FEATURE SetRootHubPortFeature;
PEI_USB_HOST_CONTROLLER_CLEAR_ROOTHUB_PORT_FEATURE ClearRootHubPortFeature;
};
extern EFI_GUID gPeiUsbHostControllerPpiGuid;
#endif

View File

@ -0,0 +1,190 @@
/** @file
Defines the PEI_USB_IO_PPI that the USB-related PEIM can use for I/O operations
on the USB BUS. This interface enables recovery from a
USB-class storage device, such as USB CD/DVD, USB hard drive, or USB FLASH
drive. These interfaces are modeled on the UEFI 2.3 specification EFI_USB_IO_PROTOCOL.
Refer to section 16.2.4 of the UEFI 2.3 Specification for more information on
these interfaces.
Copyright (c) 2006 - 2010, 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 _PEI_USB_IO_PPI_H_
#define _PEI_USB_IO_PPI_H_
#include <Protocol/Usb2HostController.h>
///
/// Global ID for the PEI_USB_IO_PPI.
///
#define PEI_USB_IO_PPI_GUID \
{ \
0x7c29785c, 0x66b9, 0x49fc, { 0xb7, 0x97, 0x1c, 0xa5, 0x55, 0xe, 0xf2, 0x83} \
}
///
/// Forward declaration for the PEI_USB_IO_PPI.
///
typedef struct _PEI_USB_IO_PPI PEI_USB_IO_PPI;
/**
Submits control transfer to a target USB device.
@param[in] PeiServices The pointer to the PEI Services Table.
@param[in] This The pointer to this instance of the PEI_USB_IO_PPI.
@param[in] Request A pointer to the USB device request that will be
sent to the USB device.
@param[in] Direction Specifies the data direction for the transfer. There
are three values available:
EfiUsbDataIn, EfiUsbDataOut and EfiUsbNoData.
@param[in] TimeOut Indicates the maximum time, in milliseconds, that
the transfer is allowed to complete.
@param[in,out] Data A pointer to the buffer of data that will be
transmitted to or received from the USB device.
@param[in] DataLength On input, indicates the size, in bytes, of the data
buffer specified by Data.
@retval EFI_SUCCESS The control transfer was completed successfully.
@retval EFI_INVALID_PARAMETER Some parameters are invalid.
@retval EFI_OUT_OF_RESOURCES The control transfer could not be completed due
to a lack of resources.
@retval EFI_TIMEOUT The control transfer failed due to timeout.
@retval EFI_DEVICE_ERROR The control transfer failed due to host controller
or device error.
Caller should check TransferResult for detailed
error information.
**/
typedef
EFI_STATUS
(EFIAPI *PEI_USB_CONTROL_TRANSFER)(
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *This,
IN EFI_USB_DEVICE_REQUEST *Request,
IN EFI_USB_DATA_DIRECTION Direction,
IN UINT32 Timeout,
IN OUT VOID *Data OPTIONAL,
IN UINTN DataLength OPTIONAL
);
/**
Submits bulk transfer to a target USB device.
@param[in] PeiServices The pointer to the PEI Services Table.
@param[in] This The pointer to this instance of the PEI_USB_IO_PPI.
@param[in] EndPointAddress The endpoint address.
@param[in] Data The data buffer to be transfered.
@param[in] DataLength The length of data buffer.
@param[in] TimeOut The timeout for the transfer, in milliseconds.
@retval EFI_SUCCESS The bulk transfer completed successfully.
@retval EFI_INVALID_PARAMETER Some parameters are invalid.
@retval EFI_OUT_OF_RESOURCES The bulk transfer could not be completed due to
a lack of resources.
@retval EFI_TIMEOUT The bulk transfer failed due to timeout.
@retval EFI_DEVICE_ERROR The bulk transfer failed due to host controller
or device error.
Caller should check TransferResult for detailed
error information.
**/
typedef
EFI_STATUS
(EFIAPI *PEI_USB_BULK_TRANSFER)(
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *This,
IN UINT8 DeviceEndpoint,
IN OUT VOID *Data,
IN OUT UINTN *DataLength,
IN UINTN Timeout
);
/**
Get interface descriptor from a USB device.
@param[in] PeiServices The pointer to the PEI Services Table.
@param[in] This The pointer to this instance of the PEI_USB_IO_PPI.
@param[in] InterfaceDescriptor The interface descriptor.
@retval EFI_SUCCESS The interface descriptor was returned.
@retval EFI_INVALID_PARAMETER Some parameters are invalid.
@retval EFI_DEVICE_ERROR A device error occurred, the function failed to
get the interface descriptor.
**/
typedef
EFI_STATUS
(EFIAPI *PEI_USB_GET_INTERFACE_DESCRIPTOR)(
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *This,
IN EFI_USB_INTERFACE_DESCRIPTOR **InterfaceDescriptor
);
/**
Get endpoint descriptor from a USB device.
@param[in] PeiServices The pointer to the PEI Services Table.
@param[in] This The pointer to this instance of the PEI_USB_IO_PPI.
@param[in] EndPointIndex The index of the end point.
@param[in] EndpointDescriptor The endpoint descriptor.
@retval EFI_SUCCESS The endpoint descriptor was returned.
@retval EFI_INVALID_PARAMETER Some parameters are invalid.
@retval EFI_DEVICE_ERROR A device error occurred, the function failed to
get the endpoint descriptor.
**/
typedef
EFI_STATUS
(EFIAPI *PEI_USB_GET_ENDPOINT_DESCRIPTOR)(
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *This,
IN UINT8 EndpointIndex,
IN EFI_USB_ENDPOINT_DESCRIPTOR **EndpointDescriptor
);
/**
Issue a port reset to the device.
@param[in] PeiServices The pointer to the PEI Services Table.
@param[in] This The pointer to this instance of the PEI_USB_IO_PPI.
@retval EFI_SUCCESS The port reset was issued successfully.
@retval EFI_INVALID_PARAMETER Some parameters are invalid.
@retval EFI_DEVICE_ERROR Device error occurred.
**/
typedef
EFI_STATUS
(EFIAPI *PEI_USB_PORT_RESET)(
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *This
);
///
/// This PPI contains a set of services to interact with the USB host controller.
/// These interfaces are modeled on the UEFI 2.3 specification EFI_USB_IO_PROTOCOL.
/// Refer to section 16.2.4 of the UEFI 2.3 Specification for more information on
/// these interfaces.
///
struct _PEI_USB_IO_PPI {
PEI_USB_CONTROL_TRANSFER UsbControlTransfer;
PEI_USB_BULK_TRANSFER UsbBulkTransfer;
PEI_USB_GET_INTERFACE_DESCRIPTOR UsbGetInterfaceDescriptor;
PEI_USB_GET_ENDPOINT_DESCRIPTOR UsbGetEndpointDescriptor;
PEI_USB_PORT_RESET UsbPortReset;
};
extern EFI_GUID gPeiUsbIoPpiGuid;
#endif

View File

@ -173,6 +173,19 @@
# Include/Guid/EventIdle.h
gIdleLoopEventGuid = { 0x3c8d294c, 0x5fc3, 0x4451, { 0xbb, 0x31, 0xc4, 0xc0, 0x32, 0x29, 0x5e, 0x6c } }
[Ppis]
## Include/Ppi/UsbHostController.h
gPeiUsbHostControllerPpiGuid = { 0x652B38A9, 0x77F4, 0x453F, { 0x89, 0xD5, 0xE7, 0xBD, 0xC3, 0x52, 0xFC, 0x53 }}
## Include/Ppi/Usb2HostController.h
gPeiUsb2HostControllerPpiGuid = { 0xfedd6305, 0xe2d7, 0x4ed5, { 0x9f, 0xaa, 0xda, 0x8, 0xe, 0x33, 0x6c, 0x22 }}
## Include/Ppi/UsbController.h
gPeiUsbControllerPpiGuid = { 0x3BC1F6DE, 0x693E, 0x4547, { 0xA3, 0x00, 0x21, 0x82, 0x3C, 0xA4, 0x20, 0xB2 }}
## Include/Ppi/UsbIo.h
gPeiUsbIoPpiGuid = { 0x7C29785C, 0x66B9, 0x49FC, { 0xB7, 0x97, 0x1C, 0xA5, 0x55, 0x0E, 0xF2, 0x83 }}
[Protocols]
## Load File protocol provides capability to load and unload EFI image into memory and execute it.
# Include/Protocol/LoadPe32Image.h

View File

@ -185,6 +185,10 @@
MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupportDxe.inf
MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf
MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf
MdeModulePkg/Bus/Pci/UhciPei/UhciPei.inf
MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf
MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPei.inf
MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf