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