Staging: hv: move osd.h
[safe/jmp/linux-2.6] / drivers / char / cyclades.c
index 6bff9d8..2dafc2d 100644 (file)
 
 #define NR_PORTS       256
 
-#define ZE_V1_NPORTS   64
 #define ZO_V1  0
 #define ZO_V2  1
 #define ZE_V1  2
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/serial.h>
+#include <linux/smp_lock.h>
 #include <linux/major.h>
 #include <linux/string.h>
 #include <linux/fcntl.h>
 #include <linux/spinlock.h>
 #include <linux/bitops.h>
 #include <linux/firmware.h>
+#include <linux/device.h>
 
 #include <asm/system.h>
 #include <linux/io.h>
 
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 static void cy_throttle(struct tty_struct *tty);
 static void cy_send_xchar(struct tty_struct *tty, char ch);
 
-#define IS_CYC_Z(card) ((card).num_chips == (unsigned int)-1)
-
-#define Z_FPGA_CHECK(card) \
-       ((readl(&((struct RUNTIME_9060 __iomem *) \
-               ((card).ctl_addr))->init_ctrl) & (1<<17)) != 0)
-
-#define ISZLOADED(card)        (((ZO_V1 == readl(&((struct RUNTIME_9060 __iomem *) \
-                       ((card).ctl_addr))->mail_box_0)) || \
-                       Z_FPGA_CHECK(card)) && \
-                       (ZFIRM_ID == readl(&((struct FIRM_ID __iomem *) \
-                       ((card).base_addr+ID_ADDRESS))->signature)))
-
 #ifndef SERIAL_XMIT_SIZE
 #define        SERIAL_XMIT_SIZE        (min(PAGE_SIZE, 4096))
 #endif
@@ -685,8 +675,6 @@ static void cy_send_xchar(struct tty_struct *tty, char ch);
 #define DRIVER_VERSION 0x02010203
 #define RAM_SIZE 0x80000
 
-#define Z_FPGA_LOADED(X)       ((readl(&(X)->init_ctrl) & (1<<17)) != 0)
-
 enum zblock_type {
        ZBLOCK_PRG = 0,
        ZBLOCK_FPGA = 1
@@ -762,7 +750,7 @@ static int cy_next_channel; /* next minor available */
 /*
  * This is used to look up the divisor speeds and the timeouts
  * We're normally limited to 15 distinct baud rates.  The extra
- * are accessed via settings in info->flags.
+ * are accessed via settings in info->port.flags.
  *      0,     1,     2,     3,     4,     5,     6,     7,     8,     9,
  *     10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
  *                                               HI            VHI
@@ -868,8 +856,6 @@ static int cyz_issue_cmd(struct cyclades_card *, __u32, __u8, __u32);
 static unsigned detect_isa_irq(void __iomem *);
 #endif                         /* CONFIG_ISA */
 
-static int cyclades_get_proc_info(char *, char **, off_t, int, int *, void *);
-
 #ifndef CONFIG_CYZ_INTR
 static void cyz_poll(unsigned long);
 
@@ -883,6 +869,29 @@ static void cyz_rx_restart(unsigned long);
 static struct timer_list cyz_rx_full_timer[NR_PORTS];
 #endif                         /* CONFIG_CYZ_INTR */
 
+static inline bool cy_is_Z(struct cyclades_card *card)
+{
+       return card->num_chips == (unsigned int)-1;
+}
+
+static inline bool __cyz_fpga_loaded(struct RUNTIME_9060 __iomem *ctl_addr)
+{
+       return readl(&ctl_addr->init_ctrl) & (1 << 17);
+}
+
+static inline bool cyz_fpga_loaded(struct cyclades_card *card)
+{
+       return __cyz_fpga_loaded(card->ctl_addr.p9060);
+}
+
+static inline bool cyz_is_loaded(struct cyclades_card *card)
+{
+       struct FIRM_ID __iomem *fw_id = card->base_addr + ID_ADDRESS;
+
+       return (card->hw_ver == ZO_V1 || cyz_fpga_loaded(card)) &&
+                       readl(&fw_id->signature) == ZFIRM_ID;
+}
+
 static inline int serial_paranoia_check(struct cyclades_port *info,
                char *name, const char *routine)
 {
@@ -1003,7 +1012,7 @@ static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
        cy_writeb(base_addr + (CyCAR << index), save_xir);
 
        /* if there is nowhere to put the data, discard it */
-       if (info->tty == NULL) {
+       if (info->port.tty == NULL) {
                if ((readb(base_addr + (CyRIVR << index)) & CyIVRMask) ==
                                CyIVRRxEx) {    /* exception */
                        data = readb(base_addr + (CyRDSR << index));
@@ -1015,7 +1024,7 @@ static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
                goto end;
        }
        /* there is an open port for this data */
-       tty = info->tty;
+       tty = info->port.tty;
        if ((readb(base_addr + (CyRIVR << index)) & CyIVRMask) ==
                        CyIVRRxEx) {    /* exception */
                data = readb(base_addr + (CyRDSR << index));
@@ -1041,7 +1050,7 @@ static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
                                                readb(base_addr + (CyRDSR <<
                                                        index)), TTY_BREAK);
                                        info->icount.rx++;
-                                       if (info->flags & ASYNC_SAK)
+                                       if (info->port.flags & ASYNC_SAK)
                                                do_SAK(tty);
                                } else if (data & CyFRAME) {
                                        tty_insert_flip_char(tty,
@@ -1145,7 +1154,7 @@ static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip,
                goto end;
        }
        info = &cinfo->ports[channel + chip * 4];
-       if (info->tty == NULL) {
+       if (info->port.tty == NULL) {
                cy_writeb(base_addr + (CySRER << index),
                          readb(base_addr + (CySRER << index)) & ~CyTxRdy);
                goto end;
@@ -1190,13 +1199,13 @@ static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip,
                        }
                        goto done;
                }
-               if (info->xmit_buf == NULL) {
+               if (info->port.xmit_buf == NULL) {
                        cy_writeb(base_addr + (CySRER << index),
                                readb(base_addr + (CySRER << index)) &
                                        ~CyTxRdy);
                        goto done;
                }
-               if (info->tty->stopped || info->tty->hw_stopped) {
+               if (info->port.tty->stopped || info->port.tty->hw_stopped) {
                        cy_writeb(base_addr + (CySRER << index),
                                readb(base_addr + (CySRER << index)) &
                                        ~CyTxRdy);
@@ -1211,7 +1220,7 @@ static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip,
                 * character. This is necessary because there may not be room
                 * for the two chars needed to send a NULL.)
                 */
-               outch = info->xmit_buf[info->xmit_tail];
+               outch = info->port.xmit_buf[info->xmit_tail];
                if (outch) {
                        info->xmit_cnt--;
                        info->xmit_tail = (info->xmit_tail + 1) &
@@ -1232,7 +1241,7 @@ static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip,
        }
 
 done:
-       tty_wakeup(info->tty);
+       tty_wakeup(info->port.tty);
 end:
        /* end of service */
        cy_writeb(base_addr + (CyTIR << index), save_xir & 0x3f);
@@ -1256,7 +1265,7 @@ static void cyy_chip_modem(struct cyclades_card *cinfo, int chip,
        mdm_change = readb(base_addr + (CyMISR << index));
        mdm_status = readb(base_addr + (CyMSVR1 << index));
 
-       if (!info->tty)
+       if (!info->port.tty)
                goto end;
 
        if (mdm_change & CyANY_DELTA) {
@@ -1273,29 +1282,29 @@ static void cyy_chip_modem(struct cyclades_card *cinfo, int chip,
                wake_up_interruptible(&info->delta_msr_wait);
        }
 
-       if ((mdm_change & CyDCD) && (info->flags & ASYNC_CHECK_CD)) {
+       if ((mdm_change & CyDCD) && (info->port.flags & ASYNC_CHECK_CD)) {
                if (!(mdm_status & CyDCD)) {
-                       tty_hangup(info->tty);
-                       info->flags &= ~ASYNC_NORMAL_ACTIVE;
+                       tty_hangup(info->port.tty);
+                       info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
                }
-               wake_up_interruptible(&info->open_wait);
+               wake_up_interruptible(&info->port.open_wait);
        }
-       if ((mdm_change & CyCTS) && (info->flags & ASYNC_CTS_FLOW)) {
-               if (info->tty->hw_stopped) {
+       if ((mdm_change & CyCTS) && (info->port.flags & ASYNC_CTS_FLOW)) {
+               if (info->port.tty->hw_stopped) {
                        if (mdm_status & CyCTS) {
                                /* cy_start isn't used
                                   because... !!! */
-                               info->tty->hw_stopped = 0;
+                               info->port.tty->hw_stopped = 0;
                                cy_writeb(base_addr + (CySRER << index),
                                        readb(base_addr + (CySRER << index)) |
                                                CyTxRdy);
-                               tty_wakeup(info->tty);
+                               tty_wakeup(info->port.tty);
                        }
                } else {
                        if (!(mdm_status & CyCTS)) {
                                /* cy_stop isn't used
                                   because ... !!! */
-                               info->tty->hw_stopped = 1;
+                               info->port.tty->hw_stopped = 1;
                                cy_writeb(base_addr + (CySRER << index),
                                        readb(base_addr + (CySRER << index)) &
                                                ~CyTxRdy);
@@ -1395,19 +1404,15 @@ cyz_fetch_msg(struct cyclades_card *cinfo,
        unsigned long loc_doorbell;
 
        firm_id = cinfo->base_addr + ID_ADDRESS;
-       if (!ISZLOADED(*cinfo))
-               return -1;
        zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
        board_ctrl = &zfw_ctrl->board_ctrl;
 
-       loc_doorbell = readl(&((struct RUNTIME_9060 __iomem *)
-                                 (cinfo->ctl_addr))->loc_doorbell);
+       loc_doorbell = readl(&cinfo->ctl_addr.p9060->loc_doorbell);
        if (loc_doorbell) {
                *cmd = (char)(0xff & loc_doorbell);
                *channel = readl(&board_ctrl->fwcmd_channel);
                *param = (__u32) readl(&board_ctrl->fwcmd_param);
-               cy_writel(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->
-                         loc_doorbell, 0xffffffff);
+               cy_writel(&cinfo->ctl_addr.p9060->loc_doorbell, 0xffffffff);
                return 1;
        }
        return 0;
@@ -1424,15 +1429,14 @@ cyz_issue_cmd(struct cyclades_card *cinfo,
        unsigned int index;
 
        firm_id = cinfo->base_addr + ID_ADDRESS;
-       if (!ISZLOADED(*cinfo))
+       if (!cyz_is_loaded(cinfo))
                return -1;
 
        zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
        board_ctrl = &zfw_ctrl->board_ctrl;
 
        index = 0;
-       pci_doorbell =
-           &((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->pci_doorbell;
+       pci_doorbell = &cinfo->ctl_addr.p9060->pci_doorbell;
        while ((readl(pci_doorbell) & 0xff) != 0) {
                if (index++ == 1000)
                        return (int)(readl(pci_doorbell) & 0xff);
@@ -1449,7 +1453,7 @@ static void cyz_handle_rx(struct cyclades_port *info,
                struct BUF_CTRL __iomem *buf_ctrl)
 {
        struct cyclades_card *cinfo = info->card;
-       struct tty_struct *tty = info->tty;
+       struct tty_struct *tty = info->port.tty;
        unsigned int char_count;
        int len;
 #ifdef BLOCKMOVE
@@ -1542,7 +1546,7 @@ static void cyz_handle_tx(struct cyclades_port *info,
                struct BUF_CTRL __iomem *buf_ctrl)
 {
        struct cyclades_card *cinfo = info->card;
-       struct tty_struct *tty = info->tty;
+       struct tty_struct *tty = info->port.tty;
        u8 data;
        unsigned int char_count;
 #ifdef BLOCKMOVE
@@ -1585,7 +1589,7 @@ static void cyz_handle_tx(struct cyclades_port *info,
 
                        memcpy_toio((char *)(cinfo->base_addr + tx_bufaddr +
                                        tx_put),
-                                       &info->xmit_buf[info->xmit_tail],
+                                       &info->port.xmit_buf[info->xmit_tail],
                                        small_count);
 
                        tx_put = (tx_put + small_count) & (tx_bufsize - 1);
@@ -1597,7 +1601,7 @@ static void cyz_handle_tx(struct cyclades_port *info,
                }
 #else
                while (info->xmit_cnt && char_count) {
-                       data = info->xmit_buf[info->xmit_tail];
+                       data = info->port.xmit_buf[info->xmit_tail];
                        info->xmit_cnt--;
                        info->xmit_tail = (info->xmit_tail + 1) &
                                        (SERIAL_XMIT_SIZE - 1);
@@ -1624,10 +1628,8 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
        static struct BOARD_CTRL __iomem *board_ctrl;
        static struct CH_CTRL __iomem *ch_ctrl;
        static struct BUF_CTRL __iomem *buf_ctrl;
-       __u32 channel;
+       __u32 channel, param, fw_ver;
        __u8 cmd;
-       __u32 param;
-       __u32 hw_ver, fw_ver;
        int special_count;
        int delta_count;
 
@@ -1635,14 +1637,12 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
        zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
        board_ctrl = &zfw_ctrl->board_ctrl;
        fw_ver = readl(&board_ctrl->fw_version);
-       hw_ver = readl(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->
-                       mail_box_0);
 
        while (cyz_fetch_msg(cinfo, &channel, &cmd, &param) == 1) {
                special_count = 0;
                delta_count = 0;
                info = &cinfo->ports[channel];
-               tty = info->tty;
+               tty = info->port.tty;
                if (tty == NULL)
                        continue;
 
@@ -1668,15 +1668,15 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
                case C_CM_MDCD:
                        info->icount.dcd++;
                        delta_count++;
-                       if (info->flags & ASYNC_CHECK_CD) {
+                       if (info->port.flags & ASYNC_CHECK_CD) {
                                if ((fw_ver > 241 ? ((u_long) param) :
                                                readl(&ch_ctrl->rs_status)) &
                                                C_RS_DCD) {
-                                       wake_up_interruptible(&info->open_wait);
+                                       wake_up_interruptible(&info->port.open_wait);
                                } else {
-                                       tty_hangup(info->tty);
-                                       wake_up_interruptible(&info->open_wait);
-                                       info->flags &= ~ASYNC_NORMAL_ACTIVE;
+                                       tty_hangup(info->port.tty);
+                                       wake_up_interruptible(&info->port.open_wait);
+                                       info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
                                }
                        }
                        break;
@@ -1737,15 +1737,7 @@ static irqreturn_t cyz_interrupt(int irq, void *dev_id)
 {
        struct cyclades_card *cinfo = dev_id;
 
-       if (unlikely(cinfo == NULL)) {
-#ifdef CY_DEBUG_INTERRUPTS
-               printk(KERN_DEBUG "cyz_interrupt: spurious interrupt %d\n",
-                                                                       irq);
-#endif
-               return IRQ_NONE;        /* spurious interrupt */
-       }
-
-       if (unlikely(!ISZLOADED(*cinfo))) {
+       if (unlikely(!cyz_is_loaded(cinfo))) {
 #ifdef CY_DEBUG_INTERRUPTS
                printk(KERN_DEBUG "cyz_interrupt: board not yet loaded "
                                "(IRQ%d).\n", irq);
@@ -1785,7 +1777,6 @@ static void cyz_poll(unsigned long arg)
        struct tty_struct *tty;
        struct FIRM_ID __iomem *firm_id;
        struct ZFW_CTRL __iomem *zfw_ctrl;
-       struct BOARD_CTRL __iomem *board_ctrl;
        struct BUF_CTRL __iomem *buf_ctrl;
        unsigned long expires = jiffies + HZ;
        unsigned int port, card;
@@ -1793,19 +1784,17 @@ static void cyz_poll(unsigned long arg)
        for (card = 0; card < NR_CARDS; card++) {
                cinfo = &cy_card[card];
 
-               if (!IS_CYC_Z(*cinfo))
+               if (!cy_is_Z(cinfo))
                        continue;
-               if (!ISZLOADED(*cinfo))
+               if (!cyz_is_loaded(cinfo))
                        continue;
 
                firm_id = cinfo->base_addr + ID_ADDRESS;
                zfw_ctrl = cinfo->base_addr +
                                (readl(&firm_id->zfwctrl_addr) & 0xfffff);
-               board_ctrl = &(zfw_ctrl->board_ctrl);
 
        /* Skip first polling cycle to avoid racing conditions with the FW */
                if (!cinfo->intr_enabled) {
-                       cinfo->nports = (int)readl(&board_ctrl->n_channel);
                        cinfo->intr_enabled = 1;
                        continue;
                }
@@ -1814,7 +1803,7 @@ static void cyz_poll(unsigned long arg)
 
                for (port = 0; port < cinfo->nports; port++) {
                        info = &cinfo->ports[port];
-                       tty = info->tty;
+                       tty = info->port.tty;
                        buf_ctrl = &(zfw_ctrl->buf_ctrl[port]);
 
                        if (!info->throttle)
@@ -1853,28 +1842,28 @@ static int startup(struct cyclades_port *info)
 
        spin_lock_irqsave(&card->card_lock, flags);
 
-       if (info->flags & ASYNC_INITIALIZED) {
+       if (info->port.flags & ASYNC_INITIALIZED) {
                free_page(page);
                goto errout;
        }
 
        if (!info->type) {
-               if (info->tty)
-                       set_bit(TTY_IO_ERROR, &info->tty->flags);
+               if (info->port.tty)
+                       set_bit(TTY_IO_ERROR, &info->port.tty->flags);
                free_page(page);
                goto errout;
        }
 
-       if (info->xmit_buf)
+       if (info->port.xmit_buf)
                free_page(page);
        else
-               info->xmit_buf = (unsigned char *)page;
+               info->port.xmit_buf = (unsigned char *)page;
 
        spin_unlock_irqrestore(&card->card_lock, flags);
 
        set_line_char(info);
 
-       if (!IS_CYC_Z(*card)) {
+       if (!cy_is_Z(card)) {
                chip = channel >> 2;
                channel &= 0x03;
                index = card->bus_index;
@@ -1909,10 +1898,10 @@ static int startup(struct cyclades_port *info)
 
                cy_writeb(base_addr + (CySRER << index),
                        readb(base_addr + (CySRER << index)) | CyRxData);
-               info->flags |= ASYNC_INITIALIZED;
+               info->port.flags |= ASYNC_INITIALIZED;
 
-               if (info->tty)
-                       clear_bit(TTY_IO_ERROR, &info->tty->flags);
+               if (info->port.tty)
+                       clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
                info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
                info->breakon = info->breakoff = 0;
                memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
@@ -1931,7 +1920,7 @@ static int startup(struct cyclades_port *info)
                base_addr = card->base_addr;
 
                firm_id = base_addr + ID_ADDRESS;
-               if (!ISZLOADED(*card))
+               if (!cyz_is_loaded(card))
                        return -ENODEV;
 
                zfw_ctrl = card->base_addr +
@@ -1994,9 +1983,9 @@ static int startup(struct cyclades_port *info)
 
                /* enable send, recv, modem !!! */
 
-               info->flags |= ASYNC_INITIALIZED;
-               if (info->tty)
-                       clear_bit(TTY_IO_ERROR, &info->tty->flags);
+               info->port.flags |= ASYNC_INITIALIZED;
+               if (info->port.tty)
+                       clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
                info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
                info->breakon = info->breakoff = 0;
                memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
@@ -2026,7 +2015,7 @@ static void start_xmit(struct cyclades_port *info)
 
        card = info->card;
        channel = info->line - card->first_line;
-       if (!IS_CYC_Z(*card)) {
+       if (!cy_is_Z(card)) {
                chip = channel >> 2;
                channel &= 0x03;
                index = card->bus_index;
@@ -2065,12 +2054,12 @@ static void shutdown(struct cyclades_port *info)
        void __iomem *base_addr;
        int chip, channel, index;
 
-       if (!(info->flags & ASYNC_INITIALIZED))
+       if (!(info->port.flags & ASYNC_INITIALIZED))
                return;
 
        card = info->card;
        channel = info->line - card->first_line;
-       if (!IS_CYC_Z(*card)) {
+       if (!cy_is_Z(card)) {
                chip = channel >> 2;
                channel &= 0x03;
                index = card->bus_index;
@@ -2087,14 +2076,14 @@ static void shutdown(struct cyclades_port *info)
                /* Clear delta_msr_wait queue to avoid mem leaks. */
                wake_up_interruptible(&info->delta_msr_wait);
 
-               if (info->xmit_buf) {
+               if (info->port.xmit_buf) {
                        unsigned char *temp;
-                       temp = info->xmit_buf;
-                       info->xmit_buf = NULL;
+                       temp = info->port.xmit_buf;
+                       info->port.xmit_buf = NULL;
                        free_page((unsigned long)temp);
                }
                cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
-               if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
+               if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) {
                        cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS);
                        cy_writeb(base_addr + (CyMSVR2 << index), ~CyDTR);
 #ifdef CY_DEBUG_DTR
@@ -2108,9 +2097,9 @@ static void shutdown(struct cyclades_port *info)
                /* it may be appropriate to clear _XMIT at
                   some later date (after testing)!!! */
 
-               if (info->tty)
-                       set_bit(TTY_IO_ERROR, &info->tty->flags);
-               info->flags &= ~ASYNC_INITIALIZED;
+               if (info->port.tty)
+                       set_bit(TTY_IO_ERROR, &info->port.tty->flags);
+               info->port.flags &= ~ASYNC_INITIALIZED;
                spin_unlock_irqrestore(&card->card_lock, flags);
        } else {
                struct FIRM_ID __iomem *firm_id;
@@ -2126,7 +2115,7 @@ static void shutdown(struct cyclades_port *info)
 #endif
 
                firm_id = base_addr + ID_ADDRESS;
-               if (!ISZLOADED(*card))
+               if (!cyz_is_loaded(card))
                        return;
 
                zfw_ctrl = card->base_addr +
@@ -2136,14 +2125,14 @@ static void shutdown(struct cyclades_port *info)
 
                spin_lock_irqsave(&card->card_lock, flags);
 
-               if (info->xmit_buf) {
+               if (info->port.xmit_buf) {
                        unsigned char *temp;
-                       temp = info->xmit_buf;
-                       info->xmit_buf = NULL;
+                       temp = info->port.xmit_buf;
+                       info->port.xmit_buf = NULL;
                        free_page((unsigned long)temp);
                }
 
-               if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
+               if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) {
                        cy_writel(&ch_ctrl[channel].rs_control,
                                (__u32)(readl(&ch_ctrl[channel].rs_control) &
                                        ~(C_RS_RTS | C_RS_DTR)));
@@ -2158,9 +2147,9 @@ static void shutdown(struct cyclades_port *info)
 #endif
                }
 
-               if (info->tty)
-                       set_bit(TTY_IO_ERROR, &info->tty->flags);
-               info->flags &= ~ASYNC_INITIALIZED;
+               if (info->port.tty)
+                       set_bit(TTY_IO_ERROR, &info->port.tty->flags);
+               info->port.flags &= ~ASYNC_INITIALIZED;
 
                spin_unlock_irqrestore(&card->card_lock, flags);
        }
@@ -2194,10 +2183,10 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
         * If the device is in the middle of being closed, then block
         * until it's done, and then try again.
         */
-       if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) {
-               wait_event_interruptible(info->close_wait,
-                               !(info->flags & ASYNC_CLOSING));
-               return (info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
+       if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) {
+               wait_event_interruptible(info->port.close_wait,
+                               !(info->port.flags & ASYNC_CLOSING));
+               return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
        }
 
        /*
@@ -2206,34 +2195,34 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
         */
        if ((filp->f_flags & O_NONBLOCK) ||
                                        (tty->flags & (1 << TTY_IO_ERROR))) {
-               info->flags |= ASYNC_NORMAL_ACTIVE;
+               info->port.flags |= ASYNC_NORMAL_ACTIVE;
                return 0;
        }
 
        /*
         * Block waiting for the carrier detect and the line to become
         * free (i.e., not in use by the callout).  While we are in
-        * this loop, info->count is dropped by one, so that
+        * this loop, info->port.count is dropped by one, so that
         * cy_close() knows when to free things.  We restore it upon
         * exit, either normal or abnormal.
         */
        retval = 0;
-       add_wait_queue(&info->open_wait, &wait);
+       add_wait_queue(&info->port.open_wait, &wait);
 #ifdef CY_DEBUG_OPEN
        printk(KERN_DEBUG "cyc block_til_ready before block: ttyC%d, "
-               "count = %d\n", info->line, info->count);
+               "count = %d\n", info->line, info->port.count);
 #endif
        spin_lock_irqsave(&cinfo->card_lock, flags);
        if (!tty_hung_up_p(filp))
-               info->count--;
+               info->port.count--;
        spin_unlock_irqrestore(&cinfo->card_lock, flags);
 #ifdef CY_DEBUG_COUNT
        printk(KERN_DEBUG "cyc block_til_ready: (%d): decrementing count to "
-               "%d\n", current->pid, info->count);
+               "%d\n", current->pid, info->port.count);
 #endif
-       info->blocked_open++;
+       info->port.blocked_open++;
 
-       if (!IS_CYC_Z(*cinfo)) {
+       if (!cy_is_Z(cinfo)) {
                chip = channel >> 2;
                channel &= 0x03;
                index = cinfo->bus_index;
@@ -2260,8 +2249,8 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
 
                        set_current_state(TASK_INTERRUPTIBLE);
                        if (tty_hung_up_p(filp) ||
-                                       !(info->flags & ASYNC_INITIALIZED)) {
-                               retval = ((info->flags & ASYNC_HUP_NOTIFY) ?
+                                       !(info->port.flags & ASYNC_INITIALIZED)) {
+                               retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
                                          -EAGAIN : -ERESTARTSYS);
                                break;
                        }
@@ -2269,7 +2258,7 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
                        spin_lock_irqsave(&cinfo->card_lock, flags);
                        cy_writeb(base_addr + (CyCAR << index),
                                  (u_char) channel);
-                       if (!(info->flags & ASYNC_CLOSING) && (C_CLOCAL(tty) ||
+                       if (!(info->port.flags & ASYNC_CLOSING) && (C_CLOCAL(tty) ||
                                        (readb(base_addr +
                                                (CyMSVR1 << index)) & CyDCD))) {
                                spin_unlock_irqrestore(&cinfo->card_lock, flags);
@@ -2284,7 +2273,7 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
 #ifdef CY_DEBUG_OPEN
                        printk(KERN_DEBUG "cyc block_til_ready blocking: "
                                "ttyC%d, count = %d\n",
-                               info->line, info->count);
+                               info->line, info->port.count);
 #endif
                        schedule();
                }
@@ -2296,9 +2285,9 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
 
                base_addr = cinfo->base_addr;
                firm_id = base_addr + ID_ADDRESS;
-               if (!ISZLOADED(*cinfo)) {
+               if (!cyz_is_loaded(cinfo)) {
                        __set_current_state(TASK_RUNNING);
-                       remove_wait_queue(&info->open_wait, &wait);
+                       remove_wait_queue(&info->port.open_wait, &wait);
                        return -EINVAL;
                }
 
@@ -2327,12 +2316,12 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
 
                        set_current_state(TASK_INTERRUPTIBLE);
                        if (tty_hung_up_p(filp) ||
-                                       !(info->flags & ASYNC_INITIALIZED)) {
-                               retval = ((info->flags & ASYNC_HUP_NOTIFY) ?
+                                       !(info->port.flags & ASYNC_INITIALIZED)) {
+                               retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
                                          -EAGAIN : -ERESTARTSYS);
                                break;
                        }
-                       if (!(info->flags & ASYNC_CLOSING) && (C_CLOCAL(tty) ||
+                       if (!(info->port.flags & ASYNC_CLOSING) && (C_CLOCAL(tty) ||
                                        (readl(&ch_ctrl[channel].rs_status) &
                                                C_RS_DCD))) {
                                break;
@@ -2344,28 +2333,28 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
 #ifdef CY_DEBUG_OPEN
                        printk(KERN_DEBUG "cyc block_til_ready blocking: "
                                "ttyC%d, count = %d\n",
-                               info->line, info->count);
+                               info->line, info->port.count);
 #endif
                        schedule();
                }
        }
        __set_current_state(TASK_RUNNING);
-       remove_wait_queue(&info->open_wait, &wait);
+       remove_wait_queue(&info->port.open_wait, &wait);
        if (!tty_hung_up_p(filp)) {
-               info->count++;
+               info->port.count++;
 #ifdef CY_DEBUG_COUNT
                printk(KERN_DEBUG "cyc:block_til_ready (%d): incrementing "
-                       "count to %d\n", current->pid, info->count);
+                       "count to %d\n", current->pid, info->port.count);
 #endif
        }
-       info->blocked_open--;
+       info->port.blocked_open--;
 #ifdef CY_DEBUG_OPEN
        printk(KERN_DEBUG "cyc:block_til_ready after blocking: ttyC%d, "
-               "count = %d\n", info->line, info->count);
+               "count = %d\n", info->line, info->port.count);
 #endif
        if (retval)
                return retval;
-       info->flags |= ASYNC_NORMAL_ACTIVE;
+       info->port.flags |= ASYNC_NORMAL_ACTIVE;
        return 0;
 }                              /* block_til_ready */
 
@@ -2397,16 +2386,14 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
           treat it as absent from the system.  This
           will make the user pay attention.
         */
-       if (IS_CYC_Z(*info->card)) {
+       if (cy_is_Z(info->card)) {
                struct cyclades_card *cinfo = info->card;
                struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS;
 
-               if (!ISZLOADED(*cinfo)) {
-                       if (((ZE_V1 == readl(&((struct RUNTIME_9060 __iomem *)
-                                        (cinfo->ctl_addr))->mail_box_0)) &&
-                                       Z_FPGA_CHECK(*cinfo)) &&
-                                       (ZFIRM_HLT == readl(
-                                               &firm_id->signature))) {
+               if (!cyz_is_loaded(cinfo)) {
+                       if (cinfo->hw_ver == ZE_V1 && cyz_fpga_loaded(cinfo) &&
+                                       readl(&firm_id->signature) ==
+                                       ZFIRM_HLT) {
                                printk(KERN_ERR "cyc:Cyclades-Z Error: you "
                                        "need an external power supply for "
                                        "this number of ports.\nFirmware "
@@ -2423,18 +2410,13 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
                   interrupts should be enabled as soon as the first open
                   happens to one of its ports. */
                        if (!cinfo->intr_enabled) {
-                               struct ZFW_CTRL __iomem *zfw_ctrl;
-                               struct BOARD_CTRL __iomem *board_ctrl;
-
-                               zfw_ctrl = cinfo->base_addr +
-                                       (readl(&firm_id->zfwctrl_addr) &
-                                        0xfffff);
-
-                               board_ctrl = &zfw_ctrl->board_ctrl;
+                               u16 intr;
 
                                /* Enable interrupts on the PLX chip */
-                               cy_writew(cinfo->ctl_addr + 0x68,
-                                       readw(cinfo->ctl_addr + 0x68) | 0x0900);
+                               intr = readw(&cinfo->ctl_addr.p9060->
+                                               intr_ctrl_stat) | 0x0900;
+                               cy_writew(&cinfo->ctl_addr.p9060->
+                                               intr_ctrl_stat, intr);
                                /* Enable interrupts on the FW */
                                retval = cyz_issue_cmd(cinfo, 0,
                                                C_CM_IRQ_ENBL, 0L);
@@ -2442,8 +2424,6 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
                                        printk(KERN_ERR "cyc:IRQ enable retval "
                                                "was %x\n", retval);
                                }
-                               cinfo->nports =
-                                       (int)readl(&board_ctrl->n_channel);
                                cinfo->intr_enabled = 1;
                        }
                }
@@ -2456,27 +2436,27 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
        printk(KERN_DEBUG "cyc:cy_open ttyC%d\n", info->line);
 #endif
        tty->driver_data = info;
-       info->tty = tty;
+       info->port.tty = tty;
        if (serial_paranoia_check(info, tty->name, "cy_open"))
                return -ENODEV;
 
 #ifdef CY_DEBUG_OPEN
        printk(KERN_DEBUG "cyc:cy_open ttyC%d, count = %d\n", info->line,
-                       info->count);
+                       info->port.count);
 #endif
-       info->count++;
+       info->port.count++;
 #ifdef CY_DEBUG_COUNT
        printk(KERN_DEBUG "cyc:cy_open (%d): incrementing count to %d\n",
-               current->pid, info->count);
+               current->pid, info->port.count);
 #endif
 
        /*
         * If the port is the middle of closing, bail out now
         */
-       if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) {
-               wait_event_interruptible(info->close_wait,
-                               !(info->flags & ASYNC_CLOSING));
-               return (info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
+       if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) {
+               wait_event_interruptible(info->port.close_wait,
+                               !(info->port.flags & ASYNC_CLOSING));
+               return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
        }
 
        /*
@@ -2556,7 +2536,7 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
 #endif
        card = info->card;
        channel = (info->line) - (card->first_line);
-       if (!IS_CYC_Z(*card)) {
+       if (!cy_is_Z(card)) {
                chip = channel >> 2;
                channel &= 0x03;
                index = card->bus_index;
@@ -2601,7 +2581,7 @@ static void cy_flush_buffer(struct tty_struct *tty)
        info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
        spin_unlock_irqrestore(&card->card_lock, flags);
 
-       if (IS_CYC_Z(*card)) {  /* If it is a Z card, flush the on-board
+       if (cy_is_Z(card)) {    /* If it is a Z card, flush the on-board
                                           buffers as well */
                spin_lock_irqsave(&card->card_lock, flags);
                retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L);
@@ -2641,9 +2621,9 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
        }
 #ifdef CY_DEBUG_OPEN
        printk(KERN_DEBUG "cyc:cy_close ttyC%d, count = %d\n", info->line,
-               info->count);
+               info->port.count);
 #endif
-       if ((tty->count == 1) && (info->count != 1)) {
+       if ((tty->count == 1) && (info->port.count != 1)) {
                /*
                 * Uh, oh.  tty->count is 1, which means that the tty
                 * structure will be freed.  Info->count should always
@@ -2652,24 +2632,24 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
                 * serial port won't be shutdown.
                 */
                printk(KERN_ERR "cyc:cy_close: bad serial port count; "
-                       "tty->count is 1, info->count is %d\n", info->count);
-               info->count = 1;
+                       "tty->count is 1, info->port.count is %d\n", info->port.count);
+               info->port.count = 1;
        }
 #ifdef CY_DEBUG_COUNT
        printk(KERN_DEBUG  "cyc:cy_close at (%d): decrementing count to %d\n",
-               current->pid, info->count - 1);
+               current->pid, info->port.count - 1);
 #endif
-       if (--info->count < 0) {
+       if (--info->port.count < 0) {
 #ifdef CY_DEBUG_COUNT
                printk(KERN_DEBUG "cyc:cyc_close setting count to 0\n");
 #endif
-               info->count = 0;
+               info->port.count = 0;
        }
-       if (info->count) {
+       if (info->port.count) {
                spin_unlock_irqrestore(&card->card_lock, flags);
                return;
        }
-       info->flags |= ASYNC_CLOSING;
+       info->port.flags |= ASYNC_CLOSING;
 
        /*
         * Now we wait for the transmit buffer to clear; and we notify
@@ -2677,12 +2657,12 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
         */
        tty->closing = 1;
        spin_unlock_irqrestore(&card->card_lock, flags);
-       if (info->closing_wait != CY_CLOSING_WAIT_NONE)
-               tty_wait_until_sent(tty, info->closing_wait);
+       if (info->port.closing_wait != CY_CLOSING_WAIT_NONE)
+               tty_wait_until_sent(tty, info->port.closing_wait);
 
        spin_lock_irqsave(&card->card_lock, flags);
 
-       if (!IS_CYC_Z(*card)) {
+       if (!cy_is_Z(card)) {
                int channel = info->line - card->first_line;
                int index = card->bus_index;
                void __iomem *base_addr = card->base_addr +
@@ -2692,7 +2672,7 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
                cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
                cy_writeb(base_addr + (CySRER << index),
                          readb(base_addr + (CySRER << index)) & ~CyRxData);
-               if (info->flags & ASYNC_INITIALIZED) {
+               if (info->port.flags & ASYNC_INITIALIZED) {
                        /* Waiting for on-board buffers to be empty before
                           closing the port */
                        spin_unlock_irqrestore(&card->card_lock, flags);
@@ -2731,18 +2711,18 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
        spin_lock_irqsave(&card->card_lock, flags);
 
        tty->closing = 0;
-       info->tty = NULL;
-       if (info->blocked_open) {
+       info->port.tty = NULL;
+       if (info->port.blocked_open) {
                spin_unlock_irqrestore(&card->card_lock, flags);
-               if (info->close_delay) {
+               if (info->port.close_delay) {
                        msleep_interruptible(jiffies_to_msecs
-                                               (info->close_delay));
+                                               (info->port.close_delay));
                }
-               wake_up_interruptible(&info->open_wait);
+               wake_up_interruptible(&info->port.open_wait);
                spin_lock_irqsave(&card->card_lock, flags);
        }
-       info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
-       wake_up_interruptible(&info->close_wait);
+       info->port.flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
+       wake_up_interruptible(&info->port.close_wait);
 
 #ifdef CY_DEBUG_OTHER
        printk(KERN_DEBUG "cyc:cy_close done\n");
@@ -2777,7 +2757,7 @@ static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
        if (serial_paranoia_check(info, tty->name, "cy_write"))
                return 0;
 
-       if (!info->xmit_buf)
+       if (!info->port.xmit_buf)
                return 0;
 
        spin_lock_irqsave(&info->card->card_lock, flags);
@@ -2788,7 +2768,7 @@ static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
                if (c <= 0)
                        break;
 
-               memcpy(info->xmit_buf + info->xmit_head, buf, c);
+               memcpy(info->port.xmit_buf + info->xmit_head, buf, c);
                info->xmit_head = (info->xmit_head + c) &
                        (SERIAL_XMIT_SIZE - 1);
                info->xmit_cnt += c;
@@ -2826,7 +2806,7 @@ static int cy_put_char(struct tty_struct *tty, unsigned char ch)
        if (serial_paranoia_check(info, tty->name, "cy_put_char"))
                return 0;
 
-       if (!info->xmit_buf)
+       if (!info->port.xmit_buf)
                return 0;
 
        spin_lock_irqsave(&info->card->card_lock, flags);
@@ -2835,7 +2815,7 @@ static int cy_put_char(struct tty_struct *tty, unsigned char ch)
                return 0;
        }
 
-       info->xmit_buf[info->xmit_head++] = ch;
+       info->port.xmit_buf[info->xmit_head++] = ch;
        info->xmit_head &= SERIAL_XMIT_SIZE - 1;
        info->xmit_cnt++;
        info->idle_stats.xmit_bytes++;
@@ -2860,7 +2840,7 @@ static void cy_flush_chars(struct tty_struct *tty)
                return;
 
        if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
-                       !info->xmit_buf)
+                       !info->port.xmit_buf)
                return;
 
        start_xmit(info);
@@ -2902,7 +2882,7 @@ static int cy_chars_in_buffer(struct tty_struct *tty)
        channel = (info->line) - (card->first_line);
 
 #ifdef Z_EXT_CHARS_IN_BUFFER
-       if (!IS_CYC_Z(cy_card[card])) {
+       if (!cy_is_Z(card)) {
 #endif                         /* Z_EXT_CHARS_IN_BUFFER */
 #ifdef CY_DEBUG_IO
                printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n",
@@ -2984,44 +2964,42 @@ static void set_line_char(struct cyclades_port *info)
        void __iomem *base_addr;
        int chip, channel, index;
        unsigned cflag, iflag;
-       unsigned short chip_number;
        int baud, baud_rate = 0;
        int i;
 
-       if (!info->tty || !info->tty->termios)
+       if (!info->port.tty || !info->port.tty->termios)
                return;
 
        if (info->line == -1)
                return;
 
-       cflag = info->tty->termios->c_cflag;
-       iflag = info->tty->termios->c_iflag;
+       cflag = info->port.tty->termios->c_cflag;
+       iflag = info->port.tty->termios->c_iflag;
 
        /*
         * Set up the tty->alt_speed kludge
         */
-       if (info->tty) {
-               if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-                       info->tty->alt_speed = 57600;
-               if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-                       info->tty->alt_speed = 115200;
-               if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-                       info->tty->alt_speed = 230400;
-               if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-                       info->tty->alt_speed = 460800;
+       if (info->port.tty) {
+               if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+                       info->port.tty->alt_speed = 57600;
+               if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+                       info->port.tty->alt_speed = 115200;
+               if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+                       info->port.tty->alt_speed = 230400;
+               if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+                       info->port.tty->alt_speed = 460800;
        }
 
        card = info->card;
        channel = info->line - card->first_line;
-       chip_number = channel / 4;
 
-       if (!IS_CYC_Z(*card)) {
+       if (!cy_is_Z(card)) {
 
                index = card->bus_index;
 
                /* baud rate */
-               baud = tty_get_baud_rate(info->tty);
-               if (baud == 38400 && (info->flags & ASYNC_SPD_MASK) ==
+               baud = tty_get_baud_rate(info->port.tty);
+               if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
                                ASYNC_SPD_CUST) {
                        if (info->custom_divisor)
                                baud_rate = info->baud / info->custom_divisor;
@@ -3038,7 +3016,7 @@ static void set_line_char(struct cyclades_port *info)
                if (i == 20)
                        i = 19; /* CD1400_MAX_SPEED */
 
-               if (baud == 38400 && (info->flags & ASYNC_SPD_MASK) ==
+               if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
                                ASYNC_SPD_CUST) {
                        cyy_baud_calc(info, baud_rate);
                } else {
@@ -3059,7 +3037,7 @@ static void set_line_char(struct cyclades_port *info)
                        /* get it right for 134.5 baud */
                        info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) +
                                        2;
-               } else if (baud == 38400 && (info->flags & ASYNC_SPD_MASK) ==
+               } else if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
                                ASYNC_SPD_CUST) {
                        info->timeout = (info->xmit_fifo_size * HZ * 15 /
                                        baud_rate) + 2;
@@ -3108,16 +3086,16 @@ static void set_line_char(struct cyclades_port *info)
 
                /* CTS flow control flag */
                if (cflag & CRTSCTS) {
-                       info->flags |= ASYNC_CTS_FLOW;
+                       info->port.flags |= ASYNC_CTS_FLOW;
                        info->cor2 |= CyCtsAE;
                } else {
-                       info->flags &= ~ASYNC_CTS_FLOW;
+                       info->port.flags &= ~ASYNC_CTS_FLOW;
                        info->cor2 &= ~CyCtsAE;
                }
                if (cflag & CLOCAL)
-                       info->flags &= ~ASYNC_CHECK_CD;
+                       info->port.flags &= ~ASYNC_CHECK_CD;
                else
-                       info->flags |= ASYNC_CHECK_CD;
+                       info->port.flags |= ASYNC_CHECK_CD;
 
         /***********************************************
            The hardware option, CyRtsAO, presents RTS when
@@ -3146,8 +3124,8 @@ static void set_line_char(struct cyclades_port *info)
                /* set line characteristics  according configuration */
 
                cy_writeb(base_addr + (CySCHR1 << index),
-                         START_CHAR(info->tty));
-               cy_writeb(base_addr + (CySCHR2 << index), STOP_CHAR(info->tty));
+                         START_CHAR(info->port.tty));
+               cy_writeb(base_addr + (CySCHR2 << index), STOP_CHAR(info->port.tty));
                cy_writeb(base_addr + (CyCOR1 << index), info->cor1);
                cy_writeb(base_addr + (CyCOR2 << index), info->cor2);
                cy_writeb(base_addr + (CyCOR3 << index), info->cor3);
@@ -3163,7 +3141,7 @@ static void set_line_char(struct cyclades_port *info)
                        (info->default_timeout ? info->default_timeout : 0x02));
                /* 10ms rx timeout */
 
-               if (C_CLOCAL(info->tty)) {
+               if (C_CLOCAL(info->port.tty)) {
                        /* without modem intr */
                        cy_writeb(base_addr + (CySRER << index),
                                readb(base_addr + (CySRER << index)) | CyMdmCh);
@@ -3226,32 +3204,28 @@ static void set_line_char(struct cyclades_port *info)
 #endif
                }
 
-               if (info->tty)
-                       clear_bit(TTY_IO_ERROR, &info->tty->flags);
+               if (info->port.tty)
+                       clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
                spin_unlock_irqrestore(&card->card_lock, flags);
 
        } else {
                struct FIRM_ID __iomem *firm_id;
                struct ZFW_CTRL __iomem *zfw_ctrl;
-               struct BOARD_CTRL __iomem *board_ctrl;
                struct CH_CTRL __iomem *ch_ctrl;
-               struct BUF_CTRL __iomem *buf_ctrl;
                __u32 sw_flow;
                int retval;
 
                firm_id = card->base_addr + ID_ADDRESS;
-               if (!ISZLOADED(*card))
+               if (!cyz_is_loaded(card))
                        return;
 
                zfw_ctrl = card->base_addr +
                        (readl(&firm_id->zfwctrl_addr) & 0xfffff);
-               board_ctrl = &zfw_ctrl->board_ctrl;
                ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
-               buf_ctrl = &zfw_ctrl->buf_ctrl[channel];
 
                /* baud rate */
-               baud = tty_get_baud_rate(info->tty);
-               if (baud == 38400 && (info->flags & ASYNC_SPD_MASK) ==
+               baud = tty_get_baud_rate(info->port.tty);
+               if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
                                ASYNC_SPD_CUST) {
                        if (info->custom_divisor)
                                baud_rate = info->baud / info->custom_divisor;
@@ -3266,7 +3240,7 @@ static void set_line_char(struct cyclades_port *info)
                        /* get it right for 134.5 baud */
                        info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) +
                                        2;
-               } else if (baud == 38400 && (info->flags & ASYNC_SPD_MASK) ==
+               } else if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
                                ASYNC_SPD_CUST) {
                        info->timeout = (info->xmit_fifo_size * HZ * 15 /
                                        baud_rate) + 2;
@@ -3318,7 +3292,7 @@ static void set_line_char(struct cyclades_port *info)
                }
                /* As the HW flow control is done in firmware, the driver
                   doesn't need to care about it */
-               info->flags &= ~ASYNC_CTS_FLOW;
+               info->port.flags &= ~ASYNC_CTS_FLOW;
 
                /* XON/XOFF/XANY flow control flags */
                sw_flow = 0;
@@ -3337,9 +3311,9 @@ static void set_line_char(struct cyclades_port *info)
 
                /* CD sensitivity */
                if (cflag & CLOCAL)
-                       info->flags &= ~ASYNC_CHECK_CD;
+                       info->port.flags &= ~ASYNC_CHECK_CD;
                else
-                       info->flags |= ASYNC_CHECK_CD;
+                       info->port.flags |= ASYNC_CHECK_CD;
 
                if (baud == 0) {        /* baud rate is zero, turn off line */
                        cy_writel(&ch_ctrl->rs_control,
@@ -3361,8 +3335,8 @@ static void set_line_char(struct cyclades_port *info)
                                "was %x\n", info->line, retval);
                }
 
-               if (info->tty)
-                       clear_bit(TTY_IO_ERROR, &info->tty->flags);
+               if (info->port.tty)
+                       clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
        }
 }                              /* set_line_char */
 
@@ -3381,9 +3355,9 @@ get_serial_info(struct cyclades_port *info,
        tmp.port = (info->card - cy_card) * 0x100 + info->line -
                cinfo->first_line;
        tmp.irq = cinfo->irq;
-       tmp.flags = info->flags;
-       tmp.close_delay = info->close_delay;
-       tmp.closing_wait = info->closing_wait;
+       tmp.flags = info->port.flags;
+       tmp.close_delay = info->port.close_delay;
+       tmp.closing_wait = info->port.closing_wait;
        tmp.baud_base = info->baud;
        tmp.custom_divisor = info->custom_divisor;
        tmp.hub6 = 0;           /*!!! */
@@ -3402,13 +3376,13 @@ set_serial_info(struct cyclades_port *info,
        old_info = *info;
 
        if (!capable(CAP_SYS_ADMIN)) {
-               if (new_serial.close_delay != info->close_delay ||
+               if (new_serial.close_delay != info->port.close_delay ||
                                new_serial.baud_base != info->baud ||
                                (new_serial.flags & ASYNC_FLAGS &
                                        ~ASYNC_USR_MASK) !=
-                               (info->flags & ASYNC_FLAGS & ~ASYNC_USR_MASK))
+                               (info->port.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK))
                        return -EPERM;
-               info->flags = (info->flags & ~ASYNC_USR_MASK) |
+               info->port.flags = (info->port.flags & ~ASYNC_USR_MASK) |
                                (new_serial.flags & ASYNC_USR_MASK);
                info->baud = new_serial.baud_base;
                info->custom_divisor = new_serial.custom_divisor;
@@ -3422,13 +3396,13 @@ set_serial_info(struct cyclades_port *info,
 
        info->baud = new_serial.baud_base;
        info->custom_divisor = new_serial.custom_divisor;
-       info->flags = (info->flags & ~ASYNC_FLAGS) |
+       info->port.flags = (info->port.flags & ~ASYNC_FLAGS) |
                        (new_serial.flags & ASYNC_FLAGS);
-       info->close_delay = new_serial.close_delay * HZ / 100;
-       info->closing_wait = new_serial.closing_wait * HZ / 100;
+       info->port.close_delay = new_serial.close_delay * HZ / 100;
+       info->port.closing_wait = new_serial.closing_wait * HZ / 100;
 
 check_and_exit:
-       if (info->flags & ASYNC_INITIALIZED) {
+       if (info->port.flags & ASYNC_INITIALIZED) {
                set_line_char(info);
                return 0;
        } else {
@@ -3457,7 +3431,7 @@ static int get_lsr_info(struct cyclades_port *info, unsigned int __user *value)
 
        card = info->card;
        channel = (info->line) - (card->first_line);
-       if (!IS_CYC_Z(*card)) {
+       if (!cy_is_Z(card)) {
                chip = channel >> 2;
                channel &= 0x03;
                index = card->bus_index;
@@ -3497,7 +3471,7 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file)
 
        card = info->card;
        channel = info->line - card->first_line;
-       if (!IS_CYC_Z(*card)) {
+       if (!cy_is_Z(card)) {
                chip = channel >> 2;
                channel &= 0x03;
                index = card->bus_index;
@@ -3523,7 +3497,7 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file)
        } else {
                base_addr = card->base_addr;
                firm_id = card->base_addr + ID_ADDRESS;
-               if (ISZLOADED(*card)) {
+               if (cyz_is_loaded(card)) {
                        zfw_ctrl = card->base_addr +
                                (readl(&firm_id->zfwctrl_addr) & 0xfffff);
                        board_ctrl = &zfw_ctrl->board_ctrl;
@@ -3566,7 +3540,7 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
 
        card = info->card;
        channel = (info->line) - (card->first_line);
-       if (!IS_CYC_Z(*card)) {
+       if (!cy_is_Z(card)) {
                chip = channel >> 2;
                channel &= 0x03;
                index = card->bus_index;
@@ -3641,7 +3615,7 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
                base_addr = card->base_addr;
 
                firm_id = card->base_addr + ID_ADDRESS;
-               if (ISZLOADED(*card)) {
+               if (cyz_is_loaded(card)) {
                        zfw_ctrl = card->base_addr +
                                (readl(&firm_id->zfwctrl_addr) & 0xfffff);
                        board_ctrl = &zfw_ctrl->board_ctrl;
@@ -3700,19 +3674,20 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
 /*
  * cy_break() --- routine which turns the break handling on or off
  */
-static void cy_break(struct tty_struct *tty, int break_state)
+static int cy_break(struct tty_struct *tty, int break_state)
 {
        struct cyclades_port *info = tty->driver_data;
        struct cyclades_card *card;
        unsigned long flags;
+       int retval = 0;
 
        if (serial_paranoia_check(info, tty->name, "cy_break"))
-               return;
+               return -EINVAL;
 
        card = info->card;
 
        spin_lock_irqsave(&card->card_lock, flags);
-       if (!IS_CYC_Z(*card)) {
+       if (!cy_is_Z(card)) {
                /* Let the transmit ISR take care of this (since it
                   requires stuffing characters into the output stream).
                 */
@@ -3736,8 +3711,6 @@ static void cy_break(struct tty_struct *tty, int break_state)
                        }
                }
        } else {
-               int retval;
-
                if (break_state == -1) {
                        retval = cyz_issue_cmd(card,
                                info->line - card->first_line,
@@ -3758,6 +3731,7 @@ static void cy_break(struct tty_struct *tty, int break_state)
                }
        }
        spin_unlock_irqrestore(&card->card_lock, flags);
+       return retval;
 }                              /* cy_break */
 
 static int get_mon_info(struct cyclades_port *info,
@@ -3782,7 +3756,7 @@ static int set_threshold(struct cyclades_port *info, unsigned long value)
 
        card = info->card;
        channel = info->line - card->first_line;
-       if (!IS_CYC_Z(*card)) {
+       if (!cy_is_Z(card)) {
                chip = channel >> 2;
                channel &= 0x03;
                index = card->bus_index;
@@ -3810,7 +3784,7 @@ static int get_threshold(struct cyclades_port *info,
 
        card = info->card;
        channel = info->line - card->first_line;
-       if (!IS_CYC_Z(*card)) {
+       if (!cy_is_Z(card)) {
                chip = channel >> 2;
                channel &= 0x03;
                index = card->bus_index;
@@ -3844,7 +3818,7 @@ static int set_timeout(struct cyclades_port *info, unsigned long value)
 
        card = info->card;
        channel = info->line - card->first_line;
-       if (!IS_CYC_Z(*card)) {
+       if (!cy_is_Z(card)) {
                chip = channel >> 2;
                channel &= 0x03;
                index = card->bus_index;
@@ -3867,7 +3841,7 @@ static int get_timeout(struct cyclades_port *info,
 
        card = info->card;
        channel = info->line - card->first_line;
-       if (!IS_CYC_Z(*card)) {
+       if (!cy_is_Z(card)) {
                chip = channel >> 2;
                channel &= 0x03;
                index = card->bus_index;
@@ -3971,11 +3945,11 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
                break;
 #endif                         /* CONFIG_CYZ_INTR */
        case CYSETWAIT:
-               info->closing_wait = (unsigned short)arg * HZ / 100;
+               info->port.closing_wait = (unsigned short)arg * HZ / 100;
                ret_val = 0;
                break;
        case CYGETWAIT:
-               ret_val = info->closing_wait / (HZ / 100);
+               ret_val = info->port.closing_wait / (HZ / 100);
                break;
        case TIOCGSERIAL:
                ret_val = get_serial_info(info, argp);
@@ -4097,7 +4071,7 @@ static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
         */
        if (!(old_termios->c_cflag & CLOCAL) &&
            (tty->termios->c_cflag & CLOCAL))
-               wake_up_interruptible(&info->open_wait);
+               wake_up_interruptible(&info->port.open_wait);
 #endif
 }                              /* cy_set_termios */
 
@@ -4121,7 +4095,7 @@ static void cy_send_xchar(struct tty_struct *tty, char ch)
        card = info->card;
        channel = info->line - card->first_line;
 
-       if (IS_CYC_Z(*card)) {
+       if (cy_is_Z(card)) {
                if (ch == STOP_CHAR(tty))
                        cyz_issue_cmd(card, channel, C_CM_SENDXOFF, 0L);
                else if (ch == START_CHAR(tty))
@@ -4154,7 +4128,7 @@ static void cy_throttle(struct tty_struct *tty)
        card = info->card;
 
        if (I_IXOFF(tty)) {
-               if (!IS_CYC_Z(*card))
+               if (!cy_is_Z(card))
                        cy_send_xchar(tty, STOP_CHAR(tty));
                else
                        info->throttle = 1;
@@ -4162,7 +4136,7 @@ static void cy_throttle(struct tty_struct *tty)
 
        if (tty->termios->c_cflag & CRTSCTS) {
                channel = info->line - card->first_line;
-               if (!IS_CYC_Z(*card)) {
+               if (!cy_is_Z(card)) {
                        chip = channel >> 2;
                        channel &= 0x03;
                        index = card->bus_index;
@@ -4219,7 +4193,7 @@ static void cy_unthrottle(struct tty_struct *tty)
        if (tty->termios->c_cflag & CRTSCTS) {
                card = info->card;
                channel = info->line - card->first_line;
-               if (!IS_CYC_Z(*card)) {
+               if (!cy_is_Z(card)) {
                        chip = channel >> 2;
                        channel &= 0x03;
                        index = card->bus_index;
@@ -4263,7 +4237,7 @@ static void cy_stop(struct tty_struct *tty)
 
        cinfo = info->card;
        channel = info->line - cinfo->first_line;
-       if (!IS_CYC_Z(*cinfo)) {
+       if (!cy_is_Z(cinfo)) {
                index = cinfo->bus_index;
                chip = channel >> 2;
                channel &= 0x03;
@@ -4296,7 +4270,7 @@ static void cy_start(struct tty_struct *tty)
        cinfo = info->card;
        channel = info->line - cinfo->first_line;
        index = cinfo->bus_index;
-       if (!IS_CYC_Z(*cinfo)) {
+       if (!cy_is_Z(cinfo)) {
                chip = channel >> 2;
                channel &= 0x03;
                base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index);
@@ -4326,14 +4300,14 @@ static void cy_hangup(struct tty_struct *tty)
 
        cy_flush_buffer(tty);
        shutdown(info);
-       info->count = 0;
+       info->port.count = 0;
 #ifdef CY_DEBUG_COUNT
        printk(KERN_DEBUG "cyc:cy_hangup (%d): setting count to 0\n",
                current->pid);
 #endif
-       info->tty = NULL;
-       info->flags &= ~ASYNC_NORMAL_ACTIVE;
-       wake_up_interruptible(&info->open_wait);
+       info->port.tty = NULL;
+       info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
+       wake_up_interruptible(&info->port.open_wait);
 }                              /* cy_hangup */
 
 /*
@@ -4347,50 +4321,36 @@ static void cy_hangup(struct tty_struct *tty)
 static int __devinit cy_init_card(struct cyclades_card *cinfo)
 {
        struct cyclades_port *info;
-       u32 uninitialized_var(mailbox);
-       unsigned int nports, port;
+       unsigned int port;
        unsigned short chip_number;
-       int uninitialized_var(index);
 
        spin_lock_init(&cinfo->card_lock);
+       cinfo->intr_enabled = 0;
 
-       if (IS_CYC_Z(*cinfo)) { /* Cyclades-Z */
-               mailbox = readl(&((struct RUNTIME_9060 __iomem *)
-                                    cinfo->ctl_addr)->mail_box_0);
-               nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8;
-               cinfo->intr_enabled = 0;
-               cinfo->nports = 0;      /* Will be correctly set later, after
-                                          Z FW is loaded */
-       } else {
-               index = cinfo->bus_index;
-               nports = cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips;
-       }
-
-       cinfo->ports = kzalloc(sizeof(*cinfo->ports) * nports, GFP_KERNEL);
+       cinfo->ports = kcalloc(cinfo->nports, sizeof(*cinfo->ports),
+                       GFP_KERNEL);
        if (cinfo->ports == NULL) {
                printk(KERN_ERR "Cyclades: cannot allocate ports\n");
-               cinfo->nports = 0;
                return -ENOMEM;
        }
 
-       for (port = cinfo->first_line; port < cinfo->first_line + nports;
+       for (port = cinfo->first_line; port < cinfo->first_line + cinfo->nports;
                        port++) {
                info = &cinfo->ports[port - cinfo->first_line];
+               tty_port_init(&info->port);
                info->magic = CYCLADES_MAGIC;
                info->card = cinfo;
                info->line = port;
-               info->flags = STD_COM_FLAGS;
-               info->closing_wait = CLOSING_WAIT_DELAY;
-               info->close_delay = 5 * HZ / 10;
 
-               init_waitqueue_head(&info->open_wait);
-               init_waitqueue_head(&info->close_wait);
+               info->port.closing_wait = CLOSING_WAIT_DELAY;
+               info->port.close_delay = 5 * HZ / 10;
+               info->port.flags = STD_COM_FLAGS;
                init_completion(&info->shutdown_wait);
                init_waitqueue_head(&info->delta_msr_wait);
 
-               if (IS_CYC_Z(*cinfo)) {
+               if (cy_is_Z(cinfo)) {
                        info->type = PORT_STARTECH;
-                       if (mailbox == ZO_V1)
+                       if (cinfo->hw_ver == ZO_V1)
                                info->xmit_fifo_size = CYZ_FIFO_SIZE;
                        else
                                info->xmit_fifo_size = 4 * CYZ_FIFO_SIZE;
@@ -4399,6 +4359,7 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo)
                                cyz_rx_restart, (unsigned long)info);
 #endif
                } else {
+                       int index = cinfo->bus_index;
                        info->type = PORT_CIRRUS;
                        info->xmit_fifo_size = CyMAX_CHAR_FIFO;
                        info->cor1 = CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS;
@@ -4431,7 +4392,7 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo)
        }
 
 #ifndef CONFIG_CYZ_INTR
-       if (IS_CYC_Z(*cinfo) && !timer_pending(&cyz_timerlist)) {
+       if (cy_is_Z(cinfo) && !timer_pending(&cyz_timerlist)) {
                mod_timer(&cyz_timerlist, jiffies + 1);
 #ifdef CY_PCI_DEBUG
                printk(KERN_DEBUG "Cyclades-Z polling initialized\n");
@@ -4622,11 +4583,12 @@ static int __init cy_detect_isa(void)
 
                /* set cy_card */
                cy_card[j].base_addr = cy_isa_address;
-               cy_card[j].ctl_addr = NULL;
+               cy_card[j].ctl_addr.p9050 = NULL;
                cy_card[j].irq = (int)cy_isa_irq;
                cy_card[j].bus_index = 0;
                cy_card[j].first_line = cy_next_channel;
-               cy_card[j].num_chips = cy_isa_nchan / 4;
+               cy_card[j].num_chips = cy_isa_nchan / CyPORTS_PER_CHIP;
+               cy_card[j].nports = cy_isa_nchan;
                if (cy_init_card(&cy_card[j])) {
                        cy_card[j].base_addr = NULL;
                        free_irq(cy_isa_irq, &cy_card[j]);
@@ -4782,7 +4744,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
        struct CUSTOM_REG __iomem *cust = base_addr;
        struct ZFW_CTRL __iomem *pt_zfwctrl;
        void __iomem *tmp;
-       u32 mailbox, status;
+       u32 mailbox, status, nchan;
        unsigned int i;
        int retval;
 
@@ -4794,7 +4756,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
 
        /* Check whether the firmware is already loaded and running. If
           positive, skip this board */
-       if (Z_FPGA_LOADED(ctl_addr) && readl(&fid->signature) == ZFIRM_ID) {
+       if (__cyz_fpga_loaded(ctl_addr) && readl(&fid->signature) == ZFIRM_ID) {
                u32 cntval = readl(base_addr + 0x190);
 
                udelay(100);
@@ -4813,7 +4775,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
 
        mailbox = readl(&ctl_addr->mail_box_0);
 
-       if (mailbox == 0 || Z_FPGA_LOADED(ctl_addr)) {
+       if (mailbox == 0 || __cyz_fpga_loaded(ctl_addr)) {
                /* stops CPU and set window to beginning of RAM */
                cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
                cy_writel(&cust->cpu_stop, 0);
@@ -4829,7 +4791,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
                                base_addr);
                if (retval)
                        goto err_rel;
-               if (!Z_FPGA_LOADED(ctl_addr)) {
+               if (!__cyz_fpga_loaded(ctl_addr)) {
                        dev_err(&pdev->dev, "fw upload successful, but fw is "
                                        "not loaded\n");
                        goto err_rel;
@@ -4888,7 +4850,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
                                "system before loading the new FW to the "
                                "Cyclades-Z.\n");
 
-                       if (Z_FPGA_LOADED(ctl_addr))
+                       if (__cyz_fpga_loaded(ctl_addr))
                                plx_init(pdev, irq, ctl_addr);
 
                        retval = -EIO;
@@ -4903,16 +4865,16 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
                        base_addr + ID_ADDRESS, readl(&fid->zfwctrl_addr),
                        base_addr + readl(&fid->zfwctrl_addr));
 
+       nchan = readl(&pt_zfwctrl->board_ctrl.n_channel);
        dev_info(&pdev->dev, "Cyclades-Z FW loaded: version = %x, ports = %u\n",
-               readl(&pt_zfwctrl->board_ctrl.fw_version),
-               readl(&pt_zfwctrl->board_ctrl.n_channel));
+               readl(&pt_zfwctrl->board_ctrl.fw_version), nchan);
 
-       if (readl(&pt_zfwctrl->board_ctrl.n_channel) == 0) {
+       if (nchan == 0) {
                dev_warn(&pdev->dev, "no Cyclades-Z ports were found. Please "
                        "check the connection between the Z host card and the "
                        "serial expanders.\n");
 
-               if (Z_FPGA_LOADED(ctl_addr))
+               if (__cyz_fpga_loaded(ctl_addr))
                        plx_init(pdev, irq, ctl_addr);
 
                dev_info(&pdev->dev, "Null number of ports detected. Board "
@@ -4933,9 +4895,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
        cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) |
                        0x00030800UL);
 
-       plx_init(pdev, irq, ctl_addr);
-
-       return 0;
+       return nchan;
 err_rel:
        release_firmware(fw);
 err:
@@ -4947,7 +4907,7 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
 {
        void __iomem *addr0 = NULL, *addr2 = NULL;
        char *card_name = NULL;
-       u32 mailbox;
+       u32 uninitialized_var(mailbox);
        unsigned int device_id, nchan = 0, card_no, i;
        unsigned char plx_ver;
        int retval, irq;
@@ -4994,12 +4954,14 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
                        device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
                card_name = "Cyclom-Y";
 
-               addr0 = pci_iomap(pdev, 0, CyPCI_Yctl);
+               addr0 = ioremap_nocache(pci_resource_start(pdev, 0),
+                               CyPCI_Yctl);
                if (addr0 == NULL) {
                        dev_err(&pdev->dev, "can't remap ctl region\n");
                        goto err_reg;
                }
-               addr2 = pci_iomap(pdev, 2, CyPCI_Ywin);
+               addr2 = ioremap_nocache(pci_resource_start(pdev, 2),
+                               CyPCI_Ywin);
                if (addr2 == NULL) {
                        dev_err(&pdev->dev, "can't remap base region\n");
                        goto err_unmap;
@@ -5009,26 +4971,28 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
                if (nchan == 0) {
                        dev_err(&pdev->dev, "Cyclom-Y PCI host card with no "
                                        "Serial-Modules\n");
-                       return -EIO;
+                       goto err_unmap;
                }
        } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) {
                struct RUNTIME_9060 __iomem *ctl_addr;
 
-               ctl_addr = addr0 = pci_iomap(pdev, 0, CyPCI_Zctl);
+               ctl_addr = addr0 = ioremap_nocache(pci_resource_start(pdev, 0),
+                               CyPCI_Zctl);
                if (addr0 == NULL) {
                        dev_err(&pdev->dev, "can't remap ctl region\n");
                        goto err_reg;
                }
 
                /* Disable interrupts on the PLX before resetting it */
-               cy_writew(addr0 + 0x68, readw(addr0 + 0x68) & ~0x0900);
+               cy_writew(&ctl_addr->intr_ctrl_stat,
+                               readw(&ctl_addr->intr_ctrl_stat) & ~0x0900);
 
                plx_init(pdev, irq, addr0);
 
-               mailbox = (u32)readl(&ctl_addr->mail_box_0);
+               mailbox = readl(&ctl_addr->mail_box_0);
 
-               addr2 = pci_iomap(pdev, 2, mailbox == ZE_V1 ?
-                               CyPCI_Ze_win : CyPCI_Zwin);
+               addr2 = ioremap_nocache(pci_resource_start(pdev, 2),
+                               mailbox == ZE_V1 ? CyPCI_Ze_win : CyPCI_Zwin);
                if (addr2 == NULL) {
                        dev_err(&pdev->dev, "can't remap base region\n");
                        goto err_unmap;
@@ -5036,12 +5000,8 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
 
                if (mailbox == ZE_V1) {
                        card_name = "Cyclades-Ze";
-
-                       readl(&ctl_addr->mail_box_0);
-                       nchan = ZE_V1_NPORTS;
                } else {
                        card_name = "Cyclades-8Zo";
-
 #ifdef CY_PCI_DEBUG
                        if (mailbox == ZO_V1) {
                                cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
@@ -5063,15 +5023,12 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
                         */
                        if ((mailbox == ZO_V1) || (mailbox == ZO_V2))
                                cy_writel(addr2 + ID_ADDRESS, 0L);
-
-                       retval = cyz_load_fw(pdev, addr2, addr0, irq);
-                       if (retval)
-                               goto err_unmap;
-                       /* This must be a Cyclades-8Zo/PCI.  The extendable
-                          version will have a different device_id and will
-                          be allocated its maximum number of ports. */
-                       nchan = 8;
                }
+
+               retval = cyz_load_fw(pdev, addr2, addr0, irq);
+               if (retval <= 0)
+                       goto err_unmap;
+               nchan = retval;
        }
 
        if ((cy_next_channel + nchan) > NR_PORTS) {
@@ -5101,8 +5058,10 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
                        dev_err(&pdev->dev, "could not allocate IRQ\n");
                        goto err_unmap;
                }
-               cy_card[card_no].num_chips = nchan / 4;
+               cy_card[card_no].num_chips = nchan / CyPORTS_PER_CHIP;
        } else {
+               cy_card[card_no].hw_ver = mailbox;
+               cy_card[card_no].num_chips = (unsigned int)-1;
 #ifdef CONFIG_CYZ_INTR
                /* allocate IRQ only if board has an IRQ */
                if (irq != 0 && irq != 255) {
@@ -5115,15 +5074,15 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
                        }
                }
 #endif                         /* CONFIG_CYZ_INTR */
-               cy_card[card_no].num_chips = (unsigned int)-1;
        }
 
        /* set cy_card */
        cy_card[card_no].base_addr = addr2;
-       cy_card[card_no].ctl_addr = addr0;
+       cy_card[card_no].ctl_addr.p9050 = addr0;
        cy_card[card_no].irq = irq;
        cy_card[card_no].bus_index = 1;
        cy_card[card_no].first_line = cy_next_channel;
+       cy_card[card_no].nports = nchan;
        retval = cy_init_card(&cy_card[card_no]);
        if (retval)
                goto err_null;
@@ -5136,17 +5095,20 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
                plx_ver = readb(addr2 + CyPLX_VER) & 0x0f;
                switch (plx_ver) {
                case PLX_9050:
-
                        cy_writeb(addr0 + 0x4c, 0x43);
                        break;
 
                case PLX_9060:
                case PLX_9080:
                default:        /* Old boards, use PLX_9060 */
-                       plx_init(pdev, irq, addr0);
-                       cy_writew(addr0 + 0x68, readw(addr0 + 0x68) | 0x0900);
+               {
+                       struct RUNTIME_9060 __iomem *ctl_addr = addr0;
+                       plx_init(pdev, irq, ctl_addr);
+                       cy_writew(&ctl_addr->intr_ctrl_stat,
+                               readw(&ctl_addr->intr_ctrl_stat) | 0x0900);
                        break;
                }
+               }
        }
 
        dev_info(&pdev->dev, "%s/PCI #%d found: %d channels starting from "
@@ -5160,9 +5122,9 @@ err_null:
        cy_card[card_no].base_addr = NULL;
        free_irq(irq, &cy_card[card_no]);
 err_unmap:
-       pci_iounmap(pdev, addr0);
+       iounmap(addr0);
        if (addr2)
-               pci_iounmap(pdev, addr2);
+               iounmap(addr2);
 err_reg:
        pci_release_regions(pdev);
 err_dis:
@@ -5177,22 +5139,23 @@ static void __devexit cy_pci_remove(struct pci_dev *pdev)
        unsigned int i;
 
        /* non-Z with old PLX */
-       if (!IS_CYC_Z(*cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) ==
+       if (!cy_is_Z(cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) ==
                        PLX_9050)
-               cy_writeb(cinfo->ctl_addr + 0x4c, 0);
+               cy_writeb(cinfo->ctl_addr.p9050 + 0x4c, 0);
        else
 #ifndef CONFIG_CYZ_INTR
-               if (!IS_CYC_Z(*cinfo))
+               if (!cy_is_Z(cinfo))
 #endif
-               cy_writew(cinfo->ctl_addr + 0x68,
-                               readw(cinfo->ctl_addr + 0x68) & ~0x0900);
+               cy_writew(&cinfo->ctl_addr.p9060->intr_ctrl_stat,
+                       readw(&cinfo->ctl_addr.p9060->intr_ctrl_stat) &
+                       ~0x0900);
 
-       pci_iounmap(pdev, cinfo->base_addr);
-       if (cinfo->ctl_addr)
-               pci_iounmap(pdev, cinfo->ctl_addr);
+       iounmap(cinfo->base_addr);
+       if (cinfo->ctl_addr.p9050)
+               iounmap(cinfo->ctl_addr.p9050);
        if (cinfo->irq
 #ifndef CONFIG_CYZ_INTR
-               && !IS_CYC_Z(*cinfo)
+               && !cy_is_Z(cinfo)
 #endif /* CONFIG_CYZ_INTR */
                )
                free_irq(cinfo->irq, cinfo);
@@ -5214,31 +5177,22 @@ static struct pci_driver cy_pci_driver = {
 };
 #endif
 
-static int
-cyclades_get_proc_info(char *buf, char **start, off_t offset, int length,
-               int *eof, void *data)
+static int cyclades_proc_show(struct seq_file *m, void *v)
 {
        struct cyclades_port *info;
        unsigned int i, j;
-       int len = 0;
-       off_t begin = 0;
-       off_t pos = 0;
-       int size;
        __u32 cur_jifs = jiffies;
 
-       size = sprintf(buf, "Dev TimeOpen   BytesOut  IdleOut    BytesIn   "
+       seq_puts(m, "Dev TimeOpen   BytesOut  IdleOut    BytesIn   "
                        "IdleIn  Overruns  Ldisc\n");
 
-       pos += size;
-       len += size;
-
        /* Output one line for each known port */
        for (i = 0; i < NR_CARDS; i++)
                for (j = 0; j < cy_card[i].nports; j++) {
                        info = &cy_card[i].ports[j];
 
-                       if (info->count)
-                               size = sprintf(buf + len, "%3d %8lu %10lu %8lu "
+                       if (info->port.count)
+                               seq_printf(m, "%3d %8lu %10lu %8lu "
                                        "%10lu %8lu %9lu %6ld\n", info->line,
                                        (cur_jifs - info->idle_stats.in_use) /
                                        HZ, info->idle_stats.xmit_bytes,
@@ -5246,32 +5200,29 @@ cyclades_get_proc_info(char *buf, char **start, off_t offset, int length,
                                        HZ, info->idle_stats.recv_bytes,
                                        (cur_jifs - info->idle_stats.recv_idle)/
                                        HZ, info->idle_stats.overruns,
-                                       (long)info->tty->ldisc.num);
+                                       /* FIXME: double check locking */
+                                       (long)info->port.tty->ldisc->ops->num);
                        else
-                               size = sprintf(buf + len, "%3d %8lu %10lu %8lu "
+                               seq_printf(m, "%3d %8lu %10lu %8lu "
                                        "%10lu %8lu %9lu %6ld\n",
                                        info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L);
-                       len += size;
-                       pos = begin + len;
-
-                       if (pos < offset) {
-                               len = 0;
-                               begin = pos;
-                       }
-                       if (pos > offset + length)
-                               goto done;
                }
-       *eof = 1;
-done:
-       *start = buf + (offset - begin);        /* Start of wanted data */
-       len -= (offset - begin);        /* Start slop */
-       if (len > length)
-               len = length;   /* Ending slop */
-       if (len < 0)
-               len = 0;
-       return len;
+       return 0;
+}
+
+static int cyclades_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, cyclades_proc_show, NULL);
 }
 
+static const struct file_operations cyclades_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = cyclades_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
 /* The serial driver boot-time initialization code!
     Hardware I/O ports are mapped to character special devices on a
     first found, first allocated manner.  That is, this code searches
@@ -5308,9 +5259,9 @@ static const struct tty_operations cy_ops = {
        .hangup = cy_hangup,
        .break_ctl = cy_break,
        .wait_until_sent = cy_wait_until_sent,
-       .read_proc = cyclades_get_proc_info,
        .tiocmget = cy_tiocmget,
        .tiocmset = cy_tiocmset,
+       .proc_fops = &cyclades_proc_fops,
 };
 
 static int __init cy_init(void)
@@ -5396,11 +5347,11 @@ static void __exit cy_cleanup_module(void)
                        /* clear interrupt */
                        cy_writeb(card->base_addr + Cy_ClrIntr, 0);
                        iounmap(card->base_addr);
-                       if (card->ctl_addr)
-                               iounmap(card->ctl_addr);
+                       if (card->ctl_addr.p9050)
+                               iounmap(card->ctl_addr.p9050);
                        if (card->irq
 #ifndef CONFIG_CYZ_INTR
-                               && !IS_CYC_Z(*card)
+                               && !cy_is_Z(card)
 #endif /* CONFIG_CYZ_INTR */
                                )
                                free_irq(card->irq, card);
@@ -5419,3 +5370,4 @@ module_exit(cy_cleanup_module);
 
 MODULE_LICENSE("GPL");
 MODULE_VERSION(CY_VERSION);
+MODULE_ALIAS_CHARDEV_MAJOR(CYCLADES_MAJOR);