*DECK NPBACK
USETEXT NIPDEF
USETEXT AHEADER 
USETEXT DRHDR 
USETEXT NHEADER 
USETEXT NCNB
USETEXT OVERLAY 
USETEXT PARAMS
 PROC NPBACK(BUFADDR,(NCNBFWA));       # PROCESS BACK BLOCK FROM CCP   #
  
 STARTIMS;
 #
*1DC  NPBACK
* 
*    1. PROC NAME              AUTHOR           DATE
*       NPBACK                 J.C. LEE         83/04/26
* 
*    2. FUNCTIONAL DESCRIPTION :  
*       PROCESS BACK FORM CCP.
* 
*    3. METHOD USED : 
*       IF BSN DOESNOT MATCH BSN IN THE CURRENT ACKQ ENTRY
*       THEN CALL NBADBSN.
*       IF BSN DOEN MATCH, FORM FC/ACK (TO BE PASSED TO HBSTTP),
*       UPDATE ACK-QUEUE, DELINK DATA IN DATA RING, SEND DATA.
* 
*    4. ENTRY PARAMS: 
*       NCNBFWA  - NCNB ADDRESS 
*       BUFADDR  - NETWORK BLOCK ADDRESS. 
* 
*    5. OUTPUT PARAMETERS 
*       PARAMS3  - 0 IF NO ACKQ ENTRY FOUND.
* 
*    6. ROUTINS CALLED: 
*       NFOB    - SEND DATA TO CCP
*       OVLCALL - LOAD AND EXECUTE OVERLAY
* 
* 
 #
 STOPIMS; 
  
# 
      FORMAL PARAMETERS 
# 
      ITEM NCNBFWA;          # FWA OF NCNB                             #
      ITEM BUFADDR;          # FWA OF UPLINE NETWORK -BACK- BLOCK      #
# 
      EXTERNAL REFERENCES 
# 
      XREF
        BEGIN 
        PROC NFOB;           # SEND NETWORK BLOCK                      #
        PROC OVLCALL;        # LOAD OVERLAY                            #
        PROC XTRACE;         # TRACE CALL                              #
        END 
# 
      LOCAL VARIABLES 
# 
      ARRAY FC$ACK S(1);     # ARRAY OF FC/ACK SUP MSG                 #
        BEGIN 
        ITEM FC$PFCSFC  U(00,00,16) = [FCACK];  # PFC/SFC FIELD        #
        ITEM FC$FILL1   U(00,16,20) = [0];      # ZERO FILL FIELD      #
        ITEM FC$ABN     U(00,36,18) = [0];      # FC/ACK ABN FIELD     #
        ITEM FC$FILL2   U(00,54,06) = [0];      # ZERO FILL FIELD      #
        ITEM FC$WORD    U(00,00,60);            # PFC/SFC WORD         #
        END 
  
      ITEM CURRBLK;          # CURRENT QUEUED BLOCK POINTER            #
      ITEM NEXTBLK;          # NEXT BLOCK IN QUEUE POINTER             #
  
      CONTROL EJECT;
  
      BEGIN # NPBACK #
  
      CONTROL IFEQ DEBUG,1; 
      XTRACE("NBACK");
      CONTROL FI; 
  
      P<NCNB> = NCNBFWA;
      P<NHEADER> = BUFADDR+BLKHSIZE; # NETWORK HEADER FWA              #
      P<AHEADER> = NCNBACKQ[0]+ACKHSIZE+NCNBAKOU[0]; # ACKQ ENTRY      #
  
      IF ABHABT[0] NQ 0 
      THEN
        BEGIN                      #  ACK IS EXPECTING FOR THIS ENTRY  #
        IF NHBSN[0] NQ ABHADR[0]
        THEN # BSN MISMATCH, ACTIVATE BAD UPLINE BSN PROCESSING        #
          BEGIN 
          PARAMS1 = P<NCNB>;
          PARAMS2 = NHBSN[0]; # BAD BSN ON NETWORK HEADER              #
          OVLNAME = NBADBSNP; 
          OVLCALL;
          BUFADDR = PARAMS3; # FWA OF PSEUDO NAK ENTRY(S)              #
          END 
  
        ELSE # BSN MATCH, GENERATE PSEUDO ACK ENTRY FOR HOST SIDE      #
          BEGIN 
          FC$ABN[0] = ABHABN[0];   # ACKNOWLEDGED BLOCK-S ABN          #
          NHWORD[0] = FC$WORD[0];  # BUILD PFC/SFC WORD                #
          END 
        END                        #  ACK IS EXPECTING FOR THIS ENTRY  #
      ELSE
        BUFADDR = 0 ;              # FC/ACK IS NOT EXPECTED FOR THIS   #
                                   # ENTRY, SO IGNORE THIS BACK        #
  
      # UPDATE THE ACK QUEUE AND OUTSTANDING  BLOCK COUNT              #
  
      IF (NCNBAKOU[0]+1) GQ NCNBDBL[0]
      THEN # EXCEEDS ACKQ SIZE, UPDATE OUT POINTER                     #
        NCNBAKOU[0] = 0; # RESET OUT POINTER TO ZERO                   #
      ELSE # INCREMENT OUT POINTER BY ONE                              #
        NCNBAKOU[0] = NCNBAKOU[0]+1;
  
      NCNBNBO[0] = NCNBNBO[0]-1; # DECREMENT BLK OUTSTANDING COUNT     #
  
      FOR CURRBLK=CURRBLK WHILE NCNBNBO[0] LS NCNBDBL[0]
                            AND NCNBDRFP[0] NQ 0 # DATA RING EXISTS    #
                            AND NOT NCNBNBR[0] # CONN TRAFFIC ALLOWED  #
      DO # DELINK BLOCK FROM QUEUED DATA RING AND SEND TO NETWORK      #
        BEGIN 
        CURRBLK = NCNBDRFP[0]; # CURRENT BLOCK TO SEND                 #
        P<DRHDRWD> = 0; 
        NEXTBLK = NEXTPTR[CURRBLK]; # NEXT BLOCK IN QUEUE              #
        IF CURRBLK NQ NCNBDRBP[0] 
        THEN # MORE THAN ONE BLOCK QUEUED                              #
          BEGIN # DELINK BLOCK FROM QUEUE                              #
          NCNBDRFP[0] = NEXTBLK;
          BACKPTR[NEXTBLK] = LOC(NCNBDRFP[0]);
          END 
        ELSE # ONLY ONE BLOCK QUEUED                                   #
          NCNBDRPTRS[0] = 0;
        NCNBBLKSQ[0] = NCNBBLKSQ[0]-1; # DECREMENT BLOCKS QUEUED COUNT #
        NFOB(CURRBLK,P<NCNB>); # SEND DATA TO NETWORK                  #
        END 
  
      RETURN; 
      END # NPBACK #
      TERM
