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