.TITLE X1DR/X1DW ; ; 12/04/79 LEN - +++1 BUG IF WORD TO READ/WRITE IS LAST WORD IN ; BLOCK 256/512 ETC. DEC R3 DOES NOT SET CARRY BIT. ; ; BLOCKED DISK READ WRITE ; ; CALL X1DR (ID, NR, NWR, IOAR) ; WHERE - ; ID = 6 WORD ID BLOCK (SEE X1LU) ; NR = RECORD # TO BEGIN READING ; NWR = # OF I*2 WORDS TO READ ; IOAR = BUFFER AREA TO ACCEPT DATA ; ; CALL X1DW (ID, NR, NWW, IOAR) ; ; WHERE - ; ID = 6 WORD ID BLOCK ; NR = RECORD # TO BEGIN WRITE ; NWW = # I*2 WORDS TO WRITE ; IOAR = OUTPUT AREA ; ; SAME AS ABOVE BUT DATA IS TRANSFERRED FROM IOAR TO ; THE BUFFER AREA AND EVENTUALLY TO DISK ; ; ; ** NOTE ** ; NR IS ASSUMED TO BE I*2 UNLESS BIT 0 IS SET IN ID(5). ; SEE X1LU. ; ; ; DEFINE THE OFFSETS IN THE ID BLOCK ; IOF = 0 ; OFFSET FROM ID BLOCK TO BUFFER AREA (NOT USER BUFFER) NBUF = 2 ; NUMBER OF BUFFERS ALLOCATED LUN = 3 ; LOGICAL UNIT # NWPR = 4 ; NUMBER OF I*2 WORDS PER RECORD NBIB = 6 ; VIRTUAL BLOCK # OF FIRST BLOCK STORED IN BUFFER USFLG = 10 ; USER FLAGS (E.G. I*4 FLAG) X1FLG = 11 ; X1 FLAGS (MODIFIED BLOCK) NWIB = 12 ; NUMBER OF I*2 WORDS OF VALID DATA IN BUFFER I4FLG = 1 ; BIT 0 SET IF I*4 RECORD NUMBER PASSED MODIF = 1 ; BIT 0 SET IF MODIFIED BLOCK N1WPB = 256. ; NUMBER OF I*2 WORDS PER DISK BLOCK ; ; DATA AREAS ; NBUFR: .WORD 0 ; NUMBER OF BUFFERS NBF256: .WORD 0 ; NBUFR*256. NARGRD: .WORD 5 ; # OF ARGUMENTS IN DBKRD CALL NARGWR: .WORD 4 ; # OF ARGUMENTS IN DBKWR CALL NLUN: .WORD 0 ; LUN IBLOCK: .WORD 0 ; SCRATCH - VBN TO READ/WRITE RWFLG: .WORD 0 ; READ/WRITE FLAG 0=READ, NON-0 = WRITE NWRM: .WORD 0 ; SCRATCH - NUMBER OF WORDS REQUESTED TO MOVE UBUFA: .WORD 0 ; SCRATCH - USER BUFFER ADDRESS ; ; SCRATCH AREA FOR CALLS TO DBKRD/WR ; CALLRD: .WORD NARGRD ; NUMBER OF PARMS .WORD NLUN ; LUN .WORD IBLOCK ; VBN BUFAD: .WORD 0 ; TRANSFER AREA ADDRESS .WORD NBF256 ; ADDR OF # WORDS TO R/W .WORD 0 ; (DBKRD ONLY), # OF WORDS ACTUALLY READ ; CALLWR: .WORD NARGWR ; # OF PARMS FOR WRITE .WORD NLUN ; LOGICAL UNIT # .WORD 0 ; ID(4) - VBN IN BUFFER .WORD 0 ; BUFFER ADDRESS .WORD 0 ; # OF WORDS TO WRITE (ID(6)) ; X1DR:: CLR RWFLG ; CLEAR FOR READ BR COMMON ; X1DW:: MOV #1,RWFLG ; NON-ZERO FOR WRITE ; ;; COMMON: CALL $SAVAL ; SAVE EVERYTHING ; ; R4 WILL POINT TO THE ID BLOCK THROUGOUT ; MOV 2(R5),R4 ; ID BLOCK ADDRESS ; ; GET LUN AND NBUF ; MOVB LUN(R4),NLUN ; LUN TO I*2 WORD MOVB NBUF(R4),R0 ; # OF BUFFERS TO I*2 WORD MOV R0,NBUFR ; SAVE IT ASH #8.,R0 ; *256. FOR # OF WORDS IN BUFFER MOV R0,NBF256 ; SAVE IT FOR READ MOV 10(R5),UBUFA ; GET USER BUFFER ADDRESS MOV @6(R5),NWRM ; # WORDS TO READ/WRITE BGT 20$ ; INVALID NW TO MOVE ? YES IF LE JMP 280$ 20$: ; ; COMPUTE THE BUFFER ADDRESS ; MOV R4,R0 ; ID BLOCK ADDRESS ASH #-1,R0 ; WORD ADDRESS ADD IOF(R4),R0 ; ADD OFFSET TO BUFFER (MAY BE NEGATIVE - ; ; THAT'S WHY THE CALCULATION WAS DONE IN ; ; WORDS RATHER THAN BYTE ADDRESSES. DEC R0 ; ADDR FROM 0, NOT 1 LIKE FORTRAN ASL R0 ; BACK TO BYTE ADDRESS MOV R0,CALLRD+6 ; TO PARM LIST FOR DBKRD MOV R0,CALLWR+6 ; AND DBKWR ; ; GET THE REQUESTED RECORD NUMBER AND UPDATE IT BEFORE WE DO ; ANYTHING ELSE ; MOV NWPR(R4),R0 ; NEEDED FOR DMUL LATER MOV NWRM,R3 ; # WORDS TO TRANSFER ADD R0,R3 ; PLUS RECORD LENGTH DEC R3 ; MINUS 1 TO ROUND RECORD POINTER UP IF ; ; LESS THAN A NWPR(R4) TRANSFERRED CLR R2 ; FOR DIVIDE DIV R0,R2 ; R2=# OF RECORDS TRANSFERRED MOV R2,R1 ; SAVE # RECS FOR FOLLOWIN UPDATE ; ; GET THE RECORD # AND UPDATE IT ; MOV 4(R5),R5 ; MIGHT BE I*4, R5 NO LONGER NEEDED MOV (R5),R3 ; LOW ORDER WORD FOR SURE CLR R2 ; CLEAR HIGH ORDER IF NOT I*4 BITB #I4FLG,USFLG(R4); I*4 ? BEQ 30$ ; NO MOV 2(R5),R2 ; YES ! 30$: ADD R1,(R5) ; ADD TO LOW ORDER BITB #I4FLG,USFLG(R4); CHECK IT AGAIN TO ADD CARRY BEQ 35$ ; IT'S NOT ADC 2(R5) ; ADD CARRY TO HIGH ORDER 35$: ; ; R0 CONTAINS MULTIPLIER AND R2,R3 CONTAIN THE I*4 RECORD # READY ; FOR THE DOUBLE PRECISION MULTIPLY ; ; WE NEED TO FIND THE ABSOLUTE WORD THIS IS IN THE FILE SO ; SUB #1,R3 ;+++1 DO IT FROM ZERO RELATIVE SBC R2 ; AND THE HIGH ORDER WORD CALL $DMUL ; MULTIPLY BY # WORDS PER RECORD ; ; NOW DIVIDE BY I*2 WORDS PER BLOCK TO GET BLOCK # THIS RECORD IS ; IN AND THE OFFSET IN WORDS FROM THE START OF THE BLOCK. ; RESULT IN R0,R1 ; DIV #N1WPB,R0 ; R0=BLOCK, R1=WORD OFFSET INC R0 ; BLOCK FROM 1 RELATIVE MOV R0,IBLOCK ; AND SAVE IT FOR DBKRD ; ; FIND THE OFFSET INTO THE BUFFER AND CHECK IF THE NEEDED RECORD ; IS ALREADY IN THE BUFFER. ; SUB NBIB(R4),R0 BLT 205$ ; NOPE CMP R0,NBUFR ; MIGHT BE ? BGE 205$ ; DEFINITELY NOT IN THE BUFFER ; ; FINISH THE OFFSET INTO BUFFER CALCULATION ; ASH #8.,R0 ; BLOCK OFFSET * 256. TO GET WORDS ADD R0,R1 ; PLUS THE WORD OFFSET ; ; FROM THIS POINT ON R1 WILL CONTAIN THE OFFSET FROM THE START OF ; THE BUFFER AREA TO THE START OF TRANSFER INTO/OUT OF THE BUFFER ; BR 220$ ; GO DO THE MOVE SINCE IT'S IN MEMORY ; ; ; ; GET SET UP FOR DBKRD/WR ; ; 205$: MOV R1,-(SP) ; SAVE THE IMPORTANT REGISTERS MOV R4,-(SP) ; MOV R4,R0 ; ID BLOCK ADDRESS ADD #6,R0 ; ID(4) - BLOCK # TO WRITE FOR DBKWR MOV R0,CALLWR+4 ADD #4,R0 ; ID(6) - RECEIVE # OF WORDS ACTUALLY READ MOV R0,CALLWR+10 ; # OF WORDS TO WRITE FOR DBKWR AND MOV R0,CALLRD+12 ; RECEIVE # OF WORDS ACTUALLY READ ; ; ALL SET TO CALL THEM, CHECK IF THE BUFFER HAS BEEN MODIFIED. ; IF NOT, NO WRITE NECESSARY SO JUMP RIGHT TO DBKRD ; BITB #MODIF,X1FLG(R4); MODIFIED ? BEQ 210$ ; NO, GO DO THE READ ; ; ACTUALLY WRITE TO THE DISK HERE ; MOV #CALLWR,R5 ; R5 SEQUENCE CALL DBKWR ; ; READ IN THE NEW BLOCK(S) HERE FROM DISK ; 210$: MOV (SP),R4 ; GET R4 FOR A MINUTE MOV IBLOCK,NBIB(R4) ; UPDATE VBN HELD IN BUFFER BICB #MODIF,X1FLG(R4); INDICATE NOT MODIFIED MOV #CALLRD,R5 ; R5 SEQUENCE CALL DBKRD ; DO IT ; ; CLEAN UP THE STACK ; MOV (SP)+,R4 MOV (SP)+,R1 ; ; ; FIND # OF WORDS TO MOVE ; IF # WORDS REQUESTED IS MORE THAN THE # OF WORDS LEFT IN THE ; BUFFER THEN THEN THE TRANSFER IS SPLIT INTO MULTIPLE MOVES ; BECAUSE THE BUFFER WILL NEED TO BE RENEWED. ; ; 220$: MOV NBF256,R0 ; NBUFR*256. SUB R1,R0 ; = # WORDS LEFT IN BUFFER FROM START OF XFR CMP NWRM,R0 ; WHICH IS LESS ? BGE 225$ MOV NWRM,R0 ; # WORDS REQUESTED ARE LEFT IN BUFFER 225$: SUB R0,NWRM ; DECREMENT # OF WORDS REQUESTED TO MOVE ; ; SET UP BUFFER ADDRESS AND USER ADDRESS ; MOV R1,R3 ; COMPUTE BUFFER ADDRESS ADD R0,R1 ; R1 HAS MAX WORDS WRITTEN TO BUFFER ASL R3 ; WORDS TO BYTE OFFSET ADD BUFAD,R3 ; PLUS BUFFER BASE ADDRESS MOV UBUFA,R2 ; USER AREA ADDRESS ; ; MOVE THE DATA - ; R0 - # OF WORDS TO MOVE ; R2 - USER AREA ADDRESS ; R3 - X1XX BUFFER AREA ADDRESS ; ; CHECK READ/WRITE FLAG ; TST RWFLG BNE 240$ ; ; READ - MOVE FROM BUFFER TO USER AREA ; 230$: MOV (R3)+,(R2)+ SOB R0,230$ BR 250$ ; ; WRITE - MOVE FROM USER AREA TO BUFFER AREA ; 240$: MOV (R2)+,(R3)+ SOB R0,240$ BISB #MODIF,X1FLG(R4); INDICATE BUFFER MODIFIED CMP NWIB(R4),R1 ; MAX # OF WORDS IN BUFFER ? BGE 250$ MOV R1,NWIB(R4) ; # WORDS IN BUFFER EXTENDED BEYOND OLD VALUE ; ; CHECK IF ALL DATA TRANSFERED ; 250$: TST NWRM ; ANY LEFT ? BLE 280$ ; NO, RETURN MOV R2,UBUFA ; YES, UPDATE USER AREA POINTER MOV NBIB(R4),R0 ; GET NEXT BLOCK TO READ ADD NBUFR,R0 ; OLD BLOCK PLUS NBUFR MOV R0,IBLOCK ; SAVE FOR DBKRD CLR R1 ; ZERO WORD OFFSET INTO BUFFER SINCE WE'LL ; ; BE MOVING DATA FROM/TO THE START OF THIS ; ; NEW BUFFER BR 205$ ; LOOP BACK FOR MORE ; ; ALL DONE ; 280$: RETURN .END