From 1bfda055dfbc52678655ab2ded721f9f7c0cd496 Mon Sep 17 00:00:00 2001 From: andrewfish Date: Wed, 2 Feb 2011 22:35:30 +0000 Subject: Sync up ArmPkg with patch from mailing list. Changed name of BdsLib.h to BdsUnixLib.h and fixed a lot of issues with Xcode building. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11293 6f19259b-4bc3-4df7-8a09-765794883524 --- ArmPkg/Universal/MmcDxe/Mmc.c | 387 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 387 insertions(+) create mode 100644 ArmPkg/Universal/MmcDxe/Mmc.c (limited to 'ArmPkg/Universal/MmcDxe/Mmc.c') diff --git a/ArmPkg/Universal/MmcDxe/Mmc.c b/ArmPkg/Universal/MmcDxe/Mmc.c new file mode 100644 index 0000000..90d1172 --- /dev/null +++ b/ArmPkg/Universal/MmcDxe/Mmc.c @@ -0,0 +1,387 @@ +/** @file + Main file of the MMC Dxe driver. The driver entrypoint is defined into this file. + + Copyright (c) 2011, ARM Limited. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "Mmc.h" + +EFI_BLOCK_IO_MEDIA mMmcMediaTemplate = { + SIGNATURE_32('m','m','c','o'), // MediaId + TRUE, // RemovableMedia + FALSE, // MediaPresent + FALSE, // LogicalPartition + FALSE, // ReadOnly + FALSE, // WriteCaching + 512, // BlockSize + 4, // IoAlign + 0, // Pad + 0 // LastBlock +}; + +// +// This device structure is serviced as a header. +// Its next field points to the first root bridge device node. +// +LIST_ENTRY mMmcHostPool; + +/** + Initialize the MMC Host Pool to support multiple MMC devices +**/ +VOID +InitializeMmcHostPool ( + VOID + ) +{ + InitializeListHead (&mMmcHostPool); +} + +/** + Insert a new Mmc Host controller to the pool +**/ +VOID +InsertMmcHost ( + IN MMC_HOST_INSTANCE *MmcHostInstance + ) +{ + InsertTailList (&mMmcHostPool, &(MmcHostInstance->Link)); +} + +/* + Remove a new Mmc Host controller to the pool +*/ +VOID +RemoveMmcHost ( + IN MMC_HOST_INSTANCE *MmcHostInstance + ) +{ + RemoveEntryList (&(MmcHostInstance->Link)); +} + +MMC_HOST_INSTANCE* CreateMmcHostInstance( + IN EFI_MMC_HOST_PROTOCOL* MmcHost + ) +{ + EFI_STATUS Status; + MMC_HOST_INSTANCE* MmcHostInstance; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + MmcHostInstance = AllocateZeroPool (sizeof (MMC_HOST_INSTANCE)); + if (MmcHostInstance == NULL) { + return NULL; + } + + MmcHostInstance->Signature = MMC_HOST_INSTANCE_SIGNATURE; + + MmcHostInstance->State = MmcHwInitializationState; + + MmcHostInstance->BlockIo.Media = AllocateCopyPool (sizeof(EFI_BLOCK_IO_MEDIA), &mMmcMediaTemplate); + if (MmcHostInstance->BlockIo.Media == NULL) { + goto FREE_INSTANCE; + } + + MmcHostInstance->BlockIo.Revision = EFI_BLOCK_IO_INTERFACE_REVISION; + MmcHostInstance->BlockIo.Reset = MmcReset; + MmcHostInstance->BlockIo.ReadBlocks = MmcReadBlocks; + MmcHostInstance->BlockIo.WriteBlocks = MmcWriteBlocks; + MmcHostInstance->BlockIo.FlushBlocks = MmcFlushBlocks; + + MmcHostInstance->MmcHost = MmcHost; + + // Create DevicePath for the new MMC Host + Status = MmcHost->BuildDevicePath(&NewDevicePathNode); + if (EFI_ERROR (Status)) { + goto FREE_MEDIA; + } + + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH); + if (DevicePath == NULL) { + goto FREE_MEDIA; + } + + SetDevicePathEndNode (DevicePath); + MmcHostInstance->DevicePath = AppendDevicePathNode (DevicePath, NewDevicePathNode); + + // Publish BlockIO protocol interface + Status = gBS->InstallMultipleProtocolInterfaces ( + &MmcHostInstance->MmcHandle, + &gEfiBlockIoProtocolGuid,&(MmcHostInstance->BlockIo), + &gEfiDevicePathProtocolGuid,MmcHostInstance->DevicePath, + NULL + ); + if (EFI_ERROR(Status)) { + goto FREE_DEVICE_PATH; + } + + return MmcHostInstance; + +FREE_DEVICE_PATH: + FreePool(DevicePath); + +FREE_MEDIA: + FreePool(MmcHostInstance->BlockIo.Media); + +FREE_INSTANCE: + FreePool(MmcHostInstance); + + return NULL; +} + +EFI_STATUS DestroyMmcHostInstance( + IN MMC_HOST_INSTANCE* MmcHostInstance + ) +{ + EFI_STATUS Status; + + // Uninstall Protocol Interfaces + Status = gBS->UninstallMultipleProtocolInterfaces( + &MmcHostInstance->MmcHandle, + &gEfiBlockIoProtocolGuid,&(MmcHostInstance->BlockIo), + &gEfiDevicePathProtocolGuid,&(MmcHostInstance->DevicePath), + NULL + ); + ASSERT_EFI_ERROR (Status); + + // Free Memory allocated for the instance + if (MmcHostInstance->BlockIo.Media) { + FreePool(MmcHostInstance->BlockIo.Media); + } + FreePool (MmcHostInstance); + + return Status; +} + +/** + This function checks if the controller implement the Mmc Host and the Device Path Protocols +**/ +EFI_STATUS +EFIAPI +MmcDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + //EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_MMC_HOST_PROTOCOL *MmcHost; + EFI_DEV_PATH_PTR Node; + + // + // Check RemainingDevicePath validation + // + if (RemainingDevicePath != NULL) { + // + // Check if RemainingDevicePath is the End of Device Path Node, + // if yes, go on checking other conditions + // + if (!IsDevicePathEnd (RemainingDevicePath)) { + // + // If RemainingDevicePath isn't the End of Device Path Node, + // check its validation + // + Node.DevPath = RemainingDevicePath; + if (Node.DevPath->Type != HARDWARE_DEVICE_PATH || + Node.DevPath->SubType != HW_VENDOR_DP || + DevicePathNodeLength(Node.DevPath) != sizeof(VENDOR_DEVICE_PATH)) { + return EFI_UNSUPPORTED; + } + } + } + + // + // Check if Mmc Host protocol is installed by platform + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiMmcHostProtocolGuid, + (VOID **) &MmcHost, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Close the Mmc Host used to perform the supported test + // + gBS->CloseProtocol ( + Controller, + &gEfiMmcHostProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return EFI_SUCCESS; +} + +/** + +**/ +EFI_STATUS +EFIAPI +MmcDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + MMC_HOST_INSTANCE *MmcHostInstance; + EFI_MMC_HOST_PROTOCOL *MmcHost; + + // + // Check RemainingDevicePath validation + // + if (RemainingDevicePath != NULL) { + // + // Check if RemainingDevicePath is the End of Device Path Node, + // if yes, return EFI_SUCCESS + // + if (IsDevicePathEnd (RemainingDevicePath)) { + return EFI_SUCCESS; + } + } + + // + // Get the Mmc Host protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiMmcHostProtocolGuid, + (VOID **) &MmcHost, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } + return Status; + } + + MmcHostInstance = CreateMmcHostInstance(MmcHost); + if (MmcHostInstance != NULL) { + // Add the handle to the pool + InsertMmcHost (MmcHostInstance); + } + + return EFI_SUCCESS; +} + +/** + +**/ +EFI_STATUS +EFIAPI +MmcDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + LIST_ENTRY *CurrentLink; + MMC_HOST_INSTANCE *MmcHostInstance; + + MMC_TRACE("MmcDriverBindingStop()"); + + // For each MMC instance + CurrentLink = mMmcHostPool.ForwardLink; + while (CurrentLink != NULL && CurrentLink != &mMmcHostPool && (Status == EFI_SUCCESS)) { + MmcHostInstance = MMC_HOST_INSTANCE_FROM_LINK(CurrentLink); + ASSERT(MmcHostInstance != NULL); + + // Close gEfiMmcHostProtocolGuid + Status = gBS->CloseProtocol ( + Controller, + &gEfiMmcHostProtocolGuid,(VOID **) &MmcHostInstance->MmcHost, + This->DriverBindingHandle + ); + + // Remove MMC Host Instance from the pool + RemoveMmcHost (MmcHostInstance); + + // Destroy MmcHostInstance + DestroyMmcHostInstance (MmcHostInstance); + } + + return Status; +} + +EFI_DRIVER_BINDING_PROTOCOL gMmcDriverBinding = { + MmcDriverBindingSupported, + MmcDriverBindingStart, + MmcDriverBindingStop, + 0xa, + NULL, + NULL +}; + +/** + +**/ +EFI_STATUS +EFIAPI +MmcDxeInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Initializes MMC Host pool + // + InitializeMmcHostPool (); + + // + // Install driver model protocol(s). + // + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gMmcDriverBinding, + ImageHandle, + &gMmcComponentName, + &gMmcComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + // Install driver diagnostics + Status = gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gEfiDriverDiagnostics2ProtocolGuid,&gMmcDriverDiagnostics2, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} -- cgit v1.1