]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - common/console.c
Patch by Guillaume Alexandre,, 04 Nov 2002:
[karo-tx-uboot.git] / common / console.c
1 /*
2  * (C) Copyright 2000
3  * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 #include <common.h>
25 #include <stdarg.h>
26 #include <malloc.h>
27 #include <console.h>
28 #include <syscall.h>
29
30 void **syscall_tbl;
31
32 #ifdef CFG_CONSOLE_IS_IN_ENV
33 /*
34  * if overwrite_console returns 1, the stdin, stderr and stdout
35  * are switched to the serial port, else the settings in the
36  * environment are used
37  */
38 #ifdef CFG_CONSOLE_OVERWRITE_ROUTINE
39 extern int overwrite_console (void);
40 #else
41 int overwrite_console (void)
42 {
43         return (0);
44 }
45 #endif /* CFG_CONSOLE_OVERWRITE_ROUTINE */
46
47 #endif /* CFG_CONSOLE_IS_IN_ENV */
48
49 static int console_setfile (int file, device_t * dev)
50 {
51         int error = 0;
52
53         if (dev == NULL)
54                 return -1;
55
56         switch (file) {
57         case stdin:
58         case stdout:
59         case stderr:
60                 /* Start new device */
61                 if (dev->start) {
62                         error = dev->start ();
63                         /* If it's not started dont use it */
64                         if (error < 0)
65                                 break;
66                 }
67
68                 /* Assign the new device (leaving the existing one started) */
69                 stdio_devices[file] = dev;
70
71                 /*
72                  * Update monitor functions
73                  * (to use the console stuff by other applications)
74                  */
75                 switch (file) {
76                 case stdin:
77                         syscall_tbl[SYSCALL_GETC] = dev->getc;
78                         syscall_tbl[SYSCALL_TSTC] = dev->tstc;
79                         break;
80                 case stdout:
81                         syscall_tbl[SYSCALL_PUTC] = dev->putc;
82                         syscall_tbl[SYSCALL_PUTS] = dev->puts;
83                         syscall_tbl[SYSCALL_PRINTF] = printf;
84                         break;
85                 }
86                 break;
87
88         default:                /* Invalid file ID */
89                 error = -1;
90         }
91         return error;
92 }
93
94 /** U-Boot INITIAL CONSOLE-NOT COMPATIBLE FUNCTIONS *************************/
95
96 void serial_printf (const char *fmt, ...)
97 {
98         va_list args;
99         uint i;
100         char printbuffer[CFG_PBSIZE];
101
102         va_start (args, fmt);
103
104         /* For this to work, printbuffer must be larger than
105          * anything we ever want to print.
106          */
107         i = vsprintf (printbuffer, fmt, args);
108         va_end (args);
109
110         serial_puts (printbuffer);
111 }
112
113 int fgetc (int file)
114 {
115         if (file < MAX_FILES)
116                 return stdio_devices[file]->getc ();
117
118         return -1;
119 }
120
121 int ftstc (int file)
122 {
123         if (file < MAX_FILES)
124                 return stdio_devices[file]->tstc ();
125
126         return -1;
127 }
128
129 void fputc (int file, const char c)
130 {
131         if (file < MAX_FILES)
132                 stdio_devices[file]->putc (c);
133 }
134
135 void fputs (int file, const char *s)
136 {
137         if (file < MAX_FILES)
138                 stdio_devices[file]->puts (s);
139 }
140
141 void fprintf (int file, const char *fmt, ...)
142 {
143         va_list args;
144         uint i;
145         char printbuffer[CFG_PBSIZE];
146
147         va_start (args, fmt);
148
149         /* For this to work, printbuffer must be larger than
150          * anything we ever want to print.
151          */
152         i = vsprintf (printbuffer, fmt, args);
153         va_end (args);
154
155         /* Send to desired file */
156         fputs (file, printbuffer);
157 }
158
159 /** U-Boot INITIAL CONSOLE-COMPATIBLE FUNCTION *****************************/
160
161 int getc (void)
162 {
163         DECLARE_GLOBAL_DATA_PTR;
164
165         if (gd->flags & GD_FLG_DEVINIT) {
166                 /* Get from the standard input */
167                 return fgetc (stdin);
168         }
169
170         /* Send directly to the handler */
171         return serial_getc ();
172 }
173
174 int tstc (void)
175 {
176         DECLARE_GLOBAL_DATA_PTR;
177
178         if (gd->flags & GD_FLG_DEVINIT) {
179                 /* Test the standard input */
180                 return ftstc (stdin);
181         }
182
183         /* Send directly to the handler */
184         return serial_tstc ();
185 }
186
187 void putc (const char c)
188 {
189         DECLARE_GLOBAL_DATA_PTR;
190
191         if (gd->flags & GD_FLG_DEVINIT) {
192                 /* Send to the standard output */
193                 fputc (stdout, c);
194         } else {
195                 /* Send directly to the handler */
196                 serial_putc (c);
197         }
198 }
199
200 void puts (const char *s)
201 {
202         DECLARE_GLOBAL_DATA_PTR;
203
204         if (gd->flags & GD_FLG_DEVINIT) {
205                 /* Send to the standard output */
206                 fputs (stdout, s);
207         } else {
208                 /* Send directly to the handler */
209                 serial_puts (s);
210         }
211 }
212
213 void printf (const char *fmt, ...)
214 {
215         va_list args;
216         uint i;
217         char printbuffer[CFG_PBSIZE];
218
219         va_start (args, fmt);
220
221         /* For this to work, printbuffer must be larger than
222          * anything we ever want to print.
223          */
224         i = vsprintf (printbuffer, fmt, args);
225         va_end (args);
226
227         /* Print the string */
228         puts (printbuffer);
229 }
230
231 /* test if ctrl-c was pressed */
232 static int ctrlc_disabled = 0;  /* see disable_ctrl() */
233 static int ctrlc_was_pressed = 0;
234 int ctrlc (void)
235 {
236         DECLARE_GLOBAL_DATA_PTR;
237
238         if (!ctrlc_disabled && gd->have_console) {
239                 if (tstc ()) {
240                         switch (getc ()) {
241                         case 0x03:              /* ^C - Control C */
242                                 ctrlc_was_pressed = 1;
243                                 return 1;
244                         default:
245                                 break;
246                         }
247                 }
248         }
249         return 0;
250 }
251
252 /* pass 1 to disable ctrlc() checking, 0 to enable.
253  * returns previous state
254  */
255 int disable_ctrlc (int disable)
256 {
257         int prev = ctrlc_disabled;      /* save previous state */
258
259         ctrlc_disabled = disable;
260         return prev;
261 }
262
263 int had_ctrlc (void)
264 {
265         return ctrlc_was_pressed;
266 }
267
268 void clear_ctrlc (void)
269 {
270         ctrlc_was_pressed = 0;
271 }
272
273 #ifdef CONFIG_MODEM_SUPPORT_DEBUG
274 char    screen[1024];
275 char *cursor = screen;
276 int once = 0;
277 inline void dbg(const char *fmt, ...)
278 {
279         va_list args;
280         uint    i;
281         char    printbuffer[CFG_PBSIZE];
282
283         if (!once) {
284                 memset(screen, 0, sizeof(screen));
285                 once++;
286         }
287
288         va_start(args, fmt);
289
290         /* For this to work, printbuffer must be larger than
291          * anything we ever want to print.
292          */
293         i = vsprintf(printbuffer, fmt, args);
294         va_end(args);
295
296         if ((screen + sizeof(screen) - 1 - cursor) < strlen(printbuffer)+1) {
297                 memset(screen, 0, sizeof(screen));
298                 cursor = screen;
299         }
300         sprintf(cursor, printbuffer);
301         cursor += strlen(printbuffer);
302
303 }
304 #else
305 inline void dbg(const char *fmt, ...)
306 {
307 }
308 #endif
309
310 /** U-Boot INIT FUNCTIONS *************************************************/
311
312 int console_assign (int file, char *devname)
313 {
314         int flag, i;
315
316         /* Check for valid file */
317         switch (file) {
318         case stdin:
319                 flag = DEV_FLAGS_INPUT;
320                 break;
321         case stdout:
322         case stderr:
323                 flag = DEV_FLAGS_OUTPUT;
324                 break;
325         default:
326                 return -1;
327         }
328
329         /* Check for valid device name */
330
331         for (i = 1; i <= ListNumItems (devlist); i++) {
332                 device_t *dev = ListGetPtrToItem (devlist, i);
333
334                 if (strcmp (devname, dev->name) == 0) {
335                         if (dev->flags & flag)
336                                 return console_setfile (file, dev);
337
338                         return -1;
339                 }
340         }
341
342         return -1;
343 }
344
345 /* Called before relocation - use serial functions */
346 int console_init_f (void)
347 {
348         DECLARE_GLOBAL_DATA_PTR;
349
350         gd->have_console = 1;
351         return (0);
352 }
353
354 #ifdef CFG_CONSOLE_IS_IN_ENV
355 /* search a device */
356 device_t *search_device (int flags, char *name)
357 {
358         int i, items;
359         device_t *dev = NULL;
360
361         items = ListNumItems (devlist);
362         if (name == NULL)
363                 return dev;
364
365         for (i = 1; i <= items; i++) {
366                 dev = ListGetPtrToItem (devlist, i);
367                 if ((dev->flags & flags) && (strcmp (name, dev->name) == 0)) {
368                         break;
369                 }
370         }
371         return dev;
372 }
373 #endif /* CFG_CONSOLE_IS_IN_ENV */
374
375 #ifdef CFG_CONSOLE_IS_IN_ENV
376 /* Called after the relocation - use desired console functions */
377 int console_init_r (void)
378 {
379         char *stdinname, *stdoutname, *stderrname;
380         device_t *inputdev = NULL, *outputdev = NULL, *errdev = NULL;
381
382         /* set default handlers at first */
383         syscall_tbl[SYSCALL_GETC] = serial_getc;
384         syscall_tbl[SYSCALL_TSTC] = serial_tstc;
385         syscall_tbl[SYSCALL_PUTC] = serial_putc;
386         syscall_tbl[SYSCALL_PUTS] = serial_puts;
387         syscall_tbl[SYSCALL_PRINTF] = serial_printf;
388
389         /* stdin stdout and stderr are in environment */
390         /* scan for it */
391         stdinname  = getenv ("stdin");
392         stdoutname = getenv ("stdout");
393         stderrname = getenv ("stderr");
394
395         if (overwrite_console () == 0) { /* if not overwritten by config switch */
396                 inputdev  = search_device (DEV_FLAGS_INPUT,  stdinname);
397                 outputdev = search_device (DEV_FLAGS_OUTPUT, stdoutname);
398                 errdev    = search_device (DEV_FLAGS_OUTPUT, stderrname);
399         }
400         /* if the devices are overwritten or not found, use default device */
401         if (inputdev == NULL) {
402                 inputdev  = search_device (DEV_FLAGS_INPUT,  "serial");
403         }
404         if (outputdev == NULL) {
405                 outputdev = search_device (DEV_FLAGS_OUTPUT, "serial");
406         }
407         if (errdev == NULL) {
408                 errdev    = search_device (DEV_FLAGS_OUTPUT, "serial");
409         }
410         /* Initializes output console first */
411         if (outputdev != NULL) {
412                 console_setfile (stdout, outputdev);
413         }
414         if (errdev != NULL) {
415                 console_setfile (stderr, errdev);
416         }
417         if (inputdev != NULL) {
418                 console_setfile (stdin, inputdev);
419         }
420
421 #ifndef CFG_CONSOLE_INFO_QUIET
422         /* Print information */
423         printf ("In:    ");
424         if (stdio_devices[stdin] == NULL) {
425                 printf ("No input devices available!\n");
426         } else {
427                 printf ("%s\n", stdio_devices[stdin]->name);
428         }
429
430         printf ("Out:   ");
431         if (stdio_devices[stdout] == NULL) {
432                 printf ("No output devices available!\n");
433         } else {
434                 printf ("%s\n", stdio_devices[stdout]->name);
435         }
436
437         printf ("Err:   ");
438         if (stdio_devices[stderr] == NULL) {
439                 printf ("No error devices available!\n");
440         } else {
441                 printf ("%s\n", stdio_devices[stderr]->name);
442         }
443 #endif /* CFG_CONSOLE_INFO_QUIET */
444
445 #ifdef CFG_CONSOLE_ENV_OVERWRITE
446         /* set the environment variables (will overwrite previous env settings) */
447         for (i = 0; i < 3; i++) {
448                 setenv (stdio_names[i], stdio_devices[i]->name);
449         }
450 #endif /*  CFG_CONSOLE_ENV_OVERWRITE */
451
452 #if 0
453         /* If nothing usable installed, use only the initial console */
454         if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
455                 return (0);
456 #endif
457         return (0);
458 }
459
460 #else /* CFG_CONSOLE_IS_IN_ENV */
461
462 /* Called after the relocation - use desired console functions */
463 int console_init_r (void)
464 {
465         device_t *inputdev = NULL, *outputdev = NULL;
466         int i, items = ListNumItems (devlist);
467
468         /* Scan devices looking for input and output devices */
469         for (i = 1;
470              (i <= items) && ((inputdev == NULL) || (outputdev == NULL));
471              i++
472             ) {
473                 device_t *dev = ListGetPtrToItem (devlist, i);
474
475                 if ((dev->flags & DEV_FLAGS_INPUT) && (inputdev == NULL)) {
476                         inputdev = dev;
477                 }
478                 if ((dev->flags & DEV_FLAGS_OUTPUT) && (outputdev == NULL)) {
479                         outputdev = dev;
480                 }
481         }
482
483         /* Initializes output console first */
484         if (outputdev != NULL) {
485                 console_setfile (stdout, outputdev);
486                 console_setfile (stderr, outputdev);
487         }
488
489         /* Initializes input console */
490         if (inputdev != NULL) {
491                 console_setfile (stdin, inputdev);
492         }
493
494 #ifndef CFG_CONSOLE_INFO_QUIET
495         /* Print informations */
496         printf ("In:    ");
497         if (stdio_devices[stdin] == NULL) {
498                 printf ("No input devices available!\n");
499         } else {
500                 printf ("%s\n", stdio_devices[stdin]->name);
501         }
502
503         printf ("Out:   ");
504         if (stdio_devices[stdout] == NULL) {
505                 printf ("No output devices available!\n");
506         } else {
507                 printf ("%s\n", stdio_devices[stdout]->name);
508         }
509
510         printf ("Err:   ");
511         if (stdio_devices[stderr] == NULL) {
512                 printf ("No error devices available!\n");
513         } else {
514                 printf ("%s\n", stdio_devices[stderr]->name);
515         }
516 #endif /* CFG_CONSOLE_INFO_QUIET */
517
518         /* Setting environment variables */
519         for (i = 0; i < 3; i++) {
520                 setenv (stdio_names[i], stdio_devices[i]->name);
521         }
522
523 #if 0
524         /* If nothing usable installed, use only the initial console */
525         if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
526                 return (0);
527 #endif
528
529         return (0);
530 }
531
532 #endif /* CFG_CONSOLE_IS_IN_ENV */