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