Google
 

Trailing-Edge - PDP-10 Archives - BB-P363B-SM_1985 - mcb/drivers/dmcnmx.b16
There are no other files named dmcnmx.b16 in the archive.
module DMCNMX (	! DMC-11 Driver Network Management
		ident = 'X01270',
		language (bliss16)
		) =
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 DMC Driver
!
! ABSTRACT:
!
!	This module contains the DMC driver Network Management routines.
!
! ENVIRONMENT: MCB V3.2
!
! AUTHOR: Alan D. Peckham	CREATION DATE: 3-Mar-81
!
! MODIFIED BY:
!
!	Alan D. Peckham, 3-Mar-81: Version 1
! 01	- Split off from DMC module.
! 02	- Eliminate multiple vector assignment bug in SET_DMC_DEVICE.
! 03	- Identify line and circuit to NMX in SET_DMC_DEVICE.
! 04	- Correct CTLNM dispatches.
!	  Fix mapping problems in fetching counters.
! 05	- Distinguish DMCs from DMRs in SET_DMC_DEVICE.
! 06	- Event logging buffer adjustment.
! 07	- Eliminate double line status reporting.
! 08	- Add controller parameter support.
! 10	- Change to support DMC/DMR line names.
! 11	- Fix bit-mapped counter handling.
! 12	- Change linkage on DMCNM.
! 13	- Use $MCB_GET_DEVICE_NAME to get line/device name.
! 14	- Eliminate references to $MCB_GET_DEVICE_NAME and
!	  use NMX$PARAMETER calls instead.
!	  Move all counters to circuit counters.
! 15	- Add system specific parameters.
! 16	- Set counter maintenance to use snapshot for zeroing
!	  and use differences for reporting.
! 17	- I was subtracting the wrong way to get the counter differences!
! 18	- Update to NM V3.0 .
!	  Fix circuit handling to call the zero counter routines.
!	  (found by LEAPLINE).
! 19	- Add MAXIMUM RECEIVE BUFFERS support.
! 20	- Don't set DC_SET_REQUESTED_STATE in ZERO_x_COUNTERS.
! 21	- Do not force HALT for ZERO_COUNTERS.
! 22	- Support new system specific line counters (2500,2501,2502).
! 23	- De-commit half-duplex.
! 24	- Re-enable half-duplex code.
! 25	- Fix reporting of DMC counter 1021.
! 26	- Get CLEAR LINE to dispatch right from DMCNM.
! 27	- Add seconds-since-last-zeroed support for lines.
!	  Eliminate double line counter report from owner and provider.
!--
!
! INCLUDE FILES:
!

literal
    DMC$K_FANCY = 1 eql 0 %(false)%;

library 'MCBLIB';

library 'XPORTX';

library 'NMXLIB';

library 'DMCDAT';

!
! TABLE OF CONTENTS:
!

linkage
    DMC_DB = jsr (register = 5),
    DMC_DB_NUM = jsr (register = 5, register = 1) : nopreserve (0, 1);

forward routine
    CLEAR_CIRCUIT : LINKAGE_CCB,
    CLEAR_LINE : LINKAGE_CCB,
    DMCNM : MCB_DB_CCB novalue,
    NOT_APPLICABLE : DMC_DB_NUM,
    PARAMETER_CIRCUIT_COUNTERS : LINKAGE_DB novalue,
    PARAMETER_LINE_COUNTERS : LINKAGE_DB novalue,
    SET_CIRCUIT : LINKAGE_CCB,
    SET_LINE : LINKAGE_CCB,
    SET_LINE_CONTROLLER : DMC_DB_NUM,
    SET_LINE_DUPLEX : DMC_DB_NUM,
    SET_LINE_RECEIVE_BUFFERS : DMC_DB_NUM,
    SET_LINE_RETRANSMIT_TIMER : DMC_DB_NUM,
    SET_LINE_SERVICE_TIMER : DMC_DB_NUM,
    SET_LINE_STATE : DMC_DB_NUM,
    %if DMC$K_FANCY %then
    SET_LINE_CONTROLLER_REGISTER : DMC_DB_NUM,
    SET_LINE_INTERRUPT_VECTOR : DMC_DB_NUM,
    SET_LINE_INTERRUPT_PRIORITY : DMC_DB_NUM,
    %fi
    SHOW_AND_ZERO_CIRCUIT_COUNTERS : LINKAGE_CCB,
    SHOW_AND_ZERO_LINE_COUNTERS : LINKAGE_CCB,
    SHOW_CIRCUIT : LINKAGE_CCB,
    SHOW_LINE : LINKAGE_CCB,
    SHOW_SUCCESS : LINKAGE_CCB,
    SUCCESS : LINKAGE_CCB,
    ZERO_CIRCUIT_COUNTERS : LINKAGE_CCB,
    ZERO_LINE_COUNTERS : LINKAGE_CCB;

!
! MACROS:
!

macro
    CNTR_8 (NUM, FLDB) =
	begin field $CNTR$FLDB = [$SUB_FIELD (D_LNTB, FLDB)],
		    $CNTR$FLDC = [$SUB_FIELD (D_CPTB, FLDB)];
	stacklocal $CNTR$DIFF;
	$CNTR$DIFF <0, 8> = .DB [$CNTR$BYTE ($CNTR$FLDB)];
	$CNTR$DIFF = .$CNTR$DIFF - .DB [$CNTR$BYTE ($CNTR$FLDC)];
	COUNTER_8 (NUM, $CNTR$DIFF)
	end %,
    CNTR_BEGIN (DUMMY) =
	begin CTR = 255;
	begin local SUM; SUM = 0; %,
    CNTR (FLDB) =
	begin field $CNTR$FLDB = [$SUB_FIELD (D_LNTB, FLDB)],
		    $CNTR$FLDC = [$SUB_FIELD (D_CPTB, FLDB)];
	local $CNTR$DIFF; $CNTR$DIFF = .DB [$CNTR$BYTE ($CNTR$FLDB)];
	$CNTR$DIFF = .$CNTR$DIFF - .DB [$CNTR$BYTE ($CNTR$FLDC)];
	$CNTR$DIFF = .$CNTR$DIFF <0, 8, 0>;
	SUM = .SUM + .$CNTR$DIFF;
	end %,
    CNTR_POST (NUM) =
	if .SUM lssu 255 then CTR <0, 8> = .SUM;
	end;
	COUNTER_8 (NUM, CTR);
	end %,
    CNTR_BM_BEGIN (DUMMY) =
	begin CTR = 255;
	begin local SUM; SUM = 0; %,
    CNTR_BM (FLG, FLDB) =
	begin field $CNTR$FLDB = [$SUB_FIELD (D_LNTB, FLDB)],
		    $CNTR$FLDC = [$SUB_FIELD (D_CPTB, FLDB)];
	local $CNTR$DIFF; $CNTR$DIFF = .DB [$CNTR$BYTE ($CNTR$FLDB)];
	$CNTR$DIFF = .$CNTR$DIFF - .DB [$CNTR$BYTE ($CNTR$FLDC)];
	$CNTR$DIFF = .$CNTR$DIFF <0, 8, 0>;
	if .$CNTR$DIFF neq 0
	then
	    begin
	    SUM = .SUM + .$CNTR$DIFF;
	    CTR <8 + FLG, 1> = 1;
	    end
	end %,
    CNTR_BM_POST (NUM) =
	if .SUM lssu 255 then CTR <0, 8> = .SUM;
	end;
	COUNTER_8_BM (NUM, CTR);
	end %,
    $CNTR$BYTE (FLD) =
	%fieldexpand (FLD, 0), %fieldexpand (FLD, 1), %fieldexpand (FLD, 2), 1 %;

!
! EQUATED SYMBOLS:
!

literal
    TRUE = 1 EQL 1,
    FALSE = 1 EQL 0,
    NO_OPERATION = 0;

!
! OWN STORAGE:
!

external routine
    $DSPCR : novalue;

!
! EXTERNAL REFERENCES:
!

linkage
    LINKAGE_DB_CSR = jsr (register = 5, register = 1);

external routine
    DMCIN : MCB_INTERRUPT novalue,
    DMCOUT : MCB_INTERRUPT novalue,
    MASTER_CLEAR : LINKAGE_DB_CSR,
    SET_PORT : LINKAGE_DB novalue;

external
    MCB$GAW_PROCESS_DATA_BASE : vector [2],
    MCB$GW_PROCESS_HANDLE;

bind
    DB_BIAS = MCB$GAW_PROCESS_DATA_BASE [0];
routine CLEAR_CIRCUIT (CCB) : LINKAGE_CCB =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	CCB	Address of CCB
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
!	The appropriate NM status code
!
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin

    map
	CCB: ref block field (C_NM_FIELDS);

    if .CCB [C_CNT] eql 0
    then
	NM$SUC
    else
	NE$PNA

    end;
routine CLEAR_LINE (CCB) : LINKAGE_CCB =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	CCB	Address of CCB
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
!	The appropriate NM status code
!
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DMC_DATA_BASE (DB)

    map
	CCB: ref block field (C_NM_FIELDS);

    if .CCB [C_CNT] eql 0
    then
	NM$SUC
    else
	NE$PNA

    end;
global routine DMCNM

!++
! FUNCTIONAL DESCRIPTION:
!	This routine is activated by a control request from
!	Network Management.
!
! FORMAL PARAMETERS:
!
       (DB : ref block field (D_FIELDS),
	CCB : ref block field (C_NM_FIELDS))
!
! IMPLICIT INPUTS:
!	CCB Contents
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
!
	: MCB_DB_CCB novalue =
!
! SIDE EFFECTS:
!	None
!--

    begin

    CCB [C_STS] =
	begin

	case .CCB [C_NM_ENTITY] from NMX$ENT_lo to NMX$ENT_hi of
	    set
	    [NMX$ENT_ckt] : 			! NM function for
		begin				!  CIRCUIT parameter
		case .CCB [C_NM_FUNC] from NMX$FNC_lo to NMX$FNC_hi of
		    set
		    [NMX$FNC_set] :		! Set parameters
			SET_CIRCUIT (.CCB);
		    [NMX$FNC_zro] :		! Zero counters
			ZERO_CIRCUIT_COUNTERS (.CCB);
		    [NMX$FNC_sho] :		! Show selected items
			SHOW_CIRCUIT (.CCB);
		    [NMX$FNC_szc] :		! Show and zero counters
			SHOW_AND_ZERO_CIRCUIT_COUNTERS (.CCB);
		    [inrange] :
			$NM$ERR_SFS;
		    [outrange] :
			$NM$ERR_MPE;
		    tes
		end;

	    [NMX$ENT_lin] : 			! NM function for
		begin				!  LINE parameter
		case .CCB [C_NM_FUNC] from NMX$FNC_lo to NMX$FNC_hi of
		    set
		    [NMX$FNC_clr] :		! Clear parameters
			DISPATCH$ (.CCB [C_LIX],
			    TABLE$ (SUCCESS, DMC_K_NMID_HIGH,
				(DMC_K_LINE_OWNER, CLEAR_LINE),
				(DMC_K_LINE_PROVIDER, CLEAR_LINE)),
			    (.CCB), LINKAGE_CCB);
		    [NMX$FNC_set] :		! Set parameters
			DISPATCH$ (.CCB [C_LIX],
			    TABLE$ (SUCCESS, DMC_K_NMID_HIGH,
				(DMC_K_LINE_OWNER, SET_LINE),
				(DMC_K_LINE_PROVIDER, SET_LINE)),
			    (.CCB), LINKAGE_CCB);
		    [NMX$FNC_zro] :		! Zero counters
			DISPATCH$ (.CCB [C_LIX],
			    TABLE$ (SUCCESS, DMC_K_NMID_HIGH,
				(DMC_K_LINE_PROVIDER, ZERO_LINE_COUNTERS)),
			    (.CCB), LINKAGE_CCB);
		    [NMX$FNC_sho] :		! Show selected items
			DISPATCH$ (.CCB [C_LIX],
			    TABLE$ (SHOW_SUCCESS, DMC_K_NMID_HIGH,
				(DMC_K_LINE_OWNER, SHOW_SUCCESS),
				(DMC_K_LINE_PROVIDER, SHOW_LINE)),
			    (.CCB), LINKAGE_CCB);
		    [NMX$FNC_szc] :		! Show and zero counters
			DISPATCH$ (.CCB [C_LIX],
			    TABLE$ (SHOW_SUCCESS, DMC_K_NMID_HIGH,
				(DMC_K_LINE_PROVIDER, SHOW_AND_ZERO_LINE_COUNTERS)),
			    (.CCB), LINKAGE_CCB);
		    [inrange] :
			$NM$ERR_SFS;
		    [outrange] :
			$NM$ERR_MPE;
		    tes
		end;

	    [inrange, outrange] :
		$NM$ERR_MPE;

	    tes

	end;

    CCB [C_FNC] = FC_CCP;
    LLCRS$ (.CCB);
    end;				! of routine DMCNM
routine NOT_APPLICABLE (DB, DUMMY) : DMC_DB_NUM =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DUMMY = unused
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
!	The appropriate NM status code
!
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DMC_DATA_BASE (DB)
    NE$PNA
    end;
global routine PARAMETER_CIRCUIT_COUNTERS

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
       (DB : ref block field (D_FIELDS))
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
	: LINKAGE_DB novalue =
!
! SIDE EFFECTS:
!	None
!--

    begin

    local
	CTR;

    COUNTER_32 (1000, DB [D_BYTES_RECEIVED]);
    COUNTER_32 (1001, DB [D_BYTES_TRANSMITTED]);
    COUNTER_32 (1010, DB [D_BLOCKS_RECEIVED]);
    COUNTER_32 (1011, DB [D_BLOCKS_TRANSMITTED]);

    CNTR_BM_BEGIN ()
    CNTR_BM (0, BASE_NAKS_SND_HDR_BCC);
    CNTR_BM (1, BASE_NAKS_SND_DAT_BCC);
    if .DB [DF_DMR] then CNTR_BM (2, BASE_NAKS_SND_RCV_REP);
    CNTR_BM_POST (1020);

    if not .DB [DF_DMR]
    then
	begin
	CNTR_BEGIN ()
	CNTR (BASE_NAKS_RCV_HDR_BCC);
	CNTR (BASE_NAKS_RCV_DAT_BCC);
	CNTR_POST (1021);
	end
    else
	begin
	CNTR_BM_BEGIN ()
	CNTR_BM (0, BASE_NAKS_RCV_HDR_BCC);
	CNTR_BM (1, BASE_NAKS_RCV_DAT_BCC);
	CNTR_BM (2, BASE_NAKS_RCV_REP);
	CNTR_BM_POST (1021);
	end;

    CNTR_8 (1030, BASE_REPS_RCV);
    CNTR_8 (1031, BASE_REPS_SND);

    CNTR_BM_BEGIN ()
    CNTR_BM (0, BASE_NAKS_RCV_NO_BUF);
    if .DB [DF_DMR] then CNTR_BM (1, BASE_NAKS_RCV_TOO_LONG);
    CNTR_BM_POST (1040);


    CNTR_BM_BEGIN ()
    CNTR_BM (0, BASE_NAKS_SND_NO_BUF);
    CNTR_BM_POST (1041);

    if .DB [DF_DMR]
    then
	begin
	CNTR_BM_BEGIN ()
	CNTR_BM (0, BASE_NO_REPLY_TO_SEL);
	CNTR_BM (1, BASE_INCOMPLETE_SEL);
	CNTR_BM_POST (1051);
	end;

    end;			!of routine PARAMETER_CIRCUIT_COUNTERS
global routine PARAMETER_LINE_COUNTERS

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
       (DB : ref block field (D_FIELDS))
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
	: LINKAGE_DB novalue =
!
! SIDE EFFECTS:
!	None
!--

    begin

    if .DB [DF_DMR]
    then
	begin

	local
	    CTR;

	COUNTER_16_TIME (0, DB [DB_TIME_LINE_ZEROED]);
	CNTR_BM_BEGIN ()
	CNTR_BM (0, BASE_NAKS_RCV_RCV_OVRN);
	CNTR_BM (1, BASE_NAKS_SND_HDR_FMT);
	CNTR_BM (3, BASE_STRM_TIMEOUT);
	CNTR_BM_POST (1100);
	CNTR_BM_BEGIN ()
	CNTR_BM (0, BASE_NAKS_SND_RCV_OVRN);
	CNTR_BM (2, BASE_XMT_UNDR);
	CNTR_BM (3, BASE_NAKS_RCV_HDR_FMT);
	CNTR_BM_POST (1101);
	end;

    if .DB [D_CONFIGURATION_ERRORS] neq 0
    then
	COUNTER_8_BM (2500, DB [D_CONFIGURATION_ERRORS]);

    if .DB [D_DEVICE_SERVICE_ERRORS] neq 0
    then
	COUNTER_8_BM (2501, DB [D_DEVICE_SERVICE_ERRORS]);

    if .DB [D_FATAL_DEVICE_ERRORS] neq 0
    then
	COUNTER_8_BM (2502, DB [D_FATAL_DEVICE_ERRORS]);

    end;			!of routine PARAMETER_LINE_COUNTERS
routine SET_CIRCUIT (CCB) : LINKAGE_CCB =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	CCB	Address of CCB
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
!	The appropriate NM status code
!
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin

    map
	CCB: ref block field (C_NM_FIELDS);

    NE$PNA
    end;
routine SET_LINE (CCB) : LINKAGE_CCB =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	CCB	Address of CCB
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
!	The appropriate NM status code
!
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DMC_DATA_BASE (DB)

    map
	CCB: ref block field (C_NM_FIELDS);

    local
	BUF_PTR,
	DATA_ID,
	DATA_VALUE;

    MAP$ (.CCB [C_BIAS]);
    BUF_PTR = .CCB [C_ADDR];
    DATA_ID <0, 8> = ch$rchar_a (BUF_PTR);
    DATA_ID <8, 8> = ch$rchar_a (BUF_PTR);
    DATA_ID = .DATA_ID <0, 12>;
    DATA_VALUE <0, 8> = ch$rchar_a (BUF_PTR);
    DATA_VALUE <8, 8> = ch$rchar_a (BUF_PTR);
    MAP$ (.DB_BIAS);
    $NM_PARAMETER_DISPATCH (.DATA_ID, NOT_APPLICABLE,
	((0, SET_LINE_STATE),
	 (1111, SET_LINE_DUPLEX),
	 (1105, SET_LINE_RECEIVE_BUFFERS),
	 (1110, SET_LINE_CONTROLLER),
	 (1120, SET_LINE_SERVICE_TIMER),
	 (1121, SET_LINE_RETRANSMIT_TIMER)
	  %if DMC$K_FANCY %then ,
	 (2650, SET_LINE_CONTROLLER_REGISTER),
	 (2655, SET_LINE_INTERRUPT_VECTOR),
	 (2660, SET_LINE_INTERRUPT_PRIORITY)
	  %fi),
	(DB [D_TIM], .DATA_VALUE), DMC_DB_NUM)
    end;
routine SET_LINE_CONTROLLER (DB, CONTROLLER) : DMC_DB_NUM =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	CONTROLLER = (NORMAL, LOOPBACK)
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
!	The appropriate NM status code
!
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DMC_DATA_BASE (DB)

    literal
	LOOPBACK = 1,
	NORMAL = 0;

    if .DB [D_PROTOCOL_STATE] neq DS_HALTED then return NE$CWS;

    selectone .CONTROLLER of
	set
	[NORMAL] : (DB [DF_CONTROLLER_LOOPBACK] = 0; NM$SUC);
	[LOOPBACK] : (DB [DF_CONTROLLER_LOOPBACK] = 1; NM$SUC);
	[otherwise] : NE$IPV;
	tes

    end;
routine SET_LINE_DUPLEX (DB, DUPLEX) : DMC_DB_NUM =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DUPLEX = (FULL, HALF)
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
!	The appropriate NM status code
!
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DMC_DATA_BASE (DB)

    literal
	FULL = 0,
	HALF = 1;

    if .DB [D_PROTOCOL_STATE] neq DS_HALTED then return NE$CWS;

    selectone .DUPLEX of
	set
	[FULL] : (DB [DF_HALF_DUPLEX] = 0; NM$SUC);
	[HALF] : (DB [DF_HALF_DUPLEX] = 1; NM$SUC);
	[otherwise] : NE$IPV;
	tes

    end;
routine SET_LINE_RECEIVE_BUFFERS (DB, COUNT) : DMC_DB_NUM =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	COUNT = (1 to 16)
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
!	The appropriate NM status code
!
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DMC_DATA_BASE (DB)

    if not .DB [DF_DMR]
    then
	selectone .COUNT of
	    set
	    [1 to 7] : (DB [D_MAXIMUM_RECEIVE_COUNT] = .COUNT; NM$SUC);
	    [otherwise] : NE$IPV;
	    tes
    else
	selectone .COUNT of
	    set
	    [1 to 16] : (DB [D_MAXIMUM_RECEIVE_COUNT] = .COUNT; NM$SUC);
	    [otherwise] : NE$IPV;
	    tes

    end;
routine SET_LINE_RETRANSMIT_TIMER (DB, RETRANSMIT_TIMER) : DMC_DB_NUM =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	RETRANSMIT_TIMER = (1000, 3000)
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
!	The appropriate NM status code
!
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DMC_DATA_BASE (DB)

    if .DB [D_PROTOCOL_STATE] neq DS_HALTED then return NE$CWS;

    selectone .RETRANSMIT_TIMER of
	set
	[1000] : (DB [DF_1_SEC] = TRUE; NM$SUC);
	[3000] : (DB [DF_1_SEC] = FALSE; NM$SUC);
	[otherwise] : NE$IPV;
	tes

    end;
routine SET_LINE_SERVICE_TIMER (DB, MILLISECONDS) : DMC_DB_NUM =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	MILLISECONDS = 1 to 65535
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
!	The appropriate NM status code
!
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DMC_DATA_BASE (DB)

    if .MILLISECONDS<1, 15, 0> mod (1000/2) neq 0 or
	.MILLISECONDS<0, 1, 0> neq 0 then return NE$IPV;

    DB [D_SERVICE_TIMER] = .MILLISECONDS<1, 15, 0>/(1000/2);
    NM$SUC
    end;
routine SET_LINE_STATE (DB, STATE) : DMC_DB_NUM =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	STATE = (OFF, ON)
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
!	The appropriate NM status code
!
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DMC_DATA_BASE (DB)

    literal
	ON = 0,			! New state = ON
	OFF = 1,		! New state = OFF
	SERVICE = 2,		! New state = SERVICE
	CLEARED = 3;		! New state = CLEARED

    selectone .STATE <0, 8> of
	set
	[ON] :
	    begin
	    $MCB_ENABLE_LONG_TIMER ();
	    DB [DC_SET_REQUESTED_STATE] = TRUE;
	    DB [D_LINE_STATE] = .STATE <0, 8>;
	    SET_PORT (DB [D_TIM]);
	    NM$SUC
	    end;
	[OFF] :
	    begin
	    DB [DC_HALT] = TRUE;
	    DB [DC_MASTER_CLEAR] = TRUE;
	    DB [DC_BASE_IN] = FALSE;
	    DB [DC_CONTROL_IN] = FALSE;
	    DB [DC_SET_REQUESTED_STATE] = FALSE;
	    DB [D_LINE_STATE] = .STATE <0, 8>;
	    SET_PORT (DB [D_TIM]);
	    NM$SUC
	    end;
	[otherwise] : NE$MPE;
	tes

    end;
%if DMC$K_FANCY %then
routine SET_LINE_CONTROLLER_REGISTER (DB, ADDRESS) : DMC_DB_NUM =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	ADDRESS = UNIBUS address.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
!	The appropriate NM status code
!
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DMC_DATA_BASE (DB)

    if .DB [D_PROTOCOL_STATE] neq DS_HALTED then return NE$CWS;

    selectoneu .ADDRESS of
	set
	[%o'160000' to %o'177777'] : NO_OPERATION;
	[otherwise] : return NE$IPV;
	tes;

    DB [D_REGISTER] = .ADDRESS;
    DB [D_DEVICE_STATE] = DD_CLEARED;
    NM$SUC
    end;
%fi
%if DMC$K_FANCY %then
routine SET_LINE_INTERRUPT_VECTOR (DB, ADDRESS) : DMC_DB_NUM =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	ADDRESS = Interrupt vector address.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
!	The appropriate NM status code
!
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DMC_DATA_BASE (DB)

    if .DB [D_PROTOCOL_STATE] neq DS_HALTED then return NE$CWS;

    selectoneu .ADDRESS of
	set
	[%o'0000' to %o'1000'] : NO_OPERATION;
	[otherwise] : return NE$IPV;
	tes;

    DB [D_VECTOR] = .ADDRESS;
    DB [D_DEVICE_STATE] = DD_CLEARED;
    NM$SUC
    end;
%fi
%if DMC$K_FANCY %then
routine SET_LINE_INTERRUPT_PRIORITY (DB, PRIORITY) : DMC_DB_NUM =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	PRIORITY = Interrupt priority.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
!	The appropriate NM status code
!
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DMC_DATA_BASE (DB)
    PRIORITY = .PRIORITY <0, 8>;

    if .DB [D_PROTOCOL_STATE] neq DS_HALTED then return NE$CWS;

    selectone .PRIORITY of
	set
	[4 to 7] : NO_OPERATION;
	[otherwise] : return NE$IPV;
	tes;

    DB [D_PRIORITY] = .PRIORITY;
    DB [D_DEVICE_STATE] = DD_CLEARED;
    NM$SUC
    end;
%fi
routine SHOW_AND_ZERO_CIRCUIT_COUNTERS (CCB) : LINKAGE_CCB =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	CCB	Address of CCB
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
!	The appropriate NM status code
!
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DMC_DATA_BASE (DB)

    map
	CCB: ref block field (C_NM_FIELDS);

    $NM_RESPONSE_BEGIN (.CCB);
    PARAMETER_CIRCUIT_COUNTERS (DB [D_TIM]);
    $NM_RESPONSE_END (.CCB);
    ZERO_CIRCUIT_COUNTERS (.CCB);
    .CCB [C_STS]
    end;
routine SHOW_AND_ZERO_LINE_COUNTERS (CCB) : LINKAGE_CCB =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	CCB	Address of CCB
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
!	The appropriate NM status code
!
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DMC_DATA_BASE (DB)

    map
	CCB: ref block field (C_NM_FIELDS);

    $NM_RESPONSE_BEGIN (.CCB);
    PARAMETER_LINE_COUNTERS (DB [D_TIM]);
    $NM_RESPONSE_END (.CCB);
    ZERO_LINE_COUNTERS (.CCB);
    .CCB [C_STS]
    end;
routine SHOW_CIRCUIT (CCB) : LINKAGE_CCB =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	CCB	Address of CCB
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
!	The appropriate NM status code
!
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DMC_DATA_BASE (DB)

    map
	CCB: ref block field (C_NM_FIELDS);

    $NM_RESPONSE_BEGIN (.CCB);

    selectone .CCB [C_NM_SELECT] of
	set

	[NMX$SEL_sum, NMX$SEL_sta] :
	    begin
	    NMX$PARAMETER_CIRCUIT_USER (.DB [D_NMX_PIX], .DB [D_CIRCUIT_ENTITY], 1000);
	    end;

	[NMX$SEL_cha] :
	    begin

	    literal
		DDCMP_DMC = 4;			! TYPE

	    local
		PRM;

	    NMX$PARAMETER_CIRCUIT_OWNER (.DB [D_NMX_PIX], .DB [D_CIRCUIT_ENTITY], 1100);
	    NMX$PARAMETER_LINE (.DB [D_NMX_PIX], .DB [D_LINE_ENTITY], 1110);
	    PRM = DDCMP_DMC;
	    PARAMETER_C_1 (1112, PRM);			! TYPE
	    end;

	[NMX$SEL_cou] :
	    PARAMETER_CIRCUIT_COUNTERS (DB [D_TIM]);

	[otherwise] :
	    return $NM$ERR_MPE;

	tes;

    $NM_RESPONSE_END (.CCB);
    .CCB [C_STS]
    end;
routine SHOW_LINE (CCB) : LINKAGE_CCB =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	CCB	Address of CCB
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
!	The appropriate NM status code
!
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DMC_DATA_BASE (DB)

    map
	CCB: ref block field (C_NM_FIELDS);

    $NM_RESPONSE_BEGIN (.CCB);

    selectone .CCB [C_NM_SELECT] of
	set

	[NMX$SEL_sum, NMX$SEL_sta] :
	    begin
	    PARAMETER_C_1 (0, DB [D_LINE_STATE]);	! STATE
	    end;

	[NMX$SEL_cha] :
	    begin

	    literal
		DDCMP_DMC = 4,			! TYPE
		FULL = 0,			! DUPLEX
		HALF = 1,
		LOOPBACK = 1,			! CONTROLLER
		NORMAL = 0,
		EXTRN = 0,			! CLOCK
		INTRN = 1;

	    local
		PRM;

	    NMX$PARAMETER_LINE (.DB [D_NMX_PIX], .DB [D_LINE_ENTITY], 1100);
						! DEVICE
	    PRM = .DB [D_MAXIMUM_RECEIVE_COUNT];
	    PARAMETER_C_1 (1105, PRM);
	    PRM = (if .DB [DF_CONTROLLER_LOOPBACK] then LOOPBACK else NORMAL);
	    PARAMETER_C_1 (1110, PRM);
	    PRM = (if .DB [DF_HALF_DUPLEX] then HALF else FULL);
	    PARAMETER_C_1 (1111, PRM);
	    PRM = DDCMP_DMC;
	    PARAMETER_C_1 (1112, PRM);
	    PRM = EXTRN;
	    PARAMETER_C_1 (1113, PRM);
	    PRM = .DB [D_SERVICE_TIMER]*1000;
	    PARAMETER_DU_2 (1120, PRM);
	    PRM = (if .DB [DF_1_SEC] then 1000 else 3000);
	    PARAMETER_DU_2 (1121, PRM);
	    PARAMETER_O_2 (2650, DB [D_REGISTER]);
	    PARAMETER_O_2 (2655, DB [D_VECTOR]);
	    PARAMETER_DU_1 (2660, DB [D_PRIORITY]);
	    end;

	[NMX$SEL_cou] :
	    PARAMETER_LINE_COUNTERS (DB [D_TIM]);

	[otherwise] :
	    return $NM$ERR_MPE;

	tes;

    $NM_RESPONSE_END (.CCB);
    .CCB [C_STS]
    end;
routine SHOW_SUCCESS (CCB) : LINKAGE_CCB =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	CCB	Address of CCB
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
!	The appropriate NM status code
!
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin

    map
	CCB: ref block field (C_NM_FIELDS);

    CCB [C_CNT] = 0;
    NM$SUC
    end;
routine SUCCESS (CCB) : LINKAGE_CCB =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	CCB	Address of CCB
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
!	The appropriate NM status code
!
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin

    map
	CCB: ref block field (C_NM_FIELDS);

    NM$SUC
    end;
routine ZERO_CIRCUIT_COUNTERS (CCB) : LINKAGE_CCB =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	CCB	Address of CCB
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
!	The appropriate NM status code
!
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DMC_DATA_BASE (DB)

    map
	CCB : ref block field (C_FIELDS);

    DB [DC_ZERO_CIRCUIT_COUNTERS] = TRUE;
    SET_PORT (DB [D_TIM]);
    NM$SUC
    end;
routine ZERO_LINE_COUNTERS (CCB) : LINKAGE_CCB =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	CCB	Address of CCB
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
!	The appropriate NM status code
!
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DMC_DATA_BASE (DB)

    map
	CCB : ref block field (C_FIELDS);

    if .DB [DF_DMR]
    then
	begin
	DB [DC_ZERO_LINE_COUNTERS] = TRUE;
	SET_PORT (DB [D_TIM]);
	end;

    $NM_TIME (DB [DB_TIME_LINE_ZEROED]);
    COUNTER_ZERO (DB, D_CONFIGURATION_ERRORS, 8);
    COUNTER_ZERO (DB, D_DEVICE_SERVICE_ERRORS, 8);
    COUNTER_ZERO (DB, D_FATAL_DEVICE_ERRORS, 8);
    NM$SUC
    end;
end
eludom