* 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.
This commit is contained in:
parent
5f8b440b6b
commit
24977b4451
3 changed files with 31 additions and 5 deletions
|
@ -1,3 +1,10 @@
|
||||||
|
2010-10-16 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
|
* 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 <rmh@gnu.org>
|
2010-10-16 Robert Millan <rmh@gnu.org>
|
||||||
|
|
||||||
* grub-core/kern/emu/misc.c
|
* grub-core/kern/emu/misc.c
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
#include <grub/cpu/io.h>
|
#include <grub/cpu/io.h>
|
||||||
#include <grub/mm.h>
|
#include <grub/mm.h>
|
||||||
|
#include <grub/time.h>
|
||||||
|
|
||||||
#ifdef GRUB_MACHINE_PCBIOS
|
#ifdef GRUB_MACHINE_PCBIOS
|
||||||
#include <grub/machine/memory.h>
|
#include <grub/machine/memory.h>
|
||||||
|
@ -90,6 +91,8 @@ do_real_config (struct grub_serial_port *port)
|
||||||
if (port->configured)
|
if (port->configured)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
port->broken = 0;
|
||||||
|
|
||||||
divisor = serial_get_divisor (port->config.speed);
|
divisor = serial_get_divisor (port->config.speed);
|
||||||
|
|
||||||
/* Turn off the interrupt. */
|
/* Turn off the interrupt. */
|
||||||
|
@ -145,18 +148,30 @@ serial_hw_fetch (struct grub_serial_port *port)
|
||||||
static void
|
static void
|
||||||
serial_hw_put (struct grub_serial_port *port, const int c)
|
serial_hw_put (struct grub_serial_port *port, const int c)
|
||||||
{
|
{
|
||||||
unsigned int timeout = 100000;
|
grub_uint64_t endtime;
|
||||||
|
|
||||||
do_real_config (port);
|
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. */
|
/* Wait until the transmitter holding register is empty. */
|
||||||
while ((grub_inb (port->port + UART_LSR) & UART_EMPTY_TRANSMITTER) == 0)
|
while ((grub_inb (port->port + UART_LSR) & UART_EMPTY_TRANSMITTER) == 0)
|
||||||
{
|
{
|
||||||
if (--timeout == 0)
|
if (grub_get_time_ms () > endtime)
|
||||||
/* There is something wrong. But what can I do? */
|
{
|
||||||
return;
|
port->broken++;
|
||||||
|
/* There is something wrong. But what can I do? */
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (port->broken)
|
||||||
|
port->broken--;
|
||||||
|
|
||||||
grub_outb (c, port->port + UART_TX);
|
grub_outb (c, port->port + UART_TX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,11 @@ struct grub_serial_port
|
||||||
*/
|
*/
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
grub_port_t port;
|
struct
|
||||||
|
{
|
||||||
|
grub_port_t port;
|
||||||
|
int broken;
|
||||||
|
};
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
grub_usb_device_t usbdev;
|
grub_usb_device_t usbdev;
|
||||||
|
|
Loading…
Reference in a new issue