Trailing-Edge
-
PDP-10 Archives
-
BB-JR93K-BB_1990
-
10,7/galaxy/quasar/qsrmda.mac
There are 36 other files named qsrmda.mac in the archive. Click here to see a list.
TITLE QSRMDA -- Mountable Device Manager
;
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1975,1976,1977,1978,1979,
;1980,1981,1982,1983,1984,1985,1986,1987. 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 WHICH IS NOT SUPPLIED BY
; DIGITAL.
SEARCH QSRMAC,GLXMAC,ORNMAC ;GET QUASAR SYMBOLS
PROLOGUE(QSRMDA) ;GENERATE NECESSARY SYMBOLS
%%.QSR==:%%.QSR
QSRVRS==:QSRVRS
.DIRECT FLBLST ;SQUASH LITERAL EXPANSION
; TABLE OF CONTENTS FOR QSRMDA
;
;
; SECTION PAGE
; 1. Table of Contents......................................... 2
; 2. MDA structure inter-relationships......................... 3
; 3. Local Storage............................................. 4
; 4. D$CLSV - Clear All STR Valid Status....................... 5
; 5. D$CSTR - Check a structure for on-line.................... 6
; 6. D$ESTR - Extract a STR from an FD......................... 7
; 7. D$ASTD - Add a structure dependency....................... 9
; 8. FNDSTR - Find a STR entry................................. 10
; 9. D$INIT - ROUTINE TO INITIALIZE THE MDA DATA BASE.......... 15
; 10. HOLD/RELEASE/MOUNT interface for QSRQUE................... 16
; 11. D$MOUN - Process a Tape/Disk Mount Request................ 18
; 12. D$DEAS - DEASSIGN/RELEASE A VOLUME SET.................... 19
; 13. D$CMDR - ROUTINE TO CREATE AN ENTRY IN THE MDR QUEUE...... 20
; 14. D$LOGO - DELETE A USER MDR'S ON LOGOUT.................... 23
; 15. D$XCH - Exchange disk units............................... 24
; 16. D$DMDR - ROUTINE TO UNWIND AND DELETE AN MDR.............. 25
; 17. D$IDEN - ROUTINE TO PROCESS THE IDENTIFY COMMAND.......... 26
; 18. REASSIGN - Try to give a unit to a user................... 29
; 19. REAS.S - Routine to Perform Volume Switch Processing...... 31
; 20. D$ASGN - ROUTINE TO ASSIGN FOREIGN DEVICES UNDER MDA...... 33
; 21. D$ENAB/D$DISA - DRIVE AVR STATUS.......................... 35
; 22. D$RECO - PROCESS THE OPR RECOGNIZE COMMAND................ 37
; 23. D$AVR - TAPE/DISK ONLINE PROCESSOR........................ 38
; 24. D$DEVS - PROCESS TAPE/DISK STATUS MESSAGES................ 39
; 25. TAPDEV - TAPE STATUS MESSAGE PROCESSOR.................... 40
; 26. DTADEV - DECTAPE STATUS MESSAGE PROCESSOR................. 43
; 27. DSKDEV - DISK STRUCTURE DEVICE STATUS MESSAGE PROCESSOR... 45
; 28. SETOWN - ROUTINE TO SET UP OWNERSHIP FOR A VSL............ 48
; 29. MNTVSL - ROUTINE TO ATTEMPT TO MOUNT A USERS REQUESTS..... 49
; 30. MNTVSR - ROUTINE TO MOUNT A VOLUME AT VOLUME SWITCH TIME.. 52
; 31. VSLCHK - ROUTINE TO TRY TO MOUNT A VOLUME FROM THE VSL.... 53
; 32. MATUNI - ROUTINE TO GIVE A VOLUME TO ANY VALID REQUESTOR.. 55
; 33. CVLVSL - Compare Volume with Volume Set................... 56
; 34. CHKOWN - ROUTINE TO CHECK IF A USER OWNS A VOLUME......... 57
; 35. D$UNLO - ROUTINE TO UNLOAD A TAPE DRIVE................... 58
; 36. D$DISM - STRUCTURE DISMOUNT PROCESSOR..................... 59
; 37. VLUNLO - Unload a unit and break UCB-VOL links............ 60
; 38. D$DELE - ROUTINE TO DELETE REQUESTS FROM THE MOUNT QUEUE.. 61
; 39. D$SMDA - Set tape drive un/available/ initialize.......... 65
; 40. D$VSR - VOLUME SWITCH REQUEST FROM PULSAR................. 67
; 41. D$XVSL - Extend a VSL..................................... 71
; 42. D$DVS - DISMOUNT/DEALLOCATE VOLUME SET PROCESSOR.......... 74
; 43. D$ACK - ROUTINE TO PROCESS MDA ACK MESSAGES............... 76
; 44. Structure mount ACK processing............................ 77
; 45. D$RMS - Routine to process the structure removed message.. 78
; 46. DSMACK - ROUTINE TO PROCESS DISMOUNT ACKS FROM TAPE LABELER 79
; 47. DSMOPR - Tell OPR about a structure just dismounted....... 82
; 48. CATACK - ROUTINE TO PROCESS CATALOG ACKS FROM TAPE LABELER 83
; 49. ASLACK - ROUTINE TO PROCESS ACKS FOR ADDING STR TO A SEARCH LIST 84
; 50. RMSACK - ROUTINE TO PROCESS 'REMOVE STRUCTURE' ACKS....... 85
; 51. D$ALIA - ROUTINE TO MOUNT A STRUCTURE WITH AN ALIAS....... 86
; 52. CHKSTR - ROUTINE TO CHECK FOR STRUCTURE AVAILABILITY...... 88
; 53. D$LOCK - PROCESS LOCK AND UNLOCK MESSAGES................. 89
; 54. TIMER ROUTINES FOR LOCK AND UNLOCK........................ 92
; 55. LOCNOT - Notify users (countdown) of pending locks........ 94
; 56. CLEAR LOCKS ON STRUCTURE DISMOUNT......................... 95
; 57. LNEVEN - Set up a Lock notification event................. 96
; 58. D$LCKM - ROUTINE TO PROCESS THE RESET AFTER LOCK MESSAGE.. 97
; 59. VSREOV - ROUTINE TO SEND END OF VOLUME MSG TO TAPE LABELER 98
; 60. REIMSG - ROUTINE TO SEND REINITIALIZATION MESSAGE TO PULSAR 99
; 61. DELETE - ROUTINE TO DELETE ALL NEW VOL SETS FOR A USER.... 99
; 62. REMOVE - ROUTINE TO DELETE A SPECIFIC VSL AND RETRY THE MOUNT 100
; 63. DELVSL - ROUTINE TO DELETE A VSL.......................... 101
; 64. ALCVSL - ROUTINE TO RETURN A VSL TO THE ALLOCATION POOL... 104
; 65. DELMDR - ROUTINE TO DELETE AN MDR......................... 105
; 66. DELVOL - ROUTINE TO DELETE VOL BLOCKS FROM THE VOL QUEUE.. 106
; 67. GETLBT - ROUTINE TO RECODE THE VOLUME LABEL TYPE.......... 107
; 68. FNDDSK - ROUTINE TO FIND A DSK VOL BLOCK USING VOLUME ID.. 108
; 69. CREVOL - ROUTINE TO CREATE A VOL BLOCK IN VOL QUEUE....... 109
; 70. USRACK - ROUTINE TO GENERATE AN ACK TO THE USER FOR MOUNT/ALLOC 110
; 71. ACKUSR - ROUTINE TO CREATE AN ACK AFTER THE VOL SET IS MOUNTED 111
; 72. TELOPR - ROUTINE TO NOTIFY THE OPERATOR TO MOUNT DEVICES.. 114
; 73. MNTOPR - ROUTINE TO NOTIFY THE OPR OF PENDING MOUNT REQUESTS 119
; 74. SETSEL - ROUTINE TO FIND THOSE UCB'S WHICH ARE FREE....... 121
; 75. USRNOT - SEND A MESSAGE TO THE USER....................... 122
; 76. NSTUSR - Notify users of pending structure locks.......... 124
; 77. LBLNOT - ROUTINE TO NOTIFY LABEL PROCESS OF DEVICE REASSIGNMENT 125
; 78. LBLHDR - Set up for a message to MDA...................... 127
; 79. SNDREC - ROUTINE TO SEND A RECOGNIZE MSG TO THE TAPE LABELER 128
; 80. UNLOAD - TELL PULSAR TO UNLOAD THE TAPE DRIVE............. 128
; 81. SNDVDM - Send volume dismount message to tape labeler..... 129
; 82. FNDUCB - ROUTINE TO FIND A UCB IN THE UCB CHAIN........... 130
; 83. GETRSN - ROUTINE TO RETURN THE FIRST AVAILABLE RESOURCE NUMBER 131
; 84. GIVRSN - Return a slot of the A matrix.................... 132
; 85. FNTAPE - ROUTINE TO FIND A MAGTAPE VOLUME IN THE VOL DATA BASE 133
; 86. FNDOWN - FIND ANY OWNER OF A VOLUME....................... 134
; 87. FNDMDR - ROUTINE TO FIND AN MDR GIVEN ITS JOB NUMBER...... 135
; 88. FNDVSL - ROUTINE TO FIND A PARTICULAR VSL IN AN MDR....... 136
; 89. FNDVSN - ROUTINE TO FIND A VOLUME SET VIA THE VOL SET NAME 137
; 90. FNDLNM - ROUTINE TO FIND A USERS VSL GIVEN A LOGICAL NAME. 138
; 91. VSLFND - ROUTINE TO FIND A VSL IN A USERS REQUEST......... 139
; 92. GENVOL - ROUTINE TO CREATE A 'SCRATCH' VOLUME BLOCK....... 140
; 93. ADDVOL - ROUTINE TO ADD A VOL BLOCK DURING MOUNT PROCESSING 141
; 94. CKUVOL - CHECK FOR MULTIPLE USER REQUESTS FOR THE SAME TAPE VOL 142
; 95. Miscellaneous routines.................................... 143
; 96. D$MDAE - ROUTINE TO NOTIFY THE OPERATOR OF ANY ERRORS..... 146
; 97. DSKRSN - ROUTINE TO RETURN RESOURCE NUMBERS FOR DISK DRIVES 147
; 98. TAPRSN - ROUTINE TO RETURN RESOURCE NUMBERS FOR TAPE DRIVES 148
; 99. D$TNRS - GET A MAGTAPE RESOURCE NUMBER.................... 149
; 100. STRRSN - ROUTINE TO RETURN RESOURCE NUMBERS FOR STRUCTURES 150
; 101. D$T/SVRS - Generate resource #s for Tape/Structure volumes 152
; 102. VALMSG - ROUTINE TO VALIDATE THE MOUNT/ALLOCATE MESSAGE... 153
; 103. CHKBAT - ROUTINE TO CHECK FOR BATCH REQUESTS DOING MOUNTS. 154
; 104. BLDVSL - ROUTINE TO BREAK DOWN MOUNT MSG ENTRIES.......... 155
; 105. VSL DEFAULTING ROUTINES................................... 158
; 106. MOUNT REQUEST BLOCK PROCESSOR ROUTINES.................... 159
; 107. Count the number of requests needing a structure.......... 164
; 108. BLDSTR - ROUTINE TO PIECE TOGETHER VOL BLKS AND MAKE A STRUCTURE 165
; 109. SNDBLD - ROUTINE TO LINK THE STR VOL BLKS AND SEND STR BUILD MSG 166
; 110. ASLMSG - ROUTINE TO BUILD AN 'ADD STRUCTURE' MSG.......... 168
; 111. SCNVOL - ROUTINE TO FIND COMMON VOLUMES REQUESTS AND LINK THEM 170
; 112. UPDSVL - UPDATE THE STARTING VOLUME FOR A VOLUME SET...... 172
; 113. D$INID - Initialization done for tape handler............. 173
; 114. D$ALOC - ROUTINE TO PERFORM DEVICE ALLOCATION............. 174
; 115. D$BMTX - ROUTINE TO FIND A USERS ENTRY IN THE 'B' MATRIX.. 178
; 116. Deadlock Avoidance
; 116.1 DEADLK - Interface routine........................ 179
; 116.2 D$DEAD - Check for a deadlock..................... 180
; 116.3 IFPLAY - See if process is playable............... 182
; 116.4 DOPLAY - Play a process........................... 185
; 116.5 IFOTHR - Check for other owners................... 187
; 116.6 UNMAP - Remove lower level resources.............. 188
; 116.7 GTHEAD - Get column headers....................... 189
; 116.8 GTCOLM - Get column entries....................... 190
; 116.9 GTNEXT - Get next process to play................. 191
; 116.10 CLTRY - Clear all tried bits...................... 192
; 117. Dump MDA Database
; 117.1 D$DUMP - Dump all matrices........................ 193
; 117.2 DMPSM - Dump an SM Block.......................... 196
; 118. D$DLCK - ROUTINE TO SET UP THE DEADLOCK AVOIDANCE CHECK... 197
; 119. RETA%C - ROUTINE TO RETURN RESOURCES TO THE 'A' & 'C' MATRICIES 200
; 120. RETBMA - ROUTINE TO RETURN RESOURCES TO THE 'B' MATRIX.... 201
; 121. ADDBMA - ROUTINE TO UPDATE A RESOURCE NUMBER FOR A USER.. 202
; 122. SUBCMA - ROUTINE TO RETURN RESOURCES TO THE 'C' MATRIX.... 204
; 123. SUBBMA - ROUTINE TO RETURN 'B' MATRIX RESOURCES........... 204
; 124. ADDAMA - ROUTINE TO REMOVE 'A' MATRIX RESOURCES........... 205
; 125. ADJAMA - ROUTINE TO ADJUST THE 'A' MATRIX................. 206
; 126. VSLRSN - ROUTINE TO FIND A VSL'S RESOURCE NUMBERS......... 207
; 127. SETSTK - Setup a queue for VSL, RSN pairs................. 211
; 128. GETADD - ROUTINE TO CALC THE 'A', 'B', 'C' MATRIX ADD VALUE 212
; 129. MDA pseudo process routines
; 129.1 D$PPRL - Delete an MDR............................ 213
; 129.2 D$PPRE - Reset a real process..................... 214
; 129.3 D$PMDR - Find a process........................... 215
; 130. D$MODR - ROUTINE TO MODIFY A USERS ALLOCATION ON THE 'FLY' 216
; 131. SHUFFL - Routine to shuffle resources around for a requestor 217
; 132. MODALC - Routine to modify a users resource number for a request 218
; 133. D$ALCT - ROUTINE TO ALLOCATE TAPE VOLUMES FOR 'IDENTIFY' COMMAND 219
SUBTTL MDA structure inter-relationships
; !-----! !-----!
; ! ! ! !
; MDR ! MDR !<--------------->! MDR !
;CHAIN ! ! ! !
; !-----! !-----!
; /!\ /!\ /!\
; ! ! !
; ! ! !
; ! !---------------! !-------------------!
; ! ! !
; \!/ \!/ \!/
; !-----! !-----! !-----!
; ! ! ! ! ! !
; VSL ! VSL !<------------>! VSL !<--------------->! VSL !
;CHAIN ! ! ! ! ! !
; !-----! !-----! !-----!
; /!\ /!\ /!\ /!\ /!\ /!\
; ! ! ! ! ! !
; ! ! ! ! ! !--------------!
; ! ! ! ! ! !
; ! ! ! !-------------! !--------! !
; ! !----------! ! ! ! !
; ! ! !-----------! ! ! !
; ! ! ! !--------! ! !
; \!/ \!/ \!/ \!/ \!/ \!/
; !-----! !-----! !-----! !-----! !-----!
; ! ! ! ! ! ! ! ! ! !
; VOL ! VOL ! ! VOL ! ! VOL ! ! VOL ! ! VOL !
;CHAIN ! 1 !<------->! 2 !<------->! 3 !<------->! 4 !<------->! 5 !
; ! ! ! ! ! ! ! ! ! !
; !-----! !-----! !-----! !-----! !-----!
; /!\ /!\ /!\ /!\
; !-----------! ! ! !
; ! !-----------! ! !
; ! ! !-----------! !
; ! ! ! !-------------!
; ! ! ! !
; \!/ \!/ \!/ \!/
; !-----! !-----! !-----! !-----! !-----!
; ! ! ! ! ! ! ! ! ! !
; UCB ! MTA ! ! MTA ! ! MTB ! ! MTB ! ! MTB !
;CHAIN ! 0 !<------->! 1 !<------->! 0 !<------->! 1 !<------->! 2 !
; ! ! ! ! ! ! ! ! ! !
; !-----! !-----! !-----! !-----! !-----!
SUBTTL Local Storage
IFN FTUUOS,<
DSKCBL: BLOCK 5 ;DSKCHR BLOCK
> ;END IFN FTUUOS
IFN FTJSYS,<
ESTR.A: BLOCK ^D16 ;-20 STRUCTURE NAME
> ;END IFN FTJSYS
;Local variables for the TOPS-10 deadlock avoidance code
TOPS10 <
BHEAD: BLOCK 1 ;ADDRESS OF 'B' MATRIX SM BLOCKS
CHEAD: BLOCK 1 ;ADDRESS OF 'C' MATRIX SM BLOCKS
BRESN: BLOCK 1 ;ADDRESS OF 'B' MATRIX RESOURCE COUNTS
CRESN: BLOCK 1 ;ADDRESS OF 'C' MATRIX RESOURCE COUNTS
BFLAG: BLOCK 1 ;ADDRESS OF PROCESS FLAGS
SM.PLY==1B0 ;PROCESS HAS BEEN PLAYED
SM.DLK==1B1 ;PROCESS HAS BEEN TRIED, BUT IT
; IS DEADLOCKED
SM.SEQ==RHMASK ;SEQUENCE NUMBER (IF PLAYED)
ATEMP: BLOCK 1 ;ADDRESS OF 'A' MATRIX SCRATCH ARRAY
ASIZE: BLOCK 1 ;NUMBER OF ENTRIES IN 'A' MATRIX
> ;END TOPS10 CONDITIONAL
SUBTTL D$CLSV - Clear All STR Valid Status
;D$CLSV is called to clear all the STATUS-VALID indicators for all file-
; structures in the STR queue. This will cause the status to be
; re-verified upon calling D$CSTR.
;Call: No arguments
;
;T Ret: Always
D$CLSV::LOAD S1,HDRSTR##+.QHLNK,QH.PTF
;POINT TO FIRST ITEM IN STR QUEUE
MOVX S2,STSSSV ;LOAD THE STATUS-VALID BIT
CLSV.1: JUMPE S1,.RETT ;RETURN ON END OF QUEUE
ANDCAM S2,STRSTS(S1) ;CLEAR STATUS-VALID FLAG
LOAD S1,.QELNK(S1),QE.PTN ;POINT TO NEXT ITEM
JRST CLSV.1 ;AND LOOP
SUBTTL D$CSTR - Check a structure for on-line
;D$CSTR is called with a STR queue entry to check whether or not it is
; on line.
;Call: S1/ address of an STR entry
;
;T Ret: Structure is on-line
; S1/Addr of STR queue entry
;
;F Ret: Structure is off-line
; S1/Addr of STR queue entry
D$CSTR::MOVE S2,STRSTS(S1) ;GET STRUCTURE STATUS WORD
TXNN S2,STSSSV ;IS STATUS VALID?
JRST CSTR.2 ;NO, GO ASK MONITOR
CSTR.1: TXNE S2,STSONL ;YES, IS IT ON-LINE?
$RETT ;YES, RETURN TRUE
$RETF ;NO, RETURN FALSE
TOPS10 <
CSTR.2: MOVE S2,STRNAM(S1) ;GET THE STRUCTURE NAME
MOVEM S2,DSKCBL+.DCNAM ;STORE IT IN THE DSKCHR BLOCK
MOVE S2,[5,,DSKCBL] ;POINT TO DSKCHR ARG
DSKCHR S2, ;ASK THE MONITOR FOR STATUS
MOVX S2,DC.OFL ;FAILED, LOAD OFF-LINE BIT
TXNE S2,DC.OFL!DC.NNA!DC.SAF ;OFFLINE IFF OFL OR NNA OR SAF
TDZA S2,S2 ;OFF LINE!!!
MOVX S2,STSONL ;ON LINE!!!
TXO S2,STSSSV ;SET VALID STATUS
MOVEM S2,STRSTS(S1) ;STORE THE STATUS
JRST CSTR.1 ;AND RETURN CORRECT STATE
> ;END TOPS10 CONDITIONAL
TOPS20 <
CSTR.2: PUSHJ P,.SAVE3 ;SAVE P1 THRU P3
MOVE P1,S1 ;SAVE STR ADDRESS IN P1
MOVE S1,[2,,.MSGSS] ;LEN,,FUNCTION
MOVEI S2,P2 ;ADDRESS OF ARG BLOCK
HRROI P2,STRNAM(P1) ;FIRST ARG IS POINT TO STR NAME
MSTR ;GET STRUCTURE STATUS
ERJMP CSTR.3 ;LOSE, MUST BE OFF-LINE
MOVX S2,STSONL ;LOAD THE ON-LINE BIT
TXNE P3,MS%DIS ;IS STR BEING DISMOUNTED?
CSTR.3: SETZ S2, ;YES, CLEAR ON-LINE FLAG
TXO S2,STSSSV ;SET STATUS VALID
MOVEM S2,STRSTS(P1) ;SAVE THE STRUCTURE STATUS
MOVE S1,P1 ;GET STRUCTURE ADDRESS IN S1
JRST CSTR.1 ;AND RETURN
> ;END TOPS20 CONDITIONAL
SUBTTL D$ESTR - Extract a STR from an FD
;D$ESTR is called with an FD to extract the structure and return the
; address of an STR queue entry for it.
;Call: S1/ address of an FD
;
;T Ret: S1/ address of a STR queue entry
;
;F Ret: If an invalid structure field was in the FD (i.e. non-disk device)
IFN FTUUOS,<
D$ESTR::PUSHJ P,.SAVE1 ;SAVE P1
SKIPN S1,.FDSTR(S1) ;GET THE STRUCTURE NAME
$RETF ;IF NULL,,RETURN FALSE
MOVE P1,S1 ;AND SAVE IT IN P1
PUSHJ P,FNDSTR ;FIND THE STRUCTURE
JUMPT .RETT ;RETURN IF FOUND
MOVEM P1,DSKCBL+.DCNAM ;STORE STR NAME FOR DSKCHR
MOVE S2,[5,,DSKCBL] ;GET DSKCHR ARGS
DSKCHR S2, ;SEE IF STR IS ON-LINE
JRST [MOVE S2,P1 ;OFF-LINE, PUT STR NAME IN S2
DEVCHR S2, ;MAKE SURE ITS NOT A NON-DISK DEVICE
JUMPN S2,.RETF ;IF DEVICE EXISTS, RETURN FALSE
JRST ESTR.1] ;ELSE CONTINUE ON
LOAD S2,S2,DC.TYP ;GET ARGUMENT TYPE
CAXE S2,.DCTFS ;IF IT WAS A FILE STRUCTURE
CAMN P1,DSKCBL+.DCSNM ; OR SAME NAME AS WE ENTERED WITH ???
JRST ESTR.1 ;THEN GO ADD IT
MOVE P1,DSKCBL+.DCSNM ;ELSE, USE STR NAME RET BY DSKCHR
MOVE S1,P1 ;GET THE NAME IN S1
PUSHJ P,FNDSTR ;TRY ONCE MORE TO LOCATE IT
JUMPT .RETT ;WIN,,RETURN
ESTR.1: $SAVE H ;SAVE H
$SAVE AP ;SAVE AP
MOVEI H,HDRSTR## ;POINT TO THE CORRECT HEADER
PUSHJ P,M$GFRE## ;GET A FREE CELL
MOVEM P1,STRNAM(AP) ;SAVE THE STRUCTURE NAME
PUSHJ P,M$ELNK## ;LINK IT IN AT THE END
MOVE S1,AP ;PUT ADDRESS IN S1
$RETT ;AND RETURN
> ;END IFN FTUUOS
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
IFN FTJSYS,<
D$ESTR: PUSHJ P,.SAVET ;SAVE T REGISTERS
SETZM ESTR.A ;CLEAR DEVICE NAME HOLD AREA
HRROI S2,.FDFIL(S1) ;POINT TO THE FILESPEC
MOVX S1,GJ%OFG+GJ%SHT ;PARSE-ONLY AND SHORT GTJFN
GTJFN ;GET A JFN FOR THE FILESPEC
ERJMP .RETF ;ILLEGAL FILESPECIFICATION
MOVE S2,S1 ;PUT THE FILE HANDLE INTO S2
HRROI S1,ESTR.A ;PLACE TO PUT THE STRUCTURE NAME
MOVX T1,JS%DEV ;ONLY WANT THE DEVICE.
SETZ T2, ;CLEAR T2
JFNS ;GET THE STRUCTURE NAME
MOVE S1,S2 ;GET THE JFN IN S1
RLJFN ;RELEASE IT
ERJMP .+1 ;IGNORE ERRORS
MOVE S1,[ASCIZ/TTY/] ;GET AN ASCIZ 'TTY'
CAMN S1,ESTR.A ;SPECIAL CASE TTY:
$RETF ;IF TTY,,THEN RETURN FALSE
MOVE S1,[POINT 7,ESTR.A] ;POINT TO THE DEVICE NAME.
PUSHJ P,FNDSTR ;FIND THE STRUCTURE
JUMPT .RETT ;RETURN NOW IF FOUND
HRROI S1,ESTR.A ;GET THE PTR TO THE DEVICE STRING
STDEV ;CONVERT TO A DEVICE DESIGNATOR
ERJMP ESTR.1 ;IF NO SUCH DEVICE, WIN
LOAD S1,S2,DV%TYP ;GET THE DEVICE TYPE
CAIE S1,.DVDSK ;IS IT A DISK?
$RETF ;NO,,RETURN FALSE
ESTR.1: $SAVE H ;SAVE AC H
$SAVE AP ; AND AP
MOVEI H,HDRSTR## ;GET A STRUCTURE QUEUE
PUSHJ P,M$GFRE## ;GET A FREE CELL
MOVE S1,[POINT 7,ESTR.A] ;GET THE SOURCE STR BYTE PTR.
MOVE S2,[POINT 7,STRNAM(AP)] ;GET THE DESTINATION STR BYTE PTR.
ESTR.2: ILDB T1,S1 ;GET A STRUCTURE BYTE.
IDPB T1,S2 ;SAVE IT IN STR LIST.
JUMPN T1,ESTR.2 ;NOT NULL,,KEEP ON GOING.
PUSHJ P,M$ELNK## ;LINK IT IN AT THE END
MOVE S1,AP ;PUT ADDRESS IN S1
$RETT ;RETURN
> ;END IFN FTJSYS
SUBTTL D$ASTD - Add a structure dependency
;This routine is called to place a structure into the dependency list
; for a job.
;Call: S1/ adr of STR entry
; S2/ adr of QE
;
;T Ret: always
D$ASTD::PUSHJ P,.SAVET ;SAVE THE T REGISTERS
DMOVE T1,S1 ;PUT ARGUMENTS INTO T1 AND T2
LOAD S1,.QEDIN(T2),QE.DLN ;GET DEPENDENCY LIST NUMBER
PUSHJ P,L%FIRST ;AND POSITION TO THE START OF THE LIST
JUMPF ASTD.3 ;EMPTY LIST, ADD IT ON
JRST ASTD.2 ;JUMP INTO MIDDLE OF LOOP
ASTD.1: PUSHJ P,L%NEXT ;POSITION TO THE NEXT ONE
JUMPF ASTD.3 ;NO NEXT ONE, LINK IT IN
ASTD.2: LOAD T3,.DIBDS(S2),DI.TYP ;GET DEPENDENCY TYPE
CAXE T3,.DTSTR ;STRUCTURE?
JRST ASTD.1 ;NO, GET THE NEXT DEPENDENCY
CAME T1,.DIBDT(S2) ;YES, SAME STRUCTURE?
JRST ASTD.1 ;NO, ON TO THE NEXT DEPENDENCY
JRST .RETT ;YES, ALREADY RECORDED
ASTD.3: LOAD S1,.QEDIN(T2),QE.DLN ;GET LIST NUMBER
MOVX S2,DIBSIZ ;GET LIST ENTRY SIZE
PUSHJ P,L%CENT ;CREATE AN ENTRY
MOVX S1,.DTSTR ;GET CODE FOR STRUCTURE
STORE S1,.DIBDS(S2),DI.TYP ;STORE IT
STORE T1,.DIBDT(S2) ;STORE THE STR ADDRESS
$RETT ;AND RETURN
SUBTTL FNDSTR - Find a STR entry
;FNDSTR is called with a structure name to find the STR queue entry for it.
;
;Call: S1/ Structure Name (6bit on -10, byte-pointer on -20)
;
;T Ret: S1/ Address of STR queue entry
;
;F Ret: If not in STR queue
FNDSTR: LOAD S2,HDRSTR##+.QHLNK,QH.PTF
EXCH S1,S2 ;EXCHANGE S1 AND S2
IFN FTUUOS,<
FNDS.1: JUMPE S1,.RETF ;FAIL WHEN DONE.
CAMN S2,STRNAM(S1) ;MATCH?
$RETT ;YES, JUST RETURN
LOAD S1,.QELNK(S1),QE.PTN ;NO, POINT TO NEXT
JRST FNDS.1 ;AND LOOP
> ;END IFN FTUUOS
IFN FTJSYS,<
PUSHJ P,.SAVE4 ;SAVE P1 THRU P4
MOVE P4,S2 ;SAVE THE SOURCE STR POINTER.
FNDS.1: JUMPE S1,.RETF ;FAIL WHEN DONE.
MOVE P1,[POINT 7,STRNAM(S1)] ;POINT TO THE STRUCTURE NAME IN STR
FNDS.2: ILDB P2,P1 ;GET A STR CHARACTER
ILDB P3,S2 ;GET SOURCE CHARACTER
CAME P2,P3 ;ARE THEY THE SAME?
JRST FNDS.3 ;NO, NEXT STR
JUMPN P2,FNDS.2 ;YES, LOOP IF NOT NULL YET
$RETT ;WIN IF NULLS MATCH
FNDS.3: LOAD S1,.QELNK(S1),QE.PTN ;GET POINTER TO NEXT
MOVE S2,P4 ;RESET THE SOURCE STR POINTER.
JRST FNDS.1 ;AND LOOP
> ;END IFN FTJSYS
EXTERN BELLS ;MAKE THIS REFERENCE'ABLE
EXTERN G$MSG ;MESSAGE BUFFER
EXTERN G$ACKB ;GENERIC ACK BUFFER ADDRESS
TOPS10< EXTERN DEVNTB > ;%UNKN DEVICE TRANSLATION TABLE
MDRDSP: $BUILD %MDMAX+1
$SET(.MDINV,,.RETF) ;OFFSET 0 IS INVALID
$SET(.TMDEN,,MNTDEN) ;DENSITY BLOCK PROCESSOR
$SET(.TMDRV,,MNTDRV) ;DRIVE BLOCK PROCESSOR
$SET(.TMLT,,MNTLT) ;LABEL TYPE BLOCK PROCESSOR
$SET(.TMSET,,MNTSET) ;SET NAME BLOCK PROCESSOR
$SET(.TMRMK,,MNTRMK) ;REMARK BLOCK PROCESSOR
$SET(.TMSTV,,MNTSTV) ;STARTING VOLUME ID BLOCK PROCESSOR
$SET(.TMVOL,,MNTVOL) ;VOLUME ID BLOCK PROCESSOR
$SET(.TMVPR,,MNTPRT) ;VOL PROTECTION CODE BLOCK PROCESSOR
$SET(.TMINI,,.RETT) ;VOL INITIALIZATION BLOCK PROCESSOR
TOPS20< $SET(.SMNAM,,MNTSET) > ;STRUCTURE NAME PROCESSOR
TOPS10< $SET(.SMNAM,,.RETF) > ; (ILLEGAL ON TOPS10)
TOPS20< $SET(.SMALI,,MNTVOL) > ;ALIAS BLOCK PROCESSOR
TOPS10< $SET(.SMALI,,.RETF) > ; (ILLEGAL ON TOPS10)
$SET(.TMLNM,,MDRLNM) ;LOGICAL NAME PROCESSOR
$EOB
;DEFINE A MACRO TO PACK A BLOCK OF STORAGE INTO ITSELF STARTING AT
;THE ADDRESS CONTAINED IN 'AC'
DEFINE $PACK(AC),<
AOBJP AC,.+4 ;;CHECK THE AC,,IF POSITIVE,,SKIP
XLIST
MOVE TF,0(AC) ;;STILL NEGATIVE,,GET THE VALUE AT 0(AC)
MOVEM TF,-1(AC) ;;AND STORE IT AT ADDRESS AC-1
JRST .-3 ;;HEAD BACK FOR MORE
SETZM -1(AC) ;;WE'RE DONE,,ZERO THE LAST ENTRY
LIST>
;GENERALIZED VOLUME LABEL TYPE DEFINITIONS
%UNLBL==1 ;VOLUME IS UNLABELED
%LABEL==2 ;VOLUME IS LABELED
LABELS::[ASCIZ/Bypass/]
[ASCIZ/ANSI/]
[ASCIZ/ANSI/]
[ASCIZ/IBM/]
[ASCIZ/IBM/]
[ASCIZ/No/]
[ASCIZ/Non-Standard/]
[ASCIZ/No/]
[ASCIZ/Cobol Sixbit/]
[ASCIZ/Cobol Ascii/]
[ASCIZ/No/]
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
DENSTY::[ASCIZ/Default/]
[ASCIZ/200/]
[ASCIZ/556/]
[ASCIZ/800/]
[ASCIZ/1600/]
[ASCIZ/6250/]
TOPS10<
D$DEN:: 0 ;SYSTEM DEFAULT
UC.200 ;200 BPI
UC.556 ;556 BPI
UC.800 ;800 BPI
UC.1600 ;1600 BPI
UC.6250 ;6250 BPI
DENLEN==.-D$DEN
> ;END TOPS10 CONDITIONAL
TRK:: SIXBIT/ /
SIXBIT/ 7 /
SIXBIT/ 9 /
WRTENA: [ASCIZ/Enabled/]
[ASCIZ/Locked/]
AVA: [ASCIZ/Available/]
[ASCIZ/Unavailable/]
LCKTB1: SIXBIT /LOCK/
SIXBIT /UNLOCK/
LCKTB2: SIXBIT /UNLOCK/
SIXBIT /LOCK/
RID: BLOCK 1 ;REQUEST ID SAVE AREA
D$ASR:: EXP -1 ;AUTOMATIC STRUCTURE RECOGNITION FLAG
AMATRX::EXP 0 ;'A' MATRIX ADDRESS INITIALLY NONE
BMATRX::EXP 0 ;'B' MATRIX LIST ID
CMATRX::EXP 0 ;'C' MATRIX LIST ID
STRVOL: BLOCK 1 ;STARTING VOLUME SAVE AREA
VOLNBR: BLOCK 1 ;VOLUME COUNT IN A VOLUME SET
ERRACK::BLOCK 1 ;ACK BEING SENT IS A FATAL ACK
PROCNT: EXP 0 ;'B' & 'C' MATRIX PROCESS COUNTS
MDAOBJ::.OTMNT ;MDA OBJECT BLOCK - TYPE .OTMNT
EXP 0 ;SPACE FOR SIXBIT UNIT NAME
0,,0 ;NO NODE NAME
VOLNAM: BLOCK 2 ;PLACE FOR AN ASCIZ STR NAME
WRTLCK: BLOCK 1 ;WRITE-LOCKED FLAG FOR STR MOUNTS
OSNFLG: BLOCK 1 ;FLAG FOR OVERRIDE-SET-NUMBER
STRFLG: BLOCK 1 ;FLAG FOR FINDING FREE DISK UNITS
MDRQUE:: EXP -1 ;TAPE MOUNT QUEUE LIST ID
UCBQUE:: 0,,0 ;UCB QUEUE
VSLQUE:: 0,,0 ;VOLUME SET LIST QUEUE
VOLQUE:: 0,,0 ;VOLUME LIST QUEUE
CATOBJ: BLOCK OBJ.SZ ;OBJECT BLOCK FOR WTO MSG
CATFLG: BLOCK 1 ;NON-ZERO IF NO CATALOG SEARCH
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
TOPS10<
;This structure defines the initial 'A' matrix for Resource Allocation
; Call: X(Res-Name,Res-Type,Kontroler type,Unit type,Track,Density)
MAXNCH==^D39 ;MAX # OF CHARS IN A RESOURCE NAME
AMNMLN==<MAXNCH+1+4>/5 ;WORDS REQ'D TO STORE ONE OF THESE
DEFINE GENRES,<XLIST
X (RD10,%DISK,.DCCFH,.DCUFD,0,UC.SHR)
X (RS04,%DISK,.DCCFS,.DCUS4,0,UC.SHR)
X (RP04,%DISK,.DCCRP,.DCUR4,0,UC.SHR)
X (RM10B,%DISK,.DCCFH,.DCUFM,0,UC.SHR)
X (RP02,%DISK,.DCCDP,.DCUD2,0,UC.SHR)
X (RP06,%DISK,.DCCRP,.DCUR6,0,UC.SHR)
X (RP03,%DISK,.DCCDP,.DCUD3,0,UC.SHR)
X (RM03,%DISK,.DCCRP,.DCUR3,0,UC.SHR)
X (RP07,%DISK,.DCCRP,.DCUR7,0,UC.SHR)
X (RP20,%DISK,.DCCRN,.DCUN0,0,UC.SHR)
X (RA80,%DISK,.DCCRA,.DCU80,0,UC.SHR)
X (RA81,%DISK,.DCCRA,.DCU81,0,UC.SHR)
X (RA60,%DISK,.DCCRA,.DCU60,0,UC.SHR)
X (3330,%DISK,.DCCSX,.DCUS0,0,UC.SHR)
X (3331,%DISK,.DCCSX,.DCUS1,0,UC.SHR)
X (<7 TK 200/556/800>,%TAPE,0,0,%TRK7,UC.200+UC.556+UC.800)
X (<9 TK 800/1600>,%TAPE,0,0,%TRK9,UC.800+UC.1600)
X (<9 TK 1600/6250>,%TAPE,0,0,%TRK9,UC.1600+UC.6250)
X (<9 TK 200/556/800>,%TAPE,0,0,%TRK9,UC.200+UC.556+UC.800)
X (<9 TK 800/1600/6250>,%TAPE,0,0,%TRK9,UC.800+UC.1600+UC.6250)
X (TU56,%DTAP,0,0,0,0)
LIST>
DEFINE X(TYP7,TYPE,KON,UNIT,TRK,DEN),<XLIST
$BUILD AMALEN
$SET (.AMNAM,AM.NAM,[ASCIZ^TYP7^])
$SET (.AMNAM,AM.PRM,1)
$SET (.AMNAM,AM.USE,1)
$SET (.AMSTA,,<FLD(KON,UC.KTP)+FLD(UNIT,UC.UTP)+FLD(TRK,UC.TRK)+FLD(TYPE,UC.DVT)+DEN>)
$EOB
LIST>
DEFINE BLDPRM,<XLIST
GENRES ;BUILD THE PERMANENT 'A' MATRIX
LIST >
;Generate the permanent A-matrix - Build block 0, the header
AMATPM: $BUILD AMALEN
$SET (.AMHDR,AM.CNT,RESCNT) ;HIGHEST IN USE
$SET (.AMHDR,AM.MCN,RESCNT) ;BIGGEST MATRIX HAS SPACE FOR
$SET (.AMHDR,AM.LEN,RESLEN) ;LENGTH OF THIS BLOCK
$EOB
BLDPRM ;BUILD THE PERMANENT 'A' MATRIX
RESLEN==.-AMATPM ;THE LENGTH OF THE PERMANENT A MATRIX
RESCNT==<RESLEN/AMALEN>-1 ;THE NUMBER OF BLOCKS IN USE
> ;END TOPS10 CONDITIONAL
TMPVSL: BLOCK VSLLEN ;MAKE SURE WE AT LEAST HAVE ENOUGH SPACE
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
DEMOB:: ITEXT (<User: [SYSTEM] for ^15/.VSRFL(T1),MR.QUE/ Request #^D/S1/>)
DEMOT:: ITEXT (<User: ^W6/.MRNAM(AP)/^W/.MRNAM+1(AP)/ ^U/.MRUSR(AP)/ Job #^D/.MRJOB(AP),MD.PJB/>)
DEFINE X(CODE,STRING),<XLIST
EXP [ASCIZ/STRING/]
LIST >
MDAERS: MDAERR ;GENERATE THE ERROR STRINGS
SUBTTL D$INIT - ROUTINE TO INITIALIZE THE MDA DATA BASE
D$INIT::SKIPN G$MDA## ;MDA SUPPORT HERE ???
$RETT ;NO,,RETURN
PUSHJ P,L%CLST ;CREATE A LIST FOR THE MDR
MOVEM S1,MDRQUE ;SAVE THE ID
PUSHJ P,L%CLST ;CREATE A LIST FOR THE VSL SET CHAIN
MOVEM S1,VSLQUE ;SAVE THE ID
PUSHJ P,L%CLST ;CREATE A LIST FOR THE VOLUME LIST
MOVEM S1,VOLQUE ;SAVE THE ID
TOPS20< $RETT > ;RETURN NOW ON THE -20
TOPS10< ;...BUT ON THE -10...
;NOTE:::: The UCB chain will be built by I$INIT (QSRT10)
MOVEI S1,MDADAE ;GET DEADLOCK FLAG
MOVEM S1,G$DEAD## ;AND SET IT
PUSHJ P,L%CLST ;CREATE A LIST FOR THE 'B' MATRIX
MOVEM S1,BMATRX ;SAVE IT
PUSHJ P,L%CLST ;CREATE A LIST FOR THE 'C' MATRIX
MOVEM S1,CMATRX ;SAVE IT
MOVE S1,UCBQUE ;GET THE UCB QUEUE ID
PUSHJ P,L%FIRST ;POSITION TO THE FIRST UCB
JUMPT INIT.2 ;IF FOUND,,CONTINUE
STOPCD (NUE,HALT,,<Null UCB chain encountered>) ;NO,,DEEP TROUBLE
INIT.1: MOVE S1,UCBQUE ;GET THE UCB QUEUE ID
PUSHJ P,L%NEXT ;GET THE NEXT UCB ENTRY
INIT.2: JUMPF INIT.4 ;NO MORE,,SETUP PERM STRS
MOVE T1,S2 ;SAVE THE UCB ADDRESS IN T1
LOAD S1,.UCBST(T1),UC.AVA ;GET AVAILABLE BIT
JUMPE S1,INIT.1 ;NOT AVAILABLE,,SKIP THIS
MOVE S1,T1 ;GET THE UCB ADDRESS IN S1
PUSHJ P,D$INCA ;INCRIMENT THE 'A' MATRIX
JRST INIT.1 ;AND GO TRY THE NEXT UCB
INIT.4: PUSHJ P,I$ISTR## ;INITIALIZE SYSTEM STRUCTURE LIST
PUSHJ P,I$PERM## ;SETUP 'PERMENANT STRUCTURES'
MOVN P1,G$MAXJ## ;GET NUMBER OF JOBS IN THE SYSTEM
HRLZS P1 ;GET -NUMBER,,0
AOS P1 ;START WITH JOB NUMBER 1
MOVEI S1,0(P1) ;GET A JOB NUMBER
PUSHJ P,I$SSRL## ;CREATE THE GUYS MDR ENTRY
AOBJN P1,.-2 ;CONTINUE FRO ALL JOBS
PJRST MNTOPR ;RETURN,,SETTING UP MOUNTS PENDING EVENT
> ;END TOPS10 CONDITIONAL
SUBTTL HOLD/RELEASE/MOUNT interface for QSRQUE
; Here while processing a HOLD or RELEASE command to notify the
; operator of mount queue changes.
; Call: MOVE S1, QE address
; MOVE S2, 0 for HOLD or 1 for RELEASE
; PUSHJ P,D$HOLD/D$RELE
;
D$HOLD::
TOPS20 <POPJ P,> ;CAN'T DO THIS HERE
TOPS10 < ;TOPS-10 ONLY
SKIPN .QEMDR(S1) ;HAVE AN MDR?
POPJ P, ;NO
$SAVE <P1,P2,P3,P4> ;SAVE SOME ACS
$SAVE <T1,T2> ;SAVE MORE ACS
$SAVE <AP> ;SAVE AP
MOVE AP,.QEMDR(S1) ;GET THE MDR ADDRESS
MOVE T1,S2 ;REMEMBER WHAT WE'RE DOING
LOAD P1,.MRCNT(AP),MR.CNT ;GET VSL COUNT FOR THIS MDR
MOVNS P1 ;NEGATE IT
HRLI P1,.MRVSL(AP) ;GET ADDRESS OF FIRST VSL
MOVSS P1 ;MAKE AN AOBJN POINTER
HOLD.1: HRRZ P2,(P1) ;GET A VSL ADDRESS
MOVX S1,VS.ALC!VS.ABO ;GET SOME BITS
TDNE S1,.VSFLG(P2) ;ALLOCATED OR ABORTED?
JRST HOLD.4 ;YES - IGNORE THIS VSL
LOAD P3,.VSCVL(P2),VS.CNT ;GET NUMBER OF VOLS IN THE VSN
MOVNS P3 ;NEGATE IT
HRLI P3,.VSVOL(P2) ;GET ADDRESS OF FIRST VOL
MOVSS P3 ;MAKE AN AOBJN POINTER
HOLD.2: HRRZ P4,(P3) ;GET A VOL ADDRESS
HRRZ S1,.VLVSL(P4) ;GET A VSL BACK POINTER
MOVX S2,VL.ASN ;GET THE VOL ASSIGNED BIT
CAMN S1,P2 ;SAME VSL?
TDNE S2,.VLVSL(P4) ;AND VOL ASSIGNED?
JRST HOLD.3 ;TRY ANOTHER VOL
MOVE S1,.VSRID(P2) ;GET MOUNT REQUEST ID
MOVE S2,.MRQEA(AP) ;GET QE ADDRESS
MOVE S2,.QERID(S2) ;GET QE REQUEST ID
LOAD T2,.VSRFL(P2),MR.QUE ;[1173] GET OBJECT TYPE
$WTO (<Mount request #^D/S1/>,<^I/HOLD.5/>,,<$WTFLG(WT.SJI)>)
JUMPE T1,HOLD.3 ;ONWARD IF HOLDING THIS JOB
MOVX S1,VS.OPR ;GET A BIT
IORM S1,.VSFLG(P2) ;AND WAKE UP THE SLEEPING OPERATOR
HOLD.3: AOBJN P3,HOLD.2 ;LOOP THROUGH ALL VOL BLOCKS
HOLD.4: AOBJN P1,HOLD.1 ;LOOP THROUGH ALL VSL BLOCKS
POPJ P, ;RETURN
HOLD.5: ITEXT (<^T/@HOLD.6(T1)/ the queue due to ^T/@MNTTAB(T2)/
request #^D/S2/ being ^T/@HOLD.7(T1)/>)
HOLD.6: [ASCIZ |Removed from|] ;HOLD
[ASCIZ |Added to|] ;RELEASE
HOLD.7: [ASCIZ |held|] ;HOLD
[ASCIZ |released|] ;RELEASE
; Translation table of object type to text for mount displays
;
MNTTAB: [0,,0] ;INVALID
[0,,0] ;.OTRDR (READER QUEUE)
[0,,0] ;.OTNET (NETWORK QUEUE)
[ASCIZ |Print|] ;.OTLPT (PRINTER QUEUE)
[ASCIZ |Batch|] ;.OTBAT (BATCH QUEUE)
[ASCIZ |Card punch|] ;.OTCDP (CARD PUNCH QUEUE)
[ASCIZ |Paper tape punch|] ;.OTPTP (PAPER TAPE PUNCH QUEUE)
[ASCIZ |Plotter|] ;.OTPLT (PLOTTER QUEUE)
[0,,0] ;.OTJOB
[0,,0] ;.OTTRM
[0,,0] ;.OTOPR
[0,,0] ;.OTIBM
[0,,0] ;.OTMNT
[ASCIZ |File transfer|] ;.OTFTS (FILE TRANSFER QUEUE)
[ASCIZ |Interpreter|] ;.OTBIN (SPRINT)
[ASCIZ |Retrieval|] ;.OTRET
[0,,0] ;.OTNOT
[0,,0] ;.OTDBM
[0,,0] ;.OTFAL
> ;END TOPS-10 CONDITIONAL
SUBTTL D$MOUN - Process a Tape/Disk Mount Request
;CALL: M/ The Mount Message Address
; S1/ The QE address if entry point D$MNTP
;
;RET: An Ack to the user (If he wants one)
D$MNTP::SKIPA ;MNTP ENTRY POINT (CALLED FROM I$BMDR)
D$MOUN::SETZM S1 ;'MOUNT' ENTRY POINT
SKIPN G$MDA## ;[1135]IS MDA SUPPORTED ???
JRST E$MDA## ;NO,,RETURN AN ERROR !!!
PUSHJ P,.SAVE1 ;SAVE P1 FOR A SECOND
MOVE P1,S1 ;SAVE THE QE ADDRESS IF THERE IS ONE
PUSHJ P,D$CMDR ;GO CREATE THE MDR ENTRY
JUMPF .RETT ;RETURN IF AN ERROR OCCURED
JUMPN P1,MOU.7 ;[1135]JUMP IF QE ADDRESS HELD
PUSH P,S1 ;[1135]SAVE S1
LOAD S1,.MRJOB(AP),MR.JOB ;[1135]GET REQUESTING JOB NUMBER
TXNE S1,BA%JOB ;[1135]INITIAL MOUNTS FOR BATCH JOB ?
JRST MOU.6 ;[1135]JUMP IF SO
ANDX S1,MD.PJB ;JUST JOB NUMBER
MOVX S2,JI.BAT ;[1135]GET BATCH DATA FOR JOB
$CALL I%JINF ;[1135]GET DATA
TXNN S2,OB.BSS ;[1135]BATCH JOB
JRST MOU.6 ;[1135] JUMP IF NOT
PUSH P,P2 ;[1135]SAVE P2 FOR A MINUTE
LOAD P2,HDRUSE##+.QHLNK,QH.PTF ;[1135]POINT TO IN USE QUEUE
JUMPE P2,MOU.5 ;[1135]FORGET IT IF EMPTY
LOAD S1,S2,OB.BSN ;[1135]GET BATCH STREAM NUMBER
MOU.2: LOAD S2,.QEROB+.ROBTY(P2) ;[1135]GET OBJECT TYPE
CAIE S2,.OTBAT ;[1135]BATCH ?
JRST MOU.3 ;[1135]JUMP IF SO
LOAD S2,.QEOBJ(P2) ;[1135]GET BATCH OBJECT
LOAD S2,OBJUNI(S2) ;[1135]GET STREAM NUMBER
CAME S2,S1 ;RIGHT STREAM?
JRST MOU.3 ;NO, TRY AGAIN
PUSH P,S1 ;SAVE THE STREAM NUMBER
LOAD S1,.QEOBJ(P2) ;GET OBJECT BLOCK ADDRESS
LOAD S1,OBJNOD(S1) ;GET PROCESSING NODE
PUSHJ P,N$LOCL## ;IS PROCESSING LOCAL?
POP P,S1 ;RECOVER STREAM NUMBER
JUMPT MOU.4 ;SAME STREAM AND LOCAL?
MOU.3: LOAD P2,.QELNK(P2),QE.PTN ;[1135]LOOK AT NEXT ENTRY
JUMPN P2,MOU.2 ;[1135]LOOP TO END
MOU.4: MOVE P1,P2 ;[1135]IF QE FOUND, GET ADDRESS
MOU.5: POP P,P2 ;[1135]RESTORE P2
MOU.6: POP P,S1 ;[1135]RESTORE S1
MOU.7: JUMPE P1,MOU.8 ;[1135]NO QE,,SKIP NEXT 2 INSTRUCTIONS
MOVEM AP,.QEMDR(P1) ;YES,,SAVE THE MDR ADDRESS
MOVEM P1,.MRQEA(AP) ;SAVE THE QE ADDRESS IF ANY
MOU.8: MOVE P1,S1 ;[1135]SAVE VSL ADDRESS (FROM D$CMDR)
MOVE S2,G$ACK## ;GET THE ACK REQUEST CODE
STORE S2,.VSRFL(P1),MR.ACK ;[1173] SAVE IT IN VSL
SETZM G$ACK## ;CLEAR THE ACK REQUEST
PUSHJ P,I$MNTR## ;SEND THE MESSAGE TO MOUNTR (TOPS20 ONL
JUMPF D$DMDR ;NO GOOD,,DELETE THE MDR AND RETURN
TOPS20< PUSHJ P,USRACK ;ACK THE USER
$RETT ;AND RETURN
>
TOPS10< MOVE S1,P1 ;GET THE VSL ADDRESS
PUSHJ P,D$ALOC ;TRY TO PERFORM ALLOCATION
JUMPF [JUMPL S1,.RETT ;ALLOCATION POSTPONED,,JUST RETURN
MOVE S1,P1 ;NO GOOD,,GET THE VSL ADDRESS BACK
PJRST DELETE ] ;RETURN,,DELETING VOL SETS JUST ADDED
MOVE S1,P1 ;GET THE VSL ADDRESS
PUSHJ P,MNTVSL ;TRY TO MOUNT IT
$RETT ;RETURN
>
SUBTTL D$DEAS - DEASSIGN/RELEASE A VOLUME SET
;CALL: M / The Deassign Message Address
;
;RET: True Always
TOPS10 <
D$DEAS::PUSHJ P,.SAVE3 ;SAVE P1 & P2 FOR A MINUTE
LOAD S1,.TDDVT(M),TDD.FL ;[1234] GET MONITOR FLAGS
TXNN S1,TD.VSW ;[1234] VOL SWITCH STATS?
JRST DEAS.0 ;[1234] NO, CONTINUE
MOVE S1,.TDJBN(M) ;[1234] YES, GET JOB NUMBER
PUSHJ P,FNDMDR ;[1234] GET MDR FOR JOB
JUMPT I$TDSM## ;[1234] GO UPDATE ACCOUNTING
$RETT ;[1234] FORGET IT IF NO MDR
DEAS.0: MOVE S1,.TDDEV(M) ;[1234] GET THE RELEASED DEVICE NAME
PUSHJ P,UCBLOC ;FIND THE DEVICE IN THE UCB CHAIN
JUMPT DEAS.1 ;CONTINUE IF WE KNOW ABOUT THIS DEVICE
MOVE S1,.TDDEV(M) ;PICK UP THE DEVICE NAME
PUSHJ P,I$MDAC## ;CLEAR THE MDA BIT
$WTO (<Released>,,MDAOBJ) ;TELL THE OPERATOR
$RETT ;RETURN
DEAS.1: MOVE P1,S1 ;SAVE THE UCB ADDRESS IN P1
SKIPN P2,.UCBVS(P1) ;DOES THE UCB POINT TO A VSL ???
$RETT ;NO OWNER,,STRANGE !!!
MOVE AP,.VSMDR(P2) ;GET THE MDR ADDRESS
LOAD S1,.MRJOB(AP),MD.PJB ;GET THE OWNERS JOB NUMBER
CAME S1,.TDJBN(M) ;THESE MUST MATCH !!!
STOPCD (IOS,HALT,,<Invalid Owner Specified in Reassign Message>) ;NO,,UH OH !!
$WTO (<Released>,<^I/DEMOT/>,MDAOBJ) ;TELL OPR WHATS GOING ON
MOVE S1,P2 ;GET THE VSL ADDRESS IN S1
LOAD S2,.TDDVT(M),TDD.DV ;[1234] GET THE DEVICE TYPE
CAIN S2,.TYDTA ;DECTAPE?
JRST DEAS.2 ;YES
CAIN S2,.TYMTA ;MAGTAPE?
JRST DEAS.3 ;YES
MOVE S1,.TDDEV(M) ;[1141]PICK UP THE DEVICE NAME
PUSHJ P,I$MDAC## ;CLEAR THE MDA BIT
MOVE S1,UCBQUE ;[1141]GET THE UCB QUEUE ID
MOVE S2,.VSUCB(P2) ;GET THE UCB ADDRESS
PUSHJ P,L%APOS ;POSITION TO THAT ENTRY
PUSHJ P,L%DENT ;DELETE THAT ENTRY
SETZM .VSUCB(P2) ;ZAP THAT POINTER
MOVE S1,P2 ;GET THE VSL ADDRESS
PUSHJ P,DELVSL ;DELETE IT
LOAD S1,.MRCNT(AP),MR.CNT ;GET THE USERS REQUEST COUNT
JUMPE S1,DELMDR ;NOTHING LEFT,,DELETE THE MDR
$RETT ;AND EXIT
DEAS.2: PUSHJ P,I$DDSM## ;DO DECTAPE ACCOUNTING
MOVE S1,.TDDEV(M) ;COPY THE DEVICE NAME
PUSHJ P,I$MDAC## ;CLEAR THE MDA BIT
SKIPA ;ENTER COMMON CODE
DEAS.3: PUSHJ P,I$TDSM## ;DO MAGTAPE ACCOUNTING
MOVE S1,P2 ;GET THE VSL ADDRESS IN S1
PUSHJ P,ALCVSL ;RETURN THIS VSL TO THE ALLOCATION POOL
LOAD S1,.MRCNT(AP),MR.CNT ;GET THE USERS REQUEST COUNT
JUMPE S1,DELMDR ;NOTHING LEFT,,DELETE THE MDR
$RETT ;AND EXIT
>
SUBTTL D$CMDR - ROUTINE TO CREATE AN ENTRY IN THE MDR QUEUE
;CALL: M/The MOUNT Message Address
;
;RET: AP/ The MDR address
; S1/ The VSL address
D$CMDR::PUSHJ P,VALMSG ;GO VALIDATE SOME OF THE MESSAGE
JUMPF .RETF ;NO GOOD,,THATS AN ERROR
PUSHJ P,.SAVE4 ;SAVE 4 P AC'S
MOVE S1,REQIDN## ;SAVE THE LAST VALID REQUEST ID
MOVEM S1,RID ; FOR A FEW MINUTES
LOAD S1,G$PRVS##,MR.JOB ;GET THE SENDERS JOB NUMBER
PUSHJ P,FNDMDR ;FIND THIS USERS MDR
JUMPF CMDR.1 ;NOT THERE,,CREATE ONE
;Here to check to see if there is enough room for the next VSL
;and if not, create a new MDR
MOVE S1,MDRQUE ;GET THE MDR QUEUE ID
PUSHJ P,L%SIZE ;GET HIS CURRENT MDR LENGTH
MOVE P4,S2 ;SAVE THE MDR LENGTH
LOAD S1,.MRCNT(AP),MR.CNT ;GET THE VSL COUNT
SUBI S2,MDRLEN(S1) ;DELETE BASE MDR LEN+VSL CNT FROM TOTAL
SUB S2,.MMARC(M) ;SUBTRACT NEW REQUEST NUMBER
JUMPGE S2,CMDR.2 ;NEW REQUEST WILL FIT INTO OLD MDR !!
MOVNS S2 ;GET POSITIVE DIFFERENCE
ADD S2,P4 ;ADD IT TO THE OLD MDR LENGTH
MOVE S1,MDRQUE ;GET THE MDR QUEUE ID
PUSHJ P,L%CENT ;CREATE A NEW MDR FOR THE USER
MOVE P3,S2 ;SAVE THE NEW MDR ADDRESS
HRL P3,AP ;CREATE SOURCE,,DEST BLT AC
ADDI P4,-1(S2) ;GET BLT END ADDRESS
BLT P3,0(P4) ;COPY OLD MDR TO NEW MDR
EXCH AP,S2 ;EXCHANGE OLD AND NEW MDR ADDRESSES
MOVE S1,MDRQUE ;GET THE MDR QUEUE ID
PUSHJ P,L%APOS ;POSITION TO THE OLD MDR
PUSHJ P,L%DENT ; AND DELETE IT
SKIPE S1,.MRQEA(AP) ;POINTING TO A QE ???
MOVEM AP,.QEMDR(S1) ;YES,,RESET POINTER !
LOAD S1,.MRCNT(AP),MR.CNT ;GET THE VSL COUNT (CURRENT)
MOVNS S1 ;NEGATE IT
MOVSS S1 ;MOVE RIGHT TO LEFT
HRRI S1,.MRVSL(AP) ;CREATE AOBJN AC FOR VSL ADDRESS LIST
CMDR.0: MOVE S2,0(S1) ;GET A VSL ADDRESS
MOVEM AP,.VSMDR(S2) ;RESET MDR POINTER FOR NEW MDR
AOBJN S1,CMDR.0 ;RESET ALL VSL MDR POINTERS
JRST CMDR.2 ;AND CONTINUE PROCESSING
;CONTINUED ON THE NEXT PAGE
;Here to create a new MDR for a user who does not already have one
CMDR.1: MOVE S1,MDRQUE ;GET THE QUEUE ID
PUSHJ P,L%LAST ;POSITION TO THE LAST ENTRY
MOVE S1,MDRQUE ;GET THE QUEUE ID
SKIPG S2,.MMARC(M) ;CHECK AND LOAD THE VOLUME SET COUNT
PJRST E$MRP## ;NONE,,THEN 'MOUNT/WAIT' W/NONE PENDING
ADDI S2,MDRLEN-1 ;ADD MDR LENGTH-1
PUSHJ P,L%CENT ;GO CREATE A QUEUE ENTRY
MOVE AP,S2 ;GET THE ENTRY ADDRESS
MOVE S1,AP ;GET THE MDR ADDRESS IN S1
PUSHJ P,I$DFMR## ;FILL IN SYSTEM DEPENDENT DATA
CMDR.2: MOVE S1,G$SID## ;GET THE OWNERS ID
MOVEM S1,.MRUSR(AP) ;SAVE IT IN THE QUEUE
MOVE S1,G$SND## ;GET THE SENDERS PID
MOVEM S1,.MRPID(AP) ;SAVE IT
MOVE S1,.MSCOD(M) ;GET THE SENDERS ACK CODE
MOVEM S1,.MRACK(AP) ;SAVE IT
MOVE S1,G$PRVS## ;GET THE SENDERS CAPABILITIES
MOVEM S1,.MRJOB(AP) ;SAVE IT IN THE QUEUE
SETZM .MRFLG(AP) ;[1173] START CLEAN
LOAD S1,.MMFLG(M),MM.WAT ;GET USER REQUEST FOR WAITING
STORE S1,.MRFLG(AP),MR.WAT ;SAVE IN MDR
LOAD S1,.MMFLG(M),MM.NOT ;AND GET USER NOTIFY BIT
STORE S1,.MRFLG(AP),MR.NOT ;AND SAVE THAT IN MDR
LOAD S1,.MMFLG(M),MM.GFR ;GET CREATED BY [SYSTEM]GOPHER BIT
;**;[1170] Delete 3 lines after CMDR.2+12L. 29-Dec-83 /LWS
STORE S1,.MRFLG(AP),MR.GFR ;SET/CLEAR THE BIT
LOAD S1,.MRJOB(AP),MR.JOB ;GET THE REQUESTING JOB NUMBER
TXNE S1,BA%JOB ;IS THIS A BATCH REQUEST ???
JRST CMDR.3 ;YES,,SKIP THIS
MOVX S2,JI.JLT ;CODE TO GET LOGIN TIME
$CALL I%JINF ;ASK THE LIBRARY
MOVEM S2,.MRLOG(AP) ;SAVE IN MDR FOR NOTIFY
CMDR.3: INCR .MRCNT(AP),MR.LNK ;GEN A NEW VSL LINK CODE
MOVEI P2,.MMHSZ(M) ;POINT TO THE FIRST MOUNT ENTRY
SKIPN P4,.MMARC(M) ;GET THE VOLUME SET COUNT IN P4
JRST CMDR.6 ;NONE,,THEN .MOUNT/WAIT...
CMDR.4: MOVE S1,P2 ;GET THE MOUNT MSG ENTRY ADDRESS IN S1
PUSHJ P,BLDVSL ;GO BUILD THE VOLUME SET LIST
JUMPF CMDR.5 ;CHK BLDVSL - NO GOOD,,DELETE THIS MDR
MOVE P1,S1 ;SAVE THE VSL ADDRESS
PUSHJ P,MDR2VS ;[1173] COPY VSL REQUEST DEPENDENT DATA
LOAD S1,.MEHDR(P2),AR.LEN ;GET THIS ENTRIES LENGTH
ADDI P2,0(S1) ;POINT TO THE NEXT ENTRY
SOJG P4,CMDR.4 ;CONTINUE THROUGH ALL VOLUME SETS
SETOM .MRFLG(AP) ;[1173] INDICATE MDR ACK DATA COPIED
MOVE S1,P1 ;RETURN THE LAST VSL ADDRESS
$RETT ;RETURN
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
CMDR.5: PUSHJ P,DELETE ;DELETE THE VOL SETS JUST ADDED
MOVE S1,RID ;GET THE LAST VALID REQUEST ID
MOVEM S1,REQIDN## ;SAVE IT
SKIPN G$ERR## ;DID WE ALREADY SEE AN ERROR?
PJRST E$IMM## ;NO, RETURN THROUGH 'INVALID MOUNT MSG'
$RETF ;YES, BUBBLE IT UP!
;Here if MOUNT/WAIT<CRLF> was typed
CMDR.6: LOAD P1,.MRCNT(AP),MR.LNK ;GET CURRENT LINK CODE
LOAD P2,.MRCNT(AP),MR.CNT ;GET REQUEST COUNT
MOVNS P2 ;NEGATE THE REQUEST COUNT
MOVSS P2 ;GET COUNT IN LEFT HALF
HRRI P2,.MRVSL(AP) ;CREATE ABOJN AC
SETZM P3 ;SET MOUNT PENDING FLAG
CMDR.7: MOVE S1,0(P2) ;PICK UP A VSL ADDRESS
LOAD S2,.VSFLG(S1),VS.ALC ;IS IT JUST ALLOCATED ???
JUMPN S2,CMDR.8 ;YES,,TRY NEXT
PUSHJ P,CHKOWN ;CHECK FOR OWNERSHIP
JUMPT [MOVX S2,VL.ASK ;OWNED,,CHECK TO SEE IF 'ASK' IS SET
TDNN S2,0(S1) ;IS IT REALLY MOUNTED ???
JRST CMDR.8 ;YES,,TRY NEXT REQUEST
JRST .+1 ] ;NO,,ADD'EM UP
MOVE P3,0(P2) ;SAVE THE VSL ADDRESS
STORE P1,.VSLNK(P3),VS.LNK ;RESET LINK CODE
CMDR.8: AOBJN P2,CMDR.7 ;GET NEXT REQUEST
JUMPE P3,E$MRP## ;NONE WAITING,,TELL THE USER
MOVX S1,MR.ACK ;[1173] HE HAS MOUNTS, HE'LL
IORM S1,.MRFLG(AP) ;[1173] NEED 2 ACKS TO GET OUT OF MOUNT
MOVE S1,P3 ;RETURN THE LAST VSL ADDRESS
$RETT ;LETERRIP
SUBTTL D$LOGO - DELETE A USER MDR'S ON LOGOUT
;CALL: S1/ The User Job Number
;
;RET: True Always
TOPS10 <
D$LOGO::SKIPN G$MDA## ;MUST BE RUNNING WITH MDA ENABLED
$RETT ;NO,,RETURN
$SAVE <AP> ;SAVE AP FOR A SECOND
PUSHJ P,FNDMDR ;FIND THIS USERS MDR
JUMPF .RETT ;NO MORE,,RETURN
PUSHJ P,D$DMDR ;DELETE THIS MDR
$RETT ;RETURN
>
TOPS20<
D$LOGO: $RETT > ;JUST RETURN ON THE -20
SUBTTL D$XCH - Exchange disk units
; Here when the monitor sends us an exchange message (.IPCXC). This can
; happen when an operator issues the priv'ed command XCHANGE to swap two
; disk units.
;
;CALL: M/ The Message address
;
;RET: True always
TOPS10< INTERN D$XCH ;EXCHANGE DISK UNITS
D$XCH: PUSHJ P,.SAVE1 ;SAVE P1
MOVE S1,.XCHU1(M) ;GET UNIT 1 NAME
PUSHJ P,UCBLOC ;FIND THE UCB
JUMPF XCH.1 ;CAN'T - EXIT
MOVE P1,S1 ;SAVE ADDRESS
MOVE S1,.XCHU2(M) ;GET UNIT 2 NAME
PUSHJ P,UCBLOC ;FIND THE UCB
JUMPF XCH.2 ;CAN'T - EXIT
MOVE S2,.UCBNM(P1) ;GET OLD UNIT 1 NAME
EXCH S2,.UCBNM(S1) ;SET NEW UNIT 2 NAME, GET OLD UNIT 2
MOVEM S2,.UCBNM(P1) ;SET NEW UNIT 1 NAME
MOVE S2,.UCBAU(P1) ;GET OLD UNIT 1 ALT PORT
EXCH S2,.UCBAU(S1) ;SAVE OLD ALT PORT,,GET NEW ALT PORT
MOVEM S2,.UCBAU(P1) ;SAVE NEW ALT PORT NAME
$WTO (<Disk unit ^W/.XCHU1(M)/ exchanged with ^W/.XCHU2(M)/>,,,<$WTFLG(WT.SJI)>)
$RETT ;RETURN
XCH.1: SKIPA S1,.XCHU1(M) ;FIRST DEVICE FAILED
XCH.2: MOVE S1,.XCHU2(M) ;SECOND DEVICE FAILED
$WTO (<MDA data base update failure>,<Cannot find UCB for ^W/S1/>,,<$WTFLG(WT.SJI)>)
$RETT ;RETURN
> ;END TOPS10 CONDITIONAL
SUBTTL D$DMDR - ROUTINE TO UNWIND AND DELETE AN MDR
;CALL: AP/ The MDR Address
;
;RET: True Always
;AC Usage: AP/ MDR Entry
; P1/ VSL AOBJN AC
D$DMDR::PUSHJ P,.SAVE1 ;SAVE P1 FOR A MINUTE
SKIPN S1,.MRVSL(AP) ;CHECK AND LOAD THE FIRST VSL ADDRESS
PJRST DELMDR ;NONE THERE,,JUST DELETE THE MDR
CAIN S1,TMPVSL ;ARE WE POINTING TO THE TEMP VSL ???
JRST DELMDR ;YES,,JUST DELETE THE MDR AND RETURN
LOAD P1,.MRCNT(AP),MR.CNT ;GET THE VSL COUNT
DMDR.1: MOVE S1,.MRVSL(AP) ;PICK UP THE CURRENT VSL ADDRESS
PUSHJ P,DELVSL ;GO DELETE IT
SOJG P1,DMDR.1 ;CONTINUE THROUGH ALL VSL'S
PUSHJ P,DELMDR ;DELETE THIS MDR
$RETT ;RETURN
SUBTTL D$IDEN - ROUTINE TO PROCESS THE IDENTIFY COMMAND
;CALL: M /The Identify Message Address
;
;RET: True Always
TOPS10 <
D$IDEN::PUSHJ P,.SAVE4 ;SAVE SOME REGS
MOVX S1,.CMDEV ;GET THE DEVICE BLOCK TYPE
PUSHJ P,A$FNDB## ;FIND IT IN THE MESSAGE
JUMPF E$IMO## ;NOT THERE,,THATS AN ERROR
PUSHJ P,LOCUCB ;GO FIND THE AFFECTED UCB
JUMPF D$ASGN ;NO UCB,,TRY REASSIGNMENT ANYWAY !!!
MOVE P1,S1 ;SAVE POINTER TO UCB
LOAD S1,.UCBST(P1),UC.AVA ;GET THE AVAILABLE STATUS BIT
SKIPN S1 ;IS THE DEVICE AVAILABLE ???
$ERJMP MD$IUD ;NO,,RETURN ERROR
;A Small Security Check Before We Start !!!
SKIPN P3,.UCBVL(P1) ;CHECK AND LOAD THE VOL BLOCK ADDRESS
$ERJMP MD$NVM ;RETURN NO VOLUME MOUNTED ON DRIVE !!!
LOAD S1,.VLOWN(P3),VL.CNT ;GET THE VOLUME REQUEST COUNT
LOAD S2,.UCBST(P1),UC.VSW ;GET THE DEVICE VOLUME SWITCH STATUS
SKIPE S1 ;CAN'T BE REQUESTED BY ANYONE
JUMPN S2,[$ERJMP MD$CIU] ;AND BE SWITCHING VOLS ON SAME DEVICE
;Check for a VOLID Block and process it if there is one.
MOVX S1,.VOLID ;GET THE VOLID BLOCK TYPE
PUSHJ P,A$FNDB## ;FIND IT IN THE MESSAGE
JUMPF IDEN.1 ;NOT THERE,,CONTINUE ON
HRROI S1,0(S1) ;POINT TO THE ASCIZ VOLID
PUSHJ P,S%SIXB ;CONVERT IT TO SIXBIT
MOVE P4,S2 ;SAVE THE NEW VOL ID FOR A MINUTE
LOAD S1,.UCBST(P1),UC.DVT ;GET DEVICE TYPE
CAIE S1,%DTAP ;DECTAPE?
JRST IDEN.0 ;NO--MUST BE A MAGTAPE
MOVE S1,S2 ;GET THE REELID IN S1
PUSHJ P,FNDECT ;SEE IF IT'S ALREADY IN OUR DATA BASE
SKIPF ;NOT THERE,,CONTINUE ONWARD
JUMPN S2,.RETT ;IF FOUND AND MOUNTED,,JUST RETURN
MOVE S1,P3 ;GET THE VOLUME ADDRESS IN S1
PUSHJ P,FNDOWN ;ANY OWNERS OF THE VOLUME ???
SKIPF ;NO,,SKIP
$ERJMP MD$DAU ;YES,,CAN THE REQUEST
MOVEM P4,.VLNAM(P3) ;SAVE THE NEW REELID
$ACK (<Volume ^W/.VLNAM(P3)/ mounted>,,MDAOBJ,.MSCOD(M))
$RETT ;ACK THE OPR AND RETURN
IDEN.0: MOVE S1,S2 ;GET THE VOL ID IN S1
PUSHJ P,FNTAPE ;SEE IF IT'S ALREADY IN OUR DATA BASE
SKIPF ;NOT THERE,,CONTINUE ONWARD
JUMPN S2,.RETT ;IF FOUND AND MOUNTED,,JUST RETURN
MOVE S1,P3 ;GET THE VOLUME ADDRESS IN S1
PUSHJ P,FNDOWN ;ANY OWNERS OF THE VOLUME ???
SKIPF ;NO,,SKIP
$ERJMP MD$DAU ;YES,,CAN THE REQUEST
LOAD S1,.VLFLG(P3),VL.LBT ;GET THE VOLUME LABEL TYPE
PUSHJ P,GETLBT ;RECODE IT TO SOMETHING UNDERSTANDABLE
CAXN S1,%LABEL ;IS THE VOLUME LABELED ???
$ERJMP MD$VIL ;YES,,CAN'T DO THIS
MOVEM P4,.VLNAM(P3) ;SAVE THE NEW VOLUME ID
$ACK (<Unlabeled volume ^W/.VLNAM(P3)/ mounted>,,MDAOBJ,.MSCOD(M))
$RETT ;ACK THE OPR AND RETURN
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
IDEN.1: MOVX S1,.ORREQ ;GET THE REQUEST-ID BLOCK TYPE
PUSHJ P,A$FNDB## ;FIND IT IN THE MESSAGE
JUMPF E$IMO## ;NOT THERE,,THATS AN ERROR
MOVE S1,0(S1) ;LOAD THE USER REQUEST ID NUMBER
PUSHJ P,FNDVSL ;GET THE REQUESTED VSL ENTRY
JUMPF E$MRP## ;NOT THERE,,OPERATOR ERROR !!!
MOVE P4,S1 ;SAVE THE VSL ADDRESS
LOAD S1,.VSFLG(P4),VS.ABO ;WAS IT CANCELLED ???
JUMPN S1,E$MRP## ;YES,,EXIT NOW
LOAD S1,.UCBST(P1),UC.VSW ;GET THE VOLUME SWITCH BIT
SKIPE S1 ;NOT SWITCHING VOLS,,SKIP NEXT CHECK !!
CAMN P4,.UCBVS(P1) ;YES,,DOES THIS USER OWN THE DEVICE ???
SKIPA ;NO VOL SWTCH OR USER OWNS IT,,CONTINUE
$ERJMP MD$DAU ;UH OH,DEVICE IS IN USE BY SOMEONE ELSE
LOAD S2,.VSCVL(P4),VS.OFF ;GET OFFSET TO CURRENT VOLUME IN SET
ADDI S2,.VSVOL(P4) ;AIM AT THAT POINTER
MOVE P2,0(S2) ;GET ADDR OF THAT VOLUME BLOCK
SKIPE S1,.VLUCB(P2) ;IS THE REQUESTED VOLUME MOUNTED?
CAMN S1,P1 ;YES, IS THE OPR DOING THE RIGHT THING?
SKIPA ;NOT MOUNTED OR CORRECT DRIVE, SKIP
$ERJMP MD$VND,P4 ;OPR PICKED WRONG DRIVE.. TELL HIM
MOVE S1,P2 ;GET THE VOLUME ADDRESS IN S1
PUSHJ P,FNDOWN ;ANY OWNERS OF THE VOLUME ???
SKIPF ;NO,,SKIP
$ERJMP MD$VAU ;YES,,CAN THE REQUEST
;**;[1134]DELETE FIVE LINES AND IDN.1A LABEL AFTER IDEN.1:+27L 7-JUN-83/CTK
MOVE S1,P3 ;[1134]GET THE VOLUME ADDRESS IN S1
PUSHJ P,FNDOWN ;ANY OWNERS OF THE VOLUME ???
SKIPF ;NO,,SKIP
$ERJMP MD$DAU ;YES,,CAN THE REQUEST
LOAD S2,.VSFLG(P4),VS.LBT ;GET THE REQUESTED LABEL TYPE
CAXN S2,.TFLBP ;USER WANTS BYPASS?
JRST IDEN.3 ;YES,,JUST GO REASSIGN THE VOLUME
;**;[1134]ADD FIVE LINES AFTER IDEN.1:+34L 7-JUN-83/CTK
SKIPE S1,.VLNAM(P3) ;[1134]DID THE OPR SPECIFY A VOLUME?
SKIPN S2,.VLNAM(P2) ;[1134]GET USER'S REELID
JRST IDN.1A ;[1134]NO REELID OR SCRATCH
CAME S1,S2 ;[1134]IS IT WHAT THE USER SPECIFIED
$ERJMP MD$RDM,P4 ;[1134]NO, GIVE ERROR
IDN.1A: LOAD S1,.VSFLG(P4),VS.TYP ;GET REQUEST TYPE
CAIE S1,%TAPE ;MAGTAPE?
JRST IDEN.2 ;NO--MUST BE DECTAPE
LOAD S1,.VLFLG(P3),VL.LBT ;[1134]GET VOLUME'S LABEL TYPE
PUSHJ P,GETLBT ;GET EASY CODE
CAXE S1,%LABEL ;IS THE MOUNTED VOLUME LABELED?
JRST IDEN.2 ;NO,,CHECK VOLIDS
LOAD S1,.VLFLG(P2),VL.SCR ;YES,,GET THE VOLUME'S SCRATCH BIT
JUMPE S1,[$ERJMP MD$VIL,P4] ;CAN'T HAVE LABELS & NOT BE SCRATCH
IDEN.2: SKIPN .VLNAM(P2) ;REQUESTED VOL MUST HAVE A NAME !!
SKIPE .VLNAM(P3) ; OR ELSE MOUNTED VOL MUST HAVE A NAME
SKIPA ;YES TO EITHER,,WIN !!
$ERJMP MD$NVI,P4 ;BOTH NULL,,CAN'T DO THIS !!!
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
IDEN.3: DMOVE S1,P3 ;GET THE VOL AND VSL ADDRESSES
PUSHJ P,CVLVSL ;CHECK THE REQUESTED CHARACTERISTICS
JUMPF .RETF ;NO GOOD,,JUST RETURN
;Found a matching volume - there may be a VOL block off the VSL from
;the requesting MDR, and another from the UCB for the mounted volume.
;If so, we will have to merge them together, and throw one away.
CAIN P2,0(P3) ;ARE OLD AND NEW VOL'S THE SAME ???
JRST IDEN.4 ;YES,,DONT DELETE ANY - JUST CONTINUE
MOVE T1,.VLFLG(P2) ;SAVE THE OLD FLAG BITS (JUST IN CASE)
LOAD S1,.VLFLG(P3),VL.FLG ;GET ALL THE FLAGS FOR THIS UNIT'S VOL
STORE S1,.VLFLG(P2),VL.FLG ;SAVE IN REAL VOL BLOCK
MOVE S1,.VLNAM(P3) ;GET VOL NAME FOR THIS UNITS VOL BLK
SKIPE .VLNAM(P2) ;IS THERE A NAME IN THE USERS VOL BLOCK
JRST IDN.3A ;YES,,NO NEED TO ALLOCATE THE NEW ONE !!
;Update the VOL volid and allocate it
MOVEM S1,.VLNAM(P2) ;NO,,SAVE UNITS VOLID AS USERS VOLID
MOVE S1,P4 ;GET THE VSL ADDRESS
PUSHJ P,CKTVOL ;VALIDATE THIS VOLID FOR THIS USER
JUMPF [SETZM .VLNAM(P2) ;NO GOOD,,BACK TO SCRATCH
MOVEM T1,.VLFLG(P2) ;RESTORE THE OLD FLAG BITS
$RETF ] ;AND RETURN
PUSHJ P,D$BMTX ;LOCATE THIS GUYS 'B' MATRIX ENTRY
MOVE S1,P2 ;GET THE VOL ADDRESS
PUSHJ P,D$TVRS ;CONVERT TO A RESOURCE NUMBER
MOVE S2,P4 ;GET THE VSL ADDRESS
PUSHJ P,ADDBMA ;UPDATE THE USERS 'B' MATRIX
IDN.3A: MOVX S1,VL.SCR ;GET THE SCRATCH VOLUME BIT
ANDCAM S1,.VLFLG(P2) ; AND CLEAR IT
MOVE S1,P3 ;GET THE VOL BLK WE WANT TO DELETE
PUSHJ P,DELVOL ;GO DELETE IT
MOVEM P2,.UCBVL(P1) ;LINK THE USERS VOL TO THE UCB
MOVEM P1,.VLUCB(P2) ;LINK THE UCB TO THE USERS VOL
IDEN.4: LOAD S1,.VSFLG(P4),VS.LBT ;GET THE VOLUME SET LABEL TYPE
STORE S1,.VLFLG(P2),VL.LBT ;SAVE AS THE VOLUME LABEL TYPE
;Check to make sure there is no deadlock
MOVE S1,P4 ;GET THE VSL ADDRESS IN S1
PUSHJ P,D$ALCT ;ALLOCATE/DEADLOCK CHECK THE VSL
JUMPF .RETF ;NO GOOD,,OH WELL WE TRIED !!!!!
;So far so good, go off and reassign the tape
MOVE S1,P1 ;AIM AT THIS UCB
MOVE S2,P4 ;AND THIS VSL
PUSHJ P,REASSI ;TRY TO REASSIGN THE DEVICE
JUMPF .RETT ;CAN'T,,RETURN
MOVE S1,P4 ;OK,,GET THE VSL ADDRESS BACK
PUSHJ P,MNTVSL ;TRY TO MOUNT OTHER VOLS
$RETT ;AND RETURN
>;END TOPS10
SUBTTL REASSIGN - Try to give a unit to a user
;CALL: S1/ The UCB Address
; S2/ The VSL Address
; AP/ The MDR Address
;
;RET: True - The device was reassigned with the specified logical name
; False - The device is owned, the Volume is owned,
; or he has Conflicting logical names
REASSI:
TOPS10< PUSHJ P,.SAVE4 ;SAVE SOME REGS
$SAVE <T1,T2> ;SAVE T1 AND T2 ALSO
;**;[1164] Add some code to check or reinit'ing
MOVE T1,.VSFLG(S2) ;[1164] GET VSL FLAGS
TXNE T1,VS.INI ;[1164] REINIT'ING?
$RETF ;[1164] YES,,RETURN
TXNN T1,VS.NEW ;[1164] VSL NEED REINIT'ING?
JRST REAS.A ;[1164] NO,,TRY REASSIGNMENT
PUSHJ P,REINIT ;[1164] YES,,GO SEND REINIT MSG TO PULSAR
$RETF ;[1164] RETURN
REAS.A: DMOVE P1,S1 ;[1164] GET THE UCB IN P1, VSL IN P2
MOVE S1,.UCBNM(P1) ;GET THE DEIVCE NAME IN S1
MOVEM S1,MDAOBJ+OBJ.UN ;SAVE AS THE CURRENT UNIT
LOAD P3,.VSCVL(P2),VS.OFF ;GET THE OFFSET TO THE CURRENT VOLUME
ADDI P3,.VSVOL(P2) ;POINT TO THE CURRENT VOL ADDRESS
MOVE P3,0(P3) ;GET THE VOLUME ADDRESS
MOVX T1,%STAMN ;GET 'VOLUME MOUNTED' STATUS CODE
STORE T1,.VLFLG(P3),VL.STA ;SET IT IN THE VOLUME FLAG WORD
MOVE P4,.VSUCB(P2) ;GET THE OLD UNIT ADDRESS
MOVE S1,P2 ;GET THE VSL ADDRESS IN S1
PUSHJ P,SETOWN ;UPDATE VOLUME OWNERSHIP
LOAD S2,.VSFLG(P2),VS.VSW ;IS THIS GUY IN VOLUME SWITCH MODE ???
JUMPN S2,REAS.S ;YES, THEN SWITCH UNITS
MOVX S1,VL.SRD ;GET SET REQUESTED DENSITY FOR USER BIT
TDNN S1,.VLFLG(P3) ;NEED TO DO IT?
JRST REAS.0 ;NOPE
MOVE S1,.UCBNM(P1) ;GET DEVICE NAME
LOAD S2,.VSATR(P2),VS.DEN ;GET THE REQUESTED DENSITY
PUSHJ P,I$SDEN## ;SET IT
JUMPT REAS.0 ;ONWARD
MOVEI S1,[ITEXT (<Can't set density to ^T/@DENSTY(S2)/ on unit ^W/.UCBNM(P1)/>)]
LOAD S2,.VLFLG(P3),VL.DEN ;GET THE REQUESTED DENSITY AGAIN
JRST REAS.E ;PROCESS ERROR
REAS.0: LOAD S2,.MRJOB(AP),MR.JOB ;GET THE USERS JOB NUMBER
TXNE S2,BA%JOB ;FOR A PSEUDO PROCESS ???
JRST REAS.3 ;YES,,SKIP THE REST OF THIS !!
REAS.1: LOAD S1,.UCBST(P1),UC.DVT ;GET DEVICE TYPE
CAIE S1,%DTAP ;DECTAPE?
JRST REAS.4 ;NO--MUST BE A MAGTAPE
$COUNT (DTAM) ;COUNT DECTAPE MOUNTS
JRST REAS.5 ;ONWARD
REAS.4: $COUNT (TAPM) ;COUNT TAPE MOUNTS (NOT VOL SWITCHES)
MOVE S1,.UCBNM(P1) ;[1224]GET DEVICE NAME
LOAD S2,.VSFLG(P2),VS.LBT ;[1224]GET THE REQUESTED LABEL TYPE
PUSHJ P,I$SLBT## ;[1224]SET IT
REAS.5: MOVE S1,.UCBNM(P1) ;MAKE SURE DVCMDA IS TURNED
PUSHJ P,I$MDAS## ; ON SO WE GET DEASSIGN MESSAGES
MOVE T2,.VSLNM(P2) ;GET THE LOGICAL NAME IN T2
MOVE T1,.UCBNM(P1) ;GET THE DEVICE NAME IN T1
DEVLNM T1, ;ASSIGN A LOGICAL NAME
STOPCD (LNA,HALT,,<Logical name assignment failed>)
LOAD T1,.MRJOB(AP),MD.PJB ;GET THE JOB NUMBER IN T1
MOVE T2,.UCBNM(P1) ;GET THE DEVICE NAME IN T2
REASSI T1, ;REASSIGN THE DEVICE TO THE USER
JUMPLE T1,REAS.2 ;FAILED,,RETURN NO GOOD
MOVEM T2,MDAOBJ+OBJ.UN ;SAVE THE DEVICE NAME FOR LATER
MOVEM P1,.VSUCB(P2) ;LINK THE UCB TO THIS USER
MOVEM P2,.UCBVS(P1) ;LINK THIS USER TO THIS DEVICE
MOVX S1,VS.DDN+VS.DTK ;GET DEFAULT DENSITY+TRACK STATUS BITS
ANDCAM S1,.VSATR(P2) ;CLEAR THEM - NO MORE DEFAULTING !!!!!
MOVE S1,P2 ;GET THE VSL ADDRESS
PUSHJ P,I$TMNT## ;PERFORM TAPE ACCOUNTING
MOVE S1,P2 ;AIM AT THE VOLUME SET LIST
PUSHJ P,LBLNOT ;TELL THE LABEL PROCESSOR OF THE CHANGE
$WTO (<Volume ^W/.VLNAM(P3)/ reassigned>,<^I/DEMOT/>,MDAOBJ)
$RETT ;AND RETURN
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
REAS.2: SKIPE .VSLNM(P2) ;ANY LOGICAL NAME ???
JRST [SETZM .VSLNM(P2) ;YES,,ZAP IT
JRST REAS.1 ] ;AND RETRY THE REASSIGN
;**;[1224] ADD 3 LINES AT REAS.2+1L 13-AUG-84 /DPM
MOVE S1,.UCBNM(P1) ;[1224]GET DEVICE NAME
LOAD S2,.VLFLG(P3),VL.LBT ;[1224]GET THE VOLUME LABEL TYPE
PUSHJ P,I$SLBT## ;[1224]RESET IT
MOVE S1,P2 ;NO,,GET THE VSL ADDRESS
PUSHJ P,CLROWN ;CLEAR THE OWNERSHIP STATUS
MOVX S1,%STAWT ;GET WAITING STATUS
STORE S1,.VLFLG(P3),VL.STA ;SET IT
MOVEI S1,[ITEXT (<REASSI UUO failed on volume ^W/.VLNAM(P3)/>)]
REAS.E: $WTO (<Reassignment failure>,<^I/(S1)/ for ^I/DEMOT/>,MDAOBJ)
$TEXT (<-1,,G$MSG>,<^I/(S1)/, request deleted^M^J^0>)
SETOM ERRACK ;THIS IS AN ERROR
MOVE S1,P2 ;[1173] COPY VSL ADDRESS
SETOM S2 ;[1173] USE MDR ACK DATA IF VALID
PUSHJ P,USRNOT ;TELL THE USER
MOVE S1,P2 ;NO GOOD,,GET THE VSL ADDRESS
PUSHJ P,ALCVSL ;RETURN THIS VSL TO THE ALLOCATION POOL
LOAD S1,.MRCNT(AP),MR.CNT ;GET THE USERS REQUEST COUNT
SKIPN S1 ;STILL MORE REQUESTS,,SKIP
PUSHJ P,DELMDR ;NOTHING LEFT,,DELETE THE MDR
$RETF ;AND RETURN 'REASSIGN FAILED'
REAS.3: DOSCHD ;FORCE A SCHEDULING PASS
MOVX S1,VS.NMT ;GET THE 'NOT REALLY MOUNTED' FLAG BIT
IORM S1,.VSFLG(P2) ;SET IT FOR THIS PSEUDO PROCESS
MOVE S1,.MRQEA(AP) ;GET THE QE ADDRESS
MOVX S2,QE.WAM ;GET 'WAITING FOR MOUNT' STATUS
ANDCAM S2,.QESEQ(S1) ;AND CLEAR IT
MOVEM P1,.VSUCB(P2) ;LINK THE UCB TO THIS USER
MOVEM P2,.UCBVS(P1) ;LINK THIS USER TO THIS DEVICE
MOVE S1,.QERID(S1) ;GET ITS REQUEST ID
$WTO (<Volume ^W/.VLNAM(P3)/ reassigned>,<User: ^W6/.MRNAM(AP)/^W/.MRNAM+1(AP)/ ^U/.MRUSR(AP)/ batch request #^D/S1/>,MDAOBJ)
$RETT ;RETURN
SUBTTL REAS.S - Routine to Perform Volume Switch Processing
;CALL: P1/ New UCB addr
; P2/ VSL addr
; P3/ VOL addr
; P4/ Old UCB Addr
; AP/ MDR
REAS.S: $COUNT (VSWM) ;count volume switches
STORE P1,.VSUCB(P2) ;LINK THE UCB TO THIS USER
SETZM .UCBVS(P4) ;AND THE OLD UNIT ISN'T TIED UP...
STORE P2,.UCBVS(P1) ;LINK THIS USER TO THIS DEVICE
ZERO .UCBST(P4),UC.VSW ;...WAITING FOR VOLUME SWITCH
ZERO .VSFLG(P2),VS.VSW ;...AND VSL ISN'T SWITCHING, EITHER
MOVX S1,.QOVSD ;VOLUME SWITCH DIRECTIVE BLOCK
PUSHJ P,LBLHDR ;START THE MESSAGE
;Build the First Block, Describing the Units Involved
AOS G$MSG+.OARGC ;ONE MORE BLOCK
MOVEI S2,G$MSG+.OHDRS ;AIM AT THE FIRST BLOCK SPACE
MOVX S1,.VSDBL ;BLOCK TYPE - DEVICES
STORE S1,ARG.HD(S2),AR.TYP ;SET IN BLOCK
MOVX S1,ARG.DA+VSDLEN ;SIZE OF THE BLOCK
STORE S1,ARG.HD(S2),AR.LEN ;LENGTH OF THIS ONE
ADDI S2,ARG.DA ;POINT AT THE DATA
ADDM S1,G$SAB##+SAB.LN ;AND SEND LENGTH, TOO
MOVSS S1 ;TO LH
ADDM S1,G$MSG+.MSTYP ;UPDATE MESSAGE LENGTH
LOAD S1,.UCBNM(P4) ;GET OLD UNIT NAME
STORE S1,.VSDID(S2) ;SAVE IN MESSAGE
LOAD S1,.UCBNM(P1) ;GET NEW UNIT NAME
STORE S1,.VSDCD(S2) ;SAVE AS NEW UNIT NAME
ADDI S2,VSDLEN ;UPDATE POINTER PAST BLOCK
;Build the Second Block, Describing the Volume Set and User who Owns The Drive
AOS G$MSG+.OARGC ;ONE MORE BLOCK
MOVX S1,.VOLMN ;GET THE NEXT BLOCK TYPE
STORE S1,ARG.HD(S2),AR.TYP ;SAVE AS BLOCK TYPE
MOVX S1,.VMNSZ+ARG.DA ;GET THE LENGTH OF THE BLOCK
STORE S1,ARG.HD(S2),AR.LEN ;AND SAVE IN BLOCK HEADER
ADDM S1,G$SAB+SAB.LN ;UPDATE SEND LENGTH
MOVSS S1 ;GET TO LH
ADDM S1,G$MSG+.MSTYP ;UPDATE TOTAL MESSAGE LENGTH
MOVEI S2,ARG.DA(S2) ;AIM AT THE DATA PORTION OF THE BLOCK
LOAD S1,.VLNAM(P3) ;GET THE VOLUME NAME
STORE S1,.VMNIV(S2) ;SAVE AS INITIAL VOLUME NAME
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
MOVEI S1,.VSVOL(P2) ;AIM AT THE FIRST VOLUME BLOCK ADR
MOVE S1,(S1) ;GET THE ADR OF THE FIRST VOL BLOCK
LOAD S1,.VLNAM(S1) ;GET THE NAME OF THE FIRST VOLUME
STORE S1,.VMNFV(S2) ;SAVE IN MESSAGE TO LABELLER
LOAD S1,.VSFLG(P2),VS.LBT ;GET THE LABEL TYPE
STORE S1,.VMNIN(S2),VI.LTY ;SAVE IN MESSAGE
LOAD S1,.VSFLG(P2),VS.WLK ;GET THE WRITE LOCK BIT
STORE S1,.VMNIN(S2),VI.WLK ;SAVE IN INFO WORD OF MESSAGE
LOAD S1,.MRJOB(AP),MD.PJB ;GET THE JOB NUMBER
STORE S1,.VMNIN(S2),VI.JOB ;TEL THE LABELLER WHO'S THERE
;**;[1136]ADD 7 LINES AND CHANGE 1 LINE AT REAS.S:+65L 11-NOV-82/NT
;Here to make sure the density is set correctly
LOAD S1,.VLFLG(P3),VL.DEN ;[1136]GET THE DENSITY FOR THIS VOLUME
LOAD S2,.VSATR(P2),VS.DEN ;[1136]GET DENSITY CODE FOR VOL SET
CAMN S1,S2 ;[1136]ARE THEY THE SAME ??
JRST REA.S0 ;[1136]YES, NO NEED TO SET IT THEN
STORE S2,.VLFLG(P3),VL.DEN ;[1136]STORE IT AWAY FOR NEXT TIME
LOAD S1,.UCBNM(P1) ;[1136]GET THE NAME OF THE DRIVE
PUSHJ P,I$SDEN## ;[1136]SET IT
;Tell everyone about it
REA.S0: PUSHJ P,C$SEND## ;[1136]TELL THE LABELLER
MOVE S1,P2 ;GET THE VSL ADDRESS
PUSHJ P,I$TMNT## ;PERFORM TAPE ACCOUNTING
$WTO (<Volume ^W/.VLNAM(P3)/ reassigned>,<^I/DEMOT/>,MDAOBJ)
$TEXT (<-1,,G$MSG>,<Logical name ^W/.VSLNM(P2)/ switched to volume ^W/.VLNAM(P3)/ on ^W/.UCBNM(P1)/^M^J^0>)
MOVE S1,P2 ;NOTIFY [SYSTEM]CATALOG OF THE
PUSHJ P,V$EXTV## ; VOLUME-SET EXTENSION
MOVE S1,P2 ;[1173] GET VSL ADDRESS
SETZM S2 ;[1173] USE VSL ACK DATA
PUSHJ P,USRNOT ;TELL THE USER, IF INTERESTED
MOVE S1,P4 ;GET TO THE OLD UNIT
PUSHJ P,MATUNI ;TRY TO GIVE IT AWAY
$RETF ;RETURN FALSE IN ANY CASE
>
TOPS20< $RETT > ;REASSIGN FAILS ON THE -20
SUBTTL D$ASGN - ROUTINE TO ASSIGN FOREIGN DEVICES UNDER MDA
;CALL: M/ The IDENTIFY Message Address
;
;RET: True Always
TOPS10<
D$ASGN: PUSHJ P,.SAVE3 ;SAVE P1 AND P2 AND P3
MOVX S1,.CMDEV ;GET THE DEVICE BLOCK TYPE
PUSHJ P,A$FNDB## ;FIND THE DEVICE BLOCK
HRROI S1,0(S1) ;POINT TO THE ASCIZ DEVICE NAME
PUSHJ P,S%SIXB ;CONVERT IT TO SIXBIT
DEVNAM S2, ;IS IT VALID ???
JRST [MOVEI S1,[ASCIZ/Unknown device specified/] ;NO,,GET ERROR TEXT
JRST ASGN.3 ] ;AND EXIT
MOVEM S2,MDAOBJ+OBJ.UN ;SAVE THE DEVICE NAME
MOVE S1,S2 ;S1:= DEVICE NAME
PUSHJ P,I$CKAV## ;IS IT FREE ?
JUMPT [MOVEI S1,[ASCIZ/Device not available/] ;NO
JRST ASGN.3 ] ;EXIT
MOVE S2,MDAOBJ+OBJ.UN ;GET THE DEVICE
DEVTYP S2, ;GET ITS CHARACTERISTICS
JRST [MOVEI S1,[ASCIZ/Unknown device specified/] ;CAN'T
JRST ASGN.3 ] ;EXIT
LOAD P1,S2,TY.DEV ;SAVE THE DEVICE TYPE
MOVX S1,.ORREQ ;GET THE REQUEST ID BLOCK TYPE
PUSHJ P,A$FNDB## ;GET THE REQUEST TO ASSIGN TO
JUMPF [MOVEI S1,[ASCIZ/Request ID must be specified/] ;NOT THERE
JRST ASGN.3 ] ;GET ERROR TEXT AND EXIT
MOVE S1,0(S1) ;GET THE REQUEST ID
PUSHJ P,FNDVSL ;FIND THE USER
JUMPF [MOVEI S1,[ASCIZ/Invalid request ID specified/] ;NOT THERE
JRST ASGN.3 ] ;GET ERROR TEXT AND EXIT
MOVE P2,S1 ;SAVE THE VSL ADDRESS
LOAD S1,.VSFLG(P2),VS.TYP ;GET THE REQUEST TYPE
CAXE S1,%UNKN ;S IS 'UNKNOWN' ?
JRST [MOVEI S1,[ASCIZ/User requested disk, magtape, or DECtape volumes/]
JRST ASGN.3 ] ;GET ERROR TEXT AND EXIT
HRROI S1,.VSVSN(P2) ;GEN POINTER TO VOL SET NAME
PUSHJ P,S%SIXB ;CONVERT IT TO SIXBIT
DEVTYP S2, ;GET THE REQUESTED DEVICE TYPE
SKIPA S2,P1 ;ON ERROR FORCE A MATCH !!!
LOAD S2,S2,TY.DEV ;GET THE DEVICE TYPE
CAME S2,P1 ;DOES REQUESTED MATCH IDENTIFIED ???
JRST [MOVEI S1,[ASCIZ/Specified device does not match requested device/]
JRST ASGN.3 ] ;NO,,GET ERROR TEXT AND EXIT
MOVE S1,MDAOBJ+OBJ.UN ;GET THE DEVICE NAME
PUSHJ P,I$MDAS## ;SET THE MDA BIT (DVCMDA)
ASGN.1: MOVE S1,MDAOBJ+OBJ.UN ;GET THE DEVICE NAME
MOVE S2,.VSLNM(P2) ;GET THE LOGICAL NAME
DEVLNM S1, ;ASSIGN A LOGICAL NAME TO THE DEVICE
JFCL ;IGNORE THE ERROR
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
LOAD S1,.MRJOB(AP),MD.PJB ;GET THE USERS JOB NUMBER
MOVE S2,MDAOBJ+OBJ.UN ;GET THE DEVICE NAME
REASSI S1, ;ASSIGN IT TO THE USER
JUMPLE S1,ASGN.2 ;IF IT FAILED,,PROCESS THE ERROR
$COUNT (GENM) ;count generic mounts
$ACK (<Reassigned>,<^I/DEMOT/>,MDAOBJ,.MSCOD(M)) ;TELL THE OPR
MOVE S1,P2 ;GET THE VSL ADDRESS
PUSHJ P,SETOWN ;SET SOME OWNERSHIP BITS
MOVE S1,UCBQUE ;GET THE UCB QUEUE ID
PUSHJ P,L%LAST ;POSITION TO THE LAST ENTRY
MOVX S2,UCBLEN ;GET THE UCB LENGTH
PUSHJ P,L%CENT ;CREATE A UCB FOR THIS DEVICE
MOVEM S2,.VSUCB(P2) ;LINK THE UCB TO THE VSL
MOVEM P2,.UCBVS(S2) ;LINK THE VSL TO THE UCB
MOVE S1,MDAOBJ+OBJ.UN ;GET THE DEVICE NAME
MOVEM S1,.UCBNM(S2) ;SAVE IT
PUSHJ P,ASGN.A ;ACK THE USER AND GET NEXT VSL
MOVE P1,S1 ;SAVE THE NEXT MOUNT VSL ADDRESS
MOVE S1,P2 ;GET THE VSL ADDRESS IN S1
LOAD TF,.VSFLG(P2),VS.TYP ;GET THE REQUEST TYPE
CAXN TF,%DTAP ;A DECTAPE ?
PUSHJ P,I$DMNT## ;YES - MAKE ACCOUNTING ENTRY
MOVX S2,VS.WAL ;GET THE WAITING FOR ALLOCATION STATUS
IORM S2,.VSFLG(P2) ;LITE IT (WE NEVER WERE ALLOCATED)
SKIPE S1,P1 ;ANY MORE REQUESTS ???
PUSHJ P,MNTVSL ;YES,,TRY TO MOUNT THEM
$RETT ;RETURN
;Here if the reassignment fails
ASGN.2: SKIPE .VSLNM(P2) ;ANY LOGICAL NAME ???
JRST [SETZM .VSLNM(P2) ;YES,,ZAP IT
JRST ASGN.1 ] ;AND RETRY THE REASSIGNMENT
$ACK (<Reassignment failure>,<Can't reassign device to ^I/DEMOT/>,MDAOBJ,.MSCOD(M))
MOVEI S1,[ITEXT (<Reassignment failed - request deleted>)]
SETOM ERRACK ;LITE ERROR ACK FLAG
PUSHJ P,ASGN.A ;ACK THE USER AND GET NEXT VSL
MOVE P1,S1 ;SAVE THE NEXT VSL ADDRESS
MOVE S1,P2 ;GET THE VSL ADDRESS IN S1
PUSHJ P,DELVSL ;DELETE THIS REQUEST
LOAD S1,.MRCNT(AP),MR.CNT ;GET HIS REQUEST COUNT
JUMPE S1,DELMDR ;IF NO MORE REQUESTS,,DELETE THE MDR
SKIPE S1,P1 ;ANY MORE REQUESTS ???
PUSHJ P,MNTVSL ;YES,,TRY TO MOUNT THEM
$RETT ;RETURN
ASGN.3: $ACK (<Can't identyfy this device>,<^T/0(S1)/>,MDAOBJ,.MSCOD(M))
$RETT ;RETURN
;Here to ACK the user and find the next mount request
ASGN.A: LOAD P1,.MRCNT(AP),MR.CNT ;GET THE USERS REQUEST COUNT
MOVNS P1 ;NEGATE IT
MOVSS P1 ;MOVE RIGHT TO LEFT
HRRI P1,.MRVSL(AP) ;CREATE VSL AOBJN SEARCH AC
LOAD S2,.VSLNK(P2),VS.LNK ;GET THIS REQUESTS LINK CODE
ASGN.B: MOVE P3,0(P1) ;GET A VSL ADDRESS
LOAD S1,.VSLNK(P3),VS.LNK ;GET ITS LINK CODE
CAME P3,P2 ;IS THIS THE CURRENT VSL ???
CAME S1,S2 ;NO,,DO LINK CODES MATCH ???
AOBJN P1,ASGN.B ;CURRENT VSL OR NO MATCH,,TRY NEXT
MOVE S1,P2 ;GET THE VSL ADDRESS
PUSHJ P,ACKUSR ;ACK THE USER
SKIPL P1 ;DID WE FIND A MATCH ???
SETZM P3 ;NO,,CLEAR THE LAST VSL ADDRESS
MOVE S1,P3 ;RETURN NEXT VSL ADDRESS
$RETT ;RETURN
> ;END TOPS10 CONDITIONAL
SUBTTL D$ENAB/D$DISA - DRIVE AVR STATUS
;CALL: M/ The Enable/Disable Message Address
;
;The following cases for enable/disable can occur:
; .TAPDV A particular tape/disk drive - change AVR
; .ALTAP All tape drives - change AVR
; .ALDSK All disk drives - change AVR
; .ALSTR Change automatic structure recognition
; (defaults if all others fail)
;
;RET: True Always
TOPS10 <
D$ENAB::TDZA S1,S1 ;INDICATE 'ENABLE' ENTRY POINT
D$DISA::SETOM S1 ;INDICATE 'DISABLE' ENTRY POINT
PUSHJ P,.SAVE2 ;SAVE P1 AND P2 FOR A MINUTE
MOVE P1,S1 ;SAVE THE ENTRY POINT INDICATOR IN P1
MOVX S1,.TAPDV ;GET DRIVE BLOCK TYPE
PUSHJ P,A$FNDB## ;FIND IT IN OUR MESSAGE
JUMPT ABLE.0 ;Found specific unit, go process it
MOVX S1,.ALTAP ;GET ALL TAPE DRIVE MSG BLOCK
PUSHJ P,A$FNDB## ;FIND IT IN THE MESSAGE
JUMPT ABLE.1 ;FOUND IT,,GO SET ALL TAPE DRIVES
MOVX S1,.ALDSK ;Get all disk drive msg block
PUSHJ P,A$FNDB## ;Find it in the message
JUMPT ABLE.2 ;Go process it
;Fall through assuming .ALSTR
;Here to Enable/Disable Automatic Structure Recognition
SKIPN P1 ;IS THIS AN ENABLE FUNCTION ???
SETOM D$ASR ;YES,,LITE THE ASR FLAG
SKIPE P1 ;IS THIS A DISABLE FUNCTION ???
SETZM D$ASR ;YES,,CLEAR THE ASR FLAG
$ACK (<Structure recognition is ^T/@DISENA+1(P1)/>,,,.MSCOD(M))
$RETT ;RETURN
;Here to Enable/Disable Automatic Volume Recognition for a unit
ABLE.0: PUSHJ P,LOCUCB ;GO FIND THE AFFECTED UCB
JUMPF .RETF ;NOT THERE,,DEVICE DOES NOT EXIST !!!
MOVX S2,UC.AVR ;GET THE AVR BIT IN S1
SKIPN P1 ;IS THIS 'ENABLE' ???
IORM S2,.UCBST(S1) ;YES,,LITE THE AVR BIT
SKIPE P1 ;OR IS THIS 'DISABLE' ???
ANDCAM S2,.UCBST(S1) ;YES,,CLEAR THE AVR BIT
$ACK (<Volume recognition is ^T/@DISENA+1(P1)/>,,MDAOBJ,.MSCOD(M))
$RETT ;ACK THE OPERATOR AND RETURN
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
;Here to Enable/Disable Automatic Volume Recognition for all units
ABLE.1: TDZA P2,P2 ;Indicate all tapes
ABLE.2: SETOM P2 ;Indicate all disks
MOVE S1,UCBQUE ;GET THE UCB QUEUE ID
PUSHJ P,L%FIRST ;GET THE FIRST ENTRY
ABLE.3: LOAD S1,.UCBST(S2),UC.DVT ;Get the device type
CAIN S1,%TAPE ;Is it a tape?
JUMPE P2,ABLE.4 ;Yes, do we want tapes?
CAIN S1,%DISK ;No, is it a disk?
JUMPL P2,ABLE.4 ;Yes, do we want disks?
JRST ABLE.5 ;No, don't like this one
ABLE.4: MOVX S1,UC.AVR ;GET THE AVR BIT IN S1
SKIPN P1 ;IS THIS 'ENABLE' ???
IORM S1,.UCBST(S2) ;YES,,LITE THE AVR BIT
SKIPE P1 ;OR IS THIS 'DISABLE' ???
ANDCAM S1,.UCBST(S2) ;YES,,CLEAR THE AVR BIT
ABLE.5: MOVE S1,UCBQUE ;GET THE UCB QUEUE ID
PUSHJ P,L%NEXT ;GET THE NEXT UCB ENTRY
JUMPT ABLE.3 ;FOUND ONE,,GO PROCESS IT
MOVEI S1,[ASCIZ/tape drives/] ;DEFAULT TO TAPE DRIVES
SKIPE P2 ;UNLESS IT WAS DISK DRIVES
MOVEI S1,[ASCIZ/disk drives/] ; THEN MAKE IT DISKS
$ACK (<Volume recognition is ^T/@DISENA+1(P1)/ for all ^T/0(S1)/>,,,.MSCOD(M))
$RETT ;ACK THE OPERATOR AND RETURN
DISENA: [ASCIZ/Disabled/]
[ASCIZ/Enabled/]
>
SUBTTL D$RECO - PROCESS THE OPR RECOGNIZE COMMAND
;CALL: M/ The Recognize Message Address
;
;RET: True Always
TOPS10 <
D$RECO::PUSHJ P,.SAVE2 ;[1204] SAVE P1 & P2 FOR A MINUTE
MOVX S1,.TAPDV ;GET THE TAPE DEVICE NAME BLOCK TYPE
PUSHJ P,A$FNDB## ;FIND IT IN THE MESSAGE
JUMPF E$IMO## ;NOT THERE,,THATS AN ERROR
PUSHJ P,FNDUCB ;FIND THE AFFECTED UCB
JUMPF .RETF ;NOT THERE,,THATS AN ERROR
SKIPN P1,.UCBVL(S1) ;[1204] GET VOL BLOCK ADDRES
JRST RECO.1 ;[1204] NONE THERE
LOAD P2,.VLFLG(P1),VL.STA ;[1204] GET THE STATUS
CAXE P2,%STADM ;[1204] WAITING TO DISMOUNT?
JRST RECO.1 ;[1204] NO,,LET PULSAR SNIFF ON IT
$ACK (<Structure ^W/.VLNAM(P1)/ is dismounting from ^W/S2/>,,,.MSCOD(M),<$WTFLG(WT.SJI)>) ;[1204]
$RETT ;[1204] RETURN
RECO.1: MOVE S1,S2 ;[1204] GET THE DEVICE CHECKED AGAINST
PJRST SNDREC ; AND SEND THE RECOGNIZE MESSAGE TO
; THE TAPE LABELER
>
SUBTTL D$AVR - TAPE/DISK ONLINE PROCESSOR
;CALL: M/ The TAPE/DISK Online Message Address
;
;RET: True Always
;This routine fields Tape/Disk Online IPCF Messages from the
;monitor and possibly kicks the Tape Label Processor to read the
;labels from the volume mounted on the unit and send the Info
;back to QUASAR
TOPS10 <
D$AVR:: LOAD S1,.TONST(M),TON.TY ;GET DEVICE TYPE FROM MESSAGE
CAXE S1,.TYDSK ;IS IT A DISK ONLINE MESSAGE ???
CAXN S1,.TYMTA ;OR IS IT A MAGTAPE?
SKIPA ;YES,,GO PROCESS IT
$RETT ;ELSE IGNORE IT
PUSHJ P,.SAVE1 ;SAVE P1 FOR A MINUTE
MOVE S1,.TONDV(M) ;GET DEVICE NAME
PUSHJ P,UCBLOC ;FIND OUR UCB BLOCK ON THIS GUY
JUMPF .RETT ;STRANGE, MONITOR IS FUNNY
LOAD S2,.UCBST(S1),UC.AVA ;IS IT AVAILABLE ???
JUMPE S2,.RETT ;NO,,RETURN NOW
MOVE S2,S1 ;SAVE UCB ADR
MOVX S1,UC.AVR ;GET AVR ENABLED BIT
TDNE S1,.UCBST(S2) ;IS THIS DRIVE ENABLED?
SKIPA ;AVR OR DRIVE OWNED,,LETERRIP
JRST AVR.2 ;NO,,GO FINISH UP
LOAD S1,.UCBST(S2),UC.DVT ;GET THE UNIT TYPE
CAXN S1,%DISK ;IS IT A DISK UNIT ???
JRST AVR.1 ;YES,,JUST READ THE LABELS
SKIPN P1,.UCBVL(S2) ;GET ATTACHED VOLUME BLOCK, IF ANY
JRST AVR.1 ;NO VOLUME, GO READ THE LABELS
MOVE S1,P1 ;GET THE VOLUME ADDRESS IN S1
PUSHJ P,FNDOWN ;ANY OWNERS OF THE VOLUME ???
JUMPF AVR.1 ;NO,,READ THE LABELS (AGAIN)
LOAD S1,.VLFLG(P1),VL.LBT ;IT IS OWNED, GET LABEL TYPE
CAXN S1,.TFLBP ;IS IT A BYPASS LABEL TAPE?
$RETT ;YES, LEAVE IT ALL UP TO THE USER
AVR.1: MOVE S1,.TONDV(M) ;GET DEVICE NAME SUPPLIED IN MESSAGE
PJRST SNDREC ;AND ASK PULSAR FOR SERVICE
AVR.2: LOAD S1,.TONST(M),TON.TY ;GET DEVICE TYPE FROM MESSAGE
CAXE S1,.TYDSK ;IS IT A DISK ONLINE MESSAGE ???
$RETT ;NO,,RETURN
LOAD S1,.TONDV(M) ;GET DEVICE NAME
MOVE S2,[.DUCLM,,S1] ;GET DISK. PARM LIST
DISK. S2, ;CLEAR DEVICE UNISTS WORD
JFCL ;IGNORE THE ERROR
$RETT ;RETURN
>
SUBTTL D$DEVS - PROCESS TAPE/DISK STATUS MESSAGES
;CALL: M/ The Status Message Address
;
;RET: True Always
TOPS10 <
D$DEVS::MOVX S1,.STSTS ;GET THE STATUS BLOCK TYPE
PUSHJ P,A$FNDB## ;FIND IT IN THE MESSAGE
JUMPF MISC.3 ;NOT THERE,,THATS AN ERROR
MOVE T1,S1 ;SAVE THE STATUS BLOCK ADDRESS
MOVE S1,.STUNT(T1) ;GET THE UNIT NAME
PUSHJ P,UCBFND ;FIND IT IN OUR DATA BASE
JUMPF MISC.3 ;NOT THERE,,THATS AN ERROR
MOVE T2,S1 ;SAVE THE UCB ADDRESS
MOVSI S1,.DUCLM ;'CLEAR MDA WAIT' FUNCTION
HRRI S1,.UCBNM(T2) ;MUST POINT TO PRIMARY PORT NAME
DISK. S1, ; EVEN IF .STUNT HAS ALTERNATE PORT
JFCL ;IGNORE ERRORS
LOAD S1,.STFLG(T1),ST.OFL ;GET THE UNIT OFFLINE BIT
STORE S1,.UCBST(T2),UC.OFL ;AND SAVE IT
JUMPN S1,DEVS.1 ;IF OFFLINE,,GO PROCESS IT
MOVX S1,UC.INI ;GET THE 'DRIVE INITIALIZING' BIT
TDNE S1,.UCBST(T2) ;IS THIS DRIVE WRITING LABELS?
$RETT ;YES, IGNORE THE STATUS MESSAGE
MOVX S1,.TLSTA ;GET THE TAPE DEVICE STATUS BLOCK TYPE
PUSHJ P,A$FNDB## ;FIND IT IN THE MESSAGE
JUMPT [MOVE T3,S1 ;GET THE TAPE STATUS BLK ADDRESS IN T3
PJRST TAPDEV ] ;AND GO PROCESS IT
MOVX S1,.DLSTA ;GET THE DECTAPE DEVICE STATUS BLOCK
PUSHJ P,A$FNDB## ;FIND IT IN THE MESSAGE
JUMPT [MOVE T3,S1 ;GET THE DECTAPE STATUS BLK ADDR IN T3
PJRST DTADEV ] ;AND GO PROCESS IT
MOVX S1,.DSSTA ;GET STRUCTURE DEVICE STATUS BLOCK TYPE
PUSHJ P,A$FNDB## ;FIND IT IN THE MESSAGE
JUMPT [MOVE T3,S1 ;GET THE DISK STATUS BLK ADDRESS IN T3
PJRST DSKDEV ] ;AND GO PROCESS IT
PJRST MISC.3 ;NOT THERE,,INVALID STATUS MESSAGE
;Here if unit is offline
DEVS.1: $WTO (<Offline>,,MDAOBJ) ;TELL OPR
LOAD S1,.UCBST(T2),UC.DVT ;GET THE UNIT DEVICE TYPE
CAXN S1,%DISK ;IS IT A STRUCTURE ???
SKIPN S1,.UCBVL(T2) ;YES,,IS THERE A VOLUME MOUNTED ???
$RETT ;NO TO EITHER,,JUST RETURN
PUSHJ P,DELVOL ;YES,,DELETE THE VOLUME
$RETT ;AND RETURN
>
SUBTTL TAPDEV - TAPE STATUS MESSAGE PROCESSOR
;CALL: T1/ The .STSTS block address
; T2/ The UCB address
; T3/ The .TLSTA block address
;
;RET: Usually True
TOPS10 <
TAPDEV::PUSHJ P,.SAVE4 ;SAVE P1-P4
MOVE P1,T3 ;SAVE THE MESSAGE DATA ADDRESS
TAPD.1: MOVE P2,T2 ;SAVE THE UCB ADDRESS IN P2
SKIPN P3,.UCBVL(P2) ;CHECK AND LOAD THE VOL ADDRESS
JRST TAPD.2 ;NO VOLUME YET !!!
MOVE S1,P3 ;GET THE VOLUME ADDRESS IN S1
PUSHJ P,FNDOWN ;ANY OWNERS OF THE VOLUME ???
JUMPT [TXO P3,<1B0> ;YES,,INDICATE PREVIOUS VOL WAS OWNED
JRST TAPD.2 ] ; AND THEN GO CHECK LABEL TYPES
;NO -
SETZM .VLUCB(P3) ;DELINK THE VOLUME FROM THE UCB
SETZM .UCBVL(P2) ;DELINK THE UCB FROM THE VOLUME
MOVX S1,%STAWT ;GET VOLUME WAITING STATUS
STORE S1,.VLFLG(P3),VL.STA ; AND SET IT
MOVE S1,P3 ;AIM AT THE VOL BLK
PUSHJ P,DELVOL ;DELETE IT
SETZM P3 ;INDICATE NO VOLUME FOUND !!!
TAPD.2: LOAD S1,.STFLG(T1),TS.LAB ;GET THE MOUNTED VOL LABEL TYPE
PUSHJ P,GETLBT ;RECODE IT TO SOMETHING USEFULL
JUMPGE P3,[CAXE S1,%LABEL ;PREVIOUS VOL NOT OWNED AND CURRENT
JRST TAPD.8 ; VOL UNLABELED,,GEN A NEW VOL BLK
JRST TAPD.4 ] ; VOL LABELED,,FIND IN VOL DATA BASE
MOVE P4,S1 ;SAVE THE MOUNTED VOL LABEL TYPE
LOAD S1,.VLFLG(P3),VL.LBT ;GET THE PREVIOUS VOL LABEL TYPE
PUSHJ P,GETLBT ;RECODE IT TO SOMETHING USEFULL
CAMN S1,P4 ;PREVIOUS VOL OWNED,,CHECK LABEL TYPES
JRST [CAXE S1,%LABEL ;LABELS MATCH,,IS IT A LABELED VOL ???
JRST TAPD.A ;PREV VOL OWNED AND UNLABELED,,UPDATE
JRST TAPD.3 ] ;PREV VOL OWNED AND LABELED,,CHK VOL Q
LOAD S1,.VLFLG(P3),VL.LBT ;GET THE PREV VOL LABEL TYPE
$WTO (<Unloading>,<User requested ^T/@0(S1)/ labels>,MDAOBJ)
MOVE S1,.UCBNM(P2) ;GET THE UNIT NAME
PUSHJ P,UNLOAD ;UNLOAD THE UNIT
$RETT ;AND RETURN
;CONTINUED ON THE NEXT PAGE
;Here for a Labeled Volume Mount
TAPD.3: MOVE S1,.VLNAM(P3) ;GET THE VOLUME ID
CAMN S1,.TLVOL(P1) ;DO THEY MATCH ???
JRST TAPD.9 ;YES,,JUST UPDATE THE STATUS
$WTO (<Mount labeled volume ^W/S1/ on this drive>,,MDAOBJ)
MOVE S1,.UCBNM(P2) ;GET THE DEVICE THE VOL IS MOUNTED ON
PUSHJ P,UNLOAD ;UNLOAD THE DEVICE
$RETT ;AND RETURN
TAPD.4: SKIPN S1,.TLVOL(P1) ;GET THE VOLUME NAME
JRST TAPD.5 ;NULL,,THATS AN ERROR !!!
PUSHJ P,FNTAPE ;FIND IT IN OUR DATA BASE
JUMPF TAPD.8 ;NOT THERE,,CREATE A NEW VOL BLOCK
MOVE P3,S1 ;SAVE THE VOL BLOCK ADDRESS
JUMPE S2,TAPD.9 ;NOT MOUNTED,,LINK THIS VOL TO THE UCB
SKIPA ;SKIP OVER WTO
TAPD.5: $WTO (<No volume-ID found in this tapes labels>,,MDAOBJ) ;TELL OPR
MOVE S1,.UCBNM(P2) ;GET THE DEVICE THE VOL IS MOUNTED ON
PUSHJ P,UNLOAD ;UNLOAD THE DEVICE
$RETT ;RETURN
;We could not find the mounted volume in our volume list,
;so we will have to create an entry for it.
TAPD.8: PUSHJ P,CREVOL ;CREATE A VOL QUEUE ENTRY
MOVE P3,S1 ;SAVE THE ENTRY ADDRESS
MOVE S1,.TLVOL(P1) ;PICK UP THE VOLUME NAME
MOVEM S1,.VLNAM(P3) ;SAVE IT IN THE VOL ENTRY
SKIPN S1 ;IS THIS REALLY A VOL BLK?
JRST TAPD.9 ;NO NAME... NO RESOURCE NUMBER
MOVE S1,P1 ;AIM AT THIS NEW VOL BLK
PUSHJ P,D$TVRS ;GO GENERATE A RESOURCE NUMBER
;Having set everything up, link the VOL and UCB together
;and go finish updating the volume status
TAPD.9: HRRZM P3,.UCBVL(P2) ;LINK THE VOLUME TO THE UCB
MOVEM P2,.VLUCB(P3) ;LINK THE UCB TO THE VOLUME
;Update the volume status and tell the operator whats going on.
TAPD.A: LOAD S1,.STFLG(T1),ST.LOK ;GET THE WRITE LOCK STATUS
STORE S1,.UCBST(P2),UC.WLK ;SAVE THE WRITE LOCK STATUS
LOAD S1,.STFLG(T1),TS.DEN ;GET THE TAPE DENSITY
CAXLE S1,DENLEN ;VALIDATE THE RETURNED CODE
PUSHJ P,S..ITD ;DEEP TROUBLE !!!
MOVE S2,D$DEN(S1) ;CONVERT THE CODE TO A BIT MAP
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
CAXE S1,.TFD00 ;IS IT SYSTEM DEFAULT (UNREADABLE TAPE)
TDNE S2,.UCBST(P2) ;MUST BE A SUPPORTED DENSITY !!!
SKIPA ;DEFAULT, OR SUPPORTED DENSITY, GO ON
STOPCD (ITD,HALT,,<Invalid tape density specified (in .UCBNM(P2))>)
STORE S1,.VLFLG(P3),VL.DEN ;OK,,SAVE THE VOLUME DENSITY
MOVE P4,S1 ;SAVE HERE ALSO FOR WTO
LOAD S1,.STFLG(T1),TS.LAB ;GET THE VOLUME LABEL TYPE
STORE S1,.VLFLG(P3),VL.LBT ;SAVE IT
MOVE P1,S1 ;HERE ALSO
;If Unlabeled,,Just Tell OPR Whats Going On
PUSHJ P,GETLBT ;RECODE THE LABEL TYPE
CAXE S1,%LABEL ;IS IT LABELED ???
JRST TAPD.B ;NO,,FINISH UP
;If Labeled,See is we can Give the Volume Away
MOVE S1,P2 ;GET UCB ADR
PUSHJ P,MATUNI ;TRY TO MATCH THIS UNIT WITH A REQUEST
JUMPT .RETT ;DONE, DON'T BOTHER THE OPERATOR
LOAD S1,.UCBST(P2),UC.WLK ;GET THE WRITE LOCKED BIT
$WTO (<Volume ^W/.VLNAM(P3)/ mounted>,<^T/@LABELS(P1)/ labels, ^T/@DENSTY(P4)/ BPI, write-^T/@WRTENA(S1)/>,MDAOBJ)
$RETT ;AND RETURN
TAPD.B: LOAD S1,.UCBST(P2),UC.WLK ;GET THE WRITE LOCKED BIT
$WTO (<Unlabeled volume mounted>,<Density ^T/@DENSTY(P4)/ BPI, write-^T/@WRTENA(S1)/>,MDAOBJ)
$RETT ;TELL OPR AND RETURN
>
SUBTTL DTADEV - DECTAPE STATUS MESSAGE PROCESSOR
;CALL: T1/ The .STSTS block address
; T2/ The UCB address
; T3/ The .DLSTA block address
;
;RET: Usually True
TOPS10 <
DTADEV: PUSHJ P,.SAVE4 ;SAVE P1-P4
MOVE P1,T3 ;SAVE THE MESSAGE DATA ADDRESS
MOVE P2,T2 ;SAVE THE UCB ADDRESS IN P2
SKIPN P3,.UCBVL(P2) ;CHECK AND LOAD THE VOL ADDRESS
JRST DTAD.2 ;NO VOLUME YET !!!
MOVE S1,P3 ;GET THE VOLUME ADDRESS IN S1
PUSHJ P,FNDOWN ;ANY OWNERS OF THE VOLUME ???
JUMPT [TXO P3,<1B0> ;YES,,INDICATE PREVIOUS VOL WAS OWNED
JRST DTAD.1 ] ; AND CONTINUE ON
SETZM .VLUCB(P3) ;DELINK THE VOLUME FROM THE UCB
SETZM .UCBVL(P2) ;DELINK THE UCB FROM THE VOLUME
MOVX S1,%STAWT ;GET VOLUME WAITING STATUS
STORE S1,.VLFLG(P3),VL.STA ; AND SET IT
MOVE S1,P3 ;AIM AT THE VOL BLK
PUSHJ P,DELVOL ;DELETE IT
SETZM P3 ;INDICATE NO VOLUME FOUND !!!
JRST DTAD.2 ;ONWARD
DTAD.1: MOVE S1,.VLNAM(P3) ;GET THE VOLUME ID
CAMN S1,.DLRID(P1) ;DO THEY MATCH ???
JRST DTAD.4 ;YES,,JUST UPDATE THE STATUS
$WTO (<Mount DECtape volume ^W/S1/ on this drive>,,MDAOBJ)
MOVE S1,.UCBNM(P2) ;GET THE DEVICE THE VOL IS MOUNTED ON
PUSHJ P,UNLOAD ;UNLOAD THE DEVICE
$RETT ;AND RETURN
DTAD.2: SKIPN S1,.DLRID(P1) ;GET THE REELID
JRST DTAD.3 ;THERE ISN'T ONE
PUSHJ P,FNDECT ;FIND IT IN OUR DATA BASE
JUMPF DTAD.3 ;NOT THERE,,CREATE A NEW VOL BLOCK
MOVE P3,S1 ;SAVE THE VOL BLOCK ADDRESS
JUMPE S2,DTAD.4 ;NOT MOUNTED,,LINK THIS VOL TO THE UCB
MOVE S1,.UCBNM(P2) ;GET THE DEVICE THE VOL IS MOUNTED ON
PUSHJ P,UNLOAD ;UNLOAD THE DEVICE
$RETT ;RETURN
;We could not find the mounted volume in our volume list,
;so we will have to create an entry for it.
DTAD.3: PUSHJ P,CREVOL ;CREATE A VOL QUEUE ENTRY
MOVE P3,S1 ;SAVE THE ENTRY ADDRESS
MOVE S1,.DLRID(P1) ;PICK UP THE REELID
MOVEM S1,.VLNAM(P3) ;SAVE IT IN THE VOL ENTRY
SKIPN S1 ;IS THIS REALLY A VOL BLK?
JRST DTAD.4 ;NO NAME... NO RESOURCE NUMBER
MOVE S1,P1 ;AIM AT THIS NEW VOL BLK
PUSHJ P,D$OVRS ;GO GENERATE A RESOURCE NUMBER
;Having set everything up, link the VOL and UCB together
;and go finish updating the volume status
DTAD.4: HRRZM P3,.UCBVL(P2) ;LINK THE VOLUME TO THE UCB
MOVEM P2,.VLUCB(P3) ;LINK THE UCB TO THE VOLUME
;Update the volume status and tell the operator whats going on.
DTAD.5: LOAD S1,.STFLG(T1),ST.LOK ;GET THE WRITE LOCK STATUS
STORE S1,.UCBST(P2),UC.WLK ;SAVE THE WRITE LOCK STATUS
SKIPN .DLRID(P1) ;CHECK FOR A REELID
JRST DTAD.6 ;UNLABELED
MOVE S1,P2 ;GET UCB ADR
PUSHJ P,MATUNI ;TRY TO MATCH THIS UNIT WITH A REQUEST
JUMPT .RETT ;DONE, DON'T BOTHER THE OPERATOR
$WTO (<Volume ^W/.VLNAM(P3)/ mounted>,,MDAOBJ)
$RETT ;AND RETURN
DTAD.6: LOAD S1,.UCBST(P2),UC.WLK ;GET THE WRITE LOCKED BIT
$WTO (<Unlabeled volume mounted>,,MDAOBJ)
$RETT ;TELL OPR AND RETURN
>
SUBTTL DSKDEV - DISK STRUCTURE DEVICE STATUS MESSAGE PROCESSOR
;CALL: T1/ The .STSTS block address
; T2/ The UCB address
; T3/ The .DSSTA block address
;
;RET: Usually True
TOPS10 <
DSKDEV: PUSHJ P,.SAVE1 ;SAVE P1
SKIPN P1,.UCBVL(T2) ;CHECK AND LOAD ANY MOUNTED VOL ADDRESS
JRST DSKD.1 ;NONE THERE,,SKIP THIS
MOVE S1,.VLSTR(P1) ;GET THE MOUNTED STRUCTURE NAME
LOAD S2,.VLFLG(P1),VL.LUN ;AND GET ITS LOGICAL UNIT NUMBER
CAMN S1,.DSSNM(T3) ;DOES STRUCTURE NAME MATCH
CAME S2,.DSLUN(T3) ; AND ALSO LOGICAL UNIT NUMBER ???
SKIPA ;NO,,CONTINUE ON
JRST DSKD.8 ;YES,,JUST UPDATE THE VOLUME STATUS
MOVE S1,P1 ;GET THE VOL ADDRESS IN S1
DSKD.A: MOVE S2,S1 ;SAVE THE VOL ADDRESS IN S2
LOAD S1,.VLPTR(S2),VL.PRV ;FIND THE PRIMARY VOL BLOCK
JUMPN S1,DSKD.A ;NOT 0,,CONTINUE BACK CHAINING !!!
LOAD S1,.VLFLG(S2),VL.STA ;GET THE STRUCTURE STATUS
CAXN S1,%STAMN ;IS THE STRUCTURE MOUNTED ???
JRST DSK.10 ;YES,,WE HAVE AN ERROR !!!
DSKD.0: SETZM .VLUCB(P1) ;NOT MOUNTED,,ZAP THE VOL/UCB POINTER
SETZM .UCBVL(T2) ;ALSO ZAP THE UCB/VOL POINTER
MOVE S1,P1 ;GET THE VOL ADDRESS IN S1
PUSHJ P,DELVOL ;AND TRY TO DELETE THE VOL BLOCK(S)
DSKD.1: SKIPN S1,.DSHID(T3) ;GET THE VOLUME BLOCK ID
JRST DSK.11 ;NONE THERE,,UH OHHHHH !!!!
PUSHJ P,FNDDSK ;FIND IT IN THE VOL QUEUE
JUMPF [MOVE S1,.DSSNM(T3) ;NOT THERE,,GET THE STRUCTURE NAME
PUSHJ P,FNDISK ;TRY TO FIND THE PRI VOL BLOCK
JUMPF DSKD.4 ;NOT THERE,,CREATE A NEW VOL BLOCK
MOVE P1,S1 ;FOUND,,SAVE THE VOL ADDRESS
SKIPE .VLVID(P1) ;IS A VOLID PRESENT ???
JRST DSKD.4 ;YES,,CREATE A NEW VOL BLOCK
JRST DSKD.5 ] ;NO,,USE THIS VOL BLOCK
MOVE P1,S1 ;SAVE THE VOL BLOCK ADDRESS
MOVE S1,.VLSTR(P1) ;GET THE MOUNTED STRUCTURE NAME
LOAD S2,.VLFLG(P1),VL.LUN ;AND GET ITS LOGICAL UNIT NUMBER
CAMN S1,.DSSNM(T3) ;DOES STRUCTURE NAME MATCH
CAME S2,.DSLUN(T3) ; AND ALSO LOGICAL UNIT NUMBER ???
JRST DSKD.3 ;NO,,PROCESS DUPLICATE VOL BLK
PUSHJ P,FNDISK ;FIND ITS PRIMARY VOL BLOCK ADDRESS
JUMPF DSKD.2 ;NOT THERE,,SKIP MOUNTED CHECK
LOAD S1,.VLFLG(S1),VL.STA ;GET THE STRUCTURE STATUS
MOVE S2,.DSHID(T3) ;GET GET THE UNIT ID
CAIN S1,%STAMN ;MOUNTED?
CAME S2,.VLVID(P1) ;AND THE SAME UNIT ID?
JRST DSKD.2 ;NO PROBLEMS
JRST DSKD.9 ;YES,,THATS AN ERROR
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
DSKD.2: SKIPE S1,.VLUCB(P1) ;GET THE VOL UCB ADDRESS
SETZM .UCBVL(S1) ;ZAP THAT UNITS POINTER TO THE VOL BLK
JRST DSKD.7 ;AND CONTINUE
DSKD.3: SKIPN S1,.VLUCB(P1) ;IS THE DUPLICATE VOLUME MOUNTED ???
JRST DSKD.4 ;NO,,SKIP THIS
$WTO (<Warning: ^W/.VLVID(P1)/ is mounted on drive ^W/.UCBNM(S1)/>,,MDAOBJ)
MOVE S1,.UCBNM(S1) ;GET THE UNIT ON WHICH VOL IS MOUNTED
PUSHJ P,SNDREC ;REQUEST DEVICE STATUS FOR THE VOL
DSKD.4: PUSHJ P,CREVOL ;GO CREATE A VOL ENTRY FOR IT
MOVE P1,S1 ;SAVE THE NEW VOL ADDRESS
DSKD.5: MOVE S1,.DSHID(T3) ;GET THIS VOL'S VOLUME NAME
MOVEM S1,.VLVID(P1) ;SAVE IT
MOVE S1,.DSLUN(T3) ;GET THIS VOL'S LOGICAL UNIT NUMBER
STORE S1,.VLFLG(P1),VL.LUN ;SAVE IT
MOVE S1,.DSNXV(T3) ;GET THE NEXT VOLUME NAME
MOVEM S1,.VLNXT(P1) ;SAVE IT
MOVE S1,.DSSNM(T3) ;GET THE STRUCTURE NAME FOR THIS VOL
MOVEM S1,.VLSTR(P1) ;SAVE IT
MOVE S1,.DSPPN(T3) ;GET OWNER PPN
MOVEM S1,.VLOID(P1) ;SAVE IT
MOVX S1,%LABEL ;GET 'LABELED' LABEL TYPE
STORE S1,.VLFLG(P1),VL.LBT ;AND SET IT
DSKD.7: MOVEM P1,.UCBVL(T2) ;LINK THE VOL TO THE UCB
MOVEM T2,.VLUCB(P1) ;LINK THE UCB TO THE VOL
MOVE S1,.VLSTR(P1) ;GET THE STRUCTURE NAME
SKIPE .DSLUN(T3) ;THE THE FIRST UNIT IN THE STRUCTURE ??
JRST DSKD.8 ;NO, DON'T MAKE A RESOURCE NUMBER
STORE S1,.VLNAM(P1) ;YES,,SET THE STR NAME (PRIMARY VOL)
MOVE S1,P1 ;AIM AT THE STR VOL BLK
PUSHJ P,D$SVRS ;GENERATE A STRUCTURE RESOURCE NUMBER
DSKD.8: LOAD S1,.STFLG(T1),ST.LOK ;GET THE UNIT WRITE LOCK BIT
STORE S1,.UCBST(T2),UC.WLK ;SAVE IT
LOAD S2,.UCBS1(T2),U1.FRC ;[1217] GET 'FORCED' MOUNT BIT
STORE S2,.VLFLG(P1),VL.FRC ;[1217] SET IN VOL BLOCK ALSO
MOVEI S2,[ASCIZ ||] ;ASSUME WRITE ENABLED
SKIPE S1 ;WAS IT?
MOVEI S2,[ASCIZ |Unit is hardware write protected|]
$WTO (<Volume ^W/.VLVID(P1)/ for structure ^W/.DSSNM(T3)/ mounted>,<^T/(S2)/>,MDAOBJ)
MOVE S1,.VLSTR(P1) ;GET THE STRUCTURE NAME IN S1
SETZM S2 ;NO ALIAS...
MOVX TF,VL.FRC ;[1217] GET 'FORCED' MOUNT BIT
TDNN TF,.VLFLG(P1) ;[1217] IS A 'FORCED' MOUNT IN PROGRESS ?
SKIPE D$ASR ;IS AUTOMATIC STR RECOGNITION ENABLED ???
PUSHJ P,BLDSTR ;YES,,TRY TO BUILD A STR WITH WHAT WE HAVE
$RETT ;RETURN
DSKD.9: MOVE S2,.VLUCB(P1) ;GET THE VOLS UCB ADDRESS
$WTO (<Error - Can't mount volume ^W/.DSHID(T3)/ on this unit>,<The volume is already mounted on ^W/.UCBNM(S2)/>,MDAOBJ)
$RETT ;AND RETURN
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
DSK.10: $WTO (<Error - Can't mount volume ^W/.DSHID(T3)/ on this Unit>,<Volume ^W/.VLVID(P1)/ for structure ^W/.VLSTR(P1)/ is mounted on this unit>,MDAOBJ)
SKIPA ;SKIP OVER OTHER ERROR
DSK.11: $WTO (<Error - Pack on this unit has a null volume0-ID>,,MDAOBJ,<$WTFLG(WT.SJI)>)
MOVE S1,.UCBNM(T2) ;GET THE UNIT NAME
PUSHJ P,UNLOAD ;UNLOAD IT
$RETT ;AND RETURN
>
SUBTTL SETOWN - ROUTINE TO SET UP OWNERSHIP FOR A VSL
;CALL: S1/ The VSL Address
;
;RET: S1/ The VSL Address (True Always)
SETASK: TDZA TF,TF ;INDICATE 'SET MOUNT REQUESTED'
CLRASK: SETOM TF ;INDICATE 'CLEAR MOUNT REQUESTED'
MOVX S2,VL.ASK ;GET 'MOUNT REQUESTED' STATUS BIT
JRST COMMON ;CONTINUE
D$SETO:: ;MAKE 'SETOWN' GLOBAL
SETOWN: TDZA TF,TF ;INDICATE 'SET ASSIGNED'
CLROWN: SETOM TF ;INDICATE 'CLEAR ASSIGNED'
MOVX S2,VL.ASN ;GET THE 'ASSIGNED' STATUS BIT
SKIPN TF ;ARE WE SETTING THE BIT ???
TXO S2,VL.OWN ;YES,,ALSO LIGHT THE VOLUME OWNED BIT
COMMON: $SAVE <S1,P1,P2,P3> ;SAVE SOME ACS
MOVE P1,S1 ;SAVE THE VSL ADDRESS
MOVE P2,S2 ;SAVE THE BIT TO CLEAR/LITE
MOVE P3,TF ;SAVE THE SET/CLEAR FUNCTION CODE
PUSHJ P,CHKOWN ;LOCATE THIS GUYS VSL ADDR IN THE VOL
JUMPN P3,[ANDCAM P2,0(S1) ;IF CLEAR FUNCTION,,CLEAR THE BIT
SETZM .VSUCB(P1) ;ZAP THE UNIT POINTER
$RETT ] ;AND RETURN
IORM P2,0(S1) ;IF SET FUNCTION,,LITE THE BIT(S)
ZERO .VSFLG(P1),VS.NMT ;CLEAR THE PSEUDO MOUNTED STATUS BIT
TXNN P2,VL.ASN ;IF JUST 'ASKING' THEN
$RETT ;RETURN NOW
LOAD P3,.VSCVL(P1),VS.OFF ;GET THE CURRENT VOLUME OFFSET
ADDI P3,.VSVOL(P1) ;POINT TO THE VOL ADDRESS
MOVE P3,0(P3) ;GET THE VOL ADDRESS
MOVE P3,.VLUCB(P3) ;GET THE UNIT ADDRESS
MOVEM P3,.VSUCB(P1) ;AND LINK THE UCB TO THIS VSL
MOVX P2,VL.ASK ;GET THE 'ASK' BIT
ANDCAM P2,0(S1) ;AND CLEAR IT
$RETT ;RETURN
SUBTTL MNTVSL - ROUTINE TO ATTEMPT TO MOUNT A USERS REQUESTS
;CALL: S1/ The VSL Address
;
;RET: True Always
TOPS10<
D$MNTV:: ;MAKE IT GLOBAL
MNTVSL: PUSHJ P,.SAVE4 ;SAVE P1 & P2 & P3 & P4
$SAVE <AP,T3,T4> ;SAVE AP & T3 & T4 ALSO
STKVAR <NOACK,<VSLIST,^D20>,<MNTLST,^D40>> ;GEN A FLAG & SOME QUEUES
MOVE P4,S1 ;SAVE THE INITIAL VSL ADDRESS
MOVE AP,.VSMDR(P4) ;SETUP THE MDR ADDRESS
SETZM P3 ;INDICATE NORMAL MOUNT REQUEST
SETZM NOACK ;CLEAR NO ACK FLAG
MOVX S1,QE.WAM ;GET WAITING FOR MOUNT STATUS
LOAD S2,.MRJOB(AP),MR.JOB ;GET THE REQUEST JOB NUMBER
TXNE S2,BA%JOB ;IS THIS A PSEUDO REQUEST ???
SKIPN P3,.MRQEA(AP) ;YES,,PICK UP THE QE ADDRESS
SKIPA ;NOT A PSEUDO REQUEST,,SKIP
IORM S1,.QESEQ(P3) ;SET 'MOUNT WAIT' (CLEARED LATER)
MNTV.0: MOVEI T4,VSLIST ;GET THE PRIMARY VSL QUEUE ADDRESS
HRLI T4,-^D20 ;GEN THE PRIMARY VSL QUEUE STACK POINTER
PUSH T4,[-1] ;MARK END OF VSL QUEUE
MOVEI T3,MNTLST ;GET THE MOUNT VSL QUEUE ADDRESS
HRLI T3,-^D40 ;GEN MOUNT VSL QUEUE STACK POINTER
PUSH T3,[-1] ;MARK END OF VSL QUEUE
PUSH T3,[-1] ;HERE ALSO
LOAD P1,.MRCNT(AP),MR.CNT ;GET THE VSL REQUEST COUNT
LOAD P2,.VSLNK(P4),VS.LNK ;GET THE VSL LINK CODE
MOVNS P1 ;NEGATE THE VSL COUNT
MOVSS P1 ;MOVE RIGHT TO LEFT
HRRI P1,.MRVSL(AP) ;CREATE VSL AOBJN AC
MNTV.1: MOVE S1,0(P1) ;GET A VSL ADDRESS
LOAD S2,.VSLNK(S1),VS.LNK ;GET THE VSL LINK CODE
CAME S2,P2 ;DO THEY MATCH ???
JRST MNTV.2 ;NO,,TRY NEXT
MOVE S2,.VSFLG(S1) ;GET THE VSL FLAG BITS
TXNE S2,VS.ALC+VS.WAL ;JUST ALLOCATED OR AWAITING ALLOCATION ?
JRST [JUMPE P3,.RETF ;YES,,IF NOT A PSEUDO PROCESS - RETURN
MOVX S2,QE.WAM ;IF A PSEUDO PROCESS,,GET 'MOUNT WAIT'
ANDCAM S2,.QESEQ(P3) ; AND CLEAR IT
$RETF ] ;THEN RETURN
PUSH T4,S1 ;QUEUE UP THE VSL ADDRESS
LOAD S1,.VSFLG(S1),VS.TYP ;GET THE REQUEST TYPE
CAXN S1,%UNKN ;IS IT UNKNOWN ???
;**;[1225] Change code at MNTV.1+12L. /LWS
JRST [MOVE S1,P4 ;[1225] GET PRIMARY VSL ADDRESS
PUSHJ P,TELOPR ;[1225] TELL OPR OF MOUNT
$RETF] ;[1225] RETURN FALSE
MNTV.2: AOBJN P1,MNTV.1 ;LOOK FOR ALL VSL'S WITH THAT LINK CODE
MOVE P2,T4 ;SAVE THE PRIMARY VSL QUEUE STACK PTR
;CONTINUED ON THE NEXT PAGE
;Here to perform deadlock avoidance check
MOVE S1,P4 ;GET THE INITIAL VSL ADDRESS BACK
SKIPN G$DEAD## ;DEADLOCK AVOIDANCE TURNED ON?
PUSHJ P,TELOPR ;NO,,ALWAYS TELL THE OPR ABOUT MOUNTS
MOVE S1,P4 ;GET BACK VSL ADDRESS IN CASE OF MDA
PUSHJ P,D$DLCK ;DO DEADLOCK CHECKING
JUMPF .RETF ;IF DEADLOCKED,,JUST RETURN
;Here to check to make sure we can mount ALL the required volumes
MNT.2A: POP T4,S1 ;GET A VSL ADDRESS OFF THE QUEUE
CAMN S1,[-1] ;END OF THE QUEUE ???
JRST MNT.2B ;YES,,CONTINUE ONWARD !!!
LOAD S2,.VSFLG(S1),VS.INI ;[1164] GET NEW-VOLUME INITIALIZATION BIT
JUMPN S2,MNT.2A ;[1164] IF LIT,,SKIP THIS VSL
PUSHJ P,VSLCHK ;CAN WE MOUNT THIS VOLUME ???
JUMPF MNTV.9 ;NO - TELL THE OPERATOR
JUMPE S1,MNT.2A ;THAT VSL ALREADY MOUNTED,,TRY NEXT
JUMPL S1,MNTV.8 ;REQUIRED VOLUME NOT MOUNTED,,TELL OPR
PUSH T3,S1 ;QUEUE UP THE VSL ADDRESS
PUSH T3,S2 ;QUEUE UP THE UCB/VOL ADDRESS
JRST MNT.2A ;CONTINUE ON
;Now check to see if the pseudo process has been allocated
MNT.2B: JUMPE P3,MNTV.3 ;NOT A PSEUDO PROCESS,,CONTINUE
MOVX S1,QE.WAM ;GET 'WAITING FOR MOUNT' STATUS BIT
ANDCAM S1,.QESEQ(P3) ;CLEAR IT FOR THE PSEUDO PROCESS
MOVE S1,P3 ;GET THE QE ADDRESS IN S1
PUSHJ P,I$RALC## ;REQUEST ALLOCATION
;Try to mount the Volume(s)
MNTV.3: POP T3,S2 ;RESTORE A VOL/UCB ADDRESS
POP T3,S1 ;RESTORE A VSL ADDRESS
CAMN S1,[-1] ;END OF THE QUEUE ???
JRST MNTV.7 ;YES,,GO ACK THE USER
JUMPN P3,MNTV.4 ;IF A PSEUDO PROCESS,,GO MOUNT IT
LOAD P1,.VSFLG(S1),VS.TYP ;ELSE GET THE VOLUME TYPE
CAIE P1,%DTAP ;DECTAPE?
CAIN P1,%TAPE ;MAGTAPE?
JRST MNTV.5 ;YES,,GO PROCESS IT
JRST MNTV.6 ;NO,,ASSUME %DISK
;Here to perform mounts for Pseudo Processes
MNTV.4: SETOM NOACK ;LITE 'DEFERED ACK' FLAG
DOSCHD ;FORCE A SCHEDULING PASS
MOVE P1,S1 ;SAVE THE VSL ADDRESS
PUSH P,S2 ;SAVE THE VOL/UCB ADDRESS
PUSHJ P,SETOWN ;SET VOLUME OWNERSHIP
POP P,S2 ;RESTORE THE VOL/UCB ADDRESS
MOVX S1,VS.NMT ;GET THE 'NOT REALLY MOUNTED' FLAG BIT
IORM S1,.VSFLG(P1) ;SET IT FOR THIS PSEUDO PROCESS
LOAD S1,.VSFLG(P1),VS.TYP ;GET THE VOLUME TYPE
CAXE S1,%TAPE ;IS IT TAPE ???
JRST MNTV.3 ;NO,,GET NEXT VSL
MOVEM S2,.VSUCB(P1) ;LINK THE UCB TO THIS USER
MOVEM P1,.UCBVS(S2) ;LINK THIS USER TO THIS DEVICE
JRST MNTV.3 ;GET THE NEXT VSL
;CONTINUED ON THE NEXT PAGE
;Here to mount tape volumes
MNTV.5: MOVE P1,S1 ;SAVE THE VSL ADDRESS
EXCH S1,S2 ;GET UCB ADDR IN S1, VSL IN S2
PUSHJ P,REASSI ;TRY TO REASSIGN THE DEVICE
JRST MNTV.3 ;CONTINUE
;Here to mount structures
MNTV.6: SETOM NOACK ;LITE 'DEFERED ACK' FLAG
PUSH P,S2 ;SAVE THE VOL ADDRESS
PUSHJ P,SETASK ;SET THE 'MOUNT REQUESTED' STATUS
POP P,S2 ;RESTORE THE VOL ADDRESS
PUSHJ P,ASLMSG ;GEN 'ADD TO SEARCH LIST' & SEND IT
JRST MNTV.3 ;CONTINUE
;Here to ack the user that his request has been satisfied
MNTV.7: SKIPE NOACK ;IS 'NO ACK' SET ???
$RETT ;YES,,RETURN
MOVE S1,P4 ;GET THE VSL ADDRESS BACK
PUSHJ P,ACKUSR ;NOTIFY THE USER
$RETT ;AND RETURN
MNTV.8: MOVE S1,P4 ;GET THE ORIGIONAL VSL ADDRESS
SKIPE G$DEAD## ;DEADLOCK AVOIDANCE TURNED ON?
PUSHJ P,TELOPR ;ASK THE OPR TO MOUNT THE DEVICES
JUMPE P2,.RETF ;NO VSL QUEUE,,EXIT NOW
MNTV.9: POP P2,S1 ;PICK UP THE VSL ADDRESS OFF THE QUEUE
CAMN S1,[-1] ;END OF THE QUEUE ???
$RETF ;YES,,RETURN
PUSHJ P,RETA%C ;RETURN THE 'A' AND 'C' MATRIX ENTRIES
JRST MNTV.9 ;CONTINUE FOR ALL VSL'S
> ;END TOPS10 CONDITIONAL
SUBTTL MNTVSR - ROUTINE TO MOUNT A VOLUME AT VOLUME SWITCH TIME
;CALL: S1/ The VSL Address
;
;RET: True if the mount wins, False otherwise
TOPS10<
MNTVSR: $SAVE <AP,P1,P2> ;SAVE AP AND P1 & P2 FOR A SECOND
MOVE AP,.VSMDR(S1) ;SETUP A NEW MDR POINTER
MOVE P1,S1 ;SAVE THE VSL ADDRESS
PUSHJ P,D$CMTX ;LOCATE THIS GUYS 'C' MATRIX ENTRY
LOAD S1,.VSCVL(P1),VS.OFF ;GET THE OFFSET TO THE CURRENT VOLUME
ADDI S1,.VSVOL(P1) ;POINT TO THE CURRENT VOL ADDRESS
MOVE S1,0(S1) ;GET THE CURRENT VOL ADDRESS
PUSHJ P,D$TVRS ;CONVERT TO A RESOURCE NUMBER
MOVE P2,S1 ;SAVE THE RSN FOR LATER IF WE NEED IT
MOVE S2,P1 ;GET THE VSL ADDRESS IN S2
PUSHJ P,ADDAMA ;CLAIM THIS RESOURCE IN 'A' MATRIX
PUSHJ P,ADDCMA ;CLAIM THIS RESOURCE IN 'C' MATRIX
PUSHJ P,DEADLK ;DEADLOCK CHECK THE WORLD !!!
JUMPF TVSR.1 ;TOUGH NOUGEEEES !!!
MOVE S1,P1 ;GET THE VSL ADDRESS IN S1
PUSHJ P,VSLCHK ;CAN WE MOUNT THE VOLUME ???
JUMPF TVSR.1 ;NO,,THIS GUY JUST CAN'T WIN !!!
JUMPE S1,.RETT ;SHOULD NOT HAPPEN !!!
JUMPL S1,TVSR.0 ;NOT MOUNTED,,TELL OPR TO MOUNT IT
EXCH S1,S2 ;GET UCB ADDR IN S1, VSL ADDR IN S2
PUSHJ P,REASSI ;REASSIGN THE VOLUME
$RETT ;RETURN
TVSR.0: MOVE S1,P1 ;GET THE VSL ADDRESS IN S1
PUSHJ P,TELOPR ;TELL THE OPR TO MOUNT THE VOLUME
TVSR.1: MOVE S1,P2 ;GET THE VOLUME RSN BACK
MOVE S2,P1 ;GET THE VSL ADDRESS BACK
PUSHJ P,SUBAMA ;DELETE THE CLAIM FROM THE 'A' MATRIX
PUSHJ P,SUBCMA ;DELETE THE CLAIM FROM THE 'C' MATRIX
$RETT ;RETURN
> ;END TOPS10 CONDITIONAL
SUBTTL VSLCHK - ROUTINE TO TRY TO MOUNT A VOLUME FROM THE VSL
;CALL: S1/ The VSL Address
;
;RET: S1/ The VSL Address if %TAPE
; S2/ The UCB Address if %TAPE
;
; S1/ The VSL Address if %DISK
; S2/ The VOL Address if %DISK
;
;Error Return Codes:
;
; S1/ 0 If the User Already has the Volume Mounted
; S1/ -1 If the requested volume needs mounting
TOPS10<
VSLCHK: PUSHJ P,.SAVE3 ;SAVE P1 TO P3
MOVE P2,S1 ;SAVE THE VSL ADDRESS
LOAD S1,.VSCVL(P2),VS.OFF ;GET THE OFFSET TO THE CURRENT VOLUME
ADDI S1,.VSVOL(P2) ;POINT TO THE CURR VOL ADDRESS
MOVE P1,0(S1) ;GET THE CURRENT VOLUME ADDRESS
SKIPN P3,.VLUCB(P1) ;CHECK AND LOAD THE UCB ADDRESS
JRST [SETOM S1 ;NOT MOUNTED,,SET RETURN CODE
$RETT ] ; AND EXIT
MOVE S2,.UCBNM(P3) ;GET THE UNIT NAME
MOVEM S2,MDAOBJ+OBJ.UN ;SAVE IT IN THE MDA OBJECT BLOCK
LOAD S1,.VSFLG(P2),VS.NMT ;GET THE PSEUDO MOUNTED FLAG BIT
JUMPE S1,VSLC.1 ;NOT CURRENTLY MOUNTED,,SKIP THIS
LOAD S1,.MRJOB(AP),MR.JOB ;GET THE JOB NUMBER
TXNN S1,BA%JOB ;STILL A PSEUDO PROCESS ???
JRST VSLC.5 ;NO,,MOUNT IT FOR REAL !!!!
SETZM S1 ;YES,,SET 'MOUNTED' RETURN CODE
$RETT ;AND RETURN NOW
VSLC.1: LOAD S1,.VSFLG(P2),VS.TYP ;GET REQUEST TYPE
CAXN S1,%DISK ;DISK REQUEST?
JRST VSLC.6 ;YES - DON'T CHECK OWNERSHIP
MOVE S1,P2 ;GET THE VSL ADDRESS IN S1
PUSHJ P,CHKOWN ;DOES THIS GUY OWN THE VOLUME ???
JUMPT [SETZM S1 ;YES,,SET 'MOUNTED' RETURN CODE
$RETT ] ;AND RETURN
VSLC.2: LOAD S1,.VSFLG(P2),VS.TYP ;GET THE VOLUME SET TYPE
CAIN S1,%DTAP ;DECTAPE?
JRST VSLC.3 ;YES
CAXE S1,%TAPE ;IS IT A TAPE REQUEST ???
JRST VSLC.6 ;NO,,TRY DISK
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
;Here to process magtape requests
LOAD S1,.VSFLG(P2),VS.VSW ;IS THIS VSL IN VOLUME SWITCH ???
JUMPN S1,VSLC.3 ;YES,,SKIP LABEL CHECK
LOAD S1,.VLFLG(P1),VL.LBT ;GET THE MOUNTED VOL LABEL TYPE
PUSHJ P,GETLBT ;RECODE IT TO SOMETHING UNDERSTANDABLE
CAXE S1,%LABEL ;IS IT LABELED ???
;**;[1140]CHANGE 1 LINE AT VSLC.3:-1L 23-JUL-83/CTK
;**;[1150]REMOVE EDIT # 1140 7-SEP-83/CTK
$RETF ;NO,,RETURN
VSLC.3: MOVE S1,P1 ;GET THE VOL ADDRESS IN S1
PUSHJ P,FNDOWN ;IS THE VOLUME OWNED ???
JUMPT .RETF ;YES,,RETURN
VSLC.4: DMOVE S1,P1 ;GET VOL ADDR IN S1, VSL ADDR IN S2
PUSHJ P,CVLVSB ;GO CHECK DEVICE ATTRIBUTES
JUMPF .RETF ;NO MATCH,,RETURN
LOAD S1,.UCBST(P3),UC.VSW ;SWITCHING VOLUMES ON THIS UNIT?
JUMPE S1,VSLC.5 ;NO,,SKIP THIS
CAME P2,.UCBVS(P3) ;DOES THIS USER OWN THE UNIT ???
$RETF ;NO,,RETURN
VSLC.5: MOVE S1,P2 ;GET THE VSL ADDRESS IN S1
LOAD S2,.VSFLG(P2),VS.TYP ;GET THE REQUEST TYPE
CAIN S2,%DISK ;IS IT A STRUCTURE REQUEST ???
MOVE P3,.UCBVL(P3) ;YES,,LOAD UP THE VOL BLOCK ADDRESS
MOVE S2,P3 ;GET THE UCB OR VOL ADDRESS IN S2
$RETT ;RETURN OK
;Here to process Disk requests
VSLC.6: CAXE S1,%DISK ;IS THIS A DISK REQUEST ???
$RETF ;NO,,RETURN
LOAD S1,.VLFLG(P1),VL.STA ;GET THE STRUCTURE STATUS
LOAD S2,.VLFLG(P1),VL.LCK ;GET THE STR LOCK STATUS
CAIN S1,%STAWT ;IS IT WAITING TO BE MOUNTED?
JRST [MOVX S1,-1 ;YES - SET RETURN CODE
$RETT] ;AND RETURN
CAXN S1,%STAMN ;MUST BE MOUNTED AND
CAXN S2,%LOCKD ; NOT LOCKED
SKIPA ; OR NOT LOCKED
CAXN S2,%ULCKP ; WITH A PENDING UNLOCK
$RETF ;IF SO,,THATS NO GOOD !!!
MOVE S1,P2 ;GET THE VSL ADDRESS
MOVE S2,P1 ;GET THE VOL ADDRESS
$RETT ;RETURN
> ;END TOPS10 CONDITIONAL
SUBTTL MATUNI - ROUTINE TO GIVE A VOLUME TO ANY VALID REQUESTOR
;CALL: S1/ The UCB Address of the unit on which the volume is mounted
;
;RET: True Always
TOPS10<
MATUNI: PUSHJ P,.SAVE3 ;SAVE P1& P2 & P3 FOR A SECOND
SKIPN P2,.UCBVL(S1) ;CHECK AND LOAD THE VOL BLOCK ADDRESS
$RETF ;SHOULD NOT HAPPEN
LOAD P1,.VLOWN(P2),VL.CNT ;GET THE REQUEST COUNT
JUMPE P1,.RETF ;NONE THERE,,RETURN
MOVNS P1 ;NEGATE IT
MOVSS P1 ;MOVE RIGHT TO LEFT
HRRI P1,.VLVSL(P2) ;GEN VSL SEARCH AOBJN AC
LOAD S1,.UCBST(S1),UC.DVT ;GET THE DEVICE TYPE
CAIN S1,%DISK ;STRUCTURE?
JRST MATU.2 ;YES
;Here to try to satisfy DECtape or magtape mount requests
MATU.0: MOVE S1,0(P1) ;GET A VSL ADDRESS
LOAD S2,.VSCVL(S1),VS.OFF ;GET THE CURRENT VOLUME OFFSET
ADDI S2,.VSVOL(S1) ;POINT TO THE CURRENT VOL ADDRESS
CAMN P2,0(S2) ;IS HE POINTING AT THIS VOL BLOCK ???
TXNE S1,VL.ASN ;OR DOES HE ALREADY HAVE IT ASSIGNED ??
JRST MATU.1 ;ALREADY ASSGNED OR WRONG VOL,SKIP THIS
HRRZS S1 ;GET ONLY THE VSL ADDRESS (CLEAR FLAGS)
LOAD P3,.VSFLG(S1),VS.VSW ;GET THE VOLUME SWITCH STATUS
SKIPE P3 ;ARE WE SWITCHING VOLUMES ???
PUSHJ P,MNTVSR ;YES,,GO PROCESS IT
SKIPN P3 ;ARE WE SWITCHING VOLUMES ???
PUSHJ P,MNTVSL ;NO,,TRY GENERAL MOUNT
JUMPT .RETT ;WIN,,RETURN
MATU.1: AOBJN P1,MATU.0 ;NO GO,,TRY NEXT VSL
$RETF ;CAN'T,,JUST RETURN
;Here to try to satisfy structure mount requests
MATU.2: MOVE S1,0(P1) ;GET A VSL ADDRESS
TXNN S1,VL.ASK+VL.ASN ;ASSIGNED OR PENDING ???
JRST [HRRZS S1 ;GET ONLY THE VSL ADDRESS (CLEAR FLAGS)
PUSHJ P,MNTVSL ;TRY TO MOUNT IT FOR THIS USER
JRST MATU.3 ] ;AND CONTINUE
MATU.3: AOBJN P1,MATU.2 ;CHECK THROUGH ALL VSL'S
$RETT ;RETURN
> ;END TOPS10 CONDITIONAL
SUBTTL CVLVSL - Compare Volume with Volume Set
;This routine will check the user requested attributes of the
; mount request with the attributes of a particular mounted volume
; The caller must make sure that the volume is free to be
; reassigned to the user should the attributes match.
;
;CALL: S1/ addr of VOL block
; S2/ addr of VSL block
;RET: TRUE, if all the attributes match, FALSE if they don't
; Alternate entry at CVLVSB which will not match bypass requests
TOPS10<
CVLVSB: LOAD TF,.VSFLG(S2),VS.LBT ;GET THE REQUESTED LABEL TYPE
CAXN TF,.TFLBP ;BYPASS REQUESTED?
$ERJMP MD$URB,S2 ;YES,,MUST COME THROUGH IDENTIFY
CVLVSL: LOAD TF,.VSFLG(S2),VS.TYP ;GET DEVICE TYPE
CAIN TF,%DTAP ;DECTAPE?
$RETT ;YES--NOTHING TO CHECK
$SAVE <P1,P2,P3>
DMOVE P1,S1 ;COPY THE VOL, AND VSL PTRS
SKIPN P3,.VLUCB(P1) ;GET THE UNIT BLOCK
$ERJMP MD$NVM,P2 ;SHOULD NOT HAPPEN !!!
;Check the state of the write-ring against the user request
LOAD S1,.UCBST(P3),UC.WLK ;GET THE LOCK BIT FOR THIS VOLUME
LOAD S2,.VSFLG(P2),VS.WLK ;GET THE ENABLE BIT FOR THE REQUEST
CAME S1,S2 ;DO THEY MATCH ???
PJRST [SKIPE S2 ;S2 NOT EQUAL TO 0,,WRITE LOCKED
$ERJMP MD$URW,P2 ;SO TELL THE OPERATOR
$ERJMP MD$URE,P2 ] ;ELSE USER WANTS WRITE ENABLED
;Check for conflicting label types
LOAD S1,.VSFLG(P2),VS.LBT ;GET REQUESTED LABEL TYPE
CAXN S1,.TFLNV ;IS IT NO LABELS/NO EOV PROCESSING ???
MOVX S1,.TFLNL ;YES,,MAKE IT NO LABELS, PERIOD !
LOAD S2,.VLFLG(P1),VL.LBT ;GET LABEL TYPE OF THIS VOLUME
CAXN S2,.TFLNV ;IS IT NO LABELS/NO EOV PROCESSING ???
MOVX S2,.TFLNL ;YES,,MAKE IT NO LABELS, PERIOD !
CAME S1,S2 ;MATCH?
CAXN S1,.TFLBP ;NO, BUT ASKING FOR BYPASS LABELS?
SKIPA ;MATCH.. OR REQUESTING BLP, WIN
JRST [CAXN S1,.TFLNL ;USER WANTED UNLABELED?
$ERJMP MD$VIL,P2 ;NO,,VOLUME IS LABELED !!!
$ERJMP MD$URL,P2 ] ;YES,,COMPLAIN ABOUT THAT !!!
DMOVE S1,P2 ;GET VSL IN S1, UCB IN S2
PUSHJ P,D$MODR ;CHECK TRACK/DENSITY REQUIREMENTS
JUMPF .RETF ;NO GOOD,,RETURN
$RETT ;ELSE OK
>;END TOPS10
SUBTTL CHKOWN - ROUTINE TO CHECK IF A USER OWNS A VOLUME
;CALL: S1/ The VSL Address
;
;RET: S1/ The VOL block pointer to the VSL address
D$FOWN:: ;GLOBALIZE IT
CHKOWN: LOAD S2,.VSCVL(S1),VS.OFF ;GET THE OFFSET TO THE CURRENT VOLUME
ADDI S2,.VSVOL(S1) ;POINT TO THE OFFSET
MOVE S2,0(S2) ;GET THE VOL BLOCK ADDRESS
EXCH S1,S2 ;WANT S1=VOL ADDR, S2=VSL ADDR
PUSH P,S2 ;SAVE THE VSL ADDRESS
LOAD S2,.VLOWN(S1),VL.CNT ;GET THE VOLUME REQUEST COUNT
MOVNS S2 ;NEGATE IT
MOVSS S2 ;MOVE RIGHT TO LEFT
HRRI S2,.VLVSL(S1) ;CREATE AOBJN AC FOR VSL ADDR SEARCH
MOVE S1,S2 ;GET THE POINTER IN S1
POP P,S2 ;GET THE VSL ADDRESS BACK
CHKO.1: CAIN S2,@0(S1) ;FIND THE USERS VSL ADDR IN THE VOL LIST
JRST [MOVX S2,VL.ASK+VL.ASN ;FOUND,,GET REQUEST+ASSIGNED BITS
TDNE S2,0(S1) ;IF LIT,,THIS GUY WAS ALREADY PROCESSED
$RETT ;RETURN VOLUME OWNED
$RETF ] ;RETURN VOLUME NOT OWNED
AOBJN S1,CHKO.1 ;NOT THIS ONE,,TRY NEXT
STOPCD (IVV,HALT,,<Invalid VSL/VOL forward/backchain pointers>) ;NOT FOUND !!!
SUBTTL D$UNLO - ROUTINE TO UNLOAD A TAPE DRIVE
;CALL: M/ The Unload Message Address
;
;RET: True Always
TOPS10 <
D$UNLO::PUSHJ P,.SAVE1 ;SAVE P1 FOR A MINUTE
MOVX S1,.TAPDV ;GET THE DRIVE BLOCK TYPE CODE
PUSHJ P,A$FNDB## ;FIND IT IN THE MESSAGE
JUMPF E$IMO## ;INVALID ORION MESSAGE SENT !!!
PUSHJ P,FNDUCB ;FIND THE AFFECTED UCB
JUMPF .RETF ;NOT THERE,,THATS AN ERROR
MOVE P1,S1 ;SAVE THE UCB ADDRESS IN P1
MOVE S1,.UCBNM(P1) ;GET THE DEVICE NAME IN S1
SKIPN S2,.UCBVL(P1) ;CHECK AND LOAD THE VOLUME ADDRESS
PJRST UNLOAD ;NO VOLUME ON IT,,JUST SEND THE MSG
LOAD S1,.UCBST(P1),UC.VSW ;IS THIS UNIT IN VOLUME SWITCH MODE ??
JUMPN S1,UNLO.1 ;YES,,OK TO UNLOAD THE TAPE !!!
MOVE S1,S2 ;GET THE VOLUME ADDRESS IN S1
PUSHJ P,FNDOWN ;ANY OWNERS FOR THIS VOLUME ???
SKIPF ;NO,,SKIP
$ERJMP MD$VAU ;YES,,CAN THE REQUEST
UNLO.1: $ACK (<Unloading>,,MDAOBJ,.MSCOD(M)) ;TELL THE OPERATOR
MOVE S1,.UCBVL(P1) ;POINT AT THIS VOLUME
PJRST VLUNLO ;AND DELINK ALL THE GOOD STUFF
>;END TOPS10
SUBTTL D$DISM - STRUCTURE DISMOUNT PROCESSOR
;CALL: M/ The Dismount Message Address
;
;RET: True Always
TOPS10 <
D$DISM::PUSHJ P,.SAVE1 ;SAVE P1 FOR A MINUTE
MOVX S1,.STRDV ;GET THE STRUCTURE DEVICE BLOCK TYPE
PUSHJ P,A$FNDB## ;FIND IT IN THE MESSAGE
JUMPF E$IMO## ;NOT THERE,,THATS AN ERROR
HRROI S1,0(S1) ;GET POINTER TO ASCIZ STRUCTURE NAME
PUSHJ P,S%SIXB ;CONVERT IT TO SIXBIT
MOVE S1,S2 ;PUT IT IN S1
MOVE P1,S1 ;HERE ALSO
PUSHJ P,FNDISK ;FIND THE VOLUME IN THE VOL BLOCK
JUMPF DISM.2 ;NOT THERE,,THATS AN ERROR
LOAD S2,.VLFLG(S1),VL.STA ;GET THE STRUCTURE STATUS BITS
CAXE S2,%STAMN ;IS IT MOUNTED ???
JRST DISM.1 ;NO,,THATS AN ERROR
MOVX S2,%STADM ;GET THE DISMOUNT STRUCTURE STATUS BITS
STORE S2,.VLFLG(S1),VL.STA ;SET IT IN STRUCTURE BLOCK
LOAD S2,.OFLAG(M),.DMRMV ;GET THE /REMOVE BIT
STORE S2,.VLFLG(S1),VL.REM ;AND SAVE IT
MOVX S2,.DMNCK ;GET THE /NOCHECK FLAG BIT
TDNN S2,.OFLAG(M) ;DID HE SPECIFY NO CHECK ???
SETZM S2 ;NO,,CLEAR IT !!!
PUSHJ P,SNDDSM ;SEND DISMOUNT MESSAGE TO TAPE LABELER
$RETT ;RETURN
DISM.1: MOVEI S1,[ASCIZ |is not mounted|] ;[1204] GET STRING ADDR
CAXN S2,%STADM ;[1204] DISMOUNT IN PROGRESS?
MOVEI S1,[ASCIZ |- dismount already in progress|] ;[1204] YES
$ACK (<Structure ^W/P1/ ^T/(S1)/>,,,.MSCOD(M),<$WTFLG(WT.SJI)>) ;[1204]
$RETT ;RETURN
DISM.2: $ACK (Structure ^W/P1/ does not exist,,,.MSCOD(M),<$WTFLG(WT.SJI)>)
$RETT ;RETURN
>
SUBTTL VLUNLO - Unload a unit and break UCB-VOL links
;CALL: S1/ The Volume Block Address
;
;RET: True Always
;This routine will break the VOL - UCB links and request PULSAR
; to unload the drive. In addition, if there are no more
; requestors for the volume, the volume block is deleted.
; Alternate entry - VLBREAK which just breaks the
; UCB - VOL link, but does not unload.
TOPS10<
VLBREA: TDZA S2,S2 ;INDICATE 'JUST BREAK' ENTRY
VLUNLO: MOVEI S2,1 ;INDICATE 'BREAK AND UNLOAD ENTRY'
$SAVE <P1> ;SAVE P1 FOR A SECOND
MOVE P1,S2 ;SAVE THE ENTRY FLAG
MOVE S2,.VLUCB(S1) ;GET THE UCB ADDRESS IN S2
ZERO .UCBVL(S2) ;DELINK UCB FROM THE VOL
ZERO .VLUCB(S1) ;DELINK THE VOL FROM THE UCB
MOVX TF,UC.OFL ;GET 'DEVICE OFFLINE' BIT
IORM TF,.UCBST(S2) ;LITE IT IN THE UCB
MOVX TF,%STAWT ;GET VOLUME WAITING STATUS CODE
STORE TF,.VLFLG(S1),VL.STA ;AND SET IT
LOAD TF,.VLOWN(S1),VL.CNT ;GET THE NUMBER OF REMAINING REQUESTORS
EXCH S1,S2 ;GET S1=UCB, S2=VOL ADDRESS
MOVE S1,.UCBNM(S1) ;GET THE NAME OF THE UNIT
JUMPN TF,VLUN.1 ;ANY MORE REQUESTORS ?? YES, KEEP VOL
PUSH P,S1 ;SAVE UNIT NAME
MOVE S1,S2 ;GET THE VOL ADDRESS IN S1
PUSHJ P,DELVOL ;AND DELETE THE VOLUME
POP P,S1 ;GET BACK UNIT NAME
VLUN.1: JUMPE P1,.RETT ;IF VLBREAK ENTRY, QUIT
PJRST UNLOAD ;IF VLUNLO ENTRY, GO UNLOAD THE TAPE
>;END TOPS10
SUBTTL D$DELE - ROUTINE TO DELETE REQUESTS FROM THE MOUNT QUEUE
;CALL: M/ The Delete Message Address
;
;RET: True if deleted, False otherwise
TOPS10 <
D$DELE::PUSHJ P,.SAVE4 ;SAVE P1 - P4
MOVX S1,.ORREA ;GET THE REASON BLOCK TYPE
SETZM P4 ;DEFAULT TO NO REASON BLOCK
PUSHJ P,A$FNDB## ;FIND IT
SKIPF ;LOSE,,SKIP
MOVE P4,S1 ;SAVE THE REASON BLOCK ADDRESS
MOVEI P1,1 ;GET THE BLOCK COUNT
DELZ.1: MOVE S1,[EXP .ORREQ,.STRDV,](P1) ;GET THE BLK TYPE
PUSHJ P,A$FNDB## ;FIND IT
JUMPT @[EXP DELRID,DELSTR](P1) ;FOUND,,PROCESS IT
SOJGE P1,DELZ.1 ;NOT FOUND,,TRY NEXT
SETZM MDAOBJ+OBJ.UN ;ZAP THE UNIT WORD OF MDA OBJECT BLK
PJRST E$IMO## ;RETURN INVALID MESSAGE FROM ORION
;Routine to delete a mount request by request ID
DELRID: MOVE S1,0(S1) ;GET THE REQUEST ID
CAMN S1,[-1] ;IS THIS ALL REQUESTS ???
JRST DELALL ;YES,,OK YOU ASKED FOR IT !!!
MOVE P1,S1 ;NO,,SAVE IT
PUSHJ P,FNDVSL ;LOCATE THE REQUEST
JUMPF DELD.1 ;NOT THERE,,RETURN AN ERROR
MOVE P1,S1 ;SAVE THE VSL ADDRESS
PUSHJ P,CHKOWN ;DOES HE ALREADY OWN THE VOLUME ???
JUMPT DELD.0 ;YES,,CAN'T DO THIS
MOVE S1,P1 ;GET THE VSL ADDRESS BACK
PUSHJ P,DELREQ ;DELETE THE REQUEST
$RET ;AND RETURN
DELD.0: MOVE P1,.VSRID(P1) ;PICK UP THE REQUEST ID
DELD.1: $ACK (<Mount request #^D/P1/ does not exist>,,,.MSCOD(M))
$RETT ;RETURN
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
;Routine to delete all pending mount requests
DELALL: MOVE S1,VSLQUE ;GET THE VSL QUEUE ID
PUSHJ P,L%FIRST ;GET THE FIRST
JRST DELA.2 ;JUMP THE FIRST TIME THROUGH
DELA.1: MOVE S1,VSLQUE ;GET THE VSL QUEUE ID
PUSHJ P,L%NEXT ;GET THE NEXT ENTRY
DELA.2: JUMPF .RETT ;DONE,,RETURN
MOVE P1,S2 ;SAVE THE VSL ADDRESS
LOAD S1,.VSFLG(P1),VS.NMT ;GET THE PSEUDO MOUNTED FLAG BIT
JUMPN S1,DELA.1 ;IF SET,,GET NEXT VSL
MOVE S1,P1 ;GET THE VSL ADDRESS IN S1
PUSHJ P,CHKOWN ;DOES THIS GUY OWN THIS VOLUME ???
JUMPT DELA.1 ;YES,,GET THE NEXT VSL
MOVE S1,P1 ;NO,,GET THE VSL ADDRESS IN S1
PUSHJ P,DELREQ ;DELETE THE REQUEST
JRST DELA.1 ;AND GO GET ANOTHER
;Routine to delete all requests for a specific structure
DELSTR: HRROI S1,0(S1) ;GET THE STRUCTURE NAME
PUSHJ P,S%SIXB ;CONVERT IT TO SIXBIT
MOVEM S2,MDAOBJ+OBJ.UN ;SAVE IT
MOVE S1,S2 ;GET IT IN S1
PUSHJ P,D$FNDV ;LOCATE IT
JUMPF E$NSD## ;NOT THERE,,RETURN NO SUCH DEVICE
MOVE P1,S1 ;SAVE THE VOL ADDRESS
SETZM P3 ;CLEAR REQUEST DELETION COUNTER
DELS.1: LOAD P2,.VLOWN(P1),VL.CNT ;GET THE REQUESTOR COUNT
JUMPE P2,DELS.3 ;NO MORE,,FINISH UP
MOVNS P2 ;NEGATE IT
MOVSS P2 ;MOVE RIGHT TO LEFT
HRRI P2,.VLVSL(P1) ;CREATE AOBJN SEARCH AC
DELS.2: MOVE S1,0(P2) ;GET A REQUESTED VSL
TXNN S1,VL.ASN+VL.ASK ;ASSIGNED OR REQUESTED ???
JRST [PUSHJ P,DELREQ ;NO,,DELETE IT !!!
AOS P3 ;BUMP DELETION COUNTER
JRST DELS.1 ] ;START OVER
AOBJN P2,DELS.2 ;TRY NEXT REQUESTOR
DELS.3: JUMPN P3,.RETT ;DELETED SOME,,RETURN
$ACK (No requests for this structure deleted,,MDAOBJ,.MSCOD(M))
$RETT ;RETURN
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
;Routine to delete the VSL pointed to by S1
DELREQ: PUSHJ P,.SAVE1 ;SAVE P1
MOVEI P1,(S1) ;SAVE THE VSL ADDRESS
MOVE AP,.VSMDR(P1) ;SETUP THE MDR ADDRESS
DOSCHD ;FORCE A SCHEDEULING PASS
PUSH P,T1 ;SAVE T1
MOVE T1,P1 ;COPY VSL ADDRESS
MOVEI S2,DEMOB ;ASSUME A PSEUDO-PROCESS
LOAD S1,.MRJOB(AP),MR.JOB ;GET THE PROCESS JOB NUMBER
TXC S1,BA%JOB ;SWAP REQUEST STATES
TXNE S1,BA%JOB ;IS THIS A REAL REQUEST ???
MOVEI S2,DEMOT ;NO--NORMAL TIMESHARING
$ACK (<Mount request #^D/.VSRID(P1)/ cancelled>,<^I/(S2)/^M^JVolume-set-name: ^T/.VSVSN(P1)/>,,.MSCOD(M))
POP P,T1 ;RESTORE T1
PUSHJ P,MDASBP ;SET UP FOR CALLS TO MDADBP
;**;[1162] Insert 3 lines after DELREQ+11L. 29-Nov-83 /LWS
MOVE S1,.VSFLG(P1) ;[1162] GET VSL FLAGS
TXNE S1,VS.VSW ;[1162] SWITCHING VOLUMES?
JRST DELVSW ;[1162] YES,,PROCESS DIFFERENTLY !!!
$TEXT (MDADBP,<Mount request ^T/.VSVSN(P1)/ canceled by the operator^A>)
SKIPE P4 ;NO REASON,,SKIP
$TEXT (MDADBP,<^M^JReason:^T/0(P4)/^A>) ;ADD THE REASON
SETZM S1 ;GET A NULL BYTE
IDPB S1,MDBPTR ;MAKE THE MESSAGE TEXT ASCIZ
SETOM ERRACK ;INDICATE THIS IS AN ERROR ACK
MOVE S1,P1 ;[1173] GET VSL ADDRESS
SETOM S2 ;[1173] USE MDR ACK DATA IF VALID
PUSHJ P,USRNOT ;TELL THE SAD STORY TO THE USER
MOVE S1,.VSFLG(P1) ;[1164] GET VSL FLAGS
TXNN S1,VS.INI ;[1164] REINIT'ING?
JRST DELR.0 ;[1164] NO,,CONTINUE
MOVE S1,.VSVOL(P1) ;[1164] YES,,GET ADDR OF 1ST VOL BLOCK
MOVE TF,S1 ;[1164] SAVE VOL BLOCK ADDR
SKIPN S1,.VLUCB(S1) ;[1164] GET UCB BLOCK ADDR
JRST DELR.0 ;[1164] NOT THERE,,OH WELL
MOVX S2,UC.INI ;[1164] GET UCB INI STATUS BIT
ANDCAM S2,.UCBST(S1) ;[1164] CLEAR THE BIT
MOVE S1,TF ;[1164] GET VOL BLOCK ADDR BACK
PUSHJ P,VLBREA ;[1164] GO BREAK VOL/UCB LINK
DELR.0: MOVE S1,P1 ;[1164] GET THE VSL ADDRESS
LOAD P1,.VSLNK(P1),VS.LNK ;GET THIS VSL'S LINK CODE
PUSHJ P,DELVSL ;DELETE THIS REQUEST
LOAD S2,.MRCNT(AP),MR.CNT ;GET THE USERS REQUEST COUNT
JUMPE S2,DELMDR ;NOTHING LEFT,,DELETE THE MDR
MOVNS S2 ;NEGATE IT
MOVSS S2 ;MOVE RIGHT TO LEFT
HRRI S2,.MRVSL(AP) ;CREATE VSL AOBJN SEARCH AC
DELR.1: MOVE S1,0(S2) ;GET A VSL ADDRESS
LOAD TF,.VSLNK(S1),VS.LNK ;GET ITS LINK CODE
CAMN TF,P1 ;DOES IT MATCH THE ONE WE CANCELED ???
PJRST MNTVSL ;YES,,RETRY THE MOUNT
AOBJN S2,DELR.1 ;NO,,TRY NEXT VSL
$RETT ;AND RETURN
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
;Here if user was switching volumes
;S1 = VSL flag bits !!!
DELVSW: $SAVE <T1,T2> ;[1162] SAVE T1 AND T2
MOVE T1,S1 ;[1162] COPY VSL FLAGS
TXNN S1,VS.ALB ;[1162] IS PULSAR THE ONE?
SKIPA S2,[[ASCIZ\operator\]] ;[1162] NO,,OPERATOR IS CANCELING
MOVEI S2,[ASCIZ\tape labeler\];[1162] YES,,GET CORRECT STRING ADDRESS
TXZ S1,VS.VSW!VS.ALB ;[1162] NOT SWITCHING VOLS ANYMORE
TXO S1,VS.ABO ;[1162] WE'RE NOW ABORTED
MOVEM S1,.VSFLG(P1) ;[1162] UPDATE FLAGS
$TEXT (MDADBP,<Volume switch request ^T/.VSVSN(P1)/ canceled by the ^T/(S2)/^A>) ;[1162]
SKIPE P4 ;NO REASON,,SKIP
$TEXT (MDADBP,<^M^JReason:^T/0(P4)/^A>) ;ADD THE REASON
SETZM S1 ;GET A NULL BYTE
IDPB S1,MDBPTR ;MAKE THE MESSAGE TEXT ASCIZ
SETOM ERRACK ;INDICATE THIS IS AN ERROR ACK
MOVE S1,P1 ;[1173] GET VSL ADDRESS
SETZM S2 ;[1173] USE VSL ACK DATA
PUSHJ P,USRNOT ;TELL THE SAD STORY TO THE USER
MOVE S1,.VSUCB(P1) ;GET THE UNIT HE CURRENTLY OWNS
MOVX S2,UC.VSW ;GET UNIT VOL SWITCH STATUS
ANDCAM S2,.UCBST(S1) ;CLEAR IT
TXNE T1,VS.ALB ;[1162] ABORTED BY PULSAR?
JRST DEL.V1 ;[1162] YES,,ALREADY OUT OF 'EW'
MOVX S2,%VABT ;GET 'CANCELLED' STATUS
PUSHJ P,VSREOV ;GET USER OUT OF 'EW'
DEL.V1: LOAD T1,.VSCVL(P1),VS.OFF ;[1162] GET OFFSET TO VOL HE CAN'T HAVE
LOAD T2,.VSCVL(P1),VS.PRE ;[1162] GET OFFSET TO VOL HE'S KEEPING
STORE T2,.VSCVL(P1),VS.OFF ;[1162] SET CURRENT OFFSET TO PREVIOUS ONE
; Put things back together for tape user is stuck with because of
; volume switch abort.
MOVE S1,P1 ;[1162] GET VSL ADDRESS
PUSHJ P,CHKOWN ;[1162] GET VOL BLOCK POINTER TO VSL ADDR
MOVX S2,VL.ASN ;[1162] GET ASSIGNED BIT
IORM S2,0(S1) ;[1162] INDICATE THE OLD VOL STILL ASSIGNED
PUSHJ P,D$CMTX ;[1162] LOCATE THE GUY'S 'C' MATRIX ENTRY
ADDI T2,.VSVOL(P1) ;[1162] GET ITS VOL BLOCK POINTER ADDR
MOVE S1,(T2) ;[1162] PUT ADDR INTO S1 FOR D$TVSR
PUSHJ P,D$TVRS ;[1162] CONVERT TO RESOURCE NUMBER
MOVE S2,P1 ;[1162] GET VSL ADDRESS
PUSHJ P,ADDAMA ;[1162] PUT VOLUME BACK IN 'A' MATRIX
PUSHJ P,ADDCMA ;[1162] PUT VOLUME BACK IN 'C' MATRIX
; If user was trying to extend volume set make sure "scratch" vol
; block is deleted.
ADDI T1,.VSVOL(P1) ;[1162] POINT AT THE VOL BLOCK ADDR OF TAPE HE CAN'T HAVE
MOVE S2,0(T1) ;[1162] GET THE VOL BLOCK ADDRESS
LOAD S1,.VLFLG(S2),VL.SCR ;[1162] GET SCRATCH BIT
JUMPE S1,.RETT ;[1162] SCRATCH??? NO, RETURN
SETZM 0(T1) ;[1162] YES, ZAP THE VOL BLOCK ADDRESS
DECR .VSCVL(P1),VS.CNT ;SUBTRACT 1 FROM VOLUME COUNT
MOVE S1,VOLQUE ;GET THE VOL QUEUE ID
PUSHJ P,L%APOS ;POSITION TO THE VOL BLOCK
PUSHJ P,L%DENT ;AND DELETE IT
$RETT ;RETURN
>;END TOPS10
SUBTTL D$SMDA - Set tape drive un/available/ initialize
;CALL: M/ The message Address
;
;RET: True Always
TOPS10<
D$SMDA::$SAVE <P1,P2> ;SAVE SOME SPACE
MOVX S1,.TAPDV ;CODE TO FIND A TAPE DEVICE BLOCK
PUSHJ P,A$FNDB## ;FIND THAT IN THE MESSAGE
JUMPF E$IMO## ;CAN'T THAT'S AN ERROR
MOVE P2,S1 ;SAVE ADDR OF ASCII DEVICE NAME
SETZM P1 ;ASSUME WE ARE 'SET AVAILABLE'
MOVX S1,.DVAVL ;CODE FOR SET AVAILABLE
PUSHJ P,A$FNDB## ;TRY TO FIND THAT ONE
JUMPT STAP.1 ;SET AVAILABLE.. GO DO IT
MOVEI P1,1 ;MAKE IT 'SET UNAVAILABLE'
MOVX S1,.DVUAV ;CODE FOR SET UNAVAILABLE
PUSHJ P,A$FNDB## ;TRY FOR THAT ONE
JUMPF STAP.3 ;NEITHER OF THOSE, PERHAPS INITIALIZE
;Here to set unavailable
MOVE S1,P2 ;GET BACK ADDR OF ASCII DEV NAME
PUSHJ P,FNDUCB ;FIND THE AVAILABLE UCB
JUMPF .RETF ;CAN'T... GO AWAY AND COMPLAIN
MOVE P2,S1 ;FOUND THE UCB.. SAVE IT
SKIPE S1,.UCBVS(P2) ;ANY OWNERS FOR THIS UNIT ???
$ERJMP MD$VAU,S1 ;YES,,CAN THE REQUEST
MOVEI S1,[ITEXT (<Drive is currently initializing>)] ;[1472]
LOAD S2,.UCBST(P2),UC.INI ;[1472] GET THE INIT BIT FOR THIS DRIVE
JUMPN S2,STAP.E ;[1472] IF INITIALIZING, CAN'T SET UNAVAILABLE
MOVE S1,P2 ;[1472] GET THE UCB ADDRESS IN S1
PUSHJ P,D$DECA ;[1472] DECREMENT THE 'A' MATRIX
PUSHJ P,DEADLK ;[1472] CHECK WITH DEADLOCK AVOIDANCE ROUTINE
JUMPT STAP.0 ;[1472] IF OK, CONTINUE ON
$WTO (<^T/BELLS/Potential system deadlock detected>,<Cannot set unit ^W/.UCBNM(P2)/ unavailable>,,<$WTFLG(WT.SJI)>) ;[1472]
MOVE S1,P2 ;[1472] GET UCB ADDRESS AGAIN
PUSHJ P,D$INCA ;[1472] MAKE RESOURCE COUNT CORRECT
PUSHJ P,DEADLK ;[1472] LET'S BE PARANOID
$RETIT
STOPCD (UDL,HALT,,<Undeserved deadlock in D$SMDA>) ;[1472]
STAP.0: SKIPE S1,.UCBVL(P2) ;[1472] AIM AT THE VOLUME
PUSHJ P,VLBREA ;DELINK THIS VOLUME
MOVE S1,.UCBNM(P2) ;GET THE UNIT NAME
PUSHJ P,I$MDAC## ;CLEAR DVCMDA MONITOR BIT
MOVX S2,UC.AVA ;GET AVAILABLE BITS
ANDCAM S2,.UCBST(P2) ;CLEAR IT
MOVEI S1,[ITEXT (< Unavailable for use >)]
PJRST STAP.E ;[1472] ACK THE OPR
;Here to set available
STAP.1: MOVE S1,P2 ;GET BACK ADDR OF ASCII DEVICE NAME
PUSHJ P,LOCUCB ;FIND UCB, UNAVAILABLE OR NOT
JUMPF .RETF ;COULDN'T... MUST BE BAD DEVICE
MOVE P2,S1 ;FOUND IT.. SAVE ADDR OF UCB
LOAD S2,.UCBST(P2),UC.AVA ;GET THE AVAILABLE BIT
JUMPN S2,[MOVEI S1,[ITEXT (< Already available for use >)]
PJRST STAP.E ] ;ALREADY AVAILABLE,,TELL OPR AND RETURN
PUSHJ P,I$GATR## ;GET THE DEVICE ATTRIBUTES
LOAD S2,.UCBST(P2),UC.AVA ;GET THE AVAILABLE BIT
JUMPE S2,STAP.6 ;SET AVAILABLE LOST,,COMPLAIN AND QUIT
MOVEI S1,[ITEXT (< Available for use >)]
PUSHJ P,STAP.E ;TELL THE OPR
MOVE S1,.UCBNM(P2) ;GET THE UNIT NAME
MOVX S2,UC.AVR ;GET THE AVR BIT
TDNE S2,.UCBST(P2) ;NEED TO KICK PULSAR FOR AVR ???
PUSHJ P,SNDREC ;YES,,SEND A RECOGNIZE MSG TO PULSAR
MOVE S1,P2 ;GET THE UCB ADDRESS IN S1
PUSHJ P,D$INCA ;INCRIMENT THE 'A' MATRIX
$RETT ;RETURN
;Here to see if it is a SET TAP x INITIALIZE
STAP.3: MOVX S1,.DVINI ;GET BLOCK TYPE - INTIALIZE
PUSHJ P,A$FNDB## ;TRY FOR THAT BLOCK
JUMPF E$IMO## ;CAN'T, SO COMPLAIN
MOVE S1,P2 ;GET BACK ADRS OF DRIVE NAME
PUSHJ P,FNDUCB ;FIND THIS GUY'S DATA BASE
JUMPF .POPJ ;NOT THERE??!! OH WELL
MOVE P2,S1 ;SAVE ADRS OF UCB
MOVX S1,.SIABO ;GET BLOCK TYPE - /ABORT
PUSHJ P,A$FNDB## ;TRY FOR THAT BLOCK
JUMPT STAP.5 ;FOUND IT,,ABORT THE INITIALIZATION
MOVEI S1,[ITEXT (<Already initializing>)]
MOVE S2,.UCBST(P2) ;GET DRIVE STATUS
TXNE S2,UC.INI ;ALREADY BEEN HERE?
JRST STAP.E ;YES, TELL THE OPR THAT
MOVEI S1,[ITEXT (<Unavailable for initialization>)]
TXNN S2,UC.AVA ;IS DRIVE SET UNAVAILABLE?
JRST STAP.E ;TELL THE OPR THE BAD NEWS
MOVX S1,UC.VSW ;GET THE VOLUME SWITCH STATE BIT
TDNN S1,.UCBST(P2) ;IF SWITCHING REELS,,LETERRIP !!
SKIPN S1,.UCBVL(P2) ;GET ADRS OF LOADED VOL BLOCK
JRST STAP.4 ;NO VOL BLOCK, DO THE INITIALIZE
PUSHJ P,FNDOWN ;FIND THIS VOL'S OWNER
SKIPF ;SKIP IF UNOWNED
$ERJMP MD$VAU ;THERE IS ONE! CAN'T INIT THAT TAPE
MOVE S1,.UCBVL(P2) ;NO OWNER, AIM AT VOL BLOCK AGAIN
PUSHJ P,VLBREA ;BREAK THIS VOL - UCB LINK
STAP.4: MOVX S1,UC.INI ;GET THE INITIALIZING BIT
IORM S1,.UCBST(P2) ;LITE SO OTHERS WILL SEE
PJRST I$FPLR## ;LET PULSAR DO THE WORK
;Here for /ABORT processing
STAP.5: MOVX S1,UC.INI ;GET THE INITIALIZATION BIT
ANDCAM S1,.UCBST(P2) ;CLEAR IT
PJRST I$FPLR## ;TELL PULSAR NOT TO CONTINUE
;Here for could not set available
STAP.6: MOVE S1,.UCBNM(P2) ;GET THE DEVICE NAME
PUSHJ P,I$GOWN## ;TRY TO FIND THE OWNER
MOVEI P1,(S1) ;SAVE THE NUMBER IF ANY
MOVEI S1,[ITEXT (<Could not set device available for use>)]
MOVEI S2,[ITEXT (<Device ^W/.UCBNM(P2)/ already owned by job ^D/P1/>)]
SKIPT ;IF OWNED,,GO FINISH UP
MOVEI S2,[ITEXT (<No such device or error determining owning job number>)]
$ACK (<^I/0(S1)/>,<^I/0(S2)/>,MDAOBJ,.MSCOD(M))
$RETT
STAP.E: $ACK (<^I/0(S1)/>,,MDAOBJ,.MSCOD(M))
$RETT ;RETURN
>;END TOPS10
SUBTTL D$VSR - VOLUME SWITCH REQUEST FROM PULSAR
;CALL: M/ The VSR Message Address
;
;RET: True Always
TOPS10<
D$VSR:: PUSHJ P,.SAVE4 ;SAVE SOME AC'S FOR A MINUTE
MOVX S1,.RECDV ;GET THE DEVICE BLOCK TYPE
PUSHJ P,A$FNDB## ;FIND IT IN THE MESSAGE
JUMPF MISC.3 ;NOT THERE,,PULSAR MESSAGE ERROR
MOVE S1,0(S1) ;GET THE SIXBIT DEVICE NAME
PUSHJ P,UCBFND ;FIND ITS UCB ENTRY
JUMPF .RETF ;NOT THERE,,JUST RETURN
MOVE P1,S1 ;SAVE THE UCB ADDRESS
SKIPN P2,.UCBVS(P1) ;GET THE OWNERS VSL ADDRESS
PJRST [MOVE S1,P1 ;NONE,,THATS WIERD !!!
MOVX S2,%VTMV ; GET 'TOO MANY VOLUMES' STATUS
PJRST VSREOV ] ; END EXIT THROUGH VSREOV
MOVE AP,.VSMDR(P2) ;GET THE OWNER MDR ADDRESS
;**;[1133]ADD 6 LINES AFTER D$VSR:+12 LINES 2-JUN-83/CTK
MOVE S1,.UCBNM(P1) ;[1133]GET TAPE DRIVE NAME
PUSHJ P,I$GDEN## ;[1133]READ DENSITY
JUMPF VSR.T1 ;[1133]FAILED!!!
STORE S2,.VSATR(P2),VS.DEN ;[1133]AND STORE
MOVE T1,.UCBVL(P1) ;[1133]GET VL POINTER
STORE S2,.VLFLG(T1),VL.DEN ;[1133]AND STORE
VSR.T1: MOVX S1,.RLVOL ;[1133]GET RELATIVE VOLUME BLOCK TYPE
PUSHJ P,A$FNDB## ;FIND IT IN OUR MESSAGE
JUMPF MISC.3 ;NOT THERE,,ANOTHER PULSAR ERROR
MOVE S2,0(S1) ;GET THE BLOCK DATA IN S2
SETZM P4 ;DEFAULT TO READING THE VOLUME SET
TXNE S2,%VWRT ;IS HE WRITING THE VOLUME SET ???
SETOM P4 ;YES,,INDICATE WRITING VOLUME
LOAD S2,S2,RLV.CD ;GET THE OFFSET CODE FOR THE NEXT VOLUME
;**;[1162] Redo code after D$VSR+18L (approx). 29-Nov-83 /LWS
CAXE S2,%RLABO ;[1162] SHOULD WE ABORT THE SWITCH?
JRST VSR.T2 ;[1162] NO...
MOVX S1,VS.ALB ;[1162] YES,,GET ABORTED BY TAPE LBLR BIT
IORM S1,.VSFLG(P2) ;[1162] LITE IT IN VSL FLAG WORD
SETZM P4 ;[1162] NO REASON
MOVE S1,P2 ;[1162] GET VSL ADDRESS
PJRST DELREQ ;[1162] GO DELETE VOLUME SWITCH
VSR.T2: LOAD T1,.VSCVL(P2),VS.OFF ;[1162] GET THE OFFSET TO THE CURRENT VOLUME
MOVE P3,T1 ;[1162] WILL BE USED AS PREVIOUS LATER
CAXN S2,%RLNXT ;DO WE WANT THE NEXT VOLUME ???
ADDI T1,1 ;YES,,BUMP OFFSET BY 1
CAXN S2,%RLPRV ;DO WE WANT THE PREVIOUS VOLUME ???
SUBI T1,1 ;YES,,DECRIMENT OFFSET BY 1
CAXN S2,%RLFIR ;DO WE WANT THE FIRST VOLUME ???
SETZM T1 ;YES,,OFFSET IS 0
SKIPGE T1 ;OFFSET CAN'T BE NEGATIVE !!
STOPCD (ONV,HALT,,<Offset of new volume is invalid>) ;LEAVE THIS FOR A WHILE
;P4 = -1 Writing Volume Set.
;P4 = 0 Reading Volume Set.
;P4 = 1 Extending Volume Set.
LOAD S2,.VSCVL(P2),VS.CNT ;GET THE VOLUME COUNT IN S2
CAIG T1,-1(S2) ;NEW OFFSET MUST BE LESS OR EQUAL
JRST VSR.0 ;OK,,SKIP THIS
CAILE T1,^D60 ;MORE THEN 60 VOLUMES ???
PJRST [MOVE S1,P1 ;YES,,GET THE UCB ADDRESS IN S1
MOVX S2,%VTMV ;GET 'TOO MANY VOLUMES' STATUS
PJRST VSREOV ] ;END EXIT THROUGH VSREOV
MOVE S1,P1 ;GET THE UCB ADDRESS IN S1
MOVX S2,%VEOF ;GET 'END OF FILE' STATUS
JUMPE P4,VSREOV ;P4=0,,SEND EOV MSG TO PULSAR
MOVEI P4,1 ;SET FLAG INDICATING VOL SET EXTENSION
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
VSR.0: MOVE S1,.UCBNM(P1) ;GET THE DEVICE NAME IN S1
PUSHJ P,REWIND ;REWIND THE LAST VOLUME
;; LOAD S1,.VSFLG(P2),VS.ABO ;GET ABORTED BY OPERATOR STATUS
;; JUMPN S1,VSR.1 ;IF ABORTED,,DON'T DEALLOCATE
;Deallocate the current volume Resource Number
PUSHJ P,D$CMTX ;LOCATE THIS GUYS 'C' MATRIX ENTRY
LOAD S1,.VSCVL(P2),VS.OFF ;GET THE OFFSET TO THE CURRENT VOLUME
ADDI S1,.VSVOL(P2) ;POINT TO ITS ADDRESS
MOVE S1,0(S1) ;GET THE CURRENT VOLUME ADDRESS
PUSHJ P,D$TVRS ;CONVERT TO A VOLUME RESOURCE NUMBER
MOVE S2,P2 ;GET THE VSL ADDRESS IN S2
PUSHJ P,SUBAMA ;REMOVE FROM THE 'A' MATRIX
PUSHJ P,SUBCMA ;REMOVE FROM THE 'C' MATRIX
MOVE S1,P2 ;GET THE VSL ADDRESS
PUSHJ P,CLROWN ;CLEAR OWNERSHIP FLAG
;Update the VSL status
VSR.1: MOVX S1,UC.VSW ;GET THE VOLUME SWITCH STATUS BITS
IORM S1,.UCBST(P1) ;LITE IT IN THE UCB
MOVX S1,VS.VSW ;GET THE VOLUME SWITCH STATUS BITS
IORM S1,.VSFLG(P2) ;LITE IT IN THE VSL
MOVX S1,VS.ABO ;GET ABORT FLAG
ANDCAM S1,.VSFLG(P2) ;CLEAR IT
MOVEM P1,.VSUCB(P2) ;LINK THIS UCB TO THIS VSL
STORE T1,.VSCVL(P2),VS.OFF ;SAVE THE OFFSET TO THE NEW VOLUME
;**;[1162] Insert 1 line at VSR.1+7L . 18-Oct-83 /LWS
STORE P3,.VSCVL(P2),VS.PRE ;[1162]SAVE OFFSET OF PREVIOUS VOL, TOO
JUMPG P4,VSR.2 ;IF EXTENDING VOLUME SET,,SKIP THIS
MOVE S1,P2 ;GET THE VSL ADDRESS
PUSHJ P,MNTVSR ;TRY TO MOUNT THE NEXT VOLUME
$RETT ;WIN OR LOSE, KEEP GOING
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
;Here if we need the next volume in the volume set and there are no
;more volumes in the VSL. If reading the volume set, return EOV. If
;writing the volume set, generate a new VOL block for another volume
;and ask the OPR to mount another volume. Only add volumes up
;to a max of 60, after which send the EOV msg to PULSAR.
VSR.2: MOVE S1,VSLQUE ;GET THE VSL QUEUE ID
MOVE S2,P2 ;GET THE VSL ADDRESS IN S2
PUSHJ P,L%APOS ;POSITION TO THE VSL IN THE QUEUE
PUSHJ P,L%SIZE ;GET THIS VSL'S LENGTH (IN S2)
MOVE P4,S2 ;SAVE THE OLD VSL LENGTH
ADDI S2,1 ;ADD 1 FOR NEW VOL BLOCK
PUSHJ P,L%CENT ;CREATE A NEW VSL FOR THIS GUY
MOVE P3,S2 ;SAVE THE NEW VSL ADDRESS
HRL S2,P2 ;GET OLD VSL ADDR,,NEW VSL ADDR
ADDI P4,-1(P3) ;GET NEW VSL END -1
BLT S2,0(P4) ;COPY OLD VSL TO NEW VSL
MOVE S1,VSLQUE ;GET THE VSL QUEUE ID
MOVE S2,P2 ;GET THE OLD VSL ADDRESS
PUSHJ P,L%APOS ;POSITION TO THE OLD VSL
PUSHJ P,L%DENT ;AND DELETE IT !!!
MOVE AP,.VSMDR(P3) ;GET THE MDR ADDRESS
LOAD S1,.MRCNT(AP),MR.CNT ;GET THE VSL COUNT
MOVNS S1 ;NEGATE IT
MOVSS S1 ;MOVE RIGHT TO LEFT
HRRI S1,.MRVSL(AP) ;CREATE AOBJN FOR VSL LIST
VSR.2A: CAMN P2,0(S1) ;IS THIS THE VSL WE WANT ???
MOVEM P3,0(S1) ;YES,,CHANGE OLD VSL PTR TO NEW VSL
AOBJN S1,VSR.2A ;CHECK AGAIN
LOAD S1,.VSCVL(P3),VS.CNT ;GET THE VOL COUNT FOR THIS VSL
MOVNS S1 ;NEGATE IT
MOVSS S1 ;MOVE RIGHT TO LEFT
HRRI S1,.VSVOL(P3) ;CREATE AOBJN FOR VOL LIST
VSR.3: MOVE P4,0(S1) ;GET FIRST/NEXT VOL ADDRESS IN P4
LOAD S2,.VLOWN(P4),VL.CNT ;GET THE VSL COUNT FOR THIS VOLUME
MOVNS S2 ;NEGATE IT
MOVSS S2 ;MOVE RIGHT TO LEFT
HRRI S2,.VLVSL(P4) ;CREATE AOBJN FOR VSL LIST
VSR.4: CAIN P2,@0(S2) ;IS THIS VOL POINTING AT OLD VSL ???
JRST [HRRM P3,0(S2) ;YES,,POINT IT AT THE NEW VSL
JRST VSR.5 ] ;AND CONTINUE
AOBJN S2,VSR.4 ;CONTINUE THROUGH ALL VSL'S
VSR.5: AOBJN S1,VSR.3 ;CONTINUE THROUGH ALL VOL'S
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
MOVE S1,.VSUCB(P3) ;GET THE DEVICE THIS GUY OWNS
MOVEM P3,.UCBVS(S1) ;AND POINT IT AT THE OWNERS NEW VSL
MOVE S1,P3 ;GET OUR VSL ADDRESS
PUSHJ P,GENVOL ;CREATE A 'SCRATCH' VOL BLOCK
LOAD S1,.VSFLG(P3),VS.WLK ;GET THE WRITE LOCKED BIT
LOAD S2,.VSFLG(P3),VS.LBT ;GET THE LABEL TYPE
LOAD P1,.VSATR(P3),VS.TRK ;GET THE TRACK STATUS
LOAD P2,.VSATR(P3),VS.DEN ;GET THE REQUESTED DENSITY
$WTO (<Magtape mount request #^D/.VSRID(P3)/>,<^I/DEMOT/^M^JVolume-set-name: ^T/.VSVSN(P3)/^T/MTAHDR/Scratch ^T9/@WRTENA(S1)/^T9/@LABELS(S2)/^W6/TRK(P1)/^T/@DENSTY(P2)/^T/BELLS/>,,<$WTFLG(WT.SJI)>)
$RETT ;NOTIFY THE OPERATOR AND RETURN
>
SUBTTL D$XVSL - Extend a VSL
; Routine to extend a VSL
; Call: MOVE S1, VSL address
; MOVE S2, number of volumes to be added
; PUSHJ P,D$XVSL
;
; TRUE return: VSL extended and volumes added, S1 points to new VSL
; FALSE return: VSL extension failed for some reason
D$XVSL::PUSHJ P,.SAVE4 ;SAVE SOME ACS
DMOVE P1,S1 ;COPY ARGUMENTS
MOVE S1,VSLQUE ;GET THE VSL QUEUE ID
MOVE S2,P1 ;GET THE OLD VSL ADDRESS
PUSHJ P,L%APOS ;POSITION TO THE OLD VSL IN THE QUEUE
PUSHJ P,L%SIZE ;GET THE LENGTH OF THE OLD VSL
MOVE P4,S2 ;SAVE THE OLD VSL LENGTH
ADDI S2,(P2) ;PLUS THE NUMBER OF NEW VOL BLOCKS
PUSHJ P,L%CENT ;CREATE A NEW VSL
MOVE P3,S2 ;SAVE THE NEW VSL ADDRESS
HRL S2,P1 ;GET OLD VSL ADDR,,NEW VSL ADDR
ADDI P4,-1(P3) ;GET NEW VSL END -1
BLT S2,0(P4) ;COPY OLD VSL TO NEW VSL
MOVE S1,VSLQUE ;GET THE VSL QUEUE ID
MOVE S2,P1 ;GET THE OLD VSL ADDRESS
PUSHJ P,L%APOS ;POSITION TO THE OLD VSL
PUSHJ P,L%DENT ;AND DELETE IT !!!
; Here to fix up all MDR/VSL/VOL links
; The following ACs are setup:
; P1 = old VSL address
; P2 = number of new VOL blocks to create
; P3 = new VSL address
; P4 = scratch AC
MOVE S1,MDRQUE ;GET MDR QUEUE ID
PUSHJ P,L%FIRS ;FIND THE FIRST MDR
JRST XVSL.2 ;ENTER MDR LOOP
XVSL.1: MOVE S1,MDRQUE ;GET MDR QUEUE ID
PUSHJ P,L%NEXT ;FIND THE NEXT ENTRY
XVSL.2: JUMPF XVSL.4 ;ALMOST DONE IF NO MORE MDRS
LOAD S1,.MRCNT(S2),MR.CNT ;GET THE VSL COUNT
MOVNS S1 ;NEGATE IT
MOVSS S1 ;MOVE RIGHT TO LEFT
HRRI S1,.MRVSL(S2) ;CREATE AOBJN FOR VSL LIST
XVSL.3: CAMN P1,0(S1) ;FOUND THE OLD VSL?
MOVEM P3,0(S1) ;YES--REPLACE WITH NEW VSL ADDRESS
AOBJN S1,XVSL.3 ;LOOP THROUGH ALL VSLS FOR THIS MDR
JRST XVSL.1 ;GO DO ANOTHER MDR
XVSL.4: LOAD S1,.VSCVL(P3),VS.CNT ;GET THE VOL COUNT FOR THIS VSL
MOVNS S1 ;NEGATE IT
MOVSS S1 ;MOVE RIGHT TO LEFT
HRRI S1,.VSVOL(P3) ;CREATE AOBJN FOR VOL LIST
XVSL.5: MOVE P4,0(S1) ;GET FIRST/NEXT VOL ADDRESS IN P4
LOAD S2,.VLOWN(P4),VL.CNT ;GET THE VSL COUNT FOR THIS VOLUME
MOVNS S2 ;NEGATE IT
MOVSS S2 ;MOVE RIGHT TO LEFT
HRRI S2,.VLVSL(P4) ;CREATE AOBJN FOR VSL LIST
XVSL.6: CAIN P1,@0(S2) ;IS THIS VOL POINTING AT OLD VSL?
JRST XVSL.7 ;YES
AOBJN S2,XVSL.6 ;CONTINUE THROUGH ALL VSLS
JRST XVSL.8 ;ONWARD
XVSL.7: HRRM P3,(S2) ;POINT VOL AT THE NEW VSL
XVSL.8: AOBJN S1,XVSL.5 ;CONTINUE THROUGH ALL VOLS
XVSL.9: MOVE S1,VOLQUE ;GET THE VOLUME LIST QUEUE ID
MOVX S2,VOLLEN ;GET THE VOL ENTRY LENGTH
PUSHJ P,L%CENT ;CREATE SPACE FOR THE VOL ENTRY
LOAD S1,.VSCVL(P3),VS.CNT ;GET NUMBER OF VOLUMES SO FAR
ADDI S1,1 ;PLUS ONE
STORE S1,.VSCVL(P3),VS.CNT ;UPDATE
ADDI S1,.VSVOL-1(P3) ;POINT TO THE VOL BLOCK ADDRESS
MOVEM S2,0(S1) ;LINK THE VOL TO THE VSL
MOVEM P3,.VLVSL(S2) ;LINK THE VSL TO THE VOL
MOVX S1,%STAWT ;GET 'WAITING' STATUS CODE
STORE S1,.VLFLG(S2),VL.STA ;SAVE IT IN THE VOL FLAG WORD
MOVEI S1,1 ;ONE OWNER
STORE S1,.VLOWN(S2),VL.CNT ;SET COUNT IN VOL
SOJG P2,XVSL.9 ;CREATE THE REQUESTED NUMBER OF VOLS
MOVE S1,P3 ;RETURN THE NEW VSL ADDRESS IN S1
$RETT ;RETURN
SUBTTL D$DVS - DISMOUNT/DEALLOCATE VOLUME SET PROCESSOR
;CALL: M/ The message Address
;
;RET: True Always
TOPS10 <
D$DVS:: SKIPN G$MDA## ;IS MDA SUPPORTED ???
JRST E$MDA## ;NO,,RETURN AN ERROR !!!
PUSHJ P,.SAVE3 ;SAVE P1 - P3
LOAD S1,G$PRVS##,MR.JOB ;GET THE SENDERS JOB NUMBER
PUSHJ P,FNDMDR ;FIND HIS MDR
JUMPF E$SDY## ;NOT THERE,,THATS AN ERROR
MOVE S1,G$SND## ;GET THIS USERS PID
MOVEM S1,.MRPID(AP) ;SAVE IT FOR THE ACK
MOVE S1,.MSCOD(M) ;GET THE SENDERS ACK CODE
MOVEM S1,.MRACK(AP) ;SAVE IT
SETZM S1 ;NO GENERAL ACK
STORE S1,.MRFLG(AP),MR.ACK ;SO CLEAR ACK FLAG BIT
;**;[1170] Insert 1 line after D$DVS+11L. 29-Dec-83 /LWS
STORE S1,.MRFLG(AP),MR.GFR ;[1170] CLEAR [SYSTEM]GOPHER BIT (CLEAN UP)
LOAD S1,.OFLAG(M),MM.WAT ;GET 'WAITING' FLAG BIT
STORE S1,.MRFLG(AP),MR.WAT ;SET/CLEAR IT
LOAD S1,.OFLAG(M),MM.NOT ;GET 'NOTIFY' FLAG BIT
STORE S1,.MRFLG(AP),MR.NOT ;SET/CLEAR IT
LOAD P3,.OFLAG(M),MM.DLC ;SET DISMOUNT(0)/DEALLOCATE(1)
SETZM STRVOL ;CLEAR VSL PROCESSED FLAG
SETZM G$MSG ;CLEAR THE MDA BUFFER
MOVX S1,.RECDV ;GET THE DEVICE NAME BLOCK TYPE
PUSHJ P,A$FNDB## ;FIND IT IN THE MESSAGE
JUMPT DVS.3 ;FOUND IT,,GO PROCESS IT
MOVX S1,.RCTVS ;GET THE VOLUME SET NAME BLOCK TYPE
PUSHJ P,A$FNDB## ;FIND IT IN THE MESSAGE
JUMPF E$IFD## ;NOT THERE,,THATS AN ERROR
DVS.1: MOVE P2,S1 ;SAVE THE VOLUME SET NAME ADDRESS
;Here if he passed a Volume Set Name
DVS.2: PUSHJ P,FNDLNM ;LOOK FOR A VSL WITH THAT LOGICAL NAME
JUMPT DVS.5 ;FOUND IT,,GO PROCESS THE VSL
MOVE S1,P2 ;NOT FOUND,,POINT TO ASCIZ VOL SET NAME
PUSHJ P,FNDVSN ;LOOK FOR THE VSL WITH THIS NAME
JUMPT DVS.5 ;FOUND IT,,GO PROCESS THIS VSL
JRST E$IVN## ;RETURN INVALID VOL SET NAME SPECIFIED
;Here if he passed a device name
DVS.3: MOVE P2,0(S1) ;SAVE THE DEVICE NAME
MOVE S1,P2 ;GET THE SIXBIT DEVICE NAME IN S1
PUSHJ P,UCBFND ;GET THE UCB FOR THIS DEVICE
JUMPF DVS.4 ;NOT THERE,,TRY VOL SET/LOGICAL NAME
MOVE P1,S1 ;SAVE THE UCB ADDRESS
SKIPE S1,.UCBVS(P1) ;CHECK AND LOAD THE OWNING VSL ADDRESS
CAME AP,.VSMDR(S1) ;DOES HE OWN THE DEVICE ???
JRST E$SDY## ;SPECIFIED DEVICE IS NOT HIS !!!
PJRST DVS.5 ;HE OWNS THE DEVICE,,PROCESS THE VSL
;CONTINUED ON THE NEXT PAGE
DVS.4: $TEXT (<-1,,TMPVSL>,<^W/P2/^0>) ;NO,,GEN ASCIZ VOL SET NAME
MOVEI S1,TMPVSL ;POINT TO THE VOL SET NAME
JRST DVS.1 ;AND TRY TO FIND A VOL SET BY THAT NAME
;Here to process the VSL whose address is in S1.
DVS.5: MOVE P1,S1 ;SAVE THE VSL ADDRESS
SETZM G$ACK## ;DO NOT ACK TWICE !!!
PUSHJ P,MDR2VS ;[1173] COPY VSL REQUEST DEPENDENT DATA
SKIPN S1,.VSUCB(P1) ;CHECK AND LOAD THE UNIT ADDRESS
JRST DVS.6 ;NOT THERE,,CONTINUE ON
LOAD S2,.UCBST(S1),UC.DVT ;GET THE DEVICE TYPE
CAXE S2,%DISK ;IS IT A STRUCTURE ???
JRST DVS.7 ;NO,,THATS AN ERROR
MOVE S1,P1 ;GET THE VSL ADDRESS
MOVX S2,VS.ARD ;GET THE ALWAYS RECOMPUTE BIT
ANDCAM S2,.VSFLG(S1) ;CLEAR IT
MOVE S2,.VSVOL(S1) ;GET THE VOLUME BLOCK ADDRESS
PUSHJ P,DSLMSG ;GEN 'DELETE FROM SEARCH LIST' & SEND IT
SKIPE P3 ;IS THIS A DEALLOCATE ???
ZERO .VSFLG(P1),VS.UAL ;YES,,ZAP THE USER ALLOCATE FLAG
LOAD S1,.OFLAG(M),MM.REM ;GET REMOVE STR FLAG BIT
STORE S1,.VSFLG(P1),VS.REM ;SET/CLEAR IT
$RETT ;WAIT FOR PULSAR ACK !!!
DVS.6: JUMPE P3,DVS.6A ;IF DISMOUNT,,THATS AN ERROR
$TEXT (<-1,,G$MSG>,<Volume set ^T/.VSVSN(P1)/ has been Deallocated^M^J^0>)
MOVE S1,P1 ;[1173] GET VSL ADDRESS
SETOM S2 ;[1173] USE MDR ACK DATA IF VALID
PUSHJ P,USRNOT ;ACK THE USER
MOVE S1,P1 ;GET THE VSL ADDRESS
LOAD S2,.OFLAG(M),MM.REM ;GET /REMOVE STR FLAG BIT
SKIPE S2 ;DID USER SPECIFY /REMOVE ???
PUSHJ P,TELREM ;YES,,TELL THE OPERATOR
LOAD S1,.VSFLG(P1),VS.ALC ;WERE WE JUST ALLOCATED ???
SKIPN S1 ;YES,,DON'T BOTHER THE OPERATOR
$WTO (<Mount Request #^D/.VSRID(P1)/ cancelled by user>,< ^I/DEMOT/^M^J Volume-set-name: ^T/.VSVSN(P1)/>,,<$WTFLG(WT.SJI)>)
MOVE S1,P1 ;GET THE VSL ADDRESS
PUSHJ P,DELVSL ;DEALLOCATE/DELETE THIS VOLUME SET
LOAD S1,.MRCNT(AP),MR.CNT ;GET THE VSL COUNT
JUMPE S1,DELMDR ;NO MORE,,DELETE THE MDR AND RETURN
$RETT ;ELSE RETURN
DVS.6A: $TEXT (<-1,,G$MSG>,<Volume set ^T/.VSVSN(P1)/ is not Mounted^M^J^0>)
SETOM ERRACK ;INDICATE THIS IS AN ERROR
MOVE S1,P1 ;[1173] GET VSL ADDRESS
SETOM S2 ;[1173] USE MDR ACK DATA IF VALID
PUSHJ P,USRNOT ;TELL THE USER
$RETT ;AND RETURN
DVS.7: MOVEI S2,[ASCIZ/Dismount/] ;DEFAULT TO A DISMOUNT
SKIPE P3 ;UNLESS IT IS DEALLOCATE
MOVEI S2,[ASCIZ/Deallocate/] ; THEN MAKE IT DEALLOCATE
$TEXT (<-1,,G$MSG>,<Can't ^T/0(S2)/ volume set ^T/.VSVSN(P1)/^M^J Unit ^W/.UCBNM(S1)/ must be deassigned^M^J^0>)
SETOM ERRACK ;THIS IS AN ERROR
MOVE S1,P1 ;[1173] GET VSL ADDRESS
SETOM S2 ;[1173] USE MDR ACK DATA IF VALID
PUSHJ P,USRNOT ;TELL THE USER
$RETT ;AND RETURN
>
SUBTTL D$ACK - ROUTINE TO PROCESS MDA ACK MESSAGES
;CALL: M/ The ACK Message Address
;
;RET: True Always
TOPS10 <
D$ACK:: MOVX S1,.RCTVS ;GET VOL SET NAME BLOCK TYPE
PUSHJ P,A$FNDB## ;FIND IT IN OUR MESSAGE
JUMPF MISC.3 ;NOT THERE,,THATS AN ERROR
HRROI S1,0(S1) ;GET POINTER TO ASCIZ VOL SET NAME
PUSHJ P,S%SIXB ;CONVERT IT TO SIXBIT
MOVE S1,S2 ;GET STRUCTURE NAME IN S1
PUSHJ P,FNDISK ;FIND ITS VOL BLOCK ADDRESS
JUMPF .RETT ;NOT THERE,,RETURN
LOAD S2,.MSFLG(M),AK.TYP ;GET THE ACK TYPE
CAILE S2,ACKLEN ;VALIDATE IT
SETZM S2 ;NO GOOD,,ZERO IT
PJRST @ACKDSP(S2) ;DISPATCH OFF TO PROCESS THE ACK
ACKDSP: EXP MISC.3 ;ACK TYPE 0 IS INVALID
EXP MNTACK ;ACK TYPE 1 IS MOUNT ACK
EXP DSMACK ;ACK TYPE 2 IS DISMOUNT ACK
EXP CATACK ;ACK TYPE 3 IS CATALOG ACK (ERROR ONLY)
EXP ASLACK ;ACK TYPE 4 IS ADD STR TO SRCH LIST ACK
EXP RMSACK ;ACK TYPE 5 REMOVE STR FROM SRCH LIST
EXP MNTOPC ;ACK TYPE 6 IS MOUNT ACK (OWNER PPN CL)
ACKLEN==.-ACKDSP ;DISPATCH TABLE LENGTH
>
SUBTTL Structure mount ACK processing
; Here on ACK types %MOUNT and %MNTOPC
; Call: MOVE S1, primary VOL block address
; PUSHJ P,MNTACK for normal structure mount ACKs
; PUSHJ P,MNTOPC when owner PPN is cleared
;
; TRUE return: always
;
TOPS10 <
MNTACK: TDZA S2,S2 ;INDICATE NORMAL MOUNT ACK
MNTOPC: MOVEI S2,1 ;INDICATE OWNER PPN CLEARED
PUSHJ P,.SAVE1 ;SAVE P1 FOR A MINUTE
MOVE P1,S1 ;SAVE THE VOL BLOCK ADDRESS
LOAD S1,.MSFLG(M),AK.NAK ;IS THIS A NAK ???
JUMPN S1,MNTA.4 ;YES,,OH WELL !!!
MNTA.0: $COUNT (STRM) ;[1217] COUNT # OF SUCCESSFUL STR MOUNTS
MOVX S1,%STAMN ;GET STRUCTURE MOUNTED BIT
STORE S1,.VLFLG(P1),VL.STA ;SAVE IT AS NEW STRUCTURE STATUS
MOVE S1,G$NOW## ;GET THE CURRENT TIME
MOVEM S1,.VLMTM(P1) ;SAVE THE MOUNTED TIME
JUMPE S2,MNTA.3 ;SKIP LOOP IF NORMAL MOUNT ACK
SKIPA S1,P1 ;GET PRIMARY VOL BLOCK ADDRESS
MNTA.1: LOAD S1,.VLPTR(S1),VL.NXT ;GET THE NEXT VOL BLK ADDRESS
JUMPE S1,MNTA.2 ;DONE ALL VOL BLOCKS?
SETZM .VLOID(S1) ;CLEAR OWNER PPN
JRST MNTA.1 ;LOOP FOR ALL VOL BLOCKS
MNTA.2: MOVE S1,.VLNAM(P1) ;GET STR NAME
PUSHJ P,V$STRG## ;CONVERT TO ASCIZ
PUSHJ P,V$FIND## ;GET CATALOG ENTRY
SKIPF ;WE BLEW IT SOMEWHERE - AVOID A MESS
SETZM .CQVUS(S1) ;CLEAR THE OWNER PPN IN THE CATALOG
MNTA.3: MOVEI S1,[ASCIZ ||] ;ASSUME NOT WRITE-LOCKED
MOVX S2,.MTWLK ;GET A BIT TO TEST
TDNE S2,.OFLAG(M) ;WRITE-LOCKED FOR ALL USERS?
MOVEI S1,[ASCIZ |Structure is software write-locked for all users|]
$WTO (<Structure ^W/.VLNAM(P1)/ mounted>,<^T/(S1)/>,,<$WTFLG(WT.SJI)>)
DOSCHD ;FORCE A SCHEDULING PASS
MOVE S1,P1 ;GET THE VOL BLK ADDR IN S1
PUSHJ P,I$STRM## ;PERFORM STRUCTURE ACCOUNTING
MOVE S1,.VLUCB(P1) ;GET THE UCB ADDRESS
PUSHJ P,MATUNI ;TRY TO ASSIGN THE DEVICE
$RETT ;RETURN
MNTA.4: $WTO (<Can't mount structure ^W/.VLNAM(P1)/>,,,<$WTFLG(WT.SJI)>)
MOVE S1,.VLSTR(P1) ;GET THE REAL STRUCTURE NAME
MOVEM S1,.VLNAM(P1) ;AND SAVE IT
MNTA.5: LOAD S1,.VLPTR(P1),VL.NXT ;GET THE NEXT VOL ADDRESS
SETZM .VLPTR(P1) ;CLEAR THE OLD POINTERS
MOVE P1,S1 ;GET THE NEXT VOL ADDRESS IN P1
JUMPN P1,MNTA.5 ;ANOTHER,,RESET IT ALSO
$RETT ;DONE,,RETURN
>
SUBTTL D$RMS - Routine to process the structure removed message
;CALL: M/ The Message address
;
;RET: Through DSMACK (as if from PULSAR)
TOPS10<
D$RMS:: MOVE S1,1(M) ;GET THE STRUCTURE NAME
PUSHJ P,FNDISK ;FIND ITS VOL BLOCK ADDRESS
JUMPF .RETT ;NOT THERE,,RETURN
MOVX S2,VL.REM ;GET THE /REMOVE FLAG BIT
ANDCAM S2,.VLFLG(S1) ;AND CLEAR IT
SETZM .MSFLG(M) ;CLEAR THE FLAG BITS (JUST IN CASE)
PJRST DSMACK ;REALLY CLEAN THINGS UP AND RETURN
>
SUBTTL DSMACK - ROUTINE TO PROCESS DISMOUNT ACKS FROM TAPE LABELER
;CALL: S1/ The VOL Address of the Primary VOL Block
;
;RET: True Always
TOPS10 <
DSMACK: PUSHJ P,.SAVE4 ;SAVE P1 - P4 FOR A MINUTE
MOVE P1,S1 ;SAVE THE VOL BLOCK ADDRESS
LOAD TF,.MSFLG(M),AK.NAK ;IS THIS A NAK ???
JUMPN TF,DSMA.4 ;YES,,OH WELL !!!!
PUSHJ P,DSMOPR ;TELL OPR ITS GONE
MOVE S1,P1 ;GET THE VOL BLK ADDR IN S1
PUSHJ P,I$STRD## ;PERFORM STRUCTURE ACCOUNTING
;Here to clear mounted bits for the structure since its now offline
MOVX S1,%STAWT ;GET 'WAITING' VOLUME STATUS
STORE S1,.VLFLG(P1),VL.STA ;SET IT
LOAD P2,.VLOWN(P1),VL.CNT ;GET THE REQUEST COUNT
JUMPE P2,DSMA.1 ;NO REQUESTORS,,SKIP THIS
$TEXT (<-1,,G$MSG>,<[Structure ^W/.VLNAM(P1)/ dismounted]^0>)
PUSH P,[-1] ;INDICATE END OF VSL QUEUE
MOVNS P2 ;NEGATE THE COUNT
MOVSS P2 ;MOVE RIGHT TO LEFT
HRRI P2,.VLVSL(P1) ;CREATE AOBJN AC TO VSL ADR LIST
PUSH P,0(P2) ;QUEUE UP A VSL ADDRESS
AOBJN P2,.-1 ;CONTINUE FOR ALL REQUESTORS
;Here to update the poor users status since the structure is now gone
DSMA.0: POP P,P3 ;PICK OFF A VSL ADDRESS
CAMN P3,[-1] ;IS THIS THE LAST ???
JRST DSMA.1 ;YES,,CONTINUE ON
TXNN P3,VL.ASN+VL.ASK ;DOES HE HAVE IT MOUNTED ?
JRST DSMA.0 ;NO,,TRY NEXT
LOAD AP,.VSMDR(P3) ;SET UP POINTER TO MDR
MOVE S1,P3 ;[1173] GET VSL ADDRESS
SETZM S2 ;[1173] USE VSL ACK DATA
PUSHJ P,USRNOT ;TELL THE USER IT'S GONE
LOAD P4,.MRCNT(AP),MR.CNT ;SAVE THE CURRENT REQUEST COUNT
MOVE S1,.VSFLG(P3) ;DID USER ALLOCATE THIS STR OR IS VSL
TXNN S1,VS.UAL!VS.CTL ; PART OF PSEUDO PROCESS ALLOCATION?
JRST DSMA.Z ;NO TO EITHER - RETURN RESOURCES
TXO S1,VS.UAL ;INSURE ALLOC BIT ON INCASE CTL ONLY
TXZ S1,VS.NMT ;CLEAR MOUNTED FOR PSEUDO PROCESS
MOVEM S1,.VSFLG(P3) ;UPDATE FLAG WORD
PUSHJ P,DSMALC ;RETURN ALLOCATED RESOURCES
MOVE S1,P3 ;GET VSL ADDRESS
PUSHJ P,MNTVSL ;TRY TO RE-MOUNT IT
JRST DSMA.0 ;ON TO THE NEXT VSL
DSMA.Z: PUSHJ P,DSMALC ;RETURN ALLOCATED RESOURCES
JRST DSMA.0 ;GET THEM ALL
MOVE S1,P3 ;GET THE VSL ADDRESS IN S1
PUSHJ P,ALCVSL ;RETURN THE USERS RESOURCES
LOAD S1,.MRCNT(AP),MR.CNT ;GET THE USERS NEW REQUEST COUNT
CAMN S1,P4 ;WAS THE VSL DELETED ???
ZERO .VSFLG(P3),VS.ALC ;NO,,REMOUNT IT !!!
SKIPN S1 ;STILL SOME REQUESTS LEFT,,SKIP
PUSHJ P,DELMDR ;ELSE DELETE THE MDR
JRST DSMA.0 ;GET THEM ALL !!!
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
;Here to unload the volumes if /REMOVE was specified
DSMA.1: PUSH P,P1 ;SAVE THE VOL BLK ADDRESS FOR A SECOND
LOAD P2,.VLFLG(P1),VL.REM ;SAVE THE 'REMOVE' STRUCTURE STATUS
DSMA.2: SKIPN S1,.VLUCB(P1) ;GET THE UCB ADDRESS IN S1
STOPCD (IVU,HALT,,<Invalid VOL/UCB forward/backchain pointers>)
SETZM .VLUCB(P1) ;ZAP VOL LINK TO UCB
SETZM .UCBVL(S1) ;ZAP UCB LINK TO VOL
MOVE S1,.UCBNM(S1) ;GET THE UNIT NAME
SKIPE P2 ;IF 'REMOVING THE STRUCTURE',,THEN
PUSHJ P,UNLOAD ; UNLOAD THE DEVICE
LOAD P1,.VLPTR(P1),VL.NXT ;GET THE NEXT VOLUME IN THE STRUCTURE
JUMPN P1,DSMA.2 ;IF ANOTHER VOLUME,,GO PROCESS IT
;Here to clear all LOCK status and events
DSMA.3: MOVE S1,0(P) ;GET THE VOL BLK ADRS BACK
MOVE S1,.VLNAM(S1) ;AND GET THE STR NAME
PUSHJ P,DMSLOK ;CLEAR ANY PENDING LOCKS, UNLOCKS
MOVE S1,0(P) ;GET THE VOL BLK ADRS BACK
MOVE S1,.VLNAM(S1) ;AND GET THE STR NAME
PUSHJ P,CLRELN ;CLEAR ANY LOCK NOTIFICATION, TOO
POP P,P1 ;RESTORE THE VOL BLK ADDRESS
ZERO .VLFLG(P1),VL.REM ;CLEAR THE REMOVE BIT
MOVX S1,%UNLCK ;GET NORMAL UNLOCKED STATUS
STORE S1,.VLFLG(P1),VL.LCK ;SET NEW STATUS FOR NEXT MOUNT
;Here to update the 'A' matrix if a permanent structure
MOVE S1,.VLNAM(P1) ;GET THE STRUCTURE NAME
PUSHJ P,D$SRSN ;GET THE STRUCTURE RESOURCE NUMBER
IMULI S1,AMALEN ;GET 'A' MATRIX OFFSET
ADD S1,AMATRX ;GET THE ENTRY ADDRESS
LOAD S2,.AMNAM(S1),AM.PRR ;GET THE PERMANENT RESOURCE BIT
JUMPE S2,DSMA.X ;NOT PERMANENT,,SKIP THIS
MOVX S2,AM.PRR ;GET THE PERMANENT STRUCTURE BIT
ANDCAM S2,.AMNAM(S1) ;CLEAR IT FOR THIS STRUCTURE
LOAD S1,.AMNAM(S1),AM.NAM ;POINT TO ASCIZ VOLUME-SET NAME
PUSHJ P,V$FIND## ;GET THE CATALOG ENTRY
SKIPT ;IT MUST BE THERE !!!
STOPCD (SCE,HALT,,<Structure catalog entry missing>)
MOVEI S2,.CQVSL(S1) ;POINT THE THE CAT VOL LIST
MOVE S1,.CQNVL(S1) ;GET THE VOL COUNT
DSMA.A: MOVE T1,.CQRSN(S2) ;GET THE VOL RESOURCE NUMBER
IMULI T1,AMALEN ;GET THE ENTRY OFFSET
ADD T1,AMATRX ;GET THE ENTRY ADDRESS
INCR .AMCNT(T1),AM.AVA ;INCRIMENT THE AVAILABLE COUNT BY 1
ADDI S2,2 ;POINT TO THE NEXT VOL BLK
SOJG S1,DSMA.A ;CONTINUE FOR ALL VOLUMES
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
;Here when done to try to delete the VOL blocks
DSMA.X: LOAD S1,.VLOWN(P1),VL.CNT ;[1465] GET REQUEST COUNT
JUMPN S1,DSMA.Y ;[1465] KEEP CATALOG ENTRY IF NONZERO!!
MOVE S1,.VLNAM(P1) ;GET STR NAME
PUSHJ P,V$STRG## ;CONVERT TO ASCII
PUSHJ P,V$DELS## ;DELETE FROM CATALOG CACHE
DSMA.Y: MOVE S1,P1 ;[1465] GET PRIMARY VOL ADDRESS IN S1
PUSHJ P,DELVOL ;TRY TO DELETE THE VOL BLOCKS
$RETT ;RETURN
;Here if the structure could not be dismounted
DSMA.4: MOVX S1,%STAMN ;GET STRUCTURE MOUNTED BIT
STORE S1,.VLFLG(P1),VL.STA ;RESET STATUS TO 'MOUNTED'
$WTO (<Can't dismount structure ^W/.VLNAM(P1)/>,,,<$WTFLG(WT.SJI)>)
ZERO .VLFLG(P1),VL.REM ;CLEAR ANY REMOVE BITS
MOVE S1,.VLUCB(P1) ;GET THE UCB ADDRESS
PUSHJ P,MATUNI ;CHECK FOR ANY MOUNTS
$RETT ;RETURN
; Return the user's allocated resources
DSMALC: MOVE S1,P3 ;GET THE VSL ADDRESS IN S1
PUSHJ P,ALCVSL ;RETURN THE USERS RESOURCES
LOAD S1,.MRCNT(AP),MR.CNT ;GET THE USERS NEW REQUEST COUNT
CAMN S1,P4 ;WAS THE VSL DELETED ???
ZERO .VSFLG(P3),VS.ALC ;NO,,REMOUNT IT !!!
SKIPN S1 ;STILL SOME REQUESTS LEFT,,SKIP
PUSHJ P,DELMDR ;ELSE DELETE THE MDR
POPJ P, ;RETURN
> ;END TOPS10 CONDITIONAL
SUBTTL DSMOPR - Tell OPR about a structure just dismounted
;This routine informs the operator that a structure dismount
; is complete, and on which units
;Call -
; S1/ Addr of Primary VOL block (VOLs, UCBs still linked)
;Returns -
; True, after WTOing the OPR
TOPS10<
DSMOPR:
$SAVE <P1>
MOVE P1,S1 ;SAVE ADR OF PRIMARY VOL BLOCK
PUSHJ P,MDASBP ;SET UP FOR CALLS TO MDADBP
DSMO.1: SKIPN S2,.VLUCB(S1) ;GET ADRS OF THIS VOLUME'S UNIT BLK
PUSHJ P,S..IVU ;GONG, CAN'T GET HERE
$TEXT (MDADBP,<^W/.UCBNM(S2)/,^A>)
LOAD S1,.VLPTR(S1),VL.NXT ;GET POINTER TO NEXT VOL
JUMPN S1,DSMO.1 ;ANOTHER,,CONTINUE
DSMO.2: SETZ S1, ;MAKE A ZERO
DPB S1,MDBPTR ;AND TERMINATE THE TEXT
SKIPE .VLPTR(P1) ;WAS THERE MORE THAN ONE?
MOVE S1,[ASCII/s/] ;YES,,PLURALIZE IT..
$WTO (<Structure ^W/.VLNAM(P1)/ dismounted>,< From unit^T/S1/: ^T/G$MSG/>,,<$WTFLG(WT.SJI)>)
$RETT
>;END TOPS10
SUBTTL CATACK - ROUTINE TO PROCESS CATALOG ACKS FROM TAPE LABELER
;This routine is run when a volume set cannot be located in
; the volume set catalog
;
;CALL: S1/ The VOL Address of the Primary VOL Block
;
;RET: True Always
TOPS10 <
D$CACK::
CATACK: PUSHJ P,.SAVE1 ;SAVE P1 FOR A MINUTE
SKIPG S1,.MSCOD(M) ;GET THE ACK CODE
$RETT ;INTERNAL REQUEST,,RETURN NOW
PUSHJ P,FNDVSL ;FIND THE VSL
JUMPF .RETT ;NOT THERE,,JUST RETURN
MOVE P1,S1 ;SAVE THE VSL ADDRESS
MOVE AP,.VSMDR(P1) ;SETUP THE MDR ADDRESS
$TEXT (<-1,,G$MSG>,<Structure ^T/.VSVSN(P1)/ not in System Catalog^M^J^0>)
SETOM ERRACK ;THIS IS AN ERROR ACK
MOVE S1,P1 ;[1173] GET VSL ADDRESS
SETZM S2 ;[1173] USE VSL ACK DATA
PUSHJ P,USRNOT ;ACK THE USER
MOVE S1,P1 ;GET THE VSL ADDRESS BACK
PUSHJ P,REMOVE ;GO AND DELETE THIS VSL & RETRY MOUNT
HRROI S1,.VSVSN(P1) ;POINT TO THE ASCIZ VOL SET NAME
PUSHJ P,S%SIXB ;CONVERT IT TO SIXBIT
MOVE S1,S2 ;MOVE IT TO S1
PUSHJ P,D$SRSN ;GET THE RESOURCE NUMBER
PUSHJ P,GIVRSN ;TRY TO RETURN IT
$RETT ;RETURN
>
SUBTTL ASLACK - ROUTINE TO PROCESS ACKS FOR ADDING STR TO A SEARCH LIST
;CALL: S1/ The VOL Address of the Primary VOL Block
;
;RET: True Always
TOPS10 <
ASLACK: PUSHJ P,.SAVE3 ;SAVE P1 & P2 FOR A MINUTE
MOVE P3,S1 ;SAVE THE VOL ADDRESS
MOVE S1,.MSCOD(M) ;GET THE ACK CODE (REQUEST ID)
PUSHJ P,FNDVSL ;FIND THE USER.
JUMPF .RETT ;NOT THERE,,OH WELL...
MOVE P1,S1 ;SAVE THE VSL ADDRESS
SETZM P2 ;NO ADDITIONAL TEXT YET
MOVX S1,.OMTXT ;GET SECONDARY TEXT BLOCK
PUSHJ P,A$FNDB## ;FIND IT
SKIPF ;SKIP IN NOT THERE
MOVE P2,S1 ;ELSE SAVE THE TEXT ADDRESS
JUMPE P2,ASLA.1 ;NO SECONDARY TEXT,,SKIP THIS
LOAD S1,-ARG.DA(P2),AR.LEN ;GET THE BLOCK LENGTH
PUSHJ P,M%GMEM ;GET SOME MEMORY
STORE S1,.VSTXT(P1),VS.LEN ;SAVE THE BLOCK LENGTH
STORE S2,.VSTXT(P1),VS.ADR ;SAVE THE BLOCK ADDRESS
ADD S1,S2 ;POINT TO THE END OF THE BLOCK
HRL S2,P2 ;GET SOURCE,,DESTINATION ADDRESS
BLT S2,-1(S1) ;COPY THE TEXT AND SAVE IT
ASLA.1: MOVX S1,AK.NAK ;GET A BIT
TDNE S1,.MSFLG(M) ;WAS IT A NAK?
JRST ASLA.2 ;YES
$COUNT (USTM) ;# of user structure mounts
MOVE S1,P1 ;GET VSL BLOCK ADDRESS
MOVE S2,P3 ;GET VOL BLOCK ADDRESS
PUSHJ P,AASCLR ;CLEAR VL.AAS
MOVE S1,P1 ;GET THE VSL ADDRESS
PUSHJ P,SETOWN ;SAY THIS GUY OWNS THE UNIT
MOVE S1,P1 ;GET THE VSL ADDRESS
PUSHJ P,I$SMNT## ;PERFORM STRUCTURE ACCOUNTING
MOVE S1,P1 ;GET THE VSL ADDRESS
PUSHJ P,ACKUSR ;TELL THE USER
$RETT ;AND RETURN
ASLA.2: SKIPN P2 ;ANY ADDITIONAL TEXT ???
MOVEI P2,[0] ;NO,,POINT TO A NULL BLOCK
$TEXT (<-1,,G$MSG>,<Can't mount structure ^T/.VSVSN(P1)/^M^J^T/0(P2)/^M^J^0>)
SETOM ERRACK ;INDICATE THIS IS AN ERROR ACK
MOVE S1,P1 ;[1173] GET VSL ADDRESS
SETOM S2 ;[1173] USE MDR ACK DATA IF VALID
PUSHJ P,USRNOT ;NOTIFY THE USER
MOVE S1,P1 ;GET THE VSL ADDRESS BACK
PUSHJ P,ALCVSL ;RETURN THIS VSL TO THE ALLOCATION POOL
LOAD S1,.MRCNT(AP),MR.CNT ;GET THE USERS REQUEST COUNT
JUMPE S1,DELMDR ;NOTHING LEFT,,DELETE THE MDR
$RETT ;AND RETURN
>
SUBTTL RMSACK - ROUTINE TO PROCESS 'REMOVE STRUCTURE' ACKS
;CALL: S1/ The VOL Address of the Primary VOL Block
;
;RET: True Always
TOPS10<
RMSACK: PUSHJ P,.SAVE2 ;SAVE P1 AND P2 FOR A SECOND
MOVE P1,S1 ;SAVE THE VOL BLOCK ADDRESS
MOVE S1,.MSCOD(M) ;GET THE ACK CODE (REQUEST ID)
PUSHJ P,FNDVSL ;FIND THE VSL
JUMPF RMSA.1 ;NOT THERE,,GO CHECK OUT THE STR
PUSH P,S1 ;SAVE THE VSL ADDRESS FOR A SECOND
MOVX S1,.OMTXT ;GET THE REASON BLOCK
PUSHJ P,A$FNDB## ;FIND IT
SKIPT ;NOT THERE ???
MOVEI S1,[0] ;NOT THERE,,POINT TO NULL WORD
MOVE P2,S1 ;GET TEXT ADDRESS
LOAD TF,.MSFLG(M),AK.NAK ;IS THIS A NAK ???
JUMPN TF,RMSA.2 ;YES,,OH WELL !!!!
MOVE S1,(P) ;GET THE VSL ADDRESS BACK
$TEXT (<-1,,G$MSG>,<^T/(P2)/[Structure ^T/.VSVSN(S1)/ dismounted]^M^J^0>)
PUSHJ P,I$SDSM## ;PERFORM STRUCTURE ACCOUNTING
MOVE S2,(P) ;[1173] GET VSL ADDRESS AGAIN
MOVE S1,.VSRFL(S2) ;[1173] GET WAIT/NOTIFY/ACK FLAGS ETC.
TXNE S1,MR.WAT ;WAITING?
TXO S1,MR.ACK ;THEN WE WANT TO ACK VIA IPCF
MOVEM S1,.VSRFL(S2) ;[1173] RESTORE FLAG WORD
MOVX S1,MR.DMO ;GET DISMOUNT BIT
IORM S1,.VSRFL(S2) ;[1173] LITE IT SO USRNOT DOES PRETTY THINGS
MOVE S1,S2 ;[1173] GET VSL ADDRESS
SETZM S2 ;[1173] USE VSL ACK DATA!
PUSHJ P,USRNOT ;NOTIFY THE USER
MOVE S1,0(P) ;GET THE VSL ADDRESS BACK
LOAD S2,.VSFLG(S1),VS.REM ;GET THE /REMOVE STR FLAG BIT
SKIPE S2 ;DID USER SPECIFY /REMOVE ???
PUSHJ P,TELREM ;YES,,TELL THE OPERATOR
POP P,S1 ;RESTORE THE VSL ADDRESS
PUSHJ P,ALCVSL ;DEALLOCATE IF WE CAN
LOAD S1,.MRCNT(AP),MR.CNT ;GET THE VSL REQUEST COUNT
SKIPN S1 ;ANY MORE REQUESTS ???
PUSHJ P,DELMDR ;NO,,DELETE THIS MDR
RMSA.1: MOVE S1,P1 ;GET THE VOL BLOCK ADDR BACK
PUSHJ P,CHKSTR ;CHECK FOR STRUCTURE AVAILABILITY
$RETT ;THEN RETURN
RMSA.2: MOVE S1,(P) ;[1173] GET VSL ADDRESS
$TEXT (<-1,,G$MSG>,<Can't dismount structure ^T/.VSVSN(S1)/^M^J^T/(P2)/^0>)
SETOM ERRACK ;IS THIS AN ERROR
POP P,S1 ;[1173] RESTORE VSL ADDRESS
SETZM S2 ;[1173] USE VSL ACK DATA
PUSHJ P,USRNOT ;SEND IT OFF TO THE USER
$RETT ;AND RETURN
> ;END TOPS10 CONDITIONAL
SUBTTL D$ALIA - ROUTINE TO MOUNT A STRUCTURE WITH AN ALIAS
;CALL: M/ The Mount Message Address (From ORION)
;
;RET: True Always
TOPS10<
D$ALIA::PUSHJ P,.SAVE2 ;SAVE P1 & P2 FOR A SECOND
MOVX S1,.STRDV ;GET STRUCTURE NAME BLOCK TYPE
PUSHJ P,A$FNDB## ;LOCATE IT IN THE MESSAGE
JUMPF E$IMO## ;NOT THERE,,THATS AN ERROR
HRLI S1,(POINT 7,) ;MAKE A POINTER
$CALL S%SIXB ;CONVERT TO SIXBIT
MOVE P1,S2 ;GET THE STRUCTURE NAME
MOVEM P1,MDAOBJ+OBJ.UN ;SAVE IT IN THE OBJECT BLOCK
MOVE S1,VOLQUE ;GET THE VOLUME QUEUE ID
PUSHJ P,L%FIRST ;GET THE FIRST ENTRY
JRST ALIA.2 ;SKIP THE FIRST TIME THROUGH
ALIA.1: MOVE S1,VOLQUE ;GET THE VOLUME QUEUE ID
PUSHJ P,L%NEXT ;GET THE NEXT ENTRY
ALIA.2: JUMPF ALIA.9 ;NO MORE,,THATS AN ERROR
SKIPE S1,.VLUCB(S2) ;VOLUME MUST BE MOUNTED !!!
CAME P1,.VLNAM(S2) ;AND STRUCTURE NAMES MUST MATCH !!!
JRST ALIA.1 ;NO,,TRY NEXT VOLUME
LOAD S1,.UCBST(S1),UC.DVT ;GET THE DEVICE TYPE
CAXE S1,%DISK ;IS IT A STRUCTURE ???
JRST ALIA.1 ;NO,,TRY NEXT VOLUME
LOAD S1,.VLFLG(S2),VL.STA ;GET THE VOLUME STATUS
;**;[1204] Change code at ALIA.2+7L. /LWS
CAXN S1,%STAWT ;[1204] IS IT WAITING ???
JRST ALIA2A ;[1204] YES,,GO PROCESS
CAXE S1,%STADM ;[1204] NO,,DISMOUNTING???
JRST ALIA.1 ;NO,,TRY NEXT VOLUME
MOVEI S1,[ITEXT(<Structure ^W/P1/ is dismounting>)] ;[1204]
JRST ALIA.E ;[1204] GO ACK
;Here to process the primary vol block we found
ALIA2A: MOVE P1,S2 ;[1204] SAVE THE PRIMARY VOL BLOCK ADDRESS
ALIA.3: SKIPN S1,.VLNXT(S2) ;ANY 'NEXT' VOLUME FOR THIS STRUCTURE ??
JRST ALIA.4 ;NO,,LETERRIP !!!
;**;[1227] Change 1 line and delete 2 lines at ALIA.3+2L. /LWS
PUSHJ P,FNDVOL ;[1227] YES,,GO FIND IT IN OUR DATA BASE
JUMPF ALIA.9 ;NOT FOUND,,THATS AN ERROR
MOVE S2,S1 ;OK,,SET POINTER TO THIS VOLUME
JRST ALIA.3 ;AND CHECK OUT THIS VOLUME
ALIA.4: MOVE P2,.VLNAM(P1) ;DEFAULT TO THE STRUCTURE NAME
MOVX S1,.STALS ;GET THE ALIAS BLOCK TYPE
PUSHJ P,A$FNDB## ;FIND IT IN THE MESSAGE
JUMPF ALIA.5 ;NOT THERE,,JUST MOUNT IT
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
HRLI S1,(POINT 7,) ;MAKE A POINTER TO IT
$CALL S%SIXB ;CONVERT IT
MOVE P2,S2 ;SAVE THE ALIAS NAME
MOVE S1,P2 ;GET THE ALIAS NAME IN S1
PUSHJ P,I$VDEV## ;VALIDATE THE DEVICE NAME
JUMPT ALIA.7 ;NO GOOD IF DEVICE ALREADY EXISTS
ALIA.5: MOVE S1,P2 ;GET THE ALIAS NAME
PUSHJ P,V$STRG## ;CONVERT TO ASCIZ
PUSHJ P,V$FIND## ;FIND THE CATALOG ENTRY
JUMPF ALIA.6 ;ITS OK IF WE CAN'T
MOVE S1,.CQVSL+.CQVID(S1) ;GET THE PRIMARY VOL NAME
PUSHJ P,FNDDSK ;FIND ITS VOL BLOCK
JUMPF ALIA.6 ;DOESN'T HAVE TO BE THERE
CAMN S1,P1 ;SAME AS THE ONE WE'RE MOUNTING?
;**;[1227] Change 2 lines at ALIA.5+7L. /LWS
JRST ALI.6D ;[1227] YES
LOAD S2,.VLFLG(S1),VL.STA ;GET STR STATUS
CAIN S2,%STAMN ;MOUNTED?
JRST ALI.6D ;[1227] YES, CONTINUE. V$CREA WILL BOMB
MOVEI S2,.OTMNT ;GET OBJECT TYPE MOUNT
MOVEM S2,CATOBJ+OBJ.TY ;SAVE IT
SKIPE S2,.VLUCB(S1) ;[1227] GET UCB ADDR
MOVE S2,.UCBNM(S2) ;GET UNIT NAME
MOVEM S2,CATOBJ+OBJ.UN ;SAVE IN OBJECT BLOCK
SETZM CATOBJ+OBJ.ND ;NO NODE INFO
LOAD S2,.VLOWN(S1),VL.CNT ;[1227] GET REQUESTOR COUNT
JUMPN S2,ALIA.6 ;[1227] IF REQUESTORS EXIST, CANT DELETE
SKIPE CATOBJ+OBJ.UN ;[1227] IF NO UCB, DON'T USE OBJECT BLK
$WTO (<Deleting duplicate volume>,<Unit ^W/.VLVID(S1)/ for structure ^W/.VLNAM(S1)/>,CATOBJ,<$WTFLG(WT.SJI)>)
SKIPN CATOBJ+OBJ.UN ;[1227]
$WTO (<Deleting duplicate volume>,<Unit ^W/.VLVID(S1)/ for structure ^W/.VLNAM(S1)/>,,<$WTFLG(WT.SJI)>) ;[1227]
PUSHJ P,DELVOL ;DELETE THE OLD ONE
ALIA.6: LOAD S1,.VLOWN(P1),VL.CNT ;[1227] SEE IF ANY REQUESTORS
JUMPE S1,ALI.6D ;[1227] IF NONE, CONTINUE
$SAVE <T1,T2> ;[1227] SAVE T1 & T2
SETZM T1 ;[1227] INDICATE NO PREVIOUS VOL BLOCK
MOVE T2,P1 ;[1227] GET PRIMARY (OLD) VOL BLOCK ADDR
ALI.6A: PUSHJ P,CREVOL ;[1227] CREATE A NEW VOL BLOCK
MOVE S2,S1 ;[1227] COPY NEW VOL ADDR
HRL S1,T2 ;[1227] COPY OLD VOL TO NEW VOL
BLT S1,.VLVSL-1(S2) ;[1227] EXCEPT FOR VSL POINTERS
SETZM .VLPTR(S2) ;[1227] CLEAR MULTIPLE VOL BLOCK PTRS
SKIPN T1 ;[1227] SAVE PRIMARY VOL ADDR ONLY ONCE
PUSH P,S2 ;[1227]
MOVE T1,S2 ;[1227] GET NEW VOL BLOCK ADDR IN T1
MOVX S1,VL.CNT ;[1227] CLEAR REQUEST COUNT IN VOL COPY
ANDCAM S1,.VLOWN(T1) ;[1227]
MOVX S1,VL.RSN ;[1227] CLEAR RESOURCE NUMBER!
ANDCAM S1,.VLFLG(T1) ;[1227]
SETZM .VLMTM(T1) ;[1227] CLEAR MOUNT TIME
SKIPE S1,.VLUCB(T2) ;[1227] GET POINTER TO UCB
MOVEM T1,.UCBVL(S1) ;[1227] LINK UCB TO NEW VOL
MOVEM S1,.VLUCB(T1) ;[1227] LINK NEW VOL TO UCB
SETZM .VLUCB(T2) ;[1227] UNLINK OLD VOL FROM UCB
CAME T1,(P) ;[1227] NEW PRIMARY VOL BLOCK?
JRST ALI.6C ;[1227] NO, DON'T GET NEW RESOURCE
MOVE S1,T1 ;[1227] YES, GET NEW VOL BLOCK ADDRESS
EXCH P2,.VLNAM(S1) ;[1227] USE ALIAS NAME FOR NEW RESOURCE
PUSHJ P,D$SVRS ;[1227] GET A RESOURCE NUMBER
ALI.6C: LOAD T2,.VLPTR(T2),VL.NXT ;[1227] GET POINTER TO NEXT VOL BLOCK
JUMPN T2,ALI.6A ;[1227] IF ANOTHER VOL, LOOP.
POP P,P1 ;[1227] GET NEW PRIMARY VOL ADDR
TRNA ;[1227] ALREADY EXCH'D NAMES
ALI.6D: EXCH P2,.VLNAM(P1) ;[1227] SWAP ALIAS NAME WITH OLD NAME
MOVE S1,P1 ;GET THE VOLUME BLOCK ADDRESS
PUSHJ P,V$CREA## ;GENERATE A CATALOG ENTRY
JUMPF ALIA.8 ;CAN'T
LOAD S1,.OFLAG(M),.MTWLK ;GET WRITE LOCKED BIT
MOVEM S1,WRTLCK ;SAVE IT
LOAD S1,.OFLAG(M),.DMOSN ;GET OVERRIDE-SET-NUMBER BIT
MOVEM S1,OSNFLG ;SAVE IT
MOVE S1,P1 ;GET VOL BLOCK ADDRESS
MOVE S2,.VLNAM(P1) ;GET STR NAME
PUSHJ P,SNDBLD ;BUILD THE STRUCTURE
$RETT ;RETURN
ALIA.7: MOVEI S1,[ITEXT (<Device ^W/P2/ already exists>)]
JRST ALIA.E ;ACK THE ERROR AND RETURN
ALIA.8: EXCH P2,.VLNAM(P1) ;RESTORE ORIGINAL STR NAME
MOVE S1,P1 ;[1227] GET PRIMARY VOL ADDR
PUSHJ P,DELVOL ;[1227] DELETE VOL BLOCKS IF NO REQUESTORS
SKIPA S1,[EXP [ITEXT (<^W/P2/ has outstanding allocations>)]]
ALIA.9: MOVEI S1,[ITEXT (<All required volumes are not spinning>)]
ALIA.E: $ACK (<Invalid mount request>,<^I/(S1)/>,MDAOBJ,.MSCOD(M))
$RETT ;RETURN
> ;END TOPS10 CONDITIONAL
SUBTTL CHKSTR - ROUTINE TO CHECK FOR STRUCTURE AVAILABILITY
;CALL: S1/ The VOL Address of the Primary VOL Block
;
;RET: True Always
TOPS10<
D$CCHK:: ;[1153]EXTERNAL ENTRY POINT
CHKSTR: PUSHJ P,.SAVE1 ;SAVE P1 FOR A SECOND
$SAVE AP ;SAVE AP ALSO
MOVE P1,S1 ;SAVE THE VOL BLOCK ADDRESS
LOAD S1,.VLFLG(P1),VL.STA ;GET THE STRUCTURE STATUS
LOAD S2,.VLFLG(P1),VL.LCK ;GET THE STRUCTURE LOCK CODE
CAXN S1,%STAMN ;IS THE STRUCTURE MOUNTED ???
CAXE S2,%LOCKD ; AND IS IT LOCKED ???
JRST CHKS.1 ;NO,,TRY REASSIGNMENT
MOVE S1,P1 ;GET THE VOL BLOCK ADDRESS BACK
PUSHJ P,FNDOWN ;ANYONE STILL OWN IT ???
JUMPT .RETT ;YES,,RETURN NOW
MOVE S1,.VLNAM(P1) ;GET THE STRUCTURE NAME
MOVEM S1,MDAOBJ+OBJ.UN ;SAVE IT
$WTO (<This locked structure has a zero mount count^T/BELLS/>,,MDAOBJ)
MOVE S1,P1 ;GET THE VOL BLK ADDR IN S1
SETZ S2, ;NO DISMOUNT FLAGS
PUSHJ P,SNDDSM ;DISMOUNT THE STRUCTURE
$RETT ;RETURN
CHKS.1: CAXE S1,%STAMN ;ARE WE MOUNTED AT LEAST ??
$RETT ;NO,,RETURN
MOVE S1,.VLUCB(P1) ;YES,,GET THE UCB ADDRESS
PUSHJ P,MATUNI ;GO TRY TO REASSIGN THE UNIT
$RETT ;AND RETURN
> ;END TOPS10 CONDITIONAL
SUBTTL D$LOCK - PROCESS LOCK AND UNLOCK MESSAGES
;CALL: M/ Addrs of incoming LOCK and UNLOCK message
;
;RET: True, with some of the VOL database changed
TOPS10<
D$LOCK::TDZA S1,S1 ;FLAG THE LOCK ENTRY POINT
D$ULOK::MOVEI S1,1 ;FLAG UNLOCK ENTRY
$SAVE <P1,P2> ;SAVE P1 AND P2
MOVE P1,S1 ;SAVE THE ENTRY FLAG
MOVX S1,.STRDV ;BLOCK TYPE - STRUCTURE NAME
PUSHJ P,A$FNDB## ;FIND OUT WHAT STR OPR IS TALKING ABOUT
JUMPF E$IMO## ;NOT THERE, TOO BAD
HRROI S1,0(S1) ;AIM AT THE STR NAME
$CALL S%SIXB ;CONVERT IT TO 6BIT
MOVE S1,S2 ;MOVE THE STR NAME INTO PLACE
PUSHJ P,FNDISK ;FIND THE VOL BLOCK FOR THAT STR
JUMPF E$NSD## ;CAN'T, THAT'S AN ERROR
MOVE P2,S1 ;SAVE ADDR OF VOL BLOCK
LOAD S1,.VLFLG(P2),VL.LCK ;GET THE LOCK CODE
MOVEI S2,[ASCIZ/not/] ;TRYING UNLOCK BUT STR NOT LOCKED !!!
CAXN S1,%UNLCK ;IS IT UNLOCKED?
JUMPN P1,LOCK.1 ;YES, DON'T ALLOW ANOTHER UNLOCK
MOVEI S2,[ASCIZ/already/] ;ALREADY LOCKED AND TRYING AGAIN !!!
CAXN S1,%LOCKD ;IS IT LOCKED?
JUMPE P1,LOCK.1 ;YES, DON'T ALLOW ANOTHER LOCK
MOVX S1,VL.REM ;ON A LOCK
SKIPN P1 ; DEFAULT TO UNLOADING
IORM S1,.VLFLG(P2) ; THE STRUCTURE
LOAD S2,.OFLAG(M),LC.NUL ;GET THE /NOUNLOAD BIT
SKIPN P1 ;ON AN UNLOCK
SKIPE S2 ; OR A LOCK /NOUNLOAD
ANDCAM S1,.VLFLG(P2) ; DON'T UNLOAD THE STRUCTURE
LOAD S1,.VLFLG(P2),VL.LCK ;GET THE LOCK CODE BACK
CAXN S1,%LOCKP ;IS A LOCK PENDING?
JUMPN P1,CLRPND ;YES, 'UNLOCK' CLEARS THE LOCK REQUEST
CAXN S1,%ULCKP ;IS AN UNLOCK PENDING?
JUMPE P1,CLRPND ;YES, 'LOCK' CLEARS THE UNLOCK REQUEST
CAXE S1,%LOCKP ;WAS IT PENDING A LOCK
CAXN S1,%UNLCK ; OR AN UNLOCK?
SKIPA ;ONE OF THOSE, GOT SOME WORK TO DO
JRST LOCK.0 ;NO PENDING REQUEST, CONTINUE
LOAD S1,.VLNAM(P2) ;GET BACK THE STR NAME
PUSHJ P,DMSLOK ;PENDING EITHER, CANCEL IT
LOAD S1,.VLNAM(P2) ;GET BACK THE STR NAME
PUSHJ P,CLRELN ;CLEAR THE EVENT NOTIFICATION, TOO
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
;Now we've ruled out the funny state transitions
LOCK.0: MOVX S1,.ORTIM ;BLOCK TYPE FOR DATE/TIME ARGUMENT
PUSHJ P,A$FNDB## ;GET THAT BLOCK
SKIPT ;IS THERE ONE?
SKIPA S1,G$NOW## ;NO, ASSUME ACTION NOW
MOVE S1,0(S1) ;YES, GET THE LOCK TIME
CAMGE S1,G$NOW## ;IS TIME IN THE FUTURE?
MOVE S1,G$NOW## ;NO, MAKE IT THE PRESENT
MOVX S2,%LOCKP ;SAY PENDING
SKIPE P1 ;IS IT A LOCK?
MOVX S2,%ULCKP ;NO, SAY UNLOCK PENDING
STORE S2,.VLFLG(P2),VL.LCK ;SAVE THE STATUS
MOVEM S1,.VLLTM(P2) ;AND NOTE THE TIME AT WHICH IT HAPPENED
CAMN S1,G$NOW## ;IS IT TO HAPPEN NOW?
PJRST LOKSTR ;YES, GO DO IT!
$ACK (<Structure ^W/.VLNAM(P2)/>,<^W/LCKTB1(P1)/ set for ^H/.VLLTM(P2)/>,,.MSCOD(M))
MOVX S2,INSVL.(%EVLCK,EV.TYP) ;GET EVENT TYPE OF LOCK
MOVEM S2,TMPVSL+.EVTYP ;SAVE IN TEMP BLOCK
MOVEM S1,TMPVSL+.EVUDT ;AND SAVE THE TIME TO WAKE UP
MOVEI S1,LOCTIM ;ROUTINE TO CALL AT THAT TIME
MOVEM S1,TMPVSL+.EVRTN ;SAVE THAT
LOAD S1,.VLNAM(P2) ;GET THE STR NAME
MOVEM S1,TMPVSL+.EVMSZ ;SAVE THAT, TOO
MOVEI S1,.EVMSZ+1 ;MINIMAL BLOCK, WITH 1 DATA WORD
MOVEI S2,TMPVSL ;THERE'S THE ARG BLOCK
PUSHJ P,S$EVENT## ;CALL ME BACK IN A MINUTE OR AN HOUR
JUMPN P1,.RETT ;IF AN UNLOCK, THAT'S ALL
MOVE S1,P2 ;GET THE VOL BLK ADRS
PJRST LOCN.I ;NOTIFY THE USERS
LOCK.1: $ACK (<Structure ^W/.VLNAM(P2)/ is ^T/0(S2)/ locked>,,,.MSCOD(M))
MOVE S1,P2 ;GET THE VOL BLK ADDR IN S1
PUSHJ P,CHKSTR ;CHECK THE MOUNT STATUS
$RETT ;TELL OPR HE IS IN ERROR AND RETURN
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
;Here to clear a pending lock or unlock and set the
; state of the vol block back to unlocked or locked, respectively
; P1/ 0 for LOCK, -1 for UNLOCK
; P2/ VOL BLK adrs
CLRPND: MOVX S2,%LOCKD ;ASSUME CANCELLING AN UNLOCK
SKIPE P1 ;OPR SAID LOCK?
MOVX S2,%UNLCK ;NO, CANCELLING A LOCK
STORE S2,.VLFLG(P2),VL.LCK ;SAVE IN THE VOL BLOCK
ZERO .VLLTM(P2) ;NO MORE LOCK TIME
$ACK(<Structure ^W/.VLNAM(P2)/ pending ^W/LCKTB2(P1)/ canceled>,,,.MSCOD(M))
MOVE S1,.VLNAM(P2) ;GET THE STRUCTURE NAME
PUSHJ P,DMSLOK ;REMOVE ALL THE PENDING TIMERS
MOVE S1,.VLNAM(P2) ;GET THE STRUCTURE NAME
PUSHJ P,CLRELN ;REMOVE THE PENDING NOTIFICATION TIMER
MOVE S1,P2 ;GET THEN PRIMARY VOL BLOCK
MOVEI S2,[ITEXT(<LOCK for structure ^W/.VLNAM(P2)/ canceled>)]
PUSHJ P,NSTUSR ;TELL THE USERS THE GOOD NEWS
$RETT
SUBTTL TIMER ROUTINES FOR LOCK AND UNLOCK
;These routines are called when the lock or unlock timer
; goes off. The scheduler calls here as the action routine
; for the timer.
; S1/ Event block adrs
LOCTIM: $SAVE <P1>
LOAD S1,.EVMSZ(S1) ;GET THE STRUCTURE NAME
PUSHJ P,FNDISK ;GET THE VOL BLOCK
JUMPF .RETT ;STR WENT AWAY. STRANGE.
MOVE P1,S1 ;SAVE THE ADRS OF THE BLOCK
LOAD S1,.VLFLG(P1),VL.LCK ;GET THE LOCK STATE
CAXN S1,%LOCKP ;LOCK PENDING TIMER GONE OFF?
JRST LOKS.1 ;YES, LOCK IT UP!
CAXN S1,%ULCKP ;UNLOCK PENDING TIMER?
JRST UNLOCK ;YES, UNLOCK IT
$RETT ;WIERD,,TIMER WITH NOTHING PENDING
;Here to lock or unlock a structure and inform the operator
;
;CALL: P1/ 0 for LOCK, -1 for UNLOCK
; P2/ VOL block adrs
LOKSTR: EXCH P1,P2 ;SWAP VOL BLK ADRS AND LOCK/UNLOCK FLAG
JUMPN P2,UNLOCK ;GO UNLOCK THE STR
LOKS.1: LOAD S1,.VLNAM(P1) ;GET THE STR NAME BACK
PUSHJ P,I$LOCK## ;LOCK IT UP
JUMPF [$WTO(<Can't LOCK structure ^W/.VLNAM(P1)/>,,,$WTFLG(WT.SJI))
JRST UNLC.2] ;AND CLEAR THE STATUS
$WTO (<Structure ^W/.VLNAM(P1)/ locked>,,,$WTFLG(WT.SJI))
MOVE S1,.VLNAM(P1) ;GET THE STR NAME
PUSHJ P,CLRELN ;CLEAR ANY OUTSTANDING LOCK NOTIFY EVENTS
;DON'T CLEAR LOCK TIMER EVENTS,
;SINCE WE MAY BE HERE ON ONE OF THOSE
;EVENTS, AND THE SERVICE ROUTINE EXPECTS
;TO CLEAN IT UP
MOVE S1,P1 ;AIM AT THE PRIMARY VOL BLOCK
MOVEI S2,[ITEXT(<Structure ^W/.VLNAM(P1)/ locked>)]
PUSHJ P,NSTUSR ;TELL ALL THE USERS THE BAD NEWS
LOKS.2: MOVX S1,%LOCKD ;GET LOCKED STATUS
STORE S1,.VLFLG(P1),VL.LCK ;SAVE THE LOCK STATUS
SETZM .VLLTM(P1) ;NO TIME, EITHER
MOVE S1,P1 ;GET THE VOL BLK ADDR IN S1
PUSHJ P,CHKSTR ;CHECK FOR OTHER USERS
$RETT ;RETURN
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
;Here if it is an UNLOCK command. P1/ VOL block adrs
UNLOCK: LOAD S1,.VLNAM(P1) ;GET THE STR NAME BACK
PUSHJ P,I$UNLK## ;CLEAR THE LOCK
JUMPT UNLC.1 ;WINS, TELL OPR
$WTO (<Can't UNLOCK structure ^W/.VLNAM(P1)/>,,,$WTFLG(WT.SJI))
PJRST LOKS.2 ;AND SET IT STILL LOCKED
UNLC.1: MOVEI S2,[ITEXT(<Structure ^W/.VLNAM(P1)/ unlocked>)]
$WTO (<^I/0(S2)/>,,,$WTFLG(WT.SJI)) ;TELL THE OPERATOR
MOVE S1,P1 ;GET THE VOL ADDRESS IN S1
PUSHJ P,NSTUSR ;TELL THE USERS ALSO
UNLC.2: MOVX S1,%UNLCK ;GET UNLOCKED CODE
STORE S1,.VLFLG(P1),VL.LCK ;SET THE FIELD
SETZM .VLLTM(P1) ;NO TIME, EITHER
MOVE S1,P1 ;GET THE VOL ADDRESS IN S1
SKIPE S1,.VLUCB(P1) ;GET THE UCB ADDRESS (SHOULD NOT SKIP)
PUSHJ P,MATUNI ;TRY TO MOUNT THE VOLUME
$RETT ;RETURN IN ANY CASE
>;END TOPS10
SUBTTL LOCNOT - Notify users (countdown) of pending locks
;This routine is called when an event timer for a structure lock goes off
; It finds the structure data base, and notifies all remaining users
; of that structure of the time remaining on the str.
; If there are some left, then another entry is put into the timer queue
; for the next countdown time to notify.
;Call -
; S1/ Adrs of Event block for the countdown notification
TOPS10<
DEFINE UDTMIN(N),<<<N>*^O1000000>/^D<24*60>> ;UDT REPRESENTATION OF N MINUTES
MAXLMN==^D7 ;MAX EXP OF 2 AT WHICH TO NOTIFY USERS
LMNTAB: UDTMIN (^D128) ;2**8 = TOO BIG AN ELEMENT, SAY THE MAX
UDTMIN (^D1) ;2**0 = 1 MINUTE
UDTMIN (^D2) ;2**1 = 2 MINUTES
UDTMIN (^D4) ;2**2 = 4 MINUTES
UDTMIN (^D8) ;2**3 = 8 MINUTES
UDTMIN (^D16) ;2**4 = 16 MINUTES
UDTMIN (^D32) ;2**5 = 32 MINUTES
UDTMIN (^D64) ;2**6 = 64 MINUTES
LOCNOT: MOVE S1,.EVMSZ+0(S1) ;GET THE STRUCTURE NAME
PUSHJ P,FNDISK ;FIND THE PRIMARY VOLUME BLOCK
JUMPF .RETT ;NOT THERE, QUIT, NO RE-RENTRY TO TIMER QUEUE
;Internal entry with S1/ Vol block adrs
LOCN.I: $SAVE <P1,P2,P3,P4> ;SOME WORK SPACE
MOVE P1,S1 ;SAVE PRI VOL BLK ADRS
MOVE P2,.VLLTM(P1) ;GET T=0
SUB P2,G$NOW## ;FIGURE UDT LEFT IN THIS TIMER
JUMPLE P2,.RETT ;WE'RE HERE TOO LATE, GET OUT
MOVE P3,P2 ;NO, GET UDT LEFT
IDIVI P3,UDTMIN(1) ;CONVERT TO MINUTES LEFT
MOVEI S2,[ITEXT(<Structure ^W/.VLNAM(P1)/ will be locked in ^D/P3/ minutes>)]
TLNE P2,-1 ;MORE THAN A DAY LEFT?
MOVEI S2,[ITEXT(<Structure ^W/.VLNAM(P1)/ will be locked at ^H/.VLLTM(P1)/>)]
PUSHJ P,NSTUSR ;NOTIFY ALL USERS OF THE STRUCTURE
JFFO P3,.+2 ;FIND ORDER OF MAGNITUDE OF TIME LEFT
$RETT ;?? CAN'T GET HERE, QUIT
SUBI P4,^D35 ;CONVERT TO -35 TO 0 RANGE
JUMPE P4,.RETT ;LESS THAN A MINUTE,, QUIT
MOVNS P4 ;TO 0 TO 35
CAIL P4,MAXLMN ;BIGGER THAN MAX LOG MINUTES?
SETZ P4, ;YES, JUST SAY THE MOST WE KNOW
MOVE S2,LMNTAB(P4) ;GET THEN NUMBER OF MINUTES TO WAIT
ADD S2,G$NOW## ;SET THAT AS NEXT NOTIFY TIME
MOVE S1,.VLNAM(P1) ;GET THE STR NAME AGAIN
PJRST LNEVEN ;MAKE A NEW LOCK NOTIFY EVENT BLOCK
> ;END TOPS10 CONDITIONAL
SUBTTL CLEAR LOCKS ON STRUCTURE DISMOUNT
;This routine is called when a structure is dismounted, so that
; Any pending event blocks can be cleaned up.
; If we don't clean 'em up, and another structure gets mounted
; before the timer goes off, then that (new) structure
; will bear the brunt of the OPRs old LOCK or UNLOCK.
; Also, any notify request blocks for this structure are cleaned up.
;Call -
; S1/ Structure name just dismounted
;Returns -
; TRUE (always)
TOPS10<
CLRELN: MOVEI S2,%EVNLC ;GET EVENT TYPE - LOCK NOTIFY
SKIPA ;ENTER THE COMMON CODE
DMSLOK: MOVEI S2,%EVLCK ;GET EVENT TYPE - PENDING LOCK
$SAVE <P1,P2>
DMOVE P1,S1 ;PRESERVE THE STR NAME, EVENT TYPE
MOVE S1,G$EVENT## ;GET THE LIST HANDLE
$CALL L%FIRST ;GET THE FIRST GUY
DSML.1: JUMPF .RETT ;NONE THERE, OH WELL
LOAD TF,.EVTYP(S2),EV.TYP ;GET THE EVENT TYPE
CAMN TF,P2 ;IS IT THE RIGHT TYPE OF EVENT?
CAME P1,.EVMSZ(S2) ;YES, IS THIS THE STR BEING DISMOUNTED?
SKIPA ;NOT A LOCK OR WRONG STRUCTURE,,SKIP
$CALL L%DENT ;LOCK OR NOTIFY FOR THIS STR, DELETE IT
PUSHJ P,L%NEXT ;EITHER WAY,,GET THE NEXT ENTRY
JRST DSML.1 ;AND CHECK IT OUT
> ;END TOPS10 CONDITIONAL
SUBTTL LNEVEN - Set up a Lock notification event
;This routine is called whenever someone wants to put up a lock
; notification event for a particular structure.
; LOCNOT will be called at the specified time with
; the adrs of the lock notication event block.
; Call -
; S1/ SIXBIT structure name
; S2/ UDT at which to be notified
;Returns
; TRUE (ALWAYS)
TOPS10<
LNEVEN: MOVEM S1,TMPVSL+.EVMSZ+0 ;SAVE STR NAME AS FIRST (ONLY) DATA ARG
MOVEM S2,TMPVSL+.EVUDT ;SAVE WAKE-UP TIME
MOVX S1,INSVL.(%EVNLC,EV.TYP) ;EVENT TYPE
MOVEM S1,TMPVSL+.EVTYP ;NO FLAGS,
MOVEI S1,LOCNOT ;ROUTINE TO RUN AT THAT TIME
MOVEM S1,TMPVSL+.EVRTN ;SAVE THAT TOO
MOVEI S1,.EVMSZ+1 ;MINIMAL EVENT BLOCK, WITH 1 DATUM
MOVEI S2,TMPVSL ;THERE'S THE BLOCK
PJRST S$EVENT## ;SEE ME LATER!
> ;END TOPS10 CONDITIONAL
SUBTTL D$LCKM - ROUTINE TO PROCESS THE RESET AFTER LOCK MESSAGE
;CALL: M/ The Message Address
;
;RET: True Always
TOPS10< INTERN D$LCKM ;MAKE IT GLOBAL
D$LCKM: PUSHJ P,.SAVE2 ;SAVE P1 & P2 FOR A SECOND
MOVE S1,.RSTJB(M) ;GET THE USERS JOB NUMBER
PUSHJ P,FNDMDR ;FIND HIS MDR
JUMPF .RETT ;NOT THERE,,RETURN NOW
LCKM.0: LOAD P2,.MRCNT(AP),MR.CNT ;GET THE VSL REQUEST COUNT
MOVNS P2 ;NEGATE IT
MOVSS P2 ;MOVE RIGHT TO LEFT
HRRI P2,.MRVSL(AP) ;CREATE VSL SEARCH AOBJN AC
LCKM.1: MOVE S1,0(P2) ;PICK UP A VSL ADDRESS
LOAD P1,.VSFLG(S1),VS.TYP ;GET THE VOL SET TYPE
SKIPE .VSUCB(S1) ;IS THE VOL SET MOUNTED
CAXE P1,%DISK ; AND IS IT A STRUCTURE ???
JRST LCKM.2 ;NO TO EITHER,,TRY NEXT
MOVE S2,.VSVOL(S1) ;PICK UP THE VOL BLK ADDRESS
LOAD P1,.VLFLG(S2),VL.LCK ;GET THE VOL LOCK CODE
CAXN P1,%LOCKD ;IS IT LOCKED ???
PUSHJ P,D$DSLM ;YES,,TAKE THE STRUCTURE AWAY !!!
LCKM.2: AOBJN P2,LCKM.1 ;CHECK ALL VSL'S
$RETT ;THEN RETURN
> ;END TOPS10 CONDITIONAL
SUBTTL VSREOV - ROUTINE TO SEND END OF VOLUME MSG TO TAPE LABELER
;Send a End Of Volume-Set Message to the Tape Labeler on a Volume
; Switch Request in which there are no more Volumes in the
; Set.
;CALL: S1/ The UCB Address
; S2/ Returned status (%VEOF, %VABT, %VTMV)
;
;RET: True Always
TOPS10 <
VSREOV: PUSHJ P,.SAVE1 ;SAVE P1 FOR A MINUTE
MOVE P1,S1 ;SAVE THE UCB ADDRESS
PUSH P,S2 ;SAVE THE STATUS BITS
MOVX S1,.QOVSD ;GET VOLUME SET DIRECTIVE MSG TYPE
PUSHJ P,LBLHDR ;SETUP THE MSG TO TAPE LABELER
AOS G$MSG+.OARGC ;BUMP ARG COUNT BY 1
POP P,G$MSG+.MSFLG ;INSERT THE STATUS BITS
MOVEI S2,G$MSG+.OHDRS ;GET THE FIRST BLOCK ADDRESS
MOVX S1,.VSDBL ;GET THE BLOCK TYPE
STORE S1,ARG.HD(S2),AR.TYP ;SAVE IN THE MESSAGE
MOVX S1,ARG.DA+VSDLEN ;GET THE BLOCK LENGTH
STORE S1,ARG.HD(S2),AR.LEN ;SAVE IT IN THE MESSAGE
ADDM S1,G$SAB##+SAB.LN ;BUMP THE SAB LENGTH
MOVSS S1 ;MOVE RIGHT TO LEFT
ADDM S1,G$MSG+.MSTYP ;AND BUMP THE MESSAGE LENGTH
ADDI S2,ARG.DA ;POINT TO THE BLOCK DATA
MOVE S1,.UCBNM(P1) ;GET THE OLD DEVICE NAME
MOVEM S1,.VSDID(S2) ;SAVE IT IN THE MESSAGE
SETZM .VSDCD(S2) ;NO NEW DEVICE NAME !!!
PUSHJ P,C$SEND## ;SEND THE MSG OFF
$RETT ;AND RETURN
> ;END TOPS10 CONDITIONAL
SUBTTL REIMSG - ROUTINE TO SEND REINITIALIZATION MESSAGE TO PULSAR
;[1164] The REINIT message is really an device INITIALIZATION message
;[1164] with a couple extra arg blocks. The message is sent to PULSAR
;[1164] when the user specifies /NEW-VOLUME in his/her mount command.
;[1164] The allows to user to reinitalize the tapes before useing them.
;[1164] Offsets for prototype reinit message
.TAPOF==.OHDRS ;[1164] DEVICE BLOCK OFFSET
.RIDOF==.TAPOF+ARG.SZ+1 ;[1164] REQUEST ID BLOCK OFFSET
.DVIOF==.RIDOF+ARG.SZ ;[1164] DEVICE INI BLOCK OFFSET
.LBTOF==.DVIOF+1 ;[1164] LABEL TYPE BLOCK OFFSET
.DENOF==.LBTOF+ARG.SZ ;[1164] DENSITY BLOCK OFFSET
.PROOF==.DENOF+ARG.SZ ;[1164] PROTECTION BLOCK OFFSET
.OWNOF==.PROOF+ARG.SZ ;[1164] OWNER PPN
.HLDOF==.OWNOF+ARG.SZ ;[1164] HOLD TAPE BLOCK OFFSET
.OVROF==.HLDOF+1 ;[1164] OVERRIDE EXP DATE OFFSET
.CTROF==.OVROF+1 ;[1164] COUNT BLOCK OFFSET
.NEWOF==.CTROF+ARG.SZ ;[1164] NEW-VOLUME BLOCK OFFSET
.LISOF==.NEWOF+1 ;[1164] VOL LIST BLOCK OFFSET
REIMSZ==.LISOF+ARG.SZ ;[1164] MINIMUM REINIT MSG SIZE
;[1164] Prototype tape reinitialization mesage sent to PULSAR
REIMSG: $BUILD(REIMSZ)
$SET(.MSTYP,MS.TYP,.ODSTP) ;[1164] SET TAPE FUNCTION
$SET(.OARGC,,^D12) ;[1164] NUMBER OF ARG BLOCKS
$SET(.TAPOF+ARG.HD,,<ARG.SZ+1,,.TAPDV>);[1164] DEVICE BLOCK HEADER
$SET(.RIDOF+ARG.HD,,<ARG.SZ,,.ORREQ>) ;[1164] REQUEST ID BLOCK
$SET(.DVIOF+ARG.HD,,<1,,.DVINI>) ;[1164] DEVICE INI FUNCTION
$SET(.LBTOF+ARG.HD,,<ARG.SZ,,.SILBT>) ;[1164] LABEL TYPE BLOCK HEADER
$SET(.DENOF+ARG.HD,,<ARG.SZ,,.SIDEN>) ;[1164] DENSITY BLOCK HEADER
$SET(.PROOF+ARG.HD,,<ARG.SZ,,.SIPRO>) ;[1164] PROTECTION BLOCK HEADER
$SET(.OWNOF+ARG.HD,,<ARG.SZ,,.SIOWN>) ;[1164] OWNER PPN
$SET(.HLDOF+ARG.HD,,<1,,.SIHLD>) ;[1164] HOLD TAPE BLOCK
$SET(.OVROF+ARG.HD,,<1,,.SIOVR>) ;[1164] OVERRIDE EXP DATE BLOCK
$SET(.CTROF+ARG.HD,,<ARG.SZ,,.SICTR>) ;[1164] COUNT BLOCK HEADER
$SET(.NEWOF+ARG.HD,,<1,,.SINEW>) ;[1164] NEW-VOLUME BLOCK
$SET(.LISOF+ARG.HD,,<ARG.SZ,,.SILST>) ;[1164] VOL LIST BLOCK
$EOB
;Build reinit message in prototype and then copy to G$MSG.
REINIT: PUSHJ P,.SAVE4 ;[1164] SAVE P1-P4
DMOVE P1,S1 ;[1164] GET P1 = UCB, P2 = VSL
SETZM REIMSG+.TAPOF+ARG.DA+1 ;[1164] ZERO THIS WORD
MOVE S1,[POINT 6,.UCBNM(P1)] ;[1164] MAKE SOURCE BYTE POINTER
MOVE S2,[POINT 7,<REIMSG+.TAPOF+ARG.DA>] ;[1164] GET DEST BP
PUSHJ P,SX2ASC ;[1164] CONVERT SIXBIT TO ASCII (SIGH)
MOVE S1,.VSRID(P2) ;[1164] GET REQUEST ID
MOVEM S1,REIMSG+.RIDOF+ARG.DA ;[1164] STORE IN MSG
LOAD S1,.VSFLG(P2),VS.LBT ;[1164] GET LABEL TYPE
MOVEM S1,REIMSG+.LBTOF+ARG.DA ;[1164] STORE IN MSG
MOVX S2,.TFD00 ;[1164] ASSUME DENSITY DEFAULTED
MOVX S1,VS.DDN ;[1164] GET DEFAULTED DENSITY BIT
TDNN S1,.VSATR(P2) ;[1164] DID WE DEFAULT THE DENSITY?
LOAD S2,.VSATR(P2),VS.DEN ;[1164] NO,,GET DENSITY USER WANTS
MOVEM S2,REIMSG+.DENOF+ARG.DA ;[1164] STORE IN MSG
SETOM S2 ;[1164] ASSUME PROTECTION NOT SPECIFIED
MOVX S1,VS.DPR ;[1164] GET DEFAULT PROTECTION BIT
TDNN S1,.VSATR(P2) ;[1164] DID USER SPECIFY /PROT:?
LOAD S2,.VSATR(P2),VS.PRT ;[1164] YES,,GET PROTECTION HE WANTS
MOVEM S2,REIMSG+.PROOF+ARG.DA ;[1164] STORE IN MSG
MOVE S1,.MRUSR(AP) ;[1164] GET REQUESTOR'S PPN
MOVEM S1,REIMSG+.OWNOF+ARG.DA ;[1164] STORE IN MSG
LOAD S1,.VSCVL(P2),VS.CNT ;[1164] GET VOL COUNT
MOVEM S1,REIMSG+.CTROF+ARG.DA ;[1164] STORE IN MSG
MOVN P3,S1 ;[1164] SAVE NEGATIVE VOL COUNT
ADDI S1,1 ;[1164] GET CORRECT LENGTH FOR .SILST BLK
STORE S1,REIMSG+.LISOF+ARG.HD,AR.LEN ;[1164] SET CORRECT LENGTH
ADDI S1,REIMSZ-2 ;[1164] COMPUTE MSG SIZE
STORE S1,REIMSG+.MSTYP,MS.CNT ;[1164] STORE IN MSG
MOVE S2,[REIMSG,,G$MSG] ;[1164] COPY OUR MSG TO G$MSG BUFFER
BLT S2,G$MSG-1(S1) ;[1164] ..
HRLZS P3 ;[1164] MAKE AOBJN PTR FOR VOLS
HRRI P3,G$MSG+.LISOF+ARG.DA ;[1164] ..
;[1164] Copy VOLIDs to reinit message.
MOVEI P4,.VSVOL(P2) ;[1164] GET ADDR TO 1ST VOL BLOCK PTR
REIN.1: SKIPN S1,(P4) ;[1164] GET VOL BLOCK ADDR
STOPCD (MVP,HALT,,<Missing VOL block pointer>) ;[1164] OOPS!!!
MOVE S2,.VLNAM(S1) ;[1164] GET VOLID
MOVEM S2,(P3) ;[1164] STORE IN MESSAGE
MOVEI S2,%STAIN ;[1164] STATUS CODE FOR 'INITIALIZING'
STORE S2,.VLFLG(S1),VL.STA ;[1164] SET FOR ACCURATE QUEUE LISTINGS
ADDI P4,1 ;[1164] BUMP VOL BLOCK ADDR PTR
AOBJN P3,REIN.1 ;[1164] LOOP FOR ALL VOLS
;[1164] Send message to PULSAR and finish up.
MOVE S1,.VSFLG(P2) ;[1164] GET VSL FLAGS
TXZ S1,VS.NEW ;[1164] TURN OFF NEW-VOLUME BIT
TXO S1,VS.INI ;[1164] TURN ON REINIT-PROGRESS BIT
MOVEM S1,.VSFLG(P2) ;[1164] PUT FLAGS BACK
MOVX S1,UC.INI ;[1164] GET INI BIT FOR UCB
IORM S1,.UCBST(P1) ;[1164] LITE IT IN UCB STATUS WORD
MOVEI M,G$MSG ;[1164] GET MSG ADDR IN M
PJRST I$FPLR## ;[1164] SEND MESSAGE TO PULSAR
;[1164] ;Convert SIXBIT to ASCII
;[1164]
;[1164] S1 = Source BP
;[1164] S2 = Destination BP
;[1164] Only 6 chars are converted and S1, S2 are returned updated
SX2ASC: $SAVE <T1,T2> ;[1164] SAVE T1, T2
MOVEI T2,6 ;[1164] ONLY 6 CHARS CONVERTED
SX2A.1: ILDB T1,S1 ;[1164] GET A BYTE
ADDI T1,40 ;[1164] ASCIIZE
IDPB T1,S2 ;[1164] STORE IN DESTINATION
SOJG T2,SX2A.1 ;[1164] LOOP FOR 6 CHARS
POPJ P, ;[1164] RETURN
SUBTTL DELETE - ROUTINE TO DELETE ALL NEW VOL SETS FOR A USER
;CALL: S1/ The VSL Address of one of those to be deleted
; AP/ The MDR Address
;
;RET: True Always
;A NEW Volume Set is defined to be one whose LINK code is the
;same as the one in the VSL that was passed as an argument
;to this routine AND whose VS.WAL bit is still up.
D$DLVS:: ;MAKE IT GLOBAL
DELETE: PUSHJ P,.SAVE3 ;SAVE P1 & P2 & P3 FOR A MINUTE
LOAD P2,.MRCNT(AP),MR.CNT ;GET THE VSL COUNT
JUMPE P2,DELMDR ;NOTHING THERE,,DELETE THE MDR
LOAD P1,.VSLNK(S1),VS.LNK ;GET THE LINK CODE WE ARE LOOKING FOR
MOVEI P3,.MRVSL(AP) ;POINT TO THE VSL LIST
DELE.1: MOVE S1,0(P3) ;GET A VSL ADDRESS
LOAD S2,.VSLNK(S1),VS.LNK ;GET ITS LINK CODE
LOAD TF,.VSFLG(S1),VS.WAL ;GET THE WAITING FOR ALLOCATION BIT
CAMN P1,S2 ;DO THE LINK CODES MATCH ???
SKIPN TF ; AND IS HE WAITING FOR ALLOCATION ???
JRST DELE.2 ;WRONG LINK CODE OR NOT WAITING,,SKIP
PUSHJ P,DELVSL ;YES,,DELETE THE VSL
SKIPA ;LOOK AT NEXT VSL
DELE.2: AOS P3 ;POINT TO THE NEXT VSL ADDRESS
SOJG P2,DELE.1 ;CONTINUE FOR ALL VSL'S
LOAD S1,.MRCNT(AP),MR.CNT ;GET THE VSL COUNT
SKIPN S1 ;THERE ARE MORE,,DON'T DELETE THE MDR
PUSHJ P,DELMDR ;NO MORE REQUESTS,,DELETE THIS MDR
$RETT ;RETURN
SUBTTL REMOVE - ROUTINE TO DELETE A SPECIFIC VSL AND RETRY THE MOUNT
;CALL: S1/ The VSL Address
; AP/ The MDR Address
;
;RET: True Always
TOPS10<
D$REMO::
REMOVE: PUSHJ P,.SAVE1 ;SAVE P1 FOR A SECOND
LOAD P1,.VSLNK(S1),VS.LNK ;GET THE VSL LINK CODE
PUSHJ P,DELVSL ;DELETE THE BAD VSL
LOAD S2,.MRCNT(AP),MR.CNT ;ANY REQUESTS LEFT ???
JUMPE S2,DELMDR ;NO,,DELETE HIS MDR
MOVNS S2 ;NEGATE THE COUNT
MOVSS S2 ;MOVE RIGHT TO LEFT
HRRI S2,.MRVSL(AP) ;CREATE VSL SEARCH AOBJN AC
REMO.1: MOVE S1,0(S2) ;GET A VSL ADDRESS
LOAD TF,.VSLNK(S1),VS.LNK ;GET ITS LINK CODE
CAME TF,P1 ;DO THEY MATCH ???
JRST [AOBJN S2,REMO.1 ;NO,,TRY NEXT
$RETT ] ;NO MORE,,RETURN
MOVE P1,S1 ;SAVE THE VSL ADDRESS
PUSHJ P,D$ALOC ;TRY TO PERFORM ALLOCATION ONCE AGAIN
JUMPF [JUMPL S1,.RETT ;ALLOCATION POSTPONED,,JUST RETURN
MOVE S1,P1 ;NO GOOD,,GET THE VSL ADDRESS BACK
PJRST DELETE ] ; AND DELETE THE VOL SETS JUST ADDED
MOVE S1,P1 ;GET THE VSL ADDRESS BACK
PUSHJ P,MNTVSL ;RETRY THE MOUNT
$RETT ;RETURN
> ;END TOPS10 CONDITIONAL
SUBTTL DELVSL - ROUTINE TO DELETE A VSL
;CALL: S1/ The VSL Address
; AP/ The MDR Address
;
;RET: True Always
;AC Usage in this Subroutine
;
; P1/ VSL Entry
; P2/ VOL Entry
; P3/ UCB Entry
; P4/ VOL AOBJN AC
TOPS10<
D$DVSL::
DELVSL: PUSHJ P,.SAVE4 ;SAVE P1-P4
MOVEI P1,(S1) ;GET THE VSL ADDRESS IN P1
CAIN P1,TMPVSL ;IS THIS TEMPORARY VSL?
JRST DELV.0 ;YES..DON'T TRY TO DELETE IT
MOVE S2,.VSFLG(P1) ;GET THE VSL FLAG WORD
TXO S2,VS.UAL ;LITE 'USER ALLOCATED' TO STOP RECURSION
MOVEM S2,.VSFLG(P1) ;SAVE THE NEW VSL STATE
MOVE S1,P1 ;GET BACK VSL ADRS
PUSHJ P,ALCVSL ;RETURN HIS RESOURCES TO THE ALLOC POOL
MOVE S1,P1 ;RESTORE THE VSL ADDRESS
LOAD S2,.VSFLG(S1),VS.WAL ;GET THE 'WAITING FOR ALLOCATION' BIT
SKIPN S2 ;IF ALLOCATED,,THEN
PUSHJ P,RETBMA ; REMOVE HIS CLAIM ON THESE RESOURCES
DELV.0: LOAD P4,.VSCVL(P1),VS.CNT ;GET THE VOLUME COUNT
JUMPE P4,DEL.8A ;NO VOLUMES,,SKIP THIS
MOVNS P4 ;MAKE IT NEGATIVE
HRLZS P4 ;CREATE A VOL AOBJN AC (-COUNT,,0)
HRRI P4,.VSVOL(P1) ;GET THE VOL LIST ADDRESS IN RIGHT HALF
DELV.1: MOVE P2,0(P4) ;PICK UP THE CURRENT VOL ADDRESS
LOAD S1,.VLOWN(P2),VL.CNT ;GET THE VSL COUNT IN S1
MOVNS S1 ;MAKE IT NEGATIVE
HRLZS S1 ;MOVE RIGHT TO LEFT
HRRI S1,.VLVSL(P2) ;CREATE A VSL AOBJN AC
DELV.2: MOVE P3,0(S1) ;PICK UP THE VSL ADDRESS + FLAGS IN P3
CAIN P1,0(P3) ;FIND THIS USERS VSL ADDRESS IN THE VOL
JRST DELV.3 ; ENTRY.
AOBJN S1,DELV.2 ;CONTINUE TILL FOUND
STOPCD (CFV,HALT,,<Can't find VSL address in VOL entry>)
DELV.3: $PACK S1 ;PACK THE VOL VSL LIST
DECR .VLOWN(P2),VL.CNT ;AND DECRIMENT THE USER REQUEST COUNT
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
DELV.5: SKIPN S2,.VLUCB(P2) ;IS THE VOLUME MOUNTED ???
JRST [MOVE S1,P2 ;NO,,GET THE VOL ADDRESS IN S1
PUSHJ P,DELVOL ; DELETE THE VOLUME
JRST DELV.8 ] ; AND GET THE NEXT VOLUME
LOAD S1,.UCBST(S2),UC.DVT ;GET THE DEVICE TYPE
CAIN S1,%DISK ;STRUCTURE?
JRST DELV.8 ;YES,,GET NEXT VOLUME
LOAD S1,.VLOWN(P2),VL.CNT ;GET THE REQUEST COUNT
JUMPG S1,DELV.6 ;MULTIPLE REQUESTORS,,TRY ALLOCATION
JRST DELV.7 ;OTHERWISE UNLOAD THE DRIVE
;Here when a volume referenced by the VSL has other requestors
;See if we can give the volume to another requestor.
DELV.6: LOAD S1,.UCBST(S2),UC.DVT ;GET THE DEVICE TYPE
CAIN S1,%DTAP ;DECTAPE?
JRST DEL.6A ;YES--SKIP LABELED MAGTAPE STUFF
LOAD S1,.VLFLG(P2),VL.LBT ;GET LABEL TYPE
PUSHJ P,GETLBT ;AND MAP TO EASY CODE
CAXE S1,%LABEL ;IS IT A LABELED VOLUME?
JRST DELV.7 ;NO, UNLOAD THIS USER'S TAPE
DEL.6A: MOVE S1,.VLUCB(P2) ;COPY UCB NAME TO ARG REG
PUSHJ P,MATUNI ;TRY TO GIVE IT AWAY
JRST DELV.8 ;CONTINUE WITH NEXT VOLUME
DELV.7: MOVE S1,P2 ;AIM AT THIS VOLUME
TXNE P3,VL.OWN ;DID WE EVER OWN THIS VOLUME ???
PUSHJ P,VLUNLO ;UNLOAD AND BREAK LINKS FOR THIS VOL
DELV.8: AOBJN P4,DELV.1 ;CONTINUE THROUGH ALL VOLUMES
DEL.8A: LOAD S1,.MRCNT(AP),MR.CNT ;GET THE VSL COUNT IN S1
MOVNS S1 ;MAKE THE VSL COUNT NEGATIVE
HRLZS S1 ;MOVE RIGHT TO LEFT
HRRI S1,.MRVSL(AP) ;POINT TO THE VSL ADDRESS LIST
DELV.9: CAME P1,0(S1) ;FIND THE VSL POS IN THE MDR VSL LIST
JRST [AOBJN S1,DELV.9 ;NOT FOUND,,TRY ALL VSL ADDRESSES
STOPCD (VAM,HALT,,<VSL address is missing in a MDR>) ] ;NONE,,TROUBLE !
$PACK S1 ;PACK THE MDR VSL LIST
DECR .MRCNT(AP),MR.CNT ;AND DECREMENT THE MDR VSL COUNT BY 1
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
MOVEI S1,.VSVSN(P1) ;POINT TO THE VOLUME-SET NAME
LOAD S2,.VSFLG(P1),VS.TYP ;GET THE REQUEST TYPE
CAIE S2,%DISK ;DON'T DELETE STRUCTURES (SHARABLE)
PUSHJ P,V$DELE## ;POSSIBLY DELETE CATALOG CACHE ENTRY
CAIN P1,TMPVSL ;IS THIS THE TEMP VSL ???
$RETT ;YES,,JUST RETURN NOW
MOVE S1,VSLQUE ;GET THE VSL QUEUE ID IN S1
MOVE S2,P1 ;GET THE VSL ADDRESS IN S2
PUSHJ P,L%APOS ;POSITION TO THE VSL ENTRY
PUSHJ P,L%DENT ;DELETE THIS VSL ENTRY
$RETT ;RETURN
>
TOPS20 <
D$DVSL::
DELVSL: PUSHJ P,.SAVE4 ;SAVE P1-P4
MOVE P1,S1 ;GET THE VSL ADDRESS IN P1
LOAD P4,.VSCVL(P1),VS.CNT ;GET THE VOLUME COUNT
JUMPE P4,DELV.2 ;NO VOLUMES,,JUST DELETE THE VSL
MOVNS P4 ;MAKE IT NEGATIVE
HRLZS P4 ;CREATE A VOL AOBJN AC (-COUNT,,0)
HRRI P4,.VSVOL(P1) ;GET THE VOL LIST ADDRESS IN RIGHT HALF
DELV.1: MOVE P2,0(P4) ;PICK UP THE CURRENT VOL ADDRESS
SKIPE P3,.VLUCB(P2) ;PICK UP THE CURRENT UCB ADDRESS
SETZM .UCBVL(P3) ;CLEAR THE VOL POINTER IN THE UCB
MOVE S1,VOLQUE ;GET THE VOL QUEUE ID
MOVE S2,P2 ;GET THE VOLUME ENTRY ADDRESS
PUSHJ P,L%APOS ;POSITION TO THE VOLUME ENTRY
PUSHJ P,L%DENT ;AND DELETE IT
AOBJN P4,DELV.1 ;CONTINUE THROUGH ALL VOLUMES
DELV.2: LOAD S1,.MRCNT(AP),MR.CNT ;GET THE VSL COUNT IN S1
MOVNS S1 ;MAKE THE VSL COUNT NEGATIVE
HRLZS S1 ;MOVE RIGHT TO LEFT
HRRI S1,.MRVSL(AP) ;POINT TO THE VSL ADDRESS LIST
DELV.3: CAME P1,0(S1) ;FIND THE VSL POS IN THE MDR VSL LIST
JRST [AOBJN S1,DELV.3 ;NOT FOUND,,TRY ALL VSL ADDRESSES
STOPCD (VAM,HALT,,<VSL address is missing in a MDR>) ] ;NONE,,TROUBLE !
$PACK S1 ;PACK THE MDR VSL LIST
DECR .MRCNT(AP),MR.CNT ;AND DECREMENT THE MDR VSL COUNT BY 1
CAIN P1,TMPVSL ;IS THIS THE TEMPORARY VSL ???
$RETT ;YES,,THEN NOTHING TO DELETE !!
MOVE S1,VSLQUE ;GET THE VSL QUEUE ID
MOVE S2,P1 ;GET THE VSL ADDRESS
PUSHJ P,L%APOS ;POSITION TO THE VSL
PUSHJ P,L%DENT ;AND DELETE IT
$RETT ;RETURN
>
SUBTTL ALCVSL - ROUTINE TO RETURN A VSL TO THE ALLOCATION POOL
;CALL: S1/ The VSL Address
;
;RET: TRUE ALWAYS
TOPS10<
D$ALCV:: ;MAKE IT GLOBAL
ALCVSL: PUSHJ P,.SAVE1 ;SAVE P1
HRRZ P1,S1 ;SAVE THE VSL ADDRESS
MOVE S1,P1 ;GET JUST THE VSL ADDRESS
PUSHJ P,CHKOWN ;LOCATE THIS GUYS VSL ADDRESS
MOVX S2,VL.ASK+VL.ASN ;GET ASKED+ASSIGNED STATUS BITS
ANDCAM S2,0(S1) ; AND CLEAR THEM
MOVE S1,P1 ;RESTORE THE VSL ADDRESS
PUSHJ P,RETA%C ;RETURN THE 'A' AND 'C' MATRIX RESOURCES
SKIPN S1,.VSUCB(P1) ;GET ANY UCB ADDRESS
JRST ALCV.2 ;NONE THERE,,SKIP THIS
SETZM .VSUCB(P1) ;CLEAR THE VSL'S UCB POINTER
SETZM .UCBVS(S1) ;CLEAR THE UCB'S VSL POINTER
MOVX S2,UC.VSW ;GET THE VOLUME SWITCH FLAG
ANDCAM S2,.UCBST(S1) ;CLEAR IT
LOAD S2,.VSFLG(P1),VS.TYP ;GET VOLUME SET TYPE
CAXN S2,%TAPE ;IS THIS A TAPE VOLUME SET?
PUSHJ P,SNDVDM ;TELL TAPE LABELER USER IS GONE
ALCV.2: MOVX S1,VS.ALC+VS.OPR ;GET THE 'ALLOCATION'+'OPR' BITS
IORM S1,.VSFLG(P1) ;LITE THEM
ZERO .VSFLG(P1),VS.VSW ;CLEAR THE VOLUME SWITCH FLAG
ZERO .VSCVL(P1),VS.OFF ;RESET THE CURRENT VOL OFFSET
ZERO .VSLNK(P1),VS.LNK ;ALSO ZAP THE LINK CODE
SKIPN S1,.VSTXT(P1) ;ANY SECONDARY TEXT ???
JRST ALCV.3 ;NO,,SKIP THIS
LOAD S2,S1,VS.ADR ;GET THE TEXT ADDRESS IN S2
LOAD S1,S1,VS.LEN ;GET THE TEXT LENGTH IN S1
PUSHJ P,M%RMEM ;RETURN IT TO THE FREE POOL
SETZM .VSTXT(P1) ;AND ZAP THE POINTER
ALCV.3: MOVE S1,P1 ;GET THE VSL ADDRESS
LOAD S2,.VSFLG(S1),VS.UAL ;GET THE 'USER ALLOCATED' BIT
SKIPN S2 ;IF 'USER ALLOC',DONT DELETE VSL
PUSHJ P,DELVSL ;DELETE THE VSL
$RETT ;RETURN
> ;END TOPS10 CONDITIONAL
SUBTTL DELMDR - ROUTINE TO DELETE AN MDR
;CALL: AP/ The MDR Address
;
;RET: True Always
DELMDR:
TOPS10< PUSHJ P,D$BMTX ;FIND THE USERS 'B' MATRIX ENTRY
JUMPF DELM.1 ;NONE THERE,,SKIP THIS
PUSHJ P,L%DENT ;DELETE IT
PUSHJ P,D$CMTX ;FIND THE USERS 'C' MATRIX ENTRY
SKIPF ;NONE THERE,,SKIP
PUSHJ P,L%DENT ;DELETE IT
SOS PROCNT ;ADJUST THE PROCESS COUNT
> ;END TOPS10 CONDITIONAL
DELM.1: SKIPE S1,.MRQEA(AP) ;ANY QE ???
SETZM .QEMDR(S1) ;YES,,ZAP IT
MOVE S1,MDRQUE ;GET THE MDR QUEUE ID
MOVE S2,AP ;GET THE MDR ADDRESS
PUSHJ P,L%APOS ;POSITION TO THAT MDR ENTRY
PUSHJ P,L%DENT ;DELETE IT
$RETT ;AND RETURN
SUBTTL DELVOL - ROUTINE TO DELETE VOL BLOCKS FROM THE VOL QUEUE
;CALL: S1/ The VOL Address of the VOL you want deleted
;
;RET: True Always
;This routine will delete the volume whose address is passed in S1
;And also delete any VOL Blocks connected to that VOL which can
;Be Deleted
TOPS10 <
DELVOL: PUSHJ P,.SAVE3 ;SAVE P1 & P2 & P3 FOR A MINUTE
MOVE P2,S1 ;SAVE ORIGIONAL VOL ADDR HERE
DELX.0: MOVE P1,S1 ;SAVE AS CURRENT ALSO
LOAD S1,.VLPTR(P1),VL.PRV ;FIND THE PRI VOLUME BLOCK
JUMPN S1,DELX.0 ; IN THE VOL QUEUE
LOAD S1,.VLFLG(P1),VL.STA ;GET THE STRUCTURE STATUS BITS
CAXN S1,%STAMN ;IS IT MOUNTED ???
$RETT ;YES,,JUST RETURN
SKIPE S1,.VLUCB(P2) ;IS THE ARG VOLUME MOUNTED ON A DRIVE ?
SETZM .UCBVL(S1) ;YES,,BREAK UCB VOL LINK
SETZM .VLUCB(P2) ;BREAK VOL UCB LINKS
LOAD S1,.VLOWN(P1),VL.CNT ;GET THE REQUEST COUNT
JUMPN S1,.RETT ;NOT ZERO,,DON'T DELETE THE VOLUME
LOAD S1,.VLFLG(P1),VL.RSN ;GET THE VOLUME RESOURCE NUMBER
PUSHJ P,GIVRSN ;GIVE BACK THAT RESOURCE
DELX.1: MOVE S2,P1 ;GET THE PRI VOL BLK ADDRESS IN S2
LOAD P1,.VLPTR(P1),VL.NXT ;GET NEXT VOL BLK ADDRESS
SKIPE S1,.VLUCB(S2) ;IS THE VOLUME MOUNTED ???
SETZM .UCBVL(S1) ;YES,,ZAP UCB/VOL POINTER
MOVE S1,VOLQUE ;NO,,GET THE VOLUME QUEUE ID
PUSHJ P,L%APOS ;POSITION TO THAT ENTRY
PUSHJ P,L%DENT ;AND DELETE IT
JUMPN P1,DELX.1 ;IF MORE VOL BLKS,,PROCESS'EM
$RETT ;ELSE RETURN
>
SUBTTL GETLBT - ROUTINE TO RECODE THE VOLUME LABEL TYPE
;CALL: S1/ The Volume Label Type
;
;RET: S1/ either %UNLBL (Unlabeled) or %LABEL (Labeled)
TOPS10 <
D$GLBT::
GETLBT: CAXE S1,.TFLBP ;IS THE LABEL TYPE BYPASS LABELS ???
CAXN S1,.TFLTM ;OR IS IT LEADING TAPE MARK ???
JRST GETL.1 ;YES,,EXIT
CAXE S1,.TFLNS ;IS THE LABEL TYPE NON-STANDARD LABESL ?
CAXN S1,.TFLNL ;OR IS IT NO LABELS ???
SKIPA ;YES,,UNLABELED !!!
CAXN S1,.TFLNV ;UNLABELED/NO EOV PROCESSING,,UNLABELED
GETL.1: SKIPA S1,[%UNLBL] ;RETURN %UNLBL IN S1
MOVX S1,%LABEL ;IF LABELED,,RETURN %LABEL IN S1
$RETT ;RETURN
>
SUBTTL FNDDSK - ROUTINE TO FIND A DSK VOL BLOCK USING VOLUME ID
; FNDVOL - ROUTINE TO FIND A VOL BLOCK LINKED TO A UCB (SPINNING)
;CALL: S1/ The Volume ID in Sixbit
;
;RET: S1/ The VOL Block Address
TOPS10 <
FNDVOL: TDZA S2,S2 ;[1227] INDICATE ENTRY POINT
FNDDSK: SETOM S2 ;[1227]
PUSHJ P,.SAVE2 ;[1227] SAVE P1 & P2 FOR A MINUTE
DMOVE P1,S1 ;[1227] SAVE THE VOL ID WE ARE LOOKING FOR
MOVE S1,VOLQUE ;GET THE VOL QUEUE ID
PUSHJ P,L%FIRST ;GET THE FIRST ENTRY
JRST FNDD.2 ;SKIP THE FIRST TIME THROUGH
FNDD.1: MOVE S1,VOLQUE ;GET THE VOL QUEUE ID
PUSHJ P,L%NEXT ;GET THE NEXT VOL BLOCK
FNDD.2: JUMPF .RETF ;NO MORE,,RETURN VOL NOT FOUND
CAME P1,.VLVID(S2) ;YES,,IS THIS THE VOL WE WANT ???
JRST FNDD.1 ;NO,,SKIP IT
;**;[1227] Change code at FNDD.2+3L. /LWS
JUMPL P2,FNDD.3 ;[1227] IF FNDDSK, JUST RETURN VOL ADDR
SKIPN .VLUCB(S2) ;[1227] ELSE SEE IF VOL IS LINKED TO UCB
JRST FNDD.1 ;[1227] IT'S NOT, KEEP LOOKING
FNDD.3: MOVE S1,S2 ;[1227] RETURN THE VOL BLOCK ADDRESS IN S1
$RETT ;AND RETURN
> ;END TOPS10
SUBTTL CREVOL - ROUTINE TO CREATE A VOL BLOCK IN VOL QUEUE
;CALL: No Calling Parms
;
;RET: S1/ The VOL Queue Entry
D$CVOL::
CREVOL: MOVE S1,VOLQUE ;GET THE VOL QUEUE ID
PUSHJ P,L%LAST ;POSITION TO THE LAST VOL ENTRY
MOVE S1,VOLQUE ;GET THE VOL QUEUE ID
MOVX S2,VOLLEN ;AND THE VOL ENTRY LENGTH
PUSHJ P,L%CENT ;CREATE A VOL QUEUE ENTRY
MOVE S1,S2 ;GET THE ENTRY ADDRESS IN S1
$RETT ;AND RETURN
SUBTTL USRACK - ROUTINE TO GENERATE AN ACK TO THE USER FOR MOUNT/ALLOC
;CALL: AP/ The MDR Address
;
;RET: True Always
USRACK: PUSHJ P,.SAVE4 ;[1173] SAVE P1 - P4
PUSHJ P,MDASBP ;SET UP FOR CALLS TO MDADBP
SETZB P4,G$MSG## ;[1173] CLEAR P4 AND FIRST WORD OF MSG
SKIPN G$OPRA## ;OPERATOR ON DUTY?
$TEXT (MDADBP,<% No operator on duty>) ;NO
LOAD P1,.MRCNT(AP),MR.CNT ;GET THE VSL COUNT
MOVNS P1 ;NEGATE IT
MOVSS P1 ;MOVE RIGHT TO LEFT
HRRI P1,.MRVSL(AP) ;CREATE VSL AOBJN AC
LOAD S2,.MRCNT(AP),MR.LNK ;GET THE CURRENT VSL LINK CODE
USRA.1: MOVE P2,0(P1) ;GET A VSL ADDRESS
LOAD S1,.VSLNK(P2),VS.LNK ;GET THE VSL LINK CODE
CAME S1,S2 ;DO THEY MATCH ???
JRST USRA.2 ;NO,,SKIP IT
LOAD P3,.VSFLG(P2),VS.ALC ;GET THE ALLOCATE BIT
$TEXT (MDADBP,<[^T/@TYPE(P3)/ request ^T/.VSVSN(P2)/ queued, request #^D/.VSRID(P2)/]>)
MOVE P4,P2 ;[1173] SAVE VSL ADDRESS
USRA.2: AOBJN P1,USRA.1 ;LOOP THROUGH ALL VSL'S
JUMPE P4,.RETT ;[1173] SHOULDN'T HAPPEN, BUT.....
SETZM S1 ;GET A NULL BYTE
PUSHJ P,MDADBP ;MAKE IT ASCIZ
;**;[1170] Insert 3 lines after USRA.2+2L. 29-Dec-83 /LWS
MOVE S1,.VSRFL(P4) ;[1173] [1170] GET VSL ACK DATA FLAGS
TXZE S1,MR.GFR ;[1173] CLEAR GOPHER BIT
EXCH S1,.VSRFL(P4) ;[1173] GET ORIGINAL BITS AND UPDATE TOO
JUMPN P3,USRA.3 ;[1173] [1170] ALWAYS TRY TO GIVE ALLOC ACK
TXNE S1,MR.GFR ;[1173] [1170] GOPHER ONLY WANTS ACK WHEN MOUNTED
$RETT ;[1173] RETURN
USRA.3: MOVE S1,P4 ;[1173] GET VSL ADDRESS
SETOM S2 ;[1173] USE MDR ACK DATA IF VALID
PUSHJ P,USRNOT ;NOTIFY THE USER
$RETT ;AND RETURN
TYPE: [ASCIZ/Mount/]
[ASCIZ/Allocate/]
SUBTTL ACKUSR - ROUTINE TO CREATE AN ACK AFTER THE VOL SET IS MOUNTED
;CALL: S1/ The VSL Address
;
;RET: True Always
ACKUSR: PUSHJ P,.SAVE4 ;SAVE P1 - P4
$SAVE <T3> ;[1173] SAVE T3, TOO
STKVAR <<QUE,^D30>> ;SETUP A QUEUE FOR VSL'S
LOAD P1,.VSLNK(S1),VS.LNK ;GET THE VOL SET LINK CODE
MOVE AP,.VSMDR(S1) ;GET THE MDR ADDRESS
SETZM G$MSG## ;CLEAR THE FIRST WORD OF ACK BUFFER
PUSHJ P,MDASBP ;SET UP FOR CALLS TO MDADBP
LOAD P2,.MRCNT(AP),MR.CNT ;GET THE VSL REQUEST COUNT
MOVNS P2 ;NEGATE IT
MOVSS P2 ;MOVE RIGHT TO LEFT
HRRI P2,.MRVSL(AP) ;CREATE VSL AOBJN AC
MOVEI P3,QUE ;GET THE VSL QUEUE ADDRESS
HRLI P3,-^D30 ;GEN THE QUEUE STACK POINTER
PUSH P3,[-1] ;MARK THE END OF THE QUEUE
;Check to make sure user has all required volume sets assigned
ACKU.1: MOVE P4,0(P2) ;GET A VSL ADDRESS
LOAD S2,.VSLNK(P4),VS.LNK ;GET ITS LINK CODE
CAME S2,P1 ;DO THEY MATCH ???
JRST ACKU.2 ;NO,,TRY NEXT VSL
MOVE S1,P4 ;GET THE VSL ADDRESS IN S1
PUSHJ P,CHKOWN ;DOES HE OWN THE VOLUME ???
MOVE S2,(S1) ;GET FLAGS
TXNN S2,VL.AAS ;BUT WAS IT ALREADY ASSIGNED BEFORE?
TXNN S2,VL.ASN ;IS IT ASSIGNED?
$RETF ;NO,,RETURN
PUSH P3,P4 ;YES,,QUEUE UP THE VSL ADDRESS
ACKU.2: AOBJN P2,ACKU.1 ;LOOK FOR ANOTHER
;If we get this far, its OK to ack the user
ACKU.3: POP P3,P4 ;GET A VSL ADDRESS OFF THE QUEUE
CAMN P4,[-1] ;ARE WE DONE ???
JRST ACKU.6 ;YES,,ACK THE USER !!!
MOVE T3,P4 ;[1173] SAVE VSL ADDR FOR ACKING
LOAD P1,.VSCVL(P4),VS.OFF ;GET THE OFFSET TO THE CURRENT VOL
ADDI P1,.VSVOL(P4) ;POINT TO ITS ADDRESS
MOVE P1,0(P1) ;SAVE THE VOL ADDRESS IN P1
SKIPE P2,.VLUCB(P1) ;GET THE UCB ADDRESS IN P2
JRST ACKU.4 ;MUST BE A NON-MDA DEVICE
; Here for non-MDA devices
TOPS10<
MOVE S1,P4 ;GET VSL ADDRESS
PUSHJ P,I$CGEN## ;GET DEVICE TYPE
JUMPF ACKU.3 ;SHOULDN'T HAPPEN
MOVE T1,S1 ;GET INDEX INTO DEVICE NAME TABLE
MOVEI S2,ACKU.X ;ASSUME NO LOGICAL NAME ASSIGNED
SKIPE .VSLNM(P4) ;HAVE A LOGICAL NAME?
MOVEI S2,ACKU.Y ;YES
TDZA TF,TF ;NO JUNK FOR DEVICE TYPE
>
TOPS20 <JRST ACKU.3 ;TOPS20 DOESN'T UNDERSTAND REAL DEVICES
>
; Here for MDA devices
ACKU.4: LOAD TF,.UCBST(P2),UC.DVT ;GET THE DEVICE TYPE
SKIPN S1,.VSTXT(P4) ;ANY ADDITIONAL TEXT ???
MOVEI S1,[0] ;NO,,GET A NULL
CAXN TF,%DISK ;IS THIS A STRUCTURE ???
MOVEI S2,ACKU.D ;YES,,GET TEXT ADDRESS
CAXN TF,%TAPE ;IS IT A TAPE REQUEST ???
PUSHJ P,[MOVEI S2,ACKMTN ;YES,,DEFAULT TO NO LOGICAL NAME
SKIPE .VSLNM(P4) ;UNLESS HE SPECIFIED ONE
MOVEI S2,ACKMTL ; THEN GET TEXT WITH LOGICAL NAME
POPJ P, ] ;RETURN
CAXN TF,%DTAP ;IS IT A DECTAPE REQUEST?
PUSHJ P,[MOVEI S2,ACKDTN ;YES--DEFAULT TO NO LOGICAL NAME
SKIPE .VSLNM(P4) ;UNLESS HE SPECIFIED ONE
MOVEI S2,ACKDTL ;THEN GET TEXT WITH LOGICAL NAME
POPJ P,] ;RETURN
;**;[1144]ADD 6,CHANGE 1 LINES AT ACKU.4:+9L 2-AUG-83/CTK
PUSH P,T2 ;[1144]SAVE T2 FOR A BIT
MOVEI T2,ACKU.N ;[1144]GET NUL MESSAGE
LOAD TF,.VLFLG(P1),VL.LCK ;[1144]GET LOCK BIT
CAXN TF,%LOCKP ;[1144]ARE WE LOCKED ???
MOVEI T2,ACKU.K ;[1144]YES,,GET TEXT ADDRESS
$TEXT (MDADBP,<^T/(S1)/^I/(S2)/^I/(T2)/>) ;[1144]CREATE THE MESSAGE
POP P,T2 ;[1144]RESTORE T2
SKIPN S1,.VSTXT(P4) ;ANY ADDITIONAL TEXT ???
JRST ACKU.3 ;NO,,GET NEXT VSL
LOAD S2,S1,VS.ADR ;GET THE TEXT ADDRESS IN S2
LOAD S1,S1,VS.LEN ;GET THE TEXT LENGTH IN S1
PUSHJ P,M%RMEM ;RETURN IT TO THE FREE POOL
SETZM .VSTXT(P4) ;ZAP THE TEXT POINTER
JRST ACKU.3 ;GET NEXT VSL
ACKU.6: SETZM S1 ;GET A NULL BYTE
IDPB S1,MDBPTR ;MAKE THE ACK ASCIZ
MOVE S1,T3 ;[1173] GET VSL ADDRESS
SETOM S2 ;[1173] USE MDR ACK DATA IF VALID
PUSHJ P,USRNOT ;SEND THE MESSAGE OFF
ZERO .VSRFL(P4),MR.WAT ;[1173] CLEAR THE WAITING FOR ACK BIT
$RETT ;AND RETURN
ACKU.D: ITEXT (<[Structure ^W/.VLNAM(P1)/ mounted]>)
ACKMTN: ITEXT (<[Magtape ^W/.VLNAM(P1)/ mounted on ^W/.UCBNM(P2)/]>)
ACKMTL: ITEXT (<[Magtape ^W/.VLNAM(P1)/ mounted on ^W/.UCBNM(P2)/ with logical name ^W/.VSLNM(P4)/]>)
ACKDTN: ITEXT (<[DECtape ^W/.VLNAM(P1)/ mounted on ^W/.UCBNM(P2)/]>)
ACKDTL: ITEXT (<[DECtape ^W/.VLNAM(P1)/ mounted on ^W/.UCBNM(P2)/ with logical name ^W/.VSLNM(P4)/]>)
TOPS10 <
ACKU.K: ITEXT (<^M^J[Structure ^W/.VLNAM(P1)/ will be locked at ^C/.VLLTM(P1)/]>);[1144]
ACKU.N: ITEXT (<>);[1144]
ACKU.X: ITEXT (<[^T/@DEVNTB(T1)/ ^W/.VLNAM(P1)/ mounted on ^W/MDAOBJ+OBJ.UN/]>)
ACKU.Y: ITEXT (<[^T/@DEVNTB(T1)/ ^W/.VLNAM(P1)/ mounted on ^W/MDAOBJ+OBJ.UN/ with logical name ^W/.VSLNM(P4)/]>)
>
SUBTTL TELOPR - ROUTINE TO NOTIFY THE OPERATOR TO MOUNT DEVICES
;CALL: S1/ The VSL Address of Any VSL to be Mounted
; AP/ The MDR Address
;
;RET: True Always
TOPS10<
TELOPR: PUSHJ P,.SAVE4 ;SAVE P1 - P4
PUSHJ P,.SAVET ;SAVE THE 'T' ACs ALSO
SETOM STRFLG ;AND SET IT
LOAD P1,.VSLNK(S1),VS.LNK ;GET THE VSL LINK CODE
LOAD P2,.MRCNT(AP),MR.CNT ;GET THE USERS VOL SET REQUEST COUNT
MOVNS P2 ;NEGATE IT
MOVSS P2 ;MOVE RIGHT TO LEFT
HRRI P2,.MRVSL(AP) ;CREATE VSL AOBJN SEARCH AC
TELO.1: MOVE T1,0(P2) ;GET A VSL ADDRESS
LOAD S2,.VSLNK(T1),VS.LNK ;GET ITS LINK CODE
CAME S2,P1 ;DO THEY MATCH ???
JRST TELO.3 ;NO,,GET NEXT
MOVE S2,.VSFLG(T1) ;GET THE VSL FLAG BITS
TXNN S2,VS.INI ;[1164] CHECK FOR /NEW-VOLUME INITIALIZATION
TXNN S2,VS.OPR+VS.VSW ;SWITCHING VOLS OR NOTIFY OPR ???
JRST TELO.3 ;NO,,SKIP THIS
LOAD P3,.VSCVL(T1),VS.OFF ;GET THE OFFSET TO THE CURRENT VOLUME
ADDI P3,.VSVOL(T1) ;POINT TO THE CURRENT VOLUME ADDRESS
MOVE P3,0(P3) ;POINT P3 AT THE CURRENT VOLUME
LOAD S2,.VLFLG(P3),VL.STA ;GET THE VOLUME STATUS
CAXN S2,%STAMN ;IS IT MOUNTED ???
JRST TELO.3 ;YES,,DON'T TELL OPR TO REMOUNT IT
PUSHJ P,CHKBAT ;CHECK TO SEE IF BATCH REQUEST
JUMPF TELO.3 ;YES,,DON'T TELL OPR
PUSHJ P,MDASBP ;SET UP FOR CALLS TO MDADBP
MOVEI S2,DEMOB ;ASSUME A PSEUDO-PROCESS
LOAD S1,.MRJOB(AP),MR.JOB ;GET THE PROCESS JOB NUMBER
TXC S1,BA%JOB ;SWAP REQUEST STATES
TXNE S1,BA%JOB ;IS THIS A REAL REQUEST ???
MOVEI S2,DEMOT ;NO--NORMAL TIMESHARING
$TEXT (MDADBP,<^T/BELLS/^I/(S2)/>) ;DEMOGRAPHIC STUFF
LOAD S2,.VSFLG(T1),VS.TYP ;GET THE REQUEST TYPE
CAIN S2,%UNKN ;UNKNOWN?
JRST TELO.2 ;YES
$TEXT (MDADBP,<Volume-set name: ^T/.VSVSN(T1)/>)
MOVEI S1,.VSVSN(T1) ;POINT TO VOLUME-SET NAME
PUSHJ P,V$FIND## ;SEE IF CATALOGED
JUMPF TELO.2 ;JUMP IF NOT
MOVEI S1,.CQVLO(S1) ;POINT TO MEDIA STORAGE LOCATION
SKIPN (S1) ;HAVE SOMETHING THERE?
JRST TELO.2 ;NO
HRLI S1,(POINT 8,) ;8-BIT ASCII
$TEXT (MDADBP,<Media storage location: ^Q/S1/>)
TELO.2: SKIPE .VSREM(T1) ;HAVE A REMARK?
$TEXT (MDADBP,<Remark: ^T/.VSREM(T1)/>) ;YES,,GEN IT
ZERO .VSFLG(T1),VS.OPR ;CLEAR OPR BIT,,WE'RE TELLING OPR NOW
MOVE S2,G$NOW## ;GET THE CURRENT TIME
MOVEM S2,.VSSCH(T1) ;SAVE AS THE SCHEDULED TIME
LOAD S2,.VSFLG(T1),VS.TYP ;GET THE REQUEST TYPE
SETZM MDAOBJ+OBJ.UN ;[1455] GET RID OF STALE DEVICE NAME
PUSHJ P,@TELTAB(S2) ;DISPATCH TO PROPER 'TELL' PROCESSOR
$RETIF ;RETURN IF FALSE
TELO.3: AOBJN P2,TELO.1 ;CONTINUE FOR ALL VSL'S
$RETT ;RETURN
TELTAB: TELUNK ;%UNKN - UNKNOWN DEVICE
TELMTA ;%TAPE - MAGTAPE
TELDSK ;%DISK - STRUCTURE
TELDTA ;%DTAP - DECTAPE
; Tell OPR about magtape request (%TAPE)
;
TELMTA: MOVEI S2,NEWTXT ;ASSUME /SCRATCH
MOVX T3,VL.SCR ;GET 'SCRATCH' STATUS BIT
TDNN T3,.VLFLG(P3) ;IS THIS A SCRATCH OR NEW VOLUME SET?
$TEXT (MDADBP,<^T/MTAHDR/^W11/.VLNAM(P3)/^A>) ;NO
TDNE T3,.VLFLG(P3) ;CHECK AGAIN
$TEXT (MDADBP,<^T/MTAHDR/Scratch ^A>)
LOAD P4,.VSFLG(T1),VS.WLK ;GET THE WRITE-LOCKED CODE
$TEXT (MDADBP,<^T9/@WRTENA(P4)/^A>)
TDNE T3,.VLFLG(P3) ;/SCRATCH?
JRST TMTA.1 ;YES
MOVEI S2,NONEWT ;[1164] ASSUME NOT NEW
MOVX T3,VS.NEW ;[1164] GET /NEW-VOLUME BIT
TDNN T3,.VSFLG(T1) ;[1164] IS IT LIT?
JRST TMTA.1 ;[1164] NO,,CONTINUE
LOAD S2,.VSCVL(T1),VS.CNT ;[1164] GET COUNT OF VOLS IN VSN
CAIN S2,1 ;[1164] ONE VOLUME?
SKIPA S2,[REITX1] ;[1164] YES
MOVEI S2,REITX2 ;[1164] ELSE USE MULTI-VOL TEXT
JRST TMTA.2 ;[1164] SKIP LABEL TYPE CHECK
TMTA.1: LOAD S1,.VLFLG(P3),VL.LBT ;[1134]GET THE VOLUME LABEL
PUSHJ P,GETLBT ;[1134]GO SEE IF USER SPECIFIED LABELS
CAXN S1,%UNLBL ;DID HE?
MOVEI S2,NONEWT ;DON'T PROMPT FOR INITIALIZATION AT ALL
TMTA.2: LOAD P4,.VSFLG(T1),VS.WLK ;[1164] GET THE WRITE-LOCKED CODE
LOAD T2,.VSFLG(T1),VS.LBT ;GET THE REQUESTED LABEL TYPE
LOAD T3,.VSATR(T1),VS.TRK ;GET THE TRACK STATUS
LOAD T4,.VSATR(T1),VS.DEN ;GET THE REQUESTED DENSITY
$TEXT(MDADBP,<^T9/@LABELS(T2)/^W6/TRK(T3)/^T/@DENSTY(T4)/^I/(S2)/^0>)
$WTO (<Magtape mount request #^D/.VSRID(T1)/>,<^T/G$MSG/>,MDAOBJ,<$WTFLG(WT.SJI)>) ;[1455]
$RETT ;RETURN
NEWTXT: ITEXT (<^M^JInitialize new/scratch tape: - Volume-id: ^W/.VLNAM(P3)/ - Protection: ^O3/.VSATR(T1),VS.PRT/>)
NONEWT: ITEXT (<>) ;IF /NEW OR /SCRATCH NOT SEEN
MTAHDR: ASCIZ/
Volume-ID Write Labels Track Density
--------- ------- ------ ----- -------
/
REITX1: ITEXT (<^M^JUser requesting reinitialization of 1 volume^T/BELLS/>) ;[1164]
REITX2: ITEXT (<^M^JUser requesting reinitialization of ^D/.VSCVL(T1),VS.CNT/ volumes^T/BELLS/>) ;[1164]
; Tell OPR about structure request (%DISK)
;
TELDSK: $TEXT (MDADBP,<^T/DSKHDR/^A>) ;PUT OUT HEADER
MOVE S1,.VLNAM(P3) ;GET THE STRUCTURE NAME
MOVEM S1,MDAOBJ+OBJ.UN ;SAVE IT IN THE MDA OBJECT BLOCK
PUSHJ P,V$STRG## ;CONVERT TO ASCIZ
PUSHJ P,V$FIND## ;FIND ITS CATALOG ENTRY
SKIPT ;IT MUST BE THERE !!!
PUSHJ P,S..SCE ;NO,,DEEEP TROUBLE !!!
MOVE T2,.CQNVL(S1) ;GET # OF VOLUMES WORD
MOVEI P3,.CQVSL(S1) ;POINT TO THE FIRST BLOCK !!!
SETZM T1 ;CLEAR LOGICAL UNIT NUMBER COUNTER
AOSG STRFLG ;MODIFY AND CHECK STR MOUNT FLAG
PUSHJ P,SETSEL ;FIRST TIME THROUGH,,SET UNIT SELECTED
MOVE S1,UCBQUE ;GET THE UCB QUEUE ID
PUSHJ P,L%FIRST ;POSITION TO THE FIRST ENTRY
TELD.1: MOVE P4,.CQRSN(P3) ;GET THE RESOURCE NUMBER
TELD.2: MOVE S1,UCBQUE ;GET THE UCB QUEUE ID
PUSHJ P,L%NEXT ;GET THE NEXT UCB ADDRESS
JUMPF .RETF ;NO MORE AVAILABLE,,JUST RETURN
LOAD S1,.UCBST(S2),UC.DVT ;GET THE DEVICE TYPE
CAXE S1,%DISK ;IS IT A STRUCTURE ???
JRST TELD.2 ;NO,,TRY NEXT UCB
LOAD S1,.UCBST(S2),UC.RSN ;GET THE DEVICE RESOURCE NUMBER
CAME S1,P4 ;DO THEY MATCH ???
JRST TELD.2 ;NO,,TRY NEXT
LOAD S1,.UCBST(S2),UC.SEL ;GET THE UNIT SELECTED BIT
JUMPN S1,TELD.2 ;IF LIT,,SKIP THIS UNIT !!!
MOVX S1,UC.SEL ;ELSE GET THE UNIT SELECTED BIT
IORM S1,.UCBST(S2) ; AND SET IT
IMULI P4,AMALEN ;GET 'A' MATRIX OFFSET
ADD P4,AMATRX ;GET THE 'A' MATRIX ENTRY ADDRESS
$TEXT(<-1,,TMPVSL>,<^W/MDAOBJ+OBJ.UN/^O/T1/^0>) ;GEN LOGICAL UNIT NAME
$TEXT(MDADBP,<^T8/TMPVSL/^W8/.CQVID(P3)/^T6/@.AMNAM(P4)/^W/.UCBNM(S2)/>)
ADDI P3,.CQVLL ;BUMP TO THE NEXT CATALOG ENTRY
AOS T1 ;BUMP THE LOGICAL UNIT NUMBER
SOJG T2,TELD.1 ;CONTINUE FOR ALL VOLUME BLOCKS
SETZM S1 ;GET A NULL BYTE
IDPB S1,MDBPTR ;MAKE THE TEXT ASCIZ
MOVE T1,0(P2) ;PICK UP THE VSL ADDRESS AGAIN
$WTO (<Structure mount request #^D/.VSRID(T1)/>,<^T/G$MSG/>,MDAOBJ,<$WTFLG(WT.SJI)>) ;[1455]
$RETT ;RETURN
DSKHDR: ASCIZ/
Unit Volume Type Drive
------ ------ ---- -----
/
; Tell OPR about DECtape request (%DTAP)
;
TELDTA: MOVX T3,VS.SCR+VS.NEW ;GET 'SCRATCH+NEW' STATUS BITS
TDNN T3,.VSFLG(T1) ;IS THIS A SCRATCH OR NEW VOLUME SET?
$TEXT (MDADBP,<^T/DTAHDR/^W11/.VLNAM(P3)/^A>) ;NO
TDNE T3,.VSFLG(T1) ;CHECK AGAIN
$TEXT (MDADBP,<^T/DTAHDR/Scratch ^A>)
LOAD P4,.VSFLG(T1),VS.WLK ;GET THE WRITE-LOCKED CODE
$TEXT (MDADBP,<^T9/@WRTENA(P4)/^0>)
$WTO (<DECtape mount request #^D/.VSRID(T1)/>,<^T/G$MSG/>,MDAOBJ,<$WTFLG(WT.SJI)>) ;[1455]
$RETT ;RETURN
DTAHDR: ASCIZ/
Volume-ID Write
--------- -------
/
TELUNK: MOVE S1,T1 ;GET THE VSL ADDRESS
PUSHJ P,I$CGEN## ;GET THE DEVICE TYPE AND INDEX
MOVE P4,S1 ;SAVE THE DEVICE INDEX
HRROI S1,.VSVSN(T1) ;POINT TO THE VOLUME SET NAME
PUSHJ P,S%SIXB ;CONVERT TO SIXBIT
MOVEM S2,MDAOBJ+OBJ.UN ;SAVE IT IN THE OBJECT BLOCK
$TEXT (MDADBP,<Device: ^W/S2/^0>)
$WTO (<^T/@DEVNTB(P4)/ mount request #^D/.VSRID(T1)/>,<^T/G$MSG/>,MDAOBJ,<$WTFLG(WT.SJI)>) ;[1455]
$RETT ;RETURN
> ;END TOPS10 CONDITIONAL
SUBTTL MNTOPR - ROUTINE TO NOTIFY THE OPR OF PENDING MOUNT REQUESTS
;CALL: No Args
;
;RET: Nothing - Notifies the operator if mounts are pending
MNTOPR: SKIPN G$OPRA## ;OPERATOR ON DUTY?
JRST MNTO.9 ;NOPE - JUST RESCHEDULE THE EVENT
PUSHJ P,.SAVE4 ;SAVE P1 - P4
STKVAR <KOUNT> ;GET SPACE FOR A COUNT
SETZM KOUNT ;CLEAR MOUNT COUNTER
MOVE S1,VOLQUE ;GET THE VOLUME QUEUE ID
PUSHJ P,L%FIRST ;GET THE FIRST VOL IN THE QUEUE
JRST MNTO.2 ;JUMP THE FIRST TIME THROUGH
MNTO.1: MOVE S1,VOLQUE ;GET THE VOLUME QUEUE ID
PUSHJ P,L%NEXT ;GET THE NEXT VOLUME IN THE QUEUE
MNTO.2: JUMPF MNTO.7 ;NO MORE,,GO FINISH UP...
MOVE P2,S2 ;SAVE THE VOL ENTRY ADDRESS
LOAD P4,.VLOWN(P2),VL.CNT ;GET THE VOLUME REQUEST COUNT..
JUMPE P4,MNTO.1 ;NO REQUESTORS,,SKIP IT..
MOVNS P4 ;NEGATE THE REQUEST COUNT
MOVSS P4 ;MOVE RIGHT TO LEFT
HRRI P4,.VLVSL(P2) ;CREATE VSL AOBJN AC
MOVE P3,.VLUCB(P2) ;GET THE UCB ADDRESS
MNTO.3: MOVE P1,0(P4) ;GET A VSL ADDRESS
MOVE AP,.VSMDR(P1) ;GET THE MDR ADDRESS
MOVE S1,.VSFLG(P1) ;GET THE VSL FLAG BITS
TXNN P1,VL.ASN ;DOES HE OWN THE VOLUME ???
TXNE S1,VS.ALC+VS.ABO ;JUST ALLOCATED OR ABORTED ???
JRST MNTO.6 ;YES,,TRY NEXT VSL
SKIPN S1,.MRQEA(AP) ;CHECK AND LOAD QE ADDRESS
JRST MNTO.4 ;NO QE, NO BATCH JOB TO CHECK
PUSHJ P,S$INPS## ;FOUND,,CHECK SCHEDULABILITY
JUMPF MNTO.6 ;NO GO,,SKIP IT
MOVE S1,.MRQEA(AP) ;GET THE QE AGAIN
MOVX S2,QE.HBO ;GET 'HELD BY OPERATOR BIT'
TDNE S2,.QESEQ(S1) ;IS IT?
JRST MNTO.6 ;HELD JOBS CAN'T MOUNT THINGS
MNTO.4: LOAD S1,.VSCVL(P1),VS.OFF ;GET THE OFFSET TO HIS CUR VOL
ADDI S1,.VSVOL(P1) ;POINT TO HIS CURRENT VOL ADDR
CAME P2,0(S1) ;IS THIS THE VOL HE NEEDS ???
JRST MNTO.6 ;NO,,SKIP THIS
LOAD S1,.VSFLG(P1),VS.TYP ;GET THE VOLUME SET TYPE
CAXE S1,%DISK ;IS THIS A STRUCTURE REQUEST ???
JRST MNTO.5 ;NO,,ADD UP THE TAPE REQUEST
LOAD S1,.VLFLG(P2),VL.STA ;GET THE VOLUME STATUS
CAXN S1,%STAMN ;IS THE STRUCTURE MOUNTED ???
JRST MNTO.6 ;YES,,SKIP THIS REQUEST
MNTO.5: AOS KOUNT ;BUMP THE MOUNT COUNTER
MNTO.6: AOBJN P4,MNTO.3 ;CONTINUE THROUGH ALL USERS
JRST MNTO.1 ;CONTINUE THROUGH ALL VOLUMES
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
MNTO.7: SKIPN P1,KOUNT ;ANY MOUNTS PENDING ???
JRST MNTO.9 ;NO,,JUST ADD THE EVENT BACK
MOVE S1,[ASCII/is/] ;DEFAULT TO 1 MOUNT
SETZM S2 ;GET A NULL
CAIG P1,1 ;MORE THEN 1 MOUNT ???
JRST MNTO.8 ;NO,,LETERRIP !!!
MOVE S1,[ASCII/are/] ;YES,,SET IT UP
MOVE S2,[ASCII/s/] ;TAKES A LOT TO BE NICE !!!
MNTO.8: SETZM MDAOBJ+OBJ.UN ;[1455] GET RID OF STALE DEVICE
$WTO (<There ^T/S1/ ^D/KOUNT/ mount request^T/S2/ pending^T/BELLS/>,,MDAOBJ,<$WTFLG(WT.SJI)>) ;[1455]
MNTO.9: SETZM G$MSG+.EVTYP ;CLEAR THE EVENT TYPE WORD
MOVX S1,%EVAFT ;WANT TYPE 'AFTER'
STORE S1,G$MSG+.EVTYP,EV.TYP ;SET IT
MOVEI S1,3 ;GET 3 MINUTES
PUSHJ P,A$AFT## ;COMPUTE IT
MOVEM S1,G$MSG+.EVUDT ;SET IT
MOVEI S1,MNTOPR ;GET THIS ROUTINE ADDRESS
MOVEM S1,G$MSG+.EVRTN ;SET IT
MOVX S1,.EVMSZ ;GET THE EVENT BLOCK LENGTH
MOVEI S2,G$MSG ;AND ITS ADDRESS
PUSHJ P,S$EVENT## ;ADD TO THE EVENT LIST
$RETT ;AND RETURN
SUBTTL SETSEL - ROUTINE TO FIND THOSE UCB'S WHICH ARE FREE
;CALL: No Args
;
;RET: True Always
TOPS10<
SETSEL: PUSHJ P,.SAVE2 ;SAVE P1 AND P2
MOVX P1,UC.SEL ;GET THE UNIT SELECTED BIT
MOVE S1,UCBQUE ;GET THE UCB QUEUE ID
PUSHJ P,L%FIRST ;POSITION TO THE FIRST ENTRY
JRST SETS.2 ;JUMP THE FIRST TIME THROUGH
SETS.1: MOVE S1,UCBQUE ;GET THE UCB QUEUE ID
PUSHJ P,L%NEXT ;GET THE NEXT ENTRY
SETS.2: JUMPF .RETT ;DONE,,RETURN
MOVE P2,S2 ;SAVE THE UCB ADDRESS
ANDCAM P1,.UCBST(P2) ;CLEAR THE UNIT SELECTED STATUS BIT
LOAD S1,.UCBST(P2),UC.DVT ;GET THE UNIT TYPE
CAXN S1,%DISK ;IS IT A DISK UNIT ???
SKIPN S1,.UCBVL(P2) ;YES,,ANY VOLUME MOUNTED ???
JRST SETS.1 ;NOT A DISK OR NO VOL MOUNTED,,GET NEXT
SETS.3: LOAD S2,.VLPTR(S1),VL.PRV ;FIND THE PRIMARY VOL BLOCK
JUMPE S2,SETS.4 ;FOUND IT,,SEE IF ANYONE OWNS IT
MOVE S1,S2 ;ELSE SAVE THIS VOL BLOCK ADDRESS
JRST SETS.3 ;AND KEEP LOOKING
SETS.4: PUSHJ P,FNDOWN ;ANY OWNERS OF THE MOUNTED VOLUME ???
JUMPF SETS.1 ;NO,,GET NEXT UCB
IORM P1,.UCBST(P2) ;YES,,LITE UNIT SELECTED
JRST SETS.1 ;AND GO GET THE NEXT UCB
> ;END TOPS10 CONDITIONAL
SUBTTL USRNOT - SEND A MESSAGE TO THE USER
;CALL: AP/ The Users MDR Address
; S1/ VSL address (for ACK data)
; S2/ nonzero - Use MDR ACK data if valid
; zero - Use VSL ACK data
; G$MSG/ The Message to be sent
;
;RET: True Always
D$USRN:: ;MAKE IT GLOBAL
USRNOT: PUSHJ P,.SAVE4 ;[1173] SAVE P1-P4
TRVAR <PID,ACKCOD,FLAGS> ;[1173] DEFINE SOME LOCAL STORAGE
DMOVE P2,S1 ;[1173] ASSUME WE'LL USE VSL ACK DATA
;[1173] SAVE S2 TOO
MOVE S1,.VSPID(P2) ;[1173] GET PID FROM VSL
MOVEM S1,PID ;[1173] STORE IT
MOVE S1,.VSACK(P2) ;[1173] GET ACK CODE FROM VSL
MOVEM S1,ACKCOD ;[1173] STASH IT
MOVE S1,.VSRFL(P2) ;[1173] GET ACKING FLAGS
MOVEM S1,FLAGS ;[1173] SAVE THEM
MOVEI P4,RSTVSL ;[1173] GET ROUTINE ADDRESS FOR EXIT
JUMPE P3,USRN.1 ;[1173] JUMP IF ASSUMPTION CORRECT
MOVE P1,.MRFLG(AP) ;[1173] GET MDR FLAGS
CAMN P1,[-1] ;[1173] MDR ACK DATA VALID?
JRST [SETZM P3 ;[1173] NO,,REMEMBER FOR LATER
JRST USRN.1] ;[1173] WE'RE ALREADY SETUP
MOVE S1,.MRPID(AP) ;[1173] GET PID FROM MDR
MOVEM S1,PID ;[1173] STORE IT LOCALLY
MOVE S1,.MRACK(AP) ;[1173] GET ACK CODE FROM MDR
MOVEM S1,ACKCOD ;[1173] STORE IT
MOVE S1,.MRFLG(AP) ;[1173] GET FLAGS
MOVEM S1,FLAGS ;[1173] STORE THEM
MOVEI P4,RSTMDR ;[1173] GET EXIT ROUTINE ADDRESS
;**;[1170] Delete 3 lines at USRNOT+1L. 29-Dec-83 /LWS
USRN.1: LOAD S2,.MRJOB(AP),MR.JOB ;[1173] GET THE USERS JOB NUMBER
TXNN S2,BA%JOB ;IS IT AN INTERNAL REQUEST ???
TXNN S1,MR.WAT!MR.NOT!MR.ACK ;OR WANT SOME STYLE NOTIFICATION ???
JRST [SETZM ERRACK ;PSEUDO REQ OR NO ACK,,ZAP ERROR
$RETT ] ;AND RETURN
TXNN S1,MR.WAT!MR.ACK ;WAITING FOR AN ACK ???
JRST USRN.N ;NO,,MUST BE NOTIFY
TXZN S1,MR.ACK ;ACK REQUESTED ???
TXZ S1,MR.WAT ;NO,,CLEAR WAITING
MOVEM S1,FLAGS ;[1173] SAVE THE NEW STATUS
$CALL M%GPAG ;GET A PAGE TO BUILD THE ACK IN
MOVE P1,S1 ;SAVE THE ADRS OF THE TEXT PAGE
MOVEM P1,G$SAB##+SAB.MS ;AIM THE GLOBAL SAB AT THE PAGE
MOVE S1,PID ;[1173] GET USER'S PID
MOVEM S1,G$SAB##+SAB.PD ;SEND ACK TO USER
MOVX S1,.OMTXT ;MESSAGE TYPE
STORE S1,.MSTYP(P1),MS.TYP ;SAVE IN HEADER
MOVX S1,MF.FAT ;GET FATAL ACK BIT
SKIPE ERRACK ;IS THIS AN 'ERROR' ACK ???
MOVEM S1,.MSFLG(P1) ;YES,,SET THE BIT
MOVX S1,.OHDRS+ARG.DA+MSGLN## ;LENGTH OF THE MESSAGE
STORE S1,.MSTYP(P1),MS.CNT ;SAVE IN MESSAGE HEADER
MOVX S1,PAGSIZ ;GET THE PAGE SIZE
STORE S1,G$SAB##+SAB.LN ;SAVE IN SEND BLOCK
MOVE S1,ACKCOD ;[1173] GET THE MESSAGE ACK CODE
MOVEM S1,.MSCOD(P1) ;SAVE IT IN THE MESSAGE
MOVX S1,1 ;ONE ARG BLOCK
STORE S1,.OARGC(P1) ;SAVE IN HEADER
MOVX S1,.CMTXT ;BLOCK TYPE-- TEXT
STORE S1,.OHDRS+ARG.HD(P1),AR.TYP ;SET BLOCK TYPE
MOVX S1,ARG.DA+MSGLN## ;SIZE OF THIS BLOCK
STORE S1,.OHDRS+ARG.HD(P1),AR.LEN ;LENGTH INTO BLOCK HEADER
MOVSI S1,G$MSG ;GET THE SOURCE ADDRESS
HRRI S1,.OHDRS+ARG.DA(P1) ;GET DESTINATION ADDRESS
BLT S1,.OHDRS+ARG.DA+MSGLN##-1(P1) ;COPY THE TEXT OVER
PUSHJ P,C$SEND## ;ACK THE USER
MOVE S1,P2 ;[1173] GET VSL ADDRESS
PUSHJ P,(P4) ;[1173] RESTORE ACK DATA
JUMPF USRN.N ;[1173] TRY TERMINAL IF FAILURE
SETZM ERRACK ;[1173] CLEAR ERROR FLAG
$RETT ;[1173] RETURN
;HERE TO NOTIFY USER VIA ORION TYPING ON HIS TERMINAL
TOPS10 <
USRN.N: MOVE P1,FLAGS ;[1173] GET ACK DATA FLAGS
TXNE P1,MR.NOT ;[1173] WANT TO BE NOTIFIED
JRST USRN.X ;[1173] YES,,GO TRY IT
SETZM ERRACK ;[1173] NO,,CLEAR THE ERROR FLAG
$RETT ;[1173] RETURN
;[1173] USRN.W will always use VSL ack data when called directly.
;[1173] S1/ VSL address
USRN.W: PUSHJ P,.SAVE2 ;[1173] SAVE P1,P2
MOVE P2,S1 ;[1173] SAVE VSL ADDRESS
MOVE P1,.VSRFL(P2) ;[1173] GET ACK DATA FLAGS FROM VSL
USRN.X: STKVAR <FLAGSX> ;[1173] LOCAL STORAGE
MOVEM P1,FLAGSX ;[1173] SAVE FLAGS
MOVX S1,BA%JOB ;GET THE BATCH JOB BIT
TDNE S1,.MRJOB(AP) ;IS THIS REQUEST A BATCH REQUEST?
JRST USRN.6 ;YES, SKIP THE NOTIFICATION
$CALL M%GPAG ;GET A PAGE TO BUILD THE ACK IN
MOVE P1,S1 ;SAVE THE ADRS OF THE TEXT PAGE
MOVEM P1,G$SAB##+SAB.MS ;AIM THE GLOBAL SAB AT THE PAGE
MOVX S2,SI.FLG+SP.OPR ;SEND VIA INDEX TO OPR
STORE S2,G$SAB##+SAB.SI ;SAVE IN SAB
SETZM G$SAB##+SAB.PD ;BE TIDY.. NO PID
MOVX S1,.OHDRS+JBI.SZ+ARG.DA+MSGLN## ;SIZE OF THE MESSAGE
STORE S1,.MSTYP(P1),MS.CNT ;SAVE IN MESSAGE ITSELF
MOVX S1,PAGSIZ ;GET THE PAGE LENGTH
STORE S1,G$SAB##+SAB.LN ;SAVE IT IN THE SAB
MOVX S1,.OMNFY ;MESSAGE TYPE -- NOTIFY
STORE S1,.MSTYP(P1),MS.TYP ;SAVE IN HEADER
MOVX S1,2 ;TWO BLOCKS
STORE S1,.OARGC(P1) ;SAVE IN HEADER
MOVE S1,[XWD JBI.SZ,.JOBID] ;LEN,,SIZE OF JOB INFO BLOCK
MOVEM S1,.OHDRS+ARG.HD(P1) ; SAVE IN FIRST BLOCK
MOVE S1,.MRLOG(AP) ;GET JOB'S UNIV. LOGIN TIME
MOVEM S1,.OHDRS+JBI.LI(P1) ;SAVE AS DATA FOR THIS BLOCK
LOAD S1,.MRJOB(AP),MD.PJB ;GET JOB NUMBER
STORE S1,.OHDRS+JBI.JB(P1) ;SAVE AS MORE DATA IN JOB INFO BLOCK
MOVEI P1,.OHDRS+JBI.SZ(P1) ;POINT TO THE LAST BLOCK
MOVX S1,.CMTXT ;BLOCK TYPE-- TEXT
STORE S1,ARG.HD(P1),AR.TYP ;SET BLOCK TYPE
MOVX S1,ARG.DA+MSGLN## ;SIZE OF THIS BLOCK
STORE S1,ARG.HD(P1),AR.LEN ;LENGTH INTO BLOCK HEADER
MOVE S1,[BYTE(7) 15,12,0,0,0] ;GET A CRLF
SKIPE ERRACK ;UNLESS THIS IS AN ERROR ACK !!
MOVE S1,[BYTE(7) 15,12,77,0,0] ; THEN GET A <CRLF>?
MOVX S2,MR.DMO ;GET DISMOUNT STR BIT
TDNE S2,FLAGSX ;[1173] IS THAT WHAT WE'RE DOING?
SKIPA S2,[ASCIZ | |] ;YES
MOVE S2,[BYTE (7) 15,12,0] ;ELSE USE A CRLF
$TEXT (<-1,,ARG.DA(P1)>,<^T/S1/From system:^T/S2/^T/G$MSG/^T/BELLS/>)
PUSHJ P,C$SEND## ;ACK THE USER
USRN.6: SETZM ERRACK ;CLEAR THE ERROR FLAG
$RETT ;AND RETURN
>
TOPS20 <
USRN.N: $RETT > ;JUST RETURN ON THE -20
;[1173] Routines to restore ACK data flag word in MDR and VSL.
;[1173] USRNOT may modify some of the bits.
;[1173] ** Can only be called from USRNOT **
;[1173] Call: AP/ MDR address
RSTMDR: MOVE S1,FLAGS ;[1173] GET FLAGS
MOVEM S1,.MRFLG(AP) ;[1173] RESTORE THEM IN MDR
$RET ;[1173] RETURN TF INTACT
;[1173] Call: S1/ VSL address
RSTVSL:
MOVE S2,FLAGS ;[1173] GET FLAGS
MOVEM S2,.VSRFL(S1) ;[1173] RESTORE IN VSL
$RET ;[1173] RETURN TF INTACT
SUBTTL NSTUSR - Notify users of pending structure locks
;this routine will notify all the users of a given structure that a
; LOCk has been given by the operator for a structure they own,
; and will not be available for long
;Call -
; S1/ Prime volume block address
; S2/ Addrs of ITEXT for message (ITEXT should stay in P acs)
;Returns -
; TRUE, messages sent to all requestors
TOPS10<
NSTUSR: $TEXT (<-1,,G$MSG>,<^I/0(S2)/^M^J^0>) ;DUMP THE TEXT OF THE MESSAGE
$SAVE <P1,AP> ;SAVE P1 AND AP
MOVE P1,S1 ;COPY ADRS OF PRIMARY VOL BLOCK
LOAD S1,.VLOWN(P1),VL.CNT ;FIND OUT HOW MANY REQUESTORS
JUMPE S1,.RETT ;NONE, NOTHING TO DO!
MOVNS S1 ;GET NEGATIVE # OF REQUESTORS
HRL P1,S1 ;MAKE LOOP POINTER
SETZM ERRACK ;DO THE NORMAL STUFF IN USRNOT
NSTU.1: HRRZ S1,.VLVSL(P1) ;GET THE NEXT VSL ENTRY
SKIPN S1 ;BETTER BE ONE!!
STOPCD (VSA,HALT,,<VSL address is missing in a VOL>) ;NONE THERE,,END IT
SKIPN AP,.VSMDR(S1) ;GOT IT, GET BACK TO THE MDR
STOPCD (IMV,HALT,,<Invalid MDR/VSL forward/backchain pointers>)
PUSHJ P,USRN.W ;WRITE ON THE REQUESTORS TERMINAL
AOBJN P1,NSTU.1 ;CHECK ALL REQUESTORS
$RETT ;DONE
> ;END TOPS10 CONDITIONAL
SUBTTL LBLNOT - ROUTINE TO NOTIFY LABEL PROCESS OF DEVICE REASSIGNMENT
TOPS10< ;CALL: S1/ The volume set list adrs, which points back to
; the MDR, and whose current offset points to the VOL just
; mounted, and which points to the UCB.
LBLNOT: $SAVE <P1,P2,P3>
MOVE P1,S1 ;SAVE THE VSL ADDR
MOVX S1,.QOVMN ;MESSAGE TYPE - VOLUME MOUNTED
PUSHJ P,LBLHDR ;SET THE HEADER FOR MESSAGE, SAB, ETC
MOVEI P2,G$MSG+.OHDRS ;AIM AT FIRST BLOCK
;Build the First Block, Which Describes the Device Reassigned
AOS G$MSG+.OARGC ;ONE MORE BLOCK
MOVX S1,.RECDV ;FIRST BLOCK TYPE - RECOGNIZE DEVICE
STORE S1,ARG.HD(P2),AR.TYP ;SET THIS BLOCK TYPE
MOVX S1,.RECSZ+ARG.DA ;GET LENGTH OF THIS BLOCK
STORE S1,ARG.HD(P2),AR.LEN ;SAVE IN BLOCK
ADDM S1,G$SAB+SAB.LN ;UPDATE SEND LENGTH
MOVSS S1 ;GET TO LH
ADDM S1,G$MSG+.MSTYP ;UPDATE TOTAL MESSAGE LENGTH
LOAD S1,.VSCVL(P1),VS.OFF ;GET OFFSET TO CURRENT VOLUME
ADDI S1,.VSVOL(P1) ;POINT TO THIS VOLUME'S ENTRY
MOVE P3,0(S1) ;NOW GET THE VOLUME ADDRS
MOVE S2,.VLUCB(P3) ;AND GET TO UCB ADDR
MOVE S1,.UCBNM(S2) ;GET THE DEVICE NAME
MOVEM S1,.RECDN+ARG.DA(P2) ;SAVE IN MESSAGE
MOVEI P2,.RECSZ+ARG.DA(P2) ;ADVANCE TO NEXT BLOCK
;Build the Second Block, Which Describes the Volume Set and User to
; Which the Drive was Given.
AOS G$MSG+.OARGC ;ONE MORE BLOCK
MOVX S1,.VOLMN ;GET THE NEXT BLOCK TYPE
STORE S1,ARG.HD(P2),AR.TYP ;SAVE AS BLOCK TYPE
MOVX S1,.VMNSZ+ARG.DA ;GET THE LENGTH OF THE BLOCK
STORE S1,ARG.HD(P2),AR.LEN ;AND SAVE IN BLOCK HEADER
ADDM S1,G$SAB+SAB.LN ;UPDATE SEND LENGTH
MOVSS S1 ;GET TO LH
ADDM S1,G$MSG+.MSTYP ;UPDATE TOTAL MESSAGE LENGTH
MOVEI P2,ARG.DA(P2) ;AIM AT THE DATA PORTION OF THE BLOCK
LOAD S1,.VLNAM(P3) ;GET THE VOLUME NAME
STORE S1,.VMNIV(P2) ;SAVE AS INITIAL VOLUME NAME
MOVEI S1,.VSVOL(P1) ;AIM AT THE FIRST VOLUME BLOCK ADR
MOVE S1,(S1) ;GET THE ADR OF THE FIRST VOL BLOCK
LOAD S1,.VLNAM(S1) ;GET THE NAME OF THE FIRST VOLUME
STORE S1,.VMNFV(P2) ;SAVE IN MESSAGE TO LABELLER
SETZM .VMNIN(P2) ;CLEAN OUT THE GARBAGE
LOAD S1,.VSFLG(P1),VS.LBT ;GET THE LABEL TYPE
STORE S1,.VMNIN(P2),VI.LTY ;SAVE IN MESSAGE
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
LOAD S1,.VSFLG(P1),VS.WLK ;GET THE WRITE LOCK BIT
STORE S1,.VMNIN(P2),VI.WLK ;SAVE IN INFO WORD OF MESSAGE
LOAD S1,.MRJOB(AP),MD.PJB ;GET THE JOB NUMBER
STORE S1,.VMNIN(P2),VI.JOB ;TELL THE LABELLER WHO'S THERE
PUSHJ P,C$SEND## ;TELL THE LABELLER
$RETT
>;END TOPS10
SUBTTL LBLHDR - Set up for a message to MDA
;Thie routine will set up G$SAB for a message to MDA which
; will be in G$MSG
;Call -
; S1/ Message type
TOPS10<
LBLHDR: STORE S1,G$MSG+.MSTYP,MS.TYP ;SAVE THE MESSAGE TYPE
MOVX S1,.OHDRS ;SIZE OF HEADER ALONE
STORE S1,G$MSG+.MSTYP,MS.CNT ;LENGTH SO FAR
MOVEM S1,G$SAB##+SAB.LN ;LENGTH TO SEND
SETZM G$SAB##+SAB.PD ;NO PID...
MOVX S1,<SI.FLG+SP.TLP> ;.. SEND BY SPECIAL INDEX
MOVEM S1,G$SAB##+SAB.SI ;MARK IN SAB
SETZM G$SAB##+SAB.PB ;SEND ON MY BEHALF
SETZM G$MSG+.MSFLG ;NO MESSAGE FLAGS
SETZM G$MSG+.MSCOD ;NO ACK CODE
SETZM G$MSG+.OFLAG ;AND NO FLAGS (YET)
SETZM G$MSG+.OARGC ;NO ARG BLOCKS (YET)
MOVEI S1,G$MSG ;THE ADR OF THE MESSAGE
MOVEM S1,G$SAB##+SAB.MS ;AIM THE SAB AT US
$RETT ;ALL SET UP
>;END TOPS10
SUBTTL SNDREC - ROUTINE TO SEND A RECOGNIZE MSG TO THE TAPE LABELER
;CALL: S1/ The Device Name in Sixbit
;
;RET: True Always
TOPS10 <
RECMSG: $BUILD .OHDRS+ARG.DA+1
$SET(.MSTYP,MS.TYP,.QOREC) ;TYPE 'RECOGNIZE MESSAGE'
$SET(.MSTYP,MS.CNT,.OHDRS+ARG.DA+1) ;MESSAGE LENGTH
$SET(.OARGC,,1) ;A BLOCK COUNT OF 1
$SET(.OHDRS+ARG.HD,AR.LEN,2) ;THE BLOCK LENGTH
$SET(.OHDRS+ARG.HD,AR.TYP,.RECDV) ;THE BLOCK TYPE
$EOB
;**;[1175] Change some code at D$SREC. /LWS
D$SREC:: ;MAKE IT GLOBAL
SNDREC: JUMPN S1,SNDR.0 ;[1175] *** MUST BE NON-ZERO ***
$WTO (<Null device name detected>,<Recognize message not sent>,MDAOBJ) ;[1175]
$RETT ;[1175] RETURN
SNDR.0: MOVEM S1,RECMSG+.OHDRS+ARG.DA ;[1175] SAVE THE DEVICE NAME IN THE MESSAGE
MOVEI S1,.OHDRS+ARG.DA+1 ;GET THE MESSAGE LENGTH
MOVEM S1,G$SAB##+SAB.LN ;SAVE IT IN THE SAB
MOVEI S1,RECMSG ;GET THE MESSAGE ADDRESS
MOVEM S1,G$SAB##+SAB.MS ;SAVE IT IN THE SAB
SNDLBR: MOVX S1,SI.FLG+SP.TLP ;GET THE SPECIAL INDEX FOR TAPE LABELER
MOVEM S1,G$SAB##+SAB.SI ;SAVE IT IN THE SAB
SETZM G$SAB##+SAB.PD ;ZAP THE SAB PID WORD
PUSHJ P,C$SEND## ;SEND THE MESSAGE OFF
$RETT ;AND RETURN
SUBTTL UNLOAD - TELL PULSAR TO UNLOAD THE TAPE DRIVE
;CALL: S1/ The Device Name in Sixbit
;
;RET: True Always
REWIND: SKIPA S2,[.QOREW] ;REWIND ENTRY POINT,,GET REWIND MSG TYPE
UNLOAD: MOVX S2,.QOUNL ;UNLOAD ENTRY POINT,,GET UNLOAD MSG TYPE
LBLCOM: STORE S2,RECMSG+.MSTYP,MS.TYP ;MAKE THE RECOGNIZE MSG AN UNLOAD MSG
PUSHJ P,SNDREC ;SEND THE UNLOAD MSG OFF TO PULSAR
MOVX S2,.QOREC ;GET 'RECOGNIZE' MSG TYPE
STORE S2,RECMSG+.MSTYP,MS.TYP ;RESTORE THE RECOGNIZE MSG TYPE
$RETT ;AND RETURN
;STILL IN TOPS10
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVOIUS PAGE
;STILL IN TOPS10
SUBTTL SNDVDM - Send volume dismount message to tape labeler
;Call -
; S1/ UCB adrs of drive just deassigned
;Returns -
; message to tape labeler informing of drive no longer in use
SNDVDM: LOAD S2,.UCBST(S1),UC.DVT ;GET DEVICE TYPE
CAIN S2,%DTAP ;DECTAPE?
$RETT ;YES--PULSAR DOESN'T CARE
LOAD S1,.UCBNM(S1) ;GET DRIVE NAME
MOVX S2,.QOVDM ;MESSAGE TYPE - VOLUME DISMOUNTED
PJRST LBLCOM ;GO SEND MESSAGE TO LABELER
>;END TOPS10
SUBTTL FNDUCB - ROUTINE TO FIND A UCB IN THE UCB CHAIN
;CALL: FNDUCB - S1/ The Address of the message asciz device name
; UCBFND - S1/ The sixbit device name
; LOCxxx Get UCB regardless of un/available bit
; FNDxxx Only return UCB if drive is available
;
;RET: True - S1/ The UCB Address, S2/ sixbit device name checked/
; False - The UCB Was Not Found or the Device Name was Invalid,
; Or the 'Device Available' bit was not on in the UCB
TOPS10 <
LOCUCB: TDZA TF,TF ;SET FLAG FOR LOCATE UCB ENTRY POINT
FNDUCB: SETOM TF ;SET FLAG FOR FIND UCB ENTRY POINT
$SAVE <P1,P2> ;SAVE P1 AND P2
MOVE P1,TF ;SAVE THE ENTRY POINT FLAGS IN P1
HRROI S1,0(S1) ;GET A BYTE POINTER TO THE DEVICE NAME
PUSHJ P,S%SIXB ;CONVERT IT TO SIXBIT
JRST GETU.1 ;CONTINUE TO SEARCH UCB CHAIN
UCBLOC: TDZA TF,TF ;SET FLAG FOR LOCATE UCB ENTRY POINT
D$GUCB:: ;GLOBAL ENTRY POINT
UCBFND: SETOM TF ;SET FLAG FOR FIND UCB ENTRY POINT
$SAVE <P1,P2> ;SAVE P1 AND P2
MOVE P1,TF ;SAVE THE ENTRY POINT FLAGS IN T1
MOVE S2,S1 ;GET THE DEVICE NAME IN S2
GETU.1: MOVEM S2,MDAOBJ+OBJ.UN ;SAVE THE DEVICE NAME IN THE OBJ BLOCK
DEVNAM S2, ;GET THE REAL DEVICE NAME
SKIPA S2,MDAOBJ+OBJ.UN ;CAN'T - USE WHAT WE HAVE
MOVEM S2,MDAOBJ+OBJ.UN ;SAVE THE DEVICE NAME IN THE OBJ BLOCK
MOVE P2,S2 ;SAVE THE DEVICE NAME IN P2 ALSO
MOVE S1,UCBQUE ;GET THE UCB QUEUE ID
PUSHJ P,L%FIRST ;POSITION TO THE FIRST ENTRY
JUMPF E$NSD## ;NOT THERE,,RETURN NOW
FNDU.1: CAME P2,.UCBAU(S2) ;IS THIS THE UCB WE WANT ???
CAMN P2,.UCBNM(S2) ; OR DO WE MATCH HERE ???
JRST FNDU.2 ;FOUND,,SEE IF WE OWN IT !!!
MOVE S1,UCBQUE ;GET THE UCB QUEUE ID
PUSHJ P,L%NEXT ;GET THE NEXT UCB ENTRY
JUMPT FNDU.1 ;THERE IS ONE,,TRY IT OUT
PJRST E$NSD## ;RETURN THROUGH 'NO SUCH DEVICE'
FNDU.2: MOVE S1,S2 ;PLACE UCB ADDR IN RETURN REG
EXCH S2,P2 ;SWAP SIXBIT DEVICE NAME WITH UCB ADDR
JUMPE P1,.RETT ;OK IF DEVICE IS AVAILABLE,,RETURN
LOAD P2,.UCBST(P2),UC.AVA ;GET THE DEVICE AVAILABLE BIT
JUMPN P2,.RETT ;WE OWN THE DEVICE,,SO RETURN
$ERJMP MD$IUD ;RETURN ERROR
>
SUBTTL GETRSN - ROUTINE TO RETURN THE FIRST AVAILABLE RESOURCE NUMBER
;CALL: No Args
;
;RET: S1/ The Next Resource Number
TOPS10<
GETRSN: MOVE S1,AMATRX ;GET THE 'A' MATRIX ADDRESS
LOAD S2,.AMHDR(S1),AM.MCN ;GET THE NUMBER OF SLOTS IN BLOCK
JUMPE S2,GETR.2 ;NULL COUNT,,SHOULD NOT HAPPEN
MOVNS S2 ;NEGATE IT
HRLZS S2 ;TO LH
ADDI S2,1 ;1 IN RH
GETR.1: ADDI S1,AMALEN ;GET NEXT MATRIX ENTRY
SKIPGE .AMNAM(S1) ;IS THIS RESOURCE ALLOCATED ???
AOBJN S2,GETR.1 ;YES, TRY THE NEXT ONE
JUMPGE S2,GETR.2 ;NO FREE BLOCKS
HRRZ S1,S2 ;EXTRACT WINNING INDEX
MOVE S2,AMATRX ;AIM AT CURRENT BASE
LOAD TF,.AMHDR(S2),AM.CNT ;GET HIGHEST SLOT IN USE
CAIGE TF,0(S1) ;IS THIS A NEW HIGH?
STORE S1,.AMHDR(S2),AM.CNT ;YES, SAVE THE NEW HIGH WATER MARK
$RETT ;GIVE THE CALLER THE INDEX
;Here if we have to expand the 'A' matrix
GETR.2: MOVE S1,AMATRX ;GET THE 'A' MATRIX ADDRESS
INCR .AMHDR(S1),AM.CNT ;BUMP THE HIGH WATER MARK
INCR .AMHDR(S1),AM.MCN ;AND THERE WILL BE SPACE FOR 1 MORE, TOO
PUSH P,AMATRX ;SAVE THE OLD 'A' MATRIX FOR LATER
LOAD S1,.AMHDR(S1),AM.LEN ;GET THE CURRENT MATRIX LENGTH
ADDI S1,AMALEN ;ADD 1 MORE ENTRY
PUSHJ P,M%GMEM ;GET SOME CORE FOR NEW 'A' MATRIX
EXCH S2,AMATRX ;SWAP OLD AND NEW 'A' MATRIX ADDRESSES
MOVSS S2 ;GET OLD,,0
HRR S2,AMATRX ;GET OLD,,NEW ADDRESSES
ADDI S1,-AMALEN(S2) ;GET NEW MATRIX END ADDRESS
BLT S2,-1(S1) ;COPY OLD MATRIX TO NEW MATRIX
MOVE S2,AMATRX ;GET THE NEW 'A' MATRIX ADDRESS
LOAD S1,.AMHDR(S2),AM.LEN ;GET THE OLD MATRIX LENGTH
ADDI S1,AMALEN ;ADD ANOTHER ENTRY LENGTH
STORE S1,.AMHDR(S2),AM.LEN ;AND SAVE THE NEW 'A' MATRIX LENGTH
POP P,S2 ;GET THE OLD 'A' MATRIX ADDRESS BACK
LOAD S1,.AMHDR(S2),AM.LEN ;GET THE OLD 'A' MATRIX LENGTH BACK
PUSHJ P,M%RMEM ;RETURN THE MEMORY
MOVE S1,AMATRX ;GET THE 'A' MATRIX ADDRESS
LOAD S1,.AMHDR(S1),AM.CNT ;RETURN THE LAST MATRIX ENTRY AS A RSN
$RETT ;RETURN
> ;END TOPS10 CONDITIONAL
SUBTTL GIVRSN - Return a slot of the A matrix
;This routine marks a slot of the A matrix as free
;This routine also keeps track of AM.CNT, the highest
; slot in use in the A matrix.
;
;CALL: S1/ Resource number
;
;RET: True Always
TOPS10<
D$GVRS::
GIVRSN: JUMPE S1,.RETT ;IF NO RSN, JUST RETURN
MOVE S2,S1 ;GET THE RSN IN S2
IMULI S2,AMALEN ;GET THE OFFSET TO THE 'A' MATRIX ENTRY
ADD S2,AMATRX ;GET THE 'A' MATRIX ENTRY ADDRESS
LOAD S2,.AMCNT(S2),AM.ALO ;GET THE ALLOCATION COUNT
JUMPN S2,.RETT ;NOT ZERO,,DON'T DELETE THE ENTRY
MOVE S2,AMATRX ;GET THE BASE OF THE MATRIX
LOAD TF,.AMHDR(S2),AM.CNT ;GET CURRENT HIGHEST SLOT #
CAIE TF,0(S1) ;RETURNING THE HIGHEST SLOT IN USE?
JRST GIVR.3 ;NO, KEEP GOING
PUSH P,S1 ;SAVE RSN BEING RETURNED
IMULI S1,AMALEN ;INDEX INTO THE TABLE
ADDI S1,0(S2) ;AIM AT THIS SLOT
GIVR.1: SUBI S1,AMALEN ;BACK OFF TO NEXT LOWER SLOT
SOJLE TF,GIVR.2 ;ANY SLOTS LEFT?
SKIPL .AMNAM(S1) ;IS THIS SLOT FREE?
JRST GIVR.1 ;YES, TRY THE NEXT
GIVR.2: STORE TF,.AMHDR(S2),AM.CNT ;SAVE PRESENT HIGH WATER MARK
POP P,S1 ;GET BACK RETURNED RSN
GIVR.3: IMULI S1,AMALEN ;INDEX INTO THE BLOCK
ADD S1,AMATRX ;AIM AT THE ENTRY
MOVE S2,.AMNAM(S1) ;GET THE NAME, AND PERMANENT BIT
SETZM .AMNAM(S1) ;CLEAR IT ALL OUT
TXNE S2,AM.PRM ;IS NAME IN PERMANENT A MATRIX?
$RETT ;YES, LEAVE IT THERE
LOAD S2,S2,AM.NAM ;GET JUST THE STRING ADRS
MOVEI S1,AMNMLN ;LENGTH OF THE BLOCK
$CALL M%RMEM ;GIVE BACK THE STORAGE
$RETT
> ;END TOPS10 CONDITIONAL
SUBTTL FNTAPE - ROUTINE TO FIND A MAGTAPE VOLUME IN THE VOL DATA BASE
; FNDISK - "" "" "" DISK "" "" "" "" "" ""
; FNDECT - "" "" "" DECTAPE "" "" "" "" "" ""
;CALL: S1/ The Volume We are Looking For
;
;FNDISK RET: S1/ The Volume block Address
;
;FNTAPE RET: S1/ The Volume block Address
; S2/ The UCB Address if The Volume is Mounted or 0
;
;FNDECT RET: S1/ The Volume block Address
; S2/ The UCB Address if The Volume is Mounted or 0
D$FNDV:: ;MAKE 'FNDISK' GLOBAL
FNDISK: SKIPA S2,[%DISK] ;WANT TO FIND STRUCTURE VOLUMES
FNTAPE: MOVX S2,%TAPE ;WANT TO FIND TAPE VOLUMES
SETZM TF ;WANT TO WTO THE OPERATOR
JRST CHKV.0 ;CONTINUE ON
FNDECT: MOVX S2,%DTAP ;WANT TO FIND DECTAPE VOLUMES
SETZM TF ;WANT TO WTO THE OPERATOR
JRST CHKV.0 ;CONTINUE ON
D$FTPX::
FNTAPX: MOVX S2,%TAPE ;WANT A TAPE VOL
SETOM TF ; BUT NO WTO IF MOUNTED
CHKV.0: PUSHJ P,.SAVE3 ;SAVE P1 - P3 FOR A MINUTE
MOVE P1,S1 ;SAVE THE VOL WE ARE LOOKING FOR
MOVE P2,S2 ;SAVE THE ENTRY POINT INDICATOR
MOVE P3,TF ;SAVE THE WTO FLAG
;See if we can find the mounted volume in our requested volume list.
MOVE S1,VOLQUE ;GET THE VOLUME QUEUE ID
PUSHJ P,L%FIRST ;POSITION TO THE FIRST ENTRY
JRST CHKV.2 ;SKIP THE FIRST TIME THROUGH
CHKV.1: MOVE S1,VOLQUE ;GET THE VOLUME QUEUE ID
PUSHJ P,L%NEXT ;GET THE NEXT VOL ENTRY
CHKV.2: JUMPF .RETF ;MSG VOLUME NOT FOUND,,RETURN
MOVE S1,S2 ;GET THE VOLUME ADDRESS IN S1
CAME P1,.VLNAM(S1) ;HAVE WE FOUND THE MSG VOLUME ???
JRST CHKV.1 ;NO,,TRY THE NEXT VOL ENTRY
SKIPE S2,.VLVSL(S1) ;GET A VSL ADDRESS
LOAD S2,.VSFLG(S2),VS.TYP ;GET THE VOLUME TYPE
JUMPE S2,[SKIPN S2,.VLUCB(S1) ;NO VSL ADDRESS,,GET UCB ADDRESS
JRST CHKV.1 ;NO UCB, BETTER SKIP IT
LOAD S2,.UCBST(S2),UC.DVT ;GET THE VOLUME TYPE
JRST CHKV.3 ] ;AND CONTINUE
CHKV.3: CAME S2,P2 ;DO WE HAVE THE CORRECT VOLUME TYPE ???
JRST CHKV.1 ;NO,,TRY NEXT
CAIN P2,%DISK ;LOOKING FOR DECTAPE OR MAGTAPES?
$RETT ;NO,,RETURN
;Found the Tape Volume in Our VOL Data Base,,Make Sure its not Mounted
SKIPN S2,.VLUCB(S1) ;FOUND IT,,IS THE VOL ALREADY MOUNTED ?
$RETT ;NO, RETURN TRUE
JUMPN P3,.RETT ;YES, IF NO WTO WANTED, RETURN
$WTO (<Volume ^W/.VLNAM(S1)/ already mounted on ^W/.UCBNM(S2)/>,,MDAOBJ)
$RETT ;AND RETURN TRUE (FOUND)
SUBTTL FNDOWN - FIND ANY OWNER OF A VOLUME
;CALL: S1/ The VOL Block Address
;
;RET: S1/ The Address of The VSL Address of The First Owner
;
; False if the Volume is not owned
D$VOWN::
FNDOWN: LOAD TF,.VLOWN(S1),VL.CNT ;GET THE VOLUME REQUEST COUNT
JUMPE TF,.RETF ;NO REQUESTORS,,NO OWNERS...
MOVNS TF ;NEGATE IT
HRL S1,TF ;GET NEGATIVE COUNT IN LEFT HALF
MOVX TF,VL.ASN+VL.ASK ;GET THE VOLUME ASSIGNED+ASK BITS
FNDO.1: TDNE TF,.VLVSL(S1) ;DOES THIS USER OWN THE VOLUME ???
JRST [MOVEI S1,.VLVSL(S1) ;YES,,GET THE ADDRESS OF THE VSL ADDRESS
$RETT ] ;AND RETURN IT
AOBJN S1,FNDO.1 ;NO,,TRY NEXT
$RETF ;AND RETURN
SUBTTL FNDMDR - ROUTINE TO FIND AN MDR GIVEN ITS JOB NUMBER
;CALL: FNDMDR: S1/ The Users Job #
;
;RET: AP/ The MDR Address If Found
; False if the MDR Can't be Found
D$FMDR::
FNDMDR: PUSHJ P,.SAVE1 ;SAVE P1 FOR A MINUTE
MOVE P1,S1 ;SAVE THE JOB NUMBER
MOVE S1,MDRQUE ;GET THE MDR QUEUE ID
PUSHJ P,L%FIRST ;GET THE FIRST MDR ENTRY
JRST FNDM.2 ;JUMP THE FIRST TIME THROUGH
FNDM.1: MOVE S1,MDRQUE ;GET THE MDR QUEUE ID
PUSHJ P,L%NEXT ;GET THE NEXT MDR ENTRY
FNDM.2: JUMPF .RETF ;MDR NOT FOUND !!!
LOAD S1,.MRJOB(S2),MR.JOB ;LOAD THE MDR JOB NUMBER
CAME S1,P1 ;DO THEY MATCH ???
JRST FNDM.1 ;NO,,TRY THE NEXT MDR
MOVE AP,S2 ;YES,,GET THE MDR ADDRESS IN AP
$RETT ;RETURN
SUBTTL FNDVSL - ROUTINE TO FIND A PARTICULAR VSL IN AN MDR
;CALL: S1/ The VSL Request ID
;
;RET: S1/ The VSL Address if Found
; AP/ The MDR Address
D$FVSL::
FNDVSL: PUSHJ P,.SAVE1 ;SAVE P1
MOVE P1,S1 ;SAVE THE VSL REQUEST ID
MOVE S1,VSLQUE ;GET THE VSL QUEUE ID
PUSHJ P,L%FIRST ;GET THE FIRST VSL ENTRY
JRST FNDV.2 ;JUMP THE FIRST TIME THROUGH
FNDV.1: MOVE S1,VSLQUE ;GET THE VSL QUEUE ID
PUSHJ P,L%NEXT ;GET THE NEXT VSL ENTRY
FNDV.2: JUMPF .RETF ;NO MORE,,RETURN
MOVE S1,.VSRID(S2) ;GET THE VSL REQUEST ID
CAME P1,S1 ;DO THEY MATCH ???
JRST FNDV.1 ;NO,,TRY NEXT VSL
MOVE AP,.VSMDR(S2) ;YES,,SETUP THE MDR POINTER
MOVE S1,S2 ;AND THE VSL ADDRESS
$RETT ;RETURN
SUBTTL FNDVSN - ROUTINE TO FIND A VOLUME SET VIA THE VOL SET NAME
;CALL: S1/ The Asciz Vol Set Name Address
;
;RET: S1/ The VSL Address
TOPS10<
D$FVSN::
FNDVSN: PUSHJ P,.SAVE2 ;SAVE P1 & P2 FOR A MINUTE
HRROI P2,0(S1) ;GET -1,,VOL SET NAME ADDR
LOAD P1,.MRCNT(AP),MR.CNT ;GET THE VSL COUNT
MOVNS P1 ;NEGATE IT
MOVSS P1 ;MOVE RIGHT TO LEFT
HRRI P1,.MRVSL(AP) ;CREATE VSL SEARCH AOBJN AC
DVSN.1: MOVE S1,0(P1) ;GET A VSL ADDRESS
HRROI S1,.VSVSN(S1) ;POINT TO THE VSL VOL SET NAME
MOVE S2,P2 ;GET THE SOURCE VOL SET NAME POINTER
PUSHJ P,S%SCMP ;PERFORM THE STRING COMPARE
TXNN S1,SC%LSS+SC%SUB+SC%GTR ;ANY OF THESE BITS LIT ???
JRST [MOVE S1,0(P1) ;NO SO WE MATCH,,GET THE VSL ADDRESS
$RETT ] ;AND RETURN
AOBJN P1,DVSN.1 ;NO MATCH,,TRY NEXT VSL
$RETF ;NOT THERE !!!
> ;END TOPS10 CONDITIONAL
SUBTTL FNDLNM - ROUTINE TO FIND A USERS VSL GIVEN A LOGICAL NAME
;CALL: S1/ The Asciz Vole Set Name Address
; AP/ The MDR Address
;
;RET: S1/ The VSL Address if Found
TOPS10<
D$FLNM:: ;MAKE IT GLOBAL
FNDLNM: PUSHJ P,.SAVE1 ;SAVE P1
HRROI S1,0(S1) ;POINT TO ASCIZ VOLUME SET NAME
PUSHJ P,S%SIXB ;CONVERT IT TO SIXBIT
LDB S1,S1 ;GET TERMINATOR
JUMPN S1,.RETF ;MUST BE NULL FOR LOGICAL NAMES
LOAD P1,.MRCNT(AP),MR.CNT ;GET THE VSL COUNT
MOVNS P1 ;NEGATE IT
MOVSS P1 ;MOVE RIGHT TO LEFT
HRRI P1,.MRVSL(AP) ;CREATE VSL SEARCH AOBJN AC
FNDL.1: MOVE S1,0(P1) ;GET A VSL ADDRESS
CAMN S2,.VSLNM(S1) ;DO THE LOGICAL NAMES MATCH ???
$RETT ;FOUND IT,,RETURN NOW
AOBJN P1,FNDL.1 ;CONTINUE THROUGH ALL VSL'S
$RETF ;NOT THERE,,RETURN
> ;END TOPS10 CONDITIONAL
SUBTTL VSLFND - ROUTINE TO FIND A VSL IN A USERS REQUEST
;CALL: S1/ The Mount Msg Entry Address
; AP/ The MDR Address
;
;RET: S1/ The VSL Address
;This routine searches the users request queue looking for a VSL
;which has the same name as one which he is currently trying
;to mount. It first looks for a VSL which has the same logical
;name, then the one which has the same Vol Set Name.
TOPS10<
VSLFND: PUSHJ P,.SAVE2 ;SAVE P1 AND P2
MOVEI P1,.MEHSZ(S1) ;POINT TO THE FIRST ENTRY BLOCK
MOVE P2,.MECNT(S1) ;GET THE ENTRY COUNT
LOAD S1,.MRCNT(AP),MR.CNT ;GET THE REQUEST COUNT
JUMPE S1,.RETF ;NONE THERE,,RETURN
VSLF.1: LOAD S1,ARG.HD(P1),AR.TYP ;GET THIS BLOCK TYPE
CAXE S1,.SMNAM ;IS IT THE VOL SET NAME ???
CAXN S1,.TMSET ;IS IT THE VOL SET NAME BLOCK ???
JRST VSLF.2 ;YES,,CHECK IT OUT
LOAD S1,ARG.HD(P1),AR.LEN ;NO,,GET THIS BLOCKS LENGTH
ADD P1,S1 ;POINT TO THE NEXT BLOCK
SOJG P2,VSLF.1 ;CONTINUE FOR ALL BLOCKS
$RETF ;NO VOL SET NAME BLOCK FOUND !!!
VSLF.2: AOS P1 ;POINT TO THE ASCIZ VOL SET NAME
MOVE S1,P1 ;GET ITS ADDRESS IN S1
PUSHJ P,FNDLNM ;LOOK FOR THE LOGICAL NAME
JUMPT .RETT ;FOUND,,RETURN NOW
MOVE S1,P1 ;GET THE VOL SET NAME ADDR BACK
PJRST FNDVSN ;RETURN LOOKING FOR THE VOL SET NAME
> ;END TOPS10 CONTITIONAL
TOPS20<
VSLFND: $RETF > ;ALWAYS RETURN FALSE ON THE -20
SUBTTL GENVOL - ROUTINE TO CREATE A 'SCRATCH' VOLUME BLOCK
;CALL: S1/ The VSL Address of the User
;
;RET: True Always
GENVOL: PUSHJ P,.SAVE1 ;SAVE P1 FOR A MINUTE
MOVE P1,S1 ;SAVE THE VSL ADDRESS
MOVE S1,VOLQUE ;GET THE VOLUME LIST QUEUE ID
MOVX S2,VOLLEN ;GET THE VOL ENTRY LENGTH
PUSHJ P,L%CENT ;CREATE SPACE FOR THE VOL ENTRY
LOAD S1,.VSCVL(P1),VS.OFF ;GET THE OFFSET TO THE CURRENT VOL
ADDI S1,.VSVOL(P1) ;POINT TO THE VOL BLOCK ADDRESS
MOVEM S2,0(S1) ;LINK THE VOL TO THE VSL
MOVEM P1,.VLVSL(S2) ;LINK THE VSL TO THE VOL
MOVX S1,%STAWT ;GET 'WAITING' STATUS CODE
STORE S1,.VLFLG(S2),VL.STA ;SAVE IT IN THE VOL FLAG WORD
INCR .VLOWN(S2),VL.CNT ;BUMP THE REQUEST COUNT BY 1
LOAD S1,.VSFLG(P1),VS.LBT ;GET THE REQUESTED LABEL TYPE
STORE S1,.VLFLG(S2),VL.LBT ;AND SAVE IT IN THE VOL FLAG WRD
MOVX S1,VL.SCR ;GET THE VOLUME SCRATCH BIT
IORM S1,.VLFLG(S2) ;LITE IT IN THE VOL FLAG WORD
INCR .VSCVL(P1),VS.CNT ;MAKE THE VSL COUNT = 1
$RETT ;AND RETURN
SUBTTL ADDVOL - ROUTINE TO ADD A VOL BLOCK DURING MOUNT PROCESSING
;CALL: S1/ The Volume Name
; S2/ The VSL Address
;
;RET: The VOL Block Address
ADDVOL: PUSHJ P,.SAVE2 ;SAVE P1 AND P2 FOR A SECOND
DMOVE P1,S1 ;SAVE THE CALLING ARGS
PUSHJ P,SCNVOL ;GO FIND THE REQUESTED VOLUME
JUMPT .RETT ;FOUND ONE,,RETURN NOW
MOVE S1,VOLQUE ;GET THE VOLUME LIST QUEUE ID
MOVX S2,VOLLEN ;GET THE VOL LIST ENTRY LENGTH
PUSHJ P,L%CENT ;CREATE SPACE FOR THE VOL ENTRY
MOVEM P1,.VLNAM(S2) ;SAVE THE VOLID IN THE VOL
MOVEM P2,.VLVSL(S2) ;LINK THE VSL TO THE VOL
MOVX S1,%STAWT ;GET 'VOLUME WAITING' CODE
STORE S1,.VLFLG(S2),VL.STA ;SAVE IT AS THE VOLUME STATUS
INCR .VLOWN(S2),VL.CNT ;BUMP THE REQUEST COUNT BY 1
MOVE S1,S2 ;GET THE VOL BLK ADDR IN S1
$RETT ;RETURN
SUBTTL CKUVOL - CHECK FOR MULTIPLE USER REQUESTS FOR THE SAME TAPE VOL
; CKOVOL - SAME - BUT OPERATOR ENTRY POINT
;CALL: S1/ The VSL address
; AP/ The MDR Address
;
;RET: True - if ok
; False - The error text inserted into the generic ack buffer
TOPS10<
CKTVOL: PUSHJ P,.SAVE4 ;SAVE P1 - P4
$SAVE <T1,T2> ;SAVE T1 AND T2 ALSO
MOVE P1,S1 ;SAVE THE VSL ADDRESS
LOAD P2,.MRCNT(AP),MR.CNT ;GET THE VSL COUNT
MOVNS P2 ;NEGATE IT
MOVSS P2 ;MOVE RIGHT TO LEFT
HRRI P2,.MRVSL(AP) ;CREATE VSL AOBJN AC
CKTV.1: MOVE P3,0(P2) ;GET A VSL ADDRESS
LOAD S1,.VSFLG(P3),VS.TYP ;GET THE VSL TYPE
CAXE S1,%TAPE ;IS IT A TAPE VOLUME SET ???
JRST CKTV.6 ;NO,,TRY NEXT
CKTV.2: LOAD S1,.VSCVL(P1),VS.CNT ;GET THE VOLUME COUNT
MOVNS S1 ;NEGATE IT
MOVSS S1 ;MOVE RIGHT TO LEFT
HRRI S1,.VSVOL(P1) ;CREATE VOL AOBJN AC
CKTV.3: LOAD S2,.VSCVL(P3),VS.CNT ;GET THE VOLUME COUNT
MOVNS S2 ;NEGATE IT
MOVSS S2 ;MOVE RIGHT TO LEFT
HRRI S2,.VSVOL(P3) ;CREATE VOL AOBJN AC
MOVE P4,0(S1) ;GET THE MASTER VOL ADDRESS
SKIPN P4,.VLNAM(P4) ;AND GET ITS VOLID
JRST CKTV.6 ;NONE,,ASSUME A SCRATCH TAPE & CONTINUE
SETZM T2 ;CLEAR VOLUME COUNTER
CKTV.4: AOS T2 ;BUMP VOLUME COUNTER BY 1
MOVE T1,0(S2) ;GET THE TARGET VOL ADDRESS
CAME P4,.VLNAM(T1) ;DO VOLIDS MATCH ???
JRST CKTV.5 ;NO,,CONTINUE ONWARD !!!
CAMN P1,P3 ;YES,,SAME VOLUME SET ???
CAME S1,S2 ;YES,,SAME VOLUME SET INDEX ???
JRST CKTV.7 ;NO,,THATS AN ERROR
CKTV.5: AOBJN S2,CKTV.4 ;CHECK THROUGH ALL TARGET VOLUMES
AOBJN S1,CKTV.3 ;CHECK THROUGH ALL MASTER VOLIDS
CKTV.6: AOBJN P2,CKTV.1 ;CHECK THROUGH ALL VSL'S
$RETT ;OK,,RETURN
CKTV.7: $TEXT (<-1,,@G$ACKB>,<Volume ^W/P4/ is volume # ^D/T2/ in volume set ^T/.VSVSN(P3)/^0>)
PJRST E$XXX## ;RETURN THE ERROR
> ;END TOPS10 CONDITIONAL
TOPS20<
CKTVOL: $RETT > ;RETURN OK ON THE -20
SUBTTL Miscellaneous routines
TOPS10<
MISC.3: $WTO (<Invalid message from PULSAR>,<^M^JMSG: ^O/0(M)/, ^O/1(M)/, ^O/2(M)/, ^O/3(M)/, ^O/4(M)/^M^J^O/5(M)/, ^O/6(M)/, ^O/7(M)/, ^O/10(M)/, ^O/11(M)/>,,<$WTFLG(WT.SJI)>)
$RETT
;Routine to tell the operator that a user requested a structure
;be dismounted
;
;CALL: S1/ The VSL Address
; AP/ The MDR Address
TELREM: MOVE S2,.VSVOL(S1) ;GET THE VOL BLOCK ADDRESS
MOVE S1,.VLNAM(S2) ;GET THE STR NAME
MOVEM S1,MDAOBJ+OBJ.UN ;SAVE IT IN THE OBJECT BLOCK
$WTO (<User requests this structure be dismounted^T/BELLS/>,<^I/DEMOT/>,MDAOBJ)
$RETT ;RETURN
> ;END TOPS10 CONDITIONAL
;Routine to set up byte pointer for call to MDADBP.
MDASBP::PUSH P,[POINT 7,G$MSG] ;STUFF A BYTE POINTER
POP P,MDBPTR ;SET UP FOR CALLS TO MDADBP
SETZM G$MSG ;CLEAR THE FIRST WORD
SETZM G$MSG+MSGLN##-1 ; AND THE LAST WORD FOR EOB CHECK
$RETT ;WE'RE HAPPY
;$TEXT Action routine and byte pointer
MDADBP:: SKIPN G$MSG+MSGLN##-1 ;CHECK FOR END OF BUFFER
IDPB S1,MDBPTR ;JUST DUMP THE CHAR
$RETT ;AND WIN
MDBPTR:: BLOCK 1 ;SPACE FOR A BYTE POINTER
;Routine to copy VSL request dependent data from MDR to VSL
;Call: AP = MDR address
; S1 = VSL address
MDR2VS: MOVE TF,.MRPID(AP) ;[1173] MOVE REQUEST DEPENDENT
MOVEM TF,.VSPID(S1) ;[1173] DATA TO VSL
MOVE TF,.MRACK(AP) ;[1173] ..
MOVEM TF,.VSACK(S1) ;[1173] ..
MOVE TF,.MRFLG(AP) ;[1173] ..
MOVEM TF,.VSRFL(S1) ;[1173] ..
$RETT ;[1173] RETURN
SUBTTL D$MDAE - ROUTINE TO NOTIFY THE OPERATOR OF ANY ERRORS
;This routine notifies the operator of any MDA related error
;
;CALL: P/ The address of the Parameter Word
;
;RET: False Always
TOPS10<
D$MDAE::SETZM TF ;NO VSL ADDRESS
LOAD TF,@0(P),AC.VSL ;GET THE AC WHICH CONTAINS THE VSL ADDR
TXO TF,MOVE ;CREATE 'MOVE TF,AC' INSTRUCTION
XCT TF ;GET THE VSL ADDRESS IN TF
POP P,S1 ;GET THE ERROR CODE & AC ADDRESS
LOAD S1,0(S1),ER.CDE ;PICK UP THE ERROR CODE
TXNN TF,MOVE ;DO WE HAVE A VSL ADDRESS ???
JRST MDAE.1 ;YES,,PROCESS A LITTLE DIFFERENTLY !!!
$WTO (<^T/@MDAERS-1(S1)/>,,MDAOBJ) ;ELSE TELL OPERATOR
$RETF ;RETURN
MDAE.1: $SAVE <S1,S2,T1,T2,AP> ;SAVE SOME AC'S
MOVE T1,TF ;GET THE VSL ADDRESS IN T1
MOVE AP,.VSMDR(T1) ;GET THE MDR ADDRESS IN AP
LOAD T2,.VSCVL(T1),VS.OFF ;GET THE OFFSET TO THE CURRENT VOLUME
ADDI T2,.VSVOL(T1) ;POINT TO THE ADDRESS
MOVE T2,0(T2) ;LOAD THE CURRENT VOLUME ADDRESS
LOAD S2,.MRJOB(AP),MR.JOB ;GET THE USERS JOB NUMBER
TXC S2,BA%JOB ;COMPLEMENT
TXNE S2,BA%JOB ;A PSEUDO PROCESS?
SKIPA S2,[DEMOT] ;NO--NORMAL TIMESHARING
MOVEI S2,DEMOB ;PSEUDO-PROCESS
$WTO (<^T/@MDAERS-1(S1)/>,<^I/(S2)/Volume Set:^T/.VSVSN(T1)/ Volid:^W/.VLNAM(T2)/ Request-ID: ^D/.VSRID(T1)/>,MDAOBJ)
$RETF ;RETURN
> ;END TOPS10 CONDITIONAL
SUBTTL DSKRSN - ROUTINE TO RETURN RESOURCE NUMBERS FOR DISK DRIVES
;CALL: S1/ The .UCBST status word with Kontroller type & Unit Type
;
;RET: S1/ The Device Resource Number
TOPS10<
D$DRSN::
DSKRSN: PUSHJ P,.SAVE2 ;SAVE P1 & P2 FOR A SECOND
LOAD P1,S1,UC.KTP ;GET THE KONTROLLER TYPE IN P1
LOAD P2,S1,UC.UTP ;GET THE UNIT TYPE IN P2
MOVE S1,AMATRX ;GET THE 'A' MATRIX ADDRESS
LOAD S2,.AMHDR(S1),AM.CNT ;GET THE ENTRY COUNT
JUMPE S2,.RETF ;NULL MATRIX,,SHOULD NOT HAPPEN !!!
DSKR.1: ADDI S1,AMALEN ;BUMP TO NEXT MATRIX ELEMENT
LOAD TF,.AMSTA(S1),AM.DVT ;GET THE RESOURCE TYPE
SKIPGE .AMNAM(S1) ;IS THIS ENTRY VALID?
CAXE TF,%DISK ;YES,, IS THIS A DISK RESOURCE?
JRST DSKR.2 ;NO,,TRY NEXT ENTRY
LOAD TF,.AMSTA(S1),UC.KTP ;GET THE ENTRY KONTROLLER TYPE
CAME TF,P1 ;THEY MUST MATCH..
JRST DSKR.2 ;NO,,TRY NEXT ENTRY
LOAD TF,.AMSTA(S1),UC.UTP ;GET THE ENTRY UNIT TYPE
CAME TF,P2 ;THEY MUST MATCH..
JRST DSKR.2 ;NO,,TRY NEXT ENTRY
SUB S1,AMATRX ;CALC OFFSET INTO MATRIX OF THIS ENTRY
IDIVI S1,AMALEN ;CALC RESOURCE NUMBER
$RETT ;RETURN
DSKR.2: SOJG S2,DSKR.1 ;LOOK AT ALL MATRIX ENTRIES
$RETF ;NOT THERE !!!
> ;END TOPS10 CONDITIONAL
SUBTTL TAPRSN - ROUTINE TO RETURN RESOURCE NUMBERS FOR TAPE DRIVES
;CALL: S1/ The Density Status Bits
; S2/ The Track Status Code
; T1/ The starting RSN if ANYTAP entry
;
;RET: S1/ The Device Resource Number
TOPS10<
ANYTAP: PUSHJ P,.SAVE4 ;SAVE P1 - P4
DMOVE P1,S1 ;SAVE THE DENSITY AND TRACK TYPE
MOVEI P3,0 ;SET THE ENTRY INDICATOR
MOVE S1,AMATRX ;GET THE 'A' MATRIX ADDRESS
LOAD P4,.AMHDR(S1),AM.CNT ;GET THE ENTRY COUNT
SUB P4,T1 ;GET REMAINING COUNT
JUMPLE P4,.RETF ;NO MORE ENTRIES,,RETURN
MOVE S1,T1 ;GET THE STARTING RSN IN S1
IMULI S1,AMALEN ;GET THE OFFSET
ADD S1,AMATRX ;AND THE RESOURCE ADDRESS
JRST TAPR.1 ;MEET AT THE PASS
D$TRSN::PUSHJ P,.SAVE4 ;SAVE SOME ACS
DMOVE P1,S1 ;COPY DENSITY AND TRACK TYPE
MOVEI P3,0 ;SET ENTRY INDICATOR
JRST TAPR.0 ;ENTER COMMON CODE
TAPRSN: PUSHJ P,.SAVE4 ;SAVE P1 & P2 FOR A SECOND
DMOVE P1,S1 ;SAVE THE DENSITY AND TRACK TYPE
MOVEI P3,1 ;SET THE ENTRY INDICATOR
TAPR.0: MOVE S1,AMATRX ;GET THE 'A' MATRIX ADDRESS
LOAD P4,.AMHDR(S1),AM.CNT ;GET THE ENTRY COUNT
JUMPE P4,.RETF ;NULL MATRIX,,SHOULD NOT HAPPEN !!!
TAPR.1: ADDI S1,AMALEN ;BUMP TO NEXT MATRIX ENTRY
LOAD S2,.AMSTA(S1),AM.DVT ;GET THE RESOURCE TYPE
SKIPGE .AMNAM(S1) ;IS THIS ENTRY VALID AT ALL?
CAXE S2,%TAPE ;YES,, IS THIS A TAPE RESOURCE?
JRST TAPR.2 ;NO,,TRY NEXT ENTRY
LOAD S2,.AMSTA(S1),UC.TRK ;GET THE ENTRY TRACK TYPE
CAME S2,P2 ;THEY MUST MATCH..
JRST TAPR.2 ;NO,,TRY NEXT ENTRY
MOVE S2,.AMSTA(S1) ;GET THE STATUS BITS
AND S2,[UC.200+UC.556+UC.800+UC.1600+UC.6250] ;SAVE ONLY THESE BITS
XCT [TDNN S2,P1 ;ANY BITS CAN MATCH !!!
CAME S2,P1](P3) ;ALL BITS MUST MATCH !!!
JRST TAPR.2 ;NO GOOD,,TRY NEXT ENTRY
SUB S1,AMATRX ;CALC OFFSET INTO MATRIX OF THIS ENTRY
IDIVI S1,AMALEN ;CALC THE RESOURCE NUMBER
$RETT ;RETURN
TAPR.2: SOJG P4,TAPR.1 ;LOOK AT ALL MATRIX ENTRIES
$RETF ;NOT THERE !!!
D$ORSN::
DTARSN: PUSHJ P,.SAVE1 ;SAVE P1
MOVE S1,AMATRX ;GET THE 'A' MATRIX ADDRESS
LOAD P1,.AMHDR(S1),AM.CNT ;AND THE ENTRY COUNT
JUMPE P1,.RETF ;DEFEND AGAINST A NULL MATRIX
DTAR.1: ADDI S1,AMALEN ;POINT TO NEXT MATRIX ENTRY
LOAD S2,.AMSTA(S1),AM.DVT ;GET RESOURCE TYPE
SKIPGE .AMNAM(S1) ;IS THIS ENTRY VALID?
CAIE S2,%DTAP ;AND IS THIS A DECTAPE RESOURCE?
JRST DTAR.2 ;NO
SUB S1,AMATRX ;GET OFFSET INTO MATRIX
IDIVI S1,AMALEN ;COMPUTE THE RESOURCE NUMBER
$RETT ;AND RETURN
DTAR.2: SOJG P1,DTAR.1 ;LOOP
$RETF ;NO RESOURCE AVAILABLE
> ;END TOPS10 CONDITIONAL
SUBTTL D$TNRS - GET A MAGTAPE RESOURCE NUMBER
; D$DNRS - GET A DISK RESOURCE NUMBER
; D$ONRS - GET A DECTAPE RESOURCE NUMBER
;CALL: D$TNRS: S1/ The Density Status Bits
; S2/ The Track Status Code
;
; D$DNRS: S1/ The UCB Status Word
;
;RET: S1/ The Resource Number if valid, False otherwise
TOPS10<
D$TNRS::$SAVE <T1> ;SAVE T1
MOVEI T1,TAPRSN ;GET STATUS CHECK ROUTINE EXACT MATCH
PJRST KNOWRS ;TRY TO FIND ONE , OR A NEW ONE
D$DNRS::$SAVE <T1> ;SAVE T1
MOVEI T1,DSKRSN ;GET THE SERVICE ROUTINE ADRS
PJRST KNOWRS ;GO FIND A KNOWN RESOURCE
D$ONRS::$SAVE <T1> ;SAVE T1
MOVEI T1,DTARSN ;SERVICE ROUTINE
; PJRST KNOWRS ;TRY TO FIND A RESOURCE
;This routine will find an existing resource of a given type
; or look in the permanent A matrix for drives which match
; If the entry is found in the permanent matrix, it is added
; to the existing A matrix and the new resource number is returned
KNOWRS: $SAVE <P1,P2,P3> ;SAVE P1 - P3
DMOVE P1,S1 ;SAVE THE CALLING ARGS
PUSHJ P,0(T1) ;TRY TO FIND IN THE EXISTING A MATRIX
JUMPT .RETT ;IF THAT WINS, WE'RE GOLDEN!
DMOVE S1,P1 ;GET BACK STATUS BITS
MOVEI P1,AMATPM ;AIM AT THE PERMANENT A MATRIX
EXCH P1,AMATRX ;AND POINT THE WORLD AT THAT
PUSHJ P,0(T1) ;TRY TO FIND ONE OF THOSE
JUMPF [MOVEM P1,AMATRX ;CAN'T GET IT THERE, RESTORE AMATRIX
$RETF] ;GIVE THE BAD NEWS
MOVE P3,S1 ;GOT IT, SAVE ITS INDEX
EXCH P1,AMATRX ;GET BACK TO OLD A MATRIX
PUSHJ P,GETRSN ;FIND A FREE SLOT
PUSH P,S1 ;SAVE THE NEW RESOURCE NUMBER
IMULI S1,AMALEN ;INDEX INTO THE EXISTING A MATRIX
IMULI P3,AMALEN ;INDEX INTO PERMANENT A MATRIX
ADD S1,AMATRX ;AIM AT EXISTING SLOT
ADDI P3,0(P1) ;AIM AT PERMANENT SLOT
HRL S1,P3 ;SET SOURCE FOR BLT
MOVE P3,S1 ;COPY FOR TERMINATION ADRS
BLT S1,AMALEN-1(P3) ;MOVE THE DATA IN
POP P,S1 ;GET BACK THE NEW RESOURCE NUMBER
$RETT
> ;END TOPS10 CONDITIONAL
SUBTTL STRRSN - ROUTINE TO RETURN RESOURCE NUMBERS FOR STRUCTURES
;CALL: S1/ The Sixbit Structure Name
;
;RET: S1/ The Structure Resource Number
TOPS10<
D$SRSN::
MOVX S2,%STRC ;GET RESOURCE TYPE -- FILE STRUCTURE
DEVRSN: PUSHJ P,.SAVE3 ;SAVE SOME SCRATCH REGS
MOVE P3,S2 ;SAVE THE RESOURCE TYPE
$TEXT (<-1,,TMPVSL>,<^W/S1/^0>) ;CONVERT STR NAME TO ASCII
MOVE P1,AMATRX ;GET THE 'A' MATRIX ADDRESS
LOAD P2,.AMHDR(P1),AM.CNT ;GET THE ENTRY COUNT
JUMPE P2,STRR.2 ;NULL MATRIX,,SHOULD NOT HAPPEN !!!
STRR.1: ADDI P1,AMALEN ;BUMP TO THE NEXT MATRIX ELEMENT
LOAD S2,.AMSTA(P1),AM.DVT ;GET THE RESOURCE TYPE
SKIPGE S1,.AMNAM(P1) ;IS THIS ENTRY IN USE?
CAME S2,P3 ;YES,, IS THIS THE CORRECT TYPE OF RESOURCE??
JRST STR.1A ;NOPE, TRY THE NEXT ENTRY
HRLI S1,-1 ;AIM AT THE STRING
HRROI S2,TMPVSL ;AIM AT THE DESIRED NAME
$CALL S%SCMP ;COMPARE THE NAMES
TXNE S1,SC%LSS!SC%SUB!SC%GTR ;ANY BITS ON?
JRST STR.1A ;YES, THAT'S NOT EXACT MATCH
SUB P1,AMATRX ;NO,,CALC THE RESOURCE OFFSET
IDIVI P1,AMALEN ;CALC THE RESOURCE NUMBER
MOVE S1,P1 ;MOVE IT INTO RETURN SLOT
$RETT ;AND RETURN
STR.1A: SOJG P2,STRR.1 ;LOOK AT ALL MATRIX ENTRIES
;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE
;Here if the structure is not in the 'A' matrix,
; so add an entry for it!
;P1-P3 saved
;P3/ Resource type
;TMPVSL/ Resource name (ASCIZ)
STRR.2: PUSHJ P,GETRSN ;GET A RESOURCE NUMBER
MOVE P1,S1 ;SAVE IT
IMULI P1,AMALEN ;CALC OFFSET INTO THE MATRIX
ADD P1,AMATRX ;LOCATE THE ENTRY
MOVEI S1,AMNMLN ;GET THE NAME SPACE SIZE
$CALL M%GMEM ;GET THE SPACE
IORX S2,AM.USE ;LITE THE IN-USE BIT
MOVEM S2,.AMNAM(P1) ;SAVE THE ADRS OF THE NAME
HRLI S2,TMPVSL ;AIM AT THIS STRUCTURE NAME
HRRZI S1,AMNMLN(S2) ;FIGURE TERMINATION ADRS
BLT S2,-1(S1) ;MOVE TH NAME IN
SETZM .AMSTA(P1) ;ZERO THE STATUS WORD
STORE P3,.AMSTA(P1),AM.DVT ;SET DESIRED RESOURCE TYPE
MOVEI S2,1 ;GET DEFAULT NUMBER AVAILABLE
CAXN P3,%STRC ;IS THIS A SHARABLE RESOURCE?
MOVX S2,MAXRES ;YES,,GET MAX RESOURCE COUNT
STORE S2,.AMCNT(P1),AM.AVA ;MAKE IT THE NUMBER AVAILABLE
SUB P1,AMATRX ;CALC THE MATRIX OFFSET
IDIVI P1,AMALEN ;CALC THE RESOURCE NUMBER
MOVE S1,P1 ;COPY THE RSN OVER
$RETT ;AND RETURN
> ;END TOPS10 CONDITIONAL
SUBTTL D$T/SVRS - Generate resource #s for Tape/Structure volumes
;CALL: S1/ VOL Block Address
;
;RET: S1/ The Volume RSN
; Volume resource number in the vol block
TOPS10<
INTERN D$TVRS ;GLOBALIZE IT
INTERN D$SVRS ;HERE ALSO
D$TVRS: SKIPA S2,[EXP %TVOL] ;RESOURCE TYPE - TAPE VOLUME
D$SVRS: MOVX S2,%STRC ;RESOURCE TYPE - STRUCTURE
JRST VRSX ;ENTER COMMON CODE
D$OVRS: MOVX S2,%DTVOL ;RESOURCE TYPE - DECTAPE
VRSX: LOAD TF,.VLFLG(S1),VL.RSN ;IS THERE ALREADY A RSN?
JUMPN TF,[MOVE S1,TF ;YES, COPY IT
$RETT ] ;AND WIN
$SAVE <P1,P2> ;SAVE SOME SPACE
DMOVE P1,S1 ;SAVE VOL BLK, RESOURCE TYPE
MOVE S1,.VLNAM(S1) ;GET THE SIXBIT VOLUME NAME
PUSHJ P,DEVRSN ;MAKE UP A RSN
STORE S1,.VLFLG(P1),VL.RSN ;SAVE THE RSN
$RETT ;WIN
> ;END TOPS10 CONDITIONAL
SUBTTL VALMSG - ROUTINE TO VALIDATE THE MOUNT/ALLOCATE MESSAGE
;CALL: M/ The Mount/Allocate Message Address
;
;RET: True if valid, False otherwise
VALMSG: PUSHJ P,.SAVE4 ;SAVE P1 - P4
STKVAR <MSGLEN,MNTALC> ;GET SPACE FOR MSG LEN & MOUNT STATUS
LOAD S1,.MSTYP(M),MS.CNT ;GET THE MESSAGE LENGTH
CAIL S1,.MMHSZ ;MUST BE GREATER THEN .MMHSZ AND
CAIL S1,.MMUMX ; LESS THEN .MMUMX
PJRST E$IBL## ;ELSE ITS AN ERROR
ADD S1,M ;POINT TO THE END OF THE MESSAGE
MOVEM S1,MSGLEN ;AND SAVE IT
MOVE P1,.MMARC(M) ;GET THE VOLUME SET COUNT IN P1
JUMPL P1,E$IBL## ;CAN'T BE NEGATIVE
JUMPE P1,VALM.3 ;IF 0, THEN REST OF MESSAGE MBZ
MOVEI P2,.MMHSZ(M) ;POINT TO THE FIRST MOUNT ENTRY
LOAD P3,.MSTYP(M),MS.TYP ;GET THE MSG TYPE (.QIFNC IS INTERNAL)
LOAD S1,.MEFLG(P2),ME%ALC ;GET THE FIRST ENTRY'S MOUNT/ALLOC BIT
MOVEM S1,MNTALC ;SAVE IT FOR LATER
VALM.1: CAMLE P2,MSGLEN ;MUST BE LESS OR EQUAL TO END OF MSG
PJRST E$IBL## ;NO GOOD,,RETURN INVALID MESSAGE
LOAD S1,.MEFLG(P2),ME%ALC ;GET THE MOUNT/ALLOCATE STATUS BIT
CAXE P3,.QIFNC ;IS THIS AN INTERNAL REQUEST ???
CAMN S1,MNTALC ;CAN'T MIX MOUNT/ALLOCATE IN SAME MSG
SKIPA ;INTERNAL OR MATCHING TYPES,,SKIP
PJRST E$IBL## ;HE DID,,RETURN INVALID MESSAGE
LOAD S1,.MEHDR(P2),AR.LEN ;GET THIS ENTRIES LENGTH
ADD S1,P2 ;POINT TO THE END OF THE ENTRY
MOVEI S2,.MEHSZ(P2) ;POINT TO THE DATA BLOCK AREA
CAIG S2,0(S1) ;MUST BE LESS OR EQUAL TO END OF ENTRY
SKIPG P4,.MECNT(P2) ; AND ENTRY COUNT MUST BE POSITIVE
PJRST E$IBL## ;NO,,THATS AN ERROR
VALM.2: LOAD TF,ARG.HD(S2),AR.LEN ;GET THIS BLOCK'S LENGTH
ADD S2,TF ;POINT TO THE NEXT BLOCK
CAILE S2,0(S1) ;MUST STILL BE WITHIN THE ENTRY
PJRST E$IBL## ;NO,,THATS AN ERROR
SOJG P4,VALM.2 ;CONTINUE CHECKING ALL ENTRY BLOCKS
MOVE P2,S2 ;POINT TO NEXT 'ME' ENTRY
SOJG P1,VALM.1 ;CONTINUE THROUGH ALL VOLUME SETS
CAME P2,MSGLEN ;CALC AND ACTUAL END ADDRS MUST BE EQUAL
PJRST E$IBL## ;NO,,THATS AN ERROR
$RETT ;RETURN OK
VALM.3: MOVEI P1,.OFLAG(M) ;GET FLAG WORD ADDRESS
VALM.4: AOS P1 ;POINT TO NEXT WORD
SKIPE 0(P1) ;MUST BE ZERO...
JRST E$IBL## ;NO,,THATS AN ERROR
CAMGE P1,MSGLEN ;ARE WE DONE ???
JRST VALM.4 ;NO,,CHECK NEXT
$RETT ;YES,,RETURN
SUBTTL CHKBAT - ROUTINE TO CHECK FOR BATCH REQUESTS DOING MOUNTS
;CALL: AP/ The MDR Address
;
;RET: True if OK, False if Illegal
D$CHKB:: ;GLOBALIZE IT
CHKBAT: LOAD S1,.MRJOB(AP),MR.JOB ;GET THE SENDERS JOB NUMBER
TXNE S1,BA%JOB ;ARE WE EXECUTING YET ????
JRST CHKB.4 ;NO,,THEN CHECK SCHEDULABILITY
SKIPE S1,.MRQEA(AP) ;LOAD UP THE QE ADDRESS
;**;[1135]ADD AND REVAMP CODE AT CHKBAT:+4L 7-JUL-83/CTK
SKIPN .QEOBJ(S1) ;[1135]ONE MORE CHECK BEFORE WE DO IT !!
$RETT ;NOT A SCHEDULED JOB,,THEN RETURN
GETLIM S2,.QELIM(S1),OINT ;[1135]GET USERS /ASSIST: SWITCH
CAXN S2,.OPINY ;IS INTERVENTION ALLOWED ???
$RETT ;YES,,THEN HE IS OK !!!
MOVE S1,.QEOBJ(S1) ;[1135]GET ADDR OF OBJECT PARAMETERS
MOVE S2,OBJPID(S1) ;GET THE PROCESSORS PID
MOVEM S2,G$SAB##+SAB.PD ;SET IT
MOVE S2,OBJUNI(S1) ;GET THE STREAM NUMBER
MOVEM S2,ABOSTM ;SET IT
MOVE S2,OBJNOD(S1) ;GET THE NODE NUMBER
MOVEM S2,ABONOD ;SET IT
MOVX S1,ABOLEN ;GET THE MSG LENGTH
MOVEM S1,G$SAB##+SAB.LN ;SET IT
MOVEI S2,ABOMSG ;GET THE MSG ADDRESS
MOVEM S2,G$SAB##+SAB.MS ;SET IT
PUSHJ P,C$SEND## ;SEND THE CANCEL MSG
$RETF ;RETURN
CHKB.4: SKIPN S1,.MRQEA(AP) ;CHECK AND LOAD QE ADDRESS
STOPCD (MQE,HALT,,<Missing QE for a pseudo process>)
PJRST S$INPS## ;CHECK SCHEDULABILITY AND RETURN
;Gen cancel msg here (Cheaper then generating 'on the fly')
ABOMSG: ABOLEN,,.OMCAN ;.MSTYP - LENGTH,,CANCEL MSG
0,,0 ;.MSFLG - NO FLAG BITS
-1 ;.MSCOD - ACK CODE -1 IS $LOG
0,,0 ;.OFLAG - NO FLAG BITS
0,,3 ;.OARGC - 3 DATA BLOCKS
4,,.OROBJ ;OBJECT BLOCK
.OTBAT ; BATCH QUEUE
ABOSTM: 0,,0 ; STREAM #
ABONOD: 0,,0 ; NODE NAME
2,,.CANTY ;CANCEL TYPE
.CNERR ; WITH ERROR PROCESSING
5,,.ORREA ;CANCEL REASON
ASCIZ/MOUNT request in 'No Operator Intervention' batch job is illegal/
ABOLEN==.-ABOMSG ;MESSAGE LENGTH
SUBTTL BLDVSL - ROUTINE TO BREAK DOWN MOUNT MSG ENTRIES
;CALL: S1/ The Address of the Mount Msg Entry
;
;RET: S1/ The VSL Address if Mount Entry was Valid
BLDVSL: PUSHJ P,.SAVE4 ;SAVE P1 & P2 & P3 & P4 FOR A MINUTE
MOVE P3,S1 ;SAVE THE MOUNT MSG ENTRY ADDR
PUSHJ P,VSLFND ;LOOK FOR ANOTHER VSL BY THE SAME VSN
JUMPT [MOVE P2,S1 ;FOUND ONE,,SAVE THE VSL ADDRESS
TLO P2,400000 ;MARK THIS VSL AS A DUPLICATE REQUEST
JRST BLDV.3 ] ;AND CONTINUE
MOVEI S1,VSLLEN ;GET THE VSL LENGTH
MOVEI S2,TMPVSL ;GET THE TEMP VSL ADDRESS
PUSHJ P,.ZCHNK ;CLEAR THE TEMP VSL
SETZM VOLNBR ;CLEAR THE VOLUME-SET VOLUME COUNT
SETZM STRVOL ;AND THE STARTING VOLUME ID
MOVE S1,VSLQUE ;GET THE VSL QUEUE ID
PUSHJ P,L%LAST ;POSITION TO THE END OF THE VSL
MOVE S1,VOLQUE ;GET THE VOLUME QUEUE ID
PUSHJ P,L%LAST ;POSITION TO THE END OF THE LIST
MOVEI P2,TMPVSL ;POINT TO OUR TEMP VSL
MOVX S1,VS.OPR+VS.WAL+VS.ALC ;GET NOTIFY OPR+ALLOCATE WAIT BITS
MOVEM S1,.VSFLG(P2) ;SET THEM
LOAD S1,.MEHDR(P3),AR.TYP ;GET THE ENTRY TYPE
MOVX S2,%UNKN ;DEFAULT TO UNKNOWN
CAXN S1,.MNTTP ;IS THIS A TAPE MOUNT REQUEST ???
MOVX S2,%TAPE ;YES,,SAY SO
CAXN S1,.MNTST ;IS IT A STRUCTURE ???
MOVX S2,%DISK ;YES,,SAY SO
TOPS20< CAXN S1,.DSMST ;IS IT DISMOUNT STRUCTURE ???
MOVX S2,%DSMT > ;YES,,SAY SO
STORE S2,.VSFLG(P2),VS.TYP ;SAVE THE REQUEST TYPE
LOAD S1,.MEFLG(P3),ME%ALC ;GET THE ALLOCATE BIT
STORE S1,.VSFLG(P2),VS.UAL ;SET/CLEAR USER ALLOCATED
TOPS10< MOVX S1,DEFLBT ;GET THE DEFAULT LABEL TYPE
STORE S1,.VSFLG(P2),VS.LBT > ;AND SAVE IT
MOVX S1,VS.DPR ;[1164] GET DEFAULT PROTECTION BIT
IORM S1,.VSATR(P2) ;[1164] LITE IT IN ATTRIBUTE WORD
AOS S1,REQIDN## ;BUMP AND LOAD THE REQUEST COUNT
MOVEM S1,.VSRID(P2) ;SAVE IT FOR THIS VOLUME SET REQUEST
MOVE S1,G$NOW## ;GET THE CURRENT TIME
MOVEM S1,.VSCRE(P2) ;SAVE AS REQUEST CREATION TIME
MOVE P1,P3 ;SAVE THE MSG ENTRY START ADDRESS
ADDI P1,.MEHSZ ;POINT TO THE FIRST MESSAGE BLOCK
MOVE P4,.MECNT(P3) ;GET THE VOLUME SET BLOCK COUNT IN P4
SETZM CATFLG ;INIT FLAG TO ALLOW CATALOG SEARCHES
BLDV.1: LOAD S1,ARG.HD(P1),AR.TYP ;GET THE BLOCK TYPE
SKIPE S1 ;BLOCK TYPE CANT BE 0
CAILE S1,%MDMAX ;OR GREATER THEN DEFINE BLOCK TYPES
PJRST BLDV.4 ;ELSE THATS AN ERROR !!!
LOAD S1,MDRDSP(S1) ;GET THE BLOCK PROCESSOR ADDRESS
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
BLDV.2: PUSHJ P,0(S1) ;GO PROCESS THE BLOCK
JUMPF BLDV.4 ;NO GOOD,,THATS AN ERROR
LOAD S1,ARG.HD(P1),AR.LEN ;GET THE BLOCK LENGTH
ADD P1,S1 ;POINT TO THE NEXT BLOCK
SOJG P4,BLDV.1 ;CONTINUE THROUGH ALL VOL-SET BLOCKS
MOVX S1,TM%SCR ;BIT TO TEST
TDNE S1,.MEFLG(P3) ;/SCRATCH SPECIFIED?
AOS CATFLG ;DISALLOW CATALOG SEARCHES
SKIPN .VSVSN(P2) ;ANY VOL SET NAME SPECIFIED ???
PJRST E$IVN## ;NO,,THEN INVALID VOLUME SET NAME !!!
MOVE S1,P2 ;GET THE VSL ADDRESS IN S1
PUSHJ P,I$CUNK## ;CHECK FOR 'UNKNOWN' REQUEST TYPES
CAIE P2,TMPVSL ;POINTING TO TEMP VSL ???
JRST BLDV.3 ;NO,,THEN ALLS OK
MOVE S1,VSLQUE ;GET THE VSL QUEUE ID
MOVX S2,VSLLEN ;GET THE VSL ENTRY LENGTH
PUSHJ P,L%CENT ;CREATE SPACE FOR THE VSL ENTRY
MOVE P2,S2 ;SAVE THE NEW VSL ENTRY ADDRESS
HRLI S1,TMPVSL ;GET THE SOURCE VSL ADDRESS
HRRI S1,0(P2) ;GET THE DEST VSL ENTRY ADDRESS
BLT S1,VSLLEN-1(P2) ;COPY THE VSL OVER
LOAD S1,.VSFLG(P2),VS.TYP ;GET THE REQUEST TYPE
CAXE S1,%TAPE ;IS IT A TAPE REQUEST ???
JRST BLD.2A ;NO,,GEN A VOL BLOCK FOR THE REQUEST
MOVE S1,P2 ;YES,,GET THE VSL ADDRESS
PUSHJ P,GENVOL ;GEN A SCRATCH VOL BLOCK
MOVX S1,TM%NEW+TM%SCR ;GET SCRATCH OR NEW STATUS BITS
TDNE S1,.MEFLG(P3) ;WAS /SCRATCH OR /NEW REQUESTED ???
JRST BLDV.3 ;YES,,CONTINUE
PUSHJ P,E$RNS## ;UH OH,,A REEL ID IS REQUIRED !!!
JRST BLDV.4 ;RETURN THE ERROR !!!
BLD.2A: HRROI S1,.VSVSN(P2) ;POINT TO THE VOL SET NAME
PUSHJ P,S%SIXB ;CONVERT IT TO SIXBIT
MOVE S1,S2 ;SAVE THE VOLUME NAME IN S1
MOVE S2,P2 ;GET THE VSL ADDRESS IN S2
PUSHJ P,ADDVOL ;ADD A VOL BLOCK
MOVEM S1,.VSVOL(P2) ;LINK THE VOL TO THE VSL
INCR .VSCVL(P2),VS.CNT ;BUMP THE VOLUME COUNT
BLDV.3: TDZA P4,P4 ;INDICATE A NORMAL RETURN
BLDV.4: SETOM P4 ;INDICATE AN ERROR RETURN
LOAD S1,.MRCNT(AP),MR.LNK ;GET THE VSL LINK CODE
STORE S1,.VSLNK(P2),VS.LNK ;SET IT
LOAD S1,.MEFLG(P3),TM%WLK ;GET WRITE-LOCK BIT FROM REQUEST
STORE S1,.VSFLG(P2),VS.MWL ;SAVE IT FOR LATER
LOAD S1,.MEFLG(P3),TM%WEN ;GET WRITE-ENABLE BIT FROM REQUEST
STORE S1,.VSFLG(P2),VS.MWE ;SAVE IT FOR LATER
JUMPN P4,BLDV.5 ;IF AN ERROR,,SKIP THIS
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
LOAD P1,.VSFLG(P2),VS.TYP ;GET THE VSL TYPE
JUMPN P1,BLD.4B ;CONTINUE IF KNOWN TYPE
MOVX S1,VS.FDV ;BIT TO TEST
TDNE S1,.VSFLG(P2) ;FOREIGN (UNIT RECORD) DEVICE?
JRST BLD.4A ;THOSE ARE NEVER CATALOGED
SKIPE CATFLG ;OK TO SEARCH CATALOG?
JRST BLD.4B ;NO--USER SPEC'ED OUT THE VOLUME-SET
HRRZ S1,P2 ;ELSE POINT TO VSL
PUSHJ P,V$GCAT## ;AND CHECK THE CATALOG
JUMPF BLD.4C ;IF NOT FOUND, THEN CAN'T DO DEFAULTING
HRRZ P2,S1 ;ELSE THE VSL MIGHT HAVE BEEN EXTENDED
JRST BLD.4C ;DON'T OVERWRITE VSL AND VOL PARAMETERS
BLD.4A: MOVX S1,VS.ALC!VS.WAL ;CLEAR ALLOCATION BITS FOR
ANDCAM S1,.VSFLG(P2) ; FOREIGN (UNIT RECORD) DEVICES
BLD.4B: CAXN P1,%DISK ;IS IT A STRUCTURE ???
PUSHJ P,DEFDSK ;YES,,DEFAULT IT
CAXN P1,%TAPE ;IS IT A TAPE REQUEST ???
PUSHJ P,DEFTAP ;YES,,DELAULT IT
CAXN P1,%DTAP ;IS IT A DECTAPE REQUEST ?
PUSHJ P,DEFDTA ;YES - DEFAULT IT
JUMPT BLD.4C ;CONTINUE IF NO ERRORS
MOVNI P4,1 ;ELSE FLAG THE ERROR
JRST BLDV.5 ;AND FINISH UP
BLD.4C: LOAD S1,.MEFLG(P3),ME%ALC ;GET THE ALLOCATE/MOUNT BIT
LOAD S2,.VSFLG(P2),VS.ALC ;GET THE VOL SET STATE BIT
AND S1,S2 ;PERFORM SOME MAGIC !!!
STORE S1,.VSFLG(P2),VS.ALC ;SET/CLEAR THE ALLOCATE/MOUNT BIT
TLZE P2,400000 ;WAS THIS A DUPLICATE VOL SET REQUEST?
JRST [MOVE S1,P2 ;YES,,GET THE VSL ADDR IN S1
$RETT ] ; AND RETURN NOW
;Here to Link to MDR and VSL together and Update the request count
BLDV.5: LOAD S1,.MRCNT(AP),MR.CNT ;GET THE VSL REQUEST COUNT
ADDI S1,.MRVSL(AP) ;POINT TO THE CURRENT VSL ADDRESS
MOVEM P2,0(S1) ;LINK THE VSL TO THE MDR
MOVEM AP,.VSMDR(P2) ;LINK THE MDR TO THE VSL
INCR .MRCNT(AP),MR.CNT ;BUMP THE VSL COUNT BY 1
MOVE S1,P2 ;GET THE VSL ADDRESS
JUMPN P4,.RETF ;NO GOOD,,RETURN NOW
CAIE P1,%TAPE ;IS THIS A TAPE MOUNT ???
$RETT ;NO--JUST RETURN
PUSHJ P,CKTVOL ;CHECK OUT THE TAPE VOLUMES REQUESTED
MOVE S1,P2 ;GET THE VSL ADDRESS BACK
POPJ P, ;RETURN GOOD OR BAD...
SUBTTL VSL DEFAULTING ROUTINES
DEFTAP: MOVE S1,.MEFLG(P3) ;GET THE REQUEST FLAG WORD
MOVE S2,.VSFLG(P2) ;GET OUR FLAG WORD
TLNN P2,400000 ;IS THIS THE FIRST TIME AROUND ??
TXO S2,VS.WLK ;YES,,DEFAULT TO WRITE-LOCKED
TXNE S1,TM%SCR ;IS THIS A TEMP VOLUME SET ???
TXO S2,VS.SCR ;YES,,SAY SO
TXNE S1,TM%NEW ;IS THIS A NEW VOLUME SET ???
TXO S2,VS.NEW ;YES,,SAY SO
TXNE S1,TM%WEN+TM%SCR+TM%NEW ;WRITE ENABLED OR SCRATCH OR NEW ???
TXZ S2,VS.WLK ;YES,,MAKE IT WRITE ENABLED !!!
TXNE S1,TM%WLK ;ARE WE WRITE LOCKED ???
TXO S2,VS.WLK ;YES,,SAY SO
MOVEM S2,.VSFLG(P2) ;SAVE OUR FLAG WORD
TOPS10< TLNE P2,400000 ;IS THIS A DUPLICATE MOUNT REQUEST ???
$RETT ;YES,,CAN'T MODIFY THE ATTRIBUTES !!!!
MOVE S1,.VSATR(P2) ;GET THE REQUESTED ATTRIBUTES
LOAD S2,S1,VS.TRK ;GET THE REQUESTED TRACK TYPE
SKIPN S2 ;SPECIFY ANY TRACK TYPE ???
TXO S1,FLD(DEFTRK,VS.TRK)+VS.DTK ;NO,,DEFAULT IT
LOAD S2,S1,VS.DEN ;GET THE REQUESTED DENSITY
JUMPN S2,DEFT.1 ;IF SPECIFIED,,DO NOT DEFAULT
LOAD S2,S1,VS.TRK ;GET THE TRACK TYPE
CAXN S2,%TRK7 ;IS IT A 7 TRACK REQUEST ???
TXO S1,FLD(DEF7TK,VS.DEN)+VS.DDN ;YES,,DEFAULT DENSITY
CAXE S2,%TRK7 ;IS IT A 9 TRACK REQUEST ???
TXO S1,FLD(DEF9TK,VS.DEN)+VS.DDN ;YES,,DEFAULT DENSITY
DEFT.1: MOVEM S1,.VSATR(P2) ;SAVE THE ATTRIBUTES.
LOAD S1,.VSATR(P2),VS.DEN ;GET THE DENSITY STATUS CODE
MOVE S1,D$DEN(S1) ;CONVERT IT TO A BIT MASK
LOAD S2,.VSATR(P2),VS.TRK ;GET THE TRACK STATUS CODE
SETZM T1 ;START AT THE TOP OF THE RESOURCE LIST
PUSHJ P,ANYTAP ;GET THE TAPE RESOURCE NUMBER
JUMPF E$NUA## ;NO,,RETURN 'NO UNITS AVAILABLE'
STORE S1,.VSATR(P2),VS.RSN ;SAVE THE REQUESTED DEVICE TYPE
> ;END TOPS10 CONDITIONAL
$RETT ;RETURN
DEFDSK:
TOPS10< MOVE S1,.MEFLG(P3) ;GET THE REQUEST FLAG WORD
MOVE S2,.VSFLG(P2) ;GET OUR FLAG WORD
TXZ S2,VS.WLK!VS.PAS!VS.NOC!VS.ARD ;RESET BITS FROM MOUNT MESSAGE
TXNE S1,TM%WLK ;ARE WE WRITE LOCKED ???
TXO S2,VS.WLK ;YES,,SAY SO
TXNE S1,SM%PAS ;WANT IT IN PASSIVE HALF?
TXO S2,VS.PAS ;YES, LITE IT
TXNE S1,SM%NOC ;WANT NO-CREATE?
TXO S2,VS.NOC ;YES, LITE THAT
TXNE S1,SM%ARD ;WANT TO ALWAYS RECOMPUTE DISK USAGE?
TXO S2,VS.ARD ;YES
TXNE S1,SM%EXC ;WANT SINGLE ACCESS?
TLNE P2,400000 ;IS THIS THE FIRST TIME AROUND ?
SKIPA ;NOT /SINGLE OR MOUNTED AGAIN !
TXO S2,VS.SIN ;YES, SAY SO
MOVEM S2,.VSFLG(P2) ;SAVE FLAG WORD
> ;END TOPS10 CONDITIONAL
$RETT ;RETURN
DEFDTA:
TOPS10< LOAD S1,.VSCVL(P2),VS.CNT ;GET VOLUME COUNT
SOJN S1,E$MRD## ;CAN ONLY HAVE ONE REEL PER VOL-SET
MOVE S1,.MEFLG(P3) ;GET THE REQUEST FLAG WORD
MOVE S2,.VSFLG(P2) ;GET OUR FLAG WORD
TLNN P2,400000 ;IS THIS THE FIRST TIME AROUND ??
TXO S2,VS.WLK ;YES,,DEFAULT TO WRITE-LOCKED
TXNE S1,TM%SCR ;IS THIS A TEMP VOLUME SET ???
TXO S2,VS.SCR ;YES,,SAY SO
TXNE S1,TM%NEW ;IS THIS A NEW VOLUME SET ???
TXO S2,VS.NEW ;YES,,SAY SO
TXNE S1,TM%WEN+TM%SCR+TM%NEW ;WRITE ENABLED OR SCRATCH OR NEW ???
TXZ S2,VS.WLK ;YES,,MAKE IT WRITE ENABLED !!!
TXNE S1,TM%WLK ;ARE WE WRITE LOCKED ???
TXO S2,VS.WLK ;YES,,SAY SO
MOVEM S2,.VSFLG(P2) ;SAVE OUR FLAG WORD
PUSHJ P,DTARSN ;GET A DECTAPE RESOURCE
JUMPF E$NUA## ;NONE AVAILABLE
STORE S1,.VSATR(P2),VS.RSN ;SAVE
> ;END TOPS10 CONDITIONAL
$RETT ;RETURN
SUBTTL MOUNT REQUEST BLOCK PROCESSOR ROUTINES
;DENSITY BLOCK PROCESSOR
MNTDEN: AOS CATFLG ;DISALLOW CATALOG SEARCHES
TOPS10< LOAD S1,ARG.HD(P1),AR.LEN ;GET THE BLOCK LENGTH
CAIE S1,2 ;MUST BE 2
PJRST E$IDE## ;Else bad density
MOVE S1,ARG.DA(P1) ;GET THE DENSITY
JUMPL S1,E$IDE ;CAN'T BE NEGATIVE
CAXLE S1,DENLEN ;CAN'T BE GREATER THEN TABLE LENGTH
PJRST E$IDE ;YES,,THATS AN ERROR
STORE S1,.VSATR(P2),VS.DEN ;STORE DENSITY INDEX
> ;END TOPS10 CONDITIONAL
PJRST CHKTAP ;MAKE SURE THIS WAS A TAPE REQUEST !!!
MNTPRT:
TOPS10< LOAD S1,ARG.HD(P1),AR.LEN ;GET THE BLOCK LENGTH
CAIE S1,2 ;MUST BE 2
$RETF ;ELSE BAD BLOCK
MOVE S1,ARG.DA(P1) ;GET THE PROTECTION
CAIG S1,777 ;SEE IF WITHIN RANGE
SKIPGE S1 ; . . .
$RETF ;NO, RETURN FALSE
STORE S1,.VSATR(P2),VS.PRT ;STORE THE PROTECTION CODE
MOVX S1,VS.DPR ;[1164] GET DEFAULT PROTECTION BIT
ANDCAM S1,.VSATR(P2) ;[1164] TURN IT OFF
> ;END TOPS10 CONDITIONAL
PJRST CHKTAP ;MAKE SURE THIS WAS A TAPE REQUEST !!!
;DRIVE TYPE BLOCK PROCESSOR
MNTDRV: AOS CATFLG ;DISALLOW CATALOG SEARCHES
LOAD S1,ARG.HD(P1),AR.LEN ;GET THE BLOCK LENGTH
CAIE S1,2 ;MUST BE 2
$RETF ;ELSE RETURN
MOVE S1,ARG.DA(P1) ;GET THE DRIVE TYPE
MOVX S2,%TRK9 ;DEFAULT TO A 9 TRACK REQUEST
CAXN S1,.TMDR7 ;IS IT A SEVEN TRACK REQUEST ???
MOVX S2,%TRK7 ;YES,,SAY SO
STORE S2,.VSATR(P2),VS.TRK ;SAVE THE REQUEST TRACK TYPE
PJRST CHKTAP ;MAKE SURE THIS WAS A TAPE REQUEST !!!
;LABEL TYPE BLOCK PROCESSOR
MNTLT: AOS CATFLG ;DISALLOW CATALOG SEARCHES
LOAD S1,ARG.HD(P1),AR.LEN ;GET THE BLOCK LENGTH
CAIE S1,2 ;MUST BE 2
PJRST E$ILT## ;ELSE INVALID LABEL TYPE
MOVE S1,ARG.DA(P1) ;GET THE LABEL TYPE
CAXL S1,%TFMIN ;CHECK RANGE
CAXLE S1,%TFMAX ;MUST BE BETWEEN THE MIN AND MAX VALUES
PJRST E$ILT## ;INVALID LABEL TYPE
STORE S1,.VSFLG(P2),VS.LBT ;AND SAVE IT
CAXN S1,%TFLBP ;DOES HE WANT BYPASS PROCESSING ???
SKIPE [NPRTBL] ;YES,,IS IT OK FOR ALL USERS ???
PJRST CHKTAP ;NOT BLP OR OK FOR ALL USERS,,WIN
PUSHJ P,A$WHEEL## ;IS HE PRIV'D ???
JUMPF E$PRB## ;NO,,TOO BAD !!!
PJRST CHKTAP ;MAKE SURE THIS WAS A TAPE REQUEST !!!
;VOLUME SET NAME BLOCK PROCESSOR
MNTSET: LOAD S1,ARG.HD(P1),AR.LEN ;GET THE BLOCK LENGTH
SUBI S1,1 ;SUBTRACT OFF THE HEADER LENGTH
CAILE S1,VSNLEN ;MUST BE LESS OR EQUAL VSNLEN
PJRST E$IVN## ;RETURN INVALID VOL SET NAME !
TOPS10< HRROI S1,ARG.DA(P1) ;GET THE SOURCE VOLUME SET NAME
HRROI S2,.VSVSN(P2) ;GET THE DESTINATION ADDRESS
PUSHJ P,STRVSN ;STORE IT
JUMPF .RETF ;RETURN IF INVALID VOL SET NAME
> ;End TOPS10 conditional
TOPS20<
SETVSN: $TEXT (<-1,,.VSVSN(P2)>,<^W/ARG.DA(P1)/^0>) ;SIXBIT VSN TO ASCII
MOVE S2,ARG.DA(P1) ;Get SIXBIT VSN
> ;End TOPS20 conditional
SKIPN .VSLNM(P2) ;Do we have logical name?
MOVEM S2,.VSLNM(P2) ;No..store default
$RETT ;RETURN
;Here to make sure the request is a tape request
CHKTAP: LOAD S1,.VSFLG(P2),VS.TYP ;GET THE VOL SET TYPE
CAXN S1,%TAPE ;IS IT A TAPE REQUEST ???
$RETT ;YES..ALL IS FINE
CAXE S1,%UNKN ;IS IT AN UNKNOWN REQUEST ???
PJRST E$ISA## ;NO,,Invalid structure attribute
MOVX S1,%TAPE ;GET 'TAPE' REQUEST TYPE
STORE S1,.VSFLG(P2),VS.TYP ;SET IT
$RETT ;RETURN
;Here to make sure the request is a disk request
CHKDSK: LOAD S1,.VSFLG(P2),VS.TYP ;GET THE VOL SET TYPE
CAXN S1,%DISK ;IS IT A DISK REQUEST??
$RETT ;YES..ALL IS FINE
CAXE S1,%UNKN ;IS IT AN UNKNOWN REQUEST??
PJRST E$ITA## ;NO,,Invalid tape attribute
MOVX S1,%DISK ;GET 'DISK' REQUEST TYPE
STORE S1,.VSFLG(P2),VS.TYP ;SET IT
$RETT ;RETURN
TOPS10 <
;STRVSN - Routine to validate and store Volume Set name
;Translates lower case to upper and checks to make sure
;that only characters "A-Z", "0-9" and "_" are included
;ACCEPTS S1/ Pointer to source string
; S2/ Pointer to destination address
;RETURNS TRUE S1/ Sixbit equivalent of string or 0
; S2/ Sixbit abbriviation of string
;RETURNS FALSE E$IVN (Invalid Volume Set Name)
STRVSN: $SAVE <P1,P2> ;Save some AC's
TLCE S1,-1 ;Make real pointers
TLCN S1,-1
HRLI S1,(POINT 7)
TLCE S2,-1
TLCN S2,-1
HRLI S2,(POINT 7)
MOVE P1,S1 ;Copy source pointer
STRVS1: ILDB P2,P1 ;Get a source byte
CAIL P2,"a" ;Lower case?
SUBI P2,"a"-"A" ;Yes..raise it
CAIL P2,"A" ;Alpha?
CAILE P2,"Z"
JRST [CAIL P2,"0" ;No..numeric?
CAILE P2,"9"
JRST [CAIE P2,"-" ;No..hypen or null?
JUMPN P2,E$IVN##
JRST .+1] ;Yes..then store it
JRST .+1] ;Store numeric
IDPB P2,S2 ;Store the character
JUMPN P2,STRVS1 ;Terminate after null
$CALL S%SIXB ;Get sixbit abbriv.
LDB S1,S1 ;Get terminator
SKIPN S1 ;Was it null?
SKIPA S1,S2 ;Yes..return sixbit
SETZM S1 ;No..return 0
$RETT
> ;End TOPS10 conditional
;LOGICAL NAME BLOCK PROCESSOR
MDRLNM: LOAD S1,ARG.HD(P1),AR.LEN ;GET THE BLOCK LENGTH
CAIE S1,2 ;LENGTH MUST BE 2
$RETF ;ELSE RETURN
MOVE S1,ARG.DA(P1) ;GET THE LOGICAL NAME
MOVEM S1,.VSLNM(P2) ;SAVE IT
$RETT ;AND RETURN
;STARTING VOLUME BLOCK PROCESSOR
MNTSTV: LOAD S2,ARG.HD(P1),AR.LEN ;GET THE BLOCK LENGTH
MOVE S1,ARG.DA(P1) ;GET THE FIRST DATA WORD
CAIN S2,2 ;IS THE BLOCK LENGTH 2 ???
JRST MNTS.1 ;YES,,GO PROCESS THIS FORMAT
CAIE S2,3 ;OR IS THE BLOCK LENGTH 3 ???
$RETF ;ELSE THATS AN ERROR
SKIPE ARG.DA(P1) ;THIS MUST BE NULL
$RETF ;ELSE THATS AN ERROR
MOVE S1,ARG.DA+1(P1) ;GET THE SIXBIT STARTING VOLUME ID
MNTS.1: MOVEM S1,STRVOL ;SAVE IT HERE FOR A MINUTE
CAIE P2,TMPVSL ;ARE WE POINTING AT THE TEMP VSL ???
PJRST UPDSVL ;NO,,GO UPDATE STARTING VOLUME INFO
PJRST CHKTAP ;MAKE SURE THIS WAS A TAPE REQUEST !!!
;REMARK BLOCK PROCESSOR
MNTRMK: $SAVE <P4> ;SAVE P4 FOR A MINUTE
LOAD P4,ARG.HD(P1),AR.LEN ;GET THE BLOCK LENGTH
SUBI P4,1 ;GET THE TEXT LENGTH
IMULI P4,5 ;GET THE LENGTH IN BYTES
CAILE P4,^D59 ;WILL WE FIT ???
MOVEI P4,^D59 ;NO,,MAKE IT FIT
MOVEI S1,ARG.DA(P1) ;POINT TO THE SOURCE TEXT
HRLI S1,(POINT 7,0) ;MAKE IT A BYTE POINTER
MOVE S2,[POINT 7,.VSREM(P2)] ;GET THE DESTINATION BYTE POINTER
MNTR.1: ILDB TF,S1 ;GET A BYTE
IDPB TF,S2 ;SAVE IT
JUMPE TF,.RETT ;END ON A NULL
SOJG P4,MNTR.1 ;OR 59 CHARACTERS (WHICHEVER IS FIRST)
$RETT ;AND RETURN
;VOLUME LIST BLOCK PROCESSOR
MNTVOL: AOS CATFLG ;DISALLOW CATALOG SEARCHES
CAIE P2,TMPVSL ;MUST BE POINTING AT THE TEMP VSL !!!
$RETF ;NO,,THATS AN ERROR
TOPS10< LOAD S1,.VSFLG(P2),VS.TYP ;GET THE REQUEST TYPE
CAXN S1,%DISK ;CAN'T BE A STRUCTURE
PJRST E$ISS## ;YES,,THATS AN ERROR
> ;END TOPS10 CONDITIONAL
;WEED OUT DUPLICATE MSG VOLUME BLOCKS (only last one counts)
MOVE S1,P1 ;GET THE VOL BLOCK HDR ADDR IN S!
MOVE S2,.MECNT(P3) ;GET THE REMAINING BLOCK CNT IN S2
MNTV.A: LOAD TF,ARG.HD(S1),AR.LEN ;GET THE BLOCK LENGTH
ADD S1,TF ;POINT TO THE NEXT MSG BLOCK
LOAD TF,ARG.HD(S1),AR.TYP ;GET ITS TYPE
CAXE TF,.TMVOL ;IF THE A TAPE VOLUME ???
CAXN TF,.SMALI ;OR IS IT A STRUCTURE VOLUME ???
$RETT ;YES,,IGNORE THE CURRENT VOL BLOCK
SOJG S2,MNTV.A ;NO,,TRY NEXT MSG BLOCK
LOAD S2,ARG.HD(P1),AR.LEN ;GET THE BLOCK LENGTH
SOJLE S2,.RETF ;CANT BE 1 OR NEGATIVE !!!
CAILE S2,^D60 ;MUST BE LESS THE 60 VOLUMES
$RETF ;ELSE THAT AN ERROR
MOVEM S2,VOLNBR ;SAVE THE VOLUME COUNT
ADDI S2,VSLLEN-1 ;CALC THE VSL LENGTH
MOVE S1,VSLQUE ;GET THE VSL QUEUE ID
PUSHJ P,L%CENT ;CREATE SPACE FOR THE VSL ENTRY
MOVE P2,S2 ;SAVE THE NEW VSL ADDRESS
HRLI S1,TMPVSL ;GET THE SOURCE VSL ADDRESS
HRRI S1,0(P2) ;GET THE DEST VSL ADDRESS
BLT S1,VSLLEN-1(P2) ;COPY THE PROTOTYPE VSL OVER
MOVE T1,VOLNBR ;GET THE VOLUME COUNT
MOVEI T2,.VSVOL(P2) ;POINT T2 AT THE VSL VOL ADDRESSES
MOVEI T3,ARG.DA(P1) ;POINT T3 AT THE VOLUME LIST
MNTV.B: MOVE S1,0(T3) ;PICK UP THE VOLUME NAME IN S1
MOVE S2,P2 ;GET THE VSL POINTER IN S2
PUSHJ P,ADDVOL ;ADD A VOL BLOCK
MOVEM S1,0(T2) ;LINK THE VOL TO THE VSL
INCR .VSCVL(P2),VS.CNT ;BUMP THE VOLUME COUNT BY 1
SKIPN .VLNAM(S1) ;WAS IT VALID ???
PJRST E$VID## ;UH OH,,NULL VOLIDS ARE ILLEGAL !!!
MNTV.C: AOS T2 ;POINT TO THE NEXT VSL VOLUME
AOS T3 ;POINT TO THE NEXT MSG VOLUME
SOJG T1,MNTV.B ;CONTINUE TILL DONE
TOPS20< SKIPN .VSVSN(P2) ;ANY VOLUME SET NAME YET ???
PUSHJ P,SETVSN > ;NO,,GEN ONE !!!
SKIPE S1,STRVOL ;CHECK AND LOAD THE STARTING VOLUME ID
PJRST UPDSVL ;SOMETHING THERE,,UPDATE STARTING VOLUME
MOVX S1,VS.REL ;GET REEL ID SPECIFIED FLAG
IORM S1,.VSFLG(P2) ;SET IT
$RETT ;RETURN
SUBTTL Count the number of requests needing a structure
; Count up the number of requests requiring a structure
; Call: MOVE S1, VOL block address
; PUSHJ P,D$NREQ
; On return, S1:= #requests
;
TOPS10 < ;MDA ONLY
D$NREQ::
CTNREQ: $SAVE <P1,P2,P3,P4> ;SAVE SOME ACS
MOVE P1,S1 ;SAVE THE VOL BLK ADRS
LOAD P2,.VLOWN(P1),VL.CNT ;GET THE NUMBER OF REQUESTORS
JUMPE P2,NREQ.4 ;NONE, SAY SO
MOVNS P2 ;NEGATE IT
MOVSS P2 ;TO LEFT HALF
HRRI P2,.VLVSL(P1) ;AIM AT THE LIST OF VSL POINTERS
SETZ P1, ;CLEAR COUNT OF USERS
NREQ.1: MOVX TF,VL.ASN ;GET THE 'MOUNTED' BIT
TDNN TF,0(P2) ;DOES THIS REQUESTOR (VSL) OWN IT?
JRST NREQ.3 ;NO, TRY THE NEXT VSL
MOVE S1,0(P2) ;AIM AT THE VSL
SKIPN S1,.VSMDR(S1) ;BACK UP TO THE MDR
PUSHJ P,S..IMV ;OOPS!!
MOVE P4,S1 ;SAVE THE MDR ADDRESS
LOAD S2,.MRJOB(P4),MR.JOB ;GET THE JOB NUMBER
TXNE S2,BA%JOB ;PSEUDO PROCESS ???
AOS P1 ;COUNT IT
NREQ.3: AOBJN P2,NREQ.1 ;CHECK ALL THE REQUESTORS
SKIPA S1,P1 ;GET NUMBER OF REQUESTS
NREQ.4: SETZ S1, ;HERE IF NO REQUESTS
$RETT ;RETURN
> ;END TOPS10 CONDITIONAL
SUBTTL BLDSTR - ROUTINE TO PIECE TOGETHER VOL BLKS AND MAKE A STRUCTURE
;CALL: S1/ The Structure Name we want
; S2/ The Alias Name or 0
;
;RET: True if a Structure Can be Built, False Otherwise
TOPS10 <
BLDSTR: PUSHJ P,.SAVE2 ;SAVE P1 - P2
SKIPN S2 ;IS S2 NULL ???
MOVE S2,S1 ;MAKE THE ALIAS THE STRUCTURE NAME
MOVE P2,S2 ;SAVE THE ALIAS FOR LATER
MOVE P1,S1 ;SAVE THE STRUCTURE NAME
PUSHJ P,FNDISK ;FIND THE PRIMARY STR IN THE VOL QUEUE
$RETIF ;RETURN IF NOT FOUND
MOVE P1,S1 ;SAVE THE PRI STR VOL ADDRESS
BLDS.1: SKIPN .VLUCB(S1) ;IS THE VOLUME SPINNING ???
$RETF ;NO
SKIPN S1,.VLNXT(S1) ;ANOTHER VOL IN THE STRUCTURE ?
JRST BLDS.2 ;NO,,WE HAVE ALL THE REQUIRED VOLS !!!
PUSHJ P,FNDDSK ;YES,,GO FIND IT IN OUR DATA BASE
JUMPT BLDS.1 ;FOUND IT,,GO CHECK IT OUT
$RETF ;RETURN
BLDS.2: LOAD S1,.VLFLG(P1),VL.STA ;GET THE STRUCTURE STATUS BITS
CAXN S1,%STAMN ;IS IT MOUNTED ???
$RETT ;YES,,RETURN
MOVE S1,P1 ;GET PRIMARY VOL BLOCK ADDRESS
PUSHJ P,V$CREA## ;GENERATE A CATALOG ENTRY
JUMPF BLDS.3 ;CAN'T DO IT
DMOVE S1,P1 ;GET VOL ADDR AND ALIAS NAME
SETZM WRTLCK ;CLEAR WRITE-LOCKED FLAG
SETZM OSNFLG ;CLEAR OVERRIDE-SET-NUMBER FLAG
PUSHJ P,SNDBLD ;TELL PULSAR TO BUILD THE STRUCTURE
$RETT ;AND RETURN
BLDS.3: $WTO (<Cannot mount structure ^W/P2/>,,,<$WTFLG(WT.SJI)>)
MOVX S1,VL.FRC ;[1217] STRUCTURE TRYING TO BE 'FORCED'
TDNN S1,.VLFLG(P1) ;[1217] UP BY SOMEONE ??
$RETF ;RETURN
MOVE S1,P1 ;[1217] YES, BUT TOO BAD!!!
MOVX S2,.DMNCK ;[1217] GET /NOCHECK BIT
PUSHJ P,SNDDSM ;[1217] TELL PULSAR TO DISMOUNT STR
$RETF ;[1217] RETURN FALSE
> ;END TOPS-10 CONDITIONAL
SUBTTL SNDBLD - ROUTINE TO LINK THE STR VOL BLKS AND SEND STR BUILD MSG
; SNDDSM - ROUTINE TO SEND DISMOUNT STR MSG AND DELETE VOL BLKS
;CALL: S1/ The Primary STR VOL Block Address
; S2/
; SNDBLD - The Structure Name
; SNDDSM - Any flag bits (.DMNCK)
;
;RET: True Always
TOPS10 <
SNDDSM: PUSHJ P,.SAVE4 ;SAVE ALL THE P'S
MOVE P3,S2 ;SAVE THE FLAGS
LOAD S2,.VLNAM(S1) ;GET THE STRUCTURE NAME
SETZB TF,WRTLCK ;INDICATE 'SNDDSM' ENTRY POINT
SETZM OSNFLG ;CLEAR OVERRIDE-SET-NUMBER FLAG
JRST SNDB.0 ;AND ENTER THE COMMON CODE
SNDBLD: PUSHJ P,.SAVE4 ;SAVE ALL P AC'S
SETOM TF ;INDICATE 'SNDBLD' ENTRY POINT
SETZ P3, ;NO FLAGS
SNDB.0: MOVE P1,S1 ;SAVE THE PRI STR VOL ADDRESS
MOVE P2,TF ;SAVE THE ENTRY POINT INDICATOR
PUSH P,S2 ;SAVE THE STRUCTURE NAME
PUSHJ P,M%GPAG ;GET A PAGE FOR IPCF
MOVEM S1,G$SAB##+SAB.MS ;SAVE ITS ADDRESS IN THE SAB
MOVE S2,[.OHDRS+1,,.QOBLD] ;DEFAULT TO BUILD STR MSG HEADER
SKIPN P2 ;UNLESS WE ARE SENDING DISMOUNT MSG
MOVE S2,[.OHDRS+1,,.QODSM] ; THEN GET THE DISMOUNT MESSAGE HDR
MOVEM S2,.MSTYP(S1) ;SAVE IT
MOVEI S2,2 ;WE ARE PASSING 2 BLOCKS
MOVEM S2,.OARGC(S1) ;SO SET THE BLOCK COUNT IN THE MSG
IORM P3,.OFLAG(S1) ;LITE ANY FLAG BITS
MOVEI P3,.OHDRS(S1) ;POINT TO THE FIRST MSG BLOCK
JUMPN P2,SNDB.Y ;SKIP REQUEST COUNT STUFF IN MOUNTING
PUSH P,S1 ;SAVE S1
MOVEI S1,(P1) ;GET VOL BLOCK ADDRESS
PUSHJ P,CTNREQ ;GET THE NUMBER OF REQUESTS NEEDING STR
MOVE S2,S1 ;GET COUNT
POP P,S1 ;RESTORE MESSAGE ADDRESS
STORE S2,.OFLAG(S1),.DMNRQ ;SAVE IN MESSAGE
SNDB.Y: MOVE S1,[ARG.DA+.BLDLN,,.BLDSN] ;GET THE BLOCK HEADER
MOVEM S1,ARG.HD(P3) ;SET IT UP
POP P,ARG.DA+.BLDNM(P3) ;INSERT THE ALIAS NAME (STRUCTURE NAME)
SETZM ARG.DA+.BLDOW(P3) ;NO OWNER YET !!!
JUMPE P2,SNDB.X ;DISMOUNT,,THEN SKIP OWNER ID
MOVE S1,.VLNAM(P1) ;MOUNT,,GET STRUCTURE NAME
PUSHJ P,V$STRG## ;CONVERT TO ASCIZ
PUSHJ P,V$FIND## ;GET THE CATALOG ENTRY ADDRESS
JUMPF SNDB.X ;NOT THERE,,OH WELL WE TRIED !!!
MOVE S1,.CQVUS(S1) ;GET THE OWNERS ID
MOVEM S1,ARG.DA+.BLDOW(P3) ;SAVE IN MESSAGE
SNDB.X: MOVSI S1,ARG.DA+.BLDLN ;GET THE BLOCK LENGTH
ADDM S1,@G$SAB##+SAB.MS ;ADD TO THE TOTAL MESSAGE LENGTH
MOVEI P3,ARG.DA+.BLDLN(P3) ;POINT TO NEXT MSG BLOCK
MOVE S1,[1,,.BLDUN] ;GET UNIT NAME(S) BLOCK HEADER
MOVEM S1,ARG.HD(P3) ;SAVE IT IN THE MESSAGE
MOVE S1,P1 ;GET THE FIRST (PRI) VOL BLOCK ADDRESS
MOVE P4,P1 ;MAKE THIS THE CURRENT VOLUME
PUSH P,P3 ;SAVE THIS MSG BLOCK ADDRESS
SNDB.1: MOVE S2,.VLUCB(S1) ;GET THE UNIT WE ARE MOUNTED ON.
LOAD TF,.UCBST(S2),UC.WLK ;GET WRITE-LOCKED BIT
IORM TF,WRTLCK ;REMEMBER IT
MOVX TF,U1.FRC ;[1217] GET 'FORCED' MOUNT BIT FOR UCB
ANDCAM TF,.UCBS1(S2) ;[1217] CLEAR IT IN UCB.
MOVE S2,.UCBNM(S2) ;GET ITS SIXBIT NAME
MOVEM S2,ARG.DA(P3) ;SAVE IT IN THE MESSAGE
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
MOVE S2,.VLVID(S1) ;GET THE HOME BLOCK ID
MOVEM S2,ARG.DA+1(P3) ;SAVE IT IN THE MESSAGE
MOVEI P3,2(P3) ;POINT TO THE NEXT UNIT ENTRY
SKIPN S1,.VLNXT(S1) ;GET THE NEXT VOLUME NAME
JRST SNDB.3 ;NO MORE,,SEND THE MESSAGE OFF
;**;[1227] Change 1 line at SNDB.1+16L. /LWS
PUSHJ P,FNDVOL ;[1227] FIND IT IN OUR DATA BASE
JUMPE P2,SNDB.2 ;DOING 'DISMOUNT',,SKIP VOL LINK CODE
STORE P4,.VLPTR(S1),VL.PRV ;LINK THE NEXT TO THE LAST
STORE S1,.VLPTR(P4),VL.NXT ;LINK THE LAST TO THE NEXT
SNDB.2: MOVE P4,S1 ;MAKE THIS VOL THE CURRENT VOL BLOCK
JRST SNDB.1 ;AND GO PROCESS THE NEW VOLUME BLK
SNDB.3: POP P,S1 ;RESTORE OLD BLOCK ADDRESS
SUBI P3,0(S1) ;GET THE BLOCK LENGTH
MOVSS P3 ;MOVE RIGHT TO LEFT
ADDM P3,@G$SAB##+SAB.MS ;BUMP TOTAL MESSAGE LENGTH
ADDM P3,ARG.HD(S1) ;AND BUMP THE MSG BLOCK LENGTH
HRRZ S1,G$SAB##+SAB.MS ;GET MESSAGE ADDRESS
MOVX S2,.MTWLK ;GET WRITE-LOCKED FLAG
SKIPE WRTLCK ;WANT TO SET IT?
IORM S2,.OFLAG(S1) ;YES
MOVX S2,.DMOSN ;GET OVERRIDE-SET-NUMBER FLAG
SKIPE OSNFLG ;WANT TO SET IT?
IORM S2,.OFLAG(S1) ;YES
MOVX S1,PAGSIZ ;GET THE PAGE LENGTH
MOVEM S1,G$SAB##+SAB.LN ;SAVE IT
LOAD TF,.VLFLG(P1),VL.FRC ;[1217] GET 'FORCED' MOUNT BIT
SKIPE P2 ;[1217] ALWAYS SEND ON DISMOUNT
JUMPN TF,SNDB.4 ;[1217] DON'T BOTHER PULSAR IF 'FORCED'
PUSHJ P,SNDLBR ;SEND THE MSG OFF TO THE TAPE LABELER
$RETT ;AND RETURN
SNDB.4: MOVE S1,P1 ;[1217] GET PRIMARY VOL ADDRESS
SETZM S2 ;[1217] CLEAR S2
PUSHJ P,MNTA.0 ;[1217] TELL OPR IT'S MOUNTED
MOVX S1,VL.FRC ;[1217] GET 'FORCED' MOUNT BIT
ANDCAM S1,.VLFLG(P1) ;[1217] DON'T NEED IT ANYMORE
$RETT ;[1217] RETURN
>
SUBTTL ASLMSG - ROUTINE TO BUILD AN 'ADD STRUCTURE' MSG
; DSLMSG - ROUTINE TO BUILD A 'DELETE FROM SEARCH LIST' MSG
;CALL: S1/ The VSL Block Address
; S2/ The VOL Block Address
; AP/ The MDR adrs
;
;RET: TRUE ALWAYS
TOPS10< INTERN D$DSLM ;MAKE IT GLOBAL
ASLMSG: TDZA TF,TF ;NO FLAG BITS IF ENTRY IS HERE
D$DSLM: MOVX TF,ASL.RM+ASL.NRD+ASL.NQ;REMOVE STR + NO RECOMP + NO QTA CHECK
SKIPA ;SKIP NEXT ENTRY POINT
DSLMSG: MOVX TF,ASL.RM ;GET THE 'REMOVE STRUCTURE' FLAG BIT
PUSHJ P,.SAVE2 ;SAVE SOME ACS
DMOVE P1,S1 ;SAVE ARGS
MOVEM TF,TMPVSL+.OFLAG ;SAVE THE ACTION BITS
MOVE TF,[.OHDRS+ARG.DA+.BLDLN,,.QOASL] ;GET MSG LENGTH,,MSG TYPE
MOVEM TF,TMPVSL ;SAVE IT IN THE MESSAGE
SETZM TMPVSL+.MSFLG ;NO FLAG BITS
MOVEI TF,1 ;1 BLOCK
MOVEM TF,TMPVSL+.OARGC ; IN THE MESSAGE
MOVE TF,[.BLDLN+1,,.BLDSN] ;GET THE BLOCK LENGTH,,BLOCK TYPE
MOVEM TF,TMPVSL+.OHDRS+ARG.HD ;SAVE IT IN THE MESSAGE
MOVE TF,.VLNAM(S2) ;GET THE STRUCTURE NAME
MOVEM TF,TMPVSL+.OHDRS+ARG.DA+.BLDNM ;SAVE IT IN THE MESSAGE
MOVE TF,.VSRID(S1) ;GET THE USERS REQUEST ID
MOVEM TF,TMPVSL+.MSCOD ;SAVE IT AS THE ACK CODE
MOVE TF,.MRUSR(AP) ;GET THE USERS PPN
MOVEM TF,TMPVSL+.OHDRS+ARG.DA+.BLDOW ;SAVE IT IN THE MESSAGE
LOAD TF,.MRJOB(AP),MD.PJB ;GET THE USERS JOB NUMBER
IOR TF,TMPVSL+.OFLAG ;KEEP THE REMOVAL BIT
MOVE S1,.VSFLG(P1) ;GET THE USERS FLAG BITS FROM THE VSL
TXNE S1,VS.PAS ;WANT TO BE PASSIVE?
TXO TF,ASL.PS ;YES, SAY SO
TXNE S1,VS.NOC ;WANT NO-CREATE?
TXO TF,ASL.NC ;YES, SAY THAT
TXNE S1,VS.WLK ;WANT IT WRITE-LOCKED?
TXO TF,ASL.WL ;SAY THAT
TXNE S1,VS.SIN ;WANT SINGLE ACCESS
TXO TF,ASL.SA ;SAY SO
TXNE S1,VS.ARD ;WANT TO ALWAYS RECONPUTE DISK USAGE?
TXO TF,ASL.AR ;YES
MOVEM TF,TMPVSL+.OFLAG ;SAVE IT IN THE MESSAGE
MOVEI TF,TMPVSL ;GET THE MESSAGE ADDRESS
MOVEM TF,G$SAB##+SAB.MS ;SAVE IT IN THE SAB
LOAD TF,TMPVSL+.MSTYP,MS.CNT ;GET THE MESSAGE LENGTH
MOVEM TF,G$SAB##+SAB.LN ;SAVE IT IN THE SAB
DMOVE S1,P1 ;GET VSL AND VOL BLOCK ADDRESSES
PUSHJ P,AASSET ;SET VL.AAS IF NECESSARY
PUSHJ P,SNDLBR ;SEND THE MESSAGE OFF
$RETT ;RETURN
; Set or clear VL.AAS bit.
; Call: MOVE S1, VSL block address
; MOVE S2, VOL block address
; PUSHJ P,AASSET/ASSCLR
;
AASSET: TDZA TF,TF ;SETTING VL.AAS
AASCLR: MOVEI TF,1 ;CLEARING VL.AAS
PUSHJ P,.SAVE2 ;SAVE SOME ACS
DMOVE P1,S1 ;SAVE VOL BLOCK ADDRESS
LOAD S1,.VLOWN(P2),VL.CNT ;GET REQUESTOR COUNT
MOVNS S1 ;NEGATE IT
HRLI S1,.VLVSL(P2) ;POINT TO FIRST VSL
MOVSS S1 ;BUILD AN AOBJN POINTER
AASX.1: HRRZ S2,(S1) ;GET A VSL ADDRESS
CAME S2,P1 ;FOUND THE VSL?
AOBJN S1,AASX.1 ;LOOP FOR TILL WE FIND A MATCH
JUMPGE S1,.POPJ ;AOBJN POINTER RAN OUT?
MOVE S2,(S1) ;GET FLAGS,,ADDR
SKIPN TF ;ALWAYS CLEAR BIT?
TXNN S2,VL.ASN ;BUT IS IT ASSIGNED?
TXZA S2,VL.AAS ;NO
TXO S2,VL.AAS ;YES - THEN LITE ALREADY ASSIGNED
MOVEM S2,(S1) ;REPLACE FLAGS,,ADDR
POPJ P, ;RETURN
> ;END TOPS10 CONDITIONAL
SUBTTL SCNVOL - ROUTINE TO FIND COMMON VOLUMES REQUESTS AND LINK THEM
;CALL S1/ The Volume Name in Sixbit
; S2/ The VSL Address
;
;RET: S1/ The VOL Address
TOPS10 <
SCNVOL: PUSHJ P,.SAVE4 ;SAVE THE P AC'S FOR A MINUTE
STKVAR <LENGTH> ;ALLOCATE SOME STORAGE FOR ENTRY LENGTH
DMOVE P1,S1 ;SAVE THE VOLUME NAME AND VSL ADDRESS
LOAD P3,.VSFLG(P2),VS.TYP ;GET THE VOLUME TYPE
MOVX TF,FALSE ;MAKE FLAG AC FALSE
CAIE P3,%UNKN ;VOLUME UNKNOWN?
CAIN P3,%DISK ;OR A DISK?
PUSHJ P,FNDISK ;LOOK FOR A DISK
JUMPT SCNV.1 ;CONTINUE IF FOUND
CAIE P3,%UNKN ;VOLUME UNKNOWN?
CAIN P3,%TAPE ;OR A MAGTAPE?
PUSHJ P,FNTAPX ;LOOK FOR A MAGTAPE
JUMPT SCNV.1 ;CONTINUE IF FOUND
CAIE P3,%UNKN ;VOLUME UNKNOWN?
CAIN P3,%DTAP ;OR A DECTAPE?
PUSHJ P,FNDECT ;LOOK FOR A DECTAPE
JUMPT SCNV.1 ;CONTINUE IF FOUND
$RETF ;ELSE GIVE UP
SCNV.1: STORE P3,.VSFLG(P2),VS.TYP ;UPDATE INCASE CHANGED
MOVE P1,S1 ;SAVE THE VOL BLOCK ADDRESS
MOVE S1,VOLQUE ;GET THE VOLUME QUEUE ID
PUSHJ P,L%SIZE ;GET THIS ENTRY'S LENGTH
MOVEM S2,LENGTH ;SAVE THE ENTRY LENGTH FOR LATER
SUBI S2,VOLLEN-1 ;GET THE TOTAL .VLVSL BLOCK LENGTH
LOAD S1,.VLOWN(P1),VL.CNT ;GET THE TOTAL ALLOCATED LENGTH
CAIN S1,0(S2) ;ARE THEY EQUAL ???
JRST SCNV.3 ;YES,,WE NEED MORE ROOM !!!
CAIL S1,0(S2) ;IS ALLOCATED MORE THEN TOTAL ???
STOPCD (AMT,HALT,,<Allocated is more then total (vol .VLVSL blocks)>)
ADDI S1,.VLVSL(P1) ;GET THE NEXT BLOCK ADDRESS
MOVEM P2,0(S1) ;LINK THE VSL TO THE VOL
INCR .VLOWN(P1),VL.CNT ;BUMP THE REQUEST COUNT BY 1
MOVE S1,P1 ;GET THE VOL ADDRESS IN S1
$RETT ;AND RETURN
SCNV.3: AOS S2,LENGTH ;GET LENGTH+1 IN S2
MOVE S1,VOLQUE ;GET THE VOLUME QUEUE ID
PUSHJ P,L%CENT ;CREATE A NEW VOL ENTRY
HRL TF,P1 ;GET THE OLD VOL ADDRESS
HRR TF,S2 ;GET THE NEW VOL ADDRESS
MOVE S1,LENGTH ;GET THE ENTRY LENGTH
ADDI S1,-2(S2) ;GET VOL ENTRY END ADDRESS -1
BLT TF,0(S1) ;COPY OLD VOL TO NEW VOL
LOAD S1,.VLOWN(S2),VL.CNT ;GET THE REQUEST COUNT
ADDI S1,.VLVSL(S2) ;POINT TO VOL VSL ADDRESS
MOVEM P2,0(S1) ;LINK THE VOL TO THE VSL
MOVE P2,S2 ;GET THE NEW VOL ADDRESS IN P2
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
MOVE S1,VOLQUE ;GET THE VOLUME QUEUE ID
MOVE S2,P1 ;GET THE OLD VOL ADDRESS IN S2
PUSHJ P,L%APOS ;POSITION TO THE OLD ENTRY
PUSHJ P,L%DENT ;DELETE THE OLD ENTRY
;IF A MULTIPLE VOL STRS LINK LIST EXISTS THREAD NEW VOL ENTRY INTO
;EXISTING FORWARD AND BACKWARDS LINKED LIST.
LOAD S1,.VLPTR(P2),VL.NXT ;GET THE SECONDARY VOL BLOCK ADDRESS
SKIPE S1 ;NONE THERE,,SKIP
STORE P2,.VLPTR(S1),VL.PRV ;FOUND,,SAVE NEW VOL BLK ADDR AS PRIMARY
LOAD S1,.VLPTR(P2),VL.PRV ;CONNECT BACKWARDS VOL LINK
SKIPE S1 ;NONE THERE,,SKIP
XYZZY: STORE P2,.VLPTR(S1),VL.NXT ;OF PREVIOUS VOL BLK
;Now that we have deleted the old VOL entry and created a new one,
; we must go back through this volumes VSL chain and
; fixup the VSL's VOL pointer so that it now points to the new VOL
; entry instead of the old one.
LOAD P3,.VLOWN(P2),VL.CNT ;GET THE VSL COUNT FOR THIS VOL ENTRY
MOVEI S1,.VLVSL(P2) ;POINT S1 TO THE VSL ADDRESS LIST
SCNV.4: MOVE S2,0(S1) ;PICK UP A VSL ADDRESS IN S2
LOAD P4,.VSCVL(S2),VS.CNT ;GET THE VOL COUNT FOR THIS VSL IN P4
MOVEI S2,.VSVOL(S2) ;POINT TO THIS VSL'S VOL LIST
SCNV.5: CAMN P1,0(S2) ;WE ARE LOOKING FOR THE OLD VOL PTR
JRST SCNV.6 ;FOUND IT,,CONTINUE ON
AOS S2 ;POINT TO NEXT VOL POINTER
SOJG P4,SCNV.5 ;CONTINUE TILL FOUND
STOPCD (VPF,HALT,,<Volume pointer not found>) ;NOT THERE,,DEEEEP TROUBLE !!
SCNV.6: MOVEM P2,0(S2) ;LINK VSL TO NEW VOL ENTRY
AOS S1 ;POINT TO NEXT VSL ADDRESS
SOJG P3,SCNV.4 ;CONTINUE THROUGH ALL VSL'S
INCR .VLOWN(P2),VL.CNT ;BUMP THE REQUEST COUNT BY 1 (FOR CURRENT)
SKIPE S1,.VLUCB(P2) ;CHECK AND LOAD THE UCB ADDRESS
MOVEM P2,.UCBVL(S1) ;FOUND IT,,RELINK IT TO THIS VOL ENTRY
MOVE S1,P2 ;RETURN THE VOL POINTER IN S1
$RETT ;AND RETURN
>
TOPS20 <
SCNVOL: $RETF ;RETURNS FALSE ON THE -20
>
SUBTTL UPDSVL - UPDATE THE STARTING VOLUME FOR A VOLUME SET
;CALL: S1/ The Sixbit Volume name or the Volume number
;
;RET: True Always
UPDSVL: TLNE S1,770000 ;IS IT A SIXBIT ID ???
JRST UPDS.2 ;YES,,GO PROCESS IT
CAMLE S1,VOLNBR ;MUST BE LESS OR EQUAL TO VOLUME COUNT
$RETF ;NO,,OFFSET TOO GREAT - THATS AN ERROR
SUBI S1,1 ;MAKE THE COUNT AN OFFSET
STORE S1,.VSCVL(P2),VS.OFF ;AND SET IT IN VSL
$RETT ;RETURN
UPDS.2: LOAD T1,.VSCVL(P2),VS.CNT ;GET THE VOLUME COUNT
MOVNS T1 ;MAKE IT NEGATIVE
HRLZS T1 ;MOVE RIGHT TO LEFT
HRRI T1,.VSVOL(P2) ;POINT TO THE VOLUME LIST
SETZM T2 ;START OFFSET OUT AT 0
UPDS.3: MOVE S2,0(T1) ;GET A VOLUME POINTER
CAMN S1,0(S2) ;DO WE MATCH - VOLUME FOR VOLUME ???
JRST [STORE T2,.VSCVL(P2),VS.OFF ;YES,,SAVE THE VOLUME OFFSET
$RETT ] ;AND RETURN
AOS T2 ;BUMP OFFSET COUNT
AOBJN T1,UPDS.3 ;CONTINUE THROUGH ALL VOLUMES
$RETF ;NOT FOUND,,TOUGH BREAKEEEE
SUBTTL D$INID - Initialization done for tape handler
;This code is executed when the tape labeler send a message saying
; 'done with label initialization' for a particular drive
; This routine clear the UC.INI bit, and arranges to have the labels
; of the drive just freed up read.
TOPS10<
D$INID::PUSHJ P,.SAVET ;[1164] SAVE T1-T4
MOVX S1,.ORREQ ;[1164] GET BLOCK TYPE TO LOOK FOR
PUSHJ P,A$FNDB## ;[1164] FIND IT
SKIPF ;[1164] OLD PULSAR PERHAPS?
SKIPA T1,(S1) ;[1164] GET REQUEST ID
MOVEI T1,0 ;[1164] ASSUME NO REQUEST-ID
MOVX S1,.RECDV ;GET THE BLOCK TYPE TO LOOK FOR
PUSHJ P,A$FNDB## ;FIND IT
JUMPF MISC.3 ;CAN'T, SO COMPLAIN
MOVE S1,.RECDN(S1) ;GET THE SIXBIT DRIVE NAME
PUSHJ P,UCBFND ;GET THE DRIVE DATA BLOCK
JUMPF MISC.3 ;CAN'T SO COMPLAIN ABOUT THAT
MOVE T2,S1 ;[1164] SAVE UCB ADDRESS
MOVE S2,.UCBST(S1) ;GET THE STATUS BITS
TXZN S2,UC.INI ;DID WE THINK IT WAS INITING?
$RETT ;NO, FORGET THE JUNK MAIL
MOVEM S2,.UCBST(S1) ;SAVE BITS WITHOUT UC.INI
JUMPN T1,DIND.1 ;[1164] IF REQ ID THERE, IT'S REINIT
$WTO (<Volume initialization complete>,<Drive is available for use>,MDAOBJ,$WTFLG(WT.SJI))
MOVE S1,.UCBNM(S1) ;GET SIXBIT DRIVE NAME
PJRST SNDREC ;READ THE (NEW) LABELS
;[1164] Here when reinitialization complete (/NEW-VOLUME).
;[1164] T1 = Request-id, T2 = UCB address
DIND.1: HRRZ S1,T1 ;[1164] GET RID WITHOUT POSSIBLE ERROR BIT
PUSHJ P,FNDVSL ;[1164] GO FIND THIS GUY'S VSL
JUMPF .RETT ;[1164] COULD HAVE BEEN CANCELLED
MOVE T3,S1 ;[1164] SAVE VSL ADDR
MOVE S1,.VSVOL(T3) ;[1164] GET VOL BLOCK ADDR FOR 1ST VOL
SKIPE .VLUCB(S1) ;[1164] BARF IF VOL NOT MOUNTED
CAME T2,.VLUCB(S1) ;[1164] OR WRONG UCB
STOPCD (MWL,HALT,,<Missing or wrong VOL/UCB link>) ;[1164] PLEASE,,NO!!
MOVX S1,VS.INI ;[1164] GET REINIT-IN-PROGRESS BIT
TDNN S1,.VSFLG(T3) ;[1164] WAS IT LIT IN VSL?
STOPCD (NVC,HALT,,<NEW-VOLUME code not working>) ;[1164] @$##@#!!
ANDCAM S1,.VSFLG(T3) ;[1164] CLEAR BIT IN VSL FLAG WORD
MOVE S1,T3 ;[1164] GET VSL ADDRESS
PUSHJ P,SETAWT ;[1164] SET STATUS TO 'WAITING'
LOAD S1,.MSFLG(M),AK.NAK ;[1164] GET NACK BIT
JUMPN S1,DIND.2 ;[1164] JUMP IF PULSAR IS UPSET
DMOVE S1,T2 ;[1164] GET S1 = UCB ADDR, S2 = VSL ADDR
PUSHJ P,REASSI ;[1164] REASSIGN DRIVE TO USER!
JUMPF .RETT ;[1164] RETURN IF REASSIGN FAILS
MOVE S1,T3 ;[1164] GET VSL ADDR
PJRST ACKUSR ;[1164] TELL USER GOOD NEWS
;[1164] Here when operator said ABORT to PULSAR's WTOR to mount a tape
DIND.2: $SAVE <P4> ;[1164] SAVE P4
MOVEI P4,[ASCIZ\Operator aborted WTOR sent by tape labeler\] ;[1164]
MOVE S1,.VSVOL(T3) ;[1164] GET ADDRESS OF 1ST VOL BLOCK
PUSHJ P,VLBREA ;[1164] BREAK THE VOL/UCB LINK
MOVE S1,T3 ;[1164] GET VSL ADDR
PJRST DELREQ ;[1164] GO DELETE REQUEST
;[1164] Set vol status to 'waiting' after reinit is done.
;
; Call: S1 = VSL address
SETAWT: LOAD S2,.VSCVL(S1),VS.CNT ;[1164] GET NUMBER OF VOLS IN THE VSN
MOVNS S2 ;[1164] NEGATE IT
HRLI S2,.VSVOL(S1) ;[1164] GET ADDRESS OF FIRST VOL PTR
MOVSS S2 ;[1164] MAKE AN AOBJN POINTER
MOVEI TF,%STAWT ;[1164] STATUS CODE FOR 'WAITING'
SETA.1: MOVE S1,(S2) ;[1164] GET A VOL BLOCK ADDR
STORE TF,.VLFLG(S1),VL.STA ;[1164] RESET STATUS TO WAITING
AOBJN S2,SETA.1 ;[1164] LOOP THROUGH ALL VOL BLOCKS
$RETT ;[1164] RETURN
;These bits are defined so that flags can be traced from the point
; of lighting to the point of testing among various calls/levels
;Flag used to signify that a user's request has other volumes
; (already) mounted
AF.OVL==1B0
;Flag used to signify that during resource removal, there are no
; other users of a 'high level' shared resource
RF.RSN==RHMASK ;FIELD WHICH HOLDS THE RESOURCE #
RF.OTU==1B0 ;OTHER USERS OF A SHARED DISK DRIVE
> ;END TOPS10 CONDITIONAL
SUBTTL D$ALOC - ROUTINE TO PERFORM DEVICE ALLOCATION
;CALL: S1/ The VSL Address
; AP/ The MDR Address
;
;RET: True if Allocation Wins, False Otherwise
;
; If False is returned then...
;
; S1/ 0 if failed because deadlock detected
; S1/ -1 if failed because allocation deferred
TOPS10<
D$ALOC::PUSHJ P,.SAVE4 ;SAVE P1 - P4
PUSHJ P,.SAVET ;SAVE T1 - T4
LOAD P1,.VSLNK(S1),VS.LNK ;GET THE REQUEST LINK CODE
LOAD P2,.MRCNT(AP),MR.CNT ;GET THE VSL REQUEST COUNT
MOVNS P2 ;NEGATE THE COUNT
MOVSS P2 ;MOVE RIGHT TO LEFT
HRRI P2,.MRVSL(AP) ;CREATE VSL SEARCH AOBJN AC
$SAVE <M> ;PRESERVE WHATEVER IS IN M
PUSHJ P,SETSTK ;SETUP THE VSL, RSN STACK
ALOC.1: MOVE P3,0(P2) ;GET A VSL ADDRESS
LOAD S1,.VSLNK(P3),VS.LNK ;GET ITS LINK CODE
CAME P1,S1 ;DO WE WANT THIS VSL ???
JRST ALOC.2 ;NO,,SKIP IT
LOAD S1,.VSFLG(P3),VS.WAL ;IS THIS VSL AWATING ALLOCATION ???
JUMPE S1,ALOC.2 ;NO,,THEN SKIP IT
MOVE S1,P3 ;COPY VSL POINTER
PUSHJ P,VSLRSX ;GET ALL THE RSNS ONTO THE M STACK
JUMPF [SETOM S1 ;CAN'T, SO RETURN -1
$RETF ] ;MEANING DEFERRED ALLOCATION
ALOC.2: AOBJN P2,ALOC.1 ;CHECK ALL VSL'S
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
;Here to find the users 'B' matrix entry, and create one if not there
ALOC.3: PUSHJ P,D$BMTX ;FIND THE USERS ENTRY IN THE 'B' MATRIX
JUMPT ALOC.4 ;FOUND IT,,CONTINUE
MOVE S1,BMATRX ;GET THE 'B' MATRIX ID
PUSHJ P,L%LAST ;POSITION TO THE END OF THE 'B' MATRIX
MOVE S1,BMATRX ;GET THE 'B' MATRIX ID
MOVX S2,SMALEN ;GET THE 'B' MATRIX LENGTH
PUSHJ P,L%CENT ;CREATE AN ENTRY FOR THE USER
MOVE BM,S2 ;SAVE THE ENTRY ADDRESS
MOVE S1,CMATRX ;GET THE 'C' MATRIX ID
PUSHJ P,L%LAST ;POSITION TO THE END OF THE 'C' MATRIX
MOVE S1,CMATRX ;GET THE 'C' MATRIX ID
MOVX S2,SMALEN ;GET THE 'C' MATRIX LENGTH
PUSHJ P,L%CENT ;CREATE AN ENTRY FOR THE USER
MOVE CM,S2 ;SAVE THE ENTRY ADDRESS
LOAD S1,.MRJOB(AP),MR.JOB ;GET THE USERS JOB NUMBER
MOVEM S1,.SMJOB(BM) ;SAVE IT IN THE 'B' MATRIX ENTRY
MOVEM S1,.SMJOB(CM) ;SAVE IT IN THE 'C' MATRIX ENTRY
MOVEI S1,1 ;GET MAX RSN OFFSET OF 1
STORE S1,.SMFLG(BM),SM.CNT ;SET IT
STORE S1,.SMFLG(CM),SM.CNT ;HERE ALSO
AOS PROCNT ;BUMP THE PRECESS COUNT BY 1
;Here to create a secondary 'B' Matrix entry for the user which
;will be used in the deadlock avoidance check. The origional is ignored
;until the return from the deadlock routine. If the routine returns
;true, the origional is deleted, if false the secondary is deleted.
ALOC.4: MOVE S1,BMATRX ;GET THE 'B' MATRIX ID
PUSHJ P,L%RENT ;REMEMBER THE ORIGIONAL ENTRY
PUSHJ P,L%SIZE ;GET ITS LENGTH
MOVE P3,S2 ;SAVE IT FOR A SECOND
PUSHJ P,L%CENT ;CREATE A NEW ENTRY
MOVE P2,S2 ;SAVE ITS ADDRESS FOR A SECOND
ADDI P3,0(S2) ;CALC ENTRY END ADDRESS
HRL S2,BM ;GET SOURCE,,DESTINATION FOR BLT
BLT S2,-1(P3) ;COPY OLD ENTRY TO NEW ENTRY
MOVX S1,SM.IGN ;GET THE 'IGNORE' BIT
IORM S1,.SMFLG(BM) ;LITE IT FOR THE OLD ENTRY
MOVE BM,P2 ;POINT TO NEW ENTRY
ALO.4A: MOVE T4,[IOWD MSGLN##,G$MSG] ;GET A QUEUE FOR VSL ADDRESSES
PUSH T4,[-1] ;SET END OF QUEUE INDICATOR
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
;Here to perform the actual device allocation ('B' Matrix Update)
ALOC.5: POP M,S1 ;GET A RSN OFF THE Q
POP M,P2 ;GET THE VSL ADDRESS OFF THE QUEUE
CAMN P2,[-1] ;ARE WE DONE ???
JRST ALOC.8 ;YES,,GO FINISH UP
PUSH T4,P2 ;QUEUE UP THE VSL ADDRESS
LOAD S1,S1,RF.RSN ;EXTRACT JUST THE RSN
MOVE S2,P2 ;LOAD UP THE VSL ADDRESS
PUSHJ P,ADDBMA ;YES,,UPDATE THE RESOURCE COUNT
JRST ALOC.5 ; AND GO PROCESS THE NEXT VSL
;Here to perform Deadlock Avoidance Check
ALOC.8: PUSHJ P,DEADLK ;CALL DEADLOCK AVOIDANCE CHECK
JUMPT ALOC.A ;WIN,,CONTINUE ON !!!
;Here if Deadlock check fails, delete all current VSL's
ALOC.9: POP T4,S1 ;GET A VSL ADDRESS
MOVE T3,S1 ;[1173] SAVE VSL ADDRESS
PUSHJ P,SHUFFL ;SHUFFEL THIS GUYS ALLOCATION AROUND
JUMPT ALOC.A ;WIN,,IT SURE IS HARD BEING NICE !!!
MOVE S1,BMATRX ;GET THE 'B' MATRIX ID
MOVE S2,BM ;GET THE USERS CURRENT MATRIX ENTRY
PUSHJ P,L%APOS ;POSITION TO IT
PUSHJ P,L%DENT ;DELETE IT
MOVE S1,BMATRX ;GET THE 'B' MATRIX ID
PUSHJ P,L%PREM ;POSITION TO THE OLD ENTRY
ZERO .SMFLG(S2),SM.IGN ;CLEAR THE 'IGNORE' BIT
$TEXT(<-1,,G$MSG>,<Volume set allocation failed - insufficient resources available^M^J^0>)
SETOM ERRACK ;THIS IS AN ERROR ACK
MOVE S1,T3 ;[1173] GET VSL ADDRESS BACK
SETZM S2 ;[1173] USE VSL ACK DATA
PUSHJ P,USRNOT ;TELL THE USER
SETZM S1 ;RETURN ALLOCATION FAILED ERROR CODE
$RETF ;RETURN NO GOOD !!!
;Here if the Deadlock Check Wins
ALOC.A: MOVE S1,BMATRX ;GET THE 'B' MATRIX ID
PUSHJ P,L%PREM ;GET THE OLD USER ENTRY
PUSHJ P,L%DENT ;DELETE IT
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
;Here to clear 'Waiting for Allocation' bits in the VSL's
ALOC.B: POP T4,S1 ;GET THE VSL ADDRESS OFF THE QUEUE
CAMN S1,[-1] ;END OF THE QUEUE ???
JRST ALO.B0 ;YES,,FINISH UP !!!
ZERO .VSFLG(S1),VS.WAL ;NO,,CLEAR THIS VSL'S WAITING BIT
JRST ALOC.B ;AND GO GET ANOTHER
ALO.B0: LOAD S1,.MRJOB(AP),MR.JOB ;GET THE USERS JOB NUMBER
TXNN S1,BA%JOB ;IS IT AN INTERNAL REQUEST ???
PJRST USRACK ;NO,,RETURN ACKING THE USER
INCR .MRCNT(AP),MR.LNK ;YES,,GEN A NEW LINK CODE
LOAD P2,.MRCNT(AP),MR.LNK ;AND LOAD IT
LOAD P1,.MRCNT(AP),MR.CNT ;GET THE REQUEST NUMBER
MOVNS P1 ;NEGATE IT
MOVSS P1 ;MOVE RIGHT TO LEFT
HRRI P1,.MRVSL(AP) ;CREATE VSL SEARCH AOBJN AC
ALO.B1: MOVE S1,0(P1) ;GET A VSL ADDRESS
LOAD S2,.VSFLG(S1),VS.ALC ;JUST ALLOCATING ???
SKIPN S2 ;YES,,SKIP THIS
STORE P2,.VSLNK(S1),VS.LNK ;NO,,LINK THIS VSL TO ALL OTHER MOUNTS
AOBJN P1,ALO.B1 ;LOOK AT ALL VSL'S
$RETT ;AND RETURN
> ;END TOPS10 CONDITIONAL
SUBTTL D$BMTX - ROUTINE TO FIND A USERS ENTRY IN THE 'B' MATRIX
; D$CMTX - "" "" "" " "" "" "" "" 'C' ""
;CALL: AP/ The Users MDR Address
;
;RET: BM/ The 'B' Matrix Entry Address if using D$BMTX entry point
; CM/ The 'C' Matrix Entry Address if using D$CMTX entry point
TOPS10<
D$BMTX::SKIPA S1,BMATRX ;SKIP AND LOAD THE 'B' MATRIX ID
D$CMTX::MOVE S1,CMATRX ;LOAD THE 'C' MATRIX ID
PUSHJ P,.SAVE2 ;SAVE P1 & P2 FOR A SECOND
LOAD P1,.MRJOB(AP),MR.JOB ;GET THE USERS JOB NUMBER
MOVX P2,SM.IGN ;GET 'IGNORE ENTRY' FLAG BIT
PUSHJ P,L%FIRST ;GET THE FIRST ENTRY
SKIPA ;SKIP THE FIRST TIME THROUGH
BMTX.1: PUSHJ P,L%NEXT ;GET THE NEXT ENTRY
JUMPF .RETF ;NOT THERE,,RETURN NOT FOUND
CAMN P1,.SMJOB(S2) ;IS THIS THE ONE WE WANT ???
TDNE P2,.SMFLG(S2) ;YES, 'IGNORE THIS ONE' ???
JRST BMTX.1 ;NOT OURS OR IGNORED,,TRY NEXT
CAMN S1,BMATRX ;WAS THIS A 'B' MATRIX SEARCH ???
MOVE BM,S2 ;YES,,GET THE ENTRY ADDRESS IN BM
CAMN S1,CMATRX ;WAS THIS A 'C' MATRIX SEARCH ???
MOVE CM,S2 ;YES,,GET THE ENTRY ADDRESS IN CM
$RETT ;AND RETURN
> ;END TOPS10 CONDITIONAL
SUBTTL Deadlock Avoidance -- DEADLK - Interface routine
;CALL: AMATRX/ The 'A' Matrix Address
; BMATRX/ The 'B' Matrix Link List ID
; CMATRX/ The 'C' Matrix Link List ID
;
;RET: True Or False depending on the Deadlock Avoidance check
TOPS10 <
D$DLOK:: ;MAKE IT GLOBAL
DEADLK: SKIPN G$DEAD## ;DEADLOCK AVOIDANCE CHECKING ENABLED ??
$RETT ;NO,,ALWAYS WIN !!!
$COUNT (DEAD) ;COUNT NUMBER OF DEADLOCK CHECKS
PUSHJ P,D$DEAD ;PERFORM DEADLOCK AVOIDANCE
$RETIT ;RETURN IF OK
$COUNT (DFAL) ;COUNT UP THE DEADLOCK FAILURES
$RET ;PASS FAILURE ON BACK
SUBTTL Deadlock Avoidance -- D$DEAD - Check for a deadlock
;Check the proposed allocations state to see whether or not it is safe.
;The basis for this algorithm is discussed in:
;
; Habermann, A. N. "Prevention of System Deadlocks."
; _Communications_of_the_ACM_, 12, No. 7 (July 1969), 373-385.
;
; Krakowiak, Sacha. _Principles_of_Operating_Systems_.
; Trans. David Beeson. Cambridge: The MIT Press, 1988.
;
; Call: AMATRX/ Address of 'A' (resource) matrix
; BMATRX/ 'B' matrix list name
; CMATRX/ 'C' matrix list name
; PROCNT/ Process count (length of 'B' and 'C' matrices)
;
; Return: TRUE Proposed state is safe
; FALSE Proposed state presents a deadlock
D$DEAD::SKIPG S1,PROCNT ;ANY PROCESSES?
$RETT ;NO, CANNOT BE DEADLOCKED
$SAVE <T3,T4> ;QSRMDA DOESN'T SAVE THESE (!)
MOVE S2,AMATRX ;GET ADDRESS OF HEADER BLOCK
LOAD S2,.AMHDR(S2),AM.CNT ;GET NUMBER OF RESOURCES
JUMPE S2,.RETT ;NONE: WILL NEVER HAPPEN
MOVEM S2,ASIZE ;
ADD S1,S2 ;ALLOCATE SPACE FOR SIX ARRAYS
IMULI S1,3 ; (3*ASIZE + 3*PROCNT)
PUSHJ P,M%GMEM ;ALLOCATE CLEARED MEMORY
MOVEM S2,BHEAD ;ADDRESS OF 'B' MATRIX SM BLOCKS
ADD S2,PROCNT ;
MOVEM S2,CHEAD ;ADDRESS OF 'C' MATRIX SM BLOCKS
ADD S2,PROCNT ;
MOVEM S2,BFLAG ;ADDRESS OF PROCESS FLAGS
ADD S2,PROCNT ;
MOVEM S2,BRESN ;ADDRESS OF 'B' MATRIX RESOURCE COUNTS
ADD S2,ASIZE ;
MOVEM S2,CRESN ;ADDRESS OF 'C' MATRIX RESOURCE COUNTS
ADD S2,ASIZE ;
MOVEM S2,ATEMP ;ADDRESS OF 'A' MATRIX SCRATCH ARRAY
PUSH P,S1 ;SAVE NUMBER OF WORDS OBTAINED
PUSHJ P,DEAD00 ;DO THE REAL WORK
EXCH S1,(P) ;RESTORE NUMBER OF WORDS
MOVE S2,BHEAD ;RESTORE ADDRESS OF FIRST WORD
PUSHJ P,M%RMEM ;RETURN ALLOCATED MEMORY
POP P,TF ;RESTORE RESULT (SAFE/UNSAFE)
POPJ P, ;
;This routine performs the actual deadlock avoidance algorithm.
DEAD00: PUSHJ P,.SAVE2 ;SAVE P1-P2
;For efficiency, create a vector of addresses for the columns.
;Initialize the .AMDLK field of the 'A' matrix, where the computations
;are done. (No other fields are disturbed.)
MOVE S1,BMATRX ;GET LIST NAME FOR 'B' MATRIX
MOVE S2,BHEAD ;GET ADDRESS OF ARRAY
PUSHJ P,GTHEAD ;BUILD ARRAY OF ADDRESSES
MOVE S1,CMATRX ;GET LIST NAME FOR 'C' MATRIX
MOVE S2,CHEAD ;GET ADDRESS OF ARRAY
PUSHJ P,GTHEAD ;BUILD ARRAY OF ADDRESSES
MOVE T1,AMATRX ;GET ADDRESS OF HEADER BLOCK
MOVE T2,ASIZE ;GET NUMBER OF RESOURCES
DEAD11: ADDI T1,AMALEN ;GET ADDRESS OF NEXT AM BLOCK
LOAD S1,.AMCNT(T1),AM.AVA ;GET NUMBER OF UNITS AVAILABLE
MOVEM S1,.AMDLK(T1) ;
SOJG T2,DEAD11 ;COPY ALL COUNTS
;Now that all the preliminaries are out of the way, do the work.
SETZ P1, ;INITIALIZE SEQUENCE NUMBER
DEAD21: PUSHJ P,GTNEXT ;GET NEXT CANDIDATE
$RETIF ;ALL DONE: (RESULT IN S1)
MOVEM S1,P2 ;SAVE PROCESS NUMBER
ADD S1,BHEAD ;GET ADDRESS OF SM BLOCK
MOVE S1,(S1) ;
MOVE S2,BRESN ;GET ADDRESS OF ARRAY TO FILL
PUSHJ P,GTCOLM ;FILL IN 'B' MATRIX COUNTS
MOVE S1,P2 ;GET PROCESS NUMBER
ADD S1,CHEAD ;GET ADDRESS OF SM BLOCK
MOVE S1,(S1) ;
MOVE S2,CRESN ;GET ADDRESS OF ARRAY TO FILL
PUSHJ P,GTCOLM ;FILL IN 'C' MATRIX COUNTS
MOVE S1,P2 ;GET PROCESS NUMBER
PUSHJ P,IFPLAY ;SEE IF THIS PROCESS IS PLAYABLE
JUMPF DEAD22 ;NOT PLAYABLE: SET "TRIED" BIT
MOVE S1,P2 ;GET PROCESS NUMBER
PUSHJ P,DOPLAY ;PLAY THIS PROCESS
PUSHJ P,CLTRY ;CLEAR ALL TRIED BITS
AOS S1,P1 ;INCREMENT SEQUENCE NUMBER
TXO S1,SM.PLY ;MARK PROCESS "PLAYED"
TRNA ;
DEAD22: MOVX S1,SM.DLK ;MARK PROCESS "TRIED"
ADD P2,BFLAG ;GET ADDRESS OF FLAG WORD
MOVEM S1,(P2) ;MARK PROCESS
JRST DEAD21 ;LOOK FOR ANOTHER PROCESS
SUBTTL Deadlock Avoidance -- IFPLAY - See if process is playable
;See if a given process is playable.
;
;A process is playable if there are sufficient resources in the 'A'
;matrix to cover the outstanding allocation (difference between
;allocated and owned) for all resources the process is requesting.
;
;Before performing the sufficiency check, see if the process is
;requesting sharable resources currently owned by some other process.
;If so, then the requisite low-level resources are removed from the
;outstanding allocation for this process.
;
; Call: S1/ Process number (zero to PROCNT minus one)
; BHEAD/ Address of array of column headers
; CHEAD/ Address of array of column headers
; BRESN/ Address of array of resource counts for process
; CRESN/ Address of array of resource counts for process
; ATEMP/ Address of 'A' matrix scratch array
; ASIZE/ Number of resources (length of 'A' matrix)
; AMATRX/ Address of A (resource) matrix
; PROCNT/ Process count (length of 'B' and 'C' matrices)
;
; Return: TRUE Given process could play in this state.
; FALSE There are insufficient resources for it to play.
IFPLAY: PUSHJ P,.SAVE4 ;SAVE P1-P4
MOVEM S1,P4 ;SAVE PROCESS NUMBER
SKIPG P3,ASIZE ;GET MAXIMUM NUMBER OF RESOURCES
JRST .RETT ;ZERO: WILL NEVER HAPPEN
MOVN P3,P3 ;BUILD AN AOBJN POINTER
HRLZ P3,P3 ;
;Calculate the number of each resource that the process will need and
;store the result in the scratch vector.
;While doing this calculation, check for any high-level resources that
;need to be mapped into low-level resources.
;If the process needs any resources that aren't required by a
;high-level-to-low-level mapping and if there aren't enough, quit.
SETZ T1, ;INITIALIZE SHARED RESOURCE FLAG
MOVE P1,P3 ;COPY 'A' MATRIX AOBJN POINTER
MOVE P2,AMATRX ;GET ADDRESS OF 'A' MATRIX HEADER
IFPLA1: ADDI P2,AMALEN ;POINT TO NEXT 'A' MATRIX ENTRY
MOVE S1,BRESN ;POINT TO 'B' MATRIX ENTRY
ADDI S1,(P1) ;
MOVE S1,(S1) ;GET 'B' MATRIX RESOURCE COUNT
MOVE S2,CRESN ;POINT TO 'C' MATRIX ENTRY
ADDI S2,(P1) ;
SUB S1,(S2) ;CALCULATE THE NUMBER NEEDED
SKIPGE S1 ;OWNS MORE THAN ALLOCATED?
STOPCD (OMA,HALT,,<Process owns more resources than it has allocated>)
MOVE S2,ATEMP ;POINT TO TEMPORARY ARRAY
ADDI S2,(P1) ;
MOVEM S1,(S2) ;SAVE THIS VALUE
JUMPE S1,IFPLA2 ;ZERO: SIMPLE CASE
LOAD S2,.AMSTA(P2),AM.DVT ;GET DEVICE TYPE
CAIN S2,%HLR1 ;IS IT A HIGH-LEVEL RESOURCE?
AOJA T1,IFPLA2 ;YES, REMEMBER IT
CAIE S2,%LLR1 ;IS IT A LOW-LEVEL RESOURCE?
JRST IFPLA2 ;NO, SKIP THIS NEXT TEST
CAMLE S1,.AMDLK(P2) ;ASKING FOR TOO MUCH?
$RETF ;YES, NOT ENOUGH RESOURCES
IFPLA2: AOBJN P1,IFPLA1 ;CALCULATE FOR ALL RESOURCES
;If the process requires any non-permanent high-level resources that are
;in use by some yet-to-be-played process, then reduce this process'
;requirement of mapped low-level resources for each such sharable
;resource.
JUMPE T1,IFPLA5 ;NO SHARED HIGH-LEVEL RESOURCES
MOVE P1,P3 ;COPY 'A' MATRIX AOBJN POINTER
MOVE P2,AMATRX ;GET ADDRESS OF 'A' MATRIX HEADER
IFPLA3: ADDI P2,AMALEN ;POINT TO NEXT 'A' MATRIX ENTRY
MOVE S1,ATEMP ;POINT TO TEMPORARY ARRAY
ADDI S1,(P1) ;
SKIPG (S1) ;ANY OF THIS RESOURCE NEEDED?
JRST IFPLA4 ;NO, TRY NEXT RESOURCE
LOAD S1,.AMSTA(P2),AM.DVT ;GET DEVICE TYPE
CAIE S1,%HLR1 ;IS IT A HIGH-LEVEL RESOURCE?
JRST IFPLA4 ;NO, TRY NEXT RESOURCE
MOVX S1,AM.PRR ;GET A BIT TO TEST WITH
TDNE S1,.AMNAM(P2) ;IS THIS A PERMANENT RESOURCE?
JRST IFPLA4 ;YES, TRY NEXT RESOURCE
MOVE S1,P4 ;COPY PROCESS NUMBER MINUS ONE
HRRZ S2,P1 ;COPY RESOURCE NUMBER MINUS ONE
PUSHJ P,IFOTHR ;OTHER PROCESSES NEED IT?
JUMPF IFPLA4 ;NO: TRY NEXT RESOURCE
LOAD S1,.AMNAM(P2),AM.NAM ;GET ADDRESS OF NAME STRING
HRRZ S2,P1 ;COPY RESOURCE NUMBER MINUS ONE
PUSHJ P,UNMAP ;REMOVE LOWER-LEVEL RESOURCES
IFPLA4: AOBJN P1,IFPLA3 ;CHECK ALL RESOURCES
IFPLA5:
;Now, after the artificial reduction in the amount claimed (if any),
;see if there are enough resources in the 'A' matrix to add this process.
MOVE P1,P3 ;COPY 'A' MATRIX AOBJN POINTER
HRR P1,ATEMP ;INCLUDE ADDRESS OF SCRATCH ARRAY
MOVE P2,AMATRX ;GET ADDRESS OF 'A' MATRIX HEADER
IFPLA6: ADDI P2,AMALEN ;POINT TO NEXT 'A' MATRIX ENTRY
MOVE S1,(P1) ;GET COUNT FROM SCRATCH ARRAY
CAMG S1,.AMDLK(P2) ;TOO MANY FOR THIS RESOURCE?
AOBJN P1,IFPLA6 ;NO, SEARCH ALL ENTRIES
JUMPL P1,.RETF ;NEGATIVE: CANNOT ADD PROCESS
$RETT ;
SUBTTL Deadlock Avoidance -- DOPLAY - Play a process
;Play a process from the current sequence.
;
;Return all resources that the process currently owns to the resource
;pool. If the process owns any high-level resources and there are
;unplayed owners of those resources, then the low-level resources
;required by the high-level resources are not returned to the resource
;pool.
;
; Call: S1/ Process number (zero to PROCNT minus one)
; BHEAD/ Address of array of column headers
; CHEAD/ Address of array of column headers
; CRESN/ Address of array of resource counts for process
; ATEMP/ Address of 'A' matrix scratch array
; ASIZE/ Number of resources (length of 'A' matrix)
; AMATRX/ Address of A (resource) matrix
; PROCNT/ Process count (length of 'B' and 'C' matrices)
;
; Return: TRUE Always
DOPLAY: PUSHJ P,.SAVE4 ;SAVE P1-P4
MOVEM S1,P4 ;SAVE PROCESS NUMBER
SKIPG P3,ASIZE ;GET MAXIMUM NUMBER OF RESOURCES
JRST .RETT ;ZERO: WILL NEVER HAPPEN
MOVN P3,P3 ;BUILD AN AOBJN POINTER
HRLZ P3,P3 ;
;Give back most of what it owns.
MOVE T1,CRESN ;POINT TO 'C' MATRIX ENTRIES
MOVE T2,P3 ;COPY 'A' MATRIX AOBJN POINTER
HRR T2,ATEMP ;INCLUDE ADDRESS OF SCRATCH ARRAY
DOPLA1: MOVE S1,(T1) ;GET A 'C' MATRIX COLUMN ENTRY
MOVEM S1,(T2) ;PUT IT IN SCRATCH ARRAY
ADDI T1,1 ;POINT TO NEXT 'C' MATRIX ENTRY
AOBJN T2,DOPLA1 ;COPY ALL ENTRIES
;Unmap lower-level resources required by non-permanent higher-level
;resources that this process is going to give up.
MOVE P1,P3 ;COPY 'A' MATRIX AOBJN POINTER
MOVE P2,AMATRX ;GET ADDRESS OF 'A' MATRIX HEADER
DOPLA2: ADDI P2,AMALEN ;POINT TO NEXT 'A' MATRIX ENTRY
MOVE S1,ATEMP ;POINT TO TEMPORARY ARRAY
ADDI S1,(P1) ;
SKIPG (S1) ;ANY FOR THIS RESOURCE?
JRST DOPLA3 ;NO, TRY NEXT RESOURCE
LOAD S1,.AMSTA(P2),AM.DVT ;GET DEVICE TYPE
CAIE S1,%HLR1 ;IS IT A HIGH-LEVEL RESOURCE?
JRST DOPLA3 ;NO, TRY NEXT RESOURCE
MOVX S1,AM.PRR ;GET A BIT TO TEST WITH
TDNE S1,.AMNAM(P2) ;IS THIS A PERMANENT RESOURCE?
JRST DOPLA3 ;YES, TRY NEXT RESOURCE
MOVE S1,P4 ;COPY PROCESS NUMBER MINUS ONE
HRRZ S2,P1 ;COPY RESOURCE NUMBER MINUS ONE
PUSHJ P,IFOTHR ;OTHER PROCESSES NEED IT?
JUMPF DOPLA3 ;NO: TRY NEXT RESOURCE
LOAD S1,.AMNAM(P2),AM.NAM ;GET ADDRESS OF NAME STRING
HRRZ S2,P1 ;COPY RESOURCE NUMBER MINUS ONE
PUSHJ P,UNMAP ;REMOVE LOWER-LEVEL RESOURCES
DOPLA3: AOBJN P1,DOPLA2 ;CHECK ALL RESOURCES
;Now, after the artificial reduction (if any), give back this process'
;resources.
MOVE P1,P3 ;COPY 'A' MATRIX AOBJN POINTER
HRR P1,ATEMP ;INCLUDE ADDRESS OF SCRATCH ARRAY
MOVE P2,AMATRX ;GET ADDRESS OF 'A' MATRIX HEADER
DOPLA4: ADDI P2,AMALEN ;POINT TO NEXT 'A' MATRIX ENTRY
MOVE S1,(P1) ;GET COUNT FROM SCRATCH ARRAY
ADDM S1,.AMDLK(P2) ;ADD TO 'A' MATRIX COUNT
AOBJN P1,DOPLA4 ;ADD ALL ENTRIES
$RETT ;
SUBTTL Deadlock Avoidance -- IFOTHR - Check for other owners
;See if any other unplayed process is requesting a given resource.
;
; Call: S1/ Process number (zero to PROCNT minus one)
; S2/ Resource number (zero to ASIZE minus one)
; BFLAG/ Address of process flags
; CHEAD/ Address of array of column headers
; PROCNT/ Process count (length of arrays)
;
; Return: TRUE There are other unplayed owners.
; FALSE This process is the last owner.
IFOTHR: DMOVE T3,S1 ;SAVE ARGUMENTS
MOVX T2,SM.PLY ;GET A BIT TO TEST WITH
MOVN T1,PROCNT ;BUILD AN AOBJN POINTER
HRLZ T1,T1 ;
IFOTH1: CAIN T3,(T1) ;SAME PROCESS NUMBER?
JRST IFOTH2 ;YES, LOOK FOR OTHER PROCESSES
MOVE S1,BFLAG ;GET ADDRESS OF PROCESS FLAGS
ADDI S1,(T1) ;
TDNE T2,(S1) ;PROCESS ALREADY BEEN PLAYED?
JRST IFOTH2 ;YES, TRY NEXT PROCESS
MOVE S1,CHEAD ;GET ADDRESS OF 'C' MATRIX
ADDI S1,(T1) ; SM BLOCK
MOVE S1,(S1) ;
LOAD S2,.SMFLG(S1),SM.CNT ;GET RESOURCE COUNT
CAIGE S2,1(T4) ;ENOUGH ROOM FOR THIS RESOURCE?
JRST IFOTH2 ;NO, TRY NEXT PROCESS
ADDI S1,.SMRES+1(T4) ;CALCULATE ADDRESS OF COUNT
SKIPE (S1) ;DOES THIS PROCESS OWN IT?
$RETT ;YES, RETURN TRUE
IFOTH2: AOBJN T1,IFOTH1 ;CHECK ALL UNPLAYED PROCESSES
$RETF ;END OF LIST: NONE FOUND
SUBTTL Deadlock Avoidance -- UNMAP - Remove lower level resources
;Remove lower-level resources required by a given high-level resource.
;
; Call: S1/ Address of resource name string
; S2/ Resource number (zero to ASIZE minus one)
; ATEMP/ Address of 'A' matrix scratch array
; ASIZE/ Number of resources (length of 'A' matrix)
;
; Return: TRUE Always
UNMAP: PUSHJ P,.SAVE2 ;SAVE P1-P2
DMOVEM S1,P1 ;SAVE ARGUMENTS
PUSHJ P,V$FIND## ;FIND VOLUME-SET IN CACHE
JUMPF UNMAP3 ;CAN'T: FATAL ERROR
MOVE T2,.CQNVL(S1) ;GET NUMBER OF VOLUMES
JUMPLE T2,.RETT ;NONE: RETURN
MOVEI T1,.CQVSL(S1) ;POINT TO FIRST VOLUME BLOCK
UNMAP1: SKIPLE S1,.CQRSN(T1) ;GET VOLUME RESOURCE NUMBER
CAMLE S1,ASIZE ;RANGE CHECK THIS VALUE
JRST UNMAP2 ;OUT OF RANGE: TRY NEXT ONE
ADD S1,ATEMP ;POINT TO SCRATCH ENTRY (+1)
SOS -1(S1) ;DECREMENT RESOURCE COUNT
UNMAP2: ADDI T1,.CQVLL ;POINT TO NEXT VOLUME BLOCK
SOJG T2,UNMAP1 ;EXAMINE ALL VOLUME BLOCK ENTRIES
$RETT ;
UNMAP3: ADDI P2,1 ;GET REAL RESOURCE NUMBER
STOPCD (NCI,HALT,,<No Catalog information for resource>)
SUBTTL Deadlock Avoidance -- GTHEAD - Get column headers
;Fill an array of column headers (addresses of SM blocks).
;
; Call: S1/ List name
; S2/ Address of array of column headers
; PROCNT/ Process count (length of array)
;
; Return: TRUE Always
GTHEAD: MOVE T1,S2 ;SAVE ADDRESS OF ARRAY
SETZ T2, ;INITIALIZE COUNTER
MOVX T3,SM.IGN ;GET A BIT TO TEST WITH
PUSHJ P,L%FIRST ;GET ADDRESS OF FIRST ENTRY
SKIPA ;
GTHEA1: PUSHJ P,L%NEXT ;GET ADDRESS OF NEXT ENTRY
JUMPF GTHEA2 ;CAN'T: SEE IF ARRAY IS FILLED
TDNE T3,.SMFLG(S2) ;IGNORE THIS ENTRY?
JRST GTHEA1 ;YES, TRY NEXT ONE
ADDI T2,1 ;INCREMENT COUNTER
CAMLE T2,PROCNT ;TOO MANY?
JRST GTHEA3 ;YES, FATAL ERROR
MOVEM S2,(T1) ;SAVE ADDRESS OF ENTRY
AOJA T1,GTHEA1 ;SAVE ADDRESSES OF ALL ENTRIES
GTHEA2: CAMN T2,PROCNT ;CORRECT NUMBER OF ENTRIES?
$RETT ;YES, RETURN TRUE
GTHEA3: STOPCD (PCW,HALT,,<Process count (PROCNT) is wrong>)
SUBTTL Deadlock Avoidance -- GTCOLM - Get column entries
;Fill an array of column entries.
;
; Call: S1/ Address of SM block
; S2/ Address of array to fill
; ASIZE/ Number of resources (length of array)
;
; Return: TRUE Always
GTCOLM: LOAD T1,.SMFLG(S1),SM.CNT ;GET NUMBER OF RESOURCES
JUMPE T1,GTCOL2 ;ZERO: SHOULD NEVER HAPPEN
CAMLE T1,ASIZE ;MORE THAN THE NUMBER DEFINED?
MOVE T1,ASIZE ;YES, (OLD 'B' OR 'C' MATRIX ENTRY)
MOVN TF,T1 ;BUILD AN AOBJN POINTER
HRLM TF,S1 ;
GTCOL1: MOVE TF,.SMRES+1(S1) ;GET A RESOURCE COUNT
MOVEM TF,(S2) ;PUT IT IN SCRATCH ARRAY
ADDI S2,1 ;POINT TO NEXT ARRAY ADDRESS
AOBJN S1,GTCOL1 ;COPY ALL RESOURCE COUNTS
GTCOL2: SUB T1,ASIZE ;GET NEGATIVE NUMBER MISSING
JUMPGE T1,.RETT ;ZERO: EVERY LAST ONE IS THERE
GTCOL3: SETZM (S2) ;UNDEFINED VALUES ARE ZERO
ADDI S2,1 ;POINT TO NEXT ARRAY ADDRESS
AOJL T1,GTCOL3 ;FILL IN REMAINDER OF ARRAY
$RETT ;
SUBTTL Deadlock Avoidance -- GTNEXT - Get next process to play
;Find the first process that has not been tried or played.
;If there are none left and all of the processes have been played in the
;sequence, then it is a safe sequence.
;
; Call: BFLAG/ Address of process flags
; PROCNT/ Process count (length of array)
;
; Return: TRUE S1/ Process number (zero to PROCNT minus one)
; FALSE All processes have been tried or played:
; S1/ TRUE if all have been played (safe)
GTNEXT: SETO S1, ;ASSUME ALL HAVE BEEN PLAYED
MOVN S2,PROCNT ;BUILD AN AOBJN POINTER
HRLZ S2,S2 ;
HRR S2,BFLAG ;
MOVX T1,SM.PLY!SM.DLK ;GET BITS TO TEST WITH
MOVX T2,SM.PLY ;
GTNEX1: TDNN T1,(S2) ;HAS IT BEEN TRIED OR PLAYED?
JRST GTNEX2 ;NO, RETURN WITH THIS PROCESS
TDNN T2,(S2) ;HAS IT BEEN PLAYED?
SETZ S1, ;NO, SEQUENCE MAY BE UNSAFE
AOBJN S2,GTNEX1 ;LOOK AT NEXT PROCESS
$RETF ;NO MORE PROCESSES
GTNEX2: HRRZ S1,S2 ;RETURN WITH PROCESS MINUS ONE
SUB S1,BFLAG ;
$RETT ;
SUBTTL Deadlock Avoidance -- CLTRY - Clear all tried bits
;Clear the tried bits for all processes.
;This allows those processes tried (but rejected) during a previous
;scan to be included in the next scan.
;
; Call: BFLAG/ Address of process flags
; PROCNT/ Process count (length of array)
;
; Return: TRUE Always
CLTRY: MOVX TF,SM.DLK ;GET BIT TO CLEAR
MOVN S1,PROCNT ;BUILD AN AOBJN POINTER
HRLZ S1,S1 ;
HRR S1,BFLAG ;
CLTRY1: ANDCAM TF,(S1) ;CLEAR "TRIED" BIT
AOBJN S1,CLTRY1 ;CLEAR ALL "TRIED" BITS
$RETT ;
SUBTTL Dump MDA Database -- D$DUMP - Dump all matrices
;Dump the 'A', 'B', and 'C' matrices.
;
; Call:
;
; Return: TRUE Always
D$DUMP::$SAVE <TF,S1,S2> ;SINCE THIS IS A DEBUGGING AID,
PUSHJ P,.SAVE4## ; SAVE ALL REGISITERS
;Display the 'A' matrix.
MOVE P1,AMATRX ;GET ADDRESS OF HEADER BLOCK
LOAD P2,.AMHDR(P1),AM.CNT ;GET NUMBER OF RESOURCES
SETZB P3,P4 ;INITIALIZE THESE COUNTERS
DUMP11: ADDI P1,AMALEN ;POINT TO NEXT 'A' MATRIX ENTRY
LOAD S1,.AMNAM(P1),AM.NAM ;GET ADDRESS OF NAME STRING
JUMPE S1,DUMP12 ;NONE: IGNORE THIS ENTRY
ADDI P3,1 ;UPDATE THE RESOURCE NUMBER
$TEXT (,<^D4/P3/ ^T/(S1)/^A>) ;TYPE RESOURCE NUMBER AND NAME
ADDI P4,1 ;COUNT ITEMS ON THIS LINE
CAIGE P4,5 ;MORE THAN THIS MANY?
JRST DUMP12 ;NO, PUT MORE ON THIS LINE
$TEXT (,<>) ;TYPE A CRLF
SETZ P4, ;RESET THIS COUNTER
DUMP12: SOJG P2,DUMP11 ;POSITIVE: MORE TO COME
SKIPE P4 ;START OF A NEW LINE?
$TEXT (,<>) ;NO, TYPE A CRLF
$TEXT (,<>) ;TYPE AN EXTRA CRLF
;Display the resource numbers (starting with zero) as column headings.
;We start with zero because the portion of this routine that displays
;the 'B' and 'C' matrices types the resource number in that position.
MOVE P3,AMATRX ;GET ADDRESS OF FIRST BLOCK
LOAD P4,.AMHDR(P3),AM.CNT ;GET NUMBER OF RESOURCES
SETZ S1, ;INITIALIZE RESOURCE NUMBER
DUMP21: $TEXT (,<^D4/S1/ ^A>) ;TYPE THE RESOURCE NUMBER
CAMGE S1,P4 ;ARE WE FINISHED?
AOJA S1,DUMP21 ;NO, TYPE ALL RESOURCE NUMBERS
;For each resource number, display the number of units available, the
;number of units allocated, and the number of units claimed (owned).
$TEXT (,<^M^J ^A>) ;BEGIN A NEW LINE OF NUMBERS
DMOVE P1,P3 ;REINITIALIZE ADDRESS AND COUNT
DUMP22: ADDI P1,AMALEN ;POINT TO NEXT 'A' MATRIX ENTRY
LOAD S1,.AMCNT(P1),AM.AVA ;GET NUMBER OF UNITS AVAILABLE
$TEXT (,<^D4/S1/ ^A>) ;TYPE THAT NUMBER
SOJG P2,DUMP22 ;TYPE COUNT FOR ALL BLOCKS
$TEXT (,<^M^J ^A>) ;BEGIN A NEW LINE OF NUMBERS
DMOVE P1,P3 ;REINITIALIZE ADDRESS AND COUNT
DUMP23: ADDI P1,AMALEN ;POINT TO NEXT 'A' MATRIX ENTRY
LOAD S1,.AMCNT(P1),AM.ALO ;GET NUMBER OF UNITS ALLOCATED
$TEXT (,<^D4/S1/ ^A>) ;TYPE THAT NUMBER
SOJG P2,DUMP23 ;TYPE COUNT FOR ALL BLOCKS
$TEXT (,<^M^J ^A>) ;BEGIN A NEW LINE OF NUMBERS
DMOVE P1,P3 ;REINITIALIZE ADDRESS AND COUNT
DUMP24: ADDI P1,AMALEN ;POINT TO NEXT 'A' MATRIX ENTRY
LOAD S1,.AMCNT(P1),AM.CLM ;GET NUMBER OF UNITS CLAIMED
$TEXT (,<^D4/S1/ ^A>) ;TYPE THAT NUMBER
SOJG P2,DUMP24 ;TYPE COUNT FOR ALL BLOCKS
$TEXT (,<>) ;TYPE A CRLF
;Display the 'B' and 'C' matrices.
MOVEI P1,L%FIRST ;GET FIRST ENTRY IN 'B' MATRIX
MOVEI P2,L%FIRST ;GET FIRST ENTRY IN 'C' MATRIX
SETZ P3, ;INITIALIZE PROCESS NUMBER
DUMP31: ADDI P3,1 ;INCREMENT PROCESS NUMBER
$TEXT (,<>) ;TYPE AN EXTRA CRLF
;Find a 'B' matrix entry.
JUMPE P1,DUMP33 ;ZERO: ALREADY AT END-OF-LIST
DUMP32: MOVE S1,BMATRX ;
PUSHJ P,(P1) ;GET ADDRESS OF NEXT SM BLOCK
JUMPF DUMP34 ;NO MORE: CHECK THE 'C' MATRIX
MOVEI P1,L%NEXT ;ONLY CALL L%FIRST ONCE
MOVX S1,SM.IGN ;
TDNE S1,.SMFLG(S2) ;IGNORE THIS ENTRY?
JRST DUMP32 ;YES, GET ANOTHER ENTRY
$TEXT (,<^D3/P3/B ^A>) ;
PUSHJ P,DMPSM ;DUMP THE SM BLOCK
;Find a 'C' matrix entry.
JUMPE P2,DUMP31 ;ZERO: ALREADY AT END-OF-LIST
DUMP33: MOVE S1,CMATRX ;
PUSHJ P,(P2) ;GET ADDRESS OF NEXT SM BLOCK
JUMPF DUMP35 ;NO MORE: CHECK THE 'B' MATRIX
MOVEI P2,L%NEXT ;ONLY CALL L%FIRST ONCE
MOVX S1,SM.IGN ;
TDNE S1,.SMFLG(S2) ;IGNORE THIS ENTRY?
JRST DUMP33 ;YES, GET ANOTHER ENTRY
$TEXT (,<^D3/P3/C ^A>) ;
PUSHJ P,DMPSM ;DUMP THE SM BLOCK
JRST DUMP31 ;NEXT PROCESS NUMBER
DUMP34: SETZ P1, ;REACHED END OF 'B' MATRIX
JUMPN P2,DUMP33 ;MORE IN 'C' MATRIX: CONTINUE
$RETT ;
DUMP35: SETZ P2, ;REACHED END OF 'C' MATRIX
JUMPN P1,DUMP31 ;MORE IN 'B' MATRIX: CONTINUE
$RETT ;
SUBTTL Dump MDA Database -- DMPSM - Dump an SM Block
;Dump an SM block (helper routine for D$DUMP).
;
; Call: S2/ Address of SM block
; P4/ Number of resources (length of 'A' matrix)
;
; Return: TRUE Always
DMPSM: LOAD S1,.SMFLG(S2),SM.CNT ;GET NUMBER OF RESOURCES
JUMPE S1,DMPSM2 ;ZERO: SHOULD NEVER HAPPEN
CAMLE S1,P4 ;MORE THAN THE NUMBER DEFINED?
MOVE S1,P4 ;YES, (OLD 'B' OR 'C' MATRIX ENTRY)
MOVN S1,S1 ;BUILD AN AOBJN POINTER
HRLZ S1,S1 ;
HRRI S1,.SMRES+1(S2) ;CALCULATE ADDRESS OF COUNTERS
DMPSM1: $TEXT (,<^D4/(S1)/ ^A>) ;TYPE THE NUMBER CLAIMED
AOBJN S1,DMPSM1 ;TYPE ALL COUNTERS IN SM BLOCK
LOAD S1,.SMFLG(S2),SM.CNT ;GET THE NUMBER OF RESOURCES
DMPSM2: SUB S1,P4 ;GET NEGATIVE NUMBER MISSING
JUMPGE S1,DMPSM4 ;ZERO: EVERY LAST ONE IS THERE
DMPSM3: $TEXT (,< 0 ^A>) ;UNDEFINED VALUES ARE ZERO
AOJL S1,DMPSM3 ;TYPE SEVERAL EXTRA ZEROES
DMPSM4: $TEXT (,<>) ;FINISH WITH A CRLF
$RETT ;
> ;END TOPS10 CONDITIONAL
SUBTTL D$DLCK - ROUTINE TO SET UP THE DEADLOCK AVOIDANCE CHECK
;CALL: S1/ The VSL Address
; AP/ The MDR Address
;
;RET: True if Allocation Wins, False Otherwise
TOPS10<
D$DLCK::PUSHJ P,.SAVE4 ;SAVE P1 - P4
PUSHJ P,.SAVET ;SAVE T1 - T4
MOVEM S1,SAVVSL ;SAVE THE VSL FOR RETRIES
DLCK.A: LOAD P1,.VSLNK(S1),VS.LNK ;GET THE REQUEST LINK CODE
LOAD P2,.MRCNT(AP),MR.CNT ;GET THE VSL REQUEST COUNT
MOVNS P2 ;NEGATE THE COUNT
MOVSS P2 ;MOVE RIGHT TO LEFT
HRRI P2,.MRVSL(AP) ;CREATE VSL SEARCH AOBJN AC
SETZM P4 ;CLEAR THE DEADLOCK CHECK FLAG
$SAVE <M> ;PRESERVE WHATEVER IS IN M
PUSHJ P,SETSTK ;SETUP THE VSL, RSN STACK
MOVE T4,[IOWD MSGLN##,G$MSG] ;GET A QUEUE FOR VSL ADDRESSES
PUSH T4,[-1] ;INDICATE 'END OF QUEUE'
DLCK.1: MOVE P3,0(P2) ;GET A VSL ADDRESS
LOAD S1,.VSLNK(P3),VS.LNK ;GET ITS LINK CODE
MOVX S2,VS.CLM ;GET THE 'RESOURCES CLAIMED' STATUS BIT
CAMN P1,S1 ;DO WE WANT THIS VSL ???
TDNE S2,.VSFLG(P3) ; AND IS HAS IT BEEN CLAIMED YET ???
JRST DLCK.3 ;WRONG VSL OR CLAIMED,,SKIP IT
MOVE S1,P3 ;COPY THE VSL ADRS
PUSHJ P,VSLRSN ;EXTRACT ALL RSNS FOR THIS VSL
$RETIF ;RETURN IF NOT ENOUGH RESOURCES
SETOM P4 ;SET THE DEADLOCK CHECK FLAG
PUSH T4,P3 ;QUEUE UP THE VSL ADDRESS
DLCK.3: AOBJN P2,DLCK.1 ;CHECK ALL VSL'S
JUMPE P4,.RETT ;NOTHING TO DO, SO RETURN NOW!
;Here to find the users 'C' matrix entry
PUSHJ P,D$CMTX ;LOCATE THE USERS 'C' MATRIX ENTRY
SKIPT ;IT MUST BE THERE !!!
STOPCD (CME,HALT,,<'C' matrix entry is missing>)
;Here to perform 'A' & 'C' Matrix Updates
;First, Create a duplicate 'A' matrix
MOVE P4,AMATRX ;GET THE OLD 'A' MATRIX ADDRESS
LOAD S1,.AMHDR(P4),AM.LEN ;GET THE MATRIX LENGTH
PUSHJ P,M%GMEM ;GET A NEW' 'A' MATRIX
MOVEM S2,AMATRX ;SAVE THE ADDRESS OF THE NEW MATRIX
ADDI S1,0(S2) ;CALC THE MATRIX END ADDRESS
HRL S2,P4 ;GET SOURCE,,DEST FOR BLT
BLT S2,-1(S1) ;COPY OLD 'A' MATRIX TO NEW 'A' MATRIX
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
;Then, Create a duplicate 'C' matrix entry
MOVE S1,CMATRX ;GET THE 'C' MATRIX ID
PUSHJ P,L%RENT ;REMEMBER THE ORIGIONAL ENTRY
PUSHJ P,L%SIZE ;GET ITS LENGTH
MOVE P3,S2 ;SAVE IT FOR A SECOND
PUSHJ P,L%CENT ;CREATE A NEW ENTRY
MOVE P2,S2 ;SAVE ITS ADDRESS FOR A SECOND
ADDI P3,0(S2) ;CALC ENTRY END ADDRESS
HRL S2,CM ;GET SOURCE,,DESTINATION FOR BLT
BLT S2,-1(P3) ;COPY OLD ENTRY TO NEW ENTRY
MOVX S1,SM.IGN ;GET THE 'IGNORE' BIT
IORM S1,.SMFLG(CM) ;LITE IT FOR THE OLD ENTRY
MOVE CM,P2 ;POINT TO NEW ENTRY
;Here to Update the 'A' and 'C' matricies
DLCK.4: POP M,P1 ;GET A RSN OFF THE QUEUE
POP M,P3 ;GET THE VSL ADDRESS OFF THE QUEUE
CAMN P1,[-1] ;END OF THE QUEUE ???
JRST DLCK.5 ;YES,,LETERRIP !!!
LOAD S1,P1,RF.RSN ;GET JUST THE RESOURCE NUMBER
MOVE S2,P3 ;AIM AT THE VSL
PUSHJ P,ADDCMA ;UPDATE THE 'C' MATRIX
LOAD S1,P1,RF.RSN ;GET JUST THE RESOURCE NUMBER
MOVE S2,P3 ;AIM AT THE VSL
TXNN P1,RF.OTU ;IF OTHER USERS, DON'T TAKE OUT DRIVES
PUSHJ P,ADDAMA ;UPDATE THE 'A' MATRIX
JUMPT DLCK.4 ;WIN,,CONTINUE
JRST DLCK.7 ;NO GOOD,,RETURN AN ERROR
;Here to invoke the Deadlock Avoidance Routine
DLCK.5: PUSHJ P,DEADLK ;LETERRIP !!!
JUMPF DLCK.7 ;NO GOOD,,FINISH UP !!!
;Deadlock Check Wins,,delete the old 'A' Matrix and 'C' Matrix
;Also Update the VS.CLM status bit for the VSL'S involved
LOAD S1,.AMHDR(P4),AM.LEN ;GET THE OLD 'A' MATRIX LENGTH
MOVE S2,P4 ;GET THE OLD 'A' MATRIX ADDRESS
PUSHJ P,M%RMEM ;RETURN IT TO THE MEMORY MANAGER
MOVE S1,CMATRX ;GET THE 'C' MATRIX ID
PUSHJ P,L%PREM ;POSITION TO THE OLD ENTRY
PUSHJ P,L%DENT ;AND DELETE IT
MOVX S2,VS.CLM ;GET THE 'RESOURCES CLAIMED' STATUS BIT
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
DLC.5B: POP T4,S1 ;GET A VSL ADDRESS OFF THE QUEUE
CAMN S1,[-1] ;END OF QUEUE ???
$RETT ;YES,,RETURN OK...
IORM S2,.VSFLG(S1) ;LITE THE RESOURCES CLAIMED STATUS BIT
JRST DLC.5B ;AND GO TRY AGAIN
;Here if an error occurs,,delete the new 'A' and 'C' Matricies
DLCK.7: MOVE S2,AMATRX ;GET THE NEW 'A' AMATRX ADDRESS
MOVEM P4,AMATRX ;RESTORE THE OLD 'A' MATRIX ADDRESS
LOAD S1,.AMHDR(S2),AM.LEN ;GET THE OLD 'A' MATRIX LENGTH
PUSHJ P,M%RMEM ;RETURN IT TO THE MEMORY MANAGER
MOVE S1,CMATRX ;GET THE 'C' MATRIX ID
MOVE S2,CM ;GET THE 'C' MATRIX ENTRY
PUSHJ P,L%APOS ;POSITION TO THE ENTRY
PUSHJ P,L%DENT ;AND DELETE IT
MOVE S1,CMATRX ;GET THE 'C' MATRIX ENTRY
PUSHJ P,L%PREM ;POSITION TO THE OLD 'C' ENTRY
ZERO .SMFLG(S2),SM.IGN ;CLEAR THE IGNORE BIT
MOVE S1,SAVVSL ;GET THE VSL ADDRESS
PUSHJ P,SHUFFL ;SHUFFLE THE RESOURCES AROUND
JUMPF .RETF ;NO GOOD SHUFFLING
JRST DLCK.A ;TRY AGAIN WITH NEW RESOURCES
SAVVSL: BLOCK 1 ;PLACE TO SAVE A VSL
> ;END TOPS10 CONDITIONAL
SUBTTL RETA%C - ROUTINE TO RETURN RESOURCES TO THE 'A' & 'C' MATRICIES
;CALL: S1/ The VSL Being Returned
;
;RET: True Always
TOPS10<
RETA%C: LOAD TF,.VSFLG(S1),VS.CLM ;HAS THIS VSL CLAIMED ITS RESOURCES ???
JUMPE TF,.RETT ;NO,,NOTHING TO RETURN
PUSHJ P,.SAVE4 ;SAVE P1 - P4 FOR A SECOND
MOVE P2,S1 ;SAVE THE VSL ADDRESS
PUSHJ P,D$CMTX ;GET THE USERS 'C' MATRIX ADDRESS
SKIPT ;IT ALSO MUST BE THERE !!!
PUSHJ P,S..CME ;NO,,UH OH !!!
$SAVE <M> ;PRESERVE WHATEVER IS IN M
PUSHJ P,SETSTK ;SETUP THE VSL, RSN STACK
MOVE S1,P2 ;GET BACK VSL ADRS
PUSHJ P,VSLRSN ;GO GET THIS VSL'S RESOURCE NUMBERS
SKIPT ;CHECK FOR ERRORS
STOPCD (RNR,HALT,,<Returning non-existant resource>)
ZERO .VSFLG(P2),VS.CLM ;CLEAR RESOURCE CLAIMED STATUS BIT
RETA.1: POP M,P1 ;GET BACK RSN
POP M,0(M) ;THROW OUT VSL (COPY OF P2)
CAMN P1,[-1] ;TOP OF STACK?
$RETT ;YES, ALL DONE
LOAD S1,P1,RF.RSN ;GET THE RSN IN S1
MOVE S2,P2 ;GET THE VSL ADDRESS IN S2
PUSHJ P,SUBCMA ;RETURN THE 'C' MATRIX RESOURCE
TXNN P1,RF.OTU ;ARE THERE OTHER USERS?
PUSHJ P,SUBAMA ;NO, RETURN THE 'A' MATRIX RESOURCE
SKIPT ;'A' MATRIX NEGATIVE,,THATS ALL FOLKS !!
STOPCD (NAM,HALT,,<Negative 'A' matrix entry computed>) ;CNT CAN'T BE NEGATIVE
JRST RETA.1 ;PROCESS THE NEXT VSL
> ;END TOPS10 CONDITIONAL
SUBTTL RETBMA - ROUTINE TO RETURN RESOURCES TO THE 'B' MATRIX
;CALL: S1/ The VSL Being Returned
;
;RET: True Always
TOPS10<
RETBMA: PUSHJ P,.SAVE4 ;SAVE P1 - P4 FOR A SECOND
MOVE P2,S1 ;SAVE THE VSL ADDRESS
PUSHJ P,D$BMTX ;GET THE USERS 'B' MATRIX ADDRESS
SKIPT ;IT ALSO MUST BE THERE !!!
STOPCD (BME,HALT,,<'B' matrix entry is missing>)
$SAVE <M> ;PRESERVE WHATEVER IS IN M
PUSHJ P,SETSTK ;SETUP THE VSL, RSN STACK
MOVE S1,P2 ;RESTORE THE VSL ADDRESS
PUSHJ P,VSLRSX ;GO GET THIS VSL'S RESOURCE NUMBERS
JUMPT RETB.1 ;CHECK FOR ERRORS
PUSHJ P,S..RNR ;RETURNING NON-EXISTANT RESOURCE
RETB.1: POP M,P1 ;GET BACK RSN AND FLAGS
POP M,0(M) ;THROW OUT VSL ADRS (HAVE IN P2)
CAMN P1,[-1] ;TOP OF STACK?
$RETT ;YES, ALL DONE!
LOAD S1,P1,RF.RSN ;GET RESOURCE NUMBER IN S1
MOVE S2,P2 ;GET THE VSL ADDRESS IN S2
PUSHJ P,SUBBMA ;RETURN THE 'B' MATRIX RSN
JRST RETB.1 ;TRY THE NEXT ONE
> ;END TOPS10 CONDITIONAL
SUBTTL ADDBMA - ROUTINE TO UPDATE A RESOURCE NUMBER FOR A USER
; ADDCMA - "" "" "" " "" "" "" " ""
;CALL: S1/ The Resource Number
; S2/ The VSL Address
; BM or CM/ The Matrix entry address
TOPS10<
ADDBMA: PUSHJ P,.SAVE3 ;SAVE P1 - P3
MOVE P2,BM ;GET THE ENTRY ADDRESS
MOVE P3,BMATRX ;GET THE 'B' MATRIX ID
JRST UPDR.1 ;MEET AT THE PASS !!!
ADDCMA: PUSHJ P,.SAVE3 ;SAVE P1 - P3
MOVE P2,CM ;GET THE ENTRY ADDRESS
MOVE P3,CMATRX ;GET THE 'C' MATRIX ID
UPDR.1: PUSHJ P,GETADD ;GET ADDITIVE (S1 = RSN, S2 = VSL)
UPDR.3: $SAVE <S1,S2> ;SAVE THE RSN AND COUNT
LOAD P1,.SMFLG(P2),SM.CNT ;GET HIS RSN COUNT
CAIG S1,0(P1) ;DOES HE HAVE THIS RESOURCE YET ???
JRST UPDR.4 ;YES,,JUST BUMP THE COUNT
;Here to add space to the users 'B' matrix entry for the new RSN
PUSH P,S1 ;SAVE THE RSN
PUSH P,S2 ;SAVE THE COUNT
STORE S1,.SMFLG(P2),SM.CNT ;SAVE THE NEW MAX RSN OFFSET
SUB S1,P1 ;CALC NEEDED SPACE FOR NEW RSN
MOVE P1,S1 ;SAVE IT HERE
MOVE S1,P3 ;GET THE MATRIX ID
MOVE S2,P2 ;GET THE ENTRY ADDRESS
PUSHJ P,L%APOS ;POSITION TO IT
PUSHJ P,L%SIZE ;GET THE ENTRY LENGTH
PUSH P,S2 ;SAVE THE CURRENT LENGTH
ADD S2,P1 ;EXTEND IT BY CORRECT AMOUNT
PUSHJ P,L%CENT ;CREATE A NEW ENTRY FOR THE USER
POP P,S1 ;RESTORE THE OLD LENGTH
ADD S1,S2 ;CALC BLT END ADDRESS
MOVE P1,S2 ;GET 0,,DESTINATION
HRL P1,P2 ;GET SOURCE,,DESTINATION FOR BLT
BLT P1,-1(S1) ;COPY OLD TO NEW
EXCH P2,S2 ;GET NEW ENTRY ADDR IN P2, OLD IN S2
MOVE S1,P3 ;GET THE MATRIX ID
PUSHJ P,L%APOS ;POSITION TO THE OLD ENTRY
PUSHJ P,L%DENT ;DELETE IT
CAMN P3,BMATRX ;IS THIS THE 'B' MATRIX ???
MOVE BM,P2 ;YES,,SAVE THE NEW ENTRY ADDRESS
CAMN P3,CMATRX ;IS THIS THE 'C' MATRIX ???
MOVE CM,P2 ;YES,,SAVE THE NEW ENTRY ADDRESS
POP P,S2 ;RESTORE THE COUNT
POP P,S1 ;RESTORE THE RSN OFFSET
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
;Here to just update the RSN claim count for a user
UPDR.4: ADDI S1,.SMRES(P2) ;CALC RSN ENTRY ADDRESS
ADDM S2,0(S1) ;UPDATE THE MATRIX
CAME P2,BM ;ARE WE UPDATING THE 'B' MATRIX ???
$RETT ;NO,,RETURN
SUBI S1,.SMRES(P2) ;YES,,GET THE RSN BACK
IMULI S1,AMALEN ;GET THE 'A' MATRIX ENTRY OFFSET
ADD S1,AMATRX ;GET THE ENTRY ADDRESS
INCR .AMCNT(S1),AM.ALO ;BUMP THE RSN ALLOCATION COUNT
$RETT ;RETURN
> ;END TOPS10 CONDITIONAL
SUBTTL SUBCMA - ROUTINE TO RETURN RESOURCES TO THE 'C' MATRIX
;CALL: S1/ The RSN
; S2/ The VSL Address
;
;RET: True Always or not at all
TOPS10<
SUBCMA: $SAVE <S1,S2> ;SAVE S1 & S2 ACROSS THE CALL
PUSH P,S2 ;SAVE THE VSL ADDRESS FOR A SECOND
LOAD S2,.SMFLG(CM),SM.CNT ;GET THE RSN COUNT
CAIGE S2,0(S1) ;RESOURCE NUMBER MUST BE IN RANGE
STOPCD (RMC,HALT,,<Resource number missing in 'C' matrix>)
POP P,S2 ;RESTORE THE VSL ADDRESS
PUSHJ P,GETSUB ;CALC SUBTRACT QUANTITY
ADDI S1,.SMRES(CM) ;POINT TO THE RSN ENTRY
ADDM S2,0(S1) ;UPDATE THE MATRIX
SKIPGE 0(S1) ;IF STILL VALID,,SKIP
STOPCD (NCM,HALT,,<Negative 'C' matrix entry computed>) ;CNT CAN'T BE NEGATIVE
$RETT ;RETURN
SUBTTL SUBBMA - ROUTINE TO RETURN 'B' MATRIX RESOURCES
;CALL: S1/ The RSN
; S2/ The VSL Address
;
;RET: True Always or not at all
SUBBMA: $SAVE <S1,S2> ;SAVE S1 & S2 ACROSS THE CALL
PUSH P,S2 ;SAVE THE VSL ADDRESS FOR A SECOND
LOAD S2,.SMFLG(BM),SM.CNT ;GET THE RSN COUNT
CAIGE S2,0(S1) ;RESOURCE NUMBER MUST BE IN RANGE
STOPCD (RMB,HALT,,<Resource number missing in 'B' matrix>)
POP P,S2 ;RESTORE THE VSL ADDRESS
PUSHJ P,GETSUB ;GET THE SUBTRACT QUANTITY
ADDI S1,.SMRES(BM) ;POINT TO THE RSN ENTRY
ADDM S2,0(S1) ;UPDATE THE MATRIX
SKIPGE 0(S1) ;SKIP IF STILL VALID
STOPCD (NBM,HALT,,<Negative 'B' matrix entry computed>) ;CNT CAN'T BE NEGATIVE
SUBI S1,.SMRES(BM) ;YES,,GET THE RSN BACK
IMULI S1,AMALEN ;GET THE 'A' MATRIX ENTRY OFFSET
ADD S1,AMATRX ;GET THE ENTRY ADDRESS
DECR .AMCNT(S1),AM.ALO ;REDUCE THE RSN ALLOCATION COUNT
$RETT ;RETURN
> ;END TOPS10 CONDITIONAL
SUBTTL ADDAMA - ROUTINE TO REMOVE 'A' MATRIX RESOURCES
; SUBAMA - ROUTINE TO RETURN 'A' MATRIX RESOURCES
; D$INCA - ROUTINE TO ADD 1 TO THE RESOURCE COUNT
; D$DECA - ROUTINE TO SUBTRACT 1 FROM THE RESOURCE COUNT
;CALL: S1/ The RSN to be Updated (if ADDAMA or SUBAMA)
; S2/ The VSL Address
;
; S1/ The UCB Address (if D$INCA or D$DECA)
;
;RET: False iff the Matrix Count goes Negative
TOPS10<
ADDAMA: TDZA TF,TF ;FLAG ADD ENTRY POINT
SUBAMA: MOVEI TF,1 ;FLAG SUBTRACT ENTRY POINT
$SAVE <S1,S2,T1> ;SAVE S1 & S2 ACROSS THE CALL
MOVE T1,TF ;GET ENTRY POINT TYPE
XCT [PUSHJ P,GETADD
PUSHJ P,GETSUB](T1) ;GET ADD/SUBTRACT QUANTITY
SETZM T1 ;INDICATE CLAIM ADJUSTMENT
PUSHJ P,ADJAMA ;UPDATE THE MATRIX FOR THIS RSN
JUMPF .RETF ;OVER QUOTA,,RETURN NOW
$RETT ;ELSE RETURN OK
D$INCA::SKIPA S2,[-1] ;GET RSN COUNT OF -1 AND SKIP
D$DECA::MOVEI S2,1 ;GET RSN COUNT OF 1
$SAVE <T1> ;SAVE T1
SETOM T1 ;INDICATE NO CLAIM ADJUSTMENT
LOAD S1,.UCBST(S1),UC.RSN ;GET THE CURRENT RSN
PUSHJ P,ADJAMA ;UPDATE THE MATRIX FOR THIS RSN
JUMPF .RETF ;OVER QUOTA,,RETURN NOW
$RETT ;ELSE RETURN OK
SUBTTL ADJAMA - ROUTINE TO ADJUST THE 'A' MATRIX
;CALL: S1/ The RSN
; S2/ The count
; T1/ 0 if claim adjustment wanted, -1 if not
;
;RET: True if OK, False if over quota
ADJAMA: IMULI S1,AMALEN ;GET THE ENTRY OFFSET
ADD S1,AMATRX ;POINT TO THE ENTRY
JUMPN T1,ADJA.1 ;NO CLAIM ADJUSTMENT,,SKIP THIS
LOAD TF,.AMCNT(S1),AM.CLM ;GET THE NUMBER CLAIMED
ADDM S2,TF ;ADD/SUBTRACT 1
STORE TF,.AMCNT(S1),AM.CLM ;AND SAVE THE RESULT
ADJA.1: LOAD TF,.AMCNT(S1),AM.AVA ;GET THE AVAILABLE COUNT
MOVNS S2 ;REVERSE THE PROCESS
ADDM S2,TF ;ADD/SUBTRACT 1
STORE TF,.AMCNT(S1),AM.AVA ;AND SAVE THE RESULT
TXNE TF,SGNBIT ;IF FIELD SIGN BIT IS ON,, THEN
$RETF ; COUNT IS NEGATIVE SO RETURN FALSE
$RETT ;ELSE RETURN OK
> ;END TOPS10 CONDITIONAL
SUBTTL VSLRSN - ROUTINE TO FIND A VSL'S RESOURCE NUMBERS
;CALL: S1/ The VSL Address
; M/ Stack pointer to RSN Queue
;
;RET: FALSE if the disk VSL is not in the system catalog
; TRUE with the VSL & RSN pairs queued up
TOPS10<
VSLRSN: TDZA TF,TF ;INDICATE NORMAL ENTRY POINT
VSLRSX: SETOM TF ;INDICATE EXTENDED ENTRY POINT
PUSHJ P,.SAVE4 ;SAVE P1 - P4
MOVE P1,S1 ;SAVE VSL ADRS
MOVE P2,TF ;SAVE THE ENTRY POINT INDICATOR
LOAD S1,.VSFLG(S1),VS.TYP ;GET TYPE OF VOLUME SET
JRST @.+1(S1) ;DISPATCH
EXP .RETF ;%UNKN
EXP VSLMTA ;%TAPE
EXP VSLSTR ;%DISK
EXP VSLDTA ;%DTAP
;Here to queue up allocation for a tape VSL
;If the Extended entry point was used, we will also queue up
;the volume RSN's for all the volumes in the volume set.
VSLMTA: LOAD S1,.VSATR(P1),VS.RSN ;GET THE REQUESTED DEVICE TYPE
JUMPE S1,.RETF ;NEED A REAL RESOURCE NUMBER
PUSH M,P1 ;QUEUE UP THE VSL
PUSH M,S1 ;QUEUE UP THE DEVICE REQUIREMENTS
JUMPN P2,VSLMT1 ;EXTENDED ENTRY,,QUEUE ALL VOL RSN'S
;Queue the VSL's current volume RSN
;; MOVX S1,VS.ABO+VS.VSW ;GET ABORTED BY OPR + VOL SWITCH BITS
MOVX S1,VS.VSW ;GET VOL SWITCH BIT
TDNE S1,.VSFLG(P1) ;EITHER BIT ON ???
$RETT ;YES,,DON'T QUEUE UP THE VOL RSN
LOAD S1,.VSCVL(P1),VS.OFF ;GET OFFSET TO CURRENT VOLUME
ADDI S1,.VSVOL(P1) ;POINT TO THE CURRENT VOL ADDRESS
MOVE S1,0(S1) ;GET THE VOL ADDRESS
SKIPN .VLNAM(S1) ;ANY VOLID SPECIFIED ???
$RETT ;NO,,DON'T QUEUE ANYTHING UP !!!
PUSHJ P,D$TVRS ;YES,,GET THE VOLUME RSN
PUSH M,P1 ;QUEUE UP THE VSL
PUSH M,S1 ;QUEUE UP VOLUME RSN
$RETT
;Queue all the volumes in the volume set
VSLMT1: LOAD P2,.VSCVL(P1),VS.CNT ;GET THE VOLUME COUNT
MOVNS P2 ;NEGATE IT
MOVSS P2 ;MOVE RIGHT TO LEFT
HRRI P2,.VSVOL(P1) ;CREATE VOL AOBJN AC
VSLMT2: MOVE S1,0(P2) ;GET A VOLUME ADDRESS
SKIPN .VLNAM(S1) ;ANY VOLID SPECIFIED ???
JRST VSLMT3 ;NO,,DON'T QUEUE ANYTHING UP !!!
PUSHJ P,D$TVRS ;YES,,CONVERT IT TO A RSN
PUSH M,P1 ;QUEUE UP THE VSL
PUSH M,S1 ;QUEUE UP THE VOLUME RSN
VSLMT3: AOBJN P2,VSLMT2 ;CONTINUE FOR ALL VOLUMES
$RETT ;AND RETURN
;Here to queue up allocation for a disk VSL
VSLSTR: HRROI S1,.VSVSN(P1) ;POINT TO THE ASCIZ VOL SET NAME
PUSHJ P,S%SIXB ;CONVERT IT TO SIXBIT
MOVE S1,S2 ;MOVE IT TO S1
PUSH P,S1 ;SAVE STR NAME A SECOND
PUSHJ P,D$SRSN ;GET THE STRUCTURE RESOURCE NUMBER
POP P,TF ;GET BACK STR NAME
PUSH M,P1 ;QUEUE UP THE VSL ADDRESS
PUSH M,S1 ;QUEUE UP THE RESOURCE NUMBER
IMULI S1,AMALEN ;MAKE A MATRIX INDEX
ADD S1,AMATRX ;AIM AT CURRENT SLOT
MOVX S2,AM.PRR ;BIT TO TEST
TDNE S2,.AMNAM(S1) ;PERMANENT STRUCTURE?
$RETT ;YES--DONE HERE
LOAD S1,.AMNAM(S1),AM.NAM ;GET ADDRESS OF RESOURCE NAME
PUSHJ P,V$FIND## ;REQUEST THE CATALOG ENTRY
JUMPF .POPJ ;NOT THERE,,IGNORE ALLOCATION FOR NOW
MOVE P2,S1 ;SAVE CATALOG ADRS
$CALL S%SIXB ;CONVERT TO SIXBIT
MOVE S1,S2 ;COPY RESULT
PUSHJ P,D$FNDV ;FIND THE PRIMARY VOL BLOCK
PUSHJ P,D$VOWN ;FIND THE OWNER
SETZ S1, ;ASSUME NO OTHER USERS
SKIPF ;ASSUMPTION TRUE?
MOVX S1,RF.OTU ;NO, INDICATE OTHER USERS
EXCH S1,P2 ;SAVE FLAG BIT, GET BACK STR NAME
LOAD P3,.CQNVL(S1) ;GET NUMBER OF DRIVES UNDER THIS STR
MOVEI P4,.CQVSL(S1) ;AIM AT DEVICE LIST PORTION
VSLST1: MOVE S1,.CQRSN(P4) ;GET THIS RESOURCE NUMBER
PUSH M,P1 ;QUEUE UP THE VSL ADDRESS
IOR S1,P2 ;LITE (PERHAPS) THE OTHER USER BIT
PUSH M,S1 ;QUEUE UP THE CATALOG ENTRY ADDRESS
ADDI P4,.CQVLL ;STEP TO NEXT DRIVE
SOJG P3,VSLST1 ;DO 'EM ALL
$RETT ;DONE,,RETURN
;Here to queue up allocation for a DECtape VSL
VSLDTA: LOAD S1,.VSATR(P1),VS.RSN ;GET THE REQUESTED DEVICE TYPE
JUMPE S1,.RETF ;NEED A REAL RESOURCE NUMBER
LOAD TF,.VSCVL(P1),VS.CNT ;GET VOLUME COUNT
SOJN TF,.RETF ;CAN ONLY HAVE ONE REEL PER VOL-SET
PUSH M,P1 ;QUEUE UP THE VSL
PUSH M,S1 ;QUEUE UP THE DEVICE REQUIREMENTS
;Queue the VSL's one and only volume RSN
MOVEI P2,.VSVOL(P1) ;POINT TO VOL BLOCK ADDRESS
MOVE S1,0(P2) ;GET A VOLUME ADDRESS
SKIPN .VLNAM(S1) ;ANY VOLID SPECIFIED ???
$RETT ;NO
PUSHJ P,D$OVRS ;YES,,CONVERT IT TO A RSN
PUSH M,P1 ;QUEUE UP THE VSL
PUSH M,S1 ;QUEUE UP THE VOLUME RSN
$RETT ;AND RETURN
> ;END TOPS10 CONDITIONAL
SUBTTL SETSTK - Setup a queue for VSL, RSN pairs
;This routine sets up a queue so that all resource numbers for a
; given VSL or group of VSLs can be stashed in one place.
TOPS10<
SETSTK: MOVE M,[IOWD RPDLEN,RSNPDL] ;AIM AT THE QUEUE
PUSH M,[-1] ;MARK THE END OF THE QUEUE
PUSH M,[-1] ;ONE MORE TIME !!!
$RETT
RPDLEN==^D100*2 ;SPACE FOR 100 VSL, RSN PAIRS
RSNPDL: BLOCK RPDLEN ;THE RSN STACK
> ;END TOPS10 CONDITIONAL
SUBTTL GETADD - ROUTINE TO CALC THE 'A', 'B', 'C' MATRIX ADD VALUE
; GETSUB - ROUTINE TO CALC THE 'A', 'B', 'C' MATRIX SUB VALUE
;CALL: S1/ The RSN
; S2/ The VSL Address whose resource is being updated or 0 if none
;
;RET: S1/ The RSN
; S2/ The Additive or Subtractive Quantity
;This routine returns a vslue in S2 which is then used in updating
;The deadlock avoidance matricies. This value is determined as
;follows: If the Resource Type is %STRC, and the VS.SIN
;flag bit is lit, then return MAXRES in S2. If both of those
;conditions are not met, then return 1 in S2. If the GETSUB entry
;Point is used, Then the negative of those 2 values is returned.
TOPS10<
GETADD: TDZA TF,TF ;INDICATE 'GETADD' ENTRY POINT
GETSUB: SETOM TF ;INDICATE 'GETSUB' ENTRY POINT
JUMPE S2,[MOVEI S2,1 ;NO VSL ADDRESS,,GET A 1
SKIPE TF ;WAS 'GETSUB' ENTRY POINT USED ???
MOVNS S2 ;YES,,NEGATE THE VALUE
$RETT ] ;AND RETURN
$SAVE <S1,P1> ;SAVE S1 AND P1 FOR A SECOND
IMULI S1,AMALEN ;GET THE 'A' MATRIX OFFSET
ADD S1,AMATRX ;POINT TO THE 'A' MATRIX ENTRY
LOAD S1,.AMSTA(S1),AM.DVT ;GET THE RESOURCE TYPE
LOAD P1,.VSFLG(S2),VS.SIN ;GET THE 'SINGLE ACCESS' FLAG BIT
MOVEI S2,1 ;DEFAULT TO A 1
CAXN S1,%STRC ;IS THIS A STRUCTURE RESOURCE ???
SKIPN P1 ;YES,,AND IS SINGLE ACCESS REQUIRED ??
SKIPA ;NOT A STR OR NOT SINGLE ACCESS,,SKIP
MOVX S2,MAXRES ;ELSE LOAD MAX RESOURCE COUNT
SKIPE TF ;WAS ENTRY POINT 'GETSUB' ???
MOVNS S2 ;YES,,THEN NEGATE THE VALUE
$RETT ;RETURN
> ;END TOPS10 CONDITIONAL
SUBTTL MDA pseudo process routines -- D$PPRL - Delete an MDR
TOPS10<
D$PPRL::SKIPN G$MDA## ;ARE WE RUNNING WITH MDA ???
$RETT ;NO,,RETURN
$SAVE <AP,CM,BM> ;SAVE SOME AC'S
SKIPE AP,.QEMDR(S1) ;CHECK AND LOAD THE MDR ADDRESS
PJRST D$DMDR ;DELETE THE MDR FOR THIS REQUEST
$RETT ;NONE,,RETURN
> ;END TOPS10 CONDITIONAL
TOPS20<
D$PPRL: $RETT > ;A NOOP ON THE -20
SUBTTL MDA pseudo process routines -- D$PPRE - Reset a real process
D$PPRE::
TOPS10< SKIPN G$MDA## ;ARE WE RUNNING WITH MDA ???
$RETT ;NO,,RETURN
$SAVE <P1,P2,P3,P4,AP,CM,BM> ;SAVE ALL THESE AC'S
MOVE P1,S1 ;SAVE THE QE ADDRESS
SKIPN AP,.QEMDR(P1) ;CHECK AND LOAD THE MDR ADDRESS
$RETT ;RETURN IF NONE...
PUSHJ P,D$BMTX ;LOCATE THE PROCESS 'B' MATRIX
PUSHJ P,D$CMTX ;LOCATE THE PROCESS 'C' MATRIX
MOVE S1,.QERID(P1) ;GET THE PROCESS REQUEST ID
TXO S1,BA%JOB ;CREATE THE PSEUDO JOB NUMBER
STORE S1,.MRJOB(AP),MR.JOB ;CONVERT THE MDR TO A PSEUDO PROCESS MDR
STORE S1,.QEJBN(P1),QE.BJN ;SAVE IT HERE ALSO
MOVEM S1,.SMJOB(BM) ;CONVERT THE 'B' MATRIX AND
MOVEM S1,.SMJOB(CM) ;CONVERT THE 'C' MATRIX
SETZM G$ACK## ;WE DON'T WANT AN ACK LATER !!!
INCR .MRCNT(AP),MR.LNK ;GEN A NEW LINK CODE
LOAD P3,.MRCNT(AP),MR.LNK ; AND LOAD IT INTO P3
LOAD P4,.MRCNT(AP),MR.CNT ;GET THE VSL REQUEST COUNT
MOVEI P2,.MRVSL(AP) ;GET VSL LIST ADDRESS
ADDI P2,-1(P4) ;WORK FROM LAST VSL TO FIRST
PPRE.1: MOVE S1,0(P2) ;GET A VSL ADDRESS
MOVE P1,.VSFLG(S1) ;SAVE THE VOL SET FLAG BITS
PUSHJ P,D$ALCV ;RETURN THIS VSL'S ALLOCATION
MOVE S1,0(P2) ;GET THE VSL ADDRESS BACK
TXNE P1,VS.UAL ;DID THE USER ALLOCATE THIS VSL ???
TXNE P1,VS.ALC ;YES,,DID HE HAVE IT MOUNTED ???
JRST PPRE.2 ;NOT USER ALLOC OR NOT MOUNTED,,SKIP
ZERO .VSFLG(S1),VS.ALC ;WANT THIS REMOUNTED !!
STORE P3,.VSLNK(S1),VS.LNK ;RESET TO A COMMON LINK CODE
PPRE.2: SUBI P2,1 ;GET NEXT VSL ADDRESS
SOJG P4,PPRE.1 ;CONTINUE FOR ALL VSL'S
MOVE S1,.MRQEA(AP) ;GET THE QE ADDRESS
MOVX S2,QE.WAM+QE.ALR ;GET 'ALLOCATION PRE-SCAN' BITS
ANDCAM S2,.QESEQ(S1) ;CLEAR THEM
MOVX S2,QE.WAL ;FORCE ANOTHER PRE-SCAN BY
IORM S2,.QESEQ(S1) ; LIGHTING THIS BIT
> ;END TOPS10 CONDITIONAL
$RETT ;AND RETURN
SUBTTL MDA pseudo process routines -- D$PMDR - Find a process
;CALL: No Args
;
;RET: True Always
TOPS10<
D$PMDR::SKIPN G$MDA## ;ARE WE RUNNING WITH MDA ???
$RETT ;NO,,RETURN
MOVE S1,MDRQUE ;GET THE MDR QUEUE ID
PUSHJ P,L%FIRST ;GET THE FIRST ENTRY
JRST PMDR.2 ;JUMP THE FIRST TIME
PMDR.1: MOVE S1,MDRQUE ;GET THE MDR QUEUE ID
PUSHJ P,L%NEXT ;GET THE NEXT ENTRY
PMDR.2: JUMPF .RETT ;DONE,,RETURN
MOVE AP,S2 ;SAVE THE ENTRY ADDRESS
LOAD S1,.MRJOB(AP),MR.JOB ;GET THE JOB NUMBER
TXNN S1,BA%JOB ;IS IT A PSEUDO PROCESS
JRST PMDR.1 ;NO,,SKIP IT
MOVE S1,.MRQEA(AP) ;GET THE QE ADDRESS
ZERO .QESEQ(S1),QE.ALR ;ZAP THE REQUEST FOR ALLOCATION BIT
MOVE S1,.MRVSL(AP) ;GET THE VSL ADDRESS
PUSHJ P,D$MNTV ;TRY TO MOUNT IT
JRST PMDR.1 ;AND GO GET THE NEXT
> ;END TOPS10 CONDITIONAL
TOPS20<
D$PMDR: $RETT > ;A NOOP ON THE -20
SUBTTL D$MODR - ROUTINE TO MODIFY A USERS ALLOCATION ON THE 'FLY'
;CALL: S1/ The VSL to be modified
; S2/ The UCB of the device to be added
;
;RET: True if user can have the volume, false otherwise
TOPS10<
D$MODR: PUSHJ P,.SAVE3 ;SAVE P1 - P3
DMOVE P1,S1 ;SAVE THE VSL AND UCB ADDRESSES
SKIPN P3,.UCBVL(P2) ;CHK AND LOAD THE MOUNTED VOL ADDRESS
$ERJMP MD$NVM,P1 ;NONE THERE,,SOMETHING FISHY HERE !!!
;Check/Validate the Density Status
MOVX S1,VL.SRD ;GET SET REQUESTED DENSITY FOR USER BIT
ANDCAM S1,.VLFLG(P3) ;CLEAR IT INCASE SECOND TIME THROUGH
LOAD S1,.VSATR(P1),VS.DDN ;DID WE DEFAULT THE DENSITY ???
JUMPN S1,MODR.1 ;YES,,CONTINUE ONWARD
LOAD S1,.VSFLG(P1),VS.NEW ;[1164] /NEW-VOLUME REINT?
JUMPN S1,MODR.0 ;[1164] ..JUMP IF SO
LOAD S1,.VSATR(P1),VS.DEN ;NO,,GET THE REQUESTED DENSITY CODE
LOAD S2,.VLFLG(P3),VL.DEN ;GET THE VOLUME DENSITY
CAMN S1,S2 ;IT WOULD BE NICE IF THEY MATCHED
JRST MODR.1 ;THEY DO
LOAD S1,.VLFLG(P3),VL.LBT ;GET THE VOLUME LABEL TYPE
PUSHJ P,GETLBT ;CONVERT IT
MOVX S2,UC.WLK ;GET THE WRITE LOCKED BIT
CAIN S1,%UNLBL ;UNLABELED?
TDNE S2,.UCBST(P2) ;CANT SCREW AROUND UNLESS WRITE-ENABLED
$ERJMP MD$RDD,P1 ;UNLABELED OR WRITE-LOCKED
MODR.0: LOAD S1,.VSATR(P1),VS.DEN ;[1164] GET THE REQUESTED DENSITY
MOVE S1,D$DEN(S1) ;CONVERT CODE TO A BIT MAP
TDNN S1,.UCBST(P2) ;DRIVE SUPPORT THE REQUESTED DENSITY?
$ERJMP MD$IDD,P1 ;OPERATOR IS A JOKER
MOVX S1,VL.SRD ;GET SET REQUESTED DENSITY FOR USER BIT
IORM S1,.VLFLG(P3) ;REMEMBER FOR LATER
;Check/Validate the Track Status
MODR.1: LOAD S1,.VSATR(P1),VS.DTK ;DID WE DEFAULT THE TRACK STATUS ???
JUMPN S1,MODR.2 ;YES,,CONTINUE ONWARD
LOAD S1,.VSATR(P1),VS.TRK ;GET THE REQUESTED TRACK STATUS
LOAD S2,.UCBST(P2),UC.TRK ;GET THE DEVICE TRACK STATUS
CAME S1,S2 ;THEY MUST MATCH !!!
$ERJMP MD$TDM,P1 ;NO,,TOO BAD
;Check to see if requested resource matches assigned resource
MODR.2: LOAD S1,.VSATR(P1),VS.RSN ;GET THE REQUESTED DEVICE TYPE
SKIPN S1 ;CAN'T BE ZERO !!!
STOPCD (MRN,HALT,,<Missing resource number>)
LOAD P2,.UCBST(P2),UC.RSN ;GET THE DEVICE RESOURCE NUMBER
CAMN S1,P2 ;DO WE MATCH ???
JRST MODR.3 ;YES,,HE WINS BIG !!!
;See if we can change his allocation to include this device
PUSHJ P,D$BMTX ;LOCATE THE USERS 'B'
PUSHJ P,D$CMTX ; AND 'C' MATRIX ENTRIES
DMOVE S1,P1 ;GET VSL (P1) AND RSN (P2)
PUSHJ P,MODALC ;MODIFY THE USERS ALLOCATION
SKIPT ;WIN,,CONTINUE
$ERJMP MD$DDD,P1 ;RETURN THE ERROR (DEADLOCK DETECTED) !!
MODR.3: LOAD S1,.VLFLG(P3),VL.DEN ;GET THE MOUNTED VOLUME DENSITY
MOVX S2,VL.SRD ;GET SET REQUESTED DENSITY FOR USER BIT
TDNN S2,.VLFLG(P3) ;GONNA DO THIS LATER?
STORE S1,.VSATR(P1),VS.DEN ;NO - RESET IT FOR THIS VSL
$RETT ;RETURN
SUBTTL SHUFFL - Routine to shuffle resources around for a requestor
;CALL: S1/ A 'current' VSL address
;
;RET: True if resources shuffled OK, false otherwise
;This routine attempts to resolve deadlocks for a user by allocating
;different resources to a users request. The current (new) requests
;are shuffled first, then old requests are looked at. If, after all
;of this there is still a deadlock, tough noogies !!!
SHUFFL: $SAVE <P1,P2,P3,P4,T1> ;SAVE SOME AC'S
STKVAR <<VQUEUE,40>> ;ALLOCATE SOME QUEUE SPACE
LOAD P2,.VSLNK(S1),VS.LNK ;GET THE LINK CODE (NEW REQUESTS)
MOVEI P3,VQUEUE ;GET THE QUEUE ADDRESS
ADD P3,[-40,,-1] ;CREATE QUEUE PDL POINTER
PUSH P3,[-1] ;SIGNAL END OF 'NEW' REQUEST QUEUE
MOVE P4,P ;SAVE THE CURRENT STACK POINTER
PUSH P,[-2] ;SIGNAL END OF 'OLD' REQUEST QUEUE
LOAD P1,.MRCNT(AP),MR.CNT ;GET THE REQUEST COUNT
MOVNS P1 ;NEGATE IT
MOVSS P1 ;MOVE RIGHT TO LEFT
HRRI P1,.MRVSL(AP) ;CREATE AOBJN AC
SHUF.1: MOVE S1,0(P1) ;GET A VSL ADDRESS
LOAD S2,.VSFLG(S1),VS.TYP ;GET THE REQUEST TYPE
CAXE S2,%TAPE ;A TAPE ???
JRST SHUF.2 ;NO,,GET NEXT
PUSHJ P,D$FOWN ;DOES HE HAVE IT MOUNTED ???
JUMPT SHUF.2 ;YES,,SKIP THIS
MOVE S1,0(P1) ;GET THE VSL ADDRESS BACK
LOAD S2,.VSLNK(S1),VS.LNK ;GET ITS LINK CODE
CAMN P2,S2 ;A 'NEW' REQUEST ???
PUSH P3,S1 ;YES,,QUEUE IT UP
CAME P2,S2 ;AN 'OLD' REQUEST ???
PUSH P,S1 ;YES,,QUEUE IT UP
SHUF.2: AOBJN P1,SHUF.1 ;CHECK ALL REQUESTS
PUSHJ P,D$BMTX ;LOCATE THIS GUYS 'B' MATRIX ENTRY
PUSHJ P,D$CMTX ;LOCATE THIS GUYS 'C' MATRIX ENTRY
SHUF.3: POP P3,P1 ;DE-QUEUE A VSL ADDRESS
CAMN P1,[-1] ;DONE WITH THE 'NEW' QUEUE ???
JRST [MOVE P3,P ;YES,,GET POINTER TO 'OLD' QUEUE
JRST SHUF.3 ] ;AND KEEP ON TRUCK'N !!!
CAMN P1,[-2] ;DONE WITH THE 'OLD' QUEUE ???
JRST [MOVE P,P4 ;RESTORE THE STACK POINTER
$RETF ] ;JUST NO WAY TO CONTINUE !!!!!
LOAD S1,.VSATR(P1),VS.DEN ;GET HIS DENSITY CODE
MOVE S1,D$DEN(S1) ;CONVERT TO A BIT MASK
LOAD S2,.VSATR(P1),VS.TRK ;GET THE TRACK TYPE
LOAD T1,.VSATR(P1),VS.RSN ;GET THE CURRENT RESOURCE
PUSHJ P,ANYTAP ;GET THE NEXT RESOURCE WHICH FITS
JUMPF SHUF.3 ;NO MORE RESOURCES,,TRY NEXT REQUEST
MOVE S2,S1 ;GET THE NEW RESOURCE IN S2
MOVE S1,P1 ;GET THE VSL ADDRESS IN S1
PUSHJ P,MODALC ;MODIFY HIS ALLOCATION
JUMPF SHUF.3 ;LOSE,,TRY NEXT REQUEST
MOVE P,P4 ;RESTORE THE STACK POINTER
$RETT ;WIN,,RETURN
SUBTTL MODALC - Routine to modify a users resource number for a request
;CALL: S1/ The VSL Address
; S2/ The New Resource Number (RSN)
;
;RET: True - users matrix entries updated
; False - Deadlock detected (no matrix modifications)
MODALC: PUSHJ P,.SAVE3 ;SAVE P1 AND P3
DMOVE P1,S1 ;SAVE THE VSL ADDRESS AND NEW RSN
LOAD P3,.VSFLG(P1),VS.CLM ;GET THE RESOURCE CLAIMED STATUS IN P2
LOAD S1,.VSATR(P1),VS.RSN ;GET THE REQUESTED DEVICE TYPE
MOVE S2,P1 ;GET THE VSL ADDRESS IN S2
PUSHJ P,SUBBMA ;DELETE HIS 'B' MATRIX ENTRY
JUMPE P3,.+3 ;NOT CLAIMED,,DON'T MODIFY 'A' & 'C'
PUSHJ P,SUBAMA ;DELETE HIS 'A' MATRIX ENTRY
PUSHJ P,SUBCMA ;DELETE HIS 'C' MATRIX ENTRY
MOVE S1,P2 ;GET THE NEW RESOURCE NUMBER IN S1
MOVE S2,P1 ;GET THE VSL ADDRESS IN S2
PUSHJ P,ADDBMA ;ADD A NEW 'B' MATRIX ENTRY
JUMPE P3,.+3 ;NOT CLAIMED,,DON'T MODIFY 'A' & 'C'
PUSHJ P,ADDAMA ;ADD A NEW 'A' MATRIX ENTRY
PUSHJ P,ADDCMA ;ADD A NEW 'C' MATRIX ENTRY
PUSHJ P,DEADLK ;CHECK FOR DEADLOCKS
JUMPF MODA.2 ;FOUND SOME,,OH WELL WE TRIED !!!!
MODA.1: STORE P2,.VSATR(P1),VS.RSN ;WIN,,MODIFY HIS ALLOCATION
$RETT ;RETURN
;Here if user caused a deadlock - put matrix back in order
MODA.2: MOVE S1,P2 ;GET THE NEW RESOURCE NUMBER IN S1
MOVE S2,P1 ;GET THE VSL ADDRESS IN S2
PUSHJ P,SUBBMA ;DELETE HIS 'B' MATRIX ENTRY
JUMPE P3,.+3 ;NOT CLAIMED,,DON'T MODIFY 'A' & 'C'
PUSHJ P,SUBAMA ;DELETE HIS 'A' MATRIX ENTRY
PUSHJ P,SUBCMA ;DELETE HIS 'C' MATRIX ENTRY
LOAD S1,.VSATR(P1),VS.RSN ;GET THE REQUESTED DEVICE TYPE
MOVE S2,P1 ;GET THE VSL ADDRESS IN S2
PUSHJ P,ADDBMA ;RESTORE HIS 'B' MATRIX ENTRY
JUMPE P3,.+3 ;NOT CLAIMED,,DON'T MODIFY 'A' & 'C'
PUSHJ P,ADDAMA ;RESTORE HIS 'A' MATRIX ENTRY
PUSHJ P,ADDCMA ;RESTORE HIS 'C' MATRIX ENTRY
$RETF ;RETURN NO GOOD
> ;END TOPS10 CONDITIONAL
SUBTTL D$ALCT - ROUTINE TO ALLOCATE TAPE VOLUMES FOR 'IDENTIFY' COMMAND
;CALL: S1/ The VSL Address
;
;RET: True if no deadlock, False otherwise
TOPS10<
INTERN D$ALCT
D$ALCT: PUSHJ P,.SAVE2 ;SAVE P1 - P2
MOVE P1,S1 ;SAVE THE VSL ADDRESS
PUSHJ P,D$CMTX ;LOCATE THIS GUYS 'C' MATRIX ENTRY
LOAD S1,.VSCVL(P1),VS.OFF ;GET THE OFFSET TO THE CURRENT VOLUME
ADDI S1,.VSVOL(P1) ;POINT TO ITS ADDRESS
MOVE S1,0(S1) ;GET THE CURRENT VOLUME ADDRESS
PUSHJ P,D$TVRS ;GET THE VOLUME RESOURCE NUMBER
MOVE P2,S1 ;SAVE THE RSN IN P2
MOVE S2,P1 ;GET THE VSL ADDRESS IN S2
PUSHJ P,ADDAMA ;ADD THIS RESOURCE TO THE 'A' MATRIX
PUSHJ P,ADDCMA ;ADD THIS RESOURCE TO THE 'C' MATRIX
LOAD S1,.VSFLG(P1),VS.CLM ;HAS THIS DEVICE BEEN CLAIMED ???
JUMPN S1,ALCT.1 ;YES,,DON'T DO IT AGAIN
LOAD S1,.VSATR(P1),VS.RSN ;GET THE REQUESTED DEVICE RSN
MOVE S2,P1 ;GET THE VSL ADDRESS IN S2
PUSHJ P,ADDAMA ;ADD THIS RESOURCE TO THE 'A' MATRIX
PUSHJ P,ADDCMA ;ADD THIS RESOURCE TO THE 'C' MATRIX
ALCT.1: PUSHJ P,DEADLK ;PERFORM THE DEADLOCK CHECK
JUMPT [MOVX S1,VS.CLM ;WIN,,GET VSL CLAIMED STATUS
IORM S1,.VSFLG(P1) ;SET IT
$RETT ] ;AND RETURN
MOVE S1,P2 ;GET THE VOLUME RSN IN S1
MOVE S2,P1 ;GET THE VSL ADDRESS IN S2
PUSHJ P,SUBAMA ;REMOVE THIS RSN FROM THE 'A' MATRIX
PUSHJ P,SUBCMA ;REMOVE THIS RSN FROM THE 'C' MATRIX
LOAD S1,.VSFLG(P1),VS.CLM ;GET THE DEVICE CLAIMED STATUS BIT
JUMPN S1,ALCT.2 ;IF SET,,DON'T RETURN DEVICE ALLOCATION
LOAD S1,.VSATR(P1),VS.RSN ;GET THE DEVICE RESOURCE NUMBER
MOVE S2,P1 ;GET THE VSL ADDRESS
PUSHJ P,SUBAMA ;REMOVE THIS RSN FROM THE 'A' MATRIX
PUSHJ P,SUBCMA ;REMOVE THIS RSN FROM THE 'C' MATRIX
ALCT.2: $ERJMP MD$DDD,P1 ;RETURN AN ERROR
> ;END TOPS10 CONDITIONAL
END