Trailing-Edge
-
PDP-10 Archives
-
BB-H311D-RM
-
monitor-sources/scampi.mac
There are 20 other files named scampi.mac in the archive. Click here to see a list.
; UPD ID= 5054, SNARK:<6.MONITOR>SCAMPI.MAC.161, 5-Nov-84 14:42:33 by LOMARTIRE
;New table of contents
; UPD ID= 5046, SNARK:<6.MONITOR>SCAMPI.MAC.160, 31-Oct-84 15:47:06 by LOMARTIRE
;Fix typos in ring buffer usage description
; UPD ID= 4997, SNARK:<6.MONITOR>SCAMPI.MAC.159, 24-Oct-84 20:01:53 by GRANT
;In SC.RCD, return destination node name
; UPD ID= 4890, SNARK:<6.MONITOR>SCAMPI.MAC.158, 1-Oct-84 08:59:03 by HAUDEL
;Add an OKSKED at SCM.ER.
; UPD ID= 4831, SNARK:<6.MONITOR>SCAMPI.MAC.157, 17-Sep-84 11:21:03 by PURRETTA
;Update copyright notice
; UPD ID= 4750, SNARK:<6.MONITOR>SCAMPI.MAC.156, 24-Aug-84 15:50:46 by HALL
;In connect_request and accept_request, force status field to be zero
; UPD ID= 4727, SNARK:<6.MONITOR>SCAMPI.MAC.155, 22-Aug-84 10:47:39 by LOMARTIRE
;Fix bug where FQCNT and DFQCNT can go negative.
;Comment ring buffer usage.
;Fix loop comparison at SBB.CL.
;Rework ring buffer at unlock coroutine SC.FN1.
;
; UPD ID= 4656, SNARK:<6.MONITOR>SCAMPI.MAC.154, 7-Aug-84 16:13:31 by CDUNN
;Remove SC.JSY. Equivalent functionality now in SCSJSY.
;
; UPD ID= 4649, SNARK:<6.MONITOR>SCAMPI.MAC.153, 7-Aug-84 10:24:58 by CDUNN
;Fix .SSPBC callback so that both node number and CID are not returned in T2.
;The CID will be returned in T2 and the node number in T3.
;If there is to be no CID returned, T2 will contain -1.
;
; UPD ID= 4635, SNARK:<6.MONITOR>SCAMPI.MAC.152, 31-Jul-84 08:40:59 by LOMARTIRE
;SC.RRR - don't complain about non-zero requeue credit if v.c. was closed
;CLean up BUGxxxs
;get rid of JSR BUGHLT
; UPD ID= 4603, SNARK:<6.MONITOR>SCAMPI.MAC.151, 27-Jul-84 09:08:50 by LOMARTIRE
;Add buffer manipulation as a default for RNGSW
;
; UPD ID= 4602, SNARK:<6.MONITOR>SCAMPI.MAC.150, 27-Jul-84 08:52:28 by LOMARTIRE
;Replace missing calls to RG.PQM.
;Report SCAMCR BUGCHK sooner and add some additional optional data
;Add SCAOBI BUGCHK to report online interrupt before init done.
;Add routines SC.TMQ and SC.TDQ and calls to detect free queue inconsistency.
;
; UPD ID= 4591, SNARK:<6.MONITOR>SCAMPI.MAC.149, 26-Jul-84 22:25:09 by CDUNN
;Change SC.OFL/SC.ERR to loop over NOTTAB and notify on system offline/error.
;Also fix the use of NOTTAB so filling the last entry does not send monitor
;into left field.
;
; UPD ID= 4561, SNARK:<6.MONITOR>SCAMPI.MAC.148, 18-Jul-84 18:56:23 by HALL
;Cleanup (no functional change)
;SC.DIS - don't mark listener reapable. The JSYS bit would already have
;been cleared, so SC.PTC will have set the reap bit
; UPD ID= 4499, SNARK:<6.MONITOR>SCAMPI.MAC.147, 12-Jul-84 19:55:04 by LOMARTIRE
;Add .SSDDG callback (dropped datagram).
;Rearrange AC storage for .SSDGR and .SSMGR callbacks.
;Remove all maintenance data code.
;Remove .SSNWO since PHYKLP only calls SC.ERR when node goes away.
;Remove SC.P2S and SC.S2P since they are no longer needed.
;
; UPD ID= 4484, SNARK:<6.MONITOR>SCAMPI.MAC.146, 12-Jul-84 14:52:15 by HALL
;Make it possible to connect to VMS. WHen we initiate a connection, they
;send us a connect_response with zero as the source CID. We don't get the
;real CID until they send the accept_request. We had always copied the
;CID from the connect_response, and it worked with the HSC and other TOPS-20
;systems. For now, at least, we will copy the CID from the accept_request.
;If this creates a problem with the HSC, we'll have to find another
;solution.
; UPD ID= 4451, SNARK:<6.MONITOR>SCAMPI.MAC.145, 12-Jul-84 08:25:53 by HALL
;SC.SNM wasn't clearing the FLINK word when returning buffer to port
; UPD ID= 4450, SNARK:<6.MONITOR>SCAMPI.MAC.144, 11-Jul-84 14:16:47 by HALL
;Table of contents
; UPD ID= 4449, SNARK:<6.MONITOR>SCAMPI.MAC.143, 11-Jul-84 10:46:52 by HALL
;Rearrange the routines. No intended change in code.
; UPD ID= 4438, SNARK:<6.MONITOR>SCAMPI.MAC.142, 5-Jul-84 16:40:23 by HALL
;Start cleaning up BUGxxx's
; UPD ID= 4426, SNARK:<6.MONITOR>SCAMPI.MAC.141, 3-Jul-84 14:27:40 by LOMARTIRE
;Fix all references to removed DEFSTRs and obsolete fields in c.b. and s.b.
;Change SC.RCD to no longer acquire free space but to use address passed.
;Also, make SC.RCD return the intended data correctly.
;Minor changes to SC.SOA alternate code.
;
; UPD ID= 4422, SNARK:<6.MONITOR>SCAMPI.MAC.140, 3-Jul-84 11:34:24 by HALL
;SC.ULK - rearrange a little, shouldn't change action
;SC.INC - close v.c. on unexpected response
;SC.CRS - call SC.GCB
;SIN.ER - comments about lost packet
;Remove SC.MDC
;Fix all callers of OPENVC and CLOSVC to expect +1 return only
;SC.OFL - get rid of unused code, and clean up comments
;SC.NOD - use T2 and avoid saving P4
;SC.CMG - Change HLT to CHK, and return failure
;SC.CRD - if can't get buffer, don't alter count
; UPD ID= 4421, SNARK:<6.MONITOR>SCAMPI.MAC.139, 3-Jul-84 11:22:23 by HALL
;SC.SOA - call the sysap for any nodes that are already online
; UPD ID= 4417, SNARK:<6.MONITOR>SCAMPI.MAC.137, 2-Jul-84 11:37:24 by LOMARTIRE
;Make sure SC.NOD does not destroy T3 and T4 as a result of the CALL SC.CAL
;
; UPD ID= 4414, SNARK:<6.MONITOR>SCAMPI.MAC.136, 2-Jul-84 08:40:57 by HAUDEL
;Change SC.UMP code from BLCAL UMAP to JRST UMAP.
;
; UPD ID= 4412, SNARK:<6.MONITOR>SCAMPI.MAC.135, 2-Jul-84 07:17:07 by GRANT
;Remove special code for OPENVC
; UPD ID= 4393, SNARK:<6.MONITOR>SCAMPI.MAC.134, 27-Jun-84 13:48:22 by LOMARTIRE
;Do not destroy temporary ACs when recording interlocks in ring buffer.
;
; UPD ID= 4382, SNARK:<6.MONITOR>SCAMPI.MAC.133, 25-Jun-84 09:20:50 by LOMARTIRE
;Various ring buffer work -
; Add feature data to RG.BFM and RG.PQM and place calls to these routines
; Add a new jacket routine, RG.ITL, to record interlocks
;
; UPD ID= 4379, SNARK:<6.MONITOR>SCAMPI.MAC.132, 22-Jun-84 17:27:58 by HALL
;SC.FN1 - don't decrement count of locked c.b's for this s.b., because
; we're doing it in SC.ULK
; UPD ID= 4361, SNARK:<6.MONITOR>SCAMPI.MAC.131, 19-Jun-84 16:06:26 by HALL
;SC.DIS - honor, but don't lock. Use CIOFF for protection against incoming
; connection management events
;SC.SDG - if don't want response, count buffer as queued for input
; - if error, put buffer on port's queue
;SC.SMG - move error-handling code inline, handle previously-incremented
; receive credit if we didn't want the buffer back
;SC.CRD - BUG if UNLKDG fails
;Alternate code for SC.SOA to provide immediate callback - not executed yet
;SC.ALC - check counts racefree
;SC.RAP - protect don't-care list from changes
;SC.CDT - clear .CBPND if decide not to send
;SC.CVC - get rid of old code that tried to open v.c., and prepare for
; CLOSVC's never failing
;SC.RCB - bitch if can't get buffers
;Get rid of SC.VCM
;SC.ONL - get rid of literal
;Remove repeat 0 around openvc stuff so we can test it, but jump
;around it by default: SC.ERR, SC.FN1, SC.ULK
; UPD ID= 4346, SNARK:<6.MONITOR>SCAMPI.MAC.130, 15-Jun-84 13:50:56 by LOMARTIRE
;Record callbacks in ring buffer before callbacks occur
;Convert remaining references to send credit to use .CBSCD
;Lock the c.b. and verify it at SC.NOD and SC.DCI
;Change SC.CSP to use address passed to store data instead of obtaining space.
;
; UPD ID= 4328, SNARK:<6.MONITOR>SCAMPI.MAC.129, 13-Jun-84 12:09:45 by HALL
;SC.RWQ - don't unlock what you haven't locked
;SC.ULK - test for group of bits before testing each individually
;Add (under repeat 0) code for controlling when to open a v.c.
;Complain if SC.LCB finds a c.b.'s FLINK or BLINK non-zero.
;Get rid of special entry point in SC.CVC that returns a buffer. Rename
;SC.VC1 to be SC.CVC and fix the callers. Remove NOPs after some calls.
;Make changes to count of datagram buffers be race-free. Affected
;routines: SC.CRD, SC.RCB, SC.ADG, SLC.DC
; UPD ID= 4318, SNARK:<6.MONITOR>SCAMPI.MAC.128, 11-Jun-84 10:46:18 by LOMARTIRE
;Fix SC.CSP to not return pointers to the connect block as it may disappear
;
; UPD ID= 4313, SNARK:<6.MONITOR>SCAMPI.MAC.127, 9-Jun-84 15:55:49 by HALL
;Remove old code
; UPD ID= 4312, SNARK:<6.MONITOR>SCAMPI.MAC.126, 9-Jun-84 14:42:01 by HALL
;Make SC.DIS be CIOFF a little longer, to keep out incoming connection
;management requests when sysap does disconnect at odd times
; UPD ID= 4310, SNARK:<6.MONITOR>SCAMPI.MAC.125, 8-Jun-84 13:27:38 by HALL
;Add connection block locks. Create lock, honor, and unlock routines.
;Honor the lock at SC.DRQ (incoming disconnect_request), SC.DIS (sysap
;wants to disconnect), SC.ERR (node offline), SC.SNM (sending connection
;management request). Lock the lock wherever a routine cannot tolerate
;disappearance of the c.b., or change in state.
;Most routines lock the c.b. by calling SC.CAL to verify and lock.
;SC.CON and SC.LIS lock the block directly. All unlock by calling SC.ULK.
;SC.CDT no longer calls SC.SNM. Its callers do it so that they can
;unlock the c.b. first. Affected routines:
; SC.RMG, SC.CRM, SC.IDL
;Make subroutines to manipulate the queues of c.b.'s -- the system block
;list and the don't-care list.
; SC.RDQ - remove entry from don't-care queue. Called by SC.RCB and
; SC.SCM
; SC.RSQ - remove entry from system block queue. Called by SC.RCB and
; SC.LCB
;Related changes:
;SC.RCB - When can't get a buffer, don't keep trying
; - Move JSYS-only code into a subroutine
;SC.RWQ - check and lock c.b., and move entry if it's locked
;SC.ACB - don't initialize the lock word. Let it be 0
;SC.RQS- don't do CIOFF
;Move reap sanity checks into a subroutine, SC.RRR, and complain if lock
; count isn't zero.
;Make SC.CAL call the lock routine
;SC.DEF - not a bug if JFFO doesn't find bits set
;SC.IDL - use NOSKED to protect list of c.b.'s. Call SC.SNM if needed
;SC.CDT - don't do CIOFF, don't call SC.SNM
;SC.SNd and SC.REQ - combine them; get send credit to be race-free
;Clean up references to SBOBB and .CBSCD
;SC.ERR - clear address of outbound buffer with EXCH
; - clear requeue credit
; UPD ID= 4293, SNARK:<6.MONITOR>SCAMPI.MAC.124, 4-Jun-84 13:46:47 by HAUDEL
;Change SC.MAP - Now only one argument. Code JRSTs to MAPBUF.
; UPD ID= 4285, SNARK:<6.MONITOR>SCAMPI.MAC.123, 1-Jun-84 12:21:57 by LOMARTIRE
;Make the following changes for SBI to node number conversion:
; Make callers of following routines supply node number instead of SBI:
; - SC.CON, SC.LIS, SC.SMD, SC.RMD, SC.RCD, SC.RST, SC.STA, SC.ONL,
; - SC.ERR, SC.OFL
; New loop of SBLIST at SSC.SL - use C%SBLL instead of assuming dense
; Put node number, not SBI in CBDNOD at SSC.LC and SSC.FX
; LOAD SBDPA not SBSBI at SSN.SB and SBD.DN
; At SC.ONL, put node number in SBDPA and store SS.NOD in T2 for .SSNCO
; STOR CBDNOD in SC.CON and SC.LIS
; LOAD CBDNOD in SC.CSP and store in CDNOD
; LOAD CDBNOD in SSC.CL
; Replace all references to SS.SBI with SS.NOD
; Remove routine SC.SBI
;
; UPD ID= 4260, SNARK:<6.MONITOR>SCAMPI.MAC.122, 30-May-84 16:04:21 by HALL
;Restructure sending of connection management requests to avoid
;races and prepare for c.b. locks. Create SC.RWQ to remove entry from
;system block work queue, and call it from SC.SNM and SC.DEF. Change
;SC.DEF so that it removes an entry from the queue while creating
;its buffers, and then returns it to the queue. Use CIOFF to interlock
;changes to the queue. Do buffer creation for both routines in a new
;routine, SC.BUF.
;Add new entry point to SC.CSC, which will lock the c.b. Change
;callers now even though code doesn't exist. Interrupt level routines
;assume that c.b. will remain valid.
;Make SC.LCB check for open v.c. and return failure. Fix callers to
;expect that
;Miscellaneous changes:
;SC.SNM - bugchk if b.s. is zero
;SC.RQS - assume b.s. of zero is a bug
;SC.SND and SC.REQ - verify connect ID
;SC.CRM - Move CION to precede call to SC.CDT
;SC.ACC - don't return argument to caller
;SC.ERR - don't clear .CBNWQ
;RC.RAP - don't check flink for work queue
; UPD ID= 4247, SNARK:<6.MONITOR>SCAMPI.MAC.121, 25-May-84 14:19:58 by HALL
;Rearrange connection management routines to facilitate c.b. locks.
;Make SC.SCA call SC.AWQ, and change all callers of SC.SBS and SC.SNM.
;Make them call SC.SCA and SC.SNM, and allow them to unlock the c.b.
;between the two. Fix interrupt routines to avoid calling SC.SNM until
;the buffer has been returned.
;Affected routines: SC.CON, SC.LIS, SC.ACC, SC.REJ, SC.DIS, SC.CDT, SC.ARS,
; SC.DRQ
;Fix handling of canceled message buffers to handle interactions with
;other credit functions. It was possible to get confused and leave buffers
;queued to the port in excess of the current receive credit.
;Maintain return_credit, and dequeue one buffer for each time it is incremented.
;New routine, SC.GRB, does the dequeueing
;Affected routines: SC.RMG, SC.CMG, SC.CRS, SC.SMG
;SC.RCB - include return credit in count of buffers to be dequeued
;Avoid conflict between 2 contexts that need to send credit_request.
;Maintain interlock word, .CBPND, that indicates when a connection is
;in the process of sending a credit_request. Leave it locked until the
;credit_response is received. If we need to send another credit_request,
;we'll do it then.
;Affected routines: SC.CDT, SC.CRS
;Miscellaneous fixes:
;SC.IDL - call into SC.CDT to send credit_request
;SC.SMG - change send credit in one operation
; - handle receive credit better, including return credit
;SC.SNM - call SC.PTC if block state is zero
;SC.PON - include check for CION before the first CIOFF
;SC.CRD - don't load P4 until we need it
;SC.RQS - Don't clear block state until buffer has been sent
; UPD ID= 4206, SNARK:<6.MONITOR>SCAMPI.MAC.120, 10-May-84 20:33:38 by HALL
;Typo in sanity check in SC.RCB
; UPD ID= 4202, SNARK:<6.MONITOR>SCAMPI.MAC.119, 9-May-84 15:40:53 by LOMARTIRE
;Add temporary check for CBNPO going negative
; UPD ID= 4197, SNARK:<6.MONITOR>SCAMPI.MAC.118, 9-May-84 13:17:52 by LOMARTIRE
;Remove SC.ABT since it is no longer needed - use SC.DIS and give reason code
;Replace all .UCxxx codes with .CMNxx reason codes.
;Remove .RJNOM and use the reason code passed in the packet instead.
;Update table of contents.
;
; UPD ID= 4179, SNARK:<6.MONITOR>SCAMPI.MAC.117, 8-May-84 10:11:20 by HALL
;SC.CRD - return immediately if count is zero
; - change SOSG to SOSLE so that we continue until count is zero
;SC.CRM - take the buffers if we don't need to send credit_request
;SC.RCB - bitch if requeue credit is non-zero
; - Remove unnecessary saveac of P3
;SCL.MC and SCL.DC - don't save Q1 since we don't use it
; UPD ID= 4174, SNARK:<6.MONITOR>SCAMPI.MAC.116, 2-May-84 18:33:41 by HALL
;SC.CON and SC.LIS - don't store CBMNRC since it will be overwritten
;SC.CRD and SC.CRM - verify CID
;Convert receive credit away from defstrs
;SC.CRM - don't take buffers right away
; - decrement pending receive credit by full amount of request
; - send credit_request
;SC.DMA - ignore if v.c. is closed
; UPD ID= 4171, SNARK:<6.MONITOR>SCAMPI.MAC.115, 2-May-84 11:07:50 by LOMARTIRE
;Recycle CIDTAB. Add routine SC.FUB to return next uniqueness bits.
;Add CIDRFL and UNQRFL to count number of recycles done.
;Remove BDQHD and BDQTL since they are no longer used.
;Rearrange SC.ACB to create CID first then attempt to get CB buffer.
;
; UPD ID= 4168, SNARK:<6.MONITOR>SCAMPI.MAC.114, 1-May-84 19:12:59 by HALL
;Rearrange
; UPD ID= 4164, SNARK:<6.MONITOR>SCAMPI.MAC.113, 1-May-84 13:59:46 by LOMARTIRE
;Make SC.INT return +1 always.
;Add call to SC.SCS to record .SSCIA callback in ring buffer.
;
; UPD ID= 4161, SNARK:<6.MONITOR>SCAMPI.MAC.112, 1-May-84 10:23:57 by HALL
;Replace SC.TC with SC.CDT. Provide three entry points for the three
; occasions for sending credit_requests.
;SC.CRQ - maintain sign of credit field in incoming packet
; - compute returned value correctly when incoming value is negative
; - return 0 if send credit is already below minimum and incoming
; value is negative
; - give credit-available callback only if incoming credit is positive
;SC.CRS - maintain sign of credit field in incoming packet
; - update receive credit, not pending receive credit
; - send credit_request if needed
; - remove .SSCIA callback
; UPD ID= 4136, SNARK:<6.MONITOR>SCAMPI.MAC.111, 25-Apr-84 13:03:33 by LOMARTIRE
;Replace all .SCFxx error codes with equilvalent SCSxxx error codes.
;Replace .SCFNE code with SCSTBF at SAC.EH since this is the desired code.
;Make RG.SCS and RG.PKT calling comments accurate.
;
; UPD ID= 4132, SNARK:<6.MONITOR>SCAMPI.MAC.110, 25-Apr-84 11:11:54 by HALL
;SC.ERR - set CBFCVC in connection block for debugging purposes only
;SC.SMG - Check the connect ID
; - Put credit in packet only if positive
; - Increment SNDTAB only if we are successful
; - Increment send credit if we can't send
;SC.SDG - check the connect ID
; - Increment SNDTAB
; UPD ID= 4117, SNARK:<6.MONITOR>SCAMPI.MAC.109, 24-Apr-84 13:01:52 by HALL
;Handle credit in DMA -
; SC.SND and SC.REQ - set CBFNNC if fail due to lack of credit
; - allow sending if credit is 1
; SC.DMA - give callback if sysap is waiting for credit
;in SC.RIN make comment match code
;Allow sending if credit is 1
; UPD ID= 4102, SNARK:<6.MONITOR>SCAMPI.MAC.108, 18-Apr-84 20:00:33 by HALL
;Don't increment RECTAB at SC.INC. It was already done at SC.INT.
; UPD ID= 4097, SNARK:<6.MONITOR>SCAMPI.MAC.107, 18-Apr-84 17:33:27 by HALL
;Make arrival of credit_request and credit_response go through SC.INC
;Add necessary data to TABLEK
; UPD ID= 4057, SNARK:<6.MONITOR>SCAMPI.MAC.106, 10-Apr-84 13:23:36 by HALL
;New SC.ADG and SC.AMG
; Common code wherever possible
; Handle incoming packet when v.c. is closed. Previously, if v.c. was
; closed while packet was on response queue, receipt of packet
; would lead to closing the v.c. again
; Don't return failure to PHYKLP
; Change SOSG on CBDGR to SOSGE to allow receipt of datagram when
; one buffer queued
; SC.ADG was looking in c.b. for address of system block when c.b.
; didn't exist (SC.CSC had failed)
; SC.AMG was returning buffer to SCA but not decrementing receive
; credit if in middle of disconnect sequence
; If credit field is non-zero in application message, and sysap failed
; to send due to lack of credit, give callback
; UPD ID= 4055, SNARK:<6.MONITOR>SCAMPI.MAC.105, 6-Apr-84 11:40:10 by HALL
;SC.CRQ - Clear CBFNNC before calling the sysap
; UPD ID= 4043, SNARK:<6.MONITOR>SCAMPI.MAC.104, 3-Apr-84 14:46:00 by LOMARTIRE
;Test for recording of ring buffer events before SAVETs and STKVARs in
;the ring buffer jacket routines.
;Change the name of a few BUGxxx's to be more descriptive.
;Add SCAPCC BUGCHK for when SC.PTC called and the connect state not closed.
;Clean up labels in SC.SNM and SC.DEF
;
; UPD ID= 4041, SNARK:<6.MONITOR>SCAMPI.MAC.103, 3-Apr-84 10:29:17 by HALL
;SC.CSC - return error code. Change callers not to make up their own.
;SC.RDG and SC.RMG - recode to fix bugs and make routines match
; UPD ID= 4040, SNARK:<6.MONITOR>SCAMPI.MAC.102, 3-Apr-84 09:06:56 by HALL
;Remove all references to ALMTIM. Instead, AOS DDCFSF to get DDMP fork running
; Affected routines: SC.ONL, SC.ALD, SC.ABF
; UPD ID= 4039, SNARK:<6.MONITOR>SCAMPI.MAC.101, 3-Apr-84 07:20:13 by HALL
;In SC.DIS, if closing a listener, force connection state to closed. SC.PTC's
; sanity check was objecting.
; UPD ID= 4035, SNARK:<6.MONITOR>SCAMPI.MAC.100, 1-Apr-84 17:58:47 by GLINDELL
;Add ENDBS. to SC.S2P and SC.P2S
;
; UPD ID= 4034, SNARK:<6.MONITOR>SCAMPI.MAC.99, 1-Apr-84 14:22:28 by HALL
;SC.INC - call SC.VC1 instead of SC.CVC. Buffer was being returned to
;port twice
;
; UPD ID= 4026, SNARK:<6.MONITOR>SCAMPI.MAC.98, 31-Mar-84 17:37:13 by GLINDELL
;Add SC.S2P and SC.P2S to translate between system block index and port number
;
; UPD ID= 3985, SNARK:<6.MONITOR>SCAMPI.MAC.97, 27-Mar-84 14:14:46 by LOMARTIRE
;Make the default for RNGSW record all packet transactions
;
; UPD ID= 3973, SNARK:<6.MONITOR>SCAMPI.MAC.96, 25-Mar-84 10:39:42 by HALL
;Major changes to the way connections are terminated.
; 1. SC.DIS succeeds in any state. If the state is other than "open",
;the connection is marked "closed" but protocol continues until both sides
;agree.
; 2. SC.ABT will soon go away. At the moment, it calls SC.DIS
; 3. The "abort" bit no longer exists.
; 4. A sysap is called only when a connection terminates. If the
;other side initiates a disconnection on an open connection, the sysap
;is called when the disconnect_req arrives, not when the disconnect_rsp
;arrives.
; 5. In general, bits are no longer used to indicate the state of a
;connection. If the state is "closed", the sysap isn't interested in it
;any more.
; 6. A new bit, CBFPTC, indicates that the protocol is complete; that
;is, we don't expect to exchange any more messages with the other node.
;Specific changes:
;ModifY table K to allow any incoming packet when the connection
; state is closed.
;Modify table Y to leave state unchanged when connect_req is sent
;New routine, SC.PTC to declare protocol complete. Called as follows:
; SC.DIS - disconnect on listener
; SC.ERR - node went offline
; SC.ORS - connect_rsp no match
; SC.ARQ - accept_req when our side has disconnected
; SC.ARS - accept_rsp no match
; SC.RRQ - reject_req
; SC.RRS - reject_rsp
; SC.DRQ - disconnect_req when new state is closed
; SC.DRS - disconnect_rsp when new state is closed
;Don't set abort bit. Affected routines: SC.ABT,SC.ERR,SC.ORS,SC.DRQ, SC.DRS
;Don't test abort bit. Affected routines: SC.RAP, SC.SCM,SC.IDL, SC.ERR,
; SC.DMA, SC.ORS, SC.ARQ, SC.ARS, SC.RRQ, SC.RRS, SC.INC,SC.SNM, SC.DEF
;SC.DIS - set reap bit if connection state was listen
;SC.ABT - always call SC.DIS, don't do ring buffer
;SC.RAP - no longer check abort bit; do check for work queue FLINk and
;queued buffers, and postpone reaping if non-zero. If this happens repeatedly
;complain.
;SC.ACB - initialize connection state to closed
;SC.SCM - don't check abort and reap bits. Do check for listen state
; (don't care code wasn't doing that. WHY???).
;SC.ERR - notify sysap only if state is not closed. Don't check abort or
; reap bits. Don't set CBFCVC. Do call SC.PTC.
; - clear .CBNWQ when closing connection
;SC.IDL - get rid of check on abort and reap bits, combine other checks
; Send only if state is open
;SC.ORS - handle no-match when already closed
;SC.ARQ - set block state to send disconnect_req rather than calling SC.DIS
; - when sending no match, use standard routine.
; - store reason code in accept_response if no match
;SC.ARS - handle no match when already closed
;SC.RRQ - don't call sysap if already closed
;SC.DRQ - Notify sysap when remote side requests disconnect first, not at the
; end of the sequence.
; - put reason in Ac 3 before .SSRID callback
;SC.DRS - never call sysap. Declare protocol complete if new state is closed
;SC.SNM - If block state is 0 or reap bit is on, don't send request
;SC.INC - don't check CBFCVC. It no longer exists.
;SC.RQS - if block state is zero, assume v.c. is closed, and return+1
;Table X - new state for SC.CON is .CSCSE. This disagrees with corporate
;spec, which says to set the state only after the message is sent. It allows
;us to use a connection state of "closed" to mean that the sysap is not
;expecting to hear about this connection again.
;Implementation of state machine for requesting connection management
;functions. Routines call SC.OUT, which references table X, to check
;legality and get new connection and block states.
;Affected routines:
; SC.CON,SC.LIS,SC.ACC,SC.REJ,SC.DIS
;New approach to handling incoming packets if v.c. is already closed.
;We assume that the packet that caused the closure was important, and therefore
;we can't trust anything that comes after it. For now, only SC.INC implements
;this change, but all incoming packets should eventually be thrown away without
;interpretation.
;SC.INC - if v.c. state is closed, return +1.
;Miscellaneous fixes not directly related to the major edit:
;Call SC.CSC in SC.ACC, SC.REJ, SC.DIS
;SC.SMG and SC.SDG -Don't try to skip over INCR or DECR of CBNPO
;SC.ERR - add missing CION after SCAOF2
;SC.DMA - check for open connection and valid CID
;SC.ORQ - call SC.INC
;SC.ORQ,SC.ARQ - reorder events to avoid changing state without notifying sysap
;SC.CRS - bitch if can't get buffers, and go to SC.SAR. Don't fall through to
; this code
;SC.AWQ - don't queue if already on queue
; UPD ID= 3951, SNARK:<6.MONITOR>SCAMPI.MAC.95, 21-Mar-84 12:43:23 by LOMARTIRE
;Add calls to RG.SCS for callbacks
;Add feature specific data to RG.SCS - the following is placed in the entry:
; node number, CBA, callback reason code
;Add calls to RG.PKT for packet transmission/reception
;Add feature specific data to RG.PKT - the following is placed in the entry:
; node number, CBA, buffer addr, flags, prio,,length, MH$TYP, MH$SCI, MH$DCI
;Remove the old SCA ring buffer which was under the SCADBG conditional
;Remove the old PI ring buffer which was under the PIDBG conditional
;Also remove the PIDBG conditional
;Update table of contents
;
; UPD ID= 3950, SNARK:<6.MONITOR>SCAMPI.MAC.94, 20-Mar-84 21:33:49 by MCLEAN
;ADD REASON FOR DISCONNECT TO SC.DRQ
; UPD ID= 3942, SNARK:<6.MONITOR>SCAMPI.MAC.93, 19-Mar-84 09:55:00 by HAUDEL
;Put call to CLOSVC in SC.RST
; UPD ID= 3931, SNARK:<6.MONITOR>SCAMPI.MAC.92, 14-Mar-84 16:30:47 by LOMARTIRE
;Add calls to RG.SSC for connection management routines
;Add feature specific data to RG.SSC - the following is placed in the entry:
; node number, connect block address, .CBSTS, .CBFLG, .CBSCI, .CBDCI
;Add calls to RG.PIT in routines SC.PON and SC.POF
;Add feature specific data to RG.PIT - the following is placed in the entry:
; CHNCTL, PIFLAG
;
; UPD ID= 3917, SNARK:<6.MONITOR>SCAMPI.MAC.91, 13-Mar-84 12:17:14 by HAUDEL
;Add documentation for UPD ID 3906
; UPD ID= 3910, SNARK:<6.MONITOR>SCAMPI.MAC.90, 12-Mar-84 17:27:17 by HALL
;Work on BUGxxx's
; UPD ID= 3908, SNARK:<6.MONITOR>SCAMPI.MAC.89, 12-Mar-84 16:25:50 by LOMARTIRE
;Rework ring buffer - allow for selectivity of event recording
;Add ring buffer routines SC.RGI, SC.RHD, SC.RTE, and SC.RWR
;Also add ring buffer jackets for events to be recorded.
;
; UPD ID= 3906, SNARK:<6.MONITOR>SCAMPI.MAC.88, 12-Mar-84 15:49:05 by HAUDEL
;Change SC.STA and SC.RST. Move RMTSTA and RMTRST to PHYKLP.
; UPD ID= 3883, SNARK:<6.MONITOR>SCAMPI.MAC.87, 9-Mar-84 11:28:53 by HALL
;Changes in sending of connection management requests:
;For sending connection management requests, packet is no longer acquired,
;filled in, and queued. Instead, connection block's block state indicates type
;of message to be sent, and the connection block is queued. Packet is filled
;in only when it can be sent. Thus there is no failure return for sending
;requests, and connection management routines no longer try to build packets,
;acquire buffers, or send packets. Affected routines:
; SC.CON,SC.ACC,SC.REJ,SC.DIS,SC.TC,SC.IDL,SC.DRQ
;Handling of block state has changed significantly. Block state is non-zero
;only while a connection block is waiting to send a request. The sending
;routine zeroes it. Other routines that previously set or zeroed or tested
;it no longer do. Affected routines:
; SC.CON, SC.LIS, SC.ACC, SC.REJ, SC.DIS, SC.ERR,SC.ORS,SC.ARQ,SC.ARS,
; SC.RRQ, SC.RRS,SC.CRS
;New SC.SCA queues connection block to system block and calls SC.SNM.
;New SC.SNM uses block state to determine type of packet to send. If
;unable to allocate buffers requested by the sysap, it moves a connection
;block to the end of the queue and flags it for job 0. It returns when it
;sends one packet, is unable to proceed, or has no pending requests.
;SC.RQS generates the packet based on block state, sets new connection state,
;clears block state, and sends packet. It uses new table Y.
;New SC.DEF (replacing SC.ALM) finds queued connection blocks and allocates
;buffers. It tries to get them from SCA's pool in case some have been returned.
;In general, sending of connection management requests now conforms to corporate
;spec. However, SC.CON sets the connection state to connect_sent rather than
;waiting until the connect_req is sent.
;Additional changes related to this:
;SC.CON, SC.LIS - moved linking of connection block to system block to occur
; after connection block is initialized
;SC.ACC - store caller's connection data in the connection block. Previously,
; the remote node's data remained there forever. This change was necessary
; in order to have this data available when the accept_req is sent. If
; necessary, both sets of connection data could be stored in the
; connection block.
;SC.TC - return +1 always
;SC.ALM is replaced by cals to SC.DEF and SC.ALC. The latter is ALMCHK turned
;into a routine
;SC.RAP - if connection block is queued to system block's work queue, skip
; reaping it. SC.SNM or SC.ERR will dequeue it eventually.
;SC.ONL - add some sanity checks related to outgoing requests.
; - when node comes online, allocate 2 buffers for SCS control messages.
; Put one on port's message free queue, and make system block point
; to the other.
;SC.ERR - Clean work queue by resetting head and tail. No longer have buffers
; to return.
; - Clear system block's bit in SBSTUK
; - Return SCS control message buffers to SCA free pool.
;SC.SAR - Give incoming buffer to system block. Don't return to port's
; queue as before.
;SCACDT - Get op code from packet, not from caller
;Add K.CHK to TABLEK
;SC.INC - If no protocol error, and K.CHK is set, check op code against
; expected response
;Other changes not directly related to the above:
;SC.ALC - change queue count while CIOFF to update queue
;SC.ERR - set flag in system block when node goes offline. If flag is set
; when this routine is called, don't do anything
;Callers of SC.INC were handling +1 return incorrectly, losing the buffer.
;Now they go to SC.RIB. Affected routines:
; SC.ORS,SC.ARQ,SC.ARS,SC.RRQ,SC.RRS,SC.DRQ,SC.DRS
;SC.PAK - increment count only if send succeeds
;SC.INC - return +1 if protocol error when v.c. is closed. Check this before
; checking the abort bit.
; - If protocol error and incoming op code is disc_req or disc_rsp,
; close v.c. This may not be correct, but it more nearly matches the
; old code.
; UPD ID= 3839, SNARK:<6.MONITOR>SCAMPI.MAC.86, 2-Mar-84 15:52:08 by HALL
;SC.INC - if protocol error and v.c has been closed, return +1
; - if protocol error, aborted, and received disc_req, close the v.c.
; UPD ID= 3780, SNARK:<6.MONITOR>SCAMPI.MAC.85, 28-Feb-84 13:12:28 by LOMARTIRE
;Add SC.NOD to return node number given connect ID
;Modify some BUGxxx to include node number and CID when appropriate
;
; UPD ID= 3755, SNARK:<6.MONITOR>SCAMPI.MAC.84, 25-Feb-84 16:50:50 by HALL
;SC.REJ - don't put listener back on "don't care" queue
; UPD ID= 3754, SNARK:<6.MONITOR>SCAMPI.MAC.83, 25-Feb-84 07:59:33 by HALL
;Introduction of state machine for processing incoming SCS control packets --
;Includes changes to match corporate SCA spec version 6, as follows:
; Add states accept_sent and reject_sent
; Remove sub-states of closed
; After sending accept_request, state is accept_sent. Old code left it
; as connect_received
; When we receive an accept_req, and state is closed, send an accept_rsp
; with no match. Old code treated as error and closed the v.c.
; unless the "aborted" bit was on
; When we receive accept_rsp, expect state to be accept_sent. Old
; code expected connect_received
; After sending reject_request, state is reject_sent. Old code left
; is as listen
; When we receive reject_response, expect state to be reject_sent.
; Old code expected listen
; After receiving reject_response, state is closed. Old code left is
; as listen
;New routine, SC.INC, is called for incoming packets to determine validity
; for current state, and return new state and op code of response
; Called by SC.ORS,SC.ARQ,SC.ARS,SC.RRQ,SC.RRS,SC.DRQ,SC.DRS
;SC.CON - store minimum send credit in minimum_credit field
;SC.ACC - deferred new state is accept_sent
;SC.REJ - don't set state to listen
;SC.REJ - deferred new state is reject_sent
;SC.RNG - get destination CID rather than credit field
;SC.OFL - set new state to closed instead of closed_v.c. failure
;SC.ORQ - rearrange copying of input, move SOR.NM to end of routine,
; store minimum_Credit from packet into mininum receive credit
;SC.ORS - store other CID in connection block only if there's a match
; - New state is closed instead of closed_no_match if no match
;SC.ARQ - If current state is closed, go send accept_response with "no
; match"
; - At SAR.NG, assume op code was set up by SC.INC
;SC.RRQ - new state is closed instead of closed_rejected
;SC.RRS - check on "aborted" was reversed
; store new connection state as closed instead of leaving as listen
;
;SC.IDL - SCATMO BUGCHK when timed out a connection
;SC.CVC - Changed SCACVC to a BUGCHK (may be temporary), added node number
; to optional data
;SC.OFL - set CBFCVC flag in connection block when v.c. is closed. Test
; it in SC.INC. At the moment, this an CBFABT will be set when a v.c.
; is closed. This may change over time.
;
;Changes to routines that send responses. SC.RSP now fills in common data
; and then calls a specific routine according to op code for filling in
; the rest. Callers were changed to expect this: SC.ORQ, SC.ARQ,
; SC.RRQ, SC.DRQ,SC.CRQ.
;Name changes: SC.RS1 to SC.PAK, SC.MDS to SC.SMD, SC.MDR to SC.RMD
; UPD ID= 3717, SNARK:<6.MONITOR>SCAMPI.MAC.82, 21-Feb-84 13:22:13 by LOMARTIRE
;Remove name WQANB for location .WQANB since entire word is needed
;Fix manipulations of WQFLG to work with the correct half word
;Add name WQLFW to refer to the entire .WQLEN word
;Use names WQDG and WQMSG instead of .WQNBF
;
; UPD ID= 3714, SNARK:<6.MONITOR>SCAMPI.MAC.81, 21-Feb-84 13:01:09 by CDUNN
;More TCO 6.1127 - Change SC.CON and SC.LIS to use an address instead of
;a byte pointer to the process strings.
;
; UPD ID= 3689, SNARK:<6.MONITOR>SCAMPI.MAC.80, 15-Feb-84 11:05:35 by LOMARTIRE
;Add extra needed field to SCAMCR BUGCHK to insure correct assembly
;
; UPD ID= 3688, SNARK:<6.MONITOR>SCAMPI.MAC.79, 15-Feb-84 08:54:31 by LOMARTIRE
;Fix routines in which LNKMFQ/LNKDFQ used to fail to return +1 always
;Remove unneeded error routines and SC.P2Q and SC.P2M
;Fix SCAMCR BUGCHK so that it assembles correctly and fix some typos
;
; UPD ID= 3686, SNARK:<6.MONITOR>SCAMPI.MAC.78, 12-Feb-84 13:30:46 by HALL
;SC.SCA was loading connection state when it wanted block state
; UPD ID= 3681, SNARK:<6.MONITOR>SCAMPI.MAC.77, 10-Feb-84 14:37:47 by LOMARTIRE
;Change all system block references to use defined structure if one available.
;All values which are not word location independent will not use the structure.
;These include FLINKs and BLINKs and other values with must be a full word.
;
; UPD ID= 3680, SNARK:<6.MONITOR>SCAMPI.MAC.76, 9-Feb-84 10:43:10 by HALL
;Fix bug in SC.RSP, in which SC.RS1 was being called without doing
;a STKVAR
;In SC.SCA, zero FLINK when adding buffer to end of work queue
; UPD ID= 3676, SNARK:<6.MONITOR>SCAMPI.MAC.75, 8-Feb-84 17:43:35 by HALL
;General cleanup of interrupt-level code that handles incoming SCS control
;messages. Includes creation of common exits, SC.SAR and SC.RIB.
;The functions performed there will probably change over time. All
;incoming responses lead to SC.SAR, where we attempt to send the next
;queued SCS message, and fall through to SC.RIB.
;All incoming requests cause a response to be sent if possible, and go
;to SC.RIB on failure. SC.RIB returns the buffer to the free queue.
;
;New routine, SC.RSP, stores common data into a packet and sends it
;Routines that receive requests and send responses now call this instead of
;calling SNDMSG directly.
;
;The following functional changes were made as well:
;SC.DRQ - If call to SC.SCA fails, go to usual code for notifying sysap
; of disconnect
;SC.RRQ - Don't assume T3 preserved over call to SC.RSP. Get reason for
; rejection from c.b. when calling sysap
;SC.ORQ - Zero minimum_credit field in CONNECT_RSP
;SC.ARQ - store minimum_credit field of packet into connect block's
; minimum receive credit field
;Set CBDSBI in SC.SCM rather than SC.ORQ. Don't set CBDSBI in SC.ORS because
; SC.CON did it
;
; UPD ID= 3673, SNARK:<6.MONITOR>SCAMPI.MAC.74, 8-Feb-84 12:18:40 by LOMARTIRE
;Use defined structures for all message header references
;
; UPD ID= 3666, SNARK:<6.MONITOR>SCAMPI.MAC.73, 8-Feb-84 08:38:31 by LOMARTIRE
;Account for the fact that LNKDFQ and LNKMFQ now return +1 always
;
; UPD ID= 3654, SNARK:<6.MONITOR>SCAMPI.MAC.72, 3-Feb-84 19:36:51 by HALL
;In SC.ORS, add P4 to reference to SBSBI
;Add SC.RSP
; UPD ID= 3598, SNARK:<6.MONITOR>SCAMPI.MAC.71, 31-Jan-84 11:38:41 by LOMARTIRE
;Change OPSTRs to OPSTRMs for operations to memory
; Fix a few credit update manipulations
;
; UPD ID= 3593, SNARK:<6.MONITOR>SCAMPI.MAC.70, 30-Jan-84 17:06:36 by CDUNN
;More TCO 6.1127 - Add missing SETZM in SC.RLD to zeor the forward link of the
;new buffer.
;
; UPD ID= 3592, SNARK:<6.MONITOR>SCAMPI.MAC.69, 30-Jan-84 16:11:36 by MOSER
;Fix SC.RLD and SC.RBF to do BLT correctly.
;
; UPD ID= 3582, SNARK:<6.MONITOR>SCAMPI.MAC.68, 28-Jan-84 18:29:55 by MCLEAN
;ADD OPSTR'S TO .CBXXX
;
; UPD ID= 3574, SNARK:<6.MONITOR>SCAMPI.MAC.67, 28-Jan-84 01:41:51 by MCLEAN
;MASSIVE EDITS TO CONFORM TO STANDARDS
;
; UPD ID= 3570, SNARK:<6.MONITOR>SCAMPI.MAC.66, 27-Jan-84 22:04:45 by MCLEAN
;REDIT MISSED CHANGE OF ENDTV TO ENDSV OR SOMETHING....
;REMOVE IMPLIED (P1) REFERENCES
;
; UPD ID= 3569, SNARK:<6.MONITOR>SCAMPI.MAC.65, 27-Jan-84 17:53:30 by MCLEAN
;Make a few subroutines and fix up credit stuff
;
; UPD ID= 3563, SNARK:<6.MONITOR>SCAMPI.MAC.64, 26-Jan-84 22:27:01 by MCLEAN
;FIX TYPO.
;
; UPD ID= 3562, SNARK:<6.MONITOR>SCAMPI.MAC.63, 26-Jan-84 22:10:59 by MCLEAN
;FIX SC.SNM CAUSE IT DOESN'T GIVE CREDIT.....
;
; UPD ID= 3561, SNARK:<6.MONITOR>SCAMPI.MAC.62, 26-Jan-84 14:38:57 by MCLEAN
;ADD NEW PARAMETER FOR SC.MAP
;
; UPD ID= 3547, SNARK:<6.MONITOR>SCAMPI.MAC.61, 25-Jan-84 22:01:46 by MCLEAN
;FIX SCL.TC THE LABEL IS OFF BY 1
;
; UPD ID= 3546, SNARK:<6.MONITOR>SCAMPI.MAC.60, 25-Jan-84 21:22:29 by MCLEAN
;PUT ENDTV.'S IN ALL THE NECESSARY PLACES.
;
; UPD ID= 3545, SNARK:<6.MONITOR>SCAMPI.MAC.59, 25-Jan-84 21:09:30 by MCLEAN
;MISSING ENDTV. AT SC.BBF AND MISPELLING IN SC.CMG
;
; UPD ID= 3533, SNARK:<6.MONITOR>SCAMPI.MAC.58, 24-Jan-84 22:33:03 by MCLEAN
;SC.ADG SHOULD NOT CLOSE SC.CSC
;
; UPD ID= 3530, SNARK:<6.MONITOR>SCAMPI.MAC.57, 24-Jan-84 20:51:12 by MCLEAN
;ADD EXTRA ARGUMENT TO MAPBUF AND THIS WILL BE CHANGED SOON TO SS.RDW
;
; UPD ID= 3528, SNARK:<6.MONITOR>SCAMPI.MAC.56, 24-Jan-84 16:56:58 by MOSER
;FIX SC.CSP
;
; UPD ID= 3504, SNARK:<6.MONITOR>SCAMPI.MAC.55, 22-Jan-84 13:19:14 by MCLEAN
;BUFFER FIXES AND MISSING SETZM DFQCNT
;
; UPD ID= 3492, SNARK:<6.MONITOR>SCAMPI.MAC.54, 20-Jan-84 11:10:45 by CDUNN
;More TCO 6.1127 - Add buffer deferral support. Also a few random fixes
;
; UPD ID= 3412, SNARK:<6.MONITOR>SCAMPI.MAC.53, 6-Jan-84 05:42:48 by GRANT
;MAPBUF is now a BLCAL.
;
; UPD ID= 3394, SNARK:<6.MONITOR>SCAMPI.MAC.52, 3-Jan-84 07:17:09 by HALL
;In SC.RRS, fix SETZRO of CBBKST so that it works
;In SAR.AB, remove the comma after SETZM P5
;
; UPD ID= 3363, SNARK:<6.MONITOR>SCAMPI.MAC.51, 22-Dec-83 21:17:08 by GRANT
;Use BLCAL. for LNKDFQ and LNKMFQ
;
; UPD ID= 3355, SNARK:<6.MONITOR>SCAMPI.MAC.50, 22-Dec-83 09:18:46 by HALL
;Fix SC.PON and SC.POF: test for being at interrupt level was backwards.
; Channel 7 (instead of 5) was being turned on and off
;
; UPD ID= 3348, SNARK:<6.MONITOR>SCAMPI.MAC.49, 20-Dec-83 08:15:53 by GRANT
;Use BLCAL. for ULNKDG and ULNKMG
;
; UPD ID= 3333, SNARK:<6.MONITOR>SCAMPI.MAC.48, 16-Dec-83 15:50:35 by HALL
;Change calls to SNDDG and SNDMSG to get arguments right
;Call CLOSVC with BLCAL
;
; UPD ID= 3301, SNARK:<6.MONITOR>SCAMPI.MAC.47, 13-Dec-83 13:15:53 by CDUNN
;More TCO 6.1127 - Random fixes to online/offline stuff for handling VCs that
;come back. Also random DMA help...
;
; UPD ID= 3287, SNARK:<6.MONITOR>SCAMPI.MAC.46, 11-Dec-83 20:19:51 by GRANT
;In SSC.LP and SC.CLK, use new symbol VC.OPN.
;Change calling convention comments for SC.DMA - it accepts T1,T2 not T1,P4.
;
; UPD ID= 3255, SNARK:<6.MONITOR>SCAMPI.MAC.45, 5-Dec-83 19:22:37 by CDUNN
;More TCO 6.1127 - Add support for maintenance data send from JSYS level.
;Also some random fixes.
;
; UPD ID= 3185, SNARK:<6.MONITOR>SCAMPI.MAC.44, 17-Nov-83 16:18:38 by CDUNN
;More TCO 6.1127 - Remove support for mapping user buffers to monitor space
;on packet send. Handle monitor buffer being used for copy of user packet send
;data.
;
; UPD ID= 3137, SNARK:<6.MONITOR>SCAMPI.MAC.43, 11-Nov-83 10:46:56 by CDUNN
;More TCO 6.1127 - Make SC.CVC and its callers agree on how its returns
;
; UPD ID= 3118, SNARK:<6.MONITOR>SCAMPI.MAC.42, 8-Nov-83 11:47:23 by CDUNN
;More TCO 6.1127 - Move SAVEAC to top of SC.RCB so AC is always saved. Also
;add lost SETZM of first word in buffer handed to LNKMFQ by SC.P2Q
;
; UPD ID= 2874, SNARK:<6.MONITOR>SCAMPI.MAC.41, 2-Sep-83 11:27:29 by CDUNN
;More TCO 6.1127 - Add DBIU (cousin of MBIU) to add scratch datagram buffers
;
; UPD ID= 2824, SNARK:<6.MONITOR>SCAMPI.MAC.40, 11-Aug-83 15:32:59 by CDUNN
; More TCO 6.1127 - Fix SC.ALM to correctly create and lock pages. A number
;of random fixes as well.
;
; UPD ID= 2761, SNARK:<6.MONITOR>SCAMPI.MAC.39, 24-Jul-83 02:01:20 by CDUNN
; More TCO 6.1127 - Fix SC.ABF to give the return address for the buffer as
;promised.
;
; UPD ID= 2741, SNARK:<6.MONITOR>SCAMPI.MAC.38, 22-Jul-83 15:19:49 by CDUNN
;More TCO 6.1127 - General code cleanup. Removal of memory managment routines
;that try to do partial request returns. They now return all or nothing...
;
; UPD ID= 2606, SNARK:<6.MONITOR>SCAMPI.MAC.37, 20-Jun-83 16:12:30 by HALL
;TCO 6.1689 - Move fork tables to extended section
;Reference FKPGS via DEFSTR
;
; UPD ID= 2555, SNARK:<6.MONITOR>SCAMPI.MAC.36, 3-Jun-83 17:13:23 by CDUNN
;More TCO 6.1127 - Fix SC.ONL not to do anything with memory managment routines
;(Fixes ILMNRF at startup after crash). Make SC.SNM not loop to bad places on
;finding a stale message on work queue.
;
; UPD ID= 2531, SNARK:<6.MONITOR>SCAMPI.MAC.35, 26-May-83 18:07:16 by CDUNN
;More TCO 6.1127 - Fix SC.DRQ and SC.DRS to not light the abort bit on
;JSYS connections. Also make 10/11 word format byte pointers global
;
; UPD ID= 2493, SNARK:<6.MONITOR>SCAMPI.MAC.34, 19-May-83 11:14:48 by MURPHY
;Put EPGMAP in another section.
;
; UPD ID= 2461, SNARK:<6.MONITOR>SCAMPI.MAC.33, 12-May-83 17:14:28 by CDUNN
;More TCO 6.1127 - Add code to SC.RAP to observe the CBFKIL bit when
;deleting CB's
;
; UPD ID= 2420, SNARK:<6.MONITOR>SCAMPI.MAC.32, 4-May-83 13:49:30 by CDUNN
;More TCO 6.1127 - Change SC.INT and related code to return message length
;in the packet her rather than in another AC (I.E. Q1)
;
; UPD ID= 2366, SNARK:<6.MONITOR>SCAMPI.MAC.31, 27-Apr-83 23:45:11 by CDUNN
;More TCO 6.1127 - Make SC.CLK check port VC state before any other processing.
;Add code to SC.OFL/SC.ERR to mark all connections as closed by VC error.
;
; UPD ID= 2351, SNARK:<6.MONITOR>SCAMPI.MAC.30, 26-Apr-83 21:52:13 by CDUNN
;More TCO 6.1127 - Fix sense of F.RTB test in SC.SMG. Increment outstanding
;packet on correct send type. Fixes for idle chatter in SC.CLK and SC.INT
;
; UPD ID= 2326, SNARK:<6.MONITOR>SCAMPI.MAC.29, 22-Apr-83 01:41:13 by CDUNN
;More TCO 6.1127 - Change SC.SMG and SC.SMG to no do conversion from word
;count to byte count. Allow PHYKLP to do that. Also modify SC.INT to hand
;the SYSAP the length of the packet received since we now get it from PHYKLP.
;
; UPD ID= 2307, SNARK:<6.MONITOR>SCAMPI.MAC.28, 19-Apr-83 16:25:34 by CDUNN
;More TCO 6.1127
;1. Fix calling sequences for SNDMSG, flags and priority sometimes reversed
;2. Fix SC.DRQ to use a different buffer for the request sent after the
;response.
;3. Fix SC.SCA to not smash T3 on entry.
;
; UPD ID= 2251, SNARK:<6.MONITOR>SCAMPI.MAC.27, 12-Apr-83 20:06:48 by CDUNN
;More TCO 6.1127
;1. Fix SC.SCM to correctly dequeue entries from the dont care listener queue.
;2. Fix SC.ALM to use MLKMA instead of FMLKPG.
;3. Fix SC.REQ to do correct check for sufficient credits and do SOS to credit.
;
; UPD ID= 2231, SNARK:<6.MONITOR>SCAMPI.MAC.26, 10-Apr-83 18:17:14 by CDUNN
;More TCO 6.1127 - Fix sense of test for credit in SC.SND
;
; UPD ID= 2211, SNARK:<6.MONITOR>SCAMPI.MAC.25, 8-Apr-83 06:59:01 by GRANT
;TCO 6.1127 - In SC.ALD, zero the SYSAP's header area when assigning a buffer
;
; UPD ID= 2198, SNARK:<6.MONITOR>SCAMPI.MAC.24, 8-Apr-83 04:41:35 by CDUNN
;More TCO 6.1127
;1. Add address of system block to the SCA ring buffer entry. Also add
;buffer address and PC of caller to the ring buffer entry. Fix init of the end
;of the SCA ring buffer.
;2. Fix SC.ALD to zero T2 when taking an error return.
;3. Fix SC.SCM to dequeue dont care listeners only once, not twice.
;4. Add SC.CLK to do idle chatter.
;
; UPD ID= 2161, SNARK:<6.MONITOR>SCAMPI.MAC.23, 4-Apr-83 20:51:03 by CDUNN
;More TCO 6.1127 - Change default for PIDBG to be off...
;
; UPD ID= 2136, SNARK:<6.MONITOR>SCAMPI.MAC.22, 3-Apr-83 20:35:55 by CDUNN
;More TCO 6.1127 -
;1. Fix SC.ALM to use the number of buffers per page, not buffer size when
;determining page count to obtain.
;2. Fix SCA protocol violation in disconnect. Send a response to a DISC_REQ
;in ALL cases, not just some. Then do other checking...
;3. Fix AC typos in SC.DIS.
;4. Add routine SC.PRT to return the local port number on a KL with a single
;CI port.
;5. Make rejecting a connect to a listener put you back in listen, not dumping
;the connection.
;6. Support SC.REJ going to listen again by makeing SC.LCB dequeue buffer
;from current queue before putting on a new one...
;7. Add code to support the SCA ring buffer. Routine SC.RNG is the collector
;8. SC.OFL/SC.ERR remove STKVAR and use P5 instead.
;9. Fix SC.ONL to correctly calculate new buffer minimums based on system count
;10. Replace PION and PIOFF with CION and CIOFF which go NOSKED and turn off
;the channel, rather than all of PI.
;11. Add missing CION to SC.ALD exit routine
;
; UPD ID= 2066, SNARK:<6.MONITOR>SCAMPI.MAC.20, 23-Mar-83 01:21:40 by CDUNN
;More TCO 6.1127 - Add SCA overhead byte count to send message and datagrams
;
; UPD ID= 2064, SNARK:<6.MONITOR>SCAMPI.MAC.19, 23-Mar-83 00:39:26 by CDUNN
;More TCO 6.1127 - Remove referances to .CBDGB, replace with .CBDGR. Also
;fix SC.ADG to check the number of datagrams buffers queued for a connect and
;drop datagrasm if there are none. Also install .CBCDD (count of dropped
;datagrams) in the CB.
;
; UPD ID= 2061, SNARK:<6.MONITOR>SCAMPI.MAC.18, 22-Mar-83 10:12:43 by GRANT
;TCO 6.1127 - In SC.REJ, make proper test for connection state. In SC.RRQ, put
;correct destination CID in the packet being assembled.
;
; UPD ID= 2055, SNARK:<6.MONITOR>SCAMPI.MAC.17, 22-Mar-83 00:49:38 by CDUNN
;More TCO 6.1127 - Fix SC.ALD to setup T2 as promised for +1 return. Also
;add counter to SC.RCB for number of CB's killed. Teach SC.SCM to watch the
;abort and reap bits in "don't care" listeners.
;
; UPD ID= 2022, SNARK:<6.MONITOR>SCAMPI.MAC.16, 19-Mar-83 00:21:09 by CDUNN
;More TCO 6.1127 - Fix SC.SCM to check name local SYSAP wishes to talk to
;versus source name of remote on don't care listeners.
;More TCO 6.1127 - Dont be PIOFF in certain places where it turns out page
;faults are possible. Also fix sense of check for last buffer in SC.RCB when
;doing "dont care listeners".
;
; UPD ID= 2013, SNARK:<6.MONITOR>SCAMPI.MAC.14, 17-Mar-83 03:07:54 by CDUNN
;More TCO 6.1127 - 1. Fix SC.LCB to correctly link dont care listeners onto
;fork CB queue
;2. Fix SC.RCB to correctly handle deletion of dont care listeners
;3. In init, add general pool buffer to minimum count.
;4. Force SC.ALM to not run if we have not inited yet. (Prevents crash when
;no nodes are up at init and one shows up later)
;
; UPD ID= 2012, SNARK:<6.MONITOR>SCAMPI.MAC.13, 16-Mar-83 18:19:14 by CDUNN
;More TCO 6.1127 - Fix error in last edit.
;
; UPD ID= 1989, SNARK:<6.MONITOR>SCAMPI.MAC.12, 15-Mar-83 02:00:26 by CDUNN
;More TCO 6.1127 - Init tail queue to correct address when not current fork and
;deleteing last entry on a fork connect block queue.
;Also, TEMPORARILY! turn on RS%SE0 in calls to ASGRES until extended free
;space code is done...
;
; UPD ID= 1954, SNARK:<6.MONITOR>SCAMPI.MAC.11, 10-Mar-83 00:30:54 by CDUNN
;More TCO 6.1127 - Code DMA routines so rest of the world can properly
;access DMA code in port driver.
;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 1981, 1984.
;ALL RIGHTS RESERVED.
SEARCH SCAPAR,PROLOG
TTITLE (SCAMPI,,<- Systems Communications Architecture service>)
;SCAMPI - Systems Communications Architecture for Multi Processor Interconnects
; Not to be confused with an Italian shrimp dish.
;
;
; Note:
; Some abbreviations appear EVERYWHERE in this module. They are:
;
; CB - Connection block
; SB - System block
; SBI - System block index - same as node number
; CID - Source connect ID
; PPD - Physical port driver
; MBZ - Must be zero
; BDT - Buffer descriptor table (xlation for JSYS buffers to monitor buffers)
;
EXTERN SCSINI,SCSTCQ,SCSBCQ
EXTERN MSG,DG,XFER,EVT,SCSDEQ
EXTERN MAPBUF,UMAP,SNDDAT,REQDAT,OPENVC
EXTERN LOCPRT
; DESIGN NOTES:
;If a connection's state is closed, either the sysap disconnected, or it's
;been notified that the connection is closed. If CBFPTC is on, no more
;protocol is necessary (we won't send anything else over the wire, or
;receive anything).
;When CBFPTC is set, we also set CBFRAP unless it's a JSYS connection. SCSJSY
;sets reap if it is. We still can't get rid of the c.b. until the block
;has been dequeued from the work queue, and all its outstanding packets
;have been returned. The first case probably doesn't happen, but it's
;conceivable that we were about to send a credit request when the connection
;was closed. SC.SNM will dequeue the block eventually and find its block
;state set to zero. This avoids trying to dequeue it at the time that
;CBFPTC is set.
;A connection may be closed but not PTC. The opposite is not true.
; FUNCTIONAL NOTES:
;SC.ACC no longer returns the address of the other side's connect data.
;That was risky anyway because it points at a connection block that could
;conceivably go away.
;.SSRID callback occurs when the other side initiates a disconnect, rather
;than when it confirms one. It provides a reason code in T3.
;The TOPS-20 spec said that the sysap could provide a "minimum receive
;credit" value, which controlled when the sysap received a "little credit
;left" callback. That is no longer true. The code now implements the
;corporate spec, which says that the other side will set this value in
;the minimum_credit field of the connect_request or accept_request
;After receiving a connection request, a listening sysap must open another
;listener. THis is true for both accepting and rejecting.
COMMENT |
Comments on Ring Buffer Usage
The ring buffer will record various events which occur. Currently,
the following can be recorded: SYSAP to SCA calls, SCA callbacks, buffer
manipulation, packet transactions, PI transitions, port queue
manipulation, and interlocks. The recording of events is dictated by the
setting of RNGSW. If the appropriate bit is set, then that event will be
recorded when it occurs. These bit definitions are defined in SCAPAR and
are as follows for the corresponding events listed above: RSYSCA, RSCASY,
RBUFMG, RPACKT, RPITRN, RPRTQU, RINTLK.
The format of a ring buffer entry is described in SCAPAR. Briefly, an
entry starts with the entry header word (currently -77,,-77). The rest of
the entry header follows as described in SCAPAR. Every entry has this
common header. Following the header is the feature event specific data.
Each feature event has its own feature specific data which is placed in
the buffer entry. For this reason, ring buffer entries are of variable
size depending upon feature type being recorded (which depends upon the
setting of RNGSW). [The length of the buffer entry for each event is kept
in the table ENTLTB which is indexed by event code. These event codes are
defined in SCAPAR.] Following the feature specific data is the buffer
entry tail. Currently, this is one word which points to the start of the
buffer entry. This word can be used to easily step back through the ring
buffer.
RNGSIZ is the size in words of the ring buffer. At startup, SCA will
get the number of pages defined by symbol RBFLEN (in SCAPAR) for ring
buffer usage. Currently, this is 5 pages.
RNGTOP is a pointer to the top of the ring buffer pages. RNGBOT is a
pointer to the bottom of the ring buffer pages and will be RBFLEN pages
greater than the value in RNGTOP since the ring buffer is allocated in
contiguous pages.
RNGNUM is the total number of ring buffer entries written. RNGCUR is
the pointer to the top of the most recent entry completed. Use this value
as the first entry to investigate and work backwards through less recent
entries. RNGADR is used by the various ring buffer routines as a pointer
into the ring buffer.
|
SUBTTL Table of Contents
; Table of Contents for SCAMPI
;
;
; Section Page
; 1. Local variable storage for SCS . . . . . . . . . . . . 6
; 2. State Tables . . . . . . . . . . . . . . . . . . . . . 7
; 3. Initialization code. . . . . . . . . . . . . . . . . . 16
; 4. Calls from sysap
; 4.1. SC.SOA (Set ONLINE address) . . . . . . . . . 17
; 4.2. Connection management . . . . . . . . . . . . 18
; 4.2.1. SC.CON (Connect) . . . . . . . . . . 20
; 4.2.2. SC.LIS (Listen). . . . . . . . . . . 23
; 4.2.3. SC.ACC (Accept). . . . . . . . . . . 26
; 4.2.4. SC.REJ (Reject). . . . . . . . . . . 28
; 4.2.5. SC.DIS (Disconnect). . . . . . . . . 29
; 4.3. Messages and datagrams. . . . . . . . . . . . 32
; 4.3.1. SC.SDG (Send a datagram) . . . . . . 32
; 4.3.2. SC.SMG (Send a message). . . . . . . 35
; 4.3.3. SC.RDG (Receive a datagram). . . . . 39
; 4.3.4. SC.RMG (Receive a message) . . . . . 40
; 4.3.5. SC.CRD (Cancel Receive datagram) . . 42
; 4.3.6. SC.CRM (Cancel receive message). . . 43
; 4.4. Named buffers . . . . . . . . . . . . . . . . 44
; 4.4.1. SC.MAP (Map a buffer). . . . . . . . 44
; 4.4.2. SC.UMP (Unmap a mapped buffer) . . . 45
; 4.4.3. SC.SND (Send DMA data) . . . . . . . 46
; 4.5. State polling . . . . . . . . . . . . . . . . 48
; 4.5.1. SC.CSP (Connect state poll). . . . . 48
; 4.5.2. SC.DCI (Return destination connect ID) 49
; 4.5.3. SC.RCD (Return configuration data) . 50
; 4.5.4. SC.NOD (Return node number given CID) 51
; 4.5.5. SC.RAC (Return available credit) . . 52
; 4.5.6. SC.PRT (Return local port number). . 53
; 4.6. Maintenance . . . . . . . . . . . . . . . . . 54
; 4.6.1. SC.RST (Reset remote system) . . . . 54
; 4.6.2. SC.STA (Start remote node) . . . . . 55
; 5. Call from port driver. . . . . . . . . . . . . . . . . 56
; 5.1. SC.ONL (Node has come online) . . . . . . . . 56
; 5.2. SC.ERR (Node(s) have gone away) . . . . . . . 60
; 5.3. SC.DMA (DMA operation complete) . . . . . . . 64
; 5.4. Incoming buffer
; 5.4.1. SC.INT (Buffer arrival). . . . . . . 65
; 5.4.2. SC.ORQ (Connect request) . . . . . . 68
; 5.4.3. SC.ORS (Connect response). . . . . . 70
; 5.4.4. SC.ARQ (Accept request). . . . . . . 71
; 5.4.5. SC.ARS (Accept response) . . . . . . 73
; 5.4.6. SC.RRQ (Reject request). . . . . . . 74
; 5.4.7. SC.RRS (Reject response) . . . . . . 75
; 5.4.8. SC.DRQ (Disconnect request). . . . . 76
; 5.4.9. SC.DRS (Disconnect response) . . . . 79
; 5.4.10. SC.CRQ (Credit request). . . . . . . 80
; 5.4.11. SC.CRS (Credit response) . . . . . . 82
; 5.4.12. SC.INC (Connection management) . . . 84
; 5.4.13. SC.ADG/SC.AMG (application datagram/message) 88
; 6. Periodic functions . . . . . . . . . . . . . . . . . . 91
; 6.1. SC.CLK (Dispatch) . . . . . . . . . . . . . . 91
; 6.2. SC.IDL (Idle chatter) . . . . . . . . . . . . 92
; 6.3. SC.RAP (Reap old connections) . . . . . . . . 94
; 6.4. SC.ALM (Allocate buffers) . . . . . . . . . . 100
; 6.5. SC.ALC (Allocate buffers for pool). . . . . . 101
; 6.6. SC.DEF (Allocate deferred buffers for sysap). 103
; 7. Connection management utility routines . . . . . . . . 106
; 7.1. SC.SCA (Send connection management message) . 106
; 7.2. SC.SNM (Send next connection management message) 107
; 7.3. SC.AWQ (Add entry to work queue). . . . . . . 110
; 7.4. SC.RWQ (Remove entry from work queue) . . . . 111
; 7.5. SC.ACB (Allocate a connection block). . . . . 112
; 7.6. SC.LCB (Link a new CB). . . . . . . . . . . . 115
; 7.7. SC.SCM (Search for connection match). . . . . 118
; 7.8. SC.CSC (CID sanity check) . . . . . . . . . . 122
; 7.9. SC.CDT (Send credit_request). . . . . . . . . 123
; 7.10. SC.CVC (Close a virtual connection) . . . . . 126
; 7.11. SC.SDM (String and data move to CB) . . . . . 127
; 7.12. SC.OUT (Check sysap call) . . . . . . . . . . 128
; 7.13. SC.RSP (Send a response). . . . . . . . . . . 129
; 7.14. SC.RQS (Send a request) . . . . . . . . . . . 130
; 7.15. SC.PAK (Send a packet). . . . . . . . . . . . 133
; 8. Buffer management routines . . . . . . . . . . . . . . 135
; 8.1. SC.SBT (Set buffer thresholds). . . . . . . . 135
; 8.2. SC.BUF. . . . . . . . . . . . . . . . . . . . 140
; 8.3. SC.ALD (Allocate long datagram buffers) . . . 142
; 8.4. SC.ABF (Allocate a buffer/buffers). . . . . . 143
; 8.5. SC.CMG/SC.CDG (Create MSG/DG buffers) . . . . 144
; 8.6. SC.BBF (Break memory into buffers). . . . . . 145
; 8.7. SC.RBF (Return a message buffer). . . . . . . 146
; 8.8. SC.RLD (Return a datagram buffer) . . . . . . 147
; 8.9. SC.TMQ/SC.TDQ (Trace free queue). . . . . . . 148
; 9. Byte-swapping routines . . . . . . . . . . . . . . . . 149
; 9.1. SC.RIN (Byte swap incoming packet). . . . . . 149
; 9.2. SC.ISW (Swap bytes from 11 to 10 format). . . 150
; 9.3. SC.ROU (Byte swap outgoing packet). . . . . . 151
; 9.4. SC.OSW (Swap word from 10 to 11 format) . . . 152
; 10. Locking/unlocking routines . . . . . . . . . . . . . . 153
; 10.1. SC.POF (Turn KLIPA channel off) . . . . . . . 153
; 10.2. SC.PON (Turn KLIPA channel on). . . . . . . . 154
; 10.3. SC.LOK (Lock connection block). . . . . . . . 155
; 10.4. SC.ULK (Unlock connection block). . . . . . . 156
; 11. Ring Buffer routines . . . . . . . . . . . . . . . . . 157
; 11.1. SC.RGI (Initialize ring buffer variables) . . 157
; 11.2. SC.RHD (Write ring buffer entry header) . . . 158
; 11.3. SC.RTE (Write ring buffer entry tail) . . . . 159
; 11.4. SC.RWR (Write ring buffer entry). . . . . . . 160
; 11.5. RG.SSC (SYSAP to SCA calls) . . . . . . . . . 161
; 11.6. RG.SCS (SCA to SYSAP calls) . . . . . . . . . 162
; 11.7. RG.BFM (Buffer manipulation). . . . . . . . . 163
; 11.8. RG.PKT (Packet movement). . . . . . . . . . . 164
; 11.9. RG.PIT (PI transitions) . . . . . . . . . . . 165
; 11.10. RG.PQM (Port queue manipulation). . . . . . . 166
; 11.11. RG.ITL (Interlocks) . . . . . . . . . . . . . 167
; 12. Dummy routines until the port driver supports them . . 169
; 13. End of SCS . . . . . . . . . . . . . . . . . . . . . . 170
SUBTTL Local variable storage for SCS
RS (SCAINI) ;Flag set when we run through SCA init code
RS (TOPFQ) ;Pointer to top of free queue
RS (BOTFQ) ;Pointer to bottom of free queue
RS (FQCNT) ;Count of the number of buffer on free queue
RS (TOPDC) ;Top of the dont care queue
RS (BOTDC) ;Bottom of the dont care queue
RS (TOPDFQ) ;Pointer to first buffer on long DG Q
RS (BOTDFQ) ;Pointer to last buffer on long DG Q
RS (DFQCNT) ;Count of buffers on long DG queue
RS (SBCNT) ;Save the number of SB's we have
RS (NOTTAB) ;Address of notification table
RS (NOTEND) ;Address of the end of the notification table
RS (UNQBTS) ;Storage for the next CID bits to be assigned
RS (UNQRFL) ;Number of times CID bits have been recycled
RS (NXTIDX) ;Next free index into the list of CID's
RS (CIDRFL) ;Number of times CIDTAB has been recycled
RS (CIDTAB) ;Base address of the CID address table
RS (UBTTAB) ;Base address of the CID unique bits table
RS SBSTUK,1
RPMAX==:5 ;Don't postpone reaping more than this
RSI (RAPTIM,<C%RAPT>,1) ;Timer for SCA connection reaper
RSI (RAPINC,<C%RAPT>,1) ;Min time increment (millisec)between reap runs
;SCA ring buffer storage
;
RSI (RNGSW,<RPACKT+RBUFMG>,1) ;Ring buffer switch - default is RPACKT
;Note: RNGSW is not under the SCARNG conditional because it must always
; be present since SCAPAR uses it to create structure names for the
; various switch settings.
IFN SCARNG,<
RS (RNGSIZ) ;Actual length of ring buffer
RS (RNGTOP) ;Start of ring buffer
RS (RNGBOT) ;End of ring buffer
RS (RNGNUM) ;Number of entries written to ring buffer
RS (RNGCUR) ;Top of the most recent complete entry
RS (RNGADR) ;Current position in ring buffer
;Below is the ring buffer entry length table. This table contains the
;entry length for each of the events. It is indexed by event code.
ENTLTB: -1 ;Illegal event code
15 ;Code 1 - SYSAP to SCA
12 ;Code 2 - SCA to SYSAP
17 ;Code 3 - Buffer manipulation
17 ;Code 4 - Packet transaction
11 ;Code 5 - PI transition
12 ;Code 6 - Port queue manipulation
13 ;Code 7 - Interlocks
0 ;Reserved for future expansion
0 ;Reserved for future expansion
0 ;Reserved for future expansion
> ;End of IFN SCARNG
;Channel control word. When we reach zero here, really turn on the CI channel
;on a CION.
RSI (CHNCTL,<0>,1) ;CI channel control word...
; Performance and analysis counter tables
RS (SNDTAB,.STLST) ;Table for packets sent
RS (RECTAB,.STLST) ;Table for packets received
RS (LISTEN) ;A place to count listens
RS (RCBCNT) ;Count of CB killed by SC.RCB
; Idle chatter support locations.
RS (TMGCNT) ;Count of systems nailed by idle chatter
RSI (TMGSBI,<-1>,1) ;Current system under consideration
RSI (TMGTIM,<-C%TMGT>,1);Timeout perioud
; Message and datagram buffer managment parameter locations. Diddle at your
;own risk. See SCAPAR for definitions of initial values.
RSI (MBPS,<C%MBPS>,1) ;Min message buffers per SB
RSI (MBCR,<C%MBCR>,1) ;Number of msg buffers to queue before sending
; a credit request for them
RSI (DBPS,<C%DBPS>,1) ;Min datagram buffers per SB
RS (MINMSG) ;Min number of messages we should have
RS (MINDG) ;Min number of datagrams we should have
RS (NMBCNT) ;Count of times we ran out of message buffers
RS (NDBCNT) ;Count of time we ran out of datagram buffers
RS (TOTMGB) ;Total number of message buffers ever created
RS (TOTDGB) ;Total number of datagram buffers ever created
RS (MBUST) ;Number of times a small request was honored
; even though we were under message threshold
RS (DBUST) ;Number of times a small request was honored
; even though wer were under datagram threshold
RS (DMRCNT) ;Number of message buffer requests deferred
RS (DDRCNT) ;Number of datagram buffer requests deferred
RS (RMRCNT) ;Number of message buffer requests refused
RS (RDRCNT) ;Number of datagram buffer requests refused
RS (ASRMR) ;Average size of refused message request
RS (ASRDR) ;Average szie of refused datagram request
RSI (LRGREQ,<C%LGRQ>,1) ;Buffer requests of less than this size are
; small requests
RSI (MGTRSH,<C%MGTR>,1) ;MSG threshold. SC.ABF will not allocate a
; large request that would take us below this
RSI (DGTRSH,<C%DGTR>,1) ;DG threshold. SC.ALD will not allocate a
; large request that would take us below this
;A large request is any request larger than 2
RSI (LSTEPG,<777>,1) ;Last page used in EPGSEC,starts at section end
.PSECT RSDAT ;Put this in PSECT which is not zeroed
; PRESBL and SBLIST must stay together in this order!!!
;
PRESBL::-1 ;Flag for dont care for remote
SBLIST::BLOCK C%SBLL ;Keep storage for a list of system block addr's
; Byte pointers to ten format 8 bit bytes...
;
TA$LSB::POINT ^D8,T1,17 ;Ten byte A, least significant bits
TA$MSB::POINT ^D8,T1,9 ;Ten byte A, Most significant
TB$LSB::POINT ^D8,T1,35 ;Ten byte B, Least significant
TB$MSB::POINT ^D8,T1,27 ;Ten byte B, most significant
; Byte pointers to eleven format 8 bit bytes...
;
EA$LSB::POINT ^D8,T1,23 ;Eleven, byte A, least sig
EA$MSB::POINT ^D8,T1,31 ;Eleven, byte A, most sig
EB$LSB::POINT ^D8,T1,7 ;Eleven, byte B, least sig
EB$MSB::POINT ^D8,T1,15 ;Eleven, byte B, most sig
DSPTAB: $DISPA ;Generate addr table for message handlers
INITAB: $SYSAP ;Generate the SYSAP init address list
C%SYTL==<.-INITAB>-1 ;The length of INITAB
.ENDPS RSDAT ;End this part of the PSECT
;Routines to build packets
SCMKPK: MSEC1,,SC.MOQ ;Connect_request
MSEC1,,SC.MOS ;Connect_response
MSEC1,,SC.MAQ ;Accept_request
MSEC1,,SC.MAS ;Accept_response
MSEC1,,SC.MRQ ;Reject_request
MSEC1,,SC.MRS ;reject_response
MSEC1,,SC.MDQ ;Disconnect_request
MSEC1,,SC.MDS ;Disconnect_response
MSEC1,,SC.MCQ ;Credit_request
MSEC1,,SC.MCS ;Credit_response
SUBTTL State Tables
;TABLE X
;Table X - used when sysap calls SCA. For each event, provides new connection
;and block state. Also allows checking for invalid state
TABLEX:
;Connect
FLD(.BSCNP,X.BSTAT)+FLD(.CSCSE,X.CSTAT) ;Closed
X.ERR ;Listening
X.ERR ;Connect_sent
X.ERR ;Connect_received
X.ERR ;Connect_ACK
X.ERR ;Accept_sent
X.ERR ;Reject_sent
X.ERR ;Open
X.ERR ;Disconnect_sent
X.ERR ;Disconnect_rec
X.ERR ;Disconnect_ACK
X.ERR ;disconnect_match
;Listen
FLD(.CSLIS,X.CSTAT) ;Closed
0 ;Listening
X.ERR ;Connect_sent
X.ERR ;Connect_received
X.ERR ;Connect_ACK
X.ERR ;Accept_sent
X.ERR ;Reject_sent
X.ERR ;Open
X.ERR ;Disconnect_sent
X.ERR ;Disconnect_rec
X.ERR ;Disconnect_ACK
X.ERR ;disconnect_match
;Accept
X.ERR ;Closed
X.ERR ;Listening
X.ERR ;Connect_sent
FLD(.BSACP,X.BSTAT) ;Connect_received
;New state is set when request is sent
X.ERR ;Connect_ACK
X.ERR ;Accept_sent
X.ERR ;Reject_sent
X.ERR ;Open
X.ERR ;Disconnect_sent
X.ERR ;Disconnect_rec
X.ERR ;Disconnect_ACK
X.ERR ;disconnect_match
;Reject
X.ERR ;Closed
X.ERR ;Listening
X.ERR ;Connect_sent
FLD(.BSRPN,X.BSTAT) ;Connect_received
;New state is set when request is sent
X.ERR ;Connect_ACK
X.ERR ;Accept_sent
X.ERR ;Reject_sent
X.ERR ;Open
X.ERR ;Disconnect_sent
X.ERR ;Disconnect_rec
X.ERR ;Disconnect_ACK
X.ERR ;disconnect_match
;Disconnect
0 ;Closed (no change)
FLD(.CSCLO,X.CSTAT) ;Listening
FLD(.CSCLO,X.CSTAT) ;Connect_sent
FLD(.BSRPN,X.BSTAT)+FLD(.CSRJS,X.CSTAT) ;Connect_received
FLD(.CSCLO,X.CSTAT) ;Connect_ACK
FLD(.CSCLO,X.CSTAT) ;Accept_sent
FLD(.CSCLO,X.CSTAT) ;Reject_sent
FLD(.BSDPN,X.BSTAT)+FLD(.CSDSE,X.CSTAT) ;Open
0 ;Disconnect_sent (no change)
FLD(.BSDPN,X.BSTAT)+FLD(.CSDMC,X.CSTAT) ;Disconnect_rec
0 ;Disconnect_ACK (no change)
0 ;Disconnect_match (no change)
;Table Y
;For each block state, this table provides the op code to send and the
;new connection state
; * * * *
;Disagrees with corporate spec when block state is connect_pending. We
;have already set the connection state to .CSCSE in order to ensure that
;if a connection's state is "closed", the sysap never expects to hear
;about it again. If this is not changed, there is potential for the sysap
;to call SC.DIS between the time that the connection state is set and
;the message is actually sent. That sets the state to closed. We can't
;change it to connect_sent when the message is finally sent, because
;we'd lose track of the fact that the sysap had closed it.
; * * * *
TABLEY: 0 ;Not used
0 ;Free (1)
0 ;Allocate (2)
; FLD(.STORQ,Y.OP)+FLD(.CSCSE,Y.STAT) ;Connect_pending (3)
FLD(.STORQ,Y.OP) ;Connect_pending (3)
FLD(.STARQ,Y.OP)+FLD(.CSACS,Y.STAT) ;Accept_pending (4)
FLD(.STRRQ,Y.OP)+FLD(.CSRJS,Y.STAT) ;Reject_pending (5)
FLD(.STCRQ,Y.OP) ;Credit_pending (state doesn't change) (6)
FLD(.STDRQ,Y.OP) ;Disconnect_pending (state already set) (7)
YSIZE==:.-TABLEY
;Table Z
;This table indicates, for a given op code, the length of its message,
;the priority for sending it, and the expected response.
TABLEZ:
FLD(.LNORQ,Z.LEN)+FLD(.MPCMM,Z.PRI)+FLD(.STORS,Z.RSP) ;Connect_req
FLD(.LNORS,Z.LEN)+FLD(.MPCMM,Z.PRI) ;CONNECT_RSP
FLD(.LNARQ,Z.LEN)+FLD(.MPCMM,Z.PRI)+FLD(.STARS,Z.RSP) ;ACCEPT_REQ
FLD(.LNARS,Z.LEN)+FLD(.MPCMM,Z.PRI) ;ACCEPT_RSP
FLD(.LNRRQ,Z.LEN)+FLD(.MPCMM,Z.PRI)+FLD(.STRRS,Z.RSP) ;REJECT_REQ
FLD(.LNRRS,Z.LEN)+FLD(.MPCMM,Z.PRI) ;REJECT_RSP
FLD(.LNDRQ,Z.LEN)+FLD(.MPLOW,Z.PRI)+FLD(.STDRS,Z.RSP) ;DISCONNECT_REQ
FLD(.LNDRS,Z.LEN)+FLD(.MPCMM,Z.PRI) ;DISCONNECT_RSP
FLD(.LNCRQ,Z.LEN)+FLD(.MPFLO,Z.PRI)+FLD(.STCRS,Z.RSP) ;CREDIT_REQ
FLD(.LNCRS,Z.LEN)+FLD(.MPCMM,Z.PRI) ;CREDIT_RSP
;Table K
;This table indicates, for a given incoming op code and current state
;of a connection, whether the event is legal, and if it is, what the new
;state and returned op code should be
TABLEK:
;Received Connect_req
FLD(.STORS,K.OP) ;Closed
FLD(.STORS,K.OP)+FLD(.CSCRE,K.STAT) ;Listening
K.ERR ;Connect request was sent (CONNECT_SENT)
K.ERR ;Connect request was received (CONNECT_REC)
K.ERR ;Connect response was received (CONNECT_ACK)
K.ERR ;Accept request was sent (ACCEPT_SENT)
K.ERR ;Reject request was sent (REJECT_SENT)
K.ERR ;Connection is open (OPEN)
K.ERR ;Disconnect request was sent (DISCONNECT_SENT)
K.ERR ;Disconnect request received (DISCONNECT_REC)
K.ERR ;Disconnect response received (DISCONNECT_ACK)
K.ERR ;Waiting for disconnect response (DISCONNECT_MATCH)
;Received connect_response
;"No match" is handled specially.
FLD(.CSCLO,K.STAT) ;Closed
K.ERR ;Listening
FLD(.CSCAK,K.STAT)+K.CHK ;Connect_sent
K.ERR ;Connect_received
K.ERR ;Connect response was received (CONNECT_ACK)
K.ERR ;Accept request was sent (ACCEPT_SENT)
K.ERR ;Reject request was sent (REJECT_SENT)
K.ERR ;Connection is open (OPEN)
K.ERR ;Disconnect request was sent (DISCONNECT_SENT)
K.ERR ;Disconnect request received (DISCONNECT_REC)
K.ERR ;Disconnect response received (DISCONNECT_ACK)
K.ERR ;Waiting for disconnect response (DISCONNECT_MATCH)
;Received accept-request
FLD(.STARS,K.OP)+FLD(.CSCLO,K.STAT) ;Closed. Send "no match"
K.ERR ;Listening
K.ERR ;Connect_sent
K.ERR ;Connect_received
FLD(.STARS,K.OP)+FLD(.CSOPN,K.STAT) ;Connect_ACK
K.ERR ;Accept_sent
K.ERR ;Reject_sent
K.ERR ;Open
K.ERR ;Disconnect_sent
K.ERR ;Disconnect_rec
K.ERR ;Disconnect_ACK
K.ERR ;disconnect_match
;Received accept_response
;"No match" is handled specially.
;If state is "closed", we must send disconnect_request. This is handled specially.
FLD(.STDRQ,K.OP)+FLD(.CSCLO,K.STAT) ;CLosed
K.ERR ;Listening
K.ERR ;Connect_sent
K.ERR ;Connect_received
K.ERR ;Connect_ACK
FLD(.CSOPN,K.STAT)+K.CHK ;Accept_sent
K.ERR ;Reject_sent
K.ERR ;Open
K.ERR ;Disconnect_sent
K.ERR ;Disconnect_rec
K.ERR ;Disconnect_ACK
K.ERR ;disconnect_match
;Received reject_request
FLD(.STRRS,K.OP)+FLD(.CSCLO,K.STAT) ;Closed
K.ERR ;Listening
K.ERR ;Connect_sent
K.ERR ;Connect_received
FLD(.STRRS,K.OP)+FLD(.CSCLO,K.STAT) ;Connect_ACK
K.ERR ;Accept_sent
K.ERR ;Reject_sent
K.ERR ;Open
K.ERR ;Disconnect_sent
K.ERR ;Disconnect_rec
K.ERR ;Disconnect_ACK
K.ERR ;disconnect_match
;Received reject_response
FLD(.CSCLO,K.STAT) ;Closed
K.ERR ;Listening
K.ERR ;Connect_sent
K.ERR ;Connect_received
K.ERR ;Connect_ACK
K.ERR ;Accept_sent
FLD(.CSCLO,K.STAT)+K.CHK ;Reject_sent
K.ERR ;Open
K.ERR ;Disconnect_sent
K.ERR ;Disconnect_rec
K.ERR ;Disconnect_ACK
K.ERR ;disconnect_match
;Received disconnect_request
FLD(.STDRS,K.OP)+FLD(.CSCLO,K.STAT) ;Closed
K.ERR ;Listening
K.ERR ;Connect_sent
K.ERR ;Connect_received
K.ERR ;Connect_ACK
K.ERR ;Accept_sent
K.ERR ;Reject_sent
FLD(.STDRS,K.OP)+FLD(.CSDRE,K.STAT) ;Open
FLD(.STDRS,K.OP)+FLD(.CSDMC,K.STAT) ;Disconnect_sent
K.ERR ;Disconnect_rec
FLD(.STDRS,K.OP)+FLD(.CSCLO,K.STAT) ;Disconnect_ACK
K.ERR ;disconnect_match
;received disconnect_response
FLD(.CSCLO,K.STAT) ;Closed
K.ERR ;Listening
K.ERR ;Connect_sent
K.ERR ;Connect_received
K.ERR ;Connect_ACK
K.ERR ;Accept_sent
K.ERR ;Reject_sent
K.ERR ;Open
FLD(.CSDAK,K.STAT)+K.CHK ;Disconnect_sent
K.ERR ;Disconnect_rec
K.ERR ;Disconnect_ACK
FLD(.CSCLO,K.STAT)+K.CHK ;disconnect_match
;Received credit_request
FLD(.STCRS,K.OP) ;Closed
K.ERR ;Listening
K.ERR ;Connect_sent
K.ERR ;Connect_received
K.ERR ;Connect_ACK
K.ERR ;Accept_sent
K.ERR ;Reject_sent
FLD(.STCRS,K.OP) ;Open
FLD(.STCRS,K.OP) ;Disconnect_sent
K.ERR ;Disconnect_rec
FLD(.STCRS,K.OP) ;Disconnect_ACK
K.ERR ;disconnect_match
;Received credit_response
0 ;Closed
K.ERR ;Listening
K.ERR ;Connect_sent
K.ERR ;Connect_received
K.ERR ;Connect_ACK
K.ERR ;Accept_sent
K.ERR ;Reject_sent
K.CHK ;Open
0 ;Disconnect_sent
K.CHK ;Disconnect_rec
0 ;Disconnect_ACK
0 ;disconnect_match
;Table X - used when sysap calls SCA. For each event, provides new connection
;and block state. Also allows checking for invalid state
DEFSTR X.ERR,TABLEX,0,1 ;Error flag
DEFSTR X.BSTAT,TABLEX,17,17 ;New block state
DEFSTR X.CSTAT,TABLEX,35,18 ;New connection state
;In some cases, the connection state is set when the request is sent,
;rather than when the sysap calls SCA.
EV.CON==:0 ;SC.CON
EV.LIS==:1 ;SC.LIS
EV.ACC==:2 ;SC.ACC
EV.REJ==:3 ;SC.REJ
EV.DIS==:4 ;SC.DIS
;DEFSTRs for table Y. For each block state, provides op code to
;send and new connection state
DEFSTR (Y.OP,TABLEY,17,18)
DEFSTR (Y.STAT,TABLEY,35,18)
;Defstrs for table Z. For each op code to be sent, provides length, priority,
;and expected response
DEFSTR Z.LEN,TABLEZ,17,18
DEFSTR Z.PRI,TABLEZ,20,3
DEFSTR Z.RSP,TABLEZ,35,15
;Defstrs for table K. For each incoming packet, provides op code of response
;and new connection state. Also allows checking for protocol violations
DEFSTR (K.ERR,TABLEK,0,1)
DEFSTR (K.CHK,TABLEK,1,1)
DEFSTR (K.OP,TABLEK,17,16)
DEFSTR (K.STAT,TABLEK,35,18)
SUBTTL Initialization code
RESCD
; Here we start the world of SCA. One of the assumptions that we make here is
;that the port driver has already run and hence there are system blocks already
;in existance. What we must do here is queue a message receive buffer for each
;of these system blocks. In addition we must init the buffer chain that we will
;use as space for the SCA flow control messages. One buffer per system block
;is allocated at init time. So, what we do here is as follows:
;
; 1. Count how many system blocks there are.
;
; 2. Build a chain of buffers to be queued by the port driver as flow message
;receive buffers.
;
; 3. Build the chain of send buffer which SCA maintains. (Head pointer: TOPFQ)
;
SCA:: EA.ENT ;Insure we run in non-zero section
SAVEPQ
IFN SCARNG,<
CALL SC.RGI ;Initialize ring buffer
CALL SCADIE ;No space, so die
> ;End of IFN SCARNG
MOVX T1,<1B1> ;Get a very large positive number
MOVEM T1,SCSTIM ;Init SCS% clock as never going off
SETZM FQCNT ;Be sure the buffer count is accurate
SETZM TOPFQ ;Zero the FLINK for the free queue
XMOVEI T1,TOPFQ ;Get a pointer to the free queue FLINK
MOVEM T1,BOTFQ ;Init BLINK as pointer to FLINK
SETZM DFQCNT ;Init datagram buffer count
SETZM TOPDFQ ;Zero long datagram queue FLINK
XMOVEI T1,TOPDFQ ;Get a pointer to the top of this queue
MOVEM T1,BOTDFQ ;Init the BLINK as pointer to FLINK
SETZM TOPDC ;Zero the dont care queue FLINK
XMOVEI T1,TOPDC ;Get the address of top of dont care queue
MOVEM T1,BOTDC ;Save as the bottom of the queue
MOVX T1,1 ;We desire only one page
CALL PGRSKD ;Get a page of resident memory for us pls..
BUG. (HLT,SCANPT,SCAMPI,SOFT,<SCA - No page for CID table>,,<
Cause: SCA called PGRSKD for a page to put its data tables in and
the call failed. We can do nothing without these tables.
>)
PUSH P,T1 ;Save this page addr for a short while
MOVEM T1,T2 ;Set up source addr for BLT
MOVEM T1,T3 ; and destination addr
AOS T3 ;Make the destination addr source addr+1
MOVX T1,PGSIZ-1 ;Number of words to move
SETZM (T2) ;Be sure we BLT zeros
EXTEND T1,[XBLT] ;Zero the table space
POP P,T1 ;Get the table addr again
MOVEM T1,CIDTAB ;Save the address of the CID table
ADDI T1,<PGSIZ/2> ;Point to halfway through the page
MOVEM T1,UBTTAB ;Save this as address of uniqueness table
MOVX T1,C%CIDL ;Init NXTIDX as one more than highest index
MOVEM T1,NXTIDX ;. . .
SETZM CIDRFL ;Not doing CIDTAB recycling yet
SETONE UBITS,T1 ;Set all bits in the unique bits field
LSH T1,-<C%RMBU> ;Right justify said bits
MOVEM T1,UNQBTS ;Store as the uniquness bits
AOS UNQBTS ;Init as one more than the first unique bits
SETZM UNQRFL ;Not doing CID bits recycling yet
; Set buffer thresholds.
;
SETZM SBCNT ;Init the count of remotes online
CALL SC.SBT ;Set msg and dg buffer thresholds
; Set initial levels for both message and datagram buffers.
;
SSC.NX: MOVE T1,MINMSG ;Get the number of messages to start with
IDIVI T1,C%MGPG ;(T1) = (number of buffer) / (buffers per page)
SKIPE T2 ;Any remainder???
AOS T1 ;Yes, round up to the next page
CALL PGRSKD ;Get buffer space from the monitor
CALL SCADIE ;If we cannot init, die here pls...
IMULI T2,C%MGPG ;(T2) = (Number of pages) * (buffers per page)
ADDM T2,FQCNT ;Update buffer count
ADDM T2,TOTMGB ; and count of total buffers created
MOVX T2,C%MGSZ ;Get the buffer size we desire
CALL SC.BBF ;Turn it all into quanta sized pieces
MOVEM T1,TOPFQ ;Set up the pointer to the top of the free q
MOVEM T2,BOTFQ ;And the pointer to the bottom of the free q
IFN SCADBG,<
CALL SC.TMQ ;Trace the message free queue
> ;End of IFN SCADBG
MOVE T1,MINDG ;Get the number of datagrams to have onhand
CALL PGRSKD ;Get buffer space from the monitor
CALL SCADIE ;If we cannot init, die here pls...
IMULI T2,C%DGPG ;(T2) = (Number of pages) * (buffers per page)
ADDM T2,DFQCNT ;Update the buffer count
ADDM T2,TOTDGB ; and the count of datagram buffers created
MOVX T2,C%DGSZ ;Get the buffer size we desire
CALL SC.BBF ;Turn it all into quanta sized pieces
MOVEM T1,TOPDFQ ;Set up the pointer to the top of the free q
MOVEM T2,BOTDFQ ;And the pointer to the bottom of the free q
IFN SCADBG,<
CALL SC.TDQ ;Trace the datagram free queue
> ;End of IFN SCADBG
; Allocate the notification table
;
SSC.NN: MOVEI T1,1 ;We only wish one buffer
CALL SC.ABF ;Get a single buffer
BUG. (HLT,SCANBL,SCAMPI,SOFT,<SCA - No buffer for online list>,,<
Cause: SC.ABF was called to get a buffer for the address list to be used
to call SYSAPs when a node comes online. Without this list no one will
ever be told when a node comes online and hence we cannot run.
>)
MOVEM T1,NOTTAB ;Save the address of the list
ADDI T1,C%MGSZ ;Add the size of the table
MOVEM T1,NOTEND ; and save the end address of the table
; Here to init the various SYSAPs...
;
MOVEI P5,C%SYTL ;Get the length of the SYSAP table
SSC.SI: SKIPE INITAB(P5) ;Is there an entry for this index???
CALL @INITAB(P5) ;Yes, call the SYSAP init routine pls...
SOJGE P5,SSC.SI ;Loop for all SYSAPs pls...
SETOM SCAINI ;Indicate completion of init code
RET ;And return...
; Here when we find an unrecoverable error in SCA init.
;
SCADIE: BUG. (HLT,SCACCI,SCAMPI,SOFT,<SCA - Cannot complete initialization>,,<
Cause: SCA detected an error it could not recover from during the init
process. SCADIE is CALLed by the offending location and hence the
stack points out the guilty phase of init.
>)
JRST SCADIE ;Just in case we try something silly, like
; continue...
SUBTTL Calls from sysap -- SC.SOA (Set ONLINE address)
; This routine sets the online address. A SYSAP calls
;this routine to tell SCA what address to use, to notify the SYSAP of a node
;coming online.
;
; Call
; BLCAL. (SC.SOA,<SS.ADR>)
;
; Return (+1)
; T1/ Error code
;
; Return (+2)
; No data, address saved for SCA
;
SC.SOA::BLSUB. (<SS.ADR>)
SAVEAC <Q1>
;Find a free slot in the table.
MOVE T1,NOTTAB ;Get the address of the notice table
MOVX T2,C%MGSZ-1 ;Get its size
MOVE T3,SS.ADR ;Get the user provided address
SSO.EL: SKIPN (T1) ;Is there an entry here?
JRST SSO.CO ;No.Go store this address
AOS T1 ;Yes. Try for the next entry.
SOJGE T2,SSO.EL
BUG. (CHK,SCANLF,SCAMPI,SOFT,<SCA - Notice table full>,,<
Cause: So many SYSAPs have requested to be notified that nodes come on
and go off line that the table of notification addresses overflowed.
>)
RETBAD (SCSNRT) ;Return error code
;Store the address.
SSO.CO: CIOFF ;DOn't let 2 callbacks happen for one online
MOVEM T3,(T1) ;Store the address
SETZM Q1 ;Start with node zero
;If a system is already online, tell the sysap. If its system block
;exists, but its v.c. is closed, we will be notified when it is
;reopened.
SSO.LP: SKIPN T2,SBLIST(Q1) ;Is there a system block
JRST SSO.YY ;No.
LOAD T3,SBVCST,(T2) ;Yes. is v.c. open?
CAIE T3,VC.OPN
JRST SSO.YY ;No. Don't call the sysap, then.
MOVEI T1,.SSNCO ;Say why we are calling the SYSAP
MOVE T2,Q1 ;Get node number
CALL @SS.ADR ;(T1,T2/) Give online notification
NOP
SSO.YY: CAIGE Q1,C%SBLL-1 ;Step to next node
AOJA Q1,SSO.LP
CION ;Finished with all nodes
RETSKP
ENDBS.
SUBTTL Calls from sysap -- Connection management
; Functions performed within the realm of these routines:
; 1. Connect
; 2. Listen
; 3. Accept
; 4. Reject
; 5. Disconnect
;
; These routines may be called either by SYSAPs within the monitor or by the
;JSYS code
;These routines implement the SCS connection management protocol. The
;following pictures describes the normal sequence.
COMMENT #
NODE A NODE B
call state message state call
---- ----- ------- ----- ----
closed listen
SC.CON conn_sent conn_req
------->
conn_rsp M conn_rec .SSCTL
<-------
conn_ack
accept_req acc_sent SC.ACC
<---------
.SSCRA open accept_rsp M
--------->
open .SSOSD
SC.DIS disc_sent disc_req
------->
disc_rsp disc_rec .SSRID
<-------
disc_ACK
disc_req disc_match SC.DIS
<-------
closed * disc_rsp
------->
closed *
* indicates ready to reap
#
SUBTTL Calls from sysap -- Connection management -- SC.CON (Connect)
; This routine allocates a connection block and requests a connection.
;
;Usage:
; Call
;BLCAL. (SC.CON,<SS.SPN,SS.DPN,SS.NOD,SS.MSC,SS.MRC,SS.ADR,SS.SID,SS.DTA,SS.BFR,SS.DGB>)
;
; Where:
; SS.SPN -- Address of source process name
; SS.DPN -- Address of destination process name
; SS.NOD -- System block index of destination system
; SS.MSC -- Minimum send credit (Level to not allow return of credits)
; SS.MRC -- Minimum receive credit (Point at which LCL callbacks start)
; SS.ADR -- Address to call on condition changes for this connection
; SS.SID -- Six bits of connect ID set by the SYSAP
; SS.DTA -- Address of SYSAP connection data or zero
; SS.BFR -- Number of buffers to queue for message reception
; SS.DGB -- Number of datagram buffers to queue
;
; Return (+1)
; T1/ Error code
;
; Return (+2)
; T1/ Connect ID
;
SC.CON::BLSUB. (<SS.SPN,SS.DPN,SS.NOD,SS.MSC,SS.MRC,SS.ADR,SS.SID,SS.DTA,SS.BFR,SS.DGB>)
SAVEP ;Save the preserved ACs
;Don't do this if the node has never been seen
MOVE T1,SS.NOD ;Get the SBI
SKIPN P4,SBLIST(T1) ;Get the system block address
RETBAD (SCSISB) ;Doesn't exist. Fail.
;Allocate a connection block and initialize with common data
MOVE T1,SS.SID ;Get the SYSAP CID bits
CALL SC.ACB ;Allocate and initialize a connection block
RETBAD () ;Return with the error in T1
;See if the current state is correct (It should be in this case!), and
;get new connection and block states.
MOVEI T1,EV.CON ;Event is connect call
CALL SC.OUT ;(T1,P1/T1,T2)
BUG. (HLT,SCACFO,SCAMPI,SOFT,<SCA - SC.CON received failure from SC.OUT>,,<
Cause: SC.CON created a new connection block and then called SC.OUT to
check its state. The call should never fail.
>)
DMOVEM T1,P2 ;Save new states
;..
;Store address for calling the sysap into the connection block
;..
MOVE T1,SS.ADR ;Get the addr to call SYSAP at
MOVEM T1,.CBADR(P1) ;Store it in the connection block
; The minimum send credit is the lower boundary allowed for credit cancelation.
;I.E. never sink below this level when canceling credits for the remote.
MOVE T1,SS.MSC ;Get the minimum send credit
STOR T1,CBMNSC,(P1) ;Pack it away in the CB pls...
;Store source and destination process names and connection data
MOVE T1,SS.SPN ;Get a pointer to the source process name
MOVE T2,SS.DPN ; and the destination name
MOVE T3,SS.DTA ; and a pointer to the connection data
CALL SC.SDM ;Move the strings and data to the connect block
;Store in the connection block the number of buffers to be queued
MOVE T1,SS.BFR ;Number of message buffers the user wants
STOR T1,CBIMB,(P1) ;SC.SNM will look at this later
MOVE T1,SS.DGB ;Number of datagram buffers the user wants
STOR T1,CBIDB,(P1)
;Store connection state.
SKIPE P3 ;If we need to change it
STOR P3,CBCNST,(P1) ; Store connection state
;Lock the connection block before we link it to the system block. That way,
;if the node goes offline after we link it, processing will be deferred until
;we have finished changing the state.
CALL SC.LOK ;(P1/) Lock the connection block
;Make the connection block point to the system block, and vice versa
MOVE T1,SS.NOD ;Get the node number for dest system
STOR T1,CBDNOD,(P1) ;Store in the CB
MOVEM P4,.CBSBA(P1) ;Store it in the connection block
CALL SC.LCB ;Link this connection block into list
JRST SCO.FL
;..
;Record this event in the ring buffer if requested
;..
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,-1(P6) ;Get caller to feature routine
MOVE T3,P1 ;Get CB address
CALL RG.SSC ;(T1,T2,T3) Record SYSAP to SCA event
> ;End of IFN SCARNG
LOAD P5,CBSCID,(P1) ;Get the connect ID while block is locked
;Send the request now, or queue it for later
SKIPN T1,P2 ;Get the new block state
IFSKP.
CALL SC.SCA ;(T1,P1,P4/) Set block state and queue message
CALL SC.ULK ;(P1/) Unlock the connection block
CALL SC.SNM ;(P4/) Send the message if possible
ELSE.
CALL SC.ULK ;(P1/) Unlock the connection block
ENDIF.
; Here to set up the returned arg, and return.
MOVE T1,P5 ;Return the connect ID
RETSKP ;Return success
;V.C. is closed. Don't open the connection
SCO.FL: MOVEM T1,P3 ;Save error code
CALL SC.ULK ;(P1/) Unlock the connection block (does OKSKED)
CALL SC.RCB ;(P1/) Release the connection block
MOVE T1,P3 ;Recover error code
RETBAD ()
ENDBS.
SUBTTL Calls from sysap -- Connection management -- SC.LIS (Listen)
; Here when we wish to listen for a connection, any connection.
;
; Usage:
; Call
; BLCAL. (SC.LIS,<SS.SPN,SS.DPN,SS.NOD,SS.ADR,SS.SID,SS.MSC,SS.MRC>)
;
; Where:
; SS.SPN -- Address of source process name
; SS.DPN -- Address of destination process name or 0
; SS.NOD -- System block index or -1
; SS.ADR -- Address to call on connection condition changes
; SS.SID -- Six bits of Connect ID setable by the SYSAP
; SS.MSC -- Minimum send credit
; (See SS.CON code comments for more detailed info)
; SS.MRC -- Minimum receive credit (Ditto)
;
; Return (+1)
; T1/ Error code
;
; Return (+2)
; T1/ Connect ID
;
; Where a zero in SS.DPN and -1 in SS.NOD indicates a connect from anyone is
;acceptable. A byte pointer and a system block index indicate a
;listen for a particular node.
;
SC.LIS::BLSUB. (<SS.SPN,SS.DPN,SS.NOD,SS.ADR,SS.SID,SS.MSC,SS.MRC>)
SAVEP ;Save the preserved ACs
AOS LISTEN ;Count the call to LISTEN
;Don't do this if the node has never been seen
MOVE T1,SS.NOD ;Get the SBI
SKIPN P4,SBLIST(T1) ;Get the system block address
RETBAD (SCSISB) ;Doesn't exist. Fail.
;Allocate a connection block and initialize with common data
MOVE T1,SS.SID ;Get the SYSAP CID bits
CALL SC.ACB ;Allocate and initialize a connection block
RETBAD () ;Return with the error in T1
;..
;See if the current state is correct (It should be in this case!), and
;get new connection and block states.
;..
MOVEI T1,EV.LIS ;Event is listen call
CALL SC.OUT ;(T1,P1/T1,T2)
BUG. (HLT,SCALFO,SCAMPI,SOFT,<SCA - SC.LIS received failure from SC.OUT>,,<
Cause: SC.LIS created a new connection block and then called SC.OUT to
check its state. The call should never fail.
>)
DMOVEM T1,P2 ;Save new states
;Store address for calling the sysap into the connection block
MOVE T1,SS.ADR ;Get the addr to call SYSAP at
MOVEM T1,.CBADR(P1) ;Store it in the connection block
; The minimum send credit is the lower boundary allowed for credit cancelation.
;I.E. never sink below this level when canceling credits for the remote.
MOVE T1,SS.MSC ;Get the minimum send credit
STOR T1,CBMNSC,(P1) ;Pack it away in the CB pls...
; Move the source and destination process names. There is no connection
;data allowed on a LISTEN.
MOVE T1,SS.SPN ;Get address of source process name
MOVE T2,SS.DPN ;Get address of destination process name
SETZ T3, ;There is no connect data
CALL SC.SDM ;Move the process names please
;Store the connection state
SKIPE P3
STOR P3,CBCNST,(P1) ;Store new connection state
;Lock the connection block before we link it to the system block. That way,
;if the node goes offline after we link it, processing will be deferred until
;we have finished changing the state.
CALL SC.LOK ;(P1/) Lock the connection block
;Make the connection block point to the system block, and vice versa
MOVE T1,SS.NOD ;Get the node number for dest system
STOR T1,CBDNOD,(P1) ;Store in the CB
MOVEM P4,.CBSBA(P1) ;Store it in the connection block
CALL SC.LCB ;Link this connection block into list
JRST SLI.FL ;Failed. Return error
;This connection is now ready to accept a connect_request.
;Record this event in the ring buffer.
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,-1(P6) ;Get caller to feature routine
MOVE T3,P1 ;Get CB address
CALL RG.SSC ;(T1,T2,T3) Record SYSAP to SCA event
> ;End of IFN SCARNG
LOAD P5,CBSCID,(P1) ;Get connect ID while block is locked
;..
; Set the new block state. For now, this routine never
;sends a request. The code is identical to the other routines to allow for
;possible changes in the future.
;..
JUMPL P4,SCL.CO ;If don't care listener, don't do this
SKIPN T1,P2 ;Get the new block state
IFSKP.
CALL SC.SCA ;(T1,P1,P4/) Set block state and queue message
CALL SC.ULK ;(P1/) Unlock the connection block
CALL SC.SNM ;(P4/) Send the message if possible
ELSE.
SCL.CO: CALL SC.ULK ;(P1/) Unlock the connection block
ENDIF.
;Return success, providing connect ID
MOVE T1,P5 ;Get connect ID saved earlier
RETSKP ;Tell the caller we made out OK
SLI.FL: MOVEM T1,P3 ;Save error code
CALL SC.ULK ;(P1/) Unlock the connection block (does OKSKED)
CALL SC.RCB ;(P1/) Release the connection block
MOVE T1,P3 ;Recover error code
RETBAD ()
ENDBS.
SUBTTL Calls from sysap -- Connection management -- SC.ACC (Accept)
; Here when we are accepting a request from the outside for a connection.
;I.E. Allow a connect...
;
; Usage:
; Call
; BLCAL. (SC.ACC,<SS.CID,SS.DTA,SS.BFR,SS.DGB>)
;
; Where:
; SS.CID -- Connect ID
; SS.DTA -- Address of initial connection data or zero
; SS.BFR -- Number of buffers to be queued for message reception
; SS.DGB -- Number of buffers to queue for datagram reception
;
; Return (+1)
; T1/ Failure code
;
; Return (+2)
; T1/ Address of initial connect data
;
SC.ACC::BLSUB. (<SS.CID,SS.DTA,SS.BFR,SS.DGB>)
SAVEP ;Save the preserved ACs
MOVE T1,SS.CID ;Get connect ID
CALL SC.CAL ;(T1/T1,P1) Check validity, and lock
RETBAD() ;Return failure
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,-1(P6) ;Get caller to feature routine
MOVE T3,P1 ;Get CB address
CALL RG.SSC ;(T1,T2,T3) Record SYSAP to SCA event
> ;End of IFN SCARNG
;See if the current state is correct, and get new connection and block states.
MOVEI T1,EV.ACC ;Event is accept call
CALL SC.OUT ;(T1,P1/T1,T2)
RETBAD (,<CALL SC.ULK>) ;Illegal. Return failure
DMOVEM T1,P2 ;Save new states
;Store in the connection block the optional data to be sent to the
;other end.
SKIPN T2,SS.DTA ;Is there any data to move???
JRST SCA.OK ;No. Continue
MOVEI T1,C%DTLW ;Yes, get its length in words
XMOVEI T3,.CBDTA(P1) ;Destination addr in CB for connect data
XBLT. T1 ;Copy the data
;..
;Store in the connection block the number of buffers to be queued
;..
SCA.OK: MOVE T1,SS.BFR ;Number of message buffers the user wants
STOR T1,CBIMB,(P1) ;SC.SNM will look at this later
MOVE T1,SS.DGB ;Number of datagram buffers the user wants
STOR T1,CBIDB,(P1)
; Set the new connection and block states
SKIPE P3
STOR P3,CBCNST,(P1) ;Store new connection state
SKIPN T1,P2 ;Get new block state
IFSKP.
MOVE P4,.CBSBA(P1) ;Get the address of the system block
CALL SC.SCA ;(T1,P1,P4/) Set block state and queue message
CALL SC.ULK ;(P1/) Unlock the connection block
CALL SC.SNM ;(P4/) Send the message if possible
ELSE.
CALL SC.ULK ;(P1/) Unlock the connection block
ENDIF.
RETSKP
ENDBS.
SUBTTL Calls from sysap -- Connection management -- SC.REJ (Reject)
; Here to reject a connect request.
;
; Usage:
; Call
; BLCAL. (SC.REJ,<SS.CID>,<SS.RJR>)
;
; Where:
; SS.CID -- Connect ID
; SS.RJR -- Reject reason code
;
; Return (+1)
; T1/ Failure code
;
; Return (+2)
; No data is returned by this routine
;
SC.REJ::BLSUB. (<SS.CID,SS.RJR>)
SAVEAC <P1,P2,P4>
MOVE T1,SS.CID ;Get connect ID
CALL SC.CAL ;(T1/T1,P1) Check validity, and lock
RETBAD() ;Return failure
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,-1(P6) ;Get caller to feature routine
MOVE T3,P1 ;Get CB address
CALL RG.SSC ;(T1,T2,T3) Record SYSAP to SCA event
> ;End of IFN SCARNG
;See if the current state is correct, and get new connection and block states.
MOVEI T1,EV.REJ ;Event is reject call
CALL SC.OUT ;(T1,P1/T1,T2)
RETBAD (,<CALL SC.ULK>) ;Illegal. Return failure
MOVE T3,SS.RJR ;Obtain the disconnect reason
STOR T3,CBSDRE,(P1) ;Place reject reason into CB
;Store connection and block states and send message, if any
SKIPE T2
STOR T2,CBCNST,(P1) ;Store connection state
SKIPN T1
IFSKP.
MOVE P4,.CBSBA(P1) ;Get the address of the system block
CALL SC.SCA ;(T1,P1,P4/) Set block state and queue message
CALL SC.ULK ;(P1/) Unlock the connection block
CALL SC.SNM ;(P4/) Send the message if possible
ELSE.
CALL SC.ULK ;(P1/) Unlock the connection block
ENDIF.
RETSKP ;All done, return.
ENDBS.
SUBTTL Calls from sysap -- Connection management -- SC.DIS (Disconnect)
; Here to close a connection.
;
; Usage:
; Call
; BLCAL. (SC.DIS,<SS.CID,SS.DIR>)
;
; Where:
; SS.CID -- Connect ID
; SS.DIR -- Disconnect reason
;
; Return (+1)
; T1/ Failure code
;
; Return (+2)
; No data is returned by this routine
;
;This routine may be called in any context. If at interrupt level, it
;honors the connection block lock after verifying that the current
;state allows disconnection, and saving the reason code. If at non-
;interrupt level, it uses CIOFF while changing the state. This locks
;out interruption from SC.DRQ, SC.ARQ, SC.ARS, SC.ORQ.
SC.DIS::BLSUB. (<SS.CID,SS.DIR>)
SAVEP
CIOFF ;Don't let state change
MOVE T1,SS.CID ;Get connect ID
CALL SC.CSC ;(T1/T1,P1) Check validity
RETBAD(,<CION>) ;Return failure
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,-1(P6) ;Get caller to feature routine
MOVE T3,P1 ;Get CB address
CALL RG.SSC ;(T1,T2,T3) Record SYSAP to SCA event
> ;End of IFN SCARNG
;See if the current state is correct, and get new connection and block states.
MOVEI T1,EV.DIS ;Event is disconnect call
CALL SC.OUT ;(T1,P1/T1,T2)
RETBAD (,<CION>) ;Illegal. Return failure
DMOVEM T1,P2 ;Save new states
;Copy caller's reason into the connection block
MOVE T3,SS.DIR ;Get the disconnect reason
STOR T3,CBSDRE,(P1) ;Store it in the connect block
;..
;We've done all we can if someone has the c.b. locked. So check that,
;and quit if it's true. (We must be at interrupt level, then.) Otherwise,
;lock it and continue. If we can't continue, the unlock routine will
;complete this function.
;..
MOVX T1,CBFDIS ;Set this bit if we have to wait
CALL SC.HNR ;(T1,P1/) See if lock is locked
IFNSK.
CION ;We're at interrupt level, and
RETSKP ; someone beat us to it.
ENDIF.
;We got the lock.
;If old state was "listen", indicate protocol is complete.
LOAD T3,CBCNST,(P1) ;Get old state
CAIE T3,.CSLIS ;Listening?
IFSKP.
MOVEI T3,.CSCLO ;Force its state to "closed"
STOR T3,CBCNST,(P1)
CALL SC.PTC ;(P1/) declare protocol complete
; SETONE CBFRAP,(P1) ;Mark as reapable (in case JSYS connection)
CION
RETSKP ;Finished. Return success
ENDIF.
;Store connection and block states and send message, if any
SKIPE P3
STOR P3,CBCNST,(P1) ;Store new connection state
SKIPN T1,P2 ;Get new block state
IFSKP.
MOVE P4,.CBSBA(P1) ;Get the address of the system block
CALL SC.SCA ;(T1,P1,P4/) Set block state and queue message
CION ;Changes in state are OK now
CALL SC.SNM ;(P4/) Send the message if possible
ELSE.
CION ;Allow changes in state now
ENDIF.
RETSKP ;Return all OK
ENDBS.
;SC.FN2 - Finish function of SC.DIS when unlocking a c.b.
;Accepts:
; P1/ address of c.b.
; P4/ address of system block
; CALL SC.FN2
;Returns +1: always
;This is called when the owner of a c.b. is about to unlock it.
;The c.b. is still locked, and we return with it in that condition.
;Since it is locked, we don't call SC.SNM, but set a bit so that the
;unlocker will do so.
SC.FN2:
SETZRO CBFDIS,(P1) ;Clear indication that this was deferred
;If old state was "listen", indicate protocol is complete
LOAD T3,CBCNST,(P1) ;Get old state
CAIE T3,.CSLIS ;Listening?
IFSKP.
MOVEI T3,.CSCLO ;Force its state to "closed"
STOR T3,CBCNST,(P1)
CALL SC.PTC ;(P1/) declare protocol complete
SETONE CBFRAP,(P1) ;Mark as reapable (in case JSYS connection)
RET ;Nothing more to do
ENDIF.
;Connection state may have changed since SC.DIS was first called. Make
;sure a disconnect is still legal, and get new states.
MOVEI T1,EV.DIS ;Event is disconnect call
CALL SC.OUT ;(T1,P1/T1,T2) Get new states
BUG. (HLT,SCAFN2,SCAMPI,SOFT,<SCA - Can't complete deferred call to SC.DIS>,,<
Cause: A sysap called SCAMPI at SC.DIS when the connection block was locked.
Now the connection block is being unlocked, and we are processing the
request. But SC.OUT has returned failure, indicating that this
function can't be performed for the current state. There is no way
to return that failure to the sysap, which believes that the
disconnection has proceeded normally. We could continue here, but
we crash in an effort to determine the cause.
Action: It may be impossible to analyze this from the current data.
If the ring buffer was enabled, try to determine the sequence of
events. Look at the current state of the connection block, and try
to see why SC.OUT failed.
>)
;Store connection and block states. If new block state is non-zero,
;we want to send a disconnect_request. Queue the block, and flag the
;unlock code to call SC.SNM
SKIPE T2 ;Zero means no change
STOR T2,CBCNST,(P1) ;Store new connection state
IFN. T1 ;Get new block state
CALL SC.SCA ;(T1,P1,P4/) Set block state and queue message
SETONE CBFSNM,(P1) ;Indicate call to SC.SNM was deferred
ENDIF.
RET
SUBTTL Calls from sysap -- Messages and datagrams
SUBTTL Calls from sysap -- Messages and datagrams -- SC.SDG (Send a datagram)
; Usage:
; Call
; BLCAL. (SC.SDG,<SS.CID,SS.FLG,SS.LDG,SS.ADG>)
;
; Where:
; SS.CID -- Connect ID
; SS.FLG -- Flag word (See SCAPAR.MAC)
; SS.LDG -- Len of datagram (in bytes)
; SS.ADG -- Address of datagram buffer
; SS.PRI -- Priority for packet send
; SS.PTH -- Path to send the packet on
; 0 -- Auto path select
; 1 -- Use path A
; 2 -- Use path B
;
; Return (+1)
; T1/ Failure code
;
; Return (+2)
; No data is returned by this routine,datagram sent
;
; ** Note **
; The address of the datagram buffer points to the bottom of the
;header area. The offset to where user data begins is (.MHUDA)
;
SC.SDG::BLSUB. (<SS.CID,SS.FLG,SS.LDG,SS.ADG,SS.PRI,SS.PTH>)
SAVEAC <P1,P2,P3,P4>
;Validate the arguments and check the state of the connection.
MOVE T1,SS.CID ;Get connect ID
CALL SC.CAL ;(T1/T1,P1) Check validity, and lock
RETBAD () ;Return failure
LOAD T1,CBCNST,(P1) ;Get the connection state
CAIE T1,.CSOPN ;Is the connection open?
RETBAD (SCSCWS,<CALL SC.ULK>) ;No. Return failure
;..
;Check the length, and add SCA overhead
;..
MOVE T1,SS.LDG ;Get the length of the datagram
MOVX T2,F.SPM ;Get the mode flag bit
TDNE T2,SS.FLG ;Are we doing high density mode???
IFNSK.
ADDI T1,C%OVHW ;Yes, add overhead in words, not bytes
CAILE T1,C%WORD ;Is datagram longer than we should be sending??
RETBAD (SCAPTL,<CALL SC.ULK>) ;Yes, complain
ELSE.
ADDI T1,C%OVHD ;No, add overhead size in bytes
CAILE T1,C%BYTD ;Is the datagram larger than I can send???
RETBAD (SCAPTL,<CALL SC.ULK>) ;Message is too long. Fail
ENDIF.
MOVEM T1,SS.LDG ;Store for later port call
;Add the SCA header to the packet we have been passed.
MOVE P2,SS.ADG ;Get address of packet
SETZRO MH$CDT,(P2) ;Zero the credit field
MOVEI P3,.STADG ;Get the packet type (Application datagram)
STOR P3,MH$MSG,(P2) ;Place the packet type in the datagram header
LOAD T2,CBDCID,(P1) ;Get the destination connect ID
STOR T2,MH$DCI,(P2) ;Put it in the message header
LOAD T2,CBSCID,(P1) ;Get the source connect ID now
STOR T2,MH$SCI,(P2) ;This also goes into the message header
;If sysap wants the buffer back, count this among its queued buffers.
MOVX T1,F.RTB ;Packet return status flag
TDNN T1,SS.FLG ;Is sysap getting this packet back?
IFSKP.
INCR CBNPO,(P1) ;Yes, increment count of outstanding packets
ELSE.
AOS .CBDGR(P1) ;No. Count this as queued for incoming datagram
ENDIF.
;Record the sending of a packet in the ring buffer
MOVE P4,.CBSBA(P1) ;Get a pointer to the system block
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,-1(P6) ;Get caller to feature routine
MOVE T3,SS.FLG ;Get flags
HRLZ T4,SS.PRI ;Position priority correctly
HRR T4,SS.LDG ; and get packet length
CALL RG.PKT ;(T1,T2,T3,T4,P2,P4) Record packet transmission
> ;End of IFN SCARNG
;..
;Pass the buffer off to the port driver, which will send it to the node
;..
CALL SC.ROU ;Byte swap the header for output
BLCAL. (SNDDG,<SS.LDG,SS.FLG,P4,P2,SS.PRI>)
JRST SSD.ER ;Handle the error
AOS SNDTAB(P3) ;Increment send count for this type of packet
CALL SC.ULK ;(P1/) Unlock the connection block
RETSKP ;Return OK.
; Here on an error. Undo the counting that we did, and return failure.
;If we had counted up this buffer as being on the free queue, put one
;there. It's possible that we've already dequeued one while the count was
;incremented, so we can't just decrement it.
SSD.ER: MOVX T2,F.RTB ;The packet return status flag again
TDNN T2,SS.FLG ;Did we bump the pending packet count?
IFSKP.
IFN SCADBG,<
LOAD T2,CBNPO,(P1) ;Get outstanding packet count
SKIPG T2 ;Is it greater than zero?
BUG. (HLT,SCANP1,SCAMPI,SOFT,<SCA - CBNPO about to go negative>,,<
Cause: We are about to decrement the count of queued buffers for a particular
connection block, but the count is already zero or less.
>)
> ;END OF IFN SCADBG
DECR CBNPO,(P1) ;Yes, packet send failed, fix count
ELSE.
MOVEI T1,1 ;No. We counted this as queued for input
CALL SC.ALD ;(T1/T1,T2,T3) Get a buffer from SCA
JRST SSD.EX ;Couldn't get one
IFN SCARNG,<
BLOCK.
SAVEAC <T1> ;Save smashed AC
MOVE T4,T1 ;Get buffer address
XMOVEI T1,. ;Get feature routine address
MOVE T2,-1(P6) ;Get PC of caller to feature routine
MOVEI T3,1 ;Set buffer count
TXO T3,RPQFLK ;Set port link flag
TXZ T3,RPQFMG ;Clear message free queue flag since datagram
CALL RG.PQM ;(T1,T2,T3,T4,P4) Record port manipulation
ENDBK.
> ;End of IFN SCARNG
BLCAL. (LNKDFQ,<P4,T1>) ;Link buffer chain onto Datagram Free queue
ENDIF.
SSD.EX: CALL SC.ULK ;(P1/) Unlock the connection block
RETBAD () ;Return with error code in T1
ENDBS.
SUBTTL Calls from sysap -- Messages and datagrams -- SC.SMG (Send a message)
; Here to send a sequenced data message.
;
; Usage:
; Call
; BLCAL. (SC.SMG,<SS.CID,SS.FLG,SS.LMG,SS.AMG,SS.PRI,SS.TSH,SS.PTH>)
;
; Where:
; SS.CID -- Connect ID
; SS.FLG -- Flag word (See SCAPAR.MAC)
; SS.LMG -- Length of message in bytes
; SS.AMG -- Address of message buffer
; SS.PRI -- Priority to give message
; SS.TSH -- Allow send only if more than this many send credits exist
; SS.PTH -- Path to send packet on
; 0 -- Auto path select
; 1 -- Use path A
; 2 -- Use path B
;
; Return (+1)
; T1/ Failure code
;
; Return (+2)
; No data returned
;
SC.SMG::BLSUB. (<SS.CID,SS.FLG,SS.LMG,SS.AMG,SS.PRI,SS.TSH,SS.PTH>)
SAVEP ;Save the quasi preserved ACs
;Validate the arguments and check the state of the connection.
MOVE T1,SS.CID ;Get connect ID
CALL SC.CAL ;(T1/T1,P1) Check validity, and lock
RETBAD () ;Return failure
LOAD T1,CBCNST,(P1) ;Get the connection state
CAIE T1,.CSOPN ;Is the connection open?
RETBAD (SCSCWS,<CALL SC.ULK>) ;No. Return failure
;..
;Check the length, and add SCA overhead
;..
MOVE T1,SS.LMG ;Get the length of the message
MOVX T2,F.SPM ;Get the mode flag bit
TDNE T2,SS.FLG ;Are we doing high density mode???
IFNSK.
ADDI T1,C%OVHW ;Yes, add overhead in words, not bytes
CAILE T1,C%WORM ;Is message longer than we should be sending???
RETBAD (SCAPTL,<CALL SC.ULK>) ;Yes, complain
ELSE.
ADDI T1,C%OVHD ;No, add overhead size in bytes
CAILE T1,C%BYTM ;Is the message larger than I can send???
RETBAD (SCAPTL,<CALL SC.ULK>) ;Message is to long, fail the send attempt
ENDIF.
MOVEM T1,SS.LMG ;Store for later port call
;Don't send if we don't have enough send credit. We must have more than the
;threshold provided by the caller.
SOS T1,.CBSCD(P1) ;Decrement send credit
CAML T1,SS.TSH ;Do we have more than the threshold?
IFSKP.
AOS .CBSCD(P1) ;No. Put it back where we found it, then
SETONE CBFNNC,(P1) ;Set the flag to notify on credit gain
RETBAD (SCSNEC,<CALL SC.ULK>) ;Return to caller with error code
ENDIF.
;If pending receive credit is positive, we need to tell the other side
;that it can have more credit, so put that value into the packet.
;And because it's no longer pending, add it into receive credit.
;If the sysap doesn't want the buffer back, that's one more receive credit.
;If we increment pending receive credit, and it was negative, count
;this as a successful cancel.
CIOFF ;Turn off interrupts for the moment
MOVX T1,F.RTB ;Get the response bit
TDNE T1,SS.FLG ;Does sysap want this buffer back?
IFSKP.
AOS T2,.CBPRC(P1) ;No. Increment pending receive credit
SKIPG T2 ;Had we been waiting to cancel some?
AOS .CBRTC(P1) ;Yes. Count this as return credit.
ENDIF.
SKIPG T2,.CBPRC(P1) ;Is pending receive credit now positive?
IFSKP.
ADDM T2,.CBRCD(P1) ;Yes. Add this into receive credit
SETZM .CBPRC(P1) ;It's no longer pending
ELSE.
SETZM T2 ;Negative. No credit in the packet
ENDIF.
CION ;Turn CI interrupts on again
;..
;Add the SCA header to the packet we have been passed.
;..
MOVE P2,SS.AMG ;Get address of packet
STOR T2,MH$CDT,(P2) ;Store the credit field into the header
MOVEI P3,.STAMG ;Get the message type
STOR P3,MH$MSG,(P2) ;Put the message type into the message header
LOAD T2,CBDCID,(P1) ;Get the detination connect ID
STOR T2,MH$DCI,(P2) ;Put it up in the message header
LOAD T2,CBSCID,(P1) ;Get the source connect ID now
STOR T2,MH$SCI,(P2) ;This also goes into the message header
;If sysap wants the buffer back, count this among its queued buffers.
MOVX T1,F.RTB ;Get the buffer return status flag
TDNN T1,SS.FLG ;Does sysap get this buffer back?
IFSKP.
INCR CBNPO,(P1) ;Yes, bump count of outstanding packets
ENDIF.
;Record the sending of a packet
MOVE P4,.CBSBA(P1) ;Get the address of the system block
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,-1(P6) ;Get caller to feature routine
MOVE T3,SS.FLG ;Get flags
HRLZ T4,SS.PRI ;Position priority correctly
HRR T4,SS.LMG ; and get packet length
CALL RG.PKT ;(T1,T2,T3,T4,P2,P4) Record packet transmission
> ;End of IFN SCARNG
;Pass the buffer off to the port driver, which will send it to the node
CALL SC.ROU ;Revert certain words in outgoing message
BLCAL. (SNDMSG,<SS.LMG,SS.FLG,P4,P2,SS.PRI>) ;Call the port driver
JRST SSM.ER ;Handle the error
AOS SNDTAB(P3) ;Bump the sent message count
;We may have incremented return_credit. If so, reclaim a buffer.
CALL SC.GCB ;(P1,P4/)Get a canceled buffer, if any
CALL SC.ULK ;(P1/) Unlock the connection block
RETSKP ;All ok.
; Here on an error from the port driver.
;If we had incremented credit because of this buffer, we may have
;taken the buffer off the port's free queue by now. We can't just decrement
;the count, so we give the port a buffer.
SSM.ER:
AOS .CBSCD(P1) ;We didn't use the send credit after all
CIOFF ;Interlock credit database
LOAD T2,MH$CDT,(P2) ;Get the credit field back from the packet
ADDM T2,.CBPRC(P1) ;Turn it back into pending credit
MOVNS T2 ;Get negative count
ADDM T2,.CBRCD(P1) ;Update the credit count in the CB
CION ;Release the interlock
MOVX T2,F.RTB ;Packet return status flag
TDNN T2,SS.FLG ;Did we bump the pending packet count
IFSKP.
IFN SCADBG,<
LOAD T2,CBNPO,(P1) ;Get outstanding packet count
SKIPG T2 ;Is it greater than zero?
BUG. (HLT,SCANP2,SCAMPI,SOFT,<SCA - CBNPO about to go negative>,,<
Cause: We are about to decrement the count of queued buffers for a
particular connection block, but the count is already zero or less.
>)
> ;END OF IFN SCADBG
DECR CBNPO,(P1) ;Yes, packet didn't go, correct count
ELSE.
MOVEI T1,1 ;No. We counted this as queued for input
CALL SC.ABF ;(T1/T1,T2,T3) Get a buffer from SCA
JRST SSM.EX
IFN SCARNG,<
BLOCK.
SAVEAC <T1> ;Saved smashed AC
MOVE T4,T1 ;Get buffer address
XMOVEI T1,. ;Get feature routine address
MOVE T2,-1(P6) ;Get PC of caller to feature routine
MOVEI T3,1 ;Get buffer count
TXO T3,RPQFLK ;Set port link flag
TXO T3,RPQFMG ;Set message free queue flag
CALL RG.PQM ;(T1,T2,T3,T4,P4) Record port manipulation
ENDBK.
> ;End of IFN SCARNG
BLCAL. (LNKMFQ,<P4,T1>) ;Link buffer onto message free queue
ENDIF.
SSM.EX: CALL SC.ULK ;(P1/) Unlock the connection block
RETBAD () ;Return with PPD error code
ENDBS.
SUBTTL Calls from sysap -- Messages and datagrams -- SC.RDG (Receive a datagram)
; This routine queues buffers for reception of datagrams.
;
; Usage:
; Call
; BLCAL. (SC.RDG,<SS.CID,SS.NUM,SS.ADR>)
;
; Where:
; SS.CID -- Connect ID
;
; If SS.ADR is zero then:
; SS.NUM -- Number of buffers to queue
;
; If SS.ADR is non-zero, then:
; SS.NUM is ignored, and
; SS.ADR -- Address of the buffer to queue. Note that this
; buffer must be a buffer procured from SCA. This means it has
; been used as a datagram buffer before. This is handy for those
; time you are done with an SCA datagram buffer and wish to
; requeue it. It eliminated the need for two calls to SCA...
;
; Return (+1)
; T1/ Number of buffers actually queued
;
; Return (+2)
; Buffer(s) have been queued to receive datagrams.
;
;NOTE: SC.RDG and SC.RMG are almost identical. If you need to change one,
;you'll probably need to change the other.
SC.RDG::BLSUB. (<SS.CID,SS.NUM,SS.ADR>)
SAVEAC <P1,P4>
MOVE T1,SS.CID ;Get user's connect ID
CALL SC.CAL ;(T1/T1,P1) Check validity, and lock
RETBAD () ;No. return failure
MOVE P4,.CBSBA(P1) ;Get the address of the system block
SKIPN T1,SS.ADR ;Did user provide address of buffer?
IFSKP.
SETZM (T1) ;Yes. Clear its FLINK
MOVEI T2,1 ;Number of buffers is 1
ELSE.
MOVE T1,SS.NUM ;Get number of buffers desired
CALL SC.ALD ;(T1/T1,T2,T3) Create the buffers
RETBAD (,<CALL SC.ULK>) ;Can't get them. Return failure
ENDIF.
CALL SCL.DC ;(T1,T2,P1,P4/) Queue the buffers to the port
CALL SC.ULK ;(P1/) Unlock the connection block
RETSKP ;And return all OK
ENDBS.
SUBTTL Calls from sysap -- Messages and datagrams -- SC.RMG (Receive a message)
; Here to queue a buffer to receive a sequenced message.
;
; Usage:
; Call
; BLCAL. (SC.RMG,<SS.CID,SS.NRB,SS.ADR>)
;
; Where:
; SS.CID -- Connect ID
;
; SS.NUM -- If SS.ADR is zero then this is the number of buffers
; to be queued for message reception.
; If SS.ADR is non-zero, then this is the number of buffers
; in the chain pointed to by SS.ADR.
;
; SS.ADR -- Address of message buffer (Optional)
; If SS.ADR is zero then a buffer is taken from the SCA
; message buffer free queue. If it is non-zero, then it
; is assumed that no problems will arise if the buffer
; is returned to the SCA pool. Since it may end up in
; the SCA pool it must be the length of all other buffers
; in the pool, must have come from the general free
; pool,and must be resident.
;
; Return (+1)
; T1/ Failure code
;
; Return (+2)
; Buffer has been queued.
;
;NOTE: SC.RDG and SC.RMG are almost identical. If you need to change one,
;you'll probably need to change the other.
SC.RMG::BLSUB. (<SS.CID,SS.NUM,SS.ADR>)
SAVEAC <P1,P3,P4>
MOVE T1,SS.CID ;Get user's connect ID
CALL SC.CAL ;(T1/T1,P1) Check validity, and lock
RETBAD () ;No. return failure
MOVE P4,.CBSBA(P1) ;Get the address of the system block
SKIPN T1,SS.ADR ;Did user provide address of buffer?
IFSKP.
SETZM (T1) ;Yes. Clear its FLINK
MOVEI T2,1 ;Number of buffers is 1
ELSE.
MOVE T1,SS.NUM ;Get number of buffers desired
CALL SC.ABF ;(T1/T1,T2,T3) Create the buffers
RETBAD (,<CALL SC.ULK>) ;Can't get them. Return failure
ENDIF.
;..
;..
;If we had been waiting to cancel some buffers, increment return
;credit for as many buffers as possible
MOVE P3,T2 ;Save buffer count
IFN SCARNG,<
BLOCK.
SAVEAC <T1> ;Saved smashed AC
MOVE T4,T1 ;Get buffer address
XMOVEI T1,. ;Get feature routine address
MOVE T2,-1(P6) ;Get PC of caller to feature routine
MOVE T3,P3 ;Get buffer count
TXO T3,RPQFLK ;Set port link flag
TXO T3,RPQFMG ;Set message free queue flag
CALL RG.PQM ;(T1,T2,T3,T4,P4) Record port manipulation
ENDBK.
> ;End of IFN SCARNG
BLCAL. (LNKMFQ,<P4,T1>) ;Link buffer chain onto Message Free queue
CIOFF
MOVE T2,.CBPRC(P1) ;Save current pending receive count
ADDM P3,.CBPRC(P1) ;Update to include new buffers
JUMPGE T2,SCR.EX ;If always positive, nothing more to do
SKIPLE .CBPRC(P1) ;Previously negative. Is it still?
IFSKP.
ADDM P3,.CBRTC(P1) ;Yes. Reclaim all the buffers, then
ELSE.
MOVMS T2 ;No. Take only the number we wanted
ADDM T2,.CBRTC(P1)
ENDIF.
;We may want to send a credit_request. SC.CDT will queue the connection
;block to the system block work queue if we need to send the request.
;If so, we must call SC.SNM to do the sending after we unlock the
;connection block.
SCR.EX: CION
CALL SC.GCB ;(P1,P4/) Get canceled buffer, if any
SETOM P3 ;Assume we'll need to send something
CALL SC.CDT ;(P1,P4/) Queue credit request if needed
SETZM P3 ;Don't need to send a message
CALL SC.ULK ;(P1/) Unlock the connection block
SKIPE P3 ;Need to send the request?
CALL SC.SNM ;(P4/) Yes. Send next message
RETSKP ;And return all OK
ENDBS.
SUBTTL Calls from sysap -- Messages and datagrams -- SC.CRD (Cancel Receive datagram)
; Here to dequeue a datagram buffer.
;
; Usage:
; Call
; BLCAL. (SC.CRD,<SS.CID,SS.NBF>)
;
; Where:
; SS.CID -- Connect ID
; SS.NUM -- Number of buffers to dequeue
;
; Return (+1)
; T1/ Failure code
;
; Return (+2)
; No data returned, buffers dequeued.
;
SC.CRD::BLSUB. (<SS.CID,SS.NUM>)
SAVEAC <P1,P4>
MOVE T1,SS.CID ;Get user's connect ID
CALL SC.CAL ;(T1/T1,P1) Check validity, and lock
RETBAD () ;No. return failure
SKIPE T1,SS.NUM ;Get the number of buffers desired
IFSKP.
CALL SC.ULK ;(P1/) Unlock the connection block
RETSKP ;Nothing to do (but why?)
ENDIF.
MOVE P4,.CBSBA(P1) ;Get the system block address
SCR.BL: SOSL .CBDGR(P1) ;Reduce number of queued buffers
IFSKP.
AOS .CBDGR(P1) ;Didn't have that many. Restore count
RETBAD (SCSNEB,<CALL SC.ULK>) ;Return failure
ENDIF.
BLCAL. (ULNKDG,<P4>) ;(/T1) Unlink a datagram buffer
IFNSK.
EXCH T1,P4 ;Save error code, get system block address
LOAD T1,SBDPA,(T1) ;Get node number
LOAD T2,CBSCID,(P1) ;Get connect ID
MOVE T3,SS.NUM ;Number we still need
BUG. (CHK,SCACCD,SCAMPI,SOFT,<SCA - Can't cancel datagram buffer>,<<T1,NODE>,<T2,CID>,<T3,COUNT>>,<
Cause: A sysap has done the "cancel receive datagram" function of SCA, and
the port's queue did not contain as many buffers as the system believes
it should contain.
Data: NODE - Node number
CID - Connect ID
COUNT - Number of buffers we couldn't get
>)
AOS .CBDGR(P1) ;Shouldn't have decremented count in this case
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,-1(P6) ;Get PC of caller to feature routine
MOVEI T3,1 ;Set buffer count
SETOM T4 ;Set buffer address to -1 due to failure
TXZ T3,RPQFLK ;Clear port link flag since unlinking
TXZ T3,RPQFMG ;Clear message free queue flag since datagram
CALL RG.PQM ;(T1,T2,T3,T4,P4) Record port manipulation
> ;End of IFN SCARNG
MOVE T1,P4 ;Restore error code
RETBAD (,<CALL SC.ULK>) ;Return PPD failure with error code
ENDIF.
IFN SCARNG,<
BLOCK.
SAVEAC <T1> ;Save smashed AC
MOVE T4,T1 ;Get buffer address
XMOVEI T1,. ;Get feature routine address
MOVE T2,-1(P6) ;Get PC of caller to feature routine
MOVEI T3,1 ;Set buffer count
TXZ T3,RPQFLK ;Clear port link flag since unlinking
TXZ T3,RPQFMG ;Clear message free queue flag since datagram
CALL RG.PQM ;(T1,T2,T3,T4,P4) Record port manipulation
ENDBK.
> ;End of IFN SCARNG
CALL SC.RLD ;(T1/) Return the buffer to the SCA pool
SOSLE SS.NUM ;Decrement count to dequeue
JRST SCR.BL ;More to do, loop to dequeue
CALL SC.ULK ;(P1/) Unlock the connection block
RETSKP ;All done, return happy
ENDBS.
SUBTTL Calls from sysap -- Messages and datagrams -- SC.CRM (Cancel receive message)
; This routine allows a SYSAP to cancel a buffer or set of buffers that were
;queued for message reception for a particular connection.
;
; Usage:
; BLCAL. (SC.CRM,<SS.CID,SS.NUM>)
;
; Where:
; SS.CID - The connection ID
; SS.NUM - The number of buffers to dequeue
;
; Return (+1)
; T1/ Error code
;
; Return (+2)
; Operation is legal. Buffers have been returned to SCA's pool,
; or credit_request will be sent.
SC.CRM::BLSUB. (<SS.CID,SS.NUM>)
SAVEAC <P1,P3,P4>
MOVE T1,SS.CID ;Get user's connect ID
CALL SC.CAL ;(T1/T1,P1) Check validity, and lock
RETBAD () ;No. return failure
MOVN T1,SS.NUM
SKIPE T1
IFSKP.
CALL SC.ULK ;(P1/) Unlock the connection block
RETSKP
ENDIF.
;Decrease pending receive credit by the number the sysap wants back.
;If we had a positive count, we can claim some (maybe all) of the buffers
;without asking permission.
CIOFF
MOVE T2,.CBPRC(P1) ;Save current pending receive count
ADDM T1,.CBPRC(P1) ;decrease it by number desired
JUMPLE T2,SCC.FF ;If already negative, can't reclaim any
SKIPGE .CBPRC(P1) ;Did we have enough already pending?
IFSKP.
MOVE T1,SS.NUM ;Yes. Get number we wanted
ADDM T1,.CBRTC(P1) ; and count all as return credit
ELSE.
ADDM T2,.CBRTC(P1) ;No. Claim the ones we had pending
ENDIF.
;We may need to send a credit_request. If so, SC.CD5 will queue the
;packet. We must cause it to be sent after unlocking the connection
;block
SCC.FF: CION
MOVE P4,.CBSBA(P1) ;Get the system block address
CALL SC.GCB ;(P1,P4/) Get canceled buffer, if any
SETOM P3 ;Assume we'll need to send something
CALL SC.CD5 ;(P1,P4/) Queue credit request if needed
SETZM P3 ;Don't need to send a message
CALL SC.ULK ;(P1/) Unlock the connection block
SKIPE P3 ;Need to send the request?
CALL SC.SNM ;(P4/) Yes. Send next message
RETSKP
ENDBS.
SUBTTL Calls from sysap -- Named buffers
SUBTTL Calls from sysap -- Named buffers -- SC.MAP (Map a buffer)
; This routine defines a buffer for the port...
;
; Call
; BLCAL. (SC.MAP,<SS.BLK,SS.RWF>)
;
; Where:
; SS.BLK -- Address of the first entry in a chain of buffer
; descriptor blocks.
;
; Return (+1)
; T1/ Error code
;
; Return (+2)
; T1/ 32 bit buffer name
;
; Buffer descriptor blocks ahve the following format:
;
; !=======================================================!
; .MDNXT ! Address of next buffer in chain or zero if none !
; !-------------------------------------------------------!
; .MDFLG ! Flags !
; !-------------------------------------------------------!
; .MDLEN ! Length of buffer segment !
; !-------------------------------------------------------!
; .MDADR ! Physical address of the segment !
; !-------------------------------------------------------!
; \ \
; \ \
; \ N segment descriptor pairs \
; \ \
; \ \
; !-------------------------------------------------------!
; ! A zero length to terminate the descriptor list !
; !=======================================================!
;
; Note that .MDNXT is an offset from the start of the block to the address of
;the next entry in the chain, but .MDLEN and .MDADR are offsets within
;the words describing a single buffer segment.
;
SC.MAP::JRST MAPBUF ;THIS JUST PASSES THROUGH TO MAPBUF.
;THE ARGUMENTS AND CALLING CONVENTIONS
;FOR SC.MAP AND MAPBUF ARE THE SAME.
SUBTTL Calls from sysap -- Named buffers -- SC.UMP (Unmap a mapped buffer)
; This routine is called when the SYSAP has completed all operations with a
;named (mapped) buffer. Note that doing data transfers does not unmap the
;buffer. The buffer will remain mapped until the user has done this unmap
;call.
;
; Call
; BLCAL. (SS.UMP,<SS.NAM>)
;
; Where:
; SS.NAM -- 32 bit name of buffer to be unmapped
;
; Return (+1)
; T1/ Error code
;
; Return (+2)
; No data, buffer name is no longer valid
;
SC.UMP::JRST UMAP ;JUST PASS THROUGH TO UMAP. THE
;ARGUMENTS AND CALLING CONVENTIONS
;FOR SC.UMP AND UMAP ARE THE SAME.
SUBTTL Calls from sysap -- Named buffers -- SC.SND (Send DMA data)
; This routine sends block data from a named buffer.
;
; Call
; BLCAL. (SC.SND,<SS.CID,SS.SNM,SS.RNM,SS.SOF,SS.ROF>)
;
; Where:
; SS.CID -- Connection on which this transfer is being done
; SS.SNM -- 32 bit name of the buffer to get data from
; SS.RNM -- 32 bit name of buffer to put data into
; SS.SOF -- Byte offset into transmision buffer
; SS.ROF -- Byte offset into reception buffer
;
; Return (+1)
; T1/ Error code
;
; Return (+2)
; No data returned.
;
;Note:
;The corporate spec provides for the sysap's selecting
;the threshold value; we have chosen to make it 1 always.
SC.SND::BLSUB. (<SS.CID,SS.SNM,SS.RNM,SS.SOF,SS.ROF>)
SETZM T1 ;Indicate send
JRST SC.SN2
SC.REQ::BLSUB. (<SS.CID,SS.SNM,SS.RNM,SS.SOF,SS.ROF>)
SETOM T1 ;indicate request
SC.SN2: SAVEAC <P1,P3,P4>
MOVEM T1,P3 ;Save flag
MOVE T1,SS.CID ;Get connect ID
CALL SC.CAL ;(T1/T1,P1) Check validity, and lock
RETBAD ()
;Don't send if the connection isn't open
LOAD T1,CBCNST,(P1) ;Get the current connection state
CAIE T1,.CSOPN ;Is this connection open???
RETBAD (SCSCWS,<CALL SC.ULK>) ;No, return "connection in wrong state"
;Don't send if we don't have enough send credit. Must have at least 1
;This code is race-free. Comparing and then decrementing is not.
SOS T1,.CBSCD(P1) ;Decrement send credit
CAIL T1,1 ;Do we have more than the threshold?
IFSKP.
AOS .CBSCD(P1) ;No. Put it back
SETONE CBFNNC,(P1) ;No. Indicate waiting for credit callback
RETBAD (SCSNEC,<CALL SC.ULK>) ;Return "not enough credit"
ENDIF.
;..
;..
MOVE P4,.CBSBA(P1) ;Get a pointer to the system block
IFE. P3 ;Want to send?
BLCAL. (SNDDAT,<SS.SNM,SS.RNM,SS.SOF,SS.ROF,SS.CID>)
JRST SC.SN5 ;Failed
ELSE.
BLCAL. (REQDAT,<SS.SNM,SS.RNM,SS.SOF,SS.ROF,SS.CID>)
JRST SC.SN5 ;Failed
ENDIF.
CALL SC.ULK ;(P1/) Unlock the connection block
RETSKP ;Return OK
;Here when we failed. This happens only if the v.c. is closed.
SC.SN5: AOS .CBSCD(P1) ;We didn't use the send credit after all
CALL SC.ULK ;(P1/) Unlock the connection block
RETBAD () ;Return with failure
ENDBS.
SUBTTL Calls from sysap -- State polling
SUBTTL Calls from sysap -- State polling -- SC.CSP (Connect state poll)
; Here to update the state of a connection.
;
; Usage:
;
; Call
; BLCAL. (SC.CSP,<SS.CID,SS.ADR>)
;
; Where:
; SS.CID -- Connect ID
; SS.ADR -- Address of block in which to place data
;
; Return (+1) Failure, with:
; T1/ Failure code
; T2/ Pointer to data block
;
; Return (+2) Success, with:
; T1/ Connect ID
; T2/ Pointer to data block
;
;
SC.CSP::BLSUB. (<SS.CID,SS.ADR>)
SAVEP ;Save the quasi ACs
MOVE T1,SS.CID ;Get user's connect ID
CALL SC.CAL ;(T1/T1,P1) Check validity and lock CB
RETBAD (,<MOVE T2,SS.ADR>) ;Invalid connect ID, return failure
MOVE T1,SS.ADR ;Get address of where to place data
; Now that we have the space, fill it with what we promised it would contain.
;
LOAD T2,CBCNST,(P1) ;Get the connection state
STOR T2,CDCST,(T1) ;Store in the allocated block
LOAD T2,CBDCID,(P1) ;Get the destination connect ID
STOR T2,CDDCI,(T1) ;Store this in the returned data
DMOVE T2,.CBDPN(P1) ;Get first and second word of destination name
DMOVEM T2,.CDDPN(T1) ;Put it up in the returned data
DMOVE T2,.CBDPN+2(P1) ;Get third and fourth word of destination name
DMOVEM T2,.CDDPN+2(T1) ;Put it up in the returned data
LOAD T2,CBDNOD,(P1) ;Get the node number
STOR T2,CDNOD,(T1) ;Put it up in the returned data
LOAD T2,CBDDRE,(P1) ;Destination disconnect reasons
STOR T2,CDDREA,(T1) ;Put this up in the returned data too...
LOAD T2,CBSDRE,(P1) ;Once more kids, get the source disconn reasons
STOR T2,CDSREA,(T1) ;One last time... Put it in the returned data
CALL SC.ULK ;(P1/) Unlock connect block
MOVE T2,T1 ;Move block address
MOVE T1,SS.CID ;Get connect ID
RETSKP ;Return success
ENDBS.
SUBTTL Calls from sysap -- State polling -- SC.DCI (Return destination connect ID)
; This routine returns the destination connect ID for a connection.
;
; Usage:
; Call
; BLCAL. (SC.DCI,<SS.CID>)
;
; Return (+1)
; T1/ Error code
;
; Return (+2)
; T1/ Destination connect ID for given connection
;
SC.DCI::BLSUB. (<SS.CID>)
SAVEAC <P1> ;Save the preserved AC we are about to kill
MOVE T1,SS.CID ;Get connect ID
CALL SC.CAL ;(T1/T1,P1) Check validity, and lock
RETBAD() ;Return failure
LOAD T1,CBDCID,(P1) ;Get the destination connect ID
CALL SC.ULK ;(P1/) Unlock the connection block
RETSKP ;All done...
ENDBS.
SUBTTL Calls from sysap -- State polling -- SC.RCD (Return configuration data)
; Here to get configuration data on a system.
;
; Usage:
;
; Call
; BLCAL. (SC.RCD,<SS.NOD,SS.ADR>)
;
; Where:
; SS.NOD -- System block index
; SS.ADR -- Address of block in which to place data
;
; Return (+1) Failure, with:
; T1/ Failure code
; T2/ Address of data block
;
; Return (+2) Success, with:
; T1/ Node number
; T2/ Address of data block
;
SC.RCD::BLSUB. (<SS.NOD,SS.ADR>)
SAVEP ;Save the preserved ACs we use here
MOVE T2,SS.NOD ;Get the callers SBI
CAIG T2,C%SBLL-1 ;Are we over the SBLIST size???
SKIPGE T2 ;Or maybe a negative number???
RETBAD (SCSBAS,<MOVE T2,SS.ADR>) ;Bad arguments, tell the caller
SKIPN P4,SBLIST(T2) ;See if (and get) if there is an SB addr here
RETBAD (SCSBAS,<MOVE T2,SS.ADR>) ;No entry for this SBI
MOVE T2,SS.ADR ;Get address of data block
LOAD T3,SBVCST,(P4) ;Get the virtual circuit state from the SB
STOR T3,RDVCST,(T2) ;Put it up in the returned data
LOAD T3,SBDPA,(P4) ;Get the destination port number
STOR T3,RDPORT,(T2) ;And this also goes in the returned data
MOVE T3,.SBDSS(P4) ;Get the first word of the system address
MOVEM T3,.RDSYS(T2) ;Put it in the returned data
MOVE T3,.SBDSS+1(P4) ;Now the second word of the system address
MOVEM T3,.RDSYS+1(T2) ;Put it with its friend...
LOAD T3,SBMXDG,(P4) ;Get the max datagram system will allow
STOR T3,RDMDG,(T2) ;Put it up in the returned data
LOAD T3,SBMXMG,(P4) ;Now the max message allowed
STOR T3,RDMMS,(T2) ;Store in data
LOAD T3,SBDTSW,(P4) ;Dest software type
STOR T3,RDDST,(T2) ;. . .
LOAD T3,SBDVSW,(P4) ;Dest software version
STOR T3,RDDSV,(T2) ;. . .
MOVE T3,.SBDSE(P4) ;Destination software incarnation (first word)
MOVEM T3,.RDDSI(T2) ;. . .
MOVE T3,.SBDSE+1(P4) ;Destination software incarnation (second word)
MOVEM T3,.RDDSI+1(T2) ;. . .
LOAD T3,SBDTHW,(P4) ;Destination hardware type
STOR T3,RDDHT,(T2) ;. . .
LOAD T3,SBDVHW,(P4) ;Destination hardware version
STOR T3,RDDHV,(T2) ;. . .
DMOVE T3,.SBNNM(P4) ;Get destination node name
DMOVEM T3,.RDNNM(T2) ;Store it in returned data
MOVE T3,.SBDPC(P4) ;Get destination port characteristics
MOVEM T3,.RDPCH(T2) ;Store it in returned data
MOVE T3,.SBDCR(P4) ;Get destination port revision level
MOVEM T3,.RDPRL(T2) ;Store it in returned data
MOVE T3,.SBDPF(P4) ;Get destination port functionality
MOVEM T3,.RDPFC(T2) ;Store it in returned data
MOVE T3,.SBDPS(P4) ;Get destination port state
MOVEM T3,.RDPST(T2) ;Store it in returned data
MOVE T1,SS.NOD ;Get node number back
RETSKP ;Return success
ENDBS.
SUBTTL Calls from sysap -- State polling -- SC.NOD (Return node number given CID)
;This routine returns the node number associated with a CID...
;
; Usage:
; CALL SC.NOD
; T1/ Local connect ID
;
; Return (+1) Always
; T1/ Local connect ID (or SCSIID error code if CID invalid)
; T2/ Node number of the remote end of the connection specified
; (or -1 if the CID is invalid)
;
SC.NOD::SAVEAC <T3,T4,P1> ;Save the ACs we kill here
CALL SC.CAL ;(T1/T1,P1) Check validity, and lock
RETBAD (,<SETOM T2>) ;Return failure
MOVE T2,.CBSBA(P1) ;Get the system block address
LOAD T2,SBDPA,(T2) ;Get the node number
CALL SC.ULK ;(P1/) Unlock the connection block
RET
SUBTTL Calls from sysap -- State polling -- SC.RAC (Return available credit)
; This routine returns the number of credits available to a particular connect.
;
; Usage:
; Call
; BLCAL. (SC.RAC,<SS.CID>)
;
; Where:
; SS.CID -- Connect ID of connection whose credits we desire
;
; Return (+1)
; T1/ Error code
;
; Return (+2)
; T1/ Send credit
; T2/ Receive credit
; T3/ Number of datagram buffers queued
;
REPEAT 0,<
SC.RAC: BLSUB. (<SS.CID>)
SAVEAC <P1> ;Save the CB addr AC
MOVE T1,SS.CID ;Get the callers connect ID
CALL SC.CSC ;Is it valid???
RETBAD (SCSIID) ;Nope, yell at the caller
MOVX T1,CBFABT ;Get the CB aborted bit
TDNE T1,.CBFLG(P1) ;Is the abort bit lit???
RETBAD (SCSIID) ;Yes, return bad CID
MOVE T1,.CBSCD(P1) ;Get the send credit
MOVE T2,.CBRCD(P1) ; the receive credit
MOVE T3,.CBDGR(P1) ; and the number of datagrams queued
RETSKP ;Return all OK
ENDBS.
>
;END REPEAT 0
SUBTTL Calls from sysap -- State polling -- SC.PRT (Return local port number)
; This routine returns the local port number, but only on a KL with a single
;CI port!.
;
; Usage:
; Call
; No arguments
;
; Return (+1)
; No known KLIPA port
;
; Return (+2)
; T1/ Local port number
;
SC.PRT::CALLRET LOCPRT ;Get requested info from the port driver
SUBTTL Calls from sysap -- Maintenance
SUBTTL Calls from sysap -- Maintenance -- SC.RST (Reset remote system)
; This routine will call the port driver to send a remote node reset message.
;No checks are done for remote node type since this message type is ignored
;by KL's and "other" reasonable machines.
;
; Usage:
; Call
; BLCAL. (SC.RST,<SS.NOD,SS.FRB>)
;
; Where:
; SS.NOD -- SBI or remote system to be reset
; SS.FRB -- Force reset bit, if one, reset is forced, if zero,
; reset will only be done if we are the last node to do
; a reset for this remote
;
; Return (+1)
; T1/ Error code
;
; Return (+2)
; No data returned, reset packet sent
;
SC.RST::BLSUB. (<SS.NOD,SS.FRB>)
SAVEAC <P4>
MOVE P4,SS.NOD ;Get the SBI of the doomed remote
SKIPN P4,SBLIST(P4) ;Now the address of the system block
RETBAD (SCSISB) ;No such system, return failure
BLCAL. (CLOSVC,<P4>) ;CLOSE THE VC
HRRZ T1,.SBDSP(P4) ;Get the node number.
BLCAL. (RMTRST,<T1,SS.FRB>);Have te port reset the remote please
RETBAD () ;Return with error code in T1
RETSKP ;Return ok
ENDBS.
SUBTTL Calls from sysap -- Maintenance -- SC.STA (Start remote node)
; This routine will call the port driver to start a remote node. Note that
;no check of system type is done since KL's and other important machines will
;ignore this packet type...
;
; Usage:
; Call
; BLCAL. (SC.STA,<SS.NOD,SS.DSA,SS.STA>)
;
; Where:
; SS.NOD -- SBI of ill fated remote
; SS.DSA -- Flag for use of SS.STA, if zero, SS.STA is ignored and
; the default start address is used. If non-zero, SS.STA
; is used as the start address of the remote.
; SS.STA -- Start address for the remote node. Only used if SS.DSA is
; non-zero.
;
; Return (+1)
; T1/ Error code
;
; Return (+2)
; No data returned
;
SC.STA::BLSUB. (<SS.NOD,SS.DSA,SS.STA>)
SAVEAC <P4>
MOVE P4,SS.NOD ;Get the desired system block index
SKIPN P4,SBLIST(P4) ;Get the system block address for given SBI
RETBAD (SCSISB) ;No such system, return badness
HRRZ T1,.SBDSP(P4) ;Get the node number.
BLCAL. (RMTSTA,<T1,SS.DSA,SS.STA>) ;Do the packet send
RETBAD () ;Fail with code from the port driver
RETSKP ;All ok
ENDBS.
SUBTTL Call from port driver
SUBTTL Call from port driver -- SC.ONL (Node has come online)
; This routine handles the appearance of a node.
;
SC.ONL::BLSUB. (<SS.NOD>)
SAVEAC <Q1,Q2,P1,P3,P4>
SKIPN SCAINI ;Has SCA been initialized???
IFNSK.
BUG.(CHK,SCAOBI,SCAMPI,SOFT,<SCA - Online before initialization done>,,<
Cause: A node came online before the initialization of SCA was completed.
>)
CALL SCA ;It has now...
ENDIF.
MOVE T2,SS.NOD ;Get the node number
MOVE P4,SBLIST(T2) ;Now for the system block address
;By now, we shouldn't still be stuck on buffers
IFN SCADBG,<
MOVE T3,SS.NOD ;Get node number for bugs below
MOVE T1,BITS(T2)
TDNN T1,SBSTUK ;Is this system block stuck on buffers?
IFSKP.
BUG.(CHK,SCAONS,SCAMPI,SOFT,<SCA - Online when stuck on buffers>,<<T3,NODE>>,<
Cause: A node came online while stuck on buffers. This should have been cleared
up when the node went offline.
Action: Determine whether PHYKLP is calling twice with the same node.
If not, something has probably clobbered the flags word for this
system block.
Data: NODE - Node number
>)
ANDCAM T1,SBSTUK
ENDIF.
;The system block's work queue should have been cleared before.
SKIPN .SBTWQ(P4) ;Does work queue still exist?
IFSKP.
BUG.(CHK,SCAOWJ,SCAMPI,SOFT,<SCA - Online when work queue exists>,<<T3,NODE>>,<
Cause: A node came online while its work queue still contained entries. THis
should have been cleaned up when the node went offline.
Data: NODE - Node number
>)
XMOVEI T1,.SBTWQ(P4)
MOVEM T1,.SBBWQ(P4)
SETZM .SBTWQ(P4)
ENDIF.
;..
;No connection blocks should be locked now. We get here only after the
;v.c. has been closed, at which point the c.b.'s should have been unlocked.
;..
SKIPN T1,.SBCLC(P4) ;Is a connection block still locked?
IFSKP.
BUG.(CHK,SCAOWL,SCAMPI,SOFT,<SCA - Online when connection block still locked>,<<T3,NODE>,<T1,COUNT>>,<
Cause: Node came online while a connection block was still locked. We should
not have closed the v.c. until this count was zero.
Data: NODE - Node number
COUNT - Lock count for connection block
>)
SETZM .SBCLC(P4) ;Clear it and hope for the best
ENDIF.
> ;END IFN SCADBG
SETZRO SBFLG,(P4) ;Clear any residual flags
SETZM .SBTIM(P4) ;Indicate we have not spoken to the SB yet
; See if there are enough buffers around or do we need more. Also update the
;minimum number of buffers we should have onhand.
AOS SBCNT ;Account for the new system
CALL SC.SBT ;Set new buffer thresholds
MOVE T1,MINMSG ;Number of message buffers we should have
MOVE T2,MINDG ;Number of datagram buffers we should have
CAMG T1,FQCNT ;Do we have enough message buffers?
CAMLE T2,DFQCNT ;Yes. Do we have enough datagram buffers?
AOS DDCFSF ;Need to create buffers. Ask DDMP fork to run
;..
;Get two buffers -- one for incoming (give that to the port), and one for
;outgoing (queue that to the system block)
;..
IFN SCADBG,<
SKIPN T2,.SBOBB(P4) ;Already have a buffer?
IFSKP.
LOAD T3,SS.NOD ;Get node number
BUG.(CHK,SCAOBB,SCAMPI,SOFT,<SCA - Buffer already exists>,<<T3,NODE>,<T2,BUFFER>>,<
Cause: A node came online and we already had an outbound buffer for it.
This field should have been zeroed when the node went offline. Perhaps
SCAMPI was called twice for node online. The buffer will be lost after
this.
Data: NODE - Node number
BUFFER - Address of connection management buffer
>)
ENDIF.
> ;END IFN SCADBG
MOVEI T1,1 ;Need one buffer
CALL SC.ABF ;(T1/T1) Get buffer from SCA pool
JRST SON.ME
MOVEM T1,.SBOBB(P4) ;Make this the outbound buffer
MOVEI T1,1 ;Need another one
CALL SC.ABF ;(T1/T1,T2,T3) Get buffer from SCA pool
JRST SON.ME
IFN SCARNG,<
BLOCK.
SAVEAC <T1> ;Saved smashed AC
MOVE T4,T1 ;Get buffer address
XMOVEI T1,. ;Get feature routine address
MOVE T2,-1(P6) ;Get PC of caller to feature routine
MOVEI T3,1 ;Get buffer count
TXO T3,RPQFLK ;Set port link flag
TXO T3,RPQFMG ;Set message free queue flag
CALL RG.PQM ;(T1,T2,T3,T4,P4) Record port manipulation
ENDBK.
> ;End of IFN SCARNG
BLCAL. (LNKMFQ,<P4,T1>) ;Give it to port for incoming messages
;..
;Notify each sysap that's asked to be notified when nodes come online
;..
MOVE Q1,NOTTAB ;Get the address of the notification list
SON.SL: SKIPN (Q1) ;Is there an entry
; * * * Should return +1
RETSKP ;Nope, we are all done here
; * * * *
MOVX T1,.SSNCO ;Say why we are calling the SYSAP
MOVE T2,SS.NOD ;Indicate which node
CALL @(Q1) ;Call the SYSAP about this new node
NOP ;Handle any silly SYSAP's
AOS Q1 ;Point to the next entry
CAMG Q1,NOTEND ;Are we going off the end of the table???
JRST SON.SL ;No, loop for another entry
RETSKP ;Off the end of the table, all done
;Here when we failed to allocate the two buffers required for connection
;management. In theory, we should be able to tolerate this failure, and
;wait until job 0 creates more buffers. If we start to see this problem,
;it seems reasonable to try to do that. For now, we'll crash.
SON.ME: BUG. (HLT,SCASCQ,SCAMPI,SOFT,<SCA - Can't get connection management buffers>,<<T1,ERROR>>,<
Cause: SCA has been notified of a new system's coming online. It tried
to allocate two buffers to be used for connection management, and
failed. This indicates that a large number of buffers have been
allocated at interrupt level, and the process that creates more
hasn't run recently.
Action: With some work, it would be possible to recover from this
by deferring buffer allocation to process context. Meanwhile, try
to find out why buffers are being used so rapidly, or why job 0
is not running.
Data: ERROR - error code from allocation routine
>)
ENDBS.
SUBTTL Call from port driver -- SC.ERR (Node(s) have gone away)
; This routine handles a node going offline. Note that all SYSAP connections
;on this system must be closed and the SYSAP notified...
;
; Call
;
; BLCAL. (SC.ERR,<SS.NOD>)
;
; Return (+1)
; T1/ Error code
;
; Return (+2)
; No data returned...
;
SC.ERR::BLSUB. (<SS.NOD>)
CIOFF ;Dont do CI work until CB's are marked closed
SAVEP ;Save the preserved regs we kill
;See if we already counted this system as going offline. If not, set the
;flag saying we did, and decrement the count of systems online.
MOVE P4,SS.NOD ;Get the SBI of the system that went offline
MOVE P4,SBLIST(P4) ;Get the address of the system block
TMNN SBFOFL,(P4) ;Have we seen this as offline already?
IFSKP.
LOAD T1,SBDPA,(P4) ;Yes. get node number
BUG. (CHK,SCAOF2,SCAMPI,SOFT,<SCA - Offline twice for a node>,<<T1,NODE>>,<
Cause: SC.ERR was called when a system block was already flagged as offline.
While this won't cause an immediate problem, it does indicate some
sort of internal confusion and should be investigated.
Data: NODE - Node number
>)
CION
JRST SOF.NT
ENDIF.
SETONE SBFOFL,(P4) ;No. Mark it
SOSL SBCNT ;Decrement the system count
IFSKP.
BUG. (CHK,SCANSC,SCAMPI,SOFT,<SCA - Negative system count>,,<
Cause: SCA was notified of a system's going offline and decremented the count
of systems currently online. In doing so the count went negative.
>)
SETZM SBCNT ;Make the count zero, rather than -1
ENDIF. ; and continue normally
;..
;Loop over all connections on the SB and mark them as closed. If they were
;already closed, the sysap isn't interested in them any more. If not, tell
;the sysap that the connection has been closed.
;If not CIOFF, need NOSKED to keep reaper from changing the list
;Sysaps expect this callback not to be interrupted
;..
SKIPN P1,.SBFCB(P4) ;Get the addr of the first connection block
JRST SOF.NT ;No connects to mark, go on
SOF.CL:
SETONE CBFCVC,(P1) ;Indicate v.c. was closed
MOVX T1,CBFERR ;Set this flag if it's locked
CALL SC.HNR ;(T1,P1/) Is the c.b. locked?
IFNSK.
AOS .SBCLC(P4)
JRST SOF.NX ;Yes. Go to the next one
ENDIF.
LOAD T2,CBCNST,(P1) ;Get current state
MOVEI T1,.CSCLO ;New state will be "closed"
STOR T1,CBCNST,(P1) ;Store as new connect state
CAIN T2,.CSCLO ;Was it already closed?
IFSKP. ;No.
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,-1(P6) ;Get PC of caller to feature routine
MOVEI T3,.SSPBC ;Get callback notification code
CALL RG.SCS ;(T1,T2,T3,P1) Record callback event
> ;End of IFN SCARNG
MOVEI T1,.SSPBC ;Get the notification code back
LOAD T2,CBSCID,(P1) ;Get the local connect ID
MOVE T3,SS.NOD ;Get node number
SETZM T4 ;Clear unused AC
CALL @.CBADR(P1) ;Notify the SYSAP of the disaster
ENDIF.
SETZM .CBRQC(P1) ;We'll never get credit_response now
; so clear this so we can reap
CALL SC.PTC ;(P1/) Indicate protocol is complete
SOF.NX: SKIPE P1,.CBANB(P1) ;Is there a next connect block???
JRST SOF.CL ;Yes, loop for its new state
SOF.NT:
CALL SC.SBT ;Set new buffer thresholds based on SBCNT
;If there were pending connect_req or accept_req messages that required
;buffers, this system may have been marked as stuck. These messages will
;no longer be sent. Clear the "stuck" bit, and get rid of the queue of
;connection blocks needed to send requests.
MOVE T1,SS.NOD ;Get system block index
MOVE T1,BITS(T1) ;Mark this block as no longer
ANDCAM T1,SBSTUK ; stuck on buffers
XMOVEI T1,.SBTWQ(P4) ;Else, we have exhauted the q, init list ptrs
MOVEM T1,.SBBWQ(P4) ;Init tail as pointer to head
SETZM .SBTWQ(P4) ;Init head as zero
CION
;..
;When system came online, we got 2 buffers from the SCA pool for sending
;and receiving SCS control messages. Give them back to SCA now
;..
SETZM P2 ;Prepare to clear the address of the buffer
EXCH P2,.SBOBB(P4) ;Grab outbound buffer if it's there
SKIPN P2 ;Was it there?
IFSKP.
MOVE T1,P2 ;Yes. Give it back to SCA
CALL SC.RBF ;(T1/)
ENDIF.
BLCAL. (ULNKMG,<P4>) ;(/T1) Get a buffer from the port
JRST SOF.NG ;Couldn't get it.
IFN SCARNG,<
BLOCK.
SAVEAC <T1> ;Save smashed AC
MOVE T4,T1 ;Get buffer address
XMOVEI T1,. ;Get feature routine address
MOVE T2,-1(P6) ;Get PC of caller to feature routine
MOVEI T3,1 ;Set buffer count
TXZ T3,RPQFLK ;Clear port link flag since unlinking
TXO T3,RPQFMG ;Set message free queue flag
CALL RG.PQM ;(T1,T2,T3,T4,P4) Record port manipulation
ENDBK.
> ;End of IFN SCARNG
CALL SC.RBF ;(T1/) This was inbound buffer. Give it to SCA
JUMPN P2,SOF.NZ ;Did we have an outbound buffer?
BLCAL. (ULNKMG,<P4>) ;(/T1) No. get another from the port
JRST SOF.NG ;Couldn't get it
IFN SCARNG,<
BLOCK.
SAVEAC <T1> ;Save smashed AC
MOVE T4,T1 ;Get buffer address
XMOVEI T1,. ;Get feature routine address
MOVE T2,-1(P6) ;Get PC of caller to feature routine
MOVEI T3,1 ;Set buffer count
TXZ T3,RPQFLK ;Clear port link flag since unlinking
TXO T3,RPQFMG ;Set message free queue flag
CALL RG.PQM ;(T1,T2,T3,T4,P4) Record port manipulation
ENDBK.
> ;End of IFN SCARNG
CALL SC.RBF ;(T1/) Give it to SCA
JRST SOF.NZ ;Skip past the error code
;The port ran out of buffers. In theory, we put two buffers on the queue when
;this node came online, so we ought to be able to take two off.
SOF.NG: LOAD T1,SBDPA,(P4)
BUG. (CHK,SCANMB,SCAMPI,SOFT,<SCA - Can't return SCS control message buffer>,<<T1,NODE>>,<
Cause: A node went offline, and we tried to retrieve two message buffers from
the port's queue. The port's queue is empty.
Action: This may happen legitimately, depending on timing. However,
if it persists, we should stock the port's message free queue more
generously at system startup.
Data: NODE - Node number
>)
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,-1(P6) ;Get PC of caller to feature routine
MOVEI T3,1 ;Set buffer count
SETOM T4 ;Set buffer address to -1 due to failure
TXZ T3,RPQFLK ;Clear port link flag since unlinking
TXO T3,RPQFMG ;Set message free queue flag
CALL RG.PQM ;(T1,T2,T3,T4,P4) Record port manipulation
> ;End of IFN SCARNG
; Here to notify ALL sysaps that a node has gone offline. Note that this means
;any sysap with connections open to the node that went offline will get one
;extranious notification.
;
; NOTE: For this callback the connect ID returned in T2 is -1.
SOF.NZ: MOVE P5,NOTTAB ;Start with first word in notification table
SOF.VL: SKIPN (P5) ;Is there an entry
JRST SOF.VC ;Nope, go do VC opening checks
MOVX T1,.SSPBC ;Say why we are calling the SYSAP
SETOM T2 ;There is no CID returned for this callback
MOVE T3,SS.NOD ;Indicate which node
SETZM T4 ;Insure the rest of the calling ACs are zero
CALL @(P5) ;Call the SYSAP about this new node
AOS P5 ;Point to the next entry
CAMG P5,NOTEND ;Have we gone off the end of the table???
JRST SOF.VL ;No. Loop for more entries
;Tell PHYKLP it can reopen the v.c. unless we have locked connection
;blocks. If we do, SC.ULK will eventually call OPENVC.
SOF.VC: SKIPN .SBCLC(P4) ;Any locked connection blocks?
IFSKP.
SETONE SBFOVC,(P4) ;Yes. Indicate waiting to open
ELSE.
BLCAL. (OPENVC,<P4>) ;No. Open it now
ENDIF.
RETSKP
ENDBS.
;SC.FN1 - finish work of SC.ERR when c.b. is unlocked
;Accepts:
; P1/ address of connection block
; CALL SC.FN1
;Returns +1: always
SC.FN1:
SETZRO CBFERR,(P1) ;Clear indication that this was deferred
LOAD T2,CBCNST,(P1) ;Get current state
MOVEI T1,.CSCLO ;New state will be "closed"
STOR T1,CBCNST,(P1) ;Store as new connect state
CAIN T2,.CSCLO ;Was it already closed?
IFSKP.
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,(P) ;Get PC of caller to feature routine
MOVEI T3,.SSPBC ;Get callback notification code
CALL RG.SCS ;(T1,T2,T3,P1) Record callback event
> ;End of IFN SCARNG
LOAD T1,CBSCID,(P1) ;Get the local connect ID
CALL SC.NOD ;(T1/T1,T2) Get node number
MOVEM T2,T3 ;Reposition node number for callback
MOVEM T1,T2 ;Reposition CID for callback
MOVEI T1,.SSPBC ;Port broke connection
CIOFF ;Sysap wants no interrupts
CALL @.CBADR(P1) ;Notify the SYSAP of the disaster
CION
ENDIF.
CALL SC.PTC ;(P1/) Indicate protocol is complete
RET
SUBTTL Call from port driver -- SC.DMA (DMA operation complete)
; Here when the port noticed that a DMA operation has completed and we
;need to notify the guilty party...
;
; Call
; T1/ 32 bit buffer name of completed transfer
; T2/ CID
; P4/ address of system block
;
; Return (+1)
; No data returned, no failure return...
;
SC.DMA::SAVEAC <P1,P2,P3>
DMOVEM T1,P2
LOAD T3,SBVCST,(P4) ;Don't do anything if the v.c.
CAIE T3,VC.OPN ; is already closed
RET
MOVE T1,T2 ;Get CID
CALL SC.CSC ;(T1/T1,P1) Is it valid?
RET
LOAD T3,CBCNST,(P1) ;See if connection is open
CAIE T3,.CSOPN
RET ;No. Ignore it
AOS .CBSCD(P1) ;Give back the credit we took at the start
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,-4(P) ;Get PC of caller to feature routine
MOVEI T3,.SSDMA ;Get callback notification code
CALL RG.SCS ;(T1,T2,T3,P1) Record callback event
> ;End of IFN SCARNG
MOVE T3,P2 ;Put the name where promised
MOVX T1,.SSDMA ;Say why we care calling
MOVE T2,P3 ;Get CID
CALL @.CBADR(P1) ;Notify SYSAP of his DMA complete
;We've just incremented send credit. If the sysap had been told "not
;enough credit" on a previous attempt at sending, we need to tell it to
;try again.
TMNN CBFNNC,(P1) ;Does sysap need notification?
RET ;Nope, return now
SETZRO CBFNNC,(P1) ;Show notification complete, zero flag in CB
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,-4(P) ;Get PC of caller to feature routine
MOVEI T3,.SSCIA ;Get callback notification code
CALL RG.SCS ;(T1,T2,T3,P1) Record callback event
> ;End of IFN SCARNG
MOVX T1,.SSCIA ;Say why we are calling, we have credit for you
LOAD T2,CBSCID,(P1) ;Indicate which connection this for
MOVE T3,.CBSCD(P1) ;Show the send credit
MOVE T4,.CBRCD(P1) ;Receive credit
CALL @.CBADR(P1) ;Leap into the SYSAP
RET ;All done
SUBTTL Call from port driver -- Incoming buffer -- SC.INT (Buffer arrival)
; We get here when the port driver has a message the it has deceided SCA needs
;to see. The various types that make their way thourgh here are:
; 1. Application datagrams (Get passed to SYSAP)
; 2. Application messages (Get passed to SYSAP)
; 3. SCA control messages (Get eaten by SCA routines)
;
; First things the we have to do is figure out which message type we have.
;Having divined this we can do what each type requires. A datagram or message
;get passed on to the SYSAP that gets it. I.E. set up the ACs as they were
;promised (See SCAPAR) and call the address in the CB. If the message
;is an SCA control message, then dispatch to the correct routine based on
;message type. A dispatch table is provided that one merely indexes into
;by message type.
;
; Usage:
; Call
; P2/ Address of message/datagram/SCA buffer
; P4/ Address of system block
;
;
; Return +1: Always
;
SC.INT::BLSUB. (<SS.FLG,SS.LEN>)
SAVEP ;Save the ACs we kill here...
CALL SC.RIN ;Byte swap the SCA header of the packet
IFN SCARNG,<
SCINT: XMOVEI T1,. ;Get feature routine address
MOVE T2,-1(P6) ;Get caller to feature routine
MOVE T3,SS.FLG ;Get flags
HRRZ T4,SS.LEN ; and get packet length (no priority)
CALL RG.PKT ;(T1,T2,T3,T4,P2,P4) Record packet transmission
> ;End of IFN SCARNG
MOVE T2,SS.FLG ;Get the arg flags
TXNN T2,F.RSP ;Is this a local or remote packet
JRST SIN.RP ;A remote packet, dispatch to a handler
;Buffer is being returned after a send. Return it to the pool or give it
;to the sysap.
LOAD T3,MH$MSG,(P2) ;Get the packet type
CAIE T3,.STADG ;Is this a datagram??
CAIN T3,.STAMG ; or an application message
JRST SIN.MS ;Handle the return of a SYSAP buffer
;Buffer had been sent by SCA. This should happen only on error.
; * * * *
;This shouldn't happen at all. We need a BUGCHK here
; * * * *
MOVE T1,P2 ;Get the buffer address
CALL SC.RBF ;Return the buffer to the SCA free pool
RET ;Return...
; Here to return a locally generated SYSAP message buffer to its owner.
;NOTE: SC.RAP won't reap a connection until CBNPO is zero. If this is ever
;changed, the following code could cause a problem. The LDCID might produce
;a zero because the connection block may have gone away.
SIN.MS: LOAD T3,MH$SCI,(P2) ;Get the source connect ID from the packet
$LDCID P1,T3 ;Get the CB address from the CID
IFN SCADBG,<
LOAD T1,CBNPO,(P1) ;Get outstanding packet count
SKIPG T1 ;Is it greater than zero?
BUG. (HLT,SCANP3,SCAMPI,SOFT,<SCA - CBNPO about to go negative>,,<
Cause: We are about to decrement the count of queued buffers, but the
count is already zero or less.
>)
> ;END OF IFN SCADBG
DECR CBNPO,(P1) ;Decrement the count of outstanding packets
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,-1(P6) ;Get PC of caller to feature routine
MOVEI T3,.SSMSC ;Get callback notification code
CALL RG.SCS ;(T1,T2,T3,P1) Record callback event
> ;End of IFN SCARNG
MOVEI T1,.SSMSC ;Tell the SYSAP why we are calling
LOAD T2,MH$SCI,(P2) ;Indicate which connection
MOVE T3,P2 ;Setup the address of the buffer
CALL @.CBADR(P1) ;Call the SYSAP about his buffer
RET ;And return to the port driver
; Here to dispatch to a routine that will handle a remotely generated packet.
;
SIN.RP: MOVE T1,TODCLK ;Get current time of day
MOVEM T1,.SBTIM(P4) ;Store time we got this message
SETZRO SBFTMG,(P4) ;Zero the flag in the system block
MOVE T1,SS.FLG ;Make the flags available to handler routines
MOVE T2,SS.LEN ;Get the length from the PPD args
LOAD T3,MH$MSG,(P2) ;Get the message type
CAILE T3,.STLST ;Is the packet type within range???
JRST SIN.ER ;NO!! Handle remote SCA brain damage
AOS RECTAB(T3) ;Count the message we just received
JRST @DSPTAB(T3) ;Yes it is, goto the handling routine
; Here when we have a bad message type from the remote SCA. Since this could
;very well have been a message we must close the VC.
;Note that we don't know what kind of buffer we have, so we just throw
;it away.
SIN.ER: LOAD T1,SBDPA,(P4) ;Get node number
LOAD T2,CBSCID,(P1) ;Get connect ID
BUG. (CHK,SCABMT,SCAMPI,SOFT,<SCA - Bad message type from remote node>,<<T1,NODE>,<T2,CID>,<T3,OPCODE>>,<
Cause: On range checking the message type we found it was bad. This shouldn't
happen if the port and port driver are working correctly. Since we
don't know what kind of packet this is, we throw it away.
Data: NODE - node number
CID - Connect ID
OPCODE - SCS op code received
>)
CALL SC.CVC ;(P4/) Close the v.c.
RET ;All done here for now, return
ENDBS.
; Note: All message handlers assume that they have been called by SC.INT.
;Hence they assume that a SAVEP was done at that level and another is not
;necessary.
;They also assume they're at interrupt level (i.e., not interruptible),
;that v.c. is open (SC.INC checks it), that SC.RSP will fail only if the v.c.
;is closed. Note that this means there's currently no way for SC.RSP to fail,
;since we never try to send a response if the v.c. was found to be closed
;at SC.INC. In the future, we might try for some reason. If so, we may want
;to have PHYKLP check for closed v.c.
;THe order of events in these routines is deliberately as follows:
; Copy input from packet
; Send response
; Update the state
; Tell the sysap
;This allows us to be sure that the state won't be updated if sending the
;response mysteriously fails.
SUBTTL Call from port driver -- Incoming buffer -- SC.ORQ (Connect request)
; This routine handle the reception of connection requests.
;
; Call
; P2/ Addr of datagram
;
; Return +1: Always
;
SC.ORQ: CALL SC.INC ;(P2/T1,T2,P1) Just do check on v.c. closed
JRST SC.RIB ;Ignore this packet
CALL SC.SCM ;(P2/P1,P4) Search for a connection match
JRST SOR.NM ;No match, say so...
;Copy data from the packet into the connect block
LOAD T2,MH$CDT,(P2) ;Get the credit from the message header
MOVEM T2,.CBSCD(P1) ;Store it as the credit (since previous MBZ)
LOAD T2,MH$SCI,(P2) ;Get the remotes connect ID
STOR T2,CBDCID,(P1) ;Store in the CB
LOAD T2,MH$MCR,(P2) ;Get the minimum credit from mess header
STOR T2,CBMNRC,(P1) ;Store it as the minimum receive credit
MOVEI T2,<C%PNMN+3>/4 ;Number of words to move
XMOVEI T3,.MGSPN(P2) ;Source address
XMOVEI T4,.CBDPN(P1) ;Destination address
EXTEND T2,[XBLT] ;Move the destination process name
MOVEI T2,<C%SDTL+3>/4 ;Number of words to move
XMOVEI T3,.MGSDT(P2) ;Source address for connection data
XMOVEI T4,.CBDTA(P1) ;Destination address
EXTEND T2,[XBLT] ;Move the connection data
;Build and send a match CONNECT_RESPONSE.
MOVEI T4,.CMCMT ;Get the "match" status
STOR T4,MH$STS,(P2) ;Put the status info into the message header
MOVEI T1,.STORS ;Get the CONNECT_RESPONSE message type code
CALL SC.RSP ;(T1,P1,P2,P4/)Send the response
JRST SC.RIB ;Failed. Return the buffer to the free queue
;..
;Update connection state to connect_received
;..
MOVEI T2,.CSCRE ;Get the CONNECT_RECEIVED circuit state
STOR T2,CBCNST,(P1) ;Put it up in the connection block
;Notify the SYSAP that someone has connected to its listener.
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,(P) ;Get PC of caller to feature routine
MOVEI T3,.SSCTL ;Get callback notification code
CALL RG.SCS ;(T1,T2,T3,P1) Record callback event
> ;End of IFN SCARNG
MOVEI T1,.SSCTL ;Tell the reason for the SYSAP call
LOAD T2,CBSCID,(P1) ;Tell who was connected to
XMOVEI T3,.CBDTA(P1) ;Point to the remote connection data
CALL @.CBADR(P1) ;Make the trusting leap into oblivion
RET ;Return to the port driver, all went well
;Build and send a no match CONNECT_RESPONSE. Can't use standard routines
;because we want to zero the source connect ID
SOR.NM: SETZRO MH$CDT,(P2) ;Zero the credit field of the message header
MOVEI T1,.STORS ;Get op code for CONNECT_RSP
STOR T1,MH$MSG,(P2) ;Store op code
LOAD T2,MH$SCI,(P2) ;Get the sending CID
STOR T2,MH$DCI,(P2) ;Store as the receiving CID
SETZRO MH$SCI,(P2) ;Send our ID as zero since we have no connect
MOVEI T4,.CMCNM ;Say we found no connection match
STOR T4,MH$STS,(P2) ;Put the status info into the message header
SETZRO MH$MCR,(P2) ;Zero minimum_credit field for safety
CALL SC.PAK ;(P2,P4/)Send the response
JRST SC.RIB ;Failed. Return the buffer to the free queue
RET ;Else return now, no one to notify
SUBTTL Call from port driver -- Incoming buffer -- SC.ORS (Connect response)
; Here we handle connect responses.
;
; Call
; P2/ Addr of message
; P4/ Addr of system block
;
; Return +1: Always
;
SC.ORS: CALL SC.INC ;(P2/T1,T2,P1) Check validity, get state & op code
JRST SC.RIB ;Return the buffer and quit
MOVEM T1,P3 ;Save new state
;If state was closed, our end disconnected after requesting connection
;Don't need to update state. If other side said "match", wait for the
;accept or reject to come in. If it said "no match", we're finished.
LOAD T2,CBCNST,(P1) ;Get old state
LOAD T3,MH$STS,(P2) ;Get match/no match code
CAIE T2,.CSCLO ;Was it closed already?
IFSKP.
CAIE T3,.CMCMT ;It was closed. Is this a match?
CALL SC.PTC ;No. End of protocol, then
;Here when state wasn't closed. This is the normal case. If the other
;side said "no match", tell the sysap that the connection failed, and
;mark protocol complete. Otherwise, update the state and wait for
;the accept or reject.
ELSE.
CAIE T3,.CMCMT ;Not closed. Is this a match?
IFSKP.
LOAD T2,MH$SCI,(P2) ;Get source connect ID from packet
STOR T2,CBDCID,(P1) ;Store as destination ID
STOR T1,CBCNST,(P1) ;Store the new connection state
ELSE.
MOVEI T1,.CSCLO ;No match, new connect state is closed
STOR T1,CBCNST,(P1) ;Store the new connect state
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,(P) ;Get PC of caller to feature routine
MOVEI T3,.SSCRA ;Get callback notification code
CALL RG.SCS ;(T1,T2,T3,P1) Record callback event
> ;End of IFN SCARNG
MOVEI T1,.SSCRA ;Say why we are calling the SYSAP
LOAD T2,CBSCID,(P1) ;Get the connect ID
SETZ T3, ;Say we were rejected
LOAD T4,MH$STS,(P2) ;Get reason code for rejection
CALL @.CBADR(P1) ;Call the SYSAP
CALL SC.PTC ;(P1/) Declare protocol complete
ENDIF.
ENDIF.
JRST SC.SAR ;Go send next SCS control message, return buffer
SUBTTL Call from port driver -- Incoming buffer -- SC.ARQ (Accept request)
; Here to handle an ACCEPT_REQUEST.
;
; Call
; P2/ Address of message buffer
; P4/ Address of system block
;
; Return +1: Always
;
SC.ARQ: CALL SC.INC ;(P2/T1,T2,P1) Check validity, get state & op code
JRST SC.RIB ;Return the buffer and quit
MOVEM T1,P5 ;Save new state
MOVEM T2,P3 ;Save op code of response
;If the connection is currently closed, then the sysap changed its mind after
;sending a connect_request.
LOAD T3,CBCNST,(P1) ;If current state is closed, we want
CAIN T3,.CSCLO ; to send an accept-response with
JRST SAR.NG ; "no match"
;Copy data from the packet into the connect block
;* * * *
;NOTE: We've added the next two lines in order to talk to VMS.
;The connect ID that they send us with the connect_response isn't useful.
;For now, the copy remains in SC.ORS in case there's something wrong with
;this approach.
LOAD T2,MH$SCI,(P2) ;Get source connect ID from packet
STOR T2,CBDCID,(P1) ;Store as destination ID
; * * * *
LOAD T2,MH$CDT,(P2) ;Get the credit field from the message header
ADDM T2,.CBSCD(P1) ;Calculate and store the new send credit
LOAD T2,MH$MCR,(P2) ;Get the min credit out of the message header
STOR T2,CBMNRC,(P1) ;Store it in the CB as the min send credit
MOVEI T2,<C%SDTL+3>/4 ;Number of words to move
XMOVEI T3,.MGSDT(P2) ;Source address of connection data
XMOVEI T4,.CBDTA(P1) ;Destination address for connect data
EXTEND T2,[XBLT] ;Move the connection data
;Build and send the ACCEPT_RESPONSE message.
MOVX T4,.CMCMT ;Get the universal MATCH code
STOR T4,MH$STS,(P2) ;Put the status info into the message header
MOVE T1,P3 ;Get the op code
CALL SC.RSP ;(T1,P1,P2,P4/)Send the response
JRST SC.RIB ;Failed. Return the buffer to the free queue
;Set new state
STOR P5,CBCNST,(P1) ;Store connection state returned above
;..
;Notify the SYSAP about what has happened.
;..
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,(P) ;Get PC of caller to feature routine
MOVEI T3,.SSCRA ;Get callback notification code
CALL RG.SCS ;(T1,T2,T3,P1) Record callback event
> ;End of IFN SCARNG
MOVEI T1,.SSCRA ;Say why we are calling
LOAD T2,CBSCID,(P1) ;Say for whom we are calling
SETO T3, ;Indicate accepted connection request
XMOVEI T4,.CBDTA(P1) ;Build a pointer to the connection data
CALL @.CBADR(P1) ;L E A P . . . . .
RET ;And return...
;Send accept_response "no match" because our side disconnected.
;State is already closed; no need to change it.
SAR.NG: MOVE T1,P3 ;Get op code for ACCEPT_RSP
LOAD T2,CBSDRE,(P1) ;Get sysap's reason for disconnecting
STOR T2,MH$STS,(P2) ;Store as the status
CALL SC.RSP ;(T1,P1,P2,P4/)Send the response
JRST SC.RIB ;Failed. Return the buffer to the free queue
CALL SC.PTC ;(P1/) Declare protocol complete
RET
SUBTTL Call from port driver -- Incoming buffer -- SC.ARS (Accept response)
; Here to handle an ACCEPT_RESPONSE.
;
; Call
; P2/ Address of message buffer
; P4/ Address of system block
;
; Return +1: Always
;
SC.ARS: CALL SC.INC ;(P2/T1,T2,P1) Check validity, get state & op code
JRST SC.RIB ;Return the buffer and quit
LOAD T2,CBCNST,(P1) ;Get old state
LOAD T3,MH$STS,(P2) ;Get the status word from the message
CAIE T2,.CSCLO ;Was it closed?
IFSKP.
CAIE T3,.CMCMT ;Is the status MATCH?
IFSKP.
MOVEI T1,.BSDPN ;New block state is disconnect_pending
CALL SC.SCA ;(T1,P1,P4/) Set block state and queue message
ELSE.
CALL SC.PTC ;No match. We've finished with this c.b.
ENDIF.
;Here when state was not closed. This is the normal case
;If match, tell sysap it's OK to send data. if no match, the other side
;changed its mind. Tell the sysap and declare protocol complete.
ELSE.
CAIE T3,.CMCMT ;Match?
IFSKP.
STOR T1,CBCNST,(P1) ;Store the new connection state
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,(P) ;Get PC of caller to feature routine
MOVEI T3,.SSOSD ;Get callback notification code
CALL RG.SCS ;(T1,T2,T3,P1) Record callback event
> ;End of IFN SCARNG
MOVEI T1,.SSOSD ;Say why we are calling
LOAD T2,CBSCID,(P1) ;Provide local CID
CALL @.CBADR(P1) ;Make the leap of faith into the SYSAP
ELSE.
MOVEI T1,.CSCLO ;Get the closed state
STOR T1,CBCNST,(P1) ;Store as the new connection state
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,(P) ;Get PC of caller to feature routine
MOVEI T3,.SSRID ;Get callback notification code
CALL RG.SCS ;(T1,T2,T3,P1) Record callback event
> ;End of IFN SCARNG
MOVEI T1,.SSRID ;Say the remote has changed its mind
LOAD T2,CBSCID,(P1) ;Show who locally
CALL @.CBADR(P1) ;Tell the SYSAP about the change of mind
CALL SC.PTC ;(P1/) Declare protocol complete
ENDIF.
ENDIF.
JRST SC.SAR ;Go send next SCS control message, return buffer
SUBTTL Call from port driver -- Incoming buffer -- SC.RRQ (Reject request)
; Here for REJECT_REQUEST received.
;
; Call
; P2/ Address of message buffer
; P4/ Address of system block
;
; Return +1: Always
;
SC.RRQ: CALL SC.INC ;(P2/T1,T2,P1) Check validity, get state & op code
JRST SC.RIB ;Return the buffer and quit
MOVEM T1,P5 ;Save new state
;Get reason for rejection from the packet, and store it in the connect block
LOAD T3,MH$STS,(P2) ;Find out why we were rejected
STOR T3,CBDDRE,(P1) ;Store as his reason for saying "NO."
;Now build the response in the buffer we have from the REJECT_REQUEST.
MOVE T1,T2 ;Get op code returned above
CALL SC.RSP ;(T1,P1,P2,P4/)Send the response
JRST SC.RIB ;Failed. Return the buffer to the free queue
;Now poke the SYSAP with its response to our connect.
;If state was already closed, don't change it. Sysap isn't interested
;in hearing about this.
LOAD T1,CBCNST,(P1) ;Get old connection state
CAIN T1,.CSCLO ;If closed, sysap isn't interested.
IFSKP.
STOR P5,CBCNST,(P1) ;Store the new connection state
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,(P) ;Get PC of caller to feature routine
MOVEI T3,.SSCRA ;Get callback notification code
CALL RG.SCS ;(T1,T2,T3,P1) Record callback event
> ;End of IFN SCARNG
MOVEI T1,.SSCRA ;Tell the SYSAP why we are calling
LOAD T2,CBSCID,(P1) ;Get the connect ID
SETZ T3, ;Indicate that the connection was rejected
LOAD T4,CBDDRE,(P1) ;T4/ reason for rejection
CALL @.CBADR(P1) ;Call the SYSAP
ENDIF.
CALL SC.PTC ;(P1/) Declare protocol complete
RET
SUBTTL Call from port driver -- Incoming buffer -- SC.RRS (Reject response)
; Here to handle REJECT_RESPONSE messages.
;
; Call
; P2/ Address of message buffer
; P4/ Address of system block
;
; Return +1: Always
;
SC.RRS: CALL SC.INC ;(P2/T1,T2,P1) Check validity, get state & op code
JRST SC.RIB ;Return the buffer and quit
;Set new state
STOR T1,CBCNST,(P1) ;Set connection block state as returned above
CALL SC.PTC ;Declare protocol complete
JRST SC.SAR ;Go send next SCS control message, return buffer
SUBTTL Call from port driver -- Incoming buffer -- SC.DRQ (Disconnect request)
; Here for DISCONNECT_REQUESTs.
;
; Call
; P2/ Address of message buffer
; P4/ Address of system block
;
; Return +1: Always
;
;NOTE: This code assumes it's running at interrupt level. If it
;isn't, it must lock the c.b.
SC.DRQ: CALL SC.INC ;(P2/T1,T2,P1) Check validity, get state & op code
JRST SC.RIB ;Return the buffer and quit
MOVEM T1,P3 ;Save new state
;Copy reason for disconnect from packet to connect block
LOAD T3,MH$STS,(P2) ;Get the disconnect reason
STOR T3,CBDDRE,(P1) ;Stash the remote discconect reason in CB
;send a DISC_RSP
MOVE T1,T2 ;Get op code as returned above
CALL SC.RSP ;(T1,P1,P2,P4/)Send the response
JRST SC.RIB ;Failed. Return the buffer to the free queue
;Honor the c.b. lock. If it's locked, set a flag. When the locker unlocks
;the block, this function will be completed.
MOVX T1,CBFDRQ
CALL SC.HNR ;(T1,P1/) See if the c.b. is locked
RET ;Yes. Can't finish this now
;Now store new state as returned above
STOR P3,CBCNST,(P1) ;Store the new connection state
;If the new state is disconnect_received, previous state was open.
;This means the other side initiated the disconnect.
CAIN P3,.CSDRE ;Is the state disconnect received???
JRST SDR.CO ;Yes. Go handle that
;Here when new state is not disconnect_received. If new state is closed,
;protocol is complete. This happens when we initiate the disconnection, and
;the other side responds with a disconnect_request.
CAIN P3,.CSCLO ;Is the new state closed?
CALL SC.PTC ;(P1/) Yes. Indicate protocol is complete
RET
;..
;Here when new state is disconnect_received.
;Corporate spec says the sysap should be required to do a disconnect.
;We fake it by setting the state and sending the message.
;Set the state before calling the sysap. If it does an SC.DIS before returning
;we won't send two disconnect_requests.
SDR.CO: MOVEI T1,.CSDMC ;New connection state is disconnect_match
STOR T1,CBCNST,(P1)
;Tell the sysap that the other side hung up.
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,(P) ;Get PC of caller to feature routine
MOVEI T3,.SSRID ;Get callback notification code
CALL RG.SCS ;(T1,T2,T3,P1) Record callback event
> ;End of IFN SCARNG
MOVX T1,.SSRID ;Get SYSAP notify code for remote disconnect
LOAD T2,CBSCID,(P1) ;Tell the SYSAP which connection went away
LOAD T3,CBDDRE,(P1) ;Return reason from packet status field
CALL @.CBADR(P1) ;Notify sysap of disconnection
;Set block state to disconnect_pend to cause disconnect_request to be
;sent.
MOVEI T1,.BSDPN ;New block state is disconnect_pend
CALL SC.SCA ;(T1,P1,P4/) Set block state and queue message
CALL SC.SNM ;(P4/) Send the message if possible
RET
;SC.FN3 - finish work of SC.DRQ when c.b. is unlocked
;Accepts:
; P1/ address of c.b.
; P4/ address of system block
; CALL SC.FN3
;Returns +1: always
;CIOFF protects from incoming disconnect_response. Ordinarily, it can't
;interfere with incoming disc_req because both are at interrupt level.
;We must be CIOFF for the callback anyway.
SC.FN3:
CIOFF
SETZRO CBFDRQ,(P1) ;Clear indication that this was deferred
MOVEI T1,.STDRQ ;Op code is disconnect_request
IMULI T1,MXCNST ;Compute offset in the table based
OPSTR <ADD T1,>,CBCNST,(P1) ; on op code and current state
SOS T1 ;States start at 1
TMNE K.ERR,(T1) ;We can't handle protocol violation here
BUG. (HLT,SCAFN3,SCAMPI,SOFT,<SCA - Can't complete deferred call to SC.DRQ>,,<
Cause: PHYKLP called SCAMPI at SC.DRQ when the connection block was locked.
At the time, the incoming packet was legal for the current state of
the connection. Now it is not legal. This shouldn't happen, but we
don't know how to proceed. We could close the v.c. and continue, but
we halt in order to analyze the protocol confusion and fix the bug.
>)
LOAD T1,K.STAT,(T1) ;Get new state
STOR T1,CBCNST,(P1) ;Store the new connection state
;If the new state is disconnect_received, previous state was open.
;This means the other side initiated the disconnect.
CAIN T1,.CSDRE ;Is the state disconnect received?
JRST FN3.CO ;Yes. Go handle that
;Here when new state is not disconnect_received. If new state is closed,
;protocol is complete. This happens when we initiate the disconnection, and
;the other side responds with a disconnect_request.
CAIN T1,.CSCLO ;Is the new state closed?
CALL SC.PTC ;(P1/) Yes. Indicate protocol is complete
CION
RET
;Here when new state is disconnect_received.
;Corporate spec says the sysap should be required to do a disconnect.
;We fake it by setting the state and sending the message.
;Set the state before calling the sysap. If it does an SC.DIS before returning
;we won't send two disconnect_requests.
FN3.CO: MOVEI T1,.CSDMC ;New connection state is disconnect_match
STOR T1,CBCNST,(P1)
;Tell the sysap that the other side hung up.
; CIOFF ;Sysap wants us to prevent interrupts
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,(P) ;Get PC of caller to feature routine
MOVEI T3,.SSRID ;Get callback notification code
CALL RG.SCS ;(T1,T2,T3,P1) Record callback event
> ;End of IFN SCARNG
MOVEI T1,.SSRID ;Get SYSAP notify code for remote disconnect
LOAD T2,CBSCID,(P1) ;Tell the SYSAP which connection went away
LOAD T3,CBDDRE,(P1) ;Return reason from packet status field
CALL @.CBADR(P1) ;Notify sysap of disconnection
; CION
;Set block state to disconnect_pend to cause disconnect_request to be
;sent.
MOVEI T1,.BSDPN ;New block state is disconnect_pend
CALL SC.SCA ;(T1,P1,P4/) Set block state and queue message
SETONE CBFSNM,(P1) ;Indicate call to SC.SNM was deferred.
CION
RET
SUBTTL Call from port driver -- Incoming buffer -- SC.DRS (Disconnect response)
; Here for DISCONNECT_RESPONSE
;
; Call
; P2/ Address of message buffer
; P4/ Address of system block
;
; Return +1: Always
;
SC.DRS: CALL SC.INC ;(P2/T1,T2,P1) Check validity, get state & op code
JRST SC.RIB ;Return the buffer and quit
STOR T1,CBCNST,(P1) ;Store the new connect state
;If new state is closed, this is confirmation of our disconnect_request.
;earlier we had received a disconnect_request and sent a disconnect_response
;If not, the other side still needs to send a disconnect_request
CAIN T1,.CSCLO ;Is the next state CLOSED???
CALL SC.PTC ;(P1/) Yes. Declare protocol complete
JRST SC.SAR ;Go send next SCS control message, return buffer
SUBTTL Call from port driver -- Incoming buffer -- SC.CRQ (Credit request)
; Here to receive CREDIT_REQUEST messages...
;
; Call
; P2/ Address of message buffer
; P4/ Address of system block
;
; Return +1: Always
;
SC.CRQ: CALL SC.INC ;(P2/T1,T2,P1) Check validity, get state & op code
JRST SC.RIB ;Return the buffer and quit
MOVEM T2,P5 ;Save op code of response
LOADE T1,MH$CDT,(P2) ;Get the credit field from the message header
JUMPGE T1,SCR.RS ;Taking credit back?
;Here when the other side is withdrawing credit
;Don't allow this if send credit is already below the minimum, and don't
;allow it to go below the minimum
;Spec says
;if PTR^.CREDIT < 0
; then PTR^.CREDIT:=
; -MIN(MAX(0,CB$SEND_CREDIT-CB$MIN_SEND_CREDIT),-PTR^.CREDIT)
;In our terms,
; if .CBSCD < CBMNSC, use 0
; if .CBSCD - CBMNSC .LT. T1, use -(.CBSCD-CBMNSC)
; if .CBSCD - CBMNSC .GE. T1, use T1 as it is
;Implemented in the opposite sense:
; Compute CBMNSC-.CBSCD
; If positive, use 0
; If .GT. T1, use the difference as computed
; If .LE. T1, use T1 as it is
LOAD T2,CBMNSC,(P1) ;Get minimum_send_credit
SUB T2,.CBSCD(P1) ;Compute -(send_credit - minimum_send_credit)
SKIPG T2 ;Already below minimum?
IFSKP.
SETZM T1 ;Yes. Don't reduce at all
ELSE.
CAMLE T2,T1 ;Request too large?
MOVE T1,T2 ;Yes. Reduce only to minimum_send_credit
ENDIF.
;..
;Send the response.
; T1/ credit we decided to accept or give up
;..
SCR.RS: ADDM T1,.CBSCD(P1) ;Add this back into send credit
STOR T1,MH$CDT,(P2) ;Put the credit amount back into the header
EXCH T1,P5 ;Get op code, save credit value
CALL SC.RS2 ;(T1,P1,P2,P4/)Send the response, don't zero credit
IFNSK.
MOVNS P5 ;Get negative of credit
ADDM P5,.CBSCD(P1) ;Restore credit to previous value
JRST SC.RIB ;Return the buffer to the free queue
ENDIF.
;If the sysap has tried to send a message and failed because of lack of
;send credit, we need to notify it that credit has been given to it.
;Note that we must clear the flag BEFORE the call to the sysap, because
;it may try to send more messages, and run the credit down again, before
;returning control. In that case, SC.SMG could set the flag, and then this
;code would clear it.
JUMPLE P5,R ;If not adding to credit, we've finished
LOAD T1,CBCNST,(P1) ;Get current state of the connection.
TMNE CBFNNC,(P1) ;Does sysap need notification?
CAIE T1,.CSOPN ;Yes. Is connection open?
RET ;Nope, return now
SETZRO CBFNNC,(P1) ;Show notification complete, zero flag in CB
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,(P) ;Get PC of caller to feature routine
MOVEI T3,.SSCIA ;Get callback notification code
CALL RG.SCS ;(T1,T2,T3,P1) Record callback event
> ;End of IFN SCARNG
MOVX T1,.SSCIA ;Say why we are calling, we have credit for you
LOAD T2,CBSCID,(P1) ;Indicate which connection this for
MOVE T3,.CBSCD(P1) ;Show the send credit
MOVE T4,.CBRCD(P1) ;Receive credit
CALL @.CBADR(P1) ;Leap into the SYSAP
RET
SUBTTL Call from port driver -- Incoming buffer -- SC.CRS (Credit response)
; Here to receive a CREDIT_RESPONSE.
;
; Call
; P2/ Address of message buffer
; P4/ Address of system block
;
; Return +1: Always
;
;NOTE:
;If credit field is negative, we can take buffers back from the port. If
;that fails, we have a problem. There will be disagreement among 1) our
;receive credit, 2) the other side's send credit, and 3) the number of
;buffers actually queued for this connection. This code attempts to
;keep 1 and 2 in agreement.
SC.CRS: CALL SC.INC ;(P2/T1,T2,P1) Check validity, get state & op code
JRST SC.RIB ;Return the buffer and quit
;Get credit from message, and figure out what is required
LOADE P3,MH$CDT,(P2) ;Get the credit field from the message header
SKIPL .CBRQC(P1) ;Were we trying to get credit back?
IFSKP.
MOVM T2,P3 ;Get the number we were allowed
ADDM T2,.CBRTC(P1) ;Add into return credit.
IFN SCADBG,<
ELSE.
CAMN P3,.CBRQC(P1) ;Do we agree with the other end?
JRST SCC.YY ;Yes. Proceed
LOAD T1,SBDPA,(P4) ;Get node number
LOAD T2,CBSCID,(P1) ;Get connect ID
BUG. (CHK,SCAUCF,SCAMPI,SOFT,<SCA - Unexpected credit field in credit_request>,<<T1,NODE>,<T2,CID>>,<
Cause: The response to a positive credit_request contains a credit value that
is different from what we thought we'd sent.
Data: NODE - Node number
CID - Connect ID
>)
> ;End of IFN SCADBG
ENDIF.
SCC.YY: ADDM P3,.CBRCD(P1) ;Update the receive credit
SCC.XX: SETZM .CBRQC(P1) ;If negative, don't let SC.RCB dequeue
; because they are counted in return_credit
SETZM .CBPND(P1) ;Indicate no credit_request pending
CALL SC.CD1 ;(P1,P4/) Queue credit_request if needed
NOP ;Don't care whether queued or not
CALL SC.GCB ;(P1/) Get canceled buffers, if any
JRST SC.SAR ;Go send the next message
;Common exit for incoming SCS control messages.
;Here when response arrived. This is the packet that is reserved for outgoing
;messages for the system block of interest. Use it to send the next message,
;or queue it to the system block for the next time it wants to send a request.
SC.SAR: MOVEM P2,.SBOBB(P4) ;Queue buffer to system block
CALL SC.SNM ;(P4/)Send next SCS control message
RET
;Here to return buffer to the port. THis happens when the packet arrives
;after the v.c. has already been closed. If it was a request, we can't queue
;it to the system block, because SC.ERR has already run. If we queued it
;now, it would cause a problem when the node came online again, or stay there
;forever if the node never came back.
;Any failing attempt to send a response to a connection management request
;will come here. However, this shouldn't happen because of other checks that
;were made earlier.
;Failure to send a packet will occur only if the v.c. is closed. No attempt
;is made to handle the state of the connection or to notify the sysap when
;this happens, on the assumption that closing the v.c. took care of these things
SC.RIB: SETZM (P2) ;Clear forward pointer in buffer
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,(P) ;Get PC of caller to feature routine
MOVEI T3,1 ;Set buffer count
MOVE T4,P2 ;Get buffer address
TXO T3,RPQFLK ;Set port link flag
TXO T3,RPQFMG ;Set message free queue flag
CALL RG.PQM ;(T1,T2,T3,T4,P4) Record port manipulation
> ;End of IFN SCARNG
BLCAL. (LNKMFQ,<P4,P2>) ;Return buffer to port's free queue
RET
SUBTTL Call from port driver -- Incoming buffer -- SC.INC (Connection management)
;SC.INC - process incoming packet
;Accepts:
; P2/ address of buffer
; P4/ address of system block
; CALL SC.INC
;Returns +1: failure
; +2: success,
; T1/ new state
; T2/ op code of response
; P1/ address of connection block
;Determines new state for connection, and appropriate response, for
;incoming SCS control message
;NOTE: callers to this routine give the buffer back to the port if this
;returns +1, on the assumption that the v.c. has been closed. If this
;routine is changed to handle failure in some other way, changes may be
;necessary in the callers.
SC.INC: SAVEAC <P3>
LOAD T1,SBVCST,(P4) ;If the v.c. is already closed, we aren't
CAIE T1,VC.OPN ; interested in this packet
RET
LOAD P3,MH$MSG,(P2) ;Get the op code
CAIN P3,.STORQ ;Special case for CONNECT_REQ
RETSKP
;See whether we know about this connect ID
LOAD T1,MH$DCI,(P2) ;Get destination connect-ID
CALL SC.CSC ;(T1/T1,P1) Is it valid?
JRST SC.IN6 ;No. Go handle the problem
IFN SCADBG,<
CAME P4,.CBSBA(P1) ;Is address of system block OK
JRST SC.IN4 ;No.
> ;end IFN SCADBG
;See whether this event is expected given the current state
IMULI P3,MXCNST ;Compute offset in the table based
OPSTR <ADD P3,>,CBCNST,(P1) ; on op code and current state
SOS P3 ;States start at 1
JN K.ERR,(P3),SC.IN4 ;If unexpected, go handle the error
TMNN K.CHK,(P3) ;Want to check this response?
IFSKP.
LOAD T3,MH$MSG,(P2) ;Yes. Get op code
OPSTR <CAMN T3,>,CBEXPR,(P1); Is this what we expected?
JRST SC.IN2 ;Yes.
LOAD T1,SBDPA,(P4) ;Get node number
LOAD T2,CBSCID,(P1) ;Get out connect id
LOAD T4,CBEXPR,(P1) ;Get what we expected
BUG. (CHK,SCAUXR,SCAMPI,SOFT,<SCA - Unexpected response>,<<T1,NODE>,<T2,CID>,<T3,OPCODE>,<T4,EXPECT>>,<
Cause: A connection management response arrived for a particular
connection, but the op code is not the one we were expecting.
Action: The v.c. will be closed, on the assumption that the other node
violated protocol. This may correct the confusion. If this error
persists, try to determine the events that led to it. Use the
ring buffer if necessary.
Data: NODE - Node number
CID - Connect ID
OPCODE - Op code of incoming packet
EXPECT - Expected op code for this connection
>)
JRST SC.IN7 ;Go close the v.c.
ENDIF.
;We like this packet. Return success to the caller.
SC.IN2: LOAD T1,K.STAT,(P3) ;It's legal. Get new state
LOAD T2,K.OP,(P3) ; and op code to send
RETSKP ;Success
;Something unexpected happened. Handle the error here and return failure
SC.IN4:
LOAD T1,SBDPA,(P4) ;get node number
LOAD T2,CBSCID,(P1) ;get our connect ID
LOAD T3,MH$MSG,(P2) ;get op code
LOAD T4,CBCNST,(P1) ;get state of connection
BUG. (CHK,SCAPER,SCAMPI,SOFT,<SCA - Protocol error>,<<T1,NODE>,<T2,CID>,<T3,OPCODE>,<T4,STATE>>,<
Cause: An incoming message violated the SCS protocol. That is, for the current
state of a connection, this message is illegal. We close the v.c., which
will eliminate any confusion.
Action: If this persists, change it to a BUGHLT, and determine the sequence of
events that led to it. Use the ring buffer if necessary.
Data: NODE - Node number
CID - Connect ID at this node
OPCODE - Op code of incoming packet
STATE - state of connection
>)
JRST SC.IN7 ;Go close the v.c.
;Here when destination CID doesn't exist. Complain. Note: Can't use common
;BUGCHK because there's no connection block.
SC.IN6:
LOAD T1,SBDPA,(P4) ;Get node number
LOAD T2,MH$DCI,(P2) ;Get destination CID
LOAD T3,MH$MSG,(P2) ;Get op code
BUG. (CHK,SCANOC,SCAMPI,SOFT,<SCA - Received packet and connection block doesn't exist>,<<T1,NODE>,<T2,CID>,<T3,OPCODE>>,<
Cause: An incoming packet's destination CID doesn't match any connection block.
This may reflect disagreement with another node about the state of
a previously-existing connection.
Action: The v.c. will be closed, which will correct the problem.
If this bug persists, try to determine the events that led to it.
Use the ring buffer if necessary.
Data: NODE - Node number
CID - Connect ID
OPCODE - Op code
>)
;..
;Close the v.c. and return failure
;..
SC.IN7: CALL SC.CVC ;(P4/) Close the v.c.
RET ;Return failure
SUBTTL Call from port driver -- Incoming buffer -- SC.ADG/SC.AMG (application datagram/message)
;Accepts:
; T1/ Flags
; T2/ Length (bytes if industry compatible; words if high density)
; P2/ Address of packet
; P4/ Address of system block
; CALL SC.ADG/SC.AMG
;Returns +1: Always
;Caller did SAVEP
SC.ADG:
SC.AMG:
LOAD T3,SBVCST,(P4) ;If the v.c. has already been closed
CAIE T3,VC.OPN ; return the buffer
JRST SAG.RT
;Save flags and packet length
ANDX T1,C%FLGM ;Be sure to keep just the flag bits
MOVEM T1,P3 ;Save flags
MOVEM T2,P5 ;Save length
;Check for error cases -- invalid CID or invalid state
LOAD T1,MH$DCI,(P2) ;Get destination connect ID from packet
CALL SC.CSC ;(T1/T1,P1) Check if this connect ID is OK
JRST SAG.CL ;No. Close the v.c.
LOAD T1,CBCNST,(P1) ;Get the connection state
CAIN T1,.CSOPN ;Is the connect state open?
JRST SAG.OK ;Yup, allow this to happen
CAIE T1,.CSDAK ;Are we in the middle of sending
CAIN T1,.CSDSE ; or receiving a disconnect?
JRST SAG.RT ;Yes. It's OK. Return the buffer
JRST SAG.CL ;No. We shouldn't be getting this packet now
;Here when we are happy to receive this packet
SAG.OK: STOR P5,MH$PKL,(P2) ;Store packet length where sysap expects it
LOAD T2,MH$DCI,(P2) ;Sysap wants destination connect ID
MOVE T3,P2 ;Sysap wants address of packet
LOAD P5,MH$MSG,(P2) ;Which kind of packet was this?
CAIE P5,.STAMG ;Message?
IFSKP.
SOS .CBRCD(P1) ;Yes. Decrease receive credit
LOAD T1,MH$CDT,(P2) ;Get credit from packet
ADDM T1,.CBSCD(P1) ; and increase send credit by this amount
MOVEM T1,P2 ;* * *Note: P2 no longer points to buffer
MOVEI T1,.SSMGR ;Get reason code for sysap
XMOVEI T4,SC.RBF ;Address of buffer-returning routine
ELSE.
SOSGE .CBDGR(P1) ;Datagram. Do we have a buffer queued?
JRST SAG.DD ;NO. Have to drop this datagram
MOVEI T1,.SSDGR ;Get reason code for sysap
XMOVEI T4,SC.RLD ;Address of buffer-returning routine
ENDIF.
IOR T4,P3 ;Combine with flags
IFN SCARNG,<
BLOCK.
SAVEAC <T1,T2,T3> ;Save smashed ACs
MOVE T3,T1 ;Get callback notification code
XMOVEI T1,. ;Get feature routine address
MOVE T2,-5(P) ;Get PC of caller to feature routine
CALL RG.SCS ;(T1,T2,T3,P1) Record callback event
ENDBK.
> ;End of IFN SCARNG
CALL @.CBADR(P1) ;Give the packet to the sysap
CAIE P5,.STAMG ;Was this a message?
RET ;No. We've finished, then.
;This was a message.
;If the remote sysap increased our send credit, and our sysap needs
;to be told, tell it now.
TMNE CBFNNC,(P1) ;Sysap waiting for credit?
SKIPN P2 ;Yes. Did we get any?
JRST SAG.XX ;No. Don't notify, then
SETZRO CBFNNC,(P1) ;Indicate sysap no longer waiting
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,(P) ;Get PC of caller to feature routine
MOVEI T3,.SSCIA ;Get callback notification code
CALL RG.SCS ;(T1,T2,T3,P1) Record callback event
> ;End of IFN SCARNG
MOVEI T1,.SSCIA ;Credit is available
LOAD T2,CBSCID,(P1) ;Connect ID
MOVE T3,.CBSCD(P1) ;Send credit
MOVE T4,.CBRCD(P1) ;Receive credit
CALL @.CBADR(P1)
;If this pushed our receive credit under the minimum, notify the
;sysap that little credit is left.
SAG.XX: MOVE T1,.CBPRC(P1) ;Get the pending receive credit
MOVE T2,.CBRCD(P1) ; and the receive credit
ADD T1,T2 ;Get the sum of the two
LOAD T2,CBMNRC,(P1) ;Get the minimum receive credit
SUB T1,T2 ;Differenec between threshold and what we have
SKIPLE T1 ;Is there more left???
RET ;Yes return now...
MOVM T3,T1 ;Get the positive number of buffers to get
AOS T3 ;Increment just have an extra around
IFN SCARNG,<
BLOCK.
SAVEAC <T3> ;Save smashed ACs
XMOVEI T1,. ;Get feature routine address
MOVE T2,-3(P) ;Get PC of caller to feature routine
MOVEI T3,.SSLCL ;Get callback notification code
CALL RG.SCS ;(T1,T2,T3,P1) Record callback event
ENDBK.
> ;End of IFN SCARNG
MOVX T1,.SSLCL ;Get the reason for our call
LOAD T2,CBSCID,(P1) ;Get our connect ID
CALL @.CBADR(P1) ;Call the SYSAP
RET ;And return.
;Have to drop this datagram.
SAG.DD:
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,(P) ;Get PC of caller to feature routine
MOVEI T3,.SSDDG ;Get callback notification code
CALL RG.SCS ;(T1,T2,T3,P1) Record callback event
> ;End of IFN SCARNG
MOVEI T1,.SSDDG ;Get callback reason code
LOAD T2,MH$DCI,(P2) ;Sysap wants destination connect ID
CALL @.CBADR(P1) ;Call the SYSAP
INCR CBCDD,(P1) ;Count a dropped datagram
AOS .CBDGR(P1) ;Restore the count that we decremented
JRST SAG.RT ;Go return the buffer
;Here when the packet shouldn't have come. Close the v.c.
SAG.CL: CALL SC.CVC ;(P4/) Close the v.c.
;Return the buffer to the port.
;* * * *
;Might be better to adjust the count in the connection block and return
;the buffer to SCA. WOuld have to do this only when the c.b. still exists.
; * * * *
SAG.RT: SETZM (P2) ;Clear FLINK word in buffer
LOAD T1,MH$MSG,(P2) ;Get op code
CAIE T1,.STAMG ;Message?
IFSKP.
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,(P) ;Get PC of caller to feature routine
MOVEI T3,1 ;Set buffer count
MOVE T4,P2 ;Get buffer address
TXO T3,RPQFLK ;Set port link flag
TXO T3,RPQFMG ;Set message free queue flag
CALL RG.PQM ;(T1,T2,T3,T4,P4) Record port manipulation
> ;End of IFN SCARNG
BLCAL. (LNKMFQ,<P4,P2>) ;Yes. Return buffer to port
ELSE.
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,(P) ;Get PC of caller to feature routine
MOVEI T3,1 ;Set buffer count
MOVE T4,P2 ;Get buffer address
TXO T3,RPQFLK ;Set port link flag
TXZ T3,RPQFMG ;Clear message free queue flag since datagram
CALL RG.PQM ;(T1,T2,T3,T4,P4) Record port manipulation
> ;End of IFN SCARNG
BLCAL. (LNKDFQ,<P4,P2>) ;No. Return datagram buffer
ENDIF.
RET
SUBTTL Periodic functions
SUBTTL Periodic functions -- SC.CLK (Dispatch)
;This routine is called by the scheduler at CLK2.
;For debugging, it is useful to patch out the call to SC.IDL.
;
; Usage:
; Call
; No arguments
;
; Return (+1) Always
; No arguments returned
;
; * * * Seems to be called before initialization takes place. Should
;check that
; * * *
SC.CLK::CALL SC.IDL ;Do idle chatter
RET ;All done
SUBTTL Periodic functions -- SC.IDL (Idle chatter)
; This routine handles idle chatter.
; If a remote has not sent us a packet lately we will send it a credit
;request over an open connect. (Hence if there are no open connections then
;there is no idle chatter)
;
; Usage:
; Call
; No arguments
;
; Return (+1) Always
; No data returned
;
SC.IDL: SAVEP ;Save the ACs we will kill here
MOVX T1,C%STIM ;Get the cycle time for the next loop
MOVEM T1,SCATIM ;Reset the timer
AOS T1,TMGSBI ;Get the next SBI we should look at
CAIL T1,C%SBLL ;Have we gone off the end of the list???
SETZB T1,TMGSBI ;Yes, reset to the start of the list
SKIPN P4,SBLIST(T1) ;Is there an SB here???
RET ;No, all done
LOAD T1,SBVCST,(P4) ;Get the port to port virtual circuit state
CAIE T1,VC.OPN ;If it's not open,
RET ; punt on this SB
SKIPN .SBFCB(P4) ;Are there any connections on this SB???
RET ;No, we have nothing to do this time around
SKIPN T1,.SBTIM(P4) ;Has this node ever spoken to us???
RET ;No, ignore it
SUB T1,TODCLK ;Yes, build long ago that was
CAMLE T1,TMGTIM ;Has it been too long???
RET ;No, return
;It's been a while since we heard from this node. If we already sent a
;timed message the last time we came through here, give up on it and close
;the v.c. Otherwise, go send a timed message.
TMNN SBFTMG,(P4) ;Has a timed message been sent on this SB???
JRST SCL.LP ;No.
AOS TMGCNT ;Yes, count another system biting the dust
LOAD T2,SBDPA,(P4) ;Get remote node number
BUG. (CHK,SCATMO,SCAMPI,SOFT,<SCA - SCA timed out remote node>,<<T2,NODE>,<T1,TIME>>,<
Cause: SCA sent a message to another node, and did not receive a response
within a timeout period.
Action: This happens legitimately if a node crashes. If this timeout
is occurring for nodes that appear to be running, try to determine
why they are not communicating.
Data: NODE - Node number
TIME - time since we sent timed message
>)
CALL SC.CVC ;(P4/) Close the v.c.
RET ; and we are all done with this SB
;Find a connection on this system block that is fully open
;If node goes offline while we're doing this, all attempts at sending
;will fail because connection state will be closed for each c.b.,
;and v.c. will be closed
;NOSKED is sufficient to protect the list of connection blocks, because
;the reaper runs in process context.
SCL.LP:
NOSKED ;Prevent reaper from removing entries
;The following check needs some verification. However, it seems that if
;the buffer is in use, there's no need to send another message for timing
;purposes, because a message was just sent.
; SKIPN .SBOBB(P4) ;Is the buffer in use now?
; JRST SCL.EX ;Yes. Don't need to send another message, then
SKIPN P1,.SBFCB(P4) ;Get addr of first CB
JRST SCL.EX ;All CB's are gone, all done with this SB
;Try this connection block. If the connection state is OK, we'll send it
;a credit_request
SCL.TC: CALL SC.LOK ;(P1/) Lock the connection block
SETOM P3 ;Assume we'll need to send something
CALL SC.CD7 ;(P1,P4/) Queue credit request if possible
SETZM P3 ;Don't need to send a message
CALL SC.ULK ;(P1/) Unlock the connection block
SKIPN P3 ;Can we send the credit_request?
JRST SCL.NC ;No. Try another one
;We sent a credit_request to this node
CALL SC.SNM ;(P4/) Send next message
SETONE SBFTMG,(P4) ;Light the timed message sent flag
JRST SCL.EX
;Step to next connection block on this system block
SCL.NC: SKIPE P1,.CBANB(P1) ;Is there a next connection?
JRST SCL.TC ;Try it
SCL.EX: OKSKED
RET
SUBTTL Periodic functions -- SC.RAP (Reap old connections)
; This routine is called by job 0. We don't need
;to be nearly that prompt so we only do anything real every 15 seconds.
;When we do go off, loop over the total set of connections known to SCA and
;reap connection blocks that have the reap bit lit. Also, light the reap bit
;for connections with the abort bit lit.
;
; Call
; No arguments
;
; Return (+1) Always
; No data returned
;
;
;This routine assumes that it is the only deleter of connection blocks.
;In particular, it assumes that no block in the chain can be deleted by
;some other process while it is searching through the chain.
SC.RAP::MOVE T1,TODCLK ;Get the current uptime
CAMGE T1,RAPTIM ;Is it time to do my function again???
RET ;No, return until job 0 is next called
ADD T1,RAPINC ;Add the increment to get next reap time
MOVEM T1,RAPTIM ;Store for later generations
SAVEAC <P1,Q1,P5>
;Loop through all the system blocks
SETO Q1, ;Fudge so we start with the zero'th SB
SRA.NS: AOS Q1 ;Move on to the next system block
CAILE Q1,C%SBLL-1 ;Have we run off the end of the list???
JRST SRA.DC ;Yes, go do the dont care list
SKIPN T2,SBLIST(Q1) ;Is there an entry here???
JRST SRA.NS ;No, try the next system block
;Loop through all connection blocks for this system block
SKIPN P1,.SBFCB(T2) ;Is there a first CB???
JRST SRA.NS ;No, try the next system block
;..
;We're interested in this block only if it's reapable.
;This is indicated by the "reap" bit. If we are debugging, we'll make some
;sanity checks first. The sysap may have queued a buffer for output after
;the reap bit was set. If one or more buffers is still outstanding,
;we will wait a while.
;..
SRA.CC: MOVE P5,.CBANB(P1) ;Save the address of the next CB
TMNN CBFRAP,(P1) ;Is it reapable?
JRST SRA.CL ;No. Go check the next one
;Reap bit is set. Make sure we really mean it.
TMNE CBNPO,(P1) ;Are packets still on the command queue?
JRST SRA.PO ;Yes. Wait a while
IFN SCADBG,<
CALL SC.RRR ;(P1/) Is it really ready to reap?
JRST SRA.PO ;No. Postpone it, then
> ;End of IFN SCADBG
;We mean it. Do the job.
CALL SC.RCB ;(P1/) Reap the connect data
JRST SRA.CL ; and go on
;Postpone reaping because something hasn't been cleaned up. But if we do
;this several times, give up and reap anyway.
SRA.PO: INCR CBRCNT,(P1) ;Count another postponement
LOAD T1,CBRCNT,(P1) ;Have we had enough of this?
CAIGE T1,RPMAX
JRST SRA.CL ;Not yet. Go check next block
;Here when we've postponed reaping a number of times, and we're just going to
;do it anyway! The assumption is that the reason for delaying is invalid,
;that some bug is causing the count or FLINK word never to be zeroed.
LOAD T1,CBSCID,(P1) ;Get connect ID
MOVE T2,.CBSBA(P1) ;Get system block address
LOAD T2,SBDPA,(T2) ;Get node number
LOAD T3,CBBKST,(P1) ;BLock state
LOAD T4,CBNPO,(P1) ;Number of queued commands
BUG. (CHK,SCARTO,SCAMPI,SOFT,<SCA - Reap timed out>,<<T2,NODE>,<T1,CID>,<T3,STATE>,<T4,COUNT>>,<
Cause: A block that is reapable cannot be reaped because the count of
outstanding packets is non-zero or a debugging check has failed. After
several postponements, these were not corrected. Now the block is being
deleted.
Action: If COUNT is non-zero, see if the CI-20 was reloaded recently.
Buffers can be lost legitimately when this happens.
Data: NODE - Node number
CID - Connect ID at this node
STATE - Block state
COUNT - Contents of CBNPO (number of queued messages or datagrams)
>)
;* * * *NOTE: FOR NOW, DON't REAP SO WE CAN DEBUG IT!
; CALL SC.RCB ;(P1/) Reap the data
;Here when finished with current c.b. Move on to next one.
SRA.CL: MOVE P1,P5 ;Get the address of the next CB in line
JUMPN P1,SRA.CC ;If there is one, check it for reaping/aborting
JRST SRA.NS ;Else, try for the next SB
; Here when we have finished all regular CB's and are ready to work on the
;don't care queue. Since these are listeners, there should be no reason to
;postpone reaping.
SRA.DC: SKIPN P1,TOPDC ;Are there DC blocks to consider???
RET ;No, return now pls
CIOFF ;Protect against changes in the list
MOVE P1,TOPDC ;Get the top of the list
SRA.DL: SKIPE P1 ;Is this a real entry?
IFSKP.
CION ;No. We've finished
RET
ENDIF.
TMNE CBFRAP,(P1) ;Is this reapable?
IFSKP.
MOVE P1,.CBANB(P1) ;No. Get the next one
JRST SRA.DL ; and continue
ELSE.
CION ;Yes. Allow interrupts while we do it
CALL SC.RCB ;(P1/) Reap this block
JRST SRA.DC ;Go start over since list may have changed
ENDIF.
;SC.RRR - see if we're really ready to reap
;Accepts:
; P1/ address of connection block
; CALL SC.RRR
;Returns +1: not ready
; +2: ready
IFN SCADBG,<
SC.RRR:
LOAD T1,SBDPA,(P4) ;Get node number for optional data
LOAD T2,CBSCID,(P1) ;Get connect ID
;When we set the reap bit, we cleared the block state. If it's not zero now,
;something is wrong.
TMNN CBBKST,(P1) ;Not ready if block state isn't zero
IFSKP.
LOAD T3,CBBKST,(P1) ;Get block state
BUG. (CHK,SCABSN,SCAMPI,SOFT,<SCA - Block state non-zero when ready to reap>,<<T1,NODE>,<T2,CID>,<T3,STATE>>,<
Cause: SCA is ready to delete a connection block, and its block state
is non-zero. The block state should have been cleared when the reap
bit was set.
Data: NODE - Node number
CID - Connect ID
STATE - block state
>)
RET
ENDIF.
;Check requeue credit. If it's non-zero, we must have sent out a credit_request
;to which we expect a reply.
SKIPE T3,.CBRQC(P1) ;Non-zero implies credit_request outstanding
TMNN CBFCVC,(P1) ; but it's bad only if v.c. is open
IFSKP.
BUG. (CHK,SCANRC,SCAMPI,SOFT,<SCA - Non-zero requeue credit at SC.RCB>,<<T1,NODE>,<T2,CID>,<T3,CREDIT>>,<
Cause: SCA is ready to delete a connection block, and its requeue credit is
non-zero. This indicates that a credit_response is still expected.
Data: NODE - Node number
CID - Connect ID
CREDIT - Requeue credit
>)
RET
ENDIF.
;If the lock count is non-zero, some code thinks it still owns the connection
;block.
SKIPN T3,.CBLCK(P1)
IFSKP.
BUG. (CHK,SCANLC,SCAMPI,SOFT,<SCA - Non-zero lock count at SC.RCB>,<<T1,NODE>,<T2,CID>,<T3,COUNT>>,<
Cause: SCA is ready to delete a connection block, and its lock count is
non-zero.
Data: NODE - Node number
CID - Connect ID
COUNT - lock count
>)
RET
ENDIF.
;All's well. We reap.
RETSKP ;Indicate we can reap it.
> ;End of IFN SCADBG
; This routine dealocates a connection block. Simply call it with P1 set up
;to be the connection block address and it will make the block go away...
;
;Usage:
; Call
; P1/ Address of connection block
;
; Return (+1) Always
; No data returned, connection block has been dealocated.
;
SC.RCB::SAVEAC <Q1,P4>
CIOFF ;Allow no other access to CB Q
AOS RCBCNT ;Count another CB biting the dust
MOVE P4,.CBSBA(P1) ;Get the pointer to the system block
JUMPLE P4,SRC.DC ;Was this a dont care CB, if so P4 is -1
CALL SC.RSQ ;(P1/) Remove from system block queue
CION ;Has been take off CB queue, allow access
; Remove CID table entry from CIDTAB for this CB. Keep the uniqueness bits
; stored in UBTTAB for later verification (used in routine SC.FUB).
LOAD T1,CBSCID,(P1) ;Get the connect ID from the CB
LOAD T4,INDEX,T1 ;Extract the index from the CID
MOVE T1,T4 ;Get a copy we can smash
ADD T1,CIDTAB ;Add the offset to the CB addr table
SETZM (T1) ;Zero the address entry for this CB
;Here to get buffers back from the message free queue.
SRC.NJ:
MOVE Q1,.CBRCD(P1) ;Get the total current credits
ADD Q1,.CBPRC(P1) ;add the number of pending credits
ADD Q1,.CBRQC(P1) ; and number of credits in outstand CDT_REQ
ADD Q1,.CBRTC(P1) ;Add canceled buffers not yet dequeued
JUMPE Q1,SRC.DG ;If nothing to dequeue, try datagrams
SRC.B1: BLCAL. (ULNKMG,<P4>) ;(/T1) Get a buffer back from the port
IFNSK.
LOAD T1,SBDPA,(P4) ;Get node number
LOAD T2,CBSCID,(P1) ;Get connect ID
BUG. (CHK,SCACGM,SCAMPI,SOFT,<SCA - Can't get message buffer when reaping>,<<T1,NODE>,<T2,CID>,<Q1,COUNT>>,<
Cause: We are reaping a connection block. Its receive credit indicates that
message buffers are queued to the port. However, the port's queue has
become empty while we tried to remove these buffers.
Data: NODE - node number
CID - Connect ID
COUNT - number of buffers remaining to be dequeued
>)
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,-3(P) ;Get PC of caller to feature routine
MOVEI T3,1 ;Set buffer count
SETOM T4 ;Set buffer address to -1 due to failure
TXZ T3,RPQFLK ;Clear port link flag since unlinking
TXO T3,RPQFMG ;Set message free queue flag
CALL RG.PQM ;(T1,T2,T3,T4,P4) Record port manipulation
> ;End of IFN SCARNG
JRST SRC.DG ;No message buffers left, do datagrams
ENDIF.
IFN SCARNG,<
BLOCK.
SAVEAC <T1> ;Save smashed AC
MOVE T4,T1 ;Get buffer address
XMOVEI T1,. ;Get feature routine address
MOVE T2,-6(P) ;Get PC of caller to feature routine
MOVEI T3,1 ;Set buffer count
TXZ T3,RPQFLK ;Clear port link flag since unlinking
TXO T3,RPQFMG ;Set message free queue flag
CALL RG.PQM ;(T1,T2,T3,T4,P4) Record port manipulation
ENDBK.
> ;End of IFN SCARNG
CALL SC.RBF ;(T1/) Return the buffer to SCA free pool
SOJG Q1,SRC.B1 ; and loop if there are more buffers left
;..
; Here to get datagram buffers back from the free queue.
;..
SRC.DG: MOVE Q1,.CBDGR(P1) ;Get the number of datagrams queued
JUMPE Q1,SRC.EX ;Is there are none queued, exit now
SRC.DL: BLCAL. (ULNKDG,<P4>) ;Unlink a datagram
IFNSK.
LOAD T1,SBDPA,(P4) ;Get node number
LOAD T2,CBSCID,(P1) ;Get connect ID
BUG. (CHK,SCACGD,SCAMPI,SOFT,<SCA - Can't get datagram buffer when reaping>,<<T1,NODE>,<T2,CID>,<Q1,COUNT>>,<
Cause: We are reaping a connection block. Its buffer count indicates that
datagram buffers are queued to the port. However, the port's queue has
become empty while we tried to remove these buffers.
Data: NODE - node number
CID - Connect ID
COUNT - number of buffers remaining to be dequeued
>)
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,-3(P) ;Get PC of caller to feature routine
MOVEI T3,1 ;Set buffer count
SETOM T4 ;Set buffer address to -1 due to failure
TXZ T3,RPQFLK ;Clear port link flag since unlinking
TXZ T3,RPQFMG ;Clear message free queue flag since datagram
CALL RG.PQM ;(T1,T2,T3,T4,P4) Record port manipulation
> ;End of IFN SCARNG
JRST SRC.EX ;Can't get any more
ENDIF.
IFN SCARNG,<
BLOCK.
SAVEAC <T1> ;Save smashed AC
MOVE T4,T1 ;Get buffer address
XMOVEI T1,. ;Get feature routine address
MOVE T2,-6(P) ;Get PC of caller to feature routine
MOVEI T3,1 ;Set buffer count
TXZ T3,RPQFLK ;Clear port link flag since unlinking
TXZ T3,RPQFMG ;Clear message free queue flag since datagram
CALL RG.PQM ;(T1,T2,T3,T4,P4) Record port manipulation
ENDBK.
> ;End of IFN SCARNG
CALL SC.RLD ;(T1/) and return it to the SCA free pool
SOJG Q1,SRC.DL ;Loop if there are more buffers to do
SRC.EX:
; CALL SC.JSY ;(P1/) Clean up data for JSYS connection
JRST SRC.KL ;Go kill the buffer
; Here when we are deleting an entry from the dont care listen queue. We can
;make some nice assumptions about this CB here. It was never in any state other
;than listen, hence no checks need be made for buffers, or blocks hanging
;off this CB. It only needs to be removed from the don't care queue and
;the fork queue of the owning fork (if this is a JSYS connect).
;
SRC.DC: CALL SC.RDQ ;(P1/) Remove it from don't-care queue
CION ;Restore CI interrupts
;delete the connection block
SRC.KL: MOVE T1,P1 ;Move addr of CB to be released
CALL SC.RBF ;Release buffer space back to free pool
RET ; and return OK...
COMMENT |
;SC.JSY - Do cleanup required for a JSYS connection
;
;Accepts:
; P1/ address of connection block
;
; CALL SC.JSY
;
;Returns +1: always
;
SC.JSY:
;
; If this is a JSYS connection, remove it from the fork CB queue.
;
MOVE T2,.CBFLG(P1) ;Get the CB flags
TXNE T2,<CBFJSY> ;Is this a JSYS connection???
TXNE T2,<CBFKIL> ;A JSYS connect, is the fork gone???
RET ;Not a JSYS connect, or, if a JSYS connect the
; fork has been killed already
SETZ Q1, ;Clear the RELCPT flag
LOAD T4,CBFORK,(P1) ;Get the controlling fork number
CAME T4,FORKX ;Is this the current fork???
IFNSK.
SETO Q1, ;Set the RELCPT flag
LOAD T1,FKPS%,(T4) ;Nope, get the SPT slot for the PSB
CALL SETCPT ;Map the target PSB
MOVEI T1,SCSTCQ ;Get the rightmost 18 bits of the queue top
ANDI T1,777 ;Keep only the offset pls...
XMOVEI T1,CPTPGA(T1) ;Get the address of the queue top pointer
MOVEI T2,SCSBCQ ;Get the right 18 bits of the queue bottom
ANDI T2,777 ;Keep just the page offset
XMOVEI T2,CPTPGA(T2) ;Now get the address of queue bottom pointer
MOVES (T2) ;Reduce chance of NOSKED page faults
ELSE.
XMOVEI T1,SCSTCQ ;This is current fork, get Q top pointer
XMOVEI T2,SCSBCQ ; and addr of queue bottom pointer
ENDIF.
NOSKED ;Time to diddle the fork queues
LOAD T3,CPJNB,(P1) ;Get the addr of the next fork CB
LOAD T4,CPJPB,(P1) ; and the addr of the previous
SKIPN T3 ;Is this the last buffer to come off???
SKIPE T4 ;. . .
JRST SRC.NL ;No, handle case of other entries left
SETZM (T1) ;Last entry, zero the list head
XMOVEI T1,SCSTCQ ;Always use real top of queue address
MOVEM T1,(T2) ; to init tail as pointer to head
OKSKED ;We are last entry, allow access again
JRST SRC.BD ;Now go handle any BSD's we have on this CB
; Not the last entry on the fork CB queue.
;
SRC.NL: SKIPE T3 ;Is there a next entry???
STOR T4,CPJPB,(T3) ;Yes, update previous pointer of next CB
SKIPE T4 ;Is there a previous entry???
STOR T3,CPJNB,(T4) ;Yes, update next field of previous entry
OKSKED ;Done with Q pointers allow access again
; Note: We assume here that there are no pending packets on this CB. We make
;this assumption since one of two things has happened. Either the queue has
;been cleared by now or the KLIPA has been reloaded. In either case there
;are no more pending packets for this connect. No matter what the count
;may be...
SRC.BD: SKIPE Q1 ;Do we need to call RELCPT???
CALL RELCPT ;Yes, release the mapped PSB page...
OPSTR <SKIPN T1,>,CBTBQ,(P1) ;Are there BSD's on this connection???
JRST SRC.DQ ;No, go do queue entry deallocation
CALL SCM.RD ;Return Datagrams
; Here to take entries off all of the JSYS queues (messgae, datagram, DMA, and
;event).
;
SRC.DQ: OPSTR <SKIPN T1,>,CBTMQ,(P1) ;Are there any messages for this connection???
JRST SRC.DD ;No, try for datagrams
XMOVEI T2,MSG ;This is a message block
CALL SCSDEQ ;Remove it from the fork and CB queues
CALL SC.RBF ;Return the message buffer
JRST SRC.DQ ;Loop for all message buffers on the CB
; Here to get entries back from the datagram queue
;
SRC.DD: OPSTR <SKIPN T1,>,CBTDQ,(P1) ;Are there any datagrams for this connection???
JRST SRC.DX ;No, try for DMA blocks
XMOVEI T2,DG ;This is a datagram block
CALL SCSDEQ ;Remove it from the fork and CB queues
CALL SC.RLD ;Return the datagram buffer
JRST SRC.DD ;Loop for all datagram buffers on the CB
; Here to get entries back from the DMA queue
;
SRC.DX: OPSTR <SKIPN T1,>,CBTXQ,(P1) ;Are there any datagrams for this connection???
JRST SRC.DE ;No, try for DMA blocks
XMOVEI T2,XFER ;This is a datagram block
CALL SCSDEQ ;Remove it from the fork and CB queues
CALL RELRES ;Release the DMA block
JRST SRC.DX ;Loop for all DMA block
; Here to get entries back from the event queue
;
SRC.DE: OPSTR <SKIPN T1,>,CBTEQ,(P1) ;Are there any events for this connection???
RET ;No. Finished
XMOVEI T2,EVT ;This is an event block
CALL SCSDEQ ;Remove it from the fork and CB queues
CALL RELRES ;Return the event block
JRST SRC.DE ;Loop for all event blocks on the CB
RET
| ; End COMMENT
SUBTTL Periodic functions -- SC.ALM (Allocate buffers)
;SC.ALM - Allocate buffers
;Called by job 0 when DDCFSF is non-zero.
SC.ALM::SKIPN SCAINI ;Have we inited yet???
RET ;No, return now
CALL SC.DEF ;Do buffer deferral requests
CALL SC.ALC ;Allocate buffers to get us up to thresholds
RET
SUBTTL Periodic functions -- SC.ALC (Allocate buffers for pool)
; Here to check on buffer levels. First do messages.
SC.ALC: MOVE T1,MINMSG ;Get current min message threshold
SUB T1,FQCNT ;How many do we need?
JUMPLE T1,SAL.DG ;We have enough
CALL SC.CMG ;(T1/T1,T2,T3) Create the message buffers
IFNSK.
MOVE T2,FQCNT
BUG. (CHK,SCAMCF,SCAMPI,SOFT,<SCA - Message buffer creation failure>,<<T1,ERROR>,<T2,COUNT>>,<
Cause: SCA detected that the level of buffers maintained was below minimum.
The attempt to create more message buffers failed.
Data: ERROR - error code
COUNT - number of message buffers in SCA's pool
>)
JRST SAL.DG ; and try for datagrams
ENDIF.
CIOFF ;No interrupts pls...
MOVEM T1,@BOTFQ ;Link these new buffers onto datagram Q
MOVEM T2,BOTFQ ;Update the tail pointer
ADDM T3,FQCNT ;Update the buffer count
ADDM T3,TOTMGB ; and the total number of buffers created
IFN SCADBG,<
CALL SC.TMQ ;Trace the message free queue
> ;End of IFN SCADBG
CION ;Allow access again
;..
;Here to allocate datagrams as needed
;..
SAL.DG: MOVE T1,MINDG ;Get the current DG threshold
SUB T1,DFQCNT ;How many do we need?
JUMPLE T1,R ;None
CALL SC.CDG ;(T1/T1,T2,T3) Create the datagram buffers
IFNSK.
MOVE T2,DFQCNT
BUG. (CHK,SCADCF,SCAMPI,SOFT,<SCA - Datagram buffer creation failure>,<<T1,ERROR>,<T2,COUNT>>,<
Cause: SCA detected that the level of buffers maintained was below minimum.
The attempt to create more datagram buffers failed. The error code is
in T1 and output as additional data.
Data: ERROR - error code
COUNT - number of datagram buffers in SCA's pool
>)
RET ; and return
ENDIF.
CIOFF
MOVEM T1,@BOTDFQ ;Link these new buffers onto datagram Q
MOVEM T2,BOTDFQ ;Update the tail pointer
ADDM T3,DFQCNT ;Update the buffer count
ADDM T3,TOTDGB ; and the total number of buffers created
IFN SCADBG,<
CALL SC.TDQ ;Trace the datagram free queue
> ;End of IFN SCADBG
CION
RET ;All done...
SUBTTL Periodic functions -- SC.DEF (Allocate deferred buffers for sysap)
;SC.DEF - Handle buffer deferral
;No arguments
;Returns +1: always
;Called by job 0 in case there are connections waiting for buffers
;before sending connect_request or accept_request messages
SC.DEF: SKIPN T1,SBSTUK ;Any system blocks stuck?
RET
SAVEP
SBD.FB: JFFO T1,SBD.ST ;Find first system block that's stuck
RET ;Could happen if node went offline
SBD.ST: SKIPN P4,SBLIST(T2) ;Get system block address
BUG. (HLT,SCANSB,SCAMPI,SOFT,<SCA - System block has gone away>,<<T2,NODE>>,<
Cause: SC.DEF found a system block marked as stuck for buffers, but the address
of the system block is 0
Data: NODE - Node number
>)
;Mark this system block as no longer stuck. If SC.SNM runs while we're
;in here, and finds some new c.b. stuck, it'll set the bit and we'll detect
;it on the way out.
MOVE T1,BITS(T2)
ANDCAM T1,SBSTUK ;Clear stuck bit for this s.b.
SETZM P3 ;Clear record of first c.b. found on list
;Find the first connection block on the work queue.
;We'll process any entry that needs buffers, even if it's not already
;stuck.
SBD.BA: CALL SC.RWQ ;(P3,P4/P1,P3) Get and lock next entry
JRST SBD.XT ;End of the list
;If connection state is closed, sysap did a disconnect after doing a
;connect, and before we had sent the connect_request. No need to allocate
;buffers or send the request.
;To detect SC.ACC followed by SC.REJ, we'd have to look for block state
;of reject_pending while CBIMB or CBIDB was still non-zero. We just
;let that one happen. It will be cleaned up later.
LOAD T1,CBCNST,(P1) ;Get connection state
CAIN T1,.CSCLO ;No. Is it closed?
JRST SBD.CC ;Yes.
;..
;Get buffers needed by this connection
;..
CALL SC.BF2 ;Get the buffers if we can
JRST SBD.ER ;Failed. This shouldn't happen in process context
;Mark the connection block as no longer stuck, and go find the next
;one
SETZRO CBFSOB,(P1) ;No longer stuck on buffers
SKIPN P3 ;Have we recorded first moved block?
MOVEM P1,P3 ;No. This is it, then
CALL SC.AWQ ;(P1,P4/) Put on the end of the queue
CALL SC.ULK ;(P1/) Unlock the connection block
JRST SBD.BA ;Go get next connect block for this s.b.
;Connection has been closed since this c.b. was queued. There's no need
;to create buffers or send a message.
SBD.CC: SETZRO <CBIMB,CBIDB>,(P1); Don't need buffers now
SETZRO CBFSOB,(P1) ;No longer stuck
CALL SC.PTC ;(P1/) Finished with this c.b.
CALL SC.ULK ;(P1/) Unlock the connection block
JRST SBD.BA ;Go get the next c.b.
;Nothing left to do for this system block. See if another one needs help.
SBD.XT:
CALL SC.SNM ;(P4/) Maybe we can send something now
SKIPE T1,SBSTUK ;Any more stuck system blocks?
JRST SBD.FB ;Go get the next system block that's stuck
RET
;Here when we couldn't create buffers. Ultimately, we should handle
;this better but for now, we expect process context to succeed in creating
;a page.
SBD.ER:
LOAD T2,SBDPA,(P4) ;Get node number
LOAD T3,CBSCID,(P1) ;Get CID
BUG. (HLT,SCAEBD,SCAMPI,SOFT,<SCA - Error handling buffer deferral request>,<<T2,NODE>,<T3,CID>,<T1,ERROR>>,<
Cause: SCA was unable to create buffers when running in job 0. This should
never happen since job 0 can create pages as needed.
Data: NODE - Node number
CID - Connect ID
ERROR - error code
>)
;If we turn this into a BUGCHK, this code should work:
REPEAT 0,<
SETONE CBFSOB,(P1) ;Leave it stuck
SKIPN P3
MOVEM P1,P3 ;Record this as having been moved
CALL SC.AWQ ;Requeue it
CALL SC.ULK ;(P1/) Unlock the connection block
LOAD T1,SBDPA,(P4)
MOVE T1,BITS(T1)
IORM T1,SBSTUK
JRST SBD.BA
> ;END OF REPEAT 0
SUBTTL Connection management utility routines
SUBTTL Connection management utility routines -- SC.SCA (Send connection management message)
;SC.SCA - Set block state and queue SCS control message
;Accepts:
; T1/ new state
; P1/ address of connection block
; P4/ address of system block
; CALL SC.SCA
;Returns +1: always
;Caller must have locked connection block
;It is possible to find block state non-zero here. This can happen,
;for example, if we had the c.b. queued waiting to send a credit_request,
;and a disconnect_request came in. In that case, we will store the new
;state on top of the old one. The block will already be queued, so we won't
;try to queue it again. This should happen only rarely.
SC.SCA:
TMNN CBBKST,(P1) ;Is state zero?
IFSKP.
MOVE T3,.CBSBA(P1) ;Get address of system block
LOAD T3,SBDPA,(T3) ;Get node number
LOAD T4,CBSCID,(P1) ;Get CID
LOAD T2,CBBKST,(P1) ;Get block state
BUG. (INF,SCASBN,SCAMPI,SOFT,<SCA - Block state already non-zero>,<<T3,NODE>,<T4,CID>,<T2,OLDSTA>,<T1,NEWSTA>>,<
Cause: Trying to set a connection's block state, we found it already non-zero.
This can happen legitimately under some conditions.
Action: If the old state is anything except CREDIT_PEND, something is wrong.
Try to trace the events that led to this, using the ring buffer if
necessary.
Data: NODE - Node number
CID - Connect ID
OLDSTA - existing block state
NEWSTA - state we're trying to set
>)
STOR T1,CBBKST,(P1) ;Store over it
RET ;But don't try to queue it again
ENDIF.
STOR T1,CBBKST,(P1) ;Set state as requested
CALL SC.AWQ ;(P1,P4/) Add this c.b. to the work queue
RET
SUBTTL Connection management utility routines -- SC.SNM (Send next connection management message)
;SC.SNM - send an SCS control message
;Accepts:
; P4/ Address of system block
; CALL SC.SNM
;Returns +1: always
;Sends an SCS control message for this system block if the buffer is
;available and there's a waiting connnection block. If the c.b. requires
;buffers, creates them if possible. Otherwise, moves the c.b. to the
;end of the queue and tries the next one.
SC.SNM:
SKIPN .SBTWQ(P4) ;Is there a c.b. that needs something?
RET ;No. Nothing to do.
SAVEP
SETZM P2 ;Prepare to clear the address of the buffer
EXCH P2,.SBOBB(P4) ;Grab outbound buffer if it's there
JUMPE P2,R ;It was in use. We'll come here later
SETZM P3 ;Initialize address of first c.b. moved
;Here when buffer is available, and there's something to be done.
;Remove first entry from work queue
SSN.BA: CALL SC.RWQ ;(P3,P4/P1,P3) Get and lock next entry
JRST SSN.XT ;There isn't one.
;Block state shouldn't be zero. Complain if it is
IFN SCADBG,<
TMNE CBBKST,(P1) ;Is block state still non-zero?
IFSKP.
LOAD T1,SBDPA,(P4) ;Get node number
LOAD T2,CBSCID,(P1) ;Get connect ID
LOAD T3,CBCNST,(P1) ;Get connection state
BUG. (CHK,SCABSZ,SCAMI,SOFT,<SCA - Block state is zero when trying to send connection management request>,<<T1,NODE>,<T2,CID>,<T3,STATE>>,<
Cause: A connection block is on the system block's work queue, but its block
state is zero. This value should be non-zero to indicate the kind of
request to be sent.
Data: NODE - Node number
CID - Connect ID
STATE - Connection state
>)
CALL SC.PTC ;(P1/) Allow reaper to get this block
CALL SC.ULK ;(P1/) Unlock the connection block
JRST SSN.BA ;Don't try to send.
ENDIF.
> ;end of ifn scadbg
;This probably isn't necessary, but we'll do it just in case.
;If the "reap" bit is on, we shouldn't be sending any requests.
;If block state is non-zero, reap shouldn't be set.
IFN SCADBG,<
TMNN CBFRAP,(P1) ;Are we ready to reap this block?
IFSKP.
LOAD T1,SBDPA,(P4) ;Get node number
LOAD T2,CBSCID,(P1) ;Get CID
BUG. (CHK,SCARBS,SCAMPI,SOFT,<SCA - Reap bit is set when block state is non-zero>,<<T1,NODE>,<T2,CID>>,<
Cause: A connection block is marked as waiting to send a request message, but
it also is marked as reapable. The reapable bit should be set only when
there is no need to send further requests.
Action: The message is not sent, and the block is deleted. If the
problem persists, use the ring buffer to trace the events leading
to it.
Data: NODE - Node number
CID - Connect ID at this node
>)
CALL SC.PTC ;(P1/) Finish off this block
CALL SC.ULK ;(P1/) Unlock the connection block
JRST SSN.BA ;Go handle next c.b.
ENDIF.
> ;END IFN SCADBG
;It is possible for the connection state to be closed here. We could
;check for that and refuse to send connect_request. Instead, we just
;let it go. When accept_request comes in, we'll send accept_response NM
;If this connection block is already stuck on buffers, move it to the
;end of the queue.
TMNE CBFSOB,(P1) ;Are we stuck on buffers?
JRST SSN.SB ;Yes. Move it to the end of the queue
;Get buffers that we want, if possible
CALL SC.BF1 ;(P1/) Allocate buffers if we need them
JRST SSN.SB ;Couldn't get them all
;Here when we got the buffers we wanted, or didn't want any. Create the
;packet and send it.
CALL SC.RQS ;(P1,P2,P4/) Build packet, set new state, send
IFNSK.
CALL SC.ULK ;(P1/) Unlock the connection block
JRST SSN.SF ;Couldn't send
ENDIF.
CALL SC.ULK ;(P1/) Unlock the connection block
RET
;Here when we couldn't get the buffers needed or connection block was already
;stuck. Mark the connect block as "stuck on buffers" so that job 0 can
;fix things. Mark the system block, too.
SSN.SB:
SETONE CBFSOB,(P1) ;Mark c.b. as stuck on buffers
SKIPN P3 ;Is this the first block moved to end?
MOVEM P1,P3 ;Yes. record it
CALL SC.AWQ ;(P1,P4/) Move entry to end of queue
CALL SC.ULK ;(P1/) Unlock the connection block
LOAD T1,SBDPA,(P4) ;Get node number
MOVE T1,BITS(T1) ;Get bit position for this index
IORM T1,SBSTUK ;Mark system block as stuck
JRST SSN.BA ;Go see if another entry exists
;Here when all the connection blocks that are left require buffers
;or there aren't any blocks
;We have to keep the buffer that we had planned to use for the message
;Job 0 will run eventually and create the buffers needed, and send
;the next message.
;If v.c. has been closed, then SC.ERR has already checked SBOBB. We
;must give the buffer to the port, since we already took one from it.
SSN.XT: CIOFF
LOAD T1,SBVCST,(P4) ;Is v.c. open?
CAIE T1,VC.OPN
IFSKP.
MOVEM P2,.SBOBB(P4) ;Yes. Return buffer to system block
CION
SKIPE SBSTUK ;Is a system block stuck?
AOS DDCFSF ;Yes. Ask SC.DEF to run
RET
ENDIF.
CION
;Here when the v.c. has been closed. Give the buffer to
;the port, since we won't be needing it.
SSN.SF:
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,(P) ;Get PC of caller to feature routine
MOVEI T3,1 ;Set buffer count
MOVE T4,P2 ;Get buffer address
TXO T3,RPQFLK ;Set port link flag
TXO T3,RPQFMG ;Set message free queue flag
CALL RG.PQM ;(T1,T2,T3,T4,P4) Record port manipulation
> ;End of IFN SCARNG
SETZM 0(P2) ;Tell PHYKLP there's only one buffer
BLCAL. (LNKMFQ,<P4,P2>) ;Link buffer onto port's message free queue
RET
SUBTTL Connection management utility routines -- SC.AWQ (Add entry to work queue)
;SC.AWQ - add an entry to the work queue
;Accepts:
; P1/ address of connection block
; P4/ address of system block
; CALL SC.AWQ
;Returns +1: always
;Adds c.b. to end of s.b.'s work queue
;Caller must lock the connection block
SC.AWQ: CIOFF ;Protect the work queue
LOAD T1,SBVCST,(P4) ;If v.c. is not open
CAIN T1,VC.OPN
IFSKP.
CION ; don't try to send
RET
ENDIF.
MOVE T1,.SBBWQ(P4) ;Get last entry in queue
XMOVEI T2,.SBTWQ(P4) ;Get head of queue
CAMN T1,T2 ;Empty if equal
IFSKP.
MOVEM P1,.CBNWQ(T1) ;Make old "last" point to this
ELSE.
MOVEM P1,.SBTWQ(P4) ;Make this be the first
ENDIF.
MOVEM P1,.SBBWQ(P4) ;Make this be the last
CION
RET
SUBTTL Connection management utility routines -- SC.RWQ (Remove entry from work queue)
;SC.RWQ - remove entry from system block work queue
;Accepts:
; P3/ address of connection block to stop at
; P4/ address of system block
; CALL SC.RWQ
;Returns +1: no more entries
; +2: entry available and locked
; P1/ address of connection block
; P3/ updated if necessary
;Returns non-skip when there are no more entries to be processed.
;Caller initializes P3 to 0. If it returns a block to the queue, it
;stores that block's address in P3. It does this only once, to record
;the first block that has already been seen. This routine will detect when it
;has looped around to the first block. Also, if this routine finds a connection
;block locked, it will move the block to the end of the queue, and update
;P3 appropriately.
;NOTE: This routine is closely coupled to SC.SNM and SC.DEF. It is
;not meant to be called by other routines.
SC.RWQ:
CIOFF ;Protect the work queue
SCR.LP: SKIPN P1,.SBTWQ(P4) ;Get first entry on queue
JRST SRW.EX ;Empty.
CAMN P1,P3 ;Have we found this buffer before?
JRST SRW.EX ;Yes. We've finished with this system block
SKIPE T1,.CBNWQ(P1) ;Point to the second entry
IFSKP.
XMOVEI T2,.SBTWQ(P4) ;This is the end. Make tail point
MOVEM T2,.SBBWQ(P4) ; to head
ENDIF.
MOVEM T1,.SBTWQ(P4) ;Make head point to next or 0
SETZM .CBNWQ(P1) ;Indicate no longer on queue
MOVX T1,CBFSNM ;Flag to set if we have to defer
CALL SC.LAH ;(T1,P1/) Get the lock if possible
JRST SRW.NX ;We have to defer
CION
RETSKP
;Here when the connection block was locked. Move it to the end of the
;list and continue looking for a good entry.
SRW.NX: SKIPN P3 ;Have we recorded first moved block?
MOVEM P1,P3 ;No. This is it, then
CALL SC.AWQ ;(P1,P4/) Move it to the end of the queue
JRST SCR.LP ;Go try for the next entry
;Here when we're at the end of the list, or it's empty
SRW.EX: CION
SETZM P1 ;Precaution
RET
SUBTTL Connection management utility routines -- SC.ACB (Allocate a connection block)
; This routine allocates and initializes a connection block.
;
; Usage:
; Call
; T1/ SYSAP bits to be placed in CID
;
; Return (+1)
; T1/ Error code
;
; Return (+2)
; P1/ Address of connection block
;
SC.ACB::STKVAR <SYBITS,IDX,UBTS,CID>
MOVEM T1,SYBITS ;Save the SYSAP bits
;Create and store the CID pls...
;
CALL SC.FNI ;(/T1) Get the next available index
RETBAD (SCSTBF) ;No more, return with error code in T1
SETZ T4, ;Start with zero as CID
STOR T1,INDEX,T4 ;Store index
MOVEM T1,IDX ;Save the index
CALL SC.FUB ;(T1/T1,T2) Get uniqueness bits to use for CID
STOR T2,UBITS,T4 ;Store the unique bits
MOVEM T2,UBTS ;Save the unique bits
MOVE T2,SYBITS ;Get the SYSAP bits back again
STOR T2,SID,T4 ;Store these bits in the CID
MOVEM T4,CID ;Save newly created CID
MOVEI T1,1 ;We want only one quanta of memory for CB
CALL SC.ABF ;(T1/T1,T2,T3) Get it from the allocator
RETBAD () ;Return with the error code in T1
MOVE T4,CID ;Get the created CID back again
STOR T4,CBSCID,(T1) ;Store the source connect ID in the CB
MOVE P1,T1 ;Save connect block address
MOVE T1,IDX ;Get the index back again
ADD T1,CIDTAB ;Add the base addr of the CB addr table
MOVEM P1,(T1) ;Store the address of the CB
MOVE T1,IDX ;Get the index once more
ADD T1,UBTTAB ;Add the base addr of the unique bits table
MOVE T2,UBTS ;Get said bits back
MOVEM T2,(T1) ;Store the unique bits
;Init the JSYS queue pointers in the CB
;
SETZRO CBTMQ,(P1) ;Zero the FLINK for the message queue
OPSTR <XMOVEI T2,>,CBTMQ,(P1) ;Address of the FLINK
STOR T2,CBBMQ,(P1) ;Init message BLINK as pointer to FLINK
SETZRO CBTDQ,(P1) ;Zero datagram FLINK
OPSTR <XMOVEI T2,>,CBTDQ,(P1) ;Address of datagram FLINK
STOR T2,CBBDQ,(P1) ;Init DG BLINK as pointer to FLINK
SETZRO CBTXQ,(P1) ;Zero DMA Q FLINK
OPSTR <XMOVEI T2,>,CBTXQ,(P1) ;Pointer to DMA FLINK
STOR T2,CBBXQ,(P1) ;Init BLINK as pointer to FLINK
SETZRO CBTEQ,(P1) ;Zero FLINK of event queue
OPSTR <XMOVEI T2,>,CBTEQ,(P1) ;Address of event FLINK
STOR T2,CBBEQ,(P1) ;Init BLINK as pointer to FLINK
SETZRO CBTBQ,(P1) ;Zero FLINK for buffer queue
OPSTR <XMOVEI T2,>,CBTBQ,(P1) ;Pointer to buffer FLINK
STOR T2,CBBBQ,(P1) ;Init BLINK as pointer to FLINK
MOVEI T2,.CSCLO ;Initial state is "closed"
STOR T2,CBCNST,(P1) ;Set that in connection block
RETSKP ;Return happy with address in P1
ENDSV.
; This routine finds and updates the next index into the CID tables.
;
; Usage:
; Call
; No arguments
;
; Return (+1)
; No free slots left in the table
;
; Return (+2)
; T1/ Next available index
;
; Smashes T2 and T3
SC.FNI: MOVEI T3,C%CIDL ;Init count of entries searched
SFI.LP: SOSGE T1,NXTIDX ;Try for the next index
IFNSK. ;Failed, time to recycle
MOVEI T1,C%CIDL-1 ;Init NXTIDX to highest CIDTAB entry
MOVEM T1,NXTIDX
AOS CIDRFL ;Indicate CIDTAB recycling
ENDIF.
MOVEM T1,T2 ;Get a copy we can play with
ADD T2,CIDTAB ;Add the offset to the CID address table
SKIPN (T2) ;Is there an entry there???
IFSKP. ;Yes
SKIPN CIDRFL ;Are we in recycle mode?
JRST SFI.LP ;No, try for another index
SOSE T3 ;Have we checked the entire CIDTAB?
JRST SFI.LP ;No, look at next index
RET ;Yes, table must be full, return failure
ENDIF.
RETSKP ;No entry so return index found
; This routine finds and updates the next uniqueness bits for a CID.
;
; Usage:
; Call
; T1/ Index into CIDTAB of CID being formed
;
; Return +1: Always
; T1/ Index into CIDTAB of CID being formed
; T2/ Next uniqueness bits to use for CID
SC.FUB: SOSG T2,UNQBTS ;Try for the next identifier
IFNSK. ;No more left, recycle
SETONE UBITS,T2 ;Set all bits in the unique bits field
LSH T2,-<C%RMBU> ;Right justify said bits
MOVEM T2,UNQBTS ;Store as the uniquness bits
AOS UNQRFL ;Indicate recycling
ENDIF.
SKIPN UNQRFL ;Are we in recycle mode for the bits?
RET ;No, return success
ADD T1,UBTTAB ;Obtain address of old entry
CAME T2,(T1) ;Yes, are the old and new uniqueness bits equal?
IFSKP. ;Yes, make new bits different
SOS T2 ;Decrement to insure uniqueness for entry
SKIPLE T2 ;Is this new value valid?
IFSKP. ;No, adjust
SETONE UBITS,T2 ;Set all bits in the unique bits field
LSH T2,-<C%RMBU> ;Right justify said bits
ENDIF.
ENDIF.
RET ;Return success
SUBTTL Connection management utility routines -- SC.LCB (Link a new CB)
; This routine links a new conection block into the list of connection
;blocks hanging off a system block.
;
;Accepts:
; P1/ Address of CB
; P4/ System block address (or -1 for don't care listener)
;
; CALL SC.LCB
;Returns +1: Failure
; +2: Success
;CIOFF protects from node's going offline, and from changes in the
;list of c.b.'s
;Caller must have locked the connection block
;If this was previously on the don't-care queue, the caller must have
;removed it.
SC.LCB::CIOFF
JUMPL P4,SLC.DC ;Special case, handle linking dont cares
LOAD T1,SBVCST,(P4) ;Get state of connection
CAIE T1,VC.OPN ;Is it open?
RETBAD (KLPX9,<CION>) ;No. Don't try to link, then
;Remove entry from current list if it's on one. This shouldn't happen.
;If it was on the don't-care queue, the caller has removed it. And it should
;never move from one system block queue to another
SKIPN T3,.CBANB(P1) ;Is there a current forward link
SKIPE T4,.CBAPB(P1) ; or a link to a previous buffer???
IFNSK.
LOAD T1,SBDPA,(P4) ;Get node number
LOAD T2,CBSCID,(P1) ;Get connect ID
BUG. (CHK,SCABAL,SCAMPI,SOFT,<SCA - Connection block already linked>,<<T1,NODE>,<T2,CID>,<T3,FLINK>,<T4,BLINK>>,<
Cause: SCA is linking a connection block onto a system block. However, the
connection block's pointers indicate that it is already linked to some
other block
Data: NODE - node number
CID - Connect ID
FLINK - Address of next connection block
BLINK - Address of previous connection block
>)
CALL SC.RSQ ;(P1/) Dequeue CB from current queue
ENDIF.
;Add entry to the queue
MOVE T2,.SBLCB(P4) ;Get the pointer to current last
XMOVEI T3,.SBFCB(P4) ;Get the address of the SB CB FLINK
CAME T2,T3 ;Are we about to store an SB addr as BLINK???
MOVEM T2,.CBAPB(P1) ;No, make this the pointer to previous
MOVEM P1,@.SBLCB(P4) ;Link on the new buffer
MOVEM P1,.SBLCB(P4) ;Set up the new last pointer
CION ;Turn on CI interrupts, unlock CB list
RETSKP ;Indicate success
;Here to link dont care listeners togther...
SLC.DC:
MOVE T1,BOTDC ;Get the address of the last buffer on the Q
MOVEM P1,@BOTDC ;Link this to the end of the DC queue
XMOVEI T3,TOPDC ;Get the address of the top pointer
CAMN T1,T3 ;Is previous CB the top pointer???
SETZ T1, ;Yes, make it zero instead
MOVEM T1,.CBAPB(P1) ;Make this CB point to the previous one
MOVEM P1,BOTDC ;Now show it as the end of the queue
CION ;Restore the state of the PI
RETSKP ;And we are all done
;SC.RSQ - remove c.b. from its current system block queue
;Accepts:
; P1/ address of connection block
; CALL SC.RSQ
;Returns +1: always
; Here to dequeue a CB from its current queue before we go on to put it on
;the new one.
;Caller must ensure that connection block is not on the don't-care queue.
;Caller must be CIOFF
SC.RSQ:
MOVE T1,.CBANB(P1) ;Get forward pointer for CB queue
MOVE T2,.CBAPB(P1) ; and link to previous on CB queue
MOVE T3,.CBSBA(P1) ;No previous or next, this is last, get SB pntr
SKIPN T1 ;Is there a next link???
SKIPE T2 ; or a previous link???
JRST SLC.NL ;Yes, not last entry, do a real dequeue
XMOVEI T4,.SBFCB(T3) ;Get pointer to head of CB queue
MOVEM T4,.SBLCB(T3) ;Init tail as pointer to head
SETZM .SBFCB(T3) ;Init head as zero
RET ;All done
; Here when there were other things on the queue.
;
SLC.NL: SKIPE T1 ;Is there a next link???
MOVEM T2,.CBAPB(T1) ;Yes, update pointer to previous of next
SKIPE T2 ;Is there a previous link???
MOVEM T1,.CBANB(T2) ;Yes, update pointer to next of previous
SKIPN T1 ;Is there a next buffer???
MOVEM T2,.SBLCB(T3) ;No, deleted last, update queue BLINK
SKIPN T2 ;Is there a previous buffer
MOVEM T1,.SBFCB(T3) ;No, deleted first, update queue FLINK
RET ; and return
;SC.RDQ - remove entry from don't-care queue
;Accepts:
; P1/ address of connection block
; CALL SC.RDQ
;Returns +1: always
SC.RDQ: MOVE T1,.CBANB(P1) ;Get the addr of the next CB
MOVE T2,.CBAPB(P1) ; and the addr of the previous CB (on CB Q)
SKIPN T1 ;Is there a next entry???
SKIPE T2 ; or a previous entry???
JRST SRC.MT ;Yes, not the last buffer...
XMOVEI T1,TOPDC ;No, this is the last CB on DC queue
MOVEM T1,BOTDC ;Init tail as pointer to head
SETZM TOPDC ;Init head as zero
RET
SRC.MT: SKIPE T1 ;Is there a next entry???
MOVEM T2,.CBAPB(T1) ;Yes, update previous of next CB
SKIPE T2 ;Is there a previous entry???
MOVEM T1,.CBANB(T2) ;Yes, update next of previous CB
SKIPN T1 ;Was there a next entry???
MOVEM T2,BOTDC ;No, update the queue BLINK
SKIPN T2 ;Was there a previous entry???
MOVEM T1,TOPDC ;No, update the queue FLINK
RET
SUBTTL Connection management utility routines -- SC.SCM (Search for connection match)
; This routine searches the connection blocks for a match between a
;local listen and a destination connect request.
;
; Usage:
; Call
; P2/ Address of datagram/message buffer
;
; Return (+1)
; No match, no data returned
;
; Return (+2)
; P1/ Address of connection block with a match
;
; This routine assumes that the message type is CONNECT_REQUEST. If it is not
;we will have real problems...
;
;
; AC usage within this routine:
; T1/ Address of the message
; T2/ Scratch
; T3/ Scratch
; T4/ Scratch
;
; Q1/ Current system block index (SBI)
; Q2/ Address of the current system block
; Q3/ Copy of initial P1
;
; P1/ Address of current CB
; P2/ Address of message (Touch not the contents of P2!!!)
; P3/ Touch not the contents of P3!!
; P4/ System block address of remote we got connect request from
; *** Set up by port driver on call to SCA ***
; *** Touch it not ***
; P5/ Unused here
;
;This code assumes it is called at interrupt level, and therefore
;doesn't protect itself from changes in the list of connection blocks
;on a system block
SC.SCM: SAVEQ
MOVEM P1,Q3 ;Save P1 here in case we have to restore it
; Here to start looping over the system blocks.
;
SETO Q1, ;Start with the first SB
SSC.SL: AOS Q1 ;Next SB please...
CAILE Q1,C%SBLL-1 ;Have we run off the end of the list???
JRST SSC.DC ;No more SB's, try for the dont care Q
SKIPN Q2,SBLIST(Q1) ;Get the address of an SB
JRST SSC.SL ;No S.B. here, try for the next one
;..
; Here to loop over the connection blocks hung off an SB.
;
;..
MOVE P1,.SBFCB(Q2) ;Get the pointer to the first CB
$SKIP ;Dont smash what we just did...
SSC.CL: MOVE P1,.CBANB(P1) ;Get the address of the next connection block
JUMPE P1,SSC.SL ;If no connection blocks, do next SB
LOAD T1,CBCNST,(P1) ;Get the connection state
CAIE T1,.CSLIS ;Is the connect state listen???
JRST SSC.CL ;No, loop to next connection block
;Here to do system address checking
;
LOAD T1,CBDNOD,(P1) ;Get the destination node number
CAMN T1,[XWD 0,-1] ;Is this the DONT CARE of system index's???
JRST SSC.AS ;Yes, dont do a system index check
MOVE T1,SBLIST(T1) ;Now the system block address
CAME T1,P4 ;Do we have a match???
JRST SSC.CL ;Nope, wrong system, next connection block
;Here to do name checking
;
SSC.AS: SKIPN .MGDPN(P2) ;Is there a requested process name??
SKIPE .CBDPN(P1) ;And do we care who we talk to??
$SKIP ;We care, do regular name checking
JRST SSC.FX ;We have a dont care situation, match now
XMOVEI T1,.CBSPN(P1) ;Point to our name for me
XMOVEI T2,.MGDPN(P2) ;Point to the remotes name for me
CALL SC.C4S ;Do they match???
JRST SSC.CL ;No, try the next connection block
XMOVEI T1,.CBDPN(P1) ;Point to CB's destination proc name
XMOVEI T2,.MGSPN(P2) ; and the source name of the connect request
CALL SC.C4S ;Compare the two strings...
JRST SSC.CL ;No match, next connection block please
JRST SSC.FX ;Else, we have a match, return
; Here when all that is left is the dont care queue.
;
SSC.DC: MOVE P1,TOPDC ;Get the addr of the first CB on dont care Q
$SKIP ;Smash not on the first time through
SSC.DL: MOVE P1,.CBANB(P1) ;Get the address of the next CB on DC Q
JUMPE P1,SSC.YL ;No next CB, we are done and you loose
LOAD T1,CBCNST,(P1) ;Get state of connection
CAIE T1,.CSLIS ;Listening?
JRST SSC.DL ;No. Go check the next one
SKIPN .MGDPN(P2) ;Is there a requested process name???
SKIPE .CBDPN(P1) ; and do we care who we talk to???
$SKIP ;Yes, not dont care case, do regular name check
JRST SSC.LC ;No, we have default match, put CB on SB queue
XMOVEI T1,.CBSPN(P1) ;Point to our name
XMOVEI T2,.MGDPN(P2) ; and to the remotes name for us
CALL SC.C4S ;Do they match???
JRST SSC.DL ;No, try for the next CB on DC q
SKIPN .CBDPN(P1) ;Do we care who we talk to???
JRST SSC.LC ;No, then match this connect
XMOVEI T1,.CBDPN(P1) ;We care, get target name pointer
XMOVEI T2,.MGSPN(P2) ; and pointer to remotes name
CALL SC.C4S ;Does our target name match remote source name?
JRST SSC.DL ;No, try the next entry on don't care queue
;We have a match, delink us from the dont care queue and put us on the CB list
;for the SB we have found a home with.
;
SSC.LC: CALL SC.RDQ ;(P1/) remove block from queue
LOAD T1,SBDPA,(P4) ;Get node number for this system block
STOR T1,CBDNOD,(P1) ;Save it in this connect block
MOVEM P4,.CBSBA(P1) ;Be sure the CB reflects the new SB address
SETZM .CBANB(P1) ;We just dequeued, zero links so SCLCB
SETZM .CBAPB(P1) ; does not dequeue again
CALL SC.LCB ;(P1,P4/) Link this CB onto the remote's SB
IFNSK.
LOAD T2,SBDPA,(P4) ;Get node number
BUG. (HLT,SCACLB,SCAMPI,SOFT,<SCA - Incoming connect_request on closed v.c.>,<<T2,NODE>>,<
Cause: SCAMPI received a connect_request and matched it to a listener.
But when it tried to queue the connection block to the system block,
it found that the v.c. was closed. Since it had checked for that
state earlier, and this is happening at interrupt level, something
unexpected has happened.
Data: NODE - Node number
>)
ENDIF.
RETSKP ;And return success
; Here when there is no match. You lose...
;
SSC.YL: MOVE P1,Q3 ;Get the initial contents of P1 back again
RET ;Return with no match
; Here to fix things up for a match. We are here to insure the CB has good info
;about the SB.
;
SSC.FX: MOVEM P4,.CBSBA(P1) ;Store the system block address
LOAD T1,SBDPA,(P4) ;Get node number for this system block
STOR T1,CBDNOD,(P1) ;Save it in this connect block
RETSKP ;And return success
; This routine compares four word strings. The strings are always
;be padded out to their full four word size. Hence we can do this whole
;operation in a set of full word compares. This is infinitly faster than
;an ILDB/CAME loop.
;
; Usage:
; Call
; T1/ Address of one four word string
; T2/ Address of another four word string
;
; Return (+1)
; T1 and T2 are preserved - Strings do not match
;
; Return (+2)
; T1 and T2 are preserved - Strings match
;
SC.C4S: MOVE T3,(T1) ;Get first word from string
CAME T3,(T2) ;Does the first word match?
RET ;No, return no match
MOVE T3,1(T1) ;Do the next word
CAME T3,1(T2) ;Check for a match
RET ;Nope...
MOVE T3,2(T1) ;Next word along please...
CAME T3,2(T2) ;A match???
RET ;Nope...
MOVE T3,3(T1) ;Now for the last word
CAME T3,3(T2) ;A match
RET ;Nope
RETSKP ;Yes!!! Return matching strings!!
SUBTTL Connection management utility routines -- SC.CSC (CID sanity check)
; This routine checks the validity of a connect ID.
;
; Usage
; Call
; T1/ Connect ID to check
;
; Return (+1)
; T1/ error code
;
; Return (+2)
; T1/ Connect ID
; P1/ Address of connection block where match was found
;
;Alternate entry point, SC.CAL, checks the c.b. and locks it
SC.CSC::TDZA P1,P1 ;Flag = 0 means we don't want to lock
SC.CAL: SETOM P1 ;Flag = -1 means we do want to lock
CIOFF ;Insure we are the only ones in the CID table
; and protect connection block until locked
LOAD T2,INDEX,T1 ;Get the index from the connect ID
MOVEM T2,T3 ;Save a copy of the index
CAIL T2,C%CIDL ;Is it within range???
JRST SCC.XT ;No, fail
ADD T2,CIDTAB ;Add the offset to the CID table
SKIPN T2,(T2) ;Now get the address of the CB
JRST SCC.XT ;No, fail
LOAD T4,UBITS,T1 ;Get the uniqueness bits from the CID
MOVE T2,T3 ;Get a copy of the index
ADD T2,UBTTAB ;Add the offset to the uniqueness table
MOVE T2,(T2) ;Get the bits from the unique table
CAME T2,T4 ;Do we have a match???
JRST SCC.XT ;No, fail
ADD T3,CIDTAB ;Yes, T3 = CID table base addr + index
MOVE T3,(T3) ;Get address of the connection block
EXCH T3,P1 ;Put it in P1; retrieve entry flag
SKIPE T3 ;Want to lock?
CALL SC.LOK ;(P1/) Yes. Lock the connection block
CION ;Restore the state of the PI
RETSKP ;Return success
;Here to failure exit
SCC.XT: CION ;Restore the state of the PI
RETBAD (SCSIID) ;Return "invalid Connect ID"
SUBTTL Connection management utility routines -- SC.CDT (Send credit_request)
;SC.CDT - Send credit_request if necessary
;Accepts:
; P1/ address of connection block
; P4/ address of system block
; CALL SC.CDT
;Returns +1: didn't send it
; +2: did send it
;Four entry points:
; SC.CDT - when sysap queues buffer for message reception
; SC.CD1 - when credit_response arrives
; SC.CD5 - when sysap takes a buffer back
; SC.CD7 - idle chatter
;Caller must lock connection block
;If this routine returns +2, caller must call SC.SNM after unlocking
;the connection block
;Here when sysap queues buffer. Send if pend_rec_credit .GT. 0 and
;rec_credit .LT. min_rec_credit
SC.CDT:
SKIPG T1,.CBPRC(P1) ;Give up if pending receive credit
JRST SCC.RT ; is not positive
JRST SC.CD3 ;Go check on receive credit
;Here when credit_response arrives. We may have wanted to send another
;one earlier, but only one can be outstanding at a time. Send if
;pend_rec_credit is negative, or if pend_rec_credit is positive and
;rec_credit .LT. minimum_receive_credit.
SC.CD1:
SKIPGE T1,.CBPRC(P1) ;Send if pending receive credit is negative
JRST SCC.SM
JUMPE T1,SCC.RT ;Don't send if there's no change
;Send if receive creidt .LT. minimum_receive_credit or if pending
;receive credit is getting large
SC.CD3: LOAD T2,CBMNRC,(P1) ;Send if receive credit is below the
CAMLE T2,.CBRCD(P1) ; minimum
JRST SCC.SM
CAIGE T1,C%MBCR ;Send if pending is getting large
JRST SCC.RT ;Don't send
JRST SCC.SM ;Send
;Here when sysap takes a buffer back. Send only if pend_rec_credit is
;negative
SC.CD5:
SKIPL .CBPRC(P1) ;Give up if pending receive credit
JRST SCC.RT ; is not negative
JRST SCC.SM ;It's negative. Tell the other end.
;Here for idle chatter
SC.CD7:
;..
;Here because credit values suggest sending a credit_request. See
;if the state of the connection will allow it. We don't send if the connection
;isn't open. If we're still opening it, there's a risk of confusing the
;other side. If we're closing it, there's no need to send a credit_request.
;Also, we want to avoid sending anything after the disconnect sequence
;has started, because we will declare protocol complete and reap the block
;when the final disconnect_response comes in. We don't want to receive
;a credit_response after that.
;..
SCC.SM: LOAD T1,CBCNST,(P1) ;Do this only if we're open
CAIE T1,.CSOPN
JRST SCC.RT
;Racefree, indicate that we're setting up for a credit_request, and make
;sure no other context is already doing it. If someone got here ahead of
;us, we don't need to send a credit_request, because our change is already
;reflected in .CBPRC. And we don't want to send one, because we might try
;to queue the same c.b. twice. Also, the second message would contain 0,
;so why bother? If credit is still pending when the credit_response comes
;in, we'll send another credit_request.
SETOM T1 ;Indicate credit_request is pending
EXCH T1,.CBPND(P1) ;Get the old value
JUMPL T1,SCC.RT ;Already pending. Don't want to do this
LOAD T1,CBBKST,(P1) ;Get the block state
SKIPN T1
IFSKP.
MOVE T1,.CBSBA(P1) ;Get address of system block
LOAD T1,SBDPA,(T1) ;Get port number
LOAD T2,CBSCID,(P1) ;Get CID
LOAD T3,CBBKST,(P1) ;Get state
BUG. (CHK,SCACSC,SCAMPI,SOFT,<SCA - Can't send credit request>,<<T1,NODE>,<T2,CID>,<T3,STATE>>,<
Cause: SCA wants to send a credit request, but the connection block already
has some other message pending. This reflects some sort of
inconsistency, since the state was "open", and the interlock word
for credit requests was 0.
Data: NODE - Node number
CID - Connect ID
STATE - BLock state
>)
SETZM .CBPND(P1) ;We're not doing credit_request after all
RET
ENDIF.
MOVEI T1,.BSCRP ;Set block state to credit_pending
CALL SC.SCA ;(T1,P1,P4/) Set block state and queue block
RETSKP ;Tell caller to get it sent
SCC.RT:
RET
;SC.GCB - Reclaim buffers according to return_credit field of connect block
;Accepts:
; P1/ address of connect block
; P4/ address of system block
; CALL SC.GCB
;Returns +1: always
;Caller must lock connection block
SC.GCB:
SAVEAC <P3>
SETZM P3
EXCH P3,.CBRTC(P1) ;Get old value, zero it
JUMPE P3,SCG.EX ;Nothing to do if it already was zero
SCG.CL: BLCAL. (ULNKMG,<P4>) ;(/T1) Get a buffer from the port driver
IFNSK.
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,-2(P) ;Get PC of caller to feature routine
MOVEI T3,1 ;Set buffer count
SETOM T4 ;Set buffer address to -1 due to failure
TXZ T3,RPQFLK ;Clear port link flag since unlinking
TXO T3,RPQFMG ;Set message free queue flag
CALL RG.PQM ;(T1,T2,T3,T4,P4) Record port manipulation
> ;End of IFN SCARNG
LOAD T1,SBDPA,(P4) ;get node number
LOAD T2,CBSCID,(P1) ;get our connect ID
BUG. (CHK,SCACRB,SCAMPI,SOFT,<SCA - Can't reclaim buffers>,<<T1,NODE>,<T2,CID>,<P3,COUNT>>,<
Cause: Based on the return_credit field for this connection, SCAMPI is trying
to reclaim buffers from the port's queue. The queue is empty. This
reflects confusion about credit, since we should have queued these
buffers at some time in the past.
Data: NODE - Node number
CID - Connect ID at this node
COUNT - Number of buffers we couldn't get
>)
JRST SCG.EX
ENDIF.
IFN SCARNG,<
BLOCK.
SAVEAC <T1> ;Save smashed AC
MOVE T4,T1 ;Get buffer address
XMOVEI T1,. ;Get feature routine address
MOVE T2,-5(P) ;Get PC of caller to feature routine
MOVEI T3,1 ;Set buffer count
TXZ T3,RPQFLK ;Clear port link flag since unlinking
TXO T3,RPQFMG ;Set message free queue flag
CALL RG.PQM ;(T1,T2,T3,T4,P4) Record port manipulation
ENDBK.
> ;End of IFN SCARNG
CALL SC.RBF ;(T1/) Return the buffer to SCA
SOJG P3,SCG.CL ;Continue until we've gotten them all
SCG.EX: RET
SUBTTL Connection management utility routines -- SC.CVC (Close a virtual connection)
; Usage:
; Call
; P4/ Address of system block
;
; Return (+1) Always
; No data returned
SC.CVC: LOAD T1,SBDPA,(P4) ;Get port number
BUG. (CHK,SCACVC,SCAMPI,SOFT,<SCA - Virtual circuit closure requested>,<<T1,NODE>>,<
Cause: SCA has either detected an SCA protocol error or timed out a credit
request to a remote (idle chatter). In either case the VC needs to be
closed. This event indicates one of two things, a node going away,
or a problem... The effected remote is indicated by the system block
address in the additional data.
Data: NODE - Node number
>)
BLCAL. (CLOSVC,<P4>) ;Request close of the connection
;This will cause callback at SC.ERR
RET
SUBTTL Connection management utility routines -- SC.SDM (String and data move to CB)
; This routine moves the source process name, destination process name, and
;connection data from the SYSAPs arguments, into the connect block.
;Note that the addresses provided for destination name and conenction data
;may be zero, but the source name is never zero.
;
; Usage:
; Call
; T1/ Address of source process name
; T2/ Address of destination process name or zero
; T3/ Address of connection data or zero
; P1/ Address of connect block
;
; Return (+1) Always
; No data returned, T1-T3 are smashed
;
SC.SDM: STKVAR <DPN,DATA>
MOVEM T2,DPN ;Save the address of the destintion name
MOVEM T3,DATA ; and the connection data
; Move the source process name
MOVE T2,T1 ;Source address for the source process name
MOVX T1,C%PNLW ;Get the length of a process name in words
XMOVEI T3,.CBSPN(P1) ;Destination address in CB for source name
EXTEND T1,[XBLT] ;Move the source name
; Move the destination process name
SKIPN T2,DPN ;Is there a destination process name to move???
JRST SDM.DT ;No, do connection data now
MOVX T1,C%PNLW ;Yes, get its length in words
XMOVEI T3,.CBDPN(P1) ;Destination addr in CB for destination name
EXTEND T1,[XBLT] ;Move the destintion process name
; Move the connection data
SDM.DT: SKIPN T2,DATA ;Is there any data to move???
RET ;No, all done
MOVX T1,C%DTLW ;Yes, get its length in words
XMOVEI T3,.CBDTA(P1) ;Destination addr in CB for connect data
EXTEND T1,[XBLT] ;Move connetion data please...
RET ;All done
ENDSV.
SUBTTL Connection management utility routines -- SC.OUT (Check sysap call)
;SC.OUT - Handle call from sysap for connection management functions
;Accepts:
; T1/ event code
; P1/ address of connection block
;Returns +1: failure
; T1/ error code
; +2: success
; T1/ new block state (0 if no change)
; T2/ new connection state (0 if no change)
SC.OUT:
MOVEM T1,T4 ;Save the event
IMULI T4,MXCNST
OPSTR <ADD T4,>,CBCNST,(P1)
SOS T4
JN X.ERR,(T4),SC.OU5 ;Is event legal for current state?
LOAD T1,X.BSTAT,(T4) ;Yes. Return new block state
LOAD T2,X.CSTAT,(T4) ;Return new connection state
RETSKP
SC.OU5: RETBAD(SCSCWS)
SUBTTL Connection management utility routines -- SC.RSP (Send a response)
;SC.RSP - Send responses
;Accepts:
; T1/ op code
; P1/ address of connection block
; P2/ address of packet
; P4/ address of system block
; CALL SC.RSP
;Returns +1: failure to send,
; T1/ error code
; +2: success
;SC.RS2 - Special entry for credit_rsp to avoid clearing credit field
SC.RSP: SETZRO MH$CDT,(P2) ;Clear the credit field
SC.RS2: STOR T1,MH$MSG,(P2) ;Store op code
LOAD T2,MH$SCI,(P2) ;Get the sending CID
STOR T2,MH$DCI,(P2) ;Store as the receiving CID
LOAD T2,CBSCID,(P1) ;Get the source connect-ID
STOR T2,MH$SCI,(P2) ;Store in packet as sending CID
CALL @SCMKPK(T1) ;(P2/) Store op-code-specific data
CALLRET SC.PAK ;(P2,P4/) Send the packet
;Make a connect_response (caller stored MH$STS)
SC.MOS: SETZRO MH$MCR,(P2) ;Minimum credit field must be 0
;Make an accept_response (caller stored MH$STS)
SC.MAS:
;Make a reject_response
SC.MRS:
;Make a disconnect_response
SC.MDS:
;Make a credit_response
SC.MCS: RET
SUBTTL Connection management utility routines -- SC.RQS (Send a request)
;SC.RQS - send an SCS control message
;Accepts:
; P1/ Address of connection block
; P2/ Address of packet buffer
; P4/ address of system block
; CALL SC.RQS
;Returns +1: failure to send, caller must dispose of buffer
; +2: success, buffer was given to port driver
;Sends requests only. Gets data from c.b.
;Caller must lock connection block
;NOTE: Other code depends on CBBKST's being zero when there is nothing
;waiting to be sent
SC.RQS:
;Block state may have gone to zero while the c.b. was queued, if the
;node went offline after it was queued. Return failure so that caller
;will get rid of the buffer.
LOAD T1,CBBKST,(P1) ;Get block state
IFN SCADBG,<
SKIPE T1 ;Shouldn't be zero
CAILE T1,YSIZE ;Too big?
IFNSK.
LOAD T2,SBDPA,(P4) ;Get node number
LOAD T3,CBSCID,(P1) ;Get connect ID
BUG. (HLT,SCAIBS,SCAMPI,SOFT,<SCA - Invalid block state>,<<T2,NODE>,<T3,CID>,<T1,BSTATE>>,<
Cause: Caller to SC.RQS provided block state larger than table (or zero)
Data: NODE - Node number
CID - Connect ID
BSTATE - Block state
>)
ENDIF.
> ;End IFN SCADBG
LOAD T4,Y.OP,(T1) ;Get op code to be sent
STOR T4,MH$MSG,(P2) ;Store it in the packet
LOAD T1,CBDCID,(P1) ;Get destination connect ID
STOR T1,MH$DCI,(P2) ;Store it in the packet
LOAD T1,CBSCID,(P1) ;Get source connect ID
STOR T1,MH$SCI,(P2) ;Store it in the packet
CALL @SCMKPK(T4) ;(P1,P2/)Call specific routine for this op code
LOAD T1,CBBKST,(P1) ;Get block state again
OPSTR <SKIPN T1,>,Y.STAT,(T1) ;Get new connection state
IFSKP.
STOR T1,CBCNST,(P1) ;Store in connection block
ENDIF.
LOAD T1,MH$MSG,(P2) ;Get op code
OPSTR <SKIPN T1,>,Z.RSP,(T1) ;If we expect a response,
IFSKP.
STOR T1,CBEXPR,(P1) ; store its op code in connection block
ENDIF.
CALL SC.PAK ;(P2,P4/) Send the packet
RET
SETZRO CBBKST,(P1) ;Indicate nothing is pending
RETSKP
;Not necessary to clear block state as long as failure occurs only
;when node goes offline.
;SC.MOQ - Make a connect request
SC.MOQ: CALL SCACDT ;(P1,P2/) Store credit field in packet
SETZRO MH$DCI,(P2) ;We don't know the destination's CID
JRST SCM.AC
;SC.MAQ - Make an accept_request
SC.MAQ: CALL SCACDT ;(P1,P2/) Store credit field in packet
SCM.AC: SETZRO MH$STS,(P2) ;Status field must be zero
LOAD T1,CBMNSC,(P1) ;Get the minimum send credit
STOR T1,MH$MCR,(P2) ;Store in minimum_credit field
; Move the destination process name.
MOVEI T1,<C%PNMN+3>/4 ;The number of words to move
XMOVEI T2,.CBDPN(P1) ;Source address of destination process name
XMOVEI T3,.MGDPN(P2) ;It goes here...
XBLT. T1 ;Move the destination process name
; Move the source process name
MOVEI T1,<C%PNMN+3>/4 ;How many words to move
XMOVEI T2,.CBSPN(P1) ;Source address for source process name
XMOVEI T3,.MGSPN(P2) ;Destination address
XBLT. T1 ;Move the source process name
; Move the initial connection data
MOVEI T1,<C%CDMN+3>/4 ;The number of words to move
XMOVEI T2,.CBDTA(P1) ;Source
XMOVEI T3,.MGSDT(P2) ;Destination address
XBLT. T1 ;Move the initial connection data
RET
;SC.MRQ - Make a reject request
SC.MRQ:
;SC.MDQ - Make a disconnect request
SC.MDQ: SETZRO MH$CDT,(P2) ;Credit field must be zero
LOAD T1,CBSDRE,(P1) ;Get the reason for disconnecting
STOR T1,MH$STS,(P2) ;Store it in the packet
SETZRO MH$MCR,(P2) ;Minimum_credit field must be zero
RET
;SC.MCQ - Make a credit request
SC.MCQ: CALL SCACDT ;(P1,P2/) Store credit field in packet
RET
; Routine to set credit in a packet and update .CBPRC
;
;
;Usage:
;
; CALL SCACDT
;
; P1/ Address of Connection block
; P2/ Message buffer to send
;
; Does not alter any AC's except T1
SCACDT: CIOFF ;Credit play time again
LOAD T1,MH$MSG,(P2) ;Get op code from packet
CAIE T1,.STCRQ ;Is this a credit request we are sending???
IFSKP.
MOVE T1,.CBPRC(P1) ;Get the pending receive credit
MOVEM T1,.CBRQC(P1) ;Store curr pend receive credit as REQ_CREDIT
ELSE.
MOVE T1,.CBPRC(P1) ;Get the pending receive credit
ADDM T1,.CBRCD(P1) ;Update the receive credit
ENDIF.
STOR T1,MH$CDT,(P2) ;Stor the credit field
SETZM .CBPRC(P1) ;zero the pending credit
CION ;Restore the state of the PI
RET ;RETURN
SUBTTL Connection management utility routines -- SC.PAK (Send a packet)
;SC.PAK - send a packet
;Accepts:
; P2/ address of packet
; P4/ address of system block
; CALL SC.PAK
;Returns +1: failure to send,
; T1/ error code
; +2: success
SC.PAK: STKVAR <OPCODE>
IFN SCARNG,<
SCPAK: XMOVEI T1,. ;Get feature routine address
MOVE T2,-3(P) ;Get caller to feature routine
LOAD T3,MH$MSG,(P2) ;Get opcode
LOAD T4,Z.LEN,(T3) ;Get length based on opcode
LOAD T3,Z.PRI,(T3) ; and priority also
HRL T4,T3 ;Place priority correctly
SETZ T3,0 ;No flags
CALL RG.PKT ;(T1,T2,T3,T4,P2,P4) Record packet transmission
> ;End of IFN SCARNG
LOAD T1,MH$MSG,(P2) ;Get op code
MOVEM T1,OPCODE
LOAD T2,Z.LEN,(T1) ;Get length of this message
CALL SC.ROU ;Byte swap the packet header for output
LOAD T3,Z.PRI,(T1) ;Get priority for this op code
BLCAL. (SNDMSG,<T2,[0],P4,P2,T3>) ;Send the packet (no flags)
RETBAD () ;Return failure
MOVE T1,OPCODE ;Restore op code
AOS SNDTAB(T1) ;Increment count for sending this code
RETSKP
ENDSV.
;SC.PTC - Declare protocol complete
;Accepts:
; P1/ address of connection block
; CALL SC.PTC
;Returns +1: always
;This routine is called when we believe that no more output should be sent
;to a node, and we don't expect any input from it. In theory, we can delete
;the connection block now. In practice, we have to wait until all outstanding
;buffers (used for sending) have been returned. Also, if this is a JSYS
;connection, the SCSJSY code will decide when to reap the block. It doesn't
;do this until the user has run, because event blocks are queued off the
;connection block
;NOTE: It is legal for the block state to be non-zero here. This can happen
;if the node goes offline.
SC.PTC:
IFN SCADBG,<
LOAD T3,CBCNST,(P1)
CAIN T3,.CSCLO ;Should be closed
IFSKP.
MOVE T4,(P) ;Get address of caller
LOAD T1,CBSCID,(P1) ;Get connect ID
CALL SC.NOD ;(T1/T1,T2) Get node number
BUG. (CHK,SCAPCC,SCAMPI,SOFT,<SCA - Protocol complete set and connect state not closed>,<<T2,NODE>,<T1,CID>,<T3,CSTATE>,<T4,CALLER>>,<
Cause: A call was made to SC.PTC to indicate that the protocol was complete.
When this happens, the connect state should be closed. It was not.
Data: NODE - Node number
CID - Connect ID
CSTATE - Connect state
CALLER - Address of caller to SC.PTC
>)
ENDIF.
>
SETONE CBFPTC,(P1) ;Indicate we've quit talking to other end
SETZRO CBBKST,(P1) ;Clear block state
TMNE CBFJSY,(P1) ;If it's not a JSYS block
IFSKP.
SETONE CBFRAP,(P1) ; then we can go ahead and reap it
ENDIF.
RET
SUBTTL Buffer management routines
SUBTTL Buffer management routines -- SC.SBT (Set buffer thresholds)
; This routine set buffer thresholds based on the number of systems currently
;online.
;
; Usage:
; Call
; No arguments
;
; Return (+1) Always
; MINMSG/ New message buffer threshold
; MINDG/ New datagram buffer threshold
;
SC.SBT: MOVE T1,SBCNT ;Get current number of online systems
IMUL T1,MBPS ;Multiply by threshold per SB to get threshold
ADD T1,MGTRSH ;Add the threshold we must have around
MOVEM T1,MINMSG ;Update the minimum message buffer count
MOVE T1,SBCNT ;Get the system count again
IMUL T1,DBPS ;Mult by DG buffers per sys to get threshold
ADD T1,DGTRSH ;Add on the treshold we must keep about
MOVEM T1,MINDG ;Update min datagram buffer count
RET ;Return
; Routine to Link Multiple Messages onto the Port Free Queue
;
; Usage:
;
; T1/ Address of buffer chain
; T2/ Count of the buffers
; P1/ address of connection block
; P4/ address of system block
; CALL SCL.MC
;
; Returns +1 always
;
SCL.MC: SAVEAC <Q2> ;Save a temporary for buffer count
MOVEM T2,Q2 ;Save the count of buffers
IFN SCARNG,<
BLOCK.
SAVEAC <T1> ;Saved smashed AC
MOVE T4,T1 ;Get buffer address
XMOVEI T1,. ;Get feature routine address
MOVE T2,-5(P) ;Get PC of caller to feature routine
MOVE T3,Q2 ;Get buffer count
TXO T3,RPQFLK ;Set port link flag
TXO T3,RPQFMG ;Set message free queue flag
CALL RG.PQM ;(T1,T2,T3,T4,P4) Record port manipulation
ENDBK.
> ;End of IFN SCARNG
BLCAL. (LNKMFQ,<P4,T1>) ;Link buffer chain onto Message Free queue
ADDM Q2,.CBPRC(P1) ;Update credit counts
RET
; Routine to Link Multiple Datagrams onto the Port Free Queue
;
; Usage:
;
; T1/ Address of buffer chain
; T2/ Count of the buffers
; P1/ address of connection block
; P4/ address of system block
; CALL SCL.DC
;
; Returns +1 always
;
SCL.DC: SAVEAC <Q2> ;Save a temporary for buffer count
MOVEM T2,Q2 ;Save the count of buffers
IFN SCARNG,<
BLOCK.
SAVEAC <T1> ;Save smashed AC
MOVE T4,T1 ;Get buffer address
XMOVEI T1,. ;Get feature routine address
MOVE T2,-5(P) ;Get PC of caller to feature routine
MOVE T3,Q2 ;Set buffer count
TXO T3,RPQFLK ;Set port link flag
TXZ T3,RPQFMG ;Clear message free queue flag since datagram
CALL RG.PQM ;(T1,T2,T3,T4,P4) Record port manipulation
ENDBK.
> ;End of IFN SCARNG
BLCAL. (LNKDFQ,<P4,T1>) ;Link buffer chain onto Datagram Free queue
ADDM Q2,.CBDGR(P1) ;Update Datagram counts
RET
; Routine to return Multiple Message buffers to the Message pool
;
;Usage
;
; T1/ Address of Buffer list
; Call SCM.RM
;
; Returns +1 always
SCM.RM: SAVEAC <Q1> ;Save a place for the header
SCM.LM: MOVE Q1,0(T1) ;Get the pointer to the next buffer
CALL SC.RBF ;Return the buffer
SKIPN T1,Q1 ;Was there another buffer?
RET ;Return no more to do
JRST SCM.LM ;Yes try again for more
; Routine to return Multiple Datagrams buffers to the Datagrams pool
;
;Usage
;
; T1/ Address of Buffer list
; Call SCM.RD
;
; Returns +1 always
SCM.RD: SAVEAC <Q1> ;Save a place for the header
SCM.LP: MOVE Q1,0(T1) ;Get the pointer to the next buffer
CALL SC.RLD ;Return the buffer
SKIPN T1,Q1 ;Was there another buffer?
RET ;Return no more to do
JRST SCM.LP ;Yes try again for more
SUBTTL Buffer management routines -- SC.BUF
;SC.BUF - get buffers for SC.SNM or SC.DEF
;Accepts:
; P1/ address of connection block
; P4/ address of system block
; CALL SC.BF1 (if can't create buffers)
; CALL SC.BF2 (if can create buffers)
;Returns +1: failed to create buffers
; +2: buffers were created
;This routine attempts to allocate buffers from SCA's free pool. If
;the caller can tolerate page faults, it tries to create new buffers if
;the pool is empty
SC.BF1: TDZA T1,T1 ;Can't create buffers
SC.BF2: SETOM T1 ;Can create buffers
SAVEP
MOVEM T1,P2 ;Save flag
OPSTR <SKIPN T1,>,CBIMB,(P1) ;Get the number of message buffers needed
JRST SBF.DG ;None. Go try for datagram buffers
CALL SC.ABF ;(T1/T1,T2,T3) Try to get them from the pool
SKIPA ;Failed. HAve to create them
JRST SBF.QM ;Succeeded. Go give them to the port
;Didn't have enough in SCA's pool. Create them.
IFE. P2 ;Can we create them?
AOS DMRCNT ;No. Count failure
RET
ENDIF.
LOAD T1,CBIMB,(P1) ;Get number of buffers needed
CALL SC.CMG ;(T1/T1,T2,T3) Create the message buffers
RET ;Indicate failure
ADDM T3,TOTMGB ;Add to total number of message buffers created
;SC.CMG may have created more than we needed. If so, make a chain of the
;extra buffers and return them to SCA's pool.
LOAD P5,CBIMB,(P1) ;See how many buffers we wanted
CAMN P5,T3 ;Did we get exactly what we wanted???
JRST SBF.QM ;Yes, queue the buffer chain immediatly
;We got more than we wanted. Make a chain out of the desired number.
MOVEM T1,P3 ;Save the address of the buffer chain
MOVE T2,T1 ;No, loop to get address of last desired buffer
MOVE T3,T2 ;Save the address of the previous buffer
MOVE T2,(T2) ;Get the address of the next buffer
SOJG P5,.-2 ;Loop until request count is exhausted
SETZM (T3) ;Zero the forward pointer of last req buffer
;Return the excess buffers created by CMG to the SCA free pool.
MOVE T1,T2 ;Get the address of the current buffer
CALL SCM.RM ;Return messages to free pool
MOVE T1,P3 ;Get the address of the buffer chain
; Here when we are ready to queue the buffers to the port queue.
SBF.QM: LOAD T2,CBIMB,(P1) ;Get the count of the buffers in the chain
CALL SCL.MC ;(T1,T2,P1,P4/) Queue up the Messages to the port
; and update pending receive credit
SETZRO CBIMB,(P1) ;No longer need these buffers
;..
; Here to do datagrams.
;..
SBF.DG: OPSTR <SKIPN T1,>,CBIDB,(P1) ;Get the number of datagrams to create
JRST SBF.EX ;None
CALL SC.ALD ;(T1/T1,T2,T3) Try to get them from the pool
SKIPA ;Failed. HAve to create them
JRST SBF.QD ;Succeeded. Go give them to the port
;Didn't have enough in SCA's pool. Create them.
IFE. P2
AOS DDRCNT
RET
ENDIF.
LOAD T1,CBIDB,(P1) ;Get number of buffers needed
CALL SC.CDG ;(T1/T1,T2,T3) Create the datagrams
RET ;Indicate failure
ADDM T3,TOTDGB ;Add to total datagram buffers created
;SC.CMG may have created more than we needed. If so, make a chain of the
;extra buffers and return them to SCA's pool.
LOAD P5,CBIDB,(P1) ;Get the number of buffer requested
CAMN P5,T3 ;Did we get excatly what we asked for???
JRST SBF.QD ;Yes, go queue the datagrams
;We got more than we wanted. Make a chain out of the desired number.
MOVEM T1,P3 ;Save the address of the buffer chain
MOVE T2,T1 ;Get the base addr of the chain
MOVE T3,T2 ;Save the address of the previous buffer
MOVE T2,(T2) ;Move on to the next buffer
SOJG P5,.-2 ;Loop until we have the number we requested
SETZM (T3) ;Zero the FLINK of the last req buffer
; Here to put the excess buffers created by CDG on the SCA free queue.
MOVE T1,T2 ;Get the address of the current buffer
CALL SCM.RD ;Return Datagrams
MOVE T1,P3 ;Get the address of the buffer chain
; Here to link the new buffers onto the hardware free queue.
SBF.QD: LOAD T2,CBIDB,(P1) ;Get the number of datagrams queued
CALL SCL.DC ;Put the Datagrams on the Free q
SETZRO CBIDB,(P1) ;No longer need these buffers
SBF.EX: RETSKP
SUBTTL Buffer management routines -- SC.ALD (Allocate long datagram buffers)
; This routine allocates long datagram buffers. In order to receive a long
;datagram you must queue a buffer obtained with this routine.
;
; Usage:
; Call
; T1/ Number of buffers desired
;
; Return (+1)
; Not enough buffers available to fill request, try again later
;
; Return (+2)
; T1/ Address of first buffer on chain
; T2/ Number of buffers returned
; T3/ Address of routine to return buffers
;
; Local AC usage:
; T1/ Pointer to current buffer
; T3/ Saved copy of current buffer pointer
; T4/ Number of buffer left in request
;
SC.ALD::MOVE T2,T1 ;A copy we can work with
CIOFF ;Interlock the buffer counts
IFN SCADBG,<
CALL SC.TDQ ;Trace the datagram free queue
> ;End of IFN SCADBG
SUB T2,DFQCNT ;(T2) = (request) - (available)
SKIPLE T2 ;Is the request more than we have available???
JRST SAL.RF ;Yes, refuse the request
MOVMS T2 ;(T2) = (available) - (request)
CAML T2,DGTRSH ;Will there be enough left over after request??
IFSKP.
CAML T1,LRGREQ ;No, but is this a small request???
JRST SAL.RF ;No, a large request, refuse it
AOS DBUST ;Count another small request busting threshold
ENDIF.
; Here to honor the request.
;
STKVAR <NUMBUF>
MOVEM T1,NUMBUF ;Save the number of buffers requested
MOVE T4,T1 ;Working copy of the request size
SKIPN T1,TOPDFQ ;Is there a first buffer, get its address
JRST SAL.ER ;Handle a bad buffer count
MOVE T2,T1 ;Start buffer loop with addr of first buffer
SAL.BL: SOJLE T4,SAL.CR ;If no more buffers,fix up count and Q pointers
SKIPN T2,(T2) ;Now on to the next buffer
JRST SAL.ER ;No entry!!! Recover from a bad FQCNT
JRST SAL.BL ;Loop for more entries
; Here when we have completed the request.
;
; Expects:
; T1/ Address of first buffer to be returned
; T2/ Address of last buffer to be returned
;
SAL.CR: SKIPE T3,(T2) ;Get the addr of the new first buffer
IFSKP.
XMOVEI T4,TOPDFQ ;No next buffer, get pointer to top of the Q
MOVEM T4,BOTDFQ ; and init the queue BLINK as pointer to FLINK
AOS DDCFSF ;Ask DDMP fork to run for us
ENDIF.
MOVEM T3,TOPDFQ ;In any case update the q FLINK
SETZM (T2) ;Zero forward link of last buffer
MOVN T3,NUMBUF ;Get the number of buffers issued
ADDM T3,DFQCNT ;Account for these in buffer counts
IFN SCADBG,<
CALL SC.TDQ ;Trace the datagram free queue
> ;End of IFN SCADBG
MOVE T3,MINDG ;Number of buffers we should have onhand
CAMGE T3,DFQCNT ;Are there enough buffers around these days???
JRST SAL.EX ;Yes, bail out now...
AOS DDCFSF ;Ask DDMP fork to run for us
SAL.EX: CION ;Restore the channel
IFN SCARNG,<
MOVE T3,NUMBUF ;Get buffer count
BLOCK.
SAVEAC <T1> ;Save the base address of buffer chain
MOVE T4,T1 ;Get base address of buffer chain
XMOVEI T1,. ;Get feature routine address
MOVE T2,-6(P) ;Get PC of caller to feature routine
CALL RG.BFM ;(T1,T2,T3,T4) Record buffer management
ENDBK.
> ;End of IFN SCARNG
MOVE T2,NUMBUF ;Return the number of buffers queued
XMOVEI T3,SC.RLD ;Tell caller where to return this buffer pls...
RETSKP ;Return all OK
; Here to refuse the request. We have some book keeping to do.
;
; T1/ Request size
;
SAL.RF: ADD T1,ASRDR ;Add current average size to new request
SKIPE RDRCNT ;Don't averge if this is the first time through
IDIVI T1,2 ;Take the average of the two
MOVEM T1,ASRDR ;Update the average size of refused request
AOS RDRCNT ;Increment the number of refused requests
CION ;Release the counters
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,(P) ;Get PC of caller to feature routine
MOVE T3,RDRCNT ;Get count of refused requests
SETOM T4 ;Indicate buffer was not created
CALL RG.BFM ;(T1,T2,T3,T4) Record buffer management
> ;End of IFN SCARNG
RETBAD (SCSNBA) ;Return not enough buffers
; Here when we discover that the count was incorrect and that we have fewer
;buffers than we thought.
;
; Expects:
; T1/ Address of first buffer on returned chain
;
SAL.ER: AOS DDCFSF ;Ask DDMP fork to run for us
AOS NDBCNT ;Count this event
AOS RDRCNT ;Increment the number of refused requests
MOVE T1,NUMBUF ;Get the request size again
ADD T1,ASRDR ;Add current average size to new request
IDIVI T1,2 ;Take the average of the two
MOVEM T1,ASRDR ;Update the average size of refused request
; Now readjust the buffer count
;
SETZ T2, ;Zero the buffer count
SKIPE T1,TOPDFQ ;Are there any buffers here???
IFSKP.
XMOVEI T1,TOPDFQ ;No, get a pointer to the Q FLINK
MOVEM T1,BOTDFQ ;Init the Q tail pointer
SETZM TOPDFQ ;Init the Q head pointer
SETZM DFQCNT ;Reset count of buffers
JRST SAL.EE ; and error exit
ENDIF.
AOS T2 ;Count the initial buffer
SKIPE T1,(T1) ;Is there a next buffer
AOJA T2,.-1 ;Yes, continue to count buffers
MOVEM T2,DFQCNT ;Restore the buffer count
IFN SCADBG,<
CALL SC.TDQ ;Trace the datagram free queue
> ;End of IFN SCADBG
SAL.EE: CION ;Restore the state of the PI
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,-3(P) ;Get PC of caller to feature routine
MOVE T3,RDRCNT ;Get count of refused requests
SETOM T4 ;Indicate buffer was not created
CALL RG.BFM ;(T1,T2,T3,T4) Record buffer management
> ;End of IFN SCARNG
RETBAD (SCSNBA) ;Return failure
ENDSV.
SUBTTL Buffer management routines -- SC.ABF (Allocate a buffer/buffers)
; This routine is used to obtain message buffers from SCA. When you wish to
;receive or send a message, you must obtain the buffer from here.
;All you need to tell SCA is how many buffers you want. What is returned to you
;is a chain of buffers containing the number of buffer you asked for.
;
; Usage:
; Call
; T1/ Number of buffers desired
;
; Return (+1)
; T1/ Error code (No buffers returned)
;
; Return (+2)
; T1/ Address of the first buffer in the returned chain
; T2/ Count of buffer returned
; T3/ Address of routine to call to return buffers
;
SC.ABF::MOVE T2,T1 ;A copy we can work with
CIOFF ;Interlock the buffer counts
IFN SCADBG,<
CALL SC.TMQ ;Trace the message free queue
> ;End of IFN SCADBG
SUB T2,FQCNT ;(T2) = (request) - (available)
SKIPLE T2 ;Is the request more than we have available???
JRST SAB.RF ;Yes, refuse the request
MOVMS T2 ;(T2) = (available) - (request)
CAML T2,MGTRSH ;Will there be enough left over after request??
IFSKP.
CAML T1,LRGREQ ;No, but is this a small request???
JRST SAB.RF ;No, a large request, refuse it
AOS MBUST ;Count another small request busting threshold
ENDIF.
; Here to honor the request.
;
SAB.PR: STKVAR <NUMBUF>
MOVEM T1,NUMBUF ;Save the number of buffers requested
MOVE T4,T1 ;Working copy of the request size
SKIPN T1,TOPFQ ;Is there a first buffer, get its address
JRST SAB.ER ;Handle a bad buffer count
MOVE T2,T1 ;Start buffer loop with addr of first buffer
SAB.BL: SOJLE T4,SAB.CR ;If no more buffers,fix up count and Q pointers
SKIPN T2,(T2) ;Now on to the next buffer
JRST SAB.ER ;No entry!!! Recover from a bad FQCNT
JRST SAB.BL ;Loop for more entries
; Here when we have completed the request.
;
; Expects:
; T1/ Address of first buffer to be returned
; T2/ Address of last buffer to be returned
;
SAB.CR: SKIPE T3,(T2) ;Get the addr of the new first buffer
IFSKP.
XMOVEI T4,TOPFQ ;No next buffer, get pointer to top of the Q
MOVEM T4,BOTFQ ; and init the queue BLINK as pointer to FLINK
AOS DDCFSF ;Ask DDMP fork to run for us
ENDIF.
MOVEM T3,TOPFQ ;In any case update the q FLINK
SETZM (T2) ;Zero forward link of last buffer
MOVN T3,NUMBUF ;Get the number of buffers issued
ADDM T3,FQCNT ;Account for these in buffer counts
IFN SCADBG,<
CALL SC.TMQ ;Trace the message free queue
> ;End of IFN SCADBG
MOVE T3,MINMSG ;Number of buffers we should have onhand
CAMGE T3,FQCNT ;Are there enough buffers around these days???
JRST SAB.EX ;Yes, bail out now...
AOS DDCFSF ;Ask DDMP fork to run for us
SAB.EX: CION ;Restore the channel
IFN SCARNG,<
MOVE T3,NUMBUF ;Get buffer count
BLOCK.
SAVEAC <T1> ;Save the base address of buffer chain
MOVE T4,T1 ;Get base address of buffer chain
XMOVEI T1,. ;Get feature routine address
MOVE T2,-6(P) ;Get PC of caller to feature routine
CALL RG.BFM ;(T1,T2,T3,T4) Record buffer management
ENDBK.
> ;End of IFN SCARNG
MOVE T2,NUMBUF ;Return the number of buffers requested
XMOVEI T3,SC.RBF ;Tell caller where to return this buffer pls...
RETSKP ;Return all OK
; Here to refuse the request. We have some book keeping to do.
;
; T1/ Request size
;
SAB.RF: ADD T1,ASRMR ;Add current average size to new request
SKIPE RMRCNT ;If this is the first time, no averaging needed
IDIVI T1,2 ;Take the average of the two
MOVEM T1,ASRMR ;Update the average size of refused request
AOS RMRCNT ;Increment the number of refused requests
CION ;Release the counters
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,-3(P) ;Get PC of caller to feature routine
MOVE T3,RMRCNT ;Get count of refused requests
SETOM T4 ;Indicate buffer was not created
CALL RG.BFM ;(T1,T2,T3,T4) Record buffer management
> ;End of IFN SCARNG
RETBAD (SCSNBA) ;Return not enough buffers
; Here when we discover that the count was incorrect and that we have fewer
;buffers than we thought.
;
SAB.ER: MOVE T1,FQCNT ;Get number of buffers we thought we had
MOVE T2,TOPFQ ;Get pointer to top of free queue
MOVE T3,BOTFQ ;Get pointer to bottom of free queue
MOVE T3,NUMBUF ;Get number of buffers requested
BUG. (CHK,SCAMCR,SCAMPI,SOFT,<SCA - Message buffer count was incorrect>,<<T1,COUNT>,<T2,TOPQ>,<T3,BOTQ>,<T4,BUFNUM>>,<
Cause: We ran out of message buffers when the count indicated we had enough.
Data: COUNT - count of buffers we believed we had
TOPQ - pointer to top of message free queue
BOTQ - pointer to bottom of message free queue
BUFNUM - number of buffers requested
>)
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,-3(P) ;Get PC of caller to feature routine
MOVE T3,RMRCNT ;Get number of refused requests
SETOM T4 ;Indicate buffer was not created
CALL RG.BFM ;(T1,T2,T3,T4) Record buffer management
> ;End of IFN SCARNG
AOS DDCFSF ;Ask DDMP fork to run for us
AOS NMBCNT ;Count this event
AOS RMRCNT ;Increment the number of refused requests
MOVE T1,NUMBUF ;Get the request size again
ADD T1,ASRMR ;Add current average size to new request
IDIVI T1,2 ;Take the average of the two
MOVEM T1,ASRMR ;Update the average size of refused request
; Now readjust the buffer count
;
SETZ T2, ;Zero the buffer count
SKIPE T1,TOPFQ ;Are there any buffers here???
IFSKP.
XMOVEI T1,TOPFQ ;No, get a pointer to the Q FLINK
MOVEM T1,BOTFQ ;Init the Q tail pointer
SETZM TOPFQ ;Init the Q head pointer
SETZM FQCNT ;Zero the buffer count...
JRST SAB.EE ; and error exit
ENDIF.
AOS T2 ;Count the initial buffer
SKIPE T1,(T1) ;Is there a next buffer
AOJA T2,.-1 ;Yes, continue to count buffers
MOVEM T2,FQCNT ;Restore the buffer count
IFN SCADBG,<
CALL SC.TMQ ;Trace the message free queue
> ;End of IFN SCADBG
SAB.EE: CION ;Restore the state of the PI system
RETBAD (SCSNBA) ;Return failure
ENDSV.
SUBTTL Buffer management routines -- SC.CMG/SC.CDG (Create MSG/DG buffers)
; This routine creates emssage buffers by creating (touching) pages and
;turning them into SCA buffers. The pages used are created by touching them and
;then locking them down. Hence THIS ROUTINE MAY ONLY BE CALLED IN PROCESS
;CONTEXT.
;
; Usage:
; Call
; T1/ Number of buffers to create
;
; Return (+1)
; T1/ Error code
;
; Return (+2)
; T1/ Address of first buffer on chain
; T2/ Address of last buffer on chain
; T3/ Number of buffers actually returned
;
; Note: The number of buffers returned is rounded up to fill an intgeral
;number of pages. Hence the calling routine may get more buffers back than it
;requested.
;
SC.CMG: TDZA T2,T2 ;Clear the datagram flag
SC.CDG: SETO T2, ;Set the datagram flag
SAVEAC <Q1,Q2,P4,P5>
STKVAR <BUFSZ,NUMPPG,NUMBUF>
MOVX T3,C%MGSZ ;Assume messages
MOVX T4,C%MGPG ;. . .
SKIPE T2 ;Good assumption???
IFNSK.
MOVX T3,C%DGSZ ;Nope, get the size oF datagrams
MOVX T4,C%DGPG ; and the number of datagrams per page
ENDIF.
MOVEM T3,BUFSZ ;Save the size of the buffers we desire
MOVEM T4,NUMPPG ;Save the number of buffers per page
MOVE Q1,T1 ;Get the request size in buffers
IDIV Q1,NUMPPG ;(Q1) = Number of pages in request
SKIPE Q2 ;Any remainder???
AOS Q1 ;Yes, round up the page count
MOVE T1,Q1 ;Get the page count we will create
IMUL T1,NUMPPG ;Find the total number of buffers created
MOVEM T1,NUMBUF ;Save for later return
SETZ P4, ;Zero the page chain foreward pointer
MOVEI P5,P4 ;Make the tail pointer point to the head
; Create a chain of pages from which we can make buffers.
SCM.CP: NOSKED ;Interlock the first free page in EPG pointer
MOVE Q2,LSTEPG ;Get the last page we used from EPGSEC
SKIPE @[EP. EPGMAP(Q2)] ;Is this page in use???
SOJGE Q2,.-1 ;Yes? Loop for the next one
JUMPL Q2,SCM.ER ;Handle no pages left in EPGSEC
MOVEM Q2,LSTEPG ;Store as the next page to use
SOS LSTEPG ;Move pointer to next page
OKSKED ;Release the last EPG page pointer
LSH Q2,^D9 ;Convert the page number into an address
HRL Q2,EPGSEC ;Fill in the section number
MOVE T1,Q2 ;Address to lock
CALL MLKMA ;Lock the page down please
MOVEM Q2,(P5) ;Add entry to the end of the chain
MOVEM Q2,P5 ; and update the tail pointer
SOJG Q1,SCM.CP ;Loop if there are more pages to do
; Make the page chain into an SCA buffer chain
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,-12(P) ;Get PC of caller to feature routine
MOVE T3,NUMBUF ;Get buffer count
MOVE T4,P4 ;Get base address of buffer chain
CALL RG.BFM ;(T1,T2,T3,T4) Record buffer management
> ;End of IFN SCARNG
MOVE T1,P4 ;Get the base address of the page chain
MOVE T2,BUFSZ ;Get the size of the buffers desired
CALL SC.BBF ;Create the buffer chain
MOVE T3,NUMBUF ;Return the total buffer count as well
RETSKP ;Return all OK
; Here when we run out of pages in EPGSEC. This is only an indication of
;a different problem. In any case we should NEVER have so much memory in use
;for SCA buffers that we overrun the section. Hence die here... In general
;this means someone is not lighting F.RTB when it should be and buffers are
;ending up on the hardware free queue by the dozen...
;
SCM.ER: OKSKED
BUG. (CHK,SCABSF,SCAMPI,SOFT,<SCA - Buffer section full>,<>,<
Cause: SCA went to create more buffers and discovered that the section
for such things is full. This is an indication that something is
not returning buffers.
>)
RETBAD (SCSNEB)
ENDSV.
SUBTTL Buffer management routines -- SC.BBF (Break memory into buffers)
; Give this routine the number of buffers you would like and it will get a
;block of memory and break it up into the number of message buffers
;you asked for. The major use of this routine is the initialization code and
;the code that gets buffers after we have run out during system operation.
;
; Usage:
; Call
; T1/ Address of first page in page list
; T2/ Buffer size
;
; Return (+1) Always
; T1/ Address of first buffer on chain
; T2/ Address of last buffer on chain
;
; Local AC usage:
;
; T1/ Address of first buffer in list
; T2/ Address of last buffer in list
; T3/ Number of words left in the current page
; T4/ Address of the next buffer
;
; P1/ Address of next page
; P2/ Count of buffers obtained so far
;
SC.BBF: SAVEP ;Save the regs we use for work
STKVAR <BUFSIZ> ;Allocate space for the buffer size
ADDI T2,C%BINV ;Add invisible space size to buffer size
MOVEM T2,BUFSIZ ;Save the alleged buffer size
MOVEM T1,P1 ;Save the callers list pointer
ADDI T1,C%BINV ;Create the invisible buffer area
MOVEM T1,T2 ;For init, tail is same as head pointer
SETZ P2, ;Init the count at zero
MOVEI T3,PGSIZ ;Get the size of a page
MOVE P1,(P1) ;Get the address of the next page
MOVEM T1,T4 ;Init next addr as first addr
SBB.BL: CAMGE T3,BUFSIZ ;Have we run out of room on this page???
JRST SBB.PL ;Yes we have, do the next page pls...
AOS P2 ;Count this buffer into the total
MOVEM T4,T2 ;Update the tail pointer
MOVE T4,BUFSIZ ;Get the size of a buffer
ADDM T2,T4 ;Make it the address of the next buffer
MOVEM T4,(T2) ;Link it onto the list
SUB T3,BUFSIZ ;Update page space counter
JRST SBB.BL ;Loop over the whole page
; Here to loop over pages...
SBB.PL: SETZM (T2) ;Be sure nxt ptr is zero since we might be done
SKIPN P1 ;Is there a next page to do???
JRST SBB.EX ;Nope, go exit
MOVE T4,P1 ;Yes, get addr of next page
ADDI T4,C%BINV ;Create the invisible space
MOVEM T4,(T2) ;Link last page to new page
MOVE P1,(P1) ;Get the address of the next page
MOVEI T3,PGSIZ ;Reset the page space counter
JRST SBB.BL ;And break this page into buffers.
; Here to leave the routine. Place args where we promised them...
;
SBB.EX: MOVE T3,P2 ;Set up the count of buffers
RET ;And return
ENDSV.
SUBTTL Buffer management routines -- SC.RBF (Return a message buffer)
; This routine is called when you wish to return a buffer to SCA which you
;received from SCA. All that must be done is hand SCA a pointer to the
;buffer and away we go.
;
; Usage:
; Call
; T1/ Address of buffer to be returned
;
; Return (+1) Always
; No data returned, all buffers returned OK
;
SC.RBF::MOVE T4,T1 ;Save the address of the buffer
MOVE T2,T1 ;Make this address the source for XBLT
SUBI T2,C%BINV ;Move the origin to the start of the invisible
MOVE T3,T2 ; and the destination
AOS T3 ; is one more than the source
MOVX T1,<C%BINV+C%MGSZ>-1 ;Number of words to zero
SETZM (T2) ;Zero the first word
EXTEND T1,[XBLT] ;Zero the buffer please
MOVE T1,T4 ;Restore the address of the buffer
CIOFF ;Interlock my queues
MOVEM T1,@BOTFQ ;Link this buffer after the end of the list
MOVEM T1,BOTFQ ;Store the new free queue bottom pointer
SETZM (T1) ;Insure the FLINK of last buffer is zero
AOS FQCNT ;Update the buffer count
IFN SCADBG,<
CALL SC.TMQ ;Trace the message free queue
> ;End of IFN SCADBG
CION ;Bring back the world again
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,(P) ;Get PC of caller to feature routine
SETOM T3 ;Buffer is being returned
CALL RG.BFM ;(T1,T2,T3,T4) Record buffer management
> ;End of IFN SCARNG
RET ;Return
SUBTTL Buffer management routines -- SC.RLD (Return a datagram buffer)
; This routine is called when you wish to return a long datagram buffer to SCA.
;All that must be done is hand SCA a pointer to the buffer.
;
; Usage:
; Call
; T1/ Address of buffer to be returned
;
; Return (+1) Always
; No data returned, buffer is now in SCA database
;
SC.RLD::MOVE T4,T1 ;Save the address of the buffer
MOVE T2,T1 ;Make this the start address
SUBI T2,C%BINV ;Move back to start of the invisible area
MOVE T3,T2 ;Destination address is the start address
AOS T3 ; plus one
MOVX T1,<C%BINV+C%DGSZ>-1 ;Get the size of the buffer to be zeroed
SETZM (T2) ;Zero the first word
EXTEND T1,[XBLT] ;Zero the buffer
MOVE T1,T4 ;Get the address of the buffer back
CIOFF ;Interlock my queues
MOVEM T1,@BOTDFQ ;Link this buffer after the end of the list
MOVEM T1,BOTDFQ ;Store the new free queue bottom pointer
SETZM (T1) ;Zero the buffer FLINK
AOS DFQCNT ;Update the buffer count
IFN SCADBG,<
CALL SC.TDQ ;Trace the datagram free queue
> ;End of IFN SCADBG
CION ;Bring back the world again
IFN SCARNG,<
XMOVEI T1,. ;Get feature routine address
MOVE T2,(P) ;Get PC of caller to feature routine
SETOM T3 ;Buffer is being returned
CALL RG.BFM ;(T1,T2,T3,T4) Record buffer management
> ;End of IFN SCARNG
RET ;Return
IFN SCADBG,<
SUBTTL Buffer management routines -- SC.TMQ/SC.TDQ (Trace free queue)
; These routines are called whenever a message or datagram buffer is being
;removed from or replaced to the free queue. The queue is traced and the count is
;compared against the known count. If an inconsistency occurs, a SCATQF
;BUGHLT will result.
;
; Usage:
;
;For a trace of the message free queue:
;
; Call SC.TMQ
;
; Return (+1) Always
;
;For a trace of the datagram free queue:
;
; Call SC.TDQ
;
; Return (+1) Always
;
;No ACs are destroyed by either routine.
;Both routines must be called CIOFF.
SC.TMQ: SAVEAC <T1,T2,T3> ;Save the ACs we use
MOVE T1,FQCNT ;Get known count of free queue message buffers
SKIPE T2,TOPFQ ;Get first buffer on queue
IFSKP. ;No buffers
SKIPN T1 ;Did we believe we had any?
RET ;No, return ok
JRST SCT.ER ;Error, report it
ENDIF.
JRST SCT.CC ;Continue at common code
SC.TDQ: SAVEAC <T1,T2,T3> ;Save the ACs we use
MOVE T1,DFQCNT ;Get known count of free queue datagram buffers
SKIPE T2,TOPDFQ ;Get first buffer on queue
IFSKP. ;No buffers
SKIPN T1 ;Did we believe we had any?
RET ;No, return ok
JRST SCT.ER ;Error, report it
ENDIF.
SCT.CC: MOVEI T3,1 ;Set up initial value of buffers on queue
SKIPE T2,(T2) ;Is there a next buffer?
AOJA T3,.-1 ;Yes, continue to count buffers
CAMN T3,T1 ;Are the counts the same?
RET ;Yes, return ok
SCT.ER: BUG. (HLT,SCATQF,SCAMPI,SOFT,<SCA - Trace of free queue detected inconsistency>,,<
Cause: The trace of the message or datagram free queue resulted in a count
which was not equal to the known value which SCA keeps.
>)
> ;End of IFN SCADBG
SUBTTL Byte-swapping routines
SUBTTL Byte-swapping routines -- SC.RIN (Byte swap incoming packet)
; This routine performs magic on the packet header words.
;Since VAX and 11's have their heads wedged we must swap the order of the
;bytes that go out and come in from these systems.
;
;Usage:
; Call
; P2/ Address of packet being sent
;
; Return (+1) Always
; Header at address in P2 has been byte swapped
;
;
SC.RIN: SAVEAC <T1,T2,T3,T4,P5> ;Be sure we smash no ACs
LOAD T1,MH$TYP,(P2) ;Get the word conatining the message type
LDB P5,[POINT 1,T1,24] ;Get the -11 style sign bit
CALL SC.ISW ;Swap to get -10 style bytes
SKIPE P5 ;Was the number of credits negative???
TXO T1,<3B1> ;Yes, light the bits to make this a -10 neg num
STOR T1,MH$TYP,(P2) ;Put it back into the packet
LOAD T1,MH$MSG,(P2) ;Now get the message type
CAIE T1,.STADG ;Is this an application datagram
CAIN T1,.STAMG ; or application message?
RET ;Yes it is!! Skip status and min credit word
LOAD T1,MH$SMC,(P2) ;No... get the word uncommon to ADG and AMG
CALL SC.ISW ;Call the byte swapper
STOR T1,MH$SMC,(P2) ;Move the word back out to the header
RET
SUBTTL Byte-swapping routines -- SC.ISW (Swap bytes from 11 to 10 format)
; This routine byte swaps a word from 11 format to 10 format.
;
; Usage:
; Call
; T1/ Word to be swapped
;
; Return (+1) Always
; T1/ Byte swapped word
;
; Input format:
; 2 16 bit half words, left justified
;
; !=======================================================!
; ! B (lsb) ! B (msb) ! A (lsb) ! A (msb) ! IGN !
; !=======================================================!
; 0 7 8 15 16 23 24 31 32 35
;
; Where A and B are the half words, and (lsb) are the least significant bits
;and (msb) are the most significant bits.
;
;The contents of bits 32 thru 35 are ignored.
;
; Output format:
; 2 18 bit half words,
;
; !=======================================================!
; !X! Byte A (msb+lsb) !X! Byte B (msb +lsb) !
; !=======================================================!
; 0 2 17 20 35
;
; X denotes the 2 bit field within each halfword that will always be zero.
;
SC.ISW::LDB T2,EA$MSB ;Byte A, MSB
LDB T3,EA$LSB ;Byte A, LSB
LDB T4,EB$MSB ;Byte B, MSB
LSH T1,^D<-28> ;Move byte B, LSB into its poisition for the 10
DPB T4,TB$MSB ;Now replace the bytes into their 10 positions
DPB T3,TA$LSB ;. . .
DPB T2,TA$MSB ;. . .
RET ;All done
SUBTTL Byte-swapping routines -- SC.ROU (Byte swap outgoing packet)
; This routine byte swaps a packet for output to the wire...
;
; Usage:
; Call
; P2/ Address of packet
;
; Return (+1) Always
; P2/ Packet address, packet has been byte swapped
;
SC.ROU: SAVET ;Be sure we smash no ACs
LOAD T1,MH$MSG,(P2) ;Get the message type
CAIE T1,.STADG ;Is this an application message???
CAIN T1,.STAMG ; or application message
JRST SRO.CN ;Yes it is!! Skip status and min credit word
LOAD T1,MH$SMC,(P2) ;No... get the word uncommon to ADG and AMG
CALL SC.OSW ;Call the byte swapper
STOR T1,MH$SMC,(P2) ;Move the word back out to the header
SRO.CN: LOAD T1,MH$TYP,(P2) ;Lastly the credit and message type word
SKIPGE T1 ;Non-neg??? If yes, go handle the normal case
TXZ T1,<3B1> ;Else zero the bits that get in the way
CALL SC.OSW ;Byte swap this one too pls...
STOR T1,MH$TYP,(P2) ; and replace it in the header
RET ;All done...
SUBTTL Byte-swapping routines -- SC.OSW (Swap word from 10 to 11 format)
; This routine swaps individual words from PDP-10 format to PDP-11 format.
;Since these folks number funny we must do this oddity...
;
; Usage:
; Call
; T1/ Words to swap
;
; Return (+1) Always
; T1/ Byte swapped word
;
;Input format:
; 2 18 bit half words,
;
; !=======================================================!
; ! Byte A (msb+lsb) ! Byte B (msb +lsb) !
; !=======================================================!
; 0 17 18 35
;
;
;
;
; Output format:
; 2 16 bit half words, left justified
;
; !=======================================================!
; ! B (lsb) ! B (msb) ! A (lsb) ! A (msb) ! IGN !
; !=======================================================!
; 0 7 8 15 16 23 24 31 32 35
;
; Where A and B are the half words, and (lsb) are the least significant bits
;and (msb) are the most significant bits.
;
SC.OSW::LDB T2,TA$MSB ;Get ten byte A, MSB
LDB T3,TA$LSB ;Ten byte A, LSB
LDB T4,TB$MSB ;Ten byte B, MSB
LSH T1,^D28 ;Move ten byte B, LSB into correct position
DPB T4,EB$MSB ;Eleven byte B, MSB
DPB T3,EA$LSB ;Eleven byte A, LSB
DPB T2,EA$MSB ;Eleven byte A, MSB
RET ;All done return pls...
SUBTTL Locking/unlocking routines
SUBTTL Locking/unlocking routines -- SC.POF (Turn KLIPA channel off)
; This routine is the KLIPA channel controlling routine. it is called by what
;used to be a macro (CIOFF). The macro took no arguments so a CIOFF macro
;expansion or an inline call to this routine are equivalent.
;
; We are rather careful here about a few things. First check if we are at
;KLIPA interrupt level. If we are do nothing at all. If we are not at interrupt
;level but the channel is already off, go NOSKED to lock down the nesting
;counter and increment said counter. Do not set the PIFLAG however. If we are
;not at interrupt level and the channel is on, go NOSKED, increment the
;nesting counter, set PIFLAG, and turn off the channel.
;
; Usage:
; Call
; No arguments
;
; Return (+1) Always
; The KLIPA channel is either off, or we are at interrupt level
;
; *** Warning ***
; The pain factor for this routine is approximatly .96. Be sure you
;full understand it before trying to change it...
;
SC.POF::
IFN SCARNG,< ;If ring buffer recording is on
SAVEAC <T1,T2>
XMOVEI T1,. ;Get feature address
MOVE T2,-3(P) ;Get caller to this routine
CALL RG.PIT ;(T1,T2) Record the PI transition
> ;End of IFN SCARNG
IFE SCARNG, SAVEAC <T1>
CONI PI,T1 ;Get current PI state
TRNE T1,<1B25> ;Are we in KLIPA interrupt code???
RET ;Yes. Do nothing at all here
SKIPN CHNCTL ;If we have been here before, dont NOSKED again
NOSKED ;Be the only kid on the block
AOS CHNCTL ;Show another channel off has happened
TRNN T1,<1B33> ;Is the KLIPA channel already off???
RET ;Yes, return now
CHNOFF PHYCHN ;Turn off the CI channel
SETOM PIFLAG ;Show last CION that it must do channel on
RET ;Return all OK
SUBTTL Locking/unlocking routines -- SC.PON (Turn KLIPA channel on)
; This routine turns the KLIPA channel back on only if we are the outermost
;nesting level. It also checks that the outmost loop actually did a channel
;off (PIFLAG -- 0 indicates no channel off was done). Note that whenever
;the nest counter (CHNCTL) is changed we are NOSKED. This MUST be since
;CHNCTL is system wide not per process storage. Also note that we avoid doing
;redundant NOSKEDs by checking CHNCTL for previous invocations.
;
; Usage:
; Call
; No arguments
;
; Return (+1) Always
; Channel is off or you are already at KLIPA interrupt level
;
; *** Warning **
; The pain factor for this routine is approximatly .96. Be sure you
;understand it before you try to change it...
;
SC.PON::
IFN SCARNG,< ;If ring buffer recording is on
SAVEAC <T1,T2>
XMOVEI T1,. ;Get feature address
MOVE T2,-3(P) ;Get caller to this routine
CALL RG.PIT ;(T1,T2) Record the PI transition
> ;End of IFN SCARNG
IFE SCARNG, SAVEAC <T1>
CONI PI,T1 ;Get current PI state
TRNE T1,<1B25> ;Are we in KLIPA interrupt code???
RET ;Yes, we have nothing to do here
; Do nothing until we reach the outermost nesting of calls to SC.POF. This
;prevents routine A from going channel off, calling routine B which goes
;channel off and then channel on. The channel on done by routine B does
;nothing. The channel on done by routine A will actually turn on the channel.
;
SOSLE CHNCTL ;Is this an outermost CION in a nest???
RET ;No, do nothing
SKIPE CHNCTL
BUG. (HLT,SCAODI,SCAMPI,SOFT,<SCA - Overly decremented CI interlock>,,<
Cause: A CION was done when no previous CIOFF had occurred. This would lead to
an overly-decremented lock.
Action: If you are unable to determine how this happened, turn on the ring
buffer tracing of interlocks. (Do this by setting RPITRN in RINGSW.)
It should be possible to pair each CION with a preceding CIOFF.
Note that these calls are invoked from several CI-related modules.
>)
; Here at the outermost nesting level, I.E. the first routine to do the channel
;off. See if that channel off really did the CONO or was the channel off when
;we got there (I.E. did someone turn it off behind my back)...
;
SKIPE PIFLAG ;Should we really turn on the channel again?
JRST SPO.CO ;Yes, go turn on the channel
OKSKED ;No! But still at outer loop, go OKSKED
RET ; and return
; Here when that first channel off really did the CONO. Turn the channel
;back on and go OKSEKD..
;
SPO.CO: SETZM PIFLAG ;Clear channel on flag since we are about to
CHNON PHYCHN ;Turn on the CI channel once more
OKSKED ;Allow other kids onto the block again
RET ; and return
SUBTTL Locking/unlocking routines -- SC.LOK (Lock connection block)
;SC.LOK - lock a c.b.
;Accepts:
; P1/ address of c.b.
; CALL SC.LOK
;Returns +1: always
;Preserves all AC's.
;Caller usually needs to be CIOFF, since it wants to verify the
;existence of the connection block and then lock it without being
;interrupted.
SC.LOK: SZPI 1B25 ;Is channel 5 in progress?
RET ;Yes. Don't need a lock, then
NOSKED ;No. Make sure no one else can lock it
AOS .CBLCK(P1) ;Increment the lock
IFN SCARNG,<
SAVET ;Save temporary ACs
XMOVEI T1,. ;Get feature address
MOVE T2,-5(P) ;Get caller to this routine
CALL RG.ITL ;(T1,T2,P1/) Record the interlock call
> ;End of IFN SCARNG
RET
;SC.LAH - Lock and honor
;Accepts:
; T1/ bit to be set if lock is locked
; P1/ address of connection block
; CALL SC.LAH
;Returns +1: someone else has it locked
; +2: we got the lock
SC.LAH: SZPI 1B25 ;Is channel 5 interrupt in progress?
IFSKP.
NOSKED ;No. We get the lock
AOS .CBLCK(P1) ;Increment the lock
IFN SCARNG,<
SAVET ;Save temporary ACs
XMOVEI T1,. ;Get feature address
MOVE T2,-5(P) ;Get caller to this routine
CALL RG.ITL ;(T1,T2,P1/) Record the interlock call
> ;End of IFN SCARNG
RETSKP
ENDIF.
; JRST SC.HNR
;SC.HNR - honor the c.b. lock
;Accepts:
; T1/ bit to be set if it's locked
; P1/ address of connection block
; CALL SC.HNR
;Returns +1: someone else has the lock
; +2: we got the lock
;Caller must be at interrupt level
SC.HNR:
SKIPN .CBLCK(P1) ;Is it locked?
RETSKP ;No. We can proceed
IORM T1,.CBFLG(P1) ;Indicate what was deferred
IFN SCARNG,<
SAVET ;Save temporary ACs
XMOVEI T1,. ;Get feature address
MOVE T2,-5(P) ;Get caller to this routine
CALL RG.ITL ;(T1,T2,P1/) Record the interlock call
> ;End of IFN SCARNG
RET ;Return failure
SUBTTL Locking/unlocking routines -- SC.ULK (Unlock connection block)
;SC.ULK - Unlock the connection block
;Accepts:
; P1/ address of connection block
; CALL SC.ULK
;Returns +1: always
;Saves T1 because error code is in it
;We're NOSKED, so the reaper can't run and delete the connection block
SC.ULK: SZPI 1B25 ;Is interrupt on level 5 in progress?
RET ;Yes. Nothing to do, then
SAVEAC <T1,P3,P4,P5>
IFN SCARNG,<
BLOCK.
SAVET ;Save temporary ACs
XMOVEI T1,. ;Get feature address
MOVE T2,-13(P) ;Get caller to this routine
CALL RG.ITL ;(T1,T2,P1/) Record the interlock call
ENDBK.
> ;End of IFN SCARNG
MOVE T1,.CBLCK(P1) ;What's the current value of the lock?
CAIG T1,1 ;Quit if it's not 1
IFSKP.
SOS .CBLCK(P1) ;Decrement it
OKSKED ;Lock routine went NOSKED
RET ;Last unlocker will do the rest
ENDIF.
IFN SCADBG,<
SKIPG T1 ;Should never be less than 1
BUG. (HLT,SCAILC,SCAMPI,SOFT,<SCA - Illegal lock count in connection block>,,<
Cause: The routine to unlock a connection block has found that the count
is less than 1. Since the caller must have locked the connection
block earlier, something unexpected has happened.
>)
>
;Current value is 1. We will be the last unlocker. See what sorts of
;things have been deferred, and call the appropriate routines.
;Each processing routine clears its bit. If the bit gets set again while
;we're in here, we will detect that.
SETZB P3,P5 ;Initialize flags
MOVE P4,.CBSBA(P1) ;Get address of system block
;See if anything happened while we had this locked. Need to be CIOFF to
;avoid having the bit set after we make the check, and unlocking the
;c.b. without processing the deferred event.
SC.UL2: CIOFF ;Need to check for newly-set bits race-free
TMNN CBFDEF,(P1) ;Anything deferred?
JRST SC.UL6 ;No.
CION ;Yes.
;Test and handle each possible event. Node offline is first.
TMNN CBFERR,(P1) ;Deferred node offline?
IFSKP.
SETOM P5 ;Yes. Indicate we had deferred node offline
CALL SC.FN1 ;(P1,P4/) Do what's left to be done
ELSE.
TMNE CBFDIS,(P1) ;Sysap wanted disconnect?
CALL SC.FN2 ;(P1,P4/) Yes. Finish that
TMNE CBFDRQ,(P1) ;Disconnect_request arrived?
CALL SC.FN3 ;(P1,P4/) Yes. FInish that
ENDIF.
SC.UL3: TMNN CBFSNM,(P1) ;Wanted to send connect management request?
IFSKP.
SETZRO CBFSNM,(P1) ;Yes. Indicate no longer deferred
SETOM P3 ;Remember this
ENDIF.
JRST SC.UL2 ;See if anything new has come up
;Nothing left to do. Unlock the block.
SC.UL6: SOS .CBLCK(P1) ;Unlock the c.b.
CION
IFN SCADBG,<
SKIPE .CBLCK(P1) ;Better be zero now!
BUG. (HLT,SCALCC,SCAMPI,SOFT,<SCA - Connection block lock count has changed>,,<
Cause: The routine to unlock a connection block has found an inconsistency
in the lock count. Earlier in the routine, the current count was 1.
Now, after decrementing it, the count is not zero. Some other context
must have changed it, which should not happen since the locker is
NOSKED, and interrupt level code doesn't change the lock.
>)
>
OKSKED ;Lock routine went NOSKED
;If we had wanted to send a connection management request, do it
SKIPE P3
CALL SC.SNM ;(P4/) Send if there's anything to send
;If this block's node had gone offline, we have put off reopening the v.c.
;because of the locked c.b. If this is the last one to be unlocked, open
;the v.c.
SKIPN P5 ;Had we deferred node offline?
RET ;No.
SOSE .SBCLC(P4) ;Decrement system block count of locked c.b.'s
RET ;Still have more to go
SETZRO SBFOVC,(P4) ;No longer waiting to open
BLCAL. (OPENVC,<P4>) ;Let PHYKLP open the v.c.
RET
IFN SCARNG,<
SUBTTL Ring Buffer routines
SUBTTL Ring Buffer routines -- SC.RGI (Initialize ring buffer variables)
;This routine initializes the ring buffer
;
; Usage:
;
; CALL SC.RGI
;
; Returns: +1 Failure - could not allocate buffer space
; +2 Success
;
; No data is returned and no ACs are smashed.
SC.RGI: SAVEAC <T1,T2> ;Saved smashed ACs
MOVEI T1,RBFLEN ;Number of pages for ring buffer
CALL PGRSKD ;(T1/T1,T2) Get space from extended section
RET ;No space, return failure
IMULI T2,PGSIZ ;Compute actual size of ring buffer
MOVEM T2,RNGSIZ ;Save it
MOVEM T1,RNGTOP ;Save as top of ring buffer
MOVEM T1,RNGADR ;Also save as current pointer
ADD T1,RNGSIZ ;Add buffer size
SOS T1 ;Account for first word
MOVEM T1,RNGBOT ;Store as bottom of ring buffer
SETZM RNGCUR ;There are no completed entries yet
SETZM RNGNUM
RETSKP ;Return success
> ;End of IFN SCARNG
IFN SCARNG,<
SUBTTL Ring Buffer routines -- SC.RHD (Write ring buffer entry header)
;This routine will write the common entry header for a ring buffer entry
;
; Usage:
; T1/ FEATURE ROUTINE ADDRESS
; T2/ PC OF CALLER TO FEATURE ROUTINE
; T3/ EVENT CODE
; T4/ JACKET ROUTINE ADDRESS
;
; CALL SC.RHD
;
; Returns: +1 Always
;
; No data is returned and T1 and T2 are smashed.
;
;Note: This routine is designed to allow the ring buffer to wrap upon
; itself when it goes beyond RNGBOT. The entries will continue
; to be written starting from RNGTOP. A SCARAP BUGINF will be
; issued when the ring buffer wraps. This indicates that the entries
; at the top of the ring buffer are being overwritten.
;
; This routine has an explicit knowledge of the format of the ring
; buffer entry. The entry header is written in order. Should the
; header change, this routine will have to change as well.
SC.RHD: ASUBR <FRA,PCC,EVC,JKT> ;Save incoming args
MOVE T2,EVC ;Get the event code
CAIG T2,EN%CHI ;A valid event code?
CAIGE T2,EN%CLO
JRST SC.RHE ;No, return error
MOVE T1,RNGADR ;Get current pointer position
MOVEM T1,RNGCUR ;Save as the top of this new entry
ADD T1,ENTLTB(T2) ;Determine end of entry
SOS T1 ;Adjust since already pointing at first word
CAMG T1,RNGBOT ;Will it overflow?
IFSKP. ;Yes
MOVE T1,RNGTOP ;Get pointer to top of buffer
MOVEM T1,RNGADR ;Save as current pointer
MOVEM T1,RNGCUR ;Also as top of current entry
SKIPA 0 ;By default, do not report condition
;Do not issue SCARAP whenever the ring buffer wraps because certain settings
;of RNGSW will cause many SCARAPs to be issued. However, if reporting of
;this condition is desired, the above SKIPA instruction can be removed.
BUG.(INF,SCARAP,SCAMPI,SOFT,<SCA - Ring buffer has wrapped>,,<
Cause: The ring buffer has overflowed and has wrapped upon itself.
The entries at the top are now being overwritten and will be lost.
>) ;Report wraping of ring buffer
ENDIF.
MOVX T1,RNG%HC ;Get the constant for the ring header
CALL SC.RWR ;(T1) Place in ring buffer
MOVE T2,EVC ;Get event code
HRLZ T1,T2 ;Locate event code correctly
HRR T1,ENTLTB(T2) ;Put length in right half
CALL SC.RWR ;(T1) Place event code,,length in entry
MOVE T1,JKT ;Get jacket routine label
CALL SC.RWR ;(T1) Place in header
MOVE T1,FRA ;Get feature routine label
CALL SC.RWR ;(T1) Place in header
MOVE T1,PCC ;Get PC of caller to feature routine
CALL SC.RWR ;(T1) Place in header
MOVE T1,TODCLK ;Get time of day
CALL SC.RWR ;(T1) Place in entry header
RET ;Return success
SC.RHE: MOVE T1,FRA ;Get routine that called jacket routine
MOVE T2,PCC ;Get PC of caller to feature routine
MOVE T3,EVC ;Get event code
MOVE T4,JKT ;Get jacket routine address
BUG.(HLT,SCAIEC,SCAMPI,SOFT,<SCA - Invalid event code for ring buffer entry>,<<T1,FEATURE>,<T2,PC>,<T3,ENTRY>,<T4,JACKET>>,<
Cause: A bad event code was passed to SC.RHD to be placed in the ring buffer
header. This could cause problems since the entry length table is
indexed by event code.
Action: Check the caller of SC.RHD, indicated by the jacket routine address
in T4, to be sure that a valid event code is being placed in
T3 before the call.
Data: FEATURE - feature routine address
PC - PC of caller to feature routine
ENTRY - entry code
JACKET - jacket routine address
>) ;Report error and die
> ;End of IFN SCARNG
IFN SCARNG,<
SUBTTL Ring Buffer routines -- SC.RTE (Write ring buffer entry tail)
;This routine will write the common tail of a ring buffer entry
;
; Usage:
; CALL SC.RTE
;
; Returns: +1 Always
;
; No data is returned and T1 is smashed.
SC.RTE: MOVE T1,RNGCUR ;Get pointer to top of this entry
CALL SC.RWR ;(T1) Place in ring buffer entry tail
AOS RNGNUM ;Increment number of buffer entries written
RET ;Return success
> ;End of IFN SCARNG
IFN SCARNG,<
SUBTTL Ring Buffer routines -- SC.RWR (Write ring buffer entry)
;This routine will write a word of a ring buffer entry
;
; Usage:
; T1/ WORD TO WRITE
;
; CALL SC.RWR
;
; Returns: +1 Always
;
; No data is returned and no ACs are smashed.
SC.RWR: MOVEM T1,@RNGADR ;Put word in ring buffer entry
AOS RNGADR ;Increment pointer to next location
RET ;Return success
> ;End of IFN SCARNG
IFN SCARNG,<
SUBTTL Ring Buffer routines -- RG.SSC (SYSAP to SCA calls)
;This routine is used to record SYSAP to SCA calls in the ring buffer
;
; Usage:
; T1/ FEATURE ROUTINE ADDRESS
; T2/ PC OF CALLER TO FEATURE ROUTINE
; T3/ ADDRESS OF CONNECT BLOCK
;
; CALL RG.SSC
;
; Returns: +1 Always
RG.SSC: TMNN RSYSCA ;Are we recording these events?
RET ;No, just return
CIOFF ;Do not allow any interrupts
SAVET ;Make routine transparent
STKVAR <CBADDR>
MOVEM T3,CBADDR ;Save CB address
MOVEI T3,SYSSCA ;Get event code
XMOVEI T4,. ;Get jacket routine address
CALL SC.RHD ;(T1,T2,T3,T4) Write the entry header
MOVE T1,CBADDR ;Get CB address
LOAD T1,CBSCID,(T1) ;Get source connect ID
CALL SC.NOD ;(T1/T1,T2) Get node number
EXCH T1,T2 ;Get node number in T1
CALL SC.RWR ;(T1) Record node number in entry
MOVE T1,CBADDR ;Get CB address
CALL SC.RWR ;(T1) Record in entry
MOVE T2,T1 ;Move CB address
MOVE T1,.CBSTS(T2) ;Get CB status word
CALL SC.RWR ;(T1) Record in entry
MOVE T1,.CBFLG(T2) ;Get flags
CALL SC.RWR ;(T1) Record in entry
LOAD T1,CBSCID,(T2) ;Get source connect ID
CALL SC.RWR ;(T1) Record in entry
LOAD T1,CBDCID,(T2) ;Get destination connect ID
CALL SC.RWR ;(T1) Record in entry
CALL SC.RTE ;() Write the ring entry tail
CION ;Enable interrupts again
RET ;Return
ENDSV.
> ;End of IFN SCARNG
IFN SCARNG,<
SUBTTL Ring Buffer routines -- RG.SCS (SCA to SYSAP calls)
;This routine is used to record SCA to SYSAP calls (callbacks)
;in the ring buffer
;
; Usage:
; T1/ FEATURE ROUTINE ADDRESS
; T2/ PC OF CALLER TO FEATURE ROUTINE
; T3/ CALLBACK REASON CODE
; P1/ CONNECT BLOCK ADDRESS
;
; CALL RG.SCS
;
; Returns: +1 Always
RG.SCS: TMNN RSCASY ;Are we recording these events?
RET ;No, just return
CIOFF ;Do not allow any interrupts
SAVET ;Make routine transparent
STKVAR <REASON>
MOVEM T3,REASON ;Save reason code
MOVEI T3,SCASYS ;Get event code
XMOVEI T4,. ;Get jacket routine address
CALL SC.RHD ;(T1,T2,T3,T4) Write the entry header
LOAD T1,CBSCID,(P1) ;Get source connect ID
CALL SC.NOD ;(T1/T1,T2) Get node number
MOVE T1,T2 ;Relocate node number
CALL SC.RWR ;(T1) Place in entry
MOVE T1,P1 ;Get connect block address
CALL SC.RWR ;(T1) Place in entry
MOVE T1,REASON ;Get callback reason code
CALL SC.RWR ;(T1) Place in entry
CALL SC.RTE ;() Write the ring entry tail
CION ;Enable interrupts again
RET ;Return
ENDSV.
> ;End of IFN SCARNG
IFN SCARNG,<
SUBTTL Ring Buffer routines -- RG.BFM (Buffer manipulation)
;This routine is used to record buffer allocation, creation, and return.
;All calls to SC.CMG, SC.CDG, SC.ABF, SC.ALD, SC.RBF, and SC.RLD
;are recorded.
;
; Usage:
; T1/ FEATURE ROUTINE ADDRESS
; T2/ PC OF CALLER TO FEATURE ROUTINE
; T3/ NUMBER OF BUFFERS REQUESTED FOR CREATION/ALLOCATION
; T4/ ADDRESS OF FIRST BUFFER CREATED/ALLOCATED
;
; CALL RG.BFM
;
; Returns: +1 Always
RG.BFM: TMNN RBUFMG ;Are we recording these events?
RET ;No, just return
CIOFF ;Do not allow any interrupts
SAVET ;Make routine transparent
STKVAR <NUMBUF,ADDR>
MOVEM T3,NUMBUF ;Save number of buffers
MOVEM T4,ADDR ; and address of first buffer on chain
MOVEI T3,BUFMAN ;Get event code
XMOVEI T4,. ;Get jacket routine address
CALL SC.RHD ;(T1,T2,T3,T4) Write the entry header
MOVE T1,NUMBUF ;Get number of buffers requested
CALL SC.RWR ;(T1) Place in entry
MOVE T1,ADDR ;Get address of first buffer in chain
CALL SC.RWR ;(T1) Place in entry
MOVE T1,FQCNT ;Get number of buffers on message free queue
CALL SC.RWR ;(T1) Place in entry
MOVE T1,TOPFQ ;Get pointer to top of message free queue
CALL SC.RWR ;(T1) Place in entry
MOVE T1,BOTFQ ;Get pointer to bottom of message free queue
CALL SC.RWR ;(T1) Place in entry
MOVE T1,DFQCNT ;Get number of buffers on datagram queue
CALL SC.RWR ;(T1) Place in entry
MOVE T1,TOPDFQ ;Get pointer to top of datagram free queue
CALL SC.RWR ;(T1) Place in entry
MOVE T1,BOTDFQ ;Get pointer to bottom of datagram free queue
CALL SC.RWR ;(T1) Place in entry
CALL SC.RTE ;() Write the ring entry tail
CION ;Enable interrupts again
RET ;Return
ENDSV.
> ;End of IFN SCARNG
IFN SCARNG,<
SUBTTL Ring Buffer routines -- RG.PKT (Packet movement)
;This routine is used to record packet movement; both outgoing
;(calls to SNDMSG and SNDDG) and incoming (arriving at SC.INT).
;
; Usage:
; T1/ FEATURE ROUTINE ADDRESS
; T2/ PC OF CALLER TO FEATURE ROUTINE
; T3/ FLAGS,,
; T4/ PRIORITY,,PACKET LENGTH
; P2/ PACKET ADDRESS
; P4/ SYSTEM BLOCK ADDRESS
;
; CALL RG.PKT
;
; Returns: +1 Always
RG.PKT: TMNN RPACKT ;Are we recording these events?
RET ;No, just return
CIOFF ;Do not allow any interrupts
SAVET ;Make routine transparent
STKVAR <FLAGS,PRPL>
MOVEM T3,FLAGS ;Save flags
MOVEM T4,PRPL ; and priority,,packet length
MOVEI T3,PKTEVT ;Get event code
XMOVEI T4,. ;Get jacket routine address
CALL SC.RHD ;(T1,T2,T3,T4) Write the entry header
LOAD T1,SBDPA,(P4) ;Get node number
CALL SC.RWR ;(T1) Place in entry
MOVE T1,RNGCUR ;Get address if top of entry
HRRZ T1,.REFRL(T1) ;Get feature routine label
CAIN T1,SCINT ;Did the entry come from SCINT (incoming)?
IFSKP.
LOAD T1,MH$SCI,(P2) ;No, outgoing packet, use source CID always
ELSE.
MOVE T1,FLAGS ;Yes, incoming packet, get flags
TXNN T1,F.RSP ;Is this a local or remote packet?
IFSKP. ;It is local
LOAD T1,MH$SCI,(P2) ;Get source connect ID
ELSE. ;It is a remote packet
LOAD T1,MH$DCI,(P2) ;Get destination connect ID
ENDIF.
ENDIF.
$LDCID T1,T1 ;Obtain connect block address
CALL SC.RWR ;(T1) Place in entry
MOVE T1,P2 ;Get buffer address
CALL SC.RWR ;(T1) Place in entry
MOVE T1,FLAGS ;Get flags
CALL SC.RWR ;(T1) Place in entry
MOVE T1,PRPL ;Get priority,,packet length
CALL SC.RWR ;(T1) Place in entry
LOAD T1,MH$TYP,(P2) ;Get message type word
CALL SC.RWR ;(T1) Place in entry
LOAD T1,MH$SCI,(P2) ;Get source connect ID
CALL SC.RWR ;(T1) Place in entry
LOAD T1,MH$DCI,(P2) ;Get destination connect ID
CALL SC.RWR ;(T1) Place in entry
CALL SC.RTE ;() Write the ring entry tail
CION ;Enable interrupts again
RET ;Return
ENDSV.
> ;End of IFN SCARNG
IFN SCARNG,<
SUBTTL Ring Buffer routines -- RG.PIT (PI transitions)
;This routine is used to record PI transitions.
;
; Usage:
; T1/ FEATURE ROUTINE ADDRESS
; T2/ PC OF CALLER TO FEATURE ROUTINE
;
; CALL RG.PIT
;
; Returns: +1 Always
;
;Note: There are no CIONs or CIOFFs in this jacket routine since it is
; designed to be called from the routines CION and CIOFF.
RG.PIT: TMNN RPITRN ;Are we recording these events?
RET ;No, just return
SAVET ;Make routine transparent
MOVEI T3,PITRAN ;Get event code
XMOVEI T4,. ;Get jacket routine address
CALL SC.RHD ;(T1,T2,T3,T4) Write the entry header
MOVE T1,CHNCTL ;Get level of PI nesting
CALL SC.RWR ;(T1) Record it in the entry
MOVE T1,PIFLAG ;Get indication of channel on done
CALL SC.RWR ;(T1) Record it in the entry
CALL SC.RTE ;() Write the ring entry tail
RET ;Return
> ;End of IFN SCARNG
IFN SCARNG,<
SUBTTL Ring Buffer routines -- RG.PQM (Port queue manipulation)
;This routine is used to record port queue manipulation
;
; Usage:
; T1/ FEATURE ROUTINE ADDRESS
; T2/ PC OF CALLER TO FEATURE ROUTINE
; T3/ FLAGS,,COUNT OF BUFFERS UNLINKED/LINKED
; (SEE SCAPAR FOR FLAG DEFINITIONS)
; T4/ ADDRESS OF FIRST BUFFER UNLINKED/LINKED
; P4/ ADDRESS OF SYSTEM BLOCK
;
; CALL RG.PQM
;
; Returns: +1 Always
RG.PQM: TMNN RPRTQU ;Are we recording these events?
RET ;No, just return
CIOFF ;Do not allow any interrupts
SAVET ;Make routine transparent
STKVAR <COUNT,ADDR>
MOVEM T3,COUNT ;Save buffer count
MOVEM T4,ADDR ; and address of first buffer in chain
MOVEI T3,PORTQU ;Get event code
XMOVEI T4,. ;Get jacket routine address
CALL SC.RHD ;(T1,T2,T3,T4) Write the entry header
LOAD T1,SBDPA,(P4) ;Get node number
CALL SC.RWR ;(T1/) Place in entry
MOVE T1,COUNT ;Get flags,,count word
CALL SC.RWR ;(T1/) Place in entry
MOVE T1,ADDR ;Get buffer address
CALL SC.RWR ;(T1/) Place in entry
CALL SC.RTE ;() Write the ring entry tail
CION ;Enable interrupts again
RET ;Return
ENDSV.
> ;End of IFN SCARNG
IFN SCARNG,<
SUBTTL Ring Buffer routines -- RG.ITL (Interlocks)
;This routine is used to record interlocks.
;
; Usage:
; T1/ FEATURE ROUTINE ADDRESS
; T2/ PC OF CALLER TO FEATURE ROUTINE
; P1/ CONNECT BLOCK ADDRESS
;
; CALL RG.ITL
;
; Returns: +1 Always
;
; Note: It is assumed that the caller has done a SAVET before the call!
RG.ITL: TMNN RINTLK ;Are we recording these events?
RET ;No, just return
CIOFF ;Do not allow any interrupts
MOVEI T3,INTLOK ;Get event code
XMOVEI T4,. ;Get jacket routine address
CALL SC.RHD ;(T1,T2,T3,T4) Write the entry header
MOVE T1,P1 ;Get connect block address
CALL SC.RWR ;(T1/) Place in entry
MOVE T1,.CBLCK(P1) ;Get connect block lock value
CALL SC.RWR ;(T1/) Place in entry
MOVE T1,.CBFLG(P1) ;Get all connect block flags
CALL SC.RWR ;(T1/) Place in entry
MOVE T1,.CBSBA(P1) ;Get address of system block
MOVE T1,.SBCLC(T1) ;Get count of locked connect blocks on S.B.
CALL SC.RWR ;(T1/) Place in entry
CALL SC.RTE ;() Write the ring entry tail
CION ;Enable interrupts again
RET ;Return
> ;End of IFN SCARNG
; Routine to copy a strings and blank fill
;
;Usage:
; T3/ Destination address
; T4/ Source address
; Always transfers C%PNMN bytes
; CALL SCG.ST
;
; Return +1 Always
;
SCG.ST: MOVEI T2,C%PNMN ;Number of characters to move
SCG.LP: ILDB T1,T4 ;Get a character from the source
JUMPE T1,SCG.NL ;Found a 0 space fill
IDPB T1,T3 ;Store character in the Destination
SOJG T2,SCG.LP ;Try for another character
RET ;Done return
SCG.NL: MOVX T1," " ;Get a space as padding character
IDPB T1,T3 ;Store it in the Destination
SOJG T2,.-1 ;Do until count runs out
RET ;Return to caller all done
SUBTTL Dummy routines until the port driver supports them
PPDSMD::
PPDRMD::RETBAD (MONX03)
SUBTTL End of SCS
END