2 * Copyright (C) 1996 Paul Mackerras.
4 #include <linux/config.h>
5 #include <linux/string.h>
6 #include <asm/machdep.h>
10 #include <linux/pmu.h>
11 #include <linux/cuda.h>
12 #include <linux/kernel.h>
13 #include <linux/errno.h>
14 #include <linux/sysrq.h>
15 #include <linux/bitops.h>
18 #include <asm/bootx.h>
19 #include <asm/machdep.h>
20 #include <asm/errno.h>
21 #include <asm/pmac_feature.h>
22 #include <asm/processor.h>
23 #include <asm/delay.h>
24 #include <asm/btext.h>
26 static volatile unsigned char __iomem
*sccc
, *sccd
;
27 unsigned int TXRDY
, RXRDY
, DLAB
;
28 static int xmon_expect(const char *str
, unsigned int timeout
);
30 static int use_serial
;
31 static int use_screen
;
33 static int xmon_use_sccb
;
34 static struct device_node
*channel_node
;
36 #define TB_SPEED 25000000
38 static inline unsigned int readtb(void)
42 asm volatile("mftb %0" : "=r" (ret
) :);
49 sccd
[3] &= ~DLAB
; /* reset DLAB */
52 extern int adb_init(void);
54 #ifdef CONFIG_PPC_CHRP
56 * This looks in the "ranges" property for the primary PCI host bridge
57 * to find the physical address of the start of PCI/ISA I/O space.
58 * It is basically a cut-down version of pci_process_bridge_OF_ranges.
60 static unsigned long chrp_find_phys_io_base(void)
62 struct device_node
*node
;
64 unsigned long base
= CHRP_ISA_IO_BASE
;
68 node
= find_devices("isa");
71 if (node
== NULL
|| node
->type
== NULL
72 || strcmp(node
->type
, "pci") != 0)
76 node
= find_devices("pci");
80 ranges
= (unsigned int *) get_property(node
, "ranges", &rlen
);
81 np
= prom_n_addr_cells(node
) + 5;
82 while ((rlen
-= np
* sizeof(unsigned int)) >= 0) {
83 if ((ranges
[0] >> 24) == 1 && ranges
[2] == 0) {
84 /* I/O space starting at 0, grab the phys base */
85 base
= ranges
[np
- 3];
92 #endif /* CONFIG_PPC_CHRP */
94 #ifdef CONFIG_MAGIC_SYSRQ
95 static void sysrq_handle_xmon(int key
, struct pt_regs
*regs
,
96 struct tty_struct
*tty
)
101 static struct sysrq_key_op sysrq_xmon_op
=
103 .handler
= sysrq_handle_xmon
,
105 .action_msg
= "Entering xmon",
112 #ifdef CONFIG_PPC_MULTIPLATFORM
113 volatile unsigned char __iomem
*base
;
115 if (_machine
== _MACH_Pmac
) {
116 struct device_node
*np
;
118 #ifdef CONFIG_BOOTX_TEXT
119 if (!use_screen
&& !use_serial
120 && !machine_is_compatible("iMac")) {
121 /* see if there is a keyboard in the device tree
122 with a parent of type "adb" */
123 for (np
= find_devices("keyboard"); np
; np
= np
->next
)
124 if (np
->parent
&& np
->parent
->type
125 && strcmp(np
->parent
->type
, "adb") == 0)
128 /* needs to be hacked if xmon_printk is to be used
129 from within find_via_pmu() */
130 #ifdef CONFIG_ADB_PMU
131 if (np
!= NULL
&& boot_text_mapped
&& find_via_pmu())
134 #ifdef CONFIG_ADB_CUDA
135 if (np
!= NULL
&& boot_text_mapped
&& find_via_cuda())
139 if (!use_screen
&& (np
= find_devices("escc")) != NULL
) {
141 * look for the device node for the serial port
142 * we're using and see if it says it has a modem
144 char *name
= xmon_use_sccb
? "ch-b": "ch-a";
149 while (np
!= NULL
&& strcmp(np
->name
, name
) != 0)
152 /* XXX should parse this properly */
154 slots
= get_property(np
, "slot-names", &l
);
155 if (slots
!= NULL
&& l
>= 10
156 && strcmp(slots
+4, "Modem") == 0)
160 btext_drawstring("xmon uses ");
162 btext_drawstring("screen and keyboard\n");
165 btext_drawstring("modem on ");
166 btext_drawstring(xmon_use_sccb
? "printer": "modem");
167 btext_drawstring(" port\n");
170 #endif /* CONFIG_BOOTX_TEXT */
180 np
= find_devices("mac-io");
181 if (np
&& np
->n_addrs
)
182 addr
= np
->addrs
[0].address
+ 0x13020;
183 base
= (volatile unsigned char *) ioremap(addr
& PAGE_MASK
, PAGE_SIZE
);
184 sccc
= base
+ (addr
& ~PAGE_MASK
);
188 base
= (volatile unsigned char *) isa_io_base
;
190 #ifdef CONFIG_PPC_CHRP
191 if (_machine
== _MACH_chrp
)
192 base
= (volatile unsigned char __iomem
*)
193 ioremap(chrp_find_phys_io_base(), 0x1000);
206 #elif defined(CONFIG_GEMINI)
207 /* should already be mapped by the kernel boot */
208 sccc
= (volatile unsigned char __iomem
*) 0xffeffb0d;
209 sccd
= (volatile unsigned char __iomem
*) 0xffeffb08;
213 #elif defined(CONFIG_405GP)
214 sccc
= (volatile unsigned char __iomem
*)0xef600305;
215 sccd
= (volatile unsigned char __iomem
*)0xef600300;
219 #endif /* platform */
221 register_sysrq_key('x', &sysrq_xmon_op
);
224 static int scc_initialized
= 0;
226 void xmon_init_scc(void);
227 extern void cuda_poll(void);
229 static inline void do_poll_adb(void)
231 #ifdef CONFIG_ADB_PMU
232 if (sys_ctrler
== SYS_CTRLER_PMU
)
234 #endif /* CONFIG_ADB_PMU */
235 #ifdef CONFIG_ADB_CUDA
236 if (sys_ctrler
== SYS_CTRLER_CUDA
)
238 #endif /* CONFIG_ADB_CUDA */
242 xmon_write(void *handle
, void *ptr
, int nb
)
248 static unsigned long xmon_write_lock
;
249 int lock_wait
= 1000000;
252 while ((locked
= test_and_set_bit(0, &xmon_write_lock
)) != 0)
253 if (--lock_wait
== 0)
257 #ifdef CONFIG_BOOTX_TEXT
259 /* write it on the screen */
260 for (i
= 0; i
< nb
; ++i
)
261 btext_drawchar(*p
++);
265 if (!scc_initialized
)
268 for (i
= 0; i
< nb
; ++i
) {
269 while ((*sccc
& TXRDY
) == 0)
272 if (c
== '\n' && !ct
) {
287 clear_bit(0, &xmon_write_lock
);
293 int xmon_adb_keycode
;
295 #ifdef CONFIG_BOOTX_TEXT
296 static int xmon_adb_shiftstate
;
298 static unsigned char xmon_keytab
[128] =
299 "asdfhgzxcv\000bqwer" /* 0x00 - 0x0f */
300 "yt123465=97-80]o" /* 0x10 - 0x1f */
301 "u[ip\rlj'k;\\,/nm." /* 0x20 - 0x2f */
302 "\t `\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */
303 "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
304 "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
306 static unsigned char xmon_shift_keytab
[128] =
307 "ASDFHGZXCV\000BQWER" /* 0x00 - 0x0f */
308 "YT!@#$^%+(&_*)}O" /* 0x10 - 0x1f */
309 "U{IP\rLJ\"K:|<?NM>" /* 0x20 - 0x2f */
310 "\t ~\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */
311 "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
312 "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
315 xmon_get_adb_key(void)
321 xmon_adb_keycode
= -1;
327 btext_drawchar(on
? 0xdb: 0x20);
328 btext_drawchar('\b');
332 } while (xmon_adb_keycode
== -1);
333 k
= xmon_adb_keycode
;
335 btext_drawstring(" \b");
337 /* test for shift keys */
338 if ((k
& 0x7f) == 0x38 || (k
& 0x7f) == 0x7b) {
339 xmon_adb_shiftstate
= (k
& 0x80) == 0;
343 continue; /* ignore up transitions */
344 k
= (xmon_adb_shiftstate
? xmon_shift_keytab
: xmon_keytab
)[k
];
351 #endif /* CONFIG_BOOTX_TEXT */
354 xmon_read(void *handle
, void *ptr
, int nb
)
359 #ifdef CONFIG_BOOTX_TEXT
361 for (i
= 0; i
< nb
; ++i
)
362 *p
++ = xmon_get_adb_key();
366 if (!scc_initialized
)
368 for (i
= 0; i
< nb
; ++i
) {
369 while ((*sccc
& RXRDY
) == 0)
380 if ((*sccc
& RXRDY
) == 0) {
388 static unsigned char scc_inittab
[] = {
389 13, 0, /* set baud rate divisor */
391 14, 1, /* baud rate gen enable, src=rtxc */
392 11, 0x50, /* clocks = br gen */
393 5, 0xea, /* tx 8 bits, assert DTR & RTS */
394 4, 0x46, /* x16 clock, 1 stop */
395 3, 0xc1, /* rx enable, 8 bits */
401 if ( _machine
== _MACH_chrp
)
403 sccd
[3] = 0x83; eieio(); /* LCR = 8N1 + DLAB */
404 sccd
[0] = 12; eieio(); /* DLL = 9600 baud */
405 sccd
[1] = 0; eieio();
406 sccd
[2] = 0; eieio(); /* FCR = 0 */
407 sccd
[3] = 3; eieio(); /* LCR = 8N1 */
408 sccd
[1] = 0; eieio(); /* IER = 0 */
410 else if ( _machine
== _MACH_Pmac
)
414 if (channel_node
!= 0)
418 PMAC_SCC_ASYNC
| PMAC_SCC_FLAG_XMON
, 1);
419 printk(KERN_INFO
"Serial port locked ON by debugger !\n");
420 if (via_modem
&& channel_node
!= 0) {
424 PMAC_FTR_MODEM_ENABLE
,
426 printk(KERN_INFO
"Modem powered up by debugger !\n");
428 while (readtb() - t0
< 3*TB_SPEED
)
431 /* use the B channel if requested */
433 sccc
= (volatile unsigned char *)
434 ((unsigned long)sccc
& ~0x20);
437 for (i
= 20000; i
!= 0; --i
) {
440 *sccc
= 9; eieio(); /* reset A or B side */
441 *sccc
= ((unsigned long)sccc
& 0x20)? 0x80: 0x40; eieio();
442 for (i
= 0; i
< sizeof(scc_inittab
); ++i
) {
443 *sccc
= scc_inittab
[i
];
450 xmon_write(NULL
, "ATE1V1\r", 7);
451 if (xmon_expect("OK", 5)) {
452 xmon_write(NULL
, "ATA\r", 4);
453 if (xmon_expect("CONNECT", 40))
456 xmon_write(NULL
, "+++", 3);
457 xmon_expect("OK", 3);
466 int xmon_putc(int c
, void *f
)
472 return xmon_write(f
, &ch
, 1) == 1? c
: -1;
475 int xmon_putchar(int c
)
477 return xmon_putc(c
, xmon_stdout
);
480 int xmon_fputs(char *str
, void *f
)
484 return xmon_write(f
, str
, n
) == n
? 0: -1;
493 switch (xmon_read(xmon_stdin
, &ch
, 1)) {
497 xmon_printf("read(stdin) returned -1\r\n", 0, 0);
503 static char line
[256];
504 static char *lineptr
;
507 int xmon_expect(const char *str
, unsigned int timeout
)
517 c
= xmon_read_poll();
519 if (readtb() - t0
> timeout
)
525 if (c
!= '\r' && lineptr
< &line
[sizeof(line
) - 1])
529 } while (strstr(line
, str
) == NULL
);
542 if (c
== -1 || c
== 4)
544 if (c
== '\r' || c
== '\n') {
552 if (lineptr
> line
) {
560 while (lineptr
> line
) {
568 if (lineptr
>= &line
[sizeof(line
) - 1])
576 lineleft
= lineptr
- line
;
586 xmon_fgets(char *str
, int nb
, void *f
)
591 for (p
= str
; p
< str
+ nb
- 1; ) {
609 #ifdef CONFIG_ADB_PMU
610 if (_machine
== _MACH_Pmac
) {
619 #ifdef CONFIG_ADB_PMU
620 if (_machine
== _MACH_Pmac
) {