19b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney/** @file 29b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 39b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyBlock I/O protocol for CE-ATA device 49b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 59b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyCopyright (c) 2013-2015 Intel Corporation. 69b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 79b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyThis program and the accompanying materials 89b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyare licensed and made available under the terms and conditions of the BSD License 99b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneywhich accompanies this distribution. The full text of the license may be found at 109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyhttp://opensource.org/licenses/bsd-license.php 119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney**/ 169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney#include "SDMediaDevice.h" 189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney/** 209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Implements EFI_BLOCK_IO_PROTOCOL.Reset() function. 219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @param This The EFI_BLOCK_IO_PROTOCOL instance. 239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @param ExtendedVerification Indicates that the driver may perform a more exhaustive. 249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney verification operation of the device during reset. 259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney (This parameter is ingored in this driver.) 269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @retval EFI_SUCCESS Success 289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney**/ 299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEFI_STATUS 309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEFIAPI 319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyCEATABlockReset ( 329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney IN EFI_BLOCK_IO_PROTOCOL *This, 339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney IN BOOLEAN ExtendedVerification 349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney ) 359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{ 369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney EFI_STATUS Status; 379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CARD_DATA *CardData; 389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney EFI_SD_HOST_IO_PROTOCOL *SDHostIo; 399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CardData = CARD_DATA_FROM_THIS(This); 419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney SDHostIo = CardData->SDHostIo; 429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney if (!ExtendedVerification) { 449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Status = SoftwareReset (CardData); 459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } else { 469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Status = SDHostIo->ResetSDHost (SDHostIo, Reset_DAT_CMD); 479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney if (EFI_ERROR (Status)) { 489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney DEBUG((EFI_D_ERROR, "CEATABlockReset: Fail to ResetSDHost\n" )); 499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney return Status; 509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } 519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Status = MMCSDCardInit (CardData); 529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } 539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney return Status; 569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } 589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney/** 609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks() function. 619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @param This The EFI_BLOCK_IO_PROTOCOL instance. 639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @param MediaId The media id that the write request is for. 649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @param LBA The starting logical block address to read from on the device. 659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney The caller is responsible for writing to only legitimate locations. 669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @param BufferSize The size of the Buffer in bytes. This must be a multiple of the 679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney intrinsic block size of the device. 689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @param Buffer A pointer to the destination buffer for the data. The caller 699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney is responsible for either having implicit or explicit ownership 709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney of the buffer. 719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @retval EFI_SUCCESS Success 739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @retval EFI_DEVICE_ERROR Hardware Error 749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @retval EFI_INVALID_PARAMETER Parameter is error 759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @retval EFI_NO_MEDIA No media 769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @retval EFI_MEDIA_CHANGED Media Change 779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @retval EFI_BAD_BUFFER_SIZE Buffer size is bad 789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney**/ 799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEFI_STATUS 809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEFIAPI 819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyCEATABlockReadBlocks ( 829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney IN EFI_BLOCK_IO_PROTOCOL *This, 839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney IN UINT32 MediaId, 849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney IN EFI_LBA LBA, 859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney IN UINTN BufferSize, 869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney OUT VOID *Buffer 879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney ) 889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{ 899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney EFI_STATUS Status; 909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CARD_DATA *CardData; 919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney UINT32 TransferSize; 929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney UINT8 *pBuf; 939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney UINT32 Index; 949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney UINT64 Address; 959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney UINT32 Remainder; 969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney UINT64 CEATALBA; 979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney UINT32 BoundarySize; 989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Status = EFI_SUCCESS; 1009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CardData = CARD_DATA_FROM_THIS(This); 1019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney pBuf = Buffer; 1029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Index = 0; 1039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Address = MultU64x32(LBA, CardData->BlockIoMedia.BlockSize); 1049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney BoundarySize = CardData->SDHostIo->HostCapability.BoundarySize; 1059b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 1069b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney if (!Buffer) { 1079b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Status = EFI_INVALID_PARAMETER; 1089b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Invalid parameter\n" )); 1099b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney goto Exit; 1109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } 1119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 1129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney if (MediaId != CardData->BlockIoMedia.MediaId) { 1139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Status = EFI_MEDIA_CHANGED; 1149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Media changed\n" )); 1159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney goto Exit; 1169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } 1179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 1189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) { 1199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Status = EFI_BAD_BUFFER_SIZE; 1209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Bad buffer size\n" )); 1219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney goto Exit; 1229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } 1239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 1249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney if (BufferSize == 0) { 1259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Status = EFI_SUCCESS; 1269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney goto Exit; 1279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } 1289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 1299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney if ((Address + BufferSize) > MultU64x32 (CardData->BlockIoMedia.LastBlock + 1, CardData->BlockIoMedia.BlockSize)) { 1309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Status = EFI_INVALID_PARAMETER; 1319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Invalid parameter\n" )); 1329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney goto Exit; 1339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } 1349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 1359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 1369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney do { 1379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney if (BufferSize < BoundarySize) { 1389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney TransferSize = (UINT32)BufferSize; 1399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } else { 1409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney TransferSize = BoundarySize; 1419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } 1429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 1439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Address += Index * TransferSize; 1449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CEATALBA = DivU64x32Remainder (Address, DATA_UNIT_SIZE, &Remainder); 1459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney ASSERT(Remainder == 0); 1469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 1479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Status = ReadDMAExt ( 1489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CardData, 1499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CEATALBA, 1509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney pBuf, 1519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney (UINT16)(TransferSize / DATA_UNIT_SIZE) 1529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney ); 1539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney if (EFI_ERROR (Status)) { 1549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney DEBUG((EFI_D_ERROR, "Read Failed at 0x%x, Index %d, Size 0x%x\n", Address, Index, TransferSize)); 1559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney This->Reset (This, TRUE); 1569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney goto Exit; 1579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } 1589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney BufferSize -= TransferSize; 1599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney pBuf += TransferSize; 1609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Index ++; 1619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } while (BufferSize != 0); 1629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 1639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 1649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyExit: 1659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney return Status; 1669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney} 1679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 1689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney/** 1699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks() function. 1709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 1719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @param This The EFI_BLOCK_IO_PROTOCOL instance. 1729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @param MediaId The media id that the write request is for. 1739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @param LBA The starting logical block address to read from on the device. 1749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney The caller is responsible for writing to only legitimate locations. 1759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @param BufferSize The size of the Buffer in bytes. This must be a multiple of the 1769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney intrinsic block size of the device. 1779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @param Buffer A pointer to the destination buffer for the data. The caller 1789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney is responsible for either having implicit or explicit ownership 1799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney of the buffer. 1809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 1819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @retval EFI_SUCCESS Success 1829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @retval EFI_DEVICE_ERROR Hardware Error 1839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @retval EFI_INVALID_PARAMETER Parameter is error 1849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @retval EFI_NO_MEDIA No media 1859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @retval EFI_MEDIA_CHANGED Media Change 1869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @retval EFI_BAD_BUFFER_SIZE Buffer size is bad 1879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney**/ 1889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEFI_STATUS 1899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEFIAPI 1909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyCEATABlockWriteBlocks ( 1919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney IN EFI_BLOCK_IO_PROTOCOL *This, 1929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney IN UINT32 MediaId, 1939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney IN EFI_LBA LBA, 1949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney IN UINTN BufferSize, 1959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney IN VOID *Buffer 1969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney ) 1979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{ 1989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney EFI_STATUS Status; 1999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CARD_DATA *CardData; 2009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney UINT32 TransferSize; 2019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney UINT8 *pBuf; 2029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney UINT32 Index; 2039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney UINT64 Address; 2049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney UINT32 Remainder; 2059b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney UINT64 CEATALBA; 2069b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney UINT32 BoundarySize; 2079b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 2089b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 2099b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Status = EFI_SUCCESS; 2109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CardData = CARD_DATA_FROM_THIS(This); 2119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney pBuf = Buffer; 2129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Index = 0; 2139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Address = MultU64x32(LBA, CardData->BlockIoMedia.BlockSize); 2149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney BoundarySize = CardData->SDHostIo->HostCapability.BoundarySize; 2159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 2169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 2179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney if (!Buffer) { 2189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Status = EFI_INVALID_PARAMETER; 2199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney goto Exit; 2209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } 2219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 2229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney if (MediaId != CardData->BlockIoMedia.MediaId) { 2239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Status = EFI_MEDIA_CHANGED; 2249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney goto Exit; 2259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } 2269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 2279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) { 2289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Status = EFI_BAD_BUFFER_SIZE; 2299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney goto Exit; 2309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } 2319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 2329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney if (BufferSize == 0) { 2339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Status = EFI_SUCCESS; 2349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney goto Exit; 2359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } 2369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 2379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney if (CardData->BlockIoMedia.ReadOnly) { 2389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Status = EFI_WRITE_PROTECTED; 2399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney goto Exit; 2409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } 2419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 2429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney if ((Address + BufferSize) > MultU64x32 (CardData->BlockIoMedia.LastBlock + 1, CardData->BlockIoMedia.BlockSize)) { 2439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Status = EFI_INVALID_PARAMETER; 2449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney goto Exit; 2459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } 2469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 2479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CardData->NeedFlush = TRUE; 2489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 2499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney do { 2509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney if (BufferSize < BoundarySize) { 2519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney TransferSize = (UINT32)BufferSize; 2529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } else { 2539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney TransferSize = BoundarySize; 2549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } 2559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 2569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Address += Index * TransferSize; 2579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CEATALBA = DivU64x32Remainder (Address, DATA_UNIT_SIZE, &Remainder); 2589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney ASSERT(Remainder == 0); 2599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 2609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Status = WriteDMAExt ( 2619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CardData, 2629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CEATALBA, 2639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney pBuf, 2649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney (UINT16)(TransferSize / DATA_UNIT_SIZE) 2659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney ); 2669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney if (EFI_ERROR (Status)) { 2679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney DEBUG((EFI_D_ERROR, "Write Failed at 0x%x, Index %d, Size 0x%x\n", Address, Index, TransferSize)); 2689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney This->Reset (This, TRUE); 2699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney goto Exit; 2709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } 2719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney BufferSize -= TransferSize; 2729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney pBuf += TransferSize; 2739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Index ++; 2749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } while (BufferSize != 0); 2759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 2769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 2779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyExit: 2789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney return Status; 2799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney} 2809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 2819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney/** 2829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks() function. 2839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney (In this driver, this function just returns EFI_SUCCESS.) 2849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 2859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @param This The EFI_BLOCK_IO_PROTOCOL instance. 2869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 2879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @retval EFI_SUCCESS 2889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @retval Others 2899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney**/ 2909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEFI_STATUS 2919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEFIAPI 2929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyCEATABlockFlushBlocks ( 2939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney IN EFI_BLOCK_IO_PROTOCOL *This 2949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney ) 2959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{ 2969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 2979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney EFI_STATUS Status; 2989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CARD_DATA *CardData; 2999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 3009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CardData = CARD_DATA_FROM_THIS(This); 3019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 3029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney if (CardData->NeedFlush) { 3039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CardData->NeedFlush = FALSE; 3049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Status = FlushCache (CardData); 3059b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } 3069b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 3079b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney return EFI_SUCCESS; 3089b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney} 3099b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 3109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 3119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney/** 3129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CEATA card BlockIo init function. 3139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 3149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @param CardData Pointer to CARD_DATA. 3159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 3169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @retval EFI_SUCCESS 3179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney @retval Others 3189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney**/ 3199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEFI_STATUS 3209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyCEATABlockIoInit ( 3219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney IN CARD_DATA *CardData 3229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney ) 3239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney/*++ 3249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 3259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Routine Description: 3269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CEATA card BlockIo init function 3279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 3289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Arguments: 3299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CardData - Pointer to CARD_DATA 3309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 3319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Returns: 3329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney EFI_SUCCESS - Success 3339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney--*/ 3349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{ 3359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney EFI_STATUS Status; 3369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney UINT64 MaxSize; 3379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney UINT32 Remainder; 3389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney // 3399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney //BlockIO protocol 3409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney // 3419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CardData->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION; 3429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CardData->BlockIo.Media = &(CardData->BlockIoMedia); 3439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CardData->BlockIo.Reset = CEATABlockReset; 3449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CardData->BlockIo.ReadBlocks = CEATABlockReadBlocks ; 3459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CardData->BlockIo.WriteBlocks = CEATABlockWriteBlocks; 3469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CardData->BlockIo.FlushBlocks = CEATABlockFlushBlocks; 3479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 3489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CardData->BlockIoMedia.MediaId = 0; 3499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CardData->BlockIoMedia.RemovableMedia = FALSE; 3509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CardData->BlockIoMedia.MediaPresent = TRUE; 3519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CardData->BlockIoMedia.LogicalPartition = FALSE; 3529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 3539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney if (CardData->CSDRegister.PERM_WRITE_PROTECT | CardData->CSDRegister.TMP_WRITE_PROTECT) { 3549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CardData->BlockIoMedia.ReadOnly = TRUE; 3559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } else { 3569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CardData->BlockIoMedia.ReadOnly = FALSE; 3579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } 3589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 3599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 3609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CardData->BlockIoMedia.WriteCaching = FALSE; 3619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CardData->BlockIoMedia.IoAlign = 1; 3629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 3639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Status = IndentifyDevice (CardData); 3649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney if (EFI_ERROR (Status)) { 3659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney goto Exit; 3669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } 3679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 3689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney // 3699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney //Some device does not support this feature 3709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney // 3719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 3729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney if (CardData->IndentifyDeviceData.MaxWritesPerAddress == 0) { 3739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CardData->BlockIoMedia.ReadOnly = TRUE; 3749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney } 3759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 3769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CardData->BlockIoMedia.BlockSize = (1 << CardData->IndentifyDeviceData.Sectorsize); 3779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney ASSERT(CardData->BlockIoMedia.BlockSize >= 12); 3789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 3799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 3809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney MaxSize = *(UINT64*)(CardData->IndentifyDeviceData.MaximumLBA); 3819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney MaxSize = MultU64x32 (MaxSize, 512); 3829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 3839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney Remainder = 0; 3849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CardData->BlockNumber = DivU64x32Remainder (MaxSize, CardData->BlockIoMedia.BlockSize, &Remainder); 3859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney ASSERT(Remainder == 0); 3869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 3879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney CardData->BlockIoMedia.LastBlock = (EFI_LBA)(CardData->BlockNumber - 1); 3889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 3899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 3909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyExit: 3919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney return Status; 3929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 3939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney} 3949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 3959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 3969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney 397