//\r
LIST_ENTRY mMmcHostPool;\r
\r
+/**\r
+ Event triggered by the timer to check if any cards have been removed\r
+ or if new ones have been plugged in\r
+**/\r
+\r
+EFI_EVENT gCheckCardsEvent;\r
+\r
/**\r
Initialize the MMC Host Pool to support multiple MMC devices\r
**/\r
VOID\r
)\r
{\r
- InitializeListHead (&mMmcHostPool);\r
+ InitializeListHead (&mMmcHostPool);\r
}\r
\r
/**\r
IN MMC_HOST_INSTANCE *MmcHostInstance\r
)\r
{\r
- InsertTailList (&mMmcHostPool, &(MmcHostInstance->Link));\r
+ InsertTailList (&mMmcHostPool, &(MmcHostInstance->Link));\r
}\r
\r
/*\r
IN MMC_HOST_INSTANCE *MmcHostInstance\r
)\r
{\r
- RemoveEntryList (&(MmcHostInstance->Link));\r
+ RemoveEntryList (&(MmcHostInstance->Link));\r
}\r
\r
-MMC_HOST_INSTANCE* CreateMmcHostInstance(\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
+ EFI_STATUS Status;\r
+ MMC_HOST_INSTANCE* MmcHostInstance;\r
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
\r
- MmcHostInstance->Signature = MMC_HOST_INSTANCE_SIGNATURE;\r
+ MmcHostInstance = AllocateZeroPool (sizeof (MMC_HOST_INSTANCE));\r
+ if (MmcHostInstance == NULL) {\r
+ return NULL;\r
+ }\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
+ MmcHostInstance->Signature = MMC_HOST_INSTANCE_SIGNATURE;\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
+ MmcHostInstance->State = MmcHwInitializationState;\r
\r
- MmcHostInstance->MmcHost = MmcHost;\r
+ MmcHostInstance->BlockIo.Media = AllocateCopyPool (sizeof(EFI_BLOCK_IO_MEDIA), &mMmcMediaTemplate);\r
+ if (MmcHostInstance->BlockIo.Media == NULL) {\r
+ goto FREE_INSTANCE;\r
+ }\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
+ 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
- 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
+ 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
- return MmcHostInstance;\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
+ FreePool(DevicePath);\r
\r
FREE_MEDIA:\r
- FreePool(MmcHostInstance->BlockIo.Media);\r
+ FreePool(MmcHostInstance->BlockIo.Media);\r
\r
FREE_INSTANCE:\r
- FreePool(MmcHostInstance);\r
+ FreePool(MmcHostInstance);\r
\r
- return NULL;\r
+ return NULL;\r
}\r
\r
-EFI_STATUS DestroyMmcHostInstance(\r
+EFI_STATUS DestroyMmcHostInstance (\r
IN MMC_HOST_INSTANCE* MmcHostInstance\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
\r
- // Uninstall Protocol Interfaces\r
- Status = gBS->UninstallMultipleProtocolInterfaces(\r
+ // Uninstall Protocol Interfaces\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
MmcHostInstance->MmcHandle,\r
- &gEfiBlockIoProtocolGuid,&(MmcHostInstance->BlockIo),\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
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
\r
- return Status;\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
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
+ 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 RemainingDevicePath validation\r
+ // Check if RemainingDevicePath is the End of Device Path Node,\r
+ // if yes, go on checking other conditions\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
+ 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
- // 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
+ }\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
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
+ 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 RemainingDevicePath validation\r
+ // Check if RemainingDevicePath is the End of Device Path Node,\r
+ // if yes, return EFI_SUCCESS\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
+ if (IsDevicePathEnd (RemainingDevicePath)) {\r
+ return EFI_SUCCESS;\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
+ //\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
+ MmcHostInstance = CreateMmcHostInstance(MmcHost);\r
+ if (MmcHostInstance != NULL) {\r
+ // Add the handle to the pool\r
+ InsertMmcHost (MmcHostInstance);\r
\r
- return EFI_SUCCESS;\r
+ MmcHostInstance->Initialized = FALSE;\r
+\r
+ // Detect card presence now\r
+ CheckCardsCallback (NULL, NULL);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
}\r
\r
/**\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
+ 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
- // Remove MMC Host Instance from the pool\r
- RemoveMmcHost (MmcHostInstance);\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
- // Destroy MmcHostInstance\r
- DestroyMmcHostInstance (MmcHostInstance);\r
+VOID\r
+EFIAPI\r
+CheckCardsCallback (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ LIST_ENTRY *CurrentLink;\r
+ MMC_HOST_INSTANCE *MmcHostInstance;\r
+ EFI_STATUS Status;\r
+\r
+ CurrentLink = mMmcHostPool.ForwardLink;\r
+ while (CurrentLink != NULL && CurrentLink != &mMmcHostPool) {\r
+ MmcHostInstance = MMC_HOST_INSTANCE_FROM_LINK(CurrentLink);\r
+ ASSERT(MmcHostInstance != NULL);\r
+\r
+ if (MmcHostInstance->MmcHost->IsCardPresent() == !MmcHostInstance->Initialized) {\r
+ MmcHostInstance->State = MmcHwInitializationState;\r
+ MmcHostInstance->BlockIo.Media->MediaPresent = !MmcHostInstance->Initialized;\r
+ MmcHostInstance->Initialized = !MmcHostInstance->Initialized;\r
+\r
+ if(MmcHostInstance->BlockIo.Media->MediaPresent) {\r
+ InitializeMmcDevice(MmcHostInstance);\r
+ }\r
+\r
+ Status = gBS->ReinstallProtocolInterface (\r
+ (MmcHostInstance->MmcHandle),\r
+ &gEfiBlockIoProtocolGuid,\r
+ &(MmcHostInstance->BlockIo),\r
+ &(MmcHostInstance->BlockIo)\r
+ );\r
+\r
+ if (EFI_ERROR(Status)) {\r
+ Print(L"MMC Card: Error reinstalling BlockIo interface\n");\r
+ }\r
}\r
\r
- return Status;\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
}\r
\r
+\r
EFI_DRIVER_BINDING_PROTOCOL gMmcDriverBinding = {\r
MmcDriverBindingSupported,\r
MmcDriverBindingStart,\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
+ 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
+ // Use a timer to detect if a card has been plugged in or removed\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
+ TPL_CALLBACK,\r
+ CheckCardsCallback,\r
+ NULL,\r
+ &gCheckCardsEvent);\r
+ ASSERT_EFI_ERROR (Status); \r
+ \r
+ Status = gBS->SetTimer(\r
+ gCheckCardsEvent,\r
+ TimerPeriodic,\r
+ (UINT64)(10*1000*200)); // 200 ms\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return Status;\r
}\r