Google
 

Trailing-Edge - PDP-10 Archives - BB-P363B-SM_1985 - mcb/drivers/nrm.m11
There are no other files named nrm.m11 in the archive.
	.TITLE	NRM - NODE RESOURCE MANAGER
	.IDENT	/007000/
	.ENABL	LC

;
;                    COPYRIGHT (c) 1980, 1981, 1982
;                    DIGITAL EQUIPMENT CORPORATION
;                        Maynard, Massachusetts
;
;     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  which  is  not supplied by
;     DIGITAL.
;
; VERSION 01
;
; R.A. MODEEN	02-MAY-77
;
; VERSION 02
;
; L.D. WEBBER	26-SEP-77
;
; VERSION 5
;
; A.D. PECKHAM	25-JAN-78
;
; VERSION 7
;
; A.D. PECKHAM  6-JUN-80
;
; MACRO LIBRARY CALLS
;
	.MCALL	CCBDF$,DAT$,DSP$B,ScDF$,PHD$b
	.MCALL	MAP$,POP$S,PUSH$S,SAVMAP,RESMAP
	.MCALL	NCRA$,NACC$,NREJ$,NDAK$,NDIS$,NABO$
	.MCALL	NDAT$,NDRQ$,NRTN$,NIRQ$,NRTI$
	CCBDF$			; DEFINE CCB OFFSETS
	scDF$			; DEFINE Sc OFFSETS
	nrmdf$
;
; LOCAL MACROS
;
;  GTPCB$ - GET THE ASSOCIATED PCB IN R3
;

	.MACRO	GTPCB$
	GTULA$	R0
	CALL	$PCBPT
	.ENDM	GTPCB$

;
;  GTTCB$ - GET THE ASSOCIATED TCB IN R5
;

	.MACRO	GTTCB$
	CLR	R0
	BISB	C.lix(R4),R0
	CALL	$TCBTT
	.ENDM	GTTCB$

;
;  RESPOND - SEND A RESPONSE TO THE CURRENT RESOURCE MESSAGE
;

	.MACRO	RESPOND	CODE,SUB
	.IF EQ	<'CODE'-RC.IRC>	; ILLEGAL REQUEST CODE
	JMP	INVALID
	.IFF
	.IF	NB,<CODE>	; RESPONSE CODE
	MOV	#'CODE',R0
	.ENDC
	.IF	NB,<SUB>	; OPTIONAL DATA
	MOV	#'SUB',R5
	.ENDC
	JMP	RSPNS
	.ENDC
	.ENDM	RESPOND
	.SBTTL	ATS RESOURCE MANAGER SYMBOL DEFINITIONS
;+
; THESE SYMBOL DEFINITIONS ARE LOCAL TO THE ATS RESOURCE MANAGER.
; THE SYMBOLS WHICH ARE USED BY ALL THE ATS COMPONENTS (RESOURCE
; MANAGER AND DIALOGUE MANAGERS) ARE DEFINED IN THE MACRO TTDF$
; IN THE LIBRARY CELIB.MLB.
;-
 
; REQUEST CODES (SET IN 1ST BYTE OF RESOURCE MESSAGE)
 
RQ.RID=		041		; REQUESTOR ID
RQ.CAP=		042		; CAPABILITIES
RQ.RES=		047		; RESPONSE
RQ.SPC=		050		; SPECIFY
RQ.ACC=		051		; ACCESS
RQ.ASS=		052		; ASSIGN
RQ.STS=		053		; STATUS
RQ.CTL=		054		; CONTROL
 
 
 
; REQUEST TYPE CODES (SET IN 2ND BYTE OF RESOURCE MESSAGE)
 
; <SPECIFY> MESSAGE TYPES
 
SY.RES=		001		; RESERVE
SY.SHR=		002		; SHARE
SY.REF=		003		; REFER
 
; <SPECIFY> MESSAGE FLAGS
 
SY.DBL=		020		; DOUBLE (CONCATENATED) MESSAGE FLAG
 
; RANGE LIMITS FOR REQUEST CODE OF SECOND (CONCATENATED) MESSAGE
 
RS.LOW=		051		; LOW LIMIT FOR REQUEST CODE
RS.HIH=		053		; HIGH LIMIT FOR REQUEST CODE
 
; <ACCESS> MESSAGE TYPES
 
AC.SIN=		001		; OPEN SINGLE LOGICAL LINK
AC.SEP=		002		; OPEN SEPARATE DATA LINK
AC.CLO=		003		; CLOSE
AC.REL=		004		; RELEASE
 
 
; <ASSIGN> MESSAGE TYPES
 
AS.ASS=		001		; ASSIGN
AS.RES=		002		; RECLAIM
AS.HAN=		003		; HANDOFF
 
 
; <STATUS> MESSAGE TYPES
 
ST.QRY=		001		; QUERY
ST.REP=		002		; STATUS-REPORT
ST.ALT=		003		; STATUS-ALTER
 
 
; <STATUS> MESSAGE SUB-TYPES
 
SS.OPR=		001		; OPERATIONAL STATUS
SS.RES=		002		; RESOURCE CONTROL
SS.ERR=		003		; ERROR STATISTICS
SS.USA=		004		; USAGE ACCOUNTING
SS.ATS=		010		; ATS TERMINAL STATUS
 
; <STATUS> MESSAGE FLAGS
 
ST.REL=		020		; AUTOMATIC STATUS-RELEASE FLAG

 
; <RESPONSE> CODE DEFINITIONS
 
RC.FIN=		0.		; FINAL RESPONSE, NO ERROR
RC.INT=		1.		; INTERMEDIATE RESPONSE
RC.ACC=		2.		; HANDOFEE ACCEPTS RESOURCE
RC.ANP=		20.		; ACCESS NOT PERMITTED
RC.IAC=		21.		; INVALID ACCOUNTING INFORMATION
RC.IRC=		22.		; INVALID OR UNSUPPORTED REQUEST TYPE
RC.ICT=		23.		; INVALID REQUEST CONCATENATION
RC.RQO=		24.		; CONTROL ID ALREADY IN USE
RC.RNE=		25.		; SPECIFIED RESOURCE DOES NOT EXIST
RC.RNA=		26.		; REQUESTED RESOURCE NOT AVAILABLE
RC.IRD=		27.		; INVALID RESOURCE DESCRIPTOR FORMAT
RC.GND=		28.		; GENERIC DESCRIPTOR NOT SUPPORTED
RC.SHN=		29.		; SHARED ACCESS NOT SUPPORTED
RC.RSO=		30.		; TOO MANY USERS OF THE RESOURCE
RC.MLN=		31.		; MULTI-LINK USAGE NOT SUPPORTED
RC.SLN=		32.		; SINGLE-LINK USAGE NOT SUPPORTED
RC.ISO=		33.		; INVALID SERVOR OPTION FIELD
RC.SNE=		34.		; SPECIFIED SERVOR DOES NOT EXIST
RC.CNO=		35.		; TOO MANY CONNECTIONS TO SERVOR
RC.RNS=		36.		; RESOURCE NOT SUPPORTED BY SERVOR
RC.RJS=		37.		; REQUEST REJECTED BY SERVOR
RC.RSI=		38.		; RESOURCE OR SERVOR STATE INCONSISTENCY
RC.RSE=		39.		; REQUEST MESSAGE SEQUENCE ERROR
RC.HNE=		40.		; HANDOFEE DOES NOT EXIST
RC.REJ=		41.		; HANDOFEE REJECTS RESOURCE
RC.ACA=		42.		; ACCEPTANCE OF HANDOFF ABORTED
 
 
; <RESPONSE> MESSAGE DATA
 
RD.PNC=		1.		; DATA PIPE NOT CONNECTED
RD.STR=		2.		; START THRESHOLD ERROR
RD.NDI=		1.		; REQUESTED RESOURCE NOT ONLINE
 
 
; <STATUS-REPORT> MESSAGE DATA
 
RP.RCV=		1.		; RECEIVE ERROR THRESHOLD ERROR
RP.REP=		2.		; REPLY THRESHOLD ERROR
RP.NAK=		3.		; NAK THRESHOLD ERROR
RP.TRM=		4.		; HARD TERMINAL ERROR
RP.IRQ=		5.		; INTERVENTION REQUIRED AT TERMINAL
RP.PWF=		6.		; POWERFAIL
RP.DSC=		7.		; DATA PIPE DISCONNECTED



;*THESE DEFINITIONS MUST *NOT* BE CHANGED !!!

;
; BIT MASKS
;

PS.RCN	= PS.CI!PS.CC!PS.DIP		; PIPE READY FOR CONNECT
TS.OCP	= TS.CLP!TS.OPP!TS.OP		; TERMINAL OPEN OR CLOE PENDING
TS.ROP	= TS.OCP!TS.RLP!TS.HP		; TERMINAL READY FOR OPEN
TF.RAL	= TF.DEA!TF.DIS			; TERMINAL READY FOR ALLOCATION
;+
; INTERNAL DATA BASE FOR PROCESS
;-
 

;+
; THESE DISPATCH TABLES ARE USED BY THE CCB DISPATCHER TO PASS CONTROL
; TO THE APPROPRIATE ROUTINE IN THE RESOURCE MANAGER BASED ON THE FUNCTION
; AND SUBFUNCTION PASSED IN THE CCB.
;-

	phd$b	NRM
	phd$d	nrmtb
	phd$e


; FUNCTION DISPATCH TABLE
 
	.PSECT	$PLIT$,D
NRMTB:	DSP$B			; DISPATCH TABLE ADDRESS
	DSP$	FC.AST		; SRV Server error
	DSP$	FC.XME		;     TRANSMIT ENABLE ENTRY
	DSP$	FC.RCE		;     RECEIVE ENABLE ENTRY
	DSP$	FC.KIL		;     KILL ENABLE ENTRY
	DSP$	FC.CTL		; SRV CONTROL ENABLE ENTRY
	DSP$	FC.TIM,NRMTIM	;     TIMEOUT ENTRY
	DSP$	FC.XCP,NRMXCP	;     TRANSMIT COMPLETE ENTRY
	DSP$	FC.RCP,NRMRCP	; NSP RECEIVE COMPLETE ENTRY
	DSP$	FC.KCP		;     KILL COMPLETE ENTRY
	DSP$	FC.CCP,NRMCCP	;     CONTROL COMPLETE ENTRY
RM$RWT	= .-NRMTB
	DSP$	RM$RWT,NRMRWC	; NRM RESOURCE WAIT COMPLETE
	DSP$E
 
; 
; SUB-FUNCTION DISPATCH
;

NRMXCP:	JMP	@10$(R3)	; Dispatch SC Transmit Complete:

10$:	DSP$B
	DSP$			; S$CON	- Connect complete
	DSP$	,REQUEST	; S$ACC	- Accept complete
	DSP$			; S$REJ	- Reject complete
	DSP$	,NRMDAT		; S$SND	- Data transmited
	DSP$			; S$MRQ	- Message request
	DSP$	,$CCBRT		; S$DRQ	- Segment request
	DSP$			; S$SNI	- Interrupt transmitted
	DSP$			; S$IRQ	- Interrupt requested
	DSP$			; S$DIS	- Disconnect complete
	DSP$	,NRMDIS		; S$ABO	- Abort complete
	DSP$			; S$GLN	- Here is local node information
	DSP$E
 
NRMTIM:	jmp	@10$(r3)	; Timer dispatch vector

10$:	dsp$b
	dsp$			;short timer
	dsp$	,nrmtm		;long timer
	dsp$			;power fail
	dsp$	,pinset		;process initilization
	dsp$e

NRMRCP:	JMP	@10$(R3)	; Dispatch SC Receive Complete:

10$:	DSP$B
	DSP$	,NSPCON		; S$CNR	- Connect received
	DSP$	,NSPDAT		; S$DAT	- Data received
	DSP$			; S$INT	- Interrupt message received
	DSP$	,nspdis		; S$DSR	- Disconnect received
	DSP$E
 

 
NRMCCP:	JMP	@10$(R3)	;DISPATCH CONTROL COMPLETE:

10$:	DSP$B
	DSP$
	DSP$	FM.STR,SRVSTR	; SRV START COMPLETE ENTRY POINT 
	DSP$	FM.STP,SRVSTP	; SRV STOP COMPLETE ENTRY POINT 
	DSP$E
	.SBTTL	RESOURCE MESSAGE DISPATCH TABLES
;+
; THESE DISPATCH TABLES ARE USED TO DISPATCH RESOURCE MESSAGES BASED 
; ON THE REQUEST CODES AND REQUEST TYPES IN THE RESOURCE MESSAGE.
; ALSO INCLUDED IS THE DISPATCH TABLE USED BY THE ERROR PROCESSOR
; ($ERROR) TO DISPATCH ACCORDING TO ERROR CODE.
;
;-
	.PSECT	$PLIT$,D

;  REQUEST CODE DISPATCH TABLE
 
RQ.MIN=		041		; MINIMUM REQUEST CODE
MSGDSP:	.WORD	unsupported	; 041	REQUESTOR ID
	.WORD	UNSUPPORTED	; 042	CAPABILITIES
	.WORD	INVALID		; 043	
	.WORD	INVALID		; 044	
	.WORD	INVALID		; 045	
	.WORD	INVALID		; 046	
	.WORD	unsupported	; 047	RESPONSE 
	.WORD	SPECIFY		; 050	SPECIFY
	.WORD	ACCESS		; 051	ACCESS
	.WORD	ASSIGN		; 052	ASSIGN 
	.WORD	unsupported		; 053	STATUS
	.WORD	UNSUPPORTED	; 054	CONTROL
RQ.MAX	=	.-MSGDSP/2-1	; MAXIMUM REQUEST CODE
 
; REQUEST TYPE DISPATCH TABLES

; <CAPABILITIES> DISPATCH TABLE

CAPDSP:	.WORD	INVALID		; 000	
	.WORD	UNSUPPORTED	; 001	CAPABILITIES-REPORT
	.WORD	UNSUPPORTED	; 002	CAPABILITIES-REQUEST
CP.MAX	=	.-CAPDSP/2-1	; MAXIMUM REQUEST CODE
 
; <SPECIFY> DISPATCH TABLE
 
SPCDSP:	.WORD	INVALID		; 000	
	.WORD	RESERVE		; 001	SPECIFY-RESERVE
	.WORD	SHARE		; 002	SPECIFY-SHARE
	.WORD	unsupported	; 003	SPECIFY-REFER
SY.MAX	=	.-SPCDSP/2-1	; MAXIMUM REQUEST CODE
 
; <ACCESS> DISPATCH TABLE
 
ACCDSP:	.WORD	INVALID		; 000	
	.WORD	OPEN1		; 001	ACCESS-OPEN, SINGLE LOGICAL LINK
	.WORD	OPEN2		; 002	ACCESS-OPEN  ON SEPARATE DATA LINK
	.WORD	CLOSE		; 003	ACCESS-CLOSE 
	.WORD	unsupported	; 004	ACCESS-RELEASE 
AC.MAX	=	.-ACCDSP/2-1	; MAXIMUM REQUEST CODE
 
 
; <ASSIGN> DISPATCH TABLE
 
ASNDSP:	.WORD	INVALID		; 000	
	.WORD	UNSUPPORTED	; 001	ASSIGN
	.WORD	UNSUPPORTED	; 002	ASSIGN-RECLAIM
	.WORD	UNSUPPORTED	; 003	ASSIGN-HANDOFF
AS.MAX	=	.-ASNDSP/2-1	; MAXIMUM REQUEST CODE

 
	.SBTTL	$PCBGT	- Allocate a PCB
;+
; This routine will allocate a pipe control block (if available).
;
; Input:
;	None
;
; Output:
;	If success:
;	    R3 = address of PCB.
;	If failure:
;	    R3 = undefined.
;-

	.PSECT	$CODE$,I
$PCBGT::PUSH$S	<R5,R4>		; Get room to move
	mov	.crdat+2,r5	; pick up data base address
	MOV	R$PCB+2(R5),R3	; Get the PCB table
	MOV	R$PCB+0(R5),R5	; and number of pipes.
	BEQ	90$		; (if there are any)
	MOV	R5,R4		; Save for later.
70$:	TST	P.STS(R3)	; Is this PCB free?
	BEQ	80$		; If not,
	ADD	#PCBLEN,R3	; then go on to the next
	SOB	R4,70$		; until we run out.
	BR	90$		; Whoops! None available.
80$:	SUB	R4,R5		; Get the
	INC	R5		; pipe number
	MOVB	R5,P.NUM(R3)	; and store it.
	CLR	P.RES(R3)	; Initialize various items.
	CLR	P.REF(R3)
	TST	(PC)+		; (clear the carry)
90$:	SEC
	POP$S	<R4,R5>		; Restore his registers.
	RETURN
	.SBTTL	Deallocate a PCB
;+
; This routine deallocates a PCB by clearing the status word.
;
; Input:
;	R3 = address of PCB
;
; Output:
;	None
;-

	.PSECT	$CODE$,I
$PCBRT::CLR	P.STS(R3)	; Make sure it is free.
	RETURN



;routine performs process initilization

PINSET:	call	$ltmen		;enable long timer
	mov	#^rNRD,r0	;get nrd's pix
	call	pidid
	movb	r0,-(sp)
	mov	#^rLE,r0	;get LE's pix
	call	pidid
	movb	r0,-(sp)
	mov	#^rCR,r0
	call	pidid
	movb	r0,-(sp)
	clr	r0
1$:	inc	r0
	call	$tcbpt
	bcs	4$
	movb	4(sp),t.spi(r5)		;set NRD's pix
	cmpb	t.tt(r5),#tt.le		;LP11 ?
	beq	2$
	cmpb	t.tt(r5),#tt.lp		;LP20 ?
	beq	2$
	cmpb	t.tt(r5),#tt.cr		;CR11 ?
	beq	3$
	cmpb	t.tt(r5),#tt.cd		;CD11 ?
	clrb	t.pri(r5)		;ickmay !
	br	1$

2$:	tstb	2(sp)			;is LE in system ?
	beq	5$
	movb	2(sp),t.pri(r5)		;set LE's pix
	br	1$
5$:	clrb	t.obj(r5)		;no LE here
	br	1$

3$:	tstb	(sp)			;is CR in system
	beq	6$
	movb	(sp),t.pri(r5)		;set CR's pix
	br	1$
6$:	clrb	t.obj(r5)		;no CR here
	br	1$

4$:	mov	.crdat+2,r5		;set timer ticking
	incb	(r5)
	cmp	(sp)+,(sp)+		;house clean
	tst	(sp)+
	return


;routine $PCBCL called from NRD

$PCBCL::
	mov	2(r5),r0	;get the ULA
	call	$pcbpt		;get the PCB address
	bcs	1$
	call	$pcbrt		;close up shop
1$:	return
	.SBTTL	$PCBPT	- Get the Address of a PCB
;+
; This routine gets the address of the given PCB.
;
; Input:
;	R0 = pipe number (ULA)
;
; Output:
;	If success:
;	    R3 = address of PCB.
;	If failure:
;	    R3 = undefined.
;-

	.PSECT	$CODE$,I
$PCBPT::PUSH$S	R5		; Get room to move
	mov	.crdat+2,r5	; pick up data base address
	MOV	R0,R3		; copy ULA
	DEC	R3		; and turn into index.
	CMP	R$PCB+0(R5),R3	; If in range
	BLOS	90$		; then
	MUL	#PCBLEN,R3	; index into
	ADD	R$PCB+2(R5),R3	; PCB table.
	TST	(PC)+		; (clear the carry)
90$:	SEC
	POP$S	R5		; Recover his register.
	RETURN

;routine $PCBDB called from NRD

$PCBDB::
	mov	2(r5),r0	;get the ULA
	call	$pcbpt		;point to the PCB
	bcc	1$		;huray(sp)!
	clr	r3		;too bad so sad
1$:	mov	r3,r0		;return the PCB
	return
	.SBTTL	$TCBPT	- Get the Address of a TCB
;+
; This routine gets the address of the given TCB.
;
; Input:
;	R0 = resource number (BTN)
;
; Output:
;	If success:
;	    R5 = address of PCB.
;	If failure:
;	    R5 = undefined.
;-

	.PSECT	$CODE$,I
$TCBPT::PUSH$S	R3		; Get room to move
	mov	.crdat+2,r5	; pick up data base address
	MOV	R0,R3		; copy BTN
	DEC	R3		; and turn into index.
	CMP	R$TCB+0(R5),R3	; If within range
	BLOS	90$		; then
	MUL	#TCBLEN,R3	; index into
	ADD	R$TCB+2(R5),R3	; TCB table
	MOV	R3,R5		; and put in R5.
	TST	(PC)+		; (clear the carry)
90$:	SEC
	POP$S	R3		; Restore his register.
	RETURN



;routine $TCBDB called from NRD

$TCBDB::
	mov	.crdat+2,r0		;point to TCB's
	mov	r$tcb(r0),r3		;... and the
	mov	r$tcb+2(r0),r1		;the number of the buggers
1$:	cmpb	2(r5),t.pri(r1)		;do the pix's match
	beq	2$			;jolly good show
	add	#tcblen,r1		;ring around the rosie
	sob	r3,1$			;...
	clr	r0			;confusion for later
	br	3$			;exit
2$:	mov	r1,r0			;return TCB
3$:	return
	.SBTTL	GETCPB	- Get Connect Pending Block

;+
; Address the two parts of the NSP connect pending block.
;
; Input:
;	R4 = address NSP connect-received CCB.
;
; Output:
;	R0 = address of connect pending buffer.
;	R2 = address of accounting information (k.RQDL)
;	KISAR6 = mapped to connect pending buffer.
;-

	.PSECT	$CODE$,I
GETCPB::MAP$	C.BUF(R4)	; Map CPB to APR6.
	MOV	C.BUF+2(R4),R0	; Address CPB
	MOV	#k.RQDL,R2	; and
	ADD	R0,R2		; accounting area.
	RETURN



$TCBTT::
	push$s	<r1,r3>
	mov	.crdat+2,r3		;get data base address
	mov	r$tcb(r3),r1		;number of the buggers
	mov	r$tcb+2(r3),r5		;where they is at
1$:	cmpb	r0,t.pri(r5)		;got a match
	beq	2$			;yes 
	add	#tcblen,r5		;more,more
	sob	r1,1$
	mov	#-1,r5			;ickmay oemay
2$:	pop$s	<r3,r1>
	return
	;routine $PCBOP called by NRD to open a data PCB

$PCBOP::
	mov	2(r5),r4		; connect CCB
	map$	c.buf(r4)		;map in connect block
	mov	c.buf+2(r4),r2		;....
	cmp	k.rqdl(r2),#2		;requestor-id length
	bne	2$			;not the right length
	clr	r0
1$:	inc	r0
	call	$pcbpt			;get a pcb
	bcs	3$			;none left
	bit	#ps.dat,p.sts(r3)	;a data pipe?
	beq	1$			;no only look at data pipes
	cmp	p.user(r3),k.rqid(r2)	;can't have duplicate userid's
	bne	1$
2$:	clr	r0			;error return
	return
3$:	call	$pcbgt			;allocate a pcb
	bcs	2$			;all gone too bad!!!
	mov	k.rqid(r2),p.user(r3)	;copy all the good stuff..
	mov	#^rNRD,r0		;get NRD's pix
	call	pidid			;...
	movb	r0,p.spi(r3)		;...
	bis	#ps.cc!ps.dat,p.sts(r3)	;set connected data pipe
	mov	r3,r0			;return PCB address
	return
	.SBTTL	CCB DISPATCHER/RESOURCE MANAGER SCHEDULER
;+
; THESE ROUTINES HANDLES LINE CONTROL REQUESTS AND RESOURCE ALLOCATION
; FAILURE RECOVERY.
;-


;+
; QUEUE UP A CCB FOR A RESOURCE WAIT
;
; INPUTS:
;	R4 - CCB TO QUEUE UP
;	(SP) - RETRY ADDRESS
;
; REGISTERS MODIFIED: R4,R3
;-

	.PSECT	$CODE$,I
NRMRWT:	MOV	(SP)+,C.prm2(R4)	; SET RETURN ADDRESS
	MOVB	#RM$RWT,C.fnc(R4) ; AND FUNCTION CODE.
 
ENQUE:
	mov	.crdat+2,r5		; pick up data base address
	MOV	R5,R3			; and copy address
	add	#r$rwt,r3		; point to resource queue
	BIS	#RF.CCB,r$flg(r5)	; IF NO RECOVERY IN PROGRESS
	BMI	10$			; THEN
	callr	$CMQIN			; QUEUE TO THE REAR
10$:	callr	$CMQIF			; OTHERWISE TO THE FRONT.

;+
; TIMER INTERRUPT - DO ANY RESOURCE RECOVERY WHICH IS REQUIRED AND THEN
; HANDLE ANY TCBS WHICH REQUIRE LINE CONTROL SERVICE.
;
; INPUT:
;	R5 - NRM DATA BASE ADDRESS
;-
 
	.PSECT	$CODE$,I
NRMTM:
	mov	.crdat+2,r5		;data base address
	incb	(r5)			;reset timer
	BIT	#RF.CCB,r$flg(R5)	; IF NOTHING TO DO
	BEQ	900$			; THEN QUIT.
	BIC	#RF.CCB,r$flg(R5)	; RESET CCB PENDING SWITCH
	BIS	#RF.CVR,r$flg(R5)	; AND SET RECOVERY SWITCH.
120$:	MOV	R5,R3			; GET ADDRESS
	add	#r$rwt,r3		;of resource queue
	CALL	$CMQRM			; AND SEE IF ANYTHING IS THERE.
	BCS	190$			; IF SO,
	MOVB	C.MOD(R4),R3		; PICK UP MODIFIER
	MOVB	C.FNC(R4),R0		; AND FUNCTION CODE
	CALL	@NRMTB(R0)		; AND RE-DISPATCH FUNCTION.
	mov	.crdat+2,r5		; pick up data base address
	BIT	#RF.CCB,r$flg(R5)	; IF NO RESOURCE ERROR,
	BEQ	120$			; THEN GO FOR MORE.
190$:	BIC	#RF.CVR,r$flg(R5)	; RESET RECOVERY SWITCH
900$:	RETURN				; AND WAIT.

;+
; RESOURCE WAIT COMPLETE - DISPATCH THE CCB TO THE RETRY ROUTINE
;-
 
NRMRWC:	GTPCB$			;GET THE PCB ADDRESS AND
	JMP	@C.prm2(R4)	;DISPATCH TO RETRY ROUTINE. 


.PAGE
;+
; FLUSH THE RESOURCE WAIT QUEUE OF REQUESTS FOR THE PIPE SPECIFIED
; IN r$flg
;-

NRMFLS:	mov	.crdat+2,r5		;data bese address
	BIS	#RF.CVR,r$flg(r5)	; SIMULATE RESOURCE RECOVERY
	BIC	#RF.CCB,r$flg(r5)	; AND CLEAR THE CCB INDICATOR.
	MOV	r$rwt+2(r5),-(SP)	; PUSH THE LIST HEAD
	MOV	r$rwt(r5),-(SP)		; ONTO THE STACK
	CLR	r$rwt(r5)		; AND CLEAR IT.
	mov	r5,r3			; and clean out
	add	#r$rwt,r3		; the resource queue
	mov	r3,r$rwt+2(r5)		; ...

10$:	mov	.crdat+2,r5		;point to data base address
	MOV	SP,R3			; GET STACK LISTHEAD
	CALL	$CMQRM			; AND GET NEXT ITEM
	BCS	30$			; IF THERE IS ONE.
	cmpb	r$flg(r5),c.prm1(r4)	; GET SWITCHES
	BEQ	20$			; IF NOT,
	BIS	#RF.CCB,r$flg(R5)	; INDICATE QUEUE NOT CLEAR
	CALL	$CMQIN			; AND RE-INSERT THE REQUEST.
	BR	10$
20$:	MOVB	C.MOD(R4),R3		; PICK UP MODIFIER
	MOVB	C.FNC(R4),R0		; FUNCTION CODE
	CALL	@NRMTB(R0)		; AND DISPATCH.
	BR	10$			; GO BACK FOR MORE.
30$:	BIC	#RF.CVR,r$flg(r5)	; TURN OFF RECOVERY BIT
	CMP	(SP)+,(SP)+		; CLEAR OFF STACK
	RETURN				; AND GO BACK.
	.SBTTL	NSPCON	- CONNECT PROCESSOR

;+
; THIS ROUTINE HANDLES CONNECT REQUESTS FOR CONTROL PIPES.
; IT SEARCHES FOR A FREE PIPE.  IF OK, IT STORES THE USER ID IN THE
; PCB, INITIALIZES THE PCB AND POSTS COMPLETION TO THE USER.
;
;  INPUTS:	R4 -> CONNECT CCB
;
;  SCAN FOR A FREE PIPE
;
nspcon:
	mov	r4,-(sp)		;save connect ccb
	MAP$	c.buf(r4)		;map in connect block
	mov	c.buf+2(r4),r2		;...
	call	$ccbgt			;try for accept ccb
	bcc	1$			;got one
	clr	r1			;failure indicator
	mov	#s.eres,r5		;set reject code
	br	3$			;reject the connection

1$:	mov	r4,r1			;stash accept ccb
	clr	r0			;now check out the pipes..
2$:	inc	r0			;..for a duplicate user id
	call	$pcbpt			;pcb comes back in r3
	bcs	4$			;looked at them all
	bit	#ps.ctl,p.sts(r3)	;only want control pipes
	beq	2$
	cmp	p.user(r3),k.rqid(r2)	;have we had this one before
	bne	2$			;no good
6$:	mov	#s.erbo,r5		;set reject code
3$:	mov	(sp)+,r4		;get back connect ccb
	NCRA$	,r5			;reject the connect
	mov	r1,r4			;point to accept ccb
	beq	5$
	call	$ccbrt			;release accept ccb
5$:	return				;and exit

; FORMAT THE PIPE AND ACCEPT THE CONNECT

4$:	call	$pcbgt			; get a pcb
	mov	#s.eres,r5		; set reject code
	bcs	3$			; and reject the connection
	mov	k.rqid(r2),p.user(r3)	; save user id
	movb	.crpix,p.spi(r3)	; save owner of pipe
	bis	#ps.cc!ps.ctl,p.sts(r3)	; set pipe flags
	mov	(sp)+,r4		; point to connect ccb
	movb	c.lix(r4),c.lix(r1)	; copy info to accept ccb
	movb	c.lix(r4),p.lla(r3)	; put LLA in PCB
	movb	c.pix(r4),c.pix(r1)	; put in dest pix
	movb	c.pix(r4),p.pix(r3)	; and save it for later
	ncra$	p.num(r3)		; acknowledge intent to connect
	mov	r1,r4			; accept the connection
	clr	c.cnt(r4)		; no optional data
	NACC$	,p.num(r3),#s$pseg	;....
	return


;this routine processes the connect complete from SC. if the
;connect completes successfully then data segments are requested, else
;the link is closed.

request:
	GTPCB$
	bic	#ps.ci,p.sts(r3)	;clear connect initiated
	cmp	c.sts(r4),#s.ssuc	;operation a success
	bne	2$
	bis	#ps.cc,p.sts(r3)	;set pipe connected
	NDRQ$	,,r$flw(r5)		;request a few segments
	movb	r$flw(r5),p.segs(r3)	;set req cnt in PCB
	return
2$:
	NABO$	p.num(r3)		;abort the link
	return				;and exit
	.SBTTL	NSPDIS	- DISCONNECT NSP CONTROL PIPE
	.SBTTL	SRVDIS	- DISCONNECT SERVER DATA PIPE
;+
; THIS ROUTINE HANDLES DISCONNECTS FOR BOTH CONTROL AND DATA PIPES.
; CONTROL DISCONNECTS ARE RECEIVED BY THE NRM DIRECTLY FROM NSP.
; IF A CONTROL PIPE, THE FOLLOWING OCCURS:
;	1. ALL TERMINALS ARE CLOSED
;	2. ALL TERMINALS ARE RELEASED
;	3. ALL REFERRALS ARE TERMINATED
;
; DATA PIPE DISCONNECTS ARE RECEIVED BY THE ATS GENERIC MANAGER
; AND SENT TO THE NRM BY A "TERMINATE" CONTROL ENABLE COMMAND.
; IF A DATA PIPE, THE FOLLOWING OCCURS:
;	ALL TERMINALS ARE CLOSED
;
; THE GENERAL PROCEDURE IS TO SEARCH THE RESERVED TERMINAL LIST UNTIL
; AN OPEN TERMINAL IS FOUND.  A CLOSE IS THEN INITIATED FOR THAT TERMINAL
; AND THE PROCESS EXITS.  AT THIS POINT THE NEXT TERMINAL IS
; CLOSED WHEN A CLOSE COMPLETION IS RECEIVED FOR THE PRESENT TERMINAL.
; WHEN ALL TERMINALS ARE CLOSED, THE PIPE TYPE IS DETERMINED.  IF DATA
; PIPE, THE PROCESS SIMPLY POSTS DISCONNECT COMPLETION.  IF A CONTROL
; PIPE, THE RESERVED TERMINALS ON THE PIPE ARE RELEASED,  ALL REFERAL
; THREADS ARE TERMINATED, AND DISCONNECT COMPLETION IS POSTED.
;
; IF AN ABORT REQUEST IS RECEIVED, THE PROCESSING IS IDENTICAL TO THE
; ABOVE, EXCEPT THAT COMPLETION IS NOT POSTED TO THE REQUESTOR.
;
; INPUT:
;	R4= DISCONNECT CCB FROM NSP OR SERVER
;
;-
 
NSPDIS:				;DISCONNECT CONTROL PIPE
	mov	r4,r2		;save disconnect ccb
	call	$ccbgt		;try for working ccb
	mov	r4,r1		;sqve it if got one
	mov	r2,r4		;fetch disconnect ccb
	bcc	10$
	jmp	enque		;resource recovery queue

10$:
	GTPCB$			;GET THE PIPE CONTROL BLOCK
	MOVB	R0,r$flg(r5)	;SAVE THE PIPE NUMBER for nrmfls routine
	NDAK$
	mov	r1,r4		;working ccb
	BIC	#PS.CC,P.STS(R3) ;CLEAR CONNECT COMPLETE.
	mov	r5,-(sp)		;save the world
	MOV	R4,-(SP)		;
	mov	r3,-(sp)		;
	mov	r1,-(sp)		;.....
	CALL	NRMFLS		;FLUSH RECOVERY REQUESTS
	mov	(sp)+,r1		;recover the world
	mov	(sp)+,r3		;
	MOV	(SP)+,R4		;
	mov	(sp)+,r5		;...
	jmp	discp

	.PAGE 
;+
; CONTROL PIPE DISCONNECT (ENTRY  FROM <STOP> AND <START> COMPLETE PROCESSORS)
;
; INPUTS:
;	R4= ADDRESS OF FREE CCB
;	R3= ADDRESS OF CONTROL PCB
;-
 
DISCP:	BIC	#PS.DIP,P.STS(R3) ;CLEAR DISCONNECT PENDING
 
; CLOSE ALL TERMINALS ON CONTROL PIPE
 
	MOV	R3,R5		;POINT TO RESERVED TERMINAL LISTHEAD
	ADD	#P.RES,R5	;...
 
10$:	MOV	(R5),R5		;GET ADDRESS OF NEXT TCB
	BEQ	20$		;IF EQ, ALL TERMINALS PROCESSED
	BIT	#TS.OCP,T.STS(R5) ;OPEN OR CLOSE PENDING OR TERM. OPEN?
	BEQ	10$		;IF EQ, NO- TERMINAL IS NOT OPEN
	BIS	#PS.DIP,P.STS(R3) ;ELSE YES- SET DISCONNECT PENDING
	BIT	#TS.OPP,T.STS(R5) ;IF OPEN IN PROGRESS
	BNE	15$		;THEN WAIT FOR OPEN TO FINISH.
	BIT	#TS.CLP,T.STS(R5) ;IF CLOSE NOT ISSUED YET
	BNE	10$		;THEN
	JMP	CLOSE2		;INITIATE A CLOSE ON THIS TERMINAL.

15$:	MOVB	P.NUM(R3),C.prm1(R4) ;SAVE WHO WE ARE WORKING ON.
	CALL	NRMRWT		;WAIT FOR ACTION TO FINISH
	BR	DISCP		;AND TRY AGAIN.

20$:	BIT	#PS.DIP,P.STS(R3) ;DISCONNECT PENDING?
	BEQ	30$		;IF SO,
	JMP	$ccbrt		;THEN WAIT FOR IT TO COME BACK. 

; CLEAR DISCONNECT PENDING FOR ALL ASSOCIATED DATA PIPES
; AND SEND DISCONNECT COMPLETE FOR EACH DISCONNECTED DATA PIPE
; DO NOT SEND COMPLETION FOR ABORTED DATA PIPES
 
30$:	PUSH$S	R4		;SAVE CCB ADDRESS (USE FOR CONTROL PIPE
	MOV	R3,R5		;DISCONNECT COMPLETION)
	CLR	R0		;SET FOR FIRST PCB
40$:	INC	R0		;GO TO NEXT PCB.
	CALL	$PCBPT		;GET THE PCB
	BCS	70$		;IF THERE IS ONE.
	TST	P.STS(R3)	;IF NOT ACTIVE
	BEQ	40$		;THEN IGNORE.
	BIT	#PS.CTL,P.STS(R3) ;IS THIS A CONTROL PIPE?
	BNE	40$		;IF EQ, YES- GET NEXT PCB
	CMP	P.USER(R5),P.USER(R3) ;CONTROL PIPE ASSOCIATED WITH DATA PIPE?
	BNE	40$		;IF NE, NO- GET NEXT PCB
	BIT	#PS.DIP,P.STS(R3) ;DISCONNECT PENDING?
	BEQ	40$		;IF EQ, NO
 
	CALL	$CCBGT		;GET A CCB
	BCC	60$		;IF CC, GOT ONE
;
; RESOURCE FAILURE - WAIT A TICK AND TRY AGAIN
;
	BIS	#PS.DIP,P.STS(R3) ;MARK AS STILL DISCONNECTING
	POP$S	R4		;RESTORE CCB ADDRESS
	MOVB	P.NUM(R3),c.prm1(R4) ;SAVE WHO WE ARE WORKING ON.
	CALL	NRMRWT		;GO TO RESOURCE SCHEDULER
	BR	30$		;AND TRY AGAIN.
 
; CONTROL PIPE DISCONNECT REENTRY POINT
 
 
60$:	CALL	DISPC		;TELL THE SERVER TO DISCONNECT
	BR	40$		;AND CHECK SOME MORE.
 
; RELEASE ALL TERMINALS ON CONTROL PIPE
 
70$:	MOV	R5,R3
80$:	MOV	P.RES(R3),R5	;IF THERE IS ANOTHER RESOURCE
	BEQ	110$		;THEN
	MOV	(R5),P.RES(R3)	;DE-LINK AND
	BIC	#<TS.RS!TS.RLP!TS.HP!TS.SRP>,T.STS(R5) ;UNRESERVE IT.
	BR	80$
 
 
110$:	POP$S	R4		;RESTORE CCB POINTER
	BIC	#PS.DIP,P.STS(R3) ;CLEAR DISCONNECT PENDING FOR CONTROL PIPE
	BR	DISPC		;AND GO FINISH UP IN COMMON CODE
;+
; DATA PIPE DISCONNECT (ENTRY FROM <START> AND <STOP> COMPLETE ROUTINES)
;
; INPUTS:
;	R4= ADDRESS OF CCB
;	R3= ADDRESS OF DATA PCB
;-
 
DISDP:	BIC	#PS.DIP,P.STS(R3) ;CLEAR DISCONNECT PENDING
 
; CHECK IF ASSOCIATED CONTROL PIPE IS ACTIVE

	MOV	R3,R5		;SAVE PCB ADDRESS 
	CLR	R0		;AND SET FOR FIRST PCB.
10$:	INC	R0		;GO TO NEXT PCB 
	CALL	$PCBPT		;POINT TO IT
	BCS	20$		;IF IT IS THERE.
	TST	P.STS(R3)	;IF NOT ACTIVE
	BEQ	10$		;THEN IGNORE.
	BIT	#PS.CTL,P.STS(R3) ;IS THIS A CONTROL PIPE?
	BEQ	10$		;IF EQ, NO
 
	CMP	P.USER(R5),P.USER(R3) ;DATA PIPE ASSOCIATED W/CONTROL PIPE?
	BNE	10$		;IF NE, NO
	BIT	#PS.DIP,P.STS(R3) ;DISCONNECT PENDING?
	BEQ	20$		;IF EQ, NO
	MOV	R5,R3		;RESTORE PCB ADDRESS
	BIS	#PS.DIP,P.STS(R3) ;SET DISCONNECT PENDING
	JMP	$ccbrt		;RETURN CCB
 
;  CLOSE ALL TERMINALS ON DATA PIPE
 
20$:	MOV	R5,R3		;RESTORE PCB POINTER
	BIC	#PS.DIP,P.STS(R3) ;CLEAR DISCONNECT PENDING
	ADD	#<P.OPN-T.OLNK>,R5 ;POINT INTO OPEN LIST
 
30$:	MOV	T.OLNK(R5),R5	;GET ADDRESS OF NEXT TCB
	BEQ	40$		;IF THERE IS ONE
	BIS	#PS.DIP,P.STS(R3) ;SET DISCONNECT PENDING
	BIT	#TS.OPP,T.STS(R5) ;IF OPEN IN PROGRESS
	BNE	35$		;THEN WAIT FOR OPEN TO FINISH.
	BIT	#TS.CLP,T.STS(R5) ;IF CLOSE NOT PENDING
	BNE	30$		;THEN
	JMP	CLOSE2		;INITIATE A CLOSE ON THIS TERMINAL.
35$:	MOVB	P.NUM(R3),C.prm1(R4) ;SAVE WHO WE ARE WORKING ON
	CALL	NRMRWT		;WAIT FOR ACTION TO FINISH
	BR	DISDP		;AND TRY AGAIN.

40$:	BIT	#PS.DIP,P.STS(R3) ;DISCONNECT PENDING?
	BEQ	DISPC		;IF SO,
	MOVB	P.NUM(R3),C.prm1(R4) ;SAVE WHO WE ARE WORKING ON.
	CALL	NRMRWT		;WAIT FOR ACTION TO FINISH
	BR	DISDP		;AND TRY AGAIN.
;+
; PIPE DISCONNECT COMPLETED - NOTIFY NSP OR SERVER
;
; INPUTS:
;	R4= ADDRESS OF CCB
;	R3= ADDRESS OF PCB
;-
 
DISPC:	BIT	#PS.CTL,P.STS(R3)	;IF NOT CONTROL PIPE
	BEQ	80$			;THEN NOTIFY PIPE OWNER PIPE CLOSED.
	
	clr	c.cnt(r4)		;no  data
	movb	p.pix(r3),c.pix(r4)	;set dest.
	movb	p.lla(r3),c.lix(r4)	;set LLA
	NABO$	P.NUM(R3)		;ABORT
	RETURN

80$:	MOVB	P.NUM(R3),C.prm1(R4)
	MOVB	P.SPI(R3),C.pix(R4)
	MOVB	#FC.AST,C.FNC(R4)	; NOTIFY PIPE OWNER.
	JMP	$SCHED

	.SBTTL	NRMDIS	- PIPE DISCONNECTED
;+
; LINK IS CLOSED - RETURN THE PIPE
;
; INPUTS:
;	R4 - DISCONNECT OR ABORT COMPLETE CCB
;-

NRMDIS:	GTPCB$			; GET THE PCB ADDRESS
	mov	r3,r5		; save ctl pcb
	CALL	$PCBRT		; RETURN THE PCB
	CLR	R0		;AND SET FOR FIRST PCB.
10$:	INC	R0		;GO TO NEXT PCB 
	CALL	$PCBPT		;POINT TO IT
	BCS	20$		;IF IT IS THERE.
	TST	P.STS(R3)	;IF NOT ACTIVE
	BEQ	10$		;THEN IGNORE.
	BIT	#PS.CTL,P.STS(R3) ;IS THIS A CONTROL PIPE?
	Bne	10$		;IF EQ, NO
 
	CMP	P.USER(R5),P.USER(R3) ;DATA PIPE ASSOCIATED W/CONTROL PIPE?
	BNE	10$		;IF NE, NO
	
	MOVB	P.NUM(R3),C.prm1(R4)
	MOVB	P.SPI(R3),C.pix(R4)
	MOVB	#FC.AST,C.FNC(R4)	; NOTIFY PIPE OWNER.
	JMP	$SCHED


20$:	JMP	$CCBRT		; AND THE DISCONNECT CCB.
	.SBTTL	NSPDAT	- RESOURCE MESSAGE DISPATCHER
;+
; THIS ROUTINE RECEIVES CONTROL FROM THE CCB DISPATCHER.
; ITS PURPOSE IS TO PASS CONTROL TO THE APPROPRIATE MESSAGE PROCESSOR
; BASED ON THE REQUEST CODE.
; A RECEIVE DATA BUFFER (RDB) MAY CONTAIN TWO RESOURCE MESSAGES.
; FOR EXAMPLE, AN OPEN MESSAGE MAY BE CONCATENATED WITH A RESERVE
; MESSAGE.  FOR SUCH A CASE, THE FIRST MESSAGE WILL ALWAYS HAVE A
; SPECIFY MESSAGE REQUEST CODE AND THE DOUBLE MESSAGE FLAG WILL
; BE SET IN THE REQUEST TYPE BYTE (M.TYP).  FOR DOUBLE MESSAGES
; ONLY ONE STATUS RESPONSE (INDICATING FAILURE OR THE HIGHEST LEVEL
; MESSAGE COMPLETION STATUS) IS RETURNED TO THE REQUESTOR .
; 
; INPUT:
;	R5= ADDRESS OF NRM DATA BASE
;	R4= ADDRESS OF CCB-RDB (WHICH POINTS TO RESOURCE MESSAGE)
;
; OUTPUT:
;	APR6= BIASED INTO RESOURCE MESSAGE
;	R4= ADDRESS OF WORKING CCB
;	R3= ADDRESS OF CONTROL PCB (OVER WHICH MESSAGE WAS RECEIVED)
;	R2= CURRENT ADDRESS OF RESOURCE MESSAGE 
;	R0= MESSAGE SUBTYPE
;
;-
 
 
	.ENABL LSB
 
NSPDAT:				;MESSAGE ENTRY POINT
	GTPCB$			;GET THE PCB

10$:	TST	r$flg(R5) 	; IF RESOURCE ERROR RECOVERY
	BMI	20$		; NOT IN EFFECT
	TST	R$RWT(R5)	; AND THE QUEUE IS NOT EMPTY
	BNE	30$		; THEN ADD THIS TO IT.
20$:	MOV	R4,R1		; SAVE THIS CCB
	CALL	$CCBGT		; AND TRY FOR A SPAWN CCB.
	BCC	40$		; IF FAILURE
	MOV	R1,R4		; GET NSP CCB BACK
30$:	JMP	ENQUE		; AND WAIT FOR THE PROPER MOMENT.

40$:	mov	r4,-(sp)	;stash away stack ccb for now
	decb	p.segs(r3)	;decrement flow count
	bne	48$		;still permissions outstanding
	call	$ccbgt		;must request data segments
	bcc	45$		;do it
	mov	(sp)+,r4	;return stacked ccb
	call	$ccbrt
	incb	p.segs(r3)	;reset flow count
	mov	r1,r4		;and queue up received ccb
	jmp	enque		;....

45$:	movb	p.pix(r3),c.pix(r4)
	movb	r$flw(r5),p.segs(r3)
	movb	p.segs(r3),r0
	NDRQ$	p.lla(r3),p.num(r3),r0

48$:	mov	(sp)+,r4	;get back stack ccb

50$:	MOVB	C.prm1(R1),C.lin(R4)   ;SAVE PIPE NUMBER
	MOV	R1,C.stk(R4)	      ;NSP CCB-RDB ADDRESS
	MOV	C.BUF+2(R1),C.STS(R1) ;SET MESSAGE START ADDRESS.
 
; GET MESSAGE ADDRESS
 
NRMMSG:	MOV	C.stk(R4),R5	;GET NSP BUFFER ADDRESS
	MAP$	C.BUF(R5)	;MAP TO RECIEVE DATA BUFFER
	MOV	C.STS(R5),R2	;POINT TO RESOURCE MESSAGE BUFFER
 
; RANGE CHECK REQUEST CODE
 
	CALL	GET1		;GET REQUEST CODE
	SUB	#RQ.MIN,R0	;REQUEST CODE TOO LOW?
	BLT	70$		;IF LT, YES
	CMP	#RQ.MAX,R0	;REQUEST CODE TOO HIGH?
	BHIS	80$		;IF LOS, NO- CONTINUE
 
70$:	RESPOND	RC.IRC		;ERROR - ILLEGAL REQUEST CODE
 
; DISPATCH MESSAGE TO MESSAGE PROCESSOR
 
80$:	ASL	R0		;MAKE A WORD INDEX
	MOV	MSGDSP(R0),-(SP) ;SAVE DISPATCH ADDRESS
	CALL	GET1		;GET SUBTYPE
	PUSH$S	R0		;SAVE WHILE WE
	CALL	GET2		;GET CONTROL ID
	MOV	R0,C.prm1(R4)	;AND STORE IT.
	POP$S	R0		;RESTORE SUBTYPE
	RTS	PC		;AND DISPATCH MESSAGE (WITHOUT RETURN)

	.DSABL LSB
	.SBTTL	SPECIFY	-  <SPECIFY> MESSAGE PRE-PROCESSOR
;+
; THIS ROUTINE RECEIVES SPECIFY MESSAGES.  ITS DOES THE PROCESSING COMMON
; TO ALL SPECIFY MESSAGES.
; ALGORITHM:
;    CHECK FOR VALID SPECIFY-REQUEST TYPES. IF NOT VALID RETURN ERROR
;    SEARCH REFERRAL LIST FOR CCB WITH CONTROL ID. IF FOUND GO TO 1.
;    SEARCH RESERVED LIST FOR TCB WITH CONTROL ID. IF FOUND RETURN ERROR
;    ALLOCATE CCB AND LINK TO REFERRAL LIST
; 1. IF REFERRAL CCB DOES NOT POINT TO HANDOFF TCB GO TO 2.
;    DELINK REFERRAL CCB AND RETURN IT TO POOL
;    LINK TCB TO HANDOFEE'S RESERVED TERMINAL LIST
;    SEND RESPONSE MESSAGE TO HANDOFEE
;    SEND RESPONSE MESSAGE TO HANDOFER AND EXIT
; 2. SEARCH TCB TABLE FOR TCB CONTAINING TERMINAL NAME. IF FOUND RETURN SUCCESS
;    ELSE RETURN ERROR
;
; INPUT:
;	APR6= BIASED INTO RESOURCE MESSAGE
;	R4= ADDRESS OF WORKING CCB
;	R3= ADDRESS OF CONTROL PCB (OVER WHICH MESSAGE WAS RECEIVED)
;	R2= CURRENT ADDRESS OF RESOURCE MESSAGE 
;		= AT 'RESTYPE' FIELD
;	R0= MESSAGE SUBTYPE
;
; OUTPUT:
;	R4= ADDRESS OF WORKING CCB
;	R0= RESPONSE CODE
;
;	IF SUCCESS:
;	APR6= BIASED INTO RESOURCE MESSAGE
;	R5= ADDRESS OF TCB
;	R0= ADDRESS OF CCB CONTAINING CONTROL ID
;
;-
 
SPECIFY:
 
; VALIDATE REQUEST TYPE
 
	BICB	#^C17,R0	;CLEAR OUT GARBAGE
	BEQ	10$		;IF EQ, INVALID REQUEST TYPE
	CMPB	#SY.MAX,R0 	;REQUEST TYPE IN RANGE?
	BHIS	20$		;IF LOS, YES- CONTINUE
10$:	RESPOND	RC.IRC		;ERROR - ILLEGAL REQUEST CODE
 
; THE CONTROL ID SHOULD NOT BE ASSOCIATED WITH A RESERVED RESOURCE
 
20$:	CALL	FNDRES		;CHECK RESERVED LIST
	BCS	40$		;IF CS, CONTINUE
	RESPOND	RC.RQO		;ERROR - CONROL ID IN USE
 
 
; LOOK UP TCB CONTAINING RESOURCE DESCRIPTOR (TERMINAL NAME)
 
40$:	CALL	GET1		;GET THE RESOURCE OBJECT TYPE
	MOVB	R0,C.prm3(R4)	;SAVE THIS
	CALL	GET1		;GET THE FIELD LENGTH
	MOVB	R0,C.prm4(R4)	;SAVE THIS ALSO
	MOV	R2,C.prm5(R4)	;SAVE NAME POSITION
	CLR	R0		;START WITH FIRST TCB
50$:	INC	R0
	CALL	$TCBPT		;POINT TO TCB
	BCC	70$		;IF NO MORE RESOURCES
60$:	RESPOND	RC.RNE		;ERROR - RESOURCE DOES NOT EXIST

61$:	RESPOND	RC.IRD		;ERROR - INVALID RESOURCE DESCRIPTOR

	.IIF NE	<T.NAML-1-T.OBJ>,.ERROR T.NAML;MUST BE ADJACENT TO T.OBJ
	.IIF NE	<T.NAM-1-T.NAML>,.ERROR T.NAM;MUST BE ADJACENT TO T.NAML

70$:	ADD	#T.OBJ,R5	;POINT TO OBJECT TYPE
	CMPB	C.prm3(R4),(R5)+ ;IF OBJECT CODES DON'T MATCH
	BNE	50$		;THEN REJECT.
	MOVB	C.prm4(R4),R1	;GET  NAME LENGTH
	CMPB	R1,(R5)+	;AND IF NO MATCH
	BNE	50$		;THEN REJECT THIS ALSO.
	MOV	C.prm5(R4),R2	;POINT TO BEGINNING OF TERMINAL NAME
80$:	CMPB	(R2)+,(R5)+	;AND COMPARE THE NAMES
	BNE	50$		;IF NO MATCH, REJECT
	SOB	R1,80$		;CHECK THE FULL NAME
	MOVB	C.prm4(R4),R1	;GET LENGTH AGAIN
	SUB	R1,R5		;AND
	SUB	#T.NAM,R5	;BACK UP TO TCB BEGINNING
 
; DISPATCH MESSAGE TO REQUEST PROCESSOR
 
				;R5 POINTS TO TCB
90$:	MOV	C.stk(R4),R0	;GET
	MOV	C.STS(R0),R0	;MESSAGE ADDRESS
	MOVB	1(R0),R0	;AND REQUEST CODE
	BICB	#^C17,R0	;CLEAR OUT GARBAGE
	ASL	R0		;MAKE A WORD INDEX
	JMP	@SPCDSP(R0)	;DISPATCH <SPECIFY> MESSAGE
	.SBTTL	RESERVE	-   <SPECIFY-RESERVE> PROCESSOR
;+
; THIS ROUTINE RECEIVES CONTROL FROM THE <SPECIFY> PRE-PROCESSOR.
; ITS FUNCTION IS TO RESERVE A TERMINAL   FOR A REQUESTOR. 
; THE STATE OF THE TERMINAL IS CHECKED AND IF FREE, IT IS RESERVED.
;
; NOTE:	ANY REFERRAL CCB IS LEFT ALONE UNTIL THE FULL COMMAND MESSAGE
;	IS PROCESSED (INCLUDING CONCATENATED MESSAGES)
; 
;
; INPUT:
;	R5= ADDRESS OF TCB
;	R4= ADDRESS OF WORKING CCB
;	R3= ADDRESS OF CONTROL PCB
;
; OUTPUT:
;	R4= ADDRESS OF WORKING CCB
;	R0= RESPONSE CODE
;-
 
RESERVE:
	BIT	#TF.RAL,T.FLG(R5) ;IF NOT READY FOR ALLOCATION
	Beq	10$		;OR
	BIT	#TS.RS,T.STS(R5) ;TERMINAL RESERVED
	BEQ	20$		;THEN
10$:	RESPOND	RC.RNA		;ERROR - RESOURCE NOT AVAILABLE
 
; RESERVE TERMINAL
 
20$:	MOV	C.prm1(R4),T.RID(R5) ;STORE CONTROL ID
	MOV	R3,T.PCBR(R5)	;STORE CONTROL PCB THREAD IN TCB
	BIS	#TS.RS,T.STS(R5) ;SET STATUS= 'RESERVED'
	CALL	SETRES		;LINK INTO RESERVED LIST.
 
	RESPOND	RC.INT		;SUCCESS - CONTROL THREAD OPEN

;+
; SEND 'SPECIFY-SHARE' NOT SUPPORTED
;-

SHARE:	RESPOND	RC.SHN		;ERROR - SHARED ACCESS NOT SUPPORTED
	.SBTTL	ACCESS	-  <ACCESS> MESSAGE PRE-PROCESSOR
;+
; THIS ROUTINE RECEIVES CONTROL FROM THE ATS RESOURCE MESSAGE DISPATCHER.
; IT GETS THE CONTROL ID AND SEARCHES THE RESERVED TERMINAL LIST
; FOR IT.  IF FOUND, THE <ACCESS> MESSAGE IS DISPATCHED.  ELSE A CHECK IS
; MADE FOR A REQUEST TYPE= RELEASE.  IF RELEASE, THE MESSAGE IS DISPATCHED,
; ELSE THE ACCESS IS REJECTED.
;
; INPUTS:
;	APR6= BIASED INTO RESOURCE MESSAGE
;	R4= ADDRESS OF WORKING CCB
;	R3= ADDRESS OF CONTROL PCB (OVER WHICH MESSAGE WAS RECEIVED)
;	R2= CURRENT ADDRESS OF RESOURCE MESSAGE
;		= AT 'SRVTYPE' FIELD
;	R0= MESSAGE SUBTYPE
;
; OUTPUT:
;	APR6= BIASED INTO RESOURCE MESSAGE
;	R4= ADDRESS OF WORKING CCB
;	R3= ADDRESS OF PCB
;	R2= ADDRESS OF RESOURCE MESSAGE
;	R1= CONTROL ID
;
;	IF SUCCESS:
;	R5= ADDRESS OF TCB
;
;	IF FAILURE:
;	R0= RESPONSE CODE
;-
 
ACCESS:				;FIRST MESSAGE ENTRY POINT
 
; RANGE CHECK REQUEST TYPE
 
	BEQ	10$		;IF EQ, INVALID REQUEST TYPE
	CMPB	#AC.MAX,R0 	;<ACCESS> TYPE IN RANGE?
	BHIS	20$		;IF LOS, YES- CONTINUE
10$:	RESPOND	RC.IRC		;ERROR - ILLEGAL REQUEST CODE
 
; LOOK UP TCB
 
20$:	CALL	FNDRES		;CHECK RESERVED LIST FOR TERMINAL
	BCC	40$		;IF CC, FOUND IT
	CMPB	#AC.REL,R0	;IS THIS A RELEASE?
	BEQ	30$		;IF EQ, YES
	RESPOND	RC.RSE		;ERROR - REQUEST OUT OF SEQUENCE

30$:	CLR	R5		;INDICATE TCB NOT FOUND
40$:	ASL	R0		;MAKE A WORD INDEX
	JMP	@ACCDSP(R0)	;DISPATCH <ACCESS> MESSAGE

;+
; SEND 'ACCESS-OPEN ON SINGLE LINK' NOT SUPPORTED
;-

OPEN1:	RESPOND	RC.SLN		;ERROR - SINGLE LINK NOT SUPPORTED
	.SBTTL	OPEN	-   <ACCESS-OPEN> MESSAGE PROCESSOR
;+
; THIS ROUTINE RECEIVES CONTROL FROM THE <ACCESS> MESSAGE PRE-PROCESSOR.
; ITS FUNCTION IS TO OPEN A TERMINAL FOR A REQUESTOR.  THE BULA RECEIVED
; IN THE <OPEN> MESSAGE INDICATES THE DATA PIPE ONTO WHICH THE TERMINAL IS
; TO BE OPENED.  THE BULA IS VERIFIED TO BE A VALID DATA PIPE ASSOCIATED
; WITH THE REQUESTOR.  IF OK, THE DATA PIPE IS CHECKED TO BE CONNECTED,
; AND IF SO,  A START CCB IS QUEUED TO THE APPROPRIATE DIALOGUE MANAGER.
; [THE OPEN PROCESS IS COMPLETED IN THE <OPEN COMPLETE> PROCESSOR].
;
; INPUT:
;	APR6= BIASED INTO RESOURCE MESSAGE
;	R5= ADDRESS OF TCB
;	R4= ADDRESS OF WORKING CCB
;	R3= ADDRESS OF PCB
;	R2= CURRENT ADDRESS OF RESOURCE MESSAGE
;		= AT 'SRVTYPE' FIELD
;
; OUTPUT:
;	IF SUCCESS:
;	R4= ADDRESS OF WORKING CCB
;
;	IF FAILURE:
;	R4= ADDRESS OF WORKING CCB
;	R0= RESPONSE CODE
;
;-
 
OPEN2:
	BIT	#TS.ROP,T.STS(R5) ;TERMINAL READY FOR OPEN?
	BEQ	60$		;IF EQ, YES
	RESPOND	RC.RSI		;ERROR - RESOURCE STATE INCONSISTENCY
 
40$:	RESPOND	RC.ISO		;ERROR - INVALID SERVER OPTION
 
60$:
	inc	r2		;past server obj type
	call	get1		;length of srvdesc field
	add	r0,r2		;get server opts field
	call	get1		;...
	tst	r0		;can't be null
	beq	40$
	call	get1		;pick up bula
	push$s	r3		;save ctl pipe
	call	$pcbpt		;get data pipe
	mov	r3,r0		;...
	pop$s	r3
	bcs	40$		;youcky poo

	BIT	#PS.DAT,P.STS(R0) ;IS THIS A DATA PIPE?
	BEQ	40$		;IF EQ, NO- GIVE ISO ERROR
	CMP	P.USER(R3),P.USER(R0) ;CONTROL PIPE OK FOR DATA PIPE?
	BNE	40$		;IF NE, NO- GIVE ISO ERROR
	BIT	#PS.CC,P.STS(R0) ;DATA PIPE CONNECTED?
	BNE	70$		;IF NE, YES- CONTINUE
	RESPOND	RC.RJS,RD.PNC	;ERROR - DATA PIPE NOT CONNECTED
 
70$:	MOV	R0,T.PCBD(R5)	;SET DATA PCB INTO TCB
	BIS	#TS.OPP,T.STS(R5) ;SET OPEN PENDING

	MOVB	T.SPI(R5),C.pix(R4)
	movb	t.pri(r5),c.lix(r4)
	MOVB	#FC.CTL,C.FNC(R4)
	MOVB	#FM.STR,C.MOD(R4)
	JMP	$SCHED
	.SBTTL	SRVSTR	-	START COMPLETE PROCESSOR
;+
; THIS ROUTINE RECEIVES CONTROL WHEN A DIALOGUE MANAGER POSTS AN
; OPEN COMPLETION TO THE RESOURCE MANAGER.  
; THE OPEN CCB IS RETURNED TO THE POOL.  THE TCB ASSOCIATED WITH THE
; TERMINAL NUMBER IS LOOKED UP, AND THE REGISTERS ARE SET UP FOR THE
; RESPONSE PROCESSOR.  THEN A RESPONSE MESSAGE IS GENERATED BASED ON THE
; STATUS OF THE OPEN COMPLETION.
;
; INPUT:
;	R4= ADDRESS OF OPEN CCB
;
; OUTPUT:
;	R4= ADDRESS OF CCB-RDB
;	R0= RESPONSE CODE
;
;	IF SUCCESS:
;	R5(LOW BYTE)= TERMINAL NUMBER (BTN)
;	R5(HIGH BYTE)= BOUNDARY USER LINK ADDRESS (BULA)
;
;-
 
SRVSTR:
	GTTCB$			;GET THE TCB
	MOV	T.PCBR(R5),R3	;THE CONTROL PIPE
	BIC	#TS.OPP,T.STS(R5) ;CLEAR START PENDING
 
; CHECK FOR SUCCESS OR FAILURE ON START
 
	TSTB	C.STS(R4)	;START SUCCESSFUL?
	BPL	60$		;IF PL, YES
	RESPOND	RC.RJS,RD.STR	;ERROR - STARTUP FAILED
 
60$:	MOV	T.PCBD(R5),R3	;GET DATA PCB ADDRESS
	CALL	SETOPN		;LINK TCB INTO OPEN LIST.
	BIS	#TS.OP,T.STS(R5) ;SET STATUS= 'OPEN'
	MOVB	T.NUM(R5),-(SP) ;SAVE TERMINAL NUMBER  (BTN)
	MOVB	P.NUM(R3),1(SP) ;PUT BULA IN HIGH BYTE
	MOV	(SP)+,R5	;LOAD BULA-BTN COMBO IN R5
	RESPOND	RC.INT		;SUCCESS - RESOURCE OPEN
	.SBTTL	CLOSE	-   <ACCESS-CLOSE> MESSAGE PROCESSOR
;+
; THIS ROUTINE RECEIVES CONTROL FROM THE <ACCESS> MESSAGE PRE-PROCESSOR.
; ITS FUNCTION IS TO CLOSE A TERMINAL FOR A REQUESTOR.  THE 'OPEN' BIT
; IS CLEARED, THE 'CLOSE PENDING' BIT IS SET, AND THE T.PCBR THREAD IS
; REDIRECTED FROM THE DATA PIPE TO THE CONTROL PIPE.
;
; INPUT:
;	APR6= BIASED INTO RESOURCE MESSAGE
;	R5= ADDRESS OF TCB
;	R4= ADDRESS OF WORKING CCB
;	R3= ADDRESS OF PCB
;	R2= CURRENT ADDRESS OF RESOURCE MESSAGE
;		= AT 'SRVTYPE' FIELD
;
; OUTPUT:
;	IF SUCCESS:
;	R4= ADDRESS OF WORKING CCB
;
;	IF FAILURE:
;	R4= ADDRESS OF WORKING CCB
;	R0= RESPONSE CODE
;
;-
 
CLOSE:				;ENTRY POINT
	BIT	#TS.OP,T.STS(R5) ;TERMINAL OPEN?
	BNE	CLOSE1		;IF NE, YES
	RESPOND	RC.RSI		;ERROR - RESOURCE STATE INCONSISTENCY
 
; SECONDARY ENTRY POINT (FROM RELEASE PROCESSOR)
 
CLOSE1:
 
; SECONDARY ENTRY POINT (FROM ERROR PROCESSOR)
 
CLOSE2:
	CLR	C.BUF+2(R4)	;INDICATE NO OPTIONAL DATA
	CLR	C.CNT(R4)
 
; SEND CLOSE (STOP) MESSAGE TO DIALOGUE MANAGER
 
80$:	BIC	#TS.OP,T.STS(R5) ;TERMINAL NO LONGER OPEN
	BIS	#TS.CLP,T.STS(R5) ;SET CLOSE PENDING
	MOVB	T.SPI(R5),C.pix(R4)
	movb	t.pri(r5),c.lix(r4)
	MOVB	#FC.CTL,C.FNC(R4)
	MOVB	#FM.STP,C.MOD(R4)
	CALL	$SCHED 
	CLC			;INDICATE SUCCESS
	RETURN			;EXIT
 
	.SBTTL	SRVSTP	-	STOP COMPLETE PROCESSOR
;+
; THIS ROUTINE RECEIVES CONTROL WHEN A DIALOGUE MANAGER POSTS A
; CLOSE COMPLETION TO THE RESOURCE MANAGER.
; IF RELEASE PENDING IS SET, THE RELEASE PROCESSOR IS CALLED AT
; ITS 'RELES1' ENTRY POINT.  IN THIS CASE THE STATUS RETURNED TO
; THE USER WILL BE FOR A RELEASE REQUEST.
; IF A RELEASE IS NOT PENDING, A RESPONSE MESSAGE IS RETURNED
; TO THE USER FOR THE CLOSE REQUEST.
; IF THE CLOSE IS BEING DONE BECAUSE OF A DISCONNECT ON THE DATA
; PIPE AND THE CONTROL PIPE IS STILL ACTIVE, A <STATUS-REPORT>
; MESSAGE IS SENT ON THE CONTROL PIPE FOR THE TERMINAL BEING CLOSED.
; IN ANY CASE, THE CLOSE CCB IS RETURNED TO THE POOL.
;
; INPUT:
;	R4= ADDRESS OF CLOSE CCB
;
; OUTPUT:
;	R4= ADDRESS OF CCB-RDB
;	R0= RESPONSE CODE
;	
;-
 
SRVSTP:				;ENTRY POINT
	GTTCB$			;FIND THE RESOURCE CONTROL BLOCK
	BIC	#TS.CLP,T.STS(R5) ;CLEAR CLOSE PENDING
	MOV	T.PCBD(R5),R3	;POINT TO DATA PCB
	CALL	REMOPN		;REMOVE RESOURCE FROM OPEN LIST.
	CLR	R1		; TRANSFER RESOURCE
	BISB	T.SPI(R5),R1	; FROM THE SERVER
 
10$:	MOV	T.PCBR(R5),R3	;POINT TO CONTROL PCB
	MOVB	P.NUM(R3),C.prm1(R4) ;AND RESET THE PIPE NUMBER.
	TST	C.stk(R4)	;IF THIS IS A DISCONNECT OPERATION
	BNE	40$		;THEN
	BIT	#PS.DIP,P.STS(R3) ;DISCONNECT PENDING ON CONTROL PIPE?
	BEQ	20$		;IF EQ, NO
	BIC	#<TS.STE!TS.OSP!TS.RLP>,T.STS(R5) ;ELSE CLEAR PENDING BITS
	JMP	DISCP		;FINISH DISCONNECTING CONTROL PIPE

20$:	MOV	T.PCBD(R5),R0	;GET DATA PCB ADDRESS
	BIT	#PS.DIP,P.STS(R0) ;DISCONNECT PENDING ON DATA PIPE?
	BEQ	30$		;IF EQ, NO
25$:	BIT	#PS.CC,P.STS(R3) ;IF CONTROL PIPE
	BEQ	26$		 ;  IS STILL ACTIVE,
	MOV	T.RID(R5),R1	 ;  SEND A <STATUS-REPORT> MESSAGE
	MOV	#RP.DSC,R0	 ;  ON THE PIPE
	CALL	ASYREP		 ;  ASYNCHRONOUSLY
	BCC	26$		;IF NO RESOURCES
	MOV	R5,C.prm3(R4)	;SAVE THE TCB ADDRESS
	CALL	NRMRWT		;WAIT A TICK
	MOV	C.prm3(R4),R5	;RESTORE THE TCB
	BR	25$		;AND TRY AGAIN

26$:	MOV	T.PCBD(R5),R3	 ;POINT TO DATA PCB
	BIC	#<TS.STE!TS.OSP!TS.RLP>,T.STS(R5) ;CLEAR PENDING BITS
	JMP	DISDP		;FINISH DISCONNECTING DATA PIPE
 
30$:	BIT	#TS.STE,T.STS(R5) ;START ERROR PENDING?
	BEQ	40$		;IF EQ, NO
	BIC	#TS.STE,T.STS(R5) ;ELSE YES- CLEAR START ERROR PENDING
35$:	JMP	$CCBRT		;RETURN STOP CCB
 
40$:	BIT	#TS.RLP,T.STS(R5) ;IF RELEASE PENDING
	BNE	50$		;OR
	BIT	#TS.OSP,T.STS(R5) ;NO OPR RPT REQUEST PENDING
	BEQ	50$		;THEN
45$:	BIT	#PS.CC,P.STS(R3) ;IF CONTROL PIPE
	BEQ	50$		 ;  IS STILL ACTIVE,
	BIC	#TS.OSP,T.STS(R5) ;CLEAR OPERATIONAL STATUS BIT
	MOV	T.RID(R5),R1	;GET CONTROL ID
	MOV	C.PRM1(R4),R0	;GET OPERATIONAL STATUS
	CALL	ASYREP		;AND SEND STATUS-REPORT TO USER
	BCC	50$		;IF NOT SUCCESSFUL
	BIS	#TS.OSP,T.STS(R5) ;RESET THE BIT
	MOV	R5,C.prm3(R4)	;SAVE THE TCB ADDRESS
	CALL	NRMRWT		;WAIT A TICK
	MOV	C.prm3(R4),R5	;RESTORE THE TCB
	BR	45$		;AND TRY AGAIN.

50$:	TST	C.stk(R4)	;IF NO ASSOCIATED MESSAGE
	BEQ	35$		;THEN THROW THIS AWAY.
 
70$:	RESPOND	RC.INT		;SUCCESS - CONTROL THREAD OPEN
	.SBTTL	ASSIGN	-  <ASSIGN> MESSAGE PRE-PROCESSOR
;+
; THIS ROUTINE RECEIVES CONTROL FROM THE RESOURCE MANAGER DISPATCHER.
; IT DOES PROCESSING COMMON TO ALL ASSIGN REQUEST MESSAGES.
; A RANGE CHECK IS DONE ON THE REQUEST TYPE AND THE MESSAGE IS DISPATCHED.
;
; INPUT:
;	APR6= BIASED INTO RESOURCE MESSAGE
;	R4= ADDRESS OF WORKING CCB
;	R3= ADDRESS OF CONTROL PCB
;	R2= ADDRESS OF RESOURCE MESSAGE
;		= AT 'MSGFLDS' FIELD
;	R0= MESSAGE SUBTYPE
;
; OUTPUT:
;	IF SUCCESS:
;	SAME AS INPUT
;
;	IF FAILURE:
;	SAME AS INPUT, PLUS:
;	R0= RESPONSE CODE
;-
 
ASSIGN:
 
; RANGE CHECK REQUEST TYPE
 
	TST	R0
	BEQ	10$		;IF EQ, INVALID STATUS TYPE
	CMPB	R0,#AS.MAX	;ASSIGN TYPE IN RANGE?
	BLOS	20$		;IF LOS, YES- CONTINUE
10$:	RESPOND	RC.IRC		;ERROR - INVALID REQUEST CODE
 
20$:	ASL	R0		;MAKE A WORD INDEX
	JMP	@ASNDSP(R0)	;AND DISPATCH ASSIGN MESSAGE
	.SBTTL	ASYREP	- ASYNCHRONOUS STATUS REPORT
;+
; THIS ROUTINE RECEIVES CONTROL FROM THE ERROR PROCESSOR.
; ITS FUNCTION IS TO GET THE ATS TERMINAL STATUS AND THE OPERATIONAL
; STATUS, BUILD THE STATUS MESSAGE, ANS TRANSMIT THE MESSAGE.
;
; INPUTS:
;	R5= ADDRESS OF TCB
;	R3= ADDRESS OF CONTROL PCB
;	R1= CONTROL ID
;	R0= OPERATIONAL STATUS
;
; OUTPUT:
;	CARRY CLEAR= STATUS SENT
;	CARRY SET= COULD NOT OBTAIN RESOURCES
;
; REGISTERS MODIFIED: APR6,R2
;-
 
ASYREP:	PUSH$S	R4			; SAVE HIS CCB
	CALL	CSBGT			; AND GET A REPORT BUFFER
	BCS	90$			; IF WE CAN.
	MOV	R1,C.prm1(R4)		; SAVE CONTROL ID
	MOVB	P.LLA(R3),C.LIN(R4) 	; PIPE NUMBER
	MOVB	#SS.ATS,C.MOD(R4) 	; AND SET STATUS TYPE.
	MOV	C.BUF+2(R4),R2		; GET BUFFER ADDRESS
	CALL	STATSM			; AND SET UP THE MESSAGE.
	SUB	C.BUF+2(R4),R2		; FIGURE THE LENGTH AND
	MOV	R2,C.CNT(R4)		; STORE IT.
	movb	p.pix(r3),c.pix(r4)	;set destination
	NDAT$	P.LLA(R3),p.num(r3),#s$peom
	CLC				; INDICATE SUCCESS
90$:	POP$S	R4			; RESTORE HIS CCB
	RETURN
	.SBTTL	INVALID	- INVALID OR UNSUPPORTED REQUEST PROCESSOR
;+
; THIS ROUTINE PROVIDES A DISPATCH TARGET FOR ALL INVALID OR UNSUPPORTED
; REQUESTS DISPATCHED THRU THE DISPATCH TABLES.
;
; INPUT:
;	R4= ADDRESS OF CCB-RDB
;
; OUTPUT:
;	SAME AS INPUT, PLUS:
;	R0= RESPONSE CODE
;-
 
UNSUPPORTED:
INVALID:
	MOV	#RC.IRC,R0	;ERROR - ILLEGAL REQUEST CODE
	.IIF	NE,<.-RSPNS>,.ERROR RSPNS; routine must follow this one
	.SBTTL	RSPNS	- RESPONSE MESSAGE GENERATOR
;+
; GET DATA PIPE AND MESSAGE TYPE BEING RESPONDED TO AND FALL THROUGH TO
; RESPOND TO THE MESSAGE.
;
; INPUTS:
;	R5= RESPONSE DATA, IF R0=RC.RJS OR <ACCESS-OPEN> MESSAGE RESPONSE
;	R4= ADDRESS OF WORKING CCB
;	R0= RESPONSE CODE
;
; OUTPUTS (TO RSPNS1):
;	APR6= MAPPED TO RESOURCE MESSAGE
;	R5= RESPONSE DATA, IF R0=RC.RJS OR <ACCESS-OPEN> MESSAGE RESPONSE
;	R4= ADDRESS OF WORKING CCB
;	R3= ADDRESS OF CONTROL PCB
;	R1= MESSAGE TYPE (LOW BYTE) / SUBTYPE (HIGH BYTE)
;	R0= RESPONSE CODE
;-
 
RSPNS:	PUSH$S	<R0,R4>		; ROOM TO MOVE.
	MOV	C.stk(R4),R4	; GET NSP BUFFER
	GTPCB$			; AND PCB ADDRESS.
	MAP$	C.BUF(R4)	; MAP TO BUFFER
	MOV	C.STS(R4),R2	; GET ADDRESS
	CALL	GET2		; AND PICK UP
	MOV	R0,R1		; MESSAGE TYPE / SUBTYPE.
	POP$S	<R4,R0>		; RESET REGISTERS.
	.IIF	NE,<.-RSPNS2>,.ERROR RSPNS2; routine must follow this one
	.PAGE
;+
; RELEASE THE NSP RESOURCE MESSAGE BUFFER, GET A RESPONSE BUFFER
; AND FALL THROUGH TO FILL THE BUFFER AND SEND THE RESPONSE.
;
; INPUT:
;	R5= RESPONSE DATA, IF R0=RC.RJS OR <ACCESS-OPEN> MESSAGE RESPONSE
;	R4= ADDRESS OF WORKING CCB
;	R3= PCB ADDRESS
;	R1= MESSAGE TYPE (LOW BYTE), SUBTYPE (HIGH BYTE)
;	R0= RESPONSE CODE
;
; OUTPUT (TO RSPNSM):
;	R4= ADDRESS OF WORKING CCB
;		C.prm1= CONTROL ID
;		C.FLG= MESSAGE TYPE (LOW BYTE), SUBTYPE (HIGH BYTE)
;		C.PRM1= RESPONSE CODE
;		C.PRM2= RESPONSE DATA, IF R0=45 OR <OPEN> MESSAGE RESPONSE
;
; ALL REGISTERS MODIFIED
;-

RSPNS2:	MOV	R4,R2
	MOV	C.stk(R4),R4		; GET NSP'S CCB-BUFFER
	NRTN$	
	MOV	R2,R4			; RECOVER THE WORKING CCB.
20$:	CALL	SDBGT			; PUT A SDB IN OUR CCB
	BCC	30$			; IF NOT AVAILABLE
	MOV	R1,C.prm3(R4)		; MESSAGE BEING RESPONDED TO
	MOV	R0,C.prm4(R4)		; RESPONSE CODE
	MOV	R5,C.prm5(R4)		; AND DATA.
	mov	c.prm1(r4),c.sts(r4)	; save the ctl-id
	movb	p.num(r3),c.prm1(r4)	; set up ULA for dispatch
	CALL	NRMRWT			; WAIT FOR BETTER CONDITIONS
	MOV	C.prm5(R4),R5		; RESTORE
	MOV	C.prm4(R4),R0		; NEEDED
	MOV	C.prm3(R4),R1		; DATA
	mov	c.sts(r4),c.prm1(r4)	; set up ctl-id
	BR	20$			; AND TRY AGAIN
30$:	MOV	C.BUF+2(R4),R2		; AND BUFFER ADDRESS
	CALL	RSPNSM			; SET UP THE MESSAGE
	SUB	C.BUF+2(R4),R2		; FIGURE THE LENGTH AND
	MOV	R2,C.CNT(R4)		; STORE IT.
	movb	p.pix(r3),c.pix(r4)	;set destination
	NDAT$	P.LLA(R3),p.num(r3),#s$peom
	RETURN
	.SBTTL	RSPNSM	- GENERATE A <RESPONSE> MESSAGE
;+
; SET UP A RESPONSE MESSAGE IN A GIVEN BUFFER.
;
; INPUT:
;	APR6= MAPPED TO RESPONSE BUFFER
;	R5= RESPONSE DATA, IF R0=45 OR <OPEN> MESSAGE RESPONSE
;	R4= ADDRESS OF RESPONSE CCB-BUFFER
;		C.prm1= CONTROL ID
;	R2= ADDRESS TO INSERT THE STATUS MESSAGE
;	R1= MESSAGE TYPE (LOW BYTE), SUBTYPE (HIGH BYTE)
;	R0= RESPONSE CODE
;
; OUTPUTS:
;	R2= MOVED PAST THE MESSAGE INSERTED
;
; REGISTERS MODIFIED: R5,R2
;-

RSPNSM:	MOVB	#RQ.RES,(R2)+	; LOAD RESPONSE REQUEST CODE
	MOVB	R1,(R2)+	; LOAD RECEIVED MESSAGE'S REQUEST CODE
	MOVB	C.prm1(R4),(R2)+	; LOAD LOW BYTE OF CONTROL ID
	MOVB	C.prm1+1(R4),(R2)+ ; LOAD HIGH BYTE OF CONTROL ID
	MOVB	R0,(R2)+	; LOAD LOW BYTE
	SWAB	R0		; AND
	MOVB	R0,(R2)+	; HIGH BYTE OF RESPONSE CODE
	SWAB	R0		; RESTORE THE CODE.
	CMP	#RC.RJS,R0	; IS THIS A SERVOR REJECTION?
	BNE	60$		; IF NE, NO
	TST	R5		; IS THERE RESPONSE DATA?
	BEQ	70$		; IF EQ, NO
	MOVB	#2,(R2)+	; SET RESPONSE DATA COUNT
	MOVB	R5,(R2)+	; LOAD LOW BYTE
	SWAB	R5		; AND
	MOVB	R5,(R2)+	; HIGH BYTE OF RESPONSE DATA
	RETURN			; SEND RESPONSE MESSGAGE

60$:	CMP	#RQ.ACC+<AC.SEP*400>,R1 ; IF <ACCESS-OPEN>
	BNE	70$		; WITH SEPERATE DATA PIPE
	MOVB	#3,(R2)+	; THEN SET RESPONSE DATA COUNT
	MOVB	R5,(R2)+	; LOAD BTN
	CLRB	(R2)+		; CLEAR HIGH BYTE OF BTN
	SWAB	R5		; AND
	MOVB	R5,(R2)+	; LOAD BULA
	RETURN			; AND SEND RESPONSE MESSAGE

70$:	CLRB	(R2)+		; SET RESPONSE DATA LENGTH= 0
	RETURN
	.SBTTL	STATSM	- GENERATE A <STATUS> MESSAGE
;+
; SET UP A STATUS MESSAGE IN A GIVEN BUFFER.
;
; INPUT:
;	APR6= MAPPED TO RESPONSE BUFFER
;	R5= ADDRESS OF TCB FOR STATUS MESSAGE
;	R4= ADDRESS OF RESPONSE CCB-BUFFER
;		C.prm1= CONTROL ID
;		C.MOD= STATUS MESSAGE TYPE
;	R2= ADDRESS TO INSERT THE STATUS MESSAGE
;	R0= OPERATIONAL STATUS OR ZERO
;
; OUTPUTS:
;	R2= MOVED PAST THE MESSAGE INSERTED
;
; REGISTERS MODIFIED: R2
;-

STATSM:	MOVB	#RQ.STS,(R2)+	; LOAD STATUS REQUEST CODE
	MOVB	#ST.REP,(R2)+	; AS <STATUS-REPORT>
	MOVB	C.prm1(R4),(R2)+	; LOAD LOW BYTE OF CONTROL ID
	MOVB	C.prm1+1(R4),(R2)+ ; LOAD HIGH BYTE OF CONTROL ID
	MOVB	C.MOD(R4),(R2)+	; SET STATUS TYPE
	MOVB	#2,(R2)+	; AND DEFAULT TO TWO.
	MOVB	T.STS+0(R5),(R2)+ ; AND STORE
	MOVB	T.STS+1(R5),(R2)+ ; TCB STATUS.
	TST	R0		; IS THERE ANY OPERATIONAL STATUS ?
	BEQ	80$		; IF SO,
	MOVB	#4,-3(R2)	; SET COUNT TO FOUR
	MOVB	R0,(R2)+	; AND LOAD THE
	SWAB	R0
	MOVB	R0,(R2)+	; OPERATIONAL STATUS.
	SWAB	R0
80$:	RETURN
	.SBTTL	CSBGT	- GET A CCB/SDB AND SAVE BUFFER ADDRESS
;+
; GET A CCB/SDB AND FIX IT UP.
;
; NO INPUTS
;
; OUTPUTS:
;	APR6 - MAPPED TO SDB
;	R4 - CCB/SDB IF CARRY IS CLEAR
;
; REGISTERS MODIFIED: APR6,R4
;-

CSBGT:
	push$s	<r1>
	mov	#60.,r1		
	CALL	$CBBGT		;GET A CCB/SDB
	pop$s	<r1>
	RETURN

	.SBTTL	SDBGT	- GET A SDB AND INSERT IN CCB
;+
; THIS ROUTINE IS HERE FOR THE SAME REASON AS ABOVE.
;
; INPUTS:
;	R4 - CCB TO INSERT SDB INTO
;
; OUTPUTS (IF CARRY IS CLEAR):
;	APR6 - MAPPED TO SDB
;	C.BUF+0(R4) - SDB APR BIAS
;	C.BUF+2(R4) - SDB VIRTUAL ADDRESS
;
; REGISTERS MODIFIED: APR6
;-

SDBGT:	PUSH$S	<r1,r0>		; SAVE VOLOTILE REGISTERS
	mov	#60.,r1
	CALL	$corGT		; AND BID FOR A SDB.
	BCS	90$		; IF WE WON
	SMAP$	c.BUF+0(R4)	; INSERT APR BIAS
	MOV	R0,C.BUF+2(R4)	; AND VIRTUAL ADDRSS
90$:	POP$S	<r0,R1>
	RETURN

	.SBTTL	NRMDAT	- RETURN A NRM DATA BUFFER
;+
; THIS ROUTINE RETURNS BUFFERS AFTER A TRANSMIT OPERATION COMPLETES.
;
; INPUT:
;	R4= ADDRESS OF CCB-SDB
;
; OUTPUT:
;	CCB-SDB RETURNED TO POOL
;-
 
NRMDAT:
	mov	#60.,r1		;return 80. bytes
	JMP	$CbBRT		;AND RETURN CCB-SDB.
	.SBTTL	NSPRT	- RETURN CCB & ASSOCIATED NSP BUFFER
;+
;  THIS ROUTINE RETURNS CCBS AND RECEIVE BUFFERS ACQUIRED FROM NSP
;  IF ANY ARE ATTACHED TO THE CCB
;
;  INPUT:
;	R4 = ADDRESS OF CCB FOR BUFFER
;	R3 = CONTROL PCB
;
; REGISTERS MODIFIED: R1
;-
 
NSPRT:	MOV	C.stk(R4),R1	; PICK UP MYTHICAL NSP MESSAGE
	CALL	$CCBRT		; AND RELEASE THE CCB.
	MOV	R1,R4		; IF THE IS A NSP MESSAGE
	BEQ	90$		; THEN
	NRTN$	
90$:	RETURN
;		***- RESOURCE MANAGER UTILITIES -***
 
 
;+
; THE FOLLOWING ROUTINES ARE GENERAL UTILITIES USED BY THE RESOURCE
; MANAGER AND THE ATS DIALOGUE MANAGERS FOR TABLE LOOKUP; INSERTION,
; DELETION AND SCANNING OF ITEMS IN LINKED LISTS; AND A 'PUSH ONTO QUEUE'
; ROUTINE.
;-
 
 
	.SBTTL	GET*	- GET DATA FROM NRM MESSAGE
;+
; THE FOLLOWING ROUTINES EXTRACT DATA FROM THE NRM MESSAGE POINTED TO BY R2
; AND UPDATE R2 TO POINT AFTER THE DATA EXTRACTED.
;
; GET1	- GET A SINGLE BYTE (NO SIGN EXTENSION)
; GET2	- GET TWO BYTES AND ASSEMBLE AS WORD
;
; INPUTS:
;	APR6= BIASED INTO RESOURCE MESSAGE
;	R2 - POINTS TO DATA TO EXTRACT
;
; OUTPUTS:
;	R2 - POINTS AFTER EXTRACTED DATA
;	R0 - ASSEMBLED DATA
;-

GET1:	CLR	R0		;PICK UP ONE BYTE
	BISB	(R2)+,R0	;WITHOUT EXTENDING SIGN.
	RETURN

GET2:	CLR	R0		;START WITH NOTHING
	BISB	(R2)+,R0	;PICK UP LOW BYTE
	SWAB	R0
	BISB	(R2)+,R0	;PICK UP HIGH BYTE
	SWAB	R0
	RETURN
;+
; LIST MANIPULATION ROUTINES FOR REFERRAL LIST, RESERVED LIST, AND OPEN LIST.
;
; INPUTS:
;	R5= REFERRAL CCB OR RESOURCE TCB (IN SETXXX & REMXXX)
;	R4= WORKING CCB
;		C.prm1= CONTROL ID
;	R3= CONTROL / DATA PIPE ADDRESS
;
; OUTPUTS:
;	R5= REFERRAL CCB OR RESOURCE TCB (IN FNDXXX)
;-


SETRES:	MOV	P.RES(R3),(R5)	; LINK INTO
	MOV	R5,P.RES(R3)	; RESERVED RESOURCE LIST.
	RETURN

SETOPN:	MOV	P.OPN(R3),T.OLNK(R5) ; LINK INTO
	MOV	R5,P.OPN(R3)	; OPEN RESOURCE LIST.
	RETURN


FNDRES:	MOV	P.RES(R3),R5	; GET FIRST RESERVED RESOURCE
	BEQ	80$		; IF THERE IS ONE.
10$:	CMP	C.prm1(R4),T.RID(R5) ; IF CONTROL IDS MATCH
	BEQ	90$		; THEN ALL DONE
	MOV	(R5),R5		; OTHERWISE
	BNE	10$		; GO THROUGH LINKS
80$:	SEC			; UNTIL WE RUN OUT.
90$:	RETURN



REMRES:	PUSH$S	R4		; GET A WORK REGISTER
	MOV	#P.RES,R4	; AND POINT IT
	ADD	R3,R4		; TO RESERVED RESOURCE LIST.
10$:	CMP	(R4),R5		; IF NO MATCH
	BEQ	20$		; THEN
	MOV	(R4),R4		; GO THROUGH
	BNE	10$		; THE LINKS
	SEC			; UMMMM....
	BR	80$		; UNTIL RUN OUT.
20$:	MOV	(R5),(R4)	; IF FOUND, DE-LINK IT.
80$:	POP$S	R4		; RETURN R4
	RETURN

REMOPN:	PUSH$S	R4		; GET A WORK REGISTER
	MOV	#P.OPN-T.OLNK,R4 ; AND POINT IT
	ADD	R3,R4		; TO OPEN RESOURCE LIST.
10$:	CMP	T.OLNK(R4),R5	; IF NO MATCH
	BEQ	20$		; THEN
	MOV	T.OLNK(R4),R4	; GO THROUGH
	BNE	10$		; THE LINKS
	SEC			; UMMMM....
	BR	80$		; UNTIL RUN OUT.
20$:	MOV	T.OLNK(R5),T.OLNK(R4) ; IF FOUND, DE-LINK IT.
80$:	POP$S	R4		; RETURN R4
	RETURN

	.END