+++ /dev/null
-/** @file\r
-* PCIe Sata support for the Silicon Image I3132\r
-*\r
-* Copyright (c) 2011-2015, ARM Limited. All rights reserved.\r
-*\r
-* SPDX-License-Identifier: BSD-2-Clause-Patent\r
-*\r
-**/\r
-\r
-#include "SataSiI3132.h"\r
-\r
-#include <IndustryStandard/Acpi10.h>\r
-\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/DxeServicesTableLib.h>\r
-#include <Library/BaseLib.h>\r
-\r
-#define ACPI_SPECFLAG_PREFETCHABLE 0x06\r
-\r
-EFI_DRIVER_BINDING_PROTOCOL\r
-gSataSiI3132DriverBinding = {\r
- SataSiI3132DriverBindingSupported,\r
- SataSiI3132DriverBindingStart,\r
- SataSiI3132DriverBindingStop,\r
- 0x30,\r
- NULL,\r
- NULL\r
-};\r
-\r
-EFI_STATUS\r
-SataSiI3132PortConstructor (\r
- IN SATA_SI3132_INSTANCE *SataSiI3132Instance,\r
- IN UINTN Index\r
- )\r
-{\r
- EFI_STATUS Status;\r
- SATA_SI3132_PORT *Port;\r
- VOID *HostPRB;\r
- EFI_PHYSICAL_ADDRESS PhysAddrHostPRB;\r
- VOID *PciAllocMappingPRB;\r
- UINTN NumberOfBytes;\r
-\r
- Port = &(SataSiI3132Instance->Ports[Index]);\r
-\r
- Port->Index = Index;\r
- Port->RegBase = Index * 0x2000;\r
- Port->Instance = SataSiI3132Instance;\r
- InitializeListHead (&(Port->Devices));\r
-\r
- NumberOfBytes = sizeof (SATA_SI3132_PRB);\r
- Status = SataSiI3132Instance->PciIo->AllocateBuffer (\r
- SataSiI3132Instance->PciIo, AllocateAnyPages, EfiBootServicesData,\r
- EFI_SIZE_TO_PAGES (NumberOfBytes), &HostPRB, 0\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- // Check the alignment of the PCI Buffer\r
- ASSERT (((UINTN)HostPRB & (0x1000 - 1)) == 0);\r
- Status = SataSiI3132Instance->PciIo->Map (\r
- SataSiI3132Instance->PciIo, EfiPciIoOperationBusMasterCommonBuffer, HostPRB,\r
- &NumberOfBytes, &PhysAddrHostPRB, &PciAllocMappingPRB\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- Port->HostPRB = HostPRB;\r
- Port->PhysAddrHostPRB = PhysAddrHostPRB;\r
- Port->PciAllocMappingPRB = PciAllocMappingPRB;\r
-\r
- return Status;\r
-}\r
-\r
-STATIC\r
-EFI_STATUS\r
-SataSiI3132Constructor (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- OUT SATA_SI3132_INSTANCE** SataSiI3132Instance\r
- )\r
-{\r
- SATA_SI3132_INSTANCE *Instance;\r
- EFI_ATA_PASS_THRU_MODE *AtaPassThruMode;\r
-\r
- if (!SataSiI3132Instance) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Instance = (SATA_SI3132_INSTANCE*)AllocateZeroPool (sizeof (SATA_SI3132_INSTANCE));\r
- if (Instance == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- Instance->Signature = SATA_SII3132_SIGNATURE;\r
- Instance->PciIo = PciIo;\r
-\r
- AtaPassThruMode = (EFI_ATA_PASS_THRU_MODE*)AllocatePool (sizeof (EFI_ATA_PASS_THRU_MODE));\r
- AtaPassThruMode->Attributes = EFI_ATA_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_ATA_PASS_THRU_ATTRIBUTES_LOGICAL;\r
- AtaPassThruMode->IoAlign = 0x1000;\r
-\r
- // Initialize SiI3132 ports\r
- SataSiI3132PortConstructor (Instance, 0);\r
- SataSiI3132PortConstructor (Instance, 1);\r
-\r
- // Set ATA Pass Thru Protocol\r
- Instance->AtaPassThruProtocol.Mode = AtaPassThruMode;\r
- Instance->AtaPassThruProtocol.PassThru = SiI3132AtaPassThru;\r
- Instance->AtaPassThruProtocol.GetNextPort = SiI3132GetNextPort;\r
- Instance->AtaPassThruProtocol.GetNextDevice = SiI3132GetNextDevice;\r
- Instance->AtaPassThruProtocol.BuildDevicePath = SiI3132BuildDevicePath;\r
- Instance->AtaPassThruProtocol.GetDevice = SiI3132GetDevice;\r
- Instance->AtaPassThruProtocol.ResetPort = SiI3132ResetPort;\r
- Instance->AtaPassThruProtocol.ResetDevice = SiI3132ResetDevice;\r
-\r
- *SataSiI3132Instance = Instance;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-SiI3132SoftResetCommand (\r
- IN SATA_SI3132_PORT *Port,\r
- OUT UINT32* Signature\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_ATA_PASS_THRU_COMMAND_PACKET Packet;\r
- EFI_ATA_STATUS_BLOCK Asb;\r
- EFI_ATA_COMMAND_BLOCK Acb;\r
- CONST UINT16 PortMultiplierPort = 0;\r
-\r
- ZeroMem (&Acb, sizeof (EFI_ATA_COMMAND_BLOCK));\r
-\r
- Acb.Reserved1[1] = 0;\r
-\r
- Packet.Asb = &Asb;\r
- Packet.Acb = &Acb;\r
- Packet.Timeout = 100000;\r
- Packet.Protocol = EFI_ATA_PASS_THRU_PROTOCOL_ATA_SOFTWARE_RESET;\r
-\r
- Status = SiI3132AtaPassThruCommand (Port->Instance, Port, PortMultiplierPort, &Packet, 0);\r
-\r
- if (Status == EFI_SUCCESS) {\r
- *Signature = (Asb.AtaCylinderHigh << 24) | (Asb.AtaCylinderLow << 16) |\r
- (Asb.AtaSectorNumber << 8 ) | (Asb.AtaSectorCount);\r
- }\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-SataSiI3132PortInitialization (\r
- IN SATA_SI3132_PORT *Port\r
- )\r
-{\r
- UINT32 Value32;\r
- SATA_SI3132_DEVICE* Device;\r
- UINT32 Signature;\r
- EFI_STATUS Status;\r
- EFI_PCI_IO_PROTOCOL* PciIo;\r
-\r
- Status = SiI3132HwResetPort (Port);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- PciIo = Port->Instance->PciIo;\r
-\r
- // Is a device is present ?\r
- Status = SATA_PORT_READ32 (Port->RegBase + SII3132_PORT_SSTATUS_REG, &Value32);\r
- if (!EFI_ERROR (Status) && (Value32 & 0x3)) {\r
- // Do a soft reset to see if it is a port multiplier\r
- SATA_TRACE ("SataSiI3132PortInitialization: soft reset - it is a port multiplier\n");\r
- Status = SiI3132SoftResetCommand (Port, &Signature);\r
- if (!EFI_ERROR (Status)) {\r
- if (Signature == SII3132_PORT_SIGNATURE_PMP) {\r
- SATA_TRACE ("SataSiI3132PortInitialization(): a Port Multiplier is present");\r
- if (FeaturePcdGet (PcdSataSiI3132FeaturePMPSupport)) {\r
- ASSERT (0); // Not supported yet\r
- } else {\r
- return EFI_UNSUPPORTED;\r
- }\r
- } else if (Signature == SII3132_PORT_SIGNATURE_ATAPI) {\r
- ASSERT (0); // Not supported yet\r
- SATA_TRACE ("SataSiI3132PortInitialization(): an ATAPI device is present");\r
- return EFI_UNSUPPORTED;\r
- } else if (Signature == SII3132_PORT_SIGNATURE_ATA) {\r
- SATA_TRACE ("SataSiI3132PortInitialization(): an ATA device is present");\r
- } else {\r
- SATA_TRACE ("SataSiI3132PortInitialization(): Present device unknown!");\r
- ASSERT (0); // Not supported\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- // Create Device\r
- Device = (SATA_SI3132_DEVICE*)AllocatePool (sizeof (SATA_SI3132_DEVICE));\r
- Device->Index = Port->Index; //TODO: Could need to be fixed when SATA Port Multiplier support\r
- Device->Port = Port;\r
- Device->BlockSize = 0;\r
-\r
- // Attached the device to the Sata Port\r
- InsertTailList (&Port->Devices, &Device->Link);\r
-\r
- SATA_TRACE ("SataSiI3132PortInitialization(): Port Ready");\r
- }\r
- }\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-SataSiI3132Initialization (\r
- IN SATA_SI3132_INSTANCE* SataSiI3132Instance\r
- )\r
-{\r
- UINTN Index;\r
- EFI_PCI_IO_PROTOCOL* PciIo;\r
-\r
- if (!SataSiI3132Instance) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- PciIo = SataSiI3132Instance->PciIo;\r
-\r
- // Turn Off GPIO\r
- SATA_GLOBAL_WRITE32 (SII3132_GLOBAL_FLASHADDR_REG, 0x0);\r
-\r
- // Clear Global Control Register\r
- SATA_GLOBAL_WRITE32 (SII3132_GLOBAL_CONTROL_REG, 0x0);\r
-\r
- for (Index = 0; Index < SATA_SII3132_MAXPORT; Index++) {\r
- SataSiI3132PortInitialization (&(SataSiI3132Instance->Ports[Index]));\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Test to see if this driver supports ControllerHandle.\r
-\r
- @param This Protocol instance pointer.\r
- @param Controller Handle of device to test.\r
- @param RemainingDevicePath Not used.\r
-\r
- @return EFI_SUCCESS This driver supports this device.\r
- @return EFI_UNSUPPORTED This driver does not support this device.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-SataSiI3132DriverBindingSupported (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
- UINT32 PciID;\r
-\r
- //\r
- // Test whether there is PCI IO Protocol attached on the controller handle.\r
- //\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- (VOID **) &PciIo,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- Status = PciIo->Pci.Read (\r
- PciIo,\r
- EfiPciIoWidthUint32,\r
- PCI_VENDOR_ID_OFFSET,\r
- 1,\r
- &PciID\r
- );\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_UNSUPPORTED;\r
- goto ON_EXIT;\r
- }\r
-\r
- //\r
- // Test whether the controller belongs to SATA Mass Storage type\r
- //\r
- if (PciID != ((SATA_SII3132_DEVICE_ID << 16) | SATA_SII3132_VENDOR_ID)) {\r
- Status = EFI_UNSUPPORTED;\r
- }\r
-\r
-ON_EXIT:\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
-\r
- return Status;\r
-}\r
-\r
-BOOLEAN mbStarted = FALSE;\r
-\r
-/**\r
- Starting the Pci SATA Driver.\r
-\r
- @param This Protocol instance pointer.\r
- @param Controller Handle of device to test.\r
- @param RemainingDevicePath Not used.\r
-\r
- @return EFI_SUCCESS supports this device.\r
- @return EFI_UNSUPPORTED do not support this device.\r
- @return EFI_DEVICE_ERROR cannot be started due to device Error.\r
- @return EFI_OUT_OF_RESOURCES cannot allocate resources.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-SataSiI3132DriverBindingStart (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
- UINT64 Supports;\r
- UINT64 OriginalPciAttributes;\r
- BOOLEAN PciAttributesSaved;\r
- UINT32 PciID;\r
- SATA_SI3132_INSTANCE *SataSiI3132Instance = NULL;\r
-\r
- SATA_TRACE ("SataSiI3132DriverBindingStart()");\r
-\r
- //TODO: Find a nicer way to do it !\r
- if (mbStarted) {\r
- return EFI_SUCCESS; // Don't restart me !\r
- }\r
-\r
- //\r
- // Open the PciIo Protocol\r
- //\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- (VOID **) &PciIo,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- PciAttributesSaved = FALSE;\r
- //\r
- // Save original PCI attributes\r
- //\r
- Status = PciIo->Attributes (\r
- PciIo,\r
- EfiPciIoAttributeOperationGet,\r
- 0,\r
- &OriginalPciAttributes\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto CLOSE_PCIIO;\r
- }\r
- PciAttributesSaved = TRUE;\r
-\r
- Status = PciIo->Attributes (\r
- PciIo,\r
- EfiPciIoAttributeOperationSupported,\r
- 0,\r
- &Supports\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- Supports &= EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;\r
- Status = PciIo->Attributes (\r
- PciIo,\r
- EfiPciIoAttributeOperationEnable,\r
- Supports,\r
- NULL\r
- );\r
- }\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "SataSiI3132DriverBindingStart: failed to enable controller\n"));\r
- goto CLOSE_PCIIO;\r
- }\r
-\r
- //\r
- // Get the Pci device class code.\r
- //\r
- Status = PciIo->Pci.Read (\r
- PciIo,\r
- EfiPciIoWidthUint32,\r
- PCI_VENDOR_ID_OFFSET,\r
- 1,\r
- &PciID\r
- );\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_UNSUPPORTED;\r
- goto CLOSE_PCIIO;\r
- }\r
-\r
- //\r
- // Test whether the controller belongs to SATA Mass Storage type\r
- //\r
- if (PciID != ((SATA_SII3132_DEVICE_ID << 16) | SATA_SII3132_VENDOR_ID)) {\r
- Status = EFI_UNSUPPORTED;\r
- goto CLOSE_PCIIO;\r
- }\r
-\r
- // Create SiI3132 Sata Instance\r
- Status = SataSiI3132Constructor (PciIo, &SataSiI3132Instance);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- // Initialize SiI3132 Sata Controller\r
- Status = SataSiI3132Initialization (SataSiI3132Instance);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- // Install Ata Pass Thru Protocol\r
- Status = gBS->InstallProtocolInterface (\r
- &Controller,\r
- &gEfiAtaPassThruProtocolGuid,\r
- EFI_NATIVE_INTERFACE,\r
- &(SataSiI3132Instance->AtaPassThruProtocol)\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto FREE_POOL;\r
- }\r
-\r
-/* //\r
- // Create event to stop the HC when exit boot service.\r
- //\r
- Status = gBS->CreateEventEx (\r
- EVT_NOTIFY_SIGNAL,\r
- TPL_NOTIFY,\r
- EhcExitBootService,\r
- Ehc,\r
- &gEfiEventExitBootServicesGuid,\r
- &Ehc->ExitBootServiceEvent\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto UNINSTALL_USBHC;\r
- }*/\r
-\r
- mbStarted = TRUE;\r
-\r
- SATA_TRACE ("SataSiI3132DriverBindingStart() Success!");\r
- return EFI_SUCCESS;\r
-\r
-FREE_POOL:\r
- //TODO: Free SATA Instance\r
-\r
-CLOSE_PCIIO:\r
- if (PciAttributesSaved) {\r
- //\r
- // Restore original PCI attributes\r
- //\r
- PciIo->Attributes (\r
- PciIo,\r
- EfiPciIoAttributeOperationSet,\r
- OriginalPciAttributes,\r
- NULL\r
- );\r
- }\r
-\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Stop this driver on ControllerHandle. Support stopping any child handles\r
- created by this driver.\r
-\r
- @param This Protocol instance pointer.\r
- @param Controller Handle of device to stop driver on.\r
- @param NumberOfChildren Number of Children in the ChildHandleBuffer.\r
- @param ChildHandleBuffer List of handles for the children we need to stop.\r
-\r
- @return EFI_SUCCESS Success.\r
- @return EFI_DEVICE_ERROR Fail.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-SataSiI3132DriverBindingStop (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN UINTN NumberOfChildren,\r
- IN EFI_HANDLE *ChildHandleBuffer\r
- )\r
-{\r
- SATA_TRACE ("SataSiI3132DriverBindingStop()");\r
- return EFI_UNSUPPORTED;\r
-}\r
-\r
-/**\r
- Entry point of this driver\r
-\r
- @param ImageHandle Handle of driver image\r
- @param SystemTable Point to EFI_SYSTEM_TABLE\r
-\r
- @retval EFI_OUT_OF_RESOURCES Can not allocate memory resource\r
- @retval EFI_DEVICE_ERROR Can not install the protocol instance\r
- @retval EFI_SUCCESS Success to initialize the Pci host bridge.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-InitializeSataSiI3132 (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- )\r
-{\r
- SATA_TRACE ("InitializeSataSiI3132 ()");\r
-\r
- return EfiLibInstallDriverBindingComponentName2 (\r
- ImageHandle,\r
- SystemTable,\r
- &gSataSiI3132DriverBinding,\r
- ImageHandle,\r
- &gSataSiI3132ComponentName,\r
- &gSataSiI3132ComponentName2\r
- );\r
-}\r