*DECK FFSOOBN 
USETEXT TEXTFFS 
      PROC FFSOOBN; 
*CALL COPYRITE
# TITLE FFSOOBN - OUTPUT DATA BLOCK TO NETWORK                         #
  
      BEGIN                            # FFSOOBN                       #
# 
**    FFSOOBN  OUTPUT DATA BLOCK TO NETWORK 
* 
*     A. LIM                           88/01/26 
* 
*     THIS PROCEDURE IS CALLED TO SEND A DATA BLOCK TO NETWORK. 
*     THE BLOCK IS EITHER SENT IMMEDIATELY TO THE NETWORK OR QUEUED 
*     INTERNALLY DEPENDING ON THE NUMBER OF OUTSTANDING DATA BLOCKS.
* 
*     PROC FFSOOBN
* 
*     ENTRY    ACNX               = INDEX INTO CURRENT ACN ENTRY
*              CURACN             = APPL C/N NO OF CURRENT ACN ENTRY
*              REQUESTS[RTCPNAM$] = COMMON BLOCK DEFINED IN *TEXTFFS* 
*                                   CONTAINING REQUEST CODE AND ANY 
*                                   NECESSARY PARAMETERS. 
* 
*     EXIT     DATA BLOCK SENT TO NETWORK OR
*              DATA BLOCK QUEUED IN WAITING BLOCK QUEUE.
*              P<ABH>  = PTR TO OUTPUT DATA BLOCK ABH.
* 
*     METHOD   IF THE CONNECTION STATE IS NOT *ACTIVE*, THEN
*              TREAT IT AS AN INTERNAL ERROR, AND END FILE
*              SERVER.
* 
*              SET UP THE APPLICATION BLOCK HEADER AND COMMON 
*              FIELDS IN DATA BLOCK.
* 
*              IF THE OUTSTANDING BLOCK COUNT IS LESS THAN THE
*              APPLICATION BLOCK LIMIT THEN THE OUTSTANDING 
*              BLOCK COUNT IS INCREMENTED AND THE DATA BLOCK IS 
*              IS DISPATCHED TO THE NETWORK.
* 
*              OTHERWISE THE WAITING BLOCK COUNT IS INCREMENTED 
*              AND THE DATA BLOCK IS QUEUED AT THE END OF THE 
*              WAITING BLOCK QUEUE. DATA BLOCKS IN THIS QUEUE ARE 
*              DISPATCHED TO THE NETWORK ON THE RECEIPT OF FC/ACK 
*              SUPERVISORY MESSAGES FOR PREVIOUS DATA BLOCKS. 
* 
# 
  
# 
****  PROC FFSOOBN - XREF LIST
# 
      XREF
        BEGIN 
        PROC MOVE;       # MOVE A NUMBER OF WORDS - DIRECT ADDRESSING  #
        PROC NETCHEK;    # CHECK FOR WORKLIST PROCESSING COMPLETION    #
        PROC NETPUT;     # OUTPUT DATA ON A LOGICAL CONNECTION         #
        PROC FFSEEFS;    # END FILE SERVER                             #
        PROC FFSMATS;    # ALLOCATE TABLE SPACE                        #
        END 
# 
****
# 
  
      BASED ARRAY BUFFER [00:00] S(1);;# BUFFER OF DATA BLOCK          #
  
      ITEM ESIZE         I;            # SIZE OF WAITING BLOCK ENTRY   #
      ITEM INDEX         I;            # WORD INDEX TO ENTRY IN WBQ    #
      ITEM LENGTH        I;            # LENGTH OF DATA BLOCK          #
      ITEM TSIZE         I;            # SIZE OF TEXT IN WAITING BLOCK #
      CONTROL EJECT;
# 
**    START MAIN PROCEDURE
# 
      P<BUFFER> = REQ$ADDR[RTCPNAM$];    # GET BUFFER ADDRESS          #
      LENGTH    = REQ$LEN[RTCPNAM$];     # GET DATA BLOCK LENGTH       #
  
      IF ACN$STATE[ACNX] EQ ENDPEND 
      THEN
        BEGIN                          # STATE IS TERMINATION PENDING  #
        RETURN;                        # IGNORE                        #
        END 
  
      IF ACN$STATE[ACNX] LAN ACTIVE EQ 0
      THEN
        BEGIN                          # STATE NOT *ACTIVE*            #
        FFSEEFS(NSENDATA);             # ABORT WITH A MESSAGE          #
        END;
  
      P<ABH>    = LOC(DABH);           # BASE BLOCK HEADER POINTER     #
      ABHADR[0] = CURACN;              # STORE CONNECTION NUMBER       #
      ABHTLC[0] = LENGTH;              # STORE TEXT LENGTH             #
      ABHABN[0] = ACN$ABN[ACNX];       # STORE APPLICATION BLOCK NUMBER#
      IF REQ$M[RTCPNAM$]
      THEN
        BEGIN                          # PARTIAL DATA                  #
        IF REQ$Q[RTCPNAM$]
        THEN
          BEGIN                        # QUALIFY DATA                  #
          ABHABT[0] = APPQBLK;
          END 
        ELSE
          BEGIN 
          ABHABT[0] = APPBLK; 
          END 
        END 
      ELSE
        BEGIN                          # COMPLETE DATA                 #
        IF REQ$Q[RTCPNAM$]
        THEN
          BEGIN                        # QUALIFY DATA                  #
          ABHABT[0] = APPQMSG;
          END 
        ELSE
          BEGIN 
          ABHABT[0] = APMSG;
          END 
        END 
  
      ACN$OUT$M[ACNX] = REQ$M[RTCPNAM$]; # STORE THE M-BIT             #
      ACN$ABN[ACNX] = ACN$ABN[ACNX] + 1; # INCREMENT BLOCK NUMBER      #
  
# 
*     APPLICATION BLOCK LIMIT NOT REACHED.
*       - SEND THE BLOCK TO NETWORK.
*       - INCREMENT THE OUTSTANDING BLOCK COUNT.
*         IF WBC EQ FCBC
*           FCR = FALSE.
# 
      IF ACN$OBC[ACNX] LS ACN$ABL[ACNX] 
      THEN
        BEGIN                          # BLOCK LIMIT NOT REACHED       #
        NETPUT (DABH, BUFFER);         # DISPATCH THE DATA BLOCK       #
        ACN$OBC[ACNX] = ACN$OBC[ACNX] + 1; # INCR. OUTSTANDING BLOCK CT#
        IF LENGTH LS ACN$DBZ[ACNX]
        THEN
          BEGIN                        # LESS THAN A FULL BLOCK SENT   #
          NETCHEK;                     # ENSURE AIP FLUSHES THE BLOCK  #
          END;
        END 
  
# 
*     APPLICATION BLOCK LIMIT REACHED.
*       - QUEUE THE BLOCK,
*       - INCREMENT THE WAITING BLOCK COUNT *WBQ$WBC*,
*       - SET RELEASE-FLOW-CONTROL FLAG ACCORDING TO WAITING BLOCK COUNT
* 
*     NOTE THAT FOR DATA CONNECTION, WHOSE ACN$DATACN BIT IS SET, THE 
*       DATA IS NOT BEING COPIED THE WBQ. 
# 
      ELSE
        BEGIN                              # BLOCK LIMIT REACHED       #
        IF ACN$DATACN[ACNX]                # DATA CONNECTION           #
        THEN
          BEGIN 
          SAVABH$WRD = DABH$WRD;           # SAVE THE HEADER           #
          P<SDTBUF> = P<BUFFER>;           # SAVE THE DATA BUFFER      #
# 
*         ADJUST THE DATA BUFFER INDEX TO POINT TO THE OTHER HALF OF
*         THE BUFFER
# 
          IF DTBUFINDX EQ 0 
          THEN
            BEGIN 
            DTBUFINDX = 1;
            END 
          ELSE
            BEGIN 
            DTBUFINDX = 0;
            END 
          P<CDTBUF> = LOC( DTBUF[DTBUFINDX] );   #SET CURRENT DATA BUFF#
          END 
        ELSE                               # NON DATA CONNECTION       #
          BEGIN 
          TSIZE = ((LENGTH*10)+70) / 75; # DATA BLOCK LENGTH IN WORDS  #
          ESIZE = TSIZE + TXT$;          # ENTRY SIZE INCLUDES HEADER  #
          INDEX = WBQL;                  # ENTRY INDEX IS CURRENT END  #
          FFSMATS(P<WBQ>, WBQL, ESIZE);  # MAKE ROOM FOR THIS ENTRY    #
          WBQ$SIZE[INDEX] = ESIZE;       # STORE ENTRY SIZE            #
          WBQ$ABH[INDEX]  = ABHWORD[0];  # STORE APPLICATION BLOCK HDR #
          MOVE (TSIZE, BUFFER,
                WBQ[INDEX + TXT$]);      # MOVE DATA BLOCK INTO QUEUE  #
          END 
  
        ACN$WBC[ACNX] = ACN$WBC[ACNX] + 1;     # INCR WAITING BLOCK CNT#
                                 #DETERMINE FLOW CONTROL RELEASED FLAG #
        ACN$FCR[ACNX] = ACN$WBC[ACNX] LS ACN$FCBC[ACNX];
        END 
  
      RETURN;                          # RETURN TO CALLER              #
  
      END                              # FFSOOBN                       #
  
      TERM
