tty: const: constify remaining tty_operations
[safe/jmp/linux-2.6] / drivers / char / epca.c
index 39c6a36..17b044a 100644 (file)
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/init.h>
+#include <linux/sched.h>
 #include <linux/serial.h>
 #include <linux/delay.h>
 #include <linux/ctype.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
 #include <linux/spinlock.h>
 #include <linux/pci.h>
 #include "digiPCI.h"
@@ -69,11 +71,14 @@ static int invalid_lilo_config;
 
 /*
  * The ISA boards do window flipping into the same spaces so its only sane with
- * a single lock. It's still pretty efficient.
+ * a single lock. It's still pretty efficient. This lock guards the hardware
+ * and the tty_port lock guards the kernel side stuff like use counts. Take
+ * this lock inside the port lock if you must take both.
  */
 static DEFINE_SPINLOCK(epca_lock);
 
-/* MAXBOARDS is typically 12, but ISA and EISA cards are restricted to 7 below. */
+/* MAXBOARDS is typically 12, but ISA and EISA cards are restricted
+   to 7 below. */
 static struct board_info boards[MAXBOARDS];
 
 static struct tty_driver *pc_driver;
@@ -155,14 +160,12 @@ static struct channel *verifyChannel(struct tty_struct *);
 static void pc_sched_event(struct channel *, int);
 static void epca_error(int, char *);
 static void pc_close(struct tty_struct *, struct file *);
-static void shutdown(struct channel *);
+static void shutdown(struct channel *, struct tty_struct *tty);
 static void pc_hangup(struct tty_struct *);
 static int pc_write_room(struct tty_struct *);
 static int pc_chars_in_buffer(struct tty_struct *);
 static void pc_flush_buffer(struct tty_struct *);
 static void pc_flush_chars(struct tty_struct *);
-static int block_til_ready(struct tty_struct *, struct file *,
-                           struct channel *);
 static int pc_open(struct tty_struct *, struct file *);
 static void post_fep_init(unsigned int crd);
 static void epcapoll(unsigned long);
@@ -172,20 +175,19 @@ static unsigned termios2digi_h(struct channel *ch, unsigned);
 static unsigned termios2digi_i(struct channel *ch, unsigned);
 static unsigned termios2digi_c(struct channel *ch, unsigned);
 static void epcaparam(struct tty_struct *, struct channel *);
-static void receive_data(struct channel *);
+static void receive_data(struct channel *, struct tty_struct *tty);
 static int pc_ioctl(struct tty_struct *, struct file *,
-                    unsigned int, unsigned long);
+                       unsigned int, unsigned long);
 static int info_ioctl(struct tty_struct *, struct file *,
-                    unsigned int, unsigned long);
+                       unsigned int, unsigned long);
 static void pc_set_termios(struct tty_struct *, struct ktermios *);
 static void do_softint(struct work_struct *work);
 static void pc_stop(struct tty_struct *);
 static void pc_start(struct tty_struct *);
-static void pc_throttle(struct tty_struct * tty);
+static void pc_throttle(struct tty_struct *tty);
 static void pc_unthrottle(struct tty_struct *tty);
-static void digi_send_break(struct channel *ch, int msec);
+static int pc_send_break(struct tty_struct *tty, int msec);
 static void setup_empty_event(struct tty_struct *tty, struct channel *ch);
-void epca_setup(char *, int *);
 
 static int pc_write(struct tty_struct *, const unsigned char *, int);
 static int pc_init(void);
@@ -242,7 +244,7 @@ static void assertmemoff(struct channel *ch)
 /* PCXEM windowing is the same as that used in the PCXR and CX series cards. */
 static void pcxem_memwinon(struct board_info *b, unsigned int win)
 {
-        outb_p(FEPWIN|win, b->port + 1);
+       outb_p(FEPWIN | win, b->port + 1);
 }
 
 static void pcxem_memwinoff(struct board_info *b, unsigned int win)
@@ -252,7 +254,7 @@ static void pcxem_memwinoff(struct board_info *b, unsigned int win)
 
 static void pcxem_globalwinon(struct channel *ch)
 {
-       outb_p( FEPWIN, (int)ch->board->port + 1);
+       outb_p(FEPWIN, (int)ch->board->port + 1);
 }
 
 static void pcxem_rxwinon(struct channel *ch)
@@ -392,8 +394,8 @@ static struct channel *verifyChannel(struct tty_struct *tty)
         * through tty->driver_data this should catch it.
         */
        if (tty) {
-               struct channel *ch = (struct channel *)tty->driver_data;
-               if ((ch >= &digi_channels[0]) && (ch < &digi_channels[nbdevs])) {
+               struct channel *ch = tty->driver_data;
+               if (ch >= &digi_channels[0] && ch < &digi_channels[nbdevs]) {
                        if (ch->magic == EPCA_MAGIC)
                                return ch;
                }
@@ -413,80 +415,40 @@ static void pc_sched_event(struct channel *ch, int event)
 
 static void epca_error(int line, char *msg)
 {
-       printk(KERN_ERR "epca_error (Digi): line = %d %s\n",line,msg);
+       printk(KERN_ERR "epca_error (Digi): line = %d %s\n", line, msg);
 }
 
 static void pc_close(struct tty_struct *tty, struct file *filp)
 {
        struct channel *ch;
-       unsigned long flags;
+       struct tty_port *port;
        /*
         * verifyChannel returns the channel from the tty struct if it is
         * valid. This serves as a sanity check.
         */
-       if ((ch = verifyChannel(tty)) != NULL) {
-               spin_lock_irqsave(&epca_lock, flags);
-               if (tty_hung_up_p(filp)) {
-                       spin_unlock_irqrestore(&epca_lock, flags);
-                       return;
-               }
-               if (ch->count-- > 1)  {
-                       /* Begin channel is open more than once */
-                       /*
-                        * Return without doing anything. Someone might still
-                        * be using the channel.
-                        */
-                       spin_unlock_irqrestore(&epca_lock, flags);
-                       return;
-               }
-
-               /* Port open only once go ahead with shutdown & reset */
-               BUG_ON(ch->count < 0);
-
-               /*
-                * Let the rest of the driver know the channel is being closed.
-                * This becomes important if an open is attempted before close
-                * is finished.
-                */
-               ch->asyncflags |= ASYNC_CLOSING;
-               tty->closing = 1;
-
-               spin_unlock_irqrestore(&epca_lock, flags);
-
-               if (ch->asyncflags & ASYNC_INITIALIZED)  {
-                       /* Setup an event to indicate when the transmit buffer empties */
-                       setup_empty_event(tty, ch);
-                       tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
-               }
-               pc_flush_buffer(tty);
+       ch = verifyChannel(tty);
+       if (ch == NULL)
+               return;
+       port = &ch->port;
 
-               tty_ldisc_flush(tty);
-               shutdown(ch);
+       if (tty_port_close_start(port, tty, filp) == 0)
+               return;
 
-               spin_lock_irqsave(&epca_lock, flags);
-               tty->closing = 0;
-               ch->event = 0;
-               ch->tty = NULL;
-               spin_unlock_irqrestore(&epca_lock, flags);
+       pc_flush_buffer(tty);
+       shutdown(ch, tty);
 
-               if (ch->blocked_open) {
-                       if (ch->close_delay)
-                               msleep_interruptible(jiffies_to_msecs(ch->close_delay));
-                       wake_up_interruptible(&ch->open_wait);
-               }
-               ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED |
-                                     ASYNC_CLOSING);
-               wake_up_interruptible(&ch->close_wait);
-       }
+       tty_port_close_end(port, tty);
+       ch->event = 0;  /* FIXME: review ch->event locking */
+       tty_port_tty_set(port, NULL);
 }
 
-static void shutdown(struct channel *ch)
+static void shutdown(struct channel *ch, struct tty_struct *tty)
 {
        unsigned long flags;
-       struct tty_struct *tty;
        struct board_chan __iomem *bc;
+       struct tty_port *port = &ch->port;
 
-       if (!(ch->asyncflags & ASYNC_INITIALIZED))
+       if (!(port->flags & ASYNC_INITIALIZED))
                return;
 
        spin_lock_irqsave(&epca_lock, flags);
@@ -501,7 +463,6 @@ static void shutdown(struct channel *ch)
         */
        if (bc)
                writeb(0, &bc->idata);
-       tty = ch->tty;
 
        /* If we're a modem control device and HUPCL is on, drop RTS & DTR. */
        if (tty->termios->c_cflag & HUPCL)  {
@@ -515,7 +476,7 @@ static void shutdown(struct channel *ch)
         * will have to reinitialized. Set a flag to indicate this.
         */
        /* Prevent future Digi programmed interrupts from coming active */
-       ch->asyncflags &= ~ASYNC_INITIALIZED;
+       port->flags &= ~ASYNC_INITIALIZED;
        spin_unlock_irqrestore(&epca_lock, flags);
 }
 
@@ -527,25 +488,19 @@ static void pc_hangup(struct tty_struct *tty)
         * verifyChannel returns the channel from the tty struct if it is
         * valid. This serves as a sanity check.
         */
-       if ((ch = verifyChannel(tty)) != NULL) {
-               unsigned long flags;
-
+       ch = verifyChannel(tty);
+       if (ch != NULL) {
                pc_flush_buffer(tty);
                tty_ldisc_flush(tty);
-               shutdown(ch);
+               shutdown(ch, tty);
 
-               spin_lock_irqsave(&epca_lock, flags);
-               ch->tty   = NULL;
-               ch->event = 0;
-               ch->count = 0;
-               ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED);
-               spin_unlock_irqrestore(&epca_lock, flags);
-               wake_up_interruptible(&ch->open_wait);
+               ch->event = 0;  /* FIXME: review locking of ch->event */
+               tty_port_hangup(&ch->port);
        }
 }
 
 static int pc_write(struct tty_struct *tty,
-                    const unsigned char *buf, int bytesAvailable)
+                       const unsigned char *buf, int bytesAvailable)
 {
        unsigned int head, tail;
        int dataLen;
@@ -569,7 +524,8 @@ static int pc_write(struct tty_struct *tty,
         * verifyChannel returns the channel from the tty struct if it is
         * valid. This serves as a sanity check.
         */
-       if ((ch = verifyChannel(tty)) == NULL)
+       ch = verifyChannel(tty);
+       if (ch == NULL)
                return 0;
 
        /* Make a pointer to the channel data structure found on the board. */
@@ -644,19 +600,17 @@ static int pc_write(struct tty_struct *tty,
 
 static int pc_write_room(struct tty_struct *tty)
 {
-       int remain;
+       int remain = 0;
        struct channel *ch;
        unsigned long flags;
        unsigned int head, tail;
        struct board_chan __iomem *bc;
-
-       remain = 0;
-
        /*
         * verifyChannel returns the channel from the tty struct if it is
         * valid. This serves as a sanity check.
         */
-       if ((ch = verifyChannel(tty)) != NULL)  {
+       ch = verifyChannel(tty);
+       if (ch != NULL) {
                spin_lock_irqsave(&epca_lock, flags);
                globalwinon(ch);
 
@@ -668,8 +622,8 @@ static int pc_write_room(struct tty_struct *tty)
                        tail = readw(&bc->tout);
                /* Wrap tail if necessary */
                tail &= (ch->txbufsize - 1);
-
-               if ((remain = tail - head - 1) < 0 )
+               remain = tail - head - 1;
+               if (remain < 0)
                        remain += ch->txbufsize;
 
                if (remain && (ch->statusflags & LOWWAIT) == 0) {
@@ -691,12 +645,12 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
        unsigned long flags;
        struct channel *ch;
        struct board_chan __iomem *bc;
-
        /*
         * verifyChannel returns the channel from the tty struct if it is
         * valid. This serves as a sanity check.
         */
-       if ((ch = verifyChannel(tty)) == NULL)
+       ch = verifyChannel(tty);
+       if (ch == NULL)
                return 0;
 
        spin_lock_irqsave(&epca_lock, flags);
@@ -707,7 +661,8 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
        head = readw(&bc->tin);
        ctail = readw(&ch->mailbox->cout);
 
-       if (tail == head && readw(&ch->mailbox->cin) == ctail && readb(&bc->tbusy) == 0)
+       if (tail == head && readw(&ch->mailbox->cin) == ctail &&
+                                               readb(&bc->tbusy) == 0)
                chars = 0;
        else  { /* Begin if some space on the card has been used */
                head = readw(&bc->tin) & (ch->txbufsize - 1);
@@ -717,7 +672,8 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
                 * pc_write_room here we are finding the amount of bytes in the
                 * buffer filled. Not the amount of bytes empty.
                 */
-               if ((remain = tail - head - 1) < 0 )
+               remain = tail - head - 1;
+               if (remain < 0)
                        remain += ch->txbufsize;
                chars = (int)(ch->txbufsize - remain);
                /*
@@ -728,7 +684,7 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
                 * transmit buffer empties.
                 */
                if (!(ch->statusflags & EMPTYWAIT))
-                       setup_empty_event(tty,ch);
+                       setup_empty_event(tty, ch);
        } /* End if some space on the card has been used */
        memoff(ch);
        spin_unlock_irqrestore(&epca_lock, flags);
@@ -746,7 +702,8 @@ static void pc_flush_buffer(struct tty_struct *tty)
         * verifyChannel returns the channel from the tty struct if it is
         * valid. This serves as a sanity check.
         */
-       if ((ch = verifyChannel(tty)) == NULL)
+       ch = verifyChannel(tty);
+       if (ch == NULL)
                return;
 
        spin_lock_irqsave(&epca_lock, flags);
@@ -767,114 +724,37 @@ static void pc_flush_chars(struct tty_struct *tty)
         * verifyChannel returns the channel from the tty struct if it is
         * valid. This serves as a sanity check.
         */
-       if ((ch = verifyChannel(tty)) != NULL) {
+       ch = verifyChannel(tty);
+       if (ch != NULL) {
                unsigned long flags;
                spin_lock_irqsave(&epca_lock, flags);
                /*
                 * If not already set and the transmitter is busy setup an
                 * event to indicate when the transmit empties.
                 */
-               if ((ch->statusflags & TXBUSY) && !(ch->statusflags & EMPTYWAIT))
-                       setup_empty_event(tty,ch);
+               if ((ch->statusflags & TXBUSY) &&
+                               !(ch->statusflags & EMPTYWAIT))
+                       setup_empty_event(tty, ch);
                spin_unlock_irqrestore(&epca_lock, flags);
        }
 }
 
-static int block_til_ready(struct tty_struct *tty,
-                           struct file *filp, struct channel *ch)
+static int epca_carrier_raised(struct tty_port *port)
 {
-       DECLARE_WAITQUEUE(wait,current);
-       int retval, do_clocal = 0;
-       unsigned long flags;
-
-       if (tty_hung_up_p(filp)) {
-               if (ch->asyncflags & ASYNC_HUP_NOTIFY)
-                       retval = -EAGAIN;
-               else
-                       retval = -ERESTARTSYS;
-               return retval;
-       }
-
-       /*
-        * If the device is in the middle of being closed, then block until
-        * it's done, and then try again.
-        */
-       if (ch->asyncflags & ASYNC_CLOSING) {
-               interruptible_sleep_on(&ch->close_wait);
-
-               if (ch->asyncflags & ASYNC_HUP_NOTIFY)
-                       return -EAGAIN;
-               else
-                       return -ERESTARTSYS;
-       }
-
-       if (filp->f_flags & O_NONBLOCK)  {
-               /*
-                * If non-blocking mode is set, then make the check up front
-                * and then exit.
-                */
-               ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
-               return 0;
-       }
-       if (tty->termios->c_cflag & CLOCAL)
-               do_clocal = 1;
-       /* Block waiting for the carrier detect and the line to become free */
-
-       retval = 0;
-       add_wait_queue(&ch->open_wait, &wait);
-
-       spin_lock_irqsave(&epca_lock, flags);
-       /* We dec count so that pc_close will know when to free things */
-       if (!tty_hung_up_p(filp))
-               ch->count--;
-       ch->blocked_open++;
-       while (1) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               if (tty_hung_up_p(filp) ||
-                   !(ch->asyncflags & ASYNC_INITIALIZED))
-               {
-                       if (ch->asyncflags & ASYNC_HUP_NOTIFY)
-                               retval = -EAGAIN;
-                       else
-                               retval = -ERESTARTSYS;
-                       break;
-               }
-               if (!(ch->asyncflags & ASYNC_CLOSING) &&
-                         (do_clocal || (ch->imodem & ch->dcd)))
-                       break;
-               if (signal_pending(current)) {
-                       retval = -ERESTARTSYS;
-                       break;
-               }
-               spin_unlock_irqrestore(&epca_lock, flags);
-               /*
-                * Allow someone else to be scheduled. We will occasionally go
-                * through this loop until one of the above conditions change.
-                * The below schedule call will allow other processes to enter
-                * and prevent this loop from hogging the cpu.
-                */
-               schedule();
-               spin_lock_irqsave(&epca_lock, flags);
-       }
-
-       __set_current_state(TASK_RUNNING);
-       remove_wait_queue(&ch->open_wait, &wait);
-       if (!tty_hung_up_p(filp))
-               ch->count++;
-       ch->blocked_open--;
-
-       spin_unlock_irqrestore(&epca_lock, flags);
-
-       if (retval)
-               return retval;
-
-       ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
+       struct channel *ch = container_of(port, struct channel, port);
+       if (ch->imodem & ch->dcd)
+               return 1;
        return 0;
 }
 
-static int pc_open(struct tty_struct *tty, struct file * filp)
+static void epca_dtr_rts(struct tty_port *port, int onoff)
+{
+}
+
+static int pc_open(struct tty_struct *tty, struct file *filp)
 {
        struct channel *ch;
+       struct tty_port *port;
        unsigned long flags;
        int line, retval, boardnum;
        struct board_chan __iomem *bc;
@@ -885,12 +765,13 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
                return -ENODEV;
 
        ch = &digi_channels[line];
+       port = &ch->port;
        boardnum = ch->boardnum;
 
        /* Check status of board configured in system.  */
 
        /*
-        * I check to see if the epca_setup routine detected an user error. It
+        * I check to see if the epca_setup routine detected a user error. It
         * might be better to put this in pc_init, but for the moment it goes
         * here.
         */
@@ -921,22 +802,24 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
                return -ENODEV;
        }
 
-       spin_lock_irqsave(&epca_lock, flags);
+       spin_lock_irqsave(&port->lock, flags);
        /*
         * Every time a channel is opened, increment a counter. This is
         * necessary because we do not wish to flush and shutdown the channel
         * until the last app holding the channel open, closes it.
         */
-       ch->count++;
+       port->count++;
        /*
         * Set a kernel structures pointer to our local channel structure. This
         * way we can get to it when passed only a tty struct.
         */
        tty->driver_data = ch;
+       port->tty = tty;
        /*
         * If this is the first time the channel has been opened, initialize
         * the tty->termios struct otherwise let pc_close handle it.
         */
+       spin_lock(&epca_lock);
        globalwinon(ch);
        ch->statusflags = 0;
 
@@ -951,31 +834,33 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
        writew(head, &bc->rout);
 
        /* Set the channels associated tty structure */
-       ch->tty = tty;
 
        /*
         * The below routine generally sets up parity, baud, flow control
         * issues, etc.... It effect both control flags and input flags.
         */
-       epcaparam(tty,ch);
-       ch->asyncflags |= ASYNC_INITIALIZED;
+       epcaparam(tty, ch);
        memoff(ch);
-       spin_unlock_irqrestore(&epca_lock, flags);
+       spin_unlock(&epca_lock);
+       port->flags |= ASYNC_INITIALIZED;
+       spin_unlock_irqrestore(&port->lock, flags);
 
-       retval = block_til_ready(tty, filp, ch);
+       retval = tty_port_block_til_ready(port, tty, filp);
        if (retval)
                return retval;
        /*
         * Set this again in case a hangup set it to zero while this open() was
         * waiting for the line...
         */
-       spin_lock_irqsave(&epca_lock, flags);
-       ch->tty = tty;
+       spin_lock_irqsave(&port->lock, flags);
+       port->tty = tty;
+       spin_lock(&epca_lock);
        globalwinon(ch);
        /* Enable Digi Data events */
        writeb(1, &bc->idata);
        memoff(ch);
-       spin_unlock_irqrestore(&epca_lock, flags);
+       spin_unlock(&epca_lock);
+       spin_unlock_irqrestore(&port->lock, flags);
        return 0;
 }
 
@@ -995,8 +880,8 @@ static void __exit epca_module_exit(void)
 
        del_timer_sync(&epca_timer);
 
-       if (tty_unregister_driver(pc_driver) || tty_unregister_driver(pc_info))
-       {
+       if (tty_unregister_driver(pc_driver) ||
+                               tty_unregister_driver(pc_info)) {
                printk(KERN_WARNING "epca: cleanup_module failed to un-register tty driver\n");
                return;
        }
@@ -1011,8 +896,11 @@ static void __exit epca_module_exit(void)
                }
                ch = card_ptr[crd];
                for (count = 0; count < bd->numports; count++, ch++) {
-                       if (ch && ch->tty)
-                               tty_hangup(ch->tty);
+                       struct tty_struct *tty = tty_port_tty_get(&ch->port);
+                       if (tty) {
+                               tty_hangup(tty);
+                               tty_kref_put(tty);
+                       }
                }
        }
        pci_unregister_driver(&epca_driver);
@@ -1034,14 +922,20 @@ static const struct tty_operations pc_ops = {
        .throttle = pc_throttle,
        .unthrottle = pc_unthrottle,
        .hangup = pc_hangup,
+       .break_ctl = pc_send_break
+};
+
+static const struct tty_port_operations epca_port_ops = {
+       .carrier_raised = epca_carrier_raised,
+       .dtr_rts = epca_dtr_rts,
 };
 
-static int info_open(struct tty_struct *tty, struct file * filp)
+static int info_open(struct tty_struct *tty, struct file *filp)
 {
        return 0;
 }
 
-static struct tty_operations info_ops = {
+static const struct tty_operations info_ops = {
        .open = info_open,
        .ioctl = info_ioctl,
 };
@@ -1091,7 +985,7 @@ static int __init pc_init(void)
         * Set up interrupt, we will worry about memory allocation in
         * post_fep_init.
         */
-       printk(KERN_INFO "DIGI epca driver version %s loaded.\n",VERSION);
+       printk(KERN_INFO "DIGI epca driver version %s loaded.\n", VERSION);
 
        /*
         * NOTE : This code assumes that the number of ports found in the
@@ -1126,7 +1020,7 @@ static int __init pc_init(void)
        pc_driver->init_termios.c_lflag = 0;
        pc_driver->init_termios.c_ispeed = 9600;
        pc_driver->init_termios.c_ospeed = 9600;
-       pc_driver->flags = TTY_DRIVER_REAL_RAW;
+       pc_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_HARDWARE_BREAK;
        tty_set_operations(pc_driver, &pc_ops);
 
        pc_info->owner = THIS_MODULE;
@@ -1244,7 +1138,7 @@ static int __init pc_init(void)
                                if ((board_id & 0x30) == 0x30)
                                        bd->memory_seg = 0x8000;
                        } else
-                               printk(KERN_ERR "epca: Board at 0x%x doesn't appear to be an XI\n",(int)bd->port);
+                               printk(KERN_ERR "epca: Board at 0x%x doesn't appear to be an XI\n", (int)bd->port);
                        break;
                }
        }
@@ -1318,12 +1212,12 @@ static void post_fep_init(unsigned int crd)
                 */
                /* PCI cards are already remapped at this point ISA are not */
                bd->numports = readw(bd->re_map_membase + XEMPORTS);
-               epcaassert(bd->numports <= 64,"PCI returned a invalid number of ports");
+               epcaassert(bd->numports <= 64, "PCI returned a invalid number of ports");
                nbdevs += (bd->numports);
        } else {
                /* Fix up the mappings for ISA/EISA etc */
                /* FIXME: 64K - can we be smarter ? */
-               bd->re_map_membase = ioremap(bd->membase, 0x10000);
+               bd->re_map_membase = ioremap_nocache(bd->membase, 0x10000);
        }
 
        if (crd != 0)
@@ -1354,7 +1248,8 @@ static void post_fep_init(unsigned int crd)
         * XEPORTS (address 0xc22) points at the number of channels the card
         * supports. (For 64XE, XI, XEM, and XR use 0xc02)
         */
-       if ((bd->type == PCXEVE || bd->type == PCXE) && (readw(memaddr + XEPORTS) < 3))
+       if ((bd->type == PCXEVE || bd->type == PCXE) &&
+                                       (readw(memaddr + XEPORTS) < 3))
                shrinkmem = 1;
        if (bd->type < PCIXEM)
                if (!request_region((int)bd->port, 4, board_desc[bd->type]))
@@ -1369,6 +1264,8 @@ static void post_fep_init(unsigned int crd)
                unsigned long flags;
                u16 tseg, rseg;
 
+               tty_port_init(&ch->port);
+               ch->port.ops = &epca_port_ops;
                ch->brdchan = bc;
                ch->mailbox = gd;
                INIT_WORK(&ch->tqueue, do_softint);
@@ -1420,7 +1317,7 @@ static void post_fep_init(unsigned int crd)
                ch->boardnum   = crd;
                ch->channelnum = i;
                ch->magic      = EPCA_MAGIC;
-               ch->tty        = NULL;
+               tty_port_tty_set(&ch->port, NULL);
 
                if (shrinkmem) {
                        fepcmd(ch, SETBUFFER, 32, 0, 0, 0);
@@ -1453,10 +1350,12 @@ static void post_fep_init(unsigned int crd)
 
                case PCXEVE:
                case PCXE:
-                       ch->txptr = memaddr + (((tseg - bd->memory_seg) << 4) & 0x1fff);
+                       ch->txptr = memaddr + (((tseg - bd->memory_seg) << 4)
+                                                               & 0x1fff);
                        ch->txwin = FEPWIN | ((tseg - bd->memory_seg) >> 9);
-                       ch->rxptr = memaddr + (((rseg - bd->memory_seg) << 4) & 0x1fff);
-                       ch->rxwin = FEPWIN | ((rseg - bd->memory_seg) >>9 );
+                       ch->rxptr = memaddr + (((rseg - bd->memory_seg) << 4)
+                                                               & 0x1fff);
+                       ch->rxwin = FEPWIN | ((rseg - bd->memory_seg) >> 9);
                        break;
 
                case PCXI:
@@ -1500,18 +1399,15 @@ static void post_fep_init(unsigned int crd)
                ch->fepstartca = 0;
                ch->fepstopca = 0;
 
-               ch->close_delay = 50;
-               ch->count = 0;
-               ch->blocked_open = 0;
-               init_waitqueue_head(&ch->open_wait);
-               init_waitqueue_head(&ch->close_wait);
+               ch->port.close_delay = 50;
 
                spin_unlock_irqrestore(&epca_lock, flags);
        }
 
        printk(KERN_INFO
-               "Digi PC/Xx Driver V%s:  %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n",
-               VERSION, board_desc[bd->type], (long)bd->port, (long)bd->membase, bd->numports);
+       "Digi PC/Xx Driver V%s:  %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n",
+                               VERSION, board_desc[bd->type], (long)bd->port,
+                                       (long)bd->membase, bd->numports);
        memwinoff(bd, 0);
 }
 
@@ -1519,7 +1415,7 @@ static void epcapoll(unsigned long ignored)
 {
        unsigned long flags;
        int crd;
-       volatile unsigned int head, tail;
+       unsigned int head, tail;
        struct channel *ch;
        struct board_info *bd;
 
@@ -1585,7 +1481,9 @@ static void doevent(int crd)
        chan0 = card_ptr[crd];
        epcaassert(chan0 <= &digi_channels[nbdevs - 1], "ch out of range");
        assertgwinon(chan0);
-       while ((tail = readw(&chan0->mailbox->eout)) != (head = readw(&chan0->mailbox->ein))) { /* Begin while something in event queue */
+       while ((tail = readw(&chan0->mailbox->eout)) !=
+                       (head = readw(&chan0->mailbox->ein))) {
+               /* Begin while something in event queue */
                assertgwinon(chan0);
                eventbuf = bd->re_map_membase + tail + ISTART;
                /* Get the channel the event occurred on */
@@ -1609,25 +1507,27 @@ static void doevent(int crd)
                        goto next;
                }
 
-               if ((bc = ch->brdchan) == NULL)
+               bc = ch->brdchan;
+               if (bc == NULL)
                        goto next;
 
+               tty = tty_port_tty_get(&ch->port);
                if (event & DATA_IND)  { /* Begin DATA_IND */
-                       receive_data(ch);
+                       receive_data(ch, tty);
                        assertgwinon(ch);
                } /* End DATA_IND */
                /* else *//* Fix for DCD transition missed bug */
                if (event & MODEMCHG_IND) {
                        /* A modem signal change has been indicated */
                        ch->imodem = mstat;
-                       if (ch->asyncflags & ASYNC_CHECK_CD) {
-                               if (mstat & ch->dcd)  /* We are now receiving dcd */
-                                       wake_up_interruptible(&ch->open_wait);
-                               else
-                                       pc_sched_event(ch, EPCA_EVENT_HANGUP); /* No dcd; hangup */
+                       if (test_bit(ASYNCB_CHECK_CD, &ch->port.flags)) {
+                               /* We are now receiving dcd */
+                               if (mstat & ch->dcd)
+                                       wake_up_interruptible(&ch->port.open_wait);
+                               else    /* No dcd; hangup */
+                                       pc_sched_event(ch, EPCA_EVENT_HANGUP);
                        }
                }
-               tty = ch->tty;
                if (tty) {
                        if (event & BREAK_IND) {
                                /* A break has been indicated */
@@ -1639,15 +1539,17 @@ static void doevent(int crd)
                                        tty_wakeup(tty);
                                }
                        } else if (event & EMPTYTX_IND) {
-                               /* This event is generated by setup_empty_event */
+                               /* This event is generated by
+                                  setup_empty_event */
                                ch->statusflags &= ~TXBUSY;
                                if (ch->statusflags & EMPTYWAIT) {
                                        ch->statusflags &= ~EMPTYWAIT;
                                        tty_wakeup(tty);
                                }
                        }
+                       tty_kref_put(tty);
                }
-       next:
+next:
                globalwinon(ch);
                BUG_ON(!bc);
                writew(1, &bc->idata);
@@ -1657,7 +1559,7 @@ static void doevent(int crd)
 }
 
 static void fepcmd(struct channel *ch, int cmd, int word_or_byte,
-                   int byte2, int ncmds, int bytecmd)
+                                       int byte2, int ncmds, int bytecmd)
 {
        unchar __iomem *memaddr;
        unsigned int head, cmdTail, cmdStart, cmdMax;
@@ -1682,8 +1584,10 @@ static void fepcmd(struct channel *ch, int cmd, int word_or_byte,
        memaddr = ch->board->re_map_membase;
 
        if (head >= (cmdMax - cmdStart) || (head & 03))  {
-               printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n", __LINE__,  cmd, head);
-               printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n", __LINE__,  cmdMax, cmdStart);
+               printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n",
+                                               __LINE__,  cmd, head);
+               printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n",
+                                               __LINE__,  cmdMax, cmdStart);
                return;
        }
        if (bytecmd)  {
@@ -1762,7 +1666,7 @@ static unsigned termios2digi_h(struct channel *ch, unsigned cflag)
 static unsigned termios2digi_i(struct channel *ch, unsigned iflag)
 {
        unsigned res = iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK |
-                               INPCK | ISTRIP|IXON|IXANY|IXOFF);
+                                       INPCK | ISTRIP | IXON | IXANY | IXOFF);
        if (ch->digiext.digi_flags & DIGI_AIXON)
                res |= IAIXON;
        return res;
@@ -1863,9 +1767,9 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch)
                 * that the driver will wait on carrier detect.
                 */
                if (ts->c_cflag & CLOCAL)
-                       ch->asyncflags &= ~ASYNC_CHECK_CD;
+                       clear_bit(ASYNCB_CHECK_CD, &ch->port.flags);
                else
-                       ch->asyncflags |= ASYNC_CHECK_CD;
+                       set_bit(ASYNCB_CHECK_CD, &ch->port.flags);
                mval = ch->m_dtr | ch->m_rts;
        } /* End CBAUD not detected */
        iflag = termios2digi_i(ch, ts->c_iflag);
@@ -1876,8 +1780,10 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch)
                 * Command sets channels iflag structure on the board. Such
                 * things as input soft flow control, handling of parity
                 * errors, and break handling are all set here.
+                *
+                * break handling, parity handling, input stripping,
+                * flow control chars
                 */
-               /* break handling, parity handling, input stripping, flow control chars */
                fepcmd(ch, SETIFLAGS, (unsigned int) ch->fepiflag, 0, 0, 0);
        }
        /*
@@ -1936,11 +1842,10 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch)
 }
 
 /* Caller holds lock */
-static void receive_data(struct channel *ch)
+static void receive_data(struct channel *ch, struct tty_struct *tty)
 {
        unchar *rptr;
        struct ktermios *ts = NULL;
-       struct tty_struct *tty;
        struct board_chan __iomem *bc;
        int dataToRead, wrapgap, bytesAvailable;
        unsigned int tail, head;
@@ -1953,7 +1858,6 @@ static void receive_data(struct channel *ch)
        globalwinon(ch);
        if (ch->statusflags & RXSTOPPED)
                return;
-       tty = ch->tty;
        if (tty)
                ts = tty->termios;
        bc = ch->brdchan;
@@ -1973,7 +1877,7 @@ static void receive_data(struct channel *ch)
                return;
 
        /* If CREAD bit is off or device not open, set TX tail to head */
-       if (!tty || !ts || !(ts->c_cflag & CREAD))  {
+       if (!tty || !ts || !(ts->c_cflag & CREAD)) {
                writew(head, &bc->rout);
                return;
        }
@@ -1983,18 +1887,21 @@ static void receive_data(struct channel *ch)
 
        if (readb(&bc->orun)) {
                writeb(0, &bc->orun);
-               printk(KERN_WARNING "epca; overrun! DigiBoard device %s\n",tty->name);
+               printk(KERN_WARNING "epca; overrun! DigiBoard device %s\n",
+                                                               tty->name);
                tty_insert_flip_char(tty, 0, TTY_OVERRUN);
        }
        rxwinon(ch);
-       while (bytesAvailable > 0)  { /* Begin while there is data on the card */
+       while (bytesAvailable > 0) {
+               /* Begin while there is data on the card */
                wrapgap = (head >= tail) ? head - tail : ch->rxbufsize - tail;
                /*
                 * Even if head has wrapped around only report the amount of
                 * data to be equal to the size - tail. Remember memcpy can't
                 * automaticly wrap around the receive buffer.
                 */
-               dataToRead = (wrapgap < bytesAvailable) ? wrapgap : bytesAvailable;
+               dataToRead = (wrapgap < bytesAvailable) ? wrapgap
+                                                       : bytesAvailable;
                /* Make sure we don't overflow the buffer */
                dataToRead = tty_prepare_flip_string(tty, &rptr, dataToRead);
                if (dataToRead == 0)
@@ -2010,7 +1917,7 @@ static void receive_data(struct channel *ch)
        globalwinon(ch);
        writew(tail, &bc->rout);
        /* Must be called with global data */
-       tty_schedule_flip(ch->tty);
+       tty_schedule_flip(tty);
 }
 
 static int info_ioctl(struct tty_struct *tty, struct file *file,
@@ -2078,7 +1985,7 @@ static int info_ioctl(struct tty_struct *tty, struct file *file,
 
 static int pc_tiocmget(struct tty_struct *tty, struct file *file)
 {
-       struct channel *ch = (struct channel *) tty->driver_data;
+       struct channel *ch = tty->driver_data;
        struct board_chan __iomem *bc;
        unsigned int mstat, mflag = 0;
        unsigned long flags;
@@ -2112,7 +2019,7 @@ static int pc_tiocmget(struct tty_struct *tty, struct file *file)
 static int pc_tiocmset(struct tty_struct *tty, struct file *file,
                       unsigned int set, unsigned int clear)
 {
-       struct channel *ch = (struct channel *) tty->driver_data;
+       struct channel *ch = tty->driver_data;
        unsigned long flags;
 
        if (!ch)
@@ -2145,59 +2052,28 @@ static int pc_tiocmset(struct tty_struct *tty, struct file *file,
         * The below routine generally sets up parity, baud, flow control
         * issues, etc.... It effect both control flags and input flags.
         */
-       epcaparam(tty,ch);
+       epcaparam(tty, ch);
        memoff(ch);
        spin_unlock_irqrestore(&epca_lock, flags);
        return 0;
 }
 
-static int pc_ioctl(struct tty_struct *tty, struct file * file,
-                   unsigned int cmd, unsigned long arg)
+static int pc_ioctl(struct tty_struct *tty, struct file *file,
+                                       unsigned int cmd, unsigned long arg)
 {
        digiflow_t dflow;
-       int retval;
        unsigned long flags;
        unsigned int mflag, mstat;
        unsigned char startc, stopc;
        struct board_chan __iomem *bc;
-       struct channel *ch = (struct channel *) tty->driver_data;
+       struct channel *ch = tty->driver_data;
        void __user *argp = (void __user *)arg;
 
        if (ch)
                bc = ch->brdchan;
        else
                return -EINVAL;
-
-       /*
-        * For POSIX compliance we need to add more ioctls. See tty_ioctl.c in
-        * /usr/src/linux/drivers/char for a good example. In particular think
-        * about adding TCSETAF, TCSETAW, TCSETA, TCSETSF, TCSETSW, TCSETS.
-        */
        switch (cmd) {
-       case TCSBRK:    /* SVID version: non-zero arg --> no break */
-               retval = tty_check_change(tty);
-               if (retval)
-                       return retval;
-               /* Setup an event to indicate when the transmit buffer empties */
-               spin_lock_irqsave(&epca_lock, flags);
-               setup_empty_event(tty,ch);
-               spin_unlock_irqrestore(&epca_lock, flags);
-               tty_wait_until_sent(tty, 0);
-               if (!arg)
-                       digi_send_break(ch, HZ / 4);    /* 1/4 second */
-               return 0;
-       case TCSBRKP:   /* support for POSIX tcsendbreak() */
-               retval = tty_check_change(tty);
-               if (retval)
-                       return retval;
-
-               /* Setup an event to indicate when the transmit buffer empties */
-               spin_lock_irqsave(&epca_lock, flags);
-               setup_empty_event(tty,ch);
-               spin_unlock_irqrestore(&epca_lock, flags);
-               tty_wait_until_sent(tty, 0);
-               digi_send_break(ch, arg ? arg*(HZ/10) : HZ/4);
-               return 0;
        case TIOCMODG:
                mflag = pc_tiocmget(tty, file);
                if (put_user(mflag, (unsigned long __user *)argp))
@@ -2232,15 +2108,16 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
        case DIGI_SETAF:
                lock_kernel();
                if (cmd == DIGI_SETAW) {
-                       /* Setup an event to indicate when the transmit buffer empties */
+                       /* Setup an event to indicate when the transmit
+                          buffer empties */
                        spin_lock_irqsave(&epca_lock, flags);
-                       setup_empty_event(tty,ch);
+                       setup_empty_event(tty, ch);
                        spin_unlock_irqrestore(&epca_lock, flags);
                        tty_wait_until_sent(tty, 0);
                } else {
                        /* ldisc lock already held in ioctl */
-                       if (tty->ldisc.flush_buffer)
-                               tty->ldisc.flush_buffer(tty);
+                       if (tty->ldisc->ops->flush_buffer)
+                               tty->ldisc->ops->flush_buffer(tty);
                }
                unlock_kernel();
                /* Fall Thru */
@@ -2264,7 +2141,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
                 * control issues, etc.... It effect both control flags and
                 * input flags.
                 */
-               epcaparam(tty,ch);
+               epcaparam(tty, ch);
                memoff(ch);
                spin_unlock_irqrestore(&epca_lock, flags);
                break;
@@ -2300,18 +2177,21 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
                if (copy_from_user(&dflow, argp, sizeof(dflow)))
                        return -EFAULT;
 
-               if (dflow.startc != startc || dflow.stopc != stopc) { /* Begin  if setflow toggled */
+               if (dflow.startc != startc || dflow.stopc != stopc) {
+                       /* Begin  if setflow toggled */
                        spin_lock_irqsave(&epca_lock, flags);
                        globalwinon(ch);
 
                        if (cmd == DIGI_SETFLOW) {
                                ch->fepstartc = ch->startc = dflow.startc;
                                ch->fepstopc = ch->stopc = dflow.stopc;
-                               fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1);
+                               fepcmd(ch, SONOFFC, ch->fepstartc,
+                                               ch->fepstopc, 0, 1);
                        } else {
                                ch->fepstartca = ch->startca = dflow.startc;
                                ch->fepstopca  = ch->stopca = dflow.stopc;
-                               fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1);
+                               fepcmd(ch, SAUXONOFFC, ch->fepstartca,
+                                               ch->fepstopca, 0, 1);
                        }
 
                        if (ch->statusflags & TXSTOPPED)
@@ -2335,7 +2215,9 @@ static void pc_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
         * verifyChannel returns the channel from the tty struct if it is
         * valid. This serves as a sanity check.
         */
-       if ((ch = verifyChannel(tty)) != NULL)  { /* Begin if channel valid */
+       ch = verifyChannel(tty);
+
+       if (ch != NULL)  { /* Begin if channel valid */
                spin_lock_irqsave(&epca_lock, flags);
                globalwinon(ch);
                epcaparam(tty, ch);
@@ -2348,7 +2230,7 @@ static void pc_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 
                if (!(old_termios->c_cflag & CLOCAL) &&
                         (tty->termios->c_cflag & CLOCAL))
-                       wake_up_interruptible(&ch->open_wait);
+                       wake_up_interruptible(&ch->port.open_wait);
 
        } /* End if channel valid */
 }
@@ -2358,15 +2240,17 @@ static void do_softint(struct work_struct *work)
        struct channel *ch = container_of(work, struct channel, tqueue);
        /* Called in response to a modem change event */
        if (ch && ch->magic == EPCA_MAGIC) {
-               struct tty_struct *tty = ch->tty;
+               struct tty_struct *tty = tty_port_tty_get(&ch->port);
 
                if (tty && tty->driver_data) {
                        if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) {
-                               tty_hangup(tty);        /* FIXME: module removal race here - AKPM */
-                               wake_up_interruptible(&ch->open_wait);
-                               ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE;
+                               tty_hangup(tty);
+                               wake_up_interruptible(&ch->port.open_wait);
+                               clear_bit(ASYNCB_NORMAL_ACTIVE,
+                                               &ch->port.flags);
                        }
                }
+               tty_kref_put(tty);
        }
 }
 
@@ -2382,9 +2266,11 @@ static void pc_stop(struct tty_struct *tty)
         * verifyChannel returns the channel from the tty struct if it is
         * valid. This serves as a sanity check.
         */
-       if ((ch = verifyChannel(tty)) != NULL) {
+       ch = verifyChannel(tty);
+       if (ch != NULL) {
                spin_lock_irqsave(&epca_lock, flags);
-               if ((ch->statusflags & TXSTOPPED) == 0) { /* Begin if transmit stop requested */
+               if ((ch->statusflags & TXSTOPPED) == 0) {
+                       /* Begin if transmit stop requested */
                        globalwinon(ch);
                        /* STOP transmitting now !! */
                        fepcmd(ch, PAUSETX, 0, 0, 0, 0);
@@ -2402,11 +2288,14 @@ static void pc_start(struct tty_struct *tty)
         * verifyChannel returns the channel from the tty struct if it is
         * valid. This serves as a sanity check.
         */
-       if ((ch = verifyChannel(tty)) != NULL) {
+       ch = verifyChannel(tty);
+       if (ch != NULL) {
                unsigned long flags;
                spin_lock_irqsave(&epca_lock, flags);
-               /* Just in case output was resumed because of a change in Digi-flow */
-               if (ch->statusflags & TXSTOPPED)  { /* Begin transmit resume requested */
+               /* Just in case output was resumed because of a change
+                  in Digi-flow */
+               if (ch->statusflags & TXSTOPPED)  {
+                       /* Begin transmit resume requested */
                        struct board_chan __iomem *bc;
                        globalwinon(ch);
                        bc = ch->brdchan;
@@ -2436,7 +2325,8 @@ static void pc_throttle(struct tty_struct *tty)
         * verifyChannel returns the channel from the tty struct if it is
         * valid. This serves as a sanity check.
         */
-       if ((ch = verifyChannel(tty)) != NULL) {
+       ch = verifyChannel(tty);
+       if (ch != NULL) {
                spin_lock_irqsave(&epca_lock, flags);
                if ((ch->statusflags & RXSTOPPED) == 0) {
                        globalwinon(ch);
@@ -2456,8 +2346,10 @@ static void pc_unthrottle(struct tty_struct *tty)
         * verifyChannel returns the channel from the tty struct if it is
         * valid. This serves as a sanity check.
         */
-       if ((ch = verifyChannel(tty)) != NULL) {
-               /* Just in case output was resumed because of a change in Digi-flow */
+       ch = verifyChannel(tty);
+       if (ch != NULL) {
+               /* Just in case output was resumed because of a change
+                  in Digi-flow */
                spin_lock_irqsave(&epca_lock, flags);
                if (ch->statusflags & RXSTOPPED) {
                        globalwinon(ch);
@@ -2469,10 +2361,18 @@ static void pc_unthrottle(struct tty_struct *tty)
        }
 }
 
-static void digi_send_break(struct channel *ch, int msec)
+static int pc_send_break(struct tty_struct *tty, int msec)
 {
+       struct channel *ch = tty->driver_data;
        unsigned long flags;
 
+       if (msec == -1)
+               msec = 0xFFFF;
+       else if (msec > 0xFFFE)
+               msec = 0xFFFE;
+       else if (msec < 1)
+               msec = 1;
+
        spin_lock_irqsave(&epca_lock, flags);
        globalwinon(ch);
        /*
@@ -2485,6 +2385,7 @@ static void digi_send_break(struct channel *ch, int msec)
        fepcmd(ch, SENDBREAK, msec, 0, 10, 0);
        memoff(ch);
        spin_unlock_irqrestore(&epca_lock, flags);
+       return 0;
 }
 
 /* Caller MUST hold the lock */
@@ -2502,7 +2403,8 @@ static void setup_empty_event(struct tty_struct *tty, struct channel *ch)
        memoff(ch);
 }
 
-void epca_setup(char *str, int *ints)
+#ifndef MODULE
+static void __init epca_setup(char *str, int *ints)
 {
        struct board_info board;
        int               index, loop, last;
@@ -2531,14 +2433,16 @@ void epca_setup(char *str, int *ints)
                         * instructing the driver to ignore epcaconfig.) For
                         * this reason we check for 2.
                         */
-                       if (board.status == 2) { /* Begin ignore epcaconfig as well as lilo cmd line */
+                       if (board.status == 2) {
+                       /* Begin ignore epcaconfig as well as lilo cmd line */
                                nbdevs = 0;
                                num_cards = 0;
                                return;
                        } /* End ignore epcaconfig as well as lilo cmd line */
 
                        if (board.status > 2) {
-                               printk(KERN_ERR "epca_setup: Invalid board status 0x%x\n", board.status);
+                               printk(KERN_ERR "epca_setup: Invalid board status 0x%x\n",
+                                               board.status);
                                invalid_lilo_config = 1;
                                setup_error_code |= INVALID_BOARD_STATUS;
                                return;
@@ -2592,7 +2496,8 @@ void epca_setup(char *str, int *ints)
                case 6:
                        board.membase = ints[index];
                        if (ints[index] <= 0) {
-                               printk(KERN_ERR "epca_setup: Invalid memory base 0x%x\n",(unsigned int)board.membase);
+                               printk(KERN_ERR "epca_setup: Invalid memory base 0x%x\n",
+                                       (unsigned int)board.membase);
                                invalid_lilo_config = 1;
                                setup_error_code |= INVALID_MEM_BASE;
                                return;
@@ -2723,7 +2628,7 @@ void epca_setup(char *str, int *ints)
                                t2++;
 
                        if (*t2) {
-                               printk(KERN_ERR "epca_setup: Invalid memory base %s\n",str);
+                               printk(KERN_ERR "epca_setup: Invalid memory base %s\n", str);
                                invalid_lilo_config = 1;
                                setup_error_code |= INVALID_MEM_BASE;
                                return;
@@ -2745,7 +2650,7 @@ void epca_setup(char *str, int *ints)
 
        /* I should REALLY validate the stuff here */
        /* Copies our local copy of board into boards */
-       memcpy((void *)&boards[num_cards],(void *)&board, sizeof(board));
+       memcpy((void *)&boards[num_cards], (void *)&board, sizeof(board));
        /* Does this get called once per lilo arg are what ? */
        printk(KERN_INFO "PC/Xx: Added board %i, %s %i ports at 0x%4.4X base 0x%6.6X\n",
                num_cards, board_desc[board.type],
@@ -2753,6 +2658,17 @@ void epca_setup(char *str, int *ints)
        num_cards++;
 }
 
+static int __init epca_real_setup(char *str)
+{
+       int ints[11];
+
+       epca_setup(get_options(str, 11, ints), ints);
+       return 1;
+}
+
+__setup("digiepca", epca_real_setup);
+#endif
+
 enum epic_board_types {
        brd_xr = 0,
        brd_xem,
@@ -2786,9 +2702,9 @@ static int __devinit epca_init_one(struct pci_dev *pdev,
        if (board_idx >= MAXBOARDS)
                goto err_out;
 
-       addr = pci_resource_start (pdev, epca_info_tbl[info_idx].bar_idx);
+       addr = pci_resource_start(pdev, epca_info_tbl[info_idx].bar_idx);
        if (!addr) {
-               printk (KERN_ERR PFX "PCI region #%d not available (size 0)\n",
+               printk(KERN_ERR PFX "PCI region #%d not available (size 0)\n",
                        epca_info_tbl[info_idx].bar_idx);
                goto err_out;
        }
@@ -2799,28 +2715,29 @@ static int __devinit epca_init_one(struct pci_dev *pdev,
        boards[board_idx].port = addr + PCI_IO_OFFSET;
        boards[board_idx].membase = addr;
 
-       if (!request_mem_region (addr + PCI_IO_OFFSET, 0x200000, "epca")) {
-               printk (KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n",
+       if (!request_mem_region(addr + PCI_IO_OFFSET, 0x200000, "epca")) {
+               printk(KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n",
                        0x200000, addr + PCI_IO_OFFSET);
                goto err_out;
        }
 
-       boards[board_idx].re_map_port = ioremap(addr + PCI_IO_OFFSET, 0x200000);
+       boards[board_idx].re_map_port = ioremap_nocache(addr + PCI_IO_OFFSET,
+                                                               0x200000);
        if (!boards[board_idx].re_map_port) {
-               printk (KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n",
+               printk(KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n",
                        0x200000, addr + PCI_IO_OFFSET);
                goto err_out_free_pciio;
        }
 
-       if (!request_mem_region (addr, 0x200000, "epca")) {
-               printk (KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n",
+       if (!request_mem_region(addr, 0x200000, "epca")) {
+               printk(KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n",
                        0x200000, addr);
                goto err_out_free_iounmap;
        }
 
-       boards[board_idx].re_map_membase = ioremap(addr, 0x200000);
+       boards[board_idx].re_map_membase = ioremap_nocache(addr, 0x200000);
        if (!boards[board_idx].re_map_membase) {
-               printk (KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n",
+               printk(KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n",
                        0x200000, addr + PCI_IO_OFFSET);
                goto err_out_free_memregion;
        }
@@ -2837,11 +2754,11 @@ static int __devinit epca_init_one(struct pci_dev *pdev,
        return 0;
 
 err_out_free_memregion:
-       release_mem_region (addr, 0x200000);
+       release_mem_region(addr, 0x200000);
 err_out_free_iounmap:
-       iounmap (boards[board_idx].re_map_port);
+       iounmap(boards[board_idx].re_map_port);
 err_out_free_pciio:
-       release_mem_region (addr + PCI_IO_OFFSET, 0x200000);
+       release_mem_region(addr + PCI_IO_OFFSET, 0x200000);
 err_out:
        return -ENODEV;
 }
@@ -2859,7 +2776,7 @@ MODULE_DEVICE_TABLE(pci, epca_pci_tbl);
 
 static int __init init_PCI(void)
 {
-       memset (&epca_driver, 0, sizeof (epca_driver));
+       memset(&epca_driver, 0, sizeof(epca_driver));
        epca_driver.name = "epca";
        epca_driver.id_table = epca_pci_tbl;
        epca_driver.probe = epca_init_one;