.TITLE log - LOG messages for scli .IDENT /1.24/ .REM | *+ log - LOG messages for scli File:log.mac Version: 1.24 Author: Last Edit: 27-DEC-1985 11:19:08 Last Update: 27-Dec-1985 11:39:14 Log errors using smsg$ instead of rpoi of mcr *- | .LIBRARY /LB:[1,1]GLMAC.MLB/ .MCALL push,pop,return .mcall qiow$s,dir$,alun$s,gtim$s,smsg$ .mcall qio$,qiow$,astx$s,mrkt$,wtse$,cmkt$ .mcall rpoi$ .SBTTL LOCAL DATA .psect ldat,d,lcl,con ; ; use this psect for scratch storage - it is not guaranteed to be saved ; across calls to the module ; ;@MARK@ ; ; fake r5 argument list for internal error reporting ; -- allows us to report our own errors (or at least try!) errs: .word 0 ; internal error flags ; bits: er.ssm = 1 ; smsg error er.cot = 2 ; cot error er.p2 = 4 ; 1 -> on loop-back pass ; ; point r5 at erlst, then loop back to start ; erlst: .word 0 ; put number of args here .word 9. ; internal error code .word ercod ; .word nump ; erpl: .blkw 3 ; space for params ercod: .word 0 ; put internal error code here nump: .word 0 ; put number extra params here smsp0: .word 0 ; holds sms error dsw cotp0: .word 0 ; holds cot error dsw cotp1: .word 0 ; holds cot iosb word 1 cotp2: .word 0 ; holds cot iosb word 2 savr5: .word 0 ; saved original return address ; ; end of internal error stuff ; msgnum: .word 0 ; message number argblk: .blkw 10 ; ten words for $edmsg arguments buf0: .ascii /SSM / ; for rpoi buff: .blkb 134. ; buffer for building output buflen: .word 0 ; length of buffer ; ; NOTE: max buffer length for the RPOI flavor of SSM logging ; is 72. plus the SSM prefix! ; .psect data,d,gbl,con ; ; use this psect for module-specific data which must be retained across ; calls to the module ; ; ; be sure to include the message definition file ; .include /logmsg.mac/ .psect dpbs d,rw,lcl,con ; ; this psect contains the static dpbs ; rpoi: rpoi$ MCR...,,,1,1,,buf0,,,TT,0 smsg: smsg$ sm.ser,buff ; system service message cqio: qio$ io.wvb,2,2,,cotp1,qast, ; lun 2 QIO cqiok: qio$ io.kil,2,10 ; kill io on lun 2 mrkt: mrkt$ ,15.,2,mtast ; 15 second wait canmt: cmkt$ ,mtast ; cancel mrkt wtse: wtse$ 2 ; wait for efn 2 .PSECT ; code goes in the blank psect .SBTTL LOG - Log messages .REM | LOG logs messages to the error logging file (via SMSG$) and/or to the console (CO). For testing, if logtt3 is defined (just before entry point), logs all messages in raw form to LUN #3, which is hardcoded to TT3. Messages are identified by number. A variable number of parameters are required depending upon the message. For message numbers, required parameters, see module LOGMSG.MAC. Message number is a pass-by-value. All of the variable params are pass by reference. CALL call r5,log, msg = message number (messages defined above) params = parameters dependant upon message number see individual message definition above INPUT params on r5 stack OUTPUT message formatted and logged as indicated by flags word in message database (defined above) REGS preserved CALLS uses $EDMSG from SYSLIB to format messages | ;;; logtt3 = 0 ; define for test mode dump to tt3: LOG:: push clr errs ; no errors yet 10$: ; this is return-entry point for 'calling ourselves' ; ; all messages share a fixed preamble, consisting of "SECURE:" and ; the date-time. Set this up now in buff ; ; bypassed because both COT and Errlog timestamp messages ; we may need to put back in, if we must work to CO: (vs cot) ; with timestamps. ;; gtim$s #argblk ; get date and time in argblk ;; bcc 200$ ; br if no error ;; ;; mov #argblk, r0 ; if error, clear out date-time ;; mov #8., r1 ; word count ;;100$: clr (r0)+ ; clear out date-time ;; sob r1, 100$ 200$: mov #buff, r0 ; set up for first $edmsg mov #premsg, r1 ; ... control string mov #argblk, r2 ; ... argument block .globl $edmsg call $edmsg ; format the preamble mov r1, buflen ; save first length ;***** NOTE ***** ;* from here on, preserve r0, it is the buffer pointer! ;**************** ; ; now, pull off the arguments. the first argument is the number ; of remaining arguments. The only required arg is the message ; number. ; mov (r5)+, r1 ; r1=number of args mov (r5)+, msgnum ; get message number (always present) dec r1 ; count remaining args beq 350$ ; br if none ; ; copy remaining args to the arg block - all but msgnum are ; pass by reference ; mov #argblk, r2 300$: mov @(r5)+, (r2)+ ; copy an arg sob r1, 300$ ; copy remaining args ; ; obtain control string (msgx:) from message number ; 350$: mov msgnum, r1 dec r1 ; table starts at "1" asl r1 ; make offset add #msgtbl, r1 ; point into table cmp #msgtnd, r1 ; off end? blos 400$ ; yes - br to illegal msg mov (r1), r1 ; pick up pointer to control string br 500$ ; and join common code ; ; illegal message code just fakes out an internal error, ; and loops back to log that. The error number is 1. ; 400$: mov #msg9, r1 ; point to 'internal error' mov #argblk, r2 ; point to argblk mov #1, (r2) ; stuff error number mov #1, 2(r2) ; one more param mov msgnum, 4(r2) ; bad message number ; and fall thru to format code mov #9., msgnum ; now working on different message ; ; r0,r1 now set for $edmsg ; 500$: mov #argblk, r2 ; complete setup call $edmsg ; format remainder of message add r1, buflen ; total up length ; ; now examine control byte, and send the thing out ; mov #msgflg, r2 ; point to flag byte table add msgnum, r2 ; offset into table dec r2 ; back off bitb #ms.cot, (r2) ; output to co? beq 1000$ ; no - br ;*** do it to co mov #cqio, r1 ; point to qio dpb mov buflen, (r1) ; stuff length dir$ #cqio ; execute qio bcc 510$ ; no dir err - continue bit #er.p2, errs ; on second pass? bne 1000$ ; yes - abandon ship bis #er.cot, errs ; remember error mov $dsw, cotp0 ; save dsw br 1000$ ; and abandon attempt 510$: dir$ #mrkt ; set timeout bcc 530$ ; better not fail! mov $dsw, r0 ; crash and burn mov #2, r1 iot 530$: dir$ #wtse ; wait for efn - ignore errors 1000$: bitb #ms.ssm, (r2) ; output to error logging? beq 2000$ ; no - br ;*** do it to ssm mov buflen, ; stuff buffer length dir$ #smsg ; do it bcc 2000$ ; branch if directive okay br 1030$ ; dir failed, go to error handling code ; ; THE ABOVE SMSG$ CODE REQUIRES THAT SCLI BE PRIVELEGED (PR0). ; ; Rather than do that, we can get to the error logger via the ; MCR SSM command, using rpoi. Since MCR is a CLI, we are unable ; to pass the connection beyond MCR, thus we cannot tell when ; SSM/ERRLOG is completed. Use of this method may result in ; errors not being logged (giving "task active" messsages on console). ; We cannot setup a wait, since we would then expose ourselves to ; cracking during the waiting period when a cli shutdown message ; was issued. ; ; try using rpoi of mcr for the ssm ;*****NOT USING RPOI OF MCR AT THIS TIME ; ; cmp #72., buflen ; check for buffer overflow ; bhis 1010$ ; ok - br ; mov #72., ; stuff in what we can ; br 1020$ ; and join common code ;1010$: mov buflen, ; stuff in buffer length ; add #4, ; bump for /SSM / ;1020$: dir$ #rpoi ; do it ; bcc 2000$ ; no err - br ; ; set up to report our own error ; 1030$: bit #er.p2, errs ; on pass 2 already? bne 2000$ ; yes - don't try again mov $dsw, smsp0 ; save DSW bis #1, errs ; flag error 2000$: .if df logtt3 ; if test dump alun$s #3,#"TT,#3 ; force lun 3 to tt3: for test ; don't sweat errors qiow$s #IO.WVB,#3,#3,,,,<#buff,buflen,#40> ; dump it out ; don't sweat errors .endc ; logtt3 ; ; LOG is not really re-entrant, since it uses fixed local data ; However, it should be OK to call ourselves (ONCE!) in order ; to report internal errors. The idea is that, by this point in ; the code, we are done with the scratch database, so a call to ; ourselves is OK. Note, we carefully keep track of this activity, ; to prevent an infinite error loop. ; ; at this point, the r5 stack is cleaned up (points to the return ; address) and r0-r2 are still saved. ; 3000$: tst errs ; internal errors? ;***** ;* INTERNAL ERROR REPORTING DISABLED ;**** BR 5000$ ; beq 5000$ ; no - br bit #er.p2, errs ; on second pass? beq 3100$ ; yes - br mov r5, savr5 ; save return link bis #er.p2, errs ; show on second pass 3100$: mov #erpl, r5 ; point param lst bit #er.ssm, errs ; ssm error? beq 4000$ ; no - br bic #er.ssm, errs ; show done ssm mov #2, ercod ; set internal error number mov #smsp0, (r5) ; point to parameter mov #1, nump ; set number extra params mov #erlst, r5 ; set to fake arg list mov #5, (r5) ; set num args jmp 10$ ; loop back 4000$: bit #er.cot, errs ; console error? beq 4700$ ; no - br mov #erpl, r5 ; point to param list bic #er.cot, errs ; show done cot mov #3, ercod ; show internal error number mov #3, nump ; show number extra params mov #cotp0, (r5)+ ; stuff param addresses mov #cotp1, (r5)+ ; ... mov #cotp2, (r5)+ ; ... mov #erlst, r5 ; set to fake arg list mov #7, (r5) ; set num args jmp 10$ ; and loop back 4700$: mov savr5, r5 ; restore return address 5000$: pop return r5 .SBTTL qast .REM | AST service routine for QIO completion. When this one fires, cancel the mark-time. | qast: tst (sp)+ ; clean stack dir$ #canmt ; cancel mark-time cmpb #is.suc, cotp1 ; io success? beq 10$ ; y- br bit #er.p2, errs ; on second pass? bne 10$ ; yes - don't log another bis #er.cot, errs ; set cot error 10$: astx$s .SBTTL mtast .REM | This is the mark-time AST service routine. When it fires, the output qio has timed-out. Kill the qio, then exit. | mtast: tst (sp)+ ; clean stack dir$ #cqiok ; kill outstanding IO astx$s .end