/*************************************************************************** * i64.c -- program to blast data to any or all intelliport-II ports * * * * compile: i.bat * * -ls pass option s to the linker * * -w warnings on * * -1 generate 80186 instructions * * -B call assembler for inline code * * -S produce assembly listing * * -G optimize for speed * * -ml large model * * bcc -ls -w -1 -B -G -ml -wuse i64.c > a * * * * vi users, set shiftwidth=4, tabstop=4 to format correctly * * * * xon argument actually means xon/xoff (bidirectional) * * cts argument actually means cts/rts (bidirectional) * * allows for argument file (@name) * * receive flow control * * send any command packet at any time (e.g., rcv flow control!) * * if no options specified, runs all ports at 9600, 8bits, no parity, * * 1stop, no xon/xoff, no loopback * ***************************************************************************/ /*************************************************************************** revision history refer to the rcs log also for revision log messages after 9/91 ***************************************************************************/ #define VERSION "2.02" #if COMMENT 2.01 -- 1/7/92 MAG Changed many 'else if' chains to switches 2.02 -- 1/28/92 MAG Now treats embedded 8-port boxes properly. 1.10 -- 10/9/91 broke it up into smaller procedures moved global variables into procedures minor printout changes 1.00 -- 10/1/91 had to go to large model because of amount of data trying to break main up into smaller procedures 0.05 -- 9/12/91 supports 8-16 bit expandable, non-expandable uses ff.lod, not included fip_firm.h sets fifo_size automatically (but can still be overriden smaller from the command line argument "fifo=x") supports non-expandables as well "rconly" switch for receive only (i.e., no data transmit) "maxblock" switch for setting max incoming block size 0.04 -- 6/26/91 totally fixed for 16 bit 0.03 -- 3/6/91 modified for Rev. A artwork (reset at base+7, not +4) 0.02 -- 2/28/91 split out to separate channel structures cleaned up comments & structure added input capability supports any number of ports up to 64 0.01 -- 2/22/91 spiffed up a bit 0.00 -- 2/7/91 first version -- specific for 8-port only #endif /*************************************************************************** include files ***************************************************************************/ #include #include #include #include #include #include #include #include #include "termio.h" /*************************************************************************** manifest constants ***************************************************************************/ #define debugf printf #define MAXCHAN 64 //various fifo command register bits #define MB 0x04 #define I_EMPT 0x20 #define O_EMPT 0x01 #define SHIFT 0x40 #define SY_NCOM 20 //size of pending sync command buffer #define BP_NCOM 20 //size of pending bypass command buffer #define MAX_PAT 200 //size of tx & rc buffers //threshold for issuing flow control info to the board #define RECEIVE_THRESHOLD (4 * MAX_PAT / 5) // special key values #define ESCAPE 0x1B #define EXTENDED 0x100 #define FKEY_1 (0x3B + EXTENDED) #define FKEY_2 (0x3C + EXTENDED) #define FKEY_3 (0x3D + EXTENDED) #define FKEY_4 (0x3E + EXTENDED) #define FKEY_5 (0x3F + EXTENDED) #define FKEY_6 (0x40 + EXTENDED) #define FKEY_7 (0x41 + EXTENDED) #define FKEY_8 (0x42 + EXTENDED) #define FKEY_9 (0x43 + EXTENDED) #define FKEY_10 (0x44 + EXTENDED) /*************************************************************************** macros ***************************************************************************/ #define MIN(a,b) ( (a) < (b) ? (a) : (b) ) #define MAX(a,b) ( (a) > (b) ? (a) : (b) ) /*************************************************************************** definitions of typedefs, enums, strucs, unions ***************************************************************************/ typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned int uint; typedef unsigned long ulong; //structure for each channel typedef struct { ushort as_of_out; // "as of" flow control (the outbound direction) ushort room_for_out; // "room for" flow control (outbound) ushort as_of_in; // "as of" flow control (inbound) ushort room_for_in; // "room for" flow control (inbound) ulong chars_out; // total out ulong chars_in; // total in ushort nstrip; // how many receive characters we have processed // since last flow control message we sent // the board int nptr; // index into pattern int nloop; // number of chars currently in the loopback buffer char pattern[MAX_PAT]; // the string to output char expected[MAX_PAT]; // the string we're expecting back char inbuf[MAX_PAT]; // the input buffer for loopback testing // Let the counts PRECEDE the buffers... char sy_ncmd; // number of bytes of sync cmds pending in buf char bp_ncmd; // number of bytes of bypass cmds pending in buf char sy_cmds[SY_NCOM]; // synchronous command buffer char bp_cmds[BP_NCOM]; // bypass command buffer char do_it; // 1=this channel is selected for work // 2=selected for work, but no output! char i_exist; // set if channel supposed to exist. char xon_flag; // 0=no flow control, 1=xon/xoff, 2=cts/rts // 3= dtr/dcd 4=dtr/dsr char baud_flag; // baud rate indicator char loopback_flag; // loopback indicator char nbits_flag; // number of bits per character char stop_flag; // number of stop bits per character char parity_flag; // parity mode char one_packet_mode; // used to control transmission char send_one_packet; // used to control transmission char tag; // data packet tag for alt screens etc. } cstruc; //fatal error codes enum error { FATAL_HEADER = 0, FATAL_DOWNLOAD = 1, FATAL_STATUS = 2, FATAL_ROOM = 3, FATAL_TIMER = 4, FATAL_STUFF = 5, FATAL_CHANNELS = 6, FATAL_OUTBOUND = 7, FATAL_NCOM = 8, FATAL_SIZE = 9, FATAL_MATCH = 10, FATAL_PLEN = 11, FATAL_AMOUNT = 12, FATAL_BOARD = 13, }; typedef union { ushort word; struct { uchar lo; uchar hi; } byte; } Word_Flag; /*************************************************************************** function prototypes ***************************************************************************/ int main (int argc, char**argv); void init_channels (void); void process_args (int argc, char**argv); void print_ch_list (void); void print_flow_control (void); void print_total_chars (void); void configure_channels (void); void download_firmware (void); void make_chan_list (void); void set_polling_mode (void); void check_keyboard (void); void check_timer (void); void send_flow_control (void); void hit_board_mbox (void); void receive_packets (void); void receive_data (void); int receive_status (int, int); void send_packets (void); int send_bp_commands (int); int send_sy_commands (int); int send_data (int); void fatal_error (enum error code); void my_sleep (int secs); void send_256 (uchar *buf); void stuff_flow_control (void); void reset_board (void); void abort_useage (char *); void user_commands (void); int parseArgument (char *); /*************************************************************************** global data in C programs you need to be able to differentiate between global variables and local variables, so capitalize globals ***************************************************************************/ ushort Base = 0x308; //base address of board -- may be overriden // by command-line option ushort Data; //address of data port ushort Command; //address of command port ushort Reset; //board reset address ushort MailBox; //mailbox address int Fifo_Size; //size reported by board int Fifo_Size_Request = 0; //size to use int Max_Ports = 0; //read from the fifo int Use_Ports = 0; //set by np= argument int No_Receive = 0; //stop receiving data int No_Transmit = 0; //stop sending data int noInputTest = 0; int Num_Chans_Out = 0; //number of channels we're testing int Num_Chans_In = 0; //number of channels doing input char Chan_List[MAXCHAN]; //list of channel numbers we're testing int Num_Apply; //number of ports in a "ports=" argument char Chan_Apply[MAXCHAN]; //list of channel number for apply cstruc Channel[MAXCHAN+1]; // the channel structures //the pattern to output -- first byte will be replaced by channel number, // other bytes will be replaced by line number //change the word "odd" to "even" to make it an even size pattern char Pattern[] = "00/0000000 -odd- ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz\015\012"; int Pat_Len = sizeof Pattern - 1; //length of pattern int Xmit_Ack = 1; // 1=got a transmit ack // 0=don't currently have one // assume we have a transmit ack so we could theoretically start xmitting // immediately; but we really can't until we get flow control info unsigned char Mailbox_Requests = 0; //mailbox bits to hit the board with char *Bauds[] = { "0", "50", "75", "110", "134", "150", "200", "300", "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400", "2000", "3600", "7200", "56000", "57600", "64000", "76800", "115200" }; long Chars_Out = 0l; //number of characters output in 10 seconds long Chars_In = 0l; //number of characters input in 10 seconds int Debug = 0; //debugging option char Chan; //a channel number we're working on Word_Flag Oflag = 0; // unix output flag Word_Flag Lflag = 0; // unix line flag Word_Flag Cflag = 0; // unix control flag Word_Flag Iflag = 0; // unix input flag time_t Old_Time, New_Time; //for rate timing int Continuous = 0; //for Continuous dataset signal changes int Sixteen_Bit = 0; //non-zero means 16-bit interface int Expandable; //1 if ex, 0 if non-ex int Receive_Only = 0; //1 for receive only int Download = 0; //download the firmware and exit int PauseOption = 0; //pause for a key before continuing int Dump = 0; //dump output to console int Dump_Chan = 0; //the channel to dump int PrintCps = 1; //print out cps numbers int Increment = 1; //increment line numbers in pattern int ShowFlow = 0; //print out flow control packets int ShowHits = 0; //print out mailbox hits to board int ShowStuff = 0; //print out all transmittals int ShowData = 0; //print out data transmittals int ShowBypass = 0; //print out bp cmd transmittals int ShowSynch = 0; //print out sy cmd transmittals char *Error_Msgs[] = { "fifo empty, expected header data", // FATAL_HEADER "expected 0xC3 return code", // FATAL_DOWNLOAD "unexpected status type received", // FATAL_STATUS "amount of room in fifo must be > 0", // FATAL_ROOM "timer must trigger at 10 second interval", // FATAL_TIMER "overstuffed the fifo", // FATAL_STUFF "number of channels must be > 0", // FATAL_CHANNELS "outbound block was not drained from fifo", // FATAL_OUTBOUND "too many commands in command buffer", // FATAL_NCOM "received packet is too large", // FATAL_SIZE "input message does not match output", // FATAL_MATCH "pattern length is too big for buffers", // FATAL_PLEN "maximum data packet count is 0xFFF", // FATAL_AMOUNT "the board is fatal and not operational", // FATAL_BOARD }; int cpi; /* Characters per this interrupt */ int avecpi; /* Average per interrupt */ int icount; /* Count of interrupts */ /*************************************************************************** main - poll the board, sending and receiving packets ***************************************************************************/ int main (int argc, char**argv) { printf ("i64 - version %s, ", VERSION); if (Pat_Len > MAX_PAT) fatal_error(FATAL_PLEN); init_channels(); // initialize channel strucs process_args(argc,argv); // command line or command file reset_board(); // reads the power up message download_firmware(); // copy ff.lod to the board if (Pat_Len > Fifo_Size) fatal_error(FATAL_PLEN); if (!Expandable) { outp (Command, 2); //initialize the mask register outp (Command, MB); } make_chan_list(); // list of channels to test set_polling_mode(); // specify no irq will be used if (Download) exit(0); // download only if (PauseOption) { printf("\nHit a key when ready...\n"); while (!kbhit()) {} // wait for key... } print_ch_list(); // print some channel info my_sleep (2); // let firmware ramp up configure_channels(); // send initialization commands time (&Old_Time); // start time for cps calculations MAIN_LOOP: check_keyboard(); // user commands check_timer(); // calculate cps values send_flow_control(); // maybe build flow control pkts hit_board_mbox(); // mailbox hits to the board if (inp(Command) & MB) // mailbox hit from the board? receive_packets(); // yes, receive packets if (Xmit_Ack) // got a an ack for transmit? send_packets(); // yes, send packets goto MAIN_LOOP; } /*************************************************************************** initialize all channel structures and Chan_Apply ***************************************************************************/ void init_channels(void) { int i; for (i=0; i 0x3f8) abort_useage(argument); break; case ARG_DEBUG: Debug = 1; break; case ARG_PAUSE: PauseOption = 1; break; case ARG_QUESTION: user_commands(); abort_useage(""); break; case ARG_SHOWFLOW: ShowFlow = 1; break; case ARG_SHOWHITS: ShowHits = 1; break; case ARG_SHOWDATA: ShowData = 1; break; case ARG_SHOWBP: ShowBypass = 1; break; case ARG_SHOWSY: ShowSynch = 1; break; case ARG_SINGLE: for (i=0; i MAX_PAT ) fatal_error(FATAL_PLEN); for (i=0; i 8) abort_useage(argument); for (i=0; i 128) abort_useage(argument); Channel[0].bp_cmds[0] = 28; Channel[0].bp_cmds[1] = temp; Channel[0].bp_ncmd = 2; //two bytes of pending bypass commands } break; //specifying fifo size case ARG_FIFO: { int temp; i = sscanf (&argument[5], "%d", &temp); if (i != 1) abort_useage(argument); if (temp < 512 || temp > 4096) abort_useage(argument); Fifo_Size_Request = temp; } break; case ARG_DUMP: //dump output to the console { int temp; i = sscanf (&argument[5], "%d", &temp); if (i != 1) abort_useage(argument); if (temp < 0 || temp > 64) abort_useage(argument); Dump_Chan = temp; Dump = 1; } break; case ARG_NP: //specifying number of ports { int temp; i = sscanf (&argument[3], "%d", &temp); if (i != 1) abort_useage(argument); if (temp < 1 || temp > 64) abort_useage(argument); Use_Ports = temp; } break; case ARG_STOP: //specifying number of stop bits per character { int temp = -1; if (strcmp (&argument[5], "1") == 0) temp = 0; else if (strcmp (&argument[5], "1.5") == 0) temp = 1; else if (strcmp (&argument[5], "2") == 0) temp = 2; if (temp == -1) abort_useage(argument); for (i=0; i 63) abort_useage(argument); //see if temp is already in the list for (k=0; k '9') abort_useage(argument); temp = temp * 10 + j - '0'; continue; } if (temp < 0 || temp > 63) abort_useage(argument); //see if temp is already in the list for (k=0; k 63) abort_useage(argument); Channel[temp].do_it = 0; } else if (j < '0' || j > '9') abort_useage(argument); temp = temp * 10 + j - '0'; continue; } if (temp < 0 || temp > 63) abort_useage(argument); Channel[temp].do_it = 0; } break; case ARG_XOUT: { int temp = 0; Num_Apply = 0; //how many we're doing pnt = &argument[5]; while ((j = *pnt++) != 0) { if (j == ',') { if (temp < 0 || temp > 63) abort_useage(argument); Channel[temp].do_it = 2; } else if (j < '0' || j > '9') abort_useage(argument); temp = temp * 10 + j - '0'; continue; } if (temp < 0 || temp > 63) abort_useage(argument); Channel[temp].do_it = 2; } break; case ARG_INVALID: default: abort_useage(argument); } } Data = Base + 0; //data address Command = Base + 2; //command address MailBox = Base + 3; //mailbox register Reset = Base + 7; //reset address } typedef struct _alist { int length; char *testarg; int retval; } alist, *alistPtr; alist alTable[] = { 5, "base=", ARG_BASE, /* Board's base address */ 0, "debug", ARG_DEBUG, 0, "?", ARG_QUESTION, 0, "help", ARG_QUESTION, 0, "showflow", ARG_SHOWFLOW, 0, "showdata", ARG_SHOWDATA, 0, "showbp", ARG_SHOWBP, 0, "showsy", ARG_SHOWSY, 0, "single", ARG_SINGLE, 8, "pattern=", ARG_PATTERN, 0, "rconly", ARG_RCONLY, 0, "download", ARG_DOWNLOAD, 6, "nbits=", ARG_NBITS, 9, "maxblock=", ARG_MAXBLOCK, 5, "fifo=", ARG_FIFO, 5, "dump=", ARG_DUMP, 3, "np=", ARG_NP, 5, "stop=", ARG_STOP, 7, "parity=", ARG_PARITY, 0, "xon", ARG_XON, 0, "noflow", ARG_NOFLOW, 0, "ctsflow", ARG_CTSFLOW, 0, "loopback", ARG_LOOPBACK, 0, "internal", ARG_INTERNAL, 6, "oflag=", ARG_OFLAG, 0, "notest", ARG_NOTEST, 0, "nocps", ARG_NOCPS, 5, "baud=", ARG_BAUD, 0, "ports=all", ARG_ALL, 6, "ports=", ARG_PORTS, 7, "xports=", ARG_XPORTS, 5, "xout=", ARG_XOUT, 0, "pause", ARG_PAUSE, 0, "ignore", ARG_IGNORE, 0, "dcdflow", ARG_DCDFLOW, 0, "dsrflow", ARG_DSRFLOW, 0, "showhits", ARG_SHOWHITS, -1, "", 0, /* -1 length is the bumper! */ }; int parseArgument (register char *argument) { register alistPtr pAlist = alTable; while (1) { switch(pAlist->length) { case -1: return ARG_INVALID; case 0: if (strcmp(argument, pAlist->testarg) == 0) { return pAlist->retval; } break; default: if (strncmp(argument, pAlist->testarg, pAlist->length) == 0) { return pAlist->retval; } break; } pAlist++; } } /*************************************************************************** print_ch_list ***************************************************************************/ void print_ch_list(void) { int i; printf ("Testing ports: "); for (i=0; i= 0) //baud rate specified { Channel[Chan].sy_cmds[Channel[Chan].sy_ncmd++] = 7; Channel[Chan].sy_cmds[Channel[Chan].sy_ncmd++] = Channel[Chan].baud_flag; } j = Channel[Chan].nbits_flag; if (j >= 0) //bits per character specified { Channel[Chan].sy_cmds[Channel[Chan].sy_ncmd++] = 8; Channel[Chan].sy_cmds[Channel[Chan].sy_ncmd++] = Channel[Chan].nbits_flag; } j = Channel[Chan].stop_flag; if (j >= 0) //stop bits specified { Channel[Chan].sy_cmds[Channel[Chan].sy_ncmd++] = 9; Channel[Chan].sy_cmds[Channel[Chan].sy_ncmd++] = Channel[Chan].stop_flag; } j = Channel[Chan].parity_flag; if (j >= 0) //parity specified { Channel[Chan].sy_cmds[Channel[Chan].sy_ncmd++] = 10; Channel[Chan].sy_cmds[Channel[Chan].sy_ncmd++] = Channel[Chan].parity_flag; } j = Channel[Chan].loopback_flag; //send initial flow control if (j == 2) // internal loopback { Channel[Chan].sy_cmds[Channel[Chan].sy_ncmd++] = 61; Channel[Chan].sy_cmds[Channel[Chan].sy_ncmd++] = 1; } if (j) // if we are doing loopbacks stuff_flow_control (); } } /*************************************************************************** download_firmware from the ff.lod file ***************************************************************************/ void download_firmware(void) { int i; int fflod_file; uchar fflod_more; uchar fflod_buffer[512]; // stack - caution fflod_file = open ("ff.lod", O_RDONLY | O_BINARY); if (fflod_file <= 0) { printf ("\n\007Error -- no ff.lod found\n"); exit (1); } read (fflod_file, fflod_buffer, 512); fflod_more = fflod_buffer[1]; //how many more blocks printf ("downloading %d blocks ", fflod_more+1); send_256 (fflod_buffer); //send the first block for (i=1; i SY_NCOM - 4) break; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 54; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x05; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x07; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 54; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x03; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x00; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 54; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x04; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x00; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 54; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x05; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x00; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 54; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x0F; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x00; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 54; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x10; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x00; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 54; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x11; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x00; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 54; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x3D; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x00; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 54; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x3E; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x00; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 54; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x3F; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x00; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 54; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0xF5; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x00; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 54; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0xF6; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x00; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 54; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0xF7; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x00; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 54; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0xD4; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x03; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 54; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0xD5; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x03; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 54; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0xD6; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x03; // 480 01E0h // 960 03C0h // 1920 0780h // 3840 0F00h // 9000 2328H //11520 2D00h //25000 61A8h -- Seems to overrun receiver! // 4 4h // 61 3dh // 245 f5h // 980 3d4h // 4000 fa0h //10000 2710h #define TEST_DIVISOR 1 #ifndef TEST_DIVISOR Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 54; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x10; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x27; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 7; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 24; #else // 2304 (900h)= 50 baud // 1 (1h) = 115200 baud // 8 (8h) = 14400 baud Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 80; /* Command */ Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 3; /* tx and rx */ Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x08; /* lsb div. */ Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x00; /* msb div. */ #endif break; //stop receiving data (so it will issue xoff) case '.': No_Receive = 1; break; case ':': No_Transmit = 1; break; //start receiving data (so it will issue xon) case ',': No_Receive = 0; break; case ';': No_Transmit = 0; break; // To test sending xon/xoff as bypass... case '0': Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 16; Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 0; // xon/xoff off Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 17; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 1; break; case '1': //custom incoming xon character if (count > SY_NCOM - 3) break; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 11; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = '('; break; case '2': //custom incoming xoff character if (count > SY_NCOM - 3) break; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 12; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = ')'; break; case '3': //change xmit baud rate to 1200 if (count > SY_NCOM - 3) break; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 42; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 9; break; case '4': //change receive baud rate to 2400 if (count > SY_NCOM - 3) break; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 43; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 11; break; case '5': // enable live diagnostic // Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 87; // Reset channel 5's receive threshold // if (count > SY_NCOM - 4) break; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 88; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 1; // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 250; // Demand a report of DSS's Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 89; break; case '6': // disable receiver ints Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 86; Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 2; break; case '7': // enable receiver ints Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 86; Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 3; break; case '8': //custom outgoing xon character if (count > SY_NCOM - 3) break; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 63; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = '#'; break; case '9': //custom outgoing xoff character if (count > SY_NCOM - 3) break; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 64; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = '$'; break; //auto rts case 'a': case 'A': if (count > SY_NCOM - 3) break; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 65; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 1; break; // enable all types of status reporting case FKEY_3: if (count > SY_NCOM - 7) break; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 18; // cts Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 20; // dcd Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 22; // dsr Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 24; // ring Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 26; // break... Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0; // as status pkt break; //report breaks, send break case 'B': case 'b': if (count > SY_NCOM - 5) break; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 26; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 4; /* status & flush */ // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0; /* status */ // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x1a; /* status & null */ // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0xa; /* status & seq*/ // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 11; /* Send posix 3ple */ Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 35; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 250; /* original */ break; case 'c': //send Continuous dataset signal changes if (Continuous) Continuous = 0; else Continuous = 2; break; #ifdef ORIGINAL //assert dtr case 'D': if (count > SY_NCOM - 2) break; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 2; break; //deassert dtr case 'd': if (count > SY_NCOM - 2) break; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 3; break; #else //assert dtr case 'D': Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 2; break; //deassert dtr case 'd': Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 3; break; #endif /* ORIGINAL */ case 'E': // Start break Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 76; break; case 'e': // End break Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 77; break; case '?': // Request special status packet if (Channel[5].bp_ncmd + 10 > BP_NCOM) break; Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 81; Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 81; Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 81; Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 81; Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 81; Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 81; Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 81; Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 81; Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 81; Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 81; Channel[4].bp_cmds[Channel[4].bp_ncmd++] = 81; Channel[4].bp_cmds[Channel[4].bp_ncmd++] = 81; Channel[4].bp_cmds[Channel[4].bp_ncmd++] = 81; Channel[4].bp_cmds[Channel[4].bp_ncmd++] = 81; Channel[3].bp_cmds[Channel[3].bp_ncmd++] = 81; Channel[3].bp_cmds[Channel[3].bp_ncmd++] = 81; Channel[3].bp_cmds[Channel[3].bp_ncmd++] = 81; Channel[3].bp_cmds[Channel[3].bp_ncmd++] = 81; Channel[2].bp_cmds[Channel[2].bp_ncmd++] = 81; Channel[2].bp_cmds[Channel[2].bp_ncmd++] = 81; Channel[2].bp_cmds[Channel[2].bp_ncmd++] = 81; Channel[2].bp_cmds[Channel[2].bp_ncmd++] = 81; break; case '[': Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 85; Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 1; goto brack; case ']': Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 85; Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 0; brack: Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 0x55; Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 0x55; Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 0xAA; Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 0xAA; Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 0x55; Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 0x55; Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 0xAA; Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 0xAA; break; //async start flush case 'f': Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 6; break; //sync stop flush case 'F': if (count > SY_NCOM - 2) break; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 13; break; // start flush for a specific tag case FKEY_2: { static int tag = 0; Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 67; Channel[5].bp_cmds[Channel[5].bp_ncmd++] = tag; if (++tag == 15) tag = 0; } break; // p/f/o errors are exceptions causing status packets case 'g': if (count > SY_NCOM - 5) break; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 59; //enable parity check Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 36; //enable exceptions // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0x18;// user defined // Channel[5].sy_cmds[Channel[5].sy_ncmd++] = '!'; // user defined Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0; // 0 exception // 1 as good (lookout!) // 2 drop // 3 null // 4 parmark break; //un-inhibit output (as though Xon received) case 'i': case 'I': Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 41; break; //assert dtr, deassert dtr case 'j': if (count > SY_NCOM - 3) break; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 2; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 3; break; case 'J': /* Transmit immediate a '='*/ Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 79; Channel[5].bp_cmds[Channel[5].bp_ncmd++] = '='; break; //request bookmark case 'k': case 'K': if (count > SY_NCOM - 2) break; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 60; break; //no auto rts case 'm': case 'M': if (count > SY_NCOM - 3) break; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 65; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0; break; // disable output post processing case 'n': if (count > SY_NCOM - 2) break; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 40; break; case 'N': { static int i = 0; Channel[i].sy_cmds[Channel[i].sy_ncmd++] = 40; i++; if (i>=Max_Ports) i=0; } break; // enable output post processing case 'o': if (count > SY_NCOM - 4) break; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 39; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = Oflag.byte.lo; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = Oflag.byte.hi; break; case 'O': { static int i = 0; Channel[i].sy_cmds[Channel[i].sy_ncmd++] = 39; Channel[i].sy_cmds[Channel[i].sy_ncmd++] = Oflag.byte.lo; Channel[i].sy_cmds[Channel[i].sy_ncmd++] = Oflag.byte.hi; i++; if (i>=Max_Ports) i=0; } break; // unix flags case FKEY_9: if (count > SY_NCOM - 8) break; { Cflag.word = B9600 | CS8; Iflag.word = IGNBRK | IGNPAR; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 47; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = Iflag.byte.lo; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = Iflag.byte.hi; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = Cflag.byte.lo; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = Cflag.byte.hi; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = Lflag.byte.lo; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = Lflag.byte.hi; } break; //pause, 2 seconds case 'p': if (count > SY_NCOM - 3) break; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 56; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 200; break; //repetitive pinger, every 10 milliseconds case 'P': /* Can only send as in-line... */ if (count > SY_NCOM - 3) break; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 44; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 10; break; //resume case 'r': case 'R': Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 58; break; //suspend case 's': case 'S': Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 57; break; //assert rts case 'T': if (count > SY_NCOM - 2) break; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 4; break; //deassert rts case 't': if (count > SY_NCOM - 2) break; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 5; break; case 'U': /* Disable all HW xmit flow control immediately */ Channel[5].bp_cmds[Channel[5].bp_ncmd++] = 69; break; case 'w': /* Define a sequence */ if (count > SY_NCOM - 10) break; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 38; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 1; /* second one*/ Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 2; /* count*/ Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 'A'; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 'C'; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 38; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 2; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 2; /* count*/ Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 'D'; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 'F'; break; case 'W': /* Enable HOT KEY processing (!!) */ if (count > SY_NCOM - 2) break; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 45; break; // sends out one packet when in one packet mode case 'x': // Channel[0].send_one_packet = 1; Channel[5].send_one_packet = 1; break; // enable report DSS changes as data string also case 'Y': if (count > SY_NCOM - 3) break; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 75; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 1; break; // disable report DSS changes as data string also case 'y': if (count > SY_NCOM - 3) break; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 75; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 0; break; // change the hiwater mark (10-90)% case 'z': if (count > SY_NCOM - 3) break; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 66; Channel[5].sy_cmds[Channel[5].sy_ncmd++] = 99; break; default: putchar('\a'); // beep break; } if (Channel[5].sy_ncmd > SY_NCOM) fatal_error (FATAL_NCOM); } /*************************************************************************** calculate 10 second cps as well as moving average cps ***************************************************************************/ void check_timer(void) { static int not_first_time = 0; //eliminates first misleading stat static long newcps = 0; //10 second tx cps static long newcps_in; //10 second rc cps static long total_cps=0; //avg tx cps static long total_cps_in=0; //avg rc cps static long total_times=0; //number of 10 sec intervals if (!PrintCps) return; time (&New_Time); if (New_Time-Old_Time > 10) //better not happen! fatal_error (FATAL_TIMER); if (New_Time-Old_Time == 10) { if (not_first_time) { newcps = (Chars_Out + 5l*Num_Chans_Out) / (10l*Num_Chans_Out); //cps for the last 10 seconds if (Num_Chans_In) newcps_in = (Chars_In + 5l*Num_Chans_In) / (10l*Num_Chans_In); total_cps += newcps; total_cps_in += newcps_in; total_times++; //cps moving average if (Num_Chans_In) printf ("%ld/%ld, %ld/%ld cps; ", newcps, (total_cps + total_times/2) / total_times, newcps_in, (total_cps_in + total_times/2) / total_times); else printf ("%ld/%ld cps; ", newcps, (total_cps + total_times/2) / total_times); } not_first_time = 1; Old_Time = New_Time; //restart for another 10 seconds Chars_Out = 0l; //reset character counter Chars_In = 0l; } } /*************************************************************************** if any pending mailbox hits to the board, do them now ***************************************************************************/ void hit_board_mbox(void) { if (!Mailbox_Requests) //maybe do some hits return; if (Expandable) { if ((inp (Command) & 0x80) == 0) //mailbox available? { outp (MailBox, Mailbox_Requests); //write the mailbox if (ShowHits) { if (Mailbox_Requests & 0x80) putchar('X'); //stuffed xmit fifo if (Mailbox_Requests & 0x40) putchar('R'); //stripped rcv fifo } Mailbox_Requests = 0; //condition sent } } else { outp (Command, 4); //point to mailbox register if (inp (Command) == 0) //mailbox available? { outp (Command, 4); //write the mailbox outp (Command, Mailbox_Requests); if (ShowHits) { if (Mailbox_Requests & 0x80) putchar('X'); //stuffed xmit fifo if (Mailbox_Requests & 0x40) putchar('R'); //stripped rcv fifo } Mailbox_Requests = 0; //condition sent } } } /*************************************************************************** receive packets that were sent to us by the board ***************************************************************************/ void receive_packets(void) { int mbox_hits; int tmp; uchar byte2; //for interpreting incoming packets uchar status_type; //status type uchar status_count; //status type if (Expandable) mbox_hits = inp (MailBox); //read the inbound mailbox else { outp (Command, 6); //read the inbound mailbox mbox_hits = inp (Command); } //debugging info on mailbox hits if (ShowHits) { if (mbox_hits & 0x40) putchar('x'); //stripped xmit fifo if (mbox_hits & 0x80) putchar('r'); //stuffed rcv fifo } // if (mbox_hits < 0x20) // printf ("Unknown mailbox hit from board=%02X\a",mbox_hits); //the board has gone fatal if (mbox_hits & 0x20) fatal_error(FATAL_BOARD); //xmit ack -- ok to transmit more (board drained xmit fifo) if (mbox_hits & 0x40) Xmit_Ack = 1; //receive packets - board sent us some data or status packets cpi = 0; if (mbox_hits & 0x80) { //strip them out as long as the fifo is not empty while (!(inp (Command) & I_EMPT)) { // get the channel number and the packet type, first word if (Sixteen_Bit) { tmp = inpw (Data); Chan = tmp & 0xff; byte2 = tmp >> 8; } else { Chan = inp (Data); byte2 = inp (Data); } cpi += 2; /*************************************************************** data packet Note: the board does not send anything to the host until he gets initial flow control info since he assumes no room is the initial condition. Board will not send more than we can handle because of flow control credits ***************************************************************/ if (byte2 == 0) { receive_data(); continue; //maybe get another packet } if (byte2 == 1) { printf("Special Sequence Message\n"); receive_data(); continue; } /*************************************************************** here we have a status packet ***************************************************************/ //strip high 2 bits -- the rest is a count status_count = byte2 & 0x3f; cpi += status_count; /* If showing flow control, show the packet breakdowns */ if (ShowFlow) { printf("-P%x ", byte2); } while (status_count) //spin thru the packet { if (Sixteen_Bit) { tmp = inpw (Data); //channel low byte packet type high Chan = tmp & 0xff; //this is channel number status_type = tmp >> 8; } else { Chan = inp (Data); status_type = inp (Data); } status_count -= receive_status(Chan, status_type); } } // while (!(inp (Command) & I_EMPT)) // tell the board we emptied the receive data fifo Mailbox_Requests |= 0x40; avecpi = (avecpi + avecpi + avecpi + cpi) >> 2; icount++; } // if (mbox_hits & 0x80) } /*************************************************************************** receive_data the packet at the mouth of the fifo is a data packet note that Chan has been sent by the calling routine ***************************************************************************/ void receive_data(void) { int i; int count; int extra; char *pnt; static rxd_msg = 0; if (Channel[Chan].loopback_flag == 0) //shouldn't get data !! { if (rxd_msg == 0) //message only once { rxd_msg = 1; printf ("\n\007Error -- data received on channel %d\n", Chan); } } if (Sixteen_Bit) count = inpw (Data); //next byte is count else { count = inp (Data); //note 256 max? inp (Data); } cpi += count; if (Channel[Chan].nloop + count > MAX_PAT) fatal_error(FATAL_SIZE); Channel[Chan].as_of_in += count; //adjust flow control Channel[Chan].nstrip += count; Channel[Chan].chars_in += count; Chars_In += count; pnt = &Channel[Chan].inbuf[Channel[Chan].nloop]; asm push cx asm push di asm push dx asm push es asm push ds asm pop es // for large model! asm mov cx, count asm inc cx asm shr cx, 1 asm mov di, pnt asm mov dx, Data if (Sixteen_Bit) { asm rep insw } else { asm shl cx, 1 asm rep insb } asm pop es asm pop dx asm pop di asm pop cx Channel[Chan].nloop += count; // while (count--) //strip that many out // Channel[Chan].inbuf[Channel[Chan].nloop++] = inp (Data); // if not doing loopback throw away the received data chars if (Channel[Chan].loopback_flag == 0) { Channel[Chan].nloop = 0; return; } // do we have a complete pattern yet? if (Channel[Chan].nloop < Pat_Len) return; VERIFY_PATTERN: // here we have at least one complete pattern, check it, etc. if (!noInputTest && strncmp (Channel[Chan].expected, Channel[Chan].inbuf, Pat_Len)) { int counter; int value; printf ("\nchannel = %d\n",Chan); printf ("expected: %s\n", Channel[Chan].expected); printf (" got:"); for (counter = 0; counter < Channel[Chan].nloop; counter++) { value = Channel[Chan].inbuf[counter]; if (value >= ' ' && value <= 0x7e) printf("%c", value); else printf("%c%x", 0xa8, value); } printf("\n"); fatal_error(FATAL_MATCH); } // if we have some data remaining, slide it to begin of buffer extra = Channel[Chan].nloop - Pat_Len; if (extra) memcpy (Channel[Chan].inbuf, &Channel[Chan].inbuf[Pat_Len], extra); // if there's another pattern in the buffer, check it too // the board may send more than one pattern in a packet Channel[Chan].nloop -= Pat_Len; // took out one pattern if (Channel[Chan].nloop >= Pat_Len) goto VERIFY_PATTERN; // increment the line number count if necessary if (Increment) { for (i=9; i>=3; i--) { if (++Channel[Chan].expected[i] != '9'+1) break; Channel[Chan].expected[i] = '0'; } } } /*************************************************************************** receive status packet at the mouth of the fifo is a status packet ***************************************************************************/ int receive_status(int channel, int status_type) { int size = 0; int amt_in_fifo; //amt of channels data in the fifo ushort new_as_of, new_room_for, dummy; //new flow control info uchar byte_1, byte_2, byte_3, byte_4; if (channel < 0 || channel > MAXCHAN) { printf("Invalid! channel 0x%x status 0x%x\n", channel, status_type); channel = MAXCHAN; /* limit the damage */ } switch(status_type & 0xc0) { case 0x80: if (status_type & 0x01) printf("overrun %d ", channel); if (status_type & 0x02) printf("framing %d ", channel); if (status_type & 0x04) printf("parity %d ", channel); return 2; case 0xc0: printf("DSS=%x ", status_type & 0xf); return 2; default: break; } switch (status_type) { case 0: printf ("CTS%d \030 ", channel); size = 2; break; // active case 1: printf ("CTS%d \031 ", channel); size = 2; break; // inactive case 2: printf ("DCD%d \030 ", channel); size = 2; break; case 3: printf ("DCD%d \031 ", channel); size = 2; break; case 4: printf ("DSR%d \030 ", channel); size = 2; break; case 5: printf ("DSR%d \031 ", channel); size = 2; break; case 6: printf ("RI%d \030 ", channel); size = 2; break; case 7: printf ("RI%d \031 ", channel); size = 2; break; case 8: printf ("BREAK%d ", channel); size = 2; break; case 9: //flow control packet if (Sixteen_Bit) { new_as_of = inpw (Data); new_room_for = inpw (Data); } else { byte_1 = inp (Data); byte_2 = inp (Data); byte_3 = inp (Data); byte_4 = inp (Data); new_as_of = (byte_2 << 8) + byte_1; new_room_for = (byte_4 << 8) + byte_3; } // do the flow control thing amt_in_fifo = Channel[Chan].as_of_out - new_as_of; Channel[Chan].room_for_out = new_room_for - amt_in_fifo; if(ShowFlow) printf("%d:%u=%u-(%u-%u) ", Chan, Channel[Chan].room_for_out, new_room_for, Channel[Chan].as_of_out, new_as_of); size = 6; break; case 10: //bookmark printf ("Received bookmark, channel %d\n", Chan); size = 2; break; case 11: // special status packet case 12: case 13: case 14: case 15: if (Sixteen_Bit) { dummy = inpw (Data); byte_1 = dummy & 0xff; byte_2 = dummy >> 8; dummy = inpw (Data); byte_3 = dummy & 0xff; byte_4 = dummy >> 8; } else { byte_1 = inp (Data); byte_2 = inp (Data); byte_3 = inp (Data); byte_4 = inp (Data); } printf("Special status %d, ch %d: %02x, %02x, %02x, %02x\n", status_type, channel, byte_1, byte_2, byte_3, byte_4); size = 6; break; default: printf ("status = 0x%X \n", status_type); fatal_error (FATAL_STATUS); } return size; } /*************************************************************************** send packets this routine fills up the fifo with cmds and data it will not be called again until the board has emptied said fifo ***************************************************************************/ void send_packets(void) { int channel; int data_sent; //bytes put in for this packet int fifo_room; //how much room left in fifo int stuffed; //bytes stuffed into the fifo int left_in_pattern; //bytes left in pattern before wrap int chan_index; //current channel fifo_room = Fifo_Size - 8; // safety margin stuffed = 0; //spin thru all channels with fairness (pick first one randomly) chan_index = rand() % Num_Chans_Out; for (channel=0; channel= Num_Chans_Out) chan_index = 0; Chan = Chan_List[chan_index]; /******************************************************************* do bypass commands, these do not require any room on the board bypass commands DO NOT affect flow control *******************************************************************/ if (Channel[Chan].bp_ncmd) //any bypass commands pending? { int sent; int amt_to_send = Channel[Chan].bp_ncmd; if (fifo_room < amt_to_send + 4) break; //quit channel loop sent = send_bp_commands(amt_to_send); fifo_room -= sent; stuffed += sent; if (fifo_room <= 0) fatal_error (FATAL_ROOM); if (stuffed > Fifo_Size) fatal_error (FATAL_STUFF); continue; // next channel } /******************************************************************* if very little room in boards channel buffer, try next channel *******************************************************************/ if (Channel[Chan].room_for_out <= 8) continue; // next channel /******************************************************************* continous dataset signal changes, cmds 2 thru 6 if sy_cmd buffer is empty, put in a dataset signal command assert dtr, deassert dtr, assert rts, deassert rts *******************************************************************/ if (Chan == 5 && Channel[5].sy_ncmd == 0 && Continuous) { Channel[5].sy_cmds[Channel[5].sy_ncmd++] = Continuous; if (++Continuous >= 6) Continuous = 2; } /******************************************************************* do synchronous commands *******************************************************************/ if (Channel[Chan].sy_ncmd) //any sync commands pending? { int sent; int amt_to_send = Channel[Chan].sy_ncmd; // room in the fifo? if (fifo_room < amt_to_send + 4) break; //quit channel loop // room on the board in this channels buffer? if (Channel[Chan].room_for_out < amt_to_send + 4) continue; //next channel sent = send_sy_commands(amt_to_send); fifo_room -= sent; stuffed += sent; if (fifo_room <= 0) fatal_error (FATAL_ROOM); if (stuffed > Fifo_Size) fatal_error (FATAL_STUFF); } /******************************************************************* if receive only, skip the data transmit stuff *******************************************************************/ if (Receive_Only || Channel[Chan].do_it == 2) continue; //next channel /******************************************************************* in one packet mode, send one packet and clear the flag *******************************************************************/ if (No_Transmit) continue; // --New! if (Channel[Chan].one_packet_mode) if (Channel[Chan].send_one_packet) Channel[Chan].send_one_packet = 0; else continue; //next channel /******************************************************************* do data packets *******************************************************************/ //currently, we won't handle pattern wrap in one output operation left_in_pattern = Pat_Len - Channel[Chan].nptr; // if whats left wont fit in fifo, hit the mailbox and quit if (fifo_room < left_in_pattern + 6) break; //quit channel loop // it fits in the fifo, does it fit in the channels buffer? // in order for the data to fit in the board buffer // requires pattern length + optional pad byte + header word if (Channel[Chan].room_for_out < left_in_pattern + 3) left_in_pattern = Channel[Chan].room_for_out - 3; if (left_in_pattern <= 0) break; //quit channel loop data_sent = send_data(left_in_pattern); fifo_room -= data_sent; stuffed += data_sent; if (fifo_room <= 0) fatal_error (FATAL_ROOM); if (stuffed > Fifo_Size) fatal_error (FATAL_STUFF); } // for (channel=0; channel>1); i++) { if (Sixteen_Bit) { outpw (Data, *((short*)&(Channel[Chan].bp_cmds[i+i]))); } else { outp (Data, Channel[Chan].bp_cmds[i+i]); outp (Data, Channel[Chan].bp_cmds[i+i+1]); } } if (ShowBypass || ShowStuff) printf("{%u.%u.%u.%u} ", Chan, amount, Channel[Chan].as_of_out, Channel[Chan].room_for_out); Channel[Chan].bp_ncmd = 0; //we've "done" them return amount + 2 + (amount & 1); } /*************************************************************************** send_sy_commands returns the actual number of bytes put into the fifo ***************************************************************************/ int send_sy_commands(int amount) { int i; // send channel number, data count if (Sixteen_Bit) { outpw (Data, ((0x80+amount) << 8) + Chan); } else { outp (Data, Chan); outp (Data, 0x80 + amount); } for (i = 0; i < ((amount+1)>>1); i++) { if (Sixteen_Bit) { outpw (Data, *((short*)&(Channel[Chan].sy_cmds[i+i]))); } else { outp (Data, Channel[Chan].sy_cmds[i+i]); outp (Data, Channel[Chan].sy_cmds[i+i+1]); } } // maintain amounts for flow control Channel[Chan].as_of_out += amount + 2 + (amount & 1); Channel[Chan].room_for_out -= amount + 2 + (amount & 1); Channel[Chan].sy_ncmd = 0; //we've "done" them if (ShowSynch || ShowStuff) printf("[%u.%u.%u.%u] ", Chan, amount + 2 + (amount & 1), Channel[Chan].as_of_out, Channel[Chan].room_for_out); // amount put into the fifo return amount + 2 + (amount & 1); } /*************************************************************************** send_data ***************************************************************************/ int send_data(int amount) { char *pnt; int tag; int i; // 12 bits of count for data packet if (amount > 0xFFF) fatal_error(FATAL_AMOUNT); // get the data tag for this channel tag = Channel[Chan].tag; tag <<= 10; // send tag/channel number, data count, (2 words) if (Sixteen_Bit) { outpw (Data, Chan | tag); //16bit outpw (Data, amount); } else { outp (Data, Chan); //8bit outp (Data, tag); outp (Data, amount); outp (Data, 0); } Channel[Chan].chars_out += amount; Chars_Out += amount; //cps info pnt = &Channel[Chan].pattern[Channel[Chan].nptr]; // dump the output to the console if (Dump && Chan == Dump_Chan) for (i = 0; i < amount; i++) putchar(pnt[i]); asm push cx asm push si asm push dx asm mov cx, amount asm inc cx asm shr cx, 1 asm mov si, pnt asm mov dx, Data // send the data, (plus pad byte if needed) if (Sixteen_Bit) { asm rep outsw } else { asm shl cx, 1 asm rep outsb } asm pop dx asm pop si asm pop cx //maintain my flow control info Channel[Chan].as_of_out += amount + 2 + (amount & 1); Channel[Chan].room_for_out -= amount + 2 + (amount & 1); Channel[Chan].nptr += amount; if (ShowData || ShowStuff) printf("(%u.%u.%u.%u) ", Chan, amount + 2 + (amount & 1), Channel[Chan].as_of_out, Channel[Chan].room_for_out); // bump the line number in the output string after each pattern // also bumps the tag value for each pattern, 15 is reserved if (Channel[Chan].nptr >= Pat_Len) //end of pattern { Channel[Chan].nptr = 0; if (Increment) { for (i=9; i>=3; i--) //bump the line count { if (++Channel[Chan].pattern[i] != '9'+1) break; Channel[Chan].pattern[i] = '0'; } if (++Channel[Chan].tag >= 15) Channel[Chan].tag = 0; } } // return data count + 4 header bytes + 1 if odd data count return amount + 4 + (amount & 1); } /*************************************************************************** fatal_error ***************************************************************************/ void fatal_error (enum error code) { printf ("\n\007Fatal error number %d\n", code); puts (Error_Msgs[code]); exit (1); } /*************************************************************************** my_sleep ***************************************************************************/ void my_sleep (int secs) { time_t o_time, n_time; time (&o_time); n_time = o_time; while (n_time - o_time < secs) time (&n_time); return; } /*************************************************************************** send_256 sends the 256 words in buf to the board for downloading ***************************************************************************/ void send_256 (uchar *buf) { int i; if (Sixteen_Bit) { i = 256; while (i--) //send a block { outpw (Data, *((int *)buf)); buf += 2; } } else { i = 512; while (i--) //send a block outp (Data, *buf++); } //wait for outbound fifo to be emptied if (Expandable == 0) { outp (Command, 1); //send a shift command outp (Command, SHIFT); } i = 100; while (i--) { delay (1); //1 msec delay if (Expandable) { if (inp (Command) & O_EMPT) break; } else { if (inp (Command) & I_EMPT) break; } } if (i == 0) fatal_error (FATAL_OUTBOUND); if (Expandable == 0) { outp (Command, 1); //unshift outp (Command, 0); } } /*************************************************************************** see if we should issue any flow control packets to the board ***************************************************************************/ void send_flow_control(void) { int i; for (i=0; i RECEIVE_THRESHOLD) if (No_Receive == 0) stuff_flow_control (); } } /*************************************************************************** stuff_flow_control ***************************************************************************/ void stuff_flow_control () { // no room to build another flow control packet if (Channel[Chan].bp_ncmd > BP_NCOM - 6) { printf("bp_ncmd == %d",Channel[Chan].bp_ncmd); return; } Channel[Chan].bp_cmds[Channel[Chan].bp_ncmd++] = 37; Channel[Chan].bp_cmds[Channel[Chan].bp_ncmd++] = Channel[Chan].as_of_in & 0xff; Channel[Chan].bp_cmds[Channel[Chan].bp_ncmd++] = Channel[Chan].as_of_in >> 8; Channel[Chan].bp_cmds[Channel[Chan].bp_ncmd++] = Channel[Chan].room_for_in & 0xff; Channel[Chan].bp_cmds[Channel[Chan].bp_ncmd++] = Channel[Chan].room_for_in >> 8; Channel[Chan].nstrip = 0; } /*************************************************************************** reset_board expandable have 512k of memory to test, so we have to wait after reset ***************************************************************************/ void reset_board(void) { int i,j,k, iiii; int box_types; int num_boxes; //first, reset the board printf ("resetting I2 controller..., "); my_sleep (2); printf("BYM! "); outp (Reset, 1); my_sleep (1); printf("BYM! "); outp (Reset, 1); //again, for the 1400 sake my_sleep (2); //give it time to reset // now the fifo should have 16 bytes in it printf ("reading fifo header:\n"); my_sleep (1); if (inp (Command) & I_EMPT) fatal_error (FATAL_HEADER); printf ("magic number 0x%2X . . . . . . . 0x%2X\n", 0x96,inp(Data)); if (inp (Command) & I_EMPT) fatal_error (FATAL_HEADER); printf ("magic number 0x%2X . . . . . . . 0x%2X\n", 0x35,inp(Data)); if (inp (Command) & I_EMPT) fatal_error (FATAL_HEADER); printf ("firmware version . . . . . . . %u.", inp (Data)); if (inp (Command) & I_EMPT) fatal_error (FATAL_HEADER); printf ("%u.", inp (Data)); if (inp (Command) & I_EMPT) fatal_error (FATAL_HEADER); printf ("%u\n", inp (Data)); if (inp (Command) & I_EMPT) fatal_error (FATAL_HEADER); printf ("product identification . . . . %Xh = ", j = inp(Data)); switch (j & 0xC0) { case 0x00 : Expandable = 0; Sixteen_Bit = 0; printf("non-expandable"); break; case 0x40 : Expandable = 1; printf("expandable"); break; default : Expandable = -1; printf("???"); } if (!Expandable) { switch (j & 0x03) { case 0x00 : printf(", 8-port, standard brick"); break; case 0x01 : printf(", 8-port, RJ11s"); break; case 0x02 : printf(", 6-port, RJ45s"); break; case 0x03 : printf(", 4-port, RJ45s"); break; default : printf(", ???"); } } printf("\n"); if (inp (Command) & I_EMPT) fatal_error (FATAL_HEADER); printf ("bus, fifo, slot type . . . . . %Xh = ", j = inp(Data)); switch (j & 0x07) { case 0 : printf("ISA, "); break; case 1 : printf("Micro Channel, "); break; case 2 : printf("EISA, "); break; default: printf("???, "); } switch (j & 0x20) { case 0x00: printf("8 bit, "); break; case 0x20: printf("16 bit, "); break; default : printf("???, "); } switch (j & 0x10) { case 0x00: printf("8 bit, "); break; case 0x10: printf("16 bit, "); break; default : printf("???, "); } if (Expandable) { Sixteen_Bit = ((j & 0x30) == 0x30); if (Sixteen_Bit) printf ("(16 bit mode)"); else printf ("(8 bit mode)"); } else { printf ("(8 bit mode)"); } printf ("\n"); if (inp (Command) & I_EMPT) fatal_error (FATAL_HEADER); printf ("on board memory size . . . . . %uK\n", inp (Data)*32); if (inp (Command) & I_EMPT) fatal_error (FATAL_HEADER); j = inp(Data); printf ("UART Bits found (=highest). . . . . . . . %Xh = ", j); if (Expandable == 1) { for (i = iiii = k = 0; i < 8; i++, j >>= 1) { if (j & 1) { Channel[iiii++].i_exist = 1; Channel[iiii++].i_exist = 1; Channel[iiii++].i_exist = 1; Channel[iiii++].i_exist = 1; k = iiii; } else { iiii += 4; } } printf ("%d\n", k); Max_Ports = k; } else if (Expandable == 0) { Max_Ports = j; for (iiii= 0; iiii < j; ) { Channel[iiii++].i_exist = 1; } printf ("ports found . . . . . . . . . . %u\n", j); } else printf ("ports found . . . . . . . . . . error\n"); if (inp (Command) & I_EMPT) fatal_error (FATAL_HEADER); printf ("diagnostic byte . . . . . . . . %Xh ", j = inp (Data)); if (!Expandable) { if (j & 0x01) printf("uart 1 bad "); if (j & 0x02) printf("uart 2 bad "); } printf("\n"); if (inp (Command) & I_EMPT) fatal_error (FATAL_HEADER); printf ("diagnostic byte . . . . . . . . %Xh ", j = inp (Data)); if (j & 0x80) printf("debug adapter present"); printf("\n"); if (inp (Command) & I_EMPT) fatal_error (FATAL_HEADER); printf ("on board cpu speed . . . . . . %1.1f\n", inp (Data)/10.0); if (inp (Command) & I_EMPT) fatal_error (FATAL_HEADER); j = inp(Data); if (Expandable) box_types = (j & 0xF0) >> 4; j &= 0x03; printf ("on board cpu type . . . . . . . %d ", j); switch (j) { case 1 : printf("= 80188\n", j); break; case 2 : printf("= 80186\n", j); break; default: printf("= ?????\n", j); } if (inp (Command) & I_EMPT) fatal_error (FATAL_HEADER); j = inp(Data); printf ("UART Bits found (=highest). . . . . . . . %Xh = ", j); if (Expandable == 1 && j != 0) { for (i = k = 0, iiii = 32; i < 8; i++, j >>= 1) { if (j & 1) { Channel[iiii++].i_exist = 1; Channel[iiii++].i_exist = 1; Channel[iiii++].i_exist = 1; Channel[iiii++].i_exist = 1; k = iiii; } else { iiii += 4; } } printf ("%d\n", k); Max_Ports = k; } if (inp (Command) & I_EMPT) fatal_error (FATAL_HEADER); j = inp(Data); if (Expandable == 1) { printf ("fifo size in bytes . . . . . . %u\n", 1 << j); Fifo_Size = 1 << j; } else if (Expandable == 0) { printf ("fifo size in bytes . . . . . . %u\n", 512); Fifo_Size = 512; } else printf ("fifo size in bytes . . . . . . error\n"); if (Fifo_Size_Request) if (Fifo_Size_Request < Fifo_Size) Fifo_Size = Fifo_Size_Request; if (inp (Command) & I_EMPT) fatal_error (FATAL_HEADER); printf ("number of boxes (exp) . . . . . %u ", num_boxes = inp (Data)); if (Expandable) { for (i = 0; i < num_boxes; i++) printf("[%d ports]", (box_types & (1<