Commit ce97a097 authored by Jiri Slaby's avatar Jiri Slaby Committed by Linus Torvalds

Char: cyclades, make the isr code readable

Due to large indent the code was wrapped and unreadable.  Create 3 function
instead of one and reorder the code, so it is readable now.
Signed-off-by: default avatarJiri Slaby <jirislaby@gmail.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent ebafeeff
......@@ -980,378 +980,342 @@ static unsigned detect_isa_irq(void __iomem * address)
}
#endif /* CONFIG_ISA */
static void cyy_intr_chip(struct cyclades_card *cinfo, int chip,
void __iomem * base_addr, int status, int index)
static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
void __iomem *base_addr)
{
struct cyclades_port *info;
struct tty_struct *tty;
int char_count;
int j, len, mdm_change, mdm_status, outch;
int j, len, index = cinfo->bus_index;
int save_xir, channel, save_car;
char data;
if (status & CySRReceive) { /* reception interrupt */
#ifdef CY_DEBUG_INTERRUPTS
printk(KERN_DEBUG "cyy_interrupt: rcvd intr, chip %d\n", chip);
printk(KERN_DEBUG "cyy_interrupt: rcvd intr, chip %d\n", chip);
#endif
/* determine the channel & change to that context */
spin_lock(&cinfo->card_lock);
save_xir = (u_char) readb(base_addr + (CyRIR << index));
channel = (u_short) (save_xir & CyIRChannel);
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 == NULL) {
j = (readb(base_addr + (CyRIVR << index)) &
CyIVRMask);
if (j == CyIVRRxEx) { /* exception */
data = readb(base_addr + (CyRDSR << index));
} else { /* normal character reception */
char_count = readb(base_addr +
(CyRDCR << index));
while (char_count--) {
data = readb(base_addr +
(CyRDSR << index));
}
}
} else { /* there is an open port for this data */
tty = info->tty;
j = (readb(base_addr + (CyRIVR << index)) &
CyIVRMask);
if (j == CyIVRRxEx) { /* exception */
/* determine the channel & change to that context */
spin_lock(&cinfo->card_lock);
save_xir = (u_char) readb(base_addr + (CyRIR << index));
channel = (u_short) (save_xir & CyIRChannel);
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 == NULL) {
j = (readb(base_addr + (CyRIVR << index)) & CyIVRMask);
if (j == CyIVRRxEx) { /* exception */
data = readb(base_addr + (CyRDSR << index));
} else { /* normal character reception */
char_count = readb(base_addr + (CyRDCR << index));
while (char_count--)
data = readb(base_addr + (CyRDSR << index));
/* For statistics only */
if (data & CyBREAK)
info->icount.brk++;
else if (data & CyFRAME)
info->icount.frame++;
else if (data & CyPARITY)
info->icount.parity++;
else if (data & CyOVERRUN)
info->icount.overrun++;
if (data & info->ignore_status_mask) {
}
goto end;
}
/* there is an open port for this data */
tty = info->tty;
j = readb(base_addr + (CyRIVR << index)) & CyIVRMask;
if (j == CyIVRRxEx) { /* exception */
data = readb(base_addr + (CyRDSR << index));
/* For statistics only */
if (data & CyBREAK)
info->icount.brk++;
else if (data & CyFRAME)
info->icount.frame++;
else if (data & CyPARITY)
info->icount.parity++;
else if (data & CyOVERRUN)
info->icount.overrun++;
if (data & info->ignore_status_mask) {
info->icount.rx++;
spin_unlock(&cinfo->card_lock);
return;
}
if (tty_buffer_request_room(tty, 1)) {
if (data & info->read_status_mask) {
if (data & CyBREAK) {
tty_insert_flip_char(tty,
readb(base_addr + (CyRDSR <<
index)), TTY_BREAK);
info->icount.rx++;
if (info->flags & ASYNC_SAK)
do_SAK(tty);
} else if (data & CyFRAME) {
tty_insert_flip_char( tty,
readb(base_addr + (CyRDSR <<
index)), TTY_FRAME);
info->icount.rx++;
info->idle_stats.frame_errs++;
} else if (data & CyPARITY) {
/* Pieces of seven... */
tty_insert_flip_char(tty,
readb(base_addr + (CyRDSR <<
index)), TTY_PARITY);
info->icount.rx++;
info->idle_stats.parity_errs++;
} else if (data & CyOVERRUN) {
tty_insert_flip_char(tty, 0,
TTY_OVERRUN);
info->icount.rx++;
/* If the flip buffer itself is
overflowing, we still lose
the next incoming character.
*/
tty_insert_flip_char(tty,
readb(base_addr + (CyRDSR <<
index)), TTY_FRAME);
info->icount.rx++;
spin_unlock(&cinfo->card_lock);
return;
}
if (tty_buffer_request_room(tty, 1)) {
if (data & info->read_status_mask) {
if (data & CyBREAK) {
tty_insert_flip_char(
tty,
readb(
base_addr +
(CyRDSR <<
index)),
TTY_BREAK);
info->icount.rx++;
if (info->flags &
ASYNC_SAK) {
do_SAK(tty);
}
} else if (data & CyFRAME) {
tty_insert_flip_char(
tty,
readb(
base_addr +
(CyRDSR <<
index)),
TTY_FRAME);
info->icount.rx++;
info->idle_stats.
frame_errs++;
} else if (data & CyPARITY) {
/* Pieces of seven... */
tty_insert_flip_char(
tty,
readb(
base_addr +
(CyRDSR <<
index)),
TTY_PARITY);
info->icount.rx++;
info->idle_stats.
parity_errs++;
} else if (data & CyOVERRUN) {
tty_insert_flip_char(
tty, 0,
TTY_OVERRUN);
info->icount.rx++;
/* If the flip buffer itself is
overflowing, we still lose
the next incoming character.
*/
tty_insert_flip_char(
tty,
readb(
base_addr +
(CyRDSR <<
index)),
TTY_FRAME);
info->icount.rx++;
info->idle_stats.
overruns++;
/* These two conditions may imply */
/* a normal read should be done. */
/* }else if(data & CyTIMEOUT){ */
/* }else if(data & CySPECHAR){ */
} else {
tty_insert_flip_char(
tty, 0,
TTY_NORMAL);
info->icount.rx++;
}
} else {
tty_insert_flip_char(tty, 0,
TTY_NORMAL);
info->icount.rx++;
}
} else {
/* there was a software buffer
overrun and nothing could be
done about it!!! */
info->icount.buf_overrun++;
info->idle_stats.overruns++;
/* These two conditions may imply */
/* a normal read should be done. */
/* } else if(data & CyTIMEOUT) { */
/* } else if(data & CySPECHAR) { */
} else {
tty_insert_flip_char(tty, 0,
TTY_NORMAL);
info->icount.rx++;
}
} else { /* normal character reception */
/* load # chars available from the chip */
char_count = readb(base_addr +
(CyRDCR << index));
} else {
tty_insert_flip_char(tty, 0, TTY_NORMAL);
info->icount.rx++;
}
} else {
/* there was a software buffer overrun and nothing
* could be done about it!!! */
info->icount.buf_overrun++;
info->idle_stats.overruns++;
}
} else { /* normal character reception */
/* load # chars available from the chip */
char_count = readb(base_addr + (CyRDCR << index));
#ifdef CY_ENABLE_MONITORING
++info->mon.int_count;
info->mon.char_count += char_count;
if (char_count > info->mon.char_max)
info->mon.char_max = char_count;
info->mon.char_last = char_count;
++info->mon.int_count;
info->mon.char_count += char_count;
if (char_count > info->mon.char_max)
info->mon.char_max = char_count;
info->mon.char_last = char_count;
#endif
len = tty_buffer_request_room(tty, char_count);
while (len--) {
data = readb(base_addr +
(CyRDSR << index));
tty_insert_flip_char(tty, data,
TTY_NORMAL);
info->idle_stats.recv_bytes++;
info->icount.rx++;
len = tty_buffer_request_room(tty, char_count);
while (len--) {
data = readb(base_addr + (CyRDSR << index));
tty_insert_flip_char(tty, data, TTY_NORMAL);
info->idle_stats.recv_bytes++;
info->icount.rx++;
#ifdef CY_16Y_HACK
udelay(10L);
udelay(10L);
#endif
}
info->idle_stats.recv_idle = jiffies;
}
tty_schedule_flip(tty);
}
/* end of service */
cy_writeb(base_addr + (CyRIR << index), (save_xir & 0x3f));
cy_writeb(base_addr + (CyCAR << index), (save_car));
spin_unlock(&cinfo->card_lock);
info->idle_stats.recv_idle = jiffies;
}
tty_schedule_flip(tty);
end:
/* end of service */
cy_writeb(base_addr + (CyRIR << index), save_xir & 0x3f);
cy_writeb(base_addr + (CyCAR << index), save_car);
spin_unlock(&cinfo->card_lock);
}
static void cyy_chip_tx(struct cyclades_card *cinfo, int chip,
void __iomem *base_addr)
{
struct cyclades_port *info;
int char_count;
int outch;
int save_xir, channel, save_car, index = cinfo->bus_index;
if (status & CySRTransmit) { /* transmission interrupt */
/* Since we only get here when the transmit buffer
is empty, we know we can always stuff a dozen
characters. */
/* Since we only get here when the transmit buffer
is empty, we know we can always stuff a dozen
characters. */
#ifdef CY_DEBUG_INTERRUPTS
printk(KERN_DEBUG "cyy_interrupt: xmit intr, chip %d\n", chip);
printk(KERN_DEBUG "cyy_interrupt: xmit intr, chip %d\n", chip);
#endif
/* determine the channel & change to that context */
spin_lock(&cinfo->card_lock);
save_xir = (u_char) readb(base_addr + (CyTIR << index));
channel = (u_short) (save_xir & CyIRChannel);
save_car = readb(base_addr + (CyCAR << index));
cy_writeb(base_addr + (CyCAR << index), save_xir);
/* determine the channel & change to that context */
spin_lock(&cinfo->card_lock);
save_xir = (u_char) readb(base_addr + (CyTIR << index));
channel = (u_short) (save_xir & CyIRChannel);
save_car = readb(base_addr + (CyCAR << index));
cy_writeb(base_addr + (CyCAR << index), save_xir);
/* validate the port# (as configured and open) */
if (channel + chip * 4 >= cinfo->nports) {
cy_writeb(base_addr + (CySRER << index),
readb(base_addr + (CySRER << index)) &
~CyTxRdy);
goto txend;
}
info = &cinfo->ports[channel + chip * 4];
if (info->tty == NULL) {
cy_writeb(base_addr + (CySRER << index),
readb(base_addr + (CySRER << index)) &
~CyTxRdy);
goto txend;
}
/* validate the port# (as configured and open) */
if (channel + chip * 4 >= cinfo->nports) {
cy_writeb(base_addr + (CySRER << index),
readb(base_addr + (CySRER << index)) & ~CyTxRdy);
goto end;
}
info = &cinfo->ports[channel + chip * 4];
if (info->tty == NULL) {
cy_writeb(base_addr + (CySRER << index),
readb(base_addr + (CySRER << index)) & ~CyTxRdy);
goto end;
}
/* load the on-chip space for outbound data */
char_count = info->xmit_fifo_size;
/* load the on-chip space for outbound data */
char_count = info->xmit_fifo_size;
if (info->x_char) { /* send special char */
outch = info->x_char;
cy_writeb(base_addr + (CyTDR << index), outch);
char_count--;
info->icount.tx++;
info->x_char = 0;
}
if (info->x_char) { /* send special char */
outch = info->x_char;
cy_writeb(base_addr + (CyTDR << index), outch);
char_count--;
info->icount.tx++;
info->x_char = 0;
}
if (info->breakon || info->breakoff) {
if (info->breakon) {
cy_writeb(base_addr + (CyTDR << index), 0);
cy_writeb(base_addr + (CyTDR << index), 0x81);
info->breakon = 0;
char_count -= 2;
}
if (info->breakoff) {
cy_writeb(base_addr + (CyTDR << index), 0);
cy_writeb(base_addr + (CyTDR << index), 0x83);
info->breakoff = 0;
char_count -= 2;
}
if (info->breakon || info->breakoff) {
if (info->breakon) {
cy_writeb(base_addr + (CyTDR << index), 0);
cy_writeb(base_addr + (CyTDR << index), 0x81);
info->breakon = 0;
char_count -= 2;
}
if (info->breakoff) {
cy_writeb(base_addr + (CyTDR << index), 0);
cy_writeb(base_addr + (CyTDR << index), 0x83);
info->breakoff = 0;
char_count -= 2;
}
}
while (char_count-- > 0) {
if (!info->xmit_cnt) {
if (readb(base_addr + (CySRER << index)) &
CyTxMpty) {
cy_writeb(base_addr + (CySRER << index),
readb(base_addr +
(CySRER << index)) &
while (char_count-- > 0) {
if (!info->xmit_cnt) {
if (readb(base_addr + (CySRER << index)) & CyTxMpty) {
cy_writeb(base_addr + (CySRER << index),
readb(base_addr + (CySRER << index)) &
~CyTxMpty);
} else {
cy_writeb(base_addr + (CySRER << index),
(readb(base_addr +
(CySRER << index)) &
} else {
cy_writeb(base_addr + (CySRER << index),
(readb(base_addr + (CySRER << index)) &
~CyTxRdy) | CyTxMpty);
}
goto txdone;
}
if (info->xmit_buf == NULL) {
cy_writeb(base_addr + (CySRER << index),
readb(base_addr + (CySRER << index)) &
goto done;
}
if (info->xmit_buf == NULL) {
cy_writeb(base_addr + (CySRER << index),
readb(base_addr + (CySRER << index)) &
~CyTxRdy);
goto txdone;
}
if (info->tty->stopped || info->tty->hw_stopped) {
cy_writeb(base_addr + (CySRER << index),
readb(base_addr + (CySRER << index)) &
goto done;
}
if (info->tty->stopped || info->tty->hw_stopped) {
cy_writeb(base_addr + (CySRER << index),
readb(base_addr + (CySRER << index)) &
~CyTxRdy);
goto txdone;
}
/* Because the Embedded Transmit Commands have
been enabled, we must check to see if the
escape character, NULL, is being sent. If it
is, we must ensure that there is room for it
to be doubled in the output stream. Therefore
we no longer advance the pointer when the
character is fetched, but rather wait until
after the check for a NULL output 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];
if (outch) {
goto done;
}
/* Because the Embedded Transmit Commands have been enabled,
* we must check to see if the escape character, NULL, is being
* sent. If it is, we must ensure that there is room for it to
* be doubled in the output stream. Therefore we no longer
* advance the pointer when the character is fetched, but
* rather wait until after the check for a NULL output
* 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];
if (outch) {
info->xmit_cnt--;
info->xmit_tail = (info->xmit_tail + 1) &
(SERIAL_XMIT_SIZE - 1);
cy_writeb(base_addr + (CyTDR << index), outch);
info->icount.tx++;
} else {
if (char_count > 1) {
info->xmit_cnt--;
info->xmit_tail = (info->xmit_tail + 1) &
(SERIAL_XMIT_SIZE - 1);
(SERIAL_XMIT_SIZE - 1);
cy_writeb(base_addr + (CyTDR << index), outch);
cy_writeb(base_addr + (CyTDR << index), 0);
info->icount.tx++;
} else {
if (char_count > 1) {
info->xmit_cnt--;
info->xmit_tail = (info->xmit_tail + 1)&
(SERIAL_XMIT_SIZE - 1);
cy_writeb(base_addr + (CyTDR << index),
outch);
cy_writeb(base_addr + (CyTDR << index),
0);
info->icount.tx++;
char_count--;
}
char_count--;
}
}
txdone:
tty_wakeup(info->tty);
txend:
/* end of service */
cy_writeb(base_addr + (CyTIR << index), (save_xir & 0x3f));
cy_writeb(base_addr + (CyCAR << index), (save_car));
spin_unlock(&cinfo->card_lock);
}
if (status & CySRModem) { /* modem interrupt */
done:
tty_wakeup(info->tty);
end:
/* end of service */
cy_writeb(base_addr + (CyTIR << index), save_xir & 0x3f);
cy_writeb(base_addr + (CyCAR << index), save_car);
spin_unlock(&cinfo->card_lock);
}
static void cyy_chip_modem(struct cyclades_card *cinfo, int chip,
void __iomem *base_addr)
{
struct cyclades_port *info;
int mdm_change, mdm_status;
int save_xir, channel, save_car, index = cinfo->bus_index;
/* determine the channel & change to that context */
spin_lock(&cinfo->card_lock);
save_xir = (u_char) readb(base_addr + (CyMIR << index));
channel = (u_short) (save_xir & CyIRChannel);
info = &cinfo->ports[channel + chip * 4];
save_car = readb(base_addr + (CyCAR << index));
cy_writeb(base_addr + (CyCAR << index), save_xir);
/* determine the channel & change to that context */
spin_lock(&cinfo->card_lock);
save_xir = (u_char) readb(base_addr + (CyMIR << index));
channel = (u_short) (save_xir & CyIRChannel);
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));
mdm_change = readb(base_addr + (CyMISR << index));
mdm_status = readb(base_addr + (CyMSVR1 << index));
if (info->tty) {
if (mdm_change & CyANY_DELTA) {
/* For statistics only */
if (mdm_change & CyDCD)
info->icount.dcd++;
if (mdm_change & CyCTS)
info->icount.cts++;
if (mdm_change & CyDSR)
info->icount.dsr++;
if (mdm_change & CyRI)
info->icount.rng++;
wake_up_interruptible(&info->delta_msr_wait);
}
if (!info->tty)
goto end;
if ((mdm_change & CyDCD) &&
(info->flags & ASYNC_CHECK_CD)) {
if (!(mdm_status & CyDCD)) {
tty_hangup(info->tty);
info->flags &= ~ASYNC_NORMAL_ACTIVE;
}
wake_up_interruptible(&info->open_wait);
}
if ((mdm_change & CyCTS) &&
(info->flags & ASYNC_CTS_FLOW)) {
if (info->tty->hw_stopped) {
if (mdm_status & CyCTS) {
/* cy_start isn't used
because... !!! */
info->tty->hw_stopped = 0;
cy_writeb(base_addr +
(CySRER << index),
readb(base_addr +
(CySRER <<
index))|
CyTxRdy);
tty_wakeup(info->tty);
}
} else {
if (!(mdm_status & CyCTS)) {
/* cy_stop isn't used
because ... !!! */
info->tty->hw_stopped = 1;
cy_writeb(base_addr +
(CySRER << index),
readb(base_addr +
(CySRER <<
index)) &
~CyTxRdy);
}
}
if (mdm_change & CyANY_DELTA) {
/* For statistics only */
if (mdm_change & CyDCD)
info->icount.dcd++;
if (mdm_change & CyCTS)
info->icount.cts++;
if (mdm_change & CyDSR)
info->icount.dsr++;
if (mdm_change & CyRI)
info->icount.rng++;
wake_up_interruptible(&info->delta_msr_wait);
}
if ((mdm_change & CyDCD) && (info->flags & ASYNC_CHECK_CD)) {
if (!(mdm_status & CyDCD)) {
tty_hangup(info->tty);
info->flags &= ~ASYNC_NORMAL_ACTIVE;
}
wake_up_interruptible(&info->open_wait);
}
if ((mdm_change & CyCTS) && (info->flags & ASYNC_CTS_FLOW)) {
if (info->tty->hw_stopped) {
if (mdm_status & CyCTS) {
/* cy_start isn't used
because... !!! */
info->tty->hw_stopped = 0;
cy_writeb(base_addr + (CySRER << index),
readb(base_addr + (CySRER << index)) |
CyTxRdy);
tty_wakeup(info->tty);
}
/* if (mdm_change & CyDSR) {
} else {
if (!(mdm_status & CyCTS)) {
/* cy_stop isn't used
because ... !!! */
info->tty->hw_stopped = 1;
cy_writeb(base_addr + (CySRER << index),
readb(base_addr + (CySRER << index)) &
~CyTxRdy);
}
if (mdm_change & CyRI) {
}*/
}
/* end of service */
cy_writeb(base_addr + (CyMIR << index), (save_xir & 0x3f));
cy_writeb(base_addr + (CyCAR << index), save_car);
spin_unlock(&cinfo->card_lock);
}
/* if (mdm_change & CyDSR) {
}
if (mdm_change & CyRI) {
}*/
end:
/* end of service */
cy_writeb(base_addr + (CyMIR << index), save_xir & 0x3f);
cy_writeb(base_addr + (CyCAR << index), save_car);
spin_unlock(&cinfo->card_lock);
}
/* The real interrupt service routine is called
......@@ -1401,11 +1365,14 @@ static irqreturn_t cyy_interrupt(int irq, void *dev_id)
chips to be checked in a round-robin fashion (after
draining each of a bunch (1000) of characters).
*/
if (1000 < too_many++) {
if (1000 < too_many++)
break;
}
cyy_intr_chip(cinfo, chip, base_addr, status,
index);
if (status & CySRReceive) /* rx intr */
cyy_chip_rx(cinfo, chip, base_addr);
if (status & CySRTransmit) /* tx intr */
cyy_chip_tx(cinfo, chip, base_addr);
if (status & CySRModem) /* modem intr */
cyy_chip_modem(cinfo, chip, base_addr);
}
}
} while (had_work);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment