/*	DEBUGGING-- This is Matt Dillon's debugger code,
 *	which is *real* handy when you're paranoid about what
 *	you can and can't do because of your task/process state
 *
 *	It's even better than kprintf :-)
 */

#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/memory.h>
#include <devices/printer.h>
#include <devices/prtbase.h>

#ifndef DEBUG

dbprintf() {}	/* empty function declaration */

#else

#define CTOB(x) (void *)(((long)(x))>>2)

struct Task *FindTask();
struct MsgPort *CreatePort();
struct FileHandle *Open();
struct Message *GetMsg();


struct MsgPort  *Dbport;    /*	owned by the debug process	*/
struct MsgPort  *Dback;	    /*	owned by the DOS device driver	*/
short DBDisable;
struct Message  DummyMsg;

void dbstart()
{

    DBDisable = 0;
    Dbport = Dback = NULL;

    /* need DosBase and SysBase to use debugger */
    /*	DEBUGGING   */

    dbinit();	/* to close off debugger call dbuninit() */
}

/*
 *  DEBUGGING CODE.	You cannot make DOS library calls that access other
 *  devices from within a DOS device driver because they use the same
 *  message port as the driver.  If you need to make such calls you must
 *  create a port and construct the DOS messages yourself.  I do not
 *  do this.  To get debugging info out another PROCESS is created to which
 *  debugging messages can be sent.
 *
 *  You want the priority of the debug process to be larger than the
 *  priority of your DOS handler.  This is so if your DOS handler crashes
 *  you have a better idea of where it died from the debugging messages
 *  (remember that the two processes are asyncronous from each other).
 */

extern void debugproc();

dbinit()
{
    struct Task *task = FindTask(NULL);

    Dback = CreatePort(NULL,NULL);
    CreateProc("DEV_DB", task->tc_Node.ln_Pri+1, CTOB(debugproc), 4096);
    WaitPort(Dback);				/* handshake startup    */
    GetMsg(Dback);				/* remove dummy msg     */
    dbprintf("Debugger running V1.00\n");
}

dbuninit()
{
    struct Message killmsg;

    if (Dbport) {
	killmsg.mn_Length = 0;	    /*	0 means die	    */
	PutMsg(Dbport,&killmsg);
	WaitPort(Dback);	    /*	He's dead jim!      */
	GetMsg(Dback);
	DeletePort(Dback);

	/*
	 *  Since the debug process is running at a greater priority, I
	 *  am pretty sure that it is guarenteed to be completely removed
	 *  before this task gets control again.  Still, it doesn't hurt...
	 */

	/* Delay(50); */	    /*	ensure he's dead    */
    }
}

dbprintf(a,b,c,d,e,f,g,h,i,j)
{
    static char buf[256];
    struct Message *msg;

    if (Dbport && !DBDisable) {
	sprintf(buf,a,b,c,d,e,f,g,h,i,j);
	msg = AllocMem(sizeof(struct Message)+strlen(buf)+1,
		MEMF_PUBLIC|MEMF_CLEAR);
	msg->mn_Length = strlen(buf)+1;     /*	Length NEVER 0	*/
	strcpy(msg+1,buf);
	PutMsg(Dbport,msg);
    }
}

/*
 *  BTW, the DOS library used by debugmain() was actually openned by
 *  the _Init routine.	Note: DummyMsg cannot be on debugmain()'s stack
 *  since debugmain() goes away on the final handshake.
 */

debugmain()
{
    
    struct Message *msg;
    short len;
    void *fh;

    Dbport = CreatePort(NULL,NULL);
    fh = Open("con:0/0/640/100/debugwindow", 1006);
    PutMsg(Dback, &DummyMsg);
    for (;;) {
	WaitPort(Dbport);
	msg = GetMsg(Dbport);
	len = msg->mn_Length;
	if (len == 0)
	    break;
	--len;			    /*	Fix length up	*/
	Write(fh, msg+1, len);
	FreeMem(msg,sizeof(struct Message)+len+1);
    }
    Close(fh);
    DeletePort(Dbport);
    PutMsg(Dback,&DummyMsg);	      /*  Kill handshake  */
}

/*
 *  The assembly tag for the DOS process:  CNOP causes alignment problems
 *  with the Aztec assembler for some reason.  I assume then, that the
 *  alignment is unknown.  Since the BCPL conversion basically zero's the
 *  lower two bits of the address the actual code may start anywhere
 *  within 8 bytes of address (remember the first longword is a segment
 *  pointer and skipped).  Sigh....  (see CreatProc() above).
 */

#asm
	public	_debugproc
	public	_debugmain

	cseg
_debugproc:
	nop
	nop
	nop
	nop
	nop
	movem.l D2-D7/A2-A6,-(sp)
	jsr	_debugmain
	movem.l (sp)+,D2-D7/A2-A6
	rts
#endasm

#endif
