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
));
80 CreateMmcHostInstance (
81 IN EFI_MMC_HOST_PROTOCOL
*MmcHost
85 MMC_HOST_INSTANCE
*MmcHostInstance
;
86 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePathNode
;
87 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
89 MmcHostInstance
= AllocateZeroPool (sizeof (MMC_HOST_INSTANCE
));
90 if (MmcHostInstance
== NULL
) {
94 MmcHostInstance
->Signature
= MMC_HOST_INSTANCE_SIGNATURE
;
96 MmcHostInstance
->State
= MmcHwInitializationState
;
98 MmcHostInstance
->BlockIo
.Media
= AllocateCopyPool (sizeof (EFI_BLOCK_IO_MEDIA
), &mMmcMediaTemplate
);
99 if (MmcHostInstance
->BlockIo
.Media
== NULL
) {
103 MmcHostInstance
->BlockIo
.Revision
= EFI_BLOCK_IO_INTERFACE_REVISION
;
104 MmcHostInstance
->BlockIo
.Reset
= MmcReset
;
105 MmcHostInstance
->BlockIo
.ReadBlocks
= MmcReadBlocks
;
106 MmcHostInstance
->BlockIo
.WriteBlocks
= MmcWriteBlocks
;
107 MmcHostInstance
->BlockIo
.FlushBlocks
= MmcFlushBlocks
;
109 MmcHostInstance
->MmcHost
= MmcHost
;
111 // Create DevicePath for the new MMC Host
112 Status
= MmcHost
->BuildDevicePath (MmcHost
, &NewDevicePathNode
);
113 if (EFI_ERROR (Status
)) {
117 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*)AllocatePool (END_DEVICE_PATH_LENGTH
);
118 if (DevicePath
== NULL
) {
122 SetDevicePathEndNode (DevicePath
);
123 MmcHostInstance
->DevicePath
= AppendDevicePathNode (DevicePath
, NewDevicePathNode
);
125 // Publish BlockIO protocol interface
126 Status
= gBS
->InstallMultipleProtocolInterfaces (
127 &MmcHostInstance
->MmcHandle
,
128 &gEfiBlockIoProtocolGuid
,
129 &MmcHostInstance
->BlockIo
,
130 &gEfiDevicePathProtocolGuid
,
131 MmcHostInstance
->DevicePath
,
134 if (EFI_ERROR (Status
)) {
135 goto FREE_DEVICE_PATH
;
138 return MmcHostInstance
;
141 FreePool (DevicePath
);
144 FreePool (MmcHostInstance
->BlockIo
.Media
);
147 FreePool (MmcHostInstance
);
153 DestroyMmcHostInstance (
154 IN MMC_HOST_INSTANCE
*MmcHostInstance
159 // Uninstall Protocol Interfaces
160 Status
= gBS
->UninstallMultipleProtocolInterfaces (
161 MmcHostInstance
->MmcHandle
,
162 &gEfiBlockIoProtocolGuid
,
163 &(MmcHostInstance
->BlockIo
),
164 &gEfiDevicePathProtocolGuid
,
165 MmcHostInstance
->DevicePath
,
168 ASSERT_EFI_ERROR (Status
);
170 // Free Memory allocated for the instance
171 if (MmcHostInstance
->BlockIo
.Media
) {
172 FreePool (MmcHostInstance
->BlockIo
.Media
);
175 if (MmcHostInstance
->CardInfo
.ECSDData
) {
176 FreePages (MmcHostInstance
->CardInfo
.ECSDData
, EFI_SIZE_TO_PAGES (sizeof (ECSD
)));
179 FreePool (MmcHostInstance
);
185 This function checks if the controller implement the Mmc Host and the Device Path Protocols
189 MmcDriverBindingSupported (
190 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
191 IN EFI_HANDLE Controller
,
192 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
196 // EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
197 EFI_MMC_HOST_PROTOCOL
*MmcHost
;
198 EFI_DEV_PATH_PTR Node
;
201 // Check RemainingDevicePath validation
203 if (RemainingDevicePath
!= NULL
) {
205 // Check if RemainingDevicePath is the End of Device Path Node,
206 // if yes, go on checking other conditions
208 if (!IsDevicePathEnd (RemainingDevicePath
)) {
210 // If RemainingDevicePath isn't the End of Device Path Node,
211 // check its validation
213 Node
.DevPath
= RemainingDevicePath
;
214 if ((Node
.DevPath
->Type
!= HARDWARE_DEVICE_PATH
) ||
215 (Node
.DevPath
->SubType
!= HW_VENDOR_DP
) ||
216 (DevicePathNodeLength (Node
.DevPath
) != sizeof (VENDOR_DEVICE_PATH
)))
218 return EFI_UNSUPPORTED
;
224 // Check if Mmc Host protocol is installed by platform
226 Status
= gBS
->OpenProtocol (
228 &gEmbeddedMmcHostProtocolGuid
,
230 This
->DriverBindingHandle
,
232 EFI_OPEN_PROTOCOL_BY_DRIVER
234 if (Status
== EFI_ALREADY_STARTED
) {
238 if (EFI_ERROR (Status
)) {
243 // Close the Mmc Host used to perform the supported test
247 &gEmbeddedMmcHostProtocolGuid
,
248 This
->DriverBindingHandle
,
260 MmcDriverBindingStart (
261 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
262 IN EFI_HANDLE Controller
,
263 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
267 MMC_HOST_INSTANCE
*MmcHostInstance
;
268 EFI_MMC_HOST_PROTOCOL
*MmcHost
;
271 // Check RemainingDevicePath validation
273 if (RemainingDevicePath
!= NULL
) {
275 // Check if RemainingDevicePath is the End of Device Path Node,
276 // if yes, return EFI_SUCCESS
278 if (IsDevicePathEnd (RemainingDevicePath
)) {
284 // Get the Mmc Host protocol
286 Status
= gBS
->OpenProtocol (
288 &gEmbeddedMmcHostProtocolGuid
,
290 This
->DriverBindingHandle
,
292 EFI_OPEN_PROTOCOL_BY_DRIVER
294 if (EFI_ERROR (Status
)) {
295 if (Status
== EFI_ALREADY_STARTED
) {
302 MmcHostInstance
= CreateMmcHostInstance (MmcHost
);
303 if (MmcHostInstance
!= NULL
) {
304 // Add the handle to the pool
305 InsertMmcHost (MmcHostInstance
);
307 MmcHostInstance
->Initialized
= FALSE
;
309 // Detect card presence now
310 CheckCardsCallback (NULL
, NULL
);
321 MmcDriverBindingStop (
322 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
323 IN EFI_HANDLE Controller
,
324 IN UINTN NumberOfChildren
,
325 IN EFI_HANDLE
*ChildHandleBuffer
328 EFI_STATUS Status
= EFI_SUCCESS
;
329 LIST_ENTRY
*CurrentLink
;
330 MMC_HOST_INSTANCE
*MmcHostInstance
;
332 MMC_TRACE ("MmcDriverBindingStop()");
334 // For each MMC instance
335 CurrentLink
= mMmcHostPool
.ForwardLink
;
336 while (CurrentLink
!= NULL
&& CurrentLink
!= &mMmcHostPool
&& (Status
== EFI_SUCCESS
)) {
337 MmcHostInstance
= MMC_HOST_INSTANCE_FROM_LINK (CurrentLink
);
338 ASSERT (MmcHostInstance
!= NULL
);
340 // Close gEmbeddedMmcHostProtocolGuid
341 Status
= gBS
->CloseProtocol (
343 &gEmbeddedMmcHostProtocolGuid
,
344 This
->DriverBindingHandle
,
348 // Remove MMC Host Instance from the pool
349 RemoveMmcHost (MmcHostInstance
);
351 // Destroy MmcHostInstance
352 DestroyMmcHostInstance (MmcHostInstance
);
365 LIST_ENTRY
*CurrentLink
;
366 MMC_HOST_INSTANCE
*MmcHostInstance
;
369 CurrentLink
= mMmcHostPool
.ForwardLink
;
370 while (CurrentLink
!= NULL
&& CurrentLink
!= &mMmcHostPool
) {
371 MmcHostInstance
= MMC_HOST_INSTANCE_FROM_LINK (CurrentLink
);
372 ASSERT (MmcHostInstance
!= NULL
);
374 if (MmcHostInstance
->MmcHost
->IsCardPresent (MmcHostInstance
->MmcHost
) == !MmcHostInstance
->Initialized
) {
375 MmcHostInstance
->State
= MmcHwInitializationState
;
376 MmcHostInstance
->BlockIo
.Media
->MediaPresent
= !MmcHostInstance
->Initialized
;
377 MmcHostInstance
->Initialized
= !MmcHostInstance
->Initialized
;
379 if (MmcHostInstance
->BlockIo
.Media
->MediaPresent
) {
380 InitializeMmcDevice (MmcHostInstance
);
383 Status
= gBS
->ReinstallProtocolInterface (
384 (MmcHostInstance
->MmcHandle
),
385 &gEfiBlockIoProtocolGuid
,
386 &(MmcHostInstance
->BlockIo
),
387 &(MmcHostInstance
->BlockIo
)
390 if (EFI_ERROR (Status
)) {
391 Print (L
"MMC Card: Error reinstalling BlockIo interface\n");
395 CurrentLink
= CurrentLink
->ForwardLink
;
399 EFI_DRIVER_BINDING_PROTOCOL gMmcDriverBinding
= {
400 MmcDriverBindingSupported
,
401 MmcDriverBindingStart
,
402 MmcDriverBindingStop
,
414 IN EFI_HANDLE ImageHandle
,
415 IN EFI_SYSTEM_TABLE
*SystemTable
421 // Initializes MMC Host pool
423 InitializeMmcHostPool ();
426 // Install driver model protocol(s).
428 Status
= EfiLibInstallDriverBindingComponentName2 (
436 ASSERT_EFI_ERROR (Status
);
438 // Install driver diagnostics
439 Status
= gBS
->InstallMultipleProtocolInterfaces (
441 &gEfiDriverDiagnostics2ProtocolGuid
,
442 &gMmcDriverDiagnostics2
,
445 ASSERT_EFI_ERROR (Status
);
447 // Use a timer to detect if a card has been plugged in or removed
448 Status
= gBS
->CreateEvent (
449 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
455 ASSERT_EFI_ERROR (Status
);
457 Status
= gBS
->SetTimer (
460 (UINT64
)(10*1000*200)
462 ASSERT_EFI_ERROR (Status
);