Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/agpgart
[linux-drm-fsl-dcu.git] / arch / ppc / xmon / start.c
1 /*
2  * Copyright (C) 1996 Paul Mackerras.
3  */
4 #include <linux/string.h>
5 #include <asm/machdep.h>
6 #include <asm/io.h>
7 #include <asm/page.h>
8 #include <linux/kernel.h>
9 #include <linux/errno.h>
10 #include <linux/sysrq.h>
11 #include <linux/bitops.h>
12 #include <asm/xmon.h>
13 #include <asm/machdep.h>
14 #include <asm/errno.h>
15 #include <asm/processor.h>
16 #include <asm/delay.h>
17 #include <asm/btext.h>
18 #include <asm/ibm4xx.h>
19
20 static volatile unsigned char *sccc, *sccd;
21 unsigned int TXRDY, RXRDY, DLAB;
22 static int xmon_expect(const char *str, unsigned int timeout);
23
24 static int via_modem;
25
26 #define TB_SPEED        25000000
27
28 static inline unsigned int readtb(void)
29 {
30         unsigned int ret;
31
32         asm volatile("mftb %0" : "=r" (ret) :);
33         return ret;
34 }
35
36 void buf_access(void)
37 {
38         if (DLAB)
39                 sccd[3] &= ~DLAB;       /* reset DLAB */
40 }
41
42
43 #ifdef CONFIG_MAGIC_SYSRQ
44 static void sysrq_handle_xmon(int key, struct pt_regs *regs,
45                               struct tty_struct *tty)
46 {
47         xmon(regs);
48 }
49
50 static struct sysrq_key_op sysrq_xmon_op =
51 {
52         .handler =      sysrq_handle_xmon,
53         .help_msg =     "Xmon",
54         .action_msg =   "Entering xmon",
55 };
56 #endif
57
58 void
59 xmon_map_scc(void)
60 {
61 #if defined(CONFIG_405GP)
62         sccd = (volatile unsigned char *)0xef600300;
63 #elif defined(CONFIG_440EP)
64         sccd = (volatile unsigned char *) ioremap(PPC440EP_UART0_ADDR, 8);
65 #elif defined(CONFIG_440SP)
66         sccd = (volatile unsigned char *) ioremap64(PPC440SP_UART0_ADDR, 8);
67 #elif defined(CONFIG_440SPE)
68         sccd = (volatile unsigned char *) ioremap64(PPC440SPE_UART0_ADDR, 8);
69 #elif defined(CONFIG_44x)
70         /* This is the default for 44x platforms.  Any boards that have a
71            different UART address need to be put in cases before this or the
72            port will be mapped incorrectly */
73         sccd = (volatile unsigned char *) ioremap64(PPC440GP_UART0_ADDR, 8);
74 #endif /* platform */
75
76 #ifndef CONFIG_PPC_PREP
77         sccc = sccd + 5;
78         TXRDY = 0x20;
79         RXRDY = 1;
80         DLAB = 0x80;
81 #endif
82
83         register_sysrq_key('x', &sysrq_xmon_op);
84 }
85
86 static int scc_initialized;
87
88 void xmon_init_scc(void);
89
90 int
91 xmon_write(void *handle, void *ptr, int nb)
92 {
93         char *p = ptr;
94         int i, c, ct;
95
96 #ifdef CONFIG_SMP
97         static unsigned long xmon_write_lock;
98         int lock_wait = 1000000;
99         int locked;
100
101         while ((locked = test_and_set_bit(0, &xmon_write_lock)) != 0)
102                 if (--lock_wait == 0)
103                         break;
104 #endif
105
106         if (!scc_initialized)
107                 xmon_init_scc();
108         ct = 0;
109         for (i = 0; i < nb; ++i) {
110                 while ((*sccc & TXRDY) == 0)
111                         ;
112                 c = p[i];
113                 if (c == '\n' && !ct) {
114                         c = '\r';
115                         ct = 1;
116                         --i;
117                 } else {
118                         ct = 0;
119                 }
120                 buf_access();
121                 *sccd = c;
122                 eieio();
123         }
124
125 #ifdef CONFIG_SMP
126         if (!locked)
127                 clear_bit(0, &xmon_write_lock);
128 #endif
129         return nb;
130 }
131
132 int xmon_wants_key;
133
134
135 int
136 xmon_read(void *handle, void *ptr, int nb)
137 {
138     char *p = ptr;
139     int i;
140
141     if (!scc_initialized)
142         xmon_init_scc();
143     for (i = 0; i < nb; ++i) {
144         while ((*sccc & RXRDY) == 0)
145             ;
146         buf_access();
147         *p++ = *sccd;
148     }
149     return i;
150 }
151
152 int
153 xmon_read_poll(void)
154 {
155         if ((*sccc & RXRDY) == 0) {
156                 ;
157                 return -1;
158         }
159         buf_access();
160         return *sccd;
161 }
162
163 void
164 xmon_init_scc(void)
165 {
166         scc_initialized = 1;
167         if (via_modem) {
168                 for (;;) {
169                         xmon_write(NULL, "ATE1V1\r", 7);
170                         if (xmon_expect("OK", 5)) {
171                                 xmon_write(NULL, "ATA\r", 4);
172                                 if (xmon_expect("CONNECT", 40))
173                                         break;
174                         }
175                         xmon_write(NULL, "+++", 3);
176                         xmon_expect("OK", 3);
177                 }
178         }
179 }
180
181
182 void *xmon_stdin;
183 void *xmon_stdout;
184 void *xmon_stderr;
185
186 void
187 xmon_init(int arg)
188 {
189         xmon_map_scc();
190 }
191
192 int
193 xmon_putc(int c, void *f)
194 {
195     char ch = c;
196
197     if (c == '\n')
198         xmon_putc('\r', f);
199     return xmon_write(f, &ch, 1) == 1? c: -1;
200 }
201
202 int
203 xmon_putchar(int c)
204 {
205     return xmon_putc(c, xmon_stdout);
206 }
207
208 int
209 xmon_fputs(char *str, void *f)
210 {
211     int n = strlen(str);
212
213     return xmon_write(f, str, n) == n? 0: -1;
214 }
215
216 int
217 xmon_readchar(void)
218 {
219     char ch;
220
221     for (;;) {
222         switch (xmon_read(xmon_stdin, &ch, 1)) {
223         case 1:
224             return ch;
225         case -1:
226             xmon_printf("read(stdin) returned -1\r\n", 0, 0);
227             return -1;
228         }
229     }
230 }
231
232 static char line[256];
233 static char *lineptr;
234 static int lineleft;
235
236 int xmon_expect(const char *str, unsigned int timeout)
237 {
238         int c;
239         unsigned int t0;
240
241         timeout *= TB_SPEED;
242         t0 = readtb();
243         do {
244                 lineptr = line;
245                 for (;;) {
246                         c = xmon_read_poll();
247                         if (c == -1) {
248                                 if (readtb() - t0 > timeout)
249                                         return 0;
250                                 continue;
251                         }
252                         if (c == '\n')
253                                 break;
254                         if (c != '\r' && lineptr < &line[sizeof(line) - 1])
255                                 *lineptr++ = c;
256                 }
257                 *lineptr = 0;
258         } while (strstr(line, str) == NULL);
259         return 1;
260 }
261
262 int
263 xmon_getchar(void)
264 {
265     int c;
266
267     if (lineleft == 0) {
268         lineptr = line;
269         for (;;) {
270             c = xmon_readchar();
271             if (c == -1 || c == 4)
272                 break;
273             if (c == '\r' || c == '\n') {
274                 *lineptr++ = '\n';
275                 xmon_putchar('\n');
276                 break;
277             }
278             switch (c) {
279             case 0177:
280             case '\b':
281                 if (lineptr > line) {
282                     xmon_putchar('\b');
283                     xmon_putchar(' ');
284                     xmon_putchar('\b');
285                     --lineptr;
286                 }
287                 break;
288             case 'U' & 0x1F:
289                 while (lineptr > line) {
290                     xmon_putchar('\b');
291                     xmon_putchar(' ');
292                     xmon_putchar('\b');
293                     --lineptr;
294                 }
295                 break;
296             default:
297                 if (lineptr >= &line[sizeof(line) - 1])
298                     xmon_putchar('\a');
299                 else {
300                     xmon_putchar(c);
301                     *lineptr++ = c;
302                 }
303             }
304         }
305         lineleft = lineptr - line;
306         lineptr = line;
307     }
308     if (lineleft == 0)
309         return -1;
310     --lineleft;
311     return *lineptr++;
312 }
313
314 char *
315 xmon_fgets(char *str, int nb, void *f)
316 {
317     char *p;
318     int c;
319
320     for (p = str; p < str + nb - 1; ) {
321         c = xmon_getchar();
322         if (c == -1) {
323             if (p == str)
324                 return NULL;
325             break;
326         }
327         *p++ = c;
328         if (c == '\n')
329             break;
330     }
331     *p = 0;
332     return str;
333 }
334
335 void
336 xmon_enter(void)
337 {
338 }
339
340 void
341 xmon_leave(void)
342 {
343 }