]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.c
1) Add type cast for better coding style.
[mirror_edk2.git] / MdeModulePkg / Library / BaseSerialPortLib16550 / BaseSerialPortLib16550.c
index 04d8ca194934ead73b66e684dd539f97237ab0c9..2fc6031ab74d1eb0e38e08c03343fa7c4fa8dfe8 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   16550 UART Serial Port library functions\r
 \r
-  Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2006 - 2014, 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
@@ -38,6 +38,7 @@
 #define   B_UART_LSR_TEMT     BIT6\r
 #define R_UART_MSR            6\r
 #define   B_UART_MSR_CTS      BIT4\r
+#define   B_UART_MSR_DSR      BIT5\r
 \r
 /**\r
   Read an 8-bit 16550 register.  If PcdSerialUseMmio is TRUE, then the value is read from \r
@@ -87,11 +88,57 @@ SerialPortWriteRegister (
   }\r
 }\r
 \r
+/**\r
+  Return whether the hardware flow control signal allows writing.\r
+\r
+  @retval TRUE  The serial port is writable.\r
+  @retval FALSE The serial port is not writable.\r
+**/\r
+BOOLEAN\r
+SerialPortWritable (\r
+  VOID\r
+  )\r
+{\r
+  if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {\r
+    if (PcdGetBool (PcdSerialDetectCable)) {\r
+      //\r
+      // Wait for both DSR and CTS to be set\r
+      //   DSR is set if a cable is connected.\r
+      //   CTS is set if it is ok to transmit data\r
+      //\r
+      //   DSR  CTS  Description                               Action\r
+      //   ===  ===  ========================================  ========\r
+      //    0    0   No cable connected.                       Wait\r
+      //    0    1   No cable connected.                       Wait\r
+      //    1    0   Cable connected, but not clear to send.   Wait\r
+      //    1    1   Cable connected, and clear to send.       Transmit\r
+      //\r
+      return (BOOLEAN) ((SerialPortReadRegister (R_UART_MSR) & (B_UART_MSR_DSR | B_UART_MSR_CTS)) == (B_UART_MSR_DSR | B_UART_MSR_CTS));\r
+    } else {\r
+      //\r
+      // Wait for both DSR and CTS to be set OR for DSR to be clear.  \r
+      //   DSR is set if a cable is connected.\r
+      //   CTS is set if it is ok to transmit data\r
+      //\r
+      //   DSR  CTS  Description                               Action\r
+      //   ===  ===  ========================================  ========\r
+      //    0    0   No cable connected.                       Transmit\r
+      //    0    1   No cable connected.                       Transmit\r
+      //    1    0   Cable connected, but not clear to send.   Wait\r
+      //    1    1   Cable connected, and clar to send.        Transmit\r
+      //\r
+      return (BOOLEAN) ((SerialPortReadRegister (R_UART_MSR) & (B_UART_MSR_DSR | B_UART_MSR_CTS)) != (B_UART_MSR_DSR));\r
+    }\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
 /**\r
   Initialize the serial device hardware.\r
   \r
   If no initialization is required, then return RETURN_SUCCESS.\r
-  If the serial device was successfuly initialized, then return RETURN_SUCCESS.\r
+  If the serial device was successfully initialized, then return RETURN_SUCCESS.\r
   If the serial device could not be initialized, then return RETURN_DEVICE_ERROR.\r
   \r
   @retval RETURN_SUCCESS        The serial device was initialized.\r
@@ -130,7 +177,7 @@ SerialPortInitialize (
   }\r
   SerialPortWriteRegister (R_UART_LCR, (UINT8)(SerialPortReadRegister (R_UART_LCR) | B_UART_LCR_DLAB));\r
   Divisor =  SerialPortReadRegister (R_UART_BAUD_HIGH) << 8;\r
-  Divisor |= SerialPortReadRegister (R_UART_BAUD_LOW);\r
+  Divisor |= (UINTN)SerialPortReadRegister (R_UART_BAUD_LOW);\r
   SerialPortWriteRegister (R_UART_LCR, (UINT8)(SerialPortReadRegister (R_UART_LCR) & ~B_UART_LCR_DLAB));\r
   if (Divisor != 115200 / PcdGet32 (PcdSerialBaudRate)) {\r
     Initialized = FALSE;\r
@@ -157,7 +204,7 @@ SerialPortInitialize (
   // Enable and reset FIFOs\r
   // Strip reserved bits from PcdSerialFifoControl\r
   //\r
-  SerialPortWriteRegister (R_UART_FCR, (UINT8)(PcdGet8 (PcdSerialFifoControl) & 0x17));\r
+  SerialPortWriteRegister (R_UART_FCR, (UINT8)(PcdGet8 (PcdSerialFifoControl) & 0x27));\r
 \r
   //\r
   // Put Modem Control Register(MCR) into its reset state of 0x00.\r
@@ -201,6 +248,23 @@ SerialPortWrite (
     return 0;\r
   }\r
 \r
+  if (NumberOfBytes == 0) {\r
+    //\r
+    // Flush the hardware\r
+    //\r
+\r
+    //\r
+    // Wait for both the transmit FIFO and shift register empty.\r
+    //\r
+    while ((SerialPortReadRegister (R_UART_LSR) & B_UART_LSR_TEMT) == 0);\r
+\r
+    //\r
+    // Wait for the hardware flow control signal\r
+    //\r
+    while (!SerialPortWritable ());\r
+    return 0;\r
+  }\r
+\r
   //\r
   // Compute the maximum size of the Tx FIFO\r
   //\r
@@ -225,13 +289,11 @@ SerialPortWrite (
     // Fill then entire Tx FIFO\r
     //\r
     for (Index = 0; Index < FifoSize && NumberOfBytes != 0; Index++, NumberOfBytes--, Buffer++) {\r
-      if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {\r
-        //\r
-        // Wait for notification from peer to send data\r
-        //\r
-        while ((SerialPortReadRegister (R_UART_MSR) & (B_UART_MSR_CTS)) == 0);\r
-      }\r
-      \r
+      //\r
+      // Wait for the hardware flow control signal\r
+      //\r
+      while (!SerialPortWritable ());\r
+\r
       //\r
       // Write byte to the transmit buffer.\r
       //\r