;TITLE NTMAN - Network Management Interface for DECnet-36 ;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED ;OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ;COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION 1976, 1986. ;ALL RIGHTS RESERVED. SUBTTL Jim Halpin, Gunnar Lindell, & Tarl Neustaedter SEARCH D36PAR,MACSYM SALL IFN FTOPS20,< SEARCH PROLOG TTITLE NTMAN,,< - Network Management interface for DECnet-36> > IFN FTOPS10,< SEARCH F,S TITLE NTMAN - Network Management interface for DECnet-36 .CPYRT<1976,1986> $RELOC >;END IFN FTOPS10 D36SYM ;SET UP D36 SPECIFIC PARAMETERS ;Declare all global entry points to NTMAN ENTRY NTMAN ;TO FORCE LINK TO LOAD WITH REST OF DECNET INTERN .NTMAN ; = NTMAN. JSYS/UUO entry point INTERN NMXEVT ;Event logger INTERN PRSCOU ;Hook for NSP event "Database reused" IFN FTOPS20 < INTERN EVRKIL ;Kill the event reader INTERN NMLEVT ;Check if event reader should get PSI > SUBTTL Table of Contents ; Table of Contents for NTMAN ; ; ; Section Page ; 1. Table of Contents. . . . . . . . . . . . . . . . . . . 2 ; 2. Data structures ; 2.1. Value definitions . . . . . . . . . . . . . . 3 ; 2.2. BEGSTR NT . . . . . . . . . . . . . . . . . . 4 ; 2.3. Byte pointers into NSP node block . . . . . . 5 ; 2.4. Parameter and counter definitions . . . . . . 6 ; 2.5. Event and logging definitions . . . . . . . . 12 ; 3. NTMAN ; 3.1. Entry . . . . . . . . . . . . . . . . . . . . 13 ; 3.2. Get pertinent data from user's data block . . 14 ; 3.3. Dispatch to functions . . . . . . . . . . . . 15 ; 4. Functions ; 4.1. .NTMAP - Map node name/number . . . . . . . . 16 ; 4.2. .NTREX - Return local node number . . . . . . 17 ; 4.3. .NTSET,.NTCLR - Parse and process a parameter 18 ; 4.4. .NTZRO,.NTSZC - Zero counters . . . . . . . . 19 ; 4.5. .NTSHO ; 4.5.1. Select parameters to return. . . . . 20 ; 4.5.2. Return parameters to user. . . . . . 21 ; 4.6. .NTRET ; 4.6.1. List node names. . . . . . . . . . . 22 ; 4.6.2. List circuit and line names. . . . . 23 ; 5. Entities ; 5.1. Convert entity names to entity ids. . . . . . 24 ; 5.2. Circuit ID to name conversion . . . . . . . . 25 ; 5.3. Convert name to Circuit-ID. . . . . . . . . . 26 ; 6. Layers ; 6.1. Main interface to layer levels. . . . . . . . 27 ; 6.2. Read/set NSP node blocks. . . . . . . . . . . 28 ; 6.3. Read/set RTR circuit blocks . . . . . . . . . 29 ; 6.4. Read/set node state . . . . . . . . . . . . . 30 ; 6.5. Read/set executor node information. . . . . . 31 ; 6.6. Read/set RTR node information . . . . . . . . 32 ; 6.7. Find circuit which points to a node . . . . . 33 ; 6.8. Set/clear node names. . . . . . . . . . . . . 34 ; 6.9. Create/Destroy loopback nodes . . . . . . . . 35 ; 6.10. Call the data link layer. . . . . . . . . . . 36 ; 7. Events ; 7.1. Interface layer / NMX (NMXEVT). . . . . . . . 37 ; 7.2. NMXEVT ; 7.2.1. EVGEC (Get EC block) . . . . . . . . 38 ; 7.2.2. EVREC (Release Ec block) . . . . . . 39 ; 7.2.3. EVFIL (Filter an event). . . . . . . 40 ; 7.2.4. EVLOG (Log an event) . . . . . . . . 41 ; 7.2.5. EVSIG (Log a signal) . . . . . . . . 45 ; 7.3. .NTTEV function (Test event logger) . . . . . 46 ; 7.4. .NTSLM function (Set global logging mask) . . 47 ; 7.5. .NTPSI function (Set event PSI channel) . . . 48 ; 7.6. .NTEVQ function (Pass queued event to user) . 49 ; 8. User strings ; 8.1. Write parameter with nice . . . . . . . . . . 51 ; 8.2. Write coded data. . . . . . . . . . . . . . . 52 ; 8.3. Write ascii image data. . . . . . . . . . . . 53 ; 8.4. Write numeric data. . . . . . . . . . . . . . 54 ; 8.5. Read a number from user . . . . . . . . . . . 55 ; 8.6. Read and write milliseconds . . . . . . . . . 56 ; 8.7. Copy STRINGID from user to exec . . . . . . . 57 ; 8.8. Copy STRINGID from exec to user . . . . . . . 58 ; 8.9. Get and put user byte routines. . . . . . . . 59 ; 8.10. Get and put single bytes into data strings. . 60 ; 9. Miscellaneous ; 9.1. Error returns . . . . . . . . . . . . . . . . 61 ; 9.2. Name/number conversion. . . . . . . . . . . . 62 ; 10. Data base ; 10.1. Find an NSP node block. . . . . . . . . . . . 63 ; 10.2. Find an existing NSP node block . . . . . . . 64 SUBTTL Data structures -- Value definitions ;AC definitions TM=FREE0 ;A WORK AC. PRESERVED NT=FREE1 ;POINTS TO THE TABLE FORMAT BLOCK ;Network management non-error code XP NESUC%,1 ;Function codes .NTSLM==-4 ;Set global logging mask (TOPS-20 only) .NTPSI==-3 ;SET PSI MASK (TOPS20 ONLY) .NTMAP==-2 ;Map Node name/Node number .NTREX==-1 ;Return local node ID .NTSET==0 ;SET PARAMETER .NTCLR==1 ;CLEAR PARAMETER .NTZRO==2 ;ZERO COUNTERS .NTSHO==3 ;SHOW SELECTED ITEMS .NTSZC==4 ;SHOW AND ZERO COUNTERS .NTRET==5 ;RETURN LIST OF ITEMS .NTEVQ==6 ;REMOVE AN ITEM FROM THE EVENT QUEUE .NTSUM==0 ;SUMMARY ;(FOR .NTSHO) .NTSTA==1 ;STATUS .NTCHA==2 ;CHARACTERISTICS .NTCOU==3 ;COUNTERS ;Skip 4 to avoid possible confusion with EVENTS .NTCST==5 ;CIRCUIT STATE ;Offsets to important locations in block .NTQUA==5 ;BYTE POINTER TO FUNCTION QUALIFER .NTSEL==4 ;SELECTION CRITERIA FOR FUNCTION .NTQUA==5 ;QUALIFIER .NTBPT==6 ;BYTE POINTER TO DATA STRING .NTBYT==7 ;BYTE COUNT FOR DATA STRING .NTERR==10 ;RETURN CODE, OR ERROR CODE ;Some Maximum Length Constants MXNNLN==6 ;Maximum Node Name Length MXHILN==6 ;Maximum Hexidecimal Image string Length ;Constants for Memory allocations FHIBLK==4 ;Hexidecimal Image buffer COUBLK==^D100 ;Counter Block, should have plenty of ;extra room, just incase some wierd layer ;invents some newer counters. CIRBLK==^D100 ;For RETURN LIST OF ENTITY IDS function LPNBLK==^D32 ;For return list of LOOP Nodes NDBLEN==^D1024 ;For return of Home Area Nodes ;Some constants for NICE Data Type Fields NT.CNM==200 ;Coded Non-Multiple (OR'ed into byte length) NT.CM1==301 ;Coded Multiple, 1 fields long NT.CM2==302 ;Coded multiple, 2 fields long NT.CM3==303 ;Coded multiple, 3 fields long NT.DU1==1 ;Decimal, Unsigned, 1 byte long NT.DU2==2 ;Decimal, Unsigned, 2 bytes long NT.AI==100 ;ASCII Image field NT.HI==40 ;HEXIDECIMAL Image field ;Needed Parameter Numbers NODSTA==0 ;Node State Parameter number value ;MACRO TO GIVE AN ERROR RETURN. THIS IS USED SIMPLY TO HIGHLIGHT THE FACT ;OF AN ERROR RETURN, AND DOES NOT PRECLUDE OTHER WAYS OF REACHING THE ROUTINES ;WHICH SET AN ERROR CODE. A JSP IS USED TO FACILITATE DEBUGGING. DEFINE XERRRET(ROUTINE), ; Jump to error routine ; in Extended Section DEFINE ERRRET(ROUTINE), XSWAPCD ;Most of NTMAN is swappable ($HIGH on TOPS-10) EXTERN DNGWDZ,DNGWZP,DNGWDS,DNFWDS,NMXTIM,NMXPRV ;D36COM EXTERN IBBLK,D36IFG EXTERN TIMBAS,DNGTIM ;D36COM EXTERN RTRMXN EXTERN RTN,RSKP,CHKBPT,KONNAM IFN FTOPS10, ;NMX Standard Interface Routines EXTERN SCLNMX ;Session Control Layer EXTERN ECLNMX ;End Communication Layer EXTERN RTRNMX ;Routing layer EXTERN DNDNMX ;Data Link Layer SUBTTL Data structures -- BEGSTR NT ;Table to find and validate a call parameter or counter. BEGSTR NT FIELD TYP,4 ;DATA TYPE (ASCII, HEX,...) XP NT.FC,1 ;CODED FORMAT XP NT.FCM,2 ;CODED MULTIPLE (THIS MEANS SPECIAL CASING) XP NT.FAI,3 ;ASCII IMAGE (8-BIT) XP NT.FDU,4 ;DECIMAL, UNSIGNED. CANNOT BE ZERO. XP NT.FDS,5 ;DECIMAL, SIGNED XP NT.FH,6 ;HEX INTEGER. XP NT.FHI,7 ;HEX, IMAGE. XP NT.FOC,^D8 ;OCTAL. ;ABOVE ARE DATA TYPES AS DESCRIBED IN NM SPEC ; V3.0 PAGE 162. ;BELOW ARE DATA TYPES USED INTERNALLY ONLY TO ; THIS MODULE. ; THESE SHOULD BE SHIFTED DOWN IF NM SPECIFIES ; MORE DATA TYPES XP NT.FDM,^D9 ;INTERNAL DATA TYPE ONLY. DECIMAL,MILLISECONDS. ; THIS GETS OUTPUT AS NT.FDU (SEE NMXWNM) XP NT.FVN,^D10 ;INTERNAL DATA TYPE ONLY. VERSION NUMBER. ; THIS GETS OUTPUT AS NT.FCM (DU-1,DU-1,DU-1) XP NT.FNE,^D11 ;INTERNAL DATA TYPE ONLY. NODE ENTITY ID. ; THIS GETS OUTPUT AS NT.FCM (DU-2,AI-6) XP NT.FNN,^D12 ;INTERNAL DATA TYPE ONLY. ASCII NODE NAME ; THIS GET OUTPUT AS NT.FAI (AI-6) XP NT.FCN,^D13 ;INTERNAL DATA TYPE ONLY. ASCII CIRCUIT NAME ; THIS GET OUTPUT AS NT.FAI (AI-16) FIELD LEN,5 ;LENGTH FIELD ROU,6 ;INDEX TO ROUTINE TO CALL FIELD DEV,6 ;DEVICE APPLICABILITY BIT D.R ;DMR-11 BIT D.N ;Ethernet (KLNI) BIT D.C ;Computer Interconnect (KLPI) BIT D.P ;DDP BIT D.K ;KDP BIT D.D ;DTE-20 (UGH) FIELD QUA,15 ;Qualifier Parameter Number NXTWRD ;FORCE NEXT WORD ALIGNMENT. FIELD APL,4 ;APPLICABILITY RESTRICTIONS BIT A.E ;EXECUTOR BIT A.L ;LOOP NODES. BIT A.R ;REMOTE NODES. BIT A.H ;HOME AREA NODES ONLY. FIELD INF,6 ;INFORMATION TYPE BIT I.C ;CHARACTERISTICS (LISTED IN SPEC AS 'C') BIT I.S ;STATUS (LISTED IN SPEC AS 'S') BIT I.% ;SUMMARY (LISTED IN SPEC AS '*') BIT I.K ;Circuit State. BIT I.Q ;This parameter is Qualified BIT I.N ;NONE. NOOP BIT, NOT NECESSARY FIELD SET,2 ;SETTABILITY RESTRICTIONS XP NTS.,0 ;0 MEANS READ AND WRITE XP NTS.R,1 ;READ ONLY PARAMETER. XP NTS.W,2 ;WRITE ONLY PARAMETER. FIELD BUF,1 ;Buffer Field XP NTB.,0 ;Parameter Value fits into a Word XP NTB.B,1 ;Parameter value too big, go allocate a buffer FIELD BSZ,10 ;Buffer size needed (if needed) FIELD SEQ,13 ;SEQUENCE OR TYPE OF FIELD ENDSTR IFN , ;TABLE LOGIC KNOWS LENGTH ;Bit positions for fields - will need for building tables. TYP$==POS(NTTYP) SEQ$==POS(NTSEQ) SET$==POS(NTSET) LEN$==POS(NTLEN) ROU$==POS(NTROU) QUA$==POS(NTQUA) BSZ$==POS(NTBSZ) BUF$==POS(NTBUF) SUBTTL -- NMX dispatch table. Routines are indexes into this table. NMXDSP: PHASE 0 ;Make labels be relative offsets. NMXMIN:! ;Lowest offset for NMXDSP SCL:! XCDSEC,,SCLNMX ;Session Control Layer ECL:! XCDSEC,,ECLNMX ;End Communication Layer RTL:! XCDSEC,,RTRNMX ;Routing Layer DLL:! XCDSEC,,DNDNMX ;Data Link Layer NMXMAX:! ;Maximum value plus one IFGE >, DEPHASE SUBTTL Data structures -- Parameter and counter definitions DEFINE NODE$P,< N(0 ,C,1 ,S%,ERH ,R,,RTL) ;State. N(10 ,HI,6 ,S,E ,R,,DLL,,B,4) ;Physical Address repeat 0,< IFN FTOPS10,< N(100 ,AI,31 ,C%,E ,,NMI,0) ;Identification >; End IFN FTOPS10 > ;end repeat 0 N(500 ,NN,6 ,N,R ,W,,SCL) ;Name of node (set only) N(501 ,CN,16 ,C%,L ,,,SCL) ;Circuit N(502 ,DU,2 ,N,E ,W,,SCL) ;Address (set only) N(510 ,DM,2 ,C,E ,,,SCL) ;Incoming timer N(511 ,DM,2 ,C,E ,,,SCL) ;Outgoing timer N(600 ,DU,2 ,S%,ER ,R,,ECL) ;Active links. N(601 ,DM,2 ,S%,R ,R,,ECL) ;Delay N(700 ,VN,3 ,C,E ,R,,ECL) ;NSP version N(710 ,DU,2 ,C,E ,,,ECL) ;Maximum Links N(720 ,DU,1 ,C,E ,,,ECL) ;Delay factor. N(721 ,DU,1 ,C,E ,,,ECL) ;Delay weight. N(722 ,DU,2 ,C,E ,,,ECL) ;Inactivity timer. N(723 ,DU,2 ,C,E ,,,ECL) ;Retransmit factor. N(810 ,C,1 ,S,RH ,R,,RTL) ;Type N(820 ,DU,2 ,S,RH ,R,,RTL) ;Cost N(821 ,DU,1 ,S,RH ,R,,RTL) ;Hops N(822 ,CN,16 ,S%,R ,R,,RTL) ;circuit N(830 ,NE,2 ,S%,R ,R,,RTL) ;Next Node N(900 ,VN,3 ,C,E ,R,,RTL) ;Routing version N(901 ,C,1 ,C,E ,R,,RTL) ;Type N(910 ,DU,2 ,C,E ,,,RTL) ;Routing timer. N(912 ,DU,2 ,C,E ,,,RTL) ;Broadcast Routing Timer N(920 ,DU,2 ,C,E ,,,RTL) ;Maximum address. N(921 ,DU,2 ,C,E ,,,RTL) ;Maximum Circuits. N(922 ,DU,2 ,C,E ,,,RTL) ;Maximum cost. N(923 ,DU,1 ,C,E ,,,RTL) ;Maximum hops. N(924 ,DU,1 ,C,E ,,,RTL) ;Maximum visits. N(926 ,DU,2 ,C,E ,,,RTL) ;Maximum Broadcast Non-Routers N(927 ,DU,2 ,C,E ,,,RTL) ;Maximum Broadcast Routers N(930 ,DU,2 ,C,E ,,,RTL) ;Maximum Buffers N(931 ,DU,2 ,C,E ,R,,RTL) ;Buffer size. N(932 ,DU,2 ,C,E ,,,RTL) ;Segment Buffer Size > DEFINE LINE$P,< N(0 ,C,1 ,S%, ,,,DLL) ;State N(1105 ,DU,2 ,C, ,R,,DLL) ;Receive Buffers N(1110 ,C,1 ,C, ,R,,DLL) ;Controller REPEAT 0,< N(1111 ,C,1 ,C, ,R,,DLL) ;Duplex > ;END REPEAT 0 N(1112 ,C,1 ,C, ,R,,DLL) ;Protocol N(1160 ,HI,6 ,C, ,R,N,DLL,,B,4) ;Hardware Address N(2500 ,DU,2 ,C, ,R,,DLL) ;Receive block size > DEFINE CIRC$P,< N(0 ,C,1 ,K, ,,,RTL) ;State. N(400 ,NN,6 ,S%, ,R,,SCL) ;Loopback Name N(800 ,NE,2 ,%, ,R,,RTL,,B,1023) ;Adjacent node N(801 ,NE,2 ,S, ,R,N,RTL) ;Designated Router N(810 ,DU,2 ,SQ, ,R,,RTL,800) ;Block size N(900 ,DU,1 ,C, ,,,RTL) ;Cost. N(901 ,DU,1 ,C, ,,N,RTL) ;Maximum Routers N(902 ,DU,1 ,C, ,,N,RTL) ;Router Priority N(906 ,DU,2 ,C, ,,,RTL) ;Hello timer N(1112 ,C,1 ,C, ,,,DLL) ;Circuit Type N(907 ,DU,2 ,CQ, ,,,RTL,800) ;Listen timer > DEFINE XPAND(.RES,.PFX,.CHA),< .RES=0 IFB <.CHA>,<.RES=-1> IRPC .CHA,,<.RES=.RES!.PFX'.CHA>> > DEFINE .M(MASK),<1_WID(MASK)> ;Macro to create primary table entry DEFINE NTENT(.APL,.INF,.SET,.BFF,.SIZ,.SEQ),< IFB <.SIZ>, IFNB <.SIZ>, IFGE <^D'.SEQ-.M(NTSEQ)>, XPAND(APL,NTA.,.APL) XPAND(INF,NTI.,.INF) ! ! <B&NTSET>! <B&NTBUF>! <B&NTBSZ>! <<^D'.SEQ>B&NTSEQ> > ;Define rightmost positions of fields, for ddt NTNMSK==:<1B!1B!1B!1B!1B!1B> NSSMSK==:<1B!1B!1B!1B!1B> ;Example - NTN$3M NODEP+3$10r$o/ 100.,10.,4.,0.,0. ;displays fields NTAPL, NTINF, NTSET, NTSEQ . ;Macro to define secondary entry (Format) DEFINE STENT(.TYP,.LEN,.ROU,.DEV,.QUA),< XPAND(DEV,NTD.,.DEV) IFB <.QUA>, IFNB <.QUA>, IFGE <.ROU-NMXMAX>, IFGE <^D'.LEN-.M(NTLEN)>, <B&NTTYP>! <<^D'.LEN>B&NTLEN>! <<.ROU>B&NTROU>! ! <B&NTQUA> > ;Define all the REAL stuff now. DEFINE N(.SEQ,.TYP,.LEN,.INF,.APP,.SET,.DEV,.ROU,.QUA,.BFF,.SIZ),< STENT(.TYP,.LEN,.ROU,.DEV,.QUA) NTENT(.APP,.INF,.SET,.BFF,.SIZ,.SEQ) > DEFINE MAKTAB(.LAB,.STF),< XLIST .LAB: .STF .LAB'L==:.-.LAB LIST > MAKTAB(NODEP,NODE$P) MAKTAB(LINEP,LINE$P) MAKTAB(CIRCP,CIRC$P) ;Pointers to parameter data base. PRMP: XWD <-NODEPL/NT.LST>,NODEP ;NODE PARAMETERS XWD <-LINEPL/NT.LST>,LINEP ;LINE PARAMETERS Z ;LOGGING PARAMETERS XWD <-CIRCPL/NT.LST>,CIRCP ;CIRCUIT PARAMETERS Z ;MODULE - WE DON'T HAVE ANY Z ;EVENTS - CAN'T SET ANYTHING. SUBTTL Data structures -- Event and logging definitions RESVR ;Event queue variables NMXEVQ: BLOCK QH.LEN ;Event queue header NMXELO: BLOCK 1 ;Event queue contains a lost event ;Signal queue variables NMXSIQ: BLOCK QH.LEN ;Signal queue header ;Macros to define global filter table DEFINE $SFIL <> ;"Start filter table" DEFINE $FIL(A,B) < ;"Filter table entry" XWD A,B REPEAT , > DEFINE $NOFIL(A,B) < ;;"Off filter table entry" XWD A,B REPEAT , > DEFINE $EFIL ;"End filter table" ;Now generate filter table RESDT ;Initialized data NMXFIL: $SFIL $FIL(2,6) ;Event classes 2 through 6 known by monitor $NOFIL(^D96,^D96) ;LCG specific events - turned off IFN FTDEBUG < $FIL(^D480,^D480) ;Accept event class 480 while debugging > $EFIL ;Note: add more $FIL entries to declare more monitor event classes. ;The table will expand to ; ; NMXFIL: 2,,6 ; REPEAT 5,< 37777,,777777> ;All 32 event types within ; -1 ; a class in BLISS bit meaning ; -1 is an end flag SWAPCD SUBTTL NTMAN -- Entry ;Called from DISP2A in UUOCON ;Call ; M[T6]/ UUO itself (Used for storing values in the AC later) ; T1/ Contents of the AC at UUO time ; P/ Pointer to a stack in the current section ;Return ; RET error, .NTERR and AC contain error code ; SKPRET success. AC unchanged .NTMAN: NTMAN: IFN FTOPS20,< MCENT ;ENTER MONITOR CONTEXT UMOVE T1,1 ;GET ADDRESS OF BLOCK > SKIPL D36IFG ;Is DECNET initialized? IFN FTOPS20,< ITERR (NTMX3) ; -no, return error code > IFN FTOPS10,< RET ; Just give error return > ;end ifn ftops10 ;** Note ** ; If you change this TRVAR, you need to change the TRVAR in routine GENE32 ; in LLINKS as well. TRVAR <,> ;SET UP TRVAR ;** End note ** SETZM NMXVAR ;CLEAN FIRST WORD OF BLOCK HRRI T2,1+NMXVAR ;GET POINTER TO SECOND WORD IN BLOCK HRLI T2,NMXVAR ;POINT AT START OF BLOCK BLT T2,NX.LST-1+NMXVAR ;CLEAN UNTIL END OF BLOCK STOR T1,NXADR,+NMXVAR ;SAVE ADDRESS OF ARGUMENT BLOCK SETZM NFWBLK ;CLEAN FIRST WORD OF BLOCK HRRI T2,1+NFWBLK ;GET POINTER TO SECOND WORD IN BLOCK HRLI T2,NFWBLK ;POINT AT START OF BLOCK BLT T2,NF.LST-1+NFWBLK ;CLEAN UNTIL END OF BLOCK IFN FTOPS10,STOR T6,NXUUO,+NMXVAR ;** TOPS10 CALLS US WITH M/ UUO EXECUTED XCALL (XCDSEC,NMXPRV) ;MAKE SURE WE ARE PRIVED. IFN FTOPS10,< ;Tops-10 wants error in NTMAN argument block IFNSK. XERRRET NTEPRV ;NOPE, GIVE THE NO PRIVS RETURN ENDIF. > IFN FTOPS20,< ;While Tops-20 generates CAPX1 error ITERR (CAPX1) > CALL GETBLK ;GET STUFF FROM USER PARAMETER BLOCK ERRRET NTERXI ;DIDN'T MAKE IT. SOMETHING WRONG. IFN FTXMON,< XCALL (XCDSEC,NMXDIS) ;DISPATCH TO ROUTINES (IN NTMAN) > IFE FTXMON,< DNCALL (NMXDIS) > ERRRET NTERXI ;ERROR EXIT OF SOME KIND. CHECK. IFN FTDEBUG < TMNE NXERR,+NMXVAR ;MAKE SURE NO ERROR CODE HAS MADE IT'S WAY HERE BUG.(CHK,NTMSRF,NTMAN,SOFT,,,< Cause: There is an error code stored in field NXERR after a return from NTMAN with a skip return. Action: Put a non-skip return in the routine giving the error call. >,RTN) > LOAD T2,NXADR,+NMXVAR ;GET ADDRESS OF USER'S ARGUMENT BLOCK MOVX T1,NESUC% ;ERROR CODE INDICATING SUCCESS. UMOVEM T1,.NTERR(T2) ;PUT IN ERROR CODE SPOT OF ARGUMENT BLOCK UMOVE T3,.NTBYT(T2) ;GET ORIGINAL NUMBER OF BYTES HE ALLOWED US LOAD T1,NXDAT,+BP.BYT+NMXVAR ;GET NUMBER OF BYTES LEFT IN STRING SUB T3,T1 ;GET NUMBER OF BYTES WE ACTUALLY DEPOSITED TMNE NXWUS,+NMXVAR ;DID WE WRITE TO THE USER'S STRING? UMOVEM T3,.NTBYT(T2) ;TELL USER HOW MANY BYTES WE GAVE HIM IFN FTOPS20,MRETNG ;MAKE THE UUO DO A GOOD RETURN IFN FTOPS10,RETSKP NTERXI: OPSTR ,NXERR,+NMXVAR BUG.(CHK,NTMNEC,NTMAN,SOFT,,,< Cause: A routine has returned non-skip, but has not given an error code by calling NTExxx. A return to the top level found field NXERR zero. Action: Determine which routine is failing, and make the error return give an error code. >) IFN FTOPS10,< LOAD T6,NXUUO,+NMXVAR ;GET UUO BACK - NEED FOR STOTAC MCALL (RG,MCSEC0,STOTAC##) ;PUT ERROR CODE IN AC LOAD T1,NXERR,+NMXVAR ;GET ERROR CODE CAXN T1,NEADC% ;WAS THIS AN ADDRESS CHECK? RET ;YES, DON'T DO FURTHER DAMAGE. > ;END IFN FTOPS10 LOAD T2,NXADR,+NMXVAR ;GET ADDRESS OF USER BLOCK UMOVEM T1,.NTERR(T2) ;NOPE, SAFE TO GIVE HIM ERROR CODE SETZ T1, ;0 BYTES UMOVEM T1,.NTBYT(T2) ;TELL NML THAT WE DIDN'T GIVE HIM ANYTHING. IFN FTOPS20,ITERR (NTMX1) ;GENERIC NETWORK MANAGEMENT ERROR IFN FTOPS10,RET ;RETURN NON-SKIP, INDICATING UUO FAILED SUBTTL NTMAN -- Get pertinent data from user's data block ;Called from NMXDIS ;GETBLK - Copy pertinent fields from user's argument block to NX block ;;Call ; NX/ Pointer to NX block ;Returns ; Non skip on failure - Address check ; Skip return on success GETBLK: SAVEAC P1 ;SO WE CAN HOLD SOME STUFF LOAD T6,NXADR,+NMXVAR ;GETWRD UNDERSTANDS T6 AS ADDRESS. MCALL (RG,MSEC1,GETWRD) ;GET FIRST WORD OF BLOCK IFNSK. XERRRET NTEADC ;NO GO. CAN'T HAPPEN ENDIF. CAIGE T1,.NTERR ;MAKE SURE BLOCK INCLUDES .NTERR IFNSK. XERRRET NTEADC ;NOPE, ADDRESS CHECK. ENDIF. MCALL (RG,MSEC1,GETWR1) ;GET NEXT WORD IN BLOCK IFNSK. XERRRET NTEADC ;NOPE, ADDRESS CHECK. ENDIF. CAXL T1,.NTNOD ;RANGE CHECK THE ENTITY TYPE CAXLE T1,.NTARE IFNSK. XERRRET NTEINI ;NOPE, ADDRESS CHECK. ENDIF. STOR T1,NXENT,+NMXVAR ;SAVE AS ENTITY TYPE MCALL (RG,MSEC1,GETWR1) ;GET BYTE POINTER TO ENTITY ID IFNSK. XERRRET NTEADC ;NOPE, ADDRESS CHECK. ENDIF. MOVE P1,T6 ;SAVE POINTER TO ARG BLOCK FOR A WHILE MOVX T2,^D16 ;THIS COULD BE AS MUCH AS 16 BYTES MCALL (RG,MSEC1,CHKBPT##) ;ASK IF THIS IS A GOOD BYTE POINTER IFNSK. XERRRET NTEADC ;NOPE, ADDRESS CHECK. ENDIF. MOVE T6,P1 ;GET BACK POINTER TO OUR ARGUMENT LIST STOR T1,NXEID,+BP.BPT+NMXVAR ;SAVE RESOLVED BYTE POINTER MOVX T1,^D16 ;MAXIMUM LENGTH FOR AN ENTITY ID STOR T1,NXEID,+BP.BYT+NMXVAR ;SAVE MCALL (RG,MSEC1,GETWR1) ;GET FUNCTION TO BE PERFORMED IFNSK. XERRRET NTEADC ;NOPE, ADDRESS CHECK. ENDIF. IFN FTDEBUG < CAXL T1,.NTTEV > IFE FTDEBUG < CAXL T1,.NTSLM ;RANGE CHECK FUNCTION > CAXLE T1,.NTEVQ IFNSK. XERRRET NTEUFO ;BAD FUNCTION ENDIF. STOR T1,NXFNC,+NMXVAR ;SAVE AWAY. MCALL (RG,MSEC1,GETWR1) ;GET SELECTION CRITERIA IFNSK. XERRRET NTEADC ;NOPE, ADDRESS CHECK. ENDIF. STOR T1,NXSEL,+NMXVAR ;STASH AWAY MCALL (RG,MSEC1,GETWR1) ;GET FUNCTION QUALIFIER IFNSK. XERRRET NTEADC ;NOPE, ADDRESS CHECK. ENDIF. ;I DON'T KNOW WHAT TO DO WITH THIS. TOSS. MCALL (RG,MSEC1,GETWR1) ;GET BYTE POINTER TO THE USER BUFFER IFNSK. XERRRET NTEADC ;NOPE, ADDRESS CHECK. ENDIF. MOVE P1,T1 ;HANG ON TO BYTE POINTER FOR A WHILE MCALL (RG,MSEC1,GETWR1) ;GET BYTE COUNT OF STRING IFNSK. XERRRET NTEADC ;NOPE, ADDRESS CHECK. ENDIF. STOR T1,NXDAT,+BP.BYT+NMXVAR ;SAVE BYTE COUNT UMOVEM T1,(T6) ;TRY TO MOVE IT BACK. (MAKE SURE WRITABLE) IFN FTOPS10,ERJMP NTEADC ;DIDN'T WORK, MUST BE A HIGH SEGMENT. MOVE T2,T1 ;NUMBER OF BYTES WE WANT TO CHECK MOVE T1,P1 ;BYTE POINTER WE ARE GOING TO ASK ABOUT MOVE P1,T6 ;SAVE OUR ARGUMENT LIST POINTER MCALL (RG,MSEC1,CHKBPT##) ;ASK IF THIS BYTE POINTER IS ANY GOOD IFNSK. XERRRET NTEADC ;NOPE, ADDRESS CHECK. ENDIF. STOR T1,NXDAT,+BP.BPT+NMXVAR ;SAVE FOR GETBYT MOVE T6,P1 ;GET BACK POINTER TO THE USER ARG BLOCK MCALL (RG,MSEC1,GETWR1) ;MAKE SURE .NTERR IS IN CORE IFNSK. XERRRET NTEADC ;NOPE, ADDRESS CHECK. ENDIF. UMOVEM T1,(T6) ;TRY TO PUT IT BACK. IFN FTOPS10,ERJMP NTEADC ;DIDN'T WORK, MUST BE FIRST WORD IN HISEG RETSKP ;RETURN SUCCESS TO CALLER IFN FTOPS20,< ;GETWRD & GETWR1 - Get a word from user space ;Call ; T6/ address desired ;Return ; +2 always GETWR1: AOJ T6, ;POINT TO NEXT WORD GETWRD: UMOVE T1,(T6) ;GET WORD RETSKP ;AND RETURN > ;END IFN FTOPS20 SUBTTL NTMAN -- Dispatch to functions XSWAPCD ;Section 6 Swapable Code NMXDIS: LOAD P1,NXENT,+NMXVAR ;GET ENTITY TYPE LOAD T1,NXFNC,+NMXVAR ;GET FUNCTION CODE IFE FTDEBUG < MOVE T2,<-.NTSLM>+[ ;GET FLAG BITS FOR THIS FUNCTION > IFN FTDEBUG < MOVE T2,<-.NTTEV>+[ ;GET FLAG BITS FOR THIS FUNCTION NX%ECV ;.NTTEV (check entity) > NX%WRM ;.NTSLM (TOPS-20 only) NX%WRM ;.NTPSI (TOPS-20 ONLY) NX%WUS ;.NTMAP NX%WUS ;.NTREX NX%WRM!NX%ECV ;.NTSET NX%WRM!NX%ZMC!NX%ECV ;.NTCLR NX%WRM!NX%ZMC!NX%ECV ;.NTZRO NX%WUS!NX%ECV ;.NTSHO NX%WUS!NX%ZMC!NX%WRM!NX%ECV;.NTSZC NX%WUS ;.NTRET NX%WUS](T1) ;.NTDQE STOR T2,NXFLG,+NMXVAR ;SAVE FLAGS WE JUST GOT TXNN T2,NX%ECV ;SHOULD WE PARSE THE ENTITY? JRST NMXDI2 ;NO, SKIP OVER CALL ENTCVT ;CONVERT THE ENTITY TO AN ID RET ;error... LOAD T1,NXFNC,+NMXVAR ;GET FUNCTION CODE BACK AGAIN. NMXDI2: IFN FTDEBUG < CAXL T1,.NTTEV > IFE FTDEBUG < CAXL T1,.NTSLM ;RANGE CHECK FUNCTION > CAXLE T1,.NTEVQ ; CODE. BUG.(CHK,NTMFUR,NTMAN,SOFT,,,< Cause: While dispatching by function code, the function code is found to be out of range. Since the function code the user supplies is checked in GETBLK, this means that field NXFNC has been trashed in the meantime. >,NTEMPE) CAXL P1,.NTNOD ;RANGE CHECK ENTITY CAXLE P1,.NTARE ; TYPE. BUG.(CHK,NTMEOR,NTMAN,SOFT,,,< Cause: While double checking the entity ID before dispatching on it, the value was found to be illegal. Since the value the user supplies is checked at GETBLK, this means that field NXENT has been trashed. >,NTEMPE) IFN FTDEBUG < CALLRET @.+1-.NTTEV(T1) ;DISPATCH TO APPROPRIATE ROUTINE. > IFE FTDEBUG < CALLRET @.+1-.NTSLM(T1) ;DISPATCH TO APPROPRIATE ROUTINE. > IFN FTDEBUG < IFIW ;.NTTEV - Test function > IFIW ;.NTSLM - Set global logging mask IFIW ;.NTPSI - SET EVENT INTERRUPT (TOPS-20 ONLY) IFIW ;.NTMAP - MAP NODE NUMBERS AND NAMES IFIW ;.NTREX - RETURN ENTITY ID FOR EXECUTOR IFIW ;.NTSET - SET A PARAMETER IFIW ;.NTCLR - CLEAR A PARAMETER IFIW ;.NTZRO - ZERO COUNTERS IFIW ;.NTSHO - SHOW PARAMETERS/COUNTERS IFIW ;.NTSZC - SHOW AND ZERO COUNTERS IFIW @<-.NTNOD>+[ ;.NTRET - LIST ENTITIES IFIW ; .NTNOD - NODE IFIW ; .NTLIN - LINE IFIW ; .NTLOG - DOESN'T EXIST IFIW ; .NTCKT - CIRCUIT IFIW ; .NTMOD - Doesn't exist IFIW ](P1) ; .NTARE - Doesn't exist IFIW ;.NTEVQ - PASS A QUEUED EVENT TO USER SUBTTL Functions -- .NTMAP - Map node name/number ;Called from NMXDIS ;Extract parameter from input string, if a number return node name, ; if a name, return node number (Address, or ID). ;Call ; NC/ Pointer to block of data copied from user. NODMAP: SAVEAC P1 ;NEED ACS FOR BYTE ROUTINES CALL GET2BT ;GET NODE NUMBER RET STOR T1,NXNUM,+NMXVAR ;STORE ENTITY ID (MAYBE) CALL GETSTR ;COPY SOME BYTES RET JE NXVAL,+NMXVAR,NODMA2 ;IF NO NAME, HE GAVE US AN ADDR CALL NMXN2A ;CONVERT NAME IN NXVAL TO NUMBER RET ;Error return STOR T1,NXNUM,+NMXVAR ;STORE THE NODE ADDRESS AWAY. NODMA2: JE NXNUM,+NMXVAR,NTEPAM ;IF NO NODE ADDRESS YET, ILLEGAL. LOAD T1,NXADR,+NMXVAR ;GET USER'S ARG BLOCK ADDRESS S1XCT < UMOVE T1,.NTBPT(T1) ;GET BYTE POINTER AGAIN STOR T1,NXDAT,+BP.BPT+NMXVAR ;RESET EVERYTHING AGAIN LOAD T1,NXADR,+NMXVAR ;ARG BLOCK ADDRESS AGAIN ADDI T1,.NTBYT ;POINT TO BYTE COUNT UMOVE T1,(T1) ;GET BYTE COUNT FOR DATA STRING > STOR T1,NXDAT,+BP.BYT+NMXVAR ;STASH AWAY FOR PUTBYT LOAD T1,NXNUM,+NMXVAR ;GET NODE ADDRESS BACK CALL NMXA2N ;CONVERT NODE ADDRESS TO NODE NAME IFNSK. LOAD T1,NXERR,+NMXVAR ;Get the error code (If any.) CAXE T1,NF.URC ;Unrecognized Component? RET ;No, it is a real error, report it SETZRO NXVAL,+NMXVAR ;Otherwise, return #, without a name. SETZRO NXERR,+NMXVAR ;Get rid of the error code ENDIF. NODMA3: LOAD T1,NXNUM,+NMXVAR ;GET NODE NUMBER CALL PUT2BT ;PUT INTO DATA STRING RET ;error... XMOVEI P1,NX.VAL+NMXVAR ;POINTER TO STRINGID CONTAINING NODE NAME CALLRET PUTSTR ;COPY STRING FROM NXVAL TO USER DATA STRING SUBTTL Functions -- .NTREX - Return local node number ;Called from NMXDIS NODLOC: CALL LOCNID ;Get the Local Node Id RET CALL PUT2BT ;SEND TWO BYTES INTO THE OUTPUT STRING. RET ;error SETZ T1, ;NO NODE NAME (DON'T BOTHER) CALLRET PUTBYT ;STORE AWAY IN USER STRING ; Get the Local Node Id ; ;Return ; RET ;Error return from ROUTER ; RETSKP ;Local Node ID (Address) in T1 ; LOCNID: LOAD T1,IBADR,+IBBLK ;Get our node address RETSKP ;Success.... LOCARE: LOAD T1,IBADR,+IBBLK ;Get our node address ASH T1,-<^D10> ;Get just the area number RETSKP SUBTTL Functions -- .NTSET,.NTCLR - Parse and process a parameter ;Called from NMXDIS ;PRSPRM - Parse a parameter from the data string, and process ;CALL ; T1/ Function (From NXFNC) ;RETURN ; Non skip, on error, with code stored in NXERR ; Skip, no error, parameter has been processed PRSPRM: SAVEAC NT MOVE NT,PRMP(P1) ;GET AOBJN POINTER TO NMXTAB LOAD T1,NXENT,+NMXVAR ;Get the entity type STOR T1,NFETY,+NFWBLK ;Store it in the Argument Block MOVE T3,T1 ;Put Entity type into T3 for upcoming dispatch LOAD T1,NXNUM,+NMXVAR ;Get the Converted Entity Id STOR T1,NFEID,+NFWBLK ;And put it into the NFW Arg Block. JE NXDAT,+BP.BYT+NMXVAR,TABCLR ;IF NO PARAMETER, TRY CLEAR ALL CALL GET2BT ;GET DATA-ID FIELD. RET ;error STOR T1,NFPRM,+NFWBLK ;STORE SEQUENCE NUMBER ;Now search for sequence number in NMXTAB table. TABSRC: JUMPGE NT,NTEUPT ;IF END OF TABLE, NO SUCH PARAMETER LOAD T2,NTSEQ,(NT) ;GET AN ENTRY OUT OF THE TABLE. CAME T1,T2 ;IS THIS THE ENTRY WE ARE LOOKING FOR ? JRST [ADD NT,[1,,NT.LST] ;INCREMENT POINTER, DECREMENT COUNT JRST TABSRC] ;AND TRY AGAIN ;NT now points to table entry describing this parameter or counter. LOAD T1,NTSET,(NT) ;GET SETTABILITY RESTRICTIONS CAXN T1,NTS.R ;IS IT READ ONLY? ERRRET NTEOPF ;YEP - HE CAN'T BE WRITING THIS ONE LOAD T1,NXENT,+NMXVAR ;GET TYPE OF ENTITY CAXE T1,.NTNOD ;IS IT A NODE? JRST TABSR1 ;NO, APPLICABILITY DOESN'T APPLY LOAD T2,NXNTY,+NMXVAR ;GET TYPE OF NODE MOVE T2,[NTA.E ;BIT INIDICATING EXECUTOR NTA.R ; REMOTE NTA.L]-1(T2) ; LOOPBACK TDNN T2,NT.APL(NT) ;DOES THIS PARAMETER APPLY TO THIS NODE TYPE? ERRRET NTEPNA ;NO, PARAMETER NOT APPLICABLE JRST TABSR2 ;Skip over Line/Circuit Check TABSR1: TXNN T1,<.NTLIN&.NTCKT> ;Is it a LINE or a CIRCUIT? JRST TABSR2 ;No, don't bother checking Line type LOAD T2,NXLTY,+NMXVAR ;Get the Line type MOVE T2,[NTD.D ;Bit indicating DTE NTD.K ; KDP NTD.P ; DDP NTD.C ; CI NTD.N ; NI NTD.R]-1(T2) ; DMR TDNN T2,NT.DEV(NT) ;Does this Parameter apply to this Line Type? ERRRET NTEPNA ;Parameter Not Applicable TABSR2: JN NXZMC,+NMXVAR,TABSR3 ;IF ZEROING MONITOR CORE, DON'T GET VALUES LOAD T1,NTTYP,(NT) ;FIND OUT WHAT KIND OF DATA WE ARE READING CAXL T1,NT.FC ;IS IT LESSER THAN SIMPLE CODED? CAXLE T1,NT.FCN ;OR GREATER THAN CIRCUIT NAME TABSRE: BUG.(CHK,NTMBFP,NTMAN,SOFT,,,< Cause: In the process of reading a value from the user string, descriptor tables have returned an invalid format for this item. The AC "NT" points to the descriptor for this item, and field NTSEQ tells which item is being referred to. Action: Fix the entry for this item to contain a valid format type. >,NTEMPE) CALL <-NT.FC>+@[ ;DISPATCH ACCORDING TO FORMAT TYPE IFIW ;ORDINARY CODED. IFIW ;CODED MULTIPLE. ILLEGAL IFIW ;ASCII IMAGE. ILLEGAL IFIW ;DECIMAL UNSIGNED. IFIW ;DECIMAL SIGNED. IFIW ;HEX INTEGER. IFIW ;HEX IMAGE. STRING ID. IFIW ;OCTAL - READ AS DECIMAL UNSIGNED IFIW ;MILLISECONDS (REALLY DECIMAL UNSIGNED) IFIW ;VERSION NUMBER. ILLEGAL, READ-ONLY IFIW ;NODE ENTITY ID. ILLEGAL, READ-ONLY IFIW ;NODE NAME (IN ASCII IMAGE FORMAT) IFIW ](T1) ;CIRCUIT NAME. (IN ASCII IMAGE FORMAT) RET ;PROPAGATE ERROR MOVX T1,NF.SET ;Get the SET PARAMETER function code SKIPA ;Skip TABSR3: MOVX T1,NF.CLR ;Get the CLEAR PARAMETER function code XMOVEI T2,NFWBLK ;Put address of the Arg Block in T2 LOAD T3,NTROU,(NT) ;GET ROUTINE FOR THIS PARAMETER CALL NMXLAY ;HAVE THE LAYER DO THE REST. JRST NTEERR ;Go report the error JE NFBFF,+NFWBLK,RSKP ;If no buffer,we are finished LOAD T1,NFBUF,+NFWBLK ;Get the buffer address CALL DNFWDS ;Deallocate it SETZRO NFBUF,+NFWBLK ;Get rid of the address SETZRO NFBFF,+NFWBLK ;and the flag RETSKP ;FINISHED ;Logic for CLEAR ALL command TABCLR: TMNN NXZMC,+NMXVAR ;ARE WE DOING A CLEAR? ERRRET NTEPAM ;NOPE, PARAMETER MISSING TABCL1: JUMPGE NT,RSKP ;DONE WHEN POSITIVE LOAD T1,NTSET,(NT) ;GET SETTABILITY RESTRICTIONS CAXE T1,NTS. ;ARE THERE ARE RESTRICTIONS? JRST TABCL5 ;YES, IGNORE THIS PARAMETER LOAD T1,NXENT,+NMXVAR ;GET ENTITY TYPE CAXE T1,.NTNOD ;IS IT NODE? JRST TABCL2 ;NOPE, APPLICABILITY DOESN'T APPLY LOAD T1,NXNTY,+NMXVAR ;GET TYPE OF NODE MOVE T1,[NTA.E NTA.R NTA.L]-1(T1) ;GET BITS REPRESENTING APPLICABILITY TDNN T1,NT.APL(NT) ;DOES THIS APPLY TO THIS NODE? JRST TABCL5 ;NOPE, BYPASS IT TABCL2: TXNN T1,<.NTLIN&.NTCKT> ;Is it a LINE or a CIRCUIT? JRST TABCL3 ;No, don't bother checking Line type LOAD T2,NXLTY,+NMXVAR ;Get the Line type MOVE T2,[NTD.D ;Bit indicating DTE NTD.K ; KDP NTD.P ; DDP NTD.C ; CI NTD.N ; NI NTD.R]-1(T2) ; DMR TDNN T2,NT.DEV(NT) ;Does this Parameter apply to this Line Type? JRST TABCL5 ;NOPE, BYPASS IT TABCL3: CALL TABSR3 ;Go CLEAR this parameter RET ;Error TABCL5: ADD NT,[1,,NT.LST] ;INCREMENT POINTER, DECREMENT COUNT JRST TABCL1 ;AND DO THE NEXT PARAMETER SUBTTL Counter Functions ;PRSCOU - Counter Functions Routine. ; All three JSYS Counter Functions dispatch to here. The ; NFWBLK Block is set up, a memory block is allocated, ; and the NMX function code is stored in T1. ; We then dispatch off of the Entity Type field to the ; routines which call the layers. ;Note: this routine is also called from LLINKS. NSP needs a little ; help to generate the NICE message of the NSP node counters on a ; "database reused" event. ; ;LLINKS sets up a NMXVAR and NFWBLK TRVAR's, so it mimics the higher ; layers of NTMAN. PRSCOU: LOAD T1,NXENT,+NMXVAR ;Get the Entity Type STOR T1,NFETY,+NFWBLK ;Put entity Type into NFWBLK LOAD T1,NXNUM,+NMXVAR ;Get the Entity ID (Already converted) STOR T1,NFEID,+NFWBLK ;Copy it into NFWBLK MOVX T1,COUBLK ;Get the size of a counter block STOR T1,NFBLN,+NFWBLK ;Copy it into NFWBLK CALL DNGWDS ;Get buffer of that length ERRRET NTERES ;Resource Error STOR T1,NFBUF,+NFWBLK ;Put Buffer Address into NFWBLK SETONE NFBFF,+NFWBLK ;Flag that we sre sending a buffer to the layer LOAD T2,NXFNC,+NMXVAR ;Get the JSYS function code IFE FTDEBUG < MOVE T1,<-.NTSLM>+[ ;GET FLAG BITS FOR THIS FUNCTION > IFN FTDEBUG < MOVE T1,<-.NTTEV>+[ ;GET FLAG BITS FOR THIS FUNCTION NF.ILG ;.NTTEV (check entity) > NF.ILG ;.NTSLM (TOPS-20 only) NF.ILG ;.NTPSI (TOPS-20 ONLY) NF.ILG ;.NTMAP NF.ILG ;.NTREX NF.ILG ;.NTSET NF.ILG ;.NTCLR NF.SZC ;.NTZRO NF.COU ;.NTSHO NF.SZC ;.NTSZC NF.ILG ;.NTRET NF.ILG](T2) ;.NTDQE SKIPGE T1 ;Skip if Function code is alright JRST [ LOAD T1,NFBUF,+NFWBLK ;Put the buffer address back into T1 CALL DNFWDS ;Return the block SETZRO NFBUF,+NFWBLK ;Get rid of the address SETZRO NFBFF,+NFWBLK ;and the flag BUG.(CHK,NTMICF,NTMAN,SOFT,,,< Cause: There is an illegal function in the PRSCOU routine. NXFNC is wrong. >,NTEMPE)] LOAD T2,NXENT,+NMXVAR ;Get the Entity Type so we can dispatch CALL <-.NTNOD>+@[ ;Dispatch according to Entity Type IFIW ;Node Counters IFIW ;Line Counters IFIW ;Logging Counters (There are none!) IFIW ;Circuit Counters IFIW ;Module Counters (None) IFIW ](T2) ;Area Counters (None) RET ;Error has been reported and buffer deallocated LOAD T1,NFBUF,+NFWBLK ;Get the Counter Block Address CALL DNFWDS ;Return the block SETZRO NFBUF,+NFWBLK ;Get rid of the address SETZRO NFBFF,+NFWBLK ;and the flag RETSKP ;return success SUBTTL PRSNDC - Process Node counters ;Show Node counters (and maybe Zero) ;Call ; T1/ Function Code (NF.COU or NF.SZC) ; NFWBLK is all set up for call to ECLNMX and RTRNMX ;Return ; RET on error, error code in T1 ; RETSKP, via PRSCBK on success PRSNDC: SAVEAC ;Will store Function code here MOVE P1,T1 ; so we have it for RTRNMX call XMOVEI T2,NFWBLK ;And NF Block address in T2 CALL ECLNMX ;Call the End Communication Layer IFNSK. SKIPE T1 ;Is there 'error' return zero?? JRST NTEERR ;No. Report error and deallo buffer if there SETONE NXNIL,+NMXVAR ;Indicate no info returned, but no error ENDIF. LOAD T1,NFBUF,+NFWBLK ;Get the Counter Block Address LOAD T2,NFBLN,+NFWBLK ;and the # of words written CALL PRSCBK ;Go parse the counter block RET SETZRO NXNIL,+NMXVAR ;Make sure the No Information bit is clear CALL LOCNID ;Get the Local node number RET LOAD T2,NFEID,+NFWBLK ;Get the Node Number back CAME T1,T2 ;Is it our node number RETSKP ;No, Return. ROUTER has EXECUTOR COUNTERS only MOVX T1,COUBLK ;We have to reset the Buffer Length because STOR T1,NFBLN,+NFWBLK ; ECLNMX returned bytes written there. MOVE T1,P1 ;Put function code in T1 XMOVEI T2,NFWBLK ;And NF Block address in T2 CALL RTRNMX ;Call the End Communication Layer IFNSK. SKIPE T1 ;Is there 'error' return zero?? JRST NTEERR ;No. Report error and deallo buffer if there SETONE NXNIL,+NMXVAR ;Indicate no info returned, but no error ENDIF. LOAD T1,NFBUF,+NFWBLK ;Get the Counter Block Address LOAD T2,NFBLN,+NFWBLK ;and the # of words written CALLRET PRSCBK ;Go parse the counter block SUBTTL PRSCKC - Process Circuit counters ;Show Circuit counters (and maybe Zero) ;Call ; T1/ Function Code (NF.COU or NF.SZC) ; NFWBLK is all set up for call to RTRNMX and DNDNMX ;Return ; RET on error, error code in T1 ; RETSKP, via PRSCBK on success PRSCKC: SAVEAC ;Will store Function code here MOVE P1,T1 ; so we have it for DNDNMX call XMOVEI T2,NFWBLK ;And NF Block address in T2 CALL RTRNMX ;Call the End Communication Layer IFNSK. SKIPE T1 ;Is there 'error' return zero?? JRST NTEERR ;No. Report error and deallo buffer if there SETONE NXNIL,+NMXVAR ;Indicate no info returned, but no error ENDIF. LOAD T1,NFBUF,+NFWBLK ;Get the Counter Block Address LOAD T2,NFBLN,+NFWBLK ;and the # of words written CALL PRSCBK ;Go parse the counter block RET SETZRO NXNIL,+NMXVAR ;Make sure the No Information bit is clear MOVX T1,COUBLK ;We have to reset the Buffer Length because STOR T1,NFBLN,+NFWBLK ; ECLNMX returned bytes written there. MOVE T1,P1 ;Put function code in T1 XMOVEI T2,NFWBLK ;And NF Block address in T2 CALL DNDNMX ;Call the End Communication Layer IFNSK. SKIPE T1 ;Is there 'error' return zero?? JRST NTEERR ;No. Report error and deallo buffer if there SETONE NXNIL,+NMXVAR ;Indicate no info returned, but no error ENDIF. LOAD T1,NFBUF,+NFWBLK ;Get the Counter Block Address LOAD T2,NFBLN,+NFWBLK ;and the # of words written CALLRET PRSCBK ;Go parse the counter block SUBTTL PRSLNC - Process Line Counters ;Show (and maybe Zero) Line counters ;Call ; T1/ Function Code ; NFWBLK is all set up for call to DNDNMX ;Return ; RET on error ; RETSKP on success PRSLNC: XMOVEI T2,NFWBLK ;And NF Block address in T2 CALL DNDNMX ;Call the Data Link Layer IFNSK. SKIPE T1 ;Is there 'error' return zero?? JRST NTEERR ;No. Report error and deallo buffer if there SETONE NXNIL,+NMXVAR ;Indicate no info returned, but no error ENDIF. LOAD T1,NFBUF,+NFWBLK ;Get the Counter Block Address LOAD T2,NFBLN,+NFWBLK ;and the # of words written CALLRET PRSCBK ;Go parse the counter block SUBTTL Parse Counter block and build NICE response ;PRSCBK - Parse the counter block passed back from a DECnet layer ; ;Call ; T1/ Counter Block Address ; T2/ Number of words written in block ;Return ; RET ;If error ; RETSKP ;If counter block handled OK ; PRSCBK: JN NXNIL,+NMXVAR,RSKP ;If Layer didn't know about him, ignore it. JE NXWUS,+NMXVAR,RSKP ;IF NOT WRITING TO THE USER, RETURN SAVEAC ;P1<=Block Addr., P2<= # of words MOVE P1,T1 MOVE P2,T2 COULOP: LOAD T1,KBWID,(P1) ;GET COUNTER SIZE CAXN T1,40 ;IS IT SIZE 32. MOVX T1,30 ;NICE WANTS IT TO GET A 30 (octal) ASH T1,^D10 ;SHIFT IT INTO WIDTH FIELD OF HEADER FIELD TXO T1,1_^D15 ;TURN ON BIT INDICATING A COUNTER HEADER TMNE KBBMF,(P1) ;Check for a Bit Mask Field, skip if none TXO T1,1_^D12 ;set "Bit Mask" bit LOAD T2,KBTYP,(P1) ;GET SEQUENCE NUMBER OF PARAMETER OR COUNTER IOR T1,T2 ;OR INTO HEADER DUO-BYTE CALL PUT2BT ;PUT 2 BYTES OF HEADER INTO USER DATA STRING RET ;error... TMNE KBBMF,(P1) ;Skip over code that puts in Bit mask, if none IFNSK. LOAD T1,KBMSK,(P1) ;Get the Bit mask from the Counter Block CALL PUT2BT ;Put 2 bytes of bit mask into user data string RET ;error... ENDIF. NOBITM: LOAD T1,KBWID,(P1) ;Get the counter width MOVX T2,1 ;we are going to calculate overflow value in T2 LSH T2,(T1) ;Shift over counter width times, decrement SUBI T2,1 ; to get Max Counter value, and complement SETCA T2,T2 ; it to get the bits that should not be set. LOAD T1,KBVAL,(P1) ;Now get the 36-bit counter value returned TDNE T1,T2 ;Skip if we do not have a counter overflow. IFNSK. SETCA T2,T2 ;Set the mask back to the Max Counter value STOR T2,KBVAL,(P1) ;Put max value into counter block ;Now go and store the counter value ENDIF. STORCV: LOAD T2,KBWID,(P1) ;GET NUMBER OF BYTES FOR COUNTER AGAIN LOAD T1,KBVAL,(P1) ;GET VALUE TO RETURN ASH T2,-3 ;Right justify width CAXL T2,1 ;MUST BE AT LEAST ONE BYTE CAXLE T2,4 ;MAY BE AT MOST 4 BYTES COULNE: BUG.(CHK,NTMBCL,NTMAN,SOFT,,,< Cause: While generating output for a numeric field, there has been a request to generate an illegal number of bytes. >,NTEMPE) CALL <-1>+@[IFIW ;PUT A SINGLE BYTE IFIW ;PUT A DUO BYTE IFIW ;DO THREE BYTES. ILLEGAL IFIW ](T2) ;4 BYTES. RET ;error... JE KBBMF,(P1),ADDTWO ;Skip over code for Bit Masks SKIPA T1,[3] ;Three words if Bit Mask was included ADDTWO: MOVX T1,2 ;Only two words if no bit mask ADD P1,T1 ;Move the address pointer down the block SUB P2,T1 ;decrement the count of words in buffer JUMPG P2,COULOP ;do more counters if any left SKIPE P2 ;Count is zero, OK BUG.(CHK,NTMCBL,NTMAN,SOFT,,,< Cause: A DECnet Layer has returned an invalid length for a Counter Block. >,NTEMPE) RETSKP SUBTTL Functions -- .NTSHO -- Select parameters to return ;SELITM - Select items from list of parameters for an entity, and ; write their values to the user string ;Call ; P1/ Type of entity ;Return ; RET ;on error, NXERR contains code ; RETSKP ;success, all info for this entity in string ; SELITM: SAVEAC ;GET SOME WORK REGISTERS LOAD T1,NXSEL,+NMXVAR ;GET SELECTION CRITERIA CAXL T1,.NTSUM ;RANGE CHECK SELECTION CRITERIA CAXLE T1,.NTCST ;CIRCUIT STATE IS HIGHEST. BUG.(CHK,NTMSOR,NTMAN,SOFT,,,< Cause: The criteria is out of range for selecting items to return (for .NTSHO) dependent on the selection criteria. Action: Fix the check in GETBLK or find out who is trashing field NXSEL >,NTEUFO) CAXN T1,.NTCOU ;IS THIS SHOW COUNTERS? JRST PRSCOU ;Yes, jump to Counter Processing Routine MOVE NT,PRMP(P1) ;NOPE, GET POINTER TO PARAMETERS MOVE P1,<-.NTSUM>+[NTI.% ;SUMMARY BIT NTI.S ;STATUS BIT NTI.C ;CHARACTERISTICS BIT NTI.N ;NOOP (COUNTERS NOT HANDLED HERE) NTI.N ;NOOP (EVENTS NOT HANDLED HERE) NTI.K](T1) ;CIRCUIT STATE BIT LOAD T1,NXNTY,+NMXVAR ;GET NODE TYPE (REMOTE, EXECUTOR...) CAXL T1,0 ;RANGE CHECK NODE TYPE (LOWEST IS NONE) CAXLE T1,NX.LPN ;LOOPBACK IS HIGHEST YET. BUG.(CHK,NTMNTR,NTMAN,SOFT,,,< Cause: It is necessary to know the node type (executor,remote, or loop) to select entries to return (for function .NTSHO). Other entities (circuit, lines) should have this field zero. This field is set by ENTCVT. >,NTEMPE) MOVE P2,[NTAPL ;NO NODE TYPE, DO THEM ALL NTA.E ;BIT INDICATING APPLIES TO EXECUTOR NODE NTA.R ;APPLIES TO REMOTE NODES NTA.L](T1) ;APPLIES TO LOOPBACK NODES LOAD T1,NXLTY,+NMXVAR ;GET LINE TYPE (CI, NI, DTE,...) CAXL T1,0 ;RANGE CHECK LINE TYPE (LOWEST IS NONE) CAXLE T1,NX.DMR ;DMR IS HIGHEST. BUG.(CHK,NTMLTR,NTMAN,SOFT,,,< Cause: To determine entries to return (for function .NTSHO), it is necessary to know the Line type (CI,NI,DTE,...). Other entities (Nodes,Modules) should have this field zero. This field is set by ENTCVT. >,NTEMPE) MOVE P3,[NTDEV ;NO LINE TYPE, DO THEM ALL NTD.D ;APPLIES TO DTE'S NTD.K ;APPLIES TO KDP'S NTD.P ;DDP'S NTD.C ;CI'S NTD.N ;NI'S NTD.R](T1) ;DMR'S SELIT4: JUMPGE NT,RSKP ;WHEN DONE, RETURN SUCCESS LOAD T2,NXENT,+NMXVAR ;Get the Entity Type CAXE T2,.NTNOD ;Is it a NODE Entity? IFSKP. CALL LOCARE ;Yes, go get Home Area number JRST NTEERR LOAD T2,NXNUM,+NMXVAR ;Get the Node address from the user TXZ T2,RN%NOD ;Get just the AREA Number LSH T2,-^D10 ; Right justify CAMN T1,T2 ;Is the requested node in the Home Area? IFSKP. ;No, Check if parameter is for Home Area only MOVX T1,NTA.H ;Put Home Area Only flag into T1 TDNE T1,NT.APL(NT) ;Check Parameter applicabilty JRST SELIT6 ENDIF. ENDIF. TDNE P1,NT.INF(NT) ;DOES THIS MATCH OUR SELECTION CRITERIA? TDNN P2,NT.APL(NT) ;AND DOES THIS APPLY TO US? SKIPA ;NOPE. SKIP OVER IT TDNN P3,NT.DEV(NT) ;Does it apply to this device? JRST SELIT6 ;NOPE. SKIP OVER IT MOVX T1,NTI.Q ;Get the 'Qualified Parameter' bit flag TDNE T1,NT.INF(NT) ;Skip if this parameter is not qualified IFSKP. CALL SHOPRM ;Go SHOW QUALIFIED PARAMETER RET ;Error return... ELSE. CALL SHOQUP ;YEP. DO THIS PARAMETER RET ;error, punt... ENDIF. SELIT6: ADD NT,[1,,NT.LST] ;POINT TO NEXT ITEM ON LIST JRST SELIT4 ;GO TRY FOR THIS NEW ITEM SUBTTL Functions -- Get the Qualifier values, for a Qualified Parameter ;SHOQUP - Show qualified Parameter. SHOQUP: SAVEAC LOAD T1,NXENT,+NMXVAR ;Get the Entity Type Back MOVE P1,NT ;Save the Qualified Parameter table entry MOVE NT,PRMP(T1) ;Get the pointer to top of the parameter table LOAD T1,NTQUA,(P1) ;Get the Qualifier Parameter Number SHOQU1: JUMPGE NT,NTEMPE ;If we hit the end of table, we have an error LOAD T2,NTSEQ,(NT) ;Get a Sequence number CAME T1,T2 ;Is it our Qualifier???? IFNSK. ADD NT,[1,,NT.LST] ;NO! Get next entry in table JRST SHOQU1 ;And loop until we find it.... ENDIF. MOVE T1,NT ;Get the Table Entry address for the Qualifier CALL SETNFB ;Set up the NF Block RET ;error MOVX T1,NF.RED ;Set up READ function code XMOVEI T2,NFWBLK ;And the argument block goes into T2 LOAD T3,NTROU,(NT) ;GET ROUTINE FOR THIS PARAMETER CALL NMXLAY ;CALL LAYER-LEVEL ROUTINE TO DO PARAMETER IFNSK. SKIPE T1 ;Is there 'error' return zero?? JRST NTEERR ;No. Report error and deallo buffer if there SETONE NXNIL,+NMXVAR ;Indicate no info returned, but no error ENDIF. JE NFBFF,+NFWBLK,ONEQUA ;Jump if only One qualifier, (i.e no buffer) LOAD P2,NFBUF,+NFWBLK ;Get the buffer address back into P2 MOVE P4,P2 ;Keep the head of the buffer address in P4 LOAD P3,NFBLN,+NFWBLK ;And the number of words written... JUMPE P3,SHOQU3 ;Jump if no values returned SETZRO NFBFF,+NFWBLK ;indicate no buffer present. SHOQU2: MOVE T1,(P2) ;Get the first Qualifier value STOR T1,NFBUF,+NFWBLK ;Put the value into the Buffer/value field CALL NMXWTY ;Write qualifier value to user buffer IFNSK. MOVE T1,P4 ;Get the buffer address back into T1 CALL DNFWDS ;And return buffer RET ENDIF. EXCH NT,P1 ;Get the Qualified parameter table entry MOVE T1,NT ;Put the Parameter Table Entry address into T1 CALL SETNFB ;Set up the Interface Block IFNSK. MOVE T1,P4 ;Get the buffer address back into T1 CALL DNFWDS ;Deallocate it. RET ;error return, buffer has been deallocated ENDIF. MOVE T1,(P2) ;Get the first Qualifier value again STOR T1,NFQUA,+NFWBLK ;Store it in the Qualifier Field SETONE NFQUF,+NFWBLK ;Flag we are sending a qualifier MOVX T1,NF.RED ;Set up READ function code XMOVEI T2,NFWBLK ;And the argument block goes into T2 LOAD T3,NTROU,(NT) ;GET ROUTINE FOR THIS PARAMETER CALL NMXLAY ;CALL LAYER-LEVEL ROUTINE TO DO PARAMETER IFNSK. SKIPE T1 ;Is there 'error' return zero?? IFNSK. STOR P4,NFBUF,+NFWBLK ;Put buffer back in NFWBLK SETONE NFBFF,+NFWBLK ;NTEERR will deallocate buffer for us JRST NTEERR ;No. Report error and deallo buffer if there ENDIF. SETONE NXNIL,+NMXVAR ;Indicate no info returned, but no error ENDIF. CALL NMXWTY ;WRITE STRING OUT TO USER IN APPROPRIATE FORMAT IFNSK. MOVE T1,P4 ;Get the buffer address back into T1 CALL DNFWDS ;Deallocate it. RET ;error return, buffer has been deallocated ENDIF. EXCH NT,P1 ;Get the Qualifier parameter table entry AOJ P2, ;Increment the buffer pointer SOJG P3,SHOQU2 ;Jump if more qualifiers SHOQU3: MOVE T1,P4 ;Get the buffer address back CALL DNFWDS ;Deallocate the buffer RETSKP ONEQUA: JN NXNIL,+NMXVAR,RSKP ;Return if layer didn't know about Qualifier CALL NMXWTY ;Write qualifier value to user string RET ;Error return... EXCH NT,P1 ;Get the Qualified Parameter table entry LOAD P1,NFBUF,+NFWBLK ;Save the Qualifier value MOVE T1,NT ;Now put it into T1 CALL SETNFB ;Set up the NFWBLK RET STOR P1,NFQUA,+NFWBLK ;Store it in the Qualifier Field SETONE NFQUF,+NFWBLK ;Flag we are sending a qualifier JRST SHOPR1 ;And jump into SHOPRM SUBTTL Functions -- .NTSHO -- Return parameters to user ;SHOPRM - Process a parameter, and put into user data string SHOPRM: SAVEAC ;SAVE A BUNCH OF ACS (TRASHED IN CM HANDLING) MOVE T1,NT ;Put the Parameter Table Entry address into T1 CALL SETNFB ;Set up the Interface Block RET SHOPR1: MOVX T1,NF.RED ;Set up READ function code XMOVEI T2,NFWBLK ;And the argument block goes into T2 LOAD T3,NTROU,(NT) ;GET ROUTINE FOR THIS PARAMETER CALL NMXLAY ;CALL LAYER-LEVEL ROUTINE TO DO PARAMETER IFNSK. SKIPE T1 ;Is there 'error' return zero?? JRST NTEERR ;No. Report error and deallo buffer if there SETONE NXNIL,+NMXVAR ;Indicate no info returned, but no error ENDIF. CALL NMXWTY ;WRITE STRING OUT TO USER IN APPROPRIATE FORMAT RET ; error return JE NFBFF,+NFWBLK,RSKP ;If no buffer,we are finished LOAD T1,NFBUF,+NFWBLK ;Get the buffer address CALL DNFWDS ;Deallocate it SETZRO NFBUF,+NFWBLK ;Get rid of the address SETZRO NFBFF,+NFWBLK ;and the flag RETSKP ;FINISHED ;Setup NMX Interface Block ;Call: ; T1/ Address of a Parameter Table Entry ;Return ; ; RET error return ; RETSKP NFWBLK/ All set up for a call to a DECnet Layer ; SETNFB: SAVEAC ;Preserve NT MOVE NT,T1 ;Put parameter table entry address here SETZM NFWBLK ;CLEAN FIRST WORD OF BLOCK HRRI T2,1+NFWBLK ;GET POINTER TO SECOND WORD IN BLOCK HRLI T2,NFWBLK ;POINT AT START OF BLOCK BLT T2,NF.LST-1+NFWBLK ;CLEAN UNTIL END OF BLOCK LOAD T1,NXNUM,+NMXVAR ;Get the converted Entity Id STOR T1,NFEID,+NFWBLK ;Put it int the argument block LOAD T1,NTSEQ,(NT) ;Get the parameter type (number) from the table STOR T1,NFPRM,+NFWBLK ;and into the argument block LOAD T1,NXENT,+NMXVAR ;We need the Entity type STOR T1,NFETY,+NFWBLK ;save it... JE NTBUF,(NT),SETNF1 ;Does this Parameter require a buffer LOAD T1,NTBSZ,(NT) ;Yes, get the size needed from table STOR T1,NFBLN,+NFWBLK ;Put it into the argument block CALL DNGWDS ;Go allocate the block ERRRET NTERES ;No memory available, resource error STOR T1,NFBUF,+NFWBLK ;Put the buffer addr into the arg block SETONE NFBFF,+NFWBLK ;And tell Layer to expect a buffer RETSKP SETNF1: SETZRO NFBFF,+NFWBLK ;No buffer in this case. SETZRO NFBUF,+NFWBLK ;Get rid of the buffer address RETSKP SUBTTL Functions -- .NTRET -- List node names ;NMXLND - List a series of node names. Function .NTRET ;Call ; NMXVAR/ NX block ;Return ; RET ;On error, error code loaded into NXERR,+NMXVAR ; RETSKP ;Success, with user's data string containing list NMXLND: SAVEAC ;I NEED A LOT OF ACS MOVX T1,.NTNOD ;Get the NODE ENTITY TYPE code STOR T1,NFETY,+NFWBLK ;Put it into the Arg Block SETZ NT, ;FLAG NOTHING SPECIAL YET LOAD P1,NXSEL,+NMXVAR ;FIND OUT WHAT KIND OF LIST HE WANTS STOR P1,NFSEL,+NFWBLK ;Put it into the NF Block CAXL P1,.NTSGN ;Range Check the Selection Criteria CAXLE P1,.NTKNO ;If not between SIGNIFICANT & KNOW JRST NTEUFO ; it is an error JRST <-.NTSGN>+@[ IFIW ;SIGNIFICANT nodes not supported IFIW ;ADJACENT nodes IFIW ;LOOP Nodes IFIW ;ACTIVE Nodes IFIW ](P1) ;KNOWN Nodes NMXLNA: CALL GETEBY ;Get the Area Number user wants RET ;Error return STOR T1,NFEID,+NFWBLK ;Put it into the Argument Block MOVE NT,T1 ;And save it in a register for now CALL LOCARE ;Get the local Node Id RET ;Error Return CAME T1,NT ;Does user want the Home Area???? JRST NMXLFA ;No, go ask Session Control MOVX T1,NDBLEN ;Length of a Node Bffer CALL DNGWZP ;Get a Zeroed Buffer (Low Priority) JRST NTERES ;Resource Error STOR T1,NFBUF,+NFWBLK ;Put it into the arg block SETONE NFBFF,+NFWBLK ;Tell the layers we are giving them a buffer MOVX T1,NDBLEN ;Get the buffer length STOR T1,NFBLN,+NFWBLK ;So the layer knows how long it is. MOVX T1,NF.RET ;Get the function code XMOVEI T2,NFWBLK ;and the Arg Block address CALL SCLNMX ;Ask Session Control for KNOWN NODES IFNSK. SKIPE T1 ;Is there 'error' return zero?? JRST NTEERR ;and go report the error JRST NMXLA2 ;Return OK, No Data.... ENDIF. MOVX T1,NF.RET ;Get the function code XMOVEI T2,NFWBLK ;and the Arg Block address CALL RTRNMX ;Ask Routing Layer for KNOWN NODES IFNSK. SKIPE T1 ;Is there 'error' return zero?? JRST NTEERR ;and go report the error JRST NMXLA2 ;Return OK, No Data.... ENDIF. LOAD P2,NFBUF,+NFWBLK ;Get the buffer address into P2 ADDI P2,1 ;START AT NODE NUMBER 1 NMXLN2: LOAD T1,NFBUF,+NFWBLK ;Get Buffer address ADDI T1, ;Find the end of the buffer CAMLE P2,T1 ;HAVE WE PASSED THE MAXIMUM NODE NUMBER? IFNSK. LOAD T1,NFBUF,+NFWBLK ;Get the Counter Block CALL DNFWDS ;Free up memory SETZRO NFBUF,+NFWBLK ;Get rid of the address SETZRO NFBFF,+NFWBLK ;and the flag JRST RSKP ;Yes, we are all done ENDIF. MOVE T1,(P2) ;Get the contents of this cell SKIPN T1 ;Are the contents zero??? AOJA P2,NMXLN2 ;If so increment index, and loop CALL PUT2BT ;PUT NODE NUMBER IN DATA STRING RET SETZ T1, ;NO NAME FOLLOWING, SO A ZERO STRINGID HEAD CALL PUTBYT ;PUT BYTE IN DATA STRING RET AOJA P2,NMXLN2 ;GO DO ANOTHER NODE ;Ask Session Control for KNOWN NODES in a Specific area, other than ;the Home area. NMXLFA: LOAD T1,NXDAT,+BP.BPT+NMXVAR ;Get the Byte pointer to the user buffer STOR T1,NFBPT,+NFWBLK ;Put it into the Arg block LOAD T1,NXDAT,+BP.BYT+NMXVAR ;Get the number of bytes in the user buf. STOR T1,NFBLN,+NFWBLK ;Send it to Session control SETONE NFUBF,+NFWBLK ;Flag it is a user buffer MOVX T1,NF.RET ;Get the function code XMOVEI T2,NFWBLK ;and the Arg Block address CALL SCLNMX ;Ask Session Control for Known Nodes JRST NTEERR ;Report error and deallocate buffer SETZRO NFUBF,+NFWBLK ;Get rid of the User buffer flag LOAD T1,NFBPT,+NFWBLK ;Get the byte pointer back STOR T1,NXDAT,+BP.BPT+NMXVAR ;Put it back where NTMAN expects it LOAD T1,NFBLN,+NFWBLK ;And the updated count STOR T1,NXDAT,+BP.BYT+NMXVAR ;And save it again RETSKP ;return success ;Ask Session Control for LOOP NODES NMXLLN: MOVX T1,LPNBLK ;Get the size of a LOOP NODE Block STOR T1,NFBLN,+NFWBLK ;Copy it into NFWBLK CALL DNGWDS ;Get buffer of that length ERRRET NTERES ;Resource Error STOR T1,NFBUF,+NFWBLK ;Put Buffer Address into NFWBLK SETONE NFBFF,+NFWBLK ;Flag that we sre sending a buffer to the layer MOVX T1,.NTNOD ;Get the NODE ENTITY TYPE code STOR T1,NFETY,+NFWBLK ;Put it into the Arg Block MOVX T1,NF.RET ;Get the function code XMOVEI T2,NFWBLK ;and the Arg Block address CALL SCLNMX ;Ask Session Control for LOOP NODES JRST NTEERR ;Report error and Deallocate buffer LOAD NT,NFBUF,+NFWBLK ;Get the Buffer address back LOAD P2,NFBLN,+NFWBLK ;Get the number of words written into buffer JUMPE P2,NMXLN6 ;Jump if no Loop nodes returned... NMXLN5: MOVE T1,(NT) ;Get the name CALL NMXS2A ;Convert Node name to ASCII and save in NMXVAR SETZ T1, ;NO NUMBER CALL PUT2BT ;PUT TWO BYTES IN STREAM INDICATING NO NUMBER RET XMOVEI P1,NX.VAL+NMXVAR ;POINT TO THE WHERE THE NODE STRING IS CALL PUTSTR ;COPY THE STRING TO THE USER RET SOSLE P2 ;Decrement count of Circuits and skip if done AOJA NT,NMXLN5 ;Increment Buffer pointer and do next Node NMXLN6: LOAD T1,NFBUF,+NFWBLK ;Get the Buffer Address CALL DNFWDS ;Return the block SETZRO NFBUF,+NFWBLK ;Get rid of the address SETZRO NFBFF,+NFWBLK ;and the flag RETSKP ;return success ;Ask Routing Layer for ACTIVE or ADJACENT NODES. NMXLAD: NMXLAC: SAVEAC MOVX T1,NDBLEN ;Length of a Node Bffer CALL DNGWZP ;Get a Zeroed Buffer (Low Priority) JRST NTERES ;Resource Error STOR T1,NFBUF,+NFWBLK ;Put it into the arg block SETONE NFBFF,+NFWBLK ;Tell the layers we are giving them a buffer MOVX T1,NDBLEN ;Get the buffer length STOR T1,NFBLN,+NFWBLK ;So the layer knows how long it is. MOVX T1,NF.RET ;Get the function code XMOVEI T2,NFWBLK ;and the Arg Block address CALL RTRNMX ;Ask Session Control for Known Nodes IFNSK. SKIPE T1 ;Is there 'error' return zero?? JRST NTEERR ;and go report the error JRST NMXLA2 ;Return OK, No Data.... ENDIF. LOAD P1,NFBUF,+NFWBLK ;Get the buffer address LOAD P2,NFBLN,+NFWBLK ;And the number of node numbers written JUMPE P2,NMXLA2 ;Jump if the count is zero NMXLA1: MOVE T1,(P1) ;Get a node number CALL PUT2BT RET SETZ T1, CALL PUTBYT RET AOJ P1, SOJG P2,NMXLA1 NMXLA2: LOAD T1,NFBUF,+NFWBLK ;Get the Counter Block CALL DNFWDS ;Free up memory SETZRO NFBUF,+NFWBLK ;Get rid of the address SETZRO NFBFF,+NFWBLK ;and the flag RETSKP ;return success SUBTTL Functions -- .NTRET -- List circuit and line names ;NMXLCK - Return a list of line/circuit names ;Call ; NMXVAR/ NX block ; P1/ Entity Type (LINE or CIRCUIT) ;Return ; RET ;ON ERROR, NXERR,+NMXVAR CONTAINING ERROR CODE ; RETSKP ;WITH LIST OF NAMES IN USER DATA STRING NMXLCK: SAVEAC STOR P1,NFETY,+NFWBLK ;Put entity Type into NFWBLK LOAD T1,NXSEL,+NMXVAR ;Get the Selector STOR T1,NFSEL,+NFWBLK ;Copy it into NFWBLK MOVX T1,CIRBLK ;Get the size of a return-circuits block STOR T1,NFBLN,+NFWBLK ;Copy it into NFWBLK CALL DNGWDS ;Get buffer of that length ERRRET NTERES ;Resource Error STOR T1,NFBUF,+NFWBLK ;Put Buffer Address into NFWBLK SETONE NFBFF,+NFWBLK ;Flag that we sre sending a buffer to the layer MOVX T1,NF.RET ;Set up the function code XMOVEI T2,NFWBLK ;Get the buffer address into T2 CAXE P1,.NTLIN ;Is the Entity Type a LINE?? IFSKP. CALL DNDNMX ;Go ask DNADLL for the circuit ids IFNSK. SKIPE T1 ;Is there 'error' return zero?? JRST NTEERR ;No. Report error and deallo buffer if there JRST NMXLC5 ;No data returned, but no error... ENDIF. ELSE. CALL RTRNMX ;Go ask Router for the circuit ids IFNSK. SKIPE T1 ;Is there 'error' return zero?? JRST NTEERR ;No. Report error and deallo buffer if there JRST NMXLC5 ;No data returned, but no error... ENDIF. ENDIF. LOAD NT,NFBUF,+NFWBLK ;Get back the buffer address LOAD P2,NFBLN,+NFWBLK ;and the number of words returned JUMPLE P2,NMXLC5 ;If none (or less than none), do nothing. NMXLC4: MOVE T1,(NT) ;Get the Circuit Id MOVE T2,[POINT 8,NX.VAL+NMXVAR] ;DATA STORAGE AREA CALL NMXC2N ;CONVERT CIRCUIT-ID TO NAME JRST NTEMPE ;ERROR! XMOVEI P1,NX.VAL+NMXVAR ;POINT TO THE CIRCUIT NAME STRINGID CALL PUTSTR ;PUT THIS STRING IN THE USER'S BUFFER RET ;error SOSLE P2 ;Decrement count of Circuits and skip if done AOJA NT,NMXLC4 ;Increment Buffer pointer and do next circuit NMXLC5: LOAD T1,NFBUF,+NFWBLK ;Get the Buffer Address CALL DNFWDS ;Return the block SETZRO NFBUF,+NFWBLK ;Get rid of the address SETZRO NFBFF,+NFWBLK ;and the flag RETSKP ;return success SUBTTL Entities -- Convert entity names to entity ids ;Called from NMXDIS ENTCVT: SETZRO NXNTY,+NMXVAR ;NO NODE AS OF YET SETZRO NXLTY,+NMXVAR ;NO LINE AS OF YET CALLRET @.+1-.NTNOD(P1) IFIW ;CONVERT NODE TYPE IFIW ;LINE TYPE IFIW ;LOGGING. PUNT, WE DON'T DO THESE IFIW ;SAME AS LINE IFIW ;MODULE - ILLEGAL IFIW ;ILLEGAL. ;Called from ENTCVT NODCVT: SAVEAC ;NEED FOR TEMP BYTE STORAGE CALL GETEBY ;GET ENTITY STRING BYTE RET MOVE P1,T1 ;SAVE THE BYTE FOR A WHILE CALL GETEBY ;GET ANOTHER BYTE RET ASH T1,^D8 ;SHIFT HIGH-ORDER BYTE OVER IOR P1,T1 ;INCLUDE LOW ORDER BYTE JUMPN P1,NODCVX ;IF WE HAVE AN ADDRESS, WE ARE OK CALL GETSTI ;NO ADDRESS, I MUST HAVE A NAME RET CALL NMXN2A ;CONVERT THE NAME TO AN ADDRESS. JRST NODCV2 ;NO SUCH NAME, MUST BE LOOPBACK MOVE P1,T1 ;Need the address in P1 now. JRST NODCV0 NODCVX: MOVE T1,P1 ;Get the node number back ASH T1,-<^D10> ;Get just the AREA Number JUMPN T1,NODCV0 ;Jump if AREA is non-zero CALL LOCARE ;Get the Local Area Number RET ASH T1,^D10 ;Shift it over to the right position IOR P1,T1 ;And or it into the node number NODCV0: STOR P1,NXNUM,+NMXVAR ;SAVE IN ARGUMENT BLOCK CALL LOCNID ;Get our Node address, returned in T1 RET ;Error, give up... LOAD T2,NXNUM,+NMXVAR ;Get back the address we are working on CAME T2,T1 ;IS THIS US? JRST NODCV1 ;NOPE MOVX T1,NX.EXN ;THIS IS THE EXECUTOR NODE STOR T1,NXNTY,+NMXVAR ;DECLARE TYPE OF NODE RETSKP ;WE'RE DONE, RETURN NODCV1: MOVX T1,NX.REN ;THIS IS A REMOTE NODE STOR T1,NXNTY,+NMXVAR ;DECLARE THAT THIS IS A NODE, AND WHAT TYPE RETSKP ;Come here only for loop nodes after a fail return from NMXN2A. The latter ; routine will have written an error code into NXERR that needs to be cleared. NODCV2: SETZRO NXERR,+NMXVAR ;Clear error code from NMXN2A LOAD T2,NXFNC,+NMXVAR ;GET THE FUNCTION CODE WE ARE TO DO CAXE T2,.NTSET ;Is this a set? IFNSK. MOVX T1,.NTNOD ;Get the Node Entity type code STOR T1,NFETY,+NFWBLK ;Put it into the Arg block MOVX T1,NF.CKL ;Check Loopback Node function XMOVEI T2,NFWBLK ;Get the Argument Block CALL SCLNMX ;Go ask Session Control if Loopback Node Exists JRST NTEERR ;No it doesn't, go handle error ENDIF. LOAD T1,NFEID,+NFWBLK ;Get the Node Name back from the Block STOR T1,NXNUM,+NMXVAR ;SAVE THE NODNAME IN NXNUM MOVX T1,NX.LPN ;THIS IS A LOOPBACK NODE STOR T1,NXNTY,+NMXVAR ;SAVE THE NODE TYPE RETSKP ;Called from ENTCVT LINCVT: CALL GETSTI ;COPY MULTIPLE BYTES (INTERNAL LIMIT 16) RET ;error... MOVE T1,[POINT 8,NX.VAL+NMXVAR] ;BYTE POINTER TO LINE NAME WE COPIED CALL NMXN2C ;CONVERT NAME TO LINE-ID RET ; error, pass the code back SETONE LILXC,+T1 ;Flag that it is a Line Id (not circuit) STOR T1,NXNUM,+NMXVAR ;SAVE AWAY LINE ID LOAD T2,LIDEV,+T1 ;Get the Device Type Back STOR T2,NXLTY,+NMXVAR ;AND INTO THE NMX BLOCK STOR T1,NFEID,+NFWBLK ;Put the Line Id into argument block LOAD T1,NXENT,+NMXVAR ;Get the entity type STOR T1,NFETY,+NFWBLK ;Store it in Arg block MOVX T1,NF.CET ;Check Entity Function code into T1 XMOVEI T2,NFWBLK ;And the Argument Block address into T2 CALL DNDNMX ;Have the Data Link Layer Verify Line Id JRST NTEERR ;Save the error code RETSKP ;Return success if not ;Called from ENTCVT CIRCVT: CALL GETSTI ;COPY MULTIPLE BYTES (INTERNAL LIMIT 16) RET ;error... MOVE T1,[POINT 8,NX.VAL+NMXVAR] ;BYTE POINTER TO LINE NAME WE COPIED CALL NMXN2C ;CONVERT NAME TO LINE-ID RET ; error, pass the code back SETZRO LILXC,+T1 ;Flag that it is a Circuit Id (not Line) STOR T1,NXNUM,+NMXVAR ;SAVE AWAY LINE ID LOAD T2,LIDEV,+T1 ;Get the Device Type Back STOR T2,NXLTY,+NMXVAR ;AND INTO THE NMX BLOCK STOR T1,NFEID,+NFWBLK ;Put the Line Id into argument block LOAD T1,NXENT,+NMXVAR ;Get the entity type STOR T1,NFETY,+NFWBLK ;Store it in Arg block MOVX T1,NF.CET ;Check Entity Function code into T1 XMOVEI T2,NFWBLK ;And the Argument Block address into T2 CALL DNDNMX ;Have the Data Link Layer Verify Line Id JRST NTEERR ;Save the error code RETSKP ;Return Success SUBTTL Entities -- Circuit ID to name conversion ;NMXC2N - Convert circuit ID to name ;Call ; T1/ Circuit ID ; T2/ Local byte pointer to use in returning bytes ; Area must be large enough to receive 16 bytes. ;Return ; +1/ No such circuit ID ; +2/ Data area has stringid for circuit name ; NMXC2N:: SAVEAC ;SOME SCRATCH ACS DMOVE P1,T1 ;SAVE BOTH ARGUMENTS FOR THIS CALL SETZ T6, ;NUMBER OF BYTES DEPOSITED IDPB T6,P2 ;FIRST BYTE IS COUNT OF BYTES FOLLOWING MOVE T5,P2 ;SAVE BYTE POINTER TO COUNT BYTE LOAD T1,LIDEV,+P1 ;GET THE TYPE OF DEVICE CAXLE T1,LD.MAX ;IN RANGE OF DEVICES WE KNOW? BUG.(CHK,NTMKOR,NTMAN,SOFT,,,< Cause: The controller field in a line-id is out of range. The value LD.MAX defines the number of controllers known by D36PAR, and thus by NTMAN. The most likely cause of this bug is a trashed AC. Note: A controller is any device driver to which a router will interface. It is currently used to define the name of a Circuit/Line, under the assumption that each Kontroller will control only a single line type. >,RTN) ;WE KNOW THAT ALL DEVICE NAMES ARE AT MOST 4 BYTES LONG, AND THUS FIT IN A WORD HRLI T2,(POINT 7,) ;WE STORE THE DATA IN 7 BIT BYTES INTERNALLY HRRI T2,KONNAM(T1) ;GET POINTER TO DEVICE NAME NMXC20: ILDB T1,T2 ;GET A BYTE FROM THE DEVICE NAME JUMPE T1,NMXC21 ;END OF STRING, FALL THROUGH IDPB T1,P2 ;SAVE IT IN OUR DESTINATION DATA STRING AOJA T6,NMXC20 ;INCREMENT NUMBER OF BYTES DEPOSITED NMXC21: MOVEI T1,"-" ;SEPERATOR IDPB T1,P2 ;STORE IT AOJ T6, ;COUNT UP CHARACTER LOAD T1,LIKON,+P1 ;GET THE KONTROLLER NUMBER PUSHJ P,NMXC28 ;OUTPUT NUMBER IN DECIMAL IFN FTOPS10,< LOAD T1,LIDEV,+P1 ;GET THE DEVICE TYPE CAXN T1,LD.ETH ;IS IT AN ETHERNET? JRST NMXC22 ;YES, WE ARE DONE >; END IFN FTOPS10 MOVEI T1,"-" IDPB T1,P2 ;STORE THE SEPARATOR AOJ T6, ;INCREMENT NUMBER OF BYTES LOAD T1,LIUNI,+P1 ;GET THE UNIT NUMBER PUSHJ P,NMXC28 ;OUTPUT THE NUMBER IN DECIMAL JN LILXC,+P1,NMXC22 ;Jump if we are not dealing with a CIRCUIT LOAD T1,LIDEV,+P1 ;GET THE DEVICE TYPE CAXE T1,LD.CIP ;IS IT A CI? JRST NMXC22 ;NO, WE ARE DONE MOVEI T1,"." ;OUTPUT SEPERATOR IDPB T1,P2 ;STORE IT AOJ T6, ;AND INCREMENT COUNT LOAD T1,LIDRP,+P1 ;GET THE DROP NUMBER (PORT ON THE CI) PUSHJ P,NMXC28 ;AND OUTPUT IT IN DECIMAL NMXC22: CAIL T6,^D16 ;DID WE DO THIS IN 16 BYTES? BUG.(HLT,NTMCNO,NTMAN,SOFT,,,< Cause: More than 16 bytes of data have been returned into a 16 byte field. The data beyond the buffer has been trashed. Action: Examine the algorithm above to determine why more bytes than expected were returned. Fix the above code to check for overrun while it is producing the bytes, so that this halt does not occur. >) DPB T6,T5 ;STORE NUMBER OF BYTES WE GAVE RETSKP NMXC28: IDIVI T1,^D10 ;SEPERATE INTO DIGITS JUMPE T1,NMXC29 ;COMPLETED THE SEPARATION, START OUTPUTTING. PUSH P,T2 ;SAVE DIGIT ON STACK PUSHJ P,NMXC28 ;RECURSE POP P,T2 ;GET BACK DIGIT NMXC29: ADDI T2,"0" ;MAKE IT INTO AN ASCII DIGIT IDPB T2,P2 ;DEPOSIT INTO STRING AOJ T6, ;INCREMENT NUMBER OF BYTES GIVEN RET ;RETURN SUBTTL Entities -- Convert name to Circuit-ID. ;NMXN2C - Convert a string to line id ;Call ; T1/ Byte pointer to name ;Return ; +1, No such circuit ; +2, t1/ Circuit ID NMXN2C: SAVEAC ;WORK REGISTERS MOVE P1,T1 ;SAVE BYTE POINTER TO NAME MOVE T6,[POINT 7,T2] ;BYTE POINTER TO COPY NAME MOVEI T5,5 ;MAX OF 5 BYTES (ONE WORD) ILDB T4,P1 ;GET NUMBER OF BYTES IN THIS STRINGID SETZB T2,P2 ;CLEAR OUT DESTINATION, AND CIRCUIT ID NMXN20: SOJL T4,NTEINI ;TERMINATED TOO SOON. INVALID ILDB T1,P1 ;GET A BYTE CAIL T1,140 ;IS IT LOWER CASE? SUBI T1,40 ;YES, MAKE IT UPPER CASE CAIN T1,"-" ;DID IT INCLUDE THE DASH? JRST NMXN21 ;YES, STOP HERE. IDPB T1,T6 ;SAVE IN COPYING STRING SOJG T5,NMXN20 ;GET ANOTHER BYTE ERRRET NTEINI ;ILLEGAL NAME, GIVE UNRECOGNIZED COMPONENT NMXN21: MOVEI T1,LD.MAX ;MAXIMUM KONTROLLER DEVICE NUMBER NMXN22: CAMN T2,KONNAM(T1) ;IS THIS THE CONTROLLER WE CARE ABOUT? JRST NMXN23 ;YES, EXIT SOJGE T1,NMXN22 ;TRY FOR NEXT KONTROLLER DEVICE NUMBER ERRRET NTEINI ;ILLEGAL NAME NMXN23: STOR T1,LIDEV,+P2 ;STORE IN CIRCUIT ID WE ARE BUILDING CALL NMXN28 ;GET A NUMBER FROM THE STRING STOR T1,LIKON,+P2 ;STORE AS KONTROLLER NUMBER IN CIRCUIT ID CALL NMXN28 ;GET THE NEXT NUMBER FROM THE STRING STOR T1,LIUNI,+P2 ;SAVE UNIT NUMBER CALL NMXN28 ;GET NEXT NUMBER (IF ANY) STOR T1,LIDRP,+P2 ;SAVE AS DROP NUMBER (PORT ON CI) MOVE T1,P2 ;GET THE CIRCUIT ID WE JUST BUILT RETSKP ;RETURN SUCCESS. NMXN28: SETZ T1, ;CLEAR DESTINATION NUMBER NMXN29: SOJL T4,RTN ;NO MORE BYTES, RETURN ILDB T2,P1 ;GET NEXT DIGIT CAIL T2,"0" ;RANGE CAILE T2,"9" ; CHECK RET ;NOT A DIGIT SUBI T2,"0" ;CONVERT TO NUMBER IMULI T1,^D10 ;SHIFT ORIGINAL NUMBER ADD T1,T2 ;ADD IN CURRENT DIGIT JRST NMXN29 ;AND GET ANOTHER DIGIT SUBTTL Layers -- Main interface to layer levels ;NMXLAY - Call layer-level routine, to get/set value. ;CALL ; T1/ NMX Function Code ; T2/ NFWBLK - NMX Interface argument block ; T3/ Routine Index value from Parameter Table Entry (NTROU) ; NMXVAR/ NX block ; NT/ Pointer to STENT part of NT block ;Return ; RET ;on error, NXERR has code ; RETSKP ; ; NMXLAY: SETZRO NXNIL,+NMXVAR ;CLEAR THE "I DIDN'T DO ANYTHING" FLAG CAXGE T3,NMXMAX ;RANGE CHECK CAXGE T3,NMXMIN BUG.(CHK,NTMDVI,NTMAN,SOFT,,,< Cause: There will be a call to a "layer" to obtain or set a value for an item. The routine value in the descriptor block pointed to by NT is illegal. Action: Examine the data structure pointed to by NT. In all probability this is caused by a trashed NT, since the descriptor block generation macros are supposed to range check this value. Note: A "layer" is any routine described at NMXDSP. >,NTEMPE) CALLRET @NMXDSP(T3) ;CALL LAYER-LEVEL ROUTINE SUBTTL Events -- Interface layer / NMX (NMXEVT) ;NMXEVT is the interface routine between a layer and the event logger. ; ;Context: interrupt or scheduler level XRESCD ; ;Arguments: ; T1/ function code ; T2/ function dependent argument ; ;Returns (depends on function): ; +1 indicates that the function could not be successfully completed ; +2 success XRESCD NMXEVT: ;Verify the function code CAIL T1,EV.GEC ;Function code within range? CAILE T1,EV.SIG BUG.(CHK,NTMEFO,NTMAN,SOFT,,,< Cause: The event function supplied by a DECnet layer to NMXEVT was out of range. Action: Make callers of NMXEVT supply the correct function code >,RTN) ;Dispatch to appropriate routine CALLRET <-EV.GEC>+@[ ;Dispatch according to function code IFIW ;Get EC block IFIW ;Release EC block IFIW ;Filter an event IFIW ;Log an event IFIW ](T1) ;Log a signal SUBTTL Events -- NMXEVT -- EVGEC (Get EC block) ;EVGEC allocates an EC block ; ;Input: none ;Return: +1 if no memory, no EC block allocated ; +2 with T1/ address of EC block ;Resident... EVGEC: MOVX T1,EC.LEN ;Length of EC block CALLRET DNGWDZ ;Get chunk of zero words and propagate return ; from memory allocator SUBTTL Events -- NMXEVT -- EVREC (Release Ec block) ;EVREC releases an EC block ; ;Input: T2/ address of EC block ;Returns: +2 always ;Resident... EVREC: ;Unless ECCNT is non-zero (i.e. there is a NE block on queue pointing back ; to this EC block) it is OK to release the memory. In the case of ECCNT ; non-zero, the ECDEL bit is set to indicate to NTEVQ that the EC block ; should be deallocated when ECCNT goes to zero. MOVE T1,T2 ;T1 := ^EC OPSTR ,ECCNT,(T1) ;ECCNT greater than zero? IFSKP. ; -yes SETONE ECDEL,(T1) ; Set ECDEL flag ELSE. ; -no, all OK CALL DNFWDS ; Deallocate memory ENDIF. RETSKP SUBTTL Events -- NMXEVT -- EVFIL (Filter an event) ;EVFIL filters an event ; ;Input: T2/ event code in the following format: ; FIELD CCL,13 Event class ; FIELD CTY,5 Event type ; FILLER 18 ; ;Returns: +1 Event should be thrown away ; +2 Event should be logged ;Resident... EVFIL: SAVEAC MOVE P1,T2 ;P1 := event class and type LOAD T1,FACCL,+P1 ;Get event class CALL NTFFIL ;Find filter RET ; -not there, throw away event LOAD T2,FACTY,+P1 ;Get event type MOVX T3,1 ;Load a 1 into test word LSH T3,(T2) ; and shift into position TDNN T3,NMXFIL(T1) ;Is bit set in filter mask? RET ; -no, throw away RETSKP ;-yes, keep event ;NTFFIL - find index of event class in filter table (NMXFIL) ; ;Call with: T1/ event class ;Returns: +1/ did not find event class in table ; +2/ T1/ index of filter in table ; NTFFIL: ;Ac usage: T1/ event class, T2/ moving index SETZ T2, ;Start at index 0 in table DO. ;Loop over all event classes SKIPGE NMXFIL(T2) ; At end of list? RET ; -yes, return 'not found' HLRZ T3,NMXFIL(T2) ; Get low bound HRRZ T4,NMXFIL(T2) ; and high bound CAML T1,T3 ; Is event class in interval? CAMLE T1,T4 IFNSK. ; -no, step to next event class interval SUB T4,T3 ; Find out # of entries to step over ADDI T4,2 ; Dont forget the interval word ADD T2,T4 ; Add to current index LOOP. ; and loop back ELSE. ; -yes, in interval MOVE T4,T1 ; Calculate matching index SUB T4,T3 AOJ T4, ADD T4,T2 MOVE T1,T4 ; and put it in T1 EXIT. ; Exit DO loop to exit routine ENDIF. ENDDO. RETSKP ; Return 'found' SUBTTL Events -- NMXEVT -- EVLOG (Log an event) ;EVLOG logs an event ; ;Input: T2/ NE block ; Note: The NE block must contain a valid pointer to the EC block ; ;Returns: +2 always ;Resident... EVLOG: SAVEAC ;Ac usage: P1/ NE block, P2/ EC block MOVE P1,T2 ;P1 := ^NE LOAD P2,NEECP,(P1) ;P2 := ^EC CALL DNGTIM ;Get system time STOR T1,NETIM,(P1) ;Store for future conversion to julian time D36OFF ;Turn off interrupts CALL EVLOG1 ;Call coroutine that does the work IFNSK. ; No-skip means event lost; deallocate it D36ON ; First turn on interrupts MOVE T1,P1 ; Get ^NE CALL EVRNE ; Call EVRNE to release NE block RETSKP ; Always success return ENDIF. D36ON ;Skip means NE block now on queue MCALL (RG,MSEC1,PSIDVT) ;Give a PSI if someone wiating RETSKP ;EVLOG1 - EVLOG worker routine ; ;Called with D36OFF ; ;Input: ; P1/ ^NE block ; P2/ ^EC block ; ;Output: ; +1 lost event, deallocate it ; +2 do not deallocate event ; ;Local AC use: ; T4/ count of entries on queue EVLOG1: ; if ECLOS gtr 0 then lose_event JN ECLOS,(P2),EVLOGL ;If ECLOS non-zero, lose this one too ; if NMXECN = NMXELN then lose_event LOAD T4,QHCNT,+NMXEVQ ;Get current # of entries in queue CAIL T4,NMXELN ;Compare with max length of queue JRST EVLOGL ;Lose event ; if ECCNT geq ECMAX LOAD T1,ECCNT,(P2) OPSTR ,ECMAX,(P2) IFSKP. ; ... then SKIPE NMXELO ; if NMXELO = true JRST EVLOGL ; then lose event CALL EVLOGM ; else lose event and make lost event ELSE. ; ... else CAIE T4, ; if queue length = queue max - 1 IFSKP. ; then SKIPE NMXELO ; and NMXELO is false ANSKP. CALL EVLOGM ; lose event and make lost ENDIF. ENDIF. ;Queue NE block ENDQUE P1,NMXEVQ,NE.NXT,T1 ;Increment ECCNT INCR ECCNT,(P2) ;Return with queued block RETSKP ;EVLOG support routines ; ;Resident... ;EVLOGL - called to lose event and return EVLOGL: INCR ECLOS,(P2) ;Increment # of lost events RET ;No-skip to deallocate NE block ;EVLOGM - called to remake event to "lost event" ; The event will then be queued as an "ordinary event" EVLOGM: INCR ECLOS,(P2) ;Increment # of lost events SETZRO NECCL,(P1) ;Event class := 0 SETZRO NECTY,(P1) ;Event type := 0 SETONE NEETP,(P1) ;Entity type := no entity SETZRO NEDLN,(P1) ;Data length := 0 SETOM NMXELO ;And now is NMXELO true RET ;EVRNE - release NE block. Called on "lost event" or when event is copied ; to user (NTEVQ). ; ; T1/ ^NE block ;Resident... EVRNE: LOAD T2,NECBK,(T1) ;Get callback address SKIPN T2 ;Was one supplied? IFNSK. ; -no, use default CALLRET DNFWDS ; DECnet deallocator ELSE. CALL (T2) ; -yes, call users routine JFCL ; Ignore no-skip ENDIF. RET ;Return SUBTTL Events -- NMXEVT -- EVSIG (Log a signal) ;EVSIG signals an event ; ;Input: T2/ NE block ; ;Returns: +2 always ;Resident... EVSIG: SAVEAC ;Ac usage: P1/ NE block, P2/ EC block MOVE P1,T2 ;P1 := ^NE LOAD P2,NEECP,(P1) ;P2 := ^EC CALL DNGTIM ;Get system time STOR T1,NETIM,(P1) ;Store for future conversion to julian time ;Turn off interrupts D36OFF ;Verify that there is room in the signal queue LOAD T1,QHCNT,+NMXSIQ ;Get current count CAIL T1,NMXSLN ; and compare with max allowed BUG.(INF,NTMSQF,NTMAN,SOFT,,,< Cause: The signal queue was full when a new signal was logged. This might be caused by a malfunctioning NMLT20 that does not read the signals from the signal queue, or it may be caused by a DECnet device driver going bad. A signal is used to tell NMLT20 that a device needs attention/reload. Action: Restart NMLT20, or turn off malfunctioning DECnet device. If necessary, reload any devices by hand >,EVSIG2) ;If no BUGCHK, come here and insert event into signal queue ENDQUE P1,NMXSIQ,NE.NXT,T1 EVSIG1: D36ON ;Turn on interrupts MCALL (RG,MSEC1,PSIDVT) ;Give a PSI if someone waiting RETSKP EVSIG2: D36ON ;Turn on interrupts MOVE T1,P1 ;Get pointer to NE block CALL EVRNE ;Release NE block RETSKP ;End of resident code XSWAPCD IFN FTDEBUG < SUBTTL Events -- .NTTEV function (Test event logger) ;Called from NMXDIS ;The .NTTEV function tests the event logger and uses the ET structure NTTEV: SAVEAC ; P1/ ^NE block, P2/ ^EC block, MS/ ^ET block, MB/ count of events to do ;Get ET block MOVX T1,ET.LEN CALL DNGWDZ ERRRET NTERES MOVE MS,T1 ;Copy from user argument block to our ET block ; ;T1/ ^user argument ;T2/ rolling index UMOVE T1,1 UMOVE T1,.NTSEL(T1) SETZ T2, DO. CAIL T2,ET.LEN ;Through copying? EXIT. ; -yes,exit MOVE T3,T1 ADD T3,T2 UMOVE T4,(T3) ;Get user word ERJMP [ MOVE T1,MS ;On illegal read, return MS block CALL DNFWDS ERRRET NTEADC ;Give "address check" ] MOVE T3,MS ADD T3,T2 MOVEM T4,(T3) ;Store in ET block AOJ T2, LOOP. ENDDO. LOAD MB,ETCNT,(MS) ;Get count of events to do ;Get EC block MOVX T1,EV.GEC ;Get EC block CALL NMXEVT IFNSK. MOVE T1,MS CALL DNFWDS ERRRET NTERES ENDIF. MOVE P2,T1 MOVX T1,2 ;Allow 2 events on queue STOR T1,ECMAX,(P2) ;Get NE block NEGET: MOVX T1,NE.LEN ADDI T1,<44/4> ;Add data string CALL DNGWDZ IFNSK. MOVX T1,EV.REC ;Release EC block MOVE T2,P2 CALL NMXEVT JFCL MOVE T1,MS CALL DNFWDS ERRRET NTERES ENDIF. MOVE P1,T1 ;P1 := ^NE ;At this point all blocks are allocated, and the user arguments have been ; copied to our ET block ;Copy data to NE block STOR P2,NEECP,(P1) ;Store EC pointer LOAD T1,ETCCL,(MS) ;Get event class STOR T1,NECCL,(P1) LOAD T1,ETCTY,(MS) ;Get event type STOR T1,NECTY,(P1) LOAD T1,NXENT,+NMXVAR ;Get entity type STOR T1,NEETP,(P1) LOAD T1,NXNUM,+NMXVAR ;Get entity ID STOR T1,NEEID,(P1) LOAD T1,ETDLN,(MS) ;Get data length STOR T1,NEDLN,(P1) XMOVEI T1,NE.DAT(P1) ;Get address of data string AOJ T1, STOR T1,NEDAT,(P1) ;Copy the string also LOAD T1,ETDLN,(MS) ;Get string length ife ftki10,< MOVSI T2,(POINT 8,0) ;Byte pointer TDO T2,[1B12] ;Make it global... XMOVEI T3,ET.DAT(MS) ;Get source address DMOVE T4,T1 ;Duplicate T1-T2 LOAD T6,NEDAT,(P1) ;Get destination address EXTEND T1,[MOVSLJ] ;"Move string left justified" JFCL ;Ignore error >;julgransprocessor ifn ftki10,< movei t2,et.dat(ms) ;Get source address. hrli t2,(point 8,0) ;Make it a byte pointer. load t3,nedat,(p1) ;Get destination address. hrli t3,(point 8,0) ;Make it a byte pointer. jumple t1,.+4 ;Copy the string with a simple-minded loop. ildb cx,t2 idpb cx,t3 sojg t1,.-2 >;ki10 ;Now log or signal the event MOVX T1,EV.SIG ;Assume signal OPSTR ,ETSIG,(MS) IFSKP. ;No, it was "ordinary" event SETZ T2, ;Clear word to receive argument LOAD T1,NECCL,(P1) ;Get event class STOR T1,FACCL,+T2 LOAD T1,NECTY,(P1) ;Get event type STOR T1,FACTY,+T2 MOVX T1,EV.FIL ;Filter the event CALL NMXEVT IFNSK. ;Throw away this event MOVE T1,P1 CALL DNFWDS ;Release NE block ELSE. MOVX T1,EV.LOG ;Log event MOVE T2,P1 CALL NMXEVT JFCL ENDIF. ELSE. MOVE T2,P1 CALL NMXEVT JFCL ENDIF. ;Check count SOJG MB,NEGET ;More to do? ;No, deallocate EC and ET blocks MOVX T1,EV.REC MOVE T2,P2 CALL NMXEVT JFCL ;And ET block too MOVE T1,MS CALL DNFWDS ;Everything done, return success RETSKP > SUBTTL Events -- .NTSLM function (Set global logging mask) ;Called from NMXDIS ;The .NTSLM function sets/changes the global logging masks in NTMAN. ;The event class to set is in word .NTSEL, and the new filter in word .NTQUA. NTSLM: SAVEAC UMOVE P1,1 ;P1 := user ^argblk UMOVE T1,.NTSEL(P1) ;Get event class CALL NTFFIL ;Find the filter ERRRET NTEPNA ;Say 'parameter not applicable' ;Index of matching entry is now in T1 UMOVE T2,.NTQUA(P1) ;Get event filter TXZ T2,17B3 ;Clear bits 0-3 (BLISS bits 33-36) MOVEM T2,NMXFIL(T1) ;Store new filter RETSKP ;Give success return SUBTTL Events -- .NTPSI function (Set event PSI channel) ;Called from NMXDIS ;The .NTPSI sets the PSI channel for "events available" interrupts. TOPS-10 ; uses another mechanism to set event interrupts, so the following routine is ; Tops-20 only. ; ; The PSI channel is in word .NTSEL NTPSI: IFN FTOPS10, ;NOT IN TOPS10 IFN FTOPS20,< SKIPN T1,EVRFRK ;SOMEONE ALREADY DOING THIS? IFSKP. HRRZS T1 ;YES, GET HIS ID CAME T1,FORKX ;IS HE RESETTING? S1XCT ;Return "Event facility already in use" ENDIF. LOAD T1,NXSEL,+NMXVAR ;Get users PSI channel from .NTSEL CAME T1,[-1] ;DOES HE STILL WANT TO BE NOTIFIED? IFSKP. SETZM EVRFRK ;NO, NO MORE EVENT READER ELSE. CAIL T1,0 ;YES, CHECK FOR CAILE T1,^D36 ; LEGAL PSI CHANNEL ERRRET NTEMPE ; -not legal, give 'management program error' AOS T1 ;FIX IT FOR INTERNAL USE HRLM T1,EVRFRK ;SET IT UP MOVE T1,FORKX ;GET USER HRRM T1,EVRFRK ;SET IT UP SKIPE NMXEVQ ;IS THERE ANYTHING IN THE QUEUE ? CALL NMLEVT ;YES. GIVE INTERRUPT. ENDIF. RETSKP ;KILL THE EVENT READER (CALLED FROM .RESET AND KSELF) ;RETURNS: +1 ;Resident ? (To be checked in future/GL) XRESCD XRENT EVRKIL HRRZ T1,EVRFRK ;GET THE EVENT LOGGER CAMN T1,FORKX ;IS IT US? SETZM EVRFRK ;YES, NO MORE EVENT READER RET ;NO, NOTHING TO DO ;GIVE THE EVENT READER A PSI ;CALLED FROM LV8CHK ;This must be resident XRESCD NMLEVT: SETZM NMLPSI ;CLEAR THE FLAG HLRZ T1,EVRFRK ;GET PSI CHANNEL JUMPE T1,RTN ;IF THERE IS ONE. SOS T1 ;THERE IS. MAKE IT REAL. HRRZ T2,EVRFRK ;GET EVENT READER FORK XCALLRET (MSEC1,PSIRQ) ;LET HIM KNOW ;ASSERT EVENT PSI FOR SCHEDULER TO CATCH ;MAY BE CALLED AT ANY LEVEL. ;CALL PSIDVT ;RETURNS +1 ALWAYS XRESCD ;MUST BE RESIDENT PSIDVT: SETOM NMLPSI ;SET FLAG FOR SCHEDULER. RET ;No more resident code XSWAPCD >;END IFN FTOPS20 SUBTTL Events -- .NTEVQ function (Pass queued event to user) ;Called from NMXDIS ;Writes next event to user buffer. If there are no events on queue, ; a zero length is indicated to the user. ;Must be resident since D36OFF is done XRESCD NTEVQ: SAVEAC ;Ac usage: P2/ ^NE block ;Turn off interrupts and call routine to get next event. D36OFF CALL NTEVQN ;Pull next event off queues IFNSK. ;No-skip indicates no event on queue D36ON ; Turn on interrupts RETSKP ; Do success return, higher layer will write ENDIF. ; 0 into the "number of bytes returned" field D36ON ;Turn on interrupts on success return JRST NTEVQ1 ;Proceed in swappable code XSWAPCD ;Come here with T1/ ^NE block NTEVQ1: MOVE P2,T1 ;P2 := ^NE ;Now "build" a NQ block in the users buffer, i.e. ; B:2 event class and type ; 3*B:2 julian day, second and millisecond ; B:2 entity type ; B:n entity ID ; B:m m bytes of event data ;Event class and type LOAD T1,NECCL,(P2) ;Get event class ASH T1,6 ;Shift over to make room for type OPSTR ,NECTY,(P2) ;Or in event type CALL PUT2BT ;Put to user RET ;error... ;Julian day, second and millisecond LOAD T1,NETIM,(P2) ;Get system time stored STKVAR ;Two local variables CALL NMXTIM ;Convert to julian time MOVEM T2,SEC ;Save julian seconds MOVEM T3,MSC ;Save julian milliseconds CALL PUT2BT ;Put julian 1/2day to user RET ;error... MOVE T1,SEC CALL PUT2BT ;Put julian seconds to user RET ;error... MOVE T1,MSC CALL PUT2BT ;Put julian milliseconds to user RET ;error... ;Now put entity type and entity ID LOADE T1,NEETP,(P2) ;Get entity type CALL PUTBYT ;Put to user RET ;error... LOADE T1,NEETP,(P2) ;Get entity type again CAXE T1,.NTNOD ;Is it node? IFSKP. ; -yes LOAD T1,NEEID,(P2) ; Get entity ID (node number) CALL PUT2BT ; Put # in user buffer RET ;error... SETZ T1, ; Zero length node name CALL PUTBYT ; Put length byte to user RET ;error... ELSE. ; -no, not node entity CAXE T1,.NTCKT ; Is it circuit CAXN T1,.NTLIN ; or a line? IFNSK. ; -yes, it was LOAD T1,NEEID,(P2) ; Get entity ID MOVE T2,[POINT 8,NX.VAL+NMXVAR] ;Where to store circuit/line string CALL NMXC2N ; Convert id to a name JRST NTEMPE ; Error! XMOVEI P1,NX.VAL+NMXVAR ; Load pointer to string containing name CALL PUTSTR ; Copy string to user space RET ;error... ELSE. ; -not circuit or line ID AOJ T1, ; Maybe 'NO ENTITY' (elevenish -1) TRNE T1,<<377_8>+377> ; Is it? BUG.(CHK,NTMORE,NTMAN,SOFT,,,< Cause: An event was received from a DECnet layer, and the entity type is not legal. Action: Find the routine that logged the event, and change it to a legal entity type. >,NTEMPE) ENDIF. ENDIF. ;Now copy data string to user buffer SAVEAC LOAD NT,NEDLN,(P2) ;Count in NT LOAD MB,NEDAT,(P2) ;Address of string to MB MOVE P1,[POINT 8,(MB)] ;Do it this way to get intersection copy DO. SOSGE NT ;Any more bytes? EXIT. ; -no ILDB T1,P1 ;Get next byte CALL PUTBYT ; and give it to user RET ;error... LOOP. ENDDO. ;Now the NE block has been copied to the user buffer, deallocate the NE block ; and then return successfully MOVE T1,P2 ;EVRNE wants pointer in T1 CALL EVRNE RETSKP ;NTEVQN - extract next event from queue ; ;Called with D36OFF, so must be resident XRESCD ; ;Returns: +1 No events on queue ; +2 T1/ ^NE block NTEVQN: SAVEAC ;P1/ ^NE block, P2/ ^EC block ;Try dequeue an event from the signal queue DEQUE T1,NMXSIQ,NE.NXT,NTEVQM ;Dequeue into T1 RETSKP ;Success, return ;NTEVQM - try to extract event from the event queue NTEVQM: DEQUE P1,NMXEVQ,NE.NXT,RTN ;Just return if nothing available ;Come here with P1/ ^NE block LOAD P2,NEECP,(P1) ;P2 := ^EC ;Is this an events lost? LOAD T1,NECCL,(P1) ;Get event class LOAD T2,NECTY,(P1) ; and event type SKIPN T1 ;Is event class = 0 SKIPE T2 ; and event type = 0 SKIPA ; -no, skip next instruction SETZM NMXELO ; -yes, flag no "events lost" on queue any more ;Decrement ECCNT by one; and if it went to zero there may be things to do DECR ECCNT,(P2) OPSTR ,ECCNT,(P2) ;Did it go to zero? IFSKP. ; -yes ;Code may go here to generated "events were lost event" ; SETZRO ECLOS,(P2) ;No more lost events now ;If ECDEL is set, then deallocate the EC block OPSTR ,ECDEL,(P2) ;Set? IFSKP. ; -yes MOVE T2,P2 CALL EVREC JFCL ENDIF. ENDIF. ;Put NE address in T1, and return skip to indicate that there was an event MOVE T1,P1 RETSKP ;End of resident code XSWAPCD SUBTTL User strings -- Write parameter with nice ;NMXWTY - Write a parameter to the user data string, including NICE ; headers such as DATA ID and DATA TYPE ;Call ; NT/ Pointer to STENT part of NT block ; NXVAL,+NMXVAR/ Value obtained from NMXLAY ; ;Return ; RET ;On error, NXERR has error code ; RETSKP ;when done, maybe with stuff in user string ; NMXWTY: JN NXNIL,+NMXVAR,RSKP ;If Layer didn't know about him, ignore it. JE NXWUS,+NMXVAR,RSKP ;IF NOT WRITING TO THE USER, RETURN SETZ T1, ;START OFF WITH A CLEAN HEADER DUO-BYTE LOAD T2,NTSEQ,(NT) ;GET SEQUENCE NUMBER OF PARAMETER IOR T1,T2 ;OR INTO HEADER DUO-BYTE CALL PUT2BT ;PUT 2 BYTES OF HEADER INTO USER DATA STRING RET ;error... NMXWT3: LOAD T1,NTTYP,(NT) ;GET DATA TYPE OF THIS PARAMETER CAXL T1,NT.FC ;IS IT LESSER THAN SIMPLE CODED? CAXLE T1,NT.FCN ;OR GREATER THAN ASCII CIRCUIT NAME? BUG.(CHK,NTMFOR,NTMAN,SOFT,,,< Cause: While formatting output for a show, the format block for this item has been found to have an illegal format type. >,NTEMPE) CALLRET @.+1-NT.FC(T1) IFIW ;ORDINARY CODED. HANDLE AS INTEGER IFIW ;CODED MULTIPLE IS HANDLED AT ANOTHER LEVEL IFIW ;ASCII IMAGE. HANDLED AT ANOTHER LEVEL IFIW ;DECIMAL UNSIGNED IFIW ;DECIMAL SIGNED. IFIW ;HEXADECIMAL INTEGER. IFIW ;HEX IMAGE. BYTE STRING IFIW ;OCTAL IFIW ;MILLISECONDS IFIW ;VERSION NUMBER IFIW ;NODE ENTITY ID IFIW ;NODE NAME IFIW ;WRITE CIRCUIT NAME SUBTTL User strings -- Write coded data ;NMXWCD - Write coded info to user data string ;Call ; NT/ Pointer to format block ;Return ; RET ;Error, code is in NXERR ; RETSKP ;data type byte and data are in user string ; NMXWCD: SAVEAC ;GET SOME WORK AREA LOAD T1,NTLEN,(NT) ;GET SIZE OF FIELD CAIE T1,1 ;WE ONLY HAVE SINGLE BYTE CODEDS. (**HACK**) BUG.(CHK,NTMBCF,NTMAN,SOFT,,,< Cause: Output for a SHOW is being formatted, and there has been a request to generate a CODED field of more than one byte. This can't be done. Action: Look at the descriptor block pointed to by NT. Check to see if this item is supposed to be a multiple byte coded. If not, fix the item's entry. If it is correct, you are going to have to write the code to handle multiple byte codeds. >,NTEMPE) TXO T1,NT.CNM ;INDICATE CODED NON MULTIPLE (PP 148 OF NM) CALL PUTBYT ;DEPOSIT DATA TYPE BYTE IN USER STRING RET ;error LOAD T1,NFBUF,+NFWBLK ;GET THE CODED VALUE TO OUTPUT CALLRET PUTBYT ;PUT THE BYTE IN THE OUTPUT STRING, AND RETURN SUBTTL User strings -- Write ascii image data ;NMXWNN - Write ASCII image Node Name data to user data string ;Call ; NT/ Pointer to format block ; NF.BUF contains sixbit node name ;Return ; RET ;Error, code is in NXERR ; RETSKP ;Data type byte and data are in user string NMXWNN: SAVEAC MOVX T1,NT.AI ;Non-coded, ASCII image data CALL PUTBYT ;Store data type byte RET ; -error MOVE P1,[POINT 6,NF.BUF+NFWBLK] ;Byte pointer to stringid with value ;Make a first pass over sixbit string since we need the count first MOVE T1,P1 ;Get byte pointer MOVEI T2,6 ;Max 6 chars in a node name DO. ;LOOP ILDB T3,T1 ; Get next byte SKIPE T3 ; Empty? SOJG T2,TOP. ; or out of bytes? ENDDO. ; - yes, come here with T1 = remaining bytes MOVEI T1,6 ;Get max # of bytes again SUB T1,T2 ; and get # of bytes to write MOVE P2,T1 ;Remember # of bytes to write CALL PUTBYT ;Output that RET ; -error DO. ;LOOP again SOSGE P2 ; Any more bytes to do? EXIT. ; -no, all done ILDB T1,P1 ; Get byte ADDI T1,^O40 ; and make ASCII CALL PUTBYT ; Dump it to user RET ; -error LOOP. ; And go back ENDDO. RETSKP NMXWCN: SAVEAC ;GET SOME WORK AREA LOAD T1,NFBUF,+NFWBLK ;Get the returned Circuit/Line Id word MOVE T2,[POINT 8,NX.VAL+NMXVAR] ;A temporary place to write CN CALL NMXC2N ;Convert Circuit Id to Name JRST NTEMPE ;Weird error!!!!!!!!!!!!! MOVX T1,NT.AI ;NON-CODED, ASCII IMAGE DATA CALL PUTBYT ;STORE DATA TYPE BYTE RET ;error MOVE P1,[POINT 8,NX.VAL+NMXVAR] ;BYTE POINTER TO STRINGID WITH VALUE ILDB T1,P1 ;GET FIRST BYTE, WHICH IS SIZE MOVE P2,T1 ;COPY SIZE, TO COUNT DOWN BYTES NMXWC2: CALL PUTBYT ;PUT IT IN USER DATA STRING RET ILDB T1,P1 ;GET NEXT BYTE SOJGE P2,NMXWC2 ;DECREMENT COUNT, IF ANY BYTES LEFT, DO THEM RETSKP ;DO A GOOD RETURN SUBTTL User strings -- Write hexidecimal image data ;NMXWHI - Write HEXIDECIMAL image data to user data string ;Call ; NT/ Pointer to format block ; NFWBLK/ Argument Block returned from Layer ; NFBPT/ Byte pointer to start of Hexidecimal number ; NFBYT/ number of bytes in number ;Return ; RET ;Error, code is in NXERR ; RETSKP ;data type byte and data are in user string NMXWHI: SAVEAC ;GET HOME WORK AREA MOVX T1,NT.HI ;NON-CODED, HEXIDECIMAL IMAGE DATA CALL PUTBYT ;STORE DATA TYPE BYTE RET ;Error return LOAD P3,NFBUF,+NFWBLK ;Get the buffer address into P1 MOVE P1,[POINT 8,(P3)] ;Point at the buffer. MOVEI P2,6 ;Get the number of bytes in the number MOVE T1,P2 ;copy size and... NMXWH2: CALL PUTBYT ;PUT IT IN USER DATA STRING RET ILDB T1,P1 ;GET NEXT BYTE SOJGE P2,NMXWH2 ;DECREMENT COUNT, IF ANY BYTES LEFT, DO THEM RETSKP ;DO A GOOD RETURN SUBTTL User strings -- Write numeric data ;NMXWNU - Write a numeric value to the user data string ;CALL ; NMXVAR/ NX block ; NT/ Pointer to STENT part of NT block ; NFBUF,+NFWBLK/ Integer to deposit ;RETURN ; RET ;On error, NXERR contains code ; RETSKP ;Integer has been placed in data string ; NMXWNU: LOAD T2,NTLEN,(NT) ;GET LENGTH IN BYTES OF THIS NUMBER LOAD T1,NTTYP,(NT) ;GET FORMAT OF THIS NUMBER CAXL T1,NT.FDU ;MAKE SURE THIS IS IN NUMERIC RANGE CAXLE T1,NT.FOC ;BETWEEN DECIMAL UNSIGNED AND OCTAL. BUG.(CHK,NTMINT,NTMAN,SOFT,,,< Cause: When generating output for a numeric field, something other than Decimal, Hexadecimal or Octal was requested. >,NTEMPE) MOVE T1,<-NT.FDU>+[ ;GET NICE TYPE. 0_3 ;DECIMAL UNSIGNED IS FORMAT 0 1_3 ;DECIMAL SIGNED IS FORMAT 1 2_3 ;HEXADECIMAL NUMBER IS FORMAT 2 -1 ;HEX IMAGE DOESN'T COME HERE. 3_3](T1) ;OCTAL NUMBER IS FORMAT 3 IOR T1,T2 ;OR IN SIZE OF FIELD CALL PUTBYT ;PUT THIS BYTE IN USER DATA AS DATA TYPE RET NMXWCO: LOAD T2,NTLEN,(NT) ;GET NUMBER OF BYTES FOR COUNTER AGAIN LOAD T1,NFBUF,+NFWBLK ;GET VALUE TO RETURN CAXL T2,1 ;MUST BE AT LEAST ONE BYTE CAXLE T2,4 ;MAY BE AT MOST 4 BYTES NMXWCE: BUG.(CHK,NTMBDL,NTMAN,SOFT,,,< Cause: While generating output for a numeric field, there has been a request to generate an illegal number of bytes. >,NTEMPE) CALLRET @.(T2) IFIW ;PUT A SINGLE BYTE IFIW ;PUT A DUO BYTE IFIW ;DO THREE BYTES. ILLEGAL IFIW ;4 BYTES. SUBTTL Write out NSP or Routing Version numbers ;NMXWVN - Write out NSP or Routing Version numbers ; NMXWVN: SAVEAC ;We are going to put the Version # word here MOVX T1,NT.CM3 ;Going to build a CM-3 Data Type Field CALL PUTBYT ;Put it into the string RET ;Error MOVX T1,NT.DU1 ;Now we are building a DU-1 header CALL PUTBYT ;Put it into the string RET LOAD P1,NFBUF,+NFWBLK ;Get the value from the Argument Block LOAD T1,VNVER,+P1 ;Get the Version number CALL PUTBYT RET MOVX T1,NT.DU1 ;Now we are building a DU-1 header CALL PUTBYT ;Put it into the string RET LOAD T1,VNECO,+P1 ;Get the ECO number CALL PUTBYT RET MOVX T1,NT.DU1 ;Now we are building a DU-1 header CALL PUTBYT ;Put it into the string RET LOAD T1,VNUCO,+P1 ;And finally the User ECO number CALLRET PUTBYT ;Write out that byte and we are done SUBTTL Write out Node Entity Id ;NMXWNE - We come here to write out the value of parameters which are ; Node Ids, such as ADJACENT NODE, DESIGNATED ROUTER, ect... ; We have already received the Node Address part of the parameter ; from the Routing Layer. Before we write out anything to the ; user buffer, we will check to see if there is enough room in the ; buffer for the entire node entity (assuming a six character name). ; If not we give up right away, subtract two from the byte count, ; because the parameter nmuber has already been stored, and report ; a resource error. Then, we will try to get a Node Name from Session ; Control. We will then write out a Coded Multiple entry, ; depending on what we have. NMXWNE: SAVEAC ; JE NFBFF,+NFWBLK,ONENDE ;If no buffer, Write one Node Entity LOAD P2,NFBLN,+NFWBLK ;Get the number of entity Ids in buffer JUMPE P2,RSKP ;If none, then return skip LOAD P1,NFBUF,+NFWBLK ;Get the buffer address NMXWN1: MOVE T1,(P1) ;Put the Node Number into P1 CALL WRTNDE ;Write out the Node Id to user buffer RET ;Error return AOJ P1, ;Update the buffer pointer SOSG P2 ;Skip if more node numbers in buffer RETSKP LOAD T1,NTSEQ,(NT) ;Get the Parameter Number again CALL PUT2BT ;Need to put it into user buffer for each RET ;entry JRST NMXWN1 ;Loop until done. ONENDE: LOAD T1,NFBUF,+NFWBLK ;Get the node number into T1 CALL WRTNDE ;Write out the Node Id to user buffer RET ;Error return RETSKP ; ; Write Out a Node Entity Id to the user Buffer ;CALL ; T1/ Node Number ; ; WRTNDE: SAVEAC ; MOVE P1,T1 ;Get the Node Address CALL GETNDN ;Try to get Node Name from SCLINK JRST NONAME ;No name mapped in SCLINK CALL NMXS2A ;Convert SIXBIT name to ASCII, store it MOVX T1,NT.CM2 ;Get the CM-2 header CALL PUTBYT RET MOVX T1,NT.DU2 ;Get the DU-2 Header byte CALL PUTBYT ; RET MOVE T1,P1 ;Get the Node address back CALL PUT2BT ;Put it into the User string RET MOVX T1,NT.AI ;Get the AI-6 header byte CALL PUTBYT ; RET XMOVEI P1,NX.VAL+NMXVAR ;Get address of ASCII Image string CALL PUTSTR ;Write it to the user buffer RET RETSKP NONAME: MOVX T1,NT.CM1 ;Get the CM-1 header CALL PUTBYT RET MOVX T1,NT.DU2 ;Get the DU-2 Header byte CALL PUTBYT ; RET MOVE T1,P1 ;Get the Node address back CALL PUT2BT ;Put it into the User string RET RETSKP GETNDN: TRVAR <> ;Need a brand new Argument Block here SETZM NFNBLK ;CLEAN FIRST WORD OF BLOCK HRRI T2,1+NFNBLK ;GET POINTER TO SECOND WORD IN BLOCK HRLI T2,NFNBLK ;POINT AT START OF BLOCK BLT T2,NF.LST-1+NFNBLK ;CLEAN UNTIL END OF BLOCK STOR T1,NFEID,+NFNBLK ;Store the node number back into the block MOVX T1,.NTNOD ;We need the Entity Type (Node) STOR T1,NFETY,+NFNBLK ;Store the Entity Type MOVX T1,NF.A2N ;Function code into T1 XMOVEI T2,NFNBLK ;Argument Block CALL SCLNMX ;Map Node address into Node Name RET LOAD T1,NFBUF,+NFNBLK ;Get the node name into T1 RETSKP SUBTTL User strings -- Read a number from user ;NMXRNU - Read an integer from data string, and put into NXVAL ; NMXRNU: LOAD T1,NTLEN,(NT) ;GET SIZE OF FIELD CALL NMXRBY ;READ BYTES RET ;error JUMPE T1,NTEIPV ;ILLEGAL TO SET QUANTITY TO ZERO STOR T1,NFBUF,+NFWBLK ;SAVE VALUE IN NF BLOCK SETZRO NFBFF,+NFWBLK ;And Flag that there is no buffer RETSKP ;RETURN SUCCESS NMXRNC: LOAD T1,NTLEN,(NT) ;GET SIZE OF CODED FIELD CALL NMXRBY ;READ BYTES RET ;Error STOR T1,NFBUF,+NFWBLK ;SAVE VALUE IN NF BLOCK SETZRO NFBFF,+NFWBLK ;And Flag that there is no buffer RETSKP NMXRCN: CALL GETSTR ;Go read the string into Monitor Core RET ;error MOVE T1,[POINT 8,NX.VAL+NMXVAR] ;Pointer to beginging of circuit name CALL NMXN2C ;Convert Name to Line ID RET ;error STOR T1,NFBUF,+NFWBLK ;Put Line ID into the NF Block SETZRO NFBFF,+NFWBLK ;No buffer being used RETSKP NMXRNN: CALL GETSTR ;Go read the string into Monitor Core RET ;error SETZ T1 ;Start off with a clear Node Name MOVE T4,[POINT 6,NF.BUF+NFWBLK] ;Destination Byte Pointer for SIXBIT name MOVE T3,[POINT 8,NX.VAL+NMXVAR] ;Pointer to String Containing name ILDB T2,T3 ;Get Number of bytes in Node Name JUMPLE T2,NTEIPV ;No Name, return error... CAXLE T2,MXNNLN ;Make sure name is not longer than six JRST NTEIPV ;Error... NMXRN2: ILDB T5,T3 ;GET A BYTE FROM THE NODE NAME STRINGID CAIL T5,^O140 ;IS IT LOWER CASE SUBI T5,^O40 ;MAKE IT UPPER CASE SUBI T5,^O40 ;MAKE IT SIXBIT IDPB T5,T4 ;STORE IT IN THE SIXBIT NODE NAME SOJG T2,NMXRN2 ;LOOP UNTIL ENTIRE NAME COPIED. SETZRO NFBFF,+NFWBLK ;Make sure Layer knows that is no buffer RETSKP NMXRHI: SAVEAC MOVX T1,FHIBLK ;Get the size of the Buffer we need STOR T1,NFBLN,+NFWBLK ;Put it into the argument block CALL DNGWDS ;Go allocate the block ERRRET NTERES ;No memory available, resource error MOVE P1,T1 ;Put buffer address into P1 STOR T1,NFBUF,+NFWBLK ;Put the buffer addr into the arg block SETONE NFBFF,+NFWBLK ;And tell Layer to expect a buffer CALL GETSTR ;Go read the string into Monitor Core RET ;error MOVE T1,[POINT 8,NX.VAL+NMXVAR] ;Pointer to beginging of Hex String MOVE T2,[POINT 8,(P1)] ;Pointer to Buffer to go to DECnet Layer STOR T2,NFBPT,+NFWBLK ;Save Virgin Pointer for the DECnet Layer ILDB T3,T1 ;Get the Length of the string JUMPLE T3,NTEIPV ;Negative or zero, Invalid Parameter Value CAXLE T3,MXHILN ;And it must be less than or equal to 6 JRST NTEIPV ;error STOR T3,NFBYT,+NFWBLK ;Send the number of bytes to the DECnet Layer NMXRH1: ILDB T4,T1 ;Get a byte from user IDPB T4,T2 ;Put it into Buffer SOJG T3,NMXRH1 ;Loop until entire string is copied RETSKP ; I have commented out this routine (except for RETSKP) because ; there are currently NO Decimal Signed Parameters maintained ; by DECnet Layers in the Monitor. ; NMXRNS: ; LOAD T1,NTLEN,(NT) ;GET SIZE OF FIELD ; CALL NMXRBY ;READ THE BYTES ; RET ;Error ; JUMPE T1,NTEIPV ;ZERO IS AN ILLEGAL NUMBER ; LOAD T2,NTLEN,(NT) ;GET SIZE AGAIN ; IMULI T2,^D8 ;CONVERT TO NUMBER OF BITS ; SETO T3, ;POSSIBLE SIGN EXTENSION ; ASH T3,(T2) ;SHIFT TO BECOME ONLY THE SIGN BITS ; TDNE T3,T1 ;IS THE SIGN BIT ON? ; IOR T1,T3 ;YES, TURN ON ALL THE SIGN BITS ; STOR T1,NFBUF,+NFWBLK ;SAVE VALUE IN NF BLOCK ; SETZRO NFBFF,+NFWBLK ;And Flag that there is no buffer RETSKP NMXRBY: CAXL T1,1 ;RANGE CHECK NUMBER OF BYTES TO READ CAXLE T1,4 ;TO ENSURE ONLY 1,2, AND 4 NMXRBE: BUG.(CHK,NTMILN,NTMAN,SOFT,,,< Cause: When going to read a numeric value from the user's string, the format descriptor block for this item has specified an illegal number of bytes to read. >,NTEMPE) CALLRET @.(T1) ;DISPATCH IFIW ;GET A SINGLE BYTE IFIW ;GET 2 BYTES OF INTEGER IFIW ; IFIW ;GET 4 BYTES SUBTTL User strings -- Read and write milliseconds ;NMXWNM - Write milliseconds ;Call ; NMXVAR/ NX block ; NT/ Pointer to NT begstr ;Return ; see NMXWNU NMXWNM: LOAD T1,NFBUF,+NFWBLK ;GET VALUE WE ARE GOING TO WRITE OUT IDIVI T1,TIMBAS ;CONVERT TO SECONDS STOR T1,NFBUF,+NFWBLK ;PUT BACK WHERE IT CAME FROM LOAD T1,NTLEN,(NT) ;GET THE LENGTH WE ARE GOING TO STORE ; IOR T1,0_3 ;NICE CODE INDICATING DECIMAL UNSIGNED CALL PUTBYT ;PUT THE NICE HEADER IN RET ;error... JRST NMXWCO ;AND JOIN COMMON CODE ;NMXRNM - Read seconds, store milliseconds ;Call ; NMXVAR/ NX block ; NT/ Pointer to NT begstr NMXRNM: CALL NMXRNU ;READ THE NUMBER AS DECIMAL UNSIGNED RET ;error... MOVX T1,TIMBAS ;CONVERSION FACTOR OPSTRM ,NFBUF,+NFWBLK ;CONVERT TO MILLISECONDS RETSKP ;AND RETURN SUCCESSFULLY SUBTTL User strings -- Copy STRINGID from user to exec ;GETSTR - Copy a number of bytes (String) to a place in monitor core. ;Call ; NMXVAR/ NX block ;Return ; Non-skip on address check, error already in NXERR ; Skip if successfull, string starting at NXVAL GETSTR: XMOVEI T1,NX.DAT+NMXVAR ;GET POINTER TO DATA BP BLOCK JRST GETST0 ;JUMP INTO MAIN CODE GETSTI: XMOVEI T1,NX.EID+NMXVAR ;GET POINTER TO ENITITY ID BP BLOCK GETST0: SAVEAC ;SAVE SOME DATA ACS MOVE P2,T1 ;SAVE POINTER MOVE P1,[POINT 8,NX.VAL+NMXVAR] ;PUT STRING IN VALUE PART OF NX MOVE T2,P2 ;GET POINTER TO BP BLOCK CALL DNGUBT ;GET A SINGLE BYTE RET ;error... IDPB T1,P1 ;PUT BYTE AWAY IN DESTINATION STRING CAXLE T1,^D32 ;WILL THIS STRING FIT IN NXVAL? ERRRET NTEPVL ;NOPE. PARAMETER TOO LONG MOVE NT,T1 ;SAVE NUMBER OF BYTES TO DO GETST1: SOJL NT,RSKP ;AT END, RETURN SUCCESS MOVE T2,P2 ;GET POINTER TO BP BLOCK CALL DNGUBT ;GET A BYTE RET ;error... IDPB T1,P1 ;PUT BYTE AWAY. JRST GETST1 ;DO ANOTHER BYTE SUBTTL User strings -- Copy STRINGID from exec to user ;PUTSTR - Copy string from exec space to user data string ;Call ; P1/ Full word pointer to stringid in exec space ;Return ; RET on address check ; RETSKP with string in user address space PUTSTR: SAVEAC ;SAVE AN AC FOR BYTE COUNT MOVX P2, ;MAKE AN 8-BIT BYTEPOINTER TO STRING ILDB T1,P2 ;GET BYTE COUNT (FIRST BYTE) MOVE NT,T1 ;SAVE BYTE COUNT FOR LATER CALL PUTBYT ;PUT BYTE IN USER'S OUTPUT STRING RET ;error... PUTST1: SOJL NT,RSKP ;RETURN WHEN DONE ILDB T1,P2 ;GET ANOTHER BYTE CALL PUTBYT ;PUT IN USER DATA STRING RET ;error... JRST PUTST1 ;DO ANOTHER BYTE SUBTTL User strings -- Get and put user byte routines. ;CALL ; T1/ integer to deposit ;RETURN ; RET on error, code in NXERR ; RETSKP with number deposited/loaded from/to T1 PUTBYT: XMOVEI T2,NX.DAT+NMXVAR ;POINTER TO BYTE POINTER/COUNT STRUCTURE JRST DNPUBT ;PUT THE BYTE IN THE STREAM. PUT4BT: SAVEAC ;P1 IS OUR DATA, P2 IS THE NUMBER OF BYTES XMOVEI T2,NX.DAT+NMXVAR ;POINTER TO BYTE POINTER/COUNT STRUCTURE. MOVX P2,4 ;DO 4 BYTES JRST PUTMBT ;PUT MULTIPLE BYTES PUT2BT: SAVEAC ;P1 IS DATA, P2 IS COUNT OF BYTES XMOVEI T2,NX.DAT+NMXVAR ;POINTER TO BYTE POINTER/COUNT STRUCTURE. MOVX P2,2 ;WE ARE DOING 2 BYTES ;; JRST PUTMBT ;PUT MULTIPLE BYTES PUTMBT: MOVE P1,T1 ;SAVE ORIGINAL BYTES PUTMB1: LDB T1,[POINT 8,P1,35] ;GET BOTTOM BYTE CALL DNPUBT ;STORE IT IN USER'S DATA STRING RET ;error... SOJLE P2,RSKP ;IF DONE, RETURN SUCCESS. ASH P1,-10 ;DROP (INTO BIT BUCKET) THE BYTE WE JUST PUT JRST PUTMB1 ;AND PUT ANOTHER BYTE IN USER'S STRING GETEBY: XMOVEI T2,NX.EID+NMXVAR ;POINTER TO BP FOR ENTITY ID CALLRET DNGUBT ;AND GET A BYTE FROM IT. GETBYT: XMOVEI T2,NX.DAT+NMXVAR ;POINTER TO BYTE POINTER/COUNT STRUCTURE CALLRET DNGUBT ;AND GO GET THE BYTE GET2BT: SAVEAC P1 ;WE ARE GOING TO ACCUMULATE BYTES HERE XMOVEI T2,NX.DAT+NMXVAR ;POINTER TO BYTE POINTER/COUNT STRUCTURE. CALL DNGUBT ;GET A BYTE OUT OF STREAM RET ;error... MOVE P1,T1 ;SAVE WHILE WE GET HIGH ORDER BYTE CALL DNGUBT ;GET SECOND BYTE RET ;error... ASH T1,8 ;SINCE THIS IS HIGH ORDER, MAKE ROOM FOR LOW IOR T1,P1 ;OR IT IN, MAKING A 2-BYTE AC RETSKP ;RETURN WITH 2 BYTES IN T1 GET4BT: SAVEAC P1 ;THIS IS WHERE WE ACCUMULATE INCOMING BYTES XMOVEI T2,NX.DAT+NMXVAR ;POINTER TO BYTE POINTER/COUNT STRUCTURE. CALL DNGUBT ;GET A BYTE OUT OF USER STREAM RET ;error... MOVE P1,T1 ;COPY BYTE INTO SAFE AC ROT P1,-10 ;NEXT BYTE IS HIGHER ORDER THAN THIS CALL DNGUBT ;GET BYTE NUMBER 2 RET ;error... IOR P1,T1 ;ACCUMULATE THIS BYTE IN ROT P1,-10 ;LET NEXT BYTE COME IN ABOVE THIS ONE CALL DNGUBT ;GET BYTE NUMBER 3 RET ;error... IOR P1,T1 ;ACCUMULATE IT IN ROT P1,-10 ;NEXT BYTE IS THE HIGHEST ORDER BYTE CALL DNGUBT ;GET THE LAST (4TH) BYTE RET ;error... IOR T1,P1 ;INCLUDE STUFF WE HAVE BEEN ACCUMULATING ROT T1,30 ;ROTATE SO WE HAVE A REAL NUMBER RETSKP ;RETURN WITH THE ENTIRE NUMBER IN T1 SUBTTL User strings -- Get and put single bytes into data strings. ;Call ; T1/ Byte to be put, or byte returned. ; T2/ Pointer to BP block ;Return ; RET on error, error code in NXERR ; RETSKP T1 deposited/loaded ; ;Note - These assume the caller has verified the byte pointer by calling ;CHKIND, to avoid the possibility of an indirect loop, and to insure that ;the destination byte stream is in core. ;For reasons of efficiency, T2 is guaranteed to be preserved. DNPUBT: OPSTRM ,BPBYT,(T2) ;DECREMENT COUNT OF AVAILABLE BYTES JUMPL T3,NTERES ;PARAMETERS TOO LONG TMNE NXMCX,+NMXVAR ;Writing to monitor context? IFSKP. ; -no S1XCT ;deposit the byte in user context ELSE. ; -yes, IDPB T1,(T2) ; just a single deposit ENDIF. RETSKP DNGUBT: OPSTRM ,BPBYT,(T2) ;DECREMENT COUNT OF BYTES PERMITTED JUMPL T3,NTEPAM ;PARAMETER MISSING S1XCT < XCTBU [ILDB T1,(T2)] ;DO THE ILDB > RETSKP ;GOT THE BYTE IN T1 - RETURN SUCCESS SUBTTL Miscellaneous -- Error returns ;;Error returns. Put error code in AC and .NTERR in user's block, ;and return non-skip. DEFINE NMXERR(CODE),< MOVX T1,^D'CODE ;ERROR CODE JRST NTEERR ;AND DO ERROR > NTEUFO: NMXERR(-1) ;UNRECOGNIZED FUNCTION OR OPTION NTEIMF: NMXERR(-2) ;INVALID MESSAGE FORMAT NTEPRV: NMXERR(-3) ;PRIVILEGE VIOLATION. NTEMPE: NMXERR(-5) ;MANAGEMENT PROGRAM ERROR NTEUPT: NMXERR(-6) ;UNRECOGNIZED PARAMETER TYPE NTEURC: NMXERR(-8) ;UNRECOGNIZED COMPONENT NTEINI: NMXERR(-9) ;INVALID IDENTIFICATION ; NELCE%==-10 ;LINE COMMUNICATION ERROR ; NECWS%==-11 ;COMPONENT IN WRONG STATE NTERES: NMXERR(-15) ;RESOURCE ERROR NTEIPV: NMXERR(-16) ;INVALID PARAMETER VALUE NTENRM: NMXERR(-20) ;NO ROOM (OR SLOT ALREADY TAKEN) NTEPNA: NMXERR(-22) ;PARAMETER NOT APPLICABLE NTEPVL: NMXERR(-23) ;PARAMETER VALUE TOO LONG NTEOPF: NMXERR(-25) ;OPERATION FAILURE NTEFNS: NMXERR(-26) ;FUNCTION NOT SUPPORTED NTEIPG: NMXERR(-27) ;INVALID PARAMETER GROUPING NTEPAM: NMXERR(-29) ;PARAMETER MISSING NTEADC: NMXERR(-47) ;ADDRESS CHECK NTEERR: STOR T1,NXERR,+NMXVAR ;Save the error code the Layer sent back JE NFBFF,+NFWBLK,RTN ;If no buffer, return now LOAD T1,NFBUF,+NFWBLK ;Get the Counter Block CALL DNFWDS ;Free up memory SETZRO NFBUF,+NFWBLK ;Get rid of the address SETZRO NFBFF,+NFWBLK ;and the flag RET ;Return non-skip SUBTTL Miscellaneous -- Name/number conversion. ;NMXA2N - Address to name conversion ;Call ; T1/ Node address ;Return ; RET ;No such node, illegal, ect. ; RETSKP, name in NXVAL ;on success NMXA2N: SETZRO NFBUF,+NFWBLK ;SCLINK doesn't like anything in here.... STOR T1,NFEID,+NFWBLK ;Store the Node Address in the Argument block MOVX T1,.NTNOD ;NODE ENTITY TYPE STOR T1,NFETY,+NFWBLK ;Put it into the block MOVX T1,NF.A2N ;Function code into T1 XMOVEI T2,NFWBLK ;Argument Block address CALL SCLNMX ;CONVERT NODE ADDRESS TO NODE NAME IFNSK. SKIPE T1 ;Is it a zero error code? JRST NTEERR ;No, It is a real error then... SETZRO NXVAL,+NMXVAR ;SET BYTE COUNT AND NODE NAME TO 0 RETSKP ;And do an error return ENDIF. LOAD T1,NFBUF,+NFWBLK ;Get the SIXBIT Node Name CALL NMXS2A ;Convert name and store it in NMXVAR block RETSKP ;RETURN SUCCESS ;Convert SIXBIT Node Name to ASCII Node Name and save in NMXVAR Block ;Call ; T1/ SIXBIT Node Name ;Return ; RET always, ASCII Node Name stored in NXVAL,+NMXVAR NMXS2A: SETZ T2, ;START OFF WITH ZERO BYTES RETURNED MOVE T3,[POINT 6,T1] ;POINTER TO THE NODE NAME RETURNED MOVEI T4,6 ;MAXIMUM NUMBER OF CHARACTERS TO CHECK NMXS21: SOSL T4 IFNSK. ILDB T5,T3 ;GET A BYTE FROM THE NAME JUMPE T5,NMXS22 ;IF ZERO BYTE, END OF NAME AOJA T2,NMXS21 ;ELSE KEEP COUNTING. ENDIF. NMXS22: MOVE T4,[POINT 6,T1] ;BYTE POINTER TO THE NODE NAME MOVE T3,[POINT 8,NX.VAL+NMXVAR] ;BYTE POINTER TO WHERE WE WANT NAME IDPB T2,T3 ;START OFF STRINGID WITH NUMBER OF CHARACTERS NMXS23: ILDB T5,T4 ;GET A BYTE FROM THE NAME ADDI T5,^O40 ;MAKE IT ASCII IDPB T5,T3 ;STORE IT IN NMXVAR IN STRINGID FORMAT SOJG T2,NMXS23 ;AND CONTINUE COPYING UNTIL DONE. RET ;NMXN2A - Name to address conversion ;Call ; NXVAL+NMXVAR/ Stringid for node name. Max 6 chars. ;Return ; RET ;Unknown name. NTEURC. ; RETSKP ;T1 contains node address. NMXN2A: SETZ T1, ;START OFF WITH A CLEAN NODE NAME MOVE T6,[POINT 8,NX.VAL+NMXVAR] ;BYTE POINTER TO STRINGID WITH NAME MOVE T5,[POINT 6,NF.EID+NFWBLK] ;BYTE POINTER TO CREATE SIXBIT NAME ILDB T4,T6 ;GET COUNT OF BYTES JUMPE T4,RTN ;IF NOTHING, ERROR NMXN2B: ILDB T3,T6 ;GET A BYTE FROM THE NODE NAME CAIL T3,^O140 ;IS IT LOWER CASE SUBI T3,^O40 ;MAKE IT UPPER CASE SUBI T3,^O40 ;MAKE IT SIXBIT IDPB T3,T5 ;STORE IT IN THE NODE NAME SOJG T4,NMXN2B ;AND LOOP UNTIL BYTES EXHAUSTED. MOVX T1,.NTNOD ;NODE ENTITY TYPE STOR T1,NFETY,+NFWBLK ;Send it to Session Control Layer MOVX T1,NF.N2A ;Get the Function Code XMOVEI T2,NFWBLK ;And the address of the Argument Block CALL SCLNMX ;CONVERT NODE NAME TO NODE ADDRESS JRST NTEERR ;SESSION CONTROL CAN'T FIND THE NAME. ERROR. LOAD T1,NFBUF,+NFWBLK ;Put the address into T1 RETSKP ;SUCCESS. T1 CONTAINS NODE ADDRESS. XLIST LIT LIST IFN FTOPS10, .XCMSY IFN FTOPS20, TNXEND IFN FTOPS10,< RESDT NTMLOW::! XRESCD >; END IFN FTOPS10 END