Google
 

Trailing-Edge - PDP-10 Archives - tops20_version7_0_monitor_sources_clock - monitor-sources/phyklp.mac
There are 21 other files named phyklp.mac in the archive. Click here to see a list.
; UPD ID= 8714, RIP:<7.MONITOR>PHYKLP.MAC.16,  17-May-88 14:24:57 by RASPUZZI
;TCO 7.1288 - Resurrect routine SANCHK by making it do what it did at one
;	      time. It may cause CI timing problems but it is under the
;	      KLPDBG conditional anyway.
; UPD ID= 8661, RIP:<7.MONITOR>PHYKLP.MAC.15,  22-Feb-88 18:48:34 by GSCOTT
;TCO 7.1238 - Set KLPILP, KLPIPA, and KLPUMV normally not dumpable.
; UPD ID= 8585, RIP:<7.MONITOR>PHYKLP.MAC.14,  11-Feb-88 16:54:23 by GSCOTT
;TCO 7.1218 - Update copyright date.
; UPD ID= 8459, RIP:<7.MONITOR>PHYKLP.MAC.13,   5-Feb-88 09:20:55 by GSCOTT
;More of TCO 7.1210 - Fix spelling in KLPMCE
; UPD ID= 8455, RIP:<7.MONITOR>PHYKLP.MAC.12,   4-Feb-88 22:01:42 by GSCOTT
;More of TCO 7.1210 - Set KLPMVW to not normally dumpable.
; UPD ID= 8432, RIP:<7.MONITOR>PHYKLP.MAC.11,   4-Feb-88 14:33:12 by GSCOTT
;TCO 7.1210 - Set CIPDFQ, KLPCBN, KLPCBS, KLPCGN, KLPCKE, KLPCRR, KLPCSR,
; KLPCVC, KLPDED, KLPDPP, KLPDRQ, KLPDUM, KLPEBP, KLPEBQ, KLPELT, KLPEPB,
; KLPERE, KLPERQ, KLPERR, KLPFST, KLPHNG, KLPIBN, KLPINP, KLPIRD, KLPIRP,
; KLPLBF, KLPLOA, KLPMBS, KLPMCE, KLPMCR, KLPNDE, KLPNDG, KLPNEN, KLPNMG,
; KLPNOA, KLPOPC, KLPOVC, KLPPIA, KLPPLS, KLPPPD, KLPPPE, KLPRAE, KLPRCE,
; KLPRRQ, KLPRSF, KLPRSH, KLPSCE, KLPSCR, KLPSDM, KLPSRL, KLPSRM, KLPSTP,
; KLPSTR, KLPSWC, KLPSWO, KLPTAE, KLPTMO, KLPTPE, KLPUCP, KLPUMV, KLPUPC,
; KLPWAB, KLPWAG, KLPWBB, KLPWBG, and KLPWIR not dumpable.
; UPD ID= 8397, RIP:<7.MONITOR>PHYKLP.MAC.10,  28-Jan-88 14:48:27 by RASPUZZI
;TCO 7.1202 - Add KLPENT. This word will hold the high precision time when
;             PHYKLP's interrupt service routine was entered. Similar to
;             NISRV's ENTINT.
; UPD ID= 317, RIP:<7.MONITOR>PHYKLP.MAC.9,   3-Dec-87 14:56:51 by RASPUZZI
;TCO 7.1156 - Correct typo under debug conditional from previous edit
; UPD ID= 296, RIP:<7.MONITOR>PHYKLP.MAC.8,  12-Nov-87 16:57:55 by GSCOTT
;TCO 7.1134 - Handle CI20 microcode versions properly, repaginate.
; UPD ID= 251, RIP:<7.MONITOR>PHYKLP.MAC.7,   4-Nov-87 16:43:04 by MCCOLLUM
;TCO 7.1112 - Look for IPALOD on BS: instead of PS:
; UPD ID= 164, RIP:<7.MONITOR>PHYKLP.MAC.6,  19-Oct-87 17:15:30 by LOMARTIRE
;TCO 7.1072 - Add IS7020; used by the cluster-wide ENQ and CLUDGR projects
; UPD ID= 74, RIP:<7.MONITOR>PHYKLP.MAC.5,  12-Aug-87 14:48:25 by MCCOLLUM
;TCO 7.1037 - Set up SBLIST with 30-bit values. Use MSEC1 for section number.
; UPD ID= 41, RIP:<7.MONITOR>PHYKLP.MAC.4,  15-Jul-87 14:40:41 by LOMARTIRE
;TCO 7.1021 - Fix CLOSV4 to KLPDMP BUGHLT if cluster dump is in progress
; UPD ID= 7, RIP:<7.MONITOR>PHYKLP.MAC.3,  28-May-87 16:09:42 by RASPUZZI
;TCO 7.1002 - Implement PMOVE/M instructions.
; *** Edit 7444 to PHYKLP.MAC by LOMARTIRE on 13-Apr-87, for SPR #21550
; Prevent KLPNOM and KLPHOG BUGHLTs when RH20 in slot 7 
; *** Edit 7422 to PHYKLP.MAC by RASPUZZI on 10-Mar-87, for SPR #21395
; Use major and minor verion number when sending software version to remote
; nodes on CI.
; *** Edit 7255 to PHYKLP.MAC by GRANT on 10-Mar-86
; Put correct reason code in READ-COUNTERS packet after a planned CRAM CPE 
; *** Edit 7238 to PHYKLP.MAC by GRANT on 7-Feb-86
; Prevent extraneous reload of CI when link board problem is happening 
; *** Edit 7237 to PHYKLP.MAC by GRANT on 7-Feb-86
; In WIRBAD, decide to reload earlier so CFRECNs don't result 
; *** Edit 7223 to PHYKLP.MAC by GRANT on 7-Jan-86
; Make sure port is stopped in STPKLP 
; *** Edit 7211 to PHYKLP.MAC by GRANT on 18-Dec-85
; Add CI counters for WATCH 
; *** Edit 7210 to PHYKLP.MAC by GRANT on 18-Dec-85, for SPR #20924
; Reload CI when LINK BOARD arbitration timeout problem occurs 
; *** Edit 7185 to PHYKLP.MAC by GRANT on 5-Nov-85
; Prevent KPALVH BUGHLT at system start up when KL is CI node number 15 
; Edit 7134 to PHYKLP.MAC by GRANT on 15-Aug-85 (TCO 6-1-1522)
; Turn off the NI at BUGHLT and PAR>SHUT time 
; Edit 7126 to PHYKLP.MAC by GRANT on 13-Aug-85 (TCO 6-1-1518)
; Recover from unplanned CRAM parity error 
; Edit 7121 to PHYKLP.MAC by GRANT on 12-Aug-85 (TCO 6-1-1511)
; Fix powerfail/restart for CI 
; UPD ID= 2291, SNARK:<6.1.MONITOR>PHYKLP.MAC.259,  29-Jun-85 22:59:05 by GRANT
;TCO 6.1.1477 - Clean up loading the CI microcode
; UPD ID= 2279, SNARK:<6.1.MONITOR>PHYKLP.MAC.258,  25-Jun-85 14:59:22 by GRANT
;TCO 6.1.1473 - Forget about NO-ANSWER and use maintenance state for diags.
;Also, listing cleanup.
; UPD ID= 2254, SNARK:<6.1.MONITOR>PHYKLP.MAC.257,  20-Jun-85 18:03:34 by GRANT
;TCO 6.1.1467 - don't need READ-COUNTER to get ucode version anymore
; UPD ID= 2244, SNARK:<6.1.MONITOR>PHYKLP.MAC.256,  19-Jun-85 17:48:31 by GRANT
;TCO 6.1.1462 - Prevent CIPDFQ BUGINFs.  Create new entry point KLPRQC into
;routine KLPRQA and call it to process the response queue without enabling
;the port.
; UPD ID= 2222, SNARK:<6.1.MONITOR>PHYKLP.MAC.255,  12-Jun-85 18:01:30 by GRANT
;TCO 6.1.1446 - Stop sending STARTs if REQUEST-IDs are no longer being answered.
;Other minor changes involving REQUEST-ID handling.
;Change KLPNOR to KLPNOA and update its documentation.
;Also, save the result of the CONI that's done in KLPCHK.
;Change IPAFOO back to IPALOD.
; UPD ID= 2156, SNARK:<6.1.MONITOR>PHYKLP.MAC.254,   5-Jun-85 10:39:09 by MCCOLLUM
;TCO 6.1.1406  - Update copyright notice.
; UPD ID= 2006, SNARK:<6.1.MONITOR>PHYKLP.MAC.253,  24-May-85 12:19:01 by MCCOLLUM
;Fix KLPLOA BUG.
; UPD ID= 1979, SNARK:<6.1.MONITOR>PHYKLP.MAC.252,  15-May-85 14:22:00 by GRANT
;TCO 6.1.1378 - At KLPINI, check for KLIPAness before zapping channel
; UPD ID= 1978, SNARK:<6.1.MONITOR>PHYKLP.MAC.251,  14-May-85 17:49:36 by GRANT
;TCO 6.1.1379 - put KLPNMG and KLPNDG under CIBUGX control
; UPD ID= 1966, SNARK:<6.1.MONITOR>PHYKLP.MAC.250,  13-May-85 10:13:14 by GRANT
;TCO 6.1.1377 - Create routines KLPUCD and LODUCD.  Don't signal CIFORK anymore
;because monitor now loads the CI ucode.
; UPD ID= 1919, SNARK:<6.1.MONITOR>PHYKLP.MAC.249,   7-May-85 20:57:03 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1864, SNARK:<6.1.MONITOR>PHYKLP.MAC.248,   3-May-85 10:57:58 by GRANT
;Put KLPIBN BUGINF under CIBUGX 
; UPD ID= 1853, SNARK:<6.1.MONITOR>PHYKLP.MAC.247,  30-Apr-85 14:47:47 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1739, SNARK:<6.1.MONITOR>PHYKLP.MAC.246,   9-Apr-85 12:06:04 by MCCOLLUM
;TCO 6.1.1238 - Fix BUG. documentation
; UPD ID= 1720, SNARK:<6.1.MONITOR>PHYKLP.MAC.245,   8-Apr-85 07:44:12 by GRANT
;TCO 6.1.1310 - Add routine NOANSR to test ucode's diagnostic NO-ANSWER bit
; UPD ID= 1673, SNARK:<6.1.MONITOR>PHYKLP.MAC.244,  25-Mar-85 08:21:32 by GRANT
;TCO 6.1.1284 - Set CILD instead of JB0FLG
; UPD ID= 1645, SNARK:<6.1.MONITOR>PHYKLP.MAC.243,  18-Mar-85 10:06:43 by GRANT
;TCO 6.1.1273 - In CHKWIR, send only 1 loopback per second
; UPD ID= 1594, SNARK:<6.1.MONITOR>PHYKLP.MAC.242,   6-Mar-85 06:32:44 by GRANT
;Change JSR BUGHLTs to real BUG. for release.
; UPD ID= 1519, SNARK:<6.1.MONITOR>PHYKLP.MAC.241,  13-Feb-85 14:56:20 by GRANT
;TCO 6.1.1198 - In CHKOPC, remove the check for closed virutal circuits.
; UPD ID= 1498, SNARK:<6.1.MONITOR>PHYKLP.MAC.240,  11-Feb-85 09:02:17 by GRANT
;TCO 6.1.1184 - Create routine ISIT20
; UPD ID= 1490, SNARK:<6.1.MONITOR>PHYKLP.MAC.239,   8-Feb-85 08:29:10 by LOMARTIRE
;More TCO 6.1.1096 - Move the .CFHSC function of CNFIG% to PHYMSC
; UPD ID= 1455, SNARK:<6.1.MONITOR>PHYKLP.MAC.238,   1-Feb-85 14:42:55 by GRANT
;Undo TCO 6.1.1151 - put the calls to PHYSTC back in
; UPD ID= 1453, SNARK:<6.1.MONITOR>PHYKLP.MAC.237,   1-Feb-85 14:19:58 by LOMARTIRE
;Change the priority used by CLOBUF and SNDREC
; UPD ID= 1394, SNARK:<6.1.MONITOR>PHYKLP.MAC.236,  22-Jan-85 21:21:47 by GRANT
;TCO 6.1.1151 - Remove unnecessary calls to PHYSTC
; UPD ID= 1368, SNARK:<6.1.MONITOR>PHYKLP.MAC.235,  21-Jan-85 10:21:00 by GRANT
;Change KLPERR from BUGCHK to BUGINF
; UPD ID= 1263, SNARK:<6.1.MONITOR>PHYKLP.MAC.234,   4-Jan-85 08:10:53 by GRANT
;TCO 6.1.1108 - Add ability to boot system ignoring KLIPA and then later use it.
; UPD ID= 1256, SNARK:<6.1.MONITOR>PHYKLP.MAC.233,   2-Jan-85 09:05:14 by LOMARTIRE
;More TCO 6.1.1096 - Use .CFNHN instead of .CFNND
; UPD ID= 1248, SNARK:<6.1.MONITOR>PHYKLP.MAC.232,  31-Dec-84 09:33:51 by LOMARTIRE
;TCO 6.1.1096 - Add the .CFHSC function code for CNFIG% to return HSC node names
; UPD ID= 1204, SNARK:<6.1.MONITOR>PHYKLP.MAC.231,  13-Dec-84 07:06:39 by GRANT
;TCO 6.1.1086 - Change KLPNUP to KLPOVC and add KLPCVC.
; UPD ID= 1059, SNARK:<6.1.MONITOR>PHYKLP.MAC.230,  13-Nov-84 09:06:26 by LOMARTIRE
;Use new priority symbols KLPHI, KLPMED, KLPLOW, KLPDRG
; UPD ID= 991, SNARK:<6.1.MONITOR>PHYKLP.MAC.229,   7-Nov-84 13:44:21 by GRANT
;TCO 6.2272 - After a KLPHNG, go CIOFF and clean the queues.
; UPD ID= 985, SNARK:<6.1.MONITOR>PHYKLP.MAC.228,   7-Nov-84 10:40:56 by GRANT
;TCO 6.2270 - In CPEDON, retrieve the CSR from the CDB.
; UPD ID= 5033, SNARK:<6.MONITOR>PHYKLP.MAC.227,  29-Oct-84 14:29:36 by HAUDEL
;In UMAP, check for the existence of the BHD before unmapping. Mutiple unmaps
;of the same buffer destroy the BSD linked list table.
; UPD ID= 5028, SNARK:<6.MONITOR>PHYKLP.MAC.226,  29-Oct-84 07:58:38 by GRANT
;In SCAERR, BUGINF if the error is Invalid Buffer Name
; UPD ID= 5023, SNARK:<6.MONITOR>PHYKLP.MAC.225,  28-Oct-84 08:50:31 by GRANT
;In KLPNLF and KLPNDF, check for no KLIPA on system
; UPD ID= 5012, SNARK:<6.MONITOR>PHYKLP.MAC.224,  26-Oct-84 07:56:01 by GRANT
;In SCAERR, don't close VC if error is Invalid Buffer Name
; UPD ID= 4996, SNARK:<6.MONITOR>PHYKLP.MAC.223,  24-Oct-84 19:59:46 by GRANT
;In STRTDT, use new symbol SCAVER
; UPD ID= 4986, SNARK:<6.MONITOR>PHYKLP.MAC.222,  24-Oct-84 05:52:10 by GRANT
;In INTERP, increase KELEN so we don't have to truncate the text so often.
; UPD ID= 4955, SNARK:<6.MONITOR>PHYKLP.MAC.221,  18-Oct-84 14:48:38 by GRANT
;Keep node name in SB.
; UPD ID= 4923, SNARK:<6.MONITOR>PHYKLP.MAC.220,  11-Oct-84 21:20:56 by GRANT
;In PTHSTS, make sure we have a KLIPA before proceeding
; UPD ID= 4909, SNARK:<6.MONITOR>PHYKLP.MAC.219,  10-Oct-84 15:10:21 by GRANT
;At INTER2, wrong length being passed to SEBCPY.  Use P3 instead of WORDS.
; UPD ID= 4905, SNARK:<6.MONITOR>PHYKLP.MAC.218,   8-Oct-84 18:20:28 by GRANT
;Routine EP2BUG needs a RET
; UPD ID= 4904, SNARK:<6.MONITOR>PHYKLP.MAC.217,   8-Oct-84 18:17:48 by GRANT
;Use RSI to initialize KLPOWN, RIDTMO, and SSTTMO.
;In KLPINT, make ERROR.SYS entry and output BUGxxx before telling SCA that
;the port is gone.
; UPD ID= 4897, SNARK:<6.MONITOR>PHYKLP.MAC.216,   6-Oct-84 06:50:50 by GRANT
;Reorder KLPOPS and associated tables
; UPD ID= 4893, SNARK:<6.MONITOR>PHYKLP.MAC.215,   2-Oct-84 09:35:30 by GRANT
;In INTERP, make ERROR.SYS entry 246 for ERROR-LOG-MESSAGE packet (PPD byte 5)
; UPD ID= 4887, SNARK:<6.MONITOR>PHYKLP.MAC.214,  26-Sep-84 17:38:26 by GRANT
;RCTPER needs to be an RSI
; UPD ID= 4886, SNARK:<6.MONITOR>PHYKLP.MAC.213,  26-Sep-84 17:29:13 by GRANT
;Minor adjustment to KLPRCT
; UPD ID= 4885, SNARK:<6.MONITOR>PHYKLP.MAC.212,  26-Sep-84 16:40:44 by GRANT
;Create routine KLPRCT to be called from CHKR
; UPD ID= 4878, SNARK:<6.MONITOR>PHYKLP.MAC.211,  25-Sep-84 14:02:03 by GRANT
;Decrease NDSTIM from 30 to 10 seconds
; UPD ID= 4876, SNARK:<6.MONITOR>PHYKLP.MAC.210,  25-Sep-84 12:05:21 by HAUDEL
;Get the status word (.PKSTS) to determine the formatting mode at GIVSC6:
; UPD ID= 4868, SNARK:<6.MONITOR>PHYKLP.MAC.209,  24-Sep-84 16:12:23 by GRANT
;Do a READ-COUNTERS whenever a CI wire status change takes place and make an
;ERROR.SYS entry which contains the counters returns.
;Use DEFSTR CDVER.
; UPD ID= 4854, SNARK:<6.MONITOR>PHYKLP.MAC.208,  17-Sep-84 15:31:06 by GRANT
;Make KLPSWO and KLPRSH BUGINFs instead of CHKs.
;Revise DISKLP and create a special entry point for KIKKLP so we don't start
;the KLIPA at funny addresses.
; UPD ID= 4822, SNARK:<6.MONITOR>PHYKLP.MAC.207,  17-Sep-84 10:42:41 by PURRETTA
;Update copyright notice
; UPD ID= 4776, SNARK:<6.MONITOR>PHYKLP.MAC.206,  30-Aug-84 08:26:32 by GRANT
;In CLNCOM, don't call STSHIT anymore.
;Fix CIONLT.
; UPD ID= 4764, SNARK:<6.MONITOR>PHYKLP.MAC.205,  28-Aug-84 10:12:40 by GRANT
;After calling RETCLO, continue with the rest of the response queue
; UPD ID= 4762, SNARK:<6.MONITOR>PHYKLP.MAC.204,  27-Aug-84 16:30:07 by HALL
;In KLPRQA, use the correct AC to transfer through RETCLO
; UPD ID= 4751, SNARK:<6.MONITOR>PHYKLP.MAC.203,  24-Aug-84 17:43:11 by MCLEAN
;get previous edit right....
; UPD ID= 4748, SNARK:<6.MONITOR>PHYKLP.MAC.202,  24-Aug-84 13:45:28 by MCLEAN
;FIX PTHSTS NOT TO NEED P1
; UPD ID= 4735, SNARK:<6.MONITOR>PHYKLP.MAC.201,  23-Aug-84 20:30:26 by HALL
;Get the port to use both paths on free choice after a REQID or loopback
;	succeeds
;	INTLPB - OPEN BOTH PATHS ON ALL OPEN V.C.'S
;	INTIDR - OPEN BOTH PATHS, AND MARK BOTH AS TURNED ON
; UPD ID= 4705, SNARK:<6.MONITOR>PHYKLP.MAC.200,  17-Aug-84 19:59:22 by GRANT
;In KLPRLC and KLPDMC, remove SETZM UCDTIM.
;Make KLPNDM a BUGHLT.
;In ANSWE1, fix bug introduced when QEMPT was invented.
; UPD ID= 4686, SNARK:<6.MONITOR>PHYKLP.MAC.199,  14-Aug-84 13:17:47 by GRANT
;Create patchable cell NDSTTM to hold NDSTIM.
;Increase NDSTIM from 10 to 30 seconds.
;Make KLPNRL a BUGHLT.
;At KLPCH7, check to see that the port is still running.
; UPD ID= 4681, SNARK:<6.MONITOR>PHYKLP.MAC.198,  13-Aug-84 16:34:55 by CDUNN
;TEMPORARILY move the definition of IDPAO and IDPBO to SCAPAR.
; UPD ID= 4607, SNARK:<6.MONITOR>PHYKLP.MAC.197,  27-Jul-84 13:05:24 by MCLEAN
;In STRKLP, call PHYSTC when port is started.
;Move KLPVER to STG.
;Add version numbers as optional data to KLPUMV.
;Add fork number as optional data to KLPLOA and KLPDUM.
;Put ucode version in T1 for KLPERR BUGCHK.
; UPD ID= 4582, SNARK:<6.MONITOR>PHYKLP.MAC.196,  24-Jul-84 15:03:12 by GRANT
;In CHKPCB, reload port when we find PIA is gone
; UPD ID= 4580, SNARK:<6.MONITOR>PHYKLP.MAC.195,  23-Jul-84 20:24:53 by GRANT
;In RIDSTS, redefine IDPx to be IDPxO.
;In INTIDR and RIDERR, better management of no-response vs. other errors.
;Create routine PTHSTS.
;In CLOPTH, preserve T2.
; UPD ID= 4566, SNARK:<6.MONITOR>PHYKLP.MAC.194,  19-Jul-84 07:15:12 by GRANT
;A better fix to RIDERR/INTRID interaction.
; UPD ID= 4564, SNARK:<6.MONITOR>PHYKLP.MAC.193,  18-Jul-84 21:03:05 by GRANT
;Turn on the calls to PHYSTC.
;In RIDERR, fix clobbering of T1.
; UPD ID= 4559, SNARK:<6.MONITOR>PHYKLP.MAC.192,  18-Jul-84 17:29:30 by GRANT
;In KLPFQE, check for both queues and if neither is empty just return quietly
;In INTRCT, BUGINF if we load a ucode version different from what we
;are expecting.  KLPVER is now 612.
; UPD ID= 4549, SNARK:<6.MONITOR>PHYKLP.MAC.191,  16-Jul-84 21:01:10 by HALL
;RET at the beginning of SANCHK (edit originally made by GRANT, lost by 
;merge on 7/14)
; UPD ID= 4548, SNARK:<6.MONITOR>PHYKLP.MAC.190,  16-Jul-84 16:56:33 by MOSER
;MAKE MAPBUF GET HIGH DENSITY COUNT IN BYTES NOT WORDS
; UPD ID= 4528, SNARK:<6.MONITOR>PHYKLP.MAC.189,  14-Jul-84 08:55:42 by HALL
;Add ability to send a shutdown notification to a node whose v.c. we
;are closing. This will allow it to know that a v.c. has been closed when
;it happens, rather than later when a START arrives or a packet comes back
;with error status.
;Technically, we need to be sure we send these only to nodes that process
;protocol level 1. Since none of these exists in our environment, we aren't
;rushing to solve the potential problem.
;	Add shutdown message to DGDSP and DGEDSP tables
;	Add routine INTSHT to process a shutdown
;	Make CLOSVC send a shutdown message if SCA initiated the closing
;	Add shutdown to STRLEN, but cheat and use the length of an ACK
; UPD ID= 4527, SNARK:<6.MONITOR>PHYKLP.MAC.188,  14-Jul-84 08:51:09 by GRANT
;Implement the handling of packets which have B0 off and B1 on.  This means
;the packet failed on one path and then succeeded on the other;  the port has
;stopped using the failed path for packets under virtual circuit contol until
;TOPS-20 tells it to use it again.
;Restructure the interrupt routine so there are separate dispatch paths (based
;on op code) for packets with errors and for packets without errors.
;Fix bugs in wire status change processing.
; UPD ID= 4413, SNARK:<6.MONITOR>PHYKLP.MAC.185,   2-Jul-84 07:17:31 by GRANT
;Move bit clearing from KLPDAC to DIAG.MAC.
;Remove CLEANQ, it's no longer used.
;Implement OPENVC and CLOSVC so SCA can better manage its VC data.
;Continually send REQUEST-IDs to all nodes, even on open VCs.
;PHYKLP now calls SC.ERR only, it never calls SC.OFL.
; UPD ID= 4397, SNARK:<6.MONITOR>PHYKLP.MAC.184,  27-Jun-84 17:15:12 by GRANT
;In KLPDAC, clear CS.OFL
; UPD ID= 4395, SNARK:<6.MONITOR>PHYKLP.MAC.183,  27-Jun-84 14:55:11 by HALL
;GIVSC1 - BUGINF if op code "remote" bit and PKSCA disagree
; UPD ID= 4390, SNARK:<6.MONITOR>PHYKLP.MAC.181,  26-Jun-84 19:41:20 by GRANT
;In INTNBF, CAIE should be CAME
; UPD ID= 4388, SNARK:<6.MONITOR>PHYKLP.MAC.180,  26-Jun-84 15:10:09 by GRANT
;In NONODS, SBLIST is now sparse so search entire list
; UPD ID= 4385, SNARK:<6.MONITOR>PHYKLP.MAC.179,  26-Jun-84 08:01:51 by GRANT
;In GTNPTH, clear T3 before setting up the path
; UPD ID= 4384, SNARK:<6.MONITOR>PHYKLP.MAC.178,  25-Jun-84 15:08:26 by GRANT
;After KLPHNG BUGINF, don't try to restart port, just ask for a reload.
;In CLNCOM, CIOFF/CION while calling GIVSC1.
; UPD ID= 4370, SNARK:<6.MONITOR>PHYKLP.MAC.177,  21-Jun-84 11:17:25 by MCLEAN
;FIX PROBLEM WITH CDB HAVING THE WRONG SIZE FOR THE NUMBER OF KDB'S
; UPD ID= 4362, SNARK:<6.MONITOR>PHYKLP.MAC.176,  20-Jun-84 12:32:52 by GRANT
;Replace KLPNOB BUGCHK with KLPNDG and KLPNMG.
;In GIVSCA, return buffer to port's free queue if error in locally-generated
;packet and response bit not set.
;In SENDVC, check for VC being open.
; UPD ID= 4343, SNARK:<6.MONITOR>PHYKLP.MAC.175,  15-Jun-84 13:46:51 by GRANT
;Add sending of loopback packets to once-a-second code and BUGINF whenever
;a wire's status changes.  Temporarily revise CIONLT.
;Remove obsolete comment before KLPTBP.
; UPD ID= 4321, SNARK:<6.MONITOR>PHYKLP.MAC.174,  11-Jun-84 10:52:52 by HAUDEL
;Same as edit 4317, changes meant for that edit were not put into the sources.
; UPD ID= 4317, SNARK:<6.MONITOR>PHYKLP.MAC.173,  11-Jun-84 10:32:04 by HAUDEL
;Changes to MAPBUF for 10 nibbles per word for core dump mode; IMTMCR to
;change bughlt to chk and output more additional data; INTCLO to return
;to user if error.
; UPD ID= 4292, SNARK:<6.MONITOR>PHYKLP.MAC.172,   4-Jun-84 13:28:08 by HAUDEL
;Change MAPBUF routine, various changes to Maintenance Data functions 
;including CLOBUF and INTCLO routines.
; UPD ID= 4280, SNARK:<6.MONITOR>PHYKLP.MAC.171,   1-Jun-84 12:19:47 by LOMARTIRE
;Make appropriate changes for SBI to node number conversion
; UPD ID= 4236, SNARK:<6.MONITOR>PHYKLP.MAC.170,  21-May-84 15:26:41 by MCLEAN
;PUT CHANNEL BACK IN LH OF .SBDSP
; UPD ID= 4227, SNARK:<6.MONITOR>PHYKLP.MAC.169,  16-May-84 17:17:44 by HALL
;Add to the magic list of things to be done.
; UPD ID= 4180, SNARK:<6.MONITOR>PHYKLP.MAC.168,   8-May-84 14:03:05 by CDUNN
;Fix data fields in START packets. Maximum message and datagram need to be in
;bytes and system ID needs to be system serial number.
; UPD ID= 4170, SNARK:<6.MONITOR>PHYKLP.MAC.167,   2-May-84 07:53:52 by HALL
;Load P4 with address of system block before calling SC.DMA
; UPD ID= 4163, SNARK:<6.MONITOR>PHYKLP.MAC.166,   1-May-84 13:57:45 by LOMARTIRE
;Since SC.INT now returns +1 always, remove KLPSCA BUGCHK
; UPD ID= 4146, SNARK:<6.MONITOR>PHYKLP.MAC.165,  26-Apr-84 06:35:46 by GRANT
;CLOBUF routine needs ::
; UPD ID= 4140, SNARK:<6.MONITOR>PHYKLP.MAC.164,  25-Apr-84 15:22:48 by LOMARTIRE
;Add node number and CID to KLPIST BUGCHK
; UPD ID= 4125, SNARK:<6.MONITOR>PHYKLP.MAC.163,  25-Apr-84 10:03:52 by HAUDEL
;Add READ/WRITE Maintenance Data routines.
;	Add op code to KLPOPS and KLPROU tables.
;	Change interrupt routines for the READ/WRITE Maint. Data functions.
;	Add a Close Buffer routine.
;	Store Remote node's state in SB on each receipt of an IDREC.
; UPD ID= 4118, SNARK:<6.MONITOR>PHYKLP.MAC.162,  24-Apr-84 15:36:07 by HAUDEL
;Change AOBJN to loop through all op codes of the KLPOPS table.
; UPD ID= 4096, SNARK:<6.MONITOR>PHYKLP.MAC.161,  18-Apr-84 17:31:57 by HALL
;Fix bug in which we were sometimes sending REQID's to our own node
;(KLIPA can't handle that).
;	Create INCRID, and call it when we're not interested in checking Q1
;	In INCRID, never allow our node to remain in RIDNXT
;	In CHKPOL call INCRID instead of NXTRID if we just want to increment
; UPD ID= 4079, SNARK:<6.MONITOR>PHYKLP.MAC.160,  12-Apr-84 07:20:11 by HALL
;In STRKLP, if we can't get a buffer to do the read counters, just return
;happily.
; UPD ID= 4078, SNARK:<6.MONITOR>PHYKLP.MAC.159,  12-Apr-84 06:55:31 by HALL
;Typo in previous edit
; UPD ID= 4063, SNARK:<6.MONITOR>PHYKLP.MAC.158,  11-Apr-84 14:49:06 by GRANT
;Add routines KLPNLF and KLPNDF.  Add BUGCHK in STROPN.
;In STRTDT, change SCA version number so we receive error logging packets.
; UPD ID= 4000, SNARK:<6.MONITOR>PHYKLP.MAC.157,  28-Mar-84 20:41:32 by GRANT
;In CIONLT, return +1 if we decide to dump the KLIPA
; UPD ID= 3982, SNARK:<6.MONITOR>PHYKLP.MAC.156,  27-Mar-84 07:40:30 by GRANT
;In STRKLP, fix comments
; UPD ID= 3981, SNARK:<6.MONITOR>PHYKLP.MAC.155,  27-Mar-84 07:31:29 by GRANT
;In PCBINI, remove unnecessary SETZMs (now only called at system start up).
;In STRKLP, get the ucode version after port has been started.
;Enhance processing of READ-COUNTERS response.
;Random coding convention clean up.
; UPD ID= 3978, SNARK:<6.MONITOR>PHYKLP.MAC.154,  26-Mar-84 20:00:24 by GRANT
;Declare KLIPA dead if 2 consecutive start attempts failed.
;In KLPEAC, call CFDIAG.
;In CIONLT, KLIPA state must be CHNRUN (running) before trying loopback.
; UPD ID= 3976, SNARK:<6.MONITOR>PHYKLP.MAC.153,  26-Mar-84 10:33:25 by HAUDEL
;In RMTRST set up P1 for call to PPDGDB
; UPD ID= 3972, SNARK:<6.MONITOR>PHYKLP.MAC.152,  25-Mar-84 06:18:00 by GRANT
;In KLPCCW, remove check for controller type.
; UPD ID= 3970, SNARK:<6.MONITOR>PHYKLP.MAC.151,  24-Mar-84 08:43:12 by GRANT
;In CHKPAK, change RET to JSR BUGHLT.
;In INTNBF, prevent buffer from going to 2 queues.
; UPD ID= 3949, SNARK:<6.MONITOR>PHYKLP.MAC.150,  20-Mar-84 07:41:58 by GRANT
;In KLPINI, PPDINX, PCBINI, and KLPCHK, load KLIPA ucode at system start up
; UPD ID= 3943, SNARK:<6.MONITOR>PHYKLP.MAC.149,  19-Mar-84 09:56:09 by HAUDEL
;Remove call to CLOSVC from RMTRST and put in SCAMPI
; UPD ID= 3914, SNARK:<6.MONITOR>PHYKLP.MAC.148,  13-Mar-84 06:28:00 by GRANT
;Change CRAM parity error BUGxxx names to be of the form KLPxxx
; UPD ID= 3912, SNARK:<6.MONITOR>PHYKLP.MAC.147,  13-Mar-84 05:56:54 by GRANT
;Add op code 205 (Close Buffer).
;Add error code to KLPRSF's optional data.  Change some :: to :.
; UPD ID= 3911, SNARK:<6.MONITOR>PHYKLP.MAC.146,  12-Mar-84 21:03:04 by GRANT
;In STRKLP, add KLPRSF and move KLPSTR to end of routine
; UPD ID= 3907, SNARK:<6.MONITOR>PHYKLP.MAC.145,  12-Mar-84 15:49:49 by HAUDEL
;Make RESET REMOTE and START REMOTE changes.
; UPD ID= 3888, SNARK:<6.MONITOR>PHYKLP.MAC.144,  11-Mar-84 07:42:10 by GRANT
;Change DSPBAD to KLPBDS, CIPERR to KLPERR, and CIPNDF to KLPUPC
; UPD ID= 3887, SNARK:<6.MONITOR>PHYKLP.MAC.143,  11-Mar-84 07:24:41 by GRANT
;Make KLPDRG a BUGINF instead of BUGCHK
; UPD ID= 3886, SNARK:<6.MONITOR>PHYKLP.MAC.142,  11-Mar-84 07:21:45 by GRANT
;In KLPRIP/KLPDIP, save fork number instead of job number
; UPD ID= 3882, SNARK:<6.MONITOR>PHYKLP.MAC.141,   8-Mar-84 06:42:40 by GRANT
;Missing SAVEAC in previous edit
; UPD ID= 3877, SNARK:<6.MONITOR>PHYKLP.MAC.140,   7-Mar-84 20:24:56 by GRANT
;In SCAERR, do SETCKT (to close)
; UPD ID= 3872, SNARK:<6.MONITOR>PHYKLP.MAC.139,   7-Mar-84 15:42:57 by GRANT
;Add KLPVER
; UPD ID= 3871, SNARK:<6.MONITOR>PHYKLP.MAC.138,   7-Mar-84 15:29:36 by GRANT
;In PCBINI, store channel logout word address in PCB.
;In GIVSCA, add missing LOAD of VC state.
;Change EMPMBQ to KLPNOB and EMPRSQ to KLPNRQ.
; UPD ID= 3861, SNARK:<6.MONITOR>PHYKLP.MAC.137,   6-Mar-84 13:54:12 by GRANT
;Use new PCB format
; UPD ID= 3851, SNARK:<6.MONITOR>PHYKLP.MAC.136,   5-Mar-84 12:13:28 by GRANT
;Add dumping the port.
; UPD ID= 3834, SNARK:<6.MONITOR>PHYKLP.MAC.135,  29-Feb-84 19:36:57 by GRANT
;Transmitter timeout is now a planned CRAM parity error
; UPD ID= 3807, SNARK:<6.MONITOR>PHYKLP.MAC.134,  29-Feb-84 11:04:16 by GRANT
;In STRTDT, temporarily say we don't support PPD byte 5 (error log packets)
; UPD ID= 3790, SNARK:<6.MONITOR>PHYKLP.MAC.133,  28-Feb-84 15:24:43 by HAUDEL
;More TCO 6.1546 - Performance Counter format change.
;Also change call of SC.RBF to RETDG in INTRCT.
; UPD ID= 3751, SNARK:<6.MONITOR>PHYKLP.MAC.132,  25-Feb-84 06:22:59 by GRANT
;Remove old REPEAT 0ed code.
;In CHKPCB, don't assume one-to-one mapping of virtual page to physical.
; UPD ID= 3749, SNARK:<6.MONITOR>PHYKLP.MAC.131,  24-Feb-84 21:04:41 by GRANT
;In STRTDT, clear second word of sending-system field.
;In STROPN, do SETCKT to close port's VC.
;Remove extraneous AOBJN in PCBINI.
;In KLPINI, initialize state of KLIPA to CHNUNK (unknown).
;In CIOLNT, BUGHLT after 5 consectuvie failures.
; UPD ID= 3710, SNARK:<6.MONITOR>PHYKLP.MAC.130,  21-Feb-84 09:36:24 by GRANT
;In KLPINI, set up channel number and port type for ERROR.SYS packets
; UPD ID= 3706, SNARK:<6.MONITOR>PHYKLP.MAC.129,  21-Feb-84 06:52:44 by GRANT
;In STRKLP, reset PCB before starting KLIPA.
;Change KLPSTR from BUGCHK to BUGINF.
; UPD ID= 3701, SNARK:<6.MONITOR>PHYKLP.MAC.128,  19-Feb-84 06:36:48 by GRANT
;In STRKLP, reset the PCB.
;Use DEFSTRs for ucode version in CDBVER.
;Change routine CHKNOD to GETNOD and test for node number in KLPCH1.
;Repeat 0 routines RDVER, RDCRAM, WTVER, and WTCRAM.
;Minor enhancement to PIAKLP.  Fix its callers.
; UPD ID= 3694, SNARK:<6.MONITOR>PHYKLP.MAC.127,  15-Feb-84 14:59:07 by GRANT
;Implement "states" of the KLIPA.
;Create routine CLENCQ to clean the command queues.  Revise routine STSHIT.
;Enhance KLPCPE.
;In BLDSBK, don't put CI channel number in LH of .SBDSP.
; UPD ID= 3683, SNARK:<6.MONITOR>PHYKLP.MAC.126,  10-Feb-84 14:38:47 by LOMARTIRE
;Use .SBAPB not SBAPCB since name was removed due to word location dependence
; UPD ID= 3677, SNARK:<6.MONITOR>PHYKLP.MAC.125,   8-Feb-84 21:18:13 by MILLER
;Once more
; UPD ID= 3671, SNARK:<6.MONITOR>PHYKLP.MAC.124,   8-Feb-84 11:03:22 by MILLER
;Improve code of previous edit
; UPD ID= 3669, SNARK:<6.MONITOR>PHYKLP.MAC.123,   8-Feb-84 10:06:04 by MILLER
;Add path selection argument to CIONLT
; UPD ID= 3665, SNARK:<6.MONITOR>PHYKLP.MAC.122,   8-Feb-84 08:37:44 by LOMARTIRE
;Make LNKDFQ and LNKMFQ return plus 1 always instead of plus 2 always
; UPD ID= 3621, SNARK:<6.MONITOR>PHYKLP.MAC.121,   1-Feb-84 13:11:25 by GRANT
;In STRTDT, use the new definitions for word .SRRSV
; UPD ID= 3604, SNARK:<6.MONITOR>PHYKLP.MAC.120,  31-Jan-84 14:34:53 by GRANT
;In CHKPOL, send a REQUEST-ID if the VC state is closed.  (This will be
;removed when OPENVC is implemented.)
; UPD ID= 3597, SNARK:<6.MONITOR>PHYKLP.MAC.119,  31-Jan-84 07:40:55 by GRANT
;Add some form feeds.
;Eliminate routine SETPKT, put the code in KLPSND.
;Use PKSRB when clearing all software response bits.
;Use KLPPRx symbols for command priority.
; UPD ID= 3591, SNARK:<6.MONITOR>PHYKLP.MAC.118,  30-Jan-84 13:57:37 by GRANT
;Get correct optional data in CPE BUGINFs
; UPD ID= 3585, SNARK:<6.MONITOR>PHYKLP.MAC.117,  29-Jan-84 06:47:46 by GRANT
;Add KLPCGN BUGCHK when we time out the READ-REGISTER in PPDINX
; UPD ID= 3584, SNARK:<6.MONITOR>PHYKLP.MAC.116,  29-Jan-84 06:25:13 by GRANT
;Add KLPLBF BUGCHK when a loopback packet gets an error
; UPD ID= 3579, SNARK:<6.MONITOR>PHYKLP.MAC.115,  28-Jan-84 11:54:33 by GRANT
;In CHKPOL, don't send REQUEST-IDs to nodes we've already heard from.
;Remove CHKCVC, it won't be used.
; UPD ID= 3578, SNARK:<6.MONITOR>PHYKLP.MAC.114,  28-Jan-84 09:15:42 by GRANT
;Don't need to zero the packet in CIONLT
; UPD ID= 3576, SNARK:<6.MONITOR>PHYKLP.MAC.113,  28-Jan-84 08:06:52 by GRANT
;Add ENDBS. to BLSUB. routines.
;Change JRST DSPBUG to CALL DSPBUG.
; UPD ID= 3575, SNARK:<6.MONITOR>PHYKLP.MAC.112,  28-Jan-84 06:56:28 by GRANT
;In SCAERR, check for VC being open.
;,In INTSDT, enhance error checking of named buffer packets.
; UPD ID= 3568, SNARK:<6.MONITOR>PHYKLP.MAC.111,  27-Jan-84 17:13:29 by GRANT
;Remove the test for START-SENT in GIVSCA
; UPD ID= 3541, SNARK:<6.MONITOR>PHYKLP.MAC.110,  25-Jan-84 16:45:47 by MCLEAN
;MAPBUF SHOULD NOT USE P6!! CHANGE IT TO P2
; UPD ID= 3532, SNARK:<6.MONITOR>PHYKLP.MAC.109,  24-Jan-84 21:04:06 by MCLEAN
;ADD SOME COMMENTS TO UMAP
; UPD ID= 3531, SNARK:<6.MONITOR>PHYKLP.MAC.108,  24-Jan-84 20:51:46 by MCLEAN
;CHANGES TO PROTECT BHD/BSD'S FROM INTERRUPT LEVEL
; UPD ID= 3526, SNARK:<6.MONITOR>PHYKLP.MAC.107,  24-Jan-84 16:41:47 by HAUDEL
;TCO 6.1546 - More performance counter.
; UPD ID= 3525, SNARK:<6.MONITOR>PHYKLP.MAC.106,  24-Jan-84 15:45:54 by HAUDEL
;TCO 6.1546 - Performance counter change.
; UPD ID= 3523, SNARK:<6.MONITOR>PHYKLP.MAC.105,  24-Jan-84 14:09:28 by PAETZOLD
;TCO 6.1951 - Move around the push in KLPRST
; UPD ID= 3520, SNARK:<6.MONITOR>PHYKLP.MAC.104,  24-Jan-84 10:05:18 by GRANT
;Do a single CONI in KLPINT.  Analyze CRAM parity errors.  Clean up SCAERR.
;Put another buffer on the queue if we get a free queue error interrupt.
; UPD ID= 3489, SNARK:<6.MONITOR>PHYKLP.MAC.103,  20-Jan-84 11:09:14 by GRANT
;Clean up routines STRSTR and STKSTR
; UPD ID= 3484, SNARK:<6.MONITOR>PHYKLP.MAC.102,  20-Jan-84 06:52:52 by GRANT
;Add to the list of questions
;Minor clean up in GIVSCA
; UPD ID= 3483, SNARK:<6.MONITOR>PHYKLP.MAC.101,  20-Jan-84 06:49:24 by GRANT
;Rename routine OPNCIR to OPNSCA and remove its call to KLPOPN.
;In GIVSCA, check for VC state START-RECIEVED.  An incoming message will
; open the VC.
;Revise START/STACK/ACK protocol to use SETCKT in correct places.
;Undo previous edit.
; UPD ID= 3474, SNARK:<6.MONITOR>PHYKLP.MAC.100,  17-Jan-84 18:31:04 by HALL
;Make SETCKT and datagrams sent by the driver go on highest-priority queue
; UPD ID= 3464, SNARK:<6.MONITOR>PHYKLP.MAC.99,  16-Jan-84 11:56:23 by GRANT
;In KLPSDG, use table STRLEN to get packet length.
; UPD ID= 3463, SNARK:<6.MONITOR>PHYKLP.MAC.98,  16-Jan-84 11:52:37 by GRANT
;Remove check for VC.OPN in SENDVC.
;Allow for new PPD byte 5 (error packet).  Fix STRTDT.
; UPD ID= 3459, SNARK:<6.MONITOR>PHYKLP.MAC.97,  14-Jan-84 16:16:51 by GRANT
;Improve logic after KLPNOR BUGCHK.
;Eliminate STRIDT.  Put the code in KLPRID.
;Subroutinize KLPCHK.
;Add IDCVC to RIDSTS.
; UPD ID= 3430, SNARK:<6.MONITOR>PHYKLP.MAC.96,  10-Jan-84 07:59:04 by GRANT
;Fix INTSDT and INTNBF
; UPD ID= 3429, SNARK:<6.MONITOR>PHYKLP.MAC.95,   9-Jan-84 17:41:56 by HALL
;Add to the list of questions
; UPD ID= 3427, SNARK:<6.MONITOR>PHYKLP.MAC.94,   9-Jan-84 11:51:43 by HALL
;KLPRST - Check the op code in the correct AC, don't put packets back on
;free queue with software bits set
; UPD ID= 3416, SNARK:<6.MONITOR>PHYKLP.MAC.93,   6-Jan-84 07:01:19 by GRANT
;Return packet to datagram free queue after KLPPPD BUGCHK.
; UPD ID= 3415, SNARK:<6.MONITOR>PHYKLP.MAC.92,   6-Jan-84 05:58:53 by GRANT
;Add KLPNUP BUGINF
; UPD ID= 3413, SNARK:<6.MONITOR>PHYKLP.MAC.91,   6-Jan-84 05:45:29 by GRANT
;Update KPTAB.  Clean up REPORT and fix its callers.
; UPD ID= 3411, SNARK:<6.MONITOR>PHYKLP.MAC.90,   6-Jan-84 05:42:34 by GRANT
;MAPBUF is now a BLSUB.
; UPD ID= 3409, SNARK:<6.MONITOR>PHYKLP.MAC.89,   5-Jan-84 19:05:41 by HALL
;Change KLPCVC and KLPPTH from CHK to INF
;In KLPCHK, see if interlock value is good, and check queue, for each queue
;SETPKT - Check outgoing op code
;GTINTL - Check T1 for interlock word in PCB
;Add FNDKLP
;In PUTQUE and REMQUE, call SANCHK
;In CHKPAK, check physical address in FLINK word against NHIPG
;Zero flags in KLPSDG, etc
;Call TELERR with system block address in P5, not P4
; UPD ID= 3408, SNARK:<6.MONITOR>PHYKLP.MAC.88,   5-Jan-84 13:14:15 by GRANT
;Make INTRD1 identical to INTRD0.
; UPD ID= 3407, SNARK:<6.MONITOR>PHYKLP.MAC.87,   5-Jan-84 13:02:48 by GRANT
;In INTNBF, return packet to message free queue.
; UPD ID= 3399, SNARK:<6.MONITOR>PHYKLP.MAC.86,   3-Jan-84 13:16:03 by GRANT
;More work on software response bits.
; UPD ID= 3393, SNARK:<6.MONITOR>PHYKLP.MAC.85,  30-Dec-83 09:26:00 by HALL
;Rearrange routines
; UPD ID= 3386, SNARK:<6.MONITOR>PHYKLP.MAC.84,  29-Dec-83 16:17:32 by HALL
;Fix KLPBYE's optional data (T3 no longer contained PPD byte, node number is
;	more interesting, anyway)
;Move QRETS and QRET to the end of the queue routines
; UPD ID= 3379, SNARK:<6.MONITOR>PHYKLP.MAC.83,  27-Dec-83 16:59:59 by HALL
;A little more work on the state stuff
;In REMQUE, make exit from REMQU4 go through QRET like everything else
;In REMQUE, provide better data at KLPVIR
;In CHKPAK, don't allow reference to the AC's
; UPD ID= 3373, SNARK:<6.MONITOR>PHYKLP.MAC.82,  27-Dec-83 12:54:57 by HALL
;Put all the KLIPA management routines in the back
; UPD ID= 3370, SNARK:<6.MONITOR>PHYKLP.MAC.81,  27-Dec-83 08:11:46 by GRANT
;Put all CALL KLPBUG under conditional.
;Add error code to error return in GETBSD.
;Fix all SAVEACs to use < >.
;Use new software bits in word .PKVRT to indicate response requested.
;SC.DMA returns +1 only.
; UPD ID= 3369, SNARK:<6.MONITOR>PHYKLP.MAC.80,  26-Dec-83 19:58:50 by HALL
;Add KLPQ, which contains address of interlock word that we locked most
;	recently
; UPD ID= 3367, SNARK:<6.MONITOR>PHYKLP.MAC.79,  26-Dec-83 10:49:47 by HALL
;Get rid of obsolete data structure for "delayq"
;In SNDREC, return buffer to SCA if SENDVC fails
;Add KLPPRI BUGHLT in SETPKT
;Add BUGCHK KLPVIR at REMQU4
;Save Q3 in REPORT
;Work on list of concerns
; UPD ID= 3366, SNARK:<6.MONITOR>PHYKLP.MAC.78,  24-Dec-83 15:24:54 by HALL
;Start "states of the KLIPA"
; UPD ID= 3365, SNARK:<6.MONITOR>PHYKLP.MAC.77,  24-Dec-83 15:19:39 by HALL
;In PUTQUE, don't allow a buffer address less than 20
;In KLPCHK, get a buffer before trying to send a REQID in it.
; UPD ID= 3364, SNARK:<6.MONITOR>PHYKLP.MAC.76,  24-Dec-83 06:16:41 by GRANT
;Add more optional data to KLPPPD, KLPOPC, and KLPNDE, and make the BUGCHKs.
; UPD ID= 3362, SNARK:<6.MONITOR>PHYKLP.MAC.75,  22-Dec-83 21:16:59 by GRANT
;In LNKDFQ and ULNKDG, sanity check the system block address.
;In PUTQUE, sanity check the packet address.
;Initialize KLPOWN in KLPINI and add KLPOWN check at GTINTL.
;Add KLPPPD BUGHLT when we get a packet with an invalid PPD byte.
;Add KLPOPC BUGHLT when we get a packet with an invalid op-code.
;Add KLPNDE BUGCHK when we get a packet with an invalid node number.
;Add KLPSCA BUGCHK when CALL SC.INT fails.
;LNKDFQ and LNKMFQ are now BLSUB.
; UPD ID= 3353, SNARK:<6.MONITOR>PHYKLP.MAC.74,  20-Dec-83 15:59:56 by HALL
;Record owner of interlock in KLPOWN. Add this to optional data in GTINTL
; UPD ID= 3349, SNARK:<6.MONITOR>PHYKLP.MAC.73,  20-Dec-83 08:16:29 by GRANT
;ULNKDG and ULNKMG are now BLSUB.
; UPD ID= 3343, SNARK:<6.MONITOR>PHYKLP.MAC.72,  19-Dec-83 13:44:32 by GRANT
;In PPDINX, remove stocking of message free queue.
;Add error codes to routines which fail.
;Add node number as optional data to KLPCVC.
;Add PIA check and PCB check in KLPCHK.
;Change optional data in EMPMBQ to be the queue interlock word.
;Remove unexecuted code in REPORT.
;Move CILIN so it is before CALL RMASAG.
; UPD ID= 3339, SNARK:<6.MONITOR>PHYKLP.MAC.71,  19-Dec-83 09:00:59 by GRANT
;Use CION/CIOFF when trying to get a queue interlock.
; UPD ID= 3335, SNARK:<6.MONITOR>PHYKLP.MAC.70,  16-Dec-83 16:50:33 by HALL
;Break TRCKLP into two parts, and add sanity checker
;Create GTINTL to get the interlock, and make PUTQUE and REMQUE call it
; UPD ID= 3331, SNARK:<6.MONITOR>PHYKLP.MAC.69,  16-Dec-83 15:45:58 by HALL
;Use CHNOFF instead of PIOFF
; UPD ID= 3330, SNARK:<6.MONITOR>PHYKLP.MAC.68,  16-Dec-83 10:37:27 by HALL
;Reduce size of KLIPA ring buffer, KLPBUF
;Reorganize queue routines. Add SANCHK
;Add count as optional data to KLPPUT and KLPREM
;PPDSPT - Rick's fix to load mask
;Change calling conventions for SETCKT, so that length isn't passed, and
;	priority is passed in T2. This affects KLPSND, KLPRID, CLOSVC, KLPSCK,
;	KLPSDG, DIASND, and all callers of DIASND
;Maintain an increasing "transaction ID" and store it in packets that
;	require it (KLPRID, KLPSCK, DIASND)
;Create KLPRRG, subroutine for sending OP.RRG; change PPDINX and KLPCHK
;	to use it
;Fix up CLOSVC. Change to BLSUB
;Create KLPCLO, and make CLOSVC call it
;Add KLPOPN
;in KLPSCK, set .PKCKT word. Don't do it in KLPINT
;Clean up PPDSRS, KLPSST. Put "default address bit" in correct word
;In PPDSPT and PPDSRS, load Q3 as needed by DIASND. DOn't load it in DIASND.
;Get rid of INTRST
;In SETPKT, don't store .PKLEN word. Store it in SNDDG, SNDMSG, and KLPSDG
;	 instead
;In SETPKT, don't call MASAGE. Do it in SNDDG and SNDMSG
;Make REQDAT/SNDREC send data directly. Eliminate KLPSDT/KLPRDT
;Change AC usage in REQDAT/SNDREC for buffer address
;Clean up SNDMSG/SNDDG, add SENDVC
;In KLPSND make saving of queue indicator more predictable
;In MASAGE, don't check op code. Caller should do that
;OPNCIR - Call KLPOPN
;CIONLT - don't stuff things in packet that SETPKT will do
;Add PKYLEN to define length part of .PKLEN word
; UPD ID= 3330, SNARK:<6.MONITOR>PHYKLP.MAC.68,  16-Dec-83 10:37:27 by HALL
;Reduce size of KLIPA ring buffer, KLPBUF
; UPD ID= 3313, SNARK:<6.MONITOR>PHYKLP.MAC.67,  14-Dec-83 06:01:27 by GRANT
;More clean up of calls to SC.RBF
; UPD ID= 3312, SNARK:<6.MONITOR>PHYKLP.MAC.66,  14-Dec-83 05:43:53 by GRANT
;Fix calls to SC.RBF, it returns +1 only.
;In CHKOPN, set state of VC to closed.
; UPD ID= 3299, SNARK:<6.MONITOR>PHYKLP.MAC.65,  13-Dec-83 09:10:28 by GRANT
;Make returning port counters work for DIAG% interface (temporary)
; UPD ID= 3291, SNARK:<6.MONITOR>PHYKLP.MAC.64,  11-Dec-83 20:21:14 by GRANT
;Rewrite KLPINT and KLPCHK, implementing the START/STACK/ACK state machine.
;Add debugging ring buffer for PUTQUE and REMQUE.
;Create routine OPENVC.
;Add check for "our node number not known" in LOCPRT.
;Create routine TRCKLP, for tracing the packets on a queue.
;Add labels CILIN and CILOUT for the CILOOK SNOOP% program.
;At REMQU4, initialize the desired words, and release the interlock AFTER
; the FLINK and BLINK are set.
; UPD ID= 3247, SNARK:<6.MONITOR>PHYKLP.MAC.63,   4-Dec-83 11:47:02 by HALL
;In KLPRST, restore FLINKs and BLINKs for free queues before enabling the
;  KLIPA
; UPD ID= 3234, SNARK:<6.MONITOR>PHYKLP.MAC.62,  30-Nov-83 15:26:19 by HAUDEL
;Change bit and AC for Start Remote System
;
; UPD ID= 3160, SNARK:<6.MONITOR>PHYKLP.MAC.61,  15-Nov-83 17:18:56 by HALL
;Under KLPDBG there was still a reference to INIT
; UPD ID= 3150, SNARK:<6.MONITOR>PHYKLP.MAC.60,  15-Nov-83 08:05:06 by HALL
;Make KLPI19 put message buffer on correct queue
;Make KLPTMO BUGCHK print out useful data
; UPD ID= 3140, SNARK:<6.MONITOR>PHYKLP.MAC.59,  11-Nov-83 17:19:32 by MCLEAN
;FIX CORE CLOBERER
; UPD ID= 3128, SNARK:<6.MONITOR>PHYKLP.MAC.58,   9-Nov-83 15:06:28 by GRANT
;Eliminate INIT
;Set SF%KLP when PPDINX finishes so KLPCHK will know when to start polling
;Put INICMD and friends under repeat 0, and do the same for the code
; in PPDINX that we're no longer executing
;PPDINX -- zero INIT before sending read register, and REQIDs to each node
;	-- don't call SBKINI here. Let KLPINT handle the startup protocol
;Put SBKINI under repeat 0 temporarily. Shouldn't need it any longer
;Make BLDSBK do all the initialization of the system block, copy it
;	from SBKINI
;KLPINT -- At KLPIN7, after building the system block, continue and send
;		the START
;	At KLPI21, send appropriate response rather than calling SBKINx
;	At KLPI12, send start rather than calling SBKIN1
;KLPSDG -- Remove the POP P,(P)
; UPD ID= 3126, SNARK:<6.MONITOR>PHYKLP.MAC.57,   9-Nov-83 13:05:36 by HALL
;Fix typo in previous edit
; UPD ID= 3125, SNARK:<6.MONITOR>PHYKLP.MAC.56,   9-Nov-83 12:57:02 by HALL
;In KLPINT, check for OP.RDT rather than OP.DTR
;In KLPINT, check the op code before believing the PPD byte
;In SNDREC, change the LSH to +3, to account for storing 36 bits
;	left justified in 32
;In KLPHUN, set up P2 from the UDB
; UPD ID= 3098, SNARK:<6.MONITOR>PHYKLP.MAC.55,   4-Nov-83 11:00:42 by HALL
;Move SCA interface routines so that they're all together
; UPD ID= 3096, SNARK:<6.MONITOR>PHYKLP.MAC.54,   4-Nov-83 10:35:49 by GRANT
;In PPDINX, call SCA instead of using special storage (PACKET and IMSGB).
;Change TIMOUT from 2 seconds to 1.
; UPD ID= 3091, SNARK:<6.MONITOR>PHYKLP.MAC.53,   1-Nov-83 21:21:23 by GRANT
;In PUTQUE and REMQUE, BUGCHK if we time out waiting for the queue interlock
; UPD ID= 3090, SNARK:<6.MONITOR>PHYKLP.MAC.52,   1-Nov-83 21:06:06 by GRANT
;In REPORT, set only the LAR bit in the CSR
; UPD ID= 3089, SNARK:<6.MONITOR>PHYKLP.MAC.51,  31-Oct-83 21:29:21 by GRANT
;At KLPI20, restore PCB before falling through to KLPI20
; UPD ID= 3079, SNARK:<6.MONITOR>PHYKLP.MAC.50,  25-Oct-83 13:11:24 by GRANT
;REDIT problem - Previous edit also did the following:
;Change KLPDSP.  Create KLDSP, KLPSIO, KLPCCW, KLPHUN, KLPEXT, KLPCCA, and KLEXT
; UPD ID= 3074, SNARK:<6.MONITOR>PHYKLP.MAC.49,  25-Oct-83 13:05:00 by GRANT
;Move MSCCCW and MSCCCA here from PHYMSC.  Reformat listing.
; UPD ID= 3063, SNARK:<6.MONITOR>PHYKLP.MAC.48,  24-Oct-83 15:38:36 by MILLER
;Add XCT word to reset the port
; UPD ID= 3019, SNARK:<6.MONITOR>PHYKLP.MAC.47,  10-Oct-83 14:35:59 by GRANT
;In REPORT, another try at the LAR
; UPD ID= 2965, SNARK:<6.MONITOR>PHYKLP.MAC.46,   2-Oct-83 06:05:10 by GRANT
;In REPORT, set CO.LAR in CSR to read port's LAR
; UPD ID= 2936, SNARK:<6.MONITOR>PHYKLP.MAC.45,  27-Sep-83 09:44:36 by GRANT
;KLPINI (formerly INKLPA) now creates CDB.
;CONI/CONO bits moved to PHYPAR.
;Eliminate KLPSV routine - code moved to skip chain.
;Remove all ##.
; UPD ID= 2786, SNARK:<6.MONITOR>PHYKLP.MAC.44,   3-Aug-83 10:43:19 by MCLEAN
;ADD A FEW BUGCHK'S ETC
; UPD ID= 2632, SNARK:<6.MONITOR>PHYKLP.MAC.43,  23-Jun-83 19:25:04 by CDUNN
;More TCO 6.1127 - Fix RAG to always swap the PPD byte...
;
; UPD ID= 2559, SNARK:<6.MONITOR>PHYKLP.MAC.42,   4-Jun-83 19:48:40 by MILLER
;Add LAR to KLPHNG and KLPSTP
;
; UPD ID= 2554, SNARK:<6.MONITOR>PHYKLP.MAC.41,   3-Jun-83 17:10:49 by CDUNN
;More TCO 6.1127 - Support port insertion of the PPD field by the microcode.
;Also make offline detection return packets
;
; UPD ID= 2509, SNARK:<6.MONITOR>PHYKLP.MAC.38,  24-May-83 14:19:03 by MILLER
;Fix KLPRNV to return to PHYSIO
;
; UPD ID= 2473, SNARK:<6.MONITOR>PHYKLP.MAC.37,  16-May-83 17:40:35 by CDUNN
;More TCO 6.1127 - Random fixes makde by Tony.
;
; UPD ID= 2394, SNARK:<6.MONITOR>PHYKLP.MAC.36,   2-May-83 06:19:37 by WACHS
;More TCO 6.1127 - Fix race calling MASAGE, PPD byte problem on error
;
; UPD ID= 2387, SNARK:<6.MONITOR>PHYKLP.MAC.35,  29-Apr-83 21:34:28 by MILLER
;TCO 6.1610 again. Use "free choice" of path for loopback message
;
; UPD ID= 2367, SNARK:<6.MONITOR>PHYKLP.MAC.34,  27-Apr-83 23:45:50 by CDUNN
;More TCO 6.1127 - Fix KLPINT to correctly return industry compat message 
;lengths.
;
; UPD ID= 2344, SNARK:<6.MONITOR>PHYKLP.MAC.33,  26-Apr-83 07:48:46 by WACHS
;More TCO 6.1127 - general fixes
;
; UPD ID= 2331, SNARK:<6.MONITOR>PHYKLP.MAC.32,  22-Apr-83 13:08:24 by MILLER
;Fix bad AC at INKLP8+4
;
; UPD ID= 2330, SNARK:<6.MONITOR>PHYKLP.MAC.31,  22-Apr-83 12:53:27 by MILLER
;Yet more fixes. This time, we got it to work!
;
; UPD ID= 2325, SNARK:<6.MONITOR>PHYKLP.MAC.30,  22-Apr-83 01:40:54 by CDUNN
;More TCO 6.1127 - Add support for returning the packet length to SCA on a
;message or datagram receive.
;
; UPD ID= 2321, SNARK:<6.MONITOR>PHYKLP.MAC.27,  21-Apr-83 16:58:06 by MILLER
;More initialization fixes. Fix handling of DELAYQ
;
; UPD ID= 2317, SNARK:<6.MONITOR>PHYKLP.MAC.26,  20-Apr-83 12:40:31 by MILLER
;Many fixes to initialization code.
;
; UPD ID= 2306, SNARK:<6.MONITOR>PHYKLP.MAC.25,  19-Apr-83 15:29:53 by MILLER
;TCO 6.1610. Use "lopback" message on CIONLT
;
; UPD ID= 2304, SNARK:<6.MONITOR>PHYKLP.MAC.24,  19-Apr-83 07:35:14 by WACHS
;
; UPD ID= 2299, SNARK:<6.MONITOR>PHYKLP.MAC.23,  17-Apr-83 18:48:53 by MILLER
;TCO 6.1610. Add CIONLT
;
; UPD ID= 2279, SNARK:<6.MONITOR>PHYKLP.MAC.22,  15-Apr-83 07:34:38 by HAUDEL
;
; UPD ID= 2277, SNARK:<6.MONITOR>PHYKLP.MAC.21,  14-Apr-83 08:28:22 by HAUDEL
;More TCO 6.1127 - Change PPDINX so that code works on systems without KLIPAs
;
; UPD ID= 2256, SNARK:<6.MONITOR>PHYKLP.MAC.20,  12-Apr-83 23:20:45 by CDUNN
;More TCO 6.1127 - Fix references to DGPOLL under IFE FTMSCP to not be external
;
; UPD ID= 2254, SNARK:<6.MONITOR>PHYKLP.MAC.19,  12-Apr-83 23:01:17 by CDUNN
;More TCO 6.1127 - Fix DGPOLL typo
;More TCO 6.1127 - general fixes
;
; UPD ID= 2209, SNARK:<6.MONITOR>PHYKLP.MAC.17,   8-Apr-83 06:15:33 by WACHS
;TCO 6.1602 - Flag/reload KLIPA when it dies
;More TCO 6.1127 - general fixes
;
; UPD ID= 2090, SNARK:<6.MONITOR>PHYKLP.MAC.14,  28-Mar-83 02:35:59 by CDUNN
;More TCO 6.1127 - Add routine LOCPRT to return local port number
;PSECT such that the monitor can be write protected with debug on.
;
; UPD ID= 2059, SNARK:<6.MONITOR>PHYKLP.MAC.13,  22-Mar-83 08:10:33 by WACHS
;More TCO 6.1127
;
; UPD ID= 2018, SNARK:<6.MONITOR>PHYKLP.MAC.12,  18-Mar-83 03:49:13 by WACHS
;More TCO 6.1127
;TCO 6.1541 - Move DMA stuff to PHYKLP from PHYMSC
;
; UPD ID= 1987, SNARK:<6.MONITOR>PHYKLP.MAC.9,  14-Mar-83 15:31:41 by CDUNN
;More TCO 6.1127 - Change DEBUG to KLPDBG and place it under SYSFLG.MAC
;control.
;
; UPD ID= 1947, SNARK:<6.MONITOR>PHYKLP.MAC.8,   9-Mar-83 12:33:26 by CDUNN
;More TCO 6.1127 - Change debug code to be under conditionals, Also try to
;recover from errors rather than call KLPBUG.
;
; UPD ID= 1942, SNARK:<6.MONITOR>PHYKLP.MAC.7,   8-Mar-83 20:43:54 by CDUNN
;More TCO 6.1127 - Move init of SCA locations in the SB such that it always
;happens regarless of virtual circuit state.
;Also fix init sequence such that three start datagrams are recognized in
;init sequence with another KL.
;
; UPD ID= 1932, SNARK:<6.MONITOR>PHYKLP.MAC.6,   7-Mar-83 21:47:04 by CDUNN
;Change C%BMSG to C%MGSZ to conform to change in SCAPAR

;	COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1984, 1988.
;	ALL RIGHTS RESERVED.
;
;	THIS SOFTWARE IS FURNISHED UNDER A  LICENSE AND MAY BE USED AND  COPIED
;	ONLY IN  ACCORDANCE  WITH  THE  TERMS OF  SUCH  LICENSE  AND  WITH  THE
;	INCLUSION OF THE ABOVE  COPYRIGHT NOTICE.  THIS  SOFTWARE OR ANY  OTHER
;	COPIES THEREOF MAY NOT BE PROVIDED  OR OTHERWISE MADE AVAILABLE TO  ANY
;	OTHER PERSON.  NO  TITLE TO  AND OWNERSHIP  OF THE  SOFTWARE IS  HEREBY
;	TRANSFERRED.
;
;	THE INFORMATION IN THIS  SOFTWARE IS SUBJECT  TO CHANGE WITHOUT  NOTICE
;	AND SHOULD  NOT  BE CONSTRUED  AS  A COMMITMENT  BY  DIGITAL  EQUIPMENT
;	CORPORATION.
;
;	DIGITAL ASSUMES NO  RESPONSIBILITY FOR  THE USE OR  RELIABILITY OF  ITS
;	SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY DIGITAL.


	SEARCH PROLOG,SERCOD,PHYPAR,SCAPAR
	TTITLE (PHYKLP,,< - Device Dependent Code For CI KLIPA Port  >)
	Subttl	Table of Contents

;		     Table of Contents for PHYKLP
;
;				  Section		      Page
;
;
;    1. Parameters, Symbols, and Storage . . . . . . . . . . .   3
;    2. KLIPA Debugging Code . . . . . . . . . . . . . . . . .   8
;    3. System Startup
;        3.1    KLPUCD (Read Microcode into Memory)  . . . . .   9
;        3.2    PPDINX (Initialize SCA)  . . . . . . . . . . .  10
;    4. Routines for sending data  . . . . . . . . . . . . . .  11
;    5. Routines for manipulating queues . . . . . . . . . . .  29
;    6. Named-Buffer Routines  . . . . . . . . . . . . . . . .  46
;    7. Byte Swapping Routines . . . . . . . . . . . . . . . .  51
;    8. PHYSIO Interface
;        8.1    Dispatch Tables  . . . . . . . . . . . . . . .  53
;        8.2    KLPINI (Channel Initialization)  . . . . . . .  54
;        8.3    KLPSIO (Start I/O) . . . . . . . . . . . . . .  57
;        8.4    KLPINT (Interrupt Service) . . . . . . . . . .  58
;        8.5    Channel Command Word, Hung, Reset  . . . . . . 114
;        8.6    KLPCHK (Once-a-second Check) . . . . . . . . . 115
;        8.7    Check Unit Existence . . . . . . . . . . . . . 126
;    9. CI CRAM Parity Error Processing  . . . . . . . . . . . 127
;   10. States of the KLIPA
;       10.1    Commentary . . . . . . . . . . . . . . . . . . 145
;       10.2    Dispatch Tables  . . . . . . . . . . . . . . . 147
;       10.3    Loading the KLIPA
;           10.3.1    KLPRIP (Load from User)  . . . . . . . . 149
;           10.3.2    LODUCD (Load Microcode)  . . . . . . . . 150
;           10.3.3    RLDKLP (Load from Monitor) . . . . . . . 152
;           10.3.4    KLPRLC (Reload Complete) . . . . . . . . 153
;       10.4    Stopping the KLIPA
;           10.4.1    STPKLP (Stop KLIPA)  . . . . . . . . . . 154
;           10.4.2    DISKLP (Disable KLIPA) . . . . . . . . . 155
;       10.5    Starting the KLIPA
;           10.5.1    STRKLP (Start KLIPA) . . . . . . . . . . 156
;           10.5.2    KIKKLP (Ready KLIPA) . . . . . . . . . . 158
;           10.5.3    ENAKLP (Enable KLIPA)  . . . . . . . . . 159
;       10.6    Set CI Port Unavailable  . . . . . . . . . . . 160
;       10.7    Miscellaneous  . . . . . . . . . . . . . . . . 161
;   11. Utility Routines . . . . . . . . . . . . . . . . . . . 162
	SUBTTL Parameters, Symbols, and Storage

;CI OPERATION CODES

OP.SDG==1			;SEND DATAGRAM
OP.SMS==2			;SEND MESSAGE
OP.RCF==3			;CONFIRM RECEIVED
OP.MCR==4			;MAINTENANCE CONFIRM RECEIVED
OP.RID==5			;REQUEST ID
OP.RRS==6			;RESET REMOTE SYSTEM
OP.SRS==7			;START REMOTE SYSTEM
OP.RD0==10			;REQUEST DATA ON QUEUE 0
OP.RD1==11			;REQUEST DATA 1
OP.RD2==12			;REQUEST DATA 2
OP.IDR==13			;ID RECEIVED
OP.LPB==15			;SEND/RECEIVE LOOPBACK
OP.RMD==16			;REQUEST MAINTENANCE DATA
OP.SDT==20			;SEND DATA
OP.RDT==21			;RETURN DATA (DATREC)
OP.SMD==22			;SEND MAINTENANCE DATA
OP.MDR==23			;MAINTENANCE DATA RECEVIED
OP.CKT==200			;SET VIRTUAL CIRCUIT
OP.SPT==201			;SET STATISTICS COUNTER
OP.RCT==202			;READ STATISTICS COUNTER
OP.RRG==203			;READ REGISTER
OP.WRG==204			;WRITE REGISTER
OP.CLB==205			;CLOSE BUFFER
OP.RMT==40			;ON IN REMOTELY GENERATED RESPONSES

.DOLRA==1B0			;BIT ON IN DATAO TO LOAD RAM ADDRESS REGISTER
MICVSZ==^D10			;MICROCODE VERSION FIELD SIZE
MICVPS==^D29			;MICROCODE VERSION FIELD POSITION
MICVER==137			;MICROSTORE VERSION NUMBER LOC
NONVER==1777			;-1 IN THE VERSION WORD
MAXNOR==77			;NUMBER OF TIME OUTS BEFORE WE DECLARE THE OTHER PORT SICK

TIMOUT==^D1000			;VALUE OF INTERLOCK WORD AT WHICH WE DECLARE THE KLIPA DEAD
TIM==020			;[7.1202] Timer device for DATAI

OPDEF RDTIME [DATAI TIM,]	;[7.1202] Instruction for reading timer
;Global byte pointers

PKYSTS::POINT PKSSTS,.PKSTS(Q2),PKPSTS ;Status
PKYFLG::POINT PKSFLG,.PKSTS(Q2),PKPFLG ;Flags
PKYOP::	POINT PKSOP,.PKSTS(Q2),PKPOP   ;OP code
PKYNOD::POINT PKSNOD,.PKSTS(Q2),PKPNOD ;Node to send to

;The following are specialized for certain op codes

PKYREG::POINT PKSREG,.PKREG(Q2),PKPREG ;Register to read
PKYDTA::POINT PKSDTA,.PKREG(Q2),PKPDTA ;Data from register read
PKYCND::POINT PKSCND,.PKPND(Q2),PKPCND ;Node to point performance counter at
PKYFWD::POINT 32,(Q2),31	       ;Pointer for full word
PKYLHF::POINT 16,(Q2),15	       ;Left half
PKYRHF::POINT 16,(Q2),31	       ;Right half

PKYPPD::POINT PKSPPD,.PKLEN(Q2),PKPPPD ;CI.PPD
PKYPPM::POINT 8,.PKLEN(Q2),7	       ;Most sig byte of PPD field in 10 format
PKYPPL::POINT 8,.PKLEN(Q2),15	       ;Least sig byte of PPD field in 10 fmt
PKYLEN::POINT 20,.PKLEN(Q2),35		;Length for datagrams and messages

; Do not change the order of the next 4 pointers

PBYTE1:	POINT	8,T1,7
PBYTE3:	POINT	8,T1,23		;USED IN REVERSING BYTES IN A WORD
PBYTE2:	POINT	8,T1,15
PBYTE4:	POINT	8,T1,31
RS	BRKCNT,1		;NUMBER OF TIMES WE BROKE INTERLOCK
RS	MSCDAT,1		;DATA RETURNED DURING INIT
RS	KLPDIS,1		;FLAG TO SAY IF WE SHOULD RESTART AFTER PARITY ERROR

RS KLPFAI,1			;KLIPA FAILED FLAG:  0 = LAST START ATTEMPT WORKED
RS KLPRDY,1			;KLIPA READY FLAG:  0 = NOT READY FOR USE
RS CIHERE,1			;[7134] CI IN USE

SSTTMD==^D3000			;DEFAULT START SEQUENCE TIME OUT VALUE
RSI SSTTMO,SSTTMD		;START SEQUENCE TIME OUT VALUE

RS RIDNXT,1			;NEXT NODE FOR POLLER'S REQEUST ID
RS RIDTIM,MAXNDS+1		;REQUEST ID TIMER

RIDTMD==^D2000			;DEFAULT REQUEST ID TIME OUT VALUE
RSI RIDTMO,RIDTMD		;REQUEST ID TIME OUT VALUE

RS UCDTIM,1			;TIME FOR TRACKING UCODE RELOAD/DUMP
	NDSTIM==^D10000		;TIMEOUT VALUE FOR NEEDS-RELOADING/DUMPING
	IPRTIM==^D5000		;TIMEOUT VALUE FOR RELOAD/DUMP-IN-PROGRESS
RSI NDSTTM,NDSTIM		;PATCHABLE LOCATION TO HOLD TIMEOUT VALUE
RS RCTTIM,1			;NEXT TIME TO DO PERIODIC READ-COUNTERS
	RCTTMO==^D3600000	;PERIODIC READ-COUNTERS INTERVAL
RSI RCTPER,RCTTMO		;HOLDER OF INTERVAL VALUE
RS WIRNXT			;NEXT WIRE TO SEND LOOPBACK ON (0=A, -1=B)
RS CIWIRA			;CI WIRE A STATUS:  0=GOOD, -1=BAD
RS CIWIRB			;CI WIRE B STATUS:  0=GOOD, -1=BAD
RS BSDLOC,1			;POINTER TO LINKED LIST OF BSDS
RS BHDIPT,1			;INITIAL POINTER TO BUFFER DESCRIPTOR TABLE
RS BHDCPT,1			;CURRENT POINTER TO BUFFER DESCRIPTOR TABLE
RS OFFSET,1			;VIRTUAL TO PHYSICAL OFFSET OF INITIAL PACKETS
RS TIMKLP,1			;TIME OF LAST KLIPA ERROR
RS CHNCUN,1			;USED FOR SCANNING FOR QUEUED REQUESTS
RS CHNIUN,1			;DITTO
RS CRFNUM,1			;COMMAND REFERENCE NUMBER
RS BDTTAB,BHDNUM*L.BHD+3 	;BUFFER HEADER SESCRIPTORS
RS BSDTAB,BHDNUM*2*L.BSD+3 	;BUFFER SEGMENT DESCRIPTORS
RS QORTAB,BHDNUM*<QORLEN*2> 	;SPACE FOR QUEUES OF OUTSTANDING REQUESTS
RS PCB,L.PCB			;PORT CONTROL BLOCK
RS KLPXID,1			;TRANSACTION ID
RSI KLPOWN,777777		;OWNER OF THE INTERLOCK (777777 WHEN WE DON'T
				;HAVE IT, -1 FOR INTERRUPT LEVEL, 0 FOR PROCESS
				;CONTEXT, 1 FOR SCHEDULER CONTEXT)
RS KLPQ,1			;ADDRESS OF INTERLOCK WORD THAT WE GOT LAST
RS LSTCNI,1			;RESULT OF LAST CONI DONE IN KLPCHK
RS WIRCNT,1			;[7210] COUNT OF WIRE TRANSITIONS
RS WIRTIM,1			;[7210] TODCLK WHEN CURRENT COUNT OF 10 TRANSITIONS STARTED
RS KLPENT,2			;[7.1202] Time when we entered interrupt service
RSI (TOTKLP,<0,0>)		;[7.1202] Total time spent in PHYKLP at interrupt level
;Define CRC codes for loopback packet

LPBLEN==6			;LENGTH OF PACKET

LPBCRC:	365137,,27260		;Port 0
	461317,,343360		;Port 1
	777542,,171600		;Port 2
	73762,,215700		;Port 3
	142070,,514540		;Port 4
	646250,,670440		;Port 5
	550405,,442120		;Port 6
	254625,,726020		;Port 7
	731224,,250400		;Port 8
	35004,,134500		;Port 9
	323651,,306060		;Port 10
	427471,,62160		;Port 11
	516363,,763320		;Port 12
	212143,,407220		;Port 13
	104716,,635740		;Port 14
	600536,,551640		;Port 15
RS RIDSTS,MAXNDS+1		;REQUEST-ID STATUS
	MSKSTR IDSNT,RIDSTS,1B0	;LAST ID SENT:  0 = PATH A, 1 = PATH B
;	MSKSTR IDPAO,RIDSTS,1B1	;PATH A OPEN: 0 = CLOSED, 1 = OPEN
;	MSKSTR IDPBO,RIDSTS,1B2	;PATH B OPEN: 0 = CLOSED, 1 = OPEN
	MSKSTR IDNRA,RIDSTS,1B3	;NO-RESPONSE ON PATH A:  1 = NO RESPONSE
	MSKSTR IDNRB,RIDSTS,1B4	;NO-RESPONSE ON PATH B:  1 = NO RESPONSE
	MSKSTR IDTRY,RIDSTS,1B5	;LAST TRY STATUS:  0 = 1ST, 1 = 2ND
	MSKSTR IDWFR,RIDSTS,1B6	;WAITING FOR RESPONSE (FROM OUR PORT) TO REQUEST-ID
	MSKSTR IDRST,RIDSTS,1B8	;RESET REMOTE COMMAND HAS BEEN SENT
	MSKSTR IDSTA,RIDSTS,1B9	;START REMOTE COMMAND TO BE SENT
	MSKSTR IDMAI,RIDSTS,1B10 ;REMOTE PORT IS IN MAINTENANCE MODE
	MSKSTR IDNOR,RIDSTS,77B17 ;COUNT OF CONSECUTIVE NO-RESPONSES WHEN WE KNOW THE OTHER				; PORT IS RECEIVING OUR REQUEST-IDS
	MSKSTR IDSAD,RIDSTS,177777B35	;STARTING ADDRESS FOR REMOTE NODE


DEFSTR (DTLAR,,12,12)		;THE LAR
DEFSTR (DTCRM,,35,30)		;THE CONTENTS OF THE CRAM

RSI KSOFF,2			;OFFSET IN SPEAR ENTRY 241 FOR DATA
RS VER241,1			;USED WHILE MAKING ERROR.SYS ENTRY 241
MSKSTR KSRSN,VER241,KS%RSN	;REASON FIELD
MSKSTR KSCHN,VER241,KS%CHN	;KLIPA CHANNEL
MSKSTR KSVSN,VER241,KS%VSN	;UCODE VERSION

RS SRC246,1			;USED WHILE MAKING ERROR.SYS ENTRY 246
MSKSTR KECHN,SRC246,KE%CHN	;KLIPA CHANNEL #
MSKSTR KENOD,SRC246,KE%NOD	;HSC NODE #

RS UCDADR,1			;ADDRESS OF UCODE
RS UCDVER,1			;UCODE VERSION
MSKSTR UCMAJ,UCDVER,777B11	;[7.1134] Major version
MSKSTR UCMIN,UCDVER,77B17	;[7.1134] Minor version
MSKSTR UCEDT,UCDVER,777777B35	;EDIT NUMBER
	SUBTTL KLIPA Debugging Code

  IFN KLPDBG,<			;[7.1134] Move here from various places
	RESCD
COLECT::MOVEM T1,@PNTR
	CAIA
COLEC1::RET
	AOS T1,PNTR
	CAILE T1,DATEND
	MOVEI T1,DATA
	MOVEM T1,PNTR
	RET

KLPBUG:	RET			;debug breakpoint goes here

RSI (PNTR,<DATA>,1)		;ring buffer pointer
RS (DATA,137)			;ring buffer
RS (DATEND)			;ring buffer end pointer, must be first word 
				;  after ring buffer
RS RACES,1			;****counter for Sean ******
   >				;[7.1134] End of IFN KLPDBG
	SUBTTL System Startup -- KLPUCD (Read Microcode into Memory)

;GET CI UCODE INTO MONITOR RESIDENT MEMORY
;	CALL KLPUCD		;()
; RETURN +1 FAILED - T1/ ERROR CODE
;	 +2 SUCCESS

	RESCD

KLPUCD::SKIPN CIHERE		;[7444] Are we using the CI?
	RETBAD (KLPX7)		;NO, NO KLIPA
	STKVAR <FJFN,NWORD,TMPAD,ERCOD>
	MOVX T1,GJ%OLD!GJ%SHT	;FILE MUST EXIST
	HRROI T2,[ASCIZ/BS:[SYSTEM]IPALOD.EXE/]	;[7.1112]
	GTJFN%
	 RETBAD (GJFX18)
	MOVEM T1,FJFN		;PRESERVE JFN
	MOVE T2,[^D36B5!OF%RD]	;NEED TO READ 36-BIT BYTES
	OPENF%
	 RETBAD ()
	MOVEI T3,1146		;GET NUMBER OF UCODE WORDS
	RIN%
	 ERJMPR
	MOVEM T2,NWORD		;STASH IT
	ADDI T2,4		;NEED STOPPER AND VERSION WORDS, TOO
	IDIVI T2,1000		;CONVERT TO PAGES
	AOS T2			; ROUNDED UP
	IMULI T2,1000		;GO BACK TO WORDS
	BLCAL. (ASGVAS,<[1B1],T2>) ;(FLAGS,PAGES/T1) GET PAGES
	 RETBAD ()
	MOVEM T1,TMPAD		;STASH BUFFER ADDRESS
	MOVE T1,FJFN		;RETRIEVE JFN
	MOVEI T2,2000		;UCODE STARTS ON PAGE 2
	SFPTR%
	 RETBAD ()
	MOVE T4,TMPAD		;RETRIEVE BUFFER ADDRESS
	MOVE T2,[POINT 36,(T4)]	;DESTINATION
	MOVE T3,NWORD		;RETRIEVE NUMBER OF UCODE WORDS
	ADDI T3,4		;GET STOPPER AND VERSION WORDS, TOO
	MOVNS T3		;SET BYTE COUNT
	SIN%			;READ IN UCODE
	 ERJMPR
	MOVE T2,TMPAD		;GET BACK UCODE ADDRESS
	MOVEM T2,UCDADR		;SET IT FOR GOOD
	CLOSF%			;ALL DONE
	 RETBAD ()
	RETSKP

	ENDSV.
	SUBTTL System Startup -- PPDINX (Initialize SCA)

;PPDINX - CALLED FROM MEXEC AFTER SWAPPABLE MONITOR IS LOADED
;RETURNS:	+1

;NOTE: When this routine is called, KLPINI has already been called;
;      the CDB and PCB are set up for the KLIPA.

PPDINX::SAVEAC <P1>
	SKIPN P1,CHNTAB+KLPRH2	;GET CDB
	RET			;NONE
	MOVE T1,CDBSTS(P1)	;GET STAATUS
	TXNN T1,CS.CIP		;IS IT A KLIPA?
	RET			;NO. DON'T BOTHER WITH THE REST
	CALL SCA		;(/) INITIALIZE SCA
	CALL STKDFQ		;(P1/) STOCK THE DATAGRAM FREE QUEUE
	MOVEI T1,CHNNRL		;PORT NEEDS
	STOR T1,CFSTA,(P1)	; RELOADING
	MOVE T1,TODCLK		;GET NOW
	ADD T1,NDSTTM		;GET TIMEOUT TIME
	MOVEM T1,UCDTIM		;SET IT
	RET
	SUBTTL Routines for sending data

;SNDDG/SNDMSG - Send datagram or message via virtual circuit control

;Length is words if high density, bytes if industry compatible

SNDDG::	BLSUB.	(<SS.LEN,SS.FLG,SS.SBA,SS.PKA,SS.PRI>)
	SAVEPQ
	MOVEI	P4,OP.SDG	;OPCODE
	JRST	SENDPK


SNDMSG::BLSUB.	(<SS.LEN,SS.FLG,SS.SBA,SS.PKA,SS.PRI>)
	SAVEPQ
	MOVEI	P4,OP.SMS	;OPCODE
	;..

SENDPK:	
	MOVE T4,SS.LEN		;GET PACKET LENGTH
	MOVE Q3,SS.FLG		;GET FLAGS
	TXNE Q3,F.SPM		;Is this high density, I.E. a word length???
	 IFNSK.
	  MOVEI Q1,1(T4)	;Yes, get copy, rounded up for later div by 2
	  IMULI T4,4		;Account for whole byte count
	  IDIVI Q1,2		;Now get the number of extra bytes left over
	  ADD T4,Q1		;Add fractional part to whole to get byte total
	 ENDIF.
	MOVE Q2,SS.PKA		;GET ADDRESS OF PACKET
	DPB T4,PKYLEN		;STORE LENGTH IN PACKET
	MOVEI	T4,PP.DG-OP.SDG(P4) ;COMPUTE PPD BYTE
	DPB	T4,PKYPPD	;SAVE IT IN THE PACKET
	CALL MASAGE
	SETZ	T3,
	TXNE	Q3,F.RTB	;WANT A RESPONSE?
	MOVX T3,PF.RSP		;YES, GET PACKET RESPONSE BIT
	TXNE	Q3,F.SPM	;WANT HIGH DENSITY MODE?
	TXO	T3,PF.FMT
	MOVE T2,SS.PRI		;GET PRIORITY
	MOVE T1,P4		;OP CODE
	MOVE P5,SS.SBA		;GET ADDRESS OF SYSTEM BLOCK
	CALL SENDVC		;(T1,T2,T3,P5,Q2)SEND UNDER V.C. CONTROL
	 RETBAD ()
	RETSKP

	ENDBS.
;SNDDAT/REQDAT - SEND AND RECEIVE DATA

SNDDAT::BLSUB.	(<SS.SNM,SS.RNM,SS.SOF,SS.ROF,SS.CID>)
	MOVEI	T1,OP.SDT	;OP CODE FOR SEND DATA
	JRST	SNDREC

REQDAT::BLSUB.	(<SS.SNM,SS.RNM,SS.SOF,SS.ROF,SS.CID>)
	MOVEI	T1,OP.RD1	;OP CODE FOR READ DATA

; * * * *
;Do we need to shift some of these values left?
;Need to handle failure case by returning buffer to SCA.
; * * * *

SNDREC:	SAVEPQ
	MOVE	Q2,T1		;SAVE OP CODE
	MOVEI	T1,1
	CALL	SC.ABF		;GET A BUFFER FROM SCA
	  RETBAD ( )		;NONE. LOSE
	EXCH	T1,Q2		;BUFFER ADDR IN Q2, OP CODE IN T1
	MOVE	T2,SS.SNM	;SENDER NAME
	MOVE	T3,T2		;IF DOING A SEND, THIS IS OUR BUFFER NAME
	MOVEM	T2,.PKSNM(Q2)	;SAVE WHERE PORT WANTS SENDER NAME
	MOVE	T2,SS.RNM	;REC'R NAME
	CAIN	T1,OP.RD1	;ARE WE READING?
	MOVE	T3,T2		;YES. THIS IS OUR BUFFER NAME
	MOVEM	T2,.PKRNM(Q2)	;WHERE PORT WANTS REC'R NAME
	MOVE	T2,SS.SOF	;SENDER OFFSET
	MOVEM	T2,.PKSOF(Q2)	;INTO PACKET
	MOVE	T2,SS.ROF	;RECEIVER OFFSET
	MOVEM	T2,.PKROF(Q2)	;INTO PACKET
	MOVEM	T3,.PKXID(Q2)	;SENDER OR RECEIVER BUFFER NAME INTO XID
	MOVE	T2,SS.CID	;CID INTO OTHER XID
	MOVEM	T2,.PKXID+1(Q2)	;SO WE CAN TELL SCA ON THE INTERRUPT
	$LDCID	T2,T2		;GET CONNECTION BLOCK ADDRESS
	MOVE	P5,.CBSBA(T2)	;SYSTEM BLOCK (KDB)
	LDB	T2,[POINT BHSIDX,T3,BHPIDX] ;BHD INDEX FROM BUFFER NAME
	ADD	T2,BHDIPT	;POINT AT BHD TABLE ENTRY
	MOVE	T2,.BHLEN(T2)	;GET NIBBLE COUNT FROM BHD
	LSH	T2,-1+4		;CONVERT TO BYTE COUNT AND THEN SHIFT IT
	MOVEM	T2,.PKXLN(Q2)	;SAVE AS TRANSACTION LENGTH
	MOVEI T2,KLPMED		;PRIORITY
	MOVX T3,PF.SIZ		;INDICATE 576-BYTE PACKETS
	CALL SENDVC		;(T1,T2,T3,P5,Q2) SEND IT VIA VIRTUAL CIRCUIT CONTROL
	 JRST [	EXCH T1,Q2	;FAILED. RETURN BUFFER TO SCA
		CALL SC.RBF
		MOVE T1,Q2	;RESTORE ERROR CODE
		RETBAD ()]
	RETSKP

	ENDBS.
;SNDMAI/REQMAI - SEND AND RECEIVE MAINTENANCE DATA
;	RETURNS +1 ERROR
;		+2 OKAY
;	SS.SNM - SENDING BUFFER NAME
;	SS.RNM - RECEIVING BUFFER NAME
;	SS.SOF - SENDING BUFFER OFFSET
;	SS.ROF - RECEIVING BUFFER OFFSET
;	NODCHN - CHANNEL AND NODE NUMBER

;SEND MAINTENANCE DATA

SNDMAI::BLSUB.	(<SS.SNM,SS.RNM,SS.SOF,SS.ROF,NODCHN>)

	MOVEI T1,OP.SMD		;OP CODE FOR SEND MAINT. DATA
	JRST SNDMA1

;REQUEST(RECEIVE) MAINTENANCE DATA

REQMAI::BLSUB.	(<SS.SNM,SS.RNM,SS.SOF,SS.ROF,NODCHN>)

	MOVEI T1,OP.RMD		;OP CODE FOR READ MAINT. DATA

SNDMA1: SAVEPQ
	MOVE Q3,T1		;SAVE OP CODE
	HLRZ P1,NODCHN		;GET THE CHANNEL NUMBER
	MOVE P1,CHNTAB(P1)	;GET THE CHANNEL ADDRESS
	MOVEI T1,1
	CALL PPDGDB		;(P1/T1) GET A BUFFER
	  RETBAD ( )		;NONE. LOSE
	EXCH T1,Q3		;BUFFER ADDR IN Q2, OP CODE IN T1
	MOVE T2,SS.SNM		;SENDER NAME
	MOVE T3,T2		;IF DOING A SEND, THIS IS OUR BUFFER NAME
	MOVEM T2,.PKSNM(Q2)	;SAVE WHERE PORT WANTS SENDER NAME
	MOVE T2,SS.RNM		;REC'R NAME
	CAIN T1,OP.RMD		;ARE WE READING?
	MOVE T3,T2		;YES. THIS IS OUR BUFFER NAME
	MOVEM T2,.PKRNM(Q2)	;WHERE PORT WANTS REC'R NAME
	MOVE T2,SS.SOF		;SENDER OFFSET
	MOVEM T2,.PKSOF(Q2)	;INTO PACKET
	MOVE T2,SS.ROF		;RECEIVER OFFSET
	MOVEM T2,.PKROF(Q2)	;INTO PACKET
	MOVEM T3,.PKXID(Q2)	;SENDER OR RECEIVER BUFFER NAME INTO XID
	LDB T2,[POINT BHSIDX,T3,BHPIDX] ;BHD INDEX FROM BUFFER NAME
	ADD T2,BHDIPT		;POINT AT BHD TABLE ENTRY
	MOVE T2,.BHLEN(T2)	;GET NIBBLE COUNT FROM BHD
	LSH T2,-1+4		;CONVERT TO BYTE COUNT AND THEN SHIFT IT
	MOVEM T2,.PKXLN(Q2)	;SAVE AS TRANSACTION LENGTH
	SETZM T3
	HRRZ Q1,NODCHN		;GET THE NODE NUMBER
	MOVE Q3,CDBPCB(P1)	;GET THE PCB ADDRESS
	CALL DIASND		;(T1,T3,Q1,Q2,Q3/) SEND THE DATAGRAM
	RETSKP
	ENDBS.
;CLOSE A BUFFER - THIS ROUTINE ISSUES A CLSBUF COMMAND (205)

;BLCAL. (CLOBUF,<BUFNAM,BUFADR,PCBADR>)   
;	BUFNAM - BUFFER NAME
;	BUFADR - COMMAND BUFFER ADDRESS
;	PCBADR - PCB ADDRESS
;	RETURNS +2: ALWAYS

CLOBUF::BLSUB. (<BUFNAM,BUFADR,PCBADR>)
	SAVEQ
	MOVE T1,BUFNAM		;GET THE BUFFER NAME
	MOVE Q2,BUFADR		;GET COMMAND PACKET ADDRESS
	MOVE Q3,PCBADR		;GET THE PCB ADDRESS
	MOVEM T1,.PKBNM(Q2)		;STORE IT IN COMMAND PACKET
	MOVEI T1,OP.CLB		;GET COMMAND
	MOVEI T2,KLPMED		;GET PRIORITY
	SETZM Q1		;CLEAR NODE NUMBER
	MOVX T3,PF.RSP		;RESPONSE IS REQUESTED.
	CALLRET DRVSND		;(T1,T2,T3,Q1,Q2,Q3/)
	ENDBS.
;SENDVC - SEND PACKET UNDER VIRTUAL CIRCUIT CONTROL

;ACCEPTS:
;	T1/ OP CODE
;	T2/ PRIORITY
;	T3/ FLAGS
;	Q2/ ADDRESS OF PACKET
;	P5/ ADDRESS OF SYSTEM BLOCK

;	CALL SENDVC

;RETURNS +1: FAILURE
;	 +2: SUCCESS

SENDVC:	LOAD T4,SBVCST,(P5)	;GET VC STATE
	CAIE T4,VC.OPN		;IS IT OPEN?
	RETBAD (KLPX9)		;NO
	MOVE Q3,.SBAPB(P5)	;POINT Q3 AT PCB
	LOAD Q1,SBDPA,(P5)	;Q1 = DESTINATION PORT(NODE) NUMBER
	SETZRO PKSRB,(Q2) 	;ASSUME NO RESPONSE BITS DESIRED
	TXNN T3,PF.RSP		;WANT A RESPONSE?
	IFSKP.
	   SETONE PKSCA,(Q2)	;YES, SET THE SCA SOFTWARE RESPONSE BIT
	ENDIF.
	CALL KLPSND		;(T1,T2,T3,Q1,Q2,Q3) SEND THE PACKET
	 RETBAD ()
	RETSKP
COMMENT #

	The routine CLOSVC closes an open virtual circuit;  it is called from
within PHYKLP and externally from SCAMPI.  Examples are:  1) PHYKLP calls it
when it discovers the CI20 has stopped due to a CRAM parity error, 2) a packet
whose delivery is guaranteed has encountered an error,  3) SCAMPI calls CLOSVC
when an idle chatter response has timed out.  There are other reasons for 
calling CLOSVC but the idea is always the same.  CLOSVC always calls SC.ERR to
tell SCAMPI the state of the virtual circuit has been set to closed and further
calls to SENDVC will fail.  If CLOSVC can't get a datagram buffer for the Set
Circuit (to close) command, it sets SBNTC (need to close) and the once-a-second
routine CHKOPC will attempt to do it.  When either CLOSVC or CHKOPC actually do
the Set Circuit, they set SBWFI indicating we are waiting for a new (after
closing the virtual circuit) IDREC.  WARNING: SBNTC must be cleared in NONODS.

	The routine OPENVC requests steps be intiated to attempt to open a
closed virtual circuit.  OPENVC always sets SBOKO (OK to open).  Once a
virtual circuit has been established with a node and subsequently closed,
PHYKLP only begins trying to open the virtual circuit again at the direction
of SCAMPI.  The only time PHYKLP initiates the opening procedure is upon
getting an IDREC from a node with which we have never had an open virtual
circuit.  OPENVC always sets SBOKO;  this tells routine INTIDR to send a Start
once the close has completed and we have received a fresh IDREC.  OPENVC will
try to send a Request-Id if the close has been accomplished.  Sending a
Request-Id from OPENVC is an attempt to get a new IDREC as soon as possible.

	The routine INTIDR processes IDRECs, the responses to Request-Ids.
If a virtual circuit's state is closed, this routine will send a Start if
1) the Set Circuit (to close) has been done, and 2) SBOKO (it's OK to open)
has been set by OPENVC.  WARNING:  Don't clear SBOKO until SC.ONL is called.

#
;OPEN VIRTUAL CIRCUIT
;RETURNS:	+1

OPENVC::BLSUB. (<SBA>)
	SAVEPQ
	MOVE P5,SBA		;GET SB
	SKIPN P5		;IS IT POSSIBLE?
	BUG. (HLT,KLPNSB,PHYKLP,SOFT,<PHYKLP - No system block at OPENVC>,,<

Cause:	OPENVC was called with a system block address of 0.
>)
	MOVE Q3,.SBAPB(P5)	;GET PCB
	LOAD Q1,SBDPA,(P5)	;GET NODE NUMBER
	LOAD T1,SBVCST,(P5)	;GET VC STATE
	CAIE T1,VC.CLO		;CLOSED?
	BUG. (HLT,KLPONC,PHYKLP,SOFT,<PHYKLP - Trying to open a VC which isn't closed>,,<

Cause:	OPENVC was called when the VC was not closed.
>)
	SETONE SBOKO,(P5)	;SAY IT'S OK TO OPEN
	MOVE T1,CHNTAB+KLPRH2	;GET CDB
	LOAD T1,CFSTA,(T1)	;GET STATE OF PORT
	CAIE T1,CHNRUN		;IS IT RUNNING?
	RET			;NO
	TMNN SBNTC,(P5)		;STILL TRYING TO CLOSE?
	CALL KLPGDB		;(Q3/Q2) NO, GET A DATAGRAM BUFFER
	 RET			;THAT'S IT FOR NOW.  ONCE-A-SECOND WILL DO IT

;Sending a REQUEST-ID here may speed up the reopening since the once-a-second
;poller may not get to this node for a while.

	SKIPE RIDTIM(Q1)	;ALREADY HAVE A REQUEST-ID ON OUT THERE?
	RET			;YES
	CALL GTNPTH		;(Q1/T3) GET PATH FOR REQUEST-ID
	CALL KLPRID		;(T3,Q1,Q2,Q3/) SEND REQUEST-ID
	 NOP			;NO SUCH RETURN
	RET

	ENDBS.
;CLOSE VIRTUAL CIRCUIT
;RETURNS:	+1
;
;NOTE:  CLOSVC is called by SCAMPI, CLOSV1 by PHYKLP.

CLOSVC::BLSUB. (<SS.SBA>)
	SAVEPQ
	SETZB Q2,P4		;NEED TO GET A BUFFER AND DO SET CIRCUIT
	MOVE P5,SS.SBA		;GET SYSTEM BLOCK
	TDZA T2,T2		;FLAG THAT WE WANT TO SEND A SHUTDOWN

;LOCAL ENTRY POINT
;ACCEPTS:	Q2/ ADDRESS OF BUFFER TO BE USED FOR KLPCLO
;		    0 = NEED A BUFFER
;		P4/ 0 = DO THE SET CIRCUIT
;		    -1 = DON'T NEED TO DO SET CIRCUIT
;		P5/ SB

CLOSV1:	SETOM T2		;NO SHUTDOWN REQUIRED
	STKVAR <BUFADR>
	MOVEM Q2,BUFADR

;At this point, T2/0 if SCA initiated the closing. In that case, we'll
;send a shutdown to the other side. Otherwise, T2/-1, and the other
;side probably already knows about the failure.

	CIOFF			;DON'T LET INT LEVEL EVENTS CHANGE STATE OF VC
	LOAD T1,SBVCST,(P5)	;GET VC STATE
	CAIE T1,VC.OPN		;OPEN?
	JRST CLOSVX		;NO, DONE
	MOVEI T1,VC.CLO		;GET CLOSED CODE
	STOR T1,SBVCST,(P5)	;SET IT
	LOAD Q1,SBDPA,(P5)	;GET NODE NUMBER

;Try to send a shutdown if SCA asked for the closing. If there's no buffer,
;we can continue, and the other side will find out when it gets a START
;sometime later.

	MOVE Q3,.SBAPB(P5)	;GET PCB
	SKIPE T2		;WANT TO SEND A SHUTDOWN?
	IFSKP.
	  CALL KLPGDB		;(Q3/Q2) GET A BUFFER IF WE CAN
	   JRST CLOSV5		;NO BUFFER. NOT A DISASTER
	  MOVEI T1,PP.SHT	;GET PPD BYTE FOR SHUTDOWN
	  DPB T1,PKYPPD		; AND STORE IT IN THE PACKET
	  CALL KLPSDG		;(Q1,Q2,Q3/) SEND IT
	   NOP
	ENDIF.
CLOSV5:	SKIPE P4		;DO THE SET CIRCUIT?
	JRST CLOSV3		;NO
;...
;...

	SKIPE Q2,BUFADR		;HAVE A BUFFER FOR THE SET CIRCUIT?
	JRST CLOSV2		;YES. GO SEND IT
	CALL KLPGDB		;(Q3/Q2) GET A DATAGRAM BUFFER
	 IFNSK.
	    SETONE SBNTC,(P5)	;FAILED, SAY WE STILL NEED TO CLOSE VC
	    JRST CLOSV4		;TELL SCA WE'RE CLOSED
	 ENDIF.
CLOSV2:	CALL KLPCLO		;(Q1,Q2,Q3) SEND THE PACKET
	 NOP			;NO SUCH RETURN
CLOSV3:	SETONE SBWFI,(P5)	;WAITING FOR A FRESH IDREC
CLOSV4:	SKIPE CLDWRD		;[7.1021] Has a cluster-dump been requested?
	IFSKP.			;[7.1021] No, just BUGINF
	  BUG. (INF,KLPCVC,PHYKLP,SOFT,<PHYKLP - Closed virtual circuit>,<<Q1,NODE>>,<

Cause:	TOPS-20 has closed a virtual circuit to a remote node on the CI.

Data:	NODE - CI node number
>,,<DB%NND>)			;[7.1210][7.1021]
	ELSE.			;[7.1021] Yes, so BUGHLT instead!
	  BUG. (HLT,KLPDMP,PHYKLP,SOFT,<PHYKLP - Cluster dump requested>,<<Q1,NODE>>,<

Cause:	TOPS-20 has closed a virtual circuit to a remote node on the CI.
	But, previous to this, this node's cluster dump listener received 
	a connection indicating that a cluster dump was in progress.  So,
	the node is crashing upon receipt of the node offline indication.
	The node which requested the cluster dump should have crashed with
	a CFCLDP BUGHLT.

Data:	NODE - CI node number to which we lost our VC
>)				;[7.1021]
	ENDIF.			;[7.1021]
	BLCAL. (SC.ERR,<Q1>)	;TELL SCA
	 NOP			;WE DID OUR BEST
CLOSVX:	CION
	RET

	ENDSV.
	ENDBS.
;ROUTINE TO SEND A REQUEST ID

;ACCEPTS:	T3/ FLAGS
;		Q1/ NODE NUMBER
;		Q2/ ADDRESS OF PACKET
;		Q3/ PCB ADDRESS

;	CALL KLPRID

;RETURNS +1: FAILURE
;	 +2: SUCCESS

KLPRID:	MOVE T1,TODCLK		;GET CURRENT TIME
	ADD T1,RIDTMO		;CALC TIME OUT TIME
	MOVEM T1,RIDTIM(Q1)	;SET TIME OUT TIME
	MOVEI T1,20
	ADDB T1,KLPXID		;GET NEW TRANSACTION ID
	MOVEM T1,.PKXID(Q2)	;SAVE FIRST WORD
	MOVEM T1,.PKXID+1(Q2)	; AND SECOND WORD
	MOVEI T1,OP.RID		;GET OPCODE
	MOVEI T2,KLPDRG		;LOW PRIORITY
	CALLRET	DRVSND		;(T1,T2,T3,Q1,Q2,Q3) SEND THE PACKET

;KLPRRG - Routine to send a Read Register

;ACCEPTS:
;	Q2/ ADDRESS OF PACKET
;	Q3/ ADDRESS OF PCB

;	CALL KLPRRG

;Returns +1: Failure
;	 +2: Success

KLPRRG:
	SETZB Q1,.PKREG(Q2)	;CLEAR MBZ FIELDS, "NODE NUMBER"
	MOVEI T2,.RGNOD		;NODE NUMBER IS THE REGISTER TO READ
	DPB T2,PKYREG		;WHERE IT WILL DO THE MOST GOOD
	SETZM T3		;FLAGS WORD IS 0
	MOVEI T1,OP.RRG		;OP = READ REGISTER
	MOVEI T2,KLPDRG		;PRIORITY
	CALL DRVSND		;(T1,T2,T3,Q1,Q2,Q3) ASK THE KLIPA WHO WE ARE
	 RETBAD
	RETSKP
;KLPSCK - ROUTINE TO SEND SET CIRCUIT

;KLPSDG - ROUTINE TO SEND A DATAGRAM WITHOUT AN OPEN V.C.

;ACCEPTS:
;	Q1/ Node number
;	Q2/ address of buffer
;	Q3/ PCB address
;	CALL KLPSCK/KLPSDG/KLPOPN

;RETURNS +1: FAILURE
;	 +2: SUCCESS

;KLPOPN - Entry point for telling port to open V.C.
;KLPCLO - Entry point for telling port to close V.C.

;When calling KLPSCK directly, caller must store .PKCKT word according
;to function desired

KLPCLO:	MOVX T1,CK.LST		;CLOSE VIRTUAL CIRCUIT
	SETZRO <IDPAO,IDPBO>,(Q1)  ;BOTH PATHS CLOSED
	JRST KLPOP1		;MOVE ON

KLPOPN:	MOVE T1,[CK.LST!CK.CST!CK.LPT!CK.PGD] ;OPEN VIRTUAL CIRCUIT
	SETONE <IDPAO,IDPBO>,(Q1)  ;BOTH PATHS OPEN
KLPOP1:	MOVEM T1,.PKCKT(Q2)	;ASSUME NR-NS=0 INITIALLY
KLPSCK:	MOVEI T1,OP.CKT		;SET VC
	MOVEI T3,20
	ADDB T3,KLPXID		;GET NEW TRANSACTION ID
	MOVEM T3,.PKXID(Q2)	;SAVE FIRST WORD
	MOVEM T3,.PKXID+1(Q2)	; AND SECOND WORD
	JRST KLPS1

KLPSDG:	LDB T1,PKYPPD		;GET PACKET TYPE
	MOVE T2,STRLEN(T1)	;LOOK UP PACKET LENGTH
	DPB T2,PKYLEN		;STORE IT IN PACKET
	CALL MASAGE		;SWAP THE PPD BYTE AND ADJUST LENGTH
	MOVEI T1,OP.SDG		;SEND DATAGRAM

KLPS1:	MOVEI T2,KLPDRG		;PRIORITY
	SETZ T3,		;NO FLAGS
	CALLRET	DRVSND		;(T1,T2,T3,Q1,Q2,Q3) SEND THE DATAGRAM


;START PACKET LENGTH TABLE

STRLEN:	SR.LEN			;(PPD = 0) START LENGTH
	SR.LEN			;(PPD = 1) STACK LENGTH
	SR.ALN			;(PPD = 2) ACK LENGTH
	0			;3 - application datagram doesn't come here
	0			;4 - application message doesn't come here
	0			;5 - error packet doesn't come here
	SR.ALN			;6 - Shutdown
;ENTRIES FROM SCA RMTSTA AND RMTRST CALLS.

;RMTRST - RESET THE REMOTE NODE 
;	USAGE
;	BLCAL. (RMTRST,<RNODE,SS.FRB>)
;		RNODE=NODE TO BE RESET
;		SS.FRB=FORCE THE RESET
RMTRST::BLSUB.(<RNODE,SS.FRB>)
	SAVEAC <Q1,Q2,Q3,P1>
	MOVE P1,CHNTAB+KLPRH2	;GET CDB ADDRESS 
	CALL PPDGDB
	  RETBAD ()
	MOVE Q1,RNODE		;GET THE NODE
	SETONE IDRST,(Q1)	;SET RESET REMOTE INDICATOR
	SETZRO IDSTA,(Q1)	;DO NOT SEND A START
	SETZRO IDSAD,(Q1)	;CLEAR ANY STARTING ADDRESS
	HRLZ Q3,SS.FRB		;GET THE FORCE ARGUMENT
	HRLI Q1,KLPRH2		;GET THE CHANNEL NUMBER
	CALL PPDSRS		
	RETSKP

RMTSTA::BLSUB.(<RNODE,SS.DSA,SS.STA>)
	SAVEQ
	MOVE Q1,RNODE		;GET THE NODE NUMBER
	SKIPE SS.STA		;IS A STARTING ADDRESS WANTED?
	IFNSK.
	  HRRZ Q3,SS.DSA	;YES.
	  STOR Q3,IDSAD,(Q1)	;YES. STORE THE STARTING ADDRESS.
	ENDIF.
	SETONE IDSTA,(Q1)	;SET THE START REMOTE FLAG
	RETSKP
;ROUTINE TO SEND A START OR RESET MAINTENANCE FUNCTION
;CALL:	Q1/CHAN,,NODE
;	Q2/PACKET ADDRESS
;	Q3/N,,0  =	RESET. N NON-0 => FORCE
;	Q3/N,,-1 =	START. N=START ADDR (0=DEFAULT)
PPDSRS::HLRZ	T1,Q1		;CHAN
	MOVE	T1,CHNTAB(T1)	;GET CDB ADDRESS
	MOVE	T1,CDBPCB(T1)	;GET PCB
	HRRZS	Q1		;Q1=NODE
	EXCH	Q3,T1		;Q3=PCB ADDR
	TRNE	T1,-1		;RESET?
	JRST	KLPSST		;NO. START
	SETZM	T3		;YES. ASSUME NO FLAGS
	TLNE	T1,-1		;FORCE?
	MOVX	T3,PF.FRC	;YES. LIGHT THE BIT IN FLAGS WORD
	MOVEI	T1,OP.RRS	;FUNCTION = RESET
	CALLRET	DIASND		;(T1,T3,Q1,Q2,Q3) SEND THE DG

KLPSST:	HLRZ	T2,T1		;START ADDRESS
	LSH	T2,4		;POSITION IT
	MOVEM	T2,.PKSAD(Q2)	;STUFF IN THE PACKET
	SETZM	T3		;NO FLAGS
	TLNN	T1,-1		;WAS THERE A START ADDR?
	MOVX	T3,PF.DSA	;NO. ASK FOR DEFAULT STARTING ADDRESS
	MOVEI	T1,OP.SRS	;FUNCTION = START
	CALLRET	DIASND		;(T1,T3,Q1,Q2,Q3) SEND THE START AND RETURN
;ROUTINE TO SET COUNTERS
;ACCEPTS:	Q1/MASK,INCLUDING THRESHOLD
;		Q2/PACKET TO USE
;		Q3/NODES
;		P1/CDB
;RETURNS:	+1

PPDSPT::MOVEM Q1,.PKMSK(Q2)
	SETZM .PKPND(Q2)	;CLEAR PORT WORD
	DPB Q3,PKYCND		;WHICH NODE TO MONITOR
	MOVEI T1,OP.SPT		;OPERATION IS SET POINTERS
	SETZB T3,Q1		;NO FLAGS, PORT FIELD = 0
	MOVE Q3,CDBPCB(P1)	;ADDRESS OF THE PCB
	CALLRET	DIASND		;(T1,T3,Q1,Q2,Q3) TELL THE KLIPA TO SEND IT


;READ COUNTERS
;ACCEPTS:	T2/ REASON CODE
;		Q2/ PACKET ADDRESS
;		P1/ CDB
;RETURNS:	+1

PPDRPT::MOVEI T1,OP.RCT		;FUNCTION
	SETZB T3,Q1		;NO FLAGS, PORT = 0
	MOVE Q3,CDBPCB(P1)	;GET ADDRESS OF PCB
	MOVEM T2,.PKXID(Q2)	;PUT REASON IN PACKET (IT'S IN THE XID WORD)
	MOVEI T2,KLPDRG		;PRIORITY
	CALL DRVSND		;(T1,T2,T3,Q1,Q2,Q3) SEND THE PACKET
	 JFCL			;NO SUCH RETURN
	RET
	
;ACCEPTS:	T1/ OP CODE
;		T3/ FLAGS
;		Q1/ NODE NUMBER
;		Q2/ ADDRESS OF PACKET
;		Q3/ ADDRESS OF PCB
;RETURNS:	+1

DIASND:	MOVEI T4,20
	ADDB T4,KLPXID		;GET NEW TRANSACTION ID
	MOVEM T4,.PKXID(Q2)	;SAVE FIRST WORD
	MOVEM T4,.PKXID+1(Q2)	; AND SECOND WORD
	MOVEI T2,KLPDRG		;PRIORITY
	CALL DRVSND		;(T1,T2,T3,Q1,Q2,Q3) SEND THE PACKET
	 JFCL			;NO SUCH RETURN
	RET
;Called from CHKR to do a READ-COUNTERS
;RETURNS:	+1

	SWAPCD

KLPRCT::SKIPN CIHERE		;[7444] Are we using the CI?
	RET			;NO KLIPA
	MOVE T1,TODCLK		;GET CURRENT TIME
	CAMGE T1,RCTTIM		;TIME TO DO COUNTERS AGAIN?
	RET			;NO
	ADD T1,RCTPER		;YES, CALCULATE NEXT TIME
	MOVEM T1,RCTTIM		;SET IT
	SAVEPQ
	MOVE P1,CHNTAB+KLPRH2	;GET CDB
	CALL PPDGDB		;(P1/Q2) GET A DATAGRAM BUFFER
	 RET
	MOVEI T2,KS%PER		;GET REASON FOR DOING READ-COUNTERS
	CALLRET PPDRPT		;(T2,Q2,P1) DO A READ-COUNTERS

	RESCD
;SET THE SOFTWARE RESPONSE BITS
;ACCEPTS:	T1/OPCODE
;		T2/PRIORITY
;		T3/FLAGS
;		Q1/NODE NUMBER
;		Q2/BUFFER ADDRESS
;		Q3/PCB ADDRESS
;RETURNS:	+1 FAILURE
;		+2 SUCCESS

DRVSND:	SETZRO PKSRB,(Q2) 	;ASSUME NO RESPONSE BITS DESIRED
	TXNN T3,PF.RSP		;DOES THE DRVIER WANT THE BUFFER BACK?
	IFSKP.
	   SETONE PKDRV,(Q2)	;YES, SET THE SOFTWARE RESPONSE BIT
	ENDIF.
	CALLRET KLPSND		;(T1,T2,T3,Q1,Q2,Q3) SEND THE PACKET
;ROUTINE TO SEND A PACKET
;ACCEPTS:	T1/OPCODE
;		T2/PRIORITY
;		T3/FLAGS
;		Q1/NODE NUMBER
;		Q2/BUFFER ADDRESS
;		Q3/PCB ADDRESS
;	CALL KLPSND
;RETURNS:	+2

KLPSND:
   IFN KLPDBG,<
	MOVSI T4,-<KLPOPL>	;COPIED FROM KLPINT
KLPSN1:	CAMN T1,KLPOPS(T4)	;DO WE KNOW THIS OP CODE?
	JRST KLPSN2		;YES.
	AOBJN T4,KLPSN1		;KEEP LOOKING
	BUG. (HLT,KLPIOP,PHYKLP,SOFT,<PHYKLP - Invalid opcode>,,<

Cause:	KLPSND was called with an invalid opcode.
>)
   >
KLPSN2:	MOVEM T3,.PKSTS(Q2)	;SAVE FLAGS
	DPB Q1,PKYNOD		;SAVE NODE NUMBER
	DPB T1,PKYOP		;SAVE OPERATION
	SKIPGE T2		;PRIORITY CAN'T BE NEGATIVE
	BUG. (HLT,KLPPRI,PHYKLP,SOFT,<PHYKLP - Invalid priority>,,<

Cause:	KLPSND was called with an invalid priority.
>)
	CAILE T2,MAXQUE		;TOO LOW?
	MOVEI T2,MAXQUE		;YES, REDUCE IT TO LOWEST PRIORITY WE HAVE
	AOS CMDQS(T2)		;[7211] COUNT THE COMMAND
	IMULI T2,.PBBLI+1	;COMPUTE ADDRESS OF QUEUE
	ADDI T2,.PBQ3I(Q3)
	MOVE T1,T2		;PROVIDE ADDRESS OF FLINK TO PUTQUE
	CALL PUTQUE		;INSERT THE PACKET ON QUEUE
	 TDZA T4,T4		;REMEMBER EMPTY QUEUE
	SETOM T4		;REMEMBER NON-EMPTY QUEUE
IFN KLPDBG,<
	MOVE	T1,10(Q2)	;command reference number
	CALL	COLEC1
>
;Label for CILOOK SNOOP code

CILOUT:	MOVE T1,.PBPIA(Q3)	;PICK UP PIA ASSIGNMENT
	SKIPN T4		;WAS QUEUE EMPTY?
	CONO KLP,CO.CQA+CO.BTS(T1) ;QUEUE WAS EMPTY - KICK THE PORT
IFN KLPDBG,<
SPION:	MOVEI	T1,.
	HRL	T1,Q2
	CALL	COLECT
	MOVE	T1,3(Q2)	;GET STATUS WORD
	CALL	COLECT
>
	AOS CIPKSN		;[7211] COUNT THE SEND
	RETSKP			;NO, RETURN TO CALLER
	SUBTTL Routines for manipulating queues

;ULNKDG/ULNKMG - UNLINK A BUFFER FROM THE DATAGRAM OR MESSAGE FREE QUEUE
;	CALL ULNKDG for datagram free queue
;	CALL ULNKMG for message free queue

;RETURNS:	+1 FAILED.   T1/ ERROR CODE
;		+2 SUCCESS.  T1/ BUFFER ADDRESS

ULNKDG::BLSUB. (<SS.SBA>)
	MOVX T1,.PBDFI		;GET DATAGRAM FREE QUEUE INTERLOCK
	JRST ULNKM2

ULNKMG::BLSUB. (<SS.SBA>)
	MOVX T1,.PBMFI		;GET MESSAGE FREE QUEUE INTERLOCK

ULNKM2:	SAVEAC <Q2,Q3,P5>
	MOVE P5,SS.SBA		;GET SB
   IFN KLPDBG,<
	SKIPN P5
	BUG. (HLT,KLPULN,PHYKLP,SOFT,<PHYKLP - No system block when unlinking packet>,,<

Cause:	ULNKxx was called with a system block address of 0.
>)
   >
	MOVE Q3,.SBAPB(P5)	;GET PCB
	ADDI T1,(Q3)		;POINT AT INTERLOCK WORD OF CORRECT QUEUE
	CALL REMQUE		;REMOVE THE 1ST MESSAGE
	 JRST	ULNKM1		;EMPTY!
	 JFCL
	MOVE T1,Q2		;RETURN PACKET ADDRESS
	RETSKP

ULNKM1:	CAIE T1,.PBDFI(Q3)	;DG QUEUE EMPTY?
	IFSKP.
	   SKIPE CIBUGX
	   BUG. (INF,KLPNDG,PHYKLP,SOFT,<PHYKLP - No datagram buffer>,,<

Cause:	TOPS-20 tried to remove a buffer from the datagram free queue but the
	queue was empty.
>,,<DB%NND>)			;[7.1210] 
	   MOVEI T1,1		;GET A DATAGRAM BUFFER
	   CALL SC.ALD		;(T1/T1)  FROM SCA'S POOL
	    RETBAD (KLPX11)	;FAILED
	   RETSKP		;SUCCESS
	ENDIF.
;...
;...

	SKIPE CIBUGX
	BUG. (INF,KLPNMG,PHYKLP,SOFT,<PHYKLP - No message buffer>,,<

Cause:	TOPS-20 tried to remove a buffer from the message free queue but the
	queue was empty.
>,,<DB%NND>)			;[7.1210] 
	MOVEI T1,1		;GET A MESSAGE BUFFER
	CALL SC.ABF		;(T1/T1)  FROM SCA'S POOL
	 RETBAD (KLPX11)	;FAILED
	RETSKP			;SUCCESS

	ENDBS.
;LINK A BUFFER (OR CHAIN OF BUFFERS) ONTO THE DATAGRAM OR MESSAGE FREE QUEUE
;RETURNS:	+1 ALWAYS

LNKDFQ::BLSUB. (<SS.SBA,SS.PKA>)
	MOVX T1,.PBDFI		;ONTO DATAGRAM FREE QUEUE
	JRST LINKPK		;MOVE ON

LNKMFQ::BLSUB. (<SS.SBA,SS.PKA>)
	MOVX T1,.PBMFI		;ONTO MESSAGE FREE QUEUE

LINKPK:	SAVEAC <Q2,Q3,P5>
	MOVE Q2,SS.PKA		;GET PACKET ADDR
	MOVE P5,SS.SBA		;GET SB ADDRESS
   IFN KLPDBG,<
	SKIPN P5
	BUG. (HLT,KLPLNK,PHYKLP,SOFT,<PHYKLP - No system block when linking packet>,,<

Cause:	LNKxFQ was called with a system block address of 0.
>)
   >
	MOVE Q3,.SBAPB(P5)	;GET PCB ADDR
	ADDI T1,(Q3)		;POINT AT QUEUE ADDRESS
LNKMF1:	PUSH P,(Q2)		;SAVE ADDR OF NEXT PACKET BUFFER
	CALL PUTQUE		;INSERT THIS PACKET ON QUEUE
	 JFCL
	POP P,Q2		;GET ADDR OF NEXT BUFFER
	JUMPN Q2,LNKMF1		;DO IT IF IT EXISTS
	RET			;DONE

	ENDBS.
;ROUTINE TO GET A DATAGRAM BUFFER
;CALL	P1/CDB
;RETURNS +1	NONE AVAILABLE
;	 +2	Q2/BUFFER ADDR

PPDGDB::MOVE	T1,CDBPCB(P1)	;PCB LOC
	MOVEI	T1,.PBDFI(T1)	;WHICH QUEUE
	JRST	KLPGD1		;CARRY ON


;ROUTINE TO GET A BUFFER FROM THE DATAGRAM FREE QUEUE
;CALL:	Q3/PCB
;RETURNS +1 IF NONE AVAILABLE
;RETURNS +2 IF OK   Q2/ADDR OF BUFFER

KLPGDB:	MOVEI	T1,.PBDFI(Q3)	;WHICH QUEUE
KLPGD1:	CALL	REMQUE		;GET BUFFER
	  RET			;EMPTY
	  JFCL
	RETSKP			;RETURN HAPPY


;PUT A PACKET ON THE DATAGRAM OR MESSAGE FREE QUEUE
;ACCEPTS:	Q2/ PACKET ADDRESS
;		Q3/ PCB ADDRESS
;RETURNS:	+1

RETMSG:	XMOVEI T1,.PBMFI(Q3)	;GET Q INTERLOCK
	SKIPA
RETDG:	XMOVEI T1,.PBDFI(Q3)	;GET Q INTERLOCK
	CALL PUTQUE		;(T1,Q2) RETURN THE PACKET
	 JFCL			;DON'T CARE ABOUT EMPTINESS
	RET
;SUBROUTINE TO REMOVE FIRST PACKET FROM A QUEUE

;ACCEPTS:
;	T1=ADDRESS OF INTERLOCK WORD OF QUEUE

;	CALL REMQUE

;RETURNS +1: QUEUE IS EMPTY BEFORE REMOVAL
;	 +2: QUEUE IS NON-EMPTY AFTER REMOVAL
;		Q2/ ADDRESS OF PACKET (WHICH IS NOW UNQUEUED)
;	 +3: QUEUE IS EMPTY AFTER REMOVAL
;		Q2/ ADDRESS OF PACKET (WHICH IS NOW UNQUEUED)

REMQUE:
   IFN KLPDBG,<
	CALL SANCHK		;(T1/) SEE IF THE QUEUE IS INTACT
   >
	CIOFF
	CALL GTINTL
REMQU2:	CALL	CHKMPT		;IS QUEUE ALREADY EMPTY?
	  JRST	QRET		;EMPTY
	AOS	(P)		;NOT EMPTY. SET FOR SKIP/SKIP2 RETURN
	MOVE	T2,.PBFLI(T1)	;GET 1ST PACKET FROM QUEUE
	CALL	CHKPAK		;GET ITS VIRTUAL ADDRESS
	  JRST	REMQU4		;VIRTUAL ADDR DOESN'T MATCH PHYSICAL!
	MOVE	Q2,T2		;VIRTUAL ADDR OF PACKET IN Q2
   IFN KLPDBG,<
	SETO T2,		;THIS IS A REMOVE
	CALL XXXKLP
	MOVE T2,(P)		;TOP OF STACK
	CALL XXXKLP
	MOVE T2,-1(P)		;NEXT TO TOP OF STACK
	CALL XXXKLP
	MOVE T2,T1		;GET QUEUE INTERLOCK WORD
	CALL XXXKLP
	MOVE T2,Q2		;GET PACKET ADDRESS
	CALL XXXKLP
   >
	DMOVE	T2,.PKFLI(Q2)	;GET FLINK, BLINK OF THIS PACKET
	CAME	T2,T3		;FLINK=BLINK?
	JRST	REMQU3		;NO, QUEUE IS STILL NON-EMPTY

;This was last item on the queue. Mark it as empty

	DMOVEM	T2,.PBFLI(T1)	;YES. QUEUE IS EMPTY. POINT HEADER AT ITSELF
	JRST	QRETS		;AND SKIP - RETURN

;This was not the last item on the queue. Make PCB point to the next packet

REMQU3:	MOVEM	T2,.PBFLI(T1)	;POINT QUEUE HEADER AT NEXT PACKET
	ADDI	T2,.PKBLI	;POINT AT BLINK OF NEXT PACKET
	PMOVEM T3,T2		;[7.1002] Point next packet back at header
	JRST	QRET		;NON-SKIP RETURN
;...
;...

;HERE IF VIRTUAL ADDR IN PACKET ISN'T WHAT IT SHOULD BE

REMQU4:	MOVE T4,.PBFLI(T1)	;GET THE FLINK WORD
	BUG. (CHK,KLPVIR,PHYKLP,HARD,<PHYKLP - Virtual address in packet is wrong>,<<T1,QUEUE>,<T2,VMA>,<T3,PMA>,<T4,FLINK>>,<

Cause:	The virtual address of a packet is incorrect. This indicates some sort
	of inconsistency in one of the queues.

Data:	QUEUE - Address of the queue's interlock word
	VMA - Contents of the software word in the packet
	PMA - Physical address of the word pointed to
	FLINK - FLINK word from PCB
>)

IFN KLPDBG,<CALL	KLPBUG>		;LET'S FIND OUT WHY
	MAP	T2,.PBFLI(T1)	;GET PHYSICAL ADDR OF QUEUE HEADER
	TLZ	T2,777760
	MOVEM	T2,.PBFLI(T1)	;RESET QUEUE TO EMPTY
	MOVEM	T2,.PBBLI(T1)
	SOS	(P)		;GIVE EMPTY-QUEUE RETURN
	JRST QRET


   IFN KLPDBG,<
	KLPMAX==^D500		;SIZE OF BUFFER

XXXKLP:	AOS T3,KLPPTR		;ADVANCE COUNTER
	CAIL T3,KLPMAX		;TOO HIGH?
	SETZB T3,KLPPTR		;YES, RESET IT
	MOVEM T2,KLPBUF(T3)	;STORE DATA ITEM
	RET			;DONE

RS(KLPPTR,1)			;INDEX INTO BUFFER
RS(KLPBUF,KLPMAX)		;BUFFER
   >
;SUBROUTINE TO INSERT A PACKET ONTO A QUEUE

;ACCEPTS:
;	T1/ ADDR OF INTERLOCK WORD OF QUEUE 
;	Q2/ ADDRESS OF PACKET
;	CALL PUTQUE
;RETURNS +1:QUEUE WAS EMPTY
;	 +2 QUEUE WAS NON-EMPTY BEFORE INSERTION

PUTQUE:
   IFN KLPDBG,<
	CALL SANCHK		;(T1/)SEE IF THIS QUEUE IS INTACT
	CAIGE Q2,20		;AC'S AREN'T A GOOD PLACE FOR BUFFERS
	BUG. (HLT,KLPACS,PHYKLP,SOFT,<PHYKLP - Address of packet in ACs>,,<

Cause:	PUTQUE was called with a packet address in the ACs.
>)
	CAIL Q2,PCB		;NEITHER IS THE PCB
	CAILE Q2,PCB+L.PCB-1
	SKIPA
	BUG. (HLT,KLPAPC,PHYKLP,SOFT,<PHYKLP - Address of packet in PCB>,,<

Cause:	PUTQUE was called with a packet address in the PCB.
>)
   >
	CIOFF
	CALL GTINTL		;GET THE INTERLOCK
   IFN KLPDBG ,<
	SETZ T2,		;THIS IS A PUT
	CALL XXXKLP
	MOVE T2,(P)		;TOP OF STACK
	CALL XXXKLP
	MOVE T2,-1(P)		;NEXT TO TOP OF STACK
	CALL XXXKLP
	MOVE T2,T1		;GET QUEUE INTERLOCK
	CALL XXXKLP
	MOVE T2,Q2		;GET PACKET ADDRESS
	CALL XXXKLP
   >
	STOR Q2,PKVRT,(Q2)	;SAVE VIRTUAL ADDR IN PACKET
	MAP	T3,.PKFLI(Q2)	;PHYSICAL ADDR OF PACKET
	TLZ	T3,777760
	MAP	T2,.PBFLI(T1)	;PHYSICAL ADDR OF QUEUE HEADER
	TLZ	T2,777760
	CAME	T2,.PBFLI(T1)	;FLINK POINT AT ITSELF (EMPTY QUEUE)?
	JRST	PUTQU3		;NO

;Queue was empty when we started

	MOVEM	T2,.PKFLI(Q2)	;YES. POINT PACKET BACK AT QUEUE HEADER
	MOVEM	T2,.PKBLI(Q2)
	MOVEM	T3,.PBBLI(T1)	;POINT PCB FLINK AND BLINK AT PACKET
	MOVEM	T3,.PBFLI(T1)
	JRST QRET		;RETURN +1
;...
;...

;Queue wasn't empty when we started.

PUTQU3:	MOVEM	T2,.PKFLI(Q2)	;POINT FLINK OF PACKET AT PCB
	MOVE	T2,.PBBLI(T1)	;GET FORMER END OF QUEUE
	MOVEM	T3,.PBBLI(T1)	;POINT QUEUE TAIL AT THIS PACKET
	MOVEM	T2,.PKBLI(Q2)	;POINT BLINK OF THIS PACKET AT FORMER END
	PMOVEM T3,T2		;[7.1002] Point BLINK of former end at this packet
	JRST QRETS		;RETURN +2
;TRCKLP - Routine to trace a queue pointed to by the PCB

;ACCEPTS:
;	T1/ address of interlock word
;	T2/ address of where to store the VMAs

;	CALL TRCKLP

;RETURNS +1: ALWAYS

;This routine traces a queue, and places the virtual addresses of the
;packets into the location pointed to by T2, and the following locations.
;It stores the count in the first location.

TRCKLP:
	SAVET
	SAVEQ
	MOVEM T2,Q1			;SAVE THE STARTING ADDRESS
	MOVEM T2,Q2
	AOS Q1				;SAVE THE FIRST WORD FOR THE COUNT
	MAP Q3,.PBFLI(T1)		;GET PHYSICAL ADDRESS OF FLINK
	TLZ Q3,777760			;MASK OFF PAGE FAIL BITS
	CIOFF
	CALL GTINTL			;GET THE INTERLOCK
	CALL CHKMPT			;IS QUEUE EMPTY?
	 JRST TRCKL4			;YES. DONE THEN
	CALL KLPFOO
	JRST [	MOVEM T3,(Q1)		;THIS WAS THE LAST. RECORD IT
		JRST TRCKL4]		;AND QUIT
	MOVEM T3,(Q1)			;FOUND ENTRY. RECORD IT
	AOS Q1				;STEP TO NEXT LOCATION
TRCKL5:	CALL KLPFO2			;GET THE NEXT ENTRY
	JRST [	MOVEM T3,(Q1)		;SAVE ITS VMA
		JRST TRCKL4]
	MOVEM T3,(Q1)
	AOS Q1
	JRST TRCKL5

;Finished. Save the count

TRCKL4:	SUB Q1,Q2			;COMPUTE LENGTH
	SOS Q1
	MOVEM Q1,(Q2)			;SAVE IT
	JRST QRET
;FNDKLP - Routine to search a queue for a particular packet

;ACCEPTS:
;	T1/ Address of interlock word
;	T2/ Virtual address of packet

;	CALL FNDKLP

;RETURNS +1: DIDN'T FIND IT
;	 +2: FOUND IT

FNDKLP:
	SAVET
	SAVEQ
	MOVEM T2,Q1			;SAVE THE ADDRESS WE WANT TO MATCH
	MAP Q3,.PBFLI(T1)		;GET PHYSICAL ADDRESS OF FLINK
	TLZ Q3,777760			;MASK OFF PAGE FAIL BITS
	CIOFF
	CALL GTINTL			;GET THE INTERLOCK
	CALL CHKMPT			;IS QUEUE EMPTY?
	 JRST QRET			;YES. DONE THEN
	CALL KLPFOO
	JRST [	CAMN T3,Q1		;THE ONE WE WANTED?
		JRST QRETS		;YES
		JRST QRET]		;NO. QUIT
	CAMN T3,Q1			;NOT THE LAST. THE ONE WE WANTED?
	JRST QRETS			;YES.
FNDKL5:	CALL KLPFO2			;GET THE NEXT ENTRY
	JRST [	CAMN T3,Q1		;THE ONE WE WANTED?
		JRST QRETS
		JRST QRET]		;NO. QUIT
	CAMN T3,Q1			;THE ONE WE WANTED?
	JRST QRETS			;YES.
	JRST FNDKL5
;SANCHK - Perform sanity check on a queue

;ACCEPTS:
;	T1/ ADDRESS OF INTERLOCK WORD

;AT THE MOMENT, RETURNS +1 ALWAYS. INNER ROUTINE BUGHLTS ON FAILURE

   IFN KLPDBG,<
SANCHK:

;Please, leave the RET in place for production systems.  This code tends
;to produce timing problems in the CI port.  Feel free to NOP the RET for
;stand alone work, realizing the possible consequences.

;[7.1288]
;However, we have not seen any bad side effects with CI ucode 1.1(733)
;therefore, we have removed the RET. This code is only active when 
;KLPDBG=1. It may be necessary to have this code with KLPDBG=1 (for
;instance, we may catch KLPNOM BUGHLTs with this).

;	RET
	SAVET
	SAVEQ
	MAP Q3,.PBFLI(T1)		;GET PHYSICAL ADDRESS OF FLINK
	TLZ Q3,777760			;MASK OFF PAGE FAIL BITS
	CIOFF
	CALL GTINTL			;GET THE INTERLOCK
	CALL CHKMPT			;IS QUEUE EMPTY?
	 JRST QRET
	CALL KLPFOO
	 JRST QRET			;THIS WAS THE LAST. QUIT
SANCH5:	CALL KLPFO2
	 JRST QRET
	JRST SANCH5
	JRST QRET
   >					;END IFN KLPDBG
;ACCEPTS:
;	T1/ ADDRESS OF INTERLOCK WORD
;	Q3/ PHYSICAL ADDRESS OF FLINK WORD

;RETURNS +1: THIS WAS THE LAST ENTRY
;	 +2: THERE ARE MORE ENTRIES
;		T2/ PHYSICAL ADDRESS
;		T3/ VIRTUAL ADDRESS

;SUBSEQUENT CALLS TO KLPFO2 MUST HAVE T2 SET UP FROM PREVIOUS CALL

KLPFOO:	CALL CHKMPT			;IS QUEUE EMPTY?
	 BUG. (HLT,KLPMTY,PHYKLP,SOFT,<PHYKLP - Queue is empty>,,<

Cause:	We want to trace the pointers on a queue but the queue is empty.
>)
	MOVE T2,.PBFLI(T1)		;NO. POINT TO FIRST PACKET

;Here to check the next packet. PMA of packet in T2.

KLPFO2:	CALL CHKPAK			;GET VIRTUAL ADDRESS OF PACKET
	 BUG. (HLT,KLPBPK,PHYKLP,SOFT,<PHYKLP - Bad packet>,,<

Cause:	The virtual address of the packet is invalid.
>)
	MOVE T3,T2			;SAVE THE VMA
	MOVE T2,.PKFLI(T2)		;GET FLINK OF THIS PACKET
	CAMN T2,Q3			;POINTS BACK TO THE QUEUE?
	RET				;YES. THIS IS THE LAST
	RETSKP
;GTINTL - ROUTINE TO GET THE INTERLOCK

;	T1/ ADDRESS OF INTERLOCK WORD

;	CALL GTINTL

;RETURNS +1: ALWAYS

;CALLER MUST BE CIOFF

GTINTL:
   IFN KLPDBG,<
	MOVE T3,KLPOWN		;GET OWNER OF INTERLOCK
	CAIE T3,-1		;OK?
	BUG. (HLT,KLPHVL,PHYKLP,SOFT,<PHYKLP - Already have queue interlock>,,<

Cause:	We are attempting to get a queue interlock which we already have.
>)
	HRRZ T3,T1		;FORGET ABOUT SECTION 1
	CAIE T3,PCB+.PBQ3I	;MUST BE AN INTERLOCK WORD IN PCB
	CAIN T3,PCB+.PBQ2I
	JRST GTINT2
	CAIE T3,PCB+.PBQ1I
	CAIN T3,PCB+.PBQ0I
	JRST GTINT2
	CAIE T3,PCB+.PBRQI
	CAIN T3,PCB+.PBMFI
	JRST GTINT2
	CAIN T3,PCB+.PBDFI
	JRST GTINT2
	BUG. (HLT,KLPIIW,PHYKLP,SOFT,<PHYKLP - Invalid interlock word>,,<

Cause:	The interlock words are predefined locations in the PCB.  The address
	being checked was not one of those locations.
>)
   >
GTINT2:	AOSN	T2,.PBIWD(T1)	;WAIT FOR INTERLOCK
	JRST [	CONSO PI,1B25	;TAKING A KLIPA INTERRUPT NOW?
		SKIPA T2,INSKED	;NO. PROCESS OR SCHEDULER CONTEXT?
		SETOM T2	;YES. RECORD THAT
		MOVEM T2,KLPOWN	;RECORD THE OWNER OF THE INTERLOCK
		MOVEM T1,KLPQ	;SAVE WHICH INTERLOCK WORD WE GOT
		RET]
	SKIPGE T2		;SHOULDN'T BE NEGATIVE
	JRST GTINT3
	CAIGE	T2,TIMOUT	;WAITED LONG ENOUGH?
	JRST	GTINTL		;NO, TRY AGAIN
	CONSO PI,1B25		;TAKING A KLIPA INTERRUPT?
	SKIPA T4,INSKED		;NO. GET SCHEDULER VS. PROCESS CONTEXT
	SETOM T4		;YES. RECORD INTERRUPT LEVEL
	MOVE T3,KLPOWN		;GET CURRENT OWNER
	CAIE T2,TIMOUT		;YES. IS THE VALUE WHAT WE EXPECT?
	JRST GTINT3		;NO. COMPLAIN
	AOS BRKCNT
;...
;...
	BUG. (CHK,KLPTIM,PHYKLP,HARD,<PHYKLP - Timed out waiting for queue interlock>,<<T1,QUEUE>,<T2,COUNT>,<T3,OWNER>,<T4,CONTXT>>,<

Cause:	The KLIPA driver timed out trying to get the interlock for a queue.
	The KLIPA microcode should never have the lock this long.

Data:	QUEUE - Address of the queue's interlock word

>)
	RET
	
GTINT3:	BUG. (HLT,KLPHOG,PHYKLP,HARD,<PHYKLP - Interlock value on queue is too large>,<<T1,QUEUE>,<T2,COUNT>,<T3,OWNER>,<T4,CONTXT>>,<

Cause:	The KLIPA driver timed out the interlock, but the value isn't what 
	is expected.
>)
;Common exit from routines that manipulate queues. Clears the
;interlock, allows interrupts.

QRETS:	AOS	(P)		;SET FOR SKIP RETURN
QRET:	MOVEI T2,-1		;INDICATE NO SOFTWARE OWNS INTERLOCK
	MOVEM T2,KLPOWN
	SETOM	.PBIWD(T1)	;RELEASE INTERLOCK
	CION
	RET			;RETURN TO CALLER


;ROUTINE TO CHECK IF A QUEUE IS EMPTY
;CALL WITH T1=ADDRESS OF INTERLOCK WORD OF QUEUE
;RETURNS WITH T1 UNCHANGED
;NON-SKIP RETURN IF QUEUE IS EMPTY
;SKIP RETURN IF QUEUE IS NON-EMPTY

CHKMPT:	MAP	T2,.PBFLI(T1)	;GET PHYSICAL ADDRESS OF QUEUE HEADER
	TLZ	T2,777760
	CAMN	T2,.PBFLI(T1)	;DOES QUEUE POINT AT ITSELF (EMPTY) ?
	RET			;YES, NON-SKIP
	RETSKP			;NO, SKIP
;ROUTINE TO RETURN THE VIRTUAL ADDRESS OF A PACKET

;ACCEPTS:
;	T2/PACKET PHYSICAL ADDRESS

;	CALL CHKPAK

;RETURNS +1: PACKET IS BAD - THE VIRTUAL ADDRESS IN THE PACKET DOESN'T MATCH 
;		THE PHYSICAL ADDRESS
;	 +2: SUCCESS,
;		T2/ VIRTUAL ADDRESS OF PACKET

;PRESERVES T1

CHKPAK:	SAVEAC	<Q1>
   IFN KLPDBG,<
	CAIGE T2,20		;SHOULDN'T BE IN AN AC
	BUG. (HLT,KLPACP,PHYKLP,SOFT,<PHYKLP - Physical address of packet in ACs>,,<

Cause:	The physical address of this packet is less than 20.
>)
   >
	MOVE	Q1,T2		;PRESERVE PHYICAL ADDR OF PACKET
	ADDI	T2,.PKVRT	;POINT AT PACKETS VIRTUAL ADDRESS
	PMOVE T2,T2		;[7.1002] Get C(addr) which should be virtual addr
	LOAD T2,PKVRT,T2	;GET THE VIRTUAL ADDRESS
   IFN KLPDBG,<
	CAIGE T2,20
	BUG. (HLT,KLPACV,PHYKLP,SOFT,<PHYKLP - Virtual address of packet in ACs>,,<

Cause:	The virtual address of this packet is less than 20.
>)
   >
	MAP	T3,(T2)		;COMPUTE PHYSICAL ADDR OF THAT VIRTUAL ADDR
	TLZ	T3,777760
	CAME	T3,Q1		;PHYSICAL ADDRESSES MATCH?
	BUG. (HLT,KLPNOM,PHYKLP,SOFT,<PHYKLP - Physical address doesn't match>,,<

Cause:	The physical address of a packet is stored in the packet.  The physical
	address of this packet doesn't match what is in the packet.
>)
   IFN KLPDBG,<
	MOVE T4,.PKFLI(T2)	;GET PACKET'S FLINK
	LOAD T4,PHCPNO,T4	;GET PHYSICAL PAGE NUMBER
	CAMLE T4,NHIPG		;DOES IT EXIST?
	BUG. (HLT,KLPPMA,PHYKLP,SOFT,<PHYKLP - Bad physical address for packet>,,<

Cause:	Physical address for packet is impossible.
>)
   >
	RETSKP			;ALL IS WELL
Repeat 0,< 	;[7.1002] Remove obsolete routines - replaced by instructions
;SUBROUTINE TO GET THE CONTENTS OF A GIVEN PHYSICAL ADDRESS
;CALL:	T2/DESIRED PHYSICA ADDRESS
;	RETURNS +1, WITH T2=CONTENTS
;PRESERVES T1

PMOVE:	PUSH	P,T1		;SAVE T1
	LOAD	T1,PGWD,T2	;WORD NUMBER
	LOAD	T2,PHCPNO,T2	;PHYSICAL PAGE NUMBER
	CALL	MOVRCA		;GET THE CONTENTS
	MOVE	T2,T1		;RETURNS THE ANSWER IN T2
	JRST	PMOVER		;RESTORE T1 AND RETURN


;ROUTINE TO STORE INTO A GIVEN PHYSICAL ADDRESS
;CALL:	T3/CONTENTS TO BE STORED
;	T2/ PHYSICAL ADDRESS TO STORE IT
;RETURNS +1 ALWAYS
;PRESERVES T1

PMOVEM:	PUSH	P,T1		;PRESERVE T1
	LOAD	T1,PGWD,T2	;WORD NUMBER
	LOAD	T2,PHCPNO,T2	;PAGE NUMBER
	CALL	STORCA		;STORE T3 THERE
PMOVER:	POP	P,T1		;RESTORE T1
	RET			;AND RETURN TO CALLER
>	;[7.1002] End obsolete routines
	SUBTTL Named-Buffer Routines

;ROUTINE TO GET A FREE BHD
;CALL P1=0 IF USED THE RESERVED SLOT, P1 NON-0 IF DON'T
;NON-SKIP RETURN IF NONE AVAILABLE
;SKIP-RETURN NORMALLY, WITH T1=TABLE INDEX, T2=BHD ADDRESS

GETBHD::SKIPN	BSDLOC		;IF NO BSDS ARE FREE
	RETBAD (KLPX2)		;WE MIGHT AS WELL FORGET IT
	MOVE	T1,BHDCPT	;WHERE WE LAST GOT A BHD
	ADDI	T1,L.BHD-1
	AOBJP	T1,GETBH3	;STEP TO NEXT TABLE SLOT
GETBH1:	SKIPE	.BHKEY(T1)	;IS THIS ONE AVAILABLE?
	JRST	GETBH2		;NO, TRY NEXT
	MOVEM	T1,BHDCPT	;SAVE WHERE WE LEFT OFF
	HRRZ	T2,T1		;GET ADDRESS OF BHD
	SUB	T1,BHDIPT	;COMPUTE INDEX INTO TABLE
	RETSKP			;AND GOOD RETURN
GETBH2:	CAMN	T1,BHDCPT	;BACK TO WHERE WE STARTED?
	RETBAD (KLPX1)		;YES, NONE AVAILABLE
	ADDI	T1,L.BHD-1
	AOBJN	T1,GETBH1	;NO, TRY NEXT SLOT
GETBH3:	MOVE	T1,BHDIPT	;END OF TABLE, START AT BEGINNING
	JUMPE	P1,GETBH1	;START AT 1ST BHD IF WE CAN USE THE RES'VD ONE
	ADDI	T1,L.BHD-1	;CAN'T USE IT. START AT NEXT BHD
	AOBJN	T1,GETBH1


;ROUTINE TO RETURN THE BHD, BSDS ASSOCIATED WITH A PACKET
;CALL:	Q2=ADDRESS OF PACKET BUFFER
;	T1=BUFFER NAME (IN CORRECT ORDER)

RTNBHX::CIOFF			;TURN OFF INTERRUPTS
	CALL	GIVBHD		;RETURN THE BHD/BDT
	SKIPA	T3,T2		;POINT T3 AT 1ST BSD
RTNBH1:	CALL	GIVBSD		;RETURN THE BSD
	SKIPN	T1,T3		;IS THERE A BSD?
	JRST RTNCIO		;NO. WE'RE DONE
	MOVE	T3,.BSNXT(T1)	;YES. PRESERVE ITS LINK
	JRST	RTNBH1		;AND GIVE IT BACK

RTNCIO:	CION			;TURN INTERRUPTS BACK ON
	RET			;AND RETURN
;ROUTINE TO GET A BSD
;NON-SKIP IF NONE AVAILABLE, SKIP IF HAVE IT,
;T1=BSD ADDRESS
;PRESERVES T3, T4

GETBSD::CIOFF
	SKIPN	T1,BSDLOC	;ANY BSDS AT ALL?
	RETBAD (KLPX2,<CION>)	;NO. NON-SKIP
	MOVE	T2,.BSNXT(T1)	;YES. GET LINK TO NEXT

;*****************************************************************************
;WE TOLD THE DIAGNOSTICS FOLKS THAT WE'D RESERVE 1 BHD/BSD FOR THEIR USE
;WE NEED A WAY TO DETERMINE THAT THIS IS A DIAGNOSTIC, AND LET THEM HAVE THE LAST ONE
;*****************************************************************************
	JUMPE	T2,[JFCL	;DIAGNOSTIC?
		    RETBAD (KLPX2,<CION>) ;NO. DON'T USE THE LAST BSD
		    JRST .+1]	;YES. USE THE RESERVED BSD
	MOVEM	T2,BSDLOC	;STORE IT AS 1ST FREE BSD
	CION			;RE-ENABLE INTERRUPTS
	RETSKP			;GOOD-RETURN


;ROUTINE TO RETURN A BSD
;ENTER T1=BSD ADDR
;PRESERVES T3

GIVBSD::MOVE	T2,BSDLOC	;GET CURRENT 1ST BSD
	MOVEM	T1,BSDLOC	;SAVE AS 1ST AVAILABLE BSD
	MOVEM	T2,.BSNXT(T1)	;LINK FORMER 1ST FREE TO THIS
	RET			;AND WE'RE DONE


;ROUTINE TO RETURN A BHD
;CALL	T1=BUFFER NAME
;ALWAYS RETURNS TO CALL+1 WITH T1=ADDRESS OF BHD, T2=C(.BHBSA), T4 = C(.BHKEY)
;PRESERVES T3

GIVBHD::LDB	T1,[POINT BHSIDX,T1,BHPIDX] ;GET INDEX INTO BUFFER DESCRIPTOR TABLE
	ADD	T1,BHDIPT	;POINT AT RIGHT BDT ENTRY
	MOVE	T2,.BHBSA(T1)	;GET POINTER TO BSD BEFORE WE RETURN THE BHD
	MOVE T4,.BHKEY(T1)	;RETURN THE KEY INCASE OF TRANSFER ERROR
	SETZM	.BHKEY(T1)	;MAKE KEY INVALID IN CASE HSC SCREWS UP
	RET
;MAPBUF - MAP A BUFFER
;	.BLCAL (MAPBUF,(SS.BDA)
;		 SS.BDA - ADDRESS OF THE BUFFER DESCRIPTOR
;RETURNS:	+1  FAILED.  T1/ ERROR CODE
;		+2  SUCCESS

;MAPBUF WILL CREATE THE NIBBLE COUNTS FOR THE BHD AND BSD BASED UPON
;THE LENGTH SPECIFIED IN THE DESCRIPTOR AND WILL ASSUME THAT THE LENGTH
;FOR CORE MODE IS IN WORDS AND THE LENGTH FOR IND AND HIGH DENSITY IS
;IN 8 BIT BYTES.
;
;MAPBUF WILL HANDLE MULTIPLE DESCRIPTOR BLOCKS BUT WILL BUILD ONE
;BHD AND MULTIPLE BSDS. MAPBUF WILL ONLY LOOK AT THE FLAGS FROM THE FIRST
;DESCRIPTOR BLOCK AND SET ALL BSDS ACCORDING TO THESE FLAG SETTINGS.

MAPBUF::BLSUB. (<SS.BDA>)
	SAVEPQ			;WE NEED LOTS OF ACS
	MOVE P3,SS.BDA		;GET FIRST BUFFER DESCRIPTOR
	SETZ P1,		;INDICATE WE WANT THE RES'VD BHD
	CIOFF			;DISABLE CI INTERRUPTS
	CALL GETBHD		;(/T1,T2) GET A BHD
	  RETBAD (,<CION> )	;NONE AVAILABLE. LOSE
	MOVE P1,T2		;P1=BHD ADDRESS
	SETZM .BHBSA(P1)	;IN CASE NO BSDS AVAILABLE
	HRRZ P2,T1		;BHD INDEX
	LSH P2,^D35-BHPIDX	;POSITION IT WHERE THE PORT WANTS IT
	MOVEI T1,1B31
	ADDB T1,CRFNUM		;SET KEY
	LSH T1,^D35-BHPKEY-4
	IORM T1,P2		;P2=BUFFER NAME
	MOVE T2,.MDFLG(P3)	;GET THE FLAGS AND MODE
	TXNE T2,SQ%WRT		;ALLOW WRITE OF HOST MEMORY?
	TXO T1,BH.WRT		;YES. SET THE WRITE BIT IN THE BHD
	TXNE T2,SQ%CVD		;ALLOW CLEARING OF THE VALID BIT?
	TXO T1,BH.PRE		;NO. SET THE DO NOT CLEAR VALID BIT IN THE BHD
	TXO T1,BH.VAL 		;SET THE VALID BIT
	MOVEM T1,.BHKEY(P1)	;SAVE KEY/VALID BITS IN BHD
	CION			;ENABLE INTERRUPTS
	SETZ P4,		;P4 ACCUMULATES NIBBLE COUNT
	MOVEI T4,(P1)		;SET BHD ADDRESS IN T4
	SETZM .BHBSA(T4)	;ZERO THE POINTER IN CASE OF GETBSD FAILURE.
	CALL GETBSD		;(/T1) GET THE FIRST BSD
	  JRST MAPBU4		;LOSSAGE
	MOVEM T1,.BHBSA(T4)	;POINT BHD AT FIRST BSD
	MOVE T4,T1		;SET T4 WITH ADDRESS OF BSD
	MOVE Q1,P3		;Q1 USED TO PROCESS THE DESCRIPTOR BLOCKS
	MOVE P5,(P3)		;POINTER TO NEXT DESCRIPTOR BLOCK
	ADDI Q1,.MDSSD		;SET Q1 TO START OF LENGTH PAIRS
	JRST MAPBU5
				;HERE TO PROCESS DESCRIPTOR PAIRS 2-N OF THE
				;FIRST DESCRIPTOR BLOCK OR ALL DESCRIPTOR
				;PAIRS OF DESCRIPTOR BLOCKS 2-X.
;...
;...
MAPBU2:	SKIPN .MDLEN(Q1)	;ANOTHER BSD NEEDED?
	JRST MAPBU3		;NO. FINISH UP
	CALL GETBSD		;(/T1) GET THE NEXT BSD
	  JRST	MAPBU4		;LOSSAGE
	MOVEM T1,.BSNXT(T4)	;POINT PREVIOUS BSD AT THIS ONE
	MOVE T4,T1
MAPBU5:	MOVE T2,.MDLEN(Q1)	;GET LENGTH OF THIS SEGMENT
	LOAD T3,MD%DMD,.MDFLG(P3)	;GET THE MODE
	CAIE T3,MD%DIC		;IND COMPATABLE?
	IFSKP.
	  LSH T2,1		;YES. LENGTH IN BYTES,CHANGE TO NIBBLES
	  MOVEM T2,.BSLEN(T1)	;STORE IN BSD
	  ADD P4,T2		;ACCUMULATE TOTAL COUNT
	  MOVE T2,.MDADR(Q1)	;GET BASE ADDRESS WORD
	  TXO T2,BS.ICM		;SET IND COMPATABLE MODE IN BSD
	ELSE.
	  CAIE T3,MD%DHD	;HIGH DENSITY?
	  IFSKP.
	    LSH T2,1		;YES. LENGTH IN BYTES,CHANGE TO NIBBLES
	    MOVEM T2,.BSLEN(T1)	;SAVE LENGTH IN BSD
	    ADD P4,T2		;ACCUMULATE TOTAL COUNT
	    MOVE T2,.MDADR(Q1)	;GET BASE ADDRESS
	    TXO T2,BS.HDM	;SET HIGH DENSITY BIT IN BSD.
	  ELSE.
				;HERE FOR CORE DUMP MODE.
	    IMULI T2,CDNPW	;CALCULATE NIBBLES PER WORD FOR CORE DUMP.
	    MOVEM T2,.BSLEN(T1)	;SAVE LENTH IN BSD.
	    ADD P4,T2		;ACCUMULATE TOTAL COUNT.
	    MOVE T2,.MDADR(Q1)	;GET BASE ADDRESS.
	    TXO T2,BS.CDM	;SET CORE DUMP MODE BIT IN BSD.
	  ENDIF.
	ENDIF.
	MOVEM T2,.BSADR(T1)	;SET MODE AND BASE ADDRESS IN BSD
	SETZM .BSNXT(T1)	;ASSUME WE'RE AT THE END
	ADDI Q1,.MDLSD		;STEP TO NEXT DESCRIPTOR LENGTH PAIR
	JRST MAPBU2		;HANDLE IT
MAPBU3:	SKIPN Q1,P5		;ANOTHER BUFFER OF DESCRIPTORS EXIST?
	IFSKP.
	  MOVE P5,(Q1)		;POINT TO NEXT DESCRIPTOR BLOCK
	  ADDI Q1,.MDSSD	;POINT TO START OF THE DESCRIPTOR PAIRS
	  JRST MAPBU2		;GO SET UP THE BSD
	ENDIF.
	MOVEM P4,.BHLEN(P1)	;NO, DONE. SAVE TOTAL NIBBLE COUNT IN BHD.
	MOVE T1,P2		;BUFFER NAME
	RETSKP			;TELL CALLER WE'RE HAPPY

;HERE IF WE CAN'T GET ENOUGH BSDS
MAPBU4:	MOVE	T1,P2		;BUFFER NAME
	CALL	RTNBHX		;RETURN BHD, BSDS
	RETBAD (KLPX2)		;RETURN UNHAPPY

	ENDBS.
;ROUTINE TO UNMAP A BUFFER
;RETURNS T4 = THE FIRST WORD OF THE BHD IN CASE SOMEONE IS INTERESTED
;RETURNS +1 IF THERE WAS AN ERROR REPORTED IN THE BHD (BH.ERR)
;RETURNS +2 SUCCESS

UMAP::	BLSUB.	(<SS.NAM>)
	MOVE	T1,SS.NAM	;BUFFER NAME
	LDB T1,[POINT BHSIDX,T1,BHPIDX]	;GET THE INDEX.
	ADD T1,BHDIPT		;POINT AT THE RIGHT BHD
	SKIPN .BHKEY(T1)	;IS THIS BHD IN USE?
	RETSKP			;NO, THEN DO NOT TRY TO UNMAP IT.
				;NOTE - THIS MAY WANT TO BE A RETBAD,
				;BUT BECAUSE OF SCSJSY CONSIDERATIONS
				;LEAVE IT A RETSKP.
	MOVE T1,SS.NAM		;GET THE NAME AGAIN
	CALL	RTNBHX		;GIVE BACK RESOURCES
	TXNN T4,BH.ERR		;CHECK FOR ERROR
	RETSKP			;AND GO AWAY HAPPY
	RETBAD (KLPX13)		;BUFFER TRANSFER ERROR

	ENDBS.
	SUBTTL	Byte Swapping Routines

;REVERSE THE WORD AND PRESERVE THE ACS, EXCEPT FOR T1

SRVFUL::SAVET
	CALL	REVFUL		;REVERSE THE WORD
	MOVEM	T1,-4(P)	;WHERE RESTORER WILL GET T1
	RET

;REVERSE THE FULL WORD (ALL 4 BYTES)
;PRESERVES T4

REVFUL::LDB	T2,PBYTE1
	LDB	T3,PBYTE2	;PICK UP THE BYTES
	LDB	CX,PBYTE3
	LSH	T1,^D24
	DPB	CX,PBYTE2	;AND PUT THEM DOWN BACKWARDS
	DPB	T3,PBYTE3
	DPB	T2,PBYTE4
	RET


;Account for PPD byte which port will add. We have to swap the bytes into 
;eleven format and account for the PPD field in the text length...
;
; Usage:
;	Call
;	Q2/	Address of packet to be sent
;
;	Return (+1) Always
;	Q2/	Addr of corrected packet
;

;Clobbers only T1 and T2. Callers depend on this

;NOTE: Op code must be message or datagram!!!

MASAGE::
	MOVE T1,[C%PPDL]	;get # of bytes in PPD field
	ADDM T1,.PKLEN(Q2)	;Account For CI.PPD
	LDB T1,PKYPPM		;Get the most significant byte of the PPD
	LDB T2,PKYPPL		;  and the least significant byte
	DPB T2,PKYPPM		;Now swap the two bytes
	DPB T1,PKYPPL		;   into the correct format
	RET			;All done
;Byte swap the PPD byte of a packet that has come off the wire. We can always
;assume that the PPD byte is in eleven format since HSC send it that way and
;our port swaps it that way on send.
;
; Usage:
;	Call
;	Q2/	Address of packet
;
;	Return (+1)
;	Q2/	Address of packet
;	
RMASAG::LDB T1,PKYOP		;Get the port opcode
	TXZ T1,OP.RMT		;Be sure remote bit is off
	CAIE T1,OP.SMS		;Is this a message
	CAIN T1,OP.SDG		;  or datagram???
 	 SKIPA T1,[-C%PPDL]	;Yes, get neg length of PPD field and go on
	  RET			;Not a msg or datagram, return now
	ADDM T1,.PKLEN(Q2)	;Account for the PPD field length
	LDB T1,PKYPPM		;Get most significant byte of PPD field
	LDB T2,PKYPPL		;  and the least significant byte
	DPB T2,PKYPPM		;Now swap the PPD field
	DPB T1,PKYPPL		;  into 10 format
	RET			;All done
	SUBTTL PHYSIO Interface -- Dispatch Tables

;CHANNEL DISPATCH TABLE FOR THE KLIPA (CI)

KLPDSP::JRST KLPINI		;0 - INITIALIZATION
	CALL DSPBUG		;1 - STACK SECOND CHANNEL COMMAND
	JRST KLPSIO		;2 - START I/O
	CALL DSPBUG		;3 - POSITION REQUEST
	CALL DSPBUG		;4 - RETURN BEST XFER
	JRST KLPINT		;5 - INTERRUPT PROCESSING
	JRST KLPCCW		;6 - MAKE CHANNEL XFER WORD
	JRST KLPHUN		;7 - TRANSFER HUNG
	JRST KLPZAP		;10 - RESET CHANNEL
	JRST KLPCHK		;11 - PERIODIC CHECK
	JRST KLPEXT		;12 - CHECK UNIT EXISTANCE
	JRST KLPCCA		;13 - EXTRACT ADDRESS FROM CCW WORD


;CONTROLLER/UNIT DISPATCH TABLE FOR THE KLIPA (CI)

KLDSP::	CALL DSPBUG		;0 - INITIALIZATION
	CALL DSPBUG		;1 - START I/O
	CALL DSPBUG		;2 - HANDLE INTERRUPT
	CALL DSPBUG		;3 - ERROR RECOVERY
	CALL DSPBUG		;4 - HUNG DEVICE
	CALL DSPBUG		;5 - CONVERT BLK # TO CYLINDER/SURF-SEC
	CALL DSPBUG		;6 - LATENCY COMPUTATION
	CALL DSPBUG		;7 - START POSITIONING
	CALL DSPBUG		;10 - ATTENTION INTERRUPT
	CALL DSPBUG		;11 - SKIP IF POSITIONING REQUIREDD
	CALL DSPBUG		;12 - STACK SECOND TRANSFER COMMAND
	JRST KLEXT		;13- CHECK EXISTANCE OF UNIT
	RET			;14- CHECK FOR HALTED CONTROLLER


DSPBUG:	BUG. (HLT,KLPBDS,PHYKLP,SOFT,<PHYKLP - Bad dispatch from PHYSIO>,,<

Cause:	PHYKLP was called to perform a function of which it is not capable.


>)
	SUBTTL PHYSIO Interface -- KLPINI (Channel Initialization)

;KLIPA INITIALIZATION - HERE FROM PHYINI THROUGH KLPDSP (THE CDSINI OFFSET)
;RETURNS:	+1 ALWAYS - IF CDB IS CREATED, P4/ KLIPA CHANNEL NUMBER +1

KLPINI::CONI KLP,T1		;GET CHANNEL STATUS
	AND T1,[CI.KDT]		;IS IT
	CAME T1,[CI.KDT]	; REALLY A KLIPA?
	RET			;NO, DON'T TOUCH IT
	CONO KLP,CO.CPT		;[7134] YES, STOP IT
	SKIPE NOKLIP		;WANT TO USE IT?
	RET			;NO

;WE HAVE A KLIPA, BUILD THE CDB

	SETOM CIHERE		;[7134] INDICATE WE ARE USING THE CI
	MOVEI T1,CDBLEN		;GET LENGTH OF CDB
	CALL PHYALC		;ALLOCATE SOME STORAGE
	 RET			;NO SPACE FOR CDB (PHYALC WILL BUGCHK)
	SAVEAC <P1,P3>
	MOVEI P1,-CDBINT(T1)	;CDB BASE ADDRESS TO P1
	MOVEI P4,KLPRH2		;GET KLIPA'S CHANNEL
	MOVEM P1,CHNTAB(P4)	;SAVE CDB IN CHANNEL TABLE
	HRRZM P4,CDBADR(P1)	;STORE CHNTAB INDEX
	STOR P4,CDCHN,(P1)	;SAVE CHANNEL FOR ERROR.SYS PACKET
	SETZRO CDPRT,(P1)	;CI PORT FOR ERROR.SYS PACKET
	AOS P4			;SET UP FOR RETURN TO PHYINI
	EXCH P1,P3		;GET CDB IN P3
	MOVEI T1,.BTCDB		;MARK AS CDB
	DPB T1,USYBKT		; ...
	EXCH P1,P3		;RESTORE
	MOVEI T1,.CTCI		;SET CHANNEL TYPE
	DPB T1,CSYTYP		;..
	MOVEI T1,PHYCHN		;SET PIA
	DPB T1,CSYPIA		; IN CONFIGURATION INFORMATION
	MOVX T1,CS.STK		;CHANNEL CAN'T DO
	ANDCAM T1,CDBSTS(P1)	; COMMAND STACKING
	MOVX T1,CS.CIP		;THIS IS A
	IORM T1,CDBSTS(P1)	; CI CHANNEL
	MOVEI T1,CHNUNK		;GET "UNKNOWN" CODE
	STOR T1,CFSTA,(P1)	;SET INITIAL STATE OF THE KLIPA
	MOVEI T1,KLPRH2		;GET RH NUMBER
	LSH T1,2		;TIMES 4
	MOVEI T2,KIEPT+3(T1)	;IN UNUSED LOGOUT AREA
	HRLZM T2,CDBICP(P1)	;AND STORE AS INTERRUPT VECOTOR
	ADDI T1,RHEPT+KIEPT	;ADDRESS OF CHANNEL ICP AREA
	HRRM T1,CDBICP(P1)	;STASH IN CDB
	MOVEI T3,CDBINT(P1)	;ADDRESS FOR XPCW ON INTERRUPT
	HRLI T3,(<XPCW>)	;BUILD INSTRUCTION
	MOVEM T3,0(T2)		;STORE IN PAGE 0
;...
;...
	MOVEI T3,CDBINT+4(P1)	;SET JUMP ADDRESS
	MOVEM T3,CDBINT+3(P1)	;SET IN XFER VECTOR
	SETZM CDBINT+2(P1)	;SET FLAGS TO 0
	MOVE T1,[MOVEM P1,CDBSVQ]
	ADDI T1,0(P1)		;INSTRUCTION TO STORE P1 IN CDB
	MOVEM T1,CDBINT+4(P1)	;BUILD INTERRUPT CODE
	MOVE T1,[JSP P1,PHYINT]
	MOVEM T1,CDBINT+5(P1)	;DISPATCH TO PHYSIO
	MOVE T1,[BLT 17,17]	;INSTRUCTION TO RESTORE ACCUMULATORS
	MOVEM T1,CDBJEN(P1)	;PUT IN CDB
	MOVE T1,[JRST KLPCHR] 	;HOW TO EXIT THE INTERRUPT
	MOVEM T1,CDBJEN+1(P1)	;DON'T DO A DATAO RH, IN THE EXIT SEQUENCE
	MOVEI T1,CDBINT(P1)	;ADDRESS OF INTERRUPT PC
	HRLI T1,(<XJEN 0>)	;BUILD XJEN INSTRUCTION
	MOVEM T1,CDBJEN+2(P1)	;STORE
	MOVEI T1,KLPDSP		;SET UP
	MOVEM T1,CDBDSP(P1)	; CHANNEL DISPATCH VECTOR
	MOVE T1,[-1-MAXNDS,,CDBUDB] ;MAKE AOBJN POINTER
	ADDI T1,0(P1)		; TO UDB TABLE
	MOVEM T1,CDBIUN(P1)	;SET INITIAL UNIT POINTER
	MOVEM T1,CDBCUN(P1)	;SET CURRENT UNIT POINTER
	SETZM CDBFLG(P1)	;CLEAR FLAGS WORD
	SETOM CDBCTR(P1)	;SET PERFORMANCE COUNTER AVAILABLE
	SETOM CDBNOD(P1)	;WE DON'T YET KNOW OUR NODE NUMBER YET
	SETOM CDBXFR(P1)	;INDICATE CHANNEL FREE
	CALL PCBINI		;(P1) INITIALIZE THE PCB
	RET


;FIND THE KLIPA LATE (AFTER BOOTING THE MONITOR WITH NOKLIP SET NON-0)
;RETURNS:	+1
;
;NOTE: You'd better know what you are doing if you ever call this routine.
;If there are other TOPS-20 systems on your CI you will be violating some
;basic rules of CFS.  This routine is intended to be used only when there
;are no other TOPS-20 systems running on the CI.

KLPLAT:	SETZM NOKLIP		;BACK TO NORMAL
	CALL KLPINI		;PRETEND WE ARE PHYSIO
	CALLRET PPDINX		;PRETEND WE ARE MEXEC
;INITIALIZE THE PCB
;ACCEPTS:	P1/ CDB
;RETURNS:	+1

PCBINI:	SAVEAC <Q3>
	MOVEI Q3,PCB		;PCB ADDRESS
	MOVEM Q3,CDBPCB(P1)	;POINT CDB AT PCB
	MAP T1,PCB		;GET PHYSICAL ADDRESS
	TLZ T1,777760		;MASK OUT GARBAGE
	MOVEM T1,.PBPBA(Q3)	;SAVE BASE ADDR IN PCB FOR KLIPA HDWRE
	SUBM Q3,T1		;COMPUTE OFFSET BETWEEN PHYSICAL AND VIRTUAL ADDRESSES
	MOVEM T1,OFFSET		;SAVE IT
	LDB T2,CSYPIA		;GET PIA
	MOVEM T2,.PBPIA(Q3)	;PUT IT IN PCB
	CALL RSTQS		;(Q3/) RESET THE QUEUES
	MOVEI	T2,C%MGSZ
	MOVEM	T2,.PBMQE(Q3)	;MAX MESSAGE LENGTH
	MOVEI T2,C%DGSZ
	MOVEM T2,.PBDQE(Q3)	;MAX DATAGRAM LENGTH
	SKIPE	T1,BHDIPT	;ALREADY HAVE BUFFER DESCRIPTOR TABLE SET UP?
	JRST	PCBIN4		;YES
	MOVEI	T1,BDTTAB+3	;GET VIRTUAL ADDRESS OF BUFFER DESCRIPTOR TABLE
	TRZ	T1,3		;MAKE SURE IT STARTS ON 4-WORD BOUNDARY
	HRLI	T1,-BHDNUM	;SET UP AOBJN POINTER
	MOVEM	T1,BHDIPT	;SAVE FOR FINDING A FREE BHD
	MOVEM	T1,BHDCPT
PCBIN2:	SETZM	.BHKEY(T1)	;SAVE POINTER TO BHD IN TABLE
	ADDI	T1,L.BHD-1	;POINT AT NEXT BHD
	AOBJN	T1,PCBIN2	;STORE ITS ADDR IN TABLE
	MOVEI	T2,BSDTAB+3
	TRZ	T2,3		;START ON A 4-WORD BOUNDARY
	MOVEM	T2,BSDLOC	;SAVE ADDRESS OF BSD TABLE
	MOVEI	T3,2*BHDNUM-1	;LINK THE BSDS TOGETHER
PCBIN3:	MOVEI	T4,L.BSD(T2)	;POINTER TO NEXT BSD
	MOVEM	T4,.BSNXT(T2)	;LINK THIS TO NEXT
	ADDI	T2,L.BSD
	SOJG	T3,PCBIN3	;LOOP FOR ALL EXCEPT LAST
	SETZM	.BSNXT(T2)	;CLEAR LINK WORD IN LAST BSD
	MOVSI	T1,-10
	MOVEM	T1,CHNIUN	;SET UP POINTERS FOR UNQUEUEING REQUESTS
	MOVEM	T1,CHNCUN
	HRRZ	T1,BHDIPT
PCBIN4:	HRRZM	T1,.PBBDT(Q3)	;SAVE BDT IN PCB
	MOVEI T1,KIEPT+KLPRH2*4+1 ;GET CHANNEL LOGOUT WORD
	MOVEM T1,.PBRS5(Q3)	;STASH IT FOR KLIPA
	RET
	SUBTTL PHYSIO Interface -- KLPSIO (Start I/O)

;HERE THROUGH KLPDSP (THE CDSSIO OFFSET)
;RETURNS:	+1 FAILED
;		+2 SUCCESS

KLPSIO:	LOAD T1,USTYP,(P2)	;GET CONTROLLER TYPE
	CAIE T1,.UTHSC		;AN HSC?
	CALL DSPBUG		;NO
	MOVEI T1,MSCDSP		;YES, GET MSCP CONTROLLER DISPATCH VECTOR
	CALLRET UDSSIO(T1)	;GO DO THE WORK
	SUBTTL PHYSIO Interface -- KLPINT (Interrupt Service)

;INTERRUPT SERVICE - HERE FROM PHYINT THROUGH KLPDSP (THE CDSINT OFFSET)
;RETURNS:	+1  P4/ 0 - DISMISS THE INTERRUPT

;Common use of the ACs in interrupt service
;Q1/ Node number
;Q2/ packet address
;Q3/ PCB address
;P1/ CDB address
;P2/ op code
;P3/ -1 if locally-generated, 0 if remotely-generated
;P4/ PPD byte
;P5/ system block address

KLPINT::EA.ENT			;NEED TO BE IN A NON-0 SECTION
	RDTIME KLPENT		;[7.1202] Get and save current time
	LOAD T1,CFSTA,(P1)	;GET PORT STATE
	CALLRET @INTSTA(T1)	;TAKE APPROPRIATE ACTION

KLPIN1:	CONI KLP,T1		;GET CSR
	MOVEM T1,CDBCNI(P1)	;SAVE IT
	MOVE Q3,CDBPCB(P1)	;GET PCB
	TXNN T1,CI.CPE!CI.MBE	;CRAM PARITY ERROR OR MBUS ERROR?
	IFSKP.
	   MOVEI T1,CHNSTP	;YES, GET STOPPED CODE
	   STOR T1,CFSTA,(P1)	;SET PORT STATE
	   CALL REPORT		;(Q3,P1) MAKE ERROR.SYS ENTRY
	   CALL CPEBUG		;(Q3,P1) OUTPUT BUGXXX
	   CALL NONODS		;() TELL SCA ABOUT NODES GOING AWAY
	   CALL RSTLKS		;(Q3) RESET THE PCB QUEUE INTERLOCKS
	   CALL RSTRID		;() RESET REQUEST-ID DATA
	   MOVE T1,CDBCNI(P1)	;RETRIEVE CSR
	   TXNN T1,CI.CPE	;CRAM PARITY ERROR?
	   IFSKP.
	      CALL KLPCPE	;(Q3,P1) YES (KLPCPE MAY CALL KLPRQC)
	   ELSE.
	      CALL KLPMBE	;(Q3,P1) NO, MBUS ERROR (KLPRQC WON'T BE CALLED)
	   ENDIF.
	ELSE.
;There was neither a CRAM parity error nor an MBUS error

	   TXNN T1,CI.RQA	;NO, RESPONSE QUEUE AVAILABLE?
	   IFSKP.
	      CALL KLPRQA	;(Q3,P1) YES, PROCESS THE PACKETS
	      MOVE T1,CDBCNI(P1) ;RETRIEVE THE CSR
	   ENDIF.
	   TXNE T1,CI.FQE	;FREE QUEUE ERROR?
	   CALL KLPFQE		;(Q3,P1) YES, FIND OUT WHICH ONE
	ENDIF.
KLPIN2:	SETZ P4,		;TELL PHYINT NOT TO DO ANYTHING ELSE
	RDTIME T1		;[7.1202] Get exit time
	DSUB T1,KLPENT		;[7.1202] Compute time spent in interrupt routine
	DADD T1,TOTKLP		;[7.1202] Accumulate overall time
	DMOVEM T1,TOTKLP	;[7.1202] And save
	RET
;RESPONSE QUEUE AVAILABLE
;ACCEPTS:	Q3/ PCB
;		P1/ CDB
;RETURNS:	+1
;NOTE: IF YOU ARE NOT AT INTERRUPT LEVEL, YOU MUST CALL THIS ROUTINE CIOFF.

;Special entry for cleaning the response queue when the port is disabled

KLPRQC:	CONO KLP,CI.EPE!CI.RQA	;CLEAR RESPONSE-AVAILABLE, EBUS PARITY, DON'T ENABLE PORT
	JRST KLPRQ7		;DO THE REAL WORK
	
;Standard entry for processing the response queue

KLPRQA:	MOVE T1,.PBPIA(Q3)	;GET PIA
	CONO KLP,CI.EPE!CI.RQA!CO.BTS(T1) ;CLEAR RESPONSE-AVAILABLE, EBUS PARITY
KLPRQ7:	STKVAR <QEMPT>		;QEMPT:  0=QUEUE EMPTY, -1=QUEUE NOT EMPTY
KLPRQ1:	AOS CIPKRC		;[7211] COUNT THE PACKET
	SETZM QEMPT		;[7211] ASSUME RESPONSE Q EMPTY AFTER THIS PACKET
	MOVEI T1,.PBRQI(Q3)	;GET RESPONSE QUEUE INTERLOCK WORD
	CALL REMQUE		;(T1/Q2) GET 1ST PACKET OFF THE QUEUE
	 JRST [BUG. (INF,KLPERQ,PHYKLP,HARD,<PHYKLP - Empty response queue>,,<

Cause:	The monitor got an interrupt to remove a packet from the response
	queue. The queue was empty.
>,,<DB%NND>)			;[7.1210] 
		RET]		;DONE
KLPRQ2:	  SETOM QEMPT		;QUEUE IS STILL NON-EMPTY. FLAG THAT
KLPRQ3:
IFN KLPDBG,<			;[7.1134]
ANSWER:	MOVEI T1,.
	HRL T1,Q2
	CALL COLECT
	MOVE T1,3(Q2)
	CALL COLECT
	MAP T1,.PBRQF(Q3)
	TLZ T1,777760
	CAMN T1,.PBRQF(Q3)	;empty queue?
	JRST ANSWE2		;[7.1156] yes

;Queue is non-empty

ANSWE1:	MOVEI	T1,.
	HRL	T1,.PBRQF(Q3)	;no. stash current pcb+17
	CALL	COLECT
	SKIPL	QEMPT		;empty when we pulled packet off response queue?
	AOS	RACES		;yes. count one
ANSWE2:>			;[7.1134] end of IFN KLPDBG

;LABEL FOR CILOOK SNOOP% CODE
CILIN:
	CALL	RMASAG		;Byte swap PPD byte
	; ..
;We have the packet.  Get the opcode and dispatch appropriately.

	LDB Q1,PKYNOD		;GET NODE NUMBER
	CAIL Q1,0		;A LEGAL
 	CAILE Q1,MAXNDS		; NODE NUMBER?
	IFNSK.
	   LDB T2,PKYSTS	;NO, GET STATUS FIELD
	   LDB T3,PKYFLG	;GET FLAGS FIELD
	   LDB T4,PKYOP		;GET OP CODE FIELD
	   BUG. (CHK,KLPNDE,PHYKLP,SOFT,<PHYKLP - Packet with bad node number>,<<T2,STATS>,<T3,FLAGS>,<T4,OPC>,<Q1,NODE>>,<

Cause:	CI20 driver received a packet with an invalid node number. The packet
	has not been returned to a free queue.

Data:	STATS - Status field of packet
	FLAGS - Flags field of packet
	OPC   - op code field of packet
	NODE  - node number
>,,<DB%NND>)			;[7.1210] 
	   JRST KLPRQ6		;TRY FOR ANOTHER PACKET
	ENDIF.
	MOVE P5,SBLIST(Q1)	;GET THE SYSTEM BLOCK
	LDB P2,PKYOP		;GET OP CODE
;Do a sanity check on the port. The op code indicates whether the packet
;came from the other node, or we sent it out. If we sent it out,
;either there's an error, or we asked for the buffer back. If it came
;from the other node, we'd better not find the return-the-buffer bit on.

	MOVE T1,.PKSTS(Q2)	;GET STATUS
	TXZE P2,OP.RMT		;REMOTELY-GENERATED?
	IFSKP.
	  SETO P3,		;NO, SAY LOCALLY-GENERATED
   REPEAT 0,<
	  CAIL P2,OP.CKT	;SPECIAL OP CODE?
	  JRST KLPRQ9		;YES. THESE COME BACK FROM OUR PORT
	  TXNE T1,PS.ERR	;WAS THERE AN ERROR?
	  JRST KLPRQ9		;YES. THAT'S OK
	  TMNE <PKSCA,PKDRV>,(Q2) ;NO. DID WE ASK FOR THIS BUFFER BACK?
	  JRST KLPRQ9		;YES. GOOD
	  LDB T4,PKYNOD		;GET NODE FIELD
	  BUG.(CHK,KLPUER,PHYKLP,HARD,<PHYKLP - Unexpected response received>,<<T4,NODE>,<T1,STATUS>>,<

Cause:	The port placed a packet on the response queue with an op code
	indicating that the packet had been queued by this host.  The
	status bits don't confirm that.

Data:	NODE - Node number
	STATUS - Status word
>)
	RET			;THROW AWAY THE BUFFER
   >				;END OF REPEAT 0
	ELSE.
	  SETZ P3,		;YES, NOT LOCALLY-GENERATED
   REPEAT 0,<
	  TMNN <PKSCA,PKDRV>,(Q2) ;DO WE SEEM TO WANT A RESPONSE?
	  JRST KLPRQ9		;NO. THAT'S GOOD
	  LDB T4,PKYNOD		;GET OP CODE FIELD
	  BUG.(CHK,KLPIFL,PHYKLP,HARD,<PHYKLP -  Illegal flags>,<<T4,NODE>,<T1,STATUS>>,<

Cause:	The response queue contains a packet whose op code indicates
	that the packet was queued by a remote host. But the software response
	bit is set.

Data:	NODE - Node number
	STATUS - Status word
>)
	   RET			;THROW AWAY THE BUFFER
   >				;END OF REPEAT 0
	ENDIF.
KLPRQ9:	MOVSI T2,-<KLPOPL>	;MAKE AOBJN WORD FOR OPCODE SEARCH
KLPRQ4:	CAMN P2,KLPOPS(T2)	;THIS THE ONE?
	JRST KLPRQ5		;YES, GO DO THE WORK
	AOBJN T2,KLPRQ4		;NO, TRY NEXT OPCODE
	LDB T2,PKYSTS		;BAD OP CODE, GET STATUS FIELD
	LDB T3,PKYFLG		;GET FLAGS FIELD
	LDB T4,PKYNOD		;GET OP CODE FIELD
	BUG. (CHK,KLPOPC,PHYKLP,SOFT,<PHYKLP - Packet with bad op-code>,<<T2,STATS>,<T3,FLAGS>,<P2,OPC>,<T4,NODE>>,<

Cause:	CI20 driver received a packet with an invalid op-code. The packet
	has not been returned to a free queue.

Data:	STATS - Status field of packet
	FLAGS - Flags field of packet
	OPC   - op code field of packet
	NODE  - node number
>,,<DB%NND>)			;[7.1210] 
	JRST KLPRQ6		;TRY FOR ANOTHER PACKET
;.....
;All ACs are set except the PPD byte indicator

KLPRQ5:	SETOM P4		;ASSUME NO PPD BYTE
	TXNN T1,PS.ERR!PS.CLO	;ERROR OR PATH CLOSED?
	IFSKP.
	   TXNN T1,PS.ERR	;YES, WAS IT AN ERROR?
	   IFSKP.
	      CALL @KLPERB(T2)	;YES, DO ERROR PROCESSING
	      JRST KLPRQ6	;GO FOR NEXT PACKET
	   ELSE.
	      CALL CLOPTH	;(T1) NO ERROR, UPDATE PATH INFO
	      TMNE PKSRB,(Q2)	;WERE WE EXPECTING A RESPONSE?
	      IFSKP.
	        CALL @RETCLO(T2) ;(Q2,Q3) NO, RETURN PACKET TO FREE QUEUE
	        JRST KLPRQ6	;CONTINUE
	      ENDIF.
	   ENDIF.
	ENDIF.
	CALL @KLPROU(T2)	;PROCESS THE PACKET
KLPRQ6:	SKIPE QEMPT		;IS RESPONSE Q EMPTY?
	JRST KLPRQ1		;NO, GO DO THE NEXT ONE
;***** This doesn't work, we need to fix it for testing
   REPEAT 0,<
	MOVE T1,.PBPIA(Q3)
	CONO KLP,CI.RQA!CO.BTS(T1)
	CALL REMQUE
	 JRST KLPRQ1
	 JRST KLPRQ2
	JRST KLPRQ3
   >
	RET

	ENDSV.
;CLOSED PATH - PROCESS A PACKET WITH B0 OFF AND B1 ON
;ACCEPTS:	T1/ PACKET STATUS WORD
;		Q1/ NODE NUMBER
;		Q3/ PCB
;RETURNS:	+1
;PRESERVES T1-2, Q1-3, P1-6

CLOPTH:	SAVEPQ
	STKVAR <<T1T2,2>,AFLAG>
	DMOVEM T1,T1T2		;PRESERVE T1,T2
	TXNN T1,PS.AKA		;ACKED ON A?
	IFSKP.
	   SETZRO IDPBO,(Q1)	;YES, B NOW CLOSED
	   SETZM AFLAG		;PATH B
	ELSE.
	   SETZRO IDPAO,(Q1)	;NO, PATH A NOW CLOSED
	   SETOM AFLAG		;PATH A
	ENDIF.
	CALL KLPGDB		;(Q3/Q2) GET A BUFFER
	 JRST CLOPT1		;CAN'T NOW, WE'LL HAVE TO WAIT FOR THE POLLER
	MOVX T3,PF.PT0		;ASSUME PATH A WAS CLOSED
	SKIPE AFLAG		;WAS IT A?
	MOVX T3,PF.PT1		;NO, PATH B
	CALL KLPRID		;(T3,Q1,Q2,Q3) SEND A REQUEST-ID
	 NOP			;NO SUCH RETURN
CLOPT1:	DMOVE T1,T1T2		;RETRIEVE T1,T2
	RET

	ENDSV.
;OPCODE LOOK UP TABLE

KLPOPS:	OP.SMS			;SEND MESSAGE
	OP.LPB			;SEND/RECEIVE LOOPBACK
	OP.RID			;REQUEST ID
	OP.IDR			;ID RECEIVED
	OP.SDG			;SEND DATAGRAM
	OP.RCF			;DATA CONFIRM RECEIVED
	OP.RDT			;RETURN DATA (DATREC)
	OP.RCT			;READ STATISTICS COUNTERS
	OP.RRG			;READ REGISTER
	OP.CKT			;SET VIRTUAL CIRCUIT
	OP.RD1			;REQUEST DATA ON COMMAND QUEUE 1
	OP.MCR			;MAINTENANCE CONFIRM RECEIVED
	OP.MDR			;MAINTENANCE DATA RECEIVED
	OP.RD0			;REQUEST DATA ON COMMAND QUEUE 0
	OP.RD2			;REQUEST DATA ON COMMAND QUEUE 2
	OP.SDT			;SEND DATA
	OP.RRS			;RESET REMOTE SYSTEM
	OP.SRS			;START REMOTE SYSTEM
	OP.RMD			;REQUEST MAINTENANCE DATA
	OP.SMD			;SEND MAINTENANCE DATA
	OP.SPT			;SET STATISTICS COUNTERS
	OP.WRG			;WRITE REGISTER
	OP.CLB			;CLOSE BUFFER
KLPOPL==.-KLPOPS		;LENGTH OF KLPOPS

;DISPATCH TABLE (PARALLEL TO KLPOPS) FOR ERROR-FREE PACKETS

KLPROU:	IFIW!GIVSCA		;SEND MESSAGE
	IFIW!INTLPB		;SEND/RECEIVE LOOPBACK
	IFIW!INTRID		;REQUEST ID
	IFIW!INTIDR		;ID RECEIVED
	IFIW!INTDG		;SEND DATAGRAM
	IFIW!INTNBF		;DATA CONFIRM RECEIVED
	IFIW!INTNBF		;RETURN DATA (DATREC)
	IFIW!INTRCT		;READ STATISTICS COUNTERS
	IFIW!INTRRG		;READ REGISTER
	IFIW!INTCKT		;SET VIRTUAL CIRCUIT
	IFIW!INTRD1		;REQUEST DATA ON COMMAND QUEUE 1
	IFIW!INTMCR		;MAINTENANCE CONFIRM RECEIVED
	IFIW!INTMDR		;MAINTENANCE DATA RECEIVED
	IFIW!INTRD0		;REQUEST DATA ON COMMAND QUEUE 0
	IFIW!INTRD2		;REQUEST DATA ON COMMAND QUEUE 2
	IFIW!INTSDT		;SEND DATA
	IFIW!RETDG		;RESET REMOTE SYSTEM
	IFIW!RETDG		;START REMOTE SYSTEM
	IFIW!RETDG		;REQUEST MAINTENANCE DATA
	IFIW!RETDG		;SEND MAINTENANCE DATA
	IFIW!RETDG		;SET STATISTICS COUNTERS
	IFIW!RETDG		;WRITE REGISTER
	IFIW!INTCLO		;CLOSE BUFFER
;DISPATCH TABLE (PARALLEL TO KLPOPS) FOR PACKETS WITH THE ERROR (B0) BIT ON

KLPERB:	IFIW!GIVERR		;SEND MESSAGE
	IFIW!LPBERR		;SEND/RECEIVE LOOPBACK
	IFIW!RIDERR		;REQUEST ID
	IFIW!RETDG		;ID RECEIVED
	IFIW!DGERR		;SEND DATAGRAM
	IFIW!NBFERR		;DATA CONFIRM RECEIVED
	IFIW!NBFERR		;RETURN DATA (DATREC)
	IFIW!RCTERR		;READ STATISTICS COUNTERS
	IFIW!RRGERR		;READ REGISTER
	IFIW!CKTERR		;SET VIRTUAL CIRCUIT
	IFIW!RD1ERR		;REQUEST DATA ON COMMAND QUEUE 1
	IFIW!MCRERR		;MAINTENANCE CONFIRM RECEIVED
	IFIW!MDRERR		;MAINTENANCE DATA RECEIVED
	IFIW!RD0ERR		;REQUEST DATA ON COMMAND QUEUE 0
	IFIW!RD2ERR		;REQUEST DATA ON COMMAND QUEUE 2
	IFIW!SDTERR		;SEND DATA
	IFIW!RETDG		;RESET REMOTE SYSTEM
	IFIW!RETDG		;START REMOTE SYSTEM
	IFIW!RETDG		;REQUEST MAINTENANCE DATA
	IFIW!RETDG		;SEND MAINTENANCE DATA
	IFIW!RETDG		;SET STATISTICS COUNTERS
	IFIW!RETDG		;WRITE REGISTER
	IFIW!CLOERR		;CLOSE BUFFER

;DISPATCH TABLE (PARALLEL TO KLPOPS) FOR PACKETS WITH THE ERROR BIT (B0) OFF
;BUT THE CLOSED PATH BIT (B1) ON AND NO RESPONSE WAS REQUESTED

RETCLO:	IFIW!RETMSG		;SEND MESSAGE
	IFIW!RETDG		;SEND/RECEIVE LOOPBACK
	IFIW!RETDG		;REQUEST ID
	IFIW!RETDG		;ID RECEIVED
	IFIW!RETDG		;SEND DATAGRAM
	IFIW!RETMSG		;DATA CONFIRM RECEIVED
	IFIW!RETMSG		;RETURN DATA (DATREC)
	IFIW!RETDG		;READ STATISTICS COUNTERS
	IFIW!RETDG		;READ REGISTER
	IFIW!RETDG		;SET VIRTUAL CIRCUIT
	IFIW!RETMSG		;REQUEST DATA ON COMMAND QUEUE 1
	IFIW!RETDG		;MAINTENANCE CONFIRM RECEIVED
	IFIW!RETDG		;MAINTENANCE DATA RECEIVED
	IFIW!RETMSG		;REQUEST DATA ON COMMAND QUEUE 0
	IFIW!RETMSG		;REQUEST DATA ON COMMAND QUEUE 2
	IFIW!RETMSG		;SEND DATA
	IFIW!RETDG		;RESET REMOTE SYSTEM
	IFIW!RETDG		;START REMOTE SYSTEM
	IFIW!RETDG		;REQUEST MAINTENANCE DATA
	IFIW!RETDG		;SEND MAINTENANCE DATA
	IFIW!RETDG		;SET STATISTICS COUNTERS
	IFIW!RETDG		;WRITE REGISTER
	IFIW!RETDG		;CLOSE BUFFER
;Received either 1) an application datagram or 2) a message
;RETURNS:	+1

GIVSCA:	SKIPE P5		;DO WE HAVE A SB?
	IFSKP.
	   LDB T1,PKYSTS	;NO, GET STATUS FIELD
	   LDB T2,PKYFLG	;GET FLAGS FIELD
	   BUG. (CHK,KLPIPA,PHYKLP,HARD,<PHYKLP - Invalid packet arrival>,<<T1,STATS>,<T2,FLAGS>,<P2,OPC>,<Q1,NODE>>,<

Cause:	The CI20 driver has received an application packet from a node with
	which it doesn't think it has ever communicated.

DATA:	STATS - Status field of packet
	FLAGS - Flags field of packet
	OPC   - op code field of packcet
	NODE  - node number
>,,<DB%NND>)			;[7.1238]
	   CAIE P2,OP.SDG	;NO, IS IT A DATAGRAM?
	   IFSKP.
	      CALLRET RETDG	;YES
	   ELSE.
	      CALLRET RETMSG	;NO, A MESSAGE
	   ENDIF.
	ENDIF.

;We have a SB

	JUMPN P3,GIVSC1		;IF LOCAL, GO TO IT
	LOAD T1,SBVCST,(P5)	;GET VC STATE
	CAIE T1,VC.STR		;START-RECEIVED?
	JRST GIVSC1		;NO, GO TO IT
	SETZRO SBSST,(P5)	;YES, STOP TIMER
	CALL OPNSCA		;(Q1,P5) TELL SCA ABOUT NEW NODE
	; ..
;HAND THE PACKET TO SCA
;ACCEPTS:	Q2/ PACKET ADDRESS
;		P3/ 0 IF REMOTELY-GENERATED, -1 IF LOCALLY-GENERATED
;		P5/ SB
;RETURNS:	+1
;
;NOTE:  MUST BE CALLED AT INTERRUPT LEVEL BECAUSE SCA AND THE SYSAPS ASSUME
;       THEY ARE AT INTERRUPT LEVEL WHEN BEING NOTIFIED ABOUT INCOMING PACKETS.

GIVSC1:	TMNN PKSCA,(Q2)		;SCA REQUEST A RESPONSE?
	IFSKP.
	  SKIPL P3		;YES. THIS SHOULD BE LOCAL, THEN
	  BUG. (INF,KLPIRP,PHYKLP,HARD,<PHYKLP - Software response bit on in remotely-generated packet>,<<Q1,NODE>,<T1,STATUS>>,<

Cause:	The response queue contains a packet whose op code indicates
	that the packet was queued by a remote host but the software response
	bit is set.

Data:	NODE - Node number
	STATUS - Status word
>,,<DB%NND>)			;[7.1210]
	  MOVX P3,F.RSP		;TELL SCA THIS IS A RETURNED BUFFER
	  SETZRO <PKDRV,PKSCA>,(Q2) ;CLEAR ALL SOFTWARE RESPONSE BITS
	ELSE.
	  SKIPN P3		;NO. THIS SHOULD BE REMOTE, THEN
	  JRST GIVSC6		;IT IS.

;The port shouldn't have given us this buffer. SCAMPI doesn't want it,
;so put it back on the free queue.

	  BUG. (INF,KLPILP,PHYKLP,HARD,<PHYKLP - Software response bit off in locally-generated packet>,<<Q1,NODE>,<T1,STATUS>>,<

Cause:	The response queue contains a packet whose op code indicates
	that the packet was queued by this host but the software response
	bit is not set, and there was no error.

Data:	NODE - Node number
	STATUS - Status word
>,,<DB%NND>)			;[7.1238]
	  CAIN P2,OP.SDG	;Is this a datagram?
	  CALLRET RETDG		;(Q2,Q3) Yes. Give it back to the port
	  CALLRET RETMSG	;(Q2,Q3/) No. Put it on the message free queue
	ENDIF.
GIVSC6:	MOVE T1,.PKSTS(Q2)	;GET THE STATUS WORD
;...
;...
	LDB T3,PKYLEN		;Get the packet length
	TXNN T1,PF.FMT		;HIGH DENSITY?
	IFSKP.
	  TXO P3,F.SPM		;YES
	  MOVEI T3,3(T3)	;YES, Round up byte count in case of partial word
				;rounding factor = (# bytes per word) - 1
	  IMULI T3,2		;Convert bytes count to word count
	  IDIVI T3,^D9		;  I.E. (Byte count/4.5) = word count
	ENDIF.
	MOVE P2,Q2		;PACKET ADDRESS
	MOVE P4,P5		;SB ADDRESS
	BLCAL. (SC.INT,<P3,T3>) ;(P2,P4) Tell SCA, give the flags and packet length
	RET
;WE GOT A PACKET FOR SCA WITH AN ERROR
;ACCEPTS:
;RETURNS:	+1

GIVERR:	JUMPE P3,GIVER1		;IF REMOTELY-GENERATED, WE'RE DONE
	TMNE PKSCA,(Q2)		;LOCALLY-GENERATED, RESPONSE REQUESTED?
	IFSKP.

;Error in a remotely-generated packet, or
;in a locally-generated packet and no response requetsed

GIVER1:	   CAIN P2,OP.SDG	;IS IT A DATAGRAM?
	   CALLRET RETDG	;YES, RETURN IT TO FREE Q
	   CALL SCAERR		;(Q1,Q2,Q3,P5) NO, A MESSAGE. REPORT THE FAILURE
	   CALLRET RETMSG	;RETURN IT TO FREE Q
	ENDIF.

;Error in locally-generated packet and a response was requested

	CAIN P2,OP.SMS		;IS IT A MESSAGE?
	CALL SCAERR		;(Q1,Q2,Q3,P5) YES, SPEAR ENTRY, TELL SCA
	CALLRET GIVSC1		;(Q2,P3,P5) GIVE PACKET TO SCA
;WE HAVE A PACKET FOR SCA WITH AN ERROR
;ACCEPTS:	Q1/ NODE NUMBER
;		Q2/ PACKET ADDRESS
;		Q3/ PCB
;		P1/ CDB
;		P5/ SB
;RETURNS:	+1

SCAERR:	LOAD T1,SBVCST,(P5)	;GET VC STATE
	CAIE T1,VC.OPN		;VC OPEN?
	RET			;NO, DON'T NEED TO REPORT ANYTHING
	TRVAR <IBFLG>		;INVALID BUFFER NAME FLAG
	SETZM IBFLG		;ASSUME NOT INVALID BUFFER NAME
	LOAD T1,.PKSFD,(Q2)	;YES, GET ERROR CODE
	CAIN T1,PS.IBN		;INVALID BUFFER NAME ERROR?
	SETOM IBFLG		;YES, SET THE FLAG
	LOAD T1,CDVER,(P1)	;GET UCODE VERSION
	LDB T2,PKYSTS		;YES, GET STATUS FIELD
	LDB T3,PKYFLG		;GET FLAGS FIELD
	LDB T4,PKYOP		;GET OPCODE
	SKIPN IBFLG		;INVALID BUFFER NAME?
	IFSKP.
	   SKIPE CIBUGX		;YES, NOT REALLY INTERESTING
	   BUG. (INF,KLPIBN,PHYKLP,SOFT,<PHYKLP - Invalid buffer name>,<<T2,STATS>,<T3,FLAGS>,<T4,OPC>,<Q1,NODE>>,<

Cause:	The CI20 driver received a packet (message or named buffer) with an
	Invalid Buffer Name error.

Data:	STATS - Status field of packet
	FLAGS - Flags field of packet
	OPC   - op code field of packet
	NODE  - node number
>,,<DB%NND>)			;[7.1210] 
	   RET
	ENDIF.
	BUG. (INF,KLPERR,PHYKLP,SOFT,<PHYKLP - CI packet error>,<<T2,STATS>,<T3,FLAGS>,<T4,OPC>,<Q1,NODE>>,<

Cause:	The CI20 driver received a packet (message or named buffer) with an
	error.  This causes the virtual circuit to be closed.

Data:	STATS - Status field of packet
	FLAGS - Flags field of packet
	OPC   - op code field of packet
	NODE  - node number
>,,<DB%NND>)			;[7.1210] 
	SAVEAC <Q2>
	SETZB Q2,P4		;WE NEED A BUFFER TO DO THE SET CIRCUIT
	CALL CLOSV1		;(Q2,P4,P5/) CLOSE THE VC AND TELL SCA
	RET

	ENDTV.
;Received a DATAGRAM
;RETURNS:	+1

INTDG:	CALL CHKPPD		;(/P4) CHECK THE PPD BYTE
	 CALLRET RETDG		;(Q2,Q3) BAD PPD, RETURN PACKET TO FREE QUEUE
	CALLRET @DGDSP(P4)	;GO PROCESS THE PACKET

DGDSP:	IFIW!INTSTR		;START
	IFIW!INTSTK		;STACK
	IFIW!INTACK		;ACK
	IFIW!GIVSCA		;APPLICATION DATAGRAM
	IFIW!CHKPP1		;APPLICATION MESSAGE (OPCODE/PPD BYTE MISMATCH)
	IFIW!INTERP		;ERROR PACKET
	IFIW!INTSHT		;SHUTDOWN


;Received a DATAGRAM with an error
;RETURNS:	+1

DGERR:	CALL CHKPPD		;(/P4) CHECK THE PPD BYTE
	 CALLRET RETDG		;(Q2,Q3) BAD PPD, RETURN PACKET TO FREE QUEUE
	CALLRET @DGEDSP(P4)	;GO PROCESS THE PACKET

DGEDSP:	IFIW!RETDG		;START
	IFIW!RETDG		;STACK
	IFIW!RETDG		;ACK
	IFIW!GIVERR		;APPLICATION DATAGRAM
	IFIW!CHKPP1		;APPLICATION MESSAGE (OPCODE/PPD BYTE MISMATCH)
	IFIW!ERPERR		;ERROR PACKET
	IFIW!RETDG		;SHUTDOWN THAT FAILED.
;Received an ERROR-LOG Packet
;ACCEPTS:	Q2/ PACKET ADDRESS
;		Q3/ PCB
;RETURNS:	+1

KELEN==:100			;SPACE FOR BUILDING SEBPTR WORDS ON STACK

INTERP:	STKVAR <EBLOK,WORDS,<KETAB,KELEN>>
	AOS HSCELP		;[7211] COUNT THE PACKET
	LDB T1,PKYLEN		;GET NUMBER OF BYTES IN ERROR LOG MESSAGE
	ADDI T1,3		;CALCULATE NUMBER OF
	IDIVI T1,4		; WORDS NEEDED FOR MESSAGE
	ADDI T1,KE%LEN+1	;ADD LENGTH OF EVENT DATA PLUS ENTRY TYPE WORD
	MOVEM T1,WORDS		;SAVE IT
	MOVE T2,T1		;NO ADDITIONAL STRING
; ...
; ...
	CALL ALCSEB		;(T1,T2/T1) TRY TO GET ERROR BLOCK
	IFNSK.
	   BUG. (INF,KLPELL,PHYKLP,SOFT,<PHYKLP - Error Log Lost>,,<

Cause:	Can't get free space to create ERROR.SYS entry for ERROR LOG MESSAGE.
>)
	 JRST INTER1		;MOVE ON
	ENDIF.
	MOVEM T1,EBLOK		;SAVE LOC OF ERROR BLOCK
	MOVEI T2,KLPRH2		;GET KLIPA CHANNEL #
	STOR T2,KECHN		;STORE IT
	LDB T2,PKYNOD		;GET NODE #
	STOR T2,KENOD		;STORE IT
	SETZ P3,		;MAKE COUNTER FOR TABLE ENTRIES
	MOVEI T2,KETAB		;GET TABLE BEGINNING
	MOVE P4,[SEBPTR 0,SBTEVC,SEC%KE]  ;ENTRY TYPE WORD
	MOVEM P4,(T2)		;PUT IT IN TABLE
	AOS P3			;BUMP COUNTER
	AOS T2			;BUMP LOCATION
	MOVE P4,[SEBPTR KE%SRC,SBTWD,SRC246]  ;ENTRY DATA WORD
	MOVEM P4,(T2)		;PUT ITEM IN TABLE
	AOS P3			;BUMP COUNTER
	AOS T2			;BUMP LOCATION
	MOVE P4,[SEBPTR KE%ELG,SBTWD,.PKLEN+1(P3)]  ;ERROR LOG MESSAGE POINTER
INTER3:	MOVEM P4,(T2)		;PUT IT IN TABLE
	AOS P3			;BUMP COUNTER
	AOS T2			;BUMP LOCATION
	CAML P3,WORDS		;DONE?
	JRST INTER2		;YES
	INCR SEBOFS,P4		;NO, FIX DESTINATION
	INCR SEBDPT,P4		;  AND SOURCE
	CAIGE P3,KELEN		;MORE ROOM ON STACK?
	JRST INTER3		;YES, ADD NEXT ENTRY
	BUG. (INF,KLPELT,PHYKLP,SOFT,<PHYKLP - Error Log Truncated>,,<

Cause:	An ERROR LOG MESSAGE has been truncated in its ERROR.SYS entry.
>,,<DB%NND>)			;[7.1210] 

INTER2:	MOVN T2,P3		;GET NEGATIVE OF TABLE LENGTH WE BUILT ON STACK
	HRLS T2			;POSITION IT
	HRRI T2,KETAB		;GET THE TABLE ADDRESS
	MOVE P3,Q2		;SEBCPY USES Q2 INTERNALLY
	CALL SEBCPY		;(T1,T2)
	 JFCL
	MOVE T1,EBLOK		;RETRIEVE ERROR BLOCK
	CALL QUESEB		;(T1) HAND IT TO SPEAR
INTER1:	CALLRET RETDG		;(Q2,Q3) RETURN TO DG FREE Q

	ENDSV.
;Received an ERROR-LOG Packet with an error
;RETURNS:	+1

ERPERR:	LDB T2,PKYSTS		;GET STATUS FIELD
	LDB T3,PKYFLG		;GET FLAGS FIELD
	BUG. (CHK,KLPEPB,PHYKLP,SOFT,<PHYKLP - Error-logging packet is bad>,<<T2,STATS>,<T3,FLAGS>,<P2,OPC>,<Q1,NODE>>,<

Cause:	TOPS-20 received an error-logging packet (PPD byte 5) which had an
	error.  The packet is returned immediately to the free queue.  
	Whatever information it carried is lost.

Data:	STATS - Status field of packet
	FLAGS - Flags field of packet
	OPC   - op code field of packet
	NODE  - node number
>,,<DB%NND>)			;[7.1210] 
	CALLRET RETDG		;(Q2,Q3) RETURN PACKET FO FREE QUEUE
;Received a START
;RETURNS:	+1

INTSTR:	SKIPE P5		;SB EXIST?
	IFSKP.
	   SKIPE RIDTIM(Q1)	;NO, HAVE AN OUTSTANDING REQUEST-ID?
	   CALLRET RETDG	;YES, ONE'S ENOUGH
	   CALL GTCPTH		;(T1/T3) NO, GET CURRENT PATH
	   CALL KLPRID		;(T3,Q1,Q2,Q3) SEND A REQUEST ID IN THIS PACKET
	    NOP			;NO SUCH RETURN
	   RET
	ENDIF.
	CALL FILLSB		;(Q2,P5) COPY INFO TO SB
	LOAD T1,SBVCST,(P5) 	;GET VC STATE
	CALLRET @STRDSP(T1) 	;GO DO THE WORK

STRDSP:
	IFIW!RETDG		;CLOSED
	IFIW!STRSSN		;START-SENT
	IFIW!STRSTR		;START-RECEIVED
	IFIW!STROPN		;OPEN
;Received a START when in either START-SENT or START-RECEIVED state.
;Reset the timer, new state is START-RECEIVED, and send a STACK.
;RETURNS:	+1

STRSSN:	CALL KLPOPN		;(Q1,Q2,Q3) TELL PORT TO OPEN ITS CIRCUIT
	 NOP			;NO SUCH RETURN
	CALL KLPGDB		;(Q3/Q2) GET A DATAGRAM BUFFER
	 JRST STRST1		;OK, JUST LIKE THE STACK GETTING LOST
STRSTR:	MOVEI T1,PP.STK		;GET STACK CODE
	CALL STRTDT		;(T1,Q2) MAKE A STACK
	CALL KLPSDG		;(Q1,Q2,Q3) SEND IT
	 NOP
STRST1:	MOVEI T1,VC.STR		;GET START-RECEVIED CODE
	STOR T1,SBVCST,(P5)	;UPDATE STATE
	CALL STSST		;(P5) SET TIMER
	RET

;Received a START when in OPEN state.
;Close VC and inform SCA of the departure

STROPN:	BUG. (INF,KLPSWO,PHYKLP,SOFT,<PHYKLP - Received a START when VC was open>,<<Q1,NODE>>,<

Cause:	TOPS-20 has closed a virtual circuit because it received a START
	packet while the circuit was open.

Data:	NODE - node number
>,,<DB%NND>)			;[7.1210] 
	SETZ P4,
	CALL CLOSV1		;(Q2,P4,P5/) CLOSE THE VC AND TELL SCA
	RET

;COPY INFO FROM START/STACK TO SB
;ACCEPTS:	Q2/ PACKET ADDRESS
;		P5/ SB ADDRESS
;RETURNS:	+1

FILLSB:	MOVEI T1,.SBDPC-.SBDSS	;AMOUNT OF DATA TO MOVE
	XMOVEI T2,.SRSSY(Q2)	;FROM THE PACKET
	MOVEI T3,.SBDSS(P5)	;TO THE SYSTEM BLOCK
	EXTEND T1,[XBLT]	;FILL IN THE DATA
	MOVE T1,.SBMMS(P5)	;GET SIZE WORD FROM SB
	CALL REVFUL		;REVERSE THE BYTES TO MAKE THEM MEANINGFUL
	MOVEM T1,.SBMMS(P5)	;PUT MAX MESSAGE/DG SIZE INTO SYSTEM BLOCK
	RET
;Received a STACK
;RETURNS:	+1

INTSTK:	CALL FILLSB		;(Q2,P5) COPY INFO TO SB
	LOAD T1,SBVCST,(P5) 	;NO, GET VC STATE
	CALLRET @STKDSP(T1) 	;GO DO THE WORK

STKDSP:	IFIW!RETDG	;CLOSED
	IFIW!STKSTS	;START-SENT
	IFIW!STKSTR	;START-RECEIVED
	IFIW!STKOPN	;OPEN

;Received a STACK when in START-SENT or START-RECEIVED state.
;Stop timer, send ACK, open VC, new state is OPEN.
;RETURNS:	+1

STKSTS:	CALL KLPOPN		;(Q1,Q2,Q3) TELL PORT TO OPEN ITS CIRCUIT
	 NOP			;NO SUCH RETURN
	CALL KLPGDB		;(Q3/Q2) GET A DATAGRAM BUFFER
	 JRST STKST1		;OK, JUST LIKE ACK GETTING LOST
STKSTR:	MOVEI T1,PP.ACK		;GET ACK CODE
	DPB T1,PKYPPD		;PUT IT IN
	CALL KLPSDG		;(Q1,Q2,Q3) SEND IT
	 NOP			;NO SUCH RETURN
STKST1:	SETZRO SBSST,(P5)	;TURN OFF THE TIMER
	CALLRET OPNSCA		;(Q1,P5) TELL SCA ABOUT THE NEW NODE


;Received a STACK when in OPEN state.
;Send an ACK.

STKOPN:	MOVEI T1,PP.ACK		;GET ACK CODE
	DPB T1,PKYPPD		;PUT IT IN
	CALL KLPSDG		;(Q1,Q2,Q3) SEND IT
	 NOP			;NO SUCH RETURN
	RET
;Received an ACK
;ACCEPTS:	T2/ FLAGS
;		Q1/ SB ADDRESS
;		Q2/ PACKET ADDRESS
;RETURNS:	+1

INTACK:	LOAD T1,SBVCST,(P5)	;GET STATE OF VC
	CALLRET @ACKDSP(T1)	;GO DO THE WORK

ACKDSP:	IFIW!RETDG		;CLOSED
	IFIW!RETDG		;START-SEND
	IFIW!ACKSTR		;START-RECEIVED
	IFIW!RETDG		;OPEN


;Received an ACK when in START-RECEIVED state.
;Stop timer and set state to OPEN.

ACKSTR:	SETZRO SBSST,(P5)	;TURN OFF THE TIMER
	CALLRET OPNSCA		;(Q1,P5) TELL SCA ABOUT THE NEW NODE




;Received a shutdown. We don't care what state we were in because
;CLOSVC won't try to do anything if the v.c. isn't open.

INTSHT:	BUG. (INF,KLPRSH,PHYKLP,SOFT,<PHYKLP - Received shutdown message>,<<Q1,NODE>>,<

Cause:	A CI node has notified our node that it is closing our v.c.

Data:	NODE - Node number
>,,<DB%NND>)			;[7.1210] 
	SETZM P4		;INDICATE WE WANT A SET CIRCUIT DONE
	CALL CLOSV1		;(Q2,P4,P5/) CLOSE THE V.C. AND TELL SCA
	RET
;TELL SCA A NODE HAS COME ON LINE (A VC IS NOW OPEN)
;ACCEPTS:	Q1/ NODE NUMBER
;		P5/ SYSTEM BLOCK
;RETURNS:	+1

OPNSCA:
	BUG. (INF,KLPOVC,PHYKLP,SOFT,<PHYKLP - Opened virtual circuit>,<<Q1,NODE>>,<

Cause:	TOPS-20 has opened a virtual circuit to a remote node on the CI.

Data:	NODE - CI node number
>,,<DB%NND>)			;[7.1210] 
	MOVEI T1,VC.OPN		;GET OPEN CODE
	STOR T1,SBVCST,(P5)	;SET NEW VC STATE
	SETZRO SBOKO,(P5)	;NO LONGER OK TO OPEN THE VC
	BLCAL. (SC.ONL,<Q1>)	;TELL SCA ABOUT NEW NODE
	 NOP			;SOMETHING WRONG
	RET
;Check the PPD byte
;RETURNS:	+1 BAD
;		+2 OK

CHKPPD:	LDB P4,PKYPPD		;GET PPD BYTE
	CAIL P4,PP.STA		;LEGAL
	CAILE P4,PP.MAX		; PPD BYTE?
	IFNSK.

;Special entry point for opcode/PPD mismatch

CHKPP1:	   LDB T2,PKYSTS	;NO, GET STATUS FIELD
	   LDB T4,PKYOP		;GET OP CODE FIELD
	   LDB T1,PKYNOD	;GET NODE NUMBER FIELD
	   BUG. (CHK,KLPPPD,PHYKLP,SOFT,<PHYKLP - Packet with bad PPD byte>,<<T2,STATS>,<T4,OPC>,<T1,NODE>,<P4,PPD>>,<

Cause:	The CI20 driver received a packet with an invalid PPD byte. The packet
	has not been returned to a free queue.

Data:	STATS - Status field of packet
	OPC   - op code field of packcet
	NODE  - node number
	PPD   - PPD byte
>,,<DB%NND>)			;[7.1210] 
	   RET
	ENDIF.
	RETSKP			;IT'S GOOD
;Received a CONFIRM or a DATA RECEIVED
;RETURNS: 	+1

INTNBF:	CAMN P3,[-1]		;LOCALLY-GENERATED?
	CALLRET RETMSG		;(Q2,Q3) YES, GIVE PACKET BACK TO FREE QUEUE
	DMOVE T1,.PKXID(Q2)	;NO, T1=BUFFER NAME,  T2=CID
	MOVE P4,P5		;Get address of system block
	CALL SC.DMA		;(T1,T2,P4) TELL SCA
	MOVE T1,Q2		;POSITION BUFFER ADDRESS
	CALLRET SC.RBF		;(T1) GIVE BUFFER TO SCA POOL
;Received a REQUEST-ID
;ACCEPTS:	Q1/ NODE
;		Q2/ PACKET
;		Q3/ PCB
;RETURNS:	+1

;Special entry point for RIDERR

INTRER:	SAVEAC <T1,T2>

;Normal entry point through dispatch table

INTRID:	SETZRO PKSRB,(Q2) 	;CLEAR ALL SOFTWARE RESPONSE BITS
	CALL RETDG		;(Q2,Q3) RETURN THE BUFFER
	SETZRO IDWFR,(Q1)	;NO LONGER WAITING FOR RESPONSE FROM OUR PORT
				; (THIS WAS 2ND TRY)
	RET
;Received a REQUEST-ID with an error
;ACCEPTS:	T1/ PACKET STATUS WORD
;		Q1/ NODE
;		Q2/ PACKET
;		Q3/ PCB
;RETURNS:	+1

RIDERR:	SETZM RIDTIM(Q1)	;TURN OFF TIMER
	SETZRO <IDTRY,IDMAI,IDNOR>,(Q1) ;RESET 2ND TRY, NO-ANSWER, MAINT.
	LDB T2,PKYSTS		;GET STATUS FIELD FROM PACKET
	CALL INTRER		;(Q1,Q2,Q3) GIVE BACK THE BUFFER
	TXNN T1,PF.PT0		;TRIED ON PATH A?
	JRST RIDERB		;NO

;Failed on A

	CAIE T2,PS.NRA		;N-R ON A?
	JRST RIDER1		;NO

;No-Response on A

	TMNE IDNRA,(Q1)		;WAS IT THAT WAY LAST TIME?
	RET			;YES, NO CHANGE IN STATUS
	SETONE IDNRA,(Q1)	;NO, CHANGE ITS STATUS
	CALLRET PHYSTC		;() TELL DISK SERVICE ABOUT STATUS CHANGE

;Other than No-Response on A

RIDER1:	TMNN IDNRA,(Q1)		;WAS IT PREVIOUSLY N-R?
	RET			;NO, NO CHANGE IN STATUS
	SETZRO IDNRA,(Q1)	;YES, CHANGE ITS STATUS
	CALLRET PHYSTC		;() TELL DISK SERVICE ABOUT STATUS CHANGE
;Failed on B

RIDERB:	CAIE T2,PS.NRB		;N-R ON B?
	JRST RIDER2		;NO

;No-Response on B

	TMNE IDNRB,(Q1)		;WAS IT THAT WAY LAST TIME?
	RET			;YES, NO CHANGE IN STATUS
	SETONE IDNRB,(Q1)	;NO, CHANGE ITS STATUS
	CALLRET PHYSTC		;() TELL DISK SERVICE ABOUT STATUS CHANGE

;Other than No-Response on B

RIDER2:	TMNN IDNRB,(Q1)		;WAS IT PREVIOUSLY N-R?
	RET			;NO, NO CHANGE IN STATUS
	SETZRO IDNRB,(Q1)	;YES, CHANGE ITS STATUS
	CALLRET PHYSTC		;() TELL DISK SERVICE ABOUT STATUS CHANGE
;CHECK FOR AN OPEN VC
;ACCEPTS:	P5/ SB (OR 0)
;RETURNS:	+1  VC OPEN
;		+2  NO OPEN VC

CHKVCO:	SKIPN P5		;HAVE A SB?
	RET			;NO
	LOAD T2,SBVCST,(P5)	;GET VC STATE
	CAIE T2,VC.OPN		;OPEN?
	RET			;NO
	RETSKP			;YES
;Received an IDREC
;ACCEPTS:	T1/ PACKET STATUS WORD
;		Q1/ NODE
;		Q2/ PACKET
;		Q3/ PCB
;RETURNS:	+1

INTIDR:	STKVAR <WFIFL,IDPKT,FLGKL>
	SETZRO <IDTRY,IDNOR>,(Q1) ;RESET SECOND TRY AND NO-ANSWER-COUNTER
	SETZM RIDTIM(Q1)	;TURN OFF REQUEST ID TIMER
	SETZM WFIFL		;INIT THE WFI FLAG
	SETZM FLGKL		;ASSUME REMOTE IS NOT A KL
	TXNN T1,PF.PT0		;ARRIVED ON PATH A?
	JRST INTIDB		;NO

;Path A

	CALL CHKVCO		;HAVE AN OPEN VC?
	 JRST INTID1		;NO, MOVE ON
	TMNE IDPAO,(Q1)		;YES, PATH A ALREADY OPEN?
	JRST INTID1		;YES, MOVE ON
	MOVEM Q2,IDPKT		;NO, PRESERVE INCOMING PACKET ADDR
	CALL KLPGDB		;(Q3/Q2) GET A BUFFER FOR THE SET-CIRCUIT
	 JRST INTID4		;BETTER LUCK NEXT TIME
	MOVX T3,CK.LPT!CK.PGD 	;TELL PORT TO
	MOVEM T3,.PKCKT(Q2)	; OPEN PATH A
	CALL KLPSCK		;(Q1,Q2,Q3)
	 NOP			;NO SUCH RETURN
	SETONE <IDPAO,IDPBO>,(Q1) ;BOTH PATHS ARE NOW OPEN
INTID4:	MOVE Q2,IDPKT		;RETRIEVE INCOMING PACKET ADDR
INTID1:	TMNN IDNRA,(Q1)		;WAS IT PREVIOUSLY N-R?
	JRST INTID2		;NO
	SETZRO IDNRA,(Q1)	;YES, NOT ANY MORE
	JRST INTID3		;ONWARD
;Path B

INTIDB:	CALL CHKVCO		;HAVE AN OPEN VC?
	 JRST INTID6		;NO, MOVE ON
	TMNE IDPBO,(Q1)		;PATH B ALREADY OPEN?
	JRST INTID6		;YES, MOVE ON
	MOVEM Q2,IDPKT		;NO, PRESERVE INCOMING PACKET ADDR
	CALL KLPGDB		;(Q3/Q2) GET A BUFFER FOR THE SET-CIRCUIT
	 JRST INTID5		;BETTER LUCK NEXT TIME
	MOVX T3,CK.LPT!CK.PGD 	;NO, TELL PORT TO
	MOVEM T3,.PKCKT(Q2)	; OPEN PATH B
	CALL KLPSCK		;(Q1,Q2,Q3)
	 NOP			;NO SUCH RETURN
	SETONE <IDPAO,IDPBO>,(Q1); BOTH PATHS ARE NOW OPEN
INTID5:	MOVE Q2,IDPKT		;RETRIEVE INCOMING PACKET ADDR
INTID6:	TMNN IDNRB,(Q1)		;WAS IT PREVIOUSLY N-R?
	JRST INTID2		;NO
	SETZRO IDNRB,(Q1)	;YES, NOT ANY MORE
INTID3:	CALL PHYSTC		;() TELL DISK SERVICE ABOUT STATUS CHANGE
	; ..
	; ..

;For an understanding of the following code, refer to the comments at OPENVC

INTID2:	MOVX T1,IDMAI		;GET MAINTENANCE STATE
	IORM T1,RIDSTS(Q1)	;ASSUME IT
	TMNN PKMAI,(Q2)		;IT IS REALLY?
	ANDCAM T1,RIDSTS(Q1)	;NO
	LOAD T1,PKTYP,(Q2)	;YES, GET NODE TYPE
	CAIN T1,ID.KL		;IS IT A KL?
	SETOM FLGKL		;YES
	SKIPN P5		;NO, HAVE A SB?
	IFSKP.

;We have heard from this node before

	   MOVE T1,.PKPST(Q2)	;YES. GET THE NODE'S STATE 
	   MOVEM T1,.SBDPS(P5)	;STORE IT IN THE SB
	   LOAD T1,SBVCST,(P5)	;GET VC STATE
	   SKIPN FLGKL		;IS IT A KL?
	   IFSKP.
	      TMNN PKMAI,(Q2)	;YES, IS KL'S PORT IN MAINTENANCE STATE?
	      ANSKP.

;KL node is in maintenance state

	         CAIN T1,VC.CLO	;YES, VC CLOSED?
	         CALLRET RETDG	;(Q2,Q3/) YES, DONE
	         SETZ P4,	;NO, NEED TO SO SET-CIRCUIT
	         CALLRET CLOSV1	;(Q2,P4,P5/) CLOSE VC
	   ENDIF.
	   CAIE T1,VC.CLO	;NO, VC CLOSED?
	   CALLRET RETDG	;(Q2,Q3) NO, GIVE BACK BUFFER AND RETURN
	   SETZRO SBWFI,(P5)	;YES, NO LONGER WAITING FOR AN IDREC
	   SETOM WFIFL		;SAY WE TURNED IT OFF
	   TMNE SBNTC,(P5)	;STILL NEED TO CLOSE?
	   CALLRET RETDG	;(Q2,Q3) YES, GIVE BACK BUFFER AND RETURN
	   TMNN SBOKO,(P5)	;IS IT OK TO OPEN THIS VC?
	   CALLRET RETDG	;(Q2,Q3) NO, GIVE BACK BUFFER AND RETURN
	ENDIF.
	SKIPE FLGKL		;IS IT A KL?
	IFSKP.
	   CALL STARMT		;NO, CHECK FOR A START REMOTE COMMAND
	   LDB T1,[POINT PKSPST,.PKPST(Q2),PKPPST] ;GET OTHER PORT'S STATE
	   CAIE T1,PS.ENB	;ENABLED?
	   CALLRET RETDG	;(Q2,Q3) NO, GIVE BACK BUFFER AND RETURN
	ENDIF.
	SKIPE P5		;IS THIS THE FIRST RESPONSE FROM THIS NODE?
	IFSKP.

;First time we've heard from this node

	   CALL BLDSBK		;(Q1,Q2,Q3,P1/P5) YES, BUILD A SB
	    IFNSK.
	       SKIPN WFIFL	;CAN'T NOW, DID WE TURN OFF SBWIF?
	       CALLRET RETDG	;NO, GIVE BACK BUFFER AND RETURN
	       SETONE SBWFI,(P5)  ;YES, TURN IT BACK ON SO ONCE-A-SECOND
	                          ; CODE MIGHT GET OUT A REQUEST-ID SOON
	       CALLRET RETDG	;(Q2,Q3) GIVE BACK BUFFER AND RETURN
	    ENDIF.
	   SKIPN FLGKL		;IS IT A KL?
	   IFSKP.
	      TMNE PKMAI,(Q2)	;YES, IS KL'S PORT IN MAINTENANCE STATE?
	      CALLRET RETDG	;(Q2,Q3/) YES, WE'RE DONE
	   ENDIF.
	ENDIF.
	CALLRET SNDSTA		;(Q1,Q2,Q3,P5) SEND A START

	ENDSV.
;ROUTINE TO BUILD A SYSTEM BLOCK

;ACCEPTS:
;	Q1/NODE NUMBER
;	Q2/ Address of packet containing answer to REQID
;	Q3/PCB ADDRESS
;	P1/CDB ADDRESS

;	CALL BLDSBK

;RETURNS +1: FAILURE
;	 +2: SUCCESS,
;		P5/ADDRESS OF SYSTEM BLOCK

BLDSBK:	MOVEI	T1,.SBLEN	;GET CORE FOR SYSTEM BLOCK (KDB)
	CALL	PHYALC		;RESERVE SPACE
	 RET			;RETURN IF NO SPACE FOUND
	MOVEM	T1,P5		;SAVE ADDRESS IN PROPER AC
	MOVE	T1,P1
	ADD	T1,Q1		;POINT T1 AT RIGHT UNIT (KDB) SLOT IN CDB
	MOVEM	P5,CDBUDB(T1)	;SAVE ADDR OF KDB
	MOVEI	T1,.BTKDB	;MARK AS KDB
	DPB	T1,[POINT XSSTYP,UDBSTS(P5),XSPTYP]
	MOVX	T1,.UTNOD	;GET DEFAULT UNIT TYPE
	STOR	T1,USTYP,(P5)	;PUT IT IN KDB
	MOVEI	T1,KLDSP	;GET DEFAULT CONTROLLER/UNIT DISPATCH VECTOR
	MOVEM	T1,KDBDSP(P5)	;PUT IT IN KDB
	MOVSI	T1,-PRTMXU	;SET UP AOBJN INDEX LH
	HRRI	T1,KDBUDB(P5)	;MAKE RH POINT TO UDB ENTRIES IN KDB
	MOVEM	T1,KDBIUN(P5)	;INITIAL POINTER
	MOVEM	T1,KDBCUN(P5)	;CURRENT POINTER
	HRLI	P5,MSEC1	;[7.1037]STORE ADDRESS AS SECTION 1 FOR SCAMPI
	MOVEM	P5,SBLIST(Q1)	;SAVE SYS BLOCK ADDR IN TABLE INDEXED BY NODE
	MOVEI	T2,CDBSBS-.SBANB(P1) ;START AT PCB
BLDSB1:	SKIPN	T3,.SBANB(T2)	;NEXT SYSTEM BLOCK EXIST?
	JRST	BLDSB2		;NO
	MOVE	T2,T3		;YES. FOLLOW CHAIN
	JRST	BLDSB1
;.....
BLDSB2:	MOVEM	P5,.SBANB(T2)	;POINT PREDECESSOR AT THIS SYSTEM BLOCK
	SETZM	.SBANB(P5)	;NO NEXT SYSTEM BLOCK
	MOVEM	P1,.SBACD(P5)	;SAVE CDB ADDRESS IN SB
	MOVEI	T1,.SBFCB(P5)	;POINTER TO LAST CONNECTION BLOCK
	MOVEM	T1,.SBLCB(P5)	;IN BLINK OF SB
	SETZM	.SBFCB(P5)	;CLEAR FLINK OF CBS IN SB
	MOVEI	T1,.SBQOR-QORLNK(P5) ;POINT QOR WORD AT ITSELF
	HRLS	T1		; (EMPTY LIST)
	MOVEM	T1,.SBQOR(P5)	;NO OUTSTANDING REQUESTS
	HRLI	T1,KLPRH2	;GET CHANNEL NUMBER
	HRR	T1,Q1		;AND NODE NUMBER
	MOVEM	T1,.SBDSP(P5)	;SAVE CHANNEL,,PORT NUMBER
	MOVEM	Q3,.SBAPB(P5)	;POINT SYSTEM BLOCK AT PCB
	MOVEI	T1,.PBDFI(Q3)	;DATAGRAM FREE-QUEUE LOC
	MOVEM	T1,.SBDRQ(P5)	;SAVE 
	MOVE	T1,.PKMID(Q2)	;TYPE OF NODE
	MOVEM	T1,.SBDPC(P5)	;SAVE IT IN SYSTEM BLOCK
	MOVE	T1,.PKCOD(Q2)	;GET PORT CODE REVISION
	MOVEM	T1,.SBDCR(P5)	;SAVE IN SYSTEM BLOCK
	MOVE	T1,.PKFUN(Q2)	;PORT FUNCTIONALITY
	MOVEM	T1,.SBDPF(P5)	;SAVE IN SYSTEM BLOCK
	MOVE	T1,.PKPST(Q2)	;GET PORT STATE
	MOVEM	T1,.SBDPS(P5)	;SAVE IN SYSTEM BLOCK
	XMOVEI	T3,.SBTWQ(P5)	;GET ADDR OF WORK QUEUE FLINK
	MOVEM	T3,.SBBWQ(P5)	;INIT BLINK AS FLINK
	SETZM	.SBTWQ(P5)	;INIT FLINK AS ZERO
	SETZM	.SBLMB(P5)	;ZERO THE SCA MESSAGE FLOW CONTROL WORD
	RETSKP
;ROUTINE TO CHECK IF A START REMOTE COMMAND HAS BEEN REQUESTED FOR A 
;REMOTE NODE. IF THIS NODE WANTS TO START A REMOTE NODE, BUT IT WAS
;NOT THE LAST NODE TO RESET THE REMOTE NODE, THEN THE START REMOTE
;COMMAND WILL NOT BE ISSUED AND DATA IN RIDSTS FOR THE START REMOTE
;WILL BE CLEARED. IN THIS CASE, THE COMMAND IS NOT ISSUED BECAUSE THE
;REMOTE NODE WOULD NOT USE IT.

STARMT:	SAVEQ
	TMNN IDSTA,(Q1)			;START REMOTE COMMAND WANTED?
	IFSKP.
	  LOAD T1,PKPRST,(Q2)		;YES. GET REMOTES NODE'S STATE
	  CAIE T1,PS.UMS		;IS IT UNINITIALIZED MAINTENANCE?
	  IFSKP.
	    MOVE T1,CHNTAB+KLPRH2	;YES. GET CDB ADDRESS
	    MOVE T1,CDBNOD(T1)		;GET OUR NODE NUMBER
	    LOAD T2,PKPRND,(Q2)		;GET THE RESETING NODE
	    CAMN T1,T2			;DID THIS NODE DO THE LAST RESET?
	    IFSKP.
	      BUG. (INF,KLPSRM,PHYKLP,SOFT,<PHYKLP - Cannot start remote node>,<<T1,HOST NODE>,<T2,RESET NODE>,<Q1,REMOTE NODE>>,<


Cause:	This node wanted to start a remote HSC node, but it is not the node
	that did the last RESET REMOTE on the remote HSC.

Action: Do nothing. This can happen with multiple KLs for an HSC.

Data:	HOST NODE - The node number of this system
	RESET NODE - The node number that last reset the remote node
	REMOTE NODE - The remote's node number.
>,,<DB%NND>)			;[7.1210] 
	    ELSE.
	      CALL PPDGDB		;YES. DO THE START REMOTE. GET BUFFER.
	      IFSKP.
		LOAD Q3,IDSAD,(Q1)	;HAVE BUFFER. NOW,GET STARTING ADDRESS.
		HRL Q3,Q3		;PUT IT IN LEFT HALF.
		HRLI Q1,KLPRH2		;SET CHANNEL NUMBER
		HRRI Q3,777777		;SET TO -1 FOR PPDSRS
		CALL PPDSRS		;ISSUE THE START REMOTE COMMAND
	      ENDIF.
	    ENDIF.
	  HRRZ Q1,Q1			;GET JUST THE NODE NUMBER
	  SETZRO <IDSTA,IDRST,IDSAD>,(Q1) ;CLEAR START REQUESTED,
					 ; RESET SENT, AND
					 ; THE START ADDRESS
	  ENDIF.
	ENDIF.
	RET
;SEND A START
;ACCEPTS:	Q1/ NODE NUMBER
;		Q2/ PACKET ADDRESS
;		Q3/ PCB
;		P5/ SB
;RETURNS:	+1

SNDSTA:	MOVEI T1,VC.STS		;GET START-SENT CODE
	STOR T1,SBVCST,(P5)	;SET INITIAL VC STATE
	MOVEI T1,PP.STA		;GET START CODE
	CALL STRTDT		;MAKE A START PACKET
	CALL KLPSDG		;SEND IT
	 NOP			;NO SUCH RETURN
	CALL STSST		;SET THE TIMER
	RET
;Received a REQUEST DATA ON QUEUE 0 (we never use queue 0)
;Received a REQUEST DATA ON QUEUE 1 (we always use queue 1)
;Received a REQUEST DATA ON QUEUE 2 (we never use queue 2)
;Received a SEND-DATA (we never set the response bit)
;RETURNS: +1

INTRD0:
INTRD1:
INTRD2:
INTSDT:	SKIPN P3		;LOCALLY-GENERATED?
	IFSKP.

;Locally-generated

	   MOVE T1,Q2		;YES, POSITION THE BUFFER ADDRESS
	   CALLRET SC.RBF	;(T1) GIVE BUFFER BACK TO SCA POOL
	ENDIF.

;Remotely-generated packet

	LDB T1,PKYSTS		;NO, ILLEGAL.  GET PACKET STATUS FIELD
	LDB T2,PKYFLG		;GET PACKET FLAGS FIELD
	BUG. (CHK,KLPIRD,PHYKLP,SOFT,<PHYKLP - Invalid remotely-generated data request>,<<T1,STATS>,<T2,FLAGS>,<P2,OPC>,<Q1,NODE>>,<

Cause:	The CI20 driver received an error-free, remotely-generated packet with
	opcode 10, 11, 12, or 20.  This is illegal.

Data:	STATS - Status field of packet
	FLAGS - Flags field of packet
	OPC   - op code field of packet
	NODE  - node number
>,,<DB%NND>)			;[7.1210] 

;Port got the buffer from the MFQ

	CALLRET RETMSG		;(Q2,Q3) RETURN BUFFER TO MSG FREE QUEUE
;Received one of the following with an error:
;DATA CONFIRM or RETURN DATA
;REQUEST DATA ON QUEUE 0 (we never use queue 0)
;REQUEST DATA ON QUEUE 1 (we always use queue 1)
;REQUEST DATA ON QUEUE 2 (we never use queue 2)
;SEND-DATA (we never set the response bit)
;RETURNS: +1

NBFERR:
RD0ERR:
RD1ERR:
RD2ERR:
SDTERR:	CALL SCAERR		;(Q1,Q2,Q3,P5) TELL SCA
	SKIPN P3		;LOCALLY-GENERATED?
	CALLRET RETMSG		;(Q2,Q3) NO, RETURN BUFFER TO FREE QUEUE
	MOVE T1,Q2		;YES, POSITION THE BUFFER ADDRESS
	CALLRET SC.RBF		;(T1) RETURN BUFFER TO SCA POOL
;Received a LOOP-BACK
;ACCEPTS:	T1/ PACKET STATUS WORD
;		Q2/ PACKET ADDRESS
;		Q3/ PCB
;		P1/ CDB
;		P2/ OPCODE
;RETURNS:	+1

INTLPB:	TXNN T1,PF.PT0		;WIRE A?
	IFSKP.
	   SKIPN CIWIRA		;YES, WIRE A ALREADY GOOD?
	   IFSKP.
	      BUG. (INF,KLPWAG,PHYKLP,HARD,<PHYKLP - CI wire A has gone from bad to good>,,<

Cause:	A loopback packet which previously failed has successfully returned 
	on wire A.
>,,<DB%NND>)			;[7.1210] 
	      SETZM CIWIRA	;WIRE A NOW GOOD
	      MOVEI T2,KS%ABG	;GET READ-COUNTERS REASON CODE
	      CALL PPDRPT	;(T2,Q2) DO A READ-COUNTERS
	      CALL WIRBAD	;[7210] (Q3,P1) CHECK FOR EXCESSIVE TRANSITIONS
	       RET		;[7210] YES, PORT BEING RELOADED
	      CALL PHYSTC	;ALERT THE DISK SERVICE
	     JRST INTLP2	;GO OPEN THE CIRCUIT
	   ENDIF.
	ELSE.
	   SKIPN CIWIRB		;WIRE B ALREADY GOOD?
	   IFSKP.
	      BUG. (INF,KLPWBG,PHYKLP,HARD,<PHYKLP - CI wire B has gone from bad to good>,,<

Cause:	A loopback packet which previously failed has successfully returned 
	on wire B.
>,,<DB%NND>)			;[7.1210] 
	      MOVEI T2,KS%BBG	;GET READ-COUNTERS REASON CODE
	      CALL PPDRPT	;(T2,Q2) DO A READ-COUNTERS
	      SETZM CIWIRB	;WIRE B NOW GOOD
	      CALL WIRBAD	;[7210] (Q3,P1) CHECK FOR EXCESSIVE TRANSITIONS
	       RET		;[7210] YES, PORT BEING RELOADED
	      CALL PHYSTC	;ALERT THE DISK SERVICE
	      JRST INTLP2
	   ENDIF.
	ENDIF.
	CALLRET RETDG		;(Q2,Q3) RETURN THE BUFFER
;For each node to which we have an open v.c., tell the port that both paths
;are good. It will try them on free choice, and tell us if one is still bad.

INTLP2:	SETZM Q1		;Start with node zero
INTLP4:	SKIPN T2,SBLIST(Q1)	;Is there a system block
	JRST INTLP7		;No.
	LOAD T3,SBVCST,(T2)	;Yes. is v.c. open?
	CAIE T3,VC.OPN
	JRST INTLP7		;No.
	CALL KLPGDB		;GET BUFFER FOR SET CIRCUIT
	 JRST INTLP9
	MOVX T1,CK.LPT!CK.PGD	;INDICATE OPENING BOTH PATHS

	MOVEM T1,.PKCKT(Q2)	;PUT THAT IN THE PACKET
	CALL KLPSCK		;SEND A SET CIRCUIT
	 NOP
	SETONE <IDPAO,IDPBO>,(Q1) ;MARK BOTH PATHS AS OPEN FOR NOW
INTLP7:	CAIGE Q1,C%SBLL-1	;Step to next node
	AOJA Q1,INTLP4

;If we didn't get a buffer, the next REQID will take care of things.

INTLP9:	RET
;Received a LOOP-BACK with an error
;ACCEPTS:	T1/ PACKET STATUS WORD
;		Q2/ PACKET
;		Q3/ PCB
;		P1/ CDB
;		P2/ OPCODE
;RETURNS:	+1

LPBERR:	LDB T2,PKYSTS		;GET STATUS FIELD
	LDB T3,PKYFLG		;GET FLAGS FIELD
	MOVE T4,CDBCNI(P1)	;GET CSR
	TXNE T1,PS.PAE!PS.PBE	;PATH ERROR?
	JRST LPBER1		;YES, PATH ERROR

;It was a non-path error

	BUG. (CHK,KLPLBF,PHYKLP,HARD,<PHYKLP - Loopback failed>,<<T2,STATS>,<T3,FLAGS>,<P2,OPC>,<T4,CSR>>,<

Cause:	The CI20 driver has tried to send a loopback packet to the STAR
	coupler and it had a non-path error.

Data:	STATS - Status field of packet
	FLAGS - Flags field of packet
	OPC   - op code field of packet
	CSR   - result of the last CONI
>,,<DB%NND>)			;[7.1210] 
	CALLRET RETDG		;(Q2,Q3) DONE
;It was a path error

LPBER1:	TXNN T1,PS.PAE		;YES, PATH A ERROR?
	IFSKP.
	   SKIPE CIWIRA		;YES, WIRE A ALREADY BAD?
	   IFSKP.
	      BUG. (INF,KLPWAB,PHYKLP,HARD,<PHYKLP - CI wire A has gone from good to bad>,<<T2,STATS>,<T3,FLAGS>,<P2,OPC>,<T4,CSR>>,<

Cause:	A loopback packet which previously succeeded has failed on wire A.

Data:	STATS - Status field of packet
	FLAGS - Flags field of packet
	OPC   - op code field of packet
	CSR   - result of the last CONI
>,,<DB%NND>)			;[7.1210] 
	      SETOM CIWIRA	;WIRE A NOW BAD
	      MOVEI T2,KS%AGB	;GET READ-COUNTERS REASON CODE
	      CALL PPDRPT	;(T2,Q2) DO A READ-COUNTERS
	      CALL WIRBAD	;[7210] (Q3,P1) CHECK FOR EXCESSIVE TRANSITIONS
	       RET		;[7210] YES, PORT BEING RELOADED
	      CALLRET PHYSTC	;ALERT THE DISK SERVICE
	   ENDIF.
	ELSE.
	   SKIPE CIWIRB		;WIRE B ALREADY BAD?
	   IFSKP.
	      BUG. (INF,KLPWBB,PHYKLP,HARD,<PHYKLP - CI wire B has gone from good to bad>,<<T2,STATS>,<T3,FLAGS>,<P2,OPC>,<T4,CSR>>,<

Cause:	A loopback packet which previously succeeded has failed on wire B.

Data:	STATS - Status field of packet
	FLAGS - Flags field of packet
	OPC   - op code field of packet
	CSR   - result of the last CONI
>,,<DB%NND>)			;[7.1210] 
	      SETOM CIWIRB	;WIRE B NOW BAD
	      MOVEI T2,KS%BGB	;GET READ-COUNTERS REASON CODE
	      CALL PPDRPT	;(T2,Q2) DO A READ-COUNTERS
	      CALL WIRBAD	;[7210] (Q3,P1) CHECK FOR EXCESSIVE TRANSITIONS
	       RET		;[7210] YES, PORT BEING RELOADED
	      CALLRET PHYSTC	;ALERT THE DISK SERVICE
	   ENDIF.
	ENDIF.
	CALLRET RETDG		;(Q2,Q3) DONE
;WIRBAD -  RESTARTS CI20 IF WE'VE HAD EXCESSIVE WIRE TRANSITIONS.  THE MOST
;LIKELY CAUSE OF THIS IS A KNOWN PROBLEM IN THE CI LINK BOARD WHICH WILL
;SOMEDAY BE FIXED BY AN ECO
; Q3/ PCB
; P1/ CDB
;	CALL WIRBAD		;()
; RETURN +1: PORT RELOADED
;        +2: ALL IS WELL

WIRBAD:	AOS T1,WIRCNT		;BUMP COUNT
	CAIE T1,1		;IS THIS THE FIRST TIME?
	IFSKP.
	  MOVE T1,TODCLK	;YES, GET CURRENT TIME
	  ADDI T1,^D20000	;ADD TOLERANCE
	  MOVEM T1,WIRTIM	;SAVE DROP DEAD TIME
	  RETSKP		;DONE
	ENDIF.
	CAIGE T1,2		;[7237] HAD ENOUGH?
	RETSKP			;NO
	SETZM WIRCNT		;YES, START OVER
	MOVE T1,WIRTIM		;GET DROP DEAD TIME
	SETZM WIRTIM		;RESET IT
	CAMGE T1,TODCLK		;WITHIN LIMIT?
	RETSKP			;YES, DONE
	BUG. (INF,KLPWIR,PHYKLP,HARD,<PHYKLP - Excessive CI wire transitions>,,<

Cause:	CI loopback packets are alternately succeeding and failing at a rapid
	rate.  The most likely cause of this is a known problem in the CI link
	module.
>,,<DB%NND>)			;[7.1210] 
	CALL URDEAD		;(Q3,P1) NO, RESTART CI
	RET
;Received a SET-CIRCUIT
;ACCEPTS:	Q2/ PACKET ADDRESS
;		Q3/ PCB
;		P2/ OP CODE
;RETURNS:	+1

INTCKT:	LDB T1,PKYSTS		;GET STATUS FIELD
	LDB T2,PKYFLG		;GET FLAGS FIELD
	BUG. (CHK,KLPSCR,PHYKLP,HARD,<PHYKLP - SET-CIRCUIT command received>,<<T1,STATUS>,<T2,FLAGS>,<P2,OPC>>,<

Cause:	TOPS-20 has found an error free SET-CIRCUIT command on the response
	queue. The CI port has done something wrong because the response bit is
	never set so this packet should not be seen.

Data:	STATUS - status field of packet
	FLAGS  - flags field of packet
	OPC    - op code field of packet
>,,<DB%NND>)			;[7.1210] 
	CALLRET	RETDG		;(Q2,Q3) RETURN BUFFER


;Received a SET-CIRCUIT with an error
;ACCEPTS:	Q2/ PACKET ADDRESS
;		Q3/ PCB
;		P2/ OP CODE
;RETURNS:	+1

CKTERR:	LDB T1,PKYSTS		;GET STATUS FIELD
	LDB T2,PKYFLG		;GET FLAGS FIELD
	BUG. (CHK,KLPCKE,PHYKLP,HARD,<PHYKLP - SET-CIRCUIT command error>,<<T1,STATUS>,<T2,FLAGS>,<P2,OPC>>,<

Cause:	A SET-CIRCUIT command has failed.  TOPS-20 doesn't retry such commands
	because it believes the CI port always executes them properly.
	The port is probably in trouble.

Data:	STATUS - status field of packet
	FLAGS  - flags field of packet
	OPC    - op code field of packet
>,,<DB%NND>)			;[7.1210] 
	CALLRET	RETDG		;(Q2,Q3) RETURN BUFFER
;Received a READ-STATISTICS-COUNTERS
;ACCEPTS:	T1/ PACKET STATUS FIELD
;		Q2/ PACKET
;		Q3/ PCB
;		P1/ CDB
;RETURNS:	+1

INTRCT:	TXNN T1,PF.CPE		;PORT GENERATE IT AFTER CRAM PARITY ERROR?
	IFSKP.
	  MOVEI T1,KS%CRP	;[7255] YES, GET REASON CODE
	  MOVEM T1,.PKXID(Q2)	;[7255] SET REASON FOR DOING READ-COUNTERS
	  CALLRET SPR241	;[7255] (Q2,Q3) MAKE SPEAR ENTRY
	ENDIF.

;TOPS-20 did a READ-COUNTERS

	MOVE Q1,.PKXID(Q2)	;GET REASON WE DID IT
	SUBI Q1,2		;0 AND 1 DON'T COUNT (0 IS ILLEGAL, 1 IS CPE)
	SKIPL Q1
	CAILE Q1,BIG241
	JRST [	BUG. (INF,KLPBRC,PHYKLP,HARD,<Bad READ-COUNTERS>,,<

Cause:	TOPS-20 has removed a READ-COUNTERS packet from response queue and the
	reason code field contains an illegal value.
>)
		CALLRET RETDG]	;(Q2,Q3) RETURN THE PACKET TO THE FREE QUEUE
	CALLRET @DSP241(Q1)	;GO PROCESS THE PACKET

DSP241:	IFIW!SPR241		;PATH A WENT FROM GOOD TO BAD
	IFIW!SPR241		;                 BAD TO GOOD
	IFIW!SPR241		;PATH B WENT FROM GOOD TO BAD
	IFIW!SPR241		;                 BAD TO GOOD
	IFIW!SPR241		;PERIODIC COLLECTION
	IFIW!RCTUCD		;GET UCODE VERSION
	IFIW!RCTDIA		;DIAG% DID IT
BIG241=.-<DSP241-1>
;READ-COUNTERS WAS DONE TO GET UCODE VERSION
;ACCEPTS:	Q1/ REASON
;		Q2/ PACKET
;		Q3/ PCB
;		P1/ CDB
;RETURNS:	+1

RCTUCD:	MOVE T2,.PKUCD(Q2)	;[7.1134] Get ucode version
	LOAD T1,CDVER,(P1)	;[7.1134] Get the version we loaded
	CAME T1,T2		;[7.1134] Was it what we expected?
	BUG. (CHK,KLPMVW,PHYKLP,SOFT,<CI20 microcode version wrong>,<<T1,MVER>,<T2,UVER>>,<

Cause:	The CI20 has returned a microcode version that is different than the
	version the monitor thought it loaded.  

Action:	There is probably a problem with BS:<SYSTEM>IPALOD.EXE.  Find a correct
	IPALOD, put it in BS:<SYSTEM>, and reload the system.

Data:	MVER - version loaded by monitor
	UVER - version returned by microcode
>,,<DB%NND>)			;[7.1210] 
	CALLRET SPR241		;(Q2,Q3) MAKE ERROR.SYS ENTRY
;READ-COUNTERS HAS ARRIVED FOR DIAG%
;ACCEPTS:	Q2/ PACKET
;		Q3/ PCB
;RETURNS:	+1

RCTDIA:	MOVE T1,TODCLK		;GET THE TIME OF THE READ.
	MOVEM T1,CNTBUF		;STORE IT.
	MOVEI T1,.PKPDD		;SET UP FOR BLT.
	XMOVEI T2,.PKPDA(Q2)
	MOVEI T3,CNTBUF+1
	EXTEND T1,[XBLT]	;BLT DATA FROM THE PACKET TO CNTBUF.
	AOS CNTFLG		;SET THE READ DONE FLAG.
	CALLRET RETDG		;(Q2,Q3) RELEASE THE PACKET BUFFER AND RETURN


;MAKE AN ERROR.SYS ENTRY FOR "KLIPA STATISTICS EVENT" - EVENT CODE 241
;ACCEPTS:	Q2/ PACKET ADDRESS
;		Q3/ PCB
;RETURNS:	+1

SPR241:	STKVAR <EBLOK>
	MOVEI T1,KS%LEN		;YES, TOTAL BLOCK LENGTH
	MOVEI T2,KS%SIZ		;NON STRING DATA SIZE
	CALL ALCSEB		;(T1,T2/T1) TRY TO GET ERROR BLOCK
	 JRST SPR24A		;NONE AVAILABLE.
	MOVEM T1,EBLOK		;SAVE LOC OF ERROR BLOCK
	MOVE T2,.PKXID(Q2)	;GET REASON FOR DOING READ-COUNTERS
	STOR T2,KSRSN		;STASH IT
	MOVEI T2,KLPRH2		;GET KLIPA CHANNEL
	STOR T2,KSCHN		;STASH IT
	MOVE T2,.PKUCD(Q2)	;GET UCODE VERSION
	STOR T2,KSVSN		;STASH IT
	MOVE T2,[-NKSTAB,,KSTAB] ;FILL IN THE DATA
	MOVE P3,Q2		;CAN'T USE Q2 FOR SEBCPY AND DON'T NEED P3 NOW
	CALL SEBCPY		;(T1,T2)
	 JFCL
	MOVE T1,EBLOK		;RETRIEVE ERROR BLOCK
	CALL QUESEB		;(T1) HAND IT TO SPEAR
SPR24A:	CALLRET RETDG		;(Q2,Q3) RETURN TO DG FREE Q

	ENDSV.
;FORMAT DEFINITION OF KLIPA STATISTICS EVENT (ERROR.SYS ENTRY 241)
;
;NOTE: P3 (not Q2) contains the packet address because the routine SEBCPY
;      uses the Qs.

KSTAB:	SEBPTR 0,SBTEVC,SEC%KS		;BLOCK TYPE
	SEBPTR KS%OFF,SBTWD,KSOFF	;OFFSET TO STATISTICS DATA
	SEBPTR KS%VER,SBTWD,VER241	;VERSION WORD
	SEBPTR KS%AAK,SBTWD,.PKPAA(P3)	;PATH A ACKS
	SEBPTR KS%ANK,SBTWD,.PKPAN(P3)	;PATH A NACKS
	SEBPTR KS%ANR,SBTWD,.PKANR(P3)	;PATH A NO-RESPONSES
	SEBPTR KS%BAK,SBTWD,.PKPBA(P3)	;PATH B ACKS
	SEBPTR KS%BNK,SBTWD,.PKPBN(P3)	;PATH B NACKS
	SEBPTR KS%BNR,SBTWD,.PKBNR(P3)	;PATH B NO-RESPONSES
	SEBPTR KS%DGD,SBTWD,.PKDGD(P3)	;DATAGRAMS DISCARDED
	SEBPTR KS%PXM,SBTWD,.PKPXM(P3)	;PACKETS TRANSMITTED
	SEBPTR KS%PRC,SBTWD,.PKPRC(P3)	;PACKETS RECEIVED
	SEBPTR KS%DPT,SBTWD,.PKDPT(P3)	;DESIGNATED PORT
	SEBPTR KS%CRC,SBTWD,.PKCRC(P3)	;PACKETS WITH CRC ERRORS
	SEBPTR KS%EW1,SBTWD,.PKEW1(P3)	;ERROR WORD 1
	SEBPTR KS%EW2,SBTWD,.PKEW2(P3)	;ERROR WORD 2
	SEBPTR KS%EW3,SBTWD,.PKEW3(P3)	;ERROR WORD 3
	SEBPTR KS%EW4,SBTWD,.PKEW4(P3)	;ERROR WORD 4
	SEBPTR KS%EW5,SBTWD,.PKEW5(P3)	;ERROR WORD 5
	SEBPTR KS%EW6,SBTWD,.PKEW6(P3)	;ERROR WORD 6
NKSTAB==.-KSTAB



;Received a READ-STATISTICS-COUNTERS with an error
;ACEPTS:	Q2/ PACKET
;		Q3/ PCB
;RETURNS:	+1

RCTERR:	BUG. (CHK,KLPRCE,PHYKLP,HARD,<PHYKLP - READ-COUNTERS command failed>,,<

Cause: There is a problem with the CI20 port, the read-counters command failed.
>,,<DB%NND>)			;[7.1210] 
	CALLRET RETDG		;(Q2,Q3) RETURN PACKET TO FREE QUEUE
;Received a READ-REGISTER (we only do READ-NODE-ADDRESS)
;ACCEPTS:	Q2/ PACKET
;		Q3/ PCB
;		P1/ CBD
;RETURNS:	+1

INTRRG:	LDB T1,PKYDTA		;NO, GET OUR NODE NUMBER
	MOVEM T1,CDBNOD(P1)	;PUT IT IN CDB
	CALLRET RETDG		;(Q2,Q3) RETURN THE BUFFER


;Received a READ-REGISTER with an error
;ACCEPTS:	Q2/ PACKET
;		Q3/ PCB
;RETURNS:	+1

RRGERR:	BUG. (CHK,KLPCRR,PHYKLP,HARD,<PHYKLP - READ-REGISTER command failed>,,<

Cause:	There is a problem with the CI20 port, a read-register command failed.
>,,<DB%NND>)			;[7.1210] 
	CALLRET RETDG		;(Q2,Q3) RETURN THE BUFFER
;INTMCR - RECEIVED A MAINTENANCE CONFIRM (MCNF)
;	CALL @KLPROU(T1)
;RETURN: +1 ALWAYS

;INTMDR - RECEIVED A MAINTENANCE DATA RECEIVED (MDATREC)
;	CALL @KLPROU(T1)
;RETURN: +1 ALWAYS

INTMDR:
INTMCR:	CALL CHKMAI		;ARE WE EXPECTING THIS?
	 CALLRET RETDG		;(Q2,Q3) NO, RETURN PACKET TO FREE QUEUE
	SETZM MAIFLG		;YES, THERE IS NO ERROR.
	CALLRET RETDG		;(Q2,Q3) RETURN PACKET TO FREE QUEUE



;Received a MAINTENANCE-CONFIRM or MAINTENANCE-DATA-RECEIVED with an error
;ACCEPTS:	Q2/ PACKET
;		Q3/ PCB
;RETURNS:	+1

MDRERR:
MCRERR:	CALL CHKMAI		;WERE WE EXPECTING THIS?
	 CALLRET RETDG		;(Q2,Q3) NO, RETURN PACKET TO FREE QUEUE
	BUG. (INF,KLPMCE,PHYKLP,HARD,<Received an MCNF or an MDATREC with an error>,<<T1,NODE>,<T2,STATUS>>,<

Cause:	Check the error code.

Data:	NODE - The node number of the CI node. 
	STATUS - The status word of the packet.
>,,<DB%NND>)			;[7.1210] 
	MOVEI T1,1		;GET ERROR INDICATOR
	MOVEM T1,MAIFLG		;SET THE ERROR FLAG (GT 0 MEANS ERROR)
	CALLRET RETDG		;(Q2,Q3) RETURN PACKET TO FREE QUEUE
;CHECK FOR MCNF EXPECTED
;RETURNS:	+1 NO
;		+2 YES

CHKMAI:	LDB T1,[POINT PKSNOD,.PKSTS(Q2),PKPNOD]	;GET NODE NUMBER
	SKIPE MAITIM		;IS AN MCNF EXPECTED?
	RETSKP			;YES
	BUG. (CHK,KLPMCR,PHYKLP,HARD,<Received an MCNF or an MDATREC from KLIPA when not expecting it>,<<T1,NODE>>,<

Cause:	Either the Maintenance function timed out, or the KLIPA gave us a 
	spurious one.

Data:	NODE - Node number of CI node that sent the MCNF or MDATREC.
>,,<DB%NND>)			;[7.1210] 
	RET
;INTCLO - RECEIVED A CLOSE BUFFER FINISHED INTERRUPT. IF THERE IS NO
;ERROR , THEN THE OPERATION WAS SUCCESSFUL. AN ERROR, WHERE THE
;BUFFER NAME WAS NOT FOUND ALSO IMPLIES SUCCESS; IF THERE IS
;NO BUFFER BY THE NAME IN THE KLIPA'S QUEUES, THEN THE WRITE WILL NOT 
;HAPPEN.
;	CALL @KLPROU(T1)
;ACCEPTS:	Q2/ PACKET
;		Q3/ PCB
;RETURN: +1 ALWAYS

INTCLO:	SKIPN MAICLN		;IS THE DIAG% WAITING FOR THIS.
	IFSKP.
	  MOVE T1,.PKBNM(Q2)	;YES. GET THE BUFFER NAME.
	  CAMN T1,MAICLN	;IS THIS THE DIAG% ONE.
	  AOS MAICLF		;YES. SET THE FLAG.
	ENDIF.
	CALLRET RETDG		;(Q2,Q3) RETURN PACKET TO FREE QUEUE


;Received a CLOSE-BUFFER with an error
;ACCEPTS:	Q2/ PACKET
;		Q3/ PCB
;RETURNS:	+1

CLOERR:	LOAD T2,.PKSFD,(Q2)	;GET STATUS FIELD LESS ERROR BIT
	CAIE T2,PS.IBN		;IS IT INVALID BUFFER NAME ERROR?
				;NO. OUTPUT BUGINF.
	BUG. (INF,KLPCLB,PHYKLP,HARD,<Close buffer function failed>,<<T1,STATUS>>,<

Cause:	Look at the status word to find out.

Data:	STATUS - Status word
>)
	JRST INTCLO		;MOVE ON
	SUBTTL PHYSIO Interface -- Channel Command Word, Hung, Reset

;CREATE A CHANNEL XFER WORD FOR THE PORT
;HERE THROUGH KLPDSP (THE CDSCCW OFFSET)
;ACCEPTS:	T1/ MODE,,+COUNT(1B0 IF BACKWARDS)
;		T2/ PHYSICAL ADDRESS
;RETURNS:	+1  T1/ CCW FOR THIS TRANSFER
;
;NOTE: THE MAXIMUM TRANSFER WHICH WILL ALWAYS WORK IS 1 PAGE.
;THE CALLER IS EXPECTED TO WORRY ABOUT PAGE CROSSING PROBLEMS.
;WE COMPUTE RH20-LIKE CCWS SINCE THEY WILL FIT IN 1 WORD. WE GENERATE
;BHD/BSD SETS WHEN ABOUT TO START IO.

KLPCCW:	STKVAR <KCW1>
	MOVEM T1,KCW1		;SAVE ARGUMENT
	HRRZ T3,T1		;GET WORD COUNT
	HLRZS T1		;GET MODE IN CORRECT PLACE
	TRZ T1,(1B0)		;CLEAR BACKWARDS BIT FROM MODE
	CAIN T1,IRMWRD		;SPECIAL CASE CHECK FOR COMMON CASE
	JRST KLPCW1		;IS WORD MODE, DO IT FAST
	IDIV T3,MODTAB(T1)	;CONVERT TO WORDS
	SKIPE T4		;ROUND?
	AOS T3			;YES
KLPCW1:	MOVE T4,KCW1		;GET ARGUMENT BACK
	MOVE T1,T2		;ADDRESS
	STOR T3,CHCNT,T1	;STORE COUNT IN T1
	RET			;RETURN


;CHANNEL HUNG
;HERE THROUGH KLPDSP (THE CDSHNG OFFSET)
;RETURNS:	+1

KLPHUN:	HRRZ P2,UDBKDB(P3)	;GET ADDRESS OF KDB
	LOAD T1,USTYP,(P2)	;GET CONTROLLER TYPE
	CAIE T1,.UTHSC		;AN HSC?
	CALL DSPBUG		;NO
	MOVEI T1,MSCDSP		;YES, GET MSCP CONTROLLER DISPATCH VECTOR
	CALLRET UDSHNG(T1)	;GO DO THE WORK


;RESTART THE CI
;HERE THROUGH KLPDSP (THE CDSRST OFFSET)
; P1/ CDB
;	CALL KLPZAP		;(P1/)
; RETURN +1

KLPZAP::SAVEPQ			;[7121]
	MOVE Q3,CDBPCB(P1)	;[7121] GET PCB
	CALL URDEAD		;[7121] (Q3,P1) START OVER
	RET
	SUBTTL PHYSIO Interface -- KLPCHK (Once-a-second Check)

;HERE FROM PHYCHK THROUGH KLPDSP (THE CDSCHK OFFSET)
;ACCEPTS:	P1/ CDB
;RETURNS:	+1

KLPCHK:	SAVEPQ
	EA.ENT			;WE NEED TO BE IN SECTION 1
	LOAD T1,CFSTA,(P1)	;GET PORT STATE
	CALLRET @CHKSTA(T1)	;TAKE APPROPRIATE ACTION

;UCODE RUNNING

KLPCH1:	SKIPN KLPRDY		;READY TO GO?
	JRST KLPCH6		;NO, GO DO START UP STUFF
	CONI KLP,T1		;YES, GET CSR
	MOVEM T1,LSTCNI		;SAVE IT
	MOVE Q3,CDBPCB(P1)	;GET PCB
	TXNE T1,CI.ECP		;ENABLE COMPLETE
	TXNE T1,CO.ENA		; AND ENABLED?
	IFSKP.
	   BUG. (CHK,KLPNEN,PHYKLP,SOFT,<PHYKLP - CI20 not enabled>,,<

Cause:	TOPS-20 believes the CI20 should be enabled but has found otherwise.
>,,<DB%NND>)			;[7.1210] 
	   CALL URDEAD		;(Q3,P1/) STOP CI AND START OVER
	   RET
	ENDIF.
	CALL CHKPCB		;(T1,Q3) CHECK THE PCB
   IFN KLPDBG,<
	CALL CHKQS		;(Q3) CHECK THE QUEUES
   >
	CALL CHKWIR		;(Q3,P1) CHECK CI WIRES
	CALL CHKRTO		;(Q3,P1) CHECK FOR REQUEST-ID TIMEOUTS
	CALL CHKSTO		;(Q3) CHECK FOR START SEQUENCE TIMEOUTS
	CALL CHKOPC		;(Q3) CHECK FOR DEFERRED CLOSES
	CALL CHKPOL		;(Q3) POLL THE NEXT NODE WITH A REQUEST-ID
	RET
;UCODE NEEDS-RELOADING TIMER

KLPCH2:	MOVE T1,UCDTIM		;GET TIMEOUT TIME
	CAMG T1,TODCLK		;TIMED OUT?
	BUG. (HLT,KLPNRL,PHYKLP,SOFT,<PHYKLP - CI20 ucode needs reloading>,,<

Cause:	The port microcode needs to be reloaded but there is a time out 
	waiting for it to get started.  Most likely JOB 0 has a problem.
>)
	RET


;UCODE RELOAD-IN-PROGRESS TIMER

KLPCH3:	MOVE T1,UCDTIM		;GET TIMEOUT TIME
	CAMG T1,TODCLK		;TIMED OUT?
	BUG. (CHK,KLPSRL,PHYKLP,SOFT,<PHYKLP - CI20 ucode still reloading>,,<

Cause:	The port microcode is being reloaded and there is a time out 
	waiting for it to complete.
>,,<DB%NND>)			;[7.1210] 
	RET			;NO


;UCODE NEEDS-DUMPING TIMER

KLPCH4:	MOVE T1,UCDTIM		;GET TIMEOUT TIME
	CAMG T1,TODCLK		;TIMED OUT?
	BUG. (HLT,KLPNDM,PHYKLP,SOFT,<PHYKLP - CI20 ucode needs dumping>,,<

Cause:	The port microcode needs to be dumped but there is a timeout waiting  
	for it to get started.
>)
	RET			;NO


;UCODE DUMP-IN-PROGRESS TIMER

KLPCH5:	MOVE T1,UCDTIM		;GET TIMEOUT TIME
	CAMG T1,TODCLK		;TIMED OUT?
	BUG. (CHK,KLPSDM,PHYKLP,SOFT,<PHYKLP - CI20 ucode still dumping>,,<

Cause:	The port microcode is being dumped and there is a time out waiting for
	it to complete.
>,,<DB%NND>)			;[7.1210] 
	RET			;NO
;Get our CI node number

KLPCH6:	MOVE Q3,CDBPCB(P1)	;GET PCB
	CALL KLPGDB		;(Q3/Q2) GET A DG BUFFER
	 RET			;CAN'T NOW, BETTER LUCK NEXT TIME
	CALL KLPRRG		;(Q2,Q3) SEND A READ REGISTER
	 NOP			;NO SUCH RETURN
	MOVEI Q2,100000		;GET A SPIN COUNT
KLPCH7:	SKIPL CDBNOD(P1)	;HAVE OUR NODE NUMBER YET?
	JRST KLPCH8		;YES, MOVE ON
	SOJG Q2,KLPCH7		;NO, WAIT SOME MORE
	LOAD T1,CFSTA,(P1)	;WAITED LONG ENOUGH, GET STATE OF PORT
	CAIE T1,CHNRUN		;STILL RUNNING?
	RET			;NO
	BUG. (CHK,KLPCGN,PHYKLP,HARD,<PHYKLP - Can't get CI node number>,,<

Cause:	The CI20 driver did a READ-REGISTER command to get the CI node number
	from the port;  it timed out waiting for the reply.  Most likely, the
	port is sick.
>,,<DB%NND>)			;[7.1210] 
	CALL URDEAD		;(Q3,P1/) STOP CI AND START OVER
	RET			;THAT'S ALL FOR NOW

;Send a request ID to each node on the network.

KLPCH8:	STKVAR <COUNT>		;[7185]
	SETZM COUNT		;[7185] INIT NUMBER OF REQUEST-IDS ATTEMPTED
	SETOM RIDNXT		;[7185] INIT POLLER'S NODE NUMBER
KLPCH9:	CALL INCRID		;MOVE TO NEXT NODE
	MOVE Q1,RIDNXT		;GET NEXT NODE NUMBER
	SKIPE RIDTIM(Q1)	;REQUEST-ID ALREADY OUTSTANDING?
	JRST KLPC10		;YES. DON'T ASK AGAIN
	CALL KLPGDB		;(Q3/Q2) NO, GET A DATAGRAM BUFFER
	 JRST KLPC11		;CAN'T NOW, WE'LL GET TO IT LATER
	MOVX T3,PF.PT0		;USE PATH A, RESPONSE NOT NEEDED
	CALL KLPRID		;(T3,Q1,Q2,Q3) SEND REQUEST-ID
	 NOP			;NO SUCH RETURN
KLPC10:	AOS T1,COUNT		;[7185]
	CAIE T1,MAXNDS		;[7185] TRIED ALL OTHER NODES?
	AOJA Q1,KLPCH9		;NO, DO THE NEXT ONE
KLPC11:	SETOM KLPRDY		;SAY KLIPA IS READY FOR USE
	RET
	ENDSV.			;[7185]
;Check some locations in the PCB
;ACCEPTS:	T1/ CSR
;		P1/ CDB
;		Q3/ PCB
;RETURNS:	+1

CHKPCB:	CAME Q3,.PBPBA(Q3)	;PCB STILL GOOD?
CHKPC1:	BUG. (HLT,KLPPCB,PHYKLP,SOFT,<PHYKLP - PCB is corrupted>,,<

Cause:	The PCB has invalid data.
>)
	MOVEI T2,C%MGSZ		;GET MESSAGE SIZE
	CAME T2,.PBMQE(Q3)	;PCB STILL GOOD?
	JRST CHKPC1		;NO
	MOVE T3,T1		;YES, PRESERVE CSR
	ANDI T1,7		;GET JUST THE PIA
	LDB T2,CSYPIA		;GET THE CORRECT PIA
	CAMN T1,T2		;KLIPA STILL SANE?
	IFSKP.
	   BUG. (INF,KLPPIA,PHYKLP,HARD,<PHYKLP - CI20 has lost its PIA>,<<T3,CSR>>,<

Cause:	The CI20 no longer knows its interrupt assignment.

Data:	CSR - the result of the last CONI
>,,<DB%NND>)			;[7.1210] 
	   CALL URDEAD		;(Q3,P1/) STOP CI AND START OVER
	ENDIF.
	RET

;Check the queues. Each interlock word should contain either 0 or -1,
;and the contents of the queue should pass the sanity check.
;ACCEPTS:	Q3/ PCB
;RETURNS:	+1

   IFN KLPDBG,<
CHKQS:	MOVEI T1,.PBQ3I(Q3)	;GET FIRST COMMAND QUEUE INTERLOCK WORD
CHKQS1:	SKIPE T2,(T1)		;DOES IT CONTAIN A ZERO?
	CAMN T2,[-1]		;NO. HOW ABOUT -1
	SKIPA			;EITHER IS OK
	BUG. (HLT,KLPILK,PHYKLP,SOFT,<PHYKLP - Interlock word is bad>,,<

Cause:	A queue interlock word contains an invalid value.
>)
	CALL SANCHK		;(T1/)IS THIS QUEUE OK? (CRASH IF NO)
	ADDI T1,3		;STEP TO NEXT INTERLOCK
	CAMG T1,.PBDFI(Q3)	;UP TO THE DATAGRAM FREE QUEUE YET?
	JRST CHKQS1		;NO, KEEP GOING
	RET			;YES, DONE
   >
;CHKWIR - Check CI wires by sending loopback packets
;ACCEPTS:	Q3/ PCB
;		P1/ CDB
;RETURNS:	+1

CHKWIR:	HRRZ Q1,CDBNOD(P1)	;get our node number
	CALL KLPGDB		;(Q3/Q2) Get a DATAGRAM buffer
	 RET			;FAILED, NOT CRITICAL
	MOVE T2,LPBCRC(Q1)	;get the proper CRC
	MOVEM T2,LPBLEN-1(Q2)	;Stash the CRC
	MOVEI T1,OP.LPB		;OP CODE
	MOVEI T2,KLPDRG		;PRIORITY
	SKIPE WIRNXT		;WIRE A?
	SKIPA T3,[PF.PT1]	;NO, WIRE B
	MOVX T3,PF.PT0		;YES, WIRE A
	SETZM .PKLEN(Q2)	;No length
	CALL DRVSND		;(T1,T2,T3,Q1,Q2,Q3) Send it
	 NOP			;NO SUCH RETURN
	SKIPN WIRNXT		;DID WE JUST DO A?
	IFSKP.
	   SETZM WIRNXT		;NO, DO A NEXT TIME
	ELSE.
	   SETOM WIRNXT		;YES, DO B NEXT TIME
	ENDIF.
	RET
;Check for REQUEST-ID time outs
;ACCEPTS:	Q3/ PCB
;		P1/ CDB
;RETURNS:	+1

CHKRTO:	SETZ Q1,		;START WITH NODE 0
CHKRT1:	SKIPE T1,RIDTIM(Q1)	;TIMER ON?
	CAMLE T1,TODCLK		;YES, TIMED OUT?
	JRST CHKRT3		;NO, NEXT NODE
	TMNN IDTRY,(Q1)		;YES, WAS IT THE FIRST TRY?
	JRST CHKRT2		;YES, TRY A SECOND TIME
	TMNN IDWFR,(Q1)		;NO, STILL WAITING FOR OUR PORT TO RESPOND?
	IFSKP.

;Our port is sick

	   BUG. (INF,KLPHNG,PHYKLP,HARD,<PHYKLP - CI20 is hung>,,<

Cause:	The response bit on a REQUEST-ID command was set and timed out waiting
	for it to appear on the response queue.  There is a problem with 
	the port.
>,,<DB%NND>)			;[7.1210] 
	   CALL URDEAD		;(Q3,P1/) STOP CI AND START OVER
	   RET
	ENDIF.

;The remote port is sick

	LOAD T1,IDNOR,(Q1)	;NO, PORT SENT IT. GET COUNT
;...
;...
	CAIGE T1,MAXNOR		;HAVE WE TRIED ENOUGH?
	IFSKP.
	   BUG. (CHK,KLPNOA,PHYKLP,SOFT,<PHYKLP - Remote port is not answering>,<<Q1,PORT>>,<

Cause:	The remote node is ACKing REQUEST-IDs but not sending IDRECs.  The
	remote system needs to be investigated.

Data:	PORT - Remote port number
>,,<DB%NND>)			;[7.1210] 
	   MOVEI T1,1		;YES, START
	   STOR T1,IDNOR,(Q1)	; OVER
	ELSE.
	   INCR IDNOR,(Q1)	;NO, COUNT IT
	ENDIF.
	SETZRO <IDTRY,IDWFR>,(Q1) ;FIRST TRY, NOT WAITING FOR RESPONSE
	RET

;The first REQUEST-ID try has timed out

CHKRT2:	CALL KLPGDB		;(Q3/Q2) GET A NEW BUFFER FOR THE RID
	 RET			;CAN'T NOW
	SETONE <IDTRY,IDWFR>,(Q1) ;2ND TRY, WAITING FOR RESPONSE TO REQUEST-ID
	SETONE PKDRV,(Q2)	;SET THE DRIVER SOFTWARE RESPONSE BIT
	MOVX T3,PF.RSP		;GET THE PACKET RESPONSE BIT
	TMNE IDSNT,(Q1)		;USING PATH A?
	IFSKP.
	   IOR T3,[PF.PT0]	;YES
	ELSE.
	   IOR T3,[PF.PT1]	;NO, USE PATH B
	ENDIF.
	CALL KLPRID		;(T3,Q1,Q2,Q3) SEND THE REQUEST-ID
	 NOP			;NO SUCH RETURN
	CALL NXTRID		;(Q1) MOVE POLLER TO NEXT NODE
CHKRT3:	CAIL Q1,MAXNDS		;THIS THE LAST NODE?
	RET			;YES, DONE
	AOS Q1			;NO, MOVE TO NEXT 
	JRST CHKRT1		; NODE
;Check start sequence timers
;ACCEPTS:	Q3/ PCB
;RETURNS:	+1

CHKSTO:	MOVSI P6,-C%SBLL	;AOBJN WORD FOR SB LIST
CHKST1:	SKIPN P5,SBLIST(P6)	;IS THERE ONE THERE?
	JRST CHKST2		;NO
	OPSTR <SKIPE T1,>,SBSST,(P5) ;YES, TIMER ON?
	CAMLE T1,TODCLK		;YES, TIMED OUT?
	JRST CHKST2		;NO
	LOAD T1,SBDPA,(P5)	;YES, GET NODE NUMBER
	CALL PTHSTS		;(T1/T2) GET PATH STATUS
	 RET			;PORT NOT RUNNING
	TXNE T2,UDB%WA+UDB%WB	;NODE STILL ANSWERING REQUEST-IDS?
	IFSKP.
CHKST3:	   CIOFF
	   SETZRO SBSST,(P5)	;NO, TURN OFF START TIMER
	   MOVX T1,VC.CLO	;SET STATE
	   STOR T1,SBVCST,(P5)	; BACK TO CLOSED
	   SETONE SBOKO,(P5)	;SAY IT'S OK TO OPEN
	   CION
	   JRST CHKST2		;MOVE ON
	ENDIF.
	TXNN T2,UDB%MA		;YES, IS IT IN MAINTENANCE MODE?
	IFSKP.
	   MOVE T2,T1		;YES, GET NODE NUMBER
	   CALL ISIT20		;IS IT A 20?
	    SKIPA		;NO, KEEP TRYING
	   JRST CHKST3		;YES, FORGET ABOUT IT
	ENDIF.
	LOAD Q1,SBDPA,(P5)	;NO, GET NODE NUMBER
	CALL KLPGDB		;(Q3/Q2) GET A BUFFER 
	 RET			;CAN'T NOW
	LOAD T1,SBVCST,(P5)	;GET VC STATE
	CAIE T1,VC.STS		;START-SENT?
	IFSKP.
	   MOVEI T1,PP.STA	;YES, GET START CODE
	ELSE.
	   MOVEI T1,PP.STK	;NO, GET STACK CODE
	ENDIF.
	CALL STRTDT		;(T1,Q2) MAKE THE PACKET
	CALL KLPSDG		;(Q1,Q2,Q3) SEND IT
	 NOP			;NO SUCH RETURN
	CALL STSST		;(P5) SET THE TIMER
CHKST2:	AOBJN P6,CHKST1		;DO ALL SB
	RET
;Regular REQUEST-ID polling
;ACCEPTS:	Q3/ PCB
;RETURNS:	+1

CHKPOL:	MOVE Q1,RIDNXT		;NO, GET NODE
	SKIPE RIDTIM(Q1)	;ALREADY ONE OUT THERE?
	CALLRET INCRID		;(Q1) YES, MOVE POLLER TO NEXT NODE
	CALL KLPGDB		;(Q3/Q2) NO, GET A BUFFER
	 RET			;CAN'T NOW
	CALL GTNPTH		;(Q1/T3) GET NEXT PATH
	CALL KLPRID		;(T3,Q1,Q2,Q3) SEND REQUEST-ID
	 NOP			;NO SUCH RETURN
	CALLRET INCRID		;(Q1) MOVE POLLER TO NEXT NODE



;CHECK FOR DEFERRED CLOSES
;ACCEPTS:	Q3/ PCB
;RETURNS:	+1

CHKOPC:	MOVSI P4,-C%SBLL	;AOBJN WORD FOR SB LIST
CHKOP3:	HRRZ Q1,P4		;ISOLATE NODE NUMBER
	SKIPN P5,SBLIST(P4)	;IS THERE ONE THERE?
	JRST CHKOP2		;NO
	TMNN SBNTC,(P5)		;YES, NEED CLOSING?
	IFSKP.
	   CALL KLPGDB		;(Q3/Q2) YES, GET A BUFFER
	    RET			;CAN'T NOW, WE'LL TRY NEXT TIME
	   CALL KLPCLO		;(Q1,Q2,Q3) TELL PORT TO CLOSE THE VC
	    NOP			;NO SUCH RETURN
	   SETZRO SBNTC,(P5)	;NO LONGER TRYING TO CLOSE
	   SETONE SBWFI,(P5)	;WATING FOR IDREC
	ENDIF.
CHKOP2:	AOBJN P4,CHKOP3		;CHECK ALL SB
	RET
;UPDATE POLLER'S NEXT NODE ONLY IF RIDNXT AND Q1 AGREE
;ACCEPTS:	Q1/ NODE NUMBER
;		P1/ ADDRESS OF CDB
;RETURNS: +1

;Q1 represents the node to which we just send a REQID or START. If
;RIDNXT contains the same node number, the next call to CHKPOL will
;send another REQID to it. In this case, increment RIDNXT to the next
;legal node number to avoid the problem

NXTRID:	CAMN Q1,RIDNXT		;IS IT THE POLLER'S NEXT NODE
	CALL INCRID		;(P1/) YES. INCREMENT
	RET

;INCRID - Increment RIDNXT

;Accepts:
;	P1/ address of CDB

;	CALL INCRID

;Returns +1: always

;Increment RIDNXT to the next legal node number. Don't let it go
;beyond the maximum, and don't let it be our node.

INCRID:	AOS T1,RIDNXT		;Compute next node number
	CAILE T1,MAXNDS		;Too high?
	SETZB T1,RIDNXT		;Yes. Wrap to zero
	CAMN T1,CDBNOD(P1)	;Is it our node?
	JRST INCRID		;Yes. That's not good. Get the next one
	RET
;GET CURRENT PATH
;ACCEPTS:	T1/ PACKET STATUS WORD
;		Q1/ NODE NUMBER
;RETURNS:	+1  T3/ FLAGS FIELD SET WITH PATH SELECT
;PRESERVES T1

GTCPTH:	TXNN T1,PF.PT0		;DID IT ARRIVE ON PATH A?
	IFSKP.
	   SETZRO IDSNT,(Q1)	;YES, USE
	   MOVX T3,PF.PT0	; PATH A FOR NEXT REQUEST-ID
	ELSE.
	   SETONE IDSNT,(Q1)	;NO, USE
	   MOVX T3,PF.PT1	; PATH B FOR NEXT REQUEST-ID
	ENDIF.
	RET


;GET NEXT PATH
;ACCEPTS:	Q1/ NODE NUMBER
;RETURNS:	+1  T3/ FLAGS FIELD SET WITH PATH SELECT

GTNPTH:	SETZ T3,		;RESET THE PATH AC
	TMNE IDSNT,(Q1)		;LAST ONE ON PATH A?
	IFSKP.
	   IOR T3,[PF.PT1]	;YES, USE B
	   SETONE IDSNT,(Q1)	; NEXT
	ELSE.
	   IOR T3,[PF.PT0]	;NO, USE A
	   SETZRO IDSNT,(Q1)	; NEXT
	ENDIF.
	RET


;SET START SEQUENCE TIMER
;ACCEPTS:	P5/ SB
;RETURNS:	+1

STSST:	MOVE T2,TODCLK		;GET CURRENT TIME
	ADD T2,SSTTMO		;CALC TIME OUT TIME
	STOR T2,SBSST,(P5)	;RESET TIMER
	RET
	SUBTTL PHYSIO Interface -- Check Unit Existence

;CHECK EXISTENCE OF UNIT
;HERE THROUGH KLPDSP (THE CDSEXT OFFSET)
;RETURNS +1	ALWAYS

KLPEXT:	LOAD T1,USTYP,(P2)	;GET CONTROLLER TYPE
	CAIE T1,.UTHSC		;AN HSC?
	CALL DSPBUG		;NO
	MOVEI T1,MSCDSP		;YES, GET MSCP CONTROLLER DISPATCH VECTOR
	CALLRET UDSEXT(T1)	;GO DO THE WORK


;GET MEMORY ADDRESS FROM CCW
;HERE THROUGH KLPDSP (THE CDSCCA OFFSET)
;ACCEPTS:	T1/ CCW WORD
;RETURNS:	+1  T1/ ADDRESS, OR ZERO IF NONE
;PRESERVES T1

KLPCCA:	LOAD T2,USTYP,(P2)	;GET CONTROLLER TYPE
	CAIE T2,.UTHSC		;AN HSC?
	CALL DSPBUG		;NO

;MSCCCA - EXTRACT THE PHYSICAL MEMORY ADDRESS FROM A CCW TRANSFER WORD.
;ACCEPTS:	T1/ CCW WORD
;RETURNS:	+1  T1/ ADDRESS, OR ZERO IF NONE

MSCCCA:	LOAD T1,CHADR,T1	;GET PHYSICAL ADDRESS FROM CCW
	RET			;DONE


;RETURN UNIT STATUS - SINCE THERE ARE NO UNITS ON A KL KDB WE ALWAYS FAIL
;ACCEPTS:	Q2/ UNIT NUMBER
;RETURNS:	+1 FAILED.  T1/ 0
;		+2 SUCCESS

KLEXT:	SETZ T1,		;NOTHING HERE
	RET
	SUBTTL CI CRAM Parity Error Processing

;CRAM PARITY ERROR (OUTPUT THE BUGxxx)
;ACCEPTS:	Q3/ PCB
;		P1/ CDB
;RETURNS:	+1

CPEBUG:	MOVE T1,CDBCS0(P1)	;GET LAR
	CAIL T1,7750		;PLANNED?
	IFSKP.
	  CALL UNPBUG		;(P1) NO, UNPLANNED CRAM PARITY ERROR
	ELSE.
	  SUBI T1,7750		;YES, GET OFFSET INTO PLANNED ADDRESSES
	  CALL @CPEBDP(T1)	;GO DO THE WORK
	ENDIF.
	RET

CPEBDP:	IFIW!IPEBUG		;7750 INTERNAL PORT ERROR
	IFIW!STFBUG		;7751 SELF TEST FAILED
	IFIW!EP2BUG		;7752 EBUS PARITY ERROR (QUEUES OK)
	IFIW!EP1BUG		;7753 EBUS PARITY ERROR (QUEUE MESSED UP)
	IFIW!PLIBUG		;7754 PLI PARITY ERROR
	IFIW!CBPBUG		;7755 CBUS PARITY ERROR
	IFIW!DPEBUG		;7756 DATA PATH ERROR
	IFIW!CBABUG		;7757 CBUS AVAILABLE ERROR
	IFIW!EBRBUG		;7760 EBUS REQUEST ERROR
	IFIW!GCSBUG		;7761 GRANT CSR
	IFIW!CERBUG		;7762 CHANNEL ERROR - SHORT WORD COUNT
	IFIW!CHEBUG		;7763 SPURIOUS CHANNEL ERROR
	IFIW!STABUG		;7764 SPURIOUS TRANSMIT ATTENTION ERROR
	IFIW!SRABUG		;7765 SPURIOUS RECEIVE ATTENTION ERROR
	IFIW!TTOBUG		;7766 TRANSMITTER TIMEOUT
	IFIW!PNDBUG		;7767
	IFIW!PNDBUG		;7770
	IFIW!PNDBUG		;7771
	IFIW!PNDBUG		;7772
	IFIW!PNDBUG		;7773
	IFIW!PNDBUG		;7774
	IFIW!PNDBUG		;7775
	IFIW!PNDBUG		;7776
	IFIW!PNDBUG		;7777
;CRAM PARITY ERROR
;ACCEPTS:	Q3/ PCB
;		P1/ CDB
;RETURNS:	+1

KLPCPE:	MOVE T1,CDBCS0(P1)	;GET LAR
	CAIL T1,7750		;PLANNED?
	IFSKP.
	  CALL KLPUNP		;(Q3,P1/) NO, UNPLANNED CRAM PARITY ERROR
	ELSE.
	  SUBI T1,7750		;YES, GET OFFSET INTO PLANNED ADDRESSES
	  CALL @CPEDSP(T1)	;GO DO THE WORK
	ENDIF.
	RET

CPEDSP:	IFIW!CPEDON		;7750 INTERNAL PORT ERROR
	IFIW!CPEDON		;7751 SELF TEST FAILED
	IFIW!CPEDON		;7752 EBUS PARITY ERROR (QUEUES OK)
	IFIW!KLPEP1		;7753 EBUS PARITY ERROR (QUEUE MESSED UP)
	IFIW!CPEDON		;7754 PLI PARITY ERROR
	IFIW!CPEDON		;7755 CBUS PARITY ERROR
	IFIW!CPEDON		;7756 DATA PATH ERROR
	IFIW!CPEDON		;7757 CBUS AVAILABLE ERROR
	IFIW!CPEDON		;7760 EBUS REQUEST ERROR
	IFIW!CPEDON		;7761 GRANT CSR
	IFIW!CPEDON		;7762 CHANNEL ERROR - SHORT WORD COUNT
	IFIW!CPEDON		;7763 SPURIOUS CHANNEL ERROR
	IFIW!CPEDON		;7764 SPURIOUS TRANSMIT ATTENTION ERROR
	IFIW!CPEDON		;7765 SPURIOUS RECEIVE ATTENTION ERROR
	IFIW!CPEDON		;7766 TRANSMITTER TIMEOUT
	IFIW!CPEDON		;7767
	IFIW!CPEDON		;7770
	IFIW!CPEDON		;7771
	IFIW!CPEDON		;7772
	IFIW!CPEDON		;7773
	IFIW!CPEDON		;7774
	IFIW!CPEDON		;7775
	IFIW!CPEDON		;7776
	IFIW!CPEDON		;7777
;UNPLANNED CRAM PARITY ERROR (0000-7747)
;ACCEPTS:	Q3/ PCB
;		P1/ CDB
;RETURNS:	+1

UNPBUG:	CALL GETDAT		;(P1/T1,T2,T3,T4) GET OPTIONAL DATA
	BUG. (INF,KLPUCP,PHYKLP,HARD,<PHYKLP - Unplanned CRAM parity error>,<<T1,CSR>,<T2,LAR>,<T3,CRAM1>,<T4,CRAM2>>,<

Cause:	The port had an unplanned CRAM parity error.

Data:	CSR - Result of last CONI
	LAR - CRAM's last address read
	CRAM1 - contents of first CRAM word
	CRAM2 - contents of next CRAM word
>,,<DB%NND>)			;[7.1210] 
	RET



;UNPLANNED CRAM PARITY ERROR (0000-7747)
; Q3/ PCB
; P1/ CDB
;	CALL KLPUNP		;(Q3,P1/)
; RETURN +1

;RESET THE QUEUES (FORGET ABOUT PACKETS), INTERLOCK WORDS ALREADY RESET

KLPUNP:	MOVEI T1,.PBQ3I(Q3)	;GET QUEUE'S INTERLOCK WORD
KLPUN1:	MOVEI T2,.PBFLI(T1)	;GET FLINK
	SUB T2,OFFSET		;WE NEED PHYSICAL ADDRESSES
	MOVEM T2,.PBFLI(T1)	;MAKE FLINK POINT AT ITSELF
	MOVEM T2,.PBBLI(T1)	;MAKE BLINK POINT AT FLINK
	ADDI T1,.PBBLI+1	;NEXT QUEUE
	CAIGE T1,.PBQND(Q3)	;DONE THEM ALL?
	JRST KLPUN1		;NO
	BUG. (INF,KLPPLS,PHYKLP,SOFT,<PHYKLP - Packets lost>,,<

Cause:	After an unplanned CRAM parity error we can't reliably believe the
	queues so we have thrown everything away and started over.  This may
	cause SCA to do some complaining.
>,,<DB%NND>)			;[7.1210] 
	CALL STKDFQ		;[7126] (P1) RESTOCK DATAGRAM FREE QUEUE
	CALL RLDKLP		;(P1) RELOAD AND START THE PORT
	RET
;SPURIOUS CHANNEL ATTENTION ERROR
;ACCEPTS:	Q3/ PCB
;		P1/ CDB
;RETURNS:	+1

CHEBUG:	CALL GETLGO		;(Q3,P1/T1,T2,T3,T4) GET INFO
	LOAD T4,CDVER,(P1)	;GET UCODE VERSION
	BUG. (INF,KLPSCE,PHYKLP,HARD,<PHYKLP - Spurious channel error>,<<T1,CSR>,<T4,VER>,<T2,LAR>,<T3,LWORD1>>,<

Cause:	Channel Error was asserted but no channel error information was in
	the channel logout word.

Data:	CSR - Result of last CONI
	VER - ucode version
	LAR - CRAM's last address read
	LWORD1 - Channel logout word 1
>,,<DB%NND>)			;[7.1210] 
	RET
;EBUS PARITY ERROR (QUEUE MESSED UP)
;ACCEPTS:	Q3/ PCB
;		P1/ CDB
;RETURNS:	+1

EP1BUG:	CALL GETEWD		;(Q3,P1/T1,T2,T3,T4) GET ERROR DATA
	BUG. (INF,KLPEBQ,PHYKLP,HARD,<PHYKLP - EBUS parity error>,<<T1,CSR>,<T2,LAR>,<T3,EWORD0>,<T4,EWORD1>>,<

Cause:	The port received a data word with bad parity from the KL.  This
	happened while processing a queue.

Data:	CSR - Result of last CONI
	LAR - CRAM's last address read
	EWORD0 - PCB error word 0
	EWORD1 - PCB error word 1
>,,<DB%NND>)			;[7.1210] 
	RET

;EBUS PARITY ERROR (QUEUE MESSED UP)
;ACCEPTS:	Q3/ PCB
;		P1/ CDB
;RETURNS:	+1

KLPEP1:	TMNN E0RES,(Q3)		;RESPONSE QUEUE HAVE ERROR?
	IFSKP.
	  MOVEI T1,.PBRQI(Q3)	;YES, GET RESPONSE QUEUE INTERLOCK WORD
	  MOVEI T2,.PBFLI(T1)	;GET THE FLINK
	  SUB T2,OFFSET		;WE NEED PHYSICAL ADDRESSES
	  MOVEM T2,.PBFLI(T1)	;MAKE FLINK POINT AT ITSELF
	  MOVEM T2,.PBBLI(T1)	;MAKE BLINK POINT AT FLINK
	ELSE.
	  MOVE T1,CDBCNI(P1)	;GET CSR AT TIME OF INTERRUPT
	  TXNE T1,CI.RQA	;NO, RESPONSE AVAILABLE?
	  CALL KLPRQC		;(Q3,P1) YES, PROCESS THE RESPONSE ENTRIES
	ENDIF.
	TMNN E0CMD,(Q3)		;COMMAND QUEUE ERROR?
	CALLRET CPEDN1		;(P1) NO, DONE
	LOAD T2,E0QUE,(Q3)	;YES, GET COMMAND QUEUE NUMBER
	IMULI T2,3		;3 PCB ENTRIES PER QUEUE
	MOVEI T1,.PBQ0I(Q3)	;GET COMMAND QUEUE 0 INTERLOCK WORD
	SUB T1,T2		;MOVE TO THE CORRECT INTERLOCK WORD
	CALL CLENCQ		;(T1,Q3,P1) CLEAN ALL QUEUES EXCEPT THE BAD ONE
	CALLRET CPEDN1		;(P1) RESTART THE KLIPA
;INTERNAL PORT ERROR
;ACCEPTS:	P1/ CDB
;RETURNS:	+1

IPEBUG:	MOVE T1,CDBCNI(P1)	;GET CSR
	LOAD T2,CDVER,(P1)	;GET UCODE VERSION
	MOVE T3,CDBCS0(P1)	;GET LAR
	 BUG. (INF,KLPINP,PHYKLP,HARD,<PHYKLP - Internal port error>,<<T1,CSR>,<T2,VER>,<T3,LAR>>,<

Cause:	The port has found an inconsistency in an operation it was performing.

Data:	CSR - Result of last CONI
	VER - ucode version
	LAR - CRAM's last address read
>,,<DB%NND>)			;[7.1210] 
	RET


;TRANSMITTER TIMEOUT
;ACCEPTS:	Q3/ PCB
;		P1/ CDB
;RETURNS:	+1

TTOBUG:	MOVE T1,CDBCNI(P1)	;GET CSR
	MOVE T2,.PBER2(Q3)	;GET TRANSMIT STATUS REGISTER
	LOAD T3,CDVER,(P1)	;GET UCODE VERSION
	BUG. (INF,KLPTMO,PHYKLP,HARD,<PHYKLP - Transmitter timeout>,<<T1,CSR>,<T2,REG>,<T3,VER>>,<

Cause:	Someone is hogging the CI.  The LINK module could not transmit over the
	CI due to carrier detect being continuously asserted.

Data:	CSR - Result of last CONI
	REG - Transmit status register
	VER - ucode version
>,,<DB%NND>)			;[7.1210] 
	RET
;SELF TEST FAILED
;ACCEPTS:	P1/ CDB
;RETURNS:	+1

STFBUG:	MOVE T1,CDBCNI(P1)	;GET CSR
	LOAD T2,CDVER,(P1)	;GET UCODE VERSION
	MOVE T3,CDBCS0(P1)	;GET LAR
	BUG. (INF,KLPFST,PHYKLP,HARD,<PHYKLP - Self test failed>,<<T1,CSR>,<T2,VER>,<T3,LAR>>,<

Cause:	The port had a failure during its self test.

Data:	CSR - Result of last CONI
	VER - ucode version
	LAR - CRAM's last address read
>,,<DB%NND>)			;[7.1210] 
	RET


;EBUS PARITY ERROR (QUEUES OK)
;ACCEPTS:	Q3/ PCB
;		P1/ CDB
;RETURNS:	+1

EP2BUG:	CALL GETLGO		;(Q3,P1/T1,T2,T3,T4) GET INFO
	MOVE T3,.PBER0(Q3)	;GET PCB ERROR WORD 0
	BUG. (INF,KLPEBP,PHYKLP,HARD,<PHYKLP - EBUS parity error>,<<T1,CSR>,<T2,LAR>,<T3,EWORD0>>,<

Cause:	The port received a data word with bad parity from the KL.  This
	did not happen while processing a queue.

Data:	CSR    - Result of last CONI
	LAR    - CRAM's last address read
	EWORD0 - PCB error word 0
>,,<DB%NND>)			;[7.1210] 
	RET
;PLI PARITY ERROR
;ACCEPTS:	P1/ CDB
;RETURNS:	+1

PLIBUG:	CALL GETEWD		;(Q3,P1/T1,T2,T3,T4) GET INFO
	BUG. (INF,KLPPPE,PHYKLP,HARD,<PHYKLP - PLI parity error>,<<T1,CSR>,<T2,LAR>>,<

Cause:	The port detected bad parity on a PLI BUS read.

Data:	CSR - Result of last CONI
	LAR - CRAM's last address read
>,,<DB%NND>)			;[7.1210] 
	RET


;CHANNEL ERROR
;ACCEPTS:	P1/ CDB
;RETURNS:	+1

CERBUG:	CALL GETEWD		;(Q3,P1/T1,T2,T3,T4) GET INFO
	BUG. (INF,KLPSWC,PHYKLP,HARD,<PHYKLP - Short word count>,<<T1,CSR>,<T2,LAR>,<T3,LWORD1>,<T4,LWORD2>>,<

Cause:	The port detected a short word count CBUS channel error.

Data:	CSR - Result of last CONI
	LAR - CRAM's last address read
	EWORD1 - PCB error word 1
	EWORD2 - PCB error word 2
>,,<DB%NND>)			;[7.1210] 
	RET
;CBUS PARITY ERROR
;ACCEPTS:	Q3/ PCB
;		P1/ CDB
;RETURNS:	+1

CBPBUG:	CALL GETEWD		;(Q3,P1/T1,T2,T3,T4) GET INFO
	BUG. (INF,KLPCBS,PHYKLP,HARD,<PHYKLP - CBUS parity error>,<<T1,CSR>,<T2,LAR>,<T3,LWORD1>,<T4,LWORD2>>,<

Cause:	The CI20 had a CBUS parity error.

Data:	CSR - Result of last CONI
	LAR - CRAM's last address read
	EWORD1 - PCB error word 1
	EWORD2 - PCB error word 2
>,,<DB%NND>)			;[7.1210] 
	RET

;SPURIOUS TRANSMIT ATTENTION ERROR
;ACCEPTS:	Q3/ PCB
;		P1/ CDB
;RETURNS:	+1

STABUG:	MOVE T1,CDBCNI(P1)	;GET CSR
	LOAD T2,CDVER,(P1)	;GET UCODE VERSION
	MOVE T3,CDBCS0(P1)	;GET LAR
	MOVE T4,.PBER2(Q3)	;GET TRANSMIT STATUS REGISTER
	BUG. (INF,KLPTAE,PHYKLP,HARD,<PHYKLP - Spurious transmit attention error>,<<T1,CSR>,<T2,VER>,<T3,LAR>,<T4,REG>>,<

Cause:	The port found ATTENTION up before the Transmit Packet function
	completed.

Data:	CSR - Result of last CONI
	VER - ucode version
	LAR - CRAM's last address read
	REG - Transmit status register
>,,<DB%NND>)			;[7.1210] 
	RET
;SPURIOUS RECEIVE ATTENTION ERROR
;ACCEPTS:	P1/ CDB
;RETURNS:	+1

SRABUG:	MOVE T1,CDBCNI(P1)	;GET CSR
	LOAD T2,CDVER,(P1)	;GET UCODE VERSION
	MOVE T3,CDBCS0(P1)	;GET LAR
	MOVE T4,.PBER2(Q3)	;GET RECEIVE STATUS REGISTER
	BUG. (INF,KLPRAE,PHYKLP,HARD,<PHYKLP - Spurious receive attention error>,<<T1,CSR>,<T2,VER>,<T3,LAR>,<T4,REG>>,<

Cause:	The port found ATTENTION up but the packet was not totally stored
	in the receive buffers.

Data:	CSR - Result of last CONI
	VER - ucode version
	LAR - CRAM's last address read
>,,<DB%NND>)			;[7.1210] 
	RET
;DATA PATH ERROR
;ACCEPTS:	P1/ CDB
;RETURNS:	+1

DPEBUG:	CALL GETEWD		;(Q3,P1/T1,T2,T3,T4) GET INFO
	BUG. (INF,KLPDPP,PHYKLP,HARD,<PHYKLP - Data path error>,<<T1,CSR>,<T2,LAR>,<T3,WORD0>,<T4,EWORD1>>,<

Cause:	The port's MOVER/FMTR detected a parity error.

Data:	CSR - Result of last CONI
	LAR - CRAM's last address read
	EWORD0 - PCB error word 0
	EWORD1 - PCB error word 1
>,,<DB%NND>)			;[7.1210] 
	RET

;CBUS AVAILABLE ERROR
;ACCEPTS:	P1/ CDB
;RETURNS:	+1

CBABUG:	MOVE T1,CDBCNI(P1)	;GET CSR
	MOVE T2,CDBCS0(P1)	;GET LAR
	DMOVE T3,.PBER3(Q3)	;GET PCB ERROR WORDS 3 & 4
	BUG. (INF,KLPCBN,PHYKLP,HARD,<PHYKLP - CBUS not available>,<<T1,CSR>,<T2,LAR>,<T3,EWORD3>,<T4,EWORD4>>,<

Cause:	The port was not able to get the CBUS.

Data:	CSR - Result of last CONI
	LAR - CRAM's last address read
	EWORD3 - PCB error word 3
	EWORD4 - PCB error word 4
>,,<DB%NND>)			;[7.1210] 
	RET
;EBUS REQUEST ERROR
;ACCEPTS:	P1/ CDB
;RETURNS:	+1

EBRBUG:	CALL GETDAT		;(P1/T1,T2,T3,T4) GET OPTIONAL DATA
	BUG. (INF,KLPERE,PHYKLP,HARD,<PHYKLP - EBUS request error>,<<T1,CSR>,<T2,LAR>>,<

Cause:	The port could not get the EBUS.

Data:	CSR - Result of last CONI
	LAR - CRAM's last address read
>,,<DB%NND>)			;[7.1210] 
	RET


;GRANT CSR
;ACCEPTS:	P1/ CDB
;RETURNS:	+1

GCSBUG:	CALL GETDAT		;(P1/T1,T2,T3,T4) GET DATA
	BUG. (INF,KLPCSR,PHYKLP,HARD,<PHYKLP - Grant CSR error>,<<T1,CSR>,<T2,LAR>,<T3,CRAM1>,<T4,CRAM2>>,<

Cause:	The port timed out waiting for Grant CSR.

Data:	CSR - Result of last CONI
	LAR - CRAM's last address read
	CRAM1 - contents of first CRAM word
	CRAM2 - contents of next CRAM word
>,,<DB%NND>)			;[7.1210] 
	RET



;CPE PROCESSING DONE
;ACCEPTS:	Q3/ PCB
;		P1/ CDB
;RETURNS:	+1

CPEDON:	CALL CLNKLP		;(Q3,P1/) CLEANUP THE QUEUES
CPEDN1:	CALL STRKLP		;(P1) START THE KLIPA
	 CALLRET RLDKLP		;(P1) FAILED, RELOAD IT
	RET
;UNDEFINED PLANNED CRAM PARITY ERROR
;ACCEPTS:	P1/ CDB
;RETURNS:	+1

PNDBUG:	CALL GETDAT		;(P1/T1,T2,T3,T4) GET DATA
	BUG. (INF,KLPUPC,PHYKLP,HARD,<PHYKLP - Undefined planned CRAM parity error>,<<T1,CSR>,<T2,LAR>,<T3,CRAM1>,<T4,CRAM2>>,<

Cause:	The port had a planned CRAM parity error but it is not defined.

Data:	CSR   - Result of last CONI
	LAR   - CRAM's last address read
	CRAM1 - contents of first CRAM word
	CRAM2 - contents of next CRAM word
>)
	RET
;FREE QUEUE ERROR
;ACCEPTS:	Q3/ PCB
;		P1/ CDB
;RETURNS:	+1

KLPFQE:	MOVE T1,.PBPIA(Q3)	;FREE Q ERROR, GET PIA
	CONO KLP,CI.EPE+CO.BTS+CI.FQE(T1) ;CLEAR FREE Q ERROR, EBUS PARITY
	XMOVEI T1,.PBDFI(Q3)	;GET INTERLOCK WORD OF DATAGRAM FREE QUEUE
	CALL CHKMPT		;(T1) IS DATAGRAM FREE QUEUE EMPTY?
	 IFNSK.
	    BUG. (INF,CIPDFQ,PHYKLP,SOFT,<PHYKLP - Datagram free queue empty>,,<

Cause:	The port found the datagram free queue empty.
>,,<DB%NND>)			;[7.1210] 
	    MOVEI T1,1		;GET A DATAGRAM BUFFER
	    CALL SC.ALD		;(T1/T1) FROM SCA
	     JRST KLPFQ1	;COULDN'T
	    MOVE Q2,T1		;POSITION THE BUFFER ADDRESS
	    CALL RETDG		;(Q2,Q3) PUT IT ON THE DATAGRAM FREE QUEUE
KLPFQ1:	    MOVEI T1,1		;COUNT A DG FREE QUEUE ERROR
	    JRST KLPFQ3		;MOVE ON
	 ENDIF.
	XMOVEI T1,.PBMFI(Q3)	;GET INTERLOCK WORD OF MESSAGE FREE QUEUE
	CALL CHKMPT		;(T1) IS MESSAGE FREE QUEUE EMPTY
	 IFNSK.
	    BUG. (INF,CIPMFQ,PHYKLP,SOFT,<PHYKLP - Message free queue empty>,,<

Cause:	The port found the message free queue empty.
>)
	    MOVEI T1,1		;GET A MESSAGE BUFFER
	    CALL SC.ABF		;(T1/T1) FROM SCA
	     JRST KLPFQ2	;COULDN'T
	    MOVE Q2,T1		;POSITION THE BUFFER ADDRESS
	    CALL RETMSG		;(Q2,Q3) PUT IT ON THE MESSAGE FREE QUEUE
KLPFQ2:	    MOVE T1,[1,,0]	;COUNT A MESSAGE FREE QUEUE ERROR
KLPFQ3:	    ADDM T1,CDBFQE(P1)	;COUNT IT IN THE CDB FOR THIS PORT
	 ENDIF.
	RET
;MBUS ERROR
;ACCEPTS:	Q3/ PCB
;		P1/ CDB
;RETURNS:	+1
;NOTE: DO NOT PROCESS ANY QUEUE

KLPMBE:	CALL GETDAT		;(P1/T1,T2,T3,T4) GET DATA
	BUG. (INF,KLPMBS,PHYKLP,HARD,<PHYKLP - MBUS error>,<<T1,CSR>,<T2,LAR>,<T3,CRAM1>,<T4,CRAM2>>,<

Cause:	 Multiple MBUS drivers simultaneously accessing MBUS.

Data:	CSR   - Result of last CONI
	LAR   - CRAM's last address read
	CRAM1 - contents of first CRAM word
	CRAM2 - contents of next CRAM word
>,,<DB%NND>)			;[7.1210] 
	CALL STRKLP		;(Q3,P1) RESTART THE KLIPA
	 CALLRET RLDKLP		;(P1) FAILED, ASK FOR A RELOAD
	RET



;TRANSMITTER BUFFER PARITY ERROR
;ACCEPTS:	Q3/ PCB
;		P1/ CDB
;RETURNS:	+1

KLPTBP:	MOVE T1,CDBCNI(P1)	;GET CSR
	MOVE T2,.PBER2(Q3)	;GET TRANSMIT STATUS REGISTER
	SETZM .PBER2(Q3)	;CLEAR IT
	LOAD T3,CDVER,(P1)	;GET UCODE VERSION
	BUG. (INF,KLPTPE,PHYKLP,HARD,<PHYKLP - Transmit buffer parity error>,<<T1,CSR>,<T2,REG>,<T3,VER>>,<

Cause:	A bit was dropped or picked up in the TRANSMIT BUFFER or the
	TRANSMIT DATA BUS.

Data:	CSR - Result of last CONI
	REG - Transmit status register
	VER - ucode version
>,,<DB%NND>)			;[7.1210] 
	RET
;MAKE A SPEAR ENTRY
;ACCEPTS:	P1/CDB
;		Q3/PCB
;RETURNS:	+1
;NOTE: CALLED AT INTERRUPT LEVEL WITH UCODE STOPPED

REPORT:	STKVAR <EBLOK>
	CONO KLP,CO.LAR		;SET THE LAR BIT
	DATAI KLP,T1		;READ LAR
	LOAD T1,DTLAR,T1	;GET LAR
	MOVEM T1,CDBCS0(P1)	;SAVE IT
	CONO KLP,		;CLEAR LAR BIT
	MOVX T1,1B0!1B13	;SET TO READ
	DATAO KLP,T1		; LH DATA
	DATAI KLP,T2		;READ CRAM LH DATA
	LOAD T2,DTCRM,T2	;GET DATA
	MOVEM T2,CDBCS1(P1)	;SAVE
	TXZ T1,1B13		;SET TO
	DATAO KLP,T1		; READ RH
	DATAI KLP,T2		;READ RH DATA
	LOAD T2,DTCRM,T2	;GET DATA
	MOVEM T2,CDBCS2(P1)	;SAVE
	DMOVE T1,KIEPT+KLPRH2*4 ;GET LOGOUT AREA
	DMOVEM T1,CDBLG0(P1)	;SAVE IN CDB
	MOVE T1,KIEPT+KLPRH2*4+2
	MOVEM T1,CDBLG2(P1)
	MOVE T1,.PBCCW(Q3)	;PORT'S CCW
	MOVEM T1,CDBECW(P1)	;SAVE
	MOVEI T1,KP%LEN		;TOTAL BLOCK LENGTH
	MOVEI T2,KP%SIZ		;NON STRING DATA SIZE
	CALL ALCSEB		;(T1,T2/T1) TRY TO GET ERROR BLOCK
	 RET			;NONE AVAILABLE.
	MOVEM T1,EBLOK		;SAVE LOC OF ERROR BLOCK
	MOVE T2,[-NKPTAB,,KPTAB] ;FILL IN THE DATA
	CALL SEBCPY		;(T1,T2)
	 JFCL
	MOVE T1,EBLOK		;RECOVER ERROR BLOCK
	CALL QUESEB		;(T1) HAND IT TO SPEAR
	RET

	ENDSV.
;FORMAT DEFINITION OF KLIPA ERROR EVENT (ERROR.SYS ENTRY 244)

KPTAB:	SEBPTR 0,SBTEVC,SEC%KP		;BLOCK TYPE
	SEBPTR KP%CSR,SBTWD,CDBCNI(P1)	;CSR
	SEBPTR KP%VER,SBTWD,CDBVER(P1)	;VERSION WORD
	SEBPTR KP%DSP,SBTWD,KLPDIS	;DISPOSITION (0 IF RESTART,
					; TAD OF LAST ERROR IF ABORTED)
	SEBPTR KP%CRA,SBTWD,CDBCS0(P1)	;CRAM ADDRESS
	SEBPTR KP%CRD,SBTWD,CDBCS1(P1)	;LH CRAM DATA
	SEBPTR KP%CRD+1,SBTWD,CDBCS2(P1) ;RH CRAM DATA
	SEBPTR KP%LG0,SBTWD,CDBLG0(P1)	;LOGOUT WORD 0
	SEBPTR KP%LG1,SBTWD,CDBLG1(P1)	;LOGOUT WORD 1
	SEBPTR KP%LG2,SBTWD,CDBLG2(P1)	;LOGOUT WORD 2
	SEBPTR KP%ECW,SBTWD,CDBECW(P1)	;PORT'S CCW
	SEBPTR KP%PE0,SBTWD,.PBER0(Q3)	;PCB'S ERROR WORD 0
	SEBPTR KP%PE1,SBTWD,.PBER1(Q3)	;PCB'S ERROR WORD 1
NKPTAB==.-KPTAB
;GET CSR, LAR, AND 2 UCODE DATA WORDS
;ACCEPTS:	P1/ CDB
;RETURNS:	+1	T1/ CSR
;			T2/ LAR
;			T3/ UCODE 1ST DATA WORD
;			T4/ UCODE 2ND DATA WORD

GETDAT:	MOVE T1,CDBCNI(P1)	;GET CSR
	MOVE T2,CDBCS0(P1)	;GET LAR
	DMOVE T3,CDBCS1(P1)	;GET DATA WORDS
	RET


;GET CSR, LAR, AND 2 CHANNEL LOGOUT WORDS
;ACCEPTS:	Q3/ PCB
;		P1/ CDB
;RETURNS:	+1	T1/ CSR
;			T2/ LAR
;			T3/ CHANNEL LOGOUT WORD 1
;			T4/ CHANNEL LOGOUT WORD 2

GETLGO:	MOVE T1,CDBCNI(P1)	;GET CSR
	MOVE T2,CDBCS0(P1)	;GET LAR
	DMOVE T3,.PBER3(Q3)	;GET CHANNEL LOGOUT WORDS
	RET

;GET CSR, LAR, AND THE 2 PCB ERROR WORDS
;ACCEPTS:	Q3/ PCB
;		P1/ CDB
;RETURNS:	+1	T1/ CSR
;			T2/ LAR
;			T3/ ERROR WORD 0
;			T4/ ERROR WORD 1

GETEWD:	MOVE T1,CDBCNI(P1)	;GET CSR
	MOVE T2,CDBCS0(P1)	;GET LAR
	DMOVE T3,.PBER0(Q3)	;GET ERROR WORDS 0 & 1
	RET
	SUBTTL States of the KLIPA -- Commentary

COMMENT #

                                   IPALOD.EXE

The program  BS:<SYSTEM>IPALOD.EXE consists  of 2  very distinct  pieces: 1)  a
runnable program, and  2) the CI20  microcode.  At system  startup the  monitor
reads the  microcode  into  resident  memory;  the  beginning  address  of  the
microcode is stored in location UCDADR.  Later during startup, the monitor runs
IPALOD.EXE, starting  it  at a  special  entry point  (offset  3 in  its  entry
vector).  IPALOD.EXE does a DIAG% which causes the microcode to be loaded  into
the CI20.  A second DIAG% is done  which causes the monitor to start the  CI20.
During this sequence IPALOD.EXE outputs the following message:

[IPALOD: Loading CI20 microcode x.y(z)] [OK]

If IPALOD.EXE is  run by  a user during  timesharing it  outputs the  following
message:

[IPALOD: Loading resident CI20 microcode x.y(z)] [OK]

It is not possible to load a different version of the CI20 microcode while  the
system is running; all you can do is reload the version which was in IPALOD.EXE
when the system was booted.  It was done  this way so as to not cause  existing
documentation to change while  still gaining all the  advantages of having  the
CI20 microcode in resident  memory so it  can be loaded at  any time, e.g.   at
interrupt or scheduler level.
                                  Port States

The port is always in 1 of the following 3 states:

     1.  uninitialized - not running

     2.  disabled - running,  accepting  local  commands,  neither sending  nor
         receiving on the wire

     3.  enabled - fully operational


                                CONO KLP,xxxxxx

If you execute a CONO instruction while the port is enabled and you want it  to
remain enabled, you  must include  the bits CO.ENA  and CO.MRN  and the  port's
priority interrupt assignment (PIA);  CO.BTS=CO.ENA+CO.MRN.  An example is  the
processing of a response queue available interrupt; when you do the CONO  which
turns off the response queue available bit, you must heed the above and include
CO.BTS and the PIA.

On the other hand, if  the port is diabled or  stopped and you want to  process
the response queue but leave the port disblaed or stopped, when you do the CONO
which turns off the response queue available bit, you must not include  CO.BTS.
See routine KLPRAQ and its special entry point KLPRQC for precise details.


                         Cleaning/Resetting the Queues

There are times when you want to reload the port and start fresh, examples  are
1) CRAM parity  error interrupt from  the port,  2) IPALOD.EXE is  run, and  3)
TOPS-20 believes the port is sick.  When  such events occur all packets on  the
command queues and the response queue must  be processed.  In order to do  this
the port must first be stopped, SCA must be told that all connections have been
broken, the queue interlock words set to -1, and then process the packets.

In most cases nothing need be done with the packets on the free queues.  If the
packets need to be discarded or given back to SCA, then the datagram free queue
must be restocked before the port is start again.


                                Dumping the CI20

In PHYKLP.MAC and MEXEC.MAC there  are references to BS:<SYSTEM>IPADMP.EXE  and
dumping the CI20.  Once upon  a time Job 0 did  the loading and dumping of  the
port; this was  a loser.  The  microcode is now  loaded by the  monitor but  we
haven't done the work yet to dump the port directly from the monitor.  We  will
in the future.
#
	SUBTTL States of the KLIPA -- Dispatch Tables

;DEFINED IN PHYPAR, HERE FOR REFERENCE

REPEAT 0,<
	DEFSTR (CFSTA,CDBFLG,5,6) ;STATE OF THE PORT
	CHNUNK==0		;unknown (system startup)
	CHNSTP==1		;stopped (and needs to be started)
	CHNNRL==2		;needs to have ucode reloaded
	CHNRIP==3		;ucode reload in progress
	CHNNDM==4		;needs to have dump taken
	CHNDIP==5		;dump in progress
	CHNMAI==6		;maintenace mode (owned by diagnostic)
	CHNDED==7		;dead (we are not trying to start it)
	CHNRUN==10		;running
	CHNRLC==11		;ucode reload complete
	CHNDMC==12		;ucode dump complete
>

;KLPINT (INTERRUPT SERVICE)

INTSTA:	IFIW!KLPIN2		;CHNUNK	- unknown (system startup)
	IFIW!KLPIN2		;CHNSTP	- stopped (and needs to be started)
	IFIW!KLPIN2		;CHNNRL	- needs to have ucode reloaded
	IFIW!KLPIN2		;CHNRIP	- ucode reload in progress
	IFIW!KLPIN2		;CHNNDM	- needs to have dump taken
	IFIW!KLPIN2		;CHNDIP	- dump in progress
	IFIW!KLPIN2		;CHNMAI	- maintenace mode (owned by diagnostic)
	IFIW!KLPIN2		;CHNDED	- dead (we are not trying to start it
	IFIW!KLPIN1		;CHNRUN	- running
	IFIW!KLPIN2		;CHNRLC	- reload complete
	IFIW!KLPIN2		;CHNDMC - dump complete

;KLPCHK (ONCE-A-SECOND CHECKER)

CHKSTA:	IFIW!R			;CHNUNK	- unknown (system startup)
	IFIW!R			;CHNSTP	- stopped (and needs to be started)
	IFIW!KLPCH2		;CHNNRL	- needs to have ucode reloaded
	IFIW!KLPCH3		;CHNRIP	- ucode reload in progress
	IFIW!KLPCH4		;CHNNDM	- needs to have dump taken
	IFIW!KLPCH5		;CHNDIP	- dump in progress
	IFIW!R			;CHNMAI	- maintenace mode (owned by diagnostic)
	IFIW!R			;CHNDED	- dead (we are not trying to start it
	IFIW!KLPCH1		;CHNRUN	- running
	IFIW!R			;CHNRLC	- reload complete
	IFIW!R			;CHNDMC - dump complete
;RLDKLP (RELOAD THE KLIPA UCODE)

RLDSTA:	IFIW!RLDKL1		;CHNUNK	- unknown (system startup)
	IFIW!RLDKL1		;CHNSTP	- stopped (and needs to be started)
	IFIW!R			;CHNNRL	- needs to have ucode reloaded
	IFIW!R			;CHNRIP	- ucode reload in progress
	IFIW!R			;CHNNDM	- needs to have dump taken
	IFIW!R			;CHNDIP	- dump in progress
	IFIW!RLDKL1		;CHNMAI	- maintenace mode (owned by diagnostic)
	IFIW!R			;CHNDED	- dead (we are not trying to start it
	IFIW!RLDKL1		;CHNRUN	- running
	IFIW!R			;CHNRLC	- reload complete
	IFIW!RLDKL1		;CHNDMC - dump complete


;DMPKLP (DUMP THE KLIPA UCODE)

DMPSTA:	IFIW!DMPKL1		;CHNUNK	- unknown (system startup)
	IFIW!DMPKL1		;CHNSTP	- stopped (and needs to be started)
	IFIW!R			;CHNNRL	- needs to have ucode reloaded
	IFIW!R			;CHNRIP	- ucode reload in progress
	IFIW!R			;CHNNDM	- needs to have dump taken
	IFIW!R			;CHNDIP	- dump in progress
	IFIW!DMPKL1		;CHNMAI	- maintenace mode (owned by diagnostic)
	IFIW!R			;CHNDED	- dead (we are not trying to start it
	IFIW!DMPKL1		;CHNRUN	- running
	IFIW!R			;CHNRLC	- reload complete
	IFIW!R			;CHNDMC - dump complete
	SUBTTL States of the KLIPA -- Loading the KLIPA -- KLPRIP (Load from User)

;RELOAD/DUMP-IN-PROGRESS (CALLED FROM DIAG%)
;ACCEPTS:	P1/ CDB
;RETURNS:	+1

KLPRIP::SAVEPQ
	MOVE T1,FORKX		;GET FORK NUMBER
	STOR T1,CSLDF,(P1)	;SAVE IT
	MOVE T1,USRNAM+1	;GET USER NAME
	MOVEM T1,CDBLDU(P1)	;SAVE IT
	MOVEI P6,CHNRIP		;GET RELOAD-IN-PROGRESS CODE
	JRST KLPDI1		;DO COMMON STUFF

KLPDIP::SAVEPQ
	MOVE T1,FORKX		;GET FORK NUMBER
	STOR T1,CSDMF,(P1)	;SAVE IT
	BUG. (INF,KLPDUM,PHYKLP,SOFT,<PHYKLP - CI20 ucode dump in progress>,<<T1,DFORK>>,<

Cause:	DIAG% was executed prior to dumping the CI20 port's ucode.

Data:	DFORK - fork doing the dump
>,,<DB%NND>)			;[7.1210] 
	MOVE T1,USRNAM+1	;GET USER NAME
	MOVEM T1,CDBDMU(P1)	;SAVE IT
	MOVEI P6,CHNDIP		;GET DUMP-IN-PROGRESS CODE

KLPDI1:	CIOFF
	CALL DISKLP		;() PUT KLIPA IN DISABLED STATE
	 CONO KLP,CO.CPT	;[7134] FAILED, SHOOT IT
	STOR P6,CFSTA,(P1)	;SET CHANNEL STATE
	MOVE Q3,CDBPCB(P1)	;GET PCB
	CALL CIGONE		;(Q3,P1/) RESET ALL CI ACTIVITY
	CALL LODUCD		;() LOAD UCODE
	CION
	RET
	SUBTTL States of the KLIPA -- Loading the KLIPA -- LODUCD (Load Microcode)

;LOAD CI UCODE INTO PORT
;	CALL LODUCD		;()
; RETURN +1

LODUCD:	MOVE T1,TODCLK		;GET NOW
	ADDI T1,IPRTIM		;GET IN-PROGRESS TIMEOUT TIME
	MOVEM T1,UCDTIM		;RESET IT
	SKIPN T2,UCDADR		;GET UCODE ADDRESS
	RET			;NOTHING THERE
	CONO KLP,CO.CPT		;[7134] MAKE SURE PORT IS STOPPED
	DO.
	  MOVE T1,(T2)		;GET MICROWORD
	  CAMN T1,[-1]		;AT THE END?
	  EXIT.			;YES
	  DATAO KLP,T1		;NO
	  DATAO KLP,1(T2)
	  TXZ T1,1B13
	  DATAO KLP,T1
	  DATAO KLP,2(T2)
	  ADDI 2,3
	  JRST TOP.
	ENDDO.
	AOS T2
	MOVE T1,(T2)		;GET UCODE MAJOR VERSION NUMBER
	STOR T1,UCMAJ		;SAVE IT
	AOS T2
	MOVE T1,(T2)		;GET UCODE MINOR VERSION NUMBER
	STOR T1,UCMIN		;SAVE IT
	AOS T2
	MOVE T1,(T2)		;GET UCODE EDIT NUMBER
	STOR T1,UCEDT		;SAVE IT
	MOVE T2,CHNTAB+KLPRH2	;GET CDB
	STOR T1,CDVER,(T2)	;SAVE EDIT NUMBER IN CDB
	CAML T1,KLPVWD		;[7.1134] Was it at the minimum we expect?
	IFSKP.			;[7.1134] Nope
	  BUG. (CHK,KLPUMV,PHYKLP,SOFT,<Unexpected CI20 microcode version>,<<T1,AVER>,<KLPVWD,EVER>>,<

Cause:	The monitor has an assembled-in value of the CI20 ucode which it is
	expecting to load.  The ucode just loaded is a lower version number.

Action:	Find a proper IPALOD.EXE and put it into BS:<SYSTEM>.

Data:	AVER - actual version loaded
	EVER - expected version
>,,<DB%NND>)			;[7.1238][7.1134]
	  RET			;[7.1134] Return
	ENDIF.			;[7.1134]
	BUG. (INF,KLPLOA,PHYKLP,SOFT,<PHYKLP - CI20 ucode loaded>,<<T1,EDIT>>,<

Cause:	BS:<SYSTEM>IPALOD.EXE was run or the monitor initiated the reload.

Data:	EDIT - edit number of microcode
>,,<DB%NND>)			;[7.1210][7.1134]
	RET
	SUBTTL States of the KLIPA -- Loading the KLIPA -- RLDKLP (Load from Monitor)

;REQUEST A RELOAD OF THE KLIPA MICROCODE
;ACCEPTS:	P1/ CDB
;RETURNS:	+1

RLDKLP:	SKIPE CIBUGX
	BUG. (INF,KLPRRQ,PHYKLP,HARD,<PHYKLP - CI20 ucode reload requested>,,<

Cause:	TOPS-20 has decided the CI20 microcode needs to be reloaded.
>,,<DB%NND>)			;[7.1210] 
	LOAD T1,CFSTA,(P1)	;GET STATE OF PORT
	CALLRET @RLDSTA(T1)	;TAKE APPROPRIATE ACTION

RLDKL1:	MOVEI T1,CHNNRL		;GET NEEDS-RELOADING CODE
	JRST DMPKL2		;DO COMMON STUFF


;REQUEST A DUMP OF THE KLIPA MICROCODE
;ACCEPTS:	P1/ CDB
;RETURNS:	+1

DMPKLP:	BUG. (INF,KLPDRQ,PHYKLP,HARD,<PHYKLP - CI ucode dump requested>,,<

Cause:	TOPS-20 has decided the CI20 microcode needs to be dumped.
>,,<DB%NND>)			;[7.1210] 
	LOAD T1,CFSTA,(P1)	;GET STATE OF PORT
	CALLRET @DMPSTA(T1)	;TAKE APPROPRIATE ACTION

DMPKL1:	MOVEI T1,CHNNDM		;GET NEEDS-DUMPING CODE
DMPKL2:	STOR T1,CFSTA,(P1)	;SET NEW PORT STATE
	CALL LODUCD		;(/)LOAD MICROCODE
	CALL KLPRLC		;(P1/) SAY RELOAD IS DONE
	RET
	SUBTTL States of the KLIPA -- Loading the KLIPA -- KLPRLC (Reload Complete)

;RELOAD-COMPLETE (CALLED FROM DIAG%)
;ACCEPTS:	P1/ CDB
;RETURNS:	+1

KLPRLC::SAVEPQ
	CIOFF
	MOVEI T1,CHNRLC		;GET RELOAD-COMPLETE CODE
	STOR T1,CFSTA,(P1)	;SET STATE OF PORT
	CALL STRKLP		;(P1) START THE KLIPA
	 IFNSK.
	    CALL STRKLP		;FAILED, WE'LL TRY ONE MORE TIME
	     NOP		;TOO BAD
	 ENDIF.
	CION
	RET


;DUMP-COMPLETE (CALLED FROM DIAG%)
;ACCEPTS:	P1/ CDB
;RETURNS:	+1

KLPDMC::SAVEPQ
	CIOFF
	MOVEI T1,CHNDMC		;GET DUMP-COMPLETE CODE
	STOR T1,CFSTA,(P1)	;SET STATE OF PORT
	CALL RLDKLP		;(P1) ASK FOR A RELOAD
	CION
	RET
	SUBTTL States of the KLIPA -- Stopping the KLIPA -- STPKLP (Stop KLIPA)

;Stop the KLIPA
;ACCEPTS:	P1/ CDB
;RETURNS:	+1

STPKLP:	BUG. (INF,KLPSTP,PHYKLP,SOFT,<PHYKLP - CI20 stopped>,,<

Cause:	TOPS-20 has stopped the CI20.
>,,<DB%NND>)			;[7.1210] 
	CALL DISKLP		;() PUT KLIPA IN DISABLED STATE
	 NOP			;[7223] WE TRIED TO BE GRACEFUL
	CONO KLP,CO.CPT		;[7134],[7223] SHOOT IT
	MOVEI T1,CHNSTP		;GET STOPPED CODE
	STOR T1,CFSTA,(P1)	;SET NEW PORT STATE
	RET


;XCKLP - STOP THE CI
;	CALL XCKLP		;(/)
; RETURNS +1

XCKLP::	SKIPE CIHERE		;[7134] CI IN USE?
	CONO KLP,CO.CPT		;[7134] YES, Do it
	RET			;[7134]
	SUBTTL States of the KLIPA -- Stopping the KLIPA -- DISKLP (Disable KLIPA)

;Get KLIPA into disabled state
;RETURNS:	+1 FAILED.  T1/ ERROR CODE
;		+2 SUCCEEDED OR ALREADY NOT RUNNING
;NOTE: THIS ROUTINE LOSES THE PIA

DISKLP:	CONSO KLP,CO.MRN	;IS THE UCODE RUNNING?
	RETSKP			;NO

;Enter here ONLY if you know where the port will start running if it is already stopped

DISKL2:	CONO KLP,CO.DIS+CO.MRN	;YES, GET PORT INTO DISABLED STATE
	MOVEI T2,5000		;LOOP COUNT
DISKL1:	CONI KLP,T1		;GET CSR
	TXNE T1,CI.DCP		;DISABLE COMPLETE?
	RETSKP			;YES
	SOJG T2,DISKL1		;NO, WAIT A BIT LONGER?
	RETBAD (KLPX14)		;NO
	SUBTTL States of the KLIPA -- Starting the KLIPA -- STRKLP (Start KLIPA)

;Start the KLIPA
;ACCEPTS:	P1/ CDB
;RETURNS:	+1 FAILED.  T1/ ERROR CODE
;		+2 SUCCEEDED

STRKLP:	SAVEAC <Q3>
	SETZM CIWIRA		;[7238] ASSUME BOTH WIRES
	SETZM CIWIRB		;[7238]  ARE GOOD AT THE BEGINNING
	MOVE Q3,CDBPCB(P1)	;GET PCB
	CALL RSTEWD		;(Q3) RESET THE PCB ERROR WORDS
	CALL KIKKLP		;(P1) KICK THE KLIPA
	IFNSK.

;KLIPA restart has failed

	  SKIPE KLPFAI		;DID THE LAST START ATTEMPT FAIL?
	  IFSKP.
	    SETOM KLPFAI	;NO, SAY WE FAILED THIS TIME
	    BUG. (INF,KLPRSF,PHYKLP,HARD,<PHYKLP - CI restart failed>,<<T1,ERROR>>,<

Cause:	TOPS-20 tried to restart the CI20 and the procedure failed.

Data:	ERROR - error code for failure
>,,<DB%NND>)			;[7.1210] 
	    RETBAD ( )		;FAILED
	  ENDIF.

;This is the second consecutive start attempt to fail

	  SETZM KLPFAI		;RESET THE FAILED FLAG
	  MOVEI T2,CHNDED	;GET DEAD CODE
	  STOR T2,CFSTA,(P1)	;SET NEW STATE
	  CONO KLP,CO.CPT	;[7134] MAKE SURE
	  BUG. (CHK,KLPDED,PHYKLP,HARD,<PHYKLP - CI20 is dead, no longer trying to start it>,<<T1,ERROR>>,<

Cause:	TOPS-20 tried to restart the CI20 and the procedure failed twice
	in a row.  The CI20 is being left in its current state.

Data:	ERROR - error code for failure
>,,<DB%NND>)			;[7.1210] 
	  RETSKP		;DONE
	ENDIF.

;.....
;.....

;KLIPA has been restarted

	MOVE T1,.PBPIA(Q3)	;GET PI ASSIGNMENT
	CONO KLP,CO.BTS(T1)	;TURN ON INTERRUPTS
	BUG. (INF,KLPSTR,PHYKLP,HARD,<PHYKLP - CI20 started>,,<

Cause:	TOPS-20 has restarted the CI20.
>,,<DB%NND>)			;[7.1210] 
	SETZM KLPFAI		;INDICATE KLIPA STARTED OK
	MOVEI T1,CHNRUN		;GET RUNNING CODE
	STOR T1,CFSTA,(P1)	;SET STATE OF PORT
	SETZM KLPRDY		;NEED TO SEND REQIDS TO ALL NODES
	CALL PHYSTC		;() TELL DISK SERVICE
	RETSKP
	SUBTTL States of the KLIPA -- Starting the KLIPA -- KIKKLP (Ready KLIPA)

;Get the KLIPA ready to run
;ACCEPTS:	P1/ CDB
;RETURNS:	+1 FAILED.  T1/ ERROR CODE
;		+2 SUCCEEDED
;
;Assumed to be called at interrupt level or CIOFF

KIKKLP:	SAVEAC <Q3>
	MOVEI T1,CHNSTP		;GET STOPPED CODE
	STOR T1,CFSTA,(P1)	;SET NEW PORT STATE
	MOVE Q3,CDBPCB(P1)	;GET PCB
	MOVE T2,[600000+3*20,,.PBPBA] ;SET CCW TO GET THE UCODE GOING
	ADDI T2,(Q3)
	SUB T2,OFFSET		;POINT AT PHYSICAL ADDRESS
	MOVEM T2,KIEPT+KLPRH2*4 ;THE UCODE WILL FIND L(PCB) FROM THIS XFER
	DATAO KLP,[.DOLRA]	;SET START ADDRESS TO 0
	CALL DISKL2		;() PUT KLIPA IN DISABLED STATE
	 RETBAD ( )		;FAILED
	MOVSI T2,200000		;SET UP A JUMP CCW
	HRRI T2,.PBCCW(Q3)	;WHERE THE KLIPA WANTS TO SEE IT
	SUB T2,OFFSET
	MOVEM T2,KIEPT+KLPRH2*4
	CALL ENAKLP		;() PUT KLIPA IN ENABLED STATE
	 RETBAD ( )		;FAILED
	RETSKP
	SUBTTL States of the KLIPA -- Starting the KLIPA -- ENAKLP (Enable KLIPA)

;Get KLIPA into enabled state
;RETURNS:	+1 FAILED.  T1/ ERROR CODE
;		+2 SUCCEEDED

ENAKLP:	CONO KLP,CI.RQA!CO.BTS	;GO FROM DISABLED TO ENABLED
	MOVEI T2,5000		;GET LOOP COUNTER
ENAKL1:	CONI KLP,T1		;GET CSR
	TXNE T1,CI.ECP		;ENABLE COMPLETE?
	RETSKP			;YES
	SOJG T2,ENAKL1		;NO, WAIT A BIT LONGER?
	RETBAD (KLPX15)		;NO
	SUBTTL States of the KLIPA -- Set CI Port Unavailable

;ENABLE "ASSIGN CHANNEL FOR MAINTENANCE"  (CALLED FROM DIAG%)
;ACCEPTS:	P1/ CDB
;RETURNS:	+1

	SWAPCD

KLPEAC::SAVEPQ
	CIOFF
	CALL CFDIAG		;(/) HAVE CFS BREAK ITS CONNECTIONS
	CALL STPKLP		;(P1/) STOP THE KLIPA
	MOVE Q3,CDBPCB(P1)	;GET PCB
	CALL CIGONE		;(Q3,P1/) RESET ALL CI ACTIVITY
	MOVEI T1,CHNMAI		;GET MAINTENANCE-MODE CODE
	STOR T1,CFSTA,(P1)	;SET NEW PORT STATE
	CION
	RET


;DISABLE "ASSIGN CHANNEL FOR MAINTENANCE"  (CALLED FROM DIAG%)
;ACCEPTS:	P1/ CDB
;RETURNS:	+1

KLPDAC::SAVEPQ
	CIOFF
	MOVE Q3,CDBPCB(P1)	;GET PCB
	CALL STPKLP		;(P1/) STOP THE KLIPA
	CALL RSTQS		;(Q3/) RESET PCB QUEUES
	CALL STKDFQ		;(P1/) STOCK DATAGRAM FREE QUEUE
	CALL RLDKLP		;(P1/) RELOAD THE DEFAULT UCODE AND START KLIPA
	CION
	RET
	SUBTTL States of the KLIPA -- Miscellaneous

;CALLED AT SYSTEM STARTUP
;RETURNS:	+1 DOESN'T NEED ANYTHING
;		+2 NEEDS ACTION:   T2/ 0 = LOAD
;				      -1 = DUMP

	SWAPCD

CHKKLP::SKIPN T1,CHNTAB+KLPRH2	;ANYTHING IN THIS SLOT?
	RET			;NO. SAY NO HELP NEEDED
	MOVE T2,CDBSTS(T1)	;GET THE STATUS
	TXNN T2,CS.CIP		;IS THIS A KLIPA?
	RET			;NO.
	LOAD T1,CFSTA,(T1)	;YES, GET STATE OF PORT
	CAIE T1,CHNNRL		;NEED RELOADING?
	IFSKP.
	  SETZ T2,		;YES
	  RETSKP
	ENDIF.
	CAIE T1,CHNNDM		;NO, NEED DUMPING?
	IFSKP.
	  SETO T2,		;YES
	  RETSKP
	ENDIF.
	RET			;NO


;CALLED WHEN THERE IS NO IPALOD.EXE ON THE SYSTEM
;RETURNS:	+1

KLPNLF::SAVEAC <P1,P2>
	SKIPN P1,CHNTAB+KLPRH2	;GET CDB
	RET			;NO KLIPA
	MOVEI P2,CHNDED		;GET DEAD CODE
	STOR P2,CFSTA,(P1)	;SET NEW STATE
	RET


;CALLED WHEN THERE IS NO IPADMP.EXE ON THE SYSTEM
;RETURNS:	+1

KLPNDF::SAVEAC <P1,P2>
	SKIPN P1,CHNTAB+KLPRH2	;GET CDB
	RET			;NO KLIPA
	CIOFF
	MOVEI P2,CHNSTP		;GET STOPPED CODE
	STOR P2,CFSTA,(P1)	;SET NEW STATE
	CALL RLDKLP		;(P1) ASK FOR A RELOAD
	CION
	RET

	RESCD
	SUBTTL Utility Routines

;PUT START DATA INTO BUFFER
;ACCEPTS:	T1/ PPD BYTE (START OR STACK)
;		Q2/ ADDRESS OF BUFFER
;RETURNS:	+1 ALWAYS

STRTDT:	STKVAR <KLPTMP>
	DPB T1,PKYPPD		;INSERT PPD BYTE
	MOVE T1,APRSER		;GET OUR SERIAL NUMBER
	LSH T1,4		;FUDGE FOR THE LOW ORDER BITS THAT DON'T COUNT
	CALL REVFUL		;REVERSE BYTES BEFOR SHIPPING
	MOVEM T1,.SRSSY(Q2)	;STORE OUR SERIAL NUMBER AS SENDING NODE
	SETZM .SRSSY+1(Q2)	;CLEAR SECOND WORD OF SENDING SYSTEM
	MOVEI T1,SCAVER		;SCA PROTOCOL
	STOR T1,SRVRS,(Q2)	; VERSION
	SETZRO SRMBZ,(Q2)	;ZERO THE MBZ FILD
	MOVE T1,.SRRSV(Q2)	;GET THE ENTIRE WORD
	CALL REVFUL		;REVERSE THOSE BACKWARD BYTES
	MOVEM T1,.SRRSV(Q2)	;RESTORE THE WORD
	MOVE T1,[XWD C%MXMP_2,C%MXDP_4] ;MAX MESSAGE, DG SIZES
	CALL REVFUL		;REVERSE THEM
	MOVEM T1,.SRMMS(Q2)	;SAVE IN PACKET
	MOVE T1,[BYTE (8) 124,55,62,60] ;""T-20" IS SOFTWARE TYPE
	MOVEM T1,.SRSWT(Q2)	;SAVE IN PACKET
;Note comically - This will need to be modified sometime in the
;future if TOPS-20's major version number exceeds 100 octal.

	MOVE T1,[POINT 3,137,5] ;[7422] Pointer to version number
	MOVEI T2,.SRSWV(Q2)	;WHERE IN PACKET TO STORE IT
	MOVEI T3,4		;4 BYTES
	CALL STORNO		;SAVE SW VERSION
	MOVE T1,[POINT 3,137,23] ;POINTER TO VERSION
	MOVEI T2,.SRSWI+1(Q2)	;WHERE IN PACKET TO STORE
	MOVEI T3,4		;4 BYTES
	CALL STORNO		;SAVE SW INCARNATION
	MOVE T1,[BYTE (8) 40,40,40,40] ;1ST 8 BYTES OF INCARNATION ARE BLANK
	MOVEM T1,.SRSWI(Q2)	; "
	MOVEM T1,.SRHWV+1(Q2)	;PAD LAST 3 WORDS OF HDWRE VERSION
	MOVEM T1,.SRHWV+2(Q2)	; "
	MOVEM T1,.SRHWV+3(Q2)	; "
	MOVE T1,[BYTE (8) 113,114,61,60] ;""KL10"
	MOVEM T1,.SRHWT(Q2)	;IS HW TYPE
	BLKI T1			;READ MICROCODE VERSION (APRID)
	TLZ T1,777000		;MASK OUT JUNK (MICROCODE OPTIONS)
	MOVEM T1,KLPTMP		;STASH IT
	MOVE T1,[POINT 3,KLPTMP,5] ;POINT TO START OF VERSION
	MOVEI T2,.SRHWV(Q2)	;WHERE TO STORE IT
	MOVEI T3,4		;4 BYTES
	CALL STORNO		;SAVE IN PACKET
	SETZM .SRTOD(Q2)	;TIME OF DAY IN
	SETZM .SRTOD+1(Q2)	; VAX NOTATION
	RET

	ENDSV.
;ROUTINE TO STORE 8-BIT BYTES IN A PACKET
;CALL:	T1/POINTER TO DATA
;	T2/	ADDRESS OF WHERE TO STORE
;	T3/	COUNT OF BYTES TO STORE
;CALL STOR6 IF ORIGINAL DATA IS SIXBIT, STORNO IF OCTAL NUMBER

STORNO:	MOVSI	CX,(POINT 8,0(T2)) ;SET CX AS A BYTE POINTER
	HLL	T2,Q2		;TURN ON RIGHT SECTION BITS
STORLP:	ILDB	T4,T1
	ADDI	T4,60		;CONVERT TO ASCII
	IDPB	T4,CX		;SAVE IN PACKET
	SOJG	T3,STORLP	;FOR ALL CHARACTERS
	RET
;PATH STATUS
;ACCEPTS:	T1/ NODE NUMBER
;RETURNS:	+1  PORT NOT RUNNING
;		+2  T2/ STATUS
;
;PRESERVES ALL ACS EXCEPT T2
;
; UDB%WA and UDB%WB
;
;Returning a bit on means:
;  1) For our node - the wire is good
;  2) For a remote - the answer to request-ids is not no-response
;Returning a bit off means:
;  1) For our node - the wire is bad
;  2) For a remote - the answer to request-ids is no-response

; UDB%MA
;
;Indicates remote node is in maintenance state (IDREC said so)

PTHSTS::SAVEAC <P1>		;SAVE P1
	SKIPN P1,CHNTAB+KLPRH2	;GET CDB
	RET			;NO KLIPA
	LOAD T2,CFSTA,(P1)	;GET STATE OF PORT
	CAIE T2,CHNRUN		;RUNNING?
	RET			;NO
	SETZ T2,		;YES, START FRESH
	CAME T1,CDBNOD(P1)	;OUR NODE?
	IFSKP.

;Status of loopback

	   SKIPN CIWIRA		;YES, WIRE A GOOD?
	   IOR T2,[UDB%WA]	;YES
	   SKIPN CIWIRB		;WIRE B GOOD?
	   IOR T2,[UDB%WB]	;YES
	ELSE.

;Status of no-response to a remote node

	   TMNE IDMAI,(T1)	;NODE IN MAINTENANCE MODE?
	   IOR T2,[UDB%MA]	;YES
	   TMNN IDNRA,(T1)	;NO-RESPONSE ON A?
	   IOR T2,[UDB%WA]	;NO
	   TMNN IDNRB,(T1)	;NO-RESPONSE ON B?
	   IOR T2,[UDB%WB]	;NO
	ENDIF.
	RETSKP
;ISIT20 - IS THE REMOTE CI SYSTEM A TOPS-20 SYSTEM?
; T2/ CI NODE NUMER
;	CALL ISIT20		;(T2/)
; RETURN +1: REMOTE IS NOT TOPS-20
;        +2: REMOTE IS TOPS-20
;
;PRESERVES ALL ACS
;
;[7.1072]
;IS7020 - IS THE REMOTE CI SYSTEM A TOPS-20 VERSION 7.0 SYSTEM?
; T2/ CI NODE NUMER
;	CALL IS7020		;(T2/)
; RETURN +1: REMOTE IS A 6.1 VERSION TOPS-20 SYSTEM
;        +2: REMOTE IS A VERSION 7.0 OR GREATER TOPS-20 SYSTEM
;
;PRESERVES ALL ACS

IS7020::SAVEAC <T1,T2,T3>	;[7.1072] 
	SETZ T3,		;[7.1072] Indicate entry to IS7020
	JRST ISITCD		;[7.1072] Continue at common code

ISIT20::SAVEAC <T1,T2,T3>	;[7.1072] 
	SETO T3,		;[7.1072] Indicate entry at ISIT20
ISITCD:	SKIPN T2,SBLIST(T2)	;[7.1072] IS THERE A REMOTE SYSTEM?
	RET			;NO
	MOVE T1,[BYTE (8) 124,55,62,60] ;YES, GET "T-20"
	CAME T1,.SBDST(T2)	;IS REMOTE "T-20"?
	RET			;NO
	SKIPE T3		;[7.1072] Called ISIT20?
	RETSKP			;[7.1072] Yes, so return success now
	LOAD T1,SBDVSW,(T2)	;[7.1072] Get the destination version number
	CAMN T1,[BYTE (8) 60,66,60,61]  ;[7.1072] Is it "0601"?
	RET   			;[7.1072] Yes, so this is a 6.1 system
	TLZ T1,776000		;[7.1072] Mask off first 8-bit byte
	CAMN T1,[BYTE (8) 0,60,60,66]  ;[7.1072] Is it "006"?
	RET			;[7.1072] Yes, so this is a 6.1 system
	RETSKP			;[7.1072] This is a 7.0 or greater system

;Subroutine to return the local port number.
;
; Usage:
;	Call
;	No args
;
;	Return (+1)
;	No KLIPA port
;
;	Return (+2)
;	T1/	Local port number
;
LOCPRT::SKIPN T1,CHNTAB+KLPRH2	;DO WE HAVE A CDB?
	RETBAD (KLPX7)		;NO, NO KLIPA
	SKIPGE T1,CDBNOD(T1)	;YES, DO WE HAVE OUR PORT NUMBER?
	RETBAD (KLPX10)		;NO
	RETSKP			;YES
;CHECK ON THE KLIPA
;	T1/ 0=) either path working
;	    pos=) path A working
;	    neg=) path B working
;RETURNS:	+1 FAILED
;		+2 SUCCESS

CIONLT::SKIPN T2,CHNTAB+KLPRH2	;POINT AT KLIPA CHANNEL
	RET			;NO KLIPA THERE!
	LOAD T2,CFSTA,(T2)	;GET STATE OF PORT
	CAIE T2,CHNRUN		;RUNNING?
	RET			;NO. CAN'T DO LOOPBACK NOW
	SKIPE T1		;EITHER WIRE OK?
	IFSKP.
	  SKIPE CIWIRA		;YES, WIRE A WORKING?
CIONL1:	  SKIPN CIWIRB		;NO, HOW ABOUT B?
	  RETSKP		;YES
	  RET			;NO
	ENDIF.
	JUMPL T1,CIONL1		;WANT WIRE B?
	SKIPE CIWIRA		;NO, IS A WORKING?
	RET			;NO
	RETSKP			;YES


;CLEAR THE PCB ERROR WORDS
;ACCEPTS:	Q3/ PCB
;RETURNS:	+1

RSTEWD:	SETZM .PBER0(Q3)	;ERROR WORD 0
	SETZM .PBER1(Q3)	;ERROR WORD 1
	SETZM .PBER2(Q3)	;ERROR WORD 2
	SETZM .PBER3(Q3)	;ERROR WORD 3
	SETZM .PBER4(Q3)	;ERROR WORD 4
	RET
;URDEAD - STOP, RESET, AND START THE CI
; Q3/ PCB
; P1/ CDB
;	CALL URDEAD		;(Q3,P1/)
; RETURN +1
;

URDEAD:	CIOFF
	CALL STPKLP		;(P1/) STOP THE PORT
	CALL CIGONE		;(Q3,P1/) RESET ALL CI ACTIVITY
	CION			;LET SCHEDULER
	CIOFF			; RUN
	CALL RLDKLP		;(P1/) RELOAD THE PORT
	CION
	RET


;CIGONE - THE CI HAS STOPPED
; Q3/ PCB
; P1/ CDB
;	CALL CIGONE		;(Q3,P1/)
; RETURN +1
;
;Assumed to be called at interrupt level or CIOFF and CI not enabled

CIGONE:	CALL NONODS		;(/) INFORM SCA OF DEPARTED NODES
	CALL RSTRID		;(/) RESET REQUEST-ID STATUS
	CALL RSTLKS		;(Q3/) RESET QUEUE INTERLOCKS IN PCB
	CALL CLNKLP		;(Q3,P1/) CLEAN THE QUEUES
	RET


;NONODS - TELL SCA ABOUT THE DISAPPEARANCE OF EACH NODE WITH AN OPEN VC
;	CALL NONODS		;(/)
; RETURN +1
;
;Assumed to be called at interrupt level or CIOFF

NONODS:	SAVEAC <Q2,P2,P4,P5>
	MOVSI P2,-C%SBLL
NONOD1:	SKIPN P5,SBLIST(P2)	;ANOTHER SB?
	JRST NONOD2		;NO
	SETZRO SBNTC,(P5)	;YES, NO LONGER NEED TO CLOSE
	SETZ Q2,
	SETO P4,
	CALL CLOSV1		;(Q2,P4,P5/) CLOSE THE VC AND TELL SCA
NONOD2:	AOBJN P2,NONOD1		;DO ALL SB
	RET
;RSTRID - RESET THE REQUEST-ID INFO
;	CALL RSTRID		;(/)
; RETURN +1
;
;Assumed to be called at interrupt level or CIOFF

RSTRID:	MOVSI T1,-<MAXNDS+1>	;AOBJN WORD FOR ALL NODES
RSTRI1:	SETZM RIDSTS(T1)	;RESET STATUS WORD
	SETZM RIDTIM(T1)	;RESET REQUEST-ID TIMER
	AOBJN T1,RSTRI1		;DO ALL NODES
	RET


;RSTLKS - CLEAR ALL QUEUE INTERLOCKS
; Q3/ PCB
;	CALL RSTLKS		;(Q3/)
; RETURN +1
;
;Assumed to be called at interrupt level or CIOFF and CI not enabled

RSTLKS:	SETOM .PBQ3I(Q3)	;COMMAND QUEUE 3
	SETOM .PBQ2I(Q3)	;COMMAND QUEUE 2
	SETOM .PBQ1I(Q3)	;COMMAND QUEUE 1
	SETOM .PBQ0I(Q3)	;COMMAND QUEUE 0
	SETOM .PBRQI(Q3)	;RESPONSE QUEUE
	SETOM .PBMFI(Q3)	;MESSAGE FREE QUEUE
	SETOM .PBDFI(Q3)	;DATAGRAM FREE QUEUE
	RET


;CLNKLP - CLEAN ALL QUEUES
; Q3/ PCB
; P1/ CDB
;	CALL CLNKLP		;(Q3,P1/)
; RETURN +1
;
;Assumed to be called at interrupt level or CIOFF and CI not enabled

CLNKLP:	XMOVEI T1,.PBRQI(Q3)	;GET RESPONSE QUEUE INTERLOCK WORD
	CALL CHKMPT		;IS RESPONSE QUEUE EMPTY?
	 SKIPA			;YES
	CALL KLPRQC		;(Q3,P1) NO, CLEAN THE RESPONSE QUEUE
	SETZ T1,		;CLEAN ALL QUEUES
	CALL CLENCQ		;(T1,Q3,P1) CLEAN THE COMMAND QUEUES
	RET
;CLEAN THE COMMAND QUEUES
;ACCEPTS:	T1/ 0 OR INTERLOCK WORD OF QUEUE WHICH IS BAD
;		Q3/ PCB
;		P1/ CDB
;RETURNS:	+1

;Caller should have closed all v.c.'s and notified SCA. Nothing should
;be queued after this call until the port has been restarted.

CLENCQ:	STKVAR <OLDQI,BADQI>	;OLDQI = LOOPER'S OLD QUEUE INTERLOCK
				;BADQI = BAD QUEUE INTERLOCK
	MOVEM T1,BADQI		;SAVE THE BAD QUEUE INTERLOCK
	MOVEI T1,.PBQ3I(Q3)	;GET COMMAND QUEUE 3 INTERLOCK
CLENC1:	MOVEM T1,OLDQI		;STASH THE INTERLOCK WORD
	SETOM .PBIWD(T1)	;CLEAR THE INTERLOCK
	CAME T1,BADQI		;THIS THE BAD ONE?
	IFSKP.
	  MOVEI T2,.PBFLI(T1)	;YES, GET THE FLINK
	  SUB T2,OFFSET		;WE NEED PHYSICAL ADDRESSES
	  MOVEM T2,.PBFLI(T1)	;MAKE FLINK POINT AT ITSELF
	  MOVEM T2,.PBBLI(T1)	;MAKE BLINK POINT AT FLINK
	ELSE.
	  CALL CLNCOM		;(T1,Q3,P1) NO, CLEAN THE QUEUE
	ENDIF.
	MOVE T1,OLDQI		;RETRIEVE THE QUEUE INTERLOCK
	ADDI T1,.PBBLI+1	;MOVE TO NEXT INTERLOCK
	CAIGE T1,.PBRQI(Q3)	;IS THIS THE RESPONSE QUEUE?
	JRST CLENC1		;NO, GO CLEAN IT UP
	RET			;YES, DONE

	ENDSV.
;CLEAN AN INDIVIDUAL COMMAND QUEUE
;ACCEPTS:	T1/ ADDRESS OF QUEUE'S INTERLOCK WORD
;		Q3/ PCB
;		P1/ CBD
;RETURNS:	+1

;Caller should have closed all v.c.'s and notified SCA. Nothing should
;be queued after this call until the port has been restarted.

CLNCOM:	STKVAR <IWORD>
	MOVEM T1,IWORD		;STASH INTERLOCK WORD
CLNCO1:	CALL REMQUE		;(T1/Q2) GET A PACKET FROM THE QUEUE
	 RET			;QUEUE EMPTY, DONE
	 NOP
	TMNN PKSCA,(Q2)		;SCA WANT THIS PACKET?
	IFSKP.

;The packet is being returned to SCA

	  MOVE T1,.PKSTS(Q2)	;YES, GET PACKET STATUS
	  LDB T2,PKYNOD		;GET NODE NUMBER
	  MOVE P5,SBLIST(T2)	;GET SB
	  SETO P3,		;SAY PACKET WAS LOCALLY-GENERATED
	  CIOFF			;SCA EXPECTS TO BE CALLED AT INTERRUPT LEVEL
	  CALL GIVSC1		;(T1,Q2,P3,P5) GIVE IT TO SCA
	  CION
	ELSE.
;The packet is not being returned to SCA

	  SETZRO PKSRB,(Q2)	;CLEAR ALL SOFTWARE RESPONSE BITS
	  LDB T3,PKYOP		;GET OP CODE FROM PACKET
	  MOVSI T2,-<KLPOPL>	;MAKE AOBJN WORD FOR OPCODE SEARCH
CLNCO2:	  CAMN T3,KLPOPS(T2)	;THIS THE ONE?
	  IFSKP.
	    AOBJN T2,CLNCO2	;NO, TRY NEXT OPCODE
	    BUG. (CHK,KLPBOP,PHYKLP,SOFT,<PHYKLP - Bad op code on command queue>,<<T3,BOC>>,<

Cause:	A packet with an illegal op code was found while purging the 
	command queue.

Action:	If this happens frequently, use the SCAMPI and PHYKLP ring buffers to
	try to discover how such a packet is being created.

Data:	BOC - the bad code
>)
	  ELSE.
	    CALL @RETCLO(T2)	;(Q2,Q3) RETURN THE BUFFER TO ITS QUEUE
	  ENDIF.
	ENDIF.
	MOVE T1,IWORD		;RETRIEVE INTERLOCK WORD
	JRST CLNCO1		;GO GET NEXT PACKET

	ENDSV.
;RSTQS - RESET THE PCB QUEUES
; Q3/ PCB
;	CALL RSTQS		;(Q3/)
;RETURN +1

RSTQS:	MOVEI T1,.PBQ3I(Q3)	;GET INTERLOCK WORD OF FIRST QUEUE
RSTQS1:	SETOM .PBIWD(T1)	;SET INTERLOCK WORD
	MOVEI T2,.PBFLI(T1)	;GET FLINK
	SUB T2,OFFSET		;WE NEED PHYSICAL ADDRESSES
	MOVEM T2,.PBFLI(T1)	;MAKE FLINK POINT AT ITSELF
	MOVEM T2,.PBBLI(T1)	;MAKE BLINK POINT AT FLINK
	ADDI T1,.PBBLI+1	;MOVE TO NEXT INTERLOCK
	CAIGE T1,.PBQND(Q3)	;ANYMORE QUEUES?
	JRST RSTQS1		;YES, GO DO IT
	RET			;NO, DONE


;STKDFQ - STOCK THE DATAGRAM FREE QUEUE
; P1/ CBD
;	CALL STKDFQ		;(P1/)
; RETURN +1

STKDFQ:	SAVEPQ
	STKVAR <NXTBUF>		;NXTBUF - NEXT BUFFER ADDRESS
	MOVEI T1,2*MAXNDS	;GET 2 DATAGRAM BUFFERS FOR EACH NODE
	CALL SC.ALD		;(T1/T1,T2,T3) GET THE BUFFERS
	 BUG. (HLT,KLPNOD,PHYKLP,SOFT,<PHYKLP - Can't stock datagram free queue>,,<

Cause:	The CALL SC.ALD failed.  SCA can't handle the request.
>)
	MOVE Q2,T1		;POSITION THE FIRST DATAGRAM ADDRESS
	MOVE Q3,CDBPCB(P1)	;GET PCB ADDRESS
	XMOVEI T1,.PBDFI(Q3)	;QUEUE ON WHICH TO INSERT PACKET
STKDF1:	MOVE T2,(Q2)		;GET NEXT DATAGRAM ADDRESS
	MOVEM T2,NXTBUF		;SAVE IT
	CALL PUTQUE		;(T1,Q2) INSERT THIS BUFFER ON QUEUE
	 JFCL			;QUEUE WAS EMPTY, THAT'S OK
	MOVE Q2,NXTBUF		;GET NEXT DATAGRAM
	JUMPN Q2,STKDF1		;IF NONE, WE'RE DONE
	RET

	ENDSV.
	TNXEND
	END