diff options
author | kaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk> | 2006-03-29 16:02:40 +0100 |
---|---|---|
committer | kaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk> | 2006-03-29 16:02:40 +0100 |
commit | 816b45f1c4833c77ba4e15655c992b1f3de76710 (patch) | |
tree | 9c82df3feead39488add194f88086ae9a66bec75 | |
parent | 0f60ff7a3bbc10ff56b5c00498f16206ade50fe9 (diff) | |
download | xen-816b45f1c4833c77ba4e15655c992b1f3de76710.tar.gz xen-816b45f1c4833c77ba4e15655c992b1f3de76710.tar.bz2 xen-816b45f1c4833c77ba4e15655c992b1f3de76710.zip |
Compute actual baud rate from UART divisor latch contents
when no baud rate is specified. Generalise the divisor
calculation based on external clock rate.
Signed-off-by: Keir Fraser <keir@xensource.com>
-rw-r--r-- | xen/drivers/char/ns16550.c | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/xen/drivers/char/ns16550.c b/xen/drivers/char/ns16550.c index f1ad820f0d..b9e4950af1 100644 --- a/xen/drivers/char/ns16550.c +++ b/xen/drivers/char/ns16550.c @@ -99,6 +99,9 @@ static struct ns16550 { #define PARITY_MARK (5<<3) #define PARITY_SPACE (7<<3) +/* Frequency of external clock source. This definition assumes PC platform. */ +#define UART_CLOCK_HZ 1843200 + static char ns_read_reg(struct ns16550 *uart, int reg) { if ( uart->remapped_io_base == NULL ) @@ -171,6 +174,7 @@ static void ns16550_init_preirq(struct serial_port *port) { struct ns16550 *uart = port->uart; unsigned char lcr; + unsigned int divisor; /* I/O ports are distinguished by their size (16 bits). */ if ( uart->io_base >= 0x10000 ) @@ -182,13 +186,22 @@ static void ns16550_init_preirq(struct serial_port *port) ns_write_reg(uart, IER, 0); /* Line control and baud-rate generator. */ + ns_write_reg(uart, LCR, lcr | LCR_DLAB); if ( uart->baud != BAUD_AUTO ) { - ns_write_reg(uart, LCR, lcr | LCR_DLAB); - ns_write_reg(uart, DLL, 115200/uart->baud); /* baud lo */ - ns_write_reg(uart, DLM, 0); /* baud hi */ + /* Baud rate specified: program it into the divisor latch. */ + divisor = UART_CLOCK_HZ / (uart->baud * 16); + ns_write_reg(uart, DLL, (char)divisor); + ns_write_reg(uart, DLM, (char)(divisor >> 8)); + } + else + { + /* Baud rate already set: read it out from the divisor latch. */ + divisor = ns_read_reg(uart, DLL); + divisor |= ns_read_reg(uart, DLM) << 8; + uart->baud = UART_CLOCK_HZ / (divisor * 16); } - ns_write_reg(uart, LCR, lcr); /* parity, data, stop */ + ns_write_reg(uart, LCR, lcr); /* No flow ctrl: DTR and RTS are both wedged high to keep remote happy. */ ns_write_reg(uart, MCR, MCR_DTR | MCR_RTS); |