--- /dev/null
+/** @file\r
+\r
+Block I/O protocol for CE-ATA device\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "SDMediaDevice.h"\r
+\r
+/**\r
+ Implements EFI_BLOCK_IO_PROTOCOL.Reset() function.\r
+\r
+ @param This The EFI_BLOCK_IO_PROTOCOL instance.\r
+ @param ExtendedVerification Indicates that the driver may perform a more exhaustive.\r
+ verification operation of the device during reset.\r
+ (This parameter is ingored in this driver.)\r
+\r
+ @retval EFI_SUCCESS Success\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CEATABlockReset (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN BOOLEAN ExtendedVerification\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CARD_DATA *CardData;\r
+ EFI_SD_HOST_IO_PROTOCOL *SDHostIo;\r
+\r
+ CardData = CARD_DATA_FROM_THIS(This);\r
+ SDHostIo = CardData->SDHostIo;\r
+\r
+ if (!ExtendedVerification) {\r
+ Status = SoftwareReset (CardData);\r
+ } else {\r
+ Status = SDHostIo->ResetSDHost (SDHostIo, Reset_DAT_CMD);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG((EFI_D_ERROR, "CEATABlockReset: Fail to ResetSDHost\n" ));\r
+ return Status;\r
+ }\r
+ Status = MMCSDCardInit (CardData);\r
+ }\r
+\r
+\r
+ return Status;\r
+\r
+ }\r
+\r
+/**\r
+ Implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks() function.\r
+\r
+ @param This The EFI_BLOCK_IO_PROTOCOL instance.\r
+ @param MediaId The media id that the write request is for.\r
+ @param LBA The starting logical block address to read from on the device.\r
+ The caller is responsible for writing to only legitimate locations.\r
+ @param BufferSize The size of the Buffer in bytes. This must be a multiple of the\r
+ intrinsic block size of the device.\r
+ @param Buffer A pointer to the destination buffer for the data. The caller\r
+ is responsible for either having implicit or explicit ownership\r
+ of the buffer.\r
+\r
+ @retval EFI_SUCCESS Success\r
+ @retval EFI_DEVICE_ERROR Hardware Error\r
+ @retval EFI_INVALID_PARAMETER Parameter is error\r
+ @retval EFI_NO_MEDIA No media\r
+ @retval EFI_MEDIA_CHANGED Media Change\r
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CEATABlockReadBlocks (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN UINT32 MediaId,\r
+ IN EFI_LBA LBA,\r
+ IN UINTN BufferSize,\r
+ OUT VOID *Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CARD_DATA *CardData;\r
+ UINT32 TransferSize;\r
+ UINT8 *pBuf;\r
+ UINT32 Index;\r
+ UINT64 Address;\r
+ UINT32 Remainder;\r
+ UINT64 CEATALBA;\r
+ UINT32 BoundarySize;\r
+\r
+ Status = EFI_SUCCESS;\r
+ CardData = CARD_DATA_FROM_THIS(This);\r
+ pBuf = Buffer;\r
+ Index = 0;\r
+ Address = MultU64x32(LBA, CardData->BlockIoMedia.BlockSize);\r
+ BoundarySize = CardData->SDHostIo->HostCapability.BoundarySize;\r
+\r
+ if (!Buffer) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Invalid parameter\n" ));\r
+ goto Exit;\r
+ }\r
+\r
+ if (MediaId != CardData->BlockIoMedia.MediaId) {\r
+ Status = EFI_MEDIA_CHANGED;\r
+ DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Media changed\n" ));\r
+ goto Exit;\r
+ }\r
+\r
+ if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) {\r
+ Status = EFI_BAD_BUFFER_SIZE;\r
+ DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Bad buffer size\n" ));\r
+ goto Exit;\r
+ }\r
+\r
+ if (BufferSize == 0) {\r
+ Status = EFI_SUCCESS;\r
+ goto Exit;\r
+ }\r
+\r
+ if ((Address + BufferSize) > MultU64x32 (CardData->BlockIoMedia.LastBlock + 1, CardData->BlockIoMedia.BlockSize)) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Invalid parameter\n" ));\r
+ goto Exit;\r
+ }\r
+\r
+\r
+ do {\r
+ if (BufferSize < BoundarySize) {\r
+ TransferSize = (UINT32)BufferSize;\r
+ } else {\r
+ TransferSize = BoundarySize;\r
+ }\r
+\r
+ Address += Index * TransferSize;\r
+ CEATALBA = DivU64x32Remainder (Address, DATA_UNIT_SIZE, &Remainder);\r
+ ASSERT(Remainder == 0);\r
+\r
+ Status = ReadDMAExt (\r
+ CardData,\r
+ CEATALBA,\r
+ pBuf,\r
+ (UINT16)(TransferSize / DATA_UNIT_SIZE)\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG((EFI_D_ERROR, "Read Failed at 0x%x, Index %d, Size 0x%x\n", Address, Index, TransferSize));\r
+ This->Reset (This, TRUE);\r
+ goto Exit;\r
+ }\r
+ BufferSize -= TransferSize;\r
+ pBuf += TransferSize;\r
+ Index ++;\r
+ } while (BufferSize != 0);\r
+\r
+\r
+Exit:\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks() function.\r
+\r
+ @param This The EFI_BLOCK_IO_PROTOCOL instance.\r
+ @param MediaId The media id that the write request is for.\r
+ @param LBA The starting logical block address to read from on the device.\r
+ The caller is responsible for writing to only legitimate locations.\r
+ @param BufferSize The size of the Buffer in bytes. This must be a multiple of the\r
+ intrinsic block size of the device.\r
+ @param Buffer A pointer to the destination buffer for the data. The caller\r
+ is responsible for either having implicit or explicit ownership\r
+ of the buffer.\r
+\r
+ @retval EFI_SUCCESS Success\r
+ @retval EFI_DEVICE_ERROR Hardware Error\r
+ @retval EFI_INVALID_PARAMETER Parameter is error\r
+ @retval EFI_NO_MEDIA No media\r
+ @retval EFI_MEDIA_CHANGED Media Change\r
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CEATABlockWriteBlocks (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN UINT32 MediaId,\r
+ IN EFI_LBA LBA,\r
+ IN UINTN BufferSize,\r
+ IN VOID *Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CARD_DATA *CardData;\r
+ UINT32 TransferSize;\r
+ UINT8 *pBuf;\r
+ UINT32 Index;\r
+ UINT64 Address;\r
+ UINT32 Remainder;\r
+ UINT64 CEATALBA;\r
+ UINT32 BoundarySize;\r
+\r
+\r
+ Status = EFI_SUCCESS;\r
+ CardData = CARD_DATA_FROM_THIS(This);\r
+ pBuf = Buffer;\r
+ Index = 0;\r
+ Address = MultU64x32(LBA, CardData->BlockIoMedia.BlockSize);\r
+ BoundarySize = CardData->SDHostIo->HostCapability.BoundarySize;\r
+\r
+\r
+ if (!Buffer) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Exit;\r
+ }\r
+\r
+ if (MediaId != CardData->BlockIoMedia.MediaId) {\r
+ Status = EFI_MEDIA_CHANGED;\r
+ goto Exit;\r
+ }\r
+\r
+ if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) {\r
+ Status = EFI_BAD_BUFFER_SIZE;\r
+ goto Exit;\r
+ }\r
+\r
+ if (BufferSize == 0) {\r
+ Status = EFI_SUCCESS;\r
+ goto Exit;\r
+ }\r
+\r
+ if (CardData->BlockIoMedia.ReadOnly) {\r
+ Status = EFI_WRITE_PROTECTED;\r
+ goto Exit;\r
+ }\r
+\r
+ if ((Address + BufferSize) > MultU64x32 (CardData->BlockIoMedia.LastBlock + 1, CardData->BlockIoMedia.BlockSize)) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Exit;\r
+ }\r
+\r
+ CardData->NeedFlush = TRUE;\r
+\r
+ do {\r
+ if (BufferSize < BoundarySize) {\r
+ TransferSize = (UINT32)BufferSize;\r
+ } else {\r
+ TransferSize = BoundarySize;\r
+ }\r
+\r
+ Address += Index * TransferSize;\r
+ CEATALBA = DivU64x32Remainder (Address, DATA_UNIT_SIZE, &Remainder);\r
+ ASSERT(Remainder == 0);\r
+\r
+ Status = WriteDMAExt (\r
+ CardData,\r
+ CEATALBA,\r
+ pBuf,\r
+ (UINT16)(TransferSize / DATA_UNIT_SIZE)\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG((EFI_D_ERROR, "Write Failed at 0x%x, Index %d, Size 0x%x\n", Address, Index, TransferSize));\r
+ This->Reset (This, TRUE);\r
+ goto Exit;\r
+ }\r
+ BufferSize -= TransferSize;\r
+ pBuf += TransferSize;\r
+ Index ++;\r
+ } while (BufferSize != 0);\r
+\r
+\r
+Exit:\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks() function.\r
+ (In this driver, this function just returns EFI_SUCCESS.)\r
+\r
+ @param This The EFI_BLOCK_IO_PROTOCOL instance.\r
+\r
+ @retval EFI_SUCCESS\r
+ @retval Others\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CEATABlockFlushBlocks (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This\r
+ )\r
+{\r
+\r
+ EFI_STATUS Status;\r
+ CARD_DATA *CardData;\r
+\r
+ CardData = CARD_DATA_FROM_THIS(This);\r
+\r
+ if (CardData->NeedFlush) {\r
+ CardData->NeedFlush = FALSE;\r
+ Status = FlushCache (CardData);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ CEATA card BlockIo init function.\r
+\r
+ @param CardData Pointer to CARD_DATA.\r
+\r
+ @retval EFI_SUCCESS\r
+ @retval Others\r
+**/\r
+EFI_STATUS\r
+CEATABlockIoInit (\r
+ IN CARD_DATA *CardData\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ CEATA card BlockIo init function\r
+\r
+ Arguments:\r
+ CardData - Pointer to CARD_DATA\r
+\r
+ Returns:\r
+ EFI_SUCCESS - Success\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ UINT64 MaxSize;\r
+ UINT32 Remainder;\r
+ //\r
+ //BlockIO protocol\r
+ //\r
+ CardData->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;\r
+ CardData->BlockIo.Media = &(CardData->BlockIoMedia);\r
+ CardData->BlockIo.Reset = CEATABlockReset;\r
+ CardData->BlockIo.ReadBlocks = CEATABlockReadBlocks ;\r
+ CardData->BlockIo.WriteBlocks = CEATABlockWriteBlocks;\r
+ CardData->BlockIo.FlushBlocks = CEATABlockFlushBlocks;\r
+\r
+ CardData->BlockIoMedia.MediaId = 0;\r
+ CardData->BlockIoMedia.RemovableMedia = FALSE;\r
+ CardData->BlockIoMedia.MediaPresent = TRUE;\r
+ CardData->BlockIoMedia.LogicalPartition = FALSE;\r
+\r
+ if (CardData->CSDRegister.PERM_WRITE_PROTECT | CardData->CSDRegister.TMP_WRITE_PROTECT) {\r
+ CardData->BlockIoMedia.ReadOnly = TRUE;\r
+ } else {\r
+ CardData->BlockIoMedia.ReadOnly = FALSE;\r
+ }\r
+\r
+\r
+ CardData->BlockIoMedia.WriteCaching = FALSE;\r
+ CardData->BlockIoMedia.IoAlign = 1;\r
+\r
+ Status = IndentifyDevice (CardData);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ //Some device does not support this feature\r
+ //\r
+\r
+ if (CardData->IndentifyDeviceData.MaxWritesPerAddress == 0) {\r
+ CardData->BlockIoMedia.ReadOnly = TRUE;\r
+ }\r
+\r
+ CardData->BlockIoMedia.BlockSize = (1 << CardData->IndentifyDeviceData.Sectorsize);\r
+ ASSERT(CardData->BlockIoMedia.BlockSize >= 12);\r
+\r
+\r
+ MaxSize = *(UINT64*)(CardData->IndentifyDeviceData.MaximumLBA);\r
+ MaxSize = MultU64x32 (MaxSize, 512);\r
+\r
+ Remainder = 0;\r
+ CardData->BlockNumber = DivU64x32Remainder (MaxSize, CardData->BlockIoMedia.BlockSize, &Remainder);\r
+ ASSERT(Remainder == 0);\r
+\r
+ CardData->BlockIoMedia.LastBlock = (EFI_LBA)(CardData->BlockNumber - 1);\r
+\r
+\r
+Exit:\r
+ return Status;\r
+\r
+}\r
+\r
+\r
+\r