Google
 

Trailing-Edge - PDP-10 Archives - BB-X117B-SB_1986 - 10,7/vnp36/vnp36.bli
There are 2 other files named vnp36.bli in the archive. Click here to see a list.
!DSKB:VNP36.BLI[10,6026], 11-Sep-85 10:19:33, Edit by DAVENPORT
!
! 3A(7)
!	VNP36	- Add binary copyright notice.
!	ALL	- Update source copyright notice.
!
!DSKT:VNP36.BLI[10,6026,VNP36], 15-Mar-84 14:04:20, Edit by DAVENPORT
!
! 3A(6)
!	VNP36	- Fix macro CH$LEN in LOAD_MCBS to search the first
!		  four characters of a process name rather than the
!		  first three characters.  This avoids computing a
!		  negative length which used later in CH$COPY causes
!		  an illegal instruction trap from newer KL ucodes.
!
!DSKT:VNP36.BLI[10,6026,VNP36],  6-Mar-84 10:33:31, Edit by DAVENPORT
!
! 3A(5)
!	VNP36	- Add version to module declaration.
!	BLOCKT	- Fix undeclare statement to only undeclare symbols
!		  if they are already defined.
!
!NET:<DECNET20-V3P0.TKB-VNP.BIGVNP>VNP36.BLI.52 28-Sep-82 16:14:27, Edit by PECKHAM
!NET:<DECNET20-V3P0.TKB-VNP.BIGVNP>VNP36.BLI.51  5-Jun-82 11:15:37, Edit by PECKHAM
!NET:<DECNET20-V3P0.TKB-VNP.BIGVNP>VNP36.BLI.49 26-Mar-82 17:23:05, Edit by PECKHAM
!NET:<DECNET20-V3P0.TKB-VNP.BIGVNP>VNP36.BLI.48 26-Mar-82 16:11:52, Edit by PECKHAM
!NET:<DECNET20-V3P0.TKB-VNP.BIGVNP>VNP36.BLI.46 26-Aug-81 10:03:28, Edit by SROBINSON
!NET:<DECNET20-V3P0.TKB-VNP.VNPV3>VNP36.BLI.41  4-Feb-81 09:07:04, Edit by SROBINSON
!<DECNET20-V3P0.TKB-VNP.VNPV3>VNP36.BLI.39 10-Dec-80 10:50:30, Edit by SROBINSON
!<DECNET20-V3P0.TKB-VNP.VNPV3>VNP36.BLI.2, 29-Apr-80 11:45:29, Edit by SROBINSON
MODULE VNP36 (					!Main Program for VNP
		IDENT = 'X03040',
		VERSION = '3A(7)',
		MAIN = VNP20
		) =
BEGIN
!
!
!
!COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1980,1981,1982,1986. ALL RIGHTS RESERVED.
!
!
!THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
!ONLY  IN  ACCORDANCE  WITH  THE  TERMS  OF  SUCH LICENSE AND WITH THE
!INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR ANY  OTHER
!COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
!OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF THE  SOFTWARE  IS  HEREBY
!TRANSFERRED.
!
!THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT  NOTICE
!AND  SHOULD  NOT  BE  CONSTRUED  AS A COMMITMENT BY DIGITAL EQUIPMENT
!CORPORATION.
!
!DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY  OF  ITS
!SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.
!

!++
! FACILITY: MCB Configuration Facility, VNP20
!
! ABSTRACT:
!
!	This module is the main program for the MCB System Builder
!	which is part of the MCB Configuration Facility.
!
! ENVIRONMENT: TOPS-20 User Mode
!
! AUTHOR: Scott G. Robinson, Creation: 14-APR-80
!
! MODIFIED BY:
!
!	Scott G. Robinson, 10-DEC-80 : VERSION 03xx0
!
! 01	- Add Changes for MCB V3.1 Systems
! 02    - Add Changes for MCB V3.2 Systems
! 03	- Make Big System Changes (>124K Systems)
! 04	- Make all partition names to M_PCB be 6 character ASCIZ names.
!--

!
! TABLE OF CONTENTS:
!

FORWARD ROUTINE
    VNP20 : NOVALUE,				!Main Program
    DEL_BLK,
    DEL_DEV,
    DEL_CTL,
    DEL_UNT,
    LOAD_TSKS,
    LOAD_MCBS;

!
! INCLUDE FILES:
!

LIBRARY 'VNPLIB';

!
! MACROS:
!
!	NONE
!
! EQUATED SYMBOLS:
!

LITERAL
    DEBUG = 0;

!
! OWN STORAGE:
!

GLOBAL
    COPYRIGHT : vector [20]
		initial (%asciz 'COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION, 1984, 1986. ALL RIGHTS RESERVED.');

!
! EXTERNAL REFERENCES:
!

EXTERNAL ROUTINE
    RCOR : NOVALUE,				!Read Core Image
    WCOR : NOVALUE,				!Write Out Core Image
    FCOR : NOVALUE,				!Free A Core Image
    RSTB : NOVALUE,				!Read Symbol Table
    RCET : NOVALUE,				!Read CETAB.MAC
    MCEX : NOVALUE,				!Merge CEX Into Core Image
    GETSYM : NOVALUE,				!Get Symbols From Symbol Tables
    M_PCB,					!Make A Partition Control Block
    INSTAL : NOVALUE,				!Install A Task
    LOADD : NOVALUE,				!Load A Device Driver
    LD_DCB,					!Load a Process Driver
    LODMCB : NOVALUE,				!Load Process's data base
    FCLEAN : NOVALUE,				!Do Final Cleanup Of The Kernel
    TELLK : NOVALUE,				!Tell About The Core Image
    OPEN,					!OPEN A File
    OUTPUT : NOVALUE,				!Output a Character
    OUTSTR : NOVALUE,				!Output a String
    PCRLF : NOVALUE,				!Output a CR/LF
    ERRMSG : NOVALUE,				!Error Message
    CLOSE : NOVALUE,				!CLOSE A File
    INISTG : NOVALUE,				!Initialize Storage Manager
    FND_CHAIN,					!Find A Block In A Chain
    GETBLK,					!Get A Storage Block
    FREBLK : NOVALUE,				!Free A Storage Block
    RESET_ALL,					!Reset All I/O
    DEL_PTRS : NOVALUE,				!Delete Pointer Blocks
    PUTBYT : NOVALUE,				!Put A Byte Into A TSK Image
    GETBYT,					!Get A Byte From A TSK Image
    PUTWRD : NOVALUE,				!Put A Word Into A TSK Image
    GETWRD,					!Get A Word From A TSK Image
    R50TOA,					!Convert RADIX-50 To ASCII
    ALOCB,					!Allocate Some Storage (EXEC DSR)
    SYM_VAL;					!Lookup a symbol in symbol table

ROUTINE VNP20 : NOVALUE = 			!Main Program

!++
! FUNCTIONAL DESCRIPTION:
!
!	Top level program for MCB System Builder.
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS
!
!	Creates the MCB System's Image on disk.
!
!--

    BEGIN

    BIND
	ROUTINE_NAME = UPLIT (%STRING (' VNP36 - ',
	,' Conjuror for MCB V3.2 Systems',
	%IF %SWITCHES(TOPS20) %THEN ' (TOPS-20 Environment Only)',%FI
	%CHAR(0)));

    LOCAL
	CETAB_FILE : REF FILE_BLOCK,
	CEXCOM_FILE : REF FILE_BLOCK,
	KERNEL_FILE : REF FILE_BLOCK,
	LOGGING_FILE : REF FILE_BLOCK,
	RSXMS_FILE : REF FILE_BLOCK,
	MODU_PTR : REF MODU_BLOCK,
	POOL_PCB,
	POOL_PAR_BASE,
	BUF_PCB,
	BUF_PAR_BASE,
	GEN_PCB,
	GEN_PAR_BASE,
	PAR_BLK : VECTOR [4],
	VALUES : REF VNPVAL_BLOCK;

!
! Startout by initializing the support routines, and then allocate static
!  data structures 'stamp coupled' to other levels in the system builder.
!
    RESET_ALL ();
    INISTG (7000);
    VALUES = GETBLK (VNPVAL_TYP, VNPVAL_LEN);
    KERNEL_FILE = GETBLK (FILE_TYP, FILE_LEN);
    LOGGING_FILE = GETBLK (FILE_TYP, FILE_LEN);
    CETAB_FILE = GETBLK (FILE_TYP, FILE_LEN);
    CEXCOM_FILE = GETBLK (FILE_TYP, FILE_LEN);
    RSXMS_FILE = GETBLK (FILE_TYP, FILE_LEN);
!
! Open the terminal Logging File: All output through channel 0 will go
! here also...
!
    CH$MOVE (10, CH$PTR (UPLIT (%ASCIZ'MCBMAP.TXT')), CH$PTR (LOGGING_FILE [FILE_NAME]));
    OPEN (1, LOGGING_FILE [FILE_NAME], 1, 1, UPLIT (%ASCIZ'TXT'));
!
! Say who we are...
!
    OUTSTR (0, ROUTINE_NAME);
    PCRLF (0);
!
! Read CETAB.MAC to determine the configuration of the system being
!  constructed and store the textual information in our data bases.
!
    OUTSTR (0, UPLIT (%ASCIZ'[Reading Configuration File]'));
    PCRLF (0);
    CH$MOVE (10, CH$PTR (UPLIT (%ASCIZ'CETAB.MAC')), CH$PTR (CETAB_FILE [FILE_NAME]));
    RCET (2, .CETAB_FILE, .VALUES);
    FCOR (.CETAB_FILE);
!
! Next we read in the RSX11-S Executive which forms the base for the
!  MCB system.
!
    OUTSTR (0, UPLIT (%ASCIZ'[Loading Base Executive	--> '));
    CH$MOVE (7, CH$PTR (UPLIT (%ASCIZ'RSX11S')), CH$PTR (KERNEL_FILE [FILE_NAME]));
    RSTB (2, .KERNEL_FILE);			!READ SYMBOL TABLE
    RCOR (.KERNEL_FILE, 2, 160*2048);		!READ IMAGE
    KERNEL_FILE [FILE_HWM] = 0;			!INITIALIZE HIGH WATER MARK
    MODU_PTR = .KERNEL_FILE [FILE_MODU];
    OUTSTR (0, MODU_PTR [MODU_NAME]);
    OUTPUT (0, %C' ');
    OUTSTR (0, MODU_PTR [MODU_IDENT]);
    OUTSTR (0, UPLIT (%ASCIZ' ]'));
    PCRLF (0);
!
! Read the CEXCOM partition contents.
!
    OUTSTR (0, UPLIT (%ASCIZ'[Loading MCB Executive	--> '));
    CH$MOVE (7, CH$PTR (UPLIT (%ASCIZ'CEXCOM')), CH$PTR (CEXCOM_FILE [FILE_NAME]));
    RSTB (2, .CEXCOM_FILE);			!READ COMM EXEC SYMBOL TABLE
    RCOR (.CEXCOM_FILE, 2, 16*2048);		!READ CEXCOM.TSK
    MODU_PTR = .CEXCOM_FILE [FILE_MODU];
    OUTSTR (0, MODU_PTR [MODU_NAME]);
    OUTPUT (0, %C' ');
    OUTSTR (0, MODU_PTR [MODU_IDENT]);
    OUTSTR (0, UPLIT (%ASCIZ' ]'));
    PCRLF (0);
!
!  Read symbol table from RSXMS.STB, which contains all the useful
!   symbols from EXEMC.MLB
!
    CH$MOVE (6, CH$PTR (UPLIT (%ASCIZ'RSXMS')), CH$PTR (RSXMS_FILE [FILE_NAME]));
    RSTB (2, .RSXMS_FILE);
!
! Get useful symbols from various symbol table files and store them
!  in the VALUES array. This is done to increase the efficiency of
!  accessing symbol values.
!
    GETSYM (.KERNEL_FILE, .CEXCOM_FILE, .RSXMS_FILE, .VALUES);
!
! We are done with the symbol table file(s), so throw them out of memory.
!
    FCOR (.RSXMS_FILE);
!
! Generate the CEXCOM partition and store the file in it.
!
    MCEX (.KERNEL_FILE, .CEXCOM_FILE, .VALUES);
!
! We don't need the CEXCOM file any more so delete it.
!
    FCOR (.CEXCOM_FILE);
!
! Construct the GEN partition which will contain all MCB Tasks, Processes,
!  and the POOL.
!
    GEN_PAR_BASE = .KERNEL_FILE [FILE_HWM] + 1;
    GEN_PCB = M_PCB (.KERNEL_FILE, UPLIT (%ASCIZ'GEN   '), 0, .GEN_PAR_BASE, 0, %O'100200', .VALUES [PS_SYS],
	0, .VALUES);
!
! First Install Tasks indicated in CETAB.MAC
!
    PAR_BLK [0] = .GEN_PCB;
    PAR_BLK [1] = .KERNEL_FILE;
    PAR_BLK [2] = .VALUES;
    PAR_BLK [3] = 2;
    FND_CHAIN (.VALUES [TSK_CHAIN], LOAD_TSKS, PAR_BLK);
!
! Return storage associated with the loaded tasks in our data base.
!
    FND_CHAIN (.VALUES [TSK_CHAIN], DEL_BLK, 0);
    DEL_PTRS (.VALUES [TSK_CHAIN]);
!
! Load the MCB Processes into memory.
!
    FND_CHAIN (.VALUES [MCB_CHAIN], LOAD_MCBS, PAR_BLK);
!
! Complete the GEN partition by filling in the size field
!
    PUTWRD (.KERNEL_FILE, .GEN_PCB + .VALUES [P_SIZE], (.KERNEL_FILE [FILE_HWM] - .GEN_PAR_BASE + 1)/64);
!
! Generate the CEXDAT partition to contain storage for the MCB processes' data
!  bases.
!
    POOL_PAR_BASE = .KERNEL_FILE [FILE_HWM] + 1;
    POOL_PCB = M_PCB (.KERNEL_FILE, UPLIT (%ASCIZ'CEXDAT'), 0, .POOL_PAR_BASE, 0, %O'100200',
	.VALUES [PS_COM], 0, .VALUES);
!
! Now load the MCB processes' data base elements that tie this system
!  together.
!
    LODMCB (.KERNEL_FILE, .POOL_PCB, 2, .VALUES);
!
! Finish the CEXDAT partition by filling in its size
!
    PUTWRD (.KERNEL_FILE, .POOL_PCB + .VALUES [P_SIZE], (.KERNEL_FILE [FILE_HWM] - .POOL_PAR_BASE + 1)/64);
!
! Delete information blocks kept around from reading CETAB.MAC, we are done
!  with them.
!
    FND_CHAIN (.VALUES [LLC_CHAIN], DEL_BLK, 0);
    DEL_PTRS (.VALUES [LLC_CHAIN]);
    FND_CHAIN (.VALUES [DEV_CHAIN], DEL_DEV, 0);
    DEL_PTRS (.VALUES [DEV_CHAIN]);
    FND_CHAIN (.VALUES [SLT_CHAIN], DEL_BLK, 0);
    DEL_PTRS (.VALUES [SLT_CHAIN]);
!
! Return storage held to list MCB processes.
!
    FND_CHAIN (.VALUES [MCB_CHAIN], DEL_BLK, 0);
    DEL_PTRS (.VALUES [MCB_CHAIN]);
!
! Now generate the CEXBUF main partition as the last one in memory.
!
    BUF_PAR_BASE = .KERNEL_FILE [FILE_HWM] + 1;
    BUF_PCB = M_PCB (.KERNEL_FILE, UPLIT (%ASCIZ'CEXBUF'), 0, .BUF_PAR_BASE, 0, %O'100200', .VALUES [PS_COM],
	0, .VALUES);
!
! Cleanup the KERNEL
!
    FCLEAN (.KERNEL_FILE, .VALUES);
!
! Print some information about the configuration of this system.
!
    TELLK (.KERNEL_FILE, 0, .VALUES);
!
! Tell we are writing the system image now
!
    OUTSTR (0, UPLIT (%ASCIZ'[Writing '));
    OUTSTR (0, KERNEL_FILE[FILE_NAME]);
    OUTSTR (0, UPLIT (%ASCIZ'.SYS]'));
    PCRLF (0);
!
! We have the MCB system image in our memory, write it to disk.
!
    WCOR (2, .KERNEL_FILE);
!
! Free the KERNEL File, Since We Don't Need It Any Longer.
!
    FCOR (.KERNEL_FILE);
!
! Free the VALUES Block, Since We Don't Need It Any More Either.
!
    FREBLK (.VALUES);
!
! Tell user we are done
!
    OUTSTR (0, UPLIT (%ASCIZ'[Poof! MCB Conjuration Complete]'));
    PCRLF (0);
!
    CLOSE (1);
    END;					!OF VNP20
ROUTINE DEL_BLK (BLK_PTR, UNUSED) = 		!FREE ANY BLOCK OF MEMORY

!++
! FUNCITONAL DESCRIPTION:
!
!	CALLS FREBLK TO FREE ANY BLOCK OF MEMORY
!
! FORMAL PARAMETERS:
!
!	BLK_PTR - ADDRESS OF BLOCK TO FREE
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	ALWAYS 0
!
! SIDE EFFECTS:
!
!	SOME MEMORY IS RETURNED TO FREE CORE
!--

    BEGIN

    MAP
	BLK_PTR : REF ANY_BLOCK;

    FREBLK (.BLK_PTR);
    0
    END;					!END OF DEL_BLK
ROUTINE DEL_DEV (DEV_PTR, UNUSED) = 		!FREE A DEV BLOCK

!++
! FUNCITONAL DESCRIPTION:
!
!	CALLS FREBLK TO FREE DEV AND FIND_CHAIN TO REMOVE CONTROLLERS ETC.
!
! FORMAL PARAMETERS:
!
!	DEV_PTR - ADDRESS OF DEV BLOCK TO FREE
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	ALWAYS 0
!
! SIDE EFFECTS:
!
!	SOME MEMORY IS RETURNED TO FREE CORE
!--

    BEGIN

    MAP
	DEV_PTR : REF DEV_BLOCK;

    FND_CHAIN (.DEV_PTR [DEV_CTL], DEL_CTL, 0);
    DEL_PTRS (.DEV_PTR [DEV_CTL]);
    FREBLK (.DEV_PTR);
    0
    END;					!END OF DEL_DEV
ROUTINE DEL_CTL (CTL_PTR, UNUSED) = 		!FREE CTL BLOCKS

!++
! FUNCITONAL DESCRIPTION:
!
!	CALLS FREBLK TO FREE CTL BLOCK RELATED MEMORY
!
! FORMAL PARAMETERS:
!
!	CTL_PTR - ADDRESS OF CTL BLOCK TO FREE
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	ALWAYS 0
!
! SIDE EFFECTS:
!
!	SOME MEMORY IS RETURNED TO FREE CORE
!--

    BEGIN

    MAP
	CTL_PTR : REF CTL_BLOCK;

    FND_CHAIN (.CTL_PTR [CTL_UNT], DEL_UNT, 0);	!FIND AND DELETE UNITS
    DEL_PTRS (.CTL_PTR [CTL_UNT]);
    FREBLK (.CTL_PTR);
    0
    END;					!END OF DEL_CTL
ROUTINE DEL_UNT (UNT_PTR, UNUSED) = 		!FREE UNT BLOCKS

!++
! FUNCITONAL DESCRIPTION:
!
!	CALLS FREBLK TO FREE UNT BLOCK RELATED MEMORY
!
! FORMAL PARAMETERS:
!
!	UNT_PTR - ADDRESS OF UNT BLOCK TO FREE
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	ALWAYS 0
!
! SIDE EFFECTS:
!
!	SOME MEMORY IS RETURNED TO FREE CORE
!--

    BEGIN

    MAP
	UNT_PTR : REF UNT_BLOCK;

    FND_CHAIN (.UNT_PTR [UNT_TRB], DEL_BLK, 0);	!FIND AND DELETE TRIBUTARIES
    DEL_PTRS (.UNT_PTR [UNT_TRB]);
    FREBLK (.UNT_PTR);
    0
    END;					!END OF DEL_UNT
ROUTINE LOAD_TSKS (TSKB_PTR, PAR_BLK) = 	!LOAD TASKS INTO THE GEN PARTITION

!++
! FUNCTIONAL DESCRIPTION:
!
!	LOAD TASKS INTO THE GEN PARTITION.
!
! FORMAL PARAMETERS:
!
!	TSKB_PTR - POINTS TO THE VNPTSK BLOCK FOR THIS TASK
!	PAR_BLK - A VECTOR OF USEFUL LOCATIONS
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	ALWAYS 0
!
! SIDE EFFECTS:
!
!	NONE
!
!--

    BEGIN

    BIND
	ROUTINE_NAME = UPLIT (%ASCIZ'LOAD_TSKS');

    MAP
	TSKB_PTR : REF VNPTSK_BLOCK,
	PAR_BLK : REF VECTOR;

    BIND
	GEN_PCB = PAR_BLK [0],
	KERNEL_FILE = PAR_BLK [1] : REF FILE_BLOCK,
	VALUES = PAR_BLK [2] : REF VNPVAL_BLOCK,
	FILE_CHAN = PAR_BLK [3];

    LOCAL
	TSK_FILE : REF FILE_BLOCK,
	TSK_LABEL : REF VECTOR [1024],
	TSK_BASE,
	TSK_TOP,
	TSK_SIZE,
	TSK_PCB,
	TSK_R50,
	TASK_NAME : VECTOR [CH$ALLOCATION (7)],
	PARTITION_NAME : VECTOR [CH$ALLOCATION (7)],
	PARTITION_BASE,
	MODU_PTR : REF MODU_BLOCK,
	CLK_ADDR;

    IF (.TSKB_PTR [TSK_TYPE] EQL TSK_TASK_TYPE)
    THEN
	BEGIN
!
! GET FILE FIRST
!

	IF ((TSK_FILE = GETBLK (FILE_TYP, FILE_LEN)) EQL 0)
	THEN
	    ERRMSG (0, 1, ROUTINE_NAME, 0, 0, 0, 0)
	ELSE
	    BEGIN
	    OUTSTR (0, UPLIT (%ASCIZ'[Loading Task '));
	    OUTSTR (0, TSKB_PTR [TSK_NAME]);
	    OUTSTR (0, UPLIT (%ASCIZ'	--> '));
	    CH$MOVE (LEN_TSK_NAME, CH$PTR (TSKB_PTR [TSK_NAME]), CH$PTR (TSK_FILE [FILE_NAME]));
	    RSTB (.FILE_CHAN, .TSK_FILE);
	    RCOR (.TSK_FILE, .FILE_CHAN, 32*2048);
	    TSK_LABEL = .TSK_FILE [FILE_LABEL];
	    TSK_BASE = .TSK_LABEL [L$BSA] + (.TSK_LABEL [L$BSA + 1]*256);
	    TSK_TOP = .TSK_LABEL [L$BHGV] + (.TSK_LABEL [L$BHGV + 1]*256);
	    TSK_SIZE = .TSK_TOP - .TSK_BASE + 1;
	    MODU_PTR = .TSK_FILE [FILE_MODU];
	    OUTSTR (0, MODU_PTR [MODU_NAME]);
	    OUTPUT (0, %C' ');
	    OUTSTR (0, MODU_PTR [MODU_IDENT]);
	    OUTSTR (0, UPLIT (%ASCIZ' ]'));
	    PCRLF (0);
!
! FORM THE PARTITION
!
	    begin
	    macro CH$LEN (PTR) = ch$diff (ch$find_ch (6, PTR, 0), PTR) %;
	    ch$wchar (0, CH$COPY (CH$LEN (CH$PTR (TSKB_PTR [TSK_NAME])),
		CH$PTR (TSKB_PTR [TSK_NAME]),
		%c' ', 6, CH$PTR (PARTITION_NAME)));
	    end;
	    PARTITION_BASE = .KERNEL_FILE [FILE_HWM] + 1;
	    TSK_PCB = M_PCB (.KERNEL_FILE, PARTITION_NAME, .GEN_PCB, .PARTITION_BASE,
		.PARTITION_BASE + .TSK_SIZE - 1, %O'004010', .VALUES [PS_SYS], 0, .VALUES);
!
! COPY THE TASK IN
!

	    INCR COUNTER FROM 0 TO .TSK_SIZE - 1 DO
		PUTBYT (.KERNEL_FILE, .PARTITION_BASE + .COUNTER, GETBYT (.TSK_FILE, .TSK_BASE + .COUNTER));

!
! BUILD THE TASK NAME
!
	    TSK_R50 = (.TSK_LABEL [L$BTSK]^16) + (.TSK_LABEL [L$BTSK + 1]^24) + (.TSK_LABEL [L$BTSK + 2]) + (
	    .TSK_LABEL [L$BTSK + 3]^8);
	    R50TOA (.TSK_R50, TASK_NAME);
!
! INSTALL THE TASK
!
	    INSTAL (.KERNEL_FILE, .TSK_FILE, TASK_NAME, .TSK_PCB, .VALUES);
!
! DETERMINE WHETHER THIS TASK REQUIRES A CLOCK QUEUE ENTRY AND BUILD ONE IF
!  APPROPRIATE.

	    IF (.TSKB_PTR [TSK_TIME] NEQ 0)
	    THEN
		BEGIN
		CLK_ADDR = ALOCB (.KERNEL_FILE, .VALUES [CLK_LGTH], 0, .VALUES);
		PUTWRD (.KERNEL_FILE, .CLK_ADDR + .VALUES [CLK_TIM],
		    GETWRD (.KERNEL_FILE, .VALUES [ABTIM]) + (.TSKB_PTR [TSK_TIME]*GETWRD (.KERNEL_FILE,
			.VALUES [TKPS])));
		PUTWRD (.KERNEL_FILE, .CLK_ADDR + .VALUES [CLK_RQT], .VALUES [CLK_SSHT]);
		PUTWRD (.KERNEL_FILE, .CLK_ADDR + .VALUES [CLK_TCB],
		    GETWRD (.KERNEL_FILE,
			.TSK_PCB + .VALUES [P_TCB]));
		PUTWRD (.KERNEL_FILE, .CLK_ADDR + .VALUES [CLK_LNK], GETWRD (.KERNEL_FILE, .VALUES [CLKHD]));
		PUTWRD (.KERNEL_FILE, .VALUES [CLKHD], .CLK_ADDR);
		END;

!
! FREE THE FILE ETC.
!
	    FCOR (.TSK_FILE);
	    END;

	END
    ELSE
	BEGIN
!
! GET THE DRIVER FILE
!

	IF ((TSK_FILE = GETBLK (FILE_TYP, FILE_LEN)) EQL 0)
	THEN
	    ERRMSG (0, 1, ROUTINE_NAME, 0, 0, 0, 0)
	ELSE
	    BEGIN
	    OUTSTR (0, UPLIT (%ASCIZ'[Loading Driver '));
	    OUTSTR (0, TSKB_PTR [TSK_NAME]);
	    OUTSTR (0, UPLIT (%ASCIZ':	--> '));
	    CH$COPY (LEN_DRV_NAME, CH$PTR (TSKB_PTR [TSK_NAME]), 3, CH$PTR (UPLIT (%ASCIZ'DRV')), 0, 6,
		CH$PTR (TSK_FILE [FILE_NAME]));
	    RSTB (.FILE_CHAN, .TSK_FILE);
	    RCOR (.TSK_FILE, .FILE_CHAN, 4*2048);
	    MODU_PTR = .TSK_FILE [FILE_MODU];
	    OUTSTR (0, MODU_PTR [MODU_NAME]);
	    OUTPUT (0, %C' ');
	    OUTSTR (0, MODU_PTR [MODU_IDENT]);
	    OUTSTR (0, UPLIT (%ASCIZ' ]'));
	    PCRLF (0);
	    LOADD (.KERNEL_FILE, .TSK_FILE, UPLIT (%ASCIZ'GEN   '), .GEN_PCB, .VALUES);
	    FCOR (.TSK_FILE)
	    END;

	END;

    0
    END;					!OF LOAD_TSKS
ROUTINE LOAD_MCBS (MCB_PTR, PAR_BLK) = 		!Load Processes into GEN partition

!++
! FUNCTIONAL DESCRIPTION:
!
!	Load MCB processes into GEN partition. The processes loaded are those
!	 indicated in the PDV$DF line in CETAB.MAC.
!
! FORMAL PARAMETERS:
!
!	MCB_PTR - Points to the VNPMCB block for this task
!	PAR_BLK - A vector of useful locations
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
!
!	ALWAYS 0
!
! SIDE EFFECTS:
!
!	GEN partition is filled with processes.
!
!--

    BEGIN

    BIND
	ROUTINE_NAME = UPLIT (%ASCIZ'LOAD_MCBS');

    MAP
	MCB_PTR : REF VNPMCB_BLOCK,
	PAR_BLK : REF VECTOR;

    BIND
	GEN_PCB = PAR_BLK [0],
	KERNEL_FILE = PAR_BLK [1] : REF FILE_BLOCK,
	VALUES = PAR_BLK [2] : REF VNPVAL_BLOCK,
	FILE_CHAN = PAR_BLK [3];

    LOCAL
	TSK_FILE : REF FILE_BLOCK,
	TSK_LABEL : REF VECTOR [1024],
	TSK_BASE,
	TSK_TOP,
	TSK_SIZE,
	TSK_PCB,
	TSK_R50,
	TASK_NAME : VECTOR [CH$ALLOCATION (7)],
	PARTITION_NAME : VECTOR [CH$ALLOCATION (7)],
	PARTITION_BASE,
	MODU_PTR : REF MODU_BLOCK,
	DCB_ADDR,
	XXXNAME : VECTOR [CH$ALLOCATION (7)];

    IF (CH$NEQ (1, CH$PTR (MCB_PTR [PROCESS_NAME]), 1, CH$PTR (UPLIT (0)), 0))
    THEN
	BEGIN
!
! Get the file first
!

	IF ((TSK_FILE = GETBLK (FILE_TYP, FILE_LEN)) EQL 0)
	THEN
	    ERRMSG (0, 1, ROUTINE_NAME, 0, 0, 0, 0)
	ELSE
	    BEGIN
	    OUTSTR (0, UPLIT (%ASCIZ'[Loading Process '));
	    OUTSTR (0, MCB_PTR [PROCESS_NAME]);
	    OUTSTR (0, UPLIT (%ASCIZ'	--> '));
	    CH$MOVE (LEN_MCB_NAME, CH$PTR (MCB_PTR [PROCESS_NAME]), CH$PTR (TSK_FILE [FILE_NAME]));
	    RSTB (.FILE_CHAN, .TSK_FILE);
	    RCOR (.TSK_FILE, .FILE_CHAN, 10*2048);
	    TSK_LABEL = .TSK_FILE [FILE_LABEL];
	    TSK_BASE = .TSK_LABEL [L$BSA] + (.TSK_LABEL [L$BSA + 1]*256);
	    TSK_TOP = .TSK_LABEL [L$BHGV] + (.TSK_LABEL [L$BHGV + 1]*256);
	    TSK_SIZE = .TSK_TOP - .TSK_BASE + 1;
	    MODU_PTR = .TSK_FILE [FILE_MODU];
	    OUTSTR (0, MODU_PTR [MODU_NAME]);
	    OUTPUT (0, %C' ');
	    OUTSTR (0, MODU_PTR [MODU_IDENT]);
	    OUTSTR (0, UPLIT (%ASCIZ' ]'));
	    PCRLF (0);
!
! Form the partition
!
	    begin
	    macro CH$LEN (PTR) = ch$diff (ch$find_ch (4, PTR, 0), PTR) %;
	    ch$wchar (0, CH$COPY (3, CH$PTR (UPLIT (%ASCIZ'NT.')),
		CH$LEN (CH$PTR (MCB_PTR [PROCESS_NAME])), CH$PTR (MCB_PTR [PROCESS_NAME]),
		%c' ', 6, CH$PTR (PARTITION_NAME)));
	    end;
	    PARTITION_BASE = .KERNEL_FILE [FILE_HWM] + 1;
	    TSK_PCB = M_PCB (.KERNEL_FILE, PARTITION_NAME, .GEN_PCB, .PARTITION_BASE,
		.PARTITION_BASE + .TSK_SIZE - 1, %O'000000',
		.VALUES [PS_SYS] OR .VALUES [PS_COM] OR .VALUES [PS_NSF], 0, .VALUES);
!
! Copy the task into it
!

	    INCR COUNTER FROM 0 TO .TSK_SIZE - 1 DO
		PUTBYT (.KERNEL_FILE, .PARTITION_BASE + .COUNTER, GETBYT (.TSK_FILE, .TSK_BASE + .COUNTER));

!
! If the process supplies a device then load its' DCB/UCB/SCB structure and
! update UCBxxx.
!

	    IF (CH$NEQ (1, CH$PTR (MCB_PTR [DEVICE_NAME]), 1, CH$PTR (UPLIT (0)), 0))
	    THEN
		BEGIN
		DCB_ADDR = LD_DCB (.KERNEL_FILE, .FILE_CHAN, .TSK_PCB, .MCB_PTR [DEVICE_NAME], .VALUES);
!
! Store the address of the UCB in UCBxxx.
!
		CH$COPY (3, CH$PTR (UPLIT (%ASCIZ'UCB')), LEN_MCB_NAME, CH$PTR (MCB_PTR [PROCESS_NAME]), 0,
		    7, CH$PTR (XXXNAME));
		PUTWRD (.KERNEL_FILE, .VALUES [CE_DATA_BASE] + SYM_VAL (.VALUES [CE_DATA_FILE], XXXNAME, 0),
		    GETWRD (.KERNEL_FILE, .DCB_ADDR + .VALUES [D_UCB]));
		END;
!
! We used to store the PCB address in PCBxxx but for MCB V3.1 we don't
! need to do that so code has been commented out.
!
!	    CH$COPY (3, CH$PTR (UPLIT (%ASCIZ'PCB')), LEN_MCB_NAME, CH$PTR (MCB_PTR [PROCESS_NAME]), 0, 7,
!		CH$PTR (XXXNAME));
!	    PUTWRD (.KERNEL_FILE, .VALUES [CE_DATA_BASE] + SYM_VAL (.VALUES [CE_DATA_FILE], XXXNAME, 0),
!		.TSK_PCB);
!
!
! Free the file storage
!
	    FCOR (.TSK_FILE);
	    END;

	END;

    0
    END;					!OF LOAD_MCBS
END

ELUDOM
! Local Modes:
! Comment Column:36
! Comment Start:!
! Mode:Fundamental
! Auto Save Mode:2
! End: