#include <asm/irq.h>
#include <asm/uaccess.h>
-#define CY_LOCK(info,flags) \
- do { \
- spin_lock_irqsave(&info->card->card_lock, flags); \
- } while (0)
-
-#define CY_UNLOCK(info,flags) \
- do { \
- spin_unlock_irqrestore(&info->card->card_lock, flags); \
- } while (0)
-
#include <linux/kernel.h>
#include <linux/pci.h>
*/
static struct cyclades_card cy_card[NR_CARDS];
-/* This is the per-channel data structure containing pointers, flags
- and variables for the port. This driver supports a maximum of NR_PORTS.
-*/
-static struct cyclades_port cy_port[NR_PORTS];
-
static int cy_next_channel; /* next minor available */
/*
return 1;
}
- if ((long)info < (long)(&cy_port[0]) ||
- (long)(&cy_port[NR_PORTS]) < (long)info) {
- printk(KERN_WARNING "cyc Warning: cyclades_port out of range "
- "for (%s) in %s\n", name, routine);
- return 1;
- }
-
if (info->magic != CYCLADES_MAGIC) {
printk(KERN_WARNING "cyc Warning: bad magic number for serial "
"struct (%s) in %s\n", name, routine);
struct cyclades_port *info;
struct tty_struct *tty;
int char_count;
- int i, j, len, mdm_change, mdm_status, outch;
+ int j, len, mdm_change, mdm_status, outch;
int save_xir, channel, save_car;
char data;
spin_lock(&cinfo->card_lock);
save_xir = (u_char) readb(base_addr + (CyRIR << index));
channel = (u_short) (save_xir & CyIRChannel);
- i = channel + chip * 4 + cinfo->first_line;
- info = &cy_port[i];
+ info = &cinfo->ports[channel + chip * 4];
save_car = readb(base_addr + (CyCAR << index));
cy_writeb(base_addr + (CyCAR << index), save_xir);
/* if there is nowhere to put the data, discard it */
- if (info->tty == 0) {
+ if (info->tty == NULL) {
j = (readb(base_addr + (CyRIVR << index)) &
CyIVRMask);
if (j == CyIVRRxEx) { /* exception */
spin_lock(&cinfo->card_lock);
save_xir = (u_char) readb(base_addr + (CyTIR << index));
channel = (u_short) (save_xir & CyIRChannel);
- i = channel + chip * 4 + cinfo->first_line;
save_car = readb(base_addr + (CyCAR << index));
cy_writeb(base_addr + (CyCAR << index), save_xir);
/* validate the port# (as configured and open) */
- if ((i < 0) || (NR_PORTS <= i)) {
+ if (channel + chip * 4 >= cinfo->nports) {
cy_writeb(base_addr + (CySRER << index),
readb(base_addr + (CySRER << index)) &
~CyTxRdy);
goto txend;
}
- info = &cy_port[i];
- if (info->tty == 0) {
+ info = &cinfo->ports[channel + chip * 4];
+ if (info->tty == NULL) {
cy_writeb(base_addr + (CySRER << index),
readb(base_addr + (CySRER << index)) &
~CyTxRdy);
}
goto txdone;
}
- if (info->xmit_buf == 0) {
+ if (info->xmit_buf == NULL) {
cy_writeb(base_addr + (CySRER << index),
readb(base_addr + (CySRER << index)) &
~CyTxRdy);
0);
info->icount.tx++;
char_count--;
- } else {
}
}
}
spin_lock(&cinfo->card_lock);
save_xir = (u_char) readb(base_addr + (CyMIR << index));
channel = (u_short) (save_xir & CyIRChannel);
- info = &cy_port[channel + chip * 4 + cinfo->first_line];
+ info = &cinfo->ports[channel + chip * 4];
save_car = readb(base_addr + (CyCAR << index));
cy_writeb(base_addr + (CyCAR << index), save_xir);
mdm_change = readb(base_addr + (CyMISR << index));
mdm_status = readb(base_addr + (CyMSVR1 << index));
- if (info->tty == 0) { /* no place for data, ignore it */
- ;
- } else {
+ if (info->tty) {
if (mdm_change & CyANY_DELTA) {
/* For statistics only */
if (mdm_change & CyDCD)
}
}
}
- if (mdm_change & CyDSR) {
+/* if (mdm_change & CyDSR) {
}
if (mdm_change & CyRI) {
- }
+ }*/
}
/* end of service */
cy_writeb(base_addr + (CyMIR << index), (save_xir & 0x3f));
static irqreturn_t cyy_interrupt(int irq, void *dev_id)
{
int status;
- struct cyclades_card *cinfo;
+ struct cyclades_card *cinfo = dev_id;
void __iomem *base_addr, *card_base_addr;
int chip;
int index;
int too_many;
int had_work;
- if ((cinfo = (struct cyclades_card *)dev_id) == 0) {
+ if (unlikely(cinfo == NULL)) {
#ifdef CY_DEBUG_INTERRUPTS
printk(KERN_DEBUG "cyy_interrupt: spurious interrupt %d\n",irq);
#endif
info->mon.char_max = char_count;
info->mon.char_last = char_count;
#endif
- if (tty == 0) {
+ if (tty == NULL) {
/* flush received characters */
new_rx_get = (new_rx_get + char_count) &
(rx_bufsize - 1);
if (char_count) {
- if (tty == 0) {
+ if (tty == NULL)
goto ztxdone;
- }
if (info->x_char) { /* send special char */
data = info->x_char;
while (cyz_fetch_msg(cinfo, &channel, &cmd, ¶m) == 1) {
special_count = 0;
delta_count = 0;
- info = &cy_port[channel + cinfo->first_line];
- if ((tty = info->tty) == 0) {
+ info = &cinfo->ports[channel];
+ if ((tty = info->tty) == NULL)
continue;
- }
+
ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]);
#ifdef CONFIG_CYZ_INTR
static irqreturn_t cyz_interrupt(int irq, void *dev_id)
{
- struct cyclades_card *cinfo;
+ struct cyclades_card *cinfo = dev_id;
- if ((cinfo = (struct cyclades_card *)dev_id) == 0) {
+ 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 (!ISZLOADED(*cinfo)) {
+ if (unlikely(!ISZLOADED(*cinfo))) {
#ifdef CY_DEBUG_INTERRUPTS
printk(KERN_DEBUG "cyz_interrupt: board not yet loaded "
"(IRQ%d).\n", irq);
__u32 channel = info->line - card->first_line;
unsigned long flags;
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
retval = cyz_issue_cmd(card, channel, C_CM_INTBACK2, 0L);
if (retval != 0) {
printk(KERN_ERR "cyc:cyz_rx_restart retval on ttyC%d was %x\n",
info->line, retval);
}
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
}
#else /* CONFIG_CYZ_INTR */
cyz_handle_cmd(cinfo);
for (port = 0; port < cinfo->nports; port++) {
- info = &cy_port[port + cinfo->first_line];
+ info = &cinfo->ports[port];
tty = info->tty;
ch_ctrl = &(zfw_ctrl->ch_ctrl[port]);
buf_ctrl = &(zfw_ctrl->buf_ctrl[port]);
if (!page)
return -ENOMEM;
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
if (info->flags & ASYNC_INITIALIZED) {
free_page(page);
else
info->xmit_buf = (unsigned char *)page;
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
set_line_char(info);
"base_addr %p\n",
card, chip, channel, base_addr);
#endif
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
info->idle_stats.recv_idle =
info->idle_stats.xmit_idle = jiffies;
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
} else {
struct FIRM_ID __iomem *firm_id;
printk(KERN_DEBUG "cyc startup Z card %d, channel %d, "
"base_addr %p\n", card, channel, base_addr);
#endif
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
cy_writel(&ch_ctrl[channel].op_mode, C_CH_ENABLE);
#ifdef Z_WAKE
cy_writel(&ch_ctrl[channel].rs_control,
readl(&ch_ctrl[channel].rs_control) | C_RS_RTS |
C_RS_DTR);
- retval = cyz_issue_cmd(info->card, channel,
- C_CM_IOCTLM, 0L);
+ retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L);
if (retval != 0) {
printk(KERN_ERR "cyc:startup(3) retval on ttyC%d was "
"%x\n", info->line, retval);
info->idle_stats.recv_idle =
info->idle_stats.xmit_idle = jiffies;
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
}
#ifdef CY_DEBUG_OPEN
return 0;
errout:
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
return retval;
} /* startup */
index = card->bus_index;
base_addr = card->base_addr + (cy_chip_offset[chip] << index);
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
cy_writeb(base_addr + (CyCAR << index), channel);
cy_writeb(base_addr + (CySRER << index),
readb(base_addr + (CySRER << index)) | CyTxRdy);
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
} else {
#ifdef CONFIG_CYZ_INTR
int retval;
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
retval = cyz_issue_cmd(card, channel, C_CM_INTBACK, 0L);
if (retval != 0) {
printk(KERN_ERR "cyc:start_xmit retval on ttyC%d was "
"%x\n", info->line, retval);
}
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
#else /* CONFIG_CYZ_INTR */
/* Don't have to do anything at this time */
#endif /* CONFIG_CYZ_INTR */
card, chip, channel, base_addr);
#endif
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
/* Clear delta_msr_wait queue to avoid mem leaks. */
wake_up_interruptible(&info->delta_msr_wait);
set_bit(TTY_IO_ERROR, &info->tty->flags);
}
info->flags &= ~ASYNC_INITIALIZED;
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
} else {
struct FIRM_ID __iomem *firm_id;
struct ZFW_CTRL __iomem *zfw_ctrl;
board_ctrl = &zfw_ctrl->board_ctrl;
ch_ctrl = zfw_ctrl->ch_ctrl;
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
if (info->xmit_buf) {
unsigned char *temp;
}
info->flags &= ~ASYNC_INITIALIZED;
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
}
#ifdef CY_DEBUG_OPEN
printk(KERN_DEBUG "cyc block_til_ready before block: ttyC%d, "
"count = %d\n", info->line, info->count);
#endif
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&cinfo->card_lock, flags);
if (!tty_hung_up_p(filp))
info->count--;
- CY_UNLOCK(info, flags);
+ 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);
base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index);
while (1) {
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&cinfo->card_lock, flags);
if ((tty->termios->c_cflag & CBAUD)) {
cy_writeb(base_addr + (CyCAR << index),
(u_char) channel);
readb(base_addr + (CyMSVR2 << index)));
#endif
}
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&cinfo->card_lock, flags);
set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
break;
}
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&cinfo->card_lock, flags);
cy_writeb(base_addr + (CyCAR << index),
(u_char) channel);
if (!(info->flags & ASYNC_CLOSING) && (C_CLOCAL(tty) ||
(readb(base_addr +
(CyMSVR1 << index)) & CyDCD))) {
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&cinfo->card_lock, flags);
break;
}
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&cinfo->card_lock, flags);
if (signal_pending(current)) {
retval = -ERESTARTSYS;
cy_writel(&ch_ctrl[channel].rs_control,
readl(&ch_ctrl[channel].rs_control) |
C_RS_RTS | C_RS_DTR);
- retval = cyz_issue_cmd(info->card,
+ retval = cyz_issue_cmd(cinfo,
channel, C_CM_IOCTLM, 0L);
if (retval != 0) {
printk(KERN_ERR "cyc:block_til_ready "
static int cy_open(struct tty_struct *tty, struct file *filp)
{
struct cyclades_port *info;
+ unsigned int i;
int retval, line;
line = tty->index;
if ((line < 0) || (NR_PORTS <= line)) {
return -ENODEV;
}
- info = &cy_port[line];
+ for (i = 0; i < NR_CARDS; i++)
+ if (line < cy_card[i].first_line + cy_card[i].nports &&
+ line >= cy_card[i].first_line)
+ break;
+ if (i >= NR_CARDS)
+ return -ENODEV;
+ info = &cy_card[i].ports[line - cy_card[i].first_line];
if (info->line < 0) {
return -ENODEV;
}
timeout))
break;
}
- } else {
- /* Nothing to do! */
}
/* Run one more char cycle */
msleep_interruptible(jiffies_to_msecs(char_time * 5));
static void cy_close(struct tty_struct *tty, struct file *filp)
{
struct cyclades_port *info = tty->driver_data;
+ struct cyclades_card *card;
unsigned long flags;
#ifdef CY_DEBUG_OTHER
return;
}
- CY_LOCK(info, flags);
+ card = info->card;
+
+ spin_lock_irqsave(&card->card_lock, flags);
/* If the TTY is being hung up, nothing to do */
if (tty_hung_up_p(filp)) {
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
return;
}
#ifdef CY_DEBUG_OPEN
info->count = 0;
}
if (info->count) {
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
return;
}
info->flags |= ASYNC_CLOSING;
* the line discipline to only process XON/XOFF characters.
*/
tty->closing = 1;
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
if (info->closing_wait != CY_CLOSING_WAIT_NONE) {
tty_wait_until_sent(tty, info->closing_wait);
}
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
- if (!IS_CYC_Z(*info->card)) {
- int channel = info->line - info->card->first_line;
- int index = info->card->bus_index;
- void __iomem *base_addr = info->card->base_addr +
+ if (!IS_CYC_Z(*card)) {
+ int channel = info->line - card->first_line;
+ int index = card->bus_index;
+ void __iomem *base_addr = card->base_addr +
(cy_chip_offset[channel >> 2] << index);
/* Stop accepting input */
channel &= 0x03;
if (info->flags & ASYNC_INITIALIZED) {
/* Waiting for on-board buffers to be empty before closing
the port */
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
cy_wait_until_sent(tty, info->timeout);
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
}
} else {
#ifdef Z_WAKE
/* Waiting for on-board buffers to be empty before closing the port */
- void __iomem *base_addr = info->card->base_addr;
+ 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;
- int channel = info->line - info->card->first_line;
+ int channel = info->line - card->first_line;
int retval;
if (readl(&ch_ctrl[channel].flow_status) != C_FS_TXIDLE) {
- retval = cyz_issue_cmd(info->card, channel,
- C_CM_IOCTLW, 0L);
+ retval = cyz_issue_cmd(card, channel, C_CM_IOCTLW, 0L);
if (retval != 0) {
printk(KERN_DEBUG "cyc:cy_close retval on "
"ttyC%d was %x\n", info->line, retval);
}
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
wait_for_completion_interruptible(&info->shutdown_wait);
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
}
#endif
}
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
shutdown(info);
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
tty_ldisc_flush(tty);
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
tty->closing = 0;
info->event = 0;
info->tty = NULL;
if (info->blocked_open) {
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
if (info->close_delay) {
msleep_interruptible(jiffies_to_msecs
(info->close_delay));
}
wake_up_interruptible(&info->open_wait);
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
}
info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
wake_up_interruptible(&info->close_wait);
printk(KERN_DEBUG "cyc:cy_close done\n");
#endif
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
} /* cy_close */
/* This routine gets called when tty_write has put something into
if (!info->xmit_buf)
return 0;
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&info->card->card_lock, flags);
while (1) {
c = min(count, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1),
(int)(SERIAL_XMIT_SIZE - info->xmit_head)));
count -= c;
ret += c;
}
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&info->card->card_lock, flags);
info->idle_stats.xmit_bytes += ret;
info->idle_stats.xmit_idle = jiffies;
if (!info->xmit_buf)
return;
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&info->card->card_lock, flags);
if (info->xmit_cnt >= (int)(SERIAL_XMIT_SIZE - 1)) {
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&info->card->card_lock, flags);
return;
}
info->xmit_cnt++;
info->idle_stats.xmit_bytes++;
info->idle_stats.xmit_idle = jiffies;
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&info->card->card_lock, flags);
} /* cy_put_char */
/*
channel &= 0x03;
base_addr = card->base_addr + (cy_chip_offset[chip] << index);
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
/* tx and rx baud rate */
if (info->tty) {
clear_bit(TTY_IO_ERROR, &info->tty->flags);
}
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
} else {
struct FIRM_ID __iomem *firm_id;
index = card->bus_index;
base_addr = card->base_addr + (cy_chip_offset[chip] << index);
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
status = readb(base_addr + (CySRER << index)) &
(CyTxRdy | CyTxMpty);
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
result = (status ? 0 : TIOCSER_TEMT);
} else {
/* Not supported yet */
index = card->bus_index;
base_addr = card->base_addr + (cy_chip_offset[chip] << index);
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
status = readb(base_addr + (CyMSVR1 << index));
status |= readb(base_addr + (CyMSVR2 << index));
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
if (info->rtsdtr_inv) {
result = ((status & CyRTS) ? TIOCM_DTR : 0) |
base_addr = card->base_addr + (cy_chip_offset[chip] << index);
if (set & TIOCM_RTS) {
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
cy_writeb(base_addr + (CyCAR << index),
(u_char) channel);
if (info->rtsdtr_inv) {
cy_writeb(base_addr + (CyMSVR1 << index),
CyRTS);
}
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
}
if (clear & TIOCM_RTS) {
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
cy_writeb(base_addr + (CyCAR << index),
(u_char) channel);
if (info->rtsdtr_inv) {
cy_writeb(base_addr + (CyMSVR1 << index),
~CyRTS);
}
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
}
if (set & TIOCM_DTR) {
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
cy_writeb(base_addr + (CyCAR << index),
(u_char) channel);
if (info->rtsdtr_inv) {
readb(base_addr + (CyMSVR1 << index)),
readb(base_addr + (CyMSVR2 << index)));
#endif
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
}
if (clear & TIOCM_DTR) {
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
cy_writeb(base_addr + (CyCAR << index),
(u_char) channel);
if (info->rtsdtr_inv) {
readb(base_addr + (CyMSVR1 << index)),
readb(base_addr + (CyMSVR2 << index)));
#endif
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
}
} else {
base_addr = card->base_addr;
ch_ctrl = zfw_ctrl->ch_ctrl;
if (set & TIOCM_RTS) {
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
cy_writel(&ch_ctrl[channel].rs_control,
readl(&ch_ctrl[channel].rs_control) |
C_RS_RTS);
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
}
if (clear & TIOCM_RTS) {
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
cy_writel(&ch_ctrl[channel].rs_control,
readl(&ch_ctrl[channel].rs_control) &
~C_RS_RTS);
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
}
if (set & TIOCM_DTR) {
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
cy_writel(&ch_ctrl[channel].rs_control,
readl(&ch_ctrl[channel].rs_control) |
C_RS_DTR);
printk(KERN_DEBUG "cyc:set_modem_info raising "
"Z DTR\n");
#endif
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
}
if (clear & TIOCM_DTR) {
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
cy_writel(&ch_ctrl[channel].rs_control,
readl(&ch_ctrl[channel].rs_control) &
~C_RS_DTR);
printk(KERN_DEBUG "cyc:set_modem_info clearing "
"Z DTR\n");
#endif
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
}
} else {
return -ENODEV;
}
- CY_LOCK(info, flags);
- retval = cyz_issue_cmd(info->card,
- channel, C_CM_IOCTLM, 0L);
+ spin_lock_irqsave(&card->card_lock, flags);
+ retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L);
if (retval != 0) {
printk(KERN_ERR "cyc:set_modem_info retval on ttyC%d "
"was %x\n", info->line, retval);
}
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
}
return 0;
} /* cy_tiocmset */
static void cy_break(struct tty_struct *tty, int break_state)
{
struct cyclades_port *info = tty->driver_data;
+ struct cyclades_card *card;
unsigned long flags;
if (serial_paranoia_check(info, tty->name, "cy_break"))
return;
- CY_LOCK(info, flags);
- if (!IS_CYC_Z(*info->card)) {
+ card = info->card;
+
+ spin_lock_irqsave(&card->card_lock, flags);
+ if (!IS_CYC_Z(*card)) {
/* Let the transmit ISR take care of this (since it
requires stuffing characters into the output stream).
*/
if (!info->breakon) {
info->breakon = 1;
if (!info->xmit_cnt) {
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
start_xmit(info);
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
}
}
} else {
if (!info->breakoff) {
info->breakoff = 1;
if (!info->xmit_cnt) {
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
start_xmit(info);
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
}
}
}
int retval;
if (break_state == -1) {
- retval = cyz_issue_cmd(info->card,
- info->line - info->card->first_line,
+ retval = cyz_issue_cmd(card,
+ info->line - card->first_line,
C_CM_SET_BREAK, 0L);
if (retval != 0) {
printk(KERN_ERR "cyc:cy_break (set) retval on "
"ttyC%d was %x\n", info->line, retval);
}
} else {
- retval = cyz_issue_cmd(info->card,
- info->line - info->card->first_line,
+ retval = cyz_issue_cmd(card,
+ info->line - card->first_line,
C_CM_CLR_BREAK, 0L);
if (retval != 0) {
printk(KERN_DEBUG "cyc:cy_break (clr) retval "
}
}
}
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
} /* cy_break */
static int
info->cor3 &= ~CyREC_FIFO;
info->cor3 |= value & CyREC_FIFO;
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
cy_writeb(base_addr + (CyCOR3 << index), info->cor3);
cyy_issue_cmd(base_addr, CyCOR_CHANGE | CyCOR3ch, index);
- CY_UNLOCK(info, flags);
- } else {
- /* Nothing to do! */
+ spin_unlock_irqrestore(&card->card_lock, flags);
}
return 0;
} /* set_threshold */
tmp = readb(base_addr + (CyCOR3 << index)) & CyREC_FIFO;
return put_user(tmp, value);
- } else {
- /* Nothing to do! */
- return 0;
}
+ return 0;
} /* get_threshold */
static int
index = card->bus_index;
base_addr = card->base_addr + (cy_chip_offset[chip] << index);
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
cy_writeb(base_addr + (CyRTPR << index), value & 0xff);
- CY_UNLOCK(info, flags);
- } else {
- /* Nothing to do! */
+ spin_unlock_irqrestore(&card->card_lock, flags);
}
return 0;
} /* set_timeout */
tmp = readb(base_addr + (CyRTPR << index));
return put_user(tmp, value);
- } else {
- /* Nothing to do! */
- return 0;
}
+ return 0;
} /* get_timeout */
static int set_default_timeout(struct cyclades_port *info, unsigned long value)
* Caller should use TIOCGICOUNT to see which one it was
*/
case TIOCMIWAIT:
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&info->card->card_lock, flags);
/* note the counters on entry */
cnow = info->icount;
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&info->card->card_lock, flags);
ret_val = wait_event_interruptible(info->delta_msr_wait, ({
cprev = cnow;
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&info->card->card_lock, flags);
cnow = info->icount; /* atomic copy */
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&info->card->card_lock, flags);
((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
* RI where only 0->1 is counted.
*/
case TIOCGICOUNT:
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&info->card->card_lock, flags);
cnow = info->icount;
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&info->card->card_lock, flags);
p_cuser = argp;
ret_val = put_user(cnow.cts, &p_cuser->cts);
if (ret_val)
base_addr = card->base_addr +
(cy_chip_offset[chip] << index);
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
cy_writeb(base_addr + (CyCAR << index),
(u_char) channel);
if (info->rtsdtr_inv) {
cy_writeb(base_addr + (CyMSVR1 << index),
~CyRTS);
}
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
} else {
info->throttle = 1;
}
base_addr = card->base_addr +
(cy_chip_offset[chip] << index);
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
cy_writeb(base_addr + (CyCAR << index),
(u_char) channel);
if (info->rtsdtr_inv) {
cy_writeb(base_addr + (CyMSVR1 << index),
CyRTS);
}
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
} else {
info->throttle = 0;
}
index = cinfo->bus_index;
chip = channel >> 2;
channel &= 0x03;
- base_addr = info->card->base_addr +
- (cy_chip_offset[chip] << index);
+ base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index);
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&cinfo->card_lock, flags);
cy_writeb(base_addr + (CyCAR << index),
(u_char)(channel & 0x0003)); /* index channel */
cy_writeb(base_addr + (CySRER << index),
readb(base_addr + (CySRER << index)) & ~CyTxRdy);
- CY_UNLOCK(info, flags);
- } else {
- /* Nothing to do! */
+ spin_unlock_irqrestore(&cinfo->card_lock, flags);
}
} /* cy_stop */
if (!IS_CYC_Z(*cinfo)) {
chip = channel >> 2;
channel &= 0x03;
- base_addr = info->card->base_addr +
- (cy_chip_offset[chip] << index);
+ base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index);
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&cinfo->card_lock, flags);
cy_writeb(base_addr + (CyCAR << index), (u_char) (channel & 0x0003)); /* index channel */
cy_writeb(base_addr + (CySRER << index),
readb(base_addr + (CySRER << index)) | CyTxRdy);
- CY_UNLOCK(info, flags);
- } else {
- /* Nothing to do! */
+ spin_unlock_irqrestore(&cinfo->card_lock, flags);
}
} /* cy_start */
card = info->card;
channel = info->line - card->first_line;
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
if (IS_CYC_Z(*card)) { /* If it is a Z card, flush the on-board
buffers as well */
- CY_LOCK(info, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L);
if (retval != 0) {
printk(KERN_ERR "cyc: flush_buffer retval on ttyC%d "
"was %x\n", info->line, retval);
}
- CY_UNLOCK(info, flags);
+ spin_unlock_irqrestore(&card->card_lock, flags);
}
tty_wakeup(tty);
} /* cy_flush_buffer */
* ---------------------------------------------------------------------
*/
-static void __devinit cy_init_card(struct cyclades_card *cinfo)
+static int __devinit cy_init_card(struct cyclades_card *cinfo)
{
struct cyclades_port *info;
u32 mailbox;
nports = cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips;
}
+ cinfo->ports = kzalloc(sizeof(*cinfo->ports) * nports, GFP_KERNEL);
+ if (cinfo->ports == NULL) {
+ printk(KERN_ERR "Cyclades: cannot allocate ports\n");
+ return -ENOMEM;
+ }
+
for (port = cinfo->first_line; port < cinfo->first_line + nports;
port++) {
- info = &cy_port[port];
- memset(info, 0, sizeof(*info));
+ info = &cinfo->ports[port - cinfo->first_line];
info->magic = CYCLADES_MAGIC;
info->card = cinfo;
info->line = port;
#endif
}
#endif
+ return 0;
}
/* initialize chips on Cyclom-Y card -- return number of valid
}
/* fill the next cy_card structure available */
for (j = 0; j < NR_CARDS; j++) {
- if (cy_card[j].base_addr == 0)
+ if (cy_card[j].base_addr == NULL)
break;
}
if (j == NR_CARDS) { /* no more cy_cards available */
/* fill the next cy_card structure available */
for (j = 0; j < NR_CARDS; j++) {
- if (cy_card[j].base_addr == 0)
+ if (cy_card[j].base_addr == NULL)
break;
}
if (j == NR_CARDS) { /* no more cy_cards available */
}
/* fill the next cy_card structure available */
for (j = 0; j < NR_CARDS; j++) {
- if (cy_card[j].base_addr == 0)
+ if (cy_card[j].base_addr == NULL)
break;
}
if (j == NR_CARDS) { /* no more cy_cards available */
/* fill the next cy_card structure available */
for (j = 0; j < NR_CARDS; j++) {
- if (cy_card[j].base_addr == 0)
+ if (cy_card[j].base_addr == NULL)
break;
}
if (j == NR_CARDS) { /* no more cy_cards available */
pci_release_regions(pdev);
cinfo->base_addr = NULL;
- for (i = cinfo->first_line; i < cinfo->first_line + cinfo->nports; i++){
- cy_port[i].line = -1;
- cy_port[i].magic = -1;
- }
for (i = cinfo->first_line; i < cinfo->first_line +
cinfo->nports; i++)
tty_unregister_device(cy_serial_driver, i);
+ cinfo->nports = 0;
+ kfree(cinfo->ports);
}
static struct pci_driver cy_pci_driver = {
int *eof, void *data)
{
struct cyclades_port *info;
- int i;
+ unsigned int i, j;
int len = 0;
off_t begin = 0;
off_t pos = 0;
len += size;
/* Output one line for each known port */
- for (i = 0; i < NR_PORTS && cy_port[i].line >= 0; i++) {
- info = &cy_port[i];
-
- if (info->count)
- size = sprintf(buf + len, "%3d %8lu %10lu %8lu %10lu "
- "%8lu %9lu %6ld\n", info->line,
- (cur_jifs - info->idle_stats.in_use) / HZ,
- info->idle_stats.xmit_bytes,
- (cur_jifs - info->idle_stats.xmit_idle) / HZ,
- info->idle_stats.recv_bytes,
- (cur_jifs - info->idle_stats.recv_idle) / HZ,
- info->idle_stats.overruns,
- (long)info->tty->ldisc.num);
- else
- size = sprintf(buf + len, "%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;
+ 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 "
+ "%10lu %8lu %9lu %6ld\n", info->line,
+ (cur_jifs - info->idle_stats.in_use) /
+ HZ, info->idle_stats.xmit_bytes,
+ (cur_jifs - info->idle_stats.xmit_idle)/
+ HZ, info->idle_stats.recv_bytes,
+ (cur_jifs - info->idle_stats.recv_idle)/
+ HZ, info->idle_stats.overruns,
+ (long)info->tty->ldisc.num);
+ else
+ size = sprintf(buf + len, "%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;
}
- if (pos > offset + length)
- goto done;
- }
*eof = 1;
done:
*start = buf + (offset - begin); /* Start of wanted data */
static int __init cy_init(void)
{
- unsigned int i, nboards;
+ unsigned int nboards;
int retval = -ENOMEM;
cy_serial_driver = alloc_tty_driver(NR_PORTS);
goto err_frtty;
}
- for (i = 0; i < NR_PORTS; i++) {
- cy_port[i].line = -1;
- cy_port[i].magic = -1;
- }
-
/* the code below is responsible to find the boards. Each different
type of board has its own detection routine. If a board is found,
the next cy_card structure available is set by the detection
static void __exit cy_cleanup_module(void)
{
+ struct cyclades_card *card;
int i, e1;
#ifndef CONFIG_CYZ_INTR
printk(KERN_ERR "failed to unregister Cyclades serial "
"driver(%d)\n", e1);
- put_tty_driver(cy_serial_driver);
-
#ifdef CONFIG_PCI
pci_unregister_driver(&cy_pci_driver);
#endif
for (i = 0; i < NR_CARDS; i++) {
- if (cy_card[i].base_addr) {
+ card = &cy_card[i];
+ if (card->base_addr) {
/* clear interrupt */
- cy_writeb(cy_card[i].base_addr + Cy_ClrIntr, 0);
- iounmap(cy_card[i].base_addr);
- if (cy_card[i].ctl_addr)
- iounmap(cy_card[i].ctl_addr);
- if (cy_card[i].irq
+ cy_writeb(card->base_addr + Cy_ClrIntr, 0);
+ iounmap(card->base_addr);
+ if (card->ctl_addr)
+ iounmap(card->ctl_addr);
+ if (card->irq
#ifndef CONFIG_CYZ_INTR
- && !IS_CYC_Z(cy_card[i])
+ && !IS_CYC_Z(*card)
#endif /* CONFIG_CYZ_INTR */
)
- free_irq(cy_card[i].irq, &cy_card[i]);
- for (e1 = cy_card[i].first_line;
- e1 < cy_card[i].first_line +
- cy_card[i].nports; e1++)
+ free_irq(card->irq, card);
+ for (e1 = card->first_line;
+ e1 < card->first_line +
+ card->nports; e1++)
tty_unregister_device(cy_serial_driver, e1);
+ kfree(card->ports);
}
}
+
+ put_tty_driver(cy_serial_driver);
} /* cy_cleanup_module */
module_init(cy_init);