Google
 

Trailing-Edge - PDP-10 Archives - TOPS-20_V6.1_DECnetSrc_7-23-85 - mcb/nmx/nmxdle.bli
There is 1 other file named nmxdle.bli in the archive. Click here to see a list.
module NMXDLE (					! Direct Line Access Processor
		ident = 'X01090'
		) =
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:
!
!	This module provides access to the line
!	protocol level for LOOP LINE/CIRCUIT or
!	LOAD/DUMP Network Management Operations.
!
! ENVIRONMENT: MCB V3.0
!
! AUTHOR: Scott G. Robinson	CREATION DATE: 12-OCT-80
!
! MODIFIED BY:
!
! 01 - Update to MCB V3.2 Naming Conventions
! 02 - Implement MCB DLL interface
! 03 - Code compression
! 04 - Fix a dot bug Al Peckham found
! 05 - Change line/circuit references to common link block
! 06 - Add support for data link watcher.
!       Alan D. Peckham, 14-Apr-82
! 07 - Complete rework of NM support.
! 08 - Fix return of LUNBLK in DLXCCP.
! 09 - Disallow DLX_OPEN when NMX$FLG_maintenance_allowed is not on.
!--

!++
! The DLX Support Routines use the following state machine:
!
! Routine DLXIOP:
!
!   OPEN
!
!   |Validate LUN, Assign Entity| failed
!   |Allocate LUN_BLOCK         |------------> Deassign Entity, Deallocate
!              |                               LUN_BLOCK, fail IOP
!              |
!   |Send Stop to Entity Owner  |
!              |
!              | CCP/STP (DLXCCP state DLX_STOP_OWNER)
!              |
!   |Request Entity to Provider |
!              |
!              | CCP/STR (DLXCCP state DLX_REQUEST_ENTITY)
!              |
!   |                           | Failed ---> Start Owner then Backout
!   !Enter Maint to Provider    |
!              |
!              | XCP/x (DLXXCP state DLX_ENTER_MAINT)
!              |
!   |                           | Failed --> Release Entity then Backout
!   |Complete IOP Successfully  |
!
!
!  CLOSE
!
!   |Validate LUN, LUN_BLOCK    | Failed --> fail IOP
!   |Return all RCP CCBs        |
!   |Fail RCV IOPs              |
!   |Stop Protocol              |
!              |
!              | XCP/x (DLXCCP state DLX_STOP_PROTOCOL)
!              |
!   |Release Entity             |
!              |
!              | CCP/STP (DLXCCP state DLX_RELEASE_ENTITY)
!              |
!   |Start Owner                |
!              |
!              | CCP/STR (DLXCCP state DLX_START_OWNER)
!              |
!   |Deassign Entity            |
!   |Deallocate LUN_BLOCK       |
!   |Unlock LUN                 |
!   |Complete IOP               |
!
!
!  TRANSMIT
!
!   |Validate LUN, LUN_BLOCK    | Failed --> fail IOP
!   |Allocate CCB               |
!              |
!   |Transmit Buffer            |
!              |
!              | XCP/x (DLXXCP state DLX_TRANSMIT)
!              |
!   |Deallocate CCB             |
!   |Complete IOP based on C.STS|
!
!
!  RECEIVE
!
!   |Validate LUN, LUN_BLOCK    |
!   |Queue RCV IOP              |
!   |Try to match IOPs with RCPs|
!
!
! DLXRCP
!
!   |Validate LUN_BLOCK         | failed --> crash
!   |Queue RCP CCB              |
!   |Try to match RCVs with RCPs|
!
!
! DLXAST
!
!   |Validate LUN_BLOCK         | failed --> return CCB
!   |Set appropriate Error Code |
!   |Try to complete a RCV IOP  |
!   !Return CCB                 |
!
!--

!
! INCLUDE FILES:
!

library 'XPORTX';

library 'MCBLIB';

library 'NMXPAR';

library 'NMXLIB';

require 'DLLLIB';

require 'DLXPAR';

!
! TABLE OF CONTENTS:
!

forward routine
    DLXAST : MCB_DB_CCB_MOD novalue,
    DLXCCP : MCB_DB_CCB novalue,
    DLXCON : NMX$LKG_UCB_IOP novalue,   ! Process IOP Connect
    DLXCTL : MCB_DB_CCB_MOD novalue,
    DLXDSC : NMX$LKG_UCB_IOP novalue,   ! Process IOP Disconnect
    DLXRCP : MCB_DB_CCB_MOD novalue,
    DLXRCV : NMX$LKG_UCB_IOP novalue,   ! Process IOP Receive
    DLXXCP : MCB_DB_CCB_MOD novalue,
    DLXXMT : NMX$LKG_UCB_IOP novalue,   ! Process IOP Transmit
    ALLOCATE_LUNBLK,                    ! Allocate LUNBLK and initialize
    EXTRACT_LUNBLK,                     ! Extract a LUNBLK by ID
    FIND_LUNBLK,                        ! Find a LUNBLK by ID
    TRY_SOME_RCVS : novalue;            ! Try matching IOPs with Buffers

!
! Link STATE values
!

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

!
! Link SUBSTATE values
!

literal
    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 SERVICE values
!

literal
    LINK_ENABLED = 0,
    LINK_DISABLED = 1;

!
! External routines
!
external
    MCB$GAW_PROCESS_DATA_BASE : vector [2];
global routine DLXAST (NMXDB, CCB, FCM) : MCB_DB_CCB_MOD novalue = 	! Process Asynchronous notifications

!++
! FUNCTIONAL DESCRIPTION:
!
!
!
! FORMAL PARAMETERS:
!
!	None
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	None
!
! SIDE EFFECTS:
!
!	None
!--

    begin

    map
	NMXDB : ref NMXDB_BLOCK,
	CCB : ref block field (C_FIELDS);

    local
	LUNBLK : ref DLX_LUN_BLOCK;

!
! Find our LUN_BLOCK
!

    if (LUNBLK = FIND_LUNBLK (.CCB [C_LIN])) eql 0
    then
	SIGNAL_STOP (NMX$_ICP, .CCB, 0)
    else

	if (.LUNBLK [LUN_STATE] eql LUN_OPENED) and (.LUNBLK [LUN_RCV_ERROR] eql 0)
	then
	    begin

	    selectone .FCM of
		set
		[DLL$K_PERSISTENT_ERROR] :
		    LUNBLK [LUN_RCV_ERROR] = (selectone .CCB [C_STS] of
			set
			[DLL$_START_RECEIVED] : IE$EOT;
			[DLL$_MAINTENANCE_RECEIVED] : 0;
			[otherwise] : IE$BBE;
			tes);
		[otherwise] :       ! What about using state notifications ?
		;
		tes;

	    TRY_SOME_RCVS (.LUNBLK);
	    end;

    $MCB_RETURN_CCB (.CCB);
    end;					!of DLXAST
global routine DLXCCP (NMXDB, CCB) : MCB_DB_CCB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!    This routine implements the state machine for Direct Line Access
!    functions OPEN and CLOSE. It ensures an orderly transition between
!    NMX and an Entity's Owner.
!
! FORMAL PARAMETERS:
!
!	NMXDB - NMX process Data Base
!       CCB - the CCB which Dispatched us
!
! IMPLICIT INPUTS:
!
!       None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	None
!
! SIDE EFFECTS:
!
!	None
!--

    begin

    map
	NMXDB : ref NMXDB_BLOCK,
	CCB : ref DLX_CCB_BLOCK;

    bind
	LUN_BLOCK = .CCB [C_DLX_LUNBLK] : DLX_LUN_BLOCK,
	ENTBLK = .LUN_BLOCK [LUN_ENTITY_ADDRESS] : block field (NMX_GENERAL_FIELDS, NMX_LINK_FIELDS,
                NMX_CIRCUIT_FIELDS, NMX_LINE_FIELDS);

!
! Dispatch upon current state
!
    MAP$ (.LUN_BLOCK [LUN_ENTITY_BIAS]);

    case .CCB [C_DLX_STATE] from DLX_STATE_LOW to DLX_STATE_HIGH of
	set

	[DLX_STOP_OWNER] :
	    begin
	    CCB [C_DLX_STATE] = DLX_REQUEST_ENTITY;
	    $DLL_REQUEST_CIRCUIT ((.CCB), .ENTBLK [GENERAL_PROVIDER_PIX], .LUN_BLOCK [LUN_ID]);
	    end;

	[DLX_REQUEST_ENTITY] :
	    begin

	    if .CCB [C_STS]
	    then
		begin
		CCB [C_DLX_STATE] = DLX_ENTER_MAINT;
		$DLL_ENTER_MAINTENANCE ((.CCB), .ENTBLK [GENERAL_PROVIDER_PIX]);
		end
	    else
		begin
		LUN_BLOCK [LUN_ERROR_CODE] = IE$CNR;
		CCB [C_DLX_STATE] = DLX_START_OWNER;
		CCB [C_FNC] = FC_CTL;
		CCB [C_MOD] = FM_STR;
		CCB [C_DLX_EID] = .ENTBLK [GENERAL_OWNER_ID];
		$MCB_SCHEDULE_CCB (.CCB);
		end;

	    end;

	[DLX_RELEASE_ENTITY] :
	    begin
	    CCB [C_DLX_STATE] = DLX_START_OWNER;
	    CCB [C_FNC] = FC_CTL;
	    CCB [C_MOD] = FM_STR;
	    CCB [C_DLX_EID] = .ENTBLK [GENERAL_OWNER_ID];
	    $MCB_SCHEDULE_CCB (.CCB);
	    end;

	[DLX_START_OWNER] :
	    begin
	    ENTBLK [LINK_LUN_BLOCK] = 0;
	    ENTBLK [LINK_USER_ID] = .ENTBLK [GENERAL_OWNER_ID];
            begin

            local
                IOP : ref NMX_IOP_BLOCK;

            IOP = .CCB [C_DLX_IOP];
	    (.IOP [I_LN2]) = 0;
	    EXTRACT_LUNBLK (.LUN_BLOCK [LUN_ID]);
	    $NMX_RETURN_RSX_IOP (.IOP, .LUN_BLOCK [LUN_ERROR_CODE], 0);
            end;
	    $MCB_RETURN_DSR (DLX_LUN_ALLOCATION, .CCB [C_DLX_LUNBLK]);
	    $MCB_RETURN_CCB (.CCB);
	    end;

	[inrange, outrange] :
	    SIGNAL_STOP (NMX$_ICP, .CCB, .CCB [C_DLX_STATE]);
	tes;

    end;					!of DLXCCP
global routine DLXCON (UCB, IOP) : NMX$LKG_UCB_IOP novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Process RSX I/O Packets associated with
!	Direct Circuit/Line Access functions.
!
! FORMAL PARAMETERS:
!
!	IOP - the RSX IOP
!
! IMPLICIT INPUTS:
!
!	Misc NMXDB data base items
!
! IMPLICIT OUTPUTS:
!
!	Misc NMXDB data base items
!
! ROUTINE VALUE:
!
!	None
!
! SIDE EFFECTS:
!
!	None
!--

    begin

    map
	IOP : ref NMX_IOP_BLOCK;

    local
	NMXDB : ref NMXDB_BLOCK;

    $MCB_RSX_TO_MCB (.UCB, NMXDB);

!+
! OPEN MCB Entity:
!
!     Basic algorithm is:
!
!     DLXIOP: Validate 2nd LUN word is 0
!             Verify acceptable Network Management service state
!             Allocate the Logical Unit Table
!             Assign the Entity
!             Stop the current Owner
!     DLXCCP: Identify Entity Link
!     DLXCCP: Initialize Maintenance Mode
!     DLXXCP: Complete the IOP
!-
	    begin

	    local
		CCB : ref DLX_CCB_BLOCK,
		ERROR_CODE,
		LUNBLK : ref DLX_LUN_BLOCK,
		ENTBLK : ref block field (NMX_GENERAL_FIELDS, NMX_LINK_FIELDS, NMX_CIRCUIT_FIELDS, NMX_LINE_FIELDS);

	    if .(.IOP [I_LN2]) neq 0
	    then
		begin

		local
		    UCB;

		$MCB_MCB_TO_RSX (.NMXDB, UCB);
		IOFIN$ (.UCB, .IOP, IE$ALN, 0);
		return
		end;

	    if not $NMX_GET_NMX_CCB (.IOP, CCB)
	    then
		return
	    else
!
! The IOP was successfully converted to a CCB format. This
! was done to allow ease of ENTITY lookup. The NMPAR block
! will be thrown away and the CCB reformatted for DLX usage.
!
		begin
                begin

                map
                    CCB : ref NMX_CCB_BLOCK;

		bind
		    NMPAR = CCB [C_NM_NMPAR] : ref NMX_NMPAR_BLOCK;

		ERROR_CODE = IE$BDV;

		if ((ENTBLK = (selectone .IOP [I_NM_ENTITY] of
			set
			[NMX$ENT_ckt] : $NMX_MAP_ENTITY_ID (.IOP [I_NM_ENTITY], byt$ptr (NMPAR [NMX_NMPAR_ENTITY]));
			[NMX$ENT_lin] : $NMX_MAP_ENTITY_ID (.IOP [I_NM_ENTITY], byt$ptr (NMPAR [NMX_NMPAR_ENTITY]));
			[otherwise] : 0;
			tes)) neqa 0) and
                   (.ENTBLK [GENERAL_NAME_LENGTH] neq 0)
		then
		    ERROR_CODE = (selectone true of
                                  set
                                  [.ENTBLK [LINK_LUN_BLOCK] neq 0]: IE$DAA;
                                  [.ENTBLK [GENERAL_OWNER_ID] eql 0]: IE$BDV;
                                  [.ENTBLK [GENERAL_PROVIDER_ID]  eql 0]: IE$BDV;
                                  [.ENTBLK [LINK_STATE] eql LINK_OFF] : IE$DAA;
                                  [(.ENTBLK [GENERAL_SYSTEM_FLAGS] and NMX$FLG_maintenance_allowed) eql 0]: IE$PRI;
                                  [otherwise]: IS$SUC;
                                  tes);

		$MCB_RETURN_DSR (NMX_NMPAR_ALLOCATION, .CCB [C_NM_NMPAR]);	! Return Allocated Storage
                end;
!
! If the Entity is available and known try to assign it with a LUN_BLOCK
!

		if .ERROR_CODE eql IS$SUC
		then
		    begin			! Successful, try to get LUNBLK

		    if (LUNBLK = ALLOCATE_LUNBLK (.ENTBLK)) eql 0
		    then
			begin

			local
			    UCB;

			$MCB_RETURN_CCB (.CCB);	! Return CCB
			$MCB_MCB_TO_RSX (.NMXDB, UCB);
			IOFIN$ (.UCB, .IOP, IE$NDR, 0);
			return;
			end;

                    %(change state ?)%
		    ENTBLK [LINK_LUN_BLOCK] = .LUNBLK;
		    (.IOP [I_LN2]) = .LUNBLK;
		    CCB [C_DLX_EID] = .ENTBLK [GENERAL_OWNER_ID];
		    CCB [C_FNC] = FC_CTL;
		    CCB [C_MOD] = FM_STP;
		    CCB [C_DLX_STATE] = DLX_STOP_OWNER;
		    CCB [C_DLX_IOP] = .IOP;
		    CCB [C_DLX_LUNBLK] = .LUNBLK;
		    $MCB_SCHEDULE_CCB (.CCB);
		    $MCB_MCB_TO_RSX (.NMXDB);
		    end
		else
		    begin			! Unsuccessful, just return resources and leave

		    local
			UCB;

		    $MCB_RETURN_CCB (.CCB);	! Return CCB
		    $MCB_MCB_TO_RSX (.NMXDB, UCB);
		    IOFIN$ (.UCB, .IOP, .ERROR_CODE, 0);
		    end;

		end;

	    end;

    end;					!of DLXCON
global routine DLXCTL (NMXDB, CCB, FCM) : MCB_DB_CCB_MOD novalue = 	!Process CTLs

!++
! FUNCTIONAL DESCRIPTION:
!
!    This routine fields CTL/NM requests when DLX has a CIRCUIT/LINE
!    assigned.
!
! FORMAL PARAMETERS:
!
!	NMXDB - NMX process Data Base
!       CCB - the CCB which Dispatched us
!       FCM - the contents of C.MOD
!
! IMPLICIT INPUTS:
!
!       None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	None
!
! SIDE EFFECTS:
!
!	None
!--

    begin

    map
	NMXDB : ref NMXDB_BLOCK,
	CCB : ref NMX_CCB_BLOCK;

!
! Validate this is a Network Management Control Request. If not
! hold the show otherwise process it.
!

    if .FCM neq FM_NM then SIGNAL_STOP (NMX$_IFM, .CCB);

    case .CCB [C_NM_FUNC] from NMX$FNC_lo to NMX$FNC_hi of
	set

	[NMX$FNC_ret, NMX$FNC_sho] :    ! Shows complete with nothing
	    begin
	    CCB [C_CNT] = 0;
	    CCB [C_STS] = $NM$_SUC;
	    end;

	[NMX$FNC_set, NMX$FNC_clr, NMX$FNC_zro, NMX$FNC_szc] :
                                        ! Modifications can't be done now
	    CCB [C_STS] = $NM$ERR_CWS;

	[inrange, outrange] : 			! Other items are bugs
	    CCB [C_STS] = $NM$ERR_UFO;
	tes;

!
! Complete the CCB
!
    CCB [C_FNC] = FC_CCP;
    $MCB_SCHEDULE_CCB (.CCB);
    end;					!of DLXCTL
global routine DLXDSC (UCB, IOP) : NMX$LKG_UCB_IOP novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Process RSX I/O Packets associated with
!	Direct Circuit/Line Access functions.
!
! FORMAL PARAMETERS:
!
!	IOP - the RSX IOP
!
! IMPLICIT INPUTS:
!
!	Misc NMXDB data base items
!
! IMPLICIT OUTPUTS:
!
!	Misc NMXDB data base items
!
! ROUTINE VALUE:
!
!	None
!
! SIDE EFFECTS:
!
!	None
!--

    begin

    map
	IOP : ref NMX_IOP_BLOCK;

    local
	NMXDB : ref NMXDB_BLOCK;

    $MCB_RSX_TO_MCB (.UCB, NMXDB);

!+
! CLOSE MCB Entity:
!
!    Basic Algorithm is:
!
!    DLXIOP: Validate 2nd LUN word <> 0
!            Return all RCPs
!            Fail outstanding RCVs
!            Stop Protocol on Entity
!    DLXXCP: Release Entity Link
!    DLXCCP: Start the original Owner
!    DLXCCP: Deassign the Entity
!            Complete the IOP
!-
	    begin

	    local
		LUNBLK : ref DLX_LUN_BLOCK;

	    if (LUNBLK = .(.IOP [I_LN2])) eql 0
	    then
		begin

		local
		    UCB;

		$MCB_MCB_TO_RSX (.NMXDB, UCB);
		IOFIN$ (.UCB, .IOP, IE$NLN, 0);
		end
	    else
		begin

		local
		    NMXDB : ref NMXDB_BLOCK,
		    RCPCCB : ref block field (C_FIELDS),
		    RCVIOP : ref NMX_IOP_BLOCK,
		    CCB : ref DLX_CCB_BLOCK;

		bind
		    ENTBLK = LUNBLK [LUN_ENTITY_ADDRESS] : ref NMX_GENERAL_BLOCK;

		if not $MCB_GET_CCB (CCB)
		then
		    begin

		    local
			UCB;

		    $MCB_MCB_TO_RSX (.NMXDB, UCB);
		    IOFIN$ (.UCB, .IOP, IE$NDR, 0);
		    return;
		    end;

		LUNBLK [LUN_ERROR_CODE] = IS$SUC;
		LUNBLK [LUN_STATE] = LUN_CLOSING;

		while $MCB_DEQUEUE_CCB (LUNBLK [LUN_RCPS], RCPCCB) do
		    begin
		    RCPCCB [C_FNC] = FC_RCE;
		    $MCB_SCHEDULE_CCB (.RCPCCB);
		    end;

		MAP$ (.LUNBLK [LUN_ENTITY_BIAS]);
		CCB [C_DLX_STATE] = DLX_STOP_PROTOCOL;
		CCB [C_DLX_IOP] = .IOP;
		CCB [C_DLX_LUNBLK] = .LUNBLK;
		$DLL_STOP ((.CCB), .ENTBLK [GENERAL_PROVIDER_PIX]);
                begin

                local
                     UCB;

		$MCB_MCB_TO_RSX (.NMXDB,UCB);

		while $NMX_DEQUEUE (LUNBLK [LUN_RCVS], RCVIOP) do
		    IOFIN$ (.UCB, .RCVIOP, IE$ABO, 0);

                end;
		end;

	    end;

    end;					!of DLXDSC
global routine DLXRCP (NMXDB, CCB, FCM) : MCB_DB_CCB_MOD novalue = 	! Process Receives

!++
! FUNCTIONAL DESCRIPTION:
!
!    Data from an OPENED MCB line is dispatched to here. It is passed
!    on to the user if previous RECEIVEs exist otherwise we queue the
!    data CCB.
!
! FORMAL PARAMETERS:
!
!	NMXDB - NMX Process Data Base
!       CCB - the CCB which dispatched us
!       FCM - the FCM from the CCB
!
! IMPLICIT INPUTS:
!
!	Misc NMXDB items
!
! IMPLICIT OUTPUTS:
!
!	Misc NMXDB items
!
! ROUTINE VALUE:
!
!	None
!
! SIDE EFFECTS:
!
!	None
!--

    begin

    map
	NMXDB : ref NMXDB_BLOCK,
	CCB : ref block field (C_FIELDS);

    local
	LUNBLK : ref DLX_LUN_BLOCK;

!
! Intercept service slave requests
!

!   if SERVICE_SLAVE_REQUEST (.CCB) then return;

!
! If there is a LUN_BLOCK then give to user
!

    if (LUNBLK = FIND_LUNBLK (.CCB [C_LIN])) neq 0
    then

	if .LUNBLK [LUN_STATE] eql LUN_OPENED
	then
	    begin
	    $MCB_QUEUE_CCB (LUNBLK [LUN_RCPS], .CCB);
	    TRY_SOME_RCVS (.LUNBLK);
            return;
	    end;

!
! No takers - throw the message away
!

    CCB [C_FNC] = FC_RCE;
    $MCB_SCHEDULE_CCB (.CCB);
    end;					!of NMXRCP
global routine DLXRCV (UCB, IOP) : NMX$LKG_UCB_IOP novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Process RSX I/O Packets associated with
!	Direct Circuit/Line Access functions.
!
! FORMAL PARAMETERS:
!
!	IOP - the RSX IOP
!
! IMPLICIT INPUTS:
!
!	Misc NMXDB data base items
!
! IMPLICIT OUTPUTS:
!
!	Misc NMXDB data base items
!
! ROUTINE VALUE:
!
!	None
!
! SIDE EFFECTS:
!
!	None
!--

    begin

    map
	IOP : ref NMX_IOP_BLOCK;

    local
	NMXDB : ref NMXDB_BLOCK;

    $MCB_RSX_TO_MCB (.UCB, NMXDB);

!+
! RECEIVE a Data Buffer:
!
!    Basic Algorithm is:
!
!    DLXIOP: Validate 2nd LUN word <> 0
!            Validate LUT State is Running
!            Queue RCV IOP
!            Try to Complete RCV IOPs
!-
	    begin

	    local
		LUNBLK : ref DLX_LUN_BLOCK;

	    if (LUNBLK = .(.IOP [I_LN2])) eql 0
	    then
		begin

		local
		    UCB;

		$MCB_MCB_TO_RSX (.NMXDB, UCB);
		IOFIN$ (.UCB, .IOP, IE$NLN, 0);
                return;
		end
	    else
		begin

		local
		    NMXDB : ref NMXDB_BLOCK;

		if .LUNBLK [LUN_STATE] neq LUN_OPENED
		then
		    begin

		    local
			UCB;

		    $MCB_MCB_TO_RSX (.NMXDB, UCB);
		    IOFIN$ (.UCB, .IOP, IE$NLN, 0);
		    return;
		    end;

		if .IOP [I_NMX_CNT] eql 0
		then
		    begin

		    local
			UCB;

		    $MCB_MCB_TO_RSX (.NMXDB, UCB);
		    IOFIN$ (.UCB, .IOP, IE$SPC, 0);
		    return;
		    end;

                if .IOP [I_NMX_ENTITY] eql 0
                then
                    begin

                    local
                        CKTBLK : ref NMX_CIRCUIT_BLOCK,
                        SAVE_MAP;

                    SMAP$ (SAVE_MAP);
                    MAP$ (.LUNBLK [LUN_ENTITY_BIAS]);
                    CKTBLK = .LUNBLK [LUN_ENTITY_ADDRESS];
                    IOP [I_NMX_ENTITY] = .CKTBLK [CIRCUIT_SERVICE_TIMER];
                    MAP$ (.SAVE_MAP);
                    end;

		$NMX_ENQUEUE (LUNBLK [LUN_RCVS], .IOP);
		TRY_SOME_RCVS (.LUNBLK);
		$MCB_MCB_TO_RSX (.NMXDB);
		end;

	    end;

    end;					!of DLXRCV
global routine DLXXCP (NMXDB, CCB, FCM) : MCB_DB_CCB_MOD novalue = 	! Process Transmit Completes

!++
! FUNCTIONAL DESCRIPTION:
!
!    Transmit Completion involves returning the CCB and IOP.
!
! FORMAL PARAMETERS:
!
!    NMXDB - the NMX Process Data Base
!    CCB - the CCB which dispatched us
!    FCM - the functions modifier (ignored)
!
! IMPLICIT INPUTS:
!
!	Misc CCB and NMXDB fields
!
! IMPLICIT OUTPUTS:
!
!	The IOP is returned to the user.
!
! ROUTINE VALUE:
!
!	None
!
! SIDE EFFECTS:
!
!	None
!--

    begin

    map
	NMXDB : ref NMXDB_BLOCK,
	CCB : ref DLX_CCB_BLOCK;

    bind
	LUNBLK = CCB [C_DLX_LUNBLK] : ref DLX_LUN_BLOCK,
	ENTITY_BLOCK = LUNBLK [LUN_ENTITY_ADDRESS] : ref block field (NMX_CIRCUIT_FIELDS, NMX_LINE_FIELDS,
		NMX_LINK_FIELDS, NMX_GENERAL_FIELDS);

!
! Dispatch based upon State
!
    MAP$ (.LUNBLK [LUN_ENTITY_BIAS]);

    case .CCB [C_DLX_STATE] from DLX_STATE_LOW to DLX_STATE_HIGH of
	set

	[DLX_TRANSMIT] :
	    begin
	    LUNBLK [LUN_XMTS] = .LUNBLK [LUN_XMTS] - 1;
	    $NMX_RETURN_RSX_IOP (.CCB [C_DLX_IOP], (if .CCB [C_STS] then IS$SUC else IE$SRE), 0);
	    $MCB_RETURN_CCB (.CCB);		! Return the CCB
	    end;

	[DLX_ENTER_MAINT] :

	    if .CCB [C_STS]
	    then
		begin
		LUNBLK [LUN_STATE] = LUN_OPENED;
		LUNBLK [LUN_ERROR_CODE] = 0;
		ENTITY_BLOCK [LINK_USER_ID] = .NMXDB [NMX_NMX_PIX]^8 or .LUNBLK [LUN_ID];
		$NMX_RETURN_RSX_IOP (.CCB [C_DLX_IOP], IS$SUC, 0);
		$MCB_RETURN_CCB (.CCB);		! Return the CCB
		end
	    else
		begin
		LUNBLK [LUN_ERROR_CODE] = IE$ISQ;
		CCB [C_DLX_STATE] = DLX_RELEASE_ENTITY;
		$DLL_RELEASE_CIRCUIT ((.CCB), .ENTITY_BLOCK [GENERAL_PROVIDER_PIX]);
		end;

	[DLX_STOP_PROTOCOL] :
	    begin
	    CCB [C_DLX_STATE] = DLX_RELEASE_ENTITY;
	    $DLL_RELEASE_CIRCUIT ((.CCB), .ENTITY_BLOCK [GENERAL_PROVIDER_PIX]);
	    end;

	[inrange, outrange] :
	    SIGNAL_STOP (NMX$_ICP, .CCB, .CCB [C_DLX_STATE]);
	tes;

    end;					!of DLXXCP
global routine DLXXMT (UCB, IOP) : NMX$LKG_UCB_IOP novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Process RSX I/O Packets associated with
!	Direct Circuit/Line Access functions.
!
! FORMAL PARAMETERS:
!
!	IOP - the RSX IOP
!
! IMPLICIT INPUTS:
!
!	Misc NMXDB data base items
!
! IMPLICIT OUTPUTS:
!
!	Misc NMXDB data base items
!
! ROUTINE VALUE:
!
!	None
!
! SIDE EFFECTS:
!
!	None
!--

    begin

    map
	IOP : ref NMX_IOP_BLOCK;

    local
	NMXDB : ref NMXDB_BLOCK;

    $MCB_RSX_TO_MCB (.UCB, NMXDB);

!+
! TRANSMIT a Buffer:
!
!    Basic Algorithm is:
!
!    DLXIOP: Validate 2nd LUN word <> 0
!            Validate LUT State is Running
!            Count Transmits to DLL
!            Transmit Buffer
!    DLXXCP: Decrement Transmits to DLL
!            Complete IOP
!-
	    begin

	    local
		LUNBLK : ref DLX_LUN_BLOCK;

	    if (LUNBLK = .(.IOP [I_LN2])) eql 0
	    then
		begin

		local
		    UCB;

		$MCB_MCB_TO_RSX (.NMXDB, UCB);
		IOFIN$ (.UCB, .IOP, IE$NLN, 0);
		end
	    else
		begin

		if .LUNBLK [LUN_STATE] neq LUN_OPENED
		then
		    begin

		    local
			UCB;

		    $MCB_MCB_TO_RSX (.NMXDB, UCB);
		    IOFIN$ (.UCB, .IOP, IE$NLN, 0);
		    return;
		    end;

		if .IOP [I_NMX_CNT] eql 0
		then
		    begin

		    local
			UCB;

		    $MCB_MCB_TO_RSX (.NMXDB, UCB);
		    IOFIN$ (.UCB, .IOP, IE$SPC, 0);
		    return;
		    end;

		MAP$ (.LUNBLK [LUN_ENTITY_BIAS]);
                begin

		local
		    NMXDB : ref NMXDB_BLOCK,
		    CCB : ref DLX_CCB_BLOCK;

		bind
		    ENTBLK = LUNBLK [LUN_ENTITY_ADDRESS] : ref NMX_GENERAL_BLOCK;

		if not $MCB_GET_CCB (CCB)
		then
		    begin

		    local
			UCB;

		    $MCB_MCB_TO_RSX (.NMXDB, UCB);
		    IOFIN$ (.UCB, .IOP, IE$NDR, 0);
		    return
		    end;

		LUNBLK [LUN_XMTS] = .LUNBLK [LUN_XMTS] + 1;
		CCB [C_BIAS] = .IOP [I_NMX_BIAS];
		CCB [C_ADDR] = .IOP [I_NMX_ADDR];
		CCB [C_CNT] = .IOP [I_NMX_CNT];
		CCB [C_DLX_STATE] = DLX_TRANSMIT;
		CCB [C_DLX_IOP] = .IOP;
		CCB [C_DLX_LUNBLK] = .LUNBLK;
		$DLL_TRANSMIT ((.CCB), .ENTBLK [GENERAL_PROVIDER_PIX]);
                end;
		$MCB_MCB_TO_RSX (.NMXDB);
		end;

            end;

    end;					!of DLXXMT
routine FIND_LUNBLK (LUNID) = 			! Find a LUNBLK with LUNID

!++
! FUNCTIONAL DESCRIPTION:
!
!
!
! FORMAL PARAMETERS:
!
!	None
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	None
!
! SIDE EFFECTS:
!
!	Must be called in MCB mode
!--

    begin

    external
	MCB$GAW_PROCESS_DATA_BASE : vector [2];

    bind
	NMXDB = MCB$GAW_PROCESS_DATA_BASE [1] : ref NMXDB_BLOCK;

    local
	LUNBLK : ref DLX_LUN_BLOCK;

!
! Search LUN Queue for block with matching LUN_ID
!
    LUNBLK = NMXDB [NMX_LUN_QUEUE];

    while (LUNBLK = .LUNBLK [LUN_LINK]) nequ 0 do

	if .LUNBLK [LUN_ID] eqlu .LUNID<0, 8> then exitloop;

    .LUNBLK
    end;					!of FIND_LUNBLK
routine ALLOCATE_LUNBLK (ENTITY) = 		! Allocate a LUNBLK and initialize it

!++
! FUNCTIONAL DESCRIPTION:
!
!
!
! FORMAL PARAMETERS:
!
!	None
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	None
!
! SIDE EFFECTS:
!
!	Must be called in MCB mode
!--

    begin

    external
	MCB$GAW_PROCESS_DATA_BASE : vector [2];

    bind
	NMXDB = MCB$GAW_PROCESS_DATA_BASE [1] : ref NMXDB_BLOCK;

    local
	LUNBLK : ref DLX_LUN_BLOCK;

!
! Allocate and Initialize the LUN_BLOCK
!

    if $MCB_GET_DSR (DLX_LUN_ALLOCATION, LUNBLK)
    then
	begin					!LUN_BLOCK Allocation Success
	$NMX_ENQUEUE (NMXDB [NMX_LUN_QUEUE], .LUNBLK);
	LUNBLK [LUN_ENTITY_ADDRESS] = .ENTITY;
	SMAP$ (LUNBLK [LUN_ENTITY_BIAS]);
	LUNBLK [LUN_ID] = .NMXDB [NMX_NEXT_LUN_ID];
	NMXDB [NMX_NEXT_LUN_ID] = .NMXDB [NMX_NEXT_LUN_ID] + 1;
	LUNBLK [LUN_STATE] = LUN_OPENING;
        $NMX_QUEUE_INITIALIZE (LUNBLK [LUN_RCVS]);
        $NMX_QUEUE_INITIALIZE (LUNBLK [LUN_RCPS]);
	LUNBLK [LUN_XMTS] = 0;
	LUNBLK [LUN_RCV_ERROR] = 0;
	LUNBLK [LUN_ERROR_CODE] = IS$SUC;
	.LUNBLK
	end
    else
	0

    end;					!of ALLOCATE_LUNBLK
routine EXTRACT_LUNBLK (LUNID) = 		! Extract a LUNBLK with LUNID

!++
! FUNCTIONAL DESCRIPTION:
!
!
!
! FORMAL PARAMETERS:
!
!	None
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	None
!
! SIDE EFFECTS:
!
!	Must be called in MCB mode
!--

    begin

    external
	MCB$GAW_PROCESS_DATA_BASE : vector [2];

    bind
	NMXDB = MCB$GAW_PROCESS_DATA_BASE [1] : ref NMXDB_BLOCK;

    local
	LUNBLK : ref DLX_LUN_BLOCK,
	PREBLK : ref DLX_LUN_BLOCK;

!
! Search LUN Queue for block with matching LUN_ID
!
    LUNBLK = NMXDB [NMX_LUN_QUEUE];
    PREBLK = .LUNBLK;

    while (LUNBLK = .LUNBLK [LUN_LINK]) nequ 0 do
	begin

	if .LUNBLK [LUN_ID] eqlu .LUNID<0, 8>
	then
	    begin

	    if (PREBLK [LUN_LINK] = .LUNBLK [LUN_LINK]) eql 0
	    then
		NMXDB [$sub_field (NMX_LUN_QUEUE, Q_TAIL)] = .PREBLK;

	    exitloop;
	    end;

	PREBLK = .LUNBLK;
	end;

!
    .LUNBLK
    end;					!of EXTRACT_LUNBLK
routine TRY_SOME_RCVS (LUNBLK) : novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!    TRY_SOME_RCVS tries to give some receives from the RCPS Queue to
!    an RSX task.
!
! FORMAL PARAMETERS:
!
!	None
!
! IMPLICIT INPUTS:
!
!       LUNBLK RCP and IOP Queues
!
! IMPLICIT OUTPUTS:
!
!       LUNBLK RCP and IOP Queues
!
! COMPLETION CODES:
!
!	None
!
! SIDE EFFECTS:
!
!       This routine must be called in MCB mode!
!--

    begin

    map
	LUNBLK : ref DLX_LUN_BLOCK;

    bind
	NMXDB = MCB$GAW_PROCESS_DATA_BASE [1] : ref NMXDB_BLOCK,
	RCVQ = LUNBLK [LUN_RCVS] : vector,
	RCPQ = LUNBLK [LUN_RCPS] : vector;

!
! Check first for error completions
!

    while true do
        begin

        local
            AMOUNT,
            ERROR_CODE,
            IOP : ref NMX_IOP_BLOCK;

        if (IOP = .RCVQ [0]) eqla 0 then exitloop;

        if .LUNBLK [LUN_RCV_ERROR] eql 0
        then
            begin

            local
                CCB : ref block field (C_FIELDS);

            if (CCB = .RCPQ [0]) eqla 0 then exitloop;

            ERROR_CODE = IS$SUC;
            AMOUNT = .CCB [C_CNT];
            !
            ! Check if there is too much data
            !
            if .AMOUNT gtru .IOP [I_NMX_CNT]
            then
                begin
                ERROR_CODE = IE$DAO;
                AMOUNT = .IOP [I_NMX_CNT];
                end;

            begin                       ! Copy data to user buffer.

            local
                CURRENT_MAP;

            SMAP$ (CURRENT_MAP);
            MAP$ (.CCB [C_BIAS]);
            $MCB_MOVE_BUFFER_TO_BUFFER (.AMOUNT, .CCB [C_ADDR],
	        ((.IOP [I_NMX_BIAS]), (.IOP [I_NMX_ADDR])));
            MAP$ (.CURRENT_MAP);
            end;
!
! Complete IOP and return resources
!
            $MCB_DEQUEUE_CCB (RCPQ, CCB);       ! Dequeue RCPQ
            CCB [C_FNC] = FC_RCE;
            $MCB_SCHEDULE_CCB (.CCB);
            end
        else
            begin
            ERROR_CODE = .LUNBLK [LUN_RCV_ERROR];
            AMOUNT = 0;
            LUNBLK [LUN_RCV_ERROR] = 0;
            end;

        $NMX_DEQUEUE (RCVQ, IOP);
        $NMX_RETURN_RSX_IOP (.IOP, .ERROR_CODE, .AMOUNT);
	end;

    end;					!of TRY_SOME_RCVS
end

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