.TITLE FILEIO .IDENT /1401.5/ ; ; ; ; WRITTEN BY RAY DI MARCO ; 14-JAN-81. ; ; ; VERSION 140181/05. ; ; ;----------------------------------------------------------------- ; ; ; THIS MODULE CONTAINS THE DATABASE FILE I/O SUPPORT ROUTINES. THE ; FILE SUPPORT MODULE 'FILSPT' IS USED TO CARRY OUT THE ACTUAL I/O. ; THE FDB ARE DEFINED IN THE 'FORM DESCRIPTOR FILE'. THE ROUTINES ; PRESERVE ALL REGISTERS, AND TERMINATE THE PROGRAM ON ERROR AFTER ; DISPLAYING THE CUASE OF THE ERROR. AT ENTRY 'R0' HOLDS THE RECORD/KEY ; NUMBER REQUIRED. THE ROUTINES ARE ; ; FIL.DR/FIL.DW READ/WRITE RECORD R0 FROM DISK TO THE USER BUFFER ; ; FIL.KR/FIL.KW READ/WRITE KEYS R0 FROM DISK TO THE USER BUFFER ; ; FIL.PR/FIL/PW READ/WRITE THE PARAMETER BLOCK TO/FROM DISK. ; ; ; .SBTTL MODIFICATIONS ; ; ; 2-MAR-81 REFRENCE FORM TABLE INDERECTLY VIA '$$FORM' (FOR 'DBSFOR') ; CHANGE 'RECBLK', 'FIL.DR' AND 'FIL.DW' TO SUPPORT NEG BF ; CHANGE 'FIL.KR' SO THAT ACCESS OF REC 1 --> FORCES READ ; 13-MAR-81 IN 'FIL.DR/FIL.DW' - PRESERVE R1 ; 10-SEP-81 CHANGE 'KEYBLK' TO SUPPORT MORE THAN 4000 KEYS! ; 17-Sep-81 Correct "KEYBLK" to properly map KEYNUMBER > 2048! ; ; ; ; ; .SBTTL DECLARATIONS ; ; .MCALL FILSPT,.EXIT ; SYSTEM MACROS .MCALL .PUSH,.POP ; STACKING FILSPT ; INVOKE FILE SUPPORT ; ; .GLOBL FIL.DR,FIL.DW ; DATA READ/WRITE ENTRIES .GLOBL FIL.KR,FIL.KW ; KEY READ/WRITE .GLOBL FIL.PR,FIL.PW ; READ/WRITE PARAMETER FILE .GLOBL FILINT ;; INITIALIZE ENTRY ; .GLOBL $$FORM ;; HOLDS ADDRESS 'FORM$$' .GLOBL KEY$$B ; KEY BUFFER .GLOBL FIL.ST ; "FILSPT" ; ; ; .PSECT CODE ; OPEN CODE SECTION ; ------ ---- ; ; ; ; ; .SBTTL INITIALIZATION ; ; ; OPEN ALL FILES AND THEN READ IN FIRST BLOCK(S). ; ; .PSECT INITLZ ; OPEN INITIALIZATION PSECT ; ------ ------ ; CALL FILINT ;; INITIALIZE FILES ; ; .PSECT CODE ;; ENTER CODE SECTION ; ------ ---- ; ; ; FILINT: MOV $$FORM,R4 ; R4 --> FORM .IRP X,<16,20,22> ; --- DO FOR ALL FILES --- PURGE X(R4) ; ENSURE CHANNEL FREE LOOKUP ERROR=100$ ; LOOKUP PARAMETER FILE READ ERROR=100$ ; READ IN BLOCK 0 .ENDR ; ------------------------ RETURN ; ALL DONE ; 100$: CALL FIL.ST ; DISPLAY CAUSE OF ERROR .EXIT ; BYE ; ; ; ; ; ; .SBTTL ROUTINE - 'FIL.DR' ... READ IN DATA ; ; ; AT ENTRY R0 HOLDS RECORD TO READ. USE 'RECBLK' TO TRANSLATE ; RECORD NUMBER TO A BLOCK NUMBER, AND READ IN REQUIRED BLOCK ; IF NOT ALREADY IN MEMORY. THEN TRANSFER THE RECORD INTO ; THE USER RECORD BUFFER. EXIT ON ANY ERROR. ; ; ; FIL.DR: .PUSH ;; SAVE MOV $$FORM,R5 ;; R5 --> FORM CALL RECBLK ; MAP REC NUMBER -> BLOCK NUMBER BCS 700$ ; ILLEGAL NUMBER -> SKIP MOV 20(R5),R5 ; R5 --> 'FDBDAT' CMP R0,FDB.BL(R5) ; BLOCK IN CORE? BEQ 100$ ; YES -> SKIP READ READ BLOCK=R0,ERROR=1000$ ; READ IN BLOCK ; 100$: MOV FDB.BF(R5),R5 ; R5 --> DATA ADD RECOFS,R5 ; R5 --> RECORDS DATA IN BUFFER MOV $$FORM,R0 ; R0 --> FORM MOV (R0),R1 ; R1 --> RECORD MOV 6(R0),R0 ; R0 = SIZE 110$: MOVB (R5)+,(R1)+ ; COPY SOB R0,110$ ; LOOP .POP ;; RESTORE CLC ; CLEAR FAIL FLAG RETURN ; ALL DONE ; ; 700$: .POP ;; RESTORE SEC ; SET FAILED RETURN ; EXIT ; 1000$: CALL FIL.ST ; DISPLAY CAUSE OF ERROR .EXIT ; QUIT ; ; ; ; ; ; .SBTTL ROUTINE - 'FIL.DW' ... WRITE OUT DATA ; ; ; TRANSLATE RECORD NUMBER TO A BLOCK NUMBER, AND THEN WRITE OUT ; DATA IN USER BUFFER TO FILE. EXIT ON ANY ERROR. ; ; FIL.DW: .PUSH ;; SAVE MOV $$FORM,R5 ;; R5 --> FORM CALL RECBLK ; MAP REC NUMBER -> BLOCK NUMBER BCS 700$ ; ILLEGAL NUMBER -> SKIP MOV 20(R5),R5 ; R5 -> FDBDAT READ BLOCK=R0,ERROR=1000$ ; ENSURE BLOCK IN MEMORY ; MOV FDB.BF(R5),R5 ; R5 --> DATA ADD RECOFS,R5 ; R5 --> RECORDS DATA IN BUFFER MOV $$FORM,R0 ; R0 --> FORM MOV (R0),R1 ; R1 --> RECORD MOV 6(R0),R0 ; R0 = SIZE 110$: MOVB (R1)+,(R5)+ ; COPY SOB R0,110$ ; LOOP ; MOV $$FORM,R5 ; R5 --> FORM MOV 20(R5),R5 ; R5 -> FDBDAT WRITE ERROR=1000$ ; OUTPUT RECORD .POP ;; RESTORE CLC ; CLEAR FAIL FLAG RETURN ; ALL DONE ; ; 700$: .POP ;; RESTORE SEC ; SET FAILED RETURN ; EXIT ; 1000$: CALL FIL.ST ; DISPLAY CAUSE OF ERROR .EXIT ; QUIT ; ; ; ; ; ; .SBTTL ROUTINE - 'FIL.KR' ... READ IN KEYS ; ; ; TRANSLATE RECORD NUMBER TO BLOCK NUMBER, AND READ IN REQUIRED BLOCK ; IF NOT IN MEMORY, THEN TRANSFER KEYS INTO USER BUFFER. ; ; FIL.KR: .PUSH ; SAVE MOV $$FORM,R5 ;; R5 --> FORM CMP R0,#1 ;; READING KEY 1? BNE 40$ ;; NO -> SKIP MOV 22(R5),R4 ;; R4 --> FDBKEY MOV #-1,FDB.BL(R4) ;; ENSURE READ IS FORCED ; 40$: CALL KEYBLK ; MAP KEY TO BLOCK NUMBER MOV 22(R5),R5 ; R5 --> FDBKEY CMP R0,FDB.BL(R5) ; WANTED BLOCK IN MEMORY? BEQ 100$ ; YES -> SKIP READ BLOCK=R0,ERROR=1000$ ; READ BLOCK ; 100$: ADD FDB.BF(R5),R4 ; R4 --> SOURCE MOV #KEY$$B,R5 ; R5 --> DESTINATION MOV #16.,R0 ; 16 WORDS IN KEY 200$: MOV (R4)+,(R5)+ ; COPY SOB R0,200$ ; LOOP .POP ; RESTORE RETURN ; EXIT ; ; ; 1000$: CALL FIL.ST ; DISPLAY CAUSE OF ERROR .EXIT ; QUIT ; ; ; ; ; ; .SBTTL ROUTINE - 'FIL.KW' ... WRITE OUT SPECIFIED KEY ; ; ; TRANSLATE RECORD NUMBER TO BLOCK NUMBER, ENSURE THAT BLOCK ; IS IN MEMORY, THEN COPY USER KEYS TO FILE BUFFER AND WRITE IT ; OUT. ; ; FIL.KW: .PUSH ; SAVE MOV $$FORM,R5 ;; R5 --> FORM CALL KEYBLK ; MAP KEY TO BLOCK NUMBER MOV 22(R5),R5 ; R5 --> FDBKEY CMP R0,FDB.BL(R5) ; IN MEMORY? BEQ 100$ ; YES -> SKIP READ BLOCK=R0,ERROR=1000$ ; INPUT BLOCK ; 100$: .PUSH R5 ; SAVE - NEED LATER ADD FDB.BF(R5),R4 ; R4 --> DESTINATION MOV #KEY$$B,R5 ; R5 --> SOURCE MOV #16.,R0 ; 16 WORDS IN KEY 200$: MOV (R5)+,(R4)+ ; COPY SOB R0,200$ ; LOOP .POP R5 ; RESTORE FDB ADDRESS WRITE ERROR=1000$ ; WRITE OUT KEYS .POP ; RESTORE CLC ; CLEAR FAIL RETURN ; EXIT ; ; ; 1000$: CALL FIL.ST ; DISPLAY CAUSE OF ERROR .EXIT ; QUIT ; ; ; ; ; ; .SBTTL ROUTINES - 'FIL.PR'\'FIL.PW' ... READ\WRITE PARAMETER FILE ; ; ; ; FIL.PR: RETURN ; NOP- BLOCK ALREADY IN MEMORY ; ; FIL.PW: MOV $$FORM,R5 ;; ADDRESS FORM -> R5 MOV 16(R5),R5 ; ADDRESS FDB -> R5 WRITE ERROR=1000$ ; OUTPUT BLOCK RETURN ; EXIT ; 1000$: CALL FIL.ST ; DISPLAY CAUSE OF ERROR .EXIT ; EXIT TIME ; ; ; ; ; ; .SBTTL ROUTINE - 'RECBLK' ... TRANSLATE RECORD NUMBER -> DISK BLOCK ; ; ; RECBLK: CMP R0,14(R5) ; LEGAL ENTRY NUMBER? BHI 1000$ ; NO -> SKIP TST 12(R5) ; + - B.F.? BMI 200$ ; - --> 200$ ; .PUSH ; SAVE MOV 12(R5),R1 ; BLOCKING FACTOR -> R1 BEQ 100$ ; 0 -> ASSUME BF = 1 MOV R0,R2 ; COPY RECORD NUMBER -> R2 CLR R0 ; START AT BLOCK 0 10$: ADD R2,R0 ; FIND BLOCK ... SOB R1,10$ ; ... TO READ/WRITE 100$: .POP ; RESTORE CLR RECOFS ; SET RECORD OFFSET TO 0 RETURN ; EXIT ; ; ; ; ; ; IF GET HERE ARE PROCESSING A FILE WITH A NEGATIVE BF. THE RELATION- ; SHIP BETWEEN BF AND RECOORD NUMBER IS A FOLLOWS ; ; BF -1 -2 -3 -4 -5 -6 -7 ; REC/BLK 1 2 4 8 16 32 64 ; ; ; ; 200$: .PUSH ; SAVE MOV 12(R5),R1 ; R1 == BF NEG R1 ; MAKE POSITIVE CLR R2 ; OFFSET = 0 DEC R1 ; 1 -> 0 MOV R0,R3 ; REC NUM -> R4 MOV R1,R4 ; SAVE IN R4 BEQ 300$ ; IF DONE -> EXIT ; 210$: ASR R0 ; R0/2 -> R0 SOB R1,210$ ; LOOP ; ASL R4 ; BF -> R4 BIC 600$(R4),R3 ; R3 == LOW NIBLET OF BLOCK NUMBER BEQ 300$ ; FIRST RECORD IN BLOCK -> 300$ MOV 610$(R4),R1 ; R1 = OFFSET/RECORD 240$: ADD R1,R2 ; ADJUST FOR OFFSET SOB R3,240$ ; LOOP ; 300$: MOV R2,RECOFS ; SAVE OFFSET .POP ; RESTORE CLC ; CLEAR FAIL FLAG RETURN ; EXIT ; 600$: .WORD 0,^C1,^C3,^C7,^C17,^C37,^C77,^C177,^C377 610$: .WORD 0,400,200,100,40,20,10,4 ; OFFSETS PER BLOCK FOR BF ; 1000$: SEC ; SET FAIL RETURN ; EXIT ; ; ; RECOFS: .WORD 0 ;; *** OFFSET FOR RECORD *** ; ; ; ; .SBTTL ROUTINE - 'KEYBLK' ... MAP KEY TO BLOCK NUMBER ; ; This routine is called to map the Key number passed ; in R0 into a buffer number and an offset. The buffer ; number is returned in R0, and the offset in R4. The ; following factors are used in the conversion ; ; Each Key is 32 bytes in size ; Key N is in byte N*32 of the file ; The memory buffer is 4000!8 bytes in size ; (--> 64 keys in each buffer full!) ; ; KEYBLK: MOV R0,R4 ; KEY NUMBER -> R4 BIC #77,R0 ; R0 = Buffer number * 16 ASH #-4,R0 ; R0 = Buffer number BIC #^C77,R4 ; R4 = Number of key in buffer ASH #5,R4 ; R4 = Offset of key in buffer 1000$: RETURN ; ALL DONE ; ; ; .END