audk/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/SDMediaDevice.c

318 lines
8.8 KiB
C

/** @file
The definition for SD media device driver model and blkio protocol routines.
Copyright (c) 2013-2016 Intel Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "SDMediaDevice.h"
EFI_DRIVER_BINDING_PROTOCOL gSDMediaDeviceDriverBinding = {
SDMediaDeviceSupported,
SDMediaDeviceStart,
SDMediaDeviceStop,
0x20,
NULL,
NULL
};
/**
Entry point for EFI drivers.
@param ImageHandle EFI_HANDLE.
@param SystemTable EFI_SYSTEM_TABLE.
@retval EFI_SUCCESS Driver is successfully loaded.
@return Others Failed.
**/
EFI_STATUS
EFIAPI
InitializeSDMediaDevice (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
return EfiLibInstallDriverBindingComponentName2 (
ImageHandle,
SystemTable,
&gSDMediaDeviceDriverBinding,
ImageHandle,
&gSDMediaDeviceName,
&gSDMediaDeviceName2
);
}
/**
Test to see if this driver supports ControllerHandle. Any
ControllerHandle that has BlockIoProtocol installed will be supported.
@param This Protocol instance pointer.
@param Controller Handle of device to test.
@param RemainingDevicePath Not used.
@return EFI_SUCCESS This driver supports this device.
@return EFI_UNSUPPORTED This driver does not support this device.
**/
EFI_STATUS
EFIAPI
SDMediaDeviceSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
{
EFI_STATUS Status;
EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
//
// Test whether there is PCI IO Protocol attached on the controller handle.
//
Status = gBS->OpenProtocol (
Controller,
&gEfiSDHostIoProtocolGuid,
(VOID **)&SDHostIo,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
goto Exit;
}
gBS->CloseProtocol (
Controller,
&gEfiSDHostIoProtocolGuid,
This->DriverBindingHandle,
Controller
);
Exit:
return Status;
}
/**
Starting the SD Media Device Driver.
@param This Protocol instance pointer.
@param Controller Handle of device to test.
@param RemainingDevicePath Not used.
@retval EFI_SUCCESS This driver supports this device.
@retval EFI_UNSUPPORTED This driver does not support this device.
@retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
**/
EFI_STATUS
EFIAPI
SDMediaDeviceStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
{
EFI_STATUS Status;
EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
CARD_DATA *CardData;
CardData = NULL;
//
// Open PCI I/O Protocol and save pointer to open protocol
// in private data area.
//
Status = gBS->OpenProtocol (
Controller,
&gEfiSDHostIoProtocolGuid,
(VOID **) &SDHostIo,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "SDMediaDeviceStart: Fail to open gEfiSDHostIoProtocolGuid \r\n"));
goto Exit;
}
Status = SDHostIo->DetectCardAndInitHost (SDHostIo);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_INFO, "SDMediaDeviceStart: Fail to DetectCardAndInitHost \r\n"));
goto Exit;
}
CardData = (CARD_DATA*)AllocateZeroPool(sizeof (CARD_DATA));
if (CardData == NULL) {
Status = EFI_OUT_OF_RESOURCES;
DEBUG ((EFI_D_ERROR, "SDMediaDeviceStart: Fail to AllocateZeroPool(CARD_DATA) \r\n"));
goto Exit;
}
ASSERT (SDHostIo->HostCapability.BoundarySize >= 4 * 1024);
CardData->RawBufferPointer = (UINT8*)((UINTN)DMA_MEMORY_TOP);
Status = gBS->AllocatePages (
AllocateMaxAddress,
EfiBootServicesData,
EFI_SIZE_TO_PAGES (2 * SDHostIo->HostCapability.BoundarySize),
(EFI_PHYSICAL_ADDRESS *)(&CardData->RawBufferPointer)
);
if (CardData->RawBufferPointer == NULL) {
DEBUG ((EFI_D_ERROR, "SDMediaDeviceStart: Fail to AllocateZeroPool(2*x) \r\n"));
Status = EFI_OUT_OF_RESOURCES;
goto Exit;
}
CardData->AlignedBuffer = CardData->RawBufferPointer - ((UINTN)(CardData->RawBufferPointer) & (SDHostIo->HostCapability.BoundarySize - 1)) + SDHostIo->HostCapability.BoundarySize;
CardData->Signature = CARD_DATA_SIGNATURE;
CardData->SDHostIo = SDHostIo;
Status = MMCSDCardInit (CardData);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "SDMediaDeviceStart: Fail to MMCSDCardInit \r\n"));
goto Exit;
}
DEBUG ((EFI_D_INFO, "SDMediaDeviceStart: MMCSDCardInit SuccessFul\n"));
if (CardData->CardType == CEATACard) {
Status = CEATABlockIoInit (CardData);
} else {
Status = MMCSDBlockIoInit (CardData);
}
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "SDMediaDeviceStart: Fail to BlockIoInit \r\n"));
goto Exit;
}
DEBUG ((EFI_D_INFO, "SDMediaDeviceStart: BlockIo is successfully installed\n"));
Status = gBS->InstallProtocolInterface (
&Controller,
&gEfiBlockIoProtocolGuid,
EFI_NATIVE_INTERFACE,
&CardData->BlockIo
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "SDMediaDeviceStart: Fail to install gEfiBlockIoProtocolGuid \r\n"));
goto Exit;
}
//
// Install the component name protocol
//
CardData->ControllerNameTable = NULL;
AddUnicodeString2 (
"eng",
gSDMediaDeviceName.SupportedLanguages,
&CardData->ControllerNameTable,
L"MMC/SD Media Device",
TRUE
);
AddUnicodeString2 (
"en",
gSDMediaDeviceName2.SupportedLanguages,
&CardData->ControllerNameTable,
L"MMC/SD Media Device",
FALSE
);
Exit:
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_INFO, "SDMediaDeviceStart: End with failure\r\n"));
if (CardData != NULL) {
if (CardData->RawBufferPointer != NULL) {
gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) CardData->RawBufferPointer, EFI_SIZE_TO_PAGES (2 * SDHostIo->HostCapability.BoundarySize));
}
FreePool (CardData);
}
}
return Status;
}
/**
Stop this driver on ControllerHandle. Support stopping any child handles
created by this driver.
@param This Protocol instance pointer.
@param Controller Handle of device to stop driver on.
@param NumberOfChildren Number of Children in the ChildHandleBuffer.
@param ChildHandleBuffer List of handles for the children we need to stop.
@return EFI_SUCCESS
@return others
**/
EFI_STATUS
EFIAPI
SDMediaDeviceStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
)
{
EFI_STATUS Status;
CARD_DATA *CardData;
EFI_BLOCK_IO_PROTOCOL *BlockIo;
//
// First find BlockIo Protocol
//
Status = gBS->OpenProtocol (
Controller,
&gEfiBlockIoProtocolGuid,
(VOID **)&BlockIo,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return Status;
}
CardData = CARD_DATA_FROM_THIS(BlockIo);
//
// Uninstall Block I/O protocol from the device handle
//
Status = gBS->UninstallProtocolInterface (
Controller,
&gEfiBlockIoProtocolGuid,
BlockIo
);
if (EFI_ERROR (Status)) {
return Status;
}
if (CardData != NULL) {
if (CardData->RawBufferPointer != NULL) {
gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) CardData->RawBufferPointer, EFI_SIZE_TO_PAGES (2 * CardData->SDHostIo->HostCapability.BoundarySize));
}
FreeUnicodeStringTable (CardData->ControllerNameTable);
FreePool (CardData);
}
gBS->CloseProtocol (
Controller,
&gEfiSDHostIoProtocolGuid,
This->DriverBindingHandle,
Controller
);
return EFI_SUCCESS;
}