Google
 

Trailing-Edge - PDP-10 Archives - BB-P363B-SM_1985 - mcb/drivers/kdpkmc.b16
There are no other files named kdpkmc.b16 in the archive.
module KDPKMC (	! KMC11/DUP11 driver KMC routines
		ident = 'X04040',
		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 KDP Driver
!
! ABSTRACT:
!
!	This is the DDM process which services the KMC11 microprocessor
!	which controls DUP11 synchronous line devices.
!
! ENVIRONMENT: MCB V3.0
!
! AUTHOR: Alan D. Peckham	CREATION DATE: 9-Mar-81
!
! MODIFIED BY:
!
!	S. I. GOLDFARB, 25-MAR-1977
!	R. H. ROSENBAUM, 30-AUG-1977
!	L. J. TWAITS, 10-SEP-1977
!	D. B. TUTTLE, 10-OCT-1977
!
!	Alan D. Peckham, 16-APR-80: Version 4
! 01	- Split off from KDP module.
! 02	- Change K_INPUT_DATA to be 4 words.
! 03	- Add KMCPRM routine to supply NM parameters
! 04	- Avoid doing SIGNAL_STOPs on device errors.
!	  Add support for device error counters.
!--
!
! INCLUDE FILES:
!

library 'MCBLIB';

library 'XPORT';

library 'NMXLIB';

library 'KDPDAT';

!
! TABLE OF CONTENTS:
!

linkage
    KDP_CSR_MC_LNG = jsr (register = 1, register = 2, register = 3),
    KDP_CSR = jsr (register = 1);

forward routine
    DEVICE_BROKEN : LINKAGE_DB novalue,
    INPUT_TRANSFER : LINKAGE_DB novalue,
    KMC_INTERRUPT : MCB_INTERRUPT novalue,
    KMCDB : CALL$ novalue,
    KMCPRM : CALL$ novalue,
    KMCQUE : CALL$ novalue,
    KMCSTP : CALL$ novalue,
    KMCSTR : CALL$,
    KMCTIM : MCB_DB_MOD novalue,
    LOAD_MICROCODE : KDP_CSR_MC_LNG,
    OUTPUT_TRANSFER : LINKAGE_DB novalue,
    SERVICE_KMC : MCB_DB novalue,
    START_MICROCODE : KDP_CSR,
    TIMLTM : MCB_DB novalue,
    TIMPIN : MCB_DB novalue,
    TIMPWF : MCB_DB novalue;

!
! MACROS:
!
!	None
!
! EQUATED SYMBOLS:
!

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

literal
    REQUEST_TIMEOUT = 2;

global literal
    %name ('K.LEN') = K_LEN*%upval;

!
! OWN STORAGE:
!

external routine
    $DSPCR : novalue;

bind
    KMC_DISPATCH = TABLE$ ($DSPCR, FC_CCP,
	(FC_TIM, KMCTIM));
!
! EXTERNAL REFERENCES:
!

external routine
    COBAD : CALL$ novalue,
    COCTL : CALL$ novalue,
    CORBA : CALL$ novalue,
    COTBA : CALL$ novalue,
    REGISTER_NXM : KDP_CSR_NUM;

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

bind
    DB = MCB$GAW_PROCESS_DATA_BASE [1] : ref block field (K_FIELDS),
    DB_BIAS = MCB$GAW_PROCESS_DATA_BASE [0];

macro
    GET_KMC_DATA_BASE (NAME) =
	%if %declared (NAME)
	%then map NAME : ref KMC_DATA_BASE
	%else bind NAME = .MCB$GAW_PROCESS_DATA_BASE [1] : KMC_DATA_BASE
	%fi %;
routine DEVICE_BROKEN (DB) : LINKAGE_DB novalue =

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

    begin
    GET_KMC_DATA_BASE (DB);
    begin

    bind
	CSR = DB [K_REGISTER] : ref block field (KDP_FIELDS);

    DB [K_TIM] = 0;
    CSR [SEL0] = BIT_MASK [MCL];    ! Master Clear the KMC
    end;
    DB [KF_MICROCODE_RUNNING] = FALSE;
    DB [KF_MICROCODE_LOADED] = FALSE;   %(force a reload)%
    begin			    ! Notify all the DUP processes

    local
	CNT,
	PTR;

    PTR = ch$ptr (DB [K_UNITS],, 8);
    CNT = ch$rchar_a (PTR);

    do
	begin

	bind
	    REG = DB [K_OUTPUT_DATA] : block field (KDP_FIELDS);

	local
	    PIX;

	PIX = ch$rchar_a (PTR);

	if .PIX<0, 8, 0> neq 0
	then
	    CALL$P (COBAD, .PIX, REG [SEL0]);

	end
    while (CNT = .CNT - 1) neq 0;

    end;
    begin

    bind
	BUF = .DB [K_INPUT_DATA] : block field (KDP_FIELDS);

    while TRUE do
	begin

	local
	    CCB : ref block field (C_FIELDS);

	if not $MCB_DEQUEUE_CCB (DB [K_INPUT_QUEUE], CCB) then exitloop;

	begin

	bind routine
	    SERVICE_INPUT = .CCB [C_STS];

	CALL$P (SERVICE_INPUT, .CCB [C_LIX], .CCB, BUF [SEL4]);
	end;
	end;

    end;
    end;			!of routine DEVICE_BROKEN
routine INPUT_TRANSFER (DB) : LINKAGE_DB novalue =

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

    begin
    GET_KMC_DATA_BASE (DB);

    bind
	CSR = DB [K_REGISTER] : ref block field (KDP_FIELDS);

    local
	CCB : ref block field (C_FIELDS);

    DB [K_TIM] = 0;

    if not CMQRM$ (DB [K_INPUT_QUEUE], CCB)
    then
	CSR [$SUB_FIELD (SEL0, RQI)] = 0;

    begin

    bind
	BUF = .DB [K_INPUT_DATA] : block field (KDP_FIELDS);

    CSR [SEL6] = .BUF [SEL6];
    CSR [SEL4] = .BUF [SEL4];
    CSR [SEL2] = .BUF [SEL2];
    end;

    if not .CSR [$SUB_FIELD (SEL0, RQI)] then return;

    begin

    bind
	BUF = .DB [K_INPUT_DATA] : block field (KDP_FIELDS);

    bind routine
	SERVICE_INPUT = .CCB [C_STS];

    DB [K_TIM] = REQUEST_TIMEOUT;
    BUF [BSEL3] = .CCB [C_LIX];
    BUF [BSEL2] = CALL$P (SERVICE_INPUT, .CCB [C_PIX], .CCB, BUF [SEL4]);
    end;
    end;			!of routine INPUT_TRANSFER
routine KMC_INTERRUPT (DB) : MCB_INTERRUPT novalue =

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

    begin
    GET_KMC_DATA_BASE (DB);
    begin

    bind
	CSR = DB [K_REGISTER] : ref block field (KDP_FIELDS);

    CSR [$SUB_FIELD (BSEL0, IEI)] = 0;
    CSR [$SUB_FIELD (BSEL0, IEO)] = 0;
    end;
    SYNCH$ (.DB [K_SYNCH_BLOCK], SERVICE_KMC);
    end;			!of routine KMC_INTERRUPT
global routine KMCDB (BIAS, ADDRESS) : CALL$ novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	BIAS = data base bias.
!	ADDRESS = data base address.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin
    DB_BIAS = .BIAS;
    DB = .ADDRESS;
    MCB$GA_PROCESS_DISPATCH = KMC_DISPATCH;
    end;			!of routine KMCDB
global routine KMCPRM (CCB) : CALL$ novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	CCB = CCB to insert parameters into
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin

    map
	CCB : ref block field (C_FIELDS);

    stacklocal
	SAVE_MAP;

    SMAP$ (SAVE_MAP);
    MAP$ (.DB_BIAS);
    begin
    GET_KMC_DATA_BASE (DB);
    CCB [C_PRM1] = .DB [K_REGISTER];
    CCB [C_PRM3] = .DB [K_VECTOR];
    CCB [C_PRM4] = .DB [K_PRIORITY];
    end;
    MAP$ (.SAVE_MAP);
    end;			!of routine KMCPRM
global routine KMCQUE (CCB) : CALL$ novalue =

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

    begin

    map
	CCB : ref block field (C_FIELDS);

    stacklocal
	SAVE_MAP;

    SMAP$ (SAVE_MAP);
    MAP$ (.DB_BIAS);
    begin

    bind
	BUF = .DB [K_INPUT_DATA] : block field (KDP_FIELDS),
	CSR = DB [K_REGISTER] : ref block field (KDP_FIELDS);

    GET_KMC_DATA_BASE (DB);

    if not .DB [KF_MICROCODE_RUNNING]
    then
	begin

	bind routine
	    SERVICE_INPUT = .CCB [C_STS];

	BUF [BSEL2] = CALL$P (SERVICE_INPUT, .CCB [C_PIX], .CCB, BUF [SEL4]);
	end
    else

	if .CSR [$SUB_FIELD (SEL0, RQI)]
	then
	    CMQIN$ (DB [K_INPUT_QUEUE], .CCB)
	else
	    begin

	    bind routine
		SERVICE_INPUT = .CCB [C_STS];

	    CSR [$SUB_FIELD (SEL0, RQI)] = 1;
	    DB [K_TIM] = REQUEST_TIMEOUT;
	    BUF [BSEL3] = .CCB [C_LIX];
	    BUF [BSEL2] = CALL$P (SERVICE_INPUT, .CCB [C_PIX], .CCB, BUF [SEL4]);
	    end;

    end;
    MAP$ (.SAVE_MAP);
    end;			!of routine KMCQUE
global routine KMCSTP (UNIT) : CALL$ novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	UNIT = DUP unit number on KMC
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin

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

    stacklocal
	SAVE_MAP;

    SMAP$ (SAVE_MAP);
    MAP$ (.DB_BIAS);
    begin
    GET_KMC_DATA_BASE (DB);

    local
	PTR;

    PTR = ch$ptr (DB [K_UNITS],, 8);

    if ch$rchar_a (PTR) lequ .UNIT<0, 8, 0> then $return;

    PTR = ch$plus (.PTR, .UNIT);

    if ch$rchar (.PTR) eql 0 then $return;

    DB [K_ACTIVE] = .DB [K_ACTIVE] - 1;

    if .DB [K_ACTIVE] eql 0
    then
	if .DB [KF_MICROCODE_RUNNING]
	then
	    begin

	    bind
		REG = DB [K_REGISTER] : ref block field (KDP_FIELDS);

	    DB [K_TIM] = 0;
	    REG [SEL0] = BIT_MASK [MCL];
	    DB [KF_MICROCODE_RUNNING] = FALSE;
	    end;

    ch$wchar (0, .PTR);
    end;
    MAP$ (.SAVE_MAP);
    end;			!of routine KMCSTP
global routine KMCSTR (UNIT, PIX) : CALL$ =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	UNIT = DUP unit number on KMC
!	PIX = PIX if DUP process.
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin

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

    stacklocal
	SAVE_MAP;

    SMAP$ (SAVE_MAP);
    MAP$ (.DB_BIAS);
    begin

    local
	PTR;

    GET_KMC_DATA_BASE (DB);
    PTR = ch$ptr (DB [K_UNITS],, 8);

    if ch$rchar_a (PTR) lequ .UNIT<0, 8, 0> then $return (FALSE);

    PTR = ch$plus (.PTR, .UNIT);

    if ch$rchar (.PTR) neq 0 then $return (FALSE);

    if .DB [K_ACTIVE] eql 0
    then
	begin

	if not .DB [KF_MICROCODE_LOADED]
	then
	    begin

	    external
		$KDPMC : ref vector;

	    external literal
		$KDPML;

	    if .DB [K_REGISTER] lssu %o'160000' then $return (FALSE);

	    if REGISTER_NXM (.DB [K_REGISTER], 4) then $return (FALSE);

	    if not $MCB_SET_VECTOR (.DB [K_VECTOR], KMC_INTERRUPT, .DB [K_PRIORITY])
	    then
		$return (FALSE);

	    if not $MCB_SET_VECTOR (.DB [K_VECTOR] + 4, KMC_INTERRUPT, .DB [K_PRIORITY])
	    then
		begin
		$MCB_CLEAR_VECTOR (.DB [K_VECTOR]);
		$return (FALSE);
		end;

	    if not LOAD_MICROCODE (.DB [K_REGISTER], $KDPMC, $KDPML^5)
	    then
		$return (FALSE);

	    DB [KF_MICROCODE_LOADED] = TRUE;
	    end;

	if not .DB [KF_MICROCODE_RUNNING]
	then
	    begin

	    if not START_MICROCODE (.DB [K_REGISTER]) then $return (FALSE);

	    DB [KF_MICROCODE_RUNNING] = TRUE;
	    end;

	end;

    DB [K_ACTIVE] = .DB [K_ACTIVE] + 1;
    ch$wchar (.PIX, .PTR);
    end;
    MAP$ (.SAVE_MAP);
    TRUE
    end;			!of routine KMCSTR
routine KMCTIM (DB, MODIFIER) : MCB_DB_MOD novalue =

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

    begin
    DISPATCH$ (
	.MODIFIER,
	TABLE$ ($DSPCR, FD_TIM,		! Timer dispatch table:
	    (FM_LTM, TIMLTM),		!  Long timer
	    (FM_PWF, TIMPWF),		!  Power failure
	    (FM_PIN, TIMPIN)),		!  Process initialization
	(.DB),
	MCB_DB);
    end;			!of routine KMCTIM
routine LOAD_MICROCODE (CSR, MC, LNG) : KDP_CSR_MC_LNG =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	CSR = address of KMC SEL0 register
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin

    map
	CSR : ref block field (KDP_FIELDS),
	MC : ref vector;

    local
	ADR;

    incra ADDR from CSR [SEL0] to CSR [SEL6] by %upval do .ADDR = 0;

    ADR = 0;

    do
	begin

	map
	    CSR : ref block field (KDP_FIELDS) volatile;

	CSR [SEL0] = 4^8;
	CSR [SEL4] = .ADR;
	CSR [SEL6] = .MC [0];
	CSR [$SUB_FIELD (BSEL1, 0, 5, 1, 0)] = 1;
	CSR [SEL0] = 0;
	CSR [SEL4] = 0;
	CSR [SEL6] = 0;
	CSR [SEL0] = 4^8;
	CSR [SEL4] = .ADR;

	if .MC [0] neq .CSR [SEL6]
	then
	    begin
	    COUNTER_INCREMENT (DB, K_MICROCODE_WONT_LOAD);
	    COUNTER_INCREMENT (DB, K_DEVICE_ERRORS);
	    return FALSE;
	    end;

	MC = MC [1];
	ADR = .ADR + 1;
	end
    until (LNG = .LNG - 1) eql 0;

    incra ADDR from CSR [SEL0] to CSR [SEL6] by %upval do .ADDR = 0;

    TRUE
    end;			!of routine LOAD_MICROCODE
routine OUTPUT_TRANSFER (DB) : LINKAGE_DB novalue =

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

    begin
    GET_KMC_DATA_BASE (DB);

    bind
	REG = .DB [K_OUTPUT_DATA] : block field (KDP_FIELDS);

    begin

    map
	REG : vector [4];

    bind
	CSR = .DB [K_REGISTER] : vector [4];

    REG [0] = .CSR [0];
    REG [1] = .CSR [1];
    REG [2] = .CSR [2];
    REG [3] = .CSR [3];
    block [CSR, BSEL2] = 0;
    end;
    begin

    local
	DUP_NUM;

    if (DUP_NUM = .REG [BSEL3]) lss 0
    then
	begin
	COUNTER_INCREMENT (DB, K_COMPLETION_QUEUE_OVERRUN);
	COUNTER_INCREMENT (DB, K_PERFORMANCE_ERRORS);
	DEVICE_BROKEN (DB [K_TIM]);
	return;
	end;

    if .DUP_NUM <0, 8, 0> gtru .DB [K_UNITS]
    then
	begin
	COUNTER_INCREMENT (DB, K_INVALID_UNIT);
	COUNTER_INCREMENT (DB, K_DEVICE_ERRORS);
	DEVICE_BROKEN (DB [K_TIM]);
	return;
	end;

    DUP_NUM = ch$rchar (ch$ptr (DB [K_DUP_PIX], .DUP_NUM, 8));

    if .DUP_NUM<0, 8, 0> eqlu 0
    then
	begin
	COUNTER_INCREMENT (DB, K_INVALID_UNIT);
	COUNTER_INCREMENT (DB, K_DEVICE_ERRORS);
	DEVICE_BROKEN (DB [K_TIM]);
	return;
	end;

    begin

    bind routine
	SERVICE_OUTPUT =
	    (case .REG [$SUB_FIELD (SEL2, COM)] from 0 to 7 of
		set
		[TBA] : COTBA;
		[RBA] : CORBA;
		[CTL, CTL + 4] : COCTL;
		[inrange] :
		    begin
		    COUNTER_INCREMENT (DB, K_INVALID_OUTPUT_CODE);
		    COUNTER_INCREMENT (DB, K_DEVICE_ERRORS);
		    DEVICE_BROKEN (DB [K_TIM]);
		    return;
		    end;
		tes) : CALL$ novalue;

    CALL$P (SERVICE_OUTPUT, .DUP_NUM, REG [SEL0]);
    end;
    end;
    end;			!of routine OUTPUT_TRANSFER
routine SERVICE_KMC (DB) : MCB_DB novalue =

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

    begin

    label
	TEST_BLOCK;

    GET_KMC_DATA_BASE (DB);

    do TEST_BLOCK:
	begin

	bind
	    CSR = .DB [K_REGISTER] : block field (KDP_FIELDS);

	begin

	map
	    CSR : block field (KDP_FIELDS) volatile;

	if .CSR [$SUB_FIELD (SEL2, RDYI)]
	then
	    leave TEST_BLOCK with INPUT_TRANSFER (DB [K_TIM]);

	if .CSR [$SUB_FIELD (SEL2, RDYO)]
	then
	    leave TEST_BLOCK with OUTPUT_TRANSFER (DB [K_TIM]);

	end;
	CSR [$SUB_FIELD (BSEL0, IEI)] = 1;
	CSR [$SUB_FIELD (BSEL0, IEO)] = 1;
	return;
	end
    while TRUE;

    end;			!of routine SERVICE_KMC
routine START_MICROCODE (CSR) : KDP_CSR =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!	CSR = address of KMC SEL0 register
!
! IMPLICIT INPUTS:
!	None
!
! IMPLICIT OUTPUTS:
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!	None
!
! SIDE EFFECTS:
!	None
!--

    begin

    map
	CSR : ref block field (KDP_FIELDS);

    CSR [$SUB_FIELD (SEL0, MCL)] = 1;
    CSR [BSEL2] = -1;
    CSR [SEL0] = BIT_MASK [RUN];

    if
	begin

	local
	    COUNT;

	COUNT = 0;

	do
	    begin

	    map
		CSR : ref block field (KDP_FIELDS) volatile;

	    if .CSR [BSEL2] eql 0 then exitloop 0;

	    end
	until (COUNT = .COUNT - 1) eql 0

	end
    then
	begin
	COUNTER_INCREMENT (DB, K_MICROCODE_WONT_START);
	COUNTER_INCREMENT (DB, K_DEVICE_ERRORS);
	return FALSE;
	end;

    CSR [$SUB_FIELD (BSEL0, IEI)] = 1;
    CSR [$SUB_FIELD (BSEL0, IEO)] = 1;
    TRUE
    end;			!of routine START_MICROCODE
routine TIMLTM (DB) : MCB_DB novalue =

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

    begin
    GET_KMC_DATA_BASE (DB);

    local
	REG0 : block [1] field (KDP_FIELDS);

    REG0 = .block [.DB [K_REGISTER], SEL0];

    if .REG0 [IEO] eql 0 then return;

    if (.REG0 [RDYI] neq 0) or (.REG0 [RDYO] neq 0)
    then
	COUNTER_INCREMENT (DB, K_LOST_INTERRUPT)
    else
	COUNTER_INCREMENT (DB, K_LATE_RDYI);

    COUNTER_INCREMENT (DB, K_PERFORMANCE_ERRORS);
    DEVICE_BROKEN (DB [K_TIM]);
    end;			!of routine TIMLTM
routine TIMPIN (DB) : MCB_DB novalue =

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

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

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

    begin
    GET_KMC_DATA_BASE (DB);
    DEVICE_BROKEN (DB [K_TIM]);
    DB [KF_MICROCODE_LOADED] = FALSE;
    end;			!of routine TIMPWF
end
eludom