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 if (MmcHostInstance
->CardInfo
.ECSDData
) {
175 FreePages (MmcHostInstance
->CardInfo
.ECSDData
, EFI_SIZE_TO_PAGES (sizeof (ECSD
)));
177 FreePool (MmcHostInstance
);
183 This function checks if the controller implement the Mmc Host and the Device Path Protocols
187 MmcDriverBindingSupported (
188 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
189 IN EFI_HANDLE Controller
,
190 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
194 //EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
195 EFI_MMC_HOST_PROTOCOL
*MmcHost
;
196 EFI_DEV_PATH_PTR Node
;
199 // Check RemainingDevicePath validation
201 if (RemainingDevicePath
!= NULL
) {
203 // Check if RemainingDevicePath is the End of Device Path Node,
204 // if yes, go on checking other conditions
206 if (!IsDevicePathEnd (RemainingDevicePath
)) {
208 // If RemainingDevicePath isn't the End of Device Path Node,
209 // check its validation
211 Node
.DevPath
= RemainingDevicePath
;
212 if (Node
.DevPath
->Type
!= HARDWARE_DEVICE_PATH
||
213 Node
.DevPath
->SubType
!= HW_VENDOR_DP
||
214 DevicePathNodeLength(Node
.DevPath
) != sizeof(VENDOR_DEVICE_PATH
)) {
215 return EFI_UNSUPPORTED
;
221 // Check if Mmc Host protocol is installed by platform
223 Status
= gBS
->OpenProtocol (
225 &gEfiMmcHostProtocolGuid
,
227 This
->DriverBindingHandle
,
229 EFI_OPEN_PROTOCOL_BY_DRIVER
231 if (Status
== EFI_ALREADY_STARTED
) {
234 if (EFI_ERROR (Status
)) {
239 // Close the Mmc Host used to perform the supported test
243 &gEfiMmcHostProtocolGuid
,
244 This
->DriverBindingHandle
,
256 MmcDriverBindingStart (
257 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
258 IN EFI_HANDLE Controller
,
259 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
263 MMC_HOST_INSTANCE
*MmcHostInstance
;
264 EFI_MMC_HOST_PROTOCOL
*MmcHost
;
267 // Check RemainingDevicePath validation
269 if (RemainingDevicePath
!= NULL
) {
271 // Check if RemainingDevicePath is the End of Device Path Node,
272 // if yes, return EFI_SUCCESS
274 if (IsDevicePathEnd (RemainingDevicePath
)) {
280 // Get the Mmc Host protocol
282 Status
= gBS
->OpenProtocol (
284 &gEfiMmcHostProtocolGuid
,
286 This
->DriverBindingHandle
,
288 EFI_OPEN_PROTOCOL_BY_DRIVER
290 if (EFI_ERROR (Status
)) {
291 if (Status
== EFI_ALREADY_STARTED
) {
297 MmcHostInstance
= CreateMmcHostInstance(MmcHost
);
298 if (MmcHostInstance
!= NULL
) {
299 // Add the handle to the pool
300 InsertMmcHost (MmcHostInstance
);
302 MmcHostInstance
->Initialized
= FALSE
;
304 // Detect card presence now
305 CheckCardsCallback (NULL
, NULL
);
316 MmcDriverBindingStop (
317 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
318 IN EFI_HANDLE Controller
,
319 IN UINTN NumberOfChildren
,
320 IN EFI_HANDLE
*ChildHandleBuffer
323 EFI_STATUS Status
= EFI_SUCCESS
;
324 LIST_ENTRY
*CurrentLink
;
325 MMC_HOST_INSTANCE
*MmcHostInstance
;
327 MMC_TRACE("MmcDriverBindingStop()");
329 // For each MMC instance
330 CurrentLink
= mMmcHostPool
.ForwardLink
;
331 while (CurrentLink
!= NULL
&& CurrentLink
!= &mMmcHostPool
&& (Status
== EFI_SUCCESS
)) {
332 MmcHostInstance
= MMC_HOST_INSTANCE_FROM_LINK(CurrentLink
);
333 ASSERT(MmcHostInstance
!= NULL
);
335 // Close gEfiMmcHostProtocolGuid
336 Status
= gBS
->CloseProtocol (
338 &gEfiMmcHostProtocolGuid
,(VOID
**) &MmcHostInstance
->MmcHost
,
339 This
->DriverBindingHandle
342 // Remove MMC Host Instance from the pool
343 RemoveMmcHost (MmcHostInstance
);
345 // Destroy MmcHostInstance
346 DestroyMmcHostInstance (MmcHostInstance
);
359 LIST_ENTRY
*CurrentLink
;
360 MMC_HOST_INSTANCE
*MmcHostInstance
;
363 CurrentLink
= mMmcHostPool
.ForwardLink
;
364 while (CurrentLink
!= NULL
&& CurrentLink
!= &mMmcHostPool
) {
365 MmcHostInstance
= MMC_HOST_INSTANCE_FROM_LINK(CurrentLink
);
366 ASSERT(MmcHostInstance
!= NULL
);
368 if (MmcHostInstance
->MmcHost
->IsCardPresent (MmcHostInstance
->MmcHost
) == !MmcHostInstance
->Initialized
) {
369 MmcHostInstance
->State
= MmcHwInitializationState
;
370 MmcHostInstance
->BlockIo
.Media
->MediaPresent
= !MmcHostInstance
->Initialized
;
371 MmcHostInstance
->Initialized
= !MmcHostInstance
->Initialized
;
373 if (MmcHostInstance
->BlockIo
.Media
->MediaPresent
) {
374 InitializeMmcDevice (MmcHostInstance
);
377 Status
= gBS
->ReinstallProtocolInterface (
378 (MmcHostInstance
->MmcHandle
),
379 &gEfiBlockIoProtocolGuid
,
380 &(MmcHostInstance
->BlockIo
),
381 &(MmcHostInstance
->BlockIo
)
384 if (EFI_ERROR(Status
)) {
385 Print(L
"MMC Card: Error reinstalling BlockIo interface\n");
389 CurrentLink
= CurrentLink
->ForwardLink
;
394 EFI_DRIVER_BINDING_PROTOCOL gMmcDriverBinding
= {
395 MmcDriverBindingSupported
,
396 MmcDriverBindingStart
,
397 MmcDriverBindingStop
,
409 IN EFI_HANDLE ImageHandle
,
410 IN EFI_SYSTEM_TABLE
*SystemTable
416 // Initializes MMC Host pool
418 InitializeMmcHostPool ();
421 // Install driver model protocol(s).
423 Status
= EfiLibInstallDriverBindingComponentName2 (
431 ASSERT_EFI_ERROR (Status
);
433 // Install driver diagnostics
434 Status
= gBS
->InstallMultipleProtocolInterfaces (
436 &gEfiDriverDiagnostics2ProtocolGuid
,&gMmcDriverDiagnostics2
,
439 ASSERT_EFI_ERROR (Status
);
441 // Use a timer to detect if a card has been plugged in or removed
442 Status
= gBS
->CreateEvent (
443 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
448 ASSERT_EFI_ERROR (Status
);
450 Status
= gBS
->SetTimer(
453 (UINT64
)(10*1000*200)); // 200 ms
454 ASSERT_EFI_ERROR (Status
);