xref: /rk3399_ARM-atf/drivers/console/multi_console.c (revision 91b48c9f8f44db91ae73635cc543fb89d292a6f7)
1*91b48c9fSJulius Werner /*
2*91b48c9fSJulius Werner  * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3*91b48c9fSJulius Werner  *
4*91b48c9fSJulius Werner  * SPDX-License-Identifier: BSD-3-Clause
5*91b48c9fSJulius Werner  */
6*91b48c9fSJulius Werner 
7*91b48c9fSJulius Werner #if MULTI_CONSOLE_API
8*91b48c9fSJulius Werner 
9*91b48c9fSJulius Werner #include <assert.h>
10*91b48c9fSJulius Werner #include <drivers/console.h>
11*91b48c9fSJulius Werner 
12*91b48c9fSJulius Werner console_t *console_list;
13*91b48c9fSJulius Werner uint8_t console_state = CONSOLE_FLAG_BOOT;
14*91b48c9fSJulius Werner 
15*91b48c9fSJulius Werner int console_register(console_t *console)
16*91b48c9fSJulius Werner {
17*91b48c9fSJulius Werner 	IMPORT_SYM(console_t *, __STACKS_START__, stacks_start)
18*91b48c9fSJulius Werner 	IMPORT_SYM(console_t *, __STACKS_END__, stacks_end)
19*91b48c9fSJulius Werner 
20*91b48c9fSJulius Werner 	/* Assert that the struct is not on the stack (common mistake). */
21*91b48c9fSJulius Werner 	assert((console < stacks_start) || (console >= stacks_end));
22*91b48c9fSJulius Werner 	/* Assert that we won't make a circle in the list. */
23*91b48c9fSJulius Werner 	assert(!console_is_registered(console));
24*91b48c9fSJulius Werner 
25*91b48c9fSJulius Werner 	console->next = console_list;
26*91b48c9fSJulius Werner 	console_list = console;
27*91b48c9fSJulius Werner 
28*91b48c9fSJulius Werner 	/* Return 1 for convenient tail-calling from console_xxx_register(). */
29*91b48c9fSJulius Werner 	return 1;
30*91b48c9fSJulius Werner }
31*91b48c9fSJulius Werner 
32*91b48c9fSJulius Werner console_t *console_unregister(console_t *to_be_deleted)
33*91b48c9fSJulius Werner {
34*91b48c9fSJulius Werner 	console_t **ptr;
35*91b48c9fSJulius Werner 
36*91b48c9fSJulius Werner 	assert(to_be_deleted != NULL);
37*91b48c9fSJulius Werner 
38*91b48c9fSJulius Werner 	for (ptr = &console_list; *ptr != NULL; ptr = &(*ptr)->next)
39*91b48c9fSJulius Werner 		if (*ptr == to_be_deleted) {
40*91b48c9fSJulius Werner 			*ptr = (*ptr)->next;
41*91b48c9fSJulius Werner 			return to_be_deleted;
42*91b48c9fSJulius Werner 		}
43*91b48c9fSJulius Werner 
44*91b48c9fSJulius Werner 	return NULL;
45*91b48c9fSJulius Werner }
46*91b48c9fSJulius Werner 
47*91b48c9fSJulius Werner int console_is_registered(console_t *to_find)
48*91b48c9fSJulius Werner {
49*91b48c9fSJulius Werner 	console_t *console;
50*91b48c9fSJulius Werner 
51*91b48c9fSJulius Werner 	assert(to_find != NULL);
52*91b48c9fSJulius Werner 
53*91b48c9fSJulius Werner 	for (console = console_list; console != NULL; console = console->next)
54*91b48c9fSJulius Werner 		if (console == to_find)
55*91b48c9fSJulius Werner 			return 1;
56*91b48c9fSJulius Werner 
57*91b48c9fSJulius Werner 	return 0;
58*91b48c9fSJulius Werner }
59*91b48c9fSJulius Werner 
60*91b48c9fSJulius Werner void console_switch_state(unsigned int new_state)
61*91b48c9fSJulius Werner {
62*91b48c9fSJulius Werner 	console_state = new_state;
63*91b48c9fSJulius Werner }
64*91b48c9fSJulius Werner 
65*91b48c9fSJulius Werner void console_set_scope(console_t *console, unsigned int scope)
66*91b48c9fSJulius Werner {
67*91b48c9fSJulius Werner 	assert(console != NULL);
68*91b48c9fSJulius Werner 
69*91b48c9fSJulius Werner 	console->flags = (console->flags & ~CONSOLE_FLAG_SCOPE_MASK) | scope;
70*91b48c9fSJulius Werner }
71*91b48c9fSJulius Werner 
72*91b48c9fSJulius Werner int console_putc(int c)
73*91b48c9fSJulius Werner {
74*91b48c9fSJulius Werner 	int err = ERROR_NO_VALID_CONSOLE;
75*91b48c9fSJulius Werner 	console_t *console;
76*91b48c9fSJulius Werner 
77*91b48c9fSJulius Werner 	for (console = console_list; console != NULL; console = console->next)
78*91b48c9fSJulius Werner 		if (console->flags & console_state) {
79*91b48c9fSJulius Werner 			int ret = console->putc(c, console);
80*91b48c9fSJulius Werner 			if ((err == ERROR_NO_VALID_CONSOLE) || (ret < err))
81*91b48c9fSJulius Werner 				err = ret;
82*91b48c9fSJulius Werner 		}
83*91b48c9fSJulius Werner 
84*91b48c9fSJulius Werner 	return err;
85*91b48c9fSJulius Werner }
86*91b48c9fSJulius Werner 
87*91b48c9fSJulius Werner int console_getc(void)
88*91b48c9fSJulius Werner {
89*91b48c9fSJulius Werner 	int err = ERROR_NO_VALID_CONSOLE;
90*91b48c9fSJulius Werner 	console_t *console;
91*91b48c9fSJulius Werner 
92*91b48c9fSJulius Werner 	do {	/* Keep polling while at least one console works correctly. */
93*91b48c9fSJulius Werner 		for (console = console_list; console != NULL;
94*91b48c9fSJulius Werner 		     console = console->next)
95*91b48c9fSJulius Werner 			if (console->flags & console_state) {
96*91b48c9fSJulius Werner 				int ret = console->getc(console);
97*91b48c9fSJulius Werner 				if (ret >= 0)
98*91b48c9fSJulius Werner 					return ret;
99*91b48c9fSJulius Werner 				if (err != ERROR_NO_PENDING_CHAR)
100*91b48c9fSJulius Werner 					err = ret;
101*91b48c9fSJulius Werner 			}
102*91b48c9fSJulius Werner 	} while (err == ERROR_NO_PENDING_CHAR);
103*91b48c9fSJulius Werner 
104*91b48c9fSJulius Werner 	return err;
105*91b48c9fSJulius Werner }
106*91b48c9fSJulius Werner 
107*91b48c9fSJulius Werner int console_flush(void)
108*91b48c9fSJulius Werner {
109*91b48c9fSJulius Werner 	int err = ERROR_NO_VALID_CONSOLE;
110*91b48c9fSJulius Werner 	console_t *console;
111*91b48c9fSJulius Werner 
112*91b48c9fSJulius Werner 	for (console = console_list; console != NULL; console = console->next)
113*91b48c9fSJulius Werner 		if (console->flags & console_state) {
114*91b48c9fSJulius Werner 			int ret = console->flush(console);
115*91b48c9fSJulius Werner 			if ((err == ERROR_NO_VALID_CONSOLE) || (ret < err))
116*91b48c9fSJulius Werner 				err = ret;
117*91b48c9fSJulius Werner 		}
118*91b48c9fSJulius Werner 
119*91b48c9fSJulius Werner 	return err;
120*91b48c9fSJulius Werner }
121*91b48c9fSJulius Werner 
122*91b48c9fSJulius Werner #endif	/* MULTI_CONSOLE_API */
123