ArmPkg: Fix warnings raised by ARMGCC
[mirror_edk2.git] / EmbeddedPkg / Universal / MmcDxe / Mmc.c
CommitLineData
1bfda055 1/** @file\r
2 Main file of the MMC Dxe driver. The driver entrypoint is defined into this file.\r
3\r
4 Copyright (c) 2011, ARM Limited. All rights reserved.\r
5 \r
6 This program and the accompanying materials \r
7 are licensed and made available under the terms and conditions of the BSD License \r
8 which accompanies this distribution. The full text of the license may be found at \r
9 http://opensource.org/licenses/bsd-license.php \r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
13\r
14**/\r
15\r
16#include <Protocol/DevicePath.h>\r
17#include <Protocol/MmcHost.h>\r
18\r
19#include <Library/BaseLib.h>\r
20#include <Library/BaseMemoryLib.h>\r
21#include <Library/MemoryAllocationLib.h>\r
22#include <Library/UefiBootServicesTableLib.h>\r
23#include <Library/DevicePathLib.h>\r
24#include <Library/DebugLib.h>\r
25\r
26#include "Mmc.h"\r
27\r
28EFI_BLOCK_IO_MEDIA mMmcMediaTemplate = {\r
29 SIGNATURE_32('m','m','c','o'), // MediaId\r
30 TRUE, // RemovableMedia\r
31 FALSE, // MediaPresent\r
32 FALSE, // LogicalPartition\r
33 FALSE, // ReadOnly\r
34 FALSE, // WriteCaching\r
35 512, // BlockSize\r
36 4, // IoAlign\r
37 0, // Pad\r
38 0 // LastBlock\r
39};\r
40\r
41//\r
42// This device structure is serviced as a header.\r
43// Its next field points to the first root bridge device node.\r
44//\r
45LIST_ENTRY mMmcHostPool;\r
46\r
47/**\r
48 Initialize the MMC Host Pool to support multiple MMC devices\r
49**/\r
50VOID\r
51InitializeMmcHostPool (\r
52 VOID\r
53 )\r
54{\r
e8e95df4 55 InitializeListHead (&mMmcHostPool);\r
1bfda055 56}\r
57\r
58/**\r
59 Insert a new Mmc Host controller to the pool\r
60**/\r
61VOID\r
62InsertMmcHost (\r
63 IN MMC_HOST_INSTANCE *MmcHostInstance\r
64 )\r
65{\r
e8e95df4 66 InsertTailList (&mMmcHostPool, &(MmcHostInstance->Link));\r
1bfda055 67}\r
68\r
69/*\r
70 Remove a new Mmc Host controller to the pool\r
71*/\r
72VOID\r
73RemoveMmcHost (\r
74 IN MMC_HOST_INSTANCE *MmcHostInstance\r
75 )\r
76{\r
e8e95df4 77 RemoveEntryList (&(MmcHostInstance->Link));\r
1bfda055 78}\r
79\r
e8e95df4 80MMC_HOST_INSTANCE* CreateMmcHostInstance (\r
1bfda055 81 IN EFI_MMC_HOST_PROTOCOL* MmcHost\r
82 )\r
83{\r
e8e95df4 84 EFI_STATUS Status;\r
85 MMC_HOST_INSTANCE* MmcHostInstance;\r
86 EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;\r
87 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
1bfda055 88\r
e8e95df4 89 MmcHostInstance = AllocateZeroPool (sizeof (MMC_HOST_INSTANCE));\r
90 if (MmcHostInstance == NULL) {\r
91 return NULL;\r
92 }\r
1bfda055 93\r
e8e95df4 94 MmcHostInstance->Signature = MMC_HOST_INSTANCE_SIGNATURE;\r
1bfda055 95\r
e8e95df4 96 MmcHostInstance->State = MmcHwInitializationState;\r
1bfda055 97\r
e8e95df4 98 MmcHostInstance->BlockIo.Media = AllocateCopyPool (sizeof(EFI_BLOCK_IO_MEDIA), &mMmcMediaTemplate);\r
99 if (MmcHostInstance->BlockIo.Media == NULL) {\r
100 goto FREE_INSTANCE;\r
101 }\r
1bfda055 102\r
e8e95df4 103 MmcHostInstance->BlockIo.Revision = EFI_BLOCK_IO_INTERFACE_REVISION;\r
104 MmcHostInstance->BlockIo.Reset = MmcReset;\r
105 MmcHostInstance->BlockIo.ReadBlocks = MmcReadBlocks;\r
106 MmcHostInstance->BlockIo.WriteBlocks = MmcWriteBlocks;\r
107 MmcHostInstance->BlockIo.FlushBlocks = MmcFlushBlocks;\r
1bfda055 108\r
e8e95df4 109 MmcHostInstance->MmcHost = MmcHost;\r
110\r
111 // Create DevicePath for the new MMC Host\r
112 Status = MmcHost->BuildDevicePath(&NewDevicePathNode);\r
113 if (EFI_ERROR (Status)) {\r
114 goto FREE_MEDIA;\r
115 }\r
1bfda055 116\r
e8e95df4 117 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH);\r
118 if (DevicePath == NULL) {\r
119 goto FREE_MEDIA;\r
120 }\r
121\r
122 SetDevicePathEndNode (DevicePath);\r
123 MmcHostInstance->DevicePath = AppendDevicePathNode (DevicePath, NewDevicePathNode);\r
124\r
125 // Publish BlockIO protocol interface\r
126 Status = gBS->InstallMultipleProtocolInterfaces (\r
127 &MmcHostInstance->MmcHandle,\r
128 &gEfiBlockIoProtocolGuid,&(MmcHostInstance->BlockIo),\r
129 &gEfiDevicePathProtocolGuid,MmcHostInstance->DevicePath,\r
130 NULL\r
131 );\r
132 if (EFI_ERROR(Status)) {\r
133 goto FREE_DEVICE_PATH;\r
134 }\r
135\r
136 return MmcHostInstance;\r
1bfda055 137\r
138FREE_DEVICE_PATH:\r
e8e95df4 139 FreePool(DevicePath);\r
1bfda055 140\r
141FREE_MEDIA:\r
e8e95df4 142 FreePool(MmcHostInstance->BlockIo.Media);\r
1bfda055 143\r
144FREE_INSTANCE:\r
e8e95df4 145 FreePool(MmcHostInstance);\r
1bfda055 146\r
e8e95df4 147 return NULL;\r
1bfda055 148}\r
149\r
e8e95df4 150EFI_STATUS DestroyMmcHostInstance (\r
1bfda055 151 IN MMC_HOST_INSTANCE* MmcHostInstance\r
152 )\r
153{\r
e8e95df4 154 EFI_STATUS Status;\r
1bfda055 155\r
e8e95df4 156 // Uninstall Protocol Interfaces\r
157 Status = gBS->UninstallMultipleProtocolInterfaces (\r
6102636a 158 MmcHostInstance->MmcHandle,\r
e8e95df4 159 &gEfiBlockIoProtocolGuid,&(MmcHostInstance->BlockIo),\r
6102636a 160 &gEfiDevicePathProtocolGuid,MmcHostInstance->DevicePath,\r
e8e95df4 161 NULL\r
162 );\r
163 ASSERT_EFI_ERROR (Status);\r
1bfda055 164\r
e8e95df4 165 // Free Memory allocated for the instance\r
166 if (MmcHostInstance->BlockIo.Media) {\r
167 FreePool(MmcHostInstance->BlockIo.Media);\r
168 }\r
169 FreePool (MmcHostInstance);\r
170\r
171 return Status;\r
1bfda055 172}\r
173\r
174/**\r
175 This function checks if the controller implement the Mmc Host and the Device Path Protocols\r
176**/\r
177EFI_STATUS\r
178EFIAPI\r
179MmcDriverBindingSupported (\r
180 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
181 IN EFI_HANDLE Controller,\r
182 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
183 )\r
184{\r
e8e95df4 185 EFI_STATUS Status;\r
186 //EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
187 EFI_MMC_HOST_PROTOCOL *MmcHost;\r
188 EFI_DEV_PATH_PTR Node;\r
189\r
190 //\r
191 // Check RemainingDevicePath validation\r
192 //\r
193 if (RemainingDevicePath != NULL) {\r
1bfda055 194 //\r
e8e95df4 195 // Check if RemainingDevicePath is the End of Device Path Node,\r
196 // if yes, go on checking other conditions\r
1bfda055 197 //\r
e8e95df4 198 if (!IsDevicePathEnd (RemainingDevicePath)) {\r
199 //\r
200 // If RemainingDevicePath isn't the End of Device Path Node,\r
201 // check its validation\r
202 //\r
203 Node.DevPath = RemainingDevicePath;\r
204 if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||\r
205 Node.DevPath->SubType != HW_VENDOR_DP ||\r
206 DevicePathNodeLength(Node.DevPath) != sizeof(VENDOR_DEVICE_PATH)) {\r
207 return EFI_UNSUPPORTED;\r
208 }\r
1bfda055 209 }\r
e8e95df4 210 }\r
211\r
212 //\r
213 // Check if Mmc Host protocol is installed by platform\r
214 //\r
215 Status = gBS->OpenProtocol (\r
216 Controller,\r
217 &gEfiMmcHostProtocolGuid,\r
218 (VOID **) &MmcHost,\r
219 This->DriverBindingHandle,\r
220 Controller,\r
221 EFI_OPEN_PROTOCOL_BY_DRIVER\r
222 );\r
223 if (Status == EFI_ALREADY_STARTED) {\r
1bfda055 224 return EFI_SUCCESS;\r
e8e95df4 225 }\r
226 if (EFI_ERROR (Status)) {\r
227 return Status;\r
228 }\r
229\r
230 //\r
231 // Close the Mmc Host used to perform the supported test\r
232 //\r
233 gBS->CloseProtocol (\r
234 Controller,\r
235 &gEfiMmcHostProtocolGuid,\r
236 This->DriverBindingHandle,\r
237 Controller\r
238 );\r
239\r
240 return EFI_SUCCESS;\r
1bfda055 241}\r
242\r
243/**\r
244 \r
245**/\r
246EFI_STATUS\r
247EFIAPI\r
248MmcDriverBindingStart (\r
249 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
250 IN EFI_HANDLE Controller,\r
251 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
252 )\r
253{\r
e8e95df4 254 EFI_STATUS Status;\r
255 MMC_HOST_INSTANCE *MmcHostInstance;\r
256 EFI_MMC_HOST_PROTOCOL *MmcHost;\r
257\r
258 //\r
259 // Check RemainingDevicePath validation\r
260 //\r
261 if (RemainingDevicePath != NULL) {\r
1bfda055 262 //\r
e8e95df4 263 // Check if RemainingDevicePath is the End of Device Path Node,\r
264 // if yes, return EFI_SUCCESS\r
1bfda055 265 //\r
e8e95df4 266 if (IsDevicePathEnd (RemainingDevicePath)) {\r
267 return EFI_SUCCESS;\r
1bfda055 268 }\r
e8e95df4 269 }\r
270\r
271 //\r
272 // Get the Mmc Host protocol\r
273 //\r
274 Status = gBS->OpenProtocol (\r
275 Controller,\r
276 &gEfiMmcHostProtocolGuid,\r
277 (VOID **) &MmcHost,\r
278 This->DriverBindingHandle,\r
279 Controller,\r
280 EFI_OPEN_PROTOCOL_BY_DRIVER\r
281 );\r
282 if (EFI_ERROR (Status)) {\r
283 if (Status == EFI_ALREADY_STARTED) {\r
284 return EFI_SUCCESS;\r
1bfda055 285 }\r
e8e95df4 286 return Status;\r
287 }\r
1bfda055 288\r
e8e95df4 289 MmcHostInstance = CreateMmcHostInstance(MmcHost);\r
290 if (MmcHostInstance != NULL) {\r
291 // Add the handle to the pool\r
292 InsertMmcHost (MmcHostInstance);\r
293 }\r
1bfda055 294\r
e8e95df4 295 return EFI_SUCCESS;\r
1bfda055 296}\r
297\r
298/**\r
299 \r
300**/\r
301EFI_STATUS\r
302EFIAPI\r
303MmcDriverBindingStop (\r
304 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
305 IN EFI_HANDLE Controller,\r
306 IN UINTN NumberOfChildren,\r
307 IN EFI_HANDLE *ChildHandleBuffer\r
308 )\r
309{\r
e8e95df4 310 EFI_STATUS Status = EFI_SUCCESS;\r
311 LIST_ENTRY *CurrentLink;\r
312 MMC_HOST_INSTANCE *MmcHostInstance;\r
1bfda055 313\r
e8e95df4 314 MMC_TRACE("MmcDriverBindingStop()");\r
315\r
316 // For each MMC instance\r
317 CurrentLink = mMmcHostPool.ForwardLink;\r
318 while (CurrentLink != NULL && CurrentLink != &mMmcHostPool && (Status == EFI_SUCCESS)) {\r
319 MmcHostInstance = MMC_HOST_INSTANCE_FROM_LINK(CurrentLink);\r
320 ASSERT(MmcHostInstance != NULL);\r
321\r
322 // Close gEfiMmcHostProtocolGuid\r
323 Status = gBS->CloseProtocol (\r
324 Controller,\r
325 &gEfiMmcHostProtocolGuid,(VOID **) &MmcHostInstance->MmcHost,\r
326 This->DriverBindingHandle\r
327 );\r
328\r
329 // Remove MMC Host Instance from the pool\r
330 RemoveMmcHost (MmcHostInstance);\r
331\r
332 // Destroy MmcHostInstance\r
333 DestroyMmcHostInstance (MmcHostInstance);\r
334 }\r
335\r
336 return Status;\r
1bfda055 337}\r
338\r
339EFI_DRIVER_BINDING_PROTOCOL gMmcDriverBinding = {\r
340 MmcDriverBindingSupported,\r
341 MmcDriverBindingStart,\r
342 MmcDriverBindingStop,\r
343 0xa,\r
344 NULL,\r
345 NULL\r
346};\r
347\r
348/**\r
349 \r
350**/\r
351EFI_STATUS\r
352EFIAPI\r
353MmcDxeInitialize (\r
354 IN EFI_HANDLE ImageHandle,\r
355 IN EFI_SYSTEM_TABLE *SystemTable\r
356 )\r
357{\r
e8e95df4 358 EFI_STATUS Status;\r
359\r
360 //\r
361 // Initializes MMC Host pool\r
362 //\r
363 InitializeMmcHostPool ();\r
364\r
365 //\r
366 // Install driver model protocol(s).\r
367 //\r
368 Status = EfiLibInstallDriverBindingComponentName2 (\r
369 ImageHandle,\r
370 SystemTable,\r
371 &gMmcDriverBinding,\r
372 ImageHandle,\r
373 &gMmcComponentName,\r
374 &gMmcComponentName2\r
375 );\r
376 ASSERT_EFI_ERROR (Status);\r
377\r
378 // Install driver diagnostics\r
379 Status = gBS->InstallMultipleProtocolInterfaces (\r
380 &ImageHandle,\r
381 &gEfiDriverDiagnostics2ProtocolGuid,&gMmcDriverDiagnostics2,\r
382 NULL\r
383 );\r
384 ASSERT_EFI_ERROR (Status);\r
385\r
386 return Status;\r
1bfda055 387}\r