home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 183_01 / comsup.doc < prev    next >
Text File  |  1984-06-22  |  17KB  |  581 lines

  1.         =================================================
  2.         =                            =
  3.         = Communications support for DeSmet C compiler  =
  4.         =                            =
  5.         =================================================
  6.  
  7.  
  8.       Written by Tom Poindexter  (70040,1223), March 1984
  9.  
  10.  
  11. Acknowledgements:   Vern Buerg - for an example of comm support for
  12.                  the Lattice C compiler. (DRIVER.ASM)
  13.             Curt Klinsing - the author listed in DRIVER.ASM
  14.             Earl Terwilliger Jr. - referring me to the PC Tech
  15.                  Journal series on 8088 interrupts
  16.             Chris Dunford - author of the 2 part series in PC Tech
  17.                  Journal (12/83 & 1/84).
  18.  
  19. =========
  20.  
  21. The following files constitute the communication support routines.
  22.  
  23. COMMSUPP.C - The actual C interface routines.
  24.  
  25. COMMASM.A  - Internal assembler routines used by commsupp.c.
  26.  
  27. COMMSUPP.H - An #include file containing declares and defines for
  28.          an application program using commsupp.c.
  29.  
  30. COMMSUPP.DOC - This documentation.
  31.  
  32. -------------
  33.  
  34. COMMTERM.C  - Optional, an example C communications program using
  35.           commsupp.c
  36.  
  37. =========
  38.  
  39.  
  40.    COMMSUPP provides interrupt driven buffered communication support for the
  41. DeSmet C compiler.  Features: XON/XOFF support, two ports active
  42. concurrently, modem break signal generation, status reporting, and
  43. event trapping.
  44.  
  45.    Most of the routines are written in C so that it may be possible to
  46. port these routines to another compiler.  The assembler language routines
  47. are coded in DeSmet ASM88 syntax, which is somewhat different than the
  48. IBM Macro Assembler syntax.
  49.  
  50.    DeSmet library functions that may or may not be available on other
  51. compilers are:
  52.  
  53.   _lmove(num_bytes,source_offset,source_segment,target_offset,target_segment);
  54.  
  55.     Performs a memory move using REP MOVSB so that overlapping moves are
  56.     handled correctly (processor direction flag set correctly).
  57.  
  58.   _move(num_bytes,source_offset,target_offset);
  59.  
  60.     Similiar to _lmove, except that the move is within the C data segment.
  61.  
  62.   c_ds = _showds();
  63.  
  64.     Returns the C data segment.
  65.  
  66.   c_cs = _showcs();
  67.  
  68.     Returns the C program segment.
  69.  
  70.   ptr = malloc(num_bytes);
  71.  
  72.     Allocate a specific number of bytes in memory and return a pointer
  73.     to the area.
  74.  
  75.  
  76. The following functions are not available in DeSmet C, but may or may not
  77. be included in other compilers.  These routines are in COMMASM.A:
  78.  
  79.   struct { int ax,bx,cx,dx,si,di,ds,es;} in_regs,out_regs;
  80.   flags = sysint (interrupt, &in_regs, &out_regs);
  81.  
  82.     Call a system interrupt routine, passing and returning register values.
  83.  
  84.   value = inb(hardware_port);
  85.  
  86.     Input a byte value from a hardware port address.
  87.  
  88.   outb(hardware_port,value);
  89.  
  90.     Output a byte value to a hardware port address.
  91.  
  92.    cli();
  93.  
  94.      Disable system interrupts (CLI).
  95.  
  96.    sti();
  97.  
  98.      Enable system interrupts (STI);
  99.  
  100.  
  101.  
  102. DeSmet C compiler use
  103. =====================
  104.  
  105.   1. Compile COMMSUPP.C with C88
  106.      A>c88 commsupp
  107.  
  108.   2. Assemble COMMASM.A with ASM88
  109.      A>asm88 commasm
  110.  
  111.   3. If you maintain your own library, use LIB88 to add commsupp and commasm
  112.      A>lib88 commasm commsupp -oyourlib
  113.  
  114.   4. Create and compile your program.  #include "commsupp.h".
  115.      A>c88 yourprog
  116.  
  117.   5. Bind your program with your library (as in #3) or with the object
  118.      modules alone.
  119.      A>bind yourprog (your-other-modules) commsupp commasm     w/o private lib
  120.      A>bind yourprog yourlib.s                       w/  private lib
  121.  
  122.  
  123.  
  124.  
  125. Description of routines:
  126. ========================
  127.  
  128. init_com  -  Initializes the serial port, enables and sets interrupt vectors,
  129.          sets communication parameters (baud, parity, data length,
  130.          stop bits), and allocates a receive buffer.
  131.  
  132.      Parms:
  133.        port: 1 = com1:, 2 = com2:
  134.        baud: 110, 150, 300, 450, 600, 1200, 2400, 4800, 9600
  135.        parity: 0 = none, 1 = odd, 2 = even, 3 = mark, 4 = space
  136.        data: 5, 6, 7, 8
  137.        stop: 1, 2
  138.        buff_len: length of receive buffer up to 32767 bytes
  139.  
  140.      Returns:
  141.        ERROR (-1): comm port not available or invalid parm
  142.        TRUE (1): ok
  143.  
  144.      Example:
  145.  
  146.        int port, baud, parity, data, stop, buff_len;
  147.  
  148.        port = 1;
  149.        baud = 300;
  150.        parity = 0;
  151.        data = 8;
  152.        stop = 1;
  153.        buff_len = 1024;
  154.  
  155.        if (init_com(port,baud,parity,data,stop,buff_len) == ERROR)
  156.      puts("\nComm port initialzation failed.\n");
  157.  
  158.      Notes:
  159.        See defines for parity values in COMMSUPP.H.  This function sets the
  160.        8250 modem controller chip and the 8259 interrupt controller chip.
  161.        Also, this routine "pokes" the value of the C data segment into
  162.        the interrupt handler routine so that no matter where the
  163.        interrupt occurs, the interrupt handler will have access to the
  164.        C data segment.
  165.        See the PC Tech Journal (12/83 & 1/84) for details on the
  166.        interrupt controller.
  167.  
  168. =========
  169.  
  170. uninit_com - Disables interrupts, flushes buffer. Optionally leaves serial
  171.          port open.
  172.  
  173.      Parms:
  174.        port: 1 = com1:, 2 = com2:
  175.        lv_open: TRUE (1) = leave serial open (DTR enabled), FALSE (0) = close
  176.         serial port (drop DTR).
  177.  
  178.      Returns:
  179.        ERROR (-1): comm port never intialized or invalid port number.
  180.        TRUE (1): ok
  181.  
  182.      Example:
  183.        int port, lv_open;
  184.  
  185.        port = 1;
  186.        lv_open = TRUE;
  187.  
  188.        uninit_com(port,lv_open);
  189.        puts("\n\nProgram terminating.......Comm port left open.\n\n");
  190.  
  191.      Notes:
  192.        It is VERY important that this function is successfully completed
  193.        prior to the termination of the user program.  Otherwise, any incoming
  194.        chars will trigger the interrupt and control will pass to the interrupt
  195.        handler address, whether or not there is a valid routine to process
  196.        the interrupt.
  197.  
  198. =========
  199.  
  200. send_brk - Send a break signal to the specified port.  1/2 second of mark
  201.        signal is generated.
  202.  
  203.      Parms:
  204.        Port: 1 = com1:, 2 = com2:
  205.  
  206.      Returns:
  207.        ERROR (-1): comm port never intialized or invalid port number.
  208.        TRUE (1): ok
  209.  
  210.      Example:
  211.        int port;
  212.  
  213.        port = 1;
  214.        send_brk(port);
  215.  
  216.      Notes:
  217.        See this routine in commsupp.c on using the SYSINT function.  The
  218.        time-of-day interrupt (documented in the tech reference) is invoked
  219.        to return the current time-of-day tick count.  The effect of the
  220.        routine is a delay for a specified time that is independent
  221.        of processor speed.
  222.  
  223. =========
  224.  
  225. set_xoff - Enables or disables the XON/XOFF protocol.  See companion functions
  226.        recd_xoff and sent_xoff.  If enabled, an XOFF received will set
  227.        a flag which can be parsed with the recd_xoff function.  The user
  228.        program must check recd_xoff to suspend transmission, i.e.,
  229.        outp_char and outp_strn are not automatically suspended.  Also, if
  230.        the receive buffer becomes 75% full, an XOFF is sent to the remote
  231.        computer, and a flag is set, which can be parsed with sent_xoff.
  232.  
  233.      Parms:
  234.        port: 1 = com1:, 2 = com2:
  235.        state: TRUE (1) = XON/XOFF enabled, FALSE (0) = XON,XOFF disabled
  236.  
  237.      Returns:
  238.        ERROR (-1): comm port never intialized or invalid port number.
  239.        TRUE (1): ok
  240.  
  241.      Example:
  242.        int port, state;
  243.  
  244.        port = 1;
  245.        puts("\nDo you want XON/XOFF enabled (y/n) ? ");
  246.        state = (getchar() == 'y') ? TRUE : FALSE;
  247.        set_xoff(port,state);
  248.  
  249.      Notes:
  250.        XON/XOFF should be disabled anytime binary transmissions are performed,
  251.        i.e., all 8 bits significant.  When XON/XOFF is disabled, there is no
  252.        mechansism to prevent or report buffer overrun.    In this case the
  253.        user program should be alert to the number of bytes in the buffer using
  254.        the inp_cnt function.
  255.  
  256. =========
  257.  
  258. recd_xoff - Report if an XOFF character has been received.  If TRUE, then
  259.         also reset the recd_xoff flag to FALSE.
  260.  
  261.      Parms:
  262.        port: 1 = com1:, 2 = com2:
  263.  
  264.      Returns:
  265.        ERROR (-1): comm port never intialized or invalid port number.
  266.        TRUE (1): XOFF has been received
  267.        FALSE (0): XOFF has not been received
  268.  
  269.      Example:
  270.        int port, curr_state;
  271.  
  272.        port = 1;
  273.        curr_state = recd_xoff(port);
  274.        if (curr_state == TRUE)
  275.      {
  276.        puts(" XOFF received..press any key to continue ");
  277.        getchar();
  278.      }
  279.  
  280.      Notes:
  281.        recd_xoff will always return FALSE if XON/XOFF is disabled.
  282.        The recd_xoff flag is reset upon calling this function, so that
  283.        recd_xoff will return FALSE until another XOFF is received.
  284.  
  285. =========
  286.  
  287. sent_xoff - Report if XOFF has been sent, indicating that the receive buffer
  288.         is 75% or more full.  If TRUE, then also reset the sent_xoff flag
  289.         to FALSE.
  290.  
  291.      Parms:
  292.        port: 1 = com1:, 2 = com2:
  293.  
  294.      Returns:
  295.        ERROR (-1): comm port never intialized or invalid port number.
  296.        TRUE (1): XOFF has been sent.
  297.        FALSE (0): XOFF has not been sent.
  298.  
  299.      Example:
  300.        int port;
  301.  
  302.        port = 1;
  303.        if (sent_xoff(port) == TRUE)
  304.      {
  305.        puts("Your in trouble now...here's the rest of the buffer: ");
  306.        while (inp_cnt(port))
  307.          putchar(inp_char(port));
  308.      }
  309.  
  310.      Notes:
  311.        sent_xoff will always return FALSE if XON/XOFF is disabled.
  312.        The sent_xoff flag is reset upon calling this function, so that
  313.        sent_xoff will return FALSE until another XOFF is sent.
  314.  
  315. =========
  316.  
  317. inp_cnt - Reports the number of bytes available in the buffer waiting to be
  318.       read.
  319.  
  320.      Parms:
  321.        port: 1 = com1:, 2 = com2:
  322.  
  323.      Returns:
  324.        ERROR (-1): comm port never intialized or invalid port number.
  325.        other: the number of bytes in the buffer.
  326.  
  327.  
  328.      Example:
  329.        int port;
  330.        char c;
  331.  
  332.        port = 1;
  333.  
  334.        while (inp_cnt(port))
  335.      {
  336.        c = inp_char(port);
  337.        switch (c)
  338.          {
  339.            case ESC: ...
  340.            case CR: ...
  341.            case LF: ...
  342.            case BS: ...
  343.            default:
  344.          putchar(c);
  345.          }
  346.      }
  347.  
  348.      Notes:
  349.        If inp_cnt is equal to the buffer length, a buffer overflow has
  350.        probably occurred.  The incoming characters are dropped into the
  351.        AMBB (All Mighty Bit Bucket) so that the buffer is not corrupted.
  352.  
  353. =========
  354.  
  355. inp_char - Return one byte from the receive buffer.  All serial port
  356.        control lines (carrier detect, etc) are ignored.
  357.  
  358.      Parms:
  359.        port: 1 = com1:, 2 = com2:
  360.  
  361.      Returns:
  362.        ERROR (-1): comm port never intialized, invalid port number, or
  363.            no character available
  364.        other: Next (FIFO) character in the buffer.
  365.  
  366.  
  367.      Example:
  368.        int port;
  369.        char c;
  370.  
  371.        port = 1;
  372.  
  373.        outp_strn("\nWhich option (1, 2, or 3)? ");
  374.        while (inp_cnt(port) == 0)
  375.      ;
  376.        c = inp_char(port);
  377.        switch (c)
  378.      {
  379.        case '1': ....
  380.        etc.
  381.      }
  382.  
  383.      Notes:
  384.        The value return is type int, which should convert to char in most
  385.        compilers.
  386.  
  387. =========
  388.  
  389. inp_strn - Transfer n bytes from the receive buffer to a string, up to a
  390.        maximum length.  It is the responsibility of the user program
  391.        to insure that the maximum number of bytes is less than or equal
  392.        to the string length.  If the buffer contains less than the
  393.        number of bytes requested, only the available bytes are
  394.        transferred.
  395.  
  396.      Parms:
  397.        port: 1 = com1:, 2 = com2:
  398.        &strn: address of the string to receive the bytes.
  399.        cnt: the maximum number of bytes to transfer.
  400.  
  401.      Returns:
  402.        ERROR (-1): comm port never intialized, invalid port number,
  403.            or no characters available.
  404.        other: the number of bytes actually transferred.
  405.  
  406.  
  407.      Example:
  408.        #define STR_LEN 80
  409.        int port;
  410.        char strn[STR_LEN];
  411.        int cnt;
  412.  
  413.        port = 1;
  414.        cnt = inp_strn(port,&strn,STR_LEN-1);
  415.        strn[cnt] = '\0';
  416.  
  417.        printf("%d bytes were returned. Here it is: %s",cnt,strn);
  418.  
  419.      Notes:
  420.        This is trivially faster that a looping inp_char, using the _move
  421.        library function.  This may be the trick if you are having buffer
  422.        overrun problems.
  423.  
  424. =========
  425.  
  426. outp_char - Transmits one byte over the serial port.  Carrier detect, clear
  427.         to send, and data set ready signals are ignored (full duplex
  428.         is implied).
  429.  
  430.      Parms:
  431.        port: 1 = com1:, 2 = com2:
  432.       c: the character to send
  433.  
  434.      Returns:
  435.        ERROR (-1): comm port never intialized, invalid port number, or
  436.            timeout on THRE (transmitter holding register empty).
  437.        TRUE (1): ok.
  438.  
  439.  
  440.      Example:
  441.        int port;
  442.        char c;
  443.  
  444.        port = 1;
  445.        c = 'A';
  446.        outp_char(port,c);
  447.  
  448.      Notes:
  449.        A timeout is unlikely, since only the THRE is checked.  If you need
  450.        true half duplex operation, check clear to send using com_stat
  451.        before sending.    Also, if you have enabled XON/XOFF (set_xoff),
  452.        you may want to call recd_xoff to see if the remote computer has
  453.        sent you an XOFF.
  454.  
  455. =========
  456.  
  457. outp_strn - Transmits a zero terminated string or up to a specified length.
  458.  
  459.      Parms:
  460.        port: 1 = com1:, 2 = com2:
  461.        &strn: address of the string to send.
  462.        cnt: maximum characters to send.
  463.  
  464.      Returns:
  465.        ERROR (-1): comm port never intialized, invalid port number, or
  466.            timeout.
  467.        TRUE: ok
  468.  
  469.  
  470.      Example:
  471.        #define STR_LEN 80
  472.        int port;
  473.        char strn[STR_LEN];
  474.  
  475.        port = 1;
  476.        puts("\nWhat is your password on system X? ");
  477.        gets(strn);
  478.        outp_strn(port,&strn,STR_LEN);
  479.  
  480.      Notes:
  481.        This utilizes the outp_char function above; hence the same conditions
  482.        apply.  If you need to control clear to send and XON/XOFF, then don't
  483.        use outp_strn.  See the commterm.c upload routine for a method
  484.        of sending a string while checking for XOFF.
  485.  
  486. =========
  487.  
  488. com_stat - Return the serial port line status and the modem status.
  489.  
  490.      Parms:
  491.        port: 1 = com1:, 2 = com2:
  492.  
  493.      Returns:
  494.        ERROR (-1): comm port never intialized or invalid port number.
  495.        other: line status (high byte) and modem status (low byte)
  496.  
  497.  
  498.      Example:
  499.        int port;
  500.        int status;
  501.        port = 1;
  502.  
  503.        status = com_stat(port);
  504.  
  505.      Notes:
  506.        Use the defines in COMMSUPP.H to check for certain conditions by
  507.        anding the status returned with the condition value, i.e.,
  508.  
  509.        if (com_stat(port) & BREAK_IND)
  510.      puts("We got a break; quick -- do something!");
  511.  
  512.        if (com_stat(port) & CARRIER)
  513.      puts("\nONLINE\n");
  514.  
  515. =========
  516.  
  517. on_com    - Specify a C routine to execute when a byte is received.
  518.  
  519.      Parms:
  520.        port: 1 = com1:, 2 = com2:
  521.     rtn: the address of a valid C routine or NULL (0).
  522.  
  523.      Returns:
  524.        ERROR (-1): comm port never intialized or invalid port number.
  525.        TRUE: ok
  526.  
  527.  
  528.      Example:
  529.        extern int total;
  530.        int port;
  531.        int counter();
  532.        port = 1;
  533.  
  534.        com_stat(port,counter);
  535.  
  536.  
  537.        counter ()
  538.        {
  539.      total++;
  540.        }
  541.  
  542.      Notes:
  543.        This function is similar to BASICA's event trapping statements.
  544.        ON COM(n) GOSUB nnn
  545.        COM(n) ON
  546.        COM(n) OFF
  547.  
  548.        The following rules apply:
  549.        1. The routine must be a valid C routine or an assembler routine
  550.       that conforms to C's entry and exit.
  551.        2. The routine should not expect any arguments or return any
  552.       values.  Any communication to the routine is by global or
  553.       external variables.
  554.        3. Local variables should be kept to a minimun, i.e., declare
  555.       as static whenever possible.
  556.        4. Keep function calls to a minimum.
  557.        5. on_com routines will never be recursive.  Once the routine
  558.       is given control, any incoming characters will not trigger
  559.       reactivation of the routine.    Any incoming characters will
  560.       be buffered, assuming an adequate buffer size was specified.
  561.        6. To deactivate the on_com routine, call on_com with a zero
  562.       as the routine ( on_com(port,0); ).  This is evquivalent to
  563.       BASICA's   COM(1) OFF.   Note that there is no COM(1) STOP
  564.       equivalent, i.e. when the on_com routine is active, commsupp
  565.       will not 'remember' later incoming characters, and will not
  566.       reactivate the on_com routine until the next character.
  567.  
  568.        Many of the limitations have to do with the stack segment in use
  569.        at the time of the interrupt.  Your C program may be active or
  570.        DOS may be active, thus the stack segment and stack pointer
  571.        could be DOS's.  The C data segment is always guaranteed for the
  572.        small memory model (DeSmet ver 2.1).  All registers (except
  573.        SS and SP) are saved during the interrupt.
  574.  
  575. =========
  576.  
  577.  
  578. End of commsupp.doc
  579.  
  580. ==============================================================================
  581.