Trailing-Edge
-
PDP-10 Archives
-
bb-h138f-bm
-
7-sources/mxnt20.r36
There are 11 other files named mxnt20.r36 in the archive. Click here to see a list.
! UPD ID= 230, SNARK:<6.1.NML>NMUT20.R36.6, 17-Jan-85 10:45:37 by GLINDELL
! Change STOP_PROGRAM to call NMLDIE
!
! UPD ID= 187, SNARK:<6.1.NML>NMUT20.R36.5, 10-Dec-84 14:36:03 by HALPIN
! Get MONSYM Library file out of default directory, not BLI:
!
! UPD ID= 177, SNARK:<6.1.NML>NMUT20.R36.4, 7-Dec-84 08:15:29 by HALPIN
! Add NI_RECEIVER_INTERRUPT routine and linkage definitions.
!
! UPD ID= 103, SLICE:<6.1.NML>NMUT20.R36.3, 18-Sep-84 15:42:29 by GUNN
!
! Move network interface code in macros to NETT20.B36 to allow
! compilation with BLISS V3.0 and beyond. Make macros here under
! conditional for TOPS20.
!
! Fix to allow compilation under BLISS V3.0.
! Add LIBRARY's in each macro.
!
! WORK:<GUNN.NML>NMUT20.R36.3 31-Jul-84 10:53:51, Edit by GUNN
!
! Change parameter name in macro TIME_PLUS. It conflicts with the
! JSYS name 'TIME'.
!
! UPD ID= 21, SNARK:<6.1.NML>NMUT20.R36.2, 24-May-84 13:58:01 by GLINDELL
! PH4:<MCINTEE>NMUT20.R36.5, 2-Jun-83 08:31:31, Edit by MCINTEE
!
! Change the format of debugging descriptor so it is usable
! It used to be SRV:19-USERNAME or DCN:KL2102-19-USERNAME
! It now is SRV:USERNAME19 or DCN:KL2102-0-USERNAME19
!
! PH4:<BUILD>NMUT20.R36.3 3-May-83 16:14:20, Edit by GUNN
! Change debugging network filespecs to not use descriptor.
! Not allowed under R6.0
!
! <BRANDT.DEVELOPMENT>NMUT20.R36.1 29-Sep-82 9:27:30, Edit by BRANDT
! Change READ_MESSAGE timeout to 1 minute.
!
! <BRANDT.DEVELOPMENT>NMUT20.R36.1 29-Jun-82 10:00:30, Edit by BRANDT
! Change OPEN_FOR_CONNECTION so that the AC used for the local
! variable, JFN, cannot contain garbage in the left half.
!
! <BRANDT.DEVELOPMENT>NMUT20.R36.1 28-May-82 11:57:03, Edit by BRANDT
! Change READ_MESSAGE macro so function timeouts work.
!
! <PLATUKIS>NMUT20.R36.2 28-Apr-82 11:57:03, Edit by PLATUKIS
! remove SOBE jsys calls from WRITE_MESSAGE and WRITE_STRING macros.
!
! Fix bug in LOCK macro introduced by VOBA cleaning up!
!
! NET:<VOBA.NML.DEVELOPMENT>NMUT20.R36.7 19-Feb-82 11:14:04, Edit by VOBA
!
! Clean up code and update copyright date.
!
! NET:<GROSSMAN>NMUT20.R36.2 27-Jan-82 08:56:17, Edit by GROSSMAN
!
! Fix macro TIME_PLUS so that it is more accurate for long periods of time
! (on the order of 10000 seconds and up).
!
! NET:<GROSSMAN>NMUT20.R36.2 22-Jan-82 15:46:33, Edit by GROSSMAN
!
! Fix macro TIME_DIFFERENCE_SECONDS. It uses an ASH to divide by 1^18. The
! quotient should have been rounded off in order to get more accurate times
! from the expression.
!
! NET:<DECNET20-V3P1.NMLLIB>NMUT20.R36 02-Dec-81 09:49:20, Edit by THIGPEN
!
! Add WAIT_BLOCK for use in timing out NMU$SCHED_WAIT calls.
! Change call to NMU$SCHED_WAIT in macro READ_MESSAGE to include timeout value
!
! NET:<GROSSMAN>NMUT20.R36.5 18-Jan-82 23:59:00, Edit by GROSSMAN
!
! Add macros TIME_DIFFERENCE_SECONDS and TIME_PLUS to compute the temporal
! difference between two TIME_BLOCKS and to add an offset in seconds to a
! TIME_BLOCK.
!
! NET:<DECNET20-V3P1.NMU>NMUT20.R36.2 23-Sep-81 19:57:33, Edit by GUNN
!
! Change CONNECT_WAIT to look at only LSB_CIWAIT when for source link.
!
! NET:<DECNET20-V3P1.NMU>NMUT20.R36.2 26-Jun-81 13:18:35, Edit by GUNN
!
! Change call to NMU$SCHED_SLEEP (1) to $$DISMS (1) in
! ACCEPT_NETWORK_CONNECT.
!
!NET:<DECNET20-V3P1.NMU>NMUT20.R36.2 12-Jun-81 13:43:49, Edit by JENNESS
!
! Readability improvements.
!
!NET:<DECNET20-V3P1.NMU>NMUT20.R36.2 27-May-81 09:37:54, Edit by JENNESS
!
! Add definitions for all JSYS calls (JLNKG.R36).
!
!NET:<DECNET20-V3P1.NCP.SOURCES>NMUT20.R36.3 22-Apr-81 08:03:02, Edit by GUNN
!
! Fix logic error in ACCEPT_NETWORK_CONNECT. Make debugging descriptor id
! also be used when .JBOPS is non-zero.
!
!NET:<DECNET20-V3P1.NCP.SOURCES>NMUT20.R36.2 17-Apr-81 14:51:47, Edit by GUNN
!
! Fix code in ACCEPT_NETWORK_CONNECT which checks for link connection.
!
! NET:<DECNET20-V3P1.NML>NMUT20.R36.3 31-Mar-81 17:07:45, Edit by GUNN
!
! Fix ACCEPT_NETWORK_CONNECT to wait until link is actually connected,
! aborted, or disconnected before returning control to user.
!
!NET:<DECNET20-V3P1.NMU>NMUT20.R36.14 24-Mar-81 16:31:52, Edit by JENNESS
! Fix CORE_GET to return zero (0) if exceeded address 400000.
!NET:<DECNET20-V3P1.NMU>NMUT20.R36.3 17-Mar-81 15:50:54, Edit by JENNESS
! Add debugging messages in network macros.
!NET:<DECNET20-V3P1.BASELEVEL-2.SOURCES>NMUT20.R36.19 11-Mar-81 10:59:14, Edit by JENNESS
! Return true/false from OPEN_FOR_CONNECTION indicating success.
!NET:<DECNET20-V3P1.NMU>NMUT20.R36.10 3-Feb-81 10:24:09, Edit by JENNESS
! Add IPCF_INTERRUPT routine and linkage definitions.
! Add specific user name to logical link descriptor for debugging if
! .135 neq 0.
! Fix error handling in WRITE_MESSAGE and WRITE_STRING if SOUT(R) fails.
! Fix error handling if MTOPR fails in READ_STATUS.
%title 'NMUT20 - Network Management Utilities TOPS-20 Definitions'
! COPYRIGHT (C) 1981, 1982 BY
! DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS 01754
!
! THIS SOFTWARE IS FURNISHED UNDER A LICENSE FOR USE ONLY ON A SINGLE
! COMPUTER SYSTEM AND MAY BE COPIED ONLY 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
! EXCEPT FOR USE ON SUCH SYSTEM AND TO ONE WHO AGREES TO THESE LICENSE
! TERMS. TITLE TO AND OWNERSHIP OF THE SOFTWARE SHALL AT ALL TIMES
! REMAIN IN DEC.
!
! THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE
! AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT
! CORPORATION.
!
! DEC ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
! SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DEC.
!
!++
! Facility: LSG DECnet Network Management
!
! Abstract: This file contains definitions that are specific to TOPS-20.
!
! Environment: Bliss-36, TOPS20
!
! Author: Steven M. Jenness, Creation date: 21-Oct-80
!
!--
!
! Other requirements for TOPS20
!
switches list (norequire); ! Suppress monitor symbol listing
library 'MONSYM'; ! Monitor symbols
switches list (require);
library 'MXJLNK'; ! JSYS linkage definitions
%title 'NMUT20 - Network Management Utilities TOPS-20 Definitions'
%sbttl 'Definitions For 36 Bit Instructions'
literal
HRRI = %O'541', ! Half right to right immediate
HRLI = %O'505', ! Half right to left immediate
EXCH = %O'250', ! Exch register and memory
SETOM = %O'476', ! Set memory to all ones
SETZM = %O'402', ! Set memory to all zeros
AOSE = %O'352', ! Add one to memory, skip if eql 0
SOSLE = %O'373', ! Subtract one from memory, skip leq 0
PUSH = %O'261', ! Push value onto stack
POP = %O'262', ! Pop value from stack
PUSHJ = %O'260', ! Call routine, save return on stack
ADJSP = %O'105', ! Adjust stack pointer
MOVEI = %O'201', ! Load effective address into register
MOVEM = %O'202', ! Store register contents into memory
BLT = %O'251'; ! Transfer memory block
literal
MEMSIZE = %O'121', ! Location containing first free word
! in memory.
CONTEXT_SIZE = %O'20'; ! Number of fullwords in a task's
! context (all the registers).
field STACK_POINTER_FIELDS =
set
STACK_SIZE = [0, 18, 18, 1], ! Number of words left in stack
STACK_ADDRESS = [0, 0, 18, 0] ! Address of current word in stack
tes;
%sbttl 'Halt program Macro'
! macro: STOP_PROGRAM
!
! Function - This macro halts the program
!
! Parameters - None
macro
STOP_PROGRAM =
begin
local
TASK: ref TASK_BLOCK;
external routine NMLDIE;
TASK = CURRENT_TASK;
NMLDIE ( .TASK [TB_ERROR_PC], ch$ptr( TASK [TB_ERROR_BUFFER]));
end %;
%sbttl 'Semaphore LOCK/UNLOCK Macros'
! macro: LOCK
!
! Function - This macro attempts a semaphore lock. If the lock
! attempt is successful, a "true" value is returned.
!
! Parameters -
!
! SEMA_ADR Address of a SEMAPHORE_BLOCK
macro
LOCK (SEMA_ADDR) =
begin
builtin MACHSKIP;
bind SEMBLK = SEMA_ADDR : SEMAPHORE_BLOCK;
MACHSKIP (AOSE, 0, SEMBLK [SEMAPHORE])
end %;
! macro: UNLOCK
!
! Function - This macro unlocks a semaphore that has been locked
! with a LOCK macro call.
!
! Parameters -
!
! SEMA_ADDR Address of a SEMAPHORE_BLOCK.
macro
UNLOCK (SEMA_ADDR) =
begin
builtin MACHOP;
bind SEMBLK = SEMA_ADDR : SEMAPHORE_BLOCK;
MACHOP (SETOM, 0, SEMBLK [SEMAPHORE]);
end %;
%sbttl 'Task Scheduling Macros'
! macro: CONTEXT_SWITCH
!
! Function - This macro swaps the current task with the
! specified future task.
!
! Parameters -
!
! NEW_TASK Address of the new task's task block
macro
CONTEXT_SWITCH (NEW_TASK) =
begin
external routine SS_SWITCH; ! System specific routine
SS_SWITCH (NEW_TASK);
end %;
! macro: CURRENT_TASK
!
! Function - This macro returns the address of the
! current task's task block.
!
! Return value -
!
! Address the current task's task block.
macro
CURRENT_TASK =
begin
external CURTSK; ! Cell containing current task
.CURTSK
end %;
! macro: TASK_INITIALIZE
!
! Function - This macro initializes a task's task block.
! Specifically it sets up the stack and the
! starting address so that the task will swap
! context properly the first time that it
! is scheduled.
!
! Parameters -
!
! TK_BLOCK The task's task block address
! STACK_SIZE Number of fullwords for the task's stack
macro
TASK_INITIALIZE (TK_BLOCK, STACK_SIZE) =
begin
external routine SS_TINIT; ! System specific routine
SS_TINIT (TK_BLOCK, STACK_SIZE);
end %;
%sbttl 'Interrupt Macros'
! Macro - INTERRUPT_DATA_BASE
!
! Function - This macro defines the interrupt vector tables
! and any other miscellaneous variables that are
! required by the interrupt system.
macro
INTERRUPT_DATA_BASE =
literal
INTERRUPT_STACK_SIZE = 100; ! Number of words in a interrupt stack
global
VECTAB : vector [36], ! Routine to call for each channel
DATTAB : vector [36], ! Data to pass to interrupt routine
LEV1PC, ! PC storage for level 1 interrupts
LEV2PC, ! PC storage for level 2 interrupts
LEV3PC, ! PC storage for level 3 interrupts
LEVTAB : vector [3] ! Vector for PC storage for each level
preset ([0] = LEV1PC, [1] = LEV2PC, [2] = LEV3PC),
LEV1CHN, ! Channel currently active on channel 1
LEV2CHN, ! Channel currently active on channel 2
LEV3CHN; ! Channel currently active on channel 3
!
! Stack and pointer for interrupt level 1
!
own
STACK1 : vector [INTERRUPT_STACK_SIZE],
LEV1STK : block [1] field (STACK_POINTER_FIELDS)
preset ([STACK_SIZE] = -INTERRUPT_STACK_SIZE,
[STACK_ADDRESS] = STACK1);
!
! Stack and pointer for interrupt level 2
!
own
STACK2 : vector [INTERRUPT_STACK_SIZE],
LEV2STK : block [1] field (STACK_POINTER_FIELDS)
preset ([STACK_SIZE] = -INTERRUPT_STACK_SIZE,
[STACK_ADDRESS] = STACK2);
!
! Stack and pointer for interrupt level 3
!
own
STACK3 : vector [INTERRUPT_STACK_SIZE],
LEV3STK : block [1] field (STACK_POINTER_FIELDS)
preset ([STACK_SIZE] = -INTERRUPT_STACK_SIZE,
[STACK_ADDRESS] = STACK3);
!
! Define channels on each interrupt level.
!
macro
LEVEL1_INTERRUPT_SET =
$ICAOV, $ICFOV, $ICPOV, $ICILI,
$ICIRD, $ICIWR, $ICMSE
%quote %;
macro
LEVEL2_INTERRUPT_SET =
0, 1, 2, 3, 4, 5, 23, 24, 25, 26, 27,
28, 29, 30, 31, 32, 33, 34, 35
%quote %;
!
! Vector routines for each interrupt channel.
!
macro
$$INT_FORWARDS [CHNNO] =
%name ('CSRV', CHNNO) : novalue %quote %;
macro
LEVEL1_VECTOR_ROUTINES [] =
forward routine
$$INT_FORWARDS (%remaining);
$$LEV1_ROUTINE (%remaining);
%quote %;
macro
$$LEV1_ROUTINE [CHNNO] =
routine %name ('CSRV', CHNNO) : novalue =
begin
DECLARE_JSYS (DEBRK)
literal P = %O'17';
builtin MACHOP;
MACHOP (EXCH, P, LEV1STK);
MACHOP (PUSH, P, 1);
MACHOP (MOVEI, 1, CHNNO);
MACHOP (MOVEM, 1, LEV1CHN);
MACHOP (PUSHJ, P, VECTAB + CHNNO, 0, 1);
MACHOP (SETOM,, LEV1CHN);
MACHOP (POP, P, 1);
MACHOP (EXCH, P, LEV1STK);
$$DEBRK ();
end;
%quote %;
macro
LEV1INT [CHNNO] =
[CHNNO, CT_LEVEL] = 1,
[CHNNO, CT_VECTOR] = %name ('CSRV', CHNNO)
%quote %;
macro
LEVEL2_VECTOR_ROUTINES [] =
forward routine
$$INT_FORWARDS (%remaining);
$$LEV2_ROUTINE (%remaining);
%quote %;
macro
$$LEV2_ROUTINE [CHNNO] =
routine %name ('CSRV', CHNNO) : novalue =
begin
DECLARE_JSYS (DEBRK)
literal P = %O'17';
builtin MACHOP;
MACHOP (EXCH, P, LEV2STK);
MACHOP (PUSH, P, 1);
MACHOP (PUSH, P, DATTAB + CHNNO);
MACHOP (MOVEI, 1, CHNNO);
MACHOP (MOVEM, 1, LEV2CHN);
MACHOP (PUSHJ, P, VECTAB + CHNNO, 0, 1);
MACHOP (SETOM,, LEV2CHN);
MACHOP (POP, P, 1);
MACHOP (POP, P, 1);
MACHOP (EXCH, P, LEV2STK);
$$DEBRK ();
end
%quote %;
macro
LEV2INT [CHNNO] =
[CHNNO, CT_LEVEL] = 2,
[CHNNO, CT_VECTOR] = %name ('CSRV', CHNNO)
%quote %;
field CHANNEL_BLOCK_FIELDS =
set
CT_LEVEL = [0, 18, 18, 0], ! Level of interrupt
CT_VECTOR = [0, 0, 18, 0] ! Interrupt vector
tes;
LEVEL1_VECTOR_ROUTINES (LEVEL1_INTERRUPT_SET);
LEVEL2_VECTOR_ROUTINES (LEVEL2_INTERRUPT_SET);
!
! Interrupt channel table
!
global
CHNTAB : blockvector [36, 1] field (CHANNEL_BLOCK_FIELDS)
preset (LEV1INT (LEVEL1_INTERRUPT_SET),
LEV2INT (LEVEL2_INTERRUPT_SET));
%;
%sbttl 'Interrupt Routine Linkages'
macro
INTERRUPT_LINKAGE =
pushj : linkage_regs (15,13,1)
preserve (0,2,3,4,5,6,7,8,9,10,11,12,14)
%;
macro
TIMER_INTERRUPT_ROUTINE =
: TIMER_INTERRUPT_LINKAGE %,
NETWORK_INTERRUPT_ROUTINE =
(LINK_INFO : ref LINK_INFO_BLOCK) : NETWORK_INTERRUPT_LINKAGE %,
NI_RECEIVER_INTERRUPT_ROUTINE =
: NI_RECEIVER_INTERRUPT_LINKAGE %,
IPCF_INTERRUPT_ROUTINE =
: IPCF_INTERRUPT_LINKAGE %;
linkage
VANILLA_INTERRUPT_LINKAGE = INTERRUPT_LINKAGE,
TIMER_INTERRUPT_LINKAGE = INTERRUPT_LINKAGE,
NETWORK_INTERRUPT_LINKAGE = INTERRUPT_LINKAGE,
NI_RECEIVER_INTERRUPT_LINKAGE = INTERRUPT_LINKAGE,
IPCF_INTERRUPT_LINKAGE = INTERRUPT_LINKAGE;
macro
INTERRUPT_ROUTINE [] =
(%remaining) : VANILLA_INTERRUPT_LINKAGE
%warn('Best to Use ???_INTERRUPT_ROUTINE') %;
%sbttl 'Interrupt System Operation Macros'
! Macro - CLEAR_INTERRUPT_SYSTEM
!
! Function - This macro clears the interrupt system. All
! interrupts disabled. Set all interrupt channels
! to not active (-1);
macro
CLEAR_INTERRUPT_SYSTEM =
begin
DECLARE_JSYS (CIS)
$$CIS ();
LEV1CHN = -1;
LEV2CHN = -1;
LEV3CHN = -1;
end %;
! Macro - INITIALIZE_INTERRUPT_SYSTEM
!
! Function - This macro setups any initial values needed in
! the interrupt data base and informs the operating
! system about the interrupt vector tables.
macro
INITIALIZE_INTERRUPT_SYSTEM =
begin
DECLARE_JSYS (SIR, EIR)
local T2;
external INTNST;
INTNST = 0;
T2 <18, 18, 0> = LEVTAB; ! Level table vector
T2 <0, 18, 0> = CHNTAB; ! Channgel table vector
$$SIR ($FHSLF, .T2); ! Set vector tables in PSB
$$EIR ($FHSLF); ! Enable PISYS system
end %;
! Macro - ACTIVATE_INTERRUPT
!
! Function - This macro enables a specific interrupt.
!
! Parameters -
!
! CHANNEL Channel number to activate
macro
ACTIVATE_INTERRUPT (CHANNEL) =
begin
DECLARE_JSYS (AIC)
local T2;
T2 = (1 ^ (35 - CHANNEL));
$$AIC ($FHSLF, .T2);
end %;
! Macro - DEACTIVATE_INTERRUPT
!
! Function - This macro disables a specific interrupt.
!
! Parameters -
!
! CHANNEL Channel number to deactivate
macro
DEACTIVATE_INTERRUPT (CHANNEL) =
begin
DECLARE_JSYS (DIC)
local T2;
T2 = (1 ^ (35 - CHANNEL));
$$DIC ($FHSLF, .T2);
end %;
! Macro - INTERRUPT_ON
!
! Function - This macro enables the interrupt system. If nested
! INTERRUPT_OFF calls have been made, this call only
! decrements the nesting count.
macro
INTERRUPT_ON =
begin
DECLARE_JSYS (DIR, EIR)
builtin MACHSKIP;
external INTNST; ! Interrupt nesting count
$$DIR ($FHSLF); ! Disable interrupts
if MACHSKIP (SOSLE,, INTNST)
then begin
INTNST = 0;
$$EIR ($FHSLF); ! Enable interrupt system
end;
end %;
! Macro - INTERRUPT_OFF
!
! Function - This macro turns the interrupt system off. It
! also increments the nesting count of times that
! it has been turned off.
macro
INTERRUPT_OFF =
begin
DECLARE_JSYS (DIR)
external INTNST;
$$DIR ($FHSLF); ! Turn interrupt system off
INTNST = .INTNST + 1; ! Increment nesting count
end %;
! Macro - ALLOCATE_INTERRUPT_CHANNEL
!
! Function - This macro searchs the interrupt channel table
! for a free channel.
!
! Paramaters -
!
! I_ROUTINE Routine to call when interrupt occurs on channel
! I_DATA Data to pass to interrupt routine when called
!
! Return value -
!
! -1 No channel available
! >0 Channel number
macro
ALLOCATE_INTERRUPT_CHANNEL (I_ROUTINE, I_DATA) =
begin
local RESULT;
external VECTAB : vector [36],
DATTAB : vector [36];
RESULT = -1;
incr INDEX from 0 to 5
do if .VECTAB [.INDEX] eql 0
then begin
RESULT = .INDEX;
exitloop;
end;
if .RESULT lss 0
then incr INDEX from 23 to 35
do if .VECTAB [.INDEX] eql 0
then begin
RESULT = .INDEX;
exitloop;
end;
%if not %null (I_ROUTINE)
%then if .RESULT neq -1
then VECTAB [.RESULT] = I_ROUTINE; %fi
%if not %null (I_DATA)
%then if .RESULT neq -1
then DATTAB [.RESULT] = I_DATA; %fi
.RESULT
end %;
! Macro - RELEASE_INTERRUPT_CHANNEL
!
! Function - This macro flags that an interrupt channel is
! now available for use
!
! Parameters -
!
! CHANNEL Channel number to release
macro
RELEASE_INTERRUPT_CHANNEL (CHANNEL) =
begin
external VECTAB : vector [36];
VECTAB [CHANNEL] = 0;
end %;
! Macro - ARITHMETIC_OVERFLOW
!
! Function - This macro enables interrupts on arithmetic errors.
! The routine specified will be called when an error
! occurs.
!
! Parameters -
!
! E_ROUTINE Address of interrupt service routine
!
macro
ARITHMETIC_OVERFLOW (E_ROUTINE) =
begin
VECTAB [$ICAOV] = E_ROUTINE;
VECTAB [$ICFOV] = E_ROUTINE;
ACTIVATE_INTERRUPT ($ICAOV);
ACTIVATE_INTERRUPT ($ICFOV);
end %;
! Macro - STACK_OVERFLOW
!
! Function - This macro enables interrupts on push down list
! overflows. The routine specified will be called
! when an error occurs.
!
! Parameters -
!
! E_ROUTINE Address of interrupt service routine
macro
STACK_OVERFLOW (E_ROUTINE) =
begin
VECTAB [$ICPOV] = E_ROUTINE;
ACTIVATE_INTERRUPT ($ICPOV);
end %;
! Macro - ILLEGAL_INSTRUCTION
!
! Function - This macro enables interrupts on illegal instruction
! traps. The routine specified will be called when an
! error occurs.
!
! Parameters -
!
! E_ROUTINE Address of interrupt service routine
macro
ILLEGAL_INSTRUCTION (E_ROUTINE) =
begin
VECTAB [$ICILI] = E_ROUTINE;
ACTIVATE_INTERRUPT ($ICILI);
end %;
! Macro - ILLEGAL_MEMORY_REFERENCE
!
! Function - This macro enables interrupts on illegal memory reads
! and writes. The routine specified will be called when
! an error occurs.
!
! Parameters -
!
! E_ROUTINE Address of interrupt service routine
macro
ILLEGAL_MEMORY_REFERENCE (E_ROUTINE) =
begin
VECTAB [$ICIRD] = E_ROUTINE;
VECTAB [$ICIWR] = E_ROUTINE;
ACTIVATE_INTERRUPT ($ICIRD);
ACTIVATE_INTERRUPT ($ICIWR);
end %;
! Macro - SYSTEM_RESOURCE_FAILURE
!
! Function - This macro enables interrupts on system resource
! allocation failures. The routine specified will
! be called when an error occurs.
!
! Parameters -
!
! E_ROUTINE Address of interrupt service routine
macro
SYSTEM_RESOURCE_FAILURE (E_ROUTINE) =
begin
VECTAB [$ICMSE] = E_ROUTINE;
ACTIVATE_INTERRUPT ($ICMSE);
end %;
%sbttl 'System Specific Time Interface'
! This set of macros allows transparent manipulation of "time"
! in a particular system. The macros are defined to read time
! from the operating system, read time with a offset, compare time,
! set and clear interrupts on time.
!
!
! Time block structure
!
! This structure defines the format needed for a specific
! system to store a internal time/date value.
literal
TIME_BLOCK_SIZE = 1,
TIME_BLOCK_ALLOCATION = 1;
macro
TIME_BLOCK =
vector [1] %;
! Macro - TIME_PLUS
!
! Function - This macro adds the second argument (which is in units of
! seconds) to the first argument which is a time block.
macro
TIME_PLUS (TIME, SECONDS) =
begin
bind TBLK = TIME : TIME_BLOCK;
TBLK [0] = .TBLK[0] + SECONDS ^ 18 / (24 * 60 * 60)
end %;
! Macro - TIME_DIFFERENCE_SECONDS
!
! Function - Compute the difference (in seconds) of two TIME_BLOCKS
macro
TIME_DIFFERENCE_SECONDS (TIME1, TIME2) =
begin
builtin ash;
bind TBLK1 = TIME1 : TIME_BLOCK,
TBLK2 = TIME2 : TIME_BLOCK;
ash (((.TBLK1[0] - .TBLK2[0]) * 24 * 60 * 60 + 1 ^ 17), -18)
end %;
! Macro - TIME_INTERRUPT_CLEAR
!
! Function - This macro clears all outstanding timer interrupts.
macro
TIME_INTERRUPT_CLEAR =
begin
DECLARE_JSYS (TIMER)
literal TIME_CHANNEL = 35;
local T1;
T1<18,18,0> = $FHSLF;
T1<0,18,0> = $TIMAL;
$$TIMER (.T1);
DEACTIVATE_INTERRUPT (TIME_CHANNEL);
end %;
! Macro - TIME_INTERRUPT_SET
!
! Function - This macro sets a time interrupt. It also
! defines the routine to be called when the
! interrupt occurs.
!
! Note that since the interrupt channel is
! hard coded the time interrupt must be unique.
!
! Parameters -
!
! TIM_BLK Address of time block with time in the future for a interrupt
! TROUTINE Address of the interrupt service routine
macro
TIME_INTERRUPT_SET (TIM_BLK, TROUTINE) =
begin
DECLARE_JSYS (TIMER, AIC)
bind TBLK = TIM_BLK : TIME_BLOCK;
literal TIME_CHANNEL = 35;
external VECTAB : vector [36];
local T1;
T1<18,18,0> = $FHSLF;
T1<0,18,0> = $TIMDT;
VECTAB [TIME_CHANNEL] = TROUTINE;
if $$TIMER (.T1, .TBLK [0], TIME_CHANNEL)
then ACTIVATE_INTERRUPT (TIME_CHANNEL)
else if .T1 eql TIMX6
then TROUTINE ();
end %;
! Macro - TIME_CURRENT
!
! Function - This macro returns the current time in
! the host operating systems time format.
! This is the format needed to set timer
! interrupts.
!
! Parameters -
!
! OFFSET is the number of seconds to add to the actual current time.
! TIM_BLK is the address of the time block in which to store
! the resulting time.
macro
TIME_CURRENT (OFFSET, TIM_BLK) =
begin
DECLARE_JSYS (GTAD)
bind TBLK = TIM_BLK : TIME_BLOCK;
$$GTAD (;TBLK [0]);
TBLK [0] = .TBLK [0] + OFFSET * 3;
end %;
! Macro - TIME_SET_NULL
!
! Function - This macro sets a time block to a null value.
! This value is used as a sentinel to check for
! a valid time value (null/not null).
!
! Parameters -
!
! TIM_BLK Address of the time block
macro
TIME_SET_NULL (TIM_BLK) =
begin
bind TBLK = TIM_BLK : TIME_BLOCK;
TBLK [0] = -1;
end %;
! Macro - TIME_NOT_NULL
!
! Function - This macro checks to the value in a time block
! to see if it is not null (see TIME_SET_NULL).
!
! Parameters -
!
! TIM_BLK Address of the time block to test
macro
TIME_NOT_NULL (TIM_BLK) =
begin
bind TBLK = TIM_BLK : TIME_BLOCK;
.TBLK [0] neq -1
end %;
! Macro - TIME_NULL
!
! Function - This macro checks to the value in a time block
! to see if it is null (see TIME_SET_NULL).
!
! Parameters -
!
! TIM_BLK Address of the time block to test
macro
TIME_NULL (TIM_BLK) =
begin
bind TBLK = TIM_BLK : TIME_BLOCK;
.TBLK [0] eql -1
end %;
! Macro - TIME_COPY
!
! Function - This macro copies the time from one time block
! to another time block.
!
! Parameters -
!
! TO_BLK Time block to copy the time to
! FRM_BLK Time block to copy the time from
macro
TIME_COPY (TO_BLK, FRM_BLK) =
begin
bind TOBLK = TO_BLK : TIME_BLOCK,
FRMBLK = FRM_BLK : TIME_BLOCK;
TOBLK [0] = .FRMBLK [0];
end %;
! Macro - TIME_TEST
!
! Function - This macro tests the chronological relation of
! the values in two time blocks. The test operator
! is specified as an argument to the macro. The
! value returned by this macro is a boolean (true/false)
! from the test "TB1 TST_FNC TB2" (i.e. TB1 lss TB2).
!
! Parameters -
!
! TBLK1 The first time block
! TST_FNC The test operator (LSS, GTR, EQL,..etc)
! TBLK2 The second time block
macro
TIME_TEST (TBLK1, TST_FNC, TBLK2) =
begin
bind TIMBLK1 = TBLK1 : TIME_BLOCK,
TIMBLK2 = TBLK2 : TIME_BLOCK;
.TIMBLK1 [0] TST_FNC .TIMBLK2 [0]
end %;
%sbttl 'Memory Allocation'
! Wait Block Structure
!
! This defines the WAIT_BLOCK used in timing out waiting for events,
! specifically those waits implemented by calling NMU$SCHED_WAIT.
$field WAIT_BLOCK_FIELDS =
set
WAITING_TASK = [$address], ! Task block address, to ref semaphore
$align (fullword)
WAIT_EVENT = [$address], ! Address of event block to wait on
$align (fullword)
WAIT_TIME = [$sub_block(TIME_BLOCK_SIZE)] ! Time at which to 'wake'
tes;
literal
WAIT_BLOCK_SIZE = $field_set_size;
macro
WAIT_BLOCK = block [WAIT_BLOCK_SIZE] field (WAIT_BLOCK_FIELDS)%;
! Macro - CORE_GET
!
!
! Function - This macro gets a block of memory from the
! operating system of the specified size. The
! address of the block is returned as the value
! of the macro.
!
! Parameters -
!
! BLOCK_SIZE The number of fullwords to be allocated
!
! Return value -
!
! 0 if no memory can be allocated
! <>0 address of memory block allocated
macro
CORE_GET (BLKSIZE) =
begin
local BLKADDR;
BLKADDR = .%O'121'; ! Get current .JBFF value
%O'121' = .%O'121' + BLKSIZE;
if .%O'121' lss %O'400000'
then .BLKADDR
else 0
end %;
%sbttl 'Process Sleep And Wakeup'
! Macro - PROCESS_SLEEP
!
! Function - This macro puts the current process to
! sleep for the specified amount of time.
! The process is not guaranteed to sleep
! the specified amount.
!
! Parameters -
!
! TIME The number of seconds to sleep
macro
PROCESS_SLEEP (TIME) =
begin
DECLARE_JSYS (THIBR)
$$THIBR (TIME);
end %;
! Macro - PROCESS_WAKE
!
! Function - This macro wakes up the current process.
! It may be called at interrupt level to
! complement the PROCESS_SLEEP function.
macro
PROCESS_WAKE =
begin
DECLARE_JSYS (GJINF, TWAKE)
local JOB;
$$GJINF (;,,JOB);
$$TWAKE (.JOB);
end %;
%sbttl 'Network Interface Macros'
!
! System specific fields for the LINK_INFO_BLOCK
!
macro
LINK_SYSTEM_SPECIFIC_FIELDS =
LINK_FILE = [$string (150)], ! File specification
LINK_JFN = [$integer], ! JFN for link
LINK_CHANNEL = [$integer] ! Interrupt channel for link
%;
! Macro - LOCAL_NODE_NUMBER
!
! Function - This macro returns the local node number. It
! puts it into a byte string pointed to by the
! supplied byte pointer.
!
! Parameters -
!
! NODE_PTR is the address of a byte pointer that is
! updated when done.
%if not $TOPS20
%then
macro
LOCAL_NODE_NUMBER (NODE_PTR) =
begin
DECLARE_JSYS (NODE)
local NODE_NUMBER;
$$NODE ($NDGNM, NODE_NUMBER);
ch$wchar_a (.NODE_NUMBER<0,8,0>, NODE_PTR);
ch$wchar_a (.NODE_NUMBER<8,8,0>, NODE_PTR);
end %;
%fi
! Macro - LOCAL_NODE_NAME
!
! Function - This macro returns the local node name in a
! counted ASCII string. The node name is written
! into the string pointed to by the supplied byte
! pointer and the first byte is the number of characters
! in the node name.
!
! Parameters -
!
! NODE_PTR Address of a byte pointer
%if not $TOPS20
%then
macro
LOCAL_NODE_NAME (NODE_PTR) =
begin
DECLARE_JSYS (NODE)
local NAME_PTR;
NAME_PTR = ch$plus (.NODE_PTR, 1);
$$NODE ($NDGLN, NAME_PTR);
ch$wchar_a (ch$len (ch$plus (.NODE_PTR, 1)), NODE_PTR);
end %;
%fi
! Macro - BUILD_LINK_INFO_BLOCK
!
! Function - This macro fills in the system specific
! portions of the link info block. The source
! of information that it uses is the connect block
! passed to NMU$NETWORK_OPEN
!
! Parameters -
!
! CONN_BLK Address of connect block
! LINK_INFO Address of link info block
%if not $TOPS20
%then
macro
BUILD_LINK_INFO_BLOCK (CONN_BLK, LINK_INFO) =
begin
external routine USER_NAME;
local FILE_PTR;
bind LI = LINK_INFO : LINK_INFO_BLOCK,
CB = CONN_BLK : CONNECT_BLOCK;
LI [LINK_JFN] = 0;
FILE_PTR = ch$ptr (LI [LINK_FILE]);
if .LI [LINK_TYPE] eql SOURCE_LINK
then begin
!
! Create DCN:HOST-OBJECT
!
begin
local NAME_PTR, LENGTH, NODE_ADDRESS;
NAME_PTR = .CB [CB_HOST];
NODE_ADDRESS = GETW (NAME_PTR);
LENGTH = GETB (NAME_PTR);
if .LENGTH gtr 0
then $NMU$TEXT (FILE_PTR,
14,
'%NDCN:%#A-',
.LENGTH,
.NAME_PTR)
else $NMU$TEXT (FILE_PTR,
14,
'%NDCN:%D-',
.NODE_ADDRESS);
end;
!
! Add optional "descriptor" if debugging, i.e., PRIVATE_HOST_LINK is set
!
if PRIVATE_HOST_LINK
then $NMU$TEXT (FILE_PTR,
18,
'%N0-%@',
USER_NAME);
!
! Add in object type
!
$NMU$TEXT (FILE_PTR,
3,
'%N%D',
.CB [CB_OBJECT]);
! Add optional task name
!
if .CB [CB_TASK_LENGTH] gtr 0
then $NMU$TEXT (FILE_PTR,
17,
'%N.%#A',
.CB [CB_TASK_LENGTH],
.CB [CB_TASK]);
!
! Add optional userid attribute
!
if .CB [CB_USERID_LENGTH] gtr 0
then $NMU$TEXT (FILE_PTR,
24,
'%N;USERID:%#A',
.CB [CB_USERID_LENGTH],
.CB [CB_USERID]);
!
! Add optional password attribute
!
if .CB [CB_PASSWORD_LENGTH] gtr 0
then $NMU$TEXT (FILE_PTR,
18,
'%N;PASSWORD:%#A',
.CB [CB_PASSWORD_LENGTH],
.CB [CB_PASSWORD]);
!
! Add optional account attribute
!
if .CB [CB_ACCOUNT_LENGTH] gtr 0
then $NMU$TEXT (FILE_PTR,
24,
'%N;CHARGE:%#A',
.CB [CB_ACCOUNT_LENGTH],
.CB [CB_ACCOUNT]);
!
! Add optional data attribute
!
if .CB [CB_DATA_LENGTH] gtr 0
then begin
if ch$size (.CB [CB_DATA]) eql 7
then $NMU$TEXT (FILE_PTR,
24,
'%N;DATA:%#A',
.CB [CB_DATA_LENGTH],
.CB [CB_DATA])
else $NMU$TEXT (FILE_PTR,
48,
'%N;BDATA:%#B',
-.CB [CB_DATA_LENGTH],
0,
.CB [CB_DATA]);
end;
end
else begin
!
! Create SRV:OBJECT or SRV:.USERNAMEOBJECT (if debugging)
!
if PRIVATE_SERVER_LINK
then $NMU$TEXT (FILE_PTR,
150,
'%NSRV:.%@%D',
USER_NAME,
.CB [CB_OBJECT])
else $NMU$TEXT (FILE_PTR,
150,
'%NSRV:%D',
.CB [CB_OBJECT]);
!
! Add optional task name (not possible if debugging)
!
if (.CB [CB_TASK_LENGTH] gtr 0) and (not PRIVATE_SERVER_LINK)
then $NMU$TEXT (FILE_PTR,
17,
'%N.%#A',
.CB [CB_TASK_LENGTH],
.CB [CB_TASK]);
end;
!
! Make into an ASCIZ string.
!
ch$wchar_a (0, FILE_PTR);
end %;
%fi
! Macro - OPEN_FOR_CONNECTION
!
! Function - This macro opens a logical link. If it is a source
! link, the connect is sent. If it is a target link
! it opens for possible connection.
!
! Parameters -
!
! LINK_INFO Address of link info block
!
! Return value -
!
! $true Link is setup for connection properly
! $false Link setup failed
macro
OPEN_FOR_CONNECTION (LINK_INFO) =
begin
DECLARE_JSYS (GTJFN, OPENF, MTOPR, RLJFN)
bind LI = LINK_INFO : LINK_INFO_BLOCK;
external DATTAB : vector [36], VECTAB : vector [36];
local JFN;
!
! Allocate an interrupt channel from free pool
!
LI[LINK_CHANNEL] = ALLOCATE_INTERRUPT_CHANNEL (NETWORK_EVENT, LI);
!
! Get JFN for link
!
if $$GTJFN (GJ_SHT, ch$ptr (LI [LINK_FILE]); JFN)
then begin
LI [LINK_JFN] = .JFN <0, 18>; ! Open link
if $$OPENF (.JFN <0, 18>, ((8 ^ 30) + OF_WR + OF_RD))
then begin
local CHN;
CHN = .LI [LINK_CHANNEL];
$$MTOPR (.JFN <0, 18>, $MOACN, ((.CHN ^ 27) or (.CHN ^ 9)));
ACTIVATE_INTERRUPT (.LI [LINK_CHANNEL]);
$true
end
else begin
$$RLJFN (.LI [LINK_JFN]);
$false
end
end
else $false
end %;
! Macro - ACCEPT_NETWORK_CONNECT
!
! Function - This macro accepts a connect on a target link. It
! specifies optional data that is sent in response
! to the connect. It blocks the calling task until
! the connection is confirmed or broken.
!
! Parameters -
!
! LINK_INFO Address of link info block
! DATA_LEN Length (in bytes) of optional data
! DATA_PTR Pointer to optional data
macro
ACCEPT_NETWORK_CONNECT (LINK_INFO, DATA_LEN, DATA_PTR) =
begin
DECLARE_JSYS (MTOPR,DISMS)
bind LI = LINK_INFO : LINK_INFO_BLOCK;
local WAITING;
$$MTOPR (.LI [LINK_JFN], $MOCC, DATA_PTR, DATA_LEN);
WAITING = $TRUE;
while .WAITING
do begin
READ_LINK_STATUS (LINK_INFO);
if (WAITING = not ((LINK_CONNECTED (LINK_INFO)) or
(LINK_DISCONNECTED (LINK_INFO))))
then $$DISMS (1); ! Wait a millisecond
end;
end %;
! Macro - REJECT_NETWORK_CONNECT
!
! Function - This macro rejects a connect on a target logical
! link. It passes the reject reason and any optional
! data back to the connecting task.
!
! Parameters -
!
! LINK_INFO Address of link info block
! REASON DECnet reject reason code
! DATA_LEN Number of bytes in optional data
! DATA_PTR Pointer to optional data
macro
REJECT_NETWORK_CONNECT (LINK_INFO, REASON, DATA_LEN, DATA_PTR) =
begin
DECLARE_JSYS (MTOPR)
bind LI = LINK_INFO : LINK_INFO_BLOCK;
local RSN;
RSN<18,18,0> = REASON;
RSN<0,18,0> = $MOCLZ;
$$MTOPR (.LI [LINK_JFN], .RSN, DATA_PTR, DATA_LEN);
end %;
! Macro - LINK_OPEN
!
! Function - This routine checks to see if a logical link is
! open for connection.
!
! Parameters -
!
! LINK_INFO Address of link info block
!
! Return values -
!
! $true Source link If link is connected
! Target link If link is waiting for connect confirm
! $false otherwise
macro
LINK_OPEN (LINK_INFO) =
begin
bind LI = LINK_INFO : LINK_INFO_BLOCK;
if .LI [LINK_TYPE] eql SOURCE_LINK
then (.LI [$sub_field (LINK_STATUS, LSB_CONNECTED)] neq 0)
else (.LI [$sub_field (LINK_STATUS, LSB_CCWAIT)] neq 0)
end %;
! Macro - LINK_CONNECT
!
! Function - This macro checks to see if a link is connected. If
! this macro returns true, the link is ready for data
! transfer.
!
! Parameters -
!
! LINK_INFO Address of link info block
!
! Return values -
!
! $true If link is connected
! $false If link is not connected
macro
LINK_CONNECTED (LINK_INFO) =
begin
bind LI = LINK_INFO : LINK_INFO_BLOCK;
.LI [$sub_field (LINK_STATUS, LSB_CONNECTED)] neq 0
end %;
! Macro - LINK_DISCONNECTED
!
! Function - This macro checks to see is a logical link is no longer
! in a state that allows data transfer.
!
! Parameters -
!
! LINK_INFO Address of link info block
!
! Return values -
!
! $true If the link has been disconnected
! $false If the link is not in a disconnected state
macro
LINK_DISCONNECTED (LINK_INFO) =
begin
bind LI = LINK_INFO : LINK_INFO_BLOCK;
(.LI [$sub_field (LINK_STATUS, LSB_PREV_CONNECT)] neq 0) or
(.LI [$sub_field (LINK_STATUS, LSB_CLOSED)] neq 0) or
(.LI [$sub_field (LINK_STATUS, LSB_ABORTED)] neq 0)
end %;
! Macro - CONNECT_WAIT
!
! Function - This macro checks a logical link to see if it is
! waiting for a connect to complete.
!
! Parameters -
!
! LINK_INFO Address of link info block
!
! Return values -
!
! $true Source link Waiting for a connect confirm
! Target link Waiting for incoming connect initiate
! $false otherwise
macro
CONNECT_WAIT (LINK_INFO) =
begin
bind LI = LINK_INFO : LINK_INFO_BLOCK;
((if .LI [LINK_TYPE] eql SOURCE_LINK
then (.LI [$sub_field (LINK_STATUS, LSB_CCWAIT)] neq 0)
else (.LI [$sub_field (LINK_STATUS, LSB_CIWAIT)] neq 0)) and
(.LI [$sub_field (LINK_STATUS, LSB_ABORTED)] eql 0) and
(.LI [$sub_field (LINK_STATUS, LSB_CLOSED)] eql 0))
end %;
! Macro - LINK_EOM
!
! Function - This macro tests to see if the MO_EOM bit is lit. This can be
! used to detect if someone sends a null record...
!
! Parameters -
!
! LINK_INFO - address of the link info block
!
! Value -
! $true if MO_EOM is set
! $false otherwise
MACRO link_eom(link_info) =
BEGIN
BIND li = link_info : link_info_block;
.LI [$sub_field (LINK_STATUS, LSB_EOM)]
END %;
! Macro - READ_MESSAGE
!
! Function - This macro reads a message from a logical link. It
! blocks until the total message is read.
!
! Parameters -
!
! LINK_INFO Address of link info block
! BUFFER_LEN Length of receive buffer in bytes
! BUFFER_PTR Pointer to receive buffer
!
! Return values -
!
! Number of characters read
! 0 indicates a null record was sent (a record with NO characters)
! -1 indicates time out occurred
! -2 indicates link failed
macro
READ_MESSAGE (LINK_INFO, BUFFER_LEN, BUFFER_PTR) =
begin
DECLARE_JSYS (SIBE, SINR, SIN)
bind LI = LINK_INFO : LINK_INFO_BLOCK;
local CHAR_READ, READ_WAIT, CHAR_AVAIL;
CHAR_READ = -2;
READ_WAIT = $true;
while .READ_WAIT
do begin
READ_LINK_STATUS (LINK_INFO);
if LINK_CONNECTED (LINK_INFO)
then begin
if LINK_EOM (LINK_INFO)
then !It is safe to do a SINR...
begin
if $$SINR (.LI [LINK_JFN],
BUFFER_PTR,
-(BUFFER_LEN); ,,CHAR_READ)
then CHAR_READ = BUFFER_LEN + .CHAR_READ
else begin
$trace_always('SINR failed');
CHAR_READ = -2;
end;
read_wait = $false;
end
else
if $$SIBE (.LI [LINK_JFN]; CHAR_AVAIL)
then !No data - wait
(if not NMU$SCHED_WAIT (LI [LINK_EVENT], 2 * .ntimo)
then begin
$trace_always('Timeout occured');
READ_WAIT = $false;
CHAR_READ = -1; ! Indicate timeout
end)
else begin !EOM bit not set - work around it
CHAR_READ = CHAR_AVAIL = min(.CHAR_AVAIL,BUFFER_LEN);
if $$SIN (.LI [LINK_JFN], BUFFER_PTR, -(.CHAR_AVAIL))
then $trace_always('Missing EOM after %D characters',
.CHAR_AVAIL)
else begin
$trace_always('SIN failed');
CHAR_READ = -2;
end;
READ_WAIT = $false;
end
end
else begin
$trace_always('Link not connected');
READ_WAIT = $false;
end
end;
.CHAR_READ
end %;
! Macro - WRITE_MESSAGE
!
! Function - This macro writes a message on a logical link
!
! Parameters -
!
! LINK_INFO Address of link info block
! BUFFER_LEN Number of bytes to write
! BUFFER_PTR Pointer to message to write
!
! Return values -
!
! $true Successful write
! $false Failure during write
macro
WRITE_MESSAGE (LINK_INFO, BUFFER_LEN, BUFFER_PTR) =
begin
DECLARE_JSYS (SOUTR)
bind LI = LINK_INFO : LINK_INFO_BLOCK;
local WRITE_WAIT, RESULT;
WRITE_WAIT = $true;
while .WRITE_WAIT
do begin
READ_LINK_STATUS (LINK_INFO);
if LINK_CONNECTED (LINK_INFO)
then begin
RESULT = $$SOUTR (.LI [LINK_JFN], BUFFER_PTR, -(BUFFER_LEN));
nmu$sched_pause();
WRITE_WAIT = $false;
end
else WRITE_WAIT = $false;
end;
.RESULT
end %;
! Macro - WRITE_STRING
!
! Function - This macro writes a string to a logical link. It
! does not terminate the write with an End-of-Message
! indicator.
!
! Parameters -
!
! LINK_INFO Address of link info block
! BUFFER_LEN Number of bytes to write
! BUFFER_PTR Pointer to string to write
!
! Return values -
!
! $true Successful write
! $false Failure during write
macro
WRITE_STRING (LINK_INFO, BUFFER_LEN, BUFFER_PTR) =
begin
DECLARE_JSYS ( SOUT)
bind LI = LINK_INFO : LINK_INFO_BLOCK;
local WRITE_WAIT, RESULT;
WRITE_WAIT = $true;
while .WRITE_WAIT
do begin
READ_LINK_STATUS (LINK_INFO);
if LINK_CONNECTED (LINK_INFO)
then begin
RESULT = $$SOUT (.LI [LINK_JFN], BUFFER_PTR, -(BUFFER_LEN));
nmu$sched_pause();
WRITE_WAIT = $false;
end
else WRITE_WAIT = $false;
end;
.RESULT
end %;
! Macro - ABORT_LINK
!
! Function - This macro aborts a logical link connection. It
! sends the reason for abort and optional data back
! to the task at the other end of the link.
!
! Parameters -
!
! LINK_INFO Address of link info block
! REASON DECnet disconnect reason code
! DATA_LEN Number of bytes in optional data
! DATA_PTR Pointer to optional data
macro
ABORT_LINK (LINK_INFO, REASON, DATA_LEN, DATA_PTR) =
begin
DECLARE_JSYS (MTOPR, CLOSF)
bind LI = LINK_INFO : LINK_INFO_BLOCK;
local RSN;
RSN<18,18,0> = REASON;
RSN<0,18,0> = $MOCLZ;
$$MTOPR (.LI [LINK_JFN], .RSN, DATA_PTR, DATA_LEN);
$$CLOSF ((.LI [LINK_JFN] or CZ_ABT));
DEACTIVATE_INTERRUPT (.LI [LINK_CHANNEL]);
RELEASE_INTERRUPT_CHANNEL (.LI [LINK_CHANNEL]);
end %;
! Macro - CLOSE_LINK
!
! Function - This macro closes a logical link. After this macro
! the link info block can no longer be used for
! manipulations of the logical link.
!
! Parameters -
!
! LINK_INFO Address of link info block
! DATA_LEN Number of bytes in optional closure data
! DATA_PTR Pointer to optional closure data
macro
CLOSE_LINK (LINK_INFO, DATA_LEN, DATA_PTR) =
begin
DECLARE_JSYS (MTOPR, CLOSF)
bind LI = LINK_INFO : LINK_INFO_BLOCK;
$$MTOPR (.LI [LINK_JFN], $MOCLZ, DATA_PTR, DATA_LEN);
if not $$CLOSF (.LI [LINK_JFN])
then $$CLOSF ((.LI [LINK_JFN] or CZ_ABT));
DEACTIVATE_INTERRUPT (.LI [LINK_CHANNEL]);
RELEASE_INTERRUPT_CHANNEL (.LI [LINK_CHANNEL]);
end %;
! Macro - READ_LINK_STATUS
!
! Function - This macro reads the logical link status and
! stores it in the link info block. Use the
! link testing macros to check the link status.
!
! Parameters -
!
! LINK_INFO Address of link info block
macro
READ_LINK_STATUS (LINK_INFO) =
begin
DECLARE_JSYS (MTOPR)
bind LI = LINK_INFO : LINK_INFO_BLOCK;
local STATUS;
if not $$MTOPR (.LI [LINK_JFN], $MORLS; STATUS)
then STATUS = 0;
LI[$sub_field (LINK_STATUS, LSB_FLAGS)] = .STATUS <27,9,0>;
LI [$sub_field (LINK_STATUS, LSB_REASON)] = .STATUS <0,8,0>;
end %;
! Macro - READ_USER_NAME
!
! Function - This macro reads the remote user's name that is connected
! to a logical link. The CB_USERID field in the connect
! is filled in to point to the CB_USERID_BUFFER. The
! length field CB_USERID_LENGTH is also set.
!
! Parameters -
!
! CONN_BLOCK Address of connect data block
! INFO_BLOCK Address of info block
macro
READ_USER_NAME (CONN_BLOCK, INFO_BLOCK) =
begin
DECLARE_JSYS (MTOPR)
local END_PTR;
bind CB = CONN_BLOCK : CONNECT_BLOCK,
LI = INFO_BLOCK : LINK_INFO_BLOCK;
CB [CB_USERID] = ch$ptr ((CB [CB_USERID_BUFFER]),, 8);
$$MTOPR (.LI [LINK_JFN], $MORUS, .CB [CB_USERID]; END_PTR);
CB [CB_USERID_LENGTH] = ch$diff (.END_PTR, .CB [CB_USERID]);
end %;
! Macro - READ_ACCOUNT_STRING
!
! Function - This macro reads the remote task's account string.
! CB_ACCOUNT field in the connect is filled in to point
! to the CB_ACCOUNT_BUFFER. The length field
! CB_ACCOUNT_LENGTH is also set.
!
! Parameters -
!
! CONN_BLOCK Address of connect data block
! INFO_BLOCK Address of info block
macro
READ_ACCOUNT_STRING (CONN_BLOCK, INFO_BLOCK) =
begin
DECLARE_JSYS (MTOPR)
local END_PTR;
bind CB = CONN_BLOCK : CONNECT_BLOCK,
LI = INFO_BLOCK : LINK_INFO_BLOCK;
CB [CB_ACCOUNT] = ch$ptr (CB [CB_ACCOUNT_BUFFER],, 8);
$$MTOPR (.LI [LINK_JFN], $MORAC, .CB [CB_ACCOUNT]; END_PTR);
CB [CB_ACCOUNT_LENGTH] = ch$diff (.END_PTR, .CB [CB_ACCOUNT]);
end %;
! Macro - READ_PASSWORD_STRING
!
! Function - This macro reads the remote task's password string.
! CB_PASSWORD field in the connect is filled in to point
! to the CB_PASSWORD_BUFFER. The length field
! CB_PASWWORD_LENGTH is also set.
!
! Parameters -
!
! CONN_BLOCK Address of connect data block
! INFO_BLOCK Address of info block
macro
READ_PASSWORD_STRING (CONN_BLOCK, INFO_BLOCK) =
begin
DECLARE_JSYS (MTOPR)
bind CB = CONN_BLOCK : CONNECT_BLOCK,
LI = INFO_BLOCK : LINK_INFO_BLOCK;
CB [CB_PASSWORD] = ch$ptr (CB [CB_PASSWORD_BUFFER],, 8);
$$MTOPR (.LI [LINK_JFN], $MORPW, .CB [CB_PASSWORD]; ,CB [CB_PASSWORD_LENGTH]);
end %;
! Macro - READ_OPTIONAL_DATA
!
! Function - This macro reads the remote task's optional data string.
! CB_DATA field in the connect is filled in to point
! to the CB_DATA_BUFFER. The length field
! CB_DATA_LENGTH is also set.
!
! Parameters -
!
! CONN_BLOCK Address of connect data block
! INFO_BLOCK Address of info block
macro
READ_OPTIONAL_DATA (CONN_BLOCK, INFO_BLOCK) =
begin
DECLARE_JSYS (MTOPR)
bind CB = CONN_BLOCK : CONNECT_BLOCK,
LI = INFO_BLOCK : LINK_INFO_BLOCK;
CB [CB_DATA] = ch$ptr (CB [CB_DATA_BUFFER],, 8);
$$MTOPR (.LI [LINK_JFN], $MORDA, .CB [CB_DATA]; ,CB [CB_DATA_LENGTH]);
end %;
! Macro - READ_OBJECT_TYPE
!
! Function - This macro reads the object type used in completion
! of the logical link connection. The CB_OBJECT field
! in the connect is filled in with the objec type code.
!
! Parameters -
!
! CONN_BLOCK Address of connect data block
! INFO_BLOCK Address of info block
macro
READ_OBJECT_TYPE (CONN_BLOCK, INFO_BLOCK) =
begin
DECLARE_JSYS (MTOPR)
bind CB = CONN_BLOCK : CONNECT_BLOCK,
LI = INFO_BLOCK : LINK_INFO_BLOCK;
$$MTOPR (.LI [LINK_JFN], $MORCN; CB [CB_OBJECT]);
end %;
! Macro - READ_HOST_ID
!
! Function - This macro reads the remote task's host id.
! CB_HOST field in the connect is filled in to point
! to the CB_HOST_BUFFER. The length field
! CB_HOST_LENGTH is also set. The format of the id
! is 2 bytes of node number followed by a counted
! ASCII field (maximum of 6 bytes).
!
! Parameters -
!
! CONN_BLOCK Address of connect data block
! INFO_BLOCK Address of info block
macro
READ_HOST_ID (CONN_BLOCK, INFO_BLOCK) =
begin
DECLARE_JSYS (MTOPR)
local PTR, END_PTR, ERR_;
bind CB = CONN_BLOCK : CONNECT_BLOCK,
LI = INFO_BLOCK : LINK_INFO_BLOCK;
PTR = (CB [CB_HOST] = ch$ptr (CB [CB_HOST_BUFFER],, 8));
ch$wchar_a (0, PTR);
ch$wchar_a (0, PTR);
IF $$MTOPR (.LI [LINK_JFN], $MORHN, ch$plus (.PTR, 1); END_PTR)
THEN
ch$wchar_a ((ch$diff (.END_PTR, .PTR) - 1), PTR)
ELSE
IF .(.PTR<0,18,0>)<18,18,0> EQL 0
THEN
BEGIN
err_ = .ptr;
ptr = CH$PLUS(.ptr,1);
ch$wchar($NMU$TEXT(ptr,max_string_length,'%D.%D',
.(.end_ptr)<10,6,0>,
.(.end_ptr)<0,10,0>) - 1,
.err_);
END;
end %;
! Macro - READ_DESCRIPTOR
!
! Function - This macro reads the remote task's link descriptor.
! CB_DESCRIPTOR field in the connect is filled in to point
! to the CB_DESCRIPTOR_BUFFER. The length field
! CB_DESCRIPTOR_LENGTH is also set.
!
! Parameters -
!
! CONN_BLOCK Address of connect data block
! INFO_BLOCK Address of info block
macro
READ_DESCRIPTOR (CONN_BLOCK, INFO_BLOCK) =
begin
DECLARE_JSYS (MTOPR)
local END_PTR;
bind CB = CONN_BLOCK : CONNECT_BLOCK,
LI = INFO_BLOCK : LINK_INFO_BLOCK;
CB [CB_DESCRIPTOR] = ch$ptr (CB [CB_DESCRIPTOR_BUFFER],, 8);
$$MTOPR (.LI [LINK_JFN], $MORHN, .CB [CB_DESCRIPTOR]; END_PTR);
CB [CB_DESCRIPTOR_LENGTH] = ch$diff (.END_PTR, .CB [CB_DESCRIPTOR]);
end %;
! Macro - READ_REJECT_CODE
!
! Function - This macro reads the remote task's connect reject reason code.
! CB_REJECT_CODE field in the connect is filled in. The
! READ_LINK_STATUS call must have been made first.
!
! Parameters -
!
! CONN_BLOCK Address of connect data block
! INFO_BLOCK Address of info block
macro
READ_REJECT_CODE (CONN_BLOCK, INFO_BLOCK) =
begin
bind CB = CONN_BLOCK : CONNECT_BLOCK,
LI = INFO_BLOCK : LINK_INFO_BLOCK;
CB [CB_REJECT_CODE] = .LI [$sub_field (LINK_STATUS, LSB_REASON)];
end %;
! Macro - NETWORK_INTERRUPT_CLEAR
!
! Function - This macro clears any "interrupt waiting" flag in the operating
! system for a logical link. This is used to tighten code
! and suppress races.
!
! Parameters -
!
! LINK_INFO Address of link info block
macro
NETWORK_INTERRUPT_CLEAR (LINK_INFO) =
begin
bind LI = LINK_INFO : LINK_INFO_BLOCK;
DECLARE_JSYS (SIBE)
$$SIBE (.LI [LINK_JFN]);
end %;
%title ''
%sbttl ''
!
! [End of NMUT20]
! Local Modes:
! Mode:BLISS
! Auto Save Mode:0
! Comment Column:40
! Comment Rounding:+1
! End: