Add AHCI support for DUET.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11353 6f19259b-4bc3-4df7-8a09-765794883524
diff --git a/DuetPkg/DuetPkg.fdf b/DuetPkg/DuetPkg.fdf
index ca7d2be..ef4b5fe 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.<BR>

+# Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>

 #

 #    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  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 83d5688..825e0fe 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.<BR>

+#  Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>

 #

 #  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 142af25..5ccf2a3 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.<BR>

+#  Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>

 #

 #  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 0000000..57cd3c8
--- /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.<BR>

+  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 0000000..f00abce
--- /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.<BR>

+  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 0000000..0352178
--- /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.<BR>

+  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 <Uefi.h>

+#include <Protocol/ComponentName.h>

+#include <Protocol/DriverBinding.h>

+#include <Protocol/PciIo.h>

+#include <Protocol/IdeControllerInit.h>

+#include <Library/UefiDriverEntryPoint.h>

+#include <Library/DebugLib.h>

+#include <Library/UefiLib.h>

+#include <Library/BaseLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/MemoryAllocationLib.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <IndustryStandard/Pci.h>

+

+//

+// 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 0000000..b3b37dd
--- /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.<BR>

+#  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