Trailing-Edge
-
PDP-10 Archives
-
BB-P363B-SM_1985
-
t20/nmlt20/nmldtl.bli
There are 2 other files named nmldtl.bli in the archive. Click here to see a list.
! UPD ID= 339, SNARK:<6.1.NML>NMLDTL.BLI.49, 15-Aug-85 12:41:10 by MCCOLLUM
! Rewrite some of the LOAD_NODE and it subroutines to handle MOP
! requests properly. This makes it possible to do downline loading
! under high load averages.
!
! UPD ID= 335, SNARK:<6.1.NML>NMLDTL.BLI.48, 10-Jul-85 13:57:47 by MCCOLLUM
! 1. Don't TRIGGER after unsucessful LOAD for now. We have a race when 2
! KL's try to load and keep TRIGGERing.
! 2. Generate 0.3 events in LOAD_NODE so we get six events for each
! complete load operation. Each request program now generates a 0.3
! REQUEST and either a 0.3 success or 0.7 failure event.
! 3. Wait a while after each file is loaded in LOAD_NODE for the response.
! We weren't waiting long enough and were getting 0.7 events when we
! shouldn't have.
! 4. Assume success in LOAD_NODE instead of failure and make sure all
! errorr returns set up an response code for the specific error. This
! will prevent us from getting ambiguous "Operation Failures".
!
! UPD ID= 325, SNARK:<6.1.NML>NMLDTL.BLI.26, 10-May-85 15:35:57 by GLINDELL
! 1. Delay sending 'ASSISTANCE VOLOUNTEER' until NMLDTL has opened the
! load file at least. This should greatly reduce the risk of NMLDTL
! volounteering to load without having all the proper parameters.
!
! UPD ID= 291, SNARK:<6.1.NML>NMLDTL.BLI.25, 15-Mar-85 13:14:06 by GLINDELL
! 1. TRIGGER after unsuccessful LOAD even if AUTOSERVICE.
! 2. Assume failure instead of success in LOAD_NODE. This will cover us
! when LOAD_NODE returns failure without setting up a response code.
!
! UPD ID= 285, SNARK:<6.1.NML>NMLDTL.BLI.24, 13-Mar-85 14:19:58 by GLINDELL
! Work on loading of MAINTENANCE images. Support a -2 as software ID.
! Add flag LB_LOAD_MAINT_IMAGE flag to service block.
!
! UPD ID= 283, SNARK:<6.1.NML>NMLDTL.BLI.23, 12-Mar-85 13:56:06 by GLINDELL
! TRIGGER code left the circuit state in TRIGGERING if a SERVICE password
! wasn't present. Need to reset RTN_COD in EXECUTE_TRIGGER before 2nd try.
!
! UPD ID= 281, SNARK:<6.1.NML>NMLDTL.BLI.22, 10-Mar-85 14:26:40 by GLINDELL
! 1. Remove edit history prior to phase IV
! 2. Rearrange order of routines.
!
! UPD ID= 278, SNARK:<6.1.NML>NMLDTL.BLI.21, 6-Mar-85 23:11:13 by GLINDELL
! NML$DLW_READ_LDAQ now has the additional argument of the hardware address
! we are interested in.
!
! UPD ID= 267, SNARK:<6.1.NML>NMLDTL.BLI.20, 1-Mar-85 10:02:37 by GLINDELL
! Lots of work to support POSEIDON's, dumping on the NI and clean up of DTE.
!
! UPD ID= 259, SNARK:<6.1.NML>NMLDTL.BLI.19, 10-Feb-85 14:49:35 by GLINDELL
! Remove definitions of STATE/SUBSTATE/SERVICE values
! Change all LINK_ to CIRCUIT_
!
! UPD ID= 248, SNARK:<6.1.NML>NMLDTL.BLI.18, 25-Jan-85 14:01:09 by HALPIN
! Add support of downline loading of DECSA's Remote Console Microcode.
!
! UPD ID= 220, SNARK:<6.1.NML>NMLDTL.BLI.17, 17-Dec-84 10:32:31 by HALPIN
! Make sure NML$LOAD prints an error message before calling EXECUTE_TRIGGER.
! Dumps via the NI only use the HARDWARE ADDRESS.
! Get MONSYM Library file out of default directory, not BLI:
! Add PHYSICAL ADDRESS (10) and HARDWARE ADDRESS (114) to the list of
! Acceptable Parameters in NML$DUMP.
!
! UPD ID= 183, SNARK:<6.1.NML>NMLDTL.BLI.16, 7-Dec-84 09:09:35 by HALPIN
! Change IMAGE_LOAD on Tertiary Loaders, the last message is a "MEMORY LOAD
! WITH TRANSFER ADDRESS" with a 'null' memory load address. System Images
! still send "PARAMETER LOAD WITH TRANSFER ADDRESS" as last message.
! Don't call $NMU_DLX_CLOSE after LOAD and DUMP requests. NI Data
! Link Watcher keeps the NI Open all the time watching for Load
! and Dump requests.
! Add SB_EXECUTE_TRIGGER bit flag to the service block.
! LOAD/DUMPS via the NI now call NML$DLW_READ_LDAQ, instead of
! $NMU_DLX_READ. The NI Data Link Watcher Task reads all messages
! from the LOAD/DUMP Portal and queues up any messages meant for current
! Load/Dump Requests.
! Make different MOP_LOAD_DATA_LENGTH symbols for DTE and NI's.
! Add PSI channel numbers in call to $NMU_DLX_OPEN
!
! UPD ID= 170, SNARK:<6.1.NML>NMLDTL.BLI.15, 19-Nov-84 09:12:26 by HALPIN
! Fix comparison for Secondary Loader too large.
! Modify edit 157. After calling EXECUTE_TRIGGER exit the Load routines
! and rely on the Data Link Watcher process to start a new load request.
!
! UPD ID= 161, SNARK:<6.1.NML>NMLDTL.BLI.14, 9-Nov-84 12:50:46 by HALPIN
! NML$LOAD node uses HARDWARE ADDRESS instead of PHYSICAL ADDRESS parameter.
!
! UPD ID= 157, SNARK:<6.1.NML>NMLDTL.BLI.13, 5-Nov-84 12:53:39 by HALPIN
! Have LOAD_NODE routine try to TRIGGER the target node if the first
! attempt at doing a Secondary Load fails.
!
! UPD ID= 156, SNARK:<6.1.NML>NMLDTL.BLI.12, 2-Nov-84 16:43:17 by HALPIN
! Move code from NML$TRIGGER to new routine EXECUTE_TRIGGER.
!
! UPD ID= 155, SNARK:<6.1.NML>NMLDTL.BLI.11, 2-Nov-84 14:14:25 by HALPIN
! Add SB_SRVC_CKT_DEVICE, Service circuit device type field to the
! Service Block. Call $NMU_DLX_DEVICE_TYPE to get the circuit device
! type code.
! Add DEVTYP_NI definition.
! Increase MOP_BUFFER_LENGTH to 1498. Keep DTE's from using more than
! 522 bytes of it.
! Call NMU$CALCULATE_CIRCUIT_STATE in CIRCUIT_OPEN before getting the
! State and Substate from VDB.
! Add HARDWARE ADDRESS to list of acceptable parameters in Load routine.
!
! UPD ID= 154, SNARK:<6.1.NML>NMLDTL.BLI.10, 1-Nov-84 17:55:50 by GUNN
! Fix DTL_SETUP to handle PHYSICAL and HARDWARE ADDRESS parameters.
! Fix TRIGGER_NODE to get SERVICE PASSWORD from VDB. It didn't work.
!
! UPD ID= 151, SNARK:<6.1.NML>NMLDTL.BLI.9, 31-Oct-84 10:20:25 by GUNN
! Change length of MOP message passed in call to NMU$DLX_WRITE from
! TRIGGER_NODE from 5 to 12 bytes. This is the MOP V3.0 BOOT message
! length.
! Remove setting of response code in response message in TRIGGER_NODE
! on failure of NMU$DLX_WRITE. The response message should be set up
! prior to the failure return.
!
! UPD ID= 148, SNARK:<6.1.NML>NMLDTL.BLI.8, 30-Oct-84 17:38:30 by GUNN
! Add DLX_TRIGGER case to CIRCUIT_OPEN.
! Add code in TRIGGER_NODE to produce MOP V3.0 BOOT message.
!
! UPD ID= 144, SNARK:<6.1.NML>NMLDTL.BLI.7, 29-Oct-84 13:46:19 by GUNN
! Change NML$TRIGGER to set SB_USAGE to DLX_TRIGGER rather than DLX_OTHER.
!
! UPD ID= 135, SNARK:<6.1.NML>NMLDTL.BLI.6, 24-Oct-84 16:13:30 by GUNN
! Add code to do trigger boot for Ethernet nodes.
! Add SB_PHY_ADDR field to service data block structure and pass
! on call to $NMU_DLX_OPEN. Remove $MCB conditionals.
! Add SB_PHY_ADDR as case in FETCH_PARAMETERS
!
! UPD ID= 122, SNARK:<6.1.NML>NMLDTL.BLI.5, 5-Oct-84 14:32:05 by HALPIN
! Allow a circuit to be opened if the Substate is STARTING.
!
! UPD ID= 85, SLICE:<6.1.NML>NMLDTL.BLI.4, 18-Sep-84 14:59:18 by GUNN
! WORK:<GUNN.NML>NMLDTL.BLI.3 24-Aug-84 16:56:54, Edit by GUNN
!
! Change call to $NMU_DLX_OPEN to accomodate new PHYSICAL ADDRESS
! parameter needed for Ethernet.
!
! WORK:<GUNN.NML>NMLDTL.BLI.2 21-Aug-84 12:04:25, Edit by GUNN
!
! Change to accomodate new LIBRARY conventions. MONSYM.L36 and JLNKG.L36
! are now explicity declared here rather than in NMULIB.
!
! UPD ID= 36, SNARK:<6.1.NML>NMLDTL.BLI.3, 24-May-84 16:27:49 by GLINDELL
! Fix dot bug in IMAGE_LOAD with regard to SERVICE NODE VERSION
!
! PH4:<HALPIN>NMLDTL.BLI.5 30-Nov-83 11:26:25, Edit by HALPIN
! Ident 53.
! IMAGE_LOAD the the value of SERVICE NODE VERSION while building
! the TARGET SYSTEM and HOST SYSTEM ADDRESSes in the PARAMETER LOAD
! WITH TRANSFER ADDRESS message
!
! Ident 52.
! New style entity id type names. Change in $NMU_DLX_OPEN invocation.
!
module NMLDTL (
ident = 'X03.53'
) =
begin
!
! COPYRIGHT (c) 1980, 1981, 1984, 1985 BY
! DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
!
! 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: DECnet-10/20 V3.0 Network Management Layer (NML)
!
! ABSTRACT:
!
! Performs remote node dump, trigger boot, and load.
!
! ENVIRONMENT: TOPS-10/20 & MCB/RSX11 User mode under NML
!
! AUTHOR: Dale C. Gunn & Steven Jenness , CREATION DATE: 12-Nov-80
!
! MODIFIED BY:
!
! , : VERSION
! 01 -
!--
!
! INCLUDE FILES:
!
library 'NMLLIB'; ! All required definitions
library 'MONSYM'; ! Monitor symbols
library 'JLNKG'; ! JSYS linkage definitions
require 'NMLEXT'; ! External routine declarations
!
! TABLE OF CONTENTS
!
%if %bliss (bliss16)
%then linkage NML_LKG_DB = jsr (register = 5);
%else macro NML_LKG_DB = bliss36c %;
%fi
forward routine
NML$DUMP,
NML$LOAD,
NML$TRIGGER,
DTL_SETUP,
DTL_CLEANUP,
CIRCUIT_CLOSE : NML_LKG_DB,
CIRCUIT_OPEN : NML_LKG_DB,
CIRCUIT_PROMPT : NML_LKG_DB,
CPU_IS_PDP11 : NML_LKG_DB,
DUMP_NODE : NML_LKG_DB,
FETCH_PARAMETERS,
FILE_CLOSE : NML_LKG_DB,
FILE_OPEN : NML_LKG_DB,
FILE_READ_LABEL : NML_LKG_DB,
GET_NEXT_PARAMETER,
IMAGE_LOAD : NML_LKG_DB,
WRITE_ASSISTANCE_VOLUNTEER : NML_LKG_DB,
WRITE_MOP_MESSAGE : NML_LKG_DB,
CONSOLE_IMAGE_LOAD : NML_LKG_DB,
LOAD_NODE : NML_LKG_DB novalue,
SECONDARY_LOAD : NML_LKG_DB,
SET_SUBSTATE : NML_LKG_DB novalue,
EXECUTE_TRIGGER : NML_LKG_DB novalue,
TRIGGER_NODE : NML_LKG_DB,
GET_VDB;
!
! LOAD, DUMP & TRIGGER data block structure definitions
!
$show (fields) $show (literals)
$field
SERVICE_DATA_FIELDS =
set
! Common data for LOAD, DUMP and TRIGGER
SB_CIRCUIT_HANDLE = [$integer], ! Link handle for circuit
SB_RESPONSE_PTR = [$pointer], ! Pointer to response buffer
SB_BUFFER = [$address], ! Address of MOP buffer
SB_BUFFER_PTR = [$pointer], ! Pointer to MOP buffer
SB_NODE_DATA = [$pointer], ! Pointer to node entity ID
SB_PHY_ADDR = [$pointer], ! Node parameter 10
SB_ETHER_ADDR_BUFFER = [$bytes (6)], ! Buffer for Ethernet Address string
SB_SERVICE_CIRCUIT = [$pointer], ! 110 Pointer to service circuit-id
SB_SERVICE_PASSWORD = [$pointer], ! 111 Pointer to hexadecimal passwd
LB_LOAD_FILE = [$pointer], ! 120 Pointer to system image
LB_SECONDARY_LOADER = [$pointer], ! 121 Pointer to secondary loader
LB_TERTIARY_LOADER = [$pointer], ! 122 Pointer to tertiary loader
LB_DIAGNOSTIC_FILE = [$pointer], ! 123 Pointer to diagnostic file
LB_CONSOLE_SECONDARY_LOADER = [$pointer], ! 2501 Pointer to console secondary loader
LB_CONSOLE_LOAD_FILE = [$pointer], ! 2502 Pointer to Console Carrier Microcode
LB_SOFTWARE_IDENTIFICATION = [$pointer], ! 126 Pointer to id string
DB_DUMP_FILE = [$pointer], ! 130 Pointer to dump image file
DB_SECONDARY_DUMPER = [$pointer], ! 131 Pointer to secondary dumper
LB_NAME = [$pointer], ! 500 Pointer to node name block
LB_ADDRESS = [$pointer], ! 502 Pointer to node address block
DB_DUMP_ADDRESS = [$bytes(4)], ! 135 4 byte dump address
DB_DUMP_COUNT = [$bytes(4)], ! 136 4 byte dump count
SB_HARDWARE_ADDRESS = [$pointer], ! 114 Pointer to ETHERNET Hardware
! Address
LB_HOST = [$bytes (NODE_ID_BUFFER_LENGTH)],
! 140 HOST node id block
LB_SERVICE_DEVICE = [$tiny_integer], ! 112 Device type
LB_CPU = [$tiny_integer], ! 113 CPU type
LB_SOFTWARE_TYPE = [$tiny_integer], ! 125 Software type
LB_PROCESSOR = [$byte], ! Processor to be loaded
LB_DL_BUFFER_SIZE = [$integer], ! Data Link Buffer Size
LB_LOAD_MAINT_IMAGE = [$bit], ! Use MAINT image if this bit set
SB_USAGE = [$tiny_integer], ! Function being performed
SB_SUBSTATE = [$tiny_integer], ! Current substate
SB_NODE_VERSION = [$tiny_integer], ! Service Node Version
SB_SRVC_CKT_DEVICE = [$tiny_integer],! Service Circuit Device Type
SB_EXECUTE_TRIGGER = [$bit], ! Secondary Load failed, call EXECUTE_TRIGGER
SB_AUTOSERVICE = [$bit], ! True if auto-service
SB_NEED_RPM = [$bit] ! Set if we need a RPM before going
tes;
literal
SERVICE_DATA_BLOCK_SIZE = $field_set_size,
SERVICE_DATA_BLOCK_ALLOCATION = $field_set_units ;
macro
SERVICE_DATA_BLOCK = block [SERVICE_DATA_BLOCK_SIZE]
field (SERVICE_DATA_FIELDS) %;
! End of service structure definition
!%( *** TEMPORARY - until NMLLIB is modified !***
macro RB_DTL_DATA = RB_LOAD_DATA%; !***
macro RB_DTL_DATA_ALLOCATION = RB_LOAD_DATA_ALLOCATION%; !***
!
! File handling structure definition
!
$field
FILE_DATA_FIELDS =
set
FB_FILE_HANDLE = [$integer],
FB_RESPONSE_PTR = [$pointer],
FB_FILE = [$pointer],
FB_CURRENT_ADDRESS = [$bytes (4)],
FB_BYTES_LEFT = [$bytes (4)],
FB_TRANSFER_ADDRESS = [$bytes (4)],
FB_FILE_TYPE = [$byte]
tes;
literal
FILE_DATA_BLOCK_SIZE = $field_set_size,
FILE_DATA_BLOCK_ALLOCATION = $field_set_units ;
macro
FILE_DATA_BLOCK = block [FILE_DATA_BLOCK_SIZE]
field (FILE_DATA_FIELDS) %;
! End of file structure definition
$show (none)
!
! Macros:
!
macro
CH$HEX [ ] =
ch$ptr (uplit (X_CHAR(%explode(%remaining))),,8) %;
macro
X_CHAR [B1,B2,B3,B4,B5,B6,B7,B8] =
((%X B1 ^ (%bpval-4))
%if not %null(B2)
%then
or (%X B2 ^ (%bpval-8))
%if not %null(B3)
%then
or (%X B3 ^ (%bpval-12))
%if not %null(B4)
%then
or (%X B4 ^ (%bpval-16))
%if not %null(B5)
%then
or (%X B5 ^ (%bpval-20))
%if not %null(B6)
%then
or (%X B6 ^ (%bpval-24))
%if not %null(B7)
%then
or (%X B7 ^ (%bpval-28))
%if not %null(B8)
%then
or (%X B8 ^ (%bpval-32))
%fi %fi %fi %fi %fi %fi %fi) %;
! CH$ASCIC (STRING, ...)
!
! Return a pointer to an ASCIC character position sequence
! formed by the characters represented by the string-params,
! which are interpreted as for the %string lexical function.
macro
DLW$ASCIC [ ] =
ch$ptr (uplit (%string (%char (%charcount (%remaining)), %remaining))) %;
!
! Equated symbols:
!
literal
DEVTYP_NI = 15, ! NI Device Type code
DEVTYP_DTE = 20, ! DTE Device type code
RESPONSE_BUFFER_LENGTH = 256, ! NICE response buffer in bytes
RESPONSE_BUFFER_SIZE = ch$allocation (RESPONSE_BUFFER_LENGTH,8),
RESPONSE_BUFFER_ALLOCATION = RESPONSE_BUFFER_SIZE * %upval,
MOP_BUFFER_LENGTH = 1506, ! MOP message buffer in bytes
MOP_BUFFER_SIZE = ch$allocation (MOP_BUFFER_LENGTH, 8),
MOP_BUFFER_ALLOCATION = MOP_BUFFER_SIZE * %upval,
DTE_MOP_LOAD_DATA_LENGTH = (254 - 6),! Max bytes in image in load message
NI_MOP_LOAD_DATA_LENGTH = (512 - 6),! Max bytes in image in load message
MOP_RESPONSE_LENGTH = 32; ! Max bytes in ACK to load
!
! RSX .SYS file label definitions
!
literal
L$BSA = %o'10', ! Base address of image
L$BLDZ = %o'16', ! Load size of image
L$BFLG = %o'30', ! Header flags word
L$BXFR = %o'350', ! Transfer address
! L$BHRB = %o'356', ! Starting block of image (0 relative)
L$BBLK = %o'360'; ! Number of label blocks
!
! STATE/SUBSTATE/SERVICE definitions
!
literal
CPARM_STATE = 0,
CPARM_SUBSTATE = 1,
CPARM_SERVICE = 100;
literal
SYSTEM_PROCESSOR = 0,
COMMUNICATION_PROCESSOR = 1;
!
! External references:
!
external routine
NML$FIND_NDB, ! Find node entity for circuit
NML$PARAMETER_DATA, ! Get NICE parameter data
NML$CLR_VDB_PARAMETER, ! Clear parameter in VDB
NML$GET_VDB_PARAMETER, ! Obtain parameter data from VDB
NML$SET_VDB_PARAMETER, ! Set parameter in VDB
NML$DLW_READ_LDAQ, ! Read the Load/Dump Assistance Queue
NML$CALCULATE_CIRCUIT_STATE : novalue,
NML$DLW_SERVICE_EVENT : novalue, ! Queue a service event
NMU$NETWORK_LOCAL, ! Get local node number/name
NMU$FILE_ROUTINES; ! File access routines
%global_routine ('NML$LOAD', REQ : ref REQUEST_BLOCK) =
!++
! Functional description:
!
! This routine performs the NICE load request function.
! It is responsible for extracting the parameter data,
! required for the load function, from the volatile data
! base and merging this data with any parameter data
! supplied with the load request. It calls LOAD_NODE to
! actually perform the function.
!
! Formal parameters:
!
! .REQ NML Request Block address.
!
! Implicit inputs: none
!
! Routine value:
!
! NICE return code.
!
! Side effects: none
!
!--
begin
bind
ACCEPTABLE_PARAMETERS = plit (10, 110, 111, 112, 113, 114, 115,
120, 121, 122, 123, 125 %(, 126)% ,
141, 500, 502, 2511, 2512);
macro ! Synonym for response buffer pointer
RESPONSE_PTR = ch$ptr (.REQ [RB_RESPONSE],, 8) %;
local
RTN_COD;
if not .REQ[RB_PRV_SERVICE] then return NICE$_PRV;
!
! Set up the load service block.
!
if DTL_SETUP (.REQ, ACCEPTABLE_PARAMETERS) lss 0
then
return (ch$rchar(RESPONSE_PTR));
!
! Access service block
!
begin
local
LB : ref SERVICE_DATA_BLOCK;
RTN_COD = NICE$_SUC;
LB = .REQ[RB_DTL_DATA];
LB [SB_USAGE] = DLX_LOAD;
LB [SB_PHY_ADDR] = .LB [SB_HARDWARE_ADDRESS]; ! Use HARDWARE ADDR for LOAD
!
! Open the link if we can
!
if not CIRCUIT_OPEN (.LB)
then
RTN_COD = ch$rchar (.LB [SB_RESPONSE_PTR]);
!
! Execute the load.
! Deallocate the buffers.
!
if .RTN_COD eql NICE$_SUC
then
begin
local TEMP_RTN_COD;
LOAD_NODE (.LB);
RTN_COD = ch$rchar (RESPONSE_PTR);
CIRCUIT_CLOSE (.LB);
end;
end;
DTL_CLEANUP (.REQ, .RTN_COD)
end; !End of NML$LOAD
%global_routine ('NML$DUMP', REQ : ref REQUEST_BLOCK) =
!++
! Functional description:
!
! This routine performs the NICE dump request function.
! It is responsible for extracting the parameter data,
! required for the dump function, from the volatile data
! base and merging this data with any parameter data
! supplied with the dump request. It calls DUMP_NODE to
! actually perform the function.
!
! Formal parameters:
!
! .REQ NML Request Block address
!
! Implicit inputs: none
!
! Routine value:
!
! NICE return code.
!
! Side effects: none
!
!--
begin
bind
ACCEPTABLE_PARAMETERS = plit (10, 110, 111, 114, 130, 131 %(, 135, 136)% );
macro ! Synonym for response buffer pointer
RESPONSE_PTR = ch$ptr (.REQ [RB_RESPONSE],, 8) %;
local
RTN_COD;
if not .REQ[RB_PRV_SERVICE] then return NICE$_PRV;
!
! Set up the dump service block
!
if DTL_SETUP (.REQ, ACCEPTABLE_PARAMETERS) lss 0
then
return (ch$rchar(RESPONSE_PTR));
!
! Access service block
!
begin
local
DB : ref SERVICE_DATA_BLOCK;
DB = .REQ[RB_DTL_DATA];
DB [SB_USAGE] = DLX_DUMP;
RTN_COD = NICE$_SUC;
DB [SB_PHY_ADDR] = .DB [SB_HARDWARE_ADDRESS]; ! Use HARDWARE ADDR for LOAD
!
! Open the link if we can
!
if not CIRCUIT_OPEN (.DB)
then
RTN_COD = ch$rchar (RESPONSE_PTR);
!
! Execute the dump.
!
if .RTN_COD eql NICE$_SUC
then
begin
DUMP_NODE (.DB);
RTN_COD = ch$rchar (RESPONSE_PTR);
CIRCUIT_CLOSE (.DB);
end;
end;
DTL_CLEANUP (.REQ, .RTN_COD)
end; !End of NML$DUMP
%global_routine ('NML$TRIGGER', REQ : ref REQUEST_BLOCK) =
!++
! Functional description:
!
! This routine performs the NICE trigger request function.
! It is responsible for extracting the parameter data,
! required for the trigger function, from the volatile data
! base and merging this data with any parameter data
! supplied with the trigger request. It calls TRIGGER_NODE to
! actually perform the function.
!
! Formal parameters:
!
! .REQ NML Request Block address.
!
! Implicit inputs: none
!
! Routine value:
!
! NICE return code.
!
! Side effects: none
!
!--
begin
bind
ACCEPTABLE_PARAMETERS = plit (10, 110, 111);
macro ! Synonym for response buffer pointer
RESPONSE_PTR = ch$ptr (.REQ [RB_RESPONSE],, 8) %;
local
RTN_COD;
if not .REQ[RB_PRV_SERVICE] then return NICE$_PRV;
!
! Set up the trigger service block.
!
if DTL_SETUP (.REQ, ACCEPTABLE_PARAMETERS) lss 0
then
return (ch$rchar(RESPONSE_PTR));
!
! Access service block
!
begin
local
TB : ref SERVICE_DATA_BLOCK;
RTN_COD = NICE$_SUC;
TB = .REQ[RB_DTL_DATA];
EXECUTE_TRIGGER (.TB, RTN_COD);
end;
DTL_CLEANUP (.REQ, .RTN_COD)
end; !End of NML$TRIGGER
%routine ('DTL_SETUP', REQ: ref REQUEST_BLOCK, ACCEPTABLE_PARAMETERS: VECTOR) =
!++
! Functional description:
!
! This routine does setup for LOAD, DUMP and TRIGGER. It allocates
! the service block that is used to control the process and sets up
! its parameters. All parameters that have no default value and that
! have not been specified will be given "NA" values: -1 for $integer's
! and the null pointer for pointers.
!
!
! Formal parameters:
!
! .REQ NML Request Block address.
! .ACCEPTABLE_PARAMETERS A list of the acceptable parameters for
! the request type being done.
!
! Implicit inputs: none
!
! Routine value:
!
! 1 Success: setup done
! -1 Failure: one or more essential parameters are missing, or an
! specified parameter was invalid. The MOP buffer,
! the service block and the NICE response buffer have
! been allocated.
! -3 Failure: the routine was not able to allocate a service block
! plus a MOP buffer. The NICE response buffer has been
! allocated.
! -4 Failure: the routine was not able to allocate a NICE response
! buffer. The service block and the MOP buffer were
! not allocated.
!
! Side effects: none.
!
!--
begin
label
CHECK_PARAMETERS;
local
RET,
BUFFER,
DLW_SR : ref DLWQ_BLOCK,
SB: ref SERVICE_DATA_BLOCK;
macro ! Synonym for response buffer pointer
RESPONSE_PTR = ch$ptr (.REQ [RB_RESPONSE],, 8) %;
REQ[RB_DTL_DATA] = 0;
RET = 1;
!
! Allocate NICE response buffer.
!
REQ[RB_RESPONSE_ALLOCATION] = RESPONSE_BUFFER_ALLOCATION ;
if (REQ[RB_RESPONSE] = NMU$MEMORY_GET (.REQ[RB_RESPONSE_ALLOCATION])) eql 0
then begin ! Allocation failure
REQ[RB_RETURN_CODE] = NICE$_REE;
return -4
end;
!
! Allocate a SERVICE_DATA_BLOCK plus transmit and receive MOP buffers
!
REQ[RB_DTL_DATA_ALLOCATION] = SERVICE_DATA_BLOCK_ALLOCATION
+ MOP_BUFFER_ALLOCATION;
if (SB = NMU$MEMORY_GET (.REQ[RB_DTL_DATA_ALLOCATION])) eql 0
then ! Allocation failure
begin
$RESPONSE (RESPONSE_PTR,NICE$_REE,0);
return -3;
end;
DLW_SR = .REQ [RB_DLW_DATA];
CHECK_PARAMETERS:
begin ! CHECK_PARAMETERS
REQ[RB_DTL_DATA] = .SB;
SB[SB_BUFFER] = vector [.SB, SERVICE_DATA_BLOCK_SIZE];
SB[SB_BUFFER_PTR] = ch$ptr (.SB [SB_BUFFER],, 8);
!
! Merge information in SERVICE_DATA_BLOCK from NML volatile data base
! for this node, and any parameters supplied on the dump request.
!
SB [SB_RESPONSE_PTR] = RESPONSE_PTR;
selectone .REQ[RB_NICE_ENTITY_TYPE] of
set
[ENTITY_NODE]: ! NODE entity
begin
SB[SB_NODE_DATA] = .REQ[RB_NICE_ENTITY] ; ! NODE for this load
if .DLW_SR neq 0
then SB[SB_SERVICE_CIRCUIT] =
ch$ptr (DLW_SR [DLWQ_CIRCUIT_NAME],,8);
end;
[ENTITY_CIRCUIT]: ! CIRCUIT entity
begin
SB[SB_SERVICE_CIRCUIT] = .REQ[RB_NICE_ENTITY] ; ! CIRCUIT for this
! load
! If this is a DTE load, then try to find the node that has this
! DTE circuit as its service circuit
if $NMU_DLX_DEVICE_TYPE (.SB [SB_SERVICE_CIRCUIT]) eql DEVTYP_DTE
then SB[SB_NODE_DATA] = NML$FIND_NDB (.REQ[RB_NICE_ENTITY])
end;
tes;
!
! Set default (NA) values for all parameter fields.
!
SB[SB_PHY_ADDR] = 0;
SB[SB_SERVICE_PASSWORD] = 0;
SB[LB_LOAD_FILE] = 0;
SB[LB_SECONDARY_LOADER] = 0; ! Set all pointer
SB[LB_TERTIARY_LOADER] = 0; ! fields to the
SB[LB_SOFTWARE_IDENTIFICATION] = 0; ! null pointer
SB[LB_CONSOLE_SECONDARY_LOADER] = 0;
SB[LB_CONSOLE_LOAD_FILE] = 0;
SB[SB_HARDWARE_ADDRESS] = 0;
SB[DB_DUMP_FILE] = 0;
SB[DB_SECONDARY_DUMPER] = 0;
begin
local PTR;
PTR = ch$ptr (SB[LB_HOST],, 8);
ch$wchar_a (0, PTR); ! Node number = 0
ch$wchar_a (0, PTR);
ch$wchar_a (0, PTR); ! Node name = ''
end;
SB[LB_NAME] = 0;
SB[LB_ADDRESS] = 0;
SB[LB_SERVICE_DEVICE] = -1;
SB[SB_NODE_VERSION] = -1;
SB[LB_CPU] = -1;
SB[LB_SOFTWARE_TYPE] = -1; ! Set all
%movi32 (0, SB[DB_DUMP_ADDRESS]); ! numeric fields
%subi32 (1, SB[DB_DUMP_ADDRESS]); ! to -1
%movi32 (0, SB[DB_DUMP_COUNT]);
%subi32 (1, SB[DB_DUMP_COUNT]);
SB[LB_LOAD_MAINT_IMAGE] = $false;
if .DLW_SR neq 0
then begin
SB[LB_PROCESSOR] = .DLW_SR [DLWQ_PROCESSOR];
if .DLW_SR [DLWQ_DL_BUFSIZ] neq 0
then SB[LB_DL_BUFFER_SIZE] = .DLW_SR [DLWQ_DL_BUFSIZ]
else SB[LB_DL_BUFFER_SIZE] = 256 - 6;
SB[LB_SOFTWARE_TYPE] = .DLW_SR [DLWQ_PROG_TYPE];
if .DLW_SR [DLWQ_MEMORY_SIZE] neq 0
then SB [DB_DUMP_COUNT] = .DLW_SR [DLWQ_MEMORY_SIZE];
SB [SB_NEED_RPM] = .DLW_SR [DLWQ_NEED_RPM];
! If Software ID is -2, then use maintenance image
! If it's greater than 0, then it's a image name
! If it's 0, ignore it, and -1 we don't support
if .DLW_SR [DLWQ_SID_FORM] eql -2
then SB [LB_LOAD_MAINT_IMAGE] = $true;
if .DLW_SR [DLWQ_SID_FORM] gtr 0
then begin
! If a software ID is present, build a filespec
! like SYS:<software-ID>.SYS and use that as load file
local F_PTR, T_PTR, X_PTR, COUNT, TC;
F_PTR = ch$ptr (DLW_SR [DLWQ_SOFTWARE_ID],,8);
T_PTR = ch$ptr (DLW_SR [DLWQ_SUPPLIED_FILE],,8);
! T_PTR is destination pointer. Move past where we are
! going to store count when we're done
T_PTR = ch$plus (.T_PTR,1);
! Copy SYS:
X_PTR = DLW$ASCIC ('SYS:');
COUNT = GETB (X_PTR);
ch$move (.COUNT, .X_PTR, .T_PTR);
T_PTR = ch$plus (.T_PTR, .COUNT);
! Copy the filename off the software ID field
TC = .DLW_SR [DLWQ_SID_FORM];
! TOPS-10 has a maximum of 6 chars in file name
%if $tops10 %then if .TC gtr 6 then TC = 6; %fi
ch$move (.TC, .F_PTR, .T_PTR);
T_PTR = ch$plus (.T_PTR, .TC);
COUNT = .COUNT + .TC;
! Copy extension .SYS
X_PTR = DLW$ASCIC ('.SYS');
TC = GETB (X_PTR);
ch$move (.TC, .X_PTR, .T_PTR);
COUNT = .COUNT + .TC;
! Now store count in first byte
X_PTR = T_PTR = ch$ptr (DLW_SR [DLWQ_SUPPLIED_FILE],,8);
PUTB (.COUNT, T_PTR);
! Set secondary, tertiary or system load file name
! depending on software type
selectone .DLW_SR [DLWQ_PROG_TYPE] of
set
[0]: SB [LB_SECONDARY_LOADER] = .X_PTR;
[1]: SB [LB_TERTIARY_LOADER] = .X_PTR;
[2]: SB [LB_LOAD_FILE] = .X_PTR;
tes;
end;
end;
SB[SB_EXECUTE_TRIGGER] = $false;
!
! Get PHYSICAL and HARDWARE ADDRESS Parameters for this NODE
!
! Get hardware address
SB [SB_HARDWARE_ADDRESS] =
(if GET_VDB (ENTITY_NODE, ! NODE for this load
.SB[SB_NODE_DATA],
114, ! HARDWARE ADDRESS
SB [SB_HARDWARE_ADDRESS])
then ch$plus (.SB [SB_HARDWARE_ADDRESS],1)
else if .DLW_SR neq 0
then ch$ptr (DLW_SR[DLWQ_HARDWARE_ADDRESS],,8)
else 0);
!
! Build Ethernet physical address for this node
! in the SB.
!
begin
local
ADDRESS,
NOD_PTR;
if .SB [SB_NODE_DATA] neq 0
then begin
NOD_PTR = .SB[SB_NODE_DATA];
ADDRESS = GETW (NOD_PTR);
NOD_PTR = ch$ptr (SB [SB_ETHER_ADDR_BUFFER],,8);
NOD_PTR = ch$move (4, ! Move HI-Order Ethernet address
CH$HEX ('AA000400'),
.NOD_PTR);
PUTW (ADDRESS, NOD_PTR);
SB [SB_PHY_ADDR] = ch$ptr (SB [SB_ETHER_ADDR_BUFFER],,8);
end
else SB [SB_PHY_ADDR] = .SB [SB_HARDWARE_ADDRESS];
end;
!
! Merge any parameters specified in the NICE request message.
!
if FETCH_PARAMETERS (.REQ, .SB, .ACCEPTABLE_PARAMETERS) lss 0
then leave CHECK_PARAMETERS with RET = -1; ! Problem with a parameter
end; ! CHECK_PARAMETERS
!
! If there was an error, release everything we got (except the
! response buffer).
!
if .RET lss 0
then begin
NMU$MEMORY_RELEASE (.REQ[RB_DTL_DATA], .REQ[RB_DTL_DATA_ALLOCATION]);
REQ[RB_DTL_DATA] = 0;
end;
.RET
end; ! End of DTL_SETUP
%routine ('DTL_CLEANUP', REQ: ref REQUEST_BLOCK, RTN_COD) =
!++
! Functional description:
!
! None
!
! Formal parameters:
!
! .REQ NML Request Block address.
! RTN_COD Current NICE return code
!
! Implicit inputs: none
!
! Routine value:
!
! return code
!
! Side effects: none.
!
!--
begin
macro ! Synonym for response buffer pointer
RESPONSE_PTR = ch$ptr (.REQ [RB_RESPONSE],, 8) %;
!
! Deallocate service blocks
!
if .REQ[RB_DTL_DATA] neqa 0
then NMU$MEMORY_RELEASE (.REQ[RB_DTL_DATA],.REQ[RB_DTL_DATA_ALLOCATION]) ;
!
! If successful, build NICE repsonse message with success code.
!
if .RTN_COD eql NICE$_SUC
then begin
REQ [RB_RESPONSE_LENGTH] = $RESPONSE (RESPONSE_PTR, NICE$_SUC, 0) ;
NML$REQUEST_FINISH (.REQ) ;
end
else if ch$rchar (RESPONSE_PTR) neq 0
then
REQ [RB_RESPONSE_LENGTH] = $RESPONSE_LENGTH (RESPONSE_PTR);
.RTN_COD
end; ! End of DTL_CLEANUP
%routine ('CIRCUIT_OPEN', DB : ref SERVICE_DATA_BLOCK) : NML_LKG_DB =
!++
! Functional description
!
! This routine opens the service circuit.
!
! Formal parameters
!
! .DB Address of the service data block
!
! Implicit inputs: none
!
! Routine value:
!
! $true Service circuit successfully opened
! $false Error in opening circuit - response set
!
! Side effects: none
!
!--
begin
local
CIRCUIT_HANDLE,
SERVICE_CIRCUIT;
if .DB [SB_SERVICE_CIRCUIT] eqla 0
then
if not GET_VDB (ENTITY_NODE, ! CIRCUIT for this load
.DB[SB_NODE_DATA],
110, ! SERVICE CIRCUIT
DB [SB_SERVICE_CIRCUIT])
then
begin
$RESPONSE_X (.DB[SB_RESPONSE_PTR],NICE$_PAM,110);
return $false;
end;
!
! Find out what type of Service Circuit we have (NI or DTE)
!
DB [SB_SRVC_CKT_DEVICE] = $NMU_DLX_DEVICE_TYPE (.DB [SB_SERVICE_CIRCUIT]);
!
! Check the circuit state for ON or SERVICE
!
begin
local
CIRCUIT_STATE;
NML$CALCULATE_CIRCUIT_STATE (.DB[SB_SERVICE_CIRCUIT]);
if not NML$GET_VDB_PARAMETER (ENTITY_CIRCUIT,
.DB [SB_SERVICE_CIRCUIT],
CPARM_STATE,
CIRCUIT_STATE)
then CIRCUIT_STATE = CIRCUIT_ON;
selectoneu .CIRCUIT_STATE of
set
[CIRCUIT_ON, CIRCUIT_SERVICE]:
;
[otherwise]:
begin
$RESPONSE (.DB[SB_RESPONSE_PTR],NICE$_CWS,ENTITY_CIRCUIT);
return $false;
end;
tes;
end;
!
! Check the service state for ENABLED
!
begin
local
CIRCUIT_SERVICE;
if not NML$GET_VDB_PARAMETER (ENTITY_CIRCUIT, .DB [SB_SERVICE_CIRCUIT],
CPARM_SERVICE, CIRCUIT_SERVICE)
then CIRCUIT_SERVICE = CIRCUIT_DISABLED;
selectoneu .CIRCUIT_SERVICE of
set
[CIRCUIT_ENABLED]:
;
[otherwise]:
begin
$RESPONSE (.DB[SB_RESPONSE_PTR],NICE$_CWS,ENTITY_CIRCUIT);
return $false;
end;
tes;
end;
!
! Check the circuit substate.
! If no substate, then we can go ahead.
! If autoservice, remember the fact.
! Otherwise abort the request.
!
begin
local
CIRCUIT_SUBSTATE;
if not NML$GET_VDB_PARAMETER (ENTITY_CIRCUIT, .DB [SB_SERVICE_CIRCUIT],
CPARM_SUBSTATE, CIRCUIT_SUBSTATE)
then CIRCUIT_SUBSTATE = CIRCUIT_NO_SUBSTATE;
DB[SB_SUBSTATE] = .CIRCUIT_SUBSTATE;
selectoneu .CIRCUIT_SUBSTATE of
set
[CIRCUIT_NO_SUBSTATE, CIRCUIT_FAILED, CIRCUIT_STARTING]:
DB[SB_AUTOSERVICE] = $false;
[CIRCUIT_AUTOSERVICE]:
DB[SB_AUTOSERVICE] = $true;
[otherwise]:
begin
$RESPONSE (.DB[SB_RESPONSE_PTR],NICE$_CWS,ENTITY_CIRCUIT);
return $false;
end;
tes;
end;
CIRCUIT_HANDLE = $NMU_DLX_OPEN (.DB [SB_USAGE],
CIRCUIT_,
.DB [SB_SERVICE_CIRCUIT],
.DB [SB_PHY_ADDR],
-1,
-1,
-1,
.DB [SB_RESPONSE_PTR]);
if .CIRCUIT_HANDLE leq 0 then return $false;
DB [SB_CIRCUIT_HANDLE] = .CIRCUIT_HANDLE;
!
! Set the substate for the requested operation
!
selectone .DB [SB_USAGE] of
set
[DLX_LOAD]:
if .DB[SB_AUTOSERVICE]
then DB[SB_SUBSTATE] = CIRCUIT_AUTOLOADING
else DB[SB_SUBSTATE] = CIRCUIT_LOADING;
[DLX_DUMP]:
if .DB[SB_AUTOSERVICE]
then DB[SB_SUBSTATE] = CIRCUIT_AUTODUMPING
else DB[SB_SUBSTATE] = CIRCUIT_DUMPING;
[DLX_TRIGGER]:
if .DB[SB_AUTOSERVICE]
then DB[SB_SUBSTATE] = CIRCUIT_AUTOTRIGGERING
else DB[SB_SUBSTATE] = CIRCUIT_TRIGGERING;
[otherwise]:
return $false;
tes;
SET_SUBSTATE (.DB);
$true
end; !End of CIRCUIT_OPEN
%routine ('CIRCUIT_CLOSE', DB : ref SERVICE_DATA_BLOCK) : NML_LKG_DB =
!++
! Functional description
!
! This routine closes the circuit.
!
! Formal parameters
!
! .DB Address of the service data block
!
! Implicit inputs: none
!
! Routine value:
!
! $true Circuit successfully closed
!
! Side effects: none
!
!--
begin
!
! Set the substate back to something reasonable
!
if .DB[SB_AUTOSERVICE]
then DB[SB_SUBSTATE] = CIRCUIT_AUTOSERVICE
else DB[SB_SUBSTATE] = CIRCUIT_NO_SUBSTATE;
SET_SUBSTATE (.DB);
if (.DB [SB_USAGE] eql DLX_TRIGGER) or
(.DB [SB_SRVC_CKT_DEVICE] eql DEVTYP_DTE)
then $NMU_DLX_CLOSE (.DB[SB_CIRCUIT_HANDLE]);
%if $TOPS20 or $TOPS10
%then
!
! If circuit state is ON then initialize the circuit
!
if (.DB [SB_USAGE] eql DLX_LOAD) and
(ch$rchar (.DB[SB_RESPONSE_PTR]) eql NICE$_SUC)
then begin
local
CIRCUIT_STATE;
if not NML$GET_VDB_PARAMETER (ENTITY_CIRCUIT,
.DB [SB_SERVICE_CIRCUIT],
CPARM_STATE,
CIRCUIT_STATE)
then CIRCUIT_STATE = CIRCUIT_ON;
if .CIRCUIT_STATE eql CIRCUIT_ON
then return $NMU_DLX_START_PROTOCOL (.DB[SB_CIRCUIT_HANDLE],
.DB[SB_RESPONSE_PTR]);
end;
%fi
$true
end; !End of CIRCUIT_CLOSE
%routine ('CIRCUIT_PROMPT', DB : ref SERVICE_DATA_BLOCK) : NML_LKG_DB =
!++
! Functional description
!
! This routine prompts for a message retransmission over the circuit
! by sending a truncated MOP_MODE_RUNNING message.
!
! Formal parameters
!
! .DB Address of the service data block
!
! Implicit inputs: none
!
! Routine value:
!
! $true Prompted successfully
! $false Error in transmission - response set
!
! Side effects: none
!
!--
begin
$NMU_DLX_WRITE (.DB[SB_CIRCUIT_HANDLE], DLX_OTHER,
ch$ptr (uplit (%char(MOP_MODE_RUNNING)),, 8), 1,
.DB [SB_RESPONSE_PTR])
end; !End of CIRCUIT_PROMPT
%routine ('LOAD_NODE', LOAD_DATA : ref SERVICE_DATA_BLOCK) : NML_LKG_DB novalue =
!++
! Functional description:
!
! This routine is called after the NICE request message
! has been decomposed. It performs the actual load
! sequence by transferring MOP messages across the specified
! circuit with the target node.
!
! Formal parameters:
!
! .LOAD_DATA Address of load data block
!
! Necessary parameters (must be specified in request or on VDB):
!
! Parameter Name
! --------- ----
!
! (one of):
!
! 121 Secondary Loader ID
! 122 Tertiary Loader ID
! 120 Load File ID
! 123 Diagnostic File ID
! 2511 Console Secondary Loader ID
! 2512 Console Load File ID
!
! Parameters that may be defaulted:
!
! Parameter Name Default Value
! --------- ---- -------------
!
! 125 Software Type SECONDARY_LOADER
!
! Implicit inputs: none
!
! Routine value: none
! Side effects: none
!
!--
begin
local
RETURN_CODE,
CURRENT_LOAD;
!
! Setup the initial load file type. Default to secondary loader.
!
begin
local
SOFTWARE_TYPE;
bind
PARAMETER_TO_GET = uplit (121,122,120,2511,2512,123): vector;
local
WHERE_TO_PUT_IT: vector[6];
WHERE_TO_PUT_IT[0] = LOAD_DATA[LB_SECONDARY_LOADER];
WHERE_TO_PUT_IT[1] = LOAD_DATA[LB_TERTIARY_LOADER];
WHERE_TO_PUT_IT[2] = LOAD_DATA[LB_LOAD_FILE];
WHERE_TO_PUT_IT[3] = LOAD_DATA[LB_CONSOLE_SECONDARY_LOADER];
WHERE_TO_PUT_IT[4] = LOAD_DATA[LB_CONSOLE_LOAD_FILE];
WHERE_TO_PUT_IT[5] = LOAD_DATA[LB_DIAGNOSTIC_FILE];
! Assume succesful load. All failures will set up error responses
$RESPONSE (.LOAD_DATA [SB_RESPONSE_PTR], NICE$_SUC);
! We don't do trigger after load failure anymore.
! Make sure the flag is turned off.
LOAD_DATA [SB_EXECUTE_TRIGGER] = $false;
!
! If any important parameters haven't been specified in the request,
! try to obtain them from the data base.
!
incr I from 0 to 5 do
if ..WHERE_TO_PUT_IT[.I] eql 0
then
GET_VDB (ENTITY_NODE,
.LOAD_DATA [SB_NODE_DATA],
.PARAMETER_TO_GET[.I],
.WHERE_TO_PUT_IT[.I]);
SOFTWARE_TYPE = .LOAD_DATA [LB_SOFTWARE_TYPE];
if .SOFTWARE_TYPE eql -1
then
if not GET_VDB (ENTITY_NODE,
.LOAD_DATA [SB_NODE_DATA],
125,
SOFTWARE_TYPE)
then
SOFTWARE_TYPE = SECONDARY_LOADER;
CURRENT_LOAD = .SOFTWARE_TYPE;
end;
!
! Load until one of the load routines indicates the loading
! has stopped. CURRENT_LOAD must never be -1 upon entry to this
! section of the code.
!
RETURN_CODE = -1;
while $true do
begin
local RESULT;
!
! Convert from a MOP program type to a internal
! file type code
!
if not
begin
case .CURRENT_LOAD from -1 to 3 of
set
[-1] : ! Leave CURRENT_LOAD as is, allow loop on $NMU_DLX_READ
$true;
[SECONDARY_LOADER] :
if .LOAD_DATA[LB_PROCESSOR] eql COMMUNICATION_PROCESSOR
then if .LOAD_DATA[LB_CONSOLE_SECONDARY_LOADER] neq 0
then
SECONDARY_LOAD (.LOAD_DATA, FILE_SECONDARY_LOADER,
.LOAD_DATA [LB_CONSOLE_SECONDARY_LOADER],
LOAD_)
else (RETURN_CODE = .CURRENT_LOAD; $false)
else if .LOAD_DATA[LB_SECONDARY_LOADER] neq 0
then
SECONDARY_LOAD (.LOAD_DATA, FILE_SECONDARY_LOADER,
.LOAD_DATA [LB_SECONDARY_LOADER],
LOAD_)
else
(RETURN_CODE = .CURRENT_LOAD; $false);
[TERTIARY_LOADER] :
if .LOAD_DATA[LB_PROCESSOR] eql COMMUNICATION_PROCESSOR
then begin
$RESPONSE_X (.LOAD_DATA [SB_RESPONSE_PTR], NICE$_MPE, 0,
'SOFTWARE TYPE parameter invalid', 105);
$false
end
else if .LOAD_DATA[LB_TERTIARY_LOADER] neq 0
then
IMAGE_LOAD (.LOAD_DATA, FILE_TERTIARY_LOADER,
.LOAD_DATA [LB_TERTIARY_LOADER])
else
(RETURN_CODE = .CURRENT_LOAD; $false);
[SYSTEM_IMAGE] :
if .LOAD_DATA[LB_PROCESSOR] eql COMMUNICATION_PROCESSOR
then if .LOAD_DATA[LB_CONSOLE_LOAD_FILE] neq 0
then
CONSOLE_IMAGE_LOAD (.LOAD_DATA, FILE_SYSTEM_IMAGE,
.LOAD_DATA [LB_CONSOLE_LOAD_FILE])
else (RETURN_CODE = .CURRENT_LOAD; $false)
else
if .LOAD_DATA [LB_LOAD_MAINT_IMAGE]
then
if .LOAD_DATA [LB_DIAGNOSTIC_FILE] neq 0
then
IMAGE_LOAD (.LOAD_DATA,
FILE_SYSTEM_IMAGE,
.LOAD_DATA [LB_DIAGNOSTIC_FILE])
else (RETURN_CODE = .CURRENT_LOAD; $false)
else
if .LOAD_DATA[LB_LOAD_FILE] neq 0
then
IMAGE_LOAD (.LOAD_DATA, FILE_SYSTEM_IMAGE,
.LOAD_DATA [LB_LOAD_FILE])
else (RETURN_CODE = .CURRENT_LOAD; $false);
[inrange, outrange] :
begin
$RESPONSE_X (.LOAD_DATA [SB_RESPONSE_PTR], NICE$_MPE, 0,
'SOFTWARE TYPE parameter invalid', 105);
$false
end;
tes
end
then
exitloop;
!
! If the above load succeeded, the subroutine will have read the
! response from the load and data will be available in the MOP
! buffer.
!
! Get the function code from the response message.
! If it is a request program load .. go load the appropriate
! image. If it is a request memory load .. it was a successful
! load. If anything else .. who knows what happened (assume it
! has died).
!
begin
local
BUFFER_PTR,
MOP_FUNCTION,
MOP_ERROR;
BUFFER_PTR = .LOAD_DATA [SB_BUFFER_PTR];
MOP_FUNCTION = GETB (BUFFER_PTR);
MOP_ERROR =$false;
selectone .MOP_FUNCTION of
set
[REQUEST_PROGRAM] :
if (.CURRENT_LOAD eql SECONDARY_LOADER) or
(.CURRENT_LOAD eql TERTIARY_LOADER)
then begin
BUFFER_PTR = ch$plus (.BUFFER_PTR, 2);
CURRENT_LOAD = GETB (BUFFER_PTR);
!
! We only generate events if the circuit is AUTO_LOADING.
!
if .LOAD_DATA [SB_SUBSTATE] eql CIRCUIT_AUTOLOADING
then begin
!
! Generate a 0.3 event to show successful load
!
NML$DLW_SERVICE_EVENT (LOAD_,
.LOAD_DATA [SB_HARDWARE_ADDRESS],
.CURRENT_LOAD,
.LOAD_DATA [SB_SERVICE_CIRCUIT],
.LOAD_DATA [SB_RESPONSE_PTR]);
!
! Generate a 0.3 event that says
! we started a new load.
!
NML$DLW_SERVICE_EVENT (LOAD_,
.LOAD_DATA [SB_HARDWARE_ADDRESS],
.CURRENT_LOAD,
.LOAD_DATA [SB_SERVICE_CIRCUIT],
0);
end;
end
else MOP_ERROR = $true;
[REQUEST_MEMORY_LOAD] :
if .CURRENT_LOAD eql SYSTEM_IMAGE
then begin
$RESPONSE (.LOAD_DATA [SB_RESPONSE_PTR], NICE$_SUC);
LOAD_DATA [SB_EXECUTE_TRIGGER] = $false;
exitloop;
end
else MOP_ERROR = $true;
[CHK11_ASCII_TEXT] :
if .LOAD_DATA [SB_SRVC_CKT_DEVICE] neq DEVTYP_NI
then CURRENT_LOAD = -1
else MOP_ERROR = $true;
[otherwise] :
MOP_ERROR = $true;
tes;
if .MOP_ERROR then
begin
$RESPONSE_X (.LOAD_DATA [SB_RESPONSE_PTR], NICE$_LPE, 0,
'Unexpected MOP response, MOP function code = %D', .MOP_FUNCTION, .MOP_FUNCTION);
%(
'Unexpected MOP response, expecting program request', 106);
)%
exitloop;
end;
end;
end;
!
! If we fell out due to a request for a software type we don't have
! a parameter for, record an error.
!
if .RETURN_CODE geq 0 then
$RESPONSE_X (.LOAD_DATA[SB_RESPONSE_PTR], NICE$_IPV,
(case .RETURN_CODE from SECONDARY_LOADER to SYSTEM_IMAGE of
set
[SECONDARY_LOADER]: 121;
[TERTIARY_LOADER]: 122;
[SYSTEM_IMAGE]: 120;
tes), 'File not specified');
end;
%routine ('SECONDARY_LOAD', LOAD_DATA : ref SERVICE_DATA_BLOCK, FILE_TYPE, FILE, MOP_FUNCTION) : NML_LKG_DB =
!++
! Functional description:
!
! This routine sends a SECONDARY LOADER to the target node.
! The whole loader is sent in one MEMORY LOAD WITH TRANSFER ADDRESS
! MOP message.
!
! Formal parameters
!
! .LOAD_DATA Address of load data block
! .FILE_TYPE Type of file for error response
! .FILE Pointer to ASCIZ file name
! MOP_FUNCTION LOAD_ or DUMP_
!
! Implicit inputs: none
!
! Routine value:
!
! $true secondary boot was transmitted
! $false failure occured while sending boot
!
! Side effects: none
!
!--
begin
macro
ABORT (FB) =
begin
FILE_CLOSE (FB);
return $false
end %;
local
FB : FILE_DATA_BLOCK,
RESULT;
FB[FB_RESPONSE_PTR] = .LOAD_DATA [SB_RESPONSE_PTR];
FB[FB_FILE_TYPE] = .FILE_TYPE;
FB[FB_FILE] = .FILE;
if .LOAD_DATA [SB_SRVC_CKT_DEVICE] eql DEVTYP_DTE
then if not CPU_IS_PDP11 (.LOAD_DATA) then return $false;
!
! Open the secondary loader file.
!
if not FILE_OPEN (FB) then return $false;
!
! Read the image base address, size of image and transfer address.
!
if not FILE_READ_LABEL (FB) then ABORT (FB);
if .LOAD_DATA [SB_SRVC_CKT_DEVICE] eql DEVTYP_NI
then
(if %cmpi32 (FB[FB_BYTES_LEFT], gtr, 1490)
then
begin
$RESPONSE_X (.LOAD_DATA [SB_RESPONSE_PTR], NICE$_IFC, .FB[FB_FILE_TYPE],
'Secondary image is too large, >1490 bytes', 110);
ABORT (FB);
end)
else
if %cmpi32 (FB[FB_BYTES_LEFT], gtr, 512)
then
begin
$RESPONSE_X (.LOAD_DATA [SB_RESPONSE_PTR], NICE$_IFC, .FB[FB_FILE_TYPE],
'Secondary image is too large, >512 bytes', 110);
ABORT (FB);
end;
begin
local
BUFFER_PTR;
!
! Make a pointer to the buffer used to construct MOP messages.
!
BUFFER_PTR = .LOAD_DATA [SB_BUFFER_PTR];
!
! Put in the header information for a "load memory with transfer address"
! Function, load number 0, load address
!
PUTB (LOAD_WITH_TRANSFER, BUFFER_PTR);
PUTB (0, BUFFER_PTR);
PUT32 (FB[FB_CURRENT_ADDRESS], BUFFER_PTR);
!
! Put in the secondary image
!
begin
local
LENGTH;
%movf32 (FB[FB_BYTES_LEFT], LENGTH);
if 0 geq (LENGTH = NMU$FILE_READ (.FB[FB_FILE_HANDLE], .BUFFER_PTR,
.LENGTH, .FB[FB_RESPONSE_PTR]))
then
begin
$RESPONSE_X (.FB[FB_RESPONSE_PTR], NICE$_FIO, .FB[FB_FILE_TYPE],
'Could not read image file', 119);
ABORT (FB);
end;
BUFFER_PTR = ch$plus (.BUFFER_PTR, .LENGTH);
end;
!
! Put in the transfer address of the secondary boot
!
PUT32 (FB[FB_TRANSFER_ADDRESS], BUFFER_PTR);
!
! Send the boot to the target node.
!
BUFFER_PTR = ch$diff (.BUFFER_PTR, .LOAD_DATA [SB_BUFFER_PTR]);
if not $NMU_DLX_WRITE (.LOAD_DATA [SB_CIRCUIT_HANDLE], DLX_SECONDARY,
.LOAD_DATA [SB_BUFFER_PTR], .BUFFER_PTR,
.LOAD_DATA [SB_RESPONSE_PTR])
then ABORT (FB);
!
! Read the response from the load.
!
if .MOP_FUNCTION eql LOAD_
then begin
RESULT = (if .LOAD_DATA [SB_SRVC_CKT_DEVICE] eql DEVTYP_NI
then
(NML$DLW_READ_LDAQ (.LOAD_DATA [SB_CIRCUIT_HANDLE],
DLX_DATA, .LOAD_DATA [SB_BUFFER_PTR],
MOP_BUFFER_LENGTH,
.LOAD_DATA [SB_RESPONSE_PTR],
.LOAD_DATA [SB_HARDWARE_ADDRESS]))
else
$NMU_DLX_READ (.LOAD_DATA [SB_CIRCUIT_HANDLE], DLX_DATA,
.LOAD_DATA [SB_BUFFER_PTR],
MOP_BUFFER_LENGTH,,
.LOAD_DATA [SB_RESPONSE_PTR]));
if .RESULT lss 0
then begin
$RESPONSE (.LOAD_DATA [SB_RESPONSE_PTR], NICE$_LCE);
ABORT (FB);
end;
end;
end;
!
! Return indicating that the load has been sent.
!
FILE_CLOSE (FB);
$true
end;
%routine ('IMAGE_LOAD', DATA : ref SERVICE_DATA_BLOCK, FILE_TYPE, FILE) : NML_LKG_DB =
!++
! Functional description:
!
! This routine is called by the LOAD_NODE routine to perform
! a core image transfer TO a target node. The images that
! this routine sends are for either a TERTIARY LOADER or
! SYSTEM IMAGE.
!
! Formal parameters
!
! .DATA Address of load data block
! .FILE_TYPE Type of file for error response
! .FILE Pointer to ASCIZ file name
!
! Implicit inputs: none
!
! Routine value:
!
! $true image was sent to node successfully
! $false failure while sending image
!
! Side effects: none
!
!--
begin
macro
ABORT (FB) =
begin
FILE_CLOSE (FB);
return $false
end %;
local
FB : FILE_DATA_BLOCK,
TARGET_NAME,
TARGET_NUMBER,
JOB_NUMBER;
!
! Get the needed information for the load
!
FB[FB_RESPONSE_PTR] = .DATA [SB_RESPONSE_PTR];
FB[FB_FILE_TYPE] = .FILE_TYPE;
FB[FB_FILE] = .FILE;
if .DATA [SB_SRVC_CKT_DEVICE] eql DEVTYP_DTE
then if not CPU_IS_PDP11 (.DATA) then return $false;
begin
local TEMP;
if .DATA[SB_NODE_VERSION] eql -1 ! Get SERVICE NODE VERSION if
then ! we don't have one already
if GET_VDB (ENTITY_NODE, .DATA[SB_NODE_DATA], 115, TEMP)
then DATA[SB_NODE_VERSION] = .TEMP
else DATA[SB_NODE_VERSION] = 1; ! Default to 1 (PHASE IV)
end;
if (TARGET_NUMBER = .DATA [LB_ADDRESS]) eql 0
then
TARGET_NUMBER = .DATA [SB_NODE_DATA];
TARGET_NAME =
(if (TARGET_NAME = .DATA [LB_NAME]) neq 0
then ch$plus (.TARGET_NAME,2)
else if .DATA [SB_NODE_DATA] neq 0
then ch$plus (.DATA [SB_NODE_DATA],2)
else 0);
begin
local PTR, TEMP;
PTR = ch$ptr (DATA [LB_HOST],, 8);
if (ch$rchar_a (PTR) eqlu 0) and
(ch$rchar_a (PTR) eqlu 0) and
(ch$rchar_a (PTR) eqlu 0)
then
if GET_VDB (ENTITY_NODE, .DATA [SB_NODE_DATA], 140, TEMP)
then
begin
PTR = .TEMP; ! (for optimization)
ch$move (ch$rchar (ch$plus (.PTR, 2)) + 3, .PTR, ch$ptr (DATA [LB_HOST],, 8));
end;
TEMP = NODE_ID_BUFFER_LENGTH;
$NML$MAP_NODE_ID (TEMP, ch$ptr (DATA [LB_HOST],, 8));
PTR = ch$ptr (DATA [LB_HOST],, 8);
if (ch$rchar_a (PTR) eqlu 0) and
(ch$rchar_a (PTR) eqlu 0)
then
begin
PTR = NMU$NETWORK_LOCAL();
ch$move (ch$rchar (ch$plus (.PTR, 2)) + 3, .PTR, ch$ptr (DATA [LB_HOST],, 8));
end;
end;
!
! Open the image file.
!
if not FILE_OPEN (FB) then return $false;
!
! Read the image base address, size of image and transfer address.
! If anything looks wrong .. make the load fail.
!
if not FILE_READ_LABEL (FB) then ABORT (FB);
!
! If we need a RPM before loading, try to get it now.
! First send an ASSISTANCE VOLUNTEER
if .DATA [SB_NEED_RPM] then
if not (WRITE_ASSISTANCE_VOLUNTEER (.DATA)) then ABORT (FB);
!
! Do the load
!
begin
local
LOAD_NUMBER;
!
! Send the image file to the target system.
! If no failure occured then start the program just
! loaded.
!
begin
local
MOP_MSG_LEN,
LENGTH;
if .DATA [SB_SRVC_CKT_DEVICE] eql DEVTYP_NI
then MOP_MSG_LEN = NI_MOP_LOAD_DATA_LENGTH
else MOP_MSG_LEN = DTE_MOP_LOAD_DATA_LENGTH;
!
! Start at the beginning of the load.
!
LOAD_NUMBER = 0;
LENGTH = 0;
!
! Loop reading from the image file and passing it on
! to the target system.
!
until %cmpi32 (FB[FB_BYTES_LEFT], leq, 0) do
begin
!
! Read in the next load message if the load number has
! been incremented.
!
if .LENGTH eql 0
then
begin
local
BUFFER_PTR;
BUFFER_PTR = .DATA [SB_BUFFER_PTR];
PUTB (LOAD_WITHOUT_TRANSFER, BUFFER_PTR);
PUTB (.LOAD_NUMBER, BUFFER_PTR);
PUT32 (FB[FB_CURRENT_ADDRESS], BUFFER_PTR);
LENGTH = .MOP_MSG_LEN;
if %cmpi32 (FB[FB_BYTES_LEFT], leq, .LENGTH)
then %movf32 (FB[FB_BYTES_LEFT], LENGTH);
if 0 geq NMU$FILE_READ (.FB[FB_FILE_HANDLE], .BUFFER_PTR,
.LENGTH, .FB[FB_RESPONSE_PTR])
then begin
$RESPONSE_X (.FB[FB_RESPONSE_PTR], NICE$_FIO, .FB[FB_FILE_TYPE],
'Could not read image file', 119);
ABORT (FB);
end;
%addi32 (.LENGTH, FB[FB_CURRENT_ADDRESS]);
LENGTH = .LENGTH + 6;
end;
%(do a $NMU_DLX_WRITE_READ)%
!
! Write the load memory message to the target node, and read the
! acknowledgement.
!
begin
local RESULT;
RESULT = WRITE_MOP_MESSAGE (.DATA, .LENGTH, .LOAD_NUMBER);
if (.RESULT lss 0) then ABORT (FB);
if .RESULT neq REQUEST_MEMORY_LOAD
then begin
$RESPONSE_X (.DATA [SB_RESPONSE_PTR], NICE$_LPE, 0,
'Invalid MOP response to MEMORY LOAD',
109);
ABORT (FB);
end;
end;
LOAD_NUMBER = (.LOAD_NUMBER + 1) and %o'377';
%subi32 ((.LENGTH-6), FB[FB_BYTES_LEFT]);
LENGTH = 0;
end;
end;
FILE_CLOSE (FB);
!
! Okay, image loaded. Now give him the parameters and start him up.
!
begin
local
BUFFER_PTR, LENGTH;
BUFFER_PTR = .DATA [SB_BUFFER_PTR];
if .FILE_TYPE eql FILE_TERTIARY_LOADER
then
begin
local LOAD_ADDRESS;
LOAD_ADDRESS = 0;
!
! Put "memory load with transfer" MOP message code
! and the load number into MOP buffer.
!
PUTB (LOAD_WITH_TRANSFER, BUFFER_PTR);
PUTB (.LOAD_NUMBER, BUFFER_PTR);
PUT32 (LOAD_ADDRESS, BUFFER_PTR); ! Null Load address
PUT32 (FB[FB_TRANSFER_ADDRESS], BUFFER_PTR);
end
else
begin
!
! Put "parameters with transfer" MOP message code
! and the load number into MOP buffer.
!
PUTB (PARAMETERS_WITH_TRANSFER, BUFFER_PTR);
PUTB (.LOAD_NUMBER, BUFFER_PTR);
! Put target node number, if we have any
if .TARGET_NUMBER neq 0
then begin
PUTB (2, BUFFER_PTR); ! Target node number
PUTB (2, BUFFER_PTR);
PUTB (GETB (TARGET_NUMBER), BUFFER_PTR);
! Check SERVICE NODE VERSION
if .DATA[SB_NODE_VERSION] eql 1
then PUTB (GETB (TARGET_NUMBER), BUFFER_PTR) ! OK if PHASE IV
else begin
local TEMP; ! Not PHASE IV....
TEMP = GETB (TARGET_NUMBER); ! Get high byte
TEMP = .TEMP and %B'00000011'; ! Only want the low two
PUTB (.TEMP, BUFFER_PTR); ! Put it in sans Area Number
end;
end;
! Now put in node name, if any
if .TARGET_NAME neq 0
then if (LENGTH = GETB (TARGET_NAME)) neq 0
then begin
PUTB (1, BUFFER_PTR); ! Target node name
PUTB (.LENGTH, BUFFER_PTR);
BUFFER_PTR = ch$move (.LENGTH,
.TARGET_NAME,
.BUFFER_PTR);
end;
! There should always be a host name
if (LENGTH = ch$rchar (ch$ptr (DATA [LB_HOST], 2, 8))) neq 0
then begin
PUTB (3, BUFFER_PTR); ! Host node name
PUTB (.LENGTH, BUFFER_PTR);
BUFFER_PTR = ch$move (.LENGTH,
ch$ptr (DATA [LB_HOST], 3, 8),
.BUFFER_PTR);
end;
! There should also always be a host number
PUTB (4, BUFFER_PTR); ! Host node number
PUTB (2, BUFFER_PTR);
PUTB (ch$rchar (ch$ptr (DATA [LB_HOST], 0, 8)), BUFFER_PTR);
if .DATA[SB_NODE_VERSION] eql 1 ! Check SERVICE NODE VERSION
then PUTB (ch$rchar (ch$ptr (DATA [LB_HOST], 1, 8)), BUFFER_PTR)
else begin
local TEMP; ! Not PHASE IV....
TEMP = ch$rchar (ch$ptr (DATA [LB_HOST], 1, 8)); ! Get high byte of Host Number
TEMP = .TEMP and %B'00000011'; ! Only want the low two bits
PUTB (.TEMP, BUFFER_PTR); ! Put it in sans Area Number
end;
! Put in END MARK
PUTB (0, BUFFER_PTR); ! End of parameters
! And then transfer address
PUT32 (FB[FB_TRANSFER_ADDRESS], BUFFER_PTR);
end;
BUFFER_PTR = ch$diff (.BUFFER_PTR, .DATA [SB_BUFFER_PTR]);
!
! Write the message to the target node, and read the
! acknowledgement.
!
begin
local RESULT;
RESULT = WRITE_MOP_MESSAGE (.DATA, .BUFFER_PTR, .LOAD_NUMBER);
if .RESULT lss 0 then return $false;
if (.RESULT eql REQUEST_MEMORY_LOAD and .FILE_TYPE neq FILE_SYSTEM_IMAGE)
then
begin
$RESPONSE_X (.DATA [SB_RESPONSE_PTR], NICE$_LPE, 0,
'Invalid MOP response to MEMORY LOAD WITH TRANFER ADDRESS',
109);
return $false;
end;
if (.RESULT eql REQUEST_PROGRAM and .FILE_TYPE neq FILE_TERTIARY_LOADER)
then
begin
$RESPONSE_X (.DATA [SB_RESPONSE_PTR], NICE$_LPE, 0,
'Invalid MOP response to PARAMETER LOAD WITH TRANFER ADDRESS',
109);
return $false;
end;
end;
end;
end;
$true
end;
%routine ('WRITE_ASSISTANCE_VOLUNTEER', DATA : ref SERVICE_DATA_BLOCK) : NML_LKG_DB =
!++
! Functional description:
!
! This routine writes an assistance volunteer to the target node and
! attempts to read an RPM back.
!
! Formal parameters:
!
! .DATA Addres of load data block
!
! Implicit inputs: none
!
! Routine value:
!
! $true RPM received from target node
! $false No RPM received from target. Response code set up.
!
! Side effects: none
!
!--
begin
local BUFFER_PTR, MOP_FUNCTION, RESULT;
BUFFER_PTR = .DATA [SB_BUFFER_PTR];
PUTB (ASSISTANCE_VOLUNTEER, BUFFER_PTR);
if not ($NMU_DLX_WRITE ( .DATA [SB_CIRCUIT_HANDLE],
DLX_DATA,
.DATA [SB_BUFFER_PTR],
1,
.DATA [SB_RESPONSE_PTR]))
then begin
$RESPONSE_X (.DATA [SB_RESPONSE_PTR], NICE$_LCE, 0,
'Timed out waiting for confirming RPM');
return $false;
end;
RESULT = NML$DLW_READ_LDAQ (.DATA [SB_CIRCUIT_HANDLE],
DLX_DATA,
.DATA [SB_BUFFER_PTR],
MOP_BUFFER_LENGTH,
.DATA [SB_RESPONSE_PTR],
.DATA [SB_HARDWARE_ADDRESS]);
if .RESULT lss 0
then
begin
$RESPONSE (.DATA [SB_RESPONSE_PTR], NICE$_LCE);
return $false;
end;
BUFFER_PTR = .DATA [SB_BUFFER_PTR];
MOP_FUNCTION = GETB (BUFFER_PTR);
if .MOP_FUNCTION neq REQUEST_PROGRAM
then begin
$RESPONSE_X (.DATA [SB_RESPONSE_PTR], NICE$_LPE, 0,
'Expected RPM, received = %D', .MOP_FUNCTION);
return $false;
end;
return $true;
end; ! end of WRITE_ASSISTANCE_VOLUNTEER
%routine ('WRITE_MOP_MESSAGE', DATA : ref SERVICE_DATA_BLOCK, LENGTH, LOAD_NUMBER) : NML_LKG_DB =
!++
! Functional description:
!
! This routine transmits writes a MOP message to the open circuit
! and waits for a reply. This routine should only be used to send
! MEMORY_LOAD, MEMORY_LOAD_WITH_TRANSFER_ADDRESS, and
! PARAMETER_LOAD_WITH_TRANSFER messages. Because this routine
! re-transmits it should not be called for seconday loaders.
!
! Formal parameters:
!
! .DATA Addres of load data block
! LENGTH Length of MOP_MESSAGE to write
! LOAD_NUMBER Current segment number in multi-segment load
!
! Implicit inputs: none
!
! Routine value:
!
! -1 Line protocol error(response pointer set up)
! -2 Line communication error (response pointer set up)
! >=0 Function of next MOP message
!
! Side effects: none
!
!--
begin
local
MOP_RESPONSE;
while $true do
begin
local
RESULT,
BUFFER_PTR;
!
! Write the load memory message to the target node, and read the
! acknowledgement. Retransmit until the proper message has been
! acknowledged.
!
decru TIMES from NMU$K_MOP_RETRY_LIMIT to 1 do
begin
NMU$SCHED_PAUSE(); ! Give others a chance
if not $NMU_DLX_WRITE (.DATA [SB_CIRCUIT_HANDLE], DLX_DATA,
.DATA [SB_BUFFER_PTR], .LENGTH,
.DATA [SB_RESPONSE_PTR])
then exitloop RESULT = -1;
RESULT = (if .DATA [SB_SRVC_CKT_DEVICE] eql DEVTYP_NI
then
NML$DLW_READ_LDAQ (.DATA [SB_CIRCUIT_HANDLE],
DLX_DATA,
.DATA [SB_BUFFER_PTR],
MOP_BUFFER_LENGTH,
.DATA [SB_RESPONSE_PTR],
.DATA [SB_HARDWARE_ADDRESS])
else
$NMU_DLX_READ (.DATA [SB_CIRCUIT_HANDLE], DLX_DATA,
.DATA [SB_BUFFER_PTR], MOP_BUFFER_LENGTH,,
.DATA [SB_RESPONSE_PTR]));
if .RESULT neq -2 then exitloop;
end;
if .RESULT lss 0
then
begin
$RESPONSE_X (.DATA[SB_RESPONSE_PTR], NICE$_LCE);
return -2;
end;
!
! If a request for the next memory load comes in, then setup
! the memory load number. Otherwise make the load fail.
!
BUFFER_PTR = .DATA [SB_BUFFER_PTR];
MOP_RESPONSE = GETB (BUFFER_PTR);
selectone .MOP_RESPONSE of
set
[REQUEST_PROGRAM] :
begin
exitloop;
end;
[REQUEST_MEMORY_LOAD] :
begin
local
LOADNUM;
LOADNUM = GETB (BUFFER_PTR);
if .LOADNUM neq .LOAD_NUMBER
then
begin
if .LOADNUM neq ((.LOAD_NUMBER+1) and %o'377')
then
begin
$RESPONSE_X (.DATA [SB_RESPONSE_PTR], NICE$_LPE, 0,
'Invalid load number requested', 108);
return -1;
end
else exitloop;
end;
end;
[otherwise] :
begin
$RESPONSE_X (.DATA [SB_RESPONSE_PTR], NICE$_LPE, 0,
'Invalid MOP response to MEMORY LOAD', 109);
return -1;
end;
tes;
end;
return .MOP_RESPONSE;
end;
%routine ('CONSOLE_IMAGE_LOAD', DATA : ref SERVICE_DATA_BLOCK, FILE_TYPE, FILE) : NML_LKG_DB =
!++
! Functional description:
!
! This routine is called by the LOAD_NODE routine to perform
! a core image transfer TO a target node. The images that
! this routine sends are for REMOTE CONSOLE SYSTEM IMAGE.
!
! Formal parameters
!
! .DATA Address of load data block
! .FILE_TYPE Type of file for error response
! .FILE Pointer to ASCIZ file name
!
! Implicit inputs: none
!
! Routine value:
!
! $true image was sent to node successfully
! $false failure while sending image
!
! Side effects: none
!
!--
begin
macro
ABORT (FB) =
begin
FILE_CLOSE (FB);
return $false
end %;
local
BUFFER_PTR,
BYTE_BUFFER,
FB : FILE_DATA_BLOCK,
LOAD_NUMBER,
PTR,
RECORD_LEN,
TEMP,
TRANSFER_ADDRESS;
!
! Get the needed information for the load
!
FB[FB_RESPONSE_PTR] = .DATA [SB_RESPONSE_PTR];
FB[FB_FILE_TYPE] = .FILE_TYPE;
FB[FB_FILE] = .FILE;
!
! Open the image file.
!
if not FILE_OPEN (FB) then return $false;
!
! If we need a RPM before loading, try to get it now.
! First send an ASSISTANCE VOLUNTEER
if .DATA [SB_NEED_RPM] then
if not (WRITE_ASSISTANCE_VOLUNTEER (.DATA)) then ABORT (FB);
!
! Begin loading at 0
!
LOAD_NUMBER = 0;
while $true do
begin
PTR = ch$ptr (BYTE_BUFFER,, 8);
if 0 geq NMU$FILE_READ (.FB[FB_FILE_HANDLE], .PTR, 2, .FB[FB_RESPONSE_PTR])
then
begin
$RESPONSE_X (.FB[FB_RESPONSE_PTR], NICE$_FIO, .FB[FB_FILE_TYPE],
'Could not read image file', 119);
ABORT (FB);
end;
TEMP = GETW (PTR);
if .TEMP neq 1
then begin
$RESPONSE_X (.FB[FB_RESPONSE_PTR], NICE$_FIO, .FB[FB_FILE_TYPE],
'Could not read image file', 119);
ABORT (FB);
end;
PTR = ch$ptr (BYTE_BUFFER,, 8);
if 0 geq NMU$FILE_READ (.FB[FB_FILE_HANDLE], .PTR, 2, .FB[FB_RESPONSE_PTR])
then
begin
$RESPONSE_X (.FB[FB_RESPONSE_PTR], NICE$_FIO, .FB[FB_FILE_TYPE],
'Could not read image file', 119);
ABORT (FB);
end;
RECORD_LEN = GETW (PTR);
PTR = ch$ptr (BYTE_BUFFER,, 8);
if 0 geq NMU$FILE_READ (.FB[FB_FILE_HANDLE], .PTR, 2, .FB[FB_RESPONSE_PTR])
then
begin
$RESPONSE_X (.FB[FB_RESPONSE_PTR], NICE$_FIO, .FB[FB_FILE_TYPE],
'Could not read image file', 119);
ABORT (FB);
end;
TRANSFER_ADDRESS = GETW (PTR);
if .RECORD_LEN eql 6
then exitloop;
BUFFER_PTR = .DATA [SB_BUFFER_PTR];
PUTB (LOAD_WITHOUT_TRANSFER, BUFFER_PTR);
PUTB (.LOAD_NUMBER, BUFFER_PTR);
PUT32 (TRANSFER_ADDRESS, BUFFER_PTR);
!
! We have already read 6 bytes out of the record that are included
! in the RECORD_LEN field, however, the Length value does not include
! the 1 byte checksum at the end of the record. Read that byte here,
! but it won't get sent with the MOP message.
!
if 0 geq NMU$FILE_READ (.FB[FB_FILE_HANDLE], .BUFFER_PTR,
(.RECORD_LEN - 5), .FB[FB_RESPONSE_PTR])
then
begin
$RESPONSE_X (.FB[FB_RESPONSE_PTR], NICE$_FIO, .FB[FB_FILE_TYPE],
'Could not read image file', 119);
ABORT (FB);
end;
%(do a $NMU_DLX_WRITE_READ)%
!
! Write the load memory message to the target node, and read the
! acknowledgement.
!
begin
local RESULT;
RESULT = WRITE_MOP_MESSAGE (.DATA, .RECORD_LEN, .LOAD_NUMBER);
if (.RESULT lss 0) then ABORT (FB);
if .RESULT neq REQUEST_MEMORY_LOAD
then begin
$RESPONSE_X (.FB[FB_RESPONSE_PTR], NICE$_LPE, 0,
'Invalid MOP response to MEMORY_LOAD',
109);
ABORT (FB);
end;
end;
LOAD_NUMBER = (.LOAD_NUMBER + 1) and %o'377';
end; ! while $true
FILE_CLOSE (FB);
!
! Okay, image loaded. Now give him the parameters and start him up.
!
begin
local
BUFFER_PTR, LENGTH;
BUFFER_PTR = .DATA [SB_BUFFER_PTR];
! Put "parameters with transfer" MOP message code
! and the load number into MOP buffer.
PUTB (PARAMETERS_WITH_TRANSFER, BUFFER_PTR);
PUTB (.LOAD_NUMBER, BUFFER_PTR);
PUTB (0, BUFFER_PTR);
PUT32 (TRANSFER_ADDRESS, BUFFER_PTR);
begin
local RESULT;
RESULT = WRITE_MOP_MESSAGE (.DATA, 7, .LOAD_NUMBER);
if .RESULT lss 0 then return $false;
if .RESULT neq REQUEST_MEMORY_LOAD
then begin
$RESPONSE_X (.DATA [SB_RESPONSE_PTR], NICE$_LPE, 0,
'Invalid MOP response to PARAMETER LOAD WITH TRANFER ADDRESS',
109);
return $false;
end;
end;
end;
$true
end;
%routine ('DUMP_NODE', DATA : ref SERVICE_DATA_BLOCK) : NML_LKG_DB =
!++
! Functional description:
!
! This routine is called after the NICE request message has been
! decomposed. It performs the actual dump of a target node
! connected to this (EXECUTOR) node by some circuit.
!
! Formal parameters:
!
! .DATA Address of dump data block
!
! Necessary parameters (must be specified in request or in VDB):
!
! Parameter Name
! --------- ----
!
! 130 Dump Image File ID
! 131 Secondary Dumper ID
!
! Parameters that may be defaulted:
!
! Parameter Name Default Value
! --------- ---- -------------
!
! 135 Dump Beginning Address 0
! 136 Dump Count gotten from target
!
! Implicit inputs: none
!
! Routine value: none
! Side effects: none
!
!--
begin
label
DUMP_REQUEST;
literal
DUMPER_ASSUMED = 0, ! We hope the target can dump
DUMPER_NEEDED = DUMPER_ASSUMED + 1, ! We need to load a secondary dumper
DUMPER_RUNNING = DUMPER_NEEDED + 1, ! Secondary dumper is loaded
DUMPER_READY = DUMPER_RUNNING + 1, ! Secondary dumper accepting dump requests
DUMPER_BROKEN = DUMPER_READY + 1; ! Target can't be dumped
local
DUMP_COUNT_DEFAULTED,
DUMPER_STATE,
FB : FILE_DATA_BLOCK,
SECONDARY_DUMPER,
SERVICE_DEVICE;
FB[FB_RESPONSE_PTR] = .DATA[SB_RESPONSE_PTR];
FB[FB_FILE_TYPE] = FILE_DUMP_IMAGE;
if .DATA [SB_SRVC_CKT_DEVICE] eql DEVTYP_DTE
then if not CPU_IS_PDP11 (.DATA) then return $false;
if (SERVICE_DEVICE = .DATA [LB_SERVICE_DEVICE]) lss 0
then
if not GET_VDB (ENTITY_NODE,
.DATA [SB_NODE_DATA],
112,
SERVICE_DEVICE)
then
SERVICE_DEVICE = -1;
if (FB[FB_FILE] = .DATA [DB_DUMP_FILE]) eql 0
then
if not GET_VDB (ENTITY_NODE,
.DATA [SB_NODE_DATA],
130,
FB[FB_FILE])
then
begin
$RESPONSE_X (.DATA[SB_RESPONSE_PTR], NICE$_PAM, 130);
return $false
end;
if (SECONDARY_DUMPER = .DATA [DB_SECONDARY_DUMPER]) eql 0
then
if not GET_VDB (ENTITY_NODE,
.DATA [SB_NODE_DATA],
131,
SECONDARY_DUMPER)
then
SECONDARY_DUMPER = 0;
!
! Set dump limits.
!
begin
local
PTR;
own NEG1: THIRTY_TWO_BIT;
%movi32 (0, NEG1);
%subi32 (1, NEG1);
%mov32 (DATA[DB_DUMP_ADDRESS], FB[FB_CURRENT_ADDRESS]);
if %cmp32 (DATA[DB_DUMP_ADDRESS], eql, NEG1)
then
if not GET_VDB (ENTITY_NODE,
.DATA [SB_NODE_DATA],
135,
FB[FB_CURRENT_ADDRESS])
then %movi32 (0, FB[FB_CURRENT_ADDRESS]);
DUMP_COUNT_DEFAULTED = $true;
%mov32 (DATA[DB_DUMP_COUNT], FB[FB_BYTES_LEFT]);
if %cmp32 (DATA[DB_DUMP_COUNT], eql, NEG1)
then
if GET_VDB (ENTITY_NODE,
.DATA [SB_NODE_DATA],
136,
FB[FB_BYTES_LEFT])
then
DUMP_COUNT_DEFAULTED = $false
else
begin
%movi32 (%o'76000', FB[FB_BYTES_LEFT]);
%asli32 (3, FB[FB_BYTES_LEFT]);
DUMP_COUNT_DEFAULTED = $true;
end
else
DUMP_COUNT_DEFAULTED = $false;
end;
!
! Open the file if we can.....
!
if not FILE_OPEN (FB) then return $false;
!
! If we need a RPM before dumping, try to get it now.
! First send an ASSISTANCE VOLUNTEER
if .DATA [SB_NEED_RPM]
then begin
local BUFFER_PTR, MOP_FUNCTION;
BUFFER_PTR = .DATA [SB_BUFFER_PTR];
PUTB (ASSISTANCE_VOLUNTEER, BUFFER_PTR);
$NMU_DLX_WRITE ( .DATA [SB_CIRCUIT_HANDLE],
DLX_DATA,
.DATA [SB_BUFFER_PTR],
1,
.DATA [SB_RESPONSE_PTR]);
if NML$DLW_READ_LDAQ (.DATA [SB_CIRCUIT_HANDLE],
DLX_DATA,
.DATA [SB_BUFFER_PTR],
MOP_BUFFER_LENGTH,
.DATA [SB_RESPONSE_PTR],
.DATA [SB_HARDWARE_ADDRESS]) gtr 0
then begin
BUFFER_PTR = .DATA [SB_BUFFER_PTR];
MOP_FUNCTION = GETB (BUFFER_PTR);
if .MOP_FUNCTION neq REQUEST_DUMP_SERVICE
then begin
$RESPONSE_X (.DATA [SB_RESPONSE_PTR], NICE$_LPE, 0,
'Expected RPM, received = %D', .MOP_FUNCTION);
return $false;
end;
end
else begin
$RESPONSE_X (.DATA [SB_RESPONSE_PTR], NICE$_LPE, 0,
'Timed out waiting for confirming RPM');
return $false;
end;
end;
!
! Until all bytes have been dumped
! Send a dump request for the next block of memory
! Receive the dump data
! Validate the dump data response
! Put data into dump image file
!
!
$RESPONSE (.DATA [SB_RESPONSE_PTR], NICE$_SUC);
DUMPER_STATE = DUMPER_ASSUMED;
while %cmpi32 (FB[FB_BYTES_LEFT], gtr, 0)
do
case .DUMPER_STATE from DUMPER_ASSUMED to DUMPER_READY of
set
!
! If we need to load the secondary dumper and there is one,
! then do so. Otherwise give up.
!
[DUMPER_NEEDED] :
if .SECONDARY_DUMPER eqla 0
then
begin
! If NI device, then we don't need a secondary loader
! so just proceed to DUMPER_RUNNING state
if .DATA [SB_SRVC_CKT_DEVICE] eql DEVTYP_NI
then DUMPER_STATE = .DUMPER_STATE + 1
else begin
$RESPONSE_X (.DATA[SB_RESPONSE_PTR], NICE$_PAM, 131);
exitloop;
end;
end
else
if SECONDARY_LOAD (.DATA,
FILE_SECONDARY_DUMPER,
.SECONDARY_DUMPER,
DUMP_)
then begin
$RESPONSE (.DATA[SB_RESPONSE_PTR], NICE$_SUC);
DUMPER_STATE = .DUMPER_STATE + 1;
end
else exitloop;
!
! Construct and send the REQUEST DUMP message
!
[DUMPER_ASSUMED, DUMPER_RUNNING, DUMPER_READY] :
DUMP_REQUEST:begin
local
BUF_PTR,
DUMP_LENGTH,
MOP_MSG_LEN,
RESULT;
if .DATA [SB_SRVC_CKT_DEVICE] eql DEVTYP_NI
then MOP_MSG_LEN = NI_MOP_LOAD_DATA_LENGTH
else MOP_MSG_LEN = DTE_MOP_LOAD_DATA_LENGTH;
BUF_PTR = .DATA [SB_BUFFER_PTR];
PUTB (REQUEST_DUMP, BUF_PTR);
PUT32 (FB[FB_CURRENT_ADDRESS], BUF_PTR);
%mov32 (FB[FB_BYTES_LEFT], DUMP_LENGTH);
if %cmpi32 (DUMP_LENGTH, gtr, .MOP_MSG_LEN)
then %movi32 (.MOP_MSG_LEN, DUMP_LENGTH);
PUTW (DUMP_LENGTH, BUF_PTR);
%(do a $NMU_DLX_WRITE_READ)%
decru TIMES from NMU$K_MOP_RETRY_LIMIT to 1 do begin
NMU$SCHED_PAUSE(); ! Let the others in first
if .DUMPER_STATE neq DUMPER_RUNNING
then
begin
if not $NMU_DLX_WRITE (.DATA [SB_CIRCUIT_HANDLE], DLX_DATA,
.DATA [SB_BUFFER_PTR], 7,
.DATA [SB_RESPONSE_PTR])
then exitloop RESULT = -1;
end
else
DUMPER_STATE = .DUMPER_STATE + 1;
RESULT = (if .DATA [SB_SRVC_CKT_DEVICE] eql DEVTYP_NI
then
NML$DLW_READ_LDAQ (.DATA [SB_CIRCUIT_HANDLE], DLX_DATA,
.DATA [SB_BUFFER_PTR], MOP_BUFFER_LENGTH,
.DATA [SB_RESPONSE_PTR],
.DATA [SB_HARDWARE_ADDRESS])
else
$NMU_DLX_READ (.DATA [SB_CIRCUIT_HANDLE], DLX_DATA,
.DATA [SB_BUFFER_PTR], MOP_BUFFER_LENGTH,,
.DATA [SB_RESPONSE_PTR]));
if .RESULT neq -2 then exitloop;
end;
if .RESULT leq 0
then
leave DUMP_REQUEST with DUMPER_STATE = .DUMPER_STATE + 1;
begin
local
BUF_PTR;
BUF_PTR = .DATA [SB_BUFFER_PTR];
selectone GETB (BUF_PTR) of
set
! MOP_MODE_RUNNING and REQUEST_DUMP_SERVICE are the same MOP function
! [MOP_MODE_RUNNING] :
[REQUEST_DUMP_SERVICE] :
if .RESULT geq 8
then
begin
local
MEMZISE : THIRTY_TWO_BIT,
TEMP;
bind
DEVTYPE = TEMP,
MOPVER = TEMP,
FEATURES = TEMP;
DEVTYPE = GETB (BUF_PTR);
if (.SERVICE_DEVICE geq 0) and
(.SERVICE_DEVICE neq .DEVTYPE)
then
begin
$RESPONSE (.DATA [SB_RESPONSE_PTR], NICE$_LPE);
exitloop;
end;
if GETB (BUF_PTR) neq 1
then
begin
$RESPONSE (.DATA [SB_RESPONSE_PTR], NICE$_LPE);
exitloop;
end;
GET32 (BUF_PTR, MEMZISE);
FEATURES = GETB (BUF_PTR);
if not .FEATURES <1, 1>
then
leave DUMP_REQUEST with DUMPER_STATE = .DUMPER_STATE + 1;
if .DUMP_COUNT_DEFAULTED
then
begin
%mov32 (MEMZISE, FB[FB_BYTES_LEFT]);
%sub32 (FB[FB_CURRENT_ADDRESS], FB[FB_BYTES_LEFT]);
end;
end;
[MEMORY_DUMP_DATA] :
begin
local
DUMPED_ADDRESS : THIRTY_TWO_BIT;
RESULT = .RESULT - 5;
if .RESULT lss 0 then exitloop;
!
! Check for the correct dump address
! Adjust dump address for next dump request
!
GET32 (BUF_PTR, DUMPED_ADDRESS);
if %cmp32 (DUMPED_ADDRESS, neq, FB[FB_CURRENT_ADDRESS])
then
begin
$RESPONSE_X (.DATA [SB_RESPONSE_PTR], NICE$_LPE, 0,
'Address received in MEMORY DUMP DATA is incorrect', 117);
exitloop;
end;
%addi32 (.RESULT, FB[FB_CURRENT_ADDRESS]);
%subi32 (.RESULT, FB[FB_BYTES_LEFT]);
!
! Write data to image file
!
if not NMU$FILE_WRITE (.FB[FB_FILE_HANDLE], .BUF_PTR, .RESULT, .FB[FB_RESPONSE_PTR])
then leave DUMP_REQUEST with DUMPER_STATE = .DUMPER_STATE + 1;
end;
[otherwise] :
leave DUMP_REQUEST with DUMPER_STATE = .DUMPER_STATE + 1;
tes;
end;
end;
!
! The dumper is broken! Long live the dumper!
!
[inrange, outrange] :
exitloop;
tes;
! End of 'WHILE bytes left to dump' loop
! If a dumped a NI device, then send 'dump complete'
if .DATA [SB_SRVC_CKT_DEVICE] eql DEVTYP_NI
then begin
local BUF_PTR;
BUF_PTR = .DATA [SB_BUFFER_PTR];
PUTB (DUMP_COMPLETE, BUF_PTR);
$NMU_DLX_WRITE ( .DATA [SB_CIRCUIT_HANDLE],
DLX_DATA,
.DATA [SB_BUFFER_PTR],
1,
.DATA [SB_RESPONSE_PTR]);
end;
!
! Close dump file
!
FILE_CLOSE (FB);
$true
end; !End of DUMP_NODE
%routine ('EXECUTE_TRIGGER', TB :ref SERVICE_DATA_BLOCK, RTN) : NML_LKG_DB novalue =
!++
! Functional description:
!
! This routine is called after the NICE request message has been
! decomposed. It attempts an OPEN to the Data Link Layer using
! both the PHYSICAL ETHERNET ADDRESS and the HARDWARE ADDRESS.
! If the open is successful, TRIGGER_NODE is called to actually
! perform the function. This code used to reside in NML$TRIGGER.
! It was broken out into a separate routine to give the LOAD_NODE
! routine an entry point to perform a TRIGGER function if it needs
! to do so ( i.e. target node does not respond to the first MEMORY
! LOAD message.)
!
! Formal parameters:
!
! .TB Address of a SSERVICE_DATA_BLOCK
! .RTN Address of location to store Return Values
!
! Implicit inputs: none
!
! Routine value: none
! Side effects: none
!
!--
begin
bind
RTN_COD = .RTN;
RTN_COD = NICE$_SUC;
TB [SB_USAGE] = DLX_TRIGGER;
!
! Open the link if we can
!
if not CIRCUIT_OPEN (.TB)
then
RTN_COD = ch$rchar (.TB [SB_RESPONSE_PTR]);
!
! Execute the load.
! Deallocate the buffers.
!
if .RTN_COD eql NICE$_SUC
then
begin
TRIGGER_NODE (.TB);
RTN_COD = ch$rchar (.TB [SB_RESPONSE_PTR]);
CIRCUIT_CLOSE (.TB);
end;
!
! Do it again for the HARDWARE ADDRESS
!
RTN_COD = NICE$_SUC; ! Reset return code
TB [SB_PHY_ADDR] = .TB [SB_HARDWARE_ADDRESS];
if not CIRCUIT_OPEN (.TB)
then
RTN_COD = ch$rchar (.TB [SB_RESPONSE_PTR]);
!
! Execute the load.
! Deallocate the buffers.
!
if .RTN_COD eql NICE$_SUC
then
begin
TRIGGER_NODE (.TB);
RTN_COD = ch$rchar (.TB [SB_RESPONSE_PTR]);
CIRCUIT_CLOSE (.TB);
end;
end; ! End of EXECUTE_TRIGGER
%routine ('TRIGGER_NODE', DATA : ref SERVICE_DATA_BLOCK) : NML_LKG_DB =
!++
! Functional description:
!
! This routine is called after the NICE request message has been
! decomposed. It performs the bootstrap ROM trigger function
! on a target node.
!
! Formal parameters:
!
! .DATA Address of trigger data block
!
! Implicit inputs: none
!
! Routine value: none
! Side effects: none
!
!--
begin
if .DATA [SB_SERVICE_PASSWORD] eql 0
then
begin
if not GET_VDB (ENTITY_NODE,
.DATA [SB_NODE_DATA],
111,
DATA [SB_SERVICE_PASSWORD])
then
begin
$RESPONSE (.DATA [SB_RESPONSE_PTR], NICE$_PAM, 111);
return $false;
end;
end;
begin
local
PASSWORD_PTR,
BUFFER_PTR;
BUFFER_PTR = .DATA [SB_BUFFER_PTR];
PASSWORD_PTR = .DATA [SB_SERVICE_PASSWORD];
PUTB (ENTER_MOP_MODE, BUFFER_PTR);
decr COUNT from 8 to 1 do
PUTB (GETB (PASSWORD_PTR), BUFFER_PTR);
PUTB (0, BUFFER_PTR); ! Write PROCESSOR field
PUTB (0, BUFFER_PTR); ! Write CONTROL field
PUTB (-1, BUFFER_PTR); ! Write SOFTWARE ID field
end;
if not $NMU_DLX_WRITE (.DATA [SB_CIRCUIT_HANDLE], DLX_DATA,
.DATA [SB_BUFFER_PTR], 12,
.DATA [SB_RESPONSE_PTR])
then
return $false;
$RESPONSE (.DATA [SB_RESPONSE_PTR], NICE$_SUC);
$true
end; !End of TRIGGER_NODE
%routine ('FILE_OPEN', FB : ref FILE_DATA_BLOCK) : NML_LKG_DB =
!++
! Functional description
!
! This routine opens the file.
!
! Formal parameters
!
! .FB Address of the file data block
!
! Implicit inputs: none
!
! Routine value:
!
! $true File opened
! $false Open failure - response set
!
! Side effects: none
!
!--
begin
local
FILE_HANDLE;
FILE_HANDLE = NMU$FILE_OPEN (.FB[FB_FILE_TYPE],
0 %(not required)%,
.FB[FB_FILE],
.FB[FB_RESPONSE_PTR]);
if .FILE_HANDLE eql 0 then return $false;
FB[FB_FILE_HANDLE] = .FILE_HANDLE;
$true
end; !End of FILE_OPEN
%routine ('FILE_READ_LABEL', FB : ref FILE_DATA_BLOCK) : NML_LKG_DB =
!++
! Functional description
!
! This routine reads the load parameters from a .SYS image
! file. When this routine completes (successfully) the
! file pointer is positioned at the start of the load image.
!
!
! Formal parameters
!
! .FB Address of the load data block
!
! Implicit inputs: none
!
! Routine value:
!
! $true Parameters read from file and put in load data block
! $false Failure while reading parameters
!
! Side effects: none
!
!--
begin
local
BYTE_BUFFER;
!
! Skip to and read the base address where image is to be loaded
!
if not NMU$FILE_SEEK (.FB[FB_FILE_HANDLE], L$BSA, .FB[FB_RESPONSE_PTR])
then return $false;
begin
local
PTR;
PTR = ch$ptr (BYTE_BUFFER,, 8);
if 0 geq NMU$FILE_READ (.FB[FB_FILE_HANDLE], .PTR, 2, .FB[FB_RESPONSE_PTR])
then
begin
$RESPONSE_X (.FB[FB_RESPONSE_PTR], NICE$_FIO, .FB[FB_FILE_TYPE],
'Could not read image file', 119);
return $false;
end;
%movi32 (GETW (PTR), FB[FB_CURRENT_ADDRESS]);
end;
!
! Skip to and read the number of bytes in the image
!
if not NMU$FILE_SEEK (.FB[FB_FILE_HANDLE], L$BLDZ, .FB[FB_RESPONSE_PTR])
then return $false;
begin
local
PTR;
PTR = ch$ptr (BYTE_BUFFER,, 8);
if 0 geq NMU$FILE_READ (.FB[FB_FILE_HANDLE], .PTR, 2, .FB[FB_RESPONSE_PTR])
then
begin
$RESPONSE_X (.FB[FB_RESPONSE_PTR], NICE$_FIO, .FB[FB_FILE_TYPE],
'Could not read image file', 119);
return $false;
end;
%movi32 (GETW (PTR), FB[FB_BYTES_LEFT]);
end;
%asli32 (6, FB[FB_BYTES_LEFT]);
!
! Skip to and read the flags word in the header
!
if not NMU$FILE_SEEK (.FB[FB_FILE_HANDLE], L$BFLG, .FB[FB_RESPONSE_PTR])
then return $false;
begin
local
PTR,
VALUE;
PTR = ch$ptr (BYTE_BUFFER,, 8);
if 0 geq NMU$FILE_READ (.FB[FB_FILE_HANDLE], .PTR, 2, .FB[FB_RESPONSE_PTR])
then
begin
$RESPONSE_X (.FB[FB_RESPONSE_PTR], NICE$_FIO, .FB[FB_FILE_TYPE],
'Could not read image file', 119);
return $false;
end;
VALUE = GETW (PTR);
if .VALUE <14, 1> eql 0
then
begin
$RESPONSE_X (.FB[FB_RESPONSE_PTR], NICE$_IFC, .FB[FB_FILE_TYPE],
'Header found in image file', 111);
return $false;
end;
end;
!
! Skip to and read the transfer address for the image
!
if not NMU$FILE_SEEK (.FB[FB_FILE_HANDLE], L$BXFR, .FB[FB_RESPONSE_PTR])
then return $false;
begin
local
TEMP,
PTR;
PTR = ch$ptr (BYTE_BUFFER,, 8);
if 0 geq NMU$FILE_READ (.FB[FB_FILE_HANDLE], .PTR, 2, .FB[FB_RESPONSE_PTR])
then
begin
$RESPONSE_X (.FB[FB_RESPONSE_PTR], NICE$_FIO, .FB[FB_FILE_TYPE],
'Could not read image file', 119);
return $false;
end;
TEMP = GETW (PTR);
%movt32 (TEMP, FB[FB_TRANSFER_ADDRESS]);
end;
!
! Skip to and read the block offset to the image in file (512 bytes
! per block).
!
if not NMU$FILE_SEEK (.FB[FB_FILE_HANDLE], L$BBLK, .FB[FB_RESPONSE_PTR])
then return $false;
begin
local
PTR;
PTR = ch$ptr (BYTE_BUFFER,, 8);
if 0 geq NMU$FILE_READ (.FB[FB_FILE_HANDLE], .PTR, 2, .FB[FB_RESPONSE_PTR])
then
begin
$RESPONSE_X (.FB[FB_RESPONSE_PTR], NICE$_FIO, .FB[FB_FILE_TYPE],
'Could not read image file', 119);
return $false;
end;
BYTE_BUFFER = GETW (PTR) * 512;
end;
if not NMU$FILE_SEEK (.FB[FB_FILE_HANDLE], .BYTE_BUFFER, .FB[FB_RESPONSE_PTR])
then return $false;
$true
end; !End of FILE_READ_LABEL
%routine ('FILE_CLOSE', FB : ref FILE_DATA_BLOCK) : NML_LKG_DB =
!++
! Functional description
!
! This routine closes the file.
!
! Formal parameters
!
! .FB Address of the file data block
!
! Implicit inputs: none
!
! Routine value:
!
! $true Parameters read from file and put in load data block
! $false Failure while reading parameters
!
! Side effects: none
!
!--
begin
NMU$FILE_CLOSE (.FB[FB_FILE_HANDLE], .FB[FB_RESPONSE_PTR]);
$true
end; !End of FILE_CLOSE
%routine ('FETCH_PARAMETERS', REQ : ref REQUEST_BLOCK, DB : ref SERVICE_DATA_BLOCK, PRM : ref vector) =
!++
! Functional description:
!
! This routine extracts the parameters supplied in the NICE request
! message, checks to make sure they are applicable to the request,
! and stores them in the service block.
!
! Formal parameters:
!
! .REQ NML Request Block address
! .DB dump/load/trigger block address
! .PRM address of plit vector with acceptable parameter numbers
!
! Implicit inputs: none
!
! Routine value:
!
! NICE return code.
!
! Side effects: none
!
!--
begin
local
ENTITY_TYPE,
PARM_NO,
PARM_DATA: THIRTY_TWO_BIT;
ENTITY_TYPE =.REQ[RB_NICE_ENTITY_TYPE] ; ! Save real entity type
REQ[RB_NICE_ENTITY_TYPE] = ENTITY_NODE ; ! Parameters are all NODE
while GET_NEXT_PARAMETER (.REQ, PARM_NO, PARM_DATA)
do
begin
selectone
begin
local
ADR : ref vector,
CNT;
ADR = .PRM;
CNT = .ADR [-1];
do
begin
local
VAL;
VAL = .ADR [0];
ADR = ADR [1];
if .PARM_NO eql .VAL then exitloop .VAL;
end
while (CNT = .CNT - 1) neq 0
end
of
set
[10]: ! PHYSICAL ADDRESS
begin
if GETB (PARM_DATA) neq 6 ! It must be HI-6
then
begin
$RESPONSE (.DB[SB_RESPONSE_PTR], $NICE$ERR_IMF);
exitloop;
end;
DB[SB_PHY_ADDR] = .PARM_DATA; ! Save pointer to data
end;
[110]: ! SERVICE CIRCUIT
DB[SB_SERVICE_CIRCUIT] = .PARM_DATA ;
[111]: ! SERVICE PASSWORD
DB[SB_SERVICE_PASSWORD] = .PARM_DATA ;
[112]: ! SERVICE DEVICE
DB[LB_SERVICE_DEVICE] = .PARM_DATA ;
[113]: ! CPU
selectone ch$rchar (.PARM_DATA) of
set
[0 to 3] : DB[LB_CPU] = .PARM_DATA;
[otherwise] :
begin
$RESPONSE_X (.DB[SB_RESPONSE_PTR], NICE$_IPV, 113);
exitloop;
end;
tes;
[114]:
DB[SB_HARDWARE_ADDRESS] = .PARM_DATA;
[115]:
DB[SB_NODE_VERSION] = .PARM_DATA ;
[120]: ! LOAD FILE
DB[LB_LOAD_FILE] = .PARM_DATA ;
[121]: ! SECONDARY LOADER
DB[LB_SECONDARY_LOADER] = .PARM_DATA ;
[122]: ! TERTIARY LOADER
DB[LB_TERTIARY_LOADER] = .PARM_DATA ;
[123]: ! DIAGNOSTIC FILE
DB[LB_DIAGNOSTIC_FILE] = .PARM_DATA ;
[125]: ! SOFTWARE TYPE
selectone .PARM_DATA of
set
[0 to 2] : DB[LB_SOFTWARE_TYPE] = .PARM_DATA;
[otherwise] :
begin
$RESPONSE_X (.DB[SB_RESPONSE_PTR], NICE$_IPV, 125);
exitloop;
end;
tes;
[126]: ! SOFTWARE IDENTIFICATION
DB[LB_SOFTWARE_IDENTIFICATION] = .PARM_DATA ;
[130]: ! DUMP FILE
DB[DB_DUMP_FILE] = .PARM_DATA ;
[131]: ! SECONDARY DUMPER
DB[DB_SECONDARY_DUMPER] = .PARM_DATA ;
[135]: ! DUMP ADDRESS
%mov32 (PARM_DATA, DB[DB_DUMP_ADDRESS]);
[136]: ! DUMP COUNT
%mov32 (PARM_DATA, DB[DB_DUMP_COUNT]);
[141]: ! HOST
begin
local
FMT,
NOD_PTR;
NOD_PTR = ch$ptr (DB[LB_HOST],,8) ;
FMT = GETB (PARM_DATA); ! Get node id format byte
selectoneu .FMT of
set
[0]:
begin ! Node address
PUTB (GETB (PARM_DATA), NOD_PTR);
PUTB (GETB (PARM_DATA), NOD_PTR);
PUTB (0,NOD_PTR) ; ! Null node name
end;
[1 to 6]:
begin ! Node name
PUTB (0,NOD_PTR); ! Node address of zero
PUTB (0,NOD_PTR);
PUTB (.FMT,NOD_PTR) ; ! Length of node name
ch$move (.FMT,.PARM_DATA,.NOD_PTR) ;
end;
[otherwise]:
begin
$RESPONSE_X (.DB[SB_RESPONSE_PTR],NICE$_IID,ENTITY_NODE,
'HOST Node Id', 101) ;
exitloop;
end;
tes;
end;
[500]: ! NAME
DB [LB_NAME] = .PARM_DATA;
[502]: ! ADDRESS
DB [LB_ADDRESS] = .PARM_DATA;
[2501]:
DB [LB_CONSOLE_SECONDARY_LOADER] = .PARM_DATA;
[2502]:
DB [LB_CONSOLE_LOAD_FILE] = .PARM_DATA;
[otherwise]:
begin
$RESPONSE_X (.DB[SB_RESPONSE_PTR],NICE$_PNA,.PARM_NO) ;
exitloop;
end;
tes;
end;
REQ[RB_NICE_ENTITY_TYPE] = .ENTITY_TYPE ; ! Restore real entity type
ch$rchar (.DB[SB_RESPONSE_PTR])
end; ! End of FETCH_PARAMETERS
%routine ('GET_NEXT_PARAMETER', REQ : ref REQUEST_BLOCK, PARM_NO, PARM_DATA) =
!++
! Functional description:
!
! Obtains the next parameter in the NICE request message.
!
! Formal parameters:
!
! .REQ The address of the NML Request Block for this request.
! .PARM_NO Address of variable to return parameter number.
! .PARM_DATA Address of variable in which to return parameter data.
!
! Implicit inputs:
!
! .REQ [RB_NICE_PARAMETERS] Contains a pointer to the previous
! parameter.
! .REQ [RB_NICE_PARAMETER_LENGTH] Contains the length of the previous
! parameter in bytes.
!
! Routine value:
!
! $true, if the next parameter exists.
! $false, otherwise.
!
! Side effects: none
!
!--
begin
local
PARM_PTR ; ! Pointer to NICE parameter
REQ[RB_NICE_PARAMETERS] = ch$plus (.REQ[RB_NICE_PARAMETERS],
.REQ[RB_NICE_PARAMETER_LENGTH]) ;
!
! Return false when all parameters have been processed.
!
if ch$diff (.REQ[RB_NICE_PARAMETERS],.REQ[RB_NICE_POINTER]) geq .REQ[RB_NICE_LENGTH]
then begin
REQ[RB_NICE_PARAMETER_LENGTH] = 0 ;
return $false;
end;
!
! Get length of the parameter, to include the data portion plus
! two bytes for the DATA ID field.
!
PARM_PTR = .REQ[RB_NICE_PARAMETERS] ; ! Make copy of pointer
.PARM_NO = GETW (PARM_PTR) ; ! Get parameter number
REQ[RB_NICE_PARAMETER_LENGTH] = NML$PARAMETER_DATA (.REQ[RB_NICE_ENTITY_TYPE],
..PARM_NO,
PARM_PTR,
.PARM_DATA) + 2 ;
!
! If this parameter is a qualifier, then call ourself recursively
! to skip over the qualifier to the next real parameter.
!
if .REQ[RB_NICE_PARAMETERS] eql .REQ[RB_NICE_QUALIFIER]
then return GET_NEXT_PARAMETER (.REQ, .PARM_NO, .PARM_DATA);
return $true
end; !End of GET_NEXT_PARAMETER
%routine ('GET_VDB', ENTITY_TYPE, ENTITY, PAR_NO, RESP_PTR) =
!++
!
! Functional description:
!
! It is possible to downline load nodes that do not have a database entry.
! This is the case for DECSERVER-100's. The code in the NMLDTL module
! needs to fetch many parameters from the node database - if it exists.
!
! This routine is an envelop routine to the NML$GET_VDB_PARAMETER routine.
! It checks if a zero entity ID is supplied. If so, it just returns $false.
! Otherwise, it call NMLVDB.
!
! Parameters are exactly as for call to NML$GET_VEB_PARAMETER
!
!--
return
if .ENTITY eql 0
then $false
else NML$GET_VDB_PARAMETER (.ENTITY_TYPE, .ENTITY, .PAR_NO, .RESP_PTR)
; ! End of GET_VDB
%routine ('SET_SUBSTATE', SB : ref SERVICE_DATA_BLOCK) : NML_LKG_DB novalue =
!++
! Functional description:
!
! Set the substate for a given circuit.
!
! Formal parameters:
!
! .DATA Address of trigger data block
!
! Implicit inputs: none
!
! Routine value: none
! Side effects: none
!
!--
begin
if .SB[SB_SUBSTATE] geq 0
then NML$SET_VDB_PARAMETER (ENTITY_CIRCUIT, .SB[SB_SERVICE_CIRCUIT],
CPARM_SUBSTATE, %ref (.SB[SB_SUBSTATE]))
else NML$CLR_VDB_PARAMETER (ENTITY_CIRCUIT, .SB[SB_SERVICE_CIRCUIT],
CPARM_SUBSTATE);
end; !End of SET_SUBSTATE
%routine ('CPU_IS_PDP11', DB : ref SERVICE_DATA_BLOCK) : NML_LKG_DB =
!++
! Functional description
!
! This routine checks that the CPU parameter is PDP11.
!
! Formal parameters
!
! .DB Address of the service data block
!
! Implicit inputs: none
!
! Routine value:
!
! $true CPU parameter is PDP11
! $false Not PDP11 - response set
!
! Side effects: none
!
!--
begin
local
CPU;
if (CPU = .DB [LB_CPU]) eql -1
then
if not GET_VDB (ENTITY_NODE,
.DB [SB_NODE_DATA],
113,
CPU)
then
begin
$RESPONSE_X (.DB [SB_RESPONSE_PTR], NICE$_PAM, 113);
return $false;
end;
if .CPU neq CPU_PDP11
then
begin
$RESPONSE_X (.DB [SB_RESPONSE_PTR], NICE$_IPV, 113);
return $false;
end;
$true
end; !End of CPU_IS_PDP11
end !End of Module NMLDTL
eludom
! Local Modes:
! Mode:BLISS
! Auto Save Mode:0
! Comment Column:40
! Comment Rounding:+1
! End: