DHCP regression on 2009-06
[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 void stdio_print_current_devices(void)
536 {
537 #ifdef CONFIG_SYS_CONSOLE_INFO_QUIET
538         /* Print information */
539         puts("In:    ");
540         if (stdio_devices[stdin] == NULL) {
541                 puts("No input devices available!\n");
542         } else {
543                 printf ("%s\n", stdio_devices[stdin]->name);
544         }
545
546         puts("Out:   ");
547         if (stdio_devices[stdout] == NULL) {
548                 puts("No output devices available!\n");
549         } else {
550                 printf ("%s\n", stdio_devices[stdout]->name);
551         }
552
553         puts("Err:   ");
554         if (stdio_devices[stderr] == NULL) {
555                 puts("No error devices available!\n");
556         } else {
557                 printf ("%s\n", stdio_devices[stderr]->name);
558         }
559 #endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */
560 }
561
562 #ifdef CONFIG_SYS_CONSOLE_IS_IN_ENV
563 /* Called after the relocation - use desired console functions */
564 int console_init_r(void)
565 {
566         char *stdinname, *stdoutname, *stderrname;
567         struct stdio_dev *inputdev = NULL, *outputdev = NULL, *errdev = NULL;
568 #ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE
569         int i;
570 #endif /* CONFIG_SYS_CONSOLE_ENV_OVERWRITE */
571 #ifdef CONFIG_CONSOLE_MUX
572         int iomux_err = 0;
573 #endif
574
575         /* set default handlers at first */
576         gd->jt[XF_getc] = serial_getc;
577         gd->jt[XF_tstc] = serial_tstc;
578         gd->jt[XF_putc] = serial_putc;
579         gd->jt[XF_puts] = serial_puts;
580         gd->jt[XF_printf] = serial_printf;
581
582         /* stdin stdout and stderr are in environment */
583         /* scan for it */
584         stdinname  = getenv("stdin");
585         stdoutname = getenv("stdout");
586         stderrname = getenv("stderr");
587
588         if (OVERWRITE_CONSOLE == 0) {   /* if not overwritten by config switch */
589                 inputdev  = search_device(DEV_FLAGS_INPUT,  stdinname);
590                 outputdev = search_device(DEV_FLAGS_OUTPUT, stdoutname);
591                 errdev    = search_device(DEV_FLAGS_OUTPUT, stderrname);
592 #ifdef CONFIG_CONSOLE_MUX
593                 iomux_err = iomux_doenv(stdin, stdinname);
594                 iomux_err += iomux_doenv(stdout, stdoutname);
595                 iomux_err += iomux_doenv(stderr, stderrname);
596                 if (!iomux_err)
597                         /* Successful, so skip all the code below. */
598                         goto done;
599 #endif
600         }
601         /* if the devices are overwritten or not found, use default device */
602         if (inputdev == NULL) {
603                 inputdev  = search_device(DEV_FLAGS_INPUT,  "serial");
604         }
605         if (outputdev == NULL) {
606                 outputdev = search_device(DEV_FLAGS_OUTPUT, "serial");
607         }
608         if (errdev == NULL) {
609                 errdev    = search_device(DEV_FLAGS_OUTPUT, "serial");
610         }
611         /* Initializes output console first */
612         if (outputdev != NULL) {
613                 /* need to set a console if not done above. */
614                 console_doenv(stdout, outputdev);
615         }
616         if (errdev != NULL) {
617                 /* need to set a console if not done above. */
618                 console_doenv(stderr, errdev);
619         }
620         if (inputdev != NULL) {
621                 /* need to set a console if not done above. */
622                 console_doenv(stdin, inputdev);
623         }
624
625 #ifdef CONFIG_CONSOLE_MUX
626 done:
627 #endif
628
629         gd->flags |= GD_FLG_DEVINIT;    /* device initialization completed */
630
631         stdio_print_current_devices();
632
633 #ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE
634         /* set the environment variables (will overwrite previous env settings) */
635         for (i = 0; i < 3; i++) {
636                 setenv(stdio_names[i], stdio_devices[i]->name);
637         }
638 #endif /* CONFIG_SYS_CONSOLE_ENV_OVERWRITE */
639
640 #if 0
641         /* If nothing usable installed, use only the initial console */
642         if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
643                 return 0;
644 #endif
645         return 0;
646 }
647
648 #else /* CONFIG_SYS_CONSOLE_IS_IN_ENV */
649
650 /* Called after the relocation - use desired console functions */
651 int console_init_r(void)
652 {
653         struct stdio_dev *inputdev = NULL, *outputdev = NULL;
654         int i;
655         struct list_head *list = stdio_get_list();
656         struct list_head *pos;
657         struct stdio_dev *dev;
658
659 #ifdef CONFIG_SPLASH_SCREEN
660         /*
661          * suppress all output if splash screen is enabled and we have
662          * a bmp to display
663          */
664         if (getenv("splashimage") != NULL)
665                 gd->flags |= GD_FLG_SILENT;
666 #endif
667
668         /* Scan devices looking for input and output devices */
669         list_for_each(pos, list) {
670                 dev = list_entry(pos, struct stdio_dev, list);
671
672                 if ((dev->flags & DEV_FLAGS_INPUT) && (inputdev == NULL)) {
673                         inputdev = dev;
674                 }
675                 if ((dev->flags & DEV_FLAGS_OUTPUT) && (outputdev == NULL)) {
676                         outputdev = dev;
677                 }
678                 if(inputdev && outputdev)
679                         break;
680         }
681
682         /* Initializes output console first */
683         if (outputdev != NULL) {
684                 console_setfile(stdout, outputdev);
685                 console_setfile(stderr, outputdev);
686 #ifdef CONFIG_CONSOLE_MUX
687                 console_devices[stdout][0] = outputdev;
688                 console_devices[stderr][0] = outputdev;
689 #endif
690         }
691
692         /* Initializes input console */
693         if (inputdev != NULL) {
694                 console_setfile(stdin, inputdev);
695 #ifdef CONFIG_CONSOLE_MUX
696                 console_devices[stdin][0] = inputdev;
697 #endif
698         }
699
700         gd->flags |= GD_FLG_DEVINIT;    /* device initialization completed */
701
702         stdio_print_current_devices();
703
704         /* Setting environment variables */
705         for (i = 0; i < 3; i++) {
706                 setenv(stdio_names[i], stdio_devices[i]->name);
707         }
708
709 #if 0
710         /* If nothing usable installed, use only the initial console */
711         if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
712                 return 0;
713 #endif
714
715         return 0;
716 }
717
718 #endif /* CONFIG_SYS_CONSOLE_IS_IN_ENV */