.TITLE FILSPT ...File I/O support module .IDENT /300583/ .enabl lc ; ; ; ; Written by Ray Di Marco ; 30-May-83. ; ; ; Version 300583/01 ; ; ;--------------------------------------------------------------------- ; ; ; This module contains a number of routines and macro definitions that ; simplify the performing of file I/O operation under the RT-11 operating ; system. The routines available are ; ; FIL.NM convert ascii file spec to RAD50 ; FIL.NA convert RAD50 file spec to ascii ; ; FIL.LK open an existing file (.LOOKUP) ; FIL.NW create a new file (.ENTER) ; FIL.CL close file (.CLOSE) ; FIL.PG purge file (.PURGE) ; ; FIL.RD read from file (.READW) ; FIL.WT write to file (.WRITW) ; ; FIL.ST display file status ; ; ; The major advantages of using this module over using the RT-11 requests ; directly are ; ; * easier transportability of code to another operating ; system ; ; * more comprehensive error diagnostics available ; ; * quicker to implement file i/o operations ; ; A set of macros are also provided in this module to simplify interfacing to ; this module. ; ; .SBTTL Documentation - Register usage ; ; Upon entry to any routine in this module register R5 must hold the ; address of a File Descriptor Block (FDB). Other registers must hold any ; other arguments required by a particular routine. All registers are ; preserved through a routine, and the PSW flags are used to signal any ; errors. The argument passing for each routine is described below ; ; ; FIL.NM R0 = default extrension in RAD50 ; R4 -> file name in .ASCIZ format ; R5 -> FDB ; C flag set on exit if an error detected ; ; FIL.NA R5 -> FDB ; no error possible ; ; FIL.LK/NW R5 -> FDB ; C flag set on exit if lookup/create fails ; ; FIL.RD/WT R5 -> FDB ; C flag set on exit if read/write fails ; Z flag set on exit if read/write past EOF ; ; FIL.ST R5 -> FDB ; no error possible ; .SBTTL Documentation - File Descriptor Block ; ; ; The File Descriptor Block (FDB) is used by the routines in this module to ; hold all data relevant to a file. One FDB is needed for each file to that ; is to be accessed. The format of a FDB is as follows- ; ; .WORD ; FDB.NR - address of rad50 file spec ; .WORD ; FDB.NA - address of ascii file spec ; .WORD ; FDB.CH - RT-11 channel to be used for file ; .BYTE ; FDB.FL - FDB status flags ; .BYTE ; FDB.ER - FDB error byte ; .WORD ; FDB.BL - start block for I/O request ; .WORD ; FDB.RQ - number words to transfer in I/O operation ; .WORD ; FDB.NB - size of file in blocks ; .WORD ; FDB.CP - actual number of words transfered ; .WORD ; FDB.BF - address of buffer for transfer ; ; FDB.NR holds the address of a 4 word buffer that holds the RAD50 file ; name. FDB.NA holds the address of the buffer that holds the ascii file name ; in the form ddu:nnnnnn.xxx. The name is terminated by a <200!8> byte. ; The FDB.NM routine is used load @FDB.NR and @FDB.NA from a .ASCIZ ; string; FDB.NR must be setup before FIL.NW or FIL.LK can be used. ; ; FDB.CH holds the number of the RT-11 channel that is to be used for I/O ; operations; the channel number is normally allocated when the FDB is ; defined. The FDB.FL entry holds 8 single bit flags used by FILSPT to record ; the status of the FDB. FDB.ER consists of two niblets. The first indicates ; the last operation performed on the file and the the second the error (if ; any) that occured when the operation was attemted. ; ; FIL.BL, FIL.RQ and FIL.BF have to be set up prior to calling FIL.RD or ; FIL.WT to perform a read or write with the the starting block number, the ; number of words to transfer and the address of the memory buffer. FIL.CP ; will hold the number of words actually transfered on return. ; ; .SBTTL Documentation - FILSPT Macro Interface ; ; ; The FILSPT macro defined in this module greatly simplifies interfacing with ; the routines in this module. The macro, when invoked will ; ; * define the offsets of the entries in the FDB ; * define the masks for the FDB.FL flags ; * define a number of other macros ; ; The following two lines should be included at the start of the users code ; to make use of FILSPT (assuming that it has been included in a macro ; library) ; ; ; .MCALL FILSPT ; get a copy of the macro ; FILSPT ; envoke macro ; ; .SBTTL Documenation - FILSPT defined symbols ; ; ; The FILSPT macro defines two classes of symbols. The first class of ; symbols are the offsets from the start of the FDB to the file entries ; (ie FIL.NR, FIL.NA, FIL.FL, FIL.ER, FIL.CH, FIL.RQ, FIL.CP, FIL.BL). These ; symbolic names, and their meaning have been previously defined. The second ; class of symbols are of the form 'F.????', and are one bit flags. These ; flag (stored in the FIL.FL byte) are ; ; name meaning ; F.BUSY 1 -> FDB is activated/busy ; F.NERR 1 -> no error message (see section on errors) ; F.EOF 1 -> EOF error occured on requested transfer ; ; ; The F.BUSY flag is set whenever the FDB is activated via a FIL.NW or ; FIL.LK operation, and cleared when the FDB is deactiavted via FIL.PG ; or FIL.CL operation. The FDB must be activated before a FIL.RD or ; FIL.WT operation is attempted. ; ; The F.NERR flag is used to suppress error messages. Normally FILSPT ; displays a one line message whenever an error occures. Setting this bit ; causes this automatic error message to be suppressed. Note that FILSPT ; clears this bit whenever an error occures. ; ; The F.EOF flag is set whenever a FIL.RD or FIL.WT operation results in a ; EOF error. This flag is cleared each time FIL.RD, FIL.WT, FIL.CL or FIL.PG ; is called. ; ; .SBTTL Documentation - FILSPT Macros ; ; The FILSPT macro when invoked will define a number of secondary macros ; needed to interface to this module. These secondary macros are detailed ; below ; ; ; FDB NAME,CHANNEL,BUFFER,SIZE,GLOBL ; where ; NAME is the symbolic name for the FDB ; CHANNEL is the RT-11 channel number to be used ; BUFFER is the address of the I/O buffer (optional) ; SIZE is the size of the buffer in words (optional) ; GLOBL if not blank, causes NAME to be global ; ; NAME FDB,STRING,ERROR,EXTENSION ; where ; FDB is the address of the FDB (default=R5) ; STRING address .ASCIZ string (default=R4) ; EXTENS rad50 default extension (default=R0) ; ERROR address error trap routine (optional) ; ; LOOKUP FDB,ERROR ; where ; FDB is the address of the FDB (default=R5) ; ERROR address error trap routine (optional) ; ; ENTER FDB,SIZE,ERROR ; where ; FDB is the address of the FDB (default=R5) ; SIZE file size in blocks (default=#-1) ; ERROR address error trap routine (optional) ; ; PURGE FDB ; CLOSE FDB ; where ; FDB is the address of the FDB (default=R5) ; ; READ FDB,BLOCK,SIZE,BUFFER,ERROR,EOF ; WRITE FDB,BLOCK,SIZE,BUFFER,ERROR,EOF ; where ; FDB is the address of the FDB (default=R5) ; BLOCK starting block number (default=FDB.BL) ; SIZE number words to read/write (default=FDB.RQ) ; BUFFER memory buffer address (default=FDB.BF) ; ERROR address error trap routine (optional) ; EOF address E.O.F trap routine (optional) ; ; STATUS FDB ; where ; FDB is the address of the FDB (default=R5) ; .SBTTL Documentation - error reporting ; ; ; Upon detection of an error, the module usually will use the RT-11 .PRINT ; EMT to display an error message. The user can suppress this error report ; if desired. ; ; If the F.NERR bit is set in FDB.FL, error messages are suppressed. Note ; that this bit is cleared after the occurance of an error, or a call to the ; STATUS display routine. The F.NERR flag is of value when doing default file ; lookups. If the default file is not found, the user may then wish to prompt ; the operator for more details, without having an error message displayed. ; ; .SBTTL Documentation - external routines used ; ; ; Two external routines are used. These are R50ASC and CNAF. The ; first is the syslib routine which converts a rad50 string to ascii. The ; second is contained in the CNAF module, and converts the word in r2 ; into an ascii string, storing the result in the string pointed to by the ; buffer by r1. R0 is used by CNAF as a format word to determine the radix ; for the number and what is to be done with leading zeros. ; ; ; .SBTTL Documentation - FDB.NB (number blocks) abnormality ; ; If a non-file structured lookup of a device is performed FDB.NB will ; be set to -1. Special attention must be given when doing I/O to a ; variable lenght device as the EOF condition will not be properly reported ; by RT-11; instead a Hard Error On Channel will be reported. ; ; To overcome this check FDB.NB if non-file structured I/O is being done. ; If FDB.NB=-1 and a Hard Error On Channel Occurs then the error may (or ; may not be) End Of File in reality. ; .SBTTL FILSPT macro definition ; .MACRO FILSPT FDB.NR = 0 FDB.NA = 2 FDB.CH = 4 FDB.FL = 6 F.BUSY = 1 F.NERR = 2 F.EOF = 200 FDB.ER = 7 FDB.BL = 10 FDB.RQ = 12 FDB.NB = 14 FDB.CP = 16 FDB.BF = 20 .GLOBL FIL.NM,FIL.NW,FIL.LK,FIL.NA,FIL.RD,FIL.WT,FIL.CL,FIL.PG,FIL.ST ; .MACRO STATUS FDB=R5 .IIF DIF,FDB,R5 MOV R5,-(SP) CALL FIL.ST .ENDM STATUS ; .MACRO FDB NAME,CHANNEL,BUFFER=0,SIZE=0,GLOBL .IIF NB,GLOBL, .GLOBL NAME NAME: .WORD 10$ ; RAD50 FILE NAME .WORD 20$ ; ASCII FILE NAME .WORD CHANNEL ; CHANNEL NUMBER .WORD 0 ; STATUS .WORD 0 ; START BLOCK .WORD SIZE ; REQUEST SIZE .WORD 0 ; FILE SIZE .WORD 0 ; COPIED .WORD BUFFER ; BUFFER ADDRESS 10$: .WORD 0,0,0,0 20$: .ASCII / /<200><0> .ENDM FDB ; .MACRO NAME FDB=R5,STRING=R4,ERROR,EXTENSION=R0 .IIF DIF,FDB,R5 MOV FDB,R5 .IIF DIF,STRING,R4 MOV STRING,R4 .IIF DIF,EXTENS,R0 MOV EXTENS,R0 CALL FIL.NM .IIF NB,ERROR, BCS ERROR .ENDM NAME ; .MACRO LOOKUP FDB=R5,ERROR .IIF DIF,FDB,R5 MOV FDB,R5 CALL FIL.LK .IIF NB,ERROR, BCS ERROR .ENDM LOOKUP ; .MACRO ENTER FDB=R5,SIZE=#-1,ERROR .IIF DIF,FDB,R5 MOV FDB,R5 MOV SIZE,FDB.BL(R5) CALL FIL.NW .IIF NB,ERROR, BCS ERROR .ENDM ENTER ; .MACRO CLOSE FDB=R5 .IIF DIF,FDB,R5 MOV FDB,R5 CALL FIL.CL .ENDM CLOSE ; .MACRO PURGE FDB=R5 .IIF DIF,FDB,R5 MOV FDB,R5 CALL FIL.PG .ENDM PURGE ; .MACRO READ FDB=R5,BLOCK,SIZE,BUFFER,ERROR,EOF,?LA,?LB .IIF DIF,FDB,R5 MOV FDB,R5 .IIF NB,BLOCK, MOV BLOCK,FDB.BL(R5) .IIF NB,SIZE, MOV SIZE,FDB.RQ(R5) .IIF NB,BUFFER, MOV BUFFER,FDB.BF(R5) CALL FIL.RD BCC LB .IIF NB,EOF, BEQ EOF .IIF NB,ERROR, BCS ERROR LB: .ENDM READ ; .MACRO WRITE FDB=R5,BLOCK,SIZE,BUFFER,ERROR,EOF,?LA,?LB .IIF DIF,FDB,R5 MOV FDB,R5 .IIF NB,BLOCK, MOV BLOCK,FDB.BL(R5) .IIF NB,SIZE, MOV SIZE,FDB.RQ(R5) .IIF NB,BUFFER, MOV BUFFER,FDB.BF(R5) CALL FIL.WT BCC LB .IIF NB,EOF, BEQ EOF .IIF NB,ERROR, BCS ERROR LB: .ENDM WRITE ; .MACRO FILSPT .ENDM FILSPT .ENDM FILSPT ; .SBTTL DECLARATIONS ; ; .MCALL .PRINT,.TTYOUT ; RT-11 terminal I/O .MCALL .CLOSE,.PURGE ; RT-11 file close/purge .MCALL .LOOKUP,.ENTER,.CSISPC ; RT-11 file oppening .MCALL .READW,.WRITW ; RT-11 file I/O .MCALL .DSTAT ; RT-11 Device status .MCALL .SERR,.HERR ; RT-11 Error interception .MCALL .PUSH,.POP ; DBSLIB Stacking .MCALL ENCODE ; DBSLIB Binary -> Ascii conversion ; .GLOBL FIL.NM,FIL.NW,FIL.LK,FIL.NA ; Entry points - activation .GLOBL FIL.RD,FIL.WT ; Entry points - I/O .GLOBL FIL.CL,FIL.PG ; Entry points - deactivation .GLOBL FIL.ST ; Entry points - status reporter ; .GLOBL CNAF ; DBSLIB binary -> ascii .GLOBL R50ASC ; SYSLIB binary -> ascii ; ; ; RTERRB = 52 ; address RT-11 error byte FILSPT ; make FILSPT definitions ; ; ; .PSECT CODE ; open code area ; ------ ---- ; .SBTTL Routine - FIL.PG ... purge out file ; ; ; Are here to purge the file whose FDB address is in R5. Do this by ; purging the RT-11 channel and clearing the FDB status flags. ; ; FIL.PG: .PURGE FDB.CH(R5) ; purge CLR FDB.FL(R5) ; clear flags RETURN ; home ; ; .SBTTL Routine - FIL.CL ... close out file ; ; ; Are here to close the file whose FDB address is in R5. Do this by ; closing the RT-11 channel and clearing the FDB status flags. ; FIL.CL: .CLOSE FDB.CH(R5) ; close channel CLR FDB.FL(R5) ; clear out flags RETURN ; home ; ; .SBTTL Routine - FIL.NM ... assign name to a file FDB ; ; Save registers and allocate scratch space on stack by invoking ..ENTR ; which returns with registers setup as follows ; ; R5 unchanged (FDB passed by caller) ; R4 stack address needed by ..EXIT ; R3 -> scratch area (40 words) ; R2 unchanged ; R1 unchanged ; R0 unchanged ; ; Also initizlize R2 as as error code and insure FDB not in use. ; FIL.NM: JSR R0,..ENTR ; save/initialize registers MOV #COD.NM+0,R2 ; R2 = error code BITB #F.BUSY,FDB.FL(R5) ; has FDB been activated BNE 7001$ ; yes --> error #1 MOVB #200,@FDB.NA(R5) ; ignore any previous names ; ; point R1 to file name ; MOV 2(R4),R1 ; R1 -> ascii string 100$: CMPB (R1)+,#40 ; trim BEQ 100$ ; leading blanks TSTB -(R1) ; is string NULL? BLE 7002$ ; yes -> error #2 ; ; ; Invoke CSI to decode file spec ; MOV R0,(R3) ; R3 -> default extension MOV R3,R0 ; R0 -> default extension TST (R3)+ ; R3 -> free space .CSISPC R3,R0,R1 ; decode filspec BCS 6000$ ; abort on error ; ; ; Copy CSI rad50 file name into FDB ; MOV (R5),R0 ; R0 -> rad50 file name buffer ADD #30.,R3 ; R3 -> returned name .REPT 4 ; copy MOV (R3)+,(R0)+ ; file .ENDR ; name TST @(R5) ; file specified? BEQ 7003$ ; no --> error #3 ; ; Setup ascii name exit ; MOV R4,SP ; release scratch area CALL FIL.NA ; setup ascii file name MOVB R2,FDB.ER(R5) ; set up error code JMP ..EXIT ; exit time ; ; Error exit ; 6000$: CALL .RTERR ; R2 = error code BMI 7000$ ; skip on .SERR 7004$: INC R2 ; bump error count 7003$: INC R2 ; Error - decode failed 7002$: INC R2 ; Error - NULL string 7001$: INC R2 ; Error - FDB in use 7000$: MOVB R2,FDB.ER(R5) ; save error code JMP ERROR ; process error ; .SBTTL Routine - "FIL.NA" ... RAD50 file name -> ASCII ; ; This routine when called will setup the FDB.NA string to match the ; file spec in the FDB.NR string. ; ; ; Wish to use syslib routine 'R50ASC' to change rad50 file name to ascii. ; To do this must set up an argument block @R5 in following format ; ; R5 --> .WORD 3 ; NUM ARGS ; .WORD 777$ ; ADDRESS OF WORD HOLDING 12. ; .WORD ; ADDRESS RAD50 STRING ; .WORD ; ADDRESS ASCII STRING ; FIL.NA: JSR R0,..ENTR ; save registers, setup R3/R4 .PUSH ; set up fortran arg blk MOV SP,R5 ; R5 -> arg block .PUSH ; save these critical registers CALL R50ASC ; RAD50 -> ASCII .POP ; restore critical registers MOV (R4),R5 ; R5 -> FDB ; ; Now must copy ascii name of file into space reserved for it in the FDB. ; MOV 2(R5),R1 ; R1 = destination MOV #3,R2 ; R2 = number bytes to copy CALL 10000$ ; set up device name MOVB #':,(R1)+ ; delimit MOV #6,R2 ; 6 letter file name CALL 10000$ ; set up file name CMPB -1(R1),#': ; have a file name? BEQ 400$ ; no --> skip MOVB #'.,(R1)+ ; yes -> delimit MOV #3,R2 ; 3 letter extension CALL 10000$ ; copy 400$: MOVB #200,(R1)+ ; terminate JMP ..EXIT ; exit time 777$: .WORD 12. ; USED IN R50ASC CALL ; ; ; This little routine is used to copy R2 characters from string R3 to ; the string R1. Note that the 'space' character will be counted as a ; character, but will not be copied. ; 10000$: CMPB (R3)+,#40 ; SPACE? BEQ 10100$ ; yes -> skip MOVB -1(R3),(R1)+ ; no --> copy 10100$: SOB R2,10000$ ; loop RETURN ; home ; .SBTTL Routine - "FIL.NW" ... create a new file ; ; Save registers and allocate scratch space on stack by invoking ..ENTR ; which returns with registers setup as follows ; ; R5 unchanged (FDB passed by caller) ; R4 stack address needed by ..EXIT ; R3 -> scratch area ; R2 unchanged ; R1 unchanged ; R0 unchanged ; ; Also initizlize R2 as as error code ; FIL.NW: JSR R0,..ENTR ; save/initialize registers .SERR ; trap all errors ourself MOV #COD.NW+0,R2 ; R2 = error code ; ; Check for illegal operation ; BITB #F.BUSY,FDB.FL(R5) ; has FDB been activated BNE 7001$ ; yes --> error #1 .DSTAT R3,(R5) ; valid device? BCS 7002$ ; no --> error #2 TST 4(R3) ; handler loaded? BEQ 7003$ ; no --> error #3 ; ; enter file ; .ENTER R3,FDB.CH(R5),FDB.NR(R5),FDB.BL(R5) ; ENTER TIME BCS 6000$ ; trap error MOV R0,FDB.NB(R5) ; setup size BNE 210$ ; skip if <> 0 MOV #-1,FDB.NB(R5) ; else force to 177777 210$: BISB #F.BUSY,FDB.FL(R5) ; FDB now busy BICB #F.EOF,FDB.FL(R5) ; clear EOF flag CLR FDB.BL(R5) ; rewind file MOVB R2,FDB.ER(R5) ; no error .HERR ; re-enable error abort JMP ..EXIT ; exit time ; ; Error exit ; 6000$: CALL .RTERR ; R2 = error code BMI 7000$ ; skip on .SERR 7004$: INC R2 ; bump error counter 7003$: INC R2 ; error - handler not loaded 7002$: INC R2 ; error - invalid device 7001$: INC R2 ; error - FDB busy 7000$: MOVB R2,FDB.ER(R5) ; save error code .HERR ; re-enable error abort JMP ERROR ; process error .SBTTL Routine - "FIL.LK" ... lookup file ; ; Save registers and allocate scratch space on stack by invoking ..ENTR ; which returns with registers setup as follows ; ; R5 unchanged (FDB passed by caller) ; R4 stack address needed by ..EXIT ; R3 -> scratch area ; R2 unchanged ; R1 unchanged ; R0 unchanged ; ; Also initizlize R2 as as error code ; FIL.LK: JSR R0,..ENTR ; save/initialize registers .SERR ; trap all errors ourself MOV #COD.LK+0,R2 ; R2 = error code ; ; Check for illegal operation ; BITB #F.BUSY,FDB.FL(R5) ; has FDB been activated BNE 7001$ ; yes --> error #1 .DSTAT R3,(R5) ; valid device? BCS 7002$ ; no --> error #2 TST 4(R3) ; handler loaded? BEQ 7003$ ; no --> error #3 ; ; Lookup file ; .LOOKUP R3,FDB.CH(R5),FDB.NR(R5); lookup time BCS 6000$ ; trap error MOV R0,FDB.NB(R5) ; setup size BNE 210$ ; skip if <> 0 MOV #-1,FDB.NB(R5) ; else force to 177777 210$: BISB #F.BUSY,FDB.FL(R5) ; FDB now busy BICB #F.EOF,FDB.FL(R5) ; clear EOF flag CLR FDB.BL(R5) ; rewind file MOVB R2,FDB.ER(R5) ; no error .HERR ; re-enable error abort JMP ..EXIT ; exit time ; ; Error exit ; 6000$: CALL .RTERR ; R2 = error code BMI 7000$ ; skip on .SERR 7004$: INC R2 ; bump error count 7003$: INC R2 ; error - handler not loaded 7002$: INC R2 ; error - invalid device 7001$: INC R2 ; error - FDB busy 7000$: MOVB R2,FDB.ER(R5) ; save error code .HERR ; re-enable error abort JMP ERROR ; process error .SBTTL Routine - "FIL.RD" ... read file ; ; Save registers and allocate scratch space on stack by invoking ..ENTR ; which returns with registers setup as follows ; ; R5 unchanged (FDB passed by caller) ; R4 stack address needed by ..EXIT ; R3 -> scratch area ; R2 unchanged ; R1 unchanged ; R0 unchanged ; ; Also clear EOF flag and initizlize R2 as as error code ; FIL.RD: JSR R0,..ENTR ; save/initialize registers BICB #F.EOF,FDB.FL(R5) ; clear EOF flag MOV #COD.RD+0,R2 ; R2 = error code ; ; ensure that fdb has been activated and I/O request less that 32k words ; BITB #F.BUSY,FDB.FL(R5) ; has FDB been activated BEQ 7001$ ; no --> error #1 TST FDB.RQ(R5) ; MSB set? BMI 7002$ ; yes -> too large a request ; ; Read file ; .READW R3,FDB.CH(R5),FDB.BF(R5),FDB.RQ(R5),FDB.BL(R5) BCS 6000$ ; FAILED -> ERROR MOV R0,FDB.CP(R5) ; number words copied MOVB R2,FDB.ER(R5) ; no error JMP ..EXIT ; exit time ; ; ; Error exit ; 6000$: CALL .RTERR ; R2 = error code BMI 7000$ ; skip on .SERR BNE 6007$ ; skip if not EOF error BISB #F.EOF,FDB.FL(R5) ; else set EOF flag 6007$: INC R2 ; bump error count 7002$: INC R2 ; error - too many words 7001$: INC R2 ; error - FDB not activated 7000$: MOVB R2,FDB.ER(R5) ; save error code JMP ERROR ; process error ; ; ; .SBTTL Routine - "FIL.WT" ... write file ; ; Save registers and allocate scratch space on stack by invoking ..ENTR ; which returns with registers setup as follows ; ; R5 unchanged (FDB passed by caller) ; R4 stack address needed by ..EXIT ; R3 -> scratch area ; R2 unchanged ; R1 unchanged ; R0 unchanged ; ; Also clear EOF flag and initizlize R2 as as error code ; FIL.WT: JSR R0,..ENTR ; save/initialize registers BICB #F.EOF,FDB.FL(R5) ; clear EOF flag MOV #COD.WT+0,R2 ; R2 = error code ; ; ensure that fdb has been activated and I/O request less that 32k words ; BITB #F.BUSY,FDB.FL(R5) ; has FDB been activated BEQ 7001$ ; no --> error #1 TST FDB.RQ(R5) ; MSB set? BMI 7002$ ; yes -> too large a request ; ; Write file ; .WRITW R3,FDB.CH(R5),FDB.BF(R5),FDB.RQ(R5),FDB.BL(R5) BCS 6000$ ; FAILED -> ERROR MOV R0,FDB.CP(R5) ; number words copied MOVB R2,FDB.ER(R5) ; no error JMP ..EXIT ; exit time ; ; ; Error exit ; 6000$: CALL .RTERR ; R2 = error code BMI 7000$ ; skip on .SERR BNE 6007$ ; skip if not EOF error BISB #F.EOF,FDB.FL(R5) ; else set EOF flag 6007$: INC R2 ; bump error count 7002$: INC R2 ; error - too many words 7001$: INC R2 ; error - FDB not activated 7000$: MOVB R2,FDB.ER(R5) ; save error code JMP ERROR ; process error ; .SBTTL ROUTINE - 'FIL.ST' .... DISPLAY FILE STATUS ; ; This routine is called to display the status of the file whose FDB ; is passed over in R5. ; ; Invoke ERROR to display error message. Must do a dummy ..ENTR as ERROR ; does a ..EXIT. ; FIL.ST: JSR R0,..ENTR ; mark entry to module MOV #100$,-(SP) ; setup ERROR return address JSR R0,..ENTR ; setup dummy module entry BICB #F.NERR,FDB.FL(R5) ; enable error message JMP ERROR ; display error message ; ; Setup R1/R2 for output loop ; 100$: MOV #ST.MES,R2 ; R2 -> message MOV #7000$,R1 ; R1 -> table ; ; Output text ; 1000$: CALL 6100$ ; output time BCS 2000$ ; skip if have to output a num JMP ..EXIT ; else terminate ; ; Output value for encode entry @R1 ; 2000$: .PUSH R2 ; save string pointer MOV (R1)+,R0 ; R0 = format byte MOV (R1)+,R2 ; R2 = offset to data BMI 2100$ ; skip if byte quantity ADD R5,R2 ; R2 -> data MOV (R2),R2 ; R2 = number BR 2400$ ; output time 2100$: BIC #100000,R2 ; R2 = byte offset ADD R5,R2 ; R2 -> data MOVB (R2),R2 ; R2 = number BIC #^C377,R2 ; discard sign bits 2400$: .PUSH R1 ; save table pointer MOV R3,R1 ; R1 -> buffer CALL CNAF ; convert to ascii CLRB (R1) ; terminate string MOV R3,R2 ; R2 -> ascii string CALL 6100$ ; output .POP ; restore ; ; Ignore any extra ? in string ; 3000$: CMPB (R2)+,#'? ; discard extra BEQ 3000$ ; ? markers DEC R2 ; adjust pointer BR 1000$ ; continue output of message ; ; ; This routine output the string @R2. The string is terminated by either a ; NULL or a ? character. The C flag will be set iff the ? terminator was ; hit. ; 6000$: .TTYOUT ; output byte 6100$: MOVB (R2)+,R0 ; R0 = next character BEQ 6700$ ; NULL -> EOS CMPB R0,#'? ; time for number? BNE 6000$ ; no --> output SEC ; yes -> flag that ? hit 6700$: RETURN ; done ; ; ; This table is used to determine how each quantity is to be displayed. ; 7000$: ENCODE SD FDB.CH ; channel number ENCODE SSSSD FDB.NB ; file size ENCODE SSSSD FDB.RQ ; number words requested ENCODE OOO FDB.ER!100000 ; error code ENCODE OOO FDB.FL!100000 ; status flags ENCODE SSSSD FDB.BL ; block number ENCODE SSSSD FDB.CP ; number words copied ENCODE OOOOOO FDB.BF ; buffer address ; .SBTTL Routine - ERROR ... common error handler ; ; Control passes here on the occurance of an error with R4 holding the address ; of the exit stack. This routine identifies the module, the routine and the ; error which occured. ; ; Clean up stack and skip in error message disabled ; ERROR: MOV R4,SP ; SP -> exit stack BIT #F.NERR,FDB.FL(R5) ; error messages allowed? BNE 7000$ ; no -> skip ; ; Display module name and load R1 with index into error table ; .PRINT #M.ID ; display module ID MOVB FDB.ER(R5),R1 ; R1 = error code ASR R1 ; discard ASR R1 ; error ASR R1 ; bits BIC #^C34,R1 ; R1 = [routine id]*4 BEQ 6000$ ; no routine -> skip ; ; Display routine name ; .PRINT INDTAB+2(R1) ; display routine name .PRINT #M.DL ; dilimiter time ; ; Display error message ; MOVB FDB.ER(R5),R0 ; R0 = error code BIC #^C17,R0 ; R0 = error number BEQ 6000$ ; no error -> skip DEC R0 ; change to base 0 ASL R0 ; R0 = word offset for error num BITB #20,FDB.ER(R5) ; have a .SERR error? BEQ 5400$ ; no --> skip CLR R1 ; yes -> use .SERR err list 5400$: ADD INDTAB+0(R1),R0 ; R0 -> address error message .PRINT (R0) ; display error message .PRINT #M.SP ; print a space ; 6000$: .PRINT FDB.NA(R5) ; display file name .PRINT #M.CR ; new line ; 7000$: BICB #F.NERR,FDB.FL(R5) ; ALLOW ERROR MESSAGE .POP ; RESTORE BIT #F.EOF,FDB.FL(R5) ; EOF ERROR? BEQ 300$ ; NO -> 300$ SEZ ; SET 'EOF' SEC ; SET FAILED RETURN ; HOME ; 300$: CLZ ; CLEAR EOF SEC ; SET FAILED RETURN ; HOME .SBTTL Primitive - ..ENTR ... mark entry into module ; ; This routine must be called directly on entry to the module with a JSR R0 ; instruction. It returns to the caller with the registers setup as follows ; ; ; R5 unchanged ; R4 stack address needed by ..EXIT ; R3 -> scratch area (40 words) ; R2 unchanged ; R1 unchanged ; R0 unchanged ; ; The caller must exit via ..EXIT. ; ..ENTR: ; R0 already saved by JSR R0 .PUSH ; save other registers MOV SP,R4 ; R4 = exit stack address SUB #40.*2,SP ; allocate room on stack MOV SP,R3 ; R3 -> scratch area MOV R0,-(SP) ; SP -> return address MOV 12(R4),R0 ; restore R0 RETURN ; return to caller ; ; ; .SBTTL Primitive - ..EXIT ... exit from module ; ; This routine is called to exit the module after a routine has called ..ENTR ; to mark entry into the module. R4 must have the same value as returned ; by ..ENTR as it is needed by ..EXIT to clean up the stack. ; ..EXIT: MOV R4,SP ; SP -> pushed R5 .POP ; restore RETURN ; exit module ; .SBTTL Primitive - .RTERR ... merge in RT-11 error byte ; ; This routine is called after a RT-11 emt failed to merge the RT-11 error ; code into the FDB error code. At entry R2 must hold the FDB routine ident- ; ifier. On exit R2 holds the appropriate FDB error code. ; ; If error code < 0 then have a .SERR error ; .RTERR: MOVB @#RTERRB,R0 ; get error code BGE 1000$ ; skip not .SERR error ; ; .SERR errors store with 20 bit set ; NEG R0 ; make positive CMP R0,#11 ; valid code? BLOS 400$ ; yes -> skip MOV #12,R0 ; no --> force into range 400$: BIS #20,R0 ; Set .SERR flag BR 1700$ ; exit time ; ; Other errors stoted with 20 bit clear ; 1000$: CMP R0,#3 ; valid code? BLOS 1700$ ; yes -> skip MOV #3,R0 ; no --> force into range ; ; Return to caller ; 1700$: ADD R0,R2 ; merge with routine number TSTB @#RTERRB ; all RETURN ; done ; .SBTTL INDTAB Table ... error index table ; ; ; The table consists of one two word entry per routine. Each entry consists of ; the address of an ascii string identifying the routine, and the address of ; the error messages describing the error that ; was detected. ; ; .MACRO ERRLST RTN,ERRORS .PSECT MESSAGE .EVEN ZZZZZZ = . .IRP X, .WORD X .ENDR ZZZZZN = . .ASCII /FIL.'RTN'/<200> .PSECT INDTAB COD.'RTN' = <.-INDTAB>*10 .WORD ZZZZZZ,ZZZZZN .ENDM ERRLST ; ; .PSECT INDTAB ; open index table psect ; ------ ------ ; INDTAB: ERRLST SE, ERRLST NM, ERRLST NW, ERRLST LK, ERRLST RD, ERRLST WT, ; .SBTTL General messages ; ; .PSECT MESSAGE ; open message area ; ------ ------- ; .nlist bin ; no binary .enabl lc ; allow lc M.ID: .ASCII /FILSPT-/<200> ; module ID M.SP: .ASCII / /<200> ; delimiter M.DL: .ASCII /-/<200> ; delimiter M.CR: .ASCIZ // ; new line ; M.ILC: .ASCII /CSI:invalid command/<200> M.ILD: .ASCII /CSI:Invalid device/<200> M.NLS: .ASCII /Null string/<200> M.DCD: .ASCII /Null file/<200> M.BSY: .ASCII /FDB in use/<200> M.LDD: .ASCII /Handler not loaded/<200> M.CHB: .ASCII /Channel in use/<200> M.SPC: .ASCII /No room for file/<200> M.UNK: .ASCII /UNKOWN ERROR CODE/<200> M.RPL: .ASCII /Cannot replace protected file/<200> M.FNF: .ASCII /File not found/<200> M.FNA: .ASCII /FDB not active/<200> M.EOF: .ASCII /End of File/<200> M.HRD: .ASCII /Hard error on channel/<200> M.CNA: .ASCII /CHANNEL not active/<200> M.WDC: .ASCII /Word count too large/<200> ; M.SE1: .ASCII |USR called from completion routine| M.SE2: .ASCII |Need handler|<200> M.SE3: .ASCII |Directory I/O error|<200> M.SE4: .ASCII |Handler fetch error|<200> M.SE5: .ASCII |Overlay read error|<200> M.SE6: .ASCII |Directory full|<200> M.SE7: .ASCII |Illegal address|<200> M.SE8: .ASCII |Illegal channel|<200> M.SE9: .ASCII |Illegal EMT|<200> ; ST.MES: .ASCII| Channel ??. Size ?. Requested ?. Error ? Flags ?|<15><12> .ASCIZ| Block ?. Transfered ?. Buffer-addrs ??|<15><12> ; .END