home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
modems
/
modem2
/
cmodem13.c
< prev
next >
Wrap
C/C++ Source or Header
|
1983-09-09
|
14KB
|
566 lines
/*This program implements the Ward Christensen assembly language
program in C. All of the original modes are available, and a
capture buffer was added to the terminal and computer modes.
The UNIX and PDP10 modes were added to facilitate sending files
to those systems. Note that the original version of this program
was written for the D.C. Hayes modem board - however, this
version is for the PMMI modem.
original by Jack M. Wierda
modified by Roderick W. Hart
*/
#include <pmmi.h>
#define FALSE 0
#define TRUE 1
#define NUL 0
#define SOH 1
#define CTRLB 2
#define CTRLC 3
#define EOT 4
#define ERRORMAX 5
#define RETRYMAX 5
#define CTRLE 5
#define ACK 6
#define TAB 9
#define LF 10
#define CR 13
#define CTRLQ 17
#define SPS 2750 /*loops per second*/
#define CTRLS 19
#define NAK 21
#define CTRLZ 26
#define SPACE 32
#define DELETE 127
#define TIMEOUT -1
#define SECSIZ 0x80
#define DATAMASK 0x7f
#define BUFSIZ 0x7f80 /*maximum size, 0x8000 will not work with
with BDS C, reduce buffer size as necessary
for smaller systems*/
char cntrlw0, cntrlw1, cntrlw2, cntrlw3;
char hangup, option, option2, mode, baudrate, display, system;
char asciiflg, showtrans, showrecv, view, dtrr;
char buffer[BUFSIZ];
moready()
{
return (inp(STATPORT) & TBMT) == (MAHI ? TBMT : 0);
}
miready()
{
return (inp(STATPORT) & DAV) == (MAHI ? DAV : 0);
}
ctsready()
{
return (inp(MODEMCP2) & CTS) == (CTSHI ? CTS : 0);
}
sendline(data)
char data;
{
while(!MOREADY());
outp(DATAPORT,data);
if(showtrans)
{ if(asciiflg)
if(((data >= ' ') && (data <= 0x7f)) || data == LF || data == CR
|| data == TAB)
putchar(data);
else
printf("[%0x]",data);
if(option2 == 'H')
printf("[%0x]",data);
}
}
readline(seconds)
int seconds;
{
char data;
seconds = seconds * SPS;
while (!MIREADY() && seconds--);
if(seconds < 0)
return(TIMEOUT);
data = inp(DATAPORT);
if(showrecv)
{ if(asciiflg)
if(((data >= ' ') && (data <= 0x7f)) || data == LF || data == CR
|| data == TAB)
putchar(data);
else
printf("[%0x]",data);
if(option2 == 'H')
printf("<%0x>",data);
}
return(data);
}
purgeline()
{
while (MIREADY())
inp(DATAPORT); /*PURGE THE RECEIVE REGISTER*/
}
initializemodem()
{
char cdflg;
cdflg = TRUE;
if((option == 'R') || (option == 'S'))
{ cntrlw0 = ORIG + NB1 + NB2 + NP;
cntrlw3 = dtrr;
}
else
{ cntrlw0 = ORIG + NB2 + EPS;
cntrlw3 = dtrr;
}
if(!CTSREADY())
{ printf("Waiting for carrier\n");
cdflg = FALSE;
}
while(!CTSREADY() && !bios(2))
{ outp(STATPORT,cntrlw0);
outp(MODEMCP2,cntrlw2);
outp(MODEMCP3,cntrlw3);
outp(DATAPORT,cntrlw1);
}
if(CTSREADY() && !cdflg)
printf("Carrier detected\n");
outp(STATPORT, (cntrlw0 & 0xfe));
purgeline();
}
sendstr(str)
char *str;
{
while(*str)
if(option == 'U')
sendline(tolower(*str++));
else
sendline(*str++);
}
termcomp()
{
char bflag, kbdata, moddata;
int fd;
int bufctr;
bflag = FALSE;
bufctr = 0;
initializemodem();
while((CTSREADY()) && (kbdata !=CTRLE))
{ if(bios(2))
switch(kbdata = bios(3))
{ case CTRLB:
bflag = ~bflag;
if(bflag)
printf("Capture initiated");
else
printf("Capture terminated");
printf(", %u bytes free\n",BUFSIZ - bufctr);
break;
case CTRLE:
break;
default:
if(option == 'C')
{ putchar(kbdata);
if(bflag && (bufctr < BUFSIZ))
buffer[bufctr++] = kbdata;
}
outp(DATAPORT,kbdata);
break;
}
if(MIREADY())
{ moddata = inp(DATAPORT);
if(option == 'C')
outp(DATAPORT,moddata);
if(bflag && (bufctr < BUFSIZ))
buffer[bufctr++] = moddata;
else if(bflag)
printf("Buffer overflow\n");
putchar(moddata);
}
}
if(bufctr)
{ buffer[bufctr] = CTRLZ;
fd = creat("cmodem.tmp");
if(fd == -1)
{ printf("Cannot create cmodem.tmp\n");
exit();
}
write(fd,buffer,1 + (bufctr/SECSIZ));
close(fd);
}
}
putbuffer(buffer,sectors)
char *buffer;
int sectors;
{
char ch, moddata;
unsigned k;
ch = 0;
k = 0;
while((ch != CTRLZ) && (k < sectors * SECSIZ) && (CTSREADY()))
{ k = k+1;
if((ch = *buffer++) == LF) /*don't send LF's*/
putchar(LF);
else
if(ch != CTRLZ || option != 'U') /*don't send CTRLZ to UNIX*/
sendline(ch);
if(!(k & 0xff)) /*let other end catch-up*/
while(readline(1) != TIMEOUT);
}
}
pdp10(file)
char *file;
{
char sectors;
int fd;
showrecv = FALSE;
asciiflg = showtrans = TRUE;
fd = open(file,0);
if(fd == -1)
{ printf("Cannot open %s\n",file);
exit();
}
initializemodem();
if(option == 'P')
{ sendstr("\nR PIP\n");
while((readline(1) != '*') && !bios(2));
if(*(++file) != ':')
sendstr(--file);
else
sendstr(++file);
sendstr("=TTY:\n");
}
else
{ sendstr("\ncat > ");
if(*(++file) != ':')
sendstr(--file);
else
sendstr(++file);
sendstr("\n");
}
while((sectors = read(fd,buffer,BUFSIZ/SECSIZ)) == BUFSIZ/SECSIZ)
putbuffer(buffer,sectors);
if(sectors)
putbuffer(buffer,sectors);
close(fd);
while(readline(1) != TIMEOUT);
if(option == 'P')
sendline(CTRLC);
else
{ sendline(CR);
sendline(LF);
sendline(EOT);
}
while(readline(10) != TIMEOUT);
sendline(CR);
sendline(LF);
}
readfile(file)
char *file;
{ int j, firstchar, sectnum, sectcurr, sectcomp, errors;
int checksum;
int errorflag, fd;
int bufctr;
if(view)
{ showrecv = TRUE;
showtrans = FALSE;
}
option2 = 'A';
fd = creat(file);
if(fd == -1)
{ printf("Cannot create %s\n",file);
exit();
}
sectnum = 0;
errors = 0;
bufctr = 0;
initializemodem();
sendline(NAK);
do
{ errorflag = FALSE;
do
firstchar = readline(6);
while(firstchar != SOH && firstchar != EOT && firstchar != TIMEOUT);
if(firstchar == TIMEOUT)
{ errorflag = TRUE;
printf("SOH timeout\n");
}
if(firstchar == SOH)
{ sectcurr = readline(1);
sectcomp = readline(1);
if((sectcurr + sectcomp) == 255)
{ if(sectcurr == sectnum + 1)
{ checksum = 0;
if(option2 == 'A')
asciiflg = TRUE;
for(j = bufctr;j < (bufctr + SECSIZ);j++)
{ buffer[j] = readline(1);
checksum = (checksum + buffer[j]) & 0xff;
}
asciiflg = FALSE;
if(checksum == readline(1))
{ errors = 0;
sectnum = sectcurr;
bufctr = bufctr + SECSIZ;
if(bufctr == BUFSIZ)
{ bufctr = 0;
write(fd,buffer,BUFSIZ/SECSIZ);
}
if(!showrecv)
printf("Received sector %d\n",sectcurr);
sendline(ACK);
}
else
{ printf("Checksum error, expected <%0x>\n",checksum);
errorflag = TRUE;
}
}
else
if(sectcurr == sectnum)
{ do;
while(readline(1) != TIMEOUT);
printf("Received duplicate sector %d\n", sectcurr);
sendline(ACK);
}
else
{ printf("Synchronization error\n");
errorflag = TRUE;
}
}
else
{ printf("Sector number error\n");
errorflag = TRUE;
}
}
if(errorflag == TRUE)
{ errors++;
printf("Error %d\n",errors);
while(readline(1) != TIMEOUT);
sendline(NAK);
}
}
while(firstchar != EOT && errors != ERRORMAX);
if((firstchar == EOT) && (errors < ERRORMAX))
{ sendline(ACK);
write(fd,buffer,1 + (bufctr/SECSIZ));
close(fd);
printf("Transfer complete\n");
}
else
printf("Aborting\n");
}
sendfile(file)
char *file;
{
int j, sectnum, sectors, attempts;
int checksum;
int bufctr, fd;
if(view)
{ showrecv = FALSE;
showtrans = TRUE;
}
option2 = 'A';
fd = open(file,0);
if(fd == -1)
{ printf("Cannot open %s\n",file);
exit();
}
initializemodem();
attempts = 0;
sectnum = 1;
while((sectors = read(fd,buffer,BUFSIZ/SECSIZ)) && (attempts != RETRYMAX))
{ if(sectors == -1)
printf("\nFile read error\n");
else
{ bufctr = 0;
do
{ attempts = 0;
do
{ if(!showtrans)
printf("\nSending sector %d\n",sectnum);
sendline(SOH);
sendline(sectnum);
sendline(-sectnum-1);
checksum = 0;
if(option2 == 'A')
asciiflg = TRUE;
for(j = bufctr;j < (bufctr + SECSIZ);j++)
{ sendline(buffer[j]);
checksum = (checksum + buffer[j]) & 0xff;
}
asciiflg = FALSE;
sendline(checksum);
purgeline();
attempts++;
}
while((readline(10) != ACK) && (attempts != RETRYMAX));
bufctr = bufctr + SECSIZ;
sectnum++;
sectors--;
}
while((sectors != 0) && (attempts != RETRYMAX));
}
}
if(attempts == RETRYMAX)
printf("\nNo ACK on sector, aborting\n");
else
{ attempts = 0;
do
{ sendline(EOT);
purgeline();
attempts++;
}
while((readline(10) != ACK) && (attempts != RETRYMAX));
if(attempts == RETRYMAX)
printf("\nNo ACK on EOT, aborting\n");
else
printf("\nTransfer complete\n");
}
close(fd);
}
ckfile(argc) int argc;
{ if(!argc)
{ printf("File required\n");
exit();
}
}
main(argc,argv)
int argc;
char **argv;
{ char *s;
printf("Cmodem (Pmmi) ver 1.3 13-Apr-81\n");
printf(" mod. by Rod Hart\n");
cntrlw2 = 0;
asciiflg = hangup = showrecv = showtrans = view = FALSE;
if(**++argv != '-')
{ printf("Command line format: cmodem -options file1 file2 ... file14\n");
printf("Available options are:\n");
printf("\ta: answer t: terminal\n");
printf("\tc: computer u: UNIX\n");
printf("\th: auto-hangup v: view data\n");
printf("\to: originate 1: 110 baud\n");
printf("\tp: PDP10 3: 300 baud\n");
printf("\tr: receive file 4: 450 baud\n");
printf("\ts: send file 6: 600 baud\n");
printf("The p, r, s, and u options require one or more files.\n");
printf("Ctrl-B initiates and terminates data capture in file\n");
printf("cmodem.tmp in the terminal and computer modes.\n");
printf("Ctrl-E is used to initiate file transfers in the UNIX and\n");
printf("PDP10 modes. In the terminal mode Ctrl-E escapes to the\n");
printf("hangup question or CP/M.\n");
printf("Any character escapes the no carrier condition.\n");
exit();
}
--argv;
while(--argc && **++argv == '-')
for(s = *argv+1;*s;s++)
switch(*s)
{ case 'C':
case 'P':
case 'R':
case 'S':
case 'T':
case 'U':
option = *s;
break;
case 'A':
cntrlw0 = cntrlw0 + ANS;
break;
case 'H':
hangup = TRUE;
break;
case 'V':
view = TRUE;
break;
case 'O':
cntrlw0 = cntrlw0 + ORIG;
break;
case '1':
cntrlw2 = BR110;
dtrr = UND300;
break;
case '3':
cntrlw2 = BR300;
dtrr = UND300;
break;
case '4':
cntrlw2 = BR450;
dtrr = OVR300;
break;
case '6':
cntrlw2 = BR600;
dtrr = OVR300;
break;
default:
printf("Unimplemented option %c\n\n",*s);
exit();
break;
}
switch(option)
{ case 'C':
case 'T':
termcomp();
break;
case 'P':
case 'U':
ckfile(argc);
termcomp();
while(argc--)
{ printf("\nSending %s\n",*argv);
pdp10(*argv++);
}
termcomp();
break;
case 'R':
ckfile(argc);
while(argc--)
{ printf("\nReceiving %s\n",*argv);
readfile(*argv++);
}
break;
case 'S':
ckfile(argc);
while(argc--)
{ printf("\nSending %s\n",*argv);
sendfile(*argv++);
}
break;
}
if(hangup)
outp(MODEMCP3,0x00);
else
{ do
{ printf("\nHangup : Y(es), N(o) ? ");
hangup = tolower(getchar());
printf("\n");
}
while((hangup != 'y') && (hangup != 'n'));
if(hangup == 'y')
outp(MODEMCP3,0x00);
}
}