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
- Lines: 198
- Date:
Mon Jul 2 14:34:57 2001
- Orig file:
v2.4.5/linux/arch/ppc/8xx_io/uart.c
- Orig date:
Mon May 21 17:04:46 2001
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)