home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------------*/
- /* */
- /* */
- /* ------------ Bit-Bucket Software, Co. */
- /* \ 10001101 / Writers and Distributors of */
- /* \ 011110 / Freely Available<tm> Software. */
- /* \ 1011 / */
- /* ------ */
- /* */
- /* (C) Copyright 1987-91, Bit Bucket Software Co., a Delaware Corporation. */
- /* */
- /* */
- /* This module was written by Peter Fitzsimmons */
- /* */
- /* */
- /* BinkleyTerm OS/2 Async Comm I/O Routines */
- /* */
- /* */
- /* For complete details of the licensing restrictions, please refer */
- /* to the License agreement, which is published in its entirety in */
- /* the MAKEFILE and BT.C, and also contained in the file LICENSE.250. */
- /* */
- /* USE OF THIS FILE IS SUBJECT TO THE RESTRICTIONS CONTAINED IN THE */
- /* BINKLEYTERM LICENSING AGREEMENT. IF YOU DO NOT FIND THE TEXT OF */
- /* THIS AGREEMENT IN ANY OF THE AFOREMENTIONED FILES, OR IF YOU DO */
- /* NOT HAVE THESE FILES, YOU SHOULD IMMEDIATELY CONTACT BIT BUCKET */
- /* SOFTWARE CO. AT ONE OF THE ADDRESSES LISTED BELOW. IN NO EVENT */
- /* SHOULD YOU PROCEED TO USE THIS FILE WITHOUT HAVING ACCEPTED THE */
- /* TERMS OF THE BINKLEYTERM LICENSING AGREEMENT, OR SUCH OTHER */
- /* AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO. */
- /* */
- /* */
- /* You can contact Bit Bucket Software Co. at any one of the following */
- /* addresses: */
- /* */
- /* Bit Bucket Software Co. FidoNet 1:104/501, 1:343/491 */
- /* P.O. Box 460398 AlterNet 7:491/0 */
- /* Aurora, CO 80046 BBS-Net 86:2030/1 */
- gg/* Internet f491.n343.z1.fidonet.org */
- /* */
- /* Please feel free to contact us at any time to share your comments about */
- /* our software and/or licensing policies. */
- /* */
- /*--------------------------------------------------------------------------*/
-
- #ifndef OS_2
- #pragma message("This Module For OS/2")
- #else
- #include <stdio.h>
- #include <stdarg.h>
- #include <ctype.h>
- #include <conio.h>
- #include <string.h>
- #include <stdlib.h>
- #define INCL_DOS
- #define INCL_DOSDEVICES
- #define INCL_DOSDEVIOCTL
- #define INCL_DOSSEMAPHORES
- #define INCL_NOPM
- #include <os2.h>
- #include "bink.h"
- #include "com.h"
- #include "async.h"
-
- /*--------------------------------------------------------*
- * This file contains the operating system specific *
- * serial communications routines for OS/2. *
- * *
- * (C) Copyright Peter Fitzsimmons Sun 04-16-1989 *
- * *
- * Add-ins for BinkleyTerm on Sat 05-06-1989 *
- * *
- * Worked over once again on 06/06-91, trying to get the *
- * same effect as the Rev 6 FOSSIL in it *
- *--------------------------------------------------------*/
-
- /* This one has excellent send or receive, even with 8088 */
- /* but the xmit rate is a bit low in Janus w/o SetPrty. */
-
-
- /* #define DEBUG */ /* Exposes a bit more about ASYNC comm */
- /* #define MultiWrt */ /* Not always reliable */
-
-
- extern void status_line (char *,...);
- extern void com_kick (void);
-
- /* Private data */
- /* static HFILE hfComHandle = -1; */ /* handle from DosOpen() */
- HFILE hfComHandle = -1; /* handle from DosOpen() */
-
- /* transmitter stuff */
- #define TSIZE 8192
- static unsigned char tBuf[TSIZE];
- static unsigned char zTxBuf[TSIZE];
- static int zpos = 0;
- static int tBufsize = 0;
- static unsigned int TQSize = 0;
- /* static HSEM WriteSem = 0; */
- ULONG WriteSem = 0;
-
- /* receiver stuff */
- #define RSIZE 8192
- static unsigned char rbuf[RSIZE];
- static USHORT rpos = 0;
- static int rbufsize = 0;
- static USHORT Rbytes = 0;
- static word RQBbytes = 0;
- static word RQBbyte2 = 0;
-
- #ifdef DEBUG
-
- #define debug_msg(m,c) status_line("!" m, c)
- #define IOCtl(func, data, parm) _ioctl(#func, func, (void far *) data, (void far *) parm)
-
- static int _ioctl(char *funcname, int func, void far * data, void far * parm)
- {
- int i;
-
- if (i = DosDevIOCtl((PVOID) data, (PVOID) parm, func, IOCTL_ASYNC, (HFILE) hfComHandle)) {
- printf("ioctl(%s) err(0x%04x)\n", funcname, i);
- status_line("!ioctl(%s) err(0x%04x)", funcname, i);
- }
- return (i);
- }
-
- #else
- #define debug_msg(m,c)
- #define IOCtl(func, data, parm) DosDevIOCtl((PVOID) data, (PVOID) parm, func, IOCTL_ASYNC, (HFILE) hfComHandle)
- #endif
-
- static int com_getDCB(struct _DCBINFO far * dcb);
- static int com_setDCB(struct _DCBINFO far * dcb);
-
-
- /* com_init() : Intialize communications port. Baud rate is preserved.
- * int port : Hardware port (0 based) to init
- * -OR- char *unc : Full UNC \\networkId\modemId to init.
- *
- * if unc==NULL, port is used. if unc != NULL, unc is used
- */
- int com_init(int port, char far *unc)
- {
- char str[30];
- char *s;
- USHORT ActionTaken; /* action: returned by OS/2 */
- USHORT stat;
- DCBINFO sDCB;
- RXQUEUE q;
-
- cputs("\033[1;33mOS/2 FOSSIL emulator for BinkleyTerm, Peter Fitzsimmons (1:250/628)\033[0m\r\n");
- sprintf(str, "COM%d", port + 1);
- if (!unc)
- unc = str;
- #ifdef DEBUG
- stat = DosOpen((PSZ) unc,(PHFILE) &hfComHandle,(PUSHORT) &ActionTaken, 0L, 0, 0x0001, 0x4012, 0L);
- #else
- stat = DosOpen((PSZ) unc,(PHFILE) &hfComHandle,(PUSHORT) &ActionTaken, 0L, 0, 0x0001, 0x6012, 0L);
- #endif
- if (stat) {
- hfComHandle = -1;
- printf("com_init() : DosOpen() error 0x%04x on '%s'\n", stat, unc);
- return (FALSE);
- }
- (void) DosSemClear((HSEM) &WriteSem);
- if (!IOCtl(ASYNC_GETINQUECOUNT, (PVOID) &q, (PVOID) 0L)) {
- s = getenv("RBUF");
- if (s)
- rbufsize = min( RSIZE, atoi(s));
- else
- rbufsize = RSIZE;
- RQBbytes = min( RSIZE, rbufsize);
- RQBbyte2 = RQBbytes/2;
- #ifdef DEBUG
- printf("com_init() : ASYNC Input Buffer size is %d'\n", q.cb);
- #endif
- }
- if (!IOCtl(ASYNC_GETOUTQUECOUNT, (PVOID) &q, (PVOID) 0L)) {
- s = getenv("TBUF");
- if (s)
- tBufsize = min( TSIZE, atoi(s));
- else
- tBufsize = TSIZE;
- /* TQSize = min(TSIZE, q.cb/2); */ /* WRA */
- TQSize = min(TSIZE, q.cb-16);
- #ifdef DEBUG
- printf("com_init() : ASYNC Output Buffer size is %d'\n", q.cb);
- #endif
- }
- com_XON_disable();
-
- com_getDCB((struct _DCBINFO far *) &sDCB);
-
- /* turn off IDSR, ODSR */
- /* sDCB.fbCtlHndShake &= ~(MODE_DSR_HANDSHAKE | MODE_DSR_SENSITIVITY); */
-
- /* raise DTR, CTS output flow control */
- /* sDCB.fbCtlHndShake |= (MODE_DTR_CONTROL | MODE_CTS_HANDSHAKE); */
-
- /* turn off XON/XOFF flow control, error replacement off, null
- * stripping off, break replacement off */
- sDCB.fbFlowReplace &= ~(MODE_AUTO_TRANSMIT | MODE_AUTO_RECEIVE |
- MODE_ERROR_CHAR | MODE_NULL_STRIPPING |
- MODE_BREAK_CHAR);
-
- /* RTS enable */
- /* sDCB.fbFlowReplace |= MODE_RTS_CONTROL; */
-
- /* sDCB.fbTimeout |= (MODE_NO_WRITE_TIMEOUT | MODE_NOWAIT_READ_TIMEOUT); */
- sDCB.fbTimeout |= (MODE_NOWAIT_READ_TIMEOUT);
- sDCB.fbTimeout &= ~(MODE_NO_WRITE_TIMEOUT);
-
- sDCB.usReadTimeout = 1000;
- sDCB.usWriteTimeout = 1000;
- com_setDCB((struct _DCBINFO far *) &sDCB);
-
- return (!stat);
- }
-
- void com_DTR_on(void)
- {
- DCBINFO sDCB;
-
- com_getDCB((struct _DCBINFO far *) &sDCB);
- sDCB.fbCtlHndShake |= MODE_DTR_CONTROL; /* raise DTR */
- com_setDCB((struct _DCBINFO far *) &sDCB);
- }
-
- void com_DTR_off(void)
- {
- DCBINFO sDCB;
-
- com_getDCB((struct _DCBINFO far *) &sDCB);
- sDCB.fbCtlHndShake &= ~MODE_DTR_CONTROL; /* lower DTR */
- com_setDCB((struct _DCBINFO far *) &sDCB);
- }
-
- /* close communications channel. Baud rate is preserved. */
- int com_fini(void)
- {
- int stat;
-
- if (!(hfComHandle == -1)) {
- /* com_wait(); : */
- while ((!com_out_empty()) && com_online())
- DosSleep (1L);
- while ((DosSemWait((HSEM) &WriteSem, 0L)) && (com_online()))
- DosSleep (1L);
- com_clear_in();
- com_clear_out();
- stat = DosClose(hfComHandle);
- if (stat) {
- hfComHandle = -1;
- debug_msg("DosClose() error 0x%04x", stat);
- return (FALSE);
- }
- hfComHandle = -1;
- }
- return(TRUE);
- }
-
- long com_cur_baud(void)
- {
- USHORT rate = 0;
-
- IOCtl(ASYNC_GETBAUDRATE, (PVOID) &rate, (PVOID) 0L);
- return ((long) rate);
- }
-
- /* com_set_baud() :
- *
- * rate = 110..19200
- * parity = N, E, O, M, S (none,even, odd, mark, space)
- * databits = 5..8
- * stopbits = 1..2
- *
- */
- int com_set_baud(unsigned rate, char parity, int databits, int stopbits)
- {
- int stat;
- struct _LINECONTROL {
- BYTE bDataBits;
- BYTE bParity;
- BYTE bStopBits;
- BYTE fbTransBreak;
- } lc;
-
- stat = IOCtl(ASYNC_SETBAUDRATE, (PVOID) 0L, (PVOID) &rate);
- if (stat) {
- return (FALSE);
- }
- lc.bDataBits = (BYTE) databits;
- switch (stopbits) {
- case 1:
- lc.bStopBits = 0;
- break;
- case 2:
- lc.bStopBits = 2;
- break;
- default:
- if (databits == 5)
- lc.bStopBits = 1;
- }
- lc.fbTransBreak = 0;
- switch (toupper(parity)) {
- case 'N':
- lc.bParity = 0;
- break;
- case 'O':
- lc.bParity = 1;
- break;
- case 'E':
- lc.bParity = 2;
- break;
- case 'M':
- lc.bParity = 3;
- break;
- case 'S':
- lc.bParity = 4;
- break;
- default:
- debug_msg("Bad parity '%c'", parity);
- return (FALSE);
- }
- stat = IOCtl(ASYNC_SETLINECTRL, (PVOID) 0L, (PVOID) &lc);
- if (stat) {
- return (FALSE);
- }
- return (TRUE);
- }
-
- static int com_getDCB(struct _DCBINFO far * dcb)
- {
- int stat;
-
- stat = IOCtl(ASYNC_GETDCBINFO, (PVOID) dcb, (PVOID) 0L);
- return (!stat);
- }
-
- static int com_setDCB(struct _DCBINFO far * dcb)
- {
- int stat;
-
- stat = IOCtl(ASYNC_SETDCBINFO, (PVOID) 0L, (PVOID) dcb);
- return (!stat);
- }
-
- void com_XON_disable(void)
- {
- DCBINFO sDCB;
-
- if (com_getDCB((struct _DCBINFO far *) &sDCB)) {
- /* disable auto Xmit and recv flow control */
- sDCB.fbFlowReplace &= ~(MODE_AUTO_TRANSMIT | MODE_AUTO_RECEIVE);
- com_setDCB((struct _DCBINFO far *) &sDCB);
- }
- com_kick();
-
- }
-
- void com_XON_enable(void)
- {
- DCBINFO sDCB;
-
- if (com_getDCB((struct _DCBINFO far *) &sDCB)) {
- /* enable auto Xmit and recv flow control */
- sDCB.fbFlowReplace |= (MODE_AUTO_TRANSMIT | MODE_AUTO_RECEIVE);
- com_setDCB((struct _DCBINFO far *) &sDCB);
- }
- }
-
- /* nuke receive buffer */
- void com_clear_in(void)
- {
- int stat;
- char FlushParm = 0; /* param to flush IOCTL function */
-
- Rbytes = rpos = 0;
- if (hfComHandle == -1)
- return;
- stat = DosDevIOCtl((PVOID) 0L, (PVOID) &FlushParm, DEV_FLUSHINPUT, IOCTL_GENERAL, hfComHandle);
- if (stat) {
- debug_msg("DEV_FLUSHINPUT err 0x%04x", stat);
- }
- }
-
- /* com_getbuf() : return negative value if error */
- int com_getbuf(void)
- {
- int stat = 0;
- RXQUEUE q;
- USHORT Rbytet;
-
- if (rpos == Rbytes) /* If buffer empty, */
- rpos = Rbytes = 0; /* reset pointers */
-
- Rbytet = Rbytes; /* Save old count */
- Rbytes = 0; /* Clear new count */
-
- if (!(IOCtl(ASYNC_GETINQUECOUNT, (PVOID) &q, (PVOID) 0L))) {
- if (q.cch > 0)
- stat = DosRead(hfComHandle, rbuf+Rbytet, (USHORT) min(RQBbytes-Rbytet,q.cch), &Rbytes);
- else
- return (-1);
- } else
- return (-1);
-
- if (stat && !Rbytes && (!(stat==ERROR_MORE_DATA))) {
- debug_msg("DosRead() error 0x%04x", stat);
- return (-1);
- }
-
- Rbytes += Rbytet;
- return (TRUE);
- }
-
- /* com_getchar() : return negative value if error */
- int com_getchar(void)
- {
- if (rpos != Rbytes)
- return ((int) rbuf[rpos++]);
-
- if (com_getbuf() == TRUE)
- return ((int) rbuf[rpos++]);
- return (-1);
- }
-
- /*non destructive read ahead; no wait */
- int com_peek(void)
- {
- int c;
-
- if (!com_char_avail())
- c = -1;
- else {
- c = com_getchar();
- if (c != -1)
- rpos--;
- }
- return (c);
- }
-
- /* if RXQueue over half full, return TRUE */
- bool com_in_check(void)
- {
- RXQUEUE q;
-
- if (IOCtl(ASYNC_GETINQUECOUNT, (PVOID) &q, (PVOID) 0L))
- return (FALSE);
- return ((bool)((q.cch > RQBbyte2) ? TRUE : FALSE));
- }
-
- /* return number of chars in input buffer */
- int com_char_avail(void)
- {
- RXQUEUE q;
-
- if (rpos < Rbytes)
- return (Rbytes-rpos);
-
- return ((!(IOCtl(ASYNC_GETINQUECOUNT, (PVOID) &q, (PVOID) 0L))) ? q.cch : 0 );
- }
-
- /* return non 0 value if carrier detected */
- bool com_online(void)
- {
- BYTE msr;
-
- if (hfComHandle == -1)
- return(FALSE);
-
- if (IOCtl(ASYNC_GETMODEMINPUT, (PVOID) &msr, (PVOID) 0L))
- return(FALSE);
- return((bool) (msr & DCD_ON));
- }
-
- /* com_break() : start break if on==TRUE, stop break if on==FALSE */
- void com_break(int on)
- {
- int cmd;
- USHORT comerr;
-
- cmd = (on) ? ASYNC_SETBREAKON : ASYNC_SETBREAKOFF;
- IOCtl(cmd, (PVOID) &comerr, (PVOID) 0L);
- }
-
- /* com_out_empty() : return TRUE if output buffer is empty */
- bool com_out_empty(void)
- {
- RXQUEUE q;
-
- /* Service Inbound side if necessary */
- if (com_in_check())
- (void) com_getbuf();
-
- if (DosSemWait((HSEM) &WriteSem, 1L) && !com_online ()) /* WRA 6/14/91 */
- return (TRUE);
-
- if (IOCtl(ASYNC_GETOUTQUECOUNT, (PVOID) &q, (PVOID) 0L))
- return (TRUE);
-
- return ((bool) (q.cch == 0));
- }
-
- /* com_out_full() : return TRUE if output buffer is full */
- bool com_out_full(void)
- {
- RXQUEUE q;
-
- if (com_in_check())
- (void) com_getbuf();
-
- if (IOCtl(ASYNC_GETOUTQUECOUNT, (PVOID) &q, (PVOID) 0L))
- return (FALSE);
-
- return ((bool) (q.cch == q.cb));
- }
-
- /* nuke transmit buffer */
- void com_clear_out(void)
- {
- char FlushParm = 0; /* param to flush IOCTL function */
- int stat;
-
- zpos = 0;
-
- DosSemClear((HSEM) &WriteSem);
- if (hfComHandle == -1)
- return;
- stat = DosDevIOCtl((PVOID) 0L, (PVOID) &FlushParm, DEV_FLUSHOUTPUT, IOCTL_GENERAL, hfComHandle);
- if (stat) {
- debug_msg("DEV_FLUSHOUTPUT err 0x%04x", stat);
- }
- com_kick ();
- }
-
- /* com_putc_now() : disregard any buffering and send a byte now damnit! */
- /* this function should be called only during emergencies...like when
- * trying to cancel a file transfer
- */
- /* Since the equivalent is a Com_ call, which in DOS is unsigned... */
- unsigned com_putc_now(byte c)
- {
- return (!IOCtl(ASYNC_TRANSMITIMM, (PVOID) 0L, (PVOID) &c));
- }
-
- /* com_putc() : output to com port */
- /* This function is very slow..where possile, write to com port in blocks
- * using com_write() instead...especially above 2400 bps
- */
- void com_putc(byte c)
- {
- static USHORT bytes;
- int stat;
- RXQUEUE q;
-
- do {
- if (com_in_check())
- (void) com_getbuf();
- } while(com_online () && DosSemWait((HSEM) &WriteSem, 0L));
-
- do {
- if (com_in_check())
- (void) com_getbuf();
- if (IOCtl(ASYNC_GETOUTQUECOUNT, (PVOID) &q, (PVOID) 0L))
- return;
- if (q.cch >= q.cb)
- {
- com_kick ();
- DosSleep (1L);
- }
- } while ((q.cch >= q.cb) && com_online ());
-
- /*
- * DosWriteAsync() didn't work here.
- */
- stat = DosWrite(hfComHandle, &c, 1, &bytes);
- if (stat)
- debug_msg("DosWrite() err 0x%04x", stat);
- }
-
- /* com_write() : buffered block write */
- void com_write(char *buf, unsigned int num, int carcheck)
- {
- static USHORT err, bytes;
- #ifdef MultiWrt
- unsigned int tnum = 0;
- #endif
-
- do {
- if ((carcheck) && !com_online())
- return;
- if (com_in_check())
- (void) com_getbuf();
- } while(DosSemWait((HSEM) &WriteSem, 1L));
-
- (void) DosSemRequest((HSEM) &WriteSem, 0L);
-
- #ifdef MultiWrt
- while (tnum+TQSize > num+TQSize) {
- memcpy (tBuf, &buf[tnum], TQSize);
- DosWriteAsync(hfComHandle, (PULONG) &WriteSem, &err, tBuf, TQSize, &bytes);
- tnum += TQSize;
- do {
- if ((carcheck) && !com_online())
- return;
- if (com_in_check())
- (void) com_getbuf();
- } while(DosSemWait((HSEM) &WriteSem, 1L));
-
- (void) DosSemRequest((HSEM) &WriteSem, 0L);
- }
-
- memcpy (tBuf, &buf[tnum], num-tnum);
- DosWriteAsync(hfComHandle, (PULONG) &WriteSem, &err, tBuf, num-tnum, &bytes);
- #else
-
- memcpy (tBuf, buf, num);
- DosWriteAsync(hfComHandle, (PULONG) &WriteSem, &err, tBuf, num, &bytes);
- #endif
- }
-
- /* wait for output buffer to empty */
- void com_wait(void)
- {
- while ((!com_out_empty()) && com_online())
- DosSleep (1L);
- }
-
- /* force transmitter to go */
- void com_kick(void)
- {
- int stat;
-
- if (hfComHandle == -1)
- return;
- stat = IOCtl(ASYNC_STARTTRANSMIT, (PVOID) 0L, (PVOID) 0L);
- if (stat) {
- debug_msg("ASYNC_STARTTRANSMIT err 0x%04x", stat);
- }
- }
-
- extern unsigned int baud;
- extern unsigned int comm_bits;
- extern unsigned int parity;
- extern unsigned int stop_bits;
- extern struct baud_str btypes[];
-
- void MDM_ENABLE(unsigned rate)
- {
- char _parity;
- int databits;
- int stopbits;
-
- if (hfComHandle == -1)
- return;
- com_clear_out();
- com_clear_in();
- databits = 7 + (comm_bits == BITS_8);
- stopbits = 1 + (stop_bits == STOP_2);
- switch (parity) {
- case NO_PARITY:
- _parity = 'N';
- break;
- case ODD_PARITY:
- _parity = 'O';
- break;
- case EVEN_PARITY:
- _parity = 'E';
- break;
- default:
- _parity = 'N';
- }
- com_set_baud(rate, _parity, databits, stopbits);
- }
-
- void MDM_DISABLE(void)
- {
- if (hfComHandle == -1)
- return;
- com_clear_out();
- com_clear_in();
- com_fini();
- }
-
- /* zsend.c uses BUFFER_BYTE and UNBUFFER_BYTES...good idea. */
- void BUFFER_BYTE(unsigned char ch)
- {
- if (zpos == tBufsize)
- UNBUFFER_BYTES();
- zTxBuf[zpos++] = ch;
- }
-
- void UNBUFFER_BYTES(void)
- {
- if (com_online() && zpos)
- (zpos == 1) ? (com_putc(zTxBuf[0])) : (com_write(zTxBuf,zpos,1)) ;
- zpos = 0;
- }
-
- unsigned Cominit(int port, int failsafe)
- {
- failsafe = failsafe;
-
- if (hfComHandle != -1)
- com_fini();
-
- if (port == 0xff || com_init(port, NULL))
- return (0x1954);
- else
- return (0);
- }
- #endif /* OS_2 */
-