From: Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
Date: Fri, 7 Mar 97 10:40:09 +0100
To: linux-m68k@phil.uni-sb.de
Subject: L68K: Updates for 2.1.28
X-Yow: ..  hubub, hubub, HUBUB, hubub, hubub, hubub, HUBUB, hubub, hubub, hubub.
Sender: owner-linux-m68k@phil.uni-sb.de
Reply-To: linux-m68k@phil.uni-sb.de

Hi!

Here are some patches that are needed if you want to upgrade to 2.1.28:

- arch/m68k/kernel/entry.S: do_bottom_half now requires intr_count == 0.

- drivers/char/m68kserial.c, include/asm-m68k/serial.h: use new procfs
interface, collect more statistics.


--- arch/m68k/kernel/entry.S.~1~	Mon Feb 17 19:01:33 1997
+++ arch/m68k/kernel/entry.S	Sat Mar  1 17:56:46 1997
@@ -272,8 +272,7 @@
 SYMBOL_NAME_LABEL(ret_from_interrupt)
 	/* check if we need to do software interrupts */
 1:
-	movel	SYMBOL_NAME(intr_count),%d1
-	subql	#1,%d1
+	subql	#1,SYMBOL_NAME(intr_count)
 	jne	4f
 	bfextu  %sp@(LSR){#5,#3},%d0    | Check for nested interrupt.
 #if MAX_NOINT_IPL > 0
@@ -283,15 +282,11 @@
 2:
 	movel	SYMBOL_NAME(bh_active),%d0
 	andl	SYMBOL_NAME(bh_mask),%d0
-	jne	3f
-
-	clrl	SYMBOL_NAME(intr_count)	| deliver signals, reschedule etc..
-	jra	SYMBOL_NAME(ret_from_exception)
+	jeq	SYMBOL_NAME(ret_from_exception)
 3:	
 	jbsr	SYMBOL_NAME(do_bottom_half)
 	jbra	2b
 4:
-	movel	%d1,SYMBOL_NAME(intr_count)
 	RESTORE_ALL
 
 
--- drivers/char/m68kserial.c.~1~	Wed Jan 15 21:18:27 1997
+++ drivers/char/m68kserial.c	Thu Mar  6 16:37:23 1997
@@ -23,7 +23,6 @@
  * This module exports the following rs232 io functions:
  *
  *	long rs_init(long);
- * 	int  rs_open(struct tty_struct * tty, struct file * filp)
  */
 
 /*
@@ -71,7 +70,9 @@
 #include <linux/fcntl.h>
 #include <linux/ptrace.h>
 #include <linux/mm.h>
+#ifdef CONFIG_PROC_FS
 #include <linux/proc_fs.h>
+#endif
 
 #include <asm/setup.h>
 #include <asm/system.h>
@@ -148,39 +149,54 @@
 #define M68K_PORT_MAX (sizeof(serialtypes68k)/sizeof(*serialtypes68k))
 #endif
 
-#ifndef MODULE
 #ifdef CONFIG_PROC_FS
-static int proc_serial_read (char *buffer, char **start, off_t offset,
-			     int size, int unused)
+static int rs_read_proc (char *buffer, char **start, off_t offset, int size,
+			 void *data)
 {
     int len, i;
+    off_t begin = 0;
     char *name;
 
     len = sprintf (buffer, "Serial ports:\n");
     for (i = 0; i < NR_PORTS; ++i) {
-	if (!rs_table[i].port) continue;
-	if (rs_table[i].type >= 0 && rs_table[i].type < PORT_MAX)
-	    name = serialtypes[rs_table[i].type];
+	struct async_struct *info = &rs_table[i];
+
+	if (!info->port) continue;
+	if (info->type >= 0 && info->type < PORT_MAX)
+	    name = serialtypes[info->type];
 #ifdef __mc68000__
-	else if (rs_table[i].type >= 100 &&
-		 rs_table[i].type < 100 + M68K_PORT_MAX)
-	    name = serialtypes68k[rs_table[i].type - 100];
+	else if (info->type >= 100 && info->type < 100 + M68K_PORT_MAX)
+	    name = serialtypes68k[info->type - 100];
 #endif
 	else
 	    name = "unknown";
-	len += sprintf (buffer + len, "\tttyS%d: %s at 0x%08x.\n", i, name,
-			rs_table[i].port);
-    }
+	len += sprintf (buffer + len, "%d: name:%s port:0x%08x tx:%d rx:%d",
+			i, name, info->port, info->icount.tx, info->icount.rx);
 
-    if (len > 14)
-	return len;
+	if (info->icount.frame)
+		len += sprintf(buffer + len, " fe:%d", info->icount.frame);
+	if (info->icount.parity)
+		len += sprintf(buffer + len, " pe:%d", info->icount.parity);
+	if (info->icount.brk)
+		len += sprintf(buffer + len, " brk:%d", info->icount.brk);
+	if (info->icount.overrun)
+		len += sprintf(buffer + len, " oe:%d", info->icount.overrun);
+	len += sprintf(buffer + len, "\n");
+
+	if (len + begin > offset + size)
+	    break;
+	if (len + begin < offset) {
+	    begin += len;
+	    len = 0;
+	}
+    }
 
-    /* No serial ports detected */
-    buffer[0] = 0;
-    return 0;
+    if (offset >= len + begin)
+	return 0;
+    *start = buffer + (begin - offset);
+    return (size < begin + len - offset ? size : begin + len - offset);
 }
 #endif
-#endif
 
 /*
  * tmp_buf is used as a temporary buffer by serial_write.  We need to
@@ -1031,7 +1047,7 @@
 /*
  * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
  */
-void rs_hangup(struct tty_struct *tty)
+static void rs_hangup(struct tty_struct *tty)
 {
 	struct async_struct * info = (struct async_struct *)tty->driver_data;
 
@@ -1190,7 +1206,7 @@
  * the IRQ chain.   It also performs the serial-specific
  * initialization for the tty structure.
  */
-int rs_open(struct tty_struct *tty, struct file * filp)
+static int rs_open(struct tty_struct *tty, struct file * filp)
 {
 	struct async_struct	*info;
 	int 			retval, line;
@@ -1339,7 +1355,6 @@
 EXPORT_SYMBOL(unregister_serial);
 EXPORT_SYMBOL(rs_start);
 EXPORT_SYMBOL(rs_stop);
-EXPORT_SYMBOL(rs_init);
 
 /*
  * The serial driver boot-time initialization code!
@@ -1359,6 +1374,7 @@
 
 	memset(&serial_driver, 0, sizeof(struct tty_driver));
 	serial_driver.magic = TTY_DRIVER_MAGIC;
+	serial_driver.driver_name = "serial";
 	serial_driver.name = "ttyS";
 	serial_driver.major = TTY_MAJOR;
 	serial_driver.minor_start = 64;
@@ -1389,6 +1405,10 @@
 	serial_driver.stop = rs_stop;
 	serial_driver.start = rs_start;
 	serial_driver.hangup = rs_hangup;
+ 	/* TODO: serial_driver.wait_until_sent = rs_wait_until_sent; */
+#ifdef CONFIG_PROC_FS
+	serial_driver.read_proc = rs_read_proc;
+#endif
 
 	/*
 	 * The callout device is just like normal device except for
@@ -1398,6 +1418,7 @@
 	callout_driver.name = "cua";
 	callout_driver.major = TTYAUX_MAJOR;
 	callout_driver.subtype = SERIAL_TYPE_CALLOUT;
+	callout_driver.read_proc = 0;
 
 	if (tty_register_driver(&serial_driver)) {
 		printk("Couldn't register serial driver\n");
@@ -1433,19 +1454,14 @@
 		info->delta_msr_wait = 0;
 		info->icount.cts = info->icount.dsr = 0;
 		info->icount.rng = info->icount.dcd = 0;
+		info->icount.rx = info->icount.tx = 0;
+		info->icount.frame = info->icount.parity = 0;
+		info->icount.overrun = info->icount.brk = 0;
 		info->next_port = 0;
 		info->prev_port = 0;
 	}
 
 #ifndef MODULE
-#ifdef CONFIG_PROC_FS
-	proc_register_dynamic(&proc_root, &(struct proc_dir_entry) {
-		0, 6, "serial",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, NULL /* ops -- default to array */,
-		&proc_serial_read /* get_info */,
-	});
-#endif /* PROC_FS */
 	switch (m68k_machtype) {
 	    case MACH_ATARI:
 #ifdef CONFIG_ATARI_SCC
--- include/asm-m68k/serial.h.~1~	Mon Nov 11 20:31:16 1996
+++ include/asm-m68k/serial.h	Tue Mar  4 17:03:28 1997
@@ -171,7 +171,10 @@
  */
 struct serial_icounter_struct {
 	int cts, dsr, rng, dcd;
-	int reserved[16];
+	int rx, tx;
+	int frame, overrun, parity, brk;
+	int buf_overrun;
+	int reserved[9];
 };
 
 
@@ -192,7 +195,9 @@
  * Counters of the input lines (CTS, DSR, RI, CD) interrupts
  */
 struct async_icount {
-	__u32	cts, dsr, rng, dcd;	
+	__u32	cts, dsr, rng, dcd, tx, rx;
+	__u32	frame, parity, overrun, brk;
+	__u32	buf_overrun;
 };
 
 struct async_struct {
@@ -299,6 +304,7 @@
 	}
 	*tty->flip.flag_buf_ptr++ = err;
 	*tty->flip.char_buf_ptr++ = ch;
+	info->icount.rx++;
 	queue_task_irq(&tty->flip.tqueue, &tq_timer);
 }
 
@@ -308,6 +314,7 @@
 	
 	if (info->x_char) {
 		ch = info->x_char;
+		info->icount.tx++;
 		info->x_char = 0;
 		return( ch );
 	}
@@ -317,6 +324,7 @@
 
 	ch = info->xmit_buf[info->xmit_tail++];
 	info->xmit_tail &= SERIAL_XMIT_SIZE - 1;
+	info->icount.tx++;
 	if (--info->xmit_cnt < WAKEUP_CHARS)
 		rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
 	return( ch );

-- 
Andreas Schwab                                      "And now for something
schwab@issan.informatik.uni-dortmund.de              completely different"
