
prototypes and equates:
------------------------------------------------------------------------------
rioini(int,int);
    1st arg: can be 1-4 (com port) or base address, or 0 to terminate
    2nd arg: can be irq line (presently 1-7) or 0 (com1/3=4, com2/4=3)
    returns: -1 if error, else 0
setbaud(int);
    returns: -1 if rioini() not called first, else 0
dtr(char);
    argument: 0 off, 1 on, 2-n off then wait n seconds for dcd off
    returns: -1 if rioini() not called or timeout, else 0
outcom(int);
    argument: character to output (low 8 bits)
    returns: state (high 8 bits)
incom(void);
    returns: character from input buffer (low 8 bits), state (high 8 bits)
rioctl(int);
    argument: action (see below)
    returns: mode or state (high 8 bits), status (low 8 bits)
rioifc(char);
    argument: defines what interrupts to intercept (see below)
    returns: -1 if no action taken, else 0


/* i/o mode and state flags */

#define CTSCK 0x800     /* check cts (mode only) */
#define ABORT 0x400     /* check for ^C (mode), aborting (state) */
#define PAUSE 0x200     /* check for ^S (mode), pausing (state) */
#define NOINP 0x100     /* input buffer empty (incom only) */

/* status flags */

#define DCD 0x80        /* DCD on */
#define CTS 0x10        /* CTS on */
#define RXLOST 1        /* Receive buffer overflow */

/* rioctl() arguments */
/* returns mode or state flags in high 8 bits, status flags in low 8 bits */

                    /* the following return mode in high 8 bits */
#define IOMODE 0        /* no operation */
#define IOSM 1          /* i/o set mode flags */
#define IOCM 2          /* i/o clear mode flags */
                    /* the following return state in high 8 bits */
#define IOSTATE 4       /* no operation */
#define IOSS 5          /* i/o set state flags */
#define IOCS 6          /* i/o clear state flags */
#define IOFB 0x308      /* i/o buffer flush */
#define IOFI 0x208      /* input buffer flush */
#define IOFO 0x108      /* output buffer flush */
#define IOSE 9          /* i/o set error flags */

/* rioifc() arguments */

#define INT29 1         /* copy int 29h output to remote */
#define INT29B 3        /* copy int 29h, use BIOS locally (_putlc) */
#define INT16 0x10      /* return remote chars to int 16h calls */
#define INTCLR 0        /* release int 16h, int 29h */
------------------------------------------------------------------------------
You can make whatever permutations of these make things easy, e.g.,

#define INCHK IOSM|PAUSE|ABORT   /* check for ^C and ^S (mode) */
#define NOCHK IOCM|PAUSE|ABORT   /* turn off ^C and ^S checking */

Then rioctl(INCHK); turns checking on, and rioctl(NOCHK); turns it off.

A sample calling sequence:

    rioini(3,0);
    setbaud(2400);
    rioctl(INCHK);
    i=incom();
    if (!i&NOINP) putlc(i);
    else if (i&ABORT) {
        rioctl(IOCS|ABORT);  /* reset abort flag */
        lprintf("YAAA!\n"); }
    rioifc(INT29B|INT16);
    spawn(or something);
    rioifc(INTCLR); /* this puts the original int29/int16 vectors back */
    rioini(0,0);  /* this puts the original int0b vector back
                     and will release the irq line */

Note: incom() returns 500h (not 400h) when in an abort wait, because the
      input buffer is always cleared.  If output is paused, incom may return
      2xxh or 300h, depending on whether there is a character in the input
      buffer.  Pause (200h) and abort (400h) will never be set at the same
      time.

No questions, right?  Clear as a sky of azure blue?
