2 * Copyright (C) 1996 Paul Mackerras.
4 #include <linux/config.h>
5 #include <linux/string.h>
6 #include <asm/machdep.h>
9 #include <asm/pgtable.h>
10 #include <linux/adb.h>
11 #include <linux/pmu.h>
13 #include <asm/bootx.h>
15 static volatile unsigned char *sccc
, *sccd
;
16 unsigned long TXRDY
, RXRDY
;
17 extern void xmon_printf(const char *fmt
, ...);
18 extern void map_bootx_text(void);
19 extern void drawchar(char);
20 extern void drawstring(const char *str
);
22 static int console
= 0;
23 static int use_screen
= 0;
27 if ( _machine
== _MACH_chrp
)
28 sccd
[3] &= ~0x80; /* reset DLAB */
34 volatile unsigned char *base
;
36 if ( _machine
== _MACH_Pmac
)
38 struct device_node
*np
;
39 extern boot_infos_t
*boot_infos
;
42 #ifdef CONFIG_BOOTX_TEXT
43 if (boot_infos
!= 0 && find_via_pmu()) {
44 printk(KERN_INFO
"xmon uses screen and keyboard\n");
58 np
= find_devices("mac-io");
59 if (np
&& np
->n_addrs
) {
60 addr
= np
->addrs
[0].address
+ 0x13000;
61 /* use the B channel on the iMac, A channel on others */
62 if (addr
>= 0xf0000000)
63 addr
+= 0x20; /* use A channel */
65 base
= (volatile unsigned char *) ioremap(addr
& PAGE_MASK
, PAGE_SIZE
);
66 sccc
= base
+ (addr
& ~PAGE_MASK
);
68 sccd
= sccc
+ (0xc1013030 - 0xc1013020);
70 sccd
= sccc
+ (0xf3013030 - 0xf3013020);
75 /* should already be mapped by the kernel boot */
76 sccc
= (volatile unsigned char *) (isa_io_base
+ 0x3fd);
77 sccd
= (volatile unsigned char *) (isa_io_base
+ 0x3f8);
83 static int scc_initialized
= 0;
85 void xmon_init_scc(void);
86 extern void pmu_poll(void);
89 xmon_write(void *handle
, void *ptr
, int nb
)
94 #ifdef CONFIG_BOOTX_TEXT
96 /* write it on the screen */
97 for (i
= 0; i
< nb
; ++i
)
102 if (!scc_initialized
)
104 for (i
= 0; i
< nb
; ++i
) {
105 while ((*sccc
& TXRDY
) == 0)
106 if (sys_ctrler
== SYS_CTRLER_PMU
)
109 if ( console
&& (*p
!= '\r'))
116 xmon_write(handle
, "\r", 1);
122 int xmon_pmu_keycode
;
124 #ifdef CONFIG_BOOTX_TEXT
125 static int xmon_pmu_shiftstate
;
127 static unsigned char xmon_keytab
[128] =
128 "asdfhgzxcv\000bqwer" /* 0x00 - 0x0f */
129 "yt123465=97-80o]" /* 0x10 - 0x1f */
130 "u[ip\rlj'k;\\,/nm." /* 0x20 - 0x2f */
131 "\t `\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */
132 "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
133 "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
135 static unsigned char xmon_shift_keytab
[128] =
136 "ASDFHGZXCV\000BQWER" /* 0x00 - 0x0f */
137 "YT!@#$^%+(&=*)}O" /* 0x10 - 0x1f */
138 "U{IP\rLJ\"K:|<?NM>" /* 0x20 - 0x2f */
139 "\t ~\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */
140 "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
141 "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
144 xmon_get_pmu_key(void)
150 xmon_pmu_keycode
= -1;
156 drawchar(on
? 0xdb: 0x20);
161 } while (xmon_pmu_keycode
== -1);
162 k
= xmon_pmu_keycode
;
166 /* test for shift keys */
167 if ((k
& 0x7f) == 0x38 || (k
& 0x7f) == 0x7b) {
168 xmon_pmu_shiftstate
= (k
& 0x80) == 0;
172 continue; /* ignore up transitions */
173 k
= (xmon_pmu_shiftstate
? xmon_shift_keytab
: xmon_keytab
)[k
];
180 #endif /* CONFIG_BOOTX_TEXT */
183 xmon_read(void *handle
, void *ptr
, int nb
)
188 #ifdef CONFIG_BOOTX_TEXT
190 for (i
= 0; i
< nb
; ++i
)
191 *p
++ = xmon_get_pmu_key();
195 if (!scc_initialized
)
197 for (i
= 0; i
< nb
; ++i
) {
198 while ((*sccc
& RXRDY
) == 0)
199 if (sys_ctrler
== SYS_CTRLER_PMU
)
204 *p
++ = ppc_md
.kbd_getkeycode();
212 static unsigned char scc_inittab
[] = {
213 13, 0, /* set baud rate divisor */
215 14, 1, /* baud rate gen enable, src=rtxc */
216 11, 0x50, /* clocks = br gen */
217 5, 0x6a, /* tx 8 bits, assert RTS */
218 4, 0x44, /* x16 clock, 1 stop */
219 3, 0xc1, /* rx enable, 8 bits */
225 if ( _machine
== _MACH_chrp
)
227 sccd
[3] = 0x83; eieio(); /* LCR = 8N1 + DLAB */
228 sccd
[0] = 3; eieio(); /* DLL = 38400 baud */
229 sccd
[1] = 0; eieio();
230 sccd
[2] = 0; eieio(); /* FCR = 0 */
231 sccd
[3] = 3; eieio(); /* LCR = 8N1 */
232 sccd
[1] = 0; eieio(); /* IER = 0 */
238 for (i
= 20000; i
!= 0; --i
) {
241 *sccc
= 9; eieio(); /* reset A or B side */
242 *sccc
= ((unsigned long)sccc
& 0x20)? 0x80: 0x40; eieio();
243 for (i
= 0; i
< sizeof(scc_inittab
); ++i
) {
244 *sccc
= scc_inittab
[i
];
252 extern int (*prom_entry
)(void *);
262 args
.service
= "exit";
263 (*prom_entry
)(&args
);
278 xmon_putc(int c
, void *f
)
284 return xmon_write(f
, &ch
, 1) == 1? c
: -1;
290 return xmon_putc(c
, xmon_stdout
);
294 xmon_fputs(char *str
, void *f
)
298 return xmon_write(f
, str
, n
) == n
? 0: -1;
307 switch (xmon_read(xmon_stdin
, &ch
, 1)) {
311 xmon_printf("read(stdin) returned -1\r\n", 0, 0);
317 static char line
[256];
318 static char *lineptr
;
330 if (c
== -1 || c
== 4)
332 if (c
== '\r' || c
== '\n') {
340 if (lineptr
> line
) {
348 while (lineptr
> line
) {
356 if (lineptr
>= &line
[sizeof(line
) - 1])
364 lineleft
= lineptr
- line
;
374 xmon_fgets(char *str
, int nb
, void *f
)
379 for (p
= str
; p
< str
+ nb
- 1; ) {