]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Sd/SdDxe/SdDxe.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Bus / Sd / SdDxe / SdDxe.c
CommitLineData
48555339
FT
1/** @file\r
2 The SdDxe driver is used to manage the SD memory card device.\r
3\r
4 It produces BlockIo and BlockIo2 protocols to allow upper layer\r
5 access the SD memory card device.\r
6\r
e25a7678 7 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
9d510e61 8 SPDX-License-Identifier: BSD-2-Clause-Patent\r
48555339
FT
9\r
10**/\r
11\r
12#include "SdDxe.h"\r
13\r
14//\r
15// SdDxe Driver Binding Protocol Instance\r
16//\r
1436aea4 17EFI_DRIVER_BINDING_PROTOCOL gSdDxeDriverBinding = {\r
48555339
FT
18 SdDxeDriverBindingSupported,\r
19 SdDxeDriverBindingStart,\r
20 SdDxeDriverBindingStop,\r
21 0x10,\r
22 NULL,\r
23 NULL\r
24};\r
25\r
26//\r
27// Template for SD_DEVICE data structure.\r
28//\r
1436aea4 29SD_DEVICE mSdDeviceTemplate = {\r
48555339
FT
30 SD_DEVICE_SIGNATURE, // Signature\r
31 NULL, // Handle\r
32 NULL, // DevicePath\r
33 0xFF, // Slot\r
34 FALSE, // SectorAddressing\r
35 { // BlockIo\r
36 EFI_BLOCK_IO_PROTOCOL_REVISION,\r
37 NULL,\r
38 SdReset,\r
39 SdReadBlocks,\r
40 SdWriteBlocks,\r
41 SdFlushBlocks\r
42 },\r
43 { // BlockIo2\r
44 NULL,\r
45 SdResetEx,\r
46 SdReadBlocksEx,\r
47 SdWriteBlocksEx,\r
48 SdFlushBlocksEx\r
49 },\r
50 { // BlockMedia\r
51 0, // MediaId\r
52 FALSE, // RemovableMedia\r
53 TRUE, // MediaPresent\r
54 FALSE, // LogicPartition\r
55 FALSE, // ReadOnly\r
56 FALSE, // WritingCache\r
57 0x200, // BlockSize\r
58 0, // IoAlign\r
59 0 // LastBlock\r
60 },\r
275d5136
FT
61 { // EraseBlock\r
62 EFI_ERASE_BLOCK_PROTOCOL_REVISION,\r
63 1,\r
64 SdEraseBlocks\r
65 },\r
af6a6bf4
HW
66 { // DiskInfo\r
67 EFI_DISK_INFO_SD_MMC_INTERFACE_GUID,\r
68 SdDiskInfoInquiry,\r
69 SdDiskInfoIdentify,\r
70 SdDiskInfoSenseData,\r
71 SdDiskInfoWhichIde\r
72 },\r
48555339
FT
73 { // Queue\r
74 NULL,\r
75 NULL\r
76 },\r
77 { // Csd\r
78 0,\r
79 },\r
80 { // Cid\r
81 0,\r
82 },\r
83 NULL, // ControllerNameTable\r
84 { // ModelName\r
85 0,\r
86 },\r
87 NULL // Private\r
88};\r
89\r
90/**\r
91 Decode and print SD CSD Register content.\r
92\r
93 @param[in] Csd Pointer to SD_CSD data structure.\r
94\r
95 @retval EFI_SUCCESS The function completed successfully\r
96**/\r
97EFI_STATUS\r
98DumpCsd (\r
99 IN SD_CSD *Csd\r
100 )\r
101{\r
1436aea4
MK
102 SD_CSD2 *Csd2;\r
103\r
104 DEBUG ((DEBUG_INFO, "== Dump Sd Csd Register==\n"));\r
105 DEBUG ((DEBUG_INFO, " CSD structure 0x%x\n", Csd->CsdStructure));\r
106 DEBUG ((DEBUG_INFO, " Data read access-time 1 0x%x\n", Csd->Taac));\r
107 DEBUG ((DEBUG_INFO, " Data read access-time 2 0x%x\n", Csd->Nsac));\r
108 DEBUG ((DEBUG_INFO, " Max. bus clock frequency 0x%x\n", Csd->TranSpeed));\r
109 DEBUG ((DEBUG_INFO, " Device command classes 0x%x\n", Csd->Ccc));\r
110 DEBUG ((DEBUG_INFO, " Max. read data block length 0x%x\n", Csd->ReadBlLen));\r
111 DEBUG ((DEBUG_INFO, " Partial blocks for read allowed 0x%x\n", Csd->ReadBlPartial));\r
112 DEBUG ((DEBUG_INFO, " Write block misalignment 0x%x\n", Csd->WriteBlkMisalign));\r
113 DEBUG ((DEBUG_INFO, " Read block misalignment 0x%x\n", Csd->ReadBlkMisalign));\r
114 DEBUG ((DEBUG_INFO, " DSR implemented 0x%x\n", Csd->DsrImp));\r
48555339 115 if (Csd->CsdStructure == 0) {\r
1436aea4
MK
116 DEBUG ((DEBUG_INFO, " Device size 0x%x\n", Csd->CSizeLow | (Csd->CSizeHigh << 2)));\r
117 DEBUG ((DEBUG_INFO, " Max. read current @ VDD min 0x%x\n", Csd->VddRCurrMin));\r
118 DEBUG ((DEBUG_INFO, " Max. read current @ VDD max 0x%x\n", Csd->VddRCurrMax));\r
119 DEBUG ((DEBUG_INFO, " Max. write current @ VDD min 0x%x\n", Csd->VddWCurrMin));\r
120 DEBUG ((DEBUG_INFO, " Max. write current @ VDD max 0x%x\n", Csd->VddWCurrMax));\r
48555339 121 } else {\r
1436aea4
MK
122 Csd2 = (SD_CSD2 *)(VOID *)Csd;\r
123 DEBUG ((DEBUG_INFO, " Device size 0x%x\n", Csd2->CSizeLow | (Csd->CSizeHigh << 16)));\r
48555339 124 }\r
1436aea4
MK
125\r
126 DEBUG ((DEBUG_INFO, " Erase sector size 0x%x\n", Csd->SectorSize));\r
127 DEBUG ((DEBUG_INFO, " Erase single block enable 0x%x\n", Csd->EraseBlkEn));\r
128 DEBUG ((DEBUG_INFO, " Write protect group size 0x%x\n", Csd->WpGrpSize));\r
129 DEBUG ((DEBUG_INFO, " Write protect group enable 0x%x\n", Csd->WpGrpEnable));\r
130 DEBUG ((DEBUG_INFO, " Write speed factor 0x%x\n", Csd->R2WFactor));\r
131 DEBUG ((DEBUG_INFO, " Max. write data block length 0x%x\n", Csd->WriteBlLen));\r
132 DEBUG ((DEBUG_INFO, " Partial blocks for write allowed 0x%x\n", Csd->WriteBlPartial));\r
133 DEBUG ((DEBUG_INFO, " File format group 0x%x\n", Csd->FileFormatGrp));\r
134 DEBUG ((DEBUG_INFO, " Copy flag (OTP) 0x%x\n", Csd->Copy));\r
135 DEBUG ((DEBUG_INFO, " Permanent write protection 0x%x\n", Csd->PermWriteProtect));\r
136 DEBUG ((DEBUG_INFO, " Temporary write protection 0x%x\n", Csd->TmpWriteProtect));\r
137 DEBUG ((DEBUG_INFO, " File format 0x%x\n", Csd->FileFormat));\r
48555339
FT
138\r
139 return EFI_SUCCESS;\r
140}\r
141\r
142/**\r
143 Get SD device model name.\r
144\r
145 @param[in, out] Device The pointer to the SD_DEVICE data structure.\r
146 @param[in] Cid Pointer to SD_CID data structure.\r
147\r
148 @retval EFI_SUCCESS The function completed successfully\r
149\r
150**/\r
151EFI_STATUS\r
152GetSdModelName (\r
1436aea4
MK
153 IN OUT SD_DEVICE *Device,\r
154 IN SD_CID *Cid\r
48555339
FT
155 )\r
156{\r
157 CHAR8 String[SD_MODEL_NAME_MAX_LEN];\r
158\r
159 ZeroMem (String, sizeof (String));\r
160 CopyMem (String, Cid->OemId, sizeof (Cid->OemId));\r
161 String[sizeof (Cid->OemId)] = ' ';\r
162 CopyMem (String + sizeof (Cid->OemId) + 1, Cid->ProductName, sizeof (Cid->ProductName));\r
163 String[sizeof (Cid->OemId) + sizeof (Cid->ProductName)] = ' ';\r
164 CopyMem (String + sizeof (Cid->OemId) + sizeof (Cid->ProductName) + 1, Cid->ProductSerialNumber, sizeof (Cid->ProductSerialNumber));\r
165\r
b68ccac1 166 AsciiStrToUnicodeStrS (String, Device->ModelName, sizeof (Device->ModelName) / sizeof (Device->ModelName[0]));\r
48555339
FT
167\r
168 return EFI_SUCCESS;\r
169}\r
170\r
171/**\r
172 Discover user area partition in the SD device.\r
173\r
174 @param[in] Device The pointer to the SD_DEVICE data structure.\r
175\r
176 @retval EFI_SUCCESS The user area partition in the SD device is successfully identified.\r
177 @return Others Some error occurs when identifying the user area.\r
178\r
179**/\r
180EFI_STATUS\r
181DiscoverUserArea (\r
1436aea4 182 IN SD_DEVICE *Device\r
48555339
FT
183 )\r
184{\r
1436aea4
MK
185 EFI_STATUS Status;\r
186 SD_CSD *Csd;\r
187 SD_CSD2 *Csd2;\r
188 SD_CID *Cid;\r
189 UINT64 Capacity;\r
190 UINT32 DevStatus;\r
191 UINT16 Rca;\r
192 UINT32 CSize;\r
193 UINT32 CSizeMul;\r
194 UINT32 ReadBlLen;\r
48555339
FT
195\r
196 //\r
197 // Deselect the device to force it enter stby mode.\r
198 // Note here we don't judge return status as some SD devices return\r
199 // error but the state has been stby.\r
200 //\r
201 SdSelect (Device, 0);\r
202\r
203 Status = SdSetRca (Device, &Rca);\r
204 if (EFI_ERROR (Status)) {\r
87000d77 205 DEBUG ((DEBUG_ERROR, "DiscoverUserArea(): Assign new Rca = 0x%x fails with %r\n", Rca, Status));\r
48555339
FT
206 return Status;\r
207 }\r
208\r
209 Csd = &Device->Csd;\r
210 Status = SdGetCsd (Device, Rca, Csd);\r
211 if (EFI_ERROR (Status)) {\r
212 return Status;\r
213 }\r
1436aea4 214\r
48555339
FT
215 DumpCsd (Csd);\r
216\r
217 Cid = &Device->Cid;\r
218 Status = SdGetCid (Device, Rca, Cid);\r
219 if (EFI_ERROR (Status)) {\r
220 return Status;\r
221 }\r
1436aea4 222\r
48555339
FT
223 GetSdModelName (Device, Cid);\r
224\r
225 Status = SdSelect (Device, Rca);\r
226 if (EFI_ERROR (Status)) {\r
87000d77 227 DEBUG ((DEBUG_ERROR, "DiscoverUserArea(): Reselect the device 0x%x fails with %r\n", Rca, Status));\r
48555339
FT
228 return Status;\r
229 }\r
230\r
231 Status = SdSendStatus (Device, Rca, &DevStatus);\r
232 if (EFI_ERROR (Status)) {\r
233 return Status;\r
234 }\r
235\r
236 if (Csd->CsdStructure == 0) {\r
237 Device->SectorAddressing = FALSE;\r
1436aea4
MK
238 CSize = (Csd->CSizeHigh << 2 | Csd->CSizeLow) + 1;\r
239 CSizeMul = (1 << (Csd->CSizeMul + 2));\r
240 ReadBlLen = (1 << (Csd->ReadBlLen));\r
241 Capacity = MultU64x32 (MultU64x32 ((UINT64)CSize, CSizeMul), ReadBlLen);\r
48555339
FT
242 } else {\r
243 Device->SectorAddressing = TRUE;\r
1436aea4
MK
244 Csd2 = (SD_CSD2 *)(VOID *)Csd;\r
245 CSize = (Csd2->CSizeHigh << 16 | Csd2->CSizeLow) + 1;\r
246 Capacity = MultU64x32 ((UINT64)CSize, SIZE_512KB);\r
48555339
FT
247 }\r
248\r
249 Device->BlockIo.Media = &Device->BlockMedia;\r
250 Device->BlockIo2.Media = &Device->BlockMedia;\r
251 Device->BlockMedia.IoAlign = Device->Private->PassThru->IoAlign;\r
252 Device->BlockMedia.BlockSize = 0x200;\r
253 Device->BlockMedia.LastBlock = 0x00;\r
254 Device->BlockMedia.RemovableMedia = TRUE;\r
255 Device->BlockMedia.MediaPresent = TRUE;\r
256 Device->BlockMedia.LogicalPartition = FALSE;\r
257 Device->BlockMedia.LastBlock = DivU64x32 (Capacity, Device->BlockMedia.BlockSize) - 1;\r
258\r
275d5136
FT
259 if (Csd->EraseBlkEn) {\r
260 Device->EraseBlock.EraseLengthGranularity = 1;\r
261 } else {\r
262 Device->EraseBlock.EraseLengthGranularity = (Csd->SectorSize + 1) * (1 << (Csd->WriteBlLen - 9));\r
263 }\r
264\r
48555339
FT
265 return Status;\r
266}\r
267\r
268/**\r
269 Scan SD Bus to discover the device.\r
270\r
271 @param[in] Private The SD driver private data structure.\r
272 @param[in] Slot The slot number to check device present.\r
273\r
274 @retval EFI_SUCCESS Successfully to discover the device and attach\r
275 SdMmcIoProtocol to it.\r
276 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack\r
277 of resources.\r
278 @retval EFI_ALREADY_STARTED The device was discovered before.\r
279 @retval Others Fail to discover the device.\r
280\r
281**/\r
282EFI_STATUS\r
283EFIAPI\r
284DiscoverSdDevice (\r
1436aea4
MK
285 IN SD_DRIVER_PRIVATE_DATA *Private,\r
286 IN UINT8 Slot\r
48555339
FT
287 )\r
288{\r
1436aea4
MK
289 EFI_STATUS Status;\r
290 SD_DEVICE *Device;\r
291 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
292 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
293 EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;\r
294 EFI_HANDLE DeviceHandle;\r
295 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;\r
48555339
FT
296\r
297 Device = NULL;\r
298 DevicePath = NULL;\r
299 NewDevicePath = NULL;\r
300 RemainingDevicePath = NULL;\r
1436aea4 301 PassThru = Private->PassThru;\r
48555339
FT
302\r
303 //\r
304 // Build Device Path\r
305 //\r
306 Status = PassThru->BuildDevicePath (\r
307 PassThru,\r
308 Slot,\r
309 &DevicePath\r
310 );\r
1436aea4 311 if (EFI_ERROR (Status)) {\r
48555339
FT
312 return Status;\r
313 }\r
314\r
315 if (DevicePath->SubType != MSG_SD_DP) {\r
316 Status = EFI_UNSUPPORTED;\r
317 goto Error;\r
318 }\r
319\r
320 NewDevicePath = AppendDevicePathNode (\r
321 Private->ParentDevicePath,\r
322 DevicePath\r
323 );\r
324\r
325 if (NewDevicePath == NULL) {\r
326 Status = EFI_OUT_OF_RESOURCES;\r
327 goto Error;\r
328 }\r
329\r
1436aea4 330 DeviceHandle = NULL;\r
48555339 331 RemainingDevicePath = NewDevicePath;\r
1436aea4
MK
332 Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &DeviceHandle);\r
333 if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd (RemainingDevicePath)) {\r
48555339
FT
334 //\r
335 // The device has been started, directly return to fast boot.\r
336 //\r
337 Status = EFI_ALREADY_STARTED;\r
338 goto Error;\r
339 }\r
340\r
341 //\r
342 // Allocate buffer to store SD_DEVICE private data.\r
343 //\r
344 Device = AllocateCopyPool (sizeof (SD_DEVICE), &mSdDeviceTemplate);\r
345 if (Device == NULL) {\r
346 Status = EFI_OUT_OF_RESOURCES;\r
347 goto Error;\r
348 }\r
349\r
350 Device->DevicePath = NewDevicePath;\r
351 Device->Slot = Slot;\r
352 Device->Private = Private;\r
353 InitializeListHead (&Device->Queue);\r
354\r
355 //\r
356 // Expose user area in the Sd memory card to upper layer.\r
357 //\r
358 Status = DiscoverUserArea (Device);\r
1436aea4 359 if (EFI_ERROR (Status)) {\r
48555339
FT
360 goto Error;\r
361 }\r
362\r
363 Device->ControllerNameTable = NULL;\r
364 AddUnicodeString2 (\r
365 "eng",\r
366 gSdDxeComponentName.SupportedLanguages,\r
367 &Device->ControllerNameTable,\r
368 Device->ModelName,\r
369 TRUE\r
370 );\r
371 AddUnicodeString2 (\r
372 "en",\r
e25a7678 373 gSdDxeComponentName2.SupportedLanguages,\r
48555339
FT
374 &Device->ControllerNameTable,\r
375 Device->ModelName,\r
376 FALSE\r
377 );\r
378\r
379 Status = gBS->InstallMultipleProtocolInterfaces (\r
380 &Device->Handle,\r
381 &gEfiDevicePathProtocolGuid,\r
382 Device->DevicePath,\r
383 &gEfiBlockIoProtocolGuid,\r
384 &Device->BlockIo,\r
385 &gEfiBlockIo2ProtocolGuid,\r
386 &Device->BlockIo2,\r
275d5136
FT
387 &gEfiEraseBlockProtocolGuid,\r
388 &Device->EraseBlock,\r
af6a6bf4
HW
389 &gEfiDiskInfoProtocolGuid,\r
390 &Device->DiskInfo,\r
48555339
FT
391 NULL\r
392 );\r
393\r
394 if (!EFI_ERROR (Status)) {\r
395 gBS->OpenProtocol (\r
396 Private->Controller,\r
397 &gEfiSdMmcPassThruProtocolGuid,\r
1436aea4 398 (VOID **)&(Private->PassThru),\r
48555339
FT
399 Private->DriverBindingHandle,\r
400 Device->Handle,\r
401 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
402 );\r
403 }\r
404\r
405Error:\r
406 FreePool (DevicePath);\r
407\r
408 if (EFI_ERROR (Status) && (NewDevicePath != NULL)) {\r
409 FreePool (NewDevicePath);\r
410 }\r
411\r
412 if (EFI_ERROR (Status) && (Device != NULL)) {\r
413 FreePool (Device);\r
414 }\r
415\r
416 return Status;\r
417}\r
418\r
419/**\r
420 Tests to see if this driver supports a given controller. If a child device is provided,\r
421 it further tests to see if this driver supports creating a handle for the specified child device.\r
422\r
423 This function checks to see if the driver specified by This supports the device specified by\r
424 ControllerHandle. Drivers will typically use the device path attached to\r
425 ControllerHandle and/or the services from the bus I/O abstraction attached to\r
426 ControllerHandle to determine if the driver supports ControllerHandle. This function\r
427 may be called many times during platform initialization. In order to reduce boot times, the tests\r
428 performed by this function must be very small, and take as little time as possible to execute. This\r
429 function must not change the state of any hardware devices, and this function must be aware that the\r
430 device specified by ControllerHandle may already be managed by the same driver or a\r
431 different driver. This function must match its calls to AllocatePages() with FreePages(),\r
432 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().\r
433 Since ControllerHandle may have been previously started by the same driver, if a protocol is\r
434 already in the opened state, then it must not be closed with CloseProtocol(). This is required\r
435 to guarantee the state of ControllerHandle is not modified by this function.\r
436\r
437 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
438 @param[in] ControllerHandle The handle of the controller to test. This handle\r
439 must support a protocol interface that supplies\r
440 an I/O abstraction to the driver.\r
441 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
442 parameter is ignored by device drivers, and is optional for bus\r
443 drivers. For bus drivers, if this parameter is not NULL, then\r
444 the bus driver must determine if the bus controller specified\r
445 by ControllerHandle and the child controller specified\r
446 by RemainingDevicePath are both supported by this\r
447 bus driver.\r
448\r
449 @retval EFI_SUCCESS The device specified by ControllerHandle and\r
450 RemainingDevicePath is supported by the driver specified by This.\r
451 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
452 RemainingDevicePath is already being managed by the driver\r
453 specified by This.\r
454 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
455 RemainingDevicePath is already being managed by a different\r
456 driver or an application that requires exclusive access.\r
457 Currently not implemented.\r
458 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
459 RemainingDevicePath is not supported by the driver specified by This.\r
460**/\r
461EFI_STATUS\r
462EFIAPI\r
463SdDxeDriverBindingSupported (\r
1436aea4
MK
464 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
465 IN EFI_HANDLE Controller,\r
466 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
48555339
FT
467 )\r
468{\r
1436aea4
MK
469 EFI_STATUS Status;\r
470 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
471 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;\r
472 UINT8 Slot;\r
48555339
FT
473\r
474 //\r
475 // Test EFI_SD_MMC_PASS_THRU_PROTOCOL on the controller handle.\r
476 //\r
477 Status = gBS->OpenProtocol (\r
478 Controller,\r
479 &gEfiSdMmcPassThruProtocolGuid,\r
1436aea4 480 (VOID **)&PassThru,\r
48555339
FT
481 This->DriverBindingHandle,\r
482 Controller,\r
483 EFI_OPEN_PROTOCOL_BY_DRIVER\r
484 );\r
485\r
486 if (Status == EFI_ALREADY_STARTED) {\r
487 return EFI_SUCCESS;\r
488 }\r
489\r
490 if (EFI_ERROR (Status)) {\r
491 return Status;\r
492 }\r
493\r
494 //\r
495 // Test RemainingDevicePath is valid or not.\r
496 //\r
497 if ((RemainingDevicePath != NULL) && !IsDevicePathEnd (RemainingDevicePath)) {\r
498 Status = PassThru->GetSlotNumber (PassThru, RemainingDevicePath, &Slot);\r
499 if (EFI_ERROR (Status)) {\r
500 //\r
501 // Close the I/O Abstraction(s) used to perform the supported test\r
502 //\r
503 gBS->CloseProtocol (\r
504 Controller,\r
505 &gEfiSdMmcPassThruProtocolGuid,\r
506 This->DriverBindingHandle,\r
507 Controller\r
508 );\r
509 return Status;\r
510 }\r
511 }\r
512\r
513 //\r
514 // Close the I/O Abstraction(s) used to perform the supported test\r
515 //\r
516 gBS->CloseProtocol (\r
517 Controller,\r
518 &gEfiSdMmcPassThruProtocolGuid,\r
519 This->DriverBindingHandle,\r
520 Controller\r
521 );\r
522\r
523 //\r
524 // Open the EFI Device Path protocol needed to perform the supported test\r
525 //\r
526 Status = gBS->OpenProtocol (\r
527 Controller,\r
528 &gEfiDevicePathProtocolGuid,\r
1436aea4 529 (VOID **)&ParentDevicePath,\r
48555339
FT
530 This->DriverBindingHandle,\r
531 Controller,\r
532 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
533 );\r
534 return Status;\r
535}\r
536\r
537/**\r
538 Starts a device controller or a bus controller.\r
539\r
540 The Start() function is designed to be invoked from the EFI boot service ConnectController().\r
541 As a result, much of the error checking on the parameters to Start() has been moved into this\r
542 common boot service. It is legal to call Start() from other locations,\r
543 but the following calling restrictions must be followed or the system behavior will not be deterministic.\r
544 1. ControllerHandle must be a valid EFI_HANDLE.\r
545 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
546 EFI_DEVICE_PATH_PROTOCOL.\r
547 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
548 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.\r
549\r
550 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
551 @param[in] ControllerHandle The handle of the controller to start. This handle\r
552 must support a protocol interface that supplies\r
553 an I/O abstraction to the driver.\r
554 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
555 parameter is ignored by device drivers, and is optional for bus\r
556 drivers. For a bus driver, if this parameter is NULL, then handles\r
557 for all the children of Controller are created by this driver.\r
558 If this parameter is not NULL and the first Device Path Node is\r
559 not the End of Device Path Node, then only the handle for the\r
560 child device specified by the first Device Path Node of\r
561 RemainingDevicePath is created by this driver.\r
562 If the first Device Path Node of RemainingDevicePath is\r
563 the End of Device Path Node, no child handle is created by this\r
564 driver.\r
565\r
566 @retval EFI_SUCCESS The device was started.\r
567 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.\r
568 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
b854b075 569 @retval Others The driver failed to start the device.\r
48555339
FT
570\r
571**/\r
572EFI_STATUS\r
573EFIAPI\r
574SdDxeDriverBindingStart (\r
1436aea4
MK
575 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
576 IN EFI_HANDLE Controller,\r
577 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
48555339
FT
578 )\r
579{\r
1436aea4
MK
580 EFI_STATUS Status;\r
581 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;\r
582 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
583 SD_DRIVER_PRIVATE_DATA *Private;\r
584 UINT8 Slot;\r
48555339
FT
585\r
586 Private = NULL;\r
587 PassThru = NULL;\r
1436aea4
MK
588 Status = gBS->OpenProtocol (\r
589 Controller,\r
590 &gEfiSdMmcPassThruProtocolGuid,\r
591 (VOID **)&PassThru,\r
592 This->DriverBindingHandle,\r
593 Controller,\r
594 EFI_OPEN_PROTOCOL_BY_DRIVER\r
595 );\r
48555339
FT
596 if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {\r
597 return Status;\r
598 }\r
599\r
600 //\r
601 // Check EFI_ALREADY_STARTED to reuse the original SD_DRIVER_PRIVATE_DATA.\r
602 //\r
603 if (Status != EFI_ALREADY_STARTED) {\r
604 Private = AllocateZeroPool (sizeof (SD_DRIVER_PRIVATE_DATA));\r
605 if (Private == NULL) {\r
606 Status = EFI_OUT_OF_RESOURCES;\r
607 goto Error;\r
608 }\r
609\r
610 Status = gBS->OpenProtocol (\r
611 Controller,\r
612 &gEfiDevicePathProtocolGuid,\r
1436aea4 613 (VOID **)&ParentDevicePath,\r
48555339
FT
614 This->DriverBindingHandle,\r
615 Controller,\r
616 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
617 );\r
618 ASSERT_EFI_ERROR (Status);\r
619 Private->PassThru = PassThru;\r
620 Private->Controller = Controller;\r
621 Private->ParentDevicePath = ParentDevicePath;\r
622 Private->DriverBindingHandle = This->DriverBindingHandle;\r
623\r
624 Status = gBS->InstallProtocolInterface (\r
625 &Controller,\r
626 &gEfiCallerIdGuid,\r
627 EFI_NATIVE_INTERFACE,\r
628 Private\r
629 );\r
630 if (EFI_ERROR (Status)) {\r
631 goto Error;\r
632 }\r
633 } else {\r
634 Status = gBS->OpenProtocol (\r
635 Controller,\r
636 &gEfiCallerIdGuid,\r
1436aea4 637 (VOID **)&Private,\r
48555339
FT
638 This->DriverBindingHandle,\r
639 Controller,\r
640 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
641 );\r
642 if (EFI_ERROR (Status)) {\r
643 goto Error;\r
644 }\r
645 }\r
646\r
647 if (RemainingDevicePath == NULL) {\r
648 Slot = 0xFF;\r
649 while (TRUE) {\r
650 Status = PassThru->GetNextSlot (PassThru, &Slot);\r
651 if (EFI_ERROR (Status)) {\r
652 //\r
653 // Cannot find more legal slots.\r
654 //\r
655 Status = EFI_SUCCESS;\r
656 break;\r
657 }\r
658\r
659 Status = DiscoverSdDevice (Private, Slot);\r
660 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
661 break;\r
662 }\r
663 }\r
664 } else if (!IsDevicePathEnd (RemainingDevicePath)) {\r
665 Status = PassThru->GetSlotNumber (PassThru, RemainingDevicePath, &Slot);\r
666 if (!EFI_ERROR (Status)) {\r
667 Status = DiscoverSdDevice (Private, Slot);\r
668 }\r
669 }\r
670\r
671Error:\r
672 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
673 gBS->CloseProtocol (\r
674 Controller,\r
675 &gEfiSdMmcPassThruProtocolGuid,\r
676 This->DriverBindingHandle,\r
677 Controller\r
678 );\r
679\r
680 if (Private != NULL) {\r
681 gBS->UninstallMultipleProtocolInterfaces (\r
1436aea4
MK
682 Controller,\r
683 &gEfiCallerIdGuid,\r
684 Private,\r
685 NULL\r
686 );\r
48555339
FT
687 FreePool (Private);\r
688 }\r
689 }\r
1436aea4 690\r
48555339
FT
691 return Status;\r
692}\r
693\r
694/**\r
695 Stops a device controller or a bus controller.\r
696\r
697 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().\r
698 As a result, much of the error checking on the parameters to Stop() has been moved\r
699 into this common boot service. It is legal to call Stop() from other locations,\r
700 but the following calling restrictions must be followed or the system behavior will not be deterministic.\r
701 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
702 same driver's Start() function.\r
703 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
704 EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
705 Start() function, and the Start() function must have called OpenProtocol() on\r
706 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
707\r
708 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
709 @param[in] ControllerHandle A handle to the device being stopped. The handle must\r
710 support a bus specific I/O protocol for the driver\r
711 to use to stop the device.\r
712 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
713 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL\r
714 if NumberOfChildren is 0.\r
715\r
716 @retval EFI_SUCCESS The device was stopped.\r
717 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
718\r
719**/\r
720EFI_STATUS\r
721EFIAPI\r
722SdDxeDriverBindingStop (\r
1436aea4
MK
723 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
724 IN EFI_HANDLE Controller,\r
725 IN UINTN NumberOfChildren,\r
726 IN EFI_HANDLE *ChildHandleBuffer\r
48555339
FT
727 )\r
728{\r
1436aea4
MK
729 EFI_STATUS Status;\r
730 BOOLEAN AllChildrenStopped;\r
731 UINTN Index;\r
732 SD_DRIVER_PRIVATE_DATA *Private;\r
733 SD_DEVICE *Device;\r
734 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;\r
735 EFI_BLOCK_IO2_PROTOCOL *BlockIo2;\r
736 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
737 LIST_ENTRY *Link;\r
738 LIST_ENTRY *NextLink;\r
739 SD_REQUEST *Request;\r
740 EFI_TPL OldTpl;\r
48555339
FT
741\r
742 if (NumberOfChildren == 0) {\r
743 Status = gBS->OpenProtocol (\r
744 Controller,\r
745 &gEfiCallerIdGuid,\r
1436aea4 746 (VOID **)&Private,\r
48555339
FT
747 This->DriverBindingHandle,\r
748 Controller,\r
749 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
750 );\r
751 if (EFI_ERROR (Status)) {\r
752 return EFI_DEVICE_ERROR;\r
753 }\r
754\r
755 gBS->UninstallProtocolInterface (\r
1436aea4
MK
756 Controller,\r
757 &gEfiCallerIdGuid,\r
758 Private\r
759 );\r
48555339 760 gBS->CloseProtocol (\r
1436aea4
MK
761 Controller,\r
762 &gEfiSdMmcPassThruProtocolGuid,\r
763 This->DriverBindingHandle,\r
764 Controller\r
765 );\r
48555339
FT
766\r
767 FreePool (Private);\r
768\r
769 return EFI_SUCCESS;\r
770 }\r
771\r
772 AllChildrenStopped = TRUE;\r
773\r
774 for (Index = 0; Index < NumberOfChildren; Index++) {\r
775 BlockIo = NULL;\r
776 BlockIo2 = NULL;\r
1436aea4
MK
777 Status = gBS->OpenProtocol (\r
778 ChildHandleBuffer[Index],\r
779 &gEfiBlockIoProtocolGuid,\r
780 (VOID **)&BlockIo,\r
781 This->DriverBindingHandle,\r
782 Controller,\r
783 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
784 );\r
48555339
FT
785 if (EFI_ERROR (Status)) {\r
786 Status = gBS->OpenProtocol (\r
787 ChildHandleBuffer[Index],\r
788 &gEfiBlockIo2ProtocolGuid,\r
1436aea4 789 (VOID **)&BlockIo2,\r
48555339
FT
790 This->DriverBindingHandle,\r
791 Controller,\r
792 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
793 );\r
794 if (EFI_ERROR (Status)) {\r
795 AllChildrenStopped = FALSE;\r
796 continue;\r
797 }\r
798 }\r
799\r
800 if (BlockIo != NULL) {\r
801 Device = SD_DEVICE_DATA_FROM_BLKIO (BlockIo);\r
802 } else {\r
803 ASSERT (BlockIo2 != NULL);\r
804 Device = SD_DEVICE_DATA_FROM_BLKIO2 (BlockIo2);\r
805 }\r
806\r
807 //\r
808 // Free all on-going async tasks.\r
809 //\r
3b1d8241 810 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
48555339
FT
811 for (Link = GetFirstNode (&Device->Queue);\r
812 !IsNull (&Device->Queue, Link);\r
1436aea4
MK
813 Link = NextLink)\r
814 {\r
48555339
FT
815 NextLink = GetNextNode (&Device->Queue, Link);\r
816 RemoveEntryList (Link);\r
817\r
818 Request = SD_REQUEST_FROM_LINK (Link);\r
819\r
820 gBS->CloseEvent (Request->Event);\r
821 Request->Token->TransactionStatus = EFI_ABORTED;\r
822\r
823 if (Request->IsEnd) {\r
824 gBS->SignalEvent (Request->Token->Event);\r
825 }\r
826\r
827 FreePool (Request);\r
828 }\r
1436aea4 829\r
48555339
FT
830 gBS->RestoreTPL (OldTpl);\r
831\r
832 //\r
833 // Close the child handle\r
834 //\r
835 Status = gBS->CloseProtocol (\r
836 Controller,\r
837 &gEfiSdMmcPassThruProtocolGuid,\r
838 This->DriverBindingHandle,\r
839 ChildHandleBuffer[Index]\r
840 );\r
841\r
842 Status = gBS->UninstallMultipleProtocolInterfaces (\r
843 ChildHandleBuffer[Index],\r
844 &gEfiDevicePathProtocolGuid,\r
845 Device->DevicePath,\r
846 &gEfiBlockIoProtocolGuid,\r
847 &Device->BlockIo,\r
848 &gEfiBlockIo2ProtocolGuid,\r
849 &Device->BlockIo2,\r
275d5136
FT
850 &gEfiEraseBlockProtocolGuid,\r
851 &Device->EraseBlock,\r
af6a6bf4
HW
852 &gEfiDiskInfoProtocolGuid,\r
853 &Device->DiskInfo,\r
48555339
FT
854 NULL\r
855 );\r
856 if (EFI_ERROR (Status)) {\r
857 AllChildrenStopped = FALSE;\r
1436aea4
MK
858 gBS->OpenProtocol (\r
859 Controller,\r
860 &gEfiSdMmcPassThruProtocolGuid,\r
861 (VOID **)&PassThru,\r
862 This->DriverBindingHandle,\r
863 ChildHandleBuffer[Index],\r
864 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
865 );\r
48555339
FT
866 } else {\r
867 FreePool (Device->DevicePath);\r
868 FreeUnicodeStringTable (Device->ControllerNameTable);\r
869 FreePool (Device);\r
870 }\r
871 }\r
872\r
873 if (!AllChildrenStopped) {\r
874 return EFI_DEVICE_ERROR;\r
875 }\r
876\r
877 return EFI_SUCCESS;\r
878}\r
879\r
880/**\r
881 The user Entry Point for module SdDxe. The user code starts with this function.\r
882\r
883 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
884 @param[in] SystemTable A pointer to the EFI System Table.\r
885\r
886 @retval EFI_SUCCESS The entry point is executed successfully.\r
887 @retval other Some errors occur when executing this entry point.\r
888\r
889**/\r
890EFI_STATUS\r
891EFIAPI\r
892InitializeSdDxe (\r
1436aea4
MK
893 IN EFI_HANDLE ImageHandle,\r
894 IN EFI_SYSTEM_TABLE *SystemTable\r
48555339
FT
895 )\r
896{\r
1436aea4 897 EFI_STATUS Status;\r
48555339
FT
898\r
899 //\r
900 // Install driver model protocol(s).\r
901 //\r
902 Status = EfiLibInstallDriverBindingComponentName2 (\r
903 ImageHandle,\r
904 SystemTable,\r
905 &gSdDxeDriverBinding,\r
906 ImageHandle,\r
907 &gSdDxeComponentName,\r
908 &gSdDxeComponentName2\r
909 );\r
910 ASSERT_EFI_ERROR (Status);\r
911\r
912 return Status;\r
913}\r