/* >>:yam5smdm.c 10-03-82 * * Smartmodem routines */ #include "yam.h" #ifdef NNC #define MODEMSTUFF #define TSTAT 3 #define TRESET 0x76 #define TDATA 1 /* * setbaud(nbaud) If legal rate, set modem registers and Baudrate */ setbaud(baud) int baud; { int lsb, msb; switch (baud) { case 300: lsb = 0x80; msb = 1; break; case 450: lsb = 0; msb = 1; break; case 600: lsb = 0xc0; msb = 0; break; case 1200: lsb = 0x60; msb = 0; break; case 2400: lsb = 0x30; msb = 0; break; case 4800: lsb = 0x18; msb = 0; break; case 9600: lsb = 0x0c; msb = 0; break; default: puts("\nillegal baud rate (300,450,600,1200,2400,4800,9600)"); return (ERROR); } outp(TSTAT, TRESET); /* reset 8253 timer */ outp(TDATA, lsb); /* send new ... */ outp(TDATA, msb); /* ... baud rate */ Baudrate = baud; return (OK); } sendbrk() { outp(Sport, 0x0d); /* request transmit break */ sleep((3 * CLKMHZ) / 4); /* wait .07(?) sec */ outp(Sport, 0x27); /* return to normal */ } readbaud() { return(Baudrate); } #endif #ifndef MODEMSTUFF setbaud() {} sendbrk() {} readbaud() { Baudrate=DEFBAUD; } #endif #ifdef SMODEM #define AUTODIAL sendcmd(cp) char *cp; { while (*cp) sendline(*cp++); } bye() { onhook(); sleep(10*CLKMHZ); /* wait one seconds */ setbaud(Baudrate); } onhook() { sleep(7 * CLKMHZ); sendcmd(SMATTN); sleep(7 * CLKMHZ); sendcmd(SMHUP); } /* * 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; 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 *s,*n, num[20]; 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); if (MIREADY) readline(0); /* dump any garbage */ 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); 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 AUTODIAL bye(){} onhook(){} /* default "autodial" routine */ dial(name) char *name; { char *s; printf("%s", name); if((s=cisubstr(name, "\tb"))) if(!setbaud(atoi(s+2))) printf("Baudrate set to %u ", Baudrate); return OK; } #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 MIREADYERROR /* Version for 8250, 8251, 2651, etc. with all bits in one register */ /* Changed by H.Schulz, 9/28/82, to reset error using MI_ERROR_RESET */ 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; if(CIREADY) { CICHAR; /* dismiss character */ return TIMEOUT; } if((Mstatus=inp(Sport))&MIREADYMASK) goto getit; for(Timeout=T1pause; --Timeout; ) if((Mstatus=inp(Sport))&MIREADYMASK) { getit: if(Mstatus & MIERRORMASK) { MICHAR; /* chuck it */ MI_ERROR_RESET; return ERROR; } else return MICHAR; } } return TIMEOUT; } #define READLINE #endif #ifndef READLINE readline(decisecs) { if(MIREADY) return MICHAR; while(--decisecs>=0) { if(MIREADY) return MICHAR; if(CIREADY) { CICHAR; /* dismiss character */ return TIMEOUT; } if(MIREADY) return MICHAR; for(Timeout=T1pause; --Timeout; ) if(MIREADY) return MICHAR; } return TIMEOUT; } #endif sendline(data) char data; { while(!MOREADY) ; outp(MODATA, data); } purgeline() { while(MIREADY) MICHAR; } /* * change modem port to n */ chngport(n) { #ifdef NNC printf("\nSorry, fixed modem port on the NNC"); #else Sport=(Dport=n)+(SPORT-DPORT); readbaud(); #endif }