Category : C Source Code
Archive   : SERIALC.ZIP
Filename : SERIAL.C
==========================
c.language/listings #115, from barryn, 8544 chars, Sat Aug 29 17:17:28 1987
--------------------------
TITLE: Communications routines in Turbo C
The following code shows how to take advantage of some of
the TurboC extensions to the C language to do asynchronous
communications (without having to write supporting assembly-
language routines). The code was supplied by Peter Ibbotson of
Borland. After the communications-related functions themselves,
you'll find a small main() section of code that uses those functions
to implement a rudimentary glass-TTY terminal program. (I say
rudimentary to mean that control characters are not recognized and
there are no file transfer, dialing directory, etc. features.)
First, here's Serial.C:
*/
/* SERIAL.C */
#include "serial.h"
#include
#include
#include
#include
#include
int SError;
int portbase=0;
void interrupt (*oldvects[2])();
char ccbuf[SBUFSIZ];
int startbuf=0;
int endbuf=0;
/* this does the hard work (handling interrupts) */
void interrupt com_int (void)
{ disable ();
if ((inportb (portbase+IIR) & RX_MASK)==RX_ID)
{ if (((endbuf+1) & 0x1fff)==startbuf)
SError=BUFOVFL;
ccbuf[endbuf++]=inportb (portbase+RX);
endbuf&=0x1fff;
};
outportb (ICR,EOI);
enable ();
}
/* this routine returns the current value in the buffer */
int getccb(void)
{ int res;
if (endbuf==startbuf) return (-1);
res=(int) ccbuf[startbuf];
startbuf=(startbuf+1) % SBUFSIZ;
return (res);
}
void setvects (void)
{ oldvects[0]=getvect(0x0b);
oldvects[1]=getvect(0x0c);
setvect(0x0b,com_int);
setvect(0x0c,com_int);
}
void resvects (void)
{ setvect(0x0b,oldvects[0]);
setvect(0x0c,oldvects[1]);
}
void i_enable (int pnum)
{ int c;
disable();
c = inportb (portbase+MCR) | MC_INT;
outportb (portbase+MCR,c);
outportb (portbase+IER,RX_INT);
c = inportb (IMR) & (pnum==2 ? IRQ3 : IRQ4);
outportb (IMR,c);
enable();
}
void i_disable (void)
{ int c;
disable ();
c=inportb (IMR) | ~IRQ3 | ~IRQ4;
outportb (IMR,c);
outportb (portbase + IER,0);
c=inportb (portbase+MCR) & ~MC_INT;
outportb (portbase+MCR,c);
enable ();
}
void comon (void)
{ int c,pnum;
pnum = portbase == COM1BASE ? 1 : 2;
i_enable (pnum);
c=inportb (portbase + MCR) | DTR | RTS;
outportb (portbase + MCR,c);
}
void initserial (void)
{ endbuf=startbuf=0;
setvects();
comon();
};
void comoff (void)
{ i_disable ();
outportb (portbase+MCR,0);
}
void closeserial(void)
{ comoff();
resvects();
};
/* this outputs a serial character */
int SerialOut (char x)
{ long timeout = 0x0000ffff;
outportb (portbase+MCR,OUT2|DTR|RTS);
/* wait for clear to send */
while ((inportb(portbase + MSR) & CTS)==0)
if ((--timeout)==0) return (-1);
timeout=0x0000ffff;
/* wait for outport register to clear */
while ((inportb(portbase+LSR) & DSR)==0)
if ((--timeout)==0) return (-1);
disable ();
outportb (portbase+TX,x);
enable ();
return (0);
}
/* this routine sets which port we are working with */
int SetPort (int Port)
{ int far * RS232_Addr;
int Offset;
switch (Port) /* sort out the base address */
{ case 1 : Offset=0x0000; break; /* only ports one & two allowed */
case 2 : Offset=0x0002; break;
default : return (-1);
};
RS232_Addr=MK_FP(0x0040,Offset); /* find out where the port is */
if (*RS232_Addr==0) return (-1); /* if it ain't there return (-1)*/
portbase=*RS232_Addr; /* otherwise set portbase */
return (0);
}
/* this routine sets the speed; will accept funny baud rates */
int SetSpeed (int Speed)
{ char c;
int divisor;
if (Speed==0) return (-1); /* avoid divide by zero */
else divisor=(int)(115200L/Speed);
if (portbase==0) return (-11);
disable ();
c=inportb (portbase+LCR);
outportb (portbase+LCR,(c|0x80)); /* set DLAB */
outportb (portbase+DLL,(divisor & 0x00ff)); /* set divisor */
outportb (portbase+DLH,((divisor>>8)&0x00ff));
outportb (portbase+LCR,c);
enable();
return (0);
}
/* This routine set the LCR */
int SetOthers (int Parity,int Bits,int StopBit)
{ int temp;
if (portbase==0) return (-1);
if ((Parity
if ((Bits<5) || (Bits>8)) return (-1);
if ((StopBit<1) || (StopBit>2)) return (-1);
temp=Bits-5;
temp|=((StopBit==1) ? 0x00 : 0x04);
switch (Parity)
{ case NO_PAR : temp |= 0x00; break;
case OD_PAR : temp |= 0x08; break;
case EV_PAR : temp |= 0x18; break;
}
disable(); /* turn off interrupts */
outportb (portbase+LCR,temp);
enable(); /* turn em back on */
return (0);
}
/* This routine sets the ports */
int setserial (int Port,int Speed,int Parity,int Bits,int StopBit)
{ if (SetPort(Port)==-1) return(-1);
if (SetSpeed(Speed)==-1) return(-1);
if (SetOthers(Parity,Bits,StopBit)==-1) return (-1);
return (0);
}
/* short demo */
/* this opens the ports and echos to screen until */
/* ESCape received */
main ()
{ int c;
if (setserial (COM1,2400,NO_PAR,8,1) ==-1) exit (1);
initserial();
printf("You're now in terminal mode. Press ESC to quit the program.\n\n");
do {
if (kbhit()) {
c = getch();
if (c==27)
break;
SerialOut(c);
}
if ((c=getccb())!=-1)
putchar (c);
} while (c!=27);
closeserial();
}
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/