/** @file\r
Serial driver for standard UARTS on an ISA bus.\r
\r
-Copyright (c) 2006 - 2010, Intel Corporation<BR>\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
which accompanies this distribution. The full text of the license may be found at\r
http://opensource.org/licenses/bsd-license.php\r
{ // SerialMode\r
SERIAL_PORT_SUPPORT_CONTROL_MASK,\r
SERIAL_PORT_DEFAULT_TIMEOUT,\r
- FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate\r
+ 0,\r
SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH,\r
- FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits\r
- FixedPcdGet8 (PcdUartDefaultParity), // Parity\r
- FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits\r
+ 0,\r
+ 0,\r
+ 0\r
},\r
NULL,\r
NULL,\r
}\r
},\r
0,\r
- FixedPcdGet64 (PcdUartDefaultBaudRate), \r
- FixedPcdGet8 (PcdUartDefaultDataBits),\r
- FixedPcdGet8 (PcdUartDefaultParity),\r
- FixedPcdGet8 (PcdUartDefaultStopBits)\r
+ 0,\r
+ 0,\r
+ 0,\r
+ 0\r
},\r
NULL,\r
0, //BaseAddress\r
Check the device path node whether it's the Flow Control node or not.\r
\r
@param[in] FlowControl The device path node to be checked.\r
- \r
+\r
@retval TRUE It's the Flow Control node.\r
@retval FALSE It's not.\r
\r
Check the device path node whether it contains Flow Control node or not.\r
\r
@param[in] DevicePath The device path to be checked.\r
- \r
+\r
@retval TRUE It contains the Flow Control node.\r
@retval FALSE It doesn't.\r
\r
/**\r
The user Entry Point for module IsaSerial. The user code starts with this function.\r
\r
- @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
@param[in] SystemTable A pointer to the EFI System Table.\r
- \r
+\r
@retval EFI_SUCCESS The entry point is executed successfully.\r
@retval other Some error occurs when executing this entry point.\r
\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
+ //\r
+ // Initialize UART default setting in gSerialDevTempate\r
+ //\r
+ gSerialDevTempate.SerialMode.BaudRate = PcdGet64 (PcdUartDefaultBaudRate);\r
+ gSerialDevTempate.SerialMode.DataBits = PcdGet8 (PcdUartDefaultDataBits);\r
+ gSerialDevTempate.SerialMode.Parity = PcdGet8 (PcdUartDefaultParity);\r
+ gSerialDevTempate.SerialMode.StopBits = PcdGet8 (PcdUartDefaultStopBits);\r
+ gSerialDevTempate.UartDevicePath.BaudRate = PcdGet64 (PcdUartDefaultBaudRate);\r
+ gSerialDevTempate.UartDevicePath.DataBits = PcdGet8 (PcdUartDefaultDataBits);\r
+ gSerialDevTempate.UartDevicePath.Parity = PcdGet8 (PcdUartDefaultParity);\r
+ gSerialDevTempate.UartDevicePath.StopBits = PcdGet8 (PcdUartDefaultStopBits);\r
\r
return Status;\r
}\r
EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
UINTN EntryCount;\r
UINTN Index;\r
+ BOOLEAN HasFlowControl;\r
\r
//\r
// Check RemainingDevicePath validation\r
//\r
if (RemainingDevicePath != NULL) {\r
//\r
- // Check if RemainingDevicePath is the End of Device Path Node, \r
+ // Check if RemainingDevicePath is the End of Device Path Node,\r
// if yes, go on checking other conditions\r
//\r
if (!IsDevicePathEnd (RemainingDevicePath)) {\r
) {\r
goto Error;\r
}\r
- \r
+\r
if (UartNode->BaudRate > SERIAL_PORT_MAX_BAUD_RATE) {\r
goto Error;\r
}\r
- \r
+\r
if (UartNode->Parity < NoParity || UartNode->Parity > SpaceParity) {\r
goto Error;\r
}\r
- \r
+\r
if (UartNode->DataBits < 5 || UartNode->DataBits > 8) {\r
goto Error;\r
}\r
- \r
+\r
if (UartNode->StopBits < OneStopBit || UartNode->StopBits > TwoStopBits) {\r
goto Error;\r
}\r
- \r
+\r
if ((UartNode->DataBits == 5) && (UartNode->StopBits == TwoStopBits)) {\r
goto Error;\r
}\r
- \r
+\r
if ((UartNode->DataBits >= 6) && (UartNode->DataBits <= 8) && (UartNode->StopBits == OneFiveStopBits)) {\r
goto Error;\r
}\r
Controller,\r
EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
);\r
- if (!EFI_ERROR (Status) &&\r
- (ContainsFlowControl (RemainingDevicePath) ^ ContainsFlowControl (DevicePath))) {\r
- Status = EFI_UNSUPPORTED;\r
+ if (!EFI_ERROR (Status)) {\r
+ HasFlowControl = ContainsFlowControl (RemainingDevicePath);\r
+ if (HasFlowControl ^ ContainsFlowControl (DevicePath)) {\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
}\r
break;\r
}\r
// Clear the bits that are not allowed to pass to SetControl\r
//\r
Control &= (EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY |\r
- EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE | \r
+ EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE |\r
EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE);\r
Status = SerialIo->SetControl (SerialIo, Control);\r
}\r
//\r
// If RemainingDevicePath is the End of Device Path Node,\r
// skip enumerate any device and return EFI_SUCESSS\r
- // \r
+ //\r
return EFI_SUCCESS;\r
}\r
}\r
FlowControlMap = 0;\r
\r
//\r
- // Check if RemainingDevicePath is NULL, \r
+ // Check if RemainingDevicePath is NULL,\r
// if yes, use the values from the gSerialDevTempate as no remaining device path was\r
// passed in.\r
//\r
if (RemainingDevicePath != NULL) {\r
//\r
- // If RemainingDevicePath isn't NULL, \r
+ // If RemainingDevicePath isn't NULL,\r
// match the configuration of the RemainingDevicePath. IsHandleSupported()\r
// already checked to make sure the RemainingDevicePath contains settings\r
// that we can support.\r
SerialDevice->BaseAddress = (UINT16) SerialDevice->IsaIo->ResourceList->ResourceItem[Index].StartRange;\r
}\r
}\r
- \r
+\r
SerialDevice->HardwareFlowControl = (BOOLEAN) (FlowControlMap == UART_FLOW_CONTROL_HARDWARE);\r
\r
//\r
\r
//\r
// Build the device path by appending the UART node to the ParentDevicePath.\r
- // The Uart setings are zero here, since SetAttribute() will update them to match \r
+ // The Uart setings are zero here, since SetAttribute() will update them to match\r
// the default setings.\r
//\r
SerialDevice->DevicePath = AppendDevicePathNode (\r
\r
/**\r
Detect whether specific FIFO is empty or not.\r
- \r
+\r
@param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO\r
\r
@return whether specific FIFO is empty or not\r
Data = READ_RBR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
\r
IsaSerialFifoAdd (&SerialDevice->Receive, Data);\r
- \r
+\r
//\r
// For full handshake flow control, if receive buffer full\r
// tell the peer to stop sending data.\r
// Compute divisor use to program the baud rate using a round determination\r
//\r
Divisor = (UINT32) DivU64x32Remainder (\r
- SERIAL_PORT_INPUT_CLOCK,\r
+ PcdGet32 (PcdSerialClockRate),\r
((UINT32) BaudRate * 16),\r
&Remained\r
);\r
- if (Remained != 0) {\r
+ if (Remained >= ((UINT32) BaudRate * 8)) {\r
Divisor += 1;\r
}\r
\r
//\r
// Compute the actual baud rate that the serial port will be programmed for.\r
//\r
- BaudRate = SERIAL_PORT_INPUT_CLOCK / Divisor / 16;\r
+ BaudRate = PcdGet32 (PcdSerialClockRate) / Divisor / 16;\r
\r
//\r
// Put serial port on Divisor Latch Mode\r
//\r
// first determine the parameter is invalid\r
//\r
- if (Control & (~(EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY |\r
- EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE | \r
- EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) {\r
+ if ((Control & (~(EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY |\r
+ EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE |\r
+ EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) != 0) {\r
return EFI_UNSUPPORTED;\r
}\r
\r
UINTN Elapsed;\r
UINTN ActualWrite;\r
EFI_TPL Tpl;\r
+ UINTN Timeout;\r
+ UINTN BitsPerCharacter;\r
\r
SerialDevice = SERIAL_DEV_FROM_THIS (This);\r
Elapsed = 0;\r
\r
CharBuffer = (UINT8 *) Buffer;\r
\r
+ //\r
+ // Compute the number of bits in a single character. This is a start bit,\r
+ // followed by the number of data bits, followed by the number of stop bits.\r
+ // The number of stop bits is specified by an enumeration that includes\r
+ // support for 1.5 stop bits. Treat 1.5 stop bits as 2 stop bits.\r
+ //\r
+ BitsPerCharacter =\r
+ 1 +\r
+ This->Mode->DataBits +\r
+ ((This->Mode->StopBits == TwoStopBits) ? 2 : This->Mode->StopBits);\r
+\r
+ //\r
+ // Compute the timeout in microseconds to wait for a single byte to be\r
+ // transmitted. The Mode structure contans a Timeout field that is the\r
+ // maximum time to transmit or receive a character. However, many UARTs\r
+ // have a FIFO for transmits, so the time required to add one new character\r
+ // to the transmit FIFO may be the time required to flush a full FIFO. If\r
+ // the Timeout in the Mode structure is smaller than the time required to\r
+ // flush a full FIFO at the current baud rate, then use a timeout value that\r
+ // is required to flush a full transmit FIFO.\r
+ //\r
+ Timeout = MAX (\r
+ This->Mode->Timeout,\r
+ (UINTN)DivU64x64Remainder (\r
+ BitsPerCharacter * (SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH + 1) * 1000000,\r
+ This->Mode->BaudRate,\r
+ NULL\r
+ )\r
+ );\r
+\r
for (Index = 0; Index < *BufferSize; Index++) {\r
IsaSerialFifoAdd (&SerialDevice->Transmit, CharBuffer[Index]);\r
\r
// Unsuccessful write so check if timeout has expired, if not,\r
// stall for a bit, increment time elapsed, and try again\r
//\r
- if (Elapsed >= This->Mode->Timeout) {\r
+ if (Elapsed >= Timeout) {\r
*BufferSize = ActualWrite;\r
gBS->RestoreTPL (Tpl);\r
return EFI_TIMEOUT;\r