home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / telecomm / ka9q_src / slfp.c < prev    next >
Encoding:
Text File  |  1988-12-02  |  12.0 KB  |  220 lines

  1. /* Send and receive IP datagrams on serial lines. Compatible with SL/FP
  2.  * as used with the Merit Network and MIT.
  3.  */
  4. #include <stdio.h>
  5. #include "global.h"
  6. #include "mbuf.h"
  7. #include "iface.h"
  8. #include "timer.h"
  9. #include "ip.h"
  10. #include "slfp.h"
  11. #ifdef UNIX    /* BSD or SYS5 */
  12. #include "unix.h"
  13. #else
  14. # ifdef ATARI_ST
  15. #  include "st.h"
  16. # else
  17. #  include "pc.h"
  18. #  include "asy.h"
  19. # endif        /* ATARI_ST */
  20. #endif        /* BSD or SYS5 */
  21. #include "trace.h"
  22.  
  23. int asy_ioctl();
  24. int slfp_send();
  25. int doslfp();
  26. int asy_output();
  27.  
  28. /* SL/FP level control structure */
  29. struct slfp slfp[ASY_MAX];
  30. char slfp_ack[ACK_LEN] = { SLFP_ACK } ;
  31. char slfp_req[REQ_LEN] = { SLFP_REQ } ;
  32. char ip_hdr[HDR_LEN] = { 2, 1, 0, 0 } ;    /* IP Packet Header */
  33. char ar_hdr[HDR_LEN] = { 2, 3, 0, 0 } ;    /* "Addr Req" Packet Header */
  34. struct interface asy_interface =    /* Fake interface for "dump" proc */
  35.     { NULLIF, "asy" } ;        /* Name of "asy" interface */
  36.  
  37. /* Routine to Initialize the Async line for SL/FP processing.
  38.  * Mostly involves requesting the IP Address for this host.
  39.  */
  40. int
  41. slfp_init(`nterface,pip_addr,modem_cmd)
  42. struct interface *interface ;
  43. int32 *pip_addr ;        /* pointer to host ip address */
  44. char *modem_cmd ;        /* optional command to Modem */
  45. {
  46.     register struct slfp *sp;
  47.     register struct timer *ar ;
  48.     char *modem_line ;
  49.     int i ;
  50.  
  51.     sp = &slfp[interface->dev];
  52.     ar = &sp->ar_timer ;
  53.     sp->ar_pending = 1 ;
  54.     slfp[interface->dev].req_pending = 0 ;
  55.  
  56.     /* If a Modem Command is preseis preseis preseis preseis prese for ACK */
  57.     start_timer(rt) ;
  58.     asy_output(dev, slfp_req, REQ_LEN) ;
  59.     }
  60. }
  61.  
  62. /* Start output, if possible, on asynch device dev */
  63. static
  64. slfp_asy_start(dev)
  65. int16 dev;
  66. {
  67.     register struct slfp *sp;
  68.     register struct timer *rt ;    /* Timer for REQ-ACK negotiation */
  69.     struct mbuf *bp ;
  70.  
  71.     if(!stxrdy(dev))
  72.         return;        /* Transmitter not ready */
  73.  
  74.     sp = &slfp[dev];
  75.     bp = sp->tbp ;
  76.     if(bp != NULLBUF){
  77.         /* transmission just completed */
  78.         free_p(bp) ;
  79.         sp->tbp = NULLBUF;
  80.     }
  81.     if(sp->sndq == NULLBUF)
  82.         return;    /* No work */
  83.  
  84.     rt = &(sp->req_timer) ;
  85.     if (sp->req_pending)
  86.         return ;
  87.     sp->reqcnt = 0 ;
  88.     sp->req_pending = 1 ;
  89.     rt->func = slfp_req_notify ;
  90.     rt->arg = (char *)dev ;
  91.     set_timer(rt,2000) ;        /* 2-Second Timeout for ACK */
  92.     start_timer(rt) ;
  93.     asy_output(dev, slfp_req, REQ_LEN) ;
  94. }
  95. /* Encode a packet in SL/FP format */
  96. static
  97. struct mbuf *
  98. slfp_encode(dev,bp)
  99. int16 dev;        /* Serial line number */
  100. struct mbuf *bp;
  101. {
  102.     struct mbuf *lbp;    /* Mbuf containing line-ready packet */
  103.     register char *cp;
  104.     char c;
  105.  
  106.     /* Allocate output mbuf that's twice as long as the packet.
  107.      * This is a worst-case guess (consider a packet full of SLFP_ENDs!)
  108.      */
  109.     lbp = alloc_mbuf(HDR_LEN + 2*len_mbuf(bp) + 2);
  110.     if(lbp == NULLBUF){
  111.         /* No space; drop */
  112.         free_p(bp);
  113.         return NULLBUF;
  114.     }
  115.     cp = lbp->data;
  116.  
  117.     /* Prefix packet with the Correct Link-Level Header */
  118.     if (slfp[dev].ar_pending)
  119.         memcpy(cp, ar_hdr, HDR_LEN) ;
  120.     else
  121.         memcpy(cp, ip_hdr, HDR_LEN) ;
  122.     cp += HDR_LEN ;
  123.  
  124.     /* Copy input to output, escaping special characters */
  125.     while(pullup(&bp,&c,1) == 1){
  126.         switch(c & 0xff){
  127.         case SLFP_ESC:
  128.             *cp++ = SLFP_ESC;
  129.             *cp++ = SLFP_ESC - SLFP_ESC;
  130.             break;
  131.         case SLFP_END:
  132.             *cp++ = SLFP_ESC;
  133.             *cp++ = SLFP_END - SLFP_ESC;
  134.             break;
  135.         case SLFP_ACK:
  136.             *cp++ = SLFP_ESC;
  137.             *cp++ = SLFP_ACK - SLFP_ESC;
  138.             break;
  139.         case SLFP_REQ:
  140.             *cp++ = SLFP_ESC;
  141.             *cp++ = SLFP_REQ - SLFP_ESC;
  142.             break;
  143.         default:
  144.             *cp++ = c;
  145.         }
  146.     }
  147.     *cp++ = SLFP_END;
  148.     lbp->cnt = cp - lbp->data;
  149.     return lbp;
  150. }
  151.  
  152. #ifdef    MSDOS
  153. /* Invoked when SLFP_REQ is received during xmit of outgoing packet.
  154.  * This allows immediate reception of packet from SCP, rather than
  155.  * forcing it to buffer it until we finish sending the outgoing packet
  156.  */
  157. static
  158. unsigned
  159. slfp_urgent(dev)
  160. int16 dev;    /* SL/FP unit number */
  161. {
  162.     register struct dma *dp ;
  163.  
  164.     dp = &asy[dev].dma ;
  165.     if (dp->last_octet == SLFP_ESC)
  166.     return 256 ;
  167.     else {
  168.     asy[dev].urgent = NULLCHAR ;
  169.     return SLFP_ACK ;
  170.     }
  171. }
  172. #endif
  173.  
  174. void
  175. hndl_rcvd_req(dev, sp)
  176. int16 dev;    /* SL/FP unit number */
  177. register struct slfp *sp;
  178. {
  179.     char i_state ;
  180.  
  181.     if (sp->reqd) { /* REQ before rcv'g END of last Packet! */
  182.     sp->missed_ends++ ;
  183.     free_p(sp->rbp);    /* throw away current packet */
  184.     sp->rbp = NULLBUF;
  185.     sp->rcnt = 0;
  186.     }
  187.  
  188.     sp->reqd = 1 ;
  189.     i_state = disable() ;
  190. #ifdef    MSDOS
  191.     if (asy[dev].dma.flags)
  192.     asy[dev].urgent = slfp_urgent ;
  193.     else
  194. #endif
  195.     asy_output(dev, slfp_ack, ACK_LEN) ;
  196.     restore(i_state) ;
  197. }
  198.  
  199. void
  200. hndl_rcvd_ack(dev, sp)
  201. int16 dev;    /* SL/FP unit number */
  202. register struct slfp *sp;
  203. {
  204.     char i_state ;
  205.  
  206.     i_state = disable() ;
  207.     if (sp->req_pending == 0) {
  208.         sp->false_acks++ ;
  209.         restore(i_state) ;
  210.         return ;
  211.     }
  212.     sp->req_pending = 0 ;
  213.     stop_timer(&(sp->req_timer)) ;
  214.     restore(i_state) ;
  215.     sp->tbp = dequeue(&sp->sndq);
  216.     sp->sndcnt--;
  217.     asy_output(dev,sp->tbp->data,sp->tbp->cnt);
  218. }
  219.  
  220. /* Process incoming bytes in