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] / arch / ia64 / hp / sim / simserial.c
index 3812778..0e5c6ae 100644 (file)
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
+#include <linux/capability.h>
 #include <linux/console.h>
 #include <linux/module.h>
 #include <linux/serial.h>
 #include <linux/serialP.h>
+#include <linux/sysrq.h>
 
 #include <asm/irq.h>
 #include <asm/hw_irq.h>
 #define KEYBOARD_INTR  3       /* must match with simulator! */
 
 #define NR_PORTS       1       /* only one port for now */
-#define SERIAL_INLINE  1
-
-#ifdef SERIAL_INLINE
-#define _INLINE_ inline
-#endif
-
-#ifndef MIN
-#define MIN(a,b)       ((a) < (b) ? (a) : (b))
-#endif
 
 #define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT)
 
@@ -110,7 +103,6 @@ static struct async_struct *IRQ_ports[NR_IRQS];
 static struct console *console;
 
 static unsigned char *tmp_buf;
-static DECLARE_MUTEX(tmp_buf_sem);
 
 extern struct console *console_drivers; /* from kernel/printk.c */
 
@@ -133,7 +125,7 @@ static void rs_stop(struct tty_struct *tty)
 
 static void rs_start(struct tty_struct *tty)
 {
-#if SIMSERIAL_DEBUG
+#ifdef SIMSERIAL_DEBUG
        printk("rs_start: tty->stopped=%d tty->hw_stopped=%d tty->flow_stopped=%d\n",
                tty->stopped, tty->hw_stopped, tty->flow_stopped);
 #endif
@@ -153,26 +145,25 @@ static  void receive_chars(struct tty_struct *tty, struct pt_regs *regs)
                                seen_esc = 2;
                                continue;
                        } else if ( seen_esc == 2 ) {
-                               if ( ch == 'P' ) show_state();          /* F1 key */
-#ifdef CONFIG_KDB
-                               if ( ch == 'S' )
-                                       kdb(KDB_REASON_KEYBOARD, 0, (kdb_eframe_t) regs);
+                               if ( ch == 'P' ) /* F1 */
+                                       show_state();
+#ifdef CONFIG_MAGIC_SYSRQ
+                               if ( ch == 'S' ) { /* F4 */
+                                       do
+                                               ch = ia64_ssc(0, 0, 0, 0,
+                                                             SSC_GETCHAR);
+                                       while (!ch);
+                                       handle_sysrq(ch, regs, NULL);
+                               }
 #endif
-
                                seen_esc = 0;
                                continue;
                        }
                }
                seen_esc = 0;
-               if (tty->flip.count >= TTY_FLIPBUF_SIZE) break;
-
-               *tty->flip.char_buf_ptr = ch;
 
-               *tty->flip.flag_buf_ptr = 0;
-
-               tty->flip.flag_buf_ptr++;
-               tty->flip.char_buf_ptr++;
-               tty->flip.count++;
+               if (tty_insert_flip_char(tty, ch, TTY_NORMAL) == 0)
+                       break;
        }
        tty_flip_buffer_push(tty);
 }
@@ -241,7 +232,7 @@ static void rs_put_char(struct tty_struct *tty, unsigned char ch)
        local_irq_restore(flags);
 }
 
-static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done)
+static void transmit_chars(struct async_struct *info, int *intr_done)
 {
        int count;
        unsigned long flags;
@@ -275,7 +266,7 @@ static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done)
         * Then from the beginning of the buffer until necessary
         */
 
-       count = MIN(CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE),
+       count = min(CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE),
                    SERIAL_XMIT_SIZE - info->xmit.tail);
        console->write(console, info->xmit.buf+info->xmit.tail, count);
 
@@ -305,7 +296,7 @@ static void rs_flush_chars(struct tty_struct *tty)
 }
 
 
-static int rs_write(struct tty_struct * tty, int from_user,
+static int rs_write(struct tty_struct * tty,
                    const unsigned char *buf, int count)
 {
        int     c, ret = 0;
@@ -314,58 +305,22 @@ static int rs_write(struct tty_struct * tty, int from_user,
 
        if (!tty || !info->xmit.buf || !tmp_buf) return 0;
 
-       if (from_user) {
-               down(&tmp_buf_sem);
-               while (1) {
-                       int c1;
-                       c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
-                       if (count < c)
-                               c = count;
-                       if (c <= 0)
-                               break;
-
-                       c -= copy_from_user(tmp_buf, buf, c);
-                       if (!c) {
-                               if (!ret)
-                                       ret = -EFAULT;
-                               break;
-                       }
-
-                       local_irq_save(flags);
-                       {
-                               c1 = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail,
-                                                      SERIAL_XMIT_SIZE);
-                               if (c1 < c)
-                                       c = c1;
-                               memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c);
-                               info->xmit.head = ((info->xmit.head + c) &
-                                                  (SERIAL_XMIT_SIZE-1));
-                       }
-                       local_irq_restore(flags);
-
-                       buf += c;
-                       count -= c;
-                       ret += c;
-               }
-               up(&tmp_buf_sem);
-       } else {
-               local_irq_save(flags);
-               while (1) {
-                       c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
-                       if (count < c)
-                               c = count;
-                       if (c <= 0) {
-                               break;
-                       }
-                       memcpy(info->xmit.buf + info->xmit.head, buf, c);
-                       info->xmit.head = ((info->xmit.head + c) &
-                                          (SERIAL_XMIT_SIZE-1));
-                       buf += c;
-                       count -= c;
-                       ret += c;
+       local_irq_save(flags);
+       while (1) {
+               c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
+               if (count < c)
+                       c = count;
+               if (c <= 0) {
+                       break;
                }
-               local_irq_restore(flags);
+               memcpy(info->xmit.buf + info->xmit.head, buf, c);
+               info->xmit.head = ((info->xmit.head + c) &
+                                  (SERIAL_XMIT_SIZE-1));
+               buf += c;
+               count -= c;
+               ret += c;
        }
+       local_irq_restore(flags);
        /*
         * Hey, we transmit directly from here in our case
         */
@@ -676,10 +631,8 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
        info->event = 0;
        info->tty = 0;
        if (info->blocked_open) {
-               if (info->close_delay) {
-                       current->state = TASK_INTERRUPTIBLE;
-                       schedule_timeout(info->close_delay);
-               }
+               if (info->close_delay)
+                       schedule_timeout_interruptible(info->close_delay);
                wake_up_interruptible(&info->open_wait);
        }
        info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
@@ -1016,7 +969,7 @@ static struct tty_operations hp_ops = {
 static int __init
 simrs_init (void)
 {
-       int                     i;
+       int                     i, rc;
        struct serial_state     *state;
 
        if (!ia64_platform_is("hpsim"))
@@ -1051,11 +1004,14 @@ simrs_init (void)
                if (state->type == PORT_UNKNOWN) continue;
 
                if (!state->irq) {
-                       state->irq = assign_irq_vector(AUTO_ASSIGN);
+                       if ((rc = assign_irq_vector(AUTO_ASSIGN)) < 0)
+                               panic("%s: out of interrupt vectors!\n",
+                                     __FUNCTION__);
+                       state->irq = rc;
                        ia64_ssc_connect_irq(KEYBOARD_INTR, state->irq);
                }
 
-               printk(KERN_INFO "ttyS%02d at 0x%04lx (irq = %d) is a %s\n",
+               printk(KERN_INFO "ttyS%d at 0x%04lx (irq = %d) is a %s\n",
                       state->line,
                       state->port, state->irq,
                       uart_config[state->type].name);