diff options
author | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2003-09-21 17:48:32 +0000 |
---|---|---|
committer | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2003-09-21 17:48:32 +0000 |
commit | 6e837f6a4a063518025a60c1f38aff088b347211 (patch) | |
tree | 76220ae49fdd0dc4b7270c1902e064826c99056b | |
parent | 6c6454c920beb1e3a706401d245d0a8c3610ff08 (diff) | |
download | xen-6e837f6a4a063518025a60c1f38aff088b347211.tar.gz xen-6e837f6a4a063518025a60c1f38aff088b347211.tar.bz2 xen-6e837f6a4a063518025a60c1f38aff088b347211.zip |
bitkeeper revision 1.456 (3f6de470w7_JGb139gaotteaX7UDcQ)
xen_serial.c, kernel.c:
Robustify Xen's serial handling. We now assert DTR and RTS so that we play nicely with flow control. Also the rx interrupt reads all chars from the fifo rather than just one. TODO: tx should be interrupt driven, and domains shouldn't be echo to serial but should go to DOM0 only.
-rw-r--r-- | xen/common/kernel.c | 10 | ||||
-rw-r--r-- | xen/drivers/char/xen_serial.c | 34 |
2 files changed, 22 insertions, 22 deletions
diff --git a/xen/common/kernel.c b/xen/common/kernel.c index d1cbe51863..7b384a90ca 100644 --- a/xen/common/kernel.c +++ b/xen/common/kernel.c @@ -218,8 +218,6 @@ void cmain (unsigned long magic, multiboot_info_t *mbi) } -#ifdef CONFIG_OUTPUT_SERIAL - #define SERIAL_BASE 0x3f8 #define RX_BUF 0 #define TX_HOLD 0 @@ -239,24 +237,24 @@ void init_serial(void) outb(115200/opt_ser_baud, SERIAL_BASE+DIVISOR_LO); outb(0, SERIAL_BASE+DIVISOR_HI); outb(0x03, SERIAL_BASE+DATA_FORMAT); + + /* DTR and RTS should both be high, to keep other end happy. */ + outb(0x02, SERIAL_BASE+LINE_CTL); /* No interrupts. */ outb(0x00, SERIAL_BASE+INT_ENABLE); } +#ifdef CONFIG_OUTPUT_SERIAL void putchar_serial(unsigned char c) { if ( c == '\n' ) putchar_serial('\r'); while ( !(inb(SERIAL_BASE+LINE_STATUS)&(1<<5)) ) barrier(); outb(c, SERIAL_BASE+TX_HOLD); } - #else - -void init_serial(void) {} void putchar_serial(unsigned char c) {} - #endif diff --git a/xen/drivers/char/xen_serial.c b/xen/drivers/char/xen_serial.c index 95107e587d..7a1560ca5b 100644 --- a/xen/drivers/char/xen_serial.c +++ b/xen/drivers/char/xen_serial.c @@ -56,15 +56,16 @@ static void serial_rx_int(int irq, void *dev_id, struct pt_regs *regs) u_char c; key_handler *handler; - /* clear the interrupt by reading the character */ - c = inb(SERIAL_BASE + NS16550_RBR); + while ( (inb(SERIAL_BASE + NS16550_LSR) & 1) == 1 ) + { + c = inb(SERIAL_BASE + NS16550_RBR); - /* if there's a handler, call it: we trust it won't screw us too badly */ - if((handler = get_key_handler(c)) != NULL) - (*handler)(c, dev_id, regs); + if( (handler = get_key_handler(c)) != NULL ) + (*handler)(c, dev_id, regs); - if(serial_echo) - printk("%c", c); + if ( serial_echo ) + printk("%c", c); + } } void initialize_serial() @@ -74,16 +75,17 @@ void initialize_serial() /* setup key handler */ add_key_handler('~', toggle_echo, "toggle serial echo"); - /* Should detect this, but must be a ns16550a at least, surely? */ - fifo = 1; - if(fifo) { - /* Clear FIFOs, enable, trigger at 1 byte */ - outb(NS16550_FCR_TRG1 | NS16550_FCR_ENABLE | - NS16550_FCR_CLRX | NS16550_FCR_CLTX, SERIAL_BASE+NS16550_FCR); - } + /* This assumes we have a 16550. It's pretty darned likely really! */ + /* Clear FIFOs, enable, trigger at 1 byte */ + outb(NS16550_FCR_TRG1 | NS16550_FCR_ENABLE | + NS16550_FCR_CLRX | NS16550_FCR_CLTX, + SERIAL_BASE+NS16550_FCR); - outb(NS16550_MCR_OUT2, SERIAL_BASE + NS16550_MCR); /* Modem control */ - outb(NS16550_IER_ERDAI, SERIAL_BASE + NS16550_IER ); /* Setup interrupts */ + /* Enable receive interrupts. Also remember to keep DTR/RTS asserted. */ + outb(NS16550_MCR_OUT2|NS16550_MCR_DTR|NS16550_MCR_RTS, + SERIAL_BASE + NS16550_MCR); + outb(NS16550_IER_ERDAI, + SERIAL_BASE + NS16550_IER ); if((rc = request_irq(4, serial_rx_int, SA_NOPROFILE, "serial", 0))) printk("initialize_serial: failed to get IRQ4, rc=%d\n", rc); |