Google
 

Trailing-Edge - PDP-10 Archives - BB-R595B-SM_11-9-85 - mcb/nsp/nsp.bli
There is 1 other file named nsp.bli in the archive. Click here to see a list.
Module NSP (
		ident = 'X01160'
		) =
begin

!
!                    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.
!

!++
!
! FACILITY:	Network Services Layer
!
! ABSTRACT:	This module contains the interfaces to Session Control. All
!		CCB's enter NSP through this module. The NSP timers are
!		maintained in this module.
!
! ENVIRONMENT:	MCB
!
! AUTHOR:	Ron Platukis		CREATION DATE: 9-june-80
!
! MODIFIED BY:
!
! 01	Alan Peckham,Ron Platukis  22-Oct-80
! 	- Move NDB bind in CCB_RETRN.
!	  Clear C_STS before sending CCB to XPT in XPT_XMIT.
!	  Set C_PRM4 to PDB address or -1 if Reserve Port in XPT_XMIT.
!
! 02	Ron Platukis  23-oct-80
!	- Set PORTstate negative if  Reserved Port.
!
! 03	Ron Platukis  12-nov-80
!	- Fix bind in ONCE_A_SECOND for reserve ports.
!
! 04	Ron Platukis  20-nov-80
!	-Add protection in RCV_DISPATCH for hostile L_DSTADDR.
!
! 05	Ron Platukis  1-dec-80
!	-Add CMP_LSS and CMP_LEQ macros to perform 12-bit arith.
!
! 06	Ron Platukis  3-dec-80
!	-Add timer support for V3.1.
!
! 07	Ron Platukis  24-dec-80
!	-Add routine NSP_INI.
!
! 08	Ron Platukis  12-jan-81
!	-Change linkages to BLISS, add access for NSP Data Base address.
!
! 09	Ron Platukis  20-jan-81
!	-Add Network Management event logging code.
!
! 10	Ron Platukis  25-mar-81
!	-Allow data timers in routine CLOCK to also run in DI state.
!
! 11	Ron Platukis  22-april-81
!	-Shorten endless loop in routine QUEUE_MSG.
!
! 12	Ron Platukis  4-september-81
!	-fix dot bug in routine ABORT.
!
! 13	Ron Platukis   6-october-81
!	-fix sign bug in routine C_XMIT.
!
! 14	Ron Platukis	28-october-81
!	a) -in routine D_REQST allow data requests in DI state also.
!	b) -in routine PDB_INIT add initilization of timer variables.
!
! 15	Ron Platukis	8-june-82
!	a) -clear out ADDRrem variable in PBD_INIT( a debug aide).
!	b) -release DSR in XCP_CI if returned status is CE_RTE.
!
! 16	Alan Peckham	22-november-82
!	-Eliminate event buffer allocation (no longer used).
!       -Add call to NDB_GET for NSPself in CCP_COMPLETE to
!        establish seconds-since-last-zeroed for executor.
!
!--
!
! INCLUDE FILES:
!
library
	'mcb:XPORTx';
library
	'MCB:MCBLIB';
library
	'mcb:nmxlib';
require
	'NSPBLI:NSPDATA';
require
	'NSPBLI:NSINFO';


%if %bliss (bliss36) %then require 'BED:NETPAR'; %fi


!
! TABLE OF CONTENTS:
!
forward routine
	ABORT: novalue,		!Abort logical link
	CCB_GET:,
	CCB_HDR_GET:,
	CCB_RETRN: novalue,
	CCP_COMPLETE: MCB_CCB_MOD novalue,	!TRANSPORT-OPEN complete
	CLOCK:  novalue,		!NSP timer control
	CLS_PORT:  novalue,		!Close a Session Control port
	CONN_REXMT: novalue,		!Connect retransmission
	C_ACC: novalue,			!Accept remote connection
	C_REJ: novalue,			!Reject remote connection
	C_XMIT: novalue,		!Initiate a remote connection
	DADD: novalue,
	DATA_RCEV:  novalue,		!Supply receive buffer
	DATA_SND: novalue,		!Xmit normal data segments
	DISCONNECT: novalue,		!Synchronous disconnect
	D_REQST:  novalue,		!Request data segments
	INTR_REQ: novalue,		!Request interrupt message
	INTR_SND: novalue,		!Xmit interrupt data
	NSP_DISPATCH: MCB_CCB_MOD  novalue,	!Main CCB dispatch
	NSP_INI: novalue,		!Turn on NSP
	OPEN_PORT: novalue,		!Open Session Control port
	PDB_INIT: novalue,
	PIN_SETUP: novalue,		!Process Initilization
	QUEUE_MSG: novalue,		!Queue up a segment
	RCV_DISPATCH: MCB_CCB_MOD novalue,	!Dispatch on msg type
	STATE_PORT: novalue,		!Return state of port
	SC_RETRN:  MCB_CCB_MOD  novalue, 	!Recv enables from SC
	STATUS_NSP: novalue,		!Get status of NSP
	TIMER:  MCB_CCB_MOD  novalue,	!Timer function dispatch
	TIMEOUT:, 			!Count other retransmissions
	TO_NM: MCB_CCB_MOD novalue,	! NM dispatch to NS2
	XME_COMPLETE:  MCB_CCB_MOD  novalue,	!Xmit complete dispatch
	XCP_CI: novalue,		!CONNECT-XMT complete
	XCP_CONN: novalue,		!ACCEPT, REJECT, ABORT, DISCONNECT complete
	XCP_DATA: novalue,		!DATA-XMT complete
	XCP_OTH:  novalue;		!Other-Data xmit complete


!
! MACROS:
!
%if %bliss (bliss36)
%then
    macro
	PXX_PRESET (LENGTH) [] =
	    [%count, PORTstate] = N$SCL,
	    [%count, ADDRloc] = %count,
	    [%count, INTtail] = PXX [%count, INThead],
	    [%count, MSGtail] = PXX [%count, MSGhead],
	    [%count, INTRtail] = PXX [%count, INTRhead],
	    [%count, DATRtail] = PXX [%count, DATRhead],
	    [%count, ACKtail] = PXX [%count, ACKhead],
	    [%count, OTHtail] = PXX [%count, OTHhead],
	    [%count, BUFFtail] = PXX [%count, BUFFhead],
	    [%count, RCVtail] = PXX [%count, RCVhead]
	    %if %count lss LENGTH-1
	    %then ,PXX_PRESET (LENGTH)
	    %fi %,

	NXX_PRESET (LENGTH) [] =
	    [%count, NDaddr] = 0
	    %if %count lss LENGTH-1
	    %then ,NXX_PRESET (LENGTH)
	    %fi %,

	RXX_PRESET (LENGTH) [] =
	    [%count, MSGtyp] = MSG_NONE
	    %if %count lss LENGTH-1
	    %then ,RXX_PRESET (LENGTH)
	    %fi %;

%fi

!
! EQUATED SYMBOLS:
!

!
! OWN STORAGE:

%if %bliss (bliss36)
%then
    own
	PXX: blockvector [NS_TPT, PDB_SIZE] field (PORT_FIELDS)
	    preset (PXX_PRESET (NS_TPT)),

	RXX: blockvector [NS_TRS, RDB_SIZE] field (PORT_FIELDS)
	    preset (RXX_PRESET (NS_TRS)),

	NXX: blockvector [XP_NN, ND_SIZE] field (NODE_FIELDS)
	    preset (NXX_PRESET (XP_NN));


    global
	NSP$DB: block [NSP_SIZE] field (NSP_FIELDS)
	    preset (
		[NSPself] = NS_slf,
		[NSPact_tim] = NS_act,
		[NSPdelay] = NS_dly,
		[NSPweight] = NS_wgt,
		[NSPretrans] = NS_ret,
		[NSPtotal] = NS_tpt,
		[NSPt_rsv] = NS_trs,
		[NSPt_nodes] = XP_nn,
		[NSPbuf] = NS_buf,
		[ADDRports] = PXX,
		[ADDRnodes] = NXX,
		[ADDRresv] = RXX);
%fi


!

!
! EXTERNAL REFERENCES:
external
	%name('.crdat'): vector[2],
	$DSPCR;

	bind DB = %name('.crdat')[1]: ref block field(NSP_fields);

!
!
!++
!
!NETWORK SERVICES DISPATCH VECTOR
!
!All CCB's enter NSP through a dispatch off this table
!
!--
bind  $NSPLL = TABLE$( $DSPCR, FC_CCP, (FC_XME, NSP_DISPATCH),
			(FC_RCE, SC_RETRN), (FC_CTL, TO_NM),
			(FC_TIM, TIMER), (FC_XCP, XME_COMPLETE),
			(FC_RCP, RCV_DISPATCH), (FC_CCP, CCP_COMPLETE));


	$MCB_PROCESS( name = NSP, llc_dispatch = $NSPLL)
routine ABORT ( CCB, PDB) : novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine processes the Session Control ABORT call.
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!	PDB = Port Data Base address
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin
	map CCB: ref block field(C_fields);
	map PDB: ref block field(PORT_fields);

	local
	NDB : ref block field(NODE_fields);

	NDB = .PDB[NODElnk];
	If .PDB[PORTstate] eql N$SRUN
	Then
		begin
		PDB[PORTstate] = N$SDI;
		PDB[NUMhigh] = .PDB[ACKrcv_dat];
		PDB[DATres] = false;
		PDB[OTHres] = false;
		PDB[DELAYstr_tim] = 0;
		PDB[TIMERdat] = 0;
		PDB[TIMERoth] = 0;
		MAP$( .DB[BIASnodes]);
		DADD( NDB[NDb_xmt], .CCB[C_CNT]);	
		MAP$( .DB[BIASports]);
		CALL$E(FLUSH_QUEUES, .DB[NSPns2_pix], .PDB, N$EABL);

		If CCB_HDR_GET( .CCB, CCB, .PDB)
		Then
			CALL$E(DI_BLD, .DB[NSPns2_pix], .CCB, .PDB)
		Else
			begin
			CMQIN$( PDB[MSG_queue], .CCB);
			PDB[OTHres] = true
			end;
		return;
		end
	Else
		begin
		If (.PDB[PORTstate] eql N$SCN) or
		(.PDB[PORTstate] eql N$SDN)
		Then
			CCB[C_STS] = N$EABR
		Else
			CCB[C_STS] = N$ESTE;
		end;
	CCB[C_FNC] = FC_XCP;
	LLCRS$( .CCB)
	end;
routine CCB_GET (CCB, PDB) =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine allocates a CCB.
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!	PDB = Port Data Base address
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--


	begin
	map PDB: ref block field(PORT_fields);

	local 
	LCCB: ref block field(C_fields);

	If not CCBGT$(LCCB)
	Then
		return false;
	LCCB[C_STK] = 0;
	LCCB[C_CHN] = 0;
	LCCB[C_BIAS] = 0;
	LCCB[C_ADDR] = 0;
	LCCB[C_PRM1] = 0;
	LCCB[C_PRM2] = 0;
	LCCB[C_PRM3] = 0;
	LCCB[C_PRM4] = 0;
	LCCB[C_PRM5] = 0;

	If .PDB neq -1
	Then
		PDB[COUNTres] = .PDB[COUNTres] + 1;
	.CCB = .LCCB;
	return true;
	end;
routine CCB_HDR_GET ( CCB, LCCB, PDB ) =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine allocates a CCB and a header buffer from DSR space.
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!	LCCB = CCB Address to stack
!	PDB = Port Data Base address
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--


	begin
	map CCB: ref block field(C_fields);
	map PDB: ref block field(PORT_fields);
	map LCCB: ref block field(C_fields);


	If not CCBGT$(.LCCB)
	Then
		return false;
	begin
	bind XCCB = .LCCB: ref block field(C_fields);
	XCCB[C_STK] = 0;
	XCCB[C_CHN] = 0;
	XCCB[C_PRM1] = 0;
	XCCB[C_PRM2] = 0;
	XCCB[C_PRM3] = 0;
	XCCB[C_PRM4] = 0;
	XCCB[C_PRM5] = 0;
	XCCB[C_BIAS] = 0;

	If not $MCB_GET_DSR( hdb_size, XCCB[C_ADDR])
	Then
		begin
		CCBRT$(..LCCB);
		return false;
		end;

	If .CCB neq 0
	Then
		XCCB[C_STK] = .CCB;
	end;

	If .PDB neq -1
	Then
		PDB[COUNTres] = .PDB[COUNTres] + 1;
	return true;
	end;
routine CCB_RETRN ( CCB, PDB):  novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine deallocates a CCB.
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!	PDB = Port Data Base address
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--


	begin
	map PDB: ref block field(PORT_fields);

	local
	temp,
	NDB : ref block field(NODE_fields),
	CLZ_CCB: ref block field(C_fields);


	CCBRT$( .CCB);

	If .PDB neq -1
	Then
		begin
		PDB[COUNTres] = .PDB[COUNTres] - 1;

		If .PDB[PORTstate] eql N$SCL and
		.PDB[COUNTres] eql 0
		Then
			begin
			NDB = .PDB[NODElnk];
			PDB[FLAGinuse] = false;
			CMQRM$( PDB[MSG_queue], CLZ_CCB);
			CLZ_CCB[C_FNC] = FC_XCP;
			CLZ_CCB[C_STS] = N$SSUC;
			LLCRS$( .CLZ_CCB);
			end;
		End;
	end;
routine CCP_COMPLETE ( CCB, FCM) : MCB_CCB_MOD novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine processes completes for the Network Management Interface
!	calls. 
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!	FCM = FC_MOD of CCB
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin
	map CCB: ref block field(C_fields);

	bind PORT = .DB[ADDRports]: blockvector[0, PDB_size] field(PORT_fields);

	local
	temp,
	STK_CCB: ref block field(C_fields);

	STK_CCB = .CCB[C_STK];

	If .CCB[C_STS] eql CE_ERR
	Then
		STK_CCB[C_STS] = N$ETRN
	Else
		begin
		DB[NSPrunning] = true;
		STK_CCB[C_STS] = N$SSUC;
		STK_CCB[C_CNT] = .DB[NSPbuf];
		STK_CCB[C_PRM1] = .DB[NSPself];
                begin
                bind NDB = temp: ref block field(NODE_fields);
                CALL$E( NDB_GET, .DB[NSPns2_pix], .STK_CCB, NDB);
		NDB[NDactive] = .NDB[NDactive] - 1;
                end;
		$mcb_enable_long_timer( );
		db[nsptimer] = .db[nsptimer] + 1;
		MAP$( .DB[BIASports]);

		Incr J from 0 to (.DB[NSPtotal] - 1) do
			begin
			bind PDB = PORT[.J,0,0,0,0]: block field(PORT_fields);
			PDB[ADDran] = RND$( 256);
			end
		end;
	STK_CCB[C_FNC] = FC_XCP;
	LLCRS$( .STK_CCB);
	CCB_RETRN( .CCB, -1);
	end;
routine CLOCK :  novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine is called every second to provide timer support.
!
! FORMAL PARAMETERS:
!	None
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin

	bind PORT = .DB[ADDRports]: blockvector[0, PDB_SIZE] field(PORT_fields);
	local
	CCB: ref block field(C_fields);

	MAP$( .DB[BIASports]);

	Incr J from 0 to (.DB[NSPtotal] - 1) do
		begin
		bind PDB = PORT[.J,0,0,0,0]: block field(PORT_fields);

		If .PDB[FLAGinuse]
		Then
			begin
			If .PDB[DELAYstr_tim] neq 0
			Then
				PDB[DELAYstr_tim] = .PDB[DELAYstr_tim] + 1;
			Select .PDB[PORTstate] of
			Set
			[N$SCC, N$SDR, N$SDI]:

				begin
				If .PDB[TIMERcon] gtr 0
				Then
					begin
					PDB[TIMERcon] = .PDB[TIMERcon] -1;

					If .PDB[TIMERcon] eql 0
					Then
						begin
						PDB[DELAYstr_tim] = 1;
						PDB[COUNToth_retrans] = .PDB[COUNToth_retrans] + 1;

						If not TIMEOUT( PDB, .PDB[COUNToth_retrans])
						Then
							PDB[TIMERcon] = 1
						Else
							CONN_REXMT( PDB);
						end;
					end;
				end;

			[N$SRUN, N$SDI]:

				begin
				If .PDB[TIMERoth] gtr 0
				Then
					begin
					PDB[TIMERoth] = .PDB[TIMERoth] -1;

					If .PDB[TIMERoth] eql 0
					Then
						begin
						PDB[OTHstate] = OTHtimeout;
						PDB[COUNToth_retrans] = .PDB[COUNToth_retrans] + 1;

						If not TIMEOUT( PDB, .PDB[COUNToth_retrans])
						Then
							PDB[TIMERoth] = 1
						Else
							CALL$E(SND_INTERRUPT, .DB[NSPns1_pix], PDB)
						end;
					end;
				If .PDB[TIMERdat] gtr 0
				Then
					begin
					PDB[TIMERdat] = .PDB[TIMERdat] -1;

					If .PDB[TIMERdat] eql 0
					Then
						begin
						PDB[COUNTdat_retrans] = .PDB[COUNTdat_retrans] + 1;
						PDB[FLAGseg] = false;

						If not TIMEOUT( PDB, .PDB[COUNTdat_retrans])
						Then
							PDB[TIMERdat] = 1
						Else
							CALL$E(SND_ONE_DATA, .DB[NSPns1_pix], PDB)
						end;
					end;
				If .PDB[TIMERinact] gtr 0
				Then
					begin
					PDB[TIMERinact] = .PDB[TIMERinact] - 1;

					If .PDB[TIMERinact] eql 0 and
					.PDB[OTHstate] eql OTHready
					Then
						begin
						If CCB_GET( CCB, PDB)
						Then
							begin
							CCB[C_FNC] = FC_XME;
							CCB[C_MOD] = N_XDRQ;
							CCB[C_LIX] = .PDB[PID];
							CCB[C_PIX] = .DB[NSPns0_pix];
							CCB[C_PRM1] = 0;
							CCB[C_PRM4] = PDB;
							LLCRS$( .CCB);
							end
						Else
							PDB[TIMERinact] = 1;
						end

					end
				end;
			Tes;
			end;
		end;

	end;
routine CLS_PORT ( CCB, PDB) :    novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine processes the Session Control Interface Call CLOSE.
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!	PDB = Port Data Base address
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin
	map CCB: ref block field(C_fields);
	map PDB: ref block field(PORT_fields);


	local
	NDB : ref block field(NODE_fields);

	NDB = .PDB[NODElnk];

	If  .PDB[FLAGinuse]
	Then
		begin
		PDB[PORTstate] = N$SCL;
		PDB[DATres] = false;
		PDB[OTHres] = false;
		DB[NSPmax] = .DB[NSPmax] - 1;
		CALL$E( FLUSH_QUEUES, .DB[NSPns2_pix], .PDB, N$ECLS);

	! these next few lines of code are to prevent Transport from
	! filling up it's intercept data base, since the plug can
	! be pulled from our end without sending any DI's or DC's( which
	! really screws Transport up when playing intercept to a phase 2
	! node). hopefully an engineered solution will replace this.
	! BEGINNING OF HACK........................................

		if .PDB[VERSIONrem] eql V3_1
		then
			begin
			local xpepix;
			PDVID$( XPE, xpepix);
			Call$p( $xpecln, .xpepix, .DB[NSPself], .PDB[ADDRloc]);
			end;
	!.............................................. END OF HACK

		Do (PDB[ADDran] = .PDB[ADDran] + 1)
		While .PDB[ADDran] eql 0;
		MAP$( .DB[BIASnodes]);
		NDB[NDactive] = .NDB[NDactive] -1;
		MAP$( .DB[BIASports]);

		IF .PDB[COUNTres] eql 0
		Then
			begin
			PDB[FLAGinuse] = false;
			CCB[C_STS] = N$SSUC;
			CCB[C_FNC] = FC_XCP;
			LLCRS$( .CCB);
			end
		Else
			CMQIN$(PDB[MSG_queue], .CCB)
		end
	Else
		begin
		CCB[C_STS] = N$ESTE;
		CCB[C_FNC] = FC_XCP;
		LLCRS$( .CCB)
		end;
	end;
routine CONN_REXMT ( PDB) :  novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine retransmits Connect/Disconnect messages for whose
!	timers have expired.
!
! FORMAL PARAMETERS:
!	PDB = Port Data Base address
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--


	begin
	map PDB: ref block field(PORT_fields);

	local
	NDB : ref block field(NODE_fields),
	CCB: ref block field(C_fields);

	NDB = .PDB[NODElnk];

	If CCB_HDR_GET( .PDB[MSGhead], CCB, .PDB)
	Then
		begin
		MAP$( .DB[BIASnodes]);
		NDB[NDtimeout] = .NDB[NDtimeout] + 1;
		MAP$( .DB[BIASports]);
		CMQRM$( PDB[MSG_queue], CCB[C_CHN]);
		PDB[DELAYstr_tim] = 1;

		If .PDB[PORTstate] eql N$SCC
		Then
			CALL$E(CC_BLD, .DB[NSPns2_pix], .CCB, .PDB)
		Else
			CALL$E(DI_BLD, .DB[NSPns2_pix], .CCB, .PDB);
		end
	Else
		begin
		PDB[OTHres] = true;
		PDB[TIMERcon] = 1;
		end;

	end;
routine C_REJ ( CCB, PDB) :  novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine processes the Session Control REJECT call.
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!	PDB = Port Data Base address
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin
	map CCB: ref block field(C_fields);
	map PDB: ref block field(PORT_fields);

	local
	NDB : ref block field(NODE_fields);

	NDB = .PDB[NODElnk];

	If .PDB[PORTstate] eql N$SCR
	Then
		begin
		MAP$( .DB[BIASnodes]);
		DADD( NDB[NDb_xmt], .CCB[C_CNT]);
		MAP$( .DB[BIASports]);
		PDB[PORTstate] = N$SDR;

		If CCB_HDR_GET( .CCB, CCB, .PDB)
		Then
			CALL$E(DI_BLD, .DB[NSPns2_pix], .CCB, .PDB)
		Else
			begin
			CMQIN$( PDB[MSG_queue], .CCB);
			PDB[OTHres] = true
			end;
		return;
		end
	Else
		CCB[C_STS] = N$este;
	CCB[C_FNC] = FC_XCP;
	LLCRS$( .CCB);
	end;
routine C_ACC ( CCB, PDB) :  novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine processes the Session Control ACCEPT call.
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!	PDB = Port Data Base address
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin
	map CCB: ref block field(C_fields);
	map PDB: ref block field(PORT_fields);

	local
	NDB : ref block field(NODE_fields);

	NDB = .PDB[NODElnk];

	If .PDB[PORTstate] eql N$SCR
	Then
		begin
		MAP$( .DB[BIASnodes]);
		DADD( NDB[NDb_xmt], .CCB[C_CNT]);	
		MAP$( .DB[BIASports]);
		PDB[PORTstate] = N$SCC;
		PDB[FLOWloc_typ] = .CCB[C_PRM1];

		If CCB_HDR_GET( .CCB, CCB, .PDB)
		Then
			CALL$E(CC_BLD, .DB[NSPns2_pix], .CCB, .PDB)
		Else
			begin
			CMQIN$( PDB[MSG_queue], .CCB);
			PDB[OTHres] = true
			end;
		return;
		end
	Else
		CCB[C_STS] = N$este;
	CCB[C_FNC] = FC_XCP;
	LLCRS$( .CCB);
	end;
routine C_XMIT (CCB, dummy):  novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!This routine processes the SC CONNECT-XMT call.
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin
	map CCB: ref block field(C_fields);
	bind NODE = .DB[ADDRnodes]: blockvector[0,ND_SIZE] field(NODE_fields);

	local
	port: ref blockvector[0,pdb_size] field(PORT_fields),
	temp;

	PORT = .DB[ADDRports];

	If .CCB[C_PRM2] eql N$FSEG or
	.CCB[C_PRM2] eql N$FMES
	Then
		begin
		If
			begin
			CCB[C_LIX] = (Incr j from 0 to .DB[NSPtotal]-1 do
				begin
				bind PDB = PORT[.j,0,0,%bpval,0]: block field(PORT_fields);			
				if (.PDB[PORTstate] eql N$SCL) and
				not .PDB[FLAGinuse]
				then exitloop .j
				end);
			if .CCB[C_LIX] eql 255
			then
				FALSE
			else
				TRUE
			end
	
			and
				begin
				If CALL$E( NDB_GET, .DB[NSPns2_pix], .CCB, temp)
				Then
					begin
					bind NDB = .temp:block field(NODE_fields);
					MAP$( .DB[BIASnodes]);
					DADD( NDB[NDb_xmt], .CCB[C_CNT]);
					MAP$( .DB[BIASports]);
					TRUE
					end
				Else
					FALSE
				end
		Then
			begin
			bind PDB = PORT[.CCB[C_LIX],0,0,%bpval,0]: block field(PORT_fields);
			PDB_INIT( PDB);
			PDB[PORTstate] = N$SCI;
			PDB[CHANNEL] = .CCB[C_PRM3];
			PDB[NODElnk] = .temp;
			PDB[NODErem] = .CCB[C_PRM1];
			PDB[FLOWloc_typ] = .CCB[C_PRM2];
			DB[NSPmax] = .DB[NSPmax] + 1;

			If CCB_HDR_GET( .CCB, CCB, PDB)
			Then
				CALL$E(CI_BLD, .DB[NSPns2_pix], .CCB, PDB)
			Else
				begin
				CMQIN$( PDB[MSG_queue], .CCB);
				PDB[OTHres] = true
				end;
			return;
			end
		Else
			CCB[C_STS] = N$ERES;
		end
	Else
		CCB[C_STS] = N$ERMO;

	CCB[C_FNC] = FC_XCP;
	LLCRS$( .CCB);
	end;
routine DADD ( double_word, value ) :novalue =		!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine performs double percision arithemitic.
!
! FORMAL PARAMETERS:
!	DOUBLE_WORD = address to add VALUE to
!	VALUE = value to add to DOUBLE_WORD
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--


	begin
	builtin  ROT;
	map double_word: ref block field(long_word);

	if rot(double_word[low] = .double_word[low] + .value, 1)
	then
		begin
		if rot(double_word[hi] = .double_word[hi] + 1, 1)
		then
			begin
			double_word[low] = -1;
			double_word[hi] = -1;
			end
		end
	end;
routine DATA_RCEV ( CCB, PDB) :    novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine processes the Session Control Interface Call DATA-RCV.
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!	PDB = Port Data Base address
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin
	map CCB: ref block field(C_fields);
	map PDB: ref block field(PORT_fields);

	If ((.PDB[PORTstate] eql N$SRUN) or
	((.PDB[PORTstate] eql N$SDI) and 
	(CMP_NEQ(.PDB[NUMhigh], .PDB[ACKrcv_dat]))))
	Then
		begin
		If .PDB[FLOWloc_typ] eql N$FMES
		Then
			begin			
			CMQIN$( PDB[DATR_queue], .CCB);
			CALL$E(SND_MSG, .DB[NSPns1_pix], .PDB);
			return;
			end
		Else
			CCB[C_STS] = N$ERMO;
		end
	Else
		begin
		If (.PDB[PORTstate] eql N$SCN) or
		(.PDB[PORTstate] eql N$SDN)
		Then
			CCB[C_STS] = N$EABR
		Else
			CCB[C_STS] = N$ESTE;
		end;
	CCB[C_FNC] = FC_XCP;
	LLCRS$( .CCB)

	end;
routine DATA_SND ( CCB, PDB) :    novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine processes the Session Control Interface Call DATA-XMT.
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!	PDB = Port Data Base address
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin
	map CCB: ref block field(C_fields);
	map PDB: ref block field(PORT_fields);

	If .PDB[PORTstate] eql N$SRUN
	Then
		begin
		QUEUE_MSG( .CCB, .PDB);
		CALL$E(SND_MSG, .DB[NSPns1_pix], .PDB);
		return;
		end
	Else
		begin
		If (.PDB[PORTstate] eql N$SCN) or
		(.PDB[PORTstate] eql N$SDN)
		Then
			CCB[C_STS] = N$EABR
		Else
			CCB[C_STS] = N$ESTE;
		end;
	CCB[C_FNC] = FC_XCP;
	LLCRS$( .CCB)
	end;
routine DISCONNECT ( CCB, PDB) :   novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine processes the Session Control DISCONNECT call.
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!	PDB = Port Data Base address
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin
	map CCB: ref block field(C_fields);
	map PDB: ref block field(PORT_fields);

	local
	NDB : ref block field(NODE_fields);

	NDB = .PDB[NODElnk];

	If .PDB[PORTstate] eql N$SRUN
	Then
		begin
		PDB[PORTstate] = N$SDI;
		MAP$( .DB[BIASnodes]);
		DADD( NDB[NDb_xmt], .CCB[C_CNT]);	
		MAP$( .DB[BIASports]);

		If .PDB[NUMhigh] eql .PDB[ACKrcv_dat]
		Then
			begin
			If CCB_HDR_GET( .CCB, CCB, .PDB)
			Then
				CALL$E(DI_BLD, .DB[NSPns2_pix], .CCB, .PDB)
			Else
				begin
				CMQIN$( PDB[MSG_queue], .CCB);
				PDB[OTHres] = true
				end;
			return;
			end
		Else
			begin
			PDB[BUFFsync_dsc] = .CCB;
			return
			end;
		end
	Else
		begin
		If (.PDB[PORTstate] eql N$SCN) or
		(.PDB[PORTstate] eql N$SDN)
		Then
			CCB[C_STS] = N$EABR
		Else
			CCB[C_STS] = N$ESTE;
		end;
	CCB[C_FNC] = FC_XCP;
	LLCRS$( .CCB)
	end;
routine D_REQST ( CCB, PDB) :    novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine processes the Session Control Interface Call DATA-REQUEST.
!	These requests can come from Session Control or from NSP( if its
!	inactivity timer has expired. This explains why a test is made in this
!	routine for either a segment-flow link( in case from SC) or if the
!	C_PIX is equal to NSP( in case of inactivity timer)...euch!!!!
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!	PDB = Port Data Base address
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin
	map CCB: ref block field(C_fields);
	map PDB: ref block field(PORT_fields);


	If ((.PDB[PORTstate] eql N$SRUN) or
	((.PDB[PORTstate] eql N$SDI) and 
	(CMP_NEQ(.PDB[NUMhigh], .PDB[ACKrcv_dat]))))
	Then
		begin
		If (.PDB[FLOWloc_typ] eql N$FSEG) or
		(.CCB[C_PIX] eql .DB[NSPns0_pix])
		Then
			begin
			CMQIN$( PDB[DATR_queue], .CCB);
			CALL$E(SND_MSG, .DB[NSPns1_pix], .PDB);
			return;
			end
		Else
			CCB[C_STS] = N$ERMO;
		end
	Else
		begin
		If (.PDB[PORTstate] eql N$SCN) or
		(.PDB[PORTstate] eql N$SDN)
		Then
			CCB[C_STS] = N$EABR
		Else
			CCB[C_STS] = N$ESTE;
		end;
	CCB[C_FNC] = FC_XCP;
	LLCRS$( .CCB)

	end;
routine INTR_REQ ( CCB, PDB) :    novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine processes the Session Control Interface Call INTERRUPT-
!	REQUEST.
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!	PDB = Port Data Base address
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin
	map CCB: ref block field(C_fields);
	map PDB: ref block field(PORT_fields);

	If .PDB[PORTstate] eql N$SRUN
	Then
		begin
		CMQIN$( PDB[INTR_queue], .CCB);
		CALL$E(SND_MSG, .DB[NSPns1_pix], .PDB);
		return
		end
	Else
		begin
		If (.PDB[PORTstate] eql N$SCN) or
		(.PDB[PORTstate] eql N$SDN)
		Then
			CCB[C_STS] = N$EABR
		Else
			CCB[C_STS] = N$ESTE;
		end;
	CCB[C_FNC] = FC_XCP;
	LLCRS$( .CCB)
	end;
routine INTR_SND ( CCB, PDB) :    novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine processes the Session Control Interface Call INTERRUPT-
!	XMT.
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!	PDB = Port Data Base address
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin
	map CCB: ref block field(C_fields);
	map PDB: ref block field(PORT_fields);

	local
	NDB : ref block field(NODE_fields);
	
	NDB = .PDB[NODElnk];

	If .PDB[PORTstate] eql N$SRUN
	Then
		begin
		If .PDB[INT_queue] eql 0
		Then
			begin
			MAP$( .DB[BIASnodes]);
			DADD( NDB[NDb_xmt], .CCB[C_CNT]);	
			MAP$( .DB[BIASports]);
			CMQIN$( PDB[INT_queue], .CCB);
			CALL$E(SND_MSG, .DB[NSPns1_pix], .PDB);
			return;
			end
		Else
			CCB[C_STS] = N$ETMI;
		end
	Else
		begin
		If (.PDB[PORTstate] eql N$SCN) or
		(.PDB[PORTstate] eql N$SDN)
		Then
			CCB[C_STS] = N$EABR
		Else
			CCB[C_STS] = N$ESTE;
		end;
	CCB[C_FNC] = FC_XCP;
	LLCRS$( .CCB)
	end;
routine NSP_DISPATCH ( CCB, FCM) :  MCB_CCB_MOD  novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine dispatches to the appropriate routines based on the
!	value of FCM.
!
! FORMAL PARAMETERS:
!	None
!
! IMPLICIT INPUTS:
!	CCB = CCB address
!	FCM = FC_MOD of the CCB
!
! IMPLICIT OUTPUTS:
!	DB = NSP data base address
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin

	map CCB: ref block field(C_fields);

	bind  XMEDSP = TABLE$( $DSPCR, N_XINI, (N_GSTS, STATUS_NSP),
				(N_POPN, OPEN_PORT), (N_PCLS, CLS_PORT),
				(N_GSTA, STATE_PORT), (N_XCON, C_XMIT),
				(N_XACC, C_ACC), (N_XREJ, C_REJ),
				(N_XDSC, DISCONNECT), (N_XABT, ABORT),
				(N_XDAT, DATA_SND), (N_XINT, INTR_SND),
				(N_XIRQ, INTR_REQ), (N_XDRQ, D_REQST),
				(N_XBUF, DATA_RCEV), (N_XINI, NSP_INI));


	bind PORT = .DB[ADDRports]: blockvector[0, PDB_SIZE] field(PORT_fields);
	bind PDB = PORT[.CCB[C_LIX], 0, 0, 0, 0]: block field(PORT_fields);

	MAP$( .DB[BIASports]);
	DISPATCH$ (.FCM, XMEDSP, ( .CCB, PDB));
	end;
routine NSP_INI (CCB, PDB) :  novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine processes the Session Control INITILIZE call.
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!	PDB = Port data base address
!
! IMPLICIT INPUTS:
!	DB = NSP Data Base Address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin
	map CCB: ref block field(C_fields);

	local
	CTL_CCB: ref block field(C_FIELDS);

	If .DB[NSPrunning]
	Then
		CCB[C_STS] = N$ERUN
	Else
		begin
		If CCB_GET( CTL_CCB, -1)
		Then
			begin
			DB[NSPsc_pix] = .CCB[C_PIX];
			CTL_CCB[C_FNC] = FC_CTL;
			CTL_CCB[C_MOD] = FM_STR;
			CTL_CCB[C_PIX] = .DB[NSPxpt_pix];
			CTL_CCB[C_PRM1] = .DB[NSPself];
			CTL_CCB[C_STK] = .CCB;
			LLCRS$( .CTL_CCB);
			return
			end
		Else
			CCB[C_STS] = N$ERES
		end;
	CCB[C_FNC] = FC_XCP;
	LLCRS$( .CCB)
	end;
routine OPEN_PORT ( CCB, dummy) :    novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine processes the Session Control Interface Call OPEN.
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin
	map CCB: ref block field(C_fields);

	local 
	port: ref blockvector[0,pdb_size] field(PORT_fields);

	port = .DB[ADDRports];
	CCB[C_STS] = N$eres;
	CCB[C_FNC] = FC_XCP;
	CCB[C_LIX] = (Incr J from 0 to (.DB[NSPtotal] - 1) do
		begin
		bind PDB = PORT[.j,0,0,%bpval,0]: block field(PORT_fields);

		If not .PDB[FLAGinuse] 
		Then
			begin
			PDB_INIT( PDB);
			PDB[PORTstate] = N$SO;
			CCB[C_STS] = N$ssuc;
			exitloop .j;
			end;
		end);
	
	LLCRS$ (.CCB)		
	end;
routine PDB_INIT  ( PDB ) :  novalue =	!
!++
! FUNCTIONAL DESCRIPTION:
!	This routine initilizes a PDB for use.
!
! FORMAL PARAMETERS:
!	PDB = Port data base address 
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin
	map PDB: ref block field(PORT_fields);


	PDB[FLAGinuse] = true;
	PDB[CONFIDENCE] = true;
	PDB[NUMdat] = 1;
	PDB[NUMoth] = 1;
	PDB[NUMhigh] = 0;
	PDB[NUMsent] = 0;
	PDB[ACKrcv_dat] = 0;
	PDB[ACKdat_xmt] = 0;
	PDB[ACKoth_xmt] = 0;
	PDB[OTHstate] = OTHready;
	PDB[FLOWint_rem] = 1;
	PDB[FLOWdat_rem] = 0;
	PDB[FLAGsnd_dc] = false;
	PDB[FLOWsw_rem] = true;
	PDB[FLAGdat_ack] = false;
	PDB[FLAGoth_ack] = false;
	PDB[FLAGseg] = true;
	PDB[FLAGnew_msg] = true;
	PDB[TIMERdat] = 0;
	PDB[TIMERoth] = 0;
	PDB[TIMERcon] = 0;
	PDB[TIMERinact] = 0;
	PDB[DELAYmsg_num] = 0;
	PDB[DELAYstr_tim] = 0;
	PDB[DATres] = false;
	PDB[OTHres] = false;
	PDB[COUNTdat_retrans] = 0;
	PDB[COUNToth_retrans] = 0;
	PDB[COUNTloc_int] = 1;
	PDB[REAS_ptr] = 0;
	PDB[ADDRrem] = 0;
	end;
routine PIN_SETUP :  novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine handles process initilization.
!
! FORMAL PARAMETERS:
!	None
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin


	PDVID$( XPT, DB[NSPxpt_pix]);
	PDVID$( NSP, DB[NSPns0_pix]);
	PDVID$( NS1, DB[NSPns1_pix]);
	PDVID$( NS2, DB[NSPns2_pix]);
	end;
routine QUEUE_MSG ( CCB, PDB) :   novalue =	!

!++
! functional description:
!	This routine queues segments on the data queue for transmission to
!	a remote NSP.
!
! formal parameters:
!	CCB = CCB address
!	PDB = Port Data Base address
!
! implicit inputs:
!	DB = NSP data base address
!
! implicit outputs:
!	none
!
! routine value:
! completion codes:
!	none
!
! side effects:
!	none
!--

	begin
	map CCB: ref block field(C_fields);
	map PDB: ref block field(PORT_fields);

	local
	temp,
	CHN_CCB: ref block field(C_fields);

	CCB[C_STS] = 0;
	temp = (.CCB[C_CNT] + .PDB[SIZEseg] -1) / .PDB[SIZEseg];
	CHN_CCB = .CCB[C_CHN];

	While .CHN_CCB neq 0 do
		begin
		temp = .temp + ((.CHN_CCB[C_CNT] + .PDB[SIZEseg] -1) / .PDB[SIZEseg]);
		CHN_CCB = .CHN_CCB[C_CHN];
		end;
	PDB[NUMhigh] = .PDB[NUMhigh] + .temp;

	If .PDB[MSGhead] eql 0
	Then
		PDB[MSG_chain] = .CCB;
	CMQIN$( PDB[MSG_queue], .CCB);
	end;
routine RCV_DISPATCH ( CCB, FCM) :MCB_CCB_MOD novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine processes CCB's entering from Transport. The message
!	header is validated and a dispatch is made to the appropriate
!	routine in either NS1 or NS2 process.
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!	FCM = FC_MOD of CCB
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin
	map CCB: ref block field(C_fields);

	bind NODE = .DB[ADDRnodes]: blockvector[0, ND_size] field(NODE_fields);
	bind PORT = .DB[ADDRports]: blockvector[0, PDB_SIZE] field(PORT_FIELDS);

	local
	PTR,
	PDB: ref block field(PORT_fields);

	PTR = .CCB[C_ADDR];

	MAP$( .DB[BIASnodes]);

	Incr j from 0 to .DB[NSPt_nodes]-1 do
		begin
		bind NDB = NODE[.j,0,0,0,0]: block field(NODE_fields);

		If .NDB[NDaddr] eql .CCB[C_PRM1]
		Then
			begin
			DADD( NDB[NDm_rcv], 1);
			exitloop
			end;
		end;

	MAP$( .CCB[C_BIAS]);
	DB[MSGFLG] = ch$rchar_a( PTR);
	DB[L_DSTADDR] = ch$rchar_a( PTR);
	DB[H_DSTADDR] = ch$rchar_a( PTR);
	DB[L_SRCADDR] = ch$rchar_a( PTR);
	DB[H_SRCADDR] = ch$rchar_a( PTR);
	MAP$( .DB[BIASports]);
	
	If not (.DB[MSGFLG] eql FLG_NBEOM or
	.DB[MSGFLG] eql FLG_BOM or
	.DB[MSGFLG] eql FLG_EOM or
	.DB[MSGFLG] eql FLG_BEOM or
	.DB[MSGFLG] eql FLG_CA or
	.DB[MSGFLG] eql FLG_OTH_ACK or
	.DB[MSGFLG] eql FLG_INT or
	.DB[MSGFLG] eql FLG_REQ or
	.DB[MSGFLG] eql FLG_DAT_ACK or
	.DB[MSGFLG] eql FLG_NOP or
	.DB[MSGFLG] eql FLG_CI or
	.DB[MSGFLG] eql FLG_CC or
	.DB[MSGFLG] eql FLG_DI or
	.DB[MSGFLG] eql FLG_DC )
	Then
		begin
		CALL$E( EVENT_LOG, .DB[NSPns2_pix], invmsg, 0, .PDB, .CCB);
		CCB[C_FNC] = FC_RCE;
		LLCRS$( .CCB)
		end
	Else
		begin
		If .DB[MSGFLG] eql FLG_NOP
		Then
			begin
			CCB[C_FNC] = FC_RCE;
			LLCRS$( .CCB);
			return
			end;
		If .DB[MSGFLG] eql FLG_CI
		Then
			begin
			PDB = (Incr j from 0 to .DB[NSPtotal] -1 do
				begin
				bind XX = PORT[.j, 0, 0, 0, 0]: block field(PORT_fields);
				If .XX[PORTstate] eql N$SO
				Then
					exitloop XX;
				end);
			end
		Else
			begin
			bind XX = PORT[ .DB[L_DSTADDR], 0, 0, 0, 0]: block field(PORT_fields);
			If .DB[L_DSTADDR] lss .DB[NSPtotal]
			Then
				begin
				If .XX[NODErem] eql .CCB[C_PRM1] 
				Then
					begin
					If .DB[H_DSTADDR] eql .XX[ADDran] 
					Then
						begin
						If .DB[L_SRCADDR] eql .XX[L_rem_addr] and
						.DB[H_SRCADDR] eql .XX[H_rem_addr]
						Then
							PDB = XX
						Else
							begin
							If .DB[MSGFLG] eql FLG_CA or
							.DB[MSGFLG] eql FLG_CC or
							.DB[MSGFLG] eql FLG_DC or
							.DB[MSGFLG] eql FLG_DI
							Then
								PDB = XX
							Else
								PDB = -1
							end
						end
					Else
						PDB = -1;
					end
				Else
					PDB = -1;
				end
			Else
				PDB = -1;
			end;
		If .PDB eql -1
		Then
			CALL$E(RESV_PORT, .DB[NSPns2_pix], .CCB)
		Else
			begin
			Selectone .DB[MSGFLG] of
				Set
				[FLG_CI]:	CALL$E(CI_RCV, .DB[NSPns2_pix], .CCB, .PDB);
				[FLG_CC]:	CALL$E(CC_RCV, .DB[NSPns2_pix], .CCB, .PDB);
				[FLG_CA]:	CALL$E(CA_RCV, .DB[NSPns2_pix], .CCB, .PDB);
				[FLG_DI]:	CALL$E(DI_RCV, .DB[NSPns2_pix], .CCB, .PDB);
				[FLG_DC]:	CALL$E(DC_RCV, .DB[NSPns2_pix], .CCB, .PDB);
				[OTHERWISE]:	CALL$E(MSG_RCV, .DB[NSPns1_pix], .CCB, .PDB);
				Tes;
			end;
		end;
	end;
routine STATE_PORT ( CCB, PDB) :    novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine processes the Session Control Interface Call STATE.
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!	PDB = Port Data Base address
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin
	map CCB: ref block field(C_fields);
	map PDB: ref block field(PORT_fields);

	CCB[C_STS] = .PDB[PORTstate];
	CCB[C_FNC] = FC_XCP;
	LLCRS$ (.CCB)		
	end;
routine SC_RETRN ( CCB, FCM) : MCB_CCB_MOD  novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine processes Enables returning from Session Control. Any
!	resources owned by NSP are released and Transport resources are
!	returned via an Enable.
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!	FCM = FC_MOD of CCB
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin
	map CCB: ref block field(C_fields);
	bind PORT = .DB[ADDRports]: blockvector[0, PDB_SIZE] field(PORT_fields);
	bind PDB = PORT[.CCB[C_LIX], 0, 0, 0, 0]: block field(PORT_fields);

	local
	STK_CCB: ref block field(C_fields);

	MAP$( .DB[BIASports]);

	If .CCB[C_STK] neq 0
	Then
		begin
		STK_CCB = .CCB[C_STK];
		STK_CCB[C_FNC] = FC_RCE;
		LLCRS$( .STK_CCB);
		end
	Else
		If .CCB[C_ADDR] neq 0
		Then
			$MCB_RETURN_DSR( hdb_size, .CCB[C_ADDR]);
	CCB_RETRN( .CCB, PDB);
	end;
routine STATUS_NSP ( CCB, PDB) :    novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine processes the Session Control Interface Call STATUS.
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!	PDB = Port Data Base address
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin
	map CCB: ref block field(C_fields);

	CCB[C_CNT] = .DB[NSPbuf];
	CCB[C_PRM1] = .DB[NSPself];
	CCB[C_STS] = N$SSUC;
	CCB[C_FNC] = FC_XCP;
	LLCRS$ (.CCB)
	
	end;
routine TIMER ( CCB, FCM) : MCB_CCB_MOD  novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine dispatches on the timer type to the appropriate
!	routines.
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!	FCM = FC_MOD of CCB
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin
	db[nsptimer] = .db[nsptimer] + 1;

	Case .FCM^-1 from FM_STM^-1 to FM_PIN^-1 of
		Set
		[FM_STM^-1]:	return;
		[FM_LTM^-1]:	begin
				CALL$E( ONCE_A_SECOND, .DB[NSPns1_pix]);
				CLOCK()
				end;
		[FM_PWF^-1]:	return;
		[FM_PIN^-1]:	PIN_SETUP();
		Tes;
	end;
routine TIMEOUT ( PDB, VALUE) :   =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine records any timeout that has occured.
!
! FORMAL PARAMETERS:
!	PDB = Port Data Base address
!	VALUE = Data Base Entry to test
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin
	map PDB: ref block field(PORT_fields);

	local
	GOT_CCB: ref block field(C_fields);

	If (.VALUE eql .DB[NSPretrans]) and .PDB[CONFIDENCE]
	Then
		begin
		If CCB_GET( GOT_CCB, .PDB)
		Then
			begin
			CALL$E( NSP_CONFIDENCE, .DB[NSPns2_pix], .GOT_CCB, .PDB);
			return true
			end
		Else
			return false
		end;
	true
	end;
routine TO_NM ( CCB, FCM) : MCB_CCB_MOD novalue = !

!++
! FUNCTIONAL DESCRIPTION:
!	This routine transfers control to module NS2 to process
!	NM interface calls.
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!	FCM = FC_MOD of the CCB
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin
	CALL$E( FCCTL, .DB[NSPns2_pix], .CCB, .FCM);
	end;
routine XME_COMPLETE ( CCB, FCM) : MCB_CCB_MOD  novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine processes Transmit-Completes. A dispatch is made to the
!	appropriate routine for which the complete is for.
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!	FCM = FC_MOD of CCB
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin
	map CCB: ref block field(C_fields);

	bind PORT = .DB[ADDRports]: blockvector[0, PDB_size] field(PORT_fields);


	local
	PDB: ref block field(PORT_fields),
	STK_CCB: ref block field(C_fields);

	MAP$( .DB[BIASports]);
	PDB = .CCB[C_PRM4];
	STK_CCB = .CCB[C_STK];


	If .CCB[C_STS] eql CE_ERR
	Then
		SIGNAL_STOP( NSP$_ERR, .CCB);

	If .CCB[C_STS] eql CE_NTE
	Then
		SIGNAL_STOP( NSP$_NTE, .CCB);

	If .CCB[C_STK] neq 0
	Then
		begin
		Case .STK_CCB[C_MOD]^-1 from N_XCON^-1 to N_XBUF^-1 of
			set
			[N_XCON^-1]:	XCP_CI( .CCB, .PDB);
			[N_XACC^-1]:	XCP_CONN( .CCB, .PDB);
			[N_XREJ^-1]:	XCP_CONN( .CCB, .PDB);
			[N_XDSC^-1]:	XCP_CONN( .CCB, .PDB);
			[N_XABT^-1]:	XCP_CONN( .CCB, .PDB);
			[N_XDAT^-1]:	XCP_DATA( .CCB, .PDB);
			[N_XINT^-1]:	XCP_OTH( .CCB, .PDB);
			[N_XIRQ^-1]:	XCP_OTH( .CCB, .PDB);
			[N_XDRQ^-1]:	XCP_OTH( .CCB, .PDB);
			[N_XBUF^-1]:	XCP_OTH( .CCB, .PDB);
			[OUTRANGE]:	SIGNAL_STOP( NSP$_RNG, .STK_CCB);
			tes;
		end
	Else
		begin
		If .CCB[C_STS] eql CE_RTE
		Then
			SIGNAL( NSP$_RTE, .CCB);
		
		If .CCB[C_ADDR] neq 0
		Then
			$MCB_RETURN_DSR(  hdb_size, .CCB[C_ADDR]);

		CCB_RETRN( .CCB, .PDB);
		end;
	
	end;


!
routine XCP_CI ( CCB, PDB) :    novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine processes a complete from Transport for the Session
!	Control CONNECT-XMT call.
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!	PDB = Port Data Base address
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin
	map CCB: ref block field(C_fields);
	map PDB: ref block field(PORT_fields);

	local
	STK_CCB: ref block field(C_fields);

	If .CCB[C_STS] eql CE_RTE
	Then
		begin
		SIGNAL( NSP$_RTE, .CCB);
		CMQIN$( PDB[MSG_queue], .CCB[C_STK]);
		PDB[OTHres] = true;
		$MCB_RETURN_DSR( hdb_size, .CCB[C_ADDR]);
		CCB_RETRN( .CCB, .PDB);		
		return
		end
	Else
		begin
		STK_CCB = .CCB[C_STK];
		$MCB_RETURN_DSR( hdb_size, .CCB[C_ADDR]);

		If .CCB[C_STS] eql CS_SUC
		Then
			STK_CCB[C_STS] = N$SSUC
		Else
			STK_CCB[C_STS] = N$ENUR;
		STK_CCB[C_FNC] = FC_XCP;
		LLCRS$( .CCB[C_STK]);
		CCB_RETRN( .CCB, .PDB);
		end;
	end;

!
routine XCP_CONN ( CCB, PDB) :    novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine processes completes from Transport for the Session 
!	Control calls ACCEPT, REJECT, ABORT, DISCONNECT.
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!	PDB = Port Data Base address
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin
	map CCB: ref block field(C_fields);
	map PDB: ref block field(PORT_fields);


	local
	temp,
	NDB : ref block field(NODE_fields),
	STK_CCB: ref block field(C_fields);

	NDB = .PDB[NODElnk];
	STK_CCB = .CCB[C_STK];

        If .PDB[PORTstate] eql N$SCL or
        .PDB[PORTstate] eql N$SCN
        Then
		begin
		If .PDB[PORTstate] eql N$SCL
		Then
			STK_CCB[C_STS] = N$ECLS
		Else
			STK_CCB[C_STS] = N$EABR;
		STK_CCB[C_FNC] = FC_XCP;
		LLCRS$( .CCB[C_STK]);
		$MCB_RETURN_DSR( hdb_size, .CCB[C_ADDR]);
		CCB_RETRN( .CCB, .PDB);
		return
		end;
	If .CCB[C_STS] eql CE_RTE
	Then
		SIGNAL( NSP$_RTE, .CCB);

	$MCB_RETURN_DSR( hdb_size, .CCB[C_ADDR] );

	If .PDB[PORTstate] eql N$SDI or
	.PDB[PORTstate] eql N$SDR or
	.PDB[PORTstate] eql N$SCC
	Then
		begin
		MAP$( .DB[BIASnodes]);
		temp = .NDB[NDdelay];
		MAP$( .DB[BIASports]);

		If .temp eql 0
		Then
			PDB[TIMERcon] = 5
		Else
			PDB[TIMERcon] = .temp + .DB[NSPdelay]
		end;
	If .PDB[PORTstate] eql N$SRUN or
	.PDB[PORTstate] eql N$SDIC
	Then
		begin
		STK_CCB[C_STS] = N$SSUC;
		STK_CCB[C_FNC] = FC_XCP;
		LLCRS$( .STK_CCB);
		end
	Else
		CMQIN$( PDB[MSG_queue], .CCB[C_STK]);

	If .PDB[VERSIONrem] eql V3_1 and
	.CCB[C_STS] eql CE_DIS and .PDB[CONFIDENCE]
	Then
		begin
		PDB[TIMERcon] = 0;
		CALL$E( NSP_CONFIDENCE, .DB[NSPns2_pix], .CCB, .PDB);
		end
	Else
		CCB_RETRN( .CCB, .PDB);

        end;




!
routine XCP_DATA ( CCB, PDB) :    novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine processes completes from Transport for the Session Control
!	call DATA-XMT.
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!	PDB = Port Data Base address
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin
	map CCB: ref block field(C_fields);
	map PDB: ref block field(PORT_fields);


	local
	c : ref block field(C_fields),
	cp : ref block field(C_fields),
	q_temp,
	c_temp: ref block field(C_fields),
	temp,
	NDB : ref block field(NODE_fields),
	STK_CCB: ref block field(C_fields);

	NDB = .PDB[NODElnk];
	STK_CCB = .CCB[C_STK];

        If .PDB[PORTstate] eql N$SCL or
        .PDB[PORTstate] eql N$SCN or
	.PDB[PORTstate] eql N$SDN or
	(.PDB[PORTstate] eql N$SDI and
	(CMP_EQL( .PDB[NUMhigh], .PDB[ACKrcv_dat])))
        Then
		begin
		If (.STK_CCB[C_PRM3] and N$FCMP) neq 0
		Then
			begin
			bind SC_CCB = .STK_CCB[C_STK]: block field(C_fields);

			If .PDB[PORTstate] eql N$SCL
			Then
				SC_CCB[C_STS] = N$ECLS
			Else
				SC_CCB[C_STS] = N$EABR;
			SC_CCB[C_FNC] = FC_XCP;
			LLCRS$( SC_CCB);
			end;
		$MCB_RETURN_DSR( hdb_size, .CCB[C_ADDR]);
		CCB_RETRN( .CCB[C_STK], .PDB);
		CCB_RETRN( .CCB, .PDB);
		return
		end;

	If .CCB[C_STS] eql CE_RTE
	Then
		SIGNAL( NSP$_RTE, .CCB);


	$MCB_RETURN_DSR( hdb_size, .CCB[C_ADDR]);
	If .STK_CCB[C_STS] eql ((.PDB[ACKrcv_dat] + 1) and %o'7777') 
	Then
		begin
		MAP$( .DB[BIASnodes]);
		temp = .NDB[NDdelay];
		MAP$( .DB[BIASports]);
		PDB[TIMERdat] = .temp * .DB[NSPdelay]
		end;

	C = PDB[ACK_queue];
	While ( CP = .C; C = .C[C_LNK]) neq 0 do
		begin
		If (CMP_LSS(( .STK_CCB[C_STS] and %o'7777'), (.C[C_STS] and %o'7777')))
		Then
			exitloop;
		end;
	STK_CCB[C_LNK] = .CP[C_LNK];
	CP[C_LNK] = .CCB[C_STK];

	If CMP_LSS( .PDB[NUMsent], (.STK_CCB[C_STS] and %o'7777'))
	Then
		PDB[NUMsent] = .STK_CCB[C_STS];

	q_temp = .PDB[ACK_queue];

	While (CMQPT$( q_temp, c_temp)) do
		begin
		If CMP_LEQ( .c_temp[C_STS], .PDB[ACKrcv_dat])
		Then
			begin
			c_temp = .PDB[ACK_queue];
			PDB[ACK_queue] = .c_temp[c_lnk];

			If (.c_temp[C_PRM3] and N$FCMP) neq 0
			Then
				begin
				bind SC_CCB = .c_temp[C_STK]: block field(C_fields);
				SC_CCB[C_FNC] = FC_XCP;
				SC_CCB[C_STS] = N$SSUC;
				LLCRS$( SC_CCB);

				If .PDB[FLOWtyp_rem] eql FLOWmsg
				Then
					PDB[FLOWdat_rem] = .PDB[FLOWdat_rem] - 1;
				end;
			CCB_RETRN( .c_temp, .PDB);
			end;
		end;
	If .PDB[VERSIONrem] eql V3_1 and
	.CCB[C_STS] eql CE_DIS and .PDB[CONFIDENCE]
	Then
		begin
		PDB[TIMERdat] = 0;
		CALL$E( NSP_CONFIDENCE, .DB[NSPns2_pix], .CCB, .PDB);
		end
	Else
		CCB_RETRN( .CCB, .PDB);

	end;


!
routine XCP_OTH ( CCB, PDB) :    novalue =	!

!++
! FUNCTIONAL DESCRIPTION:
!	This routine processes completes from Transport for the Session
!	Control calls INTERRUPT-XMT, DATA-REQUEST, DATA-RCV.
!
! FORMAL PARAMETERS:
!	CCB = CCB address
!	PDB = Port Data Base address
!
! IMPLICIT INPUTS:
!	DB = NSP data base address
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

	begin
	map CCB: ref block field(C_fields);
	map PDB: ref block field(PORT_fields);


	local
	temp,
	NDB : ref block field(NODE_fields),
	STK_CCB: ref block field(C_fields);

	STK_CCB = .CCB[C_STK];
	NDB = .PDB[NODElnk];

        If .PDB[PORTstate] eql N$SCL or
        .PDB[PORTstate] eql N$SCN or
	.PDB[PORTstate] eql N$SDN or
	(.PDB[PORTstate] eql N$SDI and
	.PDB[NUMhigh] eql .PDB[ACKrcv_dat])
        Then
		begin
		If .PDB[PORTstate] eql N$SCL
		Then
			STK_CCB[C_STS] = N$ECLS
		Else
			STK_CCB[C_STS] = N$EABR;
		STK_CCB[C_FNC] = FC_XCP;
		LLCRS$( .CCB[C_STK]);
		$MCB_RETURN_DSR( hdb_size, .CCB[C_ADDR]);
		CCB_RETRN( .CCB, .PDB);
		return
		end;

	If .CCB[C_STS] eql CE_RTE
	Then
		SIGNAL( NSP$_RTE, .CCB);

	PDB[FLAGoth_ack] = false;
	$MCB_RETURN_DSR( hdb_size, .CCB[C_ADDR]);

	If .STK_CCB[C_STS] eql ((.PDB[NUMoth] -1) and %o'7777')
	Then
		begin
		PDB[OTHstate] = OTHready;
		If .STK_CCB[C_MOD] eql N_XBUF
		Then
			begin
			STK_CCB[C_STS] = N$SSUC;
			CMQIN$( PDB[BUFF_queue], .CCB[C_STK]);
			end
		Else
			begin
			STK_CCB[C_FNC] = FC_XCP;
			STK_CCB[C_STS] = N$SSUC;
			LLCRS$( .CCB[C_STK]);
			end
		end
	Else
		begin
		MAP$( .DB[BIASnodes]);
		temp = .NDB[NDdelay];
		MAP$( .DB[BIASports]);
		PDB[TIMERoth] = .temp * .DB[NSPdelay];
		CMQIN$( PDB[OTHack_queue], .CCB[C_STK]);
		end;
	If .PDB[VERSIONrem] eql V3_1 and
	.CCB[C_STS] eql CE_DIS and .PDB[CONFIDENCE]
	Then
		begin
		PDB[TIMERoth] = 0;
		CALL$E( NSP_CONFIDENCE, .DB[NSPns2_pix], .CCB, .PDB);
		end
	Else
		CCB_RETRN( .CCB, .PDB);
	
	end;


end

eludom