112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh/** @file
212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  This driver module produces IDE_CONTROLLER_INIT protocol for Sata Controllers.
312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  This program and the accompanying materials
612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  are licensed and made available under the terms and conditions of the BSD License
712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  which accompanies this distribution.  The full text of the license may be found at
812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  http://opensource.org/licenses/bsd-license.php
912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
1012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
1112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
1212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
1312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh**/
1412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
1512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh#include "SataController.h"
1612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
1712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh///
1812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh/// EFI_DRIVER_BINDING_PROTOCOL instance
1912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh///
2012e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehEFI_DRIVER_BINDING_PROTOCOL gSataControllerDriverBinding = {
2112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  SataControllerSupported,
2212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  SataControllerStart,
2312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  SataControllerStop,
2412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  0xa,
2512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  NULL,
2612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  NULL
2712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh};
2812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
2912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh/**
3012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  Read AHCI Operation register.
3112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
3212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param PciIo      The PCI IO protocol instance.
3312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param Offset     The operation register offset.
3412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
3512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @return The register content read.
3612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
3712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh**/
3812e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehUINT32
3912e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehEFIAPI
4012e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehAhciReadReg (
4112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN EFI_PCI_IO_PROTOCOL    *PciIo,
4212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN UINT32                 Offset
4312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  )
4412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh{
4512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  UINT32    Data;
4612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
4712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  ASSERT (PciIo != NULL);
4812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
4912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  Data = 0;
5012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
5112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  PciIo->Mem.Read (
5212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh               PciIo,
5312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh               EfiPciIoWidthUint32,
5412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh               AHCI_BAR_INDEX,
5512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh               (UINT64) Offset,
5612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh               1,
5712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh               &Data
5812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh               );
5912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
6012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  return Data;
6112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh}
6212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
6312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh/**
6412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  Write AHCI Operation register.
6512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
6612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param PciIo      The PCI IO protocol instance.
6712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param Offset     The operation register offset.
6812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param Data       The data used to write down.
6912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
7012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh**/
7112e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehVOID
7212e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehEFIAPI
7312e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehAhciWriteReg (
7412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN EFI_PCI_IO_PROTOCOL    *PciIo,
7512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN UINT32                 Offset,
7612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN UINT32                 Data
7712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  )
7812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh{
7912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  ASSERT (PciIo != NULL);
8012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
8112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  PciIo->Mem.Write (
8212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh               PciIo,
8312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh               EfiPciIoWidthUint32,
8412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh               AHCI_BAR_INDEX,
8512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh               (UINT64) Offset,
8612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh               1,
8712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh               &Data
8812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh               );
8912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
9012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  return;
9112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh}
9212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
9312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh/**
9412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  This function is used to calculate the best PIO mode supported by specific IDE device
9512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
9612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param IdentifyData   The identify data of specific IDE device.
9712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param DisPioMode     Disqualified PIO modes collection.
9812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param SelectedMode   Available PIO modes collection.
9912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
10012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_SUCCESS       Best PIO modes are returned.
10112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_UNSUPPORTED   The device doesn't support PIO mode,
10212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                            or all supported modes have been disqualified.
10312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh**/
10412e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehEFI_STATUS
10512e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehCalculateBestPioMode (
10612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN EFI_IDENTIFY_DATA  *IdentifyData,
10712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN UINT16             *DisPioMode OPTIONAL,
10812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  OUT UINT16            *SelectedMode
10912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  )
11012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh{
11112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  UINT16    PioMode;
11212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  UINT16    AdvancedPioMode;
11312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  UINT16    Temp;
11412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  UINT16    Index;
11512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  UINT16    MinimumPioCycleTime;
11612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
11712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  Temp = 0xff;
11812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
11912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  PioMode = (UINT8) (((ATA5_IDENTIFY_DATA *) (&(IdentifyData->AtaData)))->pio_cycle_timing >> 8);
12012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
12112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
12212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  // See whether Identify Data word 64 - 70 are valid
12312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
12412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  if ((IdentifyData->AtaData.field_validity & 0x02) == 0x02) {
12512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
12612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    AdvancedPioMode = IdentifyData->AtaData.advanced_pio_modes;
12712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    DEBUG ((EFI_D_INFO, "CalculateBestPioMode: AdvancedPioMode = %x\n", AdvancedPioMode));
12812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
12912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    for (Index = 0; Index < 8; Index++) {
13012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      if ((AdvancedPioMode & 0x01) != 0) {
13112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh        Temp = Index;
13212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      }
13312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
13412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      AdvancedPioMode >>= 1;
13512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    }
13612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
13712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    //
13812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    // If Temp is modified, mean the advanced_pio_modes is not zero;
13912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    // if Temp is not modified, mean there is no advanced PIO mode supported,
14012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    // the best PIO Mode is the value in pio_cycle_timing.
14112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    //
14212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    if (Temp != 0xff) {
14312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      AdvancedPioMode = (UINT16) (Temp + 3);
14412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    } else {
14512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      AdvancedPioMode = PioMode;
14612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    }
14712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
14812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    //
14912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    // Limit the PIO mode to at most PIO4.
15012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    //
15112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    PioMode = (UINT16) MIN (AdvancedPioMode, 4);
15212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
15312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    MinimumPioCycleTime = IdentifyData->AtaData.min_pio_cycle_time_with_flow_control;
15412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
15512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    if (MinimumPioCycleTime <= 120) {
15612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      PioMode = (UINT16) MIN (4, PioMode);
15712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    } else if (MinimumPioCycleTime <= 180) {
15812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      PioMode = (UINT16) MIN (3, PioMode);
15912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    } else if (MinimumPioCycleTime <= 240) {
16012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      PioMode = (UINT16) MIN (2, PioMode);
16112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    } else {
16212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      PioMode = 0;
16312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    }
16412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
16512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    //
16612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    // Degrade the PIO mode if the mode has been disqualified
16712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    //
16812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    if (DisPioMode != NULL) {
16912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      if (*DisPioMode < 2) {
17012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh        return EFI_UNSUPPORTED; // no mode below ATA_PIO_MODE_BELOW_2
17112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      }
17212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
17312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      if (PioMode >= *DisPioMode) {
17412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh        PioMode = (UINT16) (*DisPioMode - 1);
17512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      }
17612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    }
17712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
17812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    if (PioMode < 2) {
17912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      *SelectedMode = 1;        // ATA_PIO_MODE_BELOW_2;
18012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    } else {
18112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      *SelectedMode = PioMode;  // ATA_PIO_MODE_2 to ATA_PIO_MODE_4;
18212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    }
18312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
18412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  } else {
18512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    //
18612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    // Identify Data word 64 - 70 are not valid
18712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    // Degrade the PIO mode if the mode has been disqualified
18812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    //
18912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    if (DisPioMode != NULL) {
19012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      if (*DisPioMode < 2) {
19112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh        return EFI_UNSUPPORTED; // no mode below ATA_PIO_MODE_BELOW_2
19212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      }
19312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
19412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      if (PioMode == *DisPioMode) {
19512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh        PioMode--;
19612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      }
19712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    }
19812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
19912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    if (PioMode < 2) {
20012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      *SelectedMode = 1;        // ATA_PIO_MODE_BELOW_2;
20112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    } else {
20212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      *SelectedMode = 2;        // ATA_PIO_MODE_2;
20312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    }
20412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
20512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  }
20612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
20712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  return EFI_SUCCESS;
20812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh}
20912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
21012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh/**
21112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  This function is used to calculate the best UDMA mode supported by specific IDE device
21212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
21312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param IdentifyData   The identify data of specific IDE device.
21412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param DisUDmaMode     Disqualified UDMA modes collection.
21512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param SelectedMode   Available UDMA modes collection.
21612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
21712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_SUCCESS       Best UDMA modes are returned.
21812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_UNSUPPORTED   The device doesn't support UDMA mode,
21912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                            or all supported modes have been disqualified.
22012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh**/
22112e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehEFI_STATUS
22212e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehCalculateBestUdmaMode (
22312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN EFI_IDENTIFY_DATA  *IdentifyData,
22412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN UINT16             *DisUDmaMode OPTIONAL,
22512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  OUT UINT16            *SelectedMode
22612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  )
22712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh{
22812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  UINT16    TempMode;
22912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  UINT16    DeviceUDmaMode;
23012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
23112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  DeviceUDmaMode = 0;
23212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
23312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
23412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  // Check whether the WORD 88 (supported UltraDMA by drive) is valid
23512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
23612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  if ((IdentifyData->AtaData.field_validity & 0x04) == 0x00) {
23712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    return EFI_UNSUPPORTED;
23812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  }
23912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
24012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  DeviceUDmaMode = IdentifyData->AtaData.ultra_dma_mode;
24112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  DEBUG ((EFI_D_INFO, "CalculateBestUdmaMode: DeviceUDmaMode = %x\n", DeviceUDmaMode));
24212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  DeviceUDmaMode &= 0x3f;
24312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  TempMode = 0;                 // initialize it to UDMA-0
24412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
24512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  while ((DeviceUDmaMode >>= 1) != 0) {
24612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    TempMode++;
24712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  }
24812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
24912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
25012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  // Degrade the UDMA mode if the mode has been disqualified
25112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
25212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  if (DisUDmaMode != NULL) {
25312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    if (*DisUDmaMode == 0) {
25412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      *SelectedMode = 0;
25512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      return EFI_UNSUPPORTED;   // no mode below ATA_UDMA_MODE_0
25612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    }
25712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
25812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    if (TempMode >= *DisUDmaMode) {
25912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      TempMode = (UINT16) (*DisUDmaMode - 1);
26012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    }
26112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  }
26212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
26312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
26412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  // Possible returned mode is between ATA_UDMA_MODE_0 and ATA_UDMA_MODE_5
26512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
26612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  *SelectedMode = TempMode;
26712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
26812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  return EFI_SUCCESS;
26912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh}
27012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
27112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh/**
27212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  The Entry Point of module. It follows the standard UEFI driver model.
27312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
27412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[in] ImageHandle    The firmware allocated handle for the EFI image.
27512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[in] SystemTable    A pointer to the EFI System Table.
27612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
27712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_SUCCESS   The entry point is executed successfully.
27812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval other         Some error occurs when executing this entry point.
27912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
28012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh**/
28112e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehEFI_STATUS
28212e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehEFIAPI
28312e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehInitializeSataControllerDriver (
28412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN EFI_HANDLE         ImageHandle,
28512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN EFI_SYSTEM_TABLE   *SystemTable
28612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  )
28712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh{
28812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  EFI_STATUS    Status;
28912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
29012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
29112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  // Install driver model protocol(s).
29212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
29312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  Status = EfiLibInstallDriverBindingComponentName2 (
29412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh             ImageHandle,
29512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh             SystemTable,
29612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh             &gSataControllerDriverBinding,
29712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh             ImageHandle,
29812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh             &gSataControllerComponentName,
29912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh             &gSataControllerComponentName2
30012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh             );
30112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  ASSERT_EFI_ERROR (Status);
30212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
30312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  return Status;
30412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh}
30512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
30612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh/**
30712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  Supported function of Driver Binding protocol for this driver.
30812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  Test to see if this driver supports ControllerHandle.
30912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
31012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param This                   Protocol instance pointer.
31112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param Controller             Handle of device to test.
31212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param RemainingDevicePath    A pointer to the device path.
31312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                                it should be ignored by device driver.
31412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
31512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_SUCCESS           This driver supports this device.
31612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_ALREADY_STARTED   This driver is already running on this device.
31712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval other                 This driver does not support this device.
31812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
31912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh**/
32012e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehEFI_STATUS
32112e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehEFIAPI
32212e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehSataControllerSupported (
32312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
32412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN EFI_HANDLE                     Controller,
32512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
32612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  )
32712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh{
32812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  EFI_STATUS            Status;
32912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  EFI_PCI_IO_PROTOCOL   *PciIo;
33012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  PCI_TYPE00            PciData;
33112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
33212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
33312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  // Attempt to open PCI I/O Protocol
33412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
33512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  Status = gBS->OpenProtocol (
33612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  Controller,
33712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  &gEfiPciIoProtocolGuid,
33812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  (VOID **) &PciIo,
33912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  This->DriverBindingHandle,
34012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  Controller,
34112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
34212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  );
34312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  if (EFI_ERROR (Status)) {
34412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    return Status;
34512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  }
34612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
34712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
34812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  // Now further check the PCI header: Base Class (offset 0x0B) and
34912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  // Sub Class (offset 0x0A). This controller should be an SATA controller
35012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
35112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  Status = PciIo->Pci.Read (
35212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                        PciIo,
35312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                        EfiPciIoWidthUint8,
35412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                        PCI_CLASSCODE_OFFSET,
35512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                        sizeof (PciData.Hdr.ClassCode),
35612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                        PciData.Hdr.ClassCode
35712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                        );
35812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  if (EFI_ERROR (Status)) {
35912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    return EFI_UNSUPPORTED;
36012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  }
36112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
36212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  if (IS_PCI_IDE (&PciData) || IS_PCI_SATADPA (&PciData)) {
36312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    return EFI_SUCCESS;
36412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  }
36512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
36612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  return EFI_UNSUPPORTED;
36712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh}
36812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
36912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh/**
37012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  This routine is called right after the .Supported() called and
37112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  Start this driver on ControllerHandle.
37212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
37312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param This                   Protocol instance pointer.
37412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param Controller             Handle of device to bind driver to.
37512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param RemainingDevicePath    A pointer to the device path.
37612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                                it should be ignored by device driver.
37712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
37812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_SUCCESS           This driver is added to this device.
37912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_ALREADY_STARTED   This driver is already running on this device.
38012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval other                 Some error occurs when binding this driver to this device.
38112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
38212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh**/
38312e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehEFI_STATUS
38412e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehEFIAPI
38512e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehSataControllerStart (
38612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
38712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN EFI_HANDLE                     Controller,
38812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
38912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  )
39012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh{
39112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  EFI_STATUS                        Status;
39212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  EFI_PCI_IO_PROTOCOL               *PciIo;
393bcab71413407e61c144994925556725dd65eede9Laszlo Ersek  UINT64                            OriginalPciAttributes;
39412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  PCI_TYPE00                        PciData;
39512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  EFI_SATA_CONTROLLER_PRIVATE_DATA  *SataPrivateData;
39612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  UINT32                            Data32;
39712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  UINTN                             ChannelDeviceCount;
39812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
39912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  DEBUG ((EFI_D_INFO, "SataControllerStart START\n"));
40012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
40112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  SataPrivateData = NULL;
40212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
40312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
40412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  // Now test and open PCI I/O Protocol
40512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
40612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  Status = gBS->OpenProtocol (
40712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  Controller,
40812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  &gEfiPciIoProtocolGuid,
40912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  (VOID **) &PciIo,
41012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  This->DriverBindingHandle,
41112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  Controller,
41212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  EFI_OPEN_PROTOCOL_BY_DRIVER
41312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  );
41412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  if (EFI_ERROR (Status)) {
415379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo Ersek    goto Bail;
41612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  }
41712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
41812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
419bcab71413407e61c144994925556725dd65eede9Laszlo Ersek  // Save original PCI attributes, and enable IO space access, memory space
420bcab71413407e61c144994925556725dd65eede9Laszlo Ersek  // access, and Bus Master (DMA).
421bcab71413407e61c144994925556725dd65eede9Laszlo Ersek  //
422bcab71413407e61c144994925556725dd65eede9Laszlo Ersek  Status = PciIo->Attributes (PciIo, EfiPciIoAttributeOperationGet, 0,
423bcab71413407e61c144994925556725dd65eede9Laszlo Ersek                    &OriginalPciAttributes);
424bcab71413407e61c144994925556725dd65eede9Laszlo Ersek  if (EFI_ERROR (Status)) {
425bcab71413407e61c144994925556725dd65eede9Laszlo Ersek    goto ClosePciIo;
426bcab71413407e61c144994925556725dd65eede9Laszlo Ersek  }
427bcab71413407e61c144994925556725dd65eede9Laszlo Ersek  Status = PciIo->Attributes (PciIo, EfiPciIoAttributeOperationEnable,
428bcab71413407e61c144994925556725dd65eede9Laszlo Ersek                    EFI_PCI_DEVICE_ENABLE, NULL);
429bcab71413407e61c144994925556725dd65eede9Laszlo Ersek  if (EFI_ERROR (Status)) {
430bcab71413407e61c144994925556725dd65eede9Laszlo Ersek    goto ClosePciIo;
431bcab71413407e61c144994925556725dd65eede9Laszlo Ersek  }
432bcab71413407e61c144994925556725dd65eede9Laszlo Ersek
433bcab71413407e61c144994925556725dd65eede9Laszlo Ersek  //
43412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  // Allocate Sata Private Data structure
43512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
43612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  SataPrivateData = AllocateZeroPool (sizeof (EFI_SATA_CONTROLLER_PRIVATE_DATA));
43712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  if (SataPrivateData == NULL) {
43812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    Status = EFI_OUT_OF_RESOURCES;
439bcab71413407e61c144994925556725dd65eede9Laszlo Ersek    goto RestorePciAttributes;
44012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  }
44112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
44212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
44312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  // Initialize Sata Private Data
44412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
44512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  SataPrivateData->Signature = SATA_CONTROLLER_SIGNATURE;
44612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  SataPrivateData->PciIo = PciIo;
447bcab71413407e61c144994925556725dd65eede9Laszlo Ersek  SataPrivateData->OriginalPciAttributes = OriginalPciAttributes;
44812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  SataPrivateData->IdeInit.GetChannelInfo = IdeInitGetChannelInfo;
44912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  SataPrivateData->IdeInit.NotifyPhase = IdeInitNotifyPhase;
45012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  SataPrivateData->IdeInit.SubmitData = IdeInitSubmitData;
45112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  SataPrivateData->IdeInit.DisqualifyMode = IdeInitDisqualifyMode;
45212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  SataPrivateData->IdeInit.CalculateMode = IdeInitCalculateMode;
45312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  SataPrivateData->IdeInit.SetTiming = IdeInitSetTiming;
45412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  SataPrivateData->IdeInit.EnumAll = SATA_ENUMER_ALL;
45512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
45612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  Status = PciIo->Pci.Read (
45712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                        PciIo,
45812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                        EfiPciIoWidthUint8,
45912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                        PCI_CLASSCODE_OFFSET,
46012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                        sizeof (PciData.Hdr.ClassCode),
46112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                        PciData.Hdr.ClassCode
46212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                        );
463379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo Ersek  if (EFI_ERROR (Status)) {
464379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo Ersek    goto FreeSataPrivateData;
465379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo Ersek  }
46612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
46712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  if (IS_PCI_IDE (&PciData)) {
46812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    SataPrivateData->IdeInit.ChannelCount = IDE_MAX_CHANNEL;
46912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    SataPrivateData->DeviceCount = IDE_MAX_DEVICES;
47012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  } else if (IS_PCI_SATADPA (&PciData)) {
47112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    //
47212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    // Read Host Capability Register(CAP) to get Number of Ports(NPS) and Supports Port Multiplier(SPM)
47312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    //   NPS is 0's based value indicating the maximum number of ports supported by the HBA silicon.
47412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    //   A maximum of 32 ports can be supported. A value of '0h', indicating one port, is the minimum requirement.
47512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    //
47612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    Data32 = AhciReadReg (PciIo, R_AHCI_CAP);
47712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    SataPrivateData->IdeInit.ChannelCount = (UINT8) ((Data32 & B_AHCI_CAP_NPS) + 1);
47812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    SataPrivateData->DeviceCount = AHCI_MAX_DEVICES;
47912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    if ((Data32 & B_AHCI_CAP_SPM) == B_AHCI_CAP_SPM) {
48012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      SataPrivateData->DeviceCount = AHCI_MULTI_MAX_DEVICES;
48112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    }
48212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  }
48312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
48412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  ChannelDeviceCount = (UINTN) (SataPrivateData->IdeInit.ChannelCount) * (UINTN) (SataPrivateData->DeviceCount);
48512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  SataPrivateData->DisqualifiedModes = AllocateZeroPool ((sizeof (EFI_ATA_COLLECTIVE_MODE)) * ChannelDeviceCount);
48612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  if (SataPrivateData->DisqualifiedModes == NULL) {
48712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    Status = EFI_OUT_OF_RESOURCES;
488379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo Ersek    goto FreeSataPrivateData;
48912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  }
49012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
49112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  SataPrivateData->IdentifyData = AllocateZeroPool ((sizeof (EFI_IDENTIFY_DATA)) * ChannelDeviceCount);
49212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  if (SataPrivateData->IdentifyData == NULL) {
49312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    Status = EFI_OUT_OF_RESOURCES;
494379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo Ersek    goto FreeDisqualifiedModes;
49512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  }
49612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
49712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  SataPrivateData->IdentifyValid = AllocateZeroPool ((sizeof (BOOLEAN)) * ChannelDeviceCount);
49812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  if (SataPrivateData->IdentifyValid == NULL) {
49912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    Status = EFI_OUT_OF_RESOURCES;
500379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo Ersek    goto FreeIdentifyData;
50112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  }
50212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
50312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
50412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  // Install IDE Controller Init Protocol to this instance
50512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
50612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  Status = gBS->InstallMultipleProtocolInterfaces (
50712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  &Controller,
50812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  &gEfiIdeControllerInitProtocolGuid,
50912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  &(SataPrivateData->IdeInit),
51012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  NULL
51112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  );
51212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
51312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  if (EFI_ERROR (Status)) {
514379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo Ersek    goto FreeIdentifyValid;
51512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  }
51612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
51712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  DEBUG ((EFI_D_INFO, "SataControllerStart END status = %r\n", Status));
518379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo Ersek  return Status;
519379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo Ersek
520379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo ErsekFreeIdentifyValid:
521379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo Ersek  FreePool (SataPrivateData->IdentifyValid);
522379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo Ersek
523379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo ErsekFreeIdentifyData:
524379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo Ersek  FreePool (SataPrivateData->IdentifyData);
525379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo Ersek
526379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo ErsekFreeDisqualifiedModes:
527379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo Ersek  FreePool (SataPrivateData->DisqualifiedModes);
528379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo Ersek
529379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo ErsekFreeSataPrivateData:
530379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo Ersek  FreePool (SataPrivateData);
531379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo Ersek
532bcab71413407e61c144994925556725dd65eede9Laszlo ErsekRestorePciAttributes:
533bcab71413407e61c144994925556725dd65eede9Laszlo Ersek  PciIo->Attributes (PciIo, EfiPciIoAttributeOperationSet,
534bcab71413407e61c144994925556725dd65eede9Laszlo Ersek           OriginalPciAttributes, NULL);
535bcab71413407e61c144994925556725dd65eede9Laszlo Ersek
536379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo ErsekClosePciIo:
537379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo Ersek  gBS->CloseProtocol (
538379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo Ersek         Controller,
539379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo Ersek         &gEfiPciIoProtocolGuid,
540379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo Ersek         This->DriverBindingHandle,
541379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo Ersek         Controller
542379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo Ersek         );
54312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
544379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo ErsekBail:
545379b17965f0fc3fcf542c606ad628856c2504a2eLaszlo Ersek  DEBUG ((EFI_D_ERROR, "SataControllerStart error return status = %r\n", Status));
54612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  return Status;
54712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh}
54812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
54912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh/**
55012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  Stop this driver on ControllerHandle.
55112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
55212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param This               Protocol instance pointer.
55312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param Controller         Handle of device to stop driver on.
55412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param NumberOfChildren   Not used.
55512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param ChildHandleBuffer  Not used.
55612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
55712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_SUCCESS   This driver is removed from this device.
55812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval other         Some error occurs when removing this driver from this device.
55912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
56012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh**/
56112e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehEFI_STATUS
56212e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehEFIAPI
56312e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehSataControllerStop (
56412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
56512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN EFI_HANDLE                     Controller,
56612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN UINTN                          NumberOfChildren,
56712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN EFI_HANDLE                     *ChildHandleBuffer
56812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  )
56912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh{
57012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  EFI_STATUS                        Status;
57112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  EFI_IDE_CONTROLLER_INIT_PROTOCOL  *IdeInit;
57212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  EFI_SATA_CONTROLLER_PRIVATE_DATA  *SataPrivateData;
57312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
57412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
57512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  // Open the produced protocol
57612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
57712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  Status = gBS->OpenProtocol (
57812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  Controller,
57912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  &gEfiIdeControllerInitProtocolGuid,
58012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  (VOID **) &IdeInit,
58112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  This->DriverBindingHandle,
58212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  Controller,
58312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
58412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  );
58512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  if (EFI_ERROR (Status)) {
58612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    return EFI_UNSUPPORTED;
58712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  }
58812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
58912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  SataPrivateData = SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (IdeInit);
59012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  ASSERT (SataPrivateData != NULL);
59112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
59212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
59312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  // Uninstall the IDE Controller Init Protocol from this instance
59412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
59512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  Status = gBS->UninstallMultipleProtocolInterfaces (
59612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  Controller,
59712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  &gEfiIdeControllerInitProtocolGuid,
59812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  &(SataPrivateData->IdeInit),
59912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  NULL
60012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                  );
60112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  if (EFI_ERROR (Status)) {
60212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    return Status;
60312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  }
60412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
60512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  if (SataPrivateData != NULL) {
60612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    if (SataPrivateData->DisqualifiedModes != NULL) {
60712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      FreePool (SataPrivateData->DisqualifiedModes);
60812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    }
60912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    if (SataPrivateData->IdentifyData != NULL) {
61012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      FreePool (SataPrivateData->IdentifyData);
61112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    }
61212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    if (SataPrivateData->IdentifyValid != NULL) {
61312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      FreePool (SataPrivateData->IdentifyValid);
61412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    }
61512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    FreePool (SataPrivateData);
61612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  }
61712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
61812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
619bcab71413407e61c144994925556725dd65eede9Laszlo Ersek  // Restore original PCI attributes
620bcab71413407e61c144994925556725dd65eede9Laszlo Ersek  //
621bcab71413407e61c144994925556725dd65eede9Laszlo Ersek  SataPrivateData->PciIo->Attributes (
622bcab71413407e61c144994925556725dd65eede9Laszlo Ersek                            SataPrivateData->PciIo,
623bcab71413407e61c144994925556725dd65eede9Laszlo Ersek                            EfiPciIoAttributeOperationSet,
624bcab71413407e61c144994925556725dd65eede9Laszlo Ersek                            SataPrivateData->OriginalPciAttributes,
625bcab71413407e61c144994925556725dd65eede9Laszlo Ersek                            NULL
626bcab71413407e61c144994925556725dd65eede9Laszlo Ersek                            );
627bcab71413407e61c144994925556725dd65eede9Laszlo Ersek
628bcab71413407e61c144994925556725dd65eede9Laszlo Ersek  //
62912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  // Close protocols opened by Sata Controller driver
63012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
63112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  return gBS->CloseProtocol (
63212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                Controller,
63312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                &gEfiPciIoProtocolGuid,
63412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                This->DriverBindingHandle,
63512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                Controller
63612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                );
63712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh}
63812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
63912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh/**
64012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  Calculate the flat array subscript of a (Channel, Device) pair.
64112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
64212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[in] SataPrivateData  The private data structure corresponding to the
64312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                              SATA controller that attaches the device for
64412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                              which the flat array subscript is being
64512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                              calculated.
64612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
64712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[in] Channel          The channel (ie. port) number on the SATA
64812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                              controller that the device is attached to.
64912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
65012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[in] Device           The device number on the channel.
65112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
65212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @return  The flat array subscript suitable for indexing DisqualifiedModes,
65312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh           IdentifyData, and IdentifyValid.
65412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh**/
65512e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehSTATIC
65612e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehUINTN
65712e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehFlatDeviceIndex (
65812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN CONST EFI_SATA_CONTROLLER_PRIVATE_DATA  *SataPrivateData,
65912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN UINTN                                   Channel,
66012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN UINTN                                   Device
66112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  )
66212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh{
66312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  ASSERT (SataPrivateData != NULL);
66412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  ASSERT (Channel < SataPrivateData->IdeInit.ChannelCount);
66512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  ASSERT (Device < SataPrivateData->DeviceCount);
66612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
66712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  return Channel * SataPrivateData->DeviceCount + Device;
66812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh}
66912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
67012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh//
67112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh// Interface functions of IDE_CONTROLLER_INIT protocol
67212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh//
67312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh/**
67412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  Returns the information about the specified IDE channel.
67512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
67612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  This function can be used to obtain information about a particular IDE channel.
67712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  The driver entity uses this information during the enumeration process.
67812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
67912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  If Enabled is set to FALSE, the driver entity will not scan the channel. Note
68012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  that it will not prevent an operating system driver from scanning the channel.
68112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
68212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  For most of today's controllers, MaxDevices will either be 1 or 2. For SATA
68312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  controllers, this value will always be 1. SATA configurations can contain SATA
68412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  port multipliers. SATA port multipliers behave like SATA bridges and can support
68512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  up to 16 devices on the other side. If a SATA port out of the IDE controller
68612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  is connected to a port multiplier, MaxDevices will be set to the number of SATA
68712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  devices that the port multiplier supports. Because today's port multipliers
68812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  support up to fifteen SATA devices, this number can be as large as fifteen. The IDE
68912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  bus driver is required to scan for the presence of port multipliers behind an SATA
69012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  controller and enumerate up to MaxDevices number of devices behind the port
69112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  multiplier.
69212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
69312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  In this context, the devices behind a port multiplier constitute a channel.
69412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
69512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[in]  This         The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
69612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[in]  Channel      Zero-based channel number.
69712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[out] Enabled      TRUE if this channel is enabled.  Disabled channels
69812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                           are not scanned to see if any devices are present.
69912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[out] MaxDevices   The maximum number of IDE devices that the bus driver
70012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                           can expect on this channel.  For the ATA/ATAPI
70112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                           specification, version 6, this number will either be
70212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                           one or two. For Serial ATA (SATA) configurations with a
70312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                           port multiplier, this number can be as large as fifteen.
70412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
70512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_SUCCESS             Information was returned without any errors.
70612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).
70712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
70812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh**/
70912e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehEFI_STATUS
71012e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehEFIAPI
71112e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehIdeInitGetChannelInfo (
71212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,
71312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN UINT8                              Channel,
71412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  OUT BOOLEAN                           *Enabled,
71512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  OUT UINT8                             *MaxDevices
71612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  )
71712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh{
71812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  EFI_SATA_CONTROLLER_PRIVATE_DATA  *SataPrivateData;
71912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  SataPrivateData = SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This);
72012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  ASSERT (SataPrivateData != NULL);
72112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
72212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  if (Channel < This->ChannelCount) {
72312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    *Enabled = TRUE;
72412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    *MaxDevices = SataPrivateData->DeviceCount;
72512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    return EFI_SUCCESS;
72612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  }
72712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
72812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  *Enabled = FALSE;
72912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  return EFI_INVALID_PARAMETER;
73012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh}
73112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
73212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh/**
73312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  The notifications from the driver entity that it is about to enter a certain
73412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  phase of the IDE channel enumeration process.
73512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
73612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  This function can be used to notify the IDE controller driver to perform
73712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  specific actions, including any chipset-specific initialization, so that the
73812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  chipset is ready to enter the next phase. Seven notification points are defined
73912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  at this time.
74012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
74112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  More synchronization points may be added as required in the future.
74212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
74312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[in] This      The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
74412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[in] Phase     The phase during enumeration.
74512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[in] Channel   Zero-based channel number.
74612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
74712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_SUCCESS             The notification was accepted without any errors.
74812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_UNSUPPORTED         Phase is not supported.
74912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).
75012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_NOT_READY           This phase cannot be entered at this time; for
75112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                                  example, an attempt was made to enter a Phase
75212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                                  without having entered one or more previous
75312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                                  Phase.
75412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
75512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh**/
75612e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehEFI_STATUS
75712e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehEFIAPI
75812e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehIdeInitNotifyPhase (
75912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,
76012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN EFI_IDE_CONTROLLER_ENUM_PHASE      Phase,
76112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN UINT8                              Channel
76212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  )
76312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh{
76412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  return EFI_SUCCESS;
76512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh}
76612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
76712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh/**
76812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  Submits the device information to the IDE controller driver.
76912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
77012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  This function is used by the driver entity to pass detailed information about
77112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  a particular device to the IDE controller driver. The driver entity obtains
77212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  this information by issuing an ATA or ATAPI IDENTIFY_DEVICE command. IdentifyData
77312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  is the pointer to the response data buffer. The IdentifyData buffer is owned
77412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  by the driver entity, and the IDE controller driver must make a local copy
77512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  of the entire buffer or parts of the buffer as needed. The original IdentifyData
77612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  buffer pointer may not be valid when
77712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
77812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    - EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() or
77912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    - EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() is called at a later point.
78012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
78112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  The IDE controller driver may consult various fields of EFI_IDENTIFY_DATA to
78212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  compute the optimum mode for the device. These fields are not limited to the
78312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  timing information. For example, an implementation of the IDE controller driver
78412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  may examine the vendor and type/mode field to match known bad drives.
78512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
78612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  The driver entity may submit drive information in any order, as long as it
78712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  submits information for all the devices belonging to the enumeration group
78812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  before EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() is called for any device
78912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  in that enumeration group. If a device is absent, EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()
79012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  should be called with IdentifyData set to NULL.  The IDE controller driver may
79112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  not have any other mechanism to know whether a device is present or not. Therefore,
79212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  setting IdentifyData to NULL does not constitute an error condition.
79312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() can be called only once for a
79412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  given (Channel, Device) pair.
79512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
79612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[in] This           A pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
79712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[in] Channel        Zero-based channel number.
79812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[in] Device         Zero-based device number on the Channel.
79912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[in] IdentifyData   The device's response to the ATA IDENTIFY_DEVICE command.
80012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
80112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_SUCCESS             The information was accepted without any errors.
80212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).
80312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_INVALID_PARAMETER   Device is invalid.
80412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
80512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh**/
80612e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehEFI_STATUS
80712e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehEFIAPI
80812e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehIdeInitSubmitData (
80912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,
81012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN UINT8                              Channel,
81112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN UINT8                              Device,
81212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN EFI_IDENTIFY_DATA                  *IdentifyData
81312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  )
81412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh{
81512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  EFI_SATA_CONTROLLER_PRIVATE_DATA  *SataPrivateData;
81612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  UINTN                             DeviceIndex;
81712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
81812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  SataPrivateData = SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This);
81912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  ASSERT (SataPrivateData != NULL);
82012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
82112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  if ((Channel >= This->ChannelCount) || (Device >= SataPrivateData->DeviceCount)) {
82212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    return EFI_INVALID_PARAMETER;
82312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  }
82412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
82512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  DeviceIndex = FlatDeviceIndex (SataPrivateData, Channel, Device);
82612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
82712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
82812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  // Make a local copy of device's IdentifyData and mark the valid flag
82912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
83012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  if (IdentifyData != NULL) {
83112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    CopyMem (
83212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      &(SataPrivateData->IdentifyData[DeviceIndex]),
83312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      IdentifyData,
83412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      sizeof (EFI_IDENTIFY_DATA)
83512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh      );
83612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
83712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    SataPrivateData->IdentifyValid[DeviceIndex] = TRUE;
83812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  } else {
83912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    SataPrivateData->IdentifyValid[DeviceIndex] = FALSE;
84012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  }
84112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
84212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  return EFI_SUCCESS;
84312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh}
84412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
84512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh/**
84612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  Disqualifies specific modes for an IDE device.
84712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
84812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  This function allows the driver entity or other drivers (such as platform
84912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  drivers) to reject certain timing modes and request the IDE controller driver
85012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  to recalculate modes. This function allows the driver entity and the IDE
85112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  controller driver to negotiate the timings on a per-device basis. This function
85212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  is useful in the case of drives that lie about their capabilities. An example
85312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  is when the IDE device fails to accept the timing modes that are calculated
85412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  by the IDE controller driver based on the response to the Identify Drive command.
85512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
85612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  If the driver entity does not want to limit the ATA timing modes and leave that
85712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  decision to the IDE controller driver, it can either not call this function for
85812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  the given device or call this function and set the Valid flag to FALSE for all
85912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  modes that are listed in EFI_ATA_COLLECTIVE_MODE.
86012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
86112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  The driver entity may disqualify modes for a device in any order and any number
86212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  of times.
86312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
86412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  This function can be called multiple times to invalidate multiple modes of the
86512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  same type (e.g., Programmed Input/Output [PIO] modes 3 and 4). See the ATA/ATAPI
86612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  specification for more information on PIO modes.
86712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
86812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  For Serial ATA (SATA) controllers, this member function can be used to disqualify
86912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  a higher transfer rate mode on a given channel. For example, a platform driver
87012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  may inform the IDE controller driver to not use second-generation (Gen2) speeds
87112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  for a certain SATA drive.
87212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
87312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[in] This       The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
87412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[in] Channel    The zero-based channel number.
87512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[in] Device     The zero-based device number on the Channel.
87612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[in] BadModes   The modes that the device does not support and that
87712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                        should be disqualified.
87812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
87912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_SUCCESS             The modes were accepted without any errors.
88012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).
88112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_INVALID_PARAMETER   Device is invalid.
88212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_INVALID_PARAMETER   IdentifyData is NULL.
88312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
88412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh**/
88512e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehEFI_STATUS
88612e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehEFIAPI
88712e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehIdeInitDisqualifyMode (
88812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,
88912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN UINT8                              Channel,
89012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN UINT8                              Device,
89112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN EFI_ATA_COLLECTIVE_MODE            *BadModes
89212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  )
89312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh{
89412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  EFI_SATA_CONTROLLER_PRIVATE_DATA  *SataPrivateData;
89512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  UINTN                             DeviceIndex;
89612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
89712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  SataPrivateData = SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This);
89812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  ASSERT (SataPrivateData != NULL);
89912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
90012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  if ((Channel >= This->ChannelCount) || (BadModes == NULL) || (Device >= SataPrivateData->DeviceCount)) {
90112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    return EFI_INVALID_PARAMETER;
90212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  }
90312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
90412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  DeviceIndex = FlatDeviceIndex (SataPrivateData, Channel, Device);
90512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
90612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
90712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  // Record the disqualified modes per channel per device. From ATA/ATAPI spec,
90812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  // if a mode is not supported, the modes higher than it is also not supported.
90912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
91012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  CopyMem (
91112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    &(SataPrivateData->DisqualifiedModes[DeviceIndex]),
91212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    BadModes,
91312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    sizeof (EFI_ATA_COLLECTIVE_MODE)
91412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    );
91512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
91612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  return EFI_SUCCESS;
91712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh}
91812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
91912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh/**
92012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  Returns the information about the optimum modes for the specified IDE device.
92112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
92212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  This function is used by the driver entity to obtain the optimum ATA modes for
92312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  a specific device.  The IDE controller driver takes into account the following
92412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  while calculating the mode:
92512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    - The IdentifyData inputs to EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()
92612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    - The BadModes inputs to EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode()
92712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
92812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  The driver entity is required to call EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()
92912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  for all the devices that belong to an enumeration group before calling
93012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() for any device in the same group.
93112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
93212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  The IDE controller driver will use controller- and possibly platform-specific
93312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  algorithms to arrive at SupportedModes.  The IDE controller may base its
93412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  decision on user preferences and other considerations as well. This function
93512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  may be called multiple times because the driver entity may renegotiate the mode
93612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  with the IDE controller driver using EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode().
93712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
93812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  The driver entity may collect timing information for various devices in any
93912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  order. The driver entity is responsible for making sure that all the dependencies
94012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  are satisfied. For example, the SupportedModes information for device A that
94112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  was previously returned may become stale after a call to
94212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() for device B.
94312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
94412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  The buffer SupportedModes is allocated by the callee because the caller does
94512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  not necessarily know the size of the buffer. The type EFI_ATA_COLLECTIVE_MODE
94612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  is defined in a way that allows for future extensibility and can be of variable
94712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  length. This memory pool should be deallocated by the caller when it is no
94812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  longer necessary.
94912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
95012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  The IDE controller driver for a Serial ATA (SATA) controller can use this
95112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  member function to force a lower speed (first-generation [Gen1] speeds on a
95212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  second-generation [Gen2]-capable hardware).  The IDE controller driver can
95312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  also allow the driver entity to stay with the speed that has been negotiated
95412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  by the physical layer.
95512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
95612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[in]  This             The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
95712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[in]  Channel          A zero-based channel number.
95812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[in]  Device           A zero-based device number on the Channel.
95912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[out] SupportedModes   The optimum modes for the device.
96012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
96112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_SUCCESS             SupportedModes was returned.
96212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).
96312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_INVALID_PARAMETER   Device is invalid.
96412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_INVALID_PARAMETER   SupportedModes is NULL.
96512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_NOT_READY           Modes cannot be calculated due to a lack of
96612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                                  data.  This error may happen if
96712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                                  EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()
96812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                                  and EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyData()
96912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                                  were not called for at least one drive in the
97012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                                  same enumeration group.
97112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
97212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh**/
97312e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehEFI_STATUS
97412e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehEFIAPI
97512e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehIdeInitCalculateMode (
97612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,
97712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN UINT8                              Channel,
97812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN UINT8                              Device,
97912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  OUT EFI_ATA_COLLECTIVE_MODE           **SupportedModes
98012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  )
98112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh{
98212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  EFI_SATA_CONTROLLER_PRIVATE_DATA  *SataPrivateData;
98312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  EFI_IDENTIFY_DATA                 *IdentifyData;
98412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  BOOLEAN                           IdentifyValid;
98512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  EFI_ATA_COLLECTIVE_MODE           *DisqualifiedModes;
98612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  UINT16                            SelectedMode;
98712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  EFI_STATUS                        Status;
98812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  UINTN                             DeviceIndex;
98912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
99012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  SataPrivateData = SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This);
99112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  ASSERT (SataPrivateData != NULL);
99212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
99312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  if ((Channel >= This->ChannelCount) || (SupportedModes == NULL) || (Device >= SataPrivateData->DeviceCount)) {
99412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    return EFI_INVALID_PARAMETER;
99512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  }
99612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
99712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  *SupportedModes = AllocateZeroPool (sizeof (EFI_ATA_COLLECTIVE_MODE));
99812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  if (*SupportedModes == NULL) {
99912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    ASSERT (*SupportedModes != NULL);
100012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    return EFI_OUT_OF_RESOURCES;
100112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  }
100212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
100312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  DeviceIndex = FlatDeviceIndex (SataPrivateData, Channel, Device);
100412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
100512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IdentifyData = &(SataPrivateData->IdentifyData[DeviceIndex]);
100612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IdentifyValid = SataPrivateData->IdentifyValid[DeviceIndex];
100712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  DisqualifiedModes = &(SataPrivateData->DisqualifiedModes[DeviceIndex]);
100812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
100912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
101012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  // Make sure we've got the valid identify data of the device from SubmitData()
101112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
101212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  if (!IdentifyValid) {
101312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    FreePool (*SupportedModes);
101412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    return EFI_NOT_READY;
101512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  }
101612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
101712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  Status = CalculateBestPioMode (
101812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh            IdentifyData,
101912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh            (DisqualifiedModes->PioMode.Valid ? ((UINT16 *) &(DisqualifiedModes->PioMode.Mode)) : NULL),
102012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh            &SelectedMode
102112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh            );
102212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  if (!EFI_ERROR (Status)) {
102312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    (*SupportedModes)->PioMode.Valid = TRUE;
102412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    (*SupportedModes)->PioMode.Mode = SelectedMode;
102512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
102612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  } else {
102712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    (*SupportedModes)->PioMode.Valid = FALSE;
102812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  }
102912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  DEBUG ((EFI_D_INFO, "IdeInitCalculateMode: PioMode = %x\n", (*SupportedModes)->PioMode.Mode));
103012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
103112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  Status = CalculateBestUdmaMode (
103212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh            IdentifyData,
103312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh            (DisqualifiedModes->UdmaMode.Valid ? ((UINT16 *) &(DisqualifiedModes->UdmaMode.Mode)) : NULL),
103412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh            &SelectedMode
103512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh            );
103612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
103712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  if (!EFI_ERROR (Status)) {
103812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    (*SupportedModes)->UdmaMode.Valid = TRUE;
103912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    (*SupportedModes)->UdmaMode.Mode  = SelectedMode;
104012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
104112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  } else {
104212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh    (*SupportedModes)->UdmaMode.Valid = FALSE;
104312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  }
104412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  DEBUG ((EFI_D_INFO, "IdeInitCalculateMode: UdmaMode = %x\n", (*SupportedModes)->UdmaMode.Mode));
104512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
104612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
104712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  // The modes other than PIO and UDMA are not supported
104812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  //
104912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  return EFI_SUCCESS;
105012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh}
105112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
105212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh/**
105312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  Commands the IDE controller driver to program the IDE controller hardware
105412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  so that the specified device can operate at the specified mode.
105512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
105612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  This function is used by the driver entity to instruct the IDE controller
105712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  driver to program the IDE controller hardware to the specified modes. This
105812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  function can be called only once for a particular device. For a Serial ATA
105912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  (SATA) Advanced Host Controller Interface (AHCI) controller, no controller-
106012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  specific programming may be required.
106112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
106212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[in] This      Pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
106312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[in] Channel   Zero-based channel number.
106412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[in] Device    Zero-based device number on the Channel.
106512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @param[in] Modes     The modes to set.
106612e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
106712e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_SUCCESS             The command was accepted without any errors.
106812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).
106912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_INVALID_PARAMETER   Device is invalid.
107012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_NOT_READY           Modes cannot be set at this time due to lack of data.
107112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  @retval EFI_DEVICE_ERROR        Modes cannot be set due to hardware failure.
107212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh                                  The driver entity should not use this device.
107312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh
107412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh**/
107512e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehEFI_STATUS
107612e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehEFIAPI
107712e92a23ada7b20e424e782fe1e2d325c22e161cReza JelvehIdeInitSetTiming (
107812e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,
107912e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN UINT8                              Channel,
108012e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN UINT8                              Device,
108112e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  IN EFI_ATA_COLLECTIVE_MODE            *Modes
108212e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  )
108312e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh{
108412e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh  return EFI_SUCCESS;
108512e92a23ada7b20e424e782fe1e2d325c22e161cReza Jelveh}
1086