Metropoli BBS
VIEWER: acl01.c MODE: TEXT (ASCII)
/*
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);
}
[ RETURN TO DIRECTORY ]