Trailing-Edge
-
PDP-10 Archives
-
BB-M780C-SM
-
monitor-sources/scsjsy.mac
There are 20 other files named scsjsy.mac in the archive. Click here to see a list.
; UPD ID= 2310, SNARK:<6.1.MONITOR>SCSJSY.MAC.93, 12-Aug-85 11:41:13 by GRANT
;TCO 6.1.1284 - Tell CIFORK to run when connect block is to be reaped
; UPD ID= 2186, SNARK:<6.1.MONITOR>SCSJSY.MAC.92, 5-Jun-85 11:06:04 by MCCOLLUM
;TCO 6.1.1406 - Update copyright notice.
; UPD ID= 2005, SNARK:<6.1.MONITOR>SCSJSY.MAC.91, 24-May-85 12:14:11 by MCCOLLUM
;TCO 6.1.1405 - Don't call FRKCHK from SCSKIL. Return +1 if the fork is not current.
; UPD ID= 1949, SNARK:<6.1.MONITOR>SCSJSY.MAC.90, 9-May-85 17:17:09 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1932, SNARK:<6.1.MONITOR>SCSJSY.MAC.89, 7-May-85 22:33:58 by MCCOLLUM
;TCO 6.1.1238 - Fix BUG. documentation
; UPD ID= 1450, SNARK:<6.1.MONITOR>SCSJSY.MAC.88, 1-Feb-85 14:18:48 by LOMARTIRE
;Add new symbols to describe the priority used by SC.SMG and SC.SDG
; UPD ID= 1222, SNARK:<6.1.MONITOR>SCSJSY.MAC.87, 18-Dec-84 14:18:28 by HAUDEL
;TCO 6.1.1090 - The following changes...
; Add FRKCHK routine and new error code.
; Repeat 0 some code that is now handled by DAIG% code.
; Delete NOSKED/OKSKED locks and add NOINT/OKINT locks.
; Change name of SCATWQ and SCABWQ to SCSTHQ and SCSBHQ and change
; the way the SCS% interrupts are passed back from PI level to
; user level.This means that many CIOFF/CION functions are
; also removed and that code is changed from RESCD to SWAPCD..
; Add some comments (calling ACs) for some utility routines.
; Remove CIOFF/CION from SCSRUB,add comments,change SCSRUB to SWAPCD
; UPD ID= 1137, SNARK:<6.1.MONITOR>SCSJSY.MAC.86, 3-Dec-84 07:53:51 by HAUDEL
; Change and add some comments.
; Remove unreferenced symbols.
; Repeat 0 some unreferenced code.
; Add CIOFF and CION to SCSCON code.
; Change some STKVARs plus other minor changes
; UPD ID= 1058, SNARK:<6.1.MONITOR>SCSJSY.MAC.85, 13-Nov-84 09:06:06 by LOMARTIRE
;Use new sending priority symbols in SC.SMG and SC.SDG calls.
;
; UPD ID= 968, SNARK:<6.1.MONITOR>SCSJSY.MAC.84, 6-Nov-84 15:54:27 by HAUDEL
;Change SCSDEQ code to RETSKP and RET so that it will not do a RET on
;both a good return and an error return.
;
; UPD ID= 963, SNARK:<6.1.MONITOR>SCSJSY.MAC.83, 6-Nov-84 09:44:04 by HAUDEL
;Changes to SCSQUE and SCSPSI so that blocks are now doubly linked and
;none are lost when SCSPSI removes them from the list. Also, a couple of
;changes to previous edit and error returns.
;
; UPD ID= 5053, SNARK:<6.MONITOR>SCSJSY.MAC.82, 5-Nov-84 08:10:30 by HAUDEL
;Many changes - Add STKVAR entries in SCSLIS so that they match those of
;SCSCON; add OKSKED to error return in SCSRMG; add OKINT to error return in
;SCSCRD; add ENDSV. in UMPERR; change ENDSV. to ENDTV. in ONTBLD; add JFCL 0
;in GDEERR after call to SCSLFQ.
;
; UPD ID= 5048, SNARK:<6.MONITOR>SCSJSY.MAC.81, 31-Oct-84 16:09:01 by HAUDEL
;Change SCSCSP code to handle a null byte pointer; do not return data
;if the byte pointer is zero.
;
; UPD ID= 5045, SNARK:<6.MONITOR>SCSJSY.MAC.80, 31-Oct-84 15:23:18 by HAUDEL
;Add code to SCSCSP to return the destination node number for the .SSCSP
;SCS% function.
;
; UPD ID= 5044, SNARK:<6.MONITOR>SCSJSY.MAC.79, 31-Oct-84 10:48:20 by HAUDEL
;Delete a NOSKED in RXNMOR code, one was done before a JRST to this code.
;
; UPD ID= 5029, SNARK:<6.MONITOR>SCSJSY.MAC.78, 29-Oct-84 08:11:54 by GRANT
;In SCSRCD, minor fixes for destination hardware version
; UPD ID= 4999, SNARK:<6.MONITOR>SCSJSY.MAC.77, 24-Oct-84 20:05:40 by GRANT
;In SCSRCD, return the remote node name and all the words of hardware version
; UPD ID= 4981, SNARK:<6.MONITOR>SCSJSY.MAC.76, 23-Oct-84 14:46:24 by HAUDEL
;Fix code in SCSLXN so that DMA buffer names are added to the fork's linked
;list.
;
; UPD ID= 4941, SNARK:<6.MONITOR>SCSJSY.MAC.75, 16-Oct-84 09:31:22 by HAUDEL
;Correct problems with the handling of SCS's BSDs - when linking a new
;user virtual address into a BSD, checked for chained BSDs; update pointers
;in the BSD when removing a user virtual address.
;
; UPD ID= 4834, SNARK:<6.MONITOR>SCSJSY.MAC.74, 17-Sep-84 11:22:43 by PURRETTA
;Update copyright notice
;
; UPD ID= 4790, SNARK:<6.MONITOR>SCSJSY.MAC.73, 5-Sep-84 15:49:56 by HAUDEL
;Change some comments. Change the SCSMAP code to use bytes for high density
;and add 2 entries to the STKVAR. Change a call of DATADR to DATRET in the
;ACCERR code(this is more of UPD ID 4690 that prevent ILLUUOs).
;
; UPD ID= 4746, SNARK:<6.MONITOR>SCSJSY.MAC.72, 24-Aug-84 11:22:55 by CDUNN
;Make SCSCBD delete the connect block from the owning fork's CB list. Prevents
;block from being reaped before SCSJSY is done with it.
;
; UPD ID= 4724, SNARK:<6.MONITOR>SCSJSY.MAC.71, 21-Aug-84 14:57:43 by CDUNN
;Fix typo in UPD ID= 4593. Make SCSDEQ referance .MEANC and .MEAPC rather than
;.MEAPC twice. Also fix SCSKIL (KILCHK) to update FLINK and BLINK pointers
;after emptying the fork CB queue.
;
; UPD ID= 4690, SNARK:<6.MONITOR>SCSJSY.MAC.70, 14-Aug-84 16:22:06 by CDUNN
;Move CID check before data check in SCSACC. Prevents ILLUUO. Also force
;minimum send credit for JSYS connection to be 5 (temporary fix to make
;diagnostics to HSC work, real solution is to allow user to specify min
;send credit).
;
; UPD ID= 4673, SNARK:<6.MONITOR>SCSJSY.MAC.69, 10-Aug-84 17:14:12 by CDUNN
;Add function .SSRPS (Return path status information)
;
; UPD ID= 4659, SNARK:<6.MONITOR>SCSJSY.MAC.68, 7-Aug-84 16:17:21 by CDUNN
;Do correct cleanup of DMA buffers on connection delete.
;
; UPD ID= 4651, SNARK:<6.MONITOR>SCSJSY.MAC.67, 7-Aug-84 10:26:02 by CDUNN
;Fix handling of .SSPBC callback since AC usage has changed.
;
; UPD ID= 4593, SNARK:<6.MONITOR>SCSJSY.MAC.66, 26-Jul-84 22:26:18 by CDUNN
;Allow forks without connect blocks to get online/offline interrupts. Also
;update the table of contents.
;
; UPD ID= 4501, SNARK:<6.MONITOR>SCSJSY.MAC.65, 12-Jul-84 19:56:15 by LOMARTIRE
;Rework of callback handling. Replace .SSCBD with .SSDDG.
;Code for AC change in .SSDGR/.SSMGR callbacks.
;Remove .SSMNT and .SSNWO callback handlers.
;Fix SBLIST searching in SINNCO since SBLIST is now sparse.
;Remove EXTERN references to SC.SMD and SC.RMD
;
; UPD ID= 4456, SNARK:<6.MONITOR>SCSJSY.MAC.64, 12-Jul-84 10:46:29 by CDUNN
;Fix SCSKIL to not smash any ACs so it can be called easily from KSELF and
;FLOGO. Also add required NOINTs to SCAMPI calls.
;
; UPD ID= 4428, SNARK:<6.MONITOR>SCSJSY.MAC.63, 3-Jul-84 14:29:28 by LOMARTIRE
;Remove reference to CBACSY and replace with .CBADR
;Replace references to CBFLG with .CBFLG
;
; UPD ID= 4409, SNARK:<6.MONITOR>SCSJSY.MAC.62, 29-Jun-84 11:29:03 by CDUNN
;Set correct flag bits in CB on end of connection events. Also remove
;referances to CBFABT. Also fix CB delete on active side of disconnect.
;
; UPD ID= 4296, SNARK:<6.MONITOR>SCSJSY.MAC.61, 4-Jun-84 14:29:11 by HAUDEL
;Change SCSMAP to use new form of SC.MAP
;
; UPD ID= 4284, SNARK:<6.MONITOR>SCSJSY.MAC.60, 1-Jun-84 12:21:26 by LOMARTIRE
;Remove SC.SBI references and use new CBDNOD instead of old CBDSBI.
;
; UPD ID= 4258, SNARK:<6.MONITOR>SCSJSY.MAC.59, 30-May-84 14:18:48 by CDUNN
;TCO 6.2073 - Fix SCSDEQ to correctly delete the first entry from a queue
;with more than one entry.
;
; UPD ID= 4199, SNARK:<6.MONITOR>SCSJSY.MAC.58, 9-May-84 13:19:09 by LOMARTIRE
;Remove reference to SC.ABT.
;
; UPD ID= 4190, SNARK:<6.MONITOR>SCSJSY.MAC.57, 9-May-84 00:34:06 by CDUNN
;Fix referances to CBSBI and .CBSBI to use correct LOAD/STOR name...
;
; UPD ID= 4169, SNARK:<6.MONITOR>SCSJSY.MAC.56, 2-May-84 03:11:58 by CDUNN
;Change SCSRMG/SCSRDG to zero leftover. bytes in an industry compatable packet.
;
; UPD ID= 4159, SNARK:<6.MONITOR>SCSJSY.MAC.55, 30-Apr-84 23:46:21 by CDUNN
;Fix the moving of process names from user to monitor pad the name with spaces.
;
; UPD ID= 4110, SNARK:<6.MONITOR>SCSJSY.MAC.54, 23-Apr-84 18:36:36 by CDUNN
;Fix SCSRMG/SCSRDG to correctly convert from bytes to words. Also report
;correct byte size to user. Also fix SCSEVT to correctly account for the
;size of the overhead area in event blocks when moving data.
;
; UPD ID= 4052, SNARK:<6.MONITOR>SCSJSY.MAC.53, 5-Apr-84 15:00:51 by CDUNN
;General work on interrupt routines. Merge SINMGR and SINDGR. Also fix
;update of datagram and message counts.
;
; UPD ID= 4045, SNARK:<6.MONITOR>SCSJSY.MAC.52, 4-Apr-84 10:45:40 by CDUNN
;Remove bad edit history entires added by last edit.
;
; UPD ID= 4044, SNARK:<6.MONITOR>SCSJSY.MAC.51, 4-Apr-84 10:38:02 by CDUNN
;Merge SCSRDG and SCSRMG into one routine with two entry points. Fixes to
;SCSKIL and SCSQRD/SCSQRM. Also get SCSEVT to use SCSDMU rather than BLTMU.
;Also disallow use of previous delete bits. Code still needs to be removed,
;only bit check was removed.
;
; UPD ID= 3990, SNARK:<6.MONITOR>SCSJSY.MAC.50, 28-Mar-84 01:06:58 by CDUNN
;Fix PSI channel check in SCSAIC. Add functions .SSGLN and .SSRBS. Fix SCSEVT
;to use ENDSV and not ENDTV.
;
; UPD ID= 3953, SNARK:<6.MONITOR>SCSJSY.MAC.49, 21-Mar-84 12:44:24 by LOMARTIRE
;Remove old PI ring buffer. This has been replaced by RG.PIT jacket routine.
;Also remove PIDBG conditional.
;
; UPD ID= 3875, SNARK:<6.MONITOR>SCSJSY.MAC.48, 7-Mar-84 19:05:38 by CDUNN
;Many, many cosmetic changes. Remove leading spaces on some instructions,
;remove SAVEAC's from top level JSYS code. Change TRVARs to STKVARs. Also
;insure calls to SCA have NOINT's as they are needed.
;
; UPD ID= 3778, SNARK:<6.MONITOR>SCSJSY.MAC.47, 28-Feb-84 13:08:23 by CDUNN
;Fix missed test in previous edit.
;
; UPD ID= 3769, SNARK:<6.MONITOR>SCSJSY.MAC.46, 27-Feb-84 11:12:49 by CDUNN
;Make SCSSMG and SCSSDG the same routine with two entry points.
;
; UPD ID= 3753, SNARK:<6.MONITOR>SCSJSY.MAC.45, 25-Feb-84 07:59:20 by HALL
;SCAMPI's names changed for maintenance functions.
;
; UPD ID= 3716, SNARK:<6.MONITOR>SCSJSY.MAC.44, 21-Feb-84 13:03:33 by CDUNN
;More TCO 6.1127 - Convert SCSCON,SCSLIS, and SCSACC into a batch of
;subroutines
;
; UPD ID= 3573, SNARK:<6.MONITOR>SCSJSY.MAC.43, 28-Jan-84 01:41:23 by MCLEAN
;EDITS TO REMOVE P1 FROM CONNECT BLOCK DEFSTRS
;
; UPD ID= 3560, SNARK:<6.MONITOR>SCSJSY.MAC.42, 26-Jan-84 14:38:16 by MCLEAN
;ADD NEW PARAMETER TO SC.MAP CALL (ALWAYS 1 FOR NOW)
;
; UPD ID= 3521, SNARK:<6.MONITOR>SCSJSY.MAC.41, 24-Jan-84 12:44:34 by HALL
;Create SCSRET for returning a buffer to the correct pool
;In SINPSC call SCSRET on both success and failure
;In SCSSDG, set JH%DGB in .JHFLG word (it was being set only in the AC)
;
; UPD ID= 3518, SNARK:<6.MONITOR>SCSJSY.MAC.40, 23-Jan-84 23:49:58 by MCLEAN
;FIX TYPO
;
; UPD ID= 3517, SNARK:<6.MONITOR>SCSJSY.MAC.39, 23-Jan-84 23:06:13 by MCLEAN
;FIX PLACES WHERE SC.RLD AND SC.RBF CALLS ARE WRONG
;ALSO MANY OTHER RANDOM FIXES
;
; UPD ID= 3508, SNARK:<6.MONITOR>SCSJSY.MAC.38, 23-Jan-84 08:49:32 by LOMARTIRE
;More TCO 6.1127 - Use correct AC to store receive credit at SINCIA
;
; UPD ID= 3493, SNARK:<6.MONITOR>SCSJSY.MAC.37, 20-Jan-84 11:12:30 by CDUNN
;More TCO 6.1127 - Fix SCSGDE to user correct interlock in error path (GDEFRK).
;Fix wrong kind of interlock used in error recovery in a number of routines.
;Also update call to SC.LIS to new calling sequence.
;
;UPD ID= 3473, SNARK:<6.MONITOR>SCSJSY.MAC.36, 17-Jan-84 15:36:37 by LOMARTIRE
;More TCO 6.1127 - Place count of datagram buffers in .CBDGJ not .CBDGR
;
;UPD ID= 3470, SNARK:<6.MONITOR>SCSJSY.MAC.35, 16-Jan-84 15:23:42 by LOMARTIRE
;More TCO 6.1127 - Use correct AC when getting next BSD at GUBTNB
;
; UPD ID= 3303, SNARK:<6.MONITOR>SCSJSY.MAC.34, 13-Dec-83 13:17:01 by CDUNN
;More TCO 6.1127 - Fix random bugs in SCSMAP and DMA support in general
;
; UPD ID= 3256, SNARK:<6.MONITOR>SCSJSY.MAC.33, 5-Dec-83 19:28:14 by CDUNN
;More TCO 6.1127 - Fix SCSRDG/SCSRMG to better test addresses handed to SCA.
;Force SCSLUB to zero the forward link of the last entry in the user buffer
;database. Add the code to support the maintainace data transfer functions.
;
; UPD ID= 3186, SNARK:<6.MONITOR>SCSJSY.MAC.32, 17-Nov-83 16:20:20 by CDUNN
;More TCO 6.1127 - Remove all code supporting the mapping if user data into
;monitor space for packet sends. Do the copy instead.
;
; UPD ID= 3138, SNARK:<6.MONITOR>SCSJSY.MAC.31, 11-Nov-83 10:47:49 by CDUNN
;More TCO 6.1127 - Fix confusion over interlocks in SCSRDG
;
; UPD ID= 2855, SNARK:<6.MONITOR>SCSJSY.MAC.30, 22-Aug-83 13:55:04 by CDUNN
;More TCO 6.1127 - Fix get a datagram (SCSRDG) to offset to user text before
;doing the BLT. Also some random fixes for bad AC usage in calculating packet
;lengths.
;
; UPD ID= 2825, SNARK:<6.MONITOR>SCSJSY.MAC.29, 11-Aug-83 15:33:36 by CDUNN
;More TCO 6.1127 Pass 2 on code cleanup. More CION/CIOFF fixes as well as
;general bug fixes.
;
; UPD ID= 2742, SNARK:<6.MONITOR>SCSJSY.MAC.28, 22-Jul-83 15:20:22 by CDUNN
;More TCO 6.1127 - Do all kinds of code cleanup and beefed up error recovery.
;Also remove all cases of CIOFF appearing in swapable code... Change CIOFF
;to be a routine accessable to the whole world
;
; UPD ID= 2610, SNARK:<6.MONITOR>SCSJSY.MAC.27, 20-Jun-83 17:09:50 by HALL
;TCO 6.1689 - Move fork tables to extended section
; Reference FKPGS and FKINT via DEFSTR
;
; UPD ID= 2557, SNARK:<6.MONITOR>SCSJSY.MAC.26, 3-Jun-83 17:14:58 by CDUNN
;More TCO 6.1127 - Fix returns from JSYS interrupt routines...
;
; UPD ID= 2533, SNARK:<6.MONITOR>SCSJSY.MAC.25, 26-May-83 18:11:13 by CDUNN
;More TCO 6.1127 - Set abort in SCSPSI after DISCONNECT has been reported to
;fork.
;
; UPD ID= 2494, SNARK:<6.MONITOR>SCSJSY.MAC.24, 19-May-83 11:15:43 by MURPHY
;Put EPGMAP in extended section.
;
; UPD ID= 2479, SNARK:<6.MONITOR>SCSJSY.MAC.23, 17-May-83 13:16:54 by CDUNN
;More TCO 6.1127 - Fix referances to send datagram and send message argument
;block to use new symbol defs.
;
; UPD ID= 2462, SNARK:<6.MONITOR>SCSJSY.MAC.22, 12-May-83 17:14:50 by CDUNN
;More TCO 6.1127 - Dont try to poke the PSB of a deleted fork.
;
; UPD ID= 2454, SNARK:<6.MONITOR>SCSJSY.MAC.21, 10-May-83 16:48:17 by CDUNN
;More TCO 6.1127 - Change SINMGR and SINDGR to conform to new packer length
;scheme.
;
; UPD ID= 2323, SNARK:<6.MONITOR>SCSJSY.MAC.19, 22-Apr-83 01:40:33 by CDUNN
;More TCO 6.1127 - Add return of packet length to SCSRDG and SCSRMG. Support
;also in SINDGR and SINMGR.
;
; UPD ID= 2301, SNARK:<6.MONITOR>SCSJSY.MAC.18, 18-Apr-83 05:29:37 by GRANT
;TCO 6.1127 - In SCSRCD, add +1 return to CALL LOCPRT
;
; UPD ID= 2253, SNARK:<6.MONITOR>SCSJSY.MAC.17, 12-Apr-83 20:07:39 by CDUNN
;More TCO 6.1127 - Finish SCSMAP
;
; UPD ID= 2172, SNARK:<6.MONITOR>SCSJSY.MAC.16, 6-Apr-83 03:59:45 by CDUNN
;More TCO 6.1127 - Fix PSIBER to observe the entry type and use the correct
;space return routine.
;
; UPD ID= 2162, SNARK:<6.MONITOR>SCSJSY.MAC.15, 4-Apr-83 20:51:29 by CDUNN
;More TCO 6.1127 - Change default for PIDBG to be off...
;
; UPD ID= 2138, SNARK:<6.MONITOR>SCSJSY.MAC.14, 3-Apr-83 20:36:26 by CDUNN
;More TCO 6.1127
;1. Add PIRNG to collect info about the CIOFF's and CION's we do.
;2. Add page offset to user address when sending essage or datagrams.
;3. Make the credit thresholds be zero on connect and listen
;4. Fix SCSCON to restore the user arg address before doing user buffer
;stuff...
;
; UPD ID= 2117, SNARK:<6.MONITOR>SCSJSY.MAC.13, 29-Mar-83 17:17:47 by CDUNN
;More TCO 6.1127 - Create SCSCLK to queue interrupts for forks which have
;entries on the SCS work queue. Also remove call to PSIGR from SCSQUE. Make
;SCSQUE zero SCSTIM, and have SCSCLK set SCSTIM to infinite. Also replace
;PION/PIOFF with CION/CIOFF.
;
; UPD ID= 2070, SNARK:<6.MONITOR>SCSJSY.MAC.12, 23-Mar-83 18:57:30 by CDUNN
;More TCO 6.1127 - Make SCSQRD add count of new buffers to CB. Also add
;routine to support DMA functions.
;
; UPD ID= 2057, SNARK:<6.MONITOR>SCSJSY.MAC.11, 22-Mar-83 00:52:02 by CDUNN
;More TCO 6.1127 - Move certain routines into RESCD since they must go
;CIOFF and hence cannot cause page faults. Also fix SCSFUB to do the right
;things with the queue ends. Also fix SCSRMG to return the CID in question
;to the user.
;Make SCSPSI check validity of CID before linking entries
;onto fork queue. Check to see if block still around and if it has abort or
;reap bits set.
;
; UPD ID= 2014, SNARK:<6.MONITOR>SCSJSY.MAC.8, 17-Mar-83 03:13:35 by CDUNN
;More TCO 6.1127 - Correctly handle linking of dont care listeners onto
;fork CB queues.
;
; UPD ID= 1990, SNARK:<6.MONITOR>SCSJSY.MAC.7, 15-Mar-83 02:00:55 by CDUNN
;More TCO 6.1127 - Fix SCSDEQ to use correct address wen deleting last entry
;on a queue while not the target fork.
;Also remove $PION and $PIOFF, replace them with CION and PIOFF
;
; UPD ID= 1956, SNARK:<6.MONITOR>SCSJSY.MAC.6, 10-Mar-83 00:37:59 by CDUNN
;More TCO 6.1127 - TEMPORARILY! turn on RS%SE0 in calls to ASGRES until
;all work is doen in FREE.
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
;OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION 1976, 1985.
;ALL RIGHTS RESERVED.
SEARCH SCAPAR,PROLOG,PHYPAR
TTITLE (SCSJSY,,<- The SCS% JSYS>)
; Note:
; Some abbreviations appear EVERYWHERE in this module. They are:
;
; CB - Connection block
; SB - System block
; SBI - System block index
; CID - Source connect ID
; PPD - Physical port driver
; WQ - Working queue used by SCA to remember flow control messages
; MBZ - Must be zero
; BDT - Buffer descriptor table (xlation for JSYS buffers to monitor buffers)
;
;
EXTERN SC.CSC,SC.ABF,SC.RBF,SBLIST,SC.CRM,CIDTAB
EXTERN SCSTDQ,SCSBDQ,SCSTMQ,SCSBMQ,SCSTEQ,SCSBEQ,SCSTXQ,SCSBXQ
EXTERN SCSTCQ,SCSBCQ,SCSPS0,SCSPS1,SCSTXN,SCSBXN
EXTERN SC.ALD,SC.RLD,SC.RCB,SC.UMP,SC.MAP,SC.SND,SC.REQ
EXTERN SETCPT,RELCPT,SC.ACB,SC.LCB
EXTERN PSIGR
EXTERN FRKTAB,FRKTLN
SUBTTL Table of Contents
; Table of Contents for SCSJSY
;
;
; Section Page
; 1. Init code. . . . . . . . . . . . . . . . . . . . . . . 4
; 2. Entry to JSYS. . . . . . . . . . . . . . . . . . . . . 5
; 3. Function code handlers
; 3.1. Connect (SCSCON). . . . . . . . . . . . . . . 6
; 3.2. Listen (SCSLIS) . . . . . . . . . . . . . . . 7
; 3.3. Receive datagram (SCSRDG) . . . . . . . . . . 8
; 3.4. Read port counters (SCSRPC) . . . . . . . . . 9
; 3.5. Reject (SCSREJ) . . . . . . . . . . . . . . . 10
; 3.6. Disconnect (SCSDIS) . . . . . . . . . . . . . 11
; 3.7. Send message/datagram (SCSSMG/SCSSDG) . . . . 12
; 3.8. Queue mess buffers (SCSQRM) . . . . . . . . . 13
; 3.9. Cancel DG buffers (SCSCRD). . . . . . . . . . 14
; 3.10. Connect state poll (SCSCSP) . . . . . . . . . 15
; 3.11. Return connect data (SCSRCD). . . . . . . . . 16
; 3.12. Status of connect (SCSSTS). . . . . . . . . . 17
; 3.13. Map a buffer (SCSMAP) . . . . . . . . . . . . 18
; 3.14. Unmap a buffer (SCSUMP) . . . . . . . . . . . 19
; 3.15. Send/Request a buffer (SCSSND/SCSREQ) . . . . 20
; 3.16. Maint. data send/rec (SCSMDS/SCSMDR). . . . . 21
; 3.17. Start a remote system . . . . . . . . . . . . 22
; 3.18. Reset a remote system . . . . . . . . . . . . 22
; 3.19. Add interrupt channel (SCSAIC). . . . . . . . 23
; 3.20. Accept connection (SCSACC). . . . . . . . . . 24
; 3.21. Get data queue entry (SCSGDE) . . . . . . . . 25
; 3.22. Get event Q entry (SCSEVT). . . . . . . . . . 26
; 3.23. SCSGLN (Get local node number). . . . . . . . 27
; 3.24. SCSRBS (Return buffer sizes). . . . . . . . . 28
; 4. SCS% error handlers. . . . . . . . . . . . . . . . . . 29
; 4.1. SERIAA (Invalid argument block address) . . . 29
; 4.2. SERIBP (Invalid byte pointer) . . . . . . . . 29
; 5. SCA call handlers
; 5.1. Main entry point. . . . . . . . . . . . . . . 30
; 5.2. SCSONT (Handle online/offline interrupts) . . 30
; 5.3. SINDGR. . . . . . . . . . . . . . . . . . . . 31
; 5.4. SINDMA. . . . . . . . . . . . . . . . . . . . 32
; 5.5. SINMSC. . . . . . . . . . . . . . . . . . . . 33
; 5.6. SINPBC. . . . . . . . . . . . . . . . . . . . 34
; 5.7. SINCTL. . . . . . . . . . . . . . . . . . . . 35
; 5.8. SINCRA. . . . . . . . . . . . . . . . . . . . 36
; 5.9. SINOSD. . . . . . . . . . . . . . . . . . . . 37
; 5.10. SINRID. . . . . . . . . . . . . . . . . . . . 38
; 5.11. SINCIA. . . . . . . . . . . . . . . . . . . . 39
; 5.12. SINPSC. . . . . . . . . . . . . . . . . . . . 40
; 5.13. SINLCL. . . . . . . . . . . . . . . . . . . . 41
; 5.14. SINNWO. . . . . . . . . . . . . . . . . . . . 42
; 6. Support routines
; 6.1. SCSDMU (Data monitor to user) . . . . . . . . 43
; 6.2. SCSRUB (Remove user buffer) . . . . . . . . . 44
; 6.3. SCSSUM (Move string from user to monitor) . . 45
; 6.4. SCSDUM (Move data from user to monitor) . . . 46
; 6.5. SCSCUB (Count user buffers) . . . . . . . . . 47
; 6.6. SCSXUB (Link buffer chain into database). . . 48
; 6.7. SCSUNM (User name move) . . . . . . . . . . . 49
; 6.8. SCSUDM (User connection data move). . . . . . 50
; 6.9. SCSCBI (Connect block data init). . . . . . . 51
; 6.10. SCSABT/SCSRBT (Add/remove bit from table) . . 52
; 6.11. SCSGNB (Get next bit) . . . . . . . . . . . . 53
; 6.12. SCSW2B (Word/bit offset to bit number conv) . 54
; 6.13. SCSAFT (Add fork to table). . . . . . . . . . 55
; 6.14. SCSRFT (Remove fork from table) . . . . . . . 56
; 6.15. SCSGNF (Get next fork). . . . . . . . . . . . 57
; 6.16. SCSQMD (Queue entry on maint. data Q) . . . . 58
; 6.17. SCSDMD (Dequeue maint. data queue entry). . . 59
; 6.18. SCSLFQ (Link packet to front of queue's). . . 60
; 6.19. SCSAER (ASGRES error handler) . . . . . . . . 61
; 6.20. SCSLCB (Link CB onto fork CB queue) . . . . . 62
; 6.21. SCSKIL (Clean up SCS% data on a CLZFF). . . . 63
; 6.22. SCSCBD (JSYS CB data delete). . . . . . . . . 64
; 6.23. SCSGPR (General packet return). . . . . . . . 65
; 6.24. SCSCLK (Clock service routine). . . . . . . . 66
; 6.25. SCSPSI (Add entry to fork queue). . . . . . . 67
; 6.26. SCSQUE (Queue a block for list queueing). . . 68
; 6.27. SCSMBS (Make another BSD) . . . . . . . . . . 69
; 6.28. SCSDEQ (Dequeue a buffer from fork+CB Q's). . 70
; 6.29. SCSLUB (Link on user message buffer addr) . . 71
; 6.30. SCSGUB (Get user buffer address). . . . . . . 72
; 6.31. SCSRET (Return buffer to correct pool). . . . 73
; 7. Storage. . . . . . . . . . . . . . . . . . . . . . . . 74
SUBTTL Init code
RESCD
; This routine initializes the SCS% JSYS SYSAP.
;
SCSINI::BLCAL. (SC.SOA,<<.,SCSONT>>) ;Tell SCA about this address
BUG. (CHK,SCSNOI,SCSJSY,SOFT,<SCSJSY - SCS% cannot receive node online/offline interrupts>,,<
Cause: SCA has told the JSYS SYSAP that there are to many SYSAPs and the JSYS
is not allowed to see online/offline interrupts. The system can run
but many diagnostics will get upset as will anything that uses the
JSYS.
>)
RET ;All done...
SUBTTL Entry to JSYS
SWAPCD
; SCS% JSYS
; T1/ Function code
; T2/ Address of argument block
; SCS%
; return +1: success,
; illegal instruction trap on failure
;
;
; What we do here is rather simple. Get the users function code from users
;T1. Range check the argument, and dispatch to the correct routine to handle
;that function code.
;
.SCS:: MCENT ;Enter monitor context
MOVE T1,CAPENB ;Get the callers enabled capabilities
TXNN T1,<SC%WHL!SC%MNT!SC%NWZ> ;Is he wheel,maintainance, or net wizard
ITERR (SCSNEP) ;Nope, not enough privs
UMOVE T1,T1 ;Get the function code from user T1
CAIL T1,.SSCON ;Lower than lowest???
CAILE T1,.SSLST ;Higher than highest???
ITERR (SCSBFC) ;Out of range, flunk with bad function code
UMOVE T2,T2 ;Get the address of the argument block
CALL @FCNTAB(T1) ;Call the routine to handle the function code
ITERR () ;Fail, passing along the error code
MRETNG ;Return from JSYS country...
SUBTTL Function code handlers -- Connect (SCSCON)
RESCD
; This routine handles the connect function code.
; Check all the args and then setup to do the SC.CON or SC.LIS call.
;Also store the fork number of the fork that opened this connection.
;
; Assumes:
; T1/ Function code
; T2/ User virtual address of arg block
;
; *** Waring ***
; The STKVAR at the top of this routine must have a set of common elements
;with the STKVAR atop SCSLIS. Error recovery routines are shared by these
;two routines and STKVAR locations are used. Hence these offsets must be
;kept in common.
;
SCSCON::SAVEAC <Q1>
STKVAR <SPN,DPN,CID,ERRCOD,STRRET,DATRET,STRADR,DATA,MSGBUF,DGBUF>
MOVE Q1,T2 ;Setup perm AC for user addr of args
SETZM DATA ;Insure null pointer to connection data
SETZM STRADR ;Zero pointer to string storage
XCTU [HRRZ T3,.SQLEN(Q1)] ;Get the first word out of the arg block
ERJMP SERIAA ;Bad address, call the error handler
CAIGE T3,.LBCON ;Is the arg block long enough???
ITERR (SCSBTS) ;Nope, cause an illegal instruction trap
XCTU [HLRE T1,.SQSYS(Q1)] ;Get the SBI word from the users arg block
ERJMP SERIAA ;Handle page fault badness
SKIPL T1 ;Is it negative???
CAILE T1,C%SBLL-1 ; or greater than the largest SBI???
ITERR (SCSISB) ;Bad SBI, fail here...
SKIPN SBLIST(T1) ;Is there a system for this SBI???
ITERR (SCSISB) ;Nope, fail pls...
XCTU [SKIP .SQRCI(Q1)] ;Is the end of the block available too???
ERJMP SERIAA ;Nope, cause an illegal instruction trap
; Move the source name, destination name, and user data into monitor space.
NOINT ;SCSUNM allocated resouces, don't loose them
CALL SCSUNM ;(Q1/T1,T2,T3,T4)Get the source and
;destination names moved.
ITERR (<>,<OKINT>) ;Failed, report error code
MOVEM T1,SPN ;Save the pointer to the source name
MOVEM T2,DPN ; and the pointer to the destination name
MOVEM T3,STRADR ; and the base addr of the free space used
MOVEM T4,STRRET ; and the routine addr to return free space
UMOVE T1,.SQCDT(Q1) ;Get user pointer to connection data
ERJMP LISER1 ;Handle page faults
SKIPN T1 ;Is there any user data pointer???
JRST CONMCN ;No,finished moving data
CALL SCSUDM ;(T1/T1,T2) Move the user data into monitor space
JRST LISERR ;Handle failure please...
MOVEM T1,DATA ;Save the address of the connect data
MOVEM T2,DATRET ; and the addr of the routine to return it
; Here to count the number of buffers desired by the user so we can queue
;them on connect.
CONMCN: SETZM MSGBUF ;Zero the message buffer count
UMOVE T1,.SQAMC(Q1) ;Get user pointer to initial message buffers
ERJMP LISER1 ;Handle nastygram page faults
JUMPE T1,CONDGC ;ANY MESSAGES? (IF ZERO GO TRY DATAGRAMS)
MOVX T2,C%MGSZ ;YES. Get the size of the message buffers
CALL SCSCUB ;(T1,T2/T1,T2,T3)Count number of buffer and
;check intergrity
JRST LISERR ;Handle a bad buffer chain
MOVEM T3,MSGBUF ;Store number of buffers on the chain
CONDGC: SETZM DGBUF ;Zero the datagram count
UMOVE T1,.SQADC(Q1) ;Get user pointer to initial datagram buffers
ERJMP LISER1 ;Handle bad addresses
SKIPN T1 ;Are there any datagram buffers to count???
JRST CONCAL ;No, do the connect call
MOVX T2,C%DGSZ ;Get the size of the buffers
CALL SCSCUB ;(T1,T2/T1,T2,T3)Count and check the buffer
;chain
JRST LISERR ;Handle a bad chain
MOVEM T3,DGBUF ;Save the count of buffers
; Here when we are ready to do the connect call
CONCAL: UMOVE T2,.SQSYS(Q1) ;Get the system word from the block
ERJMP LISER1 ;Handle page fault badness
HLRZM T2,T3 ;Move the SBI to its own AC
HRRZS T2 ;Be sure the CID bits are in their own AC
CIOFF ;Don't allow packet processing until after
; CB has been filled with JSYS data.
;THIS IS NECESSARY
;BECAUSE JSYS DATA IS IN CB AND A CONNECTION-
;RESPONSE ( WITH NO MATCH) MAY HAPPEN BEFORE
;THE CBFJSY FLAG IS SET IN THE CB. CIOFF ALSO
;GOES NOSKED.
BLCAL. (SC.CON,<SPN,DPN,T3,[5],[0],<.,SCSINT>,T2,DATA,MSGBUF,DGBUF>)
IFNSK.
CION ;Allow other processes again
JRST LISERR ; and handle call failure
ENDIF.
UMOVEM T1,.SQRCI(Q1) ;Return the connect ID
ERJMP CONERR ;Handle write locked pages and friends
MOVEM T1,CID ;Save the returned connect ID
SKIPE T1,DATA ;Get the address of the connection data
CALL @DATRET ;If there was any, return its space
MOVE T1,STRADR ;Get the address of the string space
CALL @STRRET ;Return the space the process names live in
; Here to store needed info about the fork and job in the CB
$LDCID P1,CID ;Load the CB address
CALL SCSCBI ;(P1/)Init the connect block with JSYS data
CALL SCSLCB ;(P1/)Link this CB onto my fork CB queue
CION ;Allow other processes again
; Here to store data about the users queued buffers.
SKIPN MSGBUF ;Are there any message buffer to handle???
JRST CONDGB ;No, go try for datagrams
UMOVE T1,.SQAMC(Q1) ;Get user pointer to initial message buffers
ERJMP LISER1 ;Handle nastrygram page faults
MOVX T2,.BDFMG ;Put it on the message buffer list
CALL SCSXUB ;(T1,T2,P1/P1) Link this chain of buffer
;into database
JRST LISERR ;Handle chain badness
CONDGB: SKIPN DGBUF ;Are there any datagram buffers to queue???
JRST CONSPC ;No, return
UMOVE T1,.SQADC(Q1) ;Get user pointer to arg block address
ERJMP LISER1 ;Handle bad arg block address
MOVX T2,.BDFDG ;Point buffers to the datagram queue
CALL SCSXUB ;(T1,T2,P1/P1) Link datagram chain into
;database please
JRST LISERR ;Report failure
CONSPC: OKINT ;Allow interrupts again
RETSKP ;All done, return
; Here when we have to go OKSKED before joining common error recovery code.
;We ERJMP here.
CONERR: CION ;Allow other processes again
JRST LISER1 ; and join the common error handler
ENDSV.
SUBTTL Function code handlers -- Listen (SCSLIS)
; This routine handles the listen function code...
;
; Expects:
; T2/ User addr of arg block
;
; *** Waring ***
; The STKVAR at the top of this routine must have a set of common elements
;with the STKVAR atop SCSCON. Error recovery routines are shared by these
;two routines and STKVAR locations are used. Hence these offsets must be
;kept in common.
;
SCSLIS::SAVEAC <Q1>
STKVAR <SPN,DPN,CID,ERRCOD,STRRET,DATRET,STRADR,DATA,MSGBUF,DGBUF>
MOVE Q1,T2 ;Setup perm AC with addr of user args
XCTU [HRRZ T3,.SQLEN(Q1)] ;Get the first word out of the arg block
ERJMP SERIAA ;Bad address, call the error handler
CAIGE T3,.LBLIS ;Is the arg block long enough???
ITERR (SCSBTS) ;Nope, cause an illegal instruction trap
XCTU [SKIP .SQLCI(Q1)] ;Is the end of the block available too???
ERJMP SERIAA ;Nope, cause an illegal instruction trap
XCTU [HLRE T1,.SQSYS(Q1)] ;Get the SBI we want to talk to
ERJMP SERIAA ;Handle bad page faults
CAME T1,[-1] ;If -1 its ok, its a don't care
CAIG T1,C%SBLL-1 ;Is it within range???
$SKIP ;Yes, go on...
ITERR (SCSISB) ;Not good, fail wth bad SBI pls...
SKIPN SBLIST(T1) ;Is there an entry for this SBI???
ITERR (SCSISB) ;No, fail with bad SBI
; Addresses look OK. Start moving data so SCA can get at it.
SETZM DATA ;Insure null pointer to connection data
SETZM STRADR ;Init the STRADR code
; Move the source name, destination name, and user data into monitor space.
NOINT ;SCSUNM allocates free space, don't loose it
CALL SCSUNM ;(Q1/T1,T2,T3,T4)Move user process names
;into monitor space.
ITERR (<>,<OKINT>) ;Return failure
MOVEM T1,SPN ;Save the address of the source name
MOVEM T2,DPN ;Save the address of the destination name
MOVEM T3,STRADR ;Save the address of the user free space
MOVEM T4,STRRET ; and the address of the routine to return it
; Here when we are ready to make the call.
UMOVE T2,.SQSYS(Q1) ;Get the system word from the block
ERJMP LISER1 ;Handle bad addresses
HLRE T3,T2 ;Move the SBI to its own AC
HRRZS T2 ;Be sure the CID bits are in their own AC
CIOFF ;Don't allow packet processing until after
; CB has been filled with JSYS data.
;THIS IS NECESSARY
;BECAUSE JSYS DATA IS IN CB AND A CONNECTION-
;RESPONSE ( WITH NO MATCH) MAY HAPPEN BEFORE
;THE CBFJSY FLAG IS SET IN THE CB. CIOFF ALSO
;GOES NOSKED.
BLCAL. (SC.LIS,<SPN,DPN,T3,<.,SCSINT>,T2,[0],[0]>)
JRST LISERR ;Handle failing SCA calls
UMOVEM T1,.SQLCI(Q1) ;Return the connect ID
ERJMP [CION
JRST LISER1] ;Handle write locked pages and friends
MOVEM T1,CID ;Save the connect ID
MOVE T1,STRADR ;Get the address of the string space
CALL @STRRET ;Return it
; Here to store needed data about the fork and job in the CB
;Also link the CB onto fork's CB queue
$LDCID P1,CID ;Get the CB address from the CID
CALL SCSCBI ;(P1) Init the connect block please
CALL SCSLCB ;(P1) Link this new CB onto fork CB queue
CION
OKINT ;Allow user interrupts again
RETSKP ;All done, return
; Here on failure.
;
; LISERR
; T1/ Error code
;
; LISER1
; No error code, failure is bad page access
;
LISER1: MOVX T1,SCSIAB ;Get the appropriate error code
LISERR: MOVEM T1,ERRCOD ;Save the error code
SKIPE T1,STRADR ;Is there any string space to return???
CALL @STRRET ;Yes, call the routine to return it
SKIPE T1,DATA ;Is there any connection data to return
CALL @DATRET ;Yes, return the space it came in
OKINT ;Allow user interrupts again
MOVE T1,ERRCOD ;Get the error code back
ITERR () ;Return failure
ENDSV.
SUBTTL Function code handlers -- Receive DG/MSG (SCSRDG/SCSRMG)
SWAPCD
; This routine handles the receive datagram/message function codes.
;
; Expects:
; T2/ User addr of arg block
;
SCSRDG::TDZA T1,T1 ;Indicate we are doing datagrams
SCSRMG::SETO T1, ;Indicate we are doing messages
SAVEAC <Q1,Q2,P1>
STKVAR <PAKADR,USRBUF,CID,MSGFLG,ERRCOD,LEN>
MOVEM T1,MSGFLG ;Remember how we entered this routine
MOVE Q1,T2 ;Put users addr of args in perm AC
XMOVEI Q2,MSG ;Assume we are doing messages
SKIPN MSGFLG ;A good assumption???
XMOVEI Q2,DG ;No, get the addr of the datagram header block
SETZM USRBUF ;Be sure these are zero inited since error
SETZM PAKADR ; recovery expects zero if unused
UMOVE T1,.SQLEN(Q1) ;Get the length of the block provided
ERJMP SERIAA ;Handle bad page faults
CAIGE T1,.LBRDG ;Is the block long enough to return all data in
ITERR (SCSBTS) ;No, fail with block to short
UMOVE T1,.SQCID(Q1) ;Get the connect ID from arg block
ERJMP SERIAA ;Handle bad addresses
NOINT ;Interlock the fork datagram queue
CAMN T1,[-1] ;Do we want first for fork or connection???
IFNSK.
SKIPN T1,@.TOPFQ(Q2) ;Is there a packet waiting for this fork???
ITERR (SCSQIE,<OKINT>);No, fail with queue is empty
LOAD P1,MECID,(T1) ;Get the destination connect ID
UMOVEM P1,.SQCID(Q1) ;Return it to user right away
ERJMP SERIA0 ;BAD ADDRESS
MOVEM T1,CID ;Save connect ID of the packet we found
$LDCID P1,P1 ;Turn connect ID into a CB address
ELSE.
CALL SC.CSC ;(T1/T1,P1)Sanity check the connect ID
ITERR (SCSIID,<OKINT>) ;Nope, not a good one, fail now pls...
SKIPN T1,@.TOPCQ(Q2) ;Are there datagrams queued for this connect???
ITERR (SCSQIE,<OKINT>) ;Nothing on the queue, fail with queue empty
ENDIF.
; Here with:
; T1/ Address of desired packet buffer
; Q1/ Address of user arguments
; Q2/ Address of 4 word header block pointing to list headers
; P1/ Address of connect block
;
SKIPG @.JBUFF(Q2) ;Are there datagram buffers queued???
IFNSK.
MOVX T1,SCSNMQ ;Assume we are doing messages
SKIPN MSGFLG ;Good assumption???
MOVX T1,SCSNDQ ;No, show error code for datagrams
ITERR (<>,<OKINT>) ;Now, fail with correct error code
ENDIF.
MOVEM T1,PAKADR ;Save the monitor address of the DG
MOVE T2,Q2 ;Point to the datagram list pointers
CALL SCSDEQ ;(T1,T2,P1/T1)Dequeue the buffer from
;the fork and CB queues
ITERR (<>,<OKINT>) ;RETURN ERROR
MOVX T1,.BDFMG ;Assume we are doing messages
SKIPN MSGFLG ;A good assumption???
MOVX T1,.BDFDG ;No, point at datagrams instead
CALL SCSGUB ;(T1,P1/T1,P1)Get a user datagram buffer address
JRST RDGERR ;Handle the buffer we need to return
MOVEM T1,USRBUF ;Store user buffer addr
UMOVEM T1,.SQARB(Q1) ;Return the address of the DG data
ERJMP RDGER1 ;Handle this particular write error
MOVE T4,PAKADR ;Addr of datagram in monitor space
LOAD T1,MELEN,(T4) ;Get the length of the datagram
MOVX T2,F.SPM ;Get the high density flag
TDNE T2,.METYP(T4) ;Is this a high density packet???
SUBI T1,.MHLNW ;Yes, account for the packet header
TDNN T2,.METYP(T4) ;Is this an industry compatable packet???
SUBI T1,.MHLNB ;Yes, account for the packet header
MOVEM T1,LEN ;Save the corrected length of the packet
UMOVEM T1,.SQLRP(Q1) ;Tell user how long the datagram is
ERJMP RDGER1 ;Handle write locked user pages and such
TDNN T2,.METYP(T4) ;Is this an industry compatable mode packet???
IFNSK.
MOVEI T1,3(T1) ;Yes, round up to next nearest word
IDIVI T1,4 ;Word count = Byte count/4
MOVE T2,LEN ;Get the corrected length of the packet
IDIVI T2,4 ;Convert from bytes to words
JUMPE T3,RDGNOB ;If even conversion, no bytes to zero
; Here to zero extra bytes in same word as last valid data byte
ADD T2,PAKADR ;Offset to the packet
ADDI T2,.MHUDA ;Now offset to user data area
SUBI T3,4 ;Get number of bytes to zero from
MOVMS T3 ; the number of extra valid data bytes
IMULI T3,^D8 ;Convert from bytes to bits
ADDI T3,4 ;Account for the low order bits
MOVNS T3 ;We want a shift right
MOVE T4,(T2) ;Get the word in question
LSH T4,(T3) ;Shoft out the undesirable bits
MOVMS T3 ;Now we want a shift left
LSH T4,(T3) ;Restore bit position of the word
MOVEM T4,(T2) ;Put the word back into the packet
ENDIF.
RDGNOB: MOVE T2,PAKADR ;Get the source address
ADDI T2,.MHUDA ;Don't move SCA/PPD headers
MOVE T3,USRBUF ;Get the address of te users buffer
CALL SCSDMU ;(T1,T2,T3/)Move the data to user space
JRST RDGERR ;Handle data move error
MOVX T1,.SQDFL ;Get the number of words processed
XCTU [HRLM T1,.SQLEN(Q1)] ;Return the number of words processed
ERJMP RDGER1 ;Handle bad addresses, write locked pages, etc.
MOVE T1,PAKADR ;Get the datagram buffer address again
LOAD T3,MEFLG,(T1) ;Get the flags from the entry
XCTU [HRLM T3,.SQDFL(Q1)] ;Return the flags
ERJMP RDGER1 ;Handle nasty page faults
SKIPN MSGFLG ;Are we doing messages???
CALL SC.RLD ;No, return the datagram buffer
SKIPE MSGFLG ;Are we doing datagrams???
CALL SC.RBF ;No, return the message buffer
LOAD T2,CBDNOD,(P1) ;Now get the remote node number for this
XCTU [HRRM T2,.SQDFL(Q1)] ;Store node number for the user
ERJMP SERIA0 ;Handle a bad address
OKINT
RETSKP ; and return all happy
; Here when an ERJMP takes. In this case we have a user datagram address that
;needs to be placed back into the database and a datagram that should be
;linked back onto the FRONT of the fork and connection datagram queues.
;
;Note:
;
; It is assumed that we are NOINT when we get here...
;
; Expects:
; P1/ CB addr
; USRBUF/ User virtual address that goes back into database or zero
; PAKADR/ Monitor virtual address of datagram buffer or zero
;
RDGER1: MOVX T1,SCSIAB ;Fill in the error code for bad address
RDGERR: MOVEM T1,ERRCOD ;Save the error code
SKIPN T1,USRBUF ;Is there a user buffer to worry about???
JRST RDGER2 ;No, try for the packet
MOVX T2,.BDFMG ;Assume we are doing messages
SKIPN MSGFLG ;A good assumption???
MOVX T2,.BDFDG ;No, get BSD offset for datagrams
CALL SCSLUB ;(T1,T2,P1) Link this user address back into database
IFNSK.
MOVE T2,FORKX ;Say who we are
MOVE T3,USRBUF ; and what buffer we tried for
BUG. (INF,SCSUBL,SCSJSY,SOFT,<SCSJSY - User buffer lost during error recovery>,<<T1,ERRCOD>,<T2,CURFRK>,<T3,BUFADR>>,<
Cause: Bad access to user memory or a failing routine caused SCS to try to
place the currently owned user buffer back on the buffer list. The
attempt failed and the buffer address has been lost. Note that there
is no memory loss, the monitor has just forgotten one user buffer
address.
DATA: ERRCOD - Erro code
CURFRK - Current fork
BUFADR - Buffer address
>);End of BUG. SCSUBL
ENDIF. ;Fall into packet return code please...
; Here to return the packet (if we have one)
RDGER2: SKIPN T1,PAKADR ;Do we have a packet to return???
JRST RDGER3 ;No, exit please
MOVE T2,Q2 ;Point to the 4 word list header block
CALL SCSLFQ ;(T1,T2,P1)Link this packet onto the front
;of the q's. Returns +1 always.
JFCL 0
; Here for the final exit
RDGER3: OKINT ;Allow user interrupts again
MOVE T1,ERRCOD ;Get the error code back
ITERR () ;Now yell at the user
ENDSV.
SUBTTL Function code handlers -- Read port counters (SCSRPC)
SWAPCD
; This routine handles the read port counters function code.
;
SCSRPC::RET
SUBTTL Function code handlers -- Reject (SCSREJ)
; This routine handles the reject function code.
;
; Expects:
; T2/ User address of arg block
;
SCSREJ::MOVE Q1,T2 ;Save the address of the user args
UMOVE T1,.SQLEN(Q1) ;Get the length word from the user args
ERJMP SERIAA ;Handle an address that doesn't exist
HRRZS T1 ;Get just the length part
CAIGE T1,.LBREJ ;Is the block long enough for all args???
ITERR (SCSBTS) ;Nope, fail with block to short
UMOVE T1,.SQCID(Q1) ;Get the CID from the user
ERJMP SERIAA ;Handle bad page faults
NOINT
CALL SC.CSC ;(T1/T1,P1)Is it a valid CID???
ITERR (<>,<OKINT>) ;Nope, die with invalid CID
UMOVE T2,.SQREJ(Q1) ;Get the reject reasons form the user
ERJMP SERIA0 ;Handle the address not being there
BLCAL. (SC.REJ,<T1,T2>) ;Do the reject pls...
ITERR (<>,<OKINT>) ;Fail with code from SCA
CALL SCSCBD ;(P1)All done with connect, delete JSYS data
OKINT ;Allow user interrupts again
RETSKP ;Return OK
SUBTTL Function code handlers -- Disconnect (SCSDIS)
; This routine handles the disconnect function code.
;
; Expects:
; T2/ User virtual address of arguments
;
SCSDIS::MOVE Q1,T2 ;Save the user address of args
UMOVE T1,.SQLEN(Q1) ;Get the length word
ERJMP SERIAA ;Handle the address not being there
HRRZS T1 ;Get just the length part
CAIGE T1,.LBDIS ;Is the block long enough
ITERR (SCSBTS) ;Nope, fail JSYS call with block to short
UMOVE T1,.SQCID(Q1) ;Get the CID from the user
ERJMP SERIAA ;Handle the address not being there
NOINT
CALL SC.CSC ;(T1/T1,P1)Is this a valid CID???
ITERR (<>,<OKINT>) ;Nope, fail with bad CID
LOAD T1,CBFORK,(P1) ;GET THE FORK NUMBER IN CB.
CALL FRKCHK ;DOES THIS FORK OWN IT?
ITERR (<>,<OKINT>) ;NO.
UMOVE T1,.SQCID(Q1) ;GET CID AGAIN.
UMOVE T2,.SQDIS(Q1) ;Get the disconnect reasons from the user
ERJMP SERIA0 ;Handle that address not being there
BLCAL. (SC.DIS,<T1,T2>) ;Do the disconnect
ITERR (<>,<OKINT>) ;Fail with code form SCA
CALL SCSCBD ;(P1/) All done with JSYS data, release it
OKINT ;Allow user interrupts again
RETSKP ;Succeed
SUBTTL Function code handlers -- Send message/datagram (SCSSMG/SCSSDG)
SWAPCD
; Routine to send a message/datagram.
;
; Expects:
; T2/ User address of args
;
SCSSDG::TDZA T1,T1 ;Indicate we are doing datagrams
SCSSMG::SETO T1, ;Indicate we are doing messages
SAVEAC <Q1,P1>
STKVAR <BUFADR,CID,MSGFLG,ERRCOD>
MOVEM T1,MSGFLG ;Save the entry point indicator
SETZM BUFADR ;Init the buffer address as zero
MOVE Q1,T2 ;Save the user address of the ARGUMENT BLOCK
XCTU [HRRZ T1,.SQLEN(Q1)] ;Get the length word from the block
ERJMP SERIAA ;Handle nasty page faults
CAIGE T1,.LBSDG ;Is the block long enough???
ITERR (SCSBTS) ;No, fail with block to short
XCTU [SKIP .SQFLG(Q1)] ;Touch the last word in the block
ERJMP SERIAA ;Handle case of block overflows to bad page
NOINT ;Insure no change of CID
UMOVE T1,.SQCID(Q1) ;Get the connect ID
ERJMP SDGER1 ;Handle bad addresses
CALL SC.CSC ;(T1/T1,P1)Is the ID ok???
ITERR (<>,<OKINT>) ;No, fail with invalid ID
MOVEM T1,CID ;Stash the connect ID for later
MOVX T1,1 ;We wish one packet buffer please
SKIPN MSGFLG ;Are we doing messages???
IFNSK.
CALL SC.ALD ;Get a monitor buffer for the data
ITERR (<>,<OKINT>) ;No buffer available, fail here
MOVX T2,JH%DGB ;Get the datagram buffer bit
IORM T2,.JHFLG(T1) ;Light the datagram flag in packet
ELSE.
CALL SC.ABF ;Get a monitor buffer for the data
ITERR (<>,<OKINT>) ;None available, fail please
MOVX T2,JH%DGB ;Get the datagram buffer flag
ANDCAM T2,.JHFLG(T1) ;Zero the datagram flag in the JSYS header
ENDIF.
MOVEM T1,BUFADR ;Save the buffer address
UMOVE T2,.SQAPT(Q1) ;Get the user address of the packet text
ERJMP SDGER1 ;Ooops, back out gracfully please
MOVEM T2,.JHAUB(T1) ;Store the address of the user buffer
UMOVE T1,.SQLPT(Q1) ;Get the length of the packet text
ERJMP SDGER1 ;Bad address? Back out pls...
UMOVE T2,.SQFLG(Q1) ;Get the flags word from user space
ERJMP SDGER1 ;Handle bad user addresses
TXNN T2,SC%MOD ;Is this a high density packet???
IFNSK.
ADDI T1,3 ;Round up byte count
IDIVI T1,4 ;Yes, turn the byte count into a word count
ENDIF.
MOVX T3,<C%MGSZ-.MHUDA> ;Assume messages
SKIPN MSGFLG ;A good assumption???
MOVX T3,<C%DGSZ-.MHUDA> ;No, get the size for datagrams
CAMLE T1,T3 ;Is the text too long???
IFNSK.
MOVX T1,SCAPTL ;Yes, get the appropriate error code
JRST SDGERR ; and back out of this routine
ENDIF.
MOVE T3,BUFADR ;Get the address of the monitor buffer
MOVE T2,.JHAUB(T3) ;Get user buffer address again
ADDI T3,.MHUDA ;Offset monitor space text area in buffer
CALL SCSDUM ;(T1,T2,T3) Move the data from user to
;monitor space
JRST SDGERR ;Failed, report error
MOVX T2,F.RTB ;Start with just the return buffer flag
UMOVE T3,.SQFLG(Q1) ;Get the users flag word
ERJMP SDGER1 ;Handle bad addresses
TXNE T3,SC%MOD ;Is a high density packet requested???
TXO T2,F.SPM ;Yes, light flag for SCA
LOAD T3,SC%OPS,T3 ;Now keep just the optional path spec
CAIL T3,.SSLOW ;Path spec too low???
CAILE T3,.SSHGH ; or too high???
IFNSK.
MOVX T1,SCSIPS ;Yes, fail with invalid path spec.
JRST SDGERR ;. . .
ENDIF.
UMOVE T4,.SQLPT(Q1) ;Get the length of the packet text from user
ERJMP SDGER1 ;Handle a bad address
SKIPN MSGFLG ;Are we doing messages???
IFNSK.
BLCAL. (SC.SDG,<CID,T2,T4,BUFADR,[SCSPRI],T3>) ;Have SCA send the datagram
JRST SDGERR ;Fail with code from SCA
ELSE.
BLCAL. (SC.SMG,<CID,T2,T4,BUFADR,[SCSPRI],[0],T3>) ;Have SCA send message
JRST SDGERR ;Fail with code from SCA
ENDIF.
OKINT ;Allow user interrpts again
RETSKP ;All done...
; Here when an ERJMP takes or when we get a non-skip return from a routine.
;
; Usage:
; SDGERR -- Here when we have an error code
;
; SDGER1 -- ERJMP here on a user address error. We must fill in the error
; code...
;
SDGER1: MOVX T1,SCSIAB ;Get the correct error code for address error
SDGERR: MOVEM T1,ERRCOD ;Save the error code
SKIPN T1,BUFADR ;Is there a buffer owned???
JRST SDGER2 ;No, exit please
SKIPN MSGFLG ;Datagram?
CALL SC.RLD ;Return the buffer to the SCA free pool
SKIPE MSGFLG ;Message?
CALL SC.RBF ;Yes return the message buffer
SDGER2: OKINT ;Allow interrupts again
MOVE T1,ERRCOD ;Put the error code where it belongs
ITERR () ; and fail please
ENDSV.
SUBTTL Function code handlers -- Queue mess buffers (SCSQRM)
SWAPCD
; This routine handles the queue receive message buffers function code.
;
; Assumes:
; T2/ User virtual address of arg block
;
SCSQRD::TDZA T1,T1 ;Set the flag that says we are in datagram code
SCSQRM::SETO T1, ;Claim that we are in message code
STKVAR <QRMFLG,CID>
MOVEM T1,QRMFLG ;Save message/datagram queue flag
MOVE Q1,T2 ;Set up perm AC for user arg block addr
UMOVE T1,.SQLEN(Q1) ;Get the length of the users arg block
ERJMP SERIAA ;Handle nasty page faults in the monitor
HRRZS T1 ;Get just the length part
CAIGE T1,.LBQRM ;Is the block long enough???
ITERR (SCSBTS) ;No, fail on block to short
XCTU [SKIP .SQAFB(Q1)] ;Is the end of the block touchable???
ERJMP SERIAA ;No, handle the nasty page fault
UMOVE T1,.SQCID(Q1) ;Get the connect ID from the user
ERJMP SERIAA ;Handle bad addresses
NOINT
CALL SC.CSC ;(T1,T1,P1)Sanity check the connect ID
ITERR (<>,<OKINT>) ;Bad CID, fail pls...
MOVEM T1,CID ;Save the CID for later please
UMOVE T1,.SQAFB(Q1) ;Get the address of the first buffer
MOVX T2,C%MGSZ ;Assume message buffers
SKIPN QRMFLG ;A good assumption???
MOVX T2,C%DGSZ ;No, get the size for datagrams
CALL SCSCUB ;(T1,T2/T1,T2,T3) Count buffer in chain and
;check for good chain
ITERR (<>,OKINT) ;Fail with bad pointer
; Here to start looping over buffers and adding them to the BSD for this
;connection.
UMOVE Q1,.SQAFB(Q1) ;Get the user addr of a buffer
ERJMP SERIA0 ;Handle bad addresses
SETZM Q2 ;Zero the count of buffers queued
QRMBLP: AOS Q2 ;Increment count of buffers
MOVE T1,Q1 ;Get user buffer address
MOVX T2,.BDFMG ;Assume its a message
SKIPN QRMFLG ;Was this a good assumption???
MOVX T2,.BDFDG ;No, this is a datagram buffer queueing
CALL SCSLUB ;(T1,T2,P1) Link this buffer addr into database
ITERR (<>,<OKINT>) ;Handle errors from below
XCTU [MOVE Q1,(Q1)] ;Try for the next buffer
ERJMP SERIA0 ;Hmm, handle errors touching bad address
SKIPE Q1 ;If zero we have reached the end of our rope
JRST QRMBLP ;Else loop for more buffer on the chain
; Here when the buffer addresses have all been recorded and we can queue some
;real buffers.
;
SKIPN QRMFLG ;Are we in datagram code???
JRST QRMQDG ;Yes, do datagram queue
BLCAL. (SC.RMG,<CID,Q2,[0]>) ;Queue buffer for this connection
ITERR (<>,<OKINT>) ;Fail with error code from SCA
OKINT ;Allow interrupts again
RETSKP ; or return success
QRMQDG: BLCAL. (SC.RDG,<CID,Q2,[0]>) ;Queue datagram buffers for this connect
ITERR (<>,<OKINT>) ;Fail with error code from SCA
OKINT ;Allow interrupts again
RETSKP ; and return
ENDSV.
SUBTTL Function code handlers -- Cancel DG/MSG buffers (SCSCRD/SCSCRM)
; This routine handles the cancel datagram buffers function code.
;
SCSCRM::TDZA T1,T1 ;Show we are no doing datagrams
SCSCRD::SETO T1, ;Show we are doing datagrams
STKVAR <CRDFLG,CID>
MOVEM T1,CRDFLG ;Save the state of the datagram code flag
MOVE Q1,T2 ;Save the address of the user buffer
UMOVE T2,.SQLEN(Q1) ;Get the users first word of arg block
ERJMP SERIAA ;Handle a bad address
HRRZS T2 ;Get just the length part
CAIGE T2,.LBCRD ;Is the block long enough???
ITERR (SCSBTS) ;Bomb with block to short
XCTU [SKIP .SQADB(Q1)] ;Can we get to the whole arg block???
ERJMP SERIAA ;Nope, die on a bad address
UMOVE T1,.SQCID(Q1) ;Get the CID
ERJMP SERIAA ;Handle nasty page faults
NOINT
CALL SC.CSC ;(T1/T1,P1)Is there such a thing???
ITERR (<>,<OKINT>) ;Nope, tell the user we dont like this CID
MOVEM T1,CID ;Save the connect ID
UMOVE T1,.SQADB(Q1) ;Get the addr of the user buffer to return
ERJMP SERIA0
CALL SCSRUB ;(T1,T2,P1)Remove the buffer from the database
ITERR (SCSNSB,<OKINT>) ;Return no such buffer
SKIPN CRDFLG ;Are we doing datagrams???
JRST CRDMSG ;No, cancel a message
BLCAL. (SC.CRD,<CID,[1]>) ;Cancel a datagram pls...
ITERR (<>,<OKINT>) ;Fail with code from SCAMPI
SOS .CBDGJ(P1) ;Decrement the JSYS datagram count
OKINT ;Allow user interrupts again
RETSKP ;Else return OK
CRDMSG: BLCAL. (SC.CRM,<CID,[1]>) ;Cancel a message please
ITERR (<>,<OKINT>) ;Fail with code from SCAMPI
OKINT ;Allow user interrupts again
RETSKP ;Else return OK...
ENDSV.
SUBTTL Function code handlers -- Connect state poll (SCSCSP)
; This routine handles the connect state poll function code.
;
SCSCSP::STKVAR <BYTEP>
MOVE Q1,T2 ;Save the user arg block address
UMOVE T1,.SQLEN(Q1) ;Get the length word
ERJMP SERIAA ;Handle nasty page fault from monitor
CAIGE T1,.LBCSP ;Is the block big enough???
ITERR (SCSBTS) ;No, fail with block to small
XCTU [SKIP .SQREA(Q1)] ;Touch the last word in the block
ERJMP SERIAA ;Its not there, complain
UMOVE T1,.SQCID(Q1) ;Get the CID from the users arg block
ERJMP SERIAA ;Handle bad user addresses
NOINT
CALL SC.CSC ;(T1/T1,P1) Sanity check the connect ID
ITERR (<>,<OKINT>) ;Bad connect ID. Fail pls...
LOAD T1,CBCNST,(P1) ;Get the connection state
UMOVEM T1,.SQCST(Q1) ;Store for the user
ERJMP SERIA0 ;Handle bad pages...
LOAD T1,CBDCID,(P1) ;Get the destination CID
UMOVEM T1,.SQDCI(Q1) ;Store this for the user as well
ERJMP SERIA0 ;Handle bad addresses
LOAD T1,CBDNOD,(P1) ;GET THE DESTINATION NODE NUMBER
UMOVEM T1,.SQSBI(Q1) ;STORE IN USERS BLOCK
ERJMP SERIA0 ;HANDLE BAD ADDRESS
LOAD T1,CBSDRE,(P1) ;Get the source disconnect reasons
XCTU [HRLM T1,.SQREA(Q1)] ;Store in users block
ERJMP SERIA0 ;Handle bad addresses
LOAD T1,CBDDRE,(P1) ;Get the destination disconnect reasons
XCTU [HRRM T1,.SQREA(Q1)] ;Store this as well
ERJMP SERIA0 ;Handle bad addresses
UMOVE T1,.SQBDN(Q1) ;Get the users byte pointer
ERJMP SERIA0 ;Handle bad addresses
SKIPN T1 ;IS THE POINTER ZERO?
IFSKP. ;NO, THEN GET THE NAME.
TLC T1,-1 ;Compliment left half of byte pointer
TLCN T1,-1 ;Is it a generic byte pointer???
HLL T1,[POINT 7,] ;Yes, turn it into a real one
MOVEM T1,BYTEP ;Save the byte pointer for later use
MOVX T4,<POINT 8,.CBDPN(P1)> ;Get a byte pointer to destination name
MOVX T3,C%PNMN ;Get the length of the string
CSPNLP: ILDB T2,T4 ;Get a char
XCTBU [IDPB T2,BYTEP] ;Store a byte of the destination name
ERJMP SERIB0 ;Handle bad byte instructions
SOJG T3,CSPNLP ;Loop for all bytes in the string
MOVE T1,BYTEP ;Get the updated byte pointer
UMOVEM T1,.SQBDN(Q1) ;Update the users byte pointer...
ERJMP SERIA0 ;Handle bad addresses
ENDIF.
OKINT
RETSKP ;Return...
ENDSV.
SUBTTL Function code handlers -- Return connect data (SCSRCD)
; This routine handles the RCD function code.
;
SCSRCD::MOVE Q1,T2 ;Save the address of the user arg block
UMOVE T1,.SQLEN(Q1) ;Get the block length
ERJMP SERIAA ;Handle bad addresses from monitor
CAIGE T1,.LBRCD ;Is it long enough for the job???
ITERR (SCSBTS) ;No, fail on block to short
XCTU [SKIP .SQLPN(Q1)] ;Can we get to the last word???
ERJMP SERIAA ;Nope, handle nasty page faults from monitor
XCTU [MOVE T1,.SQCID(Q1)] ;Is there a CID word in user args???
ERJMP SERIAA ;Handle bad addresses
JUMPE T1,RCDSBI ;No, use the SBI field
NOINT
CALL SC.CSC ;(T1/T1,P1) Sanity check the connect ID
ITERR (<>,<OKINT>) ;Not a good CID, fail
LOAD T1,CBDNOD,(P1) ;Else load the node we are talking about
OKINT
JRST RCDGIN ; and go give the info the world wants
; Here when the SBI field is to be used.
;
RCDSBI: UMOVE T1,.SQOSB(Q1) ;Get the SBI from the arg block
ERJMP SERIAA ;Handle bad addresses
SKIPL T1 ;Is it a negative SBI???
CAILE T1,C%SBLL-1 ;Or within the values of reason
ITERR (SCSISB) ;No, invalid SBI
; Here when we have an SBI in T1 and can start the long march of data into
;Hilbert space...
;
RCDGIN: SKIPN SBLIST(T1) ;Is this a valid SBI???
ITERR (SCSISB) ;Nope, fall over pls...
UMOVEM T1,.SQOSB(Q1) ;Store the SBI for the user
ERJMP SERIAA ;Handle bad addresses
MOVE T1,SBLIST(T1) ;Get the SB addr from the SBI
LOAD T2,SBVCST,(T1) ;Get the virtual circuit state
XCTU [HRLZM T2,.SQVCS(Q1)] ;Store the virtual circuit state for user
ERJMP SERIAA ;Oh nasty user, handle bad arg address
LOAD T2,SBDPA,(T1) ;Load the destination port number
XCTU [HRRM T2,.SQVCS(Q1)] ;Store for user
ERJMP SERIAA ;Handle bad addresses
DMOVE T2,.SBDSS(T1) ;Get the destination system address
XCTU [DMOVEM T2,.SQSAD(Q1)] ;Store
ERJMP SERIAA ;Handle bad arg addresses
LOAD T2,SBMXMG,(T1) ;Get the maximum message size
LOAD T3,SBMXDG,(T1) ; and the max datagram size
XCTU [DMOVEM T2,.SQMDD(Q1)] ;Store in user block
ERJMP SERIAA ;Handle bad argument addresses
DMOVE T2,.SBDST(T1) ;Get the software type and version
XCTU [DMOVEM T2,.SQDST(Q1)] ;Store
ERJMP SERIAA ;Handle bad argument addresses
DMOVE T2,.SBDSE(T1) ;software edit level
XCTU [DMOVEM T2,.SQDSE(Q1)] ;Store it
ERJMP SERIAA ;Handle bad argument addresses
MOVE T2,.SBDHT(T1) ;GET DESTINATION HARDWARE TYPE
UMOVEM T2,.SQDHT(Q1) ;STORE IT
ERJMP SERIAA ;HANDLE BAD ADDRESS
DMOVE T2,.SBDHV(T1) ;GET FIRST 2 WORDS OF HARDWARE VERSION
XCTU [DMOVEM T2,.SQDHV(Q1)] ;STORE THEM
ERJMP SERIAA ;Handle bad argument addresses
MOVE T2,.SBDHV+2(T1) ;GET 3RD WORD OF HARDWARE VERSION
UMOVEM T2,.SQDHV+2(Q1) ;STORE IT
ERJMP SERIAA ;Handle bad argument addresses
DMOVE T2,.SBNNM(T1) ;GET DESTINATION PORT NAME
XCTU [DMOVEM T2,.SQNNM(Q1)] ;GIVE IT TO USER
ERJMP SERIAA ;Handle bad argument addresses
MOVE T2,.SBDPC(T1) ;GET PORT CHARACTERISTICS
UMOVEM T2,.SQPCW(Q1) ;STORE IT
ERJMP SERIAA ;Handle bad argument addresses
MOVX T1,KLPRH2 ;Get the channel number of the KLIPA
UMOVEM T1,.SQLPN(Q1) ;Store for the user
ERJMP SERIAA ;Handle bad argument addresses
RETSKP ;All done
SUBTTL Function code handlers -- Status of connect (SCSSTS)
; This routine handles the quick status function code.
;
SCSSTS::MOVE Q1,T2 ;Save the user address of the user arg block
UMOVE T1,.SQLEN(Q1) ;Get the length word
ERJMP SERIAA ;Handle nasty page faults from monitor
CAIGE T1,.LBSTS ;Is the block long enough???
ITERR (SCSBTS) ;No, fail with block to short
XCTU [SKIP .SQSBR(Q1)] ;Is the whole block available???
ERJMP SERIAA ;No, handle nasty page faults
UMOVE T1,.SQCID(Q1) ;Get the users proposed CID
ERJMP SERIAA ;Handle bad addresses
NOINT
CALL SC.CSC ;(T1/T1,P1) Sanity check the connect ID
ITERR (<>,<OKINT>) ;Fail with invalid connect ID
LOAD T1,CBCNST,(P1) ;Get the connection state
XCTU [HRRZM T1,.SQFST(Q1)] ;Store for the user
ERJMP SERIA0 ;Handle bad argument addresses
LOAD T1,CBDNOD,(P1) ;Get the node number of the remote
XCTU [HRRZM T1,.SQSBR(Q1)] ;Store
ERJMP SERIA0 ;Handle bad argument addresses
SETZ T1, ;Clear a flag AC
SKIPE .CBTMQ(P1) ;Are there any messages pending???
TXO T1,SC%MSA ;Yes, light the messages bit
SKIPE .CBTXQ(P1) ;Is there a data request pending???
TXO T1,SC%DTA ;Yes, light the data available bit
SKIPE .CBTDQ(P1) ;Is there a datagram available???
TXO T1,SC%DGA ;Yes, light the datagram bit
SKIPE .CBTEQ(P1) ;Is there an event pending???
TXO T1,SC%EVA ;Yes, light the event bit
XCTU [ORM T1,.SQFST(Q1)] ;Set the appropriate flag bits
ERJMP SERIA0 ;Handle bad argument addresses
OKINT
RETSKP ;And we are all done
SUBTTL Function code handlers -- Map a buffer (SCSMAP)
SWAPCD
; This routine handles the map a DMA buffer function code.
;
;THE STKVAR ELEMENTS ARE
; USRADR - THE USER SPACE VIRTUAL ADDRESS OF THE JSYS'S ARGUMENT BLOCK
; USRLEN - LENGTH OF THE .SQBLN/.SQBAD PAIRS IN THE JSYS'S ARGUMENT BLOCK
; FBADDR - MONITOR VIRTUAL ADDRESS OF BUFFER FOR THE MAP DESCRIPTOR BLOCK
; THAT IS USED BY MAPBUF.
; PGSTK - MONITOR VIRTUAL ADDRESS OF BUFFER THAT STORES THE USER PAGES
; THAT HAVE BEEN LOCKED FOR THIS TRANSFER. FIRST WORD IS THE
; COUNT OF THE PAGES THAT HAVE BEEN LOCKED.
; ERRCOD -
; MODE - THE FORMATTING MODE THAT HAS BEEN SPECIFIED
; WRDLEN - THE NUMBER OF WORDS NEEDED FOR THE NUMBER OF BYTES
; THAT HAVE BEEN SPECIFIED IN THE JSYS'S ARGUMENT BLOCK.
SCSMAP::STKVAR <USRADR,USRLEN,FBADDR,PGSTK,ERRCOD,MODE,WRDLEN>
SETZM PGSTK ;Clear address of page stack page
MOVEM T2,USRADR ;Save user virtual addr of args
XCTU [HRRZ T1,.SQLEN(T2)] ;Get the length of the arg block
ERJMP SERIAA ;Handle bad user arg address
CAIGE T1,.SQBNA+.SQBAD+2;Is block long enough for return +1 buffer?
ITERR (SCSBTS) ;No, fail with block to short
MOVEI T1,-<.SQBNA+1>(T1) ;Get the user length minus the overhead
MOVEM T1,USRLEN ;Store for later generations
CAILE T1,<C%DGSZ-2>/<.SQBAD+1> ;More segments than we can handle???
ITERR (SCSTMS) ;Yes, fail with to many buffer segments
MOVX T1,1 ;Start with a single buffer
NOINT ;We are getting a resource...
CALL SC.ALD ;(T1/T1,T2,T3) Allocate a dataram buffer FOR
;THE MAP DESCRIPTOR BLOCK.
ITERR (,<OKINT>) ;Fail with resource allocation failure
MOVEM T1,FBADDR ;Store first block address
MOVE Q1,T1 ;Put addr of scratch buffer here for use
; Quick sanity check:
;
; T1-T4 -- Temp since MLKCP will smash them
;
; Q1/ ADDRESS OF THE MAP DESCRIPTOR BLOCK USED BY MAPBUF
; Q2/ Current USER CONTEXT VIRTUAL ADDRESS POINTER TO
; JSYS ARGUMENT BLOCK ENTRY
; Q3/ User CONTEXT VITUAL ADDRESS OF JSYS ARGUMENT BLOCK
;
; P4/ Count of LOCKED pages IN page stack
; P5/ Stack pointer for locked pages stack
;
MOVE Q2,USRADR ;Get the user arg block address again
ADDI Q2,.SQBNA+1 ;Offset into the user block to first desc blk
MOVE Q3,USRADR ;Keep the user arg address here
SETZ P4, ;Zero the page stack counter
UMOVE T1,.SQXFL(Q3) ;Get the users flags
ERJMP MAPER2 ;Bad addr, yell at the user
ANDX T1,MD%FLG ;Keep only the defined flags
TXO T1,SQ%WRT ;Set the writable bit for compatibility with
;the way code in SCAMPI use to work.
MOVEM T1,.MDFLG(Q1) ;Store flags/mode in MAP DESCRIPTOR BLOCK
LOAD T2,MD%DMD,T1 ;Get the buffer mode
CAIE T2,MD%ILL ;Is it the dissallowed value???
IFSKP.
MOVX T1,SCSIDM ;Yes, get the appropriate error code
JRST MAPER1 ; and yell at the user
ENDIF.
MOVEM T2,MODE ;SAVE THE MODE
MOVX T1,1 ;We only desire one buffer pls...
CALL SC.ALD ;Get a datagram buffer pls...
JRST MAPER1 ;Handle failure pls...
MOVEM T1,PGSTK ;Save the base address of the page stack
AOS P5,T1 ;Get the address of the page stack +1
ADDI Q1,.MDSSD ;Offset mon buffer addr to first desc blk
; Top of the loop. Here to check for valid segment length.
;
MAPELP: UMOVE T3,.SQBLN(Q2) ;Length from user block
ERJMP MAPER2 ;Arg block addr was bad, fail
JUMPE T3,MAPCAL ;Zero length, end of block, start the map call
MOVEM T3,.MDLEN(Q1) ;Store length in block for SCA
;CALCULATE NUMBER OF WORDS NEEDED FOR
;THE SPECIFIED NUMBER OF BYTES.
MOVE T1,MODE ;GET THE MODE.
CAIE T1,MD%DIC ;IS IT INDUSTRY COMPATABLE
IFSKP.
LSH T3,-2 ;YES. DIVIDE BY 4 (4 BYTES PER WORD).
ELSE.
LSH T3,1 ;HIGH DENSITY. MULTIPY BY 2/9 (4.5 PER WORD)
IDIVI T3,11
SKIPE T4 ;REMAINDER?
AOS T3 ;YES. ADD ONE TO THE WORD COUNT
ENDIF.
MOVEM T3,WRDLEN ;SAVE THE NUMBER OF WORDS NEEDED.
CAILE T3,PGSIZ ;Is the block not longer than one page???
IFNSK.
MOVEI T1,SCSSTL ;Yes, error code for segment to long
JRST MAPER1 ;Go fail...
ENDIF.
; Here to check for valid address.
;
UMOVE T1,.SQBAD(Q2) ;Get the users segment address
ERJMP MAPER2 ;Bad arg address, handle page fault
XCTU [MOVES (T1)] ;Be sure the page is writable
ERJMP MAPER2 ;Handle bad address here too
XCTU [MAP T1,(T1)] ;Get the physical address from user address
ANDX T1,C%PHAD ;Keep just the address part
MOVE T2,T1 ;Copy of the physical address
ANDI T2,777 ;Keep only the page offset
ADD T2,T3 ;Add the length of the segment
CAIG T2,1000 ;Are we still on the same page???
IFSKP.
MOVX T1,SCSSCP ;No! Get the appropriate error code
JRST MAPER1 ;Die here please...
ENDIF.
MOVEM T1,.MDADR(Q1) ;Store segment address in monitor buffer
LSH T1,^D-9 ;Turn address into page number
PUSH P5,T1 ;Save the page on the page stack
AOS P4 ;Count the page on the stack
CALL MLKCP ;Lock the physical page pls...
ADDI Q1,.MDLSD ;Point Q1 at next descriptor length pair
ADDI Q2,.SQBAD+1 ;Offset to next entry in user space
MOVX T3,-<.SQBAD+1> ;Minus length of one segment descriptor
ADDM T3,USRLEN ;Update the remaining block length
MOVMS T3 ;Get positive length of entry
CAMG T3,USRLEN ;Is there room in user block for another blk?
JRST MAPELP ;Yes, loop for another user block
MAPCAL: MOVEM P4,@PGSTK ;Save the number of pages on the stack
BLCAL. (SC.MAP,<FBADDR>) ;Do the work of mapping the buffer
JRST MAPER1 ;Hmmm, bomb with error code from SCA
MOVE Q1,T1 ;Save the buffer name
MOVE T2,FORKX ;Associate this fork with the buffer
MOVE T3,PGSTK ;Get the base address of the page stack
CALL SCSAXN ;Add the name to the fork's database
JRST MAPER1 ;Handle failure
MOVE T1,FBADDR ;Now the scratch buffer address
CALL SC.RLD ; which get returned as well
OKINT ;Allow user interrupts again
UMOVEM Q1,.SQBNA(Q3) ;Tell user what name we gave him
ERJMP SERIAA ;Handle nasty page faults
RETSKP ;All done
; Here when an ERJMP takes or we get a plus one return from a routine.
;
; MAPERR -- We are NOINT, and FBADDR has the addr of a DG buffer we must
; return to the SCA free pool
; MAPER1 -- As above but we have an error code in T1 and the page stack needs
; to be unwound, also PGSTK must be checked for a DG buffer
; which needs to be returned to SCA free pool
; MAPER2 -- As MAPER1 but no error code in T1
;
MAPER2: MOVX T1,SCSIAB ;Error code for bad addresses
MAPER1: MOVEM T1,ERRCOD ;Save the error code
JUMPE P4,MAPERA ;Anything on the page stack, if not go on...
POP P5,T1 ;Get the physical page number to be unlocked
CALL MULKCR ;Unlock the page please
SOJG P4,.-2 ;More pages to do? If so unlock them...
MAPERA: SKIPE T1,PGSTK ;A page stack DG buffer to be returned???
CALL SC.RLD ;Yes, return it please...
MOVE T1,FBADDR ;Get the address of the scratch DG buffer
CALL SC.RLD ;Resturn it to the SCA free pool
OKINT ;Allow user interrupts again
MOVE T1,ERRCOD ;Get the error code back please
ITERR () ;Yes, use it please...
ENDSV.
SUBTTL Function code handlers -- Unmap a buffer (SCSUMP)
; This routine handles the unmap a buffer function code.
;
SCSUMP::STKVAR <BUFNAM>
XCTU [HRRZ T1,.SQLEN(T2)] ;Get user length of block
ERJMP SERIAA ;Handle nasty page faults
CAIGE T1,.LBUMP ;Is the block long enough???
ITERR (SCSBTS) ;No, fail with block to short
NOINT ;Be sure there are no data alterations
UMOVE T1,.SQNAM(T2) ;Get the users buffer name
ERJMP UMPERR ;Handle addr being bad
MOVEM T1,BUFNAM ;Save the buffer name
MOVE T2,FORKX ;Look for the buffer in current fork
CALL SCSFXN ;See if we have such a buffer name???
ITERR (<>,<OKINT>) ;Fail with appropriate error code please...
BLCAL. (SC.UMP,<T1>) ;Unmap the buffer please
ITERR (<>,<OKINT>) ;Fail with error code from port driver
MOVE T1,BUFNAM ;Get the buffer name back
MOVE T2,FORKX ; and we own it
CALL SCSDXN ;Remove it from the fork database please
ITERR (<>,<OKINT>) ;Failed? Report failure
OKINT ;Allow user interrupts again
RETSKP ;Return OK
; Here on a bad user supplied address
UMPERR: OKINT ;Allow user interrupts again
JRST SERIAA ;Now go handle like any other bad address
ENDSV.
SUBTTL Function code handlers -- Send/Request a buffer (SCSSND/SCSREQ)
; This routine handles the send a buffer, and request a buffer function codes.
;
SCSREQ::TDZA T1,T1 ;Show us in request data code
SCSSND::SETO T1, ;Indicate we want a SEND_DATA
STKVAR <SNDFLG>
MOVEM T1,SNDFLG ;Save code type flag
MOVE Q1,T2 ;Save address of users arg block
XCTU [HRRZ T1,.SQLEN(Q1)] ;Get user arg block length
ERJMP SERIAA ;Handle bad addresses
CAIGE T1,.LBSND ;Is the block long enough???
ITERR (SCSBTS) ;No, fail with block to short
UMOVE T1,.SQCID(Q1) ;Get users CID
ERJMP SERIAA ;Handle bad addresses
NOINT
CALL SC.CSC ;(T1/T1,P1) Is the CID valid???
ITERR (<>,<OKINT>) ;No fail with invalid CID
UMOVE T1,.SQSNM(Q1) ;Name of buffer to send
ERJMP SERIA0 ;Handle bad addresses
UMOVE T3,.SQRNM(Q1) ;Name of receiving buffer
ERJMP SERIA0 ;Handle bad addresses
XCTU [HLRZ T4,.SQOFS(Q1)] ;Xmit offset
ERJMP SERIA0 ;Handle bad addresses
XCTU [HRRZ Q2,.SQOFS(Q1)] ;Receive offset
ERJMP SERIA0 ;Handle bad addresses
SKIPN SNDFLG ;Are we doing a data send???
JRST SNDREQ ;No, do a request data instead
BLCAL. (SC.SND,<<.CBSCI(P1)>,T1,T3,T4,Q2>) ;Send the data
ITERR (<>,<OKINT>) ;Fail with error from SCA
OKINT ;Allow user interrupts again
RETSKP ;Return all well
SNDREQ: BLCAL. (SC.REQ,<<.CBSCI(P1)>,T1,T3,T4,Q2>) ;Request the data
ITERR (<>,<OKINT>) ;Fail with code from SCA
OKINT ;Allow user interrupts again
RETSKP ;Return OK...
ENDSV.
SUBTTL Function code handlers -- Maint. data send/rec (SCSMDS/SCSMDR)
REPEAT 0,<
This function is now performed by the DIAG% JSYS
; This routine handles the sending/receiving of maintainance data.
;
; Expects:
; T2/ User address of arg block
;
SCSMDS::TDZA T1,T1 ;Clear the "receive" flag
SCSMDR::SETO T1, ;Set the "receive" flag
STKVAR <RECFLG,SBA,RESADR,NODNUM>
MOVEM T1,RECFLG ;Save value of the "recieve" flag
MOVE Q1,T2 ;Put user addr of args where it is safe
UMOVE T1,.SQLEN(Q1) ;Get the claimed length of the arg block
ERJMP SERIAA ;Handle bad addresses
CAIGE T1,.LBMDS ;Is the block long enough???
ITERR (SCSBTS) ;Nope, fail with block to short
UMOVE T1,.SQMDT(Q1) ;Now for the target node number
ITERR SERIAA ;Handle bad addresses
CAILE T1,C%SYMX ;A reasonable node number???
ITERR (SCSISB) ;Nope, fail here please
MOVEM T1,NODNUM ;Save the node number
SKIPN T1,SBLIST(T1) ;Is this a good node number???
ITERR (SCSISB) ;Nope, fail please
MOVEM T1,SBA ;Save the system block address for now
SKIPN RECFLG ;Is this a send or receive???
IFSKP.
UMOVE T1,.SQMSR(Q1) ;A receive, get the locally generated name
ERJMP SERIAA ;Address badness
ELSE.
UMOVE T1,.SQMSS(Q1) ;A send, get locally generated name
ERJMP SERIAA ;Address is bad...
ENDIF.
MOVE T2,FORKX ;Get the owning fork number
NOINT ;We are about to own a resource...
MOVE T3,NODNUM ;Get the node number back again
CALL SCSQMD ;Add entry to system maintainace data Q
ITERR (<>,<OKINT>) ;Fail with error from T1
MOVEM T1,RESADR ;Store the address of the block for error recov
MOVE T1,NODNUM ;Get the target node number again
MOVX T2,.LBMDS ;Get the expected length of the block
XCTU [HRLM T2,.SQLEN(Q1)] ;Store "words processed" for user
ERJMP MDRERR ;Handle bad page access
UMOVE T2,.SQMSS(Q1) ;Get the source buffer name
ERJMP MDRERR ;Handle address badness
UMOVE T3,.SQMSR(Q1) ;Get the destinaton buffer name
ERJMP MDRERR ;Bomb on bad addresses please
XCTU [HLRZ T4,.SQMOF(Q1)] ;Get the xmit offset
ERJMP MDRERR
XCTU [HRRZ Q1,.SQMOF(Q1)] ; and the receive offset
ERJMP MDRERR
SKIPE RECFLG ;Is this a receive or send data???
JRST MDRREC ;Its a receive, go do it
BLCAL. (SC.SMD,<T1,T2,T3,T4,Q1,<.,SINMSC>>) ;Do the call please
JRST MDRER1 ;Fail with code from SCA please
OKINT ;Allow interrupts again
RETSKP ;All went well... Return
;Here when this is a receive, not a send.
;
MDRREC: BLCAL. (SC.RMD,<T1,T2,T3,T4,Q1,<.,SINMSC>>) ;Do the receive please
JRST MDRER1 ;Fail with code from SCA please
OKINT ;Allow interrupts again
RETSKP ;All went well... Return.
; Here on errors:
;
; MDRERR -- Here when an ERJMP takes on failure to access user space
; RESADR/ Address of block to take off system maint Q
;
; MDRER1 -- Here on a routine failure or detected error.
; T1/ Error code to fail with
; RESADR/ Address of block to remove from system Q
;
MDRERR: MOVX T1,SCSIAB ;Get the error code to fail with for bad addr
MDRER1: MOVE Q1,T1 ;Save the liver
MOVE T1,RESADR ;Get the addr of the maint block we just Q'ed
CALL SCSDMD ;Remove it again
CALL RELRES ;Release the space please
OKINT ;Allow interrupts again
MOVE T1,Q1 ;Get the error code again
RETBAD () ;Fail with arranged error code pls...
ENDSV.
> ; End REPEAT 0
SUBTTL Function code handlers -- Start a remote system (SCSSRS)
REPEAT 0,<
These functions are now performed by the DIAG% JSYS
; This routine calls SCA to start a remote system.
;
; Expects:
; T2/ Address of args in user space
;
SCSSRS::RETBAD (MONX04)
SUBTTL Function code handlers -- Reset a remote system (SCSRRS)
; This routine calls SCA to reset a remote system.
;
; Expects:
; T2/ Address of args in user space
;
SCSRRS::RETBAD (MONX04)
> ;End REPEAT 0
SUBTTL Function code handlers -- Add interrupt channel (SCSAIC)
; This routine handles the add an interrupt channel function code.
;
; Expects:
; T2/ User address of argument block
;
SCSAIC::STKVAR <ARGLEN,CHAN,CODE>
MOVE Q1,T2 ;Save the user address of arg block
UMOVE T1,.SQLEN(Q1) ;Get the users arg length word
ERJMP SERIAA ;Handle nasty page faults
CAIGE T1,.SQLEN+1 ;Is block long enough for at least one chan???
ITERR (SCSBTS) ;No, fail with block to short
SOS T1 ;Make up for length word of arg block
MOVEM T1,ARGLEN ;Save the block length
; Loop over the entries in the block
;
AICEL: MOVE T2,ARGLEN ;Get the current pointer into the arg block
ADD T2,Q1 ;Get the user addr of the word we want
UMOVE T1,(T2) ;Get the user arg word
ERJMP SERIAA ;Handle a nasty page fault
; Note: If you change the channel number AC, be sure to change
;the XCT table (PSBPSI) as well since it assume T2 contains the channel number.
;
HRRZ T2,T1 ;Get the channel number
CAIE T2,-1 ;Is this a halfword -1 (Channel cancel)???
CAIG T2,.ICLST ;Within range of reasonable PSI channels???
$SKIP ;Yes, PSI channel is OK, go on
ITERR (SCSIPC) ;No, fail with bad channel number
HLRZS T1 ;Now get just interrupt type code
CAILE T1,.SIHGH ;It this within range of reasonable codes???
ITERR (SCSIST) ;No, fail
MOVEM T1,CODE ;Save the interrupt code
MOVEM T2,CHAN ;Save the current channel number as well
XCT PSBPSI(T1) ;Store the current channel in the PSB
; Check the interrupt code. If events are being turned on, add this fork to
;FRKTAB. If events are being turned off, remove fork from FRKTAB. For non-event
;interrupt codes ignore FRKTAB.
CAIE T1,.SIPAN ;Are we doing events???
JRST AICCON ;No, nothing needs to be done with FRKTAB
MOVE T1,FORKX ;Get number of fork doing this SCS% JSYS
CAIE T2,-1 ;Are we disabling event interrupts???
IFNSK.
CALL SCSAFT ;(T1)No, add this fork to FRKTAB
NOP ;We don't care if the bit was already lit
ELSE.
CALL SCSRFT ;(T1)Yes, events being disabled, remove from FRKTAB
NOP ;We don't care if the bit was already off
ENDIF.
AICCON: SKIPN P1,SCSTCQ ;Are there any CB's that need to be updated???
JRST AICELP ;No, try for another PSI code
MOVE T1,CODE ;Be sure we have the right interrupt code
MOVE T2,CHAN ;Get the channel number back
AICCBL: XCT CBPSI(T1) ;Update the PSI code for this CB
SKIPN P1,.CBJNB(P1) ;Is there another CB on this chain???
JRST AICELP ;Nope, try for anothe PSI code
JRST AICCBL ;Yes, loop to update the PSI code
AICELP: SOSG ARGLEN ;Are there more words to do???
RETSKP ;Nope, return
JRST AICEL ;Yes, handle more PSI words pls...
ENDSV.
SUBTTL Function code handlers -- Accept connection (SCSACC)
; This routine handle the acceptance of a connection.
;
; Call
; T2/ Address of users argument block (in user space)
;
SCSACC::STKVAR <DATADR,DATRET,ERRCOD>
MOVE Q1,T2 ;Setup perm AC with addr of user args
SETZM DATADR ;Zero address of user connection data
XCTU [HRRZ T1,.SQLEN(Q1)] ;Get the length word of users arg block
ERJMP SERIAA ;Bad address, handle smoothly
CAIGE T1,.LBACC ;Is the block long enough for all data needed??
ITERR (SCSBTS) ;Fail with a block too short
UMOVE T1,.SQCID(Q1) ;Get the connect ID from the user
ERJMP SERIAA ;Handle bad addresses
NOINT
CALL SC.CSC ;(T1/T1,P1) Is this a valid CID???
ITERR (<>,<OKINT>) ;Nope, bomb the JSYS here...
UMOVE T1,.SQCDA(Q1) ;Get the address of the conn data
ERJMP SERIA0 ;It was bad afterall, fail pls...
JUMPN T1,ACCDTA ;Handle user data
BLCAL. (SC.ACC,<T1,DATADR,[0],[0]>) ;Do the accept call
ITERR (<>,<OKINT>) ;Didnt make it, bomb with error from SCA
OKINT ;Allow user interrupts again
RETSKP ;Else return happy
ACCDTA: CALL SCSUDM ;(T1/T1,T2) Move the user connect data to
;monitor space
ITERR (<>,<OKINT>) ;Fail please
MOVEM T1,DATADR ;Save the address of the connect data
MOVEM T2,DATRET ; and thre address of the space return routine
UMOVE T1,.SQCID(Q1) ;Get the connect ID from the user
ERJMP ACCER1 ;Handle bad addresses pls...
CALL SC.CSC ;(T1/T1,P1)Is this a valid CID???
IFNSK.
JRST ACCERR ;Handle the error please
ENDIF.
BLCAL. (SC.ACC,<T1,DATADR,[0],[0]>) ;Do the accept call
JRST ACCERR ;Handle the failure from SCA
SKIPE T1,DATADR ;Get the data address back again
CALL @DATRET ;Release the free space we obtained
OKINT ;Allow user interrupts again
RETSKP ; and return all ok...
; Here on failure. We are NOINT and own resident free space.
;
; ACCER1
; No error code. We ERJMP here on a bad address or access failure.
;
; ACCERR
; T1/ Error code
ACCER1: MOVX T1,SCSIAB ;We ERJMP here, report bad address
ACCERR: MOVEM T1,ERRCOD ;Save the error code
SKIPE T1,DATADR ;Get the data address back again
CALL @DATRET ;Release the free space we obtained
OKINT ;Allow user interrupts again
MOVE T1,ERRCOD ;Get the error code back
ITERR () ;Report failure
ENDSV.
SUBTTL Function code handlers -- Get data queue entry (SCSGDE)
SWAPCD
; This routine handle getting entries from the data transfer complete queue.
;
; Expects:
; T2/ User address of arg block
;
SCSGDE::STKVAR <BLKADR>
MOVE Q1,T2 ;Save address of user args
XCTU [HRRZ T1,.SQLEN(Q1)] ;Get the length word from user
ERJMP SERIAA ;Handle bad addresses
CAIGE T1,.LBGDE ;Is the block long enough???
ITERR (SCSBTS) ;Nope, fail with block to short
UMOVE T1,.SQCID(Q1) ;Now get the users connect ID
ERJMP SERIAA ;Handle bad addresses
NOINT
CAMN T1,[-1] ;Does he want the next for the fork???
JRST GDEFRK ;Yes, go get an entry from the fork queue
CALL SC.CSC ;(T1/T1,P1) We have a real CID, check it
ITERR (<>,<OKINT>) ;Bad CID, yell at the user
SKIPN T1,.CBTXQ(P1) ;Is there anything on the queue for this CB???
ITERR (SCSQIE,<OKINT>) ;Nope, fail with empty queue
; Here when we have the address of a DMA complete buffer in T1.
;
GDEHBF: XMOVEI T2,XFER ;Point to the block type
CALL SCSDEQ ;(T1,T2,P1/T1) Dequeue the buffer
ITERR (<>,<OKINT>) ;RETURN ERROR
MOVE T2,.DMNAM(T1) ;Get the buffer name from the block
UMOVEM T2,.SQBID(Q1) ;Give it to the user
ERJMP GDEERR ;Handle bad page writes
CALL RELRES ;Return the free space we used
OKINT ;Allow user interrupts again
RETSKP
; Here when we want the next DMA for THIS fork.
;
GDEFRK: SKIPN T1,SCSTXQ ;Is there anything on the fork queue???
ITERR (SCSQIE,<OKINT>) ;Nope, restore channel inter and yell at user
$LDCID P1,.MECID(T1) ;Setup P1 with CB addr
JRST GDEHBF ;Else go handle this buffer
; Here when an ERJMP takes while we have resources outstanding...
;
GDEERR: XMOVEI T2,XFER ;Point to the block type
CALL SCSLFQ ;(T1,T2,P1) Link it back onto the front of the queue
JFCL 0 ;SCSLFQ ALWAYS SKIP RETURNS
OKINT ;Allow user interrupts again
ITERR (SCSIAB) ;Now yell at user for bad addresses
ENDSV.
SUBTTL Function code handlers -- Get event Q entry (SCSEVT)
; This routine handles getting an entry from the event queue.
;
; Expects:
; T2/ User address of arg block
;
SCSEVT::STKVAR <EVTADR,EVTCOD,USRLEN,ERRCOD>
MOVE Q1,T2 ;Save user arg addr in perm AC
XCTU [HRRZ T1,.SQLEN(Q1)] ;Get the length word from the arg block
ERJMP SERIAA ;Oops, bad arg address, back out pls...
MOVEM T1,USRLEN ;Stash for later
UMOVE T1,.SQCID(Q1) ;Get the users connect ID
ERJMP SERIAA ;Handle a nasty page fault, if any
NOINT
CAMN T1,[-1] ;Are fork or connect events being requested???
JRST EVTFRK ;Fork events being requested, go to it....
CALL SC.CSC ;(T1/TA,P1) Is this a valid connect ID???
ITERR (<>,<OKINT>) ;No, fail JSYS with bad CID
SKIPN T1,.CBTEQ(P1) ;Is there anything on the event queue
ITERR (SCSQIE,<OKINT>) ;No, fail with queue is empty
JRST EVTPTE ;Yes, go process it
; Here to get event entries on a per fork basis.
;
EVTFRK: SKIPN T1,SCSTEQ ;Is there something on the forks event queue???
ITERR (SCSQIE,<OKINT>) ;No, return with Q is empty
;Here when we have the address of the event block we desire in T1. Please to
;process it...
;
EVTPTE: MOVEM T1,EVTADR ;Save the address of the event block free space
LOAD T3,EBLEN,(T1) ;Get the length field from the event block
SUBI T3,.EBDAT ;Don't count the overhead area
CAML T3,USRLEN ;Is there room in user block for this event???
ITERR (SCSBTS,<OKINT>) ;No, fail with block to short
XMOVEI T2,EVT ;Point to the EVT list end pointers
LOAD P1,MECID,(T1) ;Get the CID from the event block
CAMN P1,[-1] ;Is this a special block (no CB for it)???
IFSKP.
$LDCID P1,P1 ;Get the addr of the CB in question
LOAD T4,CBDNOD,(P1) ;Get the node number of remote on this connect
UMOVEM T4,.SQESB(Q1) ;Store remote node number for user
ERJMP EVTER1 ;Handle non-writeable pages
ENDIF.
CALL SCSDEQ ;(T1,T2,P1)Remove this entry from the fork
;and CB queues
ITERR (<>,<OKINT>) ;RETURN ERROR
LOAD T4,EBCOD,(T1) ;Get the event code from the block
MOVEM T4,EVTCOD ;Save the event code
UMOVEM T4,.SQEVT(Q1) ;Give the user the event code
ERJMP EVTER1 ;Handle non-writeable pages
LOAD T4,MECID,(T1) ;Get the CID from the event block
UMOVEM T4,.SQCID(Q1) ;Store for the user...
ERJMP EVTER1 ;Handle non-writeable pages
LOAD T3,EBLEN,(T1) ;Get the length field from the event block
SUBI T3,.EBDAT ;Dont count the overhead area
JUMPE T3,EVTLST ;If there is no data to move, finish up
MOVE T2,T1 ;Source address for XBLT to user space
MOVE T1,T3 ;Set length of data to move
MOVE T3,Q1 ;Get destination address in user space
ADDI T2,.EBDAT ;Offset source to just event data
ADDI T3,.SQDTA ;Add offset to data area in user block
CALL SCSDMU ;(T1,T2,T3) Move data to user space
JRST EVTERR ;Handle bad addresses from user
; See if we need to clean up after a connection termination event.
;
EVTLST: JUMPL P1,EVTPNT ;If a special block, no CB to light bits in
MOVE T1,EVTCOD ;Get the event code back
CAIN T1,.SEPBC ;Did the VC get closed???
CALL SCSCBD ;(P1/P1) Yes, clean up JSYS connection data
CAIE T1,.SERID ;Is this a remote disconnect???
CAIN T1,.SECRR ; or a connect rejection???
CALL SCSCBD ;(P1/P1) Yes, clean up JSYS connection data
EVTPNT: MOVE T1,EVTADR ;Get the event address back
CALL RELRES ;Release the space we used for the event block
OKINT ;Allow user interrupts again
RETSKP ;All done...
; Here for error recovery, I.E. when an ERJMP takes.
;
; EVTER1 -- We are NOINT and EVTADR is the address of the event block.
;
EVTER1: MOVX T1,SCSIAB ;Get error code for bad address
EVTERR: MOVEM T1,ERRCOD ;Save the error code
MOVE T1,EVTADR ;Get the address of the event block
XMOVEI T2,EVT ;Show addr of four word list header block
CALL SCSLFQ ;(T1,T2,P1)Link it back onto the front
;of the queue
JFCL 0 ;RETURNS +2 ALWAYS
OKINT ;Restore user interrupts
MOVE T1,ERRCOD ;Get the error code again
ITERR () ;Now go yell at the user
ENDSV.
SUBTTL Function code handlers -- Get local node number (SCSGLN)
; This function code returns the local node number.
;
; Expects:
; T2/ Address of user args
;
SCSGLN::MOVE Q1,T2 ;Put user arg addr in perm AC
XCTU [HRRZ T1,.SQLEN(Q1)] ;Get the length from user
ERJMP SERIAA ;Handle bad addresses
CAIGE T1,.LBGLN ;Is the block long enough???
ITERR (SCSBTS) ;No, fail with block to short
NOINT ;Allow SCA to finish
CALL SC.PRT ;Get the local port number
ITERR (SCSNKP,<OKINT>) ;No KLIPA on this system, fail please
OKINT ;SCA is finshed
UMOVEM T1,.SQLNN(Q1) ;Tell the user who we are
ERJMP SERIAA ;Handle unwritable pages
RETSKP ;All done return to user
SUBTTL Function code handlers -- Return buffer sizes (SCSRBS)
; This routine returns the minimum sizes for message and datagram buffers.
;
; Expects:
; T2/ Addr of user args
;
SCSRBS::MOVE Q1,T2 ;Save user arg address in perm AC
XCTU [HRRZ T1,.SQLEN(Q1)] ;Get the length from the user
ERJMP SERIAA ;Handle bad addresses
CAIGE T1,.LBRBS ;Is the block long enough???
ITERR (SCSBTS) ;No, fail with block to short
MOVX T1,<C%MGSZ-.MHUDA> ;Get the size of a buffer
UMOVEM T1,.SQLMG(Q1) ;Tell user what size messages should be
ERJMP SERIAA ;Handle unwritable areas
MOVX T1,<C%DGSZ-.MHUDA> ;Get the size of datagram buffers
UMOVEM T1,.SQLDG(Q1) ;Tell user about DG lengths
ERJMP SERIAA ;Handle bad addresses
RETSKP ;All done
SUBTTL Function code handlers -- Return path status info (SCSRPS)
; Routine to return information about the status of a wire to a particular
;remote.
;
; Expects:
; T2/ Address of user arguments.
;
SCSRPS::XCTU [HRRZ T1,.SQLEN(T2)] ;Get the length of the users arg block
CAIGE T1,.LBRPS ;Is it long enough???
ITERR (SCSBTS) ;No, fail with block to short
UMOVE T1,.SQRPN(T2) ;Get target node number
ERJMP SERIAA ;Handle bad user arg addresses
SKIPL T1 ;Is node number negative???
CAILE T1,MAXNDS ; or to big???
ITERR (SCSISB) ;Invalid node number
LOAD T3,IDPAO,(T1) ;Get the status of path A
XCTU [STOR T3,SQRPA,(T2)] ;Store path status for the user
ERJMP SERIAA ;Handle bad addresses
LOAD T3,IDPBO,(T1) ;Get the status of path B
XCTU [STOR T3,SQRPB,(T2)] ;Stash the info for the user
ERJMP SERIAA ;Handle bad addresses
RETSKP ;All done, return
SUBTTL SCS% error handlers
SUBTTL SCS% error handlers -- A2MHLT (PSB mapping bug)
A2MHLT: BUG. (HLT,SCSA2M,SCSJSY,SOFT,<SCSJSY - Attempt to map second PSB>,<<MPSFRK,OWNFRK>,<T1,CURFRK>>,<
Cause: Some routine mapped a PSB but did not release it, or did not use the
correct interlock. The net result was that we are trying to map another
PSB while we still have the first one mapped.
Data: OWNFRK - The number of the fork that did the first map
CURFRK - The fork doing the second lock
>)
SUBTTL SCS% error handlers -- SERIAA (Invalid argument block address)
; This routine is called when the user supplied argument block address is
;bad. This handy label exists as a conveniant place to ERJMP/ERCAL after
;various instructions that touch the users arg block.
;
SERIA0: OKINT
SERIAA: ITERR (SCSIAB) ;Return to user with illegal instruction trap
SUBTTL SCS% error handlers -- SERIBP (Invalid byte pointer)
; Here when an ERJMP after a byte instruction takes. This is the destination
;address for any ERJMP in SCSJSY that follows a byte instruction. Simply
;return with an illegal instruction trap...
;
SERIB0: OKINT
SERIBP: ITERR (SCSIBP) ;Return to user with invalid byte pointer
SUBTTL SCA call handlers -- Main entry point
RESCD ;Called at interrupt level
; This routine is the entry point to the SYSAP from SCA.
;Note that this code is not in process context, but rather is at interrupt
;level for the CI.
;
SCSINT::SAVEP ;Save the ACs we will kill here
JRST @CALTAB(T1) ;Goto the handler routine for SCA calls
SUBTTL SCA call handlers -- SCSONT (Handle online/offline interrupts)
; This routine handles anline/offline interrupts from SCA. We are only called
;here when SCAMPI is scanning NOTTAB for addresses to notify. Hence we get
;called here once per system and with no connect ID.
;
; Expects
; T1/ .SSPBC or .SSNCO
;
; T3/ Node number for .SSPBC
; or
; T2/ Node number for .SSNCO
;
; Return (+1) Always
; No data returned
;
SCSONT: TRVAR <NOD,CODE,FORK>
CAIN T1,.SSPBC ;Did the node go offline???
MOVX T4,.SEPBC ;Yes, get the event code for node offline
CAIN T1,.SSNCO ;Did the node come online???
IFNSK.
MOVX T4,.SENCO ;Yes, get the event code for node online
MOVEM T2,T3 ;Reposition node number
ENDIF.
MOVEM T4,CODE ;Save the code we must give the user
MOVEM T3,NOD ;Save the node that just changed state
; Loop over FRKTAB looking for forks the need to be poked.
SETO T1,0 ;Make the AOS get fork zero
ONTLOP: AOS T1 ;Increment to the next fork
CALL SCSGNF ;(T1) Get the next fork with PSI's enabled
RET ;No more forks enabled, all done
CALL ONTBLD ;Build and queue a block for this fork
$SKIP ;Failed, BUGCHK and loop again
JRST ONTLOP ;All went OK, loop for more forks
BUG. (CHK,SCSPBF,SCSJSY,SOFT,<SCSJSY - PSI block build failure>,<<T1,ERRCOD>>,<
Cause: The routine to build an event block failed. It is very likely that
ASGRES did not have the space available.
Data: ERRCOD - Error code returned by ONTBLD
>,ONTLOP)
; ONTBLD
;
; This routine is a support routine for SCSONT. It builds an online/offline
;event block and queues it.
;
; Usage:
; Call
; T1/ Fork number
; CODE/ Event code to use
; NOD/ Node number that changed state
;
; Return (+1)
; T1/ Error code
;
; Return (+2)
; T1/ Fork number
;
ONTBLD: MOVEM T1,FORK ;Save the fork we are building for
MOVX T1,<XWD .RESP2,C%PBCL> ;Priority,,length of block
MOVX T2,.RESGP ;Resident pool number
CALL ASGRES ;Get space for the event block
RETBAD () ;Handle error, note - call does not return here
MOVE T2,FORK ;Get the fork number
STOR T2,MEFRK,(T1) ;Store the target fork number
SETONE MECID,(T1) ;Set CID to special case.
MOVX T2,C%PBCL ;Get the block length
STOR T2,EBLEN,(T1) ;Store the event length
MOVE T2,CODE ;Now the event code
STOR T2,EBCOD,(T1) ;Store the event code
MOVE T2,NOD ;Get the target node number
MOVEM T2,.EBDAT(T1) ;Store the desired data
MOVX T2,.ETEVT ;Get the entry type for events
CALL SCSQUE ;(T1,T2/T1,T2)Queue the block and return
MOVE T1,FORK ;Get the fork number back again
RETSKP ;All done, all went well
ENDTV.
SUBTTL SCA call handlers -- SINDGR
; This routine handles a message/datagram receive.
;
; Expects:
; T1/ .SSDGR
; T2/ Connect ID
; T3/ Packet address
; T4/ Flags from the port driver
;
SINDGR::TDZA T1,T1 ;Show we are not doing messages
SINMGR::SETO T1, ;Set the flag that says we are doing datagrams
SAVEAC <Q1> ;Save the CB addr AC
MOVX Q1,.ETMSG ;Assume we are doing messages
SKIPN T1 ;Was this a good assumption???
MOVX Q1,.ETDG ;No, set up for datagrams
MOVE T1,T3 ;Put the datagram buffer address in right place
MOVE P1,.MHPKL(T1) ;Get the packet length
STOR P1,MELEN,(T1) ;Store the packet length in the header
STOR T2,MECID,(T1) ;Store the CID in the block
$LDCID P1,T2 ;Get the CB address
LOAD T3,CBFORK,(P1) ;Get owning fork number
STOR T3,MEFRK,(T1) ;Store in the block
ANDX T4,C%FLGM ;Be sure we have just the flags
IORM T4,.METYP(T1) ;Store in block for SYSAP
MOVE T2,Q1 ;Name the block type
CALLRET SCSQUE ;Queue it for the fork and return
SUBTTL SCA call handlers -- SINDMA
; This routine handles the DMA operation complete callback from SCA.
;
; Expects:
;
; T2/ Connect ID of connection over which DMA has been completed
; T3/ 32 bit buffer name of DMA buffer
;
SINDMA::STKVAR <CID,BUFNAM>
MOVEM T2,CID ;Save the CID
MOVEM T3,BUFNAM ;Save the buffer name for later...
MOVX T1,<XWD .RESP2,.DMLEN> ;Priority,,length of block
MOVX T2,.RESGP ;Resident pool number
CALL ASGRES ;Get space for the event block
CALL SCSAER ;(T1)Handle error, note - call does not return here
MOVE T2,CID ;Get the CID back
STOR T2,MECID,(T1) ;Store in DMA block
MOVE T2,BUFNAM ;Get the buffer name
MOVEM T2,.DMNAM(T1) ; which goes in the block as well...
MOVX T2,.DMLEN ;Get the length of this block
STOR T2,MELEN,(T1) ; which also goes into the block
MOVX T2,.ETDMA ;Get the block type
CALLRET SCSQUE ;Queue the buffer and return
ENDSV.
SUBTTL SCA call handlers -- SINMSC
REPEAT 0,<
; Here to handle SCA having a mainatainace data complete for us...
;
; Note: This routine expects to always run at interrupt level.
;
; Expects:
;
; T2/ Buffer name for completed transfer
;
SINMSC: SAVEAC <Q1>
SKIPN T1,SCATMQ ;Is there anything on the queue???
JRST MSCERR ;Nope, yell and then ignore the whole mess
MSCLOP: CAMN T2,.MQBUF(T1) ;Is this the entry we are looking for???
JRST MSCOK ;Yes, go process it please
SKIPE T1,.MQNXT(T1) ;Is there a next entry???
JRST MSCLOP ;Can't find an entry for this name...
JRST MSCERR ;Nope, die here please...
; Here when we have found the entry we are looking for.
;
; Expects:
; T1/ Base address of the entry we desire
; T2/ Buffer name for completed xfer
;
MSCOK: MOVE P1,.MQCBA(T1) ;Setup the CB address
MOVE Q1,.MQBUF(T1) ;Save the address of the entry
CALL SCSDMD ;Dequeue this entry from the maint Q
JRST MSCER1 ;Handle bizzare failures
CALL RELRES ;Return the entry's free space
MOVX T1,<XWD .RESP2,C%MDCL> ;Priority,,length of block
MOVX T2,.RESGP ;Resident pool number
CALL ASGRES ;Get space for the event block
CALL SCSAER ;(T1) Handle ASGRES failure
MOVEM Q1,.EBDAT(T1) ;Store the buffer name in event entry
LOAD T2,CBSCID,(P1) ;Get the "CID" from this connect
STOR T2,MECID,(T1) ;Store in event entry
MOVX T2,.ETEVT ;Get the entry code for events
STOR T2,METYP,(T1) ;Store the event type in the block
MOVX T2,C%MDCL ;Get the length of the block
STOR T2,EBLEN,(T1) ;Store in the event block
MOVX T2,.SEMDC ;The event code
STOR T2,METYP,(T1) ; which goes in the event block as well
SETZRO MEFLG,(T1) ;Zero the flags
CALLRET SCSQUE ;Place this entry on the appropriate q's
; Here when we cannot find the buffer name SCA has just given us...
;
MSCERR: BUG. (CHK,SCSCFB,SCSJSY,SOFT,<SCSJSY - Can't find maintainance buffer name>,<<T2,BFRNAM>>,<
Cause: SCA called us with a buffer name for a completed maintainance data
transfer. Upon trying to find this name in the database of outstanding
JSYS maint xfers, no match was found. The fork which performed the
maint data xfer request will never be notified of the completion of
the request.
Action: Try to find the buffer name in the port driver database of BSD/BHD's
and see if this is a valid buffer name. If so, check the consistancy
of the SCA maint Q. Other than this, not much can be done...
Data: BFRNAM - Buffer name
>)
RETBAD ()
; Here on a bizzare failure.
;
; Expects:
; T1/ Error code
;
MSCER1: BUG. (CHK,SCSBIZ,SCSJSY,SOFT,<SCSJSY - Maintainance data transfer Q smashed>,<<T1,ERRCOD>>,<
Cause: A routine which should not return (+1), did.
Data: ERRCOD - The error code
>)
RETBAD ()
> ;End of REPEAT 0
SUBTTL SCA call handlers -- SINPBC
;This routine handle the port breaking a connection. We get here from SCA once
;per connection.
;
SINPBC::STKVAR <CID>
MOVEM T2,CID ;Save the connect ID
$LDCID P1,T2 ;Get the CB address from the CID
MOVX T1,<XWD .RESP2,C%PBCL> ;Priority,,length of block
MOVX T2,.RESGP ;Resident pool number
CALL ASGRES ;Get space for the event block
CALL SCSAER ;(T1) Handle error, note, call does not return here
MOVX T2,.SEPBC ;Get the event type
STOR T2,EBCOD,(T1) ;Store the event code in the event block
MOVX T2,C%PBCL ;Get the length of this block
STOR T2,EBLEN,(T1) ;Store this in the block as well
MOVE T2,CID ;Get the connect ID
STOR T2,MECID,(T1) ; and store this in the block as well
MOVX T2,.ETEVT ;Name the entry type
CALLRET SCSQUE ;Queue the event block and return
ENDSV.
SUBTTL SCA call handlers -- SINCTL
;This routine handles a connect to our listen.
;
; Call
; T1/ .SSCTL
; T2/ Connect ID
; T3/ Pointer to connection data from remote system
;
; Build the event queue entry, place it on the event queue for the connection,
;and interrupt the owning fork if need be...
;
SINCTL::STKVAR <CID,CDATA>
MOVEM T2,CID ;Save the connect ID
MOVEM T3,CDATA ; and the connection data
MOVX T1,<XWD .RESP2,C%CTLL> ;Priority,,length of block
MOVX T2,.RESGP ;Resident pool number
CALL ASGRES ;Get some swapable space for it
CALL SCSAER ;(T1) Handle error, note, call does not return here
MOVX T2,.SECTL ;Get the event code type
STOR T2,EBCOD,(T1) ;Store the event code in the block
MOVX T2,C%CTLL ;Now get the length of the block
STOR T2,EBLEN,(T1) ;Store this in the blcok as well
MOVE T2,CDATA ;Get the pointer to connection data back
MOVE T3,T1 ;Make the block address the destination addr
PUSH P,T3 ;Save this address
ADDI T3,.EBDAT ;Add the offset to the data portion
MOVX T1,<<C%DTAL+3>/4> ;Get the number of words to move
EXTEND T1,[XBLT] ;Move the connection data into the event block
POP P,T1 ;Get the address of the block back
MOVE T2,CID ;Get the CID back again
STOR T2,MECID,(T1) ;Get back and store the connect ID
SETZM (T1) ;Insure we are calling this the Q end
MOVX T2,.ETEVT ;Name the block type
CALLRET SCSQUE ;Queue the event block and return
ENDSV.
SUBTTL SCA call handlers -- SINCRA
; This routine handles a connect response becoming available.
;
; Call
; T1/ .SSCRA
; T2/ Connect ID
; T3/ -1 for accepted, 0 for rejected
; T4/ Reject reason or pointer to connection data
;
; Determine which event block need to be built (based on whether connect was
;accepted or rejected) and add the block to the event queue. If this is the
;first entry on the queue, then cause a PSI interrupt for the owning fork.
;
SINCRA::STKVAR <CID,RJTADR>
MOVEM T2,CID ;Save the connect ID
MOVEM T4,RJTADR ; and the reject code
JUMPE T3,CRAREJ ;Handle the rejected connections...
MOVX T1,<XWD .RESP2,C%CRAL> ;Priority,,length of block
MOVX T2,.RESGP ;Resident pool number
CALL ASGRES ;Get the event block from swapable free space
CALL SCSAER ;(T1) Handle error, note, call does not return here
MOVX T2,C%CRAL ;Get the length of the block
STOR T2,EBLEN,(T1) ;Store the length in the block
MOVX T2,.SECRA ;Get the event code
STOR T2,EBCOD,(T1) ;Store this in the block as well
MOVE T3,CID ;Get the connect ID back, and into the block
STOR T3,MECID,(T1) ;Store in the event block
MOVE T3,RJTADR ;Get the pointer to connection data back
MOVEM T1,T4 ;Set up the XBLT destination address
ADDI T4,.EBDAT ;Offset it to the data part of the block
MOVX T2,<<C%DTAL+3>/4> ;Number of words of connect data to move
EXTEND T2,[XBLT] ;Move the connect data to the block
MOVX T2,.ETEVT ;Name the block type
CALLRET SCSQUE ;Queue the event block and return
;Here to handle the rejected connections...
;
CRAREJ: MOVX T1,<XWD .RESP2,C%CRRL> ;Priority,,length of block
MOVX T2,.RESGP ;Resident pool number
CALL ASGRES ;Get the swapable space for the event block
CALL SCSAER ;(T1)Handle error, note, call does not return here
MOVE T2,RJTADR ;Get the CID again
MOVEM T2,.EBDAT(T1) ;Restore and place the reject reason in block
MOVX T2,.SECRR ;Get the event code for what we just saw
STOR T2,EBCOD,(T1) ;Store in the event block
MOVX T2,C%CRRL ;Get the length of the event block
STOR T2,EBLEN,(T1) ;Store that as well
MOVE T2,CID ;Get the connect ID back
STOR T2,MECID,(T1) ;Store the connect ID in the block
MOVX T2,.ETEVT ;Name the block type
CALLRET SCSQUE ;Queue the event block and return
ENDSV.
SUBTTL SCA call handlers -- SINOSD
; This routine handles the SCA callback that tells SYSAPs a connection
;is now fully open and data may be sent.
;
; Build an event block, queue it, and cause an interrupt if need be...
;
; Expects
; T2/ CID
;
SINOSD::STKVAR <CID>
MOVEM T2,CID ;SAve the connect ID
MOVX T1,<XWD .RESP2,C%OSDL> ;Priority,,length of block
MOVX T2,.RESGP ;Resident pool number
CALL ASGRES ;Get some space for the block
CALL SCSAER ;(T1) Handle error, note, call does not return here
MOVE T2,CID ;Get the CID again
STOR T2,MECID,(T1) ;Pop the connect ID into the event block
MOVX T2,.SEOSD ;Get the event code
STOR T2,EBCOD,(T1) ;Store in the event block
MOVX T2,C%OSDL ;And the length of the event block
STOR T2,EBLEN,(T1) ; gets stored in the block as well
MOVX T2,.ETEVT ;Name the event type
CALLRET SCSQUE ;Queue the event block and return
ENDSV.
SUBTTL SCA call handlers -- SINRID
; The routine handles a remote disconnecting from one of the JSYS connections.
;
; The Connect Block will not be deleted until the user of the SCS%
; issues a disconnect and close a connection command (.SSDIS) or until
; the user logs out.
;
; Expects
; T2/ CID
;
SINRID::STKVAR <CID>
MOVEM T2,CID ;Save the connect ID
$LDCID P1,T2 ;Get the CB address from the CID
MOVX T1,<XWD .RESP2,C%RIDL> ;Priority,,length of block
MOVX T2,.RESGP ;Resident pool number
CALL ASGRES ;Assign swapable space for the block
CALL SCSAER ;(T1) Handle error, note, call does not return here
MOVX T2,.SERID ;Get the event type
STOR T2,EBCOD,(T1) ; and store it in the event block
MOVX T2,C%RIDL ;Get the length of the block
STOR T2,EBLEN,(T1) ; which goes in the block as well
MOVE T2,CID ;Get the connect ID back again
STOR T2,MECID,(T1) ; which goes in the block too
MOVX T2,.ETEVT ;Name the event type
CALLRET SCSQUE ;Queue the event block and return
ENDSV.
SUBTTL SCA call handlers -- SINCIA
; This routine handles the "credit is available" callback...
;
; Build an event block, queue it, and cause a PSI interrupt if one is required.
;
SINCIA::STKVAR <CID,RCDT,SCDT>
MOVEM T2,CID ;Save the connect ID
MOVEM T3,SCDT ; and the send credit
MOVEM T4,RCDT ; and the receive credit
MOVX T1,<XWD .RESP2,C%CIAL> ;Priority,,length of block
MOVX T2,.RESGP ;Resident pool number
CALL ASGRES ;Get that much swapable space for the block
CALL SCSAER ;(T1) Handle error, note, call does not return here
MOVX T2,.SECIA ;Get the event code
STOR T2,EBCOD,(T1) ;Store the event type in the block
MOVX T2,C%CIAL ;Get the length of this block
STOR T2,EBLEN,(T1) ;Store this in the block as well
MOVE T2,CID ;Get the CID again
STOR T2,MECID,(T1) ; and store it in the event block
MOVE T2,SCDT ;Get the send credit back again
MOVEM T2,.EBDAT(T1) ;Store as the first word of data
MOVE T2,RCDT ;Get the receive credit again
MOVEM T2,.EBDAT+1(T1) ;Store this as the second word of data
MOVX T2,.ETEVT ;Name the event type
CALLRET SCSQUE ;Queue the event block and return
ENDSV.
SUBTTL SCA call handlers -- SINPSC
;This routine handles a packet send complete.
;
SINPSC::STKVAR <CID,BUFADR>
MOVEM T2,CID ;Save the connect ID
MOVEM T3,BUFADR ;And the buffer address
$LDCID P1,T2 ;Get the CB address
MOVX T1,CBFRAP ;Get the reap bit
TDNE T1,.CBFLG(P1) ;Is this an aborted conenction???
JRST PSCABT ;Yes, handle an aborted connect
MOVX T1,<XWD .RESP2,C%MSCL> ;Priority,,length of block
MOVX T2,.RESGP ;Resident pool number
CALL ASGRES ;Get the space required for the block
CALL SCSAER ;(T1) Handle error, NOTE, CALL DOES NOT RETURN HERE!
MOVX T2,.SEMSC ;Get the event type
STOR T2,EBCOD,(T1) ;Store it in the block
MOVX T2,C%MSCL ;And get the length of the block
STOR T2,EBLEN,(T1) ;Which also goes in the block
MOVE T2,CID ;Get the pertinant connect ID
STOR T2,MECID,(T1) ;Which goes in the block...
MOVE T3,BUFADR ;Get the buffer address again
MOVE T2,.JHAUB(T3) ;Get the address of the user buffer completed
MOVEM T2,.EBDAT(T1) ;Store user addr of packet text in EVT block
MOVX T2,.ETEVT ;Name the event type
CALL SCSQUE ;(T1,T2/T1,T2)Queue the event block
; Here directly from above when the connection has been aborted...
;
PSCABT: MOVE T1,BUFADR ;Get the monitor buffer address again
CALLRET SCSRET ;Return the buffer please
ENDSV.
SUBTTL SCA call handlers -- SINLCL
; This routine handles little credit being left.
;
; Build an event block, queue it, and check if an interrupt is necessary...
;
SINLCL::STKVAR <CID,SHRTBF>
MOVEM T2,CID ;Save the connect ID
MOVEM T3,SHRTBF ;Save the number of buffers needed
MOVX T1,<XWD .RESP2,C%LCLL> ;Priority,,length of block
MOVX T2,.RESGP ;Resident pool number
CALL ASGRES ;Get the space required for the event block
CALL SCSAER ;(T1) Handle error, note, call does not return here
MOVX T2,.SELCL ;Get the event code
STOR T2,EBCOD,(T1) ;Store in the block
MOVX T2,C%LCLL ;Now the length of the block
STOR T2,EBLEN,(T1) ;Which goes in the block too...
MOVE T4,SHRTBF ;Get the number of needed buffers back
MOVEM T4,.EBDAT(T1) ;Put the number of buffers required in the blk
MOVE T4,CID ;Get the CID back
STOR T4,MECID,(T1) ; and store it in the event block header
MOVX T2,.ETEVT ;Name the event type
CALLRET SCSQUE ;Queue the event block and return
ENDSV.
SUBTTL SCA call handlers -- SINNWO
REPEAT 0,<
;Here to handle the callback for node went offline.
;
; Usage:
; Call
; T1/ .SSNWO
; T2/ CID for your connect to remote
;
; Note that if you have more than one connect to the remote that has gone
;away, you get one callback for each connect.
;
SINNWO::STKVAR <CID>
MOVEM T2,CID ;Save CID of dead connect
MOVX T1,<XWD .RESP2,C%NWOL> ;Priority,,length of free space block
MOVX T2,.RESGP ; from the general pool please
CALL ASGRES ;Get free space for event block
CALL SCSAER ;(T1)Handle error, note we dont come back from call
MOVX T2,C%NWOL ;Get the length of this block
STOR T2,EBLEN,(T1) ;Store in event block
SETZRO MEFLG ;No flags for this one
MOVE T2,CID ;Get the connect ID again
STOR T2,MECID,(T1) ;Store CID in event block
MOVX T2,.ETEVT ;Get the block type
CALLRET SCSQUE ;Queue the block and return
ENDSV.
> ;End of REPEAT 0
SUBTTL Support routines -- SCSDMU (Data monitor to user)
SWAPCD
; This routine moves data from monitor space into user space. Checks are made
;to insure that the page we will write to is accessable to the monitor.
;
;Note:
; This routine assumes the data being moved is less than one page long. If the
;length is more than one page, the page access checks will be wrong...
;
; Usage:
; Call
; T1/ Length in words of block to move
; T2/ Source address in monitor space
; T3/ Destination adddress in user space
;
; Return (+1)
; T1/ Error code
;
; Return (+2)
; No data returned
;
SCSDMU: XCTU [MOVES (T3)] ;Try to write the page
ERJMP DMUER1 ;Failed, back out pls...
MOVE T4,T3 ;Get the base address in user space
ADD T4,T1 ;Build the last address we move things into
XCTU [MOVES (T4)] ;Can we write the end of the block???
ERJMP DMUER1 ;Nope, back out
CALL BLTMU ;Move the data into user space
RETSKP ;All done, return success
; Here when an ERJMP takes on page access failure.
DMUER1: RETBAD (SCSIAB) ;Fail with error code please...
SUBTTL Support routines -- SCSRUB (Remove user buffer)
SWAPCD
; This routine removes a user buffer entry from the BSD set for a connection.
;
; Usage:
; T1/ User buffer address entry to be removed
; T2/ Offset into BSD for buffer type
; P1/ Address of CB
;
; This routine should be called NOINT.
;
; Return (+1)
; No entry found
;
; Return (+2)
; Entry has been removed
;
SCSRUB: SKIPN T3,.CBTBQ(P1) ;Is there a BSD on this connection???
RET ;Nope, return failure to find buffer entry
SAVEAC <Q1>
SETZ Q1, ;Be sure initial back pointer is zero
MOVE T4,T3 ;Build offset to first buffer
ADD T4,T2 ; by adding offset to base address of BSD
SKIPN T4,(T4) ;Is there an address of the first entry
JRST RUBNXB ;Nope, try the next BSD
RUBCLP: CAMN T1,.BBUVA(T4) ;Is this the entry we want???
JRST RUBWIN ;Yes, put the entry on the free queue and ret
MOVE Q1,T4 ;Save the address of the current buffer
SKIPE T4,.BBNXT(T4) ;Is there a next entry in this BSD
JRST RUBCLP ;Yep, loop for it pls...
; Here to do the next BSD.
RUBNXB: SKIPN T3,.BDNXT(T3) ;Is there a next BSD???
RET ;Nope, we loose, no entry found
MOVE T4,T3 ;Build the addr of the queue FLINK
ADD T4,T2 ; by adding the offset to the base address
SKIPN T4,(T4) ;Is there a first entry here???
JRST RUBNXB ;Nope, get the next BSD pls...
SETZ Q1, ;Be sure back pointer is zero
JRST RUBCLP ;Yup, check it pls...
; Here when an entry matches. Delete it from the queue its currently on, and
;add it to the free list.
;
; Expects:
; T2/ Offset into BSD for queue FLINK
; T3/ Base addr of BSD
; T4/ Addr of current entry (one to be deleted)
; Q1/ Address of previous entry
RUBWIN: SETZM .BBUVA(T4) ;Zero the user virtual address
SKIPN Q1 ;Is there a previous entry???
SKIPE T1,.BBNXT(T4) ; or a next entry???
TRNA ;Yes, queue is not empty
JRST RUBQIE ;No previous or next, queue is empty
ADD T2,T3 ;Build the address of the queue FLINK
SKIPN Q1 ;Is there a previous entry???
MOVEM T1,(T2) ;No previous, update FLINK to show new first
SKIPN T1 ;Is there a next entry???
MOVEM Q1,.BDF2B(T2) ;No next, update BLINK for new last entry
SKIPE Q1 ;Is there a previous entry???
MOVEM T1,.BDNXT(Q1) ;Yes, point it to the next entry
; Here when the buffer has been deleted from the appropriate queue and is now
;ready to be added to the free queue.
RUBMBF: MOVEM T4,@.BDLFD(T3) ;Link this buffer onto the free queue
MOVEM T4,.BDLFD(T3) ; and update the BLINK
RETSKP ; and return all OK
; Here when we are deleting the last entry on a BSD queue.
RUBQIE: MOVE T1,T3 ;Get base addr of BSD
ADD T1,T2 ;Build it into address of queue FLINK
MOVEM T1,.BDF2B(T1) ;Store FLINK address in BLINK
SETZM (T1) ;Init FLINK as zero
JRST RUBMBF ;Now go put the entry on the free queue
SUBTTL Support routines -- SCSSUM (Move string from user to monitor)
SWAPCD ;These routines need not be resident
; This routine moves a string from user space to monitor space. It handles
;the odd cases of the addresses or byte pointer being bad. It also allows
;the byte pointer from the user to be a generic byte pointer.
;
; Usage:
; Call
; T1/ Byte pointer to string in user space
; T2/ Byte pointer to destination string in monitor space
; T3/ Max length of the string (in bytes) or zero.
; If zero -- No max length, string terminates on null byte
; If non-zero -- String terminates on this length or null byte
; and the string is padded to this length with spaces
;
; Return (+1)
; T1/ Error code
;
; Return (+2)
; T1/ Updated user byte pointer
; T2/ Updated monitor byte pointer
;
SCSSUM: SAVEAC <Q3>
MOVE Q3,T3 ;Save max length of string
TLC T1,-1 ;Compliment left half bits to determine if
TLCN T1,-1 ; this a generic byte pointer???
HLL T1,[POINT 7,] ;Yes, fill in a real byte pointer left half
SUMLOP: XCTBU [ILDB T4,T1] ;Get a byte from the user string
ERJMP SUMBER ;Handle bad instructions
JUMPE T4,SUMFIL ;Null byte, see if any padding is needed
IDPB T4,T2 ;Load byte into monitor space string
JUMPE Q3,SUMLOP ;If no initial count then loop until null byte
SOJG T3,SUMLOP ;Have a byte count, loop if more bytes allowed
RETSKP ;No more bytes allowed, hence no padding to do
; Here on a null source byte. Handle any padding as needed.
SUMFIL: JUMPE Q3,RSKP ;If no initial count, then no padding needed
JUMPE T3,RSKP ;Return if no padding required
MOVX T4," " ;Get the pad character (space)
IDPB T4,T2 ;Add the pad character to the string
SOJG T3,.-1 ;Keep adding padding chars as needed
RETSKP ;No more padding needed, return
; Here when the ERJMP on the byte instruction takes...
SUMBER: RETBAD (SCSIBP) ;Return saying bad byte pointer
SUBTTL Support routines -- SCSDUM (Move data from user to monitor)
; This routine moves a block of words from user space into monitor space.
;Checks on the validity of the user address specified are done.
;
; Usage:
; Call
; T1/ Length in words of block
; T2/ Address of source block in user space
; T3/ Address of destination block in monitor space
;
; Return (+1)
; T1/ Error code
;
; Return (+2)
; No data, block has been moved
;
; *** Warning ***
; This routine assumes that the length of the data block being moved is less
;than one page. If the block is longer than one page the checks for page
;accesability are wrong...
;
SCSDUM: XCTU [SKIP (T2)] ;Does the user address exist???
ERJMP DUMERR ;Nope, yell about a bad address
MOVE T4,T2 ;Get the base user address of the block
ADD T4,T1 ;Calculate end address of user block
XCTU [SKIP (T4)] ;Does the whole block exist???
ERJMP DUMERR ;Nope, handle this as well
CALL BLTUM ;Move data words from user to monitor
RETSKP ;Data moved, all done
; Here when the ERJMP taks on a bad address
DUMERR: RETBAD (SCSIAB)
SUBTTL Support routines -- SCSCUB (Count user buffers)
; This routine will chase a buffer chain and count the number of buffers
;in it. It will also validate the start and end addresses of the buffers in
;the chain.
;
; Note:
; This routine always assumes that we are counting buffers for the
;current fork. USECTB is checked to be sure that the section the buffers
;are in exists.
;
; Usage:
; Call
; T1/ Address of first user buffer
; T2/ Size of each buffer in the chain
;
; Return (+1)
; T1/ Error code
;
; Return (+2)
; T1/ Address of first buffer
; T2/ Size of each buffer in chain
; T3/ Count of buffers in chain
;
SCSCUB: SAVEAC <Q1,Q2>
SETZ T3, ;Zero the buffer count
MOVE Q1,T1 ;Start with the first buffer
CUBLOP: TXNE Q1,SECMSK ;Are there any bad section bits on???
JRST CUBERR ;Yes, fail
HLRZ T4,Q1 ;Get the section part of buffer address
SKIPN USECTB(T4) ;Does this section exist???
JRST CUBERR ;No, fail
XCTU [MOVES (Q1)] ;Touch the start address of the buffer
ERJMP CUBERR ;Address does not have reasonable access
MOVE Q2,Q1 ;Get a copy of the current buffer address
ADD Q2,T2 ;Calculate the end address of the buffer
HLRZ T4,Q2 ;Get the section number of the end address
SKIPN USECTB(T4) ;Does this section exist???
JRST CUBERR ;No, fail
SOS Q2 ;Yes.Set for the end of the buffer
XCTU [MOVES (Q2)] ;Touch the end of the buffer
ERJMP CUBERR ;Failed, report bad page access
AOS T3 ;Count the buffer
CAIL T3,C%MXBF ;Have we exceeded a reasonable number of buf?
IFNSK.
MOVX T1,SCSENB ;Yes, get the error code for too many buffers
RETBAD () ;Report failure
ENDIF.
XCTU [MOVE Q1,(Q1)] ;Get the addr of the next buffer
ERJMP CUBERR ;No such address, fail
SKIPE Q1 ;Is there a next buffer???
JRST CUBLOP ;Yes, loop to check it please
RETSKP ;No, all done
; Here when an ERJMP takes on a user referance or on a detected bad address.
CUBERR: RETBAD (SCSIAB) ;Return with bad address error code
SUBTTL Support routines -- SCSXUB (Link buffer chain into database)
; This routine links a user buffer chain into the JSYS translation database.
;It is assumed that the buffer chain has been previously checked for
;accesibility and length (by routine SCSCUB).
;
; Usage:
; Call
; T1/ Address of first buffer in user space
; T2/ Offset into BSD for linking these buffers
; P1/ Address of connect block
;
; Return (+1)
; T1/ Error code
;
; Return (+2)
; P1/ Address of connect block
;
SCSXUB: SAVEAC <Q1,Q2>
MOVE Q1,T1 ;Start with the first buffer please
MOVE Q2,T2 ;Save the offset into the BSD
XUBLOP: CALL SCSLUB ;(T1,T2,P1) Link buffer into data structure
RETBAD () ;Fail with error code in T1
XCTU [MOVE Q1,(Q1)] ;Get pointer to next buffer
ERJMP XUBERR ;Handle bad address chain
SKIPN Q1 ;Is there really a next buffer???
RETSKP ;No more buffers, return now
MOVE T1,Q1 ;Point SCSLUB at the current buffer
MOVE T2,Q2 ; and where in the BSD they go
JRST XUBLOP ;Loop for the next buffer please
XUBERR: RETBAD (SCSIAB) ;Address failure, report failure
SUBTTL Support routines -- SCSUNM (User name move)
; This routine moves the source and destination process names from user
;space into monitor space. Note that it assumes a particualt argument block
;format used for the connect and listen functions.
;
; Note:
; This routine assumes that it is being called NOINT. This prevents
;^C races while we own resources.
;
; Usage:
; Call
; Q1/ Addr of args in user space
;
; Return (+1)
; T1/ Error code
;
; Return (+2)
; T1/ Address of source process name
; T2/ Address of destination process name or zero if none
; T3/ Address of free space block used
; T4/ Address of routine to call to return free space
;
SCSUNM: SAVEAC <P5>
STKVAR <SPN,DPN>
SETZM DPN ;Init byte pointer to destination name
MOVX T1,<XWD .RESP2,<C%PNLW*2>> ;Priority,,length of block
MOVX T2,.RESGP ;Resident pool number
CALL ASGRES ;Get the swapable space for the event block
RETBAD () ;Fail with
MOVE P5,T1 ;Setup perm AC with base address of free space
UMOVE T1,.SQSPN(Q1) ;Get source process name argument
ERJMP UNMER1 ;Handle bad page fault
JUMPN T1,UNMSNM ;If there is a source name, move it
MOVX T1,SCSNSN ;Otherwise, get the correct error code
JRST UNMERR ; and error exit
UNMSNM: MOVEM P5,SPN ;Save addr of source process name
MOVX T2,<POINT 8,(P5)> ;Now build byte pointer we can use
MOVX T3,C%PNMN ;The maximum length of the string
CALL SCSSUM ;(T1,T2,T3/T1,T2)Move the string
JRST UNMERR ;Handle string move failure
UMOVEM T1,.SQSPN(Q1) ;Store the updated string for the user
ERJMP UNMER1 ;Handle bad page faults
UMOVE T1,.SQDPN(Q1) ;Get the destination process name
ERJMP UNMER1 ;Handle page faults
JUMPE T1,UNMEXI ;If no destination name, default no string
XMOVEI T2,<C%PNMN+3>/4(P5) ;Build address of destination name
MOVEM T2,DPN ;Save the pointer to the destination name
MOVX T2,<POINT 8,<<C%PNMN+3>/4>(P5)> ;Byte ptr we use
MOVX T3,C%PNMN ;Max length of the string
CALL SCSSUM ;(T1,T2,T3/T1,T2)Move the string please
JRST UNMERR ;Handle string move failure
UMOVEM T1,.SQDPN(Q1) ;Store updated byte pointer for user
ERJMP UNMER1 ;Handle page faults
UNMEXI: MOVE T1,SPN ;Get promised addr of source name
MOVE T2,DPN ;Get promised addr of destination name
MOVE T3,P5 ;Put addr of free space where promised
XMOVEI T4,RELRES ; and get addr of routine to return space
RETSKP ;All is well, return
; Here on failure. Be sure the free space gets returned and the error code
;reported.
;
; UNMER1
; ERJMP here on bad address. Fill in error code for that.
;
; UNMERR
; T1/ Error code
;
UNMER1: MOVX T1,SCSIAB ;Get the error code for bad address
UNMERR: EXCH T1,P5 ;SAVE ERROR IN P5,GET ADDRESS IN T1
CALL RELRES ;(T1) Return the free space to resident pool
MOVE T1,P5 ;GET THE ERROR CODE.
RETBAD () ;Report our failure
ENDSV.
SUBTTL Support routines -- SCSUDM (User connection data move)
; This routine moves connection data from user space to monitor space.
;The data is stored in a resident free sace block that the caller is
;responsible for returning. The caller does not need to know what kind
;of space was used since the base address of the block and the address of
;the space return routine are provided.
;
; Usage:
; Call
; T1/ Base address of connection data in user space
;
; Return (+1)
; T1/ Error code
;
; Return (+2)
; T1/ Monitor address of the connection data
; T2/ Address of the routine to return the free space used
;
; Note:
; It is assumed that this routine is called NOINT since it will
;allocate resources. Rather than return NOINT when the success return
;is taken, the caller must be NOINT at the time of the call.
;
SCSUDM: STKVAR <DATADR,USRDAT>
MOVEM T1,USRDAT ;Save the address of the user conn data
MOVX T1,<XWD .RESP2,C%DTLW> ;Priority,,length of block
MOVX T2,.RESGP ;Resident pool number
CALL ASGRES ;Get the resident space for the block
RETBAD () ;Return with an error from ASGRES
MOVEM T1,DATADR ;Store the address of the free space used
MOVE T3,T1 ;Make this address the destination address
MOVX T1,C%DTLW ;Get the length of the block to move
MOVE T2,USRDAT ;Now the address of the block in user space
CALL SCSDUM ;(T1,T2,T3)Move data from user space to
;monitor space
IFNSK.
EXCH T1,DATADR ;SAVE ERROR CODE,GET FREE SPACE ADDRESS
CALL RELRES ;(T1) Return the free space please
MOVE T1,DATADR ;Get the error code back again
RETBAD () ; and report failure
ENDIF.
MOVE T1,DATADR ;Return the address of the data as promised
XMOVEI T2,RELRES ;Also report addr of free space return
RETSKP ; and return
ENDSV.
SUBTTL Support routines -- SCSCBI (Connect block data init)
; This routine initializes the connect block with the data required
;by the JSYS.
;
; Note:
; This routine assumes that it is being called to add data to a connect
;block owned by the current fork. PSB cells (SCSPS0,SCSPS1) are accessed and
;it is assumed that the current PSB is the desired one.
;
; Usage:
; Call
; P1/ Address of connect block
;
; Return (+1) Always
; P1/ Address of connect block
;
; Note:
; Today the PSB cells used here do not have a MSKSTR associated with
;them for use with LOAD/STOR. Hence the MOVE/MOVEM is used to move the
;PSI information around. These PSB cells should be defined and LOAD/STOR
;used to move the data around.
;
SCSCBI: SETONE CBFJSY,(P1) ;Set the "CB is for JSYS" flag
MOVE T1,FORKX ;Get my fork number
STOR T1,CBFORK,(P1) ;Store in CB as owning fork
MOVE T1,JOBNO ;Get my job number as well
STOR T1,CBJOB,(P1) ; which is also stored in the CB
MOVE T1,SCSPS0 ;Get the first word of fork PSI channels
MOVEM T1,.CBPS0(P1) ;Store in the CB
MOVE T1,SCSPS1 ;Now get the second word of PSI channels
MOVEM T1,.CBPS1(P1) ;Store these as well
RET ;All done...
SUBTTL Support routines -- SCSABT/SCSRBT (Add/remove bit from table)
;SCSABT
; This routine adds a bit to the table who's address is specified.
;If the bit was already lit, the (+1) return is taken. If the bit was off
;it is turned on and the (+2) return is taken.
;
;SCSRBT
; This routine turns off a bit in a bit table whos base address is given.
;If the bit was already off then the (+1) return is taken. If the bit
;was on then it is cleared and the (+2) return is taken.
;
; Usage (SCSABT and SCSRBT):
;
; Call
; T1/ Bit number
; T2/ Base address of table
;
; Return (+1)
; SCSABT: Bit was already on
; SCSRBT: Bit was already off
;
; Return (+2)
; SCSABT: Bit was not on, but is now
; SCSRBT: Bit was not off, but is now
;
SCSRBT: TDZA T3,T3 ;Show we are in RBT code
SCSABT: SETO T3, ;Show we are in ABT code
SAVEAC <T1>
STKVAR <ABTCOD>
MOVEM T3,ABTCOD ;Save entry point info
MOVE T3,T1 ;Get the bit number
IDIVI T3,^D36 ;Turn bit number into word + bit offset
ADD T3,T2 ;Add table offset to table base addr
MOVE T4,BITS(T4) ;Light the bit from the bit number
MOVE T1,(T3) ;Save the origional contents of the table
SKIPN ABTCOD ;Are we adding the bit???
IFNSK.
ANDCAM T4,(T3) ;Turn off the bit please
TDNE T4,T1 ;No, we are removing the bit
RETSKP ;Bit was on before, say so
RET ;Bit was off before, say so
ENDIF.
IORM T4,(T3) ;Yes, turn the bit on please
TDNN T4,T1 ;We are adding the bit, was it on before?
RETSKP ;No, return it was off
RET ;Yes, return it was on...
ENDSV.
SUBTTL Support routines -- SCSGNB (Get next bit)
RESCD ;Called at interrupt level
; This routine finds the next bit lit in a bit table. An origin bit is
;specified. The first bit tested is the first bit to the right of the
;origin bit.
;
; Usage:
; Call
; T1/ Origin bit
; T2/ Base address of bit table
; T3/ Length of table in words
;
; Return (+1)
; All bits after origin bit to end of table are zero
;
; Return (+2)
; T1/ Bit number of next lit bit in table
;
SCSGNB: STKVAR <BASADR,ADDR,LEN>
MOVEM T2,BASADR ;Save the base address for later
MOVEM T2,ADDR ; as well as for computation
IDIVI T1,^D36 ;(T1) = word offset (T2) = bit offset into word
SUB T3,T1 ;Offset table length to current word offset
JUMPL T3,R ;If neg, we are off the end of the table...
MOVEM T3,LEN ;Save the corrected length of the table
ADDB T1,ADDR ;Convert word offset to address in table
MOVE T1,(T1) ;Get the first word to be considered
LSH T1,(T2) ;Punt any bits left of the origin bit
MOVNS T2 ;Now put the bits back
LSH T1,(T2) ; where they came from
$SKIP ;Don't smash what we just did
GNBLOP: MOVE T1,@ADDR ;Get the next word to be considered
JFFO T1,GNBEND ;If there are bits set, we are done
SOSG LEN ;Have we goen off the end of the table???
RET ;Yes, all done, no more bits let
AOS ADDR ;Otherwise point to the next word
JRST GNBLOP ; and test it...
; Here with:
; ADDR/ Address of desired bit
; T2/ Bit position of desired bit
;
GNBEND: MOVE T1,ADDR ;Get the address of the desired bit
SUB T1,BASADR ;Turn it into a table index
IMULI T1,^D36 ; and then into a bit number
ADD T1,T2 ;Add the offset into the word
RETSKP ;All done, report bit number in T1
ENDSV.
SWAPCD
SUBTTL Support routines -- SCSAFT (Add fork to table)
; This is a jacket routine (for SCSABT) to add forks to the interrupt bit
;table. There is one bit for each possible fork in the system. When the bit
;is lit the fork has enabled interrupts for configuration changes on the CI.
;
; Usage:
; Call
; T1/ Fork number
;
; Return (+1)
; Fork was already enabled for SCS interrupts
;
; Return (+2)
; Fork was not enabled for SCS interrupts but is now
;
SCSAFT: XMOVEI T2,FRKTAB ;Get the address of the fork bit table
CALLRET SCSABT ;(T1,T2)Add the bit to the table
SUBTTL Support routines -- SCSRFT (Remove fork from table)
; This routine removes a fork from the SCS interrupts fork table. It is a
;jacket routine for SCSRBT.
;
; Usage:
; Call
; T1/ Fork number
;
; Return (+1)
; Fork was not enabled for SCS interrupts
;
; Return (+2)
; Fork was enabled for SCS interrupts but isn't now
;
SCSRFT: XMOVEI T2,FRKTAB ;Get the base address of the SCS% fork table
CALLRET SCSRBT ;(T1,T2)Remove the bit from the table
SUBTTL Support routines -- SCSGNF (Get next fork)
RESCD ;Called at interrupt level
; This routine obtains the next fork with SCS% configuration change interrupts
;enabled.
;
; Usage:
; Call
; T1/ Origin fork number
;
; Return (+1)
; No fork after origin fork is enabled for SCS% interrupts
;
; Return (+2)
; T1/ Fork number of fork with SCS% PSIs enabled
;
SCSGNF: XMOVEI T2,FRKTAB ;Get the address of the fork table
MOVE T3,FRKTLN ; and the length of the table in words
CALLRET SCSGNB ;Find the appropriate bit and return
SWAPCD
SUBTTL Support routines -- SCSQMD (Queue entry on maint. data Q)
REPEAT 0,<
SUPPORT ROUTINES FOR FUNCTIONS THAT ARE NOW DONE BY DIAG%
RESCD ;These routines do CIOFF's, must be resident
; This routine adds an entry to the system wide maintainance data queue.
;
; Usage:
; Call
; T1/ Buffer name
; T2/ Owning fork number
; T3/ Target node number
;
; Return (+1)
; T1/ Error code
;
; Return (+2)
; T1/ Address of queued block
;
SCSQMD: SAVEAC <P1,P4>
STKVAR <BUFNAM,OWNFRK,NODNUM>
MOVEM T1,BUFNAM ;Save the buffer name
MOVEM T2,OWNFRK ; and the owning fork number
MOVEM T3,NODNUM ; and the target node number
; Here to set up the temporary CB. Same format as regular CB. Just no real
;connect associated with it. Hence connect state is closed.
;
MOVE P4,SBLIST(T3) ;Fetch the system block address please...
SETZ T1, ;No bits for the CID please
NOINT ;We are about to own a resource
CALL SC.ACB ;Allocate a connect block
RETBAD (<>,<OKINT>) ;Fail with error from SCA
MOVX T1,.CSCLO ;Get the closed state
STOR T1,CBCNST,(P1) ;Store as the circuit state
MOVX T1,CBFMDC ;Get the maint data CB flag
MOVEM T1,.CBFLG(P1) ;Init the CB flags to be just the MDC bit
MOVEM P4,.CBADR(P1) ;Setup the system block address
MOVE T1,NODNUM ;Get the node number again
STOR T1,CBDNOD,(P1) ;Store in the CB please...
SETZM .CBANB(P1) ;Be sure the CB links are zero
SETZM .CBAPB(P1) ;. . .
CALL SC.LCB ;Link this connect onto block for target node
MOVX T1,<XWD .RESP2,.MQLEN> ;Priority,,length of block
MOVX T2,.RESGP ;Resident pool number
CALL ASGRES ;Get the swapable space for the event block
JRST QMDERR ;Recover from the error please
MOVE T2,BUFNAM ;Get the buffer name again
MOVEM T2,.MQBUF(T1) ;Save it in the new Q entry
MOVE T2,OWNFRK ;Get the owning fork again
STOR T2,CBFORK,(P1) ;Store in the CB
SETZM .MQNXT(T1) ;Be sure the pointer to next is zero
MOVEM P1,.MQCBA(T1) ;Store the addr of the connect block
CIOFF ;Lock out oter access to the queue please
MOVEM T1,@SCABMQ ;Link this entry onto the end of the queue
MOVEM T1,SCABMQ ; and update the queue BLINK
CION ;Allow access to the queue again
OKINT ;Allow interrupts again
RETSKP ; and return OK...
; Here when the call to ASGRES fails. Dequeue the false CB we have made and
;then return failure with error code in T1.
;
QMDERR: MOVE P4,T1 ;Save the error code
CALL SC.RCB ;Release the connect block we started here
MOVE T1,P4 ;Get the error code back again
OKINT ;Allow interrupts again
RETBAD () ;Fail with error code in T1
ENDSV.
SUBTTL Support routines -- SCSDMD (Dequeue maint. data queue entry)
; This routine removes an entry from the system wide maintainance data queue.
;
; Usage:
; Call
; T1/ Address of entry to dequeue
;
; Return (+1)
; T1/ Error code
;
; Return (+2)
; T1/ Address of entry from maintainance data queue
;
SCSDMD: CIOFF ;Lock out other access to queue
SETZ T2, ;Be sure address of previous is zero at start
SKIPN T3,SCATMQ ;Is there an entry to look at here???
RETBAD (MONX03,<CION>) ;Nope, internal confusion, return badness
DMDTRY: CAMN T1,T3 ;Do we have a match???
JRST DMDMCH ;Yes, go dequeue it please
SKIPN T2,.MQNXT(T3) ;Is there a next buffer to try???
RETBAD (MONX03,<CION>) ;Nope, internal confusion, return badness
MOVE T3,T2 ;Setup address compare AC
JRST DMDTRY ;Yes, loop for the next entry
; Here on a match.
;
; Expects:
; T1/ Address of entry to be deleted
; T2/ Address of previous entry or zero if first
;
DMDMCH: MOVE T3,.MQNXT(T1) ;Address of entry after one to be deleted
SKIPE T2 ;Was this the first entry???
MOVEM T3,.MQNXT(T2) ;No, store as addr of next in previous entry
SKIPN T2 ;Was this the first entry???
MOVEM T3,SCSTMQ ;Yes, update the queue FLINK
XMOVEI T3,SCATMQ ;Get the address of the queue FLINK pointer
SKIPN SCATMQ ;Did we delete the last entry???
MOVEM T3,SCABMQ ;Yes, update the queue BLINK as addr of FLINK
CION ;Allow access to queue again
RETSKP ;Return all OK
> ;END OF REPEAT 0
SUBTTL Support routines -- SCSLFQ (Link packet to front of queue's)
SWAPCD
; This routine links a monitor packet onto the front of the fork and
;CB queues. This routine is mainly used by error recovery code to put
;buffers back onto queues after an error has been detected. Note that this
;routine assumes the packet is for the current fork. I.E. the currently
;mapped PSB contains the correct pointers.
;
; Usage:
; Call
; T1/ Address of packet to be linked
; T2/ Address of four word list header block
; P1/ Address of CB
;
; This routine should be called NOINT.
;
; Return (+2)
; All calling AC's preserved, packet has been linked onto the front of
; the fork and CB queues.
;
SCSLFQ:
MOVE T3,@.TOPFQ(T2) ;Get the addr of the first buffer on the fork Q
MOVEM T3,.MEANF(T1) ;Link new buffer at the front
SETZM .MEAPF(T1) ;Make backward link be zero (first on Q)
MOVEM T1,@.TOPFQ(T2) ; and update the queue FLINK
MOVE T3,@.TOPCQ(T2) ;Get addr of first buffer on CB Q
MOVEM T3,.MEANC(T1) ;Link new packet onto front of queue
SETZM .MEAPC(T1) ;Zero the backward link (first on queue)
MOVEM T1,@.TOPCQ(T2) ; and update the queue FLINK
RETSKP ;Return ok...
SUBTTL Support routines -- SCSAER (ASGRES error handler)
SWAPCD
; This routine handles an allocation failure from ASGRES. It causes a
;BUGINF with enough data to try to figure out what has happened from just
;the BUGINF data.
;
; Usage
; Call
; T1/ Error code from ASGRES
;
; Return (+1) Always
; No data
;
; Note:
; This routine is branched to with a PUSHJ P,. This is only to
;obtain the PC of the caller. The routine POPs this PC off the stack and
;returns to the stack loc before the call to this routine. Hence you cannot
;have and explicit PUSH's pending before the call to this routine...
;
SCSAER: POP P,T2 ;Get the callers PC back
TXZ T2,<777740,,0> ;Keep just the PC part
BUG. (INF,SCSACF,SCSJSY,SOFT,<SCSJSY - A JSYS call to ASGRES failed>,<<T1,ERRCOD>,<T2,CALLPC>>,<
Cause: A call to ASGRES (by the JSYS) has failed. With the error code and
caller's PC given by the BUGINF, figuring out why it failed should
be easy enough.
Data: ERRCOD - Error code
CALLPC - PC of caller
>)
RETBAD ;Return to callers caller with error code in T1
SUBTTL Support routines -- SCSLCB (Link CB onto fork CB queue)
SWAPCD
; This routine links a CB onto the CB queue of a fork
;
; Usage:
; Call
; P1/ Address of the CB to be linked
; Note that at present, this routine is only called for the
; current fork. Hence we make the assumption that we are
; always the current fork. We also assume that we are ALWAYS
; in process context, and that it is always called NOINT.
;
; Return (+1) Always
; P1/ Address routine was called with
;
SCSLCB:
MOVE T1,SCSBCQ ;Get addr of last entry on the queue
XMOVEI T2,SCSTCQ ; and the addr of the top of queue pointer
CAME T1,T2 ;Is BLINK a pointer to the FLINK???
IFNSK.
MOVEM T1,.CBJPB(P1) ;No, update previous pointer of new CB
ADDI T1,.CBJNB ; and offset to the forward pntr for last CB
ENDIF.
MOVEM P1,(T1) ;Link new buffer onto the fork CB queue
MOVEM P1,SCSBCQ ; and update the queue BLINK
RET ; and return all OK
SUBTTL Support routines -- SCSKIL (Clean up SCS% data)
SWAPCD
; Routine to call to release all SCS% resources owned by a fork. Currently
;the only way here is from KSELF, FLOGO, KFORK% JSYS and the CLZFF% JSYS.
;
; Note: No ACs are smashed
;
; Usage:
; Call
; T1/ Fork number of fork being killed
;
; Return (+1) Always
; No data returned
;
; Note:
; Most callers of SCSKIL/SCSLGO assume that NO ACs are smashed.
;
SCSLGO:: ;Alternate entry name for FLOGO (MEXEC)
SCSKIL::SAVEAC <T1,T2,T3,T4,P1> ;Save ALL ACs used here
TRVAR <FRKN,PSBADR,FLNK,BLNK>
MOVEM T1,FRKN ;Save the fork number for later
;
; NOTE: The folowing two lines are a temporary hack to prevent SCSFR1
; BUGCHKs from FRKCHK when SCSKIL is called from CLZFF%. The correct
; action here is to allow SCSKIL to clean up CI connections owned by a
; fork inferior to the current fork.
;
CAME T1,FORKX ;IS THE CURRENT FORK
RET ;NO. RETURN QUIETLY
; CALL FRKCHK ;(T1) CURRENT FORK?
; RETBAD() ;NO.
NOINT
CALL SCSRFT ;(T1)Remove this fork from the PSI table
NOP ;I don't care if it wasn't in the table
XMOVEI T1,SCSTCQ
MOVEM T1,FLNK ;Save the address of the queue FLINK
XMOVEI T3,SCSBCQ ;Get 18 bits of queue BLINK address
MOVEM T3,BLNK ;Save the address of the queue BLINK
SKIPE P1,(T1) ;Are there any connections for this fork???
CALL KILCLP ;(P1) Yes, loop to kill them
CALL SCSCXN ;Delete any DMA resources owned by
;this fork
OKINT
RET ;All done, return
; Here to loop over all connection opened by a fork.
;
; P1/ Pointer to the first CB in the list
; FLNK/ Address of queue FLINK
; BLNK/ Address of queue BLINK
;
; Note: KILCHK assumes that the error recovery from the failing SC.DIS call
;will eventually loop back to get the rest of the connections. It assumes the
;queue is always empty.
;
KILCLP: LOAD T1,CBFORK,(P1) ;GET FORK NUMBER OF CB
CALL FRKCHK ;(T1) IS IT FOR THIS FORK?
JRST [MOVE P1,.CBJNB(P1) ;NO. TRY THE NEXT CB.
JRST KILCHK] ;
SETONE CBFKIL,(P1) ;Set the fork is dead flag in CB flag word
CALL SCSCBD ;(P1/P1)Delete JSYS CB data from this CB
MOVE T1,.CBSCI(P1) ;Get the CID of the current CB
MOVE P1,.CBJNB(P1) ;Save the addr of the next block
BLCAL. (SC.DIS,<T1,[0]>) ;Abort the connection
JRST KILERR ;Failed??? Check the error code
KILCHK: JUMPN P1,KILCLP ;If more blocks left, delete them
XMOVEI T1,SCSTCQ ;Get extended address of queue FLINK
MOVEM T1,@BLNK ;Re-init headers for now empty queue
SETZM @FLNK ;Zero the queue FLINK
RET ;No more connect blocks, all done
; Here when SC.DIS fails.
;
KILERR: OKINT ;SCA is done, allow interrupts again
CAIN T1,SCSIID ;Is the error, bad CID
JRST KILCHK ;Yes, then connect is already gone, no problem
BUG. (CHK,SCSABF,SCSJSY,SOFT,<SCSJSY - Connection abort failure on fork delete>,<<T1,ERRCOD>>,<
Cause: During the deletion process for a fork we tried to abort the
connections it had open. We failed in the attempt.
Data: ERRCOD - Error code returned by SC.DIS
>)
JRST KILCHK ;No continue looping for connects
ENDTV.
SUBTTL Support routines -- SCSCBD (JSYS CB data delete)
; ***** CROCK ALERT *****
;This code needs to be updated to reflect the correct scheme for deletion
;of connection data.
;
; This routine deletes JSYS data from a connect block. Buffers on the port
;queues will be returned by SC.RAP. Only the buffer database is handled here.
;
; Usage:
; Call
; P1/ Connect block address
;
; This routine should be called NOINT.
;
; Return (+1) Always
; P1/ Connect block address
;
; Note:
; This routine should only be called from process context!
;
SCSCBD:
; Clean up entries on the message available queue
XMOVEI T1,.CBTMQ(P1) ;Point to top of the queue
XMOVEI T2,.CBBMQ(P1) ; and the bottom of the queue
XMOVEI T3,SC.RBF ; and the routine to call to return the space
XMOVEI T4,MSG ; and the 4 word block for messages
CALL SCSGPR ;(T1,T2,T3,T4,P1)Return the packets
; Clean up entries on the datagram available queue
XMOVEI T1,.CBTDQ(P1) ;Point to the top of the queue
XMOVEI T2,.CBBDQ(P1) ; and the bottom of the queue
XMOVEI T3,SC.RLD ; and the routine to return the space
XMOVEI T4,DG ; and the 4 word block for datagrams
CALL SCSGPR ;(T1,T2,T3,T4,P1)Return the packets
; Clean up entries on the DMA transfer complete queue
XMOVEI T1,.CBTXQ(P1) ;Point to the top of the queue
XMOVEI T2,.CBBXQ(P1) ; and the bottom of the queue
XMOVEI T3,RELRES ; and the routine to return the space
XMOVEI T4,XFER ; and the 4 word block for DMA
CALL SCSGPR ;(T1,T2,T3,T4,P1)Return the blocks on the queue
; Clean up entries on the event queue
XMOVEI T1,.CBTEQ(P1) ;Point to the top of the queue
XMOVEI T2,.CBBEQ(P1) ; and the bottom of the queue
XMOVEI T3,RELRES ; and the routine to return the space
XMOVEI T4,EVT ; and the 4 word block for events
CALL SCSGPR ;(T1,T2,T3,T4,P1)Return the blocks on the queue
; Clean up any BSD's that are around
XMOVEI T1,.CBTBQ(P1) ;Point to the top of the queue
XMOVEI T2,.CBBBQ(P1) ; and the bottom of the queue
CALL SCSCBS ;Clean up any BSD's that are around
; Now remove this connect block from the owning fork CB queue
CALL SCSRCB ;Remove current CB from owning fork CB queue
CALL CBDCHK ;Failed, BUGCHK and continue
; ***** CROCK ALERT *****
;This is a temporary fix to get SCA to delete the block when it wants to...
SETZRO CBFJSY,(P1) ;Turn off the JSYS flag bit
TMNE CBFPTC,(P1) ;Is protocol complete lit???
IFNSK.
SETONE CBFRAP,(P1) ;Yes, light reap as well
SETONE CIREP ;TELL CIFORK TO RUN
ENDIF.
RET ;All done
CBDCHK: BUG. (CHK,SCSCDC,SCSJSY,SOFT,<SCSJSY - Cannot delete connect block from fork queue>,<<T1,ERRCOD>>,<
Cause: We tried to remove a connect block from the owning fork's list of
connect blocks. The most likely failure is a +1 return from SCSMPS.
This fails only when we map a PSB but do not unmap it.
Data: ERRCOD - Error code
>,R)
SUBTTL Support routines -- SCSGPR (General packet return)
; This routine returns a set of packets/blocks linked with a standard queue
;header. The header is the one used by SCS% to queue up EVERYTHING it hangs off
;the connect block.
;
; Usage:
; Call
; T1/ Queue FLINK
; T2/ Queue BLINK
; This routine assumes that the routine address given expects
; nothing more than the space address in T1.
; T4/ Address of 4 word list header block (if there is one)
; P1/ ADDRESS OF CONNECT BLOCK
;
; Note:
; This routine will try to use the address of the 4 word list header
;block (T4) first. If this address is zero it will use just the FLINK and BLINK
;specified in T1/T2. The FLINK and BLINK must be specified, even when a 4 word
;header block address is specified.
;
; Note:
; This routine assumes that the caller will provide whatever interlock
;is necessary for the queue. This allows this routine to be used by callers
;that require different interlocks.
;
; Return (+1) Always
; No data returned
;
SCSGPR: SAVEAC <Q1>
STKVAR <RTNADR,BLKADR>
MOVEM T3,RTNADR ;Save the return routine address
MOVEM T4,BLKADR ; and the 4 word block address
SKIPN Q1,(T1) ;Anything at all on the queue???
RET ;No, all done, return
GPRBLK: MOVE T1,Q1 ;Get the address of the current entry
MOVE Q1,(Q1) ;Get the addr of the current packet/block
SKIPE T2,BLKADR ;Is there a 4 word block address???
CALL SCSDEQ ;(T1,T2,P1/T1)Yes, dequeue the packet/block
;please
SKIPA ;ERROR, BUT WHAT ELSE CAN BE DONE. MAY WANT
;A BUGCHK HERE.
CALL @RTNADR ;Call the routine to return the space
JUMPN Q1,GPRBLK ;Loop until the queue is empty
RET
ENDSV.
SUBTTL Support routines -- SCSCBS (Clean a BSD queue)
; Routine to clean up the entries on a BSD queue. Note that this routine
;should be merged with a general queue cleaning routine. For the moment however
;it solves a point problem.
;
; Usage:
; Call
; P1/ Address of connect block
;
; Should be called NOINT.
;
; Return (+1) Always
; P1/ Address of connect block
;
SCSCBS: SAVEAC <Q1>
SKIPE T1,.CBTBQ(P1) ;Is there really something here???
JRST CBSLOP ;Yes, go process it
RET ;All done...
CBSLOP: LOAD Q1,BDNXT,(T1) ;Get the address of the next entry
CALL SC.RLD ;Release the buffer
SKIPE T1,Q1 ;Is there another enty here???
JRST CBSLOP ;Yes, loop to return it
XMOVEI T1,.CBTBQ(P1) ;Get a pointer to the queue top
STOR T1,CBBBQ,(P1) ;Init BLINK as pointer to FLINK
SETZRO CBTBQ,(P1) ;Init queue FLINK as zero
RET ;All done
SUBTTL Support routines -- SCSRCB (Remove CB from owning fork CB queue)
; Routine to remove a CB from the owning forks list of CB's.
;
; Usage:
; Call
; P1/ Address of connect block
;
; Return (+1)
; T1/ Error code
;
; Return (+2) Okay
;
SCSRCB: LOAD T1,CBFORK,(P1) ;Get the owning fork number
CALL FRKCHK ;IS THIS FOR THE CURRENT FORK?
RETBAD () ;NO.
XMOVEI T3,SCSTCQ ;Get 18 bit addr of queue FLINK
XMOVEI T4,SCSBCQ ;Get 18 bit addr of queue BLINK
MOVE T1,.CBJNB(P1) ;Get forward pointer from CB
SKIPN T2,.CBJPB(P1) ;Is there a previous pointer???
SKIPE T1 ; or a forward pointer???
JRST RCBMOQ ;There are other entries, work on them
; Here to delete the last entry on the queue. Reinit the pointers
XMOVEI T1,SCSTCQ ;Get addr of queue FLINK
MOVEM T1,(T4) ;Reinit BLINK as pointer to FLINK
SETZM (T3) ;Reinit FLINK as zero
RETSKP ;All done
; Here when there are other entries on the queue.
;
; T1/ Pointer to next CB
; T2/ Pointer to previous CB
; T3/ Address of queue FLINK
; T4/ Address of queue BLINK
RCBMOQ: SKIPN T1 ;Is there a next CB???
MOVEM T2,(T4) ;No, update Q BLINK with pointer to previous
SKIPE T1 ;Is there a next CB???
MOVEM T2,.CBJPB(T1) ;Yes, update its previous pointer
SKIPN T2 ;Is there a previous CB???
MOVEM T1,(T3) ;No, update queue FLINK
SKIPE T2 ;Is there a previous CB???
MOVEM T1,.CBJNB(T2) ;Yes, update its next pointer
RETSKP ;All done
SUBTTL Support routines -- SCSAXN (Add DMA buffer name)
; Routine to add a name to the DMA name database for a fork.
;
; Usage:
; Call
; T1/ DMA buffer name
; T2/ Owning fork number
; T3/ Address of datagram buffer with page stack in it
;
; Return (+1)
; T1/ Error code
;
; Return (+2)
; T1/ DMA buffer name
; T2/ Owning form number
; T3/ Address of page stack
;
SCSAXN: SAVEAC <Q1>
STKVAR <FRKN,BUFNAM,PAGSTK,ERRCOD>
MOVEM T1,BUFNAM ;Save the fork number
MOVEM T2,FRKN ; and the buffer name
MOVEM T3,PAGSTK ; and the address of the page stack DG buffer
MOVX T1,<XWD .RESP2,.XNLEN> ;Priority,,length of block
MOVX T2,.RESGP ;Resident pool number
CALL ASGRES ;Get the swapable space for the event block
JRST AXNERR ;Recover from the error please
MOVE T2,BUFNAM ;Get the buffer name back
STOR T2,XNNAM,(T1) ;Store the name in the entry
MOVE T2,PAGSTK ;Get the address of the page stack
STOR T2,XNSTK,(T1) ;Store in the entry
CALL SCSLXN ;(T1) Link the entry onto the fork queue
MOVE T1,BUFNAM ;Get the buffer name
MOVE T2,FRKN ; as well as the fork number
RETSKP ;All done...
; Here on a failure from ASGRES.
;
AXNERR: RETBAD () ; and return
ENDSV.
SUBTTL Support routines -- SCSDXN (Delete DMA buffer name)
; Routine to delete a DMA buffer name from the fork database. Note that this
;routine unmaps the buffer.
;
; Usage:
; Call
; T1/ Buffer name
; T2/ Fork number
;
; Return (+1)
; T1/ Error code
;
; Return (+2)
; T1/ Buffer name
; T2/ Fork number
;
SCSDXN: STKVAR <FRKN,BUFNAM,PSBADR>
MOVEM T1,BUFNAM ; as well as the buffer name
MOVEM T2,FRKN ;Save the fork number
XMOVEI T1,SCSTXN ;Get 18 bit address of queue FLINK
MOVE T2,BUFNAM ;Get the buffer name back
DXNLOP: SKIPN T1,(T1) ;Is there another entry on the queue???
RETBAD (<SCSIBN>) ;No, fail please
LOAD T3,XNNAM,(T1) ;Get the name from this entry
CAME T2,T3 ;Do we have a match???
JRST DXNLOP ;No, loop for the next entry
CALL SCSRXN ;(T1)Remove the entry from the queue
MOVE T1,BUFNAM ;Get the buffer name back
MOVE T2,FRKN ; as well as the fork number
RETSKP ;We are all done...
ENDSV.
SUBTTL Support routines -- SCSFXN (Find a buffer name)
; Routine to determine if a buffer name is currently owned by a fork.
;
; Usage:
; Call
; T1/ Buffer name
; T2/ Fork number
;
; Return (+1)
; Buffer name is not owned by designated fork
;
; Return (+2)
; Buffer name is owned by designated fork
;
SCSFXN: SAVEAC <T1,T2>
STKVAR <FRKN,BUFNAM>
MOVEM T1,BUFNAM ;Save the buffer name
MOVEM T2,FRKN ; and fork number
XMOVEI T1,SCSTXN ;Get 18 bit addr of queue FLINK
MOVE T2,BUFNAM ;Get the buffer name again
FXNLOP: SKIPN T1,(T1) ;Is there a next entry???
RETBAD (SCSIBN) ;Fail please
LOAD T3,XNNAM,(T1) ;Get the name from the entry
CAME T2,T3 ;Doe we have a match???
JRST FXNLOP ;No, try for the next entry
MOVE T1,BUFNAM ;Restore the buffer name
MOVE T2,FRKN ; and fork number
RETSKP ;Return success...
ENDSV.
SUBTTL Support routines -- SCSCXN (Clean a buffer name list)
; This routine cleans the buffer name list for a given fork.
;
; Usage:
; Call
; T1/ Base address of PSB
;
; Return (+1) Always
; No data returned
;
SCSCXN: SAVEAC <Q1>
SKIPN Q1,SCSTXN ;Is there anything on the queue???
RET
CXNLOP: MOVE T1,Q1 ;Get the entry address
LOAD Q1,XNNXT,(Q1) ;Get the address of the next entry
CALL SCSRXN ;(T1) Remove the entry from the queue
JUMPN Q1,CXNLOP ;Loop if there are more entries
RET
ENDSV.
SUBTTL Support routines -- SCSLXN (Link entry onto fork DMA name queue)
; Routine to add an entry to a forks DMA buffer name list.
;
; Usage:
; Call
; T1/ Entry address
;
; Return (+1) Always
; T1/ Entry address
;
SCSLXN:
SKIPE SCSTXN ;IS THERE ANYTHING ALREADY ON THE LINKED LIST?
IFSKP. ;NO.
MOVEM T1,SCSTXN ;SET UP THE FLINK (SCSTXN).
MOVEM T1,SCSBXN ;SET UP THE BLINK (SCSBXN).
SETZRO XNPRV,(T1) ;CLEAN OUT ANTHING IN THE NAMED BUFFER LIST BLK.
SETZRO XNNXT,(T1)
ELSE. ;YES.
MOVE T4,SCSBXN ;GET THE ADDRESS OF THE LAST NAMED BUF. LIST BLK
MOVEM T1, .XNNXT(T4) ;SET UP POINTER IN PREVIOUS NAMED BUF. LIST BLK
MOVEM T1,SCSBXN ;SET UP BLINK (SCSBXN).
SETZRO XNNXT,(T1) ;CLEAN UP ANTHING IN THE NAMED BUF. LIST BLK
STOR T4, XNPRV,(T1) ;SET UP BLINK IN NAMED BUF. LIST BLK.
ENDIF.
RET
SUBTTL Support routines -- SCSRXN (Remove entry from fork DMA nam list)
; Routine to remove an entry from a forks DMA name list.
;
; Usage:
; Call
; T1/ Entry address
;
; Return (+1) Always
; T1/ Entry address
;
SCSRXN: SAVEAC <Q1>
STKVAR <ENTADR>
MOVEM T1,ENTADR ;Save the entry address
LOAD T1,XNNAM,(T1) ;Get the name of the buffer we are killing
BLCAL. (SC.UMP,<T1>) ;Unmap the buffer please
RETBAD (<>,<OKINT>) ;Fail please
MOVE T1,ENTADR ;Get the entry address back again
CALL SCSULK ;Unlock all the pages in the buffer
XMOVEI T1,SCSTXN ;Get the 18 bit addr of the queue FLINK
XMOVEI T2,SCSBXN ;Get 18 bit address of queue BLINK
MOVE Q1,ENTADR ;Get the entry address back again
; Quick sanity check:
;
; Setup already:
; T1/ Address of queue FLINK
; T2/ Address of queue BLINK
; Q1/ Address of entry to be deleted
;
; Used:
; T3/ Forward link from entry
; T4/ Back link from entry
;
LOAD T3,XNNXT,(Q1) ;Get the forward link
LOAD T4,XNPRV,(Q1) ;Get the previous link
SKIPN T3 ;Is there a forward link???
SKIPE T4 ; and no previous link???
JRST RXNMOR ;There is forward or back link, not last entry
SETZM (T1) ;Last entry on the queue, zero the list FLINK
XMOVEI T3,SCSTXN ;Get a pointer to the list FLINK
MOVEM T3,(T2) ;Init the BLINK as pointer to FLINK
MOVE T1,Q1 ;Get the address of the entry
CALL RELRES ;Release the free space
RET ;All done
; Here when this is not the last entry on the list.
;
;SHOULD BE NOSKED WHEN ENTERING RXNMOR.
RXNMOR: SKIPN T3 ;Is there a forward link???
MOVEM T4,(T2) ;No, deleting last entry, update queue BLINK
SKIPE T3 ;Is there a forward link???
STOR T4,XNPRV,(T3) ;Yes, update previous pointer of next entry
SKIPN T4 ;Is there a previous entry???
MOVEM T3,(T1) ;No, deleteing first entry, update queue FLINK
SKIPE T4 ;Is there a previous entry???
STOR T3,XNNXT,(T4) ;Yes, update the forward pointer of next entry
MOVE T1,Q1 ;Get the entry address
CALL RELRES ;Return the free space
RET ;All done
ENDSV.
SUBTTL Support routines -- SCSULK (Unlock pages in a DMA buffer)
; This routine unlocks the pages associated with a DMA buffer name. SCSMAP
;logged all of the pages it locked in a datagram buffer as a stack. The address
;of this stack is stored in the DMA name queue entry.
;
; Usage:
; Call
; T1/ Entry address
;
; Return (+1) Always
; No data returned
;
; Note: This routine returns the datagram buffer being used as a page stack.
;
SCSULK: SAVEAC <Q1,Q2>
STKVAR <STKADR>
SKIPN Q1,.XNSTK(T1) ;Get the address of the stack
RET ;What stack... Return now
MOVE T1,Q1 ;Get the address of the stack
MOVEM T1,STKADR ;Save the stack address
SKIPN Q1,(Q1) ;Is there anything on the stack???
JRST ULKEXI ;Stack is empty, release the buffer
AOS Q2,T1 ;Point to the base of the stack
ADD Q2,Q1 ;Now point to the end of the stack
ULKLOP: POP Q2,T1 ;Get the page number to unlock
NOINT ;Make sure this finishes
CALL MULKCR ;Unlock it please
OKINT ;We are done...
SOJG Q1,ULKLOP ;Loop for all locked pages
ULKEXI: MOVE T1,STKADR ;Get the entry address again
CALL SC.RLD ;RElease it please
RET ;All done
ENDSV.
SUBTTL Support routines -- SCSCLK (Clock service routine)
RESCD
; This routine is called by the scheduler when it is doing the 2nd level
;clock routines (CLK2) and when SCSTIM is zero. Here the entries that have
;been queued to the SCSTHQ (by SCSQUE at PI interrupt level) are moved
;to the SCSTPQ queue. All entries in SCSTPQ are then processed by
;SCSPSI code, on a per fork/interrupt basis when PSISC% is set. The
;SCSPSI code will then put the entries into the SCS% data portion
;of the CB and issue a channel interrupt.
;
; Usage
; Call
; No arguments
;
; Return (+1) Always
; No arg returned
;
SCSCLK::SAVEAC <Q1>
SKIPN T1,SCSTHQ ;Anything on the events queue???
JRST CLKEXI ;Nope, return now
SKIPE SCSLCK ;IS THE SCSTPQ QUEUE LOCKED?
JRST CLKEX2 ;YES. WAIT UNTIL NEXT TIME IN CLK2 CODE.
CIOFF ;NO. DON'T LET THE SCSTHQ QUEUE CHANGE
SKIPE SCSTPQ ;IS THE SCSTPQ QUEUE EMPTY?
IFSKP. ;YES.
MOVEM T1,SCSTPQ ;SET THE POINTER TO THE FIRST ENTRY
ELSE. ;NO, QUEUE IS NOT EMPTY
MOVE T2,SCSBPQ ;GET ADDRESS OF THE LAST ENTRY
MOVEM T1,.MEANC(T2) ;SET THE FORWARD POINTER IN THE LAST ENTRY.
MOVEM T2,.MEAPC(T1) ;SET THE BACKWARD POINTER IN FIRST ENTRY TO
;BE ADDED.
ENDIF.
MOVE T1,SCSBHQ ;GET ADDRESS OF LAST ENTRY TO BE ADDED.
MOVEM T1,SCSBPQ ;SET NEW ADDRESS OF LAST ENTRY.
SETZM SCSTHQ ;RESET THE SCSTHQ QUEUE FORWARD POINTER.
XMOVEI T1,SCSTHQ
MOVEM T1,SCSBHQ ;RESET TE SCSTHQ QUEUE BACKWARD POINTER.
CALL CLKEXI ;RESET SCSTIM
CION ;CAN NOW LET SYSTEM UPDATE THE SCSTHQ QUEUE.
;NOW WORKING WITH SCSTPQ QUEUE.
MOVE Q1,SCSTPQ
CLKFLP: LOAD T2,MEFRK,(Q1) ;Get the target fork number
MOVX T1,PSISC% ;Get the bit to light in FKINT (if needed)
TMNN FKISC,(T2) ;Has this fork been poked already???
CALL PSIGR ;No, request an interrupt for this fork
SKIPE Q1,.MEANC(Q1) ;Is there a next entry???
JRST CLKFLP ;Yes, loop for the next entry pls...
RET
CLKEXI: MOVX T1,<1B1> ;Get a VERY large positive number
MOVEM T1,SCSTIM ;Turn our clock off pls...
; OKSKED ;Allow other queue deletes again
CLKEX2: RET ; and return
SUBTTL Support routines -- SCSPSI (Add entry to fork queue)
; This routine is called by SCHED at PIRQ when PSISC% is on in FKINT. We
;need to look down the queue of packets and see if there is one for this
;fork. This routine processes entries in the queue pointed to by
;SCSTPQ. When it removes entries from this queue, SCSLCK must be
;set so that SCSCLK: code will not be able to change the SCSTPQ queue.
;An alternate way of preventing such damage, would be to go NOSKED
;while removing an entry from the SCSTPQ queue.
;
; Call
; No arguments
;
; Return (+1) Always to PIRQR
; No data returned
;
;
;THE .MEANC OFFSET OF EACH QUEUE ENTRY IS USED AS A FORWARD POINTER
;TO THE NEXT ENTRY. THE .MEAPC OFFSET IS USED AS A BACKWARD POINTER.
;THIS IS TRUE ONLY BETWEEN THE TIMES WHEN THE ENTRY
;IS QUEUED (VIA QUEFRK) AND WHEN IT IS REMOVED (VIA SCSPSI). AFTER THE
;ENTRY IS REMOVED FROM THE SCSTPQ LIST, THE .MEANC AND .MEAPC OFFSETS
;ARE USED FOR ANOTHER PURPOSE.
;
SCSPSI::SKIPN SCSTPQ ;Is there anything at all on the queue???
RET ;No, nothing to do here
SAVEAC <Q1,Q2,Q3,P1> ;Save the ACs we will need here
STKVAR <BLKADR,EVTTYP,LSTENT> ;Address of the current event block
;LSTENT IS THE ENTRY PRECEDING THE
;ENTRY THAT WAS REMOVED FOR THIS FORK.
;IT IS NEEDED BECAUSE SCSCLK: CODE CAN
;ADD ENTRIES TO THE SCSTPQ QUEUE IF SCSLCK
;IS NOT SET..
PSIELP: SKIPN T1,SCSTPQ ;Is there another entry???
JRST PSIEXI ;No, bail out here
JRST PSIFRK ;GO CHECK IF ENTRY IS FOR THIS FORK.
PSINXT:
SKIPN T1,LSTENT ;GET THE LAST ENTRY THAT WAS ON QUEUE.
IFSKP. ;FOUND ONE.
SKIPN T1,.MEANC(T1) ;IS THERE ANOTHER ENTRY ON THE QUEUE?
JRST PSIEXI ;NO. FINISHED.
ELSE. ;DID NOT KNOW OF ANY OTHER ENTRIES ON QUEUE.
SKIPN T1,SCSTPQ ;HAVE ANY ENTRIES BEEN ADDED?
JRST PSIEXI ;NO. FINISHED FOR THIS FORK.
ENDIF.
;T1 SHOULD NOW HAVE THE ADDRESS OF AN ENTRY
;ON THE QUEUE THAT HAS NOT BEEN LOOKED AT.
PSIFRK: LOAD T2,MEFRK,(T1) ;Get the target fork number
CAMN T2,FORKX ;Is this one for us???
IFSKP.
SKIPN T1,(T1) ;Get the addr of the next entry
JRST PSIEXI ;No next entry, fall out here
JRST PSIFRK ;Test the next entry
ENDIF.
;YES THIS ENTRY IS FOR THIS FORK.
AOS SCSLCK ;SET THE LOCK, THE SCSTPQ QUEUE WILL NOT
;BE TOUCHED BY ANYTHING BUT THIS.
MOVE T2,.MEAPC(T1) ;GET ADDRESS OF THE PREVIOUS ENTRY
MOVEM T2,LSTENT ;SAVE IT.
;NOW DELETE THIS ENTRY FROM THE SCSTPQ LIST.
SKIPE T2,.MEANC(T1) ;IS THERE A NEXT ENTRY?
IFSKP. ;NO.
SKIPE T2,.MEAPC(T1) ;IS THERE PREVIOUS ENTRY?
IFSKP. ;NO. THEN THIS IS THE ONLY ENTRY.
SETZM SCSTPQ ;RESET THE SCSTPQ AND SCSBPQ POINTERS.
XMOVEI T2,SCSTPQ
MOVEM T2,SCSBPQ
ELSE. ;YES. THEN THIS IS THE LAST ENTRY.
SETZM .MEANC(T2) ;ZERO THE FORWARD POINTER IN PREVIOUS ENTRY.
MOVEM T2,SCSBPQ ;RESET THE POINTER FOR NEXT TIME AROUND.
ENDIF.
ELSE. ;YES, THERE IS A NEXT ENTRY.
SKIPE T3,.MEAPC(T1) ;IS THERE A PREVIOUS ENTRY ON THE QUEUE?
IFSKP. ;NO, THEN THIS IS THE FIRST ENTRY.
SETZM .MEAPC(T2) ;SETUP BACKWARD POINTER.
MOVEM T2,SCSTPQ ;SET UP SCSTPQ
ELSE. ;YES, THERE IS PREVIOUS ENTRY.
MOVEM T3,.MEAPC(T2) ;SET NEXT TO POINT TO PREVIOUS.
MOVEM T2,.MEANC(T3) ;SET PREVIOUS TO POINT TO NEXT.
ENDIF.
ENDIF. ;ENTRY NOW DELETED FROM SCSTPQ. CONTINUE ON.
SETZM SCSLCK ;UNDO THE SCSLCK LOCK.
MOVEM T1,BLKADR ;Save the event block address
LOAD T1,MECID,(T1) ;Get the CID from the event block
CAMN T1,[-1] ;Is this a special block with no CID???
IFNSK.
SETO P1,0 ;Yes, special block, show address of CB as -1
JRST PSINDL ;Yes, no CB work to do
ENDIF.
; Here to see if this event requires bits to be set in the connect block.
CALL SC.CSC1 ;Sanity check the CID
JRST PSIBER ;Stale CID, do not queue this block
MOVX T1,CBFRAP ;Get reap bit
TDNE T1,.CBFLG(P1) ;Is this still a valid CB???
JRST PSIBER ;No, loop for next entry
; Here to put the new entry onto the fork and connection queues.
MOVE T1,BLKADR ;Get the event block address again
$LDCID P1,.MECID(T1) ;Now for the CB address
LOAD T2,METYP,(T1) ;Get the entry type
MOVEM T2,EVTTYP ;Save the event type
MOVE T2,PSITAB(T2) ;Now the address of the list pointer block
; Add the entry to the CB queue.
MOVE Q1,.TOPCQ(T2) ;Pointer to CB queue top pointer
XMOVEI Q1,@Q1 ;Turn index into CB into a real address
MOVE Q2,.BOTCQ(T2) ;Pointer to CB queue bottom pointer
XMOVEI Q2,@Q2 ;Turn index into CB into a real address
TXO Q2,C%IND ;Turn on the indirect bit for this address
SETZM .MEANC(T1) ;There is no next buffer since we are last
SETZM .MEAPC(T1) ; and for now assume there is no previous
MOVE T3,(Q2) ;Get the current last entry
CAME T3,Q1 ;Is this a pointer to the q head pointer???
MOVEM T3,.MEAPC(T1) ;No, update the previous pointer of new entry
MOVEM T1,@Q2 ;Link this entry onto the end of the queue
MOVEM T1,(Q2) ; and update the tail pointer
; Here to put the new entry onto the fork queues.
PSINDL: MOVE T1,BLKADR ;Get the entry address
LOAD T2,METYP,(T1) ;Get the entry type
MOVEM T2,EVTTYP ;Save the event type
MOVE T2,PSITAB(T2) ;Now the address of the list pointer block
; Add the entry to the fork queue
MOVE Q1,.TOPFQ(T2) ;Get addr of the fork queue FLINK
MOVE Q2,.BOTFQ(T2) ;Get addr of the fork queue BLINK
SETZM .MEANF(T1) ;No next on fork queue since we are last
SETZM .MEAPF(T1) ; and for now, assume no previous
MOVE T4,@Q1 ;Save the current state of the queue
MOVE T3,@Q2 ;Get addr of current last entry
CAMN T3,Q1 ;Is this a pointer to the FLINK???
IFNSK.
MOVEM T1,(Q1) ;Yes, update the fork Q FLINK
ELSE.
MOVEM T3,.MEAPF(T1) ;No, update link to previous of new entry
MOVEM T1,.MEANF(T3) ;Update next field of previous entry
ENDIF.
MOVEM T1,(Q2) ;In any case, update the fork queue BLINK
JUMPN T4,PSINXT ;If there were entries before, don't give a PSI
MOVE T4,EVTTYP ;Get the event type
XCT PSIXCT(T4) ;Fetch the PSI channel from the PSB
CAIN T1,-1 ;Is it the null channel???
JRST PSINXT ;Yes, don't give a PSI
MOVE T3,BLKADR ;Get the event block address again
LOAD T2,MEFRK,(T3) ;Get the fork to interrupt
CALL PSIRQ ;Queue a PSI interrupt for the fork
JRST PSINXT ;Loop for more entries
; Here on finding an old CB. Return the free space and loop for the next
;entry.
PSIBER: MOVE T1,BLKADR ;Get the free space addr back
LOAD T2,METYP,(T1) ;Get the entry type
CAILE T2,.ETDMA ;Check entry type
PSIBUG: BUG. (CHK,SCSBDE,SCSJSY,SOFT,<SCSJSY - Bad entry type found>,<<T2,TYPE>,<T1,BLKADR>>,<
Cause: An illegal type of message buffer was attempted to be returned.
It is now lost.
Data: TYPE - Message buffer type
BLKADR - Free space block address
>,PSINXT)
JUMPE T2,PSIBUG ;Check for type of 0
CALL @[ IFIW!SC.RBF ;Free correct data type
IFIW!SC.RLD
IFIW!RELRES
IFIW!RELRES]-1(T2)
JRST PSINXT ;Loop for more entries
; Here to leave this routine
PSIEXI: RET ; and return
ENDSV.
SUBTTL Support routines -- SCSQUE (Queue a block for list queueing)
; This routine places blocks on a system wide queue for the scheduler.
;This is the routine called by interrupt level to get a block moved up to
;the user. The route is as follows:
;
; 1. Interrupt level calls SCSQUE which places blocks on a system wide queue
; and sets off a timer. This is the queue that is pointed to by SCSTHQ.
; 2. The timer goes off and the scheduler runs SCSCLK. SCSCLK takes all
; of the entries on the SCSTHQ and puts them on the SCSTPQ loops over
; the SCSTPQ queue placing an interrupt for the indicated target
; forks.
; 3. The interrupt happens (at SCSPSI) and in the target fork's context we
; take entries off the SCSTPQ queue and places them on the fork's
; queue. We also queue a PSI interrupt for the fork if needed.
;
; Note:
; This routine assumes that if the CID in the block is -1 the block
; is a special fork only block. Hence the target fork number has already been
; filled in and there is no connect block to retrieve data from.
;
; Usage:
; Call
; T1/ Addr of block to be queued
; T2/ Block type code
;
; Return (+1) Always
; T1/ Addr of block which was queued
; T2/ Block type code
;
SCSQUE: SAVEAC <P1> ;We need the CB addr AC here...
SETZM .MEANC(T1) ;Zero any old link pointers
SETZM .MEAPC(T1) ;. . .
SETZM .MEANF(T1) ;. . .
SETZM .MEAPF(T1) ;. . .
STOR T2,METYP,(T1) ;Store the block type in the event block
LOAD P1,MECID,(T1) ;Get the CID from the event block
CAMN P1,[-1] ;Is this a special fork only block???
JRST QUEFRK ;Yes, do no CID checking
$LDCID P1,P1 ;Now the CB addr
LOAD T3,CBFORK,(P1) ;Get the fork this block applies to
STOR T3,MEFRK,(T1) ;Save in the block
;BETWEEN THE TIME THE ENTRY IS QUEUED (VIA
;QUEFRK) AND REMOVED FROM THE SCSTPQ LIST,(VIA
;SCSPSI)THE .MEANC OFFSET OF THE ENTRY WILL BE
;USED AS A FORWARD LINK AND THE .MEAPC
;OFFSET WILL BE USED AS A BACKWARD LINK.
;A ZERO IN EITHER ENTRY INDICATES
;THE END OF THE CHAIN IN THAT PARTICULAR
;DIRECTION. NOTE THAT SCSCLK: CODE TRANFERS
;ENTRIES ON THE SCSTHQ/SCSBHQ QUEUE TO THE
;SCSTPQ/SCSBPQ QUEUE.
QUEFRK: SKIPN SCSTHQ ;ANY ENTRIES ON THE QUEUE
IFSKP. ;YES.
MOVE T3,SCSBHQ ;GET ADDRESS OF LAST ENTRY
MOVEM T3,.MEAPC(T1) ;UPDATE THE BACKWARD LINK IN ENTRY TO BE ADDED.
ENDIF.
MOVEM T1,@SCSBHQ ;UPDATE THE FORWARD LINK OR SCSTHQ
MOVEM T1,SCSBHQ ;UPDATE SCSBHQ
SETZM SCSTIM ;Tell scheduler that its time to run SCSCLK
RET ;All done...
SUBTTL Support routines -- SCSMBS (Make another BSD)
SWAPCD
;This routine creates a BSD and links it onto the list of BSD's for a
;connection.
;
; Note: This routine needs to be protected from user interrupts. SC.ALD must
;be allowed to complete and the obtained resource must not be lost.
;
; Call
; P1/ Address of connection block
;
; This routine should be called NOINT.
;
; Return (+1)
; T1/ Error code
;
; Return (+2)
; T1/ Address of the new BSD
; P1/ Address of the connection block
;
SCSMBS::MOVX T1,1 ;We only need one buffer thank you.
CALL SC.ALD ;Allocate a long datagram buffer
RETBAD () ;No buffers, we loose, return badness
XMOVEI T2,.BDFMG(T1) ;Addr of first message pointer
MOVEM T2,.BDLMG(T1) ;Init message tail as pointer to head
SETZM .BDFMG(T1) ;Zero the message entry head
XMOVEI T2,.BDFDG(T1) ;Addr of first datagram pointer
MOVEM T2,.BDLDG(T1) ;Init tail as pointer to head
SETZM .BDFDG(T1) ;Init head as zero
MOVX T4,C%NBSD ;Get the number of entries in a BSD
MOVEM T1,T2 ;A copy we can play with
ADDI T2,.BDBDB ;Offset this to the first slot address
MOVEM T2,.BDFFD(T1) ;Store as the addr of the first free entry
MOVEM T2,T3 ;Dont smash the pointer to last entry
MBSLOP: ADDI T3,.BBLEN ;Add the offset to the next entry
MOVEM T3,(T2) ;Link on this next entry
MOVE T2,T3 ;Move to the next buffer
SOJG T4,MBSLOP ;Loop for the entire BSD
MOVEM T3,.BDLFD(T1) ;Store the list tail pointer
SETZM (T3) ;Insure a null last entry pointer
MOVEM T1,@.CBBBQ(P1) ;Link this new buffer onto the end of the queue
MOVEM T1,.CBBBQ(P1) ; and update the tail pointer
RETSKP ;Return all happy...
SUBTTL Support routines -- SCSDEQ (Dequeue a buffer from fork+CB Q's)
; This routine dequeues a packet from the fork and connection lists it is on.
;
; Note:
; May only be called from process context.
;
; Call
; T1/ Address of packet
; T2/ Address of 4 word list header block
; P1/ Address of CB or -1, if -1 there is no CB entry to delete
;
; Should be called NOINT.
;
; Return (+1) Error
; T1/ Error code
;
;
; Return (+2) No error
; T1/ Address of packet
;
SCSDEQ::SAVEQ
STKVAR <PAKADR,BLKADR>
MOVEM T1,PAKADR ;Save the packet address
MOVEM T2,BLKADR ; as well as the addr of the list header block
JUMPL P1,DEQFRK ;This a fork only entry? If yes, skip CB stuff
MOVE T3,.MEANC(T1) ;Get next connection entry
SKIPN T4,.MEAPC(T1) ;Is there another entry
SKIPE T3 ; on the queue???
JRST DEQMEL ;No, there are entries left on the queue
XMOVEI T3,@.TOPCQ(T2) ;Get the addr of the top of the queue
MOVEM T3,@.BOTCQ(T2) ;Init tail pointer as pointer to head
SETZM @.TOPCQ(T2) ;Init head pointer as zero
JRST DEQFRK ;Now do the fork list
DEQMEL: SKIPE T3 ;Is there a next entry???
MOVEM T4,.MEAPC(T3) ;Yes, update previous entry pointer in nxt buff
SKIPN T3 ;Is there a next entry???
MOVEM T4,@.BOTCQ(T2) ;No, update the tail pointer in the CB
SKIPE T4 ;Is there a previous entry???
MOVEM T3,.MEANC(T4) ;Yes, update next pointer of previous
SKIPN T4 ;Is there a previous entry???
MOVEM T3,@.TOPCQ(T2) ;No, update the head pointer in the CB
; Here to remove the entry from the fork list
;
DEQFRK: SKIPL P1 ;Is this fork only case???
IFNSK.
MOVX T3,CBFKIL ;No, see if fork with connect is dead
TDNE T3,.CBFLG(P1) ;Is the fork already gone???
RETSKP ;Yes, then don't try to delete fork Q entries.
ENDIF.
LOAD T1,MEFRK,(T1) ;Get the owning fork number
MOVE T3,BLKADR ;Get well as the header block addr
MOVE Q1,.TOPFQ(T3) ;Get the addr of the fork Q top
MOVE Q2,.BOTFQ(T3) ;Get the addr of the fork Q bottom pointer
MOVE T1,PAKADR ;Restore the packet address
MOVE T3,.MEANF(T1) ;Get the previous entry
SKIPN T4,.MEAPF(T1) ;Is there no next entry
SKIPE T3 ; and no previous entry (I.E. last entry)???
JRST DEQMFE ;No, there are entries left on the queue
; Deleting last entry on queue.
;
MOVE T3,BLKADR ;Get header block address again
MOVE T3,.TOPFQ(T3) ;Now the real top of queue pointer address
MOVEM T3,(Q2) ;Init tail pointer as pointer to head
SETZM (Q1) ;Init head pointer as zero
JRST DEQEXI ;All done, exit please...
; Here when there are other fork entries.
;
DEQMFE: SKIPE T3 ;Is there a next entry???
MOVEM T4,.MEAPF(T3) ;Yes, update previous entry in next buffer
SKIPN T3 ;Is there a next entry???
MOVEM T4,(Q2) ;No, update the tail pointer in the PSB
SKIPE T4 ;Is there a previous entry???
MOVEM T3,.MEANF(T4) ;Yes, update next pointer of previous
SKIPN T4 ;Is there a previous entry???
MOVEM T3,(Q1) ;No, update the head pointer in the PSB
DEQEXI: MOVE T1,PAKADR ;Restore the entry address
RETSKP ;All done
ENDSV.
SUBTTL Support routines -- SCSMPS (Map a forks PSB)
REPEAT 0,<
; Jacket routine for SETCPT. Maps the target forks PSB if the target is
;not the current fork. Also not that it is expected that multiple routines
;will try to map the PSB for the same fork at the same time. This is a result
;of more than one routine needing access to the PSB to perform its function.
;It is not normal however to try to map the PSB of two different forks at the
;same time. This would indicate that someone neglected an interlock.
;
; Usage:
; Call
; T1/ Fork number
;
; Return (+1)
; T1/ Fork number
;
; Return (+2)
; T1/ Fork number
; T2/ Base address of target fork's PSB
;
; Note:
; It is the responsibility of the caller to provide an interlock while
;we own the PSB.
;
SCSMPS: SKIPL T2,MPSFRK ;Have we got a fork mapped already???
IFNSK.
CAME T1,T2 ;Yes, are we mapping the same fork again???
RETBAD (MONX03) ;NO! Someone missed an interlock, fail
AOS MPSCNT ;Increment the nesting count
AOS MPSNST ;Count a nested fork map event
MOVE T2,MPSADR ;Get the address we reported the last time
RETSKP ; and return as if we did the work again
ENDIF.
MOVEM T1,MPSFRK ;Save the fork number of last fork mapped
CAMN T1,FORKX ;Are we the target fork???
IFNSK.
AOS MPSCNT ;Increment the nesting level
AOS MPSFKX ;Count a mapped ourselves occurance
XMOVEI T2,PSBPGA ;Point to the base of our PSB
MOVEM T2,MPSADR ;Save the last reported address
RETSKP ; and return
ENDIF.
STKVAR <FRKN>
AOS MPSCPT ;Count a use of SETCPT for fork mapping
MOVEM T1,FRKN ;Save the fork number
LOAD T1,FKPS%,(T1) ;Get the SPT index for the target PSB
HRLZS T1 ;Put the SPT slot where SETCPT wants it
CALL SETCPT ;Map the PSB of the target fork
MOVE T1,FRKN ;Restore fork number
AOS MPSCNT ;Increment the nesting count
XMOVEI T2,CPTPGA ;Show the base addr of the PSB
MOVEM T2,MPSADR ;Save the last reported address
RETSKP ;All done
ENDSV.
SUBTTL Support routines -- SCSUPS (Unmap a forks PSB)
; Routine to unmap the PSB mapped with SCSMPS.
;
; Usage:
; Call
; No arguments required
;
; Return (+1) Always
;
; Note:
; It is the responsibility of the caller to provide an interlock while
;we own the PSB.
;
SCSUPS: SOSLE MPSCNT ;Have we reached the base nesting level???
RET ;No, nothing to do yet
MOVE T1,FORKX ;Get the current fork
CAME T1,MPSFRK ;Did we map the current fork???
CALL RELCPT ;No, release the mapped PSB page
SETOM MPSFRK ;Show we have no PSB mapped
RET ;All done
> ;END OF REPEAT 0
SUBTTL Support routines -- SCSLUB (Link on user buffer addr)
; This routine links a user buffer address into a BSD for the current
;connection.
;
; Usage:
; Call
; T1/ User address of message buffer
; T2/ Offset in BSD to desired FLINK (indicates desired queue)
; P1/ CB addr
;
; This routine should be called NOINT.
;
; Return (+1)
; T1/ Error codes
;
; Return (+2)
; Entry is linked, T1-T4 ARE SMASHED!
;
SCSLUB: STKVAR <BUFADR,BSDOFS>
MOVEM T1,BUFADR ;Save the user buffer address
MOVEM T2,BSDOFS ; and the BSD offset
SKIPE T3,.CBTBQ(P1) ;Are there any BSD's on this connect???
JRST LUBAHD ;Yes, dont create one
LUBMBS: CALL SCSMBS ;(P1/T1,P1) Create the BSD
RETBAD () ;Return badness with error code in T1
MOVE T3,T1 ;Put the BSD addr where expected
MOVE T2,BSDOFS ;Restore the BSD offset
MOVE T1,BUFADR ; and the user address of message buffer
LUBAHD: SKIPE T4,.BDFFD(T3) ;Is there a free entry in the BSD???
IFSKP. ;NO.
SKIPE T3,.BDNXT(T3) ;IS THERE ANOTHER BSD ON THE CHAIN?
JRST LUBAHD ;YES. GO FIND THE FIRST FREE ENTRY IN THIS BSD.
JRST LUBMBS ;NO. GO CREATE A NEW BSD.
ENDIF.
ADD T2,T3 ;Calculate the addr of the FLINK
MOVEM T1,.BBUVA(T4) ;Store user addr in BSD entry
MOVE T1,.BBNXT(T4) ;Get the addr of the next buffer
MOVEM T1,.BDFFD(T3) ;Delete this entry from the free queue
SETZM .BBNXT(T4) ;Zero the forward link of the new entry
JUMPN T1,LUBNLF ;If next entry don't do Q end code
XMOVEI T1,.BDFFD(T3) ;Get the addr of the free queue FLINK
MOVEM T1,.BDLFD(T3) ;Init BLINK as pointer to FLINK
LUBNLF: MOVEM T4,@.BDF2B(T2) ;Link this buffer onto the end of the queue
MOVEM T4,.BDF2B(T2) ; and update the queue BLINK
MOVE T2,BSDOFS ;Get the BSD offset
CAIN T2,.BDFDG ;Was this a new datagram???
AOS .CBDGJ(P1) ;Yes, increment the count of JSYS DG buffers
CAIN T2,.BDFMG ;Was this a new message???
AOS .CBMGJ(P1) ;Yes, update the JSYS message buffer count
RETSKP ;Return all OK
ENDSV.
SUBTTL Support routines -- SCSGUB (Get user buffer address)
; This routine obtains the address of a buffer in user space.
;
; (This routine is expected to remove the buffer from the BSD)
;
; Call
; T1/ Offset into BSD indicating packet type
; P1/ Address of connection block
;
; Should be called NOINT.
;
; Return (+1)
; T1/ Error code
; P1/ Address of connection block
; (No buffers available)
;
; Return (+2)
; T1/ Address of buffer in user space
; P1/ Address of connection block
;
SCSGUB: LOAD T2,CBTBQ,(P1) ;Get the address of the first BSD
JUMPE T2,[RETBAD (SCSNSB)] ;If no BSD then no message buffers
SAVEQ ;Save addr ACs
MOVE Q1,T2 ;Save the addr of the BSD
MOVE Q2,T2 ;Get the BSD addr again
MOVE Q3,T1 ;Save the BSD offset indicated
ADD Q2,T1 ;Build this into the FLINK address
GUBELP: SKIPN T4,(Q2) ;Get the address of the first packet entry
JRST GUBTNB ;None in this BSD, try the next one
;NOW THAT AN ENTRY HAS BEEN FOUND
;FOR A DG OR MSG, UPDATE THE FREE
;QUEUE POINTERS OF THE BSD AND THE
;DG OR MSG QUEUE POINTERS OF THE BSD.
;FIRST, UPDATE THE DG OR MSG POINTERS.
SKIPE .BBNXT(T4) ;ONLY DG OR MSG ENTRY?
IFSKP. ;YES.
SETZM (Q2) ;SET THE DG OR MSG FIRST ENTRY TO ZERO
MOVEM Q2,.BDF2B(Q2) ;SET THE DG OR MSG LAST POINTER TO POINT
;TO THE FIRST POINTER.
ELSE. ;NO.
MOVE T1,.BBNXT(T4) ;GET THE ADDRESS OF THE SECOND DG OR MSG
MOVEM T1,(Q2) ;MAKE IT THE FIRST.
ENDIF.
;NOW, UPDATE THE FREE QUEUE POINTERS.
SKIPE .BDFFD(Q1) ;ANY ENTRIES IN FREE QUEUE OF BSD?
IFSKP. ;NO.
MOVEM T4,.BDLFD(Q1) ;UPDATE LAST FREE ENTRY POINTER BECAUSE
;IT POINTS TO FIRST FREE QUEUE POINTER
;WHEN FREE QUEUE IS EMPTY.
SETZM .BBNXT(T4) ;SET END OF FREE QUEUE ENTIES TO ZERO.
ELSE. ;YES.
MOVE T1,.BDFFD(Q1) ;GET THE ADDRESS OF THE FIRST ENTRY.
MOVEM T1,.BBNXT(T4) ;MAKE NEW FREE QUEUE ENTRY POINT TO
;THE PREVIOUS FIRST FREE QUEUE ENTRY.
ENDIF.
MOVEM T4,.BDFFD(Q1) ;UPDATE THE FIRST FREE ENTRY POINTER
MOVE T1,.BBUVA(T4) ;Get the user address from this entry
CAIN Q3,.BDFDG ;Did we get a datagram???
DECR CBDGJ,(P1) ;Yes, update the JSYS buffer count
CAIN Q3,.BDFMG ;Did we get a message???
DECR CBMGJ,(P1) ;Yes, update the JSYS buffer count
RETSKP ;Return all happy
;Here to try the next BSD...
;
GUBTNB: SKIPE Q1,.BDNXT(Q1) ;Get the address of the next BSD
JRST GUBNXT ;We have the next BSD, look for DG entries
RETBAD (SCSNSB) ;Fail please
GUBNXT: MOVE Q2,Q1 ;Get the new BSD addr
ADD Q2,T1 ;Add the offset to the FLINK
JRST GUBELP ; and loop for more datagrams
SUBTTL Support routines -- SCSRET (Return buffer to correct pool)
; Common routine to return buffers to SCA pool.
;
;Usage:
;
; Call
; T1/ Address of buffer
;
;
; Returns (+1) Always
;
;Note: Buffer must have been initialized so that .JHFLG indicates the
;kind of buffer
;
;Note: Also, this routine must be protected from user interrupts such that
;the SCA calls are guarenteed to complete.
;
SCSRET: MOVX T2,JH%DGB ;Get the datagram buffer bit
TDNN T2,.JHFLG(T1) ;Is this a datagram buffer???
CALLRET SC.RBF ;No, return the message buffer please
CALLRET SC.RLD ;yes, return this datagram buffer
;Routine to check if the current fork matches the fork number
;to be checked.
; Call
; T1/ Fork number to be checked
;
; Return (+1) Fork number does not match
; T1/ Error code
;
; Return (+2) Fork number does match
FRKCHK: SAVEAC <T1,T2,T3>
CAMN T1,FORKX ;FOR THIS FORK?
IFSKP. ;NO.
MOVE T2,FORKX
MOVE T3,(P) ;CALLING ADDRESS
BUG. (CHK,SCSFR1,SCSJSY,SOFT,<SCSJSY - SCS% fork removing entries that do not belong to it>,<<T1,FRKNUM>,<T2,CURFRK>,<T3,ADDRESS>>,<
Cause: It is assumed that only the owning fork can manipulate SCS% in
a CB or in its own PSB.
Data: FRKNUM - Fork number to be checked
CURFRK - Current fork
ADDRESS - Address of calling routine.
>)
AOS MPSFR1
RETBAD (SCSFRK)
ENDIF.
RETSKP
SUBTTL Storage
.PSECT RSDAT
FCNTAB: $SCSFC ;Function code dispatch table for SCS JSYS
CALTAB: $CALTB ;Dispat for SCA to SYSAP calls
CBPSI: $BUILD (.SIHGH+1) ;Block for storing PSI codes into CB's
$SET (.SIDGA,<>,<HRRM T2,.CBPS0(P1)>);Instruction to store DG int chan
$SET (.SIMSA,<>,<HRLM T2,.CBPS0(P1)>);Instruction to store MSG int chan
$SET (.SIDMA,<>,<HRLM T2,.CBPS1(P1)>);Instruction to store DMA int chan
$SET (.SIPAN,<>,<HRRM T2,.CBPS1(P1)>);Instruction store EVNT int chan
$EOB
PSBPSI: $BUILD (.SIHGH+1) ;Block for storing PSI codes into PSB's
$SET (.SIDGA,<>,<HRRM T2,SCSPS0>);Instruction to store DG int chan
$SET (.SIMSA,<>,<HRLM T2,SCSPS0>);Instruction to store MSG int chan
$SET (.SIDMA,<>,<HRLM T2,SCSPS1>);Instruction to store DMA int chan
$SET (.SIPAN,<>,<HRRM T2,SCSPS1>);Instruction store EVNT int chan
$EOB
MSG:: $BUILD (QLEN)
$SET (.TOPCQ,<>,<<IFIW>!<.CBTMQ(P1)>>) ;Top of CB message queue
$SET (.BOTCQ,<>,<<IFIW>!<.CBBMQ(P1)>>) ;Bot of CB message queue
$SET (.TOPFQ,<>,<MSEC1,,SCSTMQ>) ;Top of fork message queue
$SET (.BOTFQ,<>,<MSEC1,,SCSBMQ>) ;Bot of fork message queue
$SET (.JBUFF,<>,<IFIW!.CBMGJ(P1)>) ;Count of JSYS MSG buffers
$EOB
DG:: $BUILD (QLEN)
$SET (.TOPCQ,<>,<<IFIW>!<.CBTDQ(P1)>>) ;Top of CB datagram queue
$SET (.BOTCQ,<>,<<IFIW>!<.CBBDQ(P1)>>) ;Bot of CB datagram queue
$SET (.TOPFQ,<>,<MSEC1,,SCSTDQ>) ;Top of fork datagram queue
$SET (.BOTFQ,<>,<MSEC1,,SCSBDQ>) ;Bot of fork datagram queue
$SET (.JBUFF,<>,<IFIW!.CBDGJ(P1)>) ;Count of JSYS DG buffers
$EOB
XFER:: $BUILD (QLEN)
$SET (.TOPCQ,<>,<<IFIW>!<.CBTXQ(P1)>>) ;Top of CB xfer queue
$SET (.BOTCQ,<>,<<IFIW>!<.CBBXQ(P1)>>) ;Bot of CB xfer queue
$SET (.TOPFQ,<>,<MSEC1,,SCSTXQ>) ;Top of fork xfer queue
$SET (.BOTFQ,<>,<MSEC1,,SCSBXQ>) ;Bot of fork xfer queue
$EOB
EVT:: $BUILD (QLEN)
$SET (.TOPCQ,<>,<<IFIW>!<.CBTEQ(P1)>>) ;Top of CB event queue
$SET (.BOTCQ,<>,<<IFIW>!<.CBBEQ(P1)>>) ;Bot of CB event queue
$SET (.TOPFQ,<>,<MSEC1,,SCSTEQ>) ;Top of fork event queue
$SET (.BOTFQ,<>,<MSEC1,,SCSBEQ>) ;Bot of fork event queue
$EOB
PSITAB: $BUILD (4+1) ;Table of queue pointers,4 types, but no type 0
$SET (.ETMSG,<>,MSG) ;Pointer message list pointer block
$SET (.ETDG,<>,DG) ;Pointer to datagram list pointer block
$SET (.ETEVT,<>,EVT) ;Pointer to event list pointer block
$SET (.ETDMA,<>,XFER) ;Pointer to DMA list pointer block
$EOB
;Warning, do not change the loaded AC without changing SCSPSI as well...
;
PSIXCT: 0 ;No code 0
HLRZ T1,SCSPS0 ;Load the message available channel
HRRZ T1,SCSPS0 ;Load the datagram avail channel
HRRZ T1,SCSPS1 ;Load the event channel
HLRZ T1,SCSPS1 ;Load the DMA channel
.ENDPS RSDAT
; Random locations
;ENTRIES ARE ADDED TO THE FOLLOWING QUEUE WHILE AT A HARWARE
;PI LEVEL. ENTRIES ARE ADDED AT SCSQUE BEFORE THE PI INTERRUPT IS
;DISMISSED.
RSI (SCSTHQ,<0>,1) ;Top pointer for SCS% PI
;INTERRUPT working queue
RSI (SCSBHQ,<<MSEC1,,SCSTHQ>>,1) ;Bottom pointer for SCS% PI
;INTERRUPT working queue
;ENTIES ARE ADDED TO THE FOLLOWING QUEUE WHILE AT SCHEDULER LEVEL.
;AND ALL ENTIRES FROM THE SCSTHQ QUEUE ARE ADDED AT ONE TIME IN THE
;SCSCLK CODE. ENTRIES ARE DELETED BY THE SCSPSI CODE.
RSI (SCSTPQ,<0>,1) ;FLINK SCS% PROCESS CONTEXT
;WORKING QUEUE.
RSI (SCSBPQ,<<MSEC1,,SCSTPQ>>,1) ;BLINK SCS% PROCESS CONTEXT
;WORKING QUEUE.
RS SCSLCK ;LOCK TO INDICATE THAT PROCESS CONTEXT
;IS DELETING ENTRIES FROM THE SCSTPQ
;QUEUE. 0 = QUEUE NOT LOCKED. 1 =
;QUEUE IS LOCKED.
RSI (MPSFRK,<-1>,1) ;Last fork mapped by SCSMPS
RSI (MPSCNT,<0>,1) ;Nesting level count for SCSMPS
RSI (MPSADR,<-1>,1) ;Last address reported by SCSMPS
RSI (MPSFKX,<0>,1) ;Count of times we asked to map ourselves
RSI (MPSCPT,<0>,1) ;Count of times we used SETCPT to map PSB
RSI (MPSNST,<0>,1) ;Count of times we did a nested MPS call
RSI (MPSFR1,<0>,1) ;PROCESS MANIPULATING ENTIRES NOT ITS OWN
; Support location for CION/CIOFF
;
RS (PIFLAG) ;-1 -- Last real CIOFF did a channel off
; 0 -- Don't channel on at last CION in nest
END