Trailing-Edge
-
PDP-10 Archives
-
SRI_NIC_PERM_SRC_1_19910112
-
7/galaxy-sources/lptclu.mac
There are 4 other files named lptclu.mac in the archive. Click here to see a list.
TITLE LPTCLU - LPTSPL Support for Cluster Printing
SUBTTL Preliminaries
; COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1988.
; ALL RIGHTS RESERVED.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
; ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE
; INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER
; COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
; OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY
; TRANSFERRED.
;
; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE
; AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT
; CORPORATION.
;
; DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
; SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY DIGITAL.
SEARCH GLXMAC ;SEARCH GLXLIB'S SYMBOLS
SEARCH LPTMAC ;SEARCH LPTSPL'S SYMBOLS
SEARCH LISMAC ;SEARCH LPTSPL'S LISTENER'S SYMBOLS
SEARCH QSRMAC ;SEARCH QUASAR'S SYMBOLS
SEARCH ORNMAC ;SEARCH ORION'S SYMBOLS
IFN FTACNT,<
SEARCH ACTSYM ;SEARCH FOR ACCOUNTING SYMBOLS
>
PROLOGUE(LPTCLU) ;GENERATE THE NECESSARY SYMBOLS
CLUMAN==:0 ;MAINTENANCE EDIT NUMBER
CLUDEV==:11 ;DEVELOPMENT EDIT NUMBER
VERSIN (CLU) ;GENERATE EDIT NUMBER
SALL ;CLEAN LISTINGS
Subttl Table of Contents
; Table of Contents for LPTCLU
;
; Section Page
;
;
; 1. Revision history . . . . . . . . . . . . . . . . . . . 4
; 2. Global Symbols . . . . . . . . . . . . . . . . . . . . 5
; 3. INILNK - INITIALIZE AND OPEN DCN: DECNET LINK . . . . 6
; 4. BLDDCN - BUILD THE DCN: DECNET DEVICE NAME . . . . . . 7
; 5. OPNLNK - OPEN THE DCN: DECNET DEVICE . . . . . . . . . 8
; 6. GETSIZ - GET THE SIZE OF CLUSTER LPTSPL . . . . . . . 9
; 7. STLIS - START UP THE CLUSTER LPTSPL LISTENER . . . . . 10
; 8. CLNCLU - RELEASE FILE TRANSFER BUFFER AND KILL LISTENE 11
; 9. FIXCLU - FIXUP CLUSTER LPT PARAMETERS FROM NXTJOB . . 12
; 10. CLJOB - DO THE CLUSTER LPTSPL PRINT JOB . . . . . . . 13
; 11. INTDAV - INTERRUPT ROUTINE FOR DECNET MESSAGE AVAILABL 14
; 12. XFERFI - TRANSFER FILES TO THE REMOTE SYSTEM . . . . . 15
; 13. SHULPT - SHUTDOWN DUE TO A FATAL INTERRUPT ROUTINE ERR 16
; 14. RESTAR - RESTART A NEXTJOB REQUEST . . . . . . . . . . 17
; 15. REPERR - REPORT FATAL ERROR TO QUASAR . . . . . . . . 18
; 16. CHKSUM - CHECKSUM DECNET MESSAGES . . . . . . . . . . 19
; 17. RESET - RESET THE STATE OF CLUSTER LPTSPL . . . . . . 20
; 18. UPDMSG - UPDATE THE NEXTJOB MESSAGE . . . . . . . . . 21
; 19. CFILES - CLOSE THE INACCESSIBLE FILE AND TEMPORARY FIL 22
; 20. DELTEM - DELETE AND EXPUNGE ANY TEMPORY FILES . . . . 23
; 21. SENFAI - SEND A DECNET FAIL MESSAGE TO THE LISTENER . 24
; 22. SNDINT - SEND A DECNET INTERRUPT MESSAGE TO THE LISTEN 25
; 23. RCVINT - PICK UP AN INTERRUPT MESSAGE RESPONSE FROM LI 26
; 24. ENDFRK - INFERIOR FORK TERMINATION INTERRUPT HANDLER . 27
; 25. DISINT - DEACTIVATE DATA AVAILABLE CHANNEL . . . . . . 28
; 26. ENAINT - ACTIVATE THE DATA AVAILABLE CHANNEL . . . . . 29
; 27. CHKLNK - CHECK THE STATUS OF THE SENDER DECNET LINK . 30
; 28. REMREL - RELEASE A PRINT REQUEST FROM A REMOTE NODE . 31
; 29. ADDACT - ADD ACCOUNTING INFORMATION TO A RELEASE MESSA 32
; 30. REMDIS - DELETE FILES AND PLACE FILE NAMES IN RELEASE 33
; 31. DELTFE - DELETE A FILE . . . . . . . . . . . . . . . . 34
; 32. SETFD - SETUP A TEMPORARY FILE'S FD IN THE FOB . . . . 35
; 33. LISTEN - MESSAGE SERVER FOR A REMOTE NODE . . . . . . 36
; 34. BLDSRV - BUILD THE SRV: DEVICE NAME . . . . . . . . . 37
; 35. LISSET - INITIALIZE THE LISTENER'S GLXLIB AND CAPABILI 38
; 36. LOPLNK - OPEN A DECNET SRV: DEVICE . . . . . . . . . . 39
; 37. LISINT - SET UP THE LISTENER'S INTERRUPT SYSTEM . . . 40
; 38. ACCEPT - VALIDATE A DECNET CONNECTION REQUEST . . . . 41
; 39. MSGFSN - DECNET MESSAGE FROM SENDER IS AVAILABLE . . . 42
; 40. LSSCS - TOPOLOGY CHANGE DECTECTED INTERRUPT HANDLER . 43
; 41. LCKLNK - CHECK THE STATUS OF THE LISTENER'S LINK . . . 44
; 42. LABLNK - ABORT THE LISTENER'S DECNET LINK . . . . . . 45
; 43. LISCHK - LISTENER CHECKSUM AND ACK MESSAGE . . . . . . 46
; 44. ACKSND - SEND A SUCCESS ACK TO THE SENDER . . . . . . 47
; 45. INLCRH - ROUTINE TO INDICATE LISTENER CONTROLLED CRASH 48
; 46. LPTDDT - ROUTINE TO LOAD DDT IF DEBUGGING . . . . . . 49
; 47. DOACT - DO ACCOUNTING FROM THE RELEASE MESSAGE . . . . 50
Subttl Table of Contents (page 2)
; Table of Contents for LPTCLU
;
; Section Page
;
;
; 48. ACTLIS - LISTENER ACCOUNTING RECORD . . . . . . . . . 51
; 49. STOP CODE DEFINITIONS . . . . . . . . . . . . . . . . 52
; 50. End of LPTCLU . . . . . . . . . . . . . . . . . . . . 53
SUBTTL Revision history
COMMENT \
***** Release 6.0 -- begin development edits *****
1 6.1029 19-Oct-87
Add LPTCLU as the Cluster printer handler for LPTSPL.
2 6.1036 21-Oct-87
Split subroutines into LPTSUB for use by LPTDQS.
3 6.1052 3-Nov-87
General cleanup of code as a result of unit and system testing.
4 6.1119 5-Dec-87
If the listener detects that the DECnet link is no longer connected,
then in addition to aborting and re-opening the link, cause it also to
clear and re-setup the interrupt system.
5 6.1125 6-Dec-87
If the attributes field contains %GENRC, then zero the units field.
6 6.1128 7-Dec-87
Expand on edit 4 to include all cases of the listener detecting that
the DECnet link is no longer connected. Also, clear and reset the interrupt
system outside of interrupt context to prevent NIP ("no interrupt in progress")
crashes.
7 6.1215 4-Mar-88
In a private GALAXY, use the first six characters of the user's name
rather than LISSPL and LPTSPL as part of the DCN: and SRV: name.
10 6.1220 6-Mar-88
Transfer the contents of the page shared between LPTSPL and the
inaccessible file to another page. PMAP that page to the temporary file.
11 6.1225 8-Mar-88
Update copyright notice.
\
SUBTTL Global Symbols
;Global symbols defined in LPTSPL
EXTERN CNTSTA,DETDEL,DIRNAM,DSCHD,ENDREQ,INPOPN,JOBACT
EXTERN JOBOBA,LEV1PC,LPTSIZ,LPTVNO,NXTFIL,RSETUP,SHUTIN,SNDQSR
;Global symbols defined in LPTSUB
EXTERN ABTLNK,CASTIM,GETLIK,FNDCER,PROTIM,SETIM
;Global symbols defined in LPTCLU
INTERN CLNCLU,CLUEDT,ENDFRK,FIXCLU,INILNK,INTDAV,REMREL,RCVINT,SETFD
INTERN CLJOB ;[2]
SUBTTL INILNK - INITIALIZE AND OPEN DCN: DECNET LINK
;INILNK is called during Cluster LPTSPL's SETUP to build the DECnet DCN:
;device name, to open the DECnet link and to allocate the buffer for any
;files that may need to be transferred to a remote node.
;If accounting is enabled, then a listener is also started.
;If the DECnet DCN: JFN cannot be obtained or opened, or if the listener
;cannot be started, then a SETUP RESPONSE message is sent to QUASAR
;indicating that this LPTSPL is shutting down. The operator is also
;informed that this LPTSPL is being shutdown.
;
;Call is: J/Job Context Pointer
; M/Address of the SETUP message
;Returns true: S1/SETUP response code
; The DECnet link is connected and the listener (if any) is
; started
;Returns false: A fatal error occurred (the DECnet DCN: JFN could not be
; obtained or opened, or the listener could not be started)
;ATTEMPT TO OPEN AND CONNECT THE DECNET LINK
INILNK: $CALL BLDDCN ;BUILD THE DCN: DECNET DEVICE NAME
$CALL OPNLNK ;OPEN THE DECNET LINK
JUMPF INILN3 ;A FATAL ERROR WAS DETECTED
IFN FTACNT<
SETOM J$ACCT(J) ;INDICATE ACCOUNTING IS ENABLED
>
SKIPL J$ACCT(J) ;IF ACCOUNTING ENABLED, START LISTENER
JRST INILN2 ;ELSE PICK UP THE FILE TRANSFER BUFFER
$CALL GETSIZ ;PICK UP LPTSPL'S SIZE IN PAGE
$CALL STLIS ;START UP THE LISTENER
JUMPF INILN3 ;SHUTDOWN ON AN ERROR
;PICK UP THE MEMORY FOR THE FILE TRANSFER BUFFERS.
INILN2: MOVEI S1,2 ;[10]NEED TWO FILE TRANSFER BUFFERS
$CALL M%AQNP ;[10]PICK UP THE PAGES
MOVE S2,S1 ;[10]SAVE A COPY
MOVEM S1,J$FILB(J) ;[10]SAVE PAGE NUMBER IN THE DATA BASE
PG2ADR S1 ;[10]CHANGE TO AN ADDRESS
MOVEM S1,J$FADR(J) ;[10]SAVE ADDRESS IN THE DATA BASE
AOS S2 ;[10]POINT TO THE NEXT PAGE
MOVEM S2,J$FILO(J) ;[10]SAVE PAGE NUMBER OF 2ND XFER PAGE
PG2ADR S2 ;[10]CHANGE TO AN ADDRESS
MOVEM S2,J$OADR(J) ;[10]SAVE ADDRESS IN THE DATA BASE
;PICK UP THE MEMORY FOR THE DECNET RESPONSE MESSAGES AND THE DECNET SEND
;MESSAGES
MOVEI S1,2 ;NEED TWO PAGES
$CALL M%AQNP ;PICK UP THE PAGES
PG2ADR S1 ;CHANGE PAGE NUMBER TO PAGE ADDRESS
HRLI S1,(POINT 36) ;POINT TO DECNET RESPONSE MESSAGE ADR
MOVEM S1,J$DECR(J) ;SAVE POINTER IN THE DATA BASE
ADDI S1,PAGSIZ ;POINT TO DECNET SEND MESSAGE ADDRESS
MOVEM S1,J$DECS(J) ;SAVE POINTER IN THE DATA BASE
$CALL SETIM ;SET THE DECNET INACTIVITY TIMER
MOVX S1,%RSUOK ;PICK UP THE SETUP OK RESPONSE CODE
$RETT ;RETURN TO THE CALLER
;AN ERROR HAS BEEN DETECTED. IF THE ERROR IS FATAL, THEN CLOSE THE DECNET
;DCN: DEVICE JFN AND INFORM QUASAR TO SHUT THIS LPTSPL DOWN. ALSO INFORM
;THE OPERATOR. IF THE ERROR IS NOT FATAL, THEN QUASAR WILL TEMPORARILY
;SHUT THE PRINTER DOWN.
INILN3: SKIPE S1 ;[3]SKIP IF TEMPORARY SHUTDOWN
$CALL REPERR ;REPORT THE ERROR TO QUASAR AND ORION
$RETF ;RETURN FALSE TO SETUP
SUBTTL BLDDCN - BUILD THE DCN: DECNET DEVICE NAME
;BLDDCN is called during Cluster LPTSPL SETUP to build the DECnet DCN: device
;name that Cluster LPTSPL will use in opening its DECnet link. The format of
;the DCN: device name is:
;DCN:RNODE-TASK-RNODE$LISSPL$LS.RNODE$LPTSPL$SN;BDATA:NNNNN;
;USERID:RNODE$LPTSPL$SN
;
;where RNODE is the remote node name
; NNNNN comes from the listener's node name and is used by LISSPL's
; listener in accepting a connection
;
;Call is: J/Job Context Pointer
;Returns The DCN: device name has been built and placed in the stream's
; data base
BLDDCN: $SAVE <P1,P2,P3,P4> ;SAVE THESE AC
;BUILD THE OPTIONAL DATA FIELD USING THE SIXBIT REMOTE NODE NAME AS
;THE STARTING VALUE. CREATE 12 OCTAL CHARACTERS AND CONVERT THEM TO ASCII.
MOVE S2,JOBOBA ;PICK UP THE OBJECT BLOCK ADDRESS
MOVE S2,OBJ.ND(S2) ;PICK UP THE LISTENER'S NODE NAME
MOVEM S2,J$RNOD(J) ;SAVE IN THE DATA BASE
ROT S2,3 ;ROTATE BY HALF A CHARACTER
MOVE P1,[POINT 7,S1,35] ;POINTER TO BYTE TO PICK UP
MOVE P2,[POINT 7,J$NDAT(J)] ;POINTER TO WHERE BYTE IS TO BE PUT
SETZ S1, ;CLEAR RECEIVING WORD OF OCTAL VALUE
MOVEI P3,^D36/3 ;NUMBER OF OCTAL CHARACTERS
BLDDC2: LSHC S1,3 ;MOVE NEXT OCTAL VALUE OVER
ADDI S1,60 ;MAKE IT ASCII
LDB P4,P1 ;PICK UP ASCII VALUE
IDPB P4,P2 ;PLACE IN ASCII STRING
SETZ S1, ;PREPARE FOR NEXT OCTAL VALUE
SOJN P3,BLDDC2 ;PICK UP NEXT OCTAL VALUE
IDPB S1,P2 ;MAKE INTO AN ASCIZ STRING
;BUILD THE DECNET DCN: DEVICE NAME
SKIPE DEBUGW ;[7]DEBUGGING?
JRST BLDDC6 ;[7]YES, DO DIFFERENTLY
$TEXT(<-1,,J$CDCN(J)>,<DCN:^I/@BLDDC3/^I/@BLDDC4/^I/@BLDDC5/>)
$RET ;RETURN TO THE CALLER
BLDDC3: [ITEXT(<^N/J$RNOD(J)/-TASK-^N/J$RNOD(J)/$LISSPL$LS.>)] ;LISTENER NAME
BLDDC4: [ITEXT(<^N/J$RNOD(J)/$LPTSPL$SN;BDATA:^T/J$NDAT(J)/>)] ;THE SENDER NAME
BLDDC5: [ITEXT(<;USERID:^N/J$RNOD(J)/$LPTSPL$SN>)] ;[3]USERID
BLDDC6: GJINF% ;[7]PICK UP THE USER'S NUMBER
MOVE S2,S1 ;[7]SAVE NUMBER WHERE EXPECTED
MOVEI S1,J$SDBW(J) ;[7]WHERE TO PLACE USER NAME
HRLI S1,(POINT 7) ;[7]MAKE INTO A POINTER
DIRST% ;[7]PICK UP THE USER NAME
JRST S..COD ;[7]CRASH ON AN ERROR
MOVEI S1,J$SDBW(J) ;[7]PICK UP USER NAME ADDRESS
HRLI S1,(POINT 7,) ;[7]MAKE INTO A POINTER
SETZ T1, ;[7]NUMBER OF CHAR IN NAME
BLDDC7: ILDB S2,S1 ;[7]PICK UP THE NEXT CHARACTER
SKIPN S2 ;[7]IS THIS THE LAST ONE?
JRST BLDDC8 ;[7]YES, BUILD THE DEVICE NAME
AOS T1 ;[7]INCREMENT THE CHAR COUNT
CAIG T1,^D6 ;[7]MAXIMUM COUNT?
JRST BLDDC7 ;[7]NO, GET THE NEXT CHAR
SETZ S2, ;[7]PICK UP A NULL
DPB S2,S1 ;[7]PLACE IN USER NAME
BLDDC8: MOVEI S1,J$SDBW(J) ;[7]ADDRESS OF THE USER NAME
$TEXT(<-1,,J$CDCN(J)>,<DCN:^I/@BLDDC9/^I/@BLDD10/^I/@BLDD11/^0>)
$RET ;RETURN TO THE CALLER
BLDDC9: [ITEXT(<^N/J$RNOD(J)/-TASK-^N/J$RNOD(J)/$^T/0(S1)/$LS.>)] ;[7]LISTENER NAME
BLDD10: [ITEXT(<^N/J$RNOD(J)/$^T/0(S1)/$SN;BDATA:^T/J$NDAT(J)/>)] ;[7]SENDER NAME
BLDD11: [ITEXT(<;USERID:^N/J$RNOD(J)/$^T/0(S1)/$SN>)] ;[7]
SUBTTL OPNLNK - OPEN THE DCN: DECNET DEVICE
;OPNLNK is called during SETUP and also if it is detected that the link is
;no longer connected while processing a print request. OPNLNK opens a DECnet
;link to a remote LISSPL listener.
;If a connection cannot be obtained, then a check is made to see if the
;error is fatal. If the error is fatal, then Cluster LPTSPL shuts down.
;If the error is not fatal, then OPNLNK will re-attempt to open the
;connection after a specified amount of time. Initially, the time between
;retries is MINTIM seconds. If after MAXTIM seconds a connection is still
;not obtained, then OPNLNK informs ORION. The time between retries is
;increased by MINTIM seconds and a connection is again attempted. This will
;continue until either a connection is obtained or until the time between
;retries is MAXTIM seconds. At this point, OPNLNK attempts to obtain a
;connection every MAXTIM seconds.
;It is possible for an operator to suppress OPNLNK from sending
;connection failure messages (and to later re-enable OPNLNK to send
;connection failure messages) by giving the OPR command DISABLE OUTPUT-DISPLAY
;PRINTER-MESSAGE
;
;Call is: J/Job Context Pointer
;Returns true: The DECnet link is connected
;Returns false: A fatal DECnet error was detected
; S1/Address of the error string
; Unable to obtain the DECnet connection. QUASAR will temporarily
; shut this printer down
; S1/0
OPNLNK: $SAVE <T1,T2,T3,T4> ;SAVE THESE AC
;INITIALIZE THE ATTEMPT TO OBTAIN A DECNET CONNECTION TO THE LISTENER
MOVEI T3,MINTIM ;PICK UP TIME BETWEEN RETRIES
SETOM J$LCHN(J) ;NO DECNET JFN
SETZ T4, ;NUMBER OF ATTEMPTS TO OBTAIN THE LINK
;ATTEMPT TO OBTAIN THE DECNET CONNECTION.
OPNLN2: SKIPL J$LCHN(J) ;CURRENTLY HAVE A DECNET JFN?
JRST OPNLN3 ;YES, GO CHECK ITS STATUS
$CALL GETLIK ;[3]NO, OBTAIN ONE AND OPENF
JUMPF OPNLN9 ;QUIT ON A FATAL ERROR
;CHECK THE STATUS OF THE LINK. IF THERE IS A CONNECTION, THEN ENABLE
;FOR DATA AVAILABLE INTERRUPTS.
OPNLN3: $CALL CHKLNK ;CHECK THE LINK STATUS
JUMPF OPNLN4 ;DON'T HAVE A CONNECTION
MOVE S1,J$LCHN(J) ;PICK UP THE DECNET DCN: DEVICE JFN
MOVEI S2,.MOACN ;PICK UP ACTIVATE FUNCTION
MOVX T1,<FLD(2,MO%DAV)+FLD(.MONCI,MO%CDN)+FLD(3,MO%INA)>
MTOPR% ;ENABLE FOR DATA AVAILABLE INTERRUPTS
ERJMP OPNLN8 ;FATAL ERROR, SHUTDOWN PRINTER
$RETT ;RETURN TO SENDER STARTUP
;UNABLE TO OBTAIN THE CONNECTION. DETERMINE IF THE RETRY SHOULD BE INCREASED.
OPNLN4: JUMPG S1,OPNLN9 ;QUIT IF A FATAL ERROR OCCURRED
AOS T1,T4 ;INCREMENT THE NUMBER OF OPEN ATTEMPTS
IMUL T1,T3 ;TIME BEEN TRYING TO OBTAIN CONNECTION
CAIGE T1,MAXTIM ;TIME TO GIVE UP?
JRST OPNLN7 ;NO, DISMISS AND TRY AGAIN
;REPORT THE CONNECTION FAILURE TO ORION. INFORM QUASAR TO TEMPORARILY
;SHUT THIS PRINTER DOWN.
$CALL FNDCER ;GET THE CONNECTION ERROR
$WTOJ (<LPTSPL connection failure>,<^I/@OPNL10/^M^J^I/@OPNL11/>)
MOVX S1,%RSUNA ;[3]INDICATE TEMPORARY SHUTDOWN
$CALL RSETUP ;[3]INFORM QUASAR
SETZ 1, ;[3]INDICATE TEMPORARY SHUTDOWN
JRST OPNLN9 ;[3]RETURN TO THE CALLER
;DISMISS UNTIL INDICATED
OPNLN7: MOVE S1,T3 ;PICK UP TIME TO DISMISS
$CALL I%SLP ;DISMISS OR WAIT% AS INDICATED
JRST OPNLN2 ;ATTEMPT THE CONNECTION AGAIN
;A FATAL ERROR HAS BEEN DETECTED. CLOSE AND RELEASE THE DECNET DCN: LINK
;PICK UP ADDRESS OF THE ERROR STRING.
OPNLN8: $CALL S%ERR ;PICK UP THE ERROR STRING ADDRESS
SKIPT ;UNABLE TO PICK UP ERROR STRING ADR?
MOVEI S1,[ASCIZ/Unable to set up DECnet interrupt channel/] ;YES
MOVEM S1,J$ERRA(J) ;SAVE ADDRESS OF THE ERROR STRING
$CALL ABTLNK ;CLOSE AND RELEASE THE DECNET JFN
MOVE S1,J$ERRA(J) ;RESTORE THE ERROR STRING ADDRESS
OPNLN9: $RETF ;INDICATE AN ERROR TO THE CALLER
OPNL10: [ITEXT(<LPTSPL to node ^N/J$RNOD(J)/ unable to obtain a DECnet connection>)]
OPNL11: [ITEXT(<Reason for failure: ^T/0(S1)/>)]
SUBTTL GETSIZ - GET THE SIZE OF CLUSTER LPTSPL
;GETSIZ is called during Cluster LPTSPL startup to determine the size of
;Cluster LPTSPL in pages. This information is needed in starting up
;Cluster LPTSPL's listener.
;
;Call is: No arguments
;Returns: Size of Cluster LPTSPL has been determined
GETSIZ: SKIPE DEBUGW ;ARE WE DEBUGGING?
SKIPN 116 ;YES, AND ARE SYMBOLS DEFINED?
JRST GETSI2 ;NO TO EITHER, SKIP THIS
HLRO S1,116 ;GET AOBJN LENGTH
MOVMS S1 ;GET ABSOLUTE VALUE
HRRZ S2,116 ;GET SYMBOL TABLE START ADDRESS
ADDI S1,-1(S2) ;CALCULATE THE SYMBOL TABLE LENGTH
SKIPA ;SKIP OVER NORMAL CALCULATIONS
GETSI2: HLRZ S1,.JBSA## ;GET THE PROGRAM END ADDRESS
ADDI S1,777 ;ROUND IT OFF
ADR2PG S1 ;MAKE IT A PAGE NUMBER
MOVEM S1,LPTSIZ ;SAVE IT
$RET ;RETURN TO SETUP
SUBTTL STLIS - START UP THE CLUSTER LPTSPL LISTENER
;STLIS is called to start up the Cluster LPTSPL listener.
;This routine is called at LPTSPL SETUP and also when it is detected
;that the listener has crashed.
;
;Call is: J/Job Context Pointer
;Returns true: The listener was successfully started
;Returns false: S1/Address of the ASCIZ error text
; The listener cannot be started (i.e., a CFORK%, SFORK% or
; PMAP% error has occurred).
;STLIS IS THE ENTRY POINT WHEN STARTING THE LISTENER FOR THE FIRST TIME.
;STLIS0 IS THE ENTRY POINT WHEN RESTARTING THE LISTENER AFTER IT HAS CRASHED.
STLIS: TDZA S1,S1 ;[3]INDICATE NOT RESTARTING
STLIS0: SETO S1, ;[3]INDICATE RESTARTING
$SAVE <T1,T2,T3> ;[3]SAVE THESE AC
;CREATE THE LISTENER. PICK UP ITS DATA PAGES AND SET UP IT STACK
SKIPE S1 ;[3]RESTARTING?
JRST STLIS1 ;[3]NO, ALREADY HAVE THE DATA PAGES
MOVEI S1,DBSIZ ;[3]PICK UP NUMBER OF PAGES
$CALL M%AQNP ;[3]PICK UP THE DATA PAGES
PG2ADR S1 ;[3]CHANGE PAGE NUMBER TO ADDRESS
MOVEM S1,J$LPGS(J) ;[3]SAVE THE ADDRESS
SKIPA ;[3]DON'T PICK UP THE ADDRESS AGAIN
STLIS1: MOVE S1,J$LPGS(J) ;[3]PICK UP THE ADDRESS
MOVEI S2,.LSPDL-1(S1) ;[3]PICK UP LH OF STACK POINTER
HRLI S2,-PDSIZ ;[3]PICK UP RH OF STACK POINTER
PUSH S2,[EXP LISTEN] ;[3]PLACE STARTING ADDRESS ON THE STACK
MOVEM S2,.LSACS+P(S1) ;[3]PLACE IN THE LISTENER'S AC BLOCK
MOVEM S1,.LSACS+LIS(S1) ;[3]PLACE DATA BLOCK ADDRESS IN AC BLK
MOVE T3,S1 ;[3]SAVE ADDRESS HERE ALSO
ADDI S1,PAGSIZ ;[3]ADDRESS OF THE MESSAGE PAGE
MOVEM S1,.LSMSG(T3) ;[3]PLACE IN THE DATA BLOCK
MOVX S1,<CR%CAP+CR%ACS> ;[3]SUPERIOR'S CAPABILITIES AND ACS
MOVEI S2,.LSACS(T3) ;[3]PICK UP AC BLOCK ADDRESS
CFORK% ;CREATE A LISTENER
ERJMP STLIS4 ;QUIT ON AN ERROR
MOVEM S1,J$FRKH(J) ;SAVE THE LISTENER FORK HANDLE
;MAP LPTSPL'S PAGES INTO THE LISTENER
HRLZ S2,S1 ;[3]GET THE LISTENER'S HANDLE
MOVSI S1,.FHSLF ;GET THE TOP FORK'S HANDLE
HRR T1,LPTSIZ ;GET THE LENGTH IN PAGES
HRLI T1,(PM%RWX!PM%CNT) ;COUNT+READ+EXECUTE
PMAP% ;MAP THE PAGES
ERJMP STLIS2 ;QUIT ON AN ERROR
;MAP THE DATA PAGES INTO THE LISTENER
MOVE S1,T3 ;[3]PICK UP THE DATA BLOCK ADDRESS
ADR2PG S1 ;[3]CHANGE ADDRESS INTO A PAGE NUMBER
MOVE S2,S1 ;[3]SAVE PAGE NUMBER HERE ALSO
HRLI S1,.FHSLF ;[3]PICK UP TOP FORK'S HANDLE
HRL S2,J$FRKH(J) ;[3]PICK UP LISTENER'S HANDLE
MOVEI T1,DBSIZ ;[3]PICK UP NUMBER OF PAGES IN DATA BLK
HRLI T1,(PM%RWX!PM%CNT) ;[3]COUNT+READ+EXECUTE
PMAP% ;[3]MAP THE PAGES INTO LISTENER
ERJMP STLIS2 ;[3]CRASH ON AN ERROR
;START THE LISTENER
MOVE S1,J$FRKH(J) ;GET THE LISTENER'S HANDLE
MOVEI S2,LISTEN ;GET THE START ADDRESS
SFORK% ;START THE LISTENER
ERJMP STLIS2 ;QUIT ON AN ERROR
$RETT ;AND RETURN
;AN ERROR HAS OCCURRED. DELETE THE LISTENER FORK
STLIS2: $CALL S%ERR ;PICK UP THE ERROR STRING
SKIPT ;ERROR STRING PICKED UP?
MOVEI S1,[ASCIZ/Fatal error in starting up the LPTSPL sender/] ;NO
MOVEM S1,J$ERRA(J) ;SAVE THE ERROR TEXT ADDRESS
MOVE S1,J$FRKH(J) ;PICK UP THE LISTENER'S HANDLE
KFORK% ;KILL THE LISTENER
ERJMP .+1 ;IGNORE ANY ERRORS
SETZM J$FRKH(J) ;INDICATE NO INFERIOR FORK
JRST STLIS5 ;GO CLOSE AND RELEASE THE DECNET JFN
;AN ERROR HAS OCCURRED. PICK UP THE ERROR TEXT, AND CLOSE AND RELEASE
;THE DECNET DCN: JFN
STLIS4: $CALL S%ERR ;PICK UP THE ERROR TEXT
SKIPT ;SKIP IF THE ERROR TEXT WAS PICKED UP
MOVEI S1,[ASCIZ/Fatal error in starting up the LPTSPL listener/]
STLIS5: SETZM J$FRKH(J) ;INDICATE THERE IS NO LISTENER
$RETF ;INDICATE AN ERROR TO THE CALLER
SUBTTL CLNCLU - RELEASE FILE TRANSFER BUFFER AND KILL LISTENER
;CLNCLU is called as part of the shutdown of a Cluster LPTSPL. It returns
;the file transfer buffer pages and the DECnet message receive and send
;pages to the memory manager, closes any open files, aborts the DECnet
;link and kills the listener.
;
;Call is: J/Job Context Pointer
;Returns: The Cluster LPTSPL cleanup has been performed
CLNCLU: $SAVE <T1,T2> ;SAVE THESE AC, DESTROYED BY KFORK%
SKIPN S2,J$FILB(J) ;PICK UP FILE TRANSFER PAGES, IF ANY
JRST CLNCL2 ;NO PAGES, CHECK FOR MESSAGE PAGES
MOVEI S1,2 ;[10]PICK UP NUMBER OF PAGES TO RETURN
$CALL M%RLNP ;RETURN THE PAGES
SETZM J$FILB(J) ;[3]INDICATE NO MORE FILE TRANSFER PGS
SETZM J$FILO(J) ;[10]ZERO HERE ALSO
CLNCL2: SKIPN S2,J$LPGS(J) ;[3]ANY LISTENER PAGES?
JRST CLNCL3 ;[3]NO, CHECK FOR MESSAGE PAGES
ADR2PG S2 ;[3]CHANGE ADDRESS TO A PAGE NUMBER
MOVEI S1,DBSIZ ;[3]PICK UP NUMBER OF PAGES TO RELEASE
$CALL M%RLNP ;[3]RELEASE THE PAGES
SETZM J$LPGS(J) ;[3]INDICATE NO MORE FILE TRANSFER PGS
CLNCL3: SKIPN S2,J$DECR(J) ;[3]ANY MESSAGE PAGES ALLOCATED?
JRST CLNCL4 ;[3]NO, CLOSE ANY FILES
HRRZS S2 ;[3]CHANGE FROM POINTER TO AN ADDRESS
ADR2PG S2 ;CHANGE ADDRESS TO A PAGE NUMBER
MOVEI S1,2 ;TWO PAGES TO RETURN
$CALL M%RLNP ;RETURN THE PAGES
CLNCL4: SKIPL J$LCHN(J) ;[3]IS THERE A DECNET DCN: DEVICE JFN?
$CALL ABTLNK ;YES, RELEASE IT
SETO S1, ;[3]DELETE ANY TEMPORARY FILES
$CALL CFILES ;CLOSE ANY FILES THAT MAY BE OPEN
TXZE S,TEMFIL ;ANY TEMPORARY FILES CREATED?
$CALL DELTEM ;YES, DELETE THEM
SKIPN S1,J$FRKH(J) ;PICK UP THE LISTENER'S HANDLE
JRST CLNCL5 ;THERE IS NO LISTENER
KFORK% ;KILL THE LISTENER
ERJMP .+1 ;IGNORE ANY ERRORS
SETZM J$FRKH(J) ;INDICATE NO INFERIOR FORK
CLNCL5: SETZM J$CRNM(J) ;RESET NUMBER OF TIMES LISTENER CRASHED
$RET ;RETURN TO THE SHUTDOWN
SUBTTL FIXCLU - FIXUP CLUSTER LPT PARAMETERS FROM NXTJOB
;FIXCLU is PJRSTed from routine NXTJOB when NXTJOB determines that this is
;a Cluster LPTSPL. FIXCLU zeros out selected job data words.
;The operator is also informed that the print request has been started.
;
;Call is: Call from NXTJOB
; J/Job Context Pointer
;
;Returns: Selected job data words have been zeroed and the print job's
;stack has been changed to start at CLJOB
;
FIXCLU: SETZM J$CONF(J) ;ZERO OUT CONNECTION FAILURE DURING JOB
SETZM J$STAT(J) ;ZERO OUT THE STATUS WORD
SETZM J$TEM(J) ;ZERO OUT TEMPORARY FILE'S JFN
SETZM J$JFN(J) ;ZERO OUT FILE'S JFN
SETZM J$TNUM(J) ;ZERO OUT THE NUMBER OF TEMPORARY FILES
MOVEI S1,TFNLEN ;PICK UP LENGTH OF TEMP FILE NAMES TBL
MOVEI S2,J$TFIL(J) ;PICK UP ITS ADDRESS
$CALL .ZCHNK ;INITIALIZE THE TEMP FILE NAME TABLE
$WTO (Begin,<^R/.EQJBB(J)/>,@JOBOBA)
$RET ;RETURN TO THE IPCF SCHEDULER
SUBTTL CLJOB - DO THE CLUSTER LPTSPL PRINT JOB
;CLJOB processes a NEXTJOB message that is to be routed to a remote node
;in the cluster that has a printer. CLJOB insures that the user has access
;to each file in the NEXTJOB message. If the user does not have access,
;then this is indicated in the file's FP so that the LPTSPL on the remote
;node will not print this file.
;Any files not accessible to the remote node will result in a temporary file
;being created in a directory that is shared between the remote and local
;systems. The contents of the inaccessible file will be copied to the
;temporary file.
;
;Call is: This routine is started by the job processing dispatch scheduler
;Returns: The print request has been forwarded to the node where the files
; in the print request are to be printed.
;CHECK IF THE USER HAS A VALID ACCOUNT. IF THE USER DOES NOT, THEN THE
;REMOTE LPTSPL WILL NOT PRINT THE FILES. POINT TO THE FIRST FILE IN THE
;NEXTJOB MESSAGE.
CLJOB: LOAD S1,.EQSEQ(J),EQ.IAS ;GET INVALID ACCOUNT STRING BIT
STORE S1,S,ABORT ;SAVE IT AS THE ABORT BIT
LOAD E,.EQLEN(J),EQ.LOH ;GET LENGTH OF HEADER
ADD E,J ;POINT TO FIRST FILE
;CHECK THAT THE USER HAS ACCESS TO THE FILES IN THE PRINT REQUEST
TXNE S,ABORT ;IN THE ABORT STATE?
JRST CLJOB6 ;YES, LET REMOTE LPTSPL TELL THE USER
CLJOB2: $CALL INPOPN ;CHECK IF USER HAS ACCESS TO THIS FILE
JUMPF CLJOB4 ;NO, INDICATE IN THE FILE'S FP
MOVE S1,J$DIFN(J) ;YES, PICK UP THE FILE'S IFN
$CALL F%REL ;CLOSE AND RELEASE THE JFN
MOVE P1,.FPINF(E) ;PICK UP THE FILE PARAMETER INFO WORD
TXNN P1,FP.DEL ;IS THE FILE TO BE DELETED?
JRST CLJOB5 ;NO, CHECK THE NEXT FILE
MOVEI S1,FOB.SZ ;PICK UP THE FILE OBJECT BLOCK SIZE
MOVEI S2,J$XFOB(J) ;PICK UP THE FILE OBJECT BLOCK ADDRESS
$CALL F%AOPN ;CHECK IF THE USER HAS WRITE ACCESS
JUMPT CLJOB3 ;YES, GO CLOSE THE FILE
TXZ P1,FP.DEL ;NO, TURN OFF THE DELETE BIT
MOVEM P1,.FPINF(E) ;INDICATE NO DELETE IN THE FILE'S FP
JRST CLJOB5 ;GO CHECK THE NEXT FILE
CLJOB3: $CALL F%REL ;RELEASE THE FILE
JRST CLJOB5 ;GO CHECK THE NEXT FILE
;THE USER DOES NOT HAVE READ ACCESS TO THIS FILE. INDICATE THIS TO THE
;REMOTE LPTSPL. ALSO, TURN OFF THE DELETE BIT
CLJOB4: MOVX S1,FP.NRA ;INDICATE NO READ ACCESS
IORM S1,.FPINF(E) ;PLACE IN THE FILE'S FP
MOVX S1,FP.DEL ;PICK UP THE DELETE THIS FILE BIT
ANDCAM S1,.FPINF(E) ;INDICATE DON'T DELETE THIS FILE
CLJOB5: $CALL NXTFIL ;PICK UP THE NEXT FILE
JUMPT CLJOB2 ;AND LOOP
;CHECK IF THERE IS A DECNET DCN: JFN. THERE MAY NOT BE ONE DUE TO A TIME-OUT
;OR A PREVIOUS DECNET LINK LOST.
;CHECK STATUS OF THE LINK. IF THE LINK IS NO LONGER CONNECTED, THEN RE-OPEN IT
CLJOB6: SETZM J$DIFN(J) ;[3]INDICATE ALL FILES ARE CLOSED
SKIPGE J$LCHN(J) ;IS THERE A DECNET DCN: JFN?
JRST CLJOB7 ;NO, GET ONE AND ATTEMPT TO OPEN A LINK
$CALL CHKLNK ;CHECK IF THE DECNET LINK IS CONNECTED
JUMPT CLJOB9 ;THE LINK IS CONNECTED, CHECKSUM MSG
SKIPLE S1 ;WAS THERE A FATAL ERROR?
JRST CLJO15 ;YES, GO SHUTDOWN
CLJOB7: $CALL OPNLNK ;OPEN THE DECNET LINK
JUMPF CLJO15 ;A FATAL ERROR WAS DETECTED, SHUTDOWN
REPEAT 0,<
;IF CHECKSUMMING IS ENABLED, THEN CHECKSUM THE MESSAGE.
CLJOB8:
; SETZM .MSCHS(J) ;ASSUME CHECKSUMMING NOT ENABLED
SKIPN CHECKS ;IS CHECKSUMMING ENABLED?
JRST CLJOB9 ;NO, GO SEND MESSAGE
MOVE S1,J ;YES, PICK UP ADDRESS OF THE MESSAGE
$CALL CHKSUM ;CHECKSUM THE MESSAGE
>
;INDICATE IN THE MESSAGE THAT THIS IS A REMOTE PRINT REQUEST AND INDICATE
;WHETHER ACCOUNTING IS ENABLED OR NOT. ALSO INDICATE THE NODE THE MESSAGE
;ORIGINATED FROM.
CLJOB9: $CALL UPDMSG ;UPDATE THE MESSAGE
;SET THE STATE TO "NEXTJOB MESSAGE RESPONSE" AND SEND THE MESSAGE.
CLJO10: MOVX S1,.JSNMR ;NEXTJOB MESSAGE RESPONSE
MOVEM S1,J$STAT(J) ;[3]REMEMBER THE STATE
MOVE S1,J$LCHN(J) ;PICK UP THE DECNET DCN: DEVICE JFN
MOVE S2,J ;PICK UP THE ADDRESS OF THE MESSAGE
HRLI S2,(POINT 36) ;MAKE IT INTO A POINTER
LOAD T1,.MSTYP(J),MS.CNT ;PICK UP THE MESSAGE LENGTH
MOVNS T1 ;MAKE IT NEGATIVE
TXO S,INJOB ;LET LINK DISCONNECT HANDLER KNOW
SOUTR% ;SEND THE MESSAGE
ERJMP CLJO13 ;DETERMINE THE ERROR, CHECK FOR RETRY
CLJO11: SETZ S1, ;DON'T WAKE UP UNTIL INTERRUPTED
$CALL I%SLP ;WAIT FOR THE NEXT INTERRUPT
;IF A SENDER IS AT INTERRUPT LEVEL AND THE DECNET LINK BECOMES DISCONNECTED,
;THEN WHEN THE SENDER DEBRKS FROM THE INTERRUPT LEVEL, IT WILL NOT BE
;INTERRUPTED TO BE INFORMED THAT ITS LINK IS NO LONGER CONNECTED. THEREFORE,
;THE SENDER MUST CHECK THE STATUS OF THE LINK WHEN IT DEBRKS.
$CALL CHKLNK ;CHECK THE LINK STATUS
JUMPT CLJO11 ;THE LINK IS STILL CONNECTED
SKIPLE S1 ;DID A FATAL ERROR OCCUR?
JRST CLJO15 ;YES, GO SHUTDOWN
$CALL RESET ;NO, ATTEMPT TO RESET THE STATE
JUMPT CLJO10 ;RE-ATTEMPT TO PROCESS THE NEXTJOB MSG
MOVEI S1,[ASCIZ/Too many DECnet errors/] ;PICK UP ERROR TEXT
JRST CLJO15 ;GO SHUTDOWN
;A SOUTR HAS FAILED. IF THE LINK IS STILL CONNECTED, THEN ASSUME THE
;LISTENER HAS CRASHED AND RE-ATTEMPT TO OPEN THE LINK.
;IF THE LINK IS NO LONGER CONNECTED, THEN RE-ATTEMPT TO OPEN THE LINK.
;ONCE THE LINK IS OPEN, RESET THE STATE TO PRIOR TO SENDING THE NEXTJOB
;MESSAGE.
CLJO13: $CALL RESTAR ;CAN THE NEXTJOB REQUEST BE RESTARTED?
JUMPF CLJO15 ;NO, GO SHUTDOWN
CLJO14: $CALL OPNLNK ;ATTEMPT TO CONNECT THE LINK
JUMPT CLJO10 ;ATTEMPT TO SEND THE NEXTJOB MESSAGE
;AN ERROR HAS BEEN DETECTED. IF THE ERROR IS FATAL, THEN CLOSE THE DECNET
;DCN: DEVICE JFN AND INFORM QUASAR TO SHUT THIS LPTSPL DOWN. ALSO INFORM
;THE OPERATOR. IF THE ERROR IS NOT FATAL, THEN QUASAR WILL TEMPORARILY
;SHUT THE PRINTER DOWN.
CLJO15: SKIPE S1 ;[3]SKIP IF TEMPORARY SHUTDOWN
$CALL REPERR ;REPORT FATAL ERROR TO QUASAR AND ORION
PJRST SHUTIN ;SHUT DOWN THIS LPTSPL
SUBTTL INTDAV - INTERRUPT ROUTINE FOR DECNET MESSAGE AVAILABLE
;INTDAV is invoked when a "data available or disconnect pending"
;interrupt occurs. INTDAV determines the reason for the interrupt.
;If the interrupt is a spurious interrupt, then INTDAV DEBRKs.
;If the interrupt is due to a message from the listener having arrived,
;then INTDAV picks up the message, determines the message type and
;processes it.
; If the interrupt is due to the link connection being broken, then
;INTDAV determines if a job stream is active or not. If a job stream
;is not active (or if a job stream is active, but the NEXTJOB message
;has not yet been sent to the remote node), then INTDAV DEBRKs.
; If there is an active job stream which has forwarded the NEXTJOB message
;to the listener, then INTDAV aborts the link and resets the job stream
;status to that prior to sending the NEXTJOB message.
INTDAV: $BGINT 1, ;SAVE THE PREVIOUS CONTEXT
;CHECK IF THE INTERRUPT IS DUE TO A MESSAGE BEING AVAILABLE FROM THE
;LISTENER OR NOT. IF THERE IS A MESSAGE, THEN PROCESS IT. IF THERE IS NO
;MESSAGE, THEN CHECK IF THE INTERRUPT IS SPURIOUS OR IS DUE TO THE DECNET
;LINK NO LONGER BEING CONNECTED.
SKIPGE S1,J$LCHN(J) ;IS THERE A DECNET DCN: DEVICE JFN?
JRST INTD15 ;NO, TREAT AS A SPURIOUS INTERRUPT
SIBE% ;CHECK FOR A MESSAGE
JRST INTDA1 ;THERE IS A MESSAGE, PICK IT UP
;IF CHKLNK RETURNS FALSE, THEN THERE ARE 3 POSSIBILITIES:
; 1. CHKLNK ENCOUNTERED A FATAL ERROR: SHUT THE PRINTER DOWN
; 2. WAITING FOR A CONNECTION (THIS SHOULD NEVER HAPPEN): TREAT AS A SPURIOUS
; INTERRUPT.
; 3. CONNECTION HAS BEEN LOST: IF NO ACTIVE JOB (OR AN ACTIVE JOB BUT HAS NOT
; YET SENT THE NEXTJOB MESSAGE), THEN DEBRK. IF THE NEXTJOB MESSAGE HAS
; BEEN SENT, THEN RESTORE STATE TO PRIOR TO SENDING NEXTJOB MESSAGE AND
; ATTEMPT TO RE-CONNECT THE LINK
$CALL CHKLNK ;NO MESSAGE, CHECK LINK STATUS
JUMPT INTD15 ;[3]LINK IS CONNECTED, SO SPURIOUS
SKIPLE S1 ;[3]DID A FATAL ERROR OCCUR?
JRST INTD13 ;[3]YES, THEN SHUTDOWN
SKIPE S1 ;[3]WAITING FOR A CONNECTION?
JRST INTD15 ;[3]YES, TREAT AS SPURIOUS
JRST INTDA9 ;[3]LOST THE LINK, CHECK CONTEXT
;PICK UP THE MESSAGE FROM THE LISTENER
INTDA1: MOVE S1,J$LCHN(J) ;PICK UP THE DCN: DEVICE JFN
MOVE S2,J$DECR(J) ;PICK UP THE POINTER TO MESSAGE
MOVNI T1,PAGSIZ ;[3]PICK UP MAXIMUM MESSAGE SIZE
SINR% ;PICK UP THE MESSAGE
ERJMP INTD11 ;ABORT THE LINK AND RE-OPEN
MOVE S1,J$STAT(J) ;PICK UP STATE LPTSPL IS IN
JFFO S1,.+1 ;PICK UP DISPATCH OFFSET
CAIL S2,VALMIN ;IS THIS A VALID OFFSET?
CAILE S2,VALMAX ;YES, IS THIS A VALID OFFSET?
$STOP (IFM,Illegally formatted message from the listener)
JRST @INTDA2(S2) ;PROCESS ACCORDING TO STATE
INTDA2: EXP 0 ;[3]FIRST WORD NOT USED
INTDA3 ;NEXTJOB MESSAGE RESPONSE
INTDA7 ;[3]TRANSFER FILE MESSAGE RESPONSE
;THE STATE OF LPTSPL IS "NEXTJOB MESSAGE RESPONSE". CHECK IF THE RESPONSE
;IS SUCCESS. IF IT IS, THEN CLEAR THE STATE, CLEAR THE DECNET INACTIVITY
;COUNTER AND RESET THE PC TO PROCESS THE END OF JOB.
INTDA3: ADDI T1,PAGSIZ ;[3]CALCULATE NUMBER OF WORDS IN MSG
CAIG T1,1 ;[3]IS THIS AN ACK MESSAGE?
JRST INTDA7 ;YES, GO END THIS REQUEST
;THE PRINT REQUEST CONTAINED ONE OR MORE FILES NOT ACCESSIBLE ON THE
;REMOTE NODE. COPIES OF THESE FILES WILL BE PLACED IN A SHARED
;DIRECTORY WITH THE REMOTE SYSTEM. THE NAMES OF THESE FILES WILL
;BE PASSED TO THE LISTENER.
INTDA4: $CALL DISINT ;DEACTIVATE DISCONNECT CHANNEL
MOVEI S1,XFERFI ;FORCE OUT OF THE WAIT
MOVEM S1,LEV1PC ;STORE THE NEW PC HERE
JRST INTD15 ;GO RESTORE THE CONTEXT
REPEAT 0,<
;THE STATE OF CLUSTER LPTSPL IS "TRANSFER FILE MESSAGE RESPONSE. CHECK IF
;THE RESPONSE IS A SUCCESS ACK OR IF THE TRANSFER FILE RESPONSE MESSAGE
;MUST BE RESENT.
INTDA5: CAIN S1,1 ;IS THIS A SUCCESS MESSAGE?
JRST INTDA7 ;YES, SO FINISH UP
MOVE S2,J$DECR(J) ;NO, SO RESEND RESPONSE MESSAGE
;LISTENER'S CHECKSUM OF MESSAGE SENT TO IT DOES NOT EQUAL CHECKSUM CALCULATED
;LOCALLY. RESEND THE MESSAGE.
INTDA6: HRLI S2,(POINT 36) ;MAKE IT INTO A POINTER
MOVE S1,J$LCHN(J) ;PICK UP THE DECNET DCN: DEVICE JFN
LOAD T1,.MSTYP(J),MS.CNT ;PICK UP THE MESSAGE LENGTH
MOVNS T1 ;MAKE IT NEGATIVE
SOUTR% ;SEND THE MESSAGE
ERJMP INTD11 ;RE-OPEN THE LINK
JRST INTD15 ;GO RESTORE THE CONTEXT
>
;THE NEXTJOB REQUEST HAS BEEN PROCESSED, END THIS REQUEST
INTDA7: SETZM J$STAT(J) ;CLEAR THE STATE
TXZ S,INJOB!TEMFIL ;NO LONGER PROCESSING NEXTJOB MESSAGE
TXO S,GOODBY ;INDICATE LEAVING THIS JOB
SETZM J$TNUM(J) ;NO TEMPORARY FILES
$CALL CASTIM ;CLEAR AND RESET DECNET INACTIVITY TIMER
MOVEI S1,ENDREQ ;FORCE OUT OF THE WAIT
MOVEM S1,LEV1PC ;STORE THE NEW PC HERE
JRST INTD15 ;GO RESTORE THE CONTEXT
;THE LINK IS NO LONGER CONNECTED. CHECK THE CONTEXT
INTDA9: SKIPE JOBACT ;[3]IS THERE AN ACTIVE JOB?
TXNN S,INJOB!WAITIR ;YES, NEXTJOB MSG SENT/WAITING RESP?
JRST INTD15 ;NO TO EITHER, RETURN TO PREVIOUS CONTEXT
;CHECK IF WAITING FOR AN INTERRUPT MESSAGE RESPONSE FROM THE LISTENER.
;IF SO, THEN END THIS PRINT REQUEST
TXZN S,WAITIR ;WAITING FOR INTERRUPT MSG RESPONSE?
JRST INTD11 ;NO, GO RESET THE STATE
MOVEI S1,ENDREQ ;CHANGE PC TO END THIS REQUEST
MOVEM S1,LEV1PC ;SAVE THE PC
JRST INTD15 ;RETURN TO THE NEW CONTEXT
;THE NEXTJOB MESSAGE HAS BEEN SENT. RESTORE THE JOB STREAM STATE TO PRIOR
;TO SENDING THE NEXTJOB MESSAGE.
INTD11: $CALL RESET ;RESET THE STATE
JUMPF INTD12 ;SHUTDOWN ON A FATAL ERROR
MOVEI S1,CLJO14 ;SET PC TO PRIOR TO SENDING NEXTJOB MSG
MOVEM S1,LEV1PC ;SAVE THE CHANGED PC
JRST INTD15 ;RETURN TO CLJOB
;A FATAL ERROR HAS OCCURRED. SHUTDOWN LPTSPL
INTD12: MOVEI S1,[ASCIZ/Too many DECnet errors/]
INTD13: MOVEM S1,J$ERRA(J) ;SAVE THE ERROR TEXT ADDRESS
INTD14: MOVEI S1,SHULPT ;CHANGE THE PC TO SHUTDOWN LPTSPL
MOVEM S1,LEV1PC ;SAVE THE CHANGED PC
INTD15: $DEBRK ;RESTORE THE CONTEXT
SUBTTL XFERFI - TRANSFER FILES TO THE REMOTE SYSTEM
;XFERFI is invoked by the DECnet interrupt handler INTDAV after it
;receives a TRANSFER FILE message from the remote system. XFERFI
;copies the contents of the files that are inaccessible to the
;remote system into temporary files in a directory that is shared
;between the remote system and the local system.
;When all the files have been copied, XFERFI sends a TRANSFER FILE
;RESPONSE message to the remote listener.
;
;Call is: Invoked from DECnet interrupt handler INTDAV
; J/Job Context Pointer
;Returns: The inaccessible files have been copied to a shared directory
; and a TRANSFER FILE RESPONSE message has been sent. Goes into
; WAIT state.
;CHECK IF CHECKSUMMING IS ENABLED. IF IT IS, THEN CHECKSUM THE MESSAGE.
;IF THE CHECKSUMS DO NOT AGREE, THEN SEND A FAIL ACK.
XFERFI: HRRZ P1,J$DECR(J) ;PICK UP THE XFER FILE MESSAGE ADDRESS
REPEAT 0,<
; SKIPE P2,.MSCHS(P1) ;PICK UP ITS CHECKSUM WORD
; SETZM .MSCHS(P1) ;ZERO OUT IN CASE NEED TO DO A CHECKSUM
MOVEM P2,J$RCSM(J) ;REMEMBER CHECKSUM WORD FOR LATER
SKIPN P2 ;REMOTE NODE DOING CHECKSUMS?
JRST XFERF1 ;NO, SO DON'T CHECKSUM LOCALLY
SKIPN CHECKS ;IS CHECKSUMMING ENABLED LOCALLY?
JRST XFERF1 ;NO, SO GO PROCESS THE RESPONSE
MOVE S1,P1 ;PICK UP MESSAGE ADDRESS
$CALL CHKSUM ;CHECKSUM THE MESSAGE
CAMN P2,S1 ;DO THE CHECKSUMS EQUAL?
JRST XFERF1 ;YES, DETERMINE FILES TO BE XFERRED
$CALL ENAINT ;ACTIVATE DATA AVAILABLE CHANNEL
JUMPF S..CAC ;CRASH IF CAN'T ACTIVATE
$CALL SENFAI ;SEND A FAIL ACK
JUMPF XFER10 ;GO PROCESS THE ERROR
JRST CLJO11 ;GO WAIT FOR A RESPONSE
>
;SET UP FOR DETERMINING WHICH FILES NEED TO BE SENT TO THE REMOTE NODE
XFERF1: MOVE P2,.OHDRS+.TFNUM(P1) ;PICK UP NUMBER OF FILES
LOAD P4,.EQSPC(J),EQ.NUM ;PICK UP NUMBER OF FILES IN NEXTJOB MSG
CAMLE P2,P4 ;NUMBER XFER FILES CAN'T EXCEED FILES
$STOP (TMI,TRANSFER FILE MESSAGE INCONSISTENCY)
MOVEM P4,J$RFLN(J) ;SAVE NUMBER OF FILES FOR LATER
HRRZ P3,J$DECS(J) ;[3]ADDRESS OF MESSAGE TO SEND BACK
MOVEI S1,.OHDRS ;PICK UP RESPONSE MESSAGE HEADER SIZE
MOVE S2,P3 ;PLACE RESPONSE MESSAGE ADDRESS HERE
$CALL .ZCHNK ;ZERO OUT THE RESPONSE MESSAGE HEADER
MOVEM P2,.OHDRS+.TSNUM(P3) ;PLACE # OF FILES IN THE RESPONSE MSG
ADDI P3,.OHDRS+.TSHSZ ;POINT TO FIRST FILE STATUS BLOCK
ADDI P1,.OHDRS+.TFHSZ ;POINT TO FIRST FP POSITION BLOCK
LOAD E,.EQLEN(J),EQ.LOH ;PICK UP THE EQ HEADER LENGTH
ADD E,J ;POINT TO 1ST FP IN NEXTJOB MESSAGE
MOVEI P4,1 ;INDICATE CURRENT FP NUMBER
TXO S,TEMFIL ;INDICATE TEMP FILES BEING CREATED
XFERF2: MOVE S1,.TFFPP(P1) ;PICK UP RELATIVE FP POSITION
CAMLE S1,J$RFLN(J) ;MUST BE LESS OR EQUAL # FILES
JRST S..TMI ;CRASH ON AN INCONSISTENCY
SUB S1,P4 ;FIND THE DIFFERENCE OF FP POSITIONS
JUMPE S1,XFERF3 ;IF THE SAME, THEN CHECK FILE ACCESS
XFER2A: LOAD S2,.FPLEN(E),FP.LEN ;GET THE FP LENGTH
ADD E,S2 ;BUMP TO THE FD
LOAD S2,.FDLEN(E),FD.LEN ;GET THE FD LENGTH
ADD E,S2 ;BUMP TO THE NEXT FP
SOJG S1,XFER2A ;POSITION TO THE NEXT FP
;CHECK IF THE USER STILL HAS ACCESS TO THIS FILE. IF SO, THEN OPEN
;THE FILE. IF NOT, THEN INDICATE IN THE TRANSFER FILE STATUS MESSAGE
;BY ZEROING THE TEMPORARY FILE NAME WORD.
XFERF3: $CALL INPOPN ;OPEN THE FILE
JUMPF XFERF7 ;ON ERROR, ASSUME FILE INACCESSIBLE
MOVE S1,J$DIFN(J) ;PICK UP THE IFN OF THE FILE
MOVX S2,FI.CHN ;WANT TO PICK UP THE JFN OF THE FILE
$CALL F%INFO ;PICK UP THE FILE'S JFN
MOVEM S1,J$JFN(J) ;[10]SAVE THE JFN FOR LATER
MOVSI S2,2 ;WANT TWO WORDS FROM THE FDB
HRRI S2,.FBBYV ;WANT FILE I/O INFO AND NUMBER OF BYTES
MOVEI T1,J$FDB(J) ;WHERE TO PLACE THE FILE I/O INFO
GTFDB% ;PICK UP THE FILE I/O INFO
ERJMP XFERF6 ;ASSUME FILE IS NOT ACCESSIBLE
;CREATE A TEMPORARY FILE.
XFERF4: $CALL I%NOW ;GET CURRENT UDT
AND S1,[070707,,070707] ;MAKE IT SIXBIT NUMBERIC OFFSET FROM 0
TDO S1,[SIXBIT/000000/] ;MAKE SIXBIT NUMBERS FROM 0 THROUGH 7
MOVEM S1,J$SIXB(J) ;SAVE THE SIXBIT PART OF THE NAME
$TEXT (<-1,,J$TNAM(J)>,<^T/DIRNAM/:^N/CNTSTA/-^N/J$RNOD(J)/^W/S1/.LPT;P770000^0>) ;[10]
MOVX S1,GJ%SHT!GJ%NEW ;MUST BE A NEW FILE
HRROI S2,J$TNAM(J) ;POINT TO THE FILE
GTJFN% ;PICK UP THE JFN
ERJMP [CAIN S1,GJFX27 ;DOES THE FILE ALREADY EXIST?
JRST XFERF4 ;YES, TRY A DIFFERENT FILE NAME
JRST XFERF6 ] ;NO, INDICATE THE FILE IS INACCESSIBLE
HRRZS S1 ;ISOLATE THE JFN
MOVEM S1,J$TEM(J) ;SAVE THIS FILE'S JFN
LOAD S2,J$FDB(J),FB%BSZ ;PICK UP THE BYTE SIZE
LSH S2,^D30 ;PLACE WHERE OPENF% EXPECTS IT
TXO S2,OF%WR ;OPEN FOR WRITE
OPENF% ;OPEN THE TEMPORARY FILE
ERJMP XFERF6 ;INDICATE THE FILE IS INACCESSIBLE
;COPY THE FILE INTO THE TEMPORARY FILE
LOAD T3,J$FDB(J),FB%PGC ;PICK UP THE NUMBER OF PAGES IN FILE
SETZ T4, ;CURRENT PAGE NUMBER OF FILE
XFERF5: MOVE S1,T4 ;PICK UP THE PAGE NUMBER TO BE MAPPED
HRL S1,J$JFN(J) ;PICK UP THE JFN OF THE FILE
MOVE S2,J$FILB(J) ;PICK UP THE TRANSFER PAGE NUMBER
HRLI S2,.FHSLF ;PICK UP THE HANDLE
MOVX T1,PM%RD ;WANT READ ACCESS
PMAP% ;MAP THIS PAGE
ERJMP XFERF6 ;ASSUME CAN'T ACCESS THIS FILE
HRL S1,J$FADR(J) ;[10]PICK UP XFER PAGE ADDRESS
MOVE S2,J$OADR(J) ;[10]PICK UP OUTGOING XFER PAGE ADR
HRR S1,S2 ;[10]SOURCE,,DESTINATION
BLT S1,777(S2) ;[10]COPY FILE PAGE TO OUTGOING BUFFER
MOVE S1,J$FILO(J) ;[10]PICK UP PAGE NUMBER TO PMAP
HRLI S1,.FHSLF ;PICK UP FORK HANDLE
MOVE S2,T4 ;PAGE NUMBER TO MAP PAGE TO IN TEMP
HRL S2,J$TEM(J) ;PICK UP TEMP FILE'S JFN
MOVX T1,PM%RD ;WANT READ ACCESS
PMAP% ;MAP THE PAGE TO THE TEMP FILE
ERJMP XFERF6 ;ASSUME CAN'T ACCESS THIS FILE
SETO S1, ;INDICATE UNMAP THE PAGE FROM PROCESS
MOVE S2,J$FILB(J) ;PICK UP PAGE NUMBER
HRLI S2,.FHSLF ;PICK UP FORK HANDLE
MOVEI T1,1 ;UNMAP ONLY ONE PAGE
PMAP% ;UNMAP THE PAGE
ERJMP XFERF6 ;ASSUME CAN'T ACCESS THIS FILE
$DSCHD(0) ;FORCE A SCHEDULING PASS
;IF THIS JOB HAS BEEN ABORTED, CANCELLED OR REQUEUED, THEN END THIS PRINT
;REQUEST, OTHERWISE, GO MAP THE NEXT PAGE OF THE FILE
TXNE S,ABORT!RQB ;TIME TO QUIT?
JRST XFER14 ;YES, GO CLEAN UP
AOS T4 ;INCREMENT THE PAGE NUMBER
SOJG T3,XFERF5 ;MAP THE NEXT PAGE OF THE FILE
;UPDATE THE TEMPORARY'S FILE FDB TO REFLECT THE BYTE SIZE AND NUMBER OF
;BYTES OF THE FILE THAT WAS INACCESSIBLE TO THE REMOTE SYSTEM.
MOVE S1,J$TEM(J) ;PICK UP TEMP FILE'S JFN
HRLI S1,.FBBYV ;CHANGE THE FILE I/O WORD
TXO S1,CF%NUD ;DO NOT WAIT FOR DISK COPY UPDATE
SETO S2, ;UPDATE THE ENTIRE WORD
MOVE T1,J$FDB(J) ;NEW FILE I/O WORD
CHFDB% ;UPDATE THE FILE I/O WORD
ERJMP XFERF6 ;ON ERROR ASSUME CAN'T ACCESS FILE
MOVE S1,J$TEM(J) ;PICK UP TEMP FILE'S JFN
HRLI S1,.FBSIZ ;CHANGE THE NUMBER OF BYTES
SETO S2, ;UPDATE THE ENTIRE WORD
MOVE T1,J$FDB+1(J) ;NEW BYTE COUNT IN TEMP FILE
CHFDB% ;UPDATE THE BYTE COUNT OF TEMP FILE
ERJMP XFERF6 ;ON ERROR ASSUME CAN'T ACCESS FILE
;PLACE THE 6 CHARACTER NUMBERIC PART OF THE TEMPORARY FILE NAME INTO THE
;TRANSFER FILE RESPONSE MESSAGE.
SETZ S1, ;CLOSE, BUT DON'T DELETE, THE TEMP FILE
$CALL CFILES ;CLOSE THE FILE AND TEMPORARY FILE
MOVE S2,J$TNUM(J) ;PICK UP OFFSET INTO TEMP FILE NAME BLK
AOS J$TNUM(J) ;INCREMENT THE NUMBER OF TEMP FILES
MOVE S1,J$SIXB(J) ;PICK UP SIXBIT PART OF TEMP FILE NAME
MOVEM S1,.TSTFN(P3) ;PLACE IN THE RESPONSE MESSAGE
ADD S2,J ;POINT TO CURRENT TEMP FILE NAME
MOVEM S1,J$TFIN(S2) ;PLACE TEMP FILE NAME IN BLOCK
JRST XFERF8 ;GO PLACE IN RESPONSE MESSAGE
;HERE IF THE FILE IS INACCESSIBLE. INDICATE THIS IN THE TRANSFER FILE RESPONSE
;MESSAGE. ALSO CLOSE AND RELEASE ANY JFNS. IF A TEMPORARY FILE HAS BEEN
;CREATED, THEN DELETE IT.
XFERF6: SETO S1, ;DELETE THE TEMPORARY FILE
$CALL CFILES ;CLOSE THE FILE AND TEMPORARY FILE
XFERF7: SETZM .TSTFN(P3) ;INDICATE CAN'T ACCESS THIS FILE
XFERF8: MOVE S1,.TFFPP(P1) ;PICK UP RELATIVE FP POSITION
MOVEM S1,.TSFPP(P3) ;PLACE IN RESPONSE MESSAGE
;UPDATE THE COUNTERS
MOVE P4,.TFFPP(P1) ;CURRENT FP IN THE NEXTJOB MESSAGE
ADDI P1,.TFFPS ;POINT TO NEXT RELATIVE FP BLOCK
ADDI P3,.TSSIZ ;POINT TO NEXT BLOCK IN RESPONSE MSG
SOJG P2,XFERF2 ;COPY THE NEXT UNACCESSIBLE FILE
;FIND THE LENGTH OF TRANSFER FILES RESPONSE MESSAGE AND STORE IT IN THE MESSAGE
HRRZ P1,J$DECS(J) ;PICK UP THE ADDRESS OF THE MESSAGE
MOVE S1,.OHDRS+.TSNUM(P1) ;PICK UP THE NUMBER OF FILE STATUS BLKS
IMULI S1,.TSSIZ ;MULTIPLY BY SIZE OF THE BLOCKS
ADDI S1,.OHDRS+.TSHSZ ;ADD IN THE HEADER SIZES
STORE S1,.MSTYP(P1),MS.CNT ;PLACE MESSAGE LENGTH IN MESSAGE
MOVN T1,S1 ;[3]SAVE THE LENGTH FOR THE SOUTR%
REPEAT 0,<
;CHECKSUM THE MESSAGE IF NECESSARY
SKIPN CHECKS ;CHECKSUMMING ENABLED ON LOCAL SYSTEM?
JRST XFERF9 ;NO, SO JUST SEND THE MESSAGE
SKIPN J$RCSM(J) ;CHECKSUMMING ENABLED ON REMOTE SYSTEM?
JRST XFERF9 ;NO, SO JUST SEND THE MESSAGE
MOVE S1,P1 ;PICK UP ADDRESS OF RESPONSE MESSAGE
$CALL CHKSUM ;CHECKSUM THE MESSAGE
>
;SET STATE OF LPTSPL TO TRANSFER FILE MESSAGE RESPONSE. SEND THE MESSAGE
XFERF9: MOVX S1,.JSTMR ;TRANSFER FILE MESSAGE RESPONSE
MOVEM S1,J$STAT(J) ;UPDATE CLUSTER LPTSPL'S STATE
MOVE S1,J$LCHN(J) ;PICK UP DECNET DCN: DEVICE JFN
MOVE S2,J$DECS(J) ;PICK UP RESPONSE MESSAGE ADDRESS
SOUTR% ;SEND THE MESSAGE TO THE LISTENER
ERJMP XFER10 ;GO DETERMINE THE ERROR
$CALL ENAINT ;ACTIVATE THE DISCONNECT CHANNEL
JUMPT CLJO11 ;GO WAIT FOR A RESPONSE
JRST S..CAC ;CAN'T ACTIVATE CHANNEL
;A SOUTR% HAS FAILED. CHECK IF THE LINK IS STILL CONNECTED. IF IT IS,
;THEN TREAT AS A FATAL ERROR AND CONSEQUENTLY SHUTDOWN.
XFER10: $CALL RESTAR ;CAN THIS JOB BE RESTARTED?
JUMPF XFER12 ;NO, GO ACTIVATE DATA AVAILABLE CHANNEL
$CALL ENAINT ;YES, ACTIVATE DATA AVAILABLE CHANNEL
JUMPT CLJO14 ;ATTEMPT TO OPEN LINK AND TRY AGAIN
JRST S..CAC ;CAN'T ACTIVATE THE CHANNEL
XFER12: MOVEM S1,J$ERRA(J) ;SAVE THE ERROR TEXT ADDRESS
$CALL ENAINT ;ACTIVATE THE DATA AVAILABLE CHANNEL
JUMPF S..CAC ;CAN'T ACTIVATE THE CHANNEL
MOVE S1,J$ERRA(J) ;PICK UP THE ERROR TEXT ADDRESS
XFER13: $CALL REPERR ;NO, REPORT ERROR TO QUASAR AND ORION
PJRST SHUTIN ;SHUTDOWN
;A CANCEL, ABORT, OR REQUEST MESSAGE HAS BEEN GIVEN FOR THIS PRINT JOB.
;CLOSE ANY FILES, DELETE ANY TEMPORARY FILES, RE-ENABLE THE DATA AVAILABLE/
;DISCONNECT PENDING CHANNEL, AND SEND AN INTERRUPT MESSAGE TO THE LISTENER
;INDICATING THAT IT SHOULD CEASE PROCESSING THIS PRINT REQUEST. END THIS
;PRINT REQUEST.
XFER14: SETO S1, ;DELETE THE OPEN TEMPORARY FILE
$CALL CFILES ;DELETE THE TEMPORARY FILE
TXZ S,TEMFIL!INJOB ;INDICATE NO TEMPORARY FILES
$CALL DELTEM ;DELETE THE TEMPORARY FILES
$CALL SNDINT ;SEND THE INTERRUPT MSG TO LISTENER
JUMPT XFER15 ;GO WAIT FOR THE LISTENER RESPONSE
SKIPN S1 ;DID A FATAL ERROR OCCUR?
PJRST ENDREQ ;NO, SO JUST END THIS JOB
$CALL REPERR ;YES, TELL QUASAR AND ORION
PJRST SHUTIN ;SHUT DOWN THE PRINTER
XFER15: WAIT% ;WAIT FOR THE LISTENER RESPONSE
SUBTTL SHULPT - SHUTDOWN DUE TO A FATAL INTERRUPT ROUTINE ERROR
;SHULPT is invoked if routine INTDAV (the "data available or disconnect
;pending" interrupt routine) detects a fatal error. SHULPT informs QUASAR
;that the printer is shutting down. SHULPT informs ORION the reason why
;the printer is shutting down. The printer is then shut down.
;
;Call is: Invoked from INTDAV
; J/Job Context Pointer
;Returns: Returns through routine SHUTIN
SHULPT: MOVE S1,J$ERRA(J) ;PICK UP THE ERROR TEXT ADDRESS
$CALL REPERR ;REPORT THE ERROR TO QUASAR AND ORION
PJRST SHUTIN ;GO SHUT THE PRINTER DOWN
SUBTTL RESTAR - RESTART A NEXTJOB REQUEST
;RESTAR is called after a SOUTR% fails to the remote listener. RESTAR
;checks if the DECnet link is still connected. If it is, then the
;error is assumed to be fatal and the Cluster LPTSPL will be shut down.
;If the link is no longer connected, then the state of the Cluster
;LPTSPL is reset to the state prior to sending the NEXTJOB request to
;the remote listener.
;
;Call is: J/Job Context Pointer
;Returns true: The link is no longer connected. The state has been reset
;Returns false: The link is no longer connected and too many DECnet errors
; have occurred
; S1/Address of the error text
RESTAR: $CALL RESET ;RESET THE STATE
JUMPF RESTA2 ;SHUTDOWN ON A FATAL ERROR
$RETT ;INDICATE OPEN LINK AND TRY AGAIN
RESTA2: MOVEI S1,[ASCIZ/Too many DECnet errors/]
$RETF ;INDICATE SHUTDOWN
SUBTTL REPERR - REPORT FATAL ERROR TO QUASAR
;REPERR is called by Cluster LPTSPL when it has detected a fatal DECnet error
;or if accounting is enabled and the listener cannot be started.
;REPERR sends a SETUP RESPONSE message to QUASAR indicating that this LPTSPL
;is to be shut down. It also sends a message to ORION indicating that a fatal
;error has occurred and that it is being shut down.
;
;Call is: J/Job Context Pointer
; S1/Address of ASCIZ error text
;Returns: The SETUP RESPONSE message has been sent to QUASAR and a WTO
; message has been sent to ORION
REPERR: $WTO (<Fatal LPTSPL error detected>,<^T/0(S1)/>,@JOBOBA)
MOVX S1,%RSUDE ;NEVER AVAILABLE
$CALL RSETUP ;SEND SETUP RESPONSE TO QUASAR
$RET ;RETURN TO THE CALLER
REPEAT 0,<
SUBTTL CHKSUM - CHECKSUM DECNET MESSAGES
;CHKSUM checksums messages that Cluster LPTSPL sends to the listener.
;The checksum is stored in the checksum word. The listener, upon
;receipt of the message, also checksums it. If the checksums agree,
;then the listener sends a success ACK back to the sender, otherwise,
;it sends an error ACK.
;If the sender's node does not have checksumming enabled, then the
;sender sends a zero as the checksum value. The listener, in this
;case, always returns a success ACK.
;If the listener's node does not have checksumming enabled, then it
;always sends a success ACK back.
;(Note: 1. If the calculated checksum equals zero, then CHKSUM changes
; it to -1.
; 2. CHKSUM, when calculating the checksum, assumes that the checksum
; word contains zero.)
;
;Call is: S1/Address of the message
;Returns: The checksum has been calculated and placed in the message
; checksum word (.MSCHS).
; S1/Contains the checksum
CHKSUM: $SAVE <P1> ;SAVE THIS AC
;INITIALIZE THE CHECKSUM PARAMETERS
LOAD S2,.MSTYP(S1),MS.CNT ;PICK UP LENGTH OF THE MESSAGE
MOVSS S2 ;PLACE LENGTH FOR AOBJN
MOVNS S2 ;MAKE THE COUNTER
HRR S2,S1 ;COMPLETE THE AOBJN COUNTER
SETZ P1, ;SET CHECKSUM TO ZERO
JCRY0 .+1 ;CLEAR THE CARRY 0 BIT
;COMPUTE THE CHECKSUM
COMCH1: ADD P1,0(S2) ;ADD THE NEXT MESSAGE WORD TO CHECKSUM
JCRY0 [AOJA P1,.+1] ;ADD ONE IF CARRY 0 BIT IS SET
AOBJN S2,COMCH1 ;GO ADD IN THE NEXT MESSAGE WORD
;IF CHECKSUM IS 0, THEN MAKE -1
SKIPN P1 ;IF CHECKSUM NOT 0, THEN FINISHED
SETO P1, ;MAKE THE CHECKSUM -1
; MOVEM P1,.MSCHS(S1) ;PLACE CHECKSUM IN THE MESSAGE
MOVE S1,P1 ;PLACE CHECKSUM IN RETURN AC
$RET ;RETURN TO THE CALLER
>
SUBTTL RESET - RESET THE STATE OF CLUSTER LPTSPL
;RESET is called if Cluster LPTSPL detects that the DECnet link is no
;longer connected while it is processing a print request. Cluster LPTSPL
;assumes that the remote listener did not receive or did not complete
;processing the NEXTJOB request. Cluster LPTSPL will, therefore, attempt
;to resend the NEXTJOB request. RESET resets the state of Cluster LPTSPL
;to just prior to its sending the NEXTJOB request. RESET does the following:
; 1. Closes and releases the DECnet DCN: device JFN.
; 2. If a file to be printed is open, then it is closed.
; 3. If temporary files are being created and they have not all yet been
; created, then any temporary files are deleted and expunged.
;RESET also determines if too many DECnet errors (i.e., losing DECnet
;connections) have occurred while processing the current job request.
;If so, then Cluster LPTSPL is shut down.
;
;Call is: J/Job Context Pointer
;Returns true: The state of Cluster LPTSPL has been successfully reset
;Returns false: Too many DECnet connection losts have occurred while
; processing the current job request
RESET: SKIPL J$LCHN(J) ;IS THERE A DECNET DCN: DEVICE JFN?
$CALL ABTLNK ;YES, CLOSE AND RELEASE DECNET DCN: JFN
SETO S1, ;DELETE ANY OPEN TEMPORARY FILE
$CALL CFILES ;CLOSE ANY OPEN FILES
TXZE S,TEMFIL ;HAVE TEMPORARY FILES BEEN CREATED?
$CALL DELTEM ;YES, DELETE ANY TEMPORARY FILES
SETZM J$STAT(J) ;CLEAR STATE WORD
TXZ S,INJOB ;INDICATE PRIOR TO NEXTJOB SEND
AOS S1,J$CONF(J) ;INCREMENT # OF CONNECTION FAILURES
CAILE S1,MAXFAI ;TIME TO SHUTDOWN?
$RETF ;YES, INDICATE TO CALLER TO SHUTDOWN
$RETT ;INDICATE TRY OPEN LINK AGAIN
SUBTTL UPDMSG - UPDATE THE NEXTJOB MESSAGE
;UPDMSG is called by Cluster LPTSPL to update the NEXTJOB message before
;it is sent to the remote node. The updating consists of:
; 1. Indicate the NEXTJOB message is from a different node than the node
; it is to be printed on.
; 2. Indicate if accounting is enabled on the node the message came from
; 3. Indicate in word .EQNOD the node the message has come from
; 4. If a generic LPT object is specified, then ensure that the units
; field is zero.
;
;Call is: J/Job Context Pointer
;Returns: The NEXTJOB message has been updated
UPDMSG: MOVE S1,CNTSTA ;PICK UP THE LOCAL NODE NAME
MOVEM S1,.EQNOD(J) ;PLACE IN THE NEXTJOB MESSAGE
IFN FTACNT<
MOVX S1,EQ.RLT!EQ.RAI ;REMOTE LPT AND ACCOUNTING ENABLED
>
IFE FTACNT<
MOVX S1,EQ.RLT ;CAME FROM A REMOTE LPT
>
IORM S1,.EQSEQ(J) ;INDICATE IN THE MESSAGE
MOVX S1,.CLLPT ;[3]PICK UP THE CLUSTER LPT BIT
ANDCAM S1,.EQROB+.ROBTY(J) ;[3]TURN OFF FOR THE REMOTE QUASAR
SETZ S2, ;[5]ASSUME %GENRC
LOAD S1,.EQROB+.ROBAT(J),RO.ATR ;[5]PICK UP THE ATTRIBUTES
CAIN S1,%GENRC ;[5]GENERIC?
STORE S2,.EQROB+.ROBAT(J),RO.UNI ;[5]YES, ZERO THE UNITS FIELD
$RET ;RETURN TO THE CALLER
SUBTTL CFILES - CLOSE THE INACCESSIBLE FILE AND TEMPORARY FILE.
;CFILES is called to close a file that has had its contents copied to a
;temporary file on a structure that is shared between the remote system
;and the local system.
;If the caller has detected an error condition, then the temporary file
;is also deleted
;
;Call is: J/Job Context Pointer
; S1/0 Just close the temporary file
; S1/-1 Close and delete the temporary file
;Returns: The files have been closed
;CLOSE A FILE SPECIFIED IN THE NEXTJOB REQUEST
CFILES: $SAVE <T1,T2,T3> ;SAVE THESE AC
MOVE T3,S1 ;SAVE THE FLAG WORD
SKIPE S1,J$DIFN(J) ;IS A FILE OPENED?
$CALL F%REL ;YES, CLOSE IT
JUMPT CFILE3 ;ON SUCCESS, CLOSE TEMP FILE
;CHECK IF THE ERROR IS "FILE STILL MAPPED". IF SO, THEN UNMAP PAGE
CAIE S1,ERFSM$ ;IS THE FILE STILL MAPPED?
JRST CFILE2 ;NO, ATTEMPT TO RELEASE THE JFN
SETO S1, ;INDICATE UNMAP THE PAGE FROM PROCESS
MOVE S2,J$FILB(J) ;PICK UP PAGE NUMBER
HRLI S2,.FHSLF ;PICK UP FORK HANDLE
MOVEI T1,1 ;UNMAP ONLY ONE PAGE
PMAP% ;UNMAP THE PAGE
ERJMP CFILE2 ;ATTEMPT TO RELEASE JFN ON AN ERROR
MOVE S1,J$JFN(J) ;PICK UP THE FILE'S JFN
CLOSF% ;CLOSE AND RELEASE THE JFN
ERJMP CFILE2 ;ATTEMPT TO RELEASE JFN ON AN ERROR
CFILE2: MOVE S1,J$JFN(J) ;PICK UP THE JFN
RLJFN% ;RELEASE THE JFN
ERJMP .+1 ;IGNORE ANY ERRORS
;CLOSE AND, IF INDICATED, DELETE THE CURRENT TEMPORARY FILE
CFILE3: SKIPN S1,J$TEM(J) ;IS A TEMPORARY FILE OPEN?
JRST CFILE7 ;NO, INDICATE ALL FILES CLOSED
TXO S1,CO%NRJ ;DO NOT RELEASE THE JFN
CLOSF% ;CLOSE THE TEMPORARY FILE
ERJMP CFILE4 ;CHECK IF FILE IS NOT OPENED
JRST CFILE5 ;YES, DELETE THE TEMPORARY FILE
CFILE4: CAIE S1,CLSX1 ;IS THE ERROR BECAUSE FILE NOT OPENED?
JRST CFILE6 ;NO, JUST RELEASE THE JFN
CFILE5: SKIPL T3 ;DELETE THE TEMPORARY FILE?
JRST CFILE6 ;NO, RELEASE THE JFN
MOVE S1,J$TEM(J) ;[3]PICK UP THE JFN
TXO S1,DF%EXP ;[3]INDICATE EXPUNGE THIS FILE
DELF% ;DELETE AND EXPUNGE THE FILE
ERJMP CFILE6 ;RELEASE THE JFN
JRST CFILE7 ;INDICATE NO FILES OPENED
CFILE6: MOVE S1,J$TEM(J) ;PICK UP THE JFN
RLJFN% ;RELEASE THE JFN
ERJMP .+1 ;IGNORE ANY ERRORS
;IT IS POSSIBLE THAT A JFN WAS OBTAINED, BUT BEFORE ITS VALUE COULD
;BE SAVED, THE LINK LOST ITS CONNECTION. THEREFORE, RELEASE ANY UNOPENED
;JFN
CFILE7: SKIPN T3 ;[3]WAS THE FILE ONLY TO BE CLOSED?
JRST CFILE8 ;[3]YES, SO DON'T RELEASE UNOPENED JFNS
MOVX S1,CZ%NIF!CZ%NCL ;INDICATE RELEASE ONLY UNOPENED JFNS
CLZFF% ;RELEASE ANY UNOPENED JFNS
ERJMP .+1 ;IGNORE ANY ERRORS
CFILE8: SETZM J$DIFN(J) ;[3]INDICATE NO FILE IS OPENED
SETZM J$JFN(J) ;AND HERE ALSO
SETZM J$TEM(J) ;INDICATE NO TEMP FILE OPENED
$RET ;RETURN TO THE CALLER
SUBTTL DELTEM - DELETE AND EXPUNGE ANY TEMPORY FILES
;DELTEM is called as part of resetting a Cluster LPTSPL's state to just
;prior to sending a NEXTJOB message to the remote node. The resetting of
;the state occurs after LPTSPL has detected the link is no longer
;connected while processing a NEXTJOB request.
;If the link became disconnected while Cluster LPTSPL was creating
;temporary files, then these files are deleted and expunged.
;
;Call is: J/Job Context Pointer
;Returns: The temporary files associated with the current NEXTJOB
; message have been deleted and expunged.
DELTEM: $SAVE <T1,T2,T3,T4> ;SAVE THESE AC
SKIPN T3,J$TNUM(J) ;PICK UP THE NUMBER OF TEMP FILES
JRST DELTE6 ;QUIT NOW IF THERE ARE NONE
MOVEI T4,J$TFIN(J) ;PICK UP ADDRESS OF THE FIRST TEMP FILE
DELTE2: SKIPN S1,0(T4) ;ANY MORE TEMPORARY FILES?
JRST DELTE5 ;NO, SO QUIT
;DELETE AND EXPUNGE THE TEMPORARY FILE
$TEXT (<-1,,J$TNAM(J)>,<^T/DIRNAM/:^N/CNTSTA/-^N/J$RNOD(J)/^W/S1/.LPT;P770000^0>)
MOVX S1,GJ%SHT ;WANT A SHORT JFN
HRROI S2,J$TNAM(J) ;POINT TO THE FILE
GTJFN% ;PICK UP THE JFN
ERJMP DELTE4 ;TRY THE NEXT FILE
HRRZS S1 ;ISOLATE THE JFN
MOVEM S1,J$TEM(J) ;SAVE IN THE EVENT OF AN ERROR
TXO S1,DF%EXP ;INDICATE WANT TO EXPUNGE THIS FILE
DELF% ;DELETE AND EXPUNGE THE FILE
ERJMP DELTE3 ;RELEASE THE JFN
JRST DELTE4 ;GO CHECK FOR ANY MORE FILES
DELTE3: MOVE S1,J$TEM(J) ;PICK UP THE JFN
RLJFN% ;RELEASE THE JFN
ERJMP .+1 ;IGNORE ANY ERRORS
DELTE4: AOS T4 ;POINT TO THE NEXT TABLE ENTRY
SOJG T3,DELTE2 ;GO CHECK FOR ANOTHER TEMP FILE
DELTE5: MOVE S1,J$TNUM(J) ;PICK UP SIZE OF TEMP FILE NAMES BLOCK
MOVEI S2,J$TFIN(J) ;PICK UP ADDRESS OF TEMP FILE NAMES BLK
$CALL .ZCHNK ;RESTORE THE STATE OF THE BLOCK
SETZM J$TNUM(J) ;INDICATE NO TEMPORARY FILES EXIST
DELTE6: SETZM J$TEM(J) ;RESTORE THE STATE OF TEMP JFN HOLDER
$RET ;RETURN TO THE CALLER
SUBTTL SENFAI - SEND A DECNET FAIL MESSAGE TO THE LISTENER
REPEAT 0,<
;SENFAI is called if checksumming is enabled both on the local system
;and the remote system and the checksum of the message received from
;the remote system does not agree with the checksum calculated on the
;local system. A Failure ACK is sent to the remote system indicating
;it to resend its message.
;
;Call is: J/Job Context Pointer
;Returns true: The Failure ACK was sent to the listener
;Returns false: The Failure ACK could not be sent to the listener
SENFAI: $SAVE <T1,T2> ;SAVE THESE AC
MOVE S1,J$LCHN(J) ;PICK UP THE DCN: DEVICE JFN
MOVEI S2,T1 ;ADDRESS OF THE MESSAGE
HRLI S2,(POINT 36,) ;MAKE IT INTO A POINTER
MOVNI T1,2 ;INDICATE A FAILURE MESSAGE
SOUTR% ;SEND THE MESSAGE TO THE SENDER
ERJMP .RETF ;INDICATE AN ERROR TO THE CALLER
$RETT ;INDICATE SUCCESS TO THE CALLER
>;END OF REPEAT 0
SUBTTL SNDINT - SEND A DECNET INTERRUPT MESSAGE TO THE LISTENER
;SNDINT is called if an ABORT, CANCEL or REQUEUE message is received while
;Cluster LPTSPL is copying temporary files to the shared directory. SNDINT
;sends an interrupt message to the listener. The interrupt message indicates
;to the listener to cease processing the print request.
;If a previous response to an interrupt message has not yet been received
;from the listener, then the link is aborted.
;
;Call is: J/Job Context Pointer
;Returns true: An interrupt message was successfully sent
;Returns false: The interrupt message was not successfully sent
; S1/0 The connection has been lost
; S1/Address of fatal error text
;Crashes: Cannot activate the data available channel
SNDINT: $SAVE <T1,T2> ;SAVE THESE AC
TXO S,WAITIR ;INDICATE WAITING FOR INTERRUPT MSG RES
$CALL ENAINT ;ACTIVATE THE DATA AVAILABLE CHANNEL
JUMPF S..CAC ;CAN'T ACTIVATE THE CHANNEL
MOVE S1,J$LCHN(J) ;PICK UP THE DCN: DEVICE JFN
MOVEI S2,.MOSIM ;INDICATE SEND AN INTERRUPT MESSAGE
MOVEI T1,T3 ;DON'T CARE ABOUT THE CONTENTS OF MSG
HRLI T1,(POINT 8,) ;[3]MAKE INTO A POINTER
MOVEI T2,1 ;MESSAGE LENGTH IS ONE BYTE
MTOPR% ;SEND THE INTERRUPT MESSAGE
ERJMP SNDIN2 ;ERROR - FATAL OR LINK IS LOST
$RETT ;INDICATE MESSAGE WAS SENT
SNDIN2: $CALL S%ERR ;PICK UP THE ERROR TEXT ADDRESS
SKIPT ;SKIP IF HAVE THE ERROR TEXT
MOVEI S1,[ASCIZ/Can't send interrupt message/] ;NO, MAKE ONE UP
MOVEM S1,J$ERRA(J) ;SAVE THE ERROR TEXT ADDRESS
$CALL CHKLNK ;CHECK IS THE LINK IS STILL AROUND
JUMPT SNDIN3 ;YES IT IS, THEN CONSIDER A FATAL ERROR
SKIPN S1 ;A FATAL ERROR DETECTED BY CHKLNK?
$RETF ;NO, INDICATE THE LINK IS NOT CONNECTED
SNDIN3: MOVE S1,J$ERRA(J) ;PICK UP THE FATAL ERROR TEXT ADDRESS
$RETF ;RETURN TO THE CALLER
SUBTTL RCVINT - PICK UP AN INTERRUPT MESSAGE RESPONSE FROM LISTENER
;RCVINT is the interrupt handler for interrupt messages from the listener in
;response to an interrupt message previously sent by Cluster LPTSPL. RCVINT
;picks up the interrupt message and indicates that Cluster LPTSPL is no
;longer expecting an interrupt message response from the listener.
;
;Call is: J/Job Context Pointer
;Returns: The interrupt message was picked up from the listener
RCVINT: $BGINT 1, ;SAVE THE ENVIRONMENT
MOVE S1,J$LCHN(J) ;PICK UP THE DCN: DEVICE JFN
MOVEI S2,.MORIM ;PICK UP THE FUNCTION CODE
MOVEI T1,T3 ;WHERE TO PLACE THE MESSAGE
HRLI T1,(POINT 8,) ;[3]MAKE INTO A POINTER
MTOPR% ;PICK UP THE MESSAGE
ERJMP RCVIN2 ;ON AN ERROR, ABORT THE LINK
SKIPA ;DON'T ABORT THE LINK
RCVIN2: $CALL ABTLNK ;ABORT THE LINK, RELEASE THE DCN: JFN
TXZ S,WAITIR ;NO LONGER WAITING FOR INTERRUPT RES
MOVEI S1,ENDREQ ;INDICATE END THE PRINT REQUEST
MOVEM S1,LEV1PC ;SAVE THE NEW PC VALUE
$DEBRK ;GO TO THE NEW CONTEXT
SUBTTL ENDFRK - INFERIOR FORK TERMINATION INTERRUPT HANDLER
;ENDFRK is invoked if Cluster LPTSPL's remote accounting inferior fork
;crashes. ENDFRK determines if the listener has crashed MAXCRH times.
;If it has, then ENDFRK considers this to be a fatal error and shuts
;down Cluster LPTSPL. If it has not, then ENDFRK restarts the listener.
;
;Call is: Invoked by the inferior fork crashing
;Returns: To previous context is no fatal error is detected, else returns
; context to Cluster LPTSPL shutdown
ENDFRK: $BGINT 1, ;SAVE THE PREVIOUS CONTEXT
MOVE S1,J$FRKH(J) ;PICK UP THE LISTENER'S HANDLE
KFORK% ;KILL THE LISTENER
ERJMP .+1 ;IGNORE ANY ERRORS
AOS S1,J$CRNM(J) ;INCREMENT THE NUMBER OF CRASHES
CAILE S1,MAXCRH ;HAS LISTENER CRASHED TOO MANY TIMES?
JRST ENDFR2 ;YES, GO SHUTDOWN THIS PRINTER
$CALL STLIS0 ;[3]START UP A NEW LISTENER
JUMPT ENDFR3 ;RETURN TO THE PREVIOUS CONTEXT
SKIPA ;ALREADY HAVE AN ERROR TEXT ADDRESS
ENDFR2: MOVEI S1,[ASCIZ/Cluster LPTSPL accounting listener encountered a fatal error/]
MOVEM S1,J$ERRA(J) ;SAVE THE ERROR TEXT ADDRESS
MOVEI S1,SHULPT ;PICK UP SHUTDOWN ROUTINE ADDRESS
MOVEM S1,LEV1PC ;CHANGE THE PC ON RETURN
ENDFR3: $DEBRK ;LEAVE THE INTERRUPT ROUTINE
SUBTTL DISINT - DEACTIVATE DATA AVAILABLE CHANNEL
;DISINT is called to deactivate the data available or disconnect pending
;channel. DISINT is called when one or more files in a print request are
;not accessible to the remote system. The files are copied to a directory
;shared between the remote and local systems. After a page of a file is
;copied to the shared directory, $DSCHD is called to check if the print
;request has been cancelled, aborted or requeued. The file transferrals
;are not done at interrupt level. If the link is lost while this transferral
;takes place, then it is desirable that the transferral not be interrupted.
;To insure this, the data available or disconnect pending channel is
;deactivated.
;
;Call is: No arguments
;Returns: The channel has been deactivated
DISINT: $SAVE <T1,T2> ;SAVE THESE AC
MOVEI S1,.FHSLF ;PICK UP THE FORK HANDLE
MOVX S2,1B2 ;CHANNEL TO DEACTIVATE
DIC% ;DEACTIVATE THE CHANNEL
ERJMP .+1 ;IGNORE ANY ERRORS
$RET ;RETURN TO THE CALLER
SUBTTL ENAINT - ACTIVATE THE DATA AVAILABLE CHANNEL
;ENAINT is called to activate the data available and disconnect pending
;channel. ENAINT is called after all the files have been copied into
;temporary files in the shared directory or as part of error processing if
;an error was detected in copying the files into temporary files in the
;shared directory.
;
;Call is: No arguments
;Returns true: Channel has been activated
;Returns false: Channel could not be activated
ENAINT: $SAVE <T1,T2> ;SAVE THESE AC
MOVEI S1,.FHSLF ;PICK UP THE FORK HANDLE
MOVX S2,1B2 ;CHANNEL TO ACTIVATE
AIC% ;ACTIVATE THE CHANNEL
ERJMP .RETF ;INDICATE ERROR IN ACTIVATING CHANNEL
$RETT ;INDICATE CHANNEL IS ACTIVATED
SUBTTL CHKLNK - CHECK THE STATUS OF THE SENDER DECNET LINK
;CHKLNK is called to check the status of the Cluster LPTSPL sender's DECnet
;link to the LISSPL listener. If there is no connection (or there is no longer
;a connection), then the DECnet link is closed and the DECnet JFN released.
;CHKLNK assumes that the DECnet link was previously (or still is connected).
;
;Call is: J/Job Context Pointer
;Returns true: The DECnet link is connected
;Returns false: S1/-1 The DECnet link is waiting for a connection
; S1/0 There is no DECnet link connection
; The DECnet link has been aborted
; S1/Error text address. A fatal error has occured
; The DECnet link has been aborted
CHKLNK: $SAVE <T1,T2> ;SAVE THESE AC, DESTROYED BY JSYS
;OBTAIN THE DECNET LINK STATUS.
MOVE S1,J$LCHN(J) ;PICK UP THE DECNET JFN
MOVEI S2,.MORLS ;WANT THE STATUS OF THE LINK
MTOPR% ;OBTAIN THE STATUS OF THE LINK
ERJMP CHKLN2 ;CANNOT OBTAIN THE LINK STATUS
MOVEM T1,J$LSTS(J) ;SAVE THE LINK STATUS IN SENDER BLOCK
;DETERMINE IF THE LINK IS CONNECTED. IF IT IS NOT, THEN CLOSE AND RELEASE
;THE JFN.
TXNE T1,MO%CON ;IS THE LINK CONNECTED?
$RETT ;YES, RETURN TRUE
TXNE T1,MO%WCC ;WAITING FOR A LINK?
JRST CHKLN3 ;YES, GO RETURN TO THE CALLER
$CALL ABTLNK ;CLOSE AND RELEASE THE JFN
SETZ S1, ;INDICATE ERROR NOT FATAL
JRST CHKLN4 ;GO RETURN TO THE CALLER
CHKLN2: $CALL S%ERR ;PICK UP ADDRESS OF FATAL ERROR TEXT
SKIPT ;UNABLE TO PICK UP ERROR TEXT ADR?
MOVEI S1,[ASCIZ/Unable to obtain link status/] ;YES
MOVEM S1,J$ERRA(J) ;SAVE THE ERROR TEXT ADDRESS
$CALL ABTLNK ;CLOSE AND RELEASE THE JFN
MOVE S1,J$ERRA(J) ;PICK UP THE ERROR TEXT ADDRESS
$RETF ;INDICATE ERROR TO THE CALER
CHKLN3: SETO S1, ;INDICATE WAITING FOR A CONNECTION
CHKLN4: $RETF ;INDICATE ERROR TO THE CALLER
SUBTTL REMREL - RELEASE A PRINT REQUEST FROM A REMOTE NODE
;REMREL is called after a print request that originated from a remote
;node has been printed. REMREL builds a release message. If accounting
;is enabled on the node where the print request originated, then
;accounting information is included in the print request. If any files
;specified in the print request were requested to be deleted, but are
;not accessible to this system, then the file names of any such files
;are included in the release message.
;After building the RELEASE message, REMREL sends it to QUASAR.
;
;Call is: J/Job Context Pointer
;Returns: The RELEASE message has been built and sent to QUASAR.
;Crashes: The RELEASE message could not be sent to QUASAR.
REMREL: $SAVE <P1> ;SAVE THIS AC
$CALL M%GPAG ;GET A PAGE FOR THE RELEASE MESSAGE
MOVE P1,S1 ;REMEMBER THE PAGE ADDRESS
MOVX S1,RF.REM ;INDICATE REQUEST ORIGINATED REMOTELY
STORE S1,REL.FL(P1),RF.DEC ;SAVE IN THE RELEASE MESSAGE
MOVE S1,.EQITN(J) ;PICK UP THE PRINT REQUEST'S ITN
MOVEM S1,REL.IT(P1) ;PLACE IN THE RELEASE MESSAGE
;CHECK IF ACCOUNTING IS ENABLED ON THE NODE THE PRINT REQUEST ORIGINATED
;FROM. ALSO CHECK IF THE PRINT REQUEST CONTAINS AN INVALID ACCOUNT STRING.
MOVE S1,.EQSEQ(J) ;PICK UP THE JOB REQUEST INFO WORD
TXNE S1,EQ.IAS ;INVALID ACCOUNT STRING?
JRST REMRE1 ;YES, DON'T INCLUDE ACCOUNTING INFO
TXNN S1,EQ.RAI ;ACCOUNTING ON THE REQUESTING NODE?
JRST REMRE1 ;NO, DON'T INCLUDE ACCOUNTING INFO
MOVX S1,RF.ACT ;RELEASE MSG CONTAINS ACCOUNTING INFO
IORM S1,REL.FL(P1) ;INDICATE IN THE MESSAGE
MOVX S1,.FHSLF ;PICK UP THE FORK HANDLE
RUNTM% ;CALCULATE THE RUN TIME
ERJMP [SETZ S1, ; THIS SHOULD NEVER HAPPEN
JRST .+1 ] ; CONTINUE PROCESSING
ADDM S1,J$ARTM(J) ;PLACE IN THE MESSAGE
$CALL ADDACT ;ADD THE ACCOUNTING INFORMATION TO MSG
;DELETE ANY FILES SPECIFIED TO BE DELETED IN THE PRINT REQUEST. ANY FILE
;THAT IS SPECIFIED TO BE DELETED, BUT IS NOT ACCESSIBLE TO THIS SYSTEM,
;ADD THE FILE'S NAME TO THE RELEASE MESSAGE.
REMRE1: MOVE S1,.EQNOD(J) ;[3]PICK UP NODE PRINT REQUEST WAS FROM
MOVEM S1,REL.NN(P1) ;[3]LET QUASAR KNOW WHERE TO SEND TO
$CALL REMDIS ;TAKE CARE OF FILES TO BE DELETED
JUMPF REMRE2 ;NO DELETED FILE NAMES IN THIS MSG
MOVX S2,RF.DEL ;INDICATE FILES ARE INCLUDED IN MSG
IORM S2,REL.FL(P1) ;INDICATE IN THE RELEASE MESSAGE
;FINISH BUILDING THE RELEASE MESSAGE AND SEND IT OFF TO QUASAR
REMRE2: MOVSI S2,PAGSIZ ;[3]PICK UP MESSAGE SIZE
HRRI S2,.QOREL ;INCLUDE RELEASE MESSAGE FUNCTION CODE
MOVEM S2,.MSTYP(P1) ;PLACE IN THE RELEASE MESSAGE
MOVE T1,P1 ;PICK UP THE MESSAGE ADDRESS
$CALL SNDQSR ;SEND THE MESSAGE TO QUASAR
$RET ;RETURN TO THE CALLER
SUBTTL ADDACT - ADD ACCOUNTING INFORMATION TO A RELEASE MESSAGE
;ADDACT is called during the building of a RELEASE message for a print
;request that originated from a remote node in the cluster that has
;accounting enabled. ADDACT adds to the release message the accounting
;information that will be used by the remote system when it performs
;the USAGE% JSYS.
;
;Call is: J/Job Context Pointer
; P1/RELEASE message address
;Returns: The accounting information has been added to the release message
ADDACT: MOVE S1,J$ARTM(J) ;PICK UP THE RUN TIME
MOVEM S1,REL.RT(P1) ;PLACE IN THE RELEASE MESSAGE
MOVE S1,J$ADRD(J) ;PICK UP THE DISK READS
MOVEM S1,REL.DR(P1) ;PLACE IN THE RELEASE MESSAGE
MOVE S1,.EQJOB(J) ;PICK UP THE SIXBIT JOB NAME
MOVEM S1,REL.JN(P1) ;PLACE IN THE RELEASE MESSAGE
MOVE S1,J$LDEV(J) ;PICK UP THE DEVICE NAME
MOVEM S1,REL.DN(P1) ;PLACE IN THE RELEASE MESSAGE
MOVE S1,J$ASEQ(J) ;PICK UP THE JOB SEQUENCE NUMBER
MOVEM S1,REL.SN(P1) ;PLACE IN THE RELEASE MESSAGE
MOVE S1,J$APRT(J) ;PICK UP THE TOTAL PAGES PRINTED
MOVEM S1,REL.PP(P1) ;PLACE IN THE RELEASE MESSAGE
MOVE S1,J$AFXC(J) ;PICK UP THE TOTAL FILES PROCESSED
MOVEM S1,REL.FP(P1) ;PLACE IN THE RELEASE MESSAGE
MOVE S1,.EQAFT(J) ;PICK UP CREATION DATE/TIME OF REQUEST
MOVEM S1,REL.CD(P1) ;PLACE IN THE RELEASE MESSAGE
MOVE S1,J$RTIM(J) ;PICK UP SCHEDULED DATE/TIME
MOVEM S1,REL.SD(P1) ;PLACE IN THE RELEASE MESSAGE
MOVE S1,J$FORM(J) ;PICK UP THE FORMS TYPE
MOVEM S1,REL.FT(P1) ;PLACE IN THE RELEASE MESSAGE
MOVE S1,J$APRI(J) ;PICK UP THE JOB'S PRIORITY
MOVEM S1,REL.FP(P1) ;PLACE IN THE RELEASE MESSAGE
;PLACE THE USER NAME IN THE RELEASE MESSAGE
MOVEI S1,REL.UN(P1) ;WHERE TO PLACE USER NAME IN MESSAGE
MOVE S2,S1 ;REMEMBER STARTING DESTINATION ADDRESS
HRLI S1,.EQOWN(J) ;PICK UP USER NAME ADDRESS
ADDI S2,EQNMSZ-1 ;CALCULATE THE END DESTINATION ADDRESS
BLT S1,0(S2) ;COPY THE USER NAME INTO RELEASE MSG
;PLACE THE ACCOUNT STRING IN THE RELEASE MESSAGE
MOVEI S1,REL.AS(P1) ;WHERE TO PLACE ACCOUNT STRING IN MSG
MOVE S2,S1 ;REMEMBER STARTING DESTINATION ADDRESS
HRLI S1,.EQACT(J) ;PICK UP ACCOUNT STRING ADDRESS
ADDI S2,EQASSZ-1 ;[3]CALCULATE THE END DESTINATION ADR
BLT S1,0(S2) ;COPY ACCOUNT STRING INTO RELEASE MSG
$RET ;RETURN TO THE CALLER
SUBTTL REMDIS - DELETE FILES AND PLACE FILE NAMES IN RELEASE MESSAGE
;REMDIS is called during the creation of the RELEASE message for a print
;request that orginated on a remote node in the cluster. REMDIS deletes
;any files that were indicated in the print request to be deleted. If a
;file specified to be deleted is not accessible to the system, then its
;name is placed in the release message.
;Any temporary files associated with the print request are also deleted.
;
;Call is: J/Job Context Pointer
; P1/RELEASE message address
;Returns true: One or more files need to be deleted on the requesting node
;Returns false: No files need to be deleted on the requesting node
REMDIS: $SAVE <T1,T2,T3,T4> ;SAVE THESE AC
;SET UP THE SEARCH FOR THE FILES TO BE DELETED AND FILE NAMES TO BE PLACED
;IN THE RELEASE MESSAGE.
MOVEI T3,REL.RS(P1) ;[3]POINT TO THE END OF THE RELEASE MSG
LOAD E,.EQLEN(J),EQ.LOH ;PICK UP THE LENGTH OF THE EQ
ADD E,J ;POINT TO THE FIRST FP
LOAD T1,.EQSPC(J),EQ.NUM ;PICK UP # OF FILES IN PRINT REQUEST
SETZ T4, ;LENGTH OF FD BLOCKS IN RELEASE MESSAGE
;CHECK IF THERE IS A TEMPORARY FILE ASSOCIATED WITH THE FILE. IF THERE IS,
;THEN DELETE IT.
REMDI1: MOVE T2,.FPINF(E) ;PICK UP THIS FILE'S INFORMATION WORD
TXNN T2,FP.CPY ;IS THERE A TEMP FILE WITH THIS FILE?
JRST REMDI2 ;NO, CHECK IF FILE SHOULD BE DELETED
$CALL SETFD ;PLACE THE TEMP FILE'S FD IN THE FOB
$CALL DELTFE ;DELETE THE TEMP FILE
;CHECK IF THE USER SPECIFIED THIS FILE TO BE DELETED. IF SO, THEN PLACE THE
;FILE'S NAME IN THE RELEASE MESSAGE
LOAD S1,.FPLEN(E),FP.LEN ;PICK UP THE FP LENGTH
ADD E,S1 ;POINT TO THE FD
$CALL DETDEL ;DETERMINE IF THE FILE IS TO BE DELETED
JUMPF REMDI3 ;NO, GO CHECK THE NEXT FILE
MOVE S1,T3 ;PICK UP WHERE TO PLACE FD IN MESSAGE
HRLI S1,.FDLEN(E) ;PICK UP WHERE FD IS IN DATA BASE
LOAD S2,.FDLEN(E),FD.LEN ;[3]PICK UP THE LENGTH OF THE FD
ADD T4,S2 ;ADD TO TOTAL FD BLOCK SIZE IN MESSAGE
ADD S2,T3 ;[3]DESTINATION END ADDRESS + 1
MOVE T3,S2 ;[3]ADDRESS OF THE NEXT BLOCK
BLT S1,-1(S2) ;COPY THIS FILE'S FD TO RELEASE MESSAGE
AOS REL.ND(P1) ;INCREMENT FILE COUNT IN RELEASE MSG
JRST REMDI3 ;GO CHECK THE NEXT FILE
;THERE IS NOT A TEMPORARY FILE ASSOCIATED WITH THIS FILE. CHECK IF THE FILE
;IS TO BE DELETED. IF IT IS, THEN DELETE IT.
REMDI2: LOAD S1,.FPLEN(E),FP.LEN ;[3]PICK UP THE FP LENGTH
ADD E,S1 ;[3]POINT TO THE FD
$CALL DETDEL ;DETERMINE IF THE FILE IS TO BE DELETED
JUMPF REMDI3 ;NO, GO CHECK THE NEXT FILE
MOVEM E,J$XFOB+FOB.FD(J) ;YES, PLACE FILE'S FD IN THE FOB
$CALL DELTFE ;DELETE THE FILE
;POINT TO THE NEXT FILE TO BE LOOKED AT FOR DELETION
REMDI3: LOAD S1,.FDLEN(E),FD.LEN ;PICK UP THE FILE'S FD LENGTH
ADD E,S1 ;POINT TO THE NEXT FILE'S FP
SOJG T1,REMDI1 ;CHECK THE NEXT FILE, IF ANY
SKIPN S1,T4 ;ANY FILE NAMES IN THE RELEASE MSG?
$RETF ;NO, INDICATE TO THE CALLER
$RETT ;YES, INDICATE TO THE CALLER
SUBTTL DELTFE - DELETE A FILE
;DELTFE is called during the creation of a RELEASE message for a print
;request that originated on a remote node in the cluster. DELTFE deletes
;a file that was specified in the print request to be deleted.
;
;Call is: J/Job Context Pointer
;Returns: The file has been deleted
DELTFE: SETZM J$XFOB+FOB.US(J) ;NO ACCESS CHECKING
SETZM J$XFOB+FOB.CD(J) ;NO ACCESS CHECKING
MOVEI S1,FOB.SZ ;PICK UP THE FOB SIZE
MOVEI S2,J$XFOB(J) ;PICK UP THE FOB ADDRESS
$CALL F%DEL ;DELETE THE FILE
$RET ;RETURN TO THE CALLER
SUBTTL SETFD - SETUP A TEMPORARY FILE'S FD IN THE FOB
;SETFD is called to create a FD for a temporary file associated with
;a print request that originated from a remote node in the cluster.
;The address of the FD is placed in the FOB
;
;Call is: J/Job Context Pointer
; E/Address of the file's FP
;Returns: The temporary file's FD has been created and is pointed to
; by the temporary file's FOB
SETFD: $SAVE <P1,P2> ;SAVE THIS AC
;BUILD THE TEMPORARY FILE'S NAME
$TEXT(<-1,,J$TNAM(J)>,<^T/DIRNAM/:^N/.EQNOD(J)/-^N/CNTSTA/^W/.FPTEM(E)/.LPT;P770000^0>)
;FIND THE LENGTH OF THE TEMPORARY FILE NAME
MOVEI S1,J$TNAM(J) ;ADDRESS OF THE TEMPORARY FILE NAME
HRLI S1,(POINT 7,) ;MAKE IT INTO A POINTER
SETZ P1, ;LENGTH OF THE TEMPORARY FILE NAME
SETFD1: ILDB S2,S1 ;PICK UP THE NEXT CHARACTER OF NAME
AOS P1 ;COUNT IT
SKIPE S2 ;FINISHED COUNTING CHARACTERS?
JRST SETFD1 ;NO, GO GET THE NEXT CHARACTER
;BUILD THE TEMPORARY FILE'S FD HEADER
IDIVI P1,5 ;CALCULATE THE NUMBER OF WORDS
SKIPE P2 ;SKIP IF NO FRACTIONAL WORDS
AOS P1 ;INCLUDE ANY FRACTIONAL WORDS
AOS P1 ;INCLUDE HEADER WORD IN FD LENGTH
STORE P1,J$FDHR(J),FD.LEN ;STORE FD LENGTH IN FD HEADER WORD
LOAD S1,.FPLEN(E),FP.LEN ;PICK UP ORIGINAL FILE'S FP LENGTH
ADD S1,E ;POINT TO ORIGINAL FILE'S FD
MOVEM S1,J$ORFD(J) ;SAVE ORIGINAL FILE'S FD ADDRESS
LOAD S2,.FDLEN(S1),FD.TYP ;PICK UP TYPE FIELD FROM FD HEADER
STORE S2,J$FDHR(J),FD.TYP ;PLACE IN TEMPORARY FILE'S FD
;SAVE THE TEMPORARY FILE'S FD IN THE FOB AND THE JOB DATA BASE
MOVEI S1,J$FDHR(J) ;PICK UP TEMP FILE'S FD ADDRESS
MOVEM S1,J$DFDA(J) ;PLACE IN EXPECTED FD ADDRESS WORD
STORE S1,J$XFOB+FOB.FD(J) ;PLACE IN THE FOB
$RET ;RETURN TO THE CALLER
SUBTTL LISTEN - MESSAGE SERVER FOR A REMOTE NODE
;LISTEN exists as an inferior fork in LPTSPL. LPTSPL receives RELEASE
;messages from nodes in the cluster where print requests originating
;on the local node were sent to be processed. LISTEN performs accounting
;for those print requests.
;INITIALIZATION BLOCK AND PID BLOCK
LIB: $BUILD IB.SZ
$SET (IB.PRG,,%%.MOD) ;PROGRAM 'LPTSPL'
$SET (IB.FLG,IP.STP,1) ;STOPCODES TO ORION
$SET (IB.PIB,,0) ;[3]SET UP PIB ADDRESS
$EOB ;
LPIB: $BUILD PB.MNS ;
$SET (PB.HDR,PB.LEN,PB.MNS) ;PIB LENGTH,,0
$SET (PB.FLG,IP.RSE,1) ;RETURN ON SEND ERROR
$SET (PB.SYS,IP.BQT,-1) ;MAXIMUM SEND/RECEIVE IPCF QUOTA
$SET (PB.SYS,IP.MNP,^D1) ;NUMBER OF PIDS
$EOB ;
LISCHN: XWD 1,ACCEPT ;A DECNET CONNECTION REQUEST OCCURRED
XWD 1,MSGFSN ;MESSAGE FROM A SENDER IS AVAILABLE
XWD 1,LSSCS ;SCS% DETECTED A CLUSTER TOPOLOGY CHANGE
BLOCK ^D33 ;THESE CHANNELS ARE NOT USED
SCSCHN: EXP .SIPAN,2 ;ASSOCIATE SCS EVENTS WITH CHAN 2
;SET UP DATA BASE, SET UP GLXLIB, ENABLE CAPABILITIES, AND SET UP THE INTERRUPT
;SYSTEM
LISTEN: SKIPE DEBUGW ;[3]DEBUGGING?
$CALL LPTDDT ;[3]YES, SET UP FOR DEBUGGING
$CALL LISSET ;SET UP GLXLIB AND CAPABILITIES
$CALL BLDSRV ;[3]BUILD THE DECNET SRV: DEVICE NAME
$CALL LOPLNK ;OPEN A SRV: DEVICE
$CALL LISINT ;SET UP THE INTERRUPT SYSTEM
;WAIT FOR A CONNECTION REQUEST, FOR INCOMING DECNET MESSAGES AND FOR
;REQUESTS FROM THE TOP FORK FOR A MESSAGE.
LISTE2: SETZ S1, ;INDEFINITE TIME TO WAIT
$CALL I%SLP ;WAIT% UNTIL NEEDED
JRST LISTE2 ;WAIT% FOR THE NEXT EVENT
LISTE3: MOVE P,.LSACS+P(LIS) ;[6]PICK UP THE NEW STACK POINTER
$CALL LOPLNK ;[6]RE-OPEN THE LINK
$CALL LISINT ;[6]RE-INITIALIZE INTERRUPT SYSTEM
JRST LISTE2 ;[6]WAIT% FOR THE NEXT EVENT
SUBTTL BLDSRV - BUILD THE SRV: DEVICE NAME
;BLDSRV builds the listener's DECnet SRV: device name and places it in the
;listener block. It also builds the name of LISSPL's sender that will attempt
;to establish a DECnet connection with the listener. The sender name is
;used by the listener as part of validating the link request.
;
;Call is: LIS/Address of the listener block
;Returns: The SRV: device name and the sender name have been built and
; placed in the listener block
BLDSRV: SKIPE DEBUGW ;[7]DEBUGGING?
JRST BLDS.1 ;[7]YES, SET UP DIFFERENTLY
$TEXT (<-1,,.LSSRV(LIS)>,<SRV:TASK.^N/CNTSTA/$LPTSPL$LS>)
$TEXT (<-1,,.LSSNE(LIS)>,<^N/CNTSTA/$LISSPL$SN^0>) ;[3]SENDER NAME
$RET ;RETURN TO THE CALLER
BLDS.1: $SAVE <T1,T2> ;[7]SAVE THESE AC
GJINF% ;[7]PICK UP THE USER'S NUMBER
MOVE S2,S1 ;[7]SAVE NUMBER WHERE EXPECTED
MOVEI S1,.LSDBW(LIS) ;[7]WHERE TO PLACE USER NAME
HRLI S1,(POINT 7) ;[7]MAKE INTO A POINTER
DIRST% ;[7]PICK UP THE USER NAME
JRST S..COD ;[7]CRASH ON AN ERROR
MOVEI S1,.LSDBW(LIS) ;[7]PICK UP USER NAME ADDRESS
HRLI S1,(POINT 7,) ;[7]MAKE INTO A POINTER
SETZ T1, ;[7]NUMBER OF CHAR IN NAME
BLDS.2: ILDB S2,S1 ;[7]PICK UP THE NEXT CHARACTER
SKIPN S2 ;[7]IS THIS THE LAST ONE?
JRST BLDS.3 ;[7]YES, BUILD THE DEVICE NAME
AOS T1 ;[7]INCREMENT THE CHAR COUNT
CAIG T1,^D6 ;[7]MAXIMUM COUNT?
JRST BLDS.2 ;[7]NO, GET THE NEXT CHAR
SETZ S2, ;[7]PICK UP A NULL
DPB S2,S1 ;[7]PLACE IN USER NAME
BLDS.3: MOVEI S1,.LSDBW(LIS) ;[7]ADDRESS OF THE USER NAME
$TEXT (<-1,,.LSSRV(LIS)>,<SRV:TASK.^N/CNTSTA/$^T/0(S1)/$LS^0>)
$TEXT (<-1,,.LSSNE(LIS)>,<^N/CNTSTA/$^T/0(S1)/$SN^0>) ;SENDER NAME
$RET ;[7]RETURN TO THE CALLER
SUBTTL LISSET - INITIALIZE THE LISTENER'S GLXLIB AND CAPABILITIES
;LISSET is called by the listener at listener startup. This routine sets up
;GLXLIB, the listener's capabilities and disables the listener from receiving
;any IPCF messages.
;
;Call is: LIS/Address of the listener block
;Returns: GLXLIB setup and capabilities enabled
;Crashes: Unable to set up capabilities
LISSET: $SAVE <T1,T2> ;SAVE THESE AC, DESTROYED BY JSYS
;SET UP THE GLXLIB INITIALIZATION BLOCK IN THE LISTENER BLOCK
MOVSI S1,LIB ;PICK UP ADDRESS OF THE IB BLOCK
HRRI S1,.LSIBK(LIS) ;ADDRESS OF WHERE TO PLACE THE IB BLOCK
MOVEI S2,.LSIBK+IB.SZ(LIS) ;END ADDRESS + 1
BLT S1,-1(S2) ;MOVE THE IB BLOCK TO LISTENER BLOCK
MOVEI S1,.LSPIB(LIS) ;[3]PICK UP PID BLOCK ADDRESS
MOVEM S1,.LSIBK+IB.PIB(LIS) ;[3]PLACE IN THE IB BLOCK
MOVSI S1,.LSLEV(LIS) ;ADDRESS OF THE INTERRUPT LEVEL TABLE
HRRI S1,LISCHN ;ADDRESS OF THE CHANNEL TABLE
MOVEM S1,.LSIBK+IB.INT(LIS) ;PLACE IN THE INITIALIZATION BLOCK
;SET UP THE PID BLOCK AND THE INTERRUPT LEVEL TABLE IN THE LISTENER BLOCK
MOVSI S1,LPIB ;PICK UP ADDRESS OF THE PID BLOCK
HRRI S1,.LSPIB(LIS) ;DESTINATION IS IN THE LISTENER BLOCK
MOVEI S2,.LSPIB+PB.MNS(LIS) ;END ADDRESS + 1
BLT S1,-1(S2) ;MOVE PID TABLE TO LISTENER BLOCK
MOVEI S1,.LSLEV(LIS) ;PICK UP ADR OF INTERRUPT LEVEL TABLE
MOVEI S2,.LS1PC(LIS) ;PICK UP ADR OF FIRST PC WORD
MOVEM S2,0(S1) ;PLACE PC ADR IN INTERRUPT LEVEL TABLE
AOS S1 ;[3]POINT TO NEXT INTERRUPT TABLE ENTRY
AOS S2 ;[3]POINT TO NEXT PC WORD ADDRESS
MOVEM S2,0(S1) ;PLACE PC ADR IN INTERRUPT LEVEL TABLE
AOS S1 ;[3]POINT TO NEXT INTERRUPT TABLE ENTRY
AOS S2 ;[3]POINT TO NEXT PC WORD ADDRESS
MOVEM S2,0(S1) ;PLACE PC ADR IN INTERRUPT LEVEL TABLE
;SET UP GLXLIB
MOVEI S1,IB.SZ ;PICK UP SIZE OF THE INITIALIZATION BLK
MOVEI S2,.LSIBK(LIS) ;[3]PICK UP INITIALIZATION BLOCK ADR
$CALL I%INIT ;INITIALIZE GLXLIB
;ENABLE THE LISTENER'S CAPABILITIES TO BE THOSE OF THE TOP FORK.
MOVX S1,.FHSLF ;PICK UP THE LISTENER'S HANDLE
RPCAP%
ERJMP [$CALL INLCRH ;INDICATE A CONTROLLED CRASH
$STOP(LCC,Listener can't obtain capabilities) ]
MOVE T1,S2 ;ENABLE ALL CAPABILITIES
MOVEI S1,.FHSLF ;PICK UP THE LISTENER'S HANDLE
EPCAP% ;ENABLE THE CAPABILITIES
ERJMP [$CALL INLCRH ;INDICATE A CONTROLLED CRASH
$STOP(LCE,Listener can't enable capabilities) ]
;DISABLE RECEIVING IPCF MESSAGES
MOVEI S1,.MUDIS ;DISABLE RECEIVING IPCF MESSAGES
MOVEM S1,.LSMUT(LIS) ;PLACE IN THE ARGUMENT BLOCK
MOVE S1,.LSPIB+PB.PID(LIS) ;PICK UP LISTENER'S PID
MOVEM S1,.LSMUT+1(LIS) ;PLACE IN THE ARGUMENT BLOCK
MOVEI S1,2 ;PICK UP SIZE OF ARGUMENT BLOCK
MOVEI S2,.LSMUT(LIS) ;PICK ADDRESS OF THE ARGUMENT BLOCK
MUTIL% ;DISABLE RECEIVING IPCF MESSAGES
ERJMP .+1 ;SHOULDN'T HAPPEN, BUT DON'T CARE
$RET ;RETURN TO STARTUP
SUBTTL LOPLNK - OPEN A DECNET SRV: DEVICE
;LOPLNK is called during the listener's initialization to open a SRV:
;device.
;
;Call is: LIS/Address of the listener block
;Returns: The SRV: device has been open
;Crashes: Unable to obtain a JFN or open the SRV: device
LOPLNK: $SAVE <T1,T2> ;SAVE THESE AC
;PICK UP THE SRV: JFN AND OPEN THE SRV: DEVICE
MOVX S1,GJ%SHT ;SHORT JFN
HRROI S2,.LSSRV(LIS) ;POINT TO THE DEVICE NAME
GTJFN%
ERJMP LOPLN3 ;CRASH IF CAN'T GET JFN
HRRZS S1 ;ISOLATE THE JFN
MOVEM S1,.LSJFN(LIS) ;SAVE THE JFN FOR LATER
MOVX S2,<FLD(^D36,OF%BSZ)+OF%WR+OF%RD> ;OPEN FOR READ AND WRITE
OPENF%
ERJMP LOPLN3 ;CRASH IF CAN'T OPEN THE DEVICE
$RET ;RETURN TO THE CALLER
LOPLN3: $CALL INLCRH ;INDICATE A CONTROLLED CRASH
$STOP (LOD, LISTENER CAN'T OPEN DECNET DEVICE)
SUBTTL LISINT - SET UP THE LISTENER'S INTERRUPT SYSTEM
;LISINT is called by the listener during listener startup. LISINT sets up
;the listener's interrupt system.
;
;Call is: LIS/Address of the listener block
;Returns: The interrupt system has been set up
;Crashes: The interrupt system could not be set up
LISINT: $SAVE <T1,T2> ;SAVE THESE AC
MOVEI S1,.FHSLF ;PICK UP THE LISTENER'S HANDLE
SETO S2, ;INDICATE DISABLE ALL 36 CHANNELS
DIC% ;DISABLE THE CHANNELS
ERJMP .+1 ;SHOULDN'T HAPPEN, BUT IGNORE
CIS% ;CLEAR THE INTERRUPT SYSTEM
ERJMP .+1 ;SHOULDN'T HAPPEN, BUT IGNORE
MOVEI S1,.FHSLF ;PICK UP THE LISTENER'S HANDLE
HRLI S2,.LSLEV(LIS) ;PICK UP INTERRUPT LEVEL TABLE ADDRESS
HRRI S2,LISCHN ;PICK UP CHANNEL TABLE ADDRESS
SIR% ;SET UP THE INTERRUPT TABLE ADDRESSES
ERJMP LISIN2 ;CRASH IF CAN'T SET UP
MOVEI S1,.FHSLF ;PICK UP THE LISTENER'S HANDLE
EIR% ;ENABLE THE INTERRUPT SYSTEM
ERJMP LISIN2 ;CRASH IF CAN'T ENABLE INTERRUPT SYSTEM
MOVEI S1,.FHSLF ;PICK UP THE LISTENER'S HANDLE
MOVX S2,1B0+1B1+1B2 ;PICK UP CHANNELS TO ACTIVATE
AIC% ;ACTIVATE THE CHANNELS
ERJMP LISIN2 ;CRASH IF CAN'T ACTIVATE THE CHANNELS
MOVE S1,.LSJFN(LIS) ;PICK UP THE SRV: DEVICE JFN
MOVEI S2,.MOACN ;PICK UP THE FUNCTION CODE
MOVX T1,<FLD(0,MO%CDN)+FLD(1,MO%DAV)+FLD(.MONCI,MO%INA)>
MTOPR% ;ACTIVATE THE DECNET CHANNELS
ERJMP LISIN2 ;CRASH ON AN ERROR
MOVEI S1,2 ;PICK UP INTERRUPT ENABLED BLOCK SIZE
MOVEM S1,.LSSBK(LIS) ;PLACE IN THE INTERRUPT ENABLED BLOCK
MOVE S1,SCSCHN ;ASSOCIATE SCS% EVENTS WITH CHANNEL 2
MOVEM S1,.LSSBK+1(LIS) ;PLACE IN THE INTERRUPT ENABLED BLOCK
MOVEI S1,.SSAIC ;PICK UP THE FUNCTION CODE
MOVEI S2,.LSSBK(LIS) ;PICK UP INTERRUPT ENABLED BLOCK ADR
SCS% ;ACTIVATE THE SCS% EVENT CHANNEL
ERJMP LISIN2 ;CRASH ON AN ERROR
$RET ;RETURN TO LISTENER STARTUP
LISIN2: $CALL INLCRH ;INDICATE CONTROLLED CRASH
JRST $STOP(CSI,Can't set up interrupt system)
SUBTTL ACCEPT - VALIDATE A DECNET CONNECTION REQUEST
;ACCEPT is the listener's interrupt handler for DECnet connection requests.
;ACCEPT validates a sender's request for a DECnet connection. The following
;two checks are made:
;1. The sender's name must be in the form expected by the listener. The
; expected form is:
; LNODE$LISSPL$SN
; where LNODE is the local node's name
;3. The optional data (BDATA) field must contain the value that results from
; the following algorithm:
; a. The listener's node name expressed in SIXBIT is rotated left by 3 bits
; b. This value is then converted into 4 octal 8 bit bytes
;If the sender fails to pass these two checks, then the sender's DECnet
;connection request is rejected with reason "Reject or disconnect by
;object" (error .DCX0). ORION is informed of the rejection.
;If the sender passes the two checks, then its connection request is
;accepted.
;
;Call is: LIS/Address of the listener block
;Returns: The connecton request has been accepted or rejected
;Crashes: Cannot obtain the information to validate the connection request
; or cannot interrupt the top fork
ACCEPT: $BGINT 1,
;CHECK IF THE SENDER'S NAME IS VALID
MOVE S1,.LSJFN(LIS) ;PICK UP THE SRV: DEVICE JFN
MOVEI S2,.MORUS ;WANT THE SENDER'S USER NAME
HRROI T1,.LSUSR(LIS) ;WHERE TO PLACE THE USER NAME
MTOPR% ;PICK UP THE USER NAME
ERJMP ACCEP5 ;CRASH IF CAN'T OBTAIN INFORMATION
HRROI S1,.LSSNE(LIS) ;POINT TO THE EXPECTED SENDER'S NAME
HRROI S2,.LSUSR(LIS) ;POINT TO THE SENDER'S NAME
$CALL S%SCMP ;COMPARE THE TWO NAMES
SKIPE S1 ;ARE THE NAMES THE SAME?
JRST ACCEP3 ;NO, SO REJECT THIS REQUEST
;CHECK THE OCTAL DATA FIELD
repeat 0,<
MOVE S1,.LSJFN(LIS) ;PICK UP THE SRV: DEVICE JFN
MOVEI S2,.MORDA ;WANT THE OCTAL DATA FIELD
HRROI T1,.LSOPT(LIS) ;WHERE TO PLACE THE OCTAL DATA
MTOPR% ;PCIK UP THE OCTAL DATA
ERJMP ACCEP5 ;CRASH IF CAN'T OBTAIN INFORMATION
MOVE S2,CNTSTA ;PICK UP THE LOCAL SIXBIT NODE NAME
ROT S2,3 ;ROTATE BY 3
MOVE T1,[POINT 8,T3] ;WHERE TO PLACE OCTAL VALUE
SETZ T3, ;INITIALIZE OCTAL VALUE TO ZERO
MOVEI T2,4 ;PICK UP NUMBER OF BYTES TO BUILD
ACCEP2: LSHC S1,^D9 ;PICK UP THE NEXT BYTE
IDPB S1,T1 ;STORE AS AN EIGHT BIT BYTE
SOJN T2,ACCEP2 ;PICK UP THE NEXT BYTE
CAME T3,.LSOPT(LIS) ;SAME OCTAL VALUE AS THE SENDER'S?
JRST ACCEP3 ;NO, SO REJECT THIS REQUEST
>;end of temp repeat 0
;THE SENDER HAS PASSED THE VALIDITY CHECKS. SAVE THE SENDER'S NODE NAME AND
;ACCEPT THE DECNET CONNECTION REQUEST.
MOVE S1,.LSJFN(LIS) ;PICK UP THE SRV: DEVICE JFN
MOVEI S2,.MORHN ;WANT THE SENDER'S NODE NAME
HRROI T1,.LSANN(LIS) ;WHERE TO PLACE THE NODE NAME
MTOPR% ;PICK UP THE SENDER'S NODE NAME
ERJMP ACCEP5 ;CRASH IF CAN'T OBTAIN INFORMATION
HRROI S1,.LSANN(LIS) ;PICK UP THE SENDER'S NODE NAME
$CALL S%SIXB ;CHANGE IT TO SIXBIT
MOVEM .LSNME(LIS) ;SAVE THE SIXBIT NODE NAME
MOVE S1,.LSJFN(LIS) ;PICK UP SRV: DEVICE JFN
MOVEI S2,.MOCC ;THE CONNECTION WILL BE ACCEPTED
SETZB T1,T2 ;NO OPTIONAL DATA
MTOPR% ;ACCEPT THE CONNECTION
ERJMP ACCEP5 ;CRASH ON AN ERROR
JRST ACCEP4 ;[3]RETURN TO THE PREVIOUS CONTEXT
;THE SENDER'S DECNET CONNECTION REQUEST HAS BEEN DENIED. REJECT THE
;CONNECTION, INDICATE THAT THE CONNECTION HAS BEEN REJECTED IN THE LISTENER'S
;STATUS WORD IN THE NODE TABLE ENTRY AND INFORM ORION OF THE REJECTION.
ACCEP3: MOVE S1,.LSJFN(LIS) ;PICK UP THE SRV: DEVICE JFN
MOVEI S2,.MOCLZ ;WILL REJECT THIS REQUEST
SETZB T1,T2 ;NO OPTIONAL DATA
MTOPR% ;REJECT THE REQUEST
ERJMP ACCEP5 ;CRASH ON AN ERROR
$LOG (<DECnet connection rejected>,<LPTSPL's listener has rejected a DECnet connection from node ^N/.LSNME(LIS)/>)
ACCEP4: $DEBRK ;RETURN TO THE PREVIOUS CONTEXT
;A FATAL ERROR HAS BEEN ENCOUNTERED. INDICATE A CONTROLLED CRASH AND CRASH
ACCEP5: $CALL INLCRH ;INDICATE A CONTROLLED CRASH
$STOP (CVC, SENDER CAN'T VALIDATE A CONNECTION REQUEST)
SUBTTL MSGFSN - DECNET MESSAGE FROM SENDER IS AVAILABLE
;MSGFSN is the interrupt handler for processing DECnet messages from LISSPL.
;
;Call is: LIS/Address of the listener block
;Returns: The message has been processed
;Crashes: The link status cannot be obtained, the link is no longer connected,
; or the message cannot be picked up.
MSGFSN: $BGINT 1,
;CHECK IF THE INTERRUPT IS DUE TO A MESSAGE BEING AVAILABLE FROM THE SENDER.
;IF IT IS, THEN PICK IT UP AND PROCESS IT. IF THERE IS NO MESSAGE AVAILABLE,
;THEN CHECK THE LINK STATUS. IF THE LINK IS STILL CONNECTED, THEN IT IS A
;SPURIOUS INTERRUPT. IF THE LINK IS NO LONGER CONNECTED AND THERE IS NOT A
;FATAL ERROR, THEN ATTEMPT TO RE-OPEN THE LINK.
SKIPG S1,.LSJFN(LIS) ;PICK UP THE SRV: DEVICE JFN
JRST MSGFS6 ;THERE IS NONE, TREAT AS SPURIOUS
SIBE% ;CHECK FOR A MESSAGE
JRST MSGFS1 ;THERE IS ONE, PICK IT UP
$CALL LCKLNK ;NO MESSAGE, CHECK THE LINK STATUS
JUMPT MSGFS6 ;LINK CONNECTED, TREAT AS SPURIOUS
JRST MSGFS5 ;ATTEMPT TO RE-OPEN THE LINK
;PICK UP THE MESSAGE
MSGFS1: MOVE S1,.LSJFN(LIS) ;PICK UP THE SRV: DEVICE JRN
MOVE S2,.LSMSG(LIS) ;PICK UP THE MESSAGE BUFFER ADDRESS
HRLI S2,(POINT 36) ;MAKE IT INTO A POINTER
MOVNI T1,PAGSIZ ;ASSUME MAXIMUM (DON'T TRUST SIBE%)
SINR% ;PICK UP THE MESSAGE
ERJMP MSGFS4 ;ABORT THE LINK AND RE-OPEN
REPEAT 0,<
;CHECK IF CHECKSUMMING IS ENABLED. IF IT IS NOT, THEN SEND A SUCCESS ACK
;BACK TO LISSPL. IF IT IS ENABLED, THEN CALCULATE THE CHECKSUM. IF
;THE CHECKSUMS DO NOT AGREE, THEN SEND A FAILURE ACK MESSAGE BACK TO
;LISSPL, OTHERWISE SEND A SUCCESS ACK BACK TO LISSPL.
MOVE S1,.LSMSG(LIS) ;PICK UP THE MESSAGE ADDRESS
$CALL LISCHK ;CHECKSUM THE MESSAGE IF NECESSARY
JUMPF MSGFS3 ;CHECKSUMS DO NOT AGREE
>
;PROCESS THE RELEASE MESSAGE. DO THE ACCOUNTING AND SEND A SUCCESS ACK
;TO THE SENDER
$CALL DOACT ;DO THE ACCOUNTING, DELETE ANY FILES
JUMPT MSGFS2 ;ACCOUNTING WAS SUCCESSFULLY PERFORMED
; $WTO (System Accounting Failure,<^R/.EQJBB(J)/>,)
MSGFS2: $CALL ACKSND ;SEND THE ACK MESSAGE
JUMPT MSGFS6 ;ACK MESSAGE SUCCESSFULLY SENT
JRST MSGFS4 ;ABORT AND RE-OPEN THE LINK
;THE CHECKSUMS DO NOT AGREE, SEND A FAILURE ACK TO THE SENDER
REPEAT 0,<
MSGFS3: $CALL ACKFAI ;SEND THE FAILURE ACK
JUMPT MSGFS6 ;MESSAGE SUCCESSFULLY SENT
>
;A DECNET I/O ERROR HAS OCCURRED. ABORT THE LINK AND RE-OPEN IT.
MSGFS4: $CALL LABLNK ;[3]ABORT THE LINK
MSGFS5: MOVEI S1,.LSPDL(LIS) ;[6]SET UP THE LISTENER CONTEXT
HRLI S1,-<PDSIZ-1> ;[6]STACK POINTER
MOVEM S1,.LSACS+P(LIS) ;[6]SAVE AS THE NEW STACK POINTER
MOVEI S1,LISTE3 ;[6]ADDRESS TO RESUME EXECUTION FROM
TXO S1,1B5 ;[6]
MOVEM S1,.LS1PC(LIS) ;[6]STORE AS THE NEW PC
MSGFS6: $DEBRK ;RETURN TO THE PREVIOUS CONTEXT
;A FATAL ERROR HAS OCCURRED
MSGFS7: $CALL INLCRH ;RESET THE FORK
$STOP (FED, FATAL ERROR DETECTED)
SUBTTL LSSCS - TOPOLOGY CHANGE DECTECTED INTERRUPT HANDLER
;LSSCS processes interrupts that occur as a consequence of a cluster
;topology change. If LSSCS detects that a node has left the cluster,
;then it checks the link status. If the link is no longer connected,
;then an attempt is made to re-open the link.
;
;Call is: Invoked when a cluster topology change has occurred
;DEBRKs: The link has been re-opened if it was detected that the link
; had become disconnected.
;Crashes: If the SCS% JSYS returns an error other than "event queue empty"
LSSCS: $BGINT 1, ;INITIALIZE INTERRUPT LEVEL
SETZM .LSSCS(LIS) ;ASSUME NO NODES HAVE LEFT THE CLUSTER
;PICK UP THE NEXT EVENT FROM THE EVENT QUEUE
LSSC2: MOVEI S1,SCSLEN ;LENGTH OF THE ARGUMENT BLOCK
MOVEM S1,.LSSEB+.SQLEN(LIS) ;PLACE IN THE ARGUMENT BLOCK
SETOM .LSSEB+.SQCID(LIS) ;GET THE NEXT EVENT
MOVEI S1,.SSEVT ;RETRIEVE NEXT ENTRY FROM EVENT QUEUE
MOVEI S2,.LSSEB(LIS) ;ADDRESS OF THE ARGUMENT BLOCK
SCS% ;PICK UP THE NEXT EVENT QUEUE ENTRY
ERJMP LSSC4 ;CHECK IF THE EVENT QUEUE IS NOW EMPTY
;CHECK THE TYPE OF EVENT THAT HAS OCCURRED
MOVE S1,.LSSEB+.SQEVT(LIS) ;PICK UP THE EVENT CODE
CAIN S1,.SENCO ;HAS A NODE COME ONLINE?
JRST LSSC2 ;YES, DON'T CARE ABOUT THIS EVENT
CAIE S1,.SEPBC ;HAS A NODE GONE OFFLINE?
JRST LSSC2 ;NO, DON'T CARE ABOUT THIS EVENT
;INDICATE THAT A NODE HAS LEFT THE CLUSTER
LSSC3: SETOM .LSSCS(LIS) ;A CLUSTER TOPOLOGY CHANGE OCCURRED
JRST LSSC2 ;CHECK FOR ANOTHER EVENT QUEUE ENTRY
;THE SCS% JSYS RETURNED AN ERROR. CHECK IF THE EVENT QUEUE IS EMPTY.
;IF SO, RETURN. ON OTHER ERRORS, CRASH. THIS IS BECAUSE IT CANNOT JUST BE
;ASSUMED THAT A TOPOLOGY CHANGE HAS OCCURRED, SINCE IF THE ROUTINE EXITS ON
;THIS ASSUMPTION AND THERE ARE MORE EVENTS IN THE EVENT QUEUE, THEN THE
;LISTENER WILL NOT BE INTERRUPTED AGAIN IF A CLUSTER TOPOLOGY CHANGE OCCURS.
LSSC4: MOVEI S1,.FHSLF ;GET LATEST ERROR OF LISSPL
GETER% ;PICK UP THE ERROR
ERJMP S..SFE ;FATAL ERROR IN SCS% INTERRUPT HANDLER
HRRZS S2 ;ISOLATE THE ERROR CODE
CAIE S2,SCSQIE ;EVENT QUEUE EMPTY?
JRST S..SFE ;NO, CONSIDER TO BE A FATAL ERROR
SKIPL .LSSCS(LIS) ;DID A NODE LEAVE THE CLUSTER?
JRST LSSC5 ;NO, SO GO RETURN TO PREVIOUS CONTEXT
$CALL LCKLNK ;CHECK THE LINK STATUS
JUMPT LSSC5 ;LINK STILL CONNECTED
MOVEI S1,.LSPDL(LIS) ;[6]SET UP THE LISTENER CONTEXT
HRLI S1,-<PDSIZ-1> ;[6]STACK POINTER
MOVEM S1,.LSACS+P(LIS) ;[6]SAVE AS THE NEW STACK POINTER
MOVEI S1,LISTE3 ;[6]ADDRESS TO RESUME EXECUTION FROM
TXO S1,1B5 ;[6]
MOVEM S1,.LS1PC(LIS) ;[6]STORE AS THE NEW PC
LSSC5: $DEBRK
$STOP (SFE, SCS% FATAL ERROR)
SUBTTL LCKLNK - CHECK THE STATUS OF THE LISTENER'S LINK
;LCKLNK is called to check the status of the listener's DECnet link to
;the sender. If there is no connection, then the DECnet link is
;closed and the DECnet JFN released
;
;Call is: LIS/Address of the listener block
;Returns true: The DECnet link is connected
;Returns false: The DECnet link has been aborted
;Crashes: Unable obtain the link status
LCKLNK: $SAVE <T1,T2> ;SAVE THESE AC, DESTROYED BY JSYS
;OBTAIN THE DECNET LINK STATUS.
SKIPG S1,.LSJFN(LIS) ;PICK UP THE DECNET JFN
$RETF ;NO JFN, NO LINK
MOVEI S2,.MORLS ;WANT THE STATUS OF THE LINK
MTOPR% ;OBTAIN THE STATUS OF THE LINK
ERJMP LCKLN1 ;[3]ON AN ERROR, ABORT THE LINK
MOVEM T1,.LSLNK(LIS) ;SAVE THE LINK STATUS IN LISTENER BLOCK
;DETERMINE IF THE LINK IS CONNECTED. IF IT IS NOT, THEN CLOSE AND RELEASE
;THE JFN.
TXNE T1,MO%CON ;IS THE LINK CONNECTED?
$RETT ;YES, RETURN TRUE
LCKLN1: $CALL LABLNK ;[3]CLOSE AND RELEASE THE JFN
$RETF ;INDICATE DON'T HAVE A LINK
SUBTTL LABLNK - ABORT THE LISTENER'S DECNET LINK
;LABLNK is called to abort the listener's DECnet link by closing the
;DECnet link with ABORT and releasing its JFN if necessary.
;
;Call is: LIS/Address of the listener block
;Returns: The listener's DECnet link has been aborted
LABLNK: $SAVE <T1,T2> ;SAVE THESE AC, DESTROYED BY JSYS
MOVE S1,.LSJFN(LIS) ;PICK UP THE DECNET JFN
TXO S1,CZ%ABT ;CLOSE WITH ABORT
CLOSF% ;CLOSE THE DECNET LINK
ERJMP LABLN2 ;SHOULDN'T HAPPEN
JRST LABLN3 ;GO RETURN
LABLN2: MOVE S1,.LSJFN(LIS) ;PICK UP THE DECNET JFN AGAIN
RLJFN% ;RELEASE THE JFN
ERJMP .+1 ;SHOULDN'T HAPPEN
LABLN3: SETZM .LSJFN(LIS) ;INDICATE NO LONGER HAVE A JFN
$RET ;INDICATE DON'T HAVE A LINK
REPEAT 0,<
SUBTTL LISCHK - LISTENER CHECKSUM AND ACK MESSAGE
;LISCHK is called when the listener has picked up a message. If checksumming
;is enabled on the sender's node and the listener's node, then a checksum of
;the message is performed.
;If checksumming is disabled, either on the sender's node or the listener's
;node, then a checksum is not performed.
;
;Call is: S1/Address of the message
;Returns true: The checksums match or checksumming not enabled
;Returns false: The checksums do not match and a failure ACK has been sent
; to the sender.
LISCHK: $SAVE <P1> ;SAVE THIS AC
SKIPN CHKSUMO ;CHECKSUMMING ENABLED ON LOCAL NODE?
JRST LISCH2 ;NO, JUST RETURN
; SKIPN P1,.MSCHS(S1) ;YES, CHECKSUMMING ENABLED REMOTELY?
JRST LISCH2 ;NO, JUST RETURN
; SETZM .MSCHS(S1) ;ZERO OUT THE CHECKSUM WORD
$CALL CHKSUM ;CALCULATE THE CHECKSUM
CAME P1,S1 ;DO THE CHECKSUMS AGREE?
JRST LISCH3 ;NO, SEND FAILURE ACK TO SENDER
LISCH2: $RETT ;INDICATE MESSAGE IS VALID
LISCH3: $RETF ;INDICATE MESSAGE IS INVALID
>
SUBTTL ACKSND - SEND A SUCCESS ACK TO THE SENDER
;ACKSND is called to send an ACK message to the sender indicating that
;the RELEASE message has been picked up.
;
;Call is LIS/Address of the listener block
;Returns true: The ACK message was sent
;Returns false: The ACK message was not sent
ACKSND: $SAVE <T1,T2> ;SAVE THESE AC
MOVE S1,.LSJFN(LIS) ;PICK UP SRV: DEVICE JFN
MOVEI S2,T1 ;ADDRESS OF THE MESSAGE
HRLI S2,(POINT 36,) ;MAKE IT INTO A POINTER
SETO T1, ;[3]NEGATIVE LENGTH OF THE MESSAGE
SOUTR% ;SEND THE MESSAGE TO THE SENDER
ERJMP .RETF ;INDICATE FAILURE TO THE CALLER
$RETT ;INDICATE SUCCESS TO THE CALLER
SUBTTL INLCRH - ROUTINE TO INDICATE LISTENER CONTROLLED CRASH
;INLCRH is called by the listener when it has detected a fatal error.
;A RESET is performed to break the DECnet link.
;
;Call is: LIS/Address of the listener block
INLCRH: DMOVEM S1,.LSERR(LIS) ;SAVE THE CONTEXT OF S1 AND S2
RESET% ;BREAK THE DECNET LINK
DMOVE S1,.LSERR(LIS) ;RESTORE CONTEXT OF S1 AND S2
$RET ;RETURN TO THE CALLER
SUBTTL LPTDDT - ROUTINE TO LOAD DDT IF DEBUGGING
;LPTDDT is called if LPTSPL is running in a DEBUG environment.
;LPTDDT maps in and starts DDT.
;
;Call is: No arguments
;Returns: DDT has been loaded
;Crashes: If unable to load DDT
LPTDDT: $SAVE <T1,T2> ;SAVE THESE AC, DESTROYED BY JSYS
MOVX S1,GJ%OLD+GJ%SHT ;OLD FILE+SHORT JFN
HRROI S2,[ASCIZ/SYS:SDDT.EXE/] ;POINT TO DDT
GTJFN% ;GET DDT'S JFN
ERJMP LPTDD2 ;CRASH IF CAN'T GET DDT'S JFN
HRLI S1,.FHSLF ;PICK UP HANDLE
GET% ;LOAD DDT
ERJMP LPTDD2 ;CRASH IF CAN'T LOAD DDT
MOVE S1,116 ;GET CONTENTS OF .JBSYM
HRRZ S2,770001 ;GET ADDRESS OF WHERE TO PUT IT
MOVEM S1,0(S2) ;POINT DDT AT LPTSPL'S SYMBOL TABLE
JRST 770000 ;AND ENTER DDT
GO: $RET ;RETURN
LPTDD2: $STOP (DDE, DDT ERROR) ;CRASH, IF CAN'T GET DDT
SUBTTL DOACT - DO ACCOUNTING FROM THE RELEASE MESSAGE
;DOACT is called when processing a RELEASE message sent by LISSPL.
;DOACT deletes any files that were specified by the user to be deleted
;but which are not accessible to the remote system. DOACT also does
;accounting using information supplied in the RELEASE message.
;
;Call is: LIS/Address of the listener block
;Returns true: The accounting was successfully done
;Returns false: The accounting was not done
DOACT: $SAVE <P1,P2> ;SAVE THIS AC
;FIRST CHECK FOR ANY FILES TO BE DELETED AND THEN DELETE THEM
MOVE P1,.LSMSG(LIS) ;[3]PICK UP THE MESSAGE ADDRESS
SKIPN P2,REL.ND(P1) ;[3]PICK UP NUMBER OF FILES TO DELETED
JRST DOACT2 ;NO FILES TO DELETE
MOVEI P1,REL.RS(P1) ;[3]POINT TO THE FIRST FILE'S FD
DOACT1: MOVEM P1,.LSFOB+FOB.FD(LIS) ;SAVE THE FD ADDRESS IN THE FOB
LOAD S2,.FDLEN(P1),FD.LEN ;GET THE FD LENGTH.
ADD P1,S2 ;POINT TO THE NEXT FILE'S FD
SETZM .LSFOB+FOB.US(LIS) ;NO ACCESS CHECKING
SETZM .LSFOB+FOB.CD(LIS) ;HERE ALSO
MOVEI S1,FOB.SZ ;GET THE FOB LENGTH
MOVEI S2,.LSFOB(LIS) ;AND THE FOB ADDRESS
$CALL F%DEL ;DELETE THE FILE
SOJG P2,DOACT1 ;GO PROCESS THE NEXT FILE
;CHECK IF ACCOUNTING IS TO BE PERFORMED
DOACT2: MOVE P1,.LSMSG(LIS) ;PICK UP THE MESSAGE ADDRESS
MOVE S1,REL.FL(P1) ;PICK UP THE FLAG WORD
TXNN S1,RF.ACT ;IS THERE ACCOUNTING INFORMATION?
$RETT ;NO, RETURN NOW
MOVEI S1,.USENT ;WRITE AN ENTRY
MOVEI S2,ACTLIS ;POINT TO THE LIST
USAGE% ;DO THE JSYS
ERJMP .RETF ;INDICATE ERROR TO THE CALLER
$RETT ;INDICATE SUCCESS TO THE CALLER
SUBTTL ACTLIS - LISTENER ACCOUNTING RECORD
ACTLIS:
IFN FTACNT,<
USENT. (.UTOUT,1,1,0)
USTAD. (-1) ;CURRENT DATE/TIME
USPNM. (<SIXBIT/LPTSPL/>,US%IMM) ;PROGRAM NAME
USPVR. (LPTVNO) ;PROGRAM VERSION
USAMV. (-1) ;ACCOUNTING MODULE VERSION
USNOD. (REL.NN(P1)) ;NODE NAME
USSRT. (REL.RT(P1)) ;RUN TIME
USSDR. (REL.DR(P1)) ;DISK READS
USSDW. (0,US%IMM) ;DISK WRITES
USJNM. (REL.JN(P1)) ;JOB NAME
USQNM. (<SIXBIT /LPT/>,US%IMM) ;QUEUE NAME
USSDV. (REL.DN(P1)) ;DEVICE NAME
USSSN. (REL.SN(P1)) ;JOB SEQUENCE NUMBER
USSUN. (REL.PP(P1)) ;TOTAL PAGES PRINTED
USSNF. (REL.FP(P1)) ;TOTAL FILES PROCESSED
USCRT. (REL.CD(P1)) ;CREATION DATE/TIME OF REQUEST
USSCD. (REL.SD(P1)) ;SCHEDULED DATE/TIME
USFRM. (REL.FT(P1)) ;FORMS TYPE
USDSP. (<SIXBIT/NORMAL/>,US%IMM) ;DISPOSITION
USPRI. (REL.JP(P1)) ;JOB PRIORITY
USJNO. (-1) ;JOB NUMBER
USTRM. (-1) ;TERMINAL DESIGNATOR
USLNO. (-1) ;TTY LINE NUMBER
USTXT. (<-1,,[ASCIZ / /]>) ;SYSTEM TEXT
USNM2. (<POINT 7,REL.UN(P1) >) ;USER NAME (TOPS20)
USACT. (<POINT 7,REL.AS(P1) >) ;ACCOUNT STRING POINTER
0 ;END OF LIST
>
ACTLEN==.-ACTLIS ;ACCOUNTING BLOCK LENGTH
SUBTTL STOP CODE DEFINITIONS
$STOP (CAC,CAN'T ACTIVATE DECNET DATA AVAILABLE CHANNEL)
$STOP (COD, CAN'T SETUP DEBUGGING DECNET DEVICE NAME) ;[10]
SUBTTL End of LPTCLU
END