Trailing-Edge
-
PDP-10 Archives
-
BB-P363B-SM_1985
-
mcb/drivers/dmc.b16
There are no other files named dmc.b16 in the archive.
module DMC ( ! Driver for DMC11
ident = 'X04690',
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 is the DLC process which services the DMC11 synchronous
! line interface.
!
! ENVIRONMENT: MCB V3.0
!
! AUTHOR: Alan D. Peckham CREATION DATE: 7-Apr-80
!
! MODIFIED BY:
!
! Maynard, 10-Feb-78: Version 1
! Maynard, 29-Feb-79: Version 3
! Alan D. Peckham, 7-Apr-80: Version 4
! 01 - Update to operate under MCB V3.0
! 02 - Check DS.MC properly in GET_PORT.
! Clear DS.MC after DMC is set up in CTLSTR.
! Make initialization handle D.XBFC properly.
! Correct queue address calculation in CTLSTP.
! Receive buffer lengths come from .RDBSZ, not C.CNT!
! Save the CTL/STP CCB while flushing the queues.
! 03 - Do not copy transmit buffer if single segment message.
! 04 - Change call JMPs to CALLRs and add macro for debugging.
! 05 - Seperate DLC and DDM dispatch tables to avoid C.MOD bug.
! 06 - Put routines in alphabetical order.
! Eliminate CALLRs.
! Fix bit test in CTLSTP.
! Master clear DMC on fatal errors in CONTROL_OUT.
! Turn off output interrupts during interrupt service.
! Ignore output interrupt while DMC inactive.
! 07 - Insert SIGNALs for empty queues.
! 08 - Rewrite in BLISS and update for MCB V3.1.
! 09 - Add internal event logging.
! 10 - Map the data base and add Network Management code.
! 11 - Add Network Management event logging.
! 12 - Clean up current Network Management code.
! 13 - Signal on event logging buffer too small.
! 14 - Add long timer control.
! 15 - Compensate for UNWIND bug in condition handling.
! 16 - Process multiple output transfers during output interrupt.
! Allow master clear to fail.
! 17 - Fix interrupt vector assignment bug in DMCNMX.
! Allow number of receive buffers to be specified in CETAB.
! 18 - Temporarily remove RQI test in GET_PORT to allow lost
! RDYI recovery.
! 19 - Identify line and circuit to NMX in DMCNMX.
! 20 - Move BASE-IN and CONTROL-IN in test loop in SET_PORT.
! 21 - Argh! Create common interrupt service routine which
! processes both input and output requests.
! 22 - Streamline linkages.
! Do not SYNCH unless interrupt enable is on.
! 23 - Do not reset IEO during interrupt handling (no-no on DMR).
! Rewrite port handling code.
! 24 - Rework HALT command handling.
! Reset certain variables on CTL/STR.
! 25 - Flush transmits before waiting for the cows to come home in CTLSTP.
! 26 - Hunting for bugs. Rework timer code.
! Rework CCB control function handling.
! 27 - Experimental bug fixes to look for shutdown bug.
! 29 - Correct event logging bugs.
! 30 - Add code to record program flow of shutdown.
! Verify message lengths by examination in RECEIVE_OUT.
! Verify receive buffer addresses on RECEIVE_OUT.
! 31 - Remove message length verification.
! Add transmit buffer address verification in TRANSMIT_OUT.
! 32 - Fix transmit buffer address verification in TRANSMIT_OUT.
! Optimize some generated code.
! 33 - Close window in CTL/STP/STR which allowed CTL deadlock.
! 34 - Do not set function code during port load in SERVICE_DMC
! in order to avoid clearing RDI.
! 35 - Remove DLC interface.
! 36 - Add controller loopback support.
! 37 - Add 96+5/13 event for NM line attention.
! 38 - Distinguish between overrun due to no buffer available
! and due to transmission threshold.
! 39 - Finish DLC interface removal.
! Add parameter to SHOW LINE CHARACTERISTICS.
! 40 - Do NOT send state when there is no circuit owner.
! 41 - Do not set half duplex when in maintenance mode.
! 42 - Add DMR line/device name display and support for DMR process.
! 43 - Adapt to using new UNIBUS address conversion routines.
! Adjust buffer address checking for DMC bug.
! 44 - Eliminate extra OFF notification in CURRENT_STATUS.
! Optimize CHECK_BA.
! 45 - Add device and performance error counter support.
! Fix control CCB handling - CTLNXT had not been updated.
! 46 - Do not declare interrupt lost in TIMLTM if synchronization
! in progress.
! 47 - Turn off FLUSHING_DMC when DMC shuts down.
! 48 - More work on non-existent device notification.
! 49 - Cut down on extraneous functionality to save space.
! 50 - Set threshold errors to display circuit counters.
! 51 - Handle counters by copying when zeroed and using differences
! for reporting.
! 52 - Add "counters zeroed" event.
! 53 - Remove "counters zeroed" event.
! 54 - Update to NM V3.0.0 .
! 55 - Set default DMC receive buffers to 7 in DMCINI.
! Add MAXIMUM RECEIVE BUFFERS parameter support in DMCNMX.
! 56 - Schedule DC_CONTROL_IN after ZERO_x_COUNTERS in SET_INPUT_REQUEST
! if DMC is only DD_HALTED.
! 57 - Disable TRANSMIT_THRESHOLD_ERROR notification on O_RUN.
! Do not force HALT state for ZERO_COUNTERS.
! 58 - Support new system specific line counters.
! 59 - De-commit half-duplex.
! 60 - Poke our DEVTYP into any MOP message requiring it.
! 61 - Handle change in NMX interface in DMCINI.
! 62 - Re-enable half-duplex code.
! 63 - Disable time out for first transmit. This is because protocol
! may not have been established yet.
! 64 - Make sure flag is cleared at appropriate places.
! 65 - Fix display of DMC counter #1021 in DMCNMX.
! 66 - Modify CTLSTR to return the CIRCUIT COST to XPT in C_PRM1.
! 67 - We got the meaning of the timer bit in a control-in wrong -
! the 1 and 3 second timers were reversed.
! 68 - Fix TIMLTM to do a transmit timeout on maintenance messages.
!
! Dennis Brannon, 23-Sep-83: Version 4 autopatch tape 7
! 69 - Fix CONTROL_OUT to reinitialize DMR/DMC after it turns the
! circuit off when a DDCMP START is received.
!--
!
! INCLUDE FILES:
!
library 'MCBLIB';
library 'XPORTX';
$SHOW (NONE)
require 'DLLLIB';
library 'NMXLIB';
library 'DMCDAT';
!
! TABLE OF CONTENTS:
!
linkage
CBIT_LINKAGE = jsr (register = 4) : clearstack valuecbit,
DMC_CCB_DB = jsr (register = 4, register = 5) : nopreserve (4),
DMC_CCB_DB_STS = jsr (register = 4, register = 5, register = 0) :
nopreserve (4),
DMC_DB = jsr (register = 5) : nopreserve (0, 1, 2, 3, 4),
DMC_DB_BIAS_ADDR = jsr (register = 5, register = 2, register = 3) :
nopreserve (0, 2, 3),
DMC_DB_CCB = jsr (register = 5, register = 4) : nopreserve (4),
DMC_DB_ERR = jsr (register = 5, register = 3) : nopreserve (3, 4),
DMC_DB_LOW_HIGH = jsr (register = 5) : nopreserve (2, 3, 4),
DMC_REG = jsr (register = 1) : nopreserve (1),
DMC_DB_STS = jsr (register = 5, register = 3) : nopreserve (3, 4);
forward routine
BASE_IN : DMC_DB_LOW_HIGH novalue,
CHECK_BA : DMC_DB_BIAS_ADDR,
CONTROL_OUT : DMC_DB_ERR novalue,
CTLNXT : LINKAGE_DB novalue,
CTLSTP : MCB_DB_CCB novalue,
CTLSTR : MCB_DB_CCB novalue,
CURRENT_STATUS : LINKAGE_DB,
DEVICE_SHUT_DOWN : LINKAGE_DB novalue,
DLLINI : DMC_DB_CCB novalue,
DLLMOP : DMC_DB_CCB novalue,
DLLSTP : DMC_DB_CCB novalue,
DMC_INTERRUPT : MCB_INTERRUPT novalue,
DMC_SYNCHRONIZE : MCB_DB novalue,
DMCCTL : MCB_DB_CCB_MOD novalue,
DMCDB : CALL$ novalue,
DMCRCE : MCB_DB_CCB novalue,
DMCTIM : MCB_DB_MOD novalue,
DMCXME : MCB_DB_CCB_MOD novalue,
FLUSH_QUEUES : DMC_DB novalue,
MASTER_CLEAR : LINKAGE_DB,
OUTPUT_TRANSFER : LINKAGE_DB novalue,
PARAMETER_DEVICE_REGISTERS : DMC_REG novalue,
QUEUE_TRANSMIT : DMC_DB_CCB novalue,
RECEIVE_IN : DMC_DB_LOW_HIGH novalue,
RECEIVE_OUT : DMC_DB_LOW_HIGH novalue,
RESET_TIMER : LINKAGE_DB novalue,
SCHEDULE_PERSISTENT_AST : DMC_CCB_DB novalue,
SCHEDULE_RECEIVE : DMC_CCB_DB novalue,
SCHEDULE_STATE_AST : DMC_CCB_DB novalue,
SCHEDULE_TRANSIENT_AST : DMC_CCB_DB novalue,
SCHEDULE_TRANSMIT : DMC_CCB_DB_STS novalue,
SEND_PERSISTENT_ERROR : DMC_DB_STS novalue,
SEND_STATE : DMC_DB novalue,
SEND_TRANSIENT_ERROR : DMC_DB_STS novalue,
SERVICE_DMC : MCB_DB novalue,
SET_INPUT_REQUEST : LINKAGE_DB novalue,
SET_PORT : LINKAGE_DB novalue,
TIMCCB : MCB_DB_CCB novalue,
TIMLTM : MCB_DB novalue,
TIMPIN : MCB_DB novalue,
TIMPWF : MCB_DB novalue,
TIMRDB : MCB_DB_CCB novalue,
TRANSMIT_IN : DMC_DB_LOW_HIGH novalue,
TRANSMIT_OUT : DMC_DB_LOW_HIGH novalue,
ZERO_CIRCUIT_COUNTERS : LINKAGE_DB novalue,
ZERO_LINE_COUNTERS : LINKAGE_DB novalue;
global bind routine
DMCIN = DMC_INTERRUPT : MCB_INTERRUPT novalue,
DMCOUT = DMC_INTERRUPT : MCB_INTERRUPT novalue;
!
! MACROS:
!
macro
CHANGE_PROTOCOL_STATE (DUMMY, STATE, REASON) =
begin
literal LCL = 0, RMT = 1;
$NM_DLL_EVENT (REASON, .DB [D_CIRCUIT_ENTITY],
PARAMETER_C_1 (0, DB [D_PROTOCOL_STATE]),
DB [D_PROTOCOL_STATE] = STATE,
PARAMETER_C_1 (1, DB [D_PROTOCOL_STATE]));
SEND_STATE (DB [D_TIM]);
end %;
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 %;
!
! EQUATED SYMBOLS:
!
literal
TRUE = 1 EQL 1,
FALSE = 1 EQL 0,
NO_OPERATION = 0;
macro
C_HANDLE = %fieldexpand (C_LIX, 0), 0, 16, 0 %;
global literal
%name ('DD.INI') = DD_CLEARED,
%name ('D.LEN') = %fieldexpand (D_BUF, 0)^1;
!
! OWN STORAGE:
!
external routine
$DSPCR : novalue;
bind
DMC_TABLE = TABLE$ ($DSPCR, FC_CCP,
(FC_XME, DMCXME), ! Transmit enable
(FC_RCE, DMCRCE), ! Receive enable
(FC_CTL, DMCCTL), ! Control enable
(FC_TIM, DMCTIM)); ! Timeout
$MCB_PROCESS (
NAME = DMC, ! Process name
DLC_DISPATCH = DMC_TABLE) ! DLC dispatch vector
!
! EXTERNAL REFERENCES:
!
external routine
DMCDBI : novalue,
DMCDVI,
DMCNM : MCB_DB_CCB novalue,
DMCNMI;
external
MCB$GA_PROCESS_DISPATCH,
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];
routine BASE_IN (DB, LOW, HIGH) : DMC_DB_LOW_HIGH novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
local
TEMP;
$MCB_CONVERT_TO_UBA_ADDRESS ((.DB_BIAS, DB [D_LNTB]), .LOW, TEMP);
.HIGH = (TEMP = .TEMP^%fieldexpand (BA_HIGH, 1));
end; !of routine BASE_IN
routine CHECK_BA (DB, BIAS, ADDR) : DMC_DB_BIAS_ADDR =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! ?
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
bind
BUF = DB [D_OUTPUT_DATA] : block field (DMC_FIELDS);
local
HIGH,
LOW;
if .ADDR eqla 0 then return TRUE;
$MCB_CONVERT_TO_UBA_ADDRESS ((.BIAS, .ADDR), LOW, HIGH);
if .LOW nequ .BUF [$SUB_FIELD (SEL4, BA_LOW)] then return FALSE;
if not .DB [DF_DMR] then return TRUE;
if .HIGH eqlu .BUF [$SUB_FIELD (SEL6, BA_HIGH)] then return TRUE;
FALSE
end; ! of routine CHECK_BA
routine CONTROL_OUT (DB, ERROR) : DMC_DB_ERR novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
map
ERROR : block [1] field (DMC_FIELDS);
if .ERROR [O_RUN] ! Buffer not available
then
begin
if FALSE %(.DB [D_ASSIGNED_RECEIVE_COUNT] neq 0)%
then
SEND_TRANSIENT_ERROR (DB [D_TIM], DLL$_TRANSMIT_THRESHOLD);
return;
end;
if .ERROR [DATA_CK] ! Non-fatal error
then
begin
external routine
PARAMETER_CIRCUIT_COUNTERS : LINKAGE_DB novalue;
$NM_DLL_EVENT (4, .DB [D_CIRCUIT_ENTITY], ! Transmit Threshold Error
PARAMETER_CIRCUIT_COUNTERS (DB [D_TIM]));
SEND_TRANSIENT_ERROR (DB [D_TIM], DLL$_RECEIVE_THRESHOLD);
return;
end;
if .ERROR [DISC] ! Non-fatal error
then
begin
local
STATE;
STATE = 0;
$NM_PLL_EVENT (0, .DB [D_LINE_ENTITY], ! Data Set Ready Transition
PARAMETER_C_1 (1, STATE));
return;
end;
if .ERROR [TIME_OUT] ! Non-fatal error
then
begin
external routine
PARAMETER_CIRCUIT_COUNTERS : LINKAGE_DB novalue;
$NM_DLL_EVENT (3, .DB [D_CIRCUIT_ENTITY], ! Transmit Threshold Error
PARAMETER_CIRCUIT_COUNTERS (DB [D_TIM]));
SEND_TRANSIENT_ERROR (DB [D_TIM], DLL$_TRANSMIT_THRESHOLD);
return;
end;
if .ERROR [PROC_ERR] and .DB [DF_FLUSHING_DMC] ! Procedure error
then
begin
DB [DF_FLUSHING_DMC] = FALSE;
DB [D_DEVICE_STATE] = DD_HALTED;
return;
end;
if .ERROR [STR_RCVD]
then
begin
if .DB [D_PROTOCOL_STATE] eqlu DS_MAINTENANCE
then
$NM_DLL_EVENT (2, .DB [D_CIRCUIT_ENTITY]);
SEND_PERSISTENT_ERROR (DB [D_TIM], DLL$_START_RECEIVED);
DEVICE_SHUT_DOWN (DB [D_TIM]);
SET_PORT (DB [D_TIM]);
return;
end;
if .ERROR [DATA_LOST]
then
begin
$NM_DLL_EVENT (9, .DB [D_CIRCUIT_ENTITY],
PARAMETER_DU_2 (8, MCB$GW_RDB_SIZE));
DEVICE_SHUT_DOWN (DB [D_TIM]);
return;
end;
if .ERROR [MNT_RCVD] ! Fatal error
then
begin
$NM_DLL_EVENT (96^6 + 13, .DB [D_CIRCUIT_ENTITY]);
SEND_PERSISTENT_ERROR (DB [D_TIM], DLL$_MAINTENANCE_RECEIVED);
DEVICE_SHUT_DOWN (DB [D_TIM]);
return;
end;
if .ERROR [NXM] ! Fatal error
then
begin
$NM_PLL_EVENT (3, .DB [D_LINE_ENTITY], ! Memory Access Error
PARAMETER_DEVICE_REGISTERS (DB [D_OUTPUT_DATA]));
COUNTER_INCREMENT (DB, D_NXM_TO_DEVICE);
COUNTER_INCREMENT (DB, D_FATAL_DEVICE_ERRORS);
SEND_PERSISTENT_ERROR (DB [D_TIM], DLL$_DEVICE_OPERATION_ERROR);
DEVICE_SHUT_DOWN (DB [D_TIM]);
return;
end;
$NM_PLL_EVENT (4, .DB [D_LINE_ENTITY],
PARAMETER_DEVICE_REGISTERS (DB [D_OUTPUT_DATA]));
SEND_PERSISTENT_ERROR (DB [D_TIM], DLL$_DEVICE_OPERATION_ERROR);
if .ERROR [PROC_ERR]
then
begin
COUNTER_INCREMENT (DB, D_PROCEDURE_ERROR);
COUNTER_INCREMENT (DB, D_FATAL_DEVICE_ERRORS);
DEVICE_SHUT_DOWN (DB [D_TIM]);
return;
end;
COUNTER_INCREMENT (DB, D_INVALID_REGISTER_CONTENTS);
COUNTER_INCREMENT (DB, D_FATAL_DEVICE_ERRORS);
MASTER_CLEAR (DB [D_TIM]);
end; !of routine CONTROL_OUT
routine CTLNXT (DB) : LINKAGE_DB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
local
CCB : ref block field (C_FIELDS);
DB [DF_CTL] = FALSE;
if not $MCB_DEQUEUE_CCB (DB [D_PENDING_CONTROLS], CCB) then return;
CCB [C_FNC] = FC_CCP;
CCB [C_STS] = CURRENT_STATUS (DB [D_TIM]);
$MCB_SCHEDULE_CCB (.CCB);
end; !of routine CTLNXT
routine CTLSTP
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!
(DB : ref block field (D_FIELDS),
CCB : ref block field (C_FIELDS))
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
!
: MCB_DB_CCB novalue =
!
! SIDE EFFECTS:
! None
!--
begin
DB [DF_NOTIFY_OFF] = FALSE;
DB [DF_NOTIFY_STATE] = FALSE;
DB [D_TRANSIENT_ERROR] = 0;
DB [D_PERSISTENT_ERROR] = 0;
DB [D_OWNER_HANDLE] = 0;
if .DB [D_ACTIVE_BUFFERS] neq 0
then
begin
! Wait for transmits and receives to complete
CMQIF$ (DB [D_PENDING_CONTROLS], .CCB);
DB [DF_CTL] = TRUE;
return;
end;
CCB [C_FNC] = FC_CCP;
CCB [C_STS] = CURRENT_STATUS (DB [D_TIM]);
$MCB_SCHEDULE_CCB (.CCB);
end; !of routine CTLSTP
routine CTLSTR
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!
(DB : ref block field (D_FIELDS),
CCB : ref block field (C_FIELDS))
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
!
: MCB_DB_CCB novalue =
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
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 DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_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_ISTRT^1, DLL_SYNCHRONIZING),
(DS_ASTRT^1, DLL_SYNCHRONIZING),
(DS_RUNNING^1, DLL_RUNNING),
(DS_MAINTENANCE^1, DLL_MAINTENANCE)) : 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 DEVICE_SHUT_DOWN
!++
! 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
CHANGE_PROTOCOL_STATE (DB [D_TIM], DS_HALTED, RMT);
DB [D_DEVICE_STATE] = DD_SHUT_DOWN;
DB [DF_FLUSHING_DMC] = FALSE;
DB [D_INPUT_COMMAND] = 0;
DB [DF_PROTOCOL_UP] = FALSE;
DB [DC_MASTER_CLEAR] = FALSE;
DB [DC_BASE_IN] = FALSE;
DB [DC_CONTROL_IN] = FALSE;
DB [DC_SET_REQUESTED_STATE] = FALSE;
end; !of routine DEVICE_SHUT_DOWN
routine DLLINI (DB, CCB) : DMC_DB_CCB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
! CCB = address of CCB.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
map
CCB : ref block field (C_FIELDS);
DB [DC_HALT] = TRUE;
DB [DC_MASTER_CLEAR] = TRUE;
DB [D_REQUESTED_STATE] = DS_RUNNING;
DB [DC_SET_REQUESTED_STATE] = TRUE;
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) : DMC_DB_CCB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
! CCB = address of CCB.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
map
CCB : ref block field (C_FIELDS);
DB [DC_HALT] = TRUE;
DB [DC_MASTER_CLEAR] = TRUE;
DB [D_REQUESTED_STATE] = DS_MAINTENANCE;
DB [DC_SET_REQUESTED_STATE] = TRUE;
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 DLLMOP
routine DLLSTP (DB, CCB) : DMC_DB_CCB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
! CCB = address of CCB.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
map
CCB : ref block field (C_FIELDS);
DB [DC_HALT] = TRUE;
DB [DC_MASTER_CLEAR] = TRUE;
DB [D_REQUESTED_STATE] = DS_HALTED;
DB [DC_SET_REQUESTED_STATE] = TRUE;
CCB [C_FNC] = FC_XCP;
CCB [C_STS] = DLL$_SUCCESS;
$MCB_SCHEDULE_CCB (.CCB);
end; !of routine DLLSTP
routine DMC_INTERRUPT (DB) : MCB_INTERRUPT novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
if .DB [DF_SYNCHRONIZING]
then
return
else
DB [DF_SYNCHRONIZING] = TRUE;
SYNCH$ (.DB [D_SYNCH_BLOCK], DMC_SYNCHRONIZE);
end; !of routine DMC_INTERRUPT
routine DMC_SYNCHRONIZE (DB) : MCB_DB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
$DMC_CLEAR_BITS (.DB [D_REGISTER], SEL0, IEI);
DB [DF_SYNCHRONIZING] = FALSE;
SERVICE_DMC (DB [D_TIM]);
end; !of routine DMC_SYNCHRONIZE
routine DMCCTL
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!
(DB : ref block field (D_FIELDS),
CCB : ref block field (C_FIELDS),
MODIFIER)
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
!
: MCB_DB_CCB_MOD novalue =
!
! SIDE EFFECTS:
! None
!--
begin
DISPATCH$ (.MODIFIER,
TABLE$ ($DSPCR, FD_CTL, ! Control dispatch table:
(FM_NM, DMCNM), ! Network Management
(FM_STR, CTLSTR), ! Start line
(FM_STP, CTLSTP)), ! Stop line
(DB [D_TIM], .CCB),
MCB_DB_CCB);
SET_PORT (DB [D_TIM]);
end; !of routine DMCCTL
global routine DMCDB
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!
(BIAS,
DB : ref block field (D_FIELDS))
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
!
: CALL$ novalue =
!
! SIDE EFFECTS:
! None
!--
begin
MCB$GAW_PROCESS_DATA_BASE [0] = .BIAS;
MCB$GAW_PROCESS_DATA_BASE [1] = DB [D_TIM];
MCB$GA_PROCESS_DISPATCH = DMC_TABLE;
DMCDBI ();
DMCNMI ();
DMCDVI ();
if .DB [D_LINE_STATE] eql DL_ON then $MCB_ENABLE_LONG_TIMER ();
end; !of routine DMCDB
routine DMCRCE (DB, CCB) : MCB_DB_CCB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
! CCB =
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
map
CCB : ref block field (C_FIELDS);
RDBRT$ (.CCB);
DB [D_ACTIVE_BUFFERS] = .DB [D_ACTIVE_BUFFERS] - 1;
if .DB [D_ACTIVE_BUFFERS] neq 0 then return;
if .DB [DF_CTL] then CTLNXT (DB [D_TIM]);
end; !of routine DMCRCE
routine DMCTIM (DB, MODIFIER) : MCB_DB_MOD novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
! MODIFIER = timer function modifier.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
DISPATCH$ (
.MODIFIER,
TABLE$ ($DSPCR, FD_TIM, ! Timer dispatch table:
(FM_PIN, TIMPIN), ! Process initialization
(FM_PWF, TIMPWF), ! Power failure
(FM_LTM, TIMLTM), ! Long timer
(FM_CCB, TIMCCB), ! CCB available
(FM_RDB, TIMRDB)), ! RDB available
(DB [D_TIM]),
MCB_DB);
end; !of routine DMCTIM
routine DMCXME (DB, CCB, MODIFIER) : MCB_DB_CCB_MOD novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC 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_DMC_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, QUEUE_TRANSMIT),
(DLL$K_TRANSMIT_AND_TIME, QUEUE_TRANSMIT)),
(DB [D_TIM], .CCB),
DMC_DB_CCB);
SET_PORT (DB [D_TIM]);
end; !of routine DMCXME
routine FLUSH_QUEUES (DB) : DMC_DB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
local
CCB : ref block field (C_FIELDS);
RDBCN$ ();
FLUSH_QUEUE (DB [D_ASSIGNED_TRANSMIT_CCBS], %quote SCHEDULE_TRANSMIT, DB [D_TIM], DLL$_ABORTED);
FLUSH_QUEUE (DB [D_ASSIGNABLE_TRANSMIT_CCBS], %quote SCHEDULE_TRANSMIT, DB [D_TIM], DLL$_ABORTED);
FLUSH_QUEUE (DB [D_ASSIGNED_RECEIVE_CCBS], %quote RDBRT$);
FLUSH_QUEUE (DB [D_ASSIGNABLE_RECEIVE_CCBS], %quote RDBRT$);
DB [D_ASSIGNABLE_TRANSMIT_COUNT] = 0;
DB [D_ASSIGNABLE_RECEIVE_COUNT] = 0;
end; !of routine FLUSH_QUEUES
global routine MASTER_CLEAR (DB) : LINKAGE_DB =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
local
STATUS;
STATUS = FALSE;
if .DB [D_DEVICE_STATE] eql DD_CLEARED then return .STATUS;
$DMC_WRITE (.DB [D_REGISTER], BSEL2, 0);
$DMC_WRITE (.DB [D_REGISTER], SEL0, 1^%fieldexpand (MC, 1));
do
begin
if not $DMC_BITS_CLEAR (.DB [D_REGISTER], SEL0, RUN) then exitloop STATUS = TRUE;
end
until (STATUS = .STATUS - 1) eql FALSE;
if .DB [D_PROTOCOL_STATE] neq DS_HALTED
then
CHANGE_PROTOCOL_STATE (DB [D_TIM], DS_HALTED, LCL);
if .DB [D_DEVICE_STATE] neq DD_MASTER_CLEARED
then
begin
FLUSH_QUEUES (DB [D_TIM]);
DB [D_ASSIGNED_TRANSMIT_COUNT] = 0;
DB [D_ASSIGNED_RECEIVE_COUNT] = 0;
DB [D_DEVICE_STATE] = DD_MASTER_CLEARED;
DB [D_INPUT_COMMAND] = 0;
DB [DF_PROTOCOL_UP] = FALSE;
end;
.STATUS
end; !of routine MASTER_CLEAR
routine OUTPUT_TRANSFER (DB) : LINKAGE_DB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
macro
REG (FLD) = DB [$SUB_FIELD (D_OUTPUT_DATA, FLD)] %;
field
CMD = [$SUB_FIELD (SEL2, TYPEO)];
case .REG [CMD] from 0 to 7 of
set
[BA_CC_O + XMT] :
begin
TRANSMIT_OUT (DB [D_TIM], .REG [SEL4], .REG [SEL6]);
DB [D_ASSIGNED_TRANSMIT_COUNT] = .DB [D_ASSIGNED_TRANSMIT_COUNT] - 1;
RESET_TIMER (DB [D_TIM]);
end;
[BA_CC_O + RCV] :
begin
RECEIVE_OUT (DB [D_TIM], .REG [SEL4], .REG [SEL6]);
DB [D_ASSIGNED_RECEIVE_COUNT] = .DB [D_ASSIGNED_RECEIVE_COUNT] - 1;
end;
[CNTL_O + XMT, CNTL_O + RCV] :
begin
CONTROL_OUT (DB [D_TIM], .REG [SEL6]);
end;
[inrange] :
begin
$NM_PLL_EVENT (4, .DB [D_LINE_ENTITY],
PARAMETER_DEVICE_REGISTERS (REG [SEL0]));
COUNTER_INCREMENT (DB, D_INVALID_REGISTER_CONTENTS);
COUNTER_INCREMENT (DB, D_FATAL_DEVICE_ERRORS);
SEND_PERSISTENT_ERROR (DB [D_TIM], DLL$_DEVICE_OPERATION_ERROR);
MASTER_CLEAR (DB [D_TIM]);
end;
tes;
SET_PORT (DB [D_TIM]);
end; !of routine OUTPUT_TRANSFER
global routine PARAMETER_DEVICE_REGISTERS
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!
(REG : ref vector)
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
: DMC_REG novalue =
!
! SIDE EFFECTS:
! None
!--
begin
!
! DMC registers
!
PARAMETER_H_2 (0, REG [0]);
REG = REG [1];
PARAMETER_H_2 (0, REG [0]);
REG = REG [1];
PARAMETER_H_2 (0, REG [0]);
REG = REG [1];
PARAMETER_H_2 (0, REG [0]);
end; !of routine PARAMETER_DEVICE_REGISTERS
routine QUEUE_TRANSMIT (DB, CCB) : DMC_DB_CCB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
! CCB = address of CCB.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
map
CCB : ref block field (C_FIELDS);
local
MSG_CNT;
if .DB [D_PROTOCOL_STATE] eql DS_MAINTENANCE
then
begin
local
SAVE_MAP;
SMAP$ (SAVE_MAP);
MAP$ (.CCB [C_BIAS]);
selectone ch$rchar (.CCB [C_ADDR]) of
set
[8, 12]:
ch$wchar (12, ch$plus (.CCB [C_ADDR], 1));
tes;
MAP$ (.SAVE_MAP);
end;
DB [D_ACTIVE_BUFFERS] = .DB [D_ACTIVE_BUFFERS] + 1;
DB [D_ASSIGNABLE_TRANSMIT_COUNT] = .DB [D_ASSIGNABLE_TRANSMIT_COUNT] + 1;
CMQIN$ (DB [D_ASSIGNABLE_TRANSMIT_CCBS], .CCB);
if .CCB [C_CHN] eqla 0 then return;
MSG_CNT = .DB [D_TRANSMIT_BUFFER_SIZE];
do
begin
if (MSG_CNT = .MSG_CNT - .CCB [C_CNT]) lss 0
then
SIGNAL_STOP (DMC$_MTL, .DB [$SUB_FIELD (D_ASSIGNABLE_TRANSMIT_CCBS, LIST_LAST)]);
end
while (CCB = .CCB [C_CHN]) neq 0;
end; !of routine QUEUE_TRANSMIT
routine RECEIVE_IN (DB, LOW, HIGH) : DMC_DB_LOW_HIGH novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
local
CCB : ref block field (C_FIELDS);
if not CMQRM$ (DB [D_ASSIGNABLE_RECEIVE_CCBS], CCB)
then
return SIGNAL_STOP (DMC$_QUE, DB [D_ASSIGNABLE_RECEIVE_CCBS]);
DB [D_ASSIGNABLE_RECEIVE_COUNT] = .DB [D_ASSIGNABLE_RECEIVE_COUNT] - 1;
CMQIN$ (DB [D_ASSIGNED_RECEIVE_CCBS], .CCB);
begin
local
TEMP;
$MCB_CONVERT_TO_UBA_ADDRESS ((.CCB [C_BIAS], .CCB [C_ADDR]), .LOW, TEMP);
TEMP = .TEMP^%fieldexpand (BA_HIGH, 1);
.HIGH = (TEMP = .TEMP + .MCB$GW_RDB_SIZE);
end;
end; !of routine RECEIVE_IN
routine RECEIVE_OUT (DB, LOW, HIGH) : DMC_DB_LOW_HIGH novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
map
HIGH : block [1] field (DMC_FIELDS),
LOW : block [1] field (DMC_FIELDS);
local
CCB : ref block field (C_FIELDS);
if not CMQRM$ (DB [D_ASSIGNED_RECEIVE_CCBS], CCB)
then
SIGNAL_STOP (DMC$_QUE, DB [D_ASSIGNED_RECEIVE_CCBS]);
if not CHECK_BA (DB [D_TIM], .CCB [C_BIAS], .CCB [C_ADDR])
then
begin
RDBRT$ (.CCB);
COUNTER_INCREMENT (DB, D_RECEIVE_BA_MISMATCH);
COUNTER_INCREMENT (DB, D_FATAL_DEVICE_ERRORS);
SEND_PERSISTENT_ERROR (DB [D_TIM], DLL$_DEVICE_OPERATION_ERROR);
MASTER_CLEAR (DB [D_TIM]);
return;
end;
CCB [C_CNT] = .HIGH [CC];
if .DB [D_PROTOCOL_STATE] eql DS_RUNNING
then
begin
COUNTER_ADD (DB, D_BYTES_RECEIVED, .CCB [C_CNT]);
COUNTER_INCREMENT (DB, D_BLOCKS_RECEIVED);
end;
DB [DF_PROTOCOL_UP] = TRUE;
SCHEDULE_RECEIVE (.CCB, DB [D_TIM]);
DB [DF_WAITING_FOR_RECEIVE] = FALSE;
end; !of routine RECEIVE_OUT
routine RESET_TIMER (DB) : LINKAGE_DB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
DB [D_TIM] = 0;
selectone TRUE of
set
[.DB [DF_WAITING_FOR_RDYI]] :
DB [D_TIM] = .DB [D_TIM] + 1;
[.DB [DF_FLUSHING_DMC]] :
DB [D_TIM] = 3;
[.DB [D_TRANSIENT_ERROR] neq 0] :
DB [D_TIM] = 2;
[.DB [D_PERSISTENT_ERROR] neq 0] :
DB [D_TIM] = 2;
[.DB [D_ASSIGNED_TRANSMIT_COUNT] neq 0] :
DB [D_TIM] = .DB [D_TRANSMIT_TIMEOUT];
[.DB [DF_WAITING_FOR_RECEIVE]] :
DB [D_TIM] = .DB [D_SERVICE_TIMER];
tes;
end; !of routine RESET_TIMER
routine SCHEDULE_PERSISTENT_AST (CCB, DB) : DMC_CCB_DB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! CCB = address of CCB to use for status nodification.
! DB = address of DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_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) : DMC_CCB_DB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_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) : DMC_CCB_DB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! CCB = address of CCB to use for status nodification.
! DB = address of DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_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) : DMC_CCB_DB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! CCB = address of CCB to use for status nodification.
! DB = address of DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_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) : DMC_CCB_DB_STS novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_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_CTL] then CTLNXT (DB [D_TIM]);
end; !of routine SCHEDULE_TRANSMIT
routine SEND_PERSISTENT_ERROR (DB, STATUS) : DMC_DB_STS novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_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) : DMC_DB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_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) : DMC_DB_STS novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_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 SERVICE_DMC (DB) : MCB_DB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
label
SERVICE_FOUND;
bind
CSR = .DB [D_REGISTER];
DB [DF_SERVICING_DMC] = TRUE;
do
SERVICE_FOUND : begin
case .DB [D_DEVICE_STATE] from DD_LOW to DD_HIGH of
set
[DD_CLEARED, DD_MASTER_CLEARED, DD_SHUT_DOWN] :
begin
DB [DF_SERVICING_DMC] = FALSE;
return;
end;
[inrange] :
NO_OPERATION;
tes;
decru COUNT from 4 to 1 do
begin
if not $DMC_BITS_CLEAR (CSR, SEL0, RDYI)
then
begin
if not $DMC_BITS_CLEAR (CSR, SEL0, RQI)
then
begin
!
! We have requested the input port and
! the DMC has complied.
!
bind
BUF = DB [D_INPUT_DATA] : block field (DMC_FIELDS);
DB [DF_WAITING_FOR_RDYI] = FALSE;
RESET_TIMER (DB [D_TIM]);
$DMC_WRITE (CSR, SEL6, .BUF [SEL6]);
$DMC_WRITE (CSR, SEL4, .BUF [SEL4]);
$DMC_CLEAR_BITS (CSR, SEL0, RQI);
DB [D_INPUT_COMMAND] = 0;
SET_INPUT_REQUEST (DB [D_TIM]);
leave SERVICE_FOUND;
end
else
begin
!
! We have given the DMC a command
! the DMC is processing it.
!
NO_OPERATION
end;
end
else
begin
if $DMC_BITS_CLEAR (CSR, SEL0, RQI)
then
begin
!
! No input transfer operation in progress.
!
if .DB [D_INPUT_COMMAND] neq 0
then
begin
bind
BUF = DB [D_INPUT_DATA] : block field (DMC_FIELDS);
$DMC_WRITE (CSR, BSEL0, .BUF [BSEL0]);
DB [DF_WAITING_FOR_RDYI] = TRUE;
RESET_TIMER (DB [D_TIM]);
leave SERVICE_FOUND;
end;
end
else
begin
!
! We have requested the input port and
! the DMC hasn't complied yet.
!
NO_OPERATION
end;
end;
if not $DMC_BITS_CLEAR (CSR, SEL2, RDYO)
then
begin
!
! The DMC has data for us.
!
bind
BUF = DB [D_OUTPUT_DATA] : block field (DMC_FIELDS);
BUF [SEL0] = $DMC_READ (CSR, SEL0);
BUF [SEL2] = $DMC_READ (CSR, SEL2);
BUF [SEL4] = $DMC_READ (CSR, SEL4);
BUF [SEL6] = $DMC_READ (CSR, SEL6);
$DMC_CLEAR_BITS (CSR, SEL2, RDYO);
OUTPUT_TRANSFER (DB [D_TIM]);
leave SERVICE_FOUND;
end;
end;
if not $DMC_BITS_CLEAR (CSR, SEL0, RQI)
then
begin
$DMC_SET_BITS (CSR, SEL0, IEI);
$DMC_SET_BITS (CSR, SEL0, IEI);
end;
DB [DF_SERVICING_DMC] = FALSE;
return;
end
while TRUE;
end; !of routine SERVICE_DMC
routine SET_INPUT_REQUEST (DB) : LINKAGE_DB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
bind
BUF = DB [D_INPUT_DATA] : block field (DMC_FIELDS);
while .DB [D_CONTROL_FLAGS] neq 0 do
selectone TRUE of
set
[.DB [DC_HALT]] :
begin
if .DB [DF_FLUSHING_DMC] then return;
case .DB [D_DEVICE_STATE] from DD_LOW to DD_HIGH of
set
[DD_RUNNING] :
begin
DB [DF_FLUSHING_DMC] = TRUE;
RESET_TIMER (DB [D_TIM]);
BUF [SEL6] = 0;
BUF [SEL4] = 0;
BUF [BSEL0] = HALT + 1^%fieldexpand (RQI, 1);
return;
end;
[DD_CLEARED, DD_MASTER_CLEARED, DD_HALTED] :
DB [DC_HALT] = FALSE;
[inrange] :
begin
DB [DC_MASTER_CLEAR] = TRUE;
DB [DC_HALT] = FALSE;
end;
tes;
end;
[.DB [DC_MASTER_CLEAR]] :
case .DB [D_DEVICE_STATE] from DD_LOW to DD_HIGH of
set
[DD_CLEARED, DD_MASTER_CLEARED] :
DB [DC_MASTER_CLEAR] = FALSE;
[inrange] :
begin
MASTER_CLEAR (DB [D_TIM]);
DB [DC_MASTER_CLEAR] = FALSE;
end;
tes;
[.DB [DC_ZERO_CIRCUIT_COUNTERS]] :
begin
ZERO_CIRCUIT_COUNTERS (DB [D_TIM]);
DB [DC_ZERO_CIRCUIT_COUNTERS] = FALSE;
end;
[.DB [DC_ZERO_LINE_COUNTERS]] :
begin
ZERO_LINE_COUNTERS (DB [D_TIM]);
DB [DC_ZERO_LINE_COUNTERS] = FALSE;
end;
[.DB [DC_BASE_IN]] :
case .DB [D_DEVICE_STATE] from DD_LOW to DD_HIGH of
set
[DD_RUNNING] : DB [DC_HALT] = TRUE;
[DD_HALTED, DD_MASTER_CLEARED] :
begin
if .DB [D_DEVICE_STATE] eql DD_MASTER_CLEARED
then
$DMC_SET_BITS (.DB [D_REGISTER], SEL2, IEO);
BASE_IN (DB [D_TIM], BUF [SEL4], BUF [SEL6]);
BUF [$SUB_FIELD (SEL6, RESUME)] = 0;
if .DB [D_DEVICE_STATE] neq DD_MASTER_CLEARED
then
BUF [$SUB_FIELD (SEL6, RESUME)] = 1;
BUF [BSEL0] = BASE_I + 1^%fieldexpand (RQI, 1);
DB [DC_BASE_IN] = FALSE;
DB [D_DEVICE_STATE] = DD_BASE_TABLE_ASSIGNED;
return;
end;
[DD_BASE_TABLE_ASSIGNED, DD_CLEARED] : DB [DC_BASE_IN] = FALSE;
[inrange] : DB [DC_MASTER_CLEAR] = TRUE;
tes;
[.DB [DC_CONTROL_IN]] :
case .DB [D_DEVICE_STATE] from DD_LOW to DD_HIGH of
set
[DD_BASE_TABLE_ASSIGNED] :
begin
DB [DC_CONTROL_IN] = FALSE;
BUF [SEL4] = 0;
BUF [SEL6] = 0;
if .DB [DF_CONTROLLER_LOOPBACK]
then
$DMC_SET_BITS (.DB [D_REGISTER], SEL0, LU_LOOP)
else
$DMC_CLEAR_BITS (.DB [D_REGISTER], SEL0, LU_LOOP);
if .DB [DF_HALF_DUPLEX]
then
BUF [$SUB_FIELD (SEL6, HD)] = 1;
if .DB [D_REQUESTED_STATE] eql DS_MAINTENANCE
then
BUF [$SUB_FIELD (SEL6, MAINT)] = 1;
if not .DB [DF_1_SEC]
then
BUF [$SUB_FIELD (SEL6, SEC)] = 1;
BUF [BSEL0] = CNTL_I + 1^%fieldexpand (RQI, 1);
DB [D_DEVICE_STATE] = DD_RUNNING;
CHANGE_PROTOCOL_STATE (DB [D_TIM], .DB [D_REQUESTED_STATE], LCL);
return;
end;
[DD_CLEARED, DD_RUNNING] : DB [DC_CONTROL_IN] = FALSE;
[inrange] : DB [DC_BASE_IN] = TRUE;
tes;
[.DB [DC_SET_REQUESTED_STATE]] :
selectone TRUE of
set
[.DB [D_LINE_STATE] neq DL_ON] :
DB [DC_SET_REQUESTED_STATE] = FALSE;
[.DB [D_DEVICE_STATE] eql DD_CLEARED] :
DB [DC_SET_REQUESTED_STATE] = FALSE;
[.DB [D_PROTOCOL_STATE] eql .DB [D_REQUESTED_STATE]] :
DB [DC_SET_REQUESTED_STATE] = FALSE;
[.DB [D_REQUESTED_STATE] eql DS_HALTED] :
DB [DC_MASTER_CLEAR] = TRUE;
[otherwise] :
DB [DC_CONTROL_IN] = TRUE;
tes;
[.DB [DC_CONTINUE_CONTROL]] :
begin
DB [DC_CONTINUE_CONTROL] = FALSE;
if .DB [DF_CTL] then CTLNXT (DB [D_TIM]);
end;
tes;
if .DB [D_DEVICE_STATE] neq DD_RUNNING then return;
if .DB [D_ASSIGNED_RECEIVE_COUNT] lssu .DB [D_MAXIMUM_RECEIVE_COUNT]
then
if .DB [D_ASSIGNABLE_RECEIVE_COUNT] neq 0
then
begin
RECEIVE_IN (DB [D_TIM], BUF [SEL4], BUF [SEL6]);
BUF [BSEL0] = BA_CC_I + RCV + 1^%fieldexpand (RQI, 1);
DB [D_ASSIGNED_RECEIVE_COUNT] = .DB [D_ASSIGNED_RECEIVE_COUNT] + 1;
return;
end
else
begin
local
RDB : ref block field (C_FIELDS);
if RDBGT$ (RDB)
then
begin
DB [D_ASSIGNABLE_RECEIVE_COUNT] = .DB [D_ASSIGNABLE_RECEIVE_COUNT] + 1;
CMQIN$ (DB [D_ASSIGNABLE_RECEIVE_CCBS], .RDB);
RECEIVE_IN (DB [D_TIM], BUF [SEL4], BUF [SEL6]);
BUF [BSEL0] = BA_CC_I + RCV + 1^%fieldexpand (RQI, 1);
DB [D_ASSIGNED_RECEIVE_COUNT] = .DB [D_ASSIGNED_RECEIVE_COUNT] + 1;
return;
end
else
RDBRQ$ ();
end;
if .DB [D_ASSIGNED_TRANSMIT_COUNT] lssu .DB [D_MAXIMUM_TRANSMIT_COUNT]
then
if .DB [D_ASSIGNABLE_TRANSMIT_COUNT] neq 0
then
begin
TRANSMIT_IN (DB [D_TIM], BUF [SEL4], BUF [SEL6]);
BUF [BSEL0] = BA_CC_I + XMT + 1^%fieldexpand (RQI, 1);
DB [D_ASSIGNED_TRANSMIT_COUNT] = .DB [D_ASSIGNED_TRANSMIT_COUNT] + 1;
return;
end;
end; !of routine SET_INPUT_REQUEST
global routine SET_PORT (DB) : LINKAGE_DB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
if .DB [D_INPUT_COMMAND] eql 0
then
SET_INPUT_REQUEST (DB [D_TIM]);
if not .DB [DF_SERVICING_DMC] then SERVICE_DMC (DB [D_TIM]);
end; !of routine SET_PORT
routine TIMCCB (DB, CCB) : MCB_DB_CCB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
! CCB =
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_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_OFF]
then
leave RECOVERY with SCHEDULE_STATE_AST (.CCB, DB [D_TIM]);
if .DB [DF_NOTIFY_STATE]
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 DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
if not .DB [DF_SYNCHRONIZING] and
not ($DMC_BITS_CLEAR (.DB [D_REGISTER], SEL0, RDYI) and
$DMC_BITS_CLEAR (.DB [D_REGISTER], SEL2, RDYO))
then
begin
RESET_TIMER (DB [D_TIM]);
COUNTER_INCREMENT (DB, D_LOST_INTERRUPT);
COUNTER_INCREMENT (DB, D_DEVICE_SERVICE_ERRORS);
SERVICE_DMC (DB [D_TIM]);
return;
end;
if .DB [DF_WAITING_FOR_RDYI]
then
begin
RESET_TIMER (DB [D_TIM]);
COUNTER_INCREMENT (DB, D_LOST_RDYI);
COUNTER_INCREMENT (DB, D_DEVICE_SERVICE_ERRORS);
SET_PORT (DB [D_TIM]);
! SEND_PERSISTENT_ERROR (DB [D_TIM], DLL$_DEVICE_RESPONSE_ERROR);
return;
end;
if .DB [DF_FLUSHING_DMC]
then
begin
DB [DF_FLUSHING_DMC] = FALSE;
COUNTER_INCREMENT (DB, D_LOST_HALT);
COUNTER_INCREMENT (DB, D_DEVICE_SERVICE_ERRORS);
MASTER_CLEAR (DB [D_TIM]);
RESET_TIMER (DB [D_TIM]);
SEND_PERSISTENT_ERROR (DB [D_TIM], DLL$_DEVICE_RESPONSE_ERROR);
CHANGE_PROTOCOL_STATE (DB [D_TIM], DS_HALTED, RMT);
SET_PORT (DB [D_TIM]);
return;
end;
if .DB [D_ASSIGNED_TRANSMIT_COUNT] neq 0
then
if (.DB [D_PROTOCOL_STATE] eql DS_MAINTENANCE) or .DB [DF_PROTOCOL_UP]
then
begin
SEND_PERSISTENT_ERROR (DB [D_TIM], DLL$_DEVICE_RESPONSE_ERROR);
COUNTER_INCREMENT (DB, D_LOST_TRANSMIT);
COUNTER_INCREMENT (DB, D_DEVICE_SERVICE_ERRORS);
MASTER_CLEAR (DB [D_TIM]);
RESET_TIMER (DB [D_TIM]);
SET_PORT (DB [D_TIM]);
return;
end;
if .DB [DF_WAITING_FOR_RECEIVE]
then
begin
DB [DF_WAITING_FOR_RECEIVE] = FALSE;
SEND_TRANSIENT_ERROR (DB [D_TIM], DLL$_SERVICE_TIMEOUT);
RESET_TIMER (DB [D_TIM]);
return;
end;
end; !of routine TIMLTM
routine TIMPIN (DB) : MCB_DB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
if .DB [DF_DMR_LINE] then return;
DMCDBI ();
DMCNMI ();
DMCDVI ();
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 DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
SIGNAL_STOP (DMC$_PWF);
end; !of routine TIMPWF
routine TIMRDB (DB, CCB) : MCB_DB_CCB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
! CCB =
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
map
CCB : ref block field (C_FIELDS);
case .DB [D_DEVICE_STATE] from DD_LOW to DD_HIGH of
set
[DD_CLEARED, DD_MASTER_CLEARED] :
RDBRT$ (.CCB);
[inrange] :
begin
DB [D_ASSIGNABLE_RECEIVE_COUNT] = .DB [D_ASSIGNABLE_RECEIVE_COUNT] + 1;
CMQIN$ (DB [D_ASSIGNABLE_RECEIVE_CCBS], .CCB);
SET_PORT (DB [D_TIM]);
end;
tes;
end; !of routine TIMRDB
routine TRANSMIT_IN (DB, LOW, HIGH) : DMC_DB_LOW_HIGH novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
local
ADDRESS,
BIAS,
CCB : ref block field (C_FIELDS),
LENGTH;
if not CMQRM$ (DB [D_ASSIGNABLE_TRANSMIT_CCBS], CCB)
then
return SIGNAL_STOP (DMC$_QUE, DB [D_ASSIGNABLE_TRANSMIT_CCBS]);
DB [D_ASSIGNABLE_TRANSMIT_COUNT] = .DB [D_ASSIGNABLE_TRANSMIT_COUNT] - 1;
CMQIN$ (DB [D_ASSIGNED_TRANSMIT_CCBS], .CCB);
if .CCB [C_CHN] eql 0
then
begin
BIAS = .CCB [C_BIAS];
ADDRESS = .CCB [C_ADDR];
LENGTH = .CCB [C_CNT];
end
else
begin
BIAS = .DB_BIAS;
ADDRESS = LENGTH = .DB [D_NEXT_TRANSMIT_BUFFER];
LENGTH = $MCB_COPY_CHAIN_TO_BUFFER (.CCB, (.BIAS, .ADDRESS));
MAP$ (.DB_BIAS);
DB [D_NEXT_TRANSMIT_BUFFER] = .DB [D_NEXT_TRANSMIT_BUFFER] + .DB [D_TRANSMIT_BUFFER_SIZE];
if .DB [D_NEXT_TRANSMIT_BUFFER] geqa .DB [D_HIGHEST_TRANSMIT_BUFFER]
then
DB [D_NEXT_TRANSMIT_BUFFER] = DB [D_BUF];
end;
begin
local
TEMP;
$MCB_CONVERT_TO_UBA_ADDRESS ((.BIAS, .ADDRESS), .LOW, TEMP);
TEMP = .TEMP^%fieldexpand (BA_HIGH, 1);
.HIGH = (TEMP = .TEMP + .LENGTH);
end;
end; !of routine TRANSMIT_IN
routine TRANSMIT_OUT (DB, LOW, HIGH) : DMC_DB_LOW_HIGH novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
!
! IMPLICIT INPUTS:
! None
!
! IMPLICIT OUTPUTS:
! None
!
! ROUTINE VALUE:
! COMPLETION CODES:
! None
!
! SIDE EFFECTS:
! None
!--
begin
GET_DMC_DATA_BASE (DB)
map
HIGH : block [1] field (DMC_FIELDS),
LOW : block [1] field (DMC_FIELDS);
local
CCB : ref block field (C_FIELDS);
if not CMQRM$ (DB [D_ASSIGNED_TRANSMIT_CCBS], CCB)
then
SIGNAL_STOP (DMC$_QUE, DB [D_ASSIGNED_TRANSMIT_CCBS]);
if
not begin
if .CCB [C_CHN] eqla 0
then
CHECK_BA (DB [D_TIM], .CCB [C_BIAS], .CCB [C_ADDR])
else
CHECK_BA (DB [D_TIM], .DB_BIAS, 0)
end
then
begin
SCHEDULE_TRANSMIT (.CCB, DB [D_TIM], DLL$_ABORTED);
COUNTER_INCREMENT (DB, D_TRANSMIT_BA_MISMATCH);
COUNTER_INCREMENT (DB, D_FATAL_DEVICE_ERRORS);
SEND_PERSISTENT_ERROR (DB [D_TIM], DLL$_DEVICE_OPERATION_ERROR);
MASTER_CLEAR (DB [D_TIM]);
return;
end;
selectone .DB [D_PROTOCOL_STATE] of
set
[DS_RUNNING] :
begin
COUNTER_ADD (DB, D_BYTES_TRANSMITTED, .HIGH [CC]);
COUNTER_INCREMENT (DB, D_BLOCKS_TRANSMITTED);
end;
[DS_MAINTENANCE] :
if .CCB [C_MOD] eql DLL$K_TRANSMIT_AND_TIME
then
DB [DF_WAITING_FOR_RECEIVE] = TRUE;
tes;
DB [DF_PROTOCOL_UP] = TRUE;
SCHEDULE_TRANSMIT (.CCB, DB [D_TIM], DLL$_SUCCESS);
end; !of routine TRANSMIT_OUT
routine ZERO_CIRCUIT_COUNTERS (DB) : LINKAGE_DB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
!
! 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)
COUNTER_ZERO (DB, D_BYTES_RECEIVED); ! [1000]
COUNTER_ZERO (DB, D_BYTES_TRANSMITTED); ! [1001]
COUNTER_ZERO (DB, D_BLOCKS_RECEIVED); ! [1010]
COUNTER_ZERO (DB, D_BLOCKS_TRANSMITTED); ! [1011]
begin
macro
BASE (FLD) = DB [$SUB_FIELD (D_LNTB, FLD)] %,
COPY (FLD) = DB [$SUB_FIELD (D_CPTB, FLD)] %;
begin
local
CNT,
FRM_PTR,
TO_PTR;
FRM_PTR = BASE [BASE_COUNTER_BEGIN];
TO_PTR = COPY [BASE_COUNTER_BEGIN];
CNT = %fieldexpand (BASE_NAKS_RCV_REP, 0)^1 + %fieldexpand (BASE_NAKS_RCV_REP, 1)/8
- %fieldexpand (BASE_COUNTER_BEGIN, 0)^1 + %fieldexpand (BASE_COUNTER_BEGIN, 1)/8;
do ch$wchar_a (ch$rchar_a (FRM_PTR), TO_PTR) while (CNT = .CNT - 1) nequ 0;
end;
if .DB [DF_DMR]
then
begin
COPY [BASE_NAKS_RCV_REP] = .BASE [BASE_NAKS_RCV_REP];
COPY [BASE_NAKS_RCV_TOO_LONG] = .BASE [BASE_NAKS_RCV_TOO_LONG];
COPY [BASE_NAKS_SND_RCV_REP] = .BASE [BASE_NAKS_SND_RCV_REP];
COPY [BASE_INCOMPLETE_SEL] = .BASE [BASE_INCOMPLETE_SEL];
COPY [BASE_NO_REPLY_TO_SEL] = .BASE [BASE_NO_REPLY_TO_SEL];
end;
end;
end;
routine ZERO_LINE_COUNTERS (DB) : LINKAGE_DB novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
! DB = address of DMC data base.
!
! 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 [DF_DMR]
then
begin
macro
BASE (FLD) = DB [$SUB_FIELD (D_LNTB, FLD)] %,
COPY (FLD) = DB [$SUB_FIELD (D_CPTB, FLD)] %;
COPY [BASE_NAKS_RCV_RCV_OVRN] = .BASE [BASE_NAKS_RCV_RCV_OVRN];
COPY [BASE_NAKS_RCV_HDR_FMT] = .BASE [BASE_NAKS_RCV_HDR_FMT];
COPY [BASE_NAKS_SND_RCV_OVRN] = .BASE [BASE_NAKS_SND_RCV_OVRN];
COPY [BASE_NAKS_SND_HDR_FMT] = .BASE [BASE_NAKS_SND_HDR_FMT];
COPY [BASE_XMT_UNDR] = .BASE [BASE_XMT_UNDR];
COPY [BASE_STRM_TIMEOUT] = .BASE [BASE_STRM_TIMEOUT];
end;
end;
end
eludom