2 Main file of the MMC Dxe driver. The driver entrypoint is defined into this file.
4 Copyright (c) 2011-2013, ARM Limited. All rights reserved.
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include <Protocol/DevicePath.h>
12 #include <Library/BaseLib.h>
13 #include <Library/BaseMemoryLib.h>
14 #include <Library/MemoryAllocationLib.h>
15 #include <Library/UefiBootServicesTableLib.h>
16 #include <Library/DevicePathLib.h>
20 EFI_BLOCK_IO_MEDIA mMmcMediaTemplate
= {
21 SIGNATURE_32('m','m','c','o'), // MediaId
22 TRUE
, // RemovableMedia
23 FALSE
, // MediaPresent
24 FALSE
, // LogicalPartition
26 FALSE
, // WriteCaching
34 // This device structure is serviced as a header.
35 // Its next field points to the first root bridge device node.
37 LIST_ENTRY mMmcHostPool
;
40 Event triggered by the timer to check if any cards have been removed
41 or if new ones have been plugged in
44 EFI_EVENT gCheckCardsEvent
;
47 Initialize the MMC Host Pool to support multiple MMC devices
50 InitializeMmcHostPool (
54 InitializeListHead (&mMmcHostPool
);
58 Insert a new Mmc Host controller to the pool
62 IN MMC_HOST_INSTANCE
*MmcHostInstance
65 InsertTailList (&mMmcHostPool
, &(MmcHostInstance
->Link
));
69 Remove a new Mmc Host controller to the pool
73 IN MMC_HOST_INSTANCE
*MmcHostInstance
76 RemoveEntryList (&(MmcHostInstance
->Link
));
79 MMC_HOST_INSTANCE
* CreateMmcHostInstance (
80 IN EFI_MMC_HOST_PROTOCOL
* MmcHost
84 MMC_HOST_INSTANCE
* MmcHostInstance
;
85 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePathNode
;
86 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
88 MmcHostInstance
= AllocateZeroPool (sizeof (MMC_HOST_INSTANCE
));
89 if (MmcHostInstance
== NULL
) {
93 MmcHostInstance
->Signature
= MMC_HOST_INSTANCE_SIGNATURE
;
95 MmcHostInstance
->State
= MmcHwInitializationState
;
97 MmcHostInstance
->BlockIo
.Media
= AllocateCopyPool (sizeof(EFI_BLOCK_IO_MEDIA
), &mMmcMediaTemplate
);
98 if (MmcHostInstance
->BlockIo
.Media
== NULL
) {
102 MmcHostInstance
->BlockIo
.Revision
= EFI_BLOCK_IO_INTERFACE_REVISION
;
103 MmcHostInstance
->BlockIo
.Reset
= MmcReset
;
104 MmcHostInstance
->BlockIo
.ReadBlocks
= MmcReadBlocks
;
105 MmcHostInstance
->BlockIo
.WriteBlocks
= MmcWriteBlocks
;
106 MmcHostInstance
->BlockIo
.FlushBlocks
= MmcFlushBlocks
;
108 MmcHostInstance
->MmcHost
= MmcHost
;
110 // Create DevicePath for the new MMC Host
111 Status
= MmcHost
->BuildDevicePath (MmcHost
, &NewDevicePathNode
);
112 if (EFI_ERROR (Status
)) {
116 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) AllocatePool (END_DEVICE_PATH_LENGTH
);
117 if (DevicePath
== NULL
) {
121 SetDevicePathEndNode (DevicePath
);
122 MmcHostInstance
->DevicePath
= AppendDevicePathNode (DevicePath
, NewDevicePathNode
);
124 // Publish BlockIO protocol interface
125 Status
= gBS
->InstallMultipleProtocolInterfaces (
126 &MmcHostInstance
->MmcHandle
,
127 &gEfiBlockIoProtocolGuid
,&MmcHostInstance
->BlockIo
,
128 &gEfiDevicePathProtocolGuid
,MmcHostInstance
->DevicePath
,
131 if (EFI_ERROR(Status
)) {
132 goto FREE_DEVICE_PATH
;
135 return MmcHostInstance
;
138 FreePool(DevicePath
);
141 FreePool(MmcHostInstance
->BlockIo
.Media
);
144 FreePool(MmcHostInstance
);
149 EFI_STATUS
DestroyMmcHostInstance (
150 IN MMC_HOST_INSTANCE
* MmcHostInstance
155 // Uninstall Protocol Interfaces
156 Status
= gBS
->UninstallMultipleProtocolInterfaces (
157 MmcHostInstance
->MmcHandle
,
158 &gEfiBlockIoProtocolGuid
,&(MmcHostInstance
->BlockIo
),
159 &gEfiDevicePathProtocolGuid
,MmcHostInstance
->DevicePath
,
162 ASSERT_EFI_ERROR (Status
);
164 // Free Memory allocated for the instance
165 if (MmcHostInstance
->BlockIo
.Media
) {
166 FreePool(MmcHostInstance
->BlockIo
.Media
);
168 if (MmcHostInstance
->CardInfo
.ECSDData
) {
169 FreePages (MmcHostInstance
->CardInfo
.ECSDData
, EFI_SIZE_TO_PAGES (sizeof (ECSD
)));
171 FreePool (MmcHostInstance
);
177 This function checks if the controller implement the Mmc Host and the Device Path Protocols
181 MmcDriverBindingSupported (
182 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
183 IN EFI_HANDLE Controller
,
184 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
188 //EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
189 EFI_MMC_HOST_PROTOCOL
*MmcHost
;
190 EFI_DEV_PATH_PTR Node
;
193 // Check RemainingDevicePath validation
195 if (RemainingDevicePath
!= NULL
) {
197 // Check if RemainingDevicePath is the End of Device Path Node,
198 // if yes, go on checking other conditions
200 if (!IsDevicePathEnd (RemainingDevicePath
)) {
202 // If RemainingDevicePath isn't the End of Device Path Node,
203 // check its validation
205 Node
.DevPath
= RemainingDevicePath
;
206 if (Node
.DevPath
->Type
!= HARDWARE_DEVICE_PATH
||
207 Node
.DevPath
->SubType
!= HW_VENDOR_DP
||
208 DevicePathNodeLength(Node
.DevPath
) != sizeof(VENDOR_DEVICE_PATH
)) {
209 return EFI_UNSUPPORTED
;
215 // Check if Mmc Host protocol is installed by platform
217 Status
= gBS
->OpenProtocol (
219 &gEmbeddedMmcHostProtocolGuid
,
221 This
->DriverBindingHandle
,
223 EFI_OPEN_PROTOCOL_BY_DRIVER
225 if (Status
== EFI_ALREADY_STARTED
) {
228 if (EFI_ERROR (Status
)) {
233 // Close the Mmc Host used to perform the supported test
237 &gEmbeddedMmcHostProtocolGuid
,
238 This
->DriverBindingHandle
,
250 MmcDriverBindingStart (
251 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
252 IN EFI_HANDLE Controller
,
253 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
257 MMC_HOST_INSTANCE
*MmcHostInstance
;
258 EFI_MMC_HOST_PROTOCOL
*MmcHost
;
261 // Check RemainingDevicePath validation
263 if (RemainingDevicePath
!= NULL
) {
265 // Check if RemainingDevicePath is the End of Device Path Node,
266 // if yes, return EFI_SUCCESS
268 if (IsDevicePathEnd (RemainingDevicePath
)) {
274 // Get the Mmc Host protocol
276 Status
= gBS
->OpenProtocol (
278 &gEmbeddedMmcHostProtocolGuid
,
280 This
->DriverBindingHandle
,
282 EFI_OPEN_PROTOCOL_BY_DRIVER
284 if (EFI_ERROR (Status
)) {
285 if (Status
== EFI_ALREADY_STARTED
) {
291 MmcHostInstance
= CreateMmcHostInstance(MmcHost
);
292 if (MmcHostInstance
!= NULL
) {
293 // Add the handle to the pool
294 InsertMmcHost (MmcHostInstance
);
296 MmcHostInstance
->Initialized
= FALSE
;
298 // Detect card presence now
299 CheckCardsCallback (NULL
, NULL
);
310 MmcDriverBindingStop (
311 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
312 IN EFI_HANDLE Controller
,
313 IN UINTN NumberOfChildren
,
314 IN EFI_HANDLE
*ChildHandleBuffer
317 EFI_STATUS Status
= EFI_SUCCESS
;
318 LIST_ENTRY
*CurrentLink
;
319 MMC_HOST_INSTANCE
*MmcHostInstance
;
321 MMC_TRACE("MmcDriverBindingStop()");
323 // For each MMC instance
324 CurrentLink
= mMmcHostPool
.ForwardLink
;
325 while (CurrentLink
!= NULL
&& CurrentLink
!= &mMmcHostPool
&& (Status
== EFI_SUCCESS
)) {
326 MmcHostInstance
= MMC_HOST_INSTANCE_FROM_LINK(CurrentLink
);
327 ASSERT(MmcHostInstance
!= NULL
);
329 // Close gEmbeddedMmcHostProtocolGuid
330 Status
= gBS
->CloseProtocol (
332 &gEmbeddedMmcHostProtocolGuid
,
333 This
->DriverBindingHandle
,
337 // Remove MMC Host Instance from the pool
338 RemoveMmcHost (MmcHostInstance
);
340 // Destroy MmcHostInstance
341 DestroyMmcHostInstance (MmcHostInstance
);
354 LIST_ENTRY
*CurrentLink
;
355 MMC_HOST_INSTANCE
*MmcHostInstance
;
358 CurrentLink
= mMmcHostPool
.ForwardLink
;
359 while (CurrentLink
!= NULL
&& CurrentLink
!= &mMmcHostPool
) {
360 MmcHostInstance
= MMC_HOST_INSTANCE_FROM_LINK(CurrentLink
);
361 ASSERT(MmcHostInstance
!= NULL
);
363 if (MmcHostInstance
->MmcHost
->IsCardPresent (MmcHostInstance
->MmcHost
) == !MmcHostInstance
->Initialized
) {
364 MmcHostInstance
->State
= MmcHwInitializationState
;
365 MmcHostInstance
->BlockIo
.Media
->MediaPresent
= !MmcHostInstance
->Initialized
;
366 MmcHostInstance
->Initialized
= !MmcHostInstance
->Initialized
;
368 if (MmcHostInstance
->BlockIo
.Media
->MediaPresent
) {
369 InitializeMmcDevice (MmcHostInstance
);
372 Status
= gBS
->ReinstallProtocolInterface (
373 (MmcHostInstance
->MmcHandle
),
374 &gEfiBlockIoProtocolGuid
,
375 &(MmcHostInstance
->BlockIo
),
376 &(MmcHostInstance
->BlockIo
)
379 if (EFI_ERROR(Status
)) {
380 Print(L
"MMC Card: Error reinstalling BlockIo interface\n");
384 CurrentLink
= CurrentLink
->ForwardLink
;
389 EFI_DRIVER_BINDING_PROTOCOL gMmcDriverBinding
= {
390 MmcDriverBindingSupported
,
391 MmcDriverBindingStart
,
392 MmcDriverBindingStop
,
404 IN EFI_HANDLE ImageHandle
,
405 IN EFI_SYSTEM_TABLE
*SystemTable
411 // Initializes MMC Host pool
413 InitializeMmcHostPool ();
416 // Install driver model protocol(s).
418 Status
= EfiLibInstallDriverBindingComponentName2 (
426 ASSERT_EFI_ERROR (Status
);
428 // Install driver diagnostics
429 Status
= gBS
->InstallMultipleProtocolInterfaces (
431 &gEfiDriverDiagnostics2ProtocolGuid
,&gMmcDriverDiagnostics2
,
434 ASSERT_EFI_ERROR (Status
);
436 // Use a timer to detect if a card has been plugged in or removed
437 Status
= gBS
->CreateEvent (
438 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
443 ASSERT_EFI_ERROR (Status
);
445 Status
= gBS
->SetTimer(
448 (UINT64
)(10*1000*200)); // 200 ms
449 ASSERT_EFI_ERROR (Status
);