home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / MODEM / UWPC201.ZIP / UW-SRC.ZIP / COMMS.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-31  |  20.4 KB  |  707 lines

  1. /*-----------------------------------------------------------------------------
  2.  
  3.    COMMS.C - Serial Communications Routines for Turbo C/C++
  4.  
  5.     NOTE: COM1 and COM3 cannot be used simultaneously and COM2 and COM4
  6.     cannot be used simultaneously.
  7.  
  8.     This file is part of UW/PC - a multi-window comms package for the PC.
  9.     Copyright (C) 1990-1991  Rhys Weatherley
  10.  
  11.     This program is free software; you can redistribute it and/or modify
  12.     it under the terms of the GNU General Public License as published by
  13.     the Free Software Foundation; either version 1, or (at your option)
  14.     any later version.
  15.  
  16.     This program is distributed in the hope that it will be useful,
  17.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.     GNU General Public License for more details.
  20.  
  21.     You should have received a copy of the GNU General Public License
  22.     along with this program; if not, write to the Free Software
  23.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  
  25.    Revision History:
  26.    ================
  27.  
  28.     Version  DD/MM/YY  By  Description
  29.     -------  --------  --  ---------------------------------------------------
  30.       1.0    ??/09/90  RW  Original version of COMMS.C
  31.       1.1    10/11/90  RW  Added ability to call comcarrier before comenable,
  32.                      support for 57600 baud and automatic raising of
  33.                the DTR signal.
  34.       1.2    17/11/90  RW  Add 'leavedtr' parameter to "comrestore".
  35.       1.3    17/03/91  RW  Create 'comfix' to fix DOS shell-out bug.
  36.       1.4    21/03/91  RW  Fix minor problem with sign extension in comreceive.
  37.       1.5    22/03/91  RW  Fix COM port addressing & add COM3/COM4 support.
  38.       1.6    31/10/91  RW  Add some more stuff for Windows 3.0 support.
  39.  
  40.    Authors:
  41.    =======
  42.  
  43.     RW - Rhys Weatherley (e-mail: rhys@cs.uq.oz.au)
  44.          5 Horizon Drive
  45.      Jamboree Heights  QLD  4074
  46.      Australia
  47.  
  48. -----------------------------------------------------------------------------*/
  49.  
  50. #pragma    inline            /* There is inline assembly in this file */
  51.  
  52. #include "comms.h"        /* Declarations for this module */
  53. #include <dos.h>
  54.  
  55. /* Various PIC/COM masks and values */
  56.  
  57. #define PIC_MASK 0x21
  58. #define    PIC_EOI  0x20
  59. #define ERR_MSK     0x9E
  60.  
  61. /* Definitions for interrupt handling */
  62.  
  63. /* COM port offsets */
  64.  
  65. #define COM_DATA     0    /* Data received on this I/O address */
  66. #define COM_IER       1    /* This register enables interrupts */
  67. #define    COM_LCR         3    /* Line control register */
  68. #define COM_MCR         4    /* Control Register (signals) */
  69. #define COM_STAT     5    /* Status Register */
  70. #define    COM_MSR         6    /* Modem Status Register */
  71.  
  72. /* Data for installing COM port interrupts */
  73.  
  74. #define COM_INT_1   0x0C    /* Interrupt 0x0C handles IRQ4 (or COM1) */
  75. #define INT_MASK_1  0x10    /* Mask for PIC (programmable interrupt
  76.                    controller) 8259A */
  77. #define COM_INT_2   0x0B    /* Interrupt 0x0B handles IRQ3 (or COM2) */
  78. #define INT_MASK_2  0x08    /* Mask for PIC (programmable interrupt
  79.                    controller) 8259A */
  80.  
  81. /* Define the port addresses for the 4 serial ports. */
  82. /* These can be changed by the caller if necessary.  */
  83. int    _Cdecl    comports[4] = {0x3F8,0x2F8,0x3E8,0x2E8};
  84.  
  85. /* Define the interrupt buffer structure */
  86.  
  87. #define    MAX_INT_BUFSIZ    4096
  88. struct    IntBuf    {
  89.           char    buffer[MAX_INT_BUFSIZ];
  90.           int    input,output,size;
  91.           int    statport,dataport;
  92.           int    testbit;
  93.           int    oldier,oldmcr,oldlcr,oldbaud;
  94.           int    checkloss;
  95.         };
  96.  
  97. static    struct    IntBuf    Com1Buf,Com2Buf;
  98.  
  99. /* Define the data for the interrupt handlers */
  100.  
  101. static void interrupt int_com1();
  102. static void interrupt int_com2();
  103. static void interrupt (*old_c1)();
  104. static void interrupt (*old_c2)();
  105.  
  106. /* Change the test loop-back properties of a COM port (given MCR reg) */
  107. static    int    _Cdecl    changetest (mcrport,on)
  108. int    mcrport,on;
  109. {
  110.   if (on)
  111.     {
  112.       outportb (mcrport, inportb (mcrport) | 0x10);
  113.       return (0x10);
  114.     }
  115.    else
  116.     {
  117.       outportb (mcrport, inportb (mcrport) & 0x0F);
  118.       return (0);
  119.     }
  120. }
  121.  
  122. /* Turn a COM port's test loop-back mode on or off */
  123. /* NOTE: comenable always turns the loop-mode off  */
  124. void    _Cdecl    comtest (port,on)
  125. int    port,on;
  126. {
  127.   switch (port)
  128.     {
  129.       case 1: case 3:
  130.               Com1Buf.testbit = changetest (Com1Buf.dataport + COM_MCR,on);
  131.             break;
  132.       case 2: case 4:
  133.               Com2Buf.testbit = changetest (Com2Buf.dataport + COM_MCR,on);
  134.             break;
  135.       default:    break;
  136.     }
  137. }
  138.  
  139. /* Return the number of available input chars on a COM port */
  140. /* Will raise the DTR signal if it is not already raised.   */
  141. int    _Cdecl    comavail (port)
  142. int    port;
  143. {
  144.   switch (port)
  145.     {
  146.       case 1: case 3:
  147.               outportb (Com1Buf.dataport + COM_MCR,0x0B |
  148.               Com1Buf.testbit);    /* Raise DTR */
  149.         return (Com1Buf.size);
  150.       case 2: case 4:
  151.               outportb (Com2Buf.dataport + COM_MCR,0x0B |
  152.               Com2Buf.testbit);    /* Raise DTR */
  153.         return (Com2Buf.size);
  154.       default:    return 0;
  155.     }
  156. }
  157.  
  158. /* Flush all input from the COM port */
  159. void    _Cdecl    comflush (port)
  160. int    port;
  161. {
  162.   switch (port)
  163.     {
  164.       case 1: case 3:
  165.               disable ();    /* Disallow ints while flushing */
  166.         Com1Buf.size = 0;
  167.         Com1Buf.output = Com1Buf.input;
  168.         enable ();
  169.         break;
  170.       case 2: case 4:
  171.               disable ();    /* Disallow ints while flushing */
  172.         Com2Buf.size = 0;
  173.         Com2Buf.output = Com2Buf.input;
  174.         enable ();
  175.         break;
  176.       default:    break;
  177.     }
  178. } /* comflush */
  179.  
  180. /* Receive a character from the COM port: -1 if not ready */
  181. /* Will raise the DTR signal if it is not already raised. */
  182. int    _Cdecl    comreceive(port)
  183. int    port;
  184. {
  185.   int ch;
  186.   switch (port)
  187.     {
  188.       case 1: case 3:
  189.               outportb (Com1Buf.dataport + COM_MCR,0x0B |
  190.                 Com1Buf.testbit);    /* Raise DTR */
  191.         if (Com1Buf.size == 0) return -1;
  192.         else {
  193.             ch = Com1Buf.buffer[Com1Buf.output];
  194.             Com1Buf.output = (Com1Buf.output + 1) %
  195.                 MAX_INT_BUFSIZ;
  196.             --Com1Buf.size;
  197.             return (ch & 255);
  198.         }
  199.       case 2: case 4:
  200.               outportb (Com2Buf.dataport + COM_MCR,0x0B |
  201.                 Com2Buf.testbit);    /* Raise DTR */
  202.         if (Com2Buf.size == 0) return -1;
  203.         else {
  204.             ch = Com2Buf.buffer[Com2Buf.output];
  205.             Com2Buf.output = (Com2Buf.output + 1) %
  206.                 MAX_INT_BUFSIZ;
  207.             --Com2Buf.size;
  208.             return (ch & 255);
  209.         }
  210.       default:    return (-1);
  211.     }
  212. }
  213.  
  214. /*  COM1 Interrupt handler.  HARDWARE DEPENDENT */
  215.  
  216. static void interrupt int_com1()
  217. {
  218.   asm cli;            /* Make sure ints are disabled */
  219.   asm mov dx,Com1Buf.statport;    /* Check for errors */
  220.   asm in al,dx;
  221.   asm and al,ERR_MSK;
  222.   asm jnz error;
  223.   asm mov dx,Com1Buf.dataport;    /* Get the received character */
  224.   asm in al,dx;
  225.   asm mov cx,Com1Buf.size;    /* Prepare to store the character */
  226.   asm cmp cx,MAX_INT_BUFSIZ;
  227.   asm jae done;
  228.   asm mov bx,Com1Buf.input;
  229.   asm mov byte ptr Com1Buf.buffer[bx],al;/* Store character in buffer */
  230.   asm inc bx;            /* And advance buffer pointer */
  231.   asm and bx,(MAX_INT_BUFSIZ - 1);
  232.   asm mov Com1Buf.input,bx;
  233.   asm inc Com1Buf.size;
  234.   asm jmp done;
  235.  error:
  236.   asm mov dx,Com1Buf.dataport;    /* Remove the erroneous character */
  237.   asm in al,dx;
  238.  done:
  239.   asm mov al,0x20;        /* Tell PIC we have handled the int */
  240.   asm out PIC_EOI,al;
  241.   asm mov dx,Com1Buf.dataport;    /* Create an interrupt edge */
  242.   asm add dx,COM_IER;
  243.   asm in al,dx;
  244.   asm mov ah,al;
  245.   asm mov al,0;
  246.   asm out dx,al;
  247.   asm mov al,ah;
  248.   asm out dx,al;
  249. }
  250.  
  251. /*  COM2 Interrupt handler.  HARDWARE DEPENDENT */
  252.  
  253. static void interrupt int_com2()
  254. {
  255.   asm cli;            /* Make sure ints are disabled */
  256.   asm mov dx,Com2Buf.statport;    /* Check for errors */
  257.   asm in al,dx;
  258.   asm and al,ERR_MSK;
  259.   asm jnz error;
  260.   asm mov dx,Com2Buf.dataport;    /* Get the received character */
  261.   asm in al,dx;
  262.   asm mov cx,Com2Buf.size;    /* Prepare to store the character */
  263.   asm cmp cx,MAX_INT_BUFSIZ;
  264.   asm jae done;
  265.   asm mov bx,Com2Buf.input;
  266.   asm mov byte ptr Com2Buf.buffer[bx],al;/* Store character in buffer */
  267.   asm inc bx;            /* And advance buffer pointer */
  268.   asm and bx,(MAX_INT_BUFSIZ - 1);
  269.   asm mov Com2Buf.input,bx;
  270.   asm inc Com2Buf.size;
  271.   asm jmp done;
  272.  error:
  273.   asm mov dx,Com2Buf.dataport;    /* Remove the erroneous character */
  274.   asm in al,dx;
  275.  done:
  276.   asm mov al,0x20;        /* Tell PIC we have handled the int */
  277.   asm out PIC_EOI,al;
  278.   asm mov dx,Com2Buf.dataport;    /* Create an interrupt edge */
  279.   asm add dx,COM_IER;
  280.   asm in al,dx;
  281.   asm mov ah,al;
  282.   asm mov al,0;
  283.   asm out dx,al;
  284.   asm mov al,ah;
  285.   asm out dx,al;
  286. }
  287.  
  288. /* Enable a COM port given its I/O port address */
  289. static    void    _Cdecl    doenable (port)
  290. int    port;
  291. {
  292.   /* Set DLAB bit to zero to ensure that we */
  293.   /* access the correct COM port registers  */
  294.   outportb(port + COM_LCR,inportb(port + COM_LCR) & 0x7F);
  295.  
  296.   /* Turn off the chip's interrupts to start with */
  297.   outportb(port + COM_IER,0);
  298.   outportb(port + COM_MCR,8); /* Just DTR up for now */
  299.  
  300.   /* Read status and data ports to clear any outstanding errors */
  301.   inportb(port + COM_STAT);
  302.   inportb(port);
  303.  
  304.   /* Set ints for data available */
  305.   outportb(port + COM_IER,1);
  306. }
  307.  
  308. /* Enable a COM port for Interrupt Driven I/O by this module */
  309. int    _Cdecl    comenable(port)
  310. int    port;
  311. {
  312.   char ch;
  313.   int dataport;
  314.   switch (port)
  315.     {
  316.       case 1: case 3:
  317.               /* Initialise buffers for COM1 */
  318.         Com1Buf.input = 0;
  319.         Com1Buf.output = 0;
  320.         Com1Buf.size = 0;
  321.         dataport = comports[port - 1];
  322.         Com1Buf.dataport = dataport;
  323.         Com1Buf.statport = Com1Buf.dataport + COM_STAT;
  324.         Com1Buf.testbit = 0;
  325.         Com1Buf.checkloss = 0;    /* Don't check for carrier loss */
  326.  
  327.         doenable (dataport);    /* Setup the regs */
  328.  
  329.         /* Setup the ISR details */
  330.         old_c1 = getvect(COM_INT_1); /* Save old COM1 int */
  331.         setvect(COM_INT_1,int_com1); /* Install new int */
  332.  
  333.         /* Now turn on DTR, RTS and OUT2: all ready */
  334.         outportb(dataport + COM_MCR,0x0B);
  335.  
  336.         /* Program the PIC to handle COM1 interrupts */
  337.         ch = inportb(PIC_MASK);    /* Read current mask */
  338.         ch &= (0xFF^INT_MASK_1);/* Reset mask for COM1 */
  339.         outportb(PIC_MASK,ch);    /* Send it to the 8259A */
  340.         break;
  341.       case 2: case 4:
  342.               /* Initialise buffers for COM2 */
  343.         Com2Buf.input = 0;
  344.         Com2Buf.output = 0;
  345.         Com2Buf.size = 0;
  346.         dataport = comports[port - 1];
  347.         Com2Buf.dataport = dataport;
  348.         Com2Buf.statport = Com2Buf.dataport + COM_STAT;
  349.         Com2Buf.testbit = 0;
  350.         Com1Buf.checkloss = 0;    /* Don't check for carrier loss */
  351.  
  352.         doenable (dataport);    /* Setup the regs */
  353.  
  354.         /* Setup the ISR details */
  355.         old_c2 = getvect(COM_INT_2); /* Save old COM2 int */
  356.         setvect(COM_INT_2,int_com2); /* Install new int */
  357.  
  358.         /* Now turn on DTR, RTS and OUT2: all ready */
  359.         outportb(dataport + COM_MCR,0x0B);
  360.  
  361.         /* Program the PIC to handle COM2 interrupts */
  362.         ch = inportb(PIC_MASK);    /* Read current mask */
  363.         ch &= (0xFF^INT_MASK_2);/* Reset mask for COM2 */
  364.         outportb(PIC_MASK,ch);    /* Send it to the 8259A */
  365.         break;
  366.       default:    return (0);
  367.     }
  368.   return (1);
  369. }
  370.  
  371. /* Save the current setting of a COM port to be restored later */
  372. /* Call this function before calling 'comenable' on the port.  */
  373. void    _Cdecl    comsave (port)
  374. int    port;
  375. {
  376.   int dataport;
  377.   switch (port)
  378.     {
  379.       case 1: case 3:
  380.               dataport = comports[port - 1];
  381.         Com1Buf.oldlcr = inportb (dataport + COM_LCR);
  382.         Com1Buf.oldmcr = inportb (dataport + COM_MCR);
  383.         outportb (dataport + COM_LCR,Com1Buf.oldlcr & 0x7F);
  384.         Com1Buf.oldier = inportb (dataport + COM_IER);
  385.         outportb (dataport + COM_LCR,Com1Buf.oldlcr | 0x80);
  386.         Com1Buf.oldbaud = inport (dataport);
  387.         outportb (dataport + COM_LCR,Com1Buf.oldlcr);
  388.               break;
  389.       case 2: case 4:
  390.               dataport = comports[port - 1];
  391.         Com2Buf.oldlcr = inportb (dataport + COM_LCR);
  392.         Com2Buf.oldmcr = inportb (dataport + COM_MCR);
  393.         outportb (dataport + COM_LCR,Com2Buf.oldlcr & 0x7F);
  394.         Com2Buf.oldier = inportb (dataport + COM_IER);
  395.         outportb (dataport + COM_LCR,Com2Buf.oldlcr | 0x80);
  396.         Com2Buf.oldbaud = inport (dataport);
  397.         outportb (dataport + COM_LCR,Com2Buf.oldlcr);
  398.               break;
  399.       default:    break;
  400.     }
  401. }
  402.  
  403. /* Set the communications parameters for a COM port */
  404. void    _Cdecl    comparams (port,params)
  405. int    port,params;
  406. {
  407.   static int divisors[12] =        /* COM port baud rate divisors */
  408.        {0x0417,0x0300,0x0180,0x00E0,0x0060,
  409.         0x0030,0x0018,0x000C,0x0006,0x0003,
  410.         0x0002,0x0001};
  411.   int value,dataport;
  412.   switch (port)
  413.     {
  414.       case 1: case 3:
  415.               dataport = Com1Buf.dataport; break;
  416.       case 2: case 4:
  417.               dataport = Com2Buf.dataport; break;
  418.       default: return;
  419.     }
  420.   if (params & BITS_8)
  421.     value = 0x03;
  422.    else
  423.     value = 0x02;
  424.   if (params & STOP_2)
  425.     value |= 0x04;
  426.   if (params & PARITY_ODD)
  427.     value |= 0x08;
  428.    else if (params & PARITY_EVEN)
  429.     value |= 0x18;
  430.   outportb (dataport + COM_LCR,value | 0x80);    /* Set params and DLAB */
  431.   outport  (dataport,divisors[params & BAUD_RATE]); /* Set the baud rate */
  432.   outportb (dataport + COM_LCR,value);        /* Clear DLAB bit */
  433. }
  434.  
  435. /* Disable the interrupt I/O for a COM port */
  436. /* If 'leavedtr' != 0, then leave DTR up    */
  437. void    _Cdecl    comdisable(port,leavedtr)
  438. int    port,leavedtr;
  439. {
  440.   char ch;
  441.   switch (port)
  442.     {
  443.       case 1: case 3:
  444.               ch = inportb(PIC_MASK);    /* Get 8259A (PIC) Mask */
  445.         ch |= INT_MASK_1;    /* Set Interrupt Mask COM1 */
  446.         outportb(PIC_MASK,ch);    /* Write int. mask to 8259A*/
  447.  
  448.         /* Clear the interrupt enable register */
  449.         outportb(Com1Buf.dataport + COM_IER,0);
  450.  
  451.         /* Clear OUT2, and set DTR as required */
  452.         if (leavedtr)
  453.           outportb(Com1Buf.dataport + COM_MCR,1);
  454.          else
  455.           outportb(Com1Buf.dataport + COM_MCR,0);
  456.  
  457.         setvect(COM_INT_1,old_c1);/* Restore COM1 int */
  458.         break;
  459.       case 2: case 4:
  460.               ch = inportb(PIC_MASK);    /* Get 8259A (PIC) Mask */
  461.         ch |= INT_MASK_2;    /* Set Interrupt Mask COM1 */
  462.         outportb(PIC_MASK,ch);    /* Write int. mask to 8259A*/
  463.  
  464.         /* Clear the interrupt enable register */
  465.         outportb(Com2Buf.dataport + COM_IER,0);
  466.  
  467.         /* Clear OUT2, and set DTR as required */
  468.         if (leavedtr)
  469.           outportb(Com2Buf.dataport + COM_MCR,1);
  470.          else
  471.           outportb(Com2Buf.dataport + COM_MCR,0);
  472.  
  473.         setvect(COM_INT_2,old_c2);/* Restore COM2 int */
  474.         break;
  475.       default:    break;
  476.     }
  477. }
  478.  
  479. /* Restore the setting of a COM port - after 'comdisable'     */
  480. /* If 'leavedtr' is non-zero then leave DTR up no matter what */
  481. void    _Cdecl    comrestore (port,leavedtr)
  482. int    port,leavedtr;
  483. {
  484.   int dataport;
  485.   switch (port)
  486.     {
  487.       case 1: case 3:
  488.               dataport = comports[port - 1];
  489.         outportb (dataport + COM_LCR,Com1Buf.oldlcr & 0x7F);
  490.         outportb (dataport + COM_IER,Com1Buf.oldier);
  491.         outportb (dataport + COM_LCR,Com1Buf.oldlcr | 0x80);
  492.         outport (dataport,Com1Buf.oldbaud);
  493.         outportb (dataport + COM_LCR,Com1Buf.oldlcr);
  494.         if (leavedtr)
  495.           Com1Buf.oldmcr |= 0x01;    /* Leave DTR in a high state */
  496.         outportb (dataport + COM_MCR,Com1Buf.oldmcr);
  497.               break;
  498.       case 2: case 4:
  499.               dataport = comports[port - 1];
  500.         outportb (dataport + COM_LCR,Com2Buf.oldlcr & 0x7F);
  501.         outportb (dataport + COM_IER,Com2Buf.oldier);
  502.         outportb (dataport + COM_LCR,Com2Buf.oldlcr | 0x80);
  503.         outport (dataport,Com2Buf.oldbaud);
  504.         outportb (dataport + COM_LCR,Com2Buf.oldlcr);
  505.         if (leavedtr)
  506.           Com2Buf.oldmcr |= 0x01;    /* Leave DTR in a high state */
  507.         outportb (dataport + COM_MCR,Com2Buf.oldmcr);
  508.               break;
  509.       default:    break;
  510.     }
  511. }
  512.  
  513. /* Output a character to an I/O port */
  514. static    void    _Cdecl    dosend(dataport,statport,ch)
  515. int    dataport,statport,ch;
  516. {
  517.   while (!(inportb(statport) & 0x20))
  518.     ;    /* wait till port is available */
  519.   outportb(dataport,ch);
  520. }
  521.  
  522. /* Output a character to a COM port.  Will raise */
  523. /* the DTR signal if it is not already raised.   */
  524. void    _Cdecl    comsend(port,ch)
  525. int    port;
  526. unsigned char ch;
  527. {
  528.   switch (port)
  529.     {
  530.       case 1: case 3:
  531.               outportb (Com1Buf.dataport + COM_MCR,0x0B |
  532.                 Com1Buf.testbit);    /* Raise DTR */
  533.         dosend (Com1Buf.dataport,Com1Buf.statport,ch);
  534.         break;
  535.       case 2: case 4:
  536.               outportb (Com2Buf.dataport + COM_MCR,0x0B |
  537.                 Com2Buf.testbit);    /* Raise DTR */
  538.         dosend (Com2Buf.dataport,Com2Buf.statport,ch);
  539.         break;
  540.       default:    break;
  541.     }
  542. }
  543.  
  544. /* Test to see if a carrier is present - can be called before comenable */
  545. int    _Cdecl    comcarrier (port)
  546. int    port;
  547. {
  548.   int dataport;
  549.   switch (port)
  550.     {
  551.       case 1: case 3:
  552.                 dataport = comports[port - 1];    /* Get dataport address */
  553.                 return ((inportb (dataport + COM_MSR) & 0x80) != 0);
  554.       case 2: case 4:
  555.               dataport = comports[port - 1];    /* Get dataport address */
  556.                 return ((inportb (dataport + COM_MSR) & 0x80) != 0);
  557.       default: return 0;
  558.     }
  559. }
  560.  
  561. /* Enable or disable the detection of carrier loss */
  562. void    _Cdecl    comloss    (port,enable)
  563. int    port,enable;
  564. {
  565.   switch (port)
  566.     {
  567.       case 1: case 3:
  568.               Com1Buf.checkloss = enable;
  569.         break;
  570.       case 2: case 4:
  571.               Com2Buf.checkloss = enable;
  572.         break;
  573.       default:    break;
  574.     } /* switch */
  575. } /* comloss */
  576.  
  577. /* Test if the last transmitted character could not be sent because */
  578. /* the carrier has been lost.  This is mainly for Windows 3.0       */
  579. int    _Cdecl    comlost (port)
  580. int    port;
  581. {
  582.   switch (port)
  583.     {
  584.       case 1: case 3:
  585.               if (Com1Buf.checkloss && !comcarrier (port))
  586.           return (1);        /* Carrier has been lost */
  587.         break;
  588.       case 2: case 4:
  589.               if (Com2Buf.checkloss && !comcarrier (port))
  590.           return (1);        /* Carrier has been lost */
  591.         break;
  592.       default:    break;
  593.     } /* switch */
  594.   return (0);                /* Carrier is assumed still present */
  595. } /* comlost */
  596.  
  597. /* Test to see if the DSR (Data Set Ready) signal is present */
  598. int    _Cdecl    comdsr (port)
  599. int    port;
  600. {
  601.   switch (port)
  602.     {
  603.       case 1: case 3:
  604.               return ((inportb (Com1Buf.dataport + COM_MSR) & 0x20) != 0);
  605.       case 2: case 4:
  606.               return ((inportb (Com2Buf.dataport + COM_MSR) & 0x20) != 0);
  607.       default: return 0;
  608.     }
  609. }
  610.  
  611. /* Test to see if the COM port is ready for a new */
  612. /* character to transmit.  Will raise the DTR     */
  613. /* signal if it is not already raised.          */
  614. int    _Cdecl    comready (port)
  615. int    port;
  616. {
  617.   switch (port)
  618.     {
  619.       case 1: case 3:
  620.                 outportb (Com1Buf.dataport + COM_MCR,0x0B |
  621.                       Com1Buf.testbit);    /* Raise DTR */
  622.                 return ((inportb (Com1Buf.statport) & 0x20) != 0);
  623.       case 2: case 4:
  624.                 outportb (Com2Buf.dataport + COM_MCR,0x0B |
  625.                       Com2Buf.testbit);    /* Raise DTR */
  626.               return ((inportb (Com2Buf.statport) & 0x20) != 0);
  627.       default: return 0;
  628.     }
  629. }
  630.  
  631. /* Drop the DTR signal on a COM port */
  632. void    _Cdecl    comdropdtr (port)
  633. int    port;
  634. {
  635.   switch (port)
  636.     {
  637.       case 1: case 3:
  638.               outportb (Com1Buf.dataport + COM_MCR,0x0A |
  639.                 Com1Buf.testbit); break;
  640.       case 2: case 4:
  641.               outportb (Com2Buf.dataport + COM_MCR,0x0A |
  642.                 Com2Buf.testbit); break;
  643.     }
  644. }
  645.  
  646. /* Raise the DTR signal on a COM port */
  647. void    _Cdecl    comraisedtr (port)
  648. int    port;
  649. {
  650.   switch (port)
  651.     {
  652.       case 1: case 3:
  653.               outportb (Com1Buf.dataport + COM_MCR,0x0B |
  654.                 Com1Buf.testbit); break;
  655.       case 2: case 4:
  656.               outportb (Com2Buf.dataport + COM_MCR,0x0B |
  657.                 Com2Buf.testbit); break;
  658.       default: break;
  659.     }
  660. }
  661.  
  662. /* Set the BREAK pulse on a COM port to 0 or 1 */
  663. void    _Cdecl    combreak (port,value)
  664. int    port,value;
  665. {
  666.   switch (port)
  667.     {
  668.       case 1: case 3:
  669.                 outportb (Com1Buf.dataport + COM_LCR,
  670.         (value ? inportb (Com1Buf.dataport + COM_LCR) | 0x40
  671.                : inportb (Com1Buf.dataport + COM_LCR) & 0xBF));
  672.       case 2: case 4:
  673.                 outportb (Com2Buf.dataport + COM_LCR,
  674.         (value ? inportb (Com2Buf.dataport + COM_LCR) | 0x40
  675.                : inportb (Com2Buf.dataport + COM_LCR) & 0xBF));
  676.       default: break;
  677.     }
  678. }
  679.  
  680. /* Restore a COM port after a DOS shell-out, since */
  681. /* a program may have disabled interrupts, etc.    */
  682. void    _Cdecl    comfix (port)
  683. int    port;
  684. {
  685.   int ch;
  686.   switch (port)
  687.     {
  688.       case 1: case 3:
  689.               /* Restore the serial port interrupts for COM1 */
  690.         outportb(Com1Buf.dataport + COM_IER,1);
  691.         outportb(Com1Buf.dataport + COM_MCR,0x0B);
  692.         ch = inportb(PIC_MASK);    /* Read current mask */
  693.         ch &= (0xFF^INT_MASK_1);/* Reset mask for COM1 */
  694.         outportb(PIC_MASK,ch);    /* Send it to the 8259A */
  695.         break;
  696.       case 2: case 4:
  697.               /* Restore the serial port interrupts for COM2 */
  698.         outportb(Com2Buf.dataport + COM_IER,1);
  699.         outportb(Com2Buf.dataport + COM_MCR,0x0B);
  700.         ch = inportb(PIC_MASK);    /* Read current mask */
  701.         ch &= (0xFF^INT_MASK_2);/* Reset mask for COM2 */
  702.         outportb(PIC_MASK,ch);    /* Send it to the 8259A */
  703.         break;
  704.       default:    break;
  705.     }
  706. }
  707.