Parcourir la source

EmbeddedPkg/MmcDxe: Create a periodic function to check if a card is present

In the former version, the check was done for every BlockIo operation.
By using a periodical function, we check less time in consequence performance
are better.



git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12128 6f19259b-4bc3-4df7-8a09-765794883524
oliviermartin il y a 12 ans
Parent
commit
3de99375d2

+ 62 - 1
EmbeddedPkg/Universal/MmcDxe/Mmc.c

@@ -44,6 +44,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
 **/
@@ -125,7 +132,7 @@ MMC_HOST_INSTANCE* CreateMmcHostInstance (
   // Publish BlockIO protocol interface
   Status = gBS->InstallMultipleProtocolInterfaces (
                 &MmcHostInstance->MmcHandle,
-                &gEfiBlockIoProtocolGuid,&(MmcHostInstance->BlockIo),
+                &gEfiBlockIoProtocolGuid,&MmcHostInstance->BlockIo,
                 &gEfiDevicePathProtocolGuid,MmcHostInstance->DevicePath,
                 NULL
                 );
@@ -290,6 +297,8 @@ MmcDriverBindingStart (
   if (MmcHostInstance != NULL) {
     // Add the handle to the pool
     InsertMmcHost (MmcHostInstance);
+
+    MmcHostInstance->Initialized = FALSE;
   }
 
   return EFI_SUCCESS;
@@ -336,6 +345,43 @@ MmcDriverBindingStop (
   return Status;
 }
 
+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->Initialized) {
+      MmcHostInstance->State = MmcHwInitializationState;
+      MmcHostInstance->BlockIo.Media->MediaPresent = !MmcHostInstance->Initialized;
+      MmcHostInstance->Initialized = !MmcHostInstance->Initialized;
+
+      Status = gBS->ReinstallProtocolInterface (
+                    (MmcHostInstance->MmcHandle),
+                    &gEfiBlockIoProtocolGuid,
+                    &(MmcHostInstance->BlockIo),
+                    &(MmcHostInstance->BlockIo)
+                    );
+
+      if (EFI_ERROR(Status)) {
+        Print(L"MMC Card: Error reinstalling BlockIo interface\n");
+      }
+    }
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+}
+
 EFI_DRIVER_BINDING_PROTOCOL gMmcDriverBinding = {
   MmcDriverBindingSupported,
   MmcDriverBindingStart,
@@ -383,5 +429,20 @@ MmcDxeInitialize (
                 );
   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;
 }

+ 2 - 0
EmbeddedPkg/Universal/MmcDxe/Mmc.h

@@ -146,6 +146,8 @@ typedef struct _MMC_HOST_INSTANCE {
   EFI_BLOCK_IO_PROTOCOL     BlockIo;
   CARD_INFO                 CardInfo;
   EFI_MMC_HOST_PROTOCOL     *MmcHost;
+  
+  BOOLEAN                   Initialized;
 } MMC_HOST_INSTANCE;
 
 #define MMC_HOST_INSTANCE_SIGNATURE                 SIGNATURE_32('m', 'm', 'c', 'h')

+ 23 - 5
EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c

@@ -369,6 +369,28 @@ MmcReset (
   IN BOOLEAN                  ExtendedVerification
   )
 {
+  MMC_HOST_INSTANCE       *MmcHostInstance;
+
+  MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS(This);
+
+  if (MmcHostInstance->MmcHost == NULL) {
+    // Nothing to do
+    return EFI_SUCCESS;
+  }
+
+  // If a card is not present then clear all media settings
+  if (!MmcHostInstance->MmcHost->IsCardPresent()) {
+    MmcHostInstance->BlockIo.Media->MediaPresent = FALSE;
+    MmcHostInstance->BlockIo.Media->LastBlock    = 0;
+    MmcHostInstance->BlockIo.Media->BlockSize    = 512;  // Should be zero but there is a bug in DiskIo
+    MmcHostInstance->BlockIo.Media->ReadOnly     = FALSE;
+
+    // Indicate that the driver requires initialization
+    MmcHostInstance->State = MmcHwInitializationState;
+
+    return EFI_SUCCESS;
+  }
+
   // Implement me. Either send a CMD0 (could not work for some MMC host) or just turn off/turn
   //      on power and restart Identification mode
   return EFI_SUCCESS;
@@ -419,11 +441,7 @@ MmcIoBlocks (
   }
 
   // Check if a Card is Present
-  if (!MmcHost->IsCardPresent()) {
-    MmcHostInstance->BlockIo.Media->MediaPresent = FALSE;
-    MmcHostInstance->BlockIo.Media->LastBlock    = 0;
-    MmcHostInstance->BlockIo.Media->BlockSize    = 512;  // Should be zero but there is a bug in DiskIo
-    MmcHostInstance->BlockIo.Media->ReadOnly     = FALSE;
+  if (!MmcHostInstance->BlockIo.Media->MediaPresent) {
     return EFI_NO_MEDIA;
   }