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/kernel.h>
13 #include <asm/bootx.h>
14 #include <asm/feature.h>
15 #include <asm/processor.h>
17 static volatile unsigned char *sccc
, *sccd
;
18 unsigned long TXRDY
, RXRDY
;
19 extern void xmon_printf(const char *fmt
, ...);
20 extern void prom_drawchar(char);
21 extern void prom_drawstring(const char *str
);
22 static int xmon_expect(const char *str
, unsigned int timeout
);
24 static int console
= 0;
25 static int use_screen
= 1; /* default */
26 static int via_modem
= 0;
27 static int xmon_use_sccb
= 0;
28 static struct device_node
*macio_node
;
30 #define TB_SPEED 25000000
32 static inline unsigned int readtb(void)
36 asm volatile("mftb %0" : "=r" (ret
) :);
42 if ( _machine
== _MACH_chrp
)
43 sccd
[3] &= ~0x80; /* reset DLAB */
49 volatile unsigned char *base
;
53 if ( _machine
== _MACH_Pmac
)
55 struct device_node
*np
;
57 #ifdef CONFIG_BOOTX_TEXT
58 extern boot_infos_t
*disp_bi
;
60 /* needs to be hacked if xmon_printk is to be used
61 from within find_via_pmu() */
62 if (!via_modem
&& disp_bi
&& find_via_pmu()) {
63 prom_drawstring("xmon uses screen and keyboard\n");
77 np
= find_devices("mac-io");
78 if (np
&& np
->n_addrs
) {
80 addr
= np
->addrs
[0].address
+ 0x13000;
81 /* use the B channel on the iMac */
83 addr
+= 0x20; /* use A channel */
85 base
= (volatile unsigned char *) ioremap(addr
& PAGE_MASK
, PAGE_SIZE
);
86 sccc
= base
+ (addr
& ~PAGE_MASK
);
88 sccd
= sccc
+ (0xc1013030 - 0xc1013020);
90 sccd
= sccc
+ (0xf3013030 - 0xf3013020);
93 else if ( _machine
& _MACH_gemini
)
95 /* should already be mapped by the kernel boot */
96 sccc
= (volatile unsigned char *) 0xffeffb0d;
97 sccd
= (volatile unsigned char *) 0xffeffb08;
104 /* should already be mapped by the kernel boot */
105 sccc
= (volatile unsigned char *) (isa_io_base
+ 0x3fd);
106 sccd
= (volatile unsigned char *) (isa_io_base
+ 0x3f8);
112 static int scc_initialized
= 0;
114 void xmon_init_scc(void);
115 extern void pmu_poll(void);
118 xmon_write(void *handle
, void *ptr
, int nb
)
123 #ifdef CONFIG_BOOTX_TEXT
125 /* write it on the screen */
126 for (i
= 0; i
< nb
; ++i
)
131 if (!scc_initialized
)
134 for (i
= 0; i
< nb
; ++i
) {
135 while ((*sccc
& TXRDY
) == 0) {
137 if (sys_ctrler
== SYS_CTRLER_PMU
)
139 #endif /* CONFIG_ADB */
142 if (c
== '\n' && !ct
) {
159 int xmon_pmu_keycode
;
161 #ifdef CONFIG_BOOTX_TEXT
162 static int xmon_pmu_shiftstate
;
164 static unsigned char xmon_keytab
[128] =
165 "asdfhgzxcv\000bqwer" /* 0x00 - 0x0f */
166 "yt123465=97-80o]" /* 0x10 - 0x1f */
167 "u[ip\rlj'k;\\,/nm." /* 0x20 - 0x2f */
168 "\t `\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */
169 "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
170 "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
172 static unsigned char xmon_shift_keytab
[128] =
173 "ASDFHGZXCV\000BQWER" /* 0x00 - 0x0f */
174 "YT!@#$^%+(&=*)}O" /* 0x10 - 0x1f */
175 "U{IP\rLJ\"K:|<?NM>" /* 0x20 - 0x2f */
176 "\t ~\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */
177 "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
178 "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
181 xmon_get_pmu_key(void)
187 xmon_pmu_keycode
= -1;
193 prom_drawchar(on
? 0xdb: 0x20);
198 } while (xmon_pmu_keycode
== -1);
199 k
= xmon_pmu_keycode
;
201 prom_drawstring(" \b");
203 /* test for shift keys */
204 if ((k
& 0x7f) == 0x38 || (k
& 0x7f) == 0x7b) {
205 xmon_pmu_shiftstate
= (k
& 0x80) == 0;
209 continue; /* ignore up transitions */
210 k
= (xmon_pmu_shiftstate
? xmon_shift_keytab
: xmon_keytab
)[k
];
217 #endif /* CONFIG_BOOTX_TEXT */
220 xmon_read(void *handle
, void *ptr
, int nb
)
225 #ifdef CONFIG_BOOTX_TEXT
227 for (i
= 0; i
< nb
; ++i
)
228 *p
++ = xmon_get_pmu_key();
232 if (!scc_initialized
)
234 for (i
= 0; i
< nb
; ++i
) {
235 while ((*sccc
& RXRDY
) == 0)
237 if (sys_ctrler
== SYS_CTRLER_PMU
)
241 #endif /* CONFIG_ADB */
251 if ((*sccc
& RXRDY
) == 0) {
253 if (sys_ctrler
== SYS_CTRLER_PMU
)
264 static unsigned char scc_inittab
[] = {
265 13, 0, /* set baud rate divisor */
267 14, 1, /* baud rate gen enable, src=rtxc */
268 11, 0x50, /* clocks = br gen */
269 5, 0xea, /* tx 8 bits, assert DTR & RTS */
270 4, 0x46, /* x16 clock, 1 stop */
271 3, 0xc1, /* rx enable, 8 bits */
277 if ( _machine
== _MACH_chrp
)
279 sccd
[3] = 0x83; eieio(); /* LCR = 8N1 + DLAB */
280 sccd
[0] = 3; eieio(); /* DLL = 38400 baud */
281 sccd
[1] = 0; eieio();
282 sccd
[2] = 0; eieio(); /* FCR = 0 */
283 sccd
[3] = 3; eieio(); /* LCR = 8N1 */
284 sccd
[1] = 0; eieio(); /* IER = 0 */
286 else if ( _machine
== _MACH_Pmac
)
291 feature_set(macio_node
, FEATURE_Serial_enable
);
292 if (via_modem
&& macio_node
!= 0) {
295 feature_set(macio_node
, FEATURE_Modem_power
);
297 while (readtb() - t0
< 3*TB_SPEED
)
300 for (i
= 20000; i
!= 0; --i
) {
303 *sccc
= 9; eieio(); /* reset A or B side */
304 *sccc
= ((unsigned long)sccc
& 0x20)? 0x80: 0x40; eieio();
305 for (i
= 0; i
< sizeof(scc_inittab
); ++i
) {
306 *sccc
= scc_inittab
[i
];
313 xmon_write(0, "ATE1V1\r", 7);
314 if (xmon_expect("OK", 5)) {
315 xmon_write(0, "ATA\r", 4);
316 if (xmon_expect("CONNECT", 40))
319 xmon_write(0, "+++", 3);
320 xmon_expect("OK", 3);
326 extern int (*prom_entry
)(void *);
336 args
.service
= "exit";
337 (*prom_entry
)(&args
);
352 xmon_putc(int c
, void *f
)
358 return xmon_write(f
, &ch
, 1) == 1? c
: -1;
364 return xmon_putc(c
, xmon_stdout
);
368 xmon_fputs(char *str
, void *f
)
372 return xmon_write(f
, str
, n
) == n
? 0: -1;
381 switch (xmon_read(xmon_stdin
, &ch
, 1)) {
385 xmon_printf("read(stdin) returned -1\r\n", 0, 0);
391 static char line
[256];
392 static char *lineptr
;
395 int xmon_expect(const char *str
, unsigned int timeout
)
405 c
= xmon_read_poll();
407 if (readtb() - t0
> timeout
)
413 if (c
!= '\r' && lineptr
< &line
[sizeof(line
) - 1])
417 } while (strstr(line
, str
) == NULL
);
430 if (c
== -1 || c
== 4)
432 if (c
== '\r' || c
== '\n') {
440 if (lineptr
> line
) {
448 while (lineptr
> line
) {
456 if (lineptr
>= &line
[sizeof(line
) - 1])
464 lineleft
= lineptr
- line
;
474 xmon_fgets(char *str
, int nb
, void *f
)
479 for (p
= str
; p
< str
+ nb
- 1; ) {