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