Trailing-Edge
-
PDP-10 Archives
-
TOPS-20_V6.1_DECnetSrc_7-23-85
-
mcb/nsp/ns2.bli
There is 1 other file named ns2.bli in the archive. Click here to see a list.
module NS2 (
ident = 'X01150'
) =
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 allows the transmission and reception of
! NSP Connect/Disconnect messages.
!
!
! ENVIRONMENT: MCB
!
! AUTHOR: Ron Platukis CREATION DATE: 6-july-80
!
! MODIFIED BY:
!
! Alan Peckham, Ron Platukis 22-Oct-80
! 01 - 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.
! Ron Platukis 23-oct-80
! 02 - Set PORTstate negative if Reserved Port.
!
! 03 Ron Platukis 24-dec-80
! -Add Network Management Stuff.
!
! 04 Ron Platukis 13-jan-81
! -Change linkages to BLISS, add access for NSP Data Base address.
!
! 05 Ron Platukis 20-jan-81
! -Add Network Management event logging code.
!
! 06 Ron Platukis 16-feb-81
! -Add code to check BUFFsync_dsc in FLUSH_QUEUES routine.
!
! 07 Ron Platukis 30-apr-81
! -character move function overwrites temporary space in
! routine SHOW_NODE_COUNTERS.
!
! 08 Ron Platukis 1-may-81
! -Incorrect status code returned if successful completion
! of routine RETURN_NODE_LIST.
!
! 09 Ron Platukis 12-june-81
! -Include 600 series counters in SHOW_NODE_COUNTERS routine
! if asked for local data.
!
! 10 Ron Platukis 22-september-81
! -fix routine DI_RCV to send DC if in DI state and receive a DI.
!
! 11 Ron Platukis 2-february-82
! -modify routine DC_RCV to set CONFIDENCE false if receive a No-Link.
!
! 12 Ron Platukis 2-march-82
! -set entity type to "node" on event type 2
!
! 13 Alan Peckham 3-may-82
! -Do not recognize node #0 in FIND_NDB.
!
! 14 Alan Peckham 22-nov-82
! -Make EVENT_LOG use common event logging routines.
! -Support seconds-since-last-zeroed counter:
! Zero counter in NDB_GET.
! Show counter in EVENT_LOG and SHOW_NODE_COUNTERS.
! -Optimize SHOW_NODE_COUNTERS by removing loop.
! -Zero NSPmax when zeroing counters for NSPself.
!
! 15 Alan Peckham 9-dec-82
! -NDB_GET was not recycling node data bases.
! The routine was re-coded for correctness and efficiency.
!--
!
! INCLUDE FILES:
!
library
'mcb:xportx';
library
'mcb:mcblib';
library
'mcb:nmxlib';
require
'nspbli:nsinfo';
require
'nspbli:nspdata';
!
! TABLE OF CONTENTS:
!
forward routine
ACK_BLD: novalue,
CA_BLD: novalue, !format a CA msg
CA_RCV: CALL$ novalue, !process Connect Ack
CI_BLD: CALL$ novalue, !format a CI msg
CI_RECVD: novalue,
CI_RCV: CALL$ novalue, !process Connect Initiate
CC_BLD: CALL$ novalue, !format a CC msg
CC_RCV: CALL$ novalue, !process Connect Confirm
CCB_HDR_GET:,
CCB_GET:,
CCB_RETRN: novalue,
CTL_RECVD: CALL$ novalue, !Free stalled Control messages
C_STSE: novalue,
DADD: novalue,
DC_BLD: CALL$ novalue, !format a DC msg
DC_RCV: CALL$ novalue, !process Disconnect Confirm
DI_BLD: CALL$ novalue, !format a DI msg
DI_RCV: CALL$ novalue, !process Disconnect Initiate
DSC_RECVD: novalue,
EVENT_LOG: CALL$ novalue, ! event logger
FCCTL: CALL$ novalue, ! Control (i.e., NM)
FIND_NDB: , ! Locate a Node Data base
FLUSH_QUEUES: CALL$ novalue,
NDB_GET: CALL$,
NL_BLD: CALL$ novalue, !format a No-Link
NR_BLD: CALL$ novalue, !format a No-Resource
NSP_CONFIDENCE: CALL$ novalue, ! report CONFIDENCE false to SC
RESV_PORT: CALL$ novalue, !Reserve Port Process
RETURN_NODE_LIST: , !Network Management routines
SET_NODE_PARMS: , ! ""
SHOW_NODE_ITEMS: , ! ""
SHOW_NODE_COUNTERS: , ! ""
ZERO_NODE_COUNTERS: , ! ""
SHOW_ZERO_NODE_COUNTERS: , ! ""
UPDATE_DELAY: novalue, ! Update round trip delay
XPT_XMIT: novalue; !queue CCB to XPT
!
! MACROS:
!
macro
RAD50 (STR) =
%if %bliss (bliss36) %then %rad50_10 STR %else %rad50_11 STR %fi %;
!
! EQUATED SYMBOLS:
!
literal ! Autoparsing stuff
$16$ = 2^13, ! 16 bit wide counter
$32$ = 3^13, ! 32 bit wide counter
CNT = 1^15; ! Counter flag
!
! OWN STORAGE:
!
$MCB_PROCESS( name = NS2)
!
! EXTERNAL REFERENCES:
!
external
%name('.crdat'): vector[2],
$DSPCR;
bind DB = %name('.crdat')[1]: ref block field(NSP_fields);
routine ACK_BLD ( CCB, PDB) : novalue = !
!++
! FUNCTIONAL DESCRIPTION:
! This routine formats an NSP Data Acknowledgement message.
!
! 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
PTR;
PTR = .CCB[C_ADDR];
ch$wchar_a( FLG_DAT_ACK, PTR);
ch$wchar_a( .PDB[L_rem_addr], PTR);
ch$wchar_a( .PDB[H_rem_addr], PTR);
ch$wchar_a( .PDB[PID], PTR);
ch$wchar_a( .PDB[ADDran], PTR);
PUT2BYTES( (.PDB[ACKdat_xmt] and %o'7777') + Q_ACK^12 + true^15, PTR);
CCB[C_CNT] = ch$diff(.PTR, .CCB[C_ADDR]);
PDB[FLAGdat_ack] = false;
XPT_XMIT( .CCB, .PDB)
end;
routine CA_BLD ( CCB, PDB) : novalue = !
!++
! FUNCTIONAL DESCRIPTION:
! This routine formats an NSP Connect Acknowledgement message.
!
! 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
PTR;
PTR = .CCB[C_ADDR];
ch$wchar_a( FLG_CA, PTR);
ch$wchar_a( .PDB[L_rem_addr], PTR);
ch$wchar_a( .PDB[H_rem_addr], PTR);
CCB[C_CNT] = ch$diff(.PTR, .CCB[C_ADDR]);
XPT_XMIT( .CCB, .PDB)
end;
global routine CA_RCV ( CCB, PDB) :CALL$ novalue = !
!++
! FUNCTIONAL DESCRIPTION:
! This routine processes a received Connect Acknowledgement message.
!
! 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$SCI
Then
begin
PDB[PORTstate] = N$SCD;
UPDATE_DELAY( .PDB)
end;
CCB[C_FNC] = FC_RCE;
LLCRS$( .CCB)
end;
global routine CC_BLD ( CCB, PDB) :CALL$ novalue = !
!++
! FUNCTIONAL DESCRIPTION:
! This routine formats an NSP Connect Confirm message.
!
! 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
PTR;
PTR = .CCB[C_ADDR];
CCB[C_CHN] = .CCB[C_STK];
ch$wchar_a( FLG_CC, PTR);
ch$wchar_a( .PDB[L_rem_addr], PTR);
ch$wchar_a( .PDB[H_rem_addr], PTR);
ch$wchar_a( .PDB[PID], PTR);
ch$wchar_a( .PDB[ADDran], PTR);
ch$wchar_a( .PDB[FLOWloc_typ]^2 + 1, PTR);
ch$wchar_a( 0, PTR);
PUT2BYTES( .DB[NSPbuf], PTR);
CCB[C_CNT] = ch$diff(.PTR, .CCB[C_ADDR]);
If .PDB[DELAYstr_tim] eql 0
Then
PDB[DELAYstr_tim] = 1;
XPT_XMIT( .CCB, .PDB)
end;
global routine CC_RCV ( CCB, PDB ) :CALL$ novalue = !
!++
! FUNCTIONAL DESCRIPTION:
! This routine processes a received Connect Confirm message.
!
! 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
PTR,
NDB : ref block field(NODE_fields),
WK_CCB: ref block field(C_fields);
PTR = ch$plus( .CCB[C_ADDR], 5 );
NDB = .PDB[NODElnk];
If .PDB[BUFFctl] neq 0
Then
begin
CCB[C_FNC] = FC_RCE;
LLCRS$( .CCB);
return
end;
MAP$( .CCB[C_BIAS]);
DB[SERVICES] = ch$rchar_a( PTR);
DB[INFO] = ch$rchar_a( PTR);
DB[SEGSIZE] = GET2BYTES( PTR);
MAP$( .DB[BIASports]);
If (.DB[FCOPT] neq FLOWrsv) and
((.DB[SERVICES] and 1) neq 0) and
((.DB[INFO] and %o'374') eql 0)
Then
begin
IF .PDB[PORTstate] eql N$SCI or
.PDB[PORTstate] eql N$SCD
Then
begin
MAP$( .DB[BIASnodes]);
DADD( NDB[NDb_rcv], .CCB[C_CNT] - CC_SIZE);
MAP$( .DB[BIASports]);
PDB[L_rem_addr] = .DB[L_SRCADDR];
PDB[H_rem_addr] = .DB[H_SRCADDR];
PDB[FLOWtyp_rem] = .DB[FCOPT];
PDB[VERSIONrem] = .DB[INFO];
PDB[SIZEseg] = MIN( .DB[SEGSIZE], .DB[NSPbuf]);
PDB[TIMERinact] = .DB[NSPact_tim];
If .PDB[PORTstate] eql N$SCI
Then
UPDATE_DELAY( .PDB);
PDB[PORTstate] = N$SRUN;
PDB[FLAGdat_ack] = true;
If CCB_GET( WK_CCB, .PDB)
Then
begin
WK_CCB[C_STK] = .CCB;
C_STSE( .WK_CCB, .PDB)
end
Else
begin
PDB[BUFFctl] = .CCB;
return
end;
If CCB_HDR_GET( 0, WK_CCB, .PDB)
Then
ACK_BLD( .WK_CCB, .PDB)
Else
PDB[FLAGdat_ack] = true;
return
end;
If .PDB[PORTstate] eql N$SRUN
Then
PDB[FLAGdat_ack] = true
end;
CCB[C_FNC] = FC_RCE;
LLCRS$( .CCB)
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_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_RETRN ( CCB, PDB): novalue = !
!++
! FUNCTIONAL DESCRIPTION:
! This routine deallocates a CCB.
!
! 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 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;
global routine CTL_RECVD ( PDB) : CALL$ novalue = !
!++
! FUNCTIONAL DESCRIPTION:
! This routine attempts to clear out BUFFctl queue if non-zero.
!
! 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
GOT_CCB: ref block field(C_fields),
CA_CCB: ref block field(C_fields);
Selectone .PDB[PORTstate] of
Set
[N$SNR, N$SRUN, N$SRJ]:
begin
If CCB_GET(GOT_CCB, .PDB)
Then
begin
GOT_CCB[C_STK] = .PDB[BUFFctl];
C_STSE( .GOT_CCB, .PDB);
PDB[BUFFctl] = 0
End
Else
return;
end;
[N$SDN]:
begin
If CCB_GET(GOT_CCB, .PDB)
Then
begin
GOT_CCB[C_STK] = .PDB[BUFFctl];
DSC_RECVD( .GOT_CCB, .PDB);
PDB[BUFFctl] = 0
end
Else
return
end;
[N$SCR]:
begin
If CCB_GET( GOT_CCB, .PDB)
Then
begin
If not CCB_HDR_GET( 0, CA_CCB, .PDB)
Then
begin
CCB_RETRN( .GOT_CCB, .PDB);
return
end;
CA_BLD( .CA_CCB, .PDB);
GOT_CCB[C_STK] = .PDB[BUFFctl];
CI_RECVD( .GOT_CCB, .PDB);
PDB[BUFFctl] = 0;
end
Else
return;
end;
[N$SCN]:
begin
If CCB_GET(GOT_CCB, .PDB)
Then
begin
CALL$L( NSP_CONFIDENCE, .GOT_CCB, .PDB);
CA_CCB = .PDB[BUFFctl];
CA_CCB[C_FNC] = FC_RCE;
LLCRS$( .CA_CCB);
CALL$L( FLUSH_QUEUES, .PDB, N$EABR);
end
Else
return;
end;
Tes;
end;
routine C_STSE ( CCB, PDB): novalue = !
!++
! FUNCTIONAL DESCRIPTION:
! This routine generates a CONNECT-STATUS call to Session Control.
!
! 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 PDB: ref block field(PORT_fields);
map CCB: ref block field(C_fields);
bind STK_CCB = .CCB[C_STK]: block field(C_fields);
CCB[C_FNC] = FC_RCP;
CCB[C_MOD] = N_SCNS;
CCB[C_LIX] = .PDB[PID];
CCB[C_BIAS] = .STK_CCB[C_BIAS];
Selectone .PDB[PORTstate] of
Set
[N$SNR]:
begin
CCB[C_STS] = N$EOPN;
CCB[C_CNT] = 0;
CCB[C_ADDR] = 0;
end;
[N$SRJ]:
begin
CCB[C_STS] = N$SREJ;
CCB[C_CNT] = .STK_CCB[C_CNT] - DI_SIZE;
CCB[C_ADDR] = ch$plus(.STK_CCB[C_ADDR], DI_SIZE);
end;
[N$SRUN]:
begin
CCB[C_STS] = N$SACC;
CCB[C_CNT] = .STK_CCB[C_CNT] - CC_SIZE;
CCB[C_ADDR] = ch$plus(.STK_CCB[C_ADDR], CC_SIZE);
end;
Tes;
CCB[C_PIX] = .DB[NSPsc_pix];
LLCRS$( .CCB);
end;
global routine CI_BLD ( CCB, PDB) :CALL$ novalue = !
!++
! FUNCTIONAL DESCRIPTION:
! This routine formats an NSP Connect Initiate message.
!
! 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),
PTR;
PTR = .CCB[C_ADDR];
NDB = .PDB[NODElnk];
ch$wchar_a( FLG_CI, PTR);
ch$wchar_a( 0, PTR);
ch$wchar_a( 0, PTR);
ch$wchar_a( .PDB[PID], PTR);
ch$wchar_a( .PDB[ADDran], PTR);
ch$wchar_a( .PDB[FLOWloc_typ]^2 + 1, PTR);
ch$wchar_a( 0, PTR);
PUT2BYTES( .DB[NSPbuf], PTR);
CCB[C_CNT] = ch$diff(.PTR, .CCB[C_ADDR]);
CCB[C_CHN] = .CCB[C_STK];
PDB[DELAYstr_tim] = 1;
MAP$( .DB[BIASnodes]);
NDB[NDc_xmt] = .NDB[NDc_xmt] + 1;
MAP$( .DB[BIASports]);
XPT_XMIT( .CCB, .PDB)
end;
routine CI_RECVD ( CCB, PDB): novalue = !
!++
! FUNCTIONAL DESCRIPTION:
! This routine generates a CONNECT-RECIEVED call to Session
! Control.
!
! 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 PDB: ref block field(PORT_fields);
map CCB: ref block field(C_fields);
bind STK_CCB = .CCB[C_STK]: block field(C_fields);
CCB[C_FNC] = FC_RCP;
CCB[C_MOD] = N_RCON;
CCB[C_LIX] = .PDB[PID];
CCB[C_CNT] = .STK_CCB[C_CNT] - CI_SIZE;
CCB[C_BIAS] = .STK_CCB[C_BIAS];
CCB[C_ADDR] = ch$plus(.STK_CCB[C_ADDR], CI_SIZE);
CCB[C_PRM1] = .STK_CCB[C_PRM1];
CCB[C_PIX] = .DB[NSPsc_pix];
LLCRS$( .CCB);
end;
global routine CI_RCV ( CCB, PDB) :CALL$ novalue = !
!++
! FUNCTIONAL DESCRIPTION:
! This routine processes a received Connect Initiate message.
!
! 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
GOT_CCB: ref block field(C_fields),
CA_CCB: ref block field(C_fields),
PTR,
temp;
bind NODE = .DB[ADDRnodes]: blockvector[0, ND_SIZE] field(NODE_fields);
PTR = ch$plus( .CCB[C_ADDR], 5 );
MAP$( .CCB[C_BIAS]);
DB[SERVICES] = ch$rchar_a( PTR);
DB[INFO] = ch$rchar_a( PTR);
DB[SEGSIZE] = GET2BYTES( PTR);
MAP$( .DB[BIASports]);
If (.DB[FCOPT] neq FLOWrsv) and
(.DB[L_DSTADDR] eql 0 and .DB[H_DSTADDR] eql 0) and
((.DB[SERVICES] and 1) neq 0) and
((.DB[INFO] and %o'374') eql 0)
Then
begin
If not CALL$L( NDB_GET, .CCB, temp)
Then
begin
CALL$L(RESV_PORT, .CCB);
return
end
Else
begin
bind NDB = .temp: block field(NODE_fields);
PDB[NODElnk] = .temp;
MAP$( .DB[BIASnodes]);
NDB[NDc_rcv] = .NDB[NDc_rcv] + 1;
DADD( NDB[NDb_rcv], .CCB[C_CNT] - CI_SIZE);
MAP$( .DB[BIASports]);
PDB[NODErem] = .CCB[C_PRM1];
If .PDB[NODErem] eql .DB[NSPself]
Then
PDB[CHANNEL] = .CCB[C_LIX]
Else
PDB[CHANNEL] = 0;
PDB[PORTstate] = N$SCR;
DB[NSPmax] = .DB[NSPmax] + 1;
PDB[FLOWtyp_rem] = .DB[FCOPT];
PDB[VERSIONrem] = .DB[VER];
PDB[L_rem_addr] = .DB[L_SRCADDR];
PDB[H_rem_addr] = .DB[H_SRCADDR];
PDB[SIZEseg] = MIN( .DB[SEGSIZE], .DB[NSPbuf]);
If CCB_GET( GOT_CCB, .PDB)
Then
begin
If not CCB_HDR_GET( 0, CA_CCB, .PDB)
Then
begin
CCB_RETRN( .GOT_CCB, .PDB);
PDB[BUFFctl] = .CCB;
return
end;
CA_BLD( .CA_CCB, .PDB);
GOT_CCB[C_STK] = .CCB;
CI_RECVD( .GOT_CCB, .PDB);
end
Else
PDB[BUFFctl] = .CCB;
end
end
Else
begin
CCB[C_FNC] = FC_RCE;
LLCRS$( .CCB)
end
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;
global routine DC_BLD ( CCB, PDB) :CALL$ novalue = !
!++
! FUNCTIONAL DESCRIPTION:
! This routine formats an NSP Disconnect Confirm message.
!
! 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
PTR;
PTR = .CCB[C_ADDR];
ch$wchar_a( FLG_DC, PTR);
ch$wchar_a( .PDB[L_rem_addr], PTR);
ch$wchar_a( .PDB[H_rem_addr], PTR);
ch$wchar_a( .PDB[PID], PTR);
ch$wchar_a( .PDB[ADDran], PTR);
ch$wchar_a( 42, PTR);
ch$wchar_a( 0, PTR);
CCB[C_CNT] = ch$diff(.PTR, .CCB[C_ADDR]);
PDB[FLAGsnd_dc] = false;
XPT_XMIT( .CCB, .PDB)
end;
global routine DC_RCV ( CCB, PDB ) :CALL$ novalue = !
!++
! FUNCTIONAL DESCRIPTION:
! This routine processes a received Disconnect Confirm message.
!
! 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
PTR,
WK_CCB: ref block field(C_fields);
PTR = ch$plus( .CCB[C_ADDR], 5 );
MAP$( .CCB[C_BIAS]);
DB[REASON] = GET2BYTES( PTR);
MAP$( .DB[BIASports]);
Selectone .DB[REASON] of
Set
[1]:
begin
PDB[PORTstate] = N$SNR;
If CCB_GET( WK_CCB, .PDB)
Then
begin
WK_CCB[C_STK] = .CCB;
C_STSE( .WK_CCB, .PDB);
return
end
Else
begin
If .PDB[BUFFctl] eql 0
Then
begin
PDB[BUFFctl] = .CCB;
return
end;
end;
end;
[41]:
begin
If .PDB[PORTstate] eql N$SCC or
.PDB[PORTstate] eql N$SRUN or
.PDB[PORTstate] eql N$SDR or
.PDB[PORTstate] eql N$SDI
Then
begin
PDB[PORTstate] = N$SCN;
PDB[TIMERcon] = 0;
PDB[TIMERdat] = 0;
PDB[TIMERoth] = 0;
If .PDB[CONFIDENCE]
Then
begin
If CCB_GET( WK_CCB, .PDB)
Then
CALL$L( NSP_CONFIDENCE, .WK_CCB, .PDB)
Else
begin
If .PDB[BUFFctl] eql 0
Then
begin
PDB[BUFFctl] = .CCB;
return
end;
end;
end;
end;
CALL$L( FLUSH_QUEUES, .PDB, N$EABR);
end;
[42]:
begin
If .PDB[PORTstate] eql N$SDR or
.PDB[PORTstate] eql N$SDI or
.PDB[PORTstate] eql N$SDIC
Then
begin
If .PDB[PORTstate] eql N$SDR
Then
PDB[PORTstate] = N$SDRC
Else
PDB[PORTstate] = N$SDIC;
PDB[TIMERcon] = 0;
UPDATE_DELAY( .PDB);
If CMQRM$( PDB[MSG_queue], WK_CCB)
Then
begin
WK_CCB[C_STS] = N$SSUC;
WK_CCB[C_FNC] = FC_XCP;
LLCRS$( .WK_CCB)
end;
end;
end;
[otherwise]:
begin
If .PDB[VERSIONrem] eql V3_1
Then
begin
If .PDB[PORTstate] eql N$SCI
Then
begin
PDB[PORTstate] = N$SRJ;
UPDATE_DELAY( .PDB);
If CCB_GET( WK_CCB, .PDB)
Then
begin
WK_CCB[C_STK] = .CCB;
C_STSE( .WK_CCB, .PDB);
return
end
Else
begin
If .PDB[BUFFctl] eql 0
Then
begin
PDB[BUFFctl] = .CCB;
return
end;
end
end
Else
begin
If .PDB[PORTstate] eql N$SCC or
.PDB[PORTstate] eql N$SRUN or
.PDB[PORTstate] eql N$SDR or
.PDB[PORTstate] eql N$SDI
Then
begin
PDB[PORTstate] = N$SCN;
PDB[TIMERcon] = 0;
PDB[TIMERdat] = 0;
PDB[TIMERoth] = 0;
If .PDB[CONFIDENCE]
Then
begin
If CCB_GET( WK_CCB, .PDB)
Then
CALL$L( NSP_CONFIDENCE, .WK_CCB, .PDB)
Else
begin
If .PDB[BUFFctl] eql 0
Then
begin
PDB[BUFFctl] = .CCB;
return
end;
end;
end;
end;
end;
CALL$L( FLUSH_QUEUES, .PDB, N$EABR);
end;
end;
Tes;
CCB[C_FNC] = FC_RCE;
LLCRS$( .CCB)
end;
global routine DI_BLD ( CCB, PDB) :CALL$ novalue =!
!++
! FUNCTIONAL DESCRIPTION:
! This routine formats an NSP Disconnect Initiate message.
!
! 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
PTR;
PTR = .CCB[C_ADDR];
CCB[C_CHN] = .CCB[C_STK];
ch$wchar_a( FLG_DI, PTR);
ch$wchar_a( .PDB[L_rem_addr], PTR);
ch$wchar_a( .PDB[H_rem_addr], PTR);
ch$wchar_a( .PDB[PID], PTR);
ch$wchar_a( .PDB[ADDran], PTR);
CCB[C_CNT] = ch$diff(.PTR, .CCB[C_ADDR]);
If .PDB[DELAYstr_tim] eql 0
Then
PDB[DELAYstr_tim] = 1;
XPT_XMIT( .CCB, .PDB)
end;
global routine DI_RCV ( CCB, PDB ) :CALL$ novalue = !
!++
! FUNCTIONAL DESCRIPTION:
! This routine processes a received Disconnect Initiate message.
!
! 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),
NO_RCE,
WK_CCB: ref block field(C_fields);
NO_RCE = false;
NDB = .PDB[NODElnk];
If .PDB[BUFFctl] neq 0
Then
begin
CCB[C_FNC] = FC_RCE;
LLCRS$( .CCB);
return
end;
Selectone .PDB[PORTstate] of
Set
[N$SDI]:
begin
PDB[PORTstate] = N$SDIC;
PDB[DELAYstr_tim] = 0;
PDB[TIMERcon] = 0;
CALL$L( FLUSH_QUEUES, .PDB, N$EABR);
end;
[N$SCI, N$SCD, N$SRUN]:
begin
If .PDB[PORTstate] eql N$SCI
Then
UPDATE_DELAY( .PDB);
If .PDB[PORTstate] eql N$SCI or
.PDB[PORTstate] eql N$SCD
Then
begin
PDB[PORTstate] = N$SRJ;
PDB[L_rem_addr] = .DB[L_SRCADDR];
PDB[H_rem_addr] = .DB[H_SRCADDR];
end;
If .PDB[PORTstate] eql N$SRUN
Then
begin
PDB[PORTstate] = N$SDN;
CALL$L( FLUSH_QUEUES, .PDB, N$EABR);
PDB[DELAYstr_tim] = 0;
PDB[TIMERdat] = 0;
PDB[TIMERoth] = 0;
end;
MAP$( .DB[BIASnodes]);
DADD( NDB[NDb_rcv], .CCB[C_CNT] - DI_SIZE);
MAP$( .DB[BIASports]);
If CCB_GET( WK_CCB, .PDB)
Then
begin
WK_CCB[C_STK] = .CCB;
If .PDB[PORTstate] eql N$SRJ
Then
C_STSE( .WK_CCB, .PDB)
Else
DSC_RECVD( .WK_CCB, .PDB);
end
Else
PDB[BUFFctl] = .CCB;
NO_RCE = true;
end;
Tes;
If .PDB[PORTstate] eql N$SDN or
.PDB[PORTstate] eql N$SRJ or
.PDB[PORTstate] eql N$SDIC
Then
begin
If CCB_HDR_GET( 0, WK_CCB, .PDB)
Then
CALL$L(DC_BLD, .WK_CCB, .PDB)
Else
PDB[FLAGsnd_dc] = true
end;
If .NO_RCE eql false
Then
begin
CCB[C_FNC] = FC_RCE;
LLCRS$( .CCB)
end;
end;
routine DSC_RECVD ( CCB, PDB): novalue = !
!++
! FUNCTIONAL DESCRIPTION:
! This routine generates a DISCONNECT-RECIEVED call to Session
! Control.
!
! 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 PDB: ref block field(PORT_fields);
map CCB: ref block field(C_fields);
bind STK_CCB = .CCB[C_STK]: block field(C_fields);
CCB[C_FNC] = FC_RCP;
CCB[C_MOD] = N_RDSC;
CCB[C_LIX] = .PDB[PID];
CCB[C_BIAS] = .STK_CCB[C_BIAS];
CCB[C_CNT] = .STK_CCB[C_CNT] - DI_SIZE;
CCB[C_ADDR] = ch$plus(.STK_CCB[C_ADDR], DI_SIZE);
CCB[C_PIX] = .DB[NSPsc_pix];
LLCRS$( .CCB);
end;
global routine EVENT_LOG ( type, aux, PDB, CCB) : CALL$ novalue = !
!++
! FUNCTIONAL DESCRIPTION:
! This routine logs events.
!
! FORMAL PARAMETERS:
! type = event type to log
! aux = auxillary data required to log event
! PDB = Port data base address
! 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);
map PDB: ref block field(PORT_fields);
local
save_bias,
temp;
SMAP$( save_bias);
MAP$( .CCB[C_BIAS]);
$NM_LOG_BEGIN();
Case .type from invmsg to invflw of
Set
[invmsg]:
begin
PARAMETER_HI( 0, 12, .CCB[C_ADDR]);
end;
[invflw]:
begin
PARAMETER_HI( 0, 12, .CCB[C_ADDR]);
PARAMETER_DS_1( 1, aux);
end;
Tes;
$NM_LOG_END((.type + NSP_class_event^6), 0);
MAP$( .save_bias);
end;
global routine FCCTL ( CCB, FCM): CALL$ novalue =
!++
! FUNCTIONAL DESCRIPTION:
! This routine is activated by a control request from
! Network Management.
!
! FORMAL PARAMETERS:
! CCB CCB to pass to handler routine
! FCM Function code modifier (Must be FM_NM)
!
! IMPLICIT INPUTS:
! CCB Contents
! DB Data base address
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
map CCB: ref block field (C_NM_FIELDS);
local
STATUS;
MAP$( .DB[BIASnodes]);
STATUS =
begin
if .FCM neq FM_NM
then $NM$ERR_MPE
else
begin
case .CCB [C_NM_ENTITY] from NMX$ENT_lo to NMX$ENT_hi of
set
[NMX$ENT_nod]: ! NM fnc for node parameter
begin
case .CCB [C_NM_FUNC] from NMX$FNC_lo to NMX$FNC_hi of
set ! *** NODE ***
[NMX$FNC_set]:
SET_NODE_PARMS ( .CCB); ! Set parameters
[NMX$FNC_zro]:
ZERO_NODE_COUNTERS( .CCB); ! Zero counters
[NMX$FNC_sho]:
SHOW_NODE_ITEMS ( .CCB); ! Show selected items
[NMX$FNC_szc]:
SHOW_ZERO_NODE_COUNTERS( .CCB); ! Zero and show counters
[NMX$FNC_ret]:
RETURN_NODE_LIST ( .CCB); ! Return selected items
[inrange, outrange]:
$NM$ERR_MPE;
tes
end;
[inrange, outrange]:
$NM$ERR_MPE;
tes
end
end;
CCB[C_FNC] = FC_CCP;
CCB[C_STS] = .STATUS;
LLCRS$( .CCB);
end;
routine FIND_NDB ( NODEADDR): =
!++
! FUNCTIONAL DESCRIPTION:
! Locate the NDB for the Node addressed by NM_ENT in NMPAR
!
! FORMAL PARAMETERS:
! NODEADDR Address to return NDB address
!
! IMPLICIT INPUTS:
! DB Data base address
! PARBLK & NMPAR inputs, as pointed at by CCB.
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! Operation status code
!
! COMPLETION CODES:
! None
!
!
! SIDE EFFECTS:
! None
!--
begin
bind NODE = .DB[ADDRnodes]: blockvector[ 0, ND_SIZE] field( NODE_fields);
If ..NODEADDR eql 0 then return false;
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 ..NODEADDR
Then
begin
.NODEADDR = NDB;
return true
end
end;
false
end;
global routine FLUSH_QUEUES ( PDB, status_code) : CALL$ novalue = !
!++
! FUNCTIONAL DESCRIPTION:
! This routine flushes all of NSP's processing queues.
!
! FORMAL PARAMETERS:
! PDB = Port Data Base address
! STATUS_CODE = Code to return to Session Control
!
! 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
RTN_CCB: ref block field(C_fields),
STK_CCB: ref block field(C_fields);
While CMQRM$(PDB[INT_queue], rtn_ccb) do
begin
RTN_CCB[C_STS] = .status_code;
RTN_CCB[C_FNC] = FC_XCP;
LLCRS$( .RTN_CCB)
end;
If .PDB[BUFFrcv_int] neq 0
Then
begin
RTN_CCB = .PDB[BUFFrcv_int];
PDB[BUFFrcv_int] = 0;
RTN_CCB[C_FNC] = FC_RCE;
LLCRS$( .RTN_CCB)
end;
If .PDB[BUFFctl] neq 0
Then
begin
RTN_CCB = .PDB[BUFFctl];
PDB[BUFFctl] = 0;
RTN_CCB[C_FNC] = FC_RCE;
LLCRS$( .RTN_CCB)
end;
If .PDB[BUFFsync_dsc] neq 0
Then
begin
RTN_CCB = .PDB[BUFFsync_dsc];
PDB[BUFFsync_dsc] = 0;
RTN_CCB[C_FNC] = FC_XCP;
RTN_CCB[C_STS] = .status_code;
LLCRS$( .RTN_CCB)
end;
While ( rtn_ccb = .PDB[ACK_queue]) neq 0 do
begin
PDB[ACK_queue] = .rtn_ccb[C_LNK];
If (.RTN_CCB[C_PRM3] and N$FCMP) neq 0
Then
begin
STK_CCB = .RTN_CCB[C_STK];
STK_CCB[C_STS] = .status_code;
STK_CCB[C_FNC] = FC_XCP;
LLCRS$( .STK_CCB)
end;
CCBRT$( .rtn_ccb);
PDB[COUNTres] = .PDB[COUNTres] -1
end;
While CMQRM$(PDB[MSG_queue], rtn_ccb) do
begin
RTN_CCB[C_STS] = .status_code;
RTN_CCB[C_FNC] = FC_XCP;
LLCRS$( .RTN_CCB)
end;
While CMQRM$(PDB[OTHack_queue], rtn_ccb) do
begin
RTN_CCB[C_STS] = .status_code;
RTN_CCB[C_FNC] = FC_XCP;
LLCRS$( .RTN_CCB)
end;
While CMQRM$(PDB[INTR_queue], rtn_ccb) do
begin
RTN_CCB[C_STS] = .status_code;
RTN_CCB[C_FNC] = FC_XCP;
LLCRS$( .RTN_CCB)
end;
While CMQRM$(PDB[DATR_queue], rtn_ccb) do
begin
RTN_CCB[C_STS] = .status_code;
RTN_CCB[C_FNC] = FC_XCP;
LLCRS$( .RTN_CCB)
end;
While CMQRM$(PDB[BUFF_queue], rtn_ccb) do
begin
RTN_CCB[C_STS] = .status_code;
RTN_CCB[C_FNC] = FC_XCP;
LLCRS$( .RTN_CCB)
end;
While CMQRM$(PDB[RCVMSG_queue], rtn_ccb) do
begin
RTN_CCB[C_FNC] = FC_RCE;
LLCRS$( .RTN_CCB)
end;
end;
global routine NDB_GET ( CCB, RTN_NDB): CALL$ = !
!++
! FUNCTIONAL DESCRIPTION:
! This routine attempts to find a Node Data Base entry for the node
! in question.
!
! FORMAL PARAMETERS:
! CCB = CCB address
! RTN_NDB = address to return found NDB 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 RTN_NDB: block field(NODE_fields);
label NDB_FOUND, NODE_FOUND;
local NNDB: ref block field(NODE_fields),
FNDB: ref block field(NODE_fields);
MAP$ (.DB[BIASnodes]);
NNDB = .DB[ADDRnodes];
FNDB = 0;
NDB_FOUND: begin
NODE_FOUND: begin
decru J from .DB[NSPt_nodes] to 1
do begin
if .NNDB[NDaddr] eql .CCB[C_PRM1]
then leave NODE_FOUND;
if (.NNDB[NDactive] eql 0)
then begin
if (.FNDB eqla 0)
then FNDB = .NNDB
else if (.FNDB[NDaddr] neq 0)
then if (.NNDB[NDaddr] eql 0)
then FNDB = .NNDB;
end;
NNDB = vector[.NNDB,ND_SIZE];
end;
If (NNDB = .FNDB) eqla 0 then leave NDB_FOUND;
If .NNDB[NDaddr] neq 0
Then begin ! Issue "data base reused" event
literal event_code = (dbruse + NSP_class_event^6) or %o'100000';
$NM_LOG_BEGIN();
COUNTER_16_TIME( 0, NNDB[NDtime_zeroed]);
COUNTER_32( 600, NNDB[NDb_rcv]);
COUNTER_32( 601, NNDB[NDb_xmt]);
COUNTER_32( 610, NNDB[NDm_rcv]);
COUNTER_32( 611, NNDB[NDm_xmt]);
COUNTER_16( 620, NNDB[NDc_rcv]);
COUNTER_16( 621, NNDB[NDc_xmt]);
COUNTER_16( 630, NNDB[NDtimeout]);
COUNTER_16( 640, NNDB[NDc_rej]);
COUNTER_16( 700, NNDB[NDactive]);
$NM_LOG_END(event_code, .NNDB[NDaddr]);
end;
decru J from ND_SIZE to 1
do begin
map FNDB: ref vector;
FNDB[0] = 0;
FNDB = FNDB[1];
end;
$NM_TIME( NNDB[NDtime_zeroed]);
NNDB[NDaddr] = .CCB[C_PRM1];
end; ! of NODE_FOUND
NNDB[NDactive] = .NNDB[NDactive] + 1;
end; ! of NDB_FOUND
MAP$( .DB[BIASports]);
if (.RTN_NDB = .NNDB) neqa 0 then true else false
end;
global routine NL_BLD ( CCB, RDB) : CALL$ novalue = !
!++
! FUNCTIONAL DESCRIPTION:
! This routine formats an NSP No Link message.
!
! FORMAL PARAMETERS:
! CCB = CCB address
! RDB = Reserved 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 RDB: ref block field(PORT_fields);
local
PTR;
PTR = .CCB[C_ADDR];
ch$wchar_a( FLG_DC, PTR);
ch$wchar_a( .RDB[L_rem_addr], PTR);
ch$wchar_a( .RDB[H_rem_addr], PTR);
ch$wchar_a( .RDB[PID], PTR);
ch$wchar_a( .RDB[ADDran], PTR);
ch$wchar_a( 41, PTR);
ch$wchar_a( 0, PTR);
CCB[C_CNT] = ch$diff(.PTR, .CCB[C_ADDR]);
XPT_XMIT( .CCB, .RDB)
end;
global routine NR_BLD ( CCB, RDB) : CALL$ novalue = !
!++
! FUNCTIONAL DESCRIPTION:
! This routine formats an NSP No Resources message.
!
! FORMAL PARAMETERS:
! CCB = CCB address
! RDB = Reserved 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 RDB: ref block field(PORT_fields);
local
PTR;
PTR = .CCB[C_ADDR];
ch$wchar_a( FLG_DC, PTR);
ch$wchar_a( .RDB[L_rem_addr], PTR);
ch$wchar_a( .RDB[H_rem_addr], PTR);
ch$wchar_a( .RDB[PID], PTR);
ch$wchar_a( .RDB[ADDran], PTR);
ch$wchar_a( 1, PTR);
ch$wchar_a( 0, PTR);
CCB[C_CNT] = ch$diff(.PTR, .CCB[C_ADDR]);
XPT_XMIT( .CCB, .RDB)
end;
global routine NSP_CONFIDENCE ( CCB, PDB): CALL$ novalue = !
!++
! FUNCTIONAL DESCRIPTION:
! This routine generates a CONFIDENCE call to Session Control.
!
! 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 PDB: ref block field(PORT_fields);
map CCB: ref block field(C_fields);
PDB[CONFIDENCE] = false;
SIGNAL( NSP$_CFN,.PDB[PID]);
CCB[C_FNC] = FC_RCP;
CCB[C_MOD] = N_SCNF;
CCB[C_LIX] = .PDB[PID];
CCB[C_STS] = N$ECON;
CCB[C_PIX] = .DB[NSPsc_pix];
CCB[C_ADDR] = 0;
CCB[C_STK] = 0;
LLCRS$( .CCB);
end;
global routine RESV_PORT ( CCB ) :CALL$ novalue = !
!++
! FUNCTIONAL DESCRIPTION:
! This routine is the reserve port process for NSP.
!
! 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
RDB: ref block field( PORT_fields),
temp;
bind RPORT = .DB[ADDRresv]: blockvector[0, RDB_size] field(PORT_fields);
MAP$( .DB[BIASresv]);
RDB = (Incr j from 0 to .DB[NSPt_rsv] -1 do
begin
bind X = RPORT[.j, 0, 0, 0, 0]: block field(PORT_fields);
If .X[MSGtyp] eql MSG_NONE
Then
exitloop X
end);
If .RDB neq -1
Then
begin
MAP$( .DB[BIASnodes]);
temp = ( 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
exitloop NDB
end);
MAP$( .DB[BIASresv]);
If .temp neq -1
Then
RDB[NODElnk] = .temp
Else
RDB[NODElnk] = 0;
RDB[NODErem] = .CCB[C_PRM1];
RDB[CHANNEL] = .CCB[C_LIX];
RDB[L_rem_addr] = .DB[L_SRCADDR];
RDB[H_rem_addr] = .DB[H_SRCADDR];
Selectone .DB[MSGFLG] of
Set
[FLG_CI]:
begin
RDB[MSGtyp] = N_RES;
RDB[ADDRloc] = 0;
If .RDB[NODElnk] neq 0
Then
begin
local NDB :ref block field(NODE_fields);
NDB = .RDB[NODElnk];
MAP$( .DB[BIASnodes]);
NDB[NDc_rej] = .NDB[NDc_rej] + 1;
MAP$( .DB[BIASresv]);
end;
If CCB_HDR_GET( 0, temp, -1)
Then
begin
CALL$L( NR_BLD, .temp, .RDB);
RDB[MSGtyp] = MSG_NONE;
end
end;
[FLG_CC, FLG_DI, FLG_INT, FLG_REQ, FLG_NBEOM, FLG_BOM, FLG_EOM, FLG_BEOM]:
begin
RDB[MSGtyp] = N_LNK;
RDB[PID] = .DB[L_DSTADDR];
RDB[ADDran] = .DB[H_DSTADDR];
If CCB_HDR_GET( 0, temp, -1)
Then
begin
CALL$L(NL_BLD, .temp, .RDB);
RDB[MSGtyp] = MSG_NONE;
end
end
Tes;
end;
CCB[C_FNC] = FC_RCE;
LLCRS$( .CCB)
end;
routine RETURN_NODE_LIST ( CCB): =
!++
! FUNCTIONAL DESCRIPTION:
! Return list of known nodes.
!
! FORMAL PARAMETERS:
! CCB CCB address
!
! IMPLICIT INPUTS:
! DB Data base address
! PARBLK & NMPAR inputs, as pointed at by CCB.
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! Operation status code
!
! COMPLETION CODES:
! None
!
!
! SIDE EFFECTS:
! None
!--
begin
map
CCB: ref block field (C_NM_FIELDS);
bind NODE = .DB[ADDRnodes]: blockvector[ 0, ND_SIZE] field( NODE_fields);
local
STS,
BUF_PTR,
BUF_LEN,
NODEADDR;
BUF_PTR = .CCB [C_ADDR];
BUF_LEN = .CCB [C_CNT];
STS = NM$SUC;
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] neq 0
Then
begin
IF .BUF_LEN lss 3
Then
(sts = $NM$ERR_IMF;exitloop);
NODEADDR = .NDB[NDaddr];
MAP$( .CCB[C_BIAS]);
byt$short_string( NODEADDR, BUF_PTR);
ch$wchar_a( 0, BUF_PTR);
MAP$( .DB[BIASnodes]);
BUF_LEN = .BUF_LEN - 3;
end;
end;
CCB[C_CNT] = ch$diff( .BUF_PTR, .CCB[C_ADDR]);
return .STS
end;
routine SET_NODE_PARMS ( CCB): =
!++
! FUNCTIONAL DESCRIPTION:
! Perform setting of specified node parameter.
!
! FORMAL PARAMETERS:
! CCB CCB address
!
! IMPLICIT INPUTS:
! DB Data base address
! PARBLK & NMPAR inputs, as pointed at by CCB.
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! Operation status code
!
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
map CCB: ref block field (C_NM_FIELDS);
local
NIX,
BUF_PTR,
PARM_NUM,
TIMER;
bind
NMP = CCB [C_NM_NMPAR]: ref block field (NMX_NMPAR_FIELDS),
NMPAR = NMP [NMX_NMPAR_ENTITY];
BUF_PTR = .CCB [C_ADDR];
MAP$ (.CCB [C_BIAS]);
byt$string_short (BUF_PTR, PARM_NUM);
selectone .PARM_NUM of
set
[502]: ! Set node number
begin
If not .DB[NSPrunning]
Then
byt$string_short( BUF_PTR, DB[NSPself])
Else
return $NM$ERR_CWS
end;
[710]: ! Set max links
begin
return $NM$ERR_OPF
end;
[720]: ! Set local delay factor
begin
DB[NSPdelay] = ch$rchar( .BUF_PTR);
end;
[721]: ! Set local delay weight
begin
DB[NSPweight] = ch$rchar( .BUF_PTR);
end;
[722]: ! Set inactivity timer
begin
byt$string_short( BUF_PTR, DB[NSPact_tim])
end;
[723]: ! Set retransmission threshold
begin
byt$string_short( BUF_PTR, DB[NSPretrans])
end;
[otherwise]:
return $NM$ERR_UPT
tes;
MAP$( .DB[BIASports]);
return NM$SUC
end;
routine SHOW_NODE_ITEMS ( CCB): =
!++
! FUNCTIONAL DESCRIPTION:
! Show specified items
!
! FORMAL PARAMETERS:
! CCB CCB address
!
! IMPLICIT INPUTS:
! PARBLK & NMPAR inputs, as pointed at by CCB.
! DB Data base address
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! Operation status code
!
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
map
CCB: ref block field (C_NM_FIELDS);
local
DAT_LST: ref vector,
PARM_NUM,
NDB: ref block field(NODE_fields),
HOLDIT,
STS;
bind
NMP = CCB [C_NM_NMPAR]: ref block field (NMX_NMPAR_FIELDS),
NMPAR = NMP [NMX_NMPAR_ENTITY];
NDB = .NMPAR;
DAT_LST = (selectone .CCB [C_NM_SELECT] of
set
[NMX$SEL_cha]:
begin
if .NMPAR eql .DB[NSPself]
then
plit (700, 710, 720, 721, 722, 723)
else
plit( -1)
end;
[NMX$SEL_sum, NMX$SEL_sta]:
plit (600, 601);
[otherwise]:
plit (-1);
tes);
IF .CCB [C_NM_SELECT] eql NMX$sel_cou
Then
begin
STS = SHOW_NODE_COUNTERS( .CCB );
return .STS
end;
$NM_RESPONSE_BEGIN( .CCB);
incr I from 0 to .DAT_LST [-1]-1 do
selectone .DAT_LST [.I] of
set
[-1]: CCB[C_STS] = NM$SUC;
[600]: ! Active Links to remote
begin
If .NDB eql .DB[NSPself]
Then
begin
PARAMETER_DU_2( 600, DB[NSPmax]);
exitloop
end;
If not FIND_NDB( NDB)
Then
begin
CCB[C_CNT] = 0;
return NM$SUC
end
Else
begin
PARAMETER_DU_2( 600, NDB[NDACTIVE]);
end;
end;
[601]: ! Node Delay
begin
PARAMETER_DU_2( 601, NDB[NDdelay]);
end;
[700]: ! NSP Version
begin
bind ralph = uplit(3,2,0): vector;
PARAMETER_CM( 700, 3);
PARAMETER_DU_1( ,ralph[0]);
PARAMETER_DU_1( ,ralph[1]);
PARAMETER_DU_1( ,ralph[2]);
end;
[710]: ! Max Links
begin
PARAMETER_DU_2( 710, DB[NSPtotal]);
end;
[720]: ! NSP Delay
begin
PARAMETER_DU_1( 720, DB[NSPdelay]);
end;
[721]: ! NSP Weight
begin
PARAMETER_DU_1( 721, DB[NSPweight]);
end;
[722]: ! NSP Inactivity
begin
PARAMETER_DU_2( 722, DB[NSPact_tim]);
end;
[723]: ! NSP Retransmit
begin
PARAMETER_DU_2( 723, DB[NSPretrans]);
end;
Tes;
$NM_RESPONSE_END( .CCB);
return .CCB[C_STS]
end;
Routine SHOW_NODE_COUNTERS ( CCB): =
!++
! FUNCTIONAL DESCRIPTION:
! Show specified items
!
! FORMAL PARAMETERS:
! CCB CCB address
!
! IMPLICIT INPUTS:
! DB Data base address
! PARBLK & NMPAR inputs, as pointed at by CCB.
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! Operation status code
!
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
map
CCB: ref block field (C_NM_FIELDS);
bind
NMP = CCB [C_NM_NMPAR]: ref block field (NMX_NMPAR_FIELDS),
NMPAR = NMP [NMX_NMPAR_ENTITY];
local
NDB: ref block field(NODE_fields);
$NM_RESPONSE_BEGIN( .CCB);
NDB = .NMPAR;
If FIND_NDB( NDB)
Then
begin
COUNTER_16_TIME( 0, NDB[NDtime_zeroed]);
COUNTER_32( 600, NDB[NDb_rcv]);
COUNTER_32( 601, NDB[NDb_xmt]);
COUNTER_32( 610, NDB[NDm_rcv]);
COUNTER_32( 611, NDB[NDm_xmt]);
COUNTER_16( 620, NDB[NDc_rcv]);
COUNTER_16( 621, NDB[NDc_xmt]);
COUNTER_16( 630, NDB[NDtimeout]);
COUNTER_16( 640, NDB[NDc_rej]);
If .NDB[NDaddr] eql .DB[NSPself]
Then
COUNTER_16( 700, DB[NSPmax]);
end;
$NM_RESPONSE_END( .CCB);
return .CCB[C_STS]
end;
Routine SHOW_ZERO_NODE_COUNTERS ( CCB): =
!++
! FUNCTIONAL DESCRIPTION:
! Show specified items
!
! FORMAL PARAMETERS:
! CCB CCB address
!
! IMPLICIT INPUTS:
! DB Data base address
! PARBLK & NMPAR inputs, as pointed at by CCB.
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! Operation status code
!
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
local
STS;
STS = SHOW_NODE_COUNTERS( .CCB);
if .sts neq NM$SUC then return .STS;
STS = ZERO_NODE_COUNTERS( .CCB);
return .STS
end;
Routine ZERO_NODE_COUNTERS ( CCB): =
!++
! FUNCTIONAL DESCRIPTION:
! Zero out node counters for a perticular node.
!
! FORMAL PARAMETERS:
! CCB CCB address
!
! IMPLICIT INPUTS:
! DB Data base address
! PARBLK & NMPAR inputs, as pointed at by CCB.
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! Operation status code
!
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
map
CCB: ref block field (C_NM_FIELDS);
bind
NMP = CCB [C_NM_NMPAR]: ref block field (NMX_NMPAR_FIELDS),
NMPAR = NMP [NMX_NMPAR_ENTITY];
local
NDB: ref block field(NODE_fields),
DAT_LST: ref vector;
NDB = .NMPAR;
If not FIND_NDB( NDB)
Then
return NM$SUC;
ch$fill( 0, 24, byt$ptr( NDB[NDb_rcv]));
$NM_TIME( NDB[NDtime_zeroed]);
If .NDB[NDaddr] eql .DB[NSPself]
Then
DB[NSPmax] = 0;
NM$SUC
end;
routine UPDATE_DELAY ( PDB) : novalue = !
!++
! FUNCTIONAL DESCRIPTION:
! This routine calculates the round trip delay for NSp messages.
!
! 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
DELAYtime,
NDB : ref block field(NODE_fields);
NDB = .PDB[NODElnk];
If .PDB[DELAYstr_tim] neq 0
Then
begin
DELAYtime = .PDB[DELAYstr_tim];
If .DELAYtime gtr 1
Then
DELAYtime = .DELAYtime - 1;
MAP$( .DB[BIASnodes]);
If .NDB[NDdelay] eql 0
Then
NDB[NDdelay] = .DELAYtime
Else
begin
DELAYtime = .DELAYtime - .NDB[NDdelay];
NDB[NDdelay] = .NDB[NDdelay] + (.DELAYtime / (.DB[NSPweight] + 1))
end;
MAP$( .DB[BIASports]);
PDB[DELAYstr_tim] = 0;
end
end;
routine XPT_XMIT ( CCB, XXDB) : novalue = !
!++
! FUNCTIONAL DESCRIPTION:
! This routine passes packets to Transport for delivery to a remote
! NSP.
!
!
! FORMAL PARAMETERS:
! CCB = CCB address
! XXDB = Reserved/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 XXDB: ref block field(PORT_fields);
local
NDB: ref block field(NODE_fields),
temp;
NDB = .XXDB[NODElnk];
If .XXDB[PORTstate] lss 0
Then
CCB[C_PRM4] = -1
Else
CCB[C_PRM4] = .XXDB;
CCB[C_FNC] = FC_XME;
CCB[C_MOD] = FM_DAT;
CCB[C_LIX] = .XXDB[CHANNEL];
CCB[C_PIX] = .DB[NSPxpt_pix];
CCB[C_STS] = 0;
CCB[C_PRM1] = .DB[NSPself];
CCB[C_PRM2] = .XXDB[NODErem];
If .NDB neq 0
Then
begin
SMAP$( temp);
MAP$( .DB[BIASnodes]);
DADD( NDB[NDm_xmt], 1);
MAP$( .temp);
end;
LLCRS$( .CCB)
end;
end
eludom