Trailing-Edge
-
PDP-10 Archives
-
BB-X117B-SB_1986
-
10,7/nml/nmut10.mac
There are 2 other files named nmut10.mac in the archive. Click here to see a list.
;DSKT:NMUT10.MAC[10,6026,NMLUPD] 31-Jan-85 15:44:21, Edit by DAVENPORT
;
; Run NML702.EXE if started under load 70260 or earlier.
;
; DSKC:NMUT10.MAC[10,5665,SOURCE,TOPS10] 20-Oct-83 23:09:20, Edit by GROSSMAN
;
; Put literals in the hiseg.
; Edit=43
;
;NET:<GROSSMAN.NML-SOURCES>NMUT10.MAC.2 9-Feb-82 16:32:45, Edit by GROSSMAN
;
; Turn off interrupts during message processing in order to prevent typeout
; races.
;
; NMUT10 - TOPS10 specific utility functions
; LSG DECnet Network Management
;
; COPYRIGHT (c) 1980
; DIGITAL EQUIPMENT CORPORATION
;
; This software is furnished under a license and may be used
; and copied only in accordance with the terms of such license
; and 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. No title to
; and ownership of the software is hereby transferred.
;
; The information in this software is subject to change
; without notice and should not be construed as a commitment
; by DIGITAL EQUIPMENT CORPORATION.
;
; DIGITAL assumes no responsibility for the use or reliability
; of its software on equipment which is not supplied by
; DIGITAL.
;
TITLE NMUT10 - TOPS10 specific utility functions
SUBTTL Introduction
Comment &
This set of routines implements the TOPS10 versions
of utility functions required. There are two cases
for these functions:
(A) TOPS10 only functions. These are functions
that are required for TOPS10 only, and no
other operating system uses them.
(B) Generic system specific functions. These
functions are required of all operating
system interfaces, have a standard calling
convention, but have different code sets to
implement them.
&
SUBTTL Definitions
SALL ; Suppress macro expansions
; for a clean listing
SEARCH JOBDAT ; Job data area
SEARCH UUOSYM ; Monitor symbol definitions
SEARCH MACTEN ; Useful macros
; Register definitions
T0==0 ; Temporaries (scratchable)
T1==1
T2==2
T3==3
T4==4
P1==5 ; Something a little more permanent
P==17 ; Stack pointer
TWOSEG 400000 ; Put this into the high seg
define OFF%INTERRUPT
< MOVX T1,PS.FOF
PISYS. T1,
HALT .
AOS INTNST##>
define ON%INTERRUPT(%LAB)
< SOSLE INTNST##
JRST %LAB
MOVX T1,PS.FON
PISYS. T1,
HALT .
%LAB: >
SUBTTL NMLCHK
; Routine - NMLCHK
;
; Function - This routine checks the monitor load number, and
; runs SYS:NMLXXX.EXE if running 702
; or earlier.
;
; Arguments - none.
;
; Value - none.
ENTRY NMLCHK
NMLCHK: MOVE T1,[%CNDAE] ;Use same GETTAB that DAEMON does
GETTAB T1, ;To determine version
HALT . ;and quit if earlier than 702
HLRZ T2,T1 ;Save SIXBIT version number
HRRZS T1 ;isolate version
CAIL T1,703 ;If monitor is new
POPJ P, ;We're just fine
HRLI T2,'NML' ;Else, create the program name to run
MOVSI T1,'SYS' ;from SYS
SETZB T3,T4 ;Don't need extension or PPN
DMOVEM T3,T4+1 ;Or any other trash
MOVEI 0,T1
RUN 0,
HALT .
HALT .
SUBTTL DETACH
; Routine - DETACH
;
; Function - This routine will detach the job if it is started on the Force
; line.
;
; Arguments - none.
;
; Value - none.
;
ENTRY DETACH
DETACH: SETZM .JBSA ; NML is not (may NEVER be!) restartable
PUSH P,T1 ; Save an AC
PUSH P,T2 ; Save another AC
MOVEI T1,RENTER ; Get the REENTER address for crashes
MOVEM T1,.JBREN ; Install it
MOVE T1,[%CNFLN] ; Get the number of the FRCLIN
GETTAB T1, ; Get it
JRST GOVIRT ; Return, restoring T1
SETO T2, ; Prepare to
TRMNO. T2, ; get the number of this tty
JRST GOVIRT ; Probably detached already
SUBI T2,.UXTRM ; Turn the udx into a tty number
CAME T1,T2 ; Are we on the FRCLIN???
JRST GOVIRT ; No, don't detach us
HRLZI T1,-1 ; Get a -1 as the tty number
ATTACH T1, ; Detach us
JFCL ; Sigh...
; Here when we want to go virtual
GOVIRT: MOVE T2,[.STTVM,,^D500] ; Set virtual timer trap interval
SETUUO T2, ; Set it
JFCL ; ???
SUBTTL See if monitor has DECnet. Complain and log out if not
MOVE T1,[%CNST2] ; Get the DECnet feature test bit
GETTAB T1, ; Load the AC
SETZ T1, ; ?!?
TLNE T1,(ST%D36) ; Does the monitor have DECnet???
JRST T2POPJ ; Yes, all's fine
PUSH P,[[ASCIZ |?
?NML - Monitor does not have DECnet.|]]
PUSHJ P,OTSTR ; Print out the string
PUSHJ P,CHKDET ; Are we detached?
JRST ATTXIT ; No, just exit
PUSH P,[[ASCIZ | NML is logging out.
|]]
PUSHJ P,OTSTR ; Print out the string
PUSHJ P,OUTFIN ; Flush the buffer
MOVE T1,LGOARG ; And log us out
RUN T1,UU.PHY ; By running LOGOUT
EXIT 1, ; !?!
JRST .-1 ; Not really continuable
ATTXIT: PUSH P,[[ASCIZ |
|]]
PUSHJ P,OTSTR ; Print a <CRLF> on OPR
PUSHJ P,OUTFIN ; Flush the buffer
EXIT 1, ; And exit peacefully
JRST .-1 ; Not really continuable
T2POPJ: POP P,T2 ; Restore T2
TPOPJ: POP P,T1 ; " T1
.POPJ: POPJ P,
CHKDET: SETO T1, ; Set up for TRMNO. of my tty
TRMNO. T1, ; Are we detached?
AOS (P) ; Yes, give a skip
POPJ P, ; No, just return
CHKATT: SETO T1, ; Set up for TRMNO. of my TTY
TRMNO. T1, ; Are we detached?
POPJ P, ; Yes, no skip
AOS (P) ; We are attached, give a skip
POPJ P,
LGOARG: EXP .+1 ; AC for RUN uuo
SIXBIT |SYS|
SIXBIT |LOGOUT|
SIXBIT |EXE|
EXP 0
EXP 0
EXP 0
SUBTTL NMLDIE Stopcode processing for NML
; NMLDIE is where all stopcode processing ends up in NML. It will save
; all AC's, .JBOPC, and then save itself for crash analysis. The file names
; are all unique, and have the form NMLnnn, where nnn is the first number
; that makes NMLnnn a unique filename. A call to NMLDIE never returns.
;
; NML will only save itself if the logical name DUMP: is defined. The name
; should just contain the device and path of where to dump. Ie: a command
; of the form ".PATH DUMP:=DSKB:[12,3456,SFD1,SFDn]" will make NML save
; itself in the specified area under the names described above. In addition
; to this, if the logical name RUN: is defined, NML will run the program
; specified by RUN: if it can be found. A command of the form
; ".PATH RUN:/OVERRIDE=SYS:NML.EXE" will define RUN: correctly. Note that
; the filename must be specified, and that PT.OVR (/OVERRIDE) must also be
; on.
;
;
; Call: PUSHJ P,NMLDIE ; No arguments
; <Never returns>
;
; Here on a REENTER command
RENTER: PUSHJ P,NMLDIE ; So we can tell where we came from
; Here on any trap type errors
NMLTRP::
NMLDIE:: ; Here from main program, when fatal error detected
SKIPN .JBREN ; Have we been here before?
HALT . ; Recursion in error handler
SETZM .JBREN ; Can only do this once
EXCH 0,CRSHAC ; Save 0, get BLT AC
BLT 0,CRSHAC+17 ; Save all the AC's
MOVE T1,.JBOPC ; Get the old PC
MOVEM T1,CRSPC ; Save that too
HRRZ T1,.JBDDT ; Get start addr of DDT
JUMPN T1,(T1) ; Jump if it exists
SETZ P1, ; Indicate we should run new copy
SAVLOP: MOVE T1,SAVFLP ; Get ac for FILOP.
FILOP. T1, ; Does the file exist?
JRST CHKERR ; No, go check for errors
MOVE T1,LKEBLK+.RBNAM; Get name
AOJ T1, ; Increment the name
TRZE T1, 000010 ; Did field overflow?
ADDI T1,000100 ; Yes, increment next digit
TRZE T1, 001000 ; Did that field overflow??
ADDI T1,010000 ; Yes, increment that field
TRNE T1, 100000 ; Did the third digit overflow???
JRST EXTERR ; Yes, there sure are a lot of dumps out there
MOVEM T1,LKEBLK+.RBNAM; Put new name back
JRST SAVLOP ; And try again
CHKERR: CAIE T1,ERFNF% ; File Not Found?
JRST FLPERR ; Dunno, we got a strange error
MOVE T1,LKEBLK+.RBNAM ; Get name
MOVEM T1,SAVARG+1 ; Put it in SAVE. uuo arg block
MOVEI T1,SAVARG ; Get AC for SAVE. uuo
SAVE. T1, ; Save ourselves
HALT . ; Stop now, don't make it worse
MOVEI T2,SAVMSG ; Tell user we saved gracefully
SAVTYP: MOVE P,TMPSTK ; Get the stack back
PUSH P,T2 ; Put addr of text on stack
PUSHJ P,OTSTR ; Type it out
PUSHJ P,OUTFIN ; Flush the buffer
SKIPN P1 ; Should we run a new copy??
JRST RUNNEW ; Yes, go to it
EXIT 1, ; No, die gracefully
JRST .-1 ; Hardly restartable at this point
RUNNEW: SETO P1, ; Indicate we should give up in case of error
SETZB T1,T3 ; Clear I/O status and buffer pointers
MOVE T2,RUNARG+0 ; Get device name into OPEN block
OPEN T1 ; Open the device
JRST RUNERR
SETZ T2, ; Clear name
LOOKUP T1 ; Lookup the program
JRST RUNERR
MOVEI T1,RUNARG ; Set up AC for RUN uuo
RUN T1, ; Try runnung the program
HALT . ; We'll probably never get here, but...
HALT . ; We should NEVER get here!
RUNARG: SIXBIT |RUN|
SIXBIT |FOO|
EXP 0
EXP 0
EXP 0
EXP 0
EXP 0
SAVERR: ASCIZ |?
?NML - SAVE. uuo failed.
|
SAVMSG: ASCIZ |
NML saved on DSKB:NMLnnn.EXE[10,5665]
.R NML
|
BADERR: ASCIZ |?
?NML - Bad FILOP. error while trying to dump program
|
EXTDIE: ASCIZ |?
?NML - Can't save NML, too many crashes saved!
|
DIEMSG: ASCIZ |?
?NML - NML stopping program
|
FLPERR: SETO P1, ; Prevent running of new copy
CAIN T1,ERNSD% ; No such device???
RUNERR: SKIPA T2,[DIEMSG] ; Get death message
MOVEI T2,BADERR ; Get addr of message
JRST SAVTYP
EXTERR: SETO P1, ; Prevent running of new copy
MOVEI T2,EXTDIE ; Get addr of message
JRST SAVTYP
SUBTTL SS%SWITCH
; Routine - SS%SWITCH
;
; Function - This routine is called with the address of two task
; blocks. One is the "current" task, the other is for
; the "future" task. When this routine completes a
; context switch between the two tasks will have been
; done.
;
; Parameters -
;
; -1(P) Future task block address
; CURTSK/ Address of current task's task block
ENTRY SS%SWITCH
INTERN CURTSK, PRVTSK
RELOC ; Put this in low seg
CURTSK: BLOCK 1 ; Current task block address
PRVTSK: BLOCK 1 ; Previous task block address
RELOC ; Back in the high seg
SS%SWITCH:
EXCH T1,CURTSK ; Save register and get task blk addr
MOVEM T1,PRVTSK ; Save as the previous task
JUMPE T1,SSS.1 ; If no task ... just run new one
MOVEM T0,TB.CTX##+T0(T1) ; Save register 0 in context block
MOVE T0,CURTSK ; Get contents of register 1
MOVEM T0,TB.CTX##+T1(T1) ; Save register 1 in context block
MOVEI T0,TB.CTX##+P(T1) ; Calculate end of context block
ADD T1,[T2,,TB.CTX##+T2] ; Start of registers to BLT
BLT T1,@T0 ; Copy into context block
SSS.1: HRLZ T0,-1(P) ; Get new task block address
HLRZM T0,CURTSK ; Save current task block address
ADD T0,[TB.CTX##+T1,,T1] ; Offset to saved registers
BLT T0,P ; Copy back registers
MOVE T0,CURTSK ; Get current task block address
ADDI T0,TB.CTX##+T0 ; Offset to register 0
MOVE T0,@T0 ; Get register 0
POPJ P, ; Return to new task
SUBTTL SS%TINIT
; Routine - SS%TINIT
;
; Function - This routine sets up a task block for running it
; the first time. It does not start the task, only
; initializes the task block stack.
;
; Parameters -
;
; -1(P) Size of task's stack
; -2(P) Task block to initialize
ENTRY SS%TINIT
SS%TINIT:
MOVE T1,-2(P) ; Get address of task block
MOVEI T2,TB.STK##(T1) ; Copy it for a stack pointer
MOVN T3,-1(P) ; Get length of stack
HRL T2,T3 ; Make initial stack pointer
PUSH T2,[US%FINI##] ; Put task exit routine onto stack
HRRZ T3,TB.STR##(T1) ; Get starting address
PUSH T2,T3 ; Put starting address onto stack
MOVEM T2,TB.CTX##+P(T1) ; Set initial stack pointer for task
POPJ P, ; Return
SUBTTL SS%MESSAGE
; Routine - SS%MESSAGE
;
; Function - This routine outputs a message to the operator
; or console.
;
; Parameters -
;
; -1(P) Byte pointer to error message string
ENTRY SS%MESSAGE
ENTRY SS%CMESSAGE
ENTRY SS%CLMESSAGE
; Here to simulate an outstr
OTSTR: MOVEI T1,440700 ; Get magic num
HRLM T1,-1(P) ; Install it in the pointer
SS%CLMESSAGE:
PUSHJ P,NOINT ; Turn off interrupts for entire string
SS%CL2: ILDB T1,-1(P) ; Get byte
JUMPE T1,YESINT ; Return if no more
PUSHJ P,OUTC ; Output the character
JRST SS%CL2 ; And keep going
SS%CMESSAGE:
PUSHJ P,NOINT ; Turn off interrupts for a sec
PUSH P,[[BYTE (7)15,12]] ; Start message on a new line
PUSHJ P,OTSTR ; Simulate an outstr
ADJSP P,-1 ; Fix the stack
SETZ T4, ; Output all the alignment spaces
PJRST SS%MS2 ; Go print message
SS%MESSAGE:
PUSHJ P,NOINT ; Turn off interrupts
JRST SS%MS4 ;$
PUSH P,[[ASCIZ |%% NML - |]] ; Get prefix
PUSHJ P,OTSTR ; Output it
ADJSP P,-1 ; Fix the stack
SKIPE ATINTL## ; Are we at interrupt level???
JRST [PUSH P,[[ASCIZ |[(Interrupt)]:|]] ; Yes, use this one
PUSHJ P,OTSTR ; Simulate an outstr
ADJSP P,-1 ; Fix the stack
MOVEI T4,^d15 ; Get spacing factor
JRST SS%MS2] ; And continue on happily
SKIPN T2,CURTSK ; Get address of current task block
JRST [PUSH P,[[ASCIZ |[(none)]:|]]
PUSHJ P,OTSTR ; Simulate an outstr
ADJSP P,-1 ; Fix the stack
MOVEI T4,^d10
JRST SS%MS2]
PUSH P,[[ASCIZ |[|]] ; Start task name output
PUSHJ P,OTSTR ; Simulate an outstr
ADJSP P,-1 ; Fix the stack
MOVEI T4,^d16 ; Get the maximum number of chars
MOVEI T2,TB.NAM##(T2) ; Point to name of task
HRLI T2,440700
SS%MS1: ILDB T1,T2 ; Get next character in name
SKIPN T1 ; Check for null character
JRST SS%MS3 ; Null, quit now
PUSHJ P,OUTC ; Output the character
SOJG T4,SS%MS1 ; .. increment count and loop
SS%MS3:
MOVEI T3,^D16 ; Get the starting number of chars
SUBM T3,T4 ; T4 now equals the length of the name
PUSH P,[[ASCIZ |]:|]] ; Terminate the task name
PUSHJ P,OTSTR ; Simulate an outstr
ADJSP P,-1 ; Fix the stack
ADDI T4,4 ; Add " [", "]:" to count
SS%MS2: MOVE T1,[POINT 7,[ASCIZ \ \]]
EXCH T1,T4
ADJBP T1,T4
PUSH P,T1 ; Save byte pointer
PUSHJ P,SS%CLMESSAGE ; Output alignment spaces
ADJSP P,-1 ; .. restore stack
SS%MS4: PUSH P,-1(P) ; Do a silly thing
PUSHJ P,SS%CLMESSAGE ; Go output supplied message
ADJSP P,-1 ; Fix the stack
PUSH P,[[BYTE (7)15,12]] ; Finish off message with a <CRLF>
PUSHJ P,OTSTR ; Simulate an outstr
ADJSP P,-1 ; Fix the stack
PUSHJ P,OUTFIN ; and flush out the buffer
PJRST YESINT ; and re-enable interrupts
NMU$FATAL==:SS%TFATAL
SS%TFATAL::
PUSH P,[[ASCIZ |? Fatal error - |]]
PUSHJ P,OTSTR ; Simulate an outstr
ADJSP P,-1 ; Fix the stack
PUSH P,-1(P)
PUSHJ P,SS%MESSAGE
PUSHJ P,OUTFIN ; And flush the buffer
EXIT 1, ; Stop execution
JRST .-1
SUBTTL OUTC Output character buffering and lowest level tty I/O
; OUTC - Output the character in T1
; OUTFIN - Flush out the remaining buffer
OUTS: PUSHJ P,OUTFIN ; Call the string putter outter
OUTC: SOSGE OUTCNT ; Any room left?
JRST OUTS ; Nope, dump out the buffer
IDPB T1,OUTPTR ; Yes, install the character
POPJ P, ; And return happily
OUTFIN: PUSH P,T1 ; Save T1
SETZ T1, ; Get a null
IDPB T1,OUTPTR ; Tie off the end of the buffer
SETO T1, ; We want to know about this jobs'
TRMNO. T1, ; controlling terminal
JRST TELOPR ; Detached -- tell OPR
OUTOUT: OUTSTR OUTBFR ; Output the buffer to the tty
FINOUT: MOVEI T1,^D80 ; Line buffer is 80 characters
MOVEM T1,OUTCNT ; Buffer is now officially empty
MOVE T1,[POINT 7,OUTBFR] ; Get the buffer pointer
MOVEM T1,OUTPTR ; Install it
POP P,T1 ; Restore the work AC
POPJ P, ; And return
TELOPR: MOVX T1,QF.PIP!QF.NBR!.QUWTO ; Get WTO function
MOVEM T1,QUEBLK+.QUFNC ; Save in QUEUE. arg block
SETZM QUEBLK+.QUNOD ; Set for central node
SETZM QUEBLK+.QURSP ; No response desired
MOVE T1,[^D80/5+1,,.QBMSG] ; Argument block is WTO message
MOVEM T1,QUEBLK+.QUARG ; ...
MOVEI T1,OUTBFR ; Argument is WTO buffer address
MOVEM T1,QUEBLK+.QUARV ; ...
MOVE T1,[^D80/5+1,,.QBTYP] ; Argument block is WTO message type
MOVEM T1,QUEBLK+.QUARG+2 ; ...
MOVEI T1,[ASCIZ |Message from NML|]
MOVEM T1,QUEBLK+.QUARV+2 ; ...
MOVE T1,[7,,QUEBLK] ; Get QUEUE. argument pointer
QUEUE. T1, ; Send message to OPR
SKIPA ; Failed, use TRMOP.
JRST FINOUT ; Success, go reset the buffer
MOVSI T1,'OPR' ; Get the device name
IONDX. T1, ; Get it's UDX
JRST OUTOUT ; Well, what can I do!
MOVEM T1,TRMBLK+1 ; Install the udx
MOVEI T1,[ASCIZ |-- Message from NML --
|]
MOVEM T1,TRMBLK+2 ; Output header string first
MOVE T1,[XWD 3,TRMBLK] ; Set up for the TRMOP.
TRMOP. T1, ; Output to OPR
JFCL ; Ignore error
MOVEI T1,OUTBFR ; Get address of message
MOVEM T1,TRMBLK+2 ; Store in TRMOP. block
MOVE T1,[XWD 3,TRMBLK] ; Set up for the TRMOP.
TRMOP. T1, ; Output to OPR
JRST OUTOUT ; Might as well hang in TO
JRST FINOUT ; SUCCESS! Go clean up the buffer
SUBTTL NOINT Turn off interrupts in a recursive manner
NOINT: AOSE INTOFF ; Been here already???
POPJ P, ; Yes, don't bother
PUSH P,T1 ; Preserve this AC
MOVX T1,PS.FOF ; Function is PIOFF
PISYS. T1, ; Disable interrupts
JFCL ; Maybe no PSIs yet???
POP P,T1 ; Restore work ac
POPJ P,
YESINT: SOSL INTOFF ; Should we enable interrupts
POPJ P, ; No, not now
MOVX T1,PS.FON ; Function is PION
PISYS. T1, ; Enable interrupts
JFCL ; Who cares
POPJ P, ; Return
RELOC ; Low seg stuff
OUTCNT: ^D80 ; Lotsa room to begin with
OUTPTR: POINT 7,OUTBFR ; Output buffer pointer
OUTBFR: BLOCK ^D80/5+1 ; The buffer itself
QUEBLK: BLOCK 7 ; QUEUE. arg block for WTO functions
TRMBLK: .TOOUS ; Output asciz string
0 ; No udx yet
OUTBFR ; Point to the buffer
INTOFF: -1 ; NOINT interlock
CRSHAC: XWD 1,.+1 ; AC for BLT to save context
BLOCK 17 ; Place to save AC's on a reenter
CRSPC: BLOCK 1 ; Death PC
TMPSTK: IOWD TMPLEN,.+1 ; Temporary PDL for death processing
BLOCK 10 ; Doesn't need to be very long
TMPLEN==.-TMPSTK
SAVFLP: XWD FLPLEN,.+1 ; AC for FILOP. for save of dead NML
XWD 0,.FORED ; Channel 0, Lookup a file
Z ; Don't care about I/O mode
SIXBIT |DUMP| ; Device
XWD 0,0 ; No I/O, no buffer headers
XWD 0,0 ; Don't allocate any buffers
XWD 0,LKEBLK ; Point to LOOKUP/ENTER block
FLPLEN==.-SAVFLP-1
LKEBLK: EXP 3 ; Length of this block
EXP 0 ; Default PPN from device
SIXBIT |NML000| ; Filename
XWD 'EXE',0 ; Extension,,path block
SAVARG: SIXBIT |DUMP|
SIXBIT |NML000|
SIXBIT |EXE|
EXP 0
EXP 0
EXP 0
EXP 0
SUBTTL Literals
XLIST ; Suppress uninteresting stuff
RELOC ; Back into the high seg
LIT ; Put the literals here
LIST ; Enable listing again
END