[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] ns16550 interrupt handler should not return until the IIR indicates
ChangeSet 1.1675, 2005/06/05 11:53:57+01:00, kaf24@xxxxxxxxxxxxxxxxxxxx ns16550 interrupt handler should not return until the IIR indicates no pending interrupts. Also a few generic serial driver cleanups. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> ns16550.c | 17 ++++++++++++---- serial.c | 65 +++++++++++++++++++++++++++++++++++--------------------------- 2 files changed, 50 insertions(+), 32 deletions(-) diff -Nru a/xen/drivers/char/ns16550.c b/xen/drivers/char/ns16550.c --- a/xen/drivers/char/ns16550.c 2005-06-05 07:02:39 -04:00 +++ b/xen/drivers/char/ns16550.c 2005-06-05 07:02:39 -04:00 @@ -49,7 +49,15 @@ #define IER_ELSI 0x04 /* rx line status */ #define IER_EMSI 0x08 /* MODEM status */ -/* FIFO control register */ +/* Interrupt Identification Register */ +#define IIR_NOINT 0x01 /* no interrupt pending */ +#define IIR_IMASK 0x06 /* interrupt identity: */ +#define IIR_LSI 0x06 /* - rx line status */ +#define IIR_RDAI 0x04 /* - rx data recv'd */ +#define IIR_THREI 0x02 /* - tx reg. empty */ +#define IIR_MSI 0x00 /* - MODEM status */ + +/* FIFO Control Register */ #define FCR_ENABLE 0x01 /* enable FIFO */ #define FCR_CLRX 0x02 /* clear Rx FIFO */ #define FCR_CLTX 0x04 /* clear Tx FIFO */ @@ -59,7 +67,7 @@ #define FCR_TRG8 0x80 /* Rx FIFO trig lev 8 */ #define FCR_TRG14 0xc0 /* Rx FIFO trig lev 14 */ -/* Line control register */ +/* Line Control Register */ #define LCR_DLAB 0x80 /* Divisor Latch Access */ /* Modem Control Register */ @@ -104,10 +112,11 @@ struct serial_port *port = dev_id; struct ns16550 *uart = port->uart; - if ( (ns_read_reg(uart, IIR) & 7) == 2 ) + while ( !(ns_read_reg(uart, IIR) & IIR_NOINT) ) + { serial_tx_interrupt(port, regs); - else serial_rx_interrupt(port, regs); + } } static int ns16550_tx_empty(struct serial_port *port) diff -Nru a/xen/drivers/char/serial.c b/xen/drivers/char/serial.c --- a/xen/drivers/char/serial.c 2005-06-05 07:02:39 -04:00 +++ b/xen/drivers/char/serial.c 2005-06-05 07:02:39 -04:00 @@ -22,20 +22,13 @@ void serial_rx_interrupt(struct serial_port *port, struct cpu_user_regs *regs) { char c; - serial_rx_fn fn; + serial_rx_fn fn = NULL; unsigned long flags; - BUG_ON(!port->driver); - BUG_ON(!port->driver->getc); + spin_lock_irqsave(&port->lock, flags); - for ( ; ; ) + if ( port->driver->getc(port, &c) ) { - spin_lock_irqsave(&port->lock, flags); - - if ( !port->driver->getc(port, &c) ) - break; - - fn = NULL; if ( port->rx != NULL ) fn = port->rx; else if ( (c & 0x80) && (port->rx_hi != NULL) ) @@ -44,16 +37,12 @@ fn = port->rx_lo; else if ( (port->rxbufp - port->rxbufc) != SERIAL_RXBUFSZ ) port->rxbuf[MASK_SERIAL_RXBUF_IDX(port->rxbufp++)] = c; - - spin_unlock_irqrestore(&port->lock, flags); - - if ( fn != NULL ) - (*fn)(c & 0x7f, regs); - - cpu_relax(); } spin_unlock_irqrestore(&port->lock, flags); + + if ( fn != NULL ) + (*fn)(c & 0x7f, regs); } void serial_tx_interrupt(struct serial_port *port, struct cpu_user_regs *regs) @@ -61,18 +50,17 @@ int i; unsigned long flags; - BUG_ON(!port->driver); - BUG_ON(!port->driver->tx_empty); - BUG_ON(!port->driver->putc); - spin_lock_irqsave(&port->lock, flags); - for ( i = 0; i < port->tx_fifo_size; i++ ) + if ( port->driver->tx_empty(port) ) { - if ( port->txbufc == port->txbufp ) - break; - port->driver->putc( - port, port->txbuf[MASK_SERIAL_TXBUF_IDX(port->txbufc++)]); + for ( i = 0; i < port->tx_fifo_size; i++ ) + { + if ( port->txbufc == port->txbufp ) + break; + port->driver->putc( + port, port->txbuf[MASK_SERIAL_TXBUF_IDX(port->txbufc++)]); + } } spin_unlock_irqrestore(&port->lock, flags); @@ -146,8 +134,29 @@ void serial_puts(int handle, const char *s) { - while ( *s != '\0' ) - serial_putc(handle, *s++); + struct serial_port *port = &com[handle & SERHND_IDX]; + unsigned long flags; + char c; + + if ( (handle == -1) || !port->driver || !port->driver->putc ) + return; + + spin_lock_irqsave(&port->lock, flags); + + while ( (c = *s++) != '\0' ) + { + if ( (c == '\n') && (handle & SERHND_COOKED) ) + __serial_putc(port, '\r'); + + if ( handle & SERHND_HI ) + c |= 0x80; + else if ( handle & SERHND_LO ) + c &= 0x7f; + + __serial_putc(port, c); + } + + spin_unlock_irqrestore(&port->lock, flags); } char serial_getc(int handle) _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |