*COMDECK X25XMIT
_$J+? 
_ 
  
  
  
                 XX      XX        222222    5555555555 
                  XX    XX        22222222   5555555555 
                   XX  XX        22      22  55 
                    XXXX                 22  55 
                     XX            2222222    5555555 
                     XX           2222222      5555555
                    XXXX         22                  55 
                   XX  XX        22          55      55 
                  XX    XX   ..  2222222222   55555555
                 XX      XX  ..  2222222222    555555 
  
  
  
       XX      XX              MM      MM    IIIIII    TTTTTTTTTT 
        XX    XX               MMM    MMM    IIIIII    TTTTTTTTTT 
         XX  XX                MMMM  MMMM      II          TT 
          XXXX                 MM MMMM MM      II          TT 
           XX       --------   MM  MM  MM      II          TT 
           XX       --------   MM      MM      II          TT 
          XXXX                 MM      MM      II          TT 
         XX  XX                MM      MM      II          TT 
        XX    XX               MM      MM    IIIIII        TT 
       XX      XX              MM      MM    IIIIII        TT 
  
  
  
       FFFFFFFFFF  RRRRRRRR      AAAAAA    MM      MM  EEEEEEEEEE 
       FFFFFFFFFF  RRRRRRRRR    AAAAAAAA   MMM    MMM  EEEEEEEEEE 
       FF          RR      RR  AA      AA  MMMM  MMMM  EE 
       FF          RR      RR  AA      AA  MM MMMM MM  EE 
       FFFFFFFF    RRRRRRRRR   AA      AA  MM  MM  MM  EEEEEEEE 
       FFFFFFFF    RRRRRRRR    AAAAAAAAAA  MM      MM  EEEEEEEE 
       FF          RR   RR     AAAAAAAAAA  MM      MM  EE 
       FF          RR    RR    AA      AA  MM      MM  EE 
       FF          RR     RR   AA      AA  MM      MM  EEEEEEEEEE 
       FF          RR      RR  AA      AA  MM      MM  EEEEEEEEEE 
  
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
*                                                                     * 
*                              PX25XMIT                               * 
*                                                                     * 
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
? 
_$I+    NON-INTERRUPTABLE?
_$J+? 
_ 
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
*                                                                     * 
** OVERVIEW:                                                          * 
*              THIS MODULE TRANSMITS A FRAME AT TIME.  IT             * 
*              TRIES TO OUTPUT A SUPERVISORY OR PROTOCOL              * 
*              FRAME IF THERE IS ANY SUCH FRAME AVAILABLE,            * 
*              IF NOT OUTPUTS AN I-FRAME.                             * 
*              PX25XMIT IS CALLED BY OPS LEVEL AND MUX LEVEL          * 
*              X.25 ROUTINES.  MUX LEVEL CALLS IT FOR THE             * 
*              RECEIPT OF THE OUTPUT BUFFER TRANSMITTED               * 
*              (MMOBUX) WORKLIST.                                     * 
*                                                                     * 
** INPUT:                                                             * 
*              XTLCB      : ADDRESS OF LCB                            * 
*              X2WKCD     : WORKCODE BY PX25TRANS                     * 
*                                                                     * 
** CALLING PROGRAMS :                                                 * 
*                                                                     * 
*              PX25MUX   : MUX LEVEL X.25 PROGRAM.                    * 
*              PX2GPF    : GENERATE PROTOCOL FRAME.                   * 
*                          (LEVEL 2 PROCEDURE IN PX25TRANS)           * 
*              PX25TRANS : MAIN PROGRAM.                              * 
*                                                                     * 
** OUTPUT:                                                            * 
*              X2FRPTR  : OUTPUT FRANE.                               * 
*                                                                     * 
** EXTERNAL SUBROUTINES:                                              * 
*                                                                     * 
*              PBTMRSRCS : TIMER SERVICE.                             * 
*              PMCDRV    : COMMAND DRIVER.                            * 
*                                                                     * 
** NOTES:                                                             * 
*                                                                     * 
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
? 
PROCEDURE PX25XMIT (XTLCB : BZLCBP; X2WKCOD : INTEGER); 
  
CONST 
*CALL X25CON01
  
      X7DOWN  = 1;                          _LINK DOWN                 ?
_ 
* * * *  PRIMARY STATES DEFINITION
? 
      X8ERROR = 0;                          _ERROR                     ?
      X8OPER  = 1;                          _OPERATIONAL               ?
      X8RBUSY = 2;                          _REMOTE BUSY               ?
      X8RCOVR = 3;                          _RECOVERY STATE            ?
      X8RESET = 4;                          _RESET STATE               ?
  
TYPE
       X25BUFFER = PACKED RECORD
  
                     XBSP1 : INTEGER;       _BUFFER FCD/LCD            ?
                     XBSP2 : INTEGER;       _BUFFER FLAG               ?
                     XBSP3 : INTEGER;       _QCHAIN                    ?
                     XBSP4 : B011BITS;      _NOT IN USE                ?
                     XBT1  : BOOLEAN;       _START T1 TIMER            ?
                     XBSP5 : B04BITS;       _NOT IN USE                ?
  
                     CASE X9TAG1 : INTEGER OF 
  
                       1: (XFA   : B08BITS; _ADDRESS FIELD             ?
                           XFNR  : B03BITS; _N(R)                      ?
                           XFPF  : BOOLEAN; _POOL/FINAL BIT            ?
                           XFNS  : B03BITS; _N(S)                      ?
                           XFSP1 : B01BIT); _NOT IN USE                ?
  
                       2: (XFSP2 : B08BITS; 
                           XFTYP : B08BITS);_FRAME TYPE                ?
                     END; _X25BUFFER? 
  
      X5BUFPTR = 'X25BUFFER;
  
      X0BUFPTR = PACKED RECORD
                 CASE X9TAG2 : INTEGER OF 
  
                   1: (X1BFPTR : B0BUFPTR); _GOLBAL ACCESS             ?
                   2: (X2BFPTR : X5BUFPTR); _X25 BUFFER ACCESS         ?
                   3: (X3BFPTR : B7PKTPTR); _TIMER PACKET ACCESS       ?
                 END; _X0BUFPTR?
  
VAR 
      X2FRPTR  : X0BUFPTR;                  _BUFFER POINTER            ?
      X2TIMPTR : X0BUFPTR;                  _TIMRE PACKET              ?
      X2CMDPKT : NKINCOM;                   _MUX COMMAND PACKET        ?
      X2VR     : INTEGER; 
      X2VS     : INTEGER; 
      X2ADDR   : ARRAY [BOOLEAN] OF INTEGER;
  
VALUE 
      X2ADDR   = (1,                        _ADDRESS A                 ?
                  3);                       _ADDRESS B                 ?
  
BEGIN 
WITH XTLCB'.BZSLCBPTR'.BZXSLCB DO           _SUB LCB POINTER           ?
  BEGIN 
  BZLOCK := FALSE;
  IF   BZHSTATE " X7DOWN                    _IS LINK DOWN              ?
  THEN
    IF BZOON = FALSE                        _IS OUTPUT IN PROGRESS     ?
    THEN
      BEGIN 
      X2FRPTR.X1BFPTR := BZSFQR;            _GET FIRST FRAME IN QUEUE  ?
      IF X2FRPTR.X1BFPTR " NIL              _SUP FRAME AVAILABLE       ?
      THEN
        BZSFQR := X2FRPTR.X1BFPTR'.         _ASSIGN NEXT SUP FRAME     ?
                         BCCHAINS[QCHN];    _ IN QUEUE                 ?
      IF X2FRPTR.X1BFPTR = NIL              _NONE FOUND                ?
      THEN
        BEGIN 
  
        CASE BZPSTATE OF                    _PRIMARY STATE             ?
  
          X8OPER:                           _OPERATIONAL               ?
            BEGIN 
            IF BZRXMT 
            THEN
              X2FRPTR.X1BFPTR := BZFRQ[BZVS]  _NEXT TO RE-XMIT         ?
            ELSE
              BEGIN                         _NORMAL XMISSION STATE     ?
              IF BZIFQR " NIL               _FRAMES IN QUEUE           ?
              THEN
                IF BZVS " ((BZLNRR + BZK) MOD 8)   _WINDOW IS OPENED   ?
                THEN
                  BEGIN 
                  X2FRPTR.X1BFPTR := BZIFQR;    _GET NEXT IN QUEUE     ?
                  BZFRQ[BZVS]     := X2FRPTR.   _SAVE IT IN RETENTION  ?
                                       X1BFPTR; _ QUEUE                ?
                  BZIFQR   := BZIFQR'.          _UNCHAIN IT FROM FRAME ?
                                BCCHAINS[QCHN]; 
  
_***? IF BZFRMCNT = 0 
_***? THEN
_***?   PBHALT ($DEAD); 
  
                  BZFRMCNT := BZFRMCNT - 1;     _UPDATE COUNT          ?
                  END;
              END; _ IF BZRXMT                                         ?
            END; _ X8OPER                                              ?
  
          X8RCOVR:                          _RECOVERY STATE            ?
            IF X2WKCOD = T1TIMER            _T1 TIMER EXPIRED          ?
            THEN
              BEGIN 
              X2FRPTR.X1BFPTR := BZFRQ[BZLNRR];  _START RE-XMIT        ?
              END;
  
          END; _ CASE BZPSTATE                                         ?
_ 
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
*                                                                     * 
*        BUILD I FRAME                                                * 
*                                                                     * 
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
? 
        IF X2FRPTR.X1BFPTR " NIL            _FRAME WAS FOUND           ?
        THEN
          WITH X2FRPTR.X2BFPTR' DO          _FRAME HEADER              ?
            BEGIN 
            X2FRPTR.X1BFPTR'.BFFCD := 8;
            X2VR   := BZVR;                 _GET V(R)                  ?
            BZLNRS := X2VR;                 _UPDATE LAST N(R)          ?
  
            CASE BZPSTATE OF                _PRIMARY STATE             ?
  
              X8OPER:                       _OPERATIONAL               ?
                BEGIN 
                X2VS := BZVS;               _CURRENT V(S)              ?
                BZVS := X2VS + 1;           _UPDATE V(S)               ?
                END; _ X8OPER                                          ?
  
              X8RBUSY,                      _REMOTE BUSY               ?
              X8RCOVR:                      _TIME OUT STATE            ?
                X2VS := BZLNRR;             _LAST N(R) RECEIVED        ?
  
              END; _ CASE                                              ?
_ 
* * * *  SET UP N(S) AND N(R) 
? 
            XFTYP := 0;                     _CLEAR FRAME HEADER        ?
            XFNR  := X2VR;                  _INSERT N(R)               ?
            XFNS  := X2VS;                  _INSERT N(S)               ?
_ 
* * * *  SET UP POLL BIT
? 
            XFPF   := BZPSTATE = X8RCOVR;   _SET POLL BIT IF X8RCOVR   ?
            BZPOLL := XFPF;                 _AND REMEMBER IT           ?
_ 
* * * *  CLEAR RE-XMT CONDITION IF V(S) = LAST V(S) SENT
? 
            IF BZVS = BZLFTR                _CHECK FOR END OF RE-XMIT  ?
            THEN                            _ CONDITION                ?
              BZRXMT := FALSE;
  
            BZREJ := FALSE;                 _RESET REJ CONDITION       ?
_ 
* * * *  SET UP ADDRESS 
? 
            XFA := X2ADDR[BZDCE]; 
_ 
* * * *  SET UP T1 REQUEST
* * * *  IF N(S) = LAST N(R) RECEIVED NO FRAMES ARE PENDING 
? 
            X2FRPTR.X2BFPTR'.XBT1 := X2VS = BZLNRR; 
            END; _ WITH X2FRPTR.X2BFPTR'                               ?
        END; _ IF X2FRPTR.X1BFPTR = NIL                                ?
  
      IF X2FRPTR.X1BFPTR " NIL              _FRAME AVAILABLE           ?
      THEN
        BEGIN 
        X2FRPTR.X1BFPTR'.BCCHAINS[QCHN]     _CLEAR QUEUE CHAIN         ?
                                    := NIL; 
        BZOON := TRUE;                      _SET OUTPUT ON             ?
        IF X2FRPTR.X2BFPTR'.XBT1            _T1 REQUEST IS SET         ?
        THEN
          BEGIN                             _START T1 TIMER            ?
          X2TIMPTR.X1BFPTR := BZT1PKT;      _ASSIGN T1 TIMER PAKCET    ?
          IF (X2TIMPTR.X3BFPTR'.BKACTIVE = FALSE) !   _IF NOT ACTIVE   ?
             (BZT1RUN = FALSE)              _OR IF T1(30) RUNNING      ?
          THEN
            BEGIN 
            BZT1RUN := TRUE;                _INDICATE T1 RUNNING       ?
            X2TIMPTR.X3BFPTR'.BKTYPE    := BKSET; 
            X2TIMPTR.X3BFPTR'.BKTIME    := 30 * BZT1; 
            X2TIMPTR.X3BFPTR'.BK2USRWRD := ORD(BZTWC[T1TIMER]) + 1; 
            IF  X2TIMPTR.X3BFPTR'.BK2USRWRD = $100
             THEN 
               X2TIMPTR.X3BFPTR'.BK2USRWRD := 1;
            BZTWC[T1TIMER] := CHR(X2TIMPTR.X3BFPTR'.BK2USRWRD); 
            PBTMRSRVS (X2TIMPTR.X3BFPTR); 
            END; _ IF BKACTIVE = FALSE                                 ?
          END;  _ IF XBT1                                              ?
  
        X2CMDPKT.NKLINO := XTLCB'.BZLINO.   _LAUNCH OUTPUT             ?
                                     BDLINO;
        X2CMDPKT.NKCMD  := NKDOUT;          _DIRECT OUTPUT             ?
        X2CMDPKT.NKOBP  := X2FRPTR.X1BFPTR; 
        BZLFRM          := X2FRPTR.X1BFPTR; 
        PMCDRV (X2CMDPKT);
        END; _ IF X2FRPTR " NIL                                        ?
      END; _ IF BZOON = FALSE                                          ?
  END; _ WITH XTSLCB'.BZXSLCB                                          ?
END; _ PROCEDURE PX25XMIT                                              ?
  
