Trailing-Edge
-
PDP-10 Archives
-
TOPS-20_V6.1_DECnetSrc_7-23-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