mirror of https://github.com/acidanthera/audk.git
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:
parent
366f81a016
commit
4b1bf81c20
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
|
@ -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) {
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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 ;
|
||||
}
|
|
@ -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
|
@ -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
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue