]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/Serial.c
IntelFrameworkModulePkg/IsaSerialDxe: Use PcdSerialClockRate instead of hard code...
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / IsaSerialDxe / Serial.c
index c62e60b6f5c3806c83e9f76870678410b29cf5e9..57ee669d140682e922f5b0d632eef765e4e411a7 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Serial driver for standard UARTS on an ISA bus.\r
 \r
-Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2015, 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
@@ -43,11 +43,11 @@ SERIAL_DEV  gSerialDevTempate = {
   { // 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
@@ -61,10 +61,10 @@ SERIAL_DEV  gSerialDevTempate = {
       }\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
@@ -163,6 +163,17 @@ InitializeIsaSerial (
              );\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
@@ -1382,7 +1393,7 @@ IsaSerialSetAttributes (
   // 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
@@ -1399,7 +1410,7 @@ IsaSerialSetAttributes (
   //\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
@@ -1744,6 +1755,8 @@ IsaSerialWrite (
   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
@@ -1767,6 +1780,36 @@ IsaSerialWrite (
 \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
@@ -1775,7 +1818,7 @@ IsaSerialWrite (
       //  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