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>
17 #include <asm/bootx.h>
18 #include <asm/machdep.h>
19 #include <asm/errno.h>
20 #include <asm/pmac_feature.h>
21 #include <asm/processor.h>
22 #include <asm/delay.h>
23 #include <asm/btext.h>
25 #include <asm/bitops.h>
28 static volatile unsigned char *sccc, *sccd;
29 unsigned int TXRDY, RXRDY, DLAB;
30 static int xmon_expect(const char *str, unsigned int timeout);
32 static int use_serial;
33 static int use_screen;
35 static int xmon_use_sccb;
36 static struct device_node *channel_node;
38 #define TB_SPEED 25000000
40 static inline unsigned int readtb(void)
44 asm volatile("mftb %0" : "=r" (ret) :);
51 sccd[3] &= ~DLAB; /* reset DLAB */
54 extern int adb_init(void);
56 #ifdef CONFIG_PPC_CHRP
58 * This looks in the "ranges" property for the primary PCI host bridge
59 * to find the physical address of the start of PCI/ISA I/O space.
60 * It is basically a cut-down version of pci_process_bridge_OF_ranges.
62 static unsigned long chrp_find_phys_io_base(void)
64 struct device_node *node;
66 unsigned long base = CHRP_ISA_IO_BASE;
70 node = find_devices("isa");
73 if (node == NULL || node->type == NULL
74 || strcmp(node->type, "pci") != 0)
78 node = find_devices("pci");
82 ranges = (unsigned int *) get_property(node, "ranges", &rlen);
83 np = prom_n_addr_cells(node) + 5;
84 while ((rlen -= np * sizeof(unsigned int)) >= 0) {
85 if ((ranges[0] >> 24) == 1 && ranges[2] == 0) {
86 /* I/O space starting at 0, grab the phys base */
87 base = ranges[np - 3];
94 #endif /* CONFIG_PPC_CHRP */
96 #ifdef CONFIG_MAGIC_SYSRQ
97 static void sysrq_handle_xmon(int key, struct pt_regs *regs,
98 struct tty_struct *tty)
103 static struct sysrq_key_op sysrq_xmon_op =
105 .handler = sysrq_handle_xmon,
107 .action_msg = "Entering xmon\n",
114 #ifdef CONFIG_PPC_MULTIPLATFORM
115 volatile unsigned char *base;
117 if (_machine == _MACH_Pmac) {
118 struct device_node *np;
120 #ifdef CONFIG_BOOTX_TEXT
121 if (!use_screen && !use_serial
122 && !machine_is_compatible("iMac")) {
123 /* see if there is a keyboard in the device tree
124 with a parent of type "adb" */
125 for (np = find_devices("keyboard"); np; np = np->next)
126 if (np->parent && np->parent->type
127 && strcmp(np->parent->type, "adb") == 0)
130 /* needs to be hacked if xmon_printk is to be used
131 from within find_via_pmu() */
132 #ifdef CONFIG_ADB_PMU
133 if (np != NULL && boot_text_mapped && find_via_pmu())
136 #ifdef CONFIG_ADB_CUDA
137 if (np != NULL && boot_text_mapped && find_via_cuda())
141 if (!use_screen && (np = find_devices("escc")) != NULL) {
143 * look for the device node for the serial port
144 * we're using and see if it says it has a modem
146 char *name = xmon_use_sccb? "ch-b": "ch-a";
151 while (np != NULL && strcmp(np->name, name) != 0)
154 /* XXX should parse this properly */
156 slots = get_property(np, "slot-names", &l);
157 if (slots != NULL && l >= 10
158 && strcmp(slots+4, "Modem") == 0)
162 btext_drawstring("xmon uses ");
164 btext_drawstring("screen and keyboard\n");
167 btext_drawstring("modem on ");
168 btext_drawstring(xmon_use_sccb? "printer": "modem");
169 btext_drawstring(" port\n");
172 #endif /* CONFIG_BOOTX_TEXT */
182 np = find_devices("mac-io");
183 if (np && np->n_addrs)
184 addr = np->addrs[0].address + 0x13020;
185 base = (volatile unsigned char *) ioremap(addr & PAGE_MASK, PAGE_SIZE);
186 sccc = base + (addr & ~PAGE_MASK);
190 base = (volatile unsigned char *) isa_io_base;
191 if (_machine == _MACH_chrp)
192 base = (volatile unsigned char *)
193 ioremap(chrp_find_phys_io_base(), 0x1000);
205 #elif defined(CONFIG_GEMINI)
206 /* should already be mapped by the kernel boot */
207 sccc = (volatile unsigned char *) 0xffeffb0d;
208 sccd = (volatile unsigned char *) 0xffeffb08;
212 #elif defined(CONFIG_405GP)
213 sccc = (volatile unsigned char *)0xef600305;
214 sccd = (volatile unsigned char *)0xef600300;
218 #endif /* platform */
220 #ifdef CONFIG_MAGIC_SYSRQ
221 __sysrq_put_key_op('x', &sysrq_xmon_op);
225 static int scc_initialized = 0;
227 void xmon_init_scc(void);
228 extern void cuda_poll(void);
230 static inline void do_poll_adb(void)
232 #ifdef CONFIG_ADB_PMU
233 if (sys_ctrler == SYS_CTRLER_PMU)
235 #endif /* CONFIG_ADB_PMU */
236 #ifdef CONFIG_ADB_CUDA
237 if (sys_ctrler == SYS_CTRLER_CUDA)
239 #endif /* CONFIG_ADB_CUDA */
243 xmon_write(void *handle, void *ptr, int nb)
249 static unsigned long xmon_write_lock;
250 int lock_wait = 1000000;
253 while ((locked = test_and_set_bit(0, &xmon_write_lock)) != 0)
254 if (--lock_wait == 0)
258 #ifdef CONFIG_BOOTX_TEXT
260 /* write it on the screen */
261 for (i = 0; i < nb; ++i)
262 btext_drawchar(*p++);
266 if (!scc_initialized)
269 for (i = 0; i < nb; ++i) {
270 while ((*sccc & TXRDY) == 0)
273 if (c == '\n' && !ct) {
288 clear_bit(0, &xmon_write_lock);
294 int xmon_adb_keycode;
296 #ifdef CONFIG_BOOTX_TEXT
297 static int xmon_adb_shiftstate;
299 static unsigned char xmon_keytab[128] =
300 "asdfhgzxcv\000bqwer" /* 0x00 - 0x0f */
301 "yt123465=97-80]o" /* 0x10 - 0x1f */
302 "u[ip\rlj'k;\\,/nm." /* 0x20 - 0x2f */
303 "\t `\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */
304 "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
305 "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
307 static unsigned char xmon_shift_keytab[128] =
308 "ASDFHGZXCV\000BQWER" /* 0x00 - 0x0f */
309 "YT!@#$^%+(&_*)}O" /* 0x10 - 0x1f */
310 "U{IP\rLJ\"K:|<?NM>" /* 0x20 - 0x2f */
311 "\t ~\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */
312 "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
313 "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
316 xmon_get_adb_key(void)
322 xmon_adb_keycode = -1;
328 btext_drawchar(on? 0xdb: 0x20);
329 btext_drawchar('\b');
333 } while (xmon_adb_keycode == -1);
334 k = xmon_adb_keycode;
336 btext_drawstring(" \b");
338 /* test for shift keys */
339 if ((k & 0x7f) == 0x38 || (k & 0x7f) == 0x7b) {
340 xmon_adb_shiftstate = (k & 0x80) == 0;
344 continue; /* ignore up transitions */
345 k = (xmon_adb_shiftstate? xmon_shift_keytab: xmon_keytab)[k];
352 #endif /* CONFIG_BOOTX_TEXT */
355 xmon_read(void *handle, void *ptr, int nb)
360 #ifdef CONFIG_BOOTX_TEXT
362 for (i = 0; i < nb; ++i)
363 *p++ = xmon_get_adb_key();
367 if (!scc_initialized)
369 for (i = 0; i < nb; ++i) {
370 while ((*sccc & RXRDY) == 0)
381 if ((*sccc & RXRDY) == 0) {
389 static unsigned char scc_inittab[] = {
390 13, 0, /* set baud rate divisor */
392 14, 1, /* baud rate gen enable, src=rtxc */
393 11, 0x50, /* clocks = br gen */
394 5, 0xea, /* tx 8 bits, assert DTR & RTS */
395 4, 0x46, /* x16 clock, 1 stop */
396 3, 0xc1, /* rx enable, 8 bits */
402 if ( _machine == _MACH_chrp )
404 sccd[3] = 0x83; eieio(); /* LCR = 8N1 + DLAB */
405 sccd[0] = 12; eieio(); /* DLL = 9600 baud */
406 sccd[1] = 0; eieio();
407 sccd[2] = 0; eieio(); /* FCR = 0 */
408 sccd[3] = 3; eieio(); /* LCR = 8N1 */
409 sccd[1] = 0; eieio(); /* IER = 0 */
411 else if ( _machine == _MACH_Pmac )
415 if (channel_node != 0)
419 PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1);
420 printk(KERN_INFO "Serial port locked ON by debugger !\n");
421 if (via_modem && channel_node != 0) {
425 PMAC_FTR_MODEM_ENABLE,
427 printk(KERN_INFO "Modem powered up by debugger !\n");
429 while (readtb() - t0 < 3*TB_SPEED)
432 /* use the B channel if requested */
434 sccc = (volatile unsigned char *)
435 ((unsigned long)sccc & ~0x20);
438 for (i = 20000; i != 0; --i) {
441 *sccc = 9; eieio(); /* reset A or B side */
442 *sccc = ((unsigned long)sccc & 0x20)? 0x80: 0x40; eieio();
443 for (i = 0; i < sizeof(scc_inittab); ++i) {
444 *sccc = scc_inittab[i];
451 xmon_write(NULL, "ATE1V1\r", 7);
452 if (xmon_expect("OK", 5)) {
453 xmon_write(NULL, "ATA\r", 4);
454 if (xmon_expect("CONNECT", 40))
457 xmon_write(NULL, "+++", 3);
458 xmon_expect("OK", 3);
464 extern int (*prom_entry)(void *);
474 args.service = "exit";
475 (*prom_entry)(&args);
490 xmon_putc(int c, void *f)
496 return xmon_write(f, &ch, 1) == 1? c: -1;
502 return xmon_putc(c, xmon_stdout);
506 xmon_fputs(char *str, void *f)
510 return xmon_write(f, str, n) == n? 0: -1;
519 switch (xmon_read(xmon_stdin, &ch, 1)) {
523 xmon_printf("read(stdin) returned -1\r\n", 0, 0);
529 static char line[256];
530 static char *lineptr;
533 int xmon_expect(const char *str, unsigned int timeout)
543 c = xmon_read_poll();
545 if (readtb() - t0 > timeout)
551 if (c != '\r' && lineptr < &line[sizeof(line) - 1])
555 } while (strstr(line, str) == NULL);
568 if (c == -1 || c == 4)
570 if (c == '\r' || c == '\n') {
578 if (lineptr > line) {
586 while (lineptr > line) {
594 if (lineptr >= &line[sizeof(line) - 1])
602 lineleft = lineptr - line;
612 xmon_fgets(char *str, int nb, void *f)
617 for (p = str; p < str + nb - 1; ) {
635 #ifdef CONFIG_ADB_PMU
636 if (_machine == _MACH_Pmac) {
645 #ifdef CONFIG_ADB_PMU
646 if (_machine == _MACH_Pmac) {