Google
 

Trailing-Edge - PDP-10 Archives - BB-P363B-SM_1985 - mcb/drivers/dte.b16
There are no other files named dte.b16 in the archive.
module DTE (	! DTE20 driver for MCB V3.2
		ident = 'X01560',
		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 DTE Driver
!
! ABSTRACT:
!
!	This is the DLC process which services the DTE20 device
!
! ENVIRONMENT: MCB V3.2
!
! AUTHOR: Alan D. Peckham	CREATION DATE: 28-May-80
!
! MODIFIED BY:
!
!	Alan D. Peckham, 28-May-80: Version 1
! 01	- New version for MCB V3.0
! 06	- Move data base to DTEDAT for dump analyzer.
! 07	- Catch interrupts during DS_COM state.
! 08	- Seperate DLC and DDM dispatch tables to avoid C.MOD bug.
! 09	- Clear doorbell on DS_COM interrupt.
! 10	- Add debugging SIGNALs to find DTE_2 bug.
! 11	- Bug found! Remove signals...
! 12	- Bug not found! Fix TENAD1 reset problem in PRTDEP and PRTEXM.
! 13	- Add global data base symbols for DTEDLC.
! 14	- MCB V3.1 update:
!	    Replace process header.
!	    Use CNV22$ instead of CNV18$.
!	    Supply routine address in SYNCH$.
! 15	- Added network management code.
!	  Clear QSIZE on line down to avoid TRANSMIT_SEGMENT activation.
! 16	- Copy messages into contiguous buffer.
! 17	- DTE shutdown could occur before all receive buffers were back.
! 18	- Add internal event logging.
! 19	- Do not start new receive in RECEIVE_MESSAGE until old one is finished.
! 20	- Map the data base.
!	  Update the network management code.
! 21	- Insert Network Management event logging.
! 22	- Bug in handling buffers that cross 32K boundries.
! 23	- Clean up current Network Management code.
! 24	- Correct transmit/receive contention for bus extension bits.
! 25	- Signal when event logging buffer too small.
! 26	- Add DTE directory process.
! 27	- Add long timer control.
! 28	- Identify line and circuit to NMX in DTENMX.
! 29	- Do not SYNCH unless interrupt enable is on.
! 30	- Flush transmits before waiting for the cows to come home in SHUTDN.
! 31	- Toss recovery RDB if receive already in progress in TIMRDB.
! 32	- Integrate DLL interface
! 33	- Add protocol pause timeout.
!	  Cover all cases where initialization should be checked for.
! 34	- Fix FLUSH_QUEUE linkage bug.
! 35	- Replace DLC with DLL interface.
! 36	- Rework initialization code.
!	  Fix mapping bug.
! 37	- Maintain requested protocol state.
!	  Handle all INIT states in ANSWER_DOORBELL.
! 38	- Eliminate CNV18.
!	  Create CHANGE_PROTOCOL_STATE routine.
! 39	- Correct NM parameters.
! 40	- Correct linkage errors to SEND_PERSISTENT_ERROR.
! 41	- Adapt to using new UNIBUS address conversion routines.
! 42	- Eliminate duplicate state notifications.
! 43	- Set protocol pause timeout to use DLL$_PAUSE_TIMEOUT status.
! 44	- Always update keep-alive if we can get at the comm region.
! 45	- Do not start transmit until -10's doorbell has stopped ringing.
!	  Add GET_HIS_STATUS to clear status word if examine failure.
!	  Check for PAUSE and INITIALIZATION requests in TIMLTM before
!	  trying to restart transmit/receive.
! 46	- Correct GETCOM to compensate for TOPS20 not initializing
!	  inactive to-him regions with their lengths.
! 47	- Update to NM V3.0.0 .
! 48	- Make sure address passed to PARAMETER_DEVICE_REGISTERS begins
!	  at beginning of DTE register set.
! 49	- Remove 'counters zeroed' event in DTENMX.
!
! 50	- Ron Platukis 26-february-82
!	  a) in routine TIMLTM add check for lost TO-10 doorbell on xmits.
!	  b) in routine TRANSMIT_SEGMENT start long timer after an xmit.
!	  c) in routine T10DON shut off long timer if in run state.
! 51	- Add pause timeout display in DTENMX.
! 52	- Rework supported counters: add system specific line counters.
! 53	- Fix areas in DTE_SYNCHRONIZE and TIMLTM to recognize a PAUSED KL.
! 54	- Correct register display of SHOW_LINE in DTENMX.
! 55	- Modify CTLSTR to return the CIRCUIT COST to XPT in C_PRM1.
! 56	- Correct for possible loss of interrupt enable during KL reload
!	  by re-enableing interrupts in ANSWER_DOORBELL during initialization.
!--
!
! INCLUDE FILES:
!

library 'MCBLIB';

library 'XPORTX';

library 'NMXLIB';

$SHOW (NONE)
require 'DLLLIB';

library 'DTEDAT';

!
! TABLE OF CONTENTS:
!

linkage
    DTE_CCB_DB = jsr (register = 4, register = 5) : nopreserve (4),
    DTE_CCB_DB_STS = jsr (register = 4, register = 5, register = 0) : nopreserve (4),
    DTE_DB = jsr (register = 5) : nopreserve (0, 1, 2, 3, 4),
    DTE_DB_CCB = jsr (register = 5, register = 4) : nopreserve (0, 1, 2, 3, 4),
    DTE_DB_DTE = jsr (register = 5, register = 1),
    DTE_DB_STS = jsr (register = 5, register = 0) : nopreserve (4, 0),
    DTE_REG = jsr (register = 1) : nopreserve (1),
    EXM_LINKAGE = jsr (register = 5) : nopreserve (0, 1, 2, 3),
    EXDP_LINKAGE = jsr (register = 5, register = 2, register = 3) : nopreserve (0, 1, 2);

forward routine
    ANSWER_DOORBELL : DTE_DB novalue,
    CHANGE_PROTOCOL_STATE : DTE_DB novalue,
    CLEAR_DOORBELL : DTE_DB,
    CTLSTP : DTE_DB_CCB novalue,
    CTLSTR : DTE_DB_CCB novalue,
    CURRENT_STATUS : LINKAGE_DB,
    DEPMYG : EXDP_LINKAGE,
    DEPMYH : EXDP_LINKAGE,
    DEVICE_BROKEN : DTE_DB novalue,
    DLLINI : DTE_DB_CCB novalue,
    DLLMOP : DTE_DB_CCB novalue,
    DLLSTP : DTE_DB_CCB novalue,
    DLLXMT : DTE_DB_CCB novalue,
    DTE_INTERRUPT : MCB_INTERRUPT novalue,
    DTE_SYNCHRONIZE : MCB_DB novalue,
    DTECTL : MCB_DB_CCB_MOD novalue,
    DTERCE : MCB_DB_CCB novalue,
    DTESTP : DTE_DB novalue,
    DTESTR : DTE_DB novalue,
    DTETIM : MCB_DB_MOD novalue,
    DTEXME : MCB_DB_CCB_MOD novalue,
    EXMHSG : EXDP_LINKAGE,
    EXMHSM : EXDP_LINKAGE,
    EXMMYG : EXDP_LINKAGE,
    EXMMYH : EXDP_LINKAGE,
    GET_HIS_STATUS : EXM_LINKAGE novalue,
    GETCOM : DTE_DB novalue,
    INITIALIZATION_REQUESTED : DTE_DB,
    NEW_RCB : DTE_DB novalue,
    PARAMETER_DEVICE_REGISTERS : DTE_REG novalue,
    PAUSED : DTE_DB,
    PROTOCOL_BROKEN : DTE_DB novalue,
    PRTDEP : EXDP_LINKAGE,
    PRTEXM : EXDP_LINKAGE,
    RECEIVE_MESSAGE : DTE_DB novalue,
    RECEIVE_SEGMENT : DTE_DB novalue,
    SCHEDULE_PERSISTENT_AST : DTE_CCB_DB novalue,
    SCHEDULE_RECEIVE : DTE_CCB_DB novalue,
    SCHEDULE_STATE_AST : DTE_CCB_DB novalue,
    SCHEDULE_TRANSIENT_AST : DTE_CCB_DB novalue,
    SCHEDULE_TRANSMIT : DTE_CCB_DB_STS novalue,
    SEND_PERSISTENT_ERROR : DTE_DB_STS novalue,
    SEND_STATE : DTE_DB novalue,
    SEND_TRANSIENT_ERROR : DTE_DB_STS novalue,
    TIMCCB : MCB_DB_CCB novalue,
    TIMLTM : MCB_DB novalue,
    TIMPIN : MCB_DB novalue,
    TIMPWF : MCB_DB novalue,
    TIMRDB : MCB_DB_CCB novalue,
    TRANSMIT_MESSAGE : DTE_DB novalue,
    TRANSMIT_SEGMENT : DTE_DB novalue,
    T10DON : DTE_DB novalue,
    T11DON : DTE_DB novalue,
    WTEXDP : DTE_DB_DTE;

global bind routine
    DTEIN = DTE_INTERRUPT : MCB_INTERRUPT novalue;

!
! MACROS:
!

macro
    FLUSH_QUEUE (QUEUE, RETURN_CALL) =
	while 1 eql 1 do
	    begin

	    local
		CCB;

	    if not CMQRM$ (QUEUE, CCB) then exitloop;

	    RETURN_CALL (.CCB %if not %null (%remaining) %then , %remaining %fi);
	    end %;

macro
    !
    ! Add the specified value to an 18 bit address in the data base
    !
    PHYSICAL_ADD (DB, FLD, VALUE) =
	begin

	builtin
	    rot;

	if rot (DB [$SUB_FIELD (FLD, PHYSICAL_LOW)] =
	    .DB [$SUB_FIELD (FLD, PHYSICAL_LOW)] + VALUE, 1)
	then
	    DB [$SUB_FIELD (FLD, PHYSICAL_HIGH)] =
		.DB [$SUB_FIELD (FLD, PHYSICAL_HIGH)] + 1;

	end %;

macro
    !
    ! Produce a mask for the given field
    !
    DTE_BIT [FLD] =
	(1^%fieldexpand (FLD, 2) - 1)^%fieldexpand (FLD, 1) %,
    !
    ! Set the buss extension bits and the delay count
    !
    DTE_EXT (CSR, BITS) =
	begin

	field
	    DLYOFF = [-%fieldexpand (DLYCNT, 0), 0, 16, 0],
	    DLYWRD = [0, 0, 16, 0];

	bind
	    REG = CSR : block volatile;

	local
	    VALUE : block [1] FIELD (DLYWRD);

	VALUE [DLYWRD] = 0;
	VALUE [$SUB_FIELD (DLYOFF, BUSEXT)] = BITS;
	REG [$SUB_FIELD (DLYCNT, DLYWRD)] = .VALUE [DLYWRD];
	end %,
    !
    ! Reset the DTE
    !
    DTE_RESET (CSR) =
	begin

	bind
	    REG = CSR : block volatile field (DIAG2);

	REG [DIAG2] = DTE_BIT (DRESET)
	end %,
    !
    ! Check if the TO-11 doorbell is ringing
    !
    DTE_RINGING (CSR) =
	begin

	bind
	    REG = CSR : volatile;

	(.REG and DTE_BIT (TO11DB)) neq 0
	end %,
    !
    ! Set the specified bits in the DTE status register
    !
    DTE_SET (CSR) =
	begin

	bind
	    REG = CSR : volatile;

	REG = +DTE_BIT (%remaining)
	end %,
    !
    ! Test if any of the specified bits are on in the DTE status register
    !
    DTE_TEST (CSR) =
	begin

	bind
	    REG = CSR : volatile;

	(.REG and +DTE_BIT (%remaining)) neq 0
	end %;

!
! EQUATED SYMBOLS:
!

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

literal
    LCL = 0,
    RMT = 1;

global literal
    %name ('D.LEN') = %fieldexpand (D_XBUF, 0)*%upval;

macro
    C_HANDLE = %fieldexpand (C_LIX, 0), 0, 16, 0 %;

!
! OWN STORAGE:
!

external routine
    $DSPCR : novalue;

$MCB_PROCESS (
    NAME = DTE,					! Process name
    DLC_DISPATCH = TABLE$ ($DSPCR, FC_CCP,	! DLL interface dispatch vector
	(FC_CTL, DTECTL),			!  Control functions
	(FC_XME, DTEXME),			!  Transmit functions
	(FC_RCE, DTERCE),			!  Receive buffer returns
	(FC_TIM, DTETIM)))			!  Timeout

external routine
    DTENM : MCB_CCB novalue;

!
! EXTERNAL REFERENCES:
!

external routine
    DTEDBI : novalue,
    DTEDVI,
    DTENMI;

external
    MCB$GA_PROCESS_DISPATCH : ref vector,
    MCB$GAW_PROCESS_DATA_BASE : vector [2],
    MCB$GW_PROCESS_HANDLE,
    MCB$GW_RDB_SIZE;		! Size of RDB buffer.

bind
    DB_BIAS = MCB$GAW_PROCESS_DATA_BASE [0];

macro
    GET_DTE_DATA_BASE (NAME) =
	%if %declared (NAME)
	%then map NAME : ref
	%else bind NAME = .MCB$GAW_PROCESS_DATA_BASE [1] :
	%fi block field (D_FIELDS); %;
routine ANSWER_DOORBELL (DB) : DTE_DB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)
    CLEAR_DOORBELL (DB [D_TIM]);

    case .DB [D_PROTOCOL_STATE] from DS_STA_LOW to DS_STA_HIGH of
	set

	[DS_INITIALIZING] :

	    if .DB [$SUB_FIELD (D_RST, V)]
	    then

		if .DB [$SUB_FIELD (D_RST, I)]
		then
		    begin
		    ! *************** Protocol deviation ******************
		    ! Our INIT bit is on, and would normally be turned off.
		    ! But the -20 never expects us to initialize protocol,
		    ! so we must leave our init bit on until he drops his.
		    ! *****************************************************
		    DEPMYH (DB [D_TIM], STATUS, DB [D_XST]);
		    DTE_SET (.DB [D_REGISTER], INT10S, INTRON);
		    DB [D_LONG_TIMER] = DTE_K_START_TIMEOUT;
		    end
		else
		    begin

		    if .DB [$SUB_FIELD (D_XST, I)]
		    then
			begin
			DB [$SUB_FIELD (D_XST, I)] = 0;
			DEPMYH (DB [D_TIM], STATUS, DB [D_XST]);
			DTE_SET (.DB [D_REGISTER], INT10S, INTRON);
			DB [D_LONG_TIMER] = DTE_K_START_TIMEOUT;
			CHANGE_PROTOCOL_STATE (DB [D_TIM], DS_RUNNING, LCL);
			end
		    else
			CHANGE_PROTOCOL_STATE (DB [D_TIM], DS_RUNNING, RMT);

		    TRANSMIT_MESSAGE (DB [D_TIM]);
		    RECEIVE_MESSAGE (DB [D_TIM]);
		    end;

	[DS_RUNNING] :

	    if not PAUSED (DB [D_TIM])
	    then

		if not INITIALIZATION_REQUESTED (DB [D_TIM])
		then
		    RECEIVE_MESSAGE (DB [D_TIM]);

	[DS_PAUSED] :

	    if .DB [$SUB_FIELD (D_RST, V)]
	    then
		begin
		CHANGE_PROTOCOL_STATE (DB [D_TIM], DS_RUNNING, RMT);

		if not INITIALIZATION_REQUESTED (DB [D_TIM])
		then
		    RECEIVE_MESSAGE (DB [D_TIM]);

		end;

	[inrange] :
	    NO_OPERATION;

	tes;

    end;			!of routine ANSWER_DOORBELL
routine CHANGE_PROTOCOL_STATE (DB, STATE, REASON) : DTE_DB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)
    DB [D_PROTOCOL_STATE] = .STATE;
    SEND_STATE (DB [D_TIM]);
    end;			!of routine CHANGE_PROTOCOL_STATE
routine CLEAR_DOORBELL (DB) : DTE_DB =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    local
	STATUS;

    STATUS = FALSE;

    do
	begin
	DTE_SET (.DB [D_REGISTER], INT11C);

	if not DTE_RINGING (.DB [D_REGISTER]) then return STATUS = TRUE;

	end
    until (STATUS = .STATUS - 1) eql FALSE;

    COUNTER_INCREMENT (DB, D_DOORBELL_STUCK);
    COUNTER_INCREMENT (DB, D_DEVICE_SERVICE_ERRORS);
    .STATUS
    end;			!of routine CLEAR_DOORBELL
routine CTLSTP (DB, CCB) : DTE_DB_CCB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!	CCB = address of CTL/STP CCB.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    map
	CCB : ref block field (C_FIELDS);

    DB [DF_NOTIFY_STATE] = FALSE;
    DB [D_TRANSIENT_ERROR] = 0;
    DB [D_PERSISTENT_ERROR] = 0;
    DB [D_OWNER_HANDLE] = 0;
    CCB [C_STS] = DLL$_SUCCESS;
    CCB [C_FNC] = FC_CCP;

    if .DB [D_ACTIVE_BUFFERS] neq 0
    then
	begin
	DB [DF_CONTROL_WAITING] = TRUE;
	CMQIN$ (DB [D_PENDING_CONTROLS], .CCB);
	end
    else
	$MCB_SCHEDULE_CCB (.CCB);

    end;			!of routine CTLSTP
routine CTLSTR (DB, CCB) : DTE_DB_CCB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!	CCB = address of CTL/STP CCB.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    map
	CCB : ref block field (C_FIELDS);

    bind
	STATUS = TABLE$ (0, 0,
	    (DS_HALTED^1, DLL$_STATE_OFF),
	    (DS_COM^1, DLL$_STATE_SYNCHRONIZING),
	    (DS_INITIALIZING^1, DLL$_STATE_SYNCHRONIZING),
	    (DS_RUNNING^1, DLL$_STATE_RUNNING),
	    (DS_PAUSED^1, DLL$_STATE_RUNNING)) : vector [5];

    DB [D_OWNER_HANDLE] = .CCB [C_HANDLE];

    if .CCB [C_PRM1] eql 0
    then
	CCB [C_PRM1] = .DB [D_CIRCUIT_COST];

    CCB [C_STS] = CURRENT_STATUS (DB [D_TIM]);
    CCB [C_FNC] = FC_CCP;
    $MCB_SCHEDULE_CCB (.CCB);
    end;			!of routine CTLSTR
routine CURRENT_STATUS (DB) : LINKAGE_DB =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    literal
	DLL_OFF = 0,
	DLL_SYNCHRONIZING = 1,
	DLL_RUNNING = 2,
	DLL_MAINTENANCE = 3;

    bind
	REPORT_STATUS = TABLE$ (0, 0,
	    (DS_HALTED^1, DLL_OFF),
	    (DS_COM^1, DLL_SYNCHRONIZING),
	    (DS_INITIALIZING^1, DLL_SYNCHRONIZING),
	    (DS_RUNNING^1, DLL_RUNNING),
	    (DS_PAUSED^1, DLL_RUNNING)) : vector,
	DLL_STATUS = TABLE$ (0, 0,
	    (DLL_OFF^1, DLL$_STATE_OFF),
	    (DLL_SYNCHRONIZING^1, DLL$_STATE_SYNCHRONIZING),
	    (DLL_RUNNING^1, DLL$_STATE_RUNNING),
	    (DLL_MAINTENANCE^1, DLL$_STATE_MAINTENANCE)) : vector;

    if .DB [DF_NOTIFY_OFF]
    then
	begin
	DB [DF_NOTIFY_OFF] = FALSE;

	if .DB [D_PROTOCOL_STATE] eql DS_HALTED
	then
	    DB [DF_NOTIFY_STATE] = FALSE;

	return .DLL_STATUS [DB [D_REPORTED_STATE] = DLL_OFF];
	end;

    DB [DF_NOTIFY_STATE] = FALSE;
    .DLL_STATUS [DB [D_REPORTED_STATE] = .REPORT_STATUS [.DB [D_PROTOCOL_STATE]]]
    end;			!of routine CURRENT_STATUS
routine DEPMYG (DB, OFFSET, BUFFER) : EXDP_LINKAGE =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!	OFFSET = comm/region offset.
!	BUFFER = address of 3 word buffer of data to deposit.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)
    PRTDEP (DB [D_TIM], .OFFSET, .BUFFER)
    end;			!of routine DEPMYG
routine DEPMYH (DB, OFFSET, BUFFER) : EXDP_LINKAGE =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!	OFFSET = comm/region offset.
!	BUFFER = address of 3 word buffer of data to deposit.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)
    PRTDEP (DB [D_TIM], .OFFSET + .DB [D_DMH], .BUFFER)
    end;			!of routine DEPMYH
routine DEVICE_BROKEN (DB) : DTE_DB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)
    DTESTP (DB [D_TIM]);
    end;			!of routine DEVICE_BROKEN
routine DLLINI (DB, CCB) : DTE_DB_CCB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!	CCB = address of CCB.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    map
	CCB : ref block field (C_FIELDS);

    if .DB [D_PROTOCOL_STATE] neq DS_HALTED
    then
	DTESTP (DB [D_TIM]);

    DB [D_REQUESTED_STATE] = DS_RUNNING;

    if .DB [D_LINE_STATE] eql DL_ON
    then
	DTESTR (DB [D_TIM]);

    CCB [C_FNC] = FC_XCP;
    CCB [C_STS] = DLL$_SUCCESS;
    $MCB_SCHEDULE_CCB (.CCB);

    if .DB [D_DEVICE_STATE] eql DD_CLEARED
    then
	begin
	SEND_PERSISTENT_ERROR (DB [D_TIM], DLL$_DEVICE_OPERATION_ERROR);
	SEND_STATE (DB [D_TIM]);
	end;

    end;			!of routine DLLINI
routine DLLMOP (DB, CCB) : DTE_DB_CCB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!	CCB = address of CCB.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    map
	CCB : ref block field (C_FIELDS);

    CCB [C_FNC] = FC_XCP;
    CCB [C_STS] = DLL$_NOT_SUPPORTED;
    $MCB_SCHEDULE_CCB (.CCB);
    end;			!of routine DLLMOP
routine DLLSTP (DB, CCB) : DTE_DB_CCB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!	CCB = address of CCB.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    map
	CCB : ref block field (C_FIELDS);

    DB [D_REQUESTED_STATE] = DS_HALTED;

    if .DB [D_PROTOCOL_STATE] neq DS_HALTED
    then
	DTESTP (DB [D_TIM]);

    CCB [C_FNC] = FC_XCP;
    CCB [C_STS] = DLL$_SUCCESS;
    $MCB_SCHEDULE_CCB (.CCB);
    end;			!of routine DLLSTP
routine DLLXMT (DB, CCB) : DTE_DB_CCB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!	CCB = address of transmit CCB.
!	MODIFIER = transmit function modifier (from C_MOD of CCB).
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    map
	CCB : ref block field (C_FIELDS);

    DB [D_ACTIVE_BUFFERS] = .DB [D_ACTIVE_BUFFERS] + 1;

    case .DB [D_PROTOCOL_STATE] from DS_STA_LOW to DS_STA_HIGH of
	set
	[DS_RUNNING, DS_PAUSED] :
	    begin
	    CMQIN$ (DB [D_XMQ], .CCB);

	    if .CCB [C_CHN] neqa 0
	    then
		begin

		local
		    MSG_CNT;

		MSG_CNT = .DB [D_DL_BLK];

		do
		    begin

		    if (MSG_CNT = .MSG_CNT - .CCB [C_CNT]) lss 0
		    then
			SIGNAL_STOP (DTE$_XMT_MTL, .DB [D_DL_BLK]);

		    end
		while (CCB = .CCB [C_CHN]) neqa 0;

		end;

	    if .DB [D_PROTOCOL_STATE] eql DS_RUNNING
	    then
		TRANSMIT_MESSAGE (DB [D_TIM]);

	    end;
	[inrange] :
	    SCHEDULE_TRANSMIT (.CCB, DB [D_TIM], DLL$_ABORTED);
	tes;

    end;			!of routine DLLXMT
routine DTE_INTERRUPT (DB) : MCB_INTERRUPT novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    if .DB [DF_SYNCHRONIZING] then return;

    DB [DF_SYNCHRONIZING] = TRUE;
    SYNCH$ (.DB [D_SYNCH_BLOCK], DTE_SYNCHRONIZE);
    end;			!of routine DTE_INTERRUPT
routine DTE_SYNCHRONIZE (DB) : MCB_DB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)
    DB [DF_SYNCHRONIZING] = FALSE;

    case .DB [D_PROTOCOL_STATE] from DS_STA_LOW to DS_STA_HIGH of
	set
	[DS_COM] :
	    GETCOM (DB [D_TIM]);

	[DS_RUNNING, DS_PAUSED] :

	    if DTE_TEST (.DB [D_REGISTER], TO10ER, TO11ER)
	    then
		begin
		$NM_PLL_EVENT (3, .DB [D_LINE_ENTITY],
		    PARAMETER_DEVICE_REGISTERS (.DB [D_REGISTER]));
		SEND_PERSISTENT_ERROR (DB [D_TIM], DLL$_DEVICE_OPERATION_ERROR);
					! Transfer error.
		DEVICE_BROKEN (DB [D_TIM]);
		end
	    else
		begin

		if DTE_TEST (.DB [D_REGISTER], TO10DN) then T10DON (DB [D_TIM]);

		if DTE_TEST (.DB [D_REGISTER], TO11DN) then T11DON (DB [D_TIM]);

		end;

	[inrange] :
	    NO_OPERATION;

	tes;

    case .DB [D_PROTOCOL_STATE] from DS_STA_LOW to DS_STA_HIGH of
	set
	[DS_INITIALIZING, DS_RUNNING, DS_PAUSED] :
	    begin
	    GET_HIS_STATUS (DB [D_TIM]);

	    if DTE_RINGING (.DB [D_REGISTER])
	    then
		ANSWER_DOORBELL (DB [D_TIM]);

	    end;

	[inrange] :
	    NO_OPERATION;

	tes;

    if .DB [D_PROTOCOL_STATE] eql DS_RUNNING
    then

	if not PAUSED (DB [D_TIM])
	then

	    if not INITIALIZATION_REQUESTED (DB [D_TIM])
	    then
		begin
		TRANSMIT_MESSAGE (DB [D_TIM]);
		RECEIVE_MESSAGE (DB [D_TIM]);
		end;

    end;			!of routine DTE_SYNCHRONIZE
routine DTECTL (DB, CCB, MODIFIER) : MCB_DB_CCB_MOD novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!	CCB = address of CTL CCB.
!	MODIFIER = control function modifier (from C_MOD of CCB).
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    map
	CCB : ref block field (C_FIELDS);

    DISPATCH$ (.MODIFIER,
	TABLE$ ($DSPCR, FD_CTL,
	    (FM_NM, DTENM),
	    (FM_STR, CTLSTR),
	    (FM_STP, CTLSTP)),
	(DB [D_TIM], .CCB),
	MCB_DB_CCB);
    end;			!of routine DTECTL
routine DTERCE (DB, CCB) : MCB_DB_CCB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!	CCB = address of returned data RDB.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)
    RDBRT$ (.CCB);
    DB [D_ACTIVE_BUFFERS] = .DB [D_ACTIVE_BUFFERS] - 1;

    if .DB [D_ACTIVE_BUFFERS] neq 0 then return;

    if .DB [DF_CONTROL_WAITING]
    then
	begin
	DB [DF_CONTROL_WAITING] = FALSE;
	FLUSH_QUEUE (DB [D_PENDING_CONTROLS], %quote $MCB_SCHEDULE_CCB);
	end;

    end;			!of routine DTERCE
global routine DTESTP (DB) : DTE_DB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)
    DTE_SET (.DB [D_REGISTER], INTROF);
    DB [$SUB_FIELD (D_XQZ, CSIZE)] = 0;
    DB [$SUB_FIELD (D_XQZ, PSIZE)] = 0;
    DEPMYH (DB [D_TIM], QSIZE, DB [D_XQZ]);
    DB [D_XCB] = 0;
    DB [D_XCT] = 0;
    DB [$SUB_FIELD (D_XST, V)] = 0;
    DB [$SUB_FIELD (D_XST, RCV)] = 0;
    DB [$SUB_FIELD (D_XST, CPQCNT)] = 0;
    DB [$SUB_FIELD (D_XST, QCOUNT)] = 0;
    DEPMYH (DB [D_TIM], STATUS, DB [D_XST]);
    DB [D_TIM] = 0;
    DB [D_LONG_TIMER] = 0;
    DTE_RESET (.DB [D_REGISTER]);
    FLUSH_QUEUE (DB [D_XMQ], %quote SCHEDULE_TRANSMIT, DB [D_TIM], DLL$_ABORTED);
    begin

    local
	CCB;

    if (CCB = .DB [D_RCB]) neq 0
    then
	begin
	RDBRT$ (.CCB);
	DB [D_RCB] = 0;
	DB [D_RCT] = 0;
	end;

    end;
    CHANGE_PROTOCOL_STATE (DB [D_TIM], DS_HALTED, LCL);
    end;			!of routine DTESTP
global routine DTESTR (DB) : DTE_DB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    if .DB [D_DEVICE_STATE] eql DD_CLEARED
    then
	return;

    CHANGE_PROTOCOL_STATE (DB [D_TIM], DS_COM, LCL);
    DB [D_START_THRESHOLD] = 7;
    DTE_SET (.DB [D_REGISTER], INTRON);
    DB [D_TIM] = .DB [D_TIM] + 1;
    GETCOM (DB [D_TIM]);
    end;			!of routine DTESTR
routine DTETIM (DB, MODIFIER) : MCB_DB_MOD novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!	MODIFIER = timer function modifier.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)
    DISPATCH$ (
	.MODIFIER,
	TABLE$ ($DSPCR, FD_TIM,			! Dispatch table:
	    (FM_LTM, TIMLTM),			!  Long timer
	    (FM_CCB, TIMCCB),			!  CCB available
	    (FM_RDB, TIMRDB),			!  RDB available
	    (FM_PWF, TIMPWF),			!  Power failure
	    (FM_PIN, TIMPIN)),			!  Process initialization
	(DB [D_TIM]),
	MCB_DB);
    end;			!of routine DTETIM
routine DTEXME (DB, CCB, MODIFIER) : MCB_DB_CCB_MOD novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!	CCB = address of transmit CCB.
!	MODIFIER = transmit function modifier (from C_MOD of CCB).
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    map
	CCB : ref block field (C_FIELDS);

    DISPATCH$ (
	.MODIFIER,
	TABLE$ ($DSPCR, 0,
	    (DLL$K_ENTER_MAINTENANCE, DLLMOP),
	    (DLL$K_INITIALIZE_LINK, DLLINI),
	    (DLL$K_STOP_LINK, DLLSTP),
	    (DLL$K_TRANSMIT, DLLXMT),
	    (DLL$K_TRANSMIT_AND_TIME, DLLXMT)),
	(DB [D_TIM], .CCB),
	DTE_DB_CCB);
    end;			!of routine DTEXME
routine EXMHSG (DB, OFFSET, BUFFER) : EXDP_LINKAGE =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!	OFFSET = comm/region offset.
!	BUFFER = address of 3 word buffer to receive examined data.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)
    PRTEXM (DB [D_TIM], .OFFSET + .DB [D_EHG], .BUFFER)
    end;			!of routine EXMHSG
routine EXMHSM (DB, OFFSET, BUFFER) : EXDP_LINKAGE =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!	OFFSET = comm/region offset.
!	BUFFER = address of 3 word buffer to receive examined data.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)
    PRTEXM (DB [D_TIM], .OFFSET + .DB [D_EHM], .BUFFER)
    end;			!of routine EXMHSM
routine EXMMYG (DB, OFFSET, BUFFER) : EXDP_LINKAGE =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!	OFFSET = comm/region offset.
!	BUFFER = address of 3 word buffer to receive examined data.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)
    PRTEXM (DB [D_TIM], .OFFSET + .DB [D_EMG], .BUFFER)
    end;			!of routine EXMMYG
routine EXMMYH (DB, OFFSET, BUFFER) : EXDP_LINKAGE =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!	OFFSET = comm/region offset.
!	BUFFER = address of 3 word buffer to receive examined data.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)
    PRTEXM (DB [D_TIM], .OFFSET + .DB [D_DMH] + .DB [D_EMG], .BUFFER)
    end;			!of routine EXMMYH
routine GET_HIS_STATUS (DB) : EXM_LINKAGE novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    local
	BUFFER : ref vector;

    BUFFER = DB [D_RST];

    if not EXMHSM (DB [D_TIM], STATUS, .BUFFER)
    then
	begin
	BUFFER [0] = 0;
	BUFFER [1] = 0;
	BUFFER [2] = 0;
	BUFFER = BUFFER [2]; %(to force auto-increment)%
	end;

    end;			!of routine GET_HIS_STATUS
routine GETCOM (DB) : DTE_DB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    literal
	SUCCESS = not -1 %(while 0 do 0)%;

    local
	BUFFER : ref block field (COM_FIELDS);

    DB [D_LONG_TIMER] = DTE_K_START_TIMEOUT;
    BUFFER = DB [D_RST];

    if not PRTEXM (DB [D_TIM], 0, .BUFFER) then return;

    DB [D_MPN] = .BUFFER [PRCNUM];
    DB [D_EMG] = .DB [D_MPN] + 1 + .BUFFER [RELADR];

    if not EXMMYG (DB [D_TIM], PIDENT, .BUFFER) then return;

    DB [D_DMH] = .BUFFER [NPRSIZ]^3;

    if (decr INDEX from .BUFFER [NPRCNT] to 1 do
	begin

	if not EXMMYH (DB [D_TIM], FORPRO, .BUFFER) then return;

	if  .BUFFER [D] and
	    .BUFFER [DTN] eql .DB [D_CONTROLLER]
	then
	    exitloop SUCCESS;

	begin

	local
	    SIZE;

	SIZE = .BUFFER [PROSIZ];

	if .SIZE eql 0 then SIZE = .SIZE + 1;

	DB [D_DMH] = .DB [D_DMH] + .SIZE^3;
	end
	end) neq SUCCESS
    then
	return;

    if .BUFFER [PROTYP] neq 1 then return;

    DB [D_HPN] = .BUFFER [TOPRCN];

    if not EXMMYH (DB [D_TIM], PROPNT, .BUFFER) then return;

    DB [D_EHG] = .DB [D_MPN] + 1 + .BUFFER [0, 0, 16, 0];

    if not EXMHSG (DB [D_TIM], PIDENT, .BUFFER) then return;

    DB [D_EHM] = .BUFFER [NPRSIZ]^3 + .DB [D_EHG];

    if (decr INDEX from .BUFFER [NPRCNT] to 1 do
	begin

	if not EXMHSM (DB [D_TIM], FORPRO, .BUFFER) then return;

	if .BUFFER [TOPRCN] eql .DB [D_MPN]
	then
	    exitloop SUCCESS;

	begin

	local
	    SIZE;

	SIZE = .BUFFER [PROSIZ];

	if .SIZE eql 0 then SIZE = .SIZE + 1;

	DB [D_EHM] = .DB [D_EHM] + .SIZE^3;
	end
	end) neq SUCCESS
    then
	return;

    if not EXMHSM (DB [D_TIM], STATUS, .BUFFER) then return;

    if not .BUFFER [V] then return;

    CHANGE_PROTOCOL_STATE (DB [D_TIM], DS_INITIALIZING, LCL);
    DB [D_START_THRESHOLD] = 7;
    CLEAR_DOORBELL (DB [D_TIM]);
    DEPMYH (DB [D_TIM], QSIZE, DB [D_XQZ]);
    DB [$SUB_FIELD (D_XST, I)] = 1;
    DB [$SUB_FIELD (D_XST, V)] = 1;
    DEPMYH (DB [D_TIM], STATUS, DB [D_XST]);
    DTE_SET (.DB [D_REGISTER], INT10S);
    end;			!of routine GETCOM
routine INITIALIZATION_REQUESTED (DB) : DTE_DB =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    if .DB [$SUB_FIELD (D_RST, I)]
    then
	begin
	SEND_PERSISTENT_ERROR (DB [D_TIM], DLL$_START_RECEIVED);
	DTESTP (DB [D_TIM]);
	TRUE
	end
    else
	false

    end;			!of routine INITIALIZATION_REQUESTED
routine NEW_RCB (DB, CCB) : DTE_DB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!	CCB = address of new receive buffer CCB.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    map
	CCB : ref block field (C_FIELDS);

    CCB [C_CNT] = 0;
    DB [D_RCB] = .CCB;
    $MCB_CONVERT_TO_UBA_ADDRESS ((.CCB [C_BIAS], .CCB [C_ADDR]),
	DB [$SUB_FIELD (D_RBA, PHYSICAL_LOW)],
	DB [$SUB_FIELD (D_RBA, PHYSICAL_HIGH)]);
    end;			!of routine NEW_RCB
global routine PARAMETER_DEVICE_REGISTERS

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
       (REG : ref vector)
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
	: DTE_REG novalue =
!
! SIDE EFFECTS:
!	None
!--

    begin

    !
    ! Adjust to beginning of register set
    !

    REG <0, 5> = 0;

    !
    ! DTE registers
    !

    decr COUNT from 16 to 1 do
	begin
	PARAMETER_H_2 (0, REG [0]);
	REG = REG [1];
	end;

    end;			!of routine PARAMETER_DEVICE_REGISTERS
routine PAUSED (DB) : DTE_DB =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    if not .DB [$SUB_FIELD (D_RST, V)]
    then
	begin
	CHANGE_PROTOCOL_STATE (DB [D_TIM], DS_PAUSED, RMT);
	DB [D_LONG_TIMER] = DTE_K_PAUSE_TIMEOUT;
	TRUE
	end
    else
	false

    end;			!of routine PAUSED
routine PROTOCOL_BROKEN (DB) : DTE_DB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)
    DTESTP (DB [D_TIM]);
    end;			!of routine PROTOCOL_BROKEN
routine PRTDEP (DB, OFFSET, BUFFER) : EXDP_LINKAGE =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!	OFFSET = comm/region offset.
!	BUFFER = address of 3 word buffer of data to deposit.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    map
	BUFFER : ref vector [3];

    local
	DTE : ref block field (DTE_FIELDS);

    DTE = .DB [D_REGISTER];
    DTE [$SUB_FIELD (DEXWD, DEXWD3)] = .BUFFER [0];
    DTE [$SUB_FIELD (DEXWD, DEXWD2)] = .BUFFER [1];
    DTE [$SUB_FIELD (DEXWD, DEXWD1)] = .BUFFER [2];
    DTE [$SUB_FIELD (TENAD, TENAD1)] = DTE_BIT (DEP);
    DTE [$SUB_FIELD (TENAD, TENAD2)] = .OFFSET;
    WTEXDP (DB [D_TIM], .DTE)
    end;			!of routine PRTDEP
routine PRTEXM (DB, OFFSET, BUFFER) : EXDP_LINKAGE =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!	OFFSET = comm/region offset.
!	BUFFER = address of 3 word buffer to receive examined data.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    map
	BUFFER : ref vector [3];

    local
	DTE : ref block field (DTE_FIELDS);

    local
	STATUS;

    DTE = .DB [D_REGISTER];
    DTE [$SUB_FIELD (TENAD, TENAD1)] = 0;
    DTE [$SUB_FIELD (TENAD, TENAD2)] = .OFFSET;
    STATUS = WTEXDP (DB [D_TIM], .DTE);
    BUFFER [0] = .DTE [$SUB_FIELD (DEXWD, DEXWD3)];
    BUFFER [1] = .DTE [$SUB_FIELD (DEXWD, DEXWD2)];
    BUFFER [2] = .DTE [$SUB_FIELD (DEXWD, DEXWD1)];
    .STATUS
    end;			!of routine PRTEXM
routine RECEIVE_MESSAGE (DB) : DTE_DB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    if .DB [$SUB_FIELD (D_RQZ, PSIZE)] neq 0
    then
	begin
	RECEIVE_SEGMENT (DB [D_TIM]);
	return;
	end;

    ! *********************** Protocol deviation **************************
    ! The -20 monitors MY CPQCNT instead of MY QCOUNT for TO-HIM transfers,
    ! so the roles of MY QCOUNT and MY CPQCNT are reversed from those in
    ! the protocol specification.
    ! *********************************************************************

    if .DB [$SUB_FIELD (D_RST, QCOUNT)] eql .DB [$SUB_FIELD (D_XST, QCOUNT)] then return;

    DB [$SUB_FIELD (D_XST, QCOUNT)] = .DB [$SUB_FIELD (D_XST, QCOUNT)] + 1;

    if .DB [$SUB_FIELD (D_RST, QCOUNT)] neq .DB [$SUB_FIELD (D_XST, QCOUNT)]
    then
	begin
	$NM_PLL_EVENT (4, .DB [D_LINE_ENTITY],
	    PARAMETER_DEVICE_REGISTERS (.DB [D_REGISTER]));
	DB [$SUB_FIELD (D_XST, QCOUNT)] = .DB [$SUB_FIELD (D_XST, QCOUNT)] - 1;
	SEND_PERSISTENT_ERROR (DB [D_TIM], DLL$_DEVICE_OPERATION_ERROR);
	COUNTER_INCREMENT (DB, D_INVALID_QCOUNT);
	COUNTER_INCREMENT (DB, D_PROTOCOL_ERRORS);
	DEVICE_BROKEN (DB [D_TIM]);
	return;
	end;

    if .DB [D_RCB] eql 0
    then
	begin

	local
	    CCB;

	if RDBGT$ (CCB) then NEW_RCB (DB [D_TIM], .CCB);

	end;

    if .DB [D_RCB] eql 0
    then
	begin
	DB [$SUB_FIELD (D_XST, QCOUNT)] = .DB [$SUB_FIELD (D_XST, QCOUNT)] - 1;
	RDBRQ$ ();
	return;
	end;

    EXMHSM (DB [D_TIM], QSIZE, DB [D_RQZ]);

    if .DB [$SUB_FIELD (D_RQZ, PSIZE)] gtr .DB [D_DL_BLK]
    then
	begin
	$NM_DLL_EVENT (9, .DB [D_CIRCUIT_ENTITY],
	    PARAMETER_DU_2 (7, DB [$SUB_FIELD (D_RQZ, PSIZE)]),
	    PARAMETER_DU_2 (8, DB [D_DL_BLK]));
	DB [$SUB_FIELD (D_XST, QCOUNT)] = .DB [$SUB_FIELD (D_XST, QCOUNT)] - 1;
	SEND_PERSISTENT_ERROR (DB [D_TIM], DLL$_DEVICE_OPERATION_ERROR);
	COUNTER_INCREMENT (DB, D_MESSAGE_TOO_LONG);
	COUNTER_INCREMENT (DB, D_PROTOCOL_ERRORS);
	PROTOCOL_BROKEN (DB [D_TIM]);
	return;
	end;

    DB [$SUB_FIELD (D_XST, RCV)] = 1;
    DEPMYH (DB [D_TIM], STATUS, DB [D_XST]);
    RECEIVE_SEGMENT (DB [D_TIM]);
    end;			!of routine RECEIVE_MESSAGE
routine RECEIVE_SEGMENT (DB) : DTE_DB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    local
	DTE : ref block field (DTE_FIELDS);

    if .DB [D_RCT] neq 0 then return;

    if .DB [$SUB_FIELD (D_RQZ, PSIZE)] eql 0 then return;

    if .DB [$SUB_FIELD (D_RQZ, CSIZE)] eql 0 then return;

    if .DB [$SUB_FIELD (D_XMQ, LIST_FIRST)] neq 0 and
	.DB [$SUB_FIELD (D_RBA, PHYSICAL_HIGH)] neq
	.DB [$SUB_FIELD (D_XBA, PHYSICAL_HIGH)] then return;

    if .DB [DF_FLUSHING_DTE] then return;

    DTE = .DB [D_REGISTER];
    DTE_EXT (.DTE, .DB [$SUB_FIELD (D_RBA, PHYSICAL_HIGH)]);
    DTE [TO11AD] = .DB [$SUB_FIELD (D_RBA, PHYSICAL_LOW)];
    DB [D_RCT] = (if .DB [$SUB_FIELD (D_RBA, PHYSICAL_LOW)] eql 0
	then .DB [$SUB_FIELD (D_RQZ, CSIZE)]
	else MINU (-.DB [$SUB_FIELD (D_RBA, PHYSICAL_LOW)],
	    .DB [$SUB_FIELD (D_RQZ, CSIZE)]));
    begin

    local
	VALUE : block [1] field (TO11BM, TO11IB, TO11CM);

    VALUE = 0;

    if .DB [$SUB_FIELD (D_RQZ, CSIZE)] eql .DB [D_RCT] then VALUE [TO11IB] = 1;

    VALUE [TO11CM] = -(if .DB [$SUB_FIELD (D_RQZ, TMODE)] eql 0
    then
	begin
	VALUE [TO11BM] = 1;
	.DB [D_RCT]
	end
    else
	(.DB [D_RCT] + 1)^-1);

    DTE [TO11BC] = .VALUE;
    end;
    DB [D_LONG_TIMER] = DTE_K_TRANSMIT_DOORBELL_TIMEOUT + 2;
    end;			!of routine RECEIVE_SEGMENT
routine SCHEDULE_PERSISTENT_AST (CCB, DB) : DTE_CCB_DB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	CCB = address of CCB to use for status nodification.
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    map
	CCB : ref block field (C_FIELDS);

    CCB [C_HANDLE] = .DB [D_OWNER_HANDLE];
    CCB [C_FNC] = FC_AST;
    CCB [C_MOD] = DLL$K_PERSISTENT_ERROR;
    CCB [C_STS] = .DB [D_PERSISTENT_ERROR];
    $MCB_SCHEDULE_CCB (.CCB);
    DB [D_PERSISTENT_ERROR] = 0;
    end;			!of routine SCHEDULE_PERSISTENT_AST
routine SCHEDULE_RECEIVE (CCB, DB) : DTE_CCB_DB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    map
	CCB : ref block field (C_FIELDS);

    CCB [C_HANDLE] = .DB [D_OWNER_HANDLE];

    if .CCB [C_HANDLE] eqlu 0 then return RDBRT$ (.CCB);

    DB [D_ACTIVE_BUFFERS] = .DB [D_ACTIVE_BUFFERS] + 1;
    CCB [C_FNC] = FC_RCP;
    CCB [C_MOD] = DLL$K_DATA_RECEIVED;
    CCB [C_STS] = DLL$_SUCCESS;
    $MCB_SCHEDULE_CCB (.CCB);
    end;			!of routine SCHEDULE_RECEIVE
routine SCHEDULE_STATE_AST (CCB, DB) : DTE_CCB_DB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	CCB = address of CCB to use for status nodification.
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    map
	CCB : ref block field (C_FIELDS);

    if not .DB [DF_NOTIFY_STATE] then return $MCB_RETURN_CCB (.CCB);

    CCB [C_HANDLE] = .DB [D_OWNER_HANDLE];
    CCB [C_FNC] = FC_AST;
    CCB [C_MOD] = DLL$K_STATE;
    CCB [C_STS] = CURRENT_STATUS (DB [D_TIM]);
    $MCB_SCHEDULE_CCB (.CCB);

    if .DB [DF_NOTIFY_STATE]
    then

	if $MCB_GET_CCB (CCB)
	then
	    SCHEDULE_STATE_AST (.CCB, DB [D_TIM])
	else
	    $MCB_REQUEST_CCB ();

    end;			!of routine SCHEDULE_STATE_AST
routine SCHEDULE_TRANSIENT_AST (CCB, DB) : DTE_CCB_DB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	CCB = address of CCB to use for status nodification.
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
      GET_DTE_DATA_BASE (DB)

    map
	CCB : ref block field (C_FIELDS);

    CCB [C_HANDLE] = .DB [D_OWNER_HANDLE];
    CCB [C_FNC] = FC_AST;
    CCB [C_MOD] = DLL$K_TRANSIENT_ERROR;
    CCB [C_STS] = .DB [D_TRANSIENT_ERROR];
    $MCB_SCHEDULE_CCB (.CCB);
    DB [D_TRANSIENT_ERROR] = 0;
    end;			!of routine SCHEDULE_TRANSIENT_AST
routine SCHEDULE_TRANSMIT (CCB, DB, STATUS) : DTE_CCB_DB_STS novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    map
	CCB : ref block field (C_FIELDS);

    CCB [C_FNC] = FC_XCP;
    CCB [C_STS] = .STATUS;
    $MCB_SCHEDULE_CCB (.CCB);
    DB [D_ACTIVE_BUFFERS] = .DB [D_ACTIVE_BUFFERS] - 1;

    if .DB [D_ACTIVE_BUFFERS] neq 0 then return;

    if .DB [DF_CONTROL_WAITING]
    then
	begin
	DB [DF_CONTROL_WAITING] = FALSE;
	FLUSH_QUEUE (DB [D_PENDING_CONTROLS], %quote $MCB_SCHEDULE_CCB);
	end;

    end;			!of routine SCHEDULE_TRANSMIT
routine SEND_PERSISTENT_ERROR (DB, STATUS) : DTE_DB_STS novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    local
	CCB : ref block field (C_FIELDS);

    if .DB [D_OWNER_HANDLE] eql 0 then return;

    DB [D_PERSISTENT_ERROR] = .STATUS;

    if $MCB_GET_CCB (CCB)
    then
	SCHEDULE_PERSISTENT_AST (.CCB, DB [D_TIM])
    else
	$MCB_REQUEST_CCB ();

    end;			!of routine SEND_PERSISTENT_ERROR
routine SEND_STATE (DB) : DTE_DB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    local
	CCB : ref block field (C_FIELDS);

    if .DB [D_OWNER_HANDLE] eql 0 then return;

    if .DB [D_PROTOCOL_STATE] eql DS_HALTED then DB [DF_NOTIFY_OFF] = TRUE;

    DB [DF_NOTIFY_STATE] = TRUE;

    if $MCB_GET_CCB (CCB)
    then
	SCHEDULE_STATE_AST (.CCB, DB [D_TIM])
    else
	$MCB_REQUEST_CCB ();

    end;			!of routine SEND_STATE
routine SEND_TRANSIENT_ERROR (DB, STATUS) : DTE_DB_STS novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    local
	CCB : ref block field (C_FIELDS);

    if .DB [D_OWNER_HANDLE] eql 0 then return;

    DB [D_TRANSIENT_ERROR] = .STATUS;

    if $MCB_GET_CCB (CCB)
    then
	SCHEDULE_TRANSIENT_AST (.CCB, DB [D_TIM])
    else
	$MCB_REQUEST_CCB ();

    end;			!of routine SEND_TRANSIENT_ERROR
routine TIMCCB (DB, CCB) : MCB_DB_CCB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!	CCB = 
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    map
	CCB : ref block field (C_FIELDS);

    label
	RECOVERY;

    if .DB [D_OWNER_HANDLE] eql 0 then return $MCB_RETURN_CCB (.CCB);

    do RECOVERY :
	begin

	if .DB [DF_NOTIFY_STATE] or .DB [DF_NOTIFY_OFF]
	then
	    leave RECOVERY with SCHEDULE_STATE_AST (.CCB, DB [D_TIM]);

	if .DB [D_TRANSIENT_ERROR] neq 0
	then
	    leave RECOVERY with SCHEDULE_TRANSIENT_AST (.CCB, DB [D_TIM]);

	if .DB [D_PERSISTENT_ERROR] neq 0
	then
	    leave RECOVERY with SCHEDULE_PERSISTENT_AST (.CCB, DB [D_TIM]);

	return $MCB_RETURN_CCB (.CCB);
	end
    while $MCB_GET_CCB (CCB);

    end;			!of routine TIMCCB
routine TIMLTM (DB) : MCB_DB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)
    DB [D_TIM] = .DB [D_TIM] + 1;

    if .DB [D_DEVICE_STATE] eql DD_CLEARED then return;

    !
    ! Update my keep-alive and get his status.
    ! Handle lost doorbells
    !

    case .DB [D_PROTOCOL_STATE] from DS_STA_LOW to DS_STA_HIGH of
	set

	[DS_INITIALIZING, DS_RUNNING, DS_PAUSED] :
	    begin
	    DB [D_MKA] = .DB [D_MKA] + 1;
	    DEPMYG (DB [D_TIM], KPALIV, DB [D_MKA]);
	    GET_HIS_STATUS (DB [D_TIM]);

	    if DTE_RINGING (.DB [D_REGISTER])
	    then
		ANSWER_DOORBELL (DB [D_TIM]);

	    if .DB [D_PROTOCOL_STATE] EQL DS_RUNNING
	    then

		if not PAUSED (DB [D_TIM])
		then

		    if not INITIALIZATION_REQUESTED (DB [D_TIM])
		    then
			begin
			TRANSMIT_MESSAGE (DB [D_TIM]);
			RECEIVE_MESSAGE (DB [D_TIM]);
			end;

	    end;

	[inrange] :
	    NO_OPERATION;

	tes;

    if .DB [D_LONG_TIMER] neq 0
    then

	if (DB [D_LONG_TIMER] = .DB [D_LONG_TIMER] - 1) eql 0
	then

	    case .DB [D_PROTOCOL_STATE] from DS_STA_LOW to DS_STA_HIGH of
		set

		[DS_COM] :
		    begin
		    GETCOM (DB [D_TIM]);

		    if .DB [D_PROTOCOL_STATE] eql DS_COM
		    then %(device not ready)%

			if (DB [D_START_THRESHOLD] = .DB [D_START_THRESHOLD] - 1) eql 0
			then
			    begin
			    SEND_TRANSIENT_ERROR (DB [D_TIM], DLL$_TRANSMIT_THRESHOLD);
			    DB [D_START_THRESHOLD] = 7;
			    end;

		    end;

		[DS_INITIALIZING] :
		    begin %(initialization timeout)%
		    DB [D_LONG_TIMER] = DTE_K_START_TIMEOUT;

		    if (DB [D_START_THRESHOLD] = .DB [D_START_THRESHOLD] - 1) eql 0
		    then
			begin
			SEND_TRANSIENT_ERROR (DB [D_TIM], DLL$_TRANSMIT_THRESHOLD);
			DB [D_START_THRESHOLD] = 7;
			end;

		    end;

		[DS_RUNNING] :
			begin
			if .DB[ $sub_field( D_RST, RCV)] eql 0
			then
				begin
				COUNTER_INCREMENT( DB, D_LOST_DOORBELL);
				COUNTER_INCREMENT( DB, D_DEVICE_SERVICE_ERRORS);
				DTE_SET ( .DB[ D_REGISTER], INT10S);
				DB[ D_LONG_TIMER] = DTE_K_TRANSMIT_DOORBELL_TIMEOUT;
				end;
			end;

		[DS_PAUSED] :
		    if .DB [$SUB_FIELD (D_RST, V)]
		    then
			begin
			CHANGE_PROTOCOL_STATE (DB [D_TIM], DS_RUNNING, RMT);

			if not INITIALIZATION_REQUESTED (DB [D_TIM])
			then
			    begin
			    TRANSMIT_MESSAGE (DB [D_TIM]);
			    RECEIVE_MESSAGE (DB [D_TIM]);
			    end;
			end
		    else
			begin
			SEND_PERSISTENT_ERROR (DB [D_TIM], DLL$_PAUSE_TIMEOUT);
						! Pause too long
			DEVICE_BROKEN (DB [D_TIM]);
			end;

		[inrange] :
		    NO_OPERATION;

		tes;

    end;			!of routine TIMLTM
routine TIMPIN (DB) : MCB_DB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)
    DTEDBI ();
    DTEDVI ();
    DTENMI ();

    if .DB [D_LINE_STATE] eql DL_ON
    then
	$MCB_ENABLE_LONG_TIMER ();

    end;			!of routine TIMPIN
routine TIMPWF (DB) : MCB_DB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    SIGNAL_STOP (DTE$_PWF);
    end;			!of routine TIMPWF
routine TIMRDB (DB, CCB) : MCB_DB_CCB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!	CCB = address of requested RDB.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    if .DB [D_RCB] neqa 0 then return RDBRT$ (.CCB);

    case .DB [D_PROTOCOL_STATE] from DS_STA_LOW to DS_STA_HIGH of
	set

	[DS_RUNNING] :
	    begin
	    NEW_RCB (DB [D_TIM], .CCB);
	    RECEIVE_MESSAGE (DB [D_TIM]);
	    end;

	[DS_PAUSED] :
	    NEW_RCB (DB [D_TIM], .CCB);

	[inrange] :
	    RDBRT$ (.CCB);

	tes;

    end;			!of routine TIMRDB
routine TRANSMIT_MESSAGE (DB) : DTE_DB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    if .DB [$SUB_FIELD (D_XQZ, PSIZE)] eql 0 and .DB [$SUB_FIELD (D_XMQ, LIST_FIRST)] neq 0
    then
	begin

	local
	    CCB : ref block field (C_FIELDS);

	CCB = .DB [$SUB_FIELD (D_XMQ, LIST_FIRST)];
	DB [D_XLN] = 0;

	if .CCB [C_CHN] eql 0
	then
	    begin
	    DB [D_XCB] = .CCB;
	    $MCB_CONVERT_TO_UBA_ADDRESS ((.CCB [C_BIAS], .CCB [C_ADDR]),
		DB [$SUB_FIELD (D_XBA, PHYSICAL_LOW)],
		DB [$SUB_FIELD (D_XBA, PHYSICAL_HIGH)]);
	    DB [D_XCT] = .CCB [C_CNT];

	    do
		DB [D_XLN] = .DB [D_XLN] + .CCB [C_CNT]
	    while (CCB = .CCB [C_CHN]) neq 0;

	    end
	else
	    begin
	    DB [D_XCB] = 0;
	    $MCB_CONVERT_TO_UBA_ADDRESS ((.DB_BIAS, DB [D_XBUF]),
		DB [$SUB_FIELD (D_XBA, PHYSICAL_LOW)],
		DB [$SUB_FIELD (D_XBA, PHYSICAL_HIGH)]);

	    begin

	    local
		LENGTH;

	    LENGTH = $MCB_COPY_CHAIN_TO_BUFFER (.CCB, (.DB_BIAS, DB [D_XBUF]));
	    MAP$ (.DB_BIAS);
	    DB [D_XCT] = DB [D_XLN] = .LENGTH;
	    end;
	    end;

	DB [$SUB_FIELD (D_XQZ, PSIZE)] = .DB [D_XLN];
	end;

    TRANSMIT_SEGMENT (DB [D_TIM]);
    end;			!of routine TRANSMIT_MESSAGE
routine TRANSMIT_SEGMENT (DB) : DTE_DB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)

    local
	DTE : ref block field (DTE_FIELDS);

    if .DB [$SUB_FIELD (D_XQZ, PSIZE)] eql 0 then return;

    if .DB [$SUB_FIELD (D_XQZ, CSIZE)] neq 0 then return;

    if .DB [D_RCT] neq 0 and
	.DB [$SUB_FIELD (D_XBA, PHYSICAL_HIGH)] neq
	.DB [$SUB_FIELD (D_RBA, PHYSICAL_HIGH)] then return;

    if .DB [DF_FLUSHING_DTE] then return;

    DTE = .DB [D_REGISTER];

    if DTE_TEST (.DTE, TO10DB) then return;

    DTE_EXT (.DTE, .DB [$SUB_FIELD (D_XBA, PHYSICAL_HIGH)]);
    DB [$SUB_FIELD (D_XQZ, CSIZE)] =
	(if .DB [$SUB_FIELD (D_XBA, PHYSICAL_LOW)] eql 0
	then .DB [D_XCT]
	else MINU (-.DB [$SUB_FIELD (D_XBA, PHYSICAL_LOW)],
	.DB [D_XCT]));
    DB [$SUB_FIELD (D_XQZ, TMODE)] = 0;
    DEPMYH (DB [D_TIM], QSIZE, DB [D_XQZ]);
    DTE [TO10AD] = .DB [$SUB_FIELD (D_XBA, PHYSICAL_LOW)];
    begin

    local
	VALUE : block [1] field (TO10BM);

    VALUE = 0;
    VALUE [TO10BM] = 1;
    DTE [DIAG3] = .VALUE;
    end;
    ! *********************** Protocol deviation **************************
    ! The -20 monitors MY CPQCNT instead of MY QCOUNT for TO-HIM transfers,
    ! so the roles of MY QCOUNT and MY CPQCNT are reversed from those in
    ! the protocol specification.
    ! *********************************************************************
    DB [$SUB_FIELD (D_XST, CPQCNT)] = .DB [$SUB_FIELD (D_XST, CPQCNT)] + 1;
    DEPMYH (DB [D_TIM], STATUS, DB [D_XST]);
    DTE_SET (.DB [D_REGISTER], INT10S);
    DB[ D_LONG_TIMER] = DTE_K_TRANSMIT_DOORBELL_TIMEOUT;
    end;			!of routine TRANSMIT_SEGMENT
routine T10DON (DB) : DTE_DB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)
    PHYSICAL_ADD (DB, D_XBA, .DB [$SUB_FIELD (D_XQZ, CSIZE)]);
    if .DB[ D_PROTOCOL_STATE] eql DS_RUNNING
    then
	DB[ D_LONG_TIMER] = 0;

    if .block [.DB [D_REGISTER], $SUB_FIELD (TO10BC, TO10CM)] or
	begin
	DTE_SET (.DB [D_REGISTER], DON10C, ERR10C);
	.block [.DB [D_REGISTER], TO10AD] neq .DB [$SUB_FIELD (D_XBA, PHYSICAL_LOW)]
	end
    then
	begin	! Incomplete transfer.
	$NM_PLL_EVENT (4, .DB [D_LINE_ENTITY],
	    PARAMETER_DEVICE_REGISTERS (.DB [D_REGISTER]));
	SEND_PERSISTENT_ERROR (DB [D_TIM], DLL$_DEVICE_OPERATION_ERROR);
	COUNTER_INCREMENT (DB, D_TRANSMIT_BA_MISMATCH);
	COUNTER_INCREMENT (DB, D_FATAL_DEVICE_ERRORS);
	DEVICE_BROKEN (DB [D_TIM]);
	return;
	end;

    DB [$SUB_FIELD (D_XQZ, PSIZE)] = .DB [$SUB_FIELD (D_XQZ, PSIZE)] -
	.DB [$SUB_FIELD (D_XQZ, CSIZE)];

    if .DB [$SUB_FIELD (D_XQZ, PSIZE)] gtr 0
    then
	begin
	DB [D_XCT] = .DB [D_XCT] - .DB [$SUB_FIELD (D_XQZ, CSIZE)];

	if .DB [D_XCT] eql 0
	then
	    begin

	    local
		CCB : ref block field (C_FIELDS);

	    DB [D_XCB] = CCB = .block [.DB [D_XCB], C_CHN];
	    $MCB_CONVERT_TO_UBA_ADDRESS ((.CCB [C_BIAS], .CCB [C_ADDR]),
		DB [$SUB_FIELD (D_XBA, PHYSICAL_LOW)],
		DB [$SUB_FIELD (D_XBA, PHYSICAL_HIGH)]);
	    DB [D_XCT] = .CCB [C_CNT];
	    end;

	DB [$SUB_FIELD (D_XQZ, CSIZE)] = 0;
	TRANSMIT_SEGMENT (DB [D_TIM]);
	end
    else
	begin

	local
	    CCB : ref block field (C_FIELDS);

	DB [$SUB_FIELD (D_XQZ, CSIZE)] = 0;
	DEPMYH (DB [D_TIM], QSIZE, DB [D_XQZ]);

	if not CMQRM$ (DB [D_XMQ], CCB) then SIGNAL_STOP (DTE$_QUE, DB [D_XMQ]);

	COUNTER_ADD (DB, D_BYTES_SENT, .DB [D_XLN]);
	COUNTER_INCREMENT (DB, D_DATA_BLOCKS_SENT);
	DB [D_XLN] = 0;
	SCHEDULE_TRANSMIT (.CCB, DB [D_TIM], DLL$_SUCCESS);
	end;

    if .DB [DF_FLUSHING_DTE] and (.DB [D_RCT] eql 0)
    then
	DB [DF_FLUSHING_DTE] = FALSE;

    end;			!of routine T10DON
routine T11DON (DB) : DTE_DB novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	DB = address of DTE data base.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    GET_DTE_DATA_BASE (DB)
    PHYSICAL_ADD (DB, D_RBA, .DB [D_RCT]);

    if .block [.DB [D_REGISTER], $SUB_FIELD (TO11BC, TO11CM)] neq 0 or
	begin
	DTE_SET (.DB [D_REGISTER], DON11C, ERR11C);
	.block [.DB [D_REGISTER], TO11AD] neq .DB [$SUB_FIELD (D_RBA, PHYSICAL_LOW)]
	end
    then
	begin	! Incomplete transfer.
	$NM_PLL_EVENT (4, .DB [D_LINE_ENTITY],
	    PARAMETER_DEVICE_REGISTERS (.DB [D_REGISTER]));
	SEND_PERSISTENT_ERROR (DB [D_TIM], DLL$_DEVICE_OPERATION_ERROR);
	COUNTER_INCREMENT (DB, D_RECEIVE_BA_MISMATCH);
	COUNTER_INCREMENT (DB, D_FATAL_DEVICE_ERRORS);
	DEVICE_BROKEN (DB [D_TIM]);
	return;
	end;

    begin

    bind
	CCB = DB [D_RCB] : ref block field (C_FIELDS);

    CCB [C_CNT] = .CCB [C_CNT] + .DB [D_RCT];
    end;
    DB [$SUB_FIELD (D_RQZ, CSIZE)] = .DB [$SUB_FIELD (D_RQZ, CSIZE)] - .DB [D_RCT];
    DB [$SUB_FIELD (D_RQZ, PSIZE)] = .DB [$SUB_FIELD (D_RQZ, PSIZE)] - .DB [D_RCT];
    DB [D_RCT] = 0;

    if .DB [$SUB_FIELD (D_RQZ, PSIZE)] neq 0
    then
	RECEIVE_SEGMENT (DB [D_TIM])
    else
	begin

	bind
	    CCB = DB [D_RCB] : ref block field (C_FIELDS);

	DB [$SUB_FIELD (D_XST, RCV)] = 0;
	DEPMYH (DB [D_TIM], STATUS, DB [D_XST]);
	COUNTER_ADD (DB, D_BYTES_RECEIVED, .CCB [C_CNT]);
	COUNTER_INCREMENT (DB, D_DATA_BLOCKS_RECEIVED);
	SCHEDULE_RECEIVE (.CCB, DB [D_TIM]);
	DB [D_RCB] = 0;
	end;

    if .DB [DF_FLUSHING_DTE] and (.DB [$SUB_FIELD (D_XQZ, CSIZE)] eql 0)
    then
	DB [DF_FLUSHING_DTE] = FALSE;

    end;			!of routine T11DON
routine WTEXDP

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!
       (DB : ref block field (D_FIELDS),
	DTE : ref block field (DTE_FIELDS) volatile)
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
!
	: DTE_DB_DTE =
!
! SIDE EFFECTS:
!	None
!--

    begin

    local
	STATUS;

    STATUS = 1536;

    do
	begin

	if .DTE [$SUB_FIELD (STAT11, DEXDON)]
	then
	    begin

	    if not .DTE [$SUB_FIELD (STAT11, BPARER)]
	    then
		STATUS = TRUE;

	    exitloop;
	    end;

	end
    while (STATUS = .STATUS - 1) neq FALSE;

    .STATUS
    end;			!of routine WTEXDP
end
eludom