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