[Protocols.common]\r
gVirtualUncachedPagesProtocolGuid = { 0xAD651C7D, 0x3C22, 0x4DBF, { 0x92, 0xe8, 0x38, 0xa7, 0xcd, 0xae, 0x87, 0xb2 } }\r
\r
- ## Include/Protocol/MmcHost.h\r
- gEfiMmcHostProtocolGuid = { 0x3e591c00, 0x9e4a, 0x11df, {0x92, 0x44, 0x00, 0x02, 0xA5, 0xD5, 0xC5, 0x1B }}\r
-\r
[PcdsFeatureFlag.common]\r
gArmTokenSpaceGuid.PcdCpuDxeProduceDebugSupport|FALSE|BOOLEAN|0x00000001\r
\r
ArmPkg/Drivers/PL390Gic/PL390GicNonSec.inf
ArmPkg/Drivers/PL390Gic/PL390GicSec.inf
ArmPkg/Filesystem/SemihostFs/SemihostFs.inf
- ArmPkg/Universal/MmcDxe/MmcDxe.inf
\r
[Packages]\r
ArmPkg/ArmPkg.dec\r
+ EmbeddedPkg/EmbeddedPkg.dec\r
MdePkg/MdePkg.dec\r
\r
[LibraryClasses]\r
+++ /dev/null
-/** @file\r
- Definition of the MMC Host Protocol\r
-\r
- Copyright (c) 2011, ARM Limited. All rights reserved.\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
-#ifndef __MMC_HOST_H__\r
-#define __MMC_HOST_H__\r
-\r
-///\r
-/// Global ID for the MMC Host Protocol\r
-///\r
-#define EFI_MMC_HOST_PROTOCOL_GUID \\r
- { 0x3e591c00, 0x9e4a, 0x11df, {0x92, 0x44, 0x00, 0x02, 0xA5, 0xD5, 0xC5, 0x1B } }\r
-\r
-#define MMC_RESPONSE_TYPE_R1 0\r
-#define MMC_RESPONSE_TYPE_R1b 0\r
-#define MMC_RESPONSE_TYPE_R2 1\r
-#define MMC_RESPONSE_TYPE_R3 0\r
-#define MMC_RESPONSE_TYPE_R6 0\r
-#define MMC_RESPONSE_TYPE_R7 0\r
-#define MMC_RESPONSE_TYPE_OCR 0\r
-#define MMC_RESPONSE_TYPE_CID 1\r
-#define MMC_RESPONSE_TYPE_CSD 1\r
-#define MMC_RESPONSE_TYPE_RCA 0\r
-\r
-typedef UINT32 MMC_RESPONSE_TYPE;\r
-\r
-typedef UINT32 MMC_CMD;\r
-\r
-#define MMC_CMD_WAIT_RESPONSE (1 << 16)\r
-#define MMC_CMD_LONG_RESPONSE (1 << 17)\r
-#define MMC_CMD_NO_CRC_RESPONSE (1 << 18)\r
-\r
-#define MMC_INDX(Index) ((Index) & 0xFFFF)\r
-#define MMC_GET_INDX(MmcCmd) ((MmcCmd) & 0xFFFF)\r
-\r
-#define MMC_CMD0 (MMC_INDX(0) | MMC_CMD_NO_CRC_RESPONSE)\r
-#define MMC_CMD1 (MMC_INDX(1) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_NO_CRC_RESPONSE)\r
-#define MMC_CMD2 (MMC_INDX(2) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_LONG_RESPONSE)\r
-#define MMC_CMD3 (MMC_INDX(3) | MMC_CMD_WAIT_RESPONSE)\r
-#define MMC_CMD5 (MMC_INDX(5) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_NO_CRC_RESPONSE)\r
-#define MMC_CMD7 (MMC_INDX(7) | MMC_CMD_WAIT_RESPONSE)\r
-#define MMC_CMD8 (MMC_INDX(8) | MMC_CMD_WAIT_RESPONSE)\r
-#define MMC_CMD9 (MMC_INDX(9) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_LONG_RESPONSE)\r
-#define MMC_CMD11 (MMC_INDX(11) | MMC_CMD_WAIT_RESPONSE)\r
-#define MMC_CMD12 (MMC_INDX(12) | MMC_CMD_WAIT_RESPONSE)\r
-#define MMC_CMD13 (MMC_INDX(13) | MMC_CMD_WAIT_RESPONSE)\r
-#define MMC_CMD16 (MMC_INDX(16) | MMC_CMD_WAIT_RESPONSE)\r
-#define MMC_CMD17 (MMC_INDX(17) | MMC_CMD_WAIT_RESPONSE)\r
-#define MMC_CMD18 (MMC_INDX(18) | MMC_CMD_WAIT_RESPONSE)\r
-#define MMC_CMD20 (MMC_INDX(20) | MMC_CMD_WAIT_RESPONSE)\r
-#define MMC_CMD23 (MMC_INDX(23) | MMC_CMD_WAIT_RESPONSE)\r
-#define MMC_CMD24 (MMC_INDX(24) | MMC_CMD_WAIT_RESPONSE)\r
-#define MMC_CMD55 (MMC_INDX(55) | MMC_CMD_WAIT_RESPONSE)\r
-#define MMC_ACMD41 (MMC_INDX(41) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_NO_CRC_RESPONSE)\r
-\r
-typedef enum _MMC_STATE {\r
- MmcInvalidState = 0,\r
- MmcHwInitializationState,\r
- MmcIdleState,\r
- MmcReadyState,\r
- MmcIdentificationState,\r
- MmcStandByState,\r
- MmcTransferState,\r
- MmcSendingDataState,\r
- MmcReceiveDataState,\r
- MmcProgrammingState,\r
- MmcDisconnectState,\r
-} MMC_STATE;\r
-\r
-typedef BOOLEAN (*MMC_ISCARDPRESENT)();\r
-\r
-typedef BOOLEAN (*MMC_ISREADONLY)();\r
-\r
-typedef EFI_STATUS (*MMC_BUILDDEVICEPATH)(EFI_DEVICE_PATH_PROTOCOL **DevicePath);\r
-\r
-typedef EFI_STATUS (*MMC_NOTIFYSTATE)(MMC_STATE State);\r
-\r
-typedef EFI_STATUS (*MMC_SENDCOMMAND)(MMC_CMD Cmd, UINT32 Argument);\r
-\r
-typedef EFI_STATUS (*MMC_RECEIVERESPONSE)(MMC_RESPONSE_TYPE Type, UINT32* Buffer);\r
-\r
-typedef EFI_STATUS (*MMC_READBLOCKDATA)(EFI_LBA Lba, UINTN Length, UINT32* Buffer);\r
-\r
-typedef EFI_STATUS (*MMC_WRITEBLOCKDATA)(EFI_LBA Lba, UINTN Length, UINT32* Buffer);\r
-\r
-typedef struct _EFI_MMC_HOST_PROTOCOL {\r
- MMC_ISCARDPRESENT IsCardPresent;\r
- MMC_ISREADONLY IsReadOnly;\r
- MMC_BUILDDEVICEPATH BuildDevicePath;\r
-\r
- MMC_NOTIFYSTATE NotifyState;\r
-\r
- MMC_SENDCOMMAND SendCommand;\r
- MMC_RECEIVERESPONSE ReceiveResponse;\r
-\r
- MMC_READBLOCKDATA ReadBlockData;\r
- MMC_WRITEBLOCKDATA WriteBlockData;\r
-} EFI_MMC_HOST_PROTOCOL;\r
-\r
-extern EFI_GUID gEfiMmcHostProtocolGuid;\r
-\r
-#endif\r
-\r
+++ /dev/null
-/** @file\r
- Component Name Protocol implementation for the MMC DXE driver\r
-\r
- Copyright (c) 2011, ARM Limited. All rights reserved.\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 "Mmc.h"\r
-\r
-//\r
-// EFI Component Name Protocol\r
-//\r
-GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gMmcComponentName = {\r
- MmcGetDriverName,\r
- MmcGetControllerName,\r
- "eng"\r
-};\r
-\r
-//\r
-// EFI Component Name 2 Protocol\r
-//\r
-GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gMmcComponentName2 = {\r
- (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) MmcGetDriverName,\r
- (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) MmcGetControllerName,\r
- "en"\r
-};\r
-\r
-GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE\r
-mMmcDriverNameTable[] = {\r
- {"eng;en", L"MMC/SD Card Interface Driver"},\r
- {NULL, NULL}\r
-};\r
-\r
-/**\r
- Retrieves a Unicode string that is the user readable name of the driver.\r
-\r
- This function retrieves the user readable name of a driver in the form of a\r
- Unicode string. If the driver specified by This has a user readable name in\r
- the language specified by Language, then a pointer to the driver name is\r
- returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
- by This does not support the language specified by Language,\r
- then EFI_UNSUPPORTED is returned.\r
-\r
- @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
- EFI_COMPONENT_NAME_PROTOCOL instance.\r
- @param Language A pointer to a Null-terminated ASCII string\r
- array indicating the language. This is the\r
- language of the driver name that the caller is\r
- requesting, and it must match one of the\r
- languages specified in SupportedLanguages. The\r
- number of languages supported by a driver is up\r
- to the driver writer. Language is specified\r
- in RFC 4646 or ISO 639-2 language code format.\r
- @param DriverName A pointer to the Unicode string to return.\r
- This Unicode string is the name of the\r
- driver specified by This in the language\r
- specified by Language.\r
-\r
- @retval EFI_SUCCESS The Unicode string for the Driver specified by\r
- This and the language specified by Language was\r
- returned in DriverName.\r
- @retval EFI_INVALID_PARAMETER Language is NULL.\r
- @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
- @retval EFI_UNSUPPORTED The driver specified by This does not support\r
- the language specified by Language.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-MmcGetDriverName (\r
- IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
- IN CHAR8 *Language,\r
- OUT CHAR16 **DriverName\r
- )\r
-{\r
- return LookupUnicodeString2 (\r
- Language,\r
- This->SupportedLanguages,\r
- mMmcDriverNameTable,\r
- DriverName,\r
- (BOOLEAN)(This == &gMmcComponentName)\r
- );\r
-}\r
-\r
-/**\r
- Retrieves a Unicode string that is the user readable name of the controller\r
- that is being managed by a driver.\r
-\r
- This function retrieves the user readable name of the controller specified by\r
- ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
- driver specified by This has a user readable name in the language specified by\r
- Language, then a pointer to the controller name is returned in ControllerName,\r
- and EFI_SUCCESS is returned. If the driver specified by This is not currently\r
- managing the controller specified by ControllerHandle and ChildHandle,\r
- then EFI_UNSUPPORTED is returned. If the driver specified by This does not\r
- support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
-\r
- @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
- EFI_COMPONENT_NAME_PROTOCOL instance.\r
- @param ControllerHandle The handle of a controller that the driver\r
- specified by This is managing. This handle\r
- specifies the controller whose name is to be\r
- returned.\r
- @param ChildHandle The handle of the child controller to retrieve\r
- the name of. This is an optional parameter that\r
- may be NULL. It will be NULL for device\r
- drivers. It will also be NULL for a bus drivers\r
- that wish to retrieve the name of the bus\r
- controller. It will not be NULL for a bus\r
- driver that wishes to retrieve the name of a\r
- child controller.\r
- @param Language A pointer to a Null-terminated ASCII string\r
- array indicating the language. This is the\r
- language of the driver name that the caller is\r
- requesting, and it must match one of the\r
- languages specified in SupportedLanguages. The\r
- number of languages supported by a driver is up\r
- to the driver writer. Language is specified in\r
- RFC 4646 or ISO 639-2 language code format.\r
- @param ControllerName A pointer to the Unicode string to return.\r
- This Unicode string is the name of the\r
- controller specified by ControllerHandle and\r
- ChildHandle in the language specified by\r
- Language from the point of view of the driver\r
- specified by This.\r
-\r
- @retval EFI_SUCCESS The Unicode string for the user readable name in\r
- the language specified by Language for the\r
- driver specified by This was returned in\r
- DriverName.\r
- @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.\r
- @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
- EFI_HANDLE.\r
- @retval EFI_INVALID_PARAMETER Language is NULL.\r
- @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
- @retval EFI_UNSUPPORTED The driver specified by This is not currently\r
- managing the controller specified by\r
- ControllerHandle and ChildHandle.\r
- @retval EFI_UNSUPPORTED The driver specified by This does not support\r
- the language specified by Language.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-MmcGetControllerName (\r
- IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
- IN EFI_HANDLE ControllerHandle,\r
- IN EFI_HANDLE ChildHandle OPTIONAL,\r
- IN CHAR8 *Language,\r
- OUT CHAR16 **ControllerName\r
- )\r
-{\r
- return EFI_UNSUPPORTED;\r
-}\r
+++ /dev/null
-/** @file\r
- Diagnostics Protocol implementation for the MMC DXE driver\r
-\r
- Copyright (c) 2011, ARM Limited. All rights reserved.\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 <Uefi.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-\r
-#include "Mmc.h"\r
-\r
-#define DIAGNOSTIC_LOGBUFFER_MAXCHAR 1024\r
-\r
-CHAR16* mLogBuffer = NULL;\r
-UINTN mLogRemainChar = 0;\r
-\r
-CHAR16* DiagnosticInitLog(UINTN MaxBufferChar) {\r
- mLogRemainChar = MaxBufferChar;\r
- mLogBuffer = AllocatePool ((UINTN)MaxBufferChar * sizeof(CHAR16));\r
- return mLogBuffer;\r
-}\r
-\r
-UINTN DiagnosticLog(CONST CHAR16* Str) {\r
- UINTN len = StrLen (Str);\r
- if (len <= mLogRemainChar) {\r
- mLogRemainChar -= len;\r
- StrCpy (mLogBuffer, Str);\r
- mLogBuffer += len;\r
- return len;\r
- } else {\r
- return 0;\r
- }\r
-}\r
-\r
-VOID GenerateRandomBuffer(VOID* Buffer, UINTN BufferSize) {\r
- UINT64 i;\r
- UINT64* Buffer64 = (UINT64*)Buffer;\r
-\r
- for (i = 0; i < (BufferSize >> 3); i++) {\r
- *Buffer64 = i | (~i << 32);\r
- Buffer64++;\r
- }\r
-}\r
-\r
-BOOLEAN CompareBuffer(VOID *BufferA, VOID *BufferB, UINTN BufferSize) {\r
- UINTN i;\r
- UINT64* BufferA64 = (UINT64*)BufferA;\r
- UINT64* BufferB64 = (UINT64*)BufferB;\r
-\r
- for (i = 0; i < (BufferSize >> 3); i++) {\r
- if (*BufferA64 != *BufferB64) {\r
- DEBUG((EFI_D_ERROR, "CompareBuffer: Error at %i", i));\r
- DEBUG((EFI_D_ERROR, "(0x%lX) != (0x%lX)\n", *BufferA64, *BufferB64));\r
- return FALSE;\r
- }\r
- BufferA64++;\r
- BufferB64++;\r
- }\r
- return TRUE;\r
-}\r
-\r
-EFI_STATUS MmcReadWriteDataTest(MMC_HOST_INSTANCE *MmcHostInstance, EFI_LBA Lba, UINTN BufferSize) {\r
- VOID *BackBuffer;\r
- VOID *WriteBuffer;\r
- VOID *ReadBuffer;\r
- EFI_STATUS Status;\r
- \r
- // Check if a Media is Present\r
- if (!MmcHostInstance->BlockIo.Media->MediaPresent) {\r
- DiagnosticLog(L"ERROR: No Media Present\n");\r
- return EFI_NO_MEDIA;\r
- }\r
-\r
- if (MmcHostInstance->State != MmcTransferState) {\r
- DiagnosticLog(L"ERROR: Not ready for Transfer state\n");\r
- return EFI_NOT_READY;\r
- }\r
-\r
- BackBuffer = AllocatePool(BufferSize);\r
- WriteBuffer = AllocatePool(BufferSize);\r
- ReadBuffer = AllocatePool(BufferSize);\r
-\r
- // Read (and save) buffer at a specific location\r
- Status = MmcReadBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,BackBuffer);\r
- if (Status != EFI_SUCCESS) {\r
- DiagnosticLog(L"ERROR: Fail to Read Block (1)\n");\r
- return Status;\r
- }\r
-\r
- // Write buffer at the same location\r
- GenerateRandomBuffer(WriteBuffer,BufferSize);\r
- Status = MmcWriteBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,WriteBuffer);\r
- if (Status != EFI_SUCCESS) {\r
- DiagnosticLog(L"ERROR: Fail to Write Block (1)\n");\r
- return Status;\r
- }\r
-\r
- // Read the buffer at the same location\r
- Status = MmcReadBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,ReadBuffer);\r
- if (Status != EFI_SUCCESS) {\r
- DiagnosticLog(L"ERROR: Fail to Read Block (2)\n");\r
- return Status;\r
- }\r
-\r
- // Check that is conform\r
- if (!CompareBuffer(ReadBuffer,WriteBuffer,BufferSize)) {\r
- DiagnosticLog(L"ERROR: Fail to Read/Write Block (1)\n");\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- // Restore content at the original location\r
- Status = MmcWriteBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,BackBuffer);\r
- if (Status != EFI_SUCCESS) {\r
- DiagnosticLog(L"ERROR: Fail to Write Block (2)\n");\r
- return Status;\r
- }\r
-\r
- // Read the restored content\r
- Status = MmcReadBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,ReadBuffer);\r
- if (Status != EFI_SUCCESS) {\r
- DiagnosticLog(L"ERROR: Fail to Read Block (3)\n");\r
- return Status;\r
- }\r
-\r
- // Check the content is correct\r
- if (!CompareBuffer(ReadBuffer,BackBuffer,BufferSize)) {\r
- DiagnosticLog(L"ERROR: Fail to Read/Write Block (2)\n");\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-MmcDriverDiagnosticsRunDiagnostics (\r
- IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL *This,\r
- IN EFI_HANDLE ControllerHandle,\r
- IN EFI_HANDLE ChildHandle OPTIONAL,\r
- IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType,\r
- IN CHAR8 *Language,\r
- OUT EFI_GUID **ErrorType,\r
- OUT UINTN *BufferSize,\r
- OUT CHAR16 **Buffer\r
- )\r
-{\r
- LIST_ENTRY *CurrentLink;\r
- MMC_HOST_INSTANCE *MmcHostInstance;\r
- EFI_STATUS Status;\r
-\r
- if (Language == NULL ||\r
- ErrorType == NULL ||\r
- Buffer == NULL ||\r
- ControllerHandle == NULL ||\r
- BufferSize == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Status = EFI_SUCCESS;\r
- *ErrorType = NULL;\r
- *BufferSize = DIAGNOSTIC_LOGBUFFER_MAXCHAR;\r
- *Buffer = DiagnosticInitLog(DIAGNOSTIC_LOGBUFFER_MAXCHAR);\r
-\r
- DiagnosticLog(L"MMC Driver Diagnostics\n");\r
-\r
- // For each MMC instance\r
- CurrentLink = mMmcHostPool.ForwardLink;\r
- while (CurrentLink != NULL && CurrentLink != &mMmcHostPool && (Status == EFI_SUCCESS)) {\r
- MmcHostInstance = MMC_HOST_INSTANCE_FROM_LINK(CurrentLink);\r
- ASSERT(MmcHostInstance != NULL);\r
-\r
- // LBA=1 Size=BlockSize\r
- DiagnosticLog(L"MMC Driver Diagnostics - Test: First Block\n");\r
- Status = MmcReadWriteDataTest(MmcHostInstance, 1, MmcHostInstance->BlockIo.Media->BlockSize);\r
-\r
- // LBA=2 Size=BlockSize\r
- DiagnosticLog(L"MMC Driver Diagnostics - Test: Second Block\n");\r
- Status = MmcReadWriteDataTest(MmcHostInstance, 2, MmcHostInstance->BlockIo.Media->BlockSize);\r
-\r
- // LBA=10 Size=BlockSize\r
- DiagnosticLog(L"MMC Driver Diagnostics - Test: Any Block\n");\r
- Status = MmcReadWriteDataTest(MmcHostInstance, MmcHostInstance->BlockIo.Media->LastBlock >> 1, MmcHostInstance->BlockIo.Media->BlockSize);\r
-\r
- // LBA=LastBlock Size=BlockSize\r
- DiagnosticLog(L"MMC Driver Diagnostics - Test: Last Block\n");\r
- Status = MmcReadWriteDataTest(MmcHostInstance, MmcHostInstance->BlockIo.Media->LastBlock, MmcHostInstance->BlockIo.Media->BlockSize);\r
-\r
- // LBA=1 Size=2*BlockSize\r
- DiagnosticLog(L"MMC Driver Diagnostics - Test: First Block / 2 BlockSSize\n");\r
- Status = MmcReadWriteDataTest(MmcHostInstance, 1, 2*MmcHostInstance->BlockIo.Media->BlockSize);\r
-\r
- CurrentLink = CurrentLink->ForwardLink;\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-//\r
-// EFI Driver Diagnostics 2 Protocol\r
-//\r
-GLOBAL_REMOVE_IF_UNREFERENCED EFI_DRIVER_DIAGNOSTICS2_PROTOCOL gMmcDriverDiagnostics2 = {\r
- (EFI_DRIVER_DIAGNOSTICS2_RUN_DIAGNOSTICS) MmcDriverDiagnosticsRunDiagnostics,\r
- "en"\r
-};\r
+++ /dev/null
-/** @file\r
- Main file of the MMC Dxe driver. The driver entrypoint is defined into this file.\r
-\r
- Copyright (c) 2011, ARM Limited. All rights reserved.\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 <Protocol/DevicePath.h>\r
-#include <Protocol/MmcHost.h>\r
-\r
-#include <Library/BaseLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/DevicePathLib.h>\r
-#include <Library/DebugLib.h>\r
-\r
-#include "Mmc.h"\r
-\r
-EFI_BLOCK_IO_MEDIA mMmcMediaTemplate = {\r
- SIGNATURE_32('m','m','c','o'), // MediaId\r
- TRUE, // RemovableMedia\r
- FALSE, // MediaPresent\r
- FALSE, // LogicalPartition\r
- FALSE, // ReadOnly\r
- FALSE, // WriteCaching\r
- 512, // BlockSize\r
- 4, // IoAlign\r
- 0, // Pad\r
- 0 // LastBlock\r
-};\r
-\r
-//\r
-// This device structure is serviced as a header.\r
-// Its next field points to the first root bridge device node.\r
-//\r
-LIST_ENTRY mMmcHostPool;\r
-\r
-/**\r
- Initialize the MMC Host Pool to support multiple MMC devices\r
-**/\r
-VOID\r
-InitializeMmcHostPool (\r
- VOID\r
- )\r
-{\r
- InitializeListHead (&mMmcHostPool);\r
-}\r
-\r
-/**\r
- Insert a new Mmc Host controller to the pool\r
-**/\r
-VOID\r
-InsertMmcHost (\r
- IN MMC_HOST_INSTANCE *MmcHostInstance\r
- )\r
-{\r
- InsertTailList (&mMmcHostPool, &(MmcHostInstance->Link));\r
-}\r
-\r
-/*\r
- Remove a new Mmc Host controller to the pool\r
-*/\r
-VOID\r
-RemoveMmcHost (\r
- IN MMC_HOST_INSTANCE *MmcHostInstance\r
- )\r
-{\r
- RemoveEntryList (&(MmcHostInstance->Link));\r
-}\r
-\r
-MMC_HOST_INSTANCE* CreateMmcHostInstance(\r
- IN EFI_MMC_HOST_PROTOCOL* MmcHost\r
- )\r
-{\r
- EFI_STATUS Status;\r
- MMC_HOST_INSTANCE* MmcHostInstance;\r
- EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
-\r
- MmcHostInstance = AllocateZeroPool (sizeof (MMC_HOST_INSTANCE));\r
- if (MmcHostInstance == NULL) {\r
- return NULL;\r
- }\r
-\r
- MmcHostInstance->Signature = MMC_HOST_INSTANCE_SIGNATURE;\r
-\r
- MmcHostInstance->State = MmcHwInitializationState;\r
- \r
- MmcHostInstance->BlockIo.Media = AllocateCopyPool (sizeof(EFI_BLOCK_IO_MEDIA), &mMmcMediaTemplate);\r
- if (MmcHostInstance->BlockIo.Media == NULL) {\r
- goto FREE_INSTANCE;\r
- }\r
-\r
- MmcHostInstance->BlockIo.Revision = EFI_BLOCK_IO_INTERFACE_REVISION;\r
- MmcHostInstance->BlockIo.Reset = MmcReset;\r
- MmcHostInstance->BlockIo.ReadBlocks = MmcReadBlocks;\r
- MmcHostInstance->BlockIo.WriteBlocks = MmcWriteBlocks;\r
- MmcHostInstance->BlockIo.FlushBlocks = MmcFlushBlocks;\r
-\r
- MmcHostInstance->MmcHost = MmcHost;\r
-\r
- // Create DevicePath for the new MMC Host\r
- Status = MmcHost->BuildDevicePath(&NewDevicePathNode);\r
- if (EFI_ERROR (Status)) {\r
- goto FREE_MEDIA;\r
- }\r
-\r
- DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH);\r
- if (DevicePath == NULL) {\r
- goto FREE_MEDIA;\r
- }\r
- \r
- SetDevicePathEndNode (DevicePath);\r
- MmcHostInstance->DevicePath = AppendDevicePathNode (DevicePath, NewDevicePathNode);\r
-\r
- // Publish BlockIO protocol interface\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &MmcHostInstance->MmcHandle,\r
- &gEfiBlockIoProtocolGuid,&(MmcHostInstance->BlockIo),\r
- &gEfiDevicePathProtocolGuid,MmcHostInstance->DevicePath,\r
- NULL\r
- );\r
- if (EFI_ERROR(Status)) {\r
- goto FREE_DEVICE_PATH;\r
- }\r
-\r
- return MmcHostInstance;\r
-\r
-FREE_DEVICE_PATH:\r
- FreePool(DevicePath);\r
-\r
-FREE_MEDIA:\r
- FreePool(MmcHostInstance->BlockIo.Media);\r
-\r
-FREE_INSTANCE:\r
- FreePool(MmcHostInstance);\r
-\r
- return NULL;\r
-}\r
-\r
-EFI_STATUS DestroyMmcHostInstance(\r
- IN MMC_HOST_INSTANCE* MmcHostInstance\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- // Uninstall Protocol Interfaces\r
- Status = gBS->UninstallMultipleProtocolInterfaces(\r
- MmcHostInstance->MmcHandle,\r
- &gEfiBlockIoProtocolGuid,&(MmcHostInstance->BlockIo),\r
- &gEfiDevicePathProtocolGuid,MmcHostInstance->DevicePath,\r
- NULL\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- \r
- // Free Memory allocated for the instance\r
- if (MmcHostInstance->BlockIo.Media) {\r
- FreePool(MmcHostInstance->BlockIo.Media);\r
- }\r
- FreePool (MmcHostInstance);\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- This function checks if the controller implement the Mmc Host and the Device Path Protocols\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-MmcDriverBindingSupported (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- //EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
- EFI_MMC_HOST_PROTOCOL *MmcHost;\r
- EFI_DEV_PATH_PTR Node;\r
-\r
- //\r
- // Check RemainingDevicePath validation\r
- //\r
- if (RemainingDevicePath != NULL) {\r
- //\r
- // Check if RemainingDevicePath is the End of Device Path Node, \r
- // if yes, go on checking other conditions\r
- //\r
- if (!IsDevicePathEnd (RemainingDevicePath)) {\r
- //\r
- // If RemainingDevicePath isn't the End of Device Path Node,\r
- // check its validation\r
- //\r
- Node.DevPath = RemainingDevicePath;\r
- if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||\r
- Node.DevPath->SubType != HW_VENDOR_DP ||\r
- DevicePathNodeLength(Node.DevPath) != sizeof(VENDOR_DEVICE_PATH)) {\r
- return EFI_UNSUPPORTED;\r
- }\r
- }\r
- }\r
-\r
- //\r
- // Check if Mmc Host protocol is installed by platform\r
- //\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiMmcHostProtocolGuid,\r
- (VOID **) &MmcHost,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
- if (Status == EFI_ALREADY_STARTED) {\r
- return EFI_SUCCESS;\r
- }\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Close the Mmc Host used to perform the supported test\r
- //\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiMmcHostProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- \r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-MmcDriverBindingStart (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- MMC_HOST_INSTANCE *MmcHostInstance;\r
- EFI_MMC_HOST_PROTOCOL *MmcHost;\r
-\r
- //\r
- // Check RemainingDevicePath validation\r
- //\r
- if (RemainingDevicePath != NULL) {\r
- //\r
- // Check if RemainingDevicePath is the End of Device Path Node, \r
- // if yes, return EFI_SUCCESS\r
- //\r
- if (IsDevicePathEnd (RemainingDevicePath)) {\r
- return EFI_SUCCESS;\r
- }\r
- }\r
-\r
- //\r
- // Get the Mmc Host protocol\r
- //\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiMmcHostProtocolGuid,\r
- (VOID **) &MmcHost,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
- if (EFI_ERROR (Status)) {\r
- if (Status == EFI_ALREADY_STARTED) {\r
- return EFI_SUCCESS;\r
- }\r
- return Status;\r
- }\r
-\r
- MmcHostInstance = CreateMmcHostInstance(MmcHost);\r
- if (MmcHostInstance != NULL) {\r
- // Add the handle to the pool\r
- InsertMmcHost (MmcHostInstance);\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- \r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-MmcDriverBindingStop (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN UINTN NumberOfChildren,\r
- IN EFI_HANDLE *ChildHandleBuffer\r
- )\r
-{\r
- EFI_STATUS Status = EFI_SUCCESS;\r
- LIST_ENTRY *CurrentLink;\r
- MMC_HOST_INSTANCE *MmcHostInstance;\r
-\r
- MMC_TRACE("MmcDriverBindingStop()");\r
-\r
- // For each MMC instance\r
- CurrentLink = mMmcHostPool.ForwardLink;\r
- while (CurrentLink != NULL && CurrentLink != &mMmcHostPool && (Status == EFI_SUCCESS)) {\r
- MmcHostInstance = MMC_HOST_INSTANCE_FROM_LINK(CurrentLink);\r
- ASSERT(MmcHostInstance != NULL);\r
-\r
- // Close gEfiMmcHostProtocolGuid\r
- Status = gBS->CloseProtocol (\r
- Controller,\r
- &gEfiMmcHostProtocolGuid,(VOID **) &MmcHostInstance->MmcHost,\r
- This->DriverBindingHandle\r
- );\r
-\r
- // Remove MMC Host Instance from the pool\r
- RemoveMmcHost (MmcHostInstance);\r
-\r
- // Destroy MmcHostInstance\r
- DestroyMmcHostInstance (MmcHostInstance);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-EFI_DRIVER_BINDING_PROTOCOL gMmcDriverBinding = {\r
- MmcDriverBindingSupported,\r
- MmcDriverBindingStart,\r
- MmcDriverBindingStop,\r
- 0xa,\r
- NULL,\r
- NULL\r
-};\r
-\r
-/**\r
- \r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-MmcDxeInitialize (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- //\r
- // Initializes MMC Host pool\r
- //\r
- InitializeMmcHostPool ();\r
-\r
- //\r
- // Install driver model protocol(s).\r
- //\r
- Status = EfiLibInstallDriverBindingComponentName2 (\r
- ImageHandle,\r
- SystemTable,\r
- &gMmcDriverBinding,\r
- ImageHandle,\r
- &gMmcComponentName,\r
- &gMmcComponentName2\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- // Install driver diagnostics\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &ImageHandle, \r
- &gEfiDriverDiagnostics2ProtocolGuid,&gMmcDriverDiagnostics2,\r
- NULL\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- return Status;\r
-}\r
+++ /dev/null
-/** @file\r
- Main Header file for the MMC DXE driver\r
-\r
- Copyright (c) 2011, ARM Limited. All rights reserved.\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
-#ifndef __MMC_H\r
-#define __MMC_H\r
-\r
-#include <Uefi.h>\r
-\r
-#include <Protocol/DiskIo.h>\r
-#include <Protocol/BlockIo.h>\r
-#include <Protocol/DevicePath.h>\r
-#include <Protocol/MmcHost.h>\r
-\r
-#include <Library/UefiLib.h>\r
-\r
-#define MMC_TRACE(txt) DEBUG((EFI_D_BLKIO, "MMC: " txt "\n"))\r
-\r
-#define MMC_IOBLOCKS_READ 0\r
-#define MMC_IOBLOCKS_WRITE 1\r
-\r
-#define MMC_OCR_POWERUP 0x80000000\r
-\r
-#define MMC_CSD_GET_CCC(Response) (Response[1] >> 20)\r
-#define MMC_CSD_GET_TRANSPEED(Response) (Response[0] & 0xFF)\r
-#define MMC_CSD_GET_READBLLEN(Response) ((Response[1] >> 16) & 0xF)\r
-#define MMC_CSD_GET_WRITEBLLEN(Response) ((Response[3] >> 22) & 0xF)\r
-#define MMC_CSD_GET_FILEFORMAT(Response) ((Response[3] >> 10) & 0x3)\r
-#define MMC_CSD_GET_FILEFORMATGRP(Response) ((Response[3] >> 15) & 0x1)\r
-#define MMC_CSD_GET_DEVICESIZE(csd) (((Response[2] >> 30) & 0x3) | ((Response[1] & 0x3FF) << 2))\r
-#define MMC_CSD_GET_DEVICESIZEMULT(csd) ((Response[2] >> 15) & 0x7)\r
-\r
-#define MMC_R0_CURRENTSTATE(Response) ((Response[0] >> 9) & 0xF)\r
-\r
-#define MMC_R0_STATE_IDLE 0\r
-#define MMC_R0_STATE_READY 1\r
-#define MMC_R0_STATE_IDENT 2\r
-#define MMC_R0_STATE_STDBY 3\r
-#define MMC_R0_STATE_TRAN 4\r
-#define MMC_R0_STATE_DATA 5\r
-\r
-typedef enum {\r
- UNKNOWN_CARD,\r
- MMC_CARD, //MMC card\r
- MMC_CARD_HIGH, //MMC Card with High capacity\r
- SD_CARD, //SD 1.1 card\r
- SD_CARD_2, //SD 2.0 or above standard card\r
- SD_CARD_2_HIGH //SD 2.0 or above high capacity card\r
-} CARD_TYPE;\r
-\r
-typedef struct {\r
- UINT32 Reserved0: 7; // 0 \r
- UINT32 V170_V195: 1; // 1.70V - 1.95V\r
- UINT32 V200_V260: 7; // 2.00V - 2.60V\r
- UINT32 V270_V360: 9; // 2.70V - 3.60V\r
- UINT32 RESERVED_1: 5; // Reserved\r
- UINT32 AccessMode: 2; // 00b (byte mode), 10b (sector mode) \r
- UINT32 Busy: 1; // This bit is set to LOW if the card has not finished the power up routine\r
-} OCR;\r
-\r
-typedef struct {\r
- UINT32 NOT_USED; // 1 [0:0]\r
- UINT32 CRC; // CRC7 checksum [7:1]\r
- UINT32 MDT; // Manufacturing date [19:8]\r
- UINT32 RESERVED_1; // Reserved [23:20]\r
- UINT32 PSN; // Product serial number [55:24]\r
- UINT8 PRV; // Product revision [63:56]\r
- UINT8 PNM[5]; // Product name [64:103]\r
- UINT16 OID; // OEM/Application ID [119:104]\r
- UINT8 MID; // Manufacturer ID [127:120]\r
-} CID;\r
-\r
-typedef struct {\r
- UINT8 NOT_USED: 1; // Not used, always 1 [0:0]\r
- UINT8 CRC: 7; // CRC [7:1]\r
-\r
- UINT8 RESERVED_1: 2; // Reserved [9:8]\r
- UINT8 FILE_FORMAT: 2; // File format [11:10]\r
- UINT8 TMP_WRITE_PROTECT: 1; // Temporary write protection [12:12]\r
- UINT8 PERM_WRITE_PROTECT: 1; // Permanent write protection [13:13]\r
- UINT8 COPY: 1; // Copy flag (OTP) [14:14]\r
- UINT8 FILE_FORMAT_GRP: 1; // File format group [15:15]\r
- \r
- UINT16 RESERVED_2: 5; // Reserved [20:16]\r
- UINT16 WRITE_BL_PARTIAL: 1; // Partial blocks for write allowed [21:21]\r
- UINT16 WRITE_BL_LEN: 4; // Max. write data block length [25:22]\r
- UINT16 R2W_FACTOR: 3; // Write speed factor [28:26]\r
- UINT16 RESERVED_3: 2; // Reserved [30:29]\r
- UINT16 WP_GRP_ENABLE: 1; // Write protect group enable [31:31]\r
- \r
- UINT32 WP_GRP_SIZE: 7; // Write protect group size [38:32]\r
- UINT32 SECTOR_SIZE: 7; // Erase sector size [45:39]\r
- UINT32 ERASE_BLK_EN: 1; // Erase single block enable [46:46]\r
- UINT32 C_SIZE_MULT: 3; // Device size multiplier [49:47]\r
- UINT32 VDD_W_CURR_MAX: 3; // Max. write current @ VDD max [52:50]\r
- UINT32 VDD_W_CURR_MIN: 3; // Max. write current @ VDD min [55:53]\r
- UINT32 VDD_R_CURR_MAX: 3; // Max. read current @ VDD max [58:56]\r
- UINT32 VDD_R_CURR_MIN: 3; // Max. read current @ VDD min [61:59]\r
- UINT32 C_SIZELow2: 2; // Device size [63:62]\r
- \r
- UINT32 C_SIZEHigh10: 10;// Device size [73:64]\r
- UINT32 RESERVED_4: 2; // Reserved [75:74]\r
- UINT32 DSR_IMP: 1; // DSR implemented [76:76]\r
- UINT32 READ_BLK_MISALIGN: 1; // Read block misalignment [77:77]\r
- UINT32 WRITE_BLK_MISALIGN: 1; // Write block misalignment [78:78]\r
- UINT32 READ_BL_PARTIAL: 1; // Partial blocks for read allowed [79:79]\r
- UINT32 READ_BL_LEN: 4; // Max. read data block length [83:80]\r
- UINT32 CCC: 12;// Card command classes [95:84]\r
-\r
- UINT8 TRAN_SPEED ; // Max. bus clock frequency [103:96]\r
- UINT8 NSAC ; // Data read access-time 2 in CLK cycles (NSAC*100) [111:104]\r
- UINT8 TAAC ; // Data read access-time 1 [119:112]\r
- \r
- UINT8 RESERVED_5: 6; // Reserved [125:120]\r
- UINT8 CSD_STRUCTURE: 2; // CSD structure [127:126]\r
-} CSD;\r
-\r
-typedef struct {\r
- UINT16 RCA;\r
- CARD_TYPE CardType;\r
- OCR OCRData;\r
- CID CIDData;\r
- CSD CSDData;\r
-} CARD_INFO;\r
-\r
-typedef struct _MMC_HOST_INSTANCE {\r
- UINTN Signature;\r
- LIST_ENTRY Link;\r
- EFI_HANDLE MmcHandle;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
-\r
- MMC_STATE State;\r
- EFI_BLOCK_IO_PROTOCOL BlockIo;\r
- CARD_INFO CardInfo;\r
- EFI_MMC_HOST_PROTOCOL *MmcHost;\r
-} MMC_HOST_INSTANCE;\r
-\r
-#define MMC_HOST_INSTANCE_SIGNATURE SIGNATURE_32('m', 'm', 'c', 'h')\r
-#define MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS(a) CR (a, MMC_HOST_INSTANCE, BlockIo, MMC_HOST_INSTANCE_SIGNATURE)\r
-#define MMC_HOST_INSTANCE_FROM_LINK(a) CR (a, MMC_HOST_INSTANCE, Link, MMC_HOST_INSTANCE_SIGNATURE)\r
-\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-MmcGetDriverName (\r
- IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
- IN CHAR8 *Language,\r
- OUT CHAR16 **DriverName\r
- );\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-MmcGetControllerName (\r
- IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
- IN EFI_HANDLE ControllerHandle,\r
- IN EFI_HANDLE ChildHandle OPTIONAL,\r
- IN CHAR8 *Language,\r
- OUT CHAR16 **ControllerName\r
- );\r
-\r
-extern EFI_COMPONENT_NAME_PROTOCOL gMmcComponentName;\r
-extern EFI_COMPONENT_NAME2_PROTOCOL gMmcComponentName2;\r
-\r
-extern EFI_DRIVER_DIAGNOSTICS2_PROTOCOL gMmcDriverDiagnostics2;\r
-\r
-extern LIST_ENTRY mMmcHostPool;\r
-\r
-/**\r
- Reset the block device.\r
-\r
- This function implements EFI_BLOCK_IO_PROTOCOL.Reset(). \r
- It resets the block device hardware.\r
- ExtendedVerification is ignored in this implementation.\r
-\r
- @param This Indicates a pointer to the calling context.\r
- @param ExtendedVerification Indicates that the driver may perform a more exhaustive\r
- verification operation of the device during reset.\r
-\r
- @retval EFI_SUCCESS The block device was reset.\r
- @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be reset.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-MmcReset (\r
- IN EFI_BLOCK_IO_PROTOCOL *This,\r
- IN BOOLEAN ExtendedVerification\r
- );\r
-\r
-/**\r
- Reads the requested number of blocks from the device.\r
-\r
- This function implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks(). \r
- It reads the requested number of blocks from the device.\r
- All the blocks are read, or an error is returned.\r
-\r
- @param This Indicates a pointer to the calling context.\r
- @param MediaId The media ID that the read request is for.\r
- @param Lba The starting logical block address to read from on the device.\r
- @param BufferSize The size of the Buffer in bytes.\r
- This must be a multiple of the intrinsic block size of the device.\r
- @param Buffer A pointer to the destination buffer for the data. The caller is\r
- responsible for either having implicit or explicit ownership of the buffer.\r
-\r
- @retval EFI_SUCCESS The data was read correctly from the device.\r
- @retval EFI_DEVICE_ERROR The device reported an error while attempting to perform the read operation.\r
- @retval EFI_NO_MEDIA There is no media in the device.\r
- @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
- @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the intrinsic block size of the device.\r
- @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,\r
- or the buffer is not on proper alignment.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-MmcReadBlocks (\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
-/**\r
- Writes a specified number of blocks to the device.\r
-\r
- This function implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks(). \r
- It writes a specified number of blocks to the device.\r
- All blocks are written, or an error is returned.\r
-\r
- @param This Indicates a pointer to the calling context.\r
- @param MediaId The media ID that the write request is for.\r
- @param Lba The starting logical block address to be written.\r
- @param BufferSize The size of the Buffer in bytes.\r
- This must be a multiple of the intrinsic block size of the device.\r
- @param Buffer Pointer to the source buffer for the data.\r
-\r
- @retval EFI_SUCCESS The data were written correctly to the device.\r
- @retval EFI_WRITE_PROTECTED The device cannot be written to.\r
- @retval EFI_NO_MEDIA There is no media in the device.\r
- @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
- @retval EFI_DEVICE_ERROR The device reported an error while attempting to perform the write operation.\r
- @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the intrinsic\r
- block size of the device.\r
- @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,\r
- or the buffer is not on proper alignment.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-MmcWriteBlocks (\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
-/**\r
- Flushes all modified data to a physical block device.\r
-\r
- @param This Indicates a pointer to the calling context.\r
-\r
- @retval EFI_SUCCESS All outstanding data were written correctly to the device.\r
- @retval EFI_DEVICE_ERROR The device reported an error while attempting to write data.\r
- @retval EFI_NO_MEDIA There is no media in the device.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-MmcFlushBlocks (\r
- IN EFI_BLOCK_IO_PROTOCOL *This\r
- );\r
-\r
-#endif\r
+++ /dev/null
-/** @file\r
-*\r
-* Copyright (c) 2011, ARM Limited. All rights reserved.\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 <Protocol/MmcHost.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/TimerLib.h>\r
-\r
-#include "Mmc.h"\r
-\r
-// Untested ...\r
-//#define USE_STREAM\r
-\r
-#define MAX_RETRY_COUNT 1000\r
-#define CMD_RETRY_COUNT 20\r
-\r
-EFI_STATUS\r
-MmcNotifyState (\r
- MMC_HOST_INSTANCE *MmcHostInstance,\r
- MMC_STATE State\r
- ) {\r
- MmcHostInstance->State = State;\r
- return MmcHostInstance->MmcHost->NotifyState(State);\r
-}\r
-\r
-VOID PrintOCR(UINT32 ocr) {\r
- UINTN minv, maxv, volts;\r
- UINTN loop;\r
-\r
- minv = 36; // 3.6\r
- maxv = 20; // 2.0\r
- volts = 20; // 2.0\r
-\r
- // The MMC register bits [23:8] indicate the working range of the card\r
- for (loop = 8; loop < 24; loop++) {\r
- if (ocr & (1 << loop)) {\r
- if (minv > volts) minv = volts;\r
- if (maxv < volts) maxv = volts + 1;\r
- }\r
- volts = volts + 1;\r
- }\r
-\r
- DEBUG((EFI_D_ERROR, "- PrintOCR ocr (0x%X)\n",ocr));\r
- DEBUG((EFI_D_ERROR, "\t- Card operating voltage: %d.%d to %d.%d\n", minv/10, minv % 10, maxv/10, maxv % 10));\r
- if (((ocr >> 29) & 3) == 0)\r
- DEBUG((EFI_D_ERROR, "\t- AccessMode: Byte Mode\n"));\r
- else\r
- DEBUG((EFI_D_ERROR, "\t- AccessMode: Block Mode (0x%X)\n",((ocr >> 29) & 3)));\r
-\r
- if (ocr & MMC_OCR_POWERUP)\r
- DEBUG((EFI_D_ERROR, "\t- PowerUp\n"));\r
- else\r
- DEBUG((EFI_D_ERROR, "\t- Voltage Not Supported\n"));\r
-}\r
-\r
-VOID PrintCID(UINT32* cid) {\r
- DEBUG((EFI_D_ERROR, "- PrintCID\n"));\r
- DEBUG((EFI_D_ERROR, "\t- Manufacturing date: %d/%d\n",(cid[0] >> 8) & 0xF,(cid[0] >> 12) & 0xFF));\r
- DEBUG((EFI_D_ERROR, "\t- Product serial number: 0x%X%X\n",cid[1] & 0xFFFFFF,(cid[0] >> 24) & 0xFF));\r
- DEBUG((EFI_D_ERROR, "\t- Product revision: %d\n",cid[1] >> 24));\r
- //DEBUG((EFI_D_ERROR, "\t- Product name: %s\n",(char*)(cid + 2)));\r
- DEBUG((EFI_D_ERROR, "\t- OEM ID: %c%c\n",(cid[3] >> 8) & 0xFF,(cid[3] >> 16) & 0xFF));\r
-}\r
-\r
-VOID PrintCSD(UINT32* csd) {\r
- UINTN val32;\r
- CONST CHAR8* str_unit[] = { "100kbit/s","1Mbit/s","10Mbit/s","100MBit/s","Unkbown","Unkbown","Unkbown","Unkbown" };\r
- CONST CHAR8* str_value[] = { "1.0","1.2","1.3","1.5","2.0","2.5","3.0","3.5","4.0","4.5","5.0","Unknown","Unknown","Unknown","Unknown" };\r
-\r
- if (((csd[2] >> 30) & 0x3) == 0)\r
- DEBUG((EFI_D_ERROR, "- PrintCSD Version 1.01-1.10/Version 2.00/Standard Capacity\n"));\r
- else if (((csd[2] >> 30) & 0x3) == 1)\r
- DEBUG((EFI_D_ERROR, "- PrintCSD Version 2.00/High Capacity\n"));\r
- else\r
- DEBUG((EFI_D_ERROR, "- PrintCSD Version Higher than v3.3\n"));\r
-\r
- DEBUG((EFI_D_ERROR, "\t- Supported card command class: 0x%X\n",MMC_CSD_GET_CCC(csd)));\r
- DEBUG((EFI_D_ERROR, "\t- Speed: %a %a\n",str_value[(MMC_CSD_GET_TRANSPEED(csd) >> 3) & 0xF],str_unit[MMC_CSD_GET_TRANSPEED(csd) & 7]));\r
- DEBUG((EFI_D_ERROR, "\t- Maximum Read Data Block: %d\n",2 << (MMC_CSD_GET_READBLLEN(csd)-1)));\r
- DEBUG((EFI_D_ERROR, "\t- Maximum Write Data Block: %d\n",2 << (MMC_CSD_GET_WRITEBLLEN(csd)-1)));\r
- \r
- if (!MMC_CSD_GET_FILEFORMATGRP(csd)) {\r
- val32 = MMC_CSD_GET_FILEFORMAT(csd);\r
- if (val32 == 0) DEBUG((EFI_D_ERROR, "\t- Format(0): Hard disk-like file system with partition table\n"));\r
- else if (val32 == 1) DEBUG((EFI_D_ERROR, "\t- Format(1): DOS FAT (floppy-like) with boot sector only (no partition table)\n"));\r
- else if (val32 == 2) DEBUG((EFI_D_ERROR, "\t- Format(2): Universal File Format\n"));\r
- else DEBUG((EFI_D_ERROR, "\t- Format(3): Others/Unknown\n"));\r
- } else {\r
- DEBUG((EFI_D_ERROR, "\t- Format: Reserved\n"));\r
- }\r
-}\r
-\r
-VOID PrintRCA(UINT32 rca) {\r
- DEBUG((EFI_D_ERROR, "- PrintRCA: 0x%X\n",rca));\r
- DEBUG((EFI_D_ERROR, "\t- Status: 0x%X\n",rca & 0xFFFF));\r
- DEBUG((EFI_D_ERROR, "\t- RCA: 0x%X\n",(rca >> 16) & 0xFFFF));\r
-}\r
-\r
-VOID PrintResponseR1(UINT32 response) {\r
- DEBUG((EFI_D_INFO, "Response: 0x%X\n",response));\r
- if (response & (1 << 8)) DEBUG((EFI_D_INFO, "\t- READY_FOR_DATA\n"));\r
-\r
- if (((response >> 9) & 0xF) == 0) DEBUG((EFI_D_INFO, "\t- State: Idle\n"));\r
- else if (((response >> 9) & 0xF) == 1) DEBUG((EFI_D_INFO, "\t- State: Ready\n"));\r
- else if (((response >> 9) & 0xF) == 2) DEBUG((EFI_D_INFO, "\t- State: Ident\n"));\r
- else if (((response >> 9) & 0xF) == 3) DEBUG((EFI_D_INFO, "\t- State: StandBy\n"));\r
- else if (((response >> 9) & 0xF) == 4) DEBUG((EFI_D_INFO, "\t- State: Tran\n"));\r
- else if (((response >> 9) & 0xF) == 5) DEBUG((EFI_D_INFO, "\t- State: Data\n"));\r
- else if (((response >> 9) & 0xF) == 6) DEBUG((EFI_D_INFO, "\t- State: Rcv\n"));\r
- else if (((response >> 9) & 0xF) == 7) DEBUG((EFI_D_INFO, "\t- State: Prg\n"));\r
- else if (((response >> 9) & 0xF) == 8) DEBUG((EFI_D_INFO, "\t- State: Dis\n"));\r
- else DEBUG((EFI_D_INFO, "\t- State: Reserved\n"));\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-MmcGetCardStatus(\r
- MMC_HOST_INSTANCE *MmcHostInstance\r
- ){\r
- EFI_STATUS Status=EFI_SUCCESS;\r
- UINT32 Response[4];\r
- UINTN CmdArg;\r
- EFI_MMC_HOST_PROTOCOL *MmcHost;\r
-\r
- MmcHost = MmcHostInstance->MmcHost;\r
- CmdArg = 0;\r
-\r
- if (MmcHost == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- if(MmcHostInstance->State != MmcHwInitializationState){\r
- //Get the Status of the card.\r
- CmdArg = MmcHostInstance->CardInfo.RCA << 16;\r
- Status = MmcHost->SendCommand(MMC_CMD13, CmdArg);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_ERROR, "MmcGetCardStatus(MMC_CMD13): Error and Status = %r\n", Status));\r
- ASSERT(0);\r
- return Status;\r
- }\r
-\r
- //Read Response\r
- MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_R1,Response);\r
- PrintResponseR1(Response[0]);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-MmcIdentificationMode (\r
- MMC_HOST_INSTANCE *MmcHostInstance\r
- ) {\r
- EFI_STATUS Status;\r
- UINT32 Response[4];\r
- UINTN Timeout;\r
- UINTN CmdArg;\r
- BOOLEAN bHCS;\r
- EFI_MMC_HOST_PROTOCOL *MmcHost;\r
- UINTN CmdRetryCnt;\r
- \r
- MmcHost = MmcHostInstance->MmcHost;\r
- CmdArg = 0;\r
- bHCS = FALSE;\r
-\r
- if (MmcHost == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- // We can get into this function if we restart the identification mode\r
- if (MmcHostInstance->State == MmcHwInitializationState) {\r
- // Initialize the MMC Host HW\r
- Status = MmcNotifyState (MmcHostInstance, MmcHwInitializationState);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcHwInitializationState\n"));\r
- return Status;\r
- }\r
- } else {\r
- //Note: Could even be used in all cases. But it looks this command could put the state machine into inactive for some cards\r
- Status = MmcHost->SendCommand(MMC_CMD0, 0);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD0): Error\n"));\r
- return Status;\r
- }\r
- }\r
-\r
- Status = MmcNotifyState (MmcHostInstance, MmcIdleState);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcIdleState\n"));\r
- return Status;\r
- }\r
-\r
- // Are we using SDIO ?\r
- Status = MmcHost->SendCommand(MMC_CMD5, 0);\r
- if (Status == EFI_SUCCESS) {\r
- DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD5): Error - SDIO not supported.\n"));\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- // Check which kind of card we are using. Ver2.00 or later SD Memory Card (PL180 is SD v1.1)\r
- CmdArg = (0x0UL << 12 | BIT8 | 0xCEUL << 0);\r
- Status = MmcHost->SendCommand(MMC_CMD8, CmdArg);\r
- if (Status == EFI_SUCCESS) {\r
- DEBUG ((EFI_D_ERROR, "Card is SD2.0 => Supports high capacity\n"));\r
- bHCS = TRUE;\r
- MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_R7,Response);\r
- PrintResponseR1(Response[0]);\r
- //check if it is valid response\r
- if(Response[0] != CmdArg){\r
- DEBUG ((EFI_D_ERROR, "The Card is not usable\n"));\r
- return EFI_UNSUPPORTED;\r
- }\r
- } else {\r
- DEBUG ((EFI_D_ERROR, "Not a SD2.0 Card\n"));\r
- }\r
-\r
- // We need to wait for the MMC or SD card is ready => (gCardInfo.OCRData.Busy == 1)\r
- Timeout = MAX_RETRY_COUNT;\r
- while (Timeout > 0) {\r
- // SD Card or MMC Card ? CMD55 indicates to the card that the next command is an application specific command\r
- Status = MmcHost->SendCommand(MMC_CMD55, 0);\r
- if (Status == EFI_SUCCESS) {\r
- DEBUG ((EFI_D_INFO, "Card should be SD\n"));\r
- if (bHCS) {\r
- MmcHostInstance->CardInfo.CardType = SD_CARD_2;\r
- } else {\r
- MmcHostInstance->CardInfo.CardType = SD_CARD;\r
- }\r
-\r
- // Note: The first time CmdArg will be zero\r
- CmdArg = ((UINTN *) &(MmcHostInstance->CardInfo.OCRData))[0];\r
- if (bHCS) {\r
- CmdArg |= BIT30;\r
- }\r
- Status = MmcHost->SendCommand(MMC_ACMD41, CmdArg);\r
- if (!EFI_ERROR(Status)) {\r
- MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_OCR,Response);\r
- ((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0];\r
- }\r
- } else {\r
- DEBUG ((EFI_D_INFO, "Card should be MMC\n"));\r
- MmcHostInstance->CardInfo.CardType = MMC_CARD;\r
-\r
- Status = MmcHost->SendCommand(MMC_CMD1, 0x800000);\r
- if (!EFI_ERROR(Status)) {\r
- MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_OCR,Response);\r
- ((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0];\r
- }\r
- }\r
-\r
- if (!EFI_ERROR(Status)) {\r
- if (MmcHostInstance->CardInfo.OCRData.Busy == 0) {\r
- MicroSecondDelay(1);\r
- Timeout--;\r
- } else {\r
- if ((MmcHostInstance->CardInfo.CardType == SD_CARD_2) && (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1)) {\r
- MmcHostInstance->CardInfo.CardType = SD_CARD_2_HIGH;\r
- DEBUG ((EFI_D_ERROR, "High capacity card.\n"));\r
- }\r
- break; // The MMC/SD card is ready. Continue the Identification Mode\r
- }\r
- } else {\r
- MicroSecondDelay(1);\r
- Timeout--;\r
- }\r
- }\r
-\r
- if (Timeout == 0) {\r
- DEBUG((EFI_D_ERROR, "MmcIdentificationMode(): No Card\n"));\r
- ASSERT(0);\r
- return EFI_NO_MEDIA;\r
- } else {\r
- PrintOCR(Response[0]);\r
- }\r
-\r
- Status = MmcNotifyState (MmcHostInstance, MmcReadyState);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcReadyState\n"));\r
- return Status;\r
- }\r
-\r
- Status = MmcHost->SendCommand(MMC_CMD2, 0);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD2): Error\n"));\r
- ASSERT(0);\r
- return Status;\r
- }\r
- MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_CID,Response);\r
- PrintCID(Response);\r
-\r
- Status = MmcNotifyState (MmcHostInstance, MmcIdentificationState);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcIdentificationState\n"));\r
- return Status;\r
- }\r
-\r
- CmdArg = 0;\r
- CmdRetryCnt = CMD_RETRY_COUNT;\r
- //Keep sending CMD 3 until card enters to Standby mode and Card status is ready\r
- while((MMC_R0_CURRENTSTATE(Response) != MMC_R0_STATE_STDBY) && CmdRetryCnt-- ){\r
- Status = MmcHost->SendCommand(MMC_CMD3, CmdArg);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD3): Error\n"));\r
- return Status;\r
- }\r
- MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_RCA,Response);\r
- PrintRCA(Response[0]);\r
- }\r
-\r
- // For MMC card, RCA is assigned by CMD3 while CMD3 dumps the RCA for SD card\r
- if (MmcHostInstance->CardInfo.CardType != MMC_CARD) {\r
- MmcHostInstance->CardInfo.RCA = Response[0] >> 16;\r
- } else {\r
- MmcHostInstance->CardInfo.RCA = CmdArg;\r
- }\r
-\r
- Status = MmcNotifyState (MmcHostInstance, MmcStandByState);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcStandByState\n"));\r
- return Status;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-MmcReset (\r
- IN EFI_BLOCK_IO_PROTOCOL *This,\r
- IN BOOLEAN ExtendedVerification\r
- ) {\r
- // Implement me. Either send a CMD0 (could not work for some MMC host) or just turn off/turn\r
- // on power and restart Identification mode\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-MmcDetectCard (\r
- EFI_MMC_HOST_PROTOCOL *MmcHost\r
- )\r
-{\r
- if (!MmcHost->IsCardPresent()) {\r
- return EFI_NO_MEDIA;\r
- } else {\r
- return EFI_SUCCESS;\r
- }\r
-}\r
-\r
-#define MMCI0_BLOCKLEN 512\r
-#define MMCI0_TIMEOUT 10000\r
-\r
-EFI_STATUS MmcIoBlocks (\r
- IN EFI_BLOCK_IO_PROTOCOL *This,\r
- IN UINTN Transfer,\r
- IN UINT32 MediaId,\r
- IN EFI_LBA Lba,\r
- IN UINTN BufferSize,\r
- OUT VOID *Buffer\r
- ) {\r
- UINT32 Response[4];\r
- EFI_STATUS Status;\r
- UINTN CardSize, NumBlocks, BlockSize, CmdArg;\r
- UINTN Timeout;\r
- UINTN Cmd;\r
- MMC_HOST_INSTANCE *MmcHostInstance;\r
- EFI_MMC_HOST_PROTOCOL *MmcHost;\r
- UINTN BytesRemainingToBeTransfered;\r
- UINTN BlockCount = 1;\r
-\r
- MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS(This);\r
- ASSERT(MmcHostInstance != 0);\r
- MmcHost = MmcHostInstance->MmcHost;\r
- ASSERT(MmcHost);\r
-\r
- if (MmcHost == 0) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- // Check if a Card is Present\r
- if (!MmcHost->IsCardPresent()) {\r
- MmcHostInstance->BlockIo.Media->MediaPresent = FALSE;\r
- MmcHostInstance->BlockIo.Media->LastBlock = 0;\r
- MmcHostInstance->BlockIo.Media->BlockSize = 512; // Should be zero but there is a bug in DiskIo\r
- MmcHostInstance->BlockIo.Media->ReadOnly = FALSE; \r
- return EFI_NO_MEDIA;\r
- }\r
-\r
- // If the driver has not been initialized yet then go into Iddentification Mode\r
- if (MmcHostInstance->State == MmcHwInitializationState) {\r
- MmcIdentificationMode (MmcHostInstance);\r
-\r
- //Send a command to get Card specific data\r
- CmdArg = MmcHostInstance->CardInfo.RCA << 16;\r
- Status = MmcHost->SendCommand(MMC_CMD9, CmdArg);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD9): Error, Status=%r\n", Status));\r
- ASSERT(0);\r
- return Status;\r
- }\r
- //Read Response\r
- MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_CSD,Response);\r
- PrintCSD(Response);\r
-\r
- if (MmcHostInstance->CardInfo.CardType == SD_CARD_2_HIGH) {\r
- ASSERT(0); //TODO: Implementation needed\r
- CardSize = MMC_CSD_GET_DEVICESIZE(Response);\r
- NumBlocks = ((CardSize + 1) * 1024);;\r
- BlockSize = 1 << MMC_CSD_GET_READBLLEN(Response);\r
- } else {\r
- CardSize = MMC_CSD_GET_DEVICESIZE(Response);\r
- NumBlocks = (CardSize + 1) * (1 << (MMC_CSD_GET_DEVICESIZEMULT(Response) + 2));\r
- BlockSize = 1 << MMC_CSD_GET_READBLLEN(Response);\r
- }\r
-\r
- //For >=2G card, BlockSize may be 1K, but the transfer size is 512 bytes.\r
- if (BlockSize > 512) {\r
- NumBlocks = MultU64x32(NumBlocks, BlockSize/512);\r
- BlockSize = 512; \r
- }\r
-\r
- MmcHostInstance->BlockIo.Media->LastBlock = (NumBlocks - 1);\r
- MmcHostInstance->BlockIo.Media->BlockSize = BlockSize;\r
- MmcHostInstance->BlockIo.Media->ReadOnly = MmcHost->IsReadOnly();\r
- MmcHostInstance->BlockIo.Media->MediaPresent = TRUE; \r
- MmcHostInstance->BlockIo.Media->MediaId++; \r
-\r
- CmdArg = MmcHostInstance->CardInfo.RCA << 16;\r
- Status = MmcHost->SendCommand(MMC_CMD7, CmdArg);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD7): Error and Status = %r\n", Status));\r
- ASSERT(0);\r
- return Status;\r
- }\r
-\r
- Status = MmcNotifyState (MmcHostInstance, MmcTransferState);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcTransferState\n"));\r
- return Status;\r
- }\r
- } else {\r
- // Maybe test if the card has changed to update gMmcMedia information\r
- if (MmcHostInstance->State == MmcTransferState) {\r
- //DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : MmcTransferState\n"));\r
- } else if (MmcHostInstance->State == MmcStandByState) {\r
- DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : MmcStandByState\n"));\r
- } else {\r
- ASSERT(0);\r
- }\r
- }\r
-\r
- if (Lba > This->Media->LastBlock) {\r
- ASSERT(0);\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- \r
- if ((BufferSize % This->Media->BlockSize) != 0) {\r
- ASSERT(0);\r
- return EFI_BAD_BUFFER_SIZE;\r
- }\r
-\r
- BytesRemainingToBeTransfered = BufferSize;\r
- while (BytesRemainingToBeTransfered > 0) {\r
-\r
- //Check if the Card is in Ready status\r
- CmdArg = MmcHostInstance->CardInfo.RCA << 16;\r
- Response[0] = 0;\r
- Timeout = 20;\r
- while((Response[0] & (1 << 8)) && Timeout-- ){\r
- Status = MmcHost->SendCommand(MMC_CMD13, CmdArg);\r
- if (!EFI_ERROR(Status)){\r
- MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_R1,Response);\r
- }\r
- }\r
-\r
- // Set Block Length\r
- Status = MmcHost->SendCommand(MMC_CMD16, This->Media->BlockSize);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD16): Error This->Media->BlockSize:%d and Error = %r\n",This->Media->BlockSize, Status));\r
- return Status;\r
- }\r
-\r
- // Block Count (not used). Could return an error for SD card\r
- MmcHost->SendCommand(MMC_CMD23, BlockCount);\r
-\r
- //Set command argument based on the card access mode (Byte mode or Block mode)\r
- if (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1) {\r
- CmdArg = Lba;\r
- } else {\r
- CmdArg = Lba * This->Media->BlockSize;\r
- }\r
-\r
- if (Transfer == MMC_IOBLOCKS_READ) {\r
-#ifndef USE_STREAM\r
- // Read a single block\r
- Cmd = MMC_CMD17;\r
-#else\r
- //TODO: Should we support read stream (MMC_CMD11)\r
-#endif\r
- } else {\r
-#ifndef USE_STREAM\r
- // Write a single block\r
- Cmd = MMC_CMD24;\r
-#else\r
- //TODO: Should we support write stream (MMC_CMD20)\r
-#endif\r
- }\r
- Status = MmcHost->SendCommand(Cmd, CmdArg);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD%d): Error %r\n",Cmd, Status));\r
- return Status;\r
- }\r
-\r
- if (Transfer == MMC_IOBLOCKS_READ) {\r
-#ifndef USE_STREAM\r
- // Read one block of Data\r
- Status = MmcHost->ReadBlockData(Lba,This->Media->BlockSize,Buffer);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_BLKIO, "MmcIdentificationMode(): Error Read Block Data and Status = %r\n", Status));\r
- return Status;\r
- }\r
-#else\r
- //TODO: Read a steam\r
- ASSERT(0);\r
-#endif\r
- Status = MmcNotifyState (MmcHostInstance, MmcProgrammingState);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcProgrammingState\n"));\r
- return Status;\r
- }\r
- } else {\r
-#ifndef USE_STREAM\r
- // Write one block of Data\r
- Status = MmcHost->WriteBlockData(Lba,This->Media->BlockSize,Buffer);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_BLKIO, "MmcIdentificationMode(): Error Write Block Data and Status = %r\n", Status));\r
- return Status;\r
- }\r
-#else\r
- //TODO: Write a steam\r
- ASSERT(0);\r
-#endif\r
- }\r
-\r
- // Command 12 - Stop transmission (ends read)\r
- Status = MmcHost->SendCommand(MMC_CMD12, 0);\r
- MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_R1b,Response);\r
-\r
- // Command 13 - Read status and wait for programming to complete (return to tran)\r
- Timeout = MMCI0_TIMEOUT;\r
- CmdArg = MmcHostInstance->CardInfo.RCA << 16;\r
- while ((MMC_R0_CURRENTSTATE(Response) != MMC_R0_STATE_TRAN) && Timeout) {\r
- MmcHost->SendCommand(MMC_CMD13, CmdArg);\r
- MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_R1,Response);\r
- NanoSecondDelay(100);\r
- Timeout--;\r
- }\r
-\r
- Status = MmcNotifyState (MmcHostInstance, MmcTransferState);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcTransferState\n"));\r
- return Status;\r
- }\r
-\r
- BytesRemainingToBeTransfered -= This->Media->BlockSize;\r
- Lba += BlockCount;\r
- Buffer = (UINT8 *)Buffer + This->Media->BlockSize;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-MmcReadBlocks (\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
- return MmcIoBlocks (This, MMC_IOBLOCKS_READ, MediaId, Lba, BufferSize, Buffer);\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-MmcWriteBlocks (\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
- return MmcIoBlocks (This, MMC_IOBLOCKS_WRITE, MediaId, Lba, BufferSize, Buffer);\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-MmcFlushBlocks (\r
- IN EFI_BLOCK_IO_PROTOCOL *This\r
- ) {\r
- return EFI_SUCCESS;\r
-}\r
-\r
+++ /dev/null
-#/** @file\r
-# Build file for the MMC DXE driver\r
-#\r
-# Copyright (c) 2011, ARM Limited. All rights reserved.\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
-[Defines]\r
- INF_VERSION = 0x00010005\r
- BASE_NAME = MmcDxe\r
- FILE_GUID = b6f44cc0-9e45-11df-be21-0002a5d5c51b\r
- MODULE_TYPE = DXE_DRIVER\r
- VERSION_STRING = 1.0\r
-\r
- ENTRY_POINT = MmcDxeInitialize\r
-\r
-[Sources.common]\r
- ComponentName.c\r
- Mmc.c\r
- MmcBlockIo.c\r
- Diagnostics.c\r
-\r
-[Packages]\r
- ArmPkg/ArmPkg.dec\r
- MdePkg/MdePkg.dec\r
-\r
-[LibraryClasses]\r
- BaseLib\r
- UefiLib\r
- UefiDriverEntryPoint\r
- BaseMemoryLib\r
- TimerLib\r
-\r
-[Protocols]\r
- gEfiDiskIoProtocolGuid\r
- gEfiBlockIoProtocolGuid\r
- gEfiDevicePathProtocolGuid\r
- gEfiMmcHostProtocolGuid\r
- gEfiDriverDiagnostics2ProtocolGuid\r
- \r
-[Depex]\r
- TRUE
\ No newline at end of file
#
# Multimedia Card Interface
#
- ArmPkg/Universal/MmcDxe/MmcDxe.inf
+ EmbeddedPkg/Universal/MmcDxe/MmcDxe.inf
ArmPkg/Drivers/PL180MciDxe/PL180MciDxe.inf
#
#
# Multimedia Card Interface
#
- INF ArmPkg/Universal/MmcDxe/MmcDxe.inf
+ INF EmbeddedPkg/Universal/MmcDxe/MmcDxe.inf
INF ArmPkg/Drivers/PL180MciDxe/PL180MciDxe.inf
#
gEmbeddedExternalDeviceProtocolGuid = { 0x735F8C64, 0xD696, 0x44D0, { 0xBD, 0xF2, 0x44, 0x7F, 0xD0, 0x5A, 0x54, 0x06 }}\r
gEmbeddedGpioProtocolGuid = { 0x17a0a3d7, 0xc0a5, 0x4635, { 0xbb, 0xd5, 0x07, 0x21, 0x87, 0xdf, 0xe2, 0xee }}\r
gPeCoffLoaderProtocolGuid = { 0xB323179B, 0x97FB, 0x477E, { 0xB0, 0xFE, 0xD8, 0x85, 0x91, 0xFA, 0x11, 0xAB } }\r
- \r
+ gEfiMmcHostProtocolGuid = { 0x3e591c00, 0x9e4a, 0x11df, {0x92, 0x44, 0x00, 0x02, 0xA5, 0xD5, 0xC5, 0x1B }}\r
+\r
[PcdsFeatureFlag.common]\r
gEmbeddedTokenSpaceGuid.PcdEmbeddedMacBoot|FALSE|BOOLEAN|0x00000001\r
gEmbeddedTokenSpaceGuid.PcdEmbeddedDirCmd|TRUE|BOOLEAN|0x00000002\r
EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf
EmbeddedPkg/MetronomeDxe/MetronomeDxe.inf
+ EmbeddedPkg/Universal/MmcDxe/MmcDxe.inf
--- /dev/null
+/** @file\r
+ Definition of the MMC Host Protocol\r
+\r
+ Copyright (c) 2011, ARM Limited. All rights reserved.\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
+#ifndef __MMC_HOST_H__\r
+#define __MMC_HOST_H__\r
+\r
+///\r
+/// Global ID for the MMC Host Protocol\r
+///\r
+#define EFI_MMC_HOST_PROTOCOL_GUID \\r
+ { 0x3e591c00, 0x9e4a, 0x11df, {0x92, 0x44, 0x00, 0x02, 0xA5, 0xD5, 0xC5, 0x1B } }\r
+\r
+#define MMC_RESPONSE_TYPE_R1 0\r
+#define MMC_RESPONSE_TYPE_R1b 0\r
+#define MMC_RESPONSE_TYPE_R2 1\r
+#define MMC_RESPONSE_TYPE_R3 0\r
+#define MMC_RESPONSE_TYPE_R6 0\r
+#define MMC_RESPONSE_TYPE_R7 0\r
+#define MMC_RESPONSE_TYPE_OCR 0\r
+#define MMC_RESPONSE_TYPE_CID 1\r
+#define MMC_RESPONSE_TYPE_CSD 1\r
+#define MMC_RESPONSE_TYPE_RCA 0\r
+\r
+typedef UINT32 MMC_RESPONSE_TYPE;\r
+\r
+typedef UINT32 MMC_CMD;\r
+\r
+#define MMC_CMD_WAIT_RESPONSE (1 << 16)\r
+#define MMC_CMD_LONG_RESPONSE (1 << 17)\r
+#define MMC_CMD_NO_CRC_RESPONSE (1 << 18)\r
+\r
+#define MMC_INDX(Index) ((Index) & 0xFFFF)\r
+#define MMC_GET_INDX(MmcCmd) ((MmcCmd) & 0xFFFF)\r
+\r
+#define MMC_CMD0 (MMC_INDX(0) | MMC_CMD_NO_CRC_RESPONSE)\r
+#define MMC_CMD1 (MMC_INDX(1) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_NO_CRC_RESPONSE)\r
+#define MMC_CMD2 (MMC_INDX(2) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_LONG_RESPONSE)\r
+#define MMC_CMD3 (MMC_INDX(3) | MMC_CMD_WAIT_RESPONSE)\r
+#define MMC_CMD5 (MMC_INDX(5) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_NO_CRC_RESPONSE)\r
+#define MMC_CMD7 (MMC_INDX(7) | MMC_CMD_WAIT_RESPONSE)\r
+#define MMC_CMD8 (MMC_INDX(8) | MMC_CMD_WAIT_RESPONSE)\r
+#define MMC_CMD9 (MMC_INDX(9) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_LONG_RESPONSE)\r
+#define MMC_CMD11 (MMC_INDX(11) | MMC_CMD_WAIT_RESPONSE)\r
+#define MMC_CMD12 (MMC_INDX(12) | MMC_CMD_WAIT_RESPONSE)\r
+#define MMC_CMD13 (MMC_INDX(13) | MMC_CMD_WAIT_RESPONSE)\r
+#define MMC_CMD16 (MMC_INDX(16) | MMC_CMD_WAIT_RESPONSE)\r
+#define MMC_CMD17 (MMC_INDX(17) | MMC_CMD_WAIT_RESPONSE)\r
+#define MMC_CMD18 (MMC_INDX(18) | MMC_CMD_WAIT_RESPONSE)\r
+#define MMC_CMD20 (MMC_INDX(20) | MMC_CMD_WAIT_RESPONSE)\r
+#define MMC_CMD23 (MMC_INDX(23) | MMC_CMD_WAIT_RESPONSE)\r
+#define MMC_CMD24 (MMC_INDX(24) | MMC_CMD_WAIT_RESPONSE)\r
+#define MMC_CMD55 (MMC_INDX(55) | MMC_CMD_WAIT_RESPONSE)\r
+#define MMC_ACMD41 (MMC_INDX(41) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_NO_CRC_RESPONSE)\r
+\r
+typedef enum _MMC_STATE {\r
+ MmcInvalidState = 0,\r
+ MmcHwInitializationState,\r
+ MmcIdleState,\r
+ MmcReadyState,\r
+ MmcIdentificationState,\r
+ MmcStandByState,\r
+ MmcTransferState,\r
+ MmcSendingDataState,\r
+ MmcReceiveDataState,\r
+ MmcProgrammingState,\r
+ MmcDisconnectState,\r
+} MMC_STATE;\r
+\r
+typedef BOOLEAN (*MMC_ISCARDPRESENT)();\r
+\r
+typedef BOOLEAN (*MMC_ISREADONLY)();\r
+\r
+typedef EFI_STATUS (*MMC_BUILDDEVICEPATH)(EFI_DEVICE_PATH_PROTOCOL **DevicePath);\r
+\r
+typedef EFI_STATUS (*MMC_NOTIFYSTATE)(MMC_STATE State);\r
+\r
+typedef EFI_STATUS (*MMC_SENDCOMMAND)(MMC_CMD Cmd, UINT32 Argument);\r
+\r
+typedef EFI_STATUS (*MMC_RECEIVERESPONSE)(MMC_RESPONSE_TYPE Type, UINT32* Buffer);\r
+\r
+typedef EFI_STATUS (*MMC_READBLOCKDATA)(EFI_LBA Lba, UINTN Length, UINT32* Buffer);\r
+\r
+typedef EFI_STATUS (*MMC_WRITEBLOCKDATA)(EFI_LBA Lba, UINTN Length, UINT32* Buffer);\r
+\r
+typedef struct _EFI_MMC_HOST_PROTOCOL {\r
+ MMC_ISCARDPRESENT IsCardPresent;\r
+ MMC_ISREADONLY IsReadOnly;\r
+ MMC_BUILDDEVICEPATH BuildDevicePath;\r
+\r
+ MMC_NOTIFYSTATE NotifyState;\r
+\r
+ MMC_SENDCOMMAND SendCommand;\r
+ MMC_RECEIVERESPONSE ReceiveResponse;\r
+\r
+ MMC_READBLOCKDATA ReadBlockData;\r
+ MMC_WRITEBLOCKDATA WriteBlockData;\r
+} EFI_MMC_HOST_PROTOCOL;\r
+\r
+extern EFI_GUID gEfiMmcHostProtocolGuid;\r
+\r
+#endif\r
+\r
--- /dev/null
+/** @file\r
+ Component Name Protocol implementation for the MMC DXE driver\r
+\r
+ Copyright (c) 2011, ARM Limited. All rights reserved.\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 "Mmc.h"\r
+\r
+//\r
+// EFI Component Name Protocol\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gMmcComponentName = {\r
+ MmcGetDriverName,\r
+ MmcGetControllerName,\r
+ "eng"\r
+};\r
+\r
+//\r
+// EFI Component Name 2 Protocol\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gMmcComponentName2 = {\r
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) MmcGetDriverName,\r
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) MmcGetControllerName,\r
+ "en"\r
+};\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE\r
+mMmcDriverNameTable[] = {\r
+ {"eng;en", L"MMC/SD Card Interface Driver"},\r
+ {NULL, NULL}\r
+};\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+ This function retrieves the user readable name of a driver in the form of a\r
+ Unicode string. If the driver specified by This has a user readable name in\r
+ the language specified by Language, then a pointer to the driver name is\r
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+ by This does not support the language specified by Language,\r
+ then EFI_UNSUPPORTED is returned.\r
+\r
+ @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+ @param Language A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified\r
+ in RFC 4646 or ISO 639-2 language code format.\r
+ @param DriverName A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ driver specified by This in the language\r
+ specified by Language.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by\r
+ This and the language specified by Language was\r
+ returned in DriverName.\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MmcGetDriverName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **DriverName\r
+ )\r
+{\r
+ return LookupUnicodeString2 (\r
+ Language,\r
+ This->SupportedLanguages,\r
+ mMmcDriverNameTable,\r
+ DriverName,\r
+ (BOOLEAN)(This == &gMmcComponentName)\r
+ );\r
+}\r
+\r
+/**\r
+ Retrieves a Unicode string that is the user readable name of the controller\r
+ that is being managed by a driver.\r
+\r
+ This function retrieves the user readable name of the controller specified by\r
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+ driver specified by This has a user readable name in the language specified by\r
+ Language, then a pointer to the controller name is returned in ControllerName,\r
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently\r
+ managing the controller specified by ControllerHandle and ChildHandle,\r
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not\r
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+ @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+ EFI_COMPONENT_NAME_PROTOCOL instance.\r
+ @param ControllerHandle The handle of a controller that the driver\r
+ specified by This is managing. This handle\r
+ specifies the controller whose name is to be\r
+ returned.\r
+ @param ChildHandle The handle of the child controller to retrieve\r
+ the name of. This is an optional parameter that\r
+ may be NULL. It will be NULL for device\r
+ drivers. It will also be NULL for a bus drivers\r
+ that wish to retrieve the name of the bus\r
+ controller. It will not be NULL for a bus\r
+ driver that wishes to retrieve the name of a\r
+ child controller.\r
+ @param Language A pointer to a Null-terminated ASCII string\r
+ array indicating the language. This is the\r
+ language of the driver name that the caller is\r
+ requesting, and it must match one of the\r
+ languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up\r
+ to the driver writer. Language is specified in\r
+ RFC 4646 or ISO 639-2 language code format.\r
+ @param ControllerName A pointer to the Unicode string to return.\r
+ This Unicode string is the name of the\r
+ controller specified by ControllerHandle and\r
+ ChildHandle in the language specified by\r
+ Language from the point of view of the driver\r
+ specified by This.\r
+\r
+ @retval EFI_SUCCESS The Unicode string for the user readable name in\r
+ the language specified by Language for the\r
+ driver specified by This was returned in\r
+ DriverName.\r
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.\r
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+ EFI_HANDLE.\r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently\r
+ managing the controller specified by\r
+ ControllerHandle and ChildHandle.\r
+ @retval EFI_UNSUPPORTED The driver specified by This does not support\r
+ the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MmcGetControllerName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle OPTIONAL,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **ControllerName\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
--- /dev/null
+/** @file\r
+ Diagnostics Protocol implementation for the MMC DXE driver\r
+\r
+ Copyright (c) 2011, ARM Limited. All rights reserved.\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 <Uefi.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+\r
+#include "Mmc.h"\r
+\r
+#define DIAGNOSTIC_LOGBUFFER_MAXCHAR 1024\r
+\r
+CHAR16* mLogBuffer = NULL;\r
+UINTN mLogRemainChar = 0;\r
+\r
+CHAR16* DiagnosticInitLog(UINTN MaxBufferChar) {\r
+ mLogRemainChar = MaxBufferChar;\r
+ mLogBuffer = AllocatePool ((UINTN)MaxBufferChar * sizeof(CHAR16));\r
+ return mLogBuffer;\r
+}\r
+\r
+UINTN DiagnosticLog(CONST CHAR16* Str) {\r
+ UINTN len = StrLen (Str);\r
+ if (len <= mLogRemainChar) {\r
+ mLogRemainChar -= len;\r
+ StrCpy (mLogBuffer, Str);\r
+ mLogBuffer += len;\r
+ return len;\r
+ } else {\r
+ return 0;\r
+ }\r
+}\r
+\r
+VOID GenerateRandomBuffer(VOID* Buffer, UINTN BufferSize) {\r
+ UINT64 i;\r
+ UINT64* Buffer64 = (UINT64*)Buffer;\r
+\r
+ for (i = 0; i < (BufferSize >> 3); i++) {\r
+ *Buffer64 = i | (~i << 32);\r
+ Buffer64++;\r
+ }\r
+}\r
+\r
+BOOLEAN CompareBuffer(VOID *BufferA, VOID *BufferB, UINTN BufferSize) {\r
+ UINTN i;\r
+ UINT64* BufferA64 = (UINT64*)BufferA;\r
+ UINT64* BufferB64 = (UINT64*)BufferB;\r
+\r
+ for (i = 0; i < (BufferSize >> 3); i++) {\r
+ if (*BufferA64 != *BufferB64) {\r
+ DEBUG((EFI_D_ERROR, "CompareBuffer: Error at %i", i));\r
+ DEBUG((EFI_D_ERROR, "(0x%lX) != (0x%lX)\n", *BufferA64, *BufferB64));\r
+ return FALSE;\r
+ }\r
+ BufferA64++;\r
+ BufferB64++;\r
+ }\r
+ return TRUE;\r
+}\r
+\r
+EFI_STATUS MmcReadWriteDataTest(MMC_HOST_INSTANCE *MmcHostInstance, EFI_LBA Lba, UINTN BufferSize) {\r
+ VOID *BackBuffer;\r
+ VOID *WriteBuffer;\r
+ VOID *ReadBuffer;\r
+ EFI_STATUS Status;\r
+ \r
+ // Check if a Media is Present\r
+ if (!MmcHostInstance->BlockIo.Media->MediaPresent) {\r
+ DiagnosticLog(L"ERROR: No Media Present\n");\r
+ return EFI_NO_MEDIA;\r
+ }\r
+\r
+ if (MmcHostInstance->State != MmcTransferState) {\r
+ DiagnosticLog(L"ERROR: Not ready for Transfer state\n");\r
+ return EFI_NOT_READY;\r
+ }\r
+\r
+ BackBuffer = AllocatePool(BufferSize);\r
+ WriteBuffer = AllocatePool(BufferSize);\r
+ ReadBuffer = AllocatePool(BufferSize);\r
+\r
+ // Read (and save) buffer at a specific location\r
+ Status = MmcReadBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,BackBuffer);\r
+ if (Status != EFI_SUCCESS) {\r
+ DiagnosticLog(L"ERROR: Fail to Read Block (1)\n");\r
+ return Status;\r
+ }\r
+\r
+ // Write buffer at the same location\r
+ GenerateRandomBuffer(WriteBuffer,BufferSize);\r
+ Status = MmcWriteBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,WriteBuffer);\r
+ if (Status != EFI_SUCCESS) {\r
+ DiagnosticLog(L"ERROR: Fail to Write Block (1)\n");\r
+ return Status;\r
+ }\r
+\r
+ // Read the buffer at the same location\r
+ Status = MmcReadBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,ReadBuffer);\r
+ if (Status != EFI_SUCCESS) {\r
+ DiagnosticLog(L"ERROR: Fail to Read Block (2)\n");\r
+ return Status;\r
+ }\r
+\r
+ // Check that is conform\r
+ if (!CompareBuffer(ReadBuffer,WriteBuffer,BufferSize)) {\r
+ DiagnosticLog(L"ERROR: Fail to Read/Write Block (1)\n");\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ // Restore content at the original location\r
+ Status = MmcWriteBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,BackBuffer);\r
+ if (Status != EFI_SUCCESS) {\r
+ DiagnosticLog(L"ERROR: Fail to Write Block (2)\n");\r
+ return Status;\r
+ }\r
+\r
+ // Read the restored content\r
+ Status = MmcReadBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,ReadBuffer);\r
+ if (Status != EFI_SUCCESS) {\r
+ DiagnosticLog(L"ERROR: Fail to Read Block (3)\n");\r
+ return Status;\r
+ }\r
+\r
+ // Check the content is correct\r
+ if (!CompareBuffer(ReadBuffer,BackBuffer,BufferSize)) {\r
+ DiagnosticLog(L"ERROR: Fail to Read/Write Block (2)\n");\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+MmcDriverDiagnosticsRunDiagnostics (\r
+ IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle OPTIONAL,\r
+ IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType,\r
+ IN CHAR8 *Language,\r
+ OUT EFI_GUID **ErrorType,\r
+ OUT UINTN *BufferSize,\r
+ OUT CHAR16 **Buffer\r
+ )\r
+{\r
+ LIST_ENTRY *CurrentLink;\r
+ MMC_HOST_INSTANCE *MmcHostInstance;\r
+ EFI_STATUS Status;\r
+\r
+ if (Language == NULL ||\r
+ ErrorType == NULL ||\r
+ Buffer == NULL ||\r
+ ControllerHandle == NULL ||\r
+ BufferSize == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ *ErrorType = NULL;\r
+ *BufferSize = DIAGNOSTIC_LOGBUFFER_MAXCHAR;\r
+ *Buffer = DiagnosticInitLog(DIAGNOSTIC_LOGBUFFER_MAXCHAR);\r
+\r
+ DiagnosticLog(L"MMC Driver Diagnostics\n");\r
+\r
+ // For each MMC instance\r
+ CurrentLink = mMmcHostPool.ForwardLink;\r
+ while (CurrentLink != NULL && CurrentLink != &mMmcHostPool && (Status == EFI_SUCCESS)) {\r
+ MmcHostInstance = MMC_HOST_INSTANCE_FROM_LINK(CurrentLink);\r
+ ASSERT(MmcHostInstance != NULL);\r
+\r
+ // LBA=1 Size=BlockSize\r
+ DiagnosticLog(L"MMC Driver Diagnostics - Test: First Block\n");\r
+ Status = MmcReadWriteDataTest(MmcHostInstance, 1, MmcHostInstance->BlockIo.Media->BlockSize);\r
+\r
+ // LBA=2 Size=BlockSize\r
+ DiagnosticLog(L"MMC Driver Diagnostics - Test: Second Block\n");\r
+ Status = MmcReadWriteDataTest(MmcHostInstance, 2, MmcHostInstance->BlockIo.Media->BlockSize);\r
+\r
+ // LBA=10 Size=BlockSize\r
+ DiagnosticLog(L"MMC Driver Diagnostics - Test: Any Block\n");\r
+ Status = MmcReadWriteDataTest(MmcHostInstance, MmcHostInstance->BlockIo.Media->LastBlock >> 1, MmcHostInstance->BlockIo.Media->BlockSize);\r
+\r
+ // LBA=LastBlock Size=BlockSize\r
+ DiagnosticLog(L"MMC Driver Diagnostics - Test: Last Block\n");\r
+ Status = MmcReadWriteDataTest(MmcHostInstance, MmcHostInstance->BlockIo.Media->LastBlock, MmcHostInstance->BlockIo.Media->BlockSize);\r
+\r
+ // LBA=1 Size=2*BlockSize\r
+ DiagnosticLog(L"MMC Driver Diagnostics - Test: First Block / 2 BlockSSize\n");\r
+ Status = MmcReadWriteDataTest(MmcHostInstance, 1, 2*MmcHostInstance->BlockIo.Media->BlockSize);\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+//\r
+// EFI Driver Diagnostics 2 Protocol\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_DRIVER_DIAGNOSTICS2_PROTOCOL gMmcDriverDiagnostics2 = {\r
+ (EFI_DRIVER_DIAGNOSTICS2_RUN_DIAGNOSTICS) MmcDriverDiagnosticsRunDiagnostics,\r
+ "en"\r
+};\r
--- /dev/null
+/** @file\r
+ Main file of the MMC Dxe driver. The driver entrypoint is defined into this file.\r
+\r
+ Copyright (c) 2011, ARM Limited. All rights reserved.\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 <Protocol/DevicePath.h>\r
+#include <Protocol/MmcHost.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/DebugLib.h>\r
+\r
+#include "Mmc.h"\r
+\r
+EFI_BLOCK_IO_MEDIA mMmcMediaTemplate = {\r
+ SIGNATURE_32('m','m','c','o'), // MediaId\r
+ TRUE, // RemovableMedia\r
+ FALSE, // MediaPresent\r
+ FALSE, // LogicalPartition\r
+ FALSE, // ReadOnly\r
+ FALSE, // WriteCaching\r
+ 512, // BlockSize\r
+ 4, // IoAlign\r
+ 0, // Pad\r
+ 0 // LastBlock\r
+};\r
+\r
+//\r
+// This device structure is serviced as a header.\r
+// Its next field points to the first root bridge device node.\r
+//\r
+LIST_ENTRY mMmcHostPool;\r
+\r
+/**\r
+ Initialize the MMC Host Pool to support multiple MMC devices\r
+**/\r
+VOID\r
+InitializeMmcHostPool (\r
+ VOID\r
+ )\r
+{\r
+ InitializeListHead (&mMmcHostPool);\r
+}\r
+\r
+/**\r
+ Insert a new Mmc Host controller to the pool\r
+**/\r
+VOID\r
+InsertMmcHost (\r
+ IN MMC_HOST_INSTANCE *MmcHostInstance\r
+ )\r
+{\r
+ InsertTailList (&mMmcHostPool, &(MmcHostInstance->Link));\r
+}\r
+\r
+/*\r
+ Remove a new Mmc Host controller to the pool\r
+*/\r
+VOID\r
+RemoveMmcHost (\r
+ IN MMC_HOST_INSTANCE *MmcHostInstance\r
+ )\r
+{\r
+ RemoveEntryList (&(MmcHostInstance->Link));\r
+}\r
+\r
+MMC_HOST_INSTANCE* CreateMmcHostInstance(\r
+ IN EFI_MMC_HOST_PROTOCOL* MmcHost\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ MMC_HOST_INSTANCE* MmcHostInstance;\r
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+\r
+ MmcHostInstance = AllocateZeroPool (sizeof (MMC_HOST_INSTANCE));\r
+ if (MmcHostInstance == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ MmcHostInstance->Signature = MMC_HOST_INSTANCE_SIGNATURE;\r
+\r
+ MmcHostInstance->State = MmcHwInitializationState;\r
+ \r
+ MmcHostInstance->BlockIo.Media = AllocateCopyPool (sizeof(EFI_BLOCK_IO_MEDIA), &mMmcMediaTemplate);\r
+ if (MmcHostInstance->BlockIo.Media == NULL) {\r
+ goto FREE_INSTANCE;\r
+ }\r
+\r
+ MmcHostInstance->BlockIo.Revision = EFI_BLOCK_IO_INTERFACE_REVISION;\r
+ MmcHostInstance->BlockIo.Reset = MmcReset;\r
+ MmcHostInstance->BlockIo.ReadBlocks = MmcReadBlocks;\r
+ MmcHostInstance->BlockIo.WriteBlocks = MmcWriteBlocks;\r
+ MmcHostInstance->BlockIo.FlushBlocks = MmcFlushBlocks;\r
+\r
+ MmcHostInstance->MmcHost = MmcHost;\r
+\r
+ // Create DevicePath for the new MMC Host\r
+ Status = MmcHost->BuildDevicePath(&NewDevicePathNode);\r
+ if (EFI_ERROR (Status)) {\r
+ goto FREE_MEDIA;\r
+ }\r
+\r
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH);\r
+ if (DevicePath == NULL) {\r
+ goto FREE_MEDIA;\r
+ }\r
+ \r
+ SetDevicePathEndNode (DevicePath);\r
+ MmcHostInstance->DevicePath = AppendDevicePathNode (DevicePath, NewDevicePathNode);\r
+\r
+ // Publish BlockIO protocol interface\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &MmcHostInstance->MmcHandle,\r
+ &gEfiBlockIoProtocolGuid,&(MmcHostInstance->BlockIo),\r
+ &gEfiDevicePathProtocolGuid,MmcHostInstance->DevicePath,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ goto FREE_DEVICE_PATH;\r
+ }\r
+\r
+ return MmcHostInstance;\r
+\r
+FREE_DEVICE_PATH:\r
+ FreePool(DevicePath);\r
+\r
+FREE_MEDIA:\r
+ FreePool(MmcHostInstance->BlockIo.Media);\r
+\r
+FREE_INSTANCE:\r
+ FreePool(MmcHostInstance);\r
+\r
+ return NULL;\r
+}\r
+\r
+EFI_STATUS DestroyMmcHostInstance(\r
+ IN MMC_HOST_INSTANCE* MmcHostInstance\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ // Uninstall Protocol Interfaces\r
+ Status = gBS->UninstallMultipleProtocolInterfaces(\r
+ MmcHostInstance->MmcHandle,\r
+ &gEfiBlockIoProtocolGuid,&(MmcHostInstance->BlockIo),\r
+ &gEfiDevicePathProtocolGuid,MmcHostInstance->DevicePath,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ \r
+ // Free Memory allocated for the instance\r
+ if (MmcHostInstance->BlockIo.Media) {\r
+ FreePool(MmcHostInstance->BlockIo.Media);\r
+ }\r
+ FreePool (MmcHostInstance);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This function checks if the controller implement the Mmc Host and the Device Path Protocols\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MmcDriverBindingSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ //EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
+ EFI_MMC_HOST_PROTOCOL *MmcHost;\r
+ EFI_DEV_PATH_PTR Node;\r
+\r
+ //\r
+ // Check RemainingDevicePath validation\r
+ //\r
+ if (RemainingDevicePath != NULL) {\r
+ //\r
+ // Check if RemainingDevicePath is the End of Device Path Node, \r
+ // if yes, go on checking other conditions\r
+ //\r
+ if (!IsDevicePathEnd (RemainingDevicePath)) {\r
+ //\r
+ // If RemainingDevicePath isn't the End of Device Path Node,\r
+ // check its validation\r
+ //\r
+ Node.DevPath = RemainingDevicePath;\r
+ if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||\r
+ Node.DevPath->SubType != HW_VENDOR_DP ||\r
+ DevicePathNodeLength(Node.DevPath) != sizeof(VENDOR_DEVICE_PATH)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Check if Mmc Host protocol is installed by platform\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiMmcHostProtocolGuid,\r
+ (VOID **) &MmcHost,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (Status == EFI_ALREADY_STARTED) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Close the Mmc Host used to perform the supported test\r
+ //\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiMmcHostProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MmcDriverBindingStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ MMC_HOST_INSTANCE *MmcHostInstance;\r
+ EFI_MMC_HOST_PROTOCOL *MmcHost;\r
+\r
+ //\r
+ // Check RemainingDevicePath validation\r
+ //\r
+ if (RemainingDevicePath != NULL) {\r
+ //\r
+ // Check if RemainingDevicePath is the End of Device Path Node, \r
+ // if yes, return EFI_SUCCESS\r
+ //\r
+ if (IsDevicePathEnd (RemainingDevicePath)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Get the Mmc Host protocol\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiMmcHostProtocolGuid,\r
+ (VOID **) &MmcHost,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ if (Status == EFI_ALREADY_STARTED) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ return Status;\r
+ }\r
+\r
+ MmcHostInstance = CreateMmcHostInstance(MmcHost);\r
+ if (MmcHostInstance != NULL) {\r
+ // Add the handle to the pool\r
+ InsertMmcHost (MmcHostInstance);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MmcDriverBindingStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer\r
+ )\r
+{\r
+ EFI_STATUS Status = EFI_SUCCESS;\r
+ LIST_ENTRY *CurrentLink;\r
+ MMC_HOST_INSTANCE *MmcHostInstance;\r
+\r
+ MMC_TRACE("MmcDriverBindingStop()");\r
+\r
+ // For each MMC instance\r
+ CurrentLink = mMmcHostPool.ForwardLink;\r
+ while (CurrentLink != NULL && CurrentLink != &mMmcHostPool && (Status == EFI_SUCCESS)) {\r
+ MmcHostInstance = MMC_HOST_INSTANCE_FROM_LINK(CurrentLink);\r
+ ASSERT(MmcHostInstance != NULL);\r
+\r
+ // Close gEfiMmcHostProtocolGuid\r
+ Status = gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiMmcHostProtocolGuid,(VOID **) &MmcHostInstance->MmcHost,\r
+ This->DriverBindingHandle\r
+ );\r
+\r
+ // Remove MMC Host Instance from the pool\r
+ RemoveMmcHost (MmcHostInstance);\r
+\r
+ // Destroy MmcHostInstance\r
+ DestroyMmcHostInstance (MmcHostInstance);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_DRIVER_BINDING_PROTOCOL gMmcDriverBinding = {\r
+ MmcDriverBindingSupported,\r
+ MmcDriverBindingStart,\r
+ MmcDriverBindingStop,\r
+ 0xa,\r
+ NULL,\r
+ NULL\r
+};\r
+\r
+/**\r
+ \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MmcDxeInitialize (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Initializes MMC Host pool\r
+ //\r
+ InitializeMmcHostPool ();\r
+\r
+ //\r
+ // Install driver model protocol(s).\r
+ //\r
+ Status = EfiLibInstallDriverBindingComponentName2 (\r
+ ImageHandle,\r
+ SystemTable,\r
+ &gMmcDriverBinding,\r
+ ImageHandle,\r
+ &gMmcComponentName,\r
+ &gMmcComponentName2\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ // Install driver diagnostics\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &ImageHandle, \r
+ &gEfiDriverDiagnostics2ProtocolGuid,&gMmcDriverDiagnostics2,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+/** @file\r
+ Main Header file for the MMC DXE driver\r
+\r
+ Copyright (c) 2011, ARM Limited. All rights reserved.\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
+#ifndef __MMC_H\r
+#define __MMC_H\r
+\r
+#include <Uefi.h>\r
+\r
+#include <Protocol/DiskIo.h>\r
+#include <Protocol/BlockIo.h>\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/MmcHost.h>\r
+\r
+#include <Library/UefiLib.h>\r
+\r
+#define MMC_TRACE(txt) DEBUG((EFI_D_BLKIO, "MMC: " txt "\n"))\r
+\r
+#define MMC_IOBLOCKS_READ 0\r
+#define MMC_IOBLOCKS_WRITE 1\r
+\r
+#define MMC_OCR_POWERUP 0x80000000\r
+\r
+#define MMC_CSD_GET_CCC(Response) (Response[1] >> 20)\r
+#define MMC_CSD_GET_TRANSPEED(Response) (Response[0] & 0xFF)\r
+#define MMC_CSD_GET_READBLLEN(Response) ((Response[1] >> 16) & 0xF)\r
+#define MMC_CSD_GET_WRITEBLLEN(Response) ((Response[3] >> 22) & 0xF)\r
+#define MMC_CSD_GET_FILEFORMAT(Response) ((Response[3] >> 10) & 0x3)\r
+#define MMC_CSD_GET_FILEFORMATGRP(Response) ((Response[3] >> 15) & 0x1)\r
+#define MMC_CSD_GET_DEVICESIZE(csd) (((Response[2] >> 30) & 0x3) | ((Response[1] & 0x3FF) << 2))\r
+#define MMC_CSD_GET_DEVICESIZEMULT(csd) ((Response[2] >> 15) & 0x7)\r
+\r
+#define MMC_R0_CURRENTSTATE(Response) ((Response[0] >> 9) & 0xF)\r
+\r
+#define MMC_R0_STATE_IDLE 0\r
+#define MMC_R0_STATE_READY 1\r
+#define MMC_R0_STATE_IDENT 2\r
+#define MMC_R0_STATE_STDBY 3\r
+#define MMC_R0_STATE_TRAN 4\r
+#define MMC_R0_STATE_DATA 5\r
+\r
+typedef enum {\r
+ UNKNOWN_CARD,\r
+ MMC_CARD, //MMC card\r
+ MMC_CARD_HIGH, //MMC Card with High capacity\r
+ SD_CARD, //SD 1.1 card\r
+ SD_CARD_2, //SD 2.0 or above standard card\r
+ SD_CARD_2_HIGH //SD 2.0 or above high capacity card\r
+} CARD_TYPE;\r
+\r
+typedef struct {\r
+ UINT32 Reserved0: 7; // 0 \r
+ UINT32 V170_V195: 1; // 1.70V - 1.95V\r
+ UINT32 V200_V260: 7; // 2.00V - 2.60V\r
+ UINT32 V270_V360: 9; // 2.70V - 3.60V\r
+ UINT32 RESERVED_1: 5; // Reserved\r
+ UINT32 AccessMode: 2; // 00b (byte mode), 10b (sector mode) \r
+ UINT32 Busy: 1; // This bit is set to LOW if the card has not finished the power up routine\r
+} OCR;\r
+\r
+typedef struct {\r
+ UINT32 NOT_USED; // 1 [0:0]\r
+ UINT32 CRC; // CRC7 checksum [7:1]\r
+ UINT32 MDT; // Manufacturing date [19:8]\r
+ UINT32 RESERVED_1; // Reserved [23:20]\r
+ UINT32 PSN; // Product serial number [55:24]\r
+ UINT8 PRV; // Product revision [63:56]\r
+ UINT8 PNM[5]; // Product name [64:103]\r
+ UINT16 OID; // OEM/Application ID [119:104]\r
+ UINT8 MID; // Manufacturer ID [127:120]\r
+} CID;\r
+\r
+typedef struct {\r
+ UINT8 NOT_USED: 1; // Not used, always 1 [0:0]\r
+ UINT8 CRC: 7; // CRC [7:1]\r
+\r
+ UINT8 RESERVED_1: 2; // Reserved [9:8]\r
+ UINT8 FILE_FORMAT: 2; // File format [11:10]\r
+ UINT8 TMP_WRITE_PROTECT: 1; // Temporary write protection [12:12]\r
+ UINT8 PERM_WRITE_PROTECT: 1; // Permanent write protection [13:13]\r
+ UINT8 COPY: 1; // Copy flag (OTP) [14:14]\r
+ UINT8 FILE_FORMAT_GRP: 1; // File format group [15:15]\r
+ \r
+ UINT16 RESERVED_2: 5; // Reserved [20:16]\r
+ UINT16 WRITE_BL_PARTIAL: 1; // Partial blocks for write allowed [21:21]\r
+ UINT16 WRITE_BL_LEN: 4; // Max. write data block length [25:22]\r
+ UINT16 R2W_FACTOR: 3; // Write speed factor [28:26]\r
+ UINT16 RESERVED_3: 2; // Reserved [30:29]\r
+ UINT16 WP_GRP_ENABLE: 1; // Write protect group enable [31:31]\r
+ \r
+ UINT32 WP_GRP_SIZE: 7; // Write protect group size [38:32]\r
+ UINT32 SECTOR_SIZE: 7; // Erase sector size [45:39]\r
+ UINT32 ERASE_BLK_EN: 1; // Erase single block enable [46:46]\r
+ UINT32 C_SIZE_MULT: 3; // Device size multiplier [49:47]\r
+ UINT32 VDD_W_CURR_MAX: 3; // Max. write current @ VDD max [52:50]\r
+ UINT32 VDD_W_CURR_MIN: 3; // Max. write current @ VDD min [55:53]\r
+ UINT32 VDD_R_CURR_MAX: 3; // Max. read current @ VDD max [58:56]\r
+ UINT32 VDD_R_CURR_MIN: 3; // Max. read current @ VDD min [61:59]\r
+ UINT32 C_SIZELow2: 2; // Device size [63:62]\r
+ \r
+ UINT32 C_SIZEHigh10: 10;// Device size [73:64]\r
+ UINT32 RESERVED_4: 2; // Reserved [75:74]\r
+ UINT32 DSR_IMP: 1; // DSR implemented [76:76]\r
+ UINT32 READ_BLK_MISALIGN: 1; // Read block misalignment [77:77]\r
+ UINT32 WRITE_BLK_MISALIGN: 1; // Write block misalignment [78:78]\r
+ UINT32 READ_BL_PARTIAL: 1; // Partial blocks for read allowed [79:79]\r
+ UINT32 READ_BL_LEN: 4; // Max. read data block length [83:80]\r
+ UINT32 CCC: 12;// Card command classes [95:84]\r
+\r
+ UINT8 TRAN_SPEED ; // Max. bus clock frequency [103:96]\r
+ UINT8 NSAC ; // Data read access-time 2 in CLK cycles (NSAC*100) [111:104]\r
+ UINT8 TAAC ; // Data read access-time 1 [119:112]\r
+ \r
+ UINT8 RESERVED_5: 6; // Reserved [125:120]\r
+ UINT8 CSD_STRUCTURE: 2; // CSD structure [127:126]\r
+} CSD;\r
+\r
+typedef struct {\r
+ UINT16 RCA;\r
+ CARD_TYPE CardType;\r
+ OCR OCRData;\r
+ CID CIDData;\r
+ CSD CSDData;\r
+} CARD_INFO;\r
+\r
+typedef struct _MMC_HOST_INSTANCE {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+ EFI_HANDLE MmcHandle;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+\r
+ MMC_STATE State;\r
+ EFI_BLOCK_IO_PROTOCOL BlockIo;\r
+ CARD_INFO CardInfo;\r
+ EFI_MMC_HOST_PROTOCOL *MmcHost;\r
+} MMC_HOST_INSTANCE;\r
+\r
+#define MMC_HOST_INSTANCE_SIGNATURE SIGNATURE_32('m', 'm', 'c', 'h')\r
+#define MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS(a) CR (a, MMC_HOST_INSTANCE, BlockIo, MMC_HOST_INSTANCE_SIGNATURE)\r
+#define MMC_HOST_INSTANCE_FROM_LINK(a) CR (a, MMC_HOST_INSTANCE, Link, MMC_HOST_INSTANCE_SIGNATURE)\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+MmcGetDriverName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **DriverName\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+MmcGetControllerName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle OPTIONAL,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **ControllerName\r
+ );\r
+\r
+extern EFI_COMPONENT_NAME_PROTOCOL gMmcComponentName;\r
+extern EFI_COMPONENT_NAME2_PROTOCOL gMmcComponentName2;\r
+\r
+extern EFI_DRIVER_DIAGNOSTICS2_PROTOCOL gMmcDriverDiagnostics2;\r
+\r
+extern LIST_ENTRY mMmcHostPool;\r
+\r
+/**\r
+ Reset the block device.\r
+\r
+ This function implements EFI_BLOCK_IO_PROTOCOL.Reset(). \r
+ It resets the block device hardware.\r
+ ExtendedVerification is ignored in this implementation.\r
+\r
+ @param This Indicates a pointer to the calling context.\r
+ @param ExtendedVerification Indicates that the driver may perform a more exhaustive\r
+ verification operation of the device during reset.\r
+\r
+ @retval EFI_SUCCESS The block device was reset.\r
+ @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be reset.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MmcReset (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN BOOLEAN ExtendedVerification\r
+ );\r
+\r
+/**\r
+ Reads the requested number of blocks from the device.\r
+\r
+ This function implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks(). \r
+ It reads the requested number of blocks from the device.\r
+ All the blocks are read, or an error is returned.\r
+\r
+ @param This Indicates a pointer to the calling context.\r
+ @param MediaId The media ID that the read request is for.\r
+ @param Lba The starting logical block address to read from on the device.\r
+ @param BufferSize The size of the Buffer in bytes.\r
+ This must be a multiple of the intrinsic block size of the device.\r
+ @param Buffer A pointer to the destination buffer for the data. The caller is\r
+ responsible for either having implicit or explicit ownership of the buffer.\r
+\r
+ @retval EFI_SUCCESS The data was read correctly from the device.\r
+ @retval EFI_DEVICE_ERROR The device reported an error while attempting to perform the read operation.\r
+ @retval EFI_NO_MEDIA There is no media in the device.\r
+ @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
+ @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the intrinsic block size of the device.\r
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,\r
+ or the buffer is not on proper alignment.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MmcReadBlocks (\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
+/**\r
+ Writes a specified number of blocks to the device.\r
+\r
+ This function implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks(). \r
+ It writes a specified number of blocks to the device.\r
+ All blocks are written, or an error is returned.\r
+\r
+ @param This Indicates a pointer to the calling context.\r
+ @param MediaId The media ID that the write request is for.\r
+ @param Lba The starting logical block address to be written.\r
+ @param BufferSize The size of the Buffer in bytes.\r
+ This must be a multiple of the intrinsic block size of the device.\r
+ @param Buffer Pointer to the source buffer for the data.\r
+\r
+ @retval EFI_SUCCESS The data were written correctly to the device.\r
+ @retval EFI_WRITE_PROTECTED The device cannot be written to.\r
+ @retval EFI_NO_MEDIA There is no media in the device.\r
+ @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
+ @retval EFI_DEVICE_ERROR The device reported an error while attempting to perform the write operation.\r
+ @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the intrinsic\r
+ block size of the device.\r
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,\r
+ or the buffer is not on proper alignment.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MmcWriteBlocks (\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
+/**\r
+ Flushes all modified data to a physical block device.\r
+\r
+ @param This Indicates a pointer to the calling context.\r
+\r
+ @retval EFI_SUCCESS All outstanding data were written correctly to the device.\r
+ @retval EFI_DEVICE_ERROR The device reported an error while attempting to write data.\r
+ @retval EFI_NO_MEDIA There is no media in the device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MmcFlushBlocks (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+*\r
+* Copyright (c) 2011, ARM Limited. All rights reserved.\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 <Protocol/MmcHost.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/TimerLib.h>\r
+\r
+#include "Mmc.h"\r
+\r
+// Untested ...\r
+//#define USE_STREAM\r
+\r
+#define MAX_RETRY_COUNT 1000\r
+#define CMD_RETRY_COUNT 20\r
+\r
+EFI_STATUS\r
+MmcNotifyState (\r
+ MMC_HOST_INSTANCE *MmcHostInstance,\r
+ MMC_STATE State\r
+ ) {\r
+ MmcHostInstance->State = State;\r
+ return MmcHostInstance->MmcHost->NotifyState(State);\r
+}\r
+\r
+VOID PrintOCR(UINT32 ocr) {\r
+ UINTN minv, maxv, volts;\r
+ UINTN loop;\r
+\r
+ minv = 36; // 3.6\r
+ maxv = 20; // 2.0\r
+ volts = 20; // 2.0\r
+\r
+ // The MMC register bits [23:8] indicate the working range of the card\r
+ for (loop = 8; loop < 24; loop++) {\r
+ if (ocr & (1 << loop)) {\r
+ if (minv > volts) minv = volts;\r
+ if (maxv < volts) maxv = volts + 1;\r
+ }\r
+ volts = volts + 1;\r
+ }\r
+\r
+ DEBUG((EFI_D_ERROR, "- PrintOCR ocr (0x%X)\n",ocr));\r
+ DEBUG((EFI_D_ERROR, "\t- Card operating voltage: %d.%d to %d.%d\n", minv/10, minv % 10, maxv/10, maxv % 10));\r
+ if (((ocr >> 29) & 3) == 0)\r
+ DEBUG((EFI_D_ERROR, "\t- AccessMode: Byte Mode\n"));\r
+ else\r
+ DEBUG((EFI_D_ERROR, "\t- AccessMode: Block Mode (0x%X)\n",((ocr >> 29) & 3)));\r
+\r
+ if (ocr & MMC_OCR_POWERUP)\r
+ DEBUG((EFI_D_ERROR, "\t- PowerUp\n"));\r
+ else\r
+ DEBUG((EFI_D_ERROR, "\t- Voltage Not Supported\n"));\r
+}\r
+\r
+VOID PrintCID(UINT32* cid) {\r
+ DEBUG((EFI_D_ERROR, "- PrintCID\n"));\r
+ DEBUG((EFI_D_ERROR, "\t- Manufacturing date: %d/%d\n",(cid[0] >> 8) & 0xF,(cid[0] >> 12) & 0xFF));\r
+ DEBUG((EFI_D_ERROR, "\t- Product serial number: 0x%X%X\n",cid[1] & 0xFFFFFF,(cid[0] >> 24) & 0xFF));\r
+ DEBUG((EFI_D_ERROR, "\t- Product revision: %d\n",cid[1] >> 24));\r
+ //DEBUG((EFI_D_ERROR, "\t- Product name: %s\n",(char*)(cid + 2)));\r
+ DEBUG((EFI_D_ERROR, "\t- OEM ID: %c%c\n",(cid[3] >> 8) & 0xFF,(cid[3] >> 16) & 0xFF));\r
+}\r
+\r
+VOID PrintCSD(UINT32* csd) {\r
+ UINTN val32;\r
+ CONST CHAR8* str_unit[] = { "100kbit/s","1Mbit/s","10Mbit/s","100MBit/s","Unkbown","Unkbown","Unkbown","Unkbown" };\r
+ CONST CHAR8* str_value[] = { "1.0","1.2","1.3","1.5","2.0","2.5","3.0","3.5","4.0","4.5","5.0","Unknown","Unknown","Unknown","Unknown" };\r
+\r
+ if (((csd[2] >> 30) & 0x3) == 0)\r
+ DEBUG((EFI_D_ERROR, "- PrintCSD Version 1.01-1.10/Version 2.00/Standard Capacity\n"));\r
+ else if (((csd[2] >> 30) & 0x3) == 1)\r
+ DEBUG((EFI_D_ERROR, "- PrintCSD Version 2.00/High Capacity\n"));\r
+ else\r
+ DEBUG((EFI_D_ERROR, "- PrintCSD Version Higher than v3.3\n"));\r
+\r
+ DEBUG((EFI_D_ERROR, "\t- Supported card command class: 0x%X\n",MMC_CSD_GET_CCC(csd)));\r
+ DEBUG((EFI_D_ERROR, "\t- Speed: %a %a\n",str_value[(MMC_CSD_GET_TRANSPEED(csd) >> 3) & 0xF],str_unit[MMC_CSD_GET_TRANSPEED(csd) & 7]));\r
+ DEBUG((EFI_D_ERROR, "\t- Maximum Read Data Block: %d\n",2 << (MMC_CSD_GET_READBLLEN(csd)-1)));\r
+ DEBUG((EFI_D_ERROR, "\t- Maximum Write Data Block: %d\n",2 << (MMC_CSD_GET_WRITEBLLEN(csd)-1)));\r
+ \r
+ if (!MMC_CSD_GET_FILEFORMATGRP(csd)) {\r
+ val32 = MMC_CSD_GET_FILEFORMAT(csd);\r
+ if (val32 == 0) DEBUG((EFI_D_ERROR, "\t- Format(0): Hard disk-like file system with partition table\n"));\r
+ else if (val32 == 1) DEBUG((EFI_D_ERROR, "\t- Format(1): DOS FAT (floppy-like) with boot sector only (no partition table)\n"));\r
+ else if (val32 == 2) DEBUG((EFI_D_ERROR, "\t- Format(2): Universal File Format\n"));\r
+ else DEBUG((EFI_D_ERROR, "\t- Format(3): Others/Unknown\n"));\r
+ } else {\r
+ DEBUG((EFI_D_ERROR, "\t- Format: Reserved\n"));\r
+ }\r
+}\r
+\r
+VOID PrintRCA(UINT32 rca) {\r
+ DEBUG((EFI_D_ERROR, "- PrintRCA: 0x%X\n",rca));\r
+ DEBUG((EFI_D_ERROR, "\t- Status: 0x%X\n",rca & 0xFFFF));\r
+ DEBUG((EFI_D_ERROR, "\t- RCA: 0x%X\n",(rca >> 16) & 0xFFFF));\r
+}\r
+\r
+VOID PrintResponseR1(UINT32 response) {\r
+ DEBUG((EFI_D_INFO, "Response: 0x%X\n",response));\r
+ if (response & (1 << 8)) DEBUG((EFI_D_INFO, "\t- READY_FOR_DATA\n"));\r
+\r
+ if (((response >> 9) & 0xF) == 0) DEBUG((EFI_D_INFO, "\t- State: Idle\n"));\r
+ else if (((response >> 9) & 0xF) == 1) DEBUG((EFI_D_INFO, "\t- State: Ready\n"));\r
+ else if (((response >> 9) & 0xF) == 2) DEBUG((EFI_D_INFO, "\t- State: Ident\n"));\r
+ else if (((response >> 9) & 0xF) == 3) DEBUG((EFI_D_INFO, "\t- State: StandBy\n"));\r
+ else if (((response >> 9) & 0xF) == 4) DEBUG((EFI_D_INFO, "\t- State: Tran\n"));\r
+ else if (((response >> 9) & 0xF) == 5) DEBUG((EFI_D_INFO, "\t- State: Data\n"));\r
+ else if (((response >> 9) & 0xF) == 6) DEBUG((EFI_D_INFO, "\t- State: Rcv\n"));\r
+ else if (((response >> 9) & 0xF) == 7) DEBUG((EFI_D_INFO, "\t- State: Prg\n"));\r
+ else if (((response >> 9) & 0xF) == 8) DEBUG((EFI_D_INFO, "\t- State: Dis\n"));\r
+ else DEBUG((EFI_D_INFO, "\t- State: Reserved\n"));\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+MmcGetCardStatus(\r
+ MMC_HOST_INSTANCE *MmcHostInstance\r
+ ){\r
+ EFI_STATUS Status=EFI_SUCCESS;\r
+ UINT32 Response[4];\r
+ UINTN CmdArg;\r
+ EFI_MMC_HOST_PROTOCOL *MmcHost;\r
+\r
+ MmcHost = MmcHostInstance->MmcHost;\r
+ CmdArg = 0;\r
+\r
+ if (MmcHost == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if(MmcHostInstance->State != MmcHwInitializationState){\r
+ //Get the Status of the card.\r
+ CmdArg = MmcHostInstance->CardInfo.RCA << 16;\r
+ Status = MmcHost->SendCommand(MMC_CMD13, CmdArg);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_ERROR, "MmcGetCardStatus(MMC_CMD13): Error and Status = %r\n", Status));\r
+ ASSERT(0);\r
+ return Status;\r
+ }\r
+\r
+ //Read Response\r
+ MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_R1,Response);\r
+ PrintResponseR1(Response[0]);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+MmcIdentificationMode (\r
+ MMC_HOST_INSTANCE *MmcHostInstance\r
+ ) {\r
+ EFI_STATUS Status;\r
+ UINT32 Response[4];\r
+ UINTN Timeout;\r
+ UINTN CmdArg;\r
+ BOOLEAN bHCS;\r
+ EFI_MMC_HOST_PROTOCOL *MmcHost;\r
+ UINTN CmdRetryCnt;\r
+ \r
+ MmcHost = MmcHostInstance->MmcHost;\r
+ CmdArg = 0;\r
+ bHCS = FALSE;\r
+\r
+ if (MmcHost == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ // We can get into this function if we restart the identification mode\r
+ if (MmcHostInstance->State == MmcHwInitializationState) {\r
+ // Initialize the MMC Host HW\r
+ Status = MmcNotifyState (MmcHostInstance, MmcHwInitializationState);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcHwInitializationState\n"));\r
+ return Status;\r
+ }\r
+ } else {\r
+ //Note: Could even be used in all cases. But it looks this command could put the state machine into inactive for some cards\r
+ Status = MmcHost->SendCommand(MMC_CMD0, 0);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD0): Error\n"));\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ Status = MmcNotifyState (MmcHostInstance, MmcIdleState);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcIdleState\n"));\r
+ return Status;\r
+ }\r
+\r
+ // Are we using SDIO ?\r
+ Status = MmcHost->SendCommand(MMC_CMD5, 0);\r
+ if (Status == EFI_SUCCESS) {\r
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD5): Error - SDIO not supported.\n"));\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ // Check which kind of card we are using. Ver2.00 or later SD Memory Card (PL180 is SD v1.1)\r
+ CmdArg = (0x0UL << 12 | BIT8 | 0xCEUL << 0);\r
+ Status = MmcHost->SendCommand(MMC_CMD8, CmdArg);\r
+ if (Status == EFI_SUCCESS) {\r
+ DEBUG ((EFI_D_ERROR, "Card is SD2.0 => Supports high capacity\n"));\r
+ bHCS = TRUE;\r
+ MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_R7,Response);\r
+ PrintResponseR1(Response[0]);\r
+ //check if it is valid response\r
+ if(Response[0] != CmdArg){\r
+ DEBUG ((EFI_D_ERROR, "The Card is not usable\n"));\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ } else {\r
+ DEBUG ((EFI_D_ERROR, "Not a SD2.0 Card\n"));\r
+ }\r
+\r
+ // We need to wait for the MMC or SD card is ready => (gCardInfo.OCRData.Busy == 1)\r
+ Timeout = MAX_RETRY_COUNT;\r
+ while (Timeout > 0) {\r
+ // SD Card or MMC Card ? CMD55 indicates to the card that the next command is an application specific command\r
+ Status = MmcHost->SendCommand(MMC_CMD55, 0);\r
+ if (Status == EFI_SUCCESS) {\r
+ DEBUG ((EFI_D_INFO, "Card should be SD\n"));\r
+ if (bHCS) {\r
+ MmcHostInstance->CardInfo.CardType = SD_CARD_2;\r
+ } else {\r
+ MmcHostInstance->CardInfo.CardType = SD_CARD;\r
+ }\r
+\r
+ // Note: The first time CmdArg will be zero\r
+ CmdArg = ((UINTN *) &(MmcHostInstance->CardInfo.OCRData))[0];\r
+ if (bHCS) {\r
+ CmdArg |= BIT30;\r
+ }\r
+ Status = MmcHost->SendCommand(MMC_ACMD41, CmdArg);\r
+ if (!EFI_ERROR(Status)) {\r
+ MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_OCR,Response);\r
+ ((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0];\r
+ }\r
+ } else {\r
+ DEBUG ((EFI_D_INFO, "Card should be MMC\n"));\r
+ MmcHostInstance->CardInfo.CardType = MMC_CARD;\r
+\r
+ Status = MmcHost->SendCommand(MMC_CMD1, 0x800000);\r
+ if (!EFI_ERROR(Status)) {\r
+ MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_OCR,Response);\r
+ ((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0];\r
+ }\r
+ }\r
+\r
+ if (!EFI_ERROR(Status)) {\r
+ if (MmcHostInstance->CardInfo.OCRData.Busy == 0) {\r
+ MicroSecondDelay(1);\r
+ Timeout--;\r
+ } else {\r
+ if ((MmcHostInstance->CardInfo.CardType == SD_CARD_2) && (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1)) {\r
+ MmcHostInstance->CardInfo.CardType = SD_CARD_2_HIGH;\r
+ DEBUG ((EFI_D_ERROR, "High capacity card.\n"));\r
+ }\r
+ break; // The MMC/SD card is ready. Continue the Identification Mode\r
+ }\r
+ } else {\r
+ MicroSecondDelay(1);\r
+ Timeout--;\r
+ }\r
+ }\r
+\r
+ if (Timeout == 0) {\r
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode(): No Card\n"));\r
+ ASSERT(0);\r
+ return EFI_NO_MEDIA;\r
+ } else {\r
+ PrintOCR(Response[0]);\r
+ }\r
+\r
+ Status = MmcNotifyState (MmcHostInstance, MmcReadyState);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcReadyState\n"));\r
+ return Status;\r
+ }\r
+\r
+ Status = MmcHost->SendCommand(MMC_CMD2, 0);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD2): Error\n"));\r
+ ASSERT(0);\r
+ return Status;\r
+ }\r
+ MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_CID,Response);\r
+ PrintCID(Response);\r
+\r
+ Status = MmcNotifyState (MmcHostInstance, MmcIdentificationState);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcIdentificationState\n"));\r
+ return Status;\r
+ }\r
+\r
+ CmdArg = 0;\r
+ CmdRetryCnt = CMD_RETRY_COUNT;\r
+ //Keep sending CMD 3 until card enters to Standby mode and Card status is ready\r
+ while((MMC_R0_CURRENTSTATE(Response) != MMC_R0_STATE_STDBY) && CmdRetryCnt-- ){\r
+ Status = MmcHost->SendCommand(MMC_CMD3, CmdArg);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD3): Error\n"));\r
+ return Status;\r
+ }\r
+ MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_RCA,Response);\r
+ PrintRCA(Response[0]);\r
+ }\r
+\r
+ // For MMC card, RCA is assigned by CMD3 while CMD3 dumps the RCA for SD card\r
+ if (MmcHostInstance->CardInfo.CardType != MMC_CARD) {\r
+ MmcHostInstance->CardInfo.RCA = Response[0] >> 16;\r
+ } else {\r
+ MmcHostInstance->CardInfo.RCA = CmdArg;\r
+ }\r
+\r
+ Status = MmcNotifyState (MmcHostInstance, MmcStandByState);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcStandByState\n"));\r
+ return Status;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+MmcReset (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN BOOLEAN ExtendedVerification\r
+ ) {\r
+ // Implement me. Either send a CMD0 (could not work for some MMC host) or just turn off/turn\r
+ // on power and restart Identification mode\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+MmcDetectCard (\r
+ EFI_MMC_HOST_PROTOCOL *MmcHost\r
+ )\r
+{\r
+ if (!MmcHost->IsCardPresent()) {\r
+ return EFI_NO_MEDIA;\r
+ } else {\r
+ return EFI_SUCCESS;\r
+ }\r
+}\r
+\r
+#define MMCI0_BLOCKLEN 512\r
+#define MMCI0_TIMEOUT 10000\r
+\r
+EFI_STATUS MmcIoBlocks (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN UINTN Transfer,\r
+ IN UINT32 MediaId,\r
+ IN EFI_LBA Lba,\r
+ IN UINTN BufferSize,\r
+ OUT VOID *Buffer\r
+ ) {\r
+ UINT32 Response[4];\r
+ EFI_STATUS Status;\r
+ UINTN CardSize, NumBlocks, BlockSize, CmdArg;\r
+ UINTN Timeout;\r
+ UINTN Cmd;\r
+ MMC_HOST_INSTANCE *MmcHostInstance;\r
+ EFI_MMC_HOST_PROTOCOL *MmcHost;\r
+ UINTN BytesRemainingToBeTransfered;\r
+ UINTN BlockCount = 1;\r
+\r
+ MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS(This);\r
+ ASSERT(MmcHostInstance != 0);\r
+ MmcHost = MmcHostInstance->MmcHost;\r
+ ASSERT(MmcHost);\r
+\r
+ if (MmcHost == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ // Check if a Card is Present\r
+ if (!MmcHost->IsCardPresent()) {\r
+ MmcHostInstance->BlockIo.Media->MediaPresent = FALSE;\r
+ MmcHostInstance->BlockIo.Media->LastBlock = 0;\r
+ MmcHostInstance->BlockIo.Media->BlockSize = 512; // Should be zero but there is a bug in DiskIo\r
+ MmcHostInstance->BlockIo.Media->ReadOnly = FALSE; \r
+ return EFI_NO_MEDIA;\r
+ }\r
+\r
+ // If the driver has not been initialized yet then go into Iddentification Mode\r
+ if (MmcHostInstance->State == MmcHwInitializationState) {\r
+ MmcIdentificationMode (MmcHostInstance);\r
+\r
+ //Send a command to get Card specific data\r
+ CmdArg = MmcHostInstance->CardInfo.RCA << 16;\r
+ Status = MmcHost->SendCommand(MMC_CMD9, CmdArg);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD9): Error, Status=%r\n", Status));\r
+ ASSERT(0);\r
+ return Status;\r
+ }\r
+ //Read Response\r
+ MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_CSD,Response);\r
+ PrintCSD(Response);\r
+\r
+ if (MmcHostInstance->CardInfo.CardType == SD_CARD_2_HIGH) {\r
+ ASSERT(0); //TODO: Implementation needed\r
+ CardSize = MMC_CSD_GET_DEVICESIZE(Response);\r
+ NumBlocks = ((CardSize + 1) * 1024);;\r
+ BlockSize = 1 << MMC_CSD_GET_READBLLEN(Response);\r
+ } else {\r
+ CardSize = MMC_CSD_GET_DEVICESIZE(Response);\r
+ NumBlocks = (CardSize + 1) * (1 << (MMC_CSD_GET_DEVICESIZEMULT(Response) + 2));\r
+ BlockSize = 1 << MMC_CSD_GET_READBLLEN(Response);\r
+ }\r
+\r
+ //For >=2G card, BlockSize may be 1K, but the transfer size is 512 bytes.\r
+ if (BlockSize > 512) {\r
+ NumBlocks = MultU64x32(NumBlocks, BlockSize/512);\r
+ BlockSize = 512; \r
+ }\r
+\r
+ MmcHostInstance->BlockIo.Media->LastBlock = (NumBlocks - 1);\r
+ MmcHostInstance->BlockIo.Media->BlockSize = BlockSize;\r
+ MmcHostInstance->BlockIo.Media->ReadOnly = MmcHost->IsReadOnly();\r
+ MmcHostInstance->BlockIo.Media->MediaPresent = TRUE; \r
+ MmcHostInstance->BlockIo.Media->MediaId++; \r
+\r
+ CmdArg = MmcHostInstance->CardInfo.RCA << 16;\r
+ Status = MmcHost->SendCommand(MMC_CMD7, CmdArg);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD7): Error and Status = %r\n", Status));\r
+ ASSERT(0);\r
+ return Status;\r
+ }\r
+\r
+ Status = MmcNotifyState (MmcHostInstance, MmcTransferState);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcTransferState\n"));\r
+ return Status;\r
+ }\r
+ } else {\r
+ // Maybe test if the card has changed to update gMmcMedia information\r
+ if (MmcHostInstance->State == MmcTransferState) {\r
+ //DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : MmcTransferState\n"));\r
+ } else if (MmcHostInstance->State == MmcStandByState) {\r
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : MmcStandByState\n"));\r
+ } else {\r
+ ASSERT(0);\r
+ }\r
+ }\r
+\r
+ if (Lba > This->Media->LastBlock) {\r
+ ASSERT(0);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ if ((BufferSize % This->Media->BlockSize) != 0) {\r
+ ASSERT(0);\r
+ return EFI_BAD_BUFFER_SIZE;\r
+ }\r
+\r
+ BytesRemainingToBeTransfered = BufferSize;\r
+ while (BytesRemainingToBeTransfered > 0) {\r
+\r
+ //Check if the Card is in Ready status\r
+ CmdArg = MmcHostInstance->CardInfo.RCA << 16;\r
+ Response[0] = 0;\r
+ Timeout = 20;\r
+ while((Response[0] & (1 << 8)) && Timeout-- ){\r
+ Status = MmcHost->SendCommand(MMC_CMD13, CmdArg);\r
+ if (!EFI_ERROR(Status)){\r
+ MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_R1,Response);\r
+ }\r
+ }\r
+\r
+ // Set Block Length\r
+ Status = MmcHost->SendCommand(MMC_CMD16, This->Media->BlockSize);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD16): Error This->Media->BlockSize:%d and Error = %r\n",This->Media->BlockSize, Status));\r
+ return Status;\r
+ }\r
+\r
+ // Block Count (not used). Could return an error for SD card\r
+ MmcHost->SendCommand(MMC_CMD23, BlockCount);\r
+\r
+ //Set command argument based on the card access mode (Byte mode or Block mode)\r
+ if (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1) {\r
+ CmdArg = Lba;\r
+ } else {\r
+ CmdArg = Lba * This->Media->BlockSize;\r
+ }\r
+\r
+ if (Transfer == MMC_IOBLOCKS_READ) {\r
+#ifndef USE_STREAM\r
+ // Read a single block\r
+ Cmd = MMC_CMD17;\r
+#else\r
+ //TODO: Should we support read stream (MMC_CMD11)\r
+#endif\r
+ } else {\r
+#ifndef USE_STREAM\r
+ // Write a single block\r
+ Cmd = MMC_CMD24;\r
+#else\r
+ //TODO: Should we support write stream (MMC_CMD20)\r
+#endif\r
+ }\r
+ Status = MmcHost->SendCommand(Cmd, CmdArg);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD%d): Error %r\n",Cmd, Status));\r
+ return Status;\r
+ }\r
+\r
+ if (Transfer == MMC_IOBLOCKS_READ) {\r
+#ifndef USE_STREAM\r
+ // Read one block of Data\r
+ Status = MmcHost->ReadBlockData(Lba,This->Media->BlockSize,Buffer);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_BLKIO, "MmcIdentificationMode(): Error Read Block Data and Status = %r\n", Status));\r
+ return Status;\r
+ }\r
+#else\r
+ //TODO: Read a steam\r
+ ASSERT(0);\r
+#endif\r
+ Status = MmcNotifyState (MmcHostInstance, MmcProgrammingState);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcProgrammingState\n"));\r
+ return Status;\r
+ }\r
+ } else {\r
+#ifndef USE_STREAM\r
+ // Write one block of Data\r
+ Status = MmcHost->WriteBlockData(Lba,This->Media->BlockSize,Buffer);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_BLKIO, "MmcIdentificationMode(): Error Write Block Data and Status = %r\n", Status));\r
+ return Status;\r
+ }\r
+#else\r
+ //TODO: Write a steam\r
+ ASSERT(0);\r
+#endif\r
+ }\r
+\r
+ // Command 12 - Stop transmission (ends read)\r
+ Status = MmcHost->SendCommand(MMC_CMD12, 0);\r
+ MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_R1b,Response);\r
+\r
+ // Command 13 - Read status and wait for programming to complete (return to tran)\r
+ Timeout = MMCI0_TIMEOUT;\r
+ CmdArg = MmcHostInstance->CardInfo.RCA << 16;\r
+ while ((MMC_R0_CURRENTSTATE(Response) != MMC_R0_STATE_TRAN) && Timeout) {\r
+ MmcHost->SendCommand(MMC_CMD13, CmdArg);\r
+ MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_R1,Response);\r
+ NanoSecondDelay(100);\r
+ Timeout--;\r
+ }\r
+\r
+ Status = MmcNotifyState (MmcHostInstance, MmcTransferState);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcTransferState\n"));\r
+ return Status;\r
+ }\r
+\r
+ BytesRemainingToBeTransfered -= This->Media->BlockSize;\r
+ Lba += BlockCount;\r
+ Buffer = (UINT8 *)Buffer + This->Media->BlockSize;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+MmcReadBlocks (\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
+ return MmcIoBlocks (This, MMC_IOBLOCKS_READ, MediaId, Lba, BufferSize, Buffer);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+MmcWriteBlocks (\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
+ return MmcIoBlocks (This, MMC_IOBLOCKS_WRITE, MediaId, Lba, BufferSize, Buffer);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+MmcFlushBlocks (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This\r
+ ) {\r
+ return EFI_SUCCESS;\r
+}\r
+\r
--- /dev/null
+#/** @file\r
+# Build file for the MMC DXE driver\r
+#\r
+# Copyright (c) 2011, ARM Limited. All rights reserved.\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
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = MmcDxe\r
+ FILE_GUID = b6f44cc0-9e45-11df-be21-0002a5d5c51b\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+\r
+ ENTRY_POINT = MmcDxeInitialize\r
+\r
+[Sources.common]\r
+ ComponentName.c\r
+ Mmc.c\r
+ MmcBlockIo.c\r
+ Diagnostics.c\r
+\r
+[Packages]\r
+ EmbeddedPkg/EmbeddedPkg.dec\r
+ MdePkg/MdePkg.dec\r
+\r
+[LibraryClasses]\r
+ BaseLib\r
+ UefiLib\r
+ UefiDriverEntryPoint\r
+ BaseMemoryLib\r
+ TimerLib\r
+\r
+[Protocols]\r
+ gEfiDiskIoProtocolGuid\r
+ gEfiBlockIoProtocolGuid\r
+ gEfiDevicePathProtocolGuid\r
+ gEfiMmcHostProtocolGuid\r
+ gEfiDriverDiagnostics2ProtocolGuid\r
+ \r
+[Depex]\r
+ TRUE
\ No newline at end of file