.TITLE MAG TAPE DLU FILE READER DRIVER (RT-11 V4) .SBTTL INTRODUCTION .IDENT /V04.00/ .ENABL LC ; ; ; This is a modified version of the ROLLIN file handler. ; It was fairly easy to modify cause DLU and ROLLIN both ; work on the same principle of writing out large buffers ; of data to mag tape for disk backup. ROLLIN uses a fixed ; 4096 word buffer while DLU uses a one track buffer depending ; upon the disk being backed up. RK05's use a (12 * 256) 3072 ; word buffer and RL01's use (20 * 256) 5120 word buffers. ; DLU uses the first record of the file to store disk type information ; and a title of the disk being backed up. ROLLIN, I believe, ; is not as convienent to use as DLU because it is stand-alone ; and must use the system console. DLU, on the other hand, ; runs under RT-11 and uses its drivers. More devices can be ; added by adding the track size to the table in DLU. ; ; I am sorry to say that the program is written to require EIS ; hardware. If you write a DIV macro, you can use this on ; EAE or no-EIS hardware machines. I plan to fix the EIS ; dependence when I first need it. ; ; And finally, I have added the ability to use this handler on ; any of the attached tape drives. Just specify RO0: through ; RO7: and it will pick up the unit number. You will still have ; to tell it the file number ; ; ; Modified by Ned W. Rhodes May-80 ; Modified again by Ned W. Rhodes for version 4 support Nov 80 ; In order to work with TSX-PLUS where the handler has ; to be resident, I added a SET option, 'SET RO RESET' that ; forces the handler to go through the first time code again. ; As you will see from the code, there is a first time section ; that positions you to the proper file. If the first time section ; is not executed, you will always get the first DLU file. ; For XM users, you will have to load and unload the handler ; cause the set command does not change the memory image. ; ; And I am sorry to say that a subtle error showed up when I ; increased the buffer size. If the 512 word transfer spanned ; record boundaries, the old logic used a arithmetic compare and ; it happened that the address were 16 bits unsigned. Therefore the ; old logic didn't work. I changed the logic to use a DIV instruction ; since I had two others anyway and now we work fine. ; ; Modified again to add the SPFUN request to RO: so we can do ; mag tape read and writes, but only with a maximum of 5K word ; buffers. ; .PAGE .SBTTL MACRO AND REGISTER DEFINITIONS ; ; ; SET MACROS ; ; .MCALL .DRDEF,.DRSET .MCALL ..V2..,.PRINT,.TTYIN,.FORK .MCALL .SYNCH ..V2.. ; ; ; SET ADDRESSES ; ; ROS=172520 ;STATUS REGISTER ROC=172522 ;CONTROL REGISTER ROBRC=172524 ;BYTE COUNT ROCMA=172526 ;CURRENT MEMORY ADDRESS ROVEC=224 ;VECTOR RWD = 373 ;REWIND EFILE = 377 ;WRITE AN EOF FSPACE = 376 ;FORWARD SPACE BSPACE = 375 ;BACKSPACE OFLINE = 372 ;OFFLINE REWIND BFOUT = 371 ;WRITE BFINP = 370 ;READ READY = 200 ;DRIVE READY AND ONLINE LOADP = 201 ;AT LOADPOIINT IEOF = 202 ;READ EOF IRING = 203 ;WRITE RING PRESENT IEOT = 204 ;PAST EOT ; ; ; BITS 800 BPI 9-TRACK/DUMP MODE 7-TRACK,INTERUPT ENABLE,GO ; ; M=60101 MMG$T = 1 ;XM HANDLER ENABLED .PAGE .SBTTL SET OPTIONS ; ; ; SET OPTIONS ; ; .DRSET RESET,NOP,O.RESET ; ; ; SET CODE ; ; O.RESET:MOV R3,ROSRT ; REPLACE WITH A NOP INSTRUCTION RETURN ; BYE BYE .PAGE .SBTTL HANDLER BEGINNING ; ; ; BEGINNING OF HANDLER ; ; .DRDEF RO,370,SPFUN$!FILST$,0,ROS,ROVEC ; ; ; BEGINING OF INITALIZATION CODE ; ; .DRBEG RO ; ; ; Check for a special function code first ; ; RO: MOV ROCQE,R4 ;POINT TO QUEUE ELEMENT MOV #8.,CTR ; SET READ TRY COUNTER TO 8 TRYS BIC #HDERR$,@-2(R4) ;CLEAR HARD ERROR BIT MOV Q$FUNC(R4),R1 ;GET UNIT STUFF BIC #174377,R1 ;ONLY UNIT MOV R1,UNIT ;SAVE AWAY BIS #60000,R1 ;800 BPI MOVB Q$FUNC(R4),R0 ;CHECK FOR SPECIAL FUNCTION BNE ROSPC ;DO SPECIAL FUNCTION JMP ROSRT ;NOT A SPECIAL FUNCTION ROSPC: ; ; ; Special function code handler ; ; ; RWD ; ; CMPB R0,#RWD ;IS IT A REWIND BNE FSPC ;NO--TRY FORWARD SPACE MOVB #16,ROIBR ;AND TO FINISH BIS RW,R1 ;FORM WHOLE CODE MOV R1,@#ROC ;AND START IT RETURN ;BYE ; ; ; FSPACE ; ; FSPC: CMPB R0,#FSPACE ;IS IT A FORWARD?? BNE BSPC ;NO--TRY BACK MOV #-1,@#ROBRC ;ONE RECORD SKIP MOVB #16,@#ROIBR ;FINISH BIS SKF,R1 ;FORM WHOLE CODE MOV R1,@#ROC ;SKIP FORWARD RETURN ;BYE ; ; ; BSPACE ; ; BSPC: CMPB R0,#BSPACE ;IS IT A BACKWARD?? BNE OLINE ;NO--TRY OFFLINE MOV #-1,@#ROBRC ;ONE RECORD SKIP MOVB #16,@#ROIBR ;FINISH BIS SKB,R1 ;FORM WHOLE CODE MOV R1,@#ROC ;SKIP FORWARD RETURN ;BYE ; ; ; OFFLINE ; ; OLINE: CMPB R0,#OFLINE ;IS IT OFF LINE?? BNE EFL ;NO--TRY EFILE MOVB #16,@#ROIBR ;FINISH BIS OFF,R1 ;FORM WHOLE CODE MOV R1,@#ROC ;DO IT RETURN ;BYE ; ; ; EFILE ; ; EFL: CMPB R0,#EFILE ;IS IT EFILE?? BNE BFI ;NO--TRY BFINP MOVB #16,@#ROIBR ;FINISH BIS EFLE,R1 ;FORM WHOLE CODE MOV R1,@#ROC ;DO IT RETURN ; ; ; BFINP--LIMITED TO 5120 WORDS ; ; BFI: CMPB R0,#BFINP ;IS IT A READ?? BNE RED ;READ CHECK CLR NUMB ;START AT BEGINNING JMP RDBLK ;USE THE READ ROUTINE ; ; ; IREADY ; ; RED: CMPB R0,#READY ;READY CHECK?? BNE LOD ;CHECK LOADPOINT MOV R1,@#ROC ;SELECT UNIT TSTB @#ROC ;CHECK FOR READY BPL NOT ;NOT READY BIT #1,@#ROS ;UNIT READY?? BNE REDOUT ;YES NOT: BIS #HDERR$,@-2(R4) ;SET NOT READY AS HARD ERROR REDOUT: JMP DONE ;ALL DONE ; ; ; LOADPOINT ; ; LOD: CMPB R0,#LOADP ;LOAD POINT?? BNE IEF ;CHECK IEOF MOV R1,@#ROC ;SELECT UNIT BIT #40,@#ROS ;CHECK FOR LOADPOINT BEQ NBOT ;NOT AT BOT BIS #HDERR$,@-2(R4) ;SET AT BOT AS HARD ERROR NBOT: JMP DONE ;ALL DONE ; ; ; IEOF ; ; IEF: CMPB R0,#IEOF ;READ EOF?? BNE IRG ;NO--CHECK RING MOV R1,@#ROC ;SELECT UNIT BIT #40000,@#ROS ;CHECK EOF BEQ NEF ;NOT EOF BIS #HDERR$,@-2(R4) ;SET EOF AS HARD ERROR NEF: JMP DONE ;ALL DONE ; ; ; IRING ; ; IRG: CMPB R0,#IRING ;RING IN PLACE?? BNE IET ;CHECK IEOT MOV R1,@#ROC ;SELECT UNIT BIT #4,@#ROS ;RING?? BNE NRING ;NO RING BIS #HDERR$,@-2(R4) ;RING THERE NRING: JMP DONE ;ALL DONE ; ; ; IEOT ; ; IET: CMPB R0,#IEOT ;AT EOT?? BNE BFO ;CHECK WRITE MOV R1,@#ROC ;SELECT UNIT BIT #2000,@#ROS ;AT EOT?? BEQ EOT2 ;NO--RETURN BIS #HDERR$,@-2(R4) ;SET FLAG EOT2: JMP DONE ;BYE BYE ; ; ; BFOUT--LIMITED TO 5120 WORDS ; ; BFO: CMPB R0,#BFOUT ;IS IT BNE ROERR1 ;ERROR TST 6(R4) ;CHECK WORD COUNT BGE BFO1 ;WORD COUNT POSITIVE NEG 6(R4) ;FORCE WORD COUNT POSITIVE BFO1: CMP 6(R4),#5121. ;> 5120 WORDS?? BLT BFO1A ;NO MOV #5120.,6(R4) ;FORCE TO 5120 WORDS BFO1A: ASL 6(R4) ;MAKE A BYTE COUNT MOV 6(R4),BCNT ;SAVE BYTE COUNT NEG BCNT ;MAKE MINUS BYTE COUNT MOV #,R3 ;GET START OF BUFFER ADD @#ROVEC,R3 ;IN A POSITION INDEPENDENT FASHION MOV R3,BADDR ;SAVE ADDRESS BFO2: .IF EQ,MMG$T ;IF NOT XM MONITOR MOV @4(R4),(R3)+ ;MOVE WORD TO BUFFER ADD #2,4(R4) ;BUMP POINTER .IFF ;BUT IF IT IS XM MONITOR CALL @$GTBYT ;GET BYTE FROM USER BUFFER MOVB (SP)+,(R3)+ ;AND STORE IT .ENDC DEC 6(R4) ;DEC BYTE COUNT BNE BFO2 ;NOT DONE YET ; ; ; BUFFER IS NOW FILLED--WRITE IT OUT ; ; WRIT: MOV BADDR,@#ROCMA ;ADDRESS TO WRITE MOV BCNT,@#ROBRC ;SET BYTE COUNT MOVB #20,ROIBR ;WRITE ERROR CHECKING ROUTINE MOV WRITE,R0 ;GET COMMAND BIS UNIT,R0 ;SELECT UNIT MOV R0,@#ROC ;DO THE COMMAND RETURN ;WAIT FOR COMPLETION ; ; ; WRITE ERROR CHECKING ; ; WERR: MOV ROCQE,R4 ;GET QUEUE ELEMENT TST @#ROC ;WRITE ERROR BLT WERR1 ;YES ERROR WERR0: JMP DONE ;OK--LEAVE WERR1: MOV @#ROS,R0 ;GET ERROR BIC #42177,R0 ;CLEAR OUT LITTLE ERRORS BEQ WERR0 ;LEAVE IF NOT A BIG ERROR DEC CTR ;CHECK RETRY COUNTER BGT WERR2 ;TRY A RE-TRY BIS #HDERR$,@-2(R4) ;ERROR STUFF--BUFFER ALREADY WRITTEN JMP DONE ;LEAVE WERR2: MOV #-1,@#ROBRC ;ONE RECORD MOV SKB,R0 ;GET THE COMMAND BIS UNIT,R0 ;SELECT THE UNIT MOV R0,@#ROC ;START IT RETURN ;BYE ROERR1: BR ROERR ;ADDRESSING PROBLEM .PAGE .SBTTL NON SPECIAL FUNCTION PORTION ROSRT: NOP ; ; ; THIS AREA IS A SPECIAL PART OF THE INITIALIZATION ; PROCEEDURE-THE FIRST TIME THROUGH-THE MAGTAPE HAS TO BE ; POSITIONED,SO THE INSTRUCTION AT RO: ALLOWS THE FOLLOWING ; INSTRUCTION TO BE EXECUTED ; ; JMP FSTIM ; ; ; THE ROUTINE 'FSTIM' THEN REPLACES THE 'NOP' AT RO: BY A ; 'BR .+6' ; SO THAT ALL SUBSEQUENT CALLS TO THE DRIVER DO NOT GO THROUGH ; THE ONE TIME ONLY CODE 'FSTIM' ; ; THE FOLLOWING CODE IS THE REGULAR I/O INIT CODE ; ; OTRTIM: MOV ROCQE,R4 ; GET POINTER TO QUE ELEMENT TST 6(R4) ; IS IT READ OR WRITE BLT ROERR ; IF LT 0 THEN ERROR-THIS IS A READ ONLY DEVICE MOV #8.,CTR ; SET READ TRY COUNTER TO 8 TRYS MOV (R4),R3 ; GET THE BLOCK NO (256. WORDS/BLOCK ) CLR R2 ; CLEAR UPPER BITS DIV NUMB,R2 ; FIND TAPE RECORD NUMBER MOV R2,R1 ; WORK ON COPY ONLY SUB PTR,R1 ; GET OFFSET FROM BLOCK NOW IN MEMORY BEQ INMEM ; IF BLOCK NOW IN MEMORY, NO TAPE HANDLEING NEEDED BLT BACKUP ; NOT IN MEMORY-GOT TO BACK UP TO GET IT DEC R1 ; SINCE THE MAG TAPE IS POSITIONED AFTER ; THE BLOCK IN MEMORY-WE ONLY NEED TO SKIP N-1 ; BLOCKS TO BE ABLE TO READ THE ONE WANTED BEQ NXTBLK ; BLOCK WANTED IS NEXT BLOCK-SO NO SKIP NEEDED SKPFWD: NEG R1 ; RECORD CONTER NEEDS 2'S COMPLIMENT MOV R1,@#ROBRC MOVB #0,ROIBR ; WHEN SKIP COMPLETED-ON INTERUPT ; GO TO ROUTINE RDBLK MOV R2,PTR ; SET POINTER TO NOEW BLOCK TO BE IN MEMORY MOV SKF,R1 ; GET COMMAND BIS UNIT,R1 ; SET UNIT NUMBER MOV R1,@#ROC ; GO DO IT RTS PC BACKUP: DEC R1 ; HAVE TO SKIP BACK ONE MORE BLOCK THAN DIFFERECE ; CALCULATED DUE TO POSITION OF TAPE MOV R1,@#ROBRC ; SET UP RCORD COUNTER MOV R2,PTR ; NEW BLOCK IN MEM VALUE MOVB #0,ROIBR ; WHEN SKIP DONE-DO A RDBLK MOV SKB,R1 ; GET THE COMMAND BIS UNIT,R1 ; SET THE UNIT NUMBER MOV R1,@#ROC ; EXECUTE RTS PC INMEM: MOVB #4,ROIBR ; JUST COPY CONTENTS OF MEMORY BR SIMINT ROERR: MOVB #2,ROIBR ; ON INTERUPT-DO ERROR EXIT BR SIMINT ; FORCE AN INTERUPT NXTBLK: MOVB #0,ROIBR ; ON INTERUPT-READ A BLOCK INC PTR ; NEXT BLOCK NO-UPDATE PTR SIMINT: MOV #100,@#ROC ; FORCE AN IMEDIATE INTERUPT ; BY SETTING THE I.E BIT ONLY RTS PC ; ; ; INTERUPT SERVICE ROUTINES ; ; .DRAST RO,5,RODONE ; ; ; TIME IS NOT CRITICAL-WAIT UNTILL ALL INTERUPTS THAT ; NEED THE TIME ARE DONE ; ; .FORK ROFBLK ; ; ; THE FOLLOWING IS A TABLE THAT ALLOWS DIFFERENT ; INTERUPT SERVICE ROUTINES TO BE CALLED AS NEEDED ; THE "BR .+N" INSTRUCTION IS MODIFIED BY MOVB ; INSTRUCTIONS TO BRANCH TO THE JUMP INSTRUCTION ; TO THE ROUTINE WANTED. ; THE COMMENTED NUMBER AFTER THE JUMP IS THE VALUE IN THE ; LOW ORDER BYTE TO GET TO THAT JUMP ; ; ROIBR: BR 1$ JMP RDBLK ; 0 1$: JMP ERROR ; 2 JMP CPYMEM ; 4 ; ; ; THE FOLLOWING ARE USED AS PART OF THE FIRST TIME THROUGH ; CODE ONLY AND AS SUCH THOSE ROUTINES RESIDE IN THE BUFFER AREA ; ; JMP SKPHDR ; 6 JMP NXTF1 ; 10 JMP BUFSZZ ; 12 JMP SKP2 ; 14 JMP DONE ; 16 JMP WERR ; 20 ; ; ; THE FOLLOWING ROUTINE IS USED TO INPUT A NEW BLOCK INTO THE ; DRIVERS INTERNAL BUFFER.THIS WILL BE BLOCK NO. N WHOSE VALUE IS ; FOUND IN PTR ; ; RDBLK: MOV #-10240.,@#ROBRC ; 5120 WORD BUFFER MOV #,R4 ; GET THE ADDRESS OF THE BUFER ADD @#ROVEC,R4 ; IN A DRIVER POSITION INDEPENDENT MANNER MOV R4,@#ROCMA ; AND LOAD IT MOVB #4,ROIBR ; WHEN IN COPY PART WANTED TO USERS BUFFER MOV READ,R4 ; GET THE COMMAND BIS UNIT,R4 ; SET THE UNIT NUMBER MOV R4,@#ROC ; HAVE AT IT RETURN ; ; ; ERROR REPORTING ROUTINE ; ; ERROR: MOV ROCQE,R4 ; GET POINTER TO QUE ELEMENT BIS #1,@-2(R4) ; SET HARD ERROR BIT RODONE: BR DONE ; GO TO COMPLETION ROUTINE EXIT ; ; ; COPY THE PORTION OF BUFFER STORED IN DRIVE ; TO USER ; ; CPYMEM: MOV ROCQE,R4 ; GET THE YOU KNOW WHAT TST @#ROC ; WAS THEIR AN ERROR BGE 1$ ; IF NO JST PROCEED WITH THE COPY OPERAQTION MOV @#ROS,R0 ;GET ERROR BIC #42177,R0 ;CLEAR OUT LITTLE ERRORS BEQ 1$ ;LEAVE IF NOT A BIG ERROR DEC CTR ; DEC RETRY COUNTER BLE 2$ ; IF USED UP ALL TRYS-REPORT THE ERROR, AND ; USE THE BUFFER AS IS MOV #-1,@#ROBRC ; OTHERWISE BACK UP FOR ANOTHER TRY MOVB #0,ROIBR MOV SKB,R0 ; GET THE COMMAND BIS UNIT,R0 ; SET THE UNIT NUMBER MOV R0,@#ROC ; ONCE MORE IN TO THE BREACH DEAR FRIENDS RTS PC 2$: BIS #1,@-2(R4) ; REPORT THE ERROR ; ; ; AND CONTINUE AS IF NOTHING HAD HAPPENED ; ; 1$: TST 6(R4) ; WAS IT A SEEK COMMAND BEQ DONE ; IF IT WAS WE ARE DONE 5$: MOV #256.,R5 ; ALL MOVES ARE DONE IN BLOCKS OF ; 256 WORDS OR LESS CMP R5,6(R4) ; IS IT LESS?? BLE 3$ ; IF NO-USE 256. MOV 6(R4),R5 ; IF YES-USE THE LESS 3$: TST NUMB ; CHECK FOR 0 NUMB BNE 77$ ; SPFUN READ--SKIP AHEAD MOV 6(R4),R5 ; USE LARGE COUNT CLR R3 ; START AT BUFFER START ADDRESS BR 78$ ; SKIP AHEAD 77$: MOV (R4),R3 ; GET THE BLOCK NO (256. WORDS/BLOCK ) CLR R2 ; CLEAR UPPER BITS DIV NUMB,R2 ; FIND TAPE RECORD NUMBER SWAB R3 ; MULTIPLY BY 512 ASL R3 78$: ADD #,R3 ; CALCULATE THE BUFFER LOCATION ADD @#ROVEC,R3 ; IN A POSITION INDEPENDENT WAY 4$: .IF EQ,MMG$T ; IF NOT XM MONITOR MOV (R3)+,@4(R4) ; MOVE WORD TO USER BUFFER ADD #2,4(R4) ; BUMP POINTER .IFF ; IF IT IS XM MONITOR MOV (R3)+,-(SP) ; STORE WORD TO BE STORED ON STACK JSR PC,@$PTWRD ; LET MONITOR STORE IT AND BUMP COUNTER .ENDC DEC 6(R4) ; DEC WC DEC R5 ; DEC BLOCK COUNTER BGT 4$ ; ; ; 256 OR LESS WORD BLOCK MOVED ; ; INC (R4) ; INC BLOCK NUMBER TO NEXT BLOCK TST 6(R4) ; WC=0(DONE) BEQ DONE ; IF SO-NO NEED TO HANG AROUND MOV (R4),R3 ; GET BLOCK NUMBER CLR R2 ; CLEAR UPPER BITS DIV NUMB,R2 ; ONLY REALLY WANT REMAINDER TST R3 ; IS REMAINDER NOT 0?? BNE 5$ ; IN SAME BUFFER INC PTR ; OTHERWISE GET ANOTHER BUFFER FULL MOV #8.,CTR JMP RDBLK DONE: CLR @#ROC .DRFIN RO ; GO TO COMPLETION ROUTINE NUMB: .WORD 0 ; NUMBER OF BLOCKS PER RECORD PTR: .WORD 0 ; NUMBER OF 4096 WORD BOCK IN BUFFER CTR: .WORD 0 ; READ RETRY COUNTER UNIT: .WORD 0 ; UNIT NUMBER BCNT: .WORD 0 ; HOLD BYTE COUNT BADDR: .WORD 0 ; BUFFER ADDRESS RW: .WORD M+16 ; REWIND SKF: .WORD M+10 ; SKIP FORWARD SKB: .WORD M+12 ; SKIP BACKWARD READ: .WORD M+2 ; READ WRITE: .WORD M+4 ; WRITE OFF: .WORD M ; OFFLINE EFLE: .WORD M+6 ; EOF ROFBLK: .WORD 0,0,0,0 ; FORK BLOCK ROSYN: .WORD 0,0,0,0,0,-1,0 ; SYNCH BLOCK ROADR: .WORD 0 ; SYNCH ADDRESS ; ; ; THE FOLLOING IS FIRST TIME THORUGH ONLY CODE,SO ; IT RESIDES IN THE SAME AREA AS THE DRIVERS BUFFER ; ; ; ; ; END OF BUFFER VALUE ; ; FSTIM: MOV #402,ROSRT ; RESET NOP TO PERMINATELY BRANCH AROUND ; THE JUMP TO THIS CODE-ONCE IS ENOUGH MOV ROCQE,R0 ; GET QUEUE ADDRESS MOV 2(R0),R0 ; GET UNIT NUMBER BIC #174377,R0 ; ISOLATE BITS MOV R0,UNIT ; SAVE UNIT NUMBER MOV #,R0 ; GET MESSAGE ADDRESS ADD @#ROVEC,R0 ; USEING A NOW FAMILIAR DRILL .PRINT ; TO PRINT OUT THE REQUEST MESSAGE CLR R1 ; ; ; GET THE DLU FILE NUMBER ; ; 1$: .TTYIN CMPB #15,R0 ; WAS IT BEQ 1$ ; IGNORE THEM CMPB #12,R0 ; WAS IT BEQ 2$ ; KEY ON THOSE AS END OF LINES SUB #60,R0 ; CONVERT IT TO BINARY BLT 1$ ; IF NOT A DIGIT-IGNORE IT CMPB #8.,R0 ; WAS IT A NON OCTAL CHR BLE 1$ ; IF SO IGNORE THEM TO ASL R1 ; TIMES TWO MOV R1,-(SP) ; STACK IT ASL R1 ; TIMES FOUR ASL R1 ; TIMES EIGHT ADD (SP)+,R1 ; MULT R1 BY 10 ADD R0,R1 ; AND PUT IN NEW DIGIT BR 1$ ; GET NEXT CHR 2$: MOV R1,FILNO ; STORE FILE NUMBER MOVB #14,ROIBR ; AFTER REWIND-SKIP THE HEADER MOV UNIT,@#ROC ;SELECT UNIT BIT #40,@#ROS ; ARE WE AT LOAD POINT?? BNE SKPHDR ; YES MOV RW,R1 ; GET COMMAND BIS UNIT,R1 ; SET UNIT NUMBER MOV R1,@#ROC ; REWIND TO BOT RTS PC ROMSG: .ASCII /?RO-I-Enter DLU file number: / .BYTE 200 .EVEN FILNO: .WORD 0 ; ; ; READ THE FIRST RECORD OF THE FILE ; ; SKPHDR: MOV UNIT,@#ROC ;SELECT UNIT BIT #2000,@#ROS ; END OF TAPE?? BNE EOV ; YES BIT #40,@#ROS ; ARE WE AT LOAD POINT?? BNE SKP2 ; YES BIT #40000,@#ROS ; END OF FILE?? BEQ NXT1A ; NO, SKIP AGAIN SKP2: MOV #-2.,@#ROBRC ; 1 WORD MOV #,R4 ; GET THE ADDRESS OF THE BUFFER ADD @#ROVEC,R4 ; IN A DRIVER POSITION INDEPENDENT MOV R4,@#ROCMA ; MANNER AND LOAD IT MOVB #12,ROIBR ; DETERMINE BUFFER SIZE ROUTINE MOV READ,R4 ; GET THE COMMAND BIS UNIT,R4 ; SET THE UNIT NUMBER MOV R4,@#ROC ; READ IT RETURN ; ; ; END OF VOLUME CODE ; ; EOV: MOV ROCQE,R4 ; POINTER TO QUEUE ELEMENT MOV 2(R4),R0 ; GET JOB NUMBER BIC #103777,R0 ; ISOLATE BITS SWAB R0 ; MOVE BITS AROUND ASR R0 ; TO THE RIGHT ASR R0 ; TO THE RIGHT ASR R0 ; TO THE RIGHT MOV R0,ROSYN+2 ; FILL IN JOB NUMBER AGAIN: .SYNCH ROSYN,PIC ; SYNCH IT BR AGAIN ; TRY UNTIL DONE MOV R0,-(SP) ; SAVE R0 MOV #,R0 ; GET MESSAGE ADDRESS ADD @#ROVEC,R0 ; USING A NOW FAMILIAR DRILL .PRINT ; ALERT USER MOV #-1,@#ROBRC ; SKIP BACK ONE RECORD MOVB #2,ROIBR ; WHEN SKIP DONE-DO ERROR MOV SKB,R0 ; GET THE COMMAND BIS UNIT,R0 ; SET THE UNIT NUMBER MOV R0,@#ROC ; EXECUTE MOV (SP)+,R0 ; RESTORE R0 RETURN EOVM: .ASCIZ /?RO-F-End of volume/ .EVEN ; ; ; DETERMINE NUMBER OF BLOCKS PER RECORD ; ; BUFSZZ: MOV UNIT,@#ROC ;SELECT UNIT BIT #2000,@#ROS ; END OF TAPE?? BNE EOV ; YES BIT #40000,@#ROS ; END OF FILE?? BNE EOV ; YES CMP #"RL,BUFFER ; IS IT AN RL?? BEQ RLBUF ; YES ; ; ; ASSUME AN RK ; ; BUZ: MOV #12.,NUMB ; NUMBER OF BLOCK PER RECORD BR NXTF1 ; CONTINUE RLBUF: MOV #20.,NUMB ; NUMBER OF BLOCKS PER RECORD ; ; ; THE NEXT TWO ROUTINE ARE USED TO SKIP TO THE DLU FILE ; WANTED ; ; NXTF1: TST FILNO ; WAS FILE 0 SECIFIED BEQ 1$ ; IF YES NO NEED TO DEC AS FILE 0 AND 1 ARE THE ; SAME DEC FILNO ; HOW MANY FILES NEED TO BE SKIPED 1$: TST FILNO ; IF NONE THEN BLE JST2 ; JUST SKIP THE NEXT BLOCK OF DATA NXT1A: CLR @#ROBRC ; 65K SKIP MOVB #6,ROIBR ; WHEN SKIP COMPLETED GO TO SKPHDR MOV SKF,R0 ; GET THE COMMAND BIS UNIT,R0 ; SET THE UNIT NUMBER MOV R0,@#ROC ; HAVE AT IT RTS PC ; ; ; NOW IN RIGHT FILE ; ; JST2: MOV ROCQE,R4 ; GET POINTER TO QUE ELEMENT TST 6(R4) ; IS IT READ OR WRITE BGE 1$ ; IF LT 0 THEN ERROR-THIS IS A READ ONLY DEVICE BIS #1,@-2(R4) ; SET HARD ERROR BIT CLR 6(R4) ; TURN INTO A SEEK 1$: MOV #8.,CTR ; SET READ TRY COUNTER TO 8 TRYS MOV (R4),R3 ; GET THE BLOCK NO (256. WORDS/BLOCK ) CLR R2 ; CLEAR DIVISOR DIV NUMB,R2 ; RECORD NUMBER ON TAPE MOV R2,R1 ; WORK ON COPY ONLY MOV R1,PTR ; UPDATE POINTER BEQ JST2D ; IF ZERO NO SKIP NEG R1 ; USE 2'S COMP ONLY MOV R1,@#ROBRC ; JST 2 MORE BLOCKS TO GO MOVB #0,ROIBR ; WHEN DONE HERE READ BLOCK MOV SKF,R1 ; GET THE COMMAND BIS UNIT,R1 ; SET THE UNIT NUMBER MOV R1,@#ROC ; JST AN EASY BUMP RTS PC JST2D: JMP RDBLK ; READ A BUFFER ; ALLOW SPACE FOR THE 5120 WORD BUFFER BUFFER: BUFEND =.+10240.+2 A =. . =.-+10240. .DREND RO .END