/*
Copyright (C) Magna Carta Software, Inc. 1990-1991. All Rights Reserved.
Routines to support the Star Gate ACL series of multiport boards.
ACL01.C -- This file contains routines that interface the ACL board to the
CCT COMM_PORT structure.
*/
#define CCT_DEVELOPMENT
#include <dos.h>
#include <comm.h>
#include <acl.h>
/*
ACL_GET -- General purpose parameter retriever for the ACL series of
multiport cards.
Return values:
Success: The value of the UART register that sets stopbits;
EOF : Invalid parameter;
*/
short acl_get(COMM_PORT *p, short cmd)
{
short ret = 0;
char *cba = p->cba;
switch (cmd) {
/* DATA FORMAT */
case DATABITS:
ret = acl_get_databits(cba);
break;
case PARITY:
ret = acl_get_parity(cba);
break;
case STOPBITS:
ret = acl_get_stopbits(cba);
break;
/* RS-232 */
case CTS:
ret = acl_ch_get_modem_status(cba) & 1;
break;
case DCD:
ret = (acl_ch_get_modem_status(cba) & 8) >> 3;
break;
case DSR:
ret = (acl_ch_get_modem_status(cba) & 2) >> 1;
break;
case DTR:
ret = acl_ch_get_modem_ctl(cba) & 1;
break;
case RI:
ret = (acl_ch_get_modem_status(cba) & 4) >> 2;
break;
case RTS:
ret = (acl_ch_get_modem_ctl(cba) & 2) >> 1;
break;
default:
ret = EOF;
}
return (ret);
}
/*
ACL_GET_SPEED -- Return the current data transfer rate of the channel.
*/
long acl_get_speed(COMM_PORT *p)
{
return ((long) acl_ch_get(p->cba, ACL_BAUD_RATE));
}
/*
ACL_GET_RX_XLAT -- Query the setting of each of the input translation
variables used in c_getc().
*/
short acl_get_rx_xlat(COMM_PORT *p, short item)
{
short ret = 0;
switch (item) {
case XLAT: ret = isrxxlat(p); break; /* OFF or ON */
case LOCAL_ECHO: ret = isrxecholocal(p); break; /* OFF or ON */
case REMOTE_ECHO: ret = isrxechoremote(p); break;/* OFF or ON */
case PRINTER_ECHO: ret = isrxechoprn(p); break; /* OFF or ON */
case CAPTURE_BUFFER_ECHO: ret = isrxechobuf(p); break; /* OFF or ON */
/*
EOL is one of: FALSE, LF2CR, CR2LF, EOL2SP,
STRIPEOL, LF2CRLF, CR2CRLF, CRLF2LF, CRLF2CR
*/
case EOL: ret = p->rx_eol; break;
case CASE: ret = p->rx_case_convert; break;
case ASCII_ONLY: ret = p->rx_ascii_only; break;
case INTERBYTE_DELAY: ret = p->rx_ibdelay; break;
case FLOWCTL: ret = p->flowctl & RX; break; /* OFF or ON */
case XONCHAR: ret = p->xonchar; break; /* ASCII value */
case XOFFCHAR: ret = p->xoffchar; break; /* ASCII value */
case ABORT_KEY: ret = p->abort_key; break;
default: ret = EOF; break;
}
return (ret);
}
/*
ACL_GET_TX_XLAT -- Return the value of various transmit data translation
parameters.
*/
short acl_get_tx_xlat(COMM_PORT *p, short item)
{
short ret = 0;
switch (item) {
case LOCAL_ECHO: ret = istxecholocal(p); break; /* OFF or ON */
case REMOTE_ECHO: ret = istxechoremote(p);break; /* OFF or ON */
case PRINTER_ECHO: ret = istxechoprn(p); break; /* OFF or ON */
case CAPTURE_BUFFER_ECHO:
ret = istxechobuf(p); break; /* OFF or ON */
case XLAT: ret = istxxlat(p); break; /* OFF or ON */
/*
EOL is one of: FALSE, LF2CR, CR2LF, EOL2SP,
STRIPEOL, LF2CRLF, CR2CRLF, CRLF2LF, CRLF2CR
*/
case EOL: ret = p->tx_eol; break;
case CASE: ret = p->tx_case_convert; break;
case ASCII_ONLY: ret = p->tx_ascii_only; break;
/* INTERBYTE AND INTERLINE DELAYS (in ms.). */
case INTERBYTE_DELAY: ret = p->tx_ibdelay; break;
case INTERLINE_DELAY: ret = p->tx_ildelay; break;
/* CHARACTER TO TRIGGER INTERLINE DELAY */
case INTERLINE_DELAY_CHAR: ret = p->tx_ildelay_ch; break;
case FLOWCTL:
ret = acl_ch_get(p->cba, ACL_LINE_PROTOCOL);
break;
case TX_DELAY:
ret = p->tx_delay;
break;
case TX_DELAYCHAR:
ret = p->tx_delaych;
break;
case XONCHAR: ret = p->xonchar; break; /* ASCII value */
case XOFFCHAR: ret = p->xoffchar; break; /* ASCII value */
/* ASCII CODE OF KEY TO ABORT XOFF */
case ABORT_KEY: ret = p->abort_key; break;
default: ret = EOF; break;
}
return (ret);
}
/*
ACL_INIT_CHANNEL -- Set the parameters for an ACL channel.
Note: The Stargate defaults are shown on p.27 of the "ACL Family Technical
Reference Manual" (Jan. 1990) as:
9600 8-N-1;
No flow ctl;
Return Value:
0 -- success;
PORT_OPEN -- port already initialized;
NO_PORT -- MAX_PORTS already in use;
-2 -- ACL board not initialized;
*/
short acl_init_channel(COMM_PORT *p, ACL *acl, WORD portnum, long speed,
WORD databits, WORD parity, WORD stopbits)
{
short i;
if (p->open) return (PORT_OPEN);
if (!acl->base_addr) return (-2);
/* INITIALIZE DATA IN THE COMM_PORT STRUCTURE */
p->utype = STARGATE_ACL;
p->rxdatabits = databits;
p->txdatabits = databits;
p->parity = parity;
p->stopbits = stopbits;
p->speed = speed;
p->dtr = HIGH;
p->rts = HIGH;
p->abort_key = ESCAPE;
p->cba = acl->cba + acl_ccb_size(acl)*portnum;
p->rxbuf = (BYTE FAR_ *) acl->base_addr;
p->rxbufend = (BYTE FAR_ *) acl->base_addr + acl_ch_get_ibuf_ea(p->cba);
p->rxbufhead = acl->base_addr + acl_ch_get_nctib(p->cba);
p->rxbuftail = acl->base_addr + acl_ch_get_ncfib(p->cba);
p->txbuf = (BYTE FAR_ *) acl->base_addr;
p->txbufend = (BYTE FAR_ *) acl->base_addr + acl_ch_get_obuf_ea(p->cba);
p->txbufhead = acl->base_addr + acl_ch_get_nctob(p->cba);
p->txbuftail = acl->base_addr + acl_ch_get_ncfob(p->cba);
for (i=0; i < 4; i++) p->a_ipr[i] = (void FAR_ *) com_dummy_;
/* INITIALIZE DEVICE-SPECIFIC FUNCTION POINTERS */
p->set = acl_set;
p->get = acl_get;
p->get_rx_xlat = acl_get_rx_xlat;
p->set_rx_xlat = acl_set_rx_xlat;
p->get_tx_xlat = acl_get_tx_xlat;
p->set_tx_xlat = acl_set_tx_xlat;
p->set_speed = acl_set_speed;
p->get_speed = acl_get_speed;
p->rxstat = acl_rxstat;
p->txstat = acl_txstat;
p->c_read = acl_read;
p->c_write = acl_write;
#if 0
p->install_ipr = acl_install_ipr;
p->deinstall_ipr = acl_deinstall_ipr;
p->deinit_port = acl_deinit;
p->enable_comm_int = acl_enable_comm_int;
p->disable_comm_int = acl_disable_comm_int;
#endif
/* OPEN THE PORT */
return (c_open_(p));
}
/*
ACL_READ -- read a byte from a channel of the ACL board.
Return: the byte read.
*/
short acl_read(COMM_PORT *p)
{
BYTE c;
WORD addr;
void *cba = p->cba;
addr = acl_ch_get_ncfib(cba);
c = *(addr++ + p->rxbuf);
if (addr > acl_ch_get_ibuf_ea(cba))
acl_ch_set_ncfib(cba, acl_ch_get_ibuf_sa(cba));
else acl_ch_set_ncfib(cba, addr);
if (p->rxdatabits == 7) c &= 0X7F;
else if (p->rxdatabits == 6) c &= 0X3F;
else if (p->rxdatabits == 5) c &= 0X1F;
return (c);
}
/*
ACL_RXSTAT -- report whether a character is ready in the channel
receive buffer.
Return value:
FALSE (NULL) if no byte is ready. Else TRUE.
*/
short acl_rxstat(COMM_PORT *p)
{
return (acl_ch_get_ncfib(p->cba) != acl_ch_get_nctib(p->cba));
}
/*
ACL_SET -- General purpose command dispatcher for the ACL board.
Return values:
0 -- Success;
EOF -- Invalid parameter;
*/
short acl_set(COMM_PORT *p, short cmd, short value)
{
short ret = 0;
char *cba = p->cba;
switch (cmd) {
/* DATA FORMAT */
case DATABITS:
ret = acl_ch_set_databits(cba, value);
break;
case PARITY:
ret = acl_ch_set_parity(cba, value);
break;
case STOPBITS:
ret = acl_ch_set_stopbits(cba, value);
break;
case BREAK:
ret = acl_ch_get_modem_ctl(cba) | ACL_BREAK;
ret = acl_ch_set_modem_ctl(cba, ret);
break;
/* RS-232 */
case DTR:
ret = (acl_ch_get_modem_ctl(cba) & ~ACL_DTR) | value;
acl_ch_set_modem_ctl(cba, ret);
break;
case OUT1:
case OUT2:
ret = EOF;
break;
case RTS:
value <<= 1;
ret = (acl_ch_get_modem_ctl(cba) & ~ACL_RTS) | value;
acl_ch_set(cba, ACL_MODEM_CONTROL, ret);
break;
/* DIAGNOSTIC/OTHER */
case LOOPBACK:
ret = acl_set_channel_mode(p, value);
break;
default:
ret = EOF;
}
return (ret);
}
/*
ACL_SET_CHANNEL_MODE -- Set the mode for an ACL channel.
Parameters:
ACL *acl -- ptr. to the ACL structure;
WORD mode -- desired operating mode;
Return Value:
the value of the Channel Status Word;
*/
short acl_set_channel_mode(COMM_PORT *p, WORD mode)
{
WORD format = (acl_ch_get(p->cba, ACL_DATA_FORMAT) & 0X3F) | mode;
return (acl_ch_set_data_format(p->cba, format));
}
/*
ACL_SET_RX_XLAT -- Specify the type of input translation used by c_getc()
and c_gets().
*/
short acl_set_rx_xlat(COMM_PORT *p, short item, short value)
{
WORD format;
short ret = 0;
switch (item) {
case LOCAL_ECHO:
case REMOTE_ECHO:
case PRINTER_ECHO:
case CAPTURE_BUFFER_ECHO:
if (value) p->echo |= item;
else p->echo &= ~item;
break;
/*
EOL is one of: FALSE, LF2CR, CR2LF, EOL2SP,
STRIPEOL, LF2CRLF, CR2CRLF, CRLF2LF, CRLF2CR
*/
case EOL:
p->rx_eol = value;
break;
case CASE: /* UPPER, LOWER, FALSE */
p->rx_case_convert = value; break;
case ASCII_ONLY:
p->rx_ascii_only = value; break;
case INTERBYTE_DELAY:
p->rx_ibdelay = value; break;
case TRAILINGBYTE_DELAY:
p->rx_tbdelay = value; break;
case FLOWCTL:
if (value) p->flowctl |= (value >> 4);
else p->flowctl &= ~RX;
break;
case FLOWHIGH:
p->flowhigh = value;
break;
case XONCHAR: /* value to be considered an XON */
format = acl_ch_get(p->cba, ACL_LINE_PROTOCOL);
if (value == XON_ALL) acl_ch_set_line_protocol(p->cba, format | ACL_XON_ALL);
else {
acl_ch_set_line_protocol(p->cba, format & ~ACL_XON_ALL);
format = acl_ch_get(p->cba, ACL_IXON_CHARACTERS) & 0X00FF;
acl_ch_set_ixon_chars(p->cba, format | (value << 8));
}
p->xonchar = value; /* a specific char. */
break;
case XOFFCHAR:
format = acl_ch_get(p->cba, ACL_IXON_CHARACTERS) & 0XFF00;
acl_ch_set_ixon_chars(p->cba, format | value);
p->xoffchar = value;
break;
/* SCAN CODE/CHARACTER CODE OF KEY TO ABORT */
case ABORT_KEY: p->abort_key = value; break;
/* INTERRUPT THRESHOLD LEVEL */
case ACL_INPUT_BUFFER_TRIGGER_RATE:
ret = acl_ch_set_ibuf_trig(p->cba, value);
break;
case ACL_INPUT_BUFFER_LWM:
ret = acl_ch_set_ibuf_lwm(p->cba, value);
break;
case ACL_INPUT_BUFFER_HWM:
ret = acl_ch_set_ibuf_hwm(p->cba, value);
break;
default: ret = EOF; break;
}
if (!ret) {
if (value) p->rx_xlat = 1;
else p->rx_xlat = isrxxlat(p);
}
return (ret);
}
/*
ACL_SET_SPEED -- Set the speed of an ACL channel.
Parameters:
ACL_GCB *acl -- ptr. to the Global Control Block structure;
long speed -- desired port speed;
Return Value:
the value of the Channel Status Word;
*/
short acl_set_speed(COMM_PORT *p, long speed)
{
return (acl_ch_set(p->cba, ACL_BAUD_RATE, (WORD) speed));
}
/*
ACL_SET_TX_XLAT -- Assign values to data translation parameters.
*/
short acl_set_tx_xlat(COMM_PORT *p, short item, short value)
{
WORD format;
short ret = 0;
switch (item) {
case LOCAL_ECHO:
case REMOTE_ECHO:
case PRINTER_ECHO:
case CAPTURE_BUFFER_ECHO:
if (value) p->echo |= (item << 4);
else p->echo &= ~(item << 4);
break;
/*
EOL is one of: FALSE, LF2CR, CR2LF, EOL2SP,
STRIPEOL, LF2CRLF, CR2CRLF, CRLF2LF, CRLF2CR
*/
case EOL:
p->tx_eol = value;
break;
case CASE: /* UPPER, LOWER, NORMAL */
p->tx_case_convert = value;
break;
case ASCII_ONLY:
p->tx_ascii_only = value;
break;
case INTERBYTE_DELAY:
p->tx_ibdelay = value;
break;
case TX_DELAY:
p->tx_delay = value;
break;
case TX_DELAYCHAR:
p->tx_delaych = value;
break;
case INTERLINE_DELAY:
p->tx_ildelay = value;
break;
case INTERLINE_DELAY_CHAR:
p->tx_ildelay_ch = value;
break;
case FLOWCTL:
format = acl_ch_get(p->cba, ACL_LINE_PROTOCOL);
if (value) switch (value) {
case XONXOFF:
acl_ch_set_line_protocol(p->cba, format | ACL_XONXOFF_ASSERT);
break;
case RTS_CTS:
acl_ch_set_line_protocol(p->cba, format | ACL_RTS_CTS_ASSERT);
break;
default:
ret = EOF;
break;
}
else switch (value) {
case XONXOFF:
acl_ch_set_line_protocol(p->cba, format & ~ACL_XONXOFF_ASSERT);
break;
case RTS_CTS:
acl_ch_set_line_protocol(p->cba, format & ~ACL_RTS_CTS_ASSERT);
break;
default:
ret = EOF;
break;
}
break;
case XONCHAR: /* value to be considered an XON */
format = acl_ch_get(p->cba, ACL_IXOFF_CHARACTERS) & 0X00FF;
acl_ch_set_ixoff_chars(p->cba, format | (value << 8));
p->xonchar = value; /* a specific char. */
break;
case XOFFCHAR:
format = acl_ch_get(p->cba, ACL_IXOFF_CHARACTERS) & 0XFF00;
acl_ch_set_ixoff_chars(p->cba, format | value);
p->xoffchar = value;
break; /* ASCII value */
/* SCAN CODE/CHARACTER CODE OF KEY TO ABORT XOFF */
case ABORT_KEY:
p->abort_key = value;
break;
case ACL_OUTPUT_BUFFER_LWM:
ret = acl_ch_set_obuf_lwm(p->cba, value);
break;
default:
ret = EOF;
break;
}
if (!ret) {
if (value) p->tx_xlat = 1;
else p->tx_xlat = istxxlat(p);
}
return (ret);
}
/*
ACL_TXSTAT -- report whether ACL transmit buffer is ready for a byte.
Return: FALSE if transmit buffer is not empty
TRUE if transmit buffer is empty.
*/
short acl_txstat(COMM_PORT *p)
{
return(acl_ch_get_ncfob(p->cba) != acl_ch_get_nctob(p->cba) + 1);
}
/*
ACL_WRITE -- write a byte to the output buffer of an ACL channel.
*/
void acl_write(COMM_PORT *p, short c)
{
char *cba = p->cba;
WORD addr = acl_ch_get_nctob(cba);
*(p->txbuf + addr++) = (BYTE) c;
if (addr > acl_ch_get_obuf_ea(cba))
acl_ch_set_nctob(cba, acl_ch_get_obuf_sa(cba));
else acl_ch_set_nctob(cba, addr);
}