X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=EmbeddedPkg%2FUniversal%2FMmcDxe%2FMmc.c;h=3b9dc187276ce190e8200c751b89aa3893a41871;hp=9c67867aa309686cd1f892e4c63d432ad7b3fb82;hb=7bb5fad566afa2dd9feef5ae1ecc658d627f5ac2;hpb=ce73d60afbf3832732f4a718497e004d6c983541 diff --git a/EmbeddedPkg/Universal/MmcDxe/Mmc.c b/EmbeddedPkg/Universal/MmcDxe/Mmc.c index 9c67867aa3..3b9dc18727 100644 --- a/EmbeddedPkg/Universal/MmcDxe/Mmc.c +++ b/EmbeddedPkg/Universal/MmcDxe/Mmc.c @@ -1,27 +1,25 @@ /** @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 + Copyright (c) 2011-2013, ARM Limited. All rights reserved. - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + 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" @@ -44,6 +42,13 @@ EFI_BLOCK_IO_MEDIA mMmcMediaTemplate = { // LIST_ENTRY mMmcHostPool; +/** + Event triggered by the timer to check if any cards have been removed + or if new ones have been plugged in +**/ + +EFI_EVENT gCheckCardsEvent; + /** Initialize the MMC Host Pool to support multiple MMC devices **/ @@ -52,7 +57,7 @@ InitializeMmcHostPool ( VOID ) { - InitializeListHead (&mMmcHostPool); + InitializeListHead (&mMmcHostPool); } /** @@ -63,7 +68,7 @@ InsertMmcHost ( IN MMC_HOST_INSTANCE *MmcHostInstance ) { - InsertTailList (&mMmcHostPool, &(MmcHostInstance->Link)); + InsertTailList (&mMmcHostPool, &(MmcHostInstance->Link)); } /* @@ -74,101 +79,104 @@ RemoveMmcHost ( IN MMC_HOST_INSTANCE *MmcHostInstance ) { - RemoveEntryList (&(MmcHostInstance->Link)); + RemoveEntryList (&(MmcHostInstance->Link)); } -MMC_HOST_INSTANCE* CreateMmcHostInstance( +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; - } + EFI_STATUS Status; + MMC_HOST_INSTANCE* MmcHostInstance; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; - MmcHostInstance->Signature = MMC_HOST_INSTANCE_SIGNATURE; + MmcHostInstance = AllocateZeroPool (sizeof (MMC_HOST_INSTANCE)); + if (MmcHostInstance == NULL) { + return NULL; + } - MmcHostInstance->State = MmcHwInitializationState; - - MmcHostInstance->BlockIo.Media = AllocateCopyPool (sizeof(EFI_BLOCK_IO_MEDIA), &mMmcMediaTemplate); - if (MmcHostInstance->BlockIo.Media == NULL) { - goto FREE_INSTANCE; - } + MmcHostInstance->Signature = MMC_HOST_INSTANCE_SIGNATURE; - 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->State = MmcHwInitializationState; - MmcHostInstance->MmcHost = MmcHost; + MmcHostInstance->BlockIo.Media = AllocateCopyPool (sizeof(EFI_BLOCK_IO_MEDIA), &mMmcMediaTemplate); + if (MmcHostInstance->BlockIo.Media == NULL) { + goto FREE_INSTANCE; + } - // Create DevicePath for the new MMC Host - Status = MmcHost->BuildDevicePath(&NewDevicePathNode); - if (EFI_ERROR (Status)) { - goto FREE_MEDIA; - } + MmcHostInstance->BlockIo.Revision = EFI_BLOCK_IO_INTERFACE_REVISION; + MmcHostInstance->BlockIo.Reset = MmcReset; + MmcHostInstance->BlockIo.ReadBlocks = MmcReadBlocks; + MmcHostInstance->BlockIo.WriteBlocks = MmcWriteBlocks; + MmcHostInstance->BlockIo.FlushBlocks = MmcFlushBlocks; - 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; - } + MmcHostInstance->MmcHost = MmcHost; + + // Create DevicePath for the new MMC Host + Status = MmcHost->BuildDevicePath (MmcHost, &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); - return MmcHostInstance; + // 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); + FreePool(DevicePath); FREE_MEDIA: - FreePool(MmcHostInstance->BlockIo.Media); + FreePool(MmcHostInstance->BlockIo.Media); FREE_INSTANCE: - FreePool(MmcHostInstance); + FreePool(MmcHostInstance); - return NULL; + return NULL; } -EFI_STATUS DestroyMmcHostInstance( +EFI_STATUS DestroyMmcHostInstance ( IN MMC_HOST_INSTANCE* MmcHostInstance ) { - EFI_STATUS Status; + EFI_STATUS Status; - // Uninstall Protocol Interfaces - Status = gBS->UninstallMultipleProtocolInterfaces( + // Uninstall Protocol Interfaces + Status = gBS->UninstallMultipleProtocolInterfaces ( MmcHostInstance->MmcHandle, - &gEfiBlockIoProtocolGuid,&(MmcHostInstance->BlockIo), + &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); + NULL + ); + ASSERT_EFI_ERROR (Status); - return Status; + // Free Memory allocated for the instance + if (MmcHostInstance->BlockIo.Media) { + FreePool(MmcHostInstance->BlockIo.Media); + } + if (MmcHostInstance->CardInfo.ECSDData) { + FreePages (MmcHostInstance->CardInfo.ECSDData, EFI_SIZE_TO_PAGES (sizeof (ECSD))); + } + FreePool (MmcHostInstance); + + return Status; } /** @@ -182,66 +190,66 @@ MmcDriverBindingSupported ( 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; - } - } - } - + 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 Mmc Host protocol is installed by platform + // Check if RemainingDevicePath is the End of Device Path Node, + // if yes, go on checking other conditions // - 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; + 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; + } } - - // - // Close the Mmc Host used to perform the supported test - // - gBS->CloseProtocol ( - Controller, - &gEfiMmcHostProtocolGuid, - This->DriverBindingHandle, - Controller - ); - + } + + // + // 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 @@ -251,52 +259,57 @@ MmcDriverBindingStart ( IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { - EFI_STATUS Status; - MMC_HOST_INSTANCE *MmcHostInstance; - EFI_MMC_HOST_PROTOCOL *MmcHost; - + EFI_STATUS Status; + MMC_HOST_INSTANCE *MmcHostInstance; + EFI_MMC_HOST_PROTOCOL *MmcHost; + + // + // Check RemainingDevicePath validation + // + if (RemainingDevicePath != NULL) { // - // Check RemainingDevicePath validation + // Check if RemainingDevicePath is the End of Device Path Node, + // if yes, return EFI_SUCCESS // - if (RemainingDevicePath != NULL) { - // - // Check if RemainingDevicePath is the End of Device Path Node, - // if yes, return EFI_SUCCESS - // - if (IsDevicePathEnd (RemainingDevicePath)) { - 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; + } + + // + // 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); - } + MmcHostInstance = CreateMmcHostInstance(MmcHost); + if (MmcHostInstance != NULL) { + // Add the handle to the pool + InsertMmcHost (MmcHostInstance); - return EFI_SUCCESS; + MmcHostInstance->Initialized = FALSE; + + // Detect card presence now + CheckCardsCallback (NULL, NULL); + } + + return EFI_SUCCESS; } /** - + **/ EFI_STATUS EFIAPI @@ -307,35 +320,77 @@ MmcDriverBindingStop ( 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 - ); + 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); - // Remove MMC Host Instance from the pool - RemoveMmcHost (MmcHostInstance); + // 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; +} - // Destroy MmcHostInstance - DestroyMmcHostInstance (MmcHostInstance); +VOID +EFIAPI +CheckCardsCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + LIST_ENTRY *CurrentLink; + MMC_HOST_INSTANCE *MmcHostInstance; + EFI_STATUS Status; + + CurrentLink = mMmcHostPool.ForwardLink; + while (CurrentLink != NULL && CurrentLink != &mMmcHostPool) { + MmcHostInstance = MMC_HOST_INSTANCE_FROM_LINK(CurrentLink); + ASSERT(MmcHostInstance != NULL); + + if (MmcHostInstance->MmcHost->IsCardPresent (MmcHostInstance->MmcHost) == !MmcHostInstance->Initialized) { + MmcHostInstance->State = MmcHwInitializationState; + MmcHostInstance->BlockIo.Media->MediaPresent = !MmcHostInstance->Initialized; + MmcHostInstance->Initialized = !MmcHostInstance->Initialized; + + if (MmcHostInstance->BlockIo.Media->MediaPresent) { + InitializeMmcDevice (MmcHostInstance); + } + + Status = gBS->ReinstallProtocolInterface ( + (MmcHostInstance->MmcHandle), + &gEfiBlockIoProtocolGuid, + &(MmcHostInstance->BlockIo), + &(MmcHostInstance->BlockIo) + ); + + if (EFI_ERROR(Status)) { + Print(L"MMC Card: Error reinstalling BlockIo interface\n"); + } } - return Status; + CurrentLink = CurrentLink->ForwardLink; + } } + EFI_DRIVER_BINDING_PROTOCOL gMmcDriverBinding = { MmcDriverBindingSupported, MmcDriverBindingStart, @@ -346,7 +401,7 @@ EFI_DRIVER_BINDING_PROTOCOL gMmcDriverBinding = { }; /** - + **/ EFI_STATUS EFIAPI @@ -355,33 +410,48 @@ MmcDxeInitialize ( 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; + 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); + + // Use a timer to detect if a card has been plugged in or removed + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL | EVT_TIMER, + TPL_CALLBACK, + CheckCardsCallback, + NULL, + &gCheckCardsEvent); + ASSERT_EFI_ERROR (Status); + + Status = gBS->SetTimer( + gCheckCardsEvent, + TimerPeriodic, + (UINT64)(10*1000*200)); // 200 ms + ASSERT_EFI_ERROR (Status); + + return Status; }