+++ /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