summaryrefslogblamecommitdiffstats
path: root/c/src/lib/libbsp/powerpc/mvme2307/console/printk.c
blob: 0058f03d74688f9b421f0703d5a1c7b3f554a148 (plain) (tree)






































































































































































































                                                                                  
#include <bsp.h>

#if 1

static void outbyte(char c) {
    volatile char * const pc16550 = (char *) IO_TO_LOCAL(0x03f8);
#   define THR  0
#   define LSR  5
#   define THRE 0x20
    while ((pc16550[LSR] & THRE) == 0) {
        ;
    }
    pc16550[THR] = c;
}

#else

/* printk to memory for debugging */
static void outbyte(char c) {
    static char *memory_log = (char *) 0x01F00000;

    *memory_log++ = c;
    if (memory_log >= (char *) 0x01F80000) {
        memory_log--;
    }
}

#endif

/*-------------------------------------------------------------------------+
| printk.c v1.1 - PC386 BSP - 1997/08/07
+--------------------------------------------------------------------------+
| (C) Copyright 1997 -
| - NavIST Group - Real-Time Distributed Systems and Industrial Automation
|
| http://pandora.ist.utl.pt
|
| Instituto Superior Tecnico * Lisboa * PORTUGAL
+--------------------------------------------------------------------------+
| Disclaimer:
|
| This file is provided "AS IS" without warranty of any kind, either
| expressed or implied.
+--------------------------------------------------------------------------+
| This code is based on code by: Jose Rufino - IST
|
|  $Id$
+--------------------------------------------------------------------------*/


#include <stdarg.h>

/*-------------------------------------------------------------------------+
|         Function: printNum
|      Description: print number in a given base.
| Global Variables: None.
|        Arguments: num - number to print, base - base used to print the number.
|          Returns: Nothing. 
+--------------------------------------------------------------------------*/
static void printNum(long unsigned int num, int base, int sign, int width,
                     int zerofill) {
    long unsigned int n;
    int count, negative = 0;
    char toPrint[80];
    char *digits = "0123456789ABCDEF";

    if (width > sizeof(toPrint)) {
        width = sizeof(toPrint);
    }
    if ((sign == 1) && ((long) num < 0)) {
        negative = 1;
        num = -num;
    }

    count = 0;
    while ((n = num / base) > 0) {
        toPrint[count++] = digits[num - (n * base)];
        num = n;
    }
    toPrint[count++] = digits[num];
    if (count + negative < width) {
        /* this needs to be padded out to width */
        if (zerofill) {
            while (count + negative < width) {
                toPrint[count++] = '0';
            }
            if (negative) {
                toPrint[count++] = '-';
            }
        } else {
            if (negative) {
                toPrint[count++] = '-';
            }
            while (count < width) {
                toPrint[count++] = ' ';
            }
        }
    } else if (negative) {
        toPrint[count++] = '-';
    }

    for (n = 0; n < count; n++) {
        outbyte(toPrint[count - (n + 1)]);
    }
}


/*-------------------------------------------------------------------------+
|         Function: printk
|      Description: a simplified version of printf intended for use when the
                    console is not yet initialized or in ISR's.
| Global Variables: None.
|        Arguments: as in printf: fmt - format string, ... - unnamed arguments.
|          Returns: Nothing. 
+--------------------------------------------------------------------------*/
int printk_enabled = 1;

void printk(char *fmt, ...) {
    va_list ap;			/* points to each unnamed argument in turn */
    char c, *str;
    int lflag, base, sign, width, zero;

    /* disable interrupts???  */

    if (printk_enabled) {
        va_start(ap, fmt);		/* make ap point to 1st unnamed arg */
        for (; *fmt != '\0'; fmt++) {
            lflag = 0;
            base = 0;
            sign = 0;
            width = 0;
            if (*fmt == '\n') {
                outbyte('\r');
            }
            if (*fmt == '%') {
                c = *++fmt;
                if (c == '0') {
                    zero = 1;
                    c = *++fmt;
                } else {
                    zero = 0;
                }
                for (; c >= '0' && c <= '9'; c = *++fmt) {
                    width = width * 10 + (c - '0');
                }
                if (c == 'l') {
                    lflag = 1;
                    c = *++fmt;
                }
                switch (c) {
                    case 'o':
                    case 'O':
                        base = 8;
                        sign = 0;
                        break;
                    case 'd':
                    case 'D':
                        base = 10;
                        sign = 1;
                        break;
                    case 'u':
                    case 'U':
                        base = 10;
                        sign = 0;
                        break;
                    case 'x':
                    case 'X':
                        base = 16;
                        sign = 0;
                        break;
                    case 's':
                        for (str = va_arg(ap, char *); *str; str++) {
                            outbyte(*str);
                            width--;
                        }
                        while (width-- > 0) {
                            outbyte(' ');
                        }
                        break;
                    case 'c':
                        outbyte(va_arg(ap, int));
                        break;
                    default:
                        outbyte(c);
                        break;
                }

                if (base) {
                    printNum(lflag ? va_arg(ap, long int) : 
                             (long int) va_arg(ap, int), base, sign, width, zero);
                }
            } else {
                outbyte(*fmt);
            }
        }
        va_end(ap);			/* clean up when done */
        /* enable interrupts???  */
    }
}