.TITLE GETPUT FORTRAN GET/PUT INTERFACE .IDENT /GCE001/ ; .MCALL FDOF$L,FCSBT$,GET$S,PUT$S ;NOTE THE $F4P$ CONDITIONAL SELECTS MACRO OR FORTRAN CALLS ; ... FOR MACRO THE FDBS MUST BE POINTED AT BY A TABLE OF ;ADDRESSES BEGINNING AT FDBTBL AND WITH FCBTBE AS END. ; THIS ALLOWS US TO ASSOCIATE A LUN WITH AN FDB. ; FDOF$L ;DEFINE FDB OFFSETS FCSBT$ ;DEFINE FDB BIT DEFINITIONS FFDBLN = 6*2 ;LENGTH OF FORTRAN FDB HEADER ; .PSECT $MACOD,RW,I,LCL,CON .IF DF,$F4P$ .IFTF ;ALWAYS DEFINE HERE .GLOBL FDBTBL,FDBTBE FDBTBL: .WORD 0,0,0,0 ;1-4 .WORD 2,2 ;5,6 .WORD 2,2 ;7,8 (8 GETS 0) .WORD 0,0,0,0,0,0,0,0 ;MORE LUNS FDBTBE: .WORD 0 ;SAFETY MARGIN 1 WORD .IFF ;MACRO ONLY HAS DEFS OF FDB AREA HERE .MCALL FDBDF$ FD.LST:: FDBDF$ ;LUN 1 FDB FDBSZ == .-FD.LST ;SIZE OF AN FDB ENTRY .REPT 15. ;ALLOW LOTSA FDB ENTRIES FDBDF$ .ENDR ;DISCIPLINE FOR OPERATION WILL BE TO CALL ICHAN TO GET A CHANNEL AND ;CLOSEC TO CLOSE IT. IN ANY CASE IF IN MACRO AND OPENING A LUN, ;SET THE FDB ADDRESS INTO FDBTBL (CALL BUKKEP(LUN) IN FORTRAN) ;AND CALL CLOSEC TO CLOSE IT. .ENDC ; ; CLSALL - CLOSE ALL OPEN CHANNELS ASSUMING CSIOPS TYPE ; COMMAND FILE ENTRY. CLSALL:: JSR R5,S.RSAV .IF NDF,$F4P$ MOV #T.LUNS,R3 ;LUN LIST MOV #T.FDBS,R4 ; ... AND FDB ADDRESS LIST MOV #ABLK,R5 ;ARG LIST 1$: MOV (R3),ALNN ;GET LUN BEQ 2$ ;ZERO MEANS NONE TO DO JSR PC,CLOSEC ;ZERO CHANNEL CLR @R3 CLR @R4 ;ZERO LOCAL ELEMENTS TOO 2$: CMP (R3)+,(R4)+ ;PASS LIST ELEMENT CMP R3,#T.FDBS ;PAST END? BLO 1$ ;IF NOT, GET MORE LUNS .IFF ;FORTRAN VERSION. NO T.LUNS TABLE, NOR T.FDBS, WILL EXIST. MOV #FDBTBL,R4 ;FDB ADDRESS LIST MOV #</2>,R3 ;LENGTH MOV #ABLK,R5 MOV #1,R2 ;START=LUN 1 1$: MOV R2,ALNN INC R2 MOV @R4,R0 ;GET THE FDB .MCALL CLOSE$ CMP R0,#100 ;R0 A "SMALL" NUMBER (NOT FDB ADDR)? BLOS 2$ ;IF LOS YES, SKIP CLOSE CLOSE$ R0 ;TRY TO CLOSE IT CLR R0 ;NOW SET 0 = NEW FDBLST VAL CMP R2,#5 ;LUN 5,6,7,8 NOT USED BLO 4$ ;IF LO THEN 1-4 CMP R0,#9. ;LUN 9 OR OVER? BHIS 4$ ;IF HIS YES MOV #2,R0 ;ELSE FILL IN FDBTBL WITH 2 4$: MOV R0,@R4 ;FILL IN FDBTBL 2$: TST (R4)+ DEC R3 ;COUNT LUNS TO DO BGT 1$ ;CLOSE ALL WE CAN .ENDC JSR R5,S.RRES RTS PC ABLK: .WORD 1 ALN: .WORD ALNN ALNN: .WORD 0 ;LUN ; IOST: IOSB: .WORD 0,0 ROWN: .BYTE -1,2 .WORD FONR ;READ FILE OWNER BLK FONR: .WORD 0,0 BUKKEP:: MOV @2(R5),R2 ;FORTRAN ENTRY TO FILL IN FDBTBL (REALLY NOT BNE 2$ MOV #8.,R2 ;CHNL 0 BECOMES LUN 8 2$: CALL $FCHNL ;NEEDED). GET THE FORTRAN FDB BCS 1$ ADD #FFDBLN,R0 ;UPDATE FDB ADDRESS MOV @2(R5),R2 BNE 3$ MOV #8.,R2 3$: ASL R2 MOV R0,FDBTBL(R2) ;FILL IN FDBTBL 1$: RTS PC ;CLOSEU - UPDATE FDBTBL BUT DON'T CLOSE CLOSEU:: JSR R5,S.RSAV MOV @2(R5),R0 ;GET LUN TO CLOSE DEC R0 BLT 1$ ;ASSURE VALID ASL R0 ;MAKE A WORD INDEX CMP R0,# ;LUN BHIS 1$ CLR FDBTBL(R0) ;MARK IT FREE NOW 1$: JSR R5,S.RRES RTS PC CLOSEC:: JSR R5,S.RSAV MOV @2(R5),R0 ;GET LUN TO CLOSE DEC R0 BLT 1$ ;ASSURE VALID ASL R0 ;MAKE A WORD INDEX CMP R0,# ;LUN BHIS 1$ MOV R0,R1 ;SAVE POINTER MOV FDBTBL(R0),R0 ;GET FDB POINTER BEQ 1$ BIT #1,R0 ;ODD - CLOSED ALREADY? BNE 1$ ;YES, SKIP RE-CLOSE .MCALL CLOSE$ TST F.BDB(R0) ;IS THE LUN REALLY OPEN? BEQ 5$ ;IF NOT, NO CLOSE NEEDED CLOSE$ R0 ;CLOSE THE LUN 5$: CLR FDBTBL(R1) ;MARK IT FREE NOW 1$: JSR R5,S.RRES RTS PC ; ; IGETC - ; LOCATE UNUSED LUN. ; AVAILABLE FROM FORTRAN OR MACRO. RESERVES LUNS 5 AND 6 FOR ; CONSOLE AND LP: USE... ; ; NOTE: ASSUMES CLOSEC WILL BE CALLED TO CLOSE CHANNEL ;PRIOR TO REUSE. ASSEMBLY LANGUAGE SHOULD ALSO CLOSE THE ;FDB WHICH WILL BE RETURNED IN R0. ; IGETC - ALLOCATE CHANNEL AND MARK TABLES HERE FOR ACCESS BY LUN IGETC:: JSR R5,S.RSAV MOV #FDBTBL,R1 ;FIND A NULL FDB POINTER MOV #1,R2 ;AND A LUN NUMBER 1$: TST (R1) ;THIS LUN EMPTY? BNE 2$ ;IF NOT GET NEXT 15$: CMP R2,#5 ;OMIT LUNS 5 AND 6 BEQ 2$ CMP R2,#6 BEQ 2$ CMP R2,#5 ;1-4? BLT 8$ CMP R2,#8. ;9 OR OVER? BLT 2$ ;NO, SKIP THIS CHNL 8$: ;GOT ONE! .IF DF,$F4P$ MOV R1,-(SP) CALL $FCHNL ;GET FORTRAN FDB AREA MOV (SP)+,R1 ADD #FFDBLN,R0 ;GET FDB AREA MOV R0,(R1) ;FILL IN CHANNEL FOR NEXT TIME .IFF MOV R2,R3 ;GET LUN NUMBER ; *** NOTICE THE CODE HERE REQUIRES FDB DEFS TO ALL BE TOGETHER, ; FIRST FDB AT FD.LST AND FDB SIZE GLOBALLY AVAILABLE AS FDBSIZ ; AND ALSO THAT FDBTBL AND FDBTBE BE DEFINED. MUL #FDBSZ,R3 ;MULTIPLY BY SIZE OF AN FDB ADD #FD.LST,R3 ;ADD IN START OF LIST MOV R3,(R1) ;FILL IN THE FDB ADDRESS NOW FOR MACRO11 .ENDC MOV R2,R0 ;GET LUN NUMBER NOW BR 4$ ;RETURN LUN IN R0 2$: CMP R2,#5 ;VALID RANGE? BLT 16$ ;IF 1-4 MAYBE CMP R2,#8. BLE 17$ ;17$ IF 5-8 RANGE 16$: ;HERE LUN MUST BE TESTED. IF NOT OPEN, ALLOW ITS USE. .IF DF,OP$TS. ;NORMALLY EXCLUDE THIS MOV @R1,R0 ;GET THE FDB POINTER BIT #1,R0 ;ODD MEANS CLOSED NOW BNE 17$ ;TEST IF FDB IS OPEN. NEED AN IO.RAT TO DO THIS UNFORTUNATELY...NO STATUS ;IN USER SPACE AUTOMATICALLY. ADD #F.FNB,R0 ;POINTER FILENAME BLK .MCALL QIOW$S QIOW$S #IO.RAT,R2,R2,,#IOST,, TSTB @#$DSW ;ERROR? BPL 17$ ;NO, FILE IS IN USE NOW. ;FILE IS CLOSED. ALLOW USE OF THIS LUN. BR 15$ ;GO BACK, SEE ABOUT THIS ONE. .ENDC 17$: TST (R1)+ INC R2 CMP R1,#FDBTBE ;GOT TO END OF TBL? BLO 1$ ;IF NOT GO AHEAD MOV #99.,R0 ;ELSE SAY LUN 99 (ILLEGAL) MOV R0,(SP) JSR R5,S.RRES SEC ;RETURN CARRY SET RTS PC 4$: MOV R0,@SP ;RETURN R0 WITH LUN CHOSEN JSR R5,S.RRES CLC ;CARRY CLEAR IF ALL WELL RTS PC .GLOBL GETFDB ; GETFDB CALLED BY GET, PUT TO FIND FORTRAN FDB INFO. GETFDB: MOV @2(R5),R2 ;GET LUN BNE 42$ MOV #8.,R2 ;LUN 0 BECOMES LUN 8 42$: .IF DF,$F4P$ .PRINT ;ASSEMBLED FOR FORTRAN CALLS CALL $FCHNL ;GET ASSOCIATED FFDB BCS 100$ ;CS - ILLEGAL LUN ADD #FFDBLN,R0 ;OFFSET TO REAL FDB ;STUFF FDB ADDRESS INTO FDBTBL MOV @2(R5),R2 BNE 142$ MOV #8.,R2 142$: MOV R2,R1 ;COPY LUN DEC R1 ;REDUCE TO START AT 0 ASL R1 MOV R0,FDBTBL(R1) ;FILL IN THE LUN ADDRESS NOW ;END OF COPY. THIS WILL ENSURE FDBTBL WILL BE OK. MOV SP,R1 SUB #12,SP ;MAKE ROOM FOR SAVE MOV (R1),(SP) ;SET UP FOR COROUTINE MOV F.URBD(R0),(R1) MOV F.URBD+2(R0),-(R1) MOV F.NRBD(R0),-(R1) MOV F.NRBD+2(R0),-(R1) MOV F.RACC(R0),-(R1) ;SAVE FORTRAN FDB INFO JSR PC,@(SP)+ ;CALL COROUTINE MOV (SP)+,F.RACC(R0) ;RESTORE FORTRAN FDB INFO MOV (SP)+,F.NRBD+2(R0) MOV (SP)+,F.NRBD(R0) MOV (SP)+,F.URBD+2(R0) MOV (SP)+,F.URBD(R0) .IFF .PRINT ;ASSEMBLED FOR MACRO-11 CALLS, FDBTBL AND FDBTBE ARE TBL ADDRS ;R2 HAS LUN NUMBER. LOCATE FDB FROM IT VIA TABLE WHICH MUST BE ;SET UP. MOV #-1,R0 ;R0 ILLEGAL TILL PROVEN OTHERWISE DEC R2 ;MAKE TABLE INDEX BLT 75$ ;ILLEGAL IF 0 OR NEG ASL R2 ;MAKE IT A WORD INDEX CMP R2,# ;PAST FDBTBE? (END OF FCB TBL ADDR) BHIS 75$ ;IF SO ALSO ILLEGAL MOV FDBTBL(R2),R0 BEQ 100$ ;IF VALID, LEAVE R0 ALONE, ELSE MAKE BAD BIT #1,R0 BNE 100$ 75$: .ENDC RETURN 100$: MOV #-99.,@10(R5) ;ILLEGAL LUN TST (SP)+ RETURN ; ;GET LOGICAL RECORD ENTRY POINT ; CALL GET(LUN,BUF,SIZE,STAT) ; ; .ENABL LSB XFDB: .WORD 0,0,0,0,0,0,0,0 ;FDB SAVE AREA GSTR1:: JSR R5,S.RSAV ;SAVE REGS ACROSS THESE CALLS MOV #6,R4 JSR PC,GETT ;BUT DO THE WORK JSR R5,S.RRES RTS PC GSTR2:: JSR R5,S.RSAV ;SAVE REGS ACROSS THESE CALLS MOV #4,R4 JSR PC,GETT ;BUT DO THE WORK JSR R5,S.RRES RTS PC GSTR4:: JSR R5,S.RSAV ;SAVE REGS ACROSS THESE CALLS MOV #2,R4 JSR PC,GETT ;BUT DO THE WORK JSR R5,S.RRES RTS PC GETSTR:: JSR R5,S.RSAV ;SAVE REGS ACROSS THESE CALLS MOV #10,R4 JSR PC,GET ;BUT DO THE WORK JSR R5,S.RRES RTS PC GET:: CLR R4 ;FDB SAVE OFFSET GETT: CMPB @R5,#1 ;AT LEAST 1 ARG? BHIS 174$ 474$: MOV XFDB(R4),R0 ;GET LAST USED FDB BEQ 274$ ;IF NONE, ERROR 174$: CMP 2(R5),#177777 ;NO REAL ARG? BEQ 474$ CALL GETFDB ;GET FORTRAN FDB CMP R0,#-1 BNE 74$ KLUG=2 ADD #12+KLUG,SP ;**** NEW 274$: SEC RTS PC ;ERR 74$: MOV R0,XFDB(R4) ;SAVE FDB ADDR BIC #FD.PLC,F.RACC(R0) ;CLEAR LOCATE MODE CMPB @R5,#1 ;CALLED WITH 0 OR 1 ARGS FOR REWIND? BHI 10$ ;IF HI NO, DO OPERATION ; TSTB @R5 ;CALLED WITH NO ARGS FOR REWIND? ; BNE 10$ ;IF NOT, NORMAL GET CLR R3 ;POINT TO BYTE 0 CLR R1 ;OF BLOCK... MOV #1,R2 ;#1 (TO 32 BITS) JSR PC,.POINT ;THANKS TO FCS... ;THEN RETURN. .IF DF,$F4P$ ADD #KLUG+12,SP ;POP OUT OF RESTORE FDB STUFF .ENDC RTS PC 10$: GET$S R0,4(R5),@6(R5) ;GET A RECORD BCC 216$ JMP X110$ 216$: ; BCS X110$ ;CS - IT FAILED .IF DF,..GS. ;NORMAL RETURNS LENGTH OR - ERR CODE MOV F.NRBD(R0),@10(R5) ;RETURN RECORD LENGTH .IFF ;RT11 DOESN'T RETURN THE LENGTH BUT NULLS THE CHARACTER AFTER THE ;LAST LINE. DO SO HERE TOO. MOV R1,-(SP) MOV 4(R5),R1 ;GET START OF RECORD ADD F.NRBD(R0),R1 ;ADD LENGTH TO POINT AFTER END CLRB @R1 ;NULL THE LAST BYTE READ IN MOV (SP)+,R1 ;(INCREDIBLE, ISN'T IT?) CLRB @10(R5) ;AND 0 ERR CODE .ENDC RETURN ; ;PUT LOGICAL RECORD ENTRY POINT ; CALL PUT(LUN,BUF,SIZE,STAT) ;EXTRA PUTSTR CALL ADDED FOR RT11 COMPATIBILITY ; PSV: .WORD 0 ;WRK AREA ARGP: .WORD 4 LN: .WORD 0 BF: .WORD 0 .WORD SZ ER: .WORD 0 SZ: .WORD 0 BUFFP: .WORD BUFF BUFF: .BLKB 512. TBUF: .BYTE 40,0 ;JUST A SPACE TCC: .WORD 0 ;NO SPECIAL FORMAT CONTROLS TARGS: .WORD 4 ;TEMP ARGLIST .WORD 0 ;LUN FOR PSTR1 TER: .WORD 0 ;ERR RETURN ADDRESS TOUT: .WORD TBUF ;STRING ADDRESS TTCC: .WORD TCC ;FORMAT CONTROL CHAR ;PSTR1 IS CALLED USING (LUN,ERR,BUFF,CC) [CC=CARRIAGE CTL] PSTR1:: JSR R5,S.RSAV ;SAVE REGS JSR PC,PSTRR ;DO THE WORK JSR R5,S.RRES RTS PC PSTRR: MOV 2(R5),TARGS+2 ;COPY LUN ADDRESS MOV 4(R5),TER ;AND ERROR MOV #TBUF,TOUT ;GET SHORT CALL TEMP BUFFER MOV #TCC,TTCC ;AND FORMAT CONTROL CMPB @R5,#2 ;2 ARG CALL TO EMIT LAST BUFFER? BLE 1$ ;IF NOT DO NORMAL THINGS MOV 6(R5),TOUT ;LIKE COPY CALLER BUFFER ADDRESS MOV 10(R5),TTCC ;AND FORMAT CONTROL 1$: MOV #TARGS,R5 ;POINT FORMAT LIST AT OUR ARG LIST PUTSTR:: TSTB @R5 ;CALLED WITH NO ARGS FOR REWIND? BNE 10$ ;IF NOT, NORMAL GET CALL GETFDB ;GET FORTRAN FDB CMP R0,#-1 BNE 74$ SEC RTS PC ;ERR 74$: CLR R3 ;POINT TO BYTE 0 CLR R1 ;OF BLOCK... MOV #1,R2 ;#1 (TO 32 BITS) JSR PC,.POINT ;THANKS TO FCS... ;THEN RETURN. .IF DF,$F4P$ ADD #12+KLUG,SP ;POP OUT OF RESTORE FDB STUFF .ENDC RTS PC 10$: JSR R5,S.RSAV MOV 2(R5),LN MOV 6(R5),BF ;ADDR MOV 4(R5),ER ;ERR ADDRESS MOV 6(R5),R0 ;STRING START ; 3RD ARG SAYS IF WE SHOULD BUFFER RECORDS. ;SEE IF WE NEED TO BUFFER THE RECORD. ; $ MEANS NO CRLF, AND + MEANS NO LF. ASSUME THAT WE WILL EVENTUALLY ;GET A RECORD WITH CR AT THE END AND ACCORDINGLY ALLOW RECORDS TO BE ;APPENDED UNTIL SUCH A RECORD IS SEEN. MOV #600.,R1 ;MAX LEN MOV R0,R2 1$: BITB #177,(R2)+ ;TERMINATOR? BEQ 2$ ;IF EQ YES SOB R1,1$ ;KEEP LOOKING 2$: DEC R2 SUB R0,R2 ;GET LENGTH BLE 4$ ;ENSURE OK MOV R2,SZ ;SIZE OF STRING ;TEST 3RD ARGUMENT HERE. EMIT NO RECORD IF A $ OR +. ;IGNORE FF OR DOUBLE SPACING STUFF FOR NOW. CMPB @10(R5),#'$ ;WAS THIS A "$" TYPE RECORD BEQ 210$ ;IF SO SERVICE ADDING MORE TO BUFFER CMPB @10(R5),#'+ ;ALSO + AS FMT CONTROL BEQ 210$ ;NOT SPECIAL. WILL IT BE NECESSARY TO OUTPUT AN OUTSTANDING SPECIAL ;RECORD HERE? CMP BUFFP,#BUFF ;AT START OF BUFFER? BEQ 11$ ;IF SO NOTHING TO DO ;COPY THIS RECORD TO END OF BUFFER AND SHIP IT OUT. MOV R2,-(SP) ;SAVE COUNTER MOV 6(R5),R0 ;GET ADDR OF THIS RECORD 12$: MOVB (R0)+,@BUFFP ;FILL IN BUFFER INC BUFFP ;UPDATE POINTER DEC R2 BGT 12$ ;COPY DATA TO BUFFER AFTER WHAT'S THERE ;NOW FILL IN ARRY MOV BUFFP,SZ SUB #,SZ MOV #BUFF,BUFFP ;RESET BUFFER TO START MOV #BUFF,BF ;SET START OF RECORD FOR THE PUT MOV (SP)+,R2 BR 11$ ;GO SHIP OUT THE RECORD ; 210$: ; HERE SERVICE SPECIAL RECORDS THAT WE JUST SHOVE INTO BUFF ;FIRST JUST COPY THE DATA. THEN EMIT A C.R. IF CODE WAS "+". MOV R2,-(SP) MOV 6(R5),R0 ;DATA ADDRESS 14$: MOVB (R0)+,@BUFFP ;SHOVE OUT DATA INC BUFFP ;COUNT IT SOB R2,14$ ;MOVE ALL DATA CMPB @10(R5),#'+ ;SHALL WE ADD THE C.R.? BNE 15$ ;IF NE NO MOVB #15,@BUFFP ;IF EQ YES INC BUFFP ;SO FILL IT IN AND COUNT IT 15$: MOV (SP)+,R2 BR 4$ ;SKIP ACTUAL OUTPUT HERE. 11$: MOV #ARGP,R5 ;GET ARG POINTER JSR PC,PUT ;EMIT RECORD 4$: JSR R5,S.RRES RTS PC ;PUT IS CALLED (LUN,BUFF,COUNT,ERR) PUT:: CALL GETFDB ;GET FORTRAN FDB CMP R0,#-1 BNE 74$ SEC RTS PC ;ERR 74$: BIC #FD.PLC,F.RACC(R0) ;CLEAR LOCATE MODE PUT$S R0,4(R5),@6(R5) ;PUT A RECORD BCS 110$ ;CS - IT FAILED CLRB @10(R5) ;RETURN SUCCESS RETURN 110$: X110$: MOVB F.ERR(R0),R1 ;GET ERROR - SIGN EXTEND CMPB R1,#IE.EOF ;ERROR IS EOF? BNE 111$ ;IF NE NO MOV #-1,R1 ;IF EQ YES 111$: MOVB R1,@10(R5) ;AND RETURN IT RETURN ; .DSABL LSB .END