blob: d9eba7f020e017cff67244b0a694a2edcc1d0d75 [file] [log] [blame]
Julius Werner03020da2018-11-27 22:10:56 -08001/*
Joel Hutton698d8352019-01-15 15:40:18 +00002 * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
Julius Werner03020da2018-11-27 22:10:56 -08003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Julius Werner03020da2018-11-27 22:10:56 -08007#include <assert.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00008
Julius Werner03020da2018-11-27 22:10:56 -08009#include <drivers/console.h>
10
11console_t *console_list;
12uint8_t console_state = CONSOLE_FLAG_BOOT;
13
Ambroise Vincenta88a35d2019-02-14 09:48:21 +000014IMPORT_SYM(console_t *, __STACKS_START__, stacks_start)
15IMPORT_SYM(console_t *, __STACKS_END__, stacks_end)
16
Julius Werner03020da2018-11-27 22:10:56 -080017int console_register(console_t *console)
18{
Julius Werner03020da2018-11-27 22:10:56 -080019 /* Assert that the struct is not on the stack (common mistake). */
20 assert((console < stacks_start) || (console >= stacks_end));
Ambroise Vincent29d5c382019-04-18 11:36:42 +010021
22 /* Check that we won't make a circle in the list. */
23 if (console_is_registered(console) == 1)
24 return 1;
Julius Werner03020da2018-11-27 22:10:56 -080025
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
33console_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
48int 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
61void console_switch_state(unsigned int new_state)
62{
63 console_state = new_state;
64}
65
66void 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
73int 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)
Joel Hutton698d8352019-01-15 15:40:18 +000079 if ((console->flags & console_state) && console->putc) {
Julius Werner03020da2018-11-27 22:10:56 -080080 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
88int 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)
Joel Hutton698d8352019-01-15 15:40:18 +000096 if ((console->flags & console_state) && console->getc) {
Julius Werner03020da2018-11-27 22:10:56 -080097 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
108int 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)
Joel Hutton698d8352019-01-15 15:40:18 +0000114 if ((console->flags & console_state) && console->flush) {
Julius Werner03020da2018-11-27 22:10:56 -0800115 int ret = console->flush(console);
116 if ((err == ERROR_NO_VALID_CONSOLE) || (ret < err))
117 err = ret;
118 }
119
120 return err;
121}