patch-2.4.0-test8 linux/drivers/sbus/char/sab82532.c

Next file: linux/drivers/sbus/char/su.c
Previous file: linux/drivers/sbus/char/rtc.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test7/linux/drivers/sbus/char/sab82532.c linux/drivers/sbus/char/sab82532.c
@@ -1,4 +1,4 @@
-/* $Id: sab82532.c,v 1.47 2000/08/16 21:12:14 ecd Exp $
+/* $Id: sab82532.c,v 1.51 2000/09/04 19:41:26 ecd Exp $
  * sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -55,9 +55,11 @@
 /* Set of debugging defines */
 #undef SERIAL_DEBUG_OPEN
 #undef SERIAL_DEBUG_FLOW
+#undef SERIAL_DEBUG_MODEM
 #undef SERIAL_DEBUG_WAIT_UNTIL_SENT
 #undef SERIAL_DEBUG_SEND_BREAK
 #undef SERIAL_DEBUG_INTR
+#define SERIAL_DEBUG_OVERFLOW 1
 
 /* Trace things on serial device, useful for console debugging: */
 #undef SERIAL_LOG_DEVICE
@@ -79,10 +81,15 @@
 static struct termios *sab82532_termios[NR_PORTS];
 static struct termios *sab82532_termios_locked[NR_PORTS];
 
+#ifdef MODULE
+#undef CONFIG_SERIAL_CONSOLE
+#endif
+
 #ifdef CONFIG_SERIAL_CONSOLE
 extern int serial_console;
 static struct console sab82532_console;
 static int sab82532_console_init(void);
+static void batten_down_hatches(struct sab82532 *info);
 #endif
 
 #ifndef MIN
@@ -208,7 +215,10 @@
 	if (!(readb(&info->regs->r.star) & SAB82532_STAR_XFW))
 		goto out;
 
+	info->interrupt_mask1 &= ~(SAB82532_IMR1_ALLS);
+	writeb(info->interrupt_mask1, &info->regs->w.imr1);
 	info->all_sent = 0;
+
 	for (i = 0; i < info->xmit_fifo_size; i++) {
 		u8 val = info->xmit_buf[info->xmit_tail++];
 		writeb(val, &info->regs->w.xfifo[i]);
@@ -264,47 +274,6 @@
 	restore_flags(flags);
 }
 
-static void batten_down_hatches(struct sab82532 *info)
-{
-	unsigned char saved_rfc, tmp;
-
-	if (!stop_a_enabled)
-		return;
-
-	/* If we are doing kadb, we call the debugger
-	 * else we just drop into the boot monitor.
-	 * Note that we must flush the user windows
-	 * first before giving up control.
-	 */
-	printk("\n");
-	flush_user_windows();
-
-	/*
-	 * Set FIFO to single character mode.
-	 */
-	saved_rfc = readb(&info->regs->r.rfc);
-	tmp = readb(&info->regs->rw.rfc);
-	tmp &= ~(SAB82532_RFC_RFDF);
-	writeb(tmp, &info->regs->rw.rfc);
-	sab82532_cec_wait(info);
-	writeb(SAB82532_CMDR_RRES, &info->regs->w.cmdr);
-
-#ifndef __sparc_v9__
-	if ((((unsigned long)linux_dbvec) >= DEBUG_FIRSTVADDR) &&
-	    (((unsigned long)linux_dbvec) <= DEBUG_LASTVADDR))
-		sp_enter_debugger();
-	else
-#endif
-		prom_cmdline();
-
-	/*
-	 * Reset FIFO to character + status mode.
-	 */
-	writeb(saved_rfc, &info->regs->w.rfc);
-	sab82532_cec_wait(info);
-	writeb(SAB82532_CMDR_RRES, &info->regs->w.cmdr);
-}
-
 /*
  * ----------------------------------------------------------------------
  *
@@ -361,12 +330,11 @@
 	if (stat->sreg.isr0 & SAB82532_ISR0_TIME) {
 		sab82532_cec_wait(info);
 		writeb(SAB82532_CMDR_RFRD, &info->regs->w.cmdr);
-		/* Wait for command execution, to catch the TCD below. */
-		sab82532_cec_wait(info);
+		return;
 	}
 
 	if (stat->sreg.isr0 & SAB82532_ISR0_RFO) {
-#if 1
+#ifdef SERIAL_DEBUG_OVERFLOW
 		printk("sab82532: receive_chars: RFO");
 #endif
 		free_fifo++;
@@ -382,14 +350,16 @@
 		writeb(SAB82532_CMDR_RMC, &info->regs->w.cmdr);
 	}
 
+#ifdef CONFIG_SERIAL_CONSOLE
 	if (info->is_console)
 		wake_up(&keypress_wait);
+#endif
 	if (!tty)
 		return;
 
 	for (i = 0; i < count; ) {
 		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-#if 1
+#ifdef SERIAL_DEBUG_OVERFLOW
 			printk("sab82532: receive_chars: tty overrun\n");
 #endif
 			info->icount.buf_overrun++;
@@ -424,9 +394,13 @@
 {
 	int i;
 
-	if (stat->sreg.isr1 & SAB82532_ISR1_ALLS)
+	if (stat->sreg.isr1 & SAB82532_ISR1_ALLS) {
+		info->interrupt_mask1 |= SAB82532_IMR1_ALLS;
+		writeb(info->interrupt_mask1, &info->regs->w.imr1);
 		info->all_sent = 1;
-	if (!(readb(&info->regs->r.star) & SAB82532_STAR_XFW))
+	}
+
+	if (!(stat->sreg.isr1 & SAB82532_ISR1_XPR))
 		return;
 
 	if (!info->tty) {
@@ -442,8 +416,11 @@
 		return;
 	}
 
-	/* Stuff 32 bytes into Transmit FIFO. */
+	info->interrupt_mask1 &= ~(SAB82532_IMR1_ALLS);
+	writeb(info->interrupt_mask1, &info->regs->w.imr1);
 	info->all_sent = 0;
+
+	/* Stuff 32 bytes into Transmit FIFO. */
 	for (i = 0; i < info->xmit_fifo_size; i++) {
 		u8 val = info->xmit_buf[info->xmit_tail++];
 		writeb(val, &info->regs->w.xfifo[i]);
@@ -476,10 +453,12 @@
 	int modem_change = 0;
 
 	if (stat->sreg.isr1 & SAB82532_ISR1_BRK) {
+#ifdef CONFIG_SERIAL_CONSOLE
 		if (info->is_console) {
 			batten_down_hatches(info);
 			return;
 		}
+#endif
 		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
 			info->icount.buf_overrun++;
 			goto check_modem;
@@ -509,7 +488,7 @@
 		info->dcd = (readb(&info->regs->r.vstr) & SAB82532_VSTR_CD) ? 0 : 1;
 		info->icount.dcd++;
 		modem_change++;
-#if 0
+#ifdef SERIAL_DEBUG_MODEM
 		printk("DCD change: %d\n", info->icount.dcd);
 #endif
 	}
@@ -517,7 +496,7 @@
 		info->cts = readb(&info->regs->r.star) & SAB82532_STAR_CTS;
 		info->icount.cts++;
 		modem_change++;
-#if 0
+#ifdef SERIAL_DEBUG_MODEM
 		printk("CTS change: %d, CTS %s\n", info->icount.cts, info->cts ? "on" : "off");
 #endif
 	}
@@ -525,7 +504,7 @@
 		info->dsr = (readb(&info->regs->r.pvr) & info->pvr_dsr_bit) ? 0 : 1;
 		info->icount.dsr++;
 		modem_change++;
-#if 0
+#ifdef SERIAL_DEBUG_MODEM
 		printk("DSR change: %d\n", info->icount.dsr);
 #endif
 	}
@@ -828,10 +807,12 @@
 	info->interrupt_mask0 = SAB82532_IMR0_PERR | SAB82532_IMR0_FERR |
 				SAB82532_IMR0_PLLA;
 	writeb(info->interrupt_mask0, &info->regs->w.imr0);
-	info->interrupt_mask1 = SAB82532_IMR1_BRKT | SAB82532_IMR1_XOFF |
-				SAB82532_IMR1_TIN | SAB82532_IMR1_CSC |
-				SAB82532_IMR1_XON | SAB82532_IMR1_XPR;
+	info->interrupt_mask1 = SAB82532_IMR1_BRKT | SAB82532_IMR1_ALLS |
+				SAB82532_IMR1_XOFF | SAB82532_IMR1_TIN |
+				SAB82532_IMR1_CSC | SAB82532_IMR1_XON |
+				SAB82532_IMR1_XPR;
 	writeb(info->interrupt_mask1, &info->regs->w.imr1);
+	info->all_sent = 1;
 
 	if (info->tty)
 		clear_bit(TTY_IO_ERROR, &info->tty->flags);
@@ -880,6 +861,7 @@
 		info->xmit_buf = 0;
 	}
 
+#ifdef CONFIG_SERIAL_CONSOLE
 	if (info->is_console) {
 		info->interrupt_mask0 = SAB82532_IMR0_PERR | SAB82532_IMR0_FERR |
 					SAB82532_IMR0_PLLA | SAB82532_IMR0_CDSC;
@@ -895,6 +877,7 @@
 		restore_flags(flags);
 		return;
 	}
+#endif
 
 	/* Disable Interrupts */
 	info->interrupt_mask0 = 0xff;
@@ -1238,10 +1221,6 @@
 	
 	if (I_IXOFF(tty))
 		sab82532_send_xchar(tty, STOP_CHAR(tty));
-#if 0
-	if (tty->termios->c_cflag & CRTSCTS)
-		writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode);
-#endif
 }
 
 static void sab82532_unthrottle(struct tty_struct * tty)
@@ -1263,11 +1242,6 @@
 		else
 			sab82532_send_xchar(tty, START_CHAR(tty));
 	}
-
-#if 0
-	if (tty->termios->c_cflag & CRTSCTS)
-		writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_RTS), &info->regs->rw.mode);
-#endif
 }
 
 /*
@@ -1562,18 +1536,6 @@
 		tty->hw_stopped = 0;
 		sab82532_start(tty);
 	}
-
-#if 0
-	/*
-	 * No need to wake up processes in open wait, since they
-	 * sample the CLOCAL flag once, and don't recheck it.
-	 * XXX  It's not clear whether the current behavior is correct
-	 * or not.  Hence, this may change.....
-	 */
-	if (!(old_termios->c_cflag & CLOCAL) &&
-	    (tty->termios->c_cflag & CLOCAL))
-		wake_up_interruptible(&info->open_wait);
-#endif
 }
 
 /*
@@ -1651,9 +1613,6 @@
 	 */
 	info->interrupt_mask0 |= SAB82532_IMR0_TCD;
 	writeb(info->interrupt_mask0, &info->regs->w.imr0);
-#if 0
-	writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_RAC), &info->regs->rw.mode);
-#endif
 	if (info->flags & ASYNC_INITIALIZED) {
 		/*
 		 * Before we drop DTR, make sure the UART transmitter
@@ -1722,7 +1681,6 @@
 		if (timeout && time_after(jiffies, orig_jiffies + timeout))
 			break;
 	}
-	current->state = TASK_RUNNING;
 #ifdef SERIAL_DEBUG_WAIT_UNTIL_SENT
 	printk("xmit_cnt = %d, alls = %d (jiff=%lu)...done\n", info->xmit_cnt, info->all_sent, jiffies);
 #endif
@@ -1738,8 +1696,10 @@
 	if (serial_paranoia_check(info, tty->device, "sab82532_hangup"))
 		return;
 
+#ifdef CONFIG_SERIAL_CONSOLE
 	if (info->is_console)
 		return;
+#endif
 
 	sab82532_flush_buffer(tty);
 	shutdown(info);
@@ -1873,7 +1833,6 @@
 #endif
 		schedule();
 	}
-	current->state = TASK_RUNNING;
 	remove_wait_queue(&info->open_wait, &wait);
 	if (!tty_hung_up_p(filp))
 		info->count++;
@@ -2010,7 +1969,7 @@
 	char stat_buf[30];
 	int ret;
 
-	ret = sprintf(buf, "%d: uart:SAB82532 ", info->line);
+	ret = sprintf(buf, "%u: uart:SAB82532 ", info->line);
 	switch (info->type) {
 		case 0:
 			ret += sprintf(buf+ret, "V1.0 ");
@@ -2056,19 +2015,22 @@
 	restore_flags(flags);
 
 	if (info->baud)
-		ret += sprintf(buf+ret, " baud:%d", info->baud);
+		ret += sprintf(buf+ret, " baud:%u", info->baud);
+
+	ret += sprintf(buf+ret, " tx:%u rx:%u",
+		       info->icount.tx, info->icount.rx);
 
 	if (info->icount.frame)
-		ret += sprintf(buf+ret, " fe:%d", info->icount.frame);
+		ret += sprintf(buf+ret, " fe:%u", info->icount.frame);
 
 	if (info->icount.parity)
-		ret += sprintf(buf+ret, " pe:%d", info->icount.parity);
+		ret += sprintf(buf+ret, " pe:%u", info->icount.parity);
 
 	if (info->icount.brk)
-		ret += sprintf(buf+ret, " brk:%d", info->icount.brk);
+		ret += sprintf(buf+ret, " brk:%u", info->icount.brk);
 
 	if (info->icount.overrun)
-		ret += sprintf(buf+ret, " oe:%d", info->icount.overrun);
+		ret += sprintf(buf+ret, " oe:%u", info->icount.overrun);
 
 	/*
 	 * Last thing is the RS-232 status lines.
@@ -2161,15 +2123,17 @@
 	return 0;
 }
 
+#ifndef MODULE
 static void __init sab82532_kgdb_hook(int line)
 {
 	prom_printf("sab82532: kgdb support is not implemented, yet\n");
 	prom_halt();
 }
+#endif
 
 static inline void __init show_serial_version(void)
 {
-	char *revision = "$Revision: 1.47 $";
+	char *revision = "$Revision: 1.51 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
@@ -2246,7 +2210,11 @@
 	 * major number and the subtype code.
 	 */
 	callout_driver = serial_driver;
+#ifdef CONFIG_DEVFS_FS
 	callout_driver.name = "cua/%d";
+#else
+	callout_driver.name = "cua";
+#endif
 	callout_driver.major = TTYAUX_MAJOR;
 	callout_driver.subtype = SERIAL_TYPE_CALLOUT;
 	callout_driver.read_proc = 0;
@@ -2364,8 +2332,10 @@
 #ifdef CONFIG_SERIAL_CONSOLE
 	sunserial_setinitfunc(sab82532_console_init);
 #endif
+#ifndef MODULE
 	sunserial_setinitfunc(sab82532_init);
 	rs_ops.rs_kgdb_hook = sab82532_kgdb_hook;
+#endif
 	return 0;
 }
 
@@ -2400,12 +2370,56 @@
 		free_page((unsigned long) tmp_buf);
 		tmp_buf = NULL;
 	}
-	for (sab = sab82532_chain; sab; sab = sab->next)
+	for (sab = sab82532_chain; sab; sab = sab->next) {
+		if (!(sab->line & 0x01))
+			free_irq(sab->irq, sab);
 		iounmap(sab->regs);
+	}
 }
 #endif /* MODULE */
 
 #ifdef CONFIG_SERIAL_CONSOLE
+static void
+batten_down_hatches(struct sab82532 *info)
+{
+	unsigned char saved_rfc, tmp;
+
+	if (!stop_a_enabled)
+		return;
+
+	/* If we are doing kadb, we call the debugger
+	 * else we just drop into the boot monitor.
+	 * Note that we must flush the user windows
+	 * first before giving up control.
+	 */
+	printk("\n");
+	flush_user_windows();
+
+	/*
+	 * Set FIFO to single character mode.
+	 */
+	saved_rfc = readb(&info->regs->r.rfc);
+	tmp = readb(&info->regs->rw.rfc);
+	tmp &= ~(SAB82532_RFC_RFDF);
+	writeb(tmp, &info->regs->rw.rfc);
+	sab82532_cec_wait(info);
+	writeb(SAB82532_CMDR_RRES, &info->regs->w.cmdr);
+
+#ifndef __sparc_v9__
+	if ((((unsigned long)linux_dbvec) >= DEBUG_FIRSTVADDR) &&
+	    (((unsigned long)linux_dbvec) <= DEBUG_LASTVADDR))
+		sp_enter_debugger();
+	else
+#endif
+		prom_cmdline();
+
+	/*
+	 * Reset FIFO to character + status mode.
+	 */
+	writeb(saved_rfc, &info->regs->w.rfc);
+	sab82532_cec_wait(info);
+	writeb(SAB82532_CMDR_RRES, &info->regs->w.cmdr);
+}
 
 static __inline__ void
 sab82532_console_putchar(struct sab82532 *info, char c)
@@ -2645,4 +2659,3 @@
 }
 #endif /* SERIAL_LOG_DEVICE */
 #endif /* CONFIG_SERIAL_CONSOLE */
-

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)