/***************************************************************** ** S T A L L E R . C ** Address Tracing System, Scott Harrington, Spring 94 ** Installs Stall Interrupt handler. ** Command line options: ** [-p port] port #(200,220,240,...,3E0) default 300 ** [-i IRQ] IRQ #(2,3,6,7) default 7 ** [-e [command]] execute command (default COMMAND.COM) ** [-d] debug ISR ** [-m max] stall for a maximum of max loops ** [-r] removes handler for IRQ (default 7) ** If neither -e or -r is used, STALLER stays resident. */ #include <stdio.h> #include <conio.h> #include <stdlib.h> #include <string.h> #include <dos.h> #define ISYS_SACK 0x01 #define ISYS_NOTIRQ 0x02 #define ISYS_RUN 0x04 #define ISYS_SRQ 0x08 #define P8259_0 0x20 #define P8259_1 0x21 #define CHECK_LEN 4 #define OCW #define SPECIFIC_EOI /* reduce heaplength and stacklength to make a smaller program in memory */ extern unsigned _heaplen = 1024; extern unsigned _stklen = 512; void interrupt far stallHandler(void); void (interrupt far *oldHandler)(void); void printStatus(void); unsigned int ioPort = 0x220; int irq = 7; int eoi = 0x20; /* non-specific EOI */ char commandPath[80] = "COMMAND"; enum {INSTALL_TSR, REMOVE_TSR, RUN_COMMAND, DEBUG_ISR}; int executionType = INSTALL_TSR; volatile unsigned char isrVal = 0; volatile int inISR = 0; int loopMax = -1; const int irqHook[] = {-1, -1, 0x0A, 0x0B, -1, -1, 0x0E, 0x0F, -1, 0x70}; const unsigned char enableMask[] = {0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F, 0xFF}; const unsigned char disableMask[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00}; void main(int argc, char *argv[]) { int i, ch; unsigned char mask; char *parmstr, *endptr; void far *s1; void far *s2; for (i=1; i<argc; i++) { if (argv[i][0] == '-' && argv[i][1]) { switch (argv[i][1]) { case 'p': parmstr = (argv[i][2]) ? &argv[i][2] : argv[++i]; ioPort = (unsigned int)strtoul(parmstr, &endptr, 0); break; case 'i': parmstr = (argv[i][2]) ? &argv[i][2] : argv[++i]; irq = atoi(parmstr); break; case 'e': parmstr = (argv[i][2]) ? &argv[i][2] : argv[++i]; executionType = RUN_COMMAND; if (i<=argc && parmstr[0] && parmstr[0] != '-') strcpy(commandPath, parmstr); else i--; break; case 'm': parmstr = (argv[i][2]) ? &argv[i][2] : argv[++i]; loopMax = atoi(parmstr); break; case 'd': executionType = DEBUG_ISR; break; case 'r': executionType = REMOVE_TSR; break; case 'h': default: printf("Usage: %s [-p port] [-i irq] [-e [cmd]] [-m maxloop] [-r(emove)]\n", argv[0]); exit(-1); } } else { printf("Usage: %s [-p port] [-i irq] [-e [cmd]] [-r]\n", argv[0]); exit(-1); } } if (irqHook[irq] < 0) { printf("Unsupported IRQ number %d.\n", irq); exit(-1); } #ifdef SPECIFIC_EOI eoi = 0x60 + (irq&0x07); #endif if (ioPort != (ioPort&0x3E0)) { printf("Valid ports are 0x200, 220, 240, ..., 3E0.\n"); exit(-1); } if (executionType == REMOVE_TSR) { /* Check that previous copy of STALLER is resident, by comparing the first few bytes of the vector with our handler code. */ s1 = (void far *)stallHandler; s2 = (void far *)_dos_getvect(irqHook[irq]); if (_fmemcmp(s1,s2,CHECK_LEN)) { printf("Previous copy of STALLER not found.\n"); exit(-1); } /* Terminate and attempt to release memory of previous handler. */ printStatus(); _disable(); #ifdef OCW mask = inportb(P8259_1); outportb(P8259_1, mask | disableMask[irq]); #endif _enable(); printStatus(); printf("Removed IRQ %d handler.\n", irq); printf("I don't know how to release TSR memory.\n"); exit(0); } printStatus(); _disable(); oldHandler = _dos_getvect(irqHook[irq]); _dos_setvect(irqHook[irq], stallHandler); #ifdef OCW mask = inportb(P8259_1); outportb(P8259_1, mask & enableMask[irq]); #endif _enable(); printf("Stall Handler hooked to IRQ %d, vector %d, port %x.\n", irq, irqHook[irq], ioPort); printf("Old interrupt vector is %Fp.\n", oldHandler); outportb(ioPort+1, 0); /* Turn recording on */ printStatus(); switch (executionType) { case INSTALL_TSR: _dos_keep(0, (_SS + ((_SP+100)/16) - _psp)); /* Does not return...terminates and stays resident. */ case RUN_COMMAND: system(commandPath); break; case DEBUG_ISR: while (!kbhit()) printStatus(); getch(); break; } printStatus(); outportb(ioPort, 0); /* Turn recording off */ _disable(); #ifdef OCW mask = inportb(P8259_1); outportb(P8259_1, mask | disableMask[irq]); #endif _dos_setvect(irqHook[irq], oldHandler); _enable(); printf("Stall Handler removed.\n"); printStatus(); } void printStatus() { unsigned char isysReg; int isysSACK, isysIRQ, isysRUN, isysSRQ; unsigned char picIMR, picISR, picIRR; isysReg = inportb(ioPort); isysSACK = isysReg & ISYS_SACK; isysIRQ = !(isysReg & ISYS_NOTIRQ); isysRUN = isysReg & ISYS_RUN; isysSRQ = isysReg & ISYS_SRQ; picIMR = inportb(P8259_1); outportb(P8259_0, 0x0A); /* read register IRR */ picIRR = inportb(P8259_0); outportb(P8259_0, 0x0B); /* read register ISR */ picISR = inportb(P8259_0); printf("isrVal=%02X ", isrVal); printf("isys: %s %s %s %s ", (isysRUN) ? " RUN " : "stall", (isysIRQ) ? "IRQ" : "irq", (isysSRQ) ? "SRQ" : "srq", (isysSACK) ? "SACK" : "sack"); printf("8259: IMR=%02x ISR=%02x IRR=%02x\n", picIMR, picISR, picIRR); } void interrupt far stallHandler() { unsigned char mask; int loopCounter; #ifdef DEBUGCRAP if (executionType == DEBUG_ISR) { isrVal++; _enable(); /* isrVal = inportb(ioPort);*/ outportb(ioPort,0); /* Turn recording off */ outportb(PIC8259A_0, eoi); _disable(); /* disable further stalls until we IRET */ } else { /* If a stallHandler is already running exit now. */ #endif if (!inISR) { #ifdef NOTOURIRQ if (inportb(ioPort) & ISYS_NOTIRQ) _chain_intr(oldHandler); /* Not our IRQ! */ else { #endif inISR = 1; /* don't _enable until we mark that we're here */ #ifdef OCW_IN_ISR mask = inportb(P8259_1); outportb(P8259_1, mask | disableMask[irq]); #endif _enable(); isrVal++; outportb(ioPort,0); /* Turn recording off */ loopCounter = 0; while (inportb(ioPort) & ISYS_SRQ) { if (loopMax != -1 && ++loopCounter >= loopMax) break; } outportb(ioPort+1,0); /* Turn recording on */ /* Send EndOfInterrupt to 8259A PIC */ outportb(P8259_0, eoi); _disable(); /* disable further stalls until we IRET */ #ifdef OCW_IN_ISR mask = inportb(P8259_1); outportb(P8259_1, mask & enableMask[irq]); #endif inISR = 0; /* }*/ } }