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(&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
;
312 MmcDriverBindingStop (
313 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
314 IN EFI_HANDLE Controller
,
315 IN UINTN NumberOfChildren
,
316 IN EFI_HANDLE
*ChildHandleBuffer
319 EFI_STATUS Status
= EFI_SUCCESS
;
320 LIST_ENTRY
*CurrentLink
;
321 MMC_HOST_INSTANCE
*MmcHostInstance
;
323 MMC_TRACE("MmcDriverBindingStop()");
325 // For each MMC instance
326 CurrentLink
= mMmcHostPool
.ForwardLink
;
327 while (CurrentLink
!= NULL
&& CurrentLink
!= &mMmcHostPool
&& (Status
== EFI_SUCCESS
)) {
328 MmcHostInstance
= MMC_HOST_INSTANCE_FROM_LINK(CurrentLink
);
329 ASSERT(MmcHostInstance
!= NULL
);
331 // Close gEfiMmcHostProtocolGuid
332 Status
= gBS
->CloseProtocol (
334 &gEfiMmcHostProtocolGuid
,(VOID
**) &MmcHostInstance
->MmcHost
,
335 This
->DriverBindingHandle
338 // Remove MMC Host Instance from the pool
339 RemoveMmcHost (MmcHostInstance
);
341 // Destroy MmcHostInstance
342 DestroyMmcHostInstance (MmcHostInstance
);
355 LIST_ENTRY
*CurrentLink
;
356 MMC_HOST_INSTANCE
*MmcHostInstance
;
359 CurrentLink
= mMmcHostPool
.ForwardLink
;
360 while (CurrentLink
!= NULL
&& CurrentLink
!= &mMmcHostPool
) {
361 MmcHostInstance
= MMC_HOST_INSTANCE_FROM_LINK(CurrentLink
);
362 ASSERT(MmcHostInstance
!= NULL
);
364 if (MmcHostInstance
->MmcHost
->IsCardPresent() == !MmcHostInstance
->Initialized
) {
365 MmcHostInstance
->State
= MmcHwInitializationState
;
366 MmcHostInstance
->BlockIo
.Media
->MediaPresent
= !MmcHostInstance
->Initialized
;
367 MmcHostInstance
->Initialized
= !MmcHostInstance
->Initialized
;
369 Status
= gBS
->ReinstallProtocolInterface (
370 (MmcHostInstance
->MmcHandle
),
371 &gEfiBlockIoProtocolGuid
,
372 &(MmcHostInstance
->BlockIo
),
373 &(MmcHostInstance
->BlockIo
)
376 if (EFI_ERROR(Status
)) {
377 Print(L
"MMC Card: Error reinstalling BlockIo interface\n");
381 CurrentLink
= CurrentLink
->ForwardLink
;
385 EFI_DRIVER_BINDING_PROTOCOL gMmcDriverBinding
= {
386 MmcDriverBindingSupported
,
387 MmcDriverBindingStart
,
388 MmcDriverBindingStop
,
400 IN EFI_HANDLE ImageHandle
,
401 IN EFI_SYSTEM_TABLE
*SystemTable
407 // Initializes MMC Host pool
409 InitializeMmcHostPool ();
412 // Install driver model protocol(s).
414 Status
= EfiLibInstallDriverBindingComponentName2 (
422 ASSERT_EFI_ERROR (Status
);
424 // Install driver diagnostics
425 Status
= gBS
->InstallMultipleProtocolInterfaces (
427 &gEfiDriverDiagnostics2ProtocolGuid
,&gMmcDriverDiagnostics2
,
430 ASSERT_EFI_ERROR (Status
);
432 // Use a timer to detect if a card has been plugged in or removed
433 Status
= gBS
->CreateEvent (
434 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
439 ASSERT_EFI_ERROR (Status
);
441 Status
= gBS
->SetTimer(
444 (UINT64
)(10*1000*200)); // 200 ms
445 ASSERT_EFI_ERROR (Status
);