If you have a PH account, you can customize your PH profile.
*/
*/

View \PORT.C

I/O port debugging tool, with C source code

Submitted By: Unknown
Rating: Not rated (Rate It)


/*
*       Port - Do all kinds of wild and crazy things to PC I/O ports
*
*       Rev 1.1                03/13/91
*       John De Armond, Rapid Deployment Systems  ([[Email Removed]])
*       Copyright 1991, John De Armond, Minimal Rights Reserved
*       
*       Compiled with the supplied project file under Borland C++ 2.0 but
*       otherwise uncontaminated with C++ drool.
*       
*       Edited with MKS vi.  To align indents, set tabstop=4, shiftwidth=4
*
*       Surgeon General's warning:  Caution:  Misuse or abuse of this
*                                                        program is dangerous to the health of
*                                                        your hard disk, your memory, your video
*                                                        monitor and other such goodies.  Govern
*                                                        your actions accordingly.
*/


#include <stdio.h>
#include <dos.h>

/***** define a few symbolic constants */
#define BYTE 1
#define WORD 2
#define HEX  3
#define DEC     4
#define IN 5
#define OUT 6
/***************************************/

unsigned int port=0, byte=0;
unsigned int save_port, save_byte;
char buf[80];
int entry_mode = HEX;
int byte_mode = BYTE;
int io_mode = OUT;
int quiet=0;
int match_byte;

extern char * token();
char *token_ptr;
int is_a_tty = 0;
int echo_command = 0;

main(argc,argv)
int argc;
char **argv;
{
        unsigned int gak;
        FILE *fp;

        /* yes, I do mean "=" below */
        if ( !(is_a_tty = isatty(0)) ) {        /* check stdin for source */
                echo_command=1;     /* if we're on a pipe, echo each
                                                                                   command */

        }

        if (argc >= 2) {        /* if only 2, then argv[1] is port number in hex */
                sscanf(argv[1],"%x",&port);
        }
        if (argc >=3) {  /* if 3 arguments, then argv[2] is the bit pattern*/
                sscanf(argv[2],"%x",&byte);
        }

        printf("PORT v1.1 03/13/91 by John De Armond.  ([[Email Removed]])\n");

        help();

        for (;;) {
                prompt();

                /* this little trick allows us to redirect a file in and
                        then take keyboard input.  This allows configuration files
                        to be piped in.
                */

                if (fgets(buf,78,stdin) == NULL) {      /* when we hit end of file, */
                        freopen("con", "r",stdin);      /* open the console         */
                        is_a_tty = 1;
                        echo_command=0;
                        continue;
                }

                if (echo_command) {
                        printf("cmd:%s",buf);
                }
                switch (buf[0]) {

                        case 'r':                     /* read port */
                                if (strlen(buf) >2) {   /* we have a wait specification */
                                token(&buf[1]);
                                        if (token_ptr != NULL) {        /* if pattern specified */
                                                sscanf(token_ptr,"%x",&match_byte);
                                                printf(
                                                "Waiting for byte %4.4x.  Hit any key to terminate\n");
                                                read_port();
                                                while (!kbhit()) {
                                                        save_byte=byte;
                                                        read_port();
                                                        if (byte == match_byte) {
                                                                printf("Pattern %4.4x found, hit any key.\n",byte);
                                                                byte=save_byte;
                                                                break;
                                                        }
                                                        byte=save_byte;
                                                } /* while */
                                                getch();        /* clears the port */
                                        }  /* if token_ptr */
                                } else {
                                        read_port();
                                }
                                break;

                        case 'w':                     /* write port */
                                if (strlen(buf) >2) {   /* we have a wait specification */
                                token(&buf[1]);
                                        if (token_ptr != NULL) {        /* if pattern specified */
                                                sscanf(token_ptr,"%x",&match_byte);
                                                printf(
                                                "Waiting for byte %4.4x.  Hit any key to terminate\n",
                                                  match_byte);
                                                write_port();
                                                while (!kbhit()) {
                                                        save_byte=byte;
                                                        read_port();
                                                        if (byte == match_byte) {
                                                                printf("Pattern %4.4x found, hit any key.\n",byte);
                                                                byte=save_byte;
                                                                break;
                                                        }
                                                        byte=save_byte;

                                                } /* while */
                                                getch();        /* clears the port */
                                        }  /* if token_ptr */
                                } else {
                                        write_port();
                                }
                                break;

                        case 'e':                     /* enter byte in default mode */
                                switch (buf[1]) {
                                case 'x':              /* enter byte in hex mode*/
                                        token(&buf[2]);
                                        gak=0;
                                        sscanf(token_ptr, "%x",&gak);
                                        byte = gak;
                                        entry_mode=HEX;
                                        break;
                                case 'd':              /* enter byte in decimal mode*/
                                        token(&buf[2]);
                                        gak=0;
                                        sscanf(token_ptr, "%u",&gak);
                                        byte = gak;
                                        entry_mode=DEC;
                                        break;
                                default:                /* use the default mode */
                                        token(&buf[2]);
                                        gak=0;
                                        if (entry_mode == HEX)
                                                sscanf(token_ptr, "%x",&gak);
                                        else
                                                sscanf(token_ptr, "%u",&gak);
                                        byte = gak;
                                        break;

                                }
                                break;

                        case 't':                     /* toggle designated bit */
                                if (buf[1] == 'a') {
                                        byte = ~ byte;  /* special case, flip all bits */
                                        break;
                                }

                                token(&buf[1]);
                                sscanf(token_ptr, "%d", &gak);
                                toggle_bit(gak);
                                break;

                        case 'i':
                                port++;
                                break;

                        case 'd':
                                port--;
                                break;

                        case 'm':                     /* set entry mode, hex, dec, byte, word */
                                switch (buf[1]) {
                                        case 'x':
                                                entry_mode = HEX;
                                                break;
                                        case 'd':
                                                entry_mode = DEC;
                                                break;
                                        case 'b':
                                                byte_mode = BYTE;
                                                break;
                                        case 'w':
                                                byte_mode = WORD;
                                                break;
                                        case '\0':      /* nothing entered */
                                        default:
                                                break;
                                }
                                break;

                        case 'c':                     /* clear all bits */
                                byte = 0;
                                break;
                        case 's':                     /* set all bits */
                                byte = ~0;
                                break;
                        case 'p':                     /* set port address */
                                token(&buf[1]);
                                if (entry_mode == HEX)
                                        sscanf(token_ptr, "%x",&gak);
                                else
                                        sscanf(token_ptr, "%u",&gak);
                                if (gak)
                                        port = gak;
                                break;

                        case 'q':                     /* quit */
                                puts("");
                                exit(0);

                        case 'g':                     /* go continuously, repeat last I/O op */
                                switch (buf[1]) {
                                        case 'i':              /* input mode */
                                                rep_io(IN);
                                                break;
                                        case 'o':
                                                rep_io(OUT);
                                                break;
                                        default:
                                                puts("Say What???");
                                                break;
                                }
                                break;

                        case '<':                     /* get commands from a file */
                                token(&buf[1]);
                                if ( freopen(token_ptr,"r",stdin) == NULL ) {
                                        printf("Cannot open file\n");
                                        break/* let the check at the head of the loop */
                                }                     /* reopen the console */
                                is_a_tty=0;
                                echo_command=1;
                                break;

                        case '?':                     /* show help */
                                help();
                                break;
                        default:
                                puts("Say What???");
                } /* switch buf[0] */
                print_it();

        }       /* for (;;) */

} /* main */

print_it()
{
        int i,j;
        unsigned int bit;
        extern char * to_bin();

        if (is_a_tty) {
                printf("                                     Bits\n");
                printf("                             5432 1098 7654 3210\n");
        }
        if (entry_mode == HEX) {
                printf("Port:  %4.4x    Byte:  %4.4x,  %s  ", port, byte, to_bin(byte));
                printf("Mode= HEX  ");
        } else {
                printf("Port: %5.5u    Byte: %5.5u,  %s  ", port, byte, to_bin(byte));
                printf("Mode= Decimal  ");
        }
        if (byte_mode == BYTE) {
                printf("Data= BYTE\n");
        } else {
                printf("Data= WORD\n");
        }
}

/* convert an unsigned int to a binary string */
char *
to_bin(bit)
unsigned int bit;
{

        static char string[25];
        int i,j;

        memset(string,0,25);

        /* convert the byte to binary */
        for (i=0,j=0; i<16; i++,j++) {
                if ( bit & 0x01) {
                        string[18-j] = '1';
                } else {
                        string[18-j] = '0';
                }
                if (!((i+1)%4) && i>1)
                        string[18- ++j] = ' ';

                bit = bit >>1;
        }

        return (string);
}

prompt()
{
        if (is_a_tty) {
                printf("Command (help-?): ");
        }
        return;
}

read_port()
{

        if (byte_mode == BYTE) {
                byte = inportb(port);
        } else {
                byte = inport(port);
        }

        return;
}

write_port()
{
        if (byte_mode == BYTE) {
                outportb(port,byte);
        } else {
                outport(port,byte);
        }
        return;

}

help()
{
        printf("\nUsage: port <port_address data>  Arguments are in hex\n");
        printf("\nCommands:\n");
        printf("        \n");
        printf("r           read the port\n");
        printf("w           write the port\n");
        printf("e<xd>       Enter a byte (word in designated mode, hex or decimal)\n");
        printf("m<xdbw>     Mode (x=hex, d=dec, b=byte, w=word)\n");
        printf("t n         Toggle bit <n>\n");
        printf("c           Clear all bits\n");
        printf("s           Set all bits\n");
        printf("p           Set port address\n");
        printf("g<io>       Go In or Go Out - perform action continuously\n");
        printf("i           Increment port address one count\n");
        printf("d           Decrement port address one count\n");
        printf("q           Quit\n");
        printf("<           Redirect commands from a file\n");
        printf("?           Help\n\n");
        printf("While in \"go out\" mode, keys 0-f will toggle bits, <t> will cause the output\n");
        printf("to alternate between the byte pattern and all zeros.\n\n");
}

/****************************************************************************/
/* token takes a string passed in x and stores the next token in the global */
/* variable token_ptr.                                                      */
/* The function returns a pointer to the next character past the end of         */
/* the token                                                 */
/****************************************************************************/

#define WHITESPACE 1
#define TOKEN 2
char *
token(x)
char *x;
{
        int state = WHITESPACE;
        static char *pointer;

        pointer = (char *) NULL;

        while (*x != (char) NULL) {
                switch (*x) {
                        case ' ':
                        case '\x09':    /* tab */
                                if (state == TOKEN) {
                                        *x = '\x0';     /* null terminate */
                                        token_ptr=pointer;      /* point to beginning of this token */
                                        return(++x);
                                } else {
                                        ++x;    /* skip this character */
                                        state = WHITESPACE;
                                }
                                break;

                        case '\n':
                                *x = '\x0';     /* null terminate return string */
                                token_ptr = pointer;
                                return((char *) 0);
                        default:                /* this must be a token */
                                if (state == WHITESPACE) {
                                        pointer=x++;    /* set pointer to start of token */
                                        state=TOKEN;
                                } else {
                                        x++;
                                        state=TOKEN;
                                }
                                break;
                } /* switch */

        } /* while */

        if (state == TOKEN) {
                *x = '\x0';
                token_ptr = pointer;
                return ( (char *) NULL);
        } else {
                token_ptr = (char *) NULL;
                return ( (char *) NULL);
        }
}

rep_io(x)
int x;  /* mode, input or output */
{
        unsigned int i;
        char str[20];
        int inp;
        int toggle = 0;
        unsigned int tmp_byte;
        int old_byte;
        int dirty;

        toggle = 0;
        i = 0;
        old_byte=0;
        dirty=0;

        if (x == OUT) {
                printf(
"\nContinuous output - Press keys 0-f to toggle bits, <t> to toggle between\n");
                printf("output byte and 0000.  Hit <enter> to stop. ");
        } else {
                printf("\nContinuous input - hit <enter> to stop. ");
        }
        printf("\"<\" and \">\" changes port address\n");
        printf("Hit any other key to update screen.\n\n");


        if (entry_mode == HEX) {
                sprintf(str,"%4.4x",port);
        } else {
                sprintf(str,"%5.5u",port);
        }

        printf("Port = %s\n", str);
        showit(x,i,toggle);

        for ( ;; ) {

                if (kbhit() ) {  /* if keyboard input, process to toggle bits */
                        inp = getch();
                        switch (inp) {
                                case '\n':
                                case '\r':
                                        puts(" ");
                                        return;
                                case '0':
                                case '1':
                                case '2':
                                case '3':
                                case '4':
                                case '5':
                                case '6':
                                case '7':
                                case '8':
                                case '9':
                                        if (x == OUT)
                                                toggle_bit(inp-'0');
                                                dirty = ~dirty;
                                        break;
                                case 'a':
                                case 'b':
                                case 'c':
                                case 'd':
                                case 'e':
                                case 'f':
                                        if (x == OUT)
                                                toggle_bit(inp - 'a' + 10);
                                                dirty = ~dirty;
                                        break;
                                case 't':       /* toggle between outputing byte and 0000 */
                                        if (x == OUT) {
                                                toggle = ~toggle;
                                                showit(x,i,toggle);
                                        }
                                        break;
                                case '<':
                                        port--;
                                        if (entry_mode == HEX) {
                                                sprintf(str,"%4.4x",port);
                                        } else {
                                                sprintf(str,"%5.5u",port);
                                        }

                                        printf(" Port = %s\n", str);
                                        showit(x,i,toggle);
                                        break;

                                case '>':
                                        port++;
                                        if (entry_mode == HEX) {
                                                sprintf(str,"%4.4x",port);
                                        } else {
                                                sprintf(str,"%5.5u",port);
                                        }

                                        printf(" Port = %s\n", str);
                                        showit(x,i,toggle);
                                        break;

                                default:        /* any other key updates the screen */
                                        showit(x,i,toggle);
                                        break;
                        }
                } /* if */

                /* actually do the port thang */
                if (x == IN) {
                        old_byte = byte;
                        read_port();
                        if (old_byte != byte)
                                showit(x,i,toggle);
                       
                } else {        /* output mode */
                        if (dirty) {
                                dirty = ~dirty;
                                showit(x,i,toggle);
                        }

                        /* if toggle specified, then alternate between the byte and
                                all 0000 */

                        if (toggle) {
                                if (i%2) {
                                        tmp_byte = byte;
                                        byte = 0;
                                        write_port();
                                        byte = tmp_byte;
                                } else {
                                        write_port();
                                }
                        } else {  /* if not toggle */
                                write_port();
                        }
                }
                i++;
        }
}

/* this routine toggles a specified bit in the global variable byte */
toggle_bit(x)
{
        unsigned int bits[] = {
                0x01,
                0x02,
                0x04,
                0x08,
                0x10,
                0x20,
                0x40,
                0x80,
                0x100,
                0x200,
                0x400,
                0x800,
                0x1000,
                0x2000,
                0x4000,
                0x8000,
        };

        byte = byte ^ bits[x%16];
        return;
}

/* update screen during continuous output or input */
showit(x,i,toggle)
int x;
int i;
int toggle;
{
        extern char * to_bin();

        if (x == IN) {
                if (entry_mode == HEX) {
                        printf("\rRead loop:%5.5u, value = %4.4x, %s", i,byte,to_bin(byte));
                } else {
                        printf("\rRead loop:%5.5u, value = %5.5u, %s", i,byte,to_bin(byte));
                }
        } else {
                if (entry_mode == HEX) {
                        printf("\rWrite loop:%5.5u, value = %4.4x, %s", i,byte,to_bin(byte));
                } else {
                        printf("\rWrite loop:%5.5u, value = %5.5u, %s", i,byte,to_bin(byte));
                }

                if (toggle) {
                        printf("    toggling");
                } else {
          &nb