/* * 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 (jgd@dixie.com) * 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 #include /***** 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. (jgd@dixie.com)\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 Arguments are in hex\n"); printf("\nCommands:\n"); printf(" \n"); printf("r read the port\n"); printf("w write the port\n"); printf("e Enter a byte (word in designated mode, hex or decimal)\n"); printf("m Mode (x=hex, d=dec, b=byte, w=word)\n"); printf("t n Toggle bit \n"); printf("c Clear all bits\n"); printf("s Set all bits\n"); printf("p Set port address\n"); printf("g 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, 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, to toggle between\n"); printf("output byte and 0000. Hit to stop. "); } else { printf("\nContinuous input - hit 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 { printf(" "); } } return; } /************************** end of file **********************************/