Commit 024b1e31 authored by Paul Mackerras's avatar Paul Mackerras

Merge bk://stop.crashing.org/linux-2.6-8260

into samba.org:/stuff/paulus/kernel/for-linus-ppc
parents c3e57580 54ce9a20
...@@ -50,6 +50,10 @@ ...@@ -50,6 +50,10 @@
#include <asm/cpm_8260.h> #include <asm/cpm_8260.h>
#include <asm/irq.h> #include <asm/irq.h>
#ifdef CONFIG_MAGIC_SYSRQ
#include <linux/sysrq.h>
#endif
#ifdef CONFIG_SERIAL_CONSOLE #ifdef CONFIG_SERIAL_CONSOLE
#include <linux/console.h> #include <linux/console.h>
...@@ -77,6 +81,14 @@ static char *serial_version = "0.02"; ...@@ -77,6 +81,14 @@ static char *serial_version = "0.02";
static struct tty_driver *serial_driver; static struct tty_driver *serial_driver;
static int serial_console_setup(struct console *co, char *options); 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: * Serial driver configuration section. Here are the various options:
*/ */
...@@ -208,6 +220,15 @@ typedef struct serial_info { ...@@ -208,6 +220,15 @@ typedef struct serial_info {
cbd_t *tx_cur; cbd_t *tx_cur;
} ser_info_t; } 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 change_speed(ser_info_t *info);
static void rs_8xx_wait_until_sent(struct tty_struct *tty, int timeout); static void rs_8xx_wait_until_sent(struct tty_struct *tty, int timeout);
...@@ -328,7 +349,7 @@ static _INLINE_ void rs_sched_event(ser_info_t *info, ...@@ -328,7 +349,7 @@ static _INLINE_ void rs_sched_event(ser_info_t *info,
schedule_work(&info->tqueue); schedule_work(&info->tqueue);
} }
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; struct tty_struct *tty = info->tty;
unsigned char ch, *cp; unsigned char ch, *cp;
...@@ -450,6 +471,19 @@ static _INLINE_ void receive_chars(ser_info_t *info) ...@@ -450,6 +471,19 @@ static _INLINE_ void receive_chars(ser_info_t *info)
} }
} }
} }
#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) if (tty->flip.count >= TTY_FLIPBUF_SIZE)
break; break;
...@@ -458,6 +492,10 @@ static _INLINE_ void receive_chars(ser_info_t *info) ...@@ -458,6 +492,10 @@ static _INLINE_ void receive_chars(ser_info_t *info)
tty->flip.count++; 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. /* This BD is ready to be used again. Clear status.
* Get next BD. * Get next BD.
*/ */
...@@ -475,7 +513,36 @@ static _INLINE_ void receive_chars(ser_info_t *info) ...@@ -475,7 +513,36 @@ static _INLINE_ void receive_chars(ser_info_t *info)
schedule_delayed_work(&tty->flip.work, 1); schedule_delayed_work(&tty->flip.work, 1);
} }
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) { if (info->flags & TX_WAKEUP) {
...@@ -575,19 +642,23 @@ static irqreturn_t rs_8xx_interrupt(int irq, void * dev_id, struct pt_regs * reg ...@@ -575,19 +642,23 @@ static irqreturn_t rs_8xx_interrupt(int irq, void * dev_id, struct pt_regs * reg
if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) { if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
smcp = &immr->im_smc[idx]; smcp = &immr->im_smc[idx];
events = smcp->smc_smce; events = smcp->smc_smce;
if (events & SMCM_BRKE)
receive_break(info, regs);
if (events & SMCM_RX) if (events & SMCM_RX)
receive_chars(info); receive_chars(info, regs);
if (events & SMCM_TX) if (events & SMCM_TX)
transmit_chars(info); transmit_chars(info, regs);
smcp->smc_smce = events; smcp->smc_smce = events;
} }
else { else {
sccp = &immr->im_scc[idx - SCC_IDX_BASE]; sccp = &immr->im_scc[idx - SCC_IDX_BASE];
events = sccp->scc_scce; events = sccp->scc_scce;
if (events & SMCM_BRKE)
receive_break(info, regs);
if (events & SCCM_RX) if (events & SCCM_RX)
receive_chars(info); receive_chars(info, regs);
if (events & SCCM_TX) if (events & SCCM_TX)
transmit_chars(info); transmit_chars(info, regs);
sccp->scc_scce = events; sccp->scc_scce = events;
} }
...@@ -2397,16 +2468,6 @@ static kdev_t serial_console_device(struct console *c) ...@@ -2397,16 +2468,6 @@ static kdev_t serial_console_device(struct console *c)
return serial_driver; return serial_driver;
} }
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. * Register console.
*/ */
......
...@@ -195,7 +195,7 @@ typedef struct smc_uart { ...@@ -195,7 +195,7 @@ typedef struct smc_uart {
/* SMC uart mode register (Internal memory map). /* SMC uart mode register (Internal memory map).
*/ */
#define SMCMR_REN ((ushort)0x0001) #define SMCMR_REN ((ushort)0x0001)
#define SMCMR_TEN ((ushort)0x0002) #define SMCMR_TEN ((ushort)0x0002)
#define SMCMR_DM ((ushort)0x000c) #define SMCMR_DM ((ushort)0x000c)
#define SMCMR_SM_GCI ((ushort)0x0000) #define SMCMR_SM_GCI ((ushort)0x0000)
...@@ -212,10 +212,12 @@ typedef struct smc_uart { ...@@ -212,10 +212,12 @@ typedef struct smc_uart {
/* SMC Event and Mask register. /* SMC Event and Mask register.
*/ */
#define SMCM_TXE ((unsigned char)0x10) #define SMCM_BRKE ((unsigned char)0x40) /* When in UART Mode */
#define SMCM_BSY ((unsigned char)0x04) #define SMCM_BRK ((unsigned char)0x10) /* When in UART Mode */
#define SMCM_TX ((unsigned char)0x02) #define SMCM_TXE ((unsigned char)0x10)
#define SMCM_RX ((unsigned char)0x01) #define SMCM_BSY ((unsigned char)0x04)
#define SMCM_TX ((unsigned char)0x02)
#define SMCM_RX ((unsigned char)0x01)
/* Baud rate generators. /* Baud rate generators.
*/ */
...@@ -314,10 +316,10 @@ typedef struct smc_uart { ...@@ -314,10 +316,10 @@ typedef struct smc_uart {
/* SCC Event and Mask register. /* SCC Event and Mask register.
*/ */
#define SCCM_TXE ((unsigned char)0x10) #define SCCM_TXE ((unsigned char)0x10)
#define SCCM_BSY ((unsigned char)0x04) #define SCCM_BSY ((unsigned char)0x04)
#define SCCM_TX ((unsigned char)0x02) #define SCCM_TX ((unsigned char)0x02)
#define SCCM_RX ((unsigned char)0x01) #define SCCM_RX ((unsigned char)0x01)
typedef struct scc_param { typedef struct scc_param {
ushort scc_rbase; /* Rx Buffer descriptor base address */ ushort scc_rbase; /* Rx Buffer descriptor base address */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment