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 Initialize the MMC Host Pool to support multiple MMC devices
51 InitializeMmcHostPool (
55 InitializeListHead (&mMmcHostPool
);
59 Insert a new Mmc Host controller to the pool
63 IN MMC_HOST_INSTANCE
*MmcHostInstance
66 InsertTailList (&mMmcHostPool
, &(MmcHostInstance
->Link
));
70 Remove a new Mmc Host controller to the pool
74 IN MMC_HOST_INSTANCE
*MmcHostInstance
77 RemoveEntryList (&(MmcHostInstance
->Link
));
80 MMC_HOST_INSTANCE
* 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(&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
,&(MmcHostInstance
->BlockIo
),
129 &gEfiDevicePathProtocolGuid
,MmcHostInstance
->DevicePath
,
132 if (EFI_ERROR(Status
)) {
133 goto FREE_DEVICE_PATH
;
136 return MmcHostInstance
;
139 FreePool(DevicePath
);
142 FreePool(MmcHostInstance
->BlockIo
.Media
);
145 FreePool(MmcHostInstance
);
150 EFI_STATUS
DestroyMmcHostInstance(
151 IN MMC_HOST_INSTANCE
* MmcHostInstance
156 // Uninstall Protocol Interfaces
157 Status
= gBS
->UninstallMultipleProtocolInterfaces(
158 MmcHostInstance
->MmcHandle
,
159 &gEfiBlockIoProtocolGuid
,&(MmcHostInstance
->BlockIo
),
160 &gEfiDevicePathProtocolGuid
,MmcHostInstance
->DevicePath
,
163 ASSERT_EFI_ERROR (Status
);
165 // Free Memory allocated for the instance
166 if (MmcHostInstance
->BlockIo
.Media
) {
167 FreePool(MmcHostInstance
->BlockIo
.Media
);
169 FreePool (MmcHostInstance
);
175 This function checks if the controller implement the Mmc Host and the Device Path Protocols
179 MmcDriverBindingSupported (
180 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
181 IN EFI_HANDLE Controller
,
182 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
186 //EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
187 EFI_MMC_HOST_PROTOCOL
*MmcHost
;
188 EFI_DEV_PATH_PTR Node
;
191 // Check RemainingDevicePath validation
193 if (RemainingDevicePath
!= NULL
) {
195 // Check if RemainingDevicePath is the End of Device Path Node,
196 // if yes, go on checking other conditions
198 if (!IsDevicePathEnd (RemainingDevicePath
)) {
200 // If RemainingDevicePath isn't the End of Device Path Node,
201 // check its validation
203 Node
.DevPath
= RemainingDevicePath
;
204 if (Node
.DevPath
->Type
!= HARDWARE_DEVICE_PATH
||
205 Node
.DevPath
->SubType
!= HW_VENDOR_DP
||
206 DevicePathNodeLength(Node
.DevPath
) != sizeof(VENDOR_DEVICE_PATH
)) {
207 return EFI_UNSUPPORTED
;
213 // Check if Mmc Host protocol is installed by platform
215 Status
= gBS
->OpenProtocol (
217 &gEfiMmcHostProtocolGuid
,
219 This
->DriverBindingHandle
,
221 EFI_OPEN_PROTOCOL_BY_DRIVER
223 if (Status
== EFI_ALREADY_STARTED
) {
226 if (EFI_ERROR (Status
)) {
231 // Close the Mmc Host used to perform the supported test
235 &gEfiMmcHostProtocolGuid
,
236 This
->DriverBindingHandle
,
248 MmcDriverBindingStart (
249 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
250 IN EFI_HANDLE Controller
,
251 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
255 MMC_HOST_INSTANCE
*MmcHostInstance
;
256 EFI_MMC_HOST_PROTOCOL
*MmcHost
;
259 // Check RemainingDevicePath validation
261 if (RemainingDevicePath
!= NULL
) {
263 // Check if RemainingDevicePath is the End of Device Path Node,
264 // if yes, return EFI_SUCCESS
266 if (IsDevicePathEnd (RemainingDevicePath
)) {
272 // Get the Mmc Host protocol
274 Status
= gBS
->OpenProtocol (
276 &gEfiMmcHostProtocolGuid
,
278 This
->DriverBindingHandle
,
280 EFI_OPEN_PROTOCOL_BY_DRIVER
282 if (EFI_ERROR (Status
)) {
283 if (Status
== EFI_ALREADY_STARTED
) {
289 MmcHostInstance
= CreateMmcHostInstance(MmcHost
);
290 if (MmcHostInstance
!= NULL
) {
291 // Add the handle to the pool
292 InsertMmcHost (MmcHostInstance
);
303 MmcDriverBindingStop (
304 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
305 IN EFI_HANDLE Controller
,
306 IN UINTN NumberOfChildren
,
307 IN EFI_HANDLE
*ChildHandleBuffer
310 EFI_STATUS Status
= EFI_SUCCESS
;
311 LIST_ENTRY
*CurrentLink
;
312 MMC_HOST_INSTANCE
*MmcHostInstance
;
314 MMC_TRACE("MmcDriverBindingStop()");
316 // For each MMC instance
317 CurrentLink
= mMmcHostPool
.ForwardLink
;
318 while (CurrentLink
!= NULL
&& CurrentLink
!= &mMmcHostPool
&& (Status
== EFI_SUCCESS
)) {
319 MmcHostInstance
= MMC_HOST_INSTANCE_FROM_LINK(CurrentLink
);
320 ASSERT(MmcHostInstance
!= NULL
);
322 // Close gEfiMmcHostProtocolGuid
323 Status
= gBS
->CloseProtocol (
325 &gEfiMmcHostProtocolGuid
,(VOID
**) &MmcHostInstance
->MmcHost
,
326 This
->DriverBindingHandle
329 // Remove MMC Host Instance from the pool
330 RemoveMmcHost (MmcHostInstance
);
332 // Destroy MmcHostInstance
333 DestroyMmcHostInstance (MmcHostInstance
);
339 EFI_DRIVER_BINDING_PROTOCOL gMmcDriverBinding
= {
340 MmcDriverBindingSupported
,
341 MmcDriverBindingStart
,
342 MmcDriverBindingStop
,
354 IN EFI_HANDLE ImageHandle
,
355 IN EFI_SYSTEM_TABLE
*SystemTable
361 // Initializes MMC Host pool
363 InitializeMmcHostPool ();
366 // Install driver model protocol(s).
368 Status
= EfiLibInstallDriverBindingComponentName2 (
376 ASSERT_EFI_ERROR (Status
);
378 // Install driver diagnostics
379 Status
= gBS
->InstallMultipleProtocolInterfaces (
381 &gEfiDriverDiagnostics2ProtocolGuid
,&gMmcDriverDiagnostics2
,
384 ASSERT_EFI_ERROR (Status
);