Google
 

Trailing-Edge - PDP-10 Archives - TOPS-20_V6.1_DECnetSrc_7-23-85 - mcb/nmx/nmxcce.bli
There is 1 other file named nmxcce.bli in the archive. Click here to see a list.
module NMXCCE (					! NMX CCP Common
		ident = 'X01070'
		) =
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: MCB Network Management
!
! ABSTRACT:
!
!
!
! ENVIRONMENT: MCB V3.0
!
! AUTHOR: Scott G. Robinson	CREATION DATE: 14-May-81
!
! MODIFIED BY:
!
! 02	- Code compression.
! 03    - Modify CCB_STATE values and handling.
!         Add call to SC during SHOW CIRCUIT CHARACTERISTICS.
!       Alan D. Peckham, 14-Apr-82
! 04    - Complete rework of NM support.
! 05    - Fix GET_ENTITY to stop an operation if unrecognized component.
!         Set FORWARD_REQUEST to handle non-existent targets.
! 06    - Disallow SERVICE state for lines and circuits.
! 07    - Send node parameter #2500 to XPT.
!--

!
! INCLUDE FILES:
!

library 'XPORTX';

library 'MCBLIB';

library 'NMXPAR';

library 'NMXLIB';

!
! TABLE OF CONTENTS:
!

linkage
    NMX_LKG_CCB = jsr (register = 4),
    NMX_LKG_CCB__VAL = jsr (register = 4; register = 1),
    NMX_LKG_DB_CCB_BLK = jsr (register = 5, register = 4, register = 2),
    NMX_LKG_DB_CCB_ENT = jsr (register = 5, register = 4, register = 3) :
        nopreserve (4);

forward routine
    BADREQ : MCB_DB_CCB novalue,
    CKTCCP : MCB_DB_CCB novalue,
    CKTREQ : MCB_DB_CCB novalue,
    LINCCP : MCB_DB_CCB novalue,
    LINREQ : MCB_DB_CCB novalue,
    MODCCP : MCB_DB_CCB novalue,
    MODREQ : MCB_DB_CCB novalue,
    NODCCP : MCB_DB_CCB novalue,
    NODREQ : MCB_DB_CCB novalue,
    FORWARD_REQUEST : NMX_LKG_DB_CCB_ENT novalue,
    GET_ENTITY : NMX_LKG_DB_CCB_BLK,
    GET_ENTITY_LIST : NMX_LKG_DB_CCB_BLK novalue,
    NEXT_STATE : NMX_LKG_CCB,
    PARAMETER_NUMBER : NMX_LKG_CCB,
    REQUEST_COMPLETE : NMX_LKG_CCB novalue,
    SET_PARAMETER_NUMBER : NMX_LKG_CCB__VAL;

!
! Literal values
!

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

!
! Externals
!

external
    MCB$GAW_PROCESS_DATA_BASE : vector [2],
    MCB$GW_PROCESS_HANDLE;
global routine BADREQ (NMXDB, CCB) : MCB_DB_CCB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!    Complete an I/O function by returning NE$URC to the user for this IOP.
!
! FORMAL PARAMETERS:
!
!       RIOP - I/O Packet
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!
!        I/O Packet is returned to the user.
!--

    begin

    map
        CCB : ref NMX_CCB_BLOCK,
	NMXDB : ref NMXDB_BLOCK;

!
! Complete I/O request with IE_BAD
!
    CCB [C_STS] = $NM$ERR_URC;
    $NMX_RETURN_NMX_CCB (.CCB);
    end;					!End of BADREQ
global routine CKTCCP (NMXDB, CCB) : MCB_DB_CCB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
!
! FORMAL PARAMETERS:
!
!	NMXDB - NMX Process Database
!	CCB   - The CCB to us
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	None
!
! SIDE EFFECTS:
!
!	None
!--

    begin

    map
	NMXDB : ref NMXDB_BLOCK,
	CCB : ref NMX_CCB_BLOCK;

    local
	CKTBLK : ref NMX_CIRCUIT_BLOCK;

!
! Setup our data structure pointers and process based upon the
! Network Management Function Code.
!

    CKTBLK = GET_ENTITY (NMXDB [NMX_BASE], .CCB, NMXDB [NMX_CIRCUITS]);
    REQUEST_COMPLETE (.CCB);
    CCB [C_NMX_STATE] = NEXT_STATE (.CCB);

    if .CCB [C_NMX_STATE] eql ST$DON
    then
        begin

        local
            VALUE;

        selectone SET_PARAMETER_NUMBER (.CCB; VALUE) of
            set
            [0] :                   ! Track STATE
                CKTBLK [LINK_STATE] = .VALUE;
            [otherwise] :
                0;
            tes;

        end;

    FORWARD_REQUEST (NMXDB [NMX_BASE], .CCB, .CKTBLK);
    end;					!of CKTCCP
global routine CKTREQ (NMXDB, CCB) : MCB_DB_CCB  novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!    Process the I/O Packet dispatched to us by NMX. Convert it to a CCB and
!    start processing the request.
!
! FORMAL PARAMETERS:
!
!	CCB - 
!
! IMPLICIT INPUTS:
!
!	Miscellaneous NMXDB items
!
! IMPLICIT OUTPUTS:
!
!	Miscellaneous NMXDB items
!
! ROUTINE VALUE:
!
!	None
!
! SIDE EFFECTS:
!
!	None
!--

    begin

    map
	CCB : ref NMX_CCB_BLOCK,
	NMXDB : ref NMXDB_BLOCK;

!
!  If the function is N$FRET we process it directly.
!  If any other function Obtain the appropriate
!   CIRCUIT Block from our data base.
!

    if .CCB [C_NM_FUNC] neq NMX$FNC_ret
    then
        begin

        local
            CKTBLK : ref NMX_CIRCUIT_BLOCK;

        CKTBLK = GET_ENTITY (NMXDB [NMX_BASE], .CCB, NMXDB [NMX_CIRCUITS]);
!
! We have a CIRCUIT Entity block which matches the Entity-Id. Determine
! processing based upon the Network Management Function Code.
!
        begin

        literal
            STATE_SERVICE = 2;

        local
            VALUE;

        selectone SET_PARAMETER_NUMBER (.CCB; VALUE) of
            set
            [0] :                   ! Verify STATE
                selectone .VALUE of
                    set
                    [STATE_SERVICE] :
                        begin
                        CCB [C_STS] = $NM$ERR_IPV;
                        CCB [C_NMX_STATE] = ST$DON;
                        end;
                    [otherwise] :
                        0;
                    tes;
            [otherwise] :
                0;
            tes;

        end;
        CCB [C_NMX_STATE] = NEXT_STATE (.CCB);
        FORWARD_REQUEST (NMXDB [NMX_BASE], .CCB, .CKTBLK);
        end
    else
        GET_ENTITY_LIST (NMXDB [NMX_BASE], .CCB, NMXDB [NMX_CIRCUITS]);

    end;					!of CKTREQ
global routine LINCCP (NMXDB, CCB) : MCB_DB_CCB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!    Process LINE Control Completes; Essentially terminate I/O requests.
!
! FORMAL PARAMETERS:
!
!	NMXDB - NMX Process Database
!	CCB   - The CCB to us
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	None
!
! SIDE EFFECTS:
!
!	None
!--

    begin

    map
	NMXDB : ref NMXDB_BLOCK,
	CCB : ref NMX_CCB_BLOCK;

    local
	LINBLK : ref NMX_LINE_BLOCK;

!
! Setup our data structure pointers and process based upon the
! Network Management Function Code.
!

    LINBLK = GET_ENTITY (NMXDB [NMX_BASE], .CCB, NMXDB [NMX_LINES]);
    REQUEST_COMPLETE (.CCB);
    CCB [C_NMX_STATE] = NEXT_STATE (.CCB);

    if .CCB [C_NMX_STATE] eql ST$DON
    then
        begin

        local
            VALUE;

        selectone SET_PARAMETER_NUMBER (.CCB; VALUE) of
            set
            [0] :                   ! Track STATE
                LINBLK [LINK_STATE] = .VALUE;
            [1120] :                ! Track SERVICE TIMER
                begin

                local
                    CKTBLK : ref NMX_CIRCUIT_BLOCK;

                CKTBLK = GET_ENTITY (NMXDB [NMX_BASE], .CCB, NMXDB [NMX_CIRCUITS]);

                if .CKTBLK neqa 0
                then
                    CKTBLK [CIRCUIT_SERVICE_TIMER] = .VALUE/1000;

                end;
            [otherwise] :
                0;
            tes;

        end;

    FORWARD_REQUEST (NMXDB [NMX_BASE], .CCB, .LINBLK);
    end;					!of LINCCP
global routine LINREQ (NMXDB, CCB) : MCB_DB_CCB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Convert RSX I/O operation to MCB operation
!	on LINE Entities.
!
! FORMAL PARAMETERS:
!
!	IOP - I/O Packet
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	None
!
! SIDE EFFECTS:
!
!	None
!--

    begin

    map
	CCB : ref NMX_CCB_BLOCK,
	NMXDB : ref NMXDB_BLOCK;

!
!  If the function is N$FRET we process it directly.
!  If any other function Obtain the appropriate
!   LINE Block from our data base.
!

    if .CCB [C_NM_FUNC] neq NMX$FNC_ret
    then
        begin

        local
            LINBLK : ref NMX_LINE_BLOCK;

        LINBLK = GET_ENTITY (NMXDB [NMX_BASE], .CCB, NMXDB [NMX_LINES]);

!
! We have a LINE Entity block which matches the Entity-Id. Determine
! processing based upon the Network Management Function Code.
!
        begin

        literal
            STATE_SERVICE = 2;

        local
            VALUE;

        selectone SET_PARAMETER_NUMBER (.CCB; VALUE) of
            set
            [0] :                   ! Verify STATE
                selectone .VALUE of
                    set
                    [STATE_SERVICE] :
                        begin
                        CCB [C_STS] = $NM$ERR_IPV;
                        CCB [C_NMX_STATE] = ST$DON;
                        end;
                    [otherwise] :
                        0;
                    tes;
            [otherwise] :
                0;
            tes;

        end;
        CCB [C_NMX_STATE] = NEXT_STATE (.CCB);
        FORWARD_REQUEST (NMXDB [NMX_BASE], .CCB, .LINBLK);
        end
    else
        GET_ENTITY_LIST (NMXDB [NMX_BASE], .CCB, NMXDB [NMX_LINES]);

    end;					!of LINREQ
global routine MODCCP (NMXDB, CCB) : MCB_DB_CCB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!    Process MODULE Control Completes; Essentially terminate I/O requests.
!
! FORMAL PARAMETERS:
!
!	NMXDB - NMX Process Database
!	CCB   - The CCB to us
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	None
!
! SIDE EFFECTS:
!
!	None
!--

    begin

    map
	NMXDB : ref NMXDB_BLOCK,
	CCB : ref NMX_CCB_BLOCK;

    local
	MODBLK : ref NMX_MODULE_BLOCK;

!
! Setup our data structure pointers and process based upon the
! Network Management Function Code.
!

    MODBLK = GET_ENTITY (NMXDB [NMX_BASE], .CCB, NMXDB [NMX_MODULES]);
    REQUEST_COMPLETE (.CCB);
    CCB [C_NMX_STATE] = NEXT_STATE (.CCB);
    FORWARD_REQUEST (NMXDB [NMX_BASE], .CCB, .MODBLK);
    end;					!of MODCCP
global routine MODREQ (NMXDB, CCB) : MCB_DB_CCB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Convert RSX I/O operation to MCB operation
!	on MODULE Entities.
!
! FORMAL PARAMETERS:
!
!	IOP - I/O Packet
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	None
!
! SIDE EFFECTS:
!
!	None
!--

    begin

    map
	CCB : ref NMX_CCB_BLOCK,
	NMXDB : ref NMXDB_BLOCK;

!
!  If the function is N$FRET we process it directly.
!  If any other function Obtain the appropriate
!   MODULE Block from our data base.
!

    if .CCB [C_NM_FUNC] neq NMX$FNC_ret
    then
        begin

        local
            MODBLK : ref NMX_MODULE_BLOCK;

        MODBLK = GET_ENTITY (NMXDB [NMX_BASE], .CCB, NMXDB [NMX_MODULES]);
!
! We have a LINE Entity block which matches the Entity-Id. Determine
! processing based upon the Network Management Function Code.
!
        CCB [C_NMX_STATE] = NEXT_STATE (.CCB);
        FORWARD_REQUEST (NMXDB [NMX_BASE], .CCB, .MODBLK);
        end
    else
        GET_ENTITY_LIST (NMXDB [NMX_BASE], .CCB, NMXDB [NMX_MODULES]);

    end;					!of MODREQ
global routine NODCCP (NMXDB, CCB) : MCB_DB_CCB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Process Control-Completes associated with NODE
!	Entities. Either complete the I/O request or
!	issue another CCB to advance state.
!
! FORMAL PARAMETERS:
!
!	NMXDB - NMX Process Database
!	CCB   - The CCB to us
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	None
!
! SIDE EFFECTS:
!
!	A CCB may be sent out for another round.
!--

    begin

    map
	NMXDB : ref NMXDB_BLOCK,
	CCB : ref NMX_CCB_BLOCK;

    REQUEST_COMPLETE (.CCB);
    CCB [C_NMX_STATE] = NEXT_STATE (.CCB);

    if .CCB [C_NMX_STATE] eql ST$DON
    then
        begin

        local
            NODE_NUMBER,
            VALUE;

        begin

        bind
            NMPAR = .CCB [C_NM_NMPAR] : block field (NMX_NMPAR_FIELDS);

        byt$string_short (byt$ptr (NMPAR [NMX_NMPAR_ENTITY]), NODE_NUMBER);
        end;

        selectone SET_PARAMETER_NUMBER (.CCB; VALUE) of
            set
            [500] :                     ! Track NAME
                selectone .NODE_NUMBER of
                    set
                    [0, .NMXDB [NMX_EXECUTOR_NUMBER]] :
                        begin
                        VALUE = .VALUE<0, 8> + 1;
                        $MCB_MOVE_BUFFER_TO_BUFFER (.VALUE, (.CCB [C_BIAS], .CCB [C_ADDR]),
                                                    byt$ptr (NMXDB [NMX_EXECUTOR_NAME]));
                        end;
                    [otherwise] :
                        0;
                    tes;
            [502] :                     ! Track ADDRESS
                begin
                NMXDB [NMX_EXECUTOR_NUMBER] = .VALUE;
                %(how do we get the name ?)%
                end;
            [otherwise] :
                0;
            tes;

        end;

    FORWARD_REQUEST (NMXDB [NMX_BASE], .CCB, 0);
    end;
global routine NODREQ (NMXDB, CCB) : MCB_DB_CCB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Process RSX I/O Packet for the NODE Entity by setting up a CCB
!	and sending it to appropriate processes.  !  ! FORMAL
! PARAMETERS:
!
!	IOP - I/O Packet
!
! IMPLICIT INPUTS:
!
!	Miscellaneous NMX Data Base Items
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	None
!
! SIDE EFFECTS:
!
!	The IOP completion could be deferred until processing of
!  a CCB completes.
!--

    begin

    map
	CCB : ref NMX_CCB_BLOCK,
	NMXDB : ref NMXDB_BLOCK;

!
! The IOP was successfully converted to a CCB format. Determine processing
! based upon the network management function code.
!

    CCB [C_NMX_STATE] = NEXT_STATE (.CCB);
    FORWARD_REQUEST (NMXDB [NMX_BASE], .CCB, 0);
    end;					! of NODREQ
routine FORWARD_REQUEST (NMXDB, CCB, GENBLK) : NMX_LKG_DB_CCB_ENT novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Set up the next destination for this CCB.
!
! FORMAL PARAMETERS:
!
!	CCB   - The CCB to us
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	None
!
! SIDE EFFECTS:
!
!	A CCB may be sent out for another round.
!--

    begin

    map
	CCB : ref NMX_CCB_BLOCK,
        GENBLK : ref NMX_GENERAL_BLOCK,
	NMXDB : ref NMXDB_BLOCK;

    CCB [C_FNC] = FC_CTL;

    case .CCB [C_NMX_STATE] from ST$LO to ST$HI of
        set
        [ST$SC] :
            CCB [C_NMX_EID] = .NMXDB [NMX_SC_EID];
        [ST$NSP] :
            CCB [C_NMX_EID] = .NMXDB [NMX_NSP_EID];
        [ST$XPT] :
            CCB [C_NMX_EID] = .NMXDB [NMX_XPT_EID];
        [ST$OWN] :
            CCB [C_NMX_EID] = .GENBLK [GENERAL_OWNER_ID];
        [ST$PRO] :
            CCB [C_NMX_EID] = .GENBLK [GENERAL_PROVIDER_ID];
        [inrange] :
            begin
            $NMX_RETURN_NMX_CCB (.CCB);
            return;
            end;
        tes;

    if .CCB [C_NMX_EID] eql 0       ! If no destination
    then                            ! then
        begin                       ! send it back to ourselves.
        case .CCB [C_NM_FUNC] from NMX$FNC_lo to NMX$FNC_hi of
            set
            [NMX$FNC_sho, NMX$FNC_szc, NMX$FNC_ret] :
                CCB [C_CNT] = 0;
            [inrange] :
                0;
            tes;
        CCB [C_FNC] = FC_CCP;
        CCB [C_PIX] = .MCB$GW_PROCESS_HANDLE;
        end;

    $MCB_SCHEDULE_CCB (.CCB);
    end;
routine GET_ENTITY (NMXDB, CCB, ENTBLK) : NMX_LKG_DB_CCB_BLK =

!++
! FUNCTIONAL DESCRIPTION:
!
!    Get the entity block for the entity in NMPAR.
!
! FORMAL PARAMETERS:
!
!    .CCB - address of the formatted CCB
!
! IMPLICIT INPUTS:
!
!    Misc GENERAL_BLOCK items
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!       Address of entity block descriptor
!
! SIDE EFFECTS:
!
!       None
!
!--

    begin

    map
	CCB : ref NMX_CCB_BLOCK,
        ENTBLK : ref vector,
	NMXDB : ref NMXDB_BLOCK;

    label
        LOOK_FOR_ENTITY;

    bind
        NMPAR = .CCB [C_NM_NMPAR] : block field (NMX_NMPAR_FIELDS);

LOOK_FOR_ENTITY:
    begin

    local
	ENTCNT,
	ENTADR : ref NMX_GENERAL_BLOCK;

    MAP$ (.ENTBLK [0]);
    ENTBLK = ENTBLK [1];	%(to force auto-increment)%
    ENTADR = .ENTBLK [0];
    ENTBLK = ENTBLK [1];	%(to force auto-increment)%
    if .ENTADR eqla 0 then leave LOOK_FOR_ENTITY;
    ENTCNT = .ENTBLK [0];
    ENTBLK = ENTBLK [1];	%(to force auto-increment)%
    if .ENTCNT eql 0 then leave LOOK_FOR_ENTITY;
!
! Search through Entity BLOCKs looking for a matching one.
!

    do
	begin

        if ch$eql (.ENTADR [GENERAL_NAME_LENGTH] + 1,
                   byt$ptr (ENTADR [GENERAL_NAME]),
                   .ENTADR [GENERAL_NAME_LENGTH] + 1,
                   byt$ptr (NMPAR [NMX_NMPAR_ENTITY]))
        then return .ENTADR;

	ENTADR = .ENTADR + .ENTBLK [0];
	end
    while (ENTCNT = .ENTCNT - 1) neq 0;

    end;
    CCB [C_STS] = $NM$ERR_URC;
    CCB [C_NMX_STATE] = ST$DON;
    return 0
    end;					!of GET_ENTITY
routine GET_ENTITY_LIST (NMXDB, CCB, ENTBLK) : NMX_LKG_DB_CCB_BLK novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!    Return to the buffer pointed to by the CCB the entire list of
!    Entities in this data base.
!
! FORMAL PARAMETERS:
!
!    .CCB - address of the formatted CCB
!    .ENTBLK - address of entity block descriptor
!
! IMPLICIT INPUTS:
!
!    Misc GENERAL_BLOCK items
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!       None
!
! SIDE EFFECTS:
!
!       None
!
!--

    begin

    map
	CCB : ref NMX_CCB_BLOCK,
	ENTBLK : ref NMX_ENTITY_BLOCK,
	NMXDB : ref NMXDB_BLOCK;

    local
        APR6,
	GENBLK : ref block field (NMX_GENERAL_FIELDS, NMX_LINK_FIELDS),
        SELECTOR;

    macro
        $return =
            begin
            MAP$ (.APR6);
            $NMX_RETURN_NMX_CCB (.CCB);
            return
            end %;

!
! Setup to loop through all Entity items
!
    SMAP$ (APR6);
    MAP$ (.ENTBLK [NMX_ENTITY_BLOCK_BIAS]);
    CCB [C_NMX_STATE] = ST$DON;
    CCB [C_STS] = $NM$ERR_OCM;
    SELECTOR = 0;
    if .CCB [C_NM_SELECT] eql NMX$SEL_act then SELECTOR = not .SELECTOR;
    GENBLK = .ENTBLK [NMX_ENTITY_BLOCK_ADDRESS];    ! Start scanning here
!
! Loop through all GENERAL_BLOCKS writing the IDs to the user buffer.
!

    decru CNT from .ENTBLK [NMX_ENTITY_BLOCK_ENTRIES] to 1
    do
	begin

	local
	    LENGTH;

	LENGTH = .GENBLK [GENERAL_NAME_LENGTH];	    ! Length of string is first byte

        if (.LENGTH neq 0) and
           ((.SELECTOR eql 0) or
            (selectone .GENBLK [LINK_STATE] of
                 set
                 [LINK_ON, LINK_SERVICE] :
                     true;          ! Only links in ON or SERVICE state
                 [otherwise] :
                     false;         ! otherwise pass this one by.
                 tes))
	then
	    begin
	    LENGTH = .LENGTH + 1;	! Determine whether next ID fits

	    if (CCB [C_CNT] = .CCB [C_CNT] - .LENGTH) lss 0 then $return;

	    $MCB_MOVE_BUFFER_TO_BUFFER (.LENGTH, byt$ptr (GENBLK [GENERAL_NAME]), (.CCB [C_BIAS], .CCB [C_ADDR]));
	    CCB [C_ADDR] = ch$plus (.CCB [C_ADDR], .LENGTH);
            CCB [C_NMX_CNT] = .CCB [C_NMX_CNT] + .LENGTH;
	    end;

	GENBLK = .GENBLK + .ENTBLK [NMX_ENTITY_BLOCK_LENGTH];
	end;

    CCB [C_STS] = $NM$_SUC;
    $return;
    end;					!of GET_ENTITY_LIST
routine NEXT_STATE (CCB) : NMX_LKG_CCB =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Set up the next destination for this CCB.
!
! FORMAL PARAMETERS:
!
!	CCB   - The CCB to us
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	Next state
!
! SIDE EFFECTS:
!
!	None
!--

    begin

    map
	CCB : ref NMX_CCB_BLOCK;

    literal
        ST$BAD = ST$DON;

    bind
        ENTITY = .CCB [C_NM_ENTITY],
        FUNCTION = .CCB [C_NM_FUNC],
        SELECTOR = .CCB [C_NM_SELECT],
        STATE = .CCB [C_NMX_STATE];

    case ENTITY from NMX$ENT_lo to NMX$ENT_hi of
        set
        [NMX$ENT_nod] :
            !
            ! [Session Control] -> [NSP] -> [Transport] -> Done
            !
            case FUNCTION from  NMX$FNC_lo to NMX$FNC_hi of
                set
                [NMX$FNC_sho] :
                    case STATE from ST$LO to ST$HI of
                        set
                        [ST$INI] :
                            ST$SC;
                        [ST$SC] :
                            ST$NSP;
                        [ST$NSP] :
                            ST$XPT;
                        [ST$XPT] :
                            ST$DON;
                        [inrange] :
                            ST$BAD;
                        tes;
                [NMX$FNC_set, NMX$FNC_clr] :
                    case STATE from ST$LO to ST$HI of
                        set
                        [ST$INI] :
                            selectone PARAMETER_NUMBER (.CCB) of
                                set
                                [700 to 799] :
                                    ST$NSP;
                                [900 to 999, 2500] :
                                    ST$XPT;
                                [otherwise] :
                                    ST$SC;
                                tes;
                        [inrange] :
                            ST$DON;
                        tes;
                [NMX$FNC_zro, NMX$FNC_szc] :
                    case STATE from ST$LO to ST$HI of
                        set
                        [ST$INI] :
                            ST$NSP;
                        [ST$NSP] :
                            ST$XPT;
                        [ST$XPT] :
                            ST$DON;
                        [inrange] :
                            ST$BAD;
                        tes;
                [NMX$FNC_ret] :
                    case SELECTOR from NMX$SEL_lo to NMX$SEL_hi of
                        set
                        [NMX$SEL_kno] :
                            case STATE from ST$LO to ST$HI of
                                set
                                [ST$INI] :
                                    ST$XPT;
                                [ST$XPT] :
                                    ST$SC;
                                [ST$SC] :
                                    ST$DON;
                                [inrange] :
                                    ST$BAD;
                                tes;
                        [NMX$SEL_act] :
                            case STATE from ST$LO to ST$HI of
                                set
                                [ST$INI] :
                                    ST$XPT;
                                [ST$XPT] :
                                    ST$DON;
                                [inrange] :
                                    ST$BAD;
                                tes;
                        [NMX$SEL_lop] :
                            case STATE from ST$LO to ST$HI of
                                set
                                [ST$INI] :
                                    ST$SC;
                                [ST$SC] :
                                    ST$DON;
                                [inrange] :
                                    ST$BAD;
                                tes;
                        [inrange] :
                            ST$BAD;
                        tes;
                [inrange] :
                    ST$BAD;
                tes;
        [NMX$ENT_lin] :
            !
            ! [Owner] -> [Provider] -> Done
            !
            case FUNCTION from NMX$FNC_lo to NMX$FNC_hi of
                set
                [NMX$FNC_sho] :
                    case SELECTOR from NMX$SEL_lo to NMX$SEL_hi of
                        set
                        [NMX$SEL_sta, NMX$SEL_sum] :
                            case STATE from ST$LO to ST$HI of
                                set
                                [ST$INI] :
                                    ST$OWN;
                                [ST$OWN] :
                                    ST$PRO;
                                [ST$PRO] :
                                    ST$DON;
                                [inrange] :
                                    ST$BAD;
                                tes;
                        [inrange] :
                            case STATE from ST$LO to ST$HI of
                                set
                                [ST$INI] :
                                    ST$PRO;
                                [ST$PRO] :
                                    ST$DON;
                                [inrange] :
                                    ST$BAD;
                                tes;
                        tes;
                [NMX$FNC_set, NMX$FNC_clr] :
                    case STATE from ST$LO to ST$HI of
                        set
                        [ST$INI] :
                            selectone PARAMETER_NUMBER (.CCB) of
                                set
                                [0] :
                                    ST$OWN;
                                [otherwise] :
                                    ST$PRO;
                                tes;
                        [ST$OWN] :
                            ST$DON;
                        [ST$PRO] :
                            ST$DON;
                        [inrange] :
                            ST$BAD;
                        tes;
                [NMX$FNC_zro, NMX$FNC_szc] :
                    case STATE from ST$LO to ST$HI of
                        set
                        [ST$INI] :
                            ST$OWN;
                        [ST$OWN] :
                            ST$PRO;
                        [ST$PRO] :
                            ST$DON;
                        [inrange] :
                            ST$BAD;
                        tes;
                [inrange] :
                    ST$BAD;
                tes;
        [NMX$ENT_ckt] :
            !
            ! [Session Control] -> [Owner] -> [Provider] -> Done
            !
            case FUNCTION from NMX$FNC_lo to NMX$FNC_hi of
                set
                [NMX$FNC_sho] :
                    case STATE from ST$LO to ST$HI of
                        set
                        [ST$INI] :
                            ST$SC;
                        [ST$SC] :
                            ST$OWN;
                        [ST$OWN] :
                            ST$PRO;
                        [ST$PRO] :
                            ST$DON;
                        [inrange] :
                            ST$BAD;
                        tes;
                [NMX$FNC_set, NMX$FNC_clr] :
                    case STATE from ST$LO to ST$HI of
                        set
                        [ST$INI] :
                            selectone PARAMETER_NUMBER (.CCB) of
                                set
                                [1000 to 1500] :
                                    ST$PRO;
                                [otherwise] :
                                    ST$OWN;
                                tes;
                        [ST$OWN] :
                            ST$DON;
                        [ST$PRO] :
                            ST$DON;
                        [inrange] :
                            ST$BAD;
                        tes;
                [NMX$FNC_zro, NMX$FNC_szc] :
                    case STATE from ST$LO to ST$HI of
                        set
                        [ST$INI] :
                            ST$OWN;
                        [ST$OWN] :
                            ST$PRO;
                        [ST$PRO] :
                            ST$DON;
                        [inrange] :
                            ST$BAD;
                        tes;
                [inrange] :
                    ST$BAD;
                tes;
        [NMX$ENT_mod] :
            !
            ! [Provider] -> Done
            !
            case STATE from ST$LO to ST$HI of
                set
                [ST$INI] :
                    ST$PRO;
                [ST$PRO] :
                    ST$DON;
                [inrange] :
                    ST$BAD;
                tes;
        [inrange] :
            ST$BAD;
        tes

    end;
routine PARAMETER_NUMBER (CCB) : NMX_LKG_CCB =

!++
! FUNCTIONAL DESCRIPTION:
!
!       Get the number of the parameter being set/cleared
!
! FORMAL PARAMETERS:
!
!	None
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	None
!
! SIDE EFFECTS:
!
!	None
!--

    begin

    map
	CCB : ref NMX_CCB_BLOCK;

    stacklocal
        PARNUM,
        SAVE_MAP;

    PARNUM = -1;
    SMAP$ (SAVE_MAP);

    if .CCB [C_CNT] gtr 0
    then
        begin

        local
            PTR;

        MAP$ (.CCB [C_BIAS]);
        PTR = .CCB [C_ADDR];
        byt$string_short (PTR, PARNUM);
        end;

    MAP$ (.SAVE_MAP);
    .PARNUM
    end;					!of PARAMETER_NUMBER
routine REQUEST_COMPLETE (CCB) : NMX_LKG_CCB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Process function completion
!
! FORMAL PARAMETERS:
!
!	CCB   - The CCB to us
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	None
!
! SIDE EFFECTS:
!
!	None
!--

    begin

    map
	CCB : ref NMX_CCB_BLOCK;

    if .CCB [C_STS] neq $NM$_SUC then CCB [C_NMX_STATE] = ST$DON;

    !
    ! Update buffer ptr/cnt for returned data
    !
    case .CCB [C_NM_FUNC] from NMX$FNC_lo to NMX$FNC_hi of
	set
	[NMX$FNC_sho, NMX$FNC_szc] :
	    begin
            bind
                IOP = .CCB [C_NMX_IOP] : NMX_IOP_BLOCK;
	    CCB [C_NMX_CNT] = .CCB [C_NMX_CNT] + .CCB [C_CNT];
	    CCB [C_ADDR] = ch$plus (.CCB [C_ADDR], .CCB [C_CNT]);
	    CCB [C_CNT] = .IOP [I_NMX_CNT] - .CCB [C_NMX_CNT];
	    end;
	[NMX$FNC_ret] :
	    begin
            bind
                IOP = .CCB [C_NMX_IOP] : NMX_IOP_BLOCK,
                NMPAR = .CCB [C_NM_NMPAR] : block field (NMX_NMPAR_FIELDS);
            CCB [C_NMX_CNT] = .CCB [C_CNT];
            NMPAR [NMX_NMPAR_RETURN_CNT] = .CCB [C_CNT];
            CCB [C_ADDR] = .IOP [I_NMX_ADDR];   ! TEMPORARY for XPT
	    CCB [C_CNT] = .IOP [I_NMX_CNT];
	    end;
	[inrange] :
            0;
	tes;

    end;
routine SET_PARAMETER_NUMBER (CCB; VALUE) : NMX_LKG_CCB__VAL =

!++
! FUNCTIONAL DESCRIPTION:
!
!       Get the number of the parameter being set/cleared
!
! FORMAL PARAMETERS:
!
!	None
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	None
!
! SIDE EFFECTS:
!
!	None
!--

    begin

    map
	CCB : ref NMX_CCB_BLOCK;

    macro
        $return =
            begin
            MAP$ (.SAVE_MAP);
            return .PARNUM
            end %;

    stacklocal
        PARNUM,
        SAVE_MAP;

    PARNUM = -1;
    SMAP$ (SAVE_MAP);

    if .CCB [C_NM_FUNC] neq NMX$FNC_set then $return;

    if .CCB [C_STS] neq $NM$_SUC then $return;

    if .CCB [C_CNT] eql 0 then $return;

    begin

    local
        PTR;

    MAP$ (.CCB [C_BIAS]);
    PTR = .CCB [C_ADDR];
    byt$string_short (PTR, PARNUM);
    byt$string_short (PTR, VALUE);
    end;
    MAP$ (.SAVE_MAP);
    .PARNUM
    end;					!of SET_PARAMETER_NUMBER

end

eludom
! Local Modes:
! Comment Column:36
! Comment Start:!
! Mode:BLISS
! Auto Save Mode:2
! End: