Blame SOURCES/0368-grub-core-term-ns8250.c-Systematically-probe-ports-b.patch

f96e0b
From 38f3f1c0902e344a92a7a8994cd25c13b544b7e9 Mon Sep 17 00:00:00 2001
f96e0b
From: Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>
f96e0b
Date: Sat, 27 Apr 2013 22:47:57 +0200
f96e0b
Subject: [PATCH 368/482] 	* grub-core/term/ns8250.c: Systematically
f96e0b
 probe ports by writing 	to SR before using them.
f96e0b
f96e0b
---
f96e0b
 ChangeLog               |  5 +++++
f96e0b
 grub-core/term/ns8250.c | 46 +++++++++++++++++++++++++++++++++++++++++++---
f96e0b
 2 files changed, 48 insertions(+), 3 deletions(-)
f96e0b
f96e0b
diff --git a/ChangeLog b/ChangeLog
f96e0b
index 83cdafc..43b2906 100644
f96e0b
--- a/ChangeLog
f96e0b
+++ b/ChangeLog
f96e0b
@@ -1,3 +1,8 @@
f96e0b
+2013-04-27  Vladimir Serbinenko  <phcoder@gmail.com>
f96e0b
+
f96e0b
+	* grub-core/term/ns8250.c: Systematically probe ports by writing
f96e0b
+	to SR before using them.
f96e0b
+
f96e0b
 2013-04-27  Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
f96e0b
 
f96e0b
 	* util/ieee1275/ofpath.c (of_path_of_scsi): Fix path output for sas
f96e0b
diff --git a/grub-core/term/ns8250.c b/grub-core/term/ns8250.c
f96e0b
index e6947f5..2064e0d 100644
f96e0b
--- a/grub-core/term/ns8250.c
f96e0b
+++ b/grub-core/term/ns8250.c
f96e0b
@@ -36,6 +36,8 @@ static const grub_port_t serial_hw_io_addr[] = GRUB_MACHINE_SERIAL_PORTS;
f96e0b
 #define GRUB_SERIAL_PORT_NUM (ARRAY_SIZE(serial_hw_io_addr))
f96e0b
 #endif
f96e0b
 
f96e0b
+static int dead_ports = 0;
f96e0b
+
f96e0b
 /* Convert speed to divisor.  */
f96e0b
 static unsigned short
f96e0b
 serial_get_divisor (const struct grub_serial_port *port __attribute__ ((unused)),
f96e0b
@@ -83,6 +85,8 @@ do_real_config (struct grub_serial_port *port)
f96e0b
 {
f96e0b
   int divisor;
f96e0b
   unsigned char status = 0;
f96e0b
+  grub_uint64_t endtime;
f96e0b
+
f96e0b
   const unsigned char parities[] = {
f96e0b
     [GRUB_SERIAL_PARITY_NONE] = UART_NO_PARITY,
f96e0b
     [GRUB_SERIAL_PARITY_ODD] = UART_ODD_PARITY,
f96e0b
@@ -132,8 +136,16 @@ do_real_config (struct grub_serial_port *port)
f96e0b
 #endif
f96e0b
 
f96e0b
   /* Drain the input buffer.  */
f96e0b
+  endtime = grub_get_time_ms () + 1000;
f96e0b
   while (grub_inb (port->port + UART_LSR) & UART_DATA_READY)
f96e0b
-    grub_inb (port->port + UART_RX);
f96e0b
+    {
f96e0b
+      grub_inb (port->port + UART_RX);
f96e0b
+      if (grub_get_time_ms () > endtime)
f96e0b
+	{
f96e0b
+	  port->broken = 1;
f96e0b
+	  break;
f96e0b
+	}
f96e0b
+    }
f96e0b
 
f96e0b
   port->configured = 1;
f96e0b
 }
f96e0b
@@ -239,6 +251,20 @@ grub_ns8250_init (void)
f96e0b
     if (serial_hw_io_addr[i])
f96e0b
       {
f96e0b
 	grub_err_t err;
f96e0b
+
f96e0b
+	grub_outb (0x5a, serial_hw_io_addr[i] + UART_SR);
f96e0b
+	if (grub_inb (serial_hw_io_addr[i] + UART_SR) != 0x5a)
f96e0b
+	  {
f96e0b
+	    dead_ports |= (1 << i);
f96e0b
+	    continue;
f96e0b
+	  }
f96e0b
+	grub_outb (0xa5, serial_hw_io_addr[i] + UART_SR);
f96e0b
+	if (grub_inb (serial_hw_io_addr[i] + UART_SR) != 0xa5)
f96e0b
+	  {
f96e0b
+	    dead_ports |= (1 << i);
f96e0b
+	    continue;
f96e0b
+	  }
f96e0b
+
f96e0b
 	grub_snprintf (com_names[i], sizeof (com_names[i]), "com%d", i);
f96e0b
 	com_ports[i].name = com_names[i];
f96e0b
 	com_ports[i].driver = &grub_ns8250_driver;
f96e0b
@@ -255,7 +281,8 @@ grub_ns8250_init (void)
f96e0b
 grub_port_t
f96e0b
 grub_ns8250_hw_get_port (const unsigned int unit)
f96e0b
 {
f96e0b
-  if (unit < GRUB_SERIAL_PORT_NUM)
f96e0b
+  if (unit < GRUB_SERIAL_PORT_NUM
f96e0b
+      && !(dead_ports & (1 << unit)))
f96e0b
     return serial_hw_io_addr[unit];
f96e0b
   else
f96e0b
     return 0;
f96e0b
@@ -268,7 +295,20 @@ grub_serial_ns8250_add_port (grub_port_t port)
f96e0b
   unsigned i;
f96e0b
   for (i = 0; i < GRUB_SERIAL_PORT_NUM; i++)
f96e0b
     if (com_ports[i].port == port)
f96e0b
-      return com_names[i];
f96e0b
+      {
f96e0b
+	if (dead_ports & (1 << i))
f96e0b
+	  return NULL;
f96e0b
+	return com_names[i];
f96e0b
+      }
f96e0b
+
f96e0b
+  grub_outb (0x5a, port + UART_SR);
f96e0b
+  if (grub_inb (port + UART_SR) != 0x5a)
f96e0b
+    return NULL;
f96e0b
+
f96e0b
+  grub_outb (0xa5, port + UART_SR);
f96e0b
+  if (grub_inb (port + UART_SR) != 0xa5)
f96e0b
+    return NULL;
f96e0b
+
f96e0b
   p = grub_malloc (sizeof (*p));
f96e0b
   if (!p)
f96e0b
     return NULL;
f96e0b
-- 
f96e0b
1.8.2.1
f96e0b