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