home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload
/
ShartewareOverload.cdr
/
progm
/
ctask.zip
/
TSKSIO.C
< prev
next >
Wrap
C/C++ Source or Header
|
1988-03-01
|
15KB
|
583 lines
/*
TSKSIO.C - CTask - Serial I/O interface routines.
Public Domain Software written by
Thomas Wagner
Patschkauer Weg 31
D-1000 Berlin 33
West Germany
*/
#include "tsk.h"
#include "sio.h"
#define MK_FP(seg,ofs) ((farptr)(((dword)(seg) << 16) | (ofs)))
typedef void (interrupt far * intprocptr)(void);
#define RTS 0x02
#define DTR 0x01
#define ERR_MASK 0x1e
#define inta00 0x20 /* 8259 interrupt controller control-port */
#define inta01 0x21 /* 8259 interrupt controller mask-port */
#define rdserv 0x0b /* read service register control value */
#define eoi 0x20 /* end of interrupt signal for 8259 */
#define intdata 0x0b /* Enable Interrupts except Line status */
#define rxreadybit 0x01
#define txemptybit 0x40
#define txreadybit 0x20
#define framingbit 0x08
#define breakbit 0x10
#define linecontrol 0x0b
#define linestatus 0x0d
#define intid 0x0a
#define intenable 0x09
#define modemcontrol 0x0c
#define modemstatus 0x0e
#define receivedata 0x08
#define transmitdata 0x08
#define baudreg_dll 0x08 /* baud rate least significant byte */
#define baudreg_dlm 0x09 /* baud rate most significant byte */
/*
Default values for initialising the ports.
Change to your liking.
*/
#define dflt_modcon 0x0f /* Modem Control: Activate DTR & RTS */
#define dflt_baud 96 /* Baud Rate Divisor: 1200 Baud */
#define dflt_lcon 0x03 /* Line Control: No Parity, 1 Stop, 8 Data */
/*
To add support for other COM-Ports, define
- Port base
- IRQ-Bit
- Interrupt vector
here, add the necessary data to the port_descr array,
and define the corresponding interrupt function by duplicating sioint0,
replacing the index into the sio_data array.
*/
#define PORTS 2 /* Number of defined ports */
#define com1_base 0x3f0 /* COM1 port base */
#define com2_base 0x2f0 /* COM2 port base */
#define com1_irq 0x10 /* IRQ-Bit for COM1 */
#define com2_irq 0x08 /* IRQ-Bit for COM2 */
#define com1_vect 0x0c /* Interrupt vector for COM1 */
#define com2_vect 0x0b /* Interrupt vector for COM2 */
typedef struct {
intprocptr proc;
int base;
byte irq;
byte vector;
} port_data;
local void interrupt far sioint0 (void);
local void interrupt far sioint1 (void);
port_data port_descr [PORTS] = {
{ sioint0, com1_base, com1_irq, com1_vect },
{ sioint1, com2_base, com2_irq, com2_vect }
};
static long baud_table [] = {
50L, 2304L,
75L, 1536L,
110L, 1047L,
134L, 857L,
150L, 768L,
300L, 384L,
600L, 192L,
1200L, 96L,
1800L, 64L,
2000L, 58L,
2400L, 48L,
3600L, 32L,
4800L, 24L,
7200L, 16L,
9600L, 12L,
19200L, 6L,
38400L, 3L,
0L, 0L };
/*-------------------------------------------------------------------------*/
typedef struct {
farptr savvect; /* Interrupt vector save location */
int port_base; /* Port base I/O address */
int r_xoff; /* Receive disable (XOFF sent) */
int t_xoff; /* Transmit disable (XOFF received) */
int xoff_threshold; /* Pipe free threshold for XOFF */
int xon_threshold; /* Pipe free threshold for XON */
byte clcontrol; /* Current line control reg */
byte cmodcontrol; /* Current modem control reg */
byte irqbit; /* IRQ-Bit for this port */
byte civect; /* Interrupt Vector for this port */
byte modstat; /* Current modem status */
byte wait_xmit; /* Transmit delayed */
byte xmit_pending; /* Transmit in progress */
byte rtsoff; /* RTS turned off by protocol */
byte overrun; /* Pipe full on receive */
byte modem_flags; /* Transmit enable modem flags */
byte flags; /* Protocol flags */
wpipe rcv_pipe; /* Received characters */
pipe xmit_pipe; /* Transmit pipe */
} sio_datarec;
typedef sio_datarec *sioptr;
static sio_datarec sio_data [PORTS];
/*-------------------------------------------------------------------------*/
local void near change_rts (sioptr data, int on)
{
data->rtsoff = (byte)(!on);
data->cmodcontrol = (data->cmodcontrol & ~RTS) | ((on) ? RTS : 0);
tsk_outp (data->port_base + modemcontrol, data->cmodcontrol);
}
local void near transmit_ready (sioptr data)
{
int i;
if ((i = data->r_xoff) < 0)
{
tsk_outp (data->port_base + transmitdata,
(byte)((i == -1) ? XOFF : XON));
data->r_xoff = (i == -1) ? 1 : 0;
data->xmit_pending = 1;
return;
}
data->xmit_pending = 0;
if (!(data->wait_xmit = (byte)(check_pipe (&data->xmit_pipe) != -1)))
return;
if ((data->modem_flags & data->modstat) ^ data->modem_flags)
return;
if (data->flags & XONXOFF && data->t_xoff)
return;
data->wait_xmit = 0;
if ((i = c_read_pipe (&data->xmit_pipe)) < 0)
return;
tsk_outp (data->port_base + transmitdata, (byte)i);
data->xmit_pending = 1;
}
local void near modem_status_int (sioptr data)
{
data->modstat = tsk_inp (data->port_base + modemstatus);
if (data->wait_xmit)
transmit_ready (data);
}
local void near receive_ready (sioptr data)
{
word status;
word ch;
while ((status = tsk_inp (data->port_base + linestatus)) & rxreadybit)
{
ch = tsk_inp (data->port_base + receivedata);
if (data->flags & XONXOFF)
{
if (ch == XON)
{
data->t_xoff = 0;
if (data->wait_xmit)
transmit_ready (data);
continue;
}
else if (ch == XOFF)
{
data->t_xoff = 1;
continue;
}
if (!data->r_xoff &&
wpipe_free (&data->rcv_pipe) < data->xoff_threshold)
{
data->r_xoff = -1;
if (!data->xmit_pending)
transmit_ready (data);
}
}
if (data->flags & RTSCTS && !data->rtsoff)
if (wpipe_free (&data->rcv_pipe) < data->xoff_threshold)
change_rts (data, 0);
status = (status & ERR_MASK) << 8;
if (c_write_wpipe (&data->rcv_pipe, ch | status) < 0)
data->overrun = 1;
}
}
/*-------------------------------------------------------------------------*/
local void near sioint (sioptr data)
{
int id;
tsk_sti ();
while (!((id = tsk_inp (data->port_base + intid)) & 1))
switch (id & 0x07)
{
case 0x00: modem_status_int (data);
break;
case 0x02: transmit_ready (data);
break;
case 0x04: receive_ready (data);
break;
/* case 0x06: line_status_int (data); (currently not used)
break;
*/
}
tsk_cli ();
tsk_outp (inta00, eoi);
}
local void interrupt far sioint0 (void)
{
sioint (&sio_data [0]);
}
local void interrupt far sioint1 (void)
{
sioint (&sio_data [1]);
}
/*-------------------------------------------------------------------------*/
int far v24_install (int port,
farptr rcvbuf, word rcvsize,
farptr xmitbuf, word xmitsize)
{
sioptr sio;
int pbase;
intprocptr far *intptr;
if (port < 0 || port >= PORTS || !rcvsize || !xmitsize)
return -1;
sio = &sio_data [port];
create_pipe (&sio->xmit_pipe, xmitbuf, xmitsize);
create_wpipe (&sio->rcv_pipe, rcvbuf, rcvsize);
pbase = sio->port_base = port_descr [port].base;
sio->civect = port_descr [port].vector;
sio->irqbit = port_descr [port].irq;
sio->clcontrol = dflt_lcon;
sio->cmodcontrol = dflt_modcon;
sio->wait_xmit = sio->xmit_pending = 0;
sio->overrun = 0;
sio->flags = 0;
sio->modem_flags = 0;
sio->r_xoff = sio->t_xoff = 0;
sio->rtsoff = 0;
tsk_outp (pbase + intenable, 0);
intptr = (intprocptr far *)MK_FP (0, sio->civect * 4);
tsk_cli ();
sio->savvect = *intptr;
*intptr = port_descr [port].proc;
tsk_sti ();
tsk_outp (pbase + linecontrol, dflt_lcon | 0x80);
tsk_outp (pbase + baudreg_dll, dflt_baud);
tsk_outp (pbase + baudreg_dlm, dflt_baud >> 8);
tsk_outp (pbase + linecontrol, dflt_lcon);
tsk_outp (pbase + modemcontrol, dflt_modcon);
while (tsk_inp (pbase + linestatus) & rxreadybit)
tsk_inp (pbase + receivedata);
tsk_inp (pbase + linestatus);
sio->modstat = tsk_inp (pbase + modemstatus);
tsk_inp (pbase + intid);
tsk_outp (inta01, tsk_inp (inta01) & ~sio->irqbit);
tsk_outp (pbase + intenable, intdata);
return 0;
}
void far v24_remove (int port)
{
sioptr sio;
intprocptr far *intptr;
sio = &sio_data [port];
tsk_outp (sio->port_base + intenable, 0);
tsk_outp (inta01, tsk_inp (inta01) | sio->irqbit);
intptr = (intprocptr far *)MK_FP (0, sio->civect * 4);
tsk_cli ();
*intptr = sio->savvect;
tsk_sti ();
delete_pipe (&sio->xmit_pipe);
delete_wpipe (&sio->rcv_pipe);
}
/*-------------------------------------------------------------------------*/
/*
void v24_change_rts (int port, int on)
*/
void far v24_change_rts (int port, int on)
{
sioptr sio;
sio = &sio_data [port];
sio->cmodcontrol = (sio->cmodcontrol & ~RTS) | ((on) ? RTS : 0);
tsk_outp (sio->port_base + modemcontrol, sio->cmodcontrol);
}
/*
void v24_change_dtr (int port, int on)
*/
void far v24_change_dtr (int port, int on)
{
sioptr sio;
sio = &sio_data [port];
sio->cmodcontrol = (sio->cmodcontrol & ~DTR) | ((on) ? DTR : 0);
tsk_outp (sio->port_base + modemcontrol, sio->cmodcontrol);
}
/*
void far v24_change_baud (int port, int rate)
*/
void far v24_change_baud (int port, long rate)
{
int i;
sioptr sio;
sio = &sio_data [port];
for (i = 0; baud_table [i]; i += 2)
if (baud_table [i] == rate)
break;
if (!(i = (int)baud_table [i + 1]))
return;
tsk_outp (sio->port_base + linecontrol, sio->clcontrol | (byte)0x80);
tsk_outp (sio->port_base + baudreg_dll, (byte)i);
tsk_outp (sio->port_base + baudreg_dlm, (byte)(i >> 8));
tsk_outp (sio->port_base + linecontrol, sio->clcontrol);
}
void far v24_change_parity (int port, int par)
{
sioptr sio;
sio = &sio_data [port];
sio->clcontrol = (sio->clcontrol & 0xc7) | par;
tsk_outp (sio->port_base + linecontrol, sio->clcontrol);
}
void far v24_change_wordlength (int port, int len)
{
int i;
sioptr sio;
sio = &sio_data [port];
switch (len)
{
case 5: i = 0x00; break;
case 6: i = 0x01; break;
case 7: i = 0x02; break;
case 8: i = 0x03; break;
default: return;
}
sio->clcontrol = (sio->clcontrol & 0xfc) | i;
tsk_outp (sio->port_base + linecontrol, sio->clcontrol);
}
void far v24_change_stopbits (int port, int n)
{
int i;
sioptr sio;
sio = &sio_data [port];
switch (n)
{
case 1: i = 0x00; break;
case 2: i = 0x04; break;
default: return;
}
sio->clcontrol = (sio->clcontrol & 0xfb) | i;
tsk_outp (sio->port_base + linecontrol, sio->clcontrol);
}
void far v24_watch_modem (int port, byte flags)
{
sio_data [port].modem_flags = flags & (CTS | DSR | RI | CD);
}
void far v24_protocol (int port, int prot, word offthresh, word onthresh)
{
byte old;
sioptr sio;
sio = &sio_data [port];
old = sio->flags;
sio->flags = (byte)prot;
if (prot)
{
if (!offthresh)
offthresh = 10;
sio->xoff_threshold = offthresh;
if (onthresh <= offthresh)
onthresh = offthresh + 10;
sio->xon_threshold = onthresh;
}
if ((old & RTSCTS) != ((byte)prot & RTSCTS))
{
change_rts (sio, 1);
sio->modem_flags = (sio->modem_flags & ~CTS) |
((prot & RTSCTS) ? CTS : 0);
}
if (!(prot & XONXOFF))
{
if (sio->r_xoff)
sio->r_xoff = -2;
sio->t_xoff = 0;
}
if (!sio->xmit_pending)
transmit_ready (sio);
}
/*-------------------------------------------------------------------------*/
int far v24_send (int port, byte ch, dword timeout)
{
int res;
if ((res = write_pipe (&sio_data [port].xmit_pipe, ch, timeout)) < 0)
return res;
tsk_cli ();
if (!sio_data [port].xmit_pending)
transmit_ready (&sio_data [port]);
tsk_sti ();
return 0;
}
int far v24_receive (int port, dword timeout)
{
int res;
sioptr sio;
sio = &sio_data [port];
if ((res = (int)read_wpipe (&sio->rcv_pipe, timeout)) < 0)
return res;
if (!sio->flags)
return res;
if (wpipe_free (&sio->rcv_pipe) > sio->xon_threshold)
{
tsk_cli ();
if (sio->r_xoff)
{
sio->r_xoff = -2;
if (!sio->xmit_pending)
transmit_ready (sio);
}
tsk_sti ();
if (sio->rtsoff)
change_rts (sio, 1);
}
return res;
}
int far v24_overrun (int port)
{
int res;
res = sio_data [port].overrun;
sio_data [port].overrun = 0;
return res;
}
int far v24_check (int port)
{
return check_wpipe (&sio_data [port].rcv_pipe);
}
int far v24_modem_status (int port)
{
return sio_data [port].modstat;
}
int far v24_complete (int port)
{
return (check_pipe (&sio_data [port].xmit_pipe) == -1);
}
int far v24_wait_complete (int port, dword timeout)
{
return wait_pipe_empty (&sio_data [port].xmit_pipe, timeout);
}