# This is a BitKeeper generated patch for the following project: # Project Name: Linux 2.4 # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.126 -> 1.127 # arch/ppc/8xx_io/uart.c 1.13 -> 1.14 # arch/ppc/8xx_io/commproc.c 1.10 -> 1.11 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 01/06/05 trini@bill-the-cat.bloom.county 1.127 # 03-sysrq.patch # -------------------------------------------- # diff -Nru a/arch/ppc/8xx_io/commproc.c b/arch/ppc/8xx_io/commproc.c --- a/arch/ppc/8xx_io/commproc.c Tue Jun 5 14:37:29 2001 +++ b/arch/ppc/8xx_io/commproc.c Tue Jun 5 14:37:29 2001 @@ -47,12 +47,12 @@ /* CPM interrupt vector functions. */ struct cpm_action { - void (*handler)(void *); + void (*handler)(void *, struct pt_regs * regs); void *dev_id; }; static struct cpm_action cpm_vecs[CPMVEC_NR]; static void cpm_interrupt(int irq, void * dev, struct pt_regs * regs); -static void cpm_error_interrupt(void *); +static void cpm_error_interrupt(void *, struct pt_regs * regs); void m8xx_cpm_reset(uint host_page_addr) @@ -129,7 +129,7 @@ vec >>= 11; if (cpm_vecs[vec].handler != 0) - (*cpm_vecs[vec].handler)(cpm_vecs[vec].dev_id); + (*cpm_vecs[vec].handler)(cpm_vecs[vec].dev_id, regs); else ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << vec); @@ -146,14 +146,15 @@ * tests in the interrupt handler. */ static void -cpm_error_interrupt(void *dev) +cpm_error_interrupt(void *dev, struct pt_regs *regs) { } /* Install a CPM interrupt handler. */ void -cpm_install_handler(int vec, void (*handler)(void *), void *dev_id) +cpm_install_handler(int vec, void (*handler)(void *, struct pt_regs *regs), + void *dev_id) { /* If null handler, assume we are trying to free the IRQ. diff -Nru a/arch/ppc/8xx_io/uart.c b/arch/ppc/8xx_io/uart.c --- a/arch/ppc/8xx_io/uart.c Tue Jun 5 14:37:29 2001 +++ b/arch/ppc/8xx_io/uart.c Tue Jun 5 14:37:29 2001 @@ -44,6 +44,9 @@ #include #include #include "commproc.h" +#ifdef CONFIG_MAGIC_SYSRQ +#include +#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; } @@ -2427,17 +2473,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. ===== arch/ppc/8xx_io/commproc.h 1.13 vs edited ===== --- 1.13/arch/ppc/8xx_io/commproc.h Thu Jun 7 13:32:54 2001 +++ edited/arch/ppc/8xx_io/commproc.h Thu Jun 7 14:46:12 2001 @@ -870,7 +870,8 @@ #define CICR_IEN ((uint)0x00000080) /* Int. enable */ #define CICR_SPS ((uint)0x00000001) /* SCC Spread */ -extern void cpm_install_handler(int vec, void (*handler)(void *), void *dev_id); +extern void cpm_install_handler(int vec, + void (*handler)(void *, struct pt_regs *regs), void *dev_id); extern void cpm_free_handler(int vec); #endif /* __CPM_8XX__ */