]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / SdMmcPciHcDxe / SdMmcPciHcDxe.c
1 /** @file
2 This driver is used to manage SD/MMC PCI host controllers which are compliance
3 with SD Host Controller Simplified Specification version 3.00 plus the 64-bit
4 System Addressing support in SD Host Controller Simplified Specification version
5 4.20.
6
7 It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer use.
8
9 Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
10 Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.<BR>
11 SPDX-License-Identifier: BSD-2-Clause-Patent
12
13 **/
14
15 #include "SdMmcPciHcDxe.h"
16
17 EDKII_SD_MMC_OVERRIDE *mOverride;
18
19 //
20 // Driver Global Variables
21 //
22 EFI_DRIVER_BINDING_PROTOCOL gSdMmcPciHcDriverBinding = {
23 SdMmcPciHcDriverBindingSupported,
24 SdMmcPciHcDriverBindingStart,
25 SdMmcPciHcDriverBindingStop,
26 0x10,
27 NULL,
28 NULL
29 };
30
31 #define SLOT_INIT_TEMPLATE {0, UnknownSlot, 0, 0, 0, 0,\
32 {EDKII_SD_MMC_BUS_WIDTH_IGNORE,\
33 EDKII_SD_MMC_CLOCK_FREQ_IGNORE,\
34 {EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE}}}
35
36 //
37 // Template for SD/MMC host controller private data.
38 //
39 SD_MMC_HC_PRIVATE_DATA gSdMmcPciHcTemplate = {
40 SD_MMC_HC_PRIVATE_SIGNATURE, // Signature
41 NULL, // ControllerHandle
42 NULL, // PciIo
43 { // PassThru
44 sizeof (UINT32),
45 SdMmcPassThruPassThru,
46 SdMmcPassThruGetNextSlot,
47 SdMmcPassThruBuildDevicePath,
48 SdMmcPassThruGetSlotNumber,
49 SdMmcPassThruResetDevice
50 },
51 0, // PciAttributes
52 0, // PreviousSlot
53 NULL, // TimerEvent
54 NULL, // ConnectEvent
55 // Queue
56 INITIALIZE_LIST_HEAD_VARIABLE (gSdMmcPciHcTemplate.Queue),
57 { // Slot
58 SLOT_INIT_TEMPLATE,
59 SLOT_INIT_TEMPLATE,
60 SLOT_INIT_TEMPLATE,
61 SLOT_INIT_TEMPLATE,
62 SLOT_INIT_TEMPLATE,
63 SLOT_INIT_TEMPLATE
64 },
65 { // Capability
66 { 0 },
67 },
68 { // MaxCurrent
69 0,
70 },
71 {
72 0 // ControllerVersion
73 }
74 };
75
76 SD_DEVICE_PATH mSdDpTemplate = {
77 {
78 MESSAGING_DEVICE_PATH,
79 MSG_SD_DP,
80 {
81 (UINT8)(sizeof (SD_DEVICE_PATH)),
82 (UINT8)((sizeof (SD_DEVICE_PATH)) >> 8)
83 }
84 },
85 0
86 };
87
88 EMMC_DEVICE_PATH mEmmcDpTemplate = {
89 {
90 MESSAGING_DEVICE_PATH,
91 MSG_EMMC_DP,
92 {
93 (UINT8)(sizeof (EMMC_DEVICE_PATH)),
94 (UINT8)((sizeof (EMMC_DEVICE_PATH)) >> 8)
95 }
96 },
97 0
98 };
99
100 //
101 // Prioritized function list to detect card type.
102 // User could add other card detection logic here.
103 //
104 CARD_TYPE_DETECT_ROUTINE mCardTypeDetectRoutineTable[] = {
105 EmmcIdentification,
106 SdCardIdentification,
107 NULL
108 };
109
110 /**
111 The entry point for SD host controller driver, used to install this driver on the ImageHandle.
112
113 @param[in] ImageHandle The firmware allocated handle for this driver image.
114 @param[in] SystemTable Pointer to the EFI system table.
115
116 @retval EFI_SUCCESS Driver loaded.
117 @retval other Driver not loaded.
118
119 **/
120 EFI_STATUS
121 EFIAPI
122 InitializeSdMmcPciHcDxe (
123 IN EFI_HANDLE ImageHandle,
124 IN EFI_SYSTEM_TABLE *SystemTable
125 )
126 {
127 EFI_STATUS Status;
128
129 Status = EfiLibInstallDriverBindingComponentName2 (
130 ImageHandle,
131 SystemTable,
132 &gSdMmcPciHcDriverBinding,
133 ImageHandle,
134 &gSdMmcPciHcComponentName,
135 &gSdMmcPciHcComponentName2
136 );
137 ASSERT_EFI_ERROR (Status);
138
139 return Status;
140 }
141
142 /**
143 Call back function when the timer event is signaled.
144
145 @param[in] Event The Event this notify function registered to.
146 @param[in] Context Pointer to the context data registered to the
147 Event.
148
149 **/
150 VOID
151 EFIAPI
152 ProcessAsyncTaskList (
153 IN EFI_EVENT Event,
154 IN VOID *Context
155 )
156 {
157 SD_MMC_HC_PRIVATE_DATA *Private;
158 LIST_ENTRY *Link;
159 SD_MMC_HC_TRB *Trb;
160 EFI_STATUS Status;
161 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;
162 BOOLEAN InfiniteWait;
163 EFI_EVENT TrbEvent;
164
165 Private = (SD_MMC_HC_PRIVATE_DATA *)Context;
166
167 //
168 // Check if the first entry in the async I/O queue is done or not.
169 //
170 Status = EFI_SUCCESS;
171 Trb = NULL;
172 Link = GetFirstNode (&Private->Queue);
173 if (!IsNull (&Private->Queue, Link)) {
174 Trb = SD_MMC_HC_TRB_FROM_THIS (Link);
175 if (!Private->Slot[Trb->Slot].MediaPresent) {
176 Status = EFI_NO_MEDIA;
177 goto Done;
178 }
179
180 if (!Trb->Started) {
181 //
182 // Check whether the cmd/data line is ready for transfer.
183 //
184 Status = SdMmcCheckTrbEnv (Private, Trb);
185 if (!EFI_ERROR (Status)) {
186 Trb->Started = TRUE;
187 Status = SdMmcExecTrb (Private, Trb);
188 if (EFI_ERROR (Status)) {
189 goto Done;
190 }
191 } else {
192 goto Done;
193 }
194 }
195
196 Status = SdMmcCheckTrbResult (Private, Trb);
197 }
198
199 Done:
200 if ((Trb != NULL) && (Status == EFI_NOT_READY)) {
201 Packet = Trb->Packet;
202 if (Packet->Timeout == 0) {
203 InfiniteWait = TRUE;
204 } else {
205 InfiniteWait = FALSE;
206 }
207
208 if ((!InfiniteWait) && (Trb->Timeout-- == 0)) {
209 RemoveEntryList (Link);
210 Trb->Packet->TransactionStatus = EFI_TIMEOUT;
211 TrbEvent = Trb->Event;
212 SdMmcFreeTrb (Trb);
213 DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p EFI_TIMEOUT\n", TrbEvent));
214 gBS->SignalEvent (TrbEvent);
215 return;
216 }
217 } else if ((Trb != NULL) && (Status == EFI_CRC_ERROR) && (Trb->Retries > 0)) {
218 Trb->Retries--;
219 Trb->Started = FALSE;
220 } else if ((Trb != NULL)) {
221 RemoveEntryList (Link);
222 Trb->Packet->TransactionStatus = Status;
223 TrbEvent = Trb->Event;
224 SdMmcFreeTrb (Trb);
225 DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p with %r\n", TrbEvent, Status));
226 gBS->SignalEvent (TrbEvent);
227 }
228
229 return;
230 }
231
232 /**
233 Sd removable device enumeration callback function when the timer event is signaled.
234
235 @param[in] Event The Event this notify function registered to.
236 @param[in] Context Pointer to the context data registered to the
237 Event.
238
239 **/
240 VOID
241 EFIAPI
242 SdMmcPciHcEnumerateDevice (
243 IN EFI_EVENT Event,
244 IN VOID *Context
245 )
246 {
247 SD_MMC_HC_PRIVATE_DATA *Private;
248 EFI_STATUS Status;
249 UINT8 Slot;
250 BOOLEAN MediaPresent;
251 UINT32 RoutineNum;
252 CARD_TYPE_DETECT_ROUTINE *Routine;
253 UINTN Index;
254 LIST_ENTRY *Link;
255 LIST_ENTRY *NextLink;
256 SD_MMC_HC_TRB *Trb;
257 EFI_TPL OldTpl;
258
259 Private = (SD_MMC_HC_PRIVATE_DATA *)Context;
260
261 for (Slot = 0; Slot < SD_MMC_HC_MAX_SLOT; Slot++) {
262 if ((Private->Slot[Slot].Enable) && (Private->Slot[Slot].SlotType == RemovableSlot)) {
263 Status = SdMmcHcCardDetect (Private->PciIo, Slot, &MediaPresent);
264 if ((Status == EFI_MEDIA_CHANGED) && !MediaPresent) {
265 DEBUG ((DEBUG_INFO, "SdMmcPciHcEnumerateDevice: device disconnected at slot %d of pci %p\n", Slot, Private->PciIo));
266 Private->Slot[Slot].MediaPresent = FALSE;
267 Private->Slot[Slot].Initialized = FALSE;
268 //
269 // Signal all async task events at the slot with EFI_NO_MEDIA status.
270 //
271 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
272 for (Link = GetFirstNode (&Private->Queue);
273 !IsNull (&Private->Queue, Link);
274 Link = NextLink)
275 {
276 NextLink = GetNextNode (&Private->Queue, Link);
277 Trb = SD_MMC_HC_TRB_FROM_THIS (Link);
278 if (Trb->Slot == Slot) {
279 RemoveEntryList (Link);
280 Trb->Packet->TransactionStatus = EFI_NO_MEDIA;
281 gBS->SignalEvent (Trb->Event);
282 SdMmcFreeTrb (Trb);
283 }
284 }
285
286 gBS->RestoreTPL (OldTpl);
287 //
288 // Notify the upper layer the connect state change through ReinstallProtocolInterface.
289 //
290 gBS->ReinstallProtocolInterface (
291 Private->ControllerHandle,
292 &gEfiSdMmcPassThruProtocolGuid,
293 &Private->PassThru,
294 &Private->PassThru
295 );
296 }
297
298 if ((Status == EFI_MEDIA_CHANGED) && MediaPresent) {
299 DEBUG ((DEBUG_INFO, "SdMmcPciHcEnumerateDevice: device connected at slot %d of pci %p\n", Slot, Private->PciIo));
300 //
301 // Reset the specified slot of the SD/MMC Pci Host Controller
302 //
303 Status = SdMmcHcReset (Private, Slot);
304 if (EFI_ERROR (Status)) {
305 continue;
306 }
307
308 //
309 // Reinitialize slot and restart identification process for the new attached device
310 //
311 Status = SdMmcHcInitHost (Private, Slot);
312 if (EFI_ERROR (Status)) {
313 continue;
314 }
315
316 Private->Slot[Slot].MediaPresent = TRUE;
317 Private->Slot[Slot].Initialized = TRUE;
318 RoutineNum = sizeof (mCardTypeDetectRoutineTable) / sizeof (CARD_TYPE_DETECT_ROUTINE);
319 for (Index = 0; Index < RoutineNum; Index++) {
320 Routine = &mCardTypeDetectRoutineTable[Index];
321 if (*Routine != NULL) {
322 Status = (*Routine)(Private, Slot);
323 if (!EFI_ERROR (Status)) {
324 break;
325 }
326 }
327 }
328
329 //
330 // This card doesn't get initialized correctly.
331 //
332 if (Index == RoutineNum) {
333 Private->Slot[Slot].Initialized = FALSE;
334 }
335
336 //
337 // Notify the upper layer the connect state change through ReinstallProtocolInterface.
338 //
339 gBS->ReinstallProtocolInterface (
340 Private->ControllerHandle,
341 &gEfiSdMmcPassThruProtocolGuid,
342 &Private->PassThru,
343 &Private->PassThru
344 );
345 }
346 }
347 }
348
349 return;
350 }
351
352 /**
353 Tests to see if this driver supports a given controller. If a child device is provided,
354 it further tests to see if this driver supports creating a handle for the specified child device.
355
356 This function checks to see if the driver specified by This supports the device specified by
357 ControllerHandle. Drivers will typically use the device path attached to
358 ControllerHandle and/or the services from the bus I/O abstraction attached to
359 ControllerHandle to determine if the driver supports ControllerHandle. This function
360 may be called many times during platform initialization. In order to reduce boot times, the tests
361 performed by this function must be very small, and take as little time as possible to execute. This
362 function must not change the state of any hardware devices, and this function must be aware that the
363 device specified by ControllerHandle may already be managed by the same driver or a
364 different driver. This function must match its calls to AllocatePages() with FreePages(),
365 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
366 Since ControllerHandle may have been previously started by the same driver, if a protocol is
367 already in the opened state, then it must not be closed with CloseProtocol(). This is required
368 to guarantee the state of ControllerHandle is not modified by this function.
369
370 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
371 @param[in] ControllerHandle The handle of the controller to test. This handle
372 must support a protocol interface that supplies
373 an I/O abstraction to the driver.
374 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
375 parameter is ignored by device drivers, and is optional for bus
376 drivers. For bus drivers, if this parameter is not NULL, then
377 the bus driver must determine if the bus controller specified
378 by ControllerHandle and the child controller specified
379 by RemainingDevicePath are both supported by this
380 bus driver.
381
382 @retval EFI_SUCCESS The device specified by ControllerHandle and
383 RemainingDevicePath is supported by the driver specified by This.
384 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
385 RemainingDevicePath is already being managed by the driver
386 specified by This.
387 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
388 RemainingDevicePath is already being managed by a different
389 driver or an application that requires exclusive access.
390 Currently not implemented.
391 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
392 RemainingDevicePath is not supported by the driver specified by This.
393 **/
394 EFI_STATUS
395 EFIAPI
396 SdMmcPciHcDriverBindingSupported (
397 IN EFI_DRIVER_BINDING_PROTOCOL *This,
398 IN EFI_HANDLE Controller,
399 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
400 )
401 {
402 EFI_STATUS Status;
403 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
404 EFI_PCI_IO_PROTOCOL *PciIo;
405 PCI_TYPE00 PciData;
406
407 PciIo = NULL;
408 ParentDevicePath = NULL;
409
410 //
411 // SdPciHcDxe is a device driver, and should ingore the
412 // "RemainingDevicePath" according to EFI spec.
413 //
414 Status = gBS->OpenProtocol (
415 Controller,
416 &gEfiDevicePathProtocolGuid,
417 (VOID *)&ParentDevicePath,
418 This->DriverBindingHandle,
419 Controller,
420 EFI_OPEN_PROTOCOL_BY_DRIVER
421 );
422 if (EFI_ERROR (Status)) {
423 //
424 // EFI_ALREADY_STARTED is also an error.
425 //
426 return Status;
427 }
428
429 //
430 // Close the protocol because we don't use it here.
431 //
432 gBS->CloseProtocol (
433 Controller,
434 &gEfiDevicePathProtocolGuid,
435 This->DriverBindingHandle,
436 Controller
437 );
438
439 //
440 // Now test the EfiPciIoProtocol.
441 //
442 Status = gBS->OpenProtocol (
443 Controller,
444 &gEfiPciIoProtocolGuid,
445 (VOID **)&PciIo,
446 This->DriverBindingHandle,
447 Controller,
448 EFI_OPEN_PROTOCOL_BY_DRIVER
449 );
450 if (EFI_ERROR (Status)) {
451 return Status;
452 }
453
454 //
455 // Now further check the PCI header: Base class (offset 0x08) and
456 // Sub Class (offset 0x05). This controller should be an SD/MMC PCI
457 // Host Controller.
458 //
459 Status = PciIo->Pci.Read (
460 PciIo,
461 EfiPciIoWidthUint8,
462 0,
463 sizeof (PciData),
464 &PciData
465 );
466 if (EFI_ERROR (Status)) {
467 gBS->CloseProtocol (
468 Controller,
469 &gEfiPciIoProtocolGuid,
470 This->DriverBindingHandle,
471 Controller
472 );
473 return EFI_UNSUPPORTED;
474 }
475
476 //
477 // Since we already got the PciData, we can close protocol to avoid to carry it
478 // on for multiple exit points.
479 //
480 gBS->CloseProtocol (
481 Controller,
482 &gEfiPciIoProtocolGuid,
483 This->DriverBindingHandle,
484 Controller
485 );
486
487 //
488 // Examine SD PCI Host Controller PCI Configuration table fields.
489 //
490 if ((PciData.Hdr.ClassCode[2] == PCI_CLASS_SYSTEM_PERIPHERAL) &&
491 (PciData.Hdr.ClassCode[1] == PCI_SUBCLASS_SD_HOST_CONTROLLER) &&
492 ((PciData.Hdr.ClassCode[0] == 0x00) || (PciData.Hdr.ClassCode[0] == 0x01)))
493 {
494 return EFI_SUCCESS;
495 }
496
497 return EFI_UNSUPPORTED;
498 }
499
500 /**
501 Starts a device controller or a bus controller.
502
503 The Start() function is designed to be invoked from the EFI boot service ConnectController().
504 As a result, much of the error checking on the parameters to Start() has been moved into this
505 common boot service. It is legal to call Start() from other locations,
506 but the following calling restrictions must be followed or the system behavior will not be deterministic.
507 1. ControllerHandle must be a valid EFI_HANDLE.
508 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
509 EFI_DEVICE_PATH_PROTOCOL.
510 3. Prior to calling Start(), the Supported() function for the driver specified by This must
511 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
512
513 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
514 @param[in] ControllerHandle The handle of the controller to start. This handle
515 must support a protocol interface that supplies
516 an I/O abstraction to the driver.
517 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
518 parameter is ignored by device drivers, and is optional for bus
519 drivers. For a bus driver, if this parameter is NULL, then handles
520 for all the children of Controller are created by this driver.
521 If this parameter is not NULL and the first Device Path Node is
522 not the End of Device Path Node, then only the handle for the
523 child device specified by the first Device Path Node of
524 RemainingDevicePath is created by this driver.
525 If the first Device Path Node of RemainingDevicePath is
526 the End of Device Path Node, no child handle is created by this
527 driver.
528
529 @retval EFI_SUCCESS The device was started.
530 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
531 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
532 @retval Others The driver failded to start the device.
533
534 **/
535 EFI_STATUS
536 EFIAPI
537 SdMmcPciHcDriverBindingStart (
538 IN EFI_DRIVER_BINDING_PROTOCOL *This,
539 IN EFI_HANDLE Controller,
540 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
541 )
542 {
543 EFI_STATUS Status;
544 SD_MMC_HC_PRIVATE_DATA *Private;
545 EFI_PCI_IO_PROTOCOL *PciIo;
546 UINT64 Supports;
547 UINT64 PciAttributes;
548 UINT8 SlotNum;
549 UINT8 FirstBar;
550 UINT8 Slot;
551 UINT8 Index;
552 CARD_TYPE_DETECT_ROUTINE *Routine;
553 UINT32 RoutineNum;
554 BOOLEAN MediaPresent;
555 BOOLEAN Support64BitDma;
556
557 DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStart: Start\n"));
558
559 //
560 // Open PCI I/O Protocol and save pointer to open protocol
561 // in private data area.
562 //
563 PciIo = NULL;
564 Status = gBS->OpenProtocol (
565 Controller,
566 &gEfiPciIoProtocolGuid,
567 (VOID **)&PciIo,
568 This->DriverBindingHandle,
569 Controller,
570 EFI_OPEN_PROTOCOL_BY_DRIVER
571 );
572 if (EFI_ERROR (Status)) {
573 return Status;
574 }
575
576 //
577 // Enable the SD Host Controller MMIO space
578 //
579 Private = NULL;
580 Status = PciIo->Attributes (
581 PciIo,
582 EfiPciIoAttributeOperationGet,
583 0,
584 &PciAttributes
585 );
586
587 if (EFI_ERROR (Status)) {
588 goto Done;
589 }
590
591 Status = PciIo->Attributes (
592 PciIo,
593 EfiPciIoAttributeOperationSupported,
594 0,
595 &Supports
596 );
597
598 if (!EFI_ERROR (Status)) {
599 Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
600 Status = PciIo->Attributes (
601 PciIo,
602 EfiPciIoAttributeOperationEnable,
603 Supports,
604 NULL
605 );
606 } else {
607 goto Done;
608 }
609
610 Private = AllocateCopyPool (sizeof (SD_MMC_HC_PRIVATE_DATA), &gSdMmcPciHcTemplate);
611 if (Private == NULL) {
612 Status = EFI_OUT_OF_RESOURCES;
613 goto Done;
614 }
615
616 Private->ControllerHandle = Controller;
617 Private->PciIo = PciIo;
618 Private->PciAttributes = PciAttributes;
619 InitializeListHead (&Private->Queue);
620
621 //
622 // Get SD/MMC Pci Host Controller Slot info
623 //
624 Status = SdMmcHcGetSlotInfo (PciIo, &FirstBar, &SlotNum);
625 if (EFI_ERROR (Status)) {
626 goto Done;
627 }
628
629 //
630 // Attempt to locate the singleton instance of the SD/MMC override protocol,
631 // which implements platform specific workarounds for non-standard SDHCI
632 // implementations.
633 //
634 if (mOverride == NULL) {
635 Status = gBS->LocateProtocol (
636 &gEdkiiSdMmcOverrideProtocolGuid,
637 NULL,
638 (VOID **)&mOverride
639 );
640 if (!EFI_ERROR (Status)) {
641 DEBUG ((
642 DEBUG_INFO,
643 "%a: found SD/MMC override protocol\n",
644 __FUNCTION__
645 ));
646 }
647 }
648
649 Support64BitDma = TRUE;
650 for (Slot = FirstBar; Slot < (FirstBar + SlotNum); Slot++) {
651 Private->Slot[Slot].Enable = TRUE;
652 //
653 // Get SD/MMC Pci Host Controller Version
654 //
655 Status = SdMmcHcGetControllerVersion (PciIo, Slot, &Private->ControllerVersion[Slot]);
656 if (EFI_ERROR (Status)) {
657 continue;
658 }
659
660 Status = SdMmcHcGetCapability (PciIo, Slot, &Private->Capability[Slot]);
661 if (EFI_ERROR (Status)) {
662 continue;
663 }
664
665 Private->BaseClkFreq[Slot] = Private->Capability[Slot].BaseClkFreq;
666
667 if (mOverride != NULL) {
668 if (mOverride->Capability != NULL) {
669 Status = mOverride->Capability (
670 Controller,
671 Slot,
672 &Private->Capability[Slot],
673 &Private->BaseClkFreq[Slot]
674 );
675 if (EFI_ERROR (Status)) {
676 DEBUG ((
677 DEBUG_WARN,
678 "%a: Failed to override capability - %r\n",
679 __FUNCTION__,
680 Status
681 ));
682 continue;
683 }
684 }
685
686 if (mOverride->NotifyPhase != NULL) {
687 Status = mOverride->NotifyPhase (
688 Controller,
689 Slot,
690 EdkiiSdMmcGetOperatingParam,
691 (VOID *)&Private->Slot[Slot].OperatingParameters
692 );
693 if (EFI_ERROR (Status)) {
694 DEBUG ((DEBUG_WARN, "%a: Failed to get operating parameters, using defaults\n", __FUNCTION__));
695 }
696 }
697 }
698
699 DumpCapabilityReg (Slot, &Private->Capability[Slot]);
700 DEBUG ((
701 DEBUG_INFO,
702 "Slot[%d] Base Clock Frequency: %dMHz\n",
703 Slot,
704 Private->BaseClkFreq[Slot]
705 ));
706
707 //
708 // If any of the slots does not support 64b system bus
709 // do not enable 64b DMA in the PCI layer.
710 //
711 if (((Private->ControllerVersion[Slot] == SD_MMC_HC_CTRL_VER_300) &&
712 (Private->Capability[Slot].SysBus64V3 == 0)) ||
713 ((Private->ControllerVersion[Slot] == SD_MMC_HC_CTRL_VER_400) &&
714 (Private->Capability[Slot].SysBus64V3 == 0)) ||
715 ((Private->ControllerVersion[Slot] >= SD_MMC_HC_CTRL_VER_410) &&
716 (Private->Capability[Slot].SysBus64V4 == 0)))
717 {
718 Support64BitDma = FALSE;
719 }
720
721 Status = SdMmcHcGetMaxCurrent (PciIo, Slot, &Private->MaxCurrent[Slot]);
722 if (EFI_ERROR (Status)) {
723 continue;
724 }
725
726 Private->Slot[Slot].SlotType = Private->Capability[Slot].SlotType;
727 if ((Private->Slot[Slot].SlotType != RemovableSlot) && (Private->Slot[Slot].SlotType != EmbeddedSlot)) {
728 DEBUG ((DEBUG_INFO, "SdMmcPciHcDxe doesn't support the slot type [%d]!!!\n", Private->Slot[Slot].SlotType));
729 continue;
730 }
731
732 //
733 // Reset the specified slot of the SD/MMC Pci Host Controller
734 //
735 Status = SdMmcHcReset (Private, Slot);
736 if (EFI_ERROR (Status)) {
737 continue;
738 }
739
740 //
741 // Check whether there is a SD/MMC card attached
742 //
743 if (Private->Slot[Slot].SlotType == RemovableSlot) {
744 Status = SdMmcHcCardDetect (PciIo, Slot, &MediaPresent);
745 if (EFI_ERROR (Status) && (Status != EFI_MEDIA_CHANGED)) {
746 continue;
747 } else if (!MediaPresent) {
748 DEBUG ((
749 DEBUG_INFO,
750 "SdMmcHcCardDetect: No device attached in Slot[%d]!!!\n",
751 Slot
752 ));
753 continue;
754 }
755 }
756
757 Status = SdMmcHcInitHost (Private, Slot);
758 if (EFI_ERROR (Status)) {
759 continue;
760 }
761
762 Private->Slot[Slot].MediaPresent = TRUE;
763 Private->Slot[Slot].Initialized = TRUE;
764 RoutineNum = sizeof (mCardTypeDetectRoutineTable) / sizeof (CARD_TYPE_DETECT_ROUTINE);
765 for (Index = 0; Index < RoutineNum; Index++) {
766 Routine = &mCardTypeDetectRoutineTable[Index];
767 if (*Routine != NULL) {
768 Status = (*Routine)(Private, Slot);
769 if (!EFI_ERROR (Status)) {
770 break;
771 }
772 }
773 }
774
775 //
776 // This card doesn't get initialized correctly.
777 //
778 if (Index == RoutineNum) {
779 Private->Slot[Slot].Initialized = FALSE;
780 }
781 }
782
783 //
784 // Enable 64-bit DMA support in the PCI layer if this controller
785 // supports it.
786 //
787 if (Support64BitDma) {
788 Status = PciIo->Attributes (
789 PciIo,
790 EfiPciIoAttributeOperationEnable,
791 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,
792 NULL
793 );
794 if (EFI_ERROR (Status)) {
795 DEBUG ((DEBUG_WARN, "SdMmcPciHcDriverBindingStart: failed to enable 64-bit DMA (%r)\n", Status));
796 }
797 }
798
799 //
800 // Start the asynchronous I/O monitor
801 //
802 Status = gBS->CreateEvent (
803 EVT_TIMER | EVT_NOTIFY_SIGNAL,
804 TPL_NOTIFY,
805 ProcessAsyncTaskList,
806 Private,
807 &Private->TimerEvent
808 );
809 if (EFI_ERROR (Status)) {
810 goto Done;
811 }
812
813 Status = gBS->SetTimer (Private->TimerEvent, TimerPeriodic, SD_MMC_HC_ASYNC_TIMER);
814 if (EFI_ERROR (Status)) {
815 goto Done;
816 }
817
818 //
819 // Start the Sd removable device connection enumeration
820 //
821 Status = gBS->CreateEvent (
822 EVT_TIMER | EVT_NOTIFY_SIGNAL,
823 TPL_CALLBACK,
824 SdMmcPciHcEnumerateDevice,
825 Private,
826 &Private->ConnectEvent
827 );
828 if (EFI_ERROR (Status)) {
829 goto Done;
830 }
831
832 Status = gBS->SetTimer (Private->ConnectEvent, TimerPeriodic, SD_MMC_HC_ENUM_TIMER);
833 if (EFI_ERROR (Status)) {
834 goto Done;
835 }
836
837 Status = gBS->InstallMultipleProtocolInterfaces (
838 &Controller,
839 &gEfiSdMmcPassThruProtocolGuid,
840 &(Private->PassThru),
841 NULL
842 );
843
844 DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStart: %r End on %x\n", Status, Controller));
845
846 Done:
847 if (EFI_ERROR (Status)) {
848 if ((Private != NULL) && (Private->PciAttributes != 0)) {
849 //
850 // Restore original PCI attributes
851 //
852 PciIo->Attributes (
853 PciIo,
854 EfiPciIoAttributeOperationSet,
855 Private->PciAttributes,
856 NULL
857 );
858 }
859
860 gBS->CloseProtocol (
861 Controller,
862 &gEfiPciIoProtocolGuid,
863 This->DriverBindingHandle,
864 Controller
865 );
866
867 if ((Private != NULL) && (Private->TimerEvent != NULL)) {
868 gBS->CloseEvent (Private->TimerEvent);
869 }
870
871 if ((Private != NULL) && (Private->ConnectEvent != NULL)) {
872 gBS->CloseEvent (Private->ConnectEvent);
873 }
874
875 if (Private != NULL) {
876 FreePool (Private);
877 }
878 }
879
880 return Status;
881 }
882
883 /**
884 Stops a device controller or a bus controller.
885
886 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
887 As a result, much of the error checking on the parameters to Stop() has been moved
888 into this common boot service. It is legal to call Stop() from other locations,
889 but the following calling restrictions must be followed or the system behavior will not be deterministic.
890 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
891 same driver's Start() function.
892 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
893 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
894 Start() function, and the Start() function must have called OpenProtocol() on
895 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
896
897 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
898 @param[in] ControllerHandle A handle to the device being stopped. The handle must
899 support a bus specific I/O protocol for the driver
900 to use to stop the device.
901 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
902 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
903 if NumberOfChildren is 0.
904
905 @retval EFI_SUCCESS The device was stopped.
906 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
907
908 **/
909 EFI_STATUS
910 EFIAPI
911 SdMmcPciHcDriverBindingStop (
912 IN EFI_DRIVER_BINDING_PROTOCOL *This,
913 IN EFI_HANDLE Controller,
914 IN UINTN NumberOfChildren,
915 IN EFI_HANDLE *ChildHandleBuffer
916 )
917 {
918 EFI_STATUS Status;
919 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
920 SD_MMC_HC_PRIVATE_DATA *Private;
921 EFI_PCI_IO_PROTOCOL *PciIo;
922 LIST_ENTRY *Link;
923 LIST_ENTRY *NextLink;
924 SD_MMC_HC_TRB *Trb;
925
926 DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStop: Start\n"));
927
928 Status = gBS->OpenProtocol (
929 Controller,
930 &gEfiSdMmcPassThruProtocolGuid,
931 (VOID **)&PassThru,
932 This->DriverBindingHandle,
933 Controller,
934 EFI_OPEN_PROTOCOL_GET_PROTOCOL
935 );
936 if (EFI_ERROR (Status)) {
937 return Status;
938 }
939
940 Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
941 //
942 // Close Non-Blocking timer and free Task list.
943 //
944 if (Private->TimerEvent != NULL) {
945 gBS->CloseEvent (Private->TimerEvent);
946 Private->TimerEvent = NULL;
947 }
948
949 if (Private->ConnectEvent != NULL) {
950 gBS->CloseEvent (Private->ConnectEvent);
951 Private->ConnectEvent = NULL;
952 }
953
954 //
955 // As the timer is closed, there is no needs to use TPL lock to
956 // protect the critical region "queue".
957 //
958 for (Link = GetFirstNode (&Private->Queue);
959 !IsNull (&Private->Queue, Link);
960 Link = NextLink)
961 {
962 NextLink = GetNextNode (&Private->Queue, Link);
963 RemoveEntryList (Link);
964 Trb = SD_MMC_HC_TRB_FROM_THIS (Link);
965 Trb->Packet->TransactionStatus = EFI_ABORTED;
966 gBS->SignalEvent (Trb->Event);
967 SdMmcFreeTrb (Trb);
968 }
969
970 //
971 // Uninstall Block I/O protocol from the device handle
972 //
973 Status = gBS->UninstallProtocolInterface (
974 Controller,
975 &gEfiSdMmcPassThruProtocolGuid,
976 &(Private->PassThru)
977 );
978
979 if (EFI_ERROR (Status)) {
980 return Status;
981 }
982
983 gBS->CloseProtocol (
984 Controller,
985 &gEfiPciIoProtocolGuid,
986 This->DriverBindingHandle,
987 Controller
988 );
989 //
990 // Restore original PCI attributes
991 //
992 PciIo = Private->PciIo;
993 Status = PciIo->Attributes (
994 PciIo,
995 EfiPciIoAttributeOperationSet,
996 Private->PciAttributes,
997 NULL
998 );
999 ASSERT_EFI_ERROR (Status);
1000
1001 FreePool (Private);
1002
1003 DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStop: End with %r\n", Status));
1004
1005 return Status;
1006 }
1007
1008 /**
1009 Execute TRB synchronously.
1010
1011 @param[in] Private Pointer to driver private data.
1012 @param[in] Trb Pointer to TRB to execute.
1013
1014 @retval EFI_SUCCESS TRB executed successfully.
1015 @retval Other TRB failed.
1016 **/
1017 EFI_STATUS
1018 SdMmcPassThruExecSyncTrb (
1019 IN SD_MMC_HC_PRIVATE_DATA *Private,
1020 IN SD_MMC_HC_TRB *Trb
1021 )
1022 {
1023 EFI_STATUS Status;
1024 EFI_TPL OldTpl;
1025
1026 //
1027 // Wait async I/O list is empty before execute sync I/O operation.
1028 //
1029 while (TRUE) {
1030 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1031 if (IsListEmpty (&Private->Queue)) {
1032 gBS->RestoreTPL (OldTpl);
1033 break;
1034 }
1035
1036 gBS->RestoreTPL (OldTpl);
1037 }
1038
1039 while (Trb->Retries) {
1040 Status = SdMmcWaitTrbEnv (Private, Trb);
1041 if (EFI_ERROR (Status)) {
1042 return Status;
1043 }
1044
1045 Status = SdMmcExecTrb (Private, Trb);
1046 if (EFI_ERROR (Status)) {
1047 return Status;
1048 }
1049
1050 Status = SdMmcWaitTrbResult (Private, Trb);
1051 if (Status == EFI_CRC_ERROR) {
1052 Trb->Retries--;
1053 } else {
1054 return Status;
1055 }
1056 }
1057
1058 return Status;
1059 }
1060
1061 /**
1062 Sends SD command to an SD card that is attached to the SD controller.
1063
1064 The PassThru() function sends the SD command specified by Packet to the SD card
1065 specified by Slot.
1066
1067 If Packet is successfully sent to the SD card, then EFI_SUCCESS is returned.
1068
1069 If a device error occurs while sending the Packet, then EFI_DEVICE_ERROR is returned.
1070
1071 If Slot is not in a valid range for the SD controller, then EFI_INVALID_PARAMETER
1072 is returned.
1073
1074 If Packet defines a data command but both InDataBuffer and OutDataBuffer are NULL,
1075 EFI_INVALID_PARAMETER is returned.
1076
1077 @param[in] This A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
1078 @param[in] Slot The slot number of the SD card to send the command to.
1079 @param[in,out] Packet A pointer to the SD command data structure.
1080 @param[in] Event If Event is NULL, blocking I/O is performed. If Event is
1081 not NULL, then nonblocking I/O is performed, and Event
1082 will be signaled when the Packet completes.
1083
1084 @retval EFI_SUCCESS The SD Command Packet was sent by the host.
1085 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the SD
1086 command Packet.
1087 @retval EFI_INVALID_PARAMETER Packet, Slot, or the contents of the Packet is invalid.
1088 @retval EFI_INVALID_PARAMETER Packet defines a data command but both InDataBuffer and
1089 OutDataBuffer are NULL.
1090 @retval EFI_NO_MEDIA SD Device not present in the Slot.
1091 @retval EFI_UNSUPPORTED The command described by the SD Command Packet is not
1092 supported by the host controller.
1093 @retval EFI_BAD_BUFFER_SIZE The InTransferLength or OutTransferLength exceeds the
1094 limit supported by SD card ( i.e. if the number of bytes
1095 exceed the Last LBA).
1096
1097 **/
1098 EFI_STATUS
1099 EFIAPI
1100 SdMmcPassThruPassThru (
1101 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This,
1102 IN UINT8 Slot,
1103 IN OUT EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet,
1104 IN EFI_EVENT Event OPTIONAL
1105 )
1106 {
1107 EFI_STATUS Status;
1108 SD_MMC_HC_PRIVATE_DATA *Private;
1109 SD_MMC_HC_TRB *Trb;
1110
1111 if ((This == NULL) || (Packet == NULL)) {
1112 return EFI_INVALID_PARAMETER;
1113 }
1114
1115 if ((Packet->SdMmcCmdBlk == NULL) || (Packet->SdMmcStatusBlk == NULL)) {
1116 return EFI_INVALID_PARAMETER;
1117 }
1118
1119 if ((Packet->OutDataBuffer == NULL) && (Packet->OutTransferLength != 0)) {
1120 return EFI_INVALID_PARAMETER;
1121 }
1122
1123 if ((Packet->InDataBuffer == NULL) && (Packet->InTransferLength != 0)) {
1124 return EFI_INVALID_PARAMETER;
1125 }
1126
1127 Private = SD_MMC_HC_PRIVATE_FROM_THIS (This);
1128
1129 if (!Private->Slot[Slot].Enable) {
1130 return EFI_INVALID_PARAMETER;
1131 }
1132
1133 if (!Private->Slot[Slot].MediaPresent) {
1134 return EFI_NO_MEDIA;
1135 }
1136
1137 if (!Private->Slot[Slot].Initialized) {
1138 return EFI_DEVICE_ERROR;
1139 }
1140
1141 Trb = SdMmcCreateTrb (Private, Slot, Packet, Event);
1142 if (Trb == NULL) {
1143 return EFI_OUT_OF_RESOURCES;
1144 }
1145
1146 //
1147 // Immediately return for async I/O.
1148 //
1149 if (Event != NULL) {
1150 return EFI_SUCCESS;
1151 }
1152
1153 Status = SdMmcPassThruExecSyncTrb (Private, Trb);
1154
1155 SdMmcFreeTrb (Trb);
1156
1157 return Status;
1158 }
1159
1160 /**
1161 Used to retrieve next slot numbers supported by the SD controller. The function
1162 returns information about all available slots (populated or not-populated).
1163
1164 The GetNextSlot() function retrieves the next slot number on an SD controller.
1165 If on input Slot is 0xFF, then the slot number of the first slot on the SD controller
1166 is returned.
1167
1168 If Slot is a slot number that was returned on a previous call to GetNextSlot(), then
1169 the slot number of the next slot on the SD controller is returned.
1170
1171 If Slot is not 0xFF and Slot was not returned on a previous call to GetNextSlot(),
1172 EFI_INVALID_PARAMETER is returned.
1173
1174 If Slot is the slot number of the last slot on the SD controller, then EFI_NOT_FOUND
1175 is returned.
1176
1177 @param[in] This A pointer to the EFI_SD_MMMC_PASS_THRU_PROTOCOL instance.
1178 @param[in,out] Slot On input, a pointer to a slot number on the SD controller.
1179 On output, a pointer to the next slot number on the SD controller.
1180 An input value of 0xFF retrieves the first slot number on the SD
1181 controller.
1182
1183 @retval EFI_SUCCESS The next slot number on the SD controller was returned in Slot.
1184 @retval EFI_NOT_FOUND There are no more slots on this SD controller.
1185 @retval EFI_INVALID_PARAMETER Slot is not 0xFF and Slot was not returned on a previous call
1186 to GetNextSlot().
1187
1188 **/
1189 EFI_STATUS
1190 EFIAPI
1191 SdMmcPassThruGetNextSlot (
1192 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This,
1193 IN OUT UINT8 *Slot
1194 )
1195 {
1196 SD_MMC_HC_PRIVATE_DATA *Private;
1197 UINT8 Index;
1198
1199 if ((This == NULL) || (Slot == NULL)) {
1200 return EFI_INVALID_PARAMETER;
1201 }
1202
1203 Private = SD_MMC_HC_PRIVATE_FROM_THIS (This);
1204
1205 if (*Slot == 0xFF) {
1206 for (Index = 0; Index < SD_MMC_HC_MAX_SLOT; Index++) {
1207 if (Private->Slot[Index].Enable) {
1208 *Slot = Index;
1209 Private->PreviousSlot = Index;
1210 return EFI_SUCCESS;
1211 }
1212 }
1213
1214 return EFI_NOT_FOUND;
1215 } else if (*Slot == Private->PreviousSlot) {
1216 for (Index = *Slot + 1; Index < SD_MMC_HC_MAX_SLOT; Index++) {
1217 if (Private->Slot[Index].Enable) {
1218 *Slot = Index;
1219 Private->PreviousSlot = Index;
1220 return EFI_SUCCESS;
1221 }
1222 }
1223
1224 return EFI_NOT_FOUND;
1225 } else {
1226 return EFI_INVALID_PARAMETER;
1227 }
1228 }
1229
1230 /**
1231 Used to allocate and build a device path node for an SD card on the SD controller.
1232
1233 The BuildDevicePath() function allocates and builds a single device node for the SD
1234 card specified by Slot.
1235
1236 If the SD card specified by Slot is not present on the SD controller, then EFI_NOT_FOUND
1237 is returned.
1238
1239 If DevicePath is NULL, then EFI_INVALID_PARAMETER is returned.
1240
1241 If there are not enough resources to allocate the device path node, then EFI_OUT_OF_RESOURCES
1242 is returned.
1243
1244 Otherwise, DevicePath is allocated with the boot service AllocatePool(), the contents of
1245 DevicePath are initialized to describe the SD card specified by Slot, and EFI_SUCCESS is
1246 returned.
1247
1248 @param[in] This A pointer to the EFI_SD_MMMC_PASS_THRU_PROTOCOL instance.
1249 @param[in] Slot Specifies the slot number of the SD card for which a device
1250 path node is to be allocated and built.
1251 @param[in,out] DevicePath A pointer to a single device path node that describes the SD
1252 card specified by Slot. This function is responsible for
1253 allocating the buffer DevicePath with the boot service
1254 AllocatePool(). It is the caller's responsibility to free
1255 DevicePath when the caller is finished with DevicePath.
1256
1257 @retval EFI_SUCCESS The device path node that describes the SD card specified by
1258 Slot was allocated and returned in DevicePath.
1259 @retval EFI_NOT_FOUND The SD card specified by Slot does not exist on the SD controller.
1260 @retval EFI_INVALID_PARAMETER DevicePath is NULL.
1261 @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate DevicePath.
1262
1263 **/
1264 EFI_STATUS
1265 EFIAPI
1266 SdMmcPassThruBuildDevicePath (
1267 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This,
1268 IN UINT8 Slot,
1269 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
1270 )
1271 {
1272 SD_MMC_HC_PRIVATE_DATA *Private;
1273 SD_DEVICE_PATH *SdNode;
1274 EMMC_DEVICE_PATH *EmmcNode;
1275
1276 if ((This == NULL) || (DevicePath == NULL) || (Slot >= SD_MMC_HC_MAX_SLOT)) {
1277 return EFI_INVALID_PARAMETER;
1278 }
1279
1280 Private = SD_MMC_HC_PRIVATE_FROM_THIS (This);
1281
1282 if ((!Private->Slot[Slot].Enable) || (!Private->Slot[Slot].MediaPresent)) {
1283 return EFI_NOT_FOUND;
1284 }
1285
1286 if (Private->Slot[Slot].CardType == SdCardType) {
1287 SdNode = AllocateCopyPool (sizeof (SD_DEVICE_PATH), &mSdDpTemplate);
1288 if (SdNode == NULL) {
1289 return EFI_OUT_OF_RESOURCES;
1290 }
1291
1292 SdNode->SlotNumber = Slot;
1293
1294 *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)SdNode;
1295 } else if (Private->Slot[Slot].CardType == EmmcCardType) {
1296 EmmcNode = AllocateCopyPool (sizeof (EMMC_DEVICE_PATH), &mEmmcDpTemplate);
1297 if (EmmcNode == NULL) {
1298 return EFI_OUT_OF_RESOURCES;
1299 }
1300
1301 EmmcNode->SlotNumber = Slot;
1302
1303 *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)EmmcNode;
1304 } else {
1305 //
1306 // Currently we only support SD and EMMC two device nodes.
1307 //
1308 return EFI_NOT_FOUND;
1309 }
1310
1311 return EFI_SUCCESS;
1312 }
1313
1314 /**
1315 This function retrieves an SD card slot number based on the input device path.
1316
1317 The GetSlotNumber() function retrieves slot number for the SD card specified by
1318 the DevicePath node. If DevicePath is NULL, EFI_INVALID_PARAMETER is returned.
1319
1320 If DevicePath is not a device path node type that the SD Pass Thru driver supports,
1321 EFI_UNSUPPORTED is returned.
1322
1323 @param[in] This A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
1324 @param[in] DevicePath A pointer to the device path node that describes a SD
1325 card on the SD controller.
1326 @param[out] Slot On return, points to the slot number of an SD card on
1327 the SD controller.
1328
1329 @retval EFI_SUCCESS SD card slot number is returned in Slot.
1330 @retval EFI_INVALID_PARAMETER Slot or DevicePath is NULL.
1331 @retval EFI_UNSUPPORTED DevicePath is not a device path node type that the SD
1332 Pass Thru driver supports.
1333
1334 **/
1335 EFI_STATUS
1336 EFIAPI
1337 SdMmcPassThruGetSlotNumber (
1338 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This,
1339 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1340 OUT UINT8 *Slot
1341 )
1342 {
1343 SD_MMC_HC_PRIVATE_DATA *Private;
1344 SD_DEVICE_PATH *SdNode;
1345 EMMC_DEVICE_PATH *EmmcNode;
1346 UINT8 SlotNumber;
1347
1348 if ((This == NULL) || (DevicePath == NULL) || (Slot == NULL)) {
1349 return EFI_INVALID_PARAMETER;
1350 }
1351
1352 Private = SD_MMC_HC_PRIVATE_FROM_THIS (This);
1353
1354 //
1355 // Check whether the DevicePath belongs to SD_DEVICE_PATH or EMMC_DEVICE_PATH
1356 //
1357 if ((DevicePath->Type != MESSAGING_DEVICE_PATH) ||
1358 ((DevicePath->SubType != MSG_SD_DP) &&
1359 (DevicePath->SubType != MSG_EMMC_DP)) ||
1360 (DevicePathNodeLength (DevicePath) != sizeof (SD_DEVICE_PATH)) ||
1361 (DevicePathNodeLength (DevicePath) != sizeof (EMMC_DEVICE_PATH)))
1362 {
1363 return EFI_UNSUPPORTED;
1364 }
1365
1366 if (DevicePath->SubType == MSG_SD_DP) {
1367 SdNode = (SD_DEVICE_PATH *)DevicePath;
1368 SlotNumber = SdNode->SlotNumber;
1369 } else {
1370 EmmcNode = (EMMC_DEVICE_PATH *)DevicePath;
1371 SlotNumber = EmmcNode->SlotNumber;
1372 }
1373
1374 if (SlotNumber >= SD_MMC_HC_MAX_SLOT) {
1375 return EFI_NOT_FOUND;
1376 }
1377
1378 if (Private->Slot[SlotNumber].Enable) {
1379 *Slot = SlotNumber;
1380 return EFI_SUCCESS;
1381 } else {
1382 return EFI_NOT_FOUND;
1383 }
1384 }
1385
1386 /**
1387 Resets an SD card that is connected to the SD controller.
1388
1389 The ResetDevice() function resets the SD card specified by Slot.
1390
1391 If this SD controller does not support a device reset operation, EFI_UNSUPPORTED is
1392 returned.
1393
1394 If Slot is not in a valid slot number for this SD controller, EFI_INVALID_PARAMETER
1395 is returned.
1396
1397 If the device reset operation is completed, EFI_SUCCESS is returned.
1398
1399 @param[in] This A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
1400 @param[in] Slot Specifies the slot number of the SD card to be reset.
1401
1402 @retval EFI_SUCCESS The SD card specified by Slot was reset.
1403 @retval EFI_UNSUPPORTED The SD controller does not support a device reset operation.
1404 @retval EFI_INVALID_PARAMETER Slot number is invalid.
1405 @retval EFI_NO_MEDIA SD Device not present in the Slot.
1406 @retval EFI_DEVICE_ERROR The reset command failed due to a device error
1407
1408 **/
1409 EFI_STATUS
1410 EFIAPI
1411 SdMmcPassThruResetDevice (
1412 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This,
1413 IN UINT8 Slot
1414 )
1415 {
1416 SD_MMC_HC_PRIVATE_DATA *Private;
1417 LIST_ENTRY *Link;
1418 LIST_ENTRY *NextLink;
1419 SD_MMC_HC_TRB *Trb;
1420 EFI_TPL OldTpl;
1421
1422 if (This == NULL) {
1423 return EFI_INVALID_PARAMETER;
1424 }
1425
1426 Private = SD_MMC_HC_PRIVATE_FROM_THIS (This);
1427
1428 if (!Private->Slot[Slot].Enable) {
1429 return EFI_INVALID_PARAMETER;
1430 }
1431
1432 if (!Private->Slot[Slot].MediaPresent) {
1433 return EFI_NO_MEDIA;
1434 }
1435
1436 if (!Private->Slot[Slot].Initialized) {
1437 return EFI_DEVICE_ERROR;
1438 }
1439
1440 //
1441 // Free all async I/O requests in the queue
1442 //
1443 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1444
1445 for (Link = GetFirstNode (&Private->Queue);
1446 !IsNull (&Private->Queue, Link);
1447 Link = NextLink)
1448 {
1449 NextLink = GetNextNode (&Private->Queue, Link);
1450 RemoveEntryList (Link);
1451 Trb = SD_MMC_HC_TRB_FROM_THIS (Link);
1452 Trb->Packet->TransactionStatus = EFI_ABORTED;
1453 gBS->SignalEvent (Trb->Event);
1454 SdMmcFreeTrb (Trb);
1455 }
1456
1457 gBS->RestoreTPL (OldTpl);
1458
1459 return EFI_SUCCESS;
1460 }