.TITLE MAG TAPE ROLLOUT FILE READER DRIVER (RT-11 V03) .IDENT /V02/ ; SET MACROS .MCALL ..V2..,.PRINT,.TTYIN,.FORK,.DRBEG,.DRAST,.DRFIN,.DREND ..V2.. ;SET ADDRESSES ROS=172520 ROC=172522 ROBRC=172524 ROCMA=172526 ROVEC=224 ; BITS 800 BPI 9-TRACK/DUMP MODE 7-TRACK,INTERUPT ENABLE,GO M=60101 ; COMMAND CONSTANTS RW=M+16 SKF=M+10 SKB=M+12 READ=M+2 ; DEFINE CONDITIONAL ASSEMBLY PARAMETERS .IIF NDF,MMG$T,MMG$T=0 ;IF NOT XM MONITOR .IIF NDF,ERL$G,ERL$G=0 ;IF NO ERROR LOGGER .IIF NDF,TIM$IT,TIM$IT=0 ;IF NO TIME OUT ; BEGINING OF INITALIZATION CODE .DRBEG RO,ROVEC,11300,100034 ;SET UP HEADER INFO RO: 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),R2 ;GET THE BLOCK NO (256. WORDS/BLOCK ) CCC ;CONVERT TO BLOCK NUMBER FOR 4096 WORDS/BLOCK ROR R2 ASR R2 ASR R2 ASR R2 ;DIVIDE BY 16 TO GET IT 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,@#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,@#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 ; 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 BRANCE 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 NXTF2 ;12 ; THE FOLLOWING ROUTINE IS USED TO INPUT A NEW BLOCK INTO THE ; DRIVERS INTERNAL BUFFER.THIS WILL BE BLOCK NO N WHOS VALUE IS ; FOUND IN PTR RDBLK: MOV #-8192.,@#ROBRC ;4K WORDS/8K BYTES 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,@#ROC ;HAVE AT IT RTS PC ; ERROR REPRTING ROUTINE ERROR: MOV ROCQE,R4 ;GET POINTER TO QUE ELEMENT BIS #1,@-2(R4) ;SET HARD ERROR BIT 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 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,@#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$: MOV (R4),R3 ;NOW WE NEED THE POSITION IN THE BUFFER OF THE ;256 WORD BLOCK WANTED BIC #177760,R3 ;CLEAR OFF THE UNNEEDED BITS SWAB R3 ;MULTIPLY BY 512 ASL R3 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 #,R2 ADD @#ROVEC,R2 CMP R3,R2 ;DO WE NEED ANOTHER BUFFER FULL BLT 5$ ;IF NO JST GET ANOTHER BLOCK INC PTR ;OTHERWISE GET ANOTHER BUFFER FULL MOV #8.,CTR JMP RDBLK DONE: CLR @#ROC .DRFIN RO ;GO TO COMPLETION ROUTINE PTR: .WORD 0 ;NUMBER OF 4096 WORD BOCK IN BUFFER CTR: .WORD 0 ;READ RETRY COUNTER ROFBLK: .WORD 0,0,0,0 ;FORK BLOCK ; THE FOLLOING IS FIRST TIME THORUGH ONLY CODE,SO ; IT RESIDES IN THE SAME AREA AS THE DRIVERS 4K BUFFER BUFFER: BUFEND=.+8192. ;END OF BUFFER VALUE FSTIM: MOV #402,RO ;RESET NOP TO PERMINATELY BRANCH AROUND ;THE JUMP TO THIS CODE-ONCE IS ENOUGH MOV #,R0 ;GET MESSAGE ADDRESS ADD @#ROVEC,R0 ;USEING A NOW FAMILIAR DRILL .PRINT ;TO PRINT OUT THE REQUEST MESSAGE CLR R1 ; GET THE ROLLIN FILE NUMBER(OCTAL) 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 ;MULT R1 BY 8 ASL R1 ASL R1 ADD R0,R1 ;AND PUT IN NEW DIGIT BR 1$ ;GET NEXT CHR 2$: MOV R1,FILNO ;STORE FILE NUMBER MOVB #6,ROIBR ;AFTER REWIND-SKIP THE HEADER BIT #40,@#ROS ;ARE WE ALREADY AT LOAD POINT BNE SKPHDR ;NO NEED TO ISSUE REWIND-GO TO NEXT STEP MOV #RW,@#ROC ;REWIND TO BOT RTS PC ROMSG: .ASCII /ROLLIN FILE NO(8) ?/ .BYTE 200 .EVEN FILNO: .WORD 0 ;THE FIRST ROLLOUT FILE ON THE TAPE HAS 4 HEADER BLOCKS ; VICE 2 FOR ALL THE OTHRES-SO SKIP 2 TO ALLOW FOR THAT ; FACT LASTER SKPHDR: MOV #-2,@#ROBRC ;SKIP 2 BLOCKS FROM BOT MOVB #10,ROIBR ;NEXT ROUTINE IS NXTF1 MOV #SKF,@#ROC ;BUMP IT UP TWO RTS PC ; THE NEXT TWO ROUTINE ARE USED TO SKIP TO THE ROLLIN 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 2 NEXT BLOCKTS TO DATA NXT1A: MOV #100000,@#ROBRC ;START 32K RECORD SKIP COUNT MOVB #12,ROIBR ;WHEN SKIP COMPLETED GO TO NXTF2 MOV #SKF,@#ROC ;HAVE AT IT RTS PC NXTF2: BIT #40000,@#ROS ;WAS SKIP ENDED BY EOF(TAPE MARK) FOUND BEQ NXT1A ;IF NOT CONTINUE SKIP DEC FILNO ;ONE (MORE) FILE DOWN BGT NXT1A ;MORE TO GO ; 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),R2 ;GET THE BLOCK NO (256. WORDS/BLOCK ) CCC ;CONVERT TO BLOCK NUMBER FOR 4096 WORDS/BLOCK ROR R2 ASR R2 ASR R2 ASR R2 ;DIVIDE BY 16 TO GET IT MOV R2,R1 ;WORK ON COPY ONLY MOV R1,PTR ;UPDATE POINTER ADD #2,R1 ;2 MORE ADDITIONAL BLOCKS TO GET TO ONE TO BE READ 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,@#ROC ;JST AN EASY BUMP RTS PC ; ALLOW SPACE FOR THE 4K WORD BUFFER A=. .=.-+8192. .DREND RO .END