next up previous contents
Next: D.3 download.c Up: D C Source Code Previous: D.1 busmon.c

D.2 staller.c

 

/*****************************************************************
** 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;
/*          }*/
        }
    }


Scott E. Harrington
Sat Apr 29 18:56:25 EDT 1995