diff options
author | Jeff Johnston <jjohnstn@redhat.com> | 2011-12-15 22:58:40 +0000 |
---|---|---|
committer | Jeff Johnston <jjohnstn@redhat.com> | 2011-12-15 22:58:40 +0000 |
commit | 8e0346d1372ed32d2c5f559e083f3bd60b281c3a (patch) | |
tree | b72116c382df57f2e7396b58d32370b731535712 /libgloss/sparc_leon/console_dbg.c | |
parent | e74758408e50f8980de0d73f5b3721efbd698df9 (diff) | |
download | cygnal-8e0346d1372ed32d2c5f559e083f3bd60b281c3a.tar.gz cygnal-8e0346d1372ed32d2c5f559e083f3bd60b281c3a.tar.bz2 cygnal-8e0346d1372ed32d2c5f559e083f3bd60b281c3a.zip |
2011-12-15 Konrad Eisele <konrad@gaisler.com>
* configure.in: Add SPARC LEON support.
* configure: Regenerated.
* sparc_leon/asm-leon/amba.h, sparc_leon/asm-leon/asmmacro.h,
sparc_leon/asm-leon/clock.h, sparc_leon/asm-leon/contextswitch.h,
sparc_leon/asm-leon/elfmacro.h, sparc_leon/asm-leon/head.h,
sparc_leon/asm-leon/irq.h, sparc_leon/asm-leon/jiffies.h,
sparc_leon/asm-leon/lambapp.h, sparc_leon/asm-leon/lambapp_devs.h,
sparc_leon/asm-leon/leon.h, sparc_leon/asm-leon/leon3.h,
sparc_leon/asm-leon/leonbare_debug.h, sparc_leon/asm-leon/leonbare_kernel.h,
sparc_leon/asm-leon/leonbare_kernel_queue.h, sparc_leon/asm-leon/leoncompat.h,
sparc_leon/asm-leon/leondbg.h, sparc_leon/asm-leon/leonstack.h,
sparc_leon/asm-leon/liblocks.h, sparc_leon/asm-leon/linkage.h,
sparc_leon/asm-leon/param.h, sparc_leon/asm-leon/queue.h,
sparc_leon/asm-leon/spinlock.h, sparc_leon/asm-leon/stack.h,
sparc_leon/asm-leon/time.h, sparc_leon/asm-leon/timer.h,
sparc_leon/asm-leon/types.h, sparc_leon/asm-leon/winmacros.h:
New file.
* sparc_leon/Makefile.in, sparc_leon/_exit.c,
sparc_leon/amba.c, sparc_leon/amba_dbg.c,
sparc_leon/amba_driver.c, sparc_leon/amba_scan.c,
sparc_leon/asm-leon, sparc_leon/bdinit.S,
sparc_leon/busscan.S, sparc_leon/cacheA.S,
sparc_leon/catch_interrupt.c, sparc_leon/catch_interrupt_mvt.c,
sparc_leon/catch_interrupt_pending.c, sparc_leon/catch_interrupt_svt.c,
sparc_leon/configure.in,
sparc_leon/console.c, sparc_leon/console_dbg.c,
sparc_leon/console_init.c, sparc_leon/contextswitch.c,
sparc_leon/contextswitch_asm.S, sparc_leon/crt0.S,
sparc_leon/crti.S, sparc_leon/crtn.S,
sparc_leon/etrap.S, sparc_leon/etrap_fast.S,
sparc_leon/fpu.S, sparc_leon/gettimeofday.c,
sparc_leon/initcalls.c, sparc_leon/io.c,
sparc_leon/irqinstall.S, sparc_leon/irqtrap.S,
sparc_leon/irqtrap_fast.S, sparc_leon/jiffies.c,
sparc_leon/kernel.c, sparc_leon/kernel_context.S,
sparc_leon/kernel_debug.c, sparc_leon/kernel_debug_var.c,
sparc_leon/kernel_mm.c, sparc_leon/kernel_mutex.c,
sparc_leon/kernel_queue.c, sparc_leon/kernel_sched.c,
sparc_leon/kernel_thread.c, sparc_leon/lcpuinit.S,
sparc_leon/locore.S, sparc_leon/locore_atexit.c,
sparc_leon/locore_clean.S, sparc_leon/locore_mvt.S,
sparc_leon/locore_mvt_reset.S, sparc_leon/locore_svt.S,
sparc_leon/locore_svt_reset.S, sparc_leon/locore_svtdisp.S,
sparc_leon/locore_var.S, sparc_leon/locore_var_svt.S,
sparc_leon/mmu_asm.S, sparc_leon/mutex.c,
sparc_leon/nocache.S, sparc_leon/pnpinit.c,
sparc_leon/pnpinit_malloc.c, sparc_leon/pnpinit_simple.c,
sparc_leon/regwin.S, sparc_leon/regwin_patch.c,
sparc_leon/regwin_slow.S, sparc_leon/regwinflush.S,
sparc_leon/rtc.c, sparc_leon/rtrap.S,
sparc_leon/rtrap_fast.S, sparc_leon/stop.S,
sparc_leon/timer.c, sparc_leon/times.c:
New file
* sparc_leon/configure: Regenerate
Diffstat (limited to 'libgloss/sparc_leon/console_dbg.c')
-rw-r--r-- | libgloss/sparc_leon/console_dbg.c | 354 |
1 files changed, 354 insertions, 0 deletions
diff --git a/libgloss/sparc_leon/console_dbg.c b/libgloss/sparc_leon/console_dbg.c new file mode 100644 index 000000000..57c258fb4 --- /dev/null +++ b/libgloss/sparc_leon/console_dbg.c @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2011 Aeroflex Gaisler + * + * BSD license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +#include <stdlib.h> +#include <ctype.h> +#ifdef _HAVE_STDC +#include <stdarg.h> +#else +#include <varargs.h> +#endif +#include <asm-leon/leoncompat.h> +#include <asm-leon/leon.h> + +static size_t +lo_strnlen (const char *s, size_t count) +{ + const char *sc; + + for (sc = s; count-- && *sc != '\0'; ++sc) + /* nothing */ ; + return sc - s; +} + +static int +lo_vsnprintf (char *buf, size_t size, const char *fmt, va_list args) +{ + int len; + unsigned long long num; + int i, j, n; + char *str, *end, c; + const char *s; + int flags; + int field_width; + int precision; + int qualifier; + int filler; + + str = buf; + end = buf + size - 1; + + if (end < buf - 1) + { + end = ((void *) -1); + size = end - buf + 1; + } + + for (; *fmt; ++fmt) + { + if (*fmt != '%') + { + if (*fmt == '\n') + { + if (str <= end) + { + *str = '\r'; + } + str++; + } + if (str <= end) + *str = *fmt; + ++str; + continue; + } + + /* process flags */ + flags = 0; + /* get field width */ + field_width = 0; + /* get the precision */ + precision = -1; + /* get the conversion qualifier */ + qualifier = 'l'; + filler = ' '; + + ++fmt; + + if (*fmt == '0') + { + filler = '0'; + ++fmt; + } + + while (isdigit (*fmt)) + { + field_width = field_width * 10 + ((*fmt) - '0'); + ++fmt; + } + + /* default base */ + switch (*fmt) + { + case 'c': + c = (unsigned char) va_arg (args, int); + if (str <= end) + *str = c; + ++str; + while (--field_width > 0) + { + if (str <= end) + *str = ' '; + ++str; + } + continue; + + case 's': + s = va_arg (args, char *); + if (!s) + s = "<NULL>"; + + len = lo_strnlen (s, precision); + + for (i = 0; i < len; ++i) + { + if (str <= end) + *str = *s; + ++str; + ++s; + } + while (len < field_width--) + { + if (str <= end) + *str = ' '; + ++str; + } + continue; + + + case '%': + if (str <= end) + *str = '%'; + ++str; + continue; + + case 'x': + break; + case 'd': + break; + + default: + if (str <= end) + *str = '%'; + ++str; + if (*fmt) + { + if (str <= end) + *str = *fmt; + ++str; + } + else + { + --fmt; + } + continue; + } + num = va_arg (args, unsigned long); + if (*fmt == 'd') + { + j = 0; + while (num && str <= end) + { + *str = (num % 10) + '0'; + num = num / 10; + ++str; + j++; + } + /* flip */ + for (i = 0; i < (j / 2); i++) + { + n = str[(-j) + i]; + str[(-j) + i] = str[-(i + 1)]; + str[-(i + 1)] = n; + } + /* shift */ + if (field_width > j) + { + i = field_width - j; + for (n = 1; n <= j; n++) + { + if (str + i - n <= end) + { + str[i - n] = str[-n]; + } + } + for (i--; i >= 0; i--) + { + str[i - j] = filler; + } + str += field_width - j; + j = 1; + } + } + else + { + for (j = 0, i = 0; i < 8 && str <= end; i++) + { + if ((n = + ((unsigned long) (num & (0xf0000000ul >> (i * 4)))) >> + ((7 - i) * 4)) || j != 0) + { + if (n >= 10) + n += 'a' - 10; + else + n += '0'; + *str = n; + ++str; + j++; + } + } + + /* shift */ + if (field_width > j) + { + i = field_width - j; + for (n = 1; n <= j; n++) + { + if (str + i - n <= end) + { + str[i - n] = str[-n]; + } + } + for (i--; i >= 0; i--) + { + str[i - j] = filler; + } + str += field_width - j; + j = 1; + } + + + } + + if (j == 0 && str <= end) + { + *str = '0'; + ++str; + } + } + if (str <= end) + *str = '\0'; + else if (size > 0) + /* don't write out a null byte if the buf size is zero */ + *end = '\0'; + /* the trailing null byte doesn't count towards the total + * ++str; + */ + return str - buf; +} + +/** + * lo_vsprintf - Format a string and place it in a buffer + * @buf: The buffer to place the result into + * @fmt: The format string to use + * @args: Arguments for the format string + * + * Call this function if you are already dealing with a va_list. + * You probably want lo_sprintf instead. + */ +static int +lo_vsprintf (char *buf, const char *fmt, va_list args) +{ + return lo_vsnprintf (buf, 0xFFFFFFFFUL, fmt, args); +} + + +int +dbgleon_sprintf (char *buf, size_t size, const char *fmt, ...) +{ + va_list args; + int printed_len; + + va_start (args, fmt); + printed_len = lo_vsnprintf (buf, size, fmt, args); + va_end (args); + return printed_len; +} + +#define UART_TIMEOUT 100000 +static LEON23_APBUART_Regs_Map *uart_regs = 0; +int +dbgleon_printf (const char *fmt, ...) +{ + unsigned int i, loops, ch; + amba_apb_device apbdevs[1]; + va_list args; + int printed_len; + char printk_buf[1024]; + char *p = printk_buf; + + /* Emit the output into the temporary buffer */ + va_start (args, fmt); + printed_len = lo_vsnprintf (printk_buf, sizeof (printk_buf), fmt, args); + va_end (args); + + //--------------------- + switch (LEONCOMPAT_VERSION) + { + case 3: + default: + { + if (!uart_regs) + { + if (i = + leon3_getapbbase (VENDOR_GAISLER, GAISLER_APBUART, apbdevs, + 1)) + { + uart_regs = (LEON23_APBUART_Regs_Map *) apbdevs[0].start; + } + } + if (uart_regs) + { + while (printed_len-- != 0) + { + ch = *p++; + if (uart_regs) + { + loops = 0; + while (!(uart_regs->status & LEON_REG_UART_STATUS_THE) + && (loops < UART_TIMEOUT)) + loops++; + uart_regs->data = ch; + loops = 0; + while (!(uart_regs->status & LEON_REG_UART_STATUS_TSE) + && (loops < UART_TIMEOUT)) + loops++; + } + } + } + } + break; + } + //--------------------- +} |