191b48c9fSJulius Werner /* 291b48c9fSJulius Werner * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. 391b48c9fSJulius Werner * 491b48c9fSJulius Werner * SPDX-License-Identifier: BSD-3-Clause 591b48c9fSJulius Werner */ 691b48c9fSJulius Werner 791b48c9fSJulius Werner #if MULTI_CONSOLE_API 891b48c9fSJulius Werner 991b48c9fSJulius Werner #include <assert.h> 10*09d40e0eSAntonio Nino Diaz 1191b48c9fSJulius Werner #include <drivers/console.h> 1291b48c9fSJulius Werner 1391b48c9fSJulius Werner console_t *console_list; 1491b48c9fSJulius Werner uint8_t console_state = CONSOLE_FLAG_BOOT; 1591b48c9fSJulius Werner 1691b48c9fSJulius Werner int console_register(console_t *console) 1791b48c9fSJulius Werner { 1891b48c9fSJulius Werner IMPORT_SYM(console_t *, __STACKS_START__, stacks_start) 1991b48c9fSJulius Werner IMPORT_SYM(console_t *, __STACKS_END__, stacks_end) 2091b48c9fSJulius Werner 2191b48c9fSJulius Werner /* Assert that the struct is not on the stack (common mistake). */ 2291b48c9fSJulius Werner assert((console < stacks_start) || (console >= stacks_end)); 2391b48c9fSJulius Werner /* Assert that we won't make a circle in the list. */ 2491b48c9fSJulius Werner assert(!console_is_registered(console)); 2591b48c9fSJulius Werner 2691b48c9fSJulius Werner console->next = console_list; 2791b48c9fSJulius Werner console_list = console; 2891b48c9fSJulius Werner 2991b48c9fSJulius Werner /* Return 1 for convenient tail-calling from console_xxx_register(). */ 3091b48c9fSJulius Werner return 1; 3191b48c9fSJulius Werner } 3291b48c9fSJulius Werner 3391b48c9fSJulius Werner console_t *console_unregister(console_t *to_be_deleted) 3491b48c9fSJulius Werner { 3591b48c9fSJulius Werner console_t **ptr; 3691b48c9fSJulius Werner 3791b48c9fSJulius Werner assert(to_be_deleted != NULL); 3891b48c9fSJulius Werner 3991b48c9fSJulius Werner for (ptr = &console_list; *ptr != NULL; ptr = &(*ptr)->next) 4091b48c9fSJulius Werner if (*ptr == to_be_deleted) { 4191b48c9fSJulius Werner *ptr = (*ptr)->next; 4291b48c9fSJulius Werner return to_be_deleted; 4391b48c9fSJulius Werner } 4491b48c9fSJulius Werner 4591b48c9fSJulius Werner return NULL; 4691b48c9fSJulius Werner } 4791b48c9fSJulius Werner 4891b48c9fSJulius Werner int console_is_registered(console_t *to_find) 4991b48c9fSJulius Werner { 5091b48c9fSJulius Werner console_t *console; 5191b48c9fSJulius Werner 5291b48c9fSJulius Werner assert(to_find != NULL); 5391b48c9fSJulius Werner 5491b48c9fSJulius Werner for (console = console_list; console != NULL; console = console->next) 5591b48c9fSJulius Werner if (console == to_find) 5691b48c9fSJulius Werner return 1; 5791b48c9fSJulius Werner 5891b48c9fSJulius Werner return 0; 5991b48c9fSJulius Werner } 6091b48c9fSJulius Werner 6191b48c9fSJulius Werner void console_switch_state(unsigned int new_state) 6291b48c9fSJulius Werner { 6391b48c9fSJulius Werner console_state = new_state; 6491b48c9fSJulius Werner } 6591b48c9fSJulius Werner 6691b48c9fSJulius Werner void console_set_scope(console_t *console, unsigned int scope) 6791b48c9fSJulius Werner { 6891b48c9fSJulius Werner assert(console != NULL); 6991b48c9fSJulius Werner 7091b48c9fSJulius Werner console->flags = (console->flags & ~CONSOLE_FLAG_SCOPE_MASK) | scope; 7191b48c9fSJulius Werner } 7291b48c9fSJulius Werner 7391b48c9fSJulius Werner int console_putc(int c) 7491b48c9fSJulius Werner { 7591b48c9fSJulius Werner int err = ERROR_NO_VALID_CONSOLE; 7691b48c9fSJulius Werner console_t *console; 7791b48c9fSJulius Werner 7891b48c9fSJulius Werner for (console = console_list; console != NULL; console = console->next) 7991b48c9fSJulius Werner if (console->flags & console_state) { 8091b48c9fSJulius Werner int ret = console->putc(c, console); 8191b48c9fSJulius Werner if ((err == ERROR_NO_VALID_CONSOLE) || (ret < err)) 8291b48c9fSJulius Werner err = ret; 8391b48c9fSJulius Werner } 8491b48c9fSJulius Werner 8591b48c9fSJulius Werner return err; 8691b48c9fSJulius Werner } 8791b48c9fSJulius Werner 8891b48c9fSJulius Werner int console_getc(void) 8991b48c9fSJulius Werner { 9091b48c9fSJulius Werner int err = ERROR_NO_VALID_CONSOLE; 9191b48c9fSJulius Werner console_t *console; 9291b48c9fSJulius Werner 9391b48c9fSJulius Werner do { /* Keep polling while at least one console works correctly. */ 9491b48c9fSJulius Werner for (console = console_list; console != NULL; 9591b48c9fSJulius Werner console = console->next) 9691b48c9fSJulius Werner if (console->flags & console_state) { 9791b48c9fSJulius Werner int ret = console->getc(console); 9891b48c9fSJulius Werner if (ret >= 0) 9991b48c9fSJulius Werner return ret; 10091b48c9fSJulius Werner if (err != ERROR_NO_PENDING_CHAR) 10191b48c9fSJulius Werner err = ret; 10291b48c9fSJulius Werner } 10391b48c9fSJulius Werner } while (err == ERROR_NO_PENDING_CHAR); 10491b48c9fSJulius Werner 10591b48c9fSJulius Werner return err; 10691b48c9fSJulius Werner } 10791b48c9fSJulius Werner 10891b48c9fSJulius Werner int console_flush(void) 10991b48c9fSJulius Werner { 11091b48c9fSJulius Werner int err = ERROR_NO_VALID_CONSOLE; 11191b48c9fSJulius Werner console_t *console; 11291b48c9fSJulius Werner 11391b48c9fSJulius Werner for (console = console_list; console != NULL; console = console->next) 11491b48c9fSJulius Werner if (console->flags & console_state) { 11591b48c9fSJulius Werner int ret = console->flush(console); 11691b48c9fSJulius Werner if ((err == ERROR_NO_VALID_CONSOLE) || (ret < err)) 11791b48c9fSJulius Werner err = ret; 11891b48c9fSJulius Werner } 11991b48c9fSJulius Werner 12091b48c9fSJulius Werner return err; 12191b48c9fSJulius Werner } 12291b48c9fSJulius Werner 12391b48c9fSJulius Werner #endif /* MULTI_CONSOLE_API */ 124