home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / modem / commsupp.arc / COMMSUPP.DOC < prev    next >
Text File  |  1988-07-21  |  18KB  |  583 lines

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