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 / char / amiserial.c
index 1dc4259..6602b31 100644 (file)
@@ -46,8 +46,6 @@
 
 /* Sanity checks */
 
-#define SERIAL_INLINE
-  
 #if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT)
 #define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \
  tty->name, (info->flags), serial_driver->refcount,info->count,tty->count,s)
@@ -95,10 +93,7 @@ static char *serial_version = "4.30";
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
 
-#ifdef SERIAL_INLINE
-#define _INLINE_ inline
-#endif
-
+#define custom amiga_custom
 static char *serial_name = "Amiga-builtin serial driver";
 
 static struct tty_driver *serial_driver;
@@ -116,7 +111,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
 
 static struct serial_state rs_table[1];
 
-#define NR_PORTS       (sizeof(rs_table)/sizeof(struct serial_state))
+#define NR_PORTS ARRAY_SIZE(rs_table)
 
 /*
  * tmp_buf is used as a temporary buffer by serial_write.  We need to
@@ -128,7 +123,6 @@ static struct serial_state rs_table[1];
  * memory if large numbers of serial ports are open.
  */
 static unsigned char *tmp_buf;
-static DECLARE_MUTEX(tmp_buf_sem);
 
 #include <asm/uaccess.h>
 
@@ -253,20 +247,21 @@ static void rs_start(struct tty_struct *tty)
  * This routine is used by the interrupt handler to schedule
  * processing in the software interrupt portion of the driver.
  */
-static _INLINE_ void rs_sched_event(struct async_struct *info,
-                                 int event)
+static void rs_sched_event(struct async_struct *info,
+                          int event)
 {
        info->event |= 1 << event;
        tasklet_schedule(&info->tlet);
 }
 
-static _INLINE_ void receive_chars(struct async_struct *info)
+static void receive_chars(struct async_struct *info)
 {
         int status;
        int serdatr;
        struct tty_struct *tty = info->tty;
-       unsigned char ch;
+       unsigned char ch, flag;
        struct  async_icount *icount;
+       int oe = 0;
 
        icount = &info->state->icount;
 
@@ -282,15 +277,12 @@ static _INLINE_ void receive_chars(struct async_struct *info)
            status |= UART_LSR_OE;
 
        ch = serdatr & 0xff;
-       if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-         goto ignore_char;
-       *tty->flip.char_buf_ptr = ch;
        icount->rx++;
 
 #ifdef SERIAL_DEBUG_INTR
        printk("DR%02x:%02x...", ch, status);
 #endif
-       *tty->flip.flag_buf_ptr = 0;
+       flag = TTY_NORMAL;
 
        /*
         * We don't handle parity or frame errors - but I have left
@@ -319,7 +311,7 @@ static _INLINE_ void receive_chars(struct async_struct *info)
           * should be ignored.
           */
          if (status & info->ignore_status_mask)
-           goto ignore_char;
+           goto out;
 
          status &= info->read_status_mask;
 
@@ -327,36 +319,31 @@ static _INLINE_ void receive_chars(struct async_struct *info)
 #ifdef SERIAL_DEBUG_INTR
            printk("handling break....");
 #endif
-           *tty->flip.flag_buf_ptr = TTY_BREAK;
+           flag = TTY_BREAK;
            if (info->flags & ASYNC_SAK)
              do_SAK(tty);
          } 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 (status & UART_LSR_OE) {
            /*
             * Overrun is special, since it's
             * reported immediately, and doesn't
             * affect the current character
             */
-           if (tty->flip.count < TTY_FLIPBUF_SIZE) {
-             tty->flip.count++;
-             tty->flip.flag_buf_ptr++;
-             tty->flip.char_buf_ptr++;
-             *tty->flip.flag_buf_ptr = TTY_OVERRUN;
-           }
+            oe = 1;
          }
        }
-       tty->flip.flag_buf_ptr++;
-       tty->flip.char_buf_ptr++;
-       tty->flip.count++;
- ignore_char:
-
+       tty_insert_flip_char(tty, ch, flag);
+       if (oe == 1)
+               tty_insert_flip_char(tty, 0, TTY_OVERRUN);
        tty_flip_buffer_push(tty);
+out:
+       return;
 }
 
-static _INLINE_ void transmit_chars(struct async_struct *info)
+static void transmit_chars(struct async_struct *info)
 {
        custom.intreq = IF_TBE;
        mb();
@@ -396,7 +383,7 @@ static _INLINE_ void transmit_chars(struct async_struct *info)
        }
 }
 
-static _INLINE_ void check_modem_status(struct async_struct *info)
+static void check_modem_status(struct async_struct *info)
 {
        unsigned char status = ciab.pra & (SER_DCD | SER_CTS | SER_DSR);
        unsigned char dstatus;
@@ -861,13 +848,18 @@ static void change_speed(struct async_struct *info,
 
 static void rs_put_char(struct tty_struct *tty, unsigned char ch)
 {
-       struct async_struct *info = (struct async_struct *)tty->driver_data;
+       struct async_struct *info;
        unsigned long flags;
 
+       if (!tty)
+               return;
+
+       info = tty->driver_data;
+
        if (serial_paranoia_check(info, tty->name, "rs_put_char"))
                return;
 
-       if (!tty || !info->xmit.buf)
+       if (!info->xmit.buf)
                return;
 
        local_irq_save(flags);
@@ -910,13 +902,18 @@ static void rs_flush_chars(struct tty_struct *tty)
 static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count)
 {
        int     c, ret = 0;
-       struct async_struct *info = (struct async_struct *)tty->driver_data;
+       struct async_struct *info;
        unsigned long flags;
 
+       if (!tty)
+               return 0;
+
+       info = tty->driver_data;
+
        if (serial_paranoia_check(info, tty->name, "rs_write"))
                return 0;
 
-       if (!tty || !info->xmit.buf || !tmp_buf)
+       if (!info->xmit.buf || !tmp_buf)
                return 0;
 
        local_save_flags(flags);
@@ -1085,7 +1082,7 @@ static void rs_unthrottle(struct tty_struct * tty)
  */
 
 static int get_serial_info(struct async_struct * info,
-                          struct serial_struct * retinfo)
+                          struct serial_struct __user * retinfo)
 {
        struct serial_struct tmp;
        struct serial_state *state = info->state;
@@ -1109,7 +1106,7 @@ static int get_serial_info(struct async_struct * info,
 }
 
 static int set_serial_info(struct async_struct * info,
-                          struct serial_struct * new_info)
+                          struct serial_struct __user * new_info)
 {
        struct serial_struct new_serial;
        struct serial_state old_state, *state;
@@ -1190,7 +1187,7 @@ check_and_exit:
  *         transmit holding register is empty.  This functionality
  *         allows an RS485 driver to be written in user space. 
  */
-static int get_lsr_info(struct async_struct * info, unsigned int *value)
+static int get_lsr_info(struct async_struct * info, unsigned int __user *value)
 {
        unsigned char status;
        unsigned int result;
@@ -1281,6 +1278,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
        struct async_struct * info = (struct async_struct *)tty->driver_data;
        struct async_icount cprev, cnow;        /* kernel counter temps */
        struct serial_icounter_struct icount;
+       void __user *argp = (void __user *)arg;
        unsigned long flags;
 
        if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
@@ -1295,19 +1293,17 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
 
        switch (cmd) {
                case TIOCGSERIAL:
-                       return get_serial_info(info,
-                                              (struct serial_struct *) arg);
+                       return get_serial_info(info, argp);
                case TIOCSSERIAL:
-                       return set_serial_info(info,
-                                              (struct serial_struct *) arg);
+                       return set_serial_info(info, argp);
                case TIOCSERCONFIG:
                        return 0;
 
                case TIOCSERGETLSR: /* Get line status register */
-                       return get_lsr_info(info, (unsigned int *) arg);
+                       return get_lsr_info(info, argp);
 
                case TIOCSERGSTRUCT:
-                       if (copy_to_user((struct async_struct *) arg,
+                       if (copy_to_user(argp,
                                         info, sizeof(struct async_struct)))
                                return -EFAULT;
                        return 0;
@@ -1366,7 +1362,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
                        icount.brk = cnow.brk;
                        icount.buf_overrun = cnow.buf_overrun;
 
-                       if (copy_to_user((void *)arg, &icount, sizeof(icount)))
+                       if (copy_to_user(argp, &icount, sizeof(icount)))
                                return -EFAULT;
                        return 0;
                case TIOCSERGWILD:
@@ -1957,16 +1953,12 @@ done:
  * number, and identifies which options were configured into this
  * driver.
  */
-static _INLINE_ void show_serial_version(void)
+static void show_serial_version(void)
 {
        printk(KERN_INFO "%s version %s\n", serial_name, serial_version);
 }
 
 
-int register_serial(struct serial_struct *req);
-void unregister_serial(int line);
-
-
 static struct tty_operations serial_ops = {
        .open = rs_open,
        .close = rs_close,
@@ -2047,10 +2039,6 @@ static int __init rs_init(void)
        state->icount.rx = state->icount.tx = 0;
        state->icount.frame = state->icount.parity = 0;
        state->icount.overrun = state->icount.brk = 0;
-       /*
-       if(state->port && check_region(state->port,REGION_LENGTH(state)))
-         continue;
-       */
 
        printk(KERN_INFO "ttyS%d is the amiga builtin serial port\n",
                       state->line);