/* 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 #include #include #include #include #include #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