X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FBus%2FAta%2FAtaAtapiPassThru%2FAhciMode.c;h=4d01c1dd7fca2c70d97250e9bace7840135e4d09;hp=f64a3407e4687d6902656d0716e748c10943006e;hb=6052a15f4a4297b430cf03f2456e51f8d3bb4598;hpb=9c32277a3f9dd7df6a71d544caffc90aab5f8e48 diff --git a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c index f64a3407e4..4d01c1dd7f 100644 --- a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c +++ b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c @@ -1,7 +1,7 @@ /** @file The file for AHCI mode of ATA host controller. - Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+ Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.
(C) Copyright 2015 Hewlett Packard Enterprise Development LP
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -371,6 +371,7 @@ AhciClearPortStatus ( in the Status Register, the Error Register's value is also be dumped. @param PciIo The PCI IO protocol instance. + @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS. @param Port The number of port. @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure. @@ -379,24 +380,42 @@ VOID EFIAPI AhciDumpPortStatus ( IN EFI_PCI_IO_PROTOCOL *PciIo, + IN EFI_AHCI_REGISTERS *AhciRegisters, IN UINT8 Port, IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock ) { - UINT32 Offset; + UINTN Offset; UINT32 Data; + UINTN FisBaseAddr; + EFI_STATUS Status; ASSERT (PciIo != NULL); - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD; - Data = AhciReadReg (PciIo, Offset); - if (AtaStatusBlock != NULL) { ZeroMem (AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK)); - AtaStatusBlock->AtaStatus = (UINT8)Data; - if ((AtaStatusBlock->AtaStatus & BIT0) != 0) { - AtaStatusBlock->AtaError = (UINT8)(Data >> 8); + FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS); + Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET; + + Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_REGISTER_D2H, NULL); + if (!EFI_ERROR (Status)) { + // + // If D2H FIS is received, update StatusBlock with its content. + // + CopyMem (AtaStatusBlock, (UINT8 *)Offset, sizeof (EFI_ATA_STATUS_BLOCK)); + } else { + // + // If D2H FIS is not received, only update Status & Error field through PxTFD + // as there is no other way to get the content of the Shadow Register Block. + // + Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD; + Data = AhciReadReg (PciIo, (UINT32)Offset); + + AtaStatusBlock->AtaStatus = (UINT8)Data; + if ((AtaStatusBlock->AtaStatus & BIT0) != 0) { + AtaStatusBlock->AtaError = (UINT8)(Data >> 8); + } } } } @@ -427,13 +446,7 @@ AhciEnableFisReceive ( Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD; AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_FRE); - return AhciWaitMmioSet ( - PciIo, - Offset, - EFI_AHCI_PORT_CMD_FR, - EFI_AHCI_PORT_CMD_FR, - Timeout - ); + return EFI_SUCCESS; } /** @@ -872,7 +885,7 @@ Exit: Map ); - AhciDumpPortStatus (PciIo, Port, AtaStatusBlock); + AhciDumpPortStatus (PciIo, AhciRegisters, Port, AtaStatusBlock); return Status; } @@ -1091,7 +1104,7 @@ Exit: } } - AhciDumpPortStatus (PciIo, Port, AtaStatusBlock); + AhciDumpPortStatus (PciIo, AhciRegisters, Port, AtaStatusBlock); return Status; } @@ -1207,7 +1220,7 @@ Exit: Timeout ); - AhciDumpPortStatus (PciIo, Port, AtaStatusBlock); + AhciDumpPortStatus (PciIo, AhciRegisters, Port, AtaStatusBlock); return Status; } @@ -1438,17 +1451,13 @@ AhciReset ( { UINT64 Delay; UINT32 Value; - UINT32 Capability; // - // Collect AHCI controller information - // - Capability = AhciReadReg (PciIo, EFI_AHCI_CAPABILITY_OFFSET); - - // - // Enable AE before accessing any AHCI registers if Supports AHCI Mode Only is not set + // Make sure that GHC.AE bit is set before accessing any AHCI registers. // - if ((Capability & EFI_AHCI_CAP_SAM) == 0) { + Value = AhciReadReg(PciIo, EFI_AHCI_GHC_OFFSET); + + if ((Value & EFI_AHCI_GHC_ENABLE) == 0) { AhciOrReg (PciIo, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE); } @@ -1484,7 +1493,7 @@ AhciReset ( @param PciIo The PCI IO protocol instance. @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS. @param Port The number of port. - @param PortMultiplier The timeout value of stop. + @param PortMultiplier The port multiplier port number. @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure. @retval EFI_SUCCESS Successfully get the return status of S.M.A.R.T command execution. @@ -1582,7 +1591,7 @@ AhciAtaSmartReturnStatusCheck ( @param PciIo The PCI IO protocol instance. @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS. @param Port The number of port. - @param PortMultiplier The timeout value of stop. + @param PortMultiplier The port multiplier port number. @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data. @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure. @@ -1698,7 +1707,7 @@ AhciAtaSmartSupport ( @param PciIo The PCI IO protocol instance. @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS. @param Port The number of port. - @param PortMultiplier The timeout value of stop. + @param PortMultiplier The port multiplier port number. @param Buffer The data buffer to store IDENTIFY PACKET data. @retval EFI_DEVICE_ERROR The cmd abort with error occurs. @@ -1756,7 +1765,7 @@ AhciIdentify ( @param PciIo The PCI IO protocol instance. @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS. @param Port The number of port. - @param PortMultiplier The timeout value of stop. + @param PortMultiplier The port multiplier port number. @param Buffer The data buffer to store IDENTIFY PACKET data. @retval EFI_DEVICE_ERROR The cmd abort with error occurs. @@ -1814,7 +1823,7 @@ AhciIdentifyPacket ( @param PciIo The PCI IO protocol instance. @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS. @param Port The number of port. - @param PortMultiplier The timeout value of stop. + @param PortMultiplier The port multiplier port number. @param Feature The data to send Feature register. @param FeatureSpecificData The specific data for SET FEATURE cmd. @@ -2239,6 +2248,7 @@ AhciModeInitialization ( EFI_ATA_COLLECTIVE_MODE *SupportedModes; EFI_ATA_TRANSFER_MODE TransferMode; UINT32 PhyDetectDelay; + UINT32 Value; if (Instance == NULL) { return EFI_INVALID_PARAMETER; @@ -2257,14 +2267,34 @@ AhciModeInitialization ( // Collect AHCI controller information // Capability = AhciReadReg (PciIo, EFI_AHCI_CAPABILITY_OFFSET); - + // - // Enable AE before accessing any AHCI registers if Supports AHCI Mode Only is not set + // Make sure that GHC.AE bit is set before accessing any AHCI registers. // - if ((Capability & EFI_AHCI_CAP_SAM) == 0) { + Value = AhciReadReg(PciIo, EFI_AHCI_GHC_OFFSET); + + if ((Value & EFI_AHCI_GHC_ENABLE) == 0) { AhciOrReg (PciIo, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE); } - + + // + // Enable 64-bit DMA support in the PCI layer if this controller + // supports it. + // + if ((Capability & EFI_AHCI_CAP_S64A) != 0) { + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE, + NULL + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_WARN, + "AhciModeInitialization: failed to enable 64-bit DMA on 64-bit capable controller (%r)\n", + Status)); + } + } + // // Get the number of command slots per port supported by this HBA. // @@ -2344,16 +2374,6 @@ AhciModeInitialization ( // Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD; AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_FRE); - Status = AhciWaitMmioSet ( - PciIo, - Offset, - EFI_AHCI_PORT_CMD_FR, - EFI_AHCI_PORT_CMD_FR, - EFI_AHCI_PORT_CMD_FR_CLEAR_TIMEOUT - ); - if (EFI_ERROR (Status)) { - continue; - } // // Wait no longer than 10 ms to wait the Phy to detect the presence of a device. @@ -2513,7 +2533,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)); }