aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2005-11-08 06:55:08 -0500
committerPaul Mackerras <paulus@samba.org>2005-11-08 06:55:08 -0500
commitfca5dcd4835ed09bb1a48a355344aff7a25c76e0 (patch)
treeb596fad4509d3208ef974b9e22b2326ecfd85b83
parent3825ac0ee66b50cb0208ee74796fe65f3040e67c (diff)
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: Paul Mackerras <paulus@samba.org>
-rw-r--r--arch/powerpc/kernel/setup-common.c21
-rw-r--r--arch/powerpc/kernel/setup_32.c11
-rw-r--r--arch/powerpc/kernel/setup_64.c20
-rw-r--r--arch/powerpc/xmon/Makefile2
-rw-r--r--arch/powerpc/xmon/nonstdio.c134
-rw-r--r--arch/powerpc/xmon/nonstdio.h28
-rw-r--r--arch/powerpc/xmon/start_32.c235
-rw-r--r--arch/powerpc/xmon/start_64.c167
-rw-r--r--arch/powerpc/xmon/start_8xx.c255
-rw-r--r--arch/powerpc/xmon/subr_prf.c54
-rw-r--r--arch/powerpc/xmon/xmon.c37
-rw-r--r--include/asm-powerpc/xmon.h1
12 files changed, 236 insertions, 729 deletions
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index e22856ecb5a0..26bb1fe6384b 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -51,6 +51,7 @@
51#include <asm/page.h> 51#include <asm/page.h>
52#include <asm/mmu.h> 52#include <asm/mmu.h>
53#include <asm/lmb.h> 53#include <asm/lmb.h>
54#include <asm/xmon.h>
54 55
55#undef DEBUG 56#undef DEBUG
56 57
@@ -559,3 +560,23 @@ void __init smp_setup_cpu_maps(void)
559#endif /* CONFIG_PPC64 */ 560#endif /* CONFIG_PPC64 */
560} 561}
561#endif /* CONFIG_SMP */ 562#endif /* CONFIG_SMP */
563
564#ifdef CONFIG_XMON
565static int __init early_xmon(char *p)
566{
567 /* ensure xmon is enabled */
568 if (p) {
569 if (strncmp(p, "on", 2) == 0)
570 xmon_init(1);
571 if (strncmp(p, "off", 3) == 0)
572 xmon_init(0);
573 if (strncmp(p, "early", 5) != 0)
574 return 0;
575 }
576 xmon_init(1);
577 debugger(NULL);
578
579 return 0;
580}
581early_param("xmon", early_xmon);
582#endif
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 3af2631e3fab..0fbc73f7f828 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -303,14 +303,9 @@ void __init setup_arch(char **cmdline_p)
303 pmac_feature_init(); /* New cool way */ 303 pmac_feature_init(); /* New cool way */
304#endif 304#endif
305 305
306#ifdef CONFIG_XMON 306#ifdef CONFIG_XMON_DEFAULT
307 xmon_map_scc(); 307 xmon_init(1);
308 if (strstr(cmd_line, "xmon")) { 308#endif
309 xmon_init(1);
310 debugger(NULL);
311 }
312#endif /* CONFIG_XMON */
313 if ( ppc_md.progress ) ppc_md.progress("setup_arch: enter", 0x3eab);
314 309
315#if defined(CONFIG_KGDB) 310#if defined(CONFIG_KGDB)
316 if (ppc_md.kgdb_map_scc) 311 if (ppc_md.kgdb_map_scc)
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 0471e843b6c5..54c606f680b3 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -858,26 +858,6 @@ int check_legacy_ioport(unsigned long base_port)
858} 858}
859EXPORT_SYMBOL(check_legacy_ioport); 859EXPORT_SYMBOL(check_legacy_ioport);
860 860
861#ifdef CONFIG_XMON
862static int __init early_xmon(char *p)
863{
864 /* ensure xmon is enabled */
865 if (p) {
866 if (strncmp(p, "on", 2) == 0)
867 xmon_init(1);
868 if (strncmp(p, "off", 3) == 0)
869 xmon_init(0);
870 if (strncmp(p, "early", 5) != 0)
871 return 0;
872 }
873 xmon_init(1);
874 debugger(NULL);
875
876 return 0;
877}
878early_param("xmon", early_xmon);
879#endif
880
881void cpu_die(void) 861void cpu_die(void)
882{ 862{
883 if (ppc_md.cpu_die) 863 if (ppc_md.cpu_die)
diff --git a/arch/powerpc/xmon/Makefile b/arch/powerpc/xmon/Makefile
index 79a784f0e7a9..b20312e5ed27 100644
--- a/arch/powerpc/xmon/Makefile
+++ b/arch/powerpc/xmon/Makefile
@@ -8,4 +8,4 @@ obj-$(CONFIG_8xx) += start_8xx.o
8obj-$(CONFIG_6xx) += start_32.o 8obj-$(CONFIG_6xx) += start_32.o
9obj-$(CONFIG_4xx) += start_32.o 9obj-$(CONFIG_4xx) += start_32.o
10obj-$(CONFIG_PPC64) += start_64.o 10obj-$(CONFIG_PPC64) += start_64.o
11obj-y += xmon.o ppc-dis.o ppc-opc.o subr_prf.o setjmp.o 11obj-y += xmon.o ppc-dis.o ppc-opc.o setjmp.o nonstdio.o
diff --git a/arch/powerpc/xmon/nonstdio.c b/arch/powerpc/xmon/nonstdio.c
new file mode 100644
index 000000000000..78765833f4c0
--- /dev/null
+++ b/arch/powerpc/xmon/nonstdio.c
@@ -0,0 +1,134 @@
1/*
2 * Copyright (C) 1996-2005 Paul Mackerras.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9#include <linux/string.h>
10#include <asm/time.h>
11#include "nonstdio.h"
12
13int xmon_putchar(int c)
14{
15 char ch = c;
16
17 if (c == '\n')
18 xmon_putchar('\r');
19 return xmon_write(&ch, 1) == 1? c: -1;
20}
21
22static char line[256];
23static char *lineptr;
24static int lineleft;
25
26int xmon_expect(const char *str, unsigned long timeout)
27{
28 int c;
29 unsigned long t0;
30
31 /* assume 25MHz default timebase if tb_ticks_per_sec not set yet */
32 timeout *= tb_ticks_per_sec? tb_ticks_per_sec: 25000000;
33 t0 = get_tbl();
34 do {
35 lineptr = line;
36 for (;;) {
37 c = xmon_read_poll();
38 if (c == -1) {
39 if (get_tbl() - t0 > timeout)
40 return 0;
41 continue;
42 }
43 if (c == '\n')
44 break;
45 if (c != '\r' && lineptr < &line[sizeof(line) - 1])
46 *lineptr++ = c;
47 }
48 *lineptr = 0;
49 } while (strstr(line, str) == NULL);
50 return 1;
51}
52
53int xmon_getchar(void)
54{
55 int c;
56
57 if (lineleft == 0) {
58 lineptr = line;
59 for (;;) {
60 c = xmon_readchar();
61 if (c == -1 || c == 4)
62 break;
63 if (c == '\r' || c == '\n') {
64 *lineptr++ = '\n';
65 xmon_putchar('\n');
66 break;
67 }
68 switch (c) {
69 case 0177:
70 case '\b':
71 if (lineptr > line) {
72 xmon_putchar('\b');
73 xmon_putchar(' ');
74 xmon_putchar('\b');
75 --lineptr;
76 }
77 break;
78 case 'U' & 0x1F:
79 while (lineptr > line) {
80 xmon_putchar('\b');
81 xmon_putchar(' ');
82 xmon_putchar('\b');
83 --lineptr;
84 }
85 break;
86 default:
87 if (lineptr >= &line[sizeof(line) - 1])
88 xmon_putchar('\a');
89 else {
90 xmon_putchar(c);
91 *lineptr++ = c;
92 }
93 }
94 }
95 lineleft = lineptr - line;
96 lineptr = line;
97 }
98 if (lineleft == 0)
99 return -1;
100 --lineleft;
101 return *lineptr++;
102}
103
104char *xmon_gets(char *str, int nb)
105{
106 char *p;
107 int c;
108
109 for (p = str; p < str + nb - 1; ) {
110 c = xmon_getchar();
111 if (c == -1) {
112 if (p == str)
113 return NULL;
114 break;
115 }
116 *p++ = c;
117 if (c == '\n')
118 break;
119 }
120 *p = 0;
121 return str;
122}
123
124void xmon_printf(const char *format, ...)
125{
126 va_list args;
127 int n;
128 static char xmon_outbuf[1024];
129
130 va_start(args, format);
131 n = vsnprintf(xmon_outbuf, sizeof(xmon_outbuf), format, args);
132 va_end(args);
133 xmon_write(xmon_outbuf, n);
134}
diff --git a/arch/powerpc/xmon/nonstdio.h b/arch/powerpc/xmon/nonstdio.h
index 84211a21c6f4..47cebbd2b1b1 100644
--- a/arch/powerpc/xmon/nonstdio.h
+++ b/arch/powerpc/xmon/nonstdio.h
@@ -1,22 +1,14 @@
1typedef int FILE;
2extern FILE *xmon_stdin, *xmon_stdout;
3#define EOF (-1) 1#define EOF (-1)
4#define stdin xmon_stdin 2
5#define stdout xmon_stdout
6#define printf xmon_printf 3#define printf xmon_printf
7#define fprintf xmon_fprintf
8#define fputs xmon_fputs
9#define fgets xmon_fgets
10#define putchar xmon_putchar 4#define putchar xmon_putchar
11#define getchar xmon_getchar
12#define putc xmon_putc
13#define getc xmon_getc
14#define fopen(n, m) NULL
15#define fflush(f) do {} while (0)
16#define fclose(f) do {} while (0)
17extern char *fgets(char *, int, void *);
18extern void xmon_printf(const char *, ...);
19extern void xmon_fprintf(void *, const char *, ...);
20extern void xmon_sprintf(char *, const char *, ...);
21 5
22#define perror(s) printf("%s: no files!\n", (s)) 6extern int xmon_putchar(int c);
7extern int xmon_getchar(void);
8extern char *xmon_gets(char *, int);
9extern void xmon_printf(const char *, ...);
10extern void xmon_map_scc(void);
11extern int xmon_expect(const char *str, unsigned long timeout);
12extern int xmon_write(void *ptr, int nb);
13extern int xmon_readchar(void);
14extern int xmon_read_poll(void);
diff --git a/arch/powerpc/xmon/start_32.c b/arch/powerpc/xmon/start_32.c
index 69b658c0f760..c2464df4217e 100644
--- a/arch/powerpc/xmon/start_32.c
+++ b/arch/powerpc/xmon/start_32.c
@@ -11,7 +11,6 @@
11#include <linux/cuda.h> 11#include <linux/cuda.h>
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/errno.h> 13#include <linux/errno.h>
14#include <linux/sysrq.h>
15#include <linux/bitops.h> 14#include <linux/bitops.h>
16#include <asm/xmon.h> 15#include <asm/xmon.h>
17#include <asm/prom.h> 16#include <asm/prom.h>
@@ -22,10 +21,11 @@
22#include <asm/processor.h> 21#include <asm/processor.h>
23#include <asm/delay.h> 22#include <asm/delay.h>
24#include <asm/btext.h> 23#include <asm/btext.h>
24#include <asm/time.h>
25#include "nonstdio.h"
25 26
26static volatile unsigned char __iomem *sccc, *sccd; 27static volatile unsigned char __iomem *sccc, *sccd;
27unsigned int TXRDY, RXRDY, DLAB; 28unsigned int TXRDY, RXRDY, DLAB;
28static int xmon_expect(const char *str, unsigned int timeout);
29 29
30static int use_serial; 30static int use_serial;
31static int use_screen; 31static int use_screen;
@@ -33,16 +33,6 @@ static int via_modem;
33static int xmon_use_sccb; 33static int xmon_use_sccb;
34static struct device_node *channel_node; 34static struct device_node *channel_node;
35 35
36#define TB_SPEED 25000000
37
38static inline unsigned int readtb(void)
39{
40 unsigned int ret;
41
42 asm volatile("mftb %0" : "=r" (ret) :);
43 return ret;
44}
45
46void buf_access(void) 36void buf_access(void)
47{ 37{
48 if (DLAB) 38 if (DLAB)
@@ -91,23 +81,7 @@ static unsigned long chrp_find_phys_io_base(void)
91} 81}
92#endif /* CONFIG_PPC_CHRP */ 82#endif /* CONFIG_PPC_CHRP */
93 83
94#ifdef CONFIG_MAGIC_SYSRQ 84void xmon_map_scc(void)
95static void sysrq_handle_xmon(int key, struct pt_regs *regs,
96 struct tty_struct *tty)
97{
98 xmon(regs);
99}
100
101static struct sysrq_key_op sysrq_xmon_op =
102{
103 .handler = sysrq_handle_xmon,
104 .help_msg = "Xmon",
105 .action_msg = "Entering xmon",
106};
107#endif
108
109void
110xmon_map_scc(void)
111{ 85{
112#ifdef CONFIG_PPC_MULTIPLATFORM 86#ifdef CONFIG_PPC_MULTIPLATFORM
113 volatile unsigned char __iomem *base; 87 volatile unsigned char __iomem *base;
@@ -217,8 +191,6 @@ xmon_map_scc(void)
217 RXRDY = 1; 191 RXRDY = 1;
218 DLAB = 0x80; 192 DLAB = 0x80;
219#endif /* platform */ 193#endif /* platform */
220
221 register_sysrq_key('x', &sysrq_xmon_op);
222} 194}
223 195
224static int scc_initialized = 0; 196static int scc_initialized = 0;
@@ -238,8 +210,7 @@ static inline void do_poll_adb(void)
238#endif /* CONFIG_ADB_CUDA */ 210#endif /* CONFIG_ADB_CUDA */
239} 211}
240 212
241int 213int xmon_write(void *ptr, int nb)
242xmon_write(void *handle, void *ptr, int nb)
243{ 214{
244 char *p = ptr; 215 char *p = ptr;
245 int i, c, ct; 216 int i, c, ct;
@@ -311,8 +282,7 @@ static unsigned char xmon_shift_keytab[128] =
311 "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */ 282 "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
312 "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */ 283 "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
313 284
314static int 285static int xmon_get_adb_key(void)
315xmon_get_adb_key(void)
316{ 286{
317 int k, t, on; 287 int k, t, on;
318 288
@@ -350,32 +320,21 @@ xmon_get_adb_key(void)
350} 320}
351#endif /* CONFIG_BOOTX_TEXT */ 321#endif /* CONFIG_BOOTX_TEXT */
352 322
353int 323int xmon_readchar(void)
354xmon_read(void *handle, void *ptr, int nb)
355{ 324{
356 char *p = ptr;
357 int i;
358
359#ifdef CONFIG_BOOTX_TEXT 325#ifdef CONFIG_BOOTX_TEXT
360 if (use_screen) { 326 if (use_screen)
361 for (i = 0; i < nb; ++i) 327 return xmon_get_adb_key();
362 *p++ = xmon_get_adb_key();
363 return i;
364 }
365#endif 328#endif
366 if (!scc_initialized) 329 if (!scc_initialized)
367 xmon_init_scc(); 330 xmon_init_scc();
368 for (i = 0; i < nb; ++i) {
369 while ((*sccc & RXRDY) == 0) 331 while ((*sccc & RXRDY) == 0)
370 do_poll_adb(); 332 do_poll_adb();
371 buf_access(); 333 buf_access();
372 *p++ = *sccd; 334 return *sccd;
373 }
374 return i;
375} 335}
376 336
377int 337int xmon_read_poll(void)
378xmon_read_poll(void)
379{ 338{
380 if ((*sccc & RXRDY) == 0) { 339 if ((*sccc & RXRDY) == 0) {
381 do_poll_adb(); 340 do_poll_adb();
@@ -395,8 +354,7 @@ static unsigned char scc_inittab[] = {
395 3, 0xc1, /* rx enable, 8 bits */ 354 3, 0xc1, /* rx enable, 8 bits */
396}; 355};
397 356
398void 357void xmon_init_scc(void)
399xmon_init_scc(void)
400{ 358{
401 if ( _machine == _MACH_chrp ) 359 if ( _machine == _MACH_chrp )
402 { 360 {
@@ -410,6 +368,7 @@ xmon_init_scc(void)
410 else if ( _machine == _MACH_Pmac ) 368 else if ( _machine == _MACH_Pmac )
411 { 369 {
412 int i, x; 370 int i, x;
371 unsigned long timeout;
413 372
414 if (channel_node != 0) 373 if (channel_node != 0)
415 pmac_call_feature( 374 pmac_call_feature(
@@ -424,8 +383,12 @@ xmon_init_scc(void)
424 PMAC_FTR_MODEM_ENABLE, 383 PMAC_FTR_MODEM_ENABLE,
425 channel_node, 0, 1); 384 channel_node, 0, 1);
426 printk(KERN_INFO "Modem powered up by debugger !\n"); 385 printk(KERN_INFO "Modem powered up by debugger !\n");
427 t0 = readtb(); 386 t0 = get_tbl();
428 while (readtb() - t0 < 3*TB_SPEED) 387 timeout = 3 * tb_ticks_per_sec;
388 if (timeout == 0)
389 /* assume 25MHz if tb_ticks_per_sec not set */
390 timeout = 75000000;
391 while (get_tbl() - t0 < timeout)
429 eieio(); 392 eieio();
430 } 393 }
431 /* use the B channel if requested */ 394 /* use the B channel if requested */
@@ -447,164 +410,19 @@ xmon_init_scc(void)
447 scc_initialized = 1; 410 scc_initialized = 1;
448 if (via_modem) { 411 if (via_modem) {
449 for (;;) { 412 for (;;) {
450 xmon_write(NULL, "ATE1V1\r", 7); 413 xmon_write("ATE1V1\r", 7);
451 if (xmon_expect("OK", 5)) { 414 if (xmon_expect("OK", 5)) {
452 xmon_write(NULL, "ATA\r", 4); 415 xmon_write("ATA\r", 4);
453 if (xmon_expect("CONNECT", 40)) 416 if (xmon_expect("CONNECT", 40))
454 break; 417 break;
455 } 418 }
456 xmon_write(NULL, "+++", 3); 419 xmon_write("+++", 3);
457 xmon_expect("OK", 3); 420 xmon_expect("OK", 3);
458 } 421 }
459 } 422 }
460} 423}
461 424
462void *xmon_stdin; 425void xmon_enter(void)
463void *xmon_stdout;
464void *xmon_stderr;
465
466int xmon_putc(int c, void *f)
467{
468 char ch = c;
469
470 if (c == '\n')
471 xmon_putc('\r', f);
472 return xmon_write(f, &ch, 1) == 1? c: -1;
473}
474
475int xmon_putchar(int c)
476{
477 return xmon_putc(c, xmon_stdout);
478}
479
480int xmon_fputs(char *str, void *f)
481{
482 int n = strlen(str);
483
484 return xmon_write(f, str, n) == n? 0: -1;
485}
486
487int
488xmon_readchar(void)
489{
490 char ch;
491
492 for (;;) {
493 switch (xmon_read(xmon_stdin, &ch, 1)) {
494 case 1:
495 return ch;
496 case -1:
497 xmon_printf("read(stdin) returned -1\r\n", 0, 0);
498 return -1;
499 }
500 }
501}
502
503static char line[256];
504static char *lineptr;
505static int lineleft;
506
507int xmon_expect(const char *str, unsigned int timeout)
508{
509 int c;
510 unsigned int t0;
511
512 timeout *= TB_SPEED;
513 t0 = readtb();
514 do {
515 lineptr = line;
516 for (;;) {
517 c = xmon_read_poll();
518 if (c == -1) {
519 if (readtb() - t0 > timeout)
520 return 0;
521 continue;
522 }
523 if (c == '\n')
524 break;
525 if (c != '\r' && lineptr < &line[sizeof(line) - 1])
526 *lineptr++ = c;
527 }
528 *lineptr = 0;
529 } while (strstr(line, str) == NULL);
530 return 1;
531}
532
533int
534xmon_getchar(void)
535{
536 int c;
537
538 if (lineleft == 0) {
539 lineptr = line;
540 for (;;) {
541 c = xmon_readchar();
542 if (c == -1 || c == 4)
543 break;
544 if (c == '\r' || c == '\n') {
545 *lineptr++ = '\n';
546 xmon_putchar('\n');
547 break;
548 }
549 switch (c) {
550 case 0177:
551 case '\b':
552 if (lineptr > line) {
553 xmon_putchar('\b');
554 xmon_putchar(' ');
555 xmon_putchar('\b');
556 --lineptr;
557 }
558 break;
559 case 'U' & 0x1F:
560 while (lineptr > line) {
561 xmon_putchar('\b');
562 xmon_putchar(' ');
563 xmon_putchar('\b');
564 --lineptr;
565 }
566 break;
567 default:
568 if (lineptr >= &line[sizeof(line) - 1])
569 xmon_putchar('\a');
570 else {
571 xmon_putchar(c);
572 *lineptr++ = c;
573 }
574 }
575 }
576 lineleft = lineptr - line;
577 lineptr = line;
578 }
579 if (lineleft == 0)
580 return -1;
581 --lineleft;
582 return *lineptr++;
583}
584
585char *
586xmon_fgets(char *str, int nb, void *f)
587{
588 char *p;
589 int c;
590
591 for (p = str; p < str + nb - 1; ) {
592 c = xmon_getchar();
593 if (c == -1) {
594 if (p == str)
595 return NULL;
596 break;
597 }
598 *p++ = c;
599 if (c == '\n')
600 break;
601 }
602 *p = 0;
603 return str;
604}
605
606void
607xmon_enter(void)
608{ 426{
609#ifdef CONFIG_ADB_PMU 427#ifdef CONFIG_ADB_PMU
610 if (_machine == _MACH_Pmac) { 428 if (_machine == _MACH_Pmac) {
@@ -613,8 +431,7 @@ xmon_enter(void)
613#endif 431#endif
614} 432}
615 433
616void 434void xmon_leave(void)
617xmon_leave(void)
618{ 435{
619#ifdef CONFIG_ADB_PMU 436#ifdef CONFIG_ADB_PMU
620 if (_machine == _MACH_Pmac) { 437 if (_machine == _MACH_Pmac) {
diff --git a/arch/powerpc/xmon/start_64.c b/arch/powerpc/xmon/start_64.c
index e50c158191e1..712552c4f242 100644
--- a/arch/powerpc/xmon/start_64.c
+++ b/arch/powerpc/xmon/start_64.c
@@ -6,182 +6,29 @@
6 * as published by the Free Software Foundation; either version 6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version. 7 * 2 of the License, or (at your option) any later version.
8 */ 8 */
9#include <linux/config.h>
10#include <linux/string.h>
11#include <linux/kernel.h>
12#include <linux/errno.h>
13#include <linux/sysrq.h>
14#include <linux/init.h>
15#include <asm/machdep.h> 9#include <asm/machdep.h>
16#include <asm/io.h>
17#include <asm/page.h>
18#include <asm/prom.h>
19#include <asm/processor.h>
20#include <asm/udbg.h> 10#include <asm/udbg.h>
21#include <asm/system.h>
22#include "nonstdio.h" 11#include "nonstdio.h"
23 12
24#ifdef CONFIG_MAGIC_SYSRQ 13void xmon_map_scc(void)
25
26static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs,
27 struct tty_struct *tty)
28{
29 /* ensure xmon is enabled */
30 xmon_init(1);
31 debugger(pt_regs);
32}
33
34static struct sysrq_key_op sysrq_xmon_op =
35{ 14{
36 .handler = sysrq_handle_xmon,
37 .help_msg = "Xmon",
38 .action_msg = "Entering xmon",
39};
40
41static int __init setup_xmon_sysrq(void)
42{
43 register_sysrq_key('x', &sysrq_xmon_op);
44 return 0;
45} 15}
46__initcall(setup_xmon_sysrq);
47#endif /* CONFIG_MAGIC_SYSRQ */
48 16
49int 17int xmon_write(void *ptr, int nb)
50xmon_write(void *handle, void *ptr, int nb)
51{ 18{
52 return udbg_write(ptr, nb); 19 return udbg_write(ptr, nb);
53} 20}
54 21
55int 22int xmon_readchar(void)
56xmon_read(void *handle, void *ptr, int nb)
57{ 23{
58 return udbg_read(ptr, nb); 24 if (udbg_getc)
25 return udbg_getc();
26 return -1;
59} 27}
60 28
61int 29int xmon_read_poll(void)
62xmon_read_poll(void)
63{ 30{
64 if (udbg_getc_poll) 31 if (udbg_getc_poll)
65 return udbg_getc_poll(); 32 return udbg_getc_poll();
66 return -1; 33 return -1;
67} 34}
68
69FILE *xmon_stdin;
70FILE *xmon_stdout;
71
72int
73xmon_putc(int c, void *f)
74{
75 char ch = c;
76
77 if (c == '\n')
78 xmon_putc('\r', f);
79 return xmon_write(f, &ch, 1) == 1? c: -1;
80}
81
82int
83xmon_putchar(int c)
84{
85 return xmon_putc(c, xmon_stdout);
86}
87
88int
89xmon_fputs(char *str, void *f)
90{
91 int n = strlen(str);
92
93 return xmon_write(f, str, n) == n? 0: -1;
94}
95
96int
97xmon_readchar(void)
98{
99 char ch;
100
101 for (;;) {
102 switch (xmon_read(xmon_stdin, &ch, 1)) {
103 case 1:
104 return ch;
105 case -1:
106 xmon_printf("read(stdin) returned -1\r\n", 0, 0);
107 return -1;
108 }
109 }
110}
111
112static char line[256];
113static char *lineptr;
114static int lineleft;
115
116int
117xmon_getchar(void)
118{
119 int c;
120
121 if (lineleft == 0) {
122 lineptr = line;
123 for (;;) {
124 c = xmon_readchar();
125 if (c == -1 || c == 4)
126 break;
127 if (c == '\r' || c == '\n') {
128 *lineptr++ = '\n';
129 xmon_putchar('\n');
130 break;
131 }
132 switch (c) {
133 case 0177:
134 case '\b':
135 if (lineptr > line) {
136 xmon_putchar('\b');
137 xmon_putchar(' ');
138 xmon_putchar('\b');
139 --lineptr;
140 }
141 break;
142 case 'U' & 0x1F:
143 while (lineptr > line) {
144 xmon_putchar('\b');
145 xmon_putchar(' ');
146 xmon_putchar('\b');
147 --lineptr;
148 }
149 break;
150 default:
151 if (lineptr >= &line[sizeof(line) - 1])
152 xmon_putchar('\a');
153 else {
154 xmon_putchar(c);
155 *lineptr++ = c;
156 }
157 }
158 }
159 lineleft = lineptr - line;
160 lineptr = line;
161 }
162 if (lineleft == 0)
163 return -1;
164 --lineleft;
165 return *lineptr++;
166}
167
168char *
169xmon_fgets(char *str, int nb, void *f)
170{
171 char *p;
172 int c;
173
174 for (p = str; p < str + nb - 1; ) {
175 c = xmon_getchar();
176 if (c == -1) {
177 if (p == str)
178 return NULL;
179 break;
180 }
181 *p++ = c;
182 if (c == '\n')
183 break;
184 }
185 *p = 0;
186 return str;
187}
diff --git a/arch/powerpc/xmon/start_8xx.c b/arch/powerpc/xmon/start_8xx.c
index a48bd594cf61..4c17b0486ad5 100644
--- a/arch/powerpc/xmon/start_8xx.c
+++ b/arch/powerpc/xmon/start_8xx.c
@@ -15,273 +15,30 @@
15#include <asm/8xx_immap.h> 15#include <asm/8xx_immap.h>
16#include <asm/mpc8xx.h> 16#include <asm/mpc8xx.h>
17#include <asm/commproc.h> 17#include <asm/commproc.h>
18#include "nonstdio.h"
18 19
19extern void xmon_printf(const char *fmt, ...);
20extern int xmon_8xx_write(char *str, int nb); 20extern int xmon_8xx_write(char *str, int nb);
21extern int xmon_8xx_read_poll(void); 21extern int xmon_8xx_read_poll(void);
22extern int xmon_8xx_read_char(void); 22extern int xmon_8xx_read_char(void);
23void prom_drawhex(uint);
24void prom_drawstring(const char *str);
25 23
26static int use_screen = 1; /* default */ 24void xmon_map_scc(void)
27
28#define TB_SPEED 25000000
29
30static inline unsigned int readtb(void)
31{
32 unsigned int ret;
33
34 asm volatile("mftb %0" : "=r" (ret) :);
35 return ret;
36}
37
38void buf_access(void)
39{
40}
41
42void
43xmon_map_scc(void)
44{ 25{
45
46 cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm); 26 cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm);
47 use_screen = 0;
48
49 prom_drawstring("xmon uses serial port\n");
50} 27}
51 28
52static int scc_initialized = 0;
53
54void xmon_init_scc(void); 29void xmon_init_scc(void);
55 30
56int 31int xmon_write(void *ptr, int nb)
57xmon_write(void *handle, void *ptr, int nb)
58{ 32{
59 char *p = ptr;
60 int i, c, ct;
61
62 if (!scc_initialized)
63 xmon_init_scc();
64
65 return(xmon_8xx_write(ptr, nb)); 33 return(xmon_8xx_write(ptr, nb));
66} 34}
67 35
68int xmon_wants_key; 36int xmon_readchar(void)
69
70int
71xmon_read(void *handle, void *ptr, int nb)
72{ 37{
73 char *p = ptr; 38 return xmon_8xx_read_char();
74 int i;
75
76 if (!scc_initialized)
77 xmon_init_scc();
78
79 for (i = 0; i < nb; ++i) {
80 *p++ = xmon_8xx_read_char();
81 }
82 return i;
83} 39}
84 40
85int 41int xmon_read_poll(void)
86xmon_read_poll(void)
87{ 42{
88 return(xmon_8xx_read_poll()); 43 return(xmon_8xx_read_poll());
89} 44}
90
91void
92xmon_init_scc()
93{
94 scc_initialized = 1;
95}
96
97#if 0
98extern int (*prom_entry)(void *);
99
100int
101xmon_exit(void)
102{
103 struct prom_args {
104 char *service;
105 } args;
106
107 for (;;) {
108 args.service = "exit";
109 (*prom_entry)(&args);
110 }
111}
112#endif
113
114void *xmon_stdin;
115void *xmon_stdout;
116void *xmon_stderr;
117
118void
119xmon_init(void)
120{
121}
122
123int
124xmon_putc(int c, void *f)
125{
126 char ch = c;
127
128 if (c == '\n')
129 xmon_putc('\r', f);
130 return xmon_write(f, &ch, 1) == 1? c: -1;
131}
132
133int
134xmon_putchar(int c)
135{
136 return xmon_putc(c, xmon_stdout);
137}
138
139int
140xmon_fputs(char *str, void *f)
141{
142 int n = strlen(str);
143
144 return xmon_write(f, str, n) == n? 0: -1;
145}
146
147int
148xmon_readchar(void)
149{
150 char ch;
151
152 for (;;) {
153 switch (xmon_read(xmon_stdin, &ch, 1)) {
154 case 1:
155 return ch;
156 case -1:
157 xmon_printf("read(stdin) returned -1\r\n", 0, 0);
158 return -1;
159 }
160 }
161}
162
163static char line[256];
164static char *lineptr;
165static int lineleft;
166
167#if 0
168int xmon_expect(const char *str, unsigned int timeout)
169{
170 int c;
171 unsigned int t0;
172
173 timeout *= TB_SPEED;
174 t0 = readtb();
175 do {
176 lineptr = line;
177 for (;;) {
178 c = xmon_read_poll();
179 if (c == -1) {
180 if (readtb() - t0 > timeout)
181 return 0;
182 continue;
183 }
184 if (c == '\n')
185 break;
186 if (c != '\r' && lineptr < &line[sizeof(line) - 1])
187 *lineptr++ = c;
188 }
189 *lineptr = 0;
190 } while (strstr(line, str) == NULL);
191 return 1;
192}
193#endif
194
195int
196xmon_getchar(void)
197{
198 int c;
199
200 if (lineleft == 0) {
201 lineptr = line;
202 for (;;) {
203 c = xmon_readchar();
204 if (c == -1 || c == 4)
205 break;
206 if (c == '\r' || c == '\n') {
207 *lineptr++ = '\n';
208 xmon_putchar('\n');
209 break;
210 }
211 switch (c) {
212 case 0177:
213 case '\b':
214 if (lineptr > line) {
215 xmon_putchar('\b');
216 xmon_putchar(' ');
217 xmon_putchar('\b');
218 --lineptr;
219 }
220 break;
221 case 'U' & 0x1F:
222 while (lineptr > line) {
223 xmon_putchar('\b');
224 xmon_putchar(' ');
225 xmon_putchar('\b');
226 --lineptr;
227 }
228 break;
229 default:
230 if (lineptr >= &line[sizeof(line) - 1])
231 xmon_putchar('\a');
232 else {
233 xmon_putchar(c);
234 *lineptr++ = c;
235 }
236 }
237 }
238 lineleft = lineptr - line;
239 lineptr = line;
240 }
241 if (lineleft == 0)
242 return -1;
243 --lineleft;
244 return *lineptr++;
245}
246
247char *
248xmon_fgets(char *str, int nb, void *f)
249{
250 char *p;
251 int c;
252
253 for (p = str; p < str + nb - 1; ) {
254 c = xmon_getchar();
255 if (c == -1) {
256 if (p == str)
257 return 0;
258 break;
259 }
260 *p++ = c;
261 if (c == '\n')
262 break;
263 }
264 *p = 0;
265 return str;
266}
267
268void
269prom_drawhex(uint val)
270{
271 unsigned char buf[10];
272
273 int i;
274 for (i = 7; i >= 0; i--)
275 {
276 buf[i] = "0123456789abcdef"[val & 0x0f];
277 val >>= 4;
278 }
279 buf[8] = '\0';
280 xmon_fputs(buf, xmon_stdout);
281}
282
283void
284prom_drawstring(const char *str)
285{
286 xmon_fputs(str, xmon_stdout);
287}
diff --git a/arch/powerpc/xmon/subr_prf.c b/arch/powerpc/xmon/subr_prf.c
deleted file mode 100644
index b48738c6dd33..000000000000
--- a/arch/powerpc/xmon/subr_prf.c
+++ /dev/null
@@ -1,54 +0,0 @@
1/*
2 * Written by Cort Dougan to replace the version originally used
3 * by Paul Mackerras, which came from NetBSD and thus had copyright
4 * conflicts with Linux.
5 *
6 * This file makes liberal use of the standard linux utility
7 * routines to reduce the size of the binary. We assume we can
8 * trust some parts of Linux inside the debugger.
9 * -- Cort (cort@cs.nmt.edu)
10 *
11 * Copyright (C) 1999 Cort Dougan.
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version
16 * 2 of the License, or (at your option) any later version.
17 */
18
19#include <linux/kernel.h>
20#include <linux/string.h>
21#include <linux/module.h>
22#include <stdarg.h>
23#include "nonstdio.h"
24
25extern int xmon_write(void *, void *, int);
26
27void xmon_vfprintf(void *f, const char *fmt, va_list ap)
28{
29 static char xmon_buf[2048];
30 int n;
31
32 n = vsprintf(xmon_buf, fmt, ap);
33 xmon_write(f, xmon_buf, n);
34}
35
36void xmon_printf(const char *fmt, ...)
37{
38 va_list ap;
39
40 va_start(ap, fmt);
41 xmon_vfprintf(stdout, fmt, ap);
42 va_end(ap);
43}
44EXPORT_SYMBOL(xmon_printf);
45
46void xmon_fprintf(void *f, const char *fmt, ...)
47{
48 va_list ap;
49
50 va_start(ap, fmt);
51 xmon_vfprintf(f, fmt, ap);
52 va_end(ap);
53}
54
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 1124f1146202..b43a57425ea9 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Routines providing a simple monitor for use on the PowerMac. 2 * Routines providing a simple monitor for use on the PowerMac.
3 * 3 *
4 * Copyright (C) 1996 Paul Mackerras. 4 * Copyright (C) 1996-2005 Paul Mackerras.
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License 7 * modify it under the terms of the GNU General Public License
@@ -18,6 +18,7 @@
18#include <linux/kallsyms.h> 18#include <linux/kallsyms.h>
19#include <linux/cpumask.h> 19#include <linux/cpumask.h>
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/sysrq.h>
21 22
22#include <asm/ptrace.h> 23#include <asm/ptrace.h>
23#include <asm/string.h> 24#include <asm/string.h>
@@ -144,15 +145,10 @@ static void xmon_print_symbol(unsigned long address, const char *mid,
144static const char *getvecname(unsigned long vec); 145static const char *getvecname(unsigned long vec);
145 146
146extern int print_insn_powerpc(unsigned long, unsigned long, int); 147extern int print_insn_powerpc(unsigned long, unsigned long, int);
147extern void printf(const char *fmt, ...);
148extern void xmon_vfprintf(void *f, const char *fmt, va_list ap);
149extern int xmon_putc(int c, void *f);
150extern int putchar(int ch);
151 148
152extern void xmon_enter(void); 149extern void xmon_enter(void);
153extern void xmon_leave(void); 150extern void xmon_leave(void);
154 151
155extern int xmon_read_poll(void);
156extern long setjmp(long *); 152extern long setjmp(long *);
157extern void longjmp(long *, long); 153extern void longjmp(long *, long);
158extern void xmon_save_regs(struct pt_regs *); 154extern void xmon_save_regs(struct pt_regs *);
@@ -748,7 +744,6 @@ cmds(struct pt_regs *excp)
748 printf("%x:", smp_processor_id()); 744 printf("%x:", smp_processor_id());
749#endif /* CONFIG_SMP */ 745#endif /* CONFIG_SMP */
750 printf("mon> "); 746 printf("mon> ");
751 fflush(stdout);
752 flush_input(); 747 flush_input();
753 termch = 0; 748 termch = 0;
754 cmd = skipbl(); 749 cmd = skipbl();
@@ -2151,7 +2146,6 @@ memzcan(void)
2151 ok = mread(a, &v, 1); 2146 ok = mread(a, &v, 1);
2152 if (ok && !ook) { 2147 if (ok && !ook) {
2153 printf("%.8x .. ", a); 2148 printf("%.8x .. ", a);
2154 fflush(stdout);
2155 } else if (!ok && ook) 2149 } else if (!ok && ook)
2156 printf("%.8x\n", a - mskip); 2150 printf("%.8x\n", a - mskip);
2157 ook = ok; 2151 ook = ok;
@@ -2372,7 +2366,7 @@ int
2372inchar(void) 2366inchar(void)
2373{ 2367{
2374 if (lineptr == NULL || *lineptr == 0) { 2368 if (lineptr == NULL || *lineptr == 0) {
2375 if (fgets(line, sizeof(line), stdin) == NULL) { 2369 if (xmon_gets(line, sizeof(line)) == NULL) {
2376 lineptr = NULL; 2370 lineptr = NULL;
2377 return EOF; 2371 return EOF;
2378 } 2372 }
@@ -2526,4 +2520,29 @@ void xmon_init(int enable)
2526 __debugger_dabr_match = NULL; 2520 __debugger_dabr_match = NULL;
2527 __debugger_fault_handler = NULL; 2521 __debugger_fault_handler = NULL;
2528 } 2522 }
2523 xmon_map_scc();
2529} 2524}
2525
2526#ifdef CONFIG_MAGIC_SYSRQ
2527static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs,
2528 struct tty_struct *tty)
2529{
2530 /* ensure xmon is enabled */
2531 xmon_init(1);
2532 debugger(pt_regs);
2533}
2534
2535static struct sysrq_key_op sysrq_xmon_op =
2536{
2537 .handler = sysrq_handle_xmon,
2538 .help_msg = "Xmon",
2539 .action_msg = "Entering xmon",
2540};
2541
2542static int __init setup_xmon_sysrq(void)
2543{
2544 register_sysrq_key('x', &sysrq_xmon_op);
2545 return 0;
2546}
2547__initcall(setup_xmon_sysrq);
2548#endif /* CONFIG_MAGIC_SYSRQ */
diff --git a/include/asm-powerpc/xmon.h b/include/asm-powerpc/xmon.h
index ace2072d4a83..43f7129984c7 100644
--- a/include/asm-powerpc/xmon.h
+++ b/include/asm-powerpc/xmon.h
@@ -7,7 +7,6 @@ struct pt_regs;
7extern int xmon(struct pt_regs *excp); 7extern int xmon(struct pt_regs *excp);
8extern void xmon_printf(const char *fmt, ...); 8extern void xmon_printf(const char *fmt, ...);
9extern void xmon_init(int); 9extern void xmon_init(int);
10extern void xmon_map_scc(void);
11 10
12#endif 11#endif
13#endif 12#endif