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