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 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>
18 #include <Library/BaseLib.h>
19 #include <Library/BaseMemoryLib.h>
20 #include <Library/MemoryAllocationLib.h>
21 #include <Library/UefiBootServicesTableLib.h>
22 #include <Library/DevicePathLib.h>
26 EFI_BLOCK_IO_MEDIA mMmcMediaTemplate
= {
27 SIGNATURE_32('m','m','c','o'), // MediaId
28 TRUE
, // RemovableMedia
29 FALSE
, // MediaPresent
30 FALSE
, // LogicalPartition
32 FALSE
, // WriteCaching
40 // This device structure is serviced as a header.
41 // Its next field points to the first root bridge device node.
43 LIST_ENTRY mMmcHostPool
;
46 Event triggered by the timer to check if any cards have been removed
47 or if new ones have been plugged in
50 EFI_EVENT gCheckCardsEvent
;
53 Initialize the MMC Host Pool to support multiple MMC devices
56 InitializeMmcHostPool (
60 InitializeListHead (&mMmcHostPool
);
64 Insert a new Mmc Host controller to the pool
68 IN MMC_HOST_INSTANCE
*MmcHostInstance
71 InsertTailList (&mMmcHostPool
, &(MmcHostInstance
->Link
));
75 Remove a new Mmc Host controller to the pool
79 IN MMC_HOST_INSTANCE
*MmcHostInstance
82 RemoveEntryList (&(MmcHostInstance
->Link
));
85 MMC_HOST_INSTANCE
* CreateMmcHostInstance (
86 IN EFI_MMC_HOST_PROTOCOL
* MmcHost
90 MMC_HOST_INSTANCE
* MmcHostInstance
;
91 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePathNode
;
92 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
94 MmcHostInstance
= AllocateZeroPool (sizeof (MMC_HOST_INSTANCE
));
95 if (MmcHostInstance
== NULL
) {
99 MmcHostInstance
->Signature
= MMC_HOST_INSTANCE_SIGNATURE
;
101 MmcHostInstance
->State
= MmcHwInitializationState
;
103 MmcHostInstance
->BlockIo
.Media
= AllocateCopyPool (sizeof(EFI_BLOCK_IO_MEDIA
), &mMmcMediaTemplate
);
104 if (MmcHostInstance
->BlockIo
.Media
== NULL
) {
108 MmcHostInstance
->BlockIo
.Revision
= EFI_BLOCK_IO_INTERFACE_REVISION
;
109 MmcHostInstance
->BlockIo
.Reset
= MmcReset
;
110 MmcHostInstance
->BlockIo
.ReadBlocks
= MmcReadBlocks
;
111 MmcHostInstance
->BlockIo
.WriteBlocks
= MmcWriteBlocks
;
112 MmcHostInstance
->BlockIo
.FlushBlocks
= MmcFlushBlocks
;
114 MmcHostInstance
->MmcHost
= MmcHost
;
116 // Create DevicePath for the new MMC Host
117 Status
= MmcHost
->BuildDevicePath (MmcHost
, &NewDevicePathNode
);
118 if (EFI_ERROR (Status
)) {
122 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) AllocatePool (END_DEVICE_PATH_LENGTH
);
123 if (DevicePath
== NULL
) {
127 SetDevicePathEndNode (DevicePath
);
128 MmcHostInstance
->DevicePath
= AppendDevicePathNode (DevicePath
, NewDevicePathNode
);
130 // Publish BlockIO protocol interface
131 Status
= gBS
->InstallMultipleProtocolInterfaces (
132 &MmcHostInstance
->MmcHandle
,
133 &gEfiBlockIoProtocolGuid
,&MmcHostInstance
->BlockIo
,
134 &gEfiDevicePathProtocolGuid
,MmcHostInstance
->DevicePath
,
137 if (EFI_ERROR(Status
)) {
138 goto FREE_DEVICE_PATH
;
141 return MmcHostInstance
;
144 FreePool(DevicePath
);
147 FreePool(MmcHostInstance
->BlockIo
.Media
);
150 FreePool(MmcHostInstance
);
155 EFI_STATUS
DestroyMmcHostInstance (
156 IN MMC_HOST_INSTANCE
* MmcHostInstance
161 // Uninstall Protocol Interfaces
162 Status
= gBS
->UninstallMultipleProtocolInterfaces (
163 MmcHostInstance
->MmcHandle
,
164 &gEfiBlockIoProtocolGuid
,&(MmcHostInstance
->BlockIo
),
165 &gEfiDevicePathProtocolGuid
,MmcHostInstance
->DevicePath
,
168 ASSERT_EFI_ERROR (Status
);
170 // Free Memory allocated for the instance
171 if (MmcHostInstance
->BlockIo
.Media
) {
172 FreePool(MmcHostInstance
->BlockIo
.Media
);
174 FreePool (MmcHostInstance
);
180 This function checks if the controller implement the Mmc Host and the Device Path Protocols
184 MmcDriverBindingSupported (
185 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
186 IN EFI_HANDLE Controller
,
187 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
191 //EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
192 EFI_MMC_HOST_PROTOCOL
*MmcHost
;
193 EFI_DEV_PATH_PTR Node
;
196 // Check RemainingDevicePath validation
198 if (RemainingDevicePath
!= NULL
) {
200 // Check if RemainingDevicePath is the End of Device Path Node,
201 // if yes, go on checking other conditions
203 if (!IsDevicePathEnd (RemainingDevicePath
)) {
205 // If RemainingDevicePath isn't the End of Device Path Node,
206 // check its validation
208 Node
.DevPath
= RemainingDevicePath
;
209 if (Node
.DevPath
->Type
!= HARDWARE_DEVICE_PATH
||
210 Node
.DevPath
->SubType
!= HW_VENDOR_DP
||
211 DevicePathNodeLength(Node
.DevPath
) != sizeof(VENDOR_DEVICE_PATH
)) {
212 return EFI_UNSUPPORTED
;
218 // Check if Mmc Host protocol is installed by platform
220 Status
= gBS
->OpenProtocol (
222 &gEfiMmcHostProtocolGuid
,
224 This
->DriverBindingHandle
,
226 EFI_OPEN_PROTOCOL_BY_DRIVER
228 if (Status
== EFI_ALREADY_STARTED
) {
231 if (EFI_ERROR (Status
)) {
236 // Close the Mmc Host used to perform the supported test
240 &gEfiMmcHostProtocolGuid
,
241 This
->DriverBindingHandle
,
253 MmcDriverBindingStart (
254 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
255 IN EFI_HANDLE Controller
,
256 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
260 MMC_HOST_INSTANCE
*MmcHostInstance
;
261 EFI_MMC_HOST_PROTOCOL
*MmcHost
;
264 // Check RemainingDevicePath validation
266 if (RemainingDevicePath
!= NULL
) {
268 // Check if RemainingDevicePath is the End of Device Path Node,
269 // if yes, return EFI_SUCCESS
271 if (IsDevicePathEnd (RemainingDevicePath
)) {
277 // Get the Mmc Host protocol
279 Status
= gBS
->OpenProtocol (
281 &gEfiMmcHostProtocolGuid
,
283 This
->DriverBindingHandle
,
285 EFI_OPEN_PROTOCOL_BY_DRIVER
287 if (EFI_ERROR (Status
)) {
288 if (Status
== EFI_ALREADY_STARTED
) {
294 MmcHostInstance
= CreateMmcHostInstance(MmcHost
);
295 if (MmcHostInstance
!= NULL
) {
296 // Add the handle to the pool
297 InsertMmcHost (MmcHostInstance
);
299 MmcHostInstance
->Initialized
= FALSE
;
301 // Detect card presence now
302 CheckCardsCallback (NULL
, NULL
);
313 MmcDriverBindingStop (
314 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
315 IN EFI_HANDLE Controller
,
316 IN UINTN NumberOfChildren
,
317 IN EFI_HANDLE
*ChildHandleBuffer
320 EFI_STATUS Status
= EFI_SUCCESS
;
321 LIST_ENTRY
*CurrentLink
;
322 MMC_HOST_INSTANCE
*MmcHostInstance
;
324 MMC_TRACE("MmcDriverBindingStop()");
326 // For each MMC instance
327 CurrentLink
= mMmcHostPool
.ForwardLink
;
328 while (CurrentLink
!= NULL
&& CurrentLink
!= &mMmcHostPool
&& (Status
== EFI_SUCCESS
)) {
329 MmcHostInstance
= MMC_HOST_INSTANCE_FROM_LINK(CurrentLink
);
330 ASSERT(MmcHostInstance
!= NULL
);
332 // Close gEfiMmcHostProtocolGuid
333 Status
= gBS
->CloseProtocol (
335 &gEfiMmcHostProtocolGuid
,(VOID
**) &MmcHostInstance
->MmcHost
,
336 This
->DriverBindingHandle
339 // Remove MMC Host Instance from the pool
340 RemoveMmcHost (MmcHostInstance
);
342 // Destroy MmcHostInstance
343 DestroyMmcHostInstance (MmcHostInstance
);
356 LIST_ENTRY
*CurrentLink
;
357 MMC_HOST_INSTANCE
*MmcHostInstance
;
360 CurrentLink
= mMmcHostPool
.ForwardLink
;
361 while (CurrentLink
!= NULL
&& CurrentLink
!= &mMmcHostPool
) {
362 MmcHostInstance
= MMC_HOST_INSTANCE_FROM_LINK(CurrentLink
);
363 ASSERT(MmcHostInstance
!= NULL
);
365 if (MmcHostInstance
->MmcHost
->IsCardPresent (MmcHostInstance
->MmcHost
) == !MmcHostInstance
->Initialized
) {
366 MmcHostInstance
->State
= MmcHwInitializationState
;
367 MmcHostInstance
->BlockIo
.Media
->MediaPresent
= !MmcHostInstance
->Initialized
;
368 MmcHostInstance
->Initialized
= !MmcHostInstance
->Initialized
;
370 if (MmcHostInstance
->BlockIo
.Media
->MediaPresent
) {
371 InitializeMmcDevice (MmcHostInstance
);
374 Status
= gBS
->ReinstallProtocolInterface (
375 (MmcHostInstance
->MmcHandle
),
376 &gEfiBlockIoProtocolGuid
,
377 &(MmcHostInstance
->BlockIo
),
378 &(MmcHostInstance
->BlockIo
)
381 if (EFI_ERROR(Status
)) {
382 Print(L
"MMC Card: Error reinstalling BlockIo interface\n");
386 CurrentLink
= CurrentLink
->ForwardLink
;
391 EFI_DRIVER_BINDING_PROTOCOL gMmcDriverBinding
= {
392 MmcDriverBindingSupported
,
393 MmcDriverBindingStart
,
394 MmcDriverBindingStop
,
406 IN EFI_HANDLE ImageHandle
,
407 IN EFI_SYSTEM_TABLE
*SystemTable
413 // Initializes MMC Host pool
415 InitializeMmcHostPool ();
418 // Install driver model protocol(s).
420 Status
= EfiLibInstallDriverBindingComponentName2 (
428 ASSERT_EFI_ERROR (Status
);
430 // Install driver diagnostics
431 Status
= gBS
->InstallMultipleProtocolInterfaces (
433 &gEfiDriverDiagnostics2ProtocolGuid
,&gMmcDriverDiagnostics2
,
436 ASSERT_EFI_ERROR (Status
);
438 // Use a timer to detect if a card has been plugged in or removed
439 Status
= gBS
->CreateEvent (
440 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
445 ASSERT_EFI_ERROR (Status
);
447 Status
= gBS
->SetTimer(
450 (UINT64
)(10*1000*200)); // 200 ms
451 ASSERT_EFI_ERROR (Status
);