home *** CD-ROM | disk | FTP | other *** search
/ The CIA World Factbook 1992 / k3bimage.iso / sel / 02 / 0035 / jmodem_e.c < prev    next >
Encoding:
Text File  |  1991-12-02  |  16.8 KB  |  184 lines

  1.  buffer and         */
  2. /*    maintaining the interrupt buffer pointers. A timeout is established.  */
  3. /*                                                                          */
  4. /****************************************************************************/
  5. unsigned short read_chan (bytes, buffer)
  6. unsigned short bytes;                    /* Bytes requested                 */
  7. register unsigned char *buffer;          /* Pointer to the user's buffer    */
  8. {
  9.     unsigned short count;                /* Byte count                      */
  10.     unsigned short avail;                /* Bytes available                 */
  11.     timer = TIMOUT;                      /* Set initial timeout value       */
  12.     count = bytes;                       /* Set byte-count                  */
  13.  
  14.     while (count && timer)               /* If byte request or no timeout   */
  15.     {
  16.         avail = write_ptr - read_ptr;    /* Bytes available                 */
  17.         if (avail)                       /* If bytes available              */
  18.         {
  19.             if (avail > count)           /* If more bytes than we need      */
  20.                 avail = count;           /* Take only what we need          */
  21.             memcpy (buffer   ,           /* User's buffer                   */
  22.                     read_ptr ,           /* Interrupt buffer pointer        */
  23.                     avail)   ;           /* Copy to user's buffer           */
  24.             count -= avail;              /* Update count                    */
  25.             read_ptr +=avail;            /* Update read pointer             */
  26.             buffer   +=avail;            /* Update write pointer            */
  27.             timer = TIMOUT;              /* Set new timer value             */
  28.         }
  29.         _disable();                      /* Clear interrupts                */
  30.         if (read_ptr == write_ptr)       /* If no bytes available           */
  31.         {
  32.             read_ptr = int_buffer;       /* Initialize the interrupt buffer */
  33.             write_ptr = int_buffer;      /* Initialize the interrupt buffer */
  34.         }
  35.         _enable();                       /* Enable interrupts               */
  36.     }
  37.     return(bytes - count);               /* Actual characters received      */
  38. }
  39. /****************************************************************************/
  40. /*                      Flush the interrupt buffer                          */
  41. /****************************************************************************/
  42. void flush()
  43. {
  44.     _disable();
  45.     read_ptr = int_buffer;               /* Initialize the interrupt buffer */
  46.     write_ptr = int_buffer;              /* Initialize the interrupt buffer */
  47.     _enable();
  48. }
  49. /****************************************************************************/
  50. /*                      Communications transmit routine                     */
  51. /*    Write 'bytes' bytes from buffer to the UART. Don't return until done  */
  52. /*    unless the carrier failed or the hardware broke.                      */
  53. /****************************************************************************/
  54. unsigned short write_chan (bytes, buffer)
  55. unsigned short bytes;                          /* Bytes to send             */
  56. register unsigned char *buffer;                /* Pointer to the buffer     */
  57. {
  58.     unsigned short status;
  59.  
  60.     timer = TIMOUT;
  61.     while ((bytes && timer) && !user_abort )  /* Bytes, no abort, no timout */
  62.     {
  63.         while (
  64.               ( status =                   /* Get modem status              */
  65.               ( inp (hardware_port+MSR)    /* ...from modem status register */
  66.                 & MSR_CHK )                /* ... check CTS and DSR only    */
  67.               ) != old_stat)               /* ... if not the same as before */
  68.         {                                  /* Flow control loop             */
  69.             if ( (status & MSR_RLSD )      /* ...check modem carrier        */
  70.                  != carrier)               /* ... if not same as before     */
  71.                 {
  72.                     user_abort = 0x0FFFF;  /* Set the abort flag            */
  73.                     return JM_ABT;         /* ... and get out               */
  74.                 }
  75.         }
  76.         status = inp(hardware_port+LSR);   /* Get line-status               */
  77.         if (status & LSR_THRE)             /* If TX holding register empty  */
  78.         {
  79.             outp(hardware_port,*buffer++); /* Send the byte                 */
  80.             bytes--;                       /* Bump the byte-count           */
  81.             timer = TIMOUT;                /* Set new timer-value           */
  82.         }
  83.     }
  84.     return JM_NRM;
  85. }
  86. /****************************************************************************/
  87. /*                Communications adapter hardware interrupt                 */
  88. /*    This is very simple because we interrupt on receive only. Since we    */
  89. /*    must wait until the entire block has been received and checked be-    */
  90. /*    for doing anything else, the transmitter is polled.                   */
  91. /*                                                                          */
  92. /****************************************************************************/
  93. void interrupt far com_int()
  94. {
  95.     *write_ptr = (unsigned char)
  96.         inp(hardware_port);                    /* Put byte in buffer        */
  97.     outp(0x20,0x20);                           /* Reset hardware controller */
  98.     if (write_ptr < int_buffer + DAT_LEN )     /* Check buffer for overflow */
  99.         write_ptr++;                           /* Bump pointer if room      */
  100. }
  101. /****************************************************************************/
  102. /*                            Timer interrupt                               */
  103. /*    A WORD (timer) gets decremented every timer-tick if it is not already */
  104. /*    zero. This is used to set time-out values in the communication pro-   */
  105. /*    cedures so that a "wait-forever" can't occur.                         */
  106. /*                                                                          */
  107. /****************************************************************************/
  108. void interrupt far tim_int()
  109. {
  110.     if (timer)                             /* If NZ                         */
  111.         timer--;                           /* Bump the timer                */
  112.     outp(0x20,0x20);                       /* Reset the hardware controller */
  113.     _enable();                             /* Allow network interrupts      */
  114.     _chain_intr(old_tim);                  /* Go to old timer-tickase;        /* Set hardware port               */
  115.     old_ier  = inp(hardware_port +IER);  /* Get interrupt enable regis      */
  116.     old_brk  = _dos_getvect(0x1B);       /* Get old break key vector        */
  117.     old_mask = inp(0x21);                /* Save old interrupt mask         */
  118.     old_tim  = _dos_getvect(0x1C);       /* Get old DOS timer-tick vector   */
  119.     old_com  = _dos_getvect(
  120.        port_pars[user_port].int_num);    /* Get old communications vector   */
  121.     _dos_setvect(0x1C,tim_int);          /* Set new timer interrupt         */
  122.     _dos_setvect(
  123.        port_pars[user_port].int_num,     /* Set new communications vector   */
  124.        com_int);
  125.     outp(0x21,old_mask &
  126.        port_pars[user_port].mask);       /* Set interrupt enable mask       */
  127.     outp(hardware_port+MCR, 0x0F);       /* Turn everything on.             */
  128.     outp(hardware_port+IER, IER_ERBFI);  /* Enable received data available  */
  129.     for (i=0; i<8; i++)                  /* Edge-triggering, read the ports */
  130.         inp(hardware_port + i);          /* Port to clear                   */
  131.     outp(0x20,0x20);                     /* Reset the hardware controller   */
  132.     timer=9;                             /* 1/2 second wait                 */
  133.     while (timer);                       /* Wait 1/2 second                 */
  134.     flush();                             /* Clear interrupt buffer again    */
  135.     i = inp(hardware_port+MSR);          /* Get current modem status        */
  136.     old_stat = i & MSR_CHK;              /* Get current modem control       */
  137.     carrier  = i & MSR_RLSD;             /* Get any modem carrier           */
  138.     return JM_NRM;
  139. }
  140. /****************************************************************************/
  141. /*                 Close the communications channel                         */
  142. /*                                                                          */
  143. /*    Under MS-DOS this involves restoring the interrupt vectors and        */
  144. /*    controller mask that was saved during the OPEN routine.               */
  145. /*                                                                          */
  146. /****************************************************************************/
  147. unsigned short close_chan (user_port)
  148. unsigned short user_port;
  149. {
  150.     outp(hardware_port+IER,old_ier);       /* Set old interrupt enable      */
  151.     outp(0x21,old_mask);                   /* Restore old interrupt mask    */
  152.     _dos_setvect(
  153.        port_pars[user_port].int_num,       /* Set old communications vector */
  154.        old_com);
  155.     _dos_setvect(0x1C,old_tim);            /* Set old timer interrupt       */
  156.     _dos_setvect(0x1B,old_brk);            /* Set old break interrupt       */
  157.     return JM_NRM;
  158. }
  159. /****************************************************************************/
  160. /*              Read from the communications channel                        */
  161. /*                                                                          */
  162. /*    This involves transferring data from the interrupt"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ routine  */
  163. }
  164. /****************************************************************************/
  165. /*                          A B O R T   trap                                */
  166. /*    Control-C and control-break vectors are set to point here so that     */
  167. /*    a user-break harmlessly sets a flag so that interrupt vectors may     */
  168. /*    properly restored upon program exit.                                  */
  169. /*                                                                          */
  170. /**************    case the BBS program has turned them off (WILDCAT does).
  171.           Some modems "hiccup" when this occurs, and the RTS line will
  172.           bounce. This caused JMODEM to "wait forever" for a RTS that
  173.           never occurs. Therefore I added a 1/2 second delay between
  174.           the time that I first set these bits and the time I start
  175.           checking for RTS and RLSD for flow-control and a possible
  176.           abort. This fixed this problem. The flow-control problem is
  177.           complex because us**************************************************************/
  178. void interrupt far fatal_abort()
  179. {
  180.     user_abort = 0xFFFF;                              /* Set abort flag     */
  181. }
  182. /****************************************************************************/
  183. /******************** E N D   O F   M O D U L E *****************************/
  184.