From nobody Fri Apr 26 12:35:01 2024 Delivered-To: importer@patchew.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Authentication-Results: mx.zoho.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org; Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1487889251923475.94360955633397; Thu, 23 Feb 2017 14:34:11 -0800 (PST) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 4A51882192; Thu, 23 Feb 2017 14:34:07 -0800 (PST) Received: from foss.arm.com (foss.arm.com [217.140.101.70]) by ml01.01.org (Postfix) with ESMTP id D287C82176 for ; Thu, 23 Feb 2017 14:34:03 -0800 (PST) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id BE02828; Thu, 23 Feb 2017 14:34:03 -0800 (PST) Received: from u200856.usa.arm.com (u201426.usa.arm.com [10.118.28.62]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 685BA3F483; Thu, 23 Feb 2017 14:34:03 -0800 (PST) X-Original-To: edk2-devel@lists.01.org From: Jeremy Linton To: edk2-devel@lists.01.org Date: Thu, 23 Feb 2017 16:33:52 -0600 Message-Id: <20170223223355.11383-6-jeremy.linton@arm.com> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20170223223355.11383-1-jeremy.linton@arm.com> References: <20170223223355.11383-1-jeremy.linton@arm.com> Subject: [edk2] [PATCH v3 5/7] EmbeddedPkg: SiI3132: Break out FIS command submission X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: ard.biesheuvel@linaro.org, Steve.Capper@arm.com, ryan.harkin@linaro.org, leif.lindholm@linaro.org, linaro-uefi@lists.linaro.org MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" The existing ATA pass-through routine builds the FIS and handles submission to the hardware. Break out the FIS submission part so that it can be utilized by the SCSI pass-through. Also, tighten up the error handling a bit. Starting with removal of the ASSERTs on errors. ATAPI like SCSI uses check conditions to indicate device state changes. So these error paths can get exercised on CD disk change/etc. Further we want the clamp the timeouts within a range rather than spinning forever if the port fails to become ready. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jeremy Linton --- .../Drivers/SataSiI3132Dxe/SiI3132AtaPassThru.c | 225 +++++++++++++----= ---- OpenPlatformPkg | 2 +- 2 files changed, 138 insertions(+), 89 deletions(-) diff --git a/EmbeddedPkg/Drivers/SataSiI3132Dxe/SiI3132AtaPassThru.c b/Embe= ddedPkg/Drivers/SataSiI3132Dxe/SiI3132AtaPassThru.c index 2fb5fd6..601583d 100644 --- a/EmbeddedPkg/Drivers/SataSiI3132Dxe/SiI3132AtaPassThru.c +++ b/EmbeddedPkg/Drivers/SataSiI3132Dxe/SiI3132AtaPassThru.c @@ -22,7 +22,8 @@ GetSataDevice ( IN SATA_SI3132_INSTANCE* SataInstance, IN UINT16 Port, IN UINT16 PortMultiplierPort -) { + ) +{ LIST_ENTRY *List; SATA_SI3132_PORT *SataPort; SATA_SI3132_DEVICE *SataDevice; @@ -44,6 +45,124 @@ GetSataDevice ( return NULL; } =20 +UINT32 +SiI3231DeviceReady ( + IN SATA_SI3132_PORT *SataPort, + IN EFI_PCI_IO_PROTOCOL *PciIo + ) +{ + UINT32 Value32; + UINT32 Timeout; + Timeout =3D SI_DEFAULT_TIMEOUT; + + do { + SATA_PORT_READ32 (SataPort->RegBase + SII3132_PORT_STATUS_REG, &Value3= 2); + Timeout--; + } while (Timeout && !(Value32 & SII3132_PORT_STATUS_PORTREADY)); + if (Timeout =3D=3D 0) { + DEBUG ((DEBUG_WARN, "SiI3132AtaPassThru() Device not ready, try anyway= \n")); + //Consider doing a device reset here. + } + + return Timeout; +} + +EFI_STATUS +SiI3132IssueCommand ( + IN SATA_SI3132_PORT *SataPort, + EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 Timeout, + VOID *StatusBlock + ) +{ + UINT32 IrqMask; + UINT32 Value32, Error; + UINTN EmptySlot; + EFI_STATUS Status; + + IrqMask =3D (SII3132_PORT_INT_CMDCOMPL | SII3132_PORT_INT_CMDERR) << 16; + EmptySlot =3D 0; + SiI3231DeviceReady (SataPort, PciIo); + // Clear IRQ + SATA_PORT_WRITE32 (SataPort->RegBase + SII3132_PORT_INTSTATUS_REG, IrqMa= sk); + + if (!FeaturePcdGet (PcdSataSiI3132FeatureDirectCommandIssuing)) { + // Indirect Command Issuance + + //TODO: Find which slot is free (maybe use the Cmd FIFO) + //SATA_PORT_READ32 (SataPort->RegBase + SII3132_PORT_CMDEXECFIFO_REG, = &EmptySlot); + SATA_PORT_WRITE32 (SataPort->RegBase + SII3132_PORT_CMDACTIV_REG + (Em= ptySlot * 8), + (UINT32)(SataPort->PhysAddrHostPRB & 0xFFFFFFFF)); + SATA_PORT_WRITE32 (SataPort->RegBase + SII3132_PORT_CMDACTIV_REG + (Em= ptySlot * 8) + 4, + (UINT32)((SataPort->PhysAddrHostPRB >> 32) & 0xFFFFFF= FF)); + } else { + // Direct Command Issuance + DEBUG ((DEBUG_ERROR ,"SiI3132AtaPassThru() Untested path\n")); + Status =3D PciIo->Mem.Write (PciIo, EfiPciIoWidthUint32, 1, // Bar 1 + SataPort->RegBase + (EmptySlot * 0x80), + sizeof (SATA_SI3132_PRB) / 4, + SataPort->HostPRB); + ASSERT_EFI_ERROR (Status); + + SATA_PORT_WRITE32 (SataPort->RegBase + SII3132_PORT_CMDEXECFIFO_REG, E= mptySlot); + } + + // Clamp the timeout range + if (Timeout < 1) { + Timeout =3D SI_DEFAULT_TIMEOUT; + } else if (Timeout > SI_DEFAULT_TIMEOUT) { + Timeout =3D SI_DEFAULT_TIMEOUT; + } + + SATA_PORT_READ32 (SataPort->RegBase + SII3132_PORT_INTSTATUS_REG, &Value= 32); + while (Timeout && !(Value32 & IrqMask)) { + gBS->Stall (1); + SATA_PORT_READ32 (SataPort->RegBase + SII3132_PORT_INTSTATUS_REG, &Val= ue32); + Timeout--; + } + + // Fill Packet Ata Status Block + Status =3D PciIo->Mem.Read (PciIo, EfiPciIoWidthUint32, 1, // Bar 1 + SataPort->RegBase + 0x08, + sizeof (EFI_ATA_STATUS_BLOCK) / 4, + StatusBlock); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SiI3132AtaPassThru() status (%d) block %X %X\n",= Status, SataPort->RegBase, StatusBlock)); + } + + if (Timeout =3D=3D 0) { + DEBUG ((DEBUG_ERROR, "SiI3132AtaPassThru() Err:Timeout\n")); + // Flush the command, reinit port + SATA_PORT_WRITE32 (SataPort->RegBase + SII3132_PORT_CONTROLSET_REG, SI= I3132_PORT_CONTROL_INT); + SiI3231DeviceReady (SataPort, PciIo); + Status =3D EFI_TIMEOUT; + + } else if (Value32 & (SII3132_PORT_INT_CMDERR << 16)) { + UINT32 Serror; + + SATA_PORT_READ32 (SataPort->RegBase + SII3132_PORT_CMDERROR_REG, &Erro= r); + SATA_PORT_READ32 (SataPort->RegBase + SII3132_PORT_SERROR_REG, &Serror= ); + SATA_PORT_WRITE32 (SataPort->RegBase + SII3132_PORT_INTSTATUS_REG, Val= ue32 & 0xFF00); //clear error bits + + DEBUG ((DEBUG_INFO, "SiI3132AtaPassThru() CmdErr:0x%X (SiI3132 Err:0x%= X) (STATUS: %X ERROR:%X) SERROR=3D%X\n", + Value32, Error, SataPort->HostPRB->Fis.Command,SataPort->HostP= RB->Fis.Features, Serror)); + + // clear port status + SATA_PORT_WRITE32 (SataPort->RegBase + SII3132_PORT_CONTROLSET_REG, SI= I3132_PORT_CONTROL_INT); + SiI3231DeviceReady (SataPort, PciIo); + Status =3D EFI_DEVICE_ERROR; + + } else if (Value32 & (SII3132_PORT_INT_CMDCOMPL << 16)) { + // Clear Command Complete + SATA_PORT_WRITE32 (SataPort->RegBase + SII3132_PORT_INTSTATUS_REG, SII= 3132_PORT_INT_CMDCOMPL << 16); + Status =3D EFI_SUCCESS; + + } + + return Status; +} + EFI_STATUS SiI3132AtaPassThruCommand ( IN SATA_SI3132_INSTANCE *SataSiI3132Instance, @@ -58,18 +177,14 @@ SiI3132AtaPassThruCommand ( UINTN InDataBufferLength =3D 0; EFI_PHYSICAL_ADDRESS PhysOutDataBuffer; UINTN OutDataBufferLength; - CONST UINTN EmptySlot =3D 0; UINTN Control =3D PRB_CTRL_ATA; - UINTN Protocol =3D 0; - UINT32 Value32, Error, Timeout =3D 0; - CONST UINT32 IrqMask =3D (SII3132_PORT_INT_CMDCOMPL | SII3132= _PORT_INT_CMDERR) << 16; + UINTN Protocol =3D PRB_PROT_DEFAULT; EFI_STATUS Status; VOID* PciAllocMapping =3D NULL; EFI_PCI_IO_PROTOCOL *PciIo; =20 PciIo =3D SataSiI3132Instance->PciIo; ZeroMem (SataPort->HostPRB, sizeof (SATA_SI3132_PRB)); - // Construct Si3132 PRB switch (Packet->Protocol) { case EFI_ATA_PASS_THRU_PROTOCOL_ATA_HARDWARE_RESET: @@ -92,7 +207,8 @@ SiI3132AtaPassThruCommand ( case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN: // Fixup the size for block transfer. Following UEFI Specification, 'I= nTransferLength' should // be in number of bytes. But for most data transfer commands, the val= ue is in number of blocks - if (Packet->Acb->AtaCommand =3D=3D ATA_CMD_IDENTIFY_DRIVE) { + if ( (Packet->Acb->AtaCommand =3D=3D ATA_CMD_IDENTIFY_DRIVE) || + (Packet->Acb->AtaCommand =3D=3D ATA_CMD_IDENTIFY_DEVICE) ) { InDataBufferLength =3D Packet->InTransferLength; } else { SataDevice =3D GetSataDevice (SataSiI3132Instance, SataPort->Index, = PortMultiplierPort); @@ -108,6 +224,7 @@ SiI3132AtaPassThruCommand ( Packet->InDataBuffer, &InDataBufferLength, &PhysInDataBuffe= r, &PciAllocMapping ); if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SiI map() failure %d\n", Status)); return Status; } =20 @@ -121,8 +238,8 @@ SiI3132AtaPassThruCommand ( CopyMem (&SataPort->HostPRB->Fis, Packet->Acb, sizeof (EFI_ATA_COMMAND= _BLOCK)); =20 // Fixup the FIS - SataPort->HostPRB->Fis.FisType =3D 0x27; // Register - Host to Device = FIS - SataPort->HostPRB->Fis.Control =3D 1 << 7; // Is a command + SataPort->HostPRB->Fis.FisType =3D SII_FIS_REGISTER_H2D; // Register -= Host to Device FIS + SataPort->HostPRB->Fis.Control =3D SII_FIS_CONTROL_CMD; // Is a command if (FeaturePcdGet (PcdSataSiI3132FeaturePMPSupport)) { SataPort->HostPRB->Fis.Control |=3D PortMultiplierPort & 0xFF; } @@ -188,81 +305,10 @@ SiI3132AtaPassThruCommand ( SataPort->HostPRB->Control =3D Control; SataPort->HostPRB->ProtocolOverride =3D Protocol; =20 - // Clear IRQ - SATA_PORT_WRITE32 (SataPort->RegBase + SII3132_PORT_INTSTATUS_REG, IrqMa= sk); - - if (!FeaturePcdGet (PcdSataSiI3132FeatureDirectCommandIssuing)) { - // Indirect Command Issuance - - //TODO: Find which slot is free (maybe use the Cmd FIFO) - //SATA_PORT_READ32 (SataPort->RegBase + SII3132_PORT_CMDEXECFIFO_REG, = &EmptySlot); - - SATA_PORT_WRITE32 (SataPort->RegBase + SII3132_PORT_CMDACTIV_REG + (Em= ptySlot * 8), - (UINT32)(SataPort->PhysAddrHostPRB & 0xFFFFFFFF)); - SATA_PORT_WRITE32 (SataPort->RegBase + SII3132_PORT_CMDACTIV_REG + (Em= ptySlot * 8) + 4, - (UINT32)((SataPort->PhysAddrHostPRB >> 32) & 0xFFFFFF= FF)); - } else { - // Direct Command Issuance - Status =3D PciIo->Mem.Write (PciIo, EfiPciIoWidthUint32, 1, // Bar 1 - SataPort->RegBase + (EmptySlot * 0x80), - sizeof (SATA_SI3132_PRB) / 4, - SataPort->HostPRB); - ASSERT_EFI_ERROR (Status); - - SATA_PORT_WRITE32 (SataPort->RegBase + SII3132_PORT_CMDEXECFIFO_REG, E= mptySlot); - } - -#if 0 - // Could need to be implemented if we run multiple command in parallel t= o know which slot has been completed - SATA_PORT_READ32 (SataPort->RegBase + SII3132_PORT_SLOTSTATUS_REG, &Valu= e32); - Timeout =3D Packet->Timeout; - while (!Timeout && !Value32) { - gBS->Stall (1); - SATA_PORT_READ32 (SataPort->RegBase + SII3132_PORT_SLOTSTATUS_REG, &Va= lue32); - Timeout--; - } -#else - SATA_PORT_READ32 (SataPort->RegBase + SII3132_PORT_INTSTATUS_REG, &Value= 32); - if (!Packet->Timeout) { - while (!(Value32 & IrqMask)) { - gBS->Stall (1); - SATA_PORT_READ32 (SataPort->RegBase + SII3132_PORT_INTSTATUS_REG, &V= alue32); - } - } else { - Timeout =3D Packet->Timeout; - while (Timeout && !(Value32 & IrqMask)) { - gBS->Stall (1); - SATA_PORT_READ32 (SataPort->RegBase + SII3132_PORT_INTSTATUS_REG, &V= alue32); - Timeout--; - } - } -#endif - // Fill Packet Ata Status Block - Status =3D PciIo->Mem.Read (PciIo, EfiPciIoWidthUint32, 1, // Bar 1 - SataPort->RegBase + 0x08, - sizeof (EFI_ATA_STATUS_BLOCK) / 4, - Packet->Asb); - ASSERT_EFI_ERROR (Status); - - - if ((Packet->Timeout !=3D 0) && (Timeout =3D=3D 0)) { - DEBUG ((EFI_D_ERROR, "SiI3132AtaPassThru() Err:Timeout\n")); - //ASSERT (0); - return EFI_TIMEOUT; - } else if (Value32 & (SII3132_PORT_INT_CMDERR << 16)) { - SATA_PORT_READ32 (SataPort->RegBase + SII3132_PORT_CMDERROR_REG, &Erro= r); - DEBUG ((EFI_D_ERROR, "SiI3132AtaPassThru() CmdErr:0x%X (SiI3132 Err:0x= %X)\n", Value32, Error)); - ASSERT (0); - return EFI_DEVICE_ERROR; - } else if (Value32 & (SII3132_PORT_INT_CMDCOMPL << 16)) { - // Clear Command Complete - SATA_PORT_WRITE32 (SataPort->RegBase + SII3132_PORT_INTSTATUS_REG, SII= 3132_PORT_INT_CMDCOMPL << 16); - - if (PciAllocMapping) { - Status =3D PciIo->Unmap (PciIo, PciAllocMapping); - ASSERT (!EFI_ERROR (Status)); - } + Status =3D SiI3132IssueCommand (SataPort, PciIo, Packet->Timeout, Packet= ->Asb); =20 + if (!EFI_ERROR (Status)) + { // If the command was ATA_CMD_IDENTIFY_DRIVE then we need to update th= e BlockSize if (Packet->Acb->AtaCommand =3D=3D ATA_CMD_IDENTIFY_DRIVE) { ATA_IDENTIFY_DATA *IdentifyData =3D (ATA_IDENTIFY_DATA*)Packet->InDa= taBuffer; @@ -279,11 +325,14 @@ SiI3132AtaPassThruCommand ( SataDevice->BlockSize =3D 0x200; } } - return EFI_SUCCESS; - } else { - ASSERT (0); - return EFI_DEVICE_ERROR; } + + if (PciAllocMapping) { + Status =3D PciIo->Unmap (PciIo, PciAllocMapping); + } + + return Status; + } =20 /** @@ -339,8 +388,7 @@ SiI3132AtaPassThru ( } SataPort =3D SataDevice->Port; =20 - DEBUG ((EFI_D_INFO, "SiI3132AtaPassThru(%d,%d) : AtaCmd:0x%X Prot:%d\n",= Port, PortMultiplierPort, + DEBUG ((DEBUG_VERBOSE, "SiI3132AtaPassThru(%p,%d,%d) : AtaCmd:0x%X Prot:= %d\n", SataPort, Port, PortMultiplierPort, Packet->Acb->AtaCommand, Packet->Protocol)); =20 return SiI3132AtaPassThruCommand (SataSiI3132Instance, SataPort, PortMul= tiplierPort, Packet, Event); --=20 2.9.3 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel