summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-09-21 22:29:00 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-09-21 22:29:00 +0000
commitf7a41bfc36a271d396debf6db6b3a3a0551514e0 (patch)
treef1db8af14cab879ff9818aa38d2ce8c9316834d5
parentbb722553b5f6467eb4acbc3afa2bf4cc7bd60474 (diff)
Same sgiserial.c fix for mainline.
-rw-r--r--drivers/sgi/char/sgiserial.c75
1 files changed, 68 insertions, 7 deletions
diff --git a/drivers/sgi/char/sgiserial.c b/drivers/sgi/char/sgiserial.c
index f779253b0..72f33ee5e 100644
--- a/drivers/sgi/char/sgiserial.c
+++ b/drivers/sgi/char/sgiserial.c
@@ -4,6 +4,18 @@
*
*/
+/*
+ * Note: This driver seems to have been derived from some
+ * version of the sbus/char/zs.c driver. A lot of clean-up
+ * and bug fixes seem to have happened to the Sun driver in
+ * the intervening time. As of 21.09.1999, I have merged in
+ * ONLY the changes necessary to fix observed functional
+ * problems on the Indy. Someone really ought to do a
+ * thorough pass to merge in the rest of the updates.
+ * Better still, someone really ought to make it a common
+ * code module for both platforms. kevink@mips.com
+ */
+
#include <linux/config.h> /* for CONFIG_REMOTE_DEBUG */
#include <linux/errno.h>
#include <linux/signal.h>
@@ -451,7 +463,7 @@ static _INLINE_ void transmit_chars(struct sgi_serial *info)
volatile unsigned char junk;
/* P3: In theory we have to test readiness here because a
- * serial console can clog the chip through rs_put_char().
+ * serial console can clog the chip through zs_cons_put_char().
* David did not do this. I think he relies on 3-chars FIFO in 8530.
* Let's watch for lost _output_ characters. XXX
*/
@@ -890,7 +902,7 @@ static void change_speed(struct sgi_serial *info)
}
/* This is for console output over ttya/ttyb */
-static void rs_put_char(char ch)
+static void zs_cons_put_char(char ch)
{
struct sgi_zschannel *chan = zs_conschan;
volatile unsigned char junk;
@@ -908,6 +920,31 @@ static void rs_put_char(char ch)
restore_flags(flags);
}
+/*
+ * This is the more generic put_char function for the driver.
+ * In earlier versions of this driver, "rs_put_char" was the
+ * name of the console-specific fucntion, now called zs_cons_put_char
+ */
+
+static void rs_put_char(struct tty_struct *tty, char ch)
+{
+ struct sgi_zschannel *chan =
+ ((struct sgi_serial *)tty->driver_data)->zs_channel;
+ volatile unsigned char junk;
+ int flags, loops = 0;
+
+ save_flags(flags); cli();
+ while(((junk = chan->control) & Tx_BUF_EMP)==0 && loops < 10000) {
+ loops++;
+ udelay(2);
+ }
+
+ udelay(2);
+ chan->data = ch;
+ junk = ioc_icontrol->istat0;
+ restore_flags(flags);
+}
+
/* These are for receiving and sending characters under the kgdb
* source level kernel debugger.
*/
@@ -965,7 +1002,7 @@ static void rs_fair_output(void)
info->xmit_cnt--;
restore_flags(flags);
- rs_put_char(c);
+ zs_cons_put_char(c);
save_flags(flags); cli();
left = MIN(info->xmit_cnt, left-1);
@@ -1018,8 +1055,18 @@ static int rs_write(struct tty_struct * tty, int from_user,
count -= c;
total += c;
}
- if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
- !(info->curregs[5] & TxENAB)) {
+
+ if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {
+ /*
+ * The above test used to include the condition
+ * "&& !(info->curregs[5] & TxENAB)", but there
+ * is reason to suspect that it is never statisfied
+ * when the port is running. The problem may in fact
+ * have been masked by the fact that, if O_POST is set,
+ * there is always a rs_flush_xx operation following the
+ * rs_write, and the flush ignores that condition when
+ * it kicks off the transmit.
+ */
/* Enable transmitter */
info->curregs[1] |= TxINT_ENAB|EXT_INT_ENAB;
info->pendregs[1] |= TxINT_ENAB|EXT_INT_ENAB;
@@ -1027,7 +1074,21 @@ static int rs_write(struct tty_struct * tty, int from_user,
info->curregs[5] |= TxENAB;
info->pendregs[5] |= TxENAB;
write_zsreg(info->zs_channel, 5, info->curregs[5]);
+
+ /*
+ * The following code is imported from the 2.3.6 Sun sbus zs.c
+ * driver, of which an earlier version served as the basis
+ * for sgiserial.c. Perhaps due to changes over time in
+ * the line discipline code, ns_write()s with from_user
+ * set would not otherwise actually kick-off output in
+ * Linux 2.2.x or later. Maybe it never really worked.
+ */
+
+ rs_put_char(tty, info->xmit_buf[info->xmit_tail++]);
+ info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
+ info->xmit_cnt--;
}
+
restore_flags(flags);
return total;
}
@@ -2025,8 +2086,8 @@ static void zs_console_write(struct console *co, const char *str, unsigned int c
while(count--) {
if(*str == '\n')
- rs_put_char('\r');
- rs_put_char(*str++);
+ zs_cons_put_char('\r');
+ zs_cons_put_char(*str++);
}
/* Comment this if you want to have a strict interrupt-driven output */