Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_SRC_1_19910112 - 6-1-monitor/physio.mac
There are 56 other files named physio.mac in the archive. Click here to see a list.
;[SRI-NIC]XS:<SU-61SU>PHYSIO.MAC.2,  5-Dec-86 15:54:01, Edit by MKL
;;[SRI-NIC]SS:<6-1-MONITOR>PHYSIO.MAC.3, 30-Oct-85 20:22:45, Edit by MKL
;; change some 'IFx STANSW' to 'IFy NICSW' in some MEIS code

; *** Edit 7312 to PHYSIO.MAC by LOMARTIRE on 3-Jun-86
; Take MS%SVD out from under DEBUG conditional 
; *** Edit 7264 to PHYSIO.MAC by MCCOLLUM on 11-Mar-86, for SPR #21150
; Set up NPWQPD BUGCHK with channel, controller, and unit as data 
;------------------------- Autopatch Tape # 13 -------------------------
; *** Edit 7247 to PHYSIO.MAC by LOMARTIRE on 19-Feb-86
; Implement OFN caching 
;Edit 7247 - Check DRMIO/DSKIO to see if any cached OFN pages are transfered
;------------------------- Autopatch Tape # 12 -------------------------
; *** Edit 7193 to PHYSIO.MAC by WONG on 14-Nov-85
; Fix undefined symbol (LPTTIM) when LPTN=0
; Edit 7157 to PHYSIO.MAC by TBOYLE on 15-Oct-85 (TCO 6-1-1526)
; Remove IORB Retry, edit 7137 did not make it in. 
;Remove IORB retry code for RP20's as it causes more problems than it solves.
; at HNGIRB and HNGIR2 do not make RP20's set once a minute check.
; reomve SETOMS routine.
; Edit 7154 to PHYSIO.MAC by GRANT on 15-Oct-85
; Fix bug which prevents monitor from finding all the disks ported to the FE. 
;Fix routines PHYFED and FESET.
; Edit 7137 to PHYSIO.MAC by TBOYLE on 15-Aug-85 (TCO 6-1-1526)
; Remove IORB retry code. 
; UPD ID= 2308, SNARK:<6.1.MONITOR>PHYSIO.MAC.204,   9-Aug-85 15:13:09 by TBOYLE
;Remove IORB retry code for RP20's as it causes more problems than it solves.
; at HNGIRB and HNGIR2 do not make RP20's set once a minute check.
; reomve SETOMS routine.
;<6-1-MONITOR.FT6>PHYSIO.MAC.2, 12-Aug-85 17:53:32, Edit by WHP4
;Stanford changes:
; Code at INT4 makes sure it is looking at a UDB before seeing if the
;  device is dual ported.  Screws up MEIS's, tapes, etc.
; Support MEIS device
; Enter TA78 in NAMUTP table
;
; UPD ID= 2282, SNARK:<6.1.MONITOR>PHYSIO.MAC.203,  25-Jun-85 15:24:14 by GRANT
;TCO 6.1.1473 - Check for UDB%MA in UPDPDB.
; UPD ID= 2264, SNARK:<6.1.MONITOR>PHYSIO.MAC.202,  21-Jun-85 12:41:04 by GRANT
;TCO 6.1.1468 - Change PHYTPD to PHYCPI and improve the description
; UPD ID= 2166, SNARK:<6.1.MONITOR>PHYSIO.MAC.201,   5-Jun-85 10:43:40 by MCCOLLUM
;TCO 6.1.1406  - Update copyright notice.
; UPD ID= 2024, SNARK:<6.1.MONITOR>PHYSIO.MAC.200,  28-May-85 12:14:51 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1927, SNARK:<6.1.MONITOR>PHYSIO.MAC.199,   7-May-85 21:46:55 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1850, SNARK:<6.1.MONITOR>PHYSIO.MAC.198,  30-Apr-85 13:47:32 by MCCOLLUM
;TCO 6.1.1238 - Fix BUG. documentation
; UPD ID= 1835, SNARK:<6.1.MONITOR>PHYSIO.MAC.197,  26-Apr-85 11:19:52 by MCCOLLUM
;Change PHYDCD and PHYDCU to BUGINF's
; UPD ID= 1779, SNARK:<6.1.MONITOR>PHYSIO.MAC.196,  23-Apr-85 08:52:22 by GRANT
;TCO 6.1.1335 - In PHYDUA, remove code which revented switching a dual-ported
;disk from one channel to the other.
; UPD ID= 1761, SNARK:<6.1.MONITOR>PHYSIO.MAC.195,  17-Apr-85 13:13:49 by GRANT
;TCO 6.1.1325 - change console message when disk is forced offline
; UPD ID= 1680, SNARK:<6.1.MONITOR>PHYSIO.MAC.194,  25-Mar-85 12:04:38 by LOMARTIRE
;TCO 6.1.1286 - Return new MS%IAC if offline due to homeblock checking
; UPD ID= 1641, SNARK:<6.1.MONITOR>PHYSIO.MAC.193,  15-Mar-85 08:24:55 by GRANT
;TCO 6.1.1272 - Rewrite routine UPDPDB (no logic changes)
; UPD ID= 1616, SNARK:<6.1.MONITOR>PHYSIO.MAC.192,  12-Mar-85 09:05:53 by GRANT
;TCO 6.1.1235 - In routine CHKPDB, check for SIXBIT/DONOCA/ instead of non-zero
; UPD ID= 1585, SNARK:<6.1.MONITOR>PHYSIO.MAC.191,   5-Mar-85 10:42:58 by GRANT
;More TCO 6.1.1220 - Put check for MS%SVD under debug
; UPD ID= 1565, SNARK:<6.1.MONITOR>PHYSIO.MAC.190,  25-Feb-85 12:33:14 by GRANT
;TCO 6.1.1220 - In GETSTR, check for unit being served
; UPD ID= 1555, SNARK:<6.1.MONITOR>PHYSIO.MAC.189,  20-Feb-85 17:29:25 by GRANT
;TCO 6.1.1200 - Create routine SETDSN and remove UDBDSH setting from routine PHYDUA.
; UPD ID= 1526, SNARK:<6.1.MONITOR>PHYSIO.MAC.188,  18-Feb-85 11:20:52 by GRANT
;TCO 6.1.1201 - In PHYDUA, change P3 to P1 so we correctly get CDBSTS.
; UPD ID= 1506, SNARK:<6.1.MONITOR>PHYSIO.MAC.187,  12-Feb-85 10:25:25 by GRANT
;TCO 6.1.1189 - Move some code from CLRPDB to CHKPDB and create RSTPDB and a
;new CLRPDB.
; UPD ID= 1501, SNARK:<6.1.MONITOR>PHYSIO.MAC.186,  12-Feb-85 07:57:31 by GRANT
;TCO 6.1.1187 - In UPDPDB, clear U1.OFS at UPDBYE.
; UPD ID= 1497, SNARK:<6.1.MONITOR>PHYSIO.MAC.185,  11-Feb-85 09:01:37 by GRANT
;TCO 6.1.1184 - In UPDPDB, check for other system being a 20 when REQUEST-IDs
;are being answered but there is no CFS connection.
; UPD ID= 1487, SNARK:<6.1.MONITOR>PHYSIO.MAC.184,   7-Feb-85 08:33:26 by GRANT
;TCO 6.1.1180 - In CLRPDB, change SKIPGE to SKIPL so PTHSTS gets called.
; UPD ID= 1430, SNARK:<6.1.MONITOR>PHYSIO.MAC.183,  31-Jan-85 07:54:00 by GRANT
;TCO 6.1.1164 - In CHKPDB, remove special check for RP20.
; UPD ID= 1397, SNARK:<6.1.MONITOR>PHYSIO.MAC.182,  23-Jan-85 16:12:43 by GRANT
;TCO 6.1.1153 - Add PHYDCU, PHYDCD, and PHYDCR BUGxxx for DON'T-CARE status
; UPD ID= 1363, SNARK:<6.1.MONITOR>PHYSIO.MAC.181,  18-Jan-85 22:02:18 by GRANT
;Routine headers, comments, coding conventions, etc.
; UPD ID= 1351, SNARK:<6.1.MONITOR>PHYSIO.MAC.180,  16-Jan-85 16:43:30 by MOSER
;TCO 6.1.1139 - *PERFORMANCE* - CHANGE PSKED REFS TO PSKD1
; UPD ID= 1326, SNARK:<6.1.MONITOR>PHYSIO.MAC.179,  14-Jan-85 13:57:31 by GRANT
;More TCO 6.1.1116 - Missing AC
; UPD ID= 1282, SNARK:<6.1.MONITOR>PHYSIO.MAC.178,   7-Jan-85 09:04:00 by GRANT
;More TCO 6.1.1116 - Check for don't-care, too.
; UPD ID= 1280, SNARK:<6.1.MONITOR>PHYSIO.MAC.177,   7-Jan-85 08:34:44 by GRANT
;TCO 6.1.1116 - In GETSTR, add checking for front-end disks.
; UPD ID= 1228, SNARK:<6.1.MONITOR>PHYSIO.MAC.176,  19-Dec-84 16:18:14 by HAUDEL
;TCO 6.1.1095 - Set US.OIR when setting US.BOT for overdue tape rewind done.
; UPD ID= 1227, SNARK:<6.1.MONITOR>PHYSIO.MAC.175,  19-Dec-84 15:01:14 by TBOYLE
;Change PDV.. to PDB...
; UPD ID= 1221, SNARK:<6.1.MONITOR>PHYSIO.MAC.174,  18-Dec-84 13:09:05 by MCLEAN
;FIX FOR TPD SERVER DISKS THRU THE SERVER
; UPD ID= 1194, SNARK:<6.1.MONITOR>PHYSIO.MAC.173,  12-Dec-84 14:57:45 by TBOYLE
;Change BUGCHK name of PDVSTA to PDBSTA.
; UPD ID= 1111, SNARK:<6.1.MONITOR>PHYSIO.MAC.172,  20-Nov-84 15:35:52 by MCLEAN
; UPD ID= 5079, SNARK:<6.MONITOR>PHYSIO.MAC.172,  20-Nov-84 15:24:08 by MCLEAN
;FIX JUMPE IN UPDXIT-1
; UPD ID= 5076, SNARK:<6.MONITOR>PHYSIO.MAC.171,  19-Nov-84 14:10:40 by MCLEAN
;INSURE PDB ALWAYS GETS CLEARED ON SINGLE PORT NO MATTER WHAT.
; UPD ID= 5065, SNARK:<6.MONITOR>PHYSIO.MAC.170,   7-Nov-84 13:22:14 by MOSER
;TCO 6.2271 - ADD CHKCKS,ADVCKS,FNDCKS FOR "RELATIVE" UNIT NUMBERING
; UPD ID= 5042, SNARK:<6.MONITOR>PHYSIO.MAC.169,  30-Oct-84 15:33:48 by MCLEAN
;REMOVE DEFINITION TO PDBLEN
; UPD ID= 5035, SNARK:<6.MONITOR>PHYSIO.MAC.168,  29-Oct-84 16:28:30 by MCLEAN
;SOME FIXES FOR NON-CI DISKS
; UPD ID= 5032, SNARK:<6.MONITOR>PHYSIO.MAC.167,  29-Oct-84 13:34:53 by MCLEAN
;FIX MESSED UP UDBSTR REFERENCE IN UNIMES
; UPD ID= 4992, SNARK:<6.MONITOR>PHYSIO.MAC.166,  24-Oct-84 17:22:44 by MCLEAN
;ADD PHYSTC CALL TO DCUNIT
; UPD ID= 4991, SNARK:<6.MONITOR>PHYSIO.MAC.165,  24-Oct-84 16:30:14 by MCLEAN
;RE-ORDER US.CHB AND U1.STC SO STC IS FIRST
; UPD ID= 4987, SNARK:<6.MONITOR>PHYSIO.MAC.164,  24-Oct-84 13:07:58 by MCLEAN
;EXTRANEOUS POP T2 IN UDSKIO
; UPD ID= 4980, SNARK:<6.MONITOR>PHYSIO.MAC.163,  23-Oct-84 14:42:53 by MCLEAN
;FIX SETTING DRIVE U1.OFS ONLINE WHEN SETTING DON'T CARE BIT
; UPD ID= 4977, SNARK:<6.MONITOR>PHYSIO.MAC.162,  22-Oct-84 16:32:15 by GRANT
;Remove references to FTCI
; UPD ID= 4970, SNARK:<6.MONITOR>PHYSIO.MAC.161,  22-Oct-84 11:26:33 by GRANT
;In CHK8, missing index register in previous edit.
; UPD ID= 4969, SNARK:<6.MONITOR>PHYSIO.MAC.160,  22-Oct-84 10:00:16 by MCLEAN
;FIX SOME WORD REFERENCES TO UDBSTR
; UPD ID= 4963, SNARK:<6.MONITOR>PHYSIO.MAC.159,  18-Oct-84 20:43:48 by MCLEAN
;ANOTHER FIX TO CHK20A
; UPD ID= 4962, SNARK:<6.MONITOR>PHYSIO.MAC.158,  18-Oct-84 20:34:49 by MCLEAN
;FIX DON'T CARE DISK  ALSO FIX NO CI CASE
; UPD ID= 4950, SNARK:<6.MONITOR>PHYSIO.MAC.157,  17-Oct-84 15:49:33 by MCLEAN
;MAKE DON'T CARE ONLY WORK FOR SETTING BIT
; UPD ID= 4949, SNARK:<6.MONITOR>PHYSIO.MAC.156,  17-Oct-84 15:43:42 by MCLEAN
;FIX DCUNIT
; UPD ID= 4942, SNARK:<6.MONITOR>PHYSIO.MAC.155,  16-Oct-84 15:24:59 by MCLEAN
;SUPPORT FOR OVERDUE DATA REQUESTS OF RP20'S.
; UPD ID= 4939, SNARK:<6.MONITOR>PHYSIO.MAC.154,  15-Oct-84 13:12:05 by GRANT
;The assembly switch CFSCOD has been eliminated
; UPD ID= 4926, SNARK:<6.MONITOR>PHYSIO.MAC.153,  15-Oct-84 10:35:54 by MCLEAN
;FIX FOR OFFLINE WHEN CFS CALLS TO SAY OFFLINE
; UPD ID= 4889, SNARK:<6.MONITOR>PHYSIO.MAC.152,  30-Sep-84 20:08:28 by MCLEAN
;FIX SERIAL NUMBER PRINTOUT. 
;tco 6.2232
; UPD ID= 4881, SNARK:<6.MONITOR>PHYSIO.MAC.151,  25-Sep-84 23:25:32 by MCLEAN
;UPDATE UPDPDB TO INCLUDE CHECKS FOR NON-CI PROCESSORS
; UPD ID= 4865, SNARK:<6.MONITOR>PHYSIO.MAC.150,  24-Sep-84 14:34:41 by MCLEAN
;FIX CLRPDB FOR CDBNOD -1
; UPD ID= 4858, SNARK:<6.MONITOR>PHYSIO.MAC.149,  20-Sep-84 11:13:35 by MCLEAN
;FIX MESSED UP CHECK FOR DOP%PS AND SECTOR SIZE WRITTEN
;FIX MESSED UP BUGCHK MESSAGE
; UPD ID= 4853, SNARK:<6.MONITOR>PHYSIO.MAC.148,  17-Sep-84 14:01:13 by MCLEAN
;REMOVE PRTTBU
; UPD ID= 4828, SNARK:<6.MONITOR>PHYSIO.MAC.147,  17-Sep-84 10:44:09 by PURRETTA
;Update copyright notice
; UPD ID= 4821, SNARK:<6.MONITOR>PHYSIO.MAC.146,  17-Sep-84 10:17:02 by MCLEAN
;FIX TXNE TO TDNE
; UPD ID= 4795, SNARK:<6.MONITOR>PHYSIO.MAC.145,   9-Sep-84 20:32:06 by MCLEAN
;ADD CHANNEL SKIP COMMAND FOR RP20'S
; UPD ID= 4791, SNARK:<6.MONITOR>PHYSIO.MAC.144,   5-Sep-84 21:39:51 by MCLEAN
;FIX UNITRY TO START HOMEBLOCK REQUESTS FIRST
; UPD ID= 4789, SNARK:<6.MONITOR>PHYSIO.MAC.143,   4-Sep-84 14:45:18 by MCLEAN
;FIX PARTIAL PAGE TRANSFERS AT UIO3
; UPD ID= 4787, SNARK:<6.MONITOR>PHYSIO.MAC.142,  31-Aug-84 20:38:01 by MCLEAN
;FIX PYCOFF COMMENTS TO IMPLY NO T3 REQUIRED
; UPD ID= 4761, SNARK:<6.MONITOR>PHYSIO.MAC.141,  27-Aug-84 13:38:28 by MCLEAN
;FIX SKIPE PROINI TO SKIPE PROFLG
; UPD ID= 4754, SNARK:<6.MONITOR>PHYSIO.MAC.140,  26-Aug-84 21:07:11 by MCLEAN
;THE GREAT CHANGE FOR PROTECTING DUAL PORTED DISKS
; UPD ID= 4700, SNARK:<6.MONITOR>PHYSIO.MAC.138,  15-Aug-84 22:39:24 by MCLEAN
;FIX PHYINT JRST TO INT2 TO ZERO P5
; UPD ID= 4629, SNARK:<6.MONITOR>PHYSIO.MAC.137,  29-Jul-84 22:40:38 by MCLEAN
;FIX PHYALL ADD Q1,T3 TO ADD T3,Q1
; UPD ID= 4626, SNARK:<6.MONITOR>PHYSIO.MAC.136,  29-Jul-84 10:07:01 by PAETZOLD
;TCO 6.2152 - Fix code at UPDPD1 to not cause PITRAPs.
; UPD ID= 4604, SNARK:<6.MONITOR>PHYSIO.MAC.135,  27-Jul-84 13:01:38 by MCLEAN
;FIX MISSING INSTRUCTION IN PHYALL
; UPD ID= 4590, SNARK:<6.MONITOR>PHYSIO.MAC.134,  26-Jul-84 10:29:55 by MCLEAN
;MAKE PHYALC ONLY ALLOCATE ON PAGE BOUNDARY'S
; UPD ID= 4589, SNARK:<6.MONITOR>PHYSIO.MAC.133,  25-Jul-84 21:30:02 by MCLEAN
;OPTIMIZATION OF PHYSTC SO THAT IT DOESN'T CHECK FED AND DCD DISK'S
; UPD ID= 4584, SNARK:<6.MONITOR>PHYSIO.MAC.132,  24-Jul-84 22:29:33 by MCLEAN
;MORE FIXES FOR HOME BLOCK CHECKING
; UPD ID= 4575, SNARK:<6.MONITOR>PHYSIO.MAC.131,  21-Jul-84 18:58:49 by MCLEAN
;PUT IN MISSING LABEL
; UPD ID= 4574, SNARK:<6.MONITOR>PHYSIO.MAC.130,  20-Jul-84 22:32:58 by MCLEAN
;FIX STRTIO SO IT DOESN'T GO TO SETOIR AND LEAVE REQUESTS ON
;TWQ FOR THE CI
; UPD ID= 4573, SNARK:<6.MONITOR>PHYSIO.MAC.129,  20-Jul-84 15:18:15 by MCLEAN
;CHANGE UNIT CHECKING CODE FOR CI
; UPD ID= 4571, SNARK:<6.MONITOR>PHYSIO.MAC.128,  19-Jul-84 19:25:46 by MCLEAN
;GOT CARRIED AWAY REMOVING CODE FROM UPDPDB
; UPD ID= 4563, SNARK:<6.MONITOR>PHYSIO.MAC.127,  18-Jul-84 20:30:26 by MCLEAN
;FIX RANDOM SETZ IN UPDPDB
; UPD ID= 4560, SNARK:<6.MONITOR>PHYSIO.MAC.126,  18-Jul-84 18:29:31 by MCLEAN
;MORE CHANGES FOR HOME BLOCK CHECKS
; UPD ID= 4430, SNARK:<6.MONITOR>PHYSIO.MAC.125,   4-Jul-84 22:15:50 by MCLEAN
;ADD CHANGES FOR NEW HOME BLOCK AND PDB BLOCK
; UPD ID= 4359, SNARK:<6.MONITOR>PHYSIO.MAC.124,  18-Jun-84 16:59:44 by MCLEAN
;FIX FIXIRB FOR INDEX REGISTER FOR SECPAG
; UPD ID= 4331, SNARK:<6.MONITOR>PHYSIO.MAC.123,  13-Jun-84 21:22:32 by MCLEAN
;MANY CHANGE FOR DOP%PS
; UPD ID= 4253, SNARK:<6.MONITOR>PHYSIO.MAC.120,  29-May-84 22:19:28 by MCLEAN
;MAKE CHANGES FOR DOP%PS
; UPD ID= 4239, SNARK:<6.MONITOR>PHYSIO.MAC.119,  23-May-84 12:21:48 by MCLEAN
;FIX THREE PORTED DISKS NOT TO CHECK HOME BLOCKS
; UPD ID= 4193, SNARK:<6.MONITOR>PHYSIO.MAC.118,   9-May-84 12:10:18 by MOSER
;MORE TCO 6.1562 - REMOVE PHYIF AND PHYION USE A FASTER METHOD
; UPD ID= 4189, SNARK:<6.MONITOR>PHYSIO.MAC.117,   8-May-84 23:57:11 by MCLEAN
;MOVE UNIC12 BACK 1 INSTRUCTION
; UPD ID= 4113, SNARK:<6.MONITOR>PHYSIO.MAC.116,  24-Apr-84 11:56:18 by MCLEAN
;PREVENT BUGHLT WHEN SWITCHING FROM CI TO NON-CI DISK
; UPD ID= 4100, SNARK:<6.MONITOR>PHYSIO.MAC.115,  18-Apr-84 19:36:30 by MCLEAN
;ADD PHYMKL TO KILL IORBS FOR CI TAPES
; UPD ID= 4070, SNARK:<6.MONITOR>PHYSIO.MAC.114,  11-Apr-84 19:17:51 by MOSER
;TCO 6.2025 - DON'T REPORT 3-PORTED DISK INFO RETURN DIAGX9
; UPD ID= 4056, SNARK:<6.MONITOR>PHYSIO.MAC.113,  10-Apr-84 07:31:23 by HAUDEL
;TCO 6.2021 - Change a SAVEQ to a SAVEPQ at PHYRWD
; UPD ID= 3977, SNARK:<6.MONITOR>PHYSIO.MAC.112,  26-Mar-84 19:56:44 by GRANT
;In GETSTR, add another check for off-line.
; UPD ID= 3959, SNARK:<6.MONITOR>PHYSIO.MAC.111,  22-Mar-84 06:55:49 by GRANT
;In GETSTR, enhance meaning of dual-ported bit MS%2PT
; UPD ID= 3957, SNARK:<6.MONITOR>PHYSIO.MAC.110,  21-Mar-84 16:41:29 by MCLEAN
;FIX DONIRB FOR VERIFICATION WITH HSC50'S
; UPD ID= 3781, SNARK:<6.MONITOR>PHYSIO.MAC.109,  28-Feb-84 13:15:47 by MOSER
;MORE 6.1562 - CHANGE PHYIOF TO PHYIF
; UPD ID= 3775, SNARK:<6.MONITOR>PHYSIO.MAC.108,  28-Feb-84 10:26:45 by MOSER
;TCO 6.1562 - ALLOW PHYSIO TO BE CALLED (AT SIO1) BY INTERRUPT LEVEL
; ROUTINES. IMPLEMENT IOON AND IOOFF MACROS AND PHYION AND PHYIOF ROUTINES.
; UPD ID= 3699, SNARK:<6.MONITOR>PHYSIO.MAC.107,  18-Feb-84 11:04:00 by PAETZOLD
;TCO 6.1973 - Range check IORB addresses in GIVIRB.  Add BADIRB BUGHLT.
; UPD ID= 3645, SNARK:<6.MONITOR>PHYSIO.MAC.106,   2-Feb-84 12:53:04 by MURPHY
;Get rid of useless PHYALZ and what it references.
; UPD ID= 3611, SNARK:<6.MONITOR>PHYSIO.MAC.105,  31-Jan-84 21:37:35 by MCLEAN
;FIX ERRFIN TO GET CORRECT UNIT TYPE
; UPD ID= 3580, SNARK:<6.MONITOR>PHYSIO.MAC.104,  28-Jan-84 16:36:59 by MCLEAN
;MAKE DEVICE NAME NODE INSTEAD OF HSC50 SINCE IT COULD BE A REMOTE SERVER
; UPD ID= 3505, SNARK:<6.MONITOR>PHYSIO.MAC.103,  22-Jan-84 16:25:42 by MCLEAN
;ADD LATEST TPD CHANGES TO PERMIT MASSBUS DISK TO TAKE CONTROL
; UPD ID= 3471, SNARK:<6.MONITOR>PHYSIO.MAC.102,  16-Jan-84 19:24:47 by MCLEAN
;FIX PROBLEM WITH DEVICE CODE 0 FOR SYSERR ENTRY
; UPD ID= 3465, SNARK:<6.MONITOR>PHYSIO.MAC.101,  16-Jan-84 12:54:41 by MCLEAN
;FIX PHYTPD AND FRIENDS
; UPD ID= 3453, SNARK:<6.MONITOR>PHYSIO.MAC.100,  12-Jan-84 20:32:33 by MCLEAN
;FIX BUGS IN CHK11 CODE FOR MULTIPLE UNITS SWITCHED.
; UPD ID= 3423, SNARK:<6.MONITOR>PHYSIO.MAC.99,   8-Jan-84 17:11:26 by MCLEAN
;SET HIGH ORDER SERIAL NUMBER AND USE OF US.TPD
; UPD ID= 3327, SNARK:<6.MONITOR>PHYSIO.MAC.98,  14-Dec-83 23:38:49 by MCLEAN
; INSURE THAT SWITCHING UDB'S FOR CI DISKS MOVES ALL THE STUFF TO
;THE CORRECT UNIT
; UPD ID= 3326, SNARK:<6.MONITOR>PHYSIO.MAC.97,  14-Dec-83 17:43:04 by MOSER
;TCO 6.1562 - ADD CALLS TO MSCP SERVER ONLINE AND OFFLINE
; UPD ID= 3283, SNARK:<6.MONITOR>PHYSIO.MAC.96,   9-Dec-83 23:08:16 by MCLEAN
;LAST EDIT DIDN'T MAKE IT.   REMOVE OVRDTA FOR CI
; UPD ID= 3278, SNARK:<6.MONITOR>PHYSIO.MAC.94,   7-Dec-83 19:27:43 by MCLEAN
;FIX UNITRY TO FORGET RETRY FOR NOW ON CI DISKS
; UPD ID= 3274, SNARK:<6.MONITOR>PHYSIO.MAC.93,   7-Dec-83 15:20:42 by MCLEAN
;SOME CLEANUP/REMOVAL OF EXTRANEOUS MSCP STUFF
; UPD ID= 3242, SNARK:<6.MONITOR>PHYSIO.MAC.92,   1-Dec-83 11:11:51 by MCLEAN
;NOIORB BUGHLT FIX FOR HSC50'S DURING POLLING
; UPD ID= 3238, SNARK:<6.MONITOR>PHYSIO.MAC.91,  30-Nov-83 19:46:43 by MCLEAN
;MAKE SPECIAL ENTRY FOR HSC BAT BLOCK ROUTINE IN JOB 0
; UPD ID= 3207, SNARK:<6.MONITOR>PHYSIO.MAC.90,  20-Nov-83 20:07:08 by MCLEAN
;TCO 6.1873 MAKE UNIMES FIND IT'S OWN P1 & P2 SO THAT UNIT SWITCHED
;AND OTHERS DON'T NEED ANYTHING BUT P3
; UPD ID= 3206, SNARK:<6.MONITOR>PHYSIO.MAC.89,  20-Nov-83 19:43:15 by MCLEAN
;ANOTHER EXTENDED ADDRESSING FIX... MOVTAB NEEDS IFIW
; UPD ID= 3202, SNARK:<6.MONITOR>PHYSIO.MAC.88,  19-Nov-83 21:46:40 by MCLEAN
;MAKE PHYDUA SAVE Q REGISTERS ALSO
; UPD ID= 3182, SNARK:<6.MONITOR>PHYSIO.MAC.87,  17-Nov-83 14:06:49 by MCLEAN
;SAVEAC (P1) SHOULD BE SAVEAC <P1>
; UPD ID= 3166, SNARK:<6.MONITOR>PHYSIO.MAC.86,  16-Nov-83 17:02:56 by MCLEAN
;REMOVE ANOTHER S0.ENT
; UPD ID= 3164, SNARK:<6.MONITOR>PHYSIO.MAC.85,  16-Nov-83 14:41:56 by MCLEAN
;RESET TIMER ON OVERDUE HOME BLOCK CHECK AND REMOVE SOME S0.ENT'S
; UPD ID= 3142, SNARK:<6.MONITOR>PHYSIO.MAC.84,  14-Nov-83 14:24:41 by MCLEAN
;NEED TO CHECK FOR UDB IN LATENCY OPTIMIZATION CALL
; UPD ID= 3133, SNARK:<6.MONITOR>PHYSIO.MAC.83,   9-Nov-83 20:18:20 by MCLEAN
;TCO 6.1818 REMOVE RSCOD (SEC0)
; UPD ID= 3129, SNARK:<6.MONITOR>PHYSIO.MAC.82,   9-Nov-83 16:59:13 by MCLEAN
;MORE TCO 1850
; UPD ID= 3124, SNARK:<6.MONITOR>PHYSIO.MAC.81,   9-Nov-83 11:04:58 by MCLEAN
;ADD PORT RELEASE FOR EXPIRED FAIRNESS COUNT
; UPD ID= 3105, SNARK:<6.MONITOR>PHYSIO.MAC.80,   7-Nov-83 13:35:19 by MCLEAN
;TCO 1850 ILTWQP BUGHLT CAUSED BY REMOVAL OF ENTRY WHILE ON PWQ
; UPD ID= 3001, SNARK:<6.MONITOR>PHYSIO.MAC.79,   5-Oct-83 20:13:01 by MCLEAN
;TCO 6.1818 RE-ADJUST CODE FOR SECTION 1 OPERATION
; UPD ID= 2985, SNARK:<6.MONITOR>PHYSIO.MAC.78,   4-Oct-83 16:39:37 by MCLEAN
;TCO 1713 COMMON FILE SUPPORT OF NEW PROBLEM ON DEVICE MESSAGE
; UPD ID= 2939, SNARK:<6.MONITOR>PHYSIO.MAC.77,  27-Sep-83 09:45:14 by GRANT
;In PHYINI, check P4 before updating MAXCHN
; UPD ID= 2812, SNARK:<6.MONITOR>PHYSIO.MAC.76,   9-Aug-83 11:52:03 by MCINTEE
;TCO 6.1762 - Make UNICHK run in section 1 when it calls ELOGOO, PSIRQ, or
;  references fork tables.
; UPD ID= 2810, SNARK:<6.MONITOR>PHYSIO.MAC.75,   9-Aug-83 11:47:42 by MURPHY
;TCO 6.1525 - Use RESCD(SEC0) to indicate code must be in section 0.
; UPD ID= 2781, SNARK:<6.MONITOR>PHYSIO.MAC.74,   1-Aug-83 08:31:35 by HAUDEL
;TCO 6.1741 - CHANGE FLAG TESTING AC FROM P1 TO CX AT PHYXF2:
; UPD ID= 2777, SNARK:<6.MONITOR>PHYSIO.MAC.73,  28-Jul-83 14:00:30 by MCLEAN
;MAKE SETUD1 RETURN -1 FOR P3
; UPD ID= 2752, SNARK:<6.MONITOR>PHYSIO.MAC.72,  23-Jul-83 02:10:59 by MCLEAN
;TCO 6.1749 MAKE SETUDB RETURN SOMETHING VALID IN P3 AT SETUD1
; UPD ID= 2659, SNARK:<6.MONITOR>PHYSIO.MAC.71,   3-Jul-83 20:32:44 by MCLEAN
;PREVIOUS FIX WAS UNNECESSARY WE MUST REMOVE CI CODE COMPLETELY AND USE IS.DTE
;TO INICATE BAT BLOCK LOGIC REQUIRED.
; UPD ID= 2637, SNARK:<6.MONITOR>PHYSIO.MAC.70,  26-Jun-83 10:37:04 by MCLEAN
;TCO 6.1706 PERMIT BAT BLOCK LOGIC.
; UPD ID= 2605, SNARK:<6.MONITOR>PHYSIO.MAC.69,  20-Jun-83 16:07:39 by HALL
;TCO 6.1689 - Move fork tables to extended section
;	Reference FKJOB via DEFSTR
; UPD ID= 2540, SNARK:<6.MONITOR>PHYSIO.MAC.68,  31-May-83 14:02:19 by MILLER
;TCO 6.1610. Yet more work on PHYUPR and friends
; UPD ID= 2538, SNARK:<6.MONITOR>PHYSIO.MAC.67,  31-May-83 13:05:14 by MURPHY
;TCO 6.1525 - Put S0.ENT at PHYINI.
; UPD ID= 2512, SNARK:<6.MONITOR>PHYSIO.MAC.66,  24-May-83 20:42:50 by MCLEAN
;TCO 6.1665 ADD SECOND WORD TO SERIAL NUMBER FOR HSC
; UPD ID= 2497, SNARK:<6.MONITOR>PHYSIO.MAC.65,  21-May-83 22:10:57 by COBB
;TCO 6.1664 - Use job number when calling ELOGOO:
; UPD ID= 2458, SNARK:<6.MONITOR>PHYSIO.MAC.64,  11-May-83 20:09:06 by MCLEAN
;FIX EXTRANEOUS CALL TO DONIRB
; UPD ID= 2434, SNARK:<6.MONITOR>PHYSIO.MAC.63,   6-May-83 10:16:28 by WACHS
;More TCO 6.1127 - Handle CI disks switching from 1 KDB to another
; UPD ID= 2426, SNARK:<6.MONITOR>PHYSIO.MAC.60,   5-May-83 20:11:21 by MCLEAN
;TCO 6.1645 PREVENT ILLUUO BY CHANGING TO PRIME UNIT AFTER DONIRB CALL
; UPD ID= 2354, SNARK:<6.MONITOR>PHYSIO.MAC.59,  27-Apr-83 07:25:32 by WACHS
;More TCO 6.1127 - Fix NOIORB bughlt for CI disks
; UPD ID= 2345, SNARK:<6.MONITOR>PHYSIO.MAC.58,  26-Apr-83 07:49:09 by WACHS
;More TCO 6.1127 - UNICKT fixup
; UPD ID= 2327, SNARK:<6.MONITOR>PHYSIO.MAC.57,  22-Apr-83 04:28:30 by WACHS
;TCO 6.1620 - Light MS%2PT
; UPD ID= 2272, SNARK:<6.MONITOR>PHYSIO.MAC.56,  13-Apr-83 14:08:40 by MILLER
;TCO 6.1610. More work on PHYMPR and PHYUPR
; UPD ID= 2261, SNARK:<6.MONITOR>PHYSIO.MAC.55,  13-Apr-83 10:45:30 by HAUDEL
;TCO 6.1583  -  Add PHYRW1 entry location to the PHYRWD code.
; UPD ID= 2250, SNARK:<6.MONITOR>PHYSIO.MAC.54,  12-Apr-83 19:55:47 by MILLER
;Fix typeo
; UPD ID= 2238, SNARK:<6.MONITOR>PHYSIO.MAC.53,  12-Apr-83 11:53:29 by MILLER
;TCO 6.1610. Add PHYMPR and PHYUPR. Also, check US.DUP at the proper places
; UPD ID= 2204, SNARK:<6.MONITOR>PHYSIO.MAC.52,   8-Apr-83 05:55:43 by WACHS
;TCO 6.1603 - Maintain US.2PT
; UPD ID= 2183, SNARK:<6.MONITOR>PHYSIO.MAC.51,   7-Apr-83 15:20:45 by MILLER
;TCO 6.1589. Use some IOPIOFs in UNICHK to avoid races
; UPD ID= 2180, SNARK:<6.MONITOR>PHYSIO.MAC.50,   6-Apr-83 14:06:46 by MILLER
;TCO 6.1589 again. Fix some races in handling US.OIR and US.OMS
; UPD ID= 2150, SNARK:<6.MONITOR>PHYSIO.MAC.49,   4-Apr-83 14:22:06 by MILLER
;TCO 6.1589 again
; UPD ID= 2145, SNARK:<6.MONITOR>PHYSIO.MAC.48,   4-Apr-83 12:54:54 by MILLER
;TCO 6.1589. Fix operator assistance message
; UPD ID= 2072, SNARK:<6.MONITOR>PHYSIO.MAC.47,  24-Mar-83 09:29:30 by HAUDEL
;More TCO 6.1538 - Edit not completed correctly first time
; UPD ID= 2054, SNARK:<6.MONITOR>PHYSIO.MAC.46,  21-Mar-83 18:06:41 by MURPHY
;GET RID OF OBSOLETE SEARCH PROKL
; UPD ID= 2032, SNARK:<6.MONITOR>PHYSIO.MAC.45,  20-Mar-83 11:46:36 by WEETON
;TCO 6.1559 -  Make IOLOCK lock pages in sections other than 0.
; UPD ID= 2004, SNARK:<6.MONITOR>PHYSIO.MAC.44,  16-Mar-83 04:51:41 by WACHS
;More TCO 6.1355
; UPD ID= 2001, SNARK:<6.MONITOR>PHYSIO.MAC.43,  16-Mar-83 03:58:37 by WACHS
;More of TCO 6.1127
; UPD ID= 1981, SNARK:<6.MONITOR>PHYSIO.MAC.42,  11-Mar-83 15:56:48 by HAUDEL
;TCO 6.1538 - Add overdue rewind timer code to the UNICHK section
; UPD ID= 1940, SNARK:<6.MONITOR>PHYSIO.MAC.41,   8-Mar-83 10:46:55 by CDUNN
;More TCO 6.1127 - Change default to include KLIPA support code
; UPD ID= 1903, SNARK:<6.MONITOR>PHYSIO.MAC.40,   2-Mar-83 07:36:03 by MCINTEE
;Fix typo in previous edit
; UPD ID= 1898, SNARK:<6.MONITOR>PHYSIO.MAC.39,   1-Mar-83 15:44:07 by HALL
;TCO 6.1502 - Allow free space outside of section 0
;	At least temporarily, make all callers request section 0
; UPD ID= 1892, SNARK:<6.MONITOR>PHYSIO.MAC.38,   1-Mar-83 14:18:24 by MOSER
;TCO 6.1530 - DON'T MONPDL IN CLRSTR IF NO UDB
; UPD ID= 1887, SNARK:<6.MONITOR>PHYSIO.MAC.37,  28-Feb-83 19:40:25 by PAETZOLD
;TCO 6.1529 - Do not trash Q1 in UNIC10 - Remove TCO 6.1515
; UPD ID= 1830, SNARK:<6.MONITOR>PHYSIO.MAC.36,  18-Feb-83 16:53:29 by PAETZOLD
;TCO 6.1515 - PH2DSW switch for debuging PH2PIMs.
; UPD ID= 1762, SNARK:<6.MONITOR>PHYSIO.MAC.35,   4-Feb-83 05:55:25 by WACHS
;More TCO 6.1355
; UPD ID= 1757, SNARK:<6.MONITOR>PHYSIO.MAC.34,   3-Feb-83 13:57:43 by GRANT
;TCO 6.1493 - use UNITS pool rather than GENERAL pool for resident free space
; UPD ID= 1587, SNARK:<6.MONITOR>PHYSIO.MAC.33,  28-Dec-82 07:54:00 by WACHS
;More TCO 6.1355
;MORE TCO 6.1355
; UPD ID= 1439, SNARK:<6.MONITOR>PHYSIO.MAC.31,  12-Nov-82 16:13:14 by PAETZOLD
;Force FTMSCP to zero if not defined- Delete some old edit history
; UPD ID= 1429, SNARK:<6.MONITOR>PHYSIO.MAC.30,   9-Nov-82 04:33:34 by WACHS
;TCO 6.1355 MSCP/KLIPA Mods
; UPD ID= 1222, SNARK:<6.MONITOR>PHYSIO.MAC.29,  23-Sep-82 12:51:20 by CDUNN
;More TCO 6.1198 Make OFFTWQ a global symbol so PHYMSC can get at it
; UPD ID= 1048, SNARK:<6.MONITOR>PHYSIO.MAC.28,   6-Aug-82 14:49:08 by PAETZOLD
;TCO 6.1217 - Count skip reads in DSKRVC
; UPD ID= 1016, SNARK:<6.MONITOR>PHYSIO.MAC.27,  30-Jul-82 04:48:56 by WACHS
;TCO 6.1198 -  Mods for CI support
; UPD ID= 907, SNARK:<6.MONITOR>PHYSIO.MAC.26,   9-Jun-82 23:37:41 by MURPHY
;TCO 6.1147 - Move bugdefs from BUGS.MAC to here and put them in-line.
; UPD ID= 772, SNARK:<6.MONITOR>PHYSIO.MAC.25,  20-May-82 07:23:36 by WACHS
;TCO 6.1127 - 1 more CI/KLIPA fix
; UPD ID= 762, SNARK:<6.MONITOR>PHYSIO.MAC.24,  18-May-82 15:47:14 by CDUNN
;TCO 6.1127 - Put references to Jupiter disk and tape under conditionals.
; UPD ID= 736, SNARK:<6.MONITOR>PHYSIO.MAC.21,  12-May-82 02:32:33 by CDUNN
;TCO 6.1126 - Put back the origional edit that REDIT lost
; UPD ID= 724, SNARK:<6.MONITOR>PHYSIO.MAC.19,  11-May-82 04:32:27 by CDUNN
;TCO 6.1127 - More, still yet, add support for CI and KLIPA
; UPD ID= 718, SNARK:<6.MONITOR>PHYSIO.MAC.18,  11-May-82 02:14:33 by CDUNN
;TCO 6.1127 - Keep PHYKLP and PHYMSC happy by making some symbols global
;In particular (CONSTW,OFFPWQ,ONPWQ,ONFTWQ)
; UPD ID= 687, SNARK:<6.MONITOR>PHYSIO.MAC.17,   4-May-82 13:40:00 by CDUNN
;TCO 6.1127 - Add call to initialize CISRV and SCA. Also add defaults setting
;for FTCI to be off.
; UPD ID= 404, SNARK:<6.MONITOR>PHYSIO.MAC.16,  14-Feb-82 01:58:04 by PAETZOLD
;More TCO 6.1010 - Fix up a couple of CSTX index registers
; UPD ID= 396, SNARK:<6.MONITOR>PHYSIO.MAC.15,  11-Feb-82 16:33:27 by PAETZOLD
;TCO 5.1727 - Fix read after write....use ONTWQ and not SIO1 in DONIRB.
; turn off IS.DON when queueing IRFRVC IORB.  Give fairness credit to
; unit for IRFRVC function
; UPD ID= 389, SNARK:<6.MONITOR>PHYSIO.MAC.14,   8-Feb-82 10:07:30 by PAETZOLD
;TCO 5.1723 - make sure STRTIO called for head of TWQ in SIO5
; UPD ID= 256, SNARK:<6.MONITOR>PHYSIO.MAC.13,  16-Dec-81 00:28:16 by PAETZOLD
;More TCO 6.1010 - Make sure all CSTX references occur while in section one
; UPD ID= 221, SNARK:<6.MONITOR>PHYSIO.MAC.12,  30-Nov-81 08:42:41 by PAETZOLD
;More TCO 6.1010 - CST3 linked list references
; UPD ID= 177, SNARK:<6.MONITOR>PHYSIO.MAC.11,  31-Oct-81 14:42:44 by PAETZOLD
;More TCO 6.1010 - Move CST3 references
; UPD ID= 171, SNARK:<6.MONITOR>PHYSIO.MAC.10,  29-Oct-81 23:04:02 by PAETZOLD
;TCO 6.1034 - Use S0.ENT before getting new stack in PHYSIO.  This
;  fixes problem where PHYSIO would return in section zero
; UPD ID= 163, SNARK:<6.MONITOR>PHYSIO.MAC.9,  23-Oct-81 15:35:38 by COBB
; UPD ID= 159, SNARK:<6.MONITOR>PHYSIO.MAC.8,  23-Oct-81 14:44:22 by COBB
; UPD ID= 146, SNARK:<6.MONITOR>PHYSIO.MAC.7,  19-Oct-81 16:19:55 by COBB
;TCO 6.1029 - CHANGE SE1CAL TO EA.ENT
;<6.MONITOR>PHYSIO.MAC.6,  5-Oct-81 14:14:12, EDIT BY MURPHY
;MAKE XINT INTERNAL
; UPD ID= 73, SNARK:<6.MONITOR>PHYSIO.MAC.5,  15-Sep-81 16:04:22 by PAETZOLD
;TCO 6.1010 - Move CSTs to CSTSEC - change non mask cst1 references
; UPD ID= 1851, SNARK:<6.MONITOR>PHYSIO.MAC.4,  21-Apr-81 06:22:12 by WACHS
;TCO 5.1288 ADD STATISTICS LOGGING CODE
; UPD ID= 1599, SNARK:<6.MONITOR>PHYSIO.MAC.3,  27-Feb-81 07:21:40 by WACHS
;TCO 6.1002 ADD CODE FOR DUAL-PORTED DISKS
; UPD ID= 1576, SNARK:<6.MONITOR>PHYSIO.MAC.2,  24-Feb-81 10:13:23 by LYONS
; UPD ID= 1573, SNARK:<5.MONITOR>PHYSIO.MAC.20,  23-Feb-81 16:11:38 by LYONS
;TCO 5.1062 FIX A BUG
; UPD ID= 1506, SNARK:<5.MONITOR>PHYSIO.MAC.19,  28-Jan-81 07:39:23 by WACHS
; UPD ID= 1452, SNARK:<5.MONITOR>PHYSIO.MAC.18,  20-Jan-81 05:44:16 by WACHS
;TCO 5.1234  ADD CODE FOR RETRY OPPOSITE IN MAGTAPE ERROR RECOVERY
; UPD ID= 1390, SNARK:<5.MONITOR>PHYSIO.MAC.17,  31-Dec-80 08:55:18 by WACHS
;TCO 5.1222 - Add code for movement of packs from drive to drive
; UPD ID= 1333, SNARK:<5.MONITOR>PHYSIO.MAC.16,   1-Dec-80 17:39:33 by LYONS
; UPD ID= 987, SNARK:<5.MONITOR>PHYSIO.MAC.15,   4-Sep-80 11:59:10 by LYONS
;FIX DESTRUCTION OF AC IN DONIRB: BY TCO 5.1062
; UPD ID= 958, SNARK:<5.MONITOR>PHYSIO.MAC.14,  25-Aug-80 15:10:00 by LYONS
; UPD ID= 956, SNARK:<5.MONITOR>PHYSIO.MAC.13,  25-Aug-80 14:44:03 by LYONS
;TCO 5.1062 - move error checking , and see if there was an error on
; a write verification, before we post the read
; UPD ID= 954, SNARK:<5.MONITOR>PHYSIO.MAC.12,  22-Aug-80 16:36:30 by LYONS
;MORE TCO 5.1062 - Make IORB modification code a little more paranoid about
;changeing a long IORB by mistake.
; UPD ID= 933, SNARK:<5.MONITOR>PHYSIO.MAC.11,  20-Aug-80 15:00:28 by LYONS
;TCO 5.1062 - Write verification stuff
; UPD ID= 735, SNARK:<5.MONITOR>PHYSIO.MAC.10,   7-Jul-80 00:47:13 by DBELL
;TCO 5.1096 - HAVE UNICHK LOOK FOR HALTED MICROCODE IN CONTROLLERS
; UPD ID= 685, SNARK:<5.MONITOR>PHYSIO.MAC.9,  22-Jun-80 12:19:58 by DBELL
;TCO 5.1065 - COMPLAIN ABOUT WRITE-LOCKED DISKS
; UPD ID= 679, SNARK:<5.MONITOR>PHYSIO.MAC.8,  19-Jun-80 16:32:02 by DBELL
;TCO 5.1071 - STORE CONTROLLER AND UNIT NUMBERS IN SYSERR BLOCKS
;TCO 5.1066 - GIVE IORB FUNCTION IN OVRDTA BUGCHK
;MAKE CLRACT GLOBAL, CLEAR US.WLK FOR DISKS ONCE A MINUTE IN UNITRY ROUTINE
; UPD ID= 616, SNARK:<5.MONITOR>PHYSIO.MAC.5,   8-Jun-80 15:52:07 by DBELL
;DON'T LET UDSKIO/MDSKIO DO TRANSFERS ACROSS CYLINDER BOUNDARIES
; UPD ID= 576, SNARK:<5.MONITOR>PHYSIO.MAC.4,  31-May-80 22:59:31 by DBELL
;TCO 5.1053 - DON'T GIVE FATAL ERROR FOR HUNG IORBS DOING SEEKS
;TCO 5.1048 - ADD ROUTINES TO ALLOW MULTIPLE-PAGE DISK I/O TO WORK
; UPD ID= 481, SNARK:<4.1.MONITOR>PHYSIO.MAC.30,  26-Apr-80 11:45:15 by DBELL
;CLEAN UP CODE LOTS BY USING TXNN AND MOVX MACROS EVERYWHERE
;TCO 4.1.1149 - MAKE HNGIRB ROUTINE KNOW ABOUT DISK CONTROLLERS
; UPD ID= 397, SNARK:<4.1.MONITOR>PHYSIO.MAC.29,   2-Apr-80 13:27:42 by DBELL
;MOVE INSTRUCTION AT PHYKIL DOWN TO PREVENT ILMNRF
; UPD ID= 366, SNARK:<4.1.MONITOR>PHYSIO.MAC.28,  26-Mar-80 11:07:44 by DBELL
;TCO 4.1.1119 - ADD LOTS OF CODE TO SUPPORT RP20 DISKS
; UPD ID= 215, SNARK:<4.1.MONITOR>PHYSIO.MAC.27,  23-Jan-80 09:19:39 by SCHMITT
;TCO 4.1.1071 - If fairness cnt exhsted at SEK1+5, chk for minimum cyl
;<4.1.MONITOR>PHYSIO.MAC.26, 10-Nov-79 11:08:37, EDIT BY DBELL
;TCO 4.1.1012 - TEST US.ACT CORRECTLY AT CHK6+3

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY  BE  USED
;OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT  (C)  DIGITAL  EQUIPMENT  CORPORATION  1976, 1985.
;ALL RIGHTS RESERVED.


	SEARCH PROLOG,PHYPAR,SERCOD,SCAPAR

	IFNDEF FTKLIPA,<FTKLIPA==:-1> ;Default is include KLIPA support code
	IFNDEF FTMSCP,<FTMSCP==:0> ;Default is no MSCP either

	TTITLE(PHYSIO,,< - DEVICE INDEPENDENT PHYSICAL IO>)
	SUBTTL L.BOSACK 17-MAY-75
	RESCD 			;RESIDENT CODE IN SECTION 0


;LATENCY OPTIMIZATION PARAMETERS

MINLAT==^D2700		;2.7MS SAFETY FACTOR
INIFCX==^D40		;INITIAL FAIRNESS COUNT FOR XFRS
			;DO A ROUND ROBIN CHANNEL SCHEDULE CYCLE
			;EVERY INFCX TRANSFERS. WHEN A CHANNEL GOES
			;IDLE, RESET THE COUNT.
INIFCP==^D40		;INITIAL FAIRNESS COUNT FOR POSITIONING
			;AT MOST INIFCP TRANSFERS WILL BE APPENDED
			;TO THE END OF A UNITS TRANSFER QUEUE IF
			;THERE ARE REQUESTS TO OTHER CYLINDERS
INIFCR==^D15		;INITIAL FAIRNESS COUNT FOR READ SEEK PREFERENCE
			;FOR INIFCR SEEK SCHEDULE CYCLES READS WILL
			;BE ABSOLUTLY PREFERABLE TO WRITES

;GLOBAL BYTE POINTERS

IRYFCN::POINT ISSFCN,IRBSTS(P4),ISPFCN ;IORB FUNCTION CODE
IRYMOD::POINT IMSMOD,IRBMOD(P4),IMPMOD ;IORB MODE

USYTYP::POINT USSTYP,UDBSTS(P3),USPTYP ;UNIT TYPE
CSYTYP::POINT CSSTYP,CDBSTS(P1),CSPTYP ;CHANNEL TYPE
CSYPIA::POINT CSSPIA,CDBSTS(P1),CSPPIA ;PI ASSIGNMENT
USYBKT::POINT XSSTYP,UDBSTS(P3),XSPTYP	;BLOCK TYPE FROM P3

;TABLE OF BYTES PER WORD AS A FUNCTION OF MODE

MODTAB::EXP -1			;ILLEGAL
	EXP 1			;WORD MODE
	EXP 6			;6 BIT MODE
	EXP 5			;7 BIT MODE
	EXP 4			;8 BIT MODE
	EXP 1			;HIGH DENSITY MODE

;TABLE OF UNIT TYPES USABLE BY THE FILESYSTEM
;NOTE: WHEN ADDING AN ENTRY TO THIS TABLE, BE SURE TO ADD A CORRESPONDING
;ENTRY IN DSKSIZ TO INDICATE THE SIZE OF THE DISK

DSKUTP::EXP .UTRP4		;RP04
	EXP .UTRP5		;RP05
	EXP .UTRP6		;RP06
	EXP .UTRP7		;RP07
	EXP .UTRM3		;RM03
	EXP .UTP20		;RP20
	EXP .UTR80		;RA80
	EXP .UTR81		;RA81
	EXP .UTR60		;RA60
	EXP .UTR82		;RA82 (FUTURE)
	EXP .UTR62		;RA62 (FUTURE)
NDSKUT==:.-DSKUTP

;TABLE	OF POINTER TO UNIT PHYSICAL SIZE PARAMETERS - THE TABLES ARE
;DEFINED IN STG


DSKSIZ::DSKSZ0			;RP04
	DSKSZ0			;RP05
	DSKSZ1			;RP06
	DSKSZ2			;RP07
	DSKSZ3			;RM03
	DSKSZ4			;RP20
	DSKSZ5			;RA80
	DSKSZ6			;RA81
	DSKSZ7			;RA60
	DSKSZ8			;RA82 (FUTURE)
	DSKSZ9			;RA62 (FUTURE)

;TABLE OF UNIT TYPE NAMES

NAMUTP::POINT 7,[ASCIZ /(ILLEGAL TYPE:0)/]
	POINT 7,[ASCIZ /RP04/]
	POINT 7,[ASCIZ /RS04/]
	POINT 7,[ASCIZ /TU45/]
	POINT 7,[ASCIZ /TM02/]
	POINT 7,[ASCIZ /RP05/]
	POINT 7,[ASCIZ /RP06/]
	POINT 7,[ASCIZ /RP07/]
	POINT 7,[ASCIZ /RP08/]
	POINT 7,[ASCIZ /RM03/]
	POINT 7,[ASCIZ /TM03/]
	POINT 7,[ASCIZ /TU77/]
	POINT 7,[ASCIZ /TM78/]
	POINT 7,[ASCIZ /TU78/]
	POINT 7,[ASCIZ /DX20A/]
	POINT 7,[ASCIZ /TU70/]
	POINT 7,[ASCIZ /TU71/]
	POINT 7,[ASCIZ /TU72/]
	POINT 7,[ASCIZ /TU73/]
	POINT 7,[ASCIZ /DX20B/]
	POINT 7,[ASCIZ /RP20/]
	POINT 7,[ASCIZ /CI PORT/]
	POINT 7,[ASCIZ /NODE/]
	POINT 7,[ASCIZ /RA80/]
	POINT 7,[ASCIZ /RA81/]
	POINT 7,[ASCIZ /RA60/]
	POINT 7,[ASCIZ /RA82/]
	POINT 7,[ASCIZ /RA62/]
IFN STANSW,<
	POINT 7,[ASCIZ /TA78/]
	POINT 7,[ASCIZ /MEIS/]
>;IFN STANSW
MSGLIM==.RTJST(-1,US.RTY)	;Min retry for operator assistance messages
;INITIALIZATION
;WIPES THE ACCUMULATORS

PHYINI::MOVSI Q1,PHYCHL		;GET LENGTH OF CHANNEL SERVICE TABLE
	MOVEI P4,0		;FIRST FREE SLOT IN CHANTAB
PHYIN2:	HRRZ T1,PHYCHT(Q1)	;GET DISPATCH ADDRESS
	PUSH P,Q1		;SAVE OVER CALL
	CALL CDSINI(T1)		;CALL TO INITIALIZE ALL CHANNELS OF THIS TYPE
	POP P,Q1		;RESTORE AOBJN POINTER
	CAMLE P4,MAXCHN		;A NEW MAXIMUM CHANNEL IN USE?
	MOVEM P4,MAXCHN		;YES
	AOBJN Q1,PHYIN2		;LOOP FOR ALL TYPES LOADED

	MOVEI T1,UIOLEN*<NUIORB-1>+UDIORB ;INITIALIZE IORB FREE LIST
	SETZM (T1)		;CLEAR END OF LIST
PHYIN3:	CAIN T1,UDIORB		;DONE?
	JRST PHYIN4		;YES
	MOVE T2,T1		;NO - SAVE SUCCESSOR
	SUBI T1,UIOLEN		;MOVE BACKWARD IN LIST
	MOVEM T2,(T1)		;STORE FOREWARD POINTER
	JRST PHYIN3

PHYIN4:	MOVEM T1,UIOLST		;STORE HEAD OF LIST
	SETOM DIAGLK		;INITIALIZE LOCK TO FREE
	RET

;UTILITY TO SET UP AND INITIALIZE A UDB
;T3/ DISPATCH ADDRESS,,LENGTH OF UDB
;Q2/ UNIT NUMBER
;P1/ CDB
;RETURNS +1(ON FAILURE):
;RETURNS +2 (SUCCESS)
;P3/ UDB ADDRESS

PHYUDB::HRRZ T1,T3		;LENGTH OF UDB
	PUSHJ P,PHYALC		;ALLOCATE STORAGE
	RET			;NONE FOUND
	MOVE P3,T1		;UDB POINTER TO P3
	HLRZ T1,T3		;DISPATCH ADDRESS
	MOVEM T1,UDBDSP(P3)	;SET UP IN UDB
	MOVEI T1,.BTUDB		;MARK AS UDB
	DPB T1,USYBKT		; ...
	HRRZM P1,UDBCDB(P3)	;SET UP CDB ADDRESS
	HRRZM Q2,UDBADR(P3)	;THIS UNITS ADDRESS ON CHANNEL
	HRL Q2,P1		;CDB,,UNIT #
	MOVEM Q2,UDBAKA(P3)	;AKA TEMPORARY SETUP
	HRRZ Q2,Q2		;RESTORE Q2
	MOVSI T1,UDBPWQ(P3)	;MAKE EMPTY QUEUES
	MOVEM T1,UDBPWQ(P3)	;POSITION WAIT QUEUE
	MOVSI T1,UDBTWQ(P3)
	MOVEM T1,UDBTWQ(P3)	;TRANSFER WAIT QUEUE
	MOVEI T1,-1		;SET POSITIONS TO UNKNOWN
	MOVEM T1,UDBPS1(P3)	; ...
	MOVEM T1,UDBPS2(P3)	; ...
	SETOM UDBSTR(P3)	;NOT ASSIGNED TO A STRUCTURE
	RETSKP
;PHYDUA - LOOK FOR A DUAL-PORTED DRIVE, BASED ON DRIVE'S SERIAL NUMBER.
;IF ONE IS FOUND, SET UP UDB2ND OR UDBALT ACCORDINGLY.
;   P3/	UDB
;	CALL PHYDUA		;(P3/)
;RETURNS +1

PHYDUA::SAVEPQ			;SAVE ACS
	HRRZ P5,P3		;SAVE TARGET UDB
	MOVSI P6,-CHNN		;PREPARE TO LOOK AT ALL CHANNELS
PHYDU1:	SKIPN P1,CHNTAB(P6)	;CHAN EXIST?
	JRST PHYDU2		;NO, TRY NEXT
	CALL DGUMAP		;YES, LOOK AT ALL UNITS
	 CALL PHYDU3		; LOOKING FOR A MATCHING SERIAL NUMBER
PHYDU2:	AOBJN P6,PHYDU1		;KEEP GOING FOR ALL CHANS
	RET

;CALLED FOR EACH UNIT ON A CHAN
PHYDU3:	MOVX T1,US.TPD		;CHECK TO SEE IF DISABLED
	TDNE T1,UDBSTS(P3)
	RET			;YES DON'T WANT TO MATCH THIS ONE
	SKIPE T1,UDBDSN(P3)	;NON-0 SERIAL NUMBER?
	CAIN P5,(P3)		;YES, DONT TRY TO MATCH OURSELVES
	RET			;TESTING OUR UNIT, OR NO SERIAL NUMBER - NO MATCH
	MOVE T2,UDBDSH(P3)	;GET HIGH SERIAL NUMBER
	CAMN T2,UDBDSH(P5)	;MATCH?
	CAME T1,UDBDSN(P5)	;YES, DOES IT MATCH TARGET SERIAL NUMBER?
	RET			;WRONG TYPE OR NO MATCH
	MOVE T1,CDBSTS(P1)	;CHAN STATUS
	TXNN T1,CS.CIP		;CI PORT?
	JRST PHYDU4		;NO
	MOVE T1,UDBCDB(P5)	;CHECK OLD TYPE
	MOVE T1,CDBSTS(T1)	;CHECK FOR CI DISK
	TXNN T1,CS.CIP		;IS IT CI?
	JRST PHYBYE		;NO PUT IT OFFLINE
	SETZB P6,Q3		;FOUND OUR MATCH DON'T NEED TO SEARCH ANY MORE
	HRRZM P5,UDBALT(P3)	;YES. SET UP UDBALT IN EACH UDB
	HRRZM P3,UDBALT(P5)	; POINTING AT THE OTHER UDB
	LDB T1,USYTYP		;GET TYPE OF ONE OF THE DRIVES
	CAIL T1,.UTNOD		;IS IT A NODE?
	RET
	JRST PHYBYE		;THREE PORTED THRU SERVER NO-NO

PHYDU4:	MOVE T1,UDBCDB(P5)	;GET THE OLD TYPE
	MOVE T1,CDBSTS(T1)
	TXNE T1,CS.CIP		;IS IT NON-CI?
	JRST PHYBHC		;YES PUT IT OFFLINE
	SETZB P6,Q3		;FOUND OUR MATCH, DON'T NEED TO SEARCH ANY MORE
	HRROM P5,UDB2ND(P3)	;MATCH. SET ALTERNATE UDB2ND = -1,,PRIME
	HRRZM P3,UDB2ND(P5)	;SET PRIME = 0,,ALTERNATE
	MOVX T1,US.2PT		;SINCE BOTH PORTS ARE ON THIS SYSTEM
	ANDCAM T1,UDBSTS(P3)	; IT ISN'T MULTI-ACCESS
	ANDCAM T1,UDBSTS(P5)
	RET

PHYBYE:	MOVX T1,US.TPD		;SET THREE PORT OFFLINE
	IORM T1,UDBSTS(P5)	;GONE FOREVER
PHYTBG:	BUG. (INF,PHYCPI,PHYSIO,HARD,<CI path ignored for Massbus disk>,<<P3,OCHN>,<P5,NCHN>>,<

Cause:	TOPS-20 is able to access a disk over the CI (through another system's
	MSCP server) but it already has had access to the disk via the Massbus.
	The system will ignore the CI path.

Action:	No action is required.  The purpose of the BUGINF is to let you know
	that the system will not use the CI path to the disk even if the
	Massbus path is disabled.

	If you were to reboot the system after disabling the Massbus path,
	then TOPS-20 would see the disk through an MSCP server only and
	would use that path for access.

Data:	OCHN - Old channel
	NCHN - New channel
>)
	MOVX T1,US.CHB!US.OIR!US.OMS	;NO MESSAGES
	ANDCAM T1,UDBSTS(P5)
	RET			;RETURN TO LOOP

PHYBHC:	MOVX T1,US.TPD		;SET THREE PORT OFFLINE
	IORM T1,UDBSTS(P5)	;SET OLD DISK OFFLINE
	HRRZ T2,UDBALT(P5)	;AN ALTERNATE?
	JUMPE T2,PHYTBG		;NO BUGCHK TOO
	IORM T1,UDBSTS(T2)	;SET THIS ONE OFFLINE TOO
	JRST PHYTBG		;AND BUG CHECK IT ALSO
;SETDSN - SET DRIVE SERIAL NUMBER
; T1/ HIGH-ORDER WORD
; T2/ LOW-ORDER WORD
; P3/ UDB
;	CALL SETDSN		;(T1,T2,P3/)
; RETURN +1

SETDSN::CAMN T1,UDBDSH(P3)	;HAS DSN
	CAME T2,UDBDSN(P3)	; CHANGED?
	IFNSK.
	   SAVEAC <Q1,Q2>	;YES
	   DMOVE Q1,UDBDSH(P3)	;PRESERVE OLD DSN
	   DMOVEM T1,UDBDSH(P3)	;SET NEW DSN
	   DMOVE T1,Q1		;RETRIEVE OLD DSN
	   IOR T1,T2		;WAS THERE ONE
	   SKIPN T1		; THERE?
	   RET			;NO, WE'RE JUST GETTING STARTED
	   DMOVE T1,Q1		;YES, RETRIEVE OLD AGAIN
	   CALL CFSDSN		;(T1,T2,P3/) TELL CFS ABOUT THE CHANGE
	ENDIF.
	RET
;ROUTINE TO CHECK FOR THE LEGALITY AND EXISTANCE OF A PARTICULAR
;UNIT ON A CHANNEL.  THIS ROUTINE HANDLES ALMOST ALL CASES, WHERE
;CONTROLLERS AND UNITS RANGE FROM 0-7, AND ARE REFERENCED AS OFFSETS
;INTO UDB TABLES.  ANY EXCEPTIONS (SUCH AS THE DX20) WILL HAVE THEIR
;OWN ROUTINES.  USED BY THE .DGPDL FUNCTION OF DIAG.  ARGUMENTS:
;  P1/	CDB
;  P2/	KDB (ONLY FOR EXTUDB CALL)
;  P5/	CONTROLLER NUMBER OR -1 IF NONE (ONLY FOR EXTKDB CALL)
;  Q2/	UNIT NUMBER
;RETURNS:
;  +1:	T1/ 0	UNIT OR CONTROLLER IS ILLEGAL
;	T1/ -1	UNIT OR CONTROLLER IS NONEXISTANT
;  +2:	CONTROLLER AND UNIT EXIST
;TRASHES T1.  P2 AND P3 ARE SET TO THE KDB AND UDB AS THEY ARE FOUND.


EXTKDB::JUMPL P5,EXTUD2		;DIFFERENT IF NO CONTROLLER
	CAILE P5,7		;CAN HAVE ONLY 8 UNITS
	JRST RFALSE		;ILLEGAL
	MOVE T1,CDBIUN(P1)	;GET ADDRESS OF KDB POINTERS
	ADD T1,P5		;ADD KDB UNIT
	SKIPN P2,(T1)		;KDB EXIST?
	JRST RTRUE		;NO
	MOVE P3,P2		;COPY FOR CHECK
	LDB T1,USYBKT		;GET BLOCK TYPE
	CAIE T1,.BTKDB		;MAKE SURE IT IS A KDB
	JRST RTRUE		;NO, ERROR
	MOVE T1,KDBDSP(P2)	;GET DISPATCH ADDRESS
	JRST UDSEXT(T1)		;ASK CONTROLLER ABOUT THE UNIT

EXTUD2:	SKIPA P3,[ADD T1,CDBIUN(P1)]	;INSTRUCTION FOR NO CONTROLLER
EXTUDB::SKIPA P3,[ADD T1,KDBIUN(P2)]	;OR INSTRUCTION FOR CONTROLLER
	SETZ P2,		;FLAG NONEXISTANCE OF CONTROLLER
	SKIPL T1,Q2		;CHECK UNIT VALIDITY
	CAILE T1,7		;ONLY CAN HAVE 8 UNITS
	JRST RFALSE		;ILLEGAL
	XCT P3			;ADD IN ADDRESS OF UNIT TABLE
	SKIPN P3,(T1)		;SEE IF UDB EXISTS
	JRST RTRUE		;NO
	LDB T1,USYBKT		;GET BLOCK TYPE
	CAIE T1,.BTUDB		;MAKE SURE IT IS A UDB
	JRST RTRUE		;NOPE
	RETSKP			;YES, SKIP RETURN
;SUBROUTINE TO FIND THE CORRECT CHANNEL, CONTROLLER, AND UNIT NUMBERS
;GIVEN THE CDB, KDB, AND UDB ADDRESSES.  USED BY VARIOUS BUGCHKS, ETC.
;THE NORMAL ENTRY IS FNDCKU - FNDCKS IS USED FOR "RELATIVE" UNIT NUMBERING
;THAT IS THE UNIT IS NUMBERED CORRESPONDING TO IT'S OFFSET IN THE TABLE RATHER
;THAN IT'S REAL UNIT NUMBER.
;CALL:
;  P1/	CDB
;  P2/	KDB, OR 0 IF NONE
;  P3/	UDB
;RETURNS +1 ALWAYS:
;  T1/	CHANNEL NUMBER
;  T2/	CONTROLLER NUMBER OR -1 IF NONE
;  T3/	UNIT NUMBER


FNDCKS::CALL FNDCKU		;GET C K AND ABSOLUTE U
	TRNN P2,-1		;REALLY A K?
	RET			;NO ALL DONE
	MOVE T3,KDBIUN(P2)	;GET AOBJN WORD
FNDCS0:	CAME P3,0(T3)		;FIND IT
	IFNSK.
	  AOBJN T3,FNDCS0	;NO KEEP LOOPING
	  BUG. (HLT,PHYNUN,PHYSIO,SOFT,<PHYSIO no unit number>,<<T1,CHAN>,<T2,KONT>,<P3,UDB>>,<

Cause:	A unit number could not be found for a given CDB, KDB, UDB.
	This indicates a software problem.

Action:	Analyse the dump. Insure that P3 contains a valid UDB.

Data:	CHAN - Channel number
	KONT - Controller number
	UDB - UDB address
>)
	ENDIF.
	HRRZS T3
	SUBI T3,KDBUDB(P2)	;RELATIVE TO KDBUDB
	RET
	
FNDCKU::HRRZ T1,CDBADR(P1)	;GET CHANNEL NUMBER
	SETO T2,		;ASSUME NO CONTROLLER
	HRRZ T3,UDBAKA(P3)	;GET UNIT IF NO CONTROLLER
	TRNN P2,-1		;GUESSED RIGHT?
	RET			;YES, DONE
	MOVE T2,T3		;NOPE, GET CONTROLLER NUMBER
	HRRZ T3,UDBSLV(P3)	;AND UNIT OF IT
	RET			;NOW DONE
;ALLOCATORS FOR USE DURING INITIALIZATION ONLY

;ALLOCATE RESIDENT STORAGE
;T1/ LENGTH OF BLOCK IN WORDS, ASSUMED LESS THAN PGSIZ
;	CALL PHYALC
;RETURNS+1:	ON FAILURE,
;RETRUNS+2:	SUCCESS,
;T1/ ADDRESS OF START OF BLOCK
;PRESERVES T3,T4

PHYALC::JUMPLE T1,INIERR	;CHECK ARG
	SAVEAC <T3,T4,Q1>	;PRESERVE USEFUL REGISTERS
	SKIPA Q1,T1		;SAVE LENGTH
PHYALL:	MOVE T1,Q1		;GET LENGTH
	HRLI T1,.RESP1		;PRIORITY
	MOVX T2,RS%SE0!.RESUP	;UNITS POOL, SECTION 0
	CALL ASGRES		;GET STG
	JRST [ BUG.(INF,PHYICE,PHYSIO,HARD,<PHYINI - Failed to assign resident STG>,,<

Cause:	The routine PHYALC was called to allocate storage for data such
	as a CDB, KDB, or UDB, but there was not enough free resident
	storage to allocate it.  The monitor will simply forget about
	any device for which it cannot build tables.
>)
		   RET]
	MOVE T4,T1		;GET ADDRESS
	MOVE T3,T1		;IN 2 PLACES
	ADD T3,Q1		;SEE IF IT IS GREATER THAN A PAGE
	ANDI T4,777000
	ANDI T3,777000
	CAME T4,T3		;IF THE SAME THEN OK
	JRST PHYALL		;LOOSE IT FOR NOW..... ;*****TEMP*****
	RETSKP


;HERE WHEN GIVEN AN ILLEGAL ARGUMENT TO ALC

INIERR:	BUG.(HLT,PHYICA,PHYSIO,HARD,<PHYINI - Illegal argument to core alloc>,,<

Cause:	The routine PHYALC was called asking for a negative number
	of words.  This routine is called to allocate resident storage
	for data such as CDB's, KDB's, and UDB's.
>)
;RESTART ENTRY
;ENTERED WITH PI OFF, STACK IN P, ALL ACCUMULATORS FREE.

PHYRST::MOVSI Q3,-CHNN		;BUILD AOBJN POINTER
RST1:	SKIPN P1,CHNTAB(Q3)	;CHANNEL PRESENT?
	JRST RST2		;NO
	PUSH P,Q3		;SAVE CHANNEL COUNTER
	CALL DGUMAP		;FOR ALL UNITS ON THIS CHANNEL
	 CALL ABTREQ		;ABORT REQUESTS
	POP P,Q3		;RESTORE CHANNEL COUNTER
	MOVX T1,CS.ACT!CS.MAI!CS.ERC	;CLEAR STATE BITS
	ANDCAM T1,CDBSTS(P1)	; ...
	MOVEI T1,1		;INDICATE FULL RESET
	HRRZ T2,CDBDSP(P1)	;GET CHANNEL DISPATCH
	CALL CDSRST(T2)		;RESET HARDWARE
RST2:	AOBJN Q3,RST1		;LOOP FOR ALL CHANNELS
	CALLRET MTCLVA		;CLEAR ALL VALID VOLUME BITS FOR MT'S

;HERE TO ABORT THE REQUESTS ON A PARTICULAR UNIT

ABTREQ:	HRRZ P4,UDBTWQ(P3)	;ANY TRANSFER REQUESTS?
	JUMPE P4,ABT1		;NO MORE
	CALL OFFTWQ		;PULL FROM TWQ
	CALL ABT3		;POST DONE IF NEEDED
	JRST ABTREQ		;LOOP FOR MORE

ABT1:	HRRZ P4,UDBPWQ(P3)	;ANY POSITION REQUEST?
	JUMPE P4,ABT2		;NO MORE
	CALL OFFPWQ		;REMOVE FROM PWQ
	CALL ABT3		;AND POST COMPLETE IF NEEDED
	JRST ABT1		;LOOP FOR MORE

ABT2:	MOVX T1,US.BLK!US.REW!US.ORC!US.OIR!US.OMS	;THINGS TO RESET ABOVE
	ANDCAM T1,UDBSTS(P3)	;WHAT CLRACT RESETS
	MOVX T1,US.PSI		;SET PSI REQUEST
	IORM T1,UDBSTS(P3)
	CALLRET CLRACT		;RESET UDB

ABT3:	MOVX T1,IS.SHT		;PAGEM REQUEST?
	TDNE T1,IRBSTS(P4)	;?
	RET			;YES, IGNORE
	MOVX T1,IS.ERR!IS.NRT	;INDICATE ERROR
	IORM T1,IRBSTS(P4)	; ..
	CALLRET DONIRB		;POST COMPLETE
				;DONE WITH THIS REQUEST
;ONLINE ENTRY - ENTERED ON THE ONLINE INTERRUPT OF A UNIT

PHYONL::MOVX T1,US.TPD		;CHECK FOR THREE PORTED DISK
	TDNE T1,UDBSTS(P3)
	RET			;CAN'T ONLINE THREE PORTED DISKS NO MATTER WHAT!
	MOVX T1,US.OFS		;CLEAR OFFLINE AND UNSAFE BITS
	ANDCAM T1,UDBSTS(P3)	; ...
	MOVX T1,US.PSI		;SET PSI REQUEST
	IORM T1,UDBSTS(P3)
	CALLRET MSSONL		;TELL MSCP SERVER AND DONE

;OFFLINE ENTRY - ENTERED ON THE OFFLINE INTERRUPT OF A UNIT

PHYOFL::MOVX T1,US.PSI!US.OFS	;GET OFFLINE AND PSI FLAGS
	IORB T1,UDBSTS(P3)	;STORE THEM AND GET OTHER BITS
	TXNN T1,US.TAP		;IS THIS A TAPE?
	CALLRET MSSOFL		;NO, TELL MSCP SERVER AND RETURN
	CALLRET MTCLVL		;CLEAR VALID VOLUME FOR THIS TAPE


;HERE ON REWIND DONE.

PHYRWD::SAVEPQ			;SAVE ALL Q'S AND P'S
	MOVX T1,US.REW!US.ORC	;NO LONGER REWINDING
	ANDCAM T1,UDBSTS(P3)
	MOVX T1,US.PSI!US.BOT	;SET POSSIBLE PSI FOR REWIND DONE,
	IORM T1,UDBSTS(P3)	; AND TELL THE WORLD IT IS AT BOT
PHYRW1::IOPIOF			; INTERLOCKED
	CALL SCHSEK		;START ANY POSITION OPS
	MOVX T1,CS.ACT!CS.ERC	;GET FLAGS READY
	TDNN T1,CDBSTS(P1)	;CHANNEL ACTIVE?
	CALL SCHXFR		;NO, START CHANNEL
	JRST ONRET		;AND RETURN
;HERE WHEN THE INTERRUPTING DEVICE HAS BEEN DETERMINED
;ENTERED WITH CDB IN P1, P1 SAVED IN CDBSVQ


PHYINT::MOVEM 17,PHYACS+17	;SAVE HIGH ACCUMULATOR
	MOVEI 17,PHYACS		;SETUP BLT POINTER
	BLT 17,PHYACS+16	;SAVE REMAINING ACCUMULATORS
	MOVE T1,CDBSVQ(P1)	;COPY P1 FROM WHERE SAVED
	MOVEM T1,PHYACS+P1	;STORE WITH REST
	MOVE P,[IOWD LPHIPD,PHYIPD] ;GET INTERRUPT PDL
	HRRZ T1,CDBDSP(P1)	;GET CHANNEL DISPATCH
;NOTE THAT INTERRUPT ROUTINES DO NOT PRESERVE P OR Q ACCUMULATORS TO SAVE TIME
	CALL CDSINT(T1)		;PASS INTERRUPT DOWNWARD
	 JRST [	MOVX T1,CS.AC2	;AN ERROR WAS DETECTED, SHUT DOWN
		ANDCAM T1,CDBSTS(P1) ;STACKED COMMAND
		JRST .+1]
	JUMPE P4,XINT		;REQUEST TO DISMISS
	JUMPL P4,[ SETZ P5,		;INSURE WE DON'T CALL THIS ALTERNATE UNIT FINISH
		   MOVX T1,CS.ERC	;REQUEST FOR SCHEDULE CYCLE,
		TDNN T1,CDBSTS(P1) ;IS CHANNEL IN ERR RECOV?
		JRST INT2	;NO - HONOR REQUEST
		JRST XINT]	;YES - SCHED AT END OF ERR RECOV
PHYINU::HLL Q3,UDBSTS(P3)	;SET UP LEFT HALF FOR SOME TESTS
	HRRZ T1,UDBTWQ(P3)	;CHECK IF THIS IS THE
	TXNE Q3,US.POS		;IORB WE EXPECTED
	HRRZ T1,UDBPWQ(P3)	;FROM EITHER QUEUE
	CAIE T1,(P4)		;??
	BUG.(HLT,ILTWQ,PHYSIO,HARD,<PHYINT - TWQ OR PWQ INCORRECT>,,<

Cause:	In the PHYINT routine to handle an interrupt, after the lower
	level interrupt code has returned, a check is made to see if
	the IORB returned matched the first element of either the position
	wait queue or the transfer wait queue.  The returned IORB did not match
	the first element in the queue checked.
>)		;NO.
	SKIPE UDBERR(P3)	;ERROR RECOVERY IN PROGRESS?
	JRST INTERR		;YES - MUST CALL LOWER LEVEL IN ALL CASES
	MOVE T1,IRBSTS(P4)	;YES - ANY ERROR INDICATION?
	TXNN T1,IS.ERR!IS.WGU!IS.DTE!IS.DVE!IS.RTL	;??
	JRST INTDON
INTERR:	SKIPN T1,UDBERP(P3)	;ERRORS - ERROR BLOCK SETUP?
	JRST [	MOVX T1,CS.ERC	;NO, SET ERROR RECOVERY ON CHANNEL
		TXNN Q3,US.POS	;TRANSFER?
		IORM T1,CDBSTS(P1) ;YES
		CALL ERRSET	;CREATE ERROR BLOCK
		JRST .+1]	;CONTINUE
	MOVEM T1,UDBERP(P3)	;STORE IN UDB
	MOVE T1,UDBDSP(P3)	;GET UNIT DISPATCH
	CALL UDSERR(T1)		;INVOKE ERROR RETRY
	 JRST XINT		;NON SKIP - RETRY IN PROGRESS
				;SKIP - DONE WITH RECOVERY, FOR GOOD OR ILL
	MOVX T1,CS.ERC		;SETUP TO CLEAR ERROR RECOVERY FLAG
	TXNN Q3,US.POS		;TRANSFER?
	ANDCAM T1,CDBSTS(P1)	;YES - CLEAR FLAG
INTDON:	TXNE Q3,US.POS		;TAKE REQUEST OUT OF QUEUE
	JRST INT8		;HANDLE TERMINATION IN POSITIONING
	CALL OFFTWQ		;PULL FROM TWQ
	MOVX T1,CS.AC2		;IS THIS A STACKED COMMAND
	TDNE T1,CDBSTS(P1)	; ??
	JRST [ANDCAM T1,CDBSTS(P1) ;YES, CLEAR BIT IN CHAN
	      JRST INTDN1]	;AND CONTINUE
	HRRZ T1,UDBTWQ(P3)	;GET 1ST REMAINING ENTRY ON TWQ
	ADD T1,UDBPWQ(P3)	;PLUS 1ST ON PWQ
	HRRZS T1		;LEAVE T1 NON-0 IF UNIT IS ACTIVE
	MOVX T2,US.CIP
	TDNE T2,UDBSTS(P3)	;IS THE UNIT ON A CI?
	JUMPN T1,INT0		;LEAVE UNIT ACTIVE IF SOMETHING ELSE IS HAPPENING
	CALL CLRACT		;NO LONGER ACTIVE
INTDN1:	SKIPL P5,UDB2ND(P3)	;XFER ON AN ALTERNATE UNIT?
	JRST INT0		;NO, CONTINUE
	MOVX T1,US.ACT		;YES, CLEAR US.ACT
	ANDCAM T1,UDBSTS(P5)	; IN PRIME UNIT TOO
	CALL DONIRB		;SET TRANSFER COMPLETE
	HRR P5,P3		;SAVE THIS UDB ADDRESS
	HRRZ P3,UDB2ND(P3)	;POINT P3 AT PRIME UNIT
	HRRZ P2,UDBKDB(P3)	;SET UP P1 AND P2 ALSO
	HRRZ P1,UDBCDB(P3)	;SO SUBSEQUENT IO REQUESTS WILL BE FOR PRIME UNIT
	JRST INTA		;AND CONTINUE
;HERE IF INTERRUPT IS FROM A CI UNIT WHICH IS STILL BUSY
INT0:	CALL DONIRB		;POST IORB AS DONE
INTA:
	MOVE T1,CDBSTS(P1)	;STATUS OF CHAN
	TXNE T1,CS.CIP		;IS IT A CI CHAN?
	RET			;YES, WE'RE THROUGH
	SKIPE PWRDWN		;OR POWER FAILING?
	JRST XINT		;YES - DISMISS
	JUMPGE P5,INT2		;GO IF WE DID THE IO ON A PRIME UNIT
	MOVE P3,P5		;IO WAS ON AN ALTERNATE - RESET ACS
	HRRZ P2,UDBKDB(P3)	; SO AS TO LOOK ON RIGHT CHAN, CONTROL
	HRRZ P1,UDBCDB(P3)	; FOR MORE WORK TO DO
INT2:	CALL SCHSEK		;SCHEDULE SEEKS (IF NEEDED)
	PUSH P,P3		;SAVE DUAL-PORTED FLAG
	CALL SCHXFR		;SCHEDULE TRANSFERS
	JUMPN P5,INT3		;FINISH ON A DUAL-PORTED DRIVE (OR JUST SEEKS FINISH)?
				;NO, SINGLE-PORTED DRIVE. EXIT INTERRUPT
	JRST XINT
;HERE WHEN A DUAL-PORTED DRIVE FINISHED, OR JUST SEEKS FINISHED
;THE MAIN PORT OF THIS DRIVE MAY HAVE XFERS WHICH ARE WAITING, OR SOME
;OTHER DRIVE MAY BE DUAL-PORTED TO THIS CHAN AND HAVE IO WHICH CAN BE STARTED.
;SCAN ALL DRIVES ON THIS CHAN, LOOKING FOR DUAL-PORTED DRIVES WE CAN START
INT3:	MOVE Q1,CDBIUN(P1)	;POINTER TO LOOK AT ALL DRIVES
IFE STANSW,<
INT4:	SKIPE P3,(Q1)		;UDB EXIST?
	SKIPN P5,UDB2ND(P3)	;YES, DUAL PORTED?
	JRST INT7		;NOT A DUAL-PORTED DRIVE. TEST NEXT
>;IFE STANSW
IFN STANSW,<
;THIS EDIT FIXES OUR MEIS PROBLEMS AT STANFORD, BUT IS IN GENERAL INCORRECT.
; AFTER FINDING A KDB, WE SHOULD SCAN ANY DISKS THAT HAPPEN TO BE ON THAT
; CONTROLLER.  SINCE WE DON'T HAVE ANY DX20 CONTROLLERS AT STANFORD, THIS
; HACK WILL SUFFICE.  I'M GOING TO LET DEC WRITE THE CORRECT CODE. -KSL
INT4:	SKIPN P3,(Q1)		;UDB OR KDB EXIST?
	 JRST INT7		;NO, GO ON TO NEXT DEVICE
	LDB T1,USYBKT		;GET BLOCK TYPE
	CAIN T1,.BTUDB		;IS IT A UDB?
	 SKIPN P5,UDB2ND(P3)	;YES, IS A DUAL PORTED DISK?
	  JRST INT7		;NOT A UDB OR NOT A DUAL PORTED DISK 
>;IFN STANSW
	SKIPG P5		;IS THIS THE ALTERNATE PATH?
	EXCH P3,P5		;YES, RESET SO P3=MAIN PORT, P5=ALTERNATE
	MOVE T1,UDBSTS(P3)	;STATUS
	TXNE T1,US.ACT		;IS DRIVE ALREADY ACTIVE?
	JRST INT7		;YES, KEEP ON LOOKING
	HRRZ P4,UDBTWQ(P3)	;NO. DOES IT HAVE ANYTHING TO DO?
	JUMPE P4,INT7		;NO. TRY NEXT DRIVE
	PUSH P,P1		;YES, TRY TO START IT GOING
	CALL CKSTRT		;CAN WE START IT ON THE MAIN PORT?
	 JRST INT5		;NO, TRY OTHER PORT
	CALL STRTIO		;START IT GOING
	 JFCL			;WONT START, TOO BAD
	JRST INT6		;LOOK FOR MORE DRIVES TO START
INT5:	EXCH P3,P5		;SET TO LOOK AT ALTERNATE PATH
	CALL CKSTRT		;CAN WE START IT HERE?
	 JRST INT6		;NO, CAN'T START THIS DRIVE ON EITHER PORT
	CALL STRALT		;YES. START IT GOING ON ALTERNATE PORT
INT6:	POP P,P1
INT7:	AOBJN Q1,INT4		;TRY NEXT UNIT
	POP P,P3		;RESTORE FLAG
	JUMPGE P3,XINT		;GO IF WE DID IT ON THE MAIN UNIT
	HRRZ P3,UDB2ND(P3)	;ALTERNATE - SWITCH TO MAIN PORT TO LOOK FOR SEEKS
	MOVE T1,UDBSTS(P3)	;IS UNIT ACTIVE AGAIN?
	TXNE T1,US.ACT		;...
	JRST XINT		;YES, WE'RE DONE
	HRRZ T1,UDBTWQ(P3)	;NOT ACTIVE. IS THERE A SEEK WAITING
	JUMPN T1,XINT		; AND NO TRANSFER WAITING?
	HRRZ T1,UDBPWQ(P3)	;NO XFER, ANY SEEKS TO DO?
	JUMPE T1,XINT		;NONE IF 0
	HRRZ P4,T1		;POINT P4 AT THE IORB
	HRRZ P2,UDBKDB(P3)	;POINT P2 AT KDB
	PUSH P,P1		;SAVE CDB ADDRESS
	HRRZ P1,UDBCDB(P3)	;POINT P1 AT CDB
	CALL SIO3A		;TRY AND START THE SEEK
	POP P,P1		;RESTORE CDB ADDR (FOR DISMISSING INTERRUPT)

XINT::	MOVSI P,PHYACS		;RESTORE BLT POINTER
	JRST CDBJEN(P1)		;RESTORE ACCUMULATORS AND DISMISS

;HERE WHEN AN IORB TERMINATES ON THE PWQ

INT8:	CALL OFFPWQ		;PULL FROM QUEUE
	CALL CLRPOS		;NO LONGER POSITIONING
	CALL DONIRB		;POST DONE
	CALL SCHSEK		;SEE IF MORE TO DO
	SKIPE PWRDWN		;POWER FAILING?
	JRST XINT		;YES, DON'T START NEW I/O
	MOVE T1,CDBSTS(P1)	;GET CHANNEL STATUS
	TXNN T1,CS.ACT!CS.ERC!CS.OFL	;CHANNEL AVAILABLE?
	CALL SCHXFR		;NO, SEE IF ANY WORK TO DO
	JRST XINT		;THEN EXIT
;HERE TO POST AN IORB COMPLETE
;P4/ IORB
;	CALL DONIRB
;RETURNS+1(ALWAYS)

DONIRB:	MOVX T1,IS.DON		;FLAG DONE
	MOVX T2,IS.WGU!IS.TPM!IS.EOT!IS.DTE!IS.DVE!IS.BOT!IS.RTL
	TDNE T2,IRBSTS(P4)	;ANY ERRORS?
	TXO T1,IS.ERR		;YES, SET GENERAL ERROR BIT
	IORM T1,IRBSTS(P4)	; ...
	CALL ERRFIN		;TERMINATE ERROR RECOVERY IF NEEDED
	SKIPL IRBSTS(P4)	;SHORT IORB?
	JRST DONIR1		;NO - CALL SPECIFIED ADDRESS
	MOVX T2,IS.WGU!IS.DTE!IS.DVE!IS.RTL	;IF ANY OF THESE ERRORS
	MOVX T3,SWPERR		;NOTIFY PAGEM
	MOVEI T1,-CST5(P4)	;GET CPN
	TDNE T2,IRBSTS(P4)	; CHECK.
	 JRST DONIR4		;YES...GO NOTIFY PAGEM
	PUSH P,T1		;SAVE T1 FOR LATER
	LDB T1,IRYFCN		;GET TYPE OF IORB
	CAIN T1,IRFWVC		;VALIDITY WRITE DONE?
	JRST [	MOVEI T1,IRFRVC	;YES, MAKE IT A READ
		DPB T1,IRYFCN	;PUT IT INTO THE IORB
		MOVX T1,IS.DON	;GET THE IORB DONE FLAG
		ANDCAM T1,(P4)	;AND TURN IT OFF
		AOS UDBFCT(P3)	;AND DONT LET THIS HURT FAIRNESS COUNT
		AOS DSKRVC	;INCREMENT SYSTEM WIDE SKIP READ COUNT
		MOVX T1,US.CIP	;CHECK FOR CI DISK
		TDNE T1,UDBSTS(P3) ;IS IT ?
		JRST .+1	;YES DON'T RE-QUEUE IT ALREADY DONE
		MOVE T1,P4	;PUT POINTER INTO T1 FOR PHYSIO
		CALL ONTWQ	;AND QUEUE IT TO THE DISK
		POP P,T1	;CLEAN STACK UP
		RET]
	CAIN T1,IRFRVC		;OR READ VALIDITY CHECK?
	JRST [	MOVEI T1,IRFWRT	;GET WRITE FUNCTION
		DPB T1,IRYFCN	;AND FIX IORB BACK FOR PAGEM
		JRST .+1]	;BACK TO THE MAIN LINE, AND LET PAGEM RUN
	POP P,T1		;RESTORE T1 WITH PAGE NUMBER
DONIR3:	PUSH P,P1		;SAVE REGISTERS
	PUSH P,P3		; ...
	CALL SWPDON		;NOTIFY PAGEM
	POP P,P3		;RESTORE REGISTERS
	POP P,P1		; ..
	RET

DONIR4:	CALL [	EA.ENT		;ENTER SECTION ONE
		IORM T3,@CST3X+T1 ;ERRORS - INDICATE TO PAGEM.
		RET]		;RETURN TO CORRECT SECTION
	JRST DONIR3		;CONTINUE, BUT FORGET VERIFICATION

;HERE ON COMPLETION OF A LONG IORB

DONIR1:	HRRZ T2,IRBIVA(P4)	;GET CALLERS INTERRUPT ADDRESS
	JUMPE T2,DONIR2		;IS THERE AN INTERRUPT ROUTINE?
	MOVE T1,P4		;COPY IORB FOR CALL
	CALLRET (T2)		;CALL

DONIR2:	BUG.(CHK,PHYNIR,PHYSIO,HARD,<PHYSIO - Null interrupt routine at operation done>,,<

Cause:	The routine DONIRB, when terminating a long IORB, attempted to notify
	higher level code about the finished IORB, but the field in the IORB
	that contained the address to call was zero.
>)
	RET
	SUBTTL START IO


;HERE TO ENQUEUE AN IO REQUEST.
;  T1/	IORB
;  T2/	UDB (FOR LONG IORB ONLY)
;	CALL PHYSIO
;RETURNS+1:(ALWAYS)
;	IO REQUEST MADE. IF UNIT IS OFFLINE, A MESSAGE TO THE
;	OPERATOR WILL BE PRINTED. IF THE CALL IS IN ANY WAY
;	INVALID (NONEXISTANT UNIT, BAD ADDRESS, ETC.) A BUGHLT WILL OCCUR
;	THE CALLING ROUTINE IS ASSUMED TO HAVE MADE THOSE CHECKS
;	AND PASSED.
;	**NOTE** NOSKED IS ASSUMED, AS A PRIVATE STACK IS USED

PHYSIO::
	MOVEM P,PHYSVP		;SAVE CALLERS STACK
	MOVE P,[IOWD LPHYPD,PHYPDL] ;LOCAL STACK
	CALL SIO1		;DO THE REAL WORK
	MOVE P,PHYSVP		;RESTORE CALLERS PC
	RET

;DETERMINE CHANNEL/CONTROLLER/UNIT FOR THIS IORB

RS PHYIFL,1			;FLAG TO INDICATE THAT WE SHOULD NOT TURN ON IO

IOSIO::	SETOM PHYIFL		;REMEMBER THAT IO IS OFF ALREADY
SIO1:	SAVEPQ			;SAVE CALLERS REGISTERS ON LOCAL STACK
	HRRZ P4,T1		;SET UP IORB POINTER
	HRRZ P3,T2		;ALSO SET UP UDB ADDRESS (IN CASE IORB IS LONG)
	SKIPL IRBSTS(P4)	;SHORT IORB?
	JRST SIO2		;NO, UDB ADDRESS ALREADY SET UP
	CALL GETCUB		;YES, COMPUTE UDB FROM PAGEM ADDRESS
	 BUG.(HLT,ILPDAR,PHYSIO,HARD,<PHYSIO - Illegal disk address in PAGEM request>,,<

Cause:	The routine PHYSIO was called to queue up an IORB for PAGEM, but
	the disk or swapping address, or unit was illegal.  All such
	arguments should have been checked by the caller.
>)
				;T1 HAS UNIT ADDRESS (LINEAR)
	MOVEI T2,-CST5(P4)	;GET CORE PAGE NUMBER
	STOR T1,CSTLDA,+T2 	;STORE UNIT RELATIVE ADDRESS
SIO2:	HRRZ P1,UDBCDB(P3)	;SET UP CDB ADDRESS
	HRRZ P2,UDBKDB(P3)	;ALSO SET UP KDB ADDRESS OR ZERO IF NONE
	HRRZ T2,UDBDSP(P3)	;GET UNIT DISPATCH BASE
	SKIPN PHYIFL		;IF WE SHOULD
	IOPIOF			; TURN PHYSIO CHANNELS OFF
	HLL Q3,UDBSTS(P3)	;GET LEFT HALF STATUS OF UNIT

	TXNE Q3,US.CIP		;UNIT ON A CI PORT?
	JRST SIO8		;YES, GO DIRECTLY TO START IO

	TXNE Q3,US.POS		;IS POSITION IN PROGRESS?
	JRST SIO3		;YES - APPEND TO PWQ
	TXNE Q3,US.TAP		;IS THIS A TAPELIKE DEVICE?
	JRST SIO6		;YES - SEE IF POSITIONING TO DO
	TXNN Q3,US.PRQ		;DOES THIS UNIT POSITION?
	JRST SIO4		;NO - APPEND TO TWQ
	CALL UDSCNV(T2)		;YES - GET CYLINDER (PS1) IN T2
SIO2DL::CAME T2,UDBPS1(P3)	;SAME AS CURRENT UDBPS1? (TAG FOR DLLOOK)
	JRST SIO3		;NO - POSITIONING NEEDED
	SOSLE UDBFCT(P3)	;YES - SHOULD WE DO SOME OTHER CYL?
	JRST SIO4		;NO - ADD REQUEST TO TWQ
	HRRZ T1,UDBPWQ(P3)	;COUNT EXHAUSTED, REQUESTS TO OTHER CYLS?
	JUMPE T1,SIO4		;IF NO, APPEND TO TWQ ANYWAY
SIO3:	MOVE T1,P4		;PLACE ON PWQ
	CALL ONPWQ		; ...
SIO3A:	MOVX T1,US.OIR!US.OMS!US.POS!US.ACT!US.MAI!US.MRQ!US.REW
	MOVX T2,CS.MAI!CS.MRQ!CS.OFL	;GET FLAGS READY
	TDNN T1,UDBSTS(P3)	;UNIT AVAILABLE?
	TDNE T2,CDBSTS(P1)	;AND CHANNEL AVAILABLE?
	JRST ONRET		;NO, DO NOTHING
	MOVX T1,KS.ACT		;GET CONTROLLER BUSY FLAG
	TRNE P2,-1		;IS THERE A CONTROLLER?
	TDNN T1,KDBSTS(P2)	; ...
	SKIPA			;(NO,NO)
	JRST ONRET		;(YES,YES)
	HRRZ T1,UDBTWQ(P3)	;ARE THERE ANY TRANSFER PENDING ON CYLINDER?
	JUMPN T1,ONRET		;IF SO, DONT MOVE UNIT
	CALL STRTPS		;UNIT FREE - START POSITIONING
	 JFCL			;COULDNT DO IT, BUT NOTHING ELSE TO DO
	JRST ONRET		;ENABLE PI AND RETURN
;HERE WHEN REQUEST NEEDS NO POSITIONING

SIO4:	MOVE T1,P4		;PLACE ON TWQ
	CALL ONTWQ		; ...
	SKIPE PWRDWN		;POWER FAILING?
	JRST ONRET		;YES - DONT STARTUP A NEW REQUEST
	MOVE T2,UDBSTS(P3)	;GET UNIT STATUS
	TXNE T2,US.POS!US.REW!US.OIR!US.OMS!US.MAI!US.MRQ ;UNIT AVAILABLE?
	JRST ONRET		;NO.
	MOVE T1,CDBSTS(P1)	;GET CURRENT CHANNEL STATUS
	TXNE T1,CS.OFL!CS.AC2!CS.MAI!CS.MRQ	;CHANNEL AVAILABLE?
	JRST SIO7		;NO, SEE IF ALTERNATE PATH EXISTS
	TXNN T1,CS.AC1		;PRIMARY COMMAND ACTIVE?
	JRST SIO5		;NO - SEE IF UNIT REALLY FREE
	TXNN T2,US.DSK		;IS THIS A DISK?
	JRST ONRET		;NO, DON'T STACK FOR MAGTAPES
	MOVE T1,CDBXFR(P1)	;IS THIS THE ACTIVE UNIT?
	CAME T1,UDBADR(P3)	; ???
	JRST SIO7		;NO, SEE IF ALTERNATE PATH AVAILABLE
	CALL SCHXFR		;YES, SEE IF WE CAN STACK ANOTHER COMMAND
	JRST ONRET

SIO5:	MOVX T1,US.ACT		;GET ACTIVE BIT FOR UNIT
	MOVX T2,KS.ACT		;AND FOR THE CONTROLLER
	TRNE P2,-1		;CHECK FOR EXISTANCE OF CONTROLLER
	TDNN T2,KDBSTS(P2)	;CONTROLLER BUSY?
	TDNE T1,UDBSTS(P3)	;OR THE UNIT?
	JRST ONRET		;YES, DO NOTHING
	HRRZ P4,UDBTWQ(P3)	;GET THE IORB ON HEAD OF THE TWQ
	CALL STRTIO		;STARTUP THIS UNIT
	 JFCL			;CANT START IT, BUT NOTHING ELSE TO DO.
	JRST ONRET		;RESTORE PI

;HERE TO SEE IF REQUEST SHOULD GO THROUGH POSITION CYCLE

SIO6:	CALL UDSPRQ(T2)		;ASK DEVICE
	 JRST SIO4		;TRANSFER ONLY
	JRST SIO3		;POSITION FIRST
;HERE TO SEE IF REQUEST CAN BE STARTED ON ALTERNATE PATH
SIO7:	TXNE T2,US.ACT		;IS UNIT ACTIVE?
	JRST ONRET		;YES, GO AWAY
	MOVE P5,P3		;NO, SAVE ORIGINAL UDB
	SKIPE P3,UDB2ND(P3)	;DRIVE DUAL-PORTED?
	SKIPG UDBSTS(P3)	;YES, OTHER PORT ON-LINE?
	JRST ONRET		;NO, RETURN
	CALL CKSTRT		;CAN WE START IO ON THIS PORT?
	 JRST ONRET		;NO, CAN'T START IT. RETURN
	CALL STRALT		;TRY TO START IT ON ALTERNATE PATH
	JRST ONRET		;RESTORE PI AND RETURN

;HERE IF THE UNIT IS ON A CI PORT. START THE IO
SIO8:	MOVE T1,P4		;PUT REQUEST ON FRONT OF TWQ
	CALL ONFTWQ
	CALL STRTIO		;START IT UP
	 JFCL			;COULDN'T START IT
	JRST ONRET		;RESTORE PI AND RETURN

;HERE TO SEE IF WE CAN START IO ON THE UDB POINTED TO BY P3
;ENTER WITH
;P3/UDB OF PORT TO START IO ON
;EXIT WITH
;P1/CDB OF THE UNIT
;P2/KDB OF THE UNIT
;RETURNS +1 IF CHAN/CONTROL ARE BUSY
;	 +2 IF CHAN/CONTROL ARE IDLE
CKSTRT:	HRRZ P2,UDBKDB(P3)	;YES, SET UP P2 AND P1
	HRRZ P1,UDBCDB(P3)	; POINTING AT ALTERNATE CONTROLLER, CHANNEL
	MOVX T1,CS.ACT		;ARE CHAN, CONTROL AVAILABLE?
	MOVX T2,KS.ACT		;...
	TRNE P2,-1		;CONTROLLER EXIST?
	TDNN T2,KDBSTS(P2)	;YES, IDLE?
	TDNE T1,CDBSTS(P1)	;AND CHAN IDLE?
	RET			;BUSY
	RETSKP			;IDLE

;HERE TO START AN IO ON THE ALTERNATE PATH
;ENTER WITH
;P3/UDB ADDRESS OF ALTERNATE PORT
;P5/UDB ADDRESS OF MAIN PORT
;RETURNS +1 (ALWAYS)
STRALT:	EXCH P3,P5		;WE'LL START IT ON ALTERNATE PATH
	CALL OFFTWQ		;PULL FROM TWQ FOR PRIME PORT
	HRRZ P4,T1		;POINT P4 AT FIRST IORB
	EXCH P3,P5
	CALL ONFTWQ		;PUT IT AS (ONLY) IORB ON ALTERNATE PORT
	CALL STRTIO		;STARTUP THE IORB
	  SKIPA			;CANT START IT NOW (PROBABLY OFF-LINE)
	JRST STRAL1		;STARTED - FINISH UP
	HRRZ T1,UDBTWQ(P3)	;NO START. IF TWQ IS NOW EMPTY
	JUMPE T1,R		; THE IORB WAS REMOVED, WE'RE DONE
	CALL OFFTWQ		;REMOVE FROM TWQ OF ALTERNATE UNIT
	EXCH P3,P5		; (WANT TO KEEP THAT UDB CLEAN)
	CALL ONFTWQ		;PUT IT ON FRONT OF TWQ OF PRIME UDB
	RET			;AND RETURN TO CALLER

;HERE IF IORB WAS STARTED ON ALTERNATE PATH
STRAL1:	MOVX T1,US.ACT		;INDICATE PRIME UDB IS ACTIVE TOO
	IORM T1,UDBSTS(P5)	; SO WE WON'T TRY TO START BOTH PORTS AT ONCE
	RET
	SUBTTL POSITION DONE
;POSITION DONE - TRANSFER ALL REQUESTS FOR THIS CYLINDER FROM PWQ TO TWQ
;CALLED ONLY AT INTERRUPT LEVEL
;P1/ CDB, P3/ UDB, USES P4


PHYSDN::CALL CLRSRC		;UNIT NO LONGER SEARCHING
	SKIPA			;SKIP
PHYPDN::CALL CLRPOS		;UNIT NO LONGER POSITIONING
	HRRZ P4,UDBPWQ(P3)	;GET HEAD OF PWQ
	CALL ERRFIN		;RETURN ERROR BLOCK IF ONE ACTIVE
	SAVEQ
	MOVEI T1,INIFCP		;RESET FAIRNESS COUNT FOR POSITIONING
	MOVEM T1,UDBFCT(P3)	; ...
	MOVEI Q1,UDBPWQ(P3)	;PREVIOUS IORB IS INITIALLY HEAD CELL
	HRRZ Q2,UDBDSP(P3)	;GET UNIT DISPATCH
	SKIPN P4		;WAS PWQ NULL?
	JRST PDN4		;YES - COMPLAIN THEN EXIT
PDN1:	CALL UDSCNV(Q2)		;GET CYLINDER FOR IORB IN P4
	CAME T2,UDBPS1(P3)	;SAME AS CURRENT CYLINDER?
	JRST PDN3		;NO - KEEP LOOKING
	MOVE T1,Q1		;PREDECESSOR
	MOVE T2,P4		;CURRENT IORB
	CALL CONSPW		;REMOVE CURRENT, SPLICE PWQ
	MOVE T1,P4		;APPEND CURRENT TO TWQ
	CALL ONTWQ		; ...
PDN2:	HRRZ P4,IRBLNK(Q1)	;GET NEW CURRENT IORB
	JUMPN P4,PDN1		;IF NOT AT END, KEEP LOOKING
	HRRZ T1,UDBTWQ(P3)	;CHECK SOME REQUEST WAS FOUND
	SKIPN T1		; ??
	BUG.(CHK,NRFTCL,PHYSIO,HARD,<PHYSIO - No requests found for cylinder seeked>,,<

Cause:	The routine PHYPDN was called on a position-done interrupt
	to transfer any IORBs that were on the position wait queue
	into the transfer wait queue; but no IORBs were found which
	were for this cylinder.
>)
	RET			;YES - ALL IS WELL

PDN3:	MOVE Q1,P4		;MOVE DOWN THE LIST
	JRST PDN2		;AND CONTINUE

;**;[7264] Add 1 LINE AT PDN4:		JDM	11-MAR-86
PDN4:	CALL FNDCKU		;[7264](P1,P3/T1,T2,T3)GET CHAN,CONTROLLER,UNIT
	BUG.(CHK,NPWQPD,PHYSIO,HARD,<PHYSIO - Null PWQ at position done>,<<T1,CHAN>,<T2,CONTRL>,<T3,UNIT>>,<

Cause:	A position-done interrupt occurred, and the routine PHYPDN was
	called to move IORBs from the position wait queue into the
	transfer wait queue, but the position wait queue was empty.

Action:	If the problem persists, notify field service

Data:	CHAN - The channel number
	CONTRL - The controller number (-1 if no controller)
	UNIT - The unit number
>)
	RET			;JUST EXIT
	SUBTTL UTILITIES
;ENTER WITH
;T1/ UNIT NUMBER
;P1/ CDB
;	CALL SETUDB
;RETURNS+1(ALWAYS):
;P2/ KDB (IF APPROPRIATE)
;P3/ UDB CORRESPONDING TO SPECIFIED UNIT # ON CHANNEL
;  NOTE: IN THE CASE OF TAPES P3 MAY BE -1 SINCE WE RETURN THE ACTIVE UDB
;T1/ UNCHANGED
;T2/ DISPATCH FOR CORRESPONDING UNIT TYPE

SETUDB::MOVE T2,CDBIUN(P1)	;GET UDB TABLE POINTER
	HLRE T3,T2		;SEE IF LEGAL NUMBER
	MOVNS T3		;AS POSITIVE NUMBER
	CAIL T1,(T3)		;LEGAL?
	BUG.(HLT,PYILUN,PHYSIO,HARD,<PHYSIO - Illegal unit number>,,<

Cause:	The routine SETUDB was called to find the UDB and KDB pointers
	given the CDB and unit number, but the unit number given was
	out of range.
>)
	ADD T2,T1		;GET UDB
	SKIPN P3,(T2)		; ...
	JRST SETUD2		;NONE PRESENT
	LDB T2,USYBKT		;GET BLOCK TYPE
	CAIE T2,.BTUDB		;UDB?
	JRST SETUD1		;NO
	HRRZ P2,UDBKDB(P3) 	;GET KDB IF ANY
	HRRZ T2,UDBDSP(P3)	;RETURN DISPATCH
	RET

SETUD1:	MOVE P2,P3		;COPY KDB
	SKIPN P3,KDBACT(P2)	;GET THE ACTIVE UDB IF POSSIBLE
	SETO P3,		;RETURN -1 IF NOT THERE
	HRRZ T2,KDBDSP(P2)	;AND RETURN DISPATCH
	RET
SETUD2:	SETZB P2,P3		;RETURN 0
	RET

;UTILITY TO RETURN THE ACTIVE IORB ON A UNIT
;P3/ UDB
;	CALL SETIRB
;RETURNS+1(ALWAYS):
;P4/ ACTIVE IORB
;PRESERVES T1

SETIRB::HRRZ P4,UDBPWQ(P3)	;ASSUME POSITIONING
	MOVX T2,US.POS		;IS UNIT REALLY POSITIONING?
	TDNN T2,UDBSTS(P3)	; ???
	HRRZ P4,UDBTWQ(P3)	;NO - GET HEAD OF TWQ
	JUMPN P4,R		;RETURN IF THERE REALLY WAS ONE
	BUG.(HLT,NOIORB,PHYSIO,HARD,<SETIRB - Missing IORB>,,<

Cause:	The routine SETIRB was called for an active unit to return
	the currently active IORB for the unit, but the position wait
	queue or transfer wait queue was empty.
>)
;DETERMINE THE UNIT RELATIVE ADDRESS FOR A DISK REQUEST

;P4/ IORB
;	CALL PHYBLK
;RETURNS+1(ALWAYS):
;T2/ UNIT RELATIVE ADDRESS
;CLOBBERS T1,T2

PHYBLK::
	EA.ENT			;WE NEED TO BE IN SECTION ONE
	SKIPL IRBSTS(P4)	;SHORT IORB?
	JRST BLK1		;NO
	MOVEI T2,-CST5(P4)	;YES - GET CPN
	LOAD T2,CSTLDA,+T2	;GET UNIT RELATIVE ADDRESS
	RET

BLK1:	MOVE T2,IRBADR(P4)	;GET UNIT RELATIVE ADDRESS
	RET
;DETERMINE CORRECT CHANNEL AND UNIT FROM A DISK REQUEST

;P4/ IORB
;T4/ STRUCTURE NUMBER IF NOT FROM PAGEM
;	CALL GETCUB
;PRESERVES T3,4
;DESTROYS T2
;RETURNS+1:
;ERROR - INVALID ADDRESS
;RETURNS+2:
;T1/ UNIT RELATIVE ADDRESS
;P1/ CDB
;P2/ KDB, OR 0 IF NONE
;P3/ UDB
;
;LOCAL FLAGS IN THE LEFT OF T2
;DSKAB, DRMOB


GETCUB:	SAVEQ			;PRESERVE ACCUMULATORS
	SETZ T2,		;CLEAR OUR FLAGS, FOR NOW
	SKIPGE IRBSTS(P4)	;SHORT FORM IORB?
	JRST GTCUB5		;YES - GET CST1
	MOVE Q2,IRBADR(P4)	;NO - GET IORB ADDRESS
	MOVEI Q1,0(T4)		;SAVE STRUCTURE NUMBER
GTCUB1:	SKIPN Q1,STRTAB(Q1)	;ANY SUCH STRUCTURE?
	RET			;ILLEGAL STRUCTURE
	HRR T2,Q1		;SAVE A POINTER TO THE SDB
	HLL T2,Q2		;SAVE IORB STATUS BITS
	TXNN Q2,DSKAB		;DISK ADDRESS?
	JRST GTCUB3		;NO - SWAP ADDRESS
	TLZ Q2,DSKMSK		;CLEAR UNUSED BITS
	IDIV Q2,SDBSIZ(Q1)	;GET UNIT, RELATIVE ADDRESS
	CAML Q2,SDBNUM(Q1)	;LEGAL UNIT?
	RET			;UNIT TOO LARGE
GTCUB2:	ADDI Q2,SDBUDB(Q1)	;GET UDB ADDRESS
	MOVE P3,(Q2)		; ...
	HRRZ P1,UDBCDB(P3)	;FOLLOW BACK POINTER TO CDB
GTCUBX:	HRRZ P2,UDBKDB(P3)	;AND FOLLOW POINTER TO KDB
	LDB T1,IRYFCN		;GET IO TYPE
	CAIN T1,IRFWRT		;WAS IT A WRITE?
	JRST [	SKIPL IRBSTS(P4);PARANOID CHECK FOR SHORT FORM IORB
		JRST .+1	;IT WAS LONG, SO RETURN
		HRRZ Q1,T2	;GET ADDRESS
		MOVE Q1,SDBSTS(Q1);GET STATUS BITS FROM STRUCTURE DATA BLOCK
		TXNN T2,DSKAB	;SWAPPING REQUEST?
		MOVEI T1,IRFWVC	;INDICATE WRITE VERIFICATION NEEDED
		TXNE Q1,MS%RWS	;SWAP VERIFICATION TURNED ON?
		DPB T1,IRYFCN	;YES, UPDATE IORB
		MOVEI T1,IRFWVC	;MAKE SURE WE HAVE THE RIGHT FUNCTION
		SKIPE VSMFLG	;ARE WE FORCING THE ISSUE?
		DPB T1,IRYFCN	;YES, DO IT
		TXNN T2,DSKAB	;DISK ADDRESS
		JRST .+1	;NO, RETURN TO MAIL LINE
		TXNE Q1,MS%RWD	;VERIFYING DATA?
		DPB T1,IRYFCN	;YES, SET VERIFY FUNCTION
		JRST .+1]
	MOVE T1,Q3		;UNIT RELATIVE ADDRESS
	RETSKP			;SUCCESS RETURN

;HERE IF SWAPPING ADDRESS

GTCUB3:	TXNN Q2,DRMOB		;REAL DRUM ADDRESS?
	JRST GTCUB4		;YES
	TLZ Q2,-1		;NO - CLEAR UNUSED BITS ***SYMBOL***
	MOVE T1,SDBTYP(Q1)	;GET TYPE OF THIS DEVICE
	IDIV Q2,SECCYL(T1)	;GET TRACK(CYLINDER), SECTOR IN TRACK
	MOVE P3,Q3		;SAVE SECTOR WITHIN TRACK
	IDIV Q2,SDBNUM(Q1)	;GET UNIT RELATIVE TRACK, UNIT
	EXCH Q2,Q3		;PUT UNIT IN Q2
	IMUL Q3,SECCYL(T1)	;GET SECTOR STARTING TRACK ON UNIT
	ADD Q3,P3		;ADD SECTOR WITHIN TRACK
	CAML Q3,SDBNSS(Q1)	;CHECK WITHIN LIMIT
	RET			;SWAPPING ADDRESS TOO LARGE
	ADD Q3,SDBFSS(Q1)	;SWAP AREA OFFSET
	JRST GTCUB2		;JOIN OTHER CODE
;HERE IF REAL DRUM ADDRESS

GTCUB4:	LOAD Q1,DRTRK,Q2	;GET TRACK
	LOAD Q2,DRSEC,Q2	;GET SECTOR
	IMULI Q1,DRMSEC		;GET SECTORS
	ADD Q2,Q1		;INTO Q2
	IDIVI Q2,NTRK*DRMSEC	;GET UNIT AND RELATIVE ADDRESS
	HLRZ P1,DRMTAB(Q2)	;GET CDB
	HRRZ P3,DRMTAB(Q2)	;GET UDB
	JRST GTCUBX

;HERE ON A PAGEM REQUEST

GTCUB5:
	MOVEI Q2,-CST5(P4)	;GET CPN
	CALL [	EA.ENT		;ENTER SECTION ONE
		MOVE Q1,@CST2X+Q2 ;GET OWNER IDENT
		RET]		;AND RETURN TO CORRECT SECTION
	CAIL Q1,NOFN		;FILE?
	JRST GTCB5A		;NO
	MOVX T1,OFN2XB		;SECOND XB
	TDNN T1,SPTH(Q1)	; ??
	JRST GTCB5A		;NO
	LDB T1,IRYFCN		;GET OPERATION
	CAIE T1,IRFRVC		;READ VERIFY
	CAIN T1,IRFRED		;READ?
	AOSA XB2RED		;YES
	AOS XB2WRT		;NO - WRITE

GTCB5A:
	CALL [	EA.ENT		;ENTER SECTION ONE
		MOVE Q2,@CST1X+Q2 ;GET DISK ADDRESS
		RET]		;AND RETURN TO CORRECT SECTION
	HLL T2,Q2		;SAVE THE BITS FOR LATER
	SETZ Q1,		;ASSUME STRUCTURE 0
	TXNN Q2,DSKAB		;IS THIS A DISK REQUEST?
	JRST GTCUB1		;NO. GO DO SWAPPING REQUEST
	MOVEI T1,-CST5(P4)	;GET CORE PAGE NUMBER
	CALL FNDSTR		;GO GET STRUCTURE NUMBER FROM PAGEM
	MOVEI Q1,0(B)		;PUT IT IN THE RIGHT PLACE
	JRST GTCUB1		;JOIN OTHER PROCESSING
;HERE TO GET THE IOLIST ASSOCIATED WITH AN IORB

;P4/ IORB
;P1/ CDB
;P3/ UDB
;CALL PHYXFL
;RETURNS+1(ALWAYS):
;T1/ POINTER TO TRANSFER LIST
;T2/ POINTER TO END OF TRANSFER LIST


PHYXFL::SKIPL IRBSTS(P4)	;SHORT IORB?
	JRST XFL1		;NO - HAS OWN POINTER
	MOVE T1,[IRMWRD,,PGSIZ]	;WORD MODE, ONE PAGE
	LDB T2,IRYFCN		;GET FUNCTION CODE
	CAIN T2,IRFRVC		;READ VALIDITY CHECK?
	JRST [	MOVEI T2,SKPPAG	;YES, CLEAR PAGE, AND WRITE INTO 0
		JRST PHYXF2]	;KEEP ON WITH SETUP
	MOVEI T2,-CST5(P4)	;GET CPN
	LSH T2,PGSFT		;AS ADDRESS
PHYXF2:	HRRZ T4,CDBDSP(P1)	;GET CHANNEL DISPATCH
	CALL CDSCCW(T4)		;FORM CCW FOR THIS CHANNEL
	MOVEI T2,CDBCCL(P1)	;COMPUTE LIST TO USE, ASSUME PRIMARY
	HLL CX,CDBSTS(P1)	;GET CHAN STATUS
	TXNE CX,CS.ACL		;USE ALTERNATE?
	MOVEI T2,CDBCL2(P1)	;YES
	MOVEM T1,(T2)		;STORE IN CDB
	SETZM 1(T2)		;MARK END WITH ZERO
	MOVE T1,T2		;RETURN ADDRESS
	ADDI T2,1		;ADDRESS OF END
	RET

;HERE ON LONG FORM IORB

XFL1:	HRRZ T1,IRBXFL(P4)	;GET USERS TRANSFER LIST
	HLRZ T2,IRBXFL(P4)	;GET TAIL OF USERS LIST
	RET

;HERE TO GET THE BYTE COUNT ASSOCIATED WITH AN IORB

;P4/ IORB
;	CALL PHYCNT
;RETURNS+1(ALWAYS):
;T1/ BYTE COUNT
;PRESERVES T3,T4

PHYCNT::SKIPL IRBSTS(P4)	;SHORT IORB?
	SKIPA T1,IRBCNT(P4)	;NO, GET COUNT FROM IORB
	MOVEI T1,PGSIZ		;YES - ALL ONE SIZE
	RET
;UTILITY TO APPEND TO TWQ
;T1/ IORB
;	CALL ONTWQ
;RETURNS+1(ALWAYS):
;T1/ UNCHANGED

ONTWQ::	HLRZ T2,UDBTWQ(P3)	;GET TAIL OF TWQ
	HRRZ T3,IRBLNK(T2)	;INSURE TAIL REALLY WAS TAIL
	JUMPN T3,IRBERR		;NOT TAIL - BOMB
	HRRM T1,IRBLNK(T2)	;STORE NEW TAIL
	HRLM T1,UDBTWQ(P3)	; ...
	RET

;HERE TO PLACE AN IORB AT THE FRONT OF THE TWQ
;T1/ IORB
;P3/ UDB
;	CALL ONFTWQ
;RETURNS+1(ALWAYS):
;	IORB AT HEAD OF TWQ

ONFTWQ::HRRZ T2,IRBLNK(T1)	;CHECK LINK OF NEW IORB IS NULL
	JUMPN T2,IRBNNT		;IF NOT NULL, DIE PROMPTLY
	HRRZ T2,UDBTWQ(P3)	;GET CURRENT HEAD OF TWQ
	HRRM T2,IRBLNK(T1)	;POINT LINK OF NEW IORB AT IT
	HRRM T1,UDBTWQ(P3)	;NEW IORB IS NEW HEAD OF LIST
	JUMPN T2,R		;WAS TWQ NON NULL?
	HLRZ T3,UDBTWQ(P3)	;WAS NULL
	CAIE T3,UDBTWQ(P3)	;CHECK TAIL WAS FOR NULL LIST
	JRST IRBERR		;POINTER WAS BAD
	HRLM T1,UDBTWQ(P3)	;STORE NEW IORB AS NEW TAIL
	RET

IRBNNT:	BUG.(HLT,ILRBLT,PHYSIO,HARD,<PHYSIO - IORB link not null at ONF/STWQ>,,<

Cause:	One of the routines ONFTWQ or ONSTWQ was called to insert an IORB
	into the transfer wait queue, but the link word for that IORB
	was not zero.  IORBs should always contain a null link when
	they are created or removed from a queue, so that many queue
	handling errors can be detected.
>)

;HERE TO PLACE AN IORB AS THE SECOND ELEMENT ON A UNITS TWQ
;ASSUMES THE FIRST ELEMENT EXISTS
;T1/ IORB
;	CALL ONSTWQ
;RETURNS+1(ALWAYS):
;	IORB SECOND ON TWQ
;T1/ UNCHANGED

ONSTWQ:	HRRZ T2,IRBLNK(T1)	;CHECK LINK OF IORB IS NULL
	JUMPN T2,IRBNNT		;IF NOT NULL, WE HAVE TROUBLE
	HRRZ T2,UDBTWQ(P3)	;GET CURRENT HEAD OF TWQ
	HRRZ T3,IRBLNK(T2)	;GET CURRENT SECOND ELEMENT
	HRRM T1,IRBLNK(T2)	;THIS IORB IS NOW SECOND
	HRRM T3,IRBLNK(T1)	;OLD SECOND IS NOW SUCCESSOR
	JUMPN T3,R		;IF SUCCESSOR NONNULL, DONE
	HRLM T1,UDBTWQ(P3)	;SUCCESSOR NULL, NEW IORB IS TAIL
	RET			;DONE
;APPEND TO PWQ
;T1/ IORB
;P3/ UDB
;	CALL ONPWQ
;RETURNS+1(ALWAYS):

ONPWQ::	HLRZ T2,UDBPWQ(P3)	;GET TAIL POINTER
	HRRZ T3,IRBLNK(T2)	;CHECK IT REALLY WAS THE TAIL
	JUMPN T3,IRBERR		;NO - BOMB
	HRRM T1,IRBLNK(T2)	;POINT TO NEW TAIL
	HRLM T1,UDBPWQ(P3)	; ...
	RET

;HERE IF THE CURRENT TAIL OF TWQ/PWQ HAS A NON ZERO FORWARD POINTER

IRBERR:	BUG.(HLT,ILTWQP,PHYSIO,HARD,<PHYSIO - PWQ or TWQ tail pointer incorrect>,,<

Cause:	The pointer to the last element in the position wait queue or
	transfer wait queue (UDBPWQ or UDBTWQ) points to an IORB which
	has a non-null link to further IORBs.  This is checked in various
	routines such as ONTWQ, ONPWQ, ONSTWQ, ONFPWQ, CONSTW, or CONSPW.
>)

;HERE TO PLACE AN IORB AT THE FRONT OF THE PWQ
;T1/ IORB
;P3/ UDB
;	CALL ONFPWQ
;RETURNS+1(ALWAYS):
;	IORB AT HEAD OF PWQ

ONFPWQ::HRRZ T2,IRBLNK(T1)	;CHECK LINK OF NEW IORB IS NULL
	JUMPN T2,IRBNNL		;IT IS NOT NULL, LOSE BIG
	HRRZ T2,UDBPWQ(P3)	;GET CURRENT HEAD OF PWQ
	HRRM T2,IRBLNK(T1)	;POINT LINK OF NEW IORB AT IT
	HRRM T1,UDBPWQ(P3)	;NEW IORB IS NEW HEAD OF LIST
	JUMPN T2,R		;WAS PWQ NON NULL?
	HLRZ T3,UDBPWQ(P3)	;WAS NULL, CHECK TAIL POINTER
	CAIE T3,UDBPWQ(P3)	;CORRECT NULL LIST?
	JRST IRBERR		;NO
	HRLM T1,UDBPWQ(P3)	;YES - NEW HEAD IS ALSO NEW TAIL
	RET

IRBNNL:	BUG.(HLT,ILIRBL,PHYSIO,HARD,<PHYSIO - IORB link not null at ONFPWQ>,,<

Cause:	The routine ONFPWQ was called to place an IORB at the front
	of the position wait queue for a unit.  But the link field
	in the IORB pointing to the next IORB was not null.
>)
;HERE TO REMOVE AN ARBITRARY ELEMENT FROM THE TWQ
;T1/ PREDECESSOR OF ELEMENT TO BE REMOVED
;T2/ ELEMENT TO BE REMOVED
;	CALL CONSTW
;RETURNS+1(ALWAYS):
;	ELEMENT REMOVED
;**SEE NOTE AT START OF CONSPW**

CONSTW::JUMPE T1,CNSTWE		;CHECK ARGUMENTS
	JUMPE T2,CNSTWE		; ...
	HRRZ T3,IRBLNK(T1)	;CHECK FOR REMOVAL OF EXACTLY ONE ELEMENT
	CAME T2,T3		; ...
	JRST CNSTWE		;MULTIPLE ELEMENTS, CURRENTLY ILLEGAL
	HRRZ T3,IRBLNK(T2)	;GET HEAD OF RIGHT RESIDUE LIST
	HLRZ T4,UDBTWQ(P3)	;GET TAIL OF TWQ
	CAME T4,T2		;IS TAIL OF LIST BEING REMOVED?
	JRST CNSTW1		;NO
	JUMPN T3,IRBERR		;YES - INSURE RIGHT RESIDUE REALLY NULL
	HRLM T1,UDBTWQ(P3)	;BACKUP TAIL OF TWQ
CNSTW1:	HRRM T3,IRBLNK(T1)	;POINT PREDECESSOR TO SUCCESSOR
	HLLZS IRBLNK(T2)	;CLEAR LINK IN REMOVED ELEMENT
	RET

CNSTWE:	BUG.(HLT,ILCNST,PHYSIO,HARD,<PHYSIO - Illegal call to CONSTW>,,<

Cause:	The routine CONSTW was called to remove an element from the
	transfer wait queue of a unit, but the arguments are illegal.
	Either the arguments are null, or CONSTW is trying to remove more than
	one element because it was passed more than one arguement.

>)

;HERE TO REMOVE AN ARBITRARY ELEMENT FROM THE PWQ
;T1/ PREDECESSOR OF ELEMENT TO BE REMOVED
;T2/ ELEMENT TO BE REMOVED
;	CALL CONSPW
;RETURNS+1(ALWAYS):
;ELEMENT REMOVED
;NOTE: THE REASON TWO ARGUMENTS ARE REQUIRED IS TO ALLOW FOR POSSIBLE
;	EXTENSION TO THE REMOVAL OF SUBLISTS. IN THIS CASE, T1 WOULD BE
;	THE PREDECESSOR OF THE FIRST ELEMENT TO BE REMOVED, T2 WOULD BE
;	THE LAST ELEMENT IN THE SUBLIST TO BE REMOVED. THIS CASE IS
;	CURRENTLY DETECTED AS ILLEGAL.

CONSPW:	JUMPE T1,CNSPWE		;VALIDATE ARGUMENTS
	JUMPE T2,CNSPWE		; ...
	HRRZ T3,IRBLNK(T1)	;CHECK ONE AND ONLY ONE ELEMENT IS
	CAME T2,T3		;BEING REMOVED.
	JRST CNSPWE		;MULTIPLE ELEMENTS, ILLEGAL
	HRRZ T3,IRBLNK(T2)	;GET HEAD OF LIST AFTER ELEMENT REMOVED
	HLRZ T4,UDBPWQ(P3)	;GET TAIL OF LIST
	CAME T4,T2		;IS TAIL BEING REMOVED?
	JRST CNSPW1		;NO, NOTHING SPECIAL
	JUMPN T3,IRBERR		;YES - INSURE RESIDUE REALLY NULL
	HRLM T1,UDBPWQ(P3)	;BACKUP TAIL OF LIST
CNSPW1:	HRRM T3,IRBLNK(T1)	;POINT PREDECESSOR TO SUCCESSOR
	HLLZS IRBLNK(T2)	;CLEAR LINK IN ELEMENT REMOVED
	RET

CNSPWE:	BUG.(HLT,ILCNSP,PHYSIO,HARD,<PHYSIO - Illegal call to CONSPW>,,<

Cause:	The routine CONSPW was called to remove an element from the
	position wait queue of a unit, but the arguments are illegal.
	Either the arguments are null, or CONSPW is trying to remove more
	than one element because it was passed more than one arguement.
>)
;UTILITY TO DEQUEUE THE HEAD OF A UNITS TWQ
;P3/ UDB
;	CALL OFFTWQ
;RETURNS+1(ALWAYS):
;T1/ IORB

OFFTWQ::HRRZ T1,UDBTWQ(P3)	;GET IORB AT HEAD OF TWQ
	JUMPE T1,IRBMIS		;NO - BOMB
	HRRZ T2,IRBLNK(T1)	;GET FORWARD LINK
	HLLZS IRBLNK(T1)	;CLEAR TAIL POINTER
	HRRM T2,UDBTWQ(P3)	;NOW AT HEAD
	JUMPN T2,R		;UNLESS NOW NULL
	MOVSI T2,UDBTWQ(P3)	;NOW NULL - RESET LIST
	MOVEM T2,UDBTWQ(P3)	; ...
	RET

;UTILITY TO REMOVE THE HEAD OF A UNITS PWQ
;JUST LIKE OFFTWQ

OFFPWQ::HRRZ T1,UDBPWQ(P3)	;GET IORB AT HEAD OF PWQ
	JUMPE T1,IRBMIS		;NO - BOMB
	HRRZ T2,IRBLNK(T1)	;GET FORWARD LINK
	HLLZS IRBLNK(T1)	;CLEAR TAIL POINTER
	HRRM T2,UDBPWQ(P3)	;NOW AT HEAD
	JUMPN T2,R		;UNLESS NOW NULL
	MOVSI T2,UDBPWQ(P3)	;NOW NULL - RESET LIST
	MOVEM T2,UDBPWQ(P3)	; ...
	RET

;HERE IF PWQ OR TWQ WAS NULL AT OFFPWQ/TWQ

IRBMIS:	BUG.(HLT,TWQNUL,PHYSIO,HARD,<PHYSIO - PWQ OR TWQ was null at a seek or transfer completion>,,<

Cause:	When I/O completed on a unit, either OFFTWQ or OFFPWQ was called to
	remove the current IORB from the position wait queue or the transfer
	wait queue.  The error occurred because the queue was empty.
>)
;HERE TO REMOVE ALL NON ACTIVE IORBS FROM A UNIT TRANSFER QUEUE
;	NOTE: THIS ROUTINE IS NOT CURRENTLY CALLED FOR DISK UDBS

;P1 & P3 SETUP
;	CALL PHYKIL
;RETURNS+1(ALWAYS):
;T1/ HEAD OF LIST OF IORBS
;NOTE: THIS ROUTINE CAN BE CALLED FROM NONZERO SECTIONS

PHYKIL::SAVEP			;SAVE REGISTERS
	HRRZ P3,T1		;SETUP UDB
	HLRZ P1,T1		;SETUP CDB
	SETZM CDBIRB(P1)	;NO PREFERENTIAL IORB ANYMORE
	MOVX T1,US.ACT		;GET ACTIVE BITS READY FOR TESTING
	MOVX T2,US.POS		; ...
	MOVX T3,US.CIP		;CHECK FOR CI
	TDNE T3,UDBSTS(P3)	;CHECK FOR CI TAPE
	CALLRET PHYMKL		;KILL IT
	PIOFF			;PREVENT RACE - MUST NEST IN IOPIOF
	TDNN T1,UDBSTS(P3)	; .?.
	JRST KILALL		;NO - CAN PRUNE ALL
	TDNE T2,UDBSTS(P3)	;UNIT ACTIVE. POSITIONING?
	JRST KIL2		;YES
	HRRZ T2,UDBTWQ(P3)	;PICK UP ACTIVE IORB
	HRRZ T1,IRBLNK(T2)	;LINK FORWARD
	JUMPE T1,KIL1		;CHECK PWQ
	HLLZS IRBLNK(T2)	;CLEAR FORWARD LINK
	HLRZ T3,UDBTWQ(P3)	;GET TAIL POINTER
	HRLM T2,UDBTWQ(P3)	;UPDATE TAIL POINTER
KIL1:	HRRZ T2,UDBPWQ(P3)	;GET HEAD OF PWQ
	JUMPE T2,PIONRT		;IF NIL, RETURN
	HRRM T2,IRBLNK(T3)	;APPEND TO TWQ LIST
	MOVSI T2,UDBPWQ(P3)	;RESET PWQ TO NULL
	MOVEM T2,UDBPWQ(P3)	; ...
	JRST PIONRT		;RETURN

KIL2:	HRRZ T2,UDBPWQ(P3)	;HERE WHEN POSITIONING ACTIVE
	HRRZ T1,IRBLNK(T2)	;GET ENTRY AFTER HEAD
	JUMPE T1,PIONRT		;RETURN NULL
	HLLZS IRBLNK(T2)	;CLEAR FORWARD LINK
	HRLM T2,UDBPWQ(P3)	;UPDATE END OF LIST
	JRST PIONRT		;RETURN

;HERE TO KILL ALL IORBS

KILALL:	HRRZ P4,UDBTWQ(P3)	;GET IORB
	JUMPN P4,KILA1		;IF PRESENT, USE FOR ERRFIN
	HRRZ P4,UDBPWQ(P3)	;NO TRANSFER, IS THERE POSITIONING
	JUMPE P4,KILA2		;NO, SKIP ERRFIN
KILA1:	CALL ERRFIN		;TERMINATE ERROR RECOVERY IF NEEDED
KILA2:	MOVX T1,US.OIR!US.OMS	;CLEAR OUT OPERATOR MESSAGE BITS
	ANDCAM T1,UDBSTS(P3)	; ...
	HRRZ T1,UDBTWQ(P3)	;GET HEAD OF LIST
	HLRZ T3,UDBTWQ(P3)	;GET TAIL OF LIST
	MOVSI T2,UDBTWQ(P3)	;SETUP NULL QUEUE
	MOVEM T2,UDBTWQ(P3)	; ...
	HRRZ T2,UDBPWQ(P3)	;GET PWQ HEAD
	JUMPE T1,KILA3		;WAS TWQ NIL?
	HRRM T2,IRBLNK(T3)	;NO - APPEND TO TWQ LIST
	MOVSI T2,UDBPWQ(P3)	;RESET PWQ TO NULL
	MOVEM T2,UDBPWQ(P3)	; ...
	JRST PIONRT		;RETURN

KILA3:	MOVE T1,T2		;TWQ NIL, RETURN PWQ
	MOVSI T2,UDBPWQ(P3)	;RESET PWQ TO NULL
	MOVEM T2,UDBPWQ(P3)	; ...
PIONRT:	PION
	RET
;HERE TO FETCH A WORD FROM A SPECIFIED PHYSICAL ADDRESS

;T1/ PHYSICAL ADDRESS
;CALL PHYMOV
;RETURNS+1(ALWAYS):
;T1/ UNCHANGED
;T2/ CONTENTS OF ((T1))

PHYMOV::PUSH P,T1		;SAVE ADDRESS OVER CALL
	IDIVI T1,PGSIZ		;ISOLATE CPN AND RELATIVE WORD
	EXCH T1,T2		;PLACE IN CORRECT ACCUMULATORS
	CALL MOVRCA		;CALL KERNEL ROUTINE
	MOVE T2,T1		;COPY RESULT
	JRST PA1		;POP T1 AND RETURN


;HERE TO STORE A WORD IN A SPECIFIED PHYSICAL ADDRESS

;T1/ PHYSICAL ADDRESS
;T2/ DATA TO STORE
;	CALL PHYSTO
;T1/ UNCHANGED

PHYSTO::PUSH P,T1		;SAVE ARGUMENT OVER CALL
	MOVE T3,T2		;MOVE DATA TO WHERE LOWER LEVEL WANTS IT
	IDIVI T1,PGSIZ		;ISOLATE CPN AND RELATIVE WORD
	EXCH T1,T2		;MOVE TO CORRECT PLACE
	CALL STORCA		;CALL KERNEL ROUTINE
	JRST PA1		;POP T1 AND RETURN

;HERE TO GENERATE A CCW FOR A PARTICULAR CHANNEL

;T1/ DATA MODE,,BYTE COUNT (1B0 IF BACKWARDS)
;T2/ PHYSICAL ADDRESS OF FIRST WORD TO TRANSFER
;T3/ CDB
;	CALL PHYCCW
;RETURNS+1(ALWAYS):
;T1/ CCW TO TRANSFER DATA AS SPECIFIED BY ARGUMENTS

PHYCCW::SAVEP			;PRESERVE REGISTERS
	MOVE P1,T3		;COPY CDB
	HRRZ T3,CDBDSP(P1)	;GET DISPATCH ADDRESS
	CALL CDSCCW(T3)		;GENERATE CCW
	RET
;ROUTINE TO WAIT FOR ALL PHYSIO ACTIVITY TO CEASE.
;CALLED AT SYSTEM STARTUP TIME JUST BEFORE THE SWAPPABLE MONITOR
;IS LOADED.

PHYIOW::SAVEPQ			;SAVE PRESERVED REGISTERS
IOW1:	MOVEI Q1,0		;CLEAR ACTIVITY FLAG
	MOVSI P4,-CHNN		;POINTER TO CHANNELS
IOW2:	SKIPN P1,CHNTAB(P4)	;CHANNEL PRESENT?
	JRST IOW3		;NO - CONTINUE
	MOVX T1,CS.ACT		;TRANSFER ON THIS CHANNEL?
	TDNE T1,CDBSTS(P1)	; ???
	AOJA Q1,IOW3		;YES - SET FLAG
	CALL DGUMAP		;MAP OVER ALL UNITS
	 CALL [	MOVX T1,US.ACT!US.POS!US.OIR!US.OMS	;CHECK ACTIVITY
		TDNE T1,UDBSTS(P3) ; ...
		AOS Q1		;FLAG ACTIVITY
		RET]
IOW3:	AOBJN P4,IOW2		;LOOP OVER ALL CHANNELS
	JUMPN Q1,IOW1		;IF ANY WERE ACTIVE, CHECK AGAIN
	RET			;NONE ACTIVE, RETURN

;ROUTINE TO RETRIEVE UDB INFO ON TAPE POSITION
;C(T1) := TAPE UNIT NUMBER
;RETURNS:
; T1/	UDBPS2	(RECORD COUNT)
; T2/	UDBPS1	(FILE COUNT)

PHYPOS::HRRZ T3,MTCUTB(T1)	;GET POINTER TO UDB
	MOVE T1,UDBPS2(T3)	;RECORD COUNT TO T1
	MOVE T2,UDBPS1(T3)	;FILE COUNT TO T2
	RET			;RETURN
	SUBTTL ERROR LOGGING INTERFACE

;HERE TO ASSIGN AN ERROR BLOCK
;P1/ CDB
;P3/ UDB
;	CALL ERRSET
;RETURNS+1(ALWAYS):
;T1/ EB ADDRESS OR ZERO IF NONE AVAILABLE


ERRSET::MOVEI T1,MB%LEN		;TOTAL BLOCK LENGTH
	MOVEI T2,MB%SIZ		;NON STRING DATA SIZE
	MOVX T3,CS.CIP
	TDNE T3,CDBSTS(P1)	;CI CHAN?
	JRST [MOVEI T1,CI%LEN	;YES, DIFFERENT PARAMETERS
	      MOVEI T2,CI%SIZ
	      JRST .+1]
	MOVX T3,IS.IEL		;GET ERROR LOGGING INHIBITED FLAG
	TDNN T3,IRBSTS(P4)	;LOGGING ALLOWED?
	CALL ALCSEB		;YES, TRY TO GET ERROR BLOCK
	 MOVEI T1,0		;NO LOGGING OR NONE AVAIL
	RET


;HERE TO LOG AND RELEASE AN ERROR BLOCK
;P1/ CDB
;P3/ UDB
;	CALL ERRFIN
;RETURNS+1(ALWAYS):
;ERROR LOGGING UNDERWAY


ERRFIN::HRRZS UDBERP(P3)	;CLEAR LEFT HALF
	SKIPN UDBERP(P3)	;AN ERROR BLOCK?
	JRST ERRFN3		;NO, DONT SAVE ACCUMULATORS
	SAVEQ
	MOVEI Q1,0		;CLEAR/GET ERROR BLOCK
	EXCH Q1,UDBERP(P3)	; ...
	JUMPE Q1,ERRFN3		;NOTHING TO LOG
	CALL PHYBLK		;FIND THE PHYSICAL BLOCK
	MOVE Q2,T2		;SAVE IT FOR CI BAT BLOCKS
	MOVE Q3,UDBSTS(P3)	;FIND UNIT TYPE
	TXNE Q3,US.CIP		;CI UNIT?
	SKIPA T2,[-NCITAB,,CITAB] ;YES. MAKE A DIFFERENT ENTRY
	SKIPA T2,[-NCTAB,,CTAB]	;GET THINGS TO COPY
	SKIPA Q3,Q2		;SET LBN FOR HSC COPY
	HRL Q3,CDBSTS(P1)	;GET CHANNEL TYPE
	HRRZ P3,P3		;CLEAR OUT ANY FLAGS
	MOVE T1,Q1		;GET ERROR BLOCK
	CALL SEBCPY		;AND DO IT
	 JFCL			;NEVER...
	HRLZ T1,UDBADR(P3)	;GET UNIT OFF OF CHANNEL READY
	HRR T1,UDBSLV(P3)	;AND SLAVE NUMBER
	TRNN P2,-1		;HAVE A CONTROLLER?
	HRRO T1,UDBADR(P3)	;NO, GET GET UNIT NUMBER THIS WAY
	MOVE CX,UDBSTS(P3)
	TXNN CX,US.CIP		;IF NOT A CI UNIT,
	MOVEM T1,SEBDAT+MB%UAD(Q1) ;STORE IN SYSERR BLOCK
	CALL SETNAM		;SET UP MB%NAM (IN T1)
	MOVE CX,UDBSTS(P3)
	TXNN CX,US.CIP		;IF NOT A CI UNIT,
	MOVEM T1,SEBDAT+MB%NAM(Q1) ;STORE IN SYSERR BLOCK
	MOVX T1,IS.ERR!IS.NRT	;IS THIS A HARD ERROR?
	TDNN T1,IRBSTS(P4)	; ?
	JRST ERRFN2		;NO, NO NEED FOR BAT BLOCK LOGIC
	MOVX T1,IS.DTE		;YES, GET DATA ERROR FLAG
	MOVX T2,US.DSK		;AND DISK FLAG
	TDNE T2,UDBSTS(P3)	;IS THIS A DISK?
	TDNN T1,IRBSTS(P4)	;AND IS THIS A DATA ERROR?
	JRST ERRFN2		;NO - DONT DO BAT BLOCK LOGIC
	MOVE T1,Q1		;GET ERROR BLOCK AGAIN
	TXNE CX,US.CIP		;IS THIS A CI DISK?
	SKIPA T2,[-1,,[SEBPTR 0,SBTFNA,HSCBAT]]
	MOVE T2,[-1,,[SEBPTR 0,SBTFNA,ERRBAT]]
	CALL SEBCPY		;INSERT JOB 0 FUNCTION
	 JFCL
ERRFN2:	MOVE T1,Q1		;RECOVER ERROR BLOCK
	CALL QUESEB
	MOVEI T1,MASBGX		;SAY WE ARE REOCRDING A MASSBUS ERROR
	CALL GENBLK		;SEE IF STATUS BLOCK NEEDED
ERRFN3:	SETZM UDBERR(P3)	;YES - CLEAR STATE INFORMATION
	SETZM UDBERC(P3)	; ...
	RET			;AND WE ARE DONE
;COPY BLOCK
CTAB:	SEBPTR 0,SBTEVC,SEC%MB	;BLOCK TYPE
	SEBPTR MB%VID,SBTWD,UDBVID(P3) ;VID
	SEBPTR MB%FES,SBTWD,UDBERR(P3) ;FINAL ERROR STATE
	SEBPTR MB%UDB,SBTWD,P3		;UDB - NEEDED FOR BAT BLOCK LOGIC IN JOB 0
	SEBPTR MB%IRS,SBTWD,IRBSTS(P4) ;IORB STATUS WORD
	SEBPTR MB%TYP,SBTWD,Q3		;CHANNEL TYPE,,UNIT TYPE
	SEBPTR MB%SEK,SBTWD,UDBSEK(P3) ;NUMBER OF SEEKS
	SEBPTR MB%RED,SBTWD,UDBRED(P3) ;DATA READ
	SEBPTR MB%WRT,SBTWD,UDBWRT(P3) ;DATA WRITTEN
	SEBPTR MB%SRE,SBTWD,UDBSRE(P3) ;SOFT READ ERRORS
	SEBPTR MB%SWE,SBTWD,UDBSWE(P3) ;SOFT WRITE ERRORS
	SEBPTR MB%HRE,SBTWD,UDBHRE(P3) ;HARD READ ERRORS
	SEBPTR MB%HWE,SBTWD,UDBHWE(P3) ;HARD WRITE ERRORS
	SEBPTR MB%PS1,SBTWD,UDBPS1(P3) ;POSITION 1
	SEBPTR MB%PS2,SBTWD,UDBPS2(P3) ;POSITION 2
	SEBPTR MB%FEC,SBTWD,UDBERC(P3) ;FINAL ERROR COUNTER
	SEBPTR MB%USR,SBTWD,UDBUDR(P3) ;USER DIRECTORY TO LOG
	SEBPTR MB%PGM,SBTWD,UDBPNM(P3) ;USER PROGRAM TO LOG
	SEBPTR MB%MPE,SBTWD,CDBPAR(P1) ;PAR ERR COUNT
	SEBPTR MB%NXM,SBTWD,CDBNXM(P1) ;NXM COUNT
	SEBPTR MB%OVR,SBTWD,CDBOVR(P1) ;NUMBER OF OVERRUNS
	SEBPTR MB%CAD,SBTWD,CDBADR(P1) ;CHANNEL NUMBER

NCTAB=.-CTAB


;COPY BLOCK FOR CI UNITS
CITAB:	SEBPTR 0,SBTEVC,SEC%CI		;BLOCK TYPE
	SEBPTR CI%NOD,SBTWD,.SBDSP(P2)	;PORT,,NODE
	SEBPTR CI%VID,SBTWD,UDBVID(P3)	;VID
	SEBPTR CI%RED,SBTWD,UDBRED(P3)	;SECTORS/FRAMES READ
	SEBPTR CI%WRT,SBTWD,UDBWRT(P3)	;SECTORS/FRAMES WRITTEN
	SEBPTR CI%PS1,SBTWD,UDBPS1(P3)	;POSITION 1
	SEBPTR CI%PS2,SBTWD,UDBPS2(P3)	;POSITION 2
	SEBPTR CI%UDB,SBTWD,P3		;UDB - NEEDED FOR BAT BLOCK LOGIC IN JOB 0
	SEBPTR CI%LOC,SBTWD,Q3		;LINEAR ADDRESS OF BAD BLOCK
NCITAB==.-CITAB


;HERE IN JOB 0 CONTEXT WHEN A HARD ERROR HAS OCCURED ON A DISK.
;THE BAT BLOCK LOGIC MUST BE INVOKED TO PREVENT RE-USE OF THE BAD BLOCK.

	SWAPCD			;RUNS IN JOB 0 CONTEXT, MAY BE SWAPPABLE
ERRBAT:	MOVE T2,SEBDAT+MB%LOC(T1) ;GET LINEAR ADDRESS FROM ERROR BLOCK
	MOVE T1,SEBDAT+MB%UDB(T1) ;GET UDB FROM ERROR BLOCK
	CALL BATQ		;MARK BAT BLOCKS, FDB, ETC.
	RET
HSCBAT:	MOVE T2,SEBDAT+CI%LOC(T1) ;GET LINEAR ADDRESS FROM ERROR BLOCK
	MOVE T1,SEBDAT+CI%UDB(T1) ;GET UDB FROM ERROR BLOCK
	CALL BATQ		;MARK BAT BLOCKS, FDB, ETC.
	RET

	RESCD
SUBTTL	STATISTICS LOGGING INTERFACE
;ROUTINE TO LOG MAGTAPE STATS ON AN UNLOAD
;CALL T1=UDB ADDR
;RETURNS +1(ALWAYS)
LOGUNL::SAVET
	MOVEI T2,ST%UNL		;REASON FOR THE ENTRY
;	CALLRET LGSTAT		;LOG IT AND RETURN

;ROUTINE TO LOG A STATISTICS ENTRY
;T1/	UDB
;T2/	CODE
;	CALL LGSTAT
;RETURNS+1(ALWAYS)
LGSTAT:	SAVEP			;SAVE SOME ACS
	MOVE P3,T1		;SET P3=UDB ADDRESS
	MOVE P2,T2		;SET P2=CODE
	MOVEI T1,ST%LEN		;TOTAL BLOCK LENGTH
	MOVEI T2,ST%SIZ		;NON-STRING DATA SIZE
	CALL ALCSEB		;GET SPACE FOR THE REPORT
	 RET			;NONE AVAILABLE. CHUCK THE MESSAGE
	HRRZ P1,UDBCDB(P3)	;SET UP CHANNEL ADDRESS
	MOVE P4,T1		;SAVE LOC OF STATS BLOCK
	CAIN P2,ST%UNL		;MAGTAPE ENTRY?
	SKIPA T2,[-STAMLN,,STATAB] ;YES. SET FOR THAT BLOCK
	MOVE T2,[-STADLN,,STATAB]  ;NO. SET FOR A DISK ENTRY
	HLL P4,T2		;SAVE LENGTH FOR LATER
	MOVE P5,UDBSTS(P3)	;GET UNIT TYPE
	HRL P5,CDBSTS(P1)	;GET CHANNEL TYPE
	CALL SEBCPY		;STORE THE STUFF IN THE SYSERR/SPEAR BLOCK
	 JFCL
	CALL SETNAM		;SET T1=ST%NAM
	MOVEM T1,SEBDAT+ST%NAM(P4) ;SAVE FOR SYSERR/SPEAR
	HRLZ T1,UDBADR(P3)	;GET UNIT OFF OF CHANNEL READY
	HRR T1,UDBSLV(P3)	;AND SLAVE NUMBER
	HRRZ T2,UDBKDB(P3)	;HAVE A CONTROLLER?
	SKIPN T2
	HRRO T1,UDBADR(P3)	;NO, GET GET UNIT NUMBER THIS WAY
	MOVEM T1,SEBDAT+ST%UAD(P4) ;STORE IN SYSERR BLOCK
	HRRZ T1,P4		;LOC OF BLOCK
	CALL QUESEB		;TAKE IT AWAY SYSERR/SPEAR
	HRRI P4,STATAB		;START OF TABLE (LENGTH ALREADY IN LH)
	ADD P4,BHC+STAZER	;POINT TO FIRST LOC TO CLEAR DOWN
	SETZM @(P4)		;CLEAR VOLUME STATISTICS
	AOBJN P4,.-1
	RET			;AND RETURN TO CALLER
;ROUTINE TO LOG DISK STATISTICS ON A SYSTEM SHUTDOWN
;CALL PHYLOG
;RETURNS +1(ALWAYS)
PHYLOG::SAVEP			;SAVE ACS
	MOVSI P6,-CHNN		;SET TO LOOK AT ALL CHANS
PHYLO1:	SKIPN P1,CHNTAB(P6)	;CHAN EXIST?
	JRST PHYLO2		;NO, TRY NEXT
	CALL DGUMAP		;YES, LOG STATS FOR ITS UNITS
	 CALL PHYLO3		;LOG EACH UNIT
PHYLO2:	AOBJN P6,PHYLO1		;KEEP GOING FOR ALL CHANS
	RET			;DONE. RETURN

;CALLED FOR EACH UNIT ON A CHANNEL
PHYLO3:	MOVX T1,US.DSK		;IS THIS UNIT A DISK?
	TDNN T1,UDBSTS(P3)
	RET			;NO, DON'T DO ANYTHING
	MOVE T1,P3		;YES, SET UP UDB ADDR WHERE LGSTAT WANTS IT
	MOVEI T2,ST%SHT		;REASON FOR ENTRY
	CALLRET LGSTAT		;LOG THE STATISTICS AND RETURN

;ROUTINE TO SET UP MB%NAM, ST%NAM
;P3/	UDB
;RETURNS +1(ALWAYS)
;T1/	MAGTAPE UNIT NUMBER, 0 IF A DISK
SETNAM:	MOVX T1,US.TAP		;IS THIS A MAGTAPE?
	TDNN T1,UDBSTS(P3)
	JRST SETNA2		;NO
	MOVE T2,[-MTAN,,MTCUTB]	;YES. COMPUTE INDEX OF UNIT
SETNA1:	HRRZ T1,(T2)		;UDB ADDR
	CAIN T1,(P3)		;ONE WE'RE LOOKING FOR?
	JRST SETNA3		;YES
	AOBJN T2,SETNA1		;NO, TRY NEXT
SETNA2:	TDZA T1,T1		;CAN'T FIND IT (!)
SETNA3:	MOVEI T1,-MTCUTB(T2)	;COMPUTE INDEX FROM AOBJN WORD
	RET			;RETURN TO CALLER

STATAB:	SEBPTR 0,SBTEVC,SEC%ST		;BLOCK TYPE
	SEBPTR ST%COD,SBTWD,P2		;REASON FOR THIS RECORD
	SEBPTR ST%VID,SBTWD,UDBVID(P3)	;VOLUME ID
	SEBPTR ST%TYP,SBTWD,P5		;DEVICE AND CHANNEL TYPE (SEE MB%TYP)
	SEBPTR ST%CAD,SBTWD,CDBADR(P1) ;CHANNEL ADDRESS
STAZER==.-STATAB			;FIRST LOC TO CLEAR AFTER COPYING
	SEBPTR ST%RED,SBTWD,UDBRED(P3)	;TOTAL READS ON THIS VOLUME
	SEBPTR ST%WRT,SBTWD,UDBWRT(P3)	;TOTAL WRITES ON THIS VOLUME
	SEBPTR ST%SEK,SBTWD,UDBSEK(P3)	;TOTAL SEEKS ON THIS VOLUME
STADLN==.-STATAB			;LENGTH OF DISK STATISTICS BLOCK
	SEBPTR ST%RNR,SBTWD,UDBRNR(P3)	;(MAGTAPE) FRAMES READ ON VOLUME IN NRZI
	SEBPTR ST%WNR,SBTWD,UDBWNR(P3)	;(MAGTAPE) FRAMES WRITTEN ON VOLUME IN NRZI
	SEBPTR ST%RPE,SBTWD,UDBRPE(P3)	;(MAGTAPE) FRAMES READ ON VOLUME IN PE
	SEBPTR ST%WPE,SBTWD,UDBWPE(P3)	;(MAGTAPE) FRAMES WRITTEN ON VOLUME IN PE
	SEBPTR ST%RGC,SBTWD,UDBRGC(P3)	;(MAGTAPE) FRAMES READ ON VOLUME IN GCR
	SEBPTR ST%WGC,SBTWD,UDBWGC(P3)	;(MAGTAPE) FRAMES WRITTEN ON VOLUME IN GCR
STAMLN==.-STATAB		;LENGTH OF MAGTAPE STATS BLOCK
SUBTTL INTERNAL START IO UTILITIES

;HERE TO START IO ON AN IORB

;SHOULD BE CALLED WITH PI OFF IF NOT AT INTERRUPT LEVEL
;P4/ IORB
;P1,2,3 SETUP
;	CALL STRTIO
;RETURNS+1:
;	IO NOT STARTED, IORB EITHER TERMINATED OR REMAINING IN QUEUES
;RETURNS+2:
;	IO STARTED

STRTIO:	SETZM CDBIRB(P1)	;NO LONGER HAVE A PREFERENTIAL IORB
	SKIPGE IRBSTS(P4)	;SHORT IORB?
	JRST STRTI1		;YES, NEVER AN EXIT ROUTINE
	HLRZ T2,IRBIVA(P4)	;GET STRTIO ENTRY ROUTINE
	JUMPE T2,STRTI1		;NONE
	MOVE T1,P4		;COPY IORB FOR CALL
	CALL (T2)		;CALL ENTRY ROUTINE
	 SKIPA			;ABORT
	JRST STRTI1		;NORMAL STARTUP
STRTI0:	MOVX T1,US.OIR!US.OMS	;NO LONGER ANY NEED FOR OPER INTERVENTION
	ANDCAM T1,UDBSTS(P3)	; ...
	CALL OFFTWQ		;REMOVE FROM TWQ
	CALL DONIRB		;FLAG AS DONE
	RET			;AND EXIT INDICATING REFUSED
STRTI1:	MOVE T1,UDBST1(P3)	;GET UNIT STATUS
	CAME P4,UDBCHB(P3)	;IS THIS THE HOMEBLOCK CHECKD?
	TXNN T1,U1.OFS		;OR NOT FORCED OFFLINE?
	SKIPA			;ALL OK TO DO TRANSFER
	CALLRET SETOIA		;NOT LEGAL TO TRANSFER DECLARE OFFLINE
	MOVE T1,UDBSTS(P3)	;GET STATUS
	TXNE T1,US.CIP		;MSCP-CONTROLLED DISK?
	JRST STRTI2		;YES. UNIT/KDB CAN ALREADY BE ACTIVE
	MOVX T2,KS.ACT		;AND CONTROLLER ACTIVE BIT
	TRNE P2,-1		;IS THERE A CONTROLLER?
	TDNN T2,KDBSTS(P2)	;YES, CONTROLLER ALREADY BUSY?
	TXNE T1,US.POS!US.ACT	;OR UNIT ALREADY BUSY?
	BUG.(HLT,ILUST1,PHYSIO,HARD,<PHYSIO - Unit status inconsistent at SIO>,,<

Cause:	The STRTIO routine was called to start IO on a unit for an IORB,
	but the unit or controller status indicated that the unit was
	already active.  IO should never be started on an active drive.
>)		;YES, ERROR
	MOVX T1,CS.AC2		;CHECK NOT OUT OF PHASE
	TDNE T1,CDBSTS(P1)	;BY SEEING IF STACKED COMMAND ACTIVE
	BUG.(HLT,ILCHS1,PHYSIO,HARD,<PHYSIO - Illegal channel status at SIO>,,<

Cause:	The STRTIO routine was called to begin IO for an IORB, but the
	channel status indicated that the channel was already active
	doing a stacked command.
>)		;YES, ERROR
STRTI2:	MOVX T1,CS.AC1		;CHANNEL GOING ACTIVE
	IORM T1,CDBSTS(P1)	; ...
	MOVX T1,KS.ACT		;AND CONTROLLER
	TRNE P2,-1		;IF PRESENT
	IORM T1,KDBSTS(P2)	; ...
	MOVX T1,US.ACT		;ALSO UNIT
	IORM T1,UDBSTS(P3)	; ...
	HRRZ T1,UDBAKA(P3)	;GET CURRENT UDB ADDRESS
	MOVEM T1,CDBXFR(P1)	;MARK A UNIT HOLDING CHANNEL
	CALL SETIO		;SETUP FOR IO
	CALL CDSSIO(T1)		;GO START IO
	 JRST STKIOF		;OFFLINE, CAN'T DO IT
	HRRZM P3,CDBLUN(P1)	;REMEMBER UDB OF THE UNIT
	RETSKP			;IO STARTED SUCCESSFULLY

STKIOF:
	MOVX T1,US.CIP
	TDNN T1,UDBSTS(P3)	;IS THIS AN MSCP-CONTROLLED DISK?
	JRST STKIF1		;NO
	HRRZ T1,IRBLNK(P4)	;YES, IS THIS THE ONLY IORB ON THE CHAIN?
	SKIPN T1		;IF NOT, DON'T SET UNIT IDLE
STKIF1:	CALL CLRACT		;CLEAR CHANNEL AND UNIT ACTIVE BITS
	MOVX T1,IS.ERR		;ANY ERRORS OCCURRED?
	TDNE T1,IRBSTS(P4)	;CHECK IORB
	JRST STRTI0		;YES, REMOVE IORB FROM QUEUE
SETOIA:	CALL SETOIR		;INDICATE OPERATOR NEEDED
	MOVX T1,US.CIP		;CHECK FOR CI
	TDNN T1,UDBSTS(P3)	;ON THIS UDB
	RET			;QUIT NOT CI
	CALL OFFTWQ		;PICK UP THE IORB AND PLACE IT ON THE
	CALLRET ONFPWQ		;PWQ

;HERE WHEN OPERATOR INTERVENTION REQUIRED

SETOIR:	MOVX T1,US.OIR		;SET OPERATOR INTERVENTION BIT
	IORM T1,UDBSTS(P3)	;FOR PERIODIC CHECKER
	SETZM UDBODT(P3)	;ALSO CLEAR OUT OVERDUE TIMER
	RET
;HERE TO STACK A SECOND DATA TRANSFER COMMAND FOR A CHANNEL

;REQUIRES THE USUAL PIOFF OR INTERRUPT LEVEL INTERLOCK
;P4/ IORB
;P1,2,3 SETUP
;	CALL STKIO
;RETURNS+1:
;	COMMAND NOT STACKED
;RETURNS+2:
;	COMMAND STACKED IN CHANNEL



STKIO:	SKIPGE IRBSTS(P4)	;SHORT IORB?
	JRST STKIO1		;YES - NO NEED TO CALL EXIT RTN
	HLRZ T2,IRBIVA(P4)	;GET SIO EXIT ROUTINE ADDRESS
	JUMPE T2,STKIO1		;IF NONE, ASSUME OK
	MOVE T1,P4		;COPY IORB
	CALL (T2)		;CALL EXIT ROUTINE
	 RET			;SIGNAL FAILURE, WILL TERMINATE AT STRTIO
STKIO1:	MOVX T1,CS.AC1		;GET PRIMARY CHANNEL ACTIVE FLAG
	MOVX T2,KS.ACT		;AND CONTROLLER ACTIVE FLAG
	TRNE P2,-1		;DOES A CONTROLLER EXIST?
	TDNE T2,KDBSTS(P2)	;YES, THEN IT BETTER BE ACTIVE
	TDNN T1,CDBSTS(P1)	;CHANNEL SHOULD BE BUSY ALSO
	BUG.(HLT,ILUST5,PHYSIO,SOFT,<PHYSIO - Illegal channel or controller state at STKIO>,,<

Cause:	The STKIO routine was called to stack up a second command for a
	channel, so that the CDB and KDB (if it exists) should have been
	marked as active.  However, at least one of them wasn't active.
>)		;WRONG, COMPLAIN
	MOVE T1,UDBSTS(P3)	;CHECK ON UNIT STATUS
	TXNE T1,US.ACT		;UNIT SHOULD BE ACTIVE
	TXNE T1,US.POS		;BUT NOT POSITIONING
	BUG.(HLT,ILUST6,PHYSIO,SOFT,<PHYSIO - Illegal unit state at STKIO>,,<

Cause:	The STKIO routine was called to stack up a second command for
	a channel, but the unit either was not active or was doing
	positioning.
>)		;OTHERWISE LOSE
	MOVX T1,CS.AC2		;NOW GET SECOND CHANNEL ACTIVE FLAG
	TDNE T1,CDBSTS(P1)	;ALREADY BUSY?
	BUG.(HLT,ILCHS2,PHYSIO,HARD,<PHYSIO - Illegal channel state at STKIO>,,<

Cause:	The STKIO routine was called to set up a second command for
	a channel, but the channel status indicated it already had
	a second command in progress.
>)		;YES, ERROR
	IORM T1,CDBSTS(P1)	;WILL NOW HAVE BOTH ACTIVE
	CALL SETIO		;SETUP
	CALL CDSSTK(T1)		;CALL LOWER LEVELS
	 SKIPA T1,[EXP CS.AC2]	;FAILED, GET FLAG READY
	RETSKP			;SUCCESSFUL
	ANDCAM T1,CDBSTS(P1)	;CLEAR SECOND ACTIVE FLAG
	RET			;AND RETURN ERROR
;HERE TO START POSITIONING FOR AN IORB

;P4/ IORB
;P1,3 SETUP
;	CALL STRTPS
;RETURN+1:
;	POSITIONING NOT STARTED, IORB TERMINATED IF APPROPRIATE
;RETURNS+2:
;	POSITIONING STARTED

STRTPS:	MOVE T1,UDBST1(P3)	;Get the status
	CAME P4,UDBCHB(P3)	;IS THIS THE HOMEBLOCK
	TXNN T1,U1.OFS		;OFFLINE?
	SKIPA			;ONLINE ALL OK
	JRST SETOIR		;NO GO DECLARE OFFLINE
STRPA:	HRRZ T1,UDBTWQ(P3)	;CHECK IF POSITIONING LEGAL NOW
	MOVX T2,US.ACT		;IF ANY PENDING REQUEST ON CYLINDER
	TDNE T2,UDBSTS(P3)	;OR IF UNIT ACTIVE
	SKIPN T1		; ...
	SKIPA			;NONE OF THE ABOVE
	BUG.(CHK,ILUST2,PHYSIO,HARD,<PHYSIO - Unit status inconsistent at SPS>,,<

Cause:	The routine STRTPS was called to begin a positioning request
	for a unit, but the status indicated that the unit was already
	active and the transfer wait queue was nonempty.
>)
	TRNN P2,-1		;IS THERE A CONTROLLER?
	JRST STRTP1		;NO
	MOVX T1,KS.ACT		;YES
	TDNE T1,KDBSTS(P2)	;ALREADY ACTIVE?
	BUG.(HLT,ILUST4,PHYSIO,HARD,<PHYSIO - Controller active at SPS>,,<

Cause:	The routine STRTPS was called to begin positioning on a
	unit, but the controller status indicated it was already
	busy.
>)
	IORM T1,KDBSTS(P2)	;NO - MAKE IT ACTIVE
STRTP1:	MOVX T1,US.ACT!US.POS	;UNIT SOON POSITIONING
	IORM T1,UDBSTS(P3)	; ...
	CALL SETIO		;SETUP
	CALL CDSPOS(T1)		;CALL LOWER LEVEL
	 JRST STRTPF		;COULDN'T
	HRRZM P3,CDBLUN(P1)	;REMEMBER LAST UNIT TALKED TO
	RETSKP			;ALL OK

STRTPF:	CALL CLRPOS		;CLEAR ACTIVE
	MOVX T1,US.TAP		;IS THIS A TAPE LIKE DEVICE?
	TDNN T1,UDBSTS(P3)	;???
	JRST STRTP2		;NO
	MOVX T1,IS.ERR		;YES - WAS AN ERROR INDICATED?
	TDNN T1,IRBSTS(P4)	; ???
	JRST STRTP2		;NO - KEEP IN QUEUES
	MOVX T1,US.OIR!US.OMS	;YES - TERMINATE
	ANDCAM T1,UDBSTS(P3)	;NO LONGER WAITING FOR OPR
	CALL OFFPWQ		;REMOVE FROM PWQ
	CALL DONIRB		;POST COMPLETE
	RET			;FAIL RETURN

STRTP2:	CALLRET	SETOIR		;SET OPERATOR INVERVENTION REQ
				;AND FAIL RETURN


;HERE TO RESTART SEEKS ON A CHANNEL
;P1/ CDB
;	CALL RSTSEK
;RETURNS+1(ALWAYS):
;CLOBBERS P REGISTERS, P2, AND P3
;SHOULD BE CALLED WITH PI OFF

RSTSEK::SAVEQ
	CALL DGUMAP		;LOOP OVER ALL UNITS
	 CALL SCHSEK		;DO THIS FOR EACH ONE
	RET			;DONE
;UTILITY TO SET UP FOR IO
;P4/IORB ADDRESS
;P1/CDB
;RETURNS +1 (ALWAYS):
;ERROR BIT CLEARED IN IORB,
;T1/DISPATCH ADDRESS


SETIO::	MOVX T1,IS.ALE		;CLEAR ALL ERROR BITS
	ANDCAM T1,IRBSTS(P4)
	MOVEI T1,^D25000	;NO, ALLOW ONLY A FEW SECONDS THEN
	ADD T1,TODCLK		;FROM NOW
	MOVEM T1,UDBODT(P3)	;AND STORE AS OVERDUE TIME
	HRRZ T1,CDBDSP(P1)
	RET



;HERE TO CLEAR CHANNEL AND UNIT ACTIVE BITS

CLRACT::MOVX T1,CS.ACT!CS.ERC	;MARK CDB NO LONGER ACTIVE OR IN ERROR RECOVERY
	ANDCAM T1,CDBSTS(P1)	; ...
	SETOM CDBXFR(P1)	;CLEAR TRANSFERING UDB
CLRPOS:	TRNN P2,-1		;ANY CONTROLLER?
	JRST CLRSRC		;NO, SKIP ON
	MOVX T1,KS.ACT		;YES, GET ACTIVE BIT
	ANDCAM T1,KDBSTS(P2)	;AND CLEAR IT
	SETZM KDBACT(P2)	;CLEAR TRANSFERING UDB
CLRSRC:	MOVX T1,US.ACT!US.POS	;UNIT IS NO LONGER ACTIVE OR POSITIONING
	ANDCAM T1,UDBSTS(P3)	; ...
CLRXIT:	SETZM UDBODT(P3)	;ALSO CLEAR TIMEOUT
	MOVX T1,US.MRQ		;UNIT WAITING FOR MAINT MODE?
	TDNN T1,UDBSTS(P3)	;?
	RET			;NO - JUST RETURN
	MOVX T2,US.MAI		;YES, SET BIT
	IORM T2,UDBSTS(P3)	; ...
	ANDCAM T1,UDBSTS(P3)	;NO LONGER REQUESTING
	AOS PSKD1		;POKE SCHED
	RET
	SUBTTL SEEK SCHEDULER
;SHOULD BE CALLED WITH INTERRUPTS OFF OR AT INTERRUPT LEVEL
;P1/ CDB
;P2/ KDB (IF PRESENT)
;P3/ UDB
;	CALL SCHSEK
;RETURNS+1(ALWAYS):
;	SEEK STARTED ON THIS UNIT IF APPROPRIATE
;	POSITION OP STARTED IF CONTROLLER FREE (SEE SCHPOS COMMENTS)
;USES P4,THE Q'S

;THE ALGORITHM USED IS THAT REFERED TO IN THE LITERATURE AS "SCAN"
;BRIEFLY STATED, THE ALGORITHM SELECTS THE REQUEST TO THE CLOSEST
;HIGHER NUMBERED CYLINDER THAN THE UNITS CURRENT CYLINDER. IF THERE IS
;NO SUCH REQUEST, THE REQUEST TO THE LOWEST NUMBERED CYLINDER IS
;SELECTED. THIS CAUSES THE DISK ARM TO "SCAN" FROM LOWER NUMBERED
;CYLINDERS TO HIGHER NUMBERED CYLINDERS. THE CACM AND IBM SYS. J.
;HAVE MANY DESCRIPTIONS AND WINDY RELIGIOUS DEBATES ON THE SUBJECT.

;NOTE: READS ARE GIVEN PREFERENCE OVER WRITES IN SELECTING THE
;	NEXT SEEK CYLINDER. THIS TENDS TO REDUCE SYSTEM SWAP WAIT TIME
;	IN THAT A PROCESS IS USUALLY BLOCKED WAITING FOR A READ WHILE
;	WRITES USUALLY ORIGINATE WITH GCCOR. ALL TRANSFERS FOR THE
;	SELECTED CYLINDER ARE DONE, BOTH READS AND WRITES.

;REGISTER USAGE:
;Q1/ FLAGS,,PREDECESSOR TO ELEMENT UNDER CONSIDERATION
;Q2/ MINIMUM CYLINDER SO FAR,,PREDECESSOR TO MINIMUM ELEMENT
;Q3/ BEST CYLINDER SO FAR,,PREDECESSOR TO BEST ELEMENT
;P4/ CURRENT ELEMENT UNDER CONSIDERATION

;LOCAL FLAGS IN LH(Q1)
SEKF%R==1B0		;PREFER READS OVER WRITES
SEKF%M==1B1		;HAVE A READ FOR MIN CYL
SEKF%B==1B2		;HAVE A READ FOR BEST CYL
SCHSEK::MOVX T1,CS.MRQ!CS.MAI	;CHANNEL IN MAINT MODE?
	SKIPN UDBCHB(P3)	;CHECKING HOMEBLOCK?
	TDNE T1,CDBSTS(P1)	; ???
	RET			;YES - NO NEW ACTIVITY
	TRNE P2,-1		;KDB FOR THIS UNIT?
	JRST SCHPOS		;YES - GO WORK ON IT
	HRRZ T1,UDBTWQ(P3)	;ANY TRANSFERS PENDING ON CYLINDER?
	JUMPN T1,R		;YES - WHY MESS THINGS UP?
	MOVEI Q1,UDBPWQ(P3)	;SETUP PREDECESSOR
	MOVSI Q2,-1		;SETUP MINIMUM CYLINDER TO LARGE NUMBER
	MOVSI Q3,-1		;SETUP BEST CYLINDER TO LARGE NUMBER
	HRRZ P4,UDBPWQ(P3)	;GET CURRENT HEAD OF PWQ
	JUMPE P4,SEKIDL		;IF QUEUE IS NULL, EXIT
	SOSG UDBFCR(P3)		;SHOULD READS GET PREFERENCE?
	SKIPA T1,[EXP INIFCR]	;NO - ALSO RESET COUNT
	TLOA Q1,(SEKF%R)	;YES
	MOVEM T1,UDBFCR(P3)	;SAVE NEW VALUE
SEK1:	HRRZ T1,UDBDSP(P3)	;GET UNIT DISPATCH
	CALL UDSCNV(T1)		;GET CYLINDER FOR THIS REQUEST
	LDB T3,IRYFCN		;GET FUNCTION CODE
	CAMN T2,UDBPS1(P3)	;SAVE AS CURRENT?
	SKIPG UDBFCT(P3)	;YES - "FAIRNESS" COUNT EXHAUSTED?
	JRST SEK3		;CNT EXHAUSTED OR NOT SAME CYL, CHK FOR MIN
	HRRZ T1,Q1		;GET PREDECESSOR
	HRRZ T2,P4		;GET ELEMENT TO BE REMOVED
	CALL CONSPW		;SPLICE QUEUE
	HRRZ T1,P4		;GET CURRENT REQUEST
	CALL ONTWQ		;AND PLACE ON TWQ
SEK2:	HRRZ P4,IRBLNK(Q1)	;ADVANCE CURRENT REQUEST
	JUMPN P4,SEK1		;IF ONE PRESENT, CONSIDER IT.
	HRRZ T1,UDBTWQ(P3)	;END OF QUEUE, ANYTHING IN TWQ?
	JUMPN T1,R		;YES - DONT DISTURB POSITION.
	HLRZ T1,Q3		;GET BEST CYLINDER FOUND
	CAIN T1,-1		;FOUND ANY REQUESTS TO HIGHER CYLINDERS?
	MOVE Q3,Q2		;NO - RESET SCAN AT MINIMUM
	HRRZ T1,Q3		;GET REQUEST DECIDED ABOVE
	HRRZ T2,IRBLNK(T1)	; ACTUAL ELEMENT
	HRRZ P4,T2		;COPY NEW CURRENT IORB
	CALL CONSPW		;SPLICE QUEUE
	MOVE T1,P4		;SHUFFLE TO HEAD OF PWQ
	CALL ONFPWQ		; ...
	MOVE T1,UDBSTS(P3)	;GET UNIT STATUS
	TXNE T1,US.OIR!US.OMS!US.MAI!US.MRQ	;WAITING FOR OPERATOR?
	RET			;YES, DO NOTHING
	TXNE T1,US.POS!US.ACT	;UNIT IDLE?
	BUG.(HLT,ILUST3,PHYSIO,HARD,<PHYSIO - SCHSEK - Impossible unit status>,,<

Cause:	The SCHSEK routine was called to start a position request for
	a unit, but the status of the unit indicated it was not idle.
	SCHSEK should only be called when a unit becomes inactive.
>)		;NO, COMPLAIN
	CALL STRTPS		;START POSITIONING
	 JFCL			;COULDNT POSITION THIS UNIT, OPERATOR NEEDED
	RET
SEK3:	JUMPGE Q1,SEK3B		;READ PREFERENCE?
	CAIE T3,IRFRVC		;YES - IS IT READ VALID
	CAIN T3,IRFRED		;OR A READ?
	JRST [TLON Q1,(SEKF%M)	;YES, SET/TEST THAT WE HAVE READ NOW
	      JRST SEK3C	;NO - TAKE THIS REQUEST
	      JRST SEK3B]	;YES - SEE IF THIS REQUEST IS BETTER
SEK3A:	TLNE Q1,(SEKF%M)	;NOT A READ - DO WE HAVE A READ NOW?
	JRST SEK4		;YES
SEK3B:	HLRZ T1,Q2		;GET MINIMUM CYLINDER FOUND SO FAR
	CAML T2,T1		;THIS REQUEST LESS THAN MINIMUM?
	JRST SEK4		;NO
SEK3C:	HRRZ Q2,Q1		;YES - SAVE PREDECESSOR
	HRL Q2,T2		;AND NEW MINIMUM CYLINDER
SEK4:	CAMG T2,UDBPS1(P3)	;THIS REQUEST GREATER THAN UNIT CURRENT?
	JRST SEK5		;NO
	JUMPGE Q1,SEK4B		;READ PREFERENCE?
	CAIE T3,IRFRED		;YES - IS THIS A READ?
	CAIN T3,IRFRVC		;OR A READ VERIFY
	JRST [TLON Q1,(SEKF%B)	;YES - SET/TEST DO WE HAVE A READ NOW?
	      JRST SEK4C	;NO - USE THIS REQUEST
	      JRST SEK4B]	;YES - CHECK IF THIS REQUEST IS BETTER
SEK4A:	TLNE Q1,(SEKF%B)	;NOT A READ - DO WE HAVE A READ NOW?
	JRST SEK5		;YES
SEK4B:	HLRZ T1,Q3		;GET CURRENT BEST CYLINDER
	CAML T2,T1		;BETTER? (LESS)
	JRST SEK5		;NO - CONTINUE SEARCH
SEK4C:	HRRZ Q3,Q1		;YES - SAVE PREDECESSOR
	HRL Q3,T2		;SAVE NEW BEST CYLINDER
SEK5:	HRR Q1,P4		;ADVANCE POINTER
	JRST SEK2		;AND CONTINUE SCAN

;HERE WHEN UNIT HAS NO MORE POSITION REQUESTS

SEKIDL:	MOVEI T1,INIFCR		;RESET READ PREFERENCE COUNT
	MOVEM T1,UDBFCR(P3)	; ...
	RET
;HERE TO SCHEDULE A POSITION OPERATION ON A UNIT WHICH IS A SUBUNIT
;OF A CONTROLLER TYPE DEVICE. THE POSITION AND TRANSFER OPERATIONS
;ARE SCHEDULED ROUND ROBIN AMONG THE DEVICES ON THE CONTROLLER.
;UNLIKE A DISK WHERE A SINGLE UNIT'S QUEUES DETERMINE WHETHER
;TO SEEK/NOT SEEK, THE UNITS OTHER THAN THE CURRENT ONE MUST BE
;SCANNED FIRST ON A CONTROLLER.

;THE CURRENT UNIT'S POSITION WAIT QUEUE IS MOVED TO ITS TWQ IF
;(AND AS FAR AS) IT IS APPROPRIATE. THE REQUESTS FOR A PARTICULAR
;DEVICE MUST BE FINISHED IN THE ORDER SUBMITTED.


SCHPOS:	MOVX T1,KS.ACT		;IS THE CONTROLLER FREE?
	TDNE T1,KDBSTS(P2)	; ???
	RET			;NO - NOTHING TO DO NOW

POS1:	HRRZ P4,UDBPWQ(P3)	;GET HEAD OF PWQ
	JUMPE P4,POS2		;IF NONE, JUST SCAN OTHER UNITS
	HRRZ T1,UDBDSP(P3)	;GET UNIT DISPATCH
	CALL UDSPRQ(T1)		;DOES THIS REQUEST REQUIRE POSITIONING?
	 SKIPA			;NO - TRANSFER IT TO UNITS TWQ
	JRST POS2		;YES - TRY OTHER UNITS
	CALL OFFPWQ		;PULL REQUEST FROM PWQ
	CALL ONTWQ		;APPEND TO TWQ
	JRST POS1		;AND CHECK AGAIN

POS2:	MOVE Q1,KDBCUN(P2)	;GET CURRENT LOOP POINTER
	JRST POS5		;AND START WITH NEXT UNIT

POS3:	SKIPN P3,(Q1)		;IS THERE A UNIT PRESENT?
	JRST POS4		;NO
	MOVX T1,US.ACT!US.POS!US.REW!US.OIR!US.OMS!US.MAI!US.MRQ
	TDNE T1,UDBSTS(P3)	;IS THIS UNIT AVAILABLE?
	JRST POS4		;NO - KEEP LOOKING
	HRRZ P4,UDBTWQ(P3)	;DOES THIS UNIT HAVE ANY TRANSFER REQS?
	JUMPN P4,R		;YES - LET TRANSFER SCHEDULER DO IT
	HRRZ P4,UDBPWQ(P3)	;ARE THERE ANY POSITION REQUESTS?
	JUMPE P4,POS4		;NO
	MOVEM Q1,KDBCUN(P2)	;YES - SAVE CURRENT UNIT POINTER
	CALL STRTPS		;TRY TO START IT
	 JRST POS5		;FAILED - SEE IF ANYTHING ELSE
	RET			;ALL DONE

POS4:	CAMN Q1,KDBCUN(P2)	;BACK TO ORIGINAL UNIT?
	RET			;YES - IDLE
POS5:	AOBJN Q1,POS3		;LOOP
	MOVE Q1,KDBIUN(P2)	;WRAP AROUND THE UNIT NUMBERS
	JRST POS3		;AND LOOP
	SUBTTL CHANNEL SCHEDULER


SCHXFR::MOVE T1,CDBSTS(P1)	;GET STATUS
	TXNE T1,CS.CIP!CS.MRQ!CS.MAI!CS.ERC	;CHANNEL IN MAINT MODE? OR CI?
	RET			;YES - NO NEW ACTIVITY
	SOSLE CDBFCT(P1)	;CHECK "FAIRNESS" COUNT
	JRST SCHLTM		;NOT TIME TO ROUND ROBIN, DO LAT OPT
	TXNE T1,CS.AC1		;IS CHANNEL NOW ACTIVE?
	RET			;YES - WAS A POSSIBLE COMMAND STACK REQ
	MOVEI T1,INIFCX		;RESET COUNT
	MOVEM T1,CDBFCT(P1)	; ...
	MOVE Q1,CDBCUN(P1)	;CONTINUE SCAN FROM LAST ACTIVE UNIT AND REL IT
	SKIPE P3,(Q1)		;CHECK FOR UNIT EXISTANCE
	JRST [	LDB T1,USYBKT	;GET BLOCK TYPE
		CAIE T1,.BTUDB	;IS IT A UDB?
		JRST XFR0	;NO FORGET IT
		MOVE T1,UDBDSP(P3) ;RELEASE PORT
		CALL UDSPRL(T1)	;RELEASE PORT
		JRST XFR0]
XFR0:	MOVE Q1,CDBCUN(P1)	;CONTINUE SCAN FROM LAST ACTIVE UNIT
	JRST XFR3

XFR1:	SKIPN P3,(Q1)		;ANY SUCH UNIT?
	JRST XFR2		;NO - CONTINUE SCAN
	LDB T1,USYBKT		;GET BLOCK TYPE
	CAIE T1,.BTUDB		;UDB?
	JRST XFR4		;SCAN KDB
	HRRZ P2,UDBKDB(P3)	;GET KDB IF ANY
	HRRZ P4,UDBTWQ(P3)	;GET REQUEST
	JUMPE P4,XFR2		;NOTHING - CONTINUE SCAN
	MOVE T1,UDBSTS(P3)	;GET STATUS
	TXNE T1,US.OIR!US.OMS!US.MAI!US.MRQ!US.REW!US.ACT ;AVAILABLE?
	JRST XFR2		;NO - CONTINUE SCAN
	CALL XFRX		;ATTEMPT TO START IO
	 JRST XFR3		;COULDNT - TRY ANOTHER UNIT
	RET			;ALL OK - RETURN

;HERE TO ATTEMPT TO START IO WHEN A REQUEST IS FOUND

XFRX:	MOVEM Q1,CDBCUN(P1)	;SETUP CURRENT UNIT POINTER
	CALLRET STRTIO		;START IO ON THIS IORB

XFR2:	CAMN Q1,CDBCUN(P1)	;BACK TO ORIGINAL UNIT?
	JRST XFRIDL		;YES - NOTHING TO DO, CHANNEL IDLE
XFR3:	AOBJN Q1,XFR1		;ADVANCE UNIT POINTER
	MOVE Q1,CDBIUN(P1)	;WRAPAROUND
	JRST XFR1		;CONTINUE SCAN

;HERE WHEN A CHANNEL GOES IDLE

XFRIDL:	MOVEI T1,INIFCX		;RESET "FAIRNESS" COUNT
	MOVEM T1,CDBFCT(P1)	; ...
	RET			;AND RETURN
;HERE TO SCAN A KDB FOR UDBS WITH WORK


XFR4:	MOVE P2,P3		;COPY KDB
	MOVX T1,KS.ACT		;IS IT FREE?
	TDNE T1,KDBSTS(P2)	; ???
	JRST XFR2		;NO - MOVE ALONG
	MOVE Q2,KDBCUN(P2)	;GET POINTER
	JRST XFR7		;ENTER BELOW

XFR5:	SKIPN P3,(Q2)		;UNIT PRESENT?
	JRST XFR6		;NO - TRY NEXT
	HRRZ P4,UDBTWQ(P3)	;ANY REQUESTS?
	JUMPE P4,XFR6		;NO - TRY AGAIN
	MOVX T1,US.ACT!US.POS!US.REW!US.OIR!US.OMS!US.MAI!US.MRQ
	TDNE T1,UDBSTS(P3)	;IS THE UNIT AVAILABLE?
	JRST XFR6		;NO - CONTINUE SCAN
	MOVEM Q2,KDBCUN(P2)	;YES - UPDATE POINTER
	CALL XFRX		;ATTEMPT START IO
	 JRST XFR7		;COULDNT - TRY AGAIN ON ANOTHER UNIT
	RET			;OK.

XFR6:	CAMN Q2,KDBCUN(P2)	;BACK TO STARTING UNIT?
	JRST XFR2		;YES - CONTINUE CHANNEL SCAN
XFR7:	AOBJN Q2,XFR5		;NEXT UNIT AND LOOP
	MOVE Q2,KDBIUN(P2)	;RESET TO START OF TABLE
	JRST XFR5		;AND LOOP
;HERE TO DO DISK LATENCY OPTIMIZATION

;REGISTER USAGE:
;  Q1/	UDB OF BEST IORB,,LATENCY OF BEST IORB SO FAR (MICROSECONDS)
;  Q2/	PREDECESSOR OF BEST IORB,,BEST IORB
;  Q3/	AOBJN POINTER TO UDB TABLE IN EITHER THE CDB OR KDB
;  P6/	NONZERO IF NON-DISKS FOUND ON THE CHANNEL


SCHLTM:	MOVX T1,CS.AC1		;PRIMARY COMMAND ACTIVE?
	TDNE T1,CDBSTS(P1)	; ???
	JRST SCHSTK		;YES - SEE IF WE SHOULD STACK ANOTHER
	MOVEI Q1,777777		;NIL UDB,,LARGE INITIAL BEST LATENCY
	SETZB Q2,P6		;INITIALIZE BEST IORBS AND NON-DISKS COUNT
	MOVE Q3,CDBIUN(P1)	;GET AOBJN POINTER

LTM1:	SKIPN P3,(Q3)		;UNIT EXIST?
	JRST LTM3		;NO
	LDB T1,USYBKT		;YES, GET BLOCK TYPE
	CAIN T1,.BTUDB		;IS IT A UDB?
	JRST LTM2		;YES, GO CHECK IT
	MOVE T1,KDBSTS(P3)	;IT'S A KDB, GET STATUS
	TXNN T1,KS.DSK		;THIS CONTROLLER FOR A DISK?
	AOJA P6,LTM3		;NO, COUNT IT AND LOOK SOME MORE
	TXNE T1,KS.ACT		;YES, IS THE CONTROLLER FREE?
	JRST LTM3		;NOPE, SKIP LOOKING AT IT THEN
	MOVE P2,P3		;MOVE KDB ADDRESS TO RIGHT AC
	PUSH P,Q3		;SAVE CURRENT AOBJN POINTER
	MOVE Q3,KDBIUN(P2)	;GET AOBJN POINTER TO ITS UNITS
LTM4:	SKIPN P3,(Q3)		;UNIT EXIST?
	JRST LTM6		;NO, GO EXAMINE NEXT ONE
	CALL LTMUNI		;YES, COMPUTE BEST IORB FOR IT
	 JRST [	POP P,Q3	;FOUND PREFERED IORB, RESTORE AC
		JRST LTM7]	;AND GO USE IT
LTM6:	AOBJN Q3,LTM4		;LOOP OVER ALL UNITS
	POP P,Q3		;RESTORE OLD AOBJN POINTER
	JRST LTM3		;AND CONTINUE LOOKING FOR UNITS OF CDB
LTM2:	MOVEI P2,0		;NO KDB EXISTS
	CALL LTMUNI		;COMPUTE BEST IORB FOR THIS UNIT
	 JRST LTM7		;FOUND PREFERED IORB, GO USE IT
LTM3:	AOBJN Q3,LTM1		;LOOP OVER ALL UNITS
LTM7:	JUMPE Q2,LTM5		;IF NO DISK TRANSFERS FOUND, CHECK FOR TAPES
	HLRZ P3,Q1		;GET BEST UDB
	HRRZ P2,UDBKDB(P3)	;AND CORRESPONDING KDB IF ANY
	HLRZ T1,Q2		;GET PREDECESSOR TO BEST IORB
	HRRZ T2,Q2		;GET BEST IORB
	MOVE P4,T2		; ...
	MOVE CX,UDBSTS(P3)	;GET STATUS
	CALL CONSTW		;PULL FROM TWQ
	MOVE T1,P4		;GET IORB
	CALL ONFTWQ		;PLACE AT HEAD OF TWQ
	CALL STRTIO		;ATTEMPT TO START IO
	 JRST XFR0		;FAILURE - REGRESS TO ROUND ROBIN
	MOVX T1,CS.STK		;CHANNEL SUPPORT COMMAND STACKING?
	TDNN T1,CDBSTS(P1)	; ???
	RET			;NO - DONE
	JRST STK1		;YES - ENTER COMMAND STACK SCHEDULER

LTM5:	JUMPN P6,XFR0		;IF FOUND ANY TAPES, TRY ROUND ROBIN
	JRST XFRIDL		;NOTHING TO DO, NOW IDLE
;HERE FOR EACH UDB FOUND.  THE UNIT IS CHECKED TO SEE IF IT IS AVAILABLE,
;AND IF SO, THE IORB WITH THE BEST LATENCY ON THE UNIT IS FOUND, AND
;COMPARED WITH THE BEST OVERALL ON ALL UNITS.  IF BEST SO FAR, THE IORB
;AND UDB ARE REMEMBERED IN Q1 AND Q2.  CALL:
;  P1/	CDB
;  P2/	KDB, OR 0 IF NONE
;  P3/	UDB
;  Q1-Q3/  CURRENT BEST IORBS
;  P6/	FLAG FOR NON-DISKS
;RETURNS:
;  +1:	IORB WAS FOUND WHICH IS PREFERED (WAS THE ONE IN CDBIRB)
;  +2:	NORMAL TYPE IORBS EXAMINED



LTMUNI:	HRRZ T1,UDBTWQ(P3)	;ANYTHING ON THE TRANSFER WAIT QUEUE?
	JUMPE T1,RSKP		;NO, RETURN
	MOVE T1,UDBSTS(P3)	;GET STATUS OF THE UNIT
	TXNE T1,US.OIR!US.OMS!US.MAI!US.MRQ!US.REW!US.ACT!US.POS
	RETSKP			;UNIT NOT AVAILABLE
	TXNN T1,US.DSK		;IS UNIT A DISK?
	AOJA P6,RSKP		;NO, ADVANCE COUNTER AND RETURN
	MOVEI T1,MINLAT		;MINIMUM ACCEPTABLE LATENCY
	PUSH P,P6		;SAVE COUNTER
	HRRZ T2,UDBDSP(P3)	;GET UNIT DISPATCH
	CALL UDSLTM(T2)		;GET BEST TRANSFER ON THIS UNIT
	 BUG.(HLT,PHYLTF,PHYSIO,HARD,<PHYSIO - SCHLTM - Unexpected LATOPT failure>,,<

Cause:	The routine SCHLTM was called to do disk latency optimization,
	by scanning all units for the best IORB.  A unit was found to have a
	nonnull transfer wait queue, but the lower level code to select the
	best IORB for that unit gave the non-skip return, indicating that no
	IORBs existed.
>)
				; T1/ LATENCY IN USEC (0 MEANS PREFERED IORB)
				; T2/ PRED. TO BEST IORB
				; T3/ BEST IORB
	POP P,P6		;RESTORE COUNTER
	CAIL T1,(Q1)		;BETTER THAN CURRENT BEST?
	RETSKP			;NO, LOOK AT NEXT UNIT
	MOVE Q1,T1		;YES - SAVE AS CURRENT BEST TIME
	HRL Q1,P3		;SAVE BEST UDB
	MOVE Q2,T3		;SAVE BEST IORB
	HRL Q2,T2		;SAVE PREDECESSOR TO BEST IORB
	JUMPN T1,RSKP		;SKIP RETURN IF NOT PREFERRED IORB
	RET			;RETURN NON-SKIP FOR SPECIAL IORB
;HERE TO DECIDE IF A SECOND COMMAND SHOULD BE STARTED TO THIS CHANNEL
;THOSE CHANNELS (RH20) WHICH SUPPORT A COMMAND STACK CAN BE RUN AT
;THEORETICAL BANDWIDTH ON A PER PAGE BASIS.

;FOR THE PRESENT, ONLY THE CURRENTLY ACTIVE UNIT IS SCANNED FOR
;A REQUEST TO STACK. A REQUEST WILL BE STACKED ONLY IF ITS LATENCY
;IS BETWEEN MINLTS AND MINLAT + (TIME TO TRANSFER ONE PAGE).


SCHSTK:	MOVX T1,CS.STK		;SET UP FOR TEST
	TDNE T1,CDBSTS(P1)	;DOES THIS CHANNEL SUPPORT COMMAND STACKING?
	SKIPGE P3,CDBXFR(P1)	;AND IS THERE A CURRENTLY TRANSFERING UNIT?
	RET			;NO
	ADDI P3,CDBUDB(P1)	;DOUBLE INDEX
	MOVE P3,(P3)		;TO GET UDB/KDB
	LDB T1,USYBKT		;GET BLOCK TYPE
	SETZ P2,		;ASSUME NO KDB NEEDED
	CAIN T1,.BTUDB		;IS IT A UDB?
	JRST STK0		;YES, PROCEED
	MOVE P2,P3		;WAS REALLY A KDB, COPY ADDRESS
	MOVE T1,UDBSTS(P3)	;GET STATUS
	SKIPE P3,KDBACT(P2)	;GET CURRENTLY ACTIVE SLAVE
	TXNN T1,US.DSK		;AND VERIFY THIS IS A DISK DEVICE
	RET			;NOT ACTIVE OR NOT A DISK
STK0:	MOVE T1,UDBSTS(P3)	;GET STATUS
	TXNE T1,US.CHB		;DON'T DO STACKING ON HOMEBLOCKS
	RET
	HRRZ P4,UDBTWQ(P3)	;GET CURRENT HEAD OF TWQ
STK1:	HRRZ P4,IRBLNK(P4)	;CHECK TO SEE IF MORE
	JUMPE P4,R		;THAN ONE REQUEST
	MOVX T1,SF%FLO		;TEST GLOBAL "FULL LATENCY OPT" ENABLE
	TDNN T1,FACTSW		; OK?
	RET			;NO
	MOVEI T1,0		;YES - FLAG STACK LATOPT, ASSUMES DISK
				; IS JUST AFTER CURRENT PAGE
	HRRZ T2,UDBDSP(P3)	;GET UNIT TRANSFER VECTOR
	CALL UDSLTM(T2)		;COMPUTE BEST LATENCY
	 RET			;NO STACKABLE REQUEST
	CAILE T1,MINLAT		;WILL IT BE LESS THAN MINLAT?
	RET			;NO - WAIT UNTIL CURRENT TRANSFER DONE
	DMOVE T1,T2		;YES - GET PRED IN T1, BEST IN T2
	MOVE P4,T2		;SAVE BEST IORB
	CALL CONSTW		;SPLICE IT OUT OF TWQ
	MOVE T1,P4		;GET IORB AGAIN
	CALL ONSTWQ		;MOVE TO SECOND POSITION ON TWQ
	CALL STKIO		;STACK COMMAND
	 JFCL			;NOTHING TO DO ABOUT IT
	RET
	SUBTTL	ROUTINES TO LOCK AND UNLOCK I/O PAGES



;IOLOCK - CALLED TO LOCK DOWN A CONTIGUOUS BLOCK OF USER PAGES AND RETURN
;A LIST OF THE PHYSICAL PAGES USED.  (ONLY USE NOW IS TO ALLOW MULTI-PAGE
;DSKOPS TO WORK).  THE RETURNED LIST IS PHYSICALLY CONTIGUOUS, AND IS
;TERMINATED BY AN EXTRA ZERO WORD.  CALLER MUST BE NOINT.
;ARGUMENTS:
;  T1/	ADDRESS OF USER'S BUFFER
;  T2/	SIZE OF BUFFER IN WORDS
;  T3/	NONZERO IF PAGES WILL BE WRITTEN INTO
;RETURNS:
;  +1:	FAILURE, ERROR CODE IN T1
;  +2:	SUCCESS
;	  T1/	ADDRESS OF STORAGE CONTAINING LIST OF PAGES, WHERE THE
;		FIRST WORD OF THE BLOCK IS AN AOBJN POINTER TO THE LIST



IOLOCK::ASUBR <IOLADR,IOLRES,IOLFLG,IOLCNT>	;ALLOCATE STORAGE
	SKIPLE T2		;SIZE MUST BE POSITIVE
	CAILE T2,CCWMAX*PGSIZ	;BUT NOT TOO LARGE
	 RETBAD(DSKOX5)		;NO, FAIL
	MOVE T3,T1		;COPY ADDRESS
	ADDI T3,-1(T2)		;COMPUTE LAST ADDRESS IN BUFFER
	TLNN T1,777740		;VERIFY BEGINNING ADDRESS IS REASONABLE
	TLNE T3,777740		;AND ENDING ADDRESS IS TOO
	 RETBAD(DSKOX6)		;NOPE, FAIL
	LSH T1,-PGSFT		;CONVERT ARGUMENTS TO PAGE NUMBERS
	LSH T3,-PGSFT		;SO CAN COMPUTE PAGE COUNT
	SUBM T3,T1		;GET DIFFERENCE
	ADDI T1,1		;CREATE NUMBER OF PAGES TO DO
	MOVEM T1,IOLCNT		;REMEMBER COUNT
	ADDI T1,2(T1)		;DOUBLE COUNT SO CAN GUARANTEE CONTIGUOUS LIST
	HRLI T1,.RESP1		;NO SPECIAL PRIORITY
	MOVX T2,RS%SE0!.RESGP	;USE GENERAL STORAGE POOL
	CALL ASGRES		;GET SOME FREE CORE
	 RETBAD()		;FAILED
	MOVEM T1,IOLRES		;REMEMBER STORAGE ADDRESS
	MOVEI T2,1(T1)		;GET POSSIBLE STORAGE ADDRESS FOR CCWS
	ANDI T2,PGSIZ-1		;KEEP ONLY OFFSET WITHIN PAGE
	ADD T2,IOLCNT		;CREATE LAST OFFSET NEEDED
	CAIGE T2,PGSIZ		;IF LIST WAS HERE, WOULD IT FIT ON ONE PAGE?
	TDZA T2,T2		;YES, SET UP TO USE THIS FIRST HALF
	MOVE T2,IOLCNT		;NO, THEN SECOND HALF WILL BE CONTIGUOUS
	ADDI T2,1(T1)		;COMPUTE ADDRESS WHERE LIST WILL GO
	MOVN T3,IOLCNT		;NEGATE PAGE COUNT
	HRL T2,T3		;FINISH AOBJN POINTER
	MOVEM T2,0(T1)		;SAVE IN FIRST WORD OF STORAGE BLOCK
	; ..			;FALL INTO LOOP
;LOOP OVER ALL PAGES, LOCKING THEM DOWN AND REMEMBERING THE PAGE NUMBERS:


IOLLOP:	MOVEM T2,IOLCNT		;SAVE CURRENT AOBJN WORD
	MOVE T1,IOLADR		;GET CURRENT USER ADDRESS
	SKIPN IOLFLG		;WRITING FROM THE PAGE?
	XCTU [SKIP (T1)]	;YES, VERIFY THE PAGE EXISTS
	 ERJMP IOLFAI		;REFERENCE FAILED
	SKIPE IOLFLG		;READING INTO THE PAGE?
	XCTU [SETMM (T1)]	;YES, VERIFY PAGE IS WRITABLE
	 ERJMP IOLFAI		;NOPE, FAILED
	TXO T1,1B0		;INDICATE FROM USER MODE
	CALL MLKMA		;LOCK THE PAGE
	MOVE T2,IOLCNT		;GET BACK AOBJN POINTER
	MOVEM T1,0(T2)		;PUT PAGE NUMBER INTO STORAGE LIST
	MOVEI T1,PGSIZ		;GET SIZE OF A PAGE
	ADDM T1,IOLADR		;UPDATE USER ADDRESS FOR NEXT LOOP
	AOBJN T2,IOLLOP		;LOOP OVER ALL PAGES
	MOVE T1,IOLRES		;ALL DONE, GET STORAGE ADDRESS BACK
	RETSKP			;SKIP RETURN



;HERE IF ONE OF THE PAGES CANNOT BE REFERENCED.  UNLOCK ALL PAGES
;AND GIVE AN ERROR.


IOLFAI:	MOVE T1,IOLRES		;GET ADDRESS OF STORAGE BLOCK
	SETZM T2		;DON'T MARK PAGES AS BEING WRITTEN
	CALL IOPNLK		;UNLOCK ALL PAGES IN THE LIST
	MOVE T1,LSTERR		;GET ERROR CAUSED BY THE PAGE REFERENCE
	RETBAD()		;AND RETURN THAT
;IOLCCW - ROUTINE TO CONVERT A LIST OF PHYSICAL PAGE NUMBERS INTO A LIST
;OF CCW WORDS.  CALL:
;  P1/	CDB ADDRESS
;  T1/	ADDRESS OF STORAGE FOR PAGE LIST
;  T2/	USER ADDRESS
;  T3/	SIZE OF BUFFER IN WORDS
;RETURNS:
;  +1:	ALWAYS




IOLCCW::STKVAR <IOLOFS,IOLSIZ,IOLAOB>	;ALLOCATE STORAGE
	SKIPL T1,0(T1)		;GET AOBJN POINTER TO PAGE LIST
	RET			;NONE, RETURN
	MOVEM T1,IOLAOB		;REMEMBER IT FOR LATER
	ANDI T2,PGSIZ-1		;KEEP ONLY THE OFFSET INTO THE USER PAGE
	MOVEM T2,IOLOFS		;SAVE FOR LATER
	MOVEM T3,IOLSIZ		;AND SAVE SIZE OF BUFFER

IOLCLP:	MOVEI T1,PGSIZ		;GET SIZE OF A PAGE
	SUB T1,IOLOFS		;SUBTRACT OFFSET TO GET WORDS REMAINING IN PAGE
	CAMLE T1,IOLSIZ		;REMAINING BUFFER LESS THAN THAT?
	MOVE T1,IOLSIZ		;YES, REDUCE WORD COUNT
	MOVN T2,T1		;GET READY
	ADDM T2,IOLSIZ		;DECREMENT WORDS LEFT IN THE BUFFER
	HRLI T1,IRMWRD		;WANT WORD MODE
	MOVE T2,IOLAOB		;GET POINTER TO CURRENT LIST ELEMENT
	MOVE T2,0(T2)		;THEN GET PHYSICAL PAGE NUMBER
	LSH T2,PGSFT		;CONVERT INTO ADDRESS
	IOR T2,IOLOFS		;FINISH THE ADDRESS BY ADDING IN OFFSET
	HRRZ T3,CDBDSP(P1)	;GET CHANNEL DISPATCH ADDRESS
	HRRZ T3,CDSCCW(T3)	;AND THEN CCW ROUTINE
	CALL (T3)		;TRANSLATE ADDRESS AND COUNT INTO CCW VALUE
	MOVE T2,IOLAOB		;GET BACK AOBJN WORD
	MOVEM T1,(T2)		;STORE CCW WORD BACK INTO THE LIST
	AOBJP T2,R		;RETURN IF DID ALL WORDS
	MOVEM T2,IOLAOB		;MORE TO DO, SAVE UPDATED AOBJN WORD
	SETZM IOLOFS		;OFFSET IS NOW ZERO
	JRST IOLCLP		;GO DO NEXT PAGE
;IOCNLK AND IOPNLK - ROUTINES TO UNLOCK A LIST OF PAGES AND RETURN THE
;RESIDENT STORAGE.  USE IOPNLK IF LIST IS PAGE NUMBERS, OR USE IOCNLK IF
;THE LIST IS CCW WORDS.  MUST BE CALLED NOINT.  CALL:
;  P1/	CDB ADDRESS IF CALLING IOCNLK
;  T1/	ADDRESS OF LIST OF PAGES
;  T2/	NONZERO IF PAGES WERE WRITTEN INTO
;RETURNS:
;  +1:	ALWAYS



IOCNLK::HRRZ T3,CDBDSP(P1)	;GET DISPATCH ADDRESS FOR CHANNEL
	MOVE T3,CDSCCA(T3)	;THEN GET ROUTINE TO EXTRACT ADDRESS FROM CCW
	TXOA T3,IFIW		;MAKE SURE INDIRECT WORKS IN SECTION 1
IOPNLK::SETZ T3,		;OR INDICATE NO ROUTINE TO CALL
	SKIPL T4,(T1)		;GET AOBJN POINTER TO LIST
	CALLRET RELRES		;NONE THERE, JUST RELEASE STORAGE
	ASUBR <IOURES,IOUFLG,IOUCCW,IOLAOB>	;REMEMBER ARGUMENTS

IOUNLP:	MOVEM T4,IOLAOB		;SAVE UPDATED AOBJN WORD
	SKIPN T1,(T4)		;OBTAIN NEXT ELEMENT FROM LIST IF ANY
	JRST IOUNXT		;NONE THERE
	SKIPE T2,IOUCCW		;NEED TO CONVERT CCW TO PAGE NUMBER?
	CALL (T2)		;YES, FIRST EXTRACT ADDRESS FROM CCW
	SKIPE IOUCCW		;WELL?
	LSH T1,-PGSFT		;YES, TURN ADDRESS INTO PAGE NUMBER
	JUMPE T1,IOUNXT		;IF ZERO, NOTHING TO DO
	SKIPE IOUFLG		;WAS PAGE WRITTEN INTO?
	CALL MRKMPG		;YES, MARK IT AS BEING MODIFIED
	CALL MULKCR		;THEN UNLOCK THE PAGE
IOUNXT:	MOVE T4,IOLAOB		;GET BACK AOBJN WORD
	AOBJN T4,IOUNLP		;LOOP FOR NEXT ELEMENT
	MOVE T1,IOURES		;UNLOCKED EVERYTHING, GET BACK ADDRESS
	CALLRET RELRES		;RELEASE STORAGE BLOCK AND RETURN
	SUBTTL UDSKIO AND MDSKIO



;UDSKIO AND MDSKIO - GENERAL NON-PAGE ALIGNED DISK I/O ROUTINES.  USED
;FOR SPECIAL DISK I/O SUCH AS READING HOME BLOCKS, BAT BLOCKS, AND
;THE DSKOP JSYS.  CALL:
;  T1/	PHYSICAL DISK ADDRESS (SECTOR NUMBER)
;  T2/	FLAGS,,WORD COUNT  (FLAG DOP%WR MEANS WRITE)
;  T3/	PHYSICAL MEMORY ADDRESS (OR ADDRESS OF LIST OF CCW WORDS FOR MDSKIO)
;  T4/	IF 1B0 SET IN T2:  CKU NUMBER OF UNIT FOR I/O
;	IF 1B0 CLEAR IN T2:  STRUCTURE NUMBER
;RETURNS:  +1:	ALWAYS
;	  T1/	ZERO IF SUCCESSFUL, ERROR BITS IF I/O FAILED
;
;RESTRICTIONS:  MDSKIO CAN CROSS ARBITRARY PAGE BOUNDARIES, BUT THE
;TOTAL NUMBER OF WORDS READ/WRITTEN MUST BE AN EXACT MULTIPLE OF THE
;DISK SECTOR SIZE.  MDSKIO ALSO CANNOT DO ERROR RECOVERY OR ERROR LOGGING.
;UDSKIO CAN READ PARTIAL SECTORS, AND DOES ERROR RECOVERY AND LOGGING,
;BUT THE I/O CANNOT CROSS A PAGE BOUNDARY.  ALSO FOR WRITES, THE COUNT
;IS MODIFIED SO THAT AN EXACT MULTIPLE OF DISK SECTORS IS WRITTEN (THIS
;IS NECESSARY TO PREVENT PARITY ERRORS FROM THE CHANNEL).  THEREFORE,
;TO WRITE OUT THE HOME AND BAT BLOCKS, IT IS NECESSARY TO BEGIN THE
;WRITE AT THE TOP OF A PAGE SO THAT THE TRANSFER WON'T TRY TO GO OFF
;THE END OF THE PAGE FOR AN RP20.

MDSKIO::SAVEPQ			;SAVE ACCUMULATORS
	SKIPL Q3,0(T3)		;GET AOBJN WORD TO CCW LIST
	 JRST UIOILA		;NONE, THEN FAIL
	JRST UIO1		;PROCEED

UDSKIO::SAVEPQ			;SALT AWAY ACCUMULATORS
	SETZM Q3		;SAY NO LIST EXISTS
UIO1:	STKVAR <IRBSAV>		;SAVE IRB COUNT
	SETZM IRBSAV		;CLEAR IRB COUNT FLAG
	DMOVE P5,T2		;SAVE FLAGS, COUNT, AND MEMORY ADDRESS
	CALL GETIRB		;GET IORB+CCW BLOCK IN P4, WAIT IF NEEDED
	MOVEM T1,IRBADR(P4)
	HRRZM P5,IRBCNT(P4)	;STORE COUNT IN IORB
	MOVEI T1,IRFRED		;SEE IF READ OR WRITE
	TXNE P5,DOP%WR		; ...
	MOVEI T1,IRFWRT		;IS WRITE.
	DPB T1,IRYFCN		;STORE IN IORB
	MOVEI T1,IRMWRD		;WORD MODE
	DPB T1,IRYMOD		;STORE IN IORB
	MOVEI T1,0		;COPY INHIBIT ERR LOG OR RECOVERY BITS
	TXNE P5,DOP%IR		;INHIBIT ERROR RECOVERY?
	TXO T1,IS.IER		;YES, INHIBIT IT
	TXNE P5,DOP%IL		;INHIBIT ERROR LOGGING?
	TXO T1,IS.IEL		;YES
	SKIPE Q3		;CALLED AT MDSKIO?
	TXO T1,IS.IER!IS.IEL	;YES, DISABLE ERROR RECOVERY AND LOGGING
	IORM T1,IRBSTS(P4)	;STORE IN IORB
	MOVEI T1,0		;NO SIO EXIT NEEDED UNLESS
	TXNE P5,DOP%EO		;USER ASKED FOR ERROR ON OFFLINE
	MOVEI T1,UDISIE		;CALLER WANTS ERROR
	HRLM T1,IRBIVA(P4)	;STORE EXIT OR NOT
	JUMPGE P5,[CALL FIXIRB	;FIX IRB ADDRESS IF DOP%PS
		   MOVEM T2, IRBSAV	;SET IRB ADJUSTED FLAG
		   MOVE T1,IRBADR(P4);MASK EXTRANEOUS BITS
		   TLZ T1,DSKMSK
		   TXO T1,DSKAB	;SET DISK ADDRESS BIT
		   MOVEM T1,IRBADR(P4)
		   CALL GETCUB	;IF STRUCTURE ADDRESS, COMPUTE UNIT ADDRESS
		    JRST UIOILX	;IT WAS ILLEGAL
		   SKIPE IRBSAV	;DID WE FIXUP IRB?
		   JRST [ MOVE T2,IRBSAV ;GET SAVED ADDRESS
		   ANDI T2,3	;GET LOW ORDER BITS
		   LSH T1,2		;BUILD REAL ADDRESS AGAIN
		   IOR T1,T2
		   MOVEM T1,IRBADR(P4)	;SAVE UNIT RELATIVE ADDRESS
		   JRST UIO2]

		MOVEM T1,IRBADR(P4)	;SAVE UNIT RELATIVE ADDRESS
		JRST UIO2]		;AND PROCEED WITH P1, P2, AND P3 SET UP
	MOVE T1,T4		;WANTS PHYSICAL UNIT, COPY CKU NUMBER
	CALL CKUNPK		;UNPACK THEM
	CALL CHKCKU		;VERIFY A LEGAL UNIT WAS SELECTED
	 JRST UIONUN		;NOPE, FAIL
	MOVE P3,T1		;COPY UDB ADDRESS
	HRRZ P2,UDBKDB(P3)	;SET UP KDB POINTER
	HRRZ P1,UDBCDB(P3)	;AND CDB POINTER
	MOVSI T1,DSKMSK		;INVALID BITS IN DISK ADDRESS
	TXNE P5,DOP%PS		;CHECK FOR PHYSICAL STRUCTURE
	MOVSI T1,DSKMSK*4	;LARGER SIZE IS LEGAL
	ANDCAB T1,IRBADR(P4)	;CLEAR THE BITS AND GET DISK ADDRESS
	HRRZ T2,UDBSIZ(P3)	;GET POINTER TO SIZE TABLES
	MOVE T3,TRECPP(T2)	;CHECK SECTORS EQUAL TO TRUE SECTORS
	CAME T3,SECPAG(T2)	;LEGAL?
	LSH T1,-2		;NO DIVIDE BY 4
	CAML T1,SECUNT(T2)	;LEGAL DISK ADDRESS SPECIFIED?
	 JRST UIOILA		;NOPE, FAIL
UIO2:	TXNN P5,DOP%EO		;WANT ERROR ON OFFLINE?
	JRST UIO3		;NO, PROCEED
	MOVE T1,UDBSTS(P3)	;YES, GET UNIT STATUS
	MOVE T2,CDBSTS(P1)	;AND CHANNEL STATUS
	TXNN T1,US.OFS!US.CHB	;UNIT OFFLINE?
	TXNE T2,CS.OFL		;OR CHANNEL OFFLINE?
	 JRST UIOUFL		;YES, RETURN ERROR
UIO3:	HRRZ Q2,UDBSIZ(P3)	;SET UP POINTER TO UNIT SIZE TABLE
	MOVE Q1,P5		;SAVE STATUS
	TXNN P5,DOP%WR		;WRITING?
	JRST UIO5		;NO, CAN SKIP ON
	MOVEI T1,PGSIZ		;GET SIZE OF PAGE
	TXNE P5,DOP%PS		;CHECK FOR PHYSICAL STRUCTURE
	JRST [	IDIV T1,TRECPP(Q2) ;GET TRUE SECTORS PER PAGE
		JRST UIO4]
	IDIV T1,SECPAG(Q2)	;COMPUTE SIZE OF A SECTOR
UIO4:	TRNN P5,-1(T1)		;WRITING PARTIAL SECTOR?
	JRST UIO5		;NO, SKIP ON
	SKIPE Q3		;CALLED AT MDSKIO?
	 JRST UIONDS		;YES, ERROR IF NOT EXACT SECTOR SIZE
	IORI P5,-1(T1)		;INCREMENT COUNT TO JUST BELOW NEXT SECTOR
	HRRI P5,1(P5)		;THEN TURN INTO EXACT MULTIPLE OF A SECTOR
	HRRZM P5,IRBCNT(P4)	;UPDATE COUNT IN IORB TOO
	MOVE T1,P6		;COPY MEMORY ADDRESS
	ANDI T1,PGSIZ-1		;LEAVE ONLY THE OFFSET INTO THE PAGE
	ADDI T1,(P5)		;ADD IN NEW COUNT
	CAILE T1,PGSIZ		;TRYING TO DO I/O OFF THE PAGE?
	 JRST UIOOPB		;YES, FAIL
UIO5:	MOVE T1,IRBADR(P4)	;GET DISK ADDRESS OF BEGINNING OF TRANSFER
	MOVE T2,Q1		;GET FLAGS
	MOVE Q1,T1
	TXNE T2,DOP%PS		;CHECK FOR PHYSICAL SECTOR ADDRESSING
	JRST [	MOVX T2,IRBPAD	;GET PHYSICAL BIT
		IORM T2,IRBADR(P4) ;SET IN THE ADDRESS
		ANDCAM T2,T1	;GET RID OF PHYSICAL BIT INCASE IT WAS SET
		MOVE T2,TRECPP(Q2) ;PHYSICAL AND LOGICAL THE SAME?
		CAME T2,SECPAG(Q2)
		LSH T1,-2	   ;NO FORM A GOOD ADDRESS
		MOVE Q1,T1	;SAVE CORRECT ADDRESS
		JRST .+1]
	IDIV T1,SECCYL(Q2)	;COMPUTE CYLINDER THIS SECTOR IS ON
	MOVE T2,IRBCNT(P4)	;GET WORD COUNT
	MOVEI T3,PGSIZ		;SIZE OF A PAGE
	IDIV T3,SECPAG(Q2)	;COMPUTE SECTOR SIZE FOR UNIT
	ADDI T2,-1(T3)		;ROUND UP PARTIAL SECTORS
	IDIV T2,T3		;COMPUTE NUMBER OF SECTORS I/O IS FOR
	ADD T2,Q1		;ADD ORIGINAL SECTOR TO THIS
	SOS T2			;FINALLY GET DISK ADDRESS OF END OF TRANSFER
	IDIV T2,SECCYL(Q2)	;COMPUTE CYLINDER THIS SECTOR IS ON
	CAME T1,T2		;WOULD WHOLE TRANSFER BE ON SAME CYLINDER?
	 JRST UIOILA		;NO, FAIL
	JUMPE Q3,UIO6		;SKIP ON IF CALLED AT UDSKIO
	HRRZM Q3,IRBXFL(P4)	;STORE FIRST CCW WORD ADDRESS AS HEAD
	HLRE T1,Q3		;EXTRACT NEGATIVE LENGTH OF CCW LIST
	SUBM Q3,T1		;COMPUTE END OF CCW LIST
	HRLM T1,IRBXFL(P4)	;STORE ADDRESS AS TAIL
	SETZM IRBLEN(P4)	;CLEAR NORMAL CCW LOCATION SINCE NOT USED
	JRST UIO7		;PROCEED

UIO6:	MOVEI T1,IRBLEN(P4)	;BUILD TAIL,,HEAD OF CCW LIST
	HRLI T1,IRBLEN+1(P4)	; ...
	MOVEM T1,IRBXFL(P4)	;STORE
	DMOVE T1,P5		;RETRIEVE WORD COUNT AND PHYSICAL ADDRESS
	HRLI T1,IRMWRD		;INSERT WORD MODE
	HRRZ T3,CDBDSP(P1)	;GET DISPATCH BASE
	CALL CDSCCW(T3)		;BUILD CCW INTO T1
	MOVEM T1,IRBLEN(P4)	;STORE AS FIRST WORD OF CCW LIST

UIO7:	SETZM IRBLEN+1(P4)	;CLEAR SECOND WORD OF CCW LIST
	MOVEI T1,UDIINT		;INTERRUPT ROUTINE TO CALL
	HRRM T1,IRBIVA(P4)	;STORE IN IORB
	MOVE T1,P4		;GET IORB FOR STARTING IO
	MOVE T2,P3		;ALSO GET UDB
	NOSKED			;PREVENT INTERRUPTIONS
	CALL PHYSIO		;START THE IO
	OKSKED
UIO9:	MOVEI T1,UDWDON		;WAIT FOR DONE
	HRL T1,P4		;ON THIS IORB
	PDISMS			; AS A PAGE FAULT
	MOVE T1,IRBSTS(P4)	;EXAMINE STATUS BITS
	TXNN T1,IS.DON		;CONDITION SATISFIED?
	JRST UIO9		;NO - BLOCK AGAIN
	TXNE T1,IS.ERR		;ANY ERRORS?
	JRST UIOCK0		;YES FIX ERRORS
	MOVEI T1,0		;NO - RETURN 0
UIOXIT:	CALLRET GIVIRB		;RELEASE THIS IORB

UIOCK0:	TXNN T1,IS.DVE!IS.DTE	;DATA OR DRIVE ERRORS?
UIOUFL:	SETO T1,0		;NO ASSUME OFFLINE
	CALLRET GIVIRB		;RELEASE IORB AND RETURN

;HERE WITH P5 FLAGS,P4 IORB,T4 STRUCTURE NUMBER
;IF FIXUP REQUIRED T2 CONTAINS THE UNFIXED ADDRESS
;RETURNS +2 IF NO FIXUP REQUIRED
;RETURNS +1 IF FIXUP REQUIRED


FIXIRB:	TXNN P5,DOP%PS		;CHECK FOR PHYSICAL STRUCTURE
	RETSKP			;RETSKPURN NOT A PS REQUEST
	SKIPN T2,STRTAB(T4)	;IS THERE A STRUCTURE?
	RETSKP			;NO JUST RETSKPURN IT WILL BE CAUGHT LATER
	MOVE T2,SDBUDB(T2)	;GET A UDB POINTER
	HRRZ T2,UDBSIZ(T2)	;GET THE SIZE POINTER TABLE
	MOVE CX,SECPAG(T2)	;GET THE NUMBER OF SECTORS PER PAGE
	CAMN CX,TRECPP(T2)	;DIFFERENT SIZE?
	RETSKP			;NO ALL OK
	MOVE T1,IRBADR(P4)	;GET THE ADDRESS
	MOVE T2,T1		;COPY ADDRESS
	LSH T1,-2		;MAKE IT LOOK GOOD
	MOVEM T1,IRBADR(P4)
	RET			;RETURN FIXUP REQUIRED
	
;HERE FOR VARIOUS UDSKIO ERRORS.  
;THE ERROR IS RETURNED IN THE RIGHT HALF OF T1, AND -1 IN THE LEFT HALF.
;(BUT CURRENT CALLERS ONLY CHECK FOR A NONZERO OR NEGATIVE RESULT).

UIOILX:	HRROI T1,DKOP01
	JRST UIOXIT		;QUIT
UIOOPB: HRROI T1,DKOP02
	JRST UIOXIT
UIONUN: HRROI T1,DKOP03
	JRST UIOXIT
UIOILA:	HRROI T1,DKOP04
	JRST UIOXIT
UIONDS:	HRROI T1,DKOP05		;NON DISK ERROR CODE (-1,,PC)
	JRST UIOXIT

;HERE JUST BEFORE SIO OF UDSKIO REQUEST
;CHECK IF UNIT OFFLINE

UDISIE:	MOVX T1,US.OFS!US.CHB	;UNIT ACCESSABLE
	TDNE T1,UDBSTS(P3)	; ???
	JRST UDISI1		;OFFLINE
	MOVX T1,U1.OFS		;CHECK FOR FORCED OFFLINE
	TDNN T1,UDBST1(P3)
	RETSKP			;ALL OK TO TRANSFER
UDISI1:	MOVX T1,IS.ERR!IS.NRT	;NO, GET ERROR BITS
	IORM T1,IRBSTS(P4)	;STORE INTO IORB
	RET			;FAIL RETURN

;HERE AT INTERRUPT LEVEL WHEN REQUEST COMPLETED

UDIINT:	AOS PSKD1		;FLAG SCHEDULER
	RET

; ALTERNATE ENTRY TO GETIRB THAT WILL RETURN +1 FOR NO IORB AND +2 FOR SUCCESS
;
GETIRC:	SKIPN UIOLST		;CHECK FOR A FREE ENTRY
	RET			;RETURN FAILURE NO MORE ROOM
	AOS (P)			;PROVIDE SKIP RETURN
	JRST GETICC
;
;HERE TO GET AN IORB FROM THE POOL
;	CALL GETIRB
;RETURNS+1(ALWAYS):
;P4/ IORB + CCW BLOCK (LENGTH UIOLEN)

GETIRB:	SKIPN NSKED		;NOSKED?
	JRST GETIR1		;NO - USUAL CASE
	SKIPN UIOLST		;YES - ANY LEFT
	BUG.(HLT,UIONIR,PHYSIO,HARD,<UDSKIO - No IORB for NOSKED fork>,,<

Cause:	The routine UDSKIO was called to do special I/O for a fork,
	and to do the I/O it uses one of a group of preallocated IORBs.
	There were no free IORBS left, and the fork could not
	block because it was NOSKED.
>)
GETICC:	PIOFF
	MOVE P4,@UIOLST		;GET SUCCESSOR
	EXCH P4,UIOLST		;NOW HEAD OF LIST
	JRST GETIR2		;CLEAR IORB AND RETURN

GETIR1:	PIOFF			;INTERLOCK LIST MANIPULATION
	SKIPN UIOLST		;LIST NONNULL?
	JRST GETIR3		;NO.
	SKIPN P4,@UIOLST	;TEST/GET SUCCESSOR
	JRST GETIR3		;NO SUCCESSOR - FORCE BLOCK
	EXCH P4,UIOLST		;NEW HEAD OF LIST
GETIR2:	PION			;RELEASE PROCESSOR
	SETZM 0(P4)		;CLEAR FIRST WORD OF BLOCK
	MOVS CX,P4		;BUILD BLT POINTER
	HRRI CX,1(P4)		; ...
	BLT CX,UIOLEN-1(P4)	;CLEAR BLOCK
	RET

GETIR3:	PION			;WE MUST BLOCK
	CALL UDIWAT		; ...
	JRST GETIR1		;AND TRY AGAIN

;SCHEDULER TEST ROUTINE, WAITS FOR IORB DONE BIT

UDWDON::MOVX T2,IS.DON		;CHECK DONE BIT
	TDNN T2,IRBSTS(T1)	;IN IORB
	JRST 0(T4)		;STILL WAITING
	JRST 1(T4)		;ALL DONE

;HERE WHEN THE IORBS ARE IN USE. WAIT FOR THEM TO BECOME FREE

UDIWAT:	SAVET			;SAVE ARGUMENTS
UDIWT1:	MOVEI T1,UDITST		;WAIT FOR FREE IORB
	MDISMS			;ORDINARY BLOCK - MAY BE LONG TERM
	RET			;FREE, LOCK ACQUIRED

;SCHEDULE TEST TO WAIT FOR IORB

UDITST:	SKIPE T1,UIOLST		;LIST NON NULL
	SKIPN (T1)		;AT LEAST 2 FREE?
	JRST 0(T4)		;NO
	JRST 1(T4)		;YES

;HERE TO RELEASE AN IORB TO THE FREE LIST

GIVIRB:				;RETURN AN IORB
	CAIL P4,UDIORB		;IS IORB LEGAL?
	 CAILE P4,<UDIORB-1+<NUIORB*UIOLEN>> ;LEGAL?
	  BUG. (HLT,BADIRB,PHYSIO,SOFT,<Bad IORB passed to GIVIRB>,,<

Cause:	An IORB was passed to GIVIRB that does not have a legal address.
	This indicates a software problem in the monitor.
>)
	PIOFF
	EXCH P4,UIOLST		;NEW HEAD OF LIST
	MOVEM P4,@UIOLST	;STORE FOREWARD LINK
	PION
	RET
	SUBTTL PAGEM INTERFACE

;HERE TO TRANSFER A PAGE
;T1/ CPN	;1B0 ON IF WRITE
;	CALL DSKIO, DRMIO
;RETURNS+1(ALWAYS)

DSKIO::
DRMIO::	PUSH P,P4		;SAVE P4, IORB MUST BE IN P4 FOR IRYFCN
	PUSH P,T1		;SAVE T1 FOR PAGEM
;**;[7247]  Add 11 lines after DRMIO:+1			DML	19-Feb-86
	CALL ISOCSH		;[7247] (T1/)Is OFN which owns page cached?
	 BUG.(HLT,TCSOFN,PHYSIO,SOFT,<Transfer of cached OFN page>,,<

Cause:	An attempt has been made to transfer a core page from or to disk.
	However, this page belongs to a cached OFN and this should not 
	happen.

Action:	Trace the stack and locate the caller.  All callers should be 
	aware of cached OFN pages and take appropriate action to insure
	that these pages are not transfered
>)				;[7247] It is cached - error!
	MOVX T2,DWRBIT		;COPY WRITE BIT TO CST3 FOR PAGEM
	AND T2,T1		; ...
	HRRZ P4,T1		;GET ONLY RIGHT HALF OF T1
	IORM T2,@CST3X+P4	; ...
	MOVEI P4,CST5(T1)	;PUT IORB ADDRESS IN P4
	MOVX T2,IS.SHT		;FLAG AS SHORT IORB
	MOVEM T2,IRBSTS(P4)	;INITIALIZE IORB
	MOVEI T2,IRFRED		;SET IORB FUNCTION
	TXNE T1,DWRBIT		;WRITE?
	MOVEI T2,IRFWRT		;YES
	DPB T2,IRYFCN		;STORE IN IORB
	MOVE T1,P4		;COPY IORB ADDRESS
	CALL PHYSIO		;NOTE - ALREADY NOSKED
	POP P,T1		;RESTORE T1
	POP P,P4		;RESTORE P4
	RET

;HERE TO QUEUE A LIST OF PAGES FOR SWAPPER
;T1/ DWRBIT,,FIRST PAGE CST INDEX
;	CALL DXXIOM
;RETURNS+1(ALWAYS):
;	WHOLE LIST STARTED

DSKIOM::
DRMIOM::PUSH P,P4		;SAVE VARIABLE FOR POINTER
IOMNXT:	HRRZ T2,T1		;GET RIGHT HALF OF T1 FOR INDEXING
	HRRZ P4,@CST3X+T2	;GET FORWARD LINK
	HLLZS @CST3X+T2		;CLEAR FORWARD LINK IN MEMORY
	CALL DRMIO		;INSERT REQUEST
	JUMPE P4,IOMXIT		;WAS LINK NULL
	HRR T1,P4		;COPY (NOTE: DWRBIT IS STILL IN LH(T1))
	JRST IOMNXT		;LOOP

IOMXIT:	POP P,P4		;RESTORE
	RET

DRMINI::SETOM DRMJ0R		;SO OLD ERROR LOGGER IS HAPPY
	SKIPG DRUMP
	TDZA T1,T1		;NO DRUMS UNLESS DRUMP .GT. 0
	MOVE T1,DRMNUM		;GET NUMBER OF DRUMS FROM RS4INI
	MOVEM T1,NPDRMS		;STORE FOR REST OF WORLD
	RET
	SUBTTL OPERATOR INTERVENTION, RESTART AND TIMEOUT


;ENTERED FROM SCHEDULER WHEN PHYTIM GT TODCLK.


PHYCHK::SAVEPQ			;SAVE ACCUMULATORS
	MOVEI T1,^D1000		;UPDATE NEXT CALL
	MOVEM T1,PHYTIM		; ...
	AOS T1,PHYSEC		;INCREMENT LOCAL ONCE A MINUTE TIMER
	CAILE T1,^D59		;AND IF EXPIRED,
	SETZM PHYSEC		;WRAPAROUND
CHK1:
	MOVSI Q1,-CHNN    	;LOOP OVER ALL CHANNELS
CHK2:	SKIPN P1,CHNTAB(Q1)	;IS THIS CHANNEL PRESENT?
	JRST CHK3		;NO - TRY NEXT
	MOVX T1,CS.OFL!CS.MAI	;CHANNEL OFFLINE OR IN MAINTENENCE MODE?
	TDNE T1,CDBSTS(P1)	;OR HAVE NO UNITS?
	JRST CHK3		;YES - IGNORE IT.
	HRRZ T1,CDBDSP(P1)	;GET CHANNEL DISPATCH
	CALL CDSCHK(T1)		;AND CALL PERIODIC CHECKER
	CALL DGUMAP		;FOR EACH UNIT,
	 CALL UNICHK		;DO CHECK CODE
CHK3:
	AOBJN Q1,CHK2     	;AND LOOP FOR ALL CHANNELS
	RET			;DONE

;HERE IF THE HOME BLOCK CHECK IORB IS DONE.
CHK8:	SAVEQ			;SAVE A FEW REGISTERS
	MOVE T1,IRBSTS(P4)	;ANY ERRORS?
	CALL GIVIRB		;RETURN THE IORB
	SETZM UDBCHB(P3)	;CLEAR IORB FLAG
	TXNE T1,IS.ERR
	JRST CHK21		;YES - COMPLAIN
	HRRZ Q1,UDBSTR(P3)	;GET STR
	SKIPGE UDBSTR(P3)	;GET STR UNIT IS IN
	TDZA Q1,Q1		;UNIT NO LONGER IN STR
	MOVE Q1,STRTAB(Q1)	;GET SDB
	MOVE T1,UDBNAM(P3)	;CHECK HOME BLOCK NAME AND CODE
	MOVE T2,UDBCOD(P3)	;GET HOMCOD (SYMBOL? )
	CAMN T1,[SIXBIT /HOM/]	;BLOCK NAME GOOD?
	CAIE T2,CODHOM		;BLOCK CODE GOOD?
	JRST CHK20		;NO TO EITHER
	HRRZ T3,UDBLUN(P3)	;CHECK IF SAME UNIT
	CAILE T3,MXSTRU		;LESS THAN MAXIMUM?
	JRST CHK20		;NO
	MOVE T1,UDBSNM(P3)	;CHECK STRUCTURE NAME
	MOVE T2,UDBMID(P3)	;AND "UNIQUE" ID
	JUMPE Q1,CHK11		;SEE IF OPR MOVED PACK IF UDB NOT IN A STR
	CAMN T1,SDBNAM(Q1)	;SAME NAME?
	CAME T2,SDBPUC(Q1)	;SAME CODE?
	JRST CHK11		;NO TO EITHER
	ADDI T3,SDBUDB(Q1)	;YES - GET POINTER TO UDB
	HRRZ T1,(T3)		;GET UDB
	HLRZ T2,UDBLUN(P3)	;GET NUMBER OF UNITS
	CAMN T1,P3		;SAME UNIT AS THIS?
	CAME T2,SDBNUM(Q1)	;SAME TOTAL NUMBER?
	JRST CHK20		;NO TO EITHER
CHK9:	MOVX T1,U1.STC		;STATUS CHANGED
	TDNE T1,UDBST1(P3)	;DURING HOMEBLOCK CHECK?
	JRST CHK10		;YES DON'T CHANGE CHECK FLAG SO WE DO IT AGAIN....
	MOVX T1,US.OMS		;SEEMS TO MATCH, PREVENT ANY
	IORM T1,UDBSTS(P3)	;DEADLOCK
	MOVX T1,US.CHB		;NO LONGER NEED CHECKING, ALLOW I/O
	ANDCAB T1,UDBSTS(P3)	; ...
	TXNN T1,US.CIP		;CI DISK?
	JRST CHK10			;NO, CARRY ON
	SETOM QUEREQ		;YES. TELL MSCP DRIVER TO RESTART A DISK
	HRRZ P1,UDBCDB(P3)
	SETOM CDBQRQ(P1)	;ON THIS CHANNEL
	MOVX T1,US.OIR!US.OMS	;TURN OF MESSAGES
	ANDCAM T1,UDBSTS(P3)
CHK10:	IOPION
	RET			;AND DO USUAL TIMER THING
;HERE WHEN WE READ A GOOD HOME BLOCK WHICH DOESN'T MATCH WHAT SHOULD HAVE BEEN READ
;CHECK ALL UDBS IN SYSTEM, SEARCHING FOR A MATCH
;IF WE FIND A MATCH, THE OPERATOR HAS MOVED THE UNIT
; FROM WHERE IT WAS TO WHERE WE JUST FOUND IT
CHK11:	MOVSI P4,-STRN		;SET TO LOOP OVER ALL STRS
	SAVEAC <P1>		;SAVE DESTROYED P1 REGISTER
CHK12:	SKIPN P5,STRTAB(P4)	;GET NEXT STR
	JRST CHK19		;THIS ONE ISNT THERE
	CAMN T1,SDBNAM(P5)	;NAMES MATCH?
	CAME T2,SDBPUC(P5)	;AND SAME CODE?
	JRST CHK19		;NO, TEST NEXT STR
	ADDI T3,SDBUDB(P5)	;YES, POINT AT RIGHT UDB
	HLRZ T2,UDBLUN(P3)	;GET TOTAL NUMBER OF PACKS IN STR
	HRRZ T1,(T3)		;POINT T1 AT UDB
	CAME T2,SDBNUM(P5)	;YES. RIGHT NUMBER OF UNITS?
	JRST CHK20		;NO. WRONG UNIT POWERED UP. COMPLAIN

;THE PACK WHICH WAS FORMERLY ON THE T1-UDB HAS SPUN UP ON THE P3-UDB
	MOVSI T2,-MOVTLN	;NUMBER OF ITEMS TO SWITCH BETWEEN UDBS
CHK13:	MOVE T3,@MOVTAB(T2)	;GET AN ITEM FROM ONE UDB
	EXCH T1,P3
	EXCH T3,@MOVTAB(T2)	;AND SAVE IT IN THE OTHER UDB
	EXCH T1,P3
	MOVEM T3,@MOVTAB(T2)	;EXCHANGE THE DATA FROM OTHER UDB
	AOBJN T2,CHK13		;KEEP GOING FOR ALL ITEMS
	MOVE T2,UDBSTS(P3)
	TXNE T2,US.CIP		;CI DISK?
	JRST CHK15
CHK13A:	MOVSI T2,-MOVQLN	;NUMBER OF QUEUES TO SWITCH BETWEEN UDBS
CHK14:	MOVE T3,@MOVTQ1(T2)	;QUEUE HEADER
	TRNN T3,-1		;EMPTY?
	MOVSI T3,@MOVTQ2(T2)	;YES, INITIALIZE
	MOVE T4,@MOVTQ2(T2)	;OTHER UDBS QUEUE
	TRNN T4,-1		;EMPTY?
	MOVSI T4,@MOVTQ1(T2)	;YES
	MOVEM T3,@MOVTQ2(T2)	;RESTORE UDBS
	MOVEM T4,@MOVTQ1(T2)
	AOBJN T2,CHK14		;KEEP ON FOR ALL QUEUES
CHK15:	MOVX T4,US.TPD		;CHECK FOR TPD
	TDNE T4,UDBSTS(P3)	;IS IT SET?
	JRST CHK17A
	HRRZ T3,UDBLUN(P3)	;UNIT NUMBER WITHIN STR
	HRRZ T2,UDBSTR(P3)	;STR NUMBER
	HRRZ T2,STRTAB(T2)	;STR DATA BLOCK
	ADD T2,T3		;SDBUDB SLOT FOR THIS UNIT
	SKIPGE T3,UDBSTR(T1)	;STR NUMBER FOR THIS UNIT
	JRST CHK16		;GO IF IT WASNT IN A STR
	HRRZS T3,		;MASK OFF UNIT NUMBER
	MOVE T3,STRTAB(T3)	;STR DATA BLOCK
	HRLI T3,-MXSTRU		;SET TO SEARCH SDBUDB
	HRRZ T4,SDBUDB(T3)	;UDB
	CAIE T4,(P3)		;RIGHT?
	AOBJN T3,.-2		;NO, TRY NEXT
	JUMPGE T3,CHK16		;NO MATCH IF T3 POSITIVE (SHOULDN'T HAPPEN)
	HRRM T1,SDBUDB(T3)	;SAVE UDB IN SDB
CHK16:	HRRM P3,SDBUDB(T2)	;SAVE OTHER UDB IN ITS SDB
CHK17A:
	MOVE T2,UDBSTS(T1)
	TXNN T2,US.CIP		;CI DISK?
	JRST CHK17		;NO
	TXZ T2,US.OMS		;YES. DON'T BUG THE OPERATOR ABOUT THE OLD DRIVE
	MOVEM T2,UDBSTS(T1)
	MOVE T3,UDBSTS(P3)	;IS THIS A CI DISK TOO?
	TXNN T3,US.CIP
	JRST CHK17		;NO FORGET IT TRY IT THE OTHER WAY
	CALL TW2PWQ		;RESET QUEUE'S FOR CI DISKS
	JRST CHK18		;KEEP ON GOING
CHK17:	MOVX T2,US.POS!US.ACT!US.BAT!US.BLK!US.PRQ
	MOVE T3,UDBSTS(T1)	;GET PACK-RELATED STATUS BITS
	AND T3,T2		; FROM 1 UDB
	ANDCAM T2,UDBSTS(T1)	;AND SWITCH THEM WITH BITS FROM THE OTHER UDB
	MOVE T4,UDBSTS(P3)
	AND T4,T2
	ANDCAM T2,UDBSTS(P3)	;LEAVING DRIVE-RELATED BITS ALONE
	IORM T3,UDBSTS(P3)
	IORM T4,UDBSTS(T1)
CHK18:	MOVE P1,T1		;SAVE OLD UDB
	MOVX T1,US.TPD		;CHECK FOR THREE PORT
	TDNE T1,UDBSTS(P3)	;IS IT?
	JRST CHK99		;YES FORGET IT
;   IFN CFSCOD,<
	MOVE T1,P3		;NEW UDB
	MOVE T2,P1		;OLD UDB
	CALL CFRDSN		;TELL CFS THE PACK HAS SWITCHED
;   >	;IFN CFSCOD
CHK99:	HRROI T1,[ASCIZ /
%Unit switched on device: /]
	CALL UNIMES		;TELL OPR ABOUT THE SWITCH
	SKIPGE UDBSTR(P1)	;WAS OTHER UNIT IN A STR?
	JRST CHK9		;NO, FINISH UP
	EXCH P1,P3		;YES, POINT AT OTHER UDB
	HRROI T1,[ASCIZ /	with: /]
	CALL UNIMES		;TELL OPR THAT WE SWITCHED THIS ONE TOO
	EXCH P1,P3		;RESET P3
	JRST CHK9		;CLEAN UP AND EXIT
CHK19:	AOBJN P4,CHK12		;TRY NEXT STR
				;FALL INTO CHK20 AND COMPLAIN
;HERE WHEN THE HOME BLOCK MISCOMPARES OR IS ILL FORMED
				;PREVIOUS PAGE FALLS INTO THIS
CHK20:	JUMPE Q1,CHK23		;GO IF NO LONGER IN A STR
	HRROI T1,[ASCIZ /
%Wrong pack on device:/]	;SLIGHTLY MISLEADING MESSAGE
	JRST CHK22		;TYPE MESSAGE AND CONTINUE

;HERE WHEN AN IO ERROR OCCURS READING A HOME BLOCK

CHK21:	TXNN T1,IS.DVE!IS.DTE	;CHECK FOR REAL ERRORS OR JUST QUITTING
	JRST CHK10		;NOT REAL ERRORS JUST TERMINATION OF IORB (ABNORMAL)
	HRROI T1,[ASCIZ /
%Error reading HOME block on device:/]
CHK22:	CALL UNIMES		;APPEND STOCK TRAILER
	MOVX T1,US.OFS		;SET DRIVE OFF-LINE UNTIL NEW PACK IS SPUN UP
	IORM T1,UDBSTS(P3)	; AT WHICH TIME WE'LL CHECK AGAIN
	MOVX T1,U1.PHB		;SET PRIMARY HOMEBLOCK BAD
	IORM T1,UDBST1(P3)

;HERE WHEN UNIT CHANGED STRUCTURE STATUS (FORCE REMOVAL?)

CHK23:	MOVX T1,U1.STC		;IS IT STATUS CHANGE?
	TDNE T1,UDBST1(P3)
	JRST CHK10		;YES TRY AGAIN
	MOVX T1,US.CHB		;CLEAR CHECK HOME BLOCK BIT
	ANDCAM T1,UDBSTS(P3)	; ...
	JRST CHK10		;AND DO NORMAL CHECKS


;TABLES TO DRIVE MOVING OF PACKS
MOVTAB:	IFIW!UDBERR(T1)
	IFIW!UDBERP(T1)
	IFIW!UDBVID(T1)
	IFIW!UDBSTR(T1)
	IFIW!UDBONR(T1)
	IFIW!UDBPNM(T1)
	IFIW!UDBUDR(T1)
MOVTLN==.-MOVTAB

MOVTQ1:	IFIW!UDBPWQ(T1)
	IFIW!UDBTWQ(T1)
MOVTQ2:	IFIW!UDBPWQ(P3)
	IFIW!UDBTWQ(P3)
MOVQLN==.-MOVTQ2

;HERE  FOR  EACH  UNIT.  CHECK  IF OPERATOR MESSAGE NEEDED OR RESTART
;NEEDED. IF UNIT IS ACTIVE, CHECK OVERDUE TIMER AND  RESET  IF  HUNG.
;SEE  IF THE CONTROLLER FOR THE UNIT NEEDS TO BE RESTARTED. PRESERVES
;Q1 AND Q3

UNICHK:	TRNE P2,-1		;IS THERE A CONTROLLER?
	SKIPE PHYSEC		;AND IS THIS A MINUTE BOUNDARY?
	JRST UNICK1		;NO, SKIP ON
	HRRZ T1,KDBDSP(P2)	;GET DISPATCH ADDRESS
	TLON P2,-1		;CHECK IF FIRST TIME FOR THIS CONTROLLER
	CALL UDSCCK(T1)		;YES, CHECK IT OUT THEN
	MOVE T1,UDBSTS(P3)	;GET THE STATUS WORD FOR THIS UNIT
	TXNE T1,US.TAP		;IF NOT TAPE GO TO DISK STUFF
	TXNN T1,US.REW		;IS THE UNIT REWINDING?
	JRST UNICK1		;NO. THEN JUST CONTINUE ON.
	TXNN T1,US.OR1		;YES. HAS IT BEEN REWINDING FOR 2 MINUTES?
	JRST UNICH1		;NO. GO INCREMENT THE TIMING FIELD.
	MOVX T1,US.REW!US.ORC	;YES. GET THE REWIND BITS.
	ANDCAM T1,UDBSTS(P3)	;RESET THE REWIND BITS.
	MOVX T1,US.BOT!US.OIR	;GET THE BOT AND OIR BITS.
	IORM T1,UDBSTS(P3)	;SET STATUS 
	JRST UNICK1		;AND NOW CONTINUE ON.
UNICH1:	MOVX T1,US.OR2		;HERE TO INCREMENT THE REWIND FIELD.
	ADDM T1,UDBSTS(P3)	;INCREMENT THE REWIND FIELD.

UNICK1:	MOVE T1,UDBSTS(P3)	;GET STATUS FOR CHECKING
	TXNE T1,US.TPD		;CHECK FOR THREE PORTED DISK
	RET			;QUIT NOTHING WE WANT TO DO WITH THIS UNIT
	TXNE T1,US.MAI		;UNIT IN MAINTENENCE MODE?
	JRST UNICK8		;YES, DISABLE USUAL CHECKS
	TXNE T1,US.MRQ		;MAINTENENCE MODE REQUESTED?
	JRST UNICK9		;YES, CHECK IF NOW ALLOWED
	TXNE T1,US.CHB		;DOES THIS UNIT NEED ITS HOME BLOCKS CHECKED?
	JRST UNIC10		;YES, SEE WHAT CAN BE DONE
	TXNE T1,US.PSI		;PSI REQUESTED?
	CALL UNIPSI		;YES, INIT PSI SEQUENCE
UNICK2:	IOPIOF			;Prevent state changes
	MOVX T1,US.OIR		;OPER INTERVENTION REQUEST?
	TDNN T1,UDBSTS(P3)	; ??
	JRST UNICK5		;NO - TRY OTHER CASES
	ANDCAM T1,UDBSTS(P3)	;YES - RESET BIT
	CALL UNITRY		;ATTEMPT TO RESTART IO
	 SKIPA			;ATTEMPT FAILED OR INDETERMINATE
	JRST UNIOK		;SUCCESS.
	MOVX T1,US.OMS		;OPERATOR MESSAGE ON MINUTE?
	TDNE T1,UDBSTS(P3)	; ??
	JRST UNICK4		;YES - CHECK FOR MINUTE
	IORM T1,UDBSTS(P3)	;NO - REQUEST IT AND PRINT MESSAGE NOW
UNICK3:	IOPION
	MOVX T1,U1.PDR!U1.PDW!U1.HBR ;CHECK FOR HOMEBLOCK PROCESS
	TDNE T1,UDBST1(P3)	;NO ERROR IF THESE ARE IN PROGRESS
	RET
	HRROI T1,[ASCIZ/
%Write-locked drive: /]		;GET POSSIBLE MESSAGE
	MOVE T2,UDBSTS(P3)	;GET UNIT STATUS
	TXNN T2,US.OFS!US.CHB!US.MAI!US.MRQ!US.TAP	;OFF-LINE OR A TAPE?
	TXNN T2,US.WLK		;OR NOT WRITE-LOCKED?
	HRROI T1,[ASCIZ /
%Problem on device: /]		;YES, GET STANDARD MESSAGE INSTEAD
	MOVE T2,UDBST1(P3)	;CHECK FOR FORCED OFFLINE
	TXNN T2,U1.OFS
	CALLRET UNIMES		;TYPE THE MESSAGE AND QUIT
	HRROI T1,[ASCIZ /
%Drive forced offline because a running system hasn't joined cluster:/]	;yup
	CALLRET UNIMES		;TYPE THE MESSAGE AND QUIT

;Here for once-a-minue check. IOPIOF!

UNICK4:	LOAD T1,US.RTY,UDBSTS(P3) ;Get error retry count
	CAIGE T1,MSGLIM		;At max count?
	IFNSK.			;If not
	 ADDI T1,1		;Increase it
	 STOR T1,US.RTY,UDBSTS(P3)
	 CALLRET ONRET
	ENDIF.
	SKIPN PHYSEC		;Minute boundary?
	JRST UNICK3		;YES - PRINT MESSAGE
	CALLRET ONRET

;Here to see if some form fo operator assitance needed. IOPIOF!

UNICK5:	MOVX T1,US.OMS		;OPERATOR MESSAGE ON MINUTE?
	TDNN T1,UDBSTS(P3)	; ??
	IFNSK.			;If not
	 IOPION			;Enable interrupts again
	 JRST UNICKT		; CHECK TIMEOUT	 
	ENDIF.
	CALL UNITRY		;DO RETRY
	 JRST UNICK4		;FAILED - DO RETRY	
UNIOK:	MOVX T1,US.OMS!US.RTY	;SUCCESS, CLEAR MESSAGE BIT and retry
	ANDCAM T1,UDBSTS(P3)	; ...
	CALLRET ONRET		;DOne

UNIPSI:	MOVX T1,US.PSI		;GET PSI BIT
	ANDCAB T1,UDBSTS(P3)	;CLEAR BIT AND GET STATUS BITS
	TXNN T1,US.TAP		;IS THIS A TAPE?
	JRST UNIDPS		;NO -- HANDLE DISK ONLINE/OFFLINE
	MOVEI T3,MTCUTB		;LOOK THRU TABLE AND FIND CORRECT UNIT
	SETZ T4,0		;COUNT OF MTA'S
UNIPS2:	HRRZ T1,0(T3)		;GET UDB ADDRESS
	CAIN P3,0(T1)		;THIS UNIT?
	JRST UNIPSF		;YES SEE IF PSI NECESSARY
	AOS T4			;NEXT UNIT
	CAIGE T4,MTAN		;CHECK FOR ALL DONE
	AOJA T3,UNIPS2
	RET			;NO MORE QUIT

UNIPSF:	HRRZ T1,MTPSFK(T4)	;GET PSI CHANNEL
	HLRZ T2,MTPSFK(T4)	;GET FORK
	JUMPE T2,R		;QUIT IF NOT INITALIZED
	EA.ENT			;MUST BE IN SECTION 1 !
	CALLRET	PSIRQ		;REQUEST PSI

UNIDPS:	HRRZ T1,DSPSFK		;GET DISK PSI REQUEST
	HLRZ T2,DSPSFK		;GET FORK
	JUMPE T2,R		;IF NONE THIS IS NOT LEGAL
	EA.ENT 			;MUST BE IN SECTION 1 !
	CALLRET PSIRQ		;REQUEST PSI
;HERE TO CHECK TIMER


UNICKT:	MOVX T1,US.ACT		;UNIT NOW ACTIVE?
	TDNN T1,UDBSTS(P3)	; ??
	RET			;NO - ALL DONE
	SKIPLE T2,UDB2ND(P3)	;DUAL PORTED?
	TDNN T1,UDBSTS(T2)	;YES, IS IT THE ALTERNATE PATH THAT'S ACTIVE?
	SKIPA T1,UDBODT(P3)	;NO, CHECK OVERDUE TIME
	RET			;THE OTHER UDB IS THE ACTIVE ONE - LEAVE THIS PORT ALONE
	CAML T1,TODCLK		;AGAINST PRESENT TIME
	RET			;NOT OVERDUE
	SAVEQ			;OVERDUE - SAVE Q ACCUMULATORS
	MOVX Q1,US.ACT		;PREPARE FOR PIOFF TESTS
	IOPIOF			;INTERLOCK AGAINST RACE
	MOVE T1,UDBODT(P3)	;GET OVERDUE TIME AGAIN
	CAMGE T1,TODCLK		;CHECK STILL OVERDUE
	TDON Q1,UDBSTS(P3)	;AND STILL ACTIVE (WHILE GETTING STATUS)
	JRST ONRET		;NOT BOTH - LOST RACE, USER WON.
	HRRZ T4,UDBERR(P3)	;GET FUNCTION CODE IF IN ERROR RECOVERY
	JUMPN T4,UNIOV0		;PROCEED IF NONZERO
	TXNE Q1,US.CIP		;CI DISK?
	JRST [MOVEI T1,^D10000	;RESET TIMER
	      ADDM T1,UDBODT(P3)
	      JRST ONRET]	;AND IGNORE THE CI DISK IT'LL BE BACK
	CALL SETIRB		;IF NOT, FIND IORB
	MOVEI T4,IRFSEK		;ASSUME DOING A SEEK
	TXNN Q1,US.TAP		;DEVICE A TAPE?
	TXNN Q1,US.POS		;OR OPERATION IS A TRANSFER?
	LDB T4,IRYFCN		;YES, GET FUNCTION FROM IORB INSTEAD
UNIOV0:	CALL FNDCKU		;FIND CHANNEL, CONTROLLER, AND UNIT NUMBERS
	BUG.(INF,OVRDTA,PHYSIO,HARD,<PHYSIO - Overdue transfer aborted>,<<T1,CHAN>,<T2,CONTRL>,<T3,UNIT>,<T4,FUNC>>,<

Cause:	The routine UNICKT checks the status of each unit periodically.  During
	one such check, some unit had an active IORB which timed out.  The I/O
	operation had been started, but not completed within 17 seconds.  This
	BUGINF can be followed by other BUGINFs or BUGCHKs when the device
	finally responds (such as PH2DNA).

Action:	If the involved device is a tape drive controlled by a DX20, a
	common cause of the BUGINF is the microcode halting.  Reloading
	the microcode will fix the problem.  Other causes are hardware
	failures, and Field Service should examine the problem.

Data:	CHAN - The channel number
	CONTRL - The controller number (-1 if no controller)
	UNIT - The unit number
	FUNC - The operation that failed

>)	;COMPLAIN
	TXNE Q1,US.POS		;CHECK SEEK OR TRANSFER THAT LOST
	CALL OFFPWQ		;WAS SEEK, PULL IORB
	TXNN Q1,US.POS		;WELL?
	CALL OFFTWQ		;WAS TRANSFER, PULL IORB
	CALL HNGIRB		;TERMINATE HUNG IORB AND RESTART CHAN
ONRET:	SKIPN PHYIFL		;SHOULD WE TURN ON INTS?
	IOPION			;YES, AT LONG LAST
	SETZM PHYIFL		;USUALLY WE DON'T WANT TO
	RET

UNICK8:	IOPIOF			;INTERLOCK CHECK
	MOVE T1,UDBODT(P3)	;CHECK OVERDUE TIME
	JUMPE T1,ONRET		;UNTIMED
	CAML T1,TODCLK		;CHECK AGAINST NOW
	JRST ONRET		;STILL OK
	MOVE T1,UDBONR(P3)	;GET OWNING FORK
	IOPION
	EA.ENT			;MUST BE IN SECTION 1 !
	LOAD T1,FKJO%,(T1)	;GET JOB
	CALL ELOGOO		;LOGOUT OUT THAT JOB
	RET

UNICK9:	MOVX T1,US.ACT		;CHECK IF UNIT STILL ACTIVE
	TDNE T1,UDBSTS(P3)	; ??
	JRST UNICK2		;YES - PERFORM USUAL CHECKS
	MOVX T1,US.MAI		;NO, SET IT INTO MAINTENENCE MODE
	IORM T1,UDBSTS(P3)	; ...
	RET			;AND CONTINUE SCAN

;TABLES FOR HOME BLOCK CHECKING
HBCNT=HBLEN-1		;WE ONLY TRANSFER 177 WORDS SINCE LAST WORD OF HB IS UNNECESSARY
;HERE WHEN A UNIT NEEDS ITS HOME BLOCKS CHECKED

UNIC10:	IOPIOF			;DISABLE ITERRUPTS
	SKIPN P4,UDBCHB(P3)	;IS THIS UNIT CURRENTLY BEING CHECKED?
	JRST UNICIA		;NO MAYBE WE SHOULD
	MOVX T1,IS.ERR!IS.DON	;ANYTHING TO DO?
	TDNE T1,IRBSTS(P4)	;CHECK THE STATUS
	JRST CHK8		;MUST BE SOMETHING TO DO
	JRST UNICK2		;YES ALL OK MUST BE ACTIVE OR OFFLINE

UNICIA:	SKIPGE UDB2ND(P3)	;IS THE THE ALTERNATE PATH OF A DUAL-PORTED DRIVE?
	JRST UNIC13		;YES, DON'T BOTHER TO CHECK IT (WILL CHECK MAIN PORT)
	MOVE T1,CDBSTS(P1)	;CHECK CHANNEL FOR ACTIVE
	TXNE T1,CS.CIP		;CI?
	JRST UNIC11		;YES NO CHECK FOR ACTIVE
	MOVX T1,US.OFS!US.ACT!US.MAI	;IS THIS UNIT OFFLINE OR ACTIVE?
	TDNE T1,UDBSTS(P3)	; ???
	JRST UNIC12		;YES - CANNOT CHECK
	MOVX T2,KS.ACT		;CONTROLLER ACTIVE
	TRNE P2,-1		;NO CONTROLLER?
	TDNN T2,KDBSTS(P2)
	TXNE T1,CS.ACT		;OR CHANNEL
	JRST UNIC12		;QUIT
UNIC11:	CALL GETIRC		;GET AN IORB
	JRST UNIC12		;NONE FOND WAIT
	MOVX T1,U1.STC!U1.PHB!U1.SHB!U1.PDR!U1.PDW ;CLEAR STATUS CHANGED FLAG
	ANDCAM T1,UDBST1(P3)
	MOVX T1,U1.HBR		;SET HOME BLOCK READ
	IORM T1,UDBST1(P3)
	MOVEI T2,HM1BLK		;READ HOMEBLOCK 1
	CALL RDHBLK		;(T2,P3,P4/) READ HOMEBLOCK

UNIC12:	IOPION			;TRY OTHER PARTS OF OFFLINE STUFF
	JRST UNICK2		;COULDNT CHECK AFTERALL

;HERE WHEN A UNIT CHANGES STRUCTURE STATUS

UNIC13:	MOVX T1,US.CHB		;CLEAR CHECK HOME BLOCKS BIT
	ANDCAM T1,UDBSTS(P3)	; ...
	MOVX T1,U1.STC		;CLEAR STC TO
	ANDCAM T1,UDBST1(P3)
	IOPION
	JRST UNICK2		;AND DO USUAL CHECKS
	SUBTTL Homeblock and PDB Routines

;CHBSTR - SETS IS.ERR IF THE DRIVE HAS GONE OFFLINE.  THIS WILL CAUSE THE
;HOMEBLOCK CHECKER TO TRY AGAIN LATER.  THIS ROUTINE WILL BE CALLED FROM
;STRTIO AS THE ENTRY ROUTINE BEFORE ACTUALLY SCHEDULING THE HOMEBLOCK IORB.
; P3/ UDB
; P4/ IORB
;	CALL CHBSTR		;(P3,P4/)
; RETURN +1: ERROR BIT SET IN IORB
;        +2: READY TO TRANSFER

CHBSTR:	MOVX T1,US.OFS		;CHECK FOR OFFLINE TRANSITION
	TDNN T1,UDBSTS(P3)
	RETSKP			;NO TRY TRANSFER
	MOVX T1,IS.ERR		;SET ERROR BUT NO ERROR BITS TO TERMINATE AND TRY LATER
	IORM T1,IRBSTS(P4)
	RET			;STOP TRANSFER
;CHBDON - FIGURES OUT THE STATE OF HOMEBLOCK CHECKING AND INITIATES THE
;NEXT STEP.  CHBDON IS CALLED BY DONIRB AS THE EXIT ROUTINE FOR THE HOMEBLOCK
;IORB. THIS ALLOWS US TO PROCESS THE COMPLETED IORB BEFORE THE POLLER CAN SEE
;THE COMPLETED REQUEST.  THIS WILL NOT BE CALLED IF THE DRIVE IS OFFLINE SO
;IS.ERR IMPLIES REAL ERROR HERE.
; P1/ CDB
; P3/ UDB
; P4/ IORB
;	CALL CHBDON		;(P1,P3,P4/)
; RETURN +1:

CHBDON:	SAVEPQ
	MOVE T1,IRBSTS(P4)	;WAS THERE
	TXNE T1,IS.ERR		; AN ERROR?
	JRST CHBDER		;YES
	MOVE T1,UDBST1(P3)	;NO, GET STATUS
	TXZE T1,U1.HBR		;IS THIS HOMEBLOCK READ?
	JRST CHBPDR		;YES
	TXZE T1,U1.PDR		;NO, IS IT PDB READ?
	JRST CHBPDB		;YES
	TXZN T1,U1.PDW		;NO, IS IT PDB WRITE?
	BUG. (CHK,PDBSTA,PHYSIO,SOFT,<PHYSIO - Inconsistent state of UDB status bits>,<<T1,STATUS>>,<

Cause:	UDBST1 is inconsistent.

Data:	STATUS - UDB status bits
>)
	MOVEM T1,UDBST1(P3)	;YES, CLEAR THE BIT AND DO CHECK AGAIN
	CALL GIVIRB		;(P4/) RETURN IORB
	SETZM UDBCHB(P3)	;CLEAR HOMEBLOCK IORB FOR THIS DISK
	RET			;WAIT FOR NEXT CALL

;HERE ON ERROR DURING HOMEBLOCK READ

CHBDER:	TXNN T1,IS.DTE!IS.DVE	;HARD ERRORS
	RET			;NO OFFLINE
	MOVE T2,UDBST1(P3)	;GET THE STATUS
	TXZN T2,U1.HBR		;HOME BLOCK READ?
	RET			;NOT HOME BLOCK ERROR
	TXOE T2,U1.PHB		;PRIMARY HOME BLOCK ERROR SET?
	JRST [	TXO T2,U1.SHB		;SET SECONDARY HOME BLOCK ERROR
		MOVEM T2,UDBST1(P3)
		RET]			;AND RETURN FOR LATER TRIES
	TXO T2,U1.PHB!U1.HBR	 ;SET PRIMARY HOME BLOCK ERROR
	MOVEM T2,UDBST1(P3)	;SET PRIMARY HOME BLOCK ERROR FLAG
	MOVX T2,HM2BLK		;HOMEBLOCK 2
	CALLRET RDHBLK		;READ THE HOMEBLOCK

CHBPDR:	TXO T1,U1.PDR		;SET PDR BIT
	MOVEM T1,UDBST1(P3)
	CALLRET RDPDB		;AND READ NEW PDB

CHBPDB:	MOVEM T1,UDBST1(P3)	;STORE UDB STATUS
	CALL CHKPDB		;IS THE STATUS ON THE DISK OK?
	 CALL WRTPDB		;NO RESET IT AND TRY AGAIN
	RET			;QUIT
;CHBCWB - BUILD CCW FOR THE HOMEBLOCK REQUEST
; P3/ UDB
; P4/ IORB
;	CALL CHBCWB		;(P3,P4/)
; RETURN +1

CHBCWB:	SAVEQ
	SETZ Q2,0		;COUNTER
	XMOVEI Q1,IRBCCW(P4)	;ADDRESS OF PLACE TO STORE CCW'S
	HRLZI Q3,1		;AMOUNT TO UPDATE IRBXFL
CHBBAK:	CALL CHBLOP		;(P3/) ADD AN ENTRY
	ADDM Q3,IRBXFL(P4)	;UPDATE COUNT OF CCW'S STORED
	AOS Q2			;UPDATE POINTER
	CAIGE Q2,HOMISZ
	AOJA Q1,CHBBAK
	RET


CHBLOP:	MOVEI T1,@HOMLIZ(Q2)	;GET SIZE OF THIS REQUEST
	HRLI T1,IRMWRD		;SET WORD MODE
	MOVE T2,HOMADR(Q2)	;MOVERESS TO TRANSFER TO
	CAIE T2,HOMSKP
	ADDI T2,(P3)		;ADD IN UDB OFFSET
	MAP T2,(T2)		;FIND REAL ADDRESS
	TLZ T2,777760		;MASK JUNK
CHBSKP:	HRRZ T3,CDBDSP(P1)	;CHANNEL DISPATCH
	CALL CDSCCW(T3)		;(T1,T2/T1) GO BUILD CCW
	MOVEM T1,0(Q1)		;SAVE CCW
	RET


HOMLIZ:	HOMLUN-HOMNAM+1		;FIRST FEW WORDS OF HOME BLOCK
	HOMMID-HOMLUN-1		;SKIPPED WORDS
	HOMDCF-HOMMID+1		;HOM MID AND DON'T CARE
	HOMCOD-HOMDCF-1
	HOMCOD-HOMCOD+1
HOMISZ=.-HOMLIZ


HOMADR:	UDBNAM			;ADDRESS OF FIRST WORD TO TRANSFER
	HOMSKP			;SKIP ADDRESS
	UDBMID			;UDB MID WORD
	HOMSKP			;SKIP ADDRESS
	UDBCOD			;CODE TO IDENTIFY HOME BLOCK
;RDHBLK - START HOMEBLOCK READ
; T2/ ADDRESS OF BLOCK
; P3/ UDB
; P4/ IORB
;	CALL RDHBLK		;(T2,P3,P4/)
; RETURN +1

RDHBLK:	SETZM IRBSTS(P4)	;CLEAR STATUS
	MOVEI T1,IRFRED		;GET READ FUNCTION CODE
	DPB T1,IRYFCN		;STORE IN IORB
	MOVEI T1,IRMWRD		;GET WORD MODE
	DPB T1,IRYMOD		;STORE IN IORB
	MOVX T1,IS.IEL		;INHIBIT ERROR LOGGING
	IORM T1,IRBSTS(P4)	; ...
	MOVEI T1,HBCNT		;SETUP COUNT
	HRRZM T1,IRBCNT(P4)	; ...
	HRRI T1,IRBCCW(P4)	;SET UP CHANNEL ADDRESS
	HRLI T1,IRBCCW(P4)	; SET ENDING ADDRESS
	MOVEM T1,IRBXFL(P4)	;STORE IN IORB
	TXO T2,IRBPAD		;SET PHYSICAL ADDRESS REQUEST
	MOVEM T2,IRBADR(P4)	;STORE ADDRESS DECIDED UPON
	MOVE T1,[CHBSTR,,CHBDON] ;INTERRUPT ROUTINE
	MOVEM T1,IRBIVA(P4)	; STORE IN IORB
	CALL CHBCWB		;(P3,P4/) BUILD CCW'S
	MOVEM P4,UDBCHB(P3)	;STORE SPECIAL IORB IN UDB
STRHBT:	SETOM PHYIFL		;DON'T TURN INTERRUPTS BACK ON
	SAVEQ			;SAVE Q REGISTERS FOR DGUMAP
	CALLRET SIO2		;(P3/) START THE I/O
;RDPDB - READ A PDB FROM DISK INTO THE UDB
; P3/ UDB
; P4/ IORB
;	CALL RDPDB		;(P3,P4/)
; RETURN +1

RDPDB:	SETZM IRBSTS(P4)	;ZERO STATUS
	MOVEI T1,IRFRED		;SET READ FUNCTION
	DPB T1,IRYFCN		;STORE IN IORB
	MOVEI T1,IRMWRD		;SET WORD MODE
	DPB T1,IRYMOD
	MOVX T1,IS.IEL		;INHIBIT ERROR LOGGING
	IORM T1,IRBSTS(P4)
	MOVEI T1,PDBLEN		;GET LENGTH OF REQUEST
	MOVEM T1,IRBCNT(P4)
	HRRI T1,IRBCCW(P4)
	HRLI T1,IRBCCW+1(P4)	;CCW POINTERS
	MOVEM T1,IRBXFL(P4)	;STORE IN IORB
	MOVEI T2,PDBBLK		;SET BLOCK OF PDB
	TXO T2,IRBPAD		;SET PHYSICAL ADDRESS
	MOVEM T2,IRBADR(P4)	;SET IN IORB ADDRESS
	MOVE T1,[CHBSTR,,CHBDON] ;SET START/STOP ADDRESS
	MOVEM T1,IRBIVA(P4)
	MOVEI T1,PDBLEN		;LENGTH OF REQUEST
	HRLI T1,IRMWRD		;SET WORD MODE
	XMOVEI T2,UDBPDB(P3)	;ADDRESS OF PDB
	MAP T2,(T2)		;FIND REAL ADDRESS
	TLZ T2,777760		;MASK JUNK
	HRRZ T3,CDBDSP(P1)	;GET CHANNEL DISPATCH
	CALL CDSCCW(T3)		;(P3,P4/) CONVERT CCW
	MOVEM T1,IRBCCW(P4)	;STORE CCW
	JRST STRHBT		;(P3/) START TRANSFER
;CHKPDB - CHECK THE CURRENT STATE OF THE UDB'S PDB.  IF IT DIFFERS FROM
;REALITY, WE MUST FIX IT, WRITE IT BACK TO THE DISK, AND START ALL OVER.
; P3/ UDB
;	CALL CHKPDB		;(T1,P3/)
; RETURN +1: NEED TO WRITE PDB TO DISK (THIS CAUSES US TO READ IT AGAIN)
;	 +2: ALL OK, NO RE-WRITE NECESSARY

CHKPDB:	DMOVE T1,UDBSER(P3)	;GET THE SERIAL NUMBER FROM THE PDB
	CAMN T2,UDBDSN(P3)	;CHECK AGAINST DRIVE SERIAL NUMBER
	CAME T1,UDBDSH(P3)	; AND SEE IF IT IS THE SAME
	IFNSK.
	   DMOVE T1,UDBDSH(P3)	;DON'T MATCH, STORE CURRENT DRIVE SERIAL NUMBER
	   DMOVEM T1,UDBPDB(P3)	; IN PDB
	   IOR T1,T2		;CHECK FOR ZERO SERIAL NUMBER
	   SKIPE T1		;IS IT ZERO?
	   CALLRET RSTPDB	;NO, RESET PDB NODE INFO
	   BUG. (CHK,PHYNOS,PHYSIO,HARD,<PHYSIO - No serial number for disk drive>,<<P1,CHAN>,<P2,CONT>,<P3,UNIT>>,<

Cause:	The serial number of the drive is missing.

Action:	Call Field Service.

Data:	CHAN - Channel number
	CONT- Controller number
	UNIT - Unit number
>)
	   MOVX T1,US.OFS	;THROW THE DRIVE OFFLINE
	   IORM T1,UDBSTS(P3)	;BYE
	   RETSKP		;DON'T RE-WRITE THE BLOCKS
	ENDIF.
	MOVX T1,U1.DCR!U1.DCD	;CLEAR DON'T-CARE
	ANDCAB T1,UDBST1(P3)	; STATUS
	MOVE T2,[SIXBIT/DONOCA/] ;GET DON'T-CARE INDICATOR
	CAMN T2,UDBDCF(P3)	;CHECK FOR DON'T-CARE FLAG ON DISK
	TXO T1,U1.DCD		;SET DON'T-CARE DISK
	MOVEM T1,UDBST1(P3)	;UPDATE STATUS
	TXNN T1,U1.DCU!U1.DCD	;ANY DON'T-CARE STATUS?
	JRST CHKPD3		;NO, ALL IS NORMAL
	TXC T1,U1.DCU!U1.DCD	;YES, IS THERE A
;...
;...
	TXNE T1,U1.DCU!U1.DCD	; DON'T-CARE MATCH?
	IFSKP.
	   MOVX T1,U1.DCR	;YES, SET DON'T-CARE
	   IORM T1,UDBST1(P3)	; ACCESS
	   BUG. (INF,PHYDCR,PHYSIO,SOFT,<PHYSIO - Disk being treated as DON'T-CARE>,<<P1,CHAN>,<P2,CONT>,<P3,UNIT>>,<

Cause:	A don't-care disk was found on a don't-care drive.

Data:	CHAN - The channel number
	CONT - The controller number or -1
	UNIT - The unit number
>)
	   RETSKP		;DON'T NEED FURTHER PDB CHECKING
	ELSE.

;We have a DON'T-CARE mismatch

	   TXNE T1,U1.DCU	;IS IT A DON'T-CARE DRIVE?
	   IFSKP.
	      BUG. (INF,PHYDCU,PHYSIO,SOFT,<PHYSIO - Do-care disk on don't-care drive>,<<P1,CHAN>,<P2,CONT>,<P3,UNIT>>,<

Cause:	A standard disk has been detected on a drive which has been declared
	DON'T-CARE.

Data:	CHAN - The channel number
	CONT - The controller number or -1
	UNIT - The unit number
>)
	   ELSE.
	      BUG. (INF,PHYDCD,PHYSIO,SOFT,<PHYSIO - Don't-care disk on do-care drive>,<<P1,CHAN>,<P2,CONT>,<P3,UNIT>>,<

Cause:	A don't-care disk has been encountered on a standard drive.

Data:	CHAN - The channel number
	CONT - The controller number or -1
	UNIT - The unit number
>)
	   ENDIF.
	ENDIF.

CHKPD3:	SKIPN FESER		;QUIT IF FE HASN'T GIVEN US SERIAL NUMBERS YET
	JRST [	SETZ T1,	;CHECK TO SEE IF WE ARE UP YET WITH CFS
		SKIPE PROFLG	;CHECK FOR USE OF SECONDARY PROTOCOL
		CALL PTHSTS	;(T1/T2) GET CI STATUS
		 RETSKP		;NO ALL OK FOR NOW
		BUG. (HLT,BADFEV,PHYSIO,SOFT,<CHKPDB - Wrong or bad front-end version>,,<

Cause:	The front-end did not send a type 40 message to idenify the
	front-end disk serial numbers.

Action: Fix the front-end.
>)]
	TXNE T1,U1.FED		;IS THIS A FE DISK?
	RETSKP			;YES DON'T RE-WRITE ANYTHING

	CALLRET UPDPDB		;CHECK PDB VALUES AND UPDATE IF NECESSARY
;RSTPDB - RESET THE UDB'S PDB LEAVING NOTHING BUT OUR OWN NODE'S STATUS AND THE
;DISK'S SERIAL NUMBER.
; P3/ UDB
;	CALL RSTPDB		;(P3/)
; RETURN +1

RSTPDB:	CALL CLRPDB		;(/) CLEAR THE PDB
	SKIPN FESER		;QUIT IF FE HASN'T GIVEN US SERIAL NUMBERS YET
	RET
	CALL GAPRID		;GET SERIAL NUMBER
	SKIPN P5,CHNTAB+7	;CI THERE?
	JRST [	HRLZM T1,UDBNPR(P3) ;NO SET PROCESSOR STATUS AND QUIT
		RET]
	MOVE T2,CDBSTS(P5)	;GET STATUS
	TXNN T2,CS.CIP		;CI TYPE CHANNNL?
	JRST [	HRLZM T1,UDBNPR(P3) ;NO SET PROCESSOR STATUS AND QUIT
		RET]
	MOVE T3,T1		;SAVE SERIAL NUMBER
	SKIPL T1,CDBNOD(P5)	;GET OUR NODE
	CALL PTHSTS		;(T1/T2) GET THE STATUS OF THE CI
	 RET			;NONE DON'T WRITE ANYTHING TILL WE EXIST
	ADD T1,P3		;ADD UDB OFFSET
	HRL T2,T3		;SET SERIAL NUMBER IN LEFT HALF
	MOVEM T2,UDBP00(T1)	;STORE STATUS
	RET
;WRTPDB - WRITE UDB'S PDB TO THE DISK
; P1/ CDB
; P3/ UDB
;	CALL WRTPDB		;(P1,P3/)
; RETURN +1

WRTPDB:	MOVE P4,UDBCHB(P3)	;GET THE ADDRESS OF THE IORB TO USE
	MOVX T1,IS.IEL		;INHIBIT ERROR LOGGING
	MOVEM T1,IRBSTS(P4)	;SET IN IORB
	MOVX T1,U1.PDW		;SET THE PDB WRITE WAIT BIT
	IORM T1,UDBST1(P3)	;SET WAITING FOR PDB
	MOVEI T1,IRFWRT		;SET WRITE FUNCTION
	DPB T1,IRYFCN		;SET IN IORB
	MOVEI T1,IRMWRD		;WORD MODE
	DPB T1,IRYMOD		;SET MODE
	HRLI T1,IRBCCW+2(P4)	;SET UP LAST WORD OF CCW FIRST IS ALREADY SETUP
	HLLM T1,IRBXFL(P4)	;STORE IN IORB
	MOVE T1,[PDBBLK!IRBPAD]	;SET PHYSICAL ADDRESS OF PDB TABLE
	MOVEM T1,IRBADR(P4)
	MOVEI T1,HBLEN		;SET LENGTH
	MOVEM T1,IRBCNT(P4)	;STORE IN IORB
	MOVEI T1,PDBLEN
	HRLI T1,IRMWRD		;SET WORD MODE
	XMOVEI T2,UDBPDB(P3)	;ADDRESS TO START XFER
	MAP T2,(T2)		;WHERE TO REALLY WRITE FROM
	TLZ T2,777760		;MASK OFF JUNK BITS
	HRRZ T3,CDBDSP(P1)	;GET THE DISPATCH ADDRESS
	CALL CDSCCW(T3)		;(P3,P4/) BUILD CCW
	MOVEM T1,IRBCCW(P4)	;STORE CCW
	MOVE T1,[IRMWRD,,HBLEN-PDBLEN]
	XMOVEI T2,HOMSKP	;WRITE JUNK
	MAP T2,(T2)
	TLZ T2,777760		;MASK OFF JUNK BITS
	HRRZ T3,CDBDSP(P1)	;GET DISPATCH ADDRESS
	CALL CDSCCW(T3)		;(P3,P4/) BUILD CCW
	MOVEM T1,IRBCCW+1(P4)	;STORE CCW
	LDB T2,USYTYP		;GET TYPE
	CAIE T2,.UTP20		;IS IT RP20?
	JRST STRHBT		;START TRANSFER
	HRLZI T1,417320		;SET CHANNEL SKIP
	MOVEM T1,IRBCCW+1(P4)
	MOVEI T1,1000		;SET UP NEW COUNT
	MOVEM T1,IRBCNT(P4)	;SET COUNT
	JRST STRHBT		;START TRANSFER
;UPDPDB - UPDATE THE UDB'S PDB WITH CURRENT STATUS
; P3/ UDB
;	CALL UPDPDB		;(P3/)
; RETURN +1: UDB'S PDB UPDATED
;	 +2: NO CHANGES MADE
;
; LOCAL AC USAGE:  Q2/ OUR CI NODE NUMBER
;		   Q3/ OUR CPU SERIAL NUBER

UPDPDB:	STKVAR <UPDAT>		;"UPDATE THE DISK" FLAG
	SETZM UPDAT		;ASSUME NOT UPDATING
	CALL GAPRID		;(/T1) GET OUR CPU SERIAL NUMBER
	MOVE Q3,T1		;PRESERVE IT
	SKIPN P5,CHNTAB+7	;CHECK FOR POSSIBLE CI
	JRST UPDNCI		;NON-CI PROCESSOR
	MOVE T3,CDBSTS(P5)	;GET THE STATUS OF THE CHANNEL
	TXNE T3,CS.CIP		;IS THIS REALLY A CI?
	IFSKP.

;We are not on a CI

UPDNCI:	   SETO Q2,		;NO, SET NODE NUMBER TO -1 (NOT ON CI)
	   MOVX T3,U1.OFS	;GET FORCED-OFFLINE INDICATOR
	   MOVEI Q1,C%SBLL-1	;CHECK FOR CI NODES
UPDNLP:	   MOVE T1,P3		;GET UDB ADDRESS
	   ADD T1,Q1		;GET NODE NUMBER TO LOOK AT
	   SKIPN T2,UDBP00(T1)	;ANYNODY THERE?
	   IFSKP.
	      TXNE T2,UDB%MA	;YES, IN MAINTENANCE MODE?
	      ANSKP.
	         MOVX T2,US.2PT		;NO, IS DISK
	         TDNN T2,UDBSTS(P3) 	; MULTI-ACCESS?
	         IFSKP.
	            IORM T3,UDBST1(P3)	;YES, FORCE DISK OFFLINE
	            JRST UPDOUT	;FINISH
	         ENDIF.
	         SETOM UPDAT		;NO, INDICATE UPDATE NEEDED
	         SETZM UDBP00(T1)	;FLUSH OLD INFORMATION
	   ENDIF.
	   SOJGE Q1,UPDNLP	;NEXT NODE
	   ANDCAM T3,UDBST1(P3)	;CLEAR FORCED-OFFLINE INDICATOR
	   JRST UPDOUT		;FINISH
	ENDIF.

;We are on a CI

	SKIPGE Q2,CDBNOD(P5)	;GET OUR NODE NUMBER
	RET			;NONE THERE, THEN NOT ABLE TO USE CI YET
	MOVE T4,Q2		;GET THE NODE NUMBER
	ADD T4,P3		;FIND THE OFFSET INTO THE UDB
	HLRZ T3,UDBP00(T4)	;GET THE PREVIOUS SERIAL NUMBER
;...
;...
	CAMN T3,Q3		;ARE THEY THE SAME?
	IFSKP.
	   MOVE T1,Q2		;NO, THEN WE MUST RE-WRITE SINCE DISK WAS MOVED
	   CALL PTHSTS		;(T1/T2) GET STATUS
	    SETO T2,		;NO CI
	   HRL T2,Q3		;FIX UP SERIAL NUMBER
	   MOVEM T2,UDBP00(T4) 	;SET IN UDB
	   SETOM UPDAT		;FLAG MUST RE-WRITE
	   JRST UPDDID		;FLAG DISK OFFLINE FOR NOW
	ENDIF.
	MOVX T1,U1.OFS		;CLEAR FORCED-FFLINE
	ANDCAM T1,UDBST1(P3)	; STATUS
	MOVEI Q1,C%SBLL-1	;LOOP THRU ALL NODES
UPDLOP:	CAMN Q1,Q2		;CHECK FOR OUR NODE
	JRST UPDEND		;IT'S US
	MOVE T1,Q1		;GET NODE NUMBER
	CALL PTHSTS		;(T1/T2) GET REQUEST-ID STATUS
	 JRST UPDDID		;DECLARE OFFLINE SINCE CI NOT RUNNING
	TXNN T2,UDB%WA+UDB%WB	;NODE ANSWERING REQUEST-IDS?
	JRST UPDEND		;NO, MOVE ON
	TXNE T2,UDB%MA		;YES, NODE IN MAINTENANCE MODE?
	JRST UPDEND		;YES, MOVE ON
	ADD T1,P3		;NO, POINT TO UDB
	HRRZ T4,UDBP00(T1)	;GET WIRE STATUS FROM PDB
	TXNN T4,UDB%WA+UDB%WB	;NODE ANSWERING REQUEST-IDS?
	JRST UPDEND		;NO, MOVE ON
	TXNE T4,UDB%MA		;YES, NODE IN MAINTENANCE MODE?
	JRST UPDEND		;YES, MOVE ON
	SKIPE CFSSTS(Q1)	;IS THERE A CFS CONNECTION?
	IFSKP.
	   MOVE T2,Q1		;NO, SET UP REMOTE NODE NUMBER
	   CALL ISIT20		;(T2/) IS REMOTE SYSTEM TOPS-20?
	   IFNSK.
	      SETZM UDBP00(T1)	;NO, CLEAR OLD DATA
	      SETOM UPDAT	;INDICATE WE MUST UPDATE DISK'S PDB
	   ELSE.
	    JRST UPDDID		;YES, DECLARE DISK OFFLINE - SOMETHING IS WRONG
	   ENDIF.
	ENDIF.
UPDEND:	SOJGE Q1,UPDLOP		;TRY NEXT NODE
	MOVX T3,U1.OFS		;CLEAR
	ANDCAM T3,UDBST1(P3)	; FORCED-OFFLINE
	SETZ T3,		;INDICATE NOT SETTING OFFLINE
	JRST UPDDI1		;MOVE ON

UPDDID:	MOVX T3,U1.OFS		;FORCE DISK OFFLINE
	IORM T3,UDBST1(P3)	;SET CURRENT STATUS
UPDDI1:	MOVX T1,US.2PT
;...
;...
	TDNE T1,UDBSTS(P3)	;IS DISK MULTI-ACCESS?
	IFSKP.
	   SKIPN T3		;NO, ARE WE OFFLINING?
	   ANSKP.
	      MOVE T1,Q2	;YES, GET OUR NODE NUMBER
	      ADD T1,P3		;GET OUR
	      MOVE T3,UDBP00(T1) ; STATUS
	      CALL CLRPDB	;(/) CLEAR ALL NODES' ENTRIES
	      MOVEM T3,UDBP00(T1) ;RESET OUR STATUS
	      SETOM UPDAT	;INDICATE RE-WRITE NEEDED
	ENDIF.
	SKIPL T1,Q2		;GET OUR NODE NUMBER
	CALL PTHSTS		;(T1/T2) GET THE PATH STATUS
UPDOUT:	 SETO T2,		;NO CI
	HRL T2,Q3		;GET CPU SERIAL NUMBER
	ADD Q2,P3		;GET UDB OFFSET
	CAMN T2,UDBP00(Q2)	;OUR NODE INFO OK?
	IFSKP.
	   MOVEM T2,UDBP00(Q2) ;NO, FIX IT
	   RET			;AND QUIT
	ENDIF.
	SKIPE UPDAT		;CHECK FOR RE-WRITE
	RET			;REWRITE NECESSARY
	RETSKP			;NO-REWRITE THE DISK

	ENDSV.
;CLRPDB - CLEAR ALL NODES' ENTRIES IN THE UDB'S PDB
;	CALL CLRNDS		;(/)
; RETURN +1
; PRESERVES ALL ACS

CLRPDB:	SAVEAC <T1>
	MOVSI T1,UDBNPR(P3)	;ZERO OUT TABLE
	HRRI T1,UDBNPR+1(P3)
	SETZM UDBNPR(P3)	;ZERO FIRST WORD
	BLT T1,UDBP15(P3)
	RET
;PHYSTC - CALLED BY PHYKLP WHEN A WIRE STATUS CHANGE OCCURS OR THE CI U-CODE
;IS STARTED
;	CALL PHYSTC		;(/)
;RETURNS:	+1

PHYSTC::SAVEPQ			;SAVE A FEW REGISTERS
	SAVET			;T'S SO NOTHING IS LOST
	MOVX P5,US.CHB		;SET A FEW REGISTERS BEFORE LOOP
	MOVX P4,US.2PT		;CHECK ONLY TWO PORTED DISKS
	MOVX Q2,US.TAP		;SET TAPE REGISTER
	MOVEI Q1,CHNTAB		;POINTER TO CHANNEL TABLE
PHYSTL:	CAILE Q1,CHNTAB+7	;END OF CHANNEL TABLE?
	RET			;ALL DONE QUIT
	SKIPN P1,(Q1)		;FIND THE POINTER TO THE CDB
	AOJA Q1,PHYSTL		;LOOK AT NEXT CHANNEL
	CALL DGUMAP		;(P1/) CHECK ALL UDB'S ON THIS CHANNEL
	 CALL PCKOFL		; FOR DUAL PORT
	AOJA Q1,PHYSTL		;LOOP TILL ALL DONE

;CALLED FOR EACH UDB FOUND BY DGUMAP

PCKOFL:	TDNN Q2,UDBSTS(P3)	;CHECK FOR TAPE
	TDNN P4,UDBSTS(P3)	;IS THIS A DUAL PORTED DRIVE?
	RET			;NO FORGET IT
	MOVX T1,U1.FED!U1.DCR	;IS THIS A DON'T CARE DISK OR A FRONT-END DISK?
	TDNE T1,UDBST1(P3)	;THEN WE DON'T BOTHER IT
	RET			;THEN DON'T BOTHER IT
	MOVX T1,U1.STC		;SET STATUS CHANGE
	IORM T1,UDBST1(P3)
	IORM P5,UDBSTS(P3)	;SET THE CHECK HOME BLOCK BIT
	RET
;PYCOFF - CALLED BY CFSSRV WHEN A CONNECTION IS BROKEN TO INSURE WE THROW ALL
;DISKS OFFLINE THAT ARE POTENTIALLY ACCESSED BY THE NODE
; T2/ CI NODE NUMBER
;	CALL PYCOFF		;(T2/)
; RETURN +1

PYCOFF::SAVEPQ			;SAVE GENERAL REGISTERS
	SETZM CFSSTS(T2)	;INDICATE THIS NODE IS OFFLINE FOR FUTURE DISKS
	MOVEI Q1,CHNTAB		;LOOP THRU ALL UNITS TO SEE IF ANYTHING TO DO
	MOVX P5,U1.STC!U1.OFS	;OFFLINE DUAL PORTED DISK FLAG
	MOVX Q2,US.TAP		;TAPE IS ILLEGAL
PYCLOP:	CAILE Q1,CHNTAB+7	;DONE?
	RET			;YES QUIT
	SKIPN P1,(Q1)		;IS THERE A CDB?
	AOJA Q1,PYCLOP		;NO TRY AGAIN
	CALL DGUMAP		;(P1/) LOOP OVER ALL UNITS
	 CALL PYCOF1		;CHECK STATUS
	AOJA Q1,PYCLOP		;LOOP TILL DONE

;CALLED FOR EACH UDB FOUND BY DGUMAP

PYCOF1:	MOVE P4,P3		;FIND ADDRESS
	ADD P4,T2		;ADD IN OFFSET
	TDNN Q2,UDBSTS(P3)	;CHECK FOR TAPE
	SKIPN UDBP00(P4)	;HAS NODE EVER ACCESSED THE DISK??
	RET			;NO
	MOVX T1,US.2PT		;YES, DISK
	TDNN T1,UDBSTS(P3)	; STILL MULTI-ACCESS?
	RET			;NO
	MOVX T1,U1.FED!U1.DCR	;YES, FRONT-END
	TDNE T1,UDBST1(P3)	; OR DON'T CARE?
	RET			;YES
	IORM P5,UDBST1(P3)	;NO, FORCE OFFLINE
	MOVX T1,US.CHB		;NEED TO
	IORM T1,UDBSTS(P3)	; CHECK HOMEBLOCKS
	RET
;PYCON - CALLED BY CFSSRV WHEN A CONNECTION IS ESTABLISHED TO INSURE WE CHECK
;ALL DISKS THAT ARE POTENTIALLY ACCESSED BY THE NODE
; T2/ CI NODE NUMBER
; T3/ CPU SERIAL NUMBER
;	CALL PYCON		;(T2,T3/)
; RETURN +1

PYCON::	SAVEPQ			;SAVE REGISTERS FOR SAFETY
	HRLM T3,CFSSTS(T2)	;INDICATE THIS NODE IS ONLINE FOR FUTURE DISKS
	MOVEI Q1,CHNTAB		;LOOP THRU ALL UNITS TO SEE IF ANYTHING TO DO
	MOVX Q2,US.TAP		;CHECK FOR TAPE
PYCNLP:	CAILE Q1,CHNTAB+7	;CHECK ALL CHANNELS
	RET			;NONE QUIT
	SKIPN P1,(Q1)		;IS THERE A CDB?
	AOJA Q1,PYCNLP		;NO TRY NEXT ONE
	CALL DGUMAP		;(P1/) CHECK ALL UNITS
	 CALL PYCON2
	AOJA Q1,PYCNLP		;DO ALL CHANNELS

;CALLED FOR EACH UDB FOUND BY DGUMAP

PYCON2:	MOVE P4,P3		;CHECK STATUS OF THIS NODE
	ADD P4,T2		;ADD THE NODE NUMBER
	TDNN Q2,UDBSTS(P3)	;CHECK FOR TAPE NOT PERMITTED HERE
	SKIPN UDBP00(P4)	;HAS NODE EVER ACCESSED THE DISK?
	RET			;NO
	MOVX T1,U1.STC		;YES, INSURE STATUS CHANGE
	IORM T1,UDBST1(P3)	; IS SEEN JUST IN CASE
	MOVX T1,US.CHB		;CHECK HOMEBLOCKS AGAIN FOR CHANGE
	IORM T1,UDBSTS(P3)
	RET			;AND QUIT
;PHYFED - CALLED BY DTESRV AT SYSTEM STARTUP TO DECLARE DISKS TO BE
;FRONT-END DISKS
;**;[7154] Replace 2 lines with 1 at PHYFED-4	CEG 15-Oct-85
;	CALL PHYFED		;()
; RETURN +1

PHYFED::SAVEPQ			;SAVE DESTROYED REGISTERS
	IOPIOF			;TURN OFF INTERRUPTS
;**;[7154] Remove 1 line at PHYFED+2	CEG 15-Oct-85
	MOVEI P5,CHNTAB		;FIRST CHANNEL
;**;[7154] Replace 3 lines with 1 line at FELOOP	CEG 15-Oct-85
FELOOP:	SKIPN P1,(P5)		;[7154] CHECK CHANNEL EXISTANCE
	JRST FELPEN		;NO TRY NEXT
;**;[7154] Change 2 lines at FELPEN-3	CEG 15-Oct-85
	CALL DGUMAP		;[7154] (P1/P3) GET THE NEXT DISK
	 CALL FESET		;[7154] (P3/) SET THE FE DISK FLAG
	CAIGE P5,CHNTAB+7
FELPEN:	AOJA P5,FELOOP
FEXIT:	IOPION			;INTERRUPTS BACK ON
	RET			;ALL DONE


;**;[7154] Replace 1 line with 5 at FESET-2	CEG 15-Oct-85
;FESET - FORCES HOMEBLOCK CHECK ON ALL UNITS AND SETS FE DISK INDICATOR IN
;APPROPRIATE UDBS
; P3/ UDB
;	CALL FESET		;(P3)
; RETURN +1

FESET:	MOVX T1,US.TAP		;CHECK FOR DISK
	TDNE T1,UDBSTS(P3)	;CHECK FOR NOT TAPE
	RET			;NOT THE CORRECT THING
	MOVX T1,U1.STC		;SET STATUS CHANGES
	IORM T1,UDBST1(P3)
	MOVX T1,US.CHB		;FORCE HOMEBLOCK CHECK ON ALL
	IORM T1,UDBSTS(P3)	;
	HRRZ T3,UDBDSN(P3)	;GET SERIAL NUMBER
;**;[7154] Replace 8 lines with 16 lines at FESET+8	CEG 15-Oct-85
	LOAD T1,USTYP,(P3)	;[7154] GET UNIT TYPE
	CAIE T1,.UTRP6		;[7154] IS IT AN RP06
	CAIN T1,.UTRP4		;[7154]  OR AN RP04?
	SKIPA			;[7154] YES, MAYBE CONNECTED TO FE
	RET			;[7154] NO, THEN IT'S NOT CONNECTED TO FE
	MOVSI T2,-FEDSKL	;[7154] MAKE AOBJN WORD FOR SEARCHING FE LIST
FELOP1:	SKIPN T4,FEDSKT(T2)	;[7154] FE KNOW THIS UNIT?
	IFSKP.			;[7154] 
	  CAME T4,T3		;[7154] YES, IS THIS IT'S UDB?
	  ANSKP.		;[7154] 
	    MOVX T4,U1.FED	;[7154] YES, SET 
	    IORM T4,UDBST1(P3)	;[7154]  FE DISK
	    RET			;[7154] FOUND THE ONE, QUIT
	ENDIF.			;[7154] 
	AOBJN T2,FELOP1		;[7154] CHECK ALL UNITS IN FE LIST
	RET			;[7154]
	SUBTTL

;HERE TO ATTEMPT RESTART OF A FAILED IORB
;Called IOPIOF.
;Returns with IOPIOF and
;	+1 failed to restart
;	+2 did a restart

UNITRY:	SAVEQ			;PRESERVE REGISTERS
	MOVX T1,US.ACT!US.CIP	;GET UNIT ACTIVE FLAGS
	MOVX T2,KS.ACT		;AND CONTROLLER ACTIVE FLAGS
	TRNE P2,-1		;KDB ?
	TDNN T2,KDBSTS(P2)	;ACTIVE?
	TDNE T1,UDBSTS(P3)	;ACTIVE?
	RET			;Yes. Who knows?
	HRRZ P4,UDBTWQ(P3)	;ANY TRANSFERS PENDING?	
	JUMPN P4,UNITR2		;YES - ATTEMPT RESTART
UNITR7:	HRRZ P4,UDBPWQ(P3)	;ANY SEEKS?
	JUMPN P4,UNITR1		;YES - RESTART
	RETSKP			;AND SAY SO.

UNITR1:	SKIPE T4,UDBCHB(P3)	;CHECK FOR A HOMEBLOCK REQUEST
	CALL FRHOMB		;HOMEBLOCK FIRST
	CALL STRTPS		;RESTART POSITION OPERATION
	 RET			;Failed
	RETSKP			;Success

UNITR2:	MOVE T1,CDBSTS(P1)	;GET CHANNEL STATUS
	TXNE T1,CS.ACT		;ACTIVE?
	RET			;Yes. Can't proceed
	SKIPE PHYSEC		;MINUTE BOUNDARY?
	JRST UNITR3		;NO, SKIP ON
	MOVX T1,US.DSK		;GET DISK FLAG READY
	MOVX T2,US.WLK		;AND WRITE-LOCKED FLAG READY
	TDNE T1,UDBSTS(P3)	;IS THIS A DISK?
	ANDCAM T2,UDBSTS(P3)	;YES, ALLOW RP20S TO TRY WRITING AGAIN
UNITR3:	SKIPE T2,UDBCHB(P3)	;IS THERE A HOMEBLOCK IORB?
	CAMN T2,P4		;AND IS IT THE ONE WE ARE WORKING ON?
	CALLRET STRTIO		;YES THEREFORE START IT
UNITR5:	CALL OFFTWQ		;FROM THE TWQ
	CALL ONFPWQ		;PUT IT ON THE PWQ
	HRRZ T1,UDBTWQ(P3)	;CHECK FOR ANOTHER ENTRY
	JUMPN T1,UNITR5		;TRY AGAIN
	JRST UNITR7		;GO TRY TO START HOMEBLOCK REQUEST

FRHOMB:	CAMN P4,UDBCHB(P3)	;CHECK TO SEE IF THIS IS THE HOMEBLOCK ENTRY
	RET			;QUIT NOW WE GOT IT (SURPRISE)
	HRRZ T2,UDBPWQ(P3)	;GET THE BEGINNING OF THE QUEUE
FRHBLP:	MOVE T1,T2		;POINTER TO PREVIOUS
	HRRZ T2,IRBLNK(T1)	;GET THE FORWARD LINK
	JUMPE T2,[ BUG. (HLT,HOMGON,PHYSIO,SOFT,<FRTHOB - Missing homeblock IORB>,<<P1,CHN>,<P2,KONT>,<P3,UNIT>>,<

Cause:	Missing homeblock IORB when we believe there should be one on
	the PWQ.

Data:	CHN - The channel number
	KONT - The controller number
	UNIT - The unit number
>)]
	CAME T2,T4		;FOUND THE IORB
	JRST FRHBLP		;NOT FOUND TRY NEXT ONE
	MOVE P4,T2		;SET UP FOR RETURN IORB
	CALL CONSPW		;REMOVE THIS IORB
	MOVE T1,P4		;INSERT IT ON THE FRONT OF THE QUEUE
	CALLRET ONFPWQ		;PUT IT ON THE PWQ AND QUIT
	
;HERE TO TERMINATE A HUNG IORB AND RESTART CHANNEL ACTIVITY


;T1/ IORB
;P1 SETUP
;WIPES THE REGISTERS
;MUST BE CALLED IOPIOF


HNGIRB:	MOVE P4,T1		;SETUP IORB IN EXPECTED PLACE
	MOVX T1,US.REW!US.ORC		;CLEAR REWINDING STATUS
	ANDCAB T1,UDBSTS(P3)	; IN THE UDB (ALSO LOAD UDBSTS INTO T1)
	TXNE T1,US.POS		;WAS THIS A POSITION REQUEST?
	JRST HNGIR1		;YES
	HRRZ T1,CDBDSP(P1)	;GET CHANNEL DISPATCH
	CALL CDSHNG(T1)		;DO HUNG RESET
	MOVX T1,US.CIP
	TDNE T1,UDBSTS(P3)	;IS IT A CI DISK?
	RET			;YES. MAYBE IT WILL COME BACK LATER
	CALL CLRACT		;NO, RESET ALL ACTIVE BITS
	MOVX T1,IS.NRT!IS.DVE	;GET ERROR FLAGS READY
	IORM T1,IRBSTS(P4)	;IN ALL CASES MARK IORB AS FAILED
	CALL DONIRB		;POST AS COMPLETE
	CALL SCHSEK		;START SEEKS (IF APPROPRIATE)
	CALL SCHXFR		;RESTART CHANNEL IF ANY WORK
	RET



;HERE TO CLEAN UP AFTER A HUNG SEEK


HNGIR1:	TRNN P2,-1		;ANY CONTROLLER?
	JRST HNGIR2		;NOPE, SKIP ON
	HRRZ T1,KDBACT(P2)	;YES, GET ACTIVE UNIT IF ANY
	CAIE T1,(P3)		;WAS CONTROLLER BUSY FOR THIS DRIVE?
	JRST HNGIR2		;NOPE, SKIP ON
	HRRZ T1,UDBDSP(P3)	;YES, GET DISPATCH ADDRESS
	CALL UDSHNG(T1)		;DO HUNG DEVICE RECOVERY
	CALL CLRPOS		;CLEAR ACTIVE BITS FOR CONTROLLER AND UNIT
	SKIPA			;SKIP INTO REST
HNGIR2:	CALL CLRSRC		;CLEAR ACTIVE BITS FOR UNIT
	MOVX T1,IS.NRT!IS.DVE	;GET ERROR FLAGS READY
	MOVX T2,US.DSK		;IF THIS IS A DISK, THEY DO IMPLIED SEEKS
	TDNN T2,UDBSTS(P3)	;SO THAT POSITIONING ERRORS CAN BE IGNORED
	IORM T1,IRBSTS(P4)	;BUT IF NOT A DISK, FLAG AN ERROR
	CALL DONIRB		;MARK THE IORB AS COMPLETE
	CALL SCHSEK		;START ANOTHER SEEK
	MOVX T1,CS.ACT!CS.ERC	;CHANNEL NOW IDLE?
	TDNN T1,CDBSTS(P1)	; ???
	CALL SCHXFR		;YES - SEE IF ANYTHING ELSE TO DO
	RET
;HERE TO ISSUE A MESSAGE TO THE OPERATOR
;  T1/ POINTER TO INITIAL MESSAGE
;  P3/ UDB


UNIMES:	SAVEPQ			;PRESERVE REGISTERS
	HRRZ P1,UDBCDB(P3)	;PICK UP CHANNEL NUMBER
	HRRZ P2,UDBKDB(P3)	;PICK UP CONTROLLER NUMBER
	CALL PMES		;PRINT START OF MESSAGE
	MOVX T1,US.TAP		;MAGTAPE?
	TDNE T1,UDBSTS(P3)	; ???
	JRST UNIMS5		;YES, PRINT OUT "MTAN"
	LDB T1,USYTYP		;GET UNIT TYPE
	MOVE T1,NAMUTP(T1)	;GET NAME AS STRING POINTER
	CALL PMES		;PRINT TYPE
	HRRZ CX,UDBSTR(P3)	;GET STRUCTURE
	SKIPL Q1,UDBSTR(P3)	;UNIT IN STR?
	SKIPN Q1,STRTAB(CX)	; ???
	JRST UNIMS0		;NO
	HRROI T1,[ASCIZ /, STR=/]
	CALL PMES		;YES - PRINT NAME
	HRRZ Q1,Q1
	MOVE T1,SDBNAM(Q1)	;COPY STR NAME
	CALL PSIX		;PRINT IT
UNIMS0:	SKIPN UDBDSN(P3)	;SERIAL NUMBER KNOWN?
	JRST UNIMS2		;NO - SKIP THAT PART
	HRROI T1,[ASCIZ /, S.N.=/]
	CALL PMES		;PREPARE TO PRINT SERIAL
	MOVE T1,UDBDSN(P3)	;GET SERIAL NUMBER
	CALL PNUM		;PRINT THE SERIAL NUMBER
UNIMS2:	HRROI T1,[ASCIZ /
	Access path: CHN=/]	;PREPARE NEXT PART
	CALL PMES		;PRINT
	HRRZ T1,CDBADR(P1)	;GET CHANNEL NUMBER
	CALL PNUM		;PRINT IT
	JUMPN P2,UNIMS4		;IF KDB, PRINT APPROPRIATE MESSAGE
UNIMS3:	HRROI T1,[ASCIZ /, UNI=/] ;PREPARE NEXT
	CALL PMES
	HRRZ T1,UDBAKA(P3)	;GET ADDRESS
	TRNE P2,-1		;UNLESS HAVE A CONTROLLER
	HRRZ T1,UDBSLV(P3)	;IN WHICH CASE, SUBUNIT IS HERE
	CALL PNUM		;PRINT IT
	HRROI T1,[ASCIZ /
/]
	CALL PMES		;FINISH IT OFF
	RET
;HERE WHEN A CONTROLLER IS IN THE WAY


UNIMS4:	HRROI T1,[ASCIZ /, /]
	CALL PMES		;PREPARE TO PRINT KON TYPE
	EXCH P2,P3		;GET KDB IN P3
	LDB T1,USYTYP		;GET UNIT TYPE
	EXCH P2,P3		;REPLACE KDB,UDB
	MOVE T1,NAMUTP(T1)	;GET KON TYPE
	CALL PMES		;PRINT IT
	HRROI T1,[ASCIZ /=/]
	CALL PMES		;ANNOUNCE OBJECT
	HRRZ T1,UDBAKA(P3)	;GET ADDRESS
	CALL PNUM		;PRINT IT
	JRST UNIMS3		;JOIN ABOVE


UNIMS5:
IFN NICSW,<
	HRROI T1,[ASCIZ/MTA/]
	CALL PMES		;GIVE LOGICAL UNIT NUMBER
	MOVSI Q1,-MTAN		;LOOK FOR THIS UNIT
UNIMS6:	HRRZ T1,MTCUTB(Q1)	;GET UDB ADR
	CAIN T1,(P3)		;FOUND THE UNIT YET?
	JRST UNIMS7		;YES
	AOBJN Q1,UNIMS6		;NO, LOOP BACK TIL FOUND
>;IFN NICSW
IFE NICSW,<
	MOVSI Q1,-MTAN		;LOOK FOR THIS UNIT
UNIMS6:	HRRZ T1,MTCUTB(Q1)	;GET UDB ADR
	CAIN T1,(P3)		;FOUND THE UNIT YET?
	IFNSK.
	  HRROI T1,[ASCIZ/MTA/]	;YES, SAY IT'S A TAPE DRIVE
	  CALL PMES
	  JRST UNIMS7		;AND PRINT THE LOGICAL UNIT NUMBER
	ENDIF.
	AOBJN Q1,UNIMS6		;NO, LOOP BACK TIL FOUND
	MOVSI Q1,-ENN		;NOT FOUND, MAYBE IT'S A MEIS
UNIM6A:	HRRZ T1,ENCUTB(Q1)	;GET UDB
	CAIN T1,(P3)		;MATCH?
	IFNSK.
	  HRROI T1,[ASCIZ/MEIS/] ;YES, SAY IT'S A MEIS
	  CALL PMES
	  JRST UNIMS7		;AND GO PRINT ITS LOGICAL UNIT NUMBER
	ENDIF.
	AOBJN Q1,UNIM6A		;LOOP OVER ALL TABLE ENTRIES
>;IFE NICSW
	JRST UNIMS0		;NOT FOUND SO DONT GIVE UNIT NUMBER

UNIMS7:	HRRZS Q1		;GET UNIT NUMBER
	MOVE T1,Q1
	CALL PNUM
	JRST UNIMS0		;GO CONTINUE MESSAGE
;**;[7193]Delete routine PMES and move it to TTYSRV	JYCW	Nov-12-85

;HERE TO PRINT A SMALL NUMBER (FOUR DIGITS OR LESS) IN T1 AS AN OCTAL NUMBER

PNUM:	SETZ T3,		;CLEAR RESULT
PNUMLP:	IDIVI T1,^D10		;SPLIT OFF A DIGIT
	ADDI T2,"0"		;CONVERT REMAINDER TO ASCII
	LSHC T2,-7		;STORE WITH OTHER CHARACTERS IN T3
	JUMPN T1,PNUMLP		;PROCEED IF NOT DONE YET
	TRZ T3,377		;INSURE A NULL EXISTS
	PUSH P,T3		;SAVE RESULT
	HRROI T1,(P)		;POINT TO WORD
	CALL PMES		;TYPE NUMBER
	JRST PA1		;SCRAP STACK AND RETURN

;HERE TO PRINT T1 IN SIXBIT

PSIX:	MOVE T2,T1		;COPY ARG
	ADJSP P,2		;ALLOC STRING SPACE (STACK ALMOST GONE)
	HRRZI T3,-1(P)		;GET START OF STRING
	HRLI T3,(<POINT 7,.-.>)	;BUILD BYTE POINTER
PSIX1:	MOVEI T1,0		;CLEAR T1
	LSHC T1,6		;GET A CHAR FROM ARG
	SKIPE T1		;IF NOT END
	ADDI T1,40		;MAKE LIKE ASCII
	IDPB T1,T3		;STORE IN OUTPUT STRING
	JUMPN T1,PSIX1		;LOOP
	HRROI T1,-1(P)		;BUILD STRING POINTER
	CALL PMES		;PRINT STRING
	ADJSP P,-2		;SCRAP STACK
	RET			;DONE

PHCVBO::MOVE T4,T1		;SAVE THE NUMBER GIVEN
	LDB T1,[POINT 4,T4,23]	;GET HIGH ORDER DIGIT
	IMULI T1,^D10		;MULT BY 10
	LDB T2,[POINT 4,T4,27]	;GET 2ND DIGIT
	ADD T1,T2		;ADD TO NUMBER
	IMULI T1,^D10
	LDB T2,[POINT 4,T4,31]	;GET THIRD DIGIT
	ADD T1,T2
	IMULI T1,^D10
	LDB T2,[POINT 4,T4,35]	;LAST DIGIT
	ADD T1,T2		;LAST ONE
	RET			;RETURN
	SUBTTL	MOUNTABLE STRUCTURE SUPPORT ROUTINES

;ROUTINE TO SET UP UDBSTR AND SDBUDB DURING MOUNTING OF A STRUCTURE
;
;ACCEPTS IN T1/ UNIT'S CKU NUMBERS (CHANNEL, CONTROLLER, UNIT NUMBERS)
;	    T2/	UNIT NUMBER IN STRUCTURE,,STRUCTURE NUMBER
;	    T3/	ADDRESS OF SDB
;		CALL SETSTR
;RETURNS: +1 ALWAYS


	SWAPCD


SETSTR::STKVAR <STRSTN,SDBADR>	;ALLOCATE STORAGE
	MOVEM T2,STRSTN		;SAVE STRUCTURE NUMBER
	MOVEM T3,SDBADR		;AND SDB ADDRESS
	CALL CKUNPK		;UNPACK THE CKU NUMBERS
	CALL CHKCKU		;THEN FIND THE UDB ADDRESS
	 BUG.(HLT,UNFWSS,PHYSIO,SOFT,<Unit not found creating SDB for structure>,,<

Cause:	The routine SETSTR was called to build an SDB for a structure.
	One of its arguments is the channel, controller, and unit numbers
	of a unit which had already been known to exist.  But when the
	routine CHKCKU was called to find the UDB of the unit, the routine
	failed to find the unit.
>)		;SHOULD BE THERE!
	HLRZ T2,STRSTN		;GET LOGICAL UNIT NUMBER WITHIN THE STRUCTURE
	ADD T2,SDBADR		;ADD IN SDB ADDRESS
	MOVEM T1,SDBUDB(T2)	;STORE UDB ADDRESS IN SDB
	MOVE T2,STRSTN		;GET BACK UNIT,,STRUCTURE NUMBERS
	MOVEM T2,UDBSTR(T1)	;STORE THEM IN THE UDB
	MOVEI T2,ST%MNT		;REASON FOR THE ENTRY
	CALLRET LGSTAT		;LOG THE DRIVE'S STATISTICS, RETURN



;ROUTINE TO CLEAR THE UDBSTR AND SDBUDB ENTRIES FOR ALL UNITS IN
;A STRUCTURE.
;
;CALL:
;ACCEPTS IN T1/ SDB ADDRESS
;	CALL CLRSTR
;RETURNS: +1 ALWAYS


CLRSTR::SAVEAC <P1>		;SAVE AN AC
	MOVN P1,SDBNUM(T1)	;MAKE AOBJN WORD FROM # OF UNITS IN STRUCTURE
	HRLZ P1,P1		;PUT NEGATIVE COUNT IN LEFT HALF
	HRR P1,T1		;AND SDB ADDRESS IN RIGHT HALF

; LOOP OVER ALL UNITS IN THE STRUCTURE

CLRST2:	MOVE T1,SDBUDB(P1)	;GET ADDRESS OF UNIT DATA BLOCK
	JUMPE T1,CLRST3		;IF NONE SETUP GO TO NEXT
	SETZM SDBUDB(P1)	;CLEAR POINTER TO UNIT DATA BLOCK
	SETOM UDBSTR(T1)	;CLEAR STRUCTURE INFORMATION IN UDB
	MOVEI T2,ST%DMT		;REASON FOR THE ENTRY
	CALL LGSTAT		;LOG THE DRIVE'S STATISTICS
CLRST3:	AOBJN P1,CLRST2		;LOOP OVER ALL UNITS IN THE STRUCTURE
	RET			;RETURN
;ROUTINE TO RETURN STRUCTURE NUMBER OF WHICH A GIVEN UNIT IS A PART
;
;ACCEPTS:	T1/  UDB ADDRESS OF UNIT
;		CALL GETSTR
;RETURNS: +1	 FAILED, UNIT OFFLINE OR IN MAINT MODE, WITH T1/ FLAGS
;         +2	SUCCESS, WITH T1/ UNIT WITHIN STRUCTURE,,STRUCTURE NUMBER
;				  OR -1 IF UNIT NOT IN STRUCTURE
;			      T2/ UNIT TYPE
;			      T3/ FLAGS:
;					MS%WLK IF UNIT IS WRITE LOCKED

GETSTR::MOVE T4,UDBSTS(T1)	;GRAB UDB STATUS
	SETZ T3,		;CLEAR FLAGS TO RETURN
	TXNE T4,US.OFS		;UNIT OFF-LINE?
	TXO T3,MS%OFL		;YES, MARK IT
	MOVE T2,UDBST1(T1)	;Get secondary status word
	TXNE T2,U1.OFS		;Is it forced offline by TOPS-20?
 	TXO T3,MS%IAC		;Yes, mark it
	TXNE T4,US.MAI		;IN MAINTENANCE MODE?
	TXO T3,MS%DIA		;YES, MARK IT
	TXNE T4,US.WLK		;WRITE-LOCKED?
	TXO T3,MS%WLK		;YES, MARK IT
;**;[7312]  Remove DEBUG conditional at GETSTR:+11	DML	22-May-86
	MOVE T2,UDBCHR(T1)	;GET CHARACTERISTICS WORD
	TXNE T2,UC.OLB		;IS UNIT SERVED (ONLINE VIA MSCP SERVER)
	TXO T3,MS%SVD		;YES, MARK IT

;Figure out if unit is currently dual-ported to an unother KL

	TXNN T4,US.OFS!US.CIP	;OFF LINE OR ON THE CI?
	TXNN T4,US.PGM		;NO, DUAL-PORTED?
	JRST GETST1		;NOT INTERESTING
	MOVE T4,UDBST1(T1)	;GET SECOND STATUS WORD
	TXNE T4,U1.FED!U1.DCR	;FRONT-END OR DON'T-CARE DISK?
	JRST GETST1		;YES, NOT INTERESTING
	SKIPN UDB2ND(T1)	;NO, BOTH PATHS TO US?
	TXO T3,MS%2PT		;NO, 1 PORT TO AN UNKNOWN SYSTEM
GETST1:	LDB T2,[POINT USSTYP,UDBSTS(T1),USPTYP] ;GET UNIT TYPE
	MOVE T1,UDBSTR(T1)	;GET STRUCTURE NUMBER FOR THIS UNIT
	TXNN T3,MS%OFL!MS%DIA	;ANY FATAL ERRORS?
	RETSKP			;NOPE, SUCCESSFUL RETURN
	MOVE T1,T3		;YES, COPY FLAGS
	RET			;GIVE ERROR RETURN
;ROUTINE TO ACCEPT CHANNEL, CONTROLLER, AND UNIT NUMBERS AND
;FIND THE UDB WITH THE SPECIFIED ADDRESS.  CALL:
;  T1/	CHANNEL NUMBER
;  T2/	CONTROLLER NUMBER OR -1 IF NONE
;  T3/	UNIT NUMBER
;  T4/  0 TO ALLOW ANY KIND OF UDB, OR -1 TO ONLY ALLOW DISKS
;RETURNS:  +1:	ARGUMENTS ARE ILLEGAL OR UNIT CANNOT BE FOUND
;		  T1/ ERROR CODE
;	   +2:	SPECIFIED UDB FOUND
;		  T1/ UDB ADDRESS
;		  T2/ UNIT TYPE
;CALL CHKCKU FOR NORMAL CASE WHERE ONLY DISK UNITS ARE ALLOWED.
;CALL CHKCKS IF UNIT NUMBERS ARE "RELATIVE" RATHER THAN ABSOLUTE

	RESCD


CHKCKS::SAVEPQ
	SETOM T4		;ONLY DISKS
	SETOM Q3		;KONTROLLER RELATIVE
	JRST CHKCK2

CHKCKU::SETOM T4		;REMEMBER TO ONLY PERMIT DISKS
CHKCKA::SAVEPQ			;SAVE SOME ACS
	SETZM Q3
CHKCK2:	MOVE Q1,T4		;REMEMBER DISK ONLY FLAG
	SKIPL T1		;SEE IF CHANNEL NUMBER IS TOO SMALL
	CAIL T1,CHNN		;OR TOO LARGE
	 RETBAD (MSTX14)	;YES, "INVALID CHANNEL NUMBER"
	SKIPN P1,CHNTAB(T1)	;GET CDB ADDRESS
	 RETBAD (MSTX41)	;NONE, "CHANNEL DOES NOT EXIST"
	HLRE T1,CDBIUN(P1)	;GET NUMBER OF UNITS
	MOVMS T1		;MAKE POSITIVE
	HRRZ T4,CDBIUN(P1)	;ALSO GET ADDRESS OF UDB/KDB TABLE
	CAME T2,[-1]		;SEE IF A CONTROLLER IS SPECIFIED
	JRST CHKISK		;YES, SKIP ON


;HERE IN THE CASE THAT NO CONTROLLER IS SPECIFIED.  CHECK TO MAKE SURE
;THAT THE UNIT NUMBER GIVEN IS LEGAL AND IS IN FACT A UDB INSTEAD OF A KDB.


CHKUNT:	SKIPL T3		;UNIT NUMBER TOO SMALL?
	CAML T3,T1		;OR TOO LARGE?
	 RETBAD (MSTX15)	;YES, "INVALID UNIT NUMBER"
	ADD T3,T4		;MAKE ADDRESS OF UDB POINTER
	SKIPN P3,(T3)		;GET UDB ADDRESS
	 RETBAD (DIAGX9)	;NONE, "UNIT DOES NOT EXIST"
	LDB T4,USYBKT		;GET BLOCK TYPE
	CAIE T4,.BTUDB		;MAKE SURE IT IS A UDB
	 RETBAD (DIAGX9)	;NOPE, "UNIT DOES NOT EXIST"
	JRST CHKHVU		;OK, GO FINISH UP
;HERE IN THE CASE THAT A CONTROLLER NUMBER WAS GIVEN.  CHECK ITS LEGALITY,
;AND MAKE SURE THAT A KDB WAS SPECIFIED INSTEAD OF A UDB.  FINALLY, THEN
;CHECK TO SEE THAT THE UNIT NUMBER IS LEGAL.


CHKISK:	SKIPL T2		;SEE IF CONTROLLER NUMBER IS TOO SMALL
	CAML T2,T1		;OR TOO LARGE
	 RETBAD (MSTX16)	;YES, "INVALID CONTROLLER NUMBER"
	ADD T2,T4		;MAKE ADDRESS OF KDB POINTER
	SKIPN P2,(T2)		;GET KDB ADDRESS
	 RETBAD (MSTX42)	;NONE, "CONTROLLER DOES NOT EXIST"
	MOVE P3,P2		;COPY FOR LDB
	LDB T4,USYBKT		;GET BLOCK TYPE
	CAIE T4,.BTKDB		;MAKE SURE IT'S A KDB AND NOT A UDB
	 RETBAD (MSTX42)	;NOPE, THEN "CONTROLLER DOES NOT EXIST"
	HLRE T1,KDBIUN(P2)	;GET NUMBER OF UNITS
	MOVMS T1		;MAKE POSITIVE
	HRRZ T4,KDBIUN(P2)	;ALSO GET ADDRESS OF UDB TABLE
	SKIPE Q3		;SPECIAL "RELATIVE" UNIT NUMBER
	JRST CHKUNT		;YES
	MOVE Q2,T3		;COPY OVER UNIT NUMBER
	HRRZ T1,KDBDSP(P2)	;GET DISPATCH ADDRESS
	CALL UDSEXT(T1)		;CHECK TO SEE IF UNIT IS VALID
	 JRST [	SKIPN T1	;BAD UNIT, DETERMINE WHY
		RETBAD(MSTX15)	;IT'S "INVALID UNIT NUMBER"
		RETBAD(DIAGX9)]	;IT'S "UNIT DOES NOT EXIST"

CHKHVU:	MOVE T1,UDBSTS(P3)	;GET STATUS
	TXNN T1,US.TPD		;NO UNIT IF A "3-PORTED" DISK
	SKIPGE UDB2ND(P3)	;NO UNIT IF 2ND PORT OF A DUAL-PORTED DRIVE
	 RETBAD (DIAGX9)	;NONE, "UNIT DOES NOT EXIST"
	MOVE T1,P3		;GET UDB FOUND
	LDB T2,USYTYP		;AND THE UNIT TYPE
	JUMPE Q1,RSKP		;DONE IF ANY KIND OF UDB IS ALLOWED
	MOVX T3,US.DSK		;GET DISK BIT READY
	TDNN T3,UDBSTS(P3)	;IS THIS A DISK DEVICE?
	 RETBAD (MSTX27)	;NO, "SPECIFIED UNIT IS NOT A DISK"
	RETSKP			;IT'S A DISK, GOOD RETURN
;ROUTINE TO ADVANCE TO THE NEXT UDB IN THE SYSTEM BY SCANNING ALL
;CHANNELS, CONTROLLERS, AND UNITS.  CALL:
;  T1/	CHANNEL NUMBER, OR -1 TO START AT BEGINNING
;  T2/	CONTROLLER NUMBER OR -1 FOR NONE
;  T3/	UNIT NUMBER, OR -1 TO START WITH FIRST ONE
;  T4/  0 TO ALLOW ANY KIND OF UDB, OR -1 TO ONLY ALLOW DISKS
;RETURNS: +1:  NO MORE UNITS IN SYSTEM
; 	  +2:  NEXT UNIT FOUND
;		T1/  NEW CHANNEL NUMBER
;		T2/  NEW CONTROLLER NUMBER OR -1 IF NONE
;		T3/  NEW UNIT NUMBER
;		T4/  UDB FOR THIS UNIT
;SEARCHING IS DONE BY INCREMENTING FIRST THE UNIT NUMBER, THEN THE
;CONTROLLER NUMBER, AND LASTLY THE CHANNEL NUMBER.  THE CASE WHERE
;NO CONTROLLER EXISTS IS HANDLED SIMPLY AS "CONTROLLER NUMBER -1".
;CALL ADVCKU FOR NORMAL CASE WHICH ONLY ALLOWS DISK UNITS.
;CALL ADVCKS WHEN USING "RELATIVE" UNIT NUMBERING

ADVCKS::SAVEPQ
	SETOM Q3		;RELATIVE UNIT NUMBERS
	JRST ADVCK0

ADVCKU::SETOM T4		;ASSUME ONLY WANT DISKS
ADVCKA::SAVEPQ			;SAVE ACS
	SETZM Q3		;ABSOLUTE UNIT NUMBERS
ADVCK0:	ASUBR <ACHAN,ACTRL,AUNIT,ATYPE>	;SAVE CALLING ARGUMENTS
	CAMN T1,[-1]		;WANTS TO START WITH FIRST CHANNEL?
	JRST ADVCHN		;YES, GO DO IT

NXTUNI:	DMOVE T1,ACHAN		;SET UP TWO OF THE ARGUMENTS
	AOS T3,AUNIT		;ADVANCE TO NEXT UNIT
	MOVE T4,ATYPE		;GET FLAG READY ALSO
	CALL CHKCK2		;SEE IF THIS COMBINATION IS LEGAL
	 JRST ADVERR		;NO, GO SEE WHY
	MOVE T4,T1		;MOVE UDB TO CORRECT AC
	DMOVE T1,ACHAN		;RESTORE NEW CHANNEL AND CONTROLLER NUMBERS
	MOVE T3,AUNIT		;ALSO RESTORE NEW UNIT NUMBER
	RETSKP			;DONE



;HERE WHEN A PARTICULAR COMBINATION ISN'T VALID.  DETERMINE WHY, AND
;THEN MOVE TO THE NEXT UNIT, CONTROLLER, OR CHANNEL AS APPROPRIATE.


ADVERR:	CAIN T1,MSTX14		;INVALID CHANNEL NUMBER?
	RET			;YES, ALL DONE
	CAIE T1,MSTX41		;CHANNEL NOT THERE?
	CAIN T1,MSTX16		;OR INVALID CONTROLLER NUMBER?
	JRST ADVCHN		;YES, GO TO NEXT CHANNEL
	CAIE T1,MSTX42		;CONTROLLER NOT THERE?
	CAIN T1,MSTX15		;OR INVALID UNIT NUMBER?
	JRST ADVCTL		;YES, ADVANCE TO NEXT CONTROLLER
	JRST NXTUNI		;NO, MOVE TO NEXT UNIT
;ROUTINES TO ADVANCE CHANNELS OR CONTROLLERS.


ADVCHN:	SETOM ACTRL		;RESET CONTROLLER NUMBER BACK TO -1
	AOSA ACHAN		;MOVE TO NEXT CHANNEL NUMBER AND SKIP
ADVCTL:	AOS ACTRL		;MOVE TO NEXT CONTROLLER NUMBER
	SETOM AUNIT		;START WITH FIRST UNIT
	JRST NXTUNI		;GO EXAMINE IT
;SIMPLE ROUTINES TO PACK AND UNPACK THE CKU NUMBERS FOR A UNIT.
;CALL FOR CKUPAK:
;  T1/	CHANNEL NUMBER
;  T2/	CONTROLLER NUMBER OR -1 IF NONE
;  T3/	UNIT NUMBER
;RETURNS +1:  ALWAYS
;		T1/  CKU NUMBER
;
;CALL FOR CKUNPK:
;  T1/	CKU NUMBER
;RETURNS +1:  ALWAYS
;		T1/  CHANNEL NUMBER
;		T2/  CONTROLLER NUMBER OR -1 IF NONE
;		T3/  UNIT NUMBER



CKUPAK::STOR T1,DOP%C2,T1	;POSITION THE CHANNEL NUMBER
	STOR T2,DOP%K2,T1	;STORE THE CONTROLLER NUMBER
	STOR T3,DOP%U2,T1	;AND FINALLY THE UNIT NUMBER
	RET			;DONE



CKUNPK::LOAD T3,DOP%U2,T1	;EXTRACT THE UNIT NUMBER
	LOAD T2,DOP%K2,T1	;AND THE CONTROLLER NUMBER
	CAIN T2,<.RTJST(-1,DOP%K2)>	;WAS FIELD ALL ONES?
	SETOM T2		;YES, SET NO CONTROLLER THEN
	LOAD T1,DOP%C2,T1	;FINALLY EXTRACT THE CHANNEL NUMBER
	RET			;DONE
;HERE TO EXECUTE AN INSTRUCTION ONCE FOR EACH UDB ON A CHANNEL

;CALL DGUMAP
; INSTRUCTION TO EXECUTE

;THE INSTRUCTION WILL BE EXECUTED ONCE WITH P3 SETUP TO EACH UDB
;THIS ROUTINE CLOBBERS Q3




DGUMAP::MOVE Q3,CDBIUN(P1)	;GET AOBJN WORD
DGUMP1:	SKIPN P3,(Q3)		;UDB PRESENT?
	JRST DGUMP2		;NO - TRY NEXT
	LDB T1,USYBKT		;GET BLOCK TYPE
	CAIE T1,.BTUDB		;UDB ?
	JRST DGUMP3		;IS KDB, LOOP FOR IT
	MOVEI P2,0		;IF NO KDB, PROVIDE A ZERO
	XCT @(P)		;EXECUTE INSTRUCTION
DGUMP2:	AOBJN Q3,DGUMP1		;LOOP
	RETSKP			;DONE

DGUMP3:	MOVE P2,P3		;COPY KDB
	PUSH P,Q3		;SAVE AOBJN POINTER
	MOVE Q3,KDBIUN(P2)	;GET NEW ONE FOR KDB'S UNITS
DGUMP4:	SKIPE P3,(Q3)		;UDB PRESENT?
	XCT @-1(P)		;YES, DO INSTRUCTION
	AOBJN Q3,DGUMP4		;LOOP FOR MORE
	POP P,Q3		;RESTORE ORIGINAL AOBJN WORD
	MOVEI P2,0		;ENSURE NIL KDB
	JRST DGUMP2		;CONTINUE OUTER LOOP
; DCUNIT ROUTINE TO SET/CLEAR DON'T CARE BIT
;
;
DCUNIT::STKVAR <SETCLR>		;SAVE UNIT STATUS
	MOVEM T2,SETCLR
	UMOVE T1,(T2)		;GET CHANNEL NUMBER
	UMOVE T3,2(T2)		;GET UNIT NUMBER
	UMOVE T2,1(T2)		;GET CONTROLLER NUMBER
	SETO T4,		;DISKS ONLY
	NOSKED			;NO INTERRUPTS
	IOPIOF			;TURN OFF INTERRUPTS TO PREVENT CHANGES
	CALL CHKCKU		;CHECK FOR LEGAL
	JRST DCUBAD		;BAD QUIT
	MOVX T2,U1.DCU		;SET DON'T-CARE DRIVE
	IORM T2,UDBST1(T1)	; IN UDB
	MOVX T2,U1.OFS		;SET DRIVE ONLINE
	ANDCAM T2,UDBST1(T1)	;SO WE CAN FIND IT
	CALL PHYSTC		;CAUSE HOMEBLOCK CHECKING
	IOPION			;TURN ON INTERRUPTS
	OKSKED
	MRETNG			;RETURN OK

DCUBAD:	IOPION			;ENABLE INTERRUPTS
	OKSKED			;AND SCHED
	RETBAD ()		;AND RETURN ERROR
	

	TNXEND
	END