/* >>:yam5smdm.c 12-14-83 * * Smartmodem routines by Herb Schultz * * CompuPro Interfacer 3 / 4 serial board routines by Paul Homchick * * Computer Innovations C86 Version */ #define EXTERN extern #include "yamc86.h" #define MODEMSTUFF /* * setbaud(nbaud) If legal rate, set modem registers and Baudrate */ setbaud(nbaud) unsigned nbaud; { int command, baudcmd, mode0, mode1; mode0=0xee; /* 16x rate 2 stop bits below 300bps */ mode1=0x6e; /* 16x rate 1 stop bit at and above 300bps */ command=0x27; switch(nbaud) { case 50: baudcmd=0x30;break; case 75: baudcmd=0x31;break; case 110: baudcmd=0x32;break; case 134: baudcmd=0x33;break; case 150: baudcmd=0x34;break; case 300: baudcmd=0x35;break; case 600: baudcmd=0x36;break; case 1200: baudcmd=0x37;break; case 1800: baudcmd=0x38;break; case 2000: baudcmd=0x39;break; case 2400: baudcmd=0x3A;break; case 3600: baudcmd=0x3B;break; case 4800: baudcmd=0x3C;break; case 7200: baudcmd=0x3D;break; case 9600: baudcmd=0x3E;break; case 19200: baudcmd=0x3F;break; default: return ERROR; } outportb(GBI4U,MDMU); if(nbaud<300) outportb(GBI4M,mode0); else outportb(GBI4M,mode1); outportb(GBI4M,baudcmd); outportb(GBI4C,command); Baudrate=nbaud; return OK; } /* fetch the baudrate from the modem port */ readbaud() { unsigned inbyt; outportb(GBI4U,MDMU); inportb(GBI4M)&0xFF; inbyt=(inportb(GBI4M)&0x0f); switch(inbyt) { case 0: Baudrate=50;break; case 1: Baudrate=75;break; case 2: Baudrate=110;break; case 3: Baudrate=134;break; case 4: Baudrate=150;break; case 5: Baudrate=300;break; case 6: Baudrate=600;break; case 7: Baudrate=1200;break; case 8: Baudrate=1800;break; case 9: Baudrate=2000;break; case 10: Baudrate=2400;break; case 11: Baudrate=3600;break; case 12: Baudrate=4800;break; case 13: Baudrate=7200;break; case 14: Baudrate=9600;break; case 15: Baudrate=19200;break; default: break; } return Baudrate; } /* Bye hangs up the line and then resets for another call */ bye() { onhook(); sleep(10*CLKMHZ); setbaud(Baudrate); } sendbrk() { unsigned char dp3; outportb(GBI4U,MDMU); dp3=inportb(GBI4C); outportb(GBI4C, 0x2f); /* set line to spacing */ sleep(CLKMHZ); outportb(GBI4C, dp3); /* return to marking */ } #define AUTODIAL sendcmd(cp) char *cp; { while (*cp) sendline(*cp++); } onhook() { sleep(8 * CLKMHZ); sendcmd(SMATTN); sleep(8 * CLKMHZ); purgeline(); sendcmd(SMHUP); } /* * flip - toggle Smodem to auto-answer mode * Not the original intention 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 (rcnt = 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 *ncp,*s,*n, num[40]; unsigned nbaud; Originate = TRUE; ncp = name; 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); purgeline(); /* dump any garbage */ sendcmd(SMATTN); sendcmd(SMCMD); /* use extended command set */ sendcmd(SMDIAL); sendcmd(num); sendline('\r'); printf("(^X aborts) Dialing -> %s\n", num); 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); if(cmdeq(ncp,"cis")) Cis02=TRUE; term(); return (OK); } result() { unsigned char rcode; unsigned nbaud; 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); } } /* * 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 MIREADYERROR /* Version for 8250, 8251, 2651, etc. with all bits in one register */ readline(decisecs) { if((Mstatus=i4rs(MDMU))&MIREADYMASK) goto getit; while(--decisecs>=0) { if((Mstatus=i4rs(MDMU))&MIREADYMASK) goto getit; #ifdef CDO if(CDO) return TIMEOUT; #endif if((Mstatus=i4rs(MDMU))&MIREADYMASK) goto getit; #ifndef REALSLOWKB if(CIREADY) { CICHAR; /* dismiss character */ return TIMEOUT; } #endif if((Mstatus=i4rs(MDMU))&MIREADYMASK) goto getit; for(Timeout=T1pause; --Timeout; ) if((Mstatus=i4rs(MDMU))&MIREADYMASK) { getit: if(Mstatus&MIERRORMASK) { michar(); /* chuck it */ inportb(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) ; outportb(MODATA, data&Wcsmask); } purgeline() { #ifdef MOEMPTY while(!MOEMPTY) ; #endif while(miready()) michar(); } /* * change modem port to n */ chngport(n) int n; { if(n < 0 || n > 7) { printf("\7User request for %d out of range (0 - 7). ",n); return(ERROR); } MDMU=n; readbaud(); } /* * Routines to handle modem status checking and i/o * when using Godbout Interfacer 4 board */ #ifdef CDO /* value = 0 if carrier there * set up to use parallel port on if4 * to monitor Cx line from modem */ i4cd() { outportb(GBI4U,0x06); return((inportb(GBI4M)&0x01)-0x01); } #endif /* read status */ i4rs(puser) unsigned char puser; { outportb(GBI4U,puser); return(inportb(MSTAT)); } /* read data */ i4rd(puser) unsigned char puser; { outportb(GBI4U,puser); return(inportb(MDATA)); } /* send data */ i4sd(puser,x) unsigned char puser,x; { outportb(GBI4U,puser); outportb(MDATA, x); } #ifdef USERINIT /* initialize special externals */ userinit() { MDMU=MUSER; #ifdef IF3CON CONU=CUSER; #endif } #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); } .