*DECK DB$ATCH 
USETEXT CDCSCTX 
      PROC DB$ATCH(LFN,PFINFO,(QUEUE)); 
      BEGIN 
 #
* *   DB$ATCH--NOS/BE ATTACH PROCESSOR           PAGE  1
* *   C O GIMBER                                 3/1/76 
* 
* DC  PURPOSE 
* 
*     ATTACH PERMANENT FILES FOR NOS/BE.
* 
* DC  ENTRY CONDITIONS
* 
*     PARAMETERS
# 
      ITEM LFN;              #LFN FOR FILE# 
      ARRAY PFINFO; 
        BEGIN 
        ITEM PFN (0,0,60);   #PERMANENT FILE NAME (MAX OF 7 CHARS)# 
        ITEM PFID (1,0,60);  #PERMANENT FILE ID (MAX OF 7 CHARS)# 
        ITEM PFPW (2,0,60);  #PASSWORD (MAX OF 7 CHARS)#
        ITEM PFDS (7,0,60);  #DEVICE SET NAME#
        ITEM PFVSN (8,0,60); #DEVICE VSN# 
        END 
      ITEM QUEUE B;          #TRUE IF ATTACH TO BE QUEUED#
# 
* DC  EXIT CONDITIONS 
* 
*     CDCS COMMON CELL ATTACHSTATUS 
*       = 0 IF PERMANENT FILE ATTACHED
*       = -PF ATTACHSTATUS IF FILE NOT AVAILABLE. 
*       OTHERWISE PF ERROR CODE.
* 
* DC  CALLED ROUTINES 
# 
      XREF PROC DB$ATCM;     #ISSUE ATTACH MACRO FOR NOS/BE#
      XREF PROC DB$FLOP;     #GENERATE FLOW POINT#
      XREF PROC DB$MBA;      #ALLOCATE TEMPORARY BUFFER#
      XREF PROC DB$MBF;      #FREE TEMPORARY BUFFER#
      XREF PROC DB$POP;      #POP ENTRY FROM PUSH DOWN STACK# 
      XREF PROC DB$PUSH;     #PUSH ENTRY INTO PUSH DOWN STACK#
      XREF PROC DB$SCHD;     #CDCS SCHEDULER# 
      XREF PROC DB$SWPO;     #SWAP OUT USER TABLES# 
# 
* DC  NON-LOCAL VARIABLES 
* 
*     CDCS COMMON 
# 
      XDEF ITEM ATCHOFT I = 0;     # OFT ADDRESS FROM DB$ADAX          #
      XDEF ITEM DB$NOS B=FALSE;    # ON NOS/BE, DB$NOS IS FALSE        #
  
      XREF ARRAY DB$ROAF; 
        BEGIN 
        ITEM ROATFLAG I(00,00,60);  # DB$ROLL ATTACH FLAG              #
        ITEM ROFDWORD I(01,00,60);  # DB$ROLL FDB WORD                 #
        END 
 #
*     LOCAL VARIABLES.
# 
      ITEM FDX;              #INDEX INTO FDB# 
      BASED ARRAY FDB;       #FDB FOR ATTACH# 
        BEGIN 
        ITEM FDQUEUE B(DFFDBSIZE,00,60);  # SAVE QUEUE DURING 1ST PFA  #
        ITEM FDWORD;
        END 
      ITEM INDEX; 
  
  
 #
* 
* DC  INTERNAL FUNCTIONS
* 
*     PFPARM((PARM))--FORMS PARAMETER FOR PF FDB. 
 #
      FUNC PFPARM((PARM));
        BEGIN 
        ITEM PARM;
  
        B<42,18>PARM = 0; 
        CONTROL SLOWLOOP; 
        FOR PARM = PARM WHILE B<0,6>PARM NQ 0 DO
          PARM = PARM*2**6; 
        PFPARM = PARM*2**6; 
        RETURN; 
        END 
  
  
  
#     B E G I N   D B $ A T C H   E X E C U T A B L E   C O D E .      #
  
  
 #
* 
* DC  DESCRIPTION 
* 
*     SAVE ENTRY POINT
 #
  
      CONTROL IFGR DFFLOP,0;
        DB$FLOP("ATCH   "); 
      CONTROL ENDIF;
  
      $BEGIN                       #DEBUG TRACE#
      XREF PROC DB$TRCT;
      DB$TRCT("ATTACH:",0,0); 
      DB$TRCT(PFN[0],"  ID IS",7);
      DB$TRCT(PFID[0],"  AS",4);
      DB$TRCT(":",C<3,7>LFN,7); 
      $END
      DB$PUSH(DB$ATCH); 
 #
*     GENERATE PF FDB ENTRY IN TEMPORARY MANAGED MEMORY.
*       PFN IN WORDS 0-3 ZERO FILLED
*       LFN IN WORD 4 
*       ID IN WORD 5
*       1 TO 5 PASSWORDS
*       PACK DEVICE SET NAME
*       PACK VSN
*       TERMINATOR (WORD OF ZEROES) 
 #
      DB$MBA(DFFDBSIZE+1,P<FDB>); 
      FDWORD[0] = PFN[0]; 
      FDWORD[1] = 0;
      FDWORD[2] = 0;
      FDWORD[3] = 0;
      FDWORD[4] = LFN*2**18;
      FDX = 5;
      IF PFID[0] NQ 0 THEN
        BEGIN 
        FDWORD[FDX] = PFPARM(PFID[0])+O"14";
        FDX = FDX+1;
        END 
      CONTROL FASTLOOP; 
      FOR INDEX=0 STEP 1 UNTIL 4 DO 
        IF PFPW[INDEX] NQ 0 THEN
          BEGIN 
          FDWORD[FDX] = PFPARM(PFPW[INDEX])+O"20"+INDEX;
          FDX = FDX+1;
          END 
      IF PFDS[0] NQ 0 THEN
        BEGIN 
        FDWORD[FDX] = (PFDS[0] LAN LNO O"777777")+O"40";
        FDX = FDX+1;
        END 
      IF PFVSN[0] NQ 0 THEN 
        BEGIN 
        FDWORD[FDX] = (PFVSN[0] LAN LNO O"777777")+O"41"; 
        FDX = FDX+1;
        END 
      FDWORD[FDX] = 0;
      IF ATCHOFT GR 0 
      THEN
        BEGIN 
        P<OFT> = ATCHOFT; 
        OFPFAERR[0] = 0;
        OFPFABUSY[0] = FALSE; 
        END 
ATTACHLOOP: 
      FDWORD[4] = FDWORD[4] LAN LNO O"777777";
 #
*     ISSUE ATTACH MACRO. 
*     IF THE ATTACH IS NOT COMPLETED BECAUSE OF CURRENT PF CONFLICT 
*       AND IF QUEUEING IS REQUESTED
*         THEN
*         SWAP OUT THE USER.
*         GO INTO A DELAY LOOP, PERIODICALLY REISSUEING THE REQUEST.
 #
      DB$ATCM(LOC(FDWORD[4]));
      FDQUEUE[0] = QUEUE; 
      DB$PUSH(ATCHOFT); 
      ATCHOFT = 0;
      DB$SCHD(LOC(FDWORD[4]),DFWAITXE);  # WAIT FOR EXTERNAL EVENT     #
      DB$POP(ATCHOFT);
      QUEUE = FDQUEUE[0]; 
      ATTACHSTATUS = B<42,9>FDWORD[4];
  
      CONTROL IFGR DFFLOP,0;
        DB$FLOP("ATCH-A "); 
      CONTROL ENDIF;
  
 #
* 
*     SET UP THE FLAG IN DB$ROAF (ROLL-OUT ATTACH FLAG - ROATFLAG). 
*     WHEN THERE ARE NO JOBS WAITING TO ATTACH A FILE, THE FLAG IS ZERO.
*     WHEN ONLY ONE JOB IS WAITING, THE FLAG CONTAINS THE RCB ADDRESS.
*       DB$MTR WILL INITIATE A CDCS ROLL-OUT.  WHILE CDCS IS ROLLED OUT 
*       DB$ROLL ATTEMPTS THE ATTACH PERIODICALLY AND WILL ROLL IN TO
*       CONTINUE PROCESSING WHEN THE FILE IS AVAILABLE. 
*     WHEN MORE THAN ONE JOB IS WAITING, THE FLAG CONTAINS THE NEGATIVE 
*       RCB ADDRESS OF THE LAST JOB THAT ATTEMPTED THE ATTACH.
*       DB$MTR WILL NOT INITIATE A CDCS ROLL-OUT. 
*     THIS LOGIC DEPENDS ON THE FACT THAT TWO JOBS WILL BOTH DELAY FOR
*     'DFATCHDELAY' SCHEDULER CYCLES. 
*     THIS CAUSES THEIR DB$ATCH EXECUTIONS TO ALTERNATE WITH EACH OTHER.
*     EACH WILL FIND ROATFLAG (DB$ROAF) SET TO THE COMPLEMENT OF THE
*     OTHERS RCB LOCATION AND RECOGNIZE THAT THERE IS ANOTHER RCB 
*     WAITING.
*     ROATFLAG IS SET TO THE COMPLEMENT OF ITS OWN RCB LOCATION TO
*     CONTINUE THIS COMMUNICATION UNTIL ONE OR THE OTHER IS DISPOSED
*     OF BY COMPLETING THE ATTACH OR BEING DROPPED. 
* 
 #
      IF ATTACHSTATUS EQ O"36"     # IF NO APF SPACE                   #
        OR ATTACHSTATUS EQ O"37"   # OR FILE ATTACHED ELSEWHERE        #
      THEN
        BEGIN 
        IF ATCHOFT GR 0 
        THEN
          BEGIN              # PASS THE STATUS BACK TO DB$ADAX         #
          P<OFT> = ATCHOFT; 
          OFPFAERR[0] = ATTACHSTATUS; 
          OFPFABUSY[0] = TRUE;
          END 
        ATTACHSTATUS = -ATTACHSTATUS;  # INDICATE FILE NOT AVAILABLE   #
        IF ROATFLAG[0] EQ 0 
          OR ROATFLAG[0] EQ -LOC(RCB) 
        THEN
          BEGIN              # MAKE A COPY OF THE FDB FOR DB$ROLL      #
          FOR INDEX = DFFDBSIZE-1 STEP -1 UNTIL 0 
          DO
            BEGIN 
            ROFDWORD[INDEX] = FDWORD[INDEX];
            END 
          ROATFLAG[0] = LOC(RCB); 
          END 
        ELSE
          BEGIN 
          IF ROATFLAG[0] NQ LOC(RCB)
          THEN
            BEGIN 
            ROATFLAG[0] = -LOC(RCB);
            END 
          END 
        END 
      ELSE
        BEGIN 
                             # FILE IS ATTACHED OR HAS A FATAL ERROR   #
        IF ABS(ROATFLAG[0]) EQ LOC(RCB) 
        THEN
          BEGIN 
            ROATFLAG[0] = 0;
          END 
        END 
      IF QUEUE
        AND ATTACHSTATUS LS 0 
      THEN
        BEGIN 
        IF NOT RCSFSWP[0] 
          AND LOC(TQT) NQ TQTMTR
        THEN
          DB$SWPO(TRUE);
        SCHDCOUNT = SCHDCOUNT -1; 
        DB$PUSH(ATCHOFT); 
        ATCHOFT = 0;
        DB$PUSH(DFATCHDELAY);  # DELAY COUNT IS PUSHED INTO THE STACK  #
                             # DB$SCHD WILL POP THE COUNT AND USE IT   #
        DB$SCHD(LOC(STATCOMP),DFWAITCOUNT); 
        DB$POP(ATCHOFT);
  
        CONTROL IFGR DFFLOP,0;
          DB$FLOP("ATCH-W");
        CONTROL ENDIF;
  
        QUEUE=TRUE; 
        GOTO ATTACHLOOP;
  
        END 
      ATCHOFT = 0;
      DB$POP(DB$ATCH);
 #
*     FREE TEMPORARY FDB BUFFER.
 #
  
      DB$MBF(P<FDB>); 
      RETURN; 
      END 
      TERM; 
