/* >>:yam5scc.c 3-29-83 * * Modem related functions. */ #include "yam.h" #include "scc.h" #define MIERROR (inpp(1)&(ROVERR+FRAMERR)) #define MI_ERROR_RESET outp(Sport, RESERROR) #define BMAGIC 57600 /* 1.8432 mHz clock */ /* * setbaud(nbaud) If legal rate, set modem registers and Baudrate * Routine to init 8530 SCC, turn on DTR, and set baud rate * Sets 2 stop bits iff baud rate is 110 baud or odd. * Sets RTS iff baud rate >= 1100 * Steps performed in recommended squence according to Zilog Document * 00-2266-01 06/28/82 * ********** N.B.: Resets entire chip ************* */ setbaud(nbaud) unsigned nbaud; { register unsigned bcmd; inp(Sport); /* make sure register pointer is reset */ outpp(9, RESCHIP); /* reset the chip */ if(nbaud==0) return ERROR; /* 8 data bits, 1 stop bit (2 if odd or 110 baud rate) */ outpp(4, ((nbaud&1)||nbaud)==110? EN2STOP+X16CLOCK:EN1STOP+X16CLOCK); outpp(1, 0); outpp(3, RX8BITS); outpp(5, DTR+TX8BITS); outpp(10,NRZ); /* nrz etc */ outpp(11, TXCFBRGEN+RXCFBRGEN); /* select clocking sources internal */ bcmd= BMAGIC; bcmd /= nbaud; /* this must be done unsigned! */ outpp(12, bcmd); outpp(13, (bcmd>>8)); outpp(14, BRGENPCLK+ENDTR+SETSRCBR); /* Zilog sez do this twice */ outpp(14, BRGENPCLK+ENDTR+SETSRCBR); /* Zilog sez do this twice */ Baudrate=nbaud; /* printf("bcmd=%d bcmdms=0%o bcmdls=0%o\n",bcmd,(bcmd>>8),(bcmd&0377)); */ outpp(3, ENRX+RX8BITS); /* turn on dtr, also rts if baudrate is 1100 or more */ outpp(5, nbaud >= 1100 ? DTR+TX8BITS+ENTX+RTS : DTR+TX8BITS+ENTX); outpp(14, ENBRGEN+BRGENPCLK+ENDTR+SETSRCBR); outpp(15,0); return OK; } /* fetch the baudrate from the modem port */ readbaud() { unsigned div; div= inpp(12) | (inpp(13)<<8); /* fetch divisor */ if (div == 0) { Baudrate=300; /* default if no baud rate in reg */ } else { Baudrate=BMAGIC; /* all this must be unsigned! */ Baudrate /= div; } } /* 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() { outpp(5, 0); } sendbrk() { outpp(5, SENDBRK); /* set line to spacing */ sleep(CLKMHZ); setbaud(Baudrate); /* then restore it */ } /* * 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. * */ readline(decisecs) { if(MIREADY) { if(MIERROR) goto fubar; else return MICHAR; } while(--decisecs>=0) { if(MIREADY) { if(MIERROR) goto fubar; else return MICHAR; } #ifdef CDO if(CDO) return TIMEOUT; #endif if(CIREADY) { CICHAR; /* dismiss character */ return TIMEOUT; } for(Timeout=T1pause; --Timeout; ) if(MIREADY) { if(MIERROR) goto fubar; else return MICHAR; } } return TIMEOUT; fubar: MICHAR; /* throw the turkey away */ MI_ERROR_RESET; return ERROR; } sendline(data) char data; { while(!MOREADY) ; outp(MODATA, data); } purgeline() { while ((inpp(1)&ALLSENT)==0) ; while(MIREADY) MICHAR; MI_ERROR_RESET; } #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.."); outpp(5, SENDBRK); sleep(5 * CLKMHZ); setbaud(300); 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 /* * change modem port to n */ chngport(n) { Sport=(Dport=n)+(SPORT-DPORT); readbaud(); } /* * Special i/o routines for Z8530 SCC with pointer register * * outpp(p, c) outputs c to subport p of chip selected by Sport * inpp(p) returns value in subport p of chip slected by Sport */ outpp(p, c) { outp(Sport, p); outp(Sport, c); } inpp(p) { outp(Sport, p); return inp(Sport); }