/***
Copyright (c) 1991, 1992 by Frank J. Edwards
See the file COPYRIGHT in this distribution for copyright details.
***/

#ident "$Id: debug.c,v 1.15 1992/11/26 03:57:53 root Exp root $";

#include "sys/types.h"
#include "sys/param.h"
#include "sys/cred.h"
#include "sys/inline.h"		/* Needed for spl*() */
#include "sys/systm.h"		/* For "wakeup()" prototype */
#include "sys/user.h"		/* For references to the "u" struct */
#include "../driver/par.h"	/* For parallel port status line #define's */
#include "amigahr.h"		/* For ACIA and AMIGA structures */
#include <stdarg.h>

struct uio;			/* Avoid 'undefined' warning in ados_proto.h */

#include "ados.h"
#include "missing.h"		/* For KPutFmt() and friends */

#if NO_STRLOG + NO_SERIAL + NO_PARALLEL + NO_PRINTF != 4

# define STRLOG		0x01
# define KPUTFMT	0x02
# define pKPUTFMT	0x04
# define PRINTF		0x08

int ados_debug = STRLOG;

int ados_mid, ados_sid, ados_log, ados_level;
int ados_initialized = 0;
char ados_buf[1024];

static INLINE char *int2ascii(register char *ptr, register int val)
{
    do {
	*ptr++ = (val % 10) + '0';
    } while (val /= 10);
    return( ptr );
}

char *ados_debug_fmtv(char *buf, char *fmt, void *args)
{
    register char *ptr;
    register int inum;
    register long lnum;
    register unsigned long unum;

    fmt--;
    while (*++fmt) {
	if (*fmt != '%')
	    *buf++ = *fmt;
	else switch (*++fmt) {
	    case '%' :
		*buf++ = '%';
		break;
	    case 'b' :
		unum = va_arg(args, long);
		lnum = 31;
		while (lnum >= 0) {
		    inum = ((unum >> lnum) & 0x1) + '0';
		    *buf++ = inum;
		    lnum--;
		}
		break;
	    case 'c' :
		*buf++ = va_arg(args, char);
		break;
	    case 'd' :
		inum = va_arg(args, int);
		ptr = int2ascii(buf+20, inum < 0 ? -inum : inum);
		if (inum < 0)
		    *ptr++ = '-';
		for (lnum = ptr - (buf+20); lnum-- > 0; *buf++ = *--ptr)
		    ;
		break;
	    case 'g' :
		*buf++ = '?';
		*buf++ = ' ';
		(void) KGetChar();
		break;
	    case 'o' :
		unum = va_arg(args, long);
		lnum = 30;
		while (lnum >= 0) {
		    inum = ((unum >> lnum) & 0x7) + '0';
		    *buf++ = inum;
		    lnum -= 3;
		}
		break;
	    case 's' :
		ptr = va_arg(args, char *);
		while (*ptr)
		    *buf++ = *ptr++;
		break;
	    case 'x' :
		unum = va_arg(args, long);
		lnum = 28;
		while (lnum >= 0) {
		    inum = (unum >> lnum) & 0xF;
		    *buf++ = (inum > 9 ? inum+'7' : inum+'0');
		    lnum -= 4;
		}
		break;
	    default :
		*buf++ = '%';		/* Print out the original format */
		*buf++ = *fmt;		/*   spec so it'll be easier to find */
	    }
    }
    *buf = '\0';
}

char *ados_debug_fmt(char *buf, char *fmt, ...)
{
    va_list args;

    va_start(args, fmt);
    ados_debug_fmtv(buf, fmt, args);
    va_end(args);
}

void ados_DBG1(int mid, int sid, int log, int level)
{
    ados_mid = mid;
    ados_sid = sid;
    ados_log = log;
    ados_level = level;
}

#if !defined(NO_PARALLEL)
void pKPutChar(char ch)
{
    register int s;

    if (!ados_initialized) {
	s = spl2();
	/* I stole these 5 lines from the par.c code; all credit to CBM! */
	ACIAB->ddra  &= ~(C_POUT|C_BUSY);	/* Set control lines to input */
	ACIAA->ddrb   = 0xFF;			/* Set all 8 bits to output */
/*	ACIAA->icr    = ICR_SET|ICR_FLG;	/* Enable "Flag" Interrupt */
	ACIAA->icr    = ICR_CLR|ICR_FLG;	/* Disable "Flag" Interrupt */
/*	AMIGA->intena = AINTSET | AIEINT2;	/* Enable Interrupt 2 */
	splx(s);
	ados_initialized = 1;
    }
    if (ACIAB->pra & (C_POUT|C_BUSY)) {		/* Check/wait for PrtrRdy */
	if (ch == '\n') {	/* Use timeout() only on <LF> character */
	    s = splhi();
	    while (ACIAB->pra & (C_POUT|C_BUSY)) {
		(void) timeout( (void (*)()) wakeup, (caddr_t) u.u_procp+1, 1);
		sleep((caddr_t) u.u_procp+1, PZERO-1);
	    }
	    splx(s);
	} else {
	    while (ACIAB->pra & (C_POUT|C_BUSY))
		;
	}
    }
    ACIAA->prb = ch;				/* Output the character */
}
#endif /* NO_PARALLEL */

void ados_DBG2(char *fmt, ...)
{
    va_list args;

    va_start(args, fmt);
    ados_debug_fmtv(ados_buf, fmt, args);

# if !defined(NO_STRLOG)
    if (ados_debug & STRLOG)
	strlog(ados_mid, ados_sid, ados_log, ados_level, ados_buf);
# endif /* NO_STRLOG */

# if !defined(NO_PARALLEL)
    if (ados_debug & pKPUTFMT)
	KPutFmt(pKPutChar, "%d %d %s\n", ados_mid, ados_sid, ados_buf);
# endif /* NO_PARALLEL */

# if !defined(NO_SERIAL)
    if (ados_debug & KPUTFMT)		/* This does conputc() also */
	KPutFmt(KPutChar, "%d %d %s\n", ados_mid, ados_sid, ados_buf);
# endif /* NO_SERIAL */

# if !defined(NO_PRINTF)
    if (ados_debug & PRINTF)
	printf("%d %d %s\n", ados_mid, ados_sid, ados_buf);
# endif /* NO_PRINTF */

    va_end(args);
}
#endif /* any debugging whatsoever */
