Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / serial / sunsu.c
index ddc97c9..2b4f965 100644 (file)
@@ -102,18 +102,16 @@ struct uart_sunsu_port {
 #endif
 };
 
-#define _INLINE_
-
-static _INLINE_ unsigned int serial_in(struct uart_sunsu_port *up, int offset)
+static unsigned int serial_in(struct uart_sunsu_port *up, int offset)
 {
        offset <<= up->port.regshift;
 
        switch (up->port.iotype) {
-       case SERIAL_IO_HUB6:
+       case UPIO_HUB6:
                outb(up->port.hub6 - 1 + offset, up->port.iobase);
                return inb(up->port.iobase + 1);
 
-       case SERIAL_IO_MEM:
+       case UPIO_MEM:
                return readb(up->port.membase + offset);
 
        default:
@@ -121,8 +119,7 @@ static _INLINE_ unsigned int serial_in(struct uart_sunsu_port *up, int offset)
        }
 }
 
-static _INLINE_ void
-serial_out(struct uart_sunsu_port *up, int offset, int value)
+static void serial_out(struct uart_sunsu_port *up, int offset, int value)
 {
 #ifndef CONFIG_SPARC64
        /*
@@ -139,12 +136,12 @@ serial_out(struct uart_sunsu_port *up, int offset, int value)
        offset <<= up->port.regshift;
 
        switch (up->port.iotype) {
-       case SERIAL_IO_HUB6:
+       case UPIO_HUB6:
                outb(up->port.hub6 - 1 + offset, up->port.iobase);
                outb(value, up->port.iobase + 1);
                break;
 
-       case SERIAL_IO_MEM:
+       case UPIO_MEM:
                writeb(value, up->port.membase + offset);
                break;
 
@@ -255,21 +252,30 @@ static void disable_rsa(struct uart_sunsu_port *up)
 }
 #endif /* CONFIG_SERIAL_8250_RSA */
 
-static void sunsu_stop_tx(struct uart_port *port, unsigned int tty_stop)
+static inline void __stop_tx(struct uart_sunsu_port *p)
+{
+       if (p->ier & UART_IER_THRI) {
+               p->ier &= ~UART_IER_THRI;
+               serial_out(p, UART_IER, p->ier);
+       }
+}
+
+static void sunsu_stop_tx(struct uart_port *port)
 {
        struct uart_sunsu_port *up = (struct uart_sunsu_port *) port;
 
-       if (up->ier & UART_IER_THRI) {
-               up->ier &= ~UART_IER_THRI;
-               serial_out(up, UART_IER, up->ier);
-       }
-       if (up->port.type == PORT_16C950 && tty_stop) {
+       __stop_tx(up);
+
+       /*
+        * We really want to stop the transmitter from sending.
+        */
+       if (up->port.type == PORT_16C950) {
                up->acr |= UART_ACR_TXDIS;
                serial_icr_write(up, UART_ACR, up->acr);
        }
 }
 
-static void sunsu_start_tx(struct uart_port *port, unsigned int tty_start)
+static void sunsu_start_tx(struct uart_port *port)
 {
        struct uart_sunsu_port *up = (struct uart_sunsu_port *) port;
 
@@ -277,10 +283,11 @@ static void sunsu_start_tx(struct uart_port *port, unsigned int tty_start)
                up->ier |= UART_IER_THRI;
                serial_out(up, UART_IER, up->ier);
        }
+
        /*
-        * We only do this from uart_start
+        * Re-enable the transmitter if we disabled it.
         */
-       if (tty_start && up->port.type == PORT_16C950) {
+       if (up->port.type == PORT_16C950 && up->acr & UART_ACR_TXDIS) {
                up->acr &= ~UART_ACR_TXDIS;
                serial_icr_write(up, UART_ACR, up->acr);
        }
@@ -289,13 +296,10 @@ static void sunsu_start_tx(struct uart_port *port, unsigned int tty_start)
 static void sunsu_stop_rx(struct uart_port *port)
 {
        struct uart_sunsu_port *up = (struct uart_sunsu_port *) port;
-       unsigned long flags;
 
-       spin_lock_irqsave(&up->port.lock, flags);
        up->ier &= ~UART_IER_RLSI;
        up->port.read_status_mask &= ~UART_LSR_DR;
        serial_out(up, UART_IER, up->ier);
-       spin_unlock_irqrestore(&up->port.lock, flags);
 }
 
 static void sunsu_enable_ms(struct uart_port *port)
@@ -309,23 +313,17 @@ static void sunsu_enable_ms(struct uart_port *port)
        spin_unlock_irqrestore(&up->port.lock, flags);
 }
 
-static _INLINE_ struct tty_struct *
+static struct tty_struct *
 receive_chars(struct uart_sunsu_port *up, unsigned char *status, struct pt_regs *regs)
 {
        struct tty_struct *tty = up->port.info->tty;
-       unsigned char ch;
+       unsigned char ch, flag;
        int max_count = 256;
        int saw_console_brk = 0;
 
        do {
-               if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
-                       tty->flip.work.func((void *)tty);
-                       if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-                               return tty; // if TTY_DONT_FLIP is set
-               }
                ch = serial_inp(up, UART_RX);
-               *tty->flip.char_buf_ptr = ch;
-               *tty->flip.flag_buf_ptr = TTY_NORMAL;
+               flag = TTY_NORMAL;
                up->port.icount.rx++;
 
                if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
@@ -367,31 +365,23 @@ receive_chars(struct uart_sunsu_port *up, unsigned char *status, struct pt_regs
                        }
 
                        if (*status & UART_LSR_BI) {
-                               *tty->flip.flag_buf_ptr = TTY_BREAK;
+                               flag = TTY_BREAK;
                        } else if (*status & UART_LSR_PE)
-                               *tty->flip.flag_buf_ptr = TTY_PARITY;
+                               flag = TTY_PARITY;
                        else if (*status & UART_LSR_FE)
-                               *tty->flip.flag_buf_ptr = TTY_FRAME;
+                               flag = TTY_FRAME;
                }
                if (uart_handle_sysrq_char(&up->port, ch, regs))
                        goto ignore_char;
-               if ((*status & up->port.ignore_status_mask) == 0) {
-                       tty->flip.flag_buf_ptr++;
-                       tty->flip.char_buf_ptr++;
-                       tty->flip.count++;
-               }
-               if ((*status & UART_LSR_OE) &&
-                   tty->flip.count < TTY_FLIPBUF_SIZE) {
+               if ((*status & up->port.ignore_status_mask) == 0)
+                       tty_insert_flip_char(tty, ch, flag);
+               if (*status & UART_LSR_OE)
                        /*
                         * Overrun is special, since it's reported
                         * immediately, and doesn't affect the current
                         * character.
                         */
-                       *tty->flip.flag_buf_ptr = TTY_OVERRUN;
-                       tty->flip.flag_buf_ptr++;
-                       tty->flip.char_buf_ptr++;
-                       tty->flip.count++;
-               }
+                        tty_insert_flip_char(tty, 0, TTY_OVERRUN);
        ignore_char:
                *status = serial_inp(up, UART_LSR);
        } while ((*status & UART_LSR_DR) && (max_count-- > 0));
@@ -402,7 +392,7 @@ receive_chars(struct uart_sunsu_port *up, unsigned char *status, struct pt_regs
        return tty;
 }
 
-static _INLINE_ void transmit_chars(struct uart_sunsu_port *up)
+static void transmit_chars(struct uart_sunsu_port *up)
 {
        struct circ_buf *xmit = &up->port.info->xmit;
        int count;
@@ -413,8 +403,12 @@ static _INLINE_ void transmit_chars(struct uart_sunsu_port *up)
                up->port.x_char = 0;
                return;
        }
-       if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
-               sunsu_stop_tx(&up->port, 0);
+       if (uart_tx_stopped(&up->port)) {
+               sunsu_stop_tx(&up->port);
+               return;
+       }
+       if (uart_circ_empty(xmit)) {
+               __stop_tx(up);
                return;
        }
 
@@ -431,10 +425,10 @@ static _INLINE_ void transmit_chars(struct uart_sunsu_port *up)
                uart_write_wakeup(&up->port);
 
        if (uart_circ_empty(xmit))
-               sunsu_stop_tx(&up->port, 0);
+               __stop_tx(up);
 }
 
-static _INLINE_ void check_modem_status(struct uart_sunsu_port *up)
+static void check_modem_status(struct uart_sunsu_port *up)
 {
        int status;
 
@@ -504,11 +498,7 @@ static void sunsu_change_mouse_baud(struct uart_sunsu_port *up)
 
        quot = up->port.uartclk / (16 * new_baud);
 
-       spin_unlock(&up->port.lock);
-
        sunsu_change_speed(&up->port, up->cflag, 0, quot);
-
-       spin_lock(&up->port.lock);
 }
 
 static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *regs, int is_break)
@@ -572,13 +562,10 @@ static unsigned int sunsu_tx_empty(struct uart_port *port)
 static unsigned int sunsu_get_mctrl(struct uart_port *port)
 {
        struct uart_sunsu_port *up = (struct uart_sunsu_port *) port;
-       unsigned long flags;
        unsigned char status;
        unsigned int ret;
 
-       spin_lock_irqsave(&up->port.lock, flags);
        status = serial_in(up, UART_MSR);
-       spin_unlock_irqrestore(&up->port.lock, flags);
 
        ret = 0;
        if (status & UART_MSR_DCD)
@@ -654,7 +641,7 @@ static int sunsu_startup(struct uart_port *port)
 
        /*
         * Clear the FIFO buffers and disable them.
-        * (they will be reeanbled in set_termios())
+        * (they will be reenabled in set_termios())
         */
        if (uart_config[up->port.type].flags & UART_CLEAR_FIFO) {
                serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
@@ -676,7 +663,7 @@ static int sunsu_startup(struct uart_port *port)
         * if it is, then bail out, because there's likely no UART
         * here.
         */
-       if (!(up->port.flags & ASYNC_BUGGY_UART) &&
+       if (!(up->port.flags & UPF_BUGGY_UART) &&
            (serial_inp(up, UART_LSR) == 0xff)) {
                printk("ttyS%d: LSR safety check engaged!\n", up->port.line);
                return -ENODEV;
@@ -714,7 +701,7 @@ static int sunsu_startup(struct uart_port *port)
        up->ier = UART_IER_RLSI | UART_IER_RDI;
        serial_outp(up, UART_IER, up->ier);
 
-       if (up->port.flags & ASYNC_FOURPORT) {
+       if (up->port.flags & UPF_FOURPORT) {
                unsigned int icp;
                /*
                 * Enable interrupts on the AST Fourport board
@@ -747,7 +734,7 @@ static void sunsu_shutdown(struct uart_port *port)
        serial_outp(up, UART_IER, 0);
 
        spin_lock_irqsave(&up->port.lock, flags);
-       if (up->port.flags & ASYNC_FOURPORT) {
+       if (up->port.flags & UPF_FOURPORT) {
                /* reset interrupts on the AST Fourport board */
                inb((up->port.iobase & 0xfe0) | 0x1f);
                up->port.mctrl |= TIOCM_OUT1;
@@ -1059,7 +1046,7 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up)
                return;
 
        up->type_probed = PORT_UNKNOWN;
-       up->port.iotype = SERIAL_IO_MEM;
+       up->port.iotype = UPIO_MEM;
 
        /*
         * First we look for Ebus-bases su's
@@ -1139,7 +1126,7 @@ ebus_done:
 
        spin_lock_irqsave(&up->port.lock, flags);
 
-       if (!(up->port.flags & ASYNC_BUGGY_UART)) {
+       if (!(up->port.flags & UPF_BUGGY_UART)) {
                /*
                 * Do a simple existence test first; if we fail this, there's
                 * no point trying anything else.
@@ -1177,7 +1164,7 @@ ebus_done:
         * manufacturer would be stupid enough to design a board
         * that conflicts with COM 1-4 --- we hope!
         */
-       if (!(up->port.flags & ASYNC_SKIP_TEST)) {
+       if (!(up->port.flags & UPF_SKIP_TEST)) {
                serial_outp(up, UART_MCR, UART_MCR_LOOP | 0x0A);
                status1 = serial_inp(up, UART_MSR) & 0xF0;
                serial_outp(up, UART_MCR, save_mcr);
@@ -1290,6 +1277,7 @@ static int __init sunsu_kbd_ms_init(struct uart_sunsu_port *up, int channel)
        struct serio *serio;
 #endif
 
+       spin_lock_init(&up->port.lock);
        up->port.line = channel;
        up->port.type = PORT_UNKNOWN;
        up->port.uartclk = (SU_BASE_BAUD * 16);
@@ -1378,7 +1366,7 @@ static __inline__ void wait_for_xmitr(struct uart_sunsu_port *up)
        } while ((status & BOTH_EMPTY) != BOTH_EMPTY);
 
        /* Wait up to 1s for flow control if necessary */
-       if (up->port.flags & ASYNC_CONS_FLOW) {
+       if (up->port.flags & UPF_CONS_FLOW) {
                tmout = 1000000;
                while (--tmout &&
                       ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
@@ -1386,6 +1374,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...
@@ -1395,7 +1391,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
@@ -1403,22 +1398,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
@@ -1434,7 +1414,7 @@ static void sunsu_console_write(struct console *co, const char *s,
  *     - initialize the serial port
  *     Return non-zero if we didn't find a serial port.
  */
-static int __init sunsu_console_setup(struct console *co, char *options)
+static int sunsu_console_setup(struct console *co, char *options)
 {
        struct uart_port *port;
        int baud = 9600;
@@ -1474,18 +1454,17 @@ static struct console sunsu_cons = {
        .index  =       -1,
        .data   =       &sunsu_reg,
 };
-#define SUNSU_CONSOLE  (&sunsu_cons)
 
 /*
  *     Register console.
  */
 
-static int __init sunsu_serial_console_init(void)
+static inline struct console *SUNSU_CONSOLE(void)
 {
        int i;
 
        if (con_is_present())
-               return 0;
+               return NULL;
 
        for (i = 0; i < UART_NR; i++) {
                int this_minor = sunsu_reg.minor + i;
@@ -1494,16 +1473,16 @@ static int __init sunsu_serial_console_init(void)
                        break;
        }
        if (i == UART_NR)
-               return 0;
+               return NULL;
        if (sunsu_ports[i].port_node == 0)
-               return 0;
+               return NULL;
 
        sunsu_cons.index = i;
-       register_console(&sunsu_cons);
-       return 0;
+
+       return &sunsu_cons;
 }
 #else
-#define SUNSU_CONSOLE                  (NULL)
+#define SUNSU_CONSOLE()                        (NULL)
 #define sunsu_serial_console_init()    do { } while (0)
 #endif
 
@@ -1520,7 +1499,8 @@ static int __init sunsu_serial_init(void)
                    up->su_type == SU_PORT_KBD)
                        continue;
 
-               up->port.flags |= ASYNC_BOOT_AUTOCONF;
+               spin_lock_init(&up->port.lock);
+               up->port.flags |= UPF_BOOT_AUTOCONF;
                up->port.type = PORT_UNKNOWN;
                up->port.uartclk = (SU_BASE_BAUD * 16);
 
@@ -1533,16 +1513,19 @@ static int __init sunsu_serial_init(void)
        }
 
        sunsu_reg.minor = sunserial_current_minor;
-       sunserial_current_minor += instance;
 
        sunsu_reg.nr = instance;
-       sunsu_reg.cons = SUNSU_CONSOLE;
 
        ret = uart_register_driver(&sunsu_reg);
        if (ret < 0)
                return ret;
 
-       sunsu_serial_console_init();
+       sunsu_reg.tty_driver->name_base = sunsu_reg.minor - 64;
+
+       sunserial_current_minor += instance;
+
+       sunsu_reg.cons = SUNSU_CONSOLE();
+
        for (i = 0; i < UART_NR; i++) {
                struct uart_sunsu_port *up = &sunsu_ports[i];
 
@@ -1747,3 +1730,4 @@ static void __exit sunsu_exit(void)
 
 module_init(sunsu_probe);
 module_exit(sunsu_exit);
+MODULE_LICENSE("GPL");