Commit fca5dcd4 authored by Paul Mackerras's avatar Paul Mackerras

powerpc: Simplify and clean up the xmon terminal I/O

This factors out the common bits of arch/powerpc/xmon/start_*.c into
a new nonstdio.c, and removes some stuff that was supposed to make
xmon's I/O routines somewhat stdio-like but was never used.

It also makes the parsing of the xmon= command line option common,
so that ppc32 can now use xmon={off,on,early} also.
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 3825ac0e
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#include <asm/page.h> #include <asm/page.h>
#include <asm/mmu.h> #include <asm/mmu.h>
#include <asm/lmb.h> #include <asm/lmb.h>
#include <asm/xmon.h>
#undef DEBUG #undef DEBUG
...@@ -559,3 +560,23 @@ void __init smp_setup_cpu_maps(void) ...@@ -559,3 +560,23 @@ void __init smp_setup_cpu_maps(void)
#endif /* CONFIG_PPC64 */ #endif /* CONFIG_PPC64 */
} }
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
#ifdef CONFIG_XMON
static int __init early_xmon(char *p)
{
/* ensure xmon is enabled */
if (p) {
if (strncmp(p, "on", 2) == 0)
xmon_init(1);
if (strncmp(p, "off", 3) == 0)
xmon_init(0);
if (strncmp(p, "early", 5) != 0)
return 0;
}
xmon_init(1);
debugger(NULL);
return 0;
}
early_param("xmon", early_xmon);
#endif
...@@ -303,14 +303,9 @@ void __init setup_arch(char **cmdline_p) ...@@ -303,14 +303,9 @@ void __init setup_arch(char **cmdline_p)
pmac_feature_init(); /* New cool way */ pmac_feature_init(); /* New cool way */
#endif #endif
#ifdef CONFIG_XMON #ifdef CONFIG_XMON_DEFAULT
xmon_map_scc(); xmon_init(1);
if (strstr(cmd_line, "xmon")) { #endif
xmon_init(1);
debugger(NULL);
}
#endif /* CONFIG_XMON */
if ( ppc_md.progress ) ppc_md.progress("setup_arch: enter", 0x3eab);
#if defined(CONFIG_KGDB) #if defined(CONFIG_KGDB)
if (ppc_md.kgdb_map_scc) if (ppc_md.kgdb_map_scc)
......
...@@ -858,26 +858,6 @@ int check_legacy_ioport(unsigned long base_port) ...@@ -858,26 +858,6 @@ int check_legacy_ioport(unsigned long base_port)
} }
EXPORT_SYMBOL(check_legacy_ioport); EXPORT_SYMBOL(check_legacy_ioport);
#ifdef CONFIG_XMON
static int __init early_xmon(char *p)
{
/* ensure xmon is enabled */
if (p) {
if (strncmp(p, "on", 2) == 0)
xmon_init(1);
if (strncmp(p, "off", 3) == 0)
xmon_init(0);
if (strncmp(p, "early", 5) != 0)
return 0;
}
xmon_init(1);
debugger(NULL);
return 0;
}
early_param("xmon", early_xmon);
#endif
void cpu_die(void) void cpu_die(void)
{ {
if (ppc_md.cpu_die) if (ppc_md.cpu_die)
......
...@@ -8,4 +8,4 @@ obj-$(CONFIG_8xx) += start_8xx.o ...@@ -8,4 +8,4 @@ obj-$(CONFIG_8xx) += start_8xx.o
obj-$(CONFIG_6xx) += start_32.o obj-$(CONFIG_6xx) += start_32.o
obj-$(CONFIG_4xx) += start_32.o obj-$(CONFIG_4xx) += start_32.o
obj-$(CONFIG_PPC64) += start_64.o obj-$(CONFIG_PPC64) += start_64.o
obj-y += xmon.o ppc-dis.o ppc-opc.o subr_prf.o setjmp.o obj-y += xmon.o ppc-dis.o ppc-opc.o setjmp.o nonstdio.o
/*
* Copyright (C) 1996-2005 Paul Mackerras.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <linux/string.h>
#include <asm/time.h>
#include "nonstdio.h"
int xmon_putchar(int c)
{
char ch = c;
if (c == '\n')
xmon_putchar('\r');
return xmon_write(&ch, 1) == 1? c: -1;
}
static char line[256];
static char *lineptr;
static int lineleft;
int xmon_expect(const char *str, unsigned long timeout)
{
int c;
unsigned long t0;
/* assume 25MHz default timebase if tb_ticks_per_sec not set yet */
timeout *= tb_ticks_per_sec? tb_ticks_per_sec: 25000000;
t0 = get_tbl();
do {
lineptr = line;
for (;;) {
c = xmon_read_poll();
if (c == -1) {
if (get_tbl() - t0 > timeout)
return 0;
continue;
}
if (c == '\n')
break;
if (c != '\r' && lineptr < &line[sizeof(line) - 1])
*lineptr++ = c;
}
*lineptr = 0;
} while (strstr(line, str) == NULL);
return 1;
}
int xmon_getchar(void)
{
int c;
if (lineleft == 0) {
lineptr = line;
for (;;) {
c = xmon_readchar();
if (c == -1 || c == 4)
break;
if (c == '\r' || c == '\n') {
*lineptr++ = '\n';
xmon_putchar('\n');
break;
}
switch (c) {
case 0177:
case '\b':
if (lineptr > line) {
xmon_putchar('\b');
xmon_putchar(' ');
xmon_putchar('\b');
--lineptr;
}
break;
case 'U' & 0x1F:
while (lineptr > line) {
xmon_putchar('\b');
xmon_putchar(' ');
xmon_putchar('\b');
--lineptr;
}
break;
default:
if (lineptr >= &line[sizeof(line) - 1])
xmon_putchar('\a');
else {
xmon_putchar(c);
*lineptr++ = c;
}
}
}
lineleft = lineptr - line;
lineptr = line;
}
if (lineleft == 0)
return -1;
--lineleft;
return *lineptr++;
}
char *xmon_gets(char *str, int nb)
{
char *p;
int c;
for (p = str; p < str + nb - 1; ) {
c = xmon_getchar();
if (c == -1) {
if (p == str)
return NULL;
break;
}
*p++ = c;
if (c == '\n')
break;
}
*p = 0;
return str;
}
void xmon_printf(const char *format, ...)
{
va_list args;
int n;
static char xmon_outbuf[1024];
va_start(args, format);
n = vsnprintf(xmon_outbuf, sizeof(xmon_outbuf), format, args);
va_end(args);
xmon_write(xmon_outbuf, n);
}
typedef int FILE;
extern FILE *xmon_stdin, *xmon_stdout;
#define EOF (-1) #define EOF (-1)
#define stdin xmon_stdin
#define stdout xmon_stdout
#define printf xmon_printf #define printf xmon_printf
#define fprintf xmon_fprintf
#define fputs xmon_fputs
#define fgets xmon_fgets
#define putchar xmon_putchar #define putchar xmon_putchar
#define getchar xmon_getchar
#define putc xmon_putc
#define getc xmon_getc
#define fopen(n, m) NULL
#define fflush(f) do {} while (0)
#define fclose(f) do {} while (0)
extern char *fgets(char *, int, void *);
extern void xmon_printf(const char *, ...);
extern void xmon_fprintf(void *, const char *, ...);
extern void xmon_sprintf(char *, const char *, ...);
#define perror(s) printf("%s: no files!\n", (s)) extern int xmon_putchar(int c);
extern int xmon_getchar(void);
extern char *xmon_gets(char *, int);
extern void xmon_printf(const char *, ...);
extern void xmon_map_scc(void);
extern int xmon_expect(const char *str, unsigned long timeout);
extern int xmon_write(void *ptr, int nb);
extern int xmon_readchar(void);
extern int xmon_read_poll(void);
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#include <linux/cuda.h> #include <linux/cuda.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/sysrq.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <asm/xmon.h> #include <asm/xmon.h>
#include <asm/prom.h> #include <asm/prom.h>
...@@ -22,10 +21,11 @@ ...@@ -22,10 +21,11 @@
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/delay.h> #include <asm/delay.h>
#include <asm/btext.h> #include <asm/btext.h>
#include <asm/time.h>
#include "nonstdio.h"
static volatile unsigned char __iomem *sccc, *sccd; static volatile unsigned char __iomem *sccc, *sccd;
unsigned int TXRDY, RXRDY, DLAB; unsigned int TXRDY, RXRDY, DLAB;
static int xmon_expect(const char *str, unsigned int timeout);
static int use_serial; static int use_serial;
static int use_screen; static int use_screen;
...@@ -33,16 +33,6 @@ static int via_modem; ...@@ -33,16 +33,6 @@ static int via_modem;
static int xmon_use_sccb; static int xmon_use_sccb;
static struct device_node *channel_node; static struct device_node *channel_node;
#define TB_SPEED 25000000
static inline unsigned int readtb(void)
{
unsigned int ret;
asm volatile("mftb %0" : "=r" (ret) :);
return ret;
}
void buf_access(void) void buf_access(void)
{ {
if (DLAB) if (DLAB)
...@@ -91,23 +81,7 @@ static unsigned long chrp_find_phys_io_base(void) ...@@ -91,23 +81,7 @@ static unsigned long chrp_find_phys_io_base(void)
} }
#endif /* CONFIG_PPC_CHRP */ #endif /* CONFIG_PPC_CHRP */
#ifdef CONFIG_MAGIC_SYSRQ void xmon_map_scc(void)
static void sysrq_handle_xmon(int key, struct pt_regs *regs,
struct tty_struct *tty)
{
xmon(regs);
}
static struct sysrq_key_op sysrq_xmon_op =
{
.handler = sysrq_handle_xmon,
.help_msg = "Xmon",
.action_msg = "Entering xmon",
};
#endif
void
xmon_map_scc(void)
{ {
#ifdef CONFIG_PPC_MULTIPLATFORM #ifdef CONFIG_PPC_MULTIPLATFORM
volatile unsigned char __iomem *base; volatile unsigned char __iomem *base;
...@@ -217,8 +191,6 @@ xmon_map_scc(void) ...@@ -217,8 +191,6 @@ xmon_map_scc(void)
RXRDY = 1; RXRDY = 1;
DLAB = 0x80; DLAB = 0x80;
#endif /* platform */ #endif /* platform */
register_sysrq_key('x', &sysrq_xmon_op);
} }
static int scc_initialized = 0; static int scc_initialized = 0;
...@@ -238,8 +210,7 @@ static inline void do_poll_adb(void) ...@@ -238,8 +210,7 @@ static inline void do_poll_adb(void)
#endif /* CONFIG_ADB_CUDA */ #endif /* CONFIG_ADB_CUDA */
} }
int int xmon_write(void *ptr, int nb)
xmon_write(void *handle, void *ptr, int nb)
{ {
char *p = ptr; char *p = ptr;
int i, c, ct; int i, c, ct;
...@@ -311,8 +282,7 @@ static unsigned char xmon_shift_keytab[128] = ...@@ -311,8 +282,7 @@ static unsigned char xmon_shift_keytab[128] =
"\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */ "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
"\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */ "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
static int static int xmon_get_adb_key(void)
xmon_get_adb_key(void)
{ {
int k, t, on; int k, t, on;
...@@ -350,32 +320,21 @@ xmon_get_adb_key(void) ...@@ -350,32 +320,21 @@ xmon_get_adb_key(void)
} }
#endif /* CONFIG_BOOTX_TEXT */ #endif /* CONFIG_BOOTX_TEXT */
int int xmon_readchar(void)
xmon_read(void *handle, void *ptr, int nb)
{ {
char *p = ptr;
int i;
#ifdef CONFIG_BOOTX_TEXT #ifdef CONFIG_BOOTX_TEXT
if (use_screen) { if (use_screen)
for (i = 0; i < nb; ++i) return xmon_get_adb_key();
*p++ = xmon_get_adb_key();
return i;
}
#endif #endif
if (!scc_initialized) if (!scc_initialized)
xmon_init_scc(); xmon_init_scc();
for (i = 0; i < nb; ++i) {
while ((*sccc & RXRDY) == 0) while ((*sccc & RXRDY) == 0)
do_poll_adb(); do_poll_adb();
buf_access(); buf_access();
*p++ = *sccd; return *sccd;
}
return i;
} }
int int xmon_read_poll(void)
xmon_read_poll(void)
{ {
if ((*sccc & RXRDY) == 0) { if ((*sccc & RXRDY) == 0) {
do_poll_adb(); do_poll_adb();
...@@ -395,8 +354,7 @@ static unsigned char scc_inittab[] = { ...@@ -395,8 +354,7 @@ static unsigned char scc_inittab[] = {
3, 0xc1, /* rx enable, 8 bits */ 3, 0xc1, /* rx enable, 8 bits */
}; };
void void xmon_init_scc(void)
xmon_init_scc(void)
{ {
if ( _machine == _MACH_chrp ) if ( _machine == _MACH_chrp )
{ {
...@@ -410,6 +368,7 @@ xmon_init_scc(void) ...@@ -410,6 +368,7 @@ xmon_init_scc(void)
else if ( _machine == _MACH_Pmac ) else if ( _machine == _MACH_Pmac )
{ {
int i, x; int i, x;
unsigned long timeout;
if (channel_node != 0) if (channel_node != 0)
pmac_call_feature( pmac_call_feature(
...@@ -424,8 +383,12 @@ xmon_init_scc(void) ...@@ -424,8 +383,12 @@ xmon_init_scc(void)
PMAC_FTR_MODEM_ENABLE, PMAC_FTR_MODEM_ENABLE,
channel_node, 0, 1); channel_node, 0, 1);
printk(KERN_INFO "Modem powered up by debugger !\n"); printk(KERN_INFO "Modem powered up by debugger !\n");
t0 = readtb(); t0 = get_tbl();
while (readtb() - t0 < 3*TB_SPEED) timeout = 3 * tb_ticks_per_sec;
if (timeout == 0)
/* assume 25MHz if tb_ticks_per_sec not set */
timeout = 75000000;
while (get_tbl() - t0 < timeout)
eieio(); eieio();
} }
/* use the B channel if requested */ /* use the B channel if requested */
...@@ -447,164 +410,19 @@ xmon_init_scc(void) ...@@ -447,164 +410,19 @@ xmon_init_scc(void)
scc_initialized = 1; scc_initialized = 1;
if (via_modem) { if (via_modem) {
for (;;) { for (;;) {
xmon_write(NULL, "ATE1V1\r", 7); xmon_write("ATE1V1\r", 7);
if (xmon_expect("OK", 5)) { if (xmon_expect("OK", 5)) {
xmon_write(NULL, "ATA\r", 4); xmon_write("ATA\r", 4);
if (xmon_expect("CONNECT", 40)) if (xmon_expect("CONNECT", 40))
break; break;
} }
xmon_write(NULL, "+++", 3); xmon_write("+++", 3);
xmon_expect("OK", 3); xmon_expect("OK", 3);
} }
} }
} }
void *xmon_stdin; void xmon_enter(void)
void *xmon_stdout;
void *xmon_stderr;
int xmon_putc(int c, void *f)
{
char ch = c;
if (c == '\n')
xmon_putc('\r', f);
return xmon_write(f, &ch, 1) == 1? c: -1;
}
int xmon_putchar(int c)
{
return xmon_putc(c, xmon_stdout);
}
int xmon_fputs(char *str, void *f)
{
int n = strlen(str);
return xmon_write(f, str, n) == n? 0: -1;
}
int
xmon_readchar(void)
{
char ch;
for (;;) {
switch (xmon_read(xmon_stdin, &ch, 1)) {
case 1:
return ch;
case -1:
xmon_printf("read(stdin) returned -1\r\n", 0, 0);
return -1;
}
}
}
static char line[256];
static char *lineptr;
static int lineleft;
int xmon_expect(const char *str, unsigned int timeout)
{
int c;
unsigned int t0;
timeout *= TB_SPEED;
t0 = readtb();
do {
lineptr = line;
for (;;) {
c = xmon_read_poll();
if (c == -1) {
if (readtb() - t0 > timeout)
return 0;
continue;
}
if (c == '\n')
break;
if (c != '\r' && lineptr < &line[sizeof(line) - 1])
*lineptr++ = c;
}
*lineptr = 0;
} while (strstr(line, str) == NULL);
return 1;
}
int
xmon_getchar(void)
{
int c;
if (lineleft == 0) {
lineptr = line;
for (;;) {
c = xmon_readchar();
if (c == -1 || c == 4)
break;
if (c == '\r' || c == '\n') {
*lineptr++ = '\n';
xmon_putchar('\n');
break;
}
switch (c) {
case 0177:
case '\b':
if (lineptr > line) {
xmon_putchar('\b');
xmon_putchar(' ');
xmon_putchar('\b');
--lineptr;
}
break;
case 'U' & 0x1F:
while (lineptr > line) {
xmon_putchar('\b');
xmon_putchar(' ');
xmon_putchar('\b');
--lineptr;
}
break;
default:
if (lineptr >= &line[sizeof(line) - 1])
xmon_putchar('\a');
else {
xmon_putchar(c);
*lineptr++ = c;
}
}
}
lineleft = lineptr - line;
lineptr = line;
}
if (lineleft == 0)
return -1;
--lineleft;
return *lineptr++;
}
char *
xmon_fgets(char *str, int nb, void *f)
{
char *p;
int c;
for (p = str; p < str + nb - 1; ) {
c = xmon_getchar();
if (c == -1) {
if (p == str)
return NULL;
break;
}
*p++ = c;
if (c == '\n')
break;
}
*p = 0;
return str;
}
void
xmon_enter(void)
{ {
#ifdef CONFIG_ADB_PMU #ifdef CONFIG_ADB_PMU
if (_machine == _MACH_Pmac) { if (_machine == _MACH_Pmac) {
...@@ -613,8 +431,7 @@ xmon_enter(void) ...@@ -613,8 +431,7 @@ xmon_enter(void)
#endif #endif
} }
void void xmon_leave(void)
xmon_leave(void)
{ {
#ifdef CONFIG_ADB_PMU #ifdef CONFIG_ADB_PMU
if (_machine == _MACH_Pmac) { if (_machine == _MACH_Pmac) {
......
...@@ -6,182 +6,29 @@ ...@@ -6,182 +6,29 @@
* as published by the Free Software Foundation; either version * as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
#include <linux/config.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/sysrq.h>
#include <linux/init.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/io.h>
#include <asm/page.h>
#include <asm/prom.h>
#include <asm/processor.h>
#include <asm/udbg.h> #include <asm/udbg.h>
#include <asm/system.h>
#include "nonstdio.h" #include "nonstdio.h"
#ifdef CONFIG_MAGIC_SYSRQ void xmon_map_scc(void)
static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs,
struct tty_struct *tty)
{
/* ensure xmon is enabled */
xmon_init(1);
debugger(pt_regs);
}
static struct sysrq_key_op sysrq_xmon_op =
{ {
.handler = sysrq_handle_xmon,
.help_msg = "Xmon",
.action_msg = "Entering xmon",
};
static int __init setup_xmon_sysrq(void)
{
register_sysrq_key('x', &sysrq_xmon_op);
return 0;
} }
__initcall(setup_xmon_sysrq);
#endif /* CONFIG_MAGIC_SYSRQ */
int int xmon_write(void *ptr, int nb)
xmon_write(void *handle, void *ptr, int nb)
{ {
return udbg_write(ptr, nb); return udbg_write(ptr, nb);
} }
int int xmon_readchar(void)
xmon_read(void *handle, void *ptr, int nb)
{ {
return udbg_read(ptr, nb); if (udbg_getc)
return udbg_getc();
return -1;
} }
int int xmon_read_poll(void)
xmon_read_poll(void)
{ {
if (udbg_getc_poll) if (udbg_getc_poll)
return udbg_getc_poll(); return udbg_getc_poll();
return -1; return -1;
} }
FILE *xmon_stdin;
FILE *xmon_stdout;
int
xmon_putc(int c, void *f)
{
char ch = c;
if (c == '\n')
xmon_putc('\r', f);
return xmon_write(f, &ch, 1) == 1? c: -1;
}
int
xmon_putchar(int c)
{
return xmon_putc(c, xmon_stdout);
}
int
xmon_fputs(char *str, void *f)
{
int n = strlen(str);
return xmon_write(f, str, n) == n? 0: -1;
}
int
xmon_readchar(void)
{
char ch;
for (;;) {
switch (xmon_read(xmon_stdin, &ch, 1)) {
case 1:
return ch;
case -1:
xmon_printf("read(stdin) returned -1\r\n", 0, 0);
return -1;
}
}
}
static char line[256];
static char *lineptr;
static int lineleft;
int
xmon_getchar(void)
{
int c;
if (lineleft == 0) {
lineptr = line;
for (;;) {
c = xmon_readchar();
if (c == -1 || c == 4)
break;
if (c == '\r' || c == '\n') {
*lineptr++ = '\n';
xmon_putchar('\n');
break;
}
switch (c) {
case 0177:
case '\b':
if (lineptr > line) {
xmon_putchar('\b');
xmon_putchar(' ');
xmon_putchar('\b');
--lineptr;
}
break;
case 'U' & 0x1F:
while (lineptr > line) {
xmon_putchar('\b');
xmon_putchar(' ');
xmon_putchar('\b');
--lineptr;
}
break;
default:
if (lineptr >= &line[sizeof(line) - 1])
xmon_putchar('\a');
else {
xmon_putchar(c);
*lineptr++ = c;
}
}
}
lineleft = lineptr - line;
lineptr = line;
}
if (lineleft == 0)
return -1;
--lineleft;
return *lineptr++;
}
char *
xmon_fgets(char *str, int nb, void *f)
{
char *p;
int c;
for (p = str; p < str + nb - 1; ) {
c = xmon_getchar();
if (c == -1) {
if (p == str)
return NULL;
break;
}
*p++ = c;
if (c == '\n')
break;
}
*p = 0;
return str;
}
...@@ -15,273 +15,30 @@ ...@@ -15,273 +15,30 @@
#include <asm/8xx_immap.h> #include <asm/8xx_immap.h>
#include <asm/mpc8xx.h> #include <asm/mpc8xx.h>
#include <asm/commproc.h> #include <asm/commproc.h>
#include "nonstdio.h"
extern void xmon_printf(const char *fmt, ...);
extern int xmon_8xx_write(char *str, int nb); extern int xmon_8xx_write(char *str, int nb);
extern int xmon_8xx_read_poll(void); extern int xmon_8xx_read_poll(void);
extern int xmon_8xx_read_char(void); extern int xmon_8xx_read_char(void);
void prom_drawhex(uint);
void prom_drawstring(const char *str);
static int use_screen = 1; /* default */ void xmon_map_scc(void)
#define TB_SPEED 25000000
static inline unsigned int readtb(void)
{
unsigned int ret;
asm volatile("mftb %0" : "=r" (ret) :);
return ret;
}
void buf_access(void)
{
}
void
xmon_map_scc(void)
{ {
cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm); cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm);
use_screen = 0;
prom_drawstring("xmon uses serial port\n");
} }
static int scc_initialized = 0;
void xmon_init_scc(void); void xmon_init_scc(void);
int int xmon_write(void *ptr, int nb)
xmon_write(void *handle, void *ptr, int nb)
{ {
char *p = ptr;
int i, c, ct;
if (!scc_initialized)
xmon_init_scc();
return(xmon_8xx_write(ptr, nb)); return(xmon_8xx_write(ptr, nb));
} }
int xmon_wants_key; int xmon_readchar(void)
int
xmon_read(void *handle, void *ptr, int nb)
{ {
char *p = ptr; return xmon_8xx_read_char();
int i;
if (!scc_initialized)
xmon_init_scc();
for (i = 0; i < nb; ++i) {
*p++ = xmon_8xx_read_char();
}
return i;
} }
int int xmon_read_poll(void)
xmon_read_poll(void)
{ {
return(xmon_8xx_read_poll()); return(xmon_8xx_read_poll());
} }
void
xmon_init_scc()
{
scc_initialized = 1;
}
#if 0
extern int (*prom_entry)(void *);
int
xmon_exit(void)
{
struct prom_args {
char *service;
} args;
for (;;) {
args.service = "exit";
(*prom_entry)(&args);
}
}
#endif
void *xmon_stdin;
void *xmon_stdout;
void *xmon_stderr;
void
xmon_init(void)
{
}
int
xmon_putc(int c, void *f)
{
char ch = c;
if (c == '\n')
xmon_putc('\r', f);
return xmon_write(f, &ch, 1) == 1? c: -1;
}
int
xmon_putchar(int c)
{
return xmon_putc(c, xmon_stdout);
}
int
xmon_fputs(char *str, void *f)
{
int n = strlen(str);
return xmon_write(f, str, n) == n? 0: -1;
}
int
xmon_readchar(void)
{
char ch;
for (;;) {
switch (xmon_read(xmon_stdin, &ch, 1)) {
case 1:
return ch;
case -1:
xmon_printf("read(stdin) returned -1\r\n", 0, 0);
return -1;
}
}
}
static char line[256];
static char *lineptr;
static int lineleft;
#if 0
int xmon_expect(const char *str, unsigned int timeout)
{
int c;
unsigned int t0;
timeout *= TB_SPEED;
t0 = readtb();
do {
lineptr = line;
for (;;) {
c = xmon_read_poll();
if (c == -1) {
if (readtb() - t0 > timeout)
return 0;
continue;
}
if (c == '\n')
break;
if (c != '\r' && lineptr < &line[sizeof(line) - 1])
*lineptr++ = c;
}
*lineptr = 0;
} while (strstr(line, str) == NULL);
return 1;
}
#endif
int
xmon_getchar(void)
{
int c;
if (lineleft == 0) {
lineptr = line;
for (;;) {
c = xmon_readchar();
if (c == -1 || c == 4)
break;
if (c == '\r' || c == '\n') {
*lineptr++ = '\n';
xmon_putchar('\n');
break;
}
switch (c) {
case 0177:
case '\b':
if (lineptr > line) {
xmon_putchar('\b');
xmon_putchar(' ');
xmon_putchar('\b');
--lineptr;
}
break;
case 'U' & 0x1F:
while (lineptr > line) {
xmon_putchar('\b');
xmon_putchar(' ');
xmon_putchar('\b');
--lineptr;
}
break;
default:
if (lineptr >= &line[sizeof(line) - 1])
xmon_putchar('\a');
else {
xmon_putchar(c);
*lineptr++ = c;
}
}
}
lineleft = lineptr - line;
lineptr = line;
}
if (lineleft == 0)
return -1;
--lineleft;
return *lineptr++;
}
char *
xmon_fgets(char *str, int nb, void *f)
{
char *p;
int c;
for (p = str; p < str + nb - 1; ) {
c = xmon_getchar();
if (c == -1) {
if (p == str)
return 0;
break;
}
*p++ = c;
if (c == '\n')
break;
}
*p = 0;
return str;
}
void
prom_drawhex(uint val)
{
unsigned char buf[10];
int i;
for (i = 7; i >= 0; i--)
{
buf[i] = "0123456789abcdef"[val & 0x0f];
val >>= 4;
}
buf[8] = '\0';
xmon_fputs(buf, xmon_stdout);
}
void
prom_drawstring(const char *str)
{
xmon_fputs(str, xmon_stdout);
}
/*
* Written by Cort Dougan to replace the version originally used
* by Paul Mackerras, which came from NetBSD and thus had copyright
* conflicts with Linux.
*
* This file makes liberal use of the standard linux utility
* routines to reduce the size of the binary. We assume we can
* trust some parts of Linux inside the debugger.
* -- Cort (cort@cs.nmt.edu)
*
* Copyright (C) 1999 Cort Dougan.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/module.h>
#include <stdarg.h>
#include "nonstdio.h"
extern int xmon_write(void *, void *, int);
void xmon_vfprintf(void *f, const char *fmt, va_list ap)
{
static char xmon_buf[2048];
int n;
n = vsprintf(xmon_buf, fmt, ap);
xmon_write(f, xmon_buf, n);
}
void xmon_printf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
xmon_vfprintf(stdout, fmt, ap);
va_end(ap);
}
EXPORT_SYMBOL(xmon_printf);
void xmon_fprintf(void *f, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
xmon_vfprintf(f, fmt, ap);
va_end(ap);
}
/* /*
* Routines providing a simple monitor for use on the PowerMac. * Routines providing a simple monitor for use on the PowerMac.
* *
* Copyright (C) 1996 Paul Mackerras. * Copyright (C) 1996-2005 Paul Mackerras.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/kallsyms.h> #include <linux/kallsyms.h>
#include <linux/cpumask.h> #include <linux/cpumask.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/sysrq.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/string.h> #include <asm/string.h>
...@@ -144,15 +145,10 @@ static void xmon_print_symbol(unsigned long address, const char *mid, ...@@ -144,15 +145,10 @@ static void xmon_print_symbol(unsigned long address, const char *mid,
static const char *getvecname(unsigned long vec); static const char *getvecname(unsigned long vec);
extern int print_insn_powerpc(unsigned long, unsigned long, int); extern int print_insn_powerpc(unsigned long, unsigned long, int);
extern void printf(const char *fmt, ...);
extern void xmon_vfprintf(void *f, const char *fmt, va_list ap);
extern int xmon_putc(int c, void *f);
extern int putchar(int ch);
extern void xmon_enter(void); extern void xmon_enter(void);
extern void xmon_leave(void); extern void xmon_leave(void);
extern int xmon_read_poll(void);
extern long setjmp(long *); extern long setjmp(long *);
extern void longjmp(long *, long); extern void longjmp(long *, long);
extern void xmon_save_regs(struct pt_regs *); extern void xmon_save_regs(struct pt_regs *);
...@@ -748,7 +744,6 @@ cmds(struct pt_regs *excp) ...@@ -748,7 +744,6 @@ cmds(struct pt_regs *excp)
printf("%x:", smp_processor_id()); printf("%x:", smp_processor_id());
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
printf("mon> "); printf("mon> ");
fflush(stdout);
flush_input(); flush_input();
termch = 0; termch = 0;
cmd = skipbl(); cmd = skipbl();
...@@ -2151,7 +2146,6 @@ memzcan(void) ...@@ -2151,7 +2146,6 @@ memzcan(void)
ok = mread(a, &v, 1); ok = mread(a, &v, 1);
if (ok && !ook) { if (ok && !ook) {
printf("%.8x .. ", a); printf("%.8x .. ", a);
fflush(stdout);
} else if (!ok && ook) } else if (!ok && ook)
printf("%.8x\n", a - mskip); printf("%.8x\n", a - mskip);
ook = ok; ook = ok;
...@@ -2372,7 +2366,7 @@ int ...@@ -2372,7 +2366,7 @@ int
inchar(void) inchar(void)
{ {
if (lineptr == NULL || *lineptr == 0) { if (lineptr == NULL || *lineptr == 0) {
if (fgets(line, sizeof(line), stdin) == NULL) { if (xmon_gets(line, sizeof(line)) == NULL) {
lineptr = NULL; lineptr = NULL;
return EOF; return EOF;
} }
...@@ -2526,4 +2520,29 @@ void xmon_init(int enable) ...@@ -2526,4 +2520,29 @@ void xmon_init(int enable)
__debugger_dabr_match = NULL; __debugger_dabr_match = NULL;
__debugger_fault_handler = NULL; __debugger_fault_handler = NULL;
} }
xmon_map_scc();
} }
#ifdef CONFIG_MAGIC_SYSRQ
static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs,
struct tty_struct *tty)
{
/* ensure xmon is enabled */
xmon_init(1);
debugger(pt_regs);
}
static struct sysrq_key_op sysrq_xmon_op =
{
.handler = sysrq_handle_xmon,
.help_msg = "Xmon",
.action_msg = "Entering xmon",
};
static int __init setup_xmon_sysrq(void)
{
register_sysrq_key('x', &sysrq_xmon_op);
return 0;
}
__initcall(setup_xmon_sysrq);
#endif /* CONFIG_MAGIC_SYSRQ */
...@@ -7,7 +7,6 @@ struct pt_regs; ...@@ -7,7 +7,6 @@ struct pt_regs;
extern int xmon(struct pt_regs *excp); extern int xmon(struct pt_regs *excp);
extern void xmon_printf(const char *fmt, ...); extern void xmon_printf(const char *fmt, ...);
extern void xmon_init(int); extern void xmon_init(int);
extern void xmon_map_scc(void);
#endif #endif
#endif #endif
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