Trailing-Edge
-
PDP-10 Archives
-
TOPS-20_V6.1_DECnetSrc_7-23-85
-
mcb/xpt/tlilin.bli
There is 1 other file named tlilin.bli in the archive. Click here to see a list.
module TLILIN (
IDENT = 'X01650'
) =
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: Transport
!
! ABSTRACT:
!
! Line Support module for Transport Line Interface: handles all
! changes in circuit state, brings circuit up and down.
!
! ENVIRONMENT: MCB
!
! AUTHOR: L. Webber , CREATION DATE: 23-Jul-79
!
! MODIFIED BY:
!
! L. Webber, 23-Jul-79 : VERSION 01
!
! 1.01 26-Oct-79, L. Webber
! Modified to allocate all its own buffers
!
! 1.02 19-Dec-79, L. Webber
! Modifications to break out Transport Line Interface into its
! own process
!
! 1.03 3-Jan-80, L. Webber
! Remove the OT state
!
! 1.04 2-Apr-80, L. Webber
! Modify to support node and line sub-data-bases
!
! 1.05 16-May-80, L. Webber
! Convert LIX to/from line index
!
! 1.06 30-Jun-80, L. Webber
! Modify to use MCBLIB macros
!
! 1.07 A. Peckham, 15-Oct-80
! Update to use new function modifiers.
!
! 1.08 L. Webber, 20-Nov-80
! Put in DTE detection for TOPS-20 adjacent nodes.
!
! 1.09 L. Webber, 11-Dec-80
! Modify to support MCB 3.1
!
! 1.10 L. Webber, 12-Jan-80
! Make INI_LIN and TERM_LIN linkages CALL$; return Network
! Management codes for the two functions.
!
! 1.11 L. Webber, 27-Feb-81
! Fix bug in TI processing: if a bad message is received, return
! the message to the DLL.
!
! 1.12 L. Webber, 17-Mar-81
! Make all fetch references to LINEstate UNSAFE, so that they
! always cause the data base to be re-referenced.
!
! 1.13 L. Webber, 26-Mar-81
! Put Phase II DLL block size into Node Init; make segment size the
! same.
!
! 1.14 L. Webber, 27-Mar-81
! Add reason code to event logging data
!
! 1.15 L. Webber, 1-Apr-81
! Fix LINE_FAIL linkage to include modifier; this is only necessary
! to humor the Test Bed, and adds no code.
!
! 1.16 L. Webber, 1-Apr-81
! Fix so that RCV_TI and RCV_OTI reject initialization on remote
! blksize LARGER than local, not smaller.
!
! 1.17 L. Webber, 6-Apr-81
! Add code for initialization timer.
!
! 1.18 L. Webber, 10-Apr-81
! Release node ID block on line down (for Phase II nodes).
!
! 1.19 L. Webber, 13-Apr-81
! Fix mapping bug in RCV_OTI
!
! 1.20 L. Webber, 1-May-81
! Fix LINTIM to put LIX into CCB gotten and dispatched.
!
! 1.21 L. Webber, 27-May-81
! Modify to support the new DLL Interface. This is a major modification.
! Some of the changes involved are:
!
! o The $DLL_REQUEST_CIRCUIT and $DLL_RELEASE_CIRCUIT functions to
! the DLL have been introduced. These functions are queued functions
! (they use CCBs).
! o "Start" and "stop" have been replaced by $DLL_INITIALIZE and
! $DLL_STOP. These functions are queued functions.
! o Because it is not necessary to stop a running circuit before doing
! a $DLL_INITIALIZE, the DP state has been eliminated.
! o TLI now monitors the DLL circuit state by means of state change AST
! CCBs from the DLL. These state changes trigger many of the
! Transport line events once triggered by CCB completions.
! o The circuit identification over the DLL Interface has been simpli-
! fied. The circuit is always identified to the DLL by "provider
! PIX"; this quantity is set in LINEindex by the Network Management
! code prior to TLI being invoked. The Transport identification for
! the circuit, the index of the circuit's entry in the line data base,
! is passed to the DLL by $DLL_REQUEST_CIRCUIT and to Network Manage-
! ment by the Transport Network Management code; any subsequent calls
! to Transport about the circuit uses the Transport ID. LIXxlate has
! been eliminated. The index of a circuit's data base entry may be
! found in the LINEnumber field in the entry.
!
! 1.22 L. Webber, 27-May-81
! Fix LINEDN so that a running line that goes down loses its node type
! immediately.
!
! 1.23 L. Webber, 28-May-81
! Put a canned password in the send OTV code.
!
! 1.24 L. Webber, 1-Jun-81
! Modify all LOG_EVENT calls to pass the NMXid.
!
! 1.25 L. Webber, 3-Jun-81
! Zero out link field when CCB_CMP removes a CCB from LINEccb.
!
! 1.26 L. Webber, 19-Jun-81
! When a REQUEST_CIRCUIT completes, do a LINE_EVENT with the returned
! status.
!
! 1.27 L. Webber, 22-Jun-81
! Fix bug in REQ_COMPLETE which was saving the returned CCB in LINEevent
! without noticing there was already one there.
!
! 1.28 L. Webber, 22-Jun-81
! Change all $DLRCE's to straight $MCB_SCHEDULE_CCB's
!
! 1.29 L. Webber, 30-Jun-81
! Fix REQUEST_CIRCUIT to get the provider PIX out of the line data base,
! not the function CCB.
!
! 1.30 L. Webber, 23-Jul-81
! Fix LINE_EVENT and REQUEST_CIRCUIT to distinguish whether the circuit
! is ON or OFF.
!
! 1.31 L. Webber, 3-Aug-81
! Fix resource retry for FUNCreini to bring the line down if it is
! running.
!
! 1.32 L. Webber, 5-Aug-81
! Fix LINE_EVENT so that two successive RUNNING state notifications
! won't cause a SIGNAL_STOP.
!
! 1.33 L. Webber, 12-Aug-81
! Finish up fix 1.32; a RUNNING can even occur in DT state.
!
! 1.34 L. Webber, 12-Aug-81
! Fix LINE_EVENT so that it logs events on transient/persistent errors
! UNLESS it's an entry to MOP, not IF.
!
! 1.35 L. Webber, 19-Aug-81
! Fix LINE_EVENT so that a state transition to SYNCHRONIZING or RUNNING
! causes a $DLL_STOP to be (re-)issued.
!
! 1.36 L. Webber, 20-Aug-81
! Fix LINE_EVENT not to change the line state on a transient error, but
! to wait for the DLL state change notification.
!
! 1.37 L. Webber, 20-Aug-81
! Fix SEND_TV to put in the (null) function value.
!
! 1.38 L. Webber, 8-Sep-81
! Fix REQ_COMPLETE not to initialize the circuit unless Network
! Management has set it ON.
!
! 1.39 L. Webber, 10-Sep-81
! Fix INI_LIN always to set the circuit state to DS when it wants to
! initialize the circuit, even if it can't get the buffer to do the
! initialization. This allows the circuit to be brought up with only
! one buffer.
!
! 1.40 L. Webber, 11-Sep-81
! Create the macro SAVSDB, which normally would just put a buffer
! address into LINEevent. Currently, because of scarceness of buffers,
! it releases the buffer.
!
! 1.41 L. Webber, 15-Sep-81
! Fix RCV_OTI so that it doesn't clear LINEevent when LINEevent contains
! a restart code.
!
! 1.42 A. Peckham, 21-Sep-81
! Change transient and persistent error response strategy in LINE_EVENT.
!
! 1.43 L. Webber, 24-Sep-81
! Modify event logging to use new macros for building the event buffer.
!
! 1.44 L. Webber, 2-Oct-81
! Fix transient error processing so that, when it reinitializes the
! circuit, it sets the state to DS.
!
! 1.45 A. Peckham, 6-Oct-81
! Only re-initialize line on WARNING status codes in LINE_EVENT.
!
! 1.46 L. Webber, 20-Oct-81
! Add a "Reset" line flag to communicate to Decision that a circuit being
! taken down had a Phase II node adjacent. This is because it is
! necessary to zero out the node type immediately.
!
! 1.47 L. Webber, 28-Oct-81
! Fix the transient/permanent error processing to declare a running
! circuit down instead of just restarting it.
!
! 1.48 L. Webber, 29-Oct-81
! Add code to "pause" a circuit for a few seconds after bringing it
! down, before bringing it back up or closing it down for good.
!
! 1.49 L. Webber, 4-Nov-81
! Fix dot bug in 1.48.
!
! 1.50 L. Webber, 5-Nov-81
! Take out 1.48; it didn't help anything.
!
! 1.51 L. Webber, 4-Jan-82
! Release the CTL/STP CCB when it comes back from the provider in
! REL_CMP.
! Zero out FNC/MOD in CCB GETCCB gets (for debugging).
!
! 1.52 L. Webber, 12-Jan-82
! Fix a dot bug in RCV_TV.
!
! 1.53 L. Webber, 12-Mar-82
! Fix RCV_TI to get a CCB to declare the circut up, rather than waiting
! for the TI transmit to complete (it may already have done so).
!
! 1.54 L. Webber, 22-Mar-82
! Add support for the Ph2Circuit circuit type. This circuit will only
! talk to Phase II nodes.
!
! 1.55 A. Peckham, 19-Apr-82
! Eliminate references to LOG_EVENT, GETLINE.
! Work on INILIN to count down its own timers.
!
! 1.56 A. Peckham, 6-May-82
! Eliminate references to RLS_BLK, GET_BLK.
!
! 1.57 A. Peckham, 2-Jul-82
! Rework line handling.
! Add false node-init code, but do not enable.
!
! 1.58 A. Peckham, 6-Jul-82
! Utilize new XPT data base for initialization passwords.
!
! 1.59 A. Peckham, 8-Jul-82
! Start initialization clock after TI is transmitted, instead of
! DLL_RUNNING transition. More work on password data base.
! Rename RCV_OTI to RCV_NI.
!
! 1.60 A. Peckham, 23-Aug-82
! Fix bug in RCV_NI which caused the DN20 to recognize only KLs
! with even node numbers. On the node number, bit 0 instead of bit 7
! was being tested for the node number extension.
!
! 1.61 A. Peckham, 10-Sep-82
! Add mechanism for getting initial circuit cost from DLL layer:
! LINRVR: Zero out C_PRM1 before sending $DLL_REQUEST_CIRCUIT.
! CCPSTR: If Lcv is zero, move C_PRM1 to Lcv, and if that is zero,
! set it to one.
!
! 1.62 A. Peckham, 13-Sep-82
! Maintain Block_size in RCV_NI and RCV_TI.
!
! 1.63 A. Peckham, 4-Oct-82
! Do not check user-ECO field of TI message in RCV_TI.
!
! 1.64 A. Peckham, 5-Dec-82
! Acomodate RSX bug in RCV_TI by not verifying full TI length.
!
! 1.65 D. Brannon, 22-Sep-83
! Correct the Data Link blocksize check for the TI message
! in RCV_TI.
!
!--
!
! INCLUDE FILES:
!
require 'XPTMAC';
!
! TABLE OF CONTENTS
!
%if %bliss(bliss16)
%then linkage TLI_LKG_LINEb_CCB = jsr (register = 5, register = 4),
TLI_LKG_LINEb_FNC = jsr (register = 5, register = 0);
%else macro TLI_LKG_LINEb_CCB = bliss36c %,
TLI_LKG_LINEb_FNC = bliss36c %;
%fi
forward routine
BAD_MSG: LINKAGE_DB_CCB novalue,
CCB_CMP: LINKAGE_DB novalue,
CCPSTP: MCB_DB_CCB novalue,
CCPSTR: MCB_DB_CCB novalue,
CIRCUIT_DOWN: LINKAGE_DB novalue,
CIRCUIT_STATE: LINKAGE_DB_CCB novalue,
CIRCUIT_UP: LINKAGE_DB novalue,
CKTOFF: LINKAGE_DB_CCB novalue,
CKTON: LINKAGE_DB_CCB novalue,
GET_FALSE_NI: LINKAGE_DB_CCB novalue,
GET_PWDb,
INI_LIN: CALL$ novalue,
LD_CMP: MCB_DB_CCB novalue,
LINRVR: LINKAGE_DB novalue,
LOG_PACKET_HEADER: LINKAGE_DB_CCB novalue,
LU_CMP: MCB_DB_CCB novalue,
NEW_FUNCTION: TLI_LKG_LINEb_FNC novalue,
NEW_STATE: TLI_LKG_LINEb_FNC novalue,
NEXT_ACTION: LINKAGE_DB novalue,
NEXT_STATE: TLI_LKG_LINEb_FNC novalue,
RCV_HLO: LINKAGE_DB_CCB novalue,
RCV_NI: LINKAGE_DB_CCB novalue,
RCV_NV: LINKAGE_DB_CCB novalue,
RCV_TI: LINKAGE_DB_CCB novalue,
RCV_TV: LINKAGE_DB_CCB novalue,
TERM_LIN: CALL$ novalue,
TLIAST: LINKAGE_DB_CCB_MOD novalue,
XCPDAT: MCB_DB_CCB novalue,
XCPINI: MCB_DB_CCB novalue,
XCPSTP: MCB_DB_CCB novalue;
!
! MACROS:
!
macro RAD50(NAME) =
%IF %BLISS(BLISS16) %THEN %rad50_11
%ELSE %IF %BLISS(BLISS36) %THEN %rad50_10
%FI %FI
%string(NAME) %;
!
! EQUATED SYMBOLS:
!
!
! OWN STORAGE:
!
!
! EXTERNAL REFERENCES:
!
global routine BAD_MSG (LINEb,CCB,CODE): LINKAGE_DB_CCB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! Processes an invalid message. In any part of the initialization
! sequence where the DLL has been started, this event will cause the
! initialization sequence to be restarted (or started from the RU state).
! In the rest of the initialization sequence and all of the termination
! sequence, the event is ignored.
!
! FORMAL PARAMETERS
!
! LINEb Address of data base entry for the circuit over which the
! bad message was received
!
! CCB CCB pointing to bad message. This parameter is
! meaningful for reason codes 1-8.
!
! CODE Reason message is bad:
!
! 0 None of this routine's business
! 1 Unexpected TI or TV when circuit is up
! 2 Unexpected message during initialization
! 3 Version skew
! 4 Out-of-range or invalid node ID
! 5 Invalid remote blocksize
! 6 Invalid verification seed in TI
! 7 Format error
! 8 Verification reject
! 9 Resource failure during initialization
!
! IMPLICIT INPUTS
!
! LINEstate
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
! May commence or restart initialization.
!
!--
begin
map CCB: ref block field(C_XPT_fields);
require 'XPTSYM';
bind REASON = uplit(! DNA "reason" CODE parameter
0, ! 0
2, ! 1
2, ! 2
6, ! 3
7, ! 4
8, ! 5
9, ! 6
2, ! 7
0, ! 8
0): ! 9
vector;
local PTR,RET;
if .CODE eql 0 then return;
PTR = .CCB[C_ADDR];
!
! Log an event
!
$NM_LOG_BEGIN();
case .CODE from 1 to 9 of ! Fill event buffer and determine code
set
[1]: begin ! Unexpected TI or TV, running circuit:
RET = 4^6+$XPT$E_LSF;
COUNTER_INCREMENT(LINEb,XPTlinedn); ! increment circuit failure counter
LOG_PACKET_HEADER(.LINEb,.CCB); ! move packet hdr into event buffer
PARAMETER_C_1(5,REASON[.CODE]); ! log the reason code
end;
[2]: begin ! Unexpected message while initializing
RET = 4^6+$XPT$E_ISF;
COUNTER_INCREMENT(LINEb,XPTini_fail);! increment init. failure counter
LOG_PACKET_HEADER(.LINEb,.CCB); ! move packet hdr into event buffer
PARAMETER_C_1(5,REASON[.CODE]); ! log the reason code
end;
[3 to 6]: begin ! Version skew, out-of-range/invalid
local VALUE; ! node ID, invalid remote blocksize,
pointer P; ! or invalid verification seed:
P = ch$plus(.PTR,6); !
RET = 4^6+$XPT$E_IOF;
COUNTER_INCREMENT(LINEb,XPTini_fail);! increment init. failure counter,
LOG_PACKET_HEADER(.LINEb,.CCB); ! move packet hdr into event buffer
if .CODE eql 3 then begin ! packet header
PARAMETER_CM(6,3); ! and the version
VALUE = getb(P); ! (if needed)
PARAMETER_DU_1(,VALUE); !
VALUE = getb(P);
PARAMETER_DU_1(,VALUE);
VALUE = getb(P);
PARAMETER_DU_1(,VALUE);
end;
PARAMETER_C_1(5,REASON[.CODE]); ! log the reason code
end;
[7]: begin ! Format error:
RET = 4^6+$XPT$E_FMT;
COUNTER_INCREMENT(XPTDB,XPTfmt_loss);! increment format loss counter
LOG_PACKET_HEADER(.LINEb,.CCB); ! move packet hdr into event buffer
PARAMETER_C_1(5,REASON[.CODE]); ! log the reason code
end;
[8]: begin ! Verification reject:
local VALUE;
pointer P;
P = ch$plus(.PTR,1);
RET = 4^6+$XPT$E_VER;
COUNTER_INCREMENT(XPTDB,XPTver_rej);! increment verification counter
PARAMETER_CM(3,1); ! and move in
VALUE = getw(P); ! the source
PARAMETER_DU_2(,VALUE); ! node address
end;
[9]: begin ! Resource failure while initializing:
RET = 4^6+$XPT$E_ISF;
COUNTER_INCREMENT(LINEb,XPTini_fail);! increment init. failure counter
PARAMETER_C_1(5,REASON[.CODE]); ! log the reason code
end;
[outrange]: ;
tes;
$NM_LOG_END(.RET,.NMXid); ! Log the event
CALL$L(INI_LIN,.LINEb); ! Re-initialize the line
end; !End of BAD_MSG
routine CCB_CMP (LINEb): LINKAGE_DB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! Terminates all pending function CCBs for a circuit with "success".
!
! FORMAL PARAMETERS
!
! LINEb Address of the line data base entry whose function CCB
! queue is to be cleared out.
!
! IMPLICIT INPUTS
!
! LINEccb
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
! NONE.
!
!--
begin
require 'XPTSYM';
while true do
begin
local CCB: ref block field (C_XPT_fields);
if (CCB = .LINEccb) eqla 0 then exitloop; ! If there is a CCB,
LINEccb = .CCB[C_LNK]; ! then de-link it,
CCB[C_FNC] = FC_CCP; ! terminate the CCB
CCB[C_STS] = NM$SUC; ! with a "success" code;
$MCB_SCHEDULE_CCB(.CCB);
end;
end; !End of CCB_CMP
global routine CCPSTR (LINEb,CCB): MCB_DB_CCB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! This is a REQUEST complete.
!
! FORMAL PARAMETERS
!
! CCB Function CCB
!
! IMPLICIT INPUTS
!
! LINEstate
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
!--
begin
map CCB: ref block field(C_fields);
require 'XPTSYM';
LINEfunction = 0;
!
! Get the initial line cost if necessary.
!
if .Lcv eql 0
then if (Lcv = .CCB[C_PRM1]) eql 0
then Lcv = .Lcv + 1;
!
! Set the Transport circuit state, depending on whether the circuit
! is ON or OFF.
!
if .NMstate eql ON
then NEW_STATE (.LINEb, DS);
!
! Simulate a line state change event
!
CIRCUIT_STATE(.LINEb,.CCB);
$MCB_RETURN_CCB (.CCB);
CCB_CMP(.LINEb); ! Clear out circuit's function queue
NEXT_ACTION (.LINEb);
end; ! End of CCPSTR
global routine CCPSTP (LINEb,CCB): MCB_DB_CCB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! This is a RELEASE complete.
!
! FORMAL PARAMETERS
!
! CCB Function CCB
!
! IMPLICIT INPUTS
!
! LINEstate
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
!--
begin
map CCB: ref block field(C_fields);
require 'XPTSYM';
LINEfunction = 0;
DLLstate = DLL_FREE; ! We are no longer using this circuit
Freeing = false; ! and complete freeing process
OWNED = false;
$MCB_RETURN_CCB(.CCB); ! Return the CCB
CCB_CMP(.LINEb); ! Post all function CCBs complete
NEXT_ACTION (.LINEb);
end; ! End of CCPSTP
routine CIRCUIT_DOWN (LINEb): LINKAGE_DB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS
!
! LINEb - line data base
!
! IMPLICIT INPUTS
!
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
! NONE.
!--
begin
require 'XPTSYM';
case .LINEstate from HA to RU of ! Actions are based
set ! circuit states:
[RU,TC]: ! Running -
NEW_STATE (.LINEb, LR);
[DT]: ! Terminate
NEXT_STATE (.LINEb, OFF);
[TI,TV]: ! Handshaking -
NEW_STATE (.LINEb, DS);
[inrange]:
; ! Otherwise - do nothing
tes;
end; !End of CIRCUIT_DOWN
routine CIRCUIT_STATE (LINEb,CCB): LINKAGE_DB_CCB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS
!
! LINEb - line data base
! CCB - CCB containing the state notification
!
! IMPLICIT INPUTS
!
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
! NONE.
!--
begin
map CCB: ref block field (C_XPT_fields);
require 'XPTSYM';
selectone .CCB[C_STS] of
set
!
! Transition to OFF (or MAINTENANCE, which is equivalent to Transport)
!
[DLL$_STATE_OFF]:
begin
DLLstate = DLL_OFF;
CIRCUIT_DOWN(.LINEb);
end;
[DLL$_STATE_MAINTENANCE]:
begin
DLLstate = DLL_MAINTENANCE;
CIRCUIT_DOWN(.LINEb);
end;
[DLL$_STATE_SYNCHRONIZING]:
begin
local CB: ref block field (C_XPT_fields);
DLLstate = DLL_SYNCHRONIZING;
end;
[DLL$_STATE_RUNNING]:
begin
DLLstate = DLL_RUNNING;
CIRCUIT_UP(.LINEb);
end;
tes;
end; !End of CIRCUIT_STATE
routine CIRCUIT_UP (LINEb): LINKAGE_DB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS
!
! LINEb - line data base
!
! IMPLICIT INPUTS
!
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
! NONE.
!--
begin
require 'XPTSYM';
local CB: ref block field (C_XPT_FIELDS);
if .LINEstate eql DS
then NEXT_STATE (.LINEb, TI);
end; !End of CIRCUIT_UP
global routine CKTOFF (LINEb, CCB): LINKAGE_DB_CCB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! Releases a circuit to the DLL.
!
! FORMAL PARAMETERS
!
! CCB Function CCB
!
! CCB[C_LIN] Index of data base entry for circuit
! CCB[C_PRM2] Provider PIX
!
! IMPLICIT INPUTS
!
! LINEccb
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
! NONE.
!
!--
begin
map CCB: ref block field (C_XPT_FIELDS);
require 'XPTSYM';
!
! Queue the function CCB into the data base
!
CCB[C_LNK] = .LINEccb;
LINEccb = .CCB;
Freeing = true; ! indicate we're freeing
!
! If the circuit needs to be brought down, start with that.
! Otherwise, get to the releasing.
!
if .LINEstate neq HA ! If not halted,
then NEW_STATE (.LINEb, DT) ! start it on the road to HA state.
else begin
LINEfunction = FUNCrelease;
NEXT_ACTION (.LINEb);
end;
end; !End of CKTOFF
global routine CKTON (LINEb, CCB): LINKAGE_DB_CCB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! Issues a request for a circuit to the DLL.
!
! FORMAL PARAMETERS
!
! CCB Function CCB
!
! CCB[C_LIN] Line number (index to data base entry)
! CCB[C_PRM2] Provider PIX
!
! IMPLICIT INPUTS
!
! LINEccb
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
! NONE.
!
!--
begin
map CCB: ref block field (C_XPT_FIELDS);
require 'XPTSYM';
!
! Queue the function CCB into the data base
!
CCB[C_LNK] = .LINEccb;
LINEccb = .CCB;
OWNED = true; ! Set state to "owned"
!
! Line will be halted.
! Start it on the road to RU state.
!
LINEfunction = FUNCrequest;
LINRVR(.LINEb);
end; !End of CKTON
routine GET_FALSE_NI (LINEb,CCB): LINKAGE_DB_CCB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! Constructs the False_NI_msg.
!
! FORMAL PARAMETERS
!
! LINEb - line data base
!
! IMPLICIT INPUTS
!
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
! NONE.
!
!--
begin
map CCB: ref block field (C_XPT_FIELDS);
require 'XPTSYM';
pointer PTR;
if ch$rchar (.CCB[C_ADDR]) eql OTI_CTLflg
then begin ! Copy and update NI.
PTR = .False_NI_msg_ADDR;
ch$move(.CCB[C_CNT],.CCB[C_ADDR],.PTR);
False_NI_msg_CNT = .CCB [C_CNT];
PTR = ch$plus(.PTR,2); ! Bypass MSGFLG and SUBFLG
do 0 while biton(getb(PTR),%o'200'); ! NODEADDR,
begin ! NODENAME
local TMP;
TMP = getb(PTR);
PTR = ch$plus(.PTR,.TMP);
end;
PTR = ch$plus(.PTR,1); ! SERVICES
if .Request_OTV
then ch$wchar((ch$rchar(.PTR) or 1),.PTR);
PTR = ch$plus(.PTR,1); ! REQUESTS
byt$short_string(PH2size,PTR); ! Put in the maximum blocksize
byt$short_string(PH2size,PTR); ! and the maximum segment size
putw($MAXlk,PTR); ! and the maximum number of links
end;
end; !End of GET_FALSE_NI
routine GET_PWDb (ADDR) =
!++
! FUNCTIONAL DESCRIPTION:
!
! Returns a password data base address for the given node.
!
! FORMAL PARAMETERS
!
! ADDR - Node address
!
! IMPLICIT INPUTS
!
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! Address of PWDb.
!
! SIDE EFFECTS:
!
! NONE.
!
!--
begin
require 'XPTSYM';
$TLI_for_each_PWDb_do_begin
if .PWDnode eql 0 then return .PWDb;
if .PWDnode eql .ADDR then return .PWDb;
$TLI_next_PWDb_end;
0 ! Never gets here
end; !End of GET_PWDb
global routine INI_LIN (LINEb_): CALL$ novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! Initializes a circuit, i.e., starts it up and transport-initializes it.
!
! FORMAL PARAMETERS
!
! LINEb - line data base
!
! IMPLICIT INPUTS
!
! LINEstate
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
! Changes circuit state. Declares circuit "down" if it is not already.
! Aborts a Terminate sequence.
! NOTE: This routine acquires a free CCB. If it is unable to do so, it
! will place the function requested in the LINEfunction entry for the
! circuit. Upon timeout, the function will be rescheduled.
!
!--
begin
local LINEb;
require 'XPTSYM';
LINEb = .LINEb_;
!
! Do initialization action depending on the circuit state
!
case .LINEstate from HA to RU of
set
[RU,TC,OFF]: ! If XPT possibly notified,
NEW_STATE (.LINEb, LR); ! then make sure line_down is done.
[HA,DT,TI,TV]: ! otherwise
NEW_STATE (.LINEb, DS); ! initialize line.
[inrange]:
; ! (already initializing)
tes;
end; !End of INI_LIN
global routine LD_CMP (LINEb,CCB): MCB_DB_CCB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! Processes "line down" completion
!
! FORMAL PARAMETERS
!
! CCB[C_LIN] - circuit that is now "down"
!
! IMPLICIT INPUTS
!
! LINEstate
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
! Changes circuit state. If in initialization sequence, starts
! DLL reinitialization of circuit. If in termination sequence,
! either returns SDB to pool or (if requested to release circuit)
! tell the DLL to release the circuit.
!
!--
begin
map CCB: ref block field (C_XPT_FIELDS);
require 'XPTSYM';
LINEfunction = 0;
$MCB_RETURN_CCB (.CCB);
case .LINEstate from HA to RU of
set
[LR]: ! Continuing initialization:
NEXT_STATE (.LINEb, DS);
[OFF]: ! Continuing termination:
NEXT_STATE (.LINEb, HA);
[inrange]:
NEXT_ACTION (.LINEb);
tes;
end; !End of LD_CMP
global routine LINRVR (LINEb): LINKAGE_DB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! Called by main Transport timer routine.
! This routine performs resource recovery.
!
! RESOURCE RECOVERY
!
! If a function code (distinguished from a SDB address by being only one
! byte in significance) is in LINEfunction for a circuit, the routine will
! attempt to get an SDB for the circuit. If it succeeds, the SDB will be
! passed to the routine if the routine takes a CCB, and returned otherwise.
! The routine to be retried will depend on the value of LINEfunction.
!
! FORMAL PARAMETERS
!
! NONE.
!
! IMPLICIT INPUTS
!
! LINEfunction
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
!
!--
begin
require 'XPTSYM';
if .LINEfunction leq 0 then return;
case .LINEfunction from FUNClo to FUNChi of
set
[FUNCrequest] :
begin
local CCB: ref block field (C_XPT_FIELDS);
if not $MCB_GET_CCB(CCB) then return;
CCB[C_PRM1] = 0;
CCB[C_HANDLE] = .DLLhandle; ! and DLL handle
$DLL_REQUEST_CIRCUIT(.CCB);
end;
[FUNCrelease]:
begin
local CCB: ref block field (C_XPT_FIELDS);
if not $MCB_GET_CCB(CCB) then return;
LINEstate = HA;
CCB[C_HANDLE] = .DLLhandle; ! and DLL handle
$DLL_RELEASE_CIRCUIT(.CCB);
end;
[FUNCinitialize]:
begin
local CCB: ref block field (C_XPT_FIELDS);
if not $MCB_GET_CCB(CCB) then return;
LINEstate = DS;
Ph2circuit = false;
CCB[C_HANDLE] = .DLLhandle; ! and DLL handle
$DLL_INITIALIZE(.CCB);
end;
[FUNCstop]:
begin
local CCB: ref block field (C_XPT_FIELDS);
if not $MCB_GET_CCB(CCB) then return;
LINEstate = DT;
CCB[C_HANDLE] = .DLLhandle; ! and DLL handle
$DLL_STOP(.CCB);
end;
[FUNC_TI]:
begin
local CCB: ref block field (C_XPT_FIELDS);
if not $MCB_GET_CCB(CCB) then return;
CCB[C_XPT_TYPE] = FUNC_TI;
CCB[C_BIAS] = 0;
if not (.Ph2only or .Ph2circuit)
then begin
CCB[C_ADDR] = .TI_msg_ADDR;
CCB[C_CNT] = .TI_msg_CNT;
end
else if .Intercept
then begin
CCB[C_ADDR] = .NI_msg_ADDR;
CCB[C_CNT] = .NI_msg_CNT;
end
else begin
CCB[C_ADDR] = .False_NI_msg_ADDR;
CCB[C_CNT] = .False_NI_msg_CNT;
end;
Send_TI = false;
CCB[C_HANDLE] = .DLLhandle; ! and DLL handle
$DLL_TRANSMIT(.CCB);
end;
[FUNC_TV]:
begin
local CCB: ref block field (C_XPT_FIELDS),
PWDb: ref PWDblock;
if not $MCB_GET_CCB(CCB) then return;
CCB[C_XPT_TYPE] = FUNC_TV;
PWDb = GET_PWDb (.Nid);
if not (.Ph2only or .Ph2circuit)
then begin
CCB[C_ADDR] = PWD3TVmsg_ptr;
CCB[C_CNT] = PWD3TVmsg_len;
end
else begin
CCB[C_ADDR] = PWD2TVmsg_ptr;
CCB[C_CNT] = PWD2TVmsg_len;
end;
Send_TV = false;
CCB[C_HANDLE] = .DLLhandle; ! and DLL handle
$DLL_TRANSMIT(.CCB);
end;
[FUNCline_up]:
begin
local CCB: ref block field (C_XPT_FIELDS);
if not $MCB_GET_CCB(CCB) then return;
XPTstate = ON;
LINEstate = TC;
CCB[C_HANDLE] = .XPThandle; ! and XPT handle
CCB[C_MOD] = TM_INI; ! "line up" CCB
CCB[C_FNC] = FC_RCP; ! and queue it
$MCB_SCHEDULE_CCB(.CCB); ! to Transport
end;
[FUNCline_down]:
begin
local CCB: ref block field (C_XPT_FIELDS);
if not $MCB_GET_CCB(CCB) then return;
XPTstate = OFF;
case .LINEstate_desired from HA to RU of
set
[LR,DS,TI,TV,TC,RU]: LINEstate = LR;
[DT,OFF,HA]: LINEstate = OFF;
tes;
if .Nty eql TOPS20
then begin ! TOPS20 node:
False_NI_LINEb = 0; ! no longer available
$XPT_for_each_LINEb_do_begin ! Stop all adjacent
if .Ph2circuit and not .Intercept ! aspiring
then CALL$L(TERM_LIN,.LINEb); ! Phase II nodes
$XPT_next_LINEb_end;
end;
Nty = 0; ! Zero out adjacent node type
CCB[C_HANDLE] = .XPThandle; ! and XPT handle
CCB[C_MOD] = TM_TRM; ! "line down" CCB
CCB[C_FNC] = FC_RCP; ! and queue it
$MCB_SCHEDULE_CCB(.CCB); ! to Transport
end;
tes;
LINEfunction = -.LINEfunction;
end; !End of LINRVR
routine LOG_PACKET_HEADER (LINEb,CCB): LINKAGE_DB_CCB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! Constructs the False_NI_msg.
!
! FORMAL PARAMETERS
!
! LINEb - line data base
!
! IMPLICIT INPUTS
!
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
! NONE.
!
!--
begin
map CCB: ref block field (C_XPT_FIELDS);
require 'XPTSYM';
local TMP;
pointer PTR;
PTR = .CCB[C_ADDR];
PARAMETER_CM(0,2); ! Multiple fields, 2
TMP=getb(PTR); ! Message type
PARAMETER_H_1(,TMP); ! Hex field, 1 byte: routing flags
TMP=getw(PTR); ! Decimal unsigned, 2 bytes:
PARAMETER_DU_2(,TMP); ! source node address
end; !End of LOG_PACKET_HEADER
global routine LU_CMP (LINEb,CCB): MCB_DB_CCB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! Processes a "line up" completion from Decision.
!
! FORMAL PARAMETERS
!
! CCB[C_LIN] - circuit that is now "up"
!
! IMPLICIT INPUTS
!
! LINEstate
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
! Changes circuit state. Returns parameter CCB to SDB pool.
!
!--
begin
map CCB: ref block field (C_XPT_fields);
require 'XPTSYM';
LINEfunction = 0;
$MCB_RETURN_CCB(.CCB);
if .LINEstate eql TC
then NEXT_STATE (.LINEb, RU)
else NEXT_ACTION (.LINEb);
end; !End of LU_CMP
routine NEW_FUNCTION (LINEb,FUNC): TLI_LKG_LINEb_FNC novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! Set up a new function and initiate it.
!
! FORMAL PARAMETERS
!
! LINEB address of the line data base
! FUNC the new function to initiate.
!
! IMPLICIT INPUTS
!
! None
!
! ROUTINE VALUE: TRUE/FALSE
! COMPLETION CODES:
!
! None
!
! SIDE EFFECTS:
! None
!--
begin
require 'XPTSYM';
LINEfunction = .FUNC;
LINRVR (.LINEb);
end; ! End of NEW_FUNCTION
routine NEW_STATE (LINEb,STATE): TLI_LKG_LINEb_FNC novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! Set the line on the way to the given new state
!
! FORMAL PARAMETERS
!
! LINEB address of the line data base
! STATE the desired new state.
!
! IMPLICIT INPUTS
!
! None
!
! ROUTINE VALUE: TRUE/FALSE
! COMPLETION CODES:
!
! None
!
! SIDE EFFECTS:
! None
!--
begin
require 'XPTSYM';
LINEstate_desired = .STATE;
if .LINEfunction geq 0
then LINEfunction = 0
else if .LINEfunction lss 0
then selectone .LINEfunction of
set
[-FUNC_TI,-FUNC_TV]:
LINEfunction = 0;
[otherwise]:
;
tes;
NEXT_ACTION (.LINEb);
end; ! End of NEW_STATE
routine NEXT_ACTION (LINEb): LINKAGE_DB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! Find the next action for the line.
!
! FORMAL PARAMETERS
!
! LINEB address of the line data base
!
! IMPLICIT INPUTS
!
! None
!
! ROUTINE VALUE: TRUE/FALSE
! COMPLETION CODES:
!
! None
!
! SIDE EFFECTS:
! None
!--
begin
require 'XPTSYM';
case .LINEstate_desired from HA to RU of
set
[HA]:
begin
Listen_clock = 0;
Send_TI = false;
Send_TV = false;
if .LINEfunction neq 0 then return;
if .LINEstate eql HA then return;
selectone .DLLstate of
set
[DLL_OFF,DLL_FREE]:
;
[otherwise]:
return NEW_FUNCTION (.LINEb, FUNCstop);
tes;
if .XPTstate eql ON
then return NEW_FUNCTION (.LINEb, FUNCline_down);
if .Freeing and (.DLLstate neq DLL_FREE)
then return NEW_FUNCTION (.LINEb, FUNCrelease);
LINEstate = .LINEstate_desired;
end;
[DT]:
begin
Listen_clock = 0;
Send_TI = false;
Send_TV = false;
if .LINEfunction neq 0 then return;
if .LINEstate eql DT then return;
return NEW_FUNCTION (.LINEb, FUNCstop);
end;
[OFF]:
begin
Listen_clock = 0;
Send_TI = false;
Send_TV = false;
if .LINEfunction neq 0 then return;
if .LINEstate eql OFF then return;
selectone .DLLstate of
set
[DLL_OFF,DLL_FREE]:
;
[otherwise]:
return NEW_FUNCTION (.LINEb, FUNCstop);
tes;
return NEW_FUNCTION (.LINEb, FUNCline_down);
end;
[LR]:
begin
Listen_clock = 0;
Send_TI = false;
Send_TV = false;
if .LINEfunction neq 0 then return;
if .LINEstate eql LR then return;
return NEW_FUNCTION (.LINEb, FUNCline_down);
end;
[DS]:
begin
Listen_clock = 0;
Send_TI = false;
Send_TV = false;
if .LINEfunction neq 0 then return;
if .LINEstate eql DS then return;
return NEW_FUNCTION (.LINEB, FUNCinitialize);
end;
[TI]: ! Line running; Waiting for TI
begin
if .DLLstate neq DLL_RUNNING then return;
If .LINEstate neq TI
then begin
LINEstate = TI;
Send_TI = true;
end;
if .LINEfunction neq 0 then return;
selectone true of
set
[.Send_TI]:
return NEW_FUNCTION (.LINEB, FUNC_TI);
[.Send_TV]:
return NEW_FUNCTION (.LINEB, FUNC_TV);
[otherwise]:
;
tes;
return;
end;
[TV]: ! TI received; waiting for TV
begin
if .DLLstate neq DLL_RUNNING then return;
if .Nty eql 0 then return;
LINEstate = TV;
if .LINEfunction neq 0 then return;
selectone true of
set
[.Send_TI]:
return NEW_FUNCTION (.LINEB, FUNC_TI);
[.Send_TV]:
return NEW_FUNCTION (.LINEB, FUNC_TV);
[otherwise]:
;
tes;
return;
end;
[TC]: ! TI(/TV) exchanged
begin
if .LINEfunction neq 0 then return;
if .DLLstate neq DLL_RUNNING then return;
selectone true of
set
[.Send_TI]:
return NEW_FUNCTION (.LINEB, FUNC_TI);
[.Send_TV]:
return NEW_FUNCTION (.LINEB, FUNC_TV);
[otherwise]:
;
tes;
if .Nty neq 0
then return NEW_FUNCTION (.LINEB, FUNCline_up);
return;
end;
[RU]:
begin
if .LINEfunction neq 0 then return;
if .DLLstate neq DLL_RUNNING then return;
if .XPTstate neq ON then return;
if .LINEstate eql RU then return;
Listen_clock = 0; ! Stop the initialization timer.
LINEstate = RU;
CCB_CMP(.LINEb); ! Clean out the function CCB queue
selectone .Nty of
set
[Full,Small]:
Listen_clock = .Listen_timer;
[TOPS20]:
begin
False_NI_LINEb = .LINEb;
$XPT_for_each_LINEb_do_begin ! Start up all adjacent
if .Ph2circuit and not .Intercept ! aspiring
then CALL$L(INI_LIN,.LINEb); ! Phase II nodes
$XPT_next_LINEb_end;
end;
[otherwise]:
;
tes;
return;
end;
tes;
end; ! End of NEXT_ACTION
routine NEXT_STATE (LINEb,STATE): TLI_LKG_LINEb_FNC novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! This is called on an automatic line state change. It only changes
! the desired state is not forcing a different state.
!
! FORMAL PARAMETERS
!
! LINEB address of the line data base
! STATE the desired new state.
!
! IMPLICIT INPUTS
!
! None
!
! ROUTINE VALUE: TRUE/FALSE
! COMPLETION CODES:
!
! None
!
! SIDE EFFECTS:
! None
!--
begin
require 'XPTSYM';
if .LINEstate_desired eql .LINEstate
then LINEstate_desired = .STATE;
NEXT_ACTION (.LINEb);
end; ! End of NEXT_STATE
global routine RCV_HLO (LINEb,CCB): LINKAGE_DB_CCB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS
!
! CCB[C_LIN] - Index of circuit data base entry
! CCB[C_BIAS] - buffer descriptor for the NI
!
! IMPLICIT INPUTS
!
! LINEstate
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
!
!--
begin
map CCB: ref block field(C_fields);
require 'XPTSYM';
label MSG_CHECK;
MSG_CHECK:
begin ! MSG_CHECK
local CNT;
pointer PTR;
! The message is already mapped.
PTR = ch$plus(.CCB[C_ADDR],1); ! Address buffer past HELLO flag
if (CNT = .CCB[C_CNT] - 4) lss 0 then leave MSG_CHECK;
!
! Validate the source node address.
!
if getw(PTR) neq .Nid
then begin ! Wrong source node:
$NM_LOG_BEGIN(); ! Build event buffer
LOG_PACKET_HEADER(.LINEb,.CCB); ! move packet hdr into event buffer
PARAMETER_CM(4,1); ! and expected
PARAMETER_DU_2(,Nid); ! node address
$NM_LOG_END(4^6+$XPT$E_LOF,.NMXid);
CALL$L(INI_LIN,.LINEb); ! signal the line should be killed
leave MSG_CHECK;
end;
!
! Validate the data
!
if .CNT neq getb(PTR) ! Extra or missing data bytes:
then begin ! fail
CALL$L(INI_LIN,.LINEb);
leave MSG_CHECK;
end;
if .CNT neq 0
then do begin
if getb(PTR) neq %o'252' ! wrong pattern:
then begin
$NM_LOG_BEGIN(); ! log the event
PARAMETER_C_1(5,uplit(11));
$NM_LOG_END(4^6+$XPT$E_LLF,.NMXid);
CALL$L(INI_LIN,.LINEb);
leave MSG_CHECK;
end;
end
while (CNT = .CNT - 1) neq 0;
end; ! MSG_CHECK
end; !End of RCV_HLO
global routine RCV_NI (LINEb,CCB): LINKAGE_DB_CCB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! Processes a received Node Init message (Phase II variety). If we are in
! the TI state (expecting a Transport Init), we will send a Node Init, a
! Node Verify if one is requested, and declare a "line up". (For sim-
! plicity, this implementation will never request verification from a Phase
! II node.) (The "line up" will be delayed until the transmit of the Trans-
! port Init and Transport Verify have completed.) The adjacent node type
! for the circuit will be set to "Phase II".
!
! FORMAL PARAMETERS
!
! CCB[C_LIN] - Index of circuit data base entry
! CCB[C_BIAS] - buffer descriptor for the NI
!
! IMPLICIT INPUTS
!
! LINEstate
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
! Will mark the node at the other end as Phase II and will perform
! special Phase II processing against it from now on (until the circuit
! goes down). May commence or restart an initialization sequence if
! we are in the wrong state.
!
!--
begin
map CCB: ref block field (C_fields);
require 'XPTSYM';
label MSG_CHECK,TI_CHECK;
local GOOD,NODEADDR,NAMEPTR,REQUESTS,BLKSIZE,RET;
MSG_CHECK:
begin ! MSG_CHECK
pointer PTR;
MAPBUF(.CCB,PTR);
!
! Validate the NI message; if it's no good, treat as a BAD_MSG
!
PTR = ch$plus(.PTR,2); ! Bypass MSGFLG and STARTTYPE
begin ! Get NODEADDR
if biton((NODEADDR = getb(PTR)),%o'200')
then begin
NODEADDR = .NODEADDR <0, 7>;
NODEADDR = .NODEADDR + getb(PTR)^7;
end;
end;
if .NODEADDR gtru NN
then begin
GOOD = 4; ! Source address too large
leave MSG_CHECK;
end;
begin
local LEN;
NAMEPTR = .PTR;
LEN = getb (PTR); ! Get node name length
selectone .LEN of
set
[1 to 6]:
begin
PTR = ch$plus(.PTR,.LEN); ! Bump pointer past name
end;
[otherwise]:
begin
GOOD = 7;
leave MSG_CHECK;
end;
tes;
end;
PTR = ch$plus(.PTR,1); ! Bypass FUNCTIONS
REQUESTS = getb(PTR); ! Save REQUESTS
BLKSIZE = getw(PTR); ! BLKSIZE
if .BLKSIZE gtru .PH2size ! BLKSIZE too large -
then begin
GOOD = 5; ! fail initialization
leave MSG_CHECK;
end;
%(
PTR = ch$plus(.PTR,2); ! NSPSIZE
PTR = ch$plus(.PTR,2); ! MAXLNKS
PTR = ch$plus(.PTR,3); ! ROUTVER
PTR = ch$plus(.PTR,3); ! COMMVER
begin
local LEN;
LEN = GETB(PTR);
PTR = ch$plus(.PTR,.LEN); ! SYSVER
end;
)%
GOOD = 0;
end; ! MSG_CHECK
!
! Dispatch on circuit state
!
case .LINEstate from HA to RU of
set
[TI]: ! This is the big case
TI_CHECK:
begin
MAP$(.CCB[C_BIAS]); ! Re-map the buffer
!
! Good Node Init - send Verification (if requested) and change state
!
if .GOOD eql 0
then begin
Ph2circuit = true;
if not .DTEcircuit ! Not DTE circuit -
then begin
if (not .Intercept) and
(.False_NI_LINEb eqla 0)
then begin
NEW_STATE (.LINEb, DT);
leave TI_CHECK;
end;
Nty = PhTwo; ! type is standard Phase II
end
else begin ! DTE circuit -
GET_FALSE_NI(.LINEb,.CCB); ! Save NI for later
Nty = TOPS20; ! Node type is TOPS-20
end;
Nid = .NODEADDR; ! Set node address,
Nnml = getb (NAMEPTR); ! name length,
ch$move (.Nnml,.NAMEPTR,byt$ptr(Nnm)); ! and name.
Block_size = .BLKSIZE; ! Block size.
if not .Ph2only ! If Phase II NI not sent yet,
then Send_TI = true; ! then set to send one.
if .REQUESTS<0,1> neq 0 ! If requested,
then Send_TV = true; ! set to send OTV.
if .Request_OTV
then NEXT_STATE (.LINEb, TV) ! Wait for TV.
else NEXT_STATE (.LINEb, TC); ! Request a line-up.
end;
end;
[RU]: ! Circuit running, message unexpected -
GOOD = 1; ! and treat as garbage message
[TV,TC]: ! Circuit initializing,
GOOD = 2; ! and treat as garbage message
[inrange]: ! In middle of DLL protocol -
GOOD = 0;
tes;
if .GOOD neq 0 ! If error, then
then BAD_MSG(.LINEb,.CCB,.GOOD); ! treat as garbage message
end; !End of RCV_NI
global routine RCV_NV (LINEb,CCB): LINKAGE_DB_CCB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! Processes a received Node Verification message. If we
! are expecting one, we will validate it and if valid, declare
! the circuit up. (If we have not received back the NI message we
! sent, the "line up" will be delayed until we do.)
!
! FORMAL PARAMETERS
!
! CCB[C_LIN] - Index of circuit data base entry
! CCB[C_BIAS] - buffer descriptor for OTV's buffer
!
! IMPLICIT INPUTS
!
! LINEstate
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
! May commence or restart an initialization sequence if we are in
! the wrong state.
!
!--
begin
map CCB: ref block field (C_fields);
require 'XPTSYM';
local GOOD;
label MSG_CHECK,TV_CHECK;
MSG_CHECK:
begin ! MSG_CHECK
local CNT;
pointer PTR;
MAPBUF(.CCB,PTR,CNT);
!
! Validate the NV message; if it's no good, treat as a BAD_MSG
!
CNT = .CNT - 10; ! Account for full message
if .CNT lss 0
then begin
GOOD = 7;
leave MSG_CHECK;
end;
GOOD = 0;
end; ! MSG_CHECK
!
! Dispatch on circuit state
!
case .LINEstate from HA to RU of
set
[TV]: ! This is the big case
TV_CHECK:
begin
local PWDb: ref PWDblock;
pointer PTR;
if .GOOD neq 0 then leave TV_CHECK;
PWDb = GET_PWDb (.Nid);
PTR = ch$plus (.CCB[C_ADDR],3);
if ch$rchar(byt$ptr (PWD2rcv)) neq 0
then if ch$neq (8, .PTR, 8, byt$ptr (PWD2rcv), 0)
then begin
GOOD = 8;
leave TV_CHECK;
end;
NEXT_STATE (.LINEb, TC);
end;
[RU]: ! Circuit running, message unexpected -
GOOD = 1; ! and treat as garbage message
[TI,TC]: ! Circuit initializing,
GOOD = 2; ! and treat as garbage message
[inrange]: ! In middle of DLL protocol -
GOOD = 0;
tes;
if .GOOD neq 0
then BAD_MSG(.LINEb,.CCB,.GOOD); ! Treat as garbage message
end; !End of RCV_NV
global routine RCV_TI (LINEb,CCB): LINKAGE_DB_CCB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! Processes a received Transport Init message. If we are expecting
! one, we will send a Transport Verify if one is requested and go either
! to receive a Transport Verify (if we asked for one) or to declare a "line
! up". (If we have not received back the TI message we sent, the "line up"
! will be delayed until we do.)
!
! FORMAL PARAMETERS
!
! CCB[C_LIN] - Index of circuit data base entry for circuit
! CCB[C_BIAS] - buffer descriptor for TI
!
! IMPLICIT INPUTS
!
! LINEstate
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
! May commence or restart an initialization sequence if we are in
! the wrong state.
!
!--
begin
map CCB: ref block field (C_fields);
require 'XPTSYM';
local GOOD,NODEADDR,TIINFO,BLKSIZE;
label MSG_CHECK;
!
! If the circuit is a Ph2Circuit, ignore the message
!
if .Ph2only then return;
MSG_CHECK:
begin ! MSG_CHECK
local CNT;
pointer PTR;
MAPBUF (.CCB,PTR,CNT);
!
! Validate the TI message; if it's no good, treat as a BAD_MSG
!
if (CNT = .CNT - 9) lss 0 then leave MSG_CHECK;
begin ! CTLFLG
local CTLFLG;
CTLFLG = getb(PTR);
if biton(.CTLFLG,%b'11110000') ! Check the control header
then begin
GOOD = 7; ! Reserved bits on - no good
leave MSG_CHECK;
end;
end;
if (NODEADDR = getw(PTR)) gtru NN ! SRCNODE
then begin
GOOD = 4; ! Source node address too large
leave MSG_CHECK;
end;
begin ! TIINFO
TIINFO = getb(PTR);
if biton(.TIINFO,%b'11111000')
then begin
GOOD = 7; ! Reserved bits on
leave MSG_CHECK;
end;
selectone .TIINFO<0,2,0> of
set
[2,3]:
0;
[otherwise]:
begin
GOOD = 7; ! Node type no good
leave MSG_CHECK;
end;
tes;
end;
BLKSIZE = getw(PTR);
!
! A received Data Link blocksize greater than or equal
! to the maximum (message size of routing message
! containing NN nodes, hello message size, 246)
!
if (.BLKSIZE lssu (NN^1 + 5)) or
(.BLKSIZE lssu (3+.HELLO_MSG_CNT)) or
(.BLKSIZE lssu 246)
then begin
GOOD = 5; ! Remote blocksize too large
leave MSG_CHECK;
end;
begin ! TIVER
if ((getb(PTR) neq 1) or
(getb(PTR) neq 3))
then begin
GOOD = 3; ! Incompatible version number
leave MSG_CHECK;
end;
getb(PTR);
end;
%(
if getb(PTR) neq 0 ! RESERVED
then begin
GOOD = 7;
end;
)%
GOOD = 0; ! Sorry, nothing wrong
end; ! MSG_CHECK
!
! Dispatch on circuit state
!
case .LINEstate from HA to RU of
set
[TI]: ! This is the big case
begin
!
! Now process message
!
if .GOOD eql 0
then begin
Nty = .TIINFO<0,2,0>; ! Set routing type.
Nid = .NODEADDR; ! Save adjacent node address
Nnml = 0; ! with no name.
Block_size = .BLKSIZE; ! This is his block size.
if biton(.TIINFO,VFY_req) ! and If requested,
then Send_TV = true; ! then schedule one sent.
if .Request_TV
then NEXT_STATE (.LINEb, TV) ! Wait for TV.
else NEXT_STATE (.LINEb, TC); ! Request a line-up.
end;
end;
[RU]: ! Circuit running, message unexpected -
GOOD = 1; ! and treat as garbage message
[TV,TC]: ! Circuit initializing,
GOOD = 2; ! and treat as garbage message
[inrange]: ! In middle of DLL protocol -
GOOD = 0;
tes;
if .GOOD neq 0
then BAD_MSG(.LINEb,.CCB,.GOOD); ! Treat as garbage message
end; !End of RCV_TI
global routine RCV_TV (LINEb,CCB): LINKAGE_DB_CCB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! Processes a received Transport Verification message. If we
! are expecting one, we will validate it and if valid, declare
! the circuit up. (If we have not received back the TI message we
! sent, the "line up" will be delayed until we do.)
!
! FORMAL PARAMETERS
!
! CCB[C_LIN] - Index of circuit data base entry
! CCB[C_BIAS] - buffer descriptor for TV's buffer
!
! IMPLICIT INPUTS
!
! LINEstate
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
! May commence or restart an initialization sequence if we are in
! the wrong state.
!
!--
begin
map CCB: ref block field (C_fields);
require 'XPTSYM';
local GOOD;
label MSG_CHECK,TV_CHECK;
MSG_CHECK:
begin ! MSG_CHECK
local CNT;
pointer PTR;
MAPBUF(.CCB,PTR,CNT);
!
! Validate the TV message; if it's no good, treat as a BAD_MSG
!
if (CNT = .CNT - 4) lss 0 then leave MSG_CHECK;
begin ! CTLFLG
local CTLFLG;
CTLFLG = getb(PTR);
if biton(.CTLFLG,%b'11110000') ! Check the control header
then begin
GOOD = 7; ! Reserved bits on - no good
leave MSG_CHECK;
end;
end;
if getw(PTR) neq .Nid ! SRCNODE
then begin
GOOD = 4; ! Source node is not the adjacent node
leave MSG_CHECK;
end;
%(
begin ! FCNVAL
local LEN;
LEN = getb(PTR);
PTR = ch$plus(.PTR,.LEN);
end;
)%
GOOD = 0;
end; ! MSG_CHECK
!
! Dispatch on circuit state
!
case .LINEstate from HA to RU of
set
[TV]: ! This is the big case
TV_CHECK:
begin
local PWDb: ref PWDblock;
pointer PTR;
if .GOOD neq 0 then leave TV_CHECK;
PWDb = GET_PWDb (.Nid);
PTR = ch$plus (.CCB[C_ADDR],3);
if .PWD3rcv_length neq 0
then if (getb(PTR) neq .PWD3rcv_length) or
ch$neq (.PWD3rcv_length, .PTR,
.PWD3rcv_length, byt$ptr (PWD3rcv), 0)
then begin
GOOD = 8;
leave TV_CHECK;
end;
NEXT_STATE (.LINEb, TC);
end;
[RU]: ! Circuit running, message unexpected -
GOOD = 1; ! and treat as garbage message
[TI,TC]: ! Circuit initializing,
GOOD = 2; ! and treat as garbage message
[inrange]: ! In middle of DLL protocol -
GOOD = 0;
tes;
if .GOOD neq 0
then BAD_MSG(.LINEb,.CCB,.GOOD); ! Treat as garbage message
end; !End of RCV_TV
global routine TERM_LIN (LINEb): CALL$ novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! Terminates a circuit, i.e., stops the circuit at the Data Link Level and
! generates a "line down" event. The sequence that this routine starts
! differs from that of INI_LIN in that the circuit will not be restarted;
! to restart the circuit, call INI_LIN.
!
! FORMAL PARAMETERS
!
! LINEb - line data base
!
! IMPLICIT INPUTS
!
! LINEstate
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
! Changes circuit state. Declares circuit "down" if it is not down
! already. Terminates a Initialize sequence.
! NOTE: This routine acquires a free CCB. If it is unable to get one,
! the function requested will be put in the LINEfunction cell for the
! circuit. The function will be retried on timeout.
!
!--
begin
require 'XPTSYM';
begin ! Kill all start requests
local Chain;
Chain = .LINEccb;
LINEccb = 0;
while true do
begin
local CCB: ref block field (C_fields);
if (CCB = .Chain) eqla 0 then exitloop;
Chain = .CCB[C_LNK];
if (.CCB[C_MOD] eql FM_STR) ! If this is...
then begin ! ...an initialization function,
CCB[C_STS] = CE_DIS; ! then return the CCB to the
CCB[C_FNC] = FC_CCP; ! caller with a failure code
$MCB_SCHEDULE_CCB(.CCB);
end
else begin ! otherwise
CCB[C_LNK] = .LINEccb; ! hold on to it.
LINEccb = .CCB;
end;
end;
end;
!
! Do termination processing depending on the circuit state
!
case .LINEstate from HA to RU of
set
[OFF,DT]: ! Do nothing
;
[HA]: ! Already halted -
CCB_CMP(.LINEb); ! clean out function queue
[inrange]: ! Start termination:
NEW_STATE (.LINEb, DT);
tes;
end; !End of TERM_LIN
global routine TLIAST (DATABASE,CCB,MODIFIER): LINKAGE_DB_CCB_MOD novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! Processes an asynchronous event from the DLL. There are three types of
! asynchronous events:
!
! o State Change This allows Transport to follow the DLL
! state. State changes drive part of the
! TLI state machine.
!
! o Transient Error These are "software" errors, which indicate
! an interruption of the DLL protocol on
! the circuit. Receipt of such an error will
! cause Transport to recycle the circuit, if
! it is up.
!
! o Persistent Error These are errors from which the device or
! protocol cannot recover on its own. If it
! is a warning, recovery can be made through
! initialization, otherwise stop using
! the circuit.
!
! All transient and persistent errors (except entry to MOP) cause logging of
! circuit events; no state change does so directly.
!
! FORMAL PARAMETERS
!
! DATABASE Dummy parameter; not used
! CCB Function CCB for the asynchronous event
! CCB[C_MOD] Event class:
! DLL$K_STATE
! DLL$K_TRANSIENT_ERROR
! DLL$K_PERSISTENT_ERROR
! CCB[C_STS] Specific event type:
!
! For DLL$K_STATE:
! DLL$_STATE_OFF
! DLL$_STATE_SYNCHRONIZING
! DLL$_STATE_RUNNING
! DLL$_STATE_MAINTENANCE
!
! For DLL$K_TRANSIENT_ERROR:
! DLL$_START_RECEIVED
! DLL$_TRANSMIT_THRESHOLD
! DLL$_RECEIVE_THRESHOLD
! DLL$_SELECTION_THRESHOLD
!
! For DLL$K_PERSISTENT_ERROR:
! DLL$_DEVICE_RESPONSE_ERROR
! DLL$_DEVICE_SERVICE_ERROR
! DLL$_DEVICE_OPERATION_ERROR
!
! MODIFIER Dummy parameter; not used
!
! IMPLICIT INPUTS
!
! LINEstate
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
! NONE.
!--
begin
local LINEb;
require 'XPTSYM';
map CCB: ref block field (C_XPT_FIELDS);
local CB: ref block field (C_XPT_FIELDS);
local REASON;
literal
REASONstop = 1^8,
REASONlog = 1^9,
REASONinit = 1^10;
!
! Address the circuit data base entry
!
LINEb = $TLI_GET_LINE_DB(.CCB[C_LIN]);
REASON = 0;
select .CCB[C_MOD] of
set
[DLL$K_STATE]: ! State change
CIRCUIT_STATE(.LINEb,.CCB);
[DLL$K_TRANSIENT_ERROR]: ! Transient errors
REASON = REASONinit + REASONlog + 0; ! Synch lost
[DLL$K_PERSISTENT_ERROR]: ! Persistent errors
selectone .block [CCB[C_STS], STS$V_SEVERITY] of
set
[STS$K_WARNING]:
REASON = REASONinit + REASONlog + 0; ! Synch lost
[otherwise]:
REASON = REASONstop + REASONlog + 1; ! Data errors
tes;
tes;
!
! Log an event (except for MOP Mode Received)
!
if biton(.REASON,REASONlog) then begin
local VALUE;
$NM_LOG_BEGIN();
VALUE = .REASON<0,8>; ! Move in the
PARAMETER_C_1(5,VALUE); ! reason code
$NM_LOG_END(4^6+
(case .LINEstate from HA to RU of
set
[HA,DT,OFF,DS]: begin
COUNTER_INCREMENT(LINEb,XPTini_fail);! Increment the
$XPT$E_ILF ! appropriate counter
end; ! ("line down" or
[inrange]: begin ! "initialization failure")
COUNTER_INCREMENT(LINEb,XPTlinedn); ! and declare the
$XPT$E_LLF ! appropriate event
end;
tes),.NMXid);
end;
!
! If the error is correctible, reinitialize the circuit.
! If it is permanent, terminate the circuit.
!
if biton(.REASON,REASONinit) ! Correctible error -
then selectone .LINEstate of ! if necessary,
set
[RU,TC]: ! declare the
NEW_STATE (.LINEb, LR);
[otherwise]: ! otherwise just
NEW_STATE (.LINEb, DS);
tes;
if biton(.REASON,REASONstop) ! Permanent error -
then NEW_STATE (.LINEb, DT); ! bring the circuit down for good
!
! Release the function CCB
!
$MCB_RETURN_CCB(.CCB);
end; !End of TLIAST
global routine XCPDAT (LINEb,CCB): MCB_DB_CCB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! This will be a TI/TV/OTI/OTV message
!
! FORMAL PARAMETERS
!
! CCB Function CCB
!
! IMPLICIT INPUTS
!
! LINEstate
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
!--
begin
map CCB:ref block field (C_XPT_FIELDS);
require 'XPTSYM';
if .CCB[C_XPT_TYPE] eql FUNC_TI
then if .LINEstate eql TI
then Listen_clock = .Init_timer;
CCB[C_XPT_TYPE] = -.CCB[C_XPT_TYPE];
if .LINEfunction eql .CCB[C_XPT_TYPE] ! (These functions can be cancelled)
then LINEfunction = 0;
$MCB_RETURN_CCB(.CCB);
NEXT_ACTION (.LINEb);
end; ! End of XCPDAT
global routine XCPINI (LINEb,CCB): MCB_DB_CCB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! This will be a TI/TV/OTI/OTV/HELLO message
!
! FORMAL PARAMETERS
!
! CCB Function CCB
!
! IMPLICIT INPUTS
!
! LINEstate
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
!--
begin
map CCB:ref block field (C_XPT_FIELDS);
require 'XPTSYM';
LINEfunction = 0;
$MCB_RETURN_CCB (.CCB);
NEXT_ACTION (.LINEb);
end; ! End of XCPINI
global routine XCPSTP (LINEb,CCB): MCB_DB_CCB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
! This will be a TI/TV/OTI/OTV/HELLO message
!
! FORMAL PARAMETERS
!
! CCB Function CCB
!
! IMPLICIT INPUTS
!
! LINEstate
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
! NONE.
!
! SIDE EFFECTS:
!
!--
begin
map CCB:ref block field (C_XPT_FIELDS);
require 'XPTSYM';
LINEfunction = 0;
$MCB_RETURN_CCB (.CCB);
NEXT_ACTION (.LINEb);
end; ! End of XCPSTP
end ! End of module TLILIN
eludom