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