Changes for V4 ============== 1) Remove Unicode character from C source file 2) Move delete of QuarkSocPkg\QuarkNorthCluster\Binary\QuarkMicrocode from QuarkPlatformPkg commit to QuarkSocPkg commit Changes for V2 ============== 1) Sync with new APIs in SmmCpuFeaturesLib class 2) Use new generic PCI serial driver PciSioSerialDxe in MdeModulePkg 3) Remove PCI serial driver from QuarkSocPkg 4) Apply optimizations to MtrrLib from MtrrLib in UefiCpuPkg 5) Convert all UNI files to utf-8 6) Replace tabs with spaces and remove trailing spaces 7) Add License.txt Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Michael Kinney <michael.d.kinney@intel.com> Acked-by: Jordan Justen <jordan.l.justen@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19286 6f19259b-4bc3-4df7-8a09-765794883524
397 lines
11 KiB
C
397 lines
11 KiB
C
/** @file
|
|
|
|
Block I/O protocol for CE-ATA device
|
|
|
|
Copyright (c) 2013-2015 Intel Corporation.
|
|
|
|
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 "SDMediaDevice.h"
|
|
|
|
/**
|
|
Implements EFI_BLOCK_IO_PROTOCOL.Reset() function.
|
|
|
|
@param This The EFI_BLOCK_IO_PROTOCOL instance.
|
|
@param ExtendedVerification Indicates that the driver may perform a more exhaustive.
|
|
verification operation of the device during reset.
|
|
(This parameter is ingored in this driver.)
|
|
|
|
@retval EFI_SUCCESS Success
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
CEATABlockReset (
|
|
IN EFI_BLOCK_IO_PROTOCOL *This,
|
|
IN BOOLEAN ExtendedVerification
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
CARD_DATA *CardData;
|
|
EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
|
|
|
|
CardData = CARD_DATA_FROM_THIS(This);
|
|
SDHostIo = CardData->SDHostIo;
|
|
|
|
if (!ExtendedVerification) {
|
|
Status = SoftwareReset (CardData);
|
|
} else {
|
|
Status = SDHostIo->ResetSDHost (SDHostIo, Reset_DAT_CMD);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG((EFI_D_ERROR, "CEATABlockReset: Fail to ResetSDHost\n" ));
|
|
return Status;
|
|
}
|
|
Status = MMCSDCardInit (CardData);
|
|
}
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
/**
|
|
Implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks() function.
|
|
|
|
@param This The EFI_BLOCK_IO_PROTOCOL instance.
|
|
@param MediaId The media id that the write request is for.
|
|
@param LBA The starting logical block address to read from on the device.
|
|
The caller is responsible for writing to only legitimate locations.
|
|
@param BufferSize The size of the Buffer in bytes. This must be a multiple of the
|
|
intrinsic block size of the device.
|
|
@param Buffer A pointer to the destination buffer for the data. The caller
|
|
is responsible for either having implicit or explicit ownership
|
|
of the buffer.
|
|
|
|
@retval EFI_SUCCESS Success
|
|
@retval EFI_DEVICE_ERROR Hardware Error
|
|
@retval EFI_INVALID_PARAMETER Parameter is error
|
|
@retval EFI_NO_MEDIA No media
|
|
@retval EFI_MEDIA_CHANGED Media Change
|
|
@retval EFI_BAD_BUFFER_SIZE Buffer size is bad
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
CEATABlockReadBlocks (
|
|
IN EFI_BLOCK_IO_PROTOCOL *This,
|
|
IN UINT32 MediaId,
|
|
IN EFI_LBA LBA,
|
|
IN UINTN BufferSize,
|
|
OUT VOID *Buffer
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
CARD_DATA *CardData;
|
|
UINT32 TransferSize;
|
|
UINT8 *pBuf;
|
|
UINT32 Index;
|
|
UINT64 Address;
|
|
UINT32 Remainder;
|
|
UINT64 CEATALBA;
|
|
UINT32 BoundarySize;
|
|
|
|
Status = EFI_SUCCESS;
|
|
CardData = CARD_DATA_FROM_THIS(This);
|
|
pBuf = Buffer;
|
|
Index = 0;
|
|
Address = MultU64x32(LBA, CardData->BlockIoMedia.BlockSize);
|
|
BoundarySize = CardData->SDHostIo->HostCapability.BoundarySize;
|
|
|
|
if (!Buffer) {
|
|
Status = EFI_INVALID_PARAMETER;
|
|
DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Invalid parameter\n" ));
|
|
goto Exit;
|
|
}
|
|
|
|
if (MediaId != CardData->BlockIoMedia.MediaId) {
|
|
Status = EFI_MEDIA_CHANGED;
|
|
DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Media changed\n" ));
|
|
goto Exit;
|
|
}
|
|
|
|
if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) {
|
|
Status = EFI_BAD_BUFFER_SIZE;
|
|
DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Bad buffer size\n" ));
|
|
goto Exit;
|
|
}
|
|
|
|
if (BufferSize == 0) {
|
|
Status = EFI_SUCCESS;
|
|
goto Exit;
|
|
}
|
|
|
|
if ((Address + BufferSize) > MultU64x32 (CardData->BlockIoMedia.LastBlock + 1, CardData->BlockIoMedia.BlockSize)) {
|
|
Status = EFI_INVALID_PARAMETER;
|
|
DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Invalid parameter\n" ));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
do {
|
|
if (BufferSize < BoundarySize) {
|
|
TransferSize = (UINT32)BufferSize;
|
|
} else {
|
|
TransferSize = BoundarySize;
|
|
}
|
|
|
|
Address += Index * TransferSize;
|
|
CEATALBA = DivU64x32Remainder (Address, DATA_UNIT_SIZE, &Remainder);
|
|
ASSERT(Remainder == 0);
|
|
|
|
Status = ReadDMAExt (
|
|
CardData,
|
|
CEATALBA,
|
|
pBuf,
|
|
(UINT16)(TransferSize / DATA_UNIT_SIZE)
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG((EFI_D_ERROR, "Read Failed at 0x%x, Index %d, Size 0x%x\n", Address, Index, TransferSize));
|
|
This->Reset (This, TRUE);
|
|
goto Exit;
|
|
}
|
|
BufferSize -= TransferSize;
|
|
pBuf += TransferSize;
|
|
Index ++;
|
|
} while (BufferSize != 0);
|
|
|
|
|
|
Exit:
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks() function.
|
|
|
|
@param This The EFI_BLOCK_IO_PROTOCOL instance.
|
|
@param MediaId The media id that the write request is for.
|
|
@param LBA The starting logical block address to read from on the device.
|
|
The caller is responsible for writing to only legitimate locations.
|
|
@param BufferSize The size of the Buffer in bytes. This must be a multiple of the
|
|
intrinsic block size of the device.
|
|
@param Buffer A pointer to the destination buffer for the data. The caller
|
|
is responsible for either having implicit or explicit ownership
|
|
of the buffer.
|
|
|
|
@retval EFI_SUCCESS Success
|
|
@retval EFI_DEVICE_ERROR Hardware Error
|
|
@retval EFI_INVALID_PARAMETER Parameter is error
|
|
@retval EFI_NO_MEDIA No media
|
|
@retval EFI_MEDIA_CHANGED Media Change
|
|
@retval EFI_BAD_BUFFER_SIZE Buffer size is bad
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
CEATABlockWriteBlocks (
|
|
IN EFI_BLOCK_IO_PROTOCOL *This,
|
|
IN UINT32 MediaId,
|
|
IN EFI_LBA LBA,
|
|
IN UINTN BufferSize,
|
|
IN VOID *Buffer
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
CARD_DATA *CardData;
|
|
UINT32 TransferSize;
|
|
UINT8 *pBuf;
|
|
UINT32 Index;
|
|
UINT64 Address;
|
|
UINT32 Remainder;
|
|
UINT64 CEATALBA;
|
|
UINT32 BoundarySize;
|
|
|
|
|
|
Status = EFI_SUCCESS;
|
|
CardData = CARD_DATA_FROM_THIS(This);
|
|
pBuf = Buffer;
|
|
Index = 0;
|
|
Address = MultU64x32(LBA, CardData->BlockIoMedia.BlockSize);
|
|
BoundarySize = CardData->SDHostIo->HostCapability.BoundarySize;
|
|
|
|
|
|
if (!Buffer) {
|
|
Status = EFI_INVALID_PARAMETER;
|
|
goto Exit;
|
|
}
|
|
|
|
if (MediaId != CardData->BlockIoMedia.MediaId) {
|
|
Status = EFI_MEDIA_CHANGED;
|
|
goto Exit;
|
|
}
|
|
|
|
if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) {
|
|
Status = EFI_BAD_BUFFER_SIZE;
|
|
goto Exit;
|
|
}
|
|
|
|
if (BufferSize == 0) {
|
|
Status = EFI_SUCCESS;
|
|
goto Exit;
|
|
}
|
|
|
|
if (CardData->BlockIoMedia.ReadOnly) {
|
|
Status = EFI_WRITE_PROTECTED;
|
|
goto Exit;
|
|
}
|
|
|
|
if ((Address + BufferSize) > MultU64x32 (CardData->BlockIoMedia.LastBlock + 1, CardData->BlockIoMedia.BlockSize)) {
|
|
Status = EFI_INVALID_PARAMETER;
|
|
goto Exit;
|
|
}
|
|
|
|
CardData->NeedFlush = TRUE;
|
|
|
|
do {
|
|
if (BufferSize < BoundarySize) {
|
|
TransferSize = (UINT32)BufferSize;
|
|
} else {
|
|
TransferSize = BoundarySize;
|
|
}
|
|
|
|
Address += Index * TransferSize;
|
|
CEATALBA = DivU64x32Remainder (Address, DATA_UNIT_SIZE, &Remainder);
|
|
ASSERT(Remainder == 0);
|
|
|
|
Status = WriteDMAExt (
|
|
CardData,
|
|
CEATALBA,
|
|
pBuf,
|
|
(UINT16)(TransferSize / DATA_UNIT_SIZE)
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG((EFI_D_ERROR, "Write Failed at 0x%x, Index %d, Size 0x%x\n", Address, Index, TransferSize));
|
|
This->Reset (This, TRUE);
|
|
goto Exit;
|
|
}
|
|
BufferSize -= TransferSize;
|
|
pBuf += TransferSize;
|
|
Index ++;
|
|
} while (BufferSize != 0);
|
|
|
|
|
|
Exit:
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks() function.
|
|
(In this driver, this function just returns EFI_SUCCESS.)
|
|
|
|
@param This The EFI_BLOCK_IO_PROTOCOL instance.
|
|
|
|
@retval EFI_SUCCESS
|
|
@retval Others
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
CEATABlockFlushBlocks (
|
|
IN EFI_BLOCK_IO_PROTOCOL *This
|
|
)
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
CARD_DATA *CardData;
|
|
|
|
CardData = CARD_DATA_FROM_THIS(This);
|
|
|
|
if (CardData->NeedFlush) {
|
|
CardData->NeedFlush = FALSE;
|
|
Status = FlushCache (CardData);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
CEATA card BlockIo init function.
|
|
|
|
@param CardData Pointer to CARD_DATA.
|
|
|
|
@retval EFI_SUCCESS
|
|
@retval Others
|
|
**/
|
|
EFI_STATUS
|
|
CEATABlockIoInit (
|
|
IN CARD_DATA *CardData
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
CEATA card BlockIo init function
|
|
|
|
Arguments:
|
|
CardData - Pointer to CARD_DATA
|
|
|
|
Returns:
|
|
EFI_SUCCESS - Success
|
|
--*/
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT64 MaxSize;
|
|
UINT32 Remainder;
|
|
//
|
|
//BlockIO protocol
|
|
//
|
|
CardData->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;
|
|
CardData->BlockIo.Media = &(CardData->BlockIoMedia);
|
|
CardData->BlockIo.Reset = CEATABlockReset;
|
|
CardData->BlockIo.ReadBlocks = CEATABlockReadBlocks ;
|
|
CardData->BlockIo.WriteBlocks = CEATABlockWriteBlocks;
|
|
CardData->BlockIo.FlushBlocks = CEATABlockFlushBlocks;
|
|
|
|
CardData->BlockIoMedia.MediaId = 0;
|
|
CardData->BlockIoMedia.RemovableMedia = FALSE;
|
|
CardData->BlockIoMedia.MediaPresent = TRUE;
|
|
CardData->BlockIoMedia.LogicalPartition = FALSE;
|
|
|
|
if (CardData->CSDRegister.PERM_WRITE_PROTECT | CardData->CSDRegister.TMP_WRITE_PROTECT) {
|
|
CardData->BlockIoMedia.ReadOnly = TRUE;
|
|
} else {
|
|
CardData->BlockIoMedia.ReadOnly = FALSE;
|
|
}
|
|
|
|
|
|
CardData->BlockIoMedia.WriteCaching = FALSE;
|
|
CardData->BlockIoMedia.IoAlign = 1;
|
|
|
|
Status = IndentifyDevice (CardData);
|
|
if (EFI_ERROR (Status)) {
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
//Some device does not support this feature
|
|
//
|
|
|
|
if (CardData->IndentifyDeviceData.MaxWritesPerAddress == 0) {
|
|
CardData->BlockIoMedia.ReadOnly = TRUE;
|
|
}
|
|
|
|
CardData->BlockIoMedia.BlockSize = (1 << CardData->IndentifyDeviceData.Sectorsize);
|
|
ASSERT(CardData->BlockIoMedia.BlockSize >= 12);
|
|
|
|
|
|
MaxSize = *(UINT64*)(CardData->IndentifyDeviceData.MaximumLBA);
|
|
MaxSize = MultU64x32 (MaxSize, 512);
|
|
|
|
Remainder = 0;
|
|
CardData->BlockNumber = DivU64x32Remainder (MaxSize, CardData->BlockIoMedia.BlockSize, &Remainder);
|
|
ASSERT(Remainder == 0);
|
|
|
|
CardData->BlockIoMedia.LastBlock = (EFI_LBA)(CardData->BlockNumber - 1);
|
|
|
|
|
|
Exit:
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|