/* * TDEBUG.C * * (C)Copyright 1987 Matthew Dillon, All Rights Reserved * FreeWare. May be distributed for non-profit only. * * Debug any device .. usually trackdisk.device * * AZTEC USERS: MUST COMPILE +CDL and LINK WITH THE LARGE EVERYTHING * LIBRARY!!!! (cl32.lib). NOTE: This source expects all the amiga * symbols to be preloaded. NOTE: There are some function calls in this * source which you don't have... the functions should be obvious and * easy to implement. * * Sorry, no support for lattice. A smart programmable will be able to * split the assembly file and do all the right #includes. * */ #define FIFO struct _FIFO typedef struct ExecBase EB; typedef struct List LIST; typedef struct Node NODE; typedef struct IOStdReq STD; typedef struct Task TASK; FIFO { FIFO *next; /* next element */ STD std; /* IO request */ }; extern EB *SysBase; extern NODE *findlist(); extern TASK *FindTask(); extern char *AllocMem(); FIFO *Base, **Lnext = &Base; NODE *Nodearray[64]; NODE *Ntrack; NODE *Nasdg; TASK *Mastertask; long Operations; /* # operations monitored */ long Mask, Signum; char *Stdname[] = { "INVALID", "RESET", "READ", "WRITE", "UPDATE", "CLEAR", "STOP", "START", "FLUSH" }; main(ac, av) char *av[]; { register FIFO *fifo; register long result; disablebreak(); Mastertask = FindTask(0); Signum = AllocSignal(-1); Mask = 1 << Signum; loadnodearray(ac, av); /* which devices to intercept? */ overidevector(1); puts ("Now intercepting all DoIO() and SendIO() operations"); puts (""); puts ("Device__ Cmd_ Len_____"); SetSignal(0, SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D); for (;;) { result = Wait(SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D|Mask); if (result & (SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D)) break; while (Base) { long block, cmd; char ext; Forbid(); fifo = Base; Base = Base->next; if (Base == NULL) Lnext = &Base; Permit(); printf ("%16s ", fifo->std.io_Device->dd_Library.lib_Node.ln_Name); cmd = fifo->std.io_Command; ext = ' '; if (cmd & TDF_EXTCOM) { cmd &= ~TDF_EXTCOM; ext = 'E'; } if (fifo->std.io_Command < CMD_NONSTD) printf ("%lc%-7s ", ext, Stdname[fifo->std.io_Command]); else printf (" NON+%lc%-2ld ", ext, fifo->std.io_Command - CMD_NONSTD); printf ("%-8ld %-8ld ", fifo->std.io_Length, fifo->std.io_Offset); if (fifo->std.io_Device == Ntrack || fifo->std.io_Device == Nasdg) { block = fifo->std.io_Offset / 512; printf ("Blk#: %-5ld ", block); printf ("(Trk %2ld Cyl %2ld) ", block/22, (block/11)&1); } puts(""); FreeMem(fifo, sizeof(*fifo)); } } puts ("Restoring intercept vector"); overidevector(0); Delay(50); while (Base) { fifo = Base->next; FreeMem(Base, sizeof(*Base)); Base = fifo; } FreeSignal(Signum); printf ("%ld operations monitored\n", Operations); } loadnodearray(ac, av) char *av[]; { register int i; register int j; register NODE *node; register LIST *list = &SysBase->DeviceList; Ntrack = findlist(list, "trackdisk.device"); Nasdg = findlist(list, "asdg.vdisk.device"); if (ac == 1) { puts ("TDEBUG V1.00 By Matthew Dillon"); puts ("(C)Copyright 1987 Mathew Dillon, All Rights Reserved"); puts ("CTRL-C, CTRL-D, or BREAK to terminate"); puts (""); puts ("tdebug device device..."); puts ("tdebug trackdisk.device"); puts (""); showlist(list); puts (""); exit(1); } for (i = 1, j = 0; av[i]; ++i) { node = findlist(list, av[i]); if (!node) printf ("Unable to find: %s\n", av[i]); else Nodearray[j++] = node; } } NODE * findlist(list, name) LIST *list; char *name; { register NODE *node; for (node = list->lh_Head; node != &list->lh_Tail; node = node->ln_Succ) { if (strcmp(name, node->ln_Name) == 0) return(node); } return(NULL); } showlist(list) LIST *list; { register NODE *node; for (node=list->lh_Head; node != &list->lh_Tail; node=node->ln_Succ) { puts(node->ln_Name); } } static long oldsendvec; static long olddovec; overidevector(n) { extern char LVODoIO; extern char LVOSendIO; extern int newsendio(), newdoio(); Forbid(); if (n) { oldsendvec = SetFunction(SysBase, &LVOSendIO, newsendio); olddovec = SetFunction(SysBase, &LVODoIO, newdoio); } else { SetFunction(SysBase, &LVOSendIO, oldsendvec); SetFunction(SysBase, &LVODoIO, olddovec); } Permit(); } /* * NOTE!!! Since BeginIO is the basis for the entire operating system, * we cannot do anything inside this routine that would ever use it. */ myio(ioreq) register STD *ioreq; { register FIFO *fifo; register int i; Forbid(); for (i = 0; Nodearray[i]; ++i) { if (Nodearray[i] == ioreq->io_Device) break; } if (Nodearray[i]) { if (fifo = (FIFO *)AllocMem(sizeof(*fifo), 0)) { *Lnext = fifo; Lnext = &fifo->next; fifo->next = NULL; fifo->std = *ioreq; } ++Operations; Signal(Mastertask, Mask); } Permit(); } #asm _newsendio: movem.l D0-D7/A0-A6,-(sp) ;save regs move.l A1,-(sp) ;the io request jsr _myio ;call my intercept routine addq.l #4,sp movem.l (sp)+,D0-D7/A0-A6 ;restore regs move.l _oldsendvec,A0 ;A0 not used by SendIO jsr (A0) rts _newdoio: movem.l D0-D7/A0-A6,-(sp) ;save regs move.l A1,-(sp) ;the io request jsr _myio ;call my intercept routine addq.l #4,sp movem.l (sp)+,D0-D7/A0-A6 ;restore regs move.l _olddovec,A0 ;A0 not used by SendIO jsr (A0) rts #endasm