vserver 1.9.5.x5
[linux-2.6.git] / drivers / tc / zs.c
index c5befc9..0f0d879 100644 (file)
@@ -6,7 +6,7 @@
  *
  * DECstation changes
  * Copyright (C) 1998-2000 Harald Koerfgen
- * Copyright (C) 2000,2001 Maciej W. Rozycki <macro@ds2.pg.gda.pl>
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004  Maciej W. Rozycki
  *
  * For the rest of the code the original Copyright applies:
  * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au)
@@ -55,7 +55,7 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
-#ifdef CONFIG_SERIAL_CONSOLE
+#ifdef CONFIG_SERIAL_DEC_CONSOLE
 #include <linux/console.h>
 #endif
 
 #include <asm/pgtable.h>
 #include <asm/irq.h>
 #include <asm/system.h>
-#include <asm/bitops.h>
 #include <asm/uaccess.h>
-#include <asm/wbflush.h>
 #include <asm/bootinfo.h>
+#include <asm/dec/serial.h>
+
 #ifdef CONFIG_MACH_DECSTATION
 #include <asm/dec/interrupts.h>
 #include <asm/dec/machtype.h>
 #include <asm/dec/tc.h>
 #include <asm/dec/ioasic_addrs.h>
 #endif
-#ifdef CONFIG_BAGET_MIPS
-#include <asm/baget/baget.h>
-unsigned long system_base;
-#endif
 #ifdef CONFIG_KGDB
 #include <asm/kgdb.h>
 #endif
@@ -94,7 +90,7 @@ unsigned long system_base;
 #define NUM_SERIAL     2               /* Max number of ZS chips supported */
 #define NUM_CHANNELS   (NUM_SERIAL * 2)        /* 2 channels per chip */
 #define CHANNEL_A_NR  (zs_parms->channel_a_offset > zs_parms->channel_b_offset)
-                                        /* Number of channel A in the chip */ 
+                                        /* Number of channel A in the chip */
 #define ZS_CHAN_IO_SIZE 8
 #define ZS_CLOCK        7372800        /* Z8530 RTxC input clock rate */
 
@@ -105,7 +101,8 @@ struct zs_parms {
        unsigned long scc1;
        int channel_a_offset;
        int channel_b_offset;
-       int irq;
+       int irq0;
+       int irq1;
        int clock;
 };
 
@@ -113,24 +110,15 @@ static struct zs_parms *zs_parms;
 
 #ifdef CONFIG_MACH_DECSTATION
 static struct zs_parms ds_parms = {
-       scc0 : SCC0,
-       scc1 : SCC1,
+       scc0 : IOASIC_SCC0,
+       scc1 : IOASIC_SCC1,
        channel_a_offset : 1,
        channel_b_offset : 9,
-       irq : SERIAL,
+       irq0 : -1,
+       irq1 : -1,
        clock : ZS_CLOCK
 };
 #endif
-#ifdef CONFIG_BAGET_MIPS
-static struct zs_parms baget_parms = {
-       scc0 : UNI_SCC0,
-       scc1 : UNI_SCC1,
-       channel_a_offset : 9,
-       channel_b_offset : 1,
-       irq : BAGET_SCC_IRQ,
-       clock : 14745000
-};
-#endif
 
 #ifdef CONFIG_MACH_DECSTATION
 #define DS_BUS_PRESENT (IOASIC)
@@ -138,13 +126,7 @@ static struct zs_parms baget_parms = {
 #define DS_BUS_PRESENT 0
 #endif
 
-#ifdef CONFIG_BAGET_MIPS
-#define BAGET_BUS_PRESENT (mips_machtype == MACH_BAGET202)
-#else
-#define BAGET_BUS_PRESENT 0
-#endif
-
-#define BUS_PRESENT (DS_BUS_PRESENT || BAGET_BUS_PRESENT)
+#define BUS_PRESENT (DS_BUS_PRESENT)
 
 struct dec_zschannel zs_channels[NUM_CHANNELS];
 struct dec_serial zs_soft[NUM_CHANNELS];
@@ -153,28 +135,28 @@ struct dec_serial *zs_chain;      /* list of all channels */
 
 struct tty_struct zs_ttys[NUM_CHANNELS];
 
-#ifdef CONFIG_SERIAL_CONSOLE
+#ifdef CONFIG_SERIAL_DEC_CONSOLE
 static struct console sercons;
 #endif
-#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) \
-    && !defined(MODULE)
+#if defined(CONFIG_SERIAL_DEC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && \
+   !defined(MODULE)
 static unsigned long break_pressed; /* break, really ... */
 #endif
 
 static unsigned char zs_init_regs[16] __initdata = {
-       0,                           /* write 0 */
-       0,                           /* write 1 */
-       0xf0,                        /* write 2 */
-       (Rx8),                       /* write 3 */
-       (X16CLK | SB1),              /* write 4 */
-       (Tx8),                       /* write 5 */
-       0, 0, 0,                     /* write 6, 7, 8 */
-       (VIS),                       /* write 9 */
-       (NRZ),                       /* write 10 */
-       (TCBR | RCBR),               /* write 11 */
-       0, 0,                        /* BRG time constant, write 12 + 13 */
-       (BRSRC | BRENABL),           /* write 14 */
-       0                            /* write 15 */
+       0,                              /* write 0 */
+       0,                              /* write 1 */
+       0,                              /* write 2 */
+       0,                              /* write 3 */
+       (X16CLK),                       /* write 4 */
+       0,                              /* write 5 */
+       0, 0, 0,                        /* write 6, 7, 8 */
+       (MIE | DLC | NV),               /* write 9 */
+       (NRZ),                          /* write 10 */
+       (TCBR | RCBR),                  /* write 11 */
+       0, 0,                           /* BRG time constant, write 12 + 13 */
+       (BRSRC | BRENABL),              /* write 14 */
+       0                               /* write 15 */
 };
 
 DECLARE_TASK_QUEUE(tq_zs_serial);
@@ -190,7 +172,6 @@ static struct tty_driver *serial_driver;
 /*
  * Debugging.
  */
-#undef SERIAL_DEBUG_INTR
 #undef SERIAL_DEBUG_OPEN
 #undef SERIAL_DEBUG_FLOW
 #undef SERIAL_DEBUG_THROTTLE
@@ -251,7 +232,7 @@ static int baud_table[] = {
        0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
        9600, 19200, 38400, 57600, 115200, 0 };
 
-/* 
+/*
  * Reading and writing Z8530 registers.
  */
 static inline unsigned char read_zsreg(struct dec_zschannel *channel,
@@ -261,7 +242,7 @@ static inline unsigned char read_zsreg(struct dec_zschannel *channel,
 
        if (reg != 0) {
                *channel->control = reg & 0xf;
-               wbflush(); RECOVERY_DELAY;
+               fast_iob(); RECOVERY_DELAY;
        }
        retval = *channel->control;
        RECOVERY_DELAY;
@@ -273,10 +254,10 @@ static inline void write_zsreg(struct dec_zschannel *channel,
 {
        if (reg != 0) {
                *channel->control = reg & 0xf;
-               wbflush(); RECOVERY_DELAY;
+               fast_iob(); RECOVERY_DELAY;
        }
        *channel->control = value;
-       wbflush(); RECOVERY_DELAY;
+       fast_iob(); RECOVERY_DELAY;
        return;
 }
 
@@ -293,7 +274,7 @@ static inline void write_zsdata(struct dec_zschannel *channel,
                                unsigned char value)
 {
        *channel->data = value;
-       wbflush(); RECOVERY_DELAY;
+       fast_iob(); RECOVERY_DELAY;
        return;
 }
 
@@ -303,9 +284,9 @@ static inline void load_zsregs(struct dec_zschannel *channel,
 /*     ZS_CLEARERR(channel);
        ZS_CLEARFIFO(channel); */
        /* Load 'em up */
-       write_zsreg(channel, R4, regs[R4]);
        write_zsreg(channel, R3, regs[R3] & ~RxENABLE);
        write_zsreg(channel, R5, regs[R5] & ~TxENAB);
+       write_zsreg(channel, R4, regs[R4]);
        write_zsreg(channel, R9, regs[R9]);
        write_zsreg(channel, R1, regs[R1]);
        write_zsreg(channel, R2, regs[R2]);
@@ -372,8 +353,6 @@ static inline void rs_recv_clear(struct dec_zschannel *zsc)
  * -----------------------------------------------------------------------
  */
 
-static int tty_break;  /* Set whenever BREAK condition is detected.  */
-
 /*
  * This routine is used by the interrupt handler to schedule
  * processing in the software interrupt portion of the driver.
@@ -397,23 +376,18 @@ static _INLINE_ void receive_chars(struct dec_serial *info,
                stat = read_zsreg(info->zs_channel, R1);
                ch = read_zsdata(info->zs_channel);
 
-               if (!tty && !info->hook && !info->hook->rx_char)
+               if (!tty && (!info->hook || !info->hook->rx_char))
                        continue;
 
-               if (tty_break) {
-                       tty_break = 0;
-#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && !defined(MODULE)
-                       if (info->line == sercons.index) {
-                               if (!break_pressed) {
-                                       break_pressed = jiffies;
-                                       goto ignore_char;
-                               }
-                               break_pressed = 0;
-                       }
-#endif
+               flag = TTY_NORMAL;
+               if (info->tty_break) {
+                       info->tty_break = 0;
                        flag = TTY_BREAK;
                        if (info->flags & ZILOG_SAK)
                                do_SAK(tty);
+                       /* Ignore the null char got when BREAK is removed.  */
+                       if (ch == 0)
+                               continue;
                } else {
                        if (stat & Rx_OVR) {
                                flag = TTY_OVERRUN;
@@ -421,20 +395,22 @@ static _INLINE_ void receive_chars(struct dec_serial *info,
                                flag = TTY_FRAME;
                        } else if (stat & PAR_ERR) {
                                flag = TTY_PARITY;
-                       } else
-                               flag = 0;
-                       if (flag)
+                       }
+                       if (flag != TTY_NORMAL)
                                /* reset the error indication */
                                write_zsreg(info->zs_channel, R0, ERR_RES);
                }
 
-#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && !defined(MODULE)
+#if defined(CONFIG_SERIAL_DEC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && \
+   !defined(MODULE)
                if (break_pressed && info->line == sercons.index) {
-                       if (ch != 0 &&
-                           time_before(jiffies, break_pressed + HZ*5)) {
+                       /* Ignore the null char got when BREAK is removed.  */
+                       if (ch == 0)
+                               continue;
+                       if (time_before(jiffies, break_pressed + HZ * 5)) {
                                handle_sysrq(ch, regs, NULL);
                                break_pressed = 0;
-                               goto ignore_char;
+                               continue;
                        }
                        break_pressed = 0;
                }
@@ -444,22 +420,8 @@ static _INLINE_ void receive_chars(struct dec_serial *info,
                        (*info->hook->rx_char)(ch, flag);
                        return;
                }
-               
-               if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-                       static int flip_buf_ovf;
-                       ++flip_buf_ovf;
-                       continue;
-               }
-               tty->flip.count++;
-               {
-                       static int flip_max_cnt;
-                       if (flip_max_cnt < tty->flip.count)
-                               flip_max_cnt = tty->flip.count;
-               }
 
-               *tty->flip.flag_buf_ptr++ = flag;
-               *tty->flip.char_buf_ptr++ = ch;
-       ignore_char:
+               tty_insert_flip_char(tty, ch, flag);
        }
        if (tty)
                tty_flip_buffer_push(tty);
@@ -501,18 +463,22 @@ static _INLINE_ void status_handle(struct dec_serial *info)
        /* Get status from Read Register 0 */
        stat = read_zsreg(info->zs_channel, R0);
 
-       if (stat & BRK_ABRT) {
-#ifdef SERIAL_DEBUG_INTR
-               printk("handling break....");
+       if ((stat & BRK_ABRT) && !(info->read_reg_zero & BRK_ABRT)) {
+#if defined(CONFIG_SERIAL_DEC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && \
+   !defined(MODULE)
+               if (info->line == sercons.index) {
+                       if (!break_pressed)
+                               break_pressed = jiffies;
+               } else
 #endif
-               tty_break = 1;
+                       info->tty_break = 1;
        }
 
        if (info->zs_channel != info->zs_chan_a) {
 
-               /* FIXEM: Check for DCD transitions */
-               if (((stat ^ info->read_reg_zero) & DCD) != 0
-                   && info->tty && !C_CLOCAL(info->tty)) {
+               /* Check for DCD transitions */
+               if (info->tty && !C_CLOCAL(info->tty) &&
+                   ((stat ^ info->read_reg_zero) & DCD) != 0 ) {
                        if (stat & DCD) {
                                wake_up_interruptible(&info->open_wait);
                        } else {
@@ -563,7 +529,7 @@ void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
                shift = 0;      /* Channel B */
 
        for (;;) {
-               zs_intreg = read_zsreg(info->zs_chan_a, R3) >> shift; 
+               zs_intreg = read_zsreg(info->zs_chan_a, R3) >> shift;
                if ((zs_intreg & CHAN_IRQMASK) == 0)
                        break;
 
@@ -577,7 +543,7 @@ void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
                        status_handle(info);
                }
        }
-       
+
        /* Why do we need this ? */
        write_zsreg(info->zs_channel, 0, RES_H_IUS);
 }
@@ -586,14 +552,14 @@ void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 void zs_dump (void) {
        int i, j;
        for (i = 0; i < zs_channels_found; i++) {
-               struct dec_zschannel *ch = &zs_channels[i]; 
+               struct dec_zschannel *ch = &zs_channels[i];
                if ((long)ch->control == UNI_IO_BASE+UNI_SCC1A_CTRL) {
                        for (j = 0; j < 15; j++) {
-                               printk("W%d = 0x%x\t", 
+                               printk("W%d = 0x%x\t",
                                       j, (int)ch->curregs[j]);
                        }
                        for (j = 0; j < 15; j++) {
-                               printk("R%d = 0x%x\t", 
+                               printk("R%d = 0x%x\t",
                                       j, (int)read_zsreg(ch,j));
                        }
                        printk("\n\n");
@@ -622,7 +588,7 @@ static void rs_stop(struct tty_struct *tty)
 
        if (serial_paranoia_check(info, tty->name, "rs_stop"))
                return;
-       
+
 #if 1
        save_flags(flags); cli();
        if (info->zs_channel->curregs[5] & TxENAB) {
@@ -637,10 +603,10 @@ static void rs_start(struct tty_struct *tty)
 {
        struct dec_serial *info = (struct dec_serial *)tty->driver_data;
        unsigned long flags;
-       
+
        if (serial_paranoia_check(info, tty->name, "rs_start"))
                return;
-       
+
        save_flags(flags); cli();
 #if 1
        if (info->xmit_cnt && info->xmit_buf && !(info->zs_channel->curregs[5] & TxENAB)) {
@@ -673,7 +639,7 @@ static void do_softint(void *private_)
 {
        struct dec_serial       *info = (struct dec_serial *) private_;
        struct tty_struct       *tty;
-       
+
        tty = info->tty;
        if (!tty)
                return;
@@ -711,8 +677,13 @@ int zs_startup(struct dec_serial * info)
        /*
         * Clear the interrupt registers.
         */
-       write_zsreg(info->zs_channel, 0, ERR_RES);
-       write_zsreg(info->zs_channel, 0, RES_H_IUS);
+       write_zsreg(info->zs_channel, R0, ERR_RES);
+       write_zsreg(info->zs_channel, R0, RES_H_IUS);
+
+       /*
+        * Set the speed of the serial port
+        */
+       change_speed(info);
 
        /*
         * Turn on RTS and DTR.
@@ -722,35 +693,30 @@ int zs_startup(struct dec_serial * info)
        /*
         * Finally, enable sequencing and interrupts
         */
-       info->zs_channel->curregs[1] = (info->zs_channel->curregs[1] & ~0x18) | (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB);
-       info->zs_channel->curregs[3] |= (RxENABLE | Rx8);
-       info->zs_channel->curregs[5] |= (TxENAB | Tx8);
-       info->zs_channel->curregs[15] |= (DCDIE | CTSIE | TxUIE | BRKIE);
-       info->zs_channel->curregs[9] |= (VIS | MIE);
-       write_zsreg(info->zs_channel, 1, info->zs_channel->curregs[1]);
-       write_zsreg(info->zs_channel, 3, info->zs_channel->curregs[3]);
-       write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]);
-       write_zsreg(info->zs_channel, 15, info->zs_channel->curregs[15]);
-       write_zsreg(info->zs_channel, 9, info->zs_channel->curregs[9]);
+       info->zs_channel->curregs[R1] &= ~RxINT_MASK;
+       info->zs_channel->curregs[R1] |= (RxINT_ALL | TxINT_ENAB |
+                                         EXT_INT_ENAB);
+       info->zs_channel->curregs[R3] |= RxENABLE;
+       info->zs_channel->curregs[R5] |= TxENAB;
+       info->zs_channel->curregs[R15] |= (DCDIE | CTSIE | TxUIE | BRKIE);
+       write_zsreg(info->zs_channel, R1, info->zs_channel->curregs[R1]);
+       write_zsreg(info->zs_channel, R3, info->zs_channel->curregs[R3]);
+       write_zsreg(info->zs_channel, R5, info->zs_channel->curregs[R5]);
+       write_zsreg(info->zs_channel, R15, info->zs_channel->curregs[R15]);
 
        /*
         * And clear the interrupt registers again for luck.
         */
-       write_zsreg(info->zs_channel, 0, ERR_RES);
-       write_zsreg(info->zs_channel, 0, RES_H_IUS);
+       write_zsreg(info->zs_channel, R0, ERR_RES);
+       write_zsreg(info->zs_channel, R0, RES_H_IUS);
+
+       /* Save the current value of RR0 */
+       info->read_reg_zero = read_zsreg(info->zs_channel, R0);
 
        if (info->tty)
                clear_bit(TTY_IO_ERROR, &info->tty->flags);
        info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
 
-       /*
-        * Set the speed of the serial port
-        */
-       change_speed(info);
-
-       /* Save the current value of RR0 */
-       info->read_reg_zero = read_zsreg(info->zs_channel, 0);
-
        info->flags |= ZILOG_INITIALIZED;
        restore_flags(flags);
        return 0;
@@ -771,9 +737,9 @@ static void shutdown(struct dec_serial * info)
        printk("Shutting down serial port %d (irq %d)....", info->line,
               info->irq);
 #endif
-       
+
        save_flags(flags); cli(); /* Disable interrupts */
-       
+
        if (info->xmit_buf) {
                free_page((unsigned long) info->xmit_buf);
                info->xmit_buf = 0;
@@ -833,13 +799,11 @@ static void change_speed(struct dec_serial *info)
 
        save_flags(flags); cli();
        info->zs_baud = baud_table[i];
-       info->clk_divisor = 16;
        if (info->zs_baud) {
-               info->zs_channel->curregs[4] = X16CLK;
                brg = BPS_TO_BRG(info->zs_baud, zs_parms->clock/info->clk_divisor);
                info->zs_channel->curregs[12] = (brg & 255);
                info->zs_channel->curregs[13] = ((brg >> 8) & 255);
-               zs_rtsdtr(info, DTR, 1); 
+               zs_rtsdtr(info, DTR, 1);
        } else {
                zs_rtsdtr(info, RTS | DTR, 0);
                return;
@@ -927,7 +891,7 @@ static void rs_flush_chars(struct tty_struct *tty)
        restore_flags(flags);
 }
 
-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, total = 0;
@@ -942,17 +906,17 @@ static int rs_write(struct tty_struct * tty, int from_user,
 
        save_flags(flags);
        while (1) {
-               cli();          
-               c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-                                         SERIAL_XMIT_SIZE - info->xmit_head));
+               cli();
+               c = min(count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+                                  SERIAL_XMIT_SIZE - info->xmit_head));
                if (c <= 0)
                        break;
 
                if (from_user) {
                        down(&tmp_buf_sem);
                        copy_from_user(tmp_buf, buf, c);
-                       c = min_t(int, c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-                                             SERIAL_XMIT_SIZE - info->xmit_head));
+                       c = min(c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+                                      SERIAL_XMIT_SIZE - info->xmit_head));
                        memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
                        up(&tmp_buf_sem);
                } else
@@ -976,7 +940,7 @@ static int rs_write_room(struct tty_struct *tty)
 {
        struct dec_serial *info = (struct dec_serial *)tty->driver_data;
        int     ret;
-                               
+
        if (serial_paranoia_check(info, tty->name, "rs_write_room"))
                return 0;
        ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
@@ -988,7 +952,7 @@ static int rs_write_room(struct tty_struct *tty)
 static int rs_chars_in_buffer(struct tty_struct *tty)
 {
        struct dec_serial *info = (struct dec_serial *)tty->driver_data;
-                       
+
        if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer"))
                return 0;
        return info->xmit_cnt;
@@ -997,7 +961,7 @@ static int rs_chars_in_buffer(struct tty_struct *tty)
 static void rs_flush_buffer(struct tty_struct *tty)
 {
        struct dec_serial *info = (struct dec_serial *)tty->driver_data;
-                               
+
        if (serial_paranoia_check(info, tty->name, "rs_flush_buffer"))
                return;
        cli();
@@ -1009,7 +973,7 @@ static void rs_flush_buffer(struct tty_struct *tty)
 /*
  * ------------------------------------------------------------
  * rs_throttle()
- * 
+ *
  * This routine is called by the upper-layer tty layer to signal that
  * incoming characters should be throttled.
  * ------------------------------------------------------------
@@ -1021,14 +985,14 @@ static void rs_throttle(struct tty_struct * tty)
 
 #ifdef SERIAL_DEBUG_THROTTLE
        char    buf[64];
-       
+
        printk("throttle %s: %d....\n", _tty_name(tty, buf),
               tty->ldisc.chars_in_buffer(tty));
 #endif
 
        if (serial_paranoia_check(info, tty->name, "rs_throttle"))
                return;
-       
+
        if (I_IXOFF(tty)) {
                save_flags(flags); cli();
                info->x_char = STOP_CHAR(tty);
@@ -1049,14 +1013,14 @@ static void rs_unthrottle(struct tty_struct * tty)
 
 #ifdef SERIAL_DEBUG_THROTTLE
        char    buf[64];
-       
+
        printk("unthrottle %s: %d....\n", _tty_name(tty, buf),
               tty->ldisc.chars_in_buffer(tty));
 #endif
 
        if (serial_paranoia_check(info, tty->name, "rs_unthrottle"))
                return;
-       
+
        if (I_IXOFF(tty)) {
                save_flags(flags); cli();
                if (info->x_char)
@@ -1153,7 +1117,7 @@ check_and_exit:
  *         release the bus after transmitting. This must be done when
  *         the transmit shift register is empty, not be done when the
  *         transmit holding register is empty.  This functionality
- *         allows an RS485 driver to be written in user space. 
+ *         allows an RS485 driver to be written in user space.
  */
 static int get_lsr_info(struct dec_serial * info, unsigned int *value)
 {
@@ -1200,7 +1164,7 @@ static int rs_tiocmget(struct tty_struct *tty, struct file *file)
 }
 
 static int rs_tiocmset(struct tty_struct *tty, struct file *file,
-                      unsigned int set, unsigned int clear)
+                       unsigned int set, unsigned int clear)
 {
        struct dec_serial * info = (struct dec_serial *)tty->driver_data;
        int error;
@@ -1218,6 +1182,7 @@ static int rs_tiocmset(struct tty_struct *tty, struct file *file,
        if (info->zs_channel == info->zs_chan_a)
                return 0;
 
+       get_user(arg, value);
        cli();
        if (set & TIOCM_RTS)
                info->zs_chan_a->curregs[5] |= RTS;
@@ -1272,38 +1237,38 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
                if (tty->flags & (1 << TTY_IO_ERROR))
                    return -EIO;
        }
-       
+
        switch (cmd) {
-               case TIOCGSERIAL:
-                       error = verify_area(VERIFY_WRITE, (void *) arg,
-                                               sizeof(struct serial_struct));
-                       if (error)
-                               return error;
-                       return get_serial_info(info,
-                                              (struct serial_struct *) arg);
-               case TIOCSSERIAL:
-                       return set_serial_info(info,
-                                              (struct serial_struct *) arg);
-               case TIOCSERGETLSR: /* Get line status register */
-                       error = verify_area(VERIFY_WRITE, (void *) arg,
-                               sizeof(unsigned int));
-                       if (error)
-                               return error;
-                       else
-                           return get_lsr_info(info, (unsigned int *) arg);
-
-               case TIOCSERGSTRUCT:
-                       error = verify_area(VERIFY_WRITE, (void *) arg,
-                                               sizeof(struct dec_serial));
-                       if (error)
-                               return error;
-                       copy_from_user((struct dec_serial *) arg,
-                                      info, sizeof(struct dec_serial));
-                       return 0;
-                       
-               default:
-                       return -ENOIOCTLCMD;
-               }
+       case TIOCGSERIAL:
+               error = verify_area(VERIFY_WRITE, (void *)arg,
+                                   sizeof(struct serial_struct));
+               if (error)
+                       return error;
+               return get_serial_info(info, (struct serial_struct *)arg);
+
+       case TIOCSSERIAL:
+               return set_serial_info(info, (struct serial_struct *)arg);
+
+       case TIOCSERGETLSR:                     /* Get line status register */
+               error = verify_area(VERIFY_WRITE, (void *)arg,
+                                   sizeof(unsigned int));
+               if (error)
+                       return error;
+               else
+                       return get_lsr_info(info, (unsigned int *)arg);
+
+       case TIOCSERGSTRUCT:
+               error = verify_area(VERIFY_WRITE, (void *)arg,
+                                   sizeof(struct dec_serial));
+               if (error)
+                       return error;
+               copy_from_user((struct dec_serial *)arg, info,
+                              sizeof(struct dec_serial));
+               return 0;
+
+       default:
+               return -ENOIOCTLCMD;
+       }
        return 0;
 }
 
@@ -1325,7 +1290,7 @@ static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
 /*
  * ------------------------------------------------------------
  * rs_close()
- * 
+ *
  * This routine is called when the serial port gets closed.
  * Wait for the last remaining data to be sent.
  * ------------------------------------------------------------
@@ -1337,14 +1302,14 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
 
        if (!info || serial_paranoia_check(info, tty->name, "rs_close"))
                return;
-       
+
        save_flags(flags); cli();
-       
+
        if (tty_hung_up_p(filp)) {
                restore_flags(flags);
                return;
        }
-       
+
 #ifdef SERIAL_DEBUG_OPEN
        printk("rs_close ttyS%d, count = %d\n", info->line, info->count);
 #endif
@@ -1371,7 +1336,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
        }
        info->flags |= ZILOG_CLOSING;
        /*
-        * Now we wait for the transmit buffer to clear; and we notify 
+        * Now we wait for the transmit buffer to clear; and we notify
         * the line discipline to only process XON/XOFF characters.
         */
        tty->closing = 1;
@@ -1419,7 +1384,8 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
 static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
 {
        struct dec_serial *info = (struct dec_serial *) tty->driver_data;
-       unsigned long orig_jiffies, char_time;
+       unsigned long orig_jiffies;
+       int char_time;
 
        if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent"))
                return;
@@ -1435,7 +1401,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
        if (char_time == 0)
                char_time = 1;
        if (timeout)
-               char_time = min_t(unsigned long, char_time, timeout);
+               char_time = min(char_time, timeout);
        while ((read_zsreg(info->zs_channel, 1) & Tx_BUF_EMP) == 0) {
                current->state = TASK_INTERRUPTIBLE;
                schedule_timeout(char_time);
@@ -1492,11 +1458,6 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
 #endif
        }
 
-       /*
-        * If this is a callout device, then just make sure the normal
-        * device isn't being used.
-        */
-       
        /*
         * If non-blocking mode is set, or the port is not enabled,
         * then make the check up front and then exit.
@@ -1524,7 +1485,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
               info->line, info->count);
 #endif
        cli();
-       if (!tty_hung_up_p(filp)) 
+       if (!tty_hung_up_p(filp))
                info->count--;
        sti();
        info->blocked_open++;
@@ -1540,7 +1501,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
                        if (info->flags & ZILOG_HUP_NOTIFY)
                                retval = -EAGAIN;
                        else
-                               retval = -ERESTARTSYS;  
+                               retval = -ERESTARTSYS;
 #else
                        retval = -EAGAIN;
 #endif
@@ -1572,7 +1533,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
                return retval;
        info->flags |= ZILOG_NORMAL_ACTIVE;
        return 0;
-}      
+}
 
 /*
  * This routine is called whenever a serial port is opened.  It
@@ -1634,7 +1595,7 @@ int rs_open(struct tty_struct *tty, struct file * filp)
                return retval;
        }
 
-#ifdef CONFIG_SERIAL_CONSOLE
+#ifdef CONFIG_SERIAL_DEC_CONSOLE
        if (sercons.cflag && sercons.index == line) {
                tty->termios->c_cflag = sercons.cflag;
                sercons.cflag = 0;
@@ -1653,7 +1614,7 @@ int rs_open(struct tty_struct *tty, struct file * filp)
 
 static void __init show_serial_version(void)
 {
-       printk("DECstation Z8530 serial driver version 0.05\n");
+       printk("DECstation Z8530 serial driver version 0.09\n");
 }
 
 /*  Initialize Z8530s zs_channels
@@ -1663,6 +1624,7 @@ static void __init probe_sccs(void)
 {
        struct dec_serial **pp;
        int i, n, n_chips = 0, n_channels, chip, channel;
+       unsigned long flags;
 
        /*
         * did we get here by accident?
@@ -1671,7 +1633,7 @@ static void __init probe_sccs(void)
                printk("Not on JUNKIO machine, skipping probe_sccs\n");
                return;
        }
-       
+
        /*
         * When serial console is activated, tc_init has not been called yet
         * and system_base is undefined. Unfortunately we have to hardcode
@@ -1680,27 +1642,25 @@ static void __init probe_sccs(void)
        switch(mips_machtype) {
 #ifdef CONFIG_MACH_DECSTATION
        case MACH_DS5000_2X0:
-               system_base = 0xbf800000;
+       case MACH_DS5900:
+               system_base = KSEG1ADDR(0x1f800000);
                n_chips = 2;
                zs_parms = &ds_parms;
+               zs_parms->irq0 = dec_interrupt[DEC_IRQ_SCC0];
+               zs_parms->irq1 = dec_interrupt[DEC_IRQ_SCC1];
                break;
        case MACH_DS5000_1XX:
-               system_base = 0xbc000000;
+               system_base = KSEG1ADDR(0x1c000000);
                n_chips = 2;
                zs_parms = &ds_parms;
+               zs_parms->irq0 = dec_interrupt[DEC_IRQ_SCC0];
+               zs_parms->irq1 = dec_interrupt[DEC_IRQ_SCC1];
                break;
        case MACH_DS5000_XX:
-               system_base = 0xbc000000;
+               system_base = KSEG1ADDR(0x1c000000);
                n_chips = 1;
                zs_parms = &ds_parms;
-               break;
-#endif
-#ifdef CONFIG_BAGET_MIPS
-       case MACH_BAGET202:
-               system_base = UNI_IO_BASE;
-               n_chips = 2;
-               zs_parms = &baget_parms;
-               zs_init_regs[2] = 0x8;
+               zs_parms->irq0 = dec_interrupt[DEC_IRQ_SCC0];
                break;
 #endif
        default:
@@ -1718,15 +1678,15 @@ static void __init probe_sccs(void)
                        /*
                         * The sccs reside on the high byte of the 16 bit IOBUS
                         */
-                       zs_channels[n_channels].control = 
-                               (volatile unsigned char *)system_base + 
-                         (0 == chip ? zs_parms->scc0 : zs_parms->scc1) + 
-                         (0 == channel ? zs_parms->channel_a_offset : 
+                       zs_channels[n_channels].control =
+                               (volatile unsigned char *)system_base +
+                         (0 == chip ? zs_parms->scc0 : zs_parms->scc1) +
+                         (0 == channel ? zs_parms->channel_a_offset :
                                          zs_parms->channel_b_offset);
-                       zs_channels[n_channels].data = 
+                       zs_channels[n_channels].data =
                                zs_channels[n_channels].control + 4;
 
-#ifndef CONFIG_SERIAL_CONSOLE
+#ifndef CONFIG_SERIAL_DEC_CONSOLE
                        /*
                         * We're called early and memory managment isn't up, yet.
                         * Thus check_region would fail.
@@ -1737,20 +1697,24 @@ static void __init probe_sccs(void)
                                panic("SCC I/O region is not free");
 #endif
                        zs_soft[n_channels].zs_channel = &zs_channels[n_channels];
-                       zs_soft[n_channels].irq = zs_parms->irq;
+                       /* HACK alert! */
+                       if (!(chip & 1))
+                               zs_soft[n_channels].irq = zs_parms->irq0;
+                       else
+                               zs_soft[n_channels].irq = zs_parms->irq1;
 
-                       /* 
+                       /*
                         *  Identification of channel A. Location of channel A
                          *  inside chip depends on mapping of internal address
                         *  the chip decodes channels by.
-                        *  CHANNEL_A_NR returns either 0 (in case of 
+                        *  CHANNEL_A_NR returns either 0 (in case of
                         *  DECstations) or 1 (in case of Baget).
                         */
                        if (CHANNEL_A_NR == channel)
-                               zs_soft[n_channels].zs_chan_a = 
+                               zs_soft[n_channels].zs_chan_a =
                                    &zs_channels[n_channels+1-2*CHANNEL_A_NR];
                        else
-                               zs_soft[n_channels].zs_chan_a = 
+                               zs_soft[n_channels].zs_chan_a =
                                    &zs_channels[n_channels];
 
                        *pp = &zs_soft[n_channels];
@@ -1768,16 +1732,17 @@ static void __init probe_sccs(void)
                }
        }
 
-/*     save_and_cli(flags);
+       save_and_cli(flags);
        for (n = 0; n < zs_channels_found; n++) {
-               if (((int)zs_channels[n].control & 0xf) == 1) {
+               if (n % 2 == 0) {
                        write_zsreg(zs_soft[n].zs_chan_a, R9, FHWRES);
-                       mdelay(10);
+                       udelay(10);
                        write_zsreg(zs_soft[n].zs_chan_a, R9, 0);
                }
-               load_zsregs(zs_soft[n].zs_channel, zs_soft[n].zs_channel->curregs);
-       } 
-       restore_flags(flags); */
+               load_zsregs(zs_soft[n].zs_channel,
+                           zs_soft[n].zs_channel->curregs);
+       }
+       restore_flags(flags);
 }
 
 static struct tty_operations serial_ops = {
@@ -1805,7 +1770,6 @@ static struct tty_operations serial_ops = {
 int __init zs_init(void)
 {
        int channel, i;
-       unsigned long flags;
        struct dec_serial *info;
 
        if(!BUS_PRESENT)
@@ -1817,7 +1781,6 @@ int __init zs_init(void)
        /* Find out how many Z8530 SCCs we have */
        if (zs_chain == 0)
                probe_sccs();
-
        serial_driver = alloc_tty_driver(zs_channels_found);
        if (!serial_driver)
                return -ENOMEM;
@@ -1841,39 +1804,25 @@ int __init zs_init(void)
        tty_set_operations(serial_driver, &serial_ops);
 
        if (tty_register_driver(serial_driver))
-               panic("Couldn't register serial driver\n");
-
-       save_flags(flags); cli();
-
-       for (channel = 0; channel < zs_channels_found; ++channel) {
-               if (zs_soft[channel].hook &&
-                   zs_soft[channel].hook->init_channel)
-                       (*zs_soft[channel].hook->init_channel)
-                               (&zs_soft[channel]);
+               panic("Couldn't register serial driver");
 
-               zs_soft[channel].clk_divisor = 16;
-               zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]);
+       for (info = zs_chain, i = 0; info; info = info->zs_next, i++) {
 
-               if (request_irq(zs_parms->irq, rs_interrupt, SA_SHIRQ,
-                               "SCC", &zs_soft[channel]))
-                       printk(KERN_ERR "decserial: can't get irq %d\n",
-                              zs_parms->irq);
-       }
+               /* Needed before interrupts are enabled. */
+               info->tty = 0;
+               info->x_char = 0;
 
-       for (info = zs_chain, i = 0; info; info = info->zs_next, i++)
-       {
                if (info->hook && info->hook->init_info) {
                        (*info->hook->init_info)(info);
                        continue;
                }
+
                info->magic = SERIAL_MAGIC;
                info->port = (int) info->zs_channel->control;
                info->line = i;
-               info->tty = 0;
                info->custom_divisor = 16;
                info->close_delay = 50;
                info->closing_wait = 3000;
-               info->x_char = 0;
                info->event = 0;
                info->count = 0;
                info->blocked_open = 0;
@@ -1881,94 +1830,83 @@ int __init zs_init(void)
                info->tqueue.data = info;
                init_waitqueue_head(&info->open_wait);
                init_waitqueue_head(&info->close_wait);
-               printk("ttyS%d at 0x%08x (irq = %d)", info->line,
-                      info->port, info->irq);
-               printk(" is a Z85C30 SCC\n");
+               printk("ttyS%02d at 0x%08x (irq = %d) is a Z85C30 SCC\n",
+                      info->line, info->port, info->irq);
                tty_register_device(serial_driver, info->line, NULL);
+
        }
 
-       restore_flags(flags);
+       for (channel = 0; channel < zs_channels_found; ++channel) {
+               zs_soft[channel].clk_divisor = 16;
+               zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]);
 
-       return 0;
-}
+               if (request_irq(zs_soft[channel].irq, rs_interrupt, SA_SHIRQ,
+                               "scc", &zs_soft[channel]))
+                       printk(KERN_ERR "decserial: can't get irq %d\n",
+                              zs_soft[channel].irq);
 
-/*
- * register_serial and unregister_serial allows for serial ports to be
- * configured at run-time, to support PCMCIA modems.
- */
-/* PowerMac: Unused at this time, just here to make things link. */
-int register_serial(struct serial_struct *req)
-{
-       return -1;
-}
+               if (zs_soft[channel].hook) {
+                       zs_startup(&zs_soft[channel]);
+                       if (zs_soft[channel].hook->init_channel)
+                               (*zs_soft[channel].hook->init_channel)
+                                       (&zs_soft[channel]);
+               }
+       }
 
-void unregister_serial(int line)
-{
-       return;
+       return 0;
 }
 
 /*
  * polling I/O routines
  */
 static int
-zs_poll_tx_char(struct dec_serial *info, unsigned char ch)
+zs_poll_tx_char(void *handle, unsigned char ch)
 {
+       struct dec_serial *info = handle;
        struct dec_zschannel *chan = info->zs_channel;
        int    ret;
 
        if(chan) {
                int loops = 10000;
-//             int nine = read_zsreg(chan, R9);
-
-               RECOVERY_DELAY;
-//             write_zsreg(chan, R9, nine & ~MIE);
-                       wbflush();
-               RECOVERY_DELAY;
-
-               while (!(*(chan->control) & Tx_BUF_EMP) && --loops)
-                       RECOVERY_DELAY;
-
-                if (loops) {
-                        ret = 0;
-                       *(chan->data) = ch;
-                       wbflush();
-                       RECOVERY_DELAY;
-                } else
-                        ret = -EAGAIN;
 
-//             write_zsreg(chan, R9, nine);
-                       wbflush();
-               RECOVERY_DELAY;
+               while (loops && !(read_zsreg(chan, 0) & Tx_BUF_EMP))
+                       loops--;
 
-                return ret;
-        }
+               if (loops) {
+                       write_zsdata(chan, ch);
+                       ret = 0;
+               } else
+                       ret = -EAGAIN;
 
-       return -ENODEV;
+               return ret;
+       } else
+               return -ENODEV;
 }
 
 static int
-zs_poll_rx_char(struct dec_serial *info)
+zs_poll_rx_char(void *handle)
 {
+       struct dec_serial *info = handle;
         struct dec_zschannel *chan = info->zs_channel;
         int    ret;
 
        if(chan) {
                 int loops = 10000;
 
-                while((read_zsreg(chan, 0) & Rx_CH_AV) == 0)
-                       loops--;
+               while (loops && !(read_zsreg(chan, 0) & Rx_CH_AV))
+                       loops--;
 
                 if (loops)
                         ret = read_zsdata(chan);
                 else
                         ret = -EAGAIN;
 
-                return ret;
-        } else
-                return -ENODEV;
+               return ret;
+       } else
+               return -ENODEV;
 }
 
-unsigned int register_zs_hook(unsigned int channel, struct zs_hook *hook)
+int register_zs_hook(unsigned int channel, struct dec_serial_hook *hook)
 {
        struct dec_serial *info = &zs_soft[channel];
 
@@ -1978,22 +1916,15 @@ unsigned int register_zs_hook(unsigned int channel, struct zs_hook *hook)
 
                return 0;
        } else {
-               info->hook = hook;
-
-               if (zs_chain == 0)
-                       probe_sccs();
-
-               if (!(info->flags & ZILOG_INITIALIZED))
-                       zs_startup(info);
-
                hook->poll_rx_char = zs_poll_rx_char;
                hook->poll_tx_char = zs_poll_tx_char;
+               info->hook = hook;
 
                return 1;
        }
 }
 
-unsigned int unregister_zs_hook(unsigned int channel)
+int unregister_zs_hook(unsigned int channel)
 {
        struct dec_serial *info = &zs_soft[channel];
 
@@ -2012,7 +1943,7 @@ unsigned int unregister_zs_hook(unsigned int channel)
  * Serial console driver
  * ------------------------------------------------------------
  */
-#ifdef CONFIG_SERIAL_CONSOLE
+#ifdef CONFIG_SERIAL_DEC_CONSOLE
 
 
 /*
@@ -2049,11 +1980,13 @@ static struct tty_driver *serial_console_device(struct console *c, int *index)
 static int __init serial_console_setup(struct console *co, char *options)
 {
        struct dec_serial *info;
-       int     baud = 9600;
-       int     bits = 8;
-       int     parity = 'n';
-       int     cflag = CREAD | HUPCL | CLOCAL;
-       char    *s;
+       int baud = 9600;
+       int bits = 8;
+       int parity = 'n';
+       int cflag = CREAD | HUPCL | CLOCAL;
+       int clk_divisor = 16;
+       int brg;
+       char *s;
        unsigned long flags;
 
        if(!BUS_PRESENT)
@@ -2105,6 +2038,10 @@ static int __init serial_console_setup(struct console *co, char *options)
        case 9600:
        default:
                cflag |= B9600;
+               /*
+                * Set this to a sane value to prevent a divide error.
+                */
+               baud  = 9600;
                break;
        }
        switch(bits) {
@@ -2125,43 +2062,64 @@ static int __init serial_console_setup(struct console *co, char *options)
                break;
        }
        co->cflag = cflag;
-#if 1 
+
        save_and_cli(flags);
 
+       /*
+        * Set up the baud rate generator.
+        */
+       brg = BPS_TO_BRG(baud, zs_parms->clock / clk_divisor);
+       info->zs_channel->curregs[R12] = (brg & 255);
+       info->zs_channel->curregs[R13] = ((brg >> 8) & 255);
+
+       /*
+        * Set byte size and parity.
+        */
+       if (bits == 7) {
+               info->zs_channel->curregs[R3] |= Rx7;
+               info->zs_channel->curregs[R5] |= Tx7;
+       } else {
+               info->zs_channel->curregs[R3] |= Rx8;
+               info->zs_channel->curregs[R5] |= Tx8;
+       }
+       if (cflag & PARENB) {
+               info->zs_channel->curregs[R4] |= PAR_ENA;
+       }
+       if (!(cflag & PARODD)) {
+               info->zs_channel->curregs[R4] |= PAR_EVEN;
+       }
+       info->zs_channel->curregs[R4] |= SB1;
+
        /*
         * Turn on RTS and DTR.
         */
        zs_rtsdtr(info, RTS | DTR, 1);
 
        /*
-        * Finally, enable sequencing
+        * Finally, enable sequencing.
         */
-       info->zs_channel->curregs[3] |= (RxENABLE | Rx8);
-       info->zs_channel->curregs[5] |= (TxENAB | Tx8);
-       info->zs_channel->curregs[9] |= (VIS);
-       write_zsreg(info->zs_channel, 3, info->zs_channel->curregs[3]);
-       write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]);
-       write_zsreg(info->zs_channel, 9, info->zs_channel->curregs[9]);
+       info->zs_channel->curregs[R3] |= RxENABLE;
+       info->zs_channel->curregs[R5] |= TxENAB;
 
        /*
         * Clear the interrupt registers.
         */
-       write_zsreg(info->zs_channel, 0, ERR_RES);
-       write_zsreg(info->zs_channel, 0, RES_H_IUS);
+       write_zsreg(info->zs_channel, R0, ERR_RES);
+       write_zsreg(info->zs_channel, R0, RES_H_IUS);
 
        /*
-        * Set the speed of the serial port
+        * Load up the new values.
         */
-       change_speed(info);
+       load_zsregs(info->zs_channel, info->zs_channel->curregs);
 
        /* Save the current value of RR0 */
-       info->read_reg_zero = read_zsreg(info->zs_channel, 0);
+       info->read_reg_zero = read_zsreg(info->zs_channel, R0);
 
-       zs_soft[co->index].clk_divisor = 16;
+       zs_soft[co->index].clk_divisor = clk_divisor;
        zs_soft[co->index].zs_baud = get_zsbaud(&zs_soft[co->index]);
 
        restore_flags(flags);
-#endif
+
        return 0;
 }
 
@@ -2181,7 +2139,7 @@ void __init zs_serial_console_init(void)
 {
        register_console(&sercons);
 }
-#endif /* ifdef CONFIG_SERIAL_CONSOLE */
+#endif /* ifdef CONFIG_SERIAL_DEC_CONSOLE */
 
 #ifdef CONFIG_KGDB
 struct dec_zschannel *zs_kgdbchan;
@@ -2219,7 +2177,7 @@ void kgdb_interruptible(int yes)
        int one, nine;
        nine = read_zsreg(chan, 9);
        if (yes == 1) {
-               one = EXT_INT_ENAB|INT_ALL_Rx;
+               one = EXT_INT_ENAB|RxINT_ALL;
                nine |= MIE;
                printk("turning serial ints on\n");
        } else {
@@ -2231,22 +2189,23 @@ void kgdb_interruptible(int yes)
        write_zsreg(chan, 9, nine);
 }
 
-static int kgdbhook_init_channel(struct dec_serial* info) 
+static int kgdbhook_init_channel(void *handle)
 {
        return 0;
 }
 
-static void kgdbhook_init_info(struct dec_serial* info)
+static void kgdbhook_init_info(void *handle)
 {
 }
 
-static void kgdbhook_rx_char(struct dec_serial* info, 
-                            unsigned char ch, unsigned char stat)
+static void kgdbhook_rx_char(void *handle, unsigned char ch, unsigned char fl)
 {
+       struct dec_serial *info = handle;
+
+       if (fl != TTY_NORMAL)
+               return;
        if (ch == 0x03 || ch == '$')
                breakpoint();
-       if (stat & (Rx_OVR|FRM_ERR|PAR_ERR))
-               write_zsreg(info->zs_channel, 0, ERR_RES);
 }
 
 /* This sets up the serial port we're using, and turns on
@@ -2272,11 +2231,11 @@ static inline void kgdb_chaninit(struct dec_zschannel *ms, int intson, int bps)
  * for /dev/ttyb which is determined in setup_arch() from the
  * boot command line flags.
  */
-struct zs_hook zs_kgdbhook = {
-       init_channel : kgdbhook_init_channel,
-       init_info    : kgdbhook_init_info,
-       cflags       : B38400|CS8|CLOCAL,
-       rx_char      : kgdbhook_rx_char,
+struct dec_serial_hook zs_kgdbhook = {
+       .init_channel   = kgdbhook_init_channel,
+       .init_info      = kgdbhook_init_info,
+       .rx_char        = kgdbhook_rx_char,
+       .cflags         = B38400 | CS8 | CLOCAL,
 }
 
 void __init zs_kgdb_hook(int tty_num)