/* * these functions are for the mult-i/o rev #3 serial ports */ # include # include "mult.h" FIO stdout; /* external definitions */ int base=0; /* lowest port # for most functions */ int group=0; /* group # */ int functs=0; /* upper 6 bits of group select port */ int wrdsze=8; /* word size ( 5, 6, 7, 8, ) */ char stopsze='l'; /* stop bit lenth ( 'l', 's') */ char parity='n'; /* parity enable bit ( 'y', 'n' ) */ char eoparty='e'; /* even or odd parity ( 'e', 'o' ) */ char dtr='n'; /* data terminal ready ( 'y', 'n' ) */ char rts='n'; /* request to send ( 'y', 'n' ) */ char threint='n'; /* trans. holding reg. interrupt */ char drint='n'; /* data ready interrupt */ char rlint='n'; /* receive line interrupt */ char modint='n'; /* modem interrupt */ char buff[BUFSZ]='\0'; /* buffer for output to terminal */ int baud=0; /* baud rate */ int abaud[] = { /* array of most common baud rates */ 110, 300, 600, 1200, 2400, 4800, 9600, 19200 }; int dbaud[]= { /* holds the divisor for the baud rate */ 1047, 384, 192, 96, /* in an array that matches the array */ 48, 24, 12, 6 /* above for baud rates */ }; /* has the addr of the function */ int (*error)()=0; /* that failed , cannot point to a * function that needs parameters */ int erflg=0; /* 0 if not in error loop, 1 if it is */ int verflg=1; /* 1 if not verbose ,0 if verbose */ main() /* display menu */ { int notone; long int i; char a,b; error = main; for( ; ; ) { formfeed(); /* clear screen */ if(intal(STND) > 0xff) terflg(); if(intal(TEST) > 0xff) terflg(); putsnw("Mult I/O rev. #3 test\n"); putsnw("\tA) Transmit walk-test\n"); putsnw("\tB) Receive walk-test\n"); putsnw("\tC) Word length test\n"); putsnw("\tD) Overflow test\n"); putsnw("\tE) Baud rates test\n"); putsnw("\tF) Parity test\n"); putsnw("\tG) Control lines test\n"); putsnw("\tH) Memory lines test\n"); putsnw("\tI) Parallel ports test\n"); putsnw("\tJ) Clock test\n"); putsnw("\tK) Clock read\n"); putsnw("\tL) Interrupt test\n"); putsnw("\tM) Interrupt loop (push reset to exit)\n"); putsnw("\tN) All of above tests\n"); putsnw("\tO) All of above tests repeat at end\n"); putsnw("\tP) Verbose testing\n"); putsnw("\tQ) Non-verbose testing\n"); putsnw("\tR) To return to CP/M\n"); putsnw("\nEnter the letter of the test you wish to use "); a = getkey(); /* get typed char */ b = tolower(a); /* make upper case lower case */ notone = 0; /* is 0 if one of the following letters */ switch(a) { case 'a': getgrp(); twalk(); break; case 'b': getgrp(); rwalk(); break; case 'c': getgrp(); bitest(); break; case 'd': getgrp(); ovtest(); break; case 'e': getgrp(); albaud(); break; case 'f': getgrp(); parytest(); break; case 'g': getgrp(); control(); break; case 'h': finadd(); /* test for large enough CP/M */ memtest(); break; case 'i': partest(); break; case 'j': clktest(); break; case 'k': rdclock(); break; case 'l': inttest(); break; case 'm': intloop(); break; case 'n': testall(); break; case 'o': for( ; ; ) { testall(); if(cpm(11) != 0) break; } break; case 'p': verb(); break; case 'q': noverb(); break; case 'r': error = 0; (*error)(); /* call CP/M */ default: notone = 1; /* to tell if it tested anything */ break; } if(notone == 0) { putsnw("\nto get to menu type any key\n"); for(i=0 ;i < 20000 ; ++i) { if(cpm(11) != 0) { cpm(1); /* get key */ break; } } } } } testall() { int i; formfeed(); if(intal(STND) > 0xff) terflg(); if(intal(TEST) > 0xff) terflg(); finadd(); /* find the final addr test for large enough cp/m */ for(i=1; i < 4; ++i) /* for all three groups */ { group = i; bgsel(); /* both boards select */ twalk(); /* walk test transmit */ rwalk(); /* walk test recieve */ bitest(); /* test at different word lengths */ ovtest(); /* test overflw error */ albaud(); /* test at different baud rates */ parytest(); /* test parity error */ control(); /* test control lines */ } memtest(); /* test memory */ partest(); /* test parallel ports */ clktest(); /* test clock */ inttest(); /* test the interrupts */ } clktest() { int datan[6],datac[10],datat[6],datant[6],datact[10]; long i; error = clktest; puts("\n****** testing the clk "); torstd(); puts(" ******\n\n"); intial(); datan[0] = 59; datan[1] = 59; datan[2] = 23; datan[3] = 31; datan[4] = 6; datan[5] = 10; puts("set time = "); printime(datan); /* print time that is being set */ putc('\n'); toclk(datan,datac); timest(datac,STND); /* store time in non-test clock */ timest(datac,TEST); /* store time in test clock */ for( i=0; i < 10000 ; ++i) ; timerd(datac,STND); /* reads non-test time into datac */ timerd(datact,TEST); /* read test time into datac */ fmclk(datac,datant); /* puts time in numbers into datant */ fmclk(datact,datat); /* puts time in numbers into datat */ puts("read non-test time = "); printime(datant); /* print time that was read */ putc('\n'); puts("read test time = "); printime(datat); /* print test time */ putc('\n'); timechk(datan,datat,datant); /* make sure times match */ } printime(t) int *t; { printday(t[4]); /* print the day from the number in t[4] */ printmon(t[5]); /* print the month from the number in t[5] */ putdec(t[3]); /* print the day of month (t[3]) */ putc(' '); /* print space */ putdec(t[2]); /* print hours (t[2]) */ putc(':'); /* print time seperator : */ putdec(t[1]); /* print min (t[1]) */ putc(':'); /* print time seperator : */ putdec(t[0]); /* print sec (t[0]) */ putc('\r'); /* print return */ } printday(a) /* print the day of the week */ int a; { static char *day[] ={ "sun ", "mon ", "tue ", "wed ", "thu ", "fri ", "sat ", "illegal day " }; puts((a < 0 || a > 6) ? day[7] : day[a] ); } printmon(a) /* print month */ int a; { static char *mon[] = { "jan ", "feb ", "mar ", "apr ", "may ", "jun ", "jul ", "aug ", "sep ", "oct ", "nov ", "dec ", "illegal month " }; puts((a < 0 || a > 11) ? mon[12] : mon[a] ); } timechk(n , t , nt) /* compare times */ int *n,*t,*nt; { if(arcmp(n,nt) == 0) /* compare the set up time with read time */ { puts("the non-test clock didn't increment the time!\n\n"); terflg(); } if(arcmp(nt,t)) /* compare the two clocks */ { puts("the test clock didn't keep time right !\n"); terflg(); } else { if(erflg == 0 && verflg == 0) puts("passes clock test !\n"); } } arcmp(a,b) /* compare two 6 digit arrays return 1 if no match */ int *a,*b; { int d,i; d = 0; for(i=0; i<6 ; ++i) d |= (a[i] != b[i]); return(d); } /* * takes 10 b.c.d. digits and turns them into 6 decimal digits. */ fmclk(d,p) int *p,*d; { int i; for( i = 0 ; i < 8 ; i += 2 ) fmbcd((d+i),(p+(i / 2 ))); *(p+4) = *(d+8); *(p+5) = *(d+9); } /* * takes 6 decimal digits and turns them into b.c.d. digits for * the clk. */ toclk(p,d) int *p,*d; { int i,c; for( i = 0 ; i < 4 ; ++i ) { c = p[i]; tobcd(c,d); d += 2; } *d++ = p[4]; *d = p[5]; } /* * takes two b.c.d. digits and makes one decimal digit (array-array). */ fmbcd(pa,pb) int *pa,*pb; { *pb = *pa + ( *(pa+1) * 10 ); } /* * breaks 'n' into two b.c.d. digits in the array pointed * to by 'pa'. */ tobcd(n,pa) int n,*pa; /* n- number to convert,pa-pointer to array */ { if(n < 100) { *(pa+1) = n / 10; /* the pointer +1 becomes the tens */ *pa = n % 10; /* the pointer becomes the units */ } } /* * to output commands to the clk . */ clkcom(c,z) int c,z; /* z-flag for which board,c-command to send */ { int i,port; if(z) port = SCLK; else port = TCLK; out(port,c); delay(); /* delay for clock chip */ out(port,(c | 0x20)); delay(); /* delay for clock chip */ out(port,c); delay(); /* delay for clock chip */ } /* * inputs data from the clk and returns a 4 bit b.c.d. digit. */ inclk(z) int z; /* z- flag for which board */ { int i,a,port; if(z) port = SCLK; else port = TCLK; a = 0; for( i = 0 ; i < 4 ; ++i ) { a |= (in(port) & 1 ) << i; delay(); /* delay for clock chip */ out(port,2); delay(); /* delay for clock chip */ out(port,0); delay(); /* delay for clock chip */ } return(a); } /* * output one 4 bit b.c.d. digit to the clk. */ outclk(c,z) int c,z; /* c-data to send to the clock, z-flag for board */ { int i,a,port; if(z) port = SCLK; else port = TCLK; for( i = 0 ; i < 4 ; ++i ) { a = c>>i & 1; out(port,a); delay(); /* delay for clock chip */ out(port,(a|2)); delay(); /* delay for clock chip */ out(port,a); delay(); /* delay for clock chip */ } } /* * this function collects data form the clk and * stores it in array d as ten 4 bit b.c.d. numbers. */ timerd(d,z) int z,*d; /* z-flag for which board, d-pointer to array * that will hold the clock data */ { int i; clkcom(TIMRD,z); /* read time into shift reg. */ clkcom(SHIFT,z); /* strobe shift command to clock */ for( i = 0 ; i < 10 ; ++i ) /* input 10 4 bit words */ *(d+i) = inclk(z); clkcom(HOLD,z); /* strobe hold command to clock */ } /* * this function gets data from array 'd' as ten 4 bit b.c.d. numbers * to the clk in the correct format. */ timest(d,z) int z,*d; /* z-flag for which board , d points to array * that hold the clock data */ { int i; clkcom(SHIFT,z); /* strobe the shift command to the clock */ for( i = 0 ; i < 10 ; ++i ) /* shift out 10 4 bit words */ outclk(*(d+i),z); clkcom(TIMST,z); /* store the time in the clock */ clkcom(HOLD,z); /* strobe hold to the clock */ } /* software delay for clock */ delay() { int i; for( i = 0; i < 10; ++i) ; } /* take the clock out of the test mode */ intial() { out(SBASE+7,0); out(TBASE+7,0); clkcom(TP64,STND); clkcom(TP64,TEST); } groupsel() /* select group # */ { out( (base+7) , (group | (functs&0xfc)) ); } intal(z) /* initialize all ports on one mult-i/o */ int z; { int i; int erwd=0 ; if(z) base=SBASE; else base=TBASE; if(verflg == 0) { puts("****** initializing all ports "); torstd(); puts(" ******\n"); } for( i=1 ; i<4 ; ++i ) { group = i; groupsel(); /* set group number */ baud = 19200; setbaud(); /* set baud rate */ parity='n'; stopsze='l'; wrdsze=8; setparm(); /* set the line controls */ dtr = rts = 'n'; setmod(); /* set the modem controls */ threint = drint = rlint = modint = 'n'; setint(); /* set the interrupts */ if(ckbaud() > 0xff) { puts("the baud rate of port #"); putdec(group); torstd(); puts(" won't initialize !\n"); erwd = 0x100; } if(ckparm() > 0xff) { puts("the line control reg. of port #"); putdec(group); torstd(); puts(" won't initialize !\n"); erwd = 0x100; } if(ckmod() > 0xff) { puts("the modem control reg. of port #"); putdec(group); torstd(); puts(" won't initialize !\n"); erwd = 0x100; } if(ckint() > 0xff) { puts("the interrupt reg. of port #"); putdec(group); torstd(); puts(" won't initialize !\n"); erwd = 0x100; } } return(erwd); } getkey() /* get one key from the keyboard */ { int a; a = cpm(1); /* console input */ return( a & 0x7f); } getgrp() /* used to get the group # the user wants to use */ { int a; for( ; ; ) { puts("\nWhat group # would you like to test "); a = getkey(); if(a == '1') { a = 1; break; } else if(a == '2') { a = 2; break; } else if(a == '3') { a = 3; break; } else puts("\nThat group # does not exist"); } group = a; /* set group # */ bgsel(); /* select that group both boards */ } verb() /* set for verbose mode */ { verflg = 0; /* set verflg to 0 */ } noverb() /* set for nonverbose mode */ { verflg = 1; /* set verflg to 1 */ } rdclock() /* to just read the test clock */ { int datact[10],datat[6]; out(TBASE+7,0); /* set the group for the clock */ timerd(datact,TEST); /* reads the time into datact from test clk */ fmclk(datact,datat); /* convert from bcd to decimal */ puts("\nThe time read from the test clock ="); printime(datat); /* print the time */ putc('\n'); } intloop() /* interrupt loop for use of a scope */ { char *rest; rest = 0x38; /* points to restart 7 */ *rest = 0xdb; /* input */ *(rest+1) = TBASE+2; /* clock port */ *(rest+2) = 0x3e; /* mvi a */ *(rest+3) = 0x20; /* eoi */ *(rest+4) = 0xd3; /* output */ *(rest+5) = TBASE+4; /* to ocw2 */ *(rest+6) = 0xc9; /* return */ jumploc(); /* setup jump table for initializing */ icw4 = 'n'; /* no icw4 is to be sent */ intint(); /* initialize interrupts */ out(TBASE+5,0x7f); /* set mask for clock int only */ mode(); /* set cpu to int mode 1 */ eoi(); /* send the first end of int */ for( ; ; ) enab(); /* loop forever */ }