[SERIAL] kernel console should send CRLF not LFCR
authorRussell King <rmk@dyn-67.arm.linux.org.uk>
Mon, 20 Mar 2006 20:00:09 +0000 (20:00 +0000)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Mon, 20 Mar 2006 20:00:09 +0000 (20:00 +0000)
Glen Turner reported that writing LFCR rather than the more
traditional CRLF causes issues with some terminals.

Since this aflicts many serial drivers, extract the common code
to a library function (uart_console_write) and arrange for each
driver to supply a "putchar" function.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
25 files changed:
drivers/serial/21285.c
drivers/serial/8250.c
drivers/serial/8250_early.c
drivers/serial/amba-pl010.c
drivers/serial/amba-pl011.c
drivers/serial/at91_serial.c
drivers/serial/au1x00_uart.c
drivers/serial/clps711x.c
drivers/serial/dz.c
drivers/serial/imx.c
drivers/serial/ip22zilog.c
drivers/serial/m32r_sio.c
drivers/serial/mpc52xx_uart.c
drivers/serial/pmac_zilog.c
drivers/serial/pxa.c
drivers/serial/s3c2410.c
drivers/serial/sa1100.c
drivers/serial/serial_core.c
drivers/serial/serial_lh7a40x.c
drivers/serial/serial_txx9.c
drivers/serial/sunsab.c
drivers/serial/sunsu.c
drivers/serial/sunzilog.c
drivers/serial/vr41xx_siu.c
include/linux/serial_core.h

index 8c5c276c55771eb297fa756ed2cf23e0159d8fc2..7572665a885516d89ece6dcb5898154a14be2916 100644 (file)
@@ -375,23 +375,18 @@ static void serial21285_setup_ports(void)
 }
 
 #ifdef CONFIG_SERIAL_21285_CONSOLE
+static void serial21285_console_putchar(struct uart_port *port, int ch)
+{
+       while (*CSR_UARTFLG & 0x20)
+               barrier();
+       *CSR_UARTDR = ch;
+}
 
 static void
 serial21285_console_write(struct console *co, const char *s,
                          unsigned int count)
 {
-       int i;
-
-       for (i = 0; i < count; i++) {
-               while (*CSR_UARTFLG & 0x20)
-                       barrier();
-               *CSR_UARTDR = s[i];
-               if (s[i] == '\n') {
-                       while (*CSR_UARTFLG & 0x20)
-                               barrier();
-                       *CSR_UARTDR = '\r';
-               }
-       }
+       uart_console_write(&serial21285_port, s, count, serial21285_console_putchar);
 }
 
 static void __init
index 7aca22c9976d0f37a9d8f3e0b0cf6a41d6a3d787..5996d3cd0ed854d2c13f2ecb30b2918cea025cab 100644 (file)
@@ -2182,6 +2182,14 @@ static inline void wait_for_xmitr(struct uart_8250_port *up, int bits)
        }
 }
 
+static void serial8250_console_putchar(struct uart_port *port, int ch)
+{
+       struct uart_8250_port *up = (struct uart_8250_port *)port;
+
+       wait_for_xmitr(up, UART_LSR_THRE);
+       serial_out(up, UART_TX, ch);
+}
+
 /*
  *     Print a string to the serial port trying not to disturb
  *     any possible real use of the port...
@@ -2193,7 +2201,6 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
 {
        struct uart_8250_port *up = &serial8250_ports[co->index];
        unsigned int ier;
-       int i;
 
        touch_nmi_watchdog();
 
@@ -2207,22 +2214,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
        else
                serial_out(up, UART_IER, 0);
 
-       /*
-        *      Now, do each character
-        */
-       for (i = 0; i < count; i++, s++) {
-               wait_for_xmitr(up, UART_LSR_THRE);
-
-               /*
-                *      Send the character out.
-                *      If a LF, also do CR...
-                */
-               serial_out(up, UART_TX, *s);
-               if (*s == 10) {
-                       wait_for_xmitr(up, UART_LSR_THRE);
-                       serial_out(up, UART_TX, 13);
-               }
-       }
+       uart_console_write(&up->port, s, count, serial8250_console_putchar);
 
        /*
         *      Finally, wait for transmitter to become empty
index 59ba5d993b4b6ef2fb66fc3b883639c78f19a91e..7e511199b4c5c91f09fcde69ced030c7ca15043d 100644 (file)
@@ -74,7 +74,7 @@ static void __init wait_for_xmitr(struct uart_port *port)
        }
 }
 
-static void __init putc(struct uart_port *port, unsigned char c)
+static void __init putc(struct uart_port *port, int c)
 {
        wait_for_xmitr(port);
        serial_out(port, UART_TX, c);
@@ -89,12 +89,7 @@ static void __init early_uart_write(struct console *console, const char *s, unsi
        ier = serial_in(port, UART_IER);
        serial_out(port, UART_IER, 0);
 
-       while (*s && count-- > 0) {
-               putc(port, *s);
-               if (*s == '\n')
-                       putc(port, '\r');
-               s++;
-       }
+       uart_console_write(port, s, count, putc);
 
        /* Wait for transmitter to become empty and restore the IER */
        wait_for_xmitr(port);
index 321a3b3a5728b3334afb75771722690a7d1d04cf..e04d5e82d9ae3e4e2f819348cce10cb53a3233e0 100644 (file)
@@ -591,12 +591,18 @@ static struct uart_amba_port amba_ports[UART_NR] = {
 
 #ifdef CONFIG_SERIAL_AMBA_PL010_CONSOLE
 
+static void pl010_console_putchar(struct uart_port *port, int ch)
+{
+       while (!UART_TX_READY(UART_GET_FR(port)))
+               barrier();
+       UART_PUT_CHAR(port, ch);
+}
+
 static void
 pl010_console_write(struct console *co, const char *s, unsigned int count)
 {
        struct uart_port *port = &amba_ports[co->index].port;
        unsigned int status, old_cr;
-       int i;
 
        /*
         *      First save the CR then disable the interrupts
@@ -604,21 +610,7 @@ pl010_console_write(struct console *co, const char *s, unsigned int count)
        old_cr = UART_GET_CR(port);
        UART_PUT_CR(port, UART01x_CR_UARTEN);
 
-       /*
-        *      Now, do each character
-        */
-       for (i = 0; i < count; i++) {
-               do {
-                       status = UART_GET_FR(port);
-               } while (!UART_TX_READY(status));
-               UART_PUT_CHAR(port, s[i]);
-               if (s[i] == '\n') {
-                       do {
-                               status = UART_GET_FR(port);
-                       } while (!UART_TX_READY(status));
-                       UART_PUT_CHAR(port, '\r');
-               }
-       }
+       uart_console_write(port, s, count, pl010_console_putchar);
 
        /*
         *      Finally, wait for transmitter to become empty
index 034a029e356edfe3e8f48d1749b03450e2196c26..3d966cfc9a38cba524a5a13383f4c6bda4a62328 100644 (file)
@@ -587,14 +587,12 @@ static struct uart_amba_port *amba_ports[UART_NR];
 
 #ifdef CONFIG_SERIAL_AMBA_PL011_CONSOLE
 
-static inline void
-pl011_console_write_char(struct uart_amba_port *uap, char ch)
+static void pl011_console_putchar(struct uart_port *port, int ch)
 {
-       unsigned int status;
+       struct uart_amba_port *uap = (struct uart_amba_port *)port;
 
-       do {
-               status = readw(uap->port.membase + UART01x_FR);
-       } while (status & UART01x_FR_TXFF);
+       while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)
+               barrier();
        writew(ch, uap->port.membase + UART01x_DR);
 }
 
@@ -603,7 +601,6 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
 {
        struct uart_amba_port *uap = amba_ports[co->index];
        unsigned int status, old_cr, new_cr;
-       int i;
 
        clk_enable(uap->clk);
 
@@ -615,14 +612,7 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
        new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
        writew(new_cr, uap->port.membase + UART011_CR);
 
-       /*
-        *      Now, do each character
-        */
-       for (i = 0; i < count; i++) {
-               pl011_console_write_char(uap, s[i]);
-               if (s[i] == '\n')
-                       pl011_console_write_char(uap, '\r');
-       }
+       uart_console_write(&uap->port, s, count, pl011_console_putchar);
 
        /*
         *      Finally, wait for transmitter to become empty
index 2113feb75c39890f6687d64ec80c88b3b56346f9..6547fe0cef96d49892097f3dea3dbe7b6303b715 100644 (file)
@@ -711,6 +711,12 @@ void __init at91_register_uart(int idx, int port)
 }
 
 #ifdef CONFIG_SERIAL_AT91_CONSOLE
+static void at91_console_putchar(struct uart_port *port, int ch)
+{
+       while (!(UART_GET_CSR(port) & AT91_US_TXRDY))
+               barrier();
+       UART_PUT_CHAR(port, ch);
+}
 
 /*
  * Interrupts are disabled on entering
@@ -718,7 +724,7 @@ void __init at91_register_uart(int idx, int port)
 static void at91_console_write(struct console *co, const char *s, u_int count)
 {
        struct uart_port *port = at91_ports + co->index;
-       unsigned int status, i, imr;
+       unsigned int status, imr;
 
        /*
         *      First, save IMR and then disable interrupts
@@ -726,21 +732,7 @@ static void at91_console_write(struct console *co, const char *s, u_int count)
        imr = UART_GET_IMR(port);       /* get interrupt mask */
        UART_PUT_IDR(port, AT91_US_RXRDY | AT91_US_TXRDY);
 
-       /*
-        *      Now, do each character
-        */
-       for (i = 0; i < count; i++) {
-               do {
-                       status = UART_GET_CSR(port);
-               } while (!(status & AT91_US_TXRDY));
-               UART_PUT_CHAR(port, s[i]);
-               if (s[i] == '\n') {
-                       do {
-                               status = UART_GET_CSR(port);
-                       } while (!(status & AT91_US_TXRDY));
-                       UART_PUT_CHAR(port, '\r');
-               }
-       }
+       uart_console_write(port, s, count, at91_console_putchar);
 
        /*
         *      Finally, wait for transmitter to become empty
index 344022fe53ef870522700ef2e92e57e6b25c1945..29f94bbb79be66fdde4b7096fd5caf1b12c0d5d0 100644 (file)
@@ -1121,6 +1121,14 @@ static inline void wait_for_xmitr(struct uart_8250_port *up)
        }
 }
 
+static void au1x00_console_putchar(struct uart_port *port, int ch)
+{
+       struct uart_8250_port *up = (struct uart_8250_port *)port;
+
+       wait_for_xmitr(up);
+       serial_out(up, UART_TX, ch);
+}
+
 /*
  *     Print a string to the serial port trying not to disturb
  *     any possible real use of the port...
@@ -1132,7 +1140,6 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
 {
        struct uart_8250_port *up = &serial8250_ports[co->index];
        unsigned int ier;
-       int i;
 
        /*
         *      First save the UER then disable the interrupts
@@ -1140,22 +1147,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
        ier = serial_in(up, UART_IER);
        serial_out(up, UART_IER, 0);
 
-       /*
-        *      Now, do each character
-        */
-       for (i = 0; i < count; i++, s++) {
-               wait_for_xmitr(up);
-
-               /*
-                *      Send the character out.
-                *      If a LF, also do CR...
-                */
-               serial_out(up, UART_TX, *s);
-               if (*s == 10) {
-                       wait_for_xmitr(up);
-                       serial_out(up, UART_TX, 13);
-               }
-       }
+       uart_console_write(&up->port, s, count, au1x00_console_putchar);
 
        /*
         *      Finally, wait for transmitter to become empty
index ce7b2e4ecd17c33a6fa12e2451f0e6d5ba276c1a..2691112c84adacc0c52724ff5319d3852eb6ea65 100644 (file)
@@ -424,6 +424,13 @@ static struct uart_port clps711x_ports[UART_NR] = {
 };
 
 #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
+static void clps711xuart_console_putchar(struct uart_port *port, int ch)
+{
+       while (clps_readl(SYSFLG(port)) & SYSFLG_UTXFF)
+               barrier();
+       clps_writel(ch, UARTDR(port));
+}
+
 /*
  *     Print a string to the serial port trying not to disturb
  *     any possible real use of the port...
@@ -438,7 +445,6 @@ clps711xuart_console_write(struct console *co, const char *s,
 {
        struct uart_port *port = clps711x_ports + co->index;
        unsigned int status, syscon;
-       int i;
 
        /*
         *      Ensure that the port is enabled.
@@ -446,21 +452,7 @@ clps711xuart_console_write(struct console *co, const char *s,
        syscon = clps_readl(SYSCON(port));
        clps_writel(syscon | SYSCON_UARTEN, SYSCON(port));
 
-       /*
-        *      Now, do each character
-        */
-       for (i = 0; i < count; i++) {
-               do {
-                       status = clps_readl(SYSFLG(port));
-               } while (status & SYSFLG_UTXFF);
-               clps_writel(s[i], UARTDR(port));
-               if (s[i] == '\n') {
-                       do {
-                               status = clps_readl(SYSFLG(port));
-                       } while (status & SYSFLG_UTXFF);
-                       clps_writel('\r', UARTDR(port));
-               }
-       }
+       uart_console_write(port, s, count, clps711xuart_console_putchar);
 
        /*
         *      Finally, wait for transmitter to become empty
index ba5541de673b1706079fc28e5423612e556f8006..bf71bad5c34f7ff14f3d55ec66d7f6db397e50b8 100644 (file)
@@ -674,11 +674,12 @@ static void dz_reset(struct dz_port *dport)
 }
 
 #ifdef CONFIG_SERIAL_DZ_CONSOLE
-static void dz_console_put_char(struct dz_port *dport, unsigned char ch)
+static void dz_console_putchar(struct uart_port *port, int ch)
 {
+       struct dz_port *dport = (struct dz_port *)uport;
        unsigned long flags;
        int loops = 2500;
-       unsigned short tmp = ch;
+       unsigned short tmp = (unsigned char)ch;
        /* this code sends stuff out to serial device - spinning its
           wheels and waiting. */
 
@@ -694,6 +695,7 @@ static void dz_console_put_char(struct dz_port *dport, unsigned char ch)
 
        spin_unlock_irqrestore(&dport->port.lock, flags);
 }
+
 /*
  * -------------------------------------------------------------------
  * dz_console_print ()
@@ -710,11 +712,7 @@ static void dz_console_print(struct console *cons,
 #ifdef DEBUG_DZ
        prom_printf((char *) str);
 #endif
-       while (count--) {
-               if (*str == '\n')
-                       dz_console_put_char(dport, '\r');
-               dz_console_put_char(dport, *str++);
-       }
+       uart_console_write(&dport->port, str, count, dz_console_putchar);
 }
 
 static int __init dz_console_setup(struct console *co, char *options)
index 4d53fb5ca87b7b1ded6fffb1e2ce427be1d71b23..c3b7a6673e9c81a8bea851513c61fc900b552fde 100644 (file)
@@ -743,6 +743,13 @@ static void __init imx_init_ports(void)
 }
 
 #ifdef CONFIG_SERIAL_IMX_CONSOLE
+static void imx_console_putchar(struct uart_port *port, int ch)
+{
+       struct imx_port *sport = (struct imx_port *)port;
+       while ((UTS((u32)sport->port.membase) & UTS_TXFULL))
+               barrier();
+       URTX0((u32)sport->port.membase) = ch;
+}
 
 /*
  * Interrupts are disabled on entering
@@ -751,7 +758,7 @@ static void
 imx_console_write(struct console *co, const char *s, unsigned int count)
 {
        struct imx_port *sport = &imx_ports[co->index];
-       unsigned int old_ucr1, old_ucr2, i;
+       unsigned int old_ucr1, old_ucr2;
 
        /*
         *      First, save UCR1/2 and then disable interrupts
@@ -764,22 +771,7 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
                           & ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN);
        UCR2((u32)sport->port.membase) = old_ucr2 | UCR2_TXEN;
 
-       /*
-        *      Now, do each character
-        */
-       for (i = 0; i < count; i++) {
-
-               while ((UTS((u32)sport->port.membase) & UTS_TXFULL))
-                       barrier();
-
-               URTX0((u32)sport->port.membase) = s[i];
-
-               if (s[i] == '\n') {
-                       while ((UTS((u32)sport->port.membase) & UTS_TXFULL))
-                               barrier();
-                       URTX0((u32)sport->port.membase) = '\r';
-               }
-       }
+       uart_console_write(&sport->port, s, count, imx_console_putchar);
 
        /*
         *      Finally, wait for transmitter to become empty
index 193722d680cf25f5ce42b1c1fa0e1c531940ac0b..651772474ac17d6687b4722f337b06765c2e7524 100644 (file)
@@ -967,8 +967,9 @@ static struct zilog_layout * __init get_zs(int chip)
 #define ZS_PUT_CHAR_MAX_DELAY  2000    /* 10 ms */
 
 #ifdef CONFIG_SERIAL_IP22_ZILOG_CONSOLE
-static void ip22zilog_put_char(struct zilog_channel *channel, unsigned char ch)
+static void ip22zilog_put_char(struct uart_port *port, int ch)
 {
+       struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port);
        int loops = ZS_PUT_CHAR_MAX_DELAY;
 
        /* This is a timed polling loop so do not switch the explicit
@@ -992,16 +993,10 @@ static void
 ip22zilog_console_write(struct console *con, const char *s, unsigned int count)
 {
        struct uart_ip22zilog_port *up = &ip22zilog_port_table[con->index];
-       struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
        unsigned long flags;
-       int i;
 
        spin_lock_irqsave(&up->port.lock, flags);
-       for (i = 0; i < count; i++, s++) {
-               ip22zilog_put_char(channel, *s);
-               if (*s == 10)
-                       ip22zilog_put_char(channel, 13);
-       }
+       uart_console_write(&up->port, s, count, ip22zilog_put_char);
        udelay(2);
        spin_unlock_irqrestore(&up->port.lock, flags);
 }
index 242a04104393e1e25e5462f23110830ba587c798..876bc5e027bb3592e38d9323c4e8c3085f642142 100644 (file)
@@ -1039,6 +1039,14 @@ static inline void wait_for_xmitr(struct uart_sio_port *up)
        }
 }
 
+static void m32r_sio_console_putchar(struct uart_port *port, int ch)
+{
+       struct uart_sio_port *up = (struct uart_sio_port *)port;
+
+       wait_for_xmitr(up);
+       sio_out(up, SIOTXB, ch);
+}
+
 /*
  *     Print a string to the serial port trying not to disturb
  *     any possible real use of the port...
@@ -1058,23 +1066,7 @@ static void m32r_sio_console_write(struct console *co, const char *s,
        ier = sio_in(up, SIOTRCR);
        sio_out(up, SIOTRCR, 0);
 
-       /*
-        *      Now, do each character
-        */
-       for (i = 0; i < count; i++, s++) {
-               wait_for_xmitr(up);
-
-               /*
-                *      Send the character out.
-                *      If a LF, also do CR...
-                */
-               sio_out(up, SIOTXB, *s);
-
-               if (*s == 10) {
-                       wait_for_xmitr(up);
-                       sio_out(up, SIOTXB, 13);
-               }
-       }
+       uart_console_write(&up->port, s, count, m32r_sio_console_putchar);
 
        /*
         *      Finally, wait for transmitter to become empty
index 61dd17d7bacefd0a777ad107dd75869c71b3a319..928e6cf12dca4c8d9b74b8de24293a3829213ce3 100644 (file)
@@ -603,15 +603,14 @@ mpc52xx_console_write(struct console *co, const char *s, unsigned int count)
                udelay(1);
 
        /* Write all the chars */
-       for ( i=0 ; i<count ; i++ ) {
-       
-               /* Send the char */
-               out_8(&psc->mpc52xx_psc_buffer_8, *s);
-
+       for (i = 0; i < count; i++, s++) {
                /* Line return handling */
-               if ( *s++ == '\n' )
+               if (*s == '\n')
                        out_8(&psc->mpc52xx_psc_buffer_8, '\r');
                
+               /* Send the char */
+               out_8(&psc->mpc52xx_psc_buffer_8, *s);
+
                /* Wait the TX buffer to be empty */
                j = 20000;      /* Maximum wait */      
                while (!(in_be16(&psc->mpc52xx_psc_status) & 
index 9b7ed58cb53b53a6800851d40d22ba41743668bb..513ff8597707bf5c642f0dd1d02aad97356fdf7f 100644 (file)
@@ -1916,6 +1916,16 @@ static void __exit exit_pmz(void)
 
 #ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE
 
+static void pmz_console_putchar(struct uart_port *port, int ch)
+{
+       struct uart_pmac_port *uap = (struct uart_pmac_port *)port;
+
+       /* Wait for the transmit buffer to empty. */
+       while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0)
+               udelay(5);
+       write_zsdata(uap, ch);
+}
+
 /*
  * Print a string to the serial port trying not to disturb
  * any possible real use of the port...
@@ -1924,7 +1934,6 @@ static void pmz_console_write(struct console *con, const char *s, unsigned int c
 {
        struct uart_pmac_port *uap = &pmz_ports[con->index];
        unsigned long flags;
-       int i;
 
        if (ZS_IS_ASLEEP(uap))
                return;
@@ -1934,17 +1943,7 @@ static void pmz_console_write(struct console *con, const char *s, unsigned int c
        write_zsreg(uap, R1, uap->curregs[1] & ~TxINT_ENAB);
        write_zsreg(uap, R5, uap->curregs[5] | TxENABLE | RTS | DTR);
 
-       for (i = 0; i < count; i++) {
-               /* Wait for the transmit buffer to empty. */
-               while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0)
-                       udelay(5);
-               write_zsdata(uap, s[i]);
-               if (s[i] == 10) {
-                       while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0)
-                               udelay(5);
-                       write_zsdata(uap, R13);
-               }
-       }
+       uart_console_write(&uap->port, s, count, pmz_console_putchar);
 
        /* Restore the values in the registers. */
        write_zsreg(uap, R1, uap->curregs[1]);
index 10535f00301f2e375c7a68ddf9a0d80662ffcb06..77d4568ccc3a7fdc0811783e7a1bbf52e7e1d5b9 100644 (file)
@@ -619,6 +619,14 @@ static inline void wait_for_xmitr(struct uart_pxa_port *up)
        }
 }
 
+static void serial_pxa_console_putchar(struct uart_port *port, int ch)
+{
+       struct uart_pxa_port *up = (struct uart_pxa_port *)port;
+
+       wait_for_xmitr(up);
+       serial_out(up, UART_TX, ch);
+}
+
 /*
  * Print a string to the serial port trying not to disturb
  * any possible real use of the port...
@@ -630,7 +638,6 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
 {
        struct uart_pxa_port *up = &serial_pxa_ports[co->index];
        unsigned int ier;
-       int i;
 
        /*
         *      First save the IER then disable the interrupts
@@ -638,22 +645,7 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
        ier = serial_in(up, UART_IER);
        serial_out(up, UART_IER, UART_IER_UUE);
 
-       /*
-        *      Now, do each character
-        */
-       for (i = 0; i < count; i++, s++) {
-               wait_for_xmitr(up);
-
-               /*
-                *      Send the character out.
-                *      If a LF, also do CR...
-                */
-               serial_out(up, UART_TX, *s);
-               if (*s == 10) {
-                       wait_for_xmitr(up);
-                       serial_out(up, UART_TX, 13);
-               }
-       }
+       uart_console_write(&up->port, s, count, serial_pxa_console_putchar);
 
        /*
         *      Finally, wait for transmitter to become empty
index 7410e093a6b9ffa733a4629c947c4d7324ecdcc7..e4d701239702f6438ee6beab438c9d247aa76877 100644 (file)
@@ -1584,25 +1584,19 @@ s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon)
 }
 
 static void
-s3c24xx_serial_console_write(struct console *co, const char *s,
-                            unsigned int count)
+s3c24xx_serial_console_putchar(struct uart_port *port, int ch)
 {
-       int i;
        unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON);
+       while (!s3c24xx_serial_console_txrdy(port, ufcon))
+               barrier();
+       wr_regb(cons_uart, S3C2410_UTXH, ch);
+}
 
-       for (i = 0; i < count; i++) {
-               while (!s3c24xx_serial_console_txrdy(cons_uart, ufcon))
-                       barrier();
-
-               wr_regb(cons_uart, S3C2410_UTXH, s[i]);
-
-               if (s[i] == '\n') {
-                       while (!s3c24xx_serial_console_txrdy(cons_uart, ufcon))
-                               barrier();
-
-                       wr_regb(cons_uart, S3C2410_UTXH, '\r');
-               }
-       }
+static void
+s3c24xx_serial_console_write(struct console *co, const char *s,
+                            unsigned int count)
+{
+       uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar);
 }
 
 static void __init
index 2c00b862585295474c56a32872a009d7a35c363a..c2d9068b491d8c0dacb549b365196174ef0ec63f 100644 (file)
@@ -689,6 +689,14 @@ void __init sa1100_register_uart(int idx, int port)
 
 
 #ifdef CONFIG_SERIAL_SA1100_CONSOLE
+static void sa1100_console_putchar(struct uart_port *port, int ch)
+{
+       struct sa1100_port *sport = (struct sa1100_port *)port;
+
+       while (!(UART_GET_UTSR1(sport) & UTSR1_TNF))
+               barrier();
+       UART_PUT_CHAR(sport, ch);
+}
 
 /*
  * Interrupts are disabled on entering
@@ -697,7 +705,7 @@ static void
 sa1100_console_write(struct console *co, const char *s, unsigned int count)
 {
        struct sa1100_port *sport = &sa1100_ports[co->index];
-       unsigned int old_utcr3, status, i;
+       unsigned int old_utcr3, status;
 
        /*
         *      First, save UTCR3 and then disable interrupts
@@ -706,21 +714,7 @@ sa1100_console_write(struct console *co, const char *s, unsigned int count)
        UART_PUT_UTCR3(sport, (old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE)) |
                                UTCR3_TXE);
 
-       /*
-        *      Now, do each character
-        */
-       for (i = 0; i < count; i++) {
-               do {
-                       status = UART_GET_UTSR1(sport);
-               } while (!(status & UTSR1_TNF));
-               UART_PUT_CHAR(sport, s[i]);
-               if (s[i] == '\n') {
-                       do {
-                               status = UART_GET_UTSR1(sport);
-                       } while (!(status & UTSR1_TNF));
-                       UART_PUT_CHAR(sport, '\r');
-               }
-       }
+       uart_console_write(&sport->port, s, count, sa1100_console_putchar);
 
        /*
         *      Finally, wait for transmitter to become empty
index cc1faa31d124f0308a565970bc968245cf73f351..fcd7744c4253fa390b28806baf3b093d97d82339 100644 (file)
@@ -1754,6 +1754,27 @@ static int uart_read_proc(char *page, char **start, off_t off,
 #endif
 
 #ifdef CONFIG_SERIAL_CORE_CONSOLE
+/*
+ *     uart_console_write - write a console message to a serial port
+ *     @port: the port to write the message
+ *     @s: array of characters
+ *     @count: number of characters in string to write
+ *     @write: function to write character to port
+ */
+void uart_console_write(struct uart_port *port, const char *s,
+                       unsigned int count,
+                       void (*putchar)(struct uart_port *, int))
+{
+       unsigned int i;
+
+       for (i = 0; i < count; i++, s++) {
+               if (*s == '\n')
+                       putchar(port, '\r');
+               putchar(port, *s);
+       }
+}
+EXPORT_SYMBOL_GPL(uart_console_write);
+
 /*
  *     Check whether an invalid uart number has been specified, and
  *     if so, search for the first available port that does have
index 04186eaae227053401af018fb65c4504853c863c..aa521b8e0d4e3a06a3c0c53ca7929a72d0b96763 100644 (file)
@@ -543,6 +543,12 @@ static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = {
 #else
 # define LH7A40X_CONSOLE &lh7a40x_console
 
+static void lh7a40xuart_console_putchar(struct uart_port *port, int ch)
+{
+       while (UR(port, UART_R_STATUS) & nTxRdy)
+               ;
+       UR(port, UART_R_DATA) = ch;
+}
 
 static void lh7a40xuart_console_write (struct console* co,
                                       const char* s,
@@ -556,16 +562,7 @@ static void lh7a40xuart_console_write (struct console* co,
        UR (port, UART_R_INTEN) = 0;            /* Disable all interrupts */
        BIT_SET (port, UART_R_CON, UARTEN | SIRDIS); /* Enable UART */
 
-       for (; count-- > 0; ++s) {
-               while (UR (port, UART_R_STATUS) & nTxRdy)
-                       ;
-               UR (port, UART_R_DATA) = *s;
-               if (*s == '\n') {
-                       while ((UR (port, UART_R_STATUS) & TxBusy))
-                               ;
-                       UR (port, UART_R_DATA) = '\r';
-               }
-       }
+       uart_console_write(port, s, count, lh7a40xuart_console_putchar);
 
                                /* Wait until all characters are sent */
        while (UR (port, UART_R_STATUS) & TxBusy)
index ee98a867bc6dabd5604763fb7c0c26518bdb57bf..1a259cee1a986854da0aa4de1563829261a41022 100644 (file)
@@ -854,6 +854,14 @@ static inline void wait_for_xmitr(struct uart_txx9_port *up)
        }
 }
 
+static void serial_txx9_console_putchar(struct uart_port *port, int ch)
+{
+       struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+
+       wait_for_xmitr(up);
+       sio_out(up, TXX9_SITFIFO, ch);
+}
+
 /*
  *     Print a string to the serial port trying not to disturb
  *     any possible real use of the port...
@@ -865,7 +873,6 @@ serial_txx9_console_write(struct console *co, const char *s, unsigned int count)
 {
        struct uart_txx9_port *up = &serial_txx9_ports[co->index];
        unsigned int ier, flcr;
-       int i;
 
        /*
         *      First save the UER then disable the interrupts
@@ -879,22 +886,7 @@ serial_txx9_console_write(struct console *co, const char *s, unsigned int count)
        if (!(up->port.flags & UPF_CONS_FLOW) && (flcr & TXX9_SIFLCR_TES))
                sio_out(up, TXX9_SIFLCR, flcr & ~TXX9_SIFLCR_TES);
 
-       /*
-        *      Now, do each character
-        */
-       for (i = 0; i < count; i++, s++) {
-               wait_for_xmitr(up);
-
-               /*
-                *      Send the character out.
-                *      If a LF, also do CR...
-                */
-               sio_out(up, TXX9_SITFIFO, *s);
-               if (*s == 10) {
-                       wait_for_xmitr(up);
-                       sio_out(up, TXX9_SITFIFO, 13);
-               }
-       }
+       uart_console_write(&up->port, s, count, serial_txx9_console_putchar);
 
        /*
         *      Finally, wait for transmitter to become empty
index 85664228a0b6a56123c04c00b5cf57a49f122a03..be95eabd0394069114c9c052c045275b0a82a3d5 100644 (file)
@@ -861,8 +861,9 @@ static int num_channels;
 
 #ifdef CONFIG_SERIAL_SUNSAB_CONSOLE
 
-static __inline__ void sunsab_console_putchar(struct uart_sunsab_port *up, char c)
+static void sunsab_console_putchar(struct uart_port *port, int c)
 {
+       struct uart_sunsab_port *up = (struct uart_sunsab_port *)port;
        unsigned long flags;
 
        spin_lock_irqsave(&up->port.lock, flags);
@@ -876,13 +877,8 @@ static __inline__ void sunsab_console_putchar(struct uart_sunsab_port *up, char
 static void sunsab_console_write(struct console *con, const char *s, unsigned n)
 {
        struct uart_sunsab_port *up = &sunsab_ports[con->index];
-       int i;
 
-       for (i = 0; i < n; i++) {
-               if (*s == '\n')
-                       sunsab_console_putchar(up, '\r');
-               sunsab_console_putchar(up, *s++);
-       }
+       uart_console_write(&up->port, s, n, sunsab_console_putchar);
        sunsab_tec_wait(up);
 }
 
index 4e453fa966ae23956a370ffc24dc19a2f241a0fe..9ca1d8b9364bc9ac865d193513eb65dde4dba4ec 100644 (file)
@@ -1376,6 +1376,14 @@ static __inline__ void wait_for_xmitr(struct uart_sunsu_port *up)
        }
 }
 
+static void sunsu_console_putchar(struct uart_port *port, int ch)
+{
+       struct uart_sunsu_port *up = (struct uart_sunsu_port *)port;
+
+       wait_for_xmitr(up);
+       serial_out(up, UART_TX, ch);
+}
+
 /*
  *     Print a string to the serial port trying not to disturb
  *     any possible real use of the port...
@@ -1385,7 +1393,6 @@ static void sunsu_console_write(struct console *co, const char *s,
 {
        struct uart_sunsu_port *up = &sunsu_ports[co->index];
        unsigned int ier;
-       int i;
 
        /*
         *      First save the UER then disable the interrupts
@@ -1393,22 +1400,7 @@ static void sunsu_console_write(struct console *co, const char *s,
        ier = serial_in(up, UART_IER);
        serial_out(up, UART_IER, 0);
 
-       /*
-        *      Now, do each character
-        */
-       for (i = 0; i < count; i++, s++) {
-               wait_for_xmitr(up);
-
-               /*
-                *      Send the character out.
-                *      If a LF, also do CR...
-                */
-               serial_out(up, UART_TX, *s);
-               if (*s == 10) {
-                       wait_for_xmitr(up);
-                       serial_out(up, UART_TX, 13);
-               }
-       }
+       uart_console_write(&up->port, s, count, sunsu_console_putchar);
 
        /*
         *      Finally, wait for transmitter to become empty
index 5cc4d4c2935ce7e3f2b685d4ed44e69025b12b1e..b0c46b9a59304140204ae2050ead5e27d5929a2f 100644 (file)
@@ -1252,8 +1252,9 @@ static struct zilog_layout __iomem * __init get_zs(int chip, int node)
 
 #define ZS_PUT_CHAR_MAX_DELAY  2000    /* 10 ms */
 
-static void sunzilog_put_char(struct zilog_channel __iomem *channel, unsigned char ch)
+static void sunzilog_putchar(struct uart_port *port, int ch)
 {
+       struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port);
        int loops = ZS_PUT_CHAR_MAX_DELAY;
 
        /* This is a timed polling loop so do not switch the explicit
@@ -1284,7 +1285,7 @@ static int sunzilog_serio_write(struct serio *serio, unsigned char ch)
 
        spin_lock_irqsave(&sunzilog_serio_lock, flags);
 
-       sunzilog_put_char(ZILOG_CHANNEL_FROM_PORT(&up->port), ch);
+       sunzilog_putchar(&up->port, ch);
 
        spin_unlock_irqrestore(&sunzilog_serio_lock, flags);
 
@@ -1325,16 +1326,10 @@ static void
 sunzilog_console_write(struct console *con, const char *s, unsigned int count)
 {
        struct uart_sunzilog_port *up = &sunzilog_port_table[con->index];
-       struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
        unsigned long flags;
-       int i;
 
        spin_lock_irqsave(&up->port.lock, flags);
-       for (i = 0; i < count; i++, s++) {
-               sunzilog_put_char(channel, *s);
-               if (*s == 10)
-                       sunzilog_put_char(channel, 13);
-       }
+       uart_console_write(&up->port, s, count, sunzilog_putchar);
        udelay(2);
        spin_unlock_irqrestore(&up->port.lock, flags);
 }
index d61494d185cd3a04aef5c034a9cd6938d22e0dc1..3f88b8e819376ed2001e96bbbbde289aa9845294 100644 (file)
@@ -821,25 +821,23 @@ static void wait_for_xmitr(struct uart_port *port)
        }
 }
 
+static void siu_console_putchar(struct uart_port *port, int ch)
+{
+       wait_for_xmitr(port);
+       siu_write(port, UART_TX, ch);
+}
+
 static void siu_console_write(struct console *con, const char *s, unsigned count)
 {
        struct uart_port *port;
        uint8_t ier;
-       unsigned i;
 
        port = &siu_uart_ports[con->index];
 
        ier = siu_read(port, UART_IER);
        siu_write(port, UART_IER, 0);
 
-       for (i = 0; i < count && *s != '\0'; i++, s++) {
-               wait_for_xmitr(port);
-               siu_write(port, UART_TX, *s);
-               if (*s == '\n') {
-                       wait_for_xmitr(port);
-                       siu_write(port, UART_TX, '\r');
-               }
-       }
+       uart_console_write(port, s, count, siu_console_putchar);
 
        wait_for_xmitr(port);
        siu_write(port, UART_IER, ier);
index 4041122dabfcf66cd2eca416a227569f474b5c84..f7434e5086f5c4c0d0fa2def26b8e8ff24e751ff 100644 (file)
@@ -366,6 +366,9 @@ void uart_parse_options(char *options, int *baud, int *parity, int *bits,
 int uart_set_options(struct uart_port *port, struct console *co, int baud,
                     int parity, int bits, int flow);
 struct tty_driver *uart_console_device(struct console *co, int *index);
+void uart_console_write(struct uart_port *port, const char *s,
+                       unsigned int count,
+                       void (*putchar)(struct uart_port *, int));
 
 /*
  * Port/driver registration/removal