From f910171deda0933e506cf3ffc216ee8daa418c24 Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 16 Aug 2011 15:41:46 +0200 Subject: corrected spelling mistake and added 2 new papers for gsm specs --- Src/osmoconbb/src/target/firmware/lib/console.c | 190 ++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 Src/osmoconbb/src/target/firmware/lib/console.c (limited to 'Src/osmoconbb/src/target/firmware/lib/console.c') diff --git a/Src/osmoconbb/src/target/firmware/lib/console.c b/Src/osmoconbb/src/target/firmware/lib/console.c new file mode 100644 index 0000000..7135ae2 --- /dev/null +++ b/Src/osmoconbb/src/target/firmware/lib/console.c @@ -0,0 +1,190 @@ +/* Ringbuffer based serial console layer, imported from OpenPCD */ + +/* (C) 2006-2010 by Harald Welte + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include +#include +#include + +#include + +struct cons { + char buf[CONS_RB_SIZE]; + char *next_inbyte; + char *next_outbyte; + int initialized; +}; +static struct cons cons; + +void cons_init(void) +{ + memset(cons.buf, 0, sizeof(cons.buf)); + cons.next_inbyte = &cons.buf[0]; + cons.next_outbyte = &cons.buf[0]; + cons.initialized = 1; +} + +/* determine how many bytes are left in the ringbuffer without overwriting + bytes that haven't been written to the console yet */ +static int __cons_rb_space(void) +{ + if (cons.next_inbyte == cons.next_outbyte) + return sizeof(cons.buf)-1; + else if (cons.next_outbyte > cons.next_inbyte) + return (cons.next_outbyte - cons.next_inbyte) -1; + else + return sizeof(cons.buf) - 1 - (cons.next_inbyte - cons.next_outbyte); +} + +/* pull one char out of debug ring buffer */ +static int cons_rb_pull(char *ret) +{ + unsigned long flags; + + local_irq_save(flags); + + if (cons.next_outbyte == cons.next_inbyte) { + local_irq_restore(flags); + return -1; + } + + *ret = *cons.next_outbyte; + + cons.next_outbyte++; + if (cons.next_outbyte >= &cons.buf[0]+sizeof(cons.buf)) { + cons.next_outbyte = &cons.buf[0]; + } +#if 0 + else if (cons.next_outbyte > &cons.buf[0]+sizeof(cons.buf)) { + cons.next_outbyte -= sizeof(cons.buf); + } +#endif + + local_irq_restore(flags); + + return 0; +} + +/* returns if everything was flushed (1) or if there's more to flush (0) */ +static void __rb_flush_wait(void) +{ + char ch; + while (cons_rb_pull(&ch) >= 0) + uart_putchar_wait(CONS_UART_NR, ch); +} + +/* returns if everything was flushed (1) or if there's more to flush (0) */ +static int __rb_flush(void) +{ + while (!uart_tx_busy(CONS_UART_NR)) { + char ch; + if (cons_rb_pull(&ch) < 0) { + /* no more data to write, disable interest in Tx FIFO interrupts */ + return 1; + } + uart_putchar_nb(CONS_UART_NR, ch); + } + + /* if we reach here, UART Tx FIFO is busy again */ + return 0; +} + +/* flush pending data from debug ring buffer to serial port */ +int cons_rb_flush(void) +{ + return __rb_flush(); +} + +/* Append bytes to ring buffer, not more than we have left! */ +static void __cons_rb_append(const char *data, int len) +{ + if (cons.next_inbyte + len >= &cons.buf[0]+sizeof(cons.buf)) { + int before_tail = (&cons.buf[0]+sizeof(cons.buf)) - cons.next_inbyte; + /* copy the first part before we wrap */ + memcpy(cons.next_inbyte, data, before_tail); + data += before_tail; + len -= before_tail; + /* reset the buffer */ + cons.next_inbyte = &cons.buf[0]; + } + memcpy(cons.next_inbyte, data, len); + cons.next_inbyte += len; +} + +/* append bytes to the ringbuffer, do one wrap */ +int cons_rb_append(const char *data, int len) +{ + unsigned long flags; + int bytes_left; + const char *data_cur; + + /* we will never be able to write more than the console buffer */ + if (len > (int) sizeof(cons.buf)) + len = sizeof(cons.buf); + + local_irq_save(flags); + + bytes_left = __cons_rb_space(); + data_cur = data; + + if (len > bytes_left) { + /* append what we can */ + __cons_rb_append(data_cur, bytes_left); + /* busy-wait for all characters to be transmitted */ + __rb_flush_wait(); + /* fill it with the remaining bytes */ + len -= bytes_left; + data_cur += bytes_left; + } + __cons_rb_append(data_cur, len); + + /* we want to get Tx FIFO interrupts */ + uart_irq_enable(CONS_UART_NR, UART_IRQ_TX_EMPTY, 1); + + local_irq_restore(flags); + + return len; +} + +int cons_puts(const char *s) +{ + if (cons.initialized) { + return cons_rb_append(s, strlen(s)); + } else { + /* if the console is not active yet, we need to fall back */ + int i = strlen(s); + while (i--) + uart_putchar_wait(CONS_UART_NR, *s++); + return i; + } +} + +int cons_putchar(char c) +{ + if (cons.initialized) + return cons_rb_append(&c, 1); + else { + /* if the console is not active yet, we need to fall back */ + uart_putchar_wait(CONS_UART_NR, c); + return 0; + } +} -- cgit v1.2.3-55-g7522