diff --git a/DuetPkg/DuetPkg.fdf b/DuetPkg/DuetPkg.fdf
index ca7d2be203..ef4b5fee0b 100644
--- a/DuetPkg/DuetPkg.fdf
+++ b/DuetPkg/DuetPkg.fdf
@@ -1,7 +1,7 @@
## @file
# This is DUET FDF file with UEFI HII features enabled
#
-# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.
+# Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
@@ -82,9 +82,12 @@ INF DuetPkg/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf
INF IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPortDxe.inf
INF IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf
- # IDE Support
-INF IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf
-INF PcAtChipsetPkg/Bus/Pci/IdeControllerDxe/IdeControllerDxe.inf
+ # IDE/AHCI Support
+INF DuetPkg/SataControllerDxe/SataControllerDxe.inf
+INF MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
+INF MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
+INF MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
+INF MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
# Usb Support
INF MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf
diff --git a/DuetPkg/DuetPkgIa32.dsc b/DuetPkg/DuetPkgIa32.dsc
index 83d5688b66..825e0feeb8 100644
--- a/DuetPkg/DuetPkgIa32.dsc
+++ b/DuetPkg/DuetPkgIa32.dsc
@@ -4,7 +4,7 @@
# Developer's UEFI Emulation. DUET provides an EFI/UEFI IA32/X64 environment on legacy BIOS,
# to help developing and debugging native EFI/UEFI drivers.
#
-# Copyright (c) 2010 - 2010, Intel Corporation. All rights reserved.
+# Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
@@ -218,9 +218,12 @@
IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPortDxe.inf
IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf
- # IDE Support
- IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf
- PcAtChipsetPkg/Bus/Pci/IdeControllerDxe/IdeControllerDxe.inf
+ # IDE/AHCI Support
+ DuetPkg/SataControllerDxe/SataControllerDxe.inf
+ MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
+ MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
+ MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
+ MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
# Usb Support
MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf
diff --git a/DuetPkg/DuetPkgX64.dsc b/DuetPkg/DuetPkgX64.dsc
index 142af252ec..5ccf2a3675 100644
--- a/DuetPkg/DuetPkgX64.dsc
+++ b/DuetPkg/DuetPkgX64.dsc
@@ -4,7 +4,7 @@
# Developer's UEFI Emulation. DUET provides an EFI/UEFI IA32/X64 environment on legacy BIOS,
# to help developing and debugging native EFI/UEFI drivers.
#
-# Copyright (c) 2010 - 2010, Intel Corporation. All rights reserved.
+# Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
@@ -218,9 +218,12 @@
IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPortDxe.inf
IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf
- # IDE Support
- IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf
- PcAtChipsetPkg/Bus/Pci/IdeControllerDxe/IdeControllerDxe.inf
+ # IDE/AHCI Support
+ DuetPkg/SataControllerDxe/SataControllerDxe.inf
+ MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
+ MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
+ MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
+ MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
# Usb Support
MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf
diff --git a/DuetPkg/SataControllerDxe/ComponentName.c b/DuetPkg/SataControllerDxe/ComponentName.c
new file mode 100644
index 0000000000..57cd3c88d3
--- /dev/null
+++ b/DuetPkg/SataControllerDxe/ComponentName.c
@@ -0,0 +1,176 @@
+/** @file
+ UEFI Component Name(2) protocol implementation for Sata Controller driver.
+
+ Copyright (c) 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "SataController.h"
+
+//
+/// EFI Component Name Protocol
+///
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gSataControllerComponentName = {
+ SataControllerComponentNameGetDriverName,
+ SataControllerComponentNameGetControllerName,
+ "eng"
+};
+
+//
+/// EFI Component Name 2 Protocol
+///
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gSataControllerComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) SataControllerComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) SataControllerComponentNameGetControllerName,
+ "en"
+};
+
+//
+/// Driver Name Strings
+///
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSataControllerDriverNameTable[] = {
+ {
+ "eng;en",
+ (CHAR16 *)L"Sata Controller Init Driver"
+ },
+ {
+ NULL,
+ NULL
+ }
+};
+
+///
+/// Controller Name Strings
+///
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSataControllerControllerNameTable[] = {
+ {
+ "eng;en",
+ (CHAR16 *)L"Sata Controller"
+ },
+ {
+ NULL,
+ NULL
+ }
+};
+
+/**
+ Retrieves a Unicode string that is the user readable name of the UEFI Driver.
+
+ @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param Language A pointer to a three character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ @param DriverName A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+**/
+EFI_STATUS
+EFIAPI
+SataControllerComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mSataControllerDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gSataControllerComponentName)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an UEFI Driver.
+
+ @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param ControllerHandle The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ @param ChildHandle OPTIONAL The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ @param Language A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ @param ControllerName A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language
+ specified by Language from the point of view of the
+ driver specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+**/
+EFI_STATUS
+EFIAPI
+SataControllerComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Make sure this driver is currently managing ControllHandle
+ //
+ Status = EfiTestManagedDevice (
+ ControllerHandle,
+ gSataControllerDriverBinding.DriverBindingHandle,
+ &gEfiPciIoProtocolGuid
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mSataControllerControllerNameTable,
+ ControllerName,
+ (BOOLEAN)(This == &gSataControllerComponentName)
+ );
+}
diff --git a/DuetPkg/SataControllerDxe/SataController.c b/DuetPkg/SataControllerDxe/SataController.c
new file mode 100644
index 0000000000..f00abcebb9
--- /dev/null
+++ b/DuetPkg/SataControllerDxe/SataController.c
@@ -0,0 +1,867 @@
+/** @file
+ This driver module produces IDE_CONTROLLER_INIT protocol for Sata Controllers.
+
+ Copyright (c) 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "SataController.h"
+
+///
+/// EFI_DRIVER_BINDING_PROTOCOL instance
+///
+EFI_DRIVER_BINDING_PROTOCOL gSataControllerDriverBinding = {
+ SataControllerSupported,
+ SataControllerStart,
+ SataControllerStop,
+ 0xa,
+ NULL,
+ NULL
+};
+
+/**
+ Read AHCI Operation register.
+
+ @param PciIo The PCI IO protocol instance.
+ @param Offset The operation register offset.
+
+ @return The register content read.
+
+**/
+UINT32
+EFIAPI
+AhciReadReg (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 Offset
+ )
+{
+ UINT32 Data;
+
+ ASSERT (PciIo != NULL);
+
+ Data = 0;
+
+ PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ AHCI_BAR_INDEX,
+ (UINT64) Offset,
+ 1,
+ &Data
+ );
+
+ return Data;
+}
+
+/**
+ Write AHCI Operation register.
+
+ @param PciIo The PCI IO protocol instance.
+ @param Offset The operation register offset.
+ @param Data The data used to write down.
+
+**/
+VOID
+EFIAPI
+AhciWriteReg (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 Offset,
+ IN UINT32 Data
+ )
+{
+ ASSERT (PciIo != NULL);
+
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ AHCI_BAR_INDEX,
+ (UINT64) Offset,
+ 1,
+ &Data
+ );
+
+ return;
+}
+
+/**
+ This function is used to calculate the best PIO mode supported by specific IDE device
+
+ @param IdentifyData The identify data of specific IDE device.
+ @param DisPioMode Disqualified PIO modes collection.
+ @param SelectedMode Available PIO modes collection.
+
+ @retval EFI_SUCCESS Best PIO modes are returned.
+ @retval EFI_UNSUPPORTED The device doesn't support PIO mode,
+ or all supported modes have been disqualified.
+**/
+EFI_STATUS
+CalculateBestPioMode (
+ IN EFI_IDENTIFY_DATA *IdentifyData,
+ IN UINT16 *DisPioMode OPTIONAL,
+ OUT UINT16 *SelectedMode
+ )
+{
+ UINT16 PioMode;
+ UINT16 AdvancedPioMode;
+ UINT16 Temp;
+ UINT16 Index;
+ UINT16 MinimumPioCycleTime;
+
+ Temp = 0xff;
+
+ PioMode = (UINT8) (((ATA5_IDENTIFY_DATA *) (&(IdentifyData->AtaData)))->pio_cycle_timing >> 8);
+
+ //
+ // See whether Identify Data word 64 - 70 are valid
+ //
+ if ((IdentifyData->AtaData.field_validity & 0x02) == 0x02) {
+
+ AdvancedPioMode = IdentifyData->AtaData.advanced_pio_modes;
+ DEBUG ((EFI_D_INFO, "CalculateBestPioMode: AdvancedPioMode = %x\n", AdvancedPioMode));
+
+ for (Index = 0; Index < 8; Index++) {
+ if ((AdvancedPioMode & 0x01) != 0) {
+ Temp = Index;
+ }
+
+ AdvancedPioMode >>= 1;
+ }
+
+ //
+ // If Temp is modified, mean the advanced_pio_modes is not zero;
+ // if Temp is not modified, mean there is no advanced PIO mode supported,
+ // the best PIO Mode is the value in pio_cycle_timing.
+ //
+ if (Temp != 0xff) {
+ AdvancedPioMode = (UINT16) (Temp + 3);
+ } else {
+ AdvancedPioMode = PioMode;
+ }
+
+ //
+ // Limit the PIO mode to at most PIO4.
+ //
+ PioMode = (UINT16) MIN (AdvancedPioMode, 4);
+
+ MinimumPioCycleTime = IdentifyData->AtaData.min_pio_cycle_time_with_flow_control;
+
+ if (MinimumPioCycleTime <= 120) {
+ PioMode = (UINT16) MIN (4, PioMode);
+ } else if (MinimumPioCycleTime <= 180) {
+ PioMode = (UINT16) MIN (3, PioMode);
+ } else if (MinimumPioCycleTime <= 240) {
+ PioMode = (UINT16) MIN (2, PioMode);
+ } else {
+ PioMode = 0;
+ }
+
+ //
+ // Degrade the PIO mode if the mode has been disqualified
+ //
+ if (DisPioMode != NULL) {
+ if (*DisPioMode < 2) {
+ return EFI_UNSUPPORTED; // no mode below ATA_PIO_MODE_BELOW_2
+ }
+
+ if (PioMode >= *DisPioMode) {
+ PioMode = (UINT16) (*DisPioMode - 1);
+ }
+ }
+
+ if (PioMode < 2) {
+ *SelectedMode = 1; // ATA_PIO_MODE_BELOW_2;
+ } else {
+ *SelectedMode = PioMode; // ATA_PIO_MODE_2 to ATA_PIO_MODE_4;
+ }
+
+ } else {
+ //
+ // Identify Data word 64 - 70 are not valid
+ // Degrade the PIO mode if the mode has been disqualified
+ //
+ if (DisPioMode != NULL) {
+ if (*DisPioMode < 2) {
+ return EFI_UNSUPPORTED; // no mode below ATA_PIO_MODE_BELOW_2
+ }
+
+ if (PioMode == *DisPioMode) {
+ PioMode--;
+ }
+ }
+
+ if (PioMode < 2) {
+ *SelectedMode = 1; // ATA_PIO_MODE_BELOW_2;
+ } else {
+ *SelectedMode = 2; // ATA_PIO_MODE_2;
+ }
+
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is used to calculate the best UDMA mode supported by specific IDE device
+
+ @param IdentifyData The identify data of specific IDE device.
+ @param DisUDmaMode Disqualified UDMA modes collection.
+ @param SelectedMode Available UDMA modes collection.
+
+ @retval EFI_SUCCESS Best UDMA modes are returned.
+ @retval EFI_UNSUPPORTED The device doesn't support UDMA mode,
+ or all supported modes have been disqualified.
+**/
+EFI_STATUS
+CalculateBestUdmaMode (
+ IN EFI_IDENTIFY_DATA *IdentifyData,
+ IN UINT16 *DisUDmaMode OPTIONAL,
+ OUT UINT16 *SelectedMode
+ )
+{
+ UINT16 TempMode;
+ UINT16 DeviceUDmaMode;
+
+ DeviceUDmaMode = 0;
+
+ //
+ // Check whether the WORD 88 (supported UltraDMA by drive) is valid
+ //
+ if ((IdentifyData->AtaData.field_validity & 0x04) == 0x00) {
+ return EFI_UNSUPPORTED;
+ }
+
+ DeviceUDmaMode = IdentifyData->AtaData.ultra_dma_mode;
+ DEBUG ((EFI_D_INFO, "CalculateBestUdmaMode: DeviceUDmaMode = %x\n", DeviceUDmaMode));
+ DeviceUDmaMode &= 0x3f;
+ TempMode = 0; // initialize it to UDMA-0
+
+ while ((DeviceUDmaMode >>= 1) != 0) {
+ TempMode++;
+ }
+
+ //
+ // Degrade the UDMA mode if the mode has been disqualified
+ //
+ if (DisUDmaMode != NULL) {
+ if (*DisUDmaMode == 0) {
+ *SelectedMode = 0;
+ return EFI_UNSUPPORTED; // no mode below ATA_UDMA_MODE_0
+ }
+
+ if (TempMode >= *DisUDmaMode) {
+ TempMode = (UINT16) (*DisUDmaMode - 1);
+ }
+ }
+
+ //
+ // Possible returned mode is between ATA_UDMA_MODE_0 and ATA_UDMA_MODE_5
+ //
+ *SelectedMode = TempMode;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The Entry Point of module. It follows the standard UEFI driver model.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeSataControllerDriver (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Install driver model protocol(s).
+ //
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gSataControllerDriverBinding,
+ ImageHandle,
+ &gSataControllerComponentName,
+ &gSataControllerComponentName2
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/**
+ Supported function of Driver Binding protocol for this driver.
+ Test to see if this driver supports ControllerHandle.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to test.
+ @param RemainingDevicePath A pointer to the device path.
+ it should be ignored by device driver.
+
+ @retval EFI_SUCCESS This driver supports this device.
+ @retval EFI_ALREADY_STARTED This driver is already running on this device.
+ @retval other This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+SataControllerSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 PciData;
+
+ //
+ // Attempt to open PCI I/O Protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Now further check the PCI header: Base Class (offset 0x0B) and
+ // Sub Class (offset 0x0A). This controller should be an SATA controller
+ //
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ PCI_CLASSCODE_OFFSET,
+ sizeof (PciData.Hdr.ClassCode),
+ PciData.Hdr.ClassCode
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (IS_PCI_IDE (&PciData) || IS_PCI_SATADPA (&PciData)) {
+ return EFI_SUCCESS;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ This routine is called right after the .Supported() called and
+ Start this driver on ControllerHandle.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to bind driver to.
+ @param RemainingDevicePath A pointer to the device path.
+ it should be ignored by device driver.
+
+ @retval EFI_SUCCESS This driver is added to this device.
+ @retval EFI_ALREADY_STARTED This driver is already running on this device.
+ @retval other Some error occurs when binding this driver to this device.
+
+**/
+EFI_STATUS
+EFIAPI
+SataControllerStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 PciData;
+ EFI_SATA_CONTROLLER_PRIVATE_DATA *SataPrivateData;
+ UINT32 Data32;
+ UINTN ChannelDeviceCount;
+
+ DEBUG ((EFI_D_INFO, "SataControllerStart START\n"));
+
+ SataPrivateData = NULL;
+
+ //
+ // Now test and open PCI I/O Protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SataControllerStart error return status = %r\n", Status));
+ return Status;
+ }
+
+ //
+ // Allocate Sata Private Data structure
+ //
+ SataPrivateData = AllocateZeroPool (sizeof (EFI_SATA_CONTROLLER_PRIVATE_DATA));
+ if (SataPrivateData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Initialize Sata Private Data
+ //
+ SataPrivateData->Signature = SATA_CONTROLLER_SIGNATURE;
+ SataPrivateData->PciIo = PciIo;
+ SataPrivateData->IdeInit.GetChannelInfo = IdeInitGetChannelInfo;
+ SataPrivateData->IdeInit.NotifyPhase = IdeInitNotifyPhase;
+ SataPrivateData->IdeInit.SubmitData = IdeInitSubmitData;
+ SataPrivateData->IdeInit.DisqualifyMode = IdeInitDisqualifyMode;
+ SataPrivateData->IdeInit.CalculateMode = IdeInitCalculateMode;
+ SataPrivateData->IdeInit.SetTiming = IdeInitSetTiming;
+ SataPrivateData->IdeInit.EnumAll = SATA_ENUMER_ALL;
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ PCI_CLASSCODE_OFFSET,
+ sizeof (PciData.Hdr.ClassCode),
+ PciData.Hdr.ClassCode
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (IS_PCI_IDE (&PciData)) {
+ SataPrivateData->IdeInit.ChannelCount = IDE_MAX_CHANNEL;
+ SataPrivateData->DeviceCount = IDE_MAX_DEVICES;
+ } else if (IS_PCI_SATADPA (&PciData)) {
+ //
+ // Read Host Capability Register(CAP) to get Number of Ports(NPS) and Supports Port Multiplier(SPM)
+ // NPS is 0's based value indicating the maximum number of ports supported by the HBA silicon.
+ // A maximum of 32 ports can be supported. A value of '0h', indicating one port, is the minimum requirement.
+ //
+ Data32 = AhciReadReg (PciIo, R_AHCI_CAP);
+ SataPrivateData->IdeInit.ChannelCount = (UINT8) (Data32 & B_AHCI_CAP_NPS) + 1;
+ SataPrivateData->DeviceCount = AHCI_MAX_DEVICES;
+ if ((Data32 & B_AHCI_CAP_SPM) == B_AHCI_CAP_SPM) {
+ SataPrivateData->DeviceCount = AHCI_MULTI_MAX_DEVICES;
+ }
+ }
+
+ ChannelDeviceCount = (UINTN) (SataPrivateData->IdeInit.ChannelCount) * (UINTN) (SataPrivateData->DeviceCount);
+ SataPrivateData->DisqulifiedModes = AllocateZeroPool ((sizeof (EFI_ATA_COLLECTIVE_MODE)) * ChannelDeviceCount);
+ if (SataPrivateData->DisqulifiedModes == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ SataPrivateData->IdentifyData = AllocateZeroPool ((sizeof (EFI_IDENTIFY_DATA)) * ChannelDeviceCount);
+ if (SataPrivateData->IdentifyData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ SataPrivateData->IdentifyValid = AllocateZeroPool ((sizeof (BOOLEAN)) * ChannelDeviceCount);
+ if (SataPrivateData->IdentifyValid == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Install IDE Controller Init Protocol to this instance
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ &(SataPrivateData->IdeInit),
+ NULL
+ );
+
+Done:
+ if (EFI_ERROR (Status)) {
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ if (SataPrivateData != NULL) {
+ if (SataPrivateData->DisqulifiedModes != NULL) {
+ FreePool (SataPrivateData->DisqulifiedModes);
+ }
+ if (SataPrivateData->IdentifyData != NULL) {
+ FreePool (SataPrivateData->IdentifyData);
+ }
+ if (SataPrivateData->IdentifyValid != NULL) {
+ FreePool (SataPrivateData->IdentifyValid);
+ }
+ FreePool (SataPrivateData);
+ }
+ }
+
+ DEBUG ((EFI_D_INFO, "SataControllerStart END status = %r\n", Status));
+
+ return Status;
+}
+
+/**
+ Stop this driver on ControllerHandle.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to stop driver on.
+ @param NumberOfChildren Not used.
+ @param ChildHandleBuffer Not used.
+
+ @retval EFI_SUCCESS This driver is removed from this device.
+ @retval other Some error occurs when removing this driver from this device.
+
+**/
+EFI_STATUS
+EFIAPI
+SataControllerStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit;
+ EFI_SATA_CONTROLLER_PRIVATE_DATA *SataPrivateData;
+
+ //
+ // Open the produced protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ (VOID **) &IdeInit,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ SataPrivateData = SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (IdeInit);
+ ASSERT (SataPrivateData != NULL);
+
+ //
+ // Uninstall the IDE Controller Init Protocol from this instance
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ &(SataPrivateData->IdeInit),
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (SataPrivateData != NULL) {
+ if (SataPrivateData->DisqulifiedModes != NULL) {
+ FreePool (SataPrivateData->DisqulifiedModes);
+ }
+ if (SataPrivateData->IdentifyData != NULL) {
+ FreePool (SataPrivateData->IdentifyData);
+ }
+ if (SataPrivateData->IdentifyValid != NULL) {
+ FreePool (SataPrivateData->IdentifyValid);
+ }
+ FreePool (SataPrivateData);
+ }
+
+ //
+ // Close protocols opened by Sata Controller driver
+ //
+ return gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+}
+
+//
+// Interface functions of IDE_CONTROLLER_INIT protocol
+//
+/**
+ This function can be used to obtain information about a specified channel.
+ It's usually used by IDE Bus driver during enumeration process.
+
+ @param This the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
+ @param Channel Channel number. Parallel ATA (PATA) controllers can support up to two channels.
+ Advanced Host Controller Interface (AHCI) Serial ATA (SATA) controllers
+ can support up to 32 channels, each of which can have up to 1 device.
+ In the presence of a multiplier, each channel can have 15 devices.
+ @param Enabled TRUE if the channel is enabled. If the channel is disabled,
+ then it will no be enumerated.
+ @param MaxDevices For Parallel ATA (PATA) controllers, this number will either be 1 or 2.
+ For Serial ATA (SATA) controllers, it always be 1,
+ but with a port multiplier, this number can be as large as 15.
+
+ @retval EFI_SUCCESS Success to get channel information.
+ @retval EFI_INVALID_PARAMETER Invalid channel id.
+**/
+EFI_STATUS
+EFIAPI
+IdeInitGetChannelInfo (
+ IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,
+ IN UINT8 Channel,
+ OUT BOOLEAN *Enabled,
+ OUT UINT8 *MaxDevices
+ )
+{
+ EFI_SATA_CONTROLLER_PRIVATE_DATA *SataPrivateData;
+ SataPrivateData = SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This);
+ ASSERT (SataPrivateData != NULL);
+
+ if (Channel < This->ChannelCount) {
+ *Enabled = TRUE;
+ *MaxDevices = SataPrivateData->DeviceCount;
+ return EFI_SUCCESS;
+ }
+
+ *Enabled = FALSE;
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ This function is called by IdeBus driver before executing certain actions.
+ This allows IDE Controller Init to prepare for each action.
+
+ @param This The EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
+ @param Phase Phase indicator defined by IDE_CONTROLLER_INIT protocol.
+ @param Channel Channel number.
+
+ @retval EFI_SUCCESS Success operation.
+**/
+EFI_STATUS
+EFIAPI
+IdeInitNotifyPhase (
+ IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,
+ IN EFI_IDE_CONTROLLER_ENUM_PHASE Phase,
+ IN UINT8 Channel
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is called by IdeBus driver to submit EFI_IDENTIFY_DATA data structure
+ obtained from IDE deivce. This structure is used to set IDE timing.
+
+ @param This The EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
+ @param Channel Channel number.
+ @param Device Device number.
+ @param IdentifyData A pointer to EFI_IDENTIFY_DATA data structure.
+
+ @retval EFI_SUCCESS The information is accepted without any errors.
+ @retval EFI_INVALID_PARAMETER Invalid channel id or device id.
+**/
+EFI_STATUS
+EFIAPI
+IdeInitSubmitData (
+ IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,
+ IN UINT8 Channel,
+ IN UINT8 Device,
+ IN EFI_IDENTIFY_DATA *IdentifyData
+ )
+{
+ EFI_SATA_CONTROLLER_PRIVATE_DATA *SataPrivateData;
+ SataPrivateData = SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This);
+ ASSERT (SataPrivateData != NULL);
+
+ if ((Channel >= This->ChannelCount) || (Device >= SataPrivateData->DeviceCount)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Make a local copy of device's IdentifyData and mark the valid flag
+ //
+ if (IdentifyData != NULL) {
+ CopyMem (
+ &(SataPrivateData->IdentifyData[Channel * Device]),
+ IdentifyData,
+ sizeof (EFI_IDENTIFY_DATA)
+ );
+
+ SataPrivateData->IdentifyValid[Channel * Device] = TRUE;
+ } else {
+ SataPrivateData->IdentifyValid[Channel * Device] = FALSE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is called by IdeBus driver to disqualify unsupported operation
+ mode on specfic IDE device.
+
+ @param This The EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
+ @param Channel Channel number.
+ @param Device Device number.
+ @param BadModes The modes that the device does not support and that
+ should be disqualified.
+
+ @retval EFI_SUCCESS The modes were accepted without any errors.
+ @retval EFI_INVALID_PARAMETER Invalid channel id or device id.
+**/
+EFI_STATUS
+EFIAPI
+IdeInitDisqualifyMode (
+ IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,
+ IN UINT8 Channel,
+ IN UINT8 Device,
+ IN EFI_ATA_COLLECTIVE_MODE *BadModes
+ )
+{
+ EFI_SATA_CONTROLLER_PRIVATE_DATA *SataPrivateData;
+ SataPrivateData = SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This);
+ ASSERT (SataPrivateData != NULL);
+
+ if ((Channel >= This->ChannelCount) || (BadModes == NULL) || (Device >= SataPrivateData->DeviceCount)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Record the disqualified modes per channel per device. From ATA/ATAPI spec,
+ // if a mode is not supported, the modes higher than it is also not supported.
+ //
+ CopyMem (
+ &(SataPrivateData->DisqulifiedModes[Channel * Device]),
+ BadModes,
+ sizeof (EFI_ATA_COLLECTIVE_MODE)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is called by IdeBus driver to calculate the best operation mode
+ supported by specific IDE device.
+
+ @param This The EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
+ @param Channel Channel number.
+ @param Device Device number.
+ @param SupportedModes The optimum modes for the device.
+
+ @retval EFI_SUCCESS Supported modes are returned.
+ @retval EFI_INVALID_PARAMETER Invalid channel id or device id.
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool.
+ @retval EFI_NOT_READY Identify data of the device is not ready.
+**/
+EFI_STATUS
+EFIAPI
+IdeInitCalculateMode (
+ IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,
+ IN UINT8 Channel,
+ IN UINT8 Device,
+ OUT EFI_ATA_COLLECTIVE_MODE **SupportedModes
+ )
+{
+ EFI_SATA_CONTROLLER_PRIVATE_DATA *SataPrivateData;
+ EFI_IDENTIFY_DATA *IdentifyData;
+ BOOLEAN IdentifyValid;
+ EFI_ATA_COLLECTIVE_MODE *DisqulifiedModes;
+ UINT16 SelectedMode;
+ EFI_STATUS Status;
+
+ SataPrivateData = SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This);
+ ASSERT (SataPrivateData != NULL);
+
+ if ((Channel >= This->ChannelCount) || (SupportedModes == NULL) || (Device >= SataPrivateData->DeviceCount)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *SupportedModes = AllocateZeroPool (sizeof (EFI_ATA_COLLECTIVE_MODE));
+ if (*SupportedModes == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ IdentifyData = &(SataPrivateData->IdentifyData[Channel * Device]);
+ IdentifyValid = SataPrivateData->IdentifyValid[Channel * Device];
+ DisqulifiedModes = &(SataPrivateData->DisqulifiedModes[Channel * Device]);
+
+ //
+ // Make sure we've got the valid identify data of the device from SubmitData()
+ //
+ if (!IdentifyValid) {
+ return EFI_NOT_READY;
+ }
+
+ Status = CalculateBestPioMode (
+ IdentifyData,
+ (DisqulifiedModes->PioMode.Valid ? ((UINT16 *) &(DisqulifiedModes->PioMode.Mode)) : NULL),
+ &SelectedMode
+ );
+ if (!EFI_ERROR (Status)) {
+ (*SupportedModes)->PioMode.Valid = TRUE;
+ (*SupportedModes)->PioMode.Mode = SelectedMode;
+
+ } else {
+ (*SupportedModes)->PioMode.Valid = FALSE;
+ }
+ DEBUG ((EFI_D_INFO, "IdeInitCalculateMode: PioMode = %x\n", (*SupportedModes)->PioMode.Mode));
+
+ Status = CalculateBestUdmaMode (
+ IdentifyData,
+ (DisqulifiedModes->UdmaMode.Valid ? ((UINT16 *) &(DisqulifiedModes->UdmaMode.Mode)) : NULL),
+ &SelectedMode
+ );
+
+ if (!EFI_ERROR (Status)) {
+ (*SupportedModes)->UdmaMode.Valid = TRUE;
+ (*SupportedModes)->UdmaMode.Mode = SelectedMode;
+
+ } else {
+ (*SupportedModes)->UdmaMode.Valid = FALSE;
+ }
+ DEBUG ((EFI_D_INFO, "IdeInitCalculateMode: UdmaMode = %x\n", (*SupportedModes)->UdmaMode.Mode));
+
+ //
+ // The modes other than PIO and UDMA are not supported
+ //
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is called by IdeBus driver to set appropriate timing on IDE
+ controller according supported operation mode.
+
+ @param This The EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
+ @param Channel Channel number.
+ @param Device Device number.
+ @param Modes The modes to set.
+
+ @retval EFI_SUCCESS Sucess operation.
+**/
+EFI_STATUS
+EFIAPI
+IdeInitSetTiming (
+ IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,
+ IN UINT8 Channel,
+ IN UINT8 Device,
+ IN EFI_ATA_COLLECTIVE_MODE *Modes
+ )
+{
+ return EFI_SUCCESS;
+}
diff --git a/DuetPkg/SataControllerDxe/SataController.h b/DuetPkg/SataControllerDxe/SataController.h
new file mode 100644
index 0000000000..0352178bab
--- /dev/null
+++ b/DuetPkg/SataControllerDxe/SataController.h
@@ -0,0 +1,402 @@
+/** @file
+ Header file for Sata Controller driver.
+
+ Copyright (c) 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SATA_CONTROLLER_H_
+#define _SATA_CONTROLLER_H_
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+//
+// Global Variables definitions
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gSataControllerDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gSataControllerComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gSataControllerComponentName2;
+
+#define AHCI_BAR_INDEX 0x05
+#define R_AHCI_CAP 0x0
+#define B_AHCI_CAP_NPS (BIT4 | BIT3 | BIT2 | BIT1 | BIT0) // Number of Ports
+#define B_AHCI_CAP_SPM BIT17 // Supports Port Multiplier
+
+///
+/// AHCI each channel can have up to 1 device
+///
+#define AHCI_MAX_DEVICES 0x01
+
+///
+/// AHCI each channel can have 15 devices in the presence of a multiplier
+///
+#define AHCI_MULTI_MAX_DEVICES 0x0F
+
+///
+/// IDE supports 2 channel max
+///
+#define IDE_MAX_CHANNEL 0x02
+
+///
+/// IDE supports 2 devices max
+///
+#define IDE_MAX_DEVICES 0x02
+
+#define SATA_ENUMER_ALL FALSE
+
+//
+// Sata Controller driver private data structure
+//
+
+#define SATA_CONTROLLER_SIGNATURE SIGNATURE_32('S','A','T','A')
+
+typedef struct _EFI_SATA_CONTROLLER_PRIVATE_DATA {
+ //
+ // Standard signature used to identify Sata Controller private data
+ //
+ UINT32 Signature;
+
+ //
+ // Protocol instance of IDE_CONTROLLER_INIT produced by this driver
+ //
+ EFI_IDE_CONTROLLER_INIT_PROTOCOL IdeInit;
+
+ //
+ // Copy of protocol pointers used by this driver
+ //
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ //
+ // The number of devices that are supported by this channel
+ //
+ UINT8 DeviceCount;
+
+ //
+ // The highest disqulified mode for each attached device,
+ // From ATA/ATAPI spec, if a mode is not supported,
+ // the modes higher than it is also not supported
+ //
+ EFI_ATA_COLLECTIVE_MODE *DisqulifiedModes;
+
+ //
+ // A copy of EFI_IDENTIFY_DATA data for each attached SATA device and its flag
+ //
+ EFI_IDENTIFY_DATA *IdentifyData;
+ BOOLEAN *IdentifyValid;
+} EFI_SATA_CONTROLLER_PRIVATE_DATA;
+
+#define SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS(a) CR(a, EFI_SATA_CONTROLLER_PRIVATE_DATA, IdeInit, SATA_CONTROLLER_SIGNATURE)
+
+//
+// Driver binding functions declaration
+//
+/**
+ Supported function of Driver Binding protocol for this driver.
+ Test to see if this driver supports ControllerHandle.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to test.
+ @param RemainingDevicePath A pointer to the device path. Should be ignored by
+ device driver.
+
+ @retval EFI_SUCCESS This driver supports this device.
+ @retval EFI_ALREADY_STARTED This driver is already running on this device.
+ @retval other This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+SataControllerSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+;
+
+/**
+ This routine is called right after the .Supported() called and
+ Start this driver on ControllerHandle.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to bind driver to.
+ @param RemainingDevicePath A pointer to the device path. Should be ignored by
+ device driver.
+
+ @retval EFI_SUCCESS This driver is added to this device.
+ @retval EFI_ALREADY_STARTED This driver is already running on this device.
+ @retval other Some error occurs when binding this driver to this device.
+
+**/
+EFI_STATUS
+EFIAPI
+SataControllerStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+;
+
+/**
+ Stop this driver on ControllerHandle.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to stop driver on.
+ @param NumberOfChildren Not used.
+ @param ChildHandleBuffer Not used.
+
+ @retval EFI_SUCCESS This driver is removed from this device.
+ @retval other Some error occurs when removing this driver from this device.
+
+**/
+EFI_STATUS
+EFIAPI
+SataControllerStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+;
+
+//
+// IDE controller init functions declaration
+//
+/**
+ This function can be used to obtain information about a specified channel.
+ It's usually used by IDE Bus driver during enumeration process.
+
+ @param This the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
+ @param Channel Channel number. Parallel ATA (PATA) controllers can support up to two channels.
+ Advanced Host Controller Interface (AHCI) Serial ATA (SATA) controllers
+ can support up to 32 channels, each of which can have up to one device.
+ In the presence of a multiplier, each channel can have 15 devices.
+ @param Enabled TRUE if the channel is enabled. If the channel is disabled,
+ then it will no be enumerated.
+ @param MaxDevices For Parallel ATA (PATA) controllers, this number will either be 1 or 2.
+ For Serial ATA (SATA) controllers with a port multiplier, this number can be as large as 15.
+
+ @retval EFI_SUCCESS Success to get channel information.
+ @retval EFI_INVALID_PARAMETER Invalid channel id.
+**/
+EFI_STATUS
+EFIAPI
+IdeInitGetChannelInfo (
+ IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,
+ IN UINT8 Channel,
+ OUT BOOLEAN *Enabled,
+ OUT UINT8 *MaxDevices
+ )
+;
+
+/**
+ This function is called by IdeBus driver before executing certain actions.
+ This allows IDE Controller Init to prepare for each action.
+
+ @param This The EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
+ @param Phase Phase indicator defined by IDE_CONTROLLER_INIT protocol.
+ @param Channel Channel number.
+
+ @retval EFI_SUCCESS Success operation.
+**/
+EFI_STATUS
+EFIAPI
+IdeInitNotifyPhase (
+ IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,
+ IN EFI_IDE_CONTROLLER_ENUM_PHASE Phase,
+ IN UINT8 Channel
+ )
+;
+
+/**
+ This function is called by IdeBus driver to submit EFI_IDENTIFY_DATA data structure
+ obtained from IDE deivce. This structure is used to set IDE timing.
+
+ @param This The EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
+ @param Channel Channel number.
+ @param Device Device number.
+ @param IdentifyData A pointer to EFI_IDENTIFY_DATA data structure.
+
+ @retval EFI_SUCCESS The information was accepted without any errors.
+ @retval EFI_INVALID_PARAMETER Invalid channel id or device id.
+**/
+EFI_STATUS
+EFIAPI
+IdeInitSubmitData (
+ IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,
+ IN UINT8 Channel,
+ IN UINT8 Device,
+ IN EFI_IDENTIFY_DATA *IdentifyData
+ )
+;
+
+/**
+ This function is called by IdeBus driver to disqualify unsupported operation
+ mode on specfic IDE device.
+
+ @param This The EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
+ @param Channel Channel number.
+ @param Device Device number.
+ @param BadModes The modes that the device does not support and that
+ should be disqualified.
+
+ @retval EFI_SUCCESS The modes were accepted without any errors.
+ @retval EFI_INVALID_PARAMETER Invalid channel id or device id.
+**/
+EFI_STATUS
+EFIAPI
+IdeInitDisqualifyMode (
+ IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,
+ IN UINT8 Channel,
+ IN UINT8 Device,
+ IN EFI_ATA_COLLECTIVE_MODE *BadModes
+ )
+;
+
+/**
+ This function is called by IdeBus driver to calculate the best operation mode
+ supported by specific IDE device.
+
+ @param This The EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
+ @param Channel Channel number.
+ @param Device Device number.
+ @param SupportedModes The optimum modes for the device.
+
+ @retval EFI_SUCCESS SupportedModes was returned.
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool.
+ @retval EFI_INVALID_PARAMETER Invalid channel id or device id.
+**/
+EFI_STATUS
+EFIAPI
+IdeInitCalculateMode (
+ IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,
+ IN UINT8 Channel,
+ IN UINT8 Device,
+ OUT EFI_ATA_COLLECTIVE_MODE **SupportedModes
+ )
+;
+
+/**
+ This function is called by IdeBus driver to set appropriate timing on IDE
+ controller according supported operation mode.
+
+ @param This The EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
+ @param Channel Channel number.
+ @param Device Device number.
+ @param Modes The modes to set.
+
+ @retval EFI_SUCCESS Sucess operation.
+**/
+EFI_STATUS
+EFIAPI
+IdeInitSetTiming (
+ IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,
+ IN UINT8 Channel,
+ IN UINT8 Device,
+ IN EFI_ATA_COLLECTIVE_MODE *Modes
+ )
+;
+
+//
+// Forward reference declaration
+//
+/**
+ Retrieves a Unicode string that is the user readable name of the UEFI Driver.
+
+ @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param Language A pointer to a three character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ @param DriverName A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+**/
+EFI_STATUS
+EFIAPI
+SataControllerComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+;
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an UEFI Driver.
+
+ @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param ControllerHandle The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ @param OPTIONAL ChildHandle The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ @param Language A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ @param ControllerName A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language
+ specified by Language from the point of view of the
+ driver specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+**/
+EFI_STATUS
+EFIAPI
+SataControllerComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+;
+
+#endif
diff --git a/DuetPkg/SataControllerDxe/SataControllerDxe.inf b/DuetPkg/SataControllerDxe/SataControllerDxe.inf
new file mode 100644
index 0000000000..b3b37ddd0e
--- /dev/null
+++ b/DuetPkg/SataControllerDxe/SataControllerDxe.inf
@@ -0,0 +1,49 @@
+## @file
+#
+# Component description file for the Sata Controller driver.
+#
+# Copyright (c) 2011, Intel Corporation. All rights reserved.
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SataController
+ FILE_GUID = 8F4CD826-A5A0-4e93-9522-CFB0AB72926C
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeSataControllerDriver
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ ComponentName.c
+ SataController.c
+ SataController.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ DebugLib
+ UefiLib
+ BaseLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+
+[Protocols]
+ gEfiPciIoProtocolGuid
+ gEfiIdeControllerInitProtocolGuid