patch-2.4.23 linux-2.4.23/arch/ppc/8260_io/uart.c

Next file: linux-2.4.23/arch/ppc/8xx_io/Config.in
Previous file: linux-2.4.23/arch/parisc/config.in
Back to the patch index
Back to the overall index

diff -urN linux-2.4.22/arch/ppc/8260_io/uart.c linux-2.4.23/arch/ppc/8260_io/uart.c
@@ -47,6 +47,10 @@
 #include <asm/cpm_8260.h>
 #include <asm/irq.h>
 
+#ifdef CONFIG_MAGIC_SYSRQ
+#include <linux/sysrq.h>
+#endif
+
 #ifdef CONFIG_SERIAL_CONSOLE
 #include <linux/console.h>
 
@@ -68,6 +72,14 @@
 static int serial_refcount;
 static int serial_console_setup(struct console *co, char *options);
 
+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:
  */
@@ -181,6 +193,16 @@
 	cbd_t			*tx_cur;
 } ser_info_t;
 
+static struct console sercons = {
+        name:           "ttyS",
+        write:          serial_console_write,
+        device:         serial_console_device,
+        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);
 
@@ -302,7 +324,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;
@@ -417,6 +439,19 @@
 					}
 				}
 			}
+
+#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;
 
@@ -425,6 +460,10 @@
 			tty->flip.count++;
 		}
 
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+	ignore_char:
+#endif
+
 		/* This BD is ready to be used again.  Clear status.
 		 * Get next BD.
 		 */
@@ -442,7 +481,36 @@
 	queue_task(&tty->flip.tqueue, &tq_timer);
 }
 
-static _INLINE_ void transmit_chars(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
+	 */
+	if ((tty->flip.count + 1) >= TTY_FLIPBUF_SIZE)
+		return;
+	*(tty->flip.flag_buf_ptr++) = TTY_BREAK;
+	*(tty->flip.char_buf_ptr++) = 0;
+	tty->flip.count++;
+
+	queue_task(&tty->flip.tqueue, &tq_timer);
+}
+
+
+static _INLINE_ void transmit_chars(ser_info_t *info, struct pt_regs *regs)
 {
 
 	if (info->flags & TX_WAKEUP) {
@@ -543,19 +611,23 @@
 	if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
 		smcp = &immr->im_smc[idx];
 		events = smcp->smc_smce;
+		if (events & SMCM_BRKE)
+			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;
 	}
 	else {
 		sccp = &immr->im_scc[idx - SCC_IDX_BASE];
 		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;
 	}
 
@@ -2218,16 +2290,6 @@
 	return MKDEV(TTYAUX_MAJOR, 64 + c->index);
 }
 
-
-static struct console sercons = {
-	name:		"ttyS",
-	write:		serial_console_write,
-	device:		serial_console_device,
-	setup:		serial_console_setup,
-	flags:		CON_PRINTBUFFER,
-	index:		CONFIG_SERIAL_CONSOLE_PORT,
-};
-
 /*
  *	Register console.
  */

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