312 lines
9.0 KiB
C
312 lines
9.0 KiB
C
/** @file
|
|
CBI Transportation implementation
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2012, Insyde Software Corp. All Rights Reserved.
|
|
;*
|
|
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
|
|
;* transmit, broadcast, present, recite, release, license or otherwise exploit
|
|
;* any part of this publication in any form, by any means, without the prior
|
|
;* written permission of Insyde Software Corporation.
|
|
;*
|
|
;******************************************************************************
|
|
*/
|
|
|
|
#include "UsbMassStoragePei.h"
|
|
|
|
typedef struct
|
|
{
|
|
UINT8 bType;
|
|
UINT8 bValue;
|
|
} INTERRUPT_DATA_BLOCK;
|
|
|
|
/**
|
|
|
|
Send the command to the device using control endpoint.
|
|
|
|
@param PeiServices General purpose services that are available to every PEIM.
|
|
@param PeiBlkIoDev Indicates the PEI_BLKIO_DEVICE instance.
|
|
@param Command The command to transfer to device.
|
|
@param CommandSize The length of the command.
|
|
@param Timeout Indicates the maximum time, in millisecond, which the transfer is allowed to complete.
|
|
|
|
@retval EFI_SUCCESS Successful to send the command to device.
|
|
@retval EFI_DEVICE_ERROR Failed to send the command to device.
|
|
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
CbiCommandPhase (
|
|
IN EFI_PEI_SERVICES **PeiServices,
|
|
IN PEI_BLKIO_DEVICE *PeiBlkIoDev,
|
|
IN VOID *Command,
|
|
IN UINT8 CommandSize,
|
|
IN UINT16 Timeout
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
PEI_USB3_IO_PPI *UsbIoPpi;
|
|
EFI_USB_DEVICE_REQUEST Request;
|
|
|
|
UsbIoPpi = PeiBlkIoDev->UsbIoPpi;
|
|
|
|
ZeroMem (&Request, sizeof(EFI_USB_DEVICE_REQUEST));
|
|
|
|
//
|
|
// Device request see CBI specification
|
|
//
|
|
Request.RequestType = 0x21;
|
|
Request.Request = 0x00;
|
|
Request.Value = 0 ;
|
|
Request.Index = 0 ;
|
|
Request.Length = CommandSize;
|
|
|
|
Status = UsbIoPpi->UsbControlTransfer(
|
|
PeiServices,
|
|
UsbIoPpi,
|
|
&Request,
|
|
EfiUsbDataOut,
|
|
Timeout,
|
|
Command,
|
|
CommandSize
|
|
);
|
|
|
|
if (EFI_ERROR(Status)) {
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
Transfer the data between the device and host.
|
|
|
|
@param PeiServices General purpose services that are available to every PEIM.
|
|
@param PeiBlkIoDev Indicates the PEI_BLKIO_DEVICE instance.
|
|
@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_SUCCESS Successful to send the data to device.
|
|
@retval EFI_DEVICE_ERROR Failed to send the data to device.
|
|
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
CbiDataPhase (
|
|
IN EFI_PEI_SERVICES **PeiServices,
|
|
IN PEI_BLKIO_DEVICE *PeiBlkIoDev,
|
|
IN UINT32 *DataSize,
|
|
IN OUT VOID *DataBuffer,
|
|
IN EFI_USB_DATA_DIRECTION Direction,
|
|
IN UINT16 Timeout
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
PEI_USB3_IO_PPI *UsbIoPpi;
|
|
UINT8 EndpointAddr;
|
|
UINTN Remain;
|
|
UINTN Increment;
|
|
UINT32 MaxPacketLen;
|
|
UINT8 *BufferPtr;
|
|
UINTN TransferredSize;
|
|
|
|
UsbIoPpi = PeiBlkIoDev->UsbIoPpi;
|
|
|
|
Remain = *DataSize;
|
|
BufferPtr = (UINT8 *)DataBuffer;
|
|
TransferredSize = 0;
|
|
|
|
//
|
|
// retrieve the the max packet length of the given endpoint
|
|
//
|
|
if ( Direction == EfiUsbDataIn ) {
|
|
MaxPacketLen = (PeiBlkIoDev->BulkInEndpoint)->MaxPacketSize;
|
|
EndpointAddr = (PeiBlkIoDev->BulkInEndpoint)->EndpointAddress;
|
|
} else {
|
|
MaxPacketLen = (PeiBlkIoDev->BulkOutEndpoint)->MaxPacketSize;
|
|
EndpointAddr = (PeiBlkIoDev->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)) {
|
|
UsbIoPpi->UsbClearEndpointHalt (PeiServices, UsbIoPpi, EndpointAddr);
|
|
return Status;
|
|
}
|
|
|
|
BufferPtr += Increment;
|
|
Remain -= Increment;
|
|
}
|
|
|
|
*DataSize = TransferredSize;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
|
|
Get the command execution status from device.
|
|
|
|
@param PeiServices General purpose services that are available to every PEIM.
|
|
@param PeiBlkIoDev Indicates the PEI_BLKIO_DEVICE instance.
|
|
@param InterruptDataBlock The status of the transaction.
|
|
@param Timeout Indicates the maximum time, in millisecond, which the transfer is allowed to complete.
|
|
|
|
@retval EFI_SUCCESS Successful to get the status of device.
|
|
@retval EFI_DEVICE_ERROR Failed to get the status of device.
|
|
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
CbiStatusPhase (
|
|
IN EFI_PEI_SERVICES **PeiServices,
|
|
IN PEI_BLKIO_DEVICE *PeiBlkIoDev,
|
|
OUT INTERRUPT_DATA_BLOCK *InterruptDataBlock,
|
|
IN UINT16 Timeout
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
PEI_USB3_IO_PPI *UsbIoPpi;
|
|
UINT8 EndpointAddr;
|
|
UINTN InterruptDataBlockLength;
|
|
|
|
UsbIoPpi = PeiBlkIoDev->UsbIoPpi;
|
|
|
|
ZeroMem (InterruptDataBlock,sizeof (INTERRUPT_DATA_BLOCK));
|
|
|
|
EndpointAddr = (PeiBlkIoDev->InterruptEndpoint)->EndpointAddress;
|
|
|
|
InterruptDataBlockLength = sizeof(INTERRUPT_DATA_BLOCK);
|
|
|
|
//
|
|
// Get the status field from Interrupt transfer
|
|
//
|
|
Status = UsbIoPpi->UsbSyncInterruptTransfer(
|
|
PeiServices,
|
|
UsbIoPpi,
|
|
EndpointAddr,
|
|
InterruptDataBlock,
|
|
&InterruptDataBlockLength,
|
|
Timeout
|
|
);
|
|
if (EFI_ERROR(Status)) {
|
|
UsbIoPpi->UsbClearEndpointHalt (PeiServices, UsbIoPpi, EndpointAddr);
|
|
PeiBlkIoDev->StallPpi->Stall (
|
|
(CONST EFI_PEI_SERVICES **)PeiServices,
|
|
PeiBlkIoDev->StallPpi,
|
|
10000
|
|
);
|
|
return Status;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
|
|
Send ATAPI command using CBI protocol.
|
|
|
|
@param PeiServices General purpose services that are available to every PEIM.
|
|
@param PeiBlkIoDev Indicates the PEI_BLKIO_DEVICE instance.
|
|
@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_SUCCESS Command executed successfully.
|
|
@retval EFI_DEVICE_ERROR Some device errors happen.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
PeiCbiAtapiCommand (
|
|
IN EFI_PEI_SERVICES **PeiServices,
|
|
IN PEI_BLKIO_DEVICE *PeiBlkIoDev,
|
|
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 CbiDataStatus = EFI_SUCCESS;
|
|
UINT32 BufferSize;
|
|
INTERRUPT_DATA_BLOCK InterruptDataBlock;
|
|
//
|
|
// First send ATAPI command through Bot
|
|
//
|
|
Status = CbiCommandPhase(
|
|
PeiServices,
|
|
PeiBlkIoDev,
|
|
Command,
|
|
CommandSize,
|
|
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;
|
|
|
|
CbiDataStatus = CbiDataPhase(
|
|
PeiServices,
|
|
PeiBlkIoDev,
|
|
&BufferSize,
|
|
DataBuffer,
|
|
Direction,
|
|
TimeOutInMilliSeconds
|
|
);
|
|
break;
|
|
|
|
case EfiUsbNoData:
|
|
break ;
|
|
}
|
|
if(EFI_ERROR(CbiDataStatus)) {
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
//
|
|
// Status Phase
|
|
//
|
|
Status = CbiStatusPhase(
|
|
PeiServices,
|
|
PeiBlkIoDev,
|
|
&InterruptDataBlock,
|
|
TimeOutInMilliSeconds
|
|
);
|
|
if (EFI_ERROR(Status)) {
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
return Status;
|
|
} |