/* >>:yam5.c 11-10-83 * Added Smodem setup on dial and initialize to switches on 'bye' DS 11-10-83 * Added michar, miready, term- replot, reset, init functions 7-3-83 * Return value for chngport() 6-9-83 * Added Wcsmak support 3-25-83 * Moved chngport to yam5 CAF 9-21-82 * Added MICROCOM autodial CAF 7-17-82 * Changed PORTSELAD autodial code CAF 6-11-82 * Added MICROCOM, Changed /CLKMHZ to *CLKMHZ CAF 5-27-82 * Trs80 sendbrk now calls brkint() (in yamtrsbk.csm) -CAF 4-15-82 (DS) * fixed trs-80 II routines for sendbrk; added default dummy sendbrk * to avoid compile error--DS 12-6-81 * * Modem related functions. If your modem supports baudrate setting, * and hangup, modify this file to suit your needs and give it a * unique name (NOT YAM5.C!); use it in place of yam5.c. * ====== Please edit out unused code in your file to save disk space ====== * If your modem supports an autocall, put that routine here also * define MODEMSTUFF to suppress default baud rate related functions. * define AUTOCALL in your autocall routine to suppress the default * which merely prints the phone number and recommended baud rate. */ /* * setbaud(nbaud) If legal rate, set modem registers and Baudrate */ #include "yam.h" #ifdef TUART #define MODEMSTUFF /* * set baud rate for modem driven by Cromenco TUART */ setbaud(nbaud) unsigned nbaud; { char command, baudcmd; command=0; switch(nbaud) { case 110: baudcmd=0001;break; case 150: baudcmd=0202;break; case 300: baudcmd=0204;break; case 1200: baudcmd=0210;break; case 2400: baudcmd=0220;break; case 4800: baudcmd=0240;break; case 9600: baudcmd=0300;break; case 19200: baudcmd=0220;command=020;break; case 38400: baudcmd=0240;command=020; break; default: return ERROR; } outp(Sport, baudcmd); outp(Sport+2, command); Baudrate=nbaud; return 0; } readbaud() { Baudrate=DEFBAUD; } /* Bye disconnects the line and allows another call */ bye() { outp(Sport+2, 03); /* turn on break */ sleep(20*CLKMHZ); /* wait two seconds */ setbaud(Baudrate); } sendbrk() { outp(Sport+2, 03); /* set serial line to spacing */ sleep(CLKMHZ/2); /* wait .1 second */ setbaud(Baudrate); } /* onhook disconnects the line for good */ onhook() {} /* no way to go on hook with this setup */ #endif #ifdef Z89 #define MODEMSTUFF /* * Routine to set baud rate for 8250 driven modem port */ setbaud(nbaud) unsigned nbaud; { unsigned bcmd; if(nbaud==0) return ERROR; bcmd= 57600; /* 1.8432 Mhz clock */ bcmd /= (nbaud/2); /* this must be done unsigned! */ outp(Dport+3, 0203); /* enable divisor latch */ outp(Dport, bcmd); outp(Dport+1, (bcmd>>8)); /* * 8 data bits, 1 stop bit (2 if odd or 110 baud rate) * then disable divisor latch */ outp(Dport+3, ((nbaud&1)||nbaud)==110? 07:03); /* turn on dtr and rts, also output2 is baudrate is 1100 or more */ outp(Dport+4, nbaud>=1100?017:03); Baudrate=nbaud; /* printf("bcmd=%d bcmdms=0%o bcmdls=0%o\n",bcmd,(bcmd>>8),(bcmd&0377)); */ return OK; } /* fetch the baudrate from the modem port */ readbaud() { char dp3; unsigned div; dp3=inp(Dport+3); outp(Dport+3, 0200|dp3); div= inp(Dport) | (inp(Dport+1)<<8); /* fetch divisor */ outp(Dport+3, dp3); /* restore uart modes */ Baudrate=57600; /* be sure all this remains unsigned! */ Baudrate /= div; Baudrate <<= 1; } /* Bye hangs up the line and then resets for another call */ bye() { onhook(); sleep(20*CLKMHZ); setbaud(Baudrate); } /* onhook goes off line for good */ onhook() { outp(Dport+4, 0); } sendbrk() { char dp3; dp3=inp(Dport+3); outp(Dport+3, 0100); /* set line to spacing */ sleep(CLKMHZ); outp(Dport+3, dp3); /* return to marking */ } #endif #ifdef TRSII #define MODEMSTUFF /* * set baud rate for modem driven by TRS 80 MOD II with Pickles & Trout CP/M */ setbaud(nbaud) unsigned nbaud; { char calla(), command, baudcmd, regB, regC, regD, regE, regH, regL; command=0; switch(nbaud) { case 110: baudcmd=0;break; case 150: baudcmd=2;break; case 300: baudcmd=3;break; case 600: baudcmd=4;break; case 1200: baudcmd=5;break; case 2400: baudcmd=6;break; case 4800: baudcmd=7;break; case 9600: baudcmd=8;break; default: return ERROR; } regB = 0; /* setup serial ports */ regC = 0; /* port a, parity odd and disabled */ regD = 0xe6; /* DTR,RTS high, 8-bit wds, 1 stop */ regE = baudcmd; /* baud rate */ regH = 19; /* Xmit off char */ regL = 17; /* Xmit on-off handshaking; X-on char */ calla(0x40,0,(regH << 8 | regL),(regB << 8 | regC), (regD << 8 | regE)); /* call P&T special function */ Baudrate=nbaud; return 0; } readbaud() { Baudrate=DEFBAUD; } /* Bye disconnects the line and allows another call */ bye() { onhook(); sleep(5*CLKMHZ); /* wait two seconds */ setbaud(Baudrate); } #ifndef SMODEM /* onhook disconnects the line for good */ onhook() { char calla(); calla(0x40,0,0,0x40,0); /* set DTR, RTS low */ } #endif sendbrk() { brkint(); /* call assembly language routine in yamtrsbk.csm */ } #endif /* * Smartmodem routines */ #ifdef SMODEM #define AUTODIAL sendcmd(cp) char *cp; { while (*cp) sendline(*cp++); } onhook() { sleep(7 * CLKMHZ); sendcmd(SMATTN); sleep(7 * CLKMHZ); sendcmd(SMHUP); sleep(7 * CLKMHZ); sendcmd(SMRESET); } /* * flip - toggle Smodem to auto-answer mode * Not the original intension of flip. This routine * hasn't been tested so tread with care. */ flip(argc,argp) int argc; char **argp; { int rcnt,r; if (argc != 1) { oops: printf("\007usage: flip [org | ans | auto]\n"); return ERROR; } if(strcmp("org", argp[0]) == 0 || strcmp("ans", argp[0]) == 0) { printf("Sorry: this version of flip can't do that"); return(OK); } else if (strcmp("auto", argp[0]) == 0) { puts("(^X Aborts) Waiting for Ring: "); for (r = 0; ++r <= NRING;) if (result() > 0) printf("\nRing #%d", r); else return(OK); /* got the rings, go on line */ sendcmd(SMTOANS); if (result() != OK) { puts("\nAnswer Error\n"); return(OK); } Originate = FALSE; /* You may want to turn on echo here, I haven't (yet?) */ term(); return(OK); } else goto oops; return OK; } dial(name) char *name; { char *s,*n, num[60]; Originate = TRUE; n=cisubstr(name, "\t")+1; /* I have a line "*SmodemPhones\t*" in my PHONES.T which allows me to * do a 'call *' from the command line to have it ask for the number */ if (*n == '*') { puts("Number to dial: "); gets(num); if (!*num) return (OK); } else { for (s = num; (*s = *n++) != '\t' && *s; ++s) ; *s = '\0'; } /* dial a * option number at the set baud rate! */ nbaud = ((s = cisubstr(name, "\tb")) ? atoi(s + 2) : Baudrate); /* dial at 300 unless baud rate >= 1200 */ setbaud((nbaud < 1200) ? 300 : nbaud); sendcmd(SMSETUP); sleep(2 * CLKMHZ); while (MIREADY) readline(0); /* dump any garbage */ sendcmd(SMDIAL); sendcmd(num); sendline('\r'); printf("(^X aborts) Dialing -> \n"); if (result() != OK) return (OK); if (nbaud < 1200 && nbaud > 300) setbaud(nbaud); /* reset to desired baud rate */ printf("\n++ On Line ++ Baudrate = %d ++\n\7", Baudrate); term(); return (OK); } result() { char rcode; sleep(10 * CLKMHZ); /* let the dial get out before allowing abort */ while (!MIREADY) if (CIREADY && CICHAR == '\30') { puts("Aborting"); sendline('\r'); return (ERROR); } switch ((rcode = MICHAR)) { case '5': nbaud = 1200; setbaud(1200); case '1': readline(2 * CLKMHZ); /* get rid of extra '\r' */ return (OK); case '3': puts("No Carrier\n"); return (ERROR); case '2': return (1); /* if (result() > 0) then ring */ default: printf("Dial error, return code = %c\n", rcode); return (ERROR); } } #endif #ifndef MODEMSTUFF setbaud() {} sendbrk() {} onhook() {} bye() {} readbaud() { Baudrate=DEFBAUD; } #endif /* * Readline from MODEM13.C rewritten to allow much higher * baud rates. * Timeout is in deciseconds (1/10th's) * For top speed, character ready is checked in many places. * returns TIMEOUT if kbd character is ready. * * There are three versions of readline, the first is used if * there is a separate register for error conditions. The second * is used if error condx are in the same register asrx data ready. * The last, and quickest, does not check error conditions. */ #ifdef MIERROR /* version for separate error register. NOT TESTED */ readline(decisecs) { if(miready()) { if(MIERROR) goto fubar; else return michar()&Wcsmask; } while(--decisecs>=0) { if(miready()) { if(MIERROR) goto fubar; else return michar()&Wcsmask; } if(CDO) return TIMEOUT; if(CIREADY) { CICHAR; /* dismiss character */ return TIMEOUT; } for(Timeout=T1pause; --Timeout; ) if(miready()) { if(MIERROR) goto fubar; else return michar()&Wcsmask; } } return TIMEOUT; fubar: michar(); /* throw the turkey away */ MI_ERROR_RESET; return ERROR; } #define READLINE #endif #ifdef MIREADYERROR /* Version for 8250, 8251, 2651, etc. with all bits in one register */ readline(decisecs) { if((Mstatus=inp(Sport))&MIREADYMASK) goto getit; while(--decisecs>=0) { if((Mstatus=inp(Sport))&MIREADYMASK) goto getit; if(CDO) return TIMEOUT; if((Mstatus=inp(Sport))&MIREADYMASK) goto getit; #ifndef REALSLOWKB if(CIREADY) { CICHAR; /* dismiss character */ return TIMEOUT; } #endif if((Mstatus=inp(Sport))&MIREADYMASK) goto getit; for(Timeout=T1pause; --Timeout; ) if((Mstatus=inp(Sport))&MIREADYMASK) { getit: if(Mstatus&MIERRORMASK) { michar(); /* chuck it */ inp(Sport); /* reset err bits */ return ERROR; } else return michar()&Wcsmask; } } return TIMEOUT; } #define READLINE #endif #ifndef READLINE readline(decisecs) { if(miready()) return michar()&Wcsmask; while(--decisecs>=0) { if(miready()) return michar()&Wcsmask; if(CIREADY) { CICHAR; /* dismiss character */ return TIMEOUT; } if(miready()) return michar()&Wcsmask; for(Timeout=T1pause; --Timeout; ) if(miready()) return michar()&Wcsmask; } return TIMEOUT; } #endif sendline(data) char data; { while(!MOREADY) ; outp(MODATA, data&Wcsmask); } purgeline() { #ifdef MOEMPTY while(!MOEMPTY) ; #endif while(miready()) michar(); } #ifdef PORTSELAD #define AUTODIAL dial(name) char *name; { char *s; if((s=cisubstr(name, "\tm"))) { chngport(atoi(s+2)); printf("Port %u ", Dport); } if((s=cisubstr(name, "\tb"))) if(!setbaud(atoi(s+2))) printf(" %u baud\n", Baudrate); printf("%s", name); return OK; } #endif #ifdef MICROCOM #define AUTODIAL dial(name) char *name; { int count, dp3; char *s; unsigned tbaudd; printf("%s", name); if((s=cisubstr(name, "\tb"))) tbaudd=atoi(s+2); else tbaudd=0; if((s=cisubstr(name, "\tm"))) { chngport(atoi(s+2)); printf(" Port %u ", Dport); } else { if (tbaudd>450) tbaudd=300; setbaud(300); for(count=5; --count>=0; ) { purgeline(); sendline(' '); if(readline(5) != 'C') { /* send long break to reset */ printf("Reset.."); dp3=inp(Dport+3); outp(Dport+3, 0100); sleep(5 * CLKMHZ); outp(Dport+3, dp3); while(readline(8) != TIMEOUT) ; while(readline(4) != TIMEOUT) ; sendge(ESC); sendge(EOT); continue; } for(dp3=5; --dp3>=0; ) if (sendge('D')=='D') break; /* skip to 1st digit of number */ s=cisubstr(name, "\t"); for (; *s && !isdigit(*s); ++s) ; for ( ; *s > ' '; ++s) { if(isdigit(*s) || *s=='X') sendge(*s); /* send no dashes */ } sendline('\r'); while ((dp3=readline(100)) != 'D' && dp3 != 'C') ; if(dp3!='D') { printf("\nCall Failed:%c\n", dp3); return ERROR; } else break; } } if(tbaudd) { setbaud(tbaudd); } printf(" Connected at %u Baud\n", Baudrate); return OK; } /* send char to modem controller, wait for echo, display and return it. */ sendge(c) { register b; sendline(c); putcty(b=readline(5)); return b; } #endif /* default "autodial" routine */ #ifndef AUTODIAL dial(name) char *name; { char *s; if((s=cisubstr(name, "\tb"))) if(!setbaud(atoi(s+2))) printf("Baudrate set to %u: ", Baudrate); printf("%s", name); return OK; } #endif /* return <> 0 if modem has character(s) ready */ miready() { return MIREADY; } /* return next modem character assuming miready <> 0 */ michar() { return MICHAR; } /* functions to output control strings to terminal */ termreset() { lputs(TERMRESET); } terminit() { lputs(TERMINIT); } termreplot() { lputs(TERMREPLOT); } /* * change modem port to n */ chngport(n) { Sport=(Dport=n)+(SPORT-DPORT); readbaud(); return OK; }