]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - EmbeddedPkg/Universal/MmcDxe/Mmc.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / EmbeddedPkg / Universal / MmcDxe / Mmc.c
... / ...
CommitLineData
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-2013, ARM Limited. All rights reserved.\r
5\r
6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
7\r
8**/\r
9\r
10#include <Protocol/DevicePath.h>\r
11\r
12#include <Library/BaseLib.h>\r
13#include <Library/BaseMemoryLib.h>\r
14#include <Library/MemoryAllocationLib.h>\r
15#include <Library/UefiBootServicesTableLib.h>\r
16#include <Library/DevicePathLib.h>\r
17\r
18#include "Mmc.h"\r
19\r
20EFI_BLOCK_IO_MEDIA mMmcMediaTemplate = {\r
21 SIGNATURE_32 ('m', 'm', 'c', 'o'), // MediaId\r
22 TRUE, // RemovableMedia\r
23 FALSE, // MediaPresent\r
24 FALSE, // LogicalPartition\r
25 FALSE, // ReadOnly\r
26 FALSE, // WriteCaching\r
27 512, // BlockSize\r
28 4, // IoAlign\r
29 0, // Pad\r
30 0 // LastBlock\r
31};\r
32\r
33//\r
34// This device structure is serviced as a header.\r
35// Its next field points to the first root bridge device node.\r
36//\r
37LIST_ENTRY mMmcHostPool;\r
38\r
39/**\r
40 Event triggered by the timer to check if any cards have been removed\r
41 or if new ones have been plugged in\r
42**/\r
43\r
44EFI_EVENT gCheckCardsEvent;\r
45\r
46/**\r
47 Initialize the MMC Host Pool to support multiple MMC devices\r
48**/\r
49VOID\r
50InitializeMmcHostPool (\r
51 VOID\r
52 )\r
53{\r
54 InitializeListHead (&mMmcHostPool);\r
55}\r
56\r
57/**\r
58 Insert a new Mmc Host controller to the pool\r
59**/\r
60VOID\r
61InsertMmcHost (\r
62 IN MMC_HOST_INSTANCE *MmcHostInstance\r
63 )\r
64{\r
65 InsertTailList (&mMmcHostPool, &(MmcHostInstance->Link));\r
66}\r
67\r
68/*\r
69 Remove a new Mmc Host controller to the pool\r
70*/\r
71VOID\r
72RemoveMmcHost (\r
73 IN MMC_HOST_INSTANCE *MmcHostInstance\r
74 )\r
75{\r
76 RemoveEntryList (&(MmcHostInstance->Link));\r
77}\r
78\r
79MMC_HOST_INSTANCE *\r
80CreateMmcHostInstance (\r
81 IN EFI_MMC_HOST_PROTOCOL *MmcHost\r
82 )\r
83{\r
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
88\r
89 MmcHostInstance = AllocateZeroPool (sizeof (MMC_HOST_INSTANCE));\r
90 if (MmcHostInstance == NULL) {\r
91 return NULL;\r
92 }\r
93\r
94 MmcHostInstance->Signature = MMC_HOST_INSTANCE_SIGNATURE;\r
95\r
96 MmcHostInstance->State = MmcHwInitializationState;\r
97\r
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
102\r
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
108\r
109 MmcHostInstance->MmcHost = MmcHost;\r
110\r
111 // Create DevicePath for the new MMC Host\r
112 Status = MmcHost->BuildDevicePath (MmcHost, &NewDevicePathNode);\r
113 if (EFI_ERROR (Status)) {\r
114 goto FREE_MEDIA;\r
115 }\r
116\r
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,\r
129 &MmcHostInstance->BlockIo,\r
130 &gEfiDevicePathProtocolGuid,\r
131 MmcHostInstance->DevicePath,\r
132 NULL\r
133 );\r
134 if (EFI_ERROR (Status)) {\r
135 goto FREE_DEVICE_PATH;\r
136 }\r
137\r
138 return MmcHostInstance;\r
139\r
140FREE_DEVICE_PATH:\r
141 FreePool (DevicePath);\r
142\r
143FREE_MEDIA:\r
144 FreePool (MmcHostInstance->BlockIo.Media);\r
145\r
146FREE_INSTANCE:\r
147 FreePool (MmcHostInstance);\r
148\r
149 return NULL;\r
150}\r
151\r
152EFI_STATUS\r
153DestroyMmcHostInstance (\r
154 IN MMC_HOST_INSTANCE *MmcHostInstance\r
155 )\r
156{\r
157 EFI_STATUS Status;\r
158\r
159 // Uninstall Protocol Interfaces\r
160 Status = gBS->UninstallMultipleProtocolInterfaces (\r
161 MmcHostInstance->MmcHandle,\r
162 &gEfiBlockIoProtocolGuid,\r
163 &(MmcHostInstance->BlockIo),\r
164 &gEfiDevicePathProtocolGuid,\r
165 MmcHostInstance->DevicePath,\r
166 NULL\r
167 );\r
168 ASSERT_EFI_ERROR (Status);\r
169\r
170 // Free Memory allocated for the instance\r
171 if (MmcHostInstance->BlockIo.Media) {\r
172 FreePool (MmcHostInstance->BlockIo.Media);\r
173 }\r
174\r
175 if (MmcHostInstance->CardInfo.ECSDData) {\r
176 FreePages (MmcHostInstance->CardInfo.ECSDData, EFI_SIZE_TO_PAGES (sizeof (ECSD)));\r
177 }\r
178\r
179 FreePool (MmcHostInstance);\r
180\r
181 return Status;\r
182}\r
183\r
184/**\r
185 This function checks if the controller implement the Mmc Host and the Device Path Protocols\r
186**/\r
187EFI_STATUS\r
188EFIAPI\r
189MmcDriverBindingSupported (\r
190 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
191 IN EFI_HANDLE Controller,\r
192 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
193 )\r
194{\r
195 EFI_STATUS Status;\r
196 // EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
197 EFI_MMC_HOST_PROTOCOL *MmcHost;\r
198 EFI_DEV_PATH_PTR Node;\r
199\r
200 //\r
201 // Check RemainingDevicePath validation\r
202 //\r
203 if (RemainingDevicePath != NULL) {\r
204 //\r
205 // Check if RemainingDevicePath is the End of Device Path Node,\r
206 // if yes, go on checking other conditions\r
207 //\r
208 if (!IsDevicePathEnd (RemainingDevicePath)) {\r
209 //\r
210 // If RemainingDevicePath isn't the End of Device Path Node,\r
211 // check its validation\r
212 //\r
213 Node.DevPath = RemainingDevicePath;\r
214 if ((Node.DevPath->Type != HARDWARE_DEVICE_PATH) ||\r
215 (Node.DevPath->SubType != HW_VENDOR_DP) ||\r
216 (DevicePathNodeLength (Node.DevPath) != sizeof (VENDOR_DEVICE_PATH)))\r
217 {\r
218 return EFI_UNSUPPORTED;\r
219 }\r
220 }\r
221 }\r
222\r
223 //\r
224 // Check if Mmc Host protocol is installed by platform\r
225 //\r
226 Status = gBS->OpenProtocol (\r
227 Controller,\r
228 &gEmbeddedMmcHostProtocolGuid,\r
229 (VOID **)&MmcHost,\r
230 This->DriverBindingHandle,\r
231 Controller,\r
232 EFI_OPEN_PROTOCOL_BY_DRIVER\r
233 );\r
234 if (Status == EFI_ALREADY_STARTED) {\r
235 return EFI_SUCCESS;\r
236 }\r
237\r
238 if (EFI_ERROR (Status)) {\r
239 return Status;\r
240 }\r
241\r
242 //\r
243 // Close the Mmc Host used to perform the supported test\r
244 //\r
245 gBS->CloseProtocol (\r
246 Controller,\r
247 &gEmbeddedMmcHostProtocolGuid,\r
248 This->DriverBindingHandle,\r
249 Controller\r
250 );\r
251\r
252 return EFI_SUCCESS;\r
253}\r
254\r
255/**\r
256\r
257**/\r
258EFI_STATUS\r
259EFIAPI\r
260MmcDriverBindingStart (\r
261 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
262 IN EFI_HANDLE Controller,\r
263 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
264 )\r
265{\r
266 EFI_STATUS Status;\r
267 MMC_HOST_INSTANCE *MmcHostInstance;\r
268 EFI_MMC_HOST_PROTOCOL *MmcHost;\r
269\r
270 //\r
271 // Check RemainingDevicePath validation\r
272 //\r
273 if (RemainingDevicePath != NULL) {\r
274 //\r
275 // Check if RemainingDevicePath is the End of Device Path Node,\r
276 // if yes, return EFI_SUCCESS\r
277 //\r
278 if (IsDevicePathEnd (RemainingDevicePath)) {\r
279 return EFI_SUCCESS;\r
280 }\r
281 }\r
282\r
283 //\r
284 // Get the Mmc Host protocol\r
285 //\r
286 Status = gBS->OpenProtocol (\r
287 Controller,\r
288 &gEmbeddedMmcHostProtocolGuid,\r
289 (VOID **)&MmcHost,\r
290 This->DriverBindingHandle,\r
291 Controller,\r
292 EFI_OPEN_PROTOCOL_BY_DRIVER\r
293 );\r
294 if (EFI_ERROR (Status)) {\r
295 if (Status == EFI_ALREADY_STARTED) {\r
296 return EFI_SUCCESS;\r
297 }\r
298\r
299 return Status;\r
300 }\r
301\r
302 MmcHostInstance = CreateMmcHostInstance (MmcHost);\r
303 if (MmcHostInstance != NULL) {\r
304 // Add the handle to the pool\r
305 InsertMmcHost (MmcHostInstance);\r
306\r
307 MmcHostInstance->Initialized = FALSE;\r
308\r
309 // Detect card presence now\r
310 CheckCardsCallback (NULL, NULL);\r
311 }\r
312\r
313 return EFI_SUCCESS;\r
314}\r
315\r
316/**\r
317\r
318**/\r
319EFI_STATUS\r
320EFIAPI\r
321MmcDriverBindingStop (\r
322 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
323 IN EFI_HANDLE Controller,\r
324 IN UINTN NumberOfChildren,\r
325 IN EFI_HANDLE *ChildHandleBuffer\r
326 )\r
327{\r
328 EFI_STATUS Status = EFI_SUCCESS;\r
329 LIST_ENTRY *CurrentLink;\r
330 MMC_HOST_INSTANCE *MmcHostInstance;\r
331\r
332 MMC_TRACE ("MmcDriverBindingStop()");\r
333\r
334 // For each MMC instance\r
335 CurrentLink = mMmcHostPool.ForwardLink;\r
336 while (CurrentLink != NULL && CurrentLink != &mMmcHostPool && (Status == EFI_SUCCESS)) {\r
337 MmcHostInstance = MMC_HOST_INSTANCE_FROM_LINK (CurrentLink);\r
338 ASSERT (MmcHostInstance != NULL);\r
339\r
340 // Close gEmbeddedMmcHostProtocolGuid\r
341 Status = gBS->CloseProtocol (\r
342 Controller,\r
343 &gEmbeddedMmcHostProtocolGuid,\r
344 This->DriverBindingHandle,\r
345 Controller\r
346 );\r
347\r
348 // Remove MMC Host Instance from the pool\r
349 RemoveMmcHost (MmcHostInstance);\r
350\r
351 // Destroy MmcHostInstance\r
352 DestroyMmcHostInstance (MmcHostInstance);\r
353 }\r
354\r
355 return Status;\r
356}\r
357\r
358VOID\r
359EFIAPI\r
360CheckCardsCallback (\r
361 IN EFI_EVENT Event,\r
362 IN VOID *Context\r
363 )\r
364{\r
365 LIST_ENTRY *CurrentLink;\r
366 MMC_HOST_INSTANCE *MmcHostInstance;\r
367 EFI_STATUS Status;\r
368\r
369 CurrentLink = mMmcHostPool.ForwardLink;\r
370 while (CurrentLink != NULL && CurrentLink != &mMmcHostPool) {\r
371 MmcHostInstance = MMC_HOST_INSTANCE_FROM_LINK (CurrentLink);\r
372 ASSERT (MmcHostInstance != NULL);\r
373\r
374 if (MmcHostInstance->MmcHost->IsCardPresent (MmcHostInstance->MmcHost) == !MmcHostInstance->Initialized) {\r
375 MmcHostInstance->State = MmcHwInitializationState;\r
376 MmcHostInstance->BlockIo.Media->MediaPresent = !MmcHostInstance->Initialized;\r
377 MmcHostInstance->Initialized = !MmcHostInstance->Initialized;\r
378\r
379 if (MmcHostInstance->BlockIo.Media->MediaPresent) {\r
380 InitializeMmcDevice (MmcHostInstance);\r
381 }\r
382\r
383 Status = gBS->ReinstallProtocolInterface (\r
384 (MmcHostInstance->MmcHandle),\r
385 &gEfiBlockIoProtocolGuid,\r
386 &(MmcHostInstance->BlockIo),\r
387 &(MmcHostInstance->BlockIo)\r
388 );\r
389\r
390 if (EFI_ERROR (Status)) {\r
391 Print (L"MMC Card: Error reinstalling BlockIo interface\n");\r
392 }\r
393 }\r
394\r
395 CurrentLink = CurrentLink->ForwardLink;\r
396 }\r
397}\r
398\r
399EFI_DRIVER_BINDING_PROTOCOL gMmcDriverBinding = {\r
400 MmcDriverBindingSupported,\r
401 MmcDriverBindingStart,\r
402 MmcDriverBindingStop,\r
403 0xa,\r
404 NULL,\r
405 NULL\r
406};\r
407\r
408/**\r
409\r
410**/\r
411EFI_STATUS\r
412EFIAPI\r
413MmcDxeInitialize (\r
414 IN EFI_HANDLE ImageHandle,\r
415 IN EFI_SYSTEM_TABLE *SystemTable\r
416 )\r
417{\r
418 EFI_STATUS Status;\r
419\r
420 //\r
421 // Initializes MMC Host pool\r
422 //\r
423 InitializeMmcHostPool ();\r
424\r
425 //\r
426 // Install driver model protocol(s).\r
427 //\r
428 Status = EfiLibInstallDriverBindingComponentName2 (\r
429 ImageHandle,\r
430 SystemTable,\r
431 &gMmcDriverBinding,\r
432 ImageHandle,\r
433 &gMmcComponentName,\r
434 &gMmcComponentName2\r
435 );\r
436 ASSERT_EFI_ERROR (Status);\r
437\r
438 // Install driver diagnostics\r
439 Status = gBS->InstallMultipleProtocolInterfaces (\r
440 &ImageHandle,\r
441 &gEfiDriverDiagnostics2ProtocolGuid,\r
442 &gMmcDriverDiagnostics2,\r
443 NULL\r
444 );\r
445 ASSERT_EFI_ERROR (Status);\r
446\r
447 // Use a timer to detect if a card has been plugged in or removed\r
448 Status = gBS->CreateEvent (\r
449 EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
450 TPL_CALLBACK,\r
451 CheckCardsCallback,\r
452 NULL,\r
453 &gCheckCardsEvent\r
454 );\r
455 ASSERT_EFI_ERROR (Status);\r
456\r
457 Status = gBS->SetTimer (\r
458 gCheckCardsEvent,\r
459 TimerPeriodic,\r
460 (UINT64)(10*1000*200)\r
461 ); // 200 ms\r
462 ASSERT_EFI_ERROR (Status);\r
463\r
464 return Status;\r
465}\r