diff options
Diffstat (limited to 'MdeModulePkg/Bus/Pci/PciSioSerialDxe/SerialIo.c')
-rw-r--r-- | MdeModulePkg/Bus/Pci/PciSioSerialDxe/SerialIo.c | 1320 |
1 files changed, 0 insertions, 1320 deletions
diff --git a/MdeModulePkg/Bus/Pci/PciSioSerialDxe/SerialIo.c b/MdeModulePkg/Bus/Pci/PciSioSerialDxe/SerialIo.c deleted file mode 100644 index f1870f3a1b..0000000000 --- a/MdeModulePkg/Bus/Pci/PciSioSerialDxe/SerialIo.c +++ /dev/null @@ -1,1320 +0,0 @@ -/** @file
- SerialIo implementation for PCI or SIO UARTs.
-
-Copyright (c) 2006 - 2015, 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
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "Serial.h"
-
-/**
- Skip the optional Controller device path node and return the
- pointer to the next device path node.
-
- @param DevicePath Pointer to the device path.
- @param ContainsControllerNode Returns TRUE if the Controller device path exists.
- @param ControllerNumber Returns the Controller Number if Controller device path exists.
-
- @return Pointer to the next device path node.
-**/
-UART_DEVICE_PATH *
-SkipControllerDevicePathNode (
- EFI_DEVICE_PATH_PROTOCOL *DevicePath,
- BOOLEAN *ContainsControllerNode,
- UINT32 *ControllerNumber
- )
-{
- if ((DevicePathType (DevicePath) == HARDWARE_DEVICE_PATH) &&
- (DevicePathSubType (DevicePath) == HW_CONTROLLER_DP)
- ) {
- if (ContainsControllerNode != NULL) {
- *ContainsControllerNode = TRUE;
- }
- if (ControllerNumber != NULL) {
- *ControllerNumber = ((CONTROLLER_DEVICE_PATH *) DevicePath)->ControllerNumber;
- }
- DevicePath = NextDevicePathNode (DevicePath);
- } else {
- if (ContainsControllerNode != NULL) {
- *ContainsControllerNode = FALSE;
- }
- }
- return (UART_DEVICE_PATH *) DevicePath;
-}
-
-/**
- Checks whether the UART parameters are valid and computes the Divisor.
-
- @param ClockRate The clock rate of the serial device used to verify
- the BaudRate. Do not verify the BaudRate if it's 0.
- @param BaudRate The requested baudrate of the serial device.
- @param DataBits Number of databits used in serial device.
- @param Parity The type of parity used in serial device.
- @param StopBits Number of stopbits used in serial device.
- @param Divisor Return the divisor if ClockRate is not 0.
- @param ActualBaudRate Return the actual supported baudrate without
- exceeding BaudRate. NULL means baudrate degradation
- is not allowed.
- If the requested BaudRate is not supported, the routine
- returns TRUE and the Actual Baud Rate when ActualBaudRate
- is not NULL, returns FALSE when ActualBaudRate is NULL.
-
- @retval TRUE The UART parameters are valid.
- @retval FALSE The UART parameters are not valid.
-**/
-BOOLEAN
-VerifyUartParameters (
- IN UINT32 ClockRate,
- IN UINT64 BaudRate,
- IN UINT8 DataBits,
- IN EFI_PARITY_TYPE Parity,
- IN EFI_STOP_BITS_TYPE StopBits,
- OUT UINT64 *Divisor,
- OUT UINT64 *ActualBaudRate
- )
-{
- UINT64 Remainder;
- UINT32 ComputedBaudRate;
- UINT64 ComputedDivisor;
- UINT64 Percent;
-
- if ((DataBits < 5) || (DataBits > 8) ||
- (Parity < NoParity) || (Parity > SpaceParity) ||
- (StopBits < OneStopBit) || (StopBits > TwoStopBits) ||
- ((DataBits == 5) && (StopBits == TwoStopBits)) ||
- ((DataBits >= 6) && (DataBits <= 8) && (StopBits == OneFiveStopBits))
- ) {
- return FALSE;
- }
-
- //
- // Do not verify the baud rate if clock rate is unknown (0).
- //
- if (ClockRate == 0) {
- return TRUE;
- }
-
- //
- // Compute divisor use to program the baud rate using a round determination
- // Divisor = ClockRate / 16 / BaudRate = ClockRate / (16 * BaudRate)
- // = ClockRate / (BaudRate << 4)
- //
- ComputedDivisor = DivU64x64Remainder (ClockRate, LShiftU64 (BaudRate, 4), &Remainder);
- //
- // Round Divisor up by 1 if the Remainder is more than half (16 * BaudRate)
- // BaudRate * 16 / 2 = BaudRate * 8 = (BaudRate << 3)
- //
- if (Remainder >= LShiftU64 (BaudRate, 3)) {
- ComputedDivisor++;
- }
- //
- // If the computed divisor is larger than the maximum value that can be programmed
- // into the UART, then the requested baud rate can not be supported.
- //
- if (ComputedDivisor > MAX_UINT16) {
- return FALSE;
- }
-
- //
- // If the computed divisor is 0, then use a computed divisor of 1, which will select
- // the maximum supported baud rate.
- //
- if (ComputedDivisor == 0) {
- ComputedDivisor = 1;
- }
-
- //
- // Actual baud rate that the serial port will be programmed for
- // should be with in 4% of requested one.
- //
- ComputedBaudRate = ClockRate / ((UINT16) ComputedDivisor << 4);
- if (ComputedBaudRate == 0) {
- return FALSE;
- }
-
- Percent = DivU64x32 (MultU64x32 (BaudRate, 100), ComputedBaudRate);
- DEBUG ((EFI_D_INFO, "ClockRate = %d\n", ClockRate));
- DEBUG ((EFI_D_INFO, "Divisor = %ld\n", ComputedDivisor));
- DEBUG ((EFI_D_INFO, "BaudRate/Actual (%ld/%d) = %d%%\n", BaudRate, ComputedBaudRate, Percent));
-
- //
- // If the requested BaudRate is not supported:
- // Returns TRUE and the Actual Baud Rate when ActualBaudRate is not NULL;
- // Returns FALSE when ActualBaudRate is NULL.
- //
- if ((Percent >= 96) && (Percent <= 104)) {
- if (ActualBaudRate != NULL) {
- *ActualBaudRate = BaudRate;
- }
- if (Divisor != NULL) {
- *Divisor = ComputedDivisor;
- }
- return TRUE;
- }
- if (ComputedBaudRate < BaudRate) {
- if (ActualBaudRate != NULL) {
- *ActualBaudRate = ComputedBaudRate;
- }
- if (Divisor != NULL) {
- *Divisor = ComputedDivisor;
- }
- return TRUE;
- }
-
- //
- // ActualBaudRate is higher than requested baud rate and more than 4%
- // higher than the requested value. Increment Divisor if it is less
- // than MAX_UINT16 and computed baud rate with new divisor.
- //
- if (ComputedDivisor == MAX_UINT16) {
- return FALSE;
- }
- ComputedDivisor++;
- ComputedBaudRate = ClockRate / ((UINT16) ComputedDivisor << 4);
- if (ComputedBaudRate == 0) {
- return FALSE;
- }
-
- DEBUG ((EFI_D_INFO, "ClockRate = %d\n", ClockRate));
- DEBUG ((EFI_D_INFO, "Divisor = %ld\n", ComputedDivisor));
- DEBUG ((EFI_D_INFO, "BaudRate/Actual (%ld/%d) = %d%%\n", BaudRate, ComputedBaudRate, Percent));
-
- if (ActualBaudRate != NULL) {
- *ActualBaudRate = ComputedBaudRate;
- }
- if (Divisor != NULL) {
- *Divisor = ComputedDivisor;
- }
- return TRUE;
-}
-
-/**
- Detect whether specific FIFO is full or not.
-
- @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
-
- @return whether specific FIFO is full or not
-**/
-BOOLEAN
-SerialFifoFull (
- IN SERIAL_DEV_FIFO *Fifo
- )
-{
- return (BOOLEAN) (((Fifo->Tail + 1) % SERIAL_MAX_FIFO_SIZE) == Fifo->Head);
-}
-
-/**
- Detect whether specific FIFO is empty or not.
-
- @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
-
- @return whether specific FIFO is empty or not
-**/
-BOOLEAN
-SerialFifoEmpty (
- IN SERIAL_DEV_FIFO *Fifo
- )
-
-{
- return (BOOLEAN) (Fifo->Head == Fifo->Tail);
-}
-
-/**
- Add data to specific FIFO.
-
- @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
- @param Data the data added to FIFO
-
- @retval EFI_SUCCESS Add data to specific FIFO successfully
- @retval EFI_OUT_OF_RESOURCE Failed to add data because FIFO is already full
-**/
-EFI_STATUS
-SerialFifoAdd (
- IN OUT SERIAL_DEV_FIFO *Fifo,
- IN UINT8 Data
- )
-{
- //
- // if FIFO full can not add data
- //
- if (SerialFifoFull (Fifo)) {
- return EFI_OUT_OF_RESOURCES;
- }
- //
- // FIFO is not full can add data
- //
- Fifo->Data[Fifo->Tail] = Data;
- Fifo->Tail = (Fifo->Tail + 1) % SERIAL_MAX_FIFO_SIZE;
- return EFI_SUCCESS;
-}
-
-/**
- Remove data from specific FIFO.
-
- @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
- @param Data the data removed from FIFO
-
- @retval EFI_SUCCESS Remove data from specific FIFO successfully
- @retval EFI_OUT_OF_RESOURCE Failed to remove data because FIFO is empty
-
-**/
-EFI_STATUS
-SerialFifoRemove (
- IN OUT SERIAL_DEV_FIFO *Fifo,
- OUT UINT8 *Data
- )
-{
- //
- // if FIFO is empty, no data can remove
- //
- if (SerialFifoEmpty (Fifo)) {
- return EFI_OUT_OF_RESOURCES;
- }
- //
- // FIFO is not empty, can remove data
- //
- *Data = Fifo->Data[Fifo->Head];
- Fifo->Head = (Fifo->Head + 1) % SERIAL_MAX_FIFO_SIZE;
- return EFI_SUCCESS;
-}
-
-/**
- Reads and writes all avaliable data.
-
- @param SerialDevice The device to transmit.
-
- @retval EFI_SUCCESS Data was read/written successfully.
- @retval EFI_OUT_OF_RESOURCE Failed because software receive FIFO is full. Note, when
- this happens, pending writes are not done.
-
-**/
-EFI_STATUS
-SerialReceiveTransmit (
- IN SERIAL_DEV *SerialDevice
- )
-
-{
- SERIAL_PORT_LSR Lsr;
- UINT8 Data;
- BOOLEAN ReceiveFifoFull;
- SERIAL_PORT_MSR Msr;
- SERIAL_PORT_MCR Mcr;
- UINTN TimeOut;
-
- Data = 0;
-
- //
- // Begin the read or write
- //
- if (SerialDevice->SoftwareLoopbackEnable) {
- do {
- ReceiveFifoFull = SerialFifoFull (&SerialDevice->Receive);
- if (!SerialFifoEmpty (&SerialDevice->Transmit)) {
- SerialFifoRemove (&SerialDevice->Transmit, &Data);
- if (ReceiveFifoFull) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- SerialFifoAdd (&SerialDevice->Receive, Data);
- }
- } while (!SerialFifoEmpty (&SerialDevice->Transmit));
- } else {
- ReceiveFifoFull = SerialFifoFull (&SerialDevice->Receive);
- //
- // For full handshake flow control, tell the peer to send data
- // if receive buffer is available.
- //
- if (SerialDevice->HardwareFlowControl &&
- !FeaturePcdGet(PcdSerialUseHalfHandshake)&&
- !ReceiveFifoFull
- ) {
- Mcr.Data = READ_MCR (SerialDevice);
- Mcr.Bits.Rts = 1;
- WRITE_MCR (SerialDevice, Mcr.Data);
- }
- do {
- Lsr.Data = READ_LSR (SerialDevice);
-
- //
- // Flush incomming data to prevent a an overrun during a long write
- //
- if ((Lsr.Bits.Dr == 1) && !ReceiveFifoFull) {
- ReceiveFifoFull = SerialFifoFull (&SerialDevice->Receive);
- if (!ReceiveFifoFull) {
- if (Lsr.Bits.FIFOe == 1 || Lsr.Bits.Oe == 1 || Lsr.Bits.Pe == 1 || Lsr.Bits.Fe == 1 || Lsr.Bits.Bi == 1) {
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (
- EFI_ERROR_CODE,
- EFI_P_EC_INPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT,
- SerialDevice->DevicePath
- );
- if (Lsr.Bits.FIFOe == 1 || Lsr.Bits.Pe == 1|| Lsr.Bits.Fe == 1 || Lsr.Bits.Bi == 1) {
- Data = READ_RBR (SerialDevice);
- continue;
- }
- }
-
- Data = READ_RBR (SerialDevice);
-
- SerialFifoAdd (&SerialDevice->Receive, Data);
-
- //
- // For full handshake flow control, if receive buffer full
- // tell the peer to stop sending data.
- //
- if (SerialDevice->HardwareFlowControl &&
- !FeaturePcdGet(PcdSerialUseHalfHandshake) &&
- SerialFifoFull (&SerialDevice->Receive)
- ) {
- Mcr.Data = READ_MCR (SerialDevice);
- Mcr.Bits.Rts = 0;
- WRITE_MCR (SerialDevice, Mcr.Data);
- }
-
-
- continue;
- } else {
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (
- EFI_PROGRESS_CODE,
- EFI_P_SERIAL_PORT_PC_CLEAR_BUFFER | EFI_PERIPHERAL_SERIAL_PORT,
- SerialDevice->DevicePath
- );
- }
- }
- //
- // Do the write
- //
- if (Lsr.Bits.Thre == 1 && !SerialFifoEmpty (&SerialDevice->Transmit)) {
- //
- // Make sure the transmit data will not be missed
- //
- if (SerialDevice->HardwareFlowControl) {
- //
- // For half handshake flow control assert RTS before sending.
- //
- if (FeaturePcdGet(PcdSerialUseHalfHandshake)) {
- Mcr.Data = READ_MCR (SerialDevice);
- Mcr.Bits.Rts= 0;
- WRITE_MCR (SerialDevice, Mcr.Data);
- }
- //
- // Wait for CTS
- //
- TimeOut = 0;
- Msr.Data = READ_MSR (SerialDevice);
- while ((Msr.Bits.Dcd == 1) && ((Msr.Bits.Cts == 0) ^ FeaturePcdGet(PcdSerialUseHalfHandshake))) {
- gBS->Stall (TIMEOUT_STALL_INTERVAL);
- TimeOut++;
- if (TimeOut > 5) {
- break;
- }
-
- Msr.Data = READ_MSR (SerialDevice);
- }
-
- if ((Msr.Bits.Dcd == 0) || ((Msr.Bits.Cts == 1) ^ FeaturePcdGet(PcdSerialUseHalfHandshake))) {
- SerialFifoRemove (&SerialDevice->Transmit, &Data);
- WRITE_THR (SerialDevice, Data);
- }
-
- //
- // For half handshake flow control, tell DCE we are done.
- //
- if (FeaturePcdGet(PcdSerialUseHalfHandshake)) {
- Mcr.Data = READ_MCR (SerialDevice);
- Mcr.Bits.Rts = 1;
- WRITE_MCR (SerialDevice, Mcr.Data);
- }
- } else {
- SerialFifoRemove (&SerialDevice->Transmit, &Data);
- WRITE_THR (SerialDevice, Data);
- }
- }
- } while (Lsr.Bits.Thre == 1 && !SerialFifoEmpty (&SerialDevice->Transmit));
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Flush the serial hardware transmit FIFO and shift register.
-
- @param SerialDevice The device to flush.
-**/
-VOID
-SerialFlushTransmitFifo (
- SERIAL_DEV *SerialDevice
- )
-{
- SERIAL_PORT_LSR Lsr;
-
- //
- // Wait for the serial port to be ready, to make sure both the transmit FIFO
- // and shift register empty.
- //
- do {
- Lsr.Data = READ_LSR (SerialDevice);
- } while (Lsr.Bits.Temt == 0);
-}
-
-//
-// Interface Functions
-//
-/**
- Reset serial device.
-
- @param This Pointer to EFI_SERIAL_IO_PROTOCOL
-
- @retval EFI_SUCCESS Reset successfully
- @retval EFI_DEVICE_ERROR Failed to reset
-
-**/
-EFI_STATUS
-EFIAPI
-SerialReset (
- IN EFI_SERIAL_IO_PROTOCOL *This
- )
-{
- EFI_STATUS Status;
- SERIAL_DEV *SerialDevice;
- SERIAL_PORT_LCR Lcr;
- SERIAL_PORT_IER Ier;
- SERIAL_PORT_MCR Mcr;
- SERIAL_PORT_FCR Fcr;
- EFI_TPL Tpl;
- UINT32 Control;
-
- SerialDevice = SERIAL_DEV_FROM_THIS (This);
-
- //
- // Report the status code reset the serial
- //
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (
- EFI_PROGRESS_CODE,
- EFI_P_PC_RESET | EFI_PERIPHERAL_SERIAL_PORT,
- SerialDevice->DevicePath
- );
-
- Tpl = gBS->RaiseTPL (TPL_NOTIFY);
-
- SerialFlushTransmitFifo (SerialDevice);
-
- //
- // Make sure DLAB is 0.
- //
- Lcr.Data = READ_LCR (SerialDevice);
- Lcr.Bits.DLab = 0;
- WRITE_LCR (SerialDevice, Lcr.Data);
-
- //
- // Turn off all interrupts
- //
- Ier.Data = READ_IER (SerialDevice);
- Ier.Bits.Ravie = 0;
- Ier.Bits.Theie = 0;
- Ier.Bits.Rie = 0;
- Ier.Bits.Mie = 0;
- WRITE_IER (SerialDevice, Ier.Data);
-
- //
- // Reset the FIFO
- //
- Fcr.Data = 0;
- Fcr.Bits.TrFIFOE = 0;
- WRITE_FCR (SerialDevice, Fcr.Data);
-
- //
- // Turn off loopback and disable device interrupt.
- //
- Mcr.Data = READ_MCR (SerialDevice);
- Mcr.Bits.Out1 = 0;
- Mcr.Bits.Out2 = 0;
- Mcr.Bits.Lme = 0;
- WRITE_MCR (SerialDevice, Mcr.Data);
-
- //
- // Clear the scratch pad register
- //
- WRITE_SCR (SerialDevice, 0);
-
- //
- // Enable FIFO
- //
- Fcr.Bits.TrFIFOE = 1;
- if (SerialDevice->ReceiveFifoDepth > 16) {
- Fcr.Bits.TrFIFO64 = 1;
- }
- Fcr.Bits.ResetRF = 1;
- Fcr.Bits.ResetTF = 1;
- WRITE_FCR (SerialDevice, Fcr.Data);
-
- //
- // Go set the current attributes
- //
- Status = This->SetAttributes (
- This,
- This->Mode->BaudRate,
- This->Mode->ReceiveFifoDepth,
- This->Mode->Timeout,
- (EFI_PARITY_TYPE) This->Mode->Parity,
- (UINT8) This->Mode->DataBits,
- (EFI_STOP_BITS_TYPE) This->Mode->StopBits
- );
-
- if (EFI_ERROR (Status)) {
- gBS->RestoreTPL (Tpl);
- return EFI_DEVICE_ERROR;
- }
- //
- // Go set the current control bits
- //
- Control = 0;
- if (SerialDevice->HardwareFlowControl) {
- Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
- }
- if (SerialDevice->SoftwareLoopbackEnable) {
- Control |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE;
- }
- Status = This->SetControl (
- This,
- Control
- );
-
- if (EFI_ERROR (Status)) {
- gBS->RestoreTPL (Tpl);
- return EFI_DEVICE_ERROR;
- }
-
- //
- // Reset the software FIFO
- //
- SerialDevice->Receive.Head = SerialDevice->Receive.Tail = 0;
- SerialDevice->Transmit.Head = SerialDevice->Transmit.Tail = 0;
- gBS->RestoreTPL (Tpl);
-
- //
- // Device reset is complete
- //
- return EFI_SUCCESS;
-}
-
-/**
- Set new attributes to a serial device.
-
- @param This Pointer to EFI_SERIAL_IO_PROTOCOL
- @param BaudRate The baudrate of the serial device
- @param ReceiveFifoDepth The depth of receive FIFO buffer
- @param Timeout The request timeout for a single char
- @param Parity The type of parity used in serial device
- @param DataBits Number of databits used in serial device
- @param StopBits Number of stopbits used in serial device
-
- @retval EFI_SUCCESS The new attributes were set
- @retval EFI_INVALID_PARAMETERS One or more attributes have an unsupported value
- @retval EFI_UNSUPPORTED Data Bits can not set to 5 or 6
- @retval EFI_DEVICE_ERROR The serial device is not functioning correctly (no return)
-
-**/
-EFI_STATUS
-EFIAPI
-SerialSetAttributes (
- IN EFI_SERIAL_IO_PROTOCOL *This,
- IN UINT64 BaudRate,
- IN UINT32 ReceiveFifoDepth,
- IN UINT32 Timeout,
- IN EFI_PARITY_TYPE Parity,
- IN UINT8 DataBits,
- IN EFI_STOP_BITS_TYPE StopBits
- )
-{
- EFI_STATUS Status;
- SERIAL_DEV *SerialDevice;
- UINT64 Divisor;
- SERIAL_PORT_LCR Lcr;
- UART_DEVICE_PATH *Uart;
- EFI_TPL Tpl;
-
- SerialDevice = SERIAL_DEV_FROM_THIS (This);
-
- //
- // Check for default settings and fill in actual values.
- //
- if (BaudRate == 0) {
- BaudRate = PcdGet64 (PcdUartDefaultBaudRate);
- }
-
- if (ReceiveFifoDepth == 0) {
- ReceiveFifoDepth = SerialDevice->ReceiveFifoDepth;
- }
-
- if (Timeout == 0) {
- Timeout = SERIAL_PORT_DEFAULT_TIMEOUT;
- }
-
- if (Parity == DefaultParity) {
- Parity = (EFI_PARITY_TYPE) PcdGet8 (PcdUartDefaultParity);
- }
-
- if (DataBits == 0) {
- DataBits = PcdGet8 (PcdUartDefaultDataBits);
- }
-
- if (StopBits == DefaultStopBits) {
- StopBits = (EFI_STOP_BITS_TYPE) PcdGet8 (PcdUartDefaultStopBits);
- }
-
- if (!VerifyUartParameters (SerialDevice->ClockRate, BaudRate, DataBits, Parity, StopBits, &Divisor, &BaudRate)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((ReceiveFifoDepth == 0) || (ReceiveFifoDepth > SerialDevice->ReceiveFifoDepth)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((Timeout < SERIAL_PORT_MIN_TIMEOUT) || (Timeout > SERIAL_PORT_MAX_TIMEOUT)) {
- return EFI_INVALID_PARAMETER;
- }
-
- Tpl = gBS->RaiseTPL (TPL_NOTIFY);
-
- SerialFlushTransmitFifo (SerialDevice);
-
- //
- // Put serial port on Divisor Latch Mode
- //
- Lcr.Data = READ_LCR (SerialDevice);
- Lcr.Bits.DLab = 1;
- WRITE_LCR (SerialDevice, Lcr.Data);
-
- //
- // Write the divisor to the serial port
- //
- WRITE_DLL (SerialDevice, (UINT8) Divisor);
- WRITE_DLM (SerialDevice, (UINT8) ((UINT16) Divisor >> 8));
-
- //
- // Put serial port back in normal mode and set remaining attributes.
- //
- Lcr.Bits.DLab = 0;
-
- switch (Parity) {
- case NoParity:
- Lcr.Bits.ParEn = 0;
- Lcr.Bits.EvenPar = 0;
- Lcr.Bits.SticPar = 0;
- break;
-
- case EvenParity:
- Lcr.Bits.ParEn = 1;
- Lcr.Bits.EvenPar = 1;
- Lcr.Bits.SticPar = 0;
- break;
-
- case OddParity:
- Lcr.Bits.ParEn = 1;
- Lcr.Bits.EvenPar = 0;
- Lcr.Bits.SticPar = 0;
- break;
-
- case SpaceParity:
- Lcr.Bits.ParEn = 1;
- Lcr.Bits.EvenPar = 1;
- Lcr.Bits.SticPar = 1;
- break;
-
- case MarkParity:
- Lcr.Bits.ParEn = 1;
- Lcr.Bits.EvenPar = 0;
- Lcr.Bits.SticPar = 1;
- break;
-
- default:
- break;
- }
-
- switch (StopBits) {
- case OneStopBit:
- Lcr.Bits.StopB = 0;
- break;
-
- case OneFiveStopBits:
- case TwoStopBits:
- Lcr.Bits.StopB = 1;
- break;
-
- default:
- break;
- }
- //
- // DataBits
- //
- Lcr.Bits.SerialDB = (UINT8) ((DataBits - 5) & 0x03);
- WRITE_LCR (SerialDevice, Lcr.Data);
-
- //
- // Set the Serial I/O mode
- //
- This->Mode->BaudRate = BaudRate;
- This->Mode->ReceiveFifoDepth = ReceiveFifoDepth;
- This->Mode->Timeout = Timeout;
- This->Mode->Parity = Parity;
- This->Mode->DataBits = DataBits;
- This->Mode->StopBits = StopBits;
-
- //
- // See if Device Path Node has actually changed
- //
- if (SerialDevice->UartDevicePath.BaudRate == BaudRate &&
- SerialDevice->UartDevicePath.DataBits == DataBits &&
- SerialDevice->UartDevicePath.Parity == Parity &&
- SerialDevice->UartDevicePath.StopBits == StopBits
- ) {
- gBS->RestoreTPL (Tpl);
- return EFI_SUCCESS;
- }
- //
- // Update the device path
- //
- SerialDevice->UartDevicePath.BaudRate = BaudRate;
- SerialDevice->UartDevicePath.DataBits = DataBits;
- SerialDevice->UartDevicePath.Parity = (UINT8) Parity;
- SerialDevice->UartDevicePath.StopBits = (UINT8) StopBits;
-
- Status = EFI_SUCCESS;
- if (SerialDevice->Handle != NULL) {
-
- //
- // Skip the optional Controller device path node
- //
- Uart = SkipControllerDevicePathNode (
- (EFI_DEVICE_PATH_PROTOCOL *) (
- (UINT8 *) SerialDevice->DevicePath + GetDevicePathSize (SerialDevice->ParentDevicePath) - END_DEVICE_PATH_LENGTH
- ),
- NULL,
- NULL
- );
- CopyMem (Uart, &SerialDevice->UartDevicePath, sizeof (UART_DEVICE_PATH));
- Status = gBS->ReinstallProtocolInterface (
- SerialDevice->Handle,
- &gEfiDevicePathProtocolGuid,
- SerialDevice->DevicePath,
- SerialDevice->DevicePath
- );
- }
-
- gBS->RestoreTPL (Tpl);
-
- return Status;
-}
-
-/**
- Set Control Bits.
-
- @param This Pointer to EFI_SERIAL_IO_PROTOCOL
- @param Control Control bits that can be settable
-
- @retval EFI_SUCCESS New Control bits were set successfully
- @retval EFI_UNSUPPORTED The Control bits wanted to set are not supported
-
-**/
-EFI_STATUS
-EFIAPI
-SerialSetControl (
- IN EFI_SERIAL_IO_PROTOCOL *This,
- IN UINT32 Control
- )
-{
- SERIAL_DEV *SerialDevice;
- SERIAL_PORT_MCR Mcr;
- EFI_TPL Tpl;
- UART_FLOW_CONTROL_DEVICE_PATH *FlowControl;
- EFI_STATUS Status;
-
- //
- // The control bits that can be set are :
- // EFI_SERIAL_DATA_TERMINAL_READY: 0x0001 // WO
- // EFI_SERIAL_REQUEST_TO_SEND: 0x0002 // WO
- // EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE: 0x1000 // RW
- // EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE: 0x2000 // RW
- // EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE: 0x4000 // RW
- //
- SerialDevice = SERIAL_DEV_FROM_THIS (This);
-
- //
- // first determine the parameter is invalid
- //
- if ((Control & (~(EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY |
- EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE |
- EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) != 0) {
- return EFI_UNSUPPORTED;
- }
-
- Tpl = gBS->RaiseTPL (TPL_NOTIFY);
-
- Mcr.Data = READ_MCR (SerialDevice);
- Mcr.Bits.DtrC = 0;
- Mcr.Bits.Rts = 0;
- Mcr.Bits.Lme = 0;
- SerialDevice->SoftwareLoopbackEnable = FALSE;
- SerialDevice->HardwareFlowControl = FALSE;
-
- if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) == EFI_SERIAL_DATA_TERMINAL_READY) {
- Mcr.Bits.DtrC = 1;
- }
-
- if ((Control & EFI_SERIAL_REQUEST_TO_SEND) == EFI_SERIAL_REQUEST_TO_SEND) {
- Mcr.Bits.Rts = 1;
- }
-
- if ((Control & EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) == EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) {
- Mcr.Bits.Lme = 1;
- }
-
- if ((Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) == EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) {
- SerialDevice->HardwareFlowControl = TRUE;
- }
-
- WRITE_MCR (SerialDevice, Mcr.Data);
-
- if ((Control & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) == EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) {
- SerialDevice->SoftwareLoopbackEnable = TRUE;
- }
-
- Status = EFI_SUCCESS;
- if (SerialDevice->Handle != NULL) {
- FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) (
- (UINTN) SerialDevice->DevicePath
- + GetDevicePathSize (SerialDevice->ParentDevicePath)
- - END_DEVICE_PATH_LENGTH
- + sizeof (UART_DEVICE_PATH)
- );
- if (IsUartFlowControlDevicePathNode (FlowControl) &&
- ((BOOLEAN) (ReadUnaligned32 (&FlowControl->FlowControlMap) == UART_FLOW_CONTROL_HARDWARE) != SerialDevice->HardwareFlowControl)) {
- //
- // Flow Control setting is changed, need to reinstall device path protocol
- //
- WriteUnaligned32 (&FlowControl->FlowControlMap, SerialDevice->HardwareFlowControl ? UART_FLOW_CONTROL_HARDWARE : 0);
- Status = gBS->ReinstallProtocolInterface (
- SerialDevice->Handle,
- &gEfiDevicePathProtocolGuid,
- SerialDevice->DevicePath,
- SerialDevice->DevicePath
- );
- }
- }
-
- gBS->RestoreTPL (Tpl);
-
- return Status;
-}
-
-/**
- Get ControlBits.
-
- @param This Pointer to EFI_SERIAL_IO_PROTOCOL
- @param Control Control signals of the serial device
-
- @retval EFI_SUCCESS Get Control signals successfully
-
-**/
-EFI_STATUS
-EFIAPI
-SerialGetControl (
- IN EFI_SERIAL_IO_PROTOCOL *This,
- OUT UINT32 *Control
- )
-{
- SERIAL_DEV *SerialDevice;
- SERIAL_PORT_MSR Msr;
- SERIAL_PORT_MCR Mcr;
- EFI_TPL Tpl;
-
- Tpl = gBS->RaiseTPL (TPL_NOTIFY);
-
- SerialDevice = SERIAL_DEV_FROM_THIS (This);
-
- *Control = 0;
-
- //
- // Read the Modem Status Register
- //
- Msr.Data = READ_MSR (SerialDevice);
-
- if (Msr.Bits.Cts == 1) {
- *Control |= EFI_SERIAL_CLEAR_TO_SEND;
- }
-
- if (Msr.Bits.Dsr == 1) {
- *Control |= EFI_SERIAL_DATA_SET_READY;
- }
-
- if (Msr.Bits.Ri == 1) {
- *Control |= EFI_SERIAL_RING_INDICATE;
- }
-
- if (Msr.Bits.Dcd == 1) {
- *Control |= EFI_SERIAL_CARRIER_DETECT;
- }
- //
- // Read the Modem Control Register
- //
- Mcr.Data = READ_MCR (SerialDevice);
-
- if (Mcr.Bits.DtrC == 1) {
- *Control |= EFI_SERIAL_DATA_TERMINAL_READY;
- }
-
- if (Mcr.Bits.Rts == 1) {
- *Control |= EFI_SERIAL_REQUEST_TO_SEND;
- }
-
- if (Mcr.Bits.Lme == 1) {
- *Control |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE;
- }
-
- if (SerialDevice->HardwareFlowControl) {
- *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
- }
- //
- // Update FIFO status
- //
- SerialReceiveTransmit (SerialDevice);
-
- //
- // See if the Transmit FIFO is empty
- //
- if (SerialFifoEmpty (&SerialDevice->Transmit)) {
- *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
- }
-
- //
- // See if the Receive FIFO is empty.
- //
- if (SerialFifoEmpty (&SerialDevice->Receive)) {
- *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
- }
-
- if (SerialDevice->SoftwareLoopbackEnable) {
- *Control |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE;
- }
-
- gBS->RestoreTPL (Tpl);
-
- return EFI_SUCCESS;
-}
-
-/**
- Write the specified number of bytes to serial device.
-
- @param This Pointer to EFI_SERIAL_IO_PROTOCOL
- @param BufferSize On input the size of Buffer, on output the amount of
- data actually written
- @param Buffer The buffer of data to write
-
- @retval EFI_SUCCESS The data were written successfully
- @retval EFI_DEVICE_ERROR The device reported an error
- @retval EFI_TIMEOUT The write operation was stopped due to timeout
-
-**/
-EFI_STATUS
-EFIAPI
-SerialWrite (
- IN EFI_SERIAL_IO_PROTOCOL *This,
- IN OUT UINTN *BufferSize,
- IN VOID *Buffer
- )
-{
- SERIAL_DEV *SerialDevice;
- UINT8 *CharBuffer;
- UINT32 Index;
- UINTN Elapsed;
- UINTN ActualWrite;
- EFI_TPL Tpl;
- UINTN Timeout;
- UINTN BitsPerCharacter;
-
- SerialDevice = SERIAL_DEV_FROM_THIS (This);
- Elapsed = 0;
- ActualWrite = 0;
-
- if (*BufferSize == 0) {
- return EFI_SUCCESS;
- }
-
- if (Buffer == NULL) {
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (
- EFI_ERROR_CODE,
- EFI_P_EC_OUTPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT,
- SerialDevice->DevicePath
- );
-
- return EFI_DEVICE_ERROR;
- }
-
- Tpl = gBS->RaiseTPL (TPL_NOTIFY);
-
- CharBuffer = (UINT8 *) Buffer;
-
- //
- // Compute the number of bits in a single character. This is a start bit,
- // followed by the number of data bits, followed by the number of stop bits.
- // The number of stop bits is specified by an enumeration that includes
- // support for 1.5 stop bits. Treat 1.5 stop bits as 2 stop bits.
- //
- BitsPerCharacter =
- 1 +
- This->Mode->DataBits +
- ((This->Mode->StopBits == TwoStopBits) ? 2 : This->Mode->StopBits);
-
- //
- // Compute the timeout in microseconds to wait for a single byte to be
- // transmitted. The Mode structure contans a Timeout field that is the
- // maximum time to transmit or receive a character. However, many UARTs
- // have a FIFO for transmits, so the time required to add one new character
- // to the transmit FIFO may be the time required to flush a full FIFO. If
- // the Timeout in the Mode structure is smaller than the time required to
- // flush a full FIFO at the current baud rate, then use a timeout value that
- // is required to flush a full transmit FIFO.
- //
- Timeout = MAX (
- This->Mode->Timeout,
- (UINTN)DivU64x64Remainder (
- BitsPerCharacter * (SerialDevice->TransmitFifoDepth + 1) * 1000000,
- This->Mode->BaudRate,
- NULL
- )
- );
-
- for (Index = 0; Index < *BufferSize; Index++) {
- SerialFifoAdd (&SerialDevice->Transmit, CharBuffer[Index]);
-
- while (SerialReceiveTransmit (SerialDevice) != EFI_SUCCESS || !SerialFifoEmpty (&SerialDevice->Transmit)) {
- //
- // Unsuccessful write so check if timeout has expired, if not,
- // stall for a bit, increment time elapsed, and try again
- //
- if (Elapsed >= Timeout) {
- *BufferSize = ActualWrite;
- gBS->RestoreTPL (Tpl);
- return EFI_TIMEOUT;
- }
-
- gBS->Stall (TIMEOUT_STALL_INTERVAL);
-
- Elapsed += TIMEOUT_STALL_INTERVAL;
- }
-
- ActualWrite++;
- //
- // Successful write so reset timeout
- //
- Elapsed = 0;
- }
-
- gBS->RestoreTPL (Tpl);
-
- return EFI_SUCCESS;
-}
-
-/**
- Read the specified number of bytes from serial device.
-
- @param This Pointer to EFI_SERIAL_IO_PROTOCOL
- @param BufferSize On input the size of Buffer, on output the amount of
- data returned in buffer
- @param Buffer The buffer to return the data into
-
- @retval EFI_SUCCESS The data were read successfully
- @retval EFI_DEVICE_ERROR The device reported an error
- @retval EFI_TIMEOUT The read operation was stopped due to timeout
-
-**/
-EFI_STATUS
-EFIAPI
-SerialRead (
- IN EFI_SERIAL_IO_PROTOCOL *This,
- IN OUT UINTN *BufferSize,
- OUT VOID *Buffer
- )
-{
- SERIAL_DEV *SerialDevice;
- UINT32 Index;
- UINT8 *CharBuffer;
- UINTN Elapsed;
- EFI_STATUS Status;
- EFI_TPL Tpl;
-
- SerialDevice = SERIAL_DEV_FROM_THIS (This);
- Elapsed = 0;
-
- if (*BufferSize == 0) {
- return EFI_SUCCESS;
- }
-
- if (Buffer == NULL) {
- return EFI_DEVICE_ERROR;
- }
-
- Tpl = gBS->RaiseTPL (TPL_NOTIFY);
-
- Status = SerialReceiveTransmit (SerialDevice);
-
- if (EFI_ERROR (Status)) {
- *BufferSize = 0;
-
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (
- EFI_ERROR_CODE,
- EFI_P_EC_INPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT,
- SerialDevice->DevicePath
- );
-
- gBS->RestoreTPL (Tpl);
-
- return EFI_DEVICE_ERROR;
- }
-
- CharBuffer = (UINT8 *) Buffer;
- for (Index = 0; Index < *BufferSize; Index++) {
- while (SerialFifoRemove (&SerialDevice->Receive, &(CharBuffer[Index])) != EFI_SUCCESS) {
- //
- // Unsuccessful read so check if timeout has expired, if not,
- // stall for a bit, increment time elapsed, and try again
- // Need this time out to get conspliter to work.
- //
- if (Elapsed >= This->Mode->Timeout) {
- *BufferSize = Index;
- gBS->RestoreTPL (Tpl);
- return EFI_TIMEOUT;
- }
-
- gBS->Stall (TIMEOUT_STALL_INTERVAL);
- Elapsed += TIMEOUT_STALL_INTERVAL;
-
- Status = SerialReceiveTransmit (SerialDevice);
- if (Status == EFI_DEVICE_ERROR) {
- *BufferSize = Index;
- gBS->RestoreTPL (Tpl);
- return EFI_DEVICE_ERROR;
- }
- }
- //
- // Successful read so reset timeout
- //
- Elapsed = 0;
- }
-
- SerialReceiveTransmit (SerialDevice);
-
- gBS->RestoreTPL (Tpl);
-
- return EFI_SUCCESS;
-}
-
-/**
- Use scratchpad register to test if this serial port is present.
-
- @param SerialDevice Pointer to serial device structure
-
- @return if this serial port is present
-**/
-BOOLEAN
-SerialPresent (
- IN SERIAL_DEV *SerialDevice
- )
-
-{
- UINT8 Temp;
- BOOLEAN Status;
-
- Status = TRUE;
-
- //
- // Save SCR reg
- //
- Temp = READ_SCR (SerialDevice);
- WRITE_SCR (SerialDevice, 0xAA);
-
- if (READ_SCR (SerialDevice) != 0xAA) {
- Status = FALSE;
- }
-
- WRITE_SCR (SerialDevice, 0x55);
-
- if (READ_SCR (SerialDevice) != 0x55) {
- Status = FALSE;
- }
- //
- // Restore SCR
- //
- WRITE_SCR (SerialDevice, Temp);
- return Status;
-}
-
-/**
- Read serial port.
-
- @param SerialDev Pointer to serial device
- @param Offset Offset in register group
-
- @return Data read from serial port
-
-**/
-UINT8
-SerialReadRegister (
- IN SERIAL_DEV *SerialDev,
- IN UINT32 Offset
- )
-{
- UINT8 Data;
- EFI_STATUS Status;
-
- if (SerialDev->PciDeviceInfo == NULL) {
- return IoRead8 ((UINTN) SerialDev->BaseAddress + Offset * SerialDev->RegisterStride);
- } else {
- if (SerialDev->MmioAccess) {
- Status = SerialDev->PciDeviceInfo->PciIo->Mem.Read (SerialDev->PciDeviceInfo->PciIo, EfiPciIoWidthUint8, EFI_PCI_IO_PASS_THROUGH_BAR,
- SerialDev->BaseAddress + Offset * SerialDev->RegisterStride, 1, &Data);
- } else {
- Status = SerialDev->PciDeviceInfo->PciIo->Io.Read (SerialDev->PciDeviceInfo->PciIo, EfiPciIoWidthUint8, EFI_PCI_IO_PASS_THROUGH_BAR,
- SerialDev->BaseAddress + Offset * SerialDev->RegisterStride, 1, &Data);
- }
- ASSERT_EFI_ERROR (Status);
- return Data;
- }
-}
-
-/**
- Write serial port.
-
- @param SerialDev Pointer to serial device
- @param Offset Offset in register group
- @param Data data which is to be written to some serial port register
-**/
-VOID
-SerialWriteRegister (
- IN SERIAL_DEV *SerialDev,
- IN UINT32 Offset,
- IN UINT8 Data
- )
-{
- EFI_STATUS Status;
-
- if (SerialDev->PciDeviceInfo == NULL) {
- IoWrite8 ((UINTN) SerialDev->BaseAddress + Offset * SerialDev->RegisterStride, Data);
- } else {
- if (SerialDev->MmioAccess) {
- Status = SerialDev->PciDeviceInfo->PciIo->Mem.Write (SerialDev->PciDeviceInfo->PciIo, EfiPciIoWidthUint8, EFI_PCI_IO_PASS_THROUGH_BAR,
- SerialDev->BaseAddress + Offset * SerialDev->RegisterStride, 1, &Data);
- } else {
- Status = SerialDev->PciDeviceInfo->PciIo->Io.Write (SerialDev->PciDeviceInfo->PciIo, EfiPciIoWidthUint8, EFI_PCI_IO_PASS_THROUGH_BAR,
- SerialDev->BaseAddress + Offset * SerialDev->RegisterStride, 1, &Data);
- }
- ASSERT_EFI_ERROR (Status);
- }
-}
|