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