summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHao Wu <hao.a.wu@intel.com>2016-04-08 16:23:57 +0800
committerHao Wu <hao.a.wu@intel.com>2016-05-12 14:18:08 +0800
commit23a596db1bbf4ad8d4cc297965d1744937586536 (patch)
tree83087710c0f99adfe26d0936626fb22ec48f6144
parentcc4036509e32413570430f7a2f8f92a37190cb6e (diff)
downloadedk2-23a596db1bbf4ad8d4cc297965d1744937586536.tar.gz
edk2-23a596db1bbf4ad8d4cc297965d1744937586536.tar.bz2
edk2-23a596db1bbf4ad8d4cc297965d1744937586536.zip
MdeModulePkg Ata: Use the new (incompatible) PortMultiplierPort semantics
The Mantis ticket 1353 <https://mantis.uefi.org/mantis/view.php?id=1353> and Mantis ticket 1472 <https://mantis.uefi.org/mantis/view.php?id=1472> updated the description of the port multiplier port number parameter in SATA Device Path Node and ATA Pass-Through Protocol. Now, this parameter should be set to 0xFFFF instead of 0 to indicate that an ATA device is directly attached on the controller port. Please note that this is an incompatible change. The consumer of SATA device path or ATA_PASS_THRU needs to re-examine its usage to follow UEFI 2.5 mantis 1353 and 1472. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Hao Wu <hao.a.wu@intel.com> Reviewed-by: Feng Tian <feng.tian@intel.com>
-rw-r--r--MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c2
-rw-r--r--MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c75
-rw-r--r--MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.h12
3 files changed, 66 insertions, 23 deletions
diff --git a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c
index f64a3407e4..b278aa8189 100644
--- a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c
+++ b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c
@@ -2513,7 +2513,7 @@ AhciModeInitialization (
//
// Found a ATA or ATAPI device, add it into the device list.
//
- CreateNewDeviceInfo (Instance, Port, 0, DeviceType, &Buffer);
+ CreateNewDeviceInfo (Instance, Port, 0xFFFF, DeviceType, &Buffer);
if (DeviceType == EfiIdeHarddisk) {
REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_PERIPHERAL_FIXED_MEDIA | EFI_P_PC_ENABLE));
}
diff --git a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c
index 870900f106..2389d54926 100644
--- a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c
+++ b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c
@@ -2,7 +2,7 @@
This file implements ATA_PASSTHRU_PROCTOCOL and EXT_SCSI_PASSTHRU_PROTOCOL interfaces
for managed ATA controllers.
- Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@@ -148,7 +148,7 @@ UINT8 mScsiId[TARGET_MAX_BYTES] = {
@param[in] Port The port number of the ATA device to send the command.
@param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.
- If there is no port multiplier, then specify 0.
+ If there is no port multiplier, then specify 0xFFFF.
@param[in, out] Packet A pointer to the ATA command to send to the ATA device specified by Port
and PortMultiplierPort.
@param[in] Instance Pointer to the ATA_ATAPI_PASS_THRU_INSTANCE.
@@ -272,6 +272,14 @@ AtaPassThruPassThruExecute (
}
break;
case EfiAtaAhciMode :
+ if (PortMultiplierPort == 0xFFFF) {
+ //
+ // If there is no port multiplier, PortMultiplierPort will be 0xFFFF
+ // according to UEFI spec. Here, we convert its value to 0 to follow
+ // AHCI spec.
+ //
+ PortMultiplierPort = 0;
+ }
switch (Protocol) {
case EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA:
Status = AhciNonDataTransfer (
@@ -982,7 +990,7 @@ AtaAtapiPassThruStop (
@param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
@param[in] Port The port number of the ATA device to send the command.
@param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.
- If there is no port multiplier, then specify 0.
+ If there is no port multiplier, then specify 0xFFFF.
@param[in] DeviceType The device type of the ATA device.
@retval The pointer to the data structure of the device info to access.
@@ -1004,6 +1012,18 @@ SearchDeviceInfoList (
while (!IsNull (&Instance->DeviceList, Node)) {
DeviceInfo = ATA_ATAPI_DEVICE_INFO_FROM_THIS (Node);
+ //
+ // For CD-ROM working in the AHCI mode, only 8 bits are used to record
+ // the PortMultiplier information. If the CD-ROM is directly attached
+ // on a SATA port, the PortMultiplier should be translated from 0xFF
+ // to 0xFFFF according to the UEFI spec.
+ //
+ if ((Instance->Mode == EfiAtaAhciMode) &&
+ (DeviceInfo->Type == EfiIdeCdrom) &&
+ (PortMultiplier == 0xFF)) {
+ PortMultiplier = 0xFFFF;
+ }
+
if ((DeviceInfo->Type == DeviceType) &&
(Port == DeviceInfo->Port) &&
(PortMultiplier == DeviceInfo->PortMultiplier)) {
@@ -1023,7 +1043,7 @@ SearchDeviceInfoList (
@param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
@param[in] Port The port number of the ATA device to send the command.
@param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.
- If there is no port multiplier, then specify 0.
+ If there is no port multiplier, then specify 0xFFFF.
@param[in] DeviceType The device type of the ATA device.
@param[in] IdentifyData The data buffer to store the output of the IDENTIFY cmd.
@@ -1216,7 +1236,7 @@ Done:
@param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.
@param[in] Port The port number of the ATA device to send the command.
@param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.
- If there is no port multiplier, then specify 0.
+ If there is no port multiplier, then specify 0xFFFF.
@param[in, out] Packet A pointer to the ATA command to send to the ATA device specified by Port
and PortMultiplierPort.
@param[in] Event If non-blocking I/O is not supported then Event is ignored, and blocking
@@ -1531,17 +1551,25 @@ AtaPassThruGetNextDevice (
return EFI_INVALID_PARAMETER;
}
- if (*PortMultiplierPort == 0xFFFF) {
+ if (Instance->PreviousPortMultiplier == 0xFFFF) {
//
- // If the PortMultiplierPort is all 0xFF's, start to traverse the device list from the beginning
+ // If a device is directly attached on a port, previous call to this
+ // function will return the value 0xFFFF for PortMultiplierPort. In
+ // this case, there should be no more device on the port multiplier.
//
+ Instance->PreviousPortMultiplier = 0;
+ return EFI_NOT_FOUND;
+ }
+
+ if (*PortMultiplierPort == Instance->PreviousPortMultiplier) {
Node = GetFirstNode (&Instance->DeviceList);
while (!IsNull (&Instance->DeviceList, Node)) {
DeviceInfo = ATA_ATAPI_DEVICE_INFO_FROM_THIS (Node);
if ((DeviceInfo->Type == EfiIdeHarddisk) &&
- (DeviceInfo->Port == Port)){
+ (DeviceInfo->Port == Port) &&
+ (DeviceInfo->PortMultiplier > *PortMultiplierPort)){
*PortMultiplierPort = DeviceInfo->PortMultiplier;
goto Exit;
}
@@ -1550,15 +1578,17 @@ AtaPassThruGetNextDevice (
}
return EFI_NOT_FOUND;
- } else if (*PortMultiplierPort == Instance->PreviousPortMultiplier) {
+ } else if (*PortMultiplierPort == 0xFFFF) {
+ //
+ // If the PortMultiplierPort is all 0xFF's, start to traverse the device list from the beginning
+ //
Node = GetFirstNode (&Instance->DeviceList);
while (!IsNull (&Instance->DeviceList, Node)) {
DeviceInfo = ATA_ATAPI_DEVICE_INFO_FROM_THIS (Node);
if ((DeviceInfo->Type == EfiIdeHarddisk) &&
- (DeviceInfo->Port == Port) &&
- (DeviceInfo->PortMultiplier > *PortMultiplierPort)){
+ (DeviceInfo->Port == Port)){
*PortMultiplierPort = DeviceInfo->PortMultiplier;
goto Exit;
}
@@ -1601,7 +1631,7 @@ Exit:
device path node is to be allocated and built.
@param[in] PortMultiplierPort The port multiplier port number of the ATA device for which a
device path node is to be allocated and built. If there is no
- port multiplier, then specify 0.
+ port multiplier, then specify 0xFFFF.
@param[in, out] DevicePath A pointer to a single device path node that describes the ATA
device specified by Port and PortMultiplierPort. This function
is responsible for allocating the buffer DevicePath with the
@@ -1812,7 +1842,7 @@ AtaPassThruResetPort (
@param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.
@param[in] Port Port represents the port number of the ATA device to be reset.
@param[in] PortMultiplierPort The port multiplier port number of the ATA device to reset.
- If there is no port multiplier, then specify 0.
+ If there is no port multiplier, then specify 0xFFFF.
@retval EFI_SUCCESS The ATA device specified by Port and PortMultiplierPort was reset.
@retval EFI_UNSUPPORTED The ATA controller does not support a device reset operation.
@retval EFI_INVALID_PARAMETER Port or PortMultiplierPort are invalid.
@@ -2049,6 +2079,13 @@ ExtScsiPassThruPassThru (
Status = AtaPacketCommandExecute (Instance->PciIo, &Instance->IdeRegisters[Port], Port, PortMultiplier, Packet);
break;
case EfiAtaAhciMode:
+ if (PortMultiplier == 0xFF) {
+ //
+ // If there is no port multiplier, the PortMultiplier will be 0xFF
+ // Here, we convert its value to 0 to follow the AHCI spec.
+ //
+ PortMultiplier = 0;
+ }
Status = AhciPacketCommandExecute (Instance->PciIo, &Instance->AhciRegisters, Port, PortMultiplier, Packet);
break;
default :
@@ -2186,7 +2223,7 @@ ExtScsiPassThruGetNextTargetLun (
if ((DeviceInfo->Type == EfiIdeCdrom) &&
((Target8[0] < DeviceInfo->Port) ||
((Target8[0] == DeviceInfo->Port) &&
- (Target8[1] < DeviceInfo->PortMultiplier)))) {
+ (Target8[1] < (UINT8)DeviceInfo->PortMultiplier)))) {
Target8[0] = (UINT8)DeviceInfo->Port;
Target8[1] = (UINT8)DeviceInfo->PortMultiplier;
goto Exit;
@@ -2308,7 +2345,13 @@ ExtScsiPassThruBuildDevicePath (
}
DevicePathNode->Sata.HBAPortNumber = Port;
- DevicePathNode->Sata.PortMultiplierPortNumber = PortMultiplier;
+ //
+ // For CD-ROM working in the AHCI mode, only 8 bits are used to record
+ // the PortMultiplier information. If the CD-ROM is directly attached
+ // on a SATA port, the PortMultiplier should be translated from 0xFF
+ // to 0xFFFF according to the UEFI spec.
+ //
+ DevicePathNode->Sata.PortMultiplierPortNumber = PortMultiplier == 0xFF ? 0xFFFF : PortMultiplier;
DevicePathNode->Sata.Lun = (UINT16) Lun;
}
@@ -2562,7 +2605,7 @@ ExtScsiPassThruGetNextTarget (
if ((DeviceInfo->Type == EfiIdeCdrom) &&
((Target8[0] < DeviceInfo->Port) ||
((Target8[0] == DeviceInfo->Port) &&
- (Target8[1] < DeviceInfo->PortMultiplier)))) {
+ (Target8[1] < (UINT8)DeviceInfo->PortMultiplier)))) {
Target8[0] = (UINT8)DeviceInfo->Port;
Target8[1] = (UINT8)DeviceInfo->PortMultiplier;
goto Exit;
diff --git a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.h b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.h
index 6f3407c01a..4f327dc30b 100644
--- a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.h
+++ b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.h
@@ -1,7 +1,7 @@
/** @file
Header file for ATA/ATAPI PASS THRU driver.
- Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@@ -437,7 +437,7 @@ AtaAtapiPassThruStop (
@param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
@param[in] Port The port number of the ATA device to send the command.
@param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.
- If there is no port multiplier, then specify 0.
+ If there is no port multiplier, then specify 0xFFFF.
@param[in] DeviceType The device type of the ATA device.
@retval The pointer to the data structure of the device info to access.
@@ -459,7 +459,7 @@ SearchDeviceInfoList (
@param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
@param[in] Port The port number of the ATA device to send the command.
@param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.
- If there is no port multiplier, then specify 0.
+ If there is no port multiplier, then specify 0xFFFF.
@param[in] DeviceType The device type of the ATA device.
@param[in] IdentifyData The data buffer to store the output of the IDENTIFY cmd.
@@ -544,7 +544,7 @@ AsyncNonBlockingTransferRoutine (
@param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.
@param[in] Port The port number of the ATA device to send the command.
@param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.
- If there is no port multiplier, then specify 0.
+ If there is no port multiplier, then specify 0xFFFF.
@param[in, out] Packet A pointer to the ATA command to send to the ATA device specified by Port
and PortMultiplierPort.
@param[in] Event If non-blocking I/O is not supported then Event is ignored, and blocking
@@ -681,7 +681,7 @@ AtaPassThruGetNextDevice (
device path node is to be allocated and built.
@param[in] PortMultiplierPort The port multiplier port number of the ATA device for which a
device path node is to be allocated and built. If there is no
- port multiplier, then specify 0.
+ port multiplier, then specify 0xFFFF.
@param[in, out] DevicePath A pointer to a single device path node that describes the ATA
device specified by Port and PortMultiplierPort. This function
is responsible for allocating the buffer DevicePath with the
@@ -802,7 +802,7 @@ AtaPassThruResetPort (
@param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.
@param[in] Port Port represents the port number of the ATA device to be reset.
@param[in] PortMultiplierPort The port multiplier port number of the ATA device to reset.
- If there is no port multiplier, then specify 0.
+ If there is no port multiplier, then specify 0xFFFF.
@retval EFI_SUCCESS The ATA device specified by Port and PortMultiplierPort was reset.
@retval EFI_UNSUPPORTED The ATA controller does not support a device reset operation.
@retval EFI_INVALID_PARAMETER Port or PortMultiplierPort are invalid.