.MCALL .MODULE .MODULE ELCOPY,VERSION=20,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 Who Date Description of modification ; ---- --- ---- --------------------------- ; 001 WLD 25-JUN-92 MSCP21-8 compliance. ; ;************ EDIT HISTORY ********************************************* ; ; March 1988 - add 64 unit support. ; Matthew Sacks ;*********************************************************************** .SBTTL CONDITIONAL ASSEMBLY SUMMARY ;+ ;COND ; ; ERL$U (10.) number of loggable units ; ; ERL$S (1) number of buffer blocks ; ; EL$U64 (1) build in 64 unit support ; ; MMG$T 1 std conditional (required for symbol defines) ; TIM$T std conditional (no code effects) ; ERL$G 1 std conditional (required = 1) ;- ERL$G = 1 ;MUST FORCE THIS MMG$T = 1 ;MUST FORCE THIS .IIF NDF ERL$U ERL$U = 10. ;MAXIMUM NUMBER OF LOGABLE UNITS ; ASSUME THAT WE HAVE 64 UNIT SUPPORT - because it is a very small ; addition to the error logger, its affect is transparent ; and so we won't make users rebuild it. .IIF NDF EL$U64 EL$U64 = 1 .SBTTL DEFINITIONS .ENABL LC .LIBRARY "SRC:SYSTEM.MLB" ; RT-11 MACROS TO BE USED .MCALL .QELDF, .DATE, .GTIM, .ASSUME SOB .MCALL .PRINT, .MFPS, .MTPS .CF3DF .FIXDF .DSPDF .MCALL .CF1DF .CF2DF .SYCDF .MCALL .ELDDF .ELSDF .ELIDF .ELMDF ; INVOKE SYSTEM.MLB macros .FIXDF ;RMON fixed offsets .SYCDF ;system communication area .CF1DF ;system configuration word #1 .CF2DF ;second configuration word #2 .CF3DF ;third configuration word .DSPDF ;defines bits in an spfun definition word .ELDDF ;error logger device error record .ELMDF ;error logger memory error record .ELSDF ;error logger statistcs table record .ELIDF ;error logger record types ; NOW FOR SOME OF OUR OWN MACROS .MACRO BCS. LABEL,?ALT BCC 'ALT' JMP LABEL 'ALT': .ENDM .MACRO BLT. LABEL,?ALT BGE 'ALT' JMP LABEL 'ALT': .ENDM ; SOME ASSUMPTION CHECKS .Assume ERL$U LE 22.,MESSAGE=<;ELCOPY: Too Many Loggable Units> ; RANDOM DEFINITIONS UNITMK = 7 ;UNIT MASK U64MSK = 160 ;for obtaining high three bits of ;unit number out of Q$FUNC byte PR7 = 340 ;processor priority 7 value DU$COD = 50 ;DU device ID MU$COD = 60 ;MU device ID MSGTYP = 000360 ;UQSSP message type bits L.FMT = 10 ;(B) Error Log format flags LF.INF = 2 ;Informational Error Log flag ; QUEUE ELEMENT FORMAT .QELDF ; CACHE MEMORY CONTROL REGISTERS MSYSER = 177744 ;CACHE MEMORY SYSTEM ERROR REGISTER MCONRG = 177746 ;CACHE CONTROL REGISTER MHITMS = 177752 ;CACHE HIT/MISS REGISTER ; STACK FRAME OFFSETS ;these are offsets from the top of the stack to some data that ;is kept around but not in registers ;this is where on the stack that temp word resides X.TMP = 0 ;this is where we keep a device's unit number X.UNI = 2 .SBTTL $ELCPY - START OF COPY CODE ;+ ; ; The following code is used to move the error information passed by ; the handler to the error logging buffer while updating the header. ; ; The first word of this module is the runtime entry point for the monitor's ; subroutine call of the error logger. The second word is the start up ; entry point. ; ; Successful transfers do not generate data for the logging buffer but they ; cause the appropriate counters in the statistics entry for the device ; to be incremented. There are two other cases; for a Device Error $ELCPY ; will jump from here to DEVERR, for a memory board error $ELCPY will jump ; from here to MEMERR ; ; ; For a successful device transfer: ; R4 = Device ID/-1 ; R5 -> 3rd word of queue element (Q.BLKN) ; ;- .GLOBL OPINIT, FREADY .WORD $ELCPY ;PROVIDE ADDRESS OF COPY CODE ERRLOG::JMP OPINIT ;NORMAL FRUN/SRUN ENTRY ; (PERFORM OPERATOR INIT) $ELCPY: TST (PC)+ ;STARTUP OR SHUTDOWN IN PROGRESS? FREADY: .WORD 1 ; : SUBSYSTEM STATUS FLAG ;1=STARTING UP, 0=RUNNING ;-1=SHUTTING DOWN BEQ CONTIN ;RUNNING, SO CONTINUEGr BMI 10$ ;SHUTTING DOWN, QUICK EXIT... INC NOTRDY ;BUMP 'NOT READY' COUNT 10$: CLC ;DON'T CONTINUE DISK I/O CODE RETURN CONTIN: MOV R0,-(SP) ;SAVE SOME REGISTERS MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV R4,-(SP) MOV R5,-(SP) CMPB R4,#GD.IO ;WHAT KIND OF REPORT? BEQ 8$ ;branch for a success I/O log CLR -(SP) ;will later be referenced as x.uni(sp) CLR -(SP) ;will later be referenced as x.tmp(sp) ;X.TMP(SP) : USED FOR DEVICE ;STATISTICS ; (HYBRID DATA - ZERO INDICATES ; NO STATISTICS ENTRY FOR DEVICE, ; NON-ZERO INDICATES STATISTICS ; ARE BEING KEPT, VALUE IS POINTER ; TO STATISTICS ENTRY) CMPB R4,#GD.IO ;this sets flags to indicate ;error type BGT DEVERR ;>-1, DEVICE ERROR JMP MEMERR ;<-1, MEMORY ERROR ;here for success I/O case 8$: CALL GESTAT ;KEEPING STATISTICS ON THIS DEVICE? BCS 20$ ;NOPE... CALL LOGSUC 20$: JMP $EXIT2 ;all done... .SBTTL DEVERR - DEVICE ERROR RECORD LOGGER ;+ ; ; "PATIENT: Doctor, it hurts when I do this. ; DOCTOR: Then don't do that." ; ; For an unsuccessful device transfer: ; R2 -> Device register save area in handler ; R3 = Maximum retries/# of device registers ; R4 = Device ID/retry count ; R5 -> 3rd word of queue element (Q.BLKN) ; ; When logging soft errors, a retry count is passed to the logger. ; One expectation is that the retry count passed from the handler ; must decrease to zero, zero indicating a transfer failure. ; ; If the current error being reported is for the same device/unit as ; the last one in the logging buffer AND the retry count is less than ; the previous one AND the device registers are the same, a new record ; is not built but the occurance count of the previous record is ; incremented and the new retry count is saved. ; ;- DEVERR: INC CERECR ;Increment count of errors received BISB Q$UNIT(R5),X.UNI(SP) ;Isolate unit number bits in place BICB #^c,X.UNI(SP) ; reserved on stack (already cleared) .IF NE EL$U64 CALL GTXUNI ;Get possible extended unit bits BIS R1,X.UNI(SP) ; and merge with low-order unit bits .ENDC ;NE EL$U64 CALL GESTAT ;KEEPING STATISTICS ON THIS DEVICE? BCS 60$ ;NOPE, NO ENTRY... MOV R4,R1 ;Isolate device ID in SWAB R1 ; low byte of R1 (high byte is junk) CMPB R1,# ;Is device type MSCP? BEQ 30$ ;BR if yes: MSCP. CMPB R1,# ;Is device type TMSCP? BNE 40$ ;BR if no: not TMSCP 30$: TST @R2 ;T/MSCP: SAR Packet? BEQ 40$ ;BR if yes. BIT #MSGTYP,2(R2) ;End Message? BEQ 40$ ;BR if yes. BIT #LF.INF,4+L.FMT(R2) ;Informational Error Log? BEQ 40$ ;BR if not. DEC CERECR ;Adjust overall count. BR 50$ ;Don't count Error Log as error. 40$: INC ELS.ER(R0) ;YES, BUMP COUNT OF ERRORS RECEIVED .ASSUME X.TMP EQ 0 50$: MOV R0,@SP ;save pointer to the entry ;a nil pointer indicates statistics ;are not kept for the device - any ;other pointer points to a statistics ;entry. 60$: TST PNXWRD ;any records in active block? BEQ 120$ ;no, so skip comparison with previous ;error log record CLR R1 ;yes, ready to find pointer to word CALL CHKSIZ ; following last record entered BCS 120$ ;Branch if buffer held/not available ADD @R0,R0 ;R0->PREVIOUS RECORD (BY ADDING ; NEGATED LENGTH OF PREVIOUS RECORD) MOV R4,R1 ;R1=DEVICE ID CLRB R1 BISB X.UNI(SP),R1 ;ADD THE UNIT NUMBER CMP R1,ELD.UN(R0) ;SAME DEVICE/UNIT AS LAST TIME? BNE 120$ ;NOPE...NO MORE CHECKING CMPB R4,ELD.RT(R0) ;THIS RETRY LESS THAN LAST ONE? BGE 120$ ;NOPE, BUILD A NEW RECORD MOV R0,-(SP) ;SAVE SOME REGISTERS MOV R2,-(SP) ADD #ELD.RG,R0 ;R0->PREVIOUS RECORD REGISTERS MOV @#$SYPTR,R1 ;MAPPED MONITOR? BIT #KT11$,$CNFG1(R1) BEQ 90$ ;BRANCH IF NOT MAPPED MONITOR .ASSUME EQ 2 TST (R0)+ ;1 word for Q.MEM 90$: MOVB R3,R1 ;GET NUMBER OF REGISTERS 100$: CMP (R0)+,(R2)+ ;REGISTERS THE SAME? BNE 110$ ;NOPE... DEC R1 ;YES, MORE REGISTERS TO CHECK? BGT 100$ ;YES... 110$: MOV (SP)+,R2 ;RESTORE THE REGISTERS WE SAVED MOV (SP)+,R0 TST R1 ;WERE ANY REGISTERS LEFT UNCHECKED? BNE 120$ ;YES, THEN ONE DIDN'T MATCH INCB ELD.OC(R0) ;NOPE...SAME REGISTERS, SO BUMP ; THE MULTIPLE OCCURANCE COUNT MOVB R4,ELD.RT(R0) ;UPDATE THE RETRY COUNT .ASSUME X.TMP EQ 0 TST @SP ;keeping statistics? BEQ 200$ ;NOPE, NO ENTRY .ASSUME X.TMP EQ 0 ADD #ELS.EL,@SP ;yes, point at count of errors logged INC @X.TMP(SP) ;and bump it BR 200$ 120$: ;calculate word size of new record MOVB R3,R1 ;get the number of words passed to us ADD #,R1 ;add in the word size of fixed part MOV @#$SYPTR,R0 ;Mapped monitor? BIT #KT11$,$CNFG1(R0) BEQ 70$ ;Branch if not .ASSUME </2> EQ 1 INC R1 ;add one for Q.MEM 70$: CALL CHKSIZ ;Is there enough room for this record? BCS $ELERR ;Branch if not .ASSUME X.TMP EQ 0 TST @SP ;keeping statistics for the device? BEQ 140$ ;NOPE, NO ENTRY FOR THE DEVICE... .ASSUME X.TMP EQ 0 ADD #ELS.EL,@SP ;yes, point at count of errors logged INC @X.TMP(SP) ;and bump it 140$: ; HERE TO BUILD A DEVICE ERROR RECORD IN THE LOGGING BUFFER MOVB R1,(R0)+ ; - RECORD SIZE MOVB PNXREC,(R0)+ ; - RECORD NUMBER INC PNXREC ;(KEEP RECORD NUMBER UP TO DATE) MOVB X.UNI(SP),(R0)+ ; - UNIT NUMBER SWAB R4 ;SET TO GET DEVICE ID MOVB R4,(R0)+ ; - DEVICE ID CODE SWAB R4 ;SET TO GET RETRY COUNT MOVB R4,(R0)+ ; - RETRY COUNT MOVB #1,(R0)+ ; - DUPLICATION COUNT (STARTS AT 1) CALL GETDAT ;INSERT THE DATE AND TIME MOV (R5)+,(R0)+ ; - Q.BLKN (FROM QUEUE ELEMENT) TST (R5)+ ;BYPASS Q.FUNC/Q.UNIT/Q.JNUM MOV (R5)+,(R0)+ ; - Q.BUFF (FROM QUEUE ELEMENT) ;we would like now to store the Q.WCNT field from the queue element ;but if we are logging an .SPFUN which is of type=other or type= ;motion, then we store 0 for the word count so that ERROUT knows ;that it is not a read or a write operation that failed. We also ;store the 0 if it is a "special directory operation." MOV R1,-(SP) ;Save record size TSTB Q$FUNC-Q$WCNT(R5) ;test the FUNC byte BEQ 160$ ;if zero then keep the word count BPL 150$ ;if positive then pass a zero for ;the word count ;if negative, it is an spfun operation ;so we call FNDFUN to get the TYPE ;of the SPFUN MOV R4,-(SP) ;Save R4 and R5 around FNDFUN call MOV R5,-(SP) ; because we need to use them for CLRB R4 ; parameter passing SWAB R4 ;R4 = device code SUB #Q$BLKN-Q$WCNT,R5 ;move R5 back to Q$BLKN CALL FNDFUN MOV (SP)+,R5 MOV (SP)+,R4 TST (R1) ;did FNDFUN find the type of the BEQ 150$ ;spfun? branch if not INC R1 CMPB (R1),#DSP.MV ;is the type=motion? BEQ 150$ ;branch if yes TSTB (R1) ;is the type=other? BNE 160$ ;branch if no 150$: TST (R5)+ ;Skip over Q.WCNT CLR (R0)+ ;Clear the word count BR 170$ 160$: MOV (R5)+,(R0)+ ; - Q.WCNT (FROM QUEUE ELEMENT) 170$: MOV (SP)+,R1 ;Restore record size MOV @#$SYPTR,-(SP) ;BUILD ADDRESS OF CONFIG WORD ADD #$CNFG1,(SP) ; ON STACK BIT #KT11$,@(SP)+ ;RUNNING UNDER XM? BEQ 180$ ;NOPE... CMP (R5)+,(R5)+ ;SKIP OVER Q.COMP AND Q.PAR MOV (R5)+,(R0)+ ; - Q.MEM (FROM QUEUE ELEMENT) 180$: MOV R3,(R0)+ ; - MAX RETRIES/# OF REGISTERS MOVB R3,R3 ;GET COUNT OF REGISTERS 190$: MOV (R2)+,(R0)+ ; - A DEVICE REGISTER DEC R3 ;MORE TO GO? BGT 190$ ;YES... ASL R1 ;R1 = length of record (in bytes) ADD R1,PNXWRD ; and update 'next word' offset NEG R1 ;Negate the size MOV R1,@R0 ; and save it (for use in checking ; previous record for duplicate ; register/PC values) 200$: JMP $ELXIT ;AND TAKE COMMON EXIT .SBTTL MEMERR - MEMORY ERROR RECORD LOGGER ;+ ; Memory errors are no longer logged by the error logger. The monitor ; has been changed not to call the error logger on memory errors. ;- MEMERR: JMP $ELXIT ;AND TAKE COMMON EXIT .SBTTL $ELXIT - EXIT ROUTINES ; $ELXIT is the success exit from an invokation of the error logger, ; we come here when an error has been logged ; ; $ELERR is the error exit ; $ELERR: INC CMENTB ;BUMP COUNT OF MISSED ERRORS CMP PNXBLK,SMAXSZ ;branch iff merely that the memory BLO 5$ ;buffers were full DEC CMENTB INC CMENTF TST (PC)+ ;have we already printed file full 4$: .WORD 0 ;message? BNE $ELXIT ;branch if so MOV SP,4$ ;SET ONCE-ONLY FLAG MOV PC,R0 ADD #F.FULL-.,R0 BR 6$ 5$: MOV PC,R0 ADD #B.FULL-.,R0 ;R0->BUFFER FULL MESSAGE 6$: .PRINT ;PRINT IT $ELXIT: CMP (SP)+,(SP)+ ;discard X.TMP and X.UNI from stack $EXIT2: MOV (SP)+,R5 ;RESTORE REGISTERS WE SAVED MOV (SP)+,R4 ;moves preserve carry bit!!! MOV (SP)+,R3 MOV (SP)+,R2 MOV (SP)+,R1 MOV (SP)+,R0 TST $ELRSM ;Monitor should resume I/O? (C=0) BEQ 15$ ;*C* Branch if not CLR $ELRSM ;Clear resume flag SEC 15$: RETURN .SBTTL GESTAT - GET POINTER TO DEVICE STATISTICS ENTRY ;+ ; ; GESTAT ; Determines if an entry exists in the device statistics ; table for the device currently being reported. If an ; entry exists, an address is returned which is a pointer ; to the entry. If an entry does not exist, one is created ; and its address is returned. If an entry does not exist ; and there is no room to build one, the user is informed. ; ; CALL: ; R4 = Device Id/Retry count ; R5 -> Queue element (Q.BLKN) ; ; RETURNS: ; R0 -> Statistics entry ; R1 is munged ; R4,R5 are unchanged ; ; ERRORS: ; no entry if carry=1 ; ;- .ENABL LSB GESTAT: MOVB Q$UNIT(R5),-(SP) ;GET THE UNIT NUMBER BIC #<^CUNITMK>,(SP) ;STRIP THE EXTRANEOUS BITS .IF NE EL$U64 CALL GTXUNI ;Get possible extended unit bits BIS R1,@SP ; and merge with low-order unit bits .ENDC ;NE EL$U64 MOV R4,R0 ;R0=DEVICE ID/RETRY COUNT CLRB R0 ;STRIP TO DEVICE-ID BIS R0,(SP) ;COMBINE IT WITH UNIT NUMBER MOV PC,R0 ;ASSEMBLE A POINTER TO THE DEVICE ADD #DEVSTS-.,R0 ; STATISTICS TABLE IN A PIC FASHION MOV #ERL$U,R1 ;R1=MAXIMUM NUMBER OF STAT ENTRIES 10$: CMP (R0),#-1 ;END OF STATISTICS ENTRIES? BEQ 40$ ;YES, HAVE TO ADD A NEW ENTRY... CMP (R0),(SP) ;NOPE, IS THIS THE ENTRY WE WANT? BEQ 60$ ;YES... ADD #ELS.SZ*2,R0 ;NOPE, ON TO NEXT ENTRY DEC R1 ;ARE THERE ANY MORE? BGT 10$ ;YEP... TST (PC)+ ;NOPE, PRINTED THIS MESSAGE ALREADY? 20$: .WORD 0 BNE 30$ ;YES, DON'T ANNOY USER WITH IT AGAIN MOV PC,R0 ;NOPE, ASSEMBLE A POINTER TO IT ADD #E.STAT-.,R0 ; IN A PIC FASHION .PRINT ;INFORM THE USER MOV SP,20$ ;DISABLE THE MESSAGE 30$: TST (SP)+ ;DISCARD SEARCH IDENTIFIER BR 70$ 40$: MOV #ELS.SZ,R1 ;R1=LENGTH OF STATISTICS ENTRY 50$: CLR (R0)+ ;PREPARE THE NEW ENTRY DEC R1 ;DONE? BGT 50$ ;NOPE, MORE TO CLEAR... MOV #-1,(R0) ;YES, SET THE NEW FENCE SUB #ELS.SZ*2,R0 ;R0->START OF ENTRY MOV (SP),(R0) ;SET ENTRY IDENTIFIER 60$: TST (SP)+ ;DISCARD SEARCH IDENTIFIER TST (PC)+ ;ENTRY FOUND (CARRY CLEAR) 70$: SEC ;ENTRY NOT FOUND (CARRY SET) RETURN .DSABL LSB .IF NE EL$U64 .SBTTL GTXUNI - GET EXTENDED UNIT NUMBER (HIGH 3 BITS ONLY) ;+ ; ; GTXUNI ; Gets high three bits of extended unit number (if handler is ; an extended unit handler) and returns these three bits in ; bits 3-5 of R1. All other bits in R1 are cleared. ; ; CALL: ; R4 = Device Id/Retry count ; R5 -> Queue element (Q.BLKN) ; ; RETURNS: ; R1 is high 3 bits of extended unit number in bits 3-5 ; R0 is munged ; R4,R5 are unchanged ; ; ERRORS: ; none ;- GTXUNI: MOV R2,-(SP) ;Save R2 MOV @#$SYPTR,R1 ;R1 -> $RMON BIT #CF3.64,$CNFG3(R1) ;Does monitor support extended units? BEQ 40$ ;Branch if not CLR R2 ;Clear to avoid sign extend BISB $SLOT2(R1),R2 ;Get number of device slots * 2 ADD $PNPTR(R1),R1 ;R1 -> $PNAME table ADD R2,R1 ;R1 -> $ENTRY table MOV R1,R0 ;R0 -> just past $PNAME table ADD R2,R1 ;R1 -> $ENTRY table terminator (-1) TST (R1)+ ;R1 -> $STAT table MOV R1,-(SP) ;@SP -> $STAT table ADD R2,@SP ;@SP -> $DVREC table ADD R2,@SP ;@SP -> $HSIZE table ADD R2,@SP ;@SP -> $DVSIZ table ADD R2,@SP ;@SP -> $PNAM2 table ADD R2,@SP ;@SP -> past $PNAM2 table ASR R2 ;Convert to number of slots (words) 10$: MOV R4,-(SP) ;Get device code SWAB @SP ; in low byte of @SP CMPB (SP)+,@R1 ;Does our dev code match $STAT entry? BEQ 20$ ;Branch if so TST (R1)+ ;Skip to next $STAT entry SOB R2,10$ ;Check until $STAT table exhausted TST (SP)+ ;If not found, dump $PNAM2 pointer BR 40$ ; and return extended unit bits of 0 20$: ASL R2 ;Neg. byte offset from end of dev tbl SUB R2,R0 ;R0 -> corresponding $PNAME entry SUB R2,@SP ;@SP -> corresponding $PNAM2 entry CMP @R0,@(SP)+ ;Are $PNAME and $PNAM2 entries equal? BEQ 40$ ;Branch if so -- no extended unit MOVB Q$FUNC(R5),R1 ;Get function code BPL 30$ ;If non-negative, leave as is COM R1 ; else, one's complement it 30$: BIC #^c,R1 ;Isolate high 3 bits of extended unit ASR R1 ; number and shift to bit pos 3-5 BR 50$ ;Go restore registers and return 40$: CLR R1 ;No extended unit number 50$: MOV (SP)+,R2 ;Restore R2 RETURN .ENDC ;NE EL$U64 .SBTTL CHKSIZ - CHECK FOR ROOM IN LOGGING BUFFER ;+ ; ; CHKSIZ ; Determines if there is room in the logging buffer for ; another record. If there is room, an address is returned ; which is a pointer to where the record may be inserted. ; A "fence" (-1) is placed after the last record of any ; unfilled block. ; ; CALL: ; R1 = size of record to add (in words) ; ; RETURN: ; R0 -> start of area for new record ; R1 unchanged ; ; ERRORS: ; no room in buffer if carry=1 ; ;- CHKSIZ: TST PNXWRD ;Is current buffer empty? BEQ 10$ ;Branch if so, buffer is active CALL 30$ ;Get -> to word after last record CMP @R0,#-1 ;Is fence in place? BNE 10$ ;Branch if not, buffer is active MOV $BFNUM,R0 ;Get current buffer number (for CALL) CALL 20$ ;Switch to next buffer if possible BCS 40$ ;Still held or ERRLOG.DAT too small 10$: MOV PNXWRD,R0 ;R0=OFFSET INTO ACTIVE BUFFER ADD R1,R0 ;ADD LENGTH OF RECORD TO BE LOGGED ADD R1,R0 ; (ADD TWICE, LENGTH IS IN WORDS) CMP R0,#255.*2 ;WOULD RECORD OVERFLOW THIS BUFFER? ; (LEAVE ROOM FOR -1 FENCE) BLT 30$ ;NOPE... CALL 30$ ;GET POINTER TO WORD FOLLOWING THE MOV #-1,@R0 ; LAST RECORD AND INSERT FENCE (-1) MOV $BFNUM,R0 ;DETERMINE CURRENT BUFFER INC $BFLAG(R0) ;MARK IT FULL 20$: CMP PNXBLK,SMAXSZ ;WILL RECORD GO IN NEXT BLOCK? BGE 40$ ;NOPE, THEY'RE SCARCE AT THE MOMENT NEG R0 ;YES, SELECT OTHER BUFFER ADD #2,R0 TST $BFLAG(R0) ;Is buffer full? BNE 40$ ;Branch if so -- take error return MOV R0,$BFNUM ;MAKE IT THE ACTIVE BUFFER CLR PNXWRD ;RESET THE OFFSET INC $ELRSM ;INDICATE WE WANT I/O RESUMED 30$: MOV $BFNUM,R0 ;DETERMINE ACTIVE BUFFER MOV $BFTAB(R0),R0 ;AND GET A POINTER TO IT ADD PNXWRD,R0 ;NOW ADD LOGGING OFFSET TST (PC)+ ;ROOM IN BUFFER (CARRY CLEAR) 40$: SEC ;NO ROOM (CARRY SET) RETURN .SBTTL LOGSUC - Log a successful I/O event ;+ ; ; LOGSUC ; Increment the appropriate success I/O count, to do so we ; examine the queue element to what kind of operation it was ; ; INPUT ; R0 -> to the device statistics entry for the device ; R4 high byte is device ID ; R5 -> the queue element ;- .ENABL LSB LOGSUC: MOV R1,-(SP) ;protect registers MOV R4,-(SP) TSTB Q$FUNC(R5) BEQ 30$ ;0 means decide on the basis of Q$WCNT BGT 10$ ;special directroy operations are ;logged as type = other/unknown SWAB R4 ;put desired device id in low byte CALL FNDFUN ;find this device in the table CODTAB TST (R1) BEQ 10$ ;0 means no entry in table, treat as ;type=other INC R1 ;point to high byte of entry CMPB (R1),#DSP.RD ;find the "type" of the .spfun BEQ 50$ CMPB (R1),#DSP.WR BEQ 40$ CMPB (R1),#DSP.RW BEQ 30$ CMPB (R1),#DSP.MV BEQ 20$ 10$: ADD #ELS.OS,R0 ;R0 -> count of "other" successes BR 60$ 20$: ADD #ELS.MS,R0 ;R0 -> count of "motion successes BR 60$ 30$: TST Q$WCNT(R5) ;READ, WRITE OR SEEK? BEQ 20$ ;SEEK is a motion BPL 50$ ;READ, 40$: ADD #ELS.WS,R0 ;WRITE BR 60$ 50$: ADD #ELS.RS,R0 ;ASSUME SUCCESSFUL READ 60$: ADD #1,(R0)+ ;BUMP SUCCESS COUNT ADC (R0) ; (DOUBLE PRECISION INTEGER) 70$: MOV (SP)+,R4 MOV (SP)+,R1 RETURN .DSABL LSB .SBTTL FNDFUN - Find an entry in CODTAB for a device's spfun ;+ ; ; FNDFUN - find an entry in CODTAB for a device's spfun ; ; INPUT: R4 = device ID ; R5 -> queue element ; ; OUTPUT: R1 -> spfun's entry in CODTAB (success) ; R1 -> 0 (failure) ; ; .ENABL LSB FNDFUN: MOV #CODTAB,R1 10$: TST (R1) ;end of table? BEQ 50$ ;branch if this device isn't in ;the SPFUN table CMPB (R1),R4 ;is this the device? BNE 20$ ;branch if not MOV 2(R1),R1 ;R1 -> spfun list for this device BR 30$ 20$: ADD #CTBSIZ,R1 ;go to next entry in CODTAB BR 10$ 30$: TST (R1) ;end of spfun list? BEQ 50$ ;if yes, branch and treat as other CMPB Q$FUNC(R5),(R1)+ ;is this the SPFUN? BEQ 40$ ;branch if yes INC R1 BR 30$ 40$: DEC R1 50$: RETURN .DSABL LSB .SBTTL GETDAT - PLACE DATE/TIME IN RECORD ;+ ; ; GETDAT ; Places the current date/time in an error record. ; ; CALL: ; R0 -> 3 successive words to receive date and time ; (will be returned in order date, high-order ; time, low-order time) ; ; RETURN: ; R0 = (R0 before call)+6 ; ; ERRORS: ; none ; ; NOTE: ; The following routine uses the RTEM time hook as the ; location to jump to in the monitor in order to obtain ; the time (and update the date). ; ; Because we are in system state - we must call monitor routines ; directly instead of using system macros ;- GETDAT: MOV R1,-(SP) ;SAVE R1 FOR AWHILE MOV @#$SYPTR,R1 ;R1->$RMON .MFPS ;SAVE CURRENT PRIORITY MOV R1,-(SP) ADD $ELTIM(R1),(SP) ;(SP)->'GTIHOK' TIME ROUTINE ADD #2,R0 ;R0->WHERE TO PUT TIME .MTPS #PR7 ;SET IT HIGH CALL @(SP)+ ;GO GET IT FROM THE MONITOR .MTPS ;RESTORE PREVIOUS PRIORITY MOV @#$SYPTR,R1 ;R1->$RMON MOV $DATE(R1),-4(R0) ;GET THE DATE MOV (SP)+,R1 ;RESTORE PREVIOUSLY SAVED R1 TST (R0)+ ;UPDATE R0 RETURN .SBTTL TEXT .NLIST BEX F.FULL: .ASCIZ /?ERRLOG-W-Log File Full, an error record counted but discarded/ B.FULL: .ASCIZ /?ERRLOG-W-Log Buffer Full, an error record counted but discarded/ E.STAT: .ASCIZ /?ERRLOG-W-Device statistics table is full/ .EVEN .LIST BEX .SBTTL IMPURE DATA AREA .GLOBL NOTRDY, RECHED, $ELHDR .GLOBL CMENTR, PNXBLK, $HDLEN .GLOBL $BFNUM, $BFTAB, $BFLAG .GLOBL $ELBF1, SMAXSZ NOTRDY: .WORD 0 ;COUNT OF MISSED REPORTS ; DUE TO START-UP ELAREA: .BLKW 2 ;EMT AREA FOR .GTIM RECHED: .WORD 0 ;NOT PART OF HEADER, WORD COUNT ; FILLED BY RECEIVE ; ** BEGIN CRITICAL ORDERING ** ; The following is the format of the header block ; of the logging file, ERRLOG.DAT. $ELHDR: ;EL HEADER BLOCK OFIXED: .WORD <*2> ;OFFSET TO FIXED PART OF HEADER DEVSTS: .WORD -1 ;FENCE .BLKW ;DEVICE STATISTICS CERECR: .WORD 0 ;TOTAL ERROR RECORDS RECEIVED CMENTB: .WORD 0 ;MISSED ENTRIES - BUFFER FULL CMENTF: .WORD 0 ;MISSED ENTRIES - FILE FULL CMENTR: .WORD 0 ;MISSED ENTRIES - TASK NOT READY CMPARE: .WORD 0 ;COUNT OF MEMORY PARITY ERRORS CCPARE: .WORD 0 ;COUNT OF CACHE PARITY ERRORS PNXREC: .WORD 1 ;NEXT RECORD NUMBER PNXBLK: .WORD 1 ;BLOCK NUMBER OF NEXT RECORD PNXWRD: .WORD 0 ;OFFSET WITHIN BLOCK OF NEXT RECORD SMAXSZ: .WORD 100. ;MAXIMUM SIZE OF ERROR FILE CNFGW1: .WORD 0 ;CONFIG WORD 1 CNFGW2: .WORD 0 ;CONFIG WORD 2 INIDAT: .WORD 0 ;DATE OF INITIALIZATION INTIM1: .WORD 0 ;TIME OF INITIALIZATION (WORD 1) INTIM2: .WORD 0 ;TIME OF INITIALIZATION (WORD 2) $HDLEN = <.-$ELHDR>/2 .IIF GT <$HDLEN-256.> .ERROR ;HEADER TOO LONG ; ** END CRITICAL ORDERING ** $ELRSM: .WORD 0 ;RESUME I/O CODE FLAG $BFNUM: .WORD 0 ;ACTIVE BUFFER INDICATOR ; (0 OR 2) $BFTAB: .WORD $ELBF1 ;POINTER TO BUFFER 1 .WORD $ELBF2 ;POINTER TO BUFFER 2 $BFLAG: .WORD 0 ;BUFFER 1 FULL FLAG .WORD 0 ;BUFFER 2 FULL FLAG $ELBF1: .BLKW 256. ;LOGGING BUFFER 1 $ELBF2: .BLKW 256. ;LOGGING BUFFER 2 .END ERRLOG