Google
 

Trailing-Edge - PDP-10 Archives - bb-m780d-sm - monitor-sources/phymvr.mac
There are 20 other files named phymvr.mac in the archive. Click here to see a list.
; UPD ID= 8590, RIP:<7.MONITOR>PHYMVR.MAC.6,  11-Feb-88 16:56:16 by GSCOTT
;TCO 7.1218 - Update copyright date.
; UPD ID= 8451, RIP:<7.MONITOR>PHYMVR.MAC.5,   4-Feb-88 17:13:11 by GSCOTT
;More of TCO 7.1210 - Correct spelling in MSSCGL
; UPD ID= 8437, RIP:<7.MONITOR>PHYMVR.MAC.4,   4-Feb-88 15:57:37 by GSCOTT
;TCO 7.1210 - Set MSSCGL, MSSCTO, MSSREJ, and MSSSHT normally not dumpable.
; UPD ID= 75, RIP:<7.MONITOR>PHYMVR.MAC.3,  12-Aug-87 14:49:19 by MCCOLLUM
;TCO 7.1037 - Some SCAMPI routine have changed names. Fix the CALLs.
; *** Edit 7357 to PHYMVR.MAC by RASPUZZI on 22-Aug-86
; Remove routine GAPRID since the processor serial number is already in APRSER
; and make all CALLs to GAPRID refer to that resident location. 
; *** Edit 7211 to PHYMVR.MAC by GRANT on 18-Dec-85
; Add CI counters for WATCH 
; UPD ID= 2323, SNARK:<6.1.MONITOR>PHYMVR.MAC.58,  20-Aug-85 13:53:50 by LOMARTIRE
;More TCO 6.1.1334 - Remove MSSCFS BUGHLT since this is a normal case which
;can happen.  This is not a problem as long as we reject incoming connection 
;attempts at startup until there is a CFS connection established.
; UPD ID= 2161, SNARK:<6.1.MONITOR>PHYMVR.MAC.56,   5-Jun-85 10:41:45 by MCCOLLUM
;TCO 6.1.1406  - Update copyright notice.
; UPD ID= 2114, SNARK:<6.1.MONITOR>PHYMVR.MAC.55,   4-Jun-85 13:34:06 by WAGNER
;TCO 6.1.1423 - *** PERFORMANCE *** Dont let MSSCHK get called at LV8CHK
; UPD ID= 2019, SNARK:<6.1.MONITOR>PHYMVR.MAC.54,  28-May-85 12:09:31 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1924, SNARK:<6.1.MONITOR>PHYMVR.MAC.53,   7-May-85 21:35:44 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1861, SNARK:<6.1.MONITOR>PHYMVR.MAC.52,   1-May-85 16:21:23 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1842, SNARK:<6.1.MONITOR>PHYMVR.MAC.51,  30-Apr-85 11:05:39 by MCCOLLUM
;TCO 6.1.1238 - Fix BUG. documentation
; UPD ID= 1782, SNARK:<6.1.MONITOR>PHYMVR.MAC.50,  23-Apr-85 09:57:37 by LOMARTIRE
;TCO 6.1.1334 - Reject an incoming connection if no CFS activity detected
;Also, change MSSCFS into a BUGHLT to try to catch the problem
; UPD ID= 1612, SNARK:<6.1.MONITOR>PHYMVR.MAC.49,  11-Mar-85 09:51:43 by GRANT
;TCO 6.1.1245 - Add routine MSSSVD
; UPD ID= 1496, SNARK:<6.1.MONITOR>PHYMVR.MAC.48,  11-Feb-85 08:43:17 by GRANT
;TCO 6.1.1183 - Return MSCPX4 instead of MSCPX1 when not initialized
; UPD ID= 1449, SNARK:<6.1.MONITOR>PHYMVR.MAC.47,   1-Feb-85 14:18:19 by LOMARTIRE
;Add new symbols to describe the priority used by SC.SMG
; UPD ID= 1352, SNARK:<6.1.MONITOR>PHYMVR.MAC.46,  16-Jan-85 16:43:58 by MOSER
;TCO 6.1.1139 - *PERFORMANCE* - CHANGE PSKED REFS TO PSKD1
; UPD ID= 1306, SNARK:<6.1.MONITOR>PHYMVR.MAC.45,  10-Jan-85 17:33:09 by MOSER
;TCO 6.1.1128 - FIX A BUG WITH WRITE LOCKED DRIVES
; UPD ID= 1303, SNARK:<6.1.MONITOR>PHYMVR.MAC.44,  10-Jan-85 16:58:33 by MOSER
;TCO 6.1.1126 - REMOVE MSSGON AND SELECTIVLY DO MSSSHT 
; UPD ID= 1240, SNARK:<6.1.MONITOR>PHYMVR.MAC.43,  28-Dec-84 09:35:54 by GRANT
;TCO 6..1097 - In MSXSCC, use CITIMR instead of DBUGSW and make the timeout value very large.
; UPD ID= 1135, SNARK:<6.1.MONITOR>PHYMVR.MAC.42,  28-Nov-84 17:59:18 by MOSER
;ADD MODEL BYTE 8 FOR T-20 SERVER TO CONFORM TO 1.2 OF MSCP SPEC
; UPD ID= 1057, SNARK:<6.1.MONITOR>PHYMVR.MAC.41,  13-Nov-84 09:05:52 by LOMARTIRE
;Use new sending priority symbols in SC.SMG calls.
;Remove MESPRI and replace with KLPMED.
; UPD ID= 1004, SNARK:<6.1.MONITOR>PHYMVR.MAC.40,   7-Nov-84 16:42:07 by MOSER
;TCO 6.2271 - FIX UNIT NUMBER CALC TO USE RELATIVE UNIT NUMBERS
; UPD ID= 5022, SNARK:<6.MONITOR>PHYMVR.MAC.39,  26-Oct-84 23:08:55 by MOSER
;FIX RESTRICT TO NOT ALLOW
; UPD ID= 4954, SNARK:<6.MONITOR>PHYMVR.MAC.38,  18-Oct-84 14:39:53 by MOSER
;LOOK AT INSKED BEFORE NSKED - PUT SCPAK UNDER DEBUG - MOVE MSSBCM
; UPD ID= 4826, SNARK:<6.MONITOR>PHYMVR.MAC.37,  17-Sep-84 10:43:46 by PURRETTA
;Upate copyright notice
; UPD ID= 4579, SNARK:<6.MONITOR>PHYMVR.MAC.36,  23-Jul-84 09:28:21 by HALL
;MSXABT - add index register to SETONE of MSABT
;CMDTMO - add index register to SETONE of MSCTO
; UPD ID= 4498, SNARK:<6.MONITOR>PHYMVR.MAC.35,  12-Jul-84 19:54:44 by LOMARTIRE
;REWORK CALLBACK HANDLING.  REPLACE .SSCBD WITH .SSDDG (DROPPED DATAGRAM)
;CODE FOR AC CHANGE FOR .SSDGR/.SSMGR CALLBACKS.  REMOVE .SSMNT AND .SSNWO.
; UPD ID= 4493, SNARK:<6.MONITOR>PHYMVR.MAC.34,  12-Jul-84 16:48:29 by MOSER
;SC.MAP BYTES NOT WORDS - ZERO BUFFERS AGAIN - REPORT BAD COMMANDS ALWAYS
; FIX RETRY OF FAILING COMMAND - INCREASE CONNECTION TABLE SIZE FOR BIGGER CFS
; UPD ID= 4425, SNARK:<6.MONITOR>PHYMVR.MAC.33,   3-Jul-84 14:27:09 by LOMARTIRE
;MAKE CALL TO SC.RCD PASS IN THE ADDRESS OF THE ARGUMENT BLOCK.
;OBTAIN BLOCK FROM FREE SPACE SINCE SC.RCD NO LONGER DOES SO.
;ALSO, OBTAIN BLOCK FOR SC.CSP FROM FREE SPACE AND CALL RELRES TO RELEASE.
; UPD ID= 4345, SNARK:<6.MONITOR>PHYMVR.MAC.32,  15-Jun-84 13:50:28 by LOMARTIRE
;PASS ADDRESS OF DATA BLOCK TO SC.CSP.  DO NOT CALL RELRES ANYMORE.
; UPD ID= 4319, SNARK:<6.MONITOR>PHYMVR.MAC.31,  11-Jun-84 10:46:50 by LOMARTIRE
;REMOVE MSSCSP AND MSSSLL BUGCHKS - THEY ARE NO LONGER NEEDED
; UPD ID= 4295, SNARK:<6.MONITOR>PHYMVR.MAC.30,   4-Jun-84 14:07:04 by HAUDEL
;CHANGE CALLING CONVENTIONS FOR SC.MAP, DESCRIPTOR BLOCK HAS NEW FORMAT.
; UPD ID= 4282, SNARK:<6.MONITOR>PHYMVR.MAC.29,   1-Jun-84 12:20:38 by LOMARTIRE
;USE SC.NOD INSTEAD OF SC.SBI AT HITHRE
; UPD ID= 4200, SNARK:<6.MONITOR>PHYMVR.MAC.28,   9-May-84 13:42:53 by MOSER
;USE NEW PHYSIO ENTRY IOSIO
;REPLACE CALL TO SC.ABT WITH SC.DIS
;FIX MSSRL0 - ENHANCE CLENUP
; UPD ID= 4095, SNARK:<6.MONITOR>PHYMVR.MAC.27,  18-Apr-84 16:34:26 by MOSER
;ANOTHER BUG IN PREVIOUS
; UPD ID= 4087, SNARK:<6.MONITOR>PHYMVR.MAC.26,  17-Apr-84 09:39:32 by MOSER
;FIX A BUG IN PREVIOUS
; UPD ID= 4080, SNARK:<6.MONITOR>PHYMVR.MAC.25,  12-Apr-84 15:01:50 by MOSER
;DON'T CALL CHKOFL DURING ATTENTION BROADCAST - NO Q3
; UPD ID= 4008, SNARK:<6.MONITOR>PHYMVR.MAC.24,  28-Mar-84 22:32:54 by MOSER
;MAKE SERVER MORE TUNABLE
; BETTER ADDITIONAL DATA TO MSSREJ
; TURN ON CFS COORDINATION
; UPD ID= 3880, SNARK:<6.MONITOR>PHYMVR.MAC.23,   7-Mar-84 21:47:14 by MOSER
; CHANGE BUGxxx NAME TO CONFORM TO NEW CONVENTIONS
; UPD ID= 3819, SNARK:<6.MONITOR>PHYMVR.MAC.22,  29-Feb-84 17:14:18 by MOSER
;COUNT RETRIES SEPERATE FROM ORIGIONAL COMMANDS
; UPD ID= 3774, SNARK:<6.MONITOR>PHYMVR.MAC.21,  28-Feb-84 10:26:30 by MOSER
;AQUIRE IO PAGES AS NEEDED. PREVENT MASSIVE PAGE LOCKDOWN.
; DETECT ILLEGAL STATE IF RETURNING QUEUED COMMAND THAT ISN'T QUEUED
; GET A NEW LISTNER AFTER SC.REJ
; INTERLOCK WITH CFS TO PREVENT TRASHED DISKS. ** CURRENTLY SUPPRESSED **
; ONLY CHECK STATE STUFF ONCE/SECOND
; FIX CONNECTION MANAGEMENT WHEN STIAC COMMAND TIMES OUT
; USE .RESP1 WHEN GETTING FREE SPACE
; UPD ID= 3713, SNARK:<6.MONITOR>PHYMVR.MAC.20,  21-Feb-84 13:00:23 by CDUNN
;Change process names to use a 16 byte 8 bit ASCII string. Also change calls 
;to SC.CON and SC.LIS to pass the address of the string, not a byte pointer.
; UPD ID= 3687, SNARK:<6.MONITOR>PHYMVR.MAC.19,  13-Feb-84 12:58:33 by MOSER
;FIX BUGS WHEN IO COMMAND HAS ERRORS. FIX ABORT TOO.
; UPD ID= 3664, SNARK:<6.MONITOR>PHYMVR.MAC.18,   7-Feb-84 18:22:37 by MOSER
;REPORT OFFLINE AND AVAILABLE CORRECTLY TO DRIVER
; UPD ID= 3658, SNARK:<6.MONITOR>PHYMVR.MAC.17,   7-Feb-84 14:34:22 by MOSER
;VARIOUS FIXES FOR ONLINE / OFFLINE TRANSITIONS
; UPD ID= 3625, SNARK:<6.MONITOR>PHYMVR.MAC.16,   1-Feb-84 17:55:54 by MOSER
; FIX A BUG IF NO IORBS
; CORRECTLY COUNT PACKETS IN USE.
; UPD ID= 3603, SNARK:<6.MONITOR>PHYMVR.MAC.15,  31-Jan-84 13:08:43 by MOSER
;ADD TMON FUNCTIONS
; UPD ID= 3566, SNARK:<6.MONITOR>PHYMVR.MAC.14,  27-Jan-84 15:03:08 by MOSER
;RETURN FREE SPACE AFTER SUCCESSFUL SC.CSP
; UPD ID= 3542, SNARK:<6.MONITOR>PHYMVR.MAC.13,  25-Jan-84 19:19:13 by MOSER
;MOVE SOME STORAGE TO RSEs IN STG.
; FIX A BUG IN ALLOW/RESTRICT OF A CI DISK.
; CHANGE ALLOW AND RESTRICT TO USE NEW FORMAT.
; WORK AROUND SC.CSP RETURNING WRONG VALUES.
; ADD "TRANSIENT OFFLINE" LOGIC.
; USE CORRECT UC.OLB BITS.
; USE NEW FORMAT FOR SC.MAP.
; UPD ID= 3500, SNARK:<6.MONITOR>PHYMVR.MAC.12,  20-Jan-84 17:05:47 by MOSER
; UPD ID= 3495, SNARK:<6.MONITOR>PHYMVR.MAC.11,  20-Jan-84 11:12:59 by CDUNN
;More TCO 6.1127 - Update call to SC.LIS to remove buffer arguments
; UPD ID= 3451, SNARK:<6.MONITOR>PHYMVR.MAC.10,  12-Jan-84 16:47:09 by MOSER
;WORK AROUND SCA LOSING LISTNER.
;FIX BUG IN SCFSD TO PREVENT SVILST. MAKE CHANGES FOR PERFORMANCE TESTING.
;MAKE PERIODIC CHECK RACE FREE. CHANGE ILSTAT INTO A BUGHLT. GIVE ERROR
; STATUS IF IOERR0 BUGCHK. CHANGE ORDER OF CONNECTION SHUTDOWN.
; MOVE INDICATION OF BAD COMMAND TO BUGCHK ON ALL ERRORS.
; UPD ID= 3354, SNARK:<6.MONITOR>PHYMVR.MAC.6,  21-Dec-83 08:26:33 by PURRETTA
;Fix a typeo
; UPD ID= 3351, SNARK:<6.MONITOR>PHYMVR.MAC.5,  20-Dec-83 14:49:55 by MOSER
;FIX VARIOUS BUGS. INSTALL PARANOIA CODE FOR INITIAL LOADTEST. 
; UPD ID= 3322, SNARK:<6.MONITOR>PHYMVR.MAC.4,  14-Dec-83 17:31:00 by MOSER
;RESTRICT/ALLOW CHANGES. ENFORCE US.CIA. FIX RANDOM BUGS.
; UPD ID= 3264, SNARK:<6.MONITOR>PHYMVR.MAC.3,   6-Dec-83 14:58:01 by MOSER
;LOTS OF FIXES AND DEBUGGING STUFF
; UPD ID= 3191, SNARK:<6.MONITOR>PHYMVR.MAC.2,  18-Nov-83 09:11:15 by CDUNN
;More TCO 6.1127 - Change calls to SC.SMG to conform to new calling sequence

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


	SEARCH PROLOG,PHYPAR,SCAPAR,MSCPAR

	TTITLE (PHYMVR,PHYMVR,< - MSCP SERVER>)
	SUBTTL T. MOSER 2-FEB-83
	Subttl	Table of Contents

;		     Table of Contents for PHYMVR
;
;				  Section		      Page
;
;
;    1. Comments . . . . . . . . . . . . . . . . . . . . . . .   3
;    2. Macros . . . . . . . . . . . . . . . . . . . . . . . .   4
;    3. Externs  . . . . . . . . . . . . . . . . . . . . . . .   5
;    4. Storage  . . . . . . . . . . . . . . . . . . . . . . .   6
;    5. Initialization . . . . . . . . . . . . . . . . . . . .   9
;    6. Periodic Check . . . . . . . . . . . . . . . . . . . .  10
;    7. SCA Related Routines . . . . . . . . . . . . . . . . .  13
;    8. MSCP Commands  . . . . . . . . . . . . . . . . . . . .  24
;    9. IORB Interrupt Service . . . . . . . . . . . . . . . .  34
;   10. Subroutines  . . . . . . . . . . . . . . . . . . . . .  37
;   11. CFS Interface  . . . . . . . . . . . . . . . . . . . .  59
;   12. End of PHYMVR  . . . . . . . . . . . . . . . . . . . .  61
	SUBTTL Comments
REPEAT 0,<

 PHYMVR IS THE TOPS-20 MSCP SERVER. IT EMULATES AN HSC-50 FOR MASSBUS DISKS.

 THE SERVER MAKES CERTAIN ASSUMPTIONS WHICH ARE NECESSARILY TRUE FOR ITS 
 OPERATION THEY ARE.

 1. ALL SCA CALLBACKS HAPPEN AT INTERRUPT LEVEL AND THEREFORE 2 CALLBACKS 
    CANNOT HAPPEN AT THE SAME TIME.

 2. THE INTERRUPT LEVEL FOR CI INTERRUPTS IS THE SAME AS THE INTERRUPT LEVEL 
    FOR MASSBUS (PHYSIO) INTERRUPTS

 3. SCHEDULER CALLS (PERIODIC CHECK) IS NOT AT INTERRUPT LEVEL AND CODE
    MUST BE PROTECTED FROM INTERRUPTS DURING PERIODIC CHECK.

 4. ACTUALLY AN ASPECT OF 3. NO SCHEDULER CALLS WILL HAPPEN DURING INTERRUPT
    PROCESSING.

 5. THE RPLQ IS NOT PROTECTED AT ALL INTERRUPT LEVELS (IF THIS CHANGES IT WOULD
    SIMPLIFY THINGS SOMEWHAT) BUT IS PROTECTED AT SCHEDULER CALLS INTO THE 
    SERVER AND WHEN THE SYSTEM IS NOT EITHER NOSKED OR INSKED. IT ALSO ASSUMES
    THAT THE RPLQ IS RACE FREE WHEN RUNNING THE NULL JOB (NULJBF<>0)

 6. DISK DRIVES WHICH ARE OFFLINE (US.OFS SET IN UDBSTS) BUT WHICH HAVEN'T GONE
    THROUGH THE MSCOFL CODE (FROM PHYOFL IN PHYSIO) ARE "TRANSIENTLY OFFLINE"
    AND ARE NOT TREATED AS OFFLINE TO THE DRIVERS. THIS ELIMINATES MUCH
    OVERHEAD AND IS A TREMENDOUS PERFORMANCE WIN WHEN DUAL PORTED DRIVES ARE
    PRESENT.

 REGISTER CONVENTIONS USED HEREIN:

 Q1 - ADDRESS OF COMMAND BEING PROCESSED
 Q2 - ADDRESS OF END PACKET BUFFER
 Q3 - ADDRESS OF SCDB FOR THE CONNECTION

 P1-P4 - PHYSIO REGISTER CONVENTIONS

>
	SUBTTL Macros
;
; MACRO TO GENERATE ERROR INDICATOR ACCORDING TO MSCP SPEC
;
; USE BADCMV(FIELD) TO PLACE ERROR INDICATOR (NOT BYTE SWAPPED) IN T1
; FIELD IS THE COMMAND OFFSET FOR THE FIELD OF THE COMMAND WHICH WAS IN ERROR
;
DEFINE BADCMV(FIELD)<
	MOVX T1,ST.CMD+^D256*<FIELD-P.CRF>
>
;
; MACRO TO STORE SCA ERROR INFORMATION IN SCDB
; USE SCAERR(OP) AFTER CALLS TO SCA WHICH RETURN +1 TO INDICATE AN ERROR
; OP IS ANY INSTRUCTION TO PERFORM AFTER LOGGING THE ERROR
;
DEFINE SCAERR(OP)<
	JRST [MOVEM T1,.SVSCE(Q3)
	      MOVEI T1,.
	      SUBI T1,1
	      MOVEM T1,.SVSCL(Q3)
	      MOVE T1,.SVSCE(Q3)
	      OP
	      JRST .+1]
>
	SUBTTL Externs

EXTERN SCDBTB			;LOCAL EXTERNS
EXTERN SVCMDC
EXTERN SVCMRT
EXTERN SVSCAC
EXTERN SVIORB

EXTERN MSSMBF
EXTERN NCCWS
EXTERN CCWLST
EXTERN SVIRLN
EXTERN NSVIRB
EXTERN CFSNUM
EXTERN SVRDRV
EXTERN SVRTMX
EXTERN SVRTMV
EXTERN SVRTMI
EXTERN MSSNCH
EXTERN MSSLCH
	SUBTTL Storage

HIBYT:	POINT 16,T1,19		;BYTE POINTERS FOR NORMALIZED 16 BIT BYTES
LOBYT:	POINT 16,T1,35

MSSMSC==2			;MINIMUM SEND CREDIT IS 2 (FOR BROADCASTS
				; AND GCS END)
MSSMRC==1			;MINIMUM RECIEVE CREDIT IS 1 (FOR GCS)

; MSCP SERVER STORAGE

RSI SVSTSW,<0>			;MSCP SERVER STATUS WORD
	DEFSTR SVSINF,SVSTSW,0,1 ;INITIALIZATION FLAG
	DEFSTR SVSILB,SVSTSW,1,1 ;LISTEN BUGINF HAS BEEN ISSUED
	DEFSTR SVSLIS,SVSTSW,2,1 ;OK TO OPEN A LISTNER
RS(SVSLSX,1)			;MSCP SERVER LISTNER INDEX (-1 IF NONE)
RS(SRVCHK,1)			;MSCP SERVER CHECK FLAG
RS(SRVCKT,1)			;TIME TO CHECK STATES, LISTNER AND BROADCAST
RS(SVIRBH,1)			;MSCP SERVER IORB LIST HEADER
RS(SVBDKN,1)			;MSCP SERVER COUNT OF BROADCASTS TO DO
;
; SERVER STATISTICS
;
RS(SVILCM,1)			;COUNT OF ILLEGAL (ERROR) COMMANDS
RS(SVLCMD,1)			;LAST COMMAND
RS(SVPKIU,1)			;PACKETS IN USE
RS(SVMKIU,1)			;MAX PACKETS
RS(SVCMIU,1)			;NUMBER OF COMMANDS BEING HANDLED
RS(SVMCIU,1)			;MAXIMUM COMMANDS EVER HANDLED AT ONCE
RS(SVIPIU,1)			;IO PAGES USED
RS(SVMPIU,1)			;MAX IO PAGES EVER USED
RS(SVBKNS,1)			;TIMES BLOCKED FOR NOSKED EVENTS
; SERVER CONNECTION DATA BLOCK (SCDB) -- POINTED TO BY SCDBTB

.SVCIS==0			;CONNECTION STATUS
 DEFSTR(SVSTA,.SVCIS,5,6)	;CONNECTION STATE
 SCLIS==0			;NULL OR LISTENING. NOTE: MUST BE STATE 0
 SCWOK==1			;WAITING FOR OK TO SEND
 SCOKS==2			;OK TO SEND
 SCDIS==3			;SHUTDOWN - DISCONNECT (SCA FUNCTION .SSRID)
  STFSS==SCDIS			;FIRST SHUTDOWN STATE
 SCNOF==4			;SHUTDOWN - NODE OFFLINE (SCA FUNCTION .SSNWO)
 SCPBC==5			;SHUTDOWN - PORT ERROR (SCA FUNCTION .SSPBC)
 SCFSD==6			;SHUTDOWN - DUE TO INTERNAL ERROR OR PROTOCAL
 MC.ATN==1B6			;ENABLE ATTENTION MESSAGES
 MSKSTR(MCATN,.SVCIS(Q3),MC.ATN)
.SVCID==1			;CONNECT ID
.SVTMO==2			;SERVER TIMEOUT TIME
.SVTMV==3			;SERVER TIMEOUT VALUE
.SVCMD==4			;HEAD OF COMMAND QUEUE
.SVSCL==5			;LAST SCA ERROR LOCATION
.SVSCE==6			;LAST SCA ERROR CODE
.SVCME==7			;TAIL OF COMMAND QUEUE
LENSVD==.SVCME+1		;LENGTH OF SCDB
; QUEUED COMMAND FIELDS. RESIDE IN INVISIBLE SYSAP AREA OF PACKETS

.QCRTN==-C%BINV			;RETURN ADDRESS FOR COMMAND
.QCNXT==.QCRTN+1		;NEXT COMMAND
.QCLST==.QCNXT+1		;PREVIOUS COMMAND
.QCPID==.QCLST+1		;VIRTUAL PAGE ADDRESS FOR IO
.QCSTS==.QCPID+1		;STATUS AND RETRY COUNT
 MS.COQ==1B0			;COMMAND IS QUEUED
 MSKSTR(MSCOQ,.QCSTS,MS.COQ)
 MS.ABT==1B1			;COMMAND IS ABORTED
 MSKSTR(MSABT,.QCSTS,MS.ABT)
 MS.CTO==1B2			;COMMAND IS TIMED OUT
 MSKSTR(MSCTO,.QCSTS,MS.CTO)
 DEFSTR(QCSTS,.QCSTS,8,6)	;STATE FIELD
 DEFSTR(QCENL,.QCSTS,17,9)	;END PACKET LENGTH
 MINSTA==0			;MINIMUM STATE VALUE
 STCMD==0			;TREAT AS INCOMING COMMAND
 STWAE==1			;WAITING TO ALLOCATE END
 STWSR==2			;WAITING TO SEND DATA (RETRYABLE)
 STWRR==3			;WAITING TO REQUEST DATA (RETRYABLE)
  RTYSTA==STWRR			;MAXIMUM STATE FOR RETRY OPERATIONS
 STWSE==4			;WAITING TO SEND END PACKET (IO ONLY) STATE
 STWSD==5			;WAIT FOR SEND DATA STATE
  DATSTA==STWSD			;FIRST DATA OPERATION STATE
 STWRD==6			;WAIT FOR RECIEVE DATA STATE
 STIAC==7			;IORB ACTIVE (IO ONLY) STATE
 STWSB==10			;WAITING TO SEND BUFFER (IO ONLY) STATE
 STWRB==11			;WAITING TO REQUEST BUFFER (IO ONLY) STATE
 MAXSTA==STWRB			;MAX STATE VALUE
 DEFSTR(QCCNT,.QCSTS,35,18)	;RETRY COUNT

.QCIORB==.QCSTS+1		;IORB ADDRESS
.QCDBD==.QCIORB+1		;DATA BUFFER DESCRIPTOR
.QCTMO==.QCDBD+1		;TIMEOUT TIME
.QCDBG==.QCTMO+1		;DEBUGGING WORD
.QCRT2==.QCDBG+1		;SCA RETURN ADDRESS FOR QUEUED COMMANDS
   IFLE <.MHUDA-.QCRT2>,<PRINTX ?QUEUED COMMAND INFO OVERLAPS MESSAGE>

;IORB FIELD DEFINITIONS

 DEFSTR(IRBCID,IRBLEN,5,6)	;CONNECTION INDEX
 DEFSTR(IRBCMD,IRBLEN,35,30)	;QUEUED COMMAND ADDRESS

; Note: The process names for listening are required by SCA to be 16 byte 8 
;bit ASCII strings.

CONDNM:	ASCI8 	(<T-20$DISK       >)
SRVDNM:	ASCI8	(<MSCP$DISK       >)
	SUBTTL Initialization

;MSSINI - INITIALIZE MSCP SERVER (CALLED FROM SCAMPI)
; RETURN +1: ALWAYS, SERVER STARTED
; 
MSSINI::JN SVSINF,,R		;IF INITIALIZED, JUST RETURN

; INITIALIZE IORB LIST

	MOVEI T1,SVIRLN*<SVRDRV*NSVIRB-1>+SVIORB ;T1 POINTS TO END OF LIST
	SETZM (T1)		;CLEAR END OF LIST
MSSIN1:	CAIN T1,SVIORB		;DONE? (AT BEGINNING)
	JRST MSSIN2		;YES
	MOVE T2,T1		;NO - SAVE SUCCESSOR
	SUBI T1,SVIRLN		;MOVE BACKWARD IN LIST
	MOVEM T2,(T1)		;STORE FOREWARD POINTER
	JRST MSSIN1		;DO MORE
MSSIN2:	MOVEM T1,SVIRBH		;STORE HEAD OF LIST
	SETZM SCDBTB		;ZERO CONNECTION TABLE
	XMOVEI T2,SCDBTB	;START OF BLT
	XMOVEI T3,SCDBTB+1	;DESTINATION
	MOVEI T1,CFSNUM-1	;NUMBER OF WORDS
	EXTEND T1,[XBLT]	;ZERO TABLE

	SETOM SVSLSX		;MARK NO LISTNER

	SETZM SVIPIU		;INIT STATISTICS
	SETZM SVMPIU
	SETZM SVPKIU
	SETZM SVMKIU
	SETZM SVCMIU
	SETZM SVMCIU
	SETZM SVMPIU
	SETZM SVILCM
	SETZM SVBKNS

	SETONE SVSINF		;MARK INITIALIZED
	CALLRET MSSCHK		;FINISH WITH A CHECK
	SUBTTL Periodic Check

;MSSCHK - PERIODIC CHECK
; 
; THIS PERFORMS 4 FUNCTIONS
; 1. IT CHECKS FOR A NODE TIMEOUT. IF WE DO NOT RECIEVE A MESSAGE FROM A NODE
;    WITHIN THE TIMEOUT INTERVAL WE SHUT IT DOWN AND RESYNC
;
; 2. IT RETRIES ALL COMMANDS AND EVENTUALLY TIMES THEM OUT. IT SHOULD NEVER
;    BE NECESSARY TO REMOVE A COMMAND WHICH HAS TIMED OUT BUT WE
;    DO THIS TO PREVENT ANY STRANGE ERRORS LEAVING COMMANDS QUEUED FOREVER
;
; 3. IT BROADCASTS AVAILABLE MESSAGES FOR UNITS WHICH HAVE RECENTLY COME ONLINE
;
; 4. IT GETS A NEW LISTNER IF WE DON'T HAVE ONE
;
; CALLED FROM SCHED PERIODICALLY
;	CALL MSSCHK		;()
; RETURN +1: ALWAYS
;
	RESCD

MSSCHK::JSP T1,[SETOM SRVCHK	;FLAG IN PERIODIC CHECK
		CIOFF		;NO INTERRUPTS WHILE AT SCHEDULER LEVEL
		CALL (T1)	; RETURN TO HERE
		TRNA		; IF +1 RETURN
		AOS -1(P)	; PRESERVE +2 NESS
		CION		; ALLOW INTS AGAIN
		SETZM SRVCHK	;NO LONGER IN CHECK
		RET]		; AND RETURN TO CALLER
	SAVEQ
	MOVEI T1,MSSNCH		;NEXT TIME
	MOVEM T1,MSSTIM		;SAVE IT
	JE SVSINF,,R		;IF NOT INITIALIZED FORGET CHECK
	MOVSI Q1,-CFSNUM	;SIZE OF HOST TABLE
MSSCH1:	SKIPN Q3,SCDBTB(Q1)	;ADDRESS OF SCDB
	JRST CHKNXT		;NONE. INACTIVE
	LOAD T2,SVSTA,(Q3)	;GET STATE
	CAIN T2,SCLIS		;LISTENING?
	JRST CHKNXT		;LISTNER. DO NEXT ONE
	MOVE T3,.SVCMD(Q3)	;COMMAND LIST HEAD
	CAIL T2,STFSS		;SHUTDOWN?
	JUMPE T3,[SETZ T1,	;SHUTDOWN AND EMPTY. CAN BE FREED UP
		  EXCH T1,SCDBTB(Q1) ;GET ADDRESS IN T1, MARK AS FREE
		  CALL RELRES	;RETURN FREE SPACE (T1/)
		  JRST CHKNXT]	;CHECK NEXT
	CAIE T2,SCOKS		;CONNECTION OPEN?
	JRST CHKNXT		;NO. DO NEXT ONE
	MOVE T2,TODCLK		;GET NOW
	SKIPN T3,.SVTMV(Q3)	;GET TIMEOUT VALUE IF ANY
	JRST CHKCOQ		;NO TIMEOUT SET. SEE IF COMMANDS ON QUEUE
	ADD T3,.SVTMO(Q3)	;ADD TIME OF LAST MESSAGE
	CAMG T3,TODCLK		;TIMED OUT?
	JRST CHKCOQ		;NO. SEE IF COMMANDS ARE ON QUEUE
	MOVE T2,.SVCID(Q3)	;GET CONNECT ID
	CALL MSSFSD		;SHUT IT DOWN (T2/)
	JRST CHKNXT		;AND DO NEXT COMMAND

; HERE TO CHECK FOR PENDING COMMANDS AND RETRY THEM

CHKCOQ:	MOVE T2,.SVCID(Q3)	;GET CONNECT ID
	CALL CRDTA0		;RETRY ALL QUEUED COMMANDS (T2/)
	MOVE T1,TODCLK		;GET NOW
	CAMG T1,SRVCKT		;TIME TO CHECK STATE?
	JRST CHKNXT		;NOT YET.
	LOAD T1,SVSTA,(Q3)	;GET STATE
	CAIE T1,SCOKS		;OK TO SEND?
	JRST CHKNXT		;NO, DON'T CHECK FOR OPEN
	MOVE T1,[XWD .RESP1,.RDLEN]  ;PRIORITY,,LENGTH OF FREE SPACE
	MOVEI T2,.RESGP		;GET SPACE FROM RESIDENT FREE POOL
	CALL ASGRES		;(T1,T2/T1) OBTAIN BLOCK
	 SCAERR <JRST CHKNXT>	;ERROR - COULD NOT GET A FREE SPACE BLOCK
	MOVEM T1,T2		;SAVE BLOCK ADDRESS
	MOVE T1,.SVCID(Q3)	;GET CID AGAIN
	BLCAL. (SC.SPL,<<T1>,<T2>>) ;[7.1037]GET CONNECT STATE
	 SCAERR <JRST [	MOVE T1,T2   ;GET BLOCK ADDRESS
			CALL RELRES  ;(T1) RETURN BLOCK TO FREE POOL
			JRST CHKNXT]>;DO NEXT
	LOAD T3,CDCST,(T2)	;GET STATE CODE
	CAIE T3,.CSOPN		;IS IT OPEN?
	JRST [	MOVE T1,T2	;GET BLOCK ADDRESS
		CALL RELRES	;(T1) RETURN BLOCK TO FREE POOL
		CALL ILSTAT]	;SCA ERROR
	MOVE T1,T2		;GET BLOCK ADDRESS
	CALL RELRES		;(T1) RETURN BLOCK TO FREE POOL
CHKNXT:	AOBJN Q1,MSSCH1		;DO NEXT
; BROADCAST STATUS OF NEW UNITS. COUNT OF UNITS IS IN BDKSTC. UNITS WHICH
; NEED TO BE BROADCAST HAVE US.BDK SET IN THEIR UDB THIS IS DONE ONCE EVERY
; SECOND

	MOVE T1,TODCLK		;GET NOW
	CAMG T1,SRVCKT		;TIME TO CHECK STATE?
	RET			;NOT YET ALL DONE.
	ADDI T1,MSSLCH		;NEXT TIME
	MOVEM T1,SRVCKT		;SAVE IT.
	SKIPN SVBDKN		;HAVE TO BROADCAST?
	JRST CHKLSN		;NO. CHECK LISTNER STATUS
	SETZB Q2,SVBDKN		;ASSUME ALL WILL SUCCEED. SETUP Q2 AS KONT
	SETOB Q1,Q3		;NO CHANNEL NO UNIT START WITH FIRST
BDKCK1:	DMOVE T1,Q1
	MOVE T3,Q3
	CALL ADVCKS		;GET UNIT
	 JRST CHKLSN		;NO MORE UNITS. CHECK LISTNER STATUS
	DMOVE Q1,T1		;SAVE T1-T3
	MOVE Q3,T3
	MOVE T1,UDBSTS(T4)	;GET BITS
	TXNE T1,US.CIA		;AVAILABLE?
	TXNN T1,US.BDK		;NEED TO BROADCAST?
	JRST BDKCK1		;NO TO EITHER, SKIP IT
	CALL MSXATA		;BROADCAST AVAILABILITY
	JRST BDKCK1		;DO MORE

; GET A LISTNER IF WE NEED ONE

CHKLSN:	SKIPGE Q3,SVSLSX	;IS THERE A LISTNER?
	CALLRET LISTEN		;NO LISTNER. TRY FOR ONE
	CALL SETQ3I		;GET SCDB
	 JRST SCDBBG		;NONE!
	MOVE T1,[XWD .RESP1,.RDLEN]  ;PRIORITY,,LENGTH OF FREE SPACE
	MOVEI T2,.RESGP		;GET SPACE FROM RESIDENT FREE POOL
	CALL ASGRES		;(T1,T2/T1) OBTAIN BLOCK
	 SCAERR <RET>		;ERROR - COULD NOT GET A FREE SPACE BLOCK
	MOVEM T1,T2		;SAVE BLOCK ADDRESS
	MOVE T1,.SVCID(Q3)	;GET CID
	BLCAL. (SC.SPL,<<T1>,<T2>>) ;[7.1037]GET CONNECT STATE
	 SCAERR <JRST [	MOVE T1,T2   ;GET BLOCK ADDRESS
			CALL RELRES  ;(T1) RETURN BLOCK TO FREE POOL
			RET]>
	LOAD T3,CDCST,(T2)	;GET CONNECTION STATE
	CAIE T3,.CSLIS		;IS IT LISTENING?
	JRST [	MOVE T1,T2	;GET BLOCK ADDRESS
		CALL RELRES	;(T1) RETURN BLOCK TO FREE POOL
    		CALL ILSTAT]	; NO, SCA HAS LOST IT'S MIND
	MOVE T1,T2		;GET BLOCK ADDRESS
	CALL RELRES		;(T1) RETURN BLOCK TO FREE POOL
	RET			; YES, RETURN
	SUBTTL SCA Related Routines

;MSSSTS - SCA INTERRUPT HANDLER
; T1/ SCA FUNCTION CODE
; T2-T4/ FUNCTION DEPENDENT DATA (SEE SCAPAR OR SUBROUTINE HEADER FOR DETAILS)
;	CALL MSSSTS		;(T1,T2,T3,T4/)
; RETURN +1: ALWAYS
;
MSSSTS:	SKIPL T1		;CHECK CODE FOR LEGALITY. TOO LOW?
	CAILE T1,.SSAFT		;OR TOO HIGH?
	JRST ILLFCN		;ILLEGAL CODE FROM SCA. BETTER DIE NOW
	AOS @[EP. SVSCAC(T1)]	;COUNT SCA INTERRUPTS
	CALLRET @MSSDSP(T1)	;HOP TO IT

MSSDSP:	DTBDSP (ILLFCN)		;.SSDGR - Datagram received
	DTBDSP (NEWMES)		;.SSMGR - Message received
	DTBDSP (PRTGON)		;.SSPBC - Port broke connection
	DTBDSP (HITHRE)		;.SSCTL - Connect to listen
	DTBDSP (ILLFCN)		;.SSCRA - Connect response available
	DTBDSP (R)		;.SSMSC - Message/datagram send complete
	DTBDSP (ILLFCN)		;.SSDDG - Datagram dropped
	DTBDSP (NOCRDT)		;.SSLCL - Little credit left
	DTBDSP (ILLFCN)		;.SSNCO - Node came online
	DTBDSP (OK2SND)		;.SSOSD - OK to send data
	DTBDSP (REQDIS)		;.SSRID - Remote initiated disconnect
	DTBDSP (CRDTAV)		;.SSCIA - Credit is available
	DTBDSP (DMADON)		;.SSDMA - DMA complete

;NOCRDT - SCA INTERRUPT - LITTLE CREDIT REMAINS
; T1/ .SSLCL
; T2/ CONNECT ID
; T3/ NUMBER OF CREDITS NEEDED TO GET YOU OVER THRESHOLD
; RETURNS +1: ALWAYS
;**	NO ACTION TAKEN THIS IS A CONVIENENT DUMMY ROUTINE FOR MISC. DEBUGGING
NOCRDT:	RET
;LISTEN - OPEN A LISTNER FOR A DISK SERVER CONNECTION
;	CALL LISTEN		;()
; RETURNS +1: ALWAYS
;	MSSLSI - LISTNER INDEX OR -1 IF UNABLE TO GET ONE
;
LISTEN:	SAVEAC <Q1,Q3>
	SKIPL SVSLSX		;SHOULD BE NO LISTNER
	BUG. (HLT,MSSTML,PHYMVR,SOFT,<LISTEN - MSCP server too many listners>,,<

Cause:	The MSCP server tried to obtain a listner when one already existed.
	This indicates an inconsistency in the software.
>)
	JE SVSLIS,,R		;IF ILLEGAL NOW JUST RETURN
 	MOVSI Q1,-CFSNUM	;SIZE OF HOST TABLE
LSNLUP:	SKIPE SCDBTB(Q1)	;IS THIS ENTRY FREE?
	JRST NXTLSN		;NO, TRY NEXT
	BLCAL. (ASGRSB,<[LENSVD],[.RESP1],[.RESUP]>) ;GET SOME FREE SPACE (/T1)
	 JRST NOLIS		;NONE
	HRRZS Q1		;GET INDEX ONLY
	MOVEM T1,SCDBTB(Q1)	;SAVE ADDRESS OF CONNECTION DATA BLOCK
	MOVE Q3,T1		;SAVE ADDRESS OF SCDB

; REALLY LISTEN NOW

	BLCAL. (SC.LIS,<<.,SRVDNM>,<.,CONDNM>,[-1],<.,MSSSTS>,Q1,[MSSMSC],[MSSMRC]>) ;LISTEN
	 SCAERR <JRST NOLIS>	;FAILURE
	MOVEM Q1,SVSLSX		;SAVE LISTNER INDEX
	MOVEM T1,.SVCID(Q3)	;SAVE CONNECT ID PROVIDED BY SCA
	SETZRO SVSILB		;ISSUE BUGINF IF THIS FAILS IN THE FUTURE
	RET

NXTLSN:	AOBJN Q1,LSNLUP		;TRY THE NEXT
	PUSH P,Q1		;ERROR CODE IS LOOP COUNTER
	JRST LSNBGC		;NO MORE, ISSUE BUGCHK
NOLIS:	PUSH P,T1		;SAVE ERROR CODE
	SKIPE T1,SCDBTB(Q1)	;DO WE HAVE FREE SPACE?
	CALL RELRES		;RELEASE IT (T1)
	SETZM SCDBTB(Q1)	;DON'T LET THE ENTRY LOOK USED
LSNBGC:	POP P,T1		;GET ERROR CODE
	JN SVSILB,,R		;IF BUG ALREADY ISSUED RETURN
	 BUG.(INF,MSSCGL,PHYMVR,SOFT,<MSCP server can't get listener>,<<T1,ERROR>>,<

Cause:	The MSCP server cannot get a listener for connection requests.
	The server will continue to try to get a listener.

Data:	ERROR - Error code returned by SC.LIS
>,,<DB%NND>)			;[7.1210] 
	SETONE SVSILB		;DON'T ISSUE THIS BUGINF CONSTANTLY
	RET
;HITHRE - ACCEPT/REJECT A CONNECTION WHEN WE GET A RESPONSE TO OUR LISTEN
; T1/ .SSCTL
; T2/ CONNECT ID
; T3/ POINTER TO CONNECTION DATA FROM REMOTE SYSTEM
; RETURNS +1: ALWAYS
;	   CONNECTION ACCEPTED IF CONNECTOR WAS A KL10
;	   NEW LISTNER WILL BE SETUP IF POSSIBLE
;          CONNECTION STATE WILL BE MC.WOK (WAITING FOR OK TO SEND DATA)
;
HITHRE:	SAVEQ
	LOAD Q3,SID,T2		;GET HOST INDEX
	CAME Q3,SVSLSX		;SAME AS LISTNER INDEX
	 BUG.(HLT,MSSLNM,PHYMVR,SOFT,<MSCP server listner does not match>,,<

Cause:	The listner index does not match the known index of the listner.
>)
	CALL SETQ3		;GET SCDB ADDRESS (T2/Q3)
	 JRST SCDBBG		;NONE!
	MOVEM T2,Q1		;SAVE CONNECT ID
	MOVE T1,[XWD .RESP1,.RDLEN]  ;PRIORITY,,LENGTH OF FREE SPACE
	MOVEI T2,.RESGP		;GET SPACE FROM RESIDENT FREE POOL
	CALL ASGRES		;(T1,T2/T1) OBTAIN BLOCK
	 SCAERR <JRST R2LBAD>	;ERROR - COULD NOT GET A FREE SPACE BLOCK
	MOVEM T1,T3		;SAVE BLOCK ADDRESS
	MOVE T1,Q1		;CID IN T1
	CALL SC.NOD		;GET NODE NUMBER FOR CONNECT ID (T1/T1,T2)
	MOVE T1,T3		;GET ADDRESS OF DATA BLOCK
	BLCAL.	(SC.RCD,<<T2>,<T1>>)  ;GET CONFIGURATION DATA OF THIS NODE
	 SCAERR <JRST [	MOVE T1,T2  ;GET ADDRESS OF BLOCK
			CALL RELRES ;(T1) RETURN BLOCK TO FREE POOL
			JRST R2LBAD]>  ;REJECT.  KEEP LISTENING
	LDB T1,[POINT PKSID,.RDPCH(T2),PKPID] ;GET TYPE OF NODE
	SETZ Q1,		;ASSUME A KL
	CAIE T1,ID.KL		;A KL10?
	HRRO Q1,T1		;NO FLAG IT
	SKIPN CFSHCT		;CFS talking?
	SKIPE CFSCMC		;Or trying?
	SKIPA			;Yes, all is ok
	HRLI Q1,-2		;No, reject the attempt
	MOVE T1,T2		;GET ADDRESS OF BLOCK
	CALL RELRES		;(T1) RETURN BLOCK TO FREE POOL
	JUMPL Q1,R2LBA0		;If flagged, we do not want to talk to it

	BLCAL.(SC.ACC,<.SVCID(Q3),[0],[MSSMBF],[0]>); ACCEPT THE OVERTURE
	 SCAERR <JRST R2LBA1>	;FORGET IT
	MOVX T1,SCWOK		;NEW STATE IS WAITING FOR OK TO SEND
	STOR T1,SVSTA,(Q3)
	SETOM  SVSLSX		;CURRENTLY NO LISTNER EXISTS
	CALL LISTEN		;GET A NEW LISTENER
	RET			;AND DONE
R2LBA0:	MOVE T1,Q1		;IF A BAD PROCESSOR USE TYPE AS ERROR CODE
R2LBAD:	PUSH P,T1		;SAVE ERROR
	MOVE T1,.SVCID(Q3)	;GET CID
	CALL SC.NOD
	POP P,T3
	BUG.(INF,MSSREJ,PHYMVR,SOFT,<MSCP server rejecting connection>,<<T2,NODE>,<T1,CID>,<T3,ERROR>>,<

Cause:	The MSCP server is rejecting a connection because the connector
	cannot be identified due to an SCA failure or because the connector
	is not on a KL10 processor.

Data:	NODE - Node number
	CID - Connect ID
	ERROR -  SCA error code
>,,<DB%NND>)			;[7.1210] 
	BLCAL. (SC.REJ,<.SVCID(Q3),[0]>) ;REJECT THE CONNECTION
	 SCAERR			;REMEMBER ERROR IF ANY
	SETO T2,		;GET A -1
	EXCH T2,SVSLSX		;NO LISTNER NOW. GET INDEX
	SETZ T1,		;GET A ZERO
	EXCH T1,SCDBTB(T2)	;GET FREE SPACE POINTER
	CALL RELRES		;RELEASE FREE SPACE
	CALLRET LISTEN		;GET A NEW LISTNER
	
R2LBA1:	MOVE T3,T1		;SAVE FOR BUGCHK
	MOVE T1,.SVCID(Q3)	;GET CID AGAIN
	CALL SC.NOD		;GET NODE NUMBER
	BUG.(CHK,MSSCAC,PHYMVR,SOFT,<MSCP server can't accept connection>,<<T2,NODE>,<T1,CID>,<T3,REASON>>,<

Cause:	The MSCP server cannot accept a connection.

Data:	NODE - node number
	CID - connect ID
	REASON - reason for failure
>,R)
;MSSFSD - SERVER INITIATED (FORCED) SHUTDOWN 
;PRTGON - PORT ERROR INITIATED SHUTDOWN
;REQDIS - DRIVER WISHES TO SHUT DOWN CONNECTION
; T2/ CONNECT ID
;	CALL name		;(T2/)
; RETURNS +1: ALWAYS
;	ALL QUEUED COMMANDS ABORTED (IF IORB ACTIVE ABORT IS IN MSSIRD)
;	BUGINF ISSUED AND STATUS UPDATED
REQDIS: SKIPA T1,[SCDIS]
MSSFSD:	MOVX T1,SCFSD		;ERROR BIT
	JRST MSSSH0		;AND CONTINUE

PRTGON:	MOVX T1,SCPBC		;PORT BROKE CONNECTION
MSSSH0:	SAVEPQ			;SAVE ALL P AND Q REGS
	STKVAR <REASON>
	MOVEM T1,REASON
	LOAD Q3,SID,T2		;GET CID INDEX
	CAMN Q3,SVSLSX		;LISTNER?
	SETOM SVSLSX		;NOT ANY MORE!
	MOVE T1,T2		;GET CID
	CALL SC.NOD		;AND NODE NUMBER
	MOVE T3,REASON		;GET REASON CODE
	CALL SETQ3I		;GET POINTER TO SCDB (Q3/Q3)
	 RET			;ALREADY GONE IGNORE IT
	BLCAL.	(SC.DIS,<.SVCID(Q3),T3>) ;DISCONNECT
	 SCAERR			;IGNORE ERROR. PROBABLY ALREADY GONE
	LOAD T1,SVSTA,(Q3)	;GET CURRENT STATE
	CAIL T1,STFSS		;ALREADY SHUT DOWN?
	RET			;YES, ALL DONE
	MOVE T3,REASON
	STOR T3,SVSTA,(Q3)	;SAVE NEW STATE
	CAIE T3,SCFSD		;FORCED SHUTDOWN?
	IFSKP.
	   MOVE T3,.SVCIS(Q3)	;GET COMPLETE STATUS
	   MOVE T4,.SVSCE(Q3)	;GET ERROR CODE
	   MOVE T1,.SVCID(Q3)	;GET CID
	   CALL SC.NOD		;AND NODE
	    BUG.(INF,MSSSHT,PHYMVR,SOFT,<MSCP server shutdown node>,<<T2,NODE>,<T1,CID>,<T3,STATUS>,<T4,ERROR>>,<

Cause: 	The MSCP server was forced to shut down a node.

DATA:	NODE - node number
	CID - connect ID
	STATUS - connection status
	ERROR - last SCA error
>,,<DB%NND>)			;[7.1210] 
	ENDIF.
; MARK ALL UNITS AS OFFLINE TO CI

	MOVE P5,.SVCID(Q3)	;GET CID INDEX VALUE
	LOAD P5,SID,P5
	MOVSI	P4,-CHNN	;LOOP OVER CHANNELS
	PUSH	P,Q3		;SAVE AN AC
OFLLP1:	MOVX	T1,CS.CIP
	SKIPE	P1,CHNTAB(P4)	;CHAN EXIST?
	TDNE	T1,CDBSTS(P1)	;YES. IS IT A CI CHAN?
	JRST	OFLLP2		;YES. GET NEXT
	CALL	DGUMAP		;NO. DO INSTR FOR EACH UDB
	 CALL	OFLUDB		;INSTRUCTION TO EXECUTE
OFLLP2:	AOBJN	P4,OFLLP1	;LOOP OVER ALL CHANS

; REMOVE ALL QUEUED COMMANDS (EXCEPT THOSE AWAITING IORB COMPLETION)
	
	POP P,Q3		;RESTORE Q3
	MOVE Q2,.SVCMD(Q3)	;GET HEAD OF LIST
DEQLUP:	JUMPE Q2,R		;NO MORE COMMANDS. RETURN
	MOVE Q1,Q2		;GET ADDRESS OF COMMAND IN Q1
	MOVE Q2,.QCNXT(Q1)	;GET ADDRESS OF NEXT COMMAND FOR STEPPING
	LOAD T1,QCSTS,(Q1)	;GET STATE
	CAIN T1,STIAC		;IORB ACTIVE?
	JRST IRBDEQ		;YES, REMOVE FROM PHYSIO QUEUES
	CALL RTNCMD		;RETURN BUFFER SPACE
	JRST DEQLUP		;LOOP FOR MORE

;NOTE: THE FOLLOWING LABEL IS A PLACE HOLDER FOR REMOVAL OF AN IORB FROM
; PHYSIO QUEUES.

IRBDEQ:	JRST DEQLUP		;*** NOT IMPLEMENTED JUST LEAVE IT

; THIS IS A COROUTINE FOR DGUMAP TO OFFLINE ALL UNITS FOR THE CONNECTION
; IN ERROR

OFLUDB:	MOVE T1,BITS+<^D36-CFSNUM>(P5) ;GET BIT
	ANDCAM T1,UDBCHR(P3)	;OFFLINE IT FOR THIS PORT
	RET
;OK2SND - SCA NOTIFICATION OF OK TO SEND TO CONNECTION
; T1/ .SSOSD
; T2/ CONNECT ID
;	CALL OK2SND		;(T1,T2/)
; RETURNS +1: ALWAYS
;	STATE UPDATED TO SCOKS (BUGHLT IF STATE IS NOT SCWOK ON ENTRY)
;	CONNECTION FULLY OPEN (CONTROLLER ONLINE IN MSCP SPEC.)
;
OK2SND:	SAVEQ
	CALL SETQ3		;(T2/Q3)
	 JRST SCDBBG		;NONE!
	LOAD T3,SVSTA,(Q3)	;GET STATUS
	CAIE T3,SCWOK		;WAITING FOR THIS?
	 BUG.(HLT,MSSNWO,PHYMVR,SOFT,<OK2SND - OK to send when not waiting>,<<T2,CID>>,<

Cause:	The MSCP server received notification of OK to send from a node.
	The node in question was not flagged as waiting for an OK to send.

Data:	CID - connect ID

>)
	MOVX T3,SCOKS		;NOW OK TO SEND
	STOR T3,SVSTA,(Q3)	;SAVE IT
	MOVEI T3,^D60*^D1000	;GET 60 SECONDS IN MILLISECS
	MOVEM T3,.SVTMV(Q3)	;SAVE AS TIMEOUT VALUE
	MOVE T3,TODCLK		;GET NOW
	MOVEM T3,.SVTMO(Q3)	;AND USE AS LAST TIME WE HEARD FROM DRIVER
	RET
;CRDTAV - CREDIT IS AVAILABLE
;CRDTA0 - RETRY COMMANDS BUT NO CREDIT ENTRY POINT
;
;RETRY COMMANDS AND POTENTIALLY TIME THEM OUT. IF A COMMAND IS TIMEDOUT THE 
;CONNECTION IS CLOSED.
;
; T2/ CID
; 	CALL CRDTAV		;(T2/)
; RETURNS +1: ALWAYS COMMANDS RETRIED OR TIMEDOUT.
;
CRDTA0:	TDZA T1,T1		;ONLY DO COMMAND STATE
CRDTAV: SETO T1,		;RETRY ALL
	SAVEQ
	STKVAR <NXTCMD,ENTFLG>
	MOVEM T1,ENTFLG
	CALL SETQ3		;SETUP Q3
	 JRST SCDBBG		;NONE!
	LOAD T1,SVSTA,(Q3)	;GET COMMAND STATE. INITIAL CHECK FOR
	CAIE T1,SCOKS		;OK TO SEND
	CALL ILSTAT		;NO!
	SKIPN Q1,.SVCMD(Q3)	;ANY COMMANDS QUEUED?
	RET			;NO
;
; WE MUST CHECK THE STATE FOR OK TO SEND AFTER EACH COMMAND SINCE A COMMAND
; MAY CAUSE THE STATE TO CHANGE IF IT IS NOT SCOKS WE SHOULD SIMPLY RETURN
;
CRDTA2:	LOAD T1,SVSTA,(Q3)	;GET COMMAND STATE
	CAIE T1,SCOKS		;OK TO SEND
	RET			;GOT SHUTDOWN. RETURN NOW.
	MOVE T1,.QCNXT(Q1)	;GET NEXT COMMAND
	MOVEM T1,NXTCMD		;SAVE IT
	MOVE T1,.QCTMO(Q1)	;GET TIMEOUT TIME
	CAMLE T1,TODCLK		;PAST?
	JRST CRDTA3		;NO
	MOVE T1,TODCLK		;YES, COMPUTE NEXT TIMEOUT INTERVAL
	ADDI T1,SVRTMI
	MOVEM T1,.QCTMO(Q1)	;AND SAVE IT
	INCR QCCNT,(Q1)		;COUNT NUMBER OF TRIES
	LOAD T1,QCCNT,(Q1)	;GET COUNT
	CAILE T1,SVRTMX		;TOO MANY?
	JRST CMDTMO		;YES TIMOUT COMMAND
CRDTA3:	LOAD T2,QCSTS,(Q1)	;GET STATE
	CAIL T2,MINSTA		;CHECK STATE FOR LEGALITY. TOO SMALL?
	CAILE T2,MAXSTA		;OR TOO BIG?
	CALL ILSTAT		;ILLEGAL STATE
	SETZ Q2,		;REMEMBER NO END PACKET YET
	CAILE T2,RTYSTA		;RETRYABLE ON POLL?
	SKIPN ENTFLG		;NO, RETRY ONLY IF CREDIT AVAILABLE
	SKIPN ENTFLG		;YES, DON'T RETRY ON CREDIT AVAILABLE
	CALL @CRDTAB(T2)	;RETRY FUNCTION
CRDNXT:	SKIPE Q1,NXTCMD		;GET NEXT COMMAND TO RETRY
	JRST CRDTA2		;AND TRY IT
	RET
; HERE TO TIMEOUT COMMAND

CMDTMO:	MOVE T3,.QCSTS(Q1)
	MOVE T1,.SVCID(Q3)
	LOAD T4,QCSTS,(Q1)
	CALL SC.NOD
	TXNE T3,MS.CTO		;ALREADY TIMED OUT?
	JRST CRDNXT		;YES, MUST BE STUCK IORB DO NEXT
	 BUG.(INF,MSSCTO,PHYMVR,SOFT,<PHYMVR - Command timeout>,<<T2,NODE>,<T1,CID>,<T4,STATE>>,<

Cause:	Unknown. A command did not complete in the timeout interval.

Data:	NODE - node number
	CID - connect ID
	STATE - command state
>,,<DB%NND>)			;[7.1210] 
	SETONE MSCTO,(Q1)	;MARK COMMAND AS TIMED OUT
	CALL MSSFSD		;SHUT DOWN CONNECTION
	JRST CRDNXT

CRDTAB:	DTBDSP (NEWME0)		;STCMD - TREAT LIKE MESSAGE RECIEVED
	DTBDSP (GETEND)		;STWAE - WAITING TO ALLOCATE END
	DTBDSP (SNDDAT)		;STWSR - WAITING TO SEND DATA (RETRY)
	DTBDSP (REQDAT)		;STWRR - WAITING TO REQUEST DATA (RETRY)
	DTBDSP (ENDRTY)		;STWSE - WAITING TO SEND END ONLY
	DTBDSP (R)		;STWSD - NO ACTION
	DTBDSP (R)		;STWRD - NO ACTION
	DTBDSP (R)		;STIAC - NO ACTION
	DTBDSP (SNDDAT)		;STWSB - SEND BUFFER
	DTBDSP (REQDAT)		;STWRB - REQUEST BUFFER BE SENT
;DMADON - SERVER INITIATED DMA COMPLETE
; T1/ .SSDMA
; T2/ CONNECT ID OF CONNECTION DMA WAS DONE FOR
; T3/ 32 BIT BUFFER NAME OF DMA BUFFER
;	CALL DMADON		;(T1,T2,T3/)
; RETURNS +1: ALWAYS
;	READ - SEND END PACKET AND COMMAND IS COMPLETE
;	WRITE - CALL PHYSIO TO DO DISK WORK
;
DMADON:	SAVEQ
	CALL SETQ3		;GET INDEX TO DATA (T2/Q3)
	 JRST SCDBBG		;NONE!
	SKIPN Q1,.SVCMD(Q3)	;ANY COMMANDS ON QUEUE?
	JRST DMAQNF		;NO. ERROR
DMCFNL:	CAMN T3,.QCDBD(Q1)	;SAME?
	JRST DMAFND		;YES. FOUND IT
	SKIPN Q1,.QCNXT(Q1)	;GET NEXT
DMAQNF:	BUG.(HLT,MSSDNQ,PHYMVR,SOFT,<DMADON - DMA done queue entry not found>,<<T2,CID>,<T3,BUFF>>,<

Cause:	A DMA complete interrupt occurred and no commands were found which
	had a matching buffer name. This indicates a software inconsistency.

Data:	CID - connect ID
	BUFF - 32 bit buffer name
>)
	JRST DMCFNL		;AND CHECK IT TOO

; HERE WHEN A MATCHING COMMAND IS FOUND

DMAFND:	JN MSABT,(Q1),ABTEN0	;ABORTED SEND END PACKET
	LOAD T1,QCSTS,(Q1)	;GET STATE
	CAIN T1,STWSD		;WAITING TO SEND DATA (READ) ?
	JRST MAKIOE		;YES. ALL DONE
	CAIE T1,STWRD		;WAITING TO RECIEVE DATA (WRITE)?
	CALL ILSTAT		;ILLEGAL, DIE
	SAVEP
	CALL IOUNIT		;GET UDB ADDRESS
	 RET			;CAN'T
	MOVE T1,.QCIORB(Q1)	;GET IORB ADDRESS
	MOVE T2,P3		;AND UDB ADDRESS
	CALLRET GOIO		;QUEUE IORB (T1,T2/)
;NEWMES - MESSAGE RECIEVED
; T1/ .SSMGR
; T2/ CONNECT ID
; T3/ ADDRESS OF MESSAGE BUFFER
; T4/ <FLAGS>B6 ! <ADDR OF ROUTINE TO RETURN BUFFER>B35
;	CALL NEWMES		;(T1,T2,T3,T4/)
; RETURNS +1: ALWAYS
;	APPROPRIATE ACTION PERFORMED
;
NEWMES:	SAVEQ
	AOS SVRECV		;[7211] COUNT THE MESSAGE
	AOS T1,SVCMIU		;COUNT COMMANDS
	CAMLE T1,SVMCIU		;IS THIS THE MAX EVER?
	MOVEM T1,SVMCIU		;YES
	MOVX Q2,.QCRTN		;COMPUTE
	ADD Q2,T3		;START ADDRESS OF HEADER
	MOVE Q3,Q2		;END = START...
	AOS Q3			;PLUS ONE
	SETZM (Q2)		;ZERO FIRST WORD
	MOVEI Q1,C%BINV+.QCRT2	;COUNT OF WORDS TO ZERO
	EXTEND Q1,[XBLT]	;ZERO THEM
	TXZ T4,-1B6		;CLEAR SCAMPI FLAGS
	MOVEM T4,.QCRTN(T3)	;SAVE ADDRESS TO RETURN BUFFER
	MOVE Q1,T3		;SAVE MESSAGE ADDR
	SETZ Q2,		;NO END PACKET YET
	CALL SETQ3		;SETUP Q3 AS DATA POINTER (T2/Q3)
	 JRST SCDBBG		;NONE!
	SKIPA T4,[0]		;NORMAL ENTRY POINT
NEWME0:	MOVEI T4,1		;ENTRY TO RETRY COMMANDS
	LOAD T1,SVSTA,(Q3)	;GET CONNECTION STATE
	CAIE T1,SCOKS		;OK TO SEND (CONTROLLER ONLINE)
	CALL ILSTAT		;ERROR DIE
	MOVE T1,TODCLK		;STATUS IS OK. GET NOW
	MOVEM T1,.SVTMO(Q3)	;SAVE TIME OF LAST MESSAGE
NEWME1:	MOVE T1,P.OPCD(Q1)	;GET OPCODE
	CALL SRVFUL		;REVERSE IT
	LDB T1,LOBYT		;GET OPCODE ONLY
	SETZ T3,		;INITILIZE DATA POINTER
MSFCMD:	HLRZ T2,MSFNCT(T3)	;GET COMMAND FROM TABLE
	JUMPE T2,BADCMD		;END OF DATA. ILLEGAL OP CODE
	CAME T1,T2		;THIS COMMAND?
	AOJA T3,MSFCMD		;NO. TRY AGAIN
	HRRZ T1,MSFNCT(T3)	;YES. GET ROUTINE ADDRESS
	AOS @[EP. SVCMDC(T3)	;COUNT COMMANDS AND RETRIES
	      EP. SVCMRT(T3)](T4)
	MOVEM T1,SVLCMD		;REMEMBER LAST COMMAND
	JRST (T1)		;AND GO TO IT
	SUBTTL MSCP Commands

;MSCP COMMAND TABLE. ONLY DISC COMMANDS FROM THE MSCP MINIMAL DISC SUBSET
;ARE CURRENTLY IMPLEMENTED
MSFNCT:	-1,,BADCMD		;NO SUCH COMMAND
	OP.RD,,MSXRD		;READ DATA
	OP.WR,,MSXWR		;WRITE DATA
	OP.GCS,,MSXGCS		;GET COMMAND STATUS
	OP.GUS,,MSXGUS		;GET UNIT STATUS
	OP.ONL,,MSXONL		;ONLINE A UNIT
	OP.ABO,,MSXABT		;ABORT COMMAND
	OP.SCC,,MSXSCC		;SET CONTROLLER CHARACTERISTICS
	OP.AVA,,MSXAVA		;AVAILABLE COMMAND

;THE FOLLOWING COMMANDS ARE DEFINED IN THE MINIMAL DISC MSCP SUBSET OF
;COMMANDS AND SHOULD BE ADDED FOR CONSISTENCY BUT SINCE THEY ARE NEVER USED
;IN KL-KL COMMUNICATIONS THEY ARE NOT CURRENTLY INCLUDED

REPEAT 0,<
	OP.SUC,,MSXSUC		;SET UNIT CHARACTERISTICS
	OP.DAP,,MSXDAP		;DETERMINE ACCESS PATHS
	OP.CCD,,MSXCCD		;COMPARE CONTROLLER DATA
	OP.CMP,,MSXCMP		;COMPARE HOST DATA
	OP.ACC,,MSXACC		;ACCESS COMMAND
	OP.ERS,,MSXERS		;ERASE COMMAND
	OP.FLS,,MSXFLS		;FLUSH COMMMAND
>
	0			;END OF LIST
;BADCMD - ILLEGAL COMMAND (OPCODE IS ILLEGAL OR UNSUPPORTED)
;BADCM0 - INVALID COMMAND (AC1 CONTAINS STATUS BITS)
;
; 	CALL BADCMD		;(Q1,Q3/)
;	CALL BADCM0		;(T1,T3,Q1,Q3/)
;
; RETURNS +1: ALWAYS, END PACKET SENT
;
BADCMD:	BADCMV P.OPCD		;BAD OPCODE
	MOVEI T3,P%STS		;LENGTH IS STATUS
	TDZA T2,T2		;DO BUGINF TOO
BADCM0:	SETO T2,		;NO BUGINF
	STKVAR <ERRBIT,SIZE,BGFLAG>
	MOVEM T3,SIZE
	MOVEM T2,BGFLAG
	MOVEM T1,ERRBIT
	AOS SVILCM		;COUNT BAD COMMANDS
	MOVE T1,P.STS(Q1)	;ADD STATUS TO ERROR
	CALL REVFUL
	IORX T1,OP.END		;ADD END
	IORB T1,ERRBIT		;MAKE COMPOSITE
	MOVE T1,P.OPCD(Q1)	;GET OPCODE
	CALL REVFUL		;IN NORMAL FORMAT
	MOVE T3,T1
	MOVE T4,ERRBIT
	MOVE T1,.SVCID(Q3)
	CALL SC.NOD
	SKIPN BGFLAG		;BUGINF?
	 BUG.(INF,MSSBCM,PHYMVR,SOFT,<BADCMD - MSCP server bad command>,<<T2,NODE>,<T1,CID>,<T3,OPCODE>,<T4,ERRBIT>>,<

Cause:	The MSCP server received a command with an illegal or 
	unsupported operation specified.

Data:	NODE   - node number
	CID    - connect ID
	OPCODE - operation code
	ERRBIT - error bits and status of command
>)
	JUMPN Q2,BADCM1		;HAVE A MESSAGE BUFFER
	CALL GETEBF		;NO. GET ONE
	 RET			;CAN'T
BADCM1:	MOVE T1,P.UNIT(Q1)	;UNIT IF ANY
	MOVEM T1,P.UNIT(Q2)	;SAVE IT
	MOVE T1,P.BCNT(Q1)	;BYTE COUNT
	MOVEM T1,P.BCNT(Q2)	;SAVE
	MOVE T1,ERRBIT		;GET ERROR BITS AGAIN
	CALL REVFUL		;BACK TO WIERD FORMAT
	MOVEM T1,P.STS(Q2)	;SAVE IN MESSAGE
	MOVE T3,SIZE		;LENGTH
	CALLRET SNDEND		;SEND IT
;MSXSCC - SET CONTROLLER CHARACTERISTICS
;
; 1. INSURE VERSION NUMBER IS 0 (BADCMD IF NOT)
;
; 2. INSURE ONLY LEGAL FLAGS ARE SPECIFIED
;
; 3. SAVE FLAGS AND TIMEOUT INTERVAL
;
; 4. BUILD END PACKET CONTAINING 10 SECOND TIMEOUT VALUE
;
; Q1/ COMMAND
; Q3/ POINTER TO CONNECTION DATA (SCDB)
;	CALL MSXSCC		;(Q1,Q2,Q3/)
; RETURNS +1: ALWAYS
;	ACTION PERFORMED OR ERROR FLAGGED AND END PACKET SENT
;	OR COMMAND QUEUED
MSXSCC:	CALL GETEBF		;GET A BUFFER FOR END MESSAGE (Q1/Q2)
	 RET			;CAN'T. COMMAND IS QUEUED
	MOVE T1,P.VRSN(Q1)	;GET VERSION
	CALL REVWF
	LDB T1,LOBYT		;GET BYTE
	JUMPN T1,[BADCMV P.VRSN	;BAD VERSION NUMBER
		MOVEI T3,P%CNTI	;SIZE OF MESSAGE
		CALLRET BADCM0]	;ERROR IF VERSION ISN'T ZERO
	MOVE T1,P.CNTF(Q1)	;GET CONTROLLER FLAGS
	CALL REVFUL
	ANDX T1,CF.ATN!CF.MSC!CF.THS ;ALLOW ONLY THESE FLAGS
				; ERROR FLAGS ARE SUPPORTED BUT IGNORED SINCE
				; WE DO NOT SENT ERROR DATAGRAMS
	MOVX T2,MC.ATN		;ATTENTION FLAG
	ANDCAM T2,.SVCIS(Q3)
	TXNE T1,CF.ATN		;ENABLING ATTENTION MESSAGES?
	IORM T2,.SVCIS(Q3)	;SAVE NEW FLAGS
	TXO T1,CF.MLH+CF.576	;TELL DRIVER WE ARE MULTI-HOST AND 576 BYTES
	CALL REVFUL
	MOVEM T1,P.CNTF(Q2)	;SAVE END PACKET FLAGS
	MOVE T1,P.HTMO(Q1)	;GET TIMOUT VALUE
	CALL REVWF		;IN NORMAL FORMAT
	IMULI T1,^D1000		;TO MILLISECONDS
	MOVEM T1,.SVTMV(Q3)	;SAVE
	MOVEI T1,SVRTMV		;GET SERVER TIMEOUT VALUE
	SKIPE CITIMR		;DEBUGGING?
	MOVEI T1,^D7200		;YES ALLOW MUCH LONGER TIME
	CALL REVW2
	MOVEM T1,P.CTMO(Q2)	;SAVE IN END MESSAGE
	MOVE T1,APRSER		;[7357] Get CPU serial number
	CALL REVW2
	MOVEM T1,P.CNTI(Q2)	;SAVE AS CONTROLLER ID
	MOVE T1,[BYTE (8) 1,8]	;SERVER AND MODEL 8
	CALL REVW2
	MOVEM T1,P.CNTI+1(Q2)	;SAVE IT IN END PACKET
	MOVX T1,OP.SCC!OP.END!ST.SUC ;END CODE, SUCCESS
	CALL REVFUL
	MOVEM T1,P.STS(Q2)	;SAVE AS STATUS
	MOVEI T3,P%CNTI		;SIZE OF END MESSAGE
	CALLRET SNDEND
;MSXABT - ABORT COMMAND
; FIND THE COMMAND AND IF A NON DATA OPERATION SIMPLY FORGET IT AND RETURN
; PACKETS TO SCA. IF IT IS A DATA OPERATION WE MARK IT AS ABORTED AND DO THE
; CORRECT THING WHEN IO COMPLETES
; Q1/ COMMAND
; Q3/ SCDB ADDRESS
;	CALL MSXABT		;(Q1,Q2/)
; RETURNS +1: ALWAYS
;	ACTION PERFORMED OR COMMAND QUEUED
;	COMMANDS WHICH HAVE IO ACTIVE ARE SIMPLY FLAGGED AS ABORTED AND
;	WILL BE DEQUEUED LATER
;
MSXABT:	CALL GETEBF		;GET END PACKET BUFFER (Q1/Q2)
	 RET			;CAN'T COMMAND QUEUED
	MOVE T1,P.OTRF(Q1)	;GET OLD COMMAND NUMBER
	CALL FNDCMD		;FIND COMMAND (T1/T1)
	 JRST ABTCM1		;NOT FOUND. ALREADY GONE
	SETONE MSABT,(Q1)	;SET ABORTED STATUS BIT
	LOAD T1,QCSTS,(Q1)
	CAIN T1,STIAC		;IORB ACTIVE
	JRST ABTCM1		;YES
	CAIE T1,STWSD		;WAITING FOR DATA TO BE SENT/RECIEVED
	CAIN T1,STWRD
	SKIPA			;YES. DON'T SEND END PACKET YET.
	CALL ABTEND		;NO. SEND END PACKET FOR ABORTED COMMAND (T1/)
ABTCM1:	MOVE T1,P.UNIT(Q1)	;GET UNIT NUMBER FROM ABORT COMMAND
	MOVEM T1,P.UNIT(Q2)	;SAVE IN END PACKET
	MOVE T1,P.OTRF(Q1)	;AND COMMAND REF OF COMMAND WE ABORTED
	MOVEM T1,P.OTRF(Q2)	;IN END PACKET
	MOVX T1,OP.ABO!OP.END!OP.SUC ;END, ABORT, SUCCESS
	CALL REVFUL
	MOVEM T1,P.STS(Q2)	;IN STATUS
	MOVEI T3,P%OTRF		;GET SIZE OF MESSAGE
	CALLRET SNDEND		;SEND END PACKET
;MSXGCS - GET COMMAND STATUS
;
; FIND A COMMAND AND RETURN IT'S STATUS. THE STATUS IS A NUMBER WHICH SHOULD 
; DECREASE AS THE COMMAND NEARS COMPLETION.
; STATUS = (MAX TIMEOUT VALUE + 1) - CURRENT VALUE
; IF WE ARE WAITING FOR AN IO OPERATION STATUS = 2 * STATUS
;
; Q1/ COMMAND
; Q3/ SCDB
;	CALL MSXGCS		;(Q1,Q2/)
; RETURNS +1: ALWAYS, STATUS SENT OR COMMAND QUEUED
;
MSXGCS:	CALL GETEBF		;GET BUFFER FOR END PACKET (Q1/Q2)
	 RET			;CAN'T
	MOVE T1,P.OTRF(Q1)	;GET NUMBER TO FIND
	CALL FNDCMD		;FIND IT
	 JRST MSXGC1		;STATUS IS NOT FOUND
	LOAD T3,QCSTS,(T1)	;GET STATE
	MOVEI T2,SVRTMX+1	;GET RETRY COUNTER +1
	OPSTR <SUB T2,>,QCCNT,(T1) ;SUBTRACT NUMBER OF RETRIES SO FAR
	CAIL T3,DATSTA		;DATA OPERATION PENDING?
	LSH T2,1		;YES INCREASE STATUS BY ALOT
	MOVE T1,T2		;GET STATUS IN T1
	CALL REVFUL
	MOVEM T1,P.CMST(Q2)	;SAVE STATUS OF COMMAND
MSXGC1:	MOVE T1,P.UNIT(Q1)
	MOVEM T1,P.UNIT(Q2)
	MOVE T1,P.OTRF(Q1)
	MOVEM T1,P.OTRF(Q2)	;SAVE OLD COMMAND NUMBER
	MOVX T1,OP.GCS!OP.END!ST.SUC ;GCS , END , SUCCESS
	CALL REVFUL
	MOVEM T1,P.STS(Q2)	;SAVE STATUS
	MOVEI T3,P%CMST
	CALLRET SNDEND		;SEND END PACKET
;MSXGCS - GET UNIT STATUS
; Q1/ COMMAND
; Q3/ SCDB ADDRESS
;	CALL MSXGUS		;(Q1,Q2/)
; RETURNS +1: ALWAYS, ACTION PERFORMED OR COMMAND QUEUED
;
MSXGUS:	SAVEP			;SAVE P REGS TOO
	CALL GETEBF		;GET END PACKET BUFFER (Q1/Q2)
	 RET			;CAN'T
	CALL FNDUNT		;FIND THE UNIT NUMBER (Q1/T1,P1,P2,P3)
	 JRST [	SETZM P.UNIT(Q2) ;NO UNIT FOUND
		JRST MSXGU1]	;RETURN INFO

;SAVE INFO IN BLOCK INCLUDING SUCCESS CODE

	CALL REVW2		;SAVE UNIT NUMBER (MAY HAVE CHANGED) (T1/T1)
	MOVEM T1,P.UNIT(Q2)
	SETZ T1,		;INITIALIZE FLAGS
	CALL SETUI0		;GET UNIT INFO (T1/T1)
	 JRST [	MOVEI T3,P%RCTC	;CANNOT GET SIZE AND RETURN ERROR
		JRST BADCM0]
	;CANNOT PROBLEM CODE IN T1
	MOVE T2,UDBSIZ(P3)	;GET POINTER TO SIZE
	MOVE T1,SECSRF(T2)	;SEC/SURF
	LSH T1,4		;POSITION IN 32 BITS
	MOVEI T3,1		;1 TRACK/GROUP
	DPB T3,HIBYT		;SAVE IT IN HI ORDER BYTE
	CALL REVFUL
	MOVEM T1,P.TRCK(Q2)	;SAVE IT
	MOVE T1,SECCYL(T2)	;SEC/CYL
	CALL REVW2
	MOVEM T1,P.CYL(Q2)	;SAVE IT
	MOVX T1,ST.SUC		;ASSUME ONLINE
	MOVE T2,UDBCHR(P3)	;GET BITS
	MOVE P5,.SVCID(Q3)	;GET CID INDEX
	LOAD P5,SID,P5
	TDNN T2,BITS+<^D36-CFSNUM>(P5) ;ONLINE?
	MOVX T1,ST.AVL		;NO. ASSUME AVAILABLE
	CALL CHKOFL		;CHECK IF OFFLINE (P1,P3/)
MSXGU1:	MOVX T1,ST.OFL		;YES. STATUS IS OFFLINE
	IORX T1,OP.GUS!OP.END	;END, GUS
	CALL REVFUL
	MOVEM T1,P.STS(Q2)
	MOVEI T3,P%RCTC		;SIZE OF MESSAGE
	CALLRET SNDEND		;SEND END PACKET
;MSXONL - ONLINE A UNIT
;MSXAVA - MAKE A UNIT AVAILABLE
; THE UNIT IS MARKED AS ONLINE BY A SINGLE BIT IN THE UDBCHR WORD
; THE NUMBER IS WORDSIZE-INDEX INTO CID TABLE
; AVAILABLE CLEARS THAT BIT
; Q1/ COMMAND
; Q3/ SCDB ADDRESS
;	CALL MSXAVA		;(Q1,Q3/)
;	CALL MSXONL		;(Q1,Q3/)
; RETURNS +1: ALWAYS, ACTION PERFORMED AND COMMAND QUEUED OR END PACKET SENT
;
MSXAVA: SKIPA T1,[-1]		;REMEMBER ENTRY
MSXONL:	SETZ T1,
	SAVEP			;SAVE P REGISTERS
	STKVAR <ENTFLG>		;ENTRY FLAG
	MOVEM T1,ENTFLG
	CALL GETEBF		;GET BUFFER FOR END PACKET
	 RET			;CAN'T
	CALL FNDUNT		;FIND UNIT (Q1/T1,P1,P2,P3)
	 JRST [	SETZM P.UNIT(Q2) ;NO UNIT FOUND
		MOVX T1,ST.OFL	;FLAG OFFLINE
		JRST MSXON1]	;RETURN INFO
	CALL REVW2
	MOVEM T1,P.UNIT(Q2)	;SAVE UNIT NUMBER
	MOVX T1,ST.OFL		;GET READY FOR OFFLINE
	CALL CHKOFL		;CHECK IF OFFLINE
	 JRST MSXON1		;OFFLINE.
	MOVE P5,.SVCID(Q3)	;GET CID INDEX VALUE
	LOAD P5,SID,P5
	SKIPE ENTFLG		;ONLINE COMMAND?
	JRST AVADON		;NO. AVAILABLE
	CALL SETUID		;GET UNIT INFO
	 JRST [	MOVEI T3,P%VSER	;SIZE OF ONLINE COMMAND AND RETURN ERROR
		JRST BADCM0]
	HRRZ T2,UDBSIZ(P3)	;GET POINTER TO SIZE TABLES
	MOVE T1,SECUNT(T2)	;GET SECTORS
	CALL REVW2		;REVERSE IT
	MOVEM T1,P.UNSZ(Q2)	;SAVE UNIT SIZE
	MOVX T1,ST.SUC		;ASSUME SUCCESS
	MOVE T2,UDBCHR(P3)	;GET CHARACTERISTICS WORD
	TDOE T2,BITS+<^D36-CFSNUM>(P5) ;ONLINE THE UNIT
	IORX T1,ST.ONL		;SAY ALREADY ONLINE
MSXON2:	MOVEM T2,UDBCHR(P3)	;SAVE NEW CHARACTERISTICS WORD
MSXON1:	IORX T1,OP.END		;ADD END TO STATUS
	MOVX T2,OP.ONL		;ASSUME COMMAND WAS ONLINE
	MOVEI T3,P%VSER		;SIZE OF ONLINE COMMAND
	SKIPE ENTFLG		;WAS IT?
	JRST [	MOVEI T3,P%STS	;NO. IT WAS AVAILABLE GET CORRECT SIZE
		MOVX T2,OP.AVA	;AND CORRECT OPCODE
		JRST .+1]
	IOR T1,T2		;MOVE CORRECT OPCODE TO STATUS WORD
	CALL SRVFUL
	MOVEM T1,P.STS(Q2)	;SAVE STATUS
	CALLRET SNDEND

AVADON:	MOVE T2,UDBCHR(P3)	;GET CHARACTERISTICS WORD
	TDZ T2,BITS+<^D36-CFSNUM>(P5) ;MARK AS AVAILABLE
	MOVEM T2,UDBCHR(P3)	;SAVE CHARACTERISTICS
	JRST MSXON2		;AND CONTINUE
;MSXRD - READ DATA
;
; READ DATA - 1. BUILD AN IORB AND QUEUE IT TO PHYSIO
;             2. AT IORB DONE TIME SEND THE DATA TO THE REQUESTING SYSTEM
;             3. AT DMA DONE TIME SEND AN END PACKET
;
; THE FOLLOWING ROUTINE PERFORMS STEP 1.

MSXRD:	SAVEP
	CALL IOSETU		;SETUP FOR IO
	 RET			;ERROR. MESSAGE SENT
	MOVE T1,P.MOD(Q1)
	CALL REVFUL		;REVERSE FLAGS
	MOVX T2,IRFRED		;ASSUME READ
	TXNE T1,MD.CMP		;COMPARE DATA?
	MOVX T2,IRFRVC		;YES, DO READ VALIDITY
	CALL MAKIRB		;MAKE IORB FOR READ PAGE (T2,Q1,Q3,P1,P2,P3/T1,P4)
	 JRST NOIORB		;CANNOT
GOIO:	MOVX T3,STIAC		;STATUS IS IORB ACTIVE
	STOR T3,QCSTS,(Q1)
	CALLRET IOSIO		;START IO

;MSXWR - WRITE DATA
;
; WRITE DATA - 1. BUILD AN IORB
;              2. GET DATA TO WRITE FROM REQUESTING SYSTEM
;              3. AT DMA DONE QUEUE IORB TO PHYSIO
;              4. AT IORB DONE TIME SEND END PACKET
;
; THE FOLLOWING IMPLEMENTS STEP 1 AND 2

MSXWR:	SAVEP
	CALL IOSETU
	 RET			;CAN'T
	MOVE T1,P.MOD(Q1)
	CALL REVFUL		;REVERSE FLAGS
	MOVX T2,IRFWRT		;ASSUME WRITE
	TXNE T1,MD.CMP		;COMPARE DATA?
	MOVX T2,IRFWVC		;YES, DO WRITE VALIDITY
	CALL MAKIRB		;MAKE IORB FOR WRITE PAGE
	 JRST NOIORB		;CAN'T
	CALLRET GETWD		;GET DATA AND QUEUE

NOIORB:	JUMPE T1,R		;IF RESOURCE ALLOCATION FAILURE JUST RETURN
	MOVEI T3,P%FBBK		;REAL ERROR IN T1 SET LENGTH
	CALLRET BADCM0		;AND SEND ERROR END PACKET
	SUBTTL IORB Interrupt Service

;MSSIRD - IORB COMPLETION INTERRUPT HANDLER
; T1/ IORB
; READ - SEND DATA ACROSS CI TO REQUESTING SYSTEM
;
; WRITE - SEND END PACKET. REQUEST IS COMPLETE
;
MSSIRD:	EA.ENT			;RUN IN 1
	SAVEQ
	LOAD Q3,IRBCID,(T1)	;GET CID
	CALL SETQ3I		;GET SCDB ADDRESS
	 JRST SCDBBG		;NONE!
	LOAD Q1,IRBCMD,(T1)	;AND COMMAND ADDRESS
	LOAD T1,SVSTA,(Q3)	;GET COMMAND STATE
	CAIL T1,STFSS		;SHUTDOWN?
	JRST RTNCMD		;YES, RETURN COMMAND
	JN MSABT,(Q1),ABTEN0	;ABORTED. SEND ABORTED END PACKET
	LOAD T3,QCSTS,(Q1)	;GET COMMAND STATUS
	CAIE T3,STIAC		;WAITING FOR IORB COMPLETE?
	CALL ILSTAT		;NOT WAITING FOR IORB COMPLETE IS ILLEGAL
	MOVE T2,IRBSTS(T1)	;GET STATUS
	LDB T3,IRYFCN		;GET FUNCTION CODE
	TXNE T2,IS.ERR		;COMPOSITE ERROR SET?
	CALLRET CHKIOE		;YES. ANALYZE IT
	CAIE T3,IRFRVC		;READ VALIDITY?
	CAIN T3,IRFRED		;OR READ?
	IFNSK.
	   MOVX T1,STWSB	;YES NEW STATE IS WAITING TO SEND BUFFER
	   STOR T1,QCSTS,(Q1)	;SAVE IT
	   CALLRET SNDDAT	;SEND DATA
	ENDIF.

;FUNCTION WAS WRITE. MARK SUCCESS AND SEND END PACKET

IFN ST.SUC,<			;SUCCESS MAY BE ZERO SO DON'T BOTHER
	MOVE T1,P.STS(Q1)	;GET COMMAND STATUS
	CALL REVFUL
	TXO T1,ST.SUC		;ADD SUCCESS
	CALL REVFUL
	IORM T1,P.STS(Q1)
>
	CALLRET MAKIOE		;ALL DONE. SEND END PACKET
;CHKIOE - ANALYZE IORB ERROR AND SEND END PACKET
; T2/ IORB STATUS BITS
; Q1/ COMMAND
; Q3/ SCDB ADDRESS
;	CALL CHKIOE		;(T2,Q1,Q3/)
; RETURNS +1: ALWAYS, ERROR BITS LIT, END PACKET SENT
;
CHKIOE:	SETZ T1,		;INITIALIZE MSCP ERROR BITS
	TXNE T2,IS.DVE!IS.WGU!IS.NRT ;DRIVE ERROR?
	MOVX T1,ST.DRV		;YES. FLAG IT
	TXNE T2,IS.DTE!IS.RTL	;DATA ERROR?
	MOVX T1,ST.DAT		;YES
	TXNE T1,IS.WLK		;WRITE PROTECTED?
	MOVX T1,ST.WPR		;YES
	SKIPN T1		;ANY ERROR BITS SET?
	JRST [BUG.(CHK,MSSER0,PHYMVR,SOFT,<IORB done error and error bits 0>,<<T2,IRBERR>>,<

Cause:	An IORB completed with bit IS.ERR set indicating an error. The MSCP
	server could not find any relevent error.

Data:	IRBERR - IORB status word
>)
	     MOVX T1,ST.CNT	;CONTROLLER ERROR
	     JRST .+1]
	CALL REVFUL
	IORM T1,P.STS(Q1)	;SAVE ERROR STATUS
	CALLRET MAKIOE		;SEND END PACKET
;GETEND - JACKET ROUTINE FOR RETRY END SENDING WHEN NO BUFFERS ARE AROUND
;
GETEND:	SAVEAC <Q2>
	LOAD T1,QCSTS,(Q1)
	CAIE T1,STWAE
	CALL ILSTAT
	JRST MAKIO0

;MAKIOE - MAKE AND SEND END PACKET FOR IO COMMAND
; Q1/ COMMAND
; Q3/ SCDB
;	CALL MAKIOE		;(Q1,Q3/)
; RETURNS +1: ALWAYS, END PACKET SENT OR COMMAND QUEUED (STWSE)
;
MAKIOE:	SAVEAC <Q2>		;SAVE Q2
	CALL CLENUP		;RELEASE ALL RESOURCES
	MOVEI T1,P%FBBK		;LENGTH OF END PACKET
	STOR T1,QCENL,(Q1)	;SAVE IT IN CASE WE LOSE
	MOVX T1,STWAE		;GET WAIT TO ALLOCATE END
	STOR T1,QCSTS,(Q1)	;SAVE IT
MAKIO0:	CALL GETEBF		;GET END PACKET BUFFER (/Q2)
	 RET			;CAN'T
	MOVE T1,P.STS(Q1)	;GET STATUS
	CALL REVFUL
	TXO T1,OP.END		;ADD END STATUS
	CALL REVFUL
	MOVEM T1,P.STS(Q2)	;SAVE
	MOVE T1,P.UNIT(Q1)	;AND UNIT
	MOVEM T1,P.UNIT(Q2)	;SAVE
	MOVE T1,P.BCNT(Q1)	;BYTE COUNT
	MOVEM T1,P.BCNT(Q2)	;SAVE
	MOVEI T3,P%FBBK		;SIZE OF END PACKET
	CALLRET SNDEND		;SEND IT
	SUBTTL Subroutines

;MAKIRB - MAKE IORB FROM QUEUED COMMAND
; T2/ IORB FUNCTION
; Q1/ PACKET ADDRESS
; Q3/ SCDB ADDRESS
; P1/ CDB
; P2/ KDB
; P3/ UDB
;
; RETURNS +1 ERROR T1/ 0 RESOURCE ALLOCATION FAILURE
;		   T1/ WORD OFFSET CONTAINING BAD DATA
;         +2 SUCCESS IORB ADDRESS IN P4
;
; NOTE: DESTROYS P REGISTERS
;
MAKIRB:	STKVAR <IOFNC,BYTCNT,<BDAT,5>>
	SKIPG NRPLQ		;ANY NEED TO BOTHER NOW
	JRST RETZ		;NO, NO PAGES AROUND!
	SKIPN NULJBF		;NULL JOB? OR
	SKIPE SRVCHK		;PERIODIC CHECK?
	JRST MAKIR0		;YES WE ARE RACE FREE.
	SKIPN INSKED		;INSKED?
	SKIPE NSKED		;OR NOSKED?
	JRST [AOS SVBKNS	;COUNT BLOCKS FOR NSKED EVENTS
	      CALL MSSCZK	;AND MAKE SCHED KNOW ABOUT US PAINLESSLY
	      JRST RETZ]	;YES, WE MAY SCREW UP RPLQ SO TRY LATER
MAKIR0:	MOVEM T2,IOFNC		;SAVE IORB FUNCTION CODE
	SKIPN SVIRBH		;IORB LIST NONNULL?
	JRST RETZ		;NO IORBS RETURN +1
	MOVE P4,@SVIRBH		;GET SUCCESSOR
	EXCH P4,SVIRBH		;NEW HEAD OF LIST
	MOVEM P4,.QCIORB(Q1)	;SAVE ADDRESS OF IORB
	
	PIOFF			;THIS IS VERY TRICKY. WE NEED PEACE AND QUIET
	SKIPG NRPLQ		;STILL SOME PAGES?
	JRST NOPGS		;NO
	HRRZ T1,@SRPLQ		;GET TOP PAGE
	CAIN T1,SRPLQO		;EMPTY?
	HRRZ T1,@DRPLQ		;YES, USE ALTERNATE RPLQ
	SOS NRPLQ		;TAKE PAGE OFF REPLACABLE
	MOVE 2,@CST3X+1
	HRRZ 3,2
	HLLM 2,@CST3X+3
	HLRZ 3,2
	HRRM 2,@CST3X+3
	SETZRO CORMB,@CST0X+1	;NOT MODIFIED
	SETZM @CST3X+1		;CLEAR FLAGS, OWNER, ADDRESS
	LOAD T2,CSTPST,+T1	;GET SPECIAL PAGE STATE
	CAIE T2,PSTAVL		;AVAILABLE?
	JRST [CALL OFRQ		;NO PUT IT BACK
	      JRST NOPGS]	;AND QUIT
	MOVEM T1,.QCPID(Q1)	;SAVE PAGE ID (PHYSICAL NUMBER)

	MOVX T2,PSTSPM		;CHANGE SPECIAL PAGE STATE
	STOR T2,CSTPST,+T1
	CALL ONSPMQ		;PUT PAGE ON SPECIAL MEMORY QUEUE NOW
				;RETURNS PION
	MOVE T1,.QCPID(Q1)	;GET PAGE
	MOVEI T2,PSIOP		;SET STATE TO IO TO ALLOW PARITY ERROR SCANS
	STOR T2,CSTAGE,+T1

	AOS T1,SVIPIU		;COUNT PAGES IN USE
	CAML T1,SVMPIU
	MOVEM T1,SVMPIU		;AND MAXIMUM
	SETZM 0(P4)		;CLEAR FIRST WORD OF BLOCK
	MOVS T1,P4		;BUILD BLT POINTER
	HRRI T1,1(P4)		; ...
	BLT T1,SVIRLN-1(P4)	;CLEAR BLOCK
	STOR Q1,IRBCMD,(P4)	;SAVE COMMAND ADDRESS IN IORB
	MOVE T1,.SVCID(Q3)	;GET CID INDEX
	LOAD T1,SID,T1
	STOR T1,IRBCID,(P4)	;AND SAVE IT
	MOVE T1,P.LBN(Q1)	;GET BLOCK NUMBER FROM COMMAND
	CALL REVFUL
	LSH T1,-<4+2>		;RIGHT ADJUST, UNCONVERT TO PRE MSCP FORMAT
	TLZ T1,DSKMSK		;CLEAR UNUSED BITS
	TXO T1,DSKAB		;AND SET DISK ADDRESS BIT
	MOVEM T1,IRBADR(P4)	;STORE DEVICE ADDRESS
	MOVEI T1,IRMWRD		;WORD MODE
	DPB T1,IRYMOD		;STORE IN IORB
	MOVSI T2,DSKMSK		;INVALID BITS IN DISK ADDRESS
	ANDCAB T2,IRBADR(P4)	;CLEAR THE BITS AND GET DISK ADDRESS
	HRRZ T3,UDBSIZ(P3)	;GET POINTER TO SIZE TABLES
	CAML T2,SECUNT(T3)	;LEGAL DISK ADDRESS SPECIFIED?
	JRST [BADCMV P.LBN	;NO. ERROR
	      RET]
	MOVEI T1,IRBLEN+1(P4)	;BUILD TAIL,,HEAD OF CCW LIST
	HRLI T1,IRBLEN+2(P4)	; ...
	MOVEM T1,IRBXFL(P4)	;STORE
	MOVEI T1,MSSIRD		;INTERRUPT ROUTINE TO CALL
	MOVEM T1,IRBIVA(P4)	;STORE IN IORB
	MOVE T1,P.BCNT(Q1)	;GET BYTE COUNT
	CALL REVFUL		;IN 32 BITS
	MOVEM T1,BYTCNT		;SAVE BYTE COUNT
	IDIVI T1,<^D36_4/8>	;IN 36 BITS, CONVERT BYTES (8) TO WORDS
	SKIPE T2		;INEXACT MULTIPLE?
	AOS T1			;YES, ADD 1
	CAILE T1,NCCWS*PGSIZ	;GREATER THAN MAX (ONLY DO 1 PAGE XFRS)?
	 JRST [BADCMV P.BCNT	;ERROR 
	      RET]
	HRRZM T1,IRBCNT(P4)	;STORE COUNT IN IORB
	MOVE T2,.QCPID(Q1)	;GET PHYSICAL PAGE NUMBER
	LSH T2,PGSFT		;MAKE IT A PHYSICAL ADDRESS
	SETZM .MDNXT+BDAT	;NEXT BUFFER DESCRIPTOR (NONE)
	MOVE T1,BYTCNT		;GET 32 BIT BYTE COUNT
	LSH T1,-4		;MAKE 36 BITS
	MOVEM T1,.MDLEN+.MDSSD+BDAT ;SIZE OF SEGMENT IN BYTES
	MOVEM T2,.MDADR+.MDSSD+BDAT ;PHYSICAL PAGE ADDRESS
	SETZM .MDSSD+.MDLSD+BDAT ;NEXT SEGMENT DESCRIPTOR (NONE)
	MOVE T1,IOFNC		;GET FUNCTION
	DPB T1,IRYFCN		;STORE IN IORB
	SETZ T2,		;SET UP FLAGS WORD. ASSUME READ COMMAND.
	CAIE T1,IRFWRT		;WRITE?
	CAIN T1,IRFWVC		;OR WRITE VALIDITY?
	TXO T2,SQ%WRT		;SET WRITABLE BIT
	MOVEI T1,MD%DHD		;GET HIGH DENSITY CODE
	STOR T1,MD%DMD,T2	;SET HIGH DENSITY MODE.
	MOVEM T2,.MDFLG+BDAT	;STORE FLAGS IN DESCRIPTOR BLOCK
	BLCAL. (SC.MAP,<<.,BDAT>>) ;MAP BUFFER FOR CI DMA
	 SCAERR <JRST [	CALL CLENUP ;RELEASE EVERYTHING
		JRST RETZ]>	;AND RETURN RESOURCE FAILURE
	MOVEM T1,.QCDBD(Q1)	;SAVE BUFFER NAME
	MOVE T1,IRBCNT(P4)	;RETRIEVE WORD COUNT
	MOVE T2,.QCPID(Q1)	;AND PAGE NUMBER
	LSH T2,PGSFT		;MAKE IT A PHYSICAL ADDRESS
	HRLI T1,IRMWRD		;INSERT WORD MODE
	HRRZ T3,CDBDSP(P1)	;GET DISPATCH BASE
	CALL CDSCCW(T3)		;BUILD CCW INTO T1
	MOVEM T1,CCWLST(P4)	;STORE AS FIRST WORD OF CCW LIST
	SETZM CCWLST+1(P4)	;CLEAR SECOND WORD OF CCW LIST
	MOVE T1,P4		;SETUP REGS FOR PHYSIO
	MOVE T2,P3
	RETSKP			;AND RETURN SUCCESS

NOPGS:	PION			;ALLOW PI
	CALL CLENUP		;RELEASE RESOURCES
	JRST RETZ		;AND RETURN
IOSETU:	CALL QUECMD		;SAVE COMMAND ON QUEUE
IOUNIT:	CALL FNDUNN		;FIND UNIT. NO STEPPING ALLOWED
	 JRST NOUNIT		;NONE
	CALL CHKOFL		;OFFLINE?
	 JRST IOUOFL		;YES
	MOVE P5,.SVCID(Q3)	;GET CID INDEX
	LOAD P5,SID,P5
	MOVE T1,UDBCHR(P3)	;GET UDB CHARACTERISTICS
	TDNN T1,BITS+<^D36-CFSNUM>(P5) ;IS UNIT ONLINED BY DRIVER
	JRST IOUAVA		;NO. UNIT IS AVAILABLE
	RETSKP			;ALL IS OK

NOUNIT:	SETZM P.UNIT(Q1)	;NO UNIT AND OFFLINE
IOUOFL:	SKIPA T1,[ST.OFL]	;OFFLINE
IOUAVA:	MOVX T1,ST.AVL		;AVAILABLE
	STKVAR <ERRBIT>
	MOVEM T1,ERRBIT		;SAVE ERROR BITS
	CALL CLENUP		;FREE RESOURCES
	MOVE T1,ERRBIT		;GET THEM BACK
	MOVEI T3,P%FBBK		;LENGTH
	JRST BADCM0		;TREAT AS BAD COMMAND

;CHKOFL - CHECK FOR UNIT OFFLINE
;
; THIS ROUTINE CHECKS FOR A UNIT OFFLINE. IN THIS CASE OFFLINE MEANS
; ONE OF THE FOLLOWING:
;  1. CAHNNEL IS CS.OFL
;  2. UNIT IS NOT MSCP ONLINE AND IS US.OFS
;
;  NOTE: IF A UNIT IS MSCP ONLINE AND US.OFS THEN THE US.OFS IS TREATED
;        A TRANSIENT OFFLINE CONDITION AND THE DRIVE IS NOT CONSIDERED
;        REALLY OFFLINE. THIS MAY BE CHANGED IF US.OFS IS CHANGED TO
;        MEAN OFFLINE INTERRUPT OCCURRED OR DRIVE WAS NEVER ONLINE.
;        CURRENTLY US.OFS GETS SET WHEN A DUAL PORTED DRIVE IS BEING
;        ACCESSED BY ANOTHER SYSTEM.
;
CHKOFL:	SAVEAC <T2,T3>
	MOVE T2,UDBSTS(P3)	;GET UNIT STATUS
	MOVE T3,CDBSTS(P1)	;AND CHANNEL STATUS
	TXNE T3,CS.OFL		;CHANNEL OFFLINE?
	RET			;YES, FAILURE
	MOVE T3,.SVCID(Q3)	;GET CID INDEX
	LOAD T3,SID,T3
	MOVE T3,BITS+<^D36-CFSNUM>(T3) ;GET ONLINE BIT FOR THIS CONNECTION
	TDNN T3,UDBCHR(P3)	;IS UNIT ONLINED BY DRIVER
	TXNN T2,US.OFS		;NO, IS IT CURRENTLY OFFLINE?
	RETSKP			;MSCP ONLINE OR REALLY ONLINE
	RET			;NEITHER, FAIL
;GETWD - GET WRITE DATA FROM OTHER SYSTEM. REQUEST DATA FOR A WRITE OPERATION
; Q1/ COMMAND
; Q3/ SCDB
;	CALL GETWD		;(Q1,Q3/)
; RETURNS +1: ALWAYS
;
GETWD:	MOVX T1,STWRB		;WAITING TO REQUEST BUFFER
	STOR T1,QCSTS,(Q1)	;SAVE STATUS
;	CALLRET REQDAT		;FALL INTO REQDAT

;REQDAT - REQUEST DATA FROM REMOTE SYSTEM
; Q1/ COMMAND
; Q3/ SCDB
;	CALL REQDAT		;(Q1,Q3/)
; RETURNS +1: ALWAYS
;
REQDAT:	LOAD T1,QCSTS,(Q1)	;GET COMMAND STATUS
	CAIE T1,STWRB		;IS STATE "WAITING TO REQUEST BUFFER"?
	CAIN T1,STWRR		;OR WAITING TO REQUEST (RETRY)
	SKIPA			;YES. OK
	CALL ILSTAT		;NO. DIE
	MOVE T1,P.BUFF+1(Q1)	;GET BUFFER NAME
	CALL REVFUL
	BLCAL. (SC.RQD,<.SVCID(Q3),T1,.QCDBD(Q1),[0],[0]>) ;[7.1037]GET DATA
	 SCAERR <JRST REQERR>
	MOVX T1,STWRD		;WAITING FOR RECIEPT OF DATA
	STOR T1,QCSTS,(Q1)	;SAVE STATUS
	RET

SNDDAT:	LOAD T1,QCSTS,(Q1)	;GET COMMAND STATUS
	CAIE T1,STWSB		;IS STATE "WAITING TO SEND BUFFER"?
	CAIN T1,STWSR
	SKIPA			;STATE IS OK.
	CALL ILSTAT		;NO. DIE
	MOVE T1,P.BUFF+1(Q1)
	CALL REVFUL
	BLCAL. (SC.SND,<.SVCID(Q3),.QCDBD(Q1),T1,[0],[0]>)
	 SCAERR <JRST SDDERR>	;DATA IO ERROR
	MOVX T2,STWSD		;WAITING FOR SEND COMPLETE
	STOR T2,QCSTS,(Q1)	;SAVE STATUS
	RET

;HERE WHEN A NAMED BUFFER XFR FAILS - CURRENT STATUS IS SETUP TO PREVENT RETRY

SDDERR:	SKIPA T2,[STWSR]	;WAITING TO SEND (RETRY)
REQERR:	MOVX T2,STWRR		;WAITING TO REQUEST (RETRY)
	CAIN T1,SCSNEC		;NOT ENOUGH CREDIT?
	RET			;ALL OK. WE WILL GET A CALLBACK
	CAIE T1,SCSNBA		;NO BUFFER?
	CALLRET SNDSHT		;NO, UNKNOWN ERROR CLOSE THE CONNECTION
	STOR T2,QCSTS,(Q1)	;SAVE RETRYABLE STATUS
	RET			;RETURN
;GETEBF - GET END PACKET BUFFER FOR COMMAND IN Q1
; Q1/ COMMAND
;	CALL GETEBF		;(Q1/Q2)
; RETURNS +1: FAILURE, COMMAND QUEUED
;	+2: SUCCESS, END PACKET ADDRESS IN Q2
;	    COMMAND REFERENCE NUMBER STORED IN END PACKET
;
GETBF:	SAVEAC <Q1>		;ENTRY TO GET A BUFFER FOR A NON-END USE
	SETZ Q1,		;FLAG NO COMMAND
GETEBF:	MOVEI T1,1
	CALL SC.ABF		;GET A PACKET BUFFER
	 SCAERR <CALLRET QUECMD>;CAN'T QUEUE OLD COMMAND (Q1/)
	MOVE T4,T3		;REMEMBER RETURN ADDRESS FOR BUFFER
	MOVE Q2,T1		;SAVE ITS ADDRESS
	MOVE T2,Q2		;GET READY
	SUBI T2,C%BINV		; TO BLT
	MOVE T3,T2		; ZEROS
	AOS T3
	MOVX T1,<C%BINV+C%MGSZ>-1 ;NUMBER OF WORDS TO ZERO
	SETZM (T2)		;ZERO THE FIRST WORD
	EXTEND T1,[XBLT]	;ZERO THE BUFFER
	AOS T1,SVPKIU		;COUNT PACKETS IN USE
	CAMLE T1,SVMKIU		;MAX?
	MOVEM T1,SVMKIU		;YES
	MOVEM T4,.QCRTN(Q2)	;SAVE WHERE TO RETURN THE BUFFER
	SKIPE T1,Q1		;IS THERE A CRF?
	MOVE T1,P.CRF(Q1)	;YES, GET COMMAND REFERENCE NUMBER FROM COMMAND
	MOVEM T1,P.CRF(Q2)	;SAVE IN END PACKET
	RETSKP			;GOOD RETURN

ENDRTY:	LOAD T1,QCSTS,(Q1)	;GET STATUS
	CAIE T1,STWSE		;WAITING FOR THIS
	CALL ILSTAT		;NO. DIE
	CALL GETEBF		;GET A BUFFER FOR END
	 RET
	MOVE T2,Q1
	MOVE T3,Q2
	LOAD T1,QCENL,(Q1)	;GET END PACKET LENGTH
	EXTEND T1,[XBLT]	;MOVE DATA
	MOVE T1,P.STS(Q1)	;GET STATUS
	CALL REVFUL
	TXO T1,OP.END		;ADD END STATUS
	CALL REVFUL
	MOVEM T1,P.STS(Q2)	;SAVE
	LOAD T3,QCENL,(Q1)	;GET LENGTH
;	CALLRET SNDEND

SNDEND:	STOR T3,QCENL,(Q1)	;SAVE SIZE OF MESSAGE IN CASE SEND FAILS
	MOVX T1,STWSE		;STATUS IS WAITING TO SEND END
	STOR T1,QCSTS,(Q1)	;SAVE IT

IFN DEBUG,<	CALL SCPAK
>

	BLCAL.	(SC.SMG,<.SVCID(Q3),[0],T3,Q2,[MVRPRI],[0],[0]>) ;SEND THE PACKET
	SCAERR <JRST SNDERR>	;SEND ERROR
	AOS SVSEND		;[7211] COUNT THE SEND
	SOS SVPKIU		;COUNT PACKETS IN USE
	CALLRET RTNCMD		;SEND OK RETURN COMMAND

;
; HERE IF THE SEND FAILED. FIND OUT WHY AND DO SOMETHING ABOUT IT
;
SNDERR:	MOVE T3,T1
	MOVE T1,.SVCID(Q3)
	CALL SC.NOD
	CAIE T3,SCSNEC		;NOT ENOUGH CREDIT?
SNDSHT:	BUG.(INF,MSSSBD,PHYMVR,SOFT,<Send failed>,<<T2,NODE>,<T1,CID>,<T3,ERROR>>,<
	
Cause:	A send of a message failed for an unexpected reason. The 
	connection will be shut down.

Data:	NODE - node number
	CID - connect ID
	ERROR - SCA error code

>,MSSFSD)			;UNEXPECTED ERROR SHUTDOWN AND RESYNC
	CALL QUECMD		;THIS COMMAND MUST BE RETRIED
	MOVE T2,Q2		;GET END ADDRESS
	MOVE T3,Q1		;AND COMMAND ADDRESS
	MOVEI T1,C%MGSZ		;SIZE OF A MESSAGE
	EXTEND T1,[XBLT]	;SAVE END PACKET IMAGE
RTNEND:	MOVE T1,Q2		;RETURN END PACKET BY HAND SINCE SEND FAILED
	SOS SVPKIU		;COUNT PACKETS IN USE
	CALLRET @.QCRTN(Q2)
IFN DEBUG,<
;SCPAK - SANITY CHECK OUTGOING MESSAGE
;
SCPAK:	CAIL T3,P%OPCD		;LENGTH GOOD?
	CAILE T3,P%RCTC
	CALL BADPAK
	SKIPN P.CRF(Q2)		;HAVE A CRF?
	CALL BADPAK
	MOVE T1,P.STS(Q2)	;STATUS
	CALL SRVFUL
	LDB T1,LOBYT		;GET STATUS ONLY!
	TXZN T1,OP.END		;END?
	CALL BADPAK
	SKIPN T1		;SOMETHING ELSE TOO
	CALL BADPAK
	SKIPN Q2		;REALLY ANYTING TO SEND
	CALL BADPAK
	RET

BADPAK:	 BUG.(HLT,MSSNUT,PHYMVR,SOFT,<MSCP server send sanity check failed>,,<

Cause: 	Unknown should never happen. Examine the dump to determine the 
	problem.
>)
>
;CLENUP - CLEANUP COMMAND RESOURCES
; Q1/ COMMAND
;
CLENUP:	SAVET			;PRESERVE ALL ACS
	SKIPN .QCIORB(Q1)	;ANYTHING?
	RET			;NO.
	SKIPN T1,.QCPID(Q1)	;GET PAGE PTN.PN AND MAKE SURE PAGE EXISTS
	JRST CLENU2		;NO PAGE PROCEED
	SOS SVIPIU		;COUNT PAGES USED
	LOAD T2,CSTAGE,+T1	;GET AGE FIELD
	CAIE T2,PSIOP		;IS IT ON QUEUE NOW?
	 JRST [	MOVX T1,ST.DAT	;SET DATA ERROR
		CALL REVFUL
		IORM T1,P.STS(Q1)
		JRST CLENU2]	;AND CONTINUE
	MOVEI T2,PSSPQ		;SET PAGE STATE TO ON SPMQ
	STOR T2,CSTAGE,+T1	; ...
	CALL OFFSPQ		;TAKE IT OFF SPMQ

	SETZ T1,
	EXCH T1,.QCPID(Q1)	;GET PAGE SAY NO PAGE
	MOVX T3,PSTAVL		;SET SPECIAL PAGE STATE TO AVAILABLE
	STOR T3,CSTPST,+T1	; ...
	SKIPG NRPLQ		;ANY PAGES BEFORE THIS?
	CALL MSSCZK		;NO, MAKE SCHED KNOW TO RUN US SOON
	CALL OFRQ		;AND PLACE IT ON RPLQ

CLENU2:	SETZ T1,
	EXCH T1,.QCDBD(Q1)	;MARK NO BUFFER
	JUMPE T1,CLENU1		;MAY BE NO BUFFER
	BLCAL. (SC.UMP,<T1>)	;UNMAP BUFFER
	 SCAERR <BUG.(CHK,MSSUMP,PHYMVR,SOFT,<Unmap buffer failed>,<<T1,REASON>>,<

Cause:	A routine was called to unmap a buffer and failed when it should 
	not have.

Data:	REASON - error code
>,CLNUME)>
	SETZ T1,
CLENU1:	EXCH T1,.QCIORB(Q1)	;MARK COMMAND AS HAVING NO IORB AND GET IORB
	SKIPN SVIRBH		;WERE THERE ANY IORBS BEFORE WE RETURNED THIS?
	CALL MSSCZK		;NO, MAKE SCHED KNOW ABOUT US SOON
	EXCH T1,SVIRBH		;MAKE THIS HEAD
	MOVEM T1,@SVIRBH	;AND POINT TO NEXT
	RET

CLNUME:	MOVX T1,ST.DAT		;SET DATA ERROR
	CALL REVFUL
	IORM T1,P.STS(Q1)
	SETZ T1,		;AND CONTINUE
	JRST CLENU1
;SUBROUTINE TO FIND THE COMMAND
; T1/ COMMAND REFERENCE NUMBER
; Q3/ SCDB ADDRESS
; RETURNS +1: NOT FOUND
;	+2: T1/ ADDRESS OF COMMAND
;
FNDCMD:	SKIPN T2,.SVCMD(Q3)	;ANY COMMANDS?
	RET			;NO
FNDCM1:	CAMN T1,P.CRF(T2)	;SAME COMMAND
	JRST [MOVE T1,T2	;YES
	      RETSKP]		;AND RETURN SUCCESS
	SKIPE T2,.QCNXT(T2)	;GET NEXT
	JRST FNDCM1
	RET

;BYTE SWAP ROUTINES
;REVW2 - REVERSE 36 BIT WORD TO BE SENT AS 32 BIT WORD
;REVWF - REVERSE 32 BIT WORD INTO 36 BIT WORD
REVW2:	LSH T1,4		;POSITION IN 32 BITS
	CALLRET REVFUL		;SWAP

REVWF:	CALL REVFUL		;SWAP
	LSH T1,-4		;AND MAKE IT FIT IN REAL SIZED WORDS
	RET

;SETQ3 - SETUP POINTER TO SERVER CONNECTION DATA BLOCK (SCDB)
; T2/ CID
;	CALL SETQ3		;(T2/Q3)
;SETQ3I - SETUP POINTER TO SCDB USING INDEX IN Q3
; Q3/ CID INDEX
;	CALL SETQ3I		;(Q3/Q3)
; RETURNS +1: NO SCDB FOR CID
;	  +2: SUCCESS, Q3 HAS ADDRESS OF SCDB
;
SETQ3:	LOAD Q3,SID,T2		;GET CID INDEX
SETQ3I:	SKIPN Q3,SCDBTB(Q3)
	RET
	RETSKP
;
; BUGHLTS USED BY VARIOUS PIECES OF PHYMVR
;
SCDBBG:	MOVE T1,T2
	CALL SC.NOD
	BUG.(HLT,MSSCID,PHYMVR,SOFT,<Illegal connect ID index>,<<T2,NODE>,<T1,CID>>,<

Cause:	The MSCP server cannot locate a SCDB for the given connect ID.

Data:	NODE - node number
	CID - connect ID
>)
	RET

ILLFCN:	BUG.(HLT,MSSSCA,PHYMVR,SOFT,<MSCP SERVER - Server detected SCA error>,<<T1,SCAFNC>,<T2,ARG1>,<T3,ARG2>,<T4,ARG3>>,<

Cause:	The MSCP server detected an illegal response from SCA.

Data:	SCAFNC - SCA function code
	ARG1 - ARG3 - SCA function arguments
>)

ILSTAT:	BUG.(HLT,MSSSTA,PHYMVR,SOFT,<MSCP SERVER - Illegal state>,,<

Cause:	The MSCP server detected an illegal command or connection state.

>,R)
;SUBROUTINE TO FIND SPECIFIED UNIT OR NEXT UNIT NUMBERED HIGHER

;	T1/MSCP UNIT NUMBER
;
;RETURNS:
;	+1 FAILED
;		T1 = 0	INVALID UNIT (OUT OF RANGE)
;		   = ST.OFL OFFLINE
;	+2 SUCCESS
;		T1 = NEW UNIT NUMBER
;		P1-P3 CHANNEL, KONTROLLER, UNIT
;
FNDUNT:	MOVE T1,P.MOD(Q1)	;GET COMMAND MODIFIERS
	CALL REVFUL
	TXNE T1,MD.NXU		;NEXT UNIT MODIFIER SET
	TDZA T1,T1		;YES ALLOW STEPPING
FNDUNN:	SETO T1,		;NO STEPPING ALLOWED
	STKVAR <STPFLG,CHANN,KONTN,UNITN>
	MOVEM T1,STPFLG		;SAVE ENTRY FLAG
	MOVE T1,P.UNIT(Q1)	;GET UNIT NUMBER
	CALL REVWF		;IN NORMAL FORMAT
	SOS T1			;MAKE IN RANGE 0-MAXUNN
	CAILE T1,MAXUNN		;GREATER THAN MAX UNIT
	 JRST [SETZ T1,
	       RET]
	IDIVI T1,CHNCOD		;GET CHANNEL AND KONTROLLER
	IDIVI T2,KONCOD		;KONTROLLER AND UNIT
	SOS T2			;MAKE KONT BE IN RANGE -1:7
	MOVEM T1,CHANN		;SAVE DATA
	MOVEM T2,KONTN		; FOR STEPPING
	MOVEM T3,UNITN		; LATER
	CALL CHKCKS		;VALID?
	JRST FNDSTU		;NOPE TRY TO STEP.
	MOVE P3,T1		;UDB
FNDUN1:	HRRZ P2,UDBKDB(P3)	;SET UP KDB POINTER
	HRRZ P1,UDBCDB(P3)	;AND CDB POINTER
	CALL FNDCKS		;GET NUMBERS
	MOVEM T1,CHANN		;SAVE THEM
	MOVEM T2,KONTN
	MOVEM T3,UNITN
	MOVE T1,UDBSTS(P3)	;GET FLAGS
	TXNN T1,US.CIP		;A CI DEVICE?
	TXNN T1,US.DSK		;A DISK?
	JRST FNDSTU		;CI OR NON DISK, STEP
	TXNN T1,US.CIA		;AVAILABLE?
	JRST FNDSTU		;NO AND DEFAULT REFUSE STEP
	MOVE T1,CHANN		;FOUND ONE GET NUMBERS
	MOVE T2,KONTN
	MOVE T3,UNITN
	CALL MSCUNT		;GET MSCP UNIT NUMBER (T1,T2,T3/T1)
	CALL ILSTAT
	RETSKP
FNDSTU:	MOVX T1,ST.OFL		;READY FOR OFFLINE
	SKIPE STPFLG		;STEPPING?
	RET			;NO. FAILURE
	MOVE T1,CHANN		;GET PREVIOUS C
	MOVE T2,KONTN		; K
	MOVE T3,UNITN		; AND U
	CALL ADVCKS		;STEP
	 JRST RETZ		;NONE
	MOVE P3,T4		;UDB
	JRST FNDUN1		;FOUND IT CHECK IT OUT

;******
MSCUNT:	CAILE T1,MAXCNT		;TOO BIG
	RET
	AOS T2
	CAILE T2,MAXKNT		;TOO BIG
	RET
	CAILE T3,MAXUNT		;TOO BIG
	RET
	IMULI T1,CHNCOD		;CONVERT CHANNEL KONTROLLER UNIT TO MSCP UNIT
	IMULI T2,KONCOD		;KONTROLLER
	ADD T1,T2		;ADD KONTROLLER
	ADD T1,T3		;ADD UNIT
	AOS T1			;MAKE IN RANGE 1-MAXUNN
	RETSKP
	SWAPCD

;MSSRED - TMON FUNCTION - .SFMSD
; T2/ ADDRESS OF ARGUMENT BLOCK
;
;	MOVEI 1,.SFMSD
;	MOVE 2,<address of block>
;	TMON%
;
; RETURNS +1 ALWAYS 
;            T2/ 1	-  DRIVE IS AVAILABLE THROUGH THE MSCP SERVER
;            T2/ 0      -  DRIVE IS UNAVAILABLE
;
MSSRED::JE SVSINF,,[ITERR(MSCPX4)] ;NOT INITIALIZED
	UMOVE T1,.SVCNT(T2)	;GET SIZE OF THE BLOCK
	CAIGE T1,.SVDSN+1	;BIG ENOUGH?
	 ITERR(ARGX04)		;NO.
	CALL FNDSER		;FIND THE DRIVE
	SETZ T1,		;ASSUME UNAVAILABLE
	MOVE T2,UDBSTS(T4)	;GET STATUS
	TXNE T2,US.CIA		;AVAILABLE?
	MOVEI T1,1		;YES
	RET			;ALL DONE
	
;MSSMRK - SMON FUNCTION - .SFMSD - MARK SERVER DISKS 
; T2/ ADDRESS OF ARGUMENT BLOCK
;
;	MOVEI 1,.SFMSD
;	MOVE 2,<address of block>
;	SMON%
;
; RETURNS +1: ALWAYS, UNIT UNAVAILABLE OR NOT FOUND
;
MSSMRK::JE SVSINF,,[ITERR(MSCPX4)] ;IF NOT INITIALIZED REPORT NO SERVER
	UMOVE T1,.SVCNT(T2)	;GET SIZE OF THE BLOCK
	CAIGE T1,.SVDSN+1	;BIG ENOUGH?
	 ITERR(ARGX04)		;NO.
	UMOVE T1,.SVTYP(T2)	;GET FLAGS
	TXNN T1,SV%DDU		;SETTING UNAVAILABLE?
	JRST MSSSRV		;NO, AVAILABLE.
	CALL FNDSER		;FIND DISK UDB FOR THIS SERIAL NUMBER
	MOVX T1,US.CIA		;CLEAR AVAILABLE BIT
	ANDCAM T1,UDBSTS(T4)
	RET

; HERE TO MARK DISK AVAILABLE

MSSSRV:	CALL FNDSER		;GET DISK
	MOVX T1,US.CIA		;SET AVAILABLE BIT
	IORM T1,UDBSTS(T4)
	NOINT
	CALLRET MSXATA		;TELL THE WORLD
;FNDSER - FIND A UNIT BY SERIAL NUMBER
;
;  T2/  ADDRESS OF USERS ARGUMENT BLOCK FOR SMON JSYS
;  RETURN
; CALL FNDSER			;(T2/T4)

FNDSER:	SAVEQ
	STKVAR <DSH,DSN>	;HIGH AND LOW ORDER SERIAL NUMBERS
	UMOVE T3,.SVDSH(T2)	;GET SERIAL NUMBER (HIGH)
	UMOVE T4,.SVTYP(T2)	;GET TYPE AND FLAGS
	TXZ T4,SV%DDU		;CLEAR FLAGS
	TXO T4,400		;DISK TYPE 144
	LSH T4,20		;POSITION IT
	CAME T4,T3		;MATCH?
	 ITERR(MSCPX2)		;NO, DRIVE TYPE ERROR
	MOVEM T3,DSH		;OK. SAVE IT
	UMOVE T3,.SVDSN(T2)	;GET DSN
	MOVEM T3,DSN		;SAVE IT
	SETOB Q1,Q3		;NO CHANNEL NO UNIT START WITH FIRST
	SETZ Q2,
SERNXT:	DMOVE T1,Q1		;GET SAVED VALUES
	MOVE T3,Q3
	CALL ADVCKS		;GET UNIT
	 ITERR(MSCPX3)		;NONE. DRIVE NOT FOUND
	DMOVE Q1,T1
	MOVE Q3,T3		;SAVE LATEST VALUES
	MOVE T1,UDBSTS(T4)	;GET BITS
	TXNN T1,US.DSK		;A DISK?
	JRST SERNXT		;NON DISK IS NO GOOD
	MOVE T2,UDBDSN(T4)	;GET SERIAL NUMBER
	CAME T2,DSN		;SAME ONE?
	JRST SERNXT		;NO
	MOVE T2,UDBDSH(T4)	;YES, NOW CHECK 
	TXNN T1,US.CIP		;A CI DEVICE?
	CAME T2,DSH		;IS IT THE SAME?
	 ITERR(MSCPX2)		;NOT SAME OR CI, DRIVE TYPE ERROR
	RET
	RESCD

;MSSONL - MSCP SERVER STUB OF DISK ONLINE
;ENTER HERE FROM PHYSIO TO BROADCAST THE UNIT STATUS IF THE UNIT IS AVAILABLE
;IF NOT FLAG JOB 0 TO RUN SETSPD AND DO BROADCAST LATER IF IT GETS SET 
;AVAILABLE
; P3/ UDB
;
;	CALL MSSONL		;(P3/)
;
; RETURNS +1: ALWAYS
;
MSSONL::EA.ENT			;RUN IN 1
	MOVE T1,UDBSTS(P3)	;GET BITS
	TXNE T1,US.DSK		;A DISK?
	TXNE T1,US.CIP		;CI DISK
	RET			;NOT A DISK OR CI DISK, IGNORE IT
	MOVE T4,P3		;READY TO CALL BROADCAST
	TXNE T1,US.CIA		;CI AVAILABLE ALREADY!
	CALLRET MSXATA		;NO. TELL THE WORLD (T4/)
	AOS JB0FLG		;RUN JOB 0
	AOS MTAJB0		;AT NEW MTA AND DISK ENTRY POINT
	RET

;MSSOFL - MSCP SERVER STUB OF DISK OFFLINE
;
MSSOFL::MOVE T1,UDBSTS(P3)
	TXNN T1,US.DSK		;A DISK
	RET			;NO FORGET IT
	MOVX T1,UC.OLB		;GET ONLINE BITS
	ANDCAM T1,UDBCHR(P3)	;CLEAR THEM
	RET
;MSXATA - UNIT AVAILABLE BROADCAST
;CALLED FROM .SMON CODE WHEN A UNIT IS SET CI AVAILABLE OR FROM PERIODIC
;CHECK IF FIRST BROADCAST DID NOT WORK
; T4/ UDB
;	CALL MSXATA		;(T4/)
; RETURNS +1: ALWAYS
;
MSXATA:	SAVEPQ			;PRESERVE THESE
	AOS SVBDKN		;BROADCAST COUNT
	MOVE P3,T4		;PHYSIO CALLING CONVENTIONS
	MOVE P2,UDBKDB(P3)
	MOVE P1,UDBCDB(P3)
	MOVX T1,US.BDK		;REMEMBER. BROADCAST IS NEEDED
	IORB T1,UDBSTS(P3)	; UNTIL WE ARE DONE
	TXNN T1,US.DSK		;A DISK
	 JRST ATADOK		;NO. FORGET IT
	MOVE T2,CDBSTS(P1)	;AND CHANNEL STATUS
	TXNN T1,US.OFS		;UNIT OFFLINE?
	TXNE T2,CS.OFL		;OR CHANNEL OFFLINE?
	 JRST ATADOK		;YES, DON'T BOTHER
	SETZ P4,		;NO PROBLEMS YET
	MOVSI Q1,-CFSNUM	;NUMBER OF NODES TO BROADCAST TO
	SKIPA			;DON'T DECREMENT INITIAL BUFFER COUNT
ATALUP:	SOS SVCMIU		;GETTING A NEW BUFFER. KEEP COUNT
	CALL GETBF		;GET A BUFFER
	 RET			;CANNOT
	CALL FNDCKS		;GET C K U
	CALL MSCUNT		;CONVERT TO MSCP FORMAT
	 CALL ILSTAT		;FATAL ERROR! SHOULD NEVER HAPPEN
	CALL REVW2
	MOVEM T1,P.UNIT(Q2)	;SAVE UNIT NUMBER
	MOVX T1,OP.AVA		;OPCODE
	CALL REVFUL
	MOVEM T1,P.OPCD(Q2)
	SETZ T1,		;SETUP UNIT INFO
	CALL SETUI0
	 JFCL
ATALU1:	SKIPN Q3,SCDBTB(Q1)	;GET ADDRESS OF SCDB
	JRST ATANXT		;NOT USED
	LOAD T1,SVSTA,(Q3)	;GET CONNECTION STATE
	MOVE T2,.SVCIS(Q3)
	CAIN T1,SCOKS		;OK TO SEND?
	TXNN T2,MC.ATN		;WANT ATTENTION MESSAGES?
	JRST ATANXX		;SHUTDOWN OR NO ATTENTION MESSAGES SKIP IT
	MOVE T1,.SVCID(Q3)	;GET CID INDEX
	LOAD T1,SID,T1
	MOVE T2,UDBCHR(P3)	;AND UDB CHARACTERISTICS
	TDNE T2,BITS+<^D36-CFSNUM>(T1) ;ONLINE ALREADY?
	JRST ATANXX		;YES DO NEXT
	
	BLCAL.	(SC.SMG,<.SVCID(Q3),[0],[P%RCTC],Q2,[MVRPRI],[0],[0]>) ;SEND THE PACKET
	 SCAERR <SETO P4,>	;REMEMBER ERROR
	AOS SVSEND		;[7211] COUNT THE SEND
	SKIPN P4		;ERROR
	SETZ Q2,		;SENT MESSAGE OK. DON'T RETURN BUFFER
ATANXT:	SKIPN Q3		;STILL LOOKING FOR A BLOCK?
ATANXX:	AOBJN Q1,ATALU1		;YES. DON'T NEED A BUFFER TO LOOP
	AOBJN Q1,ATALUP		;DID ONE, TRY MORE AND GET A BUFFER
	SKIPE Q2		;NEED TO RETURN BUFFER?
	CALL RTNEND		;YES.
	JUMPN P4,R		;PROBLEMS TRY AGAIN LATER.
ATADOK:	MOVX T1,US.BDK		;ALL OK. CLEAR BROADCAST NEEDED
	ANDCAM T1,UDBSTS(P3)
	SOS SVBDKN		;ALL DONE WITH THIS UNIT
	RET
;QUECMD - ADD A COMMAND TO THE QUEUE
; Q1/ COMMAND
; Q3/ SCDB
;	CALL QUECMD		;(Q1,Q3/)
; RETURNS +1 ALWAYS
QUECMD:	JN MSCOQ,(Q1),R		;IF ALREADY QUEUED JUST RETURN
	SETONE MSCOQ,(Q1)
	MOVE T1,[MSEC1,,RTNQCE]	;GET RETURN ADDRESS FOR QUEUED COMMANDS
	EXCH T1,.QCRTN(Q1)	;SAVE NEW ADDRESS GET OLD ONE
	MOVEM T1,.QCRT2(Q1)
	SETZM .QCNXT(Q1)		;ZERO LINK
	SKIPE T2,.SVCME(Q3)	;ADDRESS OF TAIL
	MOVEM Q1,.QCNXT(T2)	;POINT TAIL TO THIS
	MOVEM T2,.QCLST(Q1)	;AND POINT THIS AT TAIL
	MOVEM Q1,.SVCME(Q3)	;THIS IS NOW TAIL
	SKIPN T2		;WERE THERE ANY?
	MOVEM Q1,.SVCMD(Q3)	;NO. THIS IS THE FIRST TOO
	MOVE T1,TODCLK		;COMPUTE NEXT TIMEOUT INTERVAL
	ADDI T1,SVRTMI
	MOVEM T1,.QCTMO(Q1)	;AND SAVE IT
	RET

;RTNQCE - RETURN QUEUED COMMAND
; T1/ COMMAND
; Q3/ SCDB ADDRESS
;
RTNQCE:	SAVEAC <Q1>		;ALL OTHER ROUTINES EXPECT COMMAND IN Q1
	MOVE Q1,T1		;SO DON'T DISAPOINT THEM
	MOVX T2,MS.COQ		;GET QUEUED BIT
	TDNN T2,.QCSTS(Q1)	;REALLY QUEUED?
	CALL ILSTAT		;NO! ILLEGAL STATE
	ANDCAM T2,.QCSTS(Q1)	;YES, CLEAR BIT WE ARE DEQUEUEING NOW
	CALL CLENUP		;CLEANUP EXTRANEOUS JUNK IF ANY
	MOVE T2,.QCLST(T1)	;GET PREVIOUS
	SKIPE T3,.QCNXT(T1)	;AND NEXT IF ANY
	MOVEM T2,.QCLST(T3)	;POINT NEXT AT PREV
	SKIPE T2		;PREVIOUS EXIST?
	MOVEM T3,.QCNXT(T2)	;YES. POINT PREV AT NEXT
	CAMN T1,.SVCME(Q3)	;LAST ENTRY?
	MOVEM T2,.SVCME(Q3)	;YEP MAKE PREVIOUS LAST
	CAMN T1,.SVCMD(Q3)	;FIRST ENTRY?
	MOVEM T3,.SVCMD(Q3)	;YEP MAKE NEXT FIRST
	JRST @.QCRT2(T1)	;RETURN BUFFER

;RTNCMD - RETURN COMMAND BUFFER
; Q1/ COMMAND
; Q3/ SCDB ADDRESS
;	CALL RTNCMD		;(Q1,Q3/)

RTNCMD:	MOVE T1,Q1		;RETURN ROUTINES WANT BUFFER ADDRESS IN T1
	SOS SVCMIU		;COUNT PACKETS IN USE
	CALLRET	@.QCRTN(T1)	;RETURN THE PACKET BUFFER
;ABTEND - SEND END PACKET FOR ABORTED COMMAND
;ABTEN0 - ENTRY FOR COMMAND ADDRESS IN Q1 (RETRYING QUEUED COMMANDS)
; T1/ COMMAND BEING ABORTED (ABTEND ONLY)
; Q3/ SCDB ADDRESS
;	CALL ABTEND		;(T1,Q3/)
; RETURNS +1: ALWAYS, END SENT OR COMMAND ON QUEUE
;
ABTEND:	SAVEQ
	MOVE Q1,T1		;GET COMMAND BEING ABORTED IN CORRECT PLACE
ABTEN0:	CALL CLENUP		;RELEASE ANY RESOURCES NOW
	CALL GETEBF		;GET A END PACKET BUFFER FOR ABORTED COMMAND
	 RET			;CAN'T COMMAND IS FLAGGED AS ABORTED
	MOVE T1,P.UNIT(Q1)	;GET UNIT NUMBER FROM ABORT COMMAND
	MOVEM T1,P.UNIT(Q2)	;SAVE IN END PACKET
	MOVE T1,P.STS(Q1)	;GET STATUS, OPCODE
	CALL REVFUL
	TXO T1,ST.ABO!OP.END	;ADD ABORTED AND END TO STATUS
	CALL REVFUL
	MOVEM T1,P.STS(Q2)	;SAVE IN PACKET
	MOVEI T3,P%STS
	CALLRET SNDEND		;SEND END PACKET
;SET UNIT ID INFORMATION IN MESSAGE
;

SETUID:	MOVE T1,P.UNFL(Q1)	;GET FLAGS
	CALL REVFUL		;IN CORRECT FORMAT
	TXZE T1,UF.CMR+UF.CMW+UF.INA+UF.WPS ;ANY UNSUPPORTED FLAGS?
	JRST [BADCMV P.UNFL
	      RET]		;RETURN ERROR
	TXZ T1,UF.SCH+UF.SCL+UF.WBN
SETUI0:	TXO T1,UF.576+UF.RMV	;ALL DISKS HAVE 576 BYTE SECTORS MOST ARE REMOVABLE
	MOVE T2,UDBSTS(P3)	;GET STATUS FLAGS
	TXNE T2,US.WLK		;WRITE LOCKED
	TXO T1,UF.WPS+UF.WPH	;YES SAY SO
	LOAD T2,USTYP,(P3)	;GET DISK TYPE
	CAIE T2,.UTRP7		;RP07 AND
	CAIN T2,.UTP20		;RP20 ARE
	TXZ T1,UF.RMV		;NON REMOVABLE
	CALL SRVFUL
	MOVEM T1,P.UNFL(Q2)	;SAVE FLAGS
	MOVE T1,T2		;GET MEDIA TYPE
	CALL REVW2		;REVERSED
	MOVEM T1,P.MEDI(Q2)	;SAVE IT
	MOVE T1,UDBDSN(P3)	;SAVE SERIAL NUMBER
	CALL REVW2
	MOVEM T1,P.UNTI(Q2)
	MOVE T1,UDBDSH(P3)	;STORE HIGH ORDER SERIAL NUMBER
	CALL REVW2
	MOVEM T1,P.UNTI+1(Q2)
	RETSKP
	SUBTTL CFS Interface

;SRVCFS - CALLED BY CFS WHEN A LISTNER CAN BE OFFERED
;
SRVCFS::SETONE SVSLIS
	RET



;MSSSVD - CALLED BY "SYSTEM GOING DOWN" CODE TO SEE IF THERE ARE ANY
;SERVED DISKS
;	CALL MSSSVD		;(/)
; RETURN +1: NO SERVED DISKS
;        +2: AT LEAST 1 SERVED DISK

MSSSVD::SKIPGE SVSLSX		;IS THERE A LISTENER?
	RET			;NO
	TRVAR <SVD>
	SETZM SVD		;START WITH NO SERVED UNITS
	MOVEI P4,CHNTAB		;CHECK ALL CHANNELS
MSSSVL:	CAIL P4,CHNTAB+7	; EXCEPT CI.  DONE?
	RET			;YES, DIDN'T FIND ANY SERVED UNITS
	SKIPN P1,(P4)		;NO, IS THERE A CDB?
	IFSKP.
	   CALL DGUMAP		;(P1/) YES, LOOP OVER ALL UNITS ON CHANNEL
	    CALL MSSSVC		;(P3/) CHECK FOR ONLINED BY SERVER
	   SKIPE SVD		;FOUND ANY YET?
	   RETSKP		;YES
	ENDIF.
	AOJA P4,MSSSVL		;NO, CHECK NEXT CHANNEL
;MSSSVC - COROUTINE OF MSSSVD, CALLED FOR EACH UDB FOUND BY DGUMAP
; P3/ UDB
;	CALL MSSSVC		;(P3/)
; RETURN +1

MSSSVC:	MOVX T4,UC.OLB		;GET MASK FOR ONLINE
	TDNE T4,UDBCHR(P3)	;ONLINED VIA SERVER?
	SETOM SVD		;YES
	RET			;NO

	ENDTV.

;MSSCZK - MAKE SCHEDULER RUN US ASAP WITHOUT HOSING OTHERS
;
MSSCZK:	SETZM MSSTIM		;FORCE FAST RETRY
	AOS PSKD1		;TELL SCHED SOMETHING TO DO
	RET

	SWAPCD
	SUBTTL End of PHYMVR

	TNXEND

	END