.MCALL .MODULE .MODULE ELTASK,VERSION=09,COMMENT= ; Copyright (c) 1998 by Mentec, Inc., Nashua, NH. ; All rights reserved ; ; This software is furnished under a license for use only on a ; single computer system and may be copied only with the ; inclusion of the above copyright notice. This software, or ; any other copies thereof, may not be provided or otherwise ; made available to any other person except for use on such ; system and to one who agrees to these license terms. Title ; to and ownership of the software shall at all times remain ; in Mentec, Inc. ; ; The information in this document is subject to change without ; notice and should not be construed as a commitment by Digital ; Equipment Corporation, or Mentec, Inc. ; ; Digital and Mentec assume no responsibility for the use or ; reliability of its software on equipment which is not supplied ; by Digital or Mentec, and listed in the Software Product ; Description. ;++ ; Edit History: ; ; 001 15-Feb-80 09:40 Gentry, Martin (70039) [240,121] ; Re-ordering of .GTIM and .DATE ; Plus some general clean-up ; (001) ; 002 30-Mar-82 03:59 PM Martin Gentry [40,121] ; Alterations due to review comments ; (002) ; ; 007 JUL-87 Matthew Sacks ; IOCODE rewritten so that a system crash in the middle of the routine ; cannot cause pointers in block 0 of ERRLOG.DAT to be invalid ; ; 008 25-OCT-90 Bill Dunham ; Make ERRLOG work under RT11FB by fixing bug in OPINIT code. ; If not single-background and no system tasking, don't .LOOKUP ; after .RCVDW gets the OK from ELINIT. ;-- .SBTTL Assembly Conditionals ;***************************************************************************** ; ; CONDITIONAL SUMMARY ; ; MMG$T (0) ;standard conditional ; ; EIS$I (MMG$T) ;standard conditional ; ;***************************************************************************** .IIF NDF MMG$T, MMG$T = 0 .IIF NDF EIS$I, EIS$I = MMG$T .IIF EQ EIS$I, .MCALL SOB .SBTTL DEFINITIONS .ENABL LC .LIBRARY "SRC:SYSTEM.MLB" ; RT-11 MACROS WE WILL USE .MCALL .QSET, .PRINT, .MRKT .MCALL .RCVDW, .LOOKU, .READW .CLOSE .MCALL .CMKT, .CHCOP, .READC .MCALL .RCVDC, .SPND, .WRITW, .BR .MCALL .RSUM, .READC, .EXIT, .MTPS, .MFPS .MCALL .FIXDF .SYCDF .DSTAT .HANDF .DSTDF .DSCDF .MCALL .CF1DF .CF2DF .CF3DF .SGNDF ; invoke SYSTEM.MLB macros .FIXDF ;monitor fixed offsets .SYCDF ;system communication area .HANDF ;device handler structure .CF1DF ;system configuration word #1 .CF2DF ;system configuration word #2 .CF3DF ;system configuration word #3 .DSTDF ;.DSTAT programmed request area format .DSCDF ;.DSTAT programmed request result flags .SGNDF ;sysgen word bit masks ; RT-11 SYSTEM LOCATIONS ; SYSPTR = 54 ;POINTER TO RESIDENT MONITOR ; CONFIG = 300 ;CONFIGURATION WORD ; FBMON$ = 1 ; KT11$ = 10000 ; SYSGEN = 372 ;SYSGEN FEATURES WORD ; STASK$ = 40000 ; RANDOM DEFINITIONS RCVKEY = 101010 ;KEY TO ACKNOWLEDGING THE ; BACKGROUND REPORTER JOB ELIOCH = 0 ;ERROR LOGGER IO CHANNEL ETIOCH = 1 ;ERROR LOGGER ALTERNATE CHANNEL MSGCHN = 2 ;MESSAGE CHANNEL FOR COMMON WITH ; BG ELINIT/ERROUT INICHN = 3 ;init time channel .SBTTL START OF CUSP ;+ ; NOTE: WE DON'T HAVE TO WORRY ABOUT THE USR SWAPPING DURING INITIALIZATION ; CODE SINCE THE USR IS AT ITS STANDARD LOCATION AT THE TIME THE EL JOB IS ; FRUN/SRUN AND THE TASK WILL HAVE CONTROL UNTIL IT NO LONGER NEEDS THE USR. ; THAT IS, ALL PROG. REQUESTS REQUIRING THE USR (.QSET, .LOOKUP ETC.) ARE ; COMPLETE BEFORE WE .SPND. THE CODE WHICH EXECUTES REPETITIVELY (I.E. NOT ; INITIALIZATION CODE) DOES NOT REQUIRE THE USR. ;- .GLOBL RECHED, FREADY, NOTRDY .GLOBL CMENTR, PNXBLK .GLOBL $ELHDR, $HDLEN .GLOBL $BFNUM, $BFTAB, $BFLAG .GLOBL $ELBF1 CTBSIZ .ENABL LSB OPINIT::.QSET #XTRAQE,#2 ;ALLOCATE 2 EXTRA QUEUE ELEMENTS MOV @#$SYPTR,R1 ;R1->RESIDENT MONITOR BIT #KT11$,$CNFG1(R1) ;RUNNING UNDER XM? BEQ 10$ ;NO INCB FXM ;YES, SET FLAG FOR LATER 10$: BIT #STASK$,$SYSGE(R1) ;SYSTEM TASKING MONITOR? BEQ 20$ ;NO INCB FST ;YES SET FLAG FOR LATER 20$: CALL GETSPF ;INITIALIZE THE SPFUN TABLES .PRINT #E.INFO .PRINT #M.INI ;TELL USER TO RUN ELINIT 30$: CALL REMND1 ;SET TIMER FOR A REMINDER TSTB FST ;SYSTEM TASKING MONITOR? BNE 40$ ;YES, GO DO LOOKUP, READW .RCVDW #AREA,#RECHED,#$HDLEN ;REQUEST RECEIVE OF HEADER FROM BCS ILLER2 ;Branch if problem hearing ELINIT BR 60$ ;Branch if OK given by ELINIT 40$: .LOOKUP #AREA,#MSGCHN,#ZEROAD ;LOOKUP TO RECEIVE FROM ANY JOB BCS CHNER1 ;ERROR? 50$: .READW #AREA,#MSGCHN,#RECHED,#$HDLEN ;REQUEST HEADER FROM ELINIT ILLER2: BCS ILLER1 ;FALL THROUGH IF WE GOT IT... 60$: CMP RECHED,#$HDLEN ;IS SIZE WHAT WE EXPECTED? BEQ 70$ ;YES... JMP IMRERR ;NOPE, GO TELL USER 70$: .CMKT #AREAT,#0 ;STOP REMINDING USER TSTB FST ;SYSTEM TASKING MONITOR? BNE 80$ ;YES .CHCOPY #AREA,#ETIOCH,#ELIOCH ;COPY CHANNEL FOR ERRLOG.DAT FILE BR 90$ 80$: .CHCOPY #AREA,#ETIOCH,#ELIOCH,#BJBDES ;COPY CHANNEL FROM ELINIT 90$: BCS ILLER1 ;BRACH IF WE FAILED 100$: MOV PNXBLK,R4 ;DETERMINE ACTIVE BLOCK .READW #AREA,#ETIOCH,#$ELBF1,#256.,R4 ;READ INTO CURRENT BUFFER BCC REALTM ;GOT IT... JMP LIOERR ;FAILED, TELL USER REALTM::CLR FREADY ;ENABLE LOGGING... ADD NOTRDY,CMENTR ;ACCOUNT FOR MISSED REPORTS TSTB FST ;SYSTEM TASKING MONITOR? BEQ 110$ ;NO .READC #AREA,#MSGCHN,#RCVMSG,#1,#CRTN ;ISSUE READ FROM ERROUT BCC SUSPND ;POSTED... CHNER1: JMP CHNERR ;CHANNEL ERROR 110$: .RCVDC #AREA,#RCVMSG,#1,#CRTN ;ISSUE RECEIVE FROM ERROUT BCC SUSPND ;POSTED... ILLER1: JMP ILLERR ;NO OTHER JOBS?!... .DSABL LSB .SBTTL REMIND - STARTUP REMINDER ;+ ; ; Reminds user to run ELINIT to enable logging ; ; ; NOTE: ; The EMT area used by this MRKT is the same area as the mainline ; MRKT uses. This is because the mainline 'primes' the reminder ; code and is never executed again, therefore can not be interrupted ; by this completion routine. ; ;- REMIND: .PRINT #E.INFO ;STANDARD RT PREFIX, .PRINT #M.REM ; REMIND USER TO RUN ELINIT REMND1: .MRKT #AREAT,#WAITIM,#REMIND,#0 ;SET REMINDER TIMER BCS REMND1 ;TRY AGAIN (NO QUEUE ELEMENT) RETURN ;AND RETURN .SBTTL SUSPND - WAITING FOR ACTIVATION ;+ ; ; We wait here for activation by the monitor. This occurs when ; the copy code has determined that a buffer is full and needs ; to be written out to the disk file. The signalling occurs when ; the copy code returns to the monitor with the carry set. ; ;- SUSPND: .SPND ;NOW WE SUSPEND, AWAITING ; RESUME FROM THE MONITOR ELTASK: TST IFATAL ;ERRORS IN COMPLETION CODE? BNE 10$ ;branch if yes 20$: CALL IOCODE ;TRANSFER A BLOCK TO ERRLOG.DAT TST IFATAL ;ERRORS IN I/O? BEQ SUSPND ;BLOCK WRITTEN, SUSPEND AGAIN 10$: JMP FATALE ;GO PRINT APPROPRIATE MSG AND EXIT .SBTTL IOCODE - WRITE BUFFER TO LOGGING FILE ;+ ; ; This code runs as a result of one of the logging buffers becoming ; full. It writes out the updated header followed by the full and ; active buffers. The header is written first to "freeze" the info ; reflected in the following two buffers. ; ;- .GLOBL SMAXSZ IOCODE: MOV R2,-(SP) ;SAVE R2 FOR AWHILE MOV PNXBLK,R1 ;SAVE BLOCK NUMBER OF FULL BLOCK INC PNXBLK ; (KEEP THIS UPDATED) MOV $BFNUM,R2 ;DETERMINE FULL BUFFER NEG R2 ; (FULL BUFFER IS THE ONE THAT ADD #2,R2 ; IS NOT THE CURRENT ACTIVE ONE) .WRITW #AREA,#ETIOCH,$BFTAB(R2),#256.,R1 ;WRITE OUT THE BLOCK BCC 20$ ;SUCCESS... MOV #1,IFATAL ;WE HAVE A PROBLEM... 20$: CLR $BFLAG(R2) ;INDICATE BUFFER IS FREE AGAIN INC R1 ;SET TO WRITE ACTIVE BUFFER CMP R1,SMAXSZ ;IS THERE ROOM FOR IT? BHIS 30$ ;NOPE, WE'RE SOMEWHAT SHORT OF BLOCKS MOV $BFNUM,R2 ;YES, R2=NUMBER OF ACTIVE BUFFER .WRITW #AREA,#ETIOCH,$BFTAB(R2),#256.,R1 ;WRITE IT OUT BCC 30$ ;SUCCESS... MOV #1,IFATAL ;WE HAVE A PROBLEM... 30$: .WRITW #AREA,#ETIOCH,#$ELHDR,#$HDLEN,#0 ;WRITE THE HEADER BCC 40$ ;SUCCESS... MOV #1,IFATAL ;WE HAVE PROBLEMS 40$: MOV (SP)+,R2 ;RESTORE PREVIOUSLY SAVED R2 RETURN .SBTTL CRTN - UPDATE DUE TO ERROUT REQUEST ;+ ; ; This code runs as a result of a request from ERROUT to ; empty the current buffer so that a complete log may be ; generated. ; ;- CRTN: CMP RCVMSG+2,#RCVKEY ;IS KEY WHAT WE EXPECTED? BEQ 10$ ;YES... .PRINT #E.WARN ;IN HERE IF THE MESSAGE ISN'T FROM ERROUT.SAV, .PRINT #E.IMR ;PRINT "invalid message received warning" AND BR 50$ ;SET THE COMPLETION ROUTINE BACK UP 10$: MOV $BFNUM,R1 ;DETERMINE ACTIVE BUFFER .WRITW #AREA,#ETIOCH,$BFTAB(R1),#256.,PNXBLK ;WRITE IT OUT BCC 20$ ;SUCCESS... MOV #1,IFATAL ;WE HAVE A PROBLEM... 20$: .WRITW #AREA,#ETIOCH,#$ELHDR,#$HDLEN,#0 ;UPDATE THE HEADER BCC 30$ ;SUCCESS... MOV #1,IFATAL ;WE HAVE A PROBLEM 30$: TST IFATAL ;ANY PROBLEMS? BEQ 50$ ;NOPE... 40$: .RSUM ;YES, RESUME MAINLINE CODE TO ; REPORT THEM BR 70$ 50$: TSTB FST ;SYSTEM TASKING? BNE 60$ ;YES... .RCVDC #AREA,#RCVMSG,#1,#CRTN ;NOPE, ISSUE RECEIVE FROM BG BR 70$ 60$: .READC #AREA,#MSGCHN,#RCVMSG,#1,#CRTN ;ISSUE READ FROM BG 70$: RETURN .SBTTL GETSPF - Initialize the Spfun tables ;GETSPF - Fill the SPFUN tables ; ; build tables about the installed handlers' .spfuns ; ; --------------- -------------- ; CODTAB: | device code | (low byte) SPFUNS: | spfun code | (byte) ; | reserved | (high byte) | type code | (byte) ; --------------- -------------- ; | pointer into| | spfun code | ; | SPFUNS table| | type code | ; --------------- -------------- ; | device code | (low byte) | spfun code | ; | reserved | (high byte) | type code | ; --------------- -------------- ; | pointer into| | 0 | ; | SPFUNS table| | 0 | ; --------------- -------------- ; | device code | (low byte) | spfun code | (byte) ; | reserved | (high byte) | type code | (byte) ; --------------- -------------- ; | pointer into| . . ; | SPFUNS table| . . ; . . . . ; . . . . ; . . . . ; . . . . ; | 0 | | 0 | ; | 0 | | 0 | ; --------------- -------------- .ENABL LSB GETSPF: MOV @#$SYPTR,R5 MOV $SLOT2(R5),R3 ;get length of PNAME table ADD $PNPTR(R5),R5 MOV #CODTAB,R1 MOV #SPFUNS,R2 CLR (R1) ;initialize the null terminators CLR (R2) ;of the tables ;step through the PNAME table and for ;each handler in the table, get its ;device code, use DVREC to read in ;block 0 of the handler and copy the ;special function definition words ;into our table, SPFUNS MOV R3,R4 ASL R3 ;*2 ADD R4,R3 ;= *3 ADD #2,R3 ;R3 = (($SLOT*2)*3)+2 ADD R5,R3 ;R3 -> points into the DVREC table ;which contains the sy: block numbers ;of the first block of the ASR R4 ;R4 = length of PNAME table ($SLOT) .LOOKUP #AREA,#INICHN,#SYSNAM ;get a channel to SY: BCS 60$ 10$: TST (R5) ;is this entry in PNAME empty BEQ 55$ ;branch if yes MOV (R5),DEVNAM ;Do DSTAT on this device .DSTAT #DSTAT,#DEVNAM BCS 55$ MOV #DSTAT,R0 BIT #SPFUN$,(R0) ;does handler support spfuns? BEQ 55$ ;branch if not - see .DSTAT doc MOV (R3),AREA+2 ;read block 0 of handler DEC AREA+2 .READW #AREA,#INICHN,#$ELBF1,#256. BCS 55$ MOV #$ELBF1,R0 ;go through spfun descriptors ADD #H.SPF1,R0 MOVB DSTAT+DS.COD,(R1)+ ;move device code into CODTAB CLRB (R1)+ MOV R2,(R1)+ CLR (R1) CLR -(SP) ;handler has 3 spfun descriptors MOV #3,(SP) ;in block 0, use (SP) as a counter 20$: TSTB 1(R0) ;test the NNX byte BEQ 30$ ;branch if this word defines no ;Spfuns. CALL 70$ ; 70$ disects Spfun words BCS 110$ 30$: TST (R0)+ ;ADD #2 advance to next .SPFUN word DEC (SP) BNE 20$ TST (SP)+ ;done with counter TST (R0) ;.spfun extension table? BEQ 50$ ;branch if not MOV (R0),R0 ;offset (in bytes) to extenstion ;table. MOV R0,-(SP) BIC #^C777,(SP) BIC #777,R0 ;convert high byte of offset into SWAB R0 ;a disk block number ASR R0 ADD R0,AREA+2 ;change .read argument area to ;the appropriate block .READW #AREA,#INICHN,#$ELBF1,#256. BCS 50$ MOV #$ELBF1,R0 ADD (SP)+,R0 ;R0 points to extension table 40$: TST (R0) ;do not auto-inc in case we call 70$ BEQ 50$ ;branch if end of extension table CALL 70$ ; 70$ disects .spfun words BCS 120$ TST (R0)+ ; add #2 BR 40$ 50$: CLR (R2)+ CMP R2,#SPFEND ;is table full? BHIS 120$ ;branch if yes 55$: ADD #2,R5 ADD #2,R3 SOB R4,10$ .CLOSE #INICHN RETURN 60$: TST (SP)+ ;here if .LOOKUP failed JMP CHNER1 ;come here to disect .Spfuns ; R2 points into the table SPFUNS ; R0 points to the actual .spfun descriptor word ; must protect any register used ; ; return with the C-bit set if and only if the table ; is now full 70$: MOV R1,-(SP) MOV R4,-(SP) MOV R5,-(SP) CLR R5 ;make R5 = next entry in SPFUNS table BISB 1(R0),R5 ;first do low byte MOV R5,R4 BIC #7,R5 ;isolate the NN part of NNX BIC #370,R4 ;isolate the X part of NNX SWAB R5 ;one part for each byte BISB R4,R5 SWAB R5 CLR R4 ;now do high byte BISB (R0),R4 CLR R1 80$: ROR R4 BCC 90$ MOV R5,(R2) ADD R1,(R2)+ CMP R2,#SPFEND ;table full? BLO 90$ SEC BR 100$ 90$: CMP R1,#7 ;8 bits per byte BHIS 100$ INC R1 BR 80$ CLC 100$: MOV (SP)+,R5 ;*C* MOV (SP)+,R4 ;*C* MOV (SP)+,R1 ;*C* RETURN ;here if the SPFUNS table is now full 110$: TST (SP)+ 120$: .PRINT #E.WARN ; "ERRLOG-W-Special Function table .PRINT #M.SPF ; is full" RETURN .DSABL LSB .SBTTL FATALE - REPORT FATAL ERRORS FATALE: DEC IFATAL ;WHICH ERROR? BEQ LIOERR ;LOG-FILE I/O ERROR... IMRERR: MOV #E.IMR,R2 ; 'Invalid MESSAGE RECEIVED' BR SHUTUP LIOERR: MOV #E.LIO,R2 ; 'ERRLOG.DAT I/O ERROR' BR SHUTUP ILLERR: MOV #E.ILL,R2 ; 'ILLEGAL ERROR' BR SHUTUP CHNERR: MOV #E.CER,R2 ; 'CHANNEL ERROR' .BR SHUTUP SHUTUP: .PRINT #E.FATL .PRINT R2 MOV #-1,FREADY ;SHUTDOWN COPY CODE .EXIT ;AND GO AWAY .SBTTL IMPURE DATA AREA AREA: .BLKW 5 ;EMT AREA (GENERALIZED) AREAT: .BLKW 4 ;EMT AREA (MRKT'S) SYSNAM: .RAD50 /SY/ .WORD 0,0,0 ;for non-file structure lookup of SY ZEROAD: .RAD50 /MQ/ ;FOR LOOKUP TO RECEIVE (READ) FROM ANY JOB .WORD 0,0,0 ;A LOGICAL JOB NAME OF ZERO BJBDES: .ASCII /B/ ;JOB DESCRIPTOR FOR CHANNEL COPY TO ELINIT .BYTE 0,0,0,0,0 WAITIM: .WORD 0,3777 ;TIME INTERVAL TO WAIT FOR USER TO COMPLETE ; INITIALIZATION DEVNAM: .WORD ;this is the argument area for a .DSTAT call DSTAT: .BLKW 4 XTRAQE: .BLKW 20. ;AREA FOR 2 EXTRA QUEUE ELEMENTS RCVMSG: .BLKW 2 ;RECEIVE BUFFER FOR MESSAGE FROM ERROUT FXM: .BYTE 0 ;INDICATES XM MONITOR IS RUNING FST: .BYTE 0 ;INDICATES ST MONITOR IS RUNNING .EVEN IFATAL: .WORD 0 ;FATAL I/O INDICATOR .SBTTL MESSAGES .NLIST BEX E.FATL: .ASCII /?ERRLOG-F-/<200> E.WARN: .ASCII /?ERRLOG-W-/<200> E.INFO: .ASCII /?ERRLOG-I-/<200> E.IMR: .ASCIZ /Invalid message received/ E.ILL: .ASCIZ /Internal error/ E.LIO: .ASCIZ /Log file IO error/ E.CER: .ASCIZ /Channel error/ M.REM: .ASCII /REMINDER: / M.INI: .ASCIZ /To initiate error logging, RUN ELINIT/ M.SPF: .ASCIZ /Special Function table is full/ .EVEN .LIST BIN .SBTTL Spfun Tables ; CODTAB is a table of two word entries. The first word of an entry is ; a device code, the second word is a pointer into another table, ; SPFUNS. For each class (high byte) of .spfuns in each installed ; handler in the system, there is entry in CODTAB; the entry's first ; word is the handler's device code, the second word points to a ; special function definition word which can be used to lookup a ; an spfun's CTBSIZ =: 4 CODTAB::.BLKW 20. SPFUNS::.BLKW 236. SPFEND: .END