home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 314_01 / mnpllvl.c < prev    next >
C/C++ Source or Header  |  1990-05-15  |  26KB  |  1,310 lines

  1. /*=============================================================================
  2.  
  3.                      The Microcom MNP Library
  4.                     (Microsoft C Version)
  5.  
  6. -------------------------------------------------------------------------------
  7.  
  8.                  MNPLLVL - MNP Link Level Routines
  9.  
  10. -------------------------------------------------------------------------------
  11.  
  12.      Modification History
  13.  
  14.     3/25/87 - Compuserve V1.0
  15.  
  16. =============================================================================*/
  17.  
  18. /* Header files 
  19. */
  20. #include <dos.h>
  21. #include <mnpdat.h>
  22. #include <llvl.h>
  23.  
  24. /* External references
  25. */
  26. extern USIGN_16 sb_cnt;
  27.  
  28. /* Global buffers 
  29. */
  30. struct link_ctl_blk lcb;
  31.  
  32. struct BUFFER rb, ftb, lkb, rlkb;
  33.  
  34. struct BLST lkblst[2],
  35.         rlkblst[2],
  36.         iatblst[8];
  37.  
  38. USIGN_8 lkbuff[MAX_LPDU_SZ * 2];
  39. USIGN_8 rlkbuff[MAX_LPDU_SZ * 2];
  40. USIGN_8 iatbuff[(64+5)*8];
  41.  
  42. USIGN_16 tbcnt;
  43.  
  44. struct TIMERS tmr;
  45.  
  46. USIGN_16 port_add,
  47.     chan_no,
  48.     iir_add;
  49.  
  50. USIGN_8 linestat;
  51.  
  52. /* Function declarations
  53. */
  54. void as_disconnect();
  55. SIGN_16 acking();
  56. SIGN_16 credit_chk();
  57. SIGN_16 lpdu_send();
  58. SIGN_16 parse_lr();
  59. SIGN_16 receive_wait();
  60. SIGN_16 retran_lt();
  61. SIGN_16 send_la();
  62. SIGN_16 send_pdu();
  63. SIGN_16 send_wait();
  64.  
  65. /*GLOBAL********************************************************************
  66.  
  67.     as_connect - establish an MNP link-connection
  68.  
  69. ***************************************************************************/
  70.  
  71. SIGN_16 as_connect (mnpcb,mode)
  72.  
  73. struct MNP_CB *mnpcb;
  74. USIGN_16 mode;
  75. {
  76.  
  77. SIGN_16 lr_cnt,
  78.     la_cnt,
  79.     retcode,
  80.     link_state;
  81.  
  82. /* Initialize
  83. */
  84. lcb.lpdu_type = 0;
  85. link_state = IDLE;
  86.  
  87. for (;;)
  88.     {
  89.  
  90.     switch (link_state)
  91.         {
  92.  
  93.         case IDLE:
  94.             link_init(mnpcb);
  95.             link_reset();
  96.             if (L_ACCEPTOR)
  97.                 {
  98.                 SETBIT1(MODE)
  99.                 link_state = LR_WAIT;
  100.                 }
  101.             else
  102.                 {
  103.                 suspend(5);
  104.                 if (retcode = lpdu_send(LR,WAIT))
  105.                     link_state = LNK_ERROR;
  106.                 else
  107.                     link_state = LR_RESP_WAIT;
  108.                 }
  109.             break;
  110.  
  111.         case LR_RESP_WAIT:
  112.             lr_cnt = LR_RETRAN_CNT;
  113.             retcode = SUCCESS;
  114.             while ((retcode = receive_wait()) || !lcb.lpdu_type)
  115.                 {
  116.                 if (retcode == NO_PHYSICAL)
  117.                     {
  118.                     link_state = LNK_ERROR;
  119.                     break;
  120.                     }
  121.                 if (lr_cnt--)
  122.                     {
  123.                     if (retcode = lpdu_send(LR,WAIT))
  124.                         {
  125.                         link_state = LNK_ERROR;
  126.                         break;
  127.                         }
  128.                     }
  129.                 else
  130.                     {
  131.                     retcode = TIME_OUT;
  132.                     link_state = LNK_ERROR;
  133.                     break;
  134.                     }
  135.                 }
  136.  
  137.             if (retcode == SUCCESS) 
  138.                 link_state = PARMS_NEGO;
  139.             break;
  140.  
  141.         case PARMS_NEGO:
  142.             if (retcode = parse_lr())
  143.                 {
  144.                 as_disconnect(retcode,NULL);
  145.                 return(retcode + LR_CODE);
  146.                 }
  147.  
  148.             if (retcode = lpdu_send(LA,WAIT))
  149.                 link_state = LNK_ERROR;
  150.             else
  151.                 link_state = LNK_CONNECTED;
  152.             break;
  153.  
  154.         case LR_WAIT:
  155.             lr_cnt = 2;
  156.             while ((retcode = receive_wait()) || !lcb.lpdu_type)
  157.                 {
  158.                 if (retcode == NO_PHYSICAL)
  159.                     {
  160.                     link_state = LNK_ERROR;
  161.                     break;
  162.                     }
  163.                 if (!(--lr_cnt))
  164.                     {
  165.                     retcode = TIME_OUT;
  166.                     link_state = LNK_ERROR;
  167.                     break;
  168.                     }
  169.                 }
  170.  
  171.             if (link_state != LR_WAIT)
  172.                 break;
  173.  
  174.             if (retcode = parse_lr())
  175.                 {
  176.                 as_disconnect(retcode,NULL);
  177.                 return(retcode + LR_CODE);
  178.                 }
  179.  
  180.             lr_cnt = LR_TRAN_CNT;
  181.             link_state = CONNECT_REQ_WAIT;
  182.             break;
  183.  
  184.         case CONNECT_REQ_WAIT:
  185.             if (lr_cnt == NULL)
  186.                 {
  187.                 retcode = FAILURE;
  188.                 link_state = LNK_ERROR;
  189.                 break;
  190.                 }
  191.  
  192.             if (retcode = lpdu_send(LR,WAIT))
  193.                 link_state = LNK_ERROR;
  194.             else
  195.                 {
  196.                 lr_cnt--;
  197.                 la_cnt = LA_WAIT_CNT;
  198.                 link_state = LA_WAIT;
  199.                 }
  200.             break;
  201.  
  202.         case LA_WAIT:
  203.             while ((retcode = receive_wait()) || !lcb.lpdu_type)
  204.                 {
  205.                 if (retcode == NO_PHYSICAL)
  206.                     {
  207.                     link_state = LNK_ERROR;
  208.                     break;
  209.                     }
  210.                     if (--la_cnt)
  211.                     {
  212.                     if (retcode = lpdu_send(LR,WAIT))
  213.                         {
  214.                         link_state = LNK_ERROR;
  215.                         break;
  216.                         }
  217.                     }
  218.                 else
  219.                     {
  220.                     retcode = TIME_OUT;
  221.                     link_state = LNK_ERROR;
  222.                     break;
  223.                     }
  224.                 }
  225.  
  226.             if (link_state != LA_WAIT)
  227.                 break;
  228.  
  229.             switch (lcb.lpdu_type)
  230.                 {
  231.                 case LA:
  232.                     lcb.lt_rsn = NULL;
  233.  
  234.                 case LT:
  235.                     link_state = LNK_CONNECTED;
  236.                     break;
  237.  
  238.                 case LR:
  239.                     ret_b (&rlkb,rlkb.used_lst);
  240.                     link_state = CONNECT_REQ_WAIT;
  241.                     break;
  242.     
  243.                 default:
  244.                     retcode = FAILURE;
  245.                     link_state = LNK_ERROR;
  246.                 }
  247.  
  248.             break;
  249.  
  250.         case LNK_ERROR:
  251.             as_disconnect(NULL,NULL);
  252.             return(retcode);
  253.  
  254.         case LNK_CONNECTED:
  255.             dphase_init();
  256.             SETBIT1(LINK_EST)
  257.             return(SUCCESS);
  258.         }
  259.     }
  260. }
  261.  
  262. /*GLOBAL***********************************************************************
  263.  
  264.     as_disconnect - terminate a link-connection
  265.  
  266. ******************************************************************************/
  267.  
  268. void as_disconnect(lreason,ureason)
  269.  
  270. SIGN_16 lreason,
  271.     ureason;
  272. {
  273.  
  274. /* If the link is still up, send an LD LPDU to the other side.  If the
  275. ** caller has supplied a reason code (in ureason) then save this code
  276. ** in the lcb so that it will be sent in the LD.  Wait for the LD to 
  277. ** actually be sent (to the very last byte...). 
  278. */
  279. if (BIT1SET(LINK_EST))
  280.     {
  281.     if ((lcb.l_disc_code = lreason) == 255)
  282.         lcb.u_disc_code = ureason;
  283.     lpdu_send(LD,NOWAIT);
  284.     while (!lne_stat() && modem_out_busy)
  285.         ;
  286.     CLRBIT1(LINK_EST);
  287.     }
  288.  
  289. /* In any case, wait a bit.
  290. */
  291. suspend(10);
  292.  
  293. /* Now remove interrupt handlers - link driver and timers. 
  294. */
  295. drvr_rem();
  296. timerrem();
  297.  
  298. }
  299.  
  300. /*GLOBAL********************************************************************
  301.  
  302.     as_link - maintain a link-connection
  303.  
  304. ***************************************************************************/
  305.  
  306. SIGN_16 as_link()
  307. {
  308.  
  309. SIGN_16 retcode;
  310.  
  311. /* If the link-connection has failed, return reporting link down. 
  312. */
  313. if (!BIT1SET(LINK_EST))
  314.     return (LNK_DOWN);
  315.  
  316. /* If the physical connection has been lost, return reporting p-conn down. 
  317. */
  318. if (lne_stat())
  319.     return (NO_PHYSICAL);
  320.  
  321. /* If we support attention service, go see if we have any to process. 
  322. */
  323. if (lcb.prot_level == 2)
  324.     {
  325.     if (retcode = attn_process())
  326.         return(retcode);
  327.     }
  328.  
  329. /* Go see if it's time to send an ack. 
  330. */
  331. if (retcode = acking())
  332.     return(retcode);
  333.  
  334. /* Try to free up any transmit buffers which have been acked. 
  335. */
  336. tb_free();
  337.  
  338. /* Go see if we have to retransmit. 
  339. */
  340. if (retcode = retran_lt())
  341.     return(retcode);
  342.  
  343. /* Make sure link is still up one more time 
  344. */
  345. if (!BIT1SET(LINK_EST))
  346.     return(LNK_DOWN);
  347.  
  348. /* Exit 
  349. */
  350. return(SUCCESS);
  351. }
  352.  
  353. /*LOCAL------------------------------------------------------------------------
  354.  
  355.     acking - send an LA LPDU if an ack condition is present
  356.  
  357. -----------------------------------------------------------------------------*/
  358.  
  359. SIGN_16 acking()
  360. {
  361.  
  362. SIGN_16 retcode,                /* return code */
  363.     lt_unacked;                 /* number of unacked LTs */
  364.  
  365. /* If the force ack flag is set, send an LA right away.
  366. */
  367. clr_int();                    /* protect flag access */
  368. if (BIT2SET(FORCE_ACK))            /* reset flag if set */
  369.     {
  370.     CLRBIT2(FORCE_ACK)
  371.     set_int();
  372.     return(send_la());            /* send LA and return */
  373.     }
  374. set_int();
  375.  
  376. /* If the window timer is enabled and has expired, send an LA. 
  377. */
  378. if (BIT2SET(WNDW_TIMER) && (tmr.fcw == 0))
  379.     return(send_la());
  380.  
  381. /* If there are unacknowledged LT's, it may be time to send an LA. 
  382. */
  383. if (lcb.ltrsn_acked <= lcb.lt_rsn)
  384.     lt_unacked = lcb.lt_rsn - lcb.ltrsn_acked;
  385. else
  386.     lt_unacked = (256 - lcb.ltrsn_acked) + lcb.lt_rsn;
  387.  
  388. if (lt_unacked)
  389.     {
  390.  
  391. /* If there is no user data to send (i.e. no reason to put it off)
  392. ** send an LA.
  393. */
  394.     if (sb_cnt == 0)
  395.         return(send_la());
  396.  
  397. /* If the acknowledgment threshold has been reached, send an LA.
  398. */
  399.     if (lt_unacked >= lcb.ack_threshold)
  400.         return(send_la());
  401.  
  402. /* If the ack timer has elapsed, send an LA.  Otherwise, set the timer.
  403. */
  404.     if (BIT1SET(ACK_TIMER))
  405.         {
  406.         if (tmr.ack)
  407.             return(SUCCESS);
  408.         else
  409.             return(send_la());
  410.         }
  411.     else
  412.         {
  413.         SETBIT1(ACK_TIMER)
  414.         tmr.ack = lcb.ack_timer;
  415.         return(SUCCESS);
  416.         }
  417.     }
  418.  
  419. /* If there are no unacknowledged LT's, handle the 'zero window
  420. ** opening' case.
  421. */
  422. else
  423.     {
  424.     if (BIT2SET(ZERO_WNDW) && credit_chk())
  425.         {
  426.         CLRBIT2(ZERO_WNDW)
  427.         return(send_la());
  428.         }
  429.     }
  430.  
  431. /* Exit 
  432. */
  433. return(SUCCESS);
  434. }
  435.  
  436. /*LOCAL------------------------------------------------------------------------
  437.  
  438.     attn_process - handle break signalling
  439.  
  440. -----------------------------------------------------------------------------*/
  441.  
  442. attn_process()
  443. {
  444.  
  445. SIGN_16 retcode;
  446.  
  447. /* If the LN timer is set and has expired, it is time to retransmit the
  448. ** last LN LPDU sent.  However, if the retransmission limit has been
  449. ** reached, then the link is unusable.  Terminate the link and return
  450. ** with a function value=retran limit reached.
  451. */
  452. if (BIT3SET(LN_TIMER) && (tmr.ln == 0))
  453.     {
  454.     if (lcb.ln_ret_cnt == RET_LIMIT)
  455.         {
  456.         as_disconnect(RETRAN_TMR_EXP,NULL);
  457.         return(-67);
  458.         }
  459.     if (retcode = lpdu_send(LN,NOWAIT))
  460.         return(retcode);
  461.     ++lcb.ln_ret_cnt;
  462.     SETBIT3(LN_SENT)
  463.  
  464.     clr_int();
  465.     SETBIT3(LN_TIMER)
  466.     tmr.ln=lcb.lt_tmr;
  467.     set_int();
  468.     }
  469.  
  470. /* If an LN has been received, check its type for a destructive break
  471. ** signal.  Reset the link on receipt of a destructive break.
  472. */
  473. clr_int();
  474. if (BIT3SET(LN_RECEIVED))
  475.     {
  476.     CLRBIT3(LN_RECEIVED)            
  477.     if (lcb.ln_rtype == 1)
  478.         {
  479.         link_reset();
  480.         dphase_init();
  481.         }
  482.     set_int();
  483.     if (retcode = lpdu_send(LNA,NOWAIT))
  484.         return(retcode);
  485.     }
  486. set_int();
  487.  
  488. /* Check for need to send an LNA
  489. */
  490. if (BIT3SET(FORCE_LNA))
  491.     {
  492.     CLRBIT3(FORCE_LNA)
  493.     if (retcode = lpdu_send(LNA,NOWAIT))
  494.         return(retcode);
  495.     }
  496.  
  497. /* Exit 
  498. */
  499. return(SUCCESS);
  500. }
  501.  
  502. /*LOCAL------------------------------------------------------------------------
  503.  
  504.     credit_chk - determine local ability to receive
  505.  
  506. -----------------------------------------------------------------------------*/
  507.  
  508. SIGN_16 credit_chk()
  509. {
  510.  
  511. extern USIGN_16 rb_cnt;
  512.  
  513. /* Compute the number of LT LPDUs which can be received.  This is
  514. ** the number of max sized LT's which will fit into the receive
  515. ** ring buffer.  This number can not be larger than maximum window
  516. ** (8 for this implementation).
  517. */
  518. lcb.lcl_credit = (RBUF_LEN - rb_cnt) / lcb.max_data_sz;
  519. if (lcb.lcl_credit > lcb.window_sz)
  520.     lcb.lcl_credit = lcb.window_sz;
  521.  
  522. /* Exit.  Function value is receive credit. 
  523. */
  524. return(lcb.lcl_credit);
  525. }
  526.  
  527. /*LOCAL------------------------------------------------------------------------
  528.  
  529.     dphase_init - perform data phase initialization
  530.  
  531. -----------------------------------------------------------------------------*/
  532.  
  533. dphase_init()
  534. {
  535.  
  536. SIGN_16 i;
  537.  
  538. /* Set initial credits equal to negotiated maximum credit. 
  539. */
  540. lcb.lcl_credit = lcb.rem_credit = lcb.window_sz;
  541.  
  542. /* Compute ack threshold 
  543. */
  544. lcb.ack_threshold = (i = lcb.window_sz / 2) ? i : 1;
  545.  
  546. /* Be sure that ack conditions are reset. 
  547. */
  548. CLRBIT1(LA_RECEIVED)
  549. CLRBIT2(FORCE_ACK)
  550.  
  551. /* If window == 1, lt retran timer is specified to be 8 seconds
  552. */
  553. if (lcb.window_sz == 1)
  554.     lcb.lt_tmr = 8;
  555. else
  556.     {
  557.     SETBIT2(WNDW_TIMER)
  558.     tmr.fcw = lcb.window_tmr;
  559.     }
  560. }
  561.  
  562. /*LOCAL------------------------------------------------------------------------
  563.  
  564.     link_init - perform one-time link initialization
  565.  
  566. -----------------------------------------------------------------------------*/
  567.  
  568. link_init(mnpcb)
  569.  
  570. register struct MNP_CB *mnpcb;
  571. {
  572.  
  573. /* Initialize link control block values 
  574. */
  575. lcb.status_1 = lcb.status_2 = lcb.status_3 = NULL;
  576.  
  577. ftb.num = lcb.window_sz = STRM_WNDW_SZ;
  578. lcb.max_data_sz = STRM_DATA_SZ;
  579.  
  580. lcb.prot_level = 2;
  581. lcb.srv_class = LCL_SCLASS;
  582.  
  583. lcb.ln_rsn = lcb.ln_ssn = lcb.ln_ret_cnt = tmr.ln = NULL;
  584.  
  585. switch (lcb.baud_rate = baudrate)
  586.     {
  587.     case B_1200:
  588.         lcb.lt_tmr = LTTMR_12;
  589.         lcb.window_tmr = W_TMR_12;
  590.         break;
  591.  
  592.     case B_300:
  593.         lcb.lt_tmr = LTTMR_3;
  594.         lcb.window_tmr = W_TMR_3;
  595.         break;
  596.  
  597.     case B_110:
  598.         lcb.lt_tmr = LTTMR_110;
  599.         lcb.window_tmr = W_TMR_110;
  600.         break;
  601.  
  602.     case B_2400:
  603.     default:
  604.         lcb.lt_tmr = LTTMR_24;
  605.         lcb.window_tmr = W_TMR_24;
  606.         break;
  607.     }
  608.  
  609. lcb.ack_timer = (lcb.lt_tmr/2)+1;
  610.  
  611. /* Initialize receive and transmit buffers 
  612. */
  613. rlkb.list = rlkblst;
  614. rlkb.num = 2;
  615. lkb.list = lkblst;
  616. lkb.num = 2;
  617.  
  618. init_blst(mnpcb->rlkb = &rlkb, MAX_LPDU_SZ, rlkbuff);
  619. init_blst(mnpcb->lkb = &lkb, MAX_LPDU_SZ, lkbuff);
  620.  
  621. ftb.list = iatblst;
  622. init_blst(mnpcb->ftb = &ftb,64+5, iatbuff);
  623.  
  624. /* Initialize async driver variables, too 
  625. */
  626. p_mnpcb = mnpcb;
  627. timerins();
  628. drvr_ins();
  629.  
  630. }
  631.  
  632. /*LOCAL------------------------------------------------------------------------
  633.  
  634.     link_reset - 
  635.  
  636. -----------------------------------------------------------------------------*/
  637.  
  638. link_reset()
  639. {
  640.  
  641. /* Disable interrupts while resetting the link.
  642. */
  643. clr_int();
  644.  
  645. /* Reset lcb values - note that attention sequence numbers are not
  646. ** reintialized.
  647. */
  648. lcb.lt_rsn = lcb.lt_ssn = lcb.ltrsn_acked = lcb.ltssn_acked = NULL;
  649. lcb.lt_ret_cnt = lcb.lpdu_type = NULL;
  650.  
  651. lcb.status_1 &= ~(DATA_READY | ACK_TIMER | RET_TIMER);
  652. lcb.status_2 &= ~(FORCE_ACK | FORCE_RET | ZERO_WNDW | WNDW_TIMER);
  653. lcb.status_3 &= ~(DUP_IGNORED);
  654.  
  655. /* Reset_timers 
  656. */
  657. tmr.ack = tmr.fcw = tmr.lr = tmr.lt  = NULL;
  658.  
  659. /* Reset send and receive framers 
  660. */
  661. sf_busy = sf_lt = modem_out_busy = FALSE;
  662. rdle_flg = frame_snt = frame_rcvd = frame_dne = FALSE;
  663. sf_state = SF_INIT;
  664. rf_state = RF_INIT;
  665.  
  666. /* Reset transmit and receive buffers 
  667. */
  668. reset_blst(&rb);
  669. reset_blst(&ftb);
  670. reset_blst(&lkb);
  671. reset_blst(&rlkb);
  672.  
  673. tbcnt = 0;
  674.  
  675. p_mnpcb->ld_reason = NULL;
  676.  
  677. /* Re-enable interrupts.
  678. */
  679. set_int();
  680.  
  681. }
  682.  
  683. /*LOCAL------------------------------------------------------------------------
  684.  
  685.     lpdu_send - send an LPDU other than an LT
  686.  
  687. -----------------------------------------------------------------------------*/
  688.  
  689. SIGN_16 lpdu_send(type,wait)
  690.  
  691. SIGN_16 type,
  692.     wait;
  693. {
  694.  
  695. SIGN_16 retcode;                 /* return code */
  696. struct BLST *snd_struct;            /* LPDU structure */
  697.  
  698. /* Get a buffer for the LPDU, send the LPDU, then release buffer. 
  699. */
  700. get_b(&lkb,&snd_struct);
  701. retcode = send_pdu(type,wait,snd_struct);
  702. ret_b(&lkb,snd_struct);
  703.  
  704. /* Exit 
  705. */
  706. return(retcode);
  707. }
  708.  
  709. /*LOCAL------------------------------------------------------------------------
  710.  
  711.     parse_lr - parse an LR LPDU and perform parameter negotiation
  712.  
  713. -----------------------------------------------------------------------------*/
  714.  
  715. SIGN_16 parse_lr()
  716.  
  717. {
  718.  
  719. register USIGN_8 *p;            /* header pointer */
  720. register USIGN_16 len,
  721.             *pi;
  722.  
  723. /* Initialize 
  724. */
  725. lcb.lr_parm = 0;
  726. p = (rlkb.used_lst)->bptr;
  727. len = *p++ - 2;
  728.  
  729. /* Process fixed fields 
  730. */
  731. if (*p++ != LR)
  732.     {
  733.     ret_b(&rlkb,rlkb.used_lst);
  734.     return(PROT_ERR);
  735.     }
  736.  
  737. lcb.prot_level = min(lcb.prot_level,*p);
  738. p++;
  739.  
  740. /* Process variable part 
  741. */
  742. while (len > 0)
  743.     {
  744.     if (*p == 1)            /* skip parm 1 - serial no. */
  745.         {
  746.         len -= 8;
  747.         p += 8;
  748.         continue;
  749.         }
  750.  
  751.     if (*p == 2)            /* take min of service class values */
  752.         {
  753.         len -= 3;
  754.         p += 2;
  755.         lcb.lr_parm |= LR_SRV_CLASS;
  756.         lcb.srv_class = min(LCL_SCLASS, *p);
  757.         p++;
  758.         if (lcb.srv_class == 1)
  759.             SETBIT1(HDUPLEX)
  760.         continue;
  761.         }
  762.  
  763.     if (*p == 3)            /* take min of window size */
  764.         {
  765.         len -= 3;
  766.         p += 2;
  767.         lcb.lr_parm |= LR_WNDW_SZ;
  768.         lcb.window_sz = min (lcb.window_sz, *p);
  769.         p++;
  770.         continue;
  771.         }
  772.  
  773.     if (*p == 4)
  774.         {
  775.         len -= 4;
  776.         pi = (SIGN_16 *) (p += 2);
  777.         lcb.lr_parm |= LR_DATA_SZ;
  778.         lcb.max_data_sz = max (lcb.max_data_sz, *pi);
  779.         p += 2;
  780.         continue;
  781.         }
  782.  
  783.     if (*p > 4)            /* ignore anything else */
  784.         {
  785.         len -= *++p + 2;
  786.         p += *p++;
  787.         break;
  788.         }
  789.     }
  790.  
  791. /* All done with LR in buffer, return the buffer 
  792. */
  793. ret_b(&rlkb,rlkb.used_lst);
  794.  
  795. /* Now check for parms not received and set default values 
  796. */
  797. if (!(lcb.lr_parm & LR_SRV_CLASS))
  798.     lcb.srv_class = 1;
  799.  
  800. if (!(lcb.lr_parm & LR_WNDW_SZ))
  801.     lcb.window_sz = 1;
  802.  
  803. if (!(lcb.lr_parm & LR_DATA_SZ))
  804.     lcb.max_data_sz = BLK_DATA_SZ;
  805.  
  806. /* There is such a thing as a block-mode MNP link-connection, but
  807. ** this implementation will not talk to one (block mode links are
  808. ** for use with higher-level MNP protocols). 
  809. */
  810. if (lcb.max_data_sz == BLK_DATA_SZ)
  811.     return(BAD_LR_PARMS);
  812.  
  813. /* Adjust the credit for any receive buffers already used.
  814. */
  815. lcb.lcl_credit = lcb.window_sz - rb.used;
  816.  
  817. /* Exit 
  818. */
  819. return(SUCCESS);
  820. }
  821.  
  822. /*LOCAL------------------------------------------------------------------------
  823.  
  824.     receive_wait -  wait for an LPDU during link establishment
  825.  
  826. -----------------------------------------------------------------------------*/
  827.  
  828. SIGN_16 receive_wait ()
  829. {
  830.  
  831. /* Wait for an LPDU to be received or 2 seconds to go by, which ever
  832. ** occurs first.
  833. */
  834. clr_int();
  835. return(event_wait(20,FRAME_RCV));
  836.  
  837. }
  838.  
  839. /*LOCAL------------------------------------------------------------------------
  840.  
  841.     retran_lt - handle LT LPDU retransmission
  842.  
  843. -----------------------------------------------------------------------------*/
  844.  
  845. SIGN_16 retran_lt()
  846. {
  847.  
  848. SIGN_16 i,
  849.     retcode,
  850.     not_done;
  851. register USIGN_16 lts_unacked;
  852. register struct BLST *snd_struct;
  853.  
  854. not_done = 1;
  855. while (not_done)
  856.     {
  857.  
  858. /* If there are no buffers in use, there is nothing to retransmit. 
  859. */
  860.     if (ftb.used == 0)
  861.         {
  862.         CLRBIT2(FORCE_RET)            /* reset force flag */
  863.         return(SUCCESS);            /* and just exit */
  864.         }
  865.  
  866. /* Check for forced retransmission.  If so, clear flag and go right at
  867. ** it.  Otherwise, retransmit only when retran timer set and expired.
  868. */
  869.     clr_int();
  870.     if (BIT2SET(FORCE_RET))
  871.         {
  872.         CLRBIT2(FORCE_RET)
  873.         set_int();
  874.         }
  875.     else
  876.         {
  877.         set_int();
  878.         if (!BIT1SET(RET_TIMER))
  879.                 return(SUCCESS);
  880.     if (tmr.lt)
  881.         return (SUCCESS);
  882.     }
  883.  
  884. /* It's time to retransmit. But if we have retransmitted to the limit
  885. ** count, terminate the link.
  886. */
  887.     if (lcb.lt_ret_cnt == RET_LIMIT)
  888.         {
  889.         as_disconnect(RETRAN_TMR_EXP,NULL);
  890.         return(FAILURE);
  891.         }
  892.  
  893. /* It's OK to still retransmit if there is remote credit (no need to
  894. ** check when window is only 1).
  895. */
  896.     if (lcb.window_sz == 1)
  897.         lcb.rem_credit = 0;
  898.     else
  899.         if (lcb.rem_credit == 0)
  900.             return(SUCCESS);
  901.  
  902. /* Retransmit ALL unacknowledged LT's.
  903. */
  904.     snd_struct = ftb.used_lst;
  905.     not_done--;
  906.  
  907.     if (lcb.lt_ssn >= lcb.ltssn_acked)
  908.         lts_unacked = lcb.lt_ssn - lcb.ltssn_acked;
  909.     else
  910.         lts_unacked = (256 - lcb.ltssn_acked) + lcb.lt_ssn;
  911.  
  912.     while (lts_unacked)
  913.         {
  914.         lts_unacked--;
  915.         if (retcode = send_pdu(LT,NOWAIT,snd_struct))
  916.             return(retcode);
  917.  
  918.         if (lcb.window_sz == 1) 
  919.             event_wait(100,FRAME_SND);
  920.  
  921.         if (retcode = acking())
  922.             return(retcode);
  923.         if (lcb.prot_level == 2)
  924.             {
  925.                 if (retcode = attn_process())
  926.                 return(retcode);
  927.             }
  928.  
  929.         snd_struct = snd_struct->next_b;
  930.  
  931. /* If forced retransmission, i.e., LA received, we may have received
  932. ** another LA acknowledging frames that we would retransmit next.  If
  933. ** this happened, free up acked transmit buffer(s), then go back to
  934. ** beginning.  note: if there are buffers in use, say 3 & 4, & if after
  935. ** 3 & 4 are retransmitted, we receive an LA for 3, then this logic will
  936. ** retransmit 4 again. The last 4 will be ignored by receiver as an 
  937. ** immediate duplicate.
  938. */
  939.         if (BIT2SET(FORCE_RET) || BIT1SET(LA_RECEIVED))
  940.             {
  941.             i = ftb.used;
  942.             tb_free();
  943.             if (i != ftb.used)
  944.                 {
  945. /* Something has been freed.  If all buffers were freed, then we're
  946. ** all done.  If not, reset flags and do it over again.
  947. */
  948.                     if (ftb.used)
  949.                     {
  950.                     SETBIT2(FORCE_RET)
  951.                     not_done++;
  952.                     break;
  953.                     }
  954.                     }
  955.             }
  956.         }
  957.  
  958.     if (!not_done)
  959.         {
  960.         lcb.lt_ret_cnt++;
  961.         tmr.lt = lcb.lt_tmr;
  962.         }
  963.     }
  964.     return(SUCCESS);
  965. }
  966.  
  967. /*LOCAL------------------------------------------------------------------------
  968.  
  969.     send_la - send an LA LPDU
  970.  
  971. -----------------------------------------------------------------------------*/
  972.  
  973. SIGN_16 send_la()
  974. {
  975.  
  976. SIGN_16 retcode;
  977.  
  978. /* Check for a zero window.  We want to remember sending a zero credit.
  979. ** We don't send zero credit, however, when the window is one. 
  980. */
  981. if (!credit_chk())
  982.     {
  983.     SETBIT2(ZERO_WNDW)
  984.     if (lcb.window_sz == 1)
  985.         return(SUCCESS);
  986.     }
  987.  
  988. /* Send an LA LPDU.  Return if link-connection is lost. 
  989. */
  990. if (retcode = lpdu_send(LA,NOWAIT))
  991.     return(retcode);
  992.  
  993. /* Reset ack and flow control timers. 
  994. */
  995. clr_int();
  996. CLRBIT1(ACK_TIMER)
  997. tmr.ack = NULL;
  998. tmr.fcw = lcb.window_tmr;
  999. set_int();
  1000.  
  1001. /* Exit 
  1002. */
  1003. return(SUCCESS);
  1004. }
  1005.  
  1006. /*LOCAL------------------------------------------------------------------------
  1007.  
  1008.     send_pdu - send an LPDU
  1009.  
  1010. -----------------------------------------------------------------------------*/
  1011.  
  1012. SIGN_16 send_pdu(type,wait,snd_struct)
  1013.  
  1014. SIGN_16 type,                    /* LPDU type */
  1015.     wait;                        /* wait for send to complete */
  1016. register struct BLST *snd_struct;
  1017. {
  1018.  
  1019. register USIGN_8 *p;
  1020. USIGN_8 *pli;
  1021. USIGN_16 *pi;
  1022. SIGN_16 i;
  1023.  
  1024. /* Just return if there is no physical connection. 
  1025. */
  1026. if (lne_stat())
  1027.     return(NO_PHYSICAL);
  1028.  
  1029. /* If the lpdu is an LD, then we want to expedite it.  If an lpdu is being
  1030. ** sent, wait a bit then truncate it.  This wait is necessary so that an
  1031. ** empty frame (which is illegal) is not sent. 
  1032. */
  1033. if (type == LD && sf_busy)
  1034.     {
  1035.     switch (lcb.baud_rate)
  1036.         {    
  1037.         case B_1200:
  1038.             i = 10;
  1039.             break;
  1040.  
  1041.         case B_300:
  1042.             i = 20;
  1043.             break;
  1044.  
  1045.         case B_110:
  1046.             i = 30;
  1047.             break;
  1048.  
  1049.         default:
  1050.             i = 5;
  1051.         }
  1052.  
  1053.     suspend(i);
  1054.     sf_len = 0;
  1055.     
  1056.     while (sf_busy)
  1057.         ;
  1058.     }
  1059.  
  1060. /* Wait for the send framer to finish if a frame is in progress.  
  1061. */
  1062. clr_int();
  1063. while (sf_busy)
  1064.     if (send_wait())
  1065.         return(TIME_OUT);
  1066. set_int();                    /* added 7-5-88 */
  1067.  
  1068. /* Now prepare the requested LPDU.
  1069. */
  1070. p = snd_struct->bptr;
  1071.  
  1072. switch (type)
  1073.     {
  1074.     case LT:
  1075.         break;
  1076.  
  1077.     case LA:
  1078.         *p++ = LA_LEN;
  1079.         *p++ = LA;
  1080.         *p++ = 1;
  1081.         *p++ = 1;
  1082.         clr_int();
  1083.         *p++ = lcb.ltrsn_acked = lcb.lt_rsn;
  1084.         *p++ = 2;
  1085.         *p++ = 1;
  1086.         *p  = (USIGN_8) credit_chk();
  1087.         set_int();
  1088.         break;
  1089.  
  1090.     case LN:
  1091.         *p++ = LN_LEN;
  1092.         *p++ = LN;
  1093.         *p++ = 1;
  1094.         *p++ = 1;
  1095.         *p++ = lcb.ln_ssn;
  1096.         *p++ = 2;
  1097.         *p++ = 1;
  1098.         *p = lcb.ln_stype;
  1099.         break;
  1100.  
  1101.     case LNA:
  1102.         *p++ = LNA_LEN;
  1103.         *p++ = LNA;
  1104.         *p++ = 1;
  1105.         *p++ = 1;
  1106.         *p = lcb.ln_rsn;
  1107.         break;
  1108.  
  1109.     case LR:
  1110.         pli = p++;
  1111.         *p++ = LR;
  1112.         *p++ = lcb.prot_level;
  1113.         *p++ = 1;
  1114.         *p++ = 6;
  1115.         *p++ = 1;
  1116.         *p++ = 0;
  1117.         *p++ = 0;
  1118.         *p++ = 0;
  1119.         *p++ = 0;
  1120.         *p++ = 255;
  1121.         if (BIT1SET(MODE))
  1122.             {
  1123.                 *pli = LR_ALEN;
  1124.             if (lcb.lr_parm & LR_SRV_CLASS)
  1125.                 {
  1126.                 *p++ = 2;
  1127.                 *p++ = 1;
  1128.                 *p++ = lcb.srv_class;
  1129.                 *pli += 3;
  1130.                 
  1131.                 if (lcb.lr_parm & LR_WNDW_SZ)
  1132.                     {
  1133.                         *p++ = 3;
  1134.                         *p++ = 1;
  1135.                         *p++ = lcb.window_sz;
  1136.                         *pli += 3;
  1137.             
  1138.                     if (lcb.lr_parm & LR_DATA_SZ)
  1139.                         {
  1140.                         *p++ = 4;
  1141.                         *p++ = 2;
  1142.                         pi = (USIGN_16 *) p;
  1143.                         *pi = lcb.max_data_sz;
  1144.                         *pli += 4;
  1145.                         }
  1146.                         }
  1147.                 }
  1148.                 }
  1149.         else
  1150.             {
  1151.             *pli = LR_ILEN;
  1152.             *p++ = 2;
  1153.             *p++ = 1;
  1154.             *p++ = LCL_SCLASS;
  1155.             *p++ = 3;
  1156.             *p++ = 1;
  1157.             *p++ = lcb.window_sz;
  1158.             *p++ = 4;
  1159.             *p++ = 2;
  1160.             pi = (USIGN_16 *) p;
  1161.             *pi = lcb.max_data_sz;
  1162.             }
  1163.         break;
  1164.  
  1165.     case LD:
  1166.         *p++ = LD_LEN;
  1167.         *p++ = LD;
  1168.         *p++ = 1;
  1169.         *p++ = 1;
  1170.         if ((*p = lcb.l_disc_code) == 255)
  1171.             {
  1172.             p++;
  1173.                 *p++ = 2;
  1174.                 *p++ = 1;
  1175.                 *p = lcb.u_disc_code;
  1176.                 *(snd_struct->bptr) += 3;
  1177.                 }
  1178.         break;
  1179.     }
  1180.  
  1181. /* Pause a bit if this is a class 1 connection (hardly likely...)
  1182. */
  1183. if (BIT1SET(HDUPLEX))
  1184.     suspend (20);
  1185.  
  1186. /* Set up the interrupt-driven send framer to send the lpdu.
  1187. */
  1188. clr_int();
  1189. if (type == LT)
  1190.     sf_len = snd_struct->len;
  1191. else
  1192.     sf_len = *(snd_struct->bptr) + 1;
  1193.  
  1194. sf_ptr = snd_struct->bptr;
  1195. sf_busy = TRUE;
  1196. frame_snt = FALSE;                /* added 7-15-88 */
  1197. trigger_sf();
  1198. set_int();
  1199.  
  1200. /* Wait for the lpdu to get out, if that was what the caller wanted.
  1201. */
  1202. if (wait)
  1203.     if (send_wait()) 
  1204.         return(TIME_OUT);
  1205.  
  1206. /* Exit
  1207. */
  1208. return(SUCCESS);
  1209. }
  1210.  
  1211. /*LOCAL------------------------------------------------------------------------
  1212.  
  1213.     send_wait - wait for transmission of an LPDU or timeout
  1214.     
  1215. -----------------------------------------------------------------------------*/
  1216.  
  1217. SIGN_16 send_wait()
  1218. {
  1219.  
  1220. /* Wait 55 seconds (arbitrary number which is larger than the time
  1221. ** needed to send a long LPDU), or until the LPDU is sent. If the time
  1222. ** expires and frame send has not completed, return time out.  This
  1223. ** means, effectively, that the hardware is broken.
  1224. */
  1225. clr_int();
  1226. return(event_wait(550,FRAME_SND));
  1227.  
  1228. }
  1229.  
  1230. /*LOCAL------------------------------------------------------------------------
  1231.  
  1232.     tb_free - process acknowledged LT LPDUs
  1233.  
  1234. -----------------------------------------------------------------------------*/
  1235.  
  1236. tb_free()
  1237. {
  1238.  
  1239. register struct BLST *bp;
  1240. register USIGN_16 acked_lts;        /* to hold value between 0 and 65535 */
  1241. register USIGN_16 head_ssn;
  1242.  
  1243. /* If there are no LT LPDUs unacknowledged, just clear force retransmission
  1244. ** flag and return. 
  1245. */
  1246. if (!tbcnt)
  1247.     {
  1248.     CLRBIT2(FORCE_RET)
  1249.     return;
  1250.     }
  1251.  
  1252. /* Some LT LPDU's have been sent.  However, only try to free up transmit
  1253. ** buffers if an LA has been received. 
  1254. */
  1255. clr_int();
  1256. if (BIT1SET(LA_RECEIVED))    
  1257.     {
  1258.     CLRBIT1(LA_RECEIVED)
  1259.     set_int();
  1260.  
  1261. /* Start freeing at the head of the list of buffers in use.  Free until
  1262. ** the buffer just freed contains the LT with the same seq number as
  1263. ** that of the last LT positively acked 
  1264. */
  1265.     bp = ftb.used_lst;
  1266.  
  1267.     head_ssn = (USIGN_8)*(bp->bptr + LT_SEQ);
  1268.  
  1269.     if (head_ssn <= lcb.ltssn_acked)
  1270.         acked_lts = lcb.ltssn_acked - head_ssn +1;
  1271.     else
  1272.         acked_lts = (256 - head_ssn) + lcb.ltssn_acked + 1;
  1273.  
  1274.     while (acked_lts)
  1275.         {
  1276.         ret_b(&ftb,bp);
  1277.         bp = bp->next_b;
  1278.         acked_lts--;
  1279.         tbcnt--;
  1280.         }
  1281.     if (tbcnt < 0)
  1282.         tbcnt=0;
  1283.  
  1284. /* Clear force retransmission flag 
  1285. */
  1286.     CLRBIT2(FORCE_RET)
  1287.  
  1288. /* If any LTs remain outstanding, reset the retransmission timer for them.
  1289. ** Otherwise, be sure that the timer is cancelled. Since something has been
  1290. ** acknowledged, the retransmission count can also be reset to 0. 
  1291. */
  1292.     if (tbcnt)
  1293.         {
  1294.         SETBIT1(RET_TIMER)
  1295.         tmr.lt = lcb.lt_tmr;
  1296.         ftb.used_lst = bp;
  1297.         }
  1298.     else
  1299.         {
  1300.         CLRBIT1(RET_TIMER)
  1301.         tmr.lt = 0;
  1302.         }
  1303.     lcb.lt_ret_cnt = 0;
  1304.     }
  1305. else
  1306.     {
  1307.     set_int();
  1308.         }
  1309. }
  1310.