diff options
author | Jiri Slaby <jirislaby@gmail.com> | 2009-09-20 00:13:13 +0400 |
---|---|---|
committer | Live-CD User <linux@linux.site> | 2009-09-20 00:13:13 +0400 |
commit | f0eefdc30e55e761facf645bd1be1339b21c30e6 (patch) | |
tree | fbde46003a58550c3312ce7732a23213985e81fa /drivers/char/cyclades.c | |
parent | f0737579424dd2c4e68bdd54c718455a3f42c7b5 (diff) | |
download | linux-f0eefdc30e55e761facf645bd1be1339b21c30e6.tar.xz |
cyclades: avoid addresses recomputation
Don't fetch firmware address and recompute channel control on each
port access. Precompute the values on init and use them later all
the time.
The same for board control.
This simplify code and improves readability.
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/char/cyclades.c')
-rw-r--r-- | drivers/char/cyclades.c | 241 |
1 files changed, 71 insertions, 170 deletions
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 9e0cd7020aef..7a7092ae5d39 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -814,7 +814,7 @@ static char rflow_thr[] = { /* rflow threshold */ /* The Cyclom-Ye has placed the sequential chips in non-sequential * address order. This look-up table overcomes that problem. */ -static int cy_chip_offset[] = { 0x0000, +static const unsigned int cy_chip_offset[] = { 0x0000, 0x0400, 0x0800, 0x0C00, @@ -1406,15 +1406,9 @@ static int cyz_fetch_msg(struct cyclades_card *cinfo, __u32 *channel, __u8 *cmd, __u32 *param) { - struct FIRM_ID __iomem *firm_id; - struct ZFW_CTRL __iomem *zfw_ctrl; - struct BOARD_CTRL __iomem *board_ctrl; + struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl; unsigned long loc_doorbell; - firm_id = cinfo->base_addr + ID_ADDRESS; - zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff); - board_ctrl = &zfw_ctrl->board_ctrl; - loc_doorbell = readl(&cinfo->ctl_addr.p9060->loc_doorbell); if (loc_doorbell) { *cmd = (char)(0xff & loc_doorbell); @@ -1430,19 +1424,13 @@ static int cyz_issue_cmd(struct cyclades_card *cinfo, __u32 channel, __u8 cmd, __u32 param) { - struct FIRM_ID __iomem *firm_id; - struct ZFW_CTRL __iomem *zfw_ctrl; - struct BOARD_CTRL __iomem *board_ctrl; + struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl; __u32 __iomem *pci_doorbell; unsigned int index; - firm_id = cinfo->base_addr + ID_ADDRESS; 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 = &cinfo->ctl_addr.p9060->pci_doorbell; while ((readl(pci_doorbell) & 0xff) != 0) { @@ -1457,9 +1445,9 @@ cyz_issue_cmd(struct cyclades_card *cinfo, return 0; } /* cyz_issue_cmd */ -static void cyz_handle_rx(struct cyclades_port *info, struct tty_struct *tty, - struct BUF_CTRL __iomem *buf_ctrl) +static void cyz_handle_rx(struct cyclades_port *info, struct tty_struct *tty) { + struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl; struct cyclades_card *cinfo = info->card; unsigned int char_count; int len; @@ -1549,9 +1537,9 @@ static void cyz_handle_rx(struct cyclades_port *info, struct tty_struct *tty, } } -static void cyz_handle_tx(struct cyclades_port *info, struct tty_struct *tty, - struct BUF_CTRL __iomem *buf_ctrl) +static void cyz_handle_tx(struct cyclades_port *info, struct tty_struct *tty) { + struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl; struct cyclades_card *cinfo = info->card; u8 data; unsigned int char_count; @@ -1627,21 +1615,14 @@ ztxdone: static void cyz_handle_cmd(struct cyclades_card *cinfo) { + struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl; struct tty_struct *tty; struct cyclades_port *info; - static struct FIRM_ID __iomem *firm_id; - static struct ZFW_CTRL __iomem *zfw_ctrl; - static struct BOARD_CTRL __iomem *board_ctrl; - static struct CH_CTRL __iomem *ch_ctrl; - static struct BUF_CTRL __iomem *buf_ctrl; __u32 channel, param, fw_ver; __u8 cmd; int special_count; int delta_count; - firm_id = cinfo->base_addr + ID_ADDRESS; - zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff); - board_ctrl = &zfw_ctrl->board_ctrl; fw_ver = readl(&board_ctrl->fw_version); while (cyz_fetch_msg(cinfo, &channel, &cmd, ¶m) == 1) { @@ -1652,9 +1633,6 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo) if (tty == NULL) continue; - ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); - buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]); - switch (cmd) { case C_CM_PR_ERROR: tty_insert_flip_char(tty, 0, TTY_PARITY); @@ -1675,9 +1653,9 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo) info->icount.dcd++; delta_count++; if (info->port.flags & ASYNC_CHECK_CD) { - if ((fw_ver > 241 ? ((u_long) param) : - readl(&ch_ctrl->rs_status)) & - C_RS_DCD) { + u32 dcd = fw_ver > 241 ? param : + readl(&info->u.cyz.ch_ctrl->rs_status); + if (dcd & C_RS_DCD) { wake_up_interruptible(&info->port.open_wait); } else { tty_hangup(tty); @@ -1712,7 +1690,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo) printk(KERN_DEBUG "cyz_interrupt: rcvd intr, card %d, " "port %ld\n", info->card, channel); #endif - cyz_handle_rx(info, tty, buf_ctrl); + cyz_handle_rx(info, tty); break; case C_CM_TXBEMPTY: case C_CM_TXLOWWM: @@ -1722,7 +1700,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo) printk(KERN_DEBUG "cyz_interrupt: xmit intr, card %d, " "port %ld\n", info->card, channel); #endif - cyz_handle_tx(info, tty, buf_ctrl); + cyz_handle_tx(info, tty); break; #endif /* CONFIG_CYZ_INTR */ case C_CM_FATAL: @@ -1781,9 +1759,6 @@ static void cyz_poll(unsigned long arg) { struct cyclades_card *cinfo; struct cyclades_port *info; - struct FIRM_ID __iomem *firm_id; - struct ZFW_CTRL __iomem *zfw_ctrl; - struct BUF_CTRL __iomem *buf_ctrl; unsigned long expires = jiffies + HZ; unsigned int port, card; @@ -1795,10 +1770,6 @@ static void cyz_poll(unsigned long arg) if (!cyz_is_loaded(cinfo)) continue; - firm_id = cinfo->base_addr + ID_ADDRESS; - zfw_ctrl = cinfo->base_addr + - (readl(&firm_id->zfwctrl_addr) & 0xfffff); - /* Skip first polling cycle to avoid racing conditions with the FW */ if (!cinfo->intr_enabled) { cinfo->intr_enabled = 1; @@ -1811,15 +1782,13 @@ static void cyz_poll(unsigned long arg) struct tty_struct *tty; info = &cinfo->ports[port]; - buf_ctrl = &(zfw_ctrl->buf_ctrl[port]); - tty = tty_port_tty_get(&info->port); /* OK to pass NULL to the handle functions below. They need to drop the data in that case. */ if (!info->throttle) - cyz_handle_rx(info, tty, buf_ctrl); - cyz_handle_tx(info, tty, buf_ctrl); + cyz_handle_rx(info, tty); + cyz_handle_tx(info, tty); tty_kref_put(tty); } /* poll every 'cyz_polling_cycle' period */ @@ -1922,45 +1891,34 @@ static int cy_startup(struct cyclades_port *info, struct tty_struct *tty) 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; - - base_addr = card->base_addr; + struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; - firm_id = base_addr + ID_ADDRESS; if (!cyz_is_loaded(card)) return -ENODEV; - zfw_ctrl = card->base_addr + - (readl(&firm_id->zfwctrl_addr) & 0xfffff); - board_ctrl = &zfw_ctrl->board_ctrl; - ch_ctrl = zfw_ctrl->ch_ctrl; - #ifdef CY_DEBUG_OPEN printk(KERN_DEBUG "cyc startup Z card %d, channel %d, " - "base_addr %p\n", card, channel, base_addr); + "base_addr %p\n", card, channel, card->base_addr); #endif spin_lock_irqsave(&card->card_lock, flags); - cy_writel(&ch_ctrl[channel].op_mode, C_CH_ENABLE); + cy_writel(&ch_ctrl->op_mode, C_CH_ENABLE); #ifdef Z_WAKE #ifdef CONFIG_CYZ_INTR - cy_writel(&ch_ctrl[channel].intr_enable, + cy_writel(&ch_ctrl->intr_enable, C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM | C_IN_RXNNDT | C_IN_IOCTLW | C_IN_MDCD); #else - cy_writel(&ch_ctrl[channel].intr_enable, + cy_writel(&ch_ctrl->intr_enable, C_IN_IOCTLW | C_IN_MDCD); #endif /* CONFIG_CYZ_INTR */ #else #ifdef CONFIG_CYZ_INTR - cy_writel(&ch_ctrl[channel].intr_enable, + cy_writel(&ch_ctrl->intr_enable, C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM | C_IN_RXNNDT | C_IN_MDCD); #else - cy_writel(&ch_ctrl[channel].intr_enable, C_IN_MDCD); + cy_writel(&ch_ctrl->intr_enable, C_IN_MDCD); #endif /* CONFIG_CYZ_INTR */ #endif /* Z_WAKE */ @@ -1979,9 +1937,8 @@ static int cy_startup(struct cyclades_port *info, struct tty_struct *tty) /* set timeout !!! */ /* set RTS and DTR !!! */ - cy_writel(&ch_ctrl[channel].rs_control, - readl(&ch_ctrl[channel].rs_control) | C_RS_RTS | - C_RS_DTR); + cy_writel(&ch_ctrl->rs_control, readl(&ch_ctrl->rs_control) | + C_RS_RTS | C_RS_DTR); retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L); if (retval != 0) { printk(KERN_ERR "cyc:startup(3) retval on ttyC%d was " @@ -2110,27 +2067,17 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty) info->port.flags &= ~ASYNC_INITIALIZED; 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 CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; int retval; - base_addr = card->base_addr; #ifdef CY_DEBUG_OPEN printk(KERN_DEBUG "cyc shutdown Z card %d, channel %d, " - "base_addr %p\n", card, channel, base_addr); + "base_addr %p\n", card, channel, card->base_addr); #endif - firm_id = base_addr + ID_ADDRESS; 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; - spin_lock_irqsave(&card->card_lock, flags); if (info->port.xmit_buf) { @@ -2141,9 +2088,9 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty) } if (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))); + cy_writel(&ch_ctrl->rs_control, + readl(&ch_ctrl->rs_control) & + ~(C_RS_RTS | C_RS_DTR)); retval = cyz_issue_cmd(info->card, channel, C_CM_IOCTLM, 0L); if (retval != 0) { @@ -2497,15 +2444,11 @@ static void cy_close(struct tty_struct *tty, struct file *filp) #ifdef Z_WAKE /* Waiting for on-board buffers to be empty before closing the port */ - void __iomem *base_addr = card->base_addr; - struct FIRM_ID __iomem *firm_id = base_addr + ID_ADDRESS; - struct ZFW_CTRL __iomem *zfw_ctrl = - base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff); - struct CH_CTRL __iomem *ch_ctrl = zfw_ctrl->ch_ctrl; + struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; int channel = info->line - card->first_line; int retval; - if (readl(&ch_ctrl[channel].flow_status) != C_FS_TXIDLE) { + if (readl(&ch_ctrl->flow_status) != C_FS_TXIDLE) { retval = cyz_issue_cmd(card, channel, C_CM_IOCTLW, 0L); if (retval != 0) { printk(KERN_DEBUG "cyc:cy_close retval on " @@ -2685,18 +2628,13 @@ static int cy_write_room(struct tty_struct *tty) static int cy_chars_in_buffer(struct tty_struct *tty) { - struct cyclades_card *card; struct cyclades_port *info = tty->driver_data; - int channel; if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer")) return 0; - card = info->card; - channel = (info->line) - (card->first_line); - #ifdef Z_EXT_CHARS_IN_BUFFER - if (!cy_is_Z(card)) { + if (!cy_is_Z(info->card)) { #endif /* Z_EXT_CHARS_IN_BUFFER */ #ifdef CY_DEBUG_IO printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n", @@ -2705,20 +2643,11 @@ static int cy_chars_in_buffer(struct tty_struct *tty) return info->xmit_cnt; #ifdef Z_EXT_CHARS_IN_BUFFER } else { - static struct FIRM_ID *firm_id; - static struct ZFW_CTRL *zfw_ctrl; - static struct CH_CTRL *ch_ctrl; - static struct BUF_CTRL *buf_ctrl; + struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl; int char_count; __u32 tx_put, tx_get, tx_bufsize; lock_kernel(); - firm_id = card->base_addr + ID_ADDRESS; - zfw_ctrl = card->base_addr + - (readl(&firm_id->zfwctrl_addr) & 0xfffff); - ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); - buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]); - tx_get = readl(&buf_ctrl->tx_get); tx_put = readl(&buf_ctrl->tx_put); tx_bufsize = readl(&buf_ctrl->tx_bufsize); @@ -3019,20 +2948,13 @@ static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty) spin_unlock_irqrestore(&card->card_lock, flags); } else { - struct FIRM_ID __iomem *firm_id; - struct ZFW_CTRL __iomem *zfw_ctrl; - struct CH_CTRL __iomem *ch_ctrl; + struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; __u32 sw_flow; int retval; - firm_id = card->base_addr + ID_ADDRESS; if (!cyz_is_loaded(card)) return; - zfw_ctrl = card->base_addr + - (readl(&firm_id->zfwctrl_addr) & 0xfffff); - ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); - /* baud rate */ baud = tty_get_baud_rate(tty); if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == @@ -3268,10 +3190,6 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file) unsigned char status; unsigned long lstatus; unsigned int result; - struct FIRM_ID __iomem *firm_id; - struct ZFW_CTRL __iomem *zfw_ctrl; - struct BOARD_CTRL __iomem *board_ctrl; - struct CH_CTRL __iomem *ch_ctrl; if (serial_paranoia_check(info, tty->name, __func__)) return -ENODEV; @@ -3304,14 +3222,8 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file) ((status & CyDSR) ? TIOCM_DSR : 0) | ((status & CyCTS) ? TIOCM_CTS : 0); } else { - base_addr = card->base_addr; - firm_id = card->base_addr + ID_ADDRESS; if (cyz_is_loaded(card)) { - zfw_ctrl = card->base_addr + - (readl(&firm_id->zfwctrl_addr) & 0xfffff); - board_ctrl = &zfw_ctrl->board_ctrl; - ch_ctrl = zfw_ctrl->ch_ctrl; - lstatus = readl(&ch_ctrl[channel].rs_status); + lstatus = readl(&info->u.cyz.ch_ctrl->rs_status); result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0) | ((lstatus & C_RS_DTR) ? TIOCM_DTR : 0) | ((lstatus & C_RS_DCD) ? TIOCM_CAR : 0) | @@ -3336,12 +3248,7 @@ cy_tiocmset(struct tty_struct *tty, struct file *file, struct cyclades_port *info = tty->driver_data; struct cyclades_card *card; int chip, channel, index; - void __iomem *base_addr; unsigned long flags; - struct FIRM_ID __iomem *firm_id; - struct ZFW_CTRL __iomem *zfw_ctrl; - struct BOARD_CTRL __iomem *board_ctrl; - struct CH_CTRL __iomem *ch_ctrl; int retval; if (serial_paranoia_check(info, tty->name, __func__)) @@ -3350,6 +3257,7 @@ cy_tiocmset(struct tty_struct *tty, struct file *file, card = info->card; channel = (info->line) - (card->first_line); if (!cy_is_Z(card)) { + void __iomem *base_addr; chip = channel >> 2; channel &= 0x03; index = card->bus_index; @@ -3421,34 +3329,26 @@ cy_tiocmset(struct tty_struct *tty, struct file *file, spin_unlock_irqrestore(&card->card_lock, flags); } } else { - base_addr = card->base_addr; - - firm_id = card->base_addr + ID_ADDRESS; if (cyz_is_loaded(card)) { - zfw_ctrl = card->base_addr + - (readl(&firm_id->zfwctrl_addr) & 0xfffff); - board_ctrl = &zfw_ctrl->board_ctrl; - ch_ctrl = zfw_ctrl->ch_ctrl; + struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; if (set & TIOCM_RTS) { spin_lock_irqsave(&card->card_lock, flags); - cy_writel(&ch_ctrl[channel].rs_control, - readl(&ch_ctrl[channel].rs_control) | - C_RS_RTS); + cy_writel(&ch_ctrl->rs_control, + readl(&ch_ctrl->rs_control) | C_RS_RTS); spin_unlock_irqrestore(&card->card_lock, flags); } if (clear & TIOCM_RTS) { spin_lock_irqsave(&card->card_lock, flags); - cy_writel(&ch_ctrl[channel].rs_control, - readl(&ch_ctrl[channel].rs_control) & + cy_writel(&ch_ctrl->rs_control, + readl(&ch_ctrl->rs_control) & ~C_RS_RTS); spin_unlock_irqrestore(&card->card_lock, flags); } if (set & TIOCM_DTR) { spin_lock_irqsave(&card->card_lock, flags); - cy_writel(&ch_ctrl[channel].rs_control, - readl(&ch_ctrl[channel].rs_control) | - C_RS_DTR); + cy_writel(&ch_ctrl->rs_control, + readl(&ch_ctrl->rs_control) | C_RS_DTR); #ifdef CY_DEBUG_DTR printk(KERN_DEBUG "cyc:set_modem_info raising " "Z DTR\n"); @@ -3457,8 +3357,8 @@ cy_tiocmset(struct tty_struct *tty, struct file *file, } if (clear & TIOCM_DTR) { spin_lock_irqsave(&card->card_lock, flags); - cy_writel(&ch_ctrl[channel].rs_control, - readl(&ch_ctrl[channel].rs_control) & + cy_writel(&ch_ctrl->rs_control, + readl(&ch_ctrl->rs_control) & ~C_RS_DTR); #ifdef CY_DEBUG_DTR printk(KERN_DEBUG "cyc:set_modem_info clearing " @@ -4171,17 +4071,8 @@ static int cyz_carrier_raised(struct tty_port *port) { struct cyclades_port *info = container_of(port, struct cyclades_port, port); - struct cyclades_card *cinfo = info->card; - void __iomem *base = cinfo->base_addr; - struct FIRM_ID __iomem *firm_id = base + ID_ADDRESS; - struct ZFW_CTRL __iomem *zfw_ctrl; - struct CH_CTRL __iomem *ch_ctrl; - int channel = info->line - cinfo->first_line; - zfw_ctrl = base + (readl(&firm_id->zfwctrl_addr) & 0xfffff); - ch_ctrl = zfw_ctrl->ch_ctrl; - - return readl(&ch_ctrl[channel].rs_status) & C_RS_DCD; + return readl(&info->u.cyz.ch_ctrl->rs_status) & C_RS_DCD; } static void cyz_dtr_rts(struct tty_port *port, int raise) @@ -4189,22 +4080,16 @@ static void cyz_dtr_rts(struct tty_port *port, int raise) struct cyclades_port *info = container_of(port, struct cyclades_port, port); struct cyclades_card *cinfo = info->card; - void __iomem *base = cinfo->base_addr; - struct FIRM_ID __iomem *firm_id = base + ID_ADDRESS; - struct ZFW_CTRL __iomem *zfw_ctrl; - struct CH_CTRL __iomem *ch_ctrl; + struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; int ret, channel = info->line - cinfo->first_line; u32 rs; - zfw_ctrl = base + (readl(&firm_id->zfwctrl_addr) & 0xfffff); - ch_ctrl = zfw_ctrl->ch_ctrl; - - rs = readl(&ch_ctrl[channel].rs_control); + rs = readl(&ch_ctrl->rs_control); if (raise) rs |= C_RS_RTS | C_RS_DTR; else rs &= ~(C_RS_RTS | C_RS_DTR); - cy_writel(&ch_ctrl[channel].rs_control, rs); + cy_writel(&ch_ctrl->rs_control, rs); ret = cyz_issue_cmd(cinfo, channel, C_CM_IOCTLM, 0L); if (ret != 0) printk(KERN_ERR "%s: retval on ttyC%d was %x\n", @@ -4235,8 +4120,7 @@ static const struct tty_port_operations cyz_port_ops = { static int __devinit cy_init_card(struct cyclades_card *cinfo) { struct cyclades_port *info; - unsigned int port; - unsigned short chip_number; + unsigned int channel, port; spin_lock_init(&cinfo->card_lock); cinfo->intr_enabled = 0; @@ -4248,9 +4132,9 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo) return -ENOMEM; } - for (port = cinfo->first_line; port < cinfo->first_line + cinfo->nports; - port++) { - info = &cinfo->ports[port - cinfo->first_line]; + for (channel = 0, port = cinfo->first_line; channel < cinfo->nports; + channel++, port++) { + info = &cinfo->ports[channel]; tty_port_init(&info->port); info->magic = CYCLADES_MAGIC; info->card = cinfo; @@ -4263,8 +4147,17 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo) init_waitqueue_head(&info->delta_msr_wait); if (cy_is_Z(cinfo)) { + struct FIRM_ID *firm_id = cinfo->base_addr + ID_ADDRESS; + struct ZFW_CTRL *zfw_ctrl; + info->port.ops = &cyz_port_ops; info->type = PORT_STARTECH; + + zfw_ctrl = cinfo->base_addr + + (readl(&firm_id->zfwctrl_addr) & 0xfffff); + info->u.cyz.ch_ctrl = &zfw_ctrl->ch_ctrl[channel]; + info->u.cyz.buf_ctrl = &zfw_ctrl->buf_ctrl[channel]; + if (cinfo->hw_ver == ZO_V1) info->xmit_fifo_size = CYZ_FIFO_SIZE; else @@ -4274,7 +4167,9 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo) cyz_rx_restart, (unsigned long)info); #endif } else { + unsigned short chip_number; int index = cinfo->bus_index; + info->port.ops = &cyy_port_ops; info->type = PORT_CIRRUS; info->xmit_fifo_size = CyMAX_CHAR_FIFO; @@ -4282,7 +4177,7 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo) info->cor2 = CyETC; info->cor3 = 0x08; /* _very_ small rcv threshold */ - chip_number = (port - cinfo->first_line) / 4; + chip_number = channel / CyPORTS_PER_CHIP; info->chip_rev = readb(cinfo->base_addr + (cy_chip_offset[chip_number] << index) + (CyGFRCR << index)); @@ -4976,8 +4871,14 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, } cy_card[card_no].num_chips = nchan / CyPORTS_PER_CHIP; } else { + struct FIRM_ID __iomem *firm_id = addr2 + ID_ADDRESS; + struct ZFW_CTRL __iomem *zfw_ctrl; + + zfw_ctrl = addr2 + (readl(&firm_id->zfwctrl_addr) & 0xfffff); + cy_card[card_no].hw_ver = mailbox; cy_card[card_no].num_chips = (unsigned int)-1; + cy_card[card_no].board_ctrl = &zfw_ctrl->board_ctrl; #ifdef CONFIG_CYZ_INTR /* allocate IRQ only if board has an IRQ */ if (irq != 0 && irq != 255) { |