2 Main file of the MMC Dxe driver. The driver entrypoint is defined into this file.
4 Copyright (c) 2011, ARM Limited. All rights reserved.
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include <Protocol/DevicePath.h>
17 #include <Protocol/MmcHost.h>
19 #include <Library/BaseLib.h>
20 #include <Library/BaseMemoryLib.h>
21 #include <Library/MemoryAllocationLib.h>
22 #include <Library/UefiBootServicesTableLib.h>
23 #include <Library/DevicePathLib.h>
24 #include <Library/DebugLib.h>
28 EFI_BLOCK_IO_MEDIA mMmcMediaTemplate
= {
29 SIGNATURE_32('m','m','c','o'), // MediaId
30 TRUE
, // RemovableMedia
31 FALSE
, // MediaPresent
32 FALSE
, // LogicalPartition
34 FALSE
, // WriteCaching
42 // This device structure is serviced as a header.
43 // Its next field points to the first root bridge device node.
45 LIST_ENTRY mMmcHostPool
;
48 Event triggered by the timer to check if any cards have been removed
49 or if new ones have been plugged in
52 EFI_EVENT gCheckCardsEvent
;
55 Initialize the MMC Host Pool to support multiple MMC devices
58 InitializeMmcHostPool (
62 InitializeListHead (&mMmcHostPool
);
66 Insert a new Mmc Host controller to the pool
70 IN MMC_HOST_INSTANCE
*MmcHostInstance
73 InsertTailList (&mMmcHostPool
, &(MmcHostInstance
->Link
));
77 Remove a new Mmc Host controller to the pool
81 IN MMC_HOST_INSTANCE
*MmcHostInstance
84 RemoveEntryList (&(MmcHostInstance
->Link
));
87 MMC_HOST_INSTANCE
* CreateMmcHostInstance (
88 IN EFI_MMC_HOST_PROTOCOL
* MmcHost
92 MMC_HOST_INSTANCE
* MmcHostInstance
;
93 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePathNode
;
94 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
96 MmcHostInstance
= AllocateZeroPool (sizeof (MMC_HOST_INSTANCE
));
97 if (MmcHostInstance
== NULL
) {
101 MmcHostInstance
->Signature
= MMC_HOST_INSTANCE_SIGNATURE
;
103 MmcHostInstance
->State
= MmcHwInitializationState
;
105 MmcHostInstance
->BlockIo
.Media
= AllocateCopyPool (sizeof(EFI_BLOCK_IO_MEDIA
), &mMmcMediaTemplate
);
106 if (MmcHostInstance
->BlockIo
.Media
== NULL
) {
110 MmcHostInstance
->BlockIo
.Revision
= EFI_BLOCK_IO_INTERFACE_REVISION
;
111 MmcHostInstance
->BlockIo
.Reset
= MmcReset
;
112 MmcHostInstance
->BlockIo
.ReadBlocks
= MmcReadBlocks
;
113 MmcHostInstance
->BlockIo
.WriteBlocks
= MmcWriteBlocks
;
114 MmcHostInstance
->BlockIo
.FlushBlocks
= MmcFlushBlocks
;
116 MmcHostInstance
->MmcHost
= MmcHost
;
118 // Create DevicePath for the new MMC Host
119 Status
= MmcHost
->BuildDevicePath (MmcHost
, &NewDevicePathNode
);
120 if (EFI_ERROR (Status
)) {
124 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) AllocatePool (END_DEVICE_PATH_LENGTH
);
125 if (DevicePath
== NULL
) {
129 SetDevicePathEndNode (DevicePath
);
130 MmcHostInstance
->DevicePath
= AppendDevicePathNode (DevicePath
, NewDevicePathNode
);
132 // Publish BlockIO protocol interface
133 Status
= gBS
->InstallMultipleProtocolInterfaces (
134 &MmcHostInstance
->MmcHandle
,
135 &gEfiBlockIoProtocolGuid
,&MmcHostInstance
->BlockIo
,
136 &gEfiDevicePathProtocolGuid
,MmcHostInstance
->DevicePath
,
139 if (EFI_ERROR(Status
)) {
140 goto FREE_DEVICE_PATH
;
143 return MmcHostInstance
;
146 FreePool(DevicePath
);
149 FreePool(MmcHostInstance
->BlockIo
.Media
);
152 FreePool(MmcHostInstance
);
157 EFI_STATUS
DestroyMmcHostInstance (
158 IN MMC_HOST_INSTANCE
* MmcHostInstance
163 // Uninstall Protocol Interfaces
164 Status
= gBS
->UninstallMultipleProtocolInterfaces (
165 MmcHostInstance
->MmcHandle
,
166 &gEfiBlockIoProtocolGuid
,&(MmcHostInstance
->BlockIo
),
167 &gEfiDevicePathProtocolGuid
,MmcHostInstance
->DevicePath
,
170 ASSERT_EFI_ERROR (Status
);
172 // Free Memory allocated for the instance
173 if (MmcHostInstance
->BlockIo
.Media
) {
174 FreePool(MmcHostInstance
->BlockIo
.Media
);
176 FreePool (MmcHostInstance
);
182 This function checks if the controller implement the Mmc Host and the Device Path Protocols
186 MmcDriverBindingSupported (
187 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
188 IN EFI_HANDLE Controller
,
189 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
193 //EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
194 EFI_MMC_HOST_PROTOCOL
*MmcHost
;
195 EFI_DEV_PATH_PTR Node
;
198 // Check RemainingDevicePath validation
200 if (RemainingDevicePath
!= NULL
) {
202 // Check if RemainingDevicePath is the End of Device Path Node,
203 // if yes, go on checking other conditions
205 if (!IsDevicePathEnd (RemainingDevicePath
)) {
207 // If RemainingDevicePath isn't the End of Device Path Node,
208 // check its validation
210 Node
.DevPath
= RemainingDevicePath
;
211 if (Node
.DevPath
->Type
!= HARDWARE_DEVICE_PATH
||
212 Node
.DevPath
->SubType
!= HW_VENDOR_DP
||
213 DevicePathNodeLength(Node
.DevPath
) != sizeof(VENDOR_DEVICE_PATH
)) {
214 return EFI_UNSUPPORTED
;
220 // Check if Mmc Host protocol is installed by platform
222 Status
= gBS
->OpenProtocol (
224 &gEfiMmcHostProtocolGuid
,
226 This
->DriverBindingHandle
,
228 EFI_OPEN_PROTOCOL_BY_DRIVER
230 if (Status
== EFI_ALREADY_STARTED
) {
233 if (EFI_ERROR (Status
)) {
238 // Close the Mmc Host used to perform the supported test
242 &gEfiMmcHostProtocolGuid
,
243 This
->DriverBindingHandle
,
255 MmcDriverBindingStart (
256 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
257 IN EFI_HANDLE Controller
,
258 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
262 MMC_HOST_INSTANCE
*MmcHostInstance
;
263 EFI_MMC_HOST_PROTOCOL
*MmcHost
;
266 // Check RemainingDevicePath validation
268 if (RemainingDevicePath
!= NULL
) {
270 // Check if RemainingDevicePath is the End of Device Path Node,
271 // if yes, return EFI_SUCCESS
273 if (IsDevicePathEnd (RemainingDevicePath
)) {
279 // Get the Mmc Host protocol
281 Status
= gBS
->OpenProtocol (
283 &gEfiMmcHostProtocolGuid
,
285 This
->DriverBindingHandle
,
287 EFI_OPEN_PROTOCOL_BY_DRIVER
289 if (EFI_ERROR (Status
)) {
290 if (Status
== EFI_ALREADY_STARTED
) {
296 MmcHostInstance
= CreateMmcHostInstance(MmcHost
);
297 if (MmcHostInstance
!= NULL
) {
298 // Add the handle to the pool
299 InsertMmcHost (MmcHostInstance
);
301 MmcHostInstance
->Initialized
= FALSE
;
303 // Detect card presence now
304 CheckCardsCallback (NULL
, NULL
);
315 MmcDriverBindingStop (
316 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
317 IN EFI_HANDLE Controller
,
318 IN UINTN NumberOfChildren
,
319 IN EFI_HANDLE
*ChildHandleBuffer
322 EFI_STATUS Status
= EFI_SUCCESS
;
323 LIST_ENTRY
*CurrentLink
;
324 MMC_HOST_INSTANCE
*MmcHostInstance
;
326 MMC_TRACE("MmcDriverBindingStop()");
328 // For each MMC instance
329 CurrentLink
= mMmcHostPool
.ForwardLink
;
330 while (CurrentLink
!= NULL
&& CurrentLink
!= &mMmcHostPool
&& (Status
== EFI_SUCCESS
)) {
331 MmcHostInstance
= MMC_HOST_INSTANCE_FROM_LINK(CurrentLink
);
332 ASSERT(MmcHostInstance
!= NULL
);
334 // Close gEfiMmcHostProtocolGuid
335 Status
= gBS
->CloseProtocol (
337 &gEfiMmcHostProtocolGuid
,(VOID
**) &MmcHostInstance
->MmcHost
,
338 This
->DriverBindingHandle
341 // Remove MMC Host Instance from the pool
342 RemoveMmcHost (MmcHostInstance
);
344 // Destroy MmcHostInstance
345 DestroyMmcHostInstance (MmcHostInstance
);
358 LIST_ENTRY
*CurrentLink
;
359 MMC_HOST_INSTANCE
*MmcHostInstance
;
362 CurrentLink
= mMmcHostPool
.ForwardLink
;
363 while (CurrentLink
!= NULL
&& CurrentLink
!= &mMmcHostPool
) {
364 MmcHostInstance
= MMC_HOST_INSTANCE_FROM_LINK(CurrentLink
);
365 ASSERT(MmcHostInstance
!= NULL
);
367 if (MmcHostInstance
->MmcHost
->IsCardPresent (MmcHostInstance
->MmcHost
) == !MmcHostInstance
->Initialized
) {
368 MmcHostInstance
->State
= MmcHwInitializationState
;
369 MmcHostInstance
->BlockIo
.Media
->MediaPresent
= !MmcHostInstance
->Initialized
;
370 MmcHostInstance
->Initialized
= !MmcHostInstance
->Initialized
;
372 if (MmcHostInstance
->BlockIo
.Media
->MediaPresent
) {
373 InitializeMmcDevice (MmcHostInstance
);
376 Status
= gBS
->ReinstallProtocolInterface (
377 (MmcHostInstance
->MmcHandle
),
378 &gEfiBlockIoProtocolGuid
,
379 &(MmcHostInstance
->BlockIo
),
380 &(MmcHostInstance
->BlockIo
)
383 if (EFI_ERROR(Status
)) {
384 Print(L
"MMC Card: Error reinstalling BlockIo interface\n");
388 CurrentLink
= CurrentLink
->ForwardLink
;
393 EFI_DRIVER_BINDING_PROTOCOL gMmcDriverBinding
= {
394 MmcDriverBindingSupported
,
395 MmcDriverBindingStart
,
396 MmcDriverBindingStop
,
408 IN EFI_HANDLE ImageHandle
,
409 IN EFI_SYSTEM_TABLE
*SystemTable
415 // Initializes MMC Host pool
417 InitializeMmcHostPool ();
420 // Install driver model protocol(s).
422 Status
= EfiLibInstallDriverBindingComponentName2 (
430 ASSERT_EFI_ERROR (Status
);
432 // Install driver diagnostics
433 Status
= gBS
->InstallMultipleProtocolInterfaces (
435 &gEfiDriverDiagnostics2ProtocolGuid
,&gMmcDriverDiagnostics2
,
438 ASSERT_EFI_ERROR (Status
);
440 // Use a timer to detect if a card has been plugged in or removed
441 Status
= gBS
->CreateEvent (
442 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
447 ASSERT_EFI_ERROR (Status
);
449 Status
= gBS
->SetTimer(
452 (UINT64
)(10*1000*200)); // 200 ms
453 ASSERT_EFI_ERROR (Status
);