Merge branch 'master' of /home/wd/git/u-boot/custodians
[platform/kernel/u-boot.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 <stdio_dev.h>
28 #include <exports.h>
29
30 DECLARE_GLOBAL_DATA_PTR;
31
32 #ifdef CONFIG_AMIGAONEG3SE
33 int console_changed = 0;
34 #endif
35
36 #ifdef CONFIG_SYS_CONSOLE_IS_IN_ENV
37 /*
38  * if overwrite_console returns 1, the stdin, stderr and stdout
39  * are switched to the serial port, else the settings in the
40  * environment are used
41  */
42 #ifdef CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE
43 extern int overwrite_console(void);
44 #define OVERWRITE_CONSOLE overwrite_console()
45 #else
46 #define OVERWRITE_CONSOLE 0
47 #endif /* CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE */
48
49 #endif /* CONFIG_SYS_CONSOLE_IS_IN_ENV */
50
51 static int console_setfile(int file, struct stdio_dev * dev)
52 {
53         int error = 0;
54
55         if (dev == NULL)
56                 return -1;
57
58         switch (file) {
59         case stdin:
60         case stdout:
61         case stderr:
62                 /* Start new device */
63                 if (dev->start) {
64                         error = dev->start();
65                         /* If it's not started dont use it */
66                         if (error < 0)
67                                 break;
68                 }
69
70                 /* Assign the new device (leaving the existing one started) */
71                 stdio_devices[file] = dev;
72
73                 /*
74                  * Update monitor functions
75                  * (to use the console stuff by other applications)
76                  */
77                 switch (file) {
78                 case stdin:
79                         gd->jt[XF_getc] = dev->getc;
80                         gd->jt[XF_tstc] = dev->tstc;
81                         break;
82                 case stdout:
83                         gd->jt[XF_putc] = dev->putc;
84                         gd->jt[XF_puts] = dev->puts;
85                         gd->jt[XF_printf] = printf;
86                         break;
87                 }
88                 break;
89
90         default:                /* Invalid file ID */
91                 error = -1;
92         }
93         return error;
94 }
95
96 #if defined(CONFIG_CONSOLE_MUX)
97 /** Console I/O multiplexing *******************************************/
98
99 static struct stdio_dev *tstcdev;
100 struct stdio_dev **console_devices[MAX_FILES];
101 int cd_count[MAX_FILES];
102
103 /*
104  * This depends on tstc() always being called before getc().
105  * This is guaranteed to be true because this routine is called
106  * only from fgetc() which assures it.
107  * No attempt is made to demultiplex multiple input sources.
108  */
109 static int console_getc(int file)
110 {
111         unsigned char ret;
112
113         /* This is never called with testcdev == NULL */
114         ret = tstcdev->getc();
115         tstcdev = NULL;
116         return ret;
117 }
118
119 static int console_tstc(int file)
120 {
121         int i, ret;
122         struct stdio_dev *dev;
123
124         disable_ctrlc(1);
125         for (i = 0; i < cd_count[file]; i++) {
126                 dev = console_devices[file][i];
127                 if (dev->tstc != NULL) {
128                         ret = dev->tstc();
129                         if (ret > 0) {
130                                 tstcdev = dev;
131                                 disable_ctrlc(0);
132                                 return ret;
133                         }
134                 }
135         }
136         disable_ctrlc(0);
137
138         return 0;
139 }
140
141 static void console_putc(int file, const char c)
142 {
143         int i;
144         struct stdio_dev *dev;
145
146         for (i = 0; i < cd_count[file]; i++) {
147                 dev = console_devices[file][i];
148                 if (dev->putc != NULL)
149                         dev->putc(c);
150         }
151 }
152
153 static void console_puts(int file, const char *s)
154 {
155         int i;
156         struct stdio_dev *dev;
157
158         for (i = 0; i < cd_count[file]; i++) {
159                 dev = console_devices[file][i];
160                 if (dev->puts != NULL)
161                         dev->puts(s);
162         }
163 }
164
165 static inline void console_printdevs(int file)
166 {
167         iomux_printdevs(file);
168 }
169
170 static inline void console_doenv(int file, struct stdio_dev *dev)
171 {
172         iomux_doenv(file, dev->name);
173 }
174 #else
175 static inline int console_getc(int file)
176 {
177         return stdio_devices[file]->getc();
178 }
179
180 static inline int console_tstc(int file)
181 {
182         return stdio_devices[file]->tstc();
183 }
184
185 static inline void console_putc(int file, const char c)
186 {
187         stdio_devices[file]->putc(c);
188 }
189
190 static inline void console_puts(int file, const char *s)
191 {
192         stdio_devices[file]->puts(s);
193 }
194
195 static inline void console_printdevs(int file)
196 {
197         printf("%s\n", stdio_devices[file]->name);
198 }
199
200 static inline void console_doenv(int file, struct stdio_dev *dev)
201 {
202         console_setfile(file, dev);
203 }
204 #endif /* defined(CONFIG_CONSOLE_MUX) */
205
206 /** U-Boot INITIAL CONSOLE-NOT COMPATIBLE FUNCTIONS *************************/
207
208 void serial_printf(const char *fmt, ...)
209 {
210         va_list args;
211         uint i;
212         char printbuffer[CONFIG_SYS_PBSIZE];
213
214         va_start(args, fmt);
215
216         /* For this to work, printbuffer must be larger than
217          * anything we ever want to print.
218          */
219         i = vsprintf(printbuffer, fmt, args);
220         va_end(args);
221
222         serial_puts(printbuffer);
223 }
224
225 int fgetc(int file)
226 {
227         if (file < MAX_FILES) {
228 #if defined(CONFIG_CONSOLE_MUX)
229                 /*
230                  * Effectively poll for input wherever it may be available.
231                  */
232                 for (;;) {
233                         /*
234                          * Upper layer may have already called tstc() so
235                          * check for that first.
236                          */
237                         if (tstcdev != NULL)
238                                 return console_getc(file);
239                         console_tstc(file);
240 #ifdef CONFIG_WATCHDOG
241                         /*
242                          * If the watchdog must be rate-limited then it should
243                          * already be handled in board-specific code.
244                          */
245                          udelay(1);
246 #endif
247                 }
248 #else
249                 return console_getc(file);
250 #endif
251         }
252
253         return -1;
254 }
255
256 int ftstc(int file)
257 {
258         if (file < MAX_FILES)
259                 return console_tstc(file);
260
261         return -1;
262 }
263
264 void fputc(int file, const char c)
265 {
266         if (file < MAX_FILES)
267                 console_putc(file, c);
268 }
269
270 void fputs(int file, const char *s)
271 {
272         if (file < MAX_FILES)
273                 console_puts(file, s);
274 }
275
276 void fprintf(int file, const char *fmt, ...)
277 {
278         va_list args;
279         uint i;
280         char printbuffer[CONFIG_SYS_PBSIZE];
281
282         va_start(args, fmt);
283
284         /* For this to work, printbuffer must be larger than
285          * anything we ever want to print.
286          */
287         i = vsprintf(printbuffer, fmt, args);
288         va_end(args);
289
290         /* Send to desired file */
291         fputs(file, printbuffer);
292 }
293
294 /** U-Boot INITIAL CONSOLE-COMPATIBLE FUNCTION *****************************/
295
296 int getc(void)
297 {
298 #ifdef CONFIG_DISABLE_CONSOLE
299         if (gd->flags & GD_FLG_DISABLE_CONSOLE)
300                 return 0;
301 #endif
302
303         if (gd->flags & GD_FLG_DEVINIT) {
304                 /* Get from the standard input */
305                 return fgetc(stdin);
306         }
307
308         /* Send directly to the handler */
309         return serial_getc();
310 }
311
312 int tstc(void)
313 {
314 #ifdef CONFIG_DISABLE_CONSOLE
315         if (gd->flags & GD_FLG_DISABLE_CONSOLE)
316                 return 0;
317 #endif
318
319         if (gd->flags & GD_FLG_DEVINIT) {
320                 /* Test the standard input */
321                 return ftstc(stdin);
322         }
323
324         /* Send directly to the handler */
325         return serial_tstc();
326 }
327
328 void putc(const char c)
329 {
330 #ifdef CONFIG_SILENT_CONSOLE
331         if (gd->flags & GD_FLG_SILENT)
332                 return;
333 #endif
334
335 #ifdef CONFIG_DISABLE_CONSOLE
336         if (gd->flags & GD_FLG_DISABLE_CONSOLE)
337                 return;
338 #endif
339
340         if (gd->flags & GD_FLG_DEVINIT) {
341                 /* Send to the standard output */
342                 fputc(stdout, c);
343         } else {
344                 /* Send directly to the handler */
345                 serial_putc(c);
346         }
347 }
348
349 void puts(const char *s)
350 {
351 #ifdef CONFIG_SILENT_CONSOLE
352         if (gd->flags & GD_FLG_SILENT)
353                 return;
354 #endif
355
356 #ifdef CONFIG_DISABLE_CONSOLE
357         if (gd->flags & GD_FLG_DISABLE_CONSOLE)
358                 return;
359 #endif
360
361         if (gd->flags & GD_FLG_DEVINIT) {
362                 /* Send to the standard output */
363                 fputs(stdout, s);
364         } else {
365                 /* Send directly to the handler */
366                 serial_puts(s);
367         }
368 }
369
370 void printf(const char *fmt, ...)
371 {
372         va_list args;
373         uint i;
374         char printbuffer[CONFIG_SYS_PBSIZE];
375
376         va_start(args, fmt);
377
378         /* For this to work, printbuffer must be larger than
379          * anything we ever want to print.
380          */
381         i = vsprintf(printbuffer, fmt, args);
382         va_end(args);
383
384         /* Print the string */
385         puts(printbuffer);
386 }
387
388 void vprintf(const char *fmt, va_list args)
389 {
390         uint i;
391         char printbuffer[CONFIG_SYS_PBSIZE];
392
393         /* For this to work, printbuffer must be larger than
394          * anything we ever want to print.
395          */
396         i = vsprintf(printbuffer, fmt, args);
397
398         /* Print the string */
399         puts(printbuffer);
400 }
401
402 /* test if ctrl-c was pressed */
403 static int ctrlc_disabled = 0;  /* see disable_ctrl() */
404 static int ctrlc_was_pressed = 0;
405 int ctrlc(void)
406 {
407         if (!ctrlc_disabled && gd->have_console) {
408                 if (tstc()) {
409                         switch (getc()) {
410                         case 0x03:              /* ^C - Control C */
411                                 ctrlc_was_pressed = 1;
412                                 return 1;
413                         default:
414                                 break;
415                         }
416                 }
417         }
418         return 0;
419 }
420
421 /* pass 1 to disable ctrlc() checking, 0 to enable.
422  * returns previous state
423  */
424 int disable_ctrlc(int disable)
425 {
426         int prev = ctrlc_disabled;      /* save previous state */
427
428         ctrlc_disabled = disable;
429         return prev;
430 }
431
432 int had_ctrlc (void)
433 {
434         return ctrlc_was_pressed;
435 }
436
437 void clear_ctrlc(void)
438 {
439         ctrlc_was_pressed = 0;
440 }
441
442 #ifdef CONFIG_MODEM_SUPPORT_DEBUG
443 char    screen[1024];
444 char *cursor = screen;
445 int once = 0;
446 inline void dbg(const char *fmt, ...)
447 {
448         va_list args;
449         uint    i;
450         char    printbuffer[CONFIG_SYS_PBSIZE];
451
452         if (!once) {
453                 memset(screen, 0, sizeof(screen));
454                 once++;
455         }
456
457         va_start(args, fmt);
458
459         /* For this to work, printbuffer must be larger than
460          * anything we ever want to print.
461          */
462         i = vsprintf(printbuffer, fmt, args);
463         va_end(args);
464
465         if ((screen + sizeof(screen) - 1 - cursor)
466             < strlen(printbuffer) + 1) {
467                 memset(screen, 0, sizeof(screen));
468                 cursor = screen;
469         }
470         sprintf(cursor, printbuffer);
471         cursor += strlen(printbuffer);
472
473 }
474 #else
475 inline void dbg(const char *fmt, ...)
476 {
477 }
478 #endif
479
480 /** U-Boot INIT FUNCTIONS *************************************************/
481
482 struct stdio_dev *search_device(int flags, char *name)
483 {
484         struct stdio_dev *dev;
485
486         dev = stdio_get_by_name(name);
487
488         if (dev && (dev->flags & flags))
489                 return dev;
490
491         return NULL;
492 }
493
494 int console_assign(int file, char *devname)
495 {
496         int flag;
497         struct stdio_dev *dev;
498
499         /* Check for valid file */
500         switch (file) {
501         case stdin:
502                 flag = DEV_FLAGS_INPUT;
503                 break;
504         case stdout:
505         case stderr:
506                 flag = DEV_FLAGS_OUTPUT;
507                 break;
508         default:
509                 return -1;
510         }
511
512         /* Check for valid device name */
513
514         dev = search_device(flag, devname);
515
516         if (dev)
517                 return console_setfile(file, dev);
518
519         return -1;
520 }
521
522 /* Called before relocation - use serial functions */
523 int console_init_f(void)
524 {
525         gd->have_console = 1;
526
527 #ifdef CONFIG_SILENT_CONSOLE
528         if (getenv("silent") != NULL)
529                 gd->flags |= GD_FLG_SILENT;
530 #endif
531
532         return 0;
533 }
534
535 #ifdef CONFIG_SYS_CONSOLE_IS_IN_ENV
536 /* Called after the relocation - use desired console functions */
537 int console_init_r(void)
538 {
539         char *stdinname, *stdoutname, *stderrname;
540         struct stdio_dev *inputdev = NULL, *outputdev = NULL, *errdev = NULL;
541 #ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE
542         int i;
543 #endif /* CONFIG_SYS_CONSOLE_ENV_OVERWRITE */
544 #ifdef CONFIG_CONSOLE_MUX
545         int iomux_err = 0;
546 #endif
547
548         /* set default handlers at first */
549         gd->jt[XF_getc] = serial_getc;
550         gd->jt[XF_tstc] = serial_tstc;
551         gd->jt[XF_putc] = serial_putc;
552         gd->jt[XF_puts] = serial_puts;
553         gd->jt[XF_printf] = serial_printf;
554
555         /* stdin stdout and stderr are in environment */
556         /* scan for it */
557         stdinname  = getenv("stdin");
558         stdoutname = getenv("stdout");
559         stderrname = getenv("stderr");
560
561         if (OVERWRITE_CONSOLE == 0) {   /* if not overwritten by config switch */
562                 inputdev  = search_device(DEV_FLAGS_INPUT,  stdinname);
563                 outputdev = search_device(DEV_FLAGS_OUTPUT, stdoutname);
564                 errdev    = search_device(DEV_FLAGS_OUTPUT, stderrname);
565 #ifdef CONFIG_CONSOLE_MUX
566                 iomux_err = iomux_doenv(stdin, stdinname);
567                 iomux_err += iomux_doenv(stdout, stdoutname);
568                 iomux_err += iomux_doenv(stderr, stderrname);
569                 if (!iomux_err)
570                         /* Successful, so skip all the code below. */
571                         goto done;
572 #endif
573         }
574         /* if the devices are overwritten or not found, use default device */
575         if (inputdev == NULL) {
576                 inputdev  = search_device(DEV_FLAGS_INPUT,  "serial");
577         }
578         if (outputdev == NULL) {
579                 outputdev = search_device(DEV_FLAGS_OUTPUT, "serial");
580         }
581         if (errdev == NULL) {
582                 errdev    = search_device(DEV_FLAGS_OUTPUT, "serial");
583         }
584         /* Initializes output console first */
585         if (outputdev != NULL) {
586                 /* need to set a console if not done above. */
587                 console_doenv(stdout, outputdev);
588         }
589         if (errdev != NULL) {
590                 /* need to set a console if not done above. */
591                 console_doenv(stderr, errdev);
592         }
593         if (inputdev != NULL) {
594                 /* need to set a console if not done above. */
595                 console_doenv(stdin, inputdev);
596         }
597
598 #ifdef CONFIG_CONSOLE_MUX
599 done:
600 #endif
601
602         gd->flags |= GD_FLG_DEVINIT;    /* device initialization completed */
603
604 #ifndef CONFIG_SYS_CONSOLE_INFO_QUIET
605         /* Print information */
606         puts("In:    ");
607         if (stdio_devices[stdin] == NULL) {
608                 puts("No input devices available!\n");
609         } else {
610                 console_printdevs(stdin);
611         }
612
613         puts("Out:   ");
614         if (stdio_devices[stdout] == NULL) {
615                 puts("No output devices available!\n");
616         } else {
617                 console_printdevs(stdout);
618         }
619
620         puts("Err:   ");
621         if (stdio_devices[stderr] == NULL) {
622                 puts("No error devices available!\n");
623         } else {
624                 console_printdevs(stderr);
625         }
626 #endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */
627
628 #ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE
629         /* set the environment variables (will overwrite previous env settings) */
630         for (i = 0; i < 3; i++) {
631                 setenv(stdio_names[i], stdio_devices[i]->name);
632         }
633 #endif /* CONFIG_SYS_CONSOLE_ENV_OVERWRITE */
634
635 #if 0
636         /* If nothing usable installed, use only the initial console */
637         if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
638                 return 0;
639 #endif
640         return 0;
641 }
642
643 #else /* CONFIG_SYS_CONSOLE_IS_IN_ENV */
644
645 /* Called after the relocation - use desired console functions */
646 int console_init_r(void)
647 {
648         struct stdio_dev *inputdev = NULL, *outputdev = NULL;
649         int i;
650         struct list_head *list = stdio_get_list();
651         struct list_head *pos;
652         struct stdio_dev *dev;
653
654 #ifdef CONFIG_SPLASH_SCREEN
655         /*
656          * suppress all output if splash screen is enabled and we have
657          * a bmp to display
658          */
659         if (getenv("splashimage") != NULL)
660                 gd->flags |= GD_FLG_SILENT;
661 #endif
662
663         /* Scan devices looking for input and output devices */
664         list_for_each(pos, list) {
665                 dev = list_entry(pos, struct stdio_dev, list);
666
667                 if ((dev->flags & DEV_FLAGS_INPUT) && (inputdev == NULL)) {
668                         inputdev = dev;
669                 }
670                 if ((dev->flags & DEV_FLAGS_OUTPUT) && (outputdev == NULL)) {
671                         outputdev = dev;
672                 }
673                 if(inputdev && outputdev)
674                         break;
675         }
676
677         /* Initializes output console first */
678         if (outputdev != NULL) {
679                 console_setfile(stdout, outputdev);
680                 console_setfile(stderr, outputdev);
681 #ifdef CONFIG_CONSOLE_MUX
682                 console_devices[stdout][0] = outputdev;
683                 console_devices[stderr][0] = outputdev;
684 #endif
685         }
686
687         /* Initializes input console */
688         if (inputdev != NULL) {
689                 console_setfile(stdin, inputdev);
690 #ifdef CONFIG_CONSOLE_MUX
691                 console_devices[stdin][0] = inputdev;
692 #endif
693         }
694
695         gd->flags |= GD_FLG_DEVINIT;    /* device initialization completed */
696
697 #ifndef CONFIG_SYS_CONSOLE_INFO_QUIET
698         /* Print information */
699         puts("In:    ");
700         if (stdio_devices[stdin] == NULL) {
701                 puts("No input devices available!\n");
702         } else {
703                 printf("%s\n", stdio_devices[stdin]->name);
704         }
705
706         puts("Out:   ");
707         if (stdio_devices[stdout] == NULL) {
708                 puts("No output devices available!\n");
709         } else {
710                 printf("%s\n", stdio_devices[stdout]->name);
711         }
712
713         puts("Err:   ");
714         if (stdio_devices[stderr] == NULL) {
715                 puts("No error devices available!\n");
716         } else {
717                 printf("%s\n", stdio_devices[stderr]->name);
718         }
719 #endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */
720
721         /* Setting environment variables */
722         for (i = 0; i < 3; i++) {
723                 setenv(stdio_names[i], stdio_devices[i]->name);
724         }
725
726 #if 0
727         /* If nothing usable installed, use only the initial console */
728         if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
729                 return 0;
730 #endif
731
732         return 0;
733 }
734
735 #endif /* CONFIG_SYS_CONSOLE_IS_IN_ENV */