From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f66.google.com (mail-wm1-f66.google.com [209.85.128.66]) by mx.groups.io with SMTP id smtpd.web10.3456.1588760302961609316 for ; Wed, 06 May 2020 03:18:23 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@akeo-ie.20150623.gappssmtp.com header.s=20150623 header.b=I08PWqIP; spf=none, err=permanent DNS error (domain: akeo.ie, ip: 209.85.128.66, mailfrom: pete@akeo.ie) Received: by mail-wm1-f66.google.com with SMTP id g12so1975811wmh.3 for ; Wed, 06 May 2020 03:18:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=akeo-ie.20150623.gappssmtp.com; s=20150623; h=subject:to:cc:references:from:message-id:date:user-agent :mime-version:in-reply-to:content-language:content-transfer-encoding; bh=FPY8F2W93WhNW1BpNXEO3M89pW7dtPknRYKKJ+A1tDI=; b=I08PWqIPTvevRp7ERQoFekss3W2fAfP9Cbk9KjvwcDbP22A/Ii+aDrJVhXn6PWL+y4 9EjZjOKHJyhZzXIMSYLu9kyMfFQNxAgg8Cl1j2WebFNdPsrTWy4/ORzglStOGXyzYOut SU6hfIRo4IakWgmU6EcGEahMIbuPSneDTWvQbSZjmxt2A6HW8YyObbGjirM+bpYM9r6K TWda5Hz/nLouZQ4bJFsqCmf3NZdbvKjR/MMpSw1zDUfQL5VpxxO7mr/uNOsKCqOZTYXU 9ttgkQbejyd0HIFd48hZkrGfOfDUt7ll/8Q2iyUXawEeJ0EK+WofRSW0T0EabsXwH4+2 qtPg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:cc:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=FPY8F2W93WhNW1BpNXEO3M89pW7dtPknRYKKJ+A1tDI=; b=R3DpCE5WF2LcV8ydfEtpPMJ+vyGckkdO8lc33ATamStIoUjwJex6zGQxOOLQsL7MqO Q9e9dInUnIO4SCZFNTLdUinpu840dYCEW9TO0qiplI7ebz8EDuQsepnEtCu7OUWOMDSN 5pNZ9DDzzGR8AlNeHNVWUNZJZe2G20GicylPIKSu1N3Z/HfvpQ828rb9CxZM3DIAQpo8 7dH3O5XHmekBqJNOk5ArT1/TTpGOLo6MWVbueXO0HYPDr7JkJO6QVWORxaDKHtgE/sSw C0G3kEA6NrvmiPVi933XiBAXDb9m+R+9oNfRxcVq0ObUmIoT8VQ8fG7UrrJcNIaq51ux PtJA== X-Gm-Message-State: AGi0PuZYroxnEQ0nOh3XcSosLYRpU/rSPrSO852XZXv1xQQdoOm1/E/s c2KAs6T/c5Qb+5Vt+OkzDSQbFw== X-Google-Smtp-Source: APiQypIB6tK8LzR2Gme688pQpvB4YSQKorxOR4KCUmJ4IJXoYEUfpzZTcz2NVy+qpmKysmeLq02K2w== X-Received: by 2002:a1c:23ca:: with SMTP id j193mr290469wmj.37.1588760301190; Wed, 06 May 2020 03:18:21 -0700 (PDT) Return-Path: Received: from [10.0.0.122] ([84.203.75.87]) by smtp.googlemail.com with ESMTPSA id u74sm2421564wmu.13.2020.05.06.03.18.19 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 06 May 2020 03:18:20 -0700 (PDT) Subject: Re: [PATCH edk2-platforms 1/5] Platform/RaspberryPi/DualSerialPortLib: split up to ease reuse To: Ard Biesheuvel , devel@edk2.groups.io Cc: leif@nuviainc.com, andrey.warkentin@gmail.com References: <20200505145029.29826-1-ard.biesheuvel@arm.com> <20200505145029.29826-2-ard.biesheuvel@arm.com> From: "Pete Batard" Message-ID: <4f7dc8f9-b8a2-307c-3d0d-7f7d42865079@akeo.ie> Date: Wed, 6 May 2020 11:18:18 +0100 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Thunderbird/68.7.0 MIME-Version: 1.0 In-Reply-To: <20200505145029.29826-2-ard.biesheuvel@arm.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-GB Content-Transfer-Encoding: 7bit One minor whitespace issue inline: On 2020.05.05 15:50, Ard Biesheuvel wrote: > In preparation of creating different versions of DualSerialPortLib, > split off the parts that will be shared between all versions. > > Signed-off-by: Ard Biesheuvel > --- > Platform/RaspberryPi/Library/DualSerialPortLib/DualSerialPortLib.inf | 5 +- > Platform/RaspberryPi/Library/DualSerialPortLib/DualSerialPortLib.h | 82 +++++++ > Platform/RaspberryPi/Library/DualSerialPortLib/DualSerialPortLib.c | 229 +------------------- > Platform/RaspberryPi/Library/DualSerialPortLib/DualSerialPortLibCommon.c | 218 +++++++++++++++++++ > 4 files changed, 305 insertions(+), 229 deletions(-) > > diff --git a/Platform/RaspberryPi/Library/DualSerialPortLib/DualSerialPortLib.inf b/Platform/RaspberryPi/Library/DualSerialPortLib/DualSerialPortLib.inf > index af1e6b026fe6..fda9ff2bcbf9 100644 > --- a/Platform/RaspberryPi/Library/DualSerialPortLib/DualSerialPortLib.inf > +++ b/Platform/RaspberryPi/Library/DualSerialPortLib/DualSerialPortLib.inf > @@ -19,9 +19,8 @@ [Defines] > > [Packages] > ArmPlatformPkg/ArmPlatformPkg.dec > - EmbeddedPkg/EmbeddedPkg.dec > - MdePkg/MdePkg.dec > MdeModulePkg/MdeModulePkg.dec > + MdePkg/MdePkg.dec > Silicon/Broadcom/Bcm283x/Bcm283x.dec > > [LibraryClasses] > @@ -32,6 +31,8 @@ [LibraryClasses] > > [Sources] > DualSerialPortLib.c > + DualSerialPortLib.h > + DualSerialPortLibCommon.c > > [Pcd] > gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterAccessWidth ## SOMETIMES_CONSUMES > diff --git a/Platform/RaspberryPi/Library/DualSerialPortLib/DualSerialPortLib.h b/Platform/RaspberryPi/Library/DualSerialPortLib/DualSerialPortLib.h > new file mode 100644 > index 000000000000..a8d150f516b9 > --- /dev/null > +++ b/Platform/RaspberryPi/Library/DualSerialPortLib/DualSerialPortLib.h > @@ -0,0 +1,82 @@ > +/** @file > + 16550 and PL011 Serial Port library functions for Raspberry Pi > + > + Copyright (c) 2020, Pete Batard > + Copyright (c) 2018, AMD Incorporated. All rights reserved.
> + Copyright (c) 2014, Hewlett-Packard Development Company, L.P.
> + Copyright (c) 2012 - 2016, ARM Ltd. All rights reserved.
> + Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.
> + Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include > +#include > +#include > + > +#define PL011_UART_REGISTER_BASE BCM2836_PL011_UART_BASE_ADDRESS > +#define MINI_UART_REGISTER_BASE (BCM2836_MINI_UART_BASE_ADDRESS + 0x40) > + > +// > +// 16550 UART register offsets and bitfields > +// > +#define R_UART_RXBUF 0 // LCR_DLAB = 0 > +#define R_UART_TXBUF 0 // LCR_DLAB = 0 > +#define R_UART_BAUD_LOW 0 // LCR_DLAB = 1 > +#define R_UART_BAUD_HIGH 1 // LCR_DLAB = 1 > +#define R_UART_IER 1 // LCR_DLAB = 0 > +#define R_UART_FCR 2 > +#define B_UART_FCR_FIFOE BIT0 > +#define B_UART_FCR_FIFO64 BIT5 > +#define R_UART_LCR 3 > +#define B_UART_LCR_DLAB BIT7 > +#define R_UART_MCR 4 > +#define B_UART_MCR_DTRC BIT0 > +#define B_UART_MCR_RTS BIT1 > +#define R_UART_LSR 5 > +#define B_UART_LSR_RXRDY BIT0 > +#define B_UART_LSR_TXRDY BIT5 > +#define B_UART_LSR_TEMT BIT6 > +#define R_UART_MSR 6 > +#define B_UART_MSR_CTS BIT4 > +#define B_UART_MSR_DSR BIT5 > +#define B_UART_MSR_RI BIT6 > +#define B_UART_MSR_DCD BIT7 > + > +extern BOOLEAN UsePl011Uart; > +extern BOOLEAN UsePl011UartSet; > + > +/** > + Read an 8-bit 16550 register. > + > + @param Base The base address register of UART device. > + @param Offset The offset of the 16550 register to read. > + > + @return The value read from the 16550 register. > + > +**/ > +UINT8 > +SerialPortReadRegister ( > + UINTN Base, > + UINTN Offset > + ); > + > +/** > + Write an 8-bit 16550 register. > + > + @param Base The base address register of UART device. > + @param Offset The offset of the 16550 register to write. > + @param Value The value to write to the 16550 register specified by Offset. > + > + @return The value written to the 16550 register. > + > +**/ > +UINT8 > +SerialPortWriteRegister ( > + UINTN Base, > + UINTN Offset, > + UINT8 Value > + ); > + There's an extra trailing space here that could be removed. > diff --git a/Platform/RaspberryPi/Library/DualSerialPortLib/DualSerialPortLib.c b/Platform/RaspberryPi/Library/DualSerialPortLib/DualSerialPortLib.c > index 05e12f383785..b1d17d3fa04a 100644 > --- a/Platform/RaspberryPi/Library/DualSerialPortLib/DualSerialPortLib.c > +++ b/Platform/RaspberryPi/Library/DualSerialPortLib/DualSerialPortLib.c > @@ -13,132 +13,13 @@ > **/ > > #include > -#include > -#include > -#include > #include > #include > #include > #include > #include > > -BOOLEAN UsePl011Uart = FALSE; > -BOOLEAN UsePl011UartSet = FALSE; > - > -#define PL011_UART_REGISTER_BASE BCM2836_PL011_UART_BASE_ADDRESS > -#define MINI_UART_REGISTER_BASE (BCM2836_MINI_UART_BASE_ADDRESS + 0x40) > - > -// > -// 16550 UART register offsets and bitfields > -// > -#define R_UART_RXBUF 0 // LCR_DLAB = 0 > -#define R_UART_TXBUF 0 // LCR_DLAB = 0 > -#define R_UART_BAUD_LOW 0 // LCR_DLAB = 1 > -#define R_UART_BAUD_HIGH 1 // LCR_DLAB = 1 > -#define R_UART_IER 1 // LCR_DLAB = 0 > -#define R_UART_FCR 2 > -#define B_UART_FCR_FIFOE BIT0 > -#define B_UART_FCR_FIFO64 BIT5 > -#define R_UART_LCR 3 > -#define B_UART_LCR_DLAB BIT7 > -#define R_UART_MCR 4 > -#define B_UART_MCR_DTRC BIT0 > -#define B_UART_MCR_RTS BIT1 > -#define R_UART_LSR 5 > -#define B_UART_LSR_RXRDY BIT0 > -#define B_UART_LSR_TXRDY BIT5 > -#define B_UART_LSR_TEMT BIT6 > -#define R_UART_MSR 6 > -#define B_UART_MSR_CTS BIT4 > -#define B_UART_MSR_DSR BIT5 > -#define B_UART_MSR_RI BIT6 > -#define B_UART_MSR_DCD BIT7 > - > -/** > - Read an 8-bit 16550 register. > - > - @param Base The base address register of UART device. > - @param Offset The offset of the 16550 register to read. > - > - @return The value read from the 16550 register. > - > -**/ > -UINT8 > -SerialPortReadRegister ( > - UINTN Base, > - UINTN Offset > - ) > -{ > - return MmioRead8 (Base + Offset * PcdGet32 (PcdSerialRegisterStride)); > -} > - > -/** > - Write an 8-bit 16550 register. > - > - @param Base The base address register of UART device. > - @param Offset The offset of the 16550 register to write. > - @param Value The value to write to the 16550 register specified by Offset. > - > - @return The value written to the 16550 register. > - > -**/ > -UINT8 > -SerialPortWriteRegister ( > - UINTN Base, > - UINTN Offset, > - UINT8 Value > - ) > -{ > - return MmioWrite8 (Base + Offset * PcdGet32 (PcdSerialRegisterStride), Value); > -} > - > -/** > - Return whether the hardware flow control signal allows writing. > - > - @param SerialRegisterBase The base address register of UART device. > - > - @retval TRUE The serial port is writable. > - @retval FALSE The serial port is not writable. > -**/ > -BOOLEAN > -SerialPortWritable ( > - UINTN SerialRegisterBase > - ) > -{ > - if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { > - if (PcdGetBool (PcdSerialDetectCable)) { > - // > - // Wait for both DSR and CTS to be set > - // DSR is set if a cable is connected. > - // CTS is set if it is ok to transmit data > - // > - // DSR CTS Description Action > - // === === ======================================== ======== > - // 0 0 No cable connected. Wait > - // 0 1 No cable connected. Wait > - // 1 0 Cable connected, but not clear to send. Wait > - // 1 1 Cable connected, and clear to send. Transmit > - // > - return (BOOLEAN) ((SerialPortReadRegister (SerialRegisterBase, R_UART_MSR) & (B_UART_MSR_DSR | B_UART_MSR_CTS)) == (B_UART_MSR_DSR | B_UART_MSR_CTS)); > - } else { > - // > - // Wait for both DSR and CTS to be set OR for DSR to be clear. > - // DSR is set if a cable is connected. > - // CTS is set if it is ok to transmit data > - // > - // DSR CTS Description Action > - // === === ======================================== ======== > - // 0 0 No cable connected. Transmit > - // 0 1 No cable connected. Transmit > - // 1 0 Cable connected, but not clear to send. Wait > - // 1 1 Cable connected, and clar to send. Transmit > - // > - return (BOOLEAN) ((SerialPortReadRegister (SerialRegisterBase, R_UART_MSR) & (B_UART_MSR_DSR | B_UART_MSR_CTS)) != (B_UART_MSR_DSR)); > - } > - } > - > - return TRUE; > -} > +#include "DualSerialPortLib.h" > > /** > Return the baud generator divisor to use for 16650 setup. > @@ -147,6 +28,7 @@ SerialPortWritable ( > > @return The baud generator divisor. > **/ > +STATIC > UINT32 > SerialPortGetDivisor ( > UINT32 SerialBaudRate > @@ -288,113 +170,6 @@ SerialPortInitialize ( > } > } > > -/** > - Write data from buffer to serial device. > - > - Writes NumberOfBytes data bytes from Buffer to the serial device. > - The number of bytes actually written to the serial device is returned. > - If the return value is less than NumberOfBytes, then the write operation failed. > - > - If Buffer is NULL, then ASSERT(). > - > - If NumberOfBytes is zero, then return 0. > - > - @param Buffer Pointer to the data buffer to be written. > - @param NumberOfBytes Number of bytes to written to the serial device. > - > - @retval 0 NumberOfBytes is 0. > - @retval >0 The number of bytes written to the serial device. > - If this value is less than NumberOfBytes, then the write operation failed. > - > -**/ > -UINTN > -EFIAPI > -SerialPortWrite ( > - IN UINT8 *Buffer, > - IN UINTN NumberOfBytes > - ) > -{ > - UINTN SerialRegisterBase; > - UINTN Result; > - UINTN Index; > - UINTN FifoSize; > - > - // > - // Serial writes may happen *before* the UART has been initialized > - // and if we use the wrong UART then, all kind of bad things happen. > - // To alleviate this, we add UART detection in SerialPortWrite and > - // guard the UART detection with a second boolean. > - // > - if (!UsePl011UartSet) { > - UsePl011Uart = ((MmioRead32(GPIO_BASE_ADDRESS + 4) & 0x0003F000) == 0x00024000); > - UsePl011UartSet = TRUE; > - } > - > - if (UsePl011Uart) { > - return PL011UartWrite (PL011_UART_REGISTER_BASE, Buffer, NumberOfBytes); > - } else { > - if (Buffer == NULL) { > - return 0; > - } > - > - SerialRegisterBase = MINI_UART_REGISTER_BASE; > - > - if (NumberOfBytes == 0) { > - // > - // Flush the hardware > - // > - > - // > - // Wait for both the transmit FIFO and shift register empty. > - // > - while ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) != (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)); > - > - // > - // Wait for the hardware flow control signal > - // > - while (!SerialPortWritable (SerialRegisterBase)); > - return 0; > - } > - > - // > - // Compute the maximum size of the Tx FIFO > - // > - FifoSize = 1; > - if ((PcdGet8 (PcdSerialFifoControl) & B_UART_FCR_FIFOE) != 0) { > - if ((PcdGet8 (PcdSerialFifoControl) & B_UART_FCR_FIFO64) == 0) { > - FifoSize = 16; > - } else { > - FifoSize = PcdGet32 (PcdSerialExtendedTxFifoSize); > - } > - } > - > - Result = NumberOfBytes; > - while (NumberOfBytes != 0) { > - // > - // Wait for the serial port to be ready, to make sure both the transmit FIFO > - // and shift register empty. > - // > - while ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) != (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)); > - > - // > - // Fill then entire Tx FIFO > - // > - for (Index = 0; Index < FifoSize && NumberOfBytes != 0; Index++, NumberOfBytes--, Buffer++) { > - // > - // Wait for the hardware flow control signal > - // > - while (!SerialPortWritable (SerialRegisterBase)); > - > - // > - // Write byte to the transmit buffer. > - // > - SerialPortWriteRegister (SerialRegisterBase, R_UART_TXBUF, *Buffer); > - } > - } > - return Result; > - } > -} > - > /** > Reads data from a serial device into a buffer. > > diff --git a/Platform/RaspberryPi/Library/DualSerialPortLib/DualSerialPortLibCommon.c b/Platform/RaspberryPi/Library/DualSerialPortLib/DualSerialPortLibCommon.c > new file mode 100644 > index 000000000000..48d8df280640 > --- /dev/null > +++ b/Platform/RaspberryPi/Library/DualSerialPortLib/DualSerialPortLibCommon.c > @@ -0,0 +1,218 @@ > +/** @file > + 16550 and PL011 Serial Port library functions for Raspberry Pi > + > + Copyright (c) 2020, Pete Batard > + Copyright (c) 2018, AMD Incorporated. All rights reserved.
> + Copyright (c) 2014, Hewlett-Packard Development Company, L.P.
> + Copyright (c) 2012 - 2016, ARM Ltd. All rights reserved.
> + Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.
> + Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include > +#include > +#include > +#include > +#include > + > +#include "DualSerialPortLib.h" > + > +BOOLEAN UsePl011Uart = FALSE; > +BOOLEAN UsePl011UartSet = FALSE; > + > +/** > + Read an 8-bit 16550 register. > + > + @param Base The base address register of UART device. > + @param Offset The offset of the 16550 register to read. > + > + @return The value read from the 16550 register. > + > +**/ > +UINT8 > +SerialPortReadRegister ( > + UINTN Base, > + UINTN Offset > + ) > +{ > + return MmioRead8 (Base + Offset * PcdGet32 (PcdSerialRegisterStride)); > +} > + > +/** > + Write an 8-bit 16550 register. > + > + @param Base The base address register of UART device. > + @param Offset The offset of the 16550 register to write. > + @param Value The value to write to the 16550 register specified by Offset. > + > + @return The value written to the 16550 register. > + > +**/ > +UINT8 > +SerialPortWriteRegister ( > + UINTN Base, > + UINTN Offset, > + UINT8 Value > + ) > +{ > + return MmioWrite8 (Base + Offset * PcdGet32 (PcdSerialRegisterStride), Value); > +} > + > +/** > + Return whether the hardware flow control signal allows writing. > + > + @param SerialRegisterBase The base address register of UART device. > + > + @retval TRUE The serial port is writable. > + @retval FALSE The serial port is not writable. > +**/ > +STATIC > +BOOLEAN > +SerialPortWritable ( > + UINTN SerialRegisterBase > + ) > +{ > + if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { > + if (PcdGetBool (PcdSerialDetectCable)) { > + // > + // Wait for both DSR and CTS to be set > + // DSR is set if a cable is connected. > + // CTS is set if it is ok to transmit data > + // > + // DSR CTS Description Action > + // === === ======================================== ======== > + // 0 0 No cable connected. Wait > + // 0 1 No cable connected. Wait > + // 1 0 Cable connected, but not clear to send. Wait > + // 1 1 Cable connected, and clear to send. Transmit > + // > + return (BOOLEAN) ((SerialPortReadRegister (SerialRegisterBase, R_UART_MSR) & (B_UART_MSR_DSR | B_UART_MSR_CTS)) == (B_UART_MSR_DSR | B_UART_MSR_CTS)); > + } else { > + // > + // Wait for both DSR and CTS to be set OR for DSR to be clear. > + // DSR is set if a cable is connected. > + // CTS is set if it is ok to transmit data > + // > + // DSR CTS Description Action > + // === === ======================================== ======== > + // 0 0 No cable connected. Transmit > + // 0 1 No cable connected. Transmit > + // 1 0 Cable connected, but not clear to send. Wait > + // 1 1 Cable connected, and clar to send. Transmit > + // > + return (BOOLEAN) ((SerialPortReadRegister (SerialRegisterBase, R_UART_MSR) & (B_UART_MSR_DSR | B_UART_MSR_CTS)) != (B_UART_MSR_DSR)); > + } > + } > + > + return TRUE; > +} > + > +/** > + Write data from buffer to serial device. > + > + Writes NumberOfBytes data bytes from Buffer to the serial device. > + The number of bytes actually written to the serial device is returned. > + If the return value is less than NumberOfBytes, then the write operation failed. > + > + If Buffer is NULL, then ASSERT(). > + > + If NumberOfBytes is zero, then return 0. > + > + @param Buffer Pointer to the data buffer to be written. > + @param NumberOfBytes Number of bytes to written to the serial device. > + > + @retval 0 NumberOfBytes is 0. > + @retval >0 The number of bytes written to the serial device. > + If this value is less than NumberOfBytes, then the write operation failed. > + > +**/ > +UINTN > +EFIAPI > +SerialPortWrite ( > + IN UINT8 *Buffer, > + IN UINTN NumberOfBytes > + ) > +{ > + UINTN SerialRegisterBase; > + UINTN Result; > + UINTN Index; > + UINTN FifoSize; > + > + // > + // Serial writes may happen *before* the UART has been initialized > + // and if we use the wrong UART then, all kind of bad things happen. > + // To alleviate this, we add UART detection in SerialPortWrite and > + // guard the UART detection with a second boolean. > + // > + if (!UsePl011UartSet) { > + UsePl011Uart = ((MmioRead32(GPIO_BASE_ADDRESS + 4) & 0x0003F000) == 0x00024000); > + UsePl011UartSet = TRUE; > + } > + > + if (UsePl011Uart) { > + return PL011UartWrite (PL011_UART_REGISTER_BASE, Buffer, NumberOfBytes); > + } else { > + if (Buffer == NULL) { > + return 0; > + } > + > + SerialRegisterBase = MINI_UART_REGISTER_BASE; > + > + if (NumberOfBytes == 0) { > + // > + // Flush the hardware > + // > + > + // > + // Wait for both the transmit FIFO and shift register empty. > + // > + while ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) != (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)); > + > + // > + // Wait for the hardware flow control signal > + // > + while (!SerialPortWritable (SerialRegisterBase)); > + return 0; > + } > + > + // > + // Compute the maximum size of the Tx FIFO > + // > + FifoSize = 1; > + if ((PcdGet8 (PcdSerialFifoControl) & B_UART_FCR_FIFOE) != 0) { > + if ((PcdGet8 (PcdSerialFifoControl) & B_UART_FCR_FIFO64) == 0) { > + FifoSize = 16; > + } else { > + FifoSize = PcdGet32 (PcdSerialExtendedTxFifoSize); > + } > + } > + > + Result = NumberOfBytes; > + while (NumberOfBytes != 0) { > + // > + // Wait for the serial port to be ready, to make sure both the transmit FIFO > + // and shift register empty. > + // > + while ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) != (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)); > + > + // > + // Fill then entire Tx FIFO > + // > + for (Index = 0; Index < FifoSize && NumberOfBytes != 0; Index++, NumberOfBytes--, Buffer++) { > + // > + // Wait for the hardware flow control signal > + // > + while (!SerialPortWritable (SerialRegisterBase)); > + > + // > + // Write byte to the transmit buffer. > + // > + SerialPortWriteRegister (SerialRegisterBase, R_UART_TXBUF, *Buffer); > + } > + } > + return Result; > + } > +} > Reviewed-by: Pete Batard