home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <ctype.h>
- #include <conio.h>
- #include <string.h>
- #include <stdlib.h>
- #define INCL_DOS
- #define INCL_DOSDEVICES
- #include <os2.h>
- #include "bink.h"
- #include "com.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 *
- *--------------------------------------------------------*/
-
- #define DEBUG
-
-
- #ifndef OS_2
- #error This Module For OS/2
- #else
-
- static void zap_zbuf(void);
-
- /* Private data */
- static HFILE hfComHandle = -1; /* handle from DosOpen() */
-
- /* transmitter stuff : */
- #define TSIZE 2048
- static ULONG WriteSem = 0;
-
- /* receiver stuff : */
- #define RSIZE 1024
- static unsigned char rbuf[RSIZE];
- static int rpos = 0;
- static USHORT Rbytes = 0;
-
- #ifdef DEBUG
-
- #define debug_msg(m,c) printf(m,c)
- #define IOCtl(func, data, parm) _ioctl(#func, func, data, parm)
-
- static int _ioctl(char *funcname, int func, void far * data, void far * parm)
- {
- int i;
-
- if (i = DosDevIOCtl(data, parm, func, SERIAL, hfComHandle)) {
- printf("ioctl(%s) err(%d)\n", funcname, i);
- }
- return (i);
- }
-
- #else
- #define debug_msg(m,c)
- #define IOCtl(func, data, parm) DosDevIOCtl(data, parm, func, SERIAL, hfComHandle)
- #endif
-
- static int com_getDCB(struct _DCBINFO * dcb);
- static int com_setDCB(struct _DCBINFO * dcb);
- static void com_kick(void);
-
-
- /* 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 *unc)
- {
- char str[10];
- USHORT ActionTaken; /* action: returned by OS/2 */
- USHORT stat;
- DCBINFO sDCB;
-
- cputs("\033[1;33mOS/2 Fossill emulator for Binkley Term by Peter Fitzsimmons 1:250/628\033[0m\r\n");
- sprintf(str, "COM%d", port + 1);
- if (!unc)
- unc = str;
- stat = DosOpen(unc, &hfComHandle, &ActionTaken, 0L, 0, 0x0001, 0x4012, 0L);
- if (stat) {
- hfComHandle = -1;
- printf("com_init() : DosOpen() error %d on '%s'\n", stat, unc);
- return (FALSE);
- }
- DosSemClear(&WriteSem);
- com_XON_disable();
-
-
- com_getDCB(&sDCB);
- sDCB.bFlags1 = 0x01; /* raise DTR */
- sDCB.bFlags2 = 0x40; /* enable RTS, flow control off,
- * error replacement off, null
- * stripping off, break replacement
- * off */
- sDCB.bFlags3 = 0x07; /* set write timeout strategies to
- * INFINITE, read timeout to NO
- * WAIT */
- sDCB.usReadTimeout = 100;
- sDCB.usWriteTimeout = 10;
- com_setDCB(&sDCB);
-
- return (!stat);
- }
-
- void com_DTR_on(void)
- {
- DCBINFO sDCB;
-
- com_getDCB(&sDCB);
- sDCB.bFlags1 |= 0x01; /* raise DTR */
- com_setDCB(&sDCB);
- }
-
- void com_DTR_off(void)
- {
- DCBINFO sDCB;
-
- com_getDCB(&sDCB);
- sDCB.bFlags1 &= ~0x01; /* lower DTR */
- com_setDCB(&sDCB);
- }
-
- /* close communications channel. Baud rate is preserved. */
- int com_fini(void)
- {
- int stat;
-
- com_wait();
- com_clear_in();
- com_clear_out();
- if (stat = DosClose(hfComHandle)) {
- hfComHandle = -1;
- debug_msg("DosClose error %d\n", stat);
- return (FALSE);
- }
- hfComHandle = -1;
- }
-
-
- long com_cur_baud(void)
- {
- USHORT rate = 0;
-
- IOCtl(ASYNC_GETBAUDRATE, &rate, 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(long rate, char parity, int databits, int stopbits)
- {
- int stat;
- struct _LINECONTROL {
- BYTE bDataBits;
- BYTE bParity;
- BYTE bStopBits;
- BYTE fbTransBreak;
- } lc;
-
- stat = IOCtl(ASYNC_SETBAUDRATE, 0L, &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'\n", parity);
- return (FALSE);
- }
- stat = IOCtl(ASYNC_SETLINECTRL, 0L, &lc);
- if (stat) {
- return (FALSE);
- }
- return (TRUE);
- }
-
-
-
- static int com_getDCB(DCBINFO * dcb)
- {
- int stat;
-
- stat = IOCtl(ASYNC_GETDCBINFO, dcb, 0L);
- return (!stat);
- }
-
- static int com_setDCB(DCBINFO * dcb)
- {
- int stat;
-
- stat = IOCtl(ASYNC_SETDCBINFO, 0L, dcb);
- return (!stat);
- }
-
- void com_XON_disable(void)
- {
- DCBINFO sDCB;
-
- if (com_getDCB(&sDCB)) {
- sDCB.bFlags2 &= ~0x03; /* disable auto Xmit and recv flow
- * control */
- com_setDCB(&sDCB);
- }
- }
-
- void com_XON_enable(void)
- {
- DCBINFO sDCB;
-
- if (com_getDCB(&sDCB)) {
- sDCB.bFlags2 |= 0x03; /* enable auto Xmit and recv flow
- * control */
- com_setDCB(&sDCB);
- }
- }
-
-
-
- /* nuke receive buffer */
- void com_clear_in(void)
- {
- int stat;
- char FlushParm = 0; /* param to flush IOCTL function */
-
- Rbytes = rpos = 0;
- stat = DosDevIOCtl(0L, &FlushParm, FLUSHINPUT, GENERIC, hfComHandle);
- if (stat) {
- debug_msg("FLUSHINPUT err %d\n", stat);
- }
- }
-
-
- /* com_getchar() : return negative value if error */
- int com_getchar(void)
- {
- int stat;
-
- if (rpos == Rbytes) {
- rpos = 0;
- do {
- stat = DosRead(hfComHandle, rbuf, RSIZE, &Rbytes);
- } while (!stat && !Rbytes);
- if (stat || !Rbytes) {
- debug_msg("DosRead() error %d\n", stat);
- return (-1);
- }
- }
- return ((int) rbuf[rpos++]);
- }
-
- /*non destructive read ahead; no wait */
- int com_peek(void)
- {
- int c;
-
- if (!com_char_avail())
- c = -1;
- else {
- c = com_getchar();
- rpos--;
- }
- return (c);
- }
-
- /* return number of chars in input buffer */
- int com_char_avail(void)
- {
- RXQUEUE q;
-
- if (rpos != Rbytes)
- return (TRUE);
- if (!IOCtl(ASYNC_GETINQUECOUNT, &q, 0L))
- return ((int) q.cbChars);
- else
- return (FALSE);
- }
-
-
- /* return non 0 value if carrier detected */
- bool com_online(void)
- {
- int stat;
- BYTE msr;
-
- stat = IOCtl(ASYNC_GETMODEMINPUT, &msr, 0L);
- if (stat) {
- return (FALSE);
- }
- return (msr & RLSD);
- }
-
-
- /* 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, &comerr, 0L);
- }
-
- /* com_out_empty() : return TRUE if output buffer is empty */
- bool com_out_empty(void)
- {
- int stat;
- RXQUEUE q;
-
- if (!DosSemWait(&WriteSem, 0L)) {
- stat = IOCtl(ASYNC_GETOUTQUECOUNT, &q, 0L);
- if (stat)
- return (TRUE); // don't want someone waiting to get stuck if general error
- return ((bool) (q.cbChars == 0));
- }
- else {
- return (FALSE);
- }
- }
-
-
- /* nuke transmit buffer */
- void com_clear_out(void)
- {
- char FlushParm = 0; /* param to flush IOCTL function */
- int stat;
-
- zap_zbuf();
- stat = DosDevIOCtl(0L, &FlushParm, FLUSHOUTPUT, GENERIC, hfComHandle);
- if (stat) {
- debug_msg("FLUSHOUTPUT err %d\n", stat);
- }
- DosSemClear(&WriteSem);
- }
-
- /* 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
- */
- int com_putc_now(int c)
- {
- return (!IOCtl(ASYNC_TRANSMITIMM, 0L, &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(int c)
- {
- static USHORT bytes;
- int stat;
-
- DosSemWait(&WriteSem, -1L);
-
- /*
- * DosWriteAsync() didn't work here. After being idle for a while,
- * calling this function repeatedly to send a string (like "ATZ") would
- * somehow loose the first character. I have speant hours trying to
- * debug this, and Microsoft was no help. Basically, os/2's handling of
- * output buffering sucks for the com ports. I give up...(for now).
- * NOTE that this appeared to only happen when writting one byte; that
- * is why com_write() still uses DosWriteAsync().
- */
- if (stat = DosWrite(hfComHandle, &c, 1, &bytes))
- debug_msg("DosWrite() err %d\n", stat);
- }
-
- /* com_write() : buffered block write */
- void com_write(char *buf, int num)
- {
- static USHORT err, bytes;
- static char tbuf[TSIZE];
- int stat, pos = 0;
-
- DosSemRequest(&WriteSem, -1L); /* if sem set, wait. If clear, set. */
- while (num - pos > TSIZE) {
- if (stat = DosWrite(hfComHandle, buf + pos, TSIZE, &bytes))
- debug_msg("DosWrite() err %d\n", stat);
- pos += bytes;
- }
- memcpy(tbuf, buf + pos, num - pos);
- DosWriteAsync(hfComHandle, &WriteSem, &err, tbuf, num - pos, &bytes);
- }
-
- /* wait for output buffer to empty */
- void com_wait(void)
- {
- DosSemWait(&WriteSem, -1L);
- while (!com_out_empty())
- DosSleep(0L);
- }
-
- #ifdef BINKLEY
- /* Binkley specifics : */
-
- 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(int ignore)
- {
- long rate;
- char _parity;
- int databits;
- int stopbits;
-
- ignore; /* keep /W3 happy */
- com_clear_out();
- com_clear_in();
- rate = atol(btypes[baud].str);
- 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;
- }
- 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. */
- static unsigned char zTxBuf[TSIZE];
- static int zpos = 0;
- void BUFFER_BYTE(unsigned char ch)
- {
- if( zpos == TSIZE )
- UNBUFFER_BYTES();
- zTxBuf[zpos++] = ch;
- }
-
- void UNBUFFER_BYTES(void)
- {
- com_write(zTxBuf, zpos);
- zpos = 0;
- }
-
- static void zap_zbuf(void)
- {
- zpos = 0;
- }
-
- int Cominit(int port)
- {
- if (hfComHandle != -1)
- com_fini();
- if (com_init(port, NULL))
- return (0x1954);
- else
- return (0);
- }
- #endif /* BINKLEY */
- #endif /* OS_2 */