patch-2.4.15 linux/arch/cris/drivers/serial.c
Next file: linux/arch/cris/drivers/serial.h
Previous file: linux/arch/cris/drivers/gpio.c
Back to the patch index
Back to the overall index
- Lines: 1361
- Date:
Fri Nov 9 13:58:02 2001
- Orig file:
v2.4.14/linux/arch/cris/drivers/serial.c
- Orig date:
Tue Oct 9 17:06:51 2001
diff -u --recursive --new-file v2.4.14/linux/arch/cris/drivers/serial.c linux/arch/cris/drivers/serial.c
@@ -1,4 +1,4 @@
-/* $Id: serial.c,v 1.18 2001/09/24 09:27:22 pkj Exp $
+/* $Id: serial.c,v 1.23 2001/10/30 17:53:26 pkj Exp $
*
* Serial port driver for the ETRAX 100LX chip
*
@@ -7,6 +7,27 @@
* Many, many authors. Based once upon a time on serial.c for 16x50.
*
* $Log: serial.c,v $
+ * Revision 1.23 2001/10/30 17:53:26 pkj
+ * * Set info->uses_dma to 0 when a port is closed.
+ * * Mark the timer1 interrupt as a fast one (SA_INTERRUPT).
+ * * Call start_flush_timer() in start_receive() if
+ * CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST is defined.
+ *
+ * Revision 1.22 2001/10/30 17:44:03 pkj
+ * Use %lu for received and transmitted counters in line_info().
+ *
+ * Revision 1.21 2001/10/30 17:40:34 pkj
+ * Clean-up. The only change to functionality is that
+ * CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS(=5) is used instead of
+ * MAX_FLUSH_TIME(=8).
+ *
+ * Revision 1.20 2001/10/30 15:24:49 johana
+ * Added char_time stuff from 2.0 driver.
+ *
+ * Revision 1.19 2001/10/30 15:23:03 johana
+ * Merged with 1.13.2 branch + fixed indentation
+ * and changed CONFIG_ETRAX100_XYS to CONFIG_ETRAX_XYZ
+ *
* Revision 1.18 2001/09/24 09:27:22 pkj
* Completed ext_baud_table[] in cflag_to_baud() and cflag_to_etrax_baud().
*
@@ -26,11 +47,19 @@
* Revision 1.14 2001/08/15 07:31:23 bjarne
* Introduced two new members to the e100_serial struct.
* configured - Will be set to 1 if the port has been configured in .config
- * uses_dma - Should be set to 1 if the port uses DMA. Currently it is set to 1
+ * uses_dma - Should be set to 1 if the port uses DMA. Currently it is set
+ * to 1
* when a port is opened. This is used to limit the DMA interrupt
* routines to only manipulate DMA channels actually used by the
* serial driver.
*
+ * Revision 1.13.2.2 2001/10/17 13:57:13 starvik
+ * Receiver was broken by the break fixes
+ *
+ * Revision 1.13.2.1 2001/07/20 13:57:39 ronny
+ * Merge with new stuff from etrax100ser.c. Works but haven't checked stuff
+ * like break handling.
+ *
* Revision 1.13 2001/05/09 12:40:31 johana
* Use DMA_NBR and IRQ_NBR defines from dma.h and irq.h
*
@@ -226,7 +255,7 @@
*
*/
-static char *serial_version = "$Revision: 1.18 $";
+static char *serial_version = "$Revision: 1.23 $";
#include <linux/config.h>
#include <linux/version.h>
@@ -284,6 +313,11 @@
#define SERIAL_TYPE_CALLOUT 2
#endif
+#define DEBUG_LOG(line, string, value)
+
+/* Add an x here to log a lot of timer stuff */
+#define TIMERD(x)
+
/* number of characters left in xmit buffer before we ask for more */
#define WAKEUP_CHARS 256
@@ -299,8 +333,9 @@
expect the first received event on the serial port to
be an error, break or similar. Used to be able to flash IRMA
from eLinux */
-//#define SERIAL_HANDLE_EARLY_ERRORS
+#define SERIAL_HANDLE_EARLY_ERRORS
+#define TTY_THROTTLE_LIMIT (TTY_FLIPBUF_SIZE/10)
#ifndef CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS
/* Default number of timer ticks before flushing rx fifo
@@ -310,8 +345,6 @@
#define CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS 5
#endif
-#define MAX_FLUSH_TIME 8
-
#define _INLINE_ inline
static void change_speed(struct e100_serial *info);
@@ -320,7 +353,7 @@
const unsigned char *buf, int count);
#define DEF_BAUD 0x99 /* 115.2 kbit/s */
-#define STD_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST )
+#define STD_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
#define DEF_RX 0x20 /* or SERIAL_CTRL_W >> 8 */
/* Default value of tx_ctrl register: has txd(bit 7)=1 (idle) as default */
#define DEF_TX 0x80 /* or SERIAL_CTRL_B */
@@ -335,6 +368,22 @@
#define REG_BAUD 3
#define REG_XOFF 4 /* this is a 32 bit register */
+/* The bitfields are the same for all serial ports */
+#define SER_RXD_MASK IO_MASK(R_SERIAL0_STATUS, rxd)
+#define SER_DATA_AVAIL_MASK IO_MASK(R_SERIAL0_STATUS, data_avail)
+#define SER_FRAMING_ERR_MASK IO_MASK(R_SERIAL0_STATUS, framing_err)
+#define SER_PAR_ERR_MASK IO_MASK(R_SERIAL0_STATUS, par_err)
+#define SER_OVERRUN_MASK IO_MASK(R_SERIAL0_STATUS, overrun)
+
+#define SER_ERROR_MASK (SER_OVERRUN_MASK | SER_PAR_ERR_MASK | SER_FRAMING_ERR_MASK)
+
+/* Values for info->errorcode */
+#define ERRCODE_SET_BREAK (TTY_BREAK)
+#define ERRCODE_INSERT 0x100
+#define ERRCODE_INSERT_BREAK (ERRCODE_INSERT | TTY_BREAK)
+
+#define FORCE_EOP(info) *R_SET_EOP = 1U << info->iseteop;
+
/*
* General note regarding the use of IO_* macros in this file:
*
@@ -413,6 +462,29 @@
static struct termios *serial_termios[NR_PORTS];
static struct termios *serial_termios_locked[NR_PORTS];
+#ifdef CONFIG_SERIAL_PROC_ENTRY
+#define PROCSTAT(x) x
+struct ser_statistics_type{
+ int overrun_cnt;
+ int early_errors_cnt;
+ int ser_ints_ok_cnt;
+ int errors_cnt;
+ unsigned long int processing_flip;
+ unsigned long processing_flip_still_room;
+ unsigned long int timeout_flush_cnt;
+ int rx_dma_ints;
+ int tx_dma_ints;
+ int rx_tot;
+ int tx_tot;
+};
+
+static struct ser_statistics_type ser_stat[NR_PORTS];
+
+#else
+
+#define PROCSTAT(x)
+
+#endif /* CONFIG_SERIAL_PROC_ENTRY */
/* RS-485 */
#if defined(CONFIG_ETRAX_RS485)
@@ -577,10 +649,34 @@
/* enable timer1 irq */
*R_IRQ_MASK0_SET = IO_STATE(R_IRQ_MASK0_SET, timer1, set);
+
fast_timer_started = 1;
}
#endif /* CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST */
+/* Calculate the chartime depending on baudrate, numbor of bits etc. */
+static void update_char_time(struct e100_serial * info)
+{
+ tcflag_t cflags = info->tty->termios->c_cflag;
+ int bits;
+
+ /* calc. number of bits / data byte */
+ /* databits + startbit and 1 stopbit */
+ if ((cflags & CSIZE) == CS7)
+ bits = 9;
+ else
+ bits = 10;
+
+ if (cflags & CSTOPB) /* 2 stopbits ? */
+ bits++;
+
+ if (cflags & PARENB) /* parity bit ? */
+ bits++;
+
+ /* calc timeout */
+ info->char_time_usec = ((bits * 1000000) / info->baud) + 1;
+}
+
/*
* This function maps from the Bxxxx defines in asm/termbits.h into real
* baud rates.
@@ -642,7 +738,8 @@
e100_dtr(struct e100_serial *info, int set)
{
#ifndef CONFIG_SVINTO_SIM
- unsigned char mask = ( 1 << e100_modem_pins[info->line].dtr_bit);
+ unsigned char mask = (1 << e100_modem_pins[info->line].dtr_bit);
+
#ifdef SERIAL_DEBUG_IO
printk("ser%i dtr %i mask: 0x%02X\n", info->line, set, mask);
printk("ser%i shadow before 0x%02X get: %i\n",
@@ -651,7 +748,8 @@
#endif
/* DTR is active low */
{
- unsigned long flags;
+ unsigned long flags;
+
save_flags(flags);
cli();
*e100_modem_pins[info->line].shadow &= ~mask;
@@ -696,8 +794,9 @@
#ifndef CONFIG_SVINTO_SIM
/* RI is active low */
{
- unsigned char mask = ( 1 << e100_modem_pins[info->line].ri_bit);
- unsigned long flags;
+ unsigned char mask = (1 << e100_modem_pins[info->line].ri_bit);
+ unsigned long flags;
+
save_flags(flags);
cli();
*e100_modem_pins[info->line].shadow &= ~mask;
@@ -718,8 +817,9 @@
#ifndef CONFIG_SVINTO_SIM
/* CD is active low */
{
- unsigned char mask = ( 1 << e100_modem_pins[info->line].cd_bit);
- unsigned long flags;
+ unsigned char mask = (1 << e100_modem_pins[info->line].cd_bit);
+ unsigned long flags;
+
save_flags(flags);
cli();
*e100_modem_pins[info->line].shadow &= ~mask;
@@ -797,7 +897,7 @@
#ifdef SERIAL_HANDLE_EARLY_ERRORS
/* in order to detect and fix errors on the first byte
- we have to use the serial interrupts as well. */
+ we have to use the serial interrupts as well. */
static inline void
e100_disable_serial_data_irq(struct e100_serial *info)
@@ -860,7 +960,7 @@
e100_disable_rxdma_irq(info);
#endif
- if (info->rs485.delay_rts_before_send > 0){
+ if (info->rs485.delay_rts_before_send > 0) {
current->timeout = jiffies + (info->rs485.delay_rts_before_send * HZ)/1000;
current->state = TASK_INTERRUPTIBLE;
schedule();
@@ -880,36 +980,38 @@
/* calc. number of bits / data byte */
cflags = info->tty->termios->c_cflag;
+
/* databits + startbit and 1 stopbit */
- if((cflags & CSIZE) == CS7)
- bits = 9;
+ if ((cflags & CSIZE) == CS7)
+ bits = 9;
else
- bits = 10;
+ bits = 10;
- if(cflags & CSTOPB) /* 2 stopbits ? */
- bits++;
+ if (cflags & CSTOPB) /* 2 stopbits ? */
+ bits++;
- if(cflags & PARENB) /* parity bit ? */
- bits++;
+ if (cflags & PARENB) /* parity bit ? */
+ bits++;
/* calc timeout */
delay_ms = ((bits * size * 1000) / info->baud) + 1;
max_j = jiffies + (delay_ms * HZ)/1000 + 10;
- while (jiffies < max_j ) {
- if (info->port[REG_STATUS] &
- IO_STATE(R_SERIAL0_STATUS, tr_ready, ready)) {
- for( i=0 ; i<100; i++ ) {};
- if (info->port[REG_STATUS] &
- IO_STATE(R_SERIAL0_STATUS, tr_ready, ready)) {
- /* ~25 for loops per usec */
- stop_delay = 1000000 / info->baud;
- if(cflags & CSTOPB)
- stop_delay *= 2;
- udelay(stop_delay);
- break;
- }
- }
+ while (jiffies < max_j) {
+ if (info->port[REG_STATUS] &
+ IO_STATE(R_SERIAL0_STATUS, tr_ready, ready)) {
+ for (i = 0; i < 100; i++)
+ ;
+ if (info->port[REG_STATUS] &
+ IO_STATE(R_SERIAL0_STATUS, tr_ready, ready)) {
+ /* ~25 for loops per usec */
+ stop_delay = 1000000 / info->baud;
+ if (cflags & CSTOPB)
+ stop_delay *= 2;
+ udelay(stop_delay);
+ break;
+ }
+ }
}
e100_rts(info, info->rs485.rts_after_sent);
@@ -1004,9 +1106,9 @@
* no-op - transmit_chars would never really be called during sim
* since rs_write does not write into the xmit buffer then.
*/
- if(info->xmit.tail)
+ if (info->xmit.tail)
printk("Error in serial.c:transmit_chars(), tail!=0\n");
- if(info->xmit.head != info->xmit.tail) {
+ if (info->xmit.head != info->xmit.tail) {
SIMCOUT(info->xmit.buf + info->xmit.tail,
CIRC_CNT(info->xmit.head,
info->xmit.tail,
@@ -1022,10 +1124,10 @@
IO_STATE(R_DMA_CH6_CLR_INTR, clr_eop, do);
#ifdef SERIAL_DEBUG_INTR
- if(info->line == SERIAL_DEBUG_LINE)
+ if (info->line == SERIAL_DEBUG_LINE)
printk("tc\n");
#endif
- if(!info->tr_running) {
+ if (!info->tr_running) {
/* weirdo... we shouldn't get here! */
printk("Achtung: transmit_chars with !tr_running\n");
return;
@@ -1037,7 +1139,7 @@
and update xmit accordingly */
/* if the stop bit was not set, all data has been sent */
- if(!(descr->status & d_stop)) {
+ if (!(descr->status & d_stop)) {
sentl = descr->sw_len;
} else
/* otherwise we find the amount of data sent here */
@@ -1060,7 +1162,7 @@
c = CIRC_CNT_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
- if(c <= 0) {
+ if (c <= 0) {
/* our job here is done, don't schedule any new DMA transfer */
info->tr_running = 0;
@@ -1106,7 +1208,7 @@
start_transmit(struct e100_serial *info)
{
#if 0
- if(info->line == SERIAL_DEBUG_LINE)
+ if (info->line == SERIAL_DEBUG_LINE)
printk("x\n");
#endif
@@ -1118,7 +1220,6 @@
transmit_chars(info);
}
-
static _INLINE_ void
receive_chars(struct e100_serial *info)
{
@@ -1138,79 +1239,128 @@
/* acknowledge both a dma_descr and dma_eop irq in R_DMAx_CLRINTR */
+ // ?
*info->iclrintradr =
IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) |
IO_STATE(R_DMA_CH6_CLR_INTR, clr_eop, do);
- if(!tty) /* something wrong... */
+ if (!tty) /* something wrong... */
return;
descr = &info->rec_descr;
-
+
/* find out how many bytes were read */
/* if the eop bit was not set, all data has been received */
- if(!(descr->status & d_eop)) {
+ if (!(descr->status & d_eop)) {
recvl = descr->sw_len;
} else {
/* otherwise we find the amount of data received here */
recvl = descr->hw_len;
}
- if(recvl) {
- unsigned char *buf;
- struct async_icount *icount;
- icount = &info->icount;
-
- /* update stats */
- icount->rx += recvl;
+ /* read the status register so we can detect errors,
+ * but we can't really do anything about those errors
+ * anyway, since we have the DMA in "force eop at error" mode
+ * the fault characters are not in the buffer anyway.
+ */
- /* read the status register so we can detect errors */
- rstat = info->port[REG_STATUS];
+ rstat = info->port[REG_STATUS];
+
+ if ((rstat & SER_ERROR_MASK) != 0) {
+ unsigned char data;
+ /* if we got an error, we must reset it by reading the
+ * data_in field
+ */
+ data = info->port[REG_DATA];
+ PROCSTAT(ser_stat[info->line].errors_cnt++);
+ DEBUG_LOG(info->line, " #dERR: s d 0x%04X\n",
+ ((rstat & SER_ERROR_MASK) << 8) | data);
+ /* Only handle the saved error code, that indicates that we got
+ * the last character of a break that looks like it's ok, but
+ * is not
+ */
- if(rstat & (IO_MASK(R_SERIAL0_STATUS, overrun) |
- IO_MASK(R_SERIAL0_STATUS, par_err) |
- IO_MASK(R_SERIAL0_STATUS, framing_err))) {
- /* if we got an error, we must reset it by reading the
- * data_in field
+ if (info->errorcode == 0) {
+ *tty->flip.flag_buf_ptr = TTY_NORMAL;
+ } else {
+ unsigned char data;
+ data = info->port[REG_DATA];
+ if (info->errorcode & ERRCODE_INSERT) {
+ unsigned char *currbuf;
+ /* Get the current buffer */
+ if (tty->flip.buf_num) {
+ currbuf = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
+ } else {
+ currbuf = tty->flip.char_buf;
+ }
+ /* We should insert a character in the buffer! */
+ if (recvl == 0) {
+ recvl = 1;
+ DEBUG_LOG(info->line, "insert to %lu\n", recvl);
+ } else {
+ /* Move stuff around.. */
+ DEBUG_LOG(info->line, "#insert to %lu!\n", recvl);
+ if (recvl < TTY_FLIPBUF_SIZE) {
+ int i;
+ /* Move the data 1 step right */
+ i = recvl;
+ while (i) {
+ currbuf[i] = currbuf[i-1];
+ i--;
+ }
+ recvl++;
+ } else {
+ /* We can't move it all! Skip break! */
+ /* TODO: Handle full buffer? */
+ DEBUG_LOG(info->line, "#BRK skipped! %lu!\n", recvl);
+ info->errorcode = 0;
+ }
+ }
+ }
+
+ PROCSTAT(ser_stat[info->line].errors_cnt++);
+ DEBUG_LOG(info->line, " #bERR: s d 0x%04X\n",
+ ((rstat & SER_ERROR_MASK) << 8) | data);
+ *tty->flip.flag_buf_ptr = (info->errorcode & 0xFF);
+ info->errorcode = 0;
+#if 0
+ printk("SERERR: 0x%02X data: 0x%02X\n", rstat & SER_ERROR_MASK, data);
+#endif
+ /* we only ever write errors into the first byte in
+ * the flip flag buffer, so we dont have to clear it
+ * all every time
*/
- (void)info->port[REG_DATA];
}
-
- /* we only ever write errors into the first byte in the flip
- * flag buffer, so we dont have to clear it all every time
- */
+ }
- if(rstat & 0x04) {
- icount->parity++;
- *tty->flip.flag_buf_ptr = TTY_PARITY;
- } else if(rstat & 0x08) {
- icount->overrun++;
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- } else if(rstat & 0x02) {
- icount->frame++;
- *tty->flip.flag_buf_ptr = TTY_FRAME;
- } else
- *tty->flip.flag_buf_ptr = 0;
+ DEBUG_LOG(info->line, "recvl %lu\n", recvl);
+
+ if (recvl) {
+ unsigned char *buf;
+ struct async_icount *icount = &info->icount;
+
+ /* update stats */
+ icount->rx += recvl;
/* use the flip buffer next in turn to restart DMA into */
-
+
if (tty->flip.buf_num) {
buf = tty->flip.char_buf;
} else {
buf = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
}
- if(buf == phys_to_virt(descr->buf)) {
+ if (buf == phys_to_virt(descr->buf)) {
printk("ttyS%d flip-buffer overrun!\n", info->line);
icount->overrun++;
*tty->flip.flag_buf_ptr = TTY_OVERRUN;
/* restart old buffer */
} else {
descr->buf = virt_to_phys(buf);
-
+
/* schedule or push a flip of the buffer */
-
+
info->tty->flip.count = recvl;
#if (LINUX_VERSION_CODE > 131394) /* 2.1.66 */
@@ -1221,9 +1371,9 @@
#endif
}
}
-
+
/* restart the receiving dma */
-
+
descr->sw_len = TTY_FLIPBUF_SIZE;
descr->ctrl = d_int | d_eol | d_eop;
descr->hw_len = 0;
@@ -1236,6 +1386,10 @@
e100_enable_serial_data_irq(info);
#endif
/* input dma should be running now */
+
+ /* unthrottle if we have throttled */
+ if (E100_RTS_GET(info))
+ tty->driver.unthrottle(info->tty);
}
static void
@@ -1253,8 +1407,8 @@
/* reset the input dma channel to be sure it works */
*info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
- while(IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->icmdadr) ==
- IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset));
+ while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->icmdadr) ==
+ IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset));
descr = &info->rec_descr;
@@ -1270,7 +1424,10 @@
*info->ifirstadr = virt_to_phys(descr);
*info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, start);
-
+
+#ifdef CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST
+ start_flush_timer();
+#endif
}
@@ -1313,12 +1470,12 @@
ireg = *R_IRQ_MASK2_RD; /* get the active irq bits for the dma channels */
- for(i = 0; i < NR_PORTS; i++) {
+ for (i = 0; i < NR_PORTS; i++) {
info = rs_table + i;
if (!info->uses_dma)
continue;
/* check for dma_descr (dont need to check for dma_eop in output dma for serial */
- if(ireg & info->irq) {
+ if (ireg & info->irq) {
/* we can send a new dma bunch. make it so. */
transmit_chars(info);
}
@@ -1352,12 +1509,12 @@
ireg = *R_IRQ_MASK2_RD; /* get the active irq bits for the dma channels */
- for(i = 0; i < NR_PORTS; i++) {
+ for (i = 0; i < NR_PORTS; i++) {
info = rs_table + i;
if (!info->uses_dma)
continue;
/* check for both dma_eop and dma_descr for the input dma channel */
- if(ireg & ((info->irq << 2) | (info->irq << 3))) {
+ if (ireg & ((info->irq << 2) | (info->irq << 3))) {
/* we have received something */
receive_chars(info);
}
@@ -1367,17 +1524,156 @@
}
}
+#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER
+static int serial_fast_timer_started = 0;
+static int serial_fast_timer_expired = 0;
+static void flush_timeout_function(unsigned long data);
+#define START_FLUSH_FAST_TIMER(info, string) {\
+ unsigned long timer_flags; \
+ save_flags(timer_flags); \
+ cli(); \
+ TIMERD(DEBUG_LOG(info->line, "start_timer? %i ", info->line)); \
+ if (fast_timers[info->line].function == NULL) { \
+ serial_fast_timer_started++; \
+ TIMERD(DEBUG_LOG(info->line, "start_timer %i ", info->line)); \
+ TIMERD(DEBUG_LOG(info->line, "num started: %i\n", serial_fast_timer_started)); \
+ start_one_shot_timer(&fast_timers[info->line], \
+ flush_timeout_function, \
+ (unsigned long)info, \
+ info->char_time_usec*4, \
+ string); \
+ } \
+ else { \
+ /* DEBUG_LOG(info->line, " ## timer %i running ##\n", info->line); */ \
+ } \
+ restore_flags(timer_flags); \
+}
+
+#else
+#define START_FLUSH_FAST_TIMER(info, string)
+#endif
+
+void _INLINE_ check_flush_timeout(struct e100_serial *info)
+{
+ unsigned char rstat;
+ unsigned int magic;
+
+ if (0 /*info->tty->processing_flip*/) {
+ if (!E100_RTS_GET(info)) {
+ int left = (*info->ihwswadr >> 16) - (*info->istatusadr & 0x3F);
+
+ if (left < TTY_THROTTLE_LIMIT)
+ info->tty->driver.throttle(info->tty);
+ }
+
+ PROCSTAT(ser_stat[info->line].processing_flip++);
+ START_FLUSH_FAST_TIMER(info, "flip");
+ return;
+ }
+
+ /* We check data_avail bit to determine if data has
+ * arrived since last time
+ */
+ magic = info->fifo_magic;
+#ifdef SERIAL_DEBUG_DATA
+ if (info->fifo_magic || info->fifo_didmagic) {
+ DEBUG_LOG(info->line, "timeout_int: did fifo_magic %03X\n",
+ (info->fifo_didmagic << 8) | info->fifo_magic);
+ }
+#endif
+ rstat = info->port[REG_STATUS];
+ /* error or datavail? */
+ if (rstat & SER_ERROR_MASK) {
+ /* Some error has occured */
+ /* If there has been valid data,
+ * an EOP interrupt will be made automatically.
+ * If no data, the normal ser_interrupt should be enabled
+ * and handle it.
+ * So do nothing!
+ */
+ DEBUG_LOG(info->line, "timeout err: rstat 0x%03X\n",
+ rstat | (info->line << 8));
+ return;
+ }
+ if (rstat & SER_DATA_AVAIL_MASK) {
+ /* Ok data, no error, count it */
+ TIMERD(DEBUG_LOG(info->line, "timeout: rstat 0x%03X\n",
+ rstat | (info->line << 8)));
+ /* Read data to clear status flags */
+ (void)info->port[REG_DATA];
+
+ magic++;
+ }
+
+ if (magic != info->fifo_magic) {
+ info->fifo_magic = magic;
+ info->fifo_didmagic = 0;
+ START_FLUSH_FAST_TIMER(info, "magic");
+ } else {
+ /* hit the timeout, force an EOP for the input
+ * dma channel if we haven't already
+ */
+ if (!info->fifo_didmagic && magic) {
+ info->fifo_didmagic = 1;
+ info->fifo_magic = 0;
+ PROCSTAT(ser_stat[info->line].timeout_flush_cnt++);
+ DEBUG_LOG(info->line, "timeout EOP %i\n", info->line);
+ TIMERD(DEBUG_LOG(info->line, "timeout magic %i\n", magic));
+ FORCE_EOP(info);
+ }
+ }
+} /* check_flush_timeout */
+
+#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER
+static void flush_timeout_function(unsigned long data)
+{
+ struct e100_serial *info = (struct e100_serial *)data;
+ fast_timers[info->line].function = NULL;
+ serial_fast_timer_expired++;
+ TIMERD(DEBUG_LOG(info->line, "flush_timout %i ", info->line));
+ TIMERD(DEBUG_LOG(info->line, "num expired: %i\n", serial_fast_timer_expired));
+ check_flush_timeout(info);
+}
+
+#elif defined(CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST)
+
+static void
+timeout_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct e100_serial *info;
+ int i;
+
+#ifdef CONFIG_SVINTO_SIM
+ /* No receive in the simulator. Will probably be when the rest of
+ * the serial interface works, and this piece will just be removed.
+ */
+ {
+ const char *s = "What? timeout_interrupt in simulator??\n";
+ SIMCOUT(s,strlen(s));
+ }
+ return;
+#endif
+
+ /* acknowledge the timer1 irq */
+ *R_TIMER_CTRL = r_timer_ctrl_shadow | IO_STATE(R_TIMER_CTRL, i1, clr);
+ PROCSTAT(fast_timer_ints++);
+
+ for (i = 0; i < NR_PORTS; i++) {
+ info = rs_table + i;
+ if (info->uses_dma)
+ check_flush_timeout(info);
+ }
+} /* timeout_interrupt */
+
+#else
+
/* dma fifo/buffer timeout handler
forces an end-of-packet for the dma input channel if no chars
- have been received for CONFIG_ETRAX_RX_TIMEOUT_TICKS/100 s.
+ have been received for CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS/100 s.
If CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST is configured then this
handler is instead run at 15360 Hz.
*/
-#ifndef CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST
-static int timeout_divider = 0;
-#endif
-
static struct timer_list flush_timer;
static void
@@ -1391,9 +1687,9 @@
return;
#endif
- for(i = 0; i < NR_PORTS; i++) {
+ for (i = 0; i < NR_PORTS; i++) {
info = rs_table + i;
- if(!info->enabled || !(info->flags & ASYNC_INITIALIZED))
+ if (!info->enabled || !(info->flags & ASYNC_INITIALIZED))
continue;
/* istatusadr (bit 6-0) hold number of bytes in fifo
@@ -1402,33 +1698,32 @@
*/
magic = (*info->istatusadr & 0x3f);
- magic += ((*info->ihwswadr&0xffff ) - (*info->ihwswadr >> 16));
+ magic += ((*info->ihwswadr & 0xffff) - (*info->ihwswadr >> 16));
/* if magic is equal to fifo_magic (magic in previous
* timeout_interrupt) then no new data has arrived since last
* interrupt and we'll force eop to flush fifo+dma buffers
*/
- if(magic != info->fifo_magic) {
+ if (magic != info->fifo_magic) {
info->fifo_magic = magic;
info->fifo_didmagic = 0;
} else {
/* hit the timeout, force an EOP for the input
* dma channel if we haven't already
*/
- if(!info->fifo_didmagic && magic) {
+ if (!info->fifo_didmagic && magic) {
info->fifo_didmagic = 1;
info->fifo_magic = 0;
- *R_SET_EOP = 1U << info->iseteop;
+ FORCE_EOP(info);
}
}
}
/* restart flush timer */
-
- mod_timer(&flush_timer, jiffies + MAX_FLUSH_TIME);
+ mod_timer(&flush_timer, jiffies + CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS);
}
-
+#endif
#ifdef SERIAL_HANDLE_EARLY_ERRORS
@@ -1439,48 +1734,190 @@
* interrupts off.
*/
+/*
+BREAK handling on ETRAX 100:
+ETRAX will generate interrupt although there is no stop bit between the
+characters.
+
+Depending on how long the break sequence is, the end of the breaksequence
+will look differently:
+| indicates start/end of a character.
+
+B= Break character (0x00) with framing error.
+E= Error byte with parity error received after B characters.
+F= "Faked" valid byte received immediatly after B characters.
+V= Valid byte
+
+1.
+ B BL ___________________________ V
+.._|__________|__________| |valid data |
+
+Multiple frame errors with data == 0x00 (B),
+the timing matches up "perfectly" so no extra ending char is detected.
+The RXD pin is 1 in the last interrupt, in that case
+we set info->errorcode = ERRCODE_INSERT_BREAK, but we can't really
+know if another byte will come and this really is case 2. below
+(e.g F=0xFF or 0xFE)
+If RXD pin is 0 we can expect another character (see 2. below).
+
+
+2.
+
+ B B E or F__________________..__ V
+.._|__________|__________|______ | |valid data
+ "valid" or
+ parity error
+
+Multiple frame errors with data == 0x00 (B),
+but the part of the break trigs is interpreted as a start bit (and possibly
+som 0 bits followed by a number of 1 bits and a stop bit).
+Depending on parity settings etc. this last character can be either
+a fake "valid" char (F) or have a parity error (E).
+
+If the character is valid it will be put in the buffer,
+we set info->errorcode = ERRCODE_SET_BREAK so the receive interrupt
+will set the flags so the tty will handle it,
+if it's an error byte it will not be put in the buffer
+and we set info->errorcode = ERRCODE_INSERT_BREAK.
+
+To distinguish a V byte in 1. from an F byte in 2. we keep a timestamp
+of the last faulty char (B) and compares it with the current time:
+If the time elapsed time is less then 2*char_time_usec we will assume
+it's a faked F char and not a Valid char and set
+info->errorcode = ERRCODE_SET_BREAK.
+
+Flaws in the above solution:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+We use the timer to distinguish a F character from a V character,
+if a V character is to close after the break we might make the wrong decision.
+
+TODO: The break will be delayed until an F or V character is received.
+
+*/
+
+static void _INLINE_ handle_ser_interrupt(struct e100_serial *info)
+{
+ unsigned char rstat = info->port[REG_STATUS];
+
+#ifdef SERIAL_DEBUG_INTR
+ printk("Interrupt from serport %d\n", i);
+#endif
+/* DEBUG_LOG(info->line, "ser_interrupt stat %03X\n", rstat | (i << 8)); */
+ if (rstat & SER_ERROR_MASK) {
+ unsigned char data;
+ info->last_rx_active_usec = GET_JIFFIES_USEC();
+ info->last_rx_active = jiffies;
+ /* if we got an error, we must reset it by
+ * reading the data_in field
+ */
+ data = info->port[REG_DATA];
+
+ if ((data == 0x00) && (rstat & SER_FRAMING_ERR_MASK)) {
+ /* Most likely a break, but we get
+ * interrupts over and over again.
+ */
+
+ if (info->break_detected_cnt == 0) {
+ DEBUG_LOG(info->line, "#BRK start\n", 0);
+ }
+ if (rstat & SER_RXD_MASK) {
+ /* The RX pin is high now, so the break
+ * must be over, but....
+ * we can't really know if we will get another
+ * last byte ending the break or not.
+ * And we don't know if the byte (if any) will
+ * have an error or look valid.
+ */
+ DEBUG_LOG(info->line, "# BL BRK\n", 0);
+ info->errorcode = ERRCODE_INSERT_BREAK;
+ }
+ info->break_detected_cnt++;
+ } else {
+ /* Error doesn't look like a break,
+ * but could be end of a break
+ */
+ if (info->break_detected_cnt) {
+ DEBUG_LOG(info->line, "EBRK %i\n", info->break_detected_cnt);
+ info->errorcode = ERRCODE_INSERT_BREAK;
+ }
+ info->break_detected_cnt = 0;
+ DEBUG_LOG(info->line, "#iERR s d %04X\n",
+ ((rstat & SER_ERROR_MASK) << 8) | data);
+ }
+ PROCSTAT(ser_stat[info->line].early_errors_cnt++);
+
+#if 0
+ /* Reset DMA before starting */
+ *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
+ while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->icmdadr) ==
+ IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset));
+#endif
+ } else { /* it was a valid byte, now let the dma do the rest */
+ unsigned char data;
+ unsigned long curr_time_u = GET_JIFFIES_USEC();
+ unsigned long curr_time = jiffies;
+
+ if (info->break_detected_cnt) {
+ /* Detect if this character is a new
+ * valid char or the last char in a
+ * break sequence:
+ * If LSBits are 0 and MSBits are high
+ * AND the time is close to the
+ * previous interrupt we should discard
+ * it.
+ */
+ long elapsed_usec =
+ (curr_time - info->last_rx_active) * (1000000/HZ) +
+ curr_time_u - info->last_rx_active_usec;
+ if (elapsed_usec<2*info->char_time_usec) {
+ DEBUG_LOG(info->line, "FBRK %i\n", info->line);
+ /* Report as BREAK (error) and
+ * let receive_chars handle it
+ */
+ info->errorcode = ERRCODE_SET_BREAK;
+ } else {
+ DEBUG_LOG(info->line, "Not end of BRK (V)%i\n", info->line);
+ }
+ DEBUG_LOG(info->line, "num brk %i\n", info->break_detected_cnt);
+ }
+ /* Reset data_avail by
+ * reading the data_in field
+ */
+ data = info->port[REG_DATA];
+ info->break_detected_cnt = 0;
+ info->fifo_magic++; /* Count received chars */
+#ifdef SERIAL_DEBUG_INTR
+ printk("** OK, disabling ser_interupts\n");
+#endif
+ PROCSTAT(ser_stat[info->line].ser_ints_ok_cnt++);
+ DEBUG_LOG(info->line, " ser_int OK %03X\n",
+ (info->line << 8) | data);
+ e100_disable_serial_data_irq(info);
+ }
+
+ /* restart the DMA never hurts */
+ *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, restart);
+ START_FLUSH_FAST_TIMER(info, "ser_int");
+} /* handle_ser_interrupt */
+
static void
ser_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct e100_serial *info;
int i;
- unsigned char rstat;
- for(i = 0; i < NR_PORTS; i++) {
+ for (i = 0; i < NR_PORTS; i++) {
info = rs_table + i;
+
if (!info->uses_dma)
continue;
- rstat = info->port[REG_STATUS];
-
- if(*R_IRQ_MASK1_RD & (1U << (8+2*info->line))) { /* This line caused the irq */
-#ifdef SERIAL_DEBUG_INTR
- printk("Interrupt from serport %d\n", i);
-#endif
- if(rstat & 0x0e) {
- /* FIXME: This is weird, but if this delay is
- * not present then irmaflash does not work...
- */
- udelay(2300);
- /* if we got an error, we must reset it by
- * reading the data_in field
- */
- (void)info->port[REG_DATA];
-
- PROCSTAT(early_errors_cnt[info->line]++);
-
- /* restart the DMA */
- *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, restart);
- }
- else { /* it was a valid byte, now let the dma do the rest */
-#ifdef SERIAL_DEBUG_INTR
- printk("** OK, disabling ser_interrupts\n");
-#endif
- e100_disable_serial_data_irq(info);
- }
+ /* Which line caused the irq? */
+ if (*R_IRQ_MASK1_RD & (1U << (8+2*info->line))) {
+ handle_ser_interrupt(info);
}
}
-}
+} /* ser_interrupt */
#endif
/*
@@ -1573,7 +2010,7 @@
printk("starting up ttyS%d (xmit_buf 0x%x)...\n", info->line, info->xmit.buf);
#endif
- if(info->tty) {
+ if (info->tty) {
/* clear the tty flip flag buffer since we will not
* be using it (we only use the first byte..)
@@ -1612,11 +2049,11 @@
*info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
/* wait until reset cycle is complete */
- while(IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->icmdadr) ==
- IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset));
+ while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->icmdadr) ==
+ IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset));
- while(IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->ocmdadr) ==
- IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset));
+ while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->ocmdadr) ==
+ IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset));
*info->iclrintradr =
IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) |
@@ -1697,6 +2134,7 @@
*info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
*info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
+ info->uses_dma = 0;
#endif /* CONFIG_SVINTO_SIM */
@@ -1740,7 +2178,7 @@
/* first some safety checks */
- if(!info->tty || !info->tty->termios)
+ if (!info->tty || !info->tty->termios)
return;
if (!info->port)
return;
@@ -1807,9 +2245,10 @@
info->port[REG_TR_CTRL] = info->tx_ctrl;
info->port[REG_REC_CTRL] = info->rx_ctrl;
*((unsigned long *)&info->port[REG_XOFF]) = 0;
+#endif /* !CONFIG_SVINTO_SIM */
-#endif /* CONFIG_SVINTO_SIM */
-}
+ update_char_time(info);
+} /* change_speed */
/* start transmitting chars NOW */
@@ -1852,7 +2291,7 @@
return 0;
#ifdef SERIAL_DEBUG_DATA
- if(info->line == SERIAL_DEBUG_LINE)
+ if (info->line == SERIAL_DEBUG_LINE)
printk("rs_write (%d), status %d\n",
count, info->port[REG_STATUS]);
#endif
@@ -1871,7 +2310,7 @@
* atomic operation... this could perhaps be avoided by more clever
* design.
*/
- if(from_user) {
+ if (from_user) {
down(&tmp_buf_sem);
while (1) {
int c1;
@@ -1906,7 +2345,7 @@
up(&tmp_buf_sem);
} else {
cli();
- while(1) {
+ while (1) {
c = CIRC_SPACE_TO_END(info->xmit.head,
info->xmit.tail,
SERIAL_XMIT_SIZE);
@@ -1931,10 +2370,10 @@
* the IRQ's are not running anyway for this port.
*/
- if(info->xmit.head != info->xmit.tail
- && !tty->stopped &&
- !tty->hw_stopped &&
- !info->tr_running) {
+ if (info->xmit.head != info->xmit.tail
+ && !tty->stopped &&
+ !tty->hw_stopped &&
+ !info->tr_running) {
start_transmit(info);
}
@@ -2107,11 +2546,11 @@
old_info = *info;
- if(!capable(CAP_SYS_ADMIN)) {
- if((new_serial.type != info->type) ||
- (new_serial.close_delay != info->close_delay) ||
- ((new_serial.flags & ~ASYNC_USR_MASK) !=
- (info->flags & ~ASYNC_USR_MASK)))
+ if (!capable(CAP_SYS_ADMIN)) {
+ if ((new_serial.type != info->type) ||
+ (new_serial.close_delay != info->close_delay) ||
+ ((new_serial.flags & ~ASYNC_USR_MASK) !=
+ (info->flags & ~ASYNC_USR_MASK)))
return -EPERM;
info->flags = ((info->flags & ~ASYNC_USR_MASK) |
(new_serial.flags & ASYNC_USR_MASK));
@@ -2136,7 +2575,7 @@
#endif
check_and_exit:
- if(info->flags & ASYNC_INITIALIZED) {
+ if (info->flags & ASYNC_INITIALIZED) {
change_speed(info);
} else
retval = startup(info);
@@ -2156,16 +2595,18 @@
static int
get_lsr_info(struct e100_serial * info, unsigned int *value)
{
- unsigned int result;
+ unsigned int result = TIOCSER_TEMT;
+#ifndef CONFIG_SVINTO_SIM
+ unsigned long curr_time = jiffies;
+ unsigned long curr_time_usec = GET_JIFFIES_USEC();
+ unsigned long elapsed_usec =
+ (curr_time - info->last_tx_active) * 1000000/HZ +
+ curr_time_usec - info->last_tx_active_usec;
-#ifdef CONFIG_SVINTO_SIM
- /* Always open. */
- result = TIOCSER_TEMT;
-#else
- if (*info->ostatusadr & 0x007F) /* something in fifo */
+ if (info->xmit.head != info->xmit.tail ||
+ elapsed_usec < 2*info->char_time_usec) {
result = 0;
- else
- result = TIOCSER_TEMT;
+ }
#endif
if (copy_to_user(value, &result, sizeof(int)))
@@ -2178,10 +2619,9 @@
{
int state;
const char *str;
-
};
-const struct state_str control_state_str[]={
+const struct state_str control_state_str[] = {
{TIOCM_DTR, "DTR" },
{TIOCM_RTS, "RTS"},
{TIOCM_ST, "ST?" },
@@ -2612,20 +3052,31 @@
{
unsigned long orig_jiffies;
struct e100_serial *info = (struct e100_serial *)tty->driver_data;
+ unsigned long curr_time = jiffies;
+ unsigned long curr_time_usec = GET_JIFFIES_USEC();
+ long elapsed_usec =
+ (curr_time - info->last_tx_active) * (1000000/HZ) +
+ curr_time_usec - info->last_tx_active_usec;
/*
* Check R_DMA_CHx_STATUS bit 0-6=number of available bytes in FIFO
* R_DMA_CHx_HWSW bit 31-16=nbr of bytes left in DMA buffer (0=64k)
*/
orig_jiffies = jiffies;
- while(info->xmit.head != info->xmit.tail || /* More in send queue */
- (*info->ostatusadr & 0x007f)) { /* more in FIFO */
+ while (info->xmit.head != info->xmit.tail || /* More in send queue */
+ (*info->ostatusadr & 0x007f) || /* more in FIFO */
+ (elapsed_usec < 2*info->char_time_usec)) {
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(1);
if (signal_pending(current))
break;
if (timeout && time_after(jiffies, orig_jiffies + timeout))
break;
+ curr_time = jiffies;
+ curr_time_usec = GET_JIFFIES_USEC();
+ elapsed_usec =
+ (curr_time - info->last_tx_active) * (1000000/HZ) +
+ curr_time_usec - info->last_tx_active_usec;
}
set_current_state(TASK_RUNNING);
}
@@ -2809,10 +3260,11 @@
return -ENODEV;
/* find the corresponding e100_serial struct in the table */
-
info = rs_table + line;
- /* dont allow the opening of ports that are not enabled in the HW config */
- if (!info->enabled) return -ENODEV;
+
+ /* don't allow the opening of ports that are not enabled in the HW config */
+ if (!info->enabled)
+ return -ENODEV;
#ifdef SERIAL_DEBUG_OPEN
printk("[%d] rs_open %s%d, count = %d\n", current->pid,
@@ -2923,20 +3375,20 @@
ret += sprintf(buf+ret, " baud:%d", info->baud);
- ret += sprintf(buf+ret, " tx:%d rx:%d",
- info->icount.tx, info->icount.rx);
+ ret += sprintf(buf+ret, " tx:%lu rx:%lu",
+ info->icount.tx, info->icount.rx);
if (info->icount.frame)
- ret += sprintf(buf+ret, " fe:%d", info->icount.frame);
+ ret += sprintf(buf+ret, " fe:%lu", info->icount.frame);
if (info->icount.parity)
- ret += sprintf(buf+ret, " pe:%d", info->icount.parity);
+ ret += sprintf(buf+ret, " pe:%lu", info->icount.parity);
if (info->icount.brk)
- ret += sprintf(buf+ret, " brk:%d", info->icount.brk);
+ ret += sprintf(buf+ret, " brk:%lu", info->icount.brk);
if (info->icount.overrun)
- ret += sprintf(buf+ret, " oe:%d", info->icount.overrun);
+ ret += sprintf(buf+ret, " oe:%lu", info->icount.overrun);
/*
* Last thing is the RS-232 status lines
@@ -2996,9 +3448,11 @@
/* Setup the timed flush handler system */
+#if !defined(CONFIG_ETRAX_SERIAL_FAST_TIMER) && !defined(CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST)
init_timer(&flush_timer);
flush_timer.function = timed_flush_handler;
- mod_timer(&flush_timer, jiffies + MAX_FLUSH_TIME);
+ mod_timer(&flush_timer, jiffies + CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS);
+#endif
/* Initialize the tty_driver structure */
@@ -3089,6 +3543,7 @@
init_waitqueue_head(&info->close_wait);
info->xmit.buf = 0;
info->xmit.tail = info->xmit.head = 0;
+
if (info->enabled) {
printk(KERN_INFO "%s%d at 0x%x is a builtin UART with DMA\n",
serial_driver.name, info->line, (unsigned int)info->port);
@@ -3099,38 +3554,38 @@
/* Not needed in simulator. May only complicate stuff. */
/* hook the irq's for DMA channel 6 and 7, serial output and input, and some more... */
#ifdef CONFIG_ETRAX_SERIAL_PORT0
- if(request_irq(SER0_DMA_TX_IRQ_NBR, tr_interrupt, SA_INTERRUPT, "serial 0 dma tr", NULL))
+ if (request_irq(SER0_DMA_TX_IRQ_NBR, tr_interrupt, SA_INTERRUPT, "serial 0 dma tr", NULL))
panic("irq22");
- if(request_irq(SER0_DMA_RX_IRQ_NBR, rec_interrupt, SA_INTERRUPT, "serial 0 dma rec", NULL))
+ if (request_irq(SER0_DMA_RX_IRQ_NBR, rec_interrupt, SA_INTERRUPT, "serial 0 dma rec", NULL))
panic("irq23");
#endif
#ifdef SERIAL_HANDLE_EARLY_ERRORS
- if(request_irq(SERIAL_IRQ_NBR, ser_interrupt, SA_INTERRUPT, "serial ", NULL))
+ if (request_irq(SERIAL_IRQ_NBR, ser_interrupt, SA_INTERRUPT, "serial ", NULL))
panic("irq8");
#endif
#ifdef CONFIG_ETRAX_SERIAL_PORT1
- if(request_irq(SER1_DMA_TX_IRQ_NBR, tr_interrupt, SA_INTERRUPT, "serial 1 dma tr", NULL))
+ if (request_irq(SER1_DMA_TX_IRQ_NBR, tr_interrupt, SA_INTERRUPT, "serial 1 dma tr", NULL))
panic("irq24");
- if(request_irq(SER1_DMA_RX_IRQ_NBR, rec_interrupt, SA_INTERRUPT, "serial 1 dma rec", NULL))
+ if (request_irq(SER1_DMA_RX_IRQ_NBR, rec_interrupt, SA_INTERRUPT, "serial 1 dma rec", NULL))
panic("irq25");
#endif
#ifdef CONFIG_ETRAX_SERIAL_PORT2
/* DMA Shared with par0 (and SCSI0 and ATA) */
- if(request_irq(SER2_DMA_TX_IRQ_NBR, tr_interrupt, SA_SHIRQ, "serial 2 dma tr", NULL))
+ if (request_irq(SER2_DMA_TX_IRQ_NBR, tr_interrupt, SA_SHIRQ, "serial 2 dma tr", NULL))
panic("irq18");
- if(request_irq(SER2_DMA_RX_IRQ_NBR, rec_interrupt, SA_SHIRQ, "serial 2 dma rec", NULL))
+ if (request_irq(SER2_DMA_RX_IRQ_NBR, rec_interrupt, SA_SHIRQ, "serial 2 dma rec", NULL))
panic("irq19");
#endif
#ifdef CONFIG_ETRAX_SERIAL_PORT3
/* DMA Shared with par1 (and SCSI1 and Extern DMA 0) */
- if(request_irq(SER3_DMA_TX_IRQ_NBR, tr_interrupt, SA_SHIRQ, "serial 3 dma tr", NULL))
+ if (request_irq(SER3_DMA_TX_IRQ_NBR, tr_interrupt, SA_SHIRQ, "serial 3 dma tr", NULL))
panic("irq20");
- if(request_irq(SER3_DMA_RX_IRQ_NBR, rec_interrupt, SA_SHIRQ, "serial 3 dma rec", NULL))
+ if (request_irq(SER3_DMA_RX_IRQ_NBR, rec_interrupt, SA_SHIRQ, "serial 3 dma rec", NULL))
panic("irq21");
#endif
+
#ifdef CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST
- /* TODO: a timeout_interrupt needs to be written that calls timeout_handler */
- if(request_irq(TIMER1_IRQ_NBR, timeout_interrupt, SA_SHIRQ,
+ if (request_irq(TIMER1_IRQ_NBR, timeout_interrupt, SA_SHIRQ | SA_INTERRUPT,
"fast serial dma timeout", NULL)) {
printk("err: timer1 irq\n");
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)