xref: /rk3399_ARM-atf/drivers/console/multi_console.c (revision 831b0e9824e6c7cb07308830c12977acb79156c7)
191b48c9fSJulius Werner /*
2466bb285SZelalem  * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
391b48c9fSJulius Werner  *
491b48c9fSJulius Werner  * SPDX-License-Identifier: BSD-3-Clause
591b48c9fSJulius Werner  */
691b48c9fSJulius Werner 
791b48c9fSJulius Werner #include <assert.h>
809d40e0eSAntonio Nino Diaz 
991b48c9fSJulius Werner #include <drivers/console.h>
1091b48c9fSJulius Werner 
1191b48c9fSJulius Werner console_t *console_list;
1291b48c9fSJulius Werner uint8_t console_state = CONSOLE_FLAG_BOOT;
1391b48c9fSJulius Werner 
1491b48c9fSJulius Werner IMPORT_SYM(console_t *, __STACKS_START__, stacks_start)
1591b48c9fSJulius Werner IMPORT_SYM(console_t *, __STACKS_END__, stacks_end)
1691b48c9fSJulius Werner 
17bde2836fSAmbroise Vincent int console_register(console_t *console)
18bde2836fSAmbroise Vincent {
1991b48c9fSJulius Werner 	/* Assert that the struct is not on the stack (common mistake). */
2091b48c9fSJulius Werner 	assert((console < stacks_start) || (console >= stacks_end));
2171892ca3SAmbroise Vincent 
2271892ca3SAmbroise Vincent 	/* Check that we won't make a circle in the list. */
2371892ca3SAmbroise Vincent 	if (console_is_registered(console) == 1)
2471892ca3SAmbroise Vincent 		return 1;
2591b48c9fSJulius Werner 
2691b48c9fSJulius Werner 	console->next = console_list;
2791b48c9fSJulius Werner 	console_list = console;
2891b48c9fSJulius Werner 
2991b48c9fSJulius Werner 	/* Return 1 for convenient tail-calling from console_xxx_register(). */
3091b48c9fSJulius Werner 	return 1;
3191b48c9fSJulius Werner }
3291b48c9fSJulius Werner 
3391b48c9fSJulius Werner console_t *console_unregister(console_t *to_be_deleted)
3491b48c9fSJulius Werner {
3591b48c9fSJulius Werner 	console_t **ptr;
3691b48c9fSJulius Werner 
3791b48c9fSJulius Werner 	assert(to_be_deleted != NULL);
3891b48c9fSJulius Werner 
3991b48c9fSJulius Werner 	for (ptr = &console_list; *ptr != NULL; ptr = &(*ptr)->next)
4091b48c9fSJulius Werner 		if (*ptr == to_be_deleted) {
4191b48c9fSJulius Werner 			*ptr = (*ptr)->next;
4291b48c9fSJulius Werner 			return to_be_deleted;
4391b48c9fSJulius Werner 		}
4491b48c9fSJulius Werner 
4591b48c9fSJulius Werner 	return NULL;
4691b48c9fSJulius Werner }
4791b48c9fSJulius Werner 
4891b48c9fSJulius Werner int console_is_registered(console_t *to_find)
4991b48c9fSJulius Werner {
5091b48c9fSJulius Werner 	console_t *console;
5191b48c9fSJulius Werner 
5291b48c9fSJulius Werner 	assert(to_find != NULL);
5391b48c9fSJulius Werner 
5491b48c9fSJulius Werner 	for (console = console_list; console != NULL; console = console->next)
5591b48c9fSJulius Werner 		if (console == to_find)
5691b48c9fSJulius Werner 			return 1;
5791b48c9fSJulius Werner 
5891b48c9fSJulius Werner 	return 0;
5991b48c9fSJulius Werner }
6091b48c9fSJulius Werner 
6191b48c9fSJulius Werner void console_switch_state(unsigned int new_state)
6291b48c9fSJulius Werner {
6391b48c9fSJulius Werner 	console_state = new_state;
6491b48c9fSJulius Werner }
6591b48c9fSJulius Werner 
6691b48c9fSJulius Werner void console_set_scope(console_t *console, unsigned int scope)
6791b48c9fSJulius Werner {
6891b48c9fSJulius Werner 	assert(console != NULL);
6991b48c9fSJulius Werner 
7091b48c9fSJulius Werner 	console->flags = (console->flags & ~CONSOLE_FLAG_SCOPE_MASK) | scope;
7191b48c9fSJulius Werner }
7291b48c9fSJulius Werner 
73f51df475SMasahiro Yamada static int do_putc(int c, console_t *console)
74f51df475SMasahiro Yamada {
75f51df475SMasahiro Yamada 	int ret;
76f51df475SMasahiro Yamada 
77f51df475SMasahiro Yamada 	if ((c == '\n') &&
78f51df475SMasahiro Yamada 	    ((console->flags & CONSOLE_FLAG_TRANSLATE_CRLF) != 0)) {
79f51df475SMasahiro Yamada 		ret = console->putc('\r', console);
80f51df475SMasahiro Yamada 		if (ret < 0)
81f51df475SMasahiro Yamada 			return ret;
82f51df475SMasahiro Yamada 	}
83f51df475SMasahiro Yamada 
84f51df475SMasahiro Yamada 	return console->putc(c, console);
85f51df475SMasahiro Yamada }
86f51df475SMasahiro Yamada 
8791b48c9fSJulius Werner int console_putc(int c)
8891b48c9fSJulius Werner {
8991b48c9fSJulius Werner 	int err = ERROR_NO_VALID_CONSOLE;
9091b48c9fSJulius Werner 	console_t *console;
9191b48c9fSJulius Werner 
9291b48c9fSJulius Werner 	for (console = console_list; console != NULL; console = console->next)
93466bb285SZelalem 		if ((console->flags & console_state) && (console->putc != NULL)) {
94f51df475SMasahiro Yamada 			int ret = do_putc(c, console);
9591b48c9fSJulius Werner 			if ((err == ERROR_NO_VALID_CONSOLE) || (ret < err))
9691b48c9fSJulius Werner 				err = ret;
9791b48c9fSJulius Werner 		}
9891b48c9fSJulius Werner 
9991b48c9fSJulius Werner 	return err;
10091b48c9fSJulius Werner }
10191b48c9fSJulius Werner 
10291b48c9fSJulius Werner int console_getc(void)
10391b48c9fSJulius Werner {
10491b48c9fSJulius Werner 	int err = ERROR_NO_VALID_CONSOLE;
10591b48c9fSJulius Werner 	console_t *console;
10691b48c9fSJulius Werner 
10791b48c9fSJulius Werner 	do {	/* Keep polling while at least one console works correctly. */
10891b48c9fSJulius Werner 		for (console = console_list; console != NULL;
10991b48c9fSJulius Werner 		     console = console->next)
110466bb285SZelalem 			if ((console->flags & console_state) && (console->getc != NULL)) {
11191b48c9fSJulius Werner 				int ret = console->getc(console);
11291b48c9fSJulius Werner 				if (ret >= 0)
11391b48c9fSJulius Werner 					return ret;
11491b48c9fSJulius Werner 				if (err != ERROR_NO_PENDING_CHAR)
11591b48c9fSJulius Werner 					err = ret;
11691b48c9fSJulius Werner 			}
11791b48c9fSJulius Werner 	} while (err == ERROR_NO_PENDING_CHAR);
11891b48c9fSJulius Werner 
11991b48c9fSJulius Werner 	return err;
12091b48c9fSJulius Werner }
12191b48c9fSJulius Werner 
122*831b0e98SJimmy Brisson void console_flush(void)
12391b48c9fSJulius Werner {
12491b48c9fSJulius Werner 	console_t *console;
12591b48c9fSJulius Werner 
12691b48c9fSJulius Werner 	for (console = console_list; console != NULL; console = console->next)
127466bb285SZelalem 		if ((console->flags & console_state) && (console->flush != NULL)) {
128*831b0e98SJimmy Brisson 			console->flush(console);
12991b48c9fSJulius Werner 		}
13091b48c9fSJulius Werner }
131