18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * A udbg backend which logs messages and reads input from in memory 48c2ecf20Sopenharmony_ci * buffers. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * The console output can be read from memcons_output which is a 78c2ecf20Sopenharmony_ci * circular buffer whose next write position is stored in memcons.output_pos. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Input may be passed by writing into the memcons_input buffer when it is 108c2ecf20Sopenharmony_ci * empty. The input buffer is empty when both input_pos == input_start and 118c2ecf20Sopenharmony_ci * *input_start == '\0'. 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * Copyright (C) 2003-2005 Anton Blanchard and Milton Miller, IBM Corp 148c2ecf20Sopenharmony_ci * Copyright (C) 2013 Alistair Popple, IBM Corp 158c2ecf20Sopenharmony_ci */ 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include <linux/kernel.h> 188c2ecf20Sopenharmony_ci#include <asm/barrier.h> 198c2ecf20Sopenharmony_ci#include <asm/page.h> 208c2ecf20Sopenharmony_ci#include <asm/processor.h> 218c2ecf20Sopenharmony_ci#include <asm/udbg.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistruct memcons { 248c2ecf20Sopenharmony_ci char *output_start; 258c2ecf20Sopenharmony_ci char *output_pos; 268c2ecf20Sopenharmony_ci char *output_end; 278c2ecf20Sopenharmony_ci char *input_start; 288c2ecf20Sopenharmony_ci char *input_pos; 298c2ecf20Sopenharmony_ci char *input_end; 308c2ecf20Sopenharmony_ci}; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cistatic char memcons_output[CONFIG_PPC_MEMCONS_OUTPUT_SIZE]; 338c2ecf20Sopenharmony_cistatic char memcons_input[CONFIG_PPC_MEMCONS_INPUT_SIZE]; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistruct memcons memcons = { 368c2ecf20Sopenharmony_ci .output_start = memcons_output, 378c2ecf20Sopenharmony_ci .output_pos = memcons_output, 388c2ecf20Sopenharmony_ci .output_end = &memcons_output[CONFIG_PPC_MEMCONS_OUTPUT_SIZE], 398c2ecf20Sopenharmony_ci .input_start = memcons_input, 408c2ecf20Sopenharmony_ci .input_pos = memcons_input, 418c2ecf20Sopenharmony_ci .input_end = &memcons_input[CONFIG_PPC_MEMCONS_INPUT_SIZE], 428c2ecf20Sopenharmony_ci}; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_civoid memcons_putc(char c) 458c2ecf20Sopenharmony_ci{ 468c2ecf20Sopenharmony_ci char *new_output_pos; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci *memcons.output_pos = c; 498c2ecf20Sopenharmony_ci wmb(); 508c2ecf20Sopenharmony_ci new_output_pos = memcons.output_pos + 1; 518c2ecf20Sopenharmony_ci if (new_output_pos >= memcons.output_end) 528c2ecf20Sopenharmony_ci new_output_pos = memcons.output_start; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci memcons.output_pos = new_output_pos; 558c2ecf20Sopenharmony_ci} 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ciint memcons_getc_poll(void) 588c2ecf20Sopenharmony_ci{ 598c2ecf20Sopenharmony_ci char c; 608c2ecf20Sopenharmony_ci char *new_input_pos; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci if (*memcons.input_pos) { 638c2ecf20Sopenharmony_ci c = *memcons.input_pos; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci new_input_pos = memcons.input_pos + 1; 668c2ecf20Sopenharmony_ci if (new_input_pos >= memcons.input_end) 678c2ecf20Sopenharmony_ci new_input_pos = memcons.input_start; 688c2ecf20Sopenharmony_ci else if (*new_input_pos == '\0') 698c2ecf20Sopenharmony_ci new_input_pos = memcons.input_start; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci *memcons.input_pos = '\0'; 728c2ecf20Sopenharmony_ci wmb(); 738c2ecf20Sopenharmony_ci memcons.input_pos = new_input_pos; 748c2ecf20Sopenharmony_ci return c; 758c2ecf20Sopenharmony_ci } 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci return -1; 788c2ecf20Sopenharmony_ci} 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ciint memcons_getc(void) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci int c; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci while (1) { 858c2ecf20Sopenharmony_ci c = memcons_getc_poll(); 868c2ecf20Sopenharmony_ci if (c == -1) 878c2ecf20Sopenharmony_ci cpu_relax(); 888c2ecf20Sopenharmony_ci else 898c2ecf20Sopenharmony_ci break; 908c2ecf20Sopenharmony_ci } 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci return c; 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_civoid udbg_init_memcons(void) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci udbg_putc = memcons_putc; 988c2ecf20Sopenharmony_ci udbg_getc = memcons_getc; 998c2ecf20Sopenharmony_ci udbg_getc_poll = memcons_getc_poll; 1008c2ecf20Sopenharmony_ci} 101