patch-2.4.6 linux/arch/ppc/8xx_io/uart.c

Next file: linux/arch/ppc/boot/chrp/main.c
Previous file: linux/arch/ppc/8xx_io/commproc.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.5/linux/arch/ppc/8xx_io/uart.c linux/arch/ppc/8xx_io/uart.c
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.uart.c 1.10 05/17/01 18:14:20 cort
+ * BK Id: SCCS/s.uart.c 1.14 06/27/01 14:49:55 trini
  */
 /*
  *  UART driver for MPC860 CPM SCC or SMC
@@ -44,6 +44,9 @@
 #include <asm/8xx_immap.h>
 #include <asm/mpc8xx.h>
 #include "commproc.h"
+#ifdef CONFIG_MAGIC_SYSRQ
+#include <linux/sysrq.h>
+#endif
 
 #ifdef CONFIG_KGDB
 extern void breakpoint(void);
@@ -91,6 +94,15 @@
 static int serial_refcount;
 static int serial_console_setup(struct console *co, char *options);
 
+static int serial_console_wait_key(struct console *co);
+static void serial_console_write(struct console *c, const char *s,
+				unsigned count);
+static kdev_t serial_console_device(struct console *c);
+
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+static unsigned long break_pressed; /* break, really ... */
+#endif
+
 /*
  * Serial driver configuration section.  Here are the various options:
  */
@@ -202,6 +214,16 @@
 	cbd_t			*tx_cur;
 } ser_info_t;
 
+static struct console sercons = {
+	name:		"ttyS",
+	write:		serial_console_write,
+	device:		serial_console_device,
+	wait_key:	serial_console_wait_key,
+	setup:		serial_console_setup,
+	flags:		CON_PRINTBUFFER,
+	index:		CONFIG_SERIAL_CONSOLE_PORT,
+};
+
 static void change_speed(ser_info_t *info);
 static void rs_8xx_wait_until_sent(struct tty_struct *tty, int timeout);
 
@@ -325,7 +347,7 @@
 	mark_bh(SERIAL_BH);
 }
 
-static _INLINE_ void receive_chars(ser_info_t *info)
+static _INLINE_ void receive_chars(ser_info_t *info, struct pt_regs *regs)
 {
 	struct tty_struct *tty = info->tty;
 	unsigned char ch, *cp;
@@ -413,7 +435,7 @@
 				}
 				 */
 				status &= info->read_status_mask;
-		
+
 				if (status & (BD_SC_BR)) {
 #ifdef SERIAL_DEBUG_INTR
 					printk("handling break....");
@@ -440,6 +462,17 @@
 					}
 				}
 			}
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+			if (break_pressed && info->line == sercons.index) {
+				if (ch != 0 && time_before(jiffies, 
+							break_pressed + HZ*5)) {
+					handle_sysrq(ch, regs, NULL, NULL);
+					break_pressed = 0;
+					goto ignore_char;
+				} else
+					break_pressed = 0;
+			}
+#endif
 			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
 				break;
 
@@ -448,6 +481,7 @@
 			tty->flip.count++;
 		}
 
+	ignore_char:	
 		/* This BD is ready to be used again.  Clear status.
 		 * Get next BD.
 		 */
@@ -459,17 +493,27 @@
 		else
 			bdp++;
 	}
-
 	info->rx_cur = (cbd_t *)bdp;
 
 	queue_task(&tty->flip.tqueue, &tq_timer);
 }
 
-static _INLINE_ void receive_break(ser_info_t *info)
+static _INLINE_ void receive_break(ser_info_t *info, struct pt_regs *regs)
 {
 	struct tty_struct *tty = info->tty;
 
 	info->state->icount.brk++;
+
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+	if (info->line == sercons.index) {
+		if (!break_pressed) {
+			break_pressed = jiffies;
+			return;
+		} else
+			break_pressed = 0;
+	}
+#endif
+
 	/* Check to see if there is room in the tty buffer for
 	 * the break.  If not, we exit now, losing the break.  FIXME
 	 */
@@ -482,7 +526,7 @@
 	queue_task(&tty->flip.tqueue, &tq_timer);
 }
 
-static _INLINE_ void transmit_chars(ser_info_t *info)
+static _INLINE_ void transmit_chars(ser_info_t *info, struct pt_regs *regs)
 {
 	
 	if ((info->flags & TX_WAKEUP) ||
@@ -571,7 +615,7 @@
 /*
  * This is the serial driver's interrupt routine for a single port
  */
-static void rs_8xx_interrupt(void *dev_id)
+static void rs_8xx_interrupt(void *dev_id, struct pt_regs *regs)
 {
 	u_char	events;
 	int	idx;
@@ -585,21 +629,23 @@
 	if (info->state->smc_scc_num & NUM_IS_SCC) {
 		sccp = &cpmp->cp_scc[idx];
 		events = sccp->scc_scce;
+		if (events & SMCM_BRKE)
+			receive_break(info, regs);
 		if (events & SCCM_RX)
-			receive_chars(info);
+			receive_chars(info, regs);
 		if (events & SCCM_TX)
-			transmit_chars(info);
+			transmit_chars(info, regs);
 		sccp->scc_scce = events;
 	}
 	else {
 		smcp = &cpmp->cp_smc[idx];
 		events = smcp->smc_smce;
 		if (events & SMCM_BRKE)
-			receive_break(info);
+			receive_break(info, regs);
 		if (events & SMCM_RX)
-			receive_chars(info);
+			receive_chars(info, regs);
 		if (events & SMCM_TX)
-			transmit_chars(info);
+			transmit_chars(info, regs);
 		smcp->smc_smce = events;
 	}
 	
@@ -2428,17 +2474,6 @@
 	return MKDEV(TTY_MAJOR, 64 + c->index);
 }
 
-
-static struct console sercons = {
-	name:		"ttyS",
-	write:		serial_console_write,
-	device:		serial_console_device,
-	wait_key:	serial_console_wait_key,
-	setup:		serial_console_setup,
-	flags:		CON_PRINTBUFFER,
-	index:		CONFIG_SERIAL_CONSOLE_PORT,
-};
-
 /*
  *	Register console.
  */
@@ -2771,7 +2806,7 @@
 					immap->im_ioport.iop_padir &= ~iobits;
 					immap->im_ioport.iop_paodr &= ~iobits;
 				}
-#endif
+#endif /* CONFIG_ALTSMC2 */
 
 				/* Connect the baud rate generator to the
 				 * SMC based upon index in rs_table.  Also

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