From 24977b4451d626057ac1bf5e813baddc045ec5ec Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 16 Oct 2010 17:29:12 +0200 Subject: [PATCH] * grub-core/term/ns8250.c (do_real_config): Set port->broken to 0. (serial_hw_put): Wait based on real time rather than port reads. Don't roken ports. * include/grub/serial.h (grub_serial_port): New field broken. --- ChangeLog | 7 +++++++ grub-core/term/ns8250.c | 23 +++++++++++++++++++---- include/grub/serial.h | 6 +++++- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4b2a7a705..3f9c5a8cd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2010-10-16 Vladimir Serbinenko + + * grub-core/term/ns8250.c (do_real_config): Set port->broken to 0. + (serial_hw_put): Wait based on real time rather than port reads. Don't + roken ports. + * include/grub/serial.h (grub_serial_port): New field broken. + 2010-10-16 Robert Millan * grub-core/kern/emu/misc.c diff --git a/grub-core/term/ns8250.c b/grub-core/term/ns8250.c index 550ee6341..4be528df8 100644 --- a/grub-core/term/ns8250.c +++ b/grub-core/term/ns8250.c @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef GRUB_MACHINE_PCBIOS #include @@ -90,6 +91,8 @@ do_real_config (struct grub_serial_port *port) if (port->configured) return; + port->broken = 0; + divisor = serial_get_divisor (port->config.speed); /* Turn off the interrupt. */ @@ -145,18 +148,30 @@ serial_hw_fetch (struct grub_serial_port *port) static void serial_hw_put (struct grub_serial_port *port, const int c) { - unsigned int timeout = 100000; + grub_uint64_t endtime; do_real_config (port); + if (port->broken > 5) + endtime = grub_get_time_ms (); + else if (port->broken > 1) + endtime = grub_get_time_ms () + 50; + else + endtime = grub_get_time_ms () + 200; /* Wait until the transmitter holding register is empty. */ while ((grub_inb (port->port + UART_LSR) & UART_EMPTY_TRANSMITTER) == 0) { - if (--timeout == 0) - /* There is something wrong. But what can I do? */ - return; + if (grub_get_time_ms () > endtime) + { + port->broken++; + /* There is something wrong. But what can I do? */ + return; + } } + if (port->broken) + port->broken--; + grub_outb (c, port->port + UART_TX); } diff --git a/include/grub/serial.h b/include/grub/serial.h index 652268b2e..9540bee64 100644 --- a/include/grub/serial.h +++ b/include/grub/serial.h @@ -72,7 +72,11 @@ struct grub_serial_port */ union { - grub_port_t port; + struct + { + grub_port_t port; + int broken; + }; struct { grub_usb_device_t usbdev;