Google
 

Trailing-Edge - PDP-10 Archives - BB-P363B-SM_1985 - mcb/nml/nmllbk.bli
There are 2 other files named nmllbk.bli in the archive. Click here to see a list.
! NET:<PECKHAM.DEVELOPMENT>NMLLBK.BLI.2  4-Oct-82 07:39:16, Edit by PECKHAM
!
! Ident 33.
!   Fix bug introduced to LOOP_LINE by last edit.
!
! NET:<PECKHAM.DEVELOPMENT>NMLLBK.BLI.2  3-Oct-82 14:59:41, Edit by PECKHAM
!
! Ident 32.
!   It was found that in-house VAXes returned a MOP loopback response code
!   of 25 - it will take too long to get them to fix it, so accomodate it.
!   Hack up LOOP_LINE to recognize it as valid message.
!
! <BRANDT.DEVELOPMENT>NMLLBK.BLI.1 14-Sep-82 11:43:23, Edit by BRANDT
!
! Ident 31.
!   In NML$TEST, include an entity id in the response message.  Include
!   the data field only for specific errors.
!
! NET:<PECKHAM.DEVELOPMENT>NMLLBK.BLI.2 23-Jun-82 11:37:06, Edit by PECKHAM
!
! Ident 30.
! Check RB_PRV_* bits in request block before performing requests.
!
! NET:<PECKHAM.DEVELOPMENT>NMLLBK.BLI.3 14-Jun-82 13:43:13, Edit by PECKHAM
!
! Ident 29.
! Handle the MOP prompt message (ENTER MOP MODE) as a one byte message.
! This conforms to the VMS/RSX agreed-upon protocol.
!
! NET:<PECKHAM.DEVELOPMENT>NMLLBK.BLI.2 22-May-82 17:37:27, Edit by PECKHAM
!
! Ident 28.
! Check CIRCUIT STATE, SUBSTATE, and SERVICE in LINE_ACCESS
! for service interlocks.
!
! NET:<PECKHAM.DEVELOPMENT>NMLLBK.BLI.2 10-May-82 15:54:38, Edit by PECKHAM
!
! Ident 27.
! Fix linkage for BLISS-36
!
! NET:<PECKHAM.DEVELOPMENT>NMLLBK.BLI.13  5-May-82 11:09:50, Edit by PECKHAM
!
! Ident 26.
! Disallow LOOP LINE in NML$TEST.
! Add Loop Request Parameter Block and use (for better code efficiency).
! Optimize linkages around the parameter block.
!
! NET:<PECKHAM.DEVELOPMENT>NMLLBK.BLI.2 28-Apr-82 12:45:27, Edit by PECKHAM
!
! Ident 25.
! Change NMU$DLX_* routine references to $NMU_DLX_* macro references.
! Add receive timeout values where needed.
!
! NET:<PECKHAM.DEVELOPMENT>NMLLBK.BLI.7  8-Mar-82 13:36:45, Edit by PECKHAM
!
! Ident 24.
! Do not send ENTER MOP MODE message on LOOP LINE initialization
! in LINE_ACCESS. Add retry code in LOOP_LINE.
!
! NET:<BRANDT.DEVELOP>NMLLBK.BLI.1 14-Dec-81 16:43:23, Edit by BRANDT
!
! Ident 23.
!   Change call to NML$SET_VDB_PARAMETER so that the address of the
!   data is passed, not the value.  Add literal defs from NMLDLW for
!   circuit parameter numbers and substate values.
!
! NET:<DECNET20-V3P1.NML>NMLLBK.BLI.4 21-Oct-81 09:13:23, Edit by WEBBER
!
! Ident 22.
! Modify interface to NETWORK_OPEN to pass the response buffer and its
! length.
!
! NET:<DECNET20-V3P1.NML>NMLLBK.BLI.3 16-Jun-81 17:05:02, Edit by GUNN
!
! Ident 21.
! Make check for looped message in LINE_ACCESS allow both
! function code LOOPBACK_TEST and LOOPED_DATA. 
! Allow for reflected ENTER-MOP-MODE message.
!
! NET:<DECNET20-V3P1.NML>NMLLBK.BLI.15 16-Jun-81 12:30:15, Edit by GUNN
!
! Ident 20.
! Fix response handling in LOOP_LINE.
!
! NET:<DECNET20-V3P1.NML>NMLLBK.BLI.12 15-Jun-81 10:04:26, Edit by GUNN
!
! Ident 19.
! Fix retrieval of response code from response buffer after calling
! LINE_ACCESS.
!
! NET:<DECNET20-V3P1.NML>NMLLBK.BLI.8 12-Jun-81 10:50:01, Edit by GUNN
!
! Ident 18.
! Change default LENGTH parameter to 127. Makes default work with 
! DECnet-M.
!
! NET:<DECNET20-V3P1.NML>NMLLBK.BLI.7 11-Jun-81 17:45:07, Edit by GUNN
!
! Ident 17.
! Build response message if LINE_ACCESS fails.
!
! NET:<DECNET20-V3P1.NML>NMLLBK.BLI.6 11-Jun-81 16:07:08, Edit by GUNN
!
! Ident 16.
! Release MOP buffer in LINE_ACCESS.
! Put call to NML$SET_VDB_PARAMETER in comment.
!
! NET:<DECNET20-V3P1.NML>NMLLBK.BLI.5  8-Jun-81 10:16:54, Edit by GUNN
!
! Ident 15.
! Add code in LINE_ACCESS to write ENTER-MOP-MODE message and
! read MOP-MODE-RUNNING message. 
! Add code to handle read errors.
!
! NET:<DECNET20-V3P1.NML>NMLLBK.BLI.12 28-May-81 10:45:42, Edit by GUNN
!
! Ident 14.
! Set RB_RESPONSE_LENGTH from response message buffer after calling 
! LINE_ACCESS.
!
! NET:<DECNET20-V3P1.NML>NMLLBK.BLI.11 28-May-81 09:23:50, Edit by GUNN
!
! Ident 13.
! Change test for completion of NMU$DLX_OPEN to geq 0.
!
! NET:<DECNET20-V3P1.NML>NMLLBK.BLI.10 28-May-81 06:21:35, Edit by GUNN
!
! Ident 12.
! Add definition for RESPONSE_BUFFER_ALLOCATION.
!
! NET:<DECNET20-V3P1.NML>NMLLBK.BLI.9 28-May-81 06:11:12, Edit by GUNN
!
! Ident 11.
! Allocate a response message buffer in NML$TEST.
!
! NET:<DECNET20-V3P1.NML>NMLLBK.BLI.8 27-May-81 15:58:49, Edit by GUNN
!
! Ident 10.
! Add external declarations for NMU$DLX_xxx routines.
! Remove reference to structure REQ in LOOP_NODE and LOOP_LINE.
! Pass repsonse pointer instead.
!
! NET:<DECNET20-V3P1.NML>NMLLBK.BLI.6 27-May-81 15:03:15, Edit by GUNN
!
! Ident 09.
! Add code to perform loop line/circuit.
!
! NET:<DECNET20-V3P1.NML>NMLLBK.BLI.5 31-Mar-81 07:59:24, Edit by GUNN
!
! Release send and receive buffers in LOOP_NODE.
!
! NET:<DECNET20-V3P1.NML>NMLLBK.BLI.3 11-Mar-81 08:57:37, Edit by GUNN
!
! Change format of node id string passed to NMU$NETWORK_OPEN in the
! Connect Block CB_HOST field to be same as NODE entity id.
!
! NET:<DECNET20-V3P1.NML>NMLLBK.BLI.2  9-Mar-81 08:54:21, Edit by GUNN
!
! Change test loop limit so extra loop not taken.
! Change default length to 255.
!
! NET:<DECNET20-V3P1.NML>NMLLBK.BLI.7 13-Feb-81 10:06:16, Edit by GUNN
!
! Add CIRCUIT entity in NML$TEST.
!
! NET:<DECNET20-V3P1.NML>NMLLBK.BLI.6 12-Feb-81 15:27:19, Edit by GUNN
!
! Update copyright date.
! Change GET_LOOP_PARAMETERS to return NICE error return code on first
! invalid parameter detected.
! Change GENERATE_LOOP_MESSAGE to return NICE error code if LOOP WITH
! parameter value is invalid.
!
! NET:<DECNET20-V3P1.BASELEVEL-2.SOURCES>NMLLBK.BLI.36 10-Feb-81 13:49:06, Edit by JENNESS
!    Make sure that connect data has zero length in connect block!!
! NET:<DECNET20-V3P1.BASELEVEL-2.SOURCES>NMLLBK.BLI.35  9-Feb-81 12:43:12, Edit by GUNN
!    Remove check for version skew.
! NET:<DECNET20-V3P1.BASELEVEL-2.SOURCES>NMLLBK.BLI.33  3-Feb-81 10:34:00, Edit by JENNESS
!    Remove literal definition for MIRROR_OBJECT ... now in NMARCH.
module NMLLBK	(
		ident = 'X03.32'
		) =
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:	DECnet-10/20 V3.0 Network Management Layer (NML)
!
! ABSTRACT:
!
!	Performs loopback test function.
!
! ENVIRONMENT:	TOPS-10/20 & MCB/RSX11 User mode under NML
!
! AUTHOR: Dale C. Gunn , CREATION DATE: 12-Nov-80
!
! MODIFIED BY:
!
!	, : VERSION
! 01	-
!--
!
! INCLUDE FILES:
!

library 'NMLLIB' ;                      ! All required definitions

require 'NMLEXT';                       ! External routine declarations

!
! TABLE OF CONTENTS
!

%if %bliss (bliss16)
%then linkage NML_LKG_PB = jsr (register = 5);
%else macro NML_LKG_PB = bliss36c %;
%fi

forward routine
         NML$TEST,                         ! Perform loopback test
         GET_LOOP_PARAMETERS: NML_LKG_PB,  ! Get parameters from NICE test msg
         LOOPBACK_ACCESS: NML_LKG_PB,      ! NODE loopback access routine
         LINE_ACCESS: NML_LKG_PB,          ! LINE loopback access routine
         LOOP_NODE: NML_LKG_PB,            ! Perform NODE loop test
         LOOP_LINE: NML_LKG_PB,            ! Perform LINE loop test
         GENERATE_LOOP_MESSAGE: NML_LKG_PB,! Build LOOP data message
         VERIFY_LOOP_MESSAGE: NML_LKG_PB;  ! Check validity of LOOPED message

!
! MACROS:
!

!
! EQUATED SYMBOLS:
!
! Loop Request Block
!
$show (fields);                         ! Turn on XPORT field display
$show (literals);                       ! Turn on XPORT literal display

$field
    PARAMETER_FIELDS =
        set
        PB_BASE = [$sub_block (0)],
        PB_RESPONSE_PTR = [$pointer],
        PB_REQ_ADR = [$address],
        PB_LINK_HANDLE = [$short_integer],
        PB_COUNT = [$integer],          ! Node parameter 150
        PB_LENGTH = [$integer],         ! Node parameter 151
        PB_WITH = [$integer]            ! Node parameter 152
        tes;

literal
    PARAMETER_BLOCK_SIZE = $field_set_size,
    PARAMETER_BLOCK_ALLOCATION = $field_set_units;

macro
     PARAMETER_BLOCK = block [PARAMETER_BLOCK_SIZE] field (PARAMETER_FIELDS) %;

$show (none);                           ! Turn off XPORT display

!
! STATE/SUBSTATE/SERVICE definitions
!

literal
    CPARM_STATE = 0,
    CPARM_SUBSTATE = 1,
    CPARM_SERVICE = 100,

    LINK_ON = 0,
    LINK_OFF = 1,
    LINK_SERVICE = 2,
    LINK_CLEARED = 3,

    LINK_NO_SUBSTATE = -1,
    LINK_STARTING = 0,
    LINK_REFLECTING = 1,
    LINK_LOOPING = 2,
    LINK_LOADING = 3,
    LINK_DUMPING = 4,
    LINK_TRIGGERING = 5,
    LINK_AUTOSERVICE = 6,
    LINK_AUTOLOADING = 7,
    LINK_AUTODUMPING = 8,
    LINK_AUTOTRIGGERING = 9,
    LINK_SYNCHRONIZING = 10,
    LINK_FAILED = 11,

    LINK_ENABLED = 0,
    LINK_DISABLED = 1;

literal
       RESPONSE_BUFFER_LENGTH = 76,     ! NICE response buffer in bytes
       RESPONSE_BUFFER_SIZE = ch$allocation (RESPONSE_BUFFER_LENGTH,8),
       RESPONSE_BUFFER_ALLOCATION = RESPONSE_BUFFER_SIZE * %upval ;

literal                                 ! Defaults for test
       DEFAULT_LENGTH = 127,            ! Length of test data in bytes
       DEFAULT_COUNT = 1,               ! Same as RSX and VAX
       DEFAULT_WITH = 2 ;               ! MIXED ones and zeroes

!
! OWN STORAGE:
!

!
! EXTERNAL REFERENCES:
!

external
        NMLVER,                         ! Network Managment version number
        DECECO,                         ! Digital ECO number
        USRECO ;			! User ECO number
        
external routine
         NML$NICE_RESPONSE,
         NML$CLR_VDB_PARAMETER,
         NML$GET_VDB_PARAMETER,
         NML$SET_VDB_PARAMETER,
         NMU$NETWORK_UTILITIES;
global routine %unquote NML$TEST (REQ) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	This routine performs the NICE test request function. Either
!       a NODE or LINE loopback test is performed based on the
!       entity type in the test request message. If the NODE loop test
!       is requested the NICE message may specify optional access
!       control information to be used when connecting to the remote
!       loopback mirror. Optional test parameters may also be included.
!
! FORMAL PARAMETERS
!
!	REQ - The address of the NML Request Block.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NICE return code.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    map
       REQ: ref REQUEST_BLOCK;          ! NICE RB structure

    local
         PB: PARAMETER_BLOCK,           ! For centralized data base
         RTN_COD;                       ! NICE return code

    selectone .REQ[RB_NICE_ENTITY_TYPE] of
        set
        [CIRCUIT_, LINE_]:              ! Too dangerous

            if not .REQ[RB_PRV_SERVICE] then return NICE$_PRV;

        [otherwise]:                    ! Okay
            0;
        tes;

    !
    ! Allocate NICE response buffer.
    !

    REQ[RB_RESPONSE_ALLOCATION] = RESPONSE_BUFFER_ALLOCATION;
    REQ[RB_RESPONSE] = NMU$MEMORY_GET (.REQ[RB_RESPONSE_ALLOCATION]);

    !
    ! Set up the parameter block
    !

    PB [PB_REQ_ADR] = .REQ;
    PB [PB_RESPONSE_PTR] = ch$ptr (.REQ[RB_RESPONSE],, 8);

    !
    ! Get the LOOP test parameters from NICE message.
    !

    if (RTN_COD = GET_LOOP_PARAMETERS (PB[PB_BASE])) lss 0
    then return .RTN_COD ;

    !
    ! Perform either NODE or LINE loop test based on entity
    !

    begin
    local PBBASE;
    PBBASE = PB[PB_BASE];
    selectone .REQ[RB_NICE_ENTITY_TYPE] of
        set
        [NODE_E]:                       ! NODE loopback test
            RTN_COD = LOOPBACK_ACCESS (.PBBASE); ! Call loopback access routine
        [CIRCUIT_]:                     ! CIRCUIT loopback test
            RTN_COD = LINE_ACCESS (.PBBASE); ! Call line access routine
        [LINE_]:
            RTN_COD = NICE$_UFO;
        [otherwise]:                    ! Internal error
            RTN_COD = NICE$_MPE;
        tes;
    end;

    if .RTN_COD lss 0
    then begin
         local EID_PTR, EID_LEN, RSP_PTR;

         if ch$rchar(.PB[PB_RESPONSE_PTR]) eql 0
         then $RESPONSE (.PB[PB_RESPONSE_PTR], .RTN_COD);

         RSP_PTR = ch$plus (.PB[PB_RESPONSE_PTR],
                            $RESPONSE_LENGTH (.PB[PB_RESPONSE_PTR]));

         EID_PTR = .REQ[RB_NICE_ENTITY];      ! include an entity ID
         if .REQ[RB_NICE_ENTITY_TYPE] eql NODE_E
         then				! NODE has special format
                begin
                local
                    NODE_ID_PTR,
                    LOCAL_NODE_PTR;

                LOCAL_NODE_PTR = NMU$NETWORK_LOCAL (); ! Local node id
                NODE_ID_PTR = .RSP_PTR; ! Make copy of current pointer

                EID_LEN = ch$rchar (ch$plus (.EID_PTR,2)) + 3;
                RSP_PTR = ch$move (.EID_LEN, .EID_PTR, .RSP_PTR);
                !
                ! If node addresses are equal this is the executor node,
                ! so set bit 7 in length byte to indicate this fact.
                !
                if GETB (NODE_ID_PTR) eql GETB (LOCAL_NODE_PTR)
                then if GETB (NODE_ID_PTR) eql GETB (LOCAL_NODE_PTR)
                     then ch$wchar ((ch$rchar (.NODE_ID_PTR) or (1 ^ 7)), .NODE_ID_PTR);

                end
 	else
                begin
                EID_LEN = ch$rchar (.EID_PTR) + 1;
                RSP_PTR = ch$move (.EID_LEN, .EID_PTR, .RSP_PTR);
                end;

	selectone .RTN_COD of			! Include  date field
	    set					! for appropriate errors
	    [$NICE$ERR_LCE,
	     $NICE$ERR_BLR,
	     $NICE$ERR_OPF,
	     $NICE$ERR_IPV]:

		PUTW ((PB[PB_COUNT]),RSP_PTR);

	    [otherwise]:                    	! No data field supplied
		0;
	    tes;

         REQ[RB_RESPONSE_LENGTH] = ch$diff (.RSP_PTR, .PB[PB_RESPONSE_PTR]);
         end
    else begin
         $RESPONSE (ch$ptr(.REQ[RB_RESPONSE],,8), NICE$_SUC) ;
         REQ[RB_RESPONSE_LENGTH] = 1 ;
         NML$REQUEST_FINISH (.REQ) ;    ! Queue request for completion
         end;

    return .RTN_COD 
    end;				!End of NML$TEST
routine GET_LOOP_PARAMETERS (PB) : NML_LKG_PB =

!++
! FUNCTIONAL DESCRIPTION:
!
!	This routine extracts the three optional parameters, COUNT,
!       LENGTH, and WITH (TYPE) that may be supplied with the NICE
!       test request message. If any of the parameters are not
!       supplied in the test request appropriate defaults are 
!       returned.
!
! FORMAL PARAMETERS
!
!	PB - The address of the parameter block.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	1, if successful;
!       NICE return code otherwise.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    map
       PB : ref PARAMETER_BLOCK;

    bind
       REQ = .PB[PB_REQ_ADR]: REQUEST_BLOCK; ! NICE RB structure

    !
    ! Preset the default values.
    !

    if not NML$GET_VDB_PARAMETER (.REQ [RB_NICE_ENTITY_TYPE],
                                  .REQ [RB_NICE_ENTITY],
                                  150,  ! LOOP COUNT
                                  PB[PB_COUNT])
    then PB[PB_COUNT] = DEFAULT_COUNT;
    if not NML$GET_VDB_PARAMETER (.REQ [RB_NICE_ENTITY_TYPE],
                                  .REQ [RB_NICE_ENTITY],
                                  151,  ! LOOP LENGTH
                                  PB[PB_LENGTH])
    then PB[PB_LENGTH] = DEFAULT_LENGTH;
    if not NML$GET_VDB_PARAMETER (.REQ [RB_NICE_ENTITY_TYPE],
                                  .REQ [RB_NICE_ENTITY],
                                  152,  ! LOOP WITH
                                  PB[PB_WITH])
    then PB[PB_WITH] = DEFAULT_WITH;

    !
    ! If parameters were provided pick up their values.
    !

    if .REQ[RB_NICE_PARAMETERS] neq 0
    then begin
         local PARPTR,PAREND;
         PARPTR = .REQ[RB_NICE_PARAMETERS];
         PAREND = ch$plus (ch$ptr(.REQ[RB_NICE],,8), .REQ[RB_NICE_LENGTH]);

         while ch$diff (.PAREND, .PARPTR) gtr 0
         do begin
            local PAR_NO, PAR_VAL;
            PAR_NO = GETW (PARPTR) ;    ! Get parameters number
            selectone .PAR_NO of
                set
                [150]:                  ! LOOP COUNT
                    selectoneu (PAR_VAL = GETW (PARPTR)) of
                        set
                        [1 to 65535]:
                            PB[PB_COUNT] = .PAR_VAL;
                        [otherwise]:
                            return $NICE$ERR_IPV;
                        tes;
                [151]:                  ! LOOP LENGTH
                    selectoneu (PAR_VAL = GETW (PARPTR)) of
                        set
                        [1 to 65535]:
                            PB[PB_LENGTH] = .PAR_VAL;
                        [otherwise]:
                            return $NICE$ERR_IPV;
                        tes;
                [152]:                  ! LOOP WITH
                    selectoneu (PAR_VAL = GETB (PARPTR)) of
                        set
                        [0, 1, 2]:
                            PB[PB_WITH] = .PAR_VAL;
                        [otherwise]:
                            return $NICE$ERR_IPV;
                        tes;
                [otherwise]:            ! Invalid parameter for LOOP
                    return $NICE$ERR_UPT ;
                tes;
            end;

         if .PARPTR neq .PAREND then return $NICE$ERR_IMF;
         end;

    return 1 ;                          ! Return NICE success code
    end;				!End of GET_LOOP_PARAMETERS
routine LOOPBACK_ACCESS (PB) : NML_LKG_PB =

!++
! FUNCTIONAL DESCRIPTION:
!
!	This is the loopback access routine for the NODE loopback
!       test.
!
! FORMAL PARAMETERS
!
!	PB - The address of the parameter block.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NICE return code.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    map
       PB: ref PARAMETER_BLOCK;

    bind
       REQ = .PB[PB_REQ_ADR]: REQUEST_BLOCK ; ! NICE RB structure

    local
         CBLK: CONNECT_BLOCK,           ! DECnet link connect block
         LSBLK: LINK_STATUS_BLOCK,      ! DECnet link status block
         RTN_COD ;                      ! NICE return

    !
    ! Set up the DECnet link connect block for loopback mirror
    ! at node specified in NCP command
    !

    CBLK[CB_OBJECT] = MIRROR_OBJECT ; ! Loopback mirror object number
    CBLK[CB_DESCRIPTOR_LENGTH] = 0 ; ! No descriptor
    CBLK[CB_TASK_LENGTH] = 0 ;  ! No task name

    !
    ! Entity id specifies the node to mirror the loopback test messages
    !

    CBLK[CB_HOST] = .REQ[RB_NICE_ENTITY] ;

    CBLK[CB_HOST_LENGTH] = .REQ[RB_NICE_ENTITY_ID_LENGTH] ;

    !
    ! Copy access control fields from request block
    !

    CBLK[CB_USERID_LENGTH] = .REQ[RB_USER_LENGTH] ;
    CBLK[CB_USERID] = .REQ[RB_USER];

    CBLK[CB_ACCOUNT_LENGTH] = .REQ[RB_ACCOUNT_LENGTH] ;
    CBLK[CB_ACCOUNT] = .REQ[RB_ACCOUNT];
             

    CBLK[CB_PASSWORD_LENGTH] = .REQ[RB_PASSWORD_LENGTH] ;
    CBLK[CB_PASSWORD] = .REQ[RB_PASSWORD];
    
    CBLK[CB_DATA_LENGTH] = 0;

    !
    ! Now make network connection to Loopback Mirror
    !

    REQ[RB_RESPONSE_LENGTH] = RESPONSE_BUFFER_LENGTH;
    if (PB[PB_LINK_HANDLE] = NMU$NETWORK_OPEN (SOURCE_LINK, CBLK,
	.PB[PB_RESPONSE_PTR], REQ[RB_RESPONSE_LENGTH], NICE$_MCF))
    gtr 0
    then begin
         local
              MESSAGE_DATA_SIZE ;       ! Maximum data size of mirror

         !
         ! Check that mirror returned its maximum data buffer length
         ! and get it.
         !

         if .CBLK[CB_DATA_LENGTH] neq 2
         then return $NICE$ERR_MPE ;

         MESSAGE_DATA_SIZE = GETW (CBLK[CB_DATA]) ; ! Get mirror's data length

         !
         ! Go ahead and test if our length is not over mirrors maximum.
         !

         if .PB[PB_LENGTH] leq .MESSAGE_DATA_SIZE
         then RTN_COD = LOOP_NODE (PB[PB_BASE]) ! Loop messages to node
         else begin
              RTN_COD = NICE$_IPV;
              $RESPONSE (.PB[PB_RESPONSE_PTR], .RTN_COD, 151);
              PB[PB_COUNT] = .MESSAGE_DATA_SIZE;
              end;

         NMU$NETWORK_CLOSE (.PB[PB_LINK_HANDLE], 0, 0);
         end
    else RTN_COD = $NICE$ERR_MCF;       ! Say mirror connect failed

    return .RTN_COD
    end;				!End of LOOPBACK_ACCESS
routine LINE_ACCESS (PB) : NML_LKG_PB =

!++
! FUNCTIONAL DESCRIPTION:
!
!	This is the access routine for the LINE loopback test.
!
! FORMAL PARAMETERS
!
!	PB - The address of the parameter block.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NICE return code.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    map
       PB: ref PARAMETER_BLOCK;

    bind
       REQ = .PB[PB_REQ_ADR]: REQUEST_BLOCK; ! NICE RB structure

    local
         RTN_COD ;                      ! NICE return

    !
    ! STATE must be ON or SERVICE
    !
    begin
    local CIRCUIT_STATE;

    if not NML$GET_VDB_PARAMETER (.REQ[RB_NICE_ENTITY_TYPE],
                                  .REQ[RB_NICE_ENTITY],
                                  CPARM_STATE,
                                  CIRCUIT_STATE)
    then CIRCUIT_STATE = LINK_ON;

    selectone .CIRCUIT_STATE of
        set
        [LINK_ON, LINK_SERVICE]:
            ;
        [otherwise]:
            begin
            RTN_COD = NICE$_CWS;
            $RESPONSE (.PB[PB_RESPONSE_PTR], .RTN_COD, CIRCUIT_);
            return .RTN_COD;
            end;
        tes;

    end;
    !
    ! SERVICE must be ENABLED
    !
    begin
    local CIRCUIT_SERVICE;

    if not NML$GET_VDB_PARAMETER (.REQ[RB_NICE_ENTITY_TYPE],
                                  .REQ[RB_NICE_ENTITY],
                                  CPARM_SERVICE,
                                  CIRCUIT_SERVICE)
    then CIRCUIT_SERVICE = LINK_DISABLED;

    selectone .CIRCUIT_SERVICE of
        set
        [LINK_ENABLED]:
            ;
        [otherwise]:
            begin
            RTN_COD = NICE$_CWS;
            $RESPONSE (.PB[PB_RESPONSE_PTR], .RTN_COD, CIRCUIT_);
            return .RTN_COD;
            end;
        tes;

    end;
    !
    ! substate must not be set.
    !
    begin
    local CIRCUIT_SUBSTATE;

    if not NML$GET_VDB_PARAMETER (.REQ[RB_NICE_ENTITY_TYPE],
                                  .REQ[RB_NICE_ENTITY],
                                  CPARM_SUBSTATE,
                                  CIRCUIT_SUBSTATE)
    then CIRCUIT_SUBSTATE = LINK_NO_SUBSTATE;

    selectone .CIRCUIT_SUBSTATE of
        set
        [LINK_NO_SUBSTATE]:
            ;
        [otherwise]:
            begin
            RTN_COD = NICE$_CWS;
            $RESPONSE (.PB[PB_RESPONSE_PTR], .RTN_COD, CIRCUIT_);
            return .RTN_COD;
            end;
        tes;

    end;
    !
    ! Open the DLX data link for loopback use.
    !

    if (RTN_COD = $NMU_DLX_OPEN (DLX_LOOP,
                                 .REQ[RB_NICE_ENTITY],
                                 .PB[PB_RESPONSE_PTR])) geq 0
    then begin                          ! DLX open, got DLX link handle
         PB[PB_LINK_HANDLE] = .RTN_COD;

         !
         ! Set Data Link Substate to LOOPING.
         !

         NML$SET_VDB_PARAMETER (.REQ[RB_NICE_ENTITY_TYPE],
                                .REQ[RB_NICE_ENTITY],
                                CPARM_SUBSTATE,
                                uplit (LINK_LOOPING)) ;

         RTN_COD = LOOP_LINE (PB[PB_BASE]);     ! Loop messages to data link

         NML$CLR_VDB_PARAMETER (.REQ[RB_NICE_ENTITY_TYPE],
                                .REQ[RB_NICE_ENTITY],
                                CPARM_SUBSTATE);

         $NMU_DLX_CLOSE (.PB[PB_LINK_HANDLE]); ! Close the DLX link
         end;

    return .RTN_COD
    end;				!End of LINE_ACCESS
routine LOOP_NODE (PB) : NML_LKG_PB =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Performs the loopback function to the loopback mirror at
!       a remote node.
!
! FORMAL PARAMETERS
!
!	PB - The address of the parameter block.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!       NICE return code.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    map
        PB: ref PARAMETER_BLOCK;

    label
        AND_RETURN_BUFFERS;

    literal
           EOM = 1 ;                    ! End of message flag

    local
         BUFFER_ADR,                    ! Address of receive buffer
         BUFFER_PTR,                    ! Pointer to looped test message
         MESSAGE_ADR,                   ! Address of test message buffer
         MESSAGE_PTR,                   ! Pointer to test message
         RTN_COD ;                      ! NICE return code

    bind
        LOOP_BUFFER_ALLOCATION = ch$allocation((.PB[PB_LENGTH] + 1),8) * %upval ;

    !
    ! Get buffers for send and receive loop messages
    !

    BUFFER_ADR = NMU$MEMORY_GET (LOOP_BUFFER_ALLOCATION) ;
    BUFFER_PTR = ch$ptr (.BUFFER_ADR,,8) ; ! Pointer to buffer
    MESSAGE_ADR = NMU$MEMORY_GET (LOOP_BUFFER_ALLOCATION) ;
    MESSAGE_PTR = ch$ptr (.MESSAGE_ADR,,8) ; ! Pointer to buffer

AND_RETURN_BUFFERS:
    begin                               ! AND_RETURN_BUFFERS
    !
    ! Build a loop message to test with, function code is zero.
    !

    RTN_COD = GENERATE_LOOP_MESSAGE (PB[PB_BASE], %O'0', .MESSAGE_PTR) ;

    if .RTN_COD lss 0 then leave AND_RETURN_BUFFERS;

         until .PB[PB_COUNT] eql 0      ! Loop all messages
             do begin
                if not NMU$NETWORK_WRITE (.PB[PB_LINK_HANDLE],
                                          EOM,
                                          .PB[PB_LENGTH] + 1, ! 1 Overhead byte
                                          .MESSAGE_PTR)
                then begin
                     RTN_COD = NICE$_MLD;
                     $RESPONSE(.PB[PB_RESPONSE_PTR], .RTN_COD, 10);
                     leave AND_RETURN_BUFFERS
                     end;
                RTN_COD = NMU$NETWORK_READ (.PB[PB_LINK_HANDLE],
                                            .PB[PB_LENGTH] + 1,
                                            .BUFFER_PTR);
                if .RTN_COD lss 0 then leave AND_RETURN_BUFFERS;

                if not VERIFY_LOOP_MESSAGE (PB[PB_BASE], 1, .MESSAGE_PTR, .BUFFER_PTR)
                then begin
                     RTN_COD = $NICE$ERR_BLR;
                     leave AND_RETURN_BUFFERS
                     end;
                PB[PB_COUNT] = .PB[PB_COUNT] - 1 ; ! Another message looped
                end;

    RTN_COD = NICE$_SUC;
    end;                                ! AND_RETURN_BUFFERS
    !
    ! Release buffers
    !

    NMU$MEMORY_RELEASE (.MESSAGE_ADR,LOOP_BUFFER_ALLOCATION) ;
    NMU$MEMORY_RELEASE (.BUFFER_ADR,LOOP_BUFFER_ALLOCATION) ;

    return .RTN_COD ;                   ! Return results
    end;				!End of LOOP_NODE
routine LOOP_LINE (PB) : NML_LKG_PB =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS
!
!	PB - The address of the parameter block.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NONE.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    map
        PB: ref PARAMETER_BLOCK;

    label
        AND_RETURN_BUFFERS;

    local
         BUFFER_ADR,                    ! Address of receive buffer
         BUFFER_PTR,                    ! Pointer to looped test message
         MESSAGE_ADR,                   ! Address of test message buffer
         MESSAGE_PTR,                   ! Pointer to test message
         RTN_COD ;                      ! NICE return code

    bind
        LOOP_BUFFER_ALLOCATION = ch$allocation((.PB[PB_LENGTH] + 1),8) * %upval ;

    !
    ! Get buffers for send and receive loop messages
    !

    BUFFER_ADR = NMU$MEMORY_GET (LOOP_BUFFER_ALLOCATION) ;
    BUFFER_PTR = ch$ptr (.BUFFER_ADR,,8) ; ! Pointer to buffer
    MESSAGE_ADR = NMU$MEMORY_GET (LOOP_BUFFER_ALLOCATION) ;
    MESSAGE_PTR = ch$ptr (.MESSAGE_ADR,,8) ; ! Pointer to buffer

AND_RETURN_BUFFERS:
    begin                               ! AND_RETURN_BUFFERS
    !
    ! Build a loop message to test with, function code LOOPBACK_TEST.
    !

    RTN_COD = GENERATE_LOOP_MESSAGE (PB[PB_BASE], LOOPBACK_TEST, .MESSAGE_PTR) ;

    if .RTN_COD lss 0 then leave AND_RETURN_BUFFERS;

    until .PB[PB_COUNT] eql 0           ! Loop all messages
             do begin

                decru CNT from NMU$K_MOP_RETRY_LIMIT to 1
                do begin
                   if not $NMU_DLX_WRITE (.PB[PB_LINK_HANDLE],
                                         DLX_OTHER, ! Not doing load/dump 
                                         .MESSAGE_PTR,
                                         .PB[PB_LENGTH] + 1, ! 1 Overhead byte
                                         .PB[PB_RESPONSE_PTR])
                   then begin
                        ch$wchar(0, .PB[PB_RESPONSE_PTR]);
                        RTN_COD = $NICE$ERR_LCE;
                        leave AND_RETURN_BUFFERS
                        end;
                   RTN_COD = $NMU_DLX_READ (.PB[PB_LINK_HANDLE],
                                           DLX_OTHER, ! Not doing load/dump 
                                           .BUFFER_PTR, .PB[PB_LENGTH] + 1,,
                                           .PB[PB_RESPONSE_PTR]);
                   if .RTN_COD gtr 0 then exitloop;
                   ch$wchar(0, .PB[PB_RESPONSE_PTR]);
                   if .RTN_COD neq -2
                   then begin
                        RTN_COD = $NICE$ERR_LCE;
                        leave AND_RETURN_BUFFERS
                        end;
                   RTN_COD = $NICE$ERR_LCE;
                   end;

                if .RTN_COD lss 0 then leave AND_RETURN_BUFFERS;

                selectone ch$rchar (.BUFFER_PTR) of
                    set
                    [LOOPED_DATA, 25, LOOPBACK_TEST]:
                        if VERIFY_LOOP_MESSAGE (PB[PB_BASE],
                                                ch$rchar (.BUFFER_PTR),
                                                .MESSAGE_PTR,
                                                .BUFFER_PTR)
                        then PB[PB_COUNT] = .PB[PB_COUNT] - 1
                        else begin
                             RTN_COD = $NICE$ERR_BLR;
                             leave AND_RETURN_BUFFERS
                             end;
                    [MOP_MODE_RUNNING]:
                        if .RTN_COD geq 8
                        then if (ch$rchar (ch$plus (.BUFFER_PTR, 7)) and 1^2) eql 0
                             then begin
                                  RTN_COD = $NICE$ERR_OPF;
                                  leave AND_RETURN_BUFFERS
                                  end;
                    [otherwise]:
                        begin
                        RTN_COD = $NICE$ERR_BLR;
                        leave AND_RETURN_BUFFERS
                        end;
                    tes;
                
                end;

    RTN_COD = NICE$_SUC;
    end;                                ! AND_RETURN_BUFFERS
    !
    ! Release buffers
    !

    NMU$MEMORY_RELEASE (.MESSAGE_ADR,LOOP_BUFFER_ALLOCATION) ;
    NMU$MEMORY_RELEASE (.BUFFER_ADR,LOOP_BUFFER_ALLOCATION) ;

    return .RTN_COD ;                   ! Return results
    end;				!End of LOOP_LINE
routine GENERATE_LOOP_MESSAGE (PB, FUNC_CODE,MESSAGE_PTR) : NML_LKG_PB =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Generates a NICE test message of requested length and
!       contents determined by the LOOP WITH parameter value
!       passed as an argument.
!
! FORMAL PARAMETERS
!
!	PB - The address of the parameter block.
!       FUNC_CODE   - A value to be used as the first byte (function code)
!                     of the test message.
!       MESSAGE_PTR - A character sequence pointer to the buffer in which
!                     the NICE test message will be built.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	1, if successful;
!       NICE return code if failed.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    map
        PB: ref PARAMETER_BLOCK;

    local
         LOOP_CHAR ;

    !
    ! Set up the data pattern to be used in loop message
    !

    LOOP_CHAR = (case .PB[PB_WITH] from 0 to 2 of
                     set
                     [0]:                ! All zeroes
                         %B'00000000' ;
                     [1]:                ! All ones
                         %B'11111111' ;
                     [2]:                ! Mixed ones and zeroes
                         %B'10101010' ;
                     [inrange,           ! Default to mixed
                      outrange]:
                         return $NICE$ERR_IPV ; ! Error return
                     tes);

    !
    ! Write loop function code and fill message with appropriate pattern
    !

    ch$wchar_a (.FUNC_CODE,MESSAGE_PTR) ; ! Write function code
    ch$fill (.LOOP_CHAR,
             .PB[PB_LENGTH],
             .MESSAGE_PTR) ;

    return 1 ;                          ! Success
    end;				!End of GENERATE_LOOP_MESSAGE
routine VERIFY_LOOP_MESSAGE (PB,FUNC_CODE,TRANSMIT_PTR,RECEIVE_PTR) : NML_LKG_PB =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Determines the validity of a NICE test message response after
!       being looped to the target node. The first byte of the message
!       must contain the NICE success return code.
!
! FORMAL PARAMETERS
!
!	PB - The address of the parameter block.
!       FUNC_CODE   - A value to be used as the first byte (function code)
!                     of the test message.
!       TRANSMIT_PTR - A character sequence pointer to the NICE test
!                      message sent to the loopback mirror.
!       RECEIVE_PTR  - A character sequence pointer to the NICE test
!                      received from the loopback mirror.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	TRUE, if the looped message is valid;
!       FALSE, otherwise.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    map
        PB: ref PARAMETER_BLOCK;

    if ch$rchar_a (RECEIVE_PTR) neq .FUNC_CODE
    then $false
    else ch$eql (.PB[PB_LENGTH],
                 .RECEIVE_PTR,
                 .PB[PB_LENGTH],
                 ch$plus (.TRANSMIT_PTR, 1))

    end;				!End of VERIFY_LOOP_MESSAGE
end				!End of Module NMLLBK
eludom
! Local Modes:
! Mode:BLISS
! Auto Save Mode:2
! Comment Column:40
! Comment Rounding:+1
! End: