#define DEBUG /* comment me to eliminate main()
/* From CompuServe's BPROGB Borland Int'l forum
*
* #: 11879 S4/Turbo C
* 02-Jun-88 18:54:50
* Sb: #11817-VT100
* Fm: Jerry Joplin 70441,2627
* To: Pete Gontier 72261,1754 (X)
*
* Pete, here are the communication ISR's I've been using. Hope these
* don't overflow the message data base for BPROGB. :-)
* I think all is included to set up COM1/COM2 for receiver interrupts.
*
* Also, these are straight ports from routines in MSKERMIT 2.30 and CKERMIT
* for UNIX, which are public domain but copyrighted (c) by Columbia
* University.
*/
/* Modification, to support other compiler(s):
* Pete Gontier, July 20th, 1988
* This code is no longer portable to the UNIX systems mentioned.
* The function names were in accordance with the TT teletype conventions,
* and I couldn't stand for it. So sue me.
*/
/* Modification, to support comm ports 3 & 4
* Al Sharpe, June 7, 1989
* Minor changes added to handle DTR on port close.
*
* New function added :
* flsh_dtr( ) - drops DTR for 200 milliseconds
*
* Old function modified :
* comm_getc( unsigned seconds ) - (1) gets a char from input buffer
* with timeout
* (2) if a key is pressed a Timeout
* is returned
*/
/* Last modification by Al Sharpe, April 28, 1990.
*
* - corrected comm_close() to drop RTS and DTR, not just DTR.
* - correct flsh_dtr( ) to drop only DTR and leave RTS active.
* - flsh_dtr( ) duration extented to 1/2 second.
* - correct all bugs in function main( ) so test program will work.
* - removed global CARRIER as it was redundant.
* - conio.h added for cprintf( ) function.
*/
#include <dos.h>
#include <bios.h>
#include <conio.h>
#define TCICOMM /* avoid extern declaration in... */
#include "comm.h" /* comm prototypes */
/** macros for absolute data ************************************************/
#define MDMDAT1 0x03F8 /* Address of modem port 1 data */
#define MDMSTS1 0x03FD /* Address of modem port 1 status */
#define MDMCOM1 0x03FB /* Address of modem port 1 command */
#define MDMDAT2 0x02F8 /* Address of modem port 2 data */
#define MDMSTS2 0x02FD /* Address of modem port 2 status */
#define MDMCOM2 0x02FB /* Address of modem port 2 command */
#define MDMDAT3 0x03E8 /* Address of modem port 3 data */
#define MDMSTS3 0x03ED /* Address of modem port 3 status */
#define MDMCOM3 0x03EB /* Address of modem port 3 command */
#define MDMDAT4 0x02E8 /* Address of modem port 4 data */
#define MDMSTS4 0x02ED /* Address of modem port 4 status */
#define MDMCOM4 0x02EB /* Address of modem port 4 command */
#define MDMINTV 0x000C /* Com 1 & 3 interrupt vector */
#define MDINTV2 0x000B /* Com 2 & 4 interrupt vector */
#define MDMINTO 0x0EF /* Mask to enable IRQ3 for port 1 & 3 */
#define MDINTO2 0x0F7 /* Mask to enable IRQ4 for port 2 & 4 */
#define MDMINTC 0x010 /* Mask to Disable IRQ4 for port 1 & 3 */
#define MDINTC2 0x008 /* Mask to Disable IRQ3 for port 2 & 4 */
#define INTCONT 0x0021 /* 8259 interrupt controller ICW2-3 */
#define INTCON1 0x0020 /* Address of 8259 ICW1 */
#define CBS 2048 /* Communications port buffer size */
#define XOFF 0x13 /* XON/XOFF */
#define XON 0x11
#define CARRIER_ON 0x80 /* Return value for carrier detect */
/** globals not externally accessible ***************************************/
static int MODEM_STAT; /* 8250 modem status register */
static int dat8250; /* 8250 data register */
static int stat8250; /* 8250 line-status register */
static int com8250; /* 8250 line-control register */
static char en8259; /* 8259 IRQ enable mask */
static char dis8259; /* 8259 IRQ disable mask */
static unsigned int intv; /* interrupt number to usurp */
static char buffer[CBS]; /* Communications circular buffer */
static char *inptr; /* input address of circular buffer */
static char *outptr; /* output address of circular buffer */
static int c_in_buf = 0; /* count of characters received */
static int xoffpt; /* amount of buffer that forces XOFF */
static int xonpt; /* amount of buffer that unXOFFs */
static void interrupt ( far *oldvec ) ( );
/* vector of previous comm interrupt */
int xonxoff = 0; /* auto xon/xoff support flag */
int xofsnt = 0; /* XOFF transmitted flag */
int xofrcv = 0; /* XOFF received flag */
void interrupt serint ( void ) { /* ISR to receive character */
*inptr++ = inportb ( dat8250 ); /* Store character in buffer */
c_in_buf++; /* and increment count */
if ( xonxoff ) { /* if xon/xoff auto-support is on */
if ( c_in_buf > xoffpt && ! xofsnt ) { /* then if buf nearly full */
comm_putc ( XOFF ); /* send an XOFF */
xofsnt = 1; /* and say so */
}
}
disable ( ); /* ints off for ptr change */
if ( inptr == &buffer[CBS] ) /* Set buffer input pointer */
inptr = buffer;
enable ( );
outportb ( 0x20, 0x20 ); /* Generic EOI to 8259 */
}
void comm_close ( void ) { /* restore previous settings of 8259 */
outportb ( com8250 + 1, 0x08 ); /* Drop OUT2 */
outportb ( com8250 + 1, 0x00 ); /* Drop DTR and RTS /*
outportb ( INTCONT, dis8259 | inportb ( INTCONT ) );
/* Disable com interrupt at 8259 */
setvect ( intv, oldvec ); /* Reset original interrupt vector */
}
void dobaud ( unsigned baudrate ) { /* parses baud integer to mask,
* re-inits port accordingly */
unsigned char portval;
unsigned char blo, bhi;
switch ( baudrate ) { /* Baud rate LSB's and MSB's */
case 50: bhi = 0x9; blo = 0x00; break;
case 75: bhi = 0x6; blo = 0x00; break;
case 110: bhi = 0x4; blo = 0x17; break;
case 150: bhi = 0x3; blo = 0x00; break;
case 300: bhi = 0x1; blo = 0x80; break;
case 600: bhi = 0x0; blo = 0xC0; break;
case 1200: bhi = 0x0; blo = 0x60; break;
case 1800: bhi = 0x0; blo = 0x40; break;
case 2000: bhi = 0x0; blo = 0x3A; break;
case 2400: bhi = 0x0; blo = 0x30; break;
case 4800: bhi = 0x0; blo = 0x18; break;
case 9600: bhi = 0x0; blo = 0x0C; break;
case 19200: bhi = 0x0; blo = 0x06; break;
default:
return;
}
portval = inportb ( com8250 ); /* read Line-Control Reg val */
outportb ( com8250, portval | 0x80 ); /* set high bit for baud init */
outportb ( dat8250, blo ); /* Send LSB for baud rate */
outportb ( dat8250 + 1, bhi ); /* Send MSB for baud rate */
outportb ( com8250, portval ); /* Reset initial value at LCR */
}
/* installs comm interrupts */
int comm_open ( int portid, unsigned speed )
{
int be = biosequip ( ); /* to get # installed serial ports */
be <<= 4; /* shift-wrap high bits off */
be >>= 13; /* shift down to low bits */
i