home *** CD-ROM | disk | FTP | other *** search
/ Hacker Chronicles 2 / HACKER2.BIN / 523.L2A.C < prev    next >
Text File  |  1988-05-14  |  37KB  |  739 lines

  1. /**************************************************************************\
  2. *                                                                          *
  3. *                                                                          *
  4. *    *****                      *****                                      *
  5. *      *****                  *****                                        *
  6. *        *****              *****                                          *
  7. *          *****          *****                                            *
  8. *            *****      *****                                              *
  9. *              *****  *****                                                *
  10. *            *****      *****                                              *
  11. *          *****          *****          The Firmware. The Net.            *
  12. *        *****              *****        Portable. Compatible.             *
  13. *      *****                  *****      Public Domain.                    *
  14. *    *****                      *****    By NORD><LINK.                    *
  15. *                                                                          *
  16. *                                                                          *
  17. *                                                                          *
  18. *    L2A.C   -   Level 2, Teil 1                                           *
  19. *                                                                          *
  20. *    angelegt:      DC4OX                                                  *
  21. *    modifiziert:                                                          *
  22. *                                                                          *
  23. \**************************************************************************/
  24.  
  25.  
  26.  
  27.  
  28.  
  29. /*                                                             Includes   */
  30. /**************************************************************************/
  31.  
  32. #include "all.h"         /* allgemeine Festlegungen                       */
  33. #include "l2.h"          /* Festlegungen/Datenstrukturen fuer den Level 2 */
  34. #include "l2s.h"         /* Zugriff auf die State-Tabellen                */
  35. #include "l2ext.h"       /* globale Variable / nicht int-Funktionen       */
  36.  
  37.  
  38.  
  39.  
  40.  
  41. /**************************************************************************\
  42. *                                                                          *
  43. * "level 2"                                                                *
  44. *                                                                          *
  45. * Der Level 2. Es werden alle Level-2-internen Aktionen ausgefuehrt und    *
  46. * Meldungen an hoehere Level weitergegeben (Informationstransfer von/zum   *
  47. * Level 2 und Kommandos an den Level 2 geschehen von ausserhalb).          *
  48. *                                                                          *
  49. *                                                                          *
  50. * Der Level 2 laeuft wie folgt ab :                                        *
  51. *                                                                          *
  52. *   - Aufruf von l2init()                                                  *
  53. *                                                                          *
  54. *   - zyklisches Aufrufen von l2() und l2timr(ticks)                       *
  55. *                                                                          *
  56. *   Statusaenderungen im Level 2 (Connects, Disconnects, Failures, usw.)   *
  57. *   werden hoeheren Leveln vom Level 2 aus ueber                           *
  58. *                                                                          *
  59. *     l2tolx(<status>)  ->  l2tol3(<status>), l2tol7(<status>,lnkpoi,2)    *
  60. *                                                                          *
  61. *   mitgeteilt.                                                            *
  62. *                                                                          *
  63. *   Ein Connectwunsch wird dem Level 2 ueber das Besetzen eines leeren     *
  64. *   Linkblocks mit Quell- und Ziel- sowie Digicalls und Aufrufen von       *
  65. *   newlnk() mitgeteilt (lnkpoi zeigt auf Linkblock !).                    *
  66. *   Ein newlnk() auf einen bestehenden Link erzeugt einen Link Reset.      *
  67. *                                                                          *
  68. *   Ein Disconnectwunsch (oder bei mehrmaligem Aufruf der sofortige        *
  69. *   Disconnect) wird ueber das Setzen von lnkpoi auf den jeweiligen        *
  70. *   Linkblock und Aufruf von dsclnk() erreicht.                            *
  71. *                                                                          *
  72. *   Der Informationstransfer zum Level 2 geschieht von aussen durch        *
  73. *   Aufruf von itolnk(...), vom Level 2 durch itolx(..), welches dann      *
  74. *   fmlink() aus dem hoeheren Level aufruft.                               *
  75. *                                                                          *
  76. *   Ueber sdui(..) koennen unproto-Pakete (UI-Frames) gesendet werden.     *
  77. *                                                                          *
  78. *   Level-3-Pakete (Level-3-UI-Pakete oder Infopakete in Sequenz eines     *
  79. *   Level-2-3-Links) werden ausgefiltert und in die Level-3-Frameliste     *
  80. *   eingehaengt.                                                           *
  81. *                                                                          *
  82. \**************************************************************************/
  83.  
  84. VOID l2()
  85.   {
  86.     l2tx();                             /* der Sender                     */
  87.     l2rx();                             /* der Empfaenger                 */
  88.     l2rest();                           /* sonstiges                      */
  89.   }
  90.  
  91.  
  92.  
  93.  
  94.  
  95. /**************************************************************************\
  96. *                                                                          *
  97. * "level 2 transmitter"                                                    *
  98. *                                                                          *
  99. * Falls Infopakete zu senden sind, laut Sendefenster keine Infopakete      *
  100. * ausstehen, und laut Sendestatus auch gesendet werden duerfen, diese      *
  101. * senden.                                                                  *
  102. *                                                                          *
  103. * Frames aus Gesendet-Liste holen und in die Monitorframeliste umhaengen   *
  104. * (Firmware) oder deallokieren. Entsprechend dem Frameinhalt ggf. Timer 1  *
  105. * starten.                                                                 *
  106. *                                                                          *
  107. \**************************************************************************/
  108.  
  109. VOID l2tx()
  110.   {
  111.     unsigned    l2state;      /* aktueller Linkstate                      */
  112.     unsigned    n;            /* Laufindex                                */
  113.     MBHEAD     *sfbp;         /* Sendeframebufferpointer                  */
  114.     
  115.     for (n = 0, lnkpoi = lnktbl; n < LINKNMBR; ++n, ++lnkpoi)
  116.       if (    (l2state = lnkpoi->state) == L2SIXFER           /* duerfen  */
  117.            ||                   l2state == L2SRS              /* wir was  */
  118.            ||                   l2state == L2SDBS             /* senden ? */
  119.            ||                   l2state == L2SRSDBS
  120.          )                                                    
  121.         if (lnkpoi->VS == lnkpoi->lrxdNR)         /* nichts ausstehend ?  */
  122.           sdi(lnkpoi->k);                         /* dann Infos senden    */
  123.  
  124.     while ((sfbp = stfl.head) != &stfl)           /* Gesendetliste        */
  125.       {                                           /* aufraeumen :         */
  126.         unlink(sfbp);                             /* Frame holen          */
  127.         if ((sfbp->l2fflg & L2FT1ST) != NO)       /* ist T1 zu starten ?  */
  128.           {                                       /* ja, Zeiger auf Link- */
  129.             lnkpoi = sfbp->l2link;                /* block (zum Frame)    */
  130.             setT1();                              /* und T1 starten       */
  131.           }
  132.  
  133. #ifdef FIRMWARE
  134.         if (nmbfre > 64)                          /* falls noch genug     */
  135.           relink(sfbp,monfl.tail);                /* Platz, Frame in den  */
  136.         else                                      /* Monitor              */
  137. #endif
  138.  
  139.         dealmb(sfbp);                             /* oder deallokieren    */
  140.       }
  141.   }
  142.  
  143.  
  144.  
  145.  
  146.  
  147. /**************************************************************************\
  148. *                                                                          *
  149. * "level 2 receiver"                                                       *
  150. *                                                                          *
  151. * Alle Frames aus der RX-Frameliste holen und analysieren. Kopie an        *
  152. * Monitorliste, digipeaten oder in Level-3-Liste, falls erforderlich.      *
  153. * Auf UI-Frames antworten, falls erforderlich.                             *
  154. *                                                                          *
  155. * Reaktion entsprechend Protokoll, siehe unten.                            *
  156. *                                                                          *
  157. \**************************************************************************/
  158.  
  159. VOID l2rx()
  160.   {
  161.     char       *source;       /* Zeiger auf Quellrufzeichen/SSID          */
  162.     unsigned    l2state;      /* aktueller Level 2 Linkstatus             */
  163.     BOOLEAN     tome;         /* YES = Frame ist an mich                  */
  164.     unsigned    n;            /* Laufindex                                */
  165.     MBHEAD     *fbp;          /* Framebufferpointer lokal                 */
  166.     LNKBLK     *lblkp;        /* Linkblockpointer lokal                   */
  167.  
  168.  
  169.  
  170.     while ((fbp = rxfl.head) != &rxfl)            /* solange empfangene   */
  171.       {                                           /* Frames vorhanden     */
  172.         unlink(fbp);                              /* eins aus Liste holen */
  173.         
  174.         if (!takfhd(fbp))                         /* Kopf analysieren,    */
  175.           {                                       /* wenn nicht ok, dann  */
  176.             dealmb(fbp);                          /* wegwerfen und zum    */
  177.             continue;                             /* naechsten            */
  178.           }
  179.           
  180.         fbp->type = 2;                            /* wir sind im Level 2  */
  181.         
  182. #ifdef FIRMWARE
  183.         if (nmbfre > 64)                          /* wenn genug Platz,    */
  184.           relink(cpyfb(fbp),monfl.tail);          /* Kopie an Monitor     */
  185. #endif
  186.  
  187.         if (digipt(fbp) == YES) continue;         /* ... nur Digipeater   */
  188.  
  189.         if (rxfctl == L2CUI)                      /* UI-Frame,            */
  190.           {                                       /* wenn an mich, und    */
  191.             if (istome(rxfhdr) == YES)            /* Antwort erwuenscht,  */
  192.               if (rxfPF != NO && rxfCR != NO)     /* entsprechend         */
  193.                 xdm();                            /* beantworten          */
  194.             lnkpoi = NULL;                        /* fuer tol3sw()        */
  195.             if (!tol3sw(fbp))                     /* Level 3 UI-Frame ?   */
  196.               dealmb(fbp);                        /* nein -> weg damit    */
  197.             continue;                             /* naechstes Frame      */
  198.           }
  199.  
  200.  
  201.  
  202.         /* Haben wir einen zum Frame passenden Linkblock ?                */
  203.         /*                                                                */
  204.         /* Alle Linkbloecke durchgucken. Wenn ein aktiver Linkblock       */
  205.         /* gefunden wurde, dessen Quellcall mit dem Framezielcall         */
  206.         /* uebereinstimmt, tome auf TRUE setzen. Wenn auch noch Blockport */
  207.         /* mit Frameport und Blockzielcall mit Framequellcall             */
  208.         /* uebereinstimmen, dann ist der aktive passende Link gefunden,   */
  209.         /* Schleife abbrechen.                                            */
  210.         /*                                                                */
  211.         /* Falls ein Link inaktiv ist, aber das Framezielcall an mich     */
  212.         /* (Call + SSID oder Ident mit beliebiger SSID) ist, oder das     */
  213.         /* Blockquellcall mit dem Framezielcall uebereinstimmt, dann      */
  214.         /* Blockadresse in lblkp merken. Es wird nur der erste solche     */
  215.         /* Block genommen.                                                */
  216.  
  217.         for ( tome = NO, lblkp = NULL, n = 0, lnkpoi = lnktbl;
  218.               n < LINKNMBR;
  219.               ++n, ++lnkpoi
  220.             )
  221.           if (lnkpoi->state != L2SDSCED)
  222.             {
  223.               if (cmpid(lnkpoi->srcid,rxfhdr) == TRUE)
  224.                 {
  225.                   tome = YES;
  226.                   if (    lnkpoi->liport == rxfprt
  227.                        && cmpid(lnkpoi->dstid,rxfhdr + L2IDLEN) == TRUE
  228.                      ) break;
  229.                 }
  230.             }
  231.           else
  232.             if (    !lblkp
  233.                  && (    (    *lnkpoi->srcid == '\0'
  234.                            && istome(rxfhdr) == TRUE
  235.                          )
  236.                       || (    *lnkpoi->srcid != '\0'
  237.                            && cmpid(lnkpoi->srcid,rxfhdr) == TRUE
  238.                          )
  239.                     )
  240.                ) lblkp = lnkpoi;
  241.  
  242.  
  243.  
  244.         if (n == LINKNMBR)                   /* wenn kein aktiver Link    */
  245.           if (lblkp)                         /* passst, aber inaktiver    */
  246.             lnkpoi = lblkp;                  /* Link, dann diesen nehmen  */
  247.           else
  248.             {                                /* sonst, wenn trotzdem das  */
  249.               if (    tome == YES            /* Frame an mich gerichtet   */
  250.                    || istome(rxfhdr) == TRUE /* ist, reagieren :          */
  251.                  )
  252.                 {
  253.                   if (rxfctl == L2CSABM)     /* SABM mit DM beantworten   */
  254.                     {                        /* und hoeheren Leveln       */
  255.                       l2tolx(L2MBUSYT);      /* melden                    */
  256.                       xdm();
  257.                     }
  258.                   else                       /* sonst nur antworten, wenn */
  259.                     if (    rxfPF != 0       /* Command mit Poll, dann    */
  260.                          && rxfCR != 0       /* mit DM antworten          */
  261.                        ) xdm();
  262.                     else                     /* oder wenn kein Command    */
  263.                       if (rxfctl == L2CDISC) /* Poll, aber ein DISC, mit  */
  264.                         xua();               /* UA antworten              */
  265.                 }
  266.               dealmb(fbp);                   /* empfangenes Frame weg-    */
  267.               continue;                      /* werfen und zum naechsten  */
  268.             }
  269.                 
  270.  
  271.  
  272.         /* Falls Timer 3 aktiv, diesen neu setzen, es ist wieder          */
  273.         /* Aktivitaet auf dem Link                                        */
  274.  
  275.         if (lnkpoi->T3 != 0) setT3();
  276.  
  277.  
  278.         l2state = lnkpoi->state;        /* Linkstatus zur Abfrage         */
  279.         
  280.         if (!(rxfctl & L2CNOIM))        /* I-Frame ?                      */
  281.           {
  282.           
  283.             /* I-Frame :                                                  */
  284.             /*                                                            */
  285.             /* Nur annehmen, wenn empfangene N(R) des Frames ok,          */
  286.             /* srxdNR(), und das I-Frame das naechste erwartete in der    */
  287.             /* Sequenz ist, isntxi().                                     */
  288.             /* Wenn alles ok, Laenge pruefen und ggf. auf falsche Laenge  */
  289.             /* mit Frame-Reject reagieren, sonst Antwort entsprechend     */
  290.             /* Statetable und I-Frame verarbeiten.                        */
  291.  
  292.             if (    srxdNR() == TRUE                   /* N(R) ok ?       */
  293.                  && isnxti() == TRUE                   /* erwartet ?      */
  294.                )
  295.               if (fbp->mbpc - fbp->mbgc <= 257)        /* Laengenpruefung */
  296.                 {
  297.                   l2stma(!rxfPF ? stbl01 : stbl00);    /* Statetable      */
  298.  
  299.                   /* Linkzustand I-Transfer moeglich und nicht busy ? */
  300.  
  301.                   if (l2state >= L2SIXFER && !(lnkpoi->flag & L2FBUSY))
  302.                     {
  303.  
  304.                       /* wenn Level-3-I-Paket, dann in Level-3-RX-Liste   */
  305.                       /* einhaengen und Link als Level-3-Link markieren,  */
  306.                       /* No-Activity-Timeout neu starten                  */
  307.  
  308.                       if (tol3sw(fbp) == YES)
  309.                         {
  310.                           lnkpoi->flag |= L2FL3LNK;
  311.                           lnkpoi->noatou = ininat;
  312.                         }
  313.                       else
  314.  
  315.                         /* wenn normales Level-2-I-Paket, wenn nicht Busy */
  316.                         /* oder Level-3-Link, I annehmen und in           */
  317.                         /* Linkempfangsliste einhaengen                   */
  318.  
  319.                         if (!(lnkpoi->flag & (L2FDSLE | L2FL3LNK)))
  320.                           {
  321.                             relink(fbp,lnkpoi->rcvdil.tail);
  322.                             ++lnkpoi->rcvd;
  323.                           }
  324.                         else
  325.                           dealmb(fbp);  /* ansonsten Paket wegwerfen      */
  326.                       continue;         /* auf zum naechsten Paket        */
  327.                     }
  328.                 }
  329.               else                      /* Frame zu lang :                */
  330.                 sdfrmr(0x03);           /* "U/S-Frame mit unerlaubtem     */
  331.                                         /* Infofeld"                      */
  332.           }
  333.  
  334.  
  335.  
  336.         else                                 /* kein I-Frame :            */
  337.           if (!(rxfctl & L2CNOSM))
  338.             {
  339.             
  340.               /* S-Frame :                                                */
  341.               /*                                                          */
  342.               /* Nur annehmen, wenn empfangene N(R) des Frames ok,        */
  343.               /* srxdNR(), und wenn das Frame kein Infofeld enthaelt.     */
  344.               /*                                                          */
  345.               /* Auf RR, RNR, REJ entsprechend Statetable antworten, auf  */
  346.               /* andere mit Frame-Reject antworten.                       */
  347.  
  348.               if (srxdNR() == YES)                     /* N(R) ok ?       */
  349.                 if (fbp->mbgc == fbp->mbpc)            /* kein I-Feld ?   */
  350.                   switch ((rxfctl >> 2) & 0x03)
  351.                     {
  352.                     
  353.                       case 0 :                         /* L2CRR >> 2      */
  354.                         l2stma(   !rxfCR
  355.                                 ? (!rxfPF ? stbl11 : stbl10)
  356.                                 : (!rxfPF ? stbl03 : stbl02)
  357.                                );
  358.                       break;
  359.                       
  360.                       case 1 :                         /* L2CRNR >> 2     */
  361.                         l2stma(   !rxfCR
  362.                                 ? (!rxfPF ? stbl15 : stbl14)
  363.                                 : (!rxfPF ? stbl07 : stbl06)
  364.                                );
  365.                       break;
  366.                       
  367.                       case 2 :                         /* L2CREJ >> 2     */
  368.                         l2stma(   !rxfCR
  369.                                 ? (!rxfPF ? stbl13 : stbl12)
  370.                                 : (!rxfPF ? stbl05 : stbl04)
  371.                                );
  372.                         if (l2state >= L2SIXFER) sdoi();
  373.                       break;
  374.                       
  375.                       default :
  376.                         sdfrmr(0x01);   /* "Kontrollfeld falsch oder      */
  377.                       break;            /* nicht implementiert"           */
  378.                       
  379.                     } /* end switch ((rxfctl >> 2) & 0x03) */
  380.                 else
  381.                   sdfrmr(0x03);         /* "U/S-Frame mit unerlaubtem     */
  382.                                         /* Infofeld"                      */
  383.             } /* end S-Frame */
  384.  
  385.  
  386.             
  387.           else                               /* kein I- oder S-Frame :    */
  388.             if ((rxfctl & 0xFF) != L2CFRMR)
  389.  
  390.               /* Kein FRMR-Frame, Frame nur annehmen, wenn kein Infofeld  */
  391.               /* vorhanden.                                               */
  392.               /*                                                          */
  393.               /* Frame auswerten, reagieren, nach Statetable antworten.   */
  394.  
  395.               if (fbp->mbgc == fbp->mbpc)
  396.                 switch (rxfctl)
  397.                   {
  398.  
  399.  
  400.  
  401.                     case L2CSABM :             /* neuer Link / Linkreset  */
  402.                       lnkpoi->V2link = rxfV2;  /* Protokollversion merken */
  403.                       switch (l2state)
  404.                         {                      /* neuer Link (Connect) ?  */
  405.                           case L2SDSCED :
  406.                             if (    fvalca(VCpar,rxfhdr + L2IDLEN) == TRUE
  407.                                  && nmblks < Ypar
  408.                                  && nmbfre > 128       /* annehmbar ?     */
  409.                                )
  410.                               {
  411.                                 inilnk();              /* ja, Link init.  */
  412.                                 ++nmblks;              /* neuer Link      */
  413.                                 l2tolx(L2MCONNT);      /* melden          */
  414.                                 lnkpoi->noatou = ininat;
  415.                                 break;                 /* -> Statetable   */
  416.                               }
  417.                             l2tolx(L2MBUSYT);          /* nein, melden    */
  418.                             xdm();                     /* mit DM antwort. */
  419.                             dealmb(fbp);               /* Frame vergessen */
  420.                             continue;                  /* naechstes Paket */
  421.                           break;
  422.                           
  423.                           case L2SLKSUP :              /* beide connecten */
  424.  
  425.                             /* anderer Weg als selbst benutzt ? */
  426.  
  427.                             if ( !cmpidl(   cmpid(rxfhdr + L2IDLEN,
  428.                                                   lnkpoi->srcid) == TRUE
  429.                                           ? rxfhdr + L2ILEN
  430.                                           : txfhdr + L2ILEN,
  431.                                           lnkpoi->viaidl
  432.                                         )
  433.                                )
  434.                               {
  435.                                 clrlnk();                   /* ja, alles  */
  436.                                 l2tolx(L2MBUSYF);           /* abbrechen  */
  437.                                 xdm();
  438.                                 lnkpoi->state = L2SDSCED;
  439.                                 dealmb(fbp);
  440.                                 continue;
  441.                               }
  442.                             else
  443.                               {
  444.                                 reslnk();                   /* nein,      */
  445.                                 l2tolx(L2MCONNT);           /* gelungener */
  446.                                 lnkpoi->noatou = ininat;    /* Connect    */
  447.                               }
  448.                           break;
  449.                           
  450.                           case L2SDSCRQ :         /* sind ge-disct, Link  */
  451.                             mclrlk();             /* aufloesen und melden */
  452.                           break;
  453.                           
  454.                           default :               /* normaler Linkreset   */
  455.                             inilnk();             /* vom Partner          */
  456.                             l2tolx(L2MLRESF);
  457.                           break;
  458.                              
  459.                         } /* end switch (l2state) */
  460.                       l2stma(stbl08);             /* SABM EITHER COMMAND  */
  461.                     break;
  462.  
  463.  
  464.  
  465.                     case L2CDISC :
  466.                       if (!l2state)               /* Link aktiv ?         */
  467.                         {
  468.                           if (    rxfPF != 0      /* nein, wenn Command   */
  469.                                && rxfCR != 0      /* mit Poll, dann mit   */
  470.                              ) xdm();             /* DM antworten         */
  471.                           else
  472.                             xua();                /* sonst mit UA         */
  473.                           dealmb(fbp);            /* Frame wegwerfen      */
  474.                           continue;               /* naechstes Paket      */
  475.                         }
  476.                       else                        /* ja,                  */
  477.                         if (l2state == L2SLKSUP)  /* wenn im Linkaufbau,  */
  478.                           {                       /* dann Link sofort     */
  479.                             clrlnk();             /* aufloesen und melden */
  480.                             l2tolx(L2MBUSYF);
  481.                           }
  482.                         else                      /* sonst erst restliche */
  483.                           {                       /* I-Frames an hoeheren */
  484.                             i2tolx(YES);          /* Level geben und dann */
  485.                             mclrlk();             /* Link loesen / melden */
  486.                           }
  487.                       l2stma(stbl09);             /* DISC EITHER COMMAND  */
  488.                     break;
  489.  
  490.  
  491.  
  492.                     case L2CUA :
  493.                       if (l2state < L2SRS)             /* V1-Zustand ?    */
  494.                         {
  495.                           if (l2state == L2SLKSUP)     /* ja, wenn im     */
  496.                             {                          /* Link-Setup      */
  497.                               lnkpoi->V2link = rxfV2;  /* Protokollvers.  */
  498.                               reslnk();                /* uebernehmen,    */
  499.                               l2tolx(L2MCONNT);        /* Link neu und    */
  500.                               lnkpoi->noatou = ininat; /* melden          */
  501.                             }
  502.                           else                         /* sonst wenn im   */
  503.                             if (l2state == L2SDSCRQ)   /* Disc-Request    */
  504.                                mclrlk();               /* Link aufloesen  */
  505.                         }
  506.                       else
  507.                         {
  508.                           reslnk();                    /* nein, Linkreset */
  509.                           l2tolx(L2MLREST);            /* ausf. / melden  */
  510.                         }
  511.                       l2stma(stbl16);             /* UA EITHER RESPONSE   */
  512.                     break;
  513.  
  514.  
  515.  
  516.                     case L2CDM :
  517.                       if (l2state)                /* wenn Link aktiv ...  */
  518.                         if (l2state == L2SLKSUP)  /* wenn DM beim Link-   */
  519.                           {                       /* Setup, dann Link     */
  520.                             clrlnk();             /* sofort aufloesen und */
  521.                             l2tolx(L2MBUSYF);     /* "Busy from" melden   */
  522.                           }
  523.                         else                      /* sonst Link aufloesen */
  524.                           mclrlk();               /* mit Meldung          */
  525.                       l2stma(stbl17);             /* DM EITHER RESPONSE   */
  526.                     break;
  527.                     
  528.  
  529.  
  530.                     default :           /* unbekanntes Kontrollfeld :     */
  531.                       sdfrmr(0x01);     /* "Kontrollfeld falsch oder      */
  532.                     break;              /* nicht implementiert"           */
  533.  
  534.  
  535.  
  536.                   } /* end switch (rxfctl) */
  537.               else                                /* Frametyp unbekannt   */
  538.                 sdfrmr(0x03);                     /* "U/S-Frame mit un-   */
  539.                                                   /* erlaubtem Infofeld"  */
  540.  
  541.  
  542.  
  543.             else /* from if (rxfctl != L2CFRMR) */
  544.               {
  545.               
  546.                 /* FRMR-Frame :                                           */
  547.                 /*                                                        */
  548.                 /* Wird nur im Frame-Reject-Zustand oder bei moeglichem   */
  549.                 /* Informationstransfer angenommen.                       */
  550.                 /* Es werden die FRMR-Infobytes gelesen, FRMR an die      */
  551.                 /* hoeheren Level gemeldet, nach Statetable geantwortet.  */
  552.  
  553.                 if (l2state >= L2SIXFER || l2state == L2SFRREJ)
  554.                   {
  555.                     /* FRMR-Infobytes im Linkblock merken */
  556.                     for (source = lnkpoi->frmr, n = 0; n < 3; ++n)
  557.                       *source++ = (fbp->mbgc < fbp->mbpc) ? getchr(fbp) : 0;
  558.                     l2tolx(L2MFRMRF);
  559.                   }
  560.                 l2stma(stbl18);                   /* FRMR EITHER RESPONSE */
  561.  
  562.               }
  563.         
  564.  
  565.       
  566.         dealmb(fbp);          /* aktuelles Frame verarbeitet, wegwerfen   */
  567.              
  568.       } /* end while ((fbp = rxfl.head) != &rxfl) */
  569.   }
  570.  
  571.  
  572.  
  573.  
  574.  
  575. /**************************************************************************\
  576. *                                                                          *
  577. * "level 2 rest"                                                           *
  578. *                                                                          *
  579. * Fuer alle aktiven Links Busyzustand pruefen/setzen/aufloesen, I-Pakete   *
  580. * unter Beruecksichtigung der "Erstickungskontrolle" an hoehere Level      *
  581. * weiterreichen. Fall Zustand "Disconnecten nach Uebertragung der          *
  582. * restlichen I-Pakete" und keine I-Pakete mehr zu senden, Disconnect       *
  583. * einleiten.                                                               *
  584. * Muellbufferliste frei machen (aus Interruptroutinen entstandener Muell,  *
  585. * der besser ausserhalb der Interrupts deallokiert wird aus Zeitgruenden). *
  586. *                                                                          *
  587. \**************************************************************************/
  588.  
  589. VOID l2rest()
  590.   {
  591.     unsigned n;
  592.  
  593.  
  594.     for (n = 0, lnkpoi = lnktbl; n < LINKNMBR; ++n, ++lnkpoi)
  595.       if (lnkpoi->state != L2SDSCED)
  596.         {
  597.         
  598.           /* fuer alle aktiven (= nicht disconnecteten) Links : */
  599.  
  600.  
  601.           txfV2 = lnkpoi->V2link;                  /* Protokollversion    */
  602.  
  603.           /* wenn Zustand "nachdem alle restliche I's uebertragen wurden, */
  604.           /* disconnecten" und alle I's uebertragen, DISC einleiten       */
  605.  
  606.           if (    ((lnkpoi->flag & L2FDSLE) != NO)
  607.                && !lnkpoi->tosend
  608.              ) disc();
  609.  
  610.           /* sonst empfangene I-Pakete an hoeheren Level uebertragen und  */
  611.           /* Busy-Condition pruefen / setzen / aufheben                   */
  612.           /*                                                              */
  613.           /* "Busy werden"      -   weniger als 80 Freibuffer             */
  614.           /*                        oder so viele I-Pakete empfangen und  */
  615.           /*                        nicht abgeholt, wie                   */
  616.           /*                        "Erstickungszaehler" conctl angibt    */
  617.           /*                                                              */
  618.           /* "Busy aufloesen"   -   wieder mehr als 112 Freibuffer        */
  619.           /*                        und weniger als halb so viele         */
  620.           /*                        empfangen und nicht abgeholt wie      */
  621.           /*                        conctl angibt                         */
  622.  
  623.           else
  624.             {
  625.               i2tolx(NO);
  626.               if (!(lnkpoi->flag & L2FBUSY))     /* nicht busy            */
  627.                 {
  628.                   if (nmbfre < 80 || lnkpoi->rcvd >= conctl)
  629.                     {
  630.                       lnkpoi->flag |= L2FBUSY;   /* busy werden           */
  631.                       l2stma(stbl21);            /* STATION BECOMES BUSY  */
  632.                     }
  633.                 }
  634.               else
  635.                 if (nmbfre > 112 && lnkpoi->rcvd < conctl/2)
  636.                   {
  637.                     lnkpoi->flag &= ~L2FBUSY;    /* "busy" aufloesen      */
  638.                     l2stma(stbl22);              /* BUSY CONDITION CLEARS */
  639.                   }
  640.             }     
  641.         } /* end if (lnkpoi->state) */
  642.  
  643.     dealml(&trfl);                      /* Muellbufferliste frei machen   */
  644.   }
  645.  
  646.  
  647.  
  648.  
  649.  
  650. /**************************************************************************\
  651. *                                                                          *
  652. * "level 2 timer"                                                          *
  653. *                                                                          *
  654. * Ausfuehren der Level-2-Millisekundentimer 1, 2, 3 in allen aktiven       *
  655. * Links (herunterzaehlen und bei Ablauf reagieren).                        *
  656. * In ticks wird die Anzahl der vergangenen 10ms-Intervalle (Ticks) seit    *
  657. * dem letzten Aufruf dieser Routine angegeben.                             *
  658. *                                                                          *
  659. \**************************************************************************/
  660.  
  661. VOID l2timr(ticks)
  662.  
  663. unsigned ticks;
  664.  
  665.   {
  666.     unsigned n;
  667.     
  668.  
  669.     for (n = 0, lnkpoi = lnktbl; n < LINKNMBR; ++n, ++lnkpoi)
  670.       if (lnkpoi->state != L2SDSCED)
  671.         {
  672.         
  673.           /* fuer alle aktiven (= nicht disconnecteten) Links : */
  674.  
  675.  
  676.           txfV2 = lnkpoi->V2link;       /* Merker ob Version-2-Protokoll  */
  677.  
  678.           if (lnkpoi->T1 != 0)          /* wenn Timer 1 aktiv ...         */
  679.             if (lnkpoi->T1 <= ticks)    /*   wenn Timer 1 abgelaufen ...  */
  680.               {
  681.                 lnkpoi->T1 = 0;         /*   ... Timer 1 stoppen          */
  682.                 setT3();                /*   Timer 3 neu starten          */
  683.                 ++lnkpoi->tries;        /*   Retryzaehler                 */
  684.                 if (    !lnkpoi->N2
  685.                      || lnkpoi->tries < lnkpoi->N2 /* zu viele Retries ?  */
  686.                    )
  687.                   if (    lnkpoi->V2link == YES    /* nein, bei V2 oder   */
  688.                        || lnkpoi->state < L2SIXFER /* V1-Status < IXFER   */
  689.                      ) l2stma(stbl23);             /* Statet. T1 EXPIRES  */
  690.                   else                             /* sonst ausstehende   */
  691.                     sdoi();                        /* I's senden          */
  692.                 else
  693.                   {                                /* zu viele Retries :  */
  694.                     lnkpoi->tries = 0;             /* Retryzaehler leer   */
  695.                     clrlnk();                      /* Link sofort loesch. */
  696.                     l2tolx(L2MFAILW);              /* "Link failure"      */
  697.                     lnkpoi->state = L2SDSCED;      /* DISCONNECTED        */
  698.                   }
  699.               }
  700.             else
  701.               lnkpoi->T1 -= ticks;      /*   sonst herunterzaehlen        */
  702.               
  703.           if (lnkpoi->T2 != 0)          /* wenn Timer 2 aktiv ...         */
  704.             if (lnkpoi->T2 <= ticks)    /*   wenn Timer 2 abgelaufen ...  */
  705.               lnkpoi->T2 = 0;           /*   ... Timer 2 stoppen          */
  706.             else
  707.               lnkpoi->T2 -= ticks;      /*   sonst herunterzaehlen        */
  708.  
  709.           if (    !lnkpoi->T2           /* wenn Timer 2 abgelaufen ist    */
  710.                && lnkpoi->RStype != 0   /* und Response zu senden ist     */
  711.                && !iscd(lnkpoi->liport) /* und der Kanal frei ist ...     */
  712.              )
  713.             {
  714.               stxfad();                 /* ... dann Responseframe bauen   */ 
  715.               txfCR = txfPF = 0;
  716.               txfctl = setNR(   !(lnkpoi->flag & L2FBUSY)
  717.                               ? lnkpoi->RStype
  718.                               : L2CRNR
  719.                            );
  720.               sdl2fr(makfhd(L2FUS));    /* und senden                     */
  721.               lnkpoi->RStype = 0;       /* Responsemodus loeschen         */
  722.             }
  723.  
  724.           if (lnkpoi->T3 != 0)          /* wenn Timer 3 aktiv ...         */
  725.             if (lnkpoi->T3 <= ticks)    /*   wenn Timer 3 abgelaufen ...  */
  726.               {
  727.                 clrT3();                /*   ... Timer 3 stoppen und      */
  728.                 l2stma(stbl24);         /*       Statetable T3 EXPIRES    */  
  729.               }                         /*       ausfuehren               */
  730.             else
  731.               lnkpoi->T3 -= ticks;      /*   sonst herunterzaehlen        */
  732.  
  733.         }
  734.   }
  735.  
  736.  
  737.  
  738. /* Ende von L2A.C */
  739.