



		    disk_name_pvtx.pl1              11/11/89  1138.0r w 11/11/89  0839.5       47088



/****^  ***********************************************************
        *                                                         *
        * Copyright, (C) Honeywell Bull Inc., 1987                *
        *                                                         *
        * Copyright, (C) Honeywell Information Systems Inc., 1986 *
        *                                                         *
        *********************************************************** */


/****^  HISTORY COMMENTS:
  1) change(86-01-16,Fawcett), approve(86-04-11,MCR7383),
     audit(86-05-13,Coppola), install(86-07-17,MR12.0-1097):
     Created to find correct pvtx given disk name. (Subvolume changes).
                                                   END HISTORY COMMENTS */
/* format: off */
/* This program will find the index for a pvte in the pvt$array from the device name.

 dcl disk_name_pvtx entry (char (8), fixed bin, fixed bin (35));

 call disk_name_pvtx (disk_name, pvtx, code);

where:
   disk_name is the name of the device which has the format dsk<subsystem>_<number><subvolume>, dska_02, or dskb_00b. (Input)

   pvtx is the index in the pvt$array for the disk if found (Output).

   code is  0 for pvtx valid,
	  error_table_$resource_unknown (could not find device)
	  error_table_$subvol_needed (device requires subvolume and none given)
	  error_table_$subvol_invalid (device does not have subvolumes or the does not have the supplied subvolume).

The subsys_dev entry point is called when the caller has the subsystem and
device number as two variables. "dska" for the subsystem and "1a" for the
device number. This entry can be called without converting dska_1a to dska_01a.

 dcl disk_name_pvtx$subsys_dev entry
        (char (4), char (4), fixed bin (17), fixed bin (35);

 call disk_name_pvtx$subsys_dev (a_subsys, a_dev, a_pvtx, a_code);

where:
 a_subsys is the name of the disk subsystem (e.g., dska).

 a_dev is the device number (e.g., 01a, 12b, 1, or 1c).

 a_pvtx and a_code are the same as above.

*/
%page;
/* format: on */
disk_name_pvtx:
     proc (a_dev_name, a_pvtx, a_code);

	dcl     a_code		 fixed bin (35);
	dcl     a_dev_name		 char (8);
	dcl     a_dev		 char (4);
	dcl     a_pvtx		 fixed bin;
	dcl     a_subsys		 char (4);


/* Automatic */

	dcl     code		 fixed bin (35);
	dcl     devname		 char (4);
	dcl     devnum		 fixed bin;
	dcl     inc		 fixed bin;
	dcl     name_length		 fixed bin;
	dcl     subsys		 char (4);
	dcl     sv_idx		 fixed bin;
	dcl     the_sv		 char (1);
	dcl     pvtx		 fixed bin;


/* EXT Entry */

	dcl     cv_dec_check_	 entry (char (*), fixed bin (35)) returns (fixed bin (35));

/* Builtins */

	dcl     (addr, after, before, index, length, rtrim, search, substr) builtin;

/* Error codes */


	dcl     error_table_$resource_unknown fixed bin (35) ext static;
	dcl     error_table_$subvol_needed fixed bin (35) ext static;
	dcl     error_table_$subvol_invalid fixed bin (35) ext static;
%page;

	name_length = length (rtrim (a_dev_name));
	if name_length < 7 then goto no_such_drive;
	if index (a_dev_name, "_") ^= 5 then goto no_such_drive;
	subsys = before (a_dev_name, "_");
	devname = after (a_dev_name, "_");
	goto common_checks;


disk_name_pvtx$subsys_dev:
     entry (a_subsys, a_dev, a_pvtx, a_code);

	subsys = a_subsys;
	devname = a_dev;

common_checks:

/* make sure we are talking about a disk */
	if substr (subsys, 1, 3) ^= "dsk" then goto no_such_drive;

	inc = search (devname, valid_sv_string);
	if inc = 0 then do;
		the_sv = "";
						/* if the subvolume is not a valid sv then this check will fail */
		devnum = cv_dec_check_ (rtrim (devname), code);
	     end;
	else do;
		the_sv = substr (devname, inc, 1);
		devnum = cv_dec_check_ (substr (devname, 1, (inc - 1)), code);
	     end;

	if code ^= 0 then goto no_such_drive;

	if devnum >= 65 then goto no_such_drive;

	pvtp = addr (pvt$);
	pvt_arrayp = addr (pvt.array);
						/* find the first or only entry for the dev */
	do pvtx = 1 to pvt.n_entries while
	     (pvt_array (pvtx).devname ^= subsys |
	     pvt_array (pvtx).logical_area_number ^= devnum);
	end;
	if pvtx > pvt.n_entries then goto no_such_drive;	/* So don't bother with the subvolume */

	sv_idx = number_of_sv (pvt_array (pvtx).device_type);
	if sv_idx ^= 0 then do;
						/* the type of device requires the subvolume */
		if the_sv = "" then goto need_sub;
		inc = index (substr (valid_sv_string, 1, sv_idx), the_sv) - 1;
		if inc < 0 then goto not_valid_sv;	/* subvolume not correct for this device type */
		pvtx = pvtx + inc;
		if (pvt_array (pvtx).devname ^= subsys |
		     pvt_array (pvtx).logical_area_number ^= devnum |
		     pvt_array (pvtx).sv_name ^= the_sv) then goto no_such_drive;
	     end;
	else if the_sv ^= "" then goto no_such_drive;	/* subvolume supplied but device not divided into subvolumes */
	if pvtx > pvt.n_entries then goto no_such_drive;
	a_pvtx = pvtx;
	a_code = 0;
	return;
not_valid_sv:
	a_code = error_table_$subvol_invalid;
	goto Error_exit;
no_such_drive:
	a_code = error_table_$resource_unknown;
	goto Error_exit;
need_sub:
	a_code = error_table_$subvol_needed;
Error_exit:
	return;
%page;
%include fs_dev_types;
%page;
%include pvt;
%page;
%include pvte;
     end disk_name_pvtx;




		    disk_run.pl1                    11/11/89  1138.0r w 11/11/89  0839.5       14058



/****^  ***********************************************************
        *                                                         *
        * Copyright, (C) Honeywell Bull Inc., 1987                *
        *                                                         *
        * Copyright, (C) Honeywell Information Systems Inc., 1982 *
        *                                                         *
        * Copyright (c) 1972 by Massachusetts Institute of        *
        * Technology and Honeywell Information Systems, Inc.      *
        *                                                         *
        *********************************************************** */


disk_run: proc;

/* disk_run - externally  callable  subroutine  that  forces
   looking  at status returns from disk, regardless of whether
   interrupt has come in or not (i.e. if interrupts are  masked
   due   to  some  unexplainable  set  of  circumstances,  this
   subroutine will win).

   coded by J. A. Bush 3/11/80
*/
dcl  page$time_out entry;
dcl  pmut$wire_and_mask entry (fixed bin (71), ptr);
dcl  pmut$unwire_unmask entry (fixed bin (71), ptr);
dcl  temp_msk_ptr ptr;				/* temporary for wire_and_mask (and unwire_unmask) */
dcl  mask_temp fixed bin (71);			/* temporary for wire_and_mask (and unwire_unmask) */

	call pmut$wire_and_mask (mask_temp, temp_msk_ptr); /* wire our stack (and mask interrupts) */
	call page$time_out;				/* force looking at status */
	call pmut$unwire_unmask (mask_temp, temp_msk_ptr); /* can unwire stack now */

     end disk_run;




		    find_partition.pl1              11/11/89  1138.0r w 11/11/89  0839.5       33831



/****^  ***********************************************************
        *                                                         *
        * Copyright, (C) Honeywell Bull Inc., 1987                *
        *                                                         *
        * Copyright, (C) Honeywell Information Systems Inc., 1985 *
        *                                                         *
        *********************************************************** */


/****^  HISTORY COMMENTS:
  1) change(86-01-17,Fawcett), approve(86-04-11,MCR7383),
     audit(86-05-13,Coppola), install(86-07-17,MR12.0-1097):
     Changed for part card change, and call disk_name_pvtx, subvolume
     support.
                                                   END HISTORY COMMENTS */


find_partition: proc (a_part_name, a_pvtx, a_pvid, a_first_record, a_n_records, a_code);

/* Find the pvtx, etc. of a partition given its name, and, optionally, a disk
drive.  Taken from partition_io by Keith Loepere, January 1985. */

/* format: style2 */

	dcl     (
	        a_code		 fixed bin (35),
	        a_drive_name	 char (*),	/* drive no in subsystem */
	        a_first_record	 fixed bin (18),	/* First record of partition */
	        a_n_records		 fixed bin (18),	/* Number of records in partition */
	        a_part_name		 char (*),	/* Name of partition */
	        a_pvid		 bit (36) aligned,	/* PVID of volume with partition */
	        a_pvtx		 fixed bin,	/* PVTE index */
	        a_subsystem		 char (4)		/* as in dska */
	        )			 parameter;

	dcl     code		 fixed bin (35);
	dcl     drive_name		 char (4);
	dcl     part_idx		 fixed bin;
	dcl     part_name		 char (4) aligned;
	dcl     part_pvtx		 fixed bin (8);
	dcl     pvtx		 fixed bin (17);
	dcl     record_buffer	 (1024) bit (36) aligned;
	dcl     subsys		 char (4);
	dcl     system_initializing	 bit (1);

	dcl     error_table_$nopart	 fixed bin (35) external static;
	dcl     pvt$n_entries	 fixed bin external static;
	dcl     pvt$root_pvtx	 fixed bin external static;

	dcl     disk_name_pvtx$subsys_dev
				 entry (char (4), char (4), fixed bin (17), fixed bin (35));
	dcl     config_$find_2	 entry (char (4) aligned, char (4) aligned, ptr);
	dcl     read_disk		 entry (fixed bin (8), fixed bin (18), pointer, fixed bin (35));

	dcl     (addr, null)	 builtin;
%page;
	a_code = 0;

	part_name = a_part_name;
	call config_$find_2 ("part", part_name, part_cardp);
	if part_cardp = null ()
	then do;
NO_PART:
		a_code = error_table_$nopart;
		return;
	     end;
	subsys = part_card.subsystem;
	drive_name = part_card.drive;
	goto find_pvtx;

given_drive:
     entry (a_part_name, a_subsystem, a_drive_name, a_pvtx, a_pvid, a_first_record, a_n_records, a_code);

	a_code = 0;

	part_name = a_part_name;
	drive_name = a_drive_name;
	subsys = a_subsystem;


find_pvtx:
	pvt_arrayp = addr (pvt$array);
	system_initializing = ^pvt_array (pvt$root_pvtx).used;

	call disk_name_pvtx$subsys_dev (subsys, drive_name, pvtx, code);
	if code ^= 0
	then do;
		a_code = code;
		return;
	     end;

	pvtep = addr (pvt_array (pvtx));
	if ^(pvte.used | system_initializing)
	then goto NO_PART;
	part_pvtx = pvtx;


	labelp = addr (record_buffer);

	call read_disk (part_pvtx, 0, labelp, code);
	if code ^= 0
	then do;
		a_code = code;
		return;
	     end;

	do part_idx = 1 to label.nparts;
	     if label.parts (part_idx).part = part_name
	     then do;
		     a_pvtx = part_pvtx;
		     a_pvid = pvte.pvid;
		     a_first_record = label.parts (part_idx).frec;
		     a_n_records = label.parts (part_idx).nrec;
		     return;
		end;
	end;

	a_code = error_table_$nopart;
	return;
%page;
%include config_part_card;
%page;
%include fs_vol_label;
%page;
%include pvte;
%page;
/* %include fs_dev_types; */
     end;




		    read_disk.pl1                   11/11/89  1138.0r w 11/11/89  0839.5       85500



/****^  ***********************************************************
        *                                                         *
        * Copyright, (C) Honeywell Bull Inc., 1987                *
        *                                                         *
        * Copyright, (C) Honeywell Information Systems Inc., 1983 *
        *                                                         *
        *********************************************************** */


read_disk$init: proc;

/* This procedure performs I/O from/to a given disk address. In the current
   implementation, this will always be a one-page record. The initializer
   process uses the ASTE created by initialization to avoid calling AST
   management during collection 1, and to speed up disk initializations via
   initializer_gate. Shutdown uses this ASTE as well to avoid getting involved
   with AST management. */

/* coded	03/07/75 by Bernard S. Greenberg. */
/* Modified by BSG 04/09/76 for disk_control$test_drive */
/* Modified by BSG 08/31/76 for dynamic ASTE getting, for volume dumper */
/* Modified by J. A. Bush 2/22/80 to fix an infinite loop bug in ESD */
/* Modified 04/16/81, W. Olin Sibert, for ADP PTWs and SDWs, and to use sst external static */
/* Modified 03/01/82 by J. Bongiovanni for new PVTE include file */
/* Modified '82 for english disk error codes */
/* Modified 11/01/83 by Keith Loepere for swapping rdisk sdw at init */
/* Modified 1/13/84 by Keith Loepere for $no_test */
/* Modified 84-01-16 BIM for records = 0 */
/* Modified 84-05-04 for bce_abs_seg$add, Keith Loepere */
/* Modified 84-10-23 by Keith Loepere to null ptw when done. */

dcl  a_dataptr ptr parameter;
dcl  a_pvtx fixed bin parameter;			/* params */
dcl  a_recno fixed bin (18) parameter;

dcl  code fixed bin;				/* error code */
dcl  dataptr ptr;					/* pointer to transferable data */
dcl  ptp pointer;					/* pointer to its ASTE */
dcl  pvtx fixed bin (17);				/* phys vol table index */
dcl  rdskp ptr;					/* pointer to rdisk_seg */
dcl  record_no fixed bin (18);			/* record number on disk */
dcl  static_rdisks_astep ptr internal static init (null ()); /* Ditto astep */
dcl  static_rdisks_sdw fixed bin (71) aligned internal static init (0); /* SDW form initialization forever */
dcl  testsw bit (1);				/* "1"b => test */
dcl  tsdw fixed bin (71) aligned;			/* sdw temp */
dcl  use_init bit (1) aligned;			/* 1 = use init SDW, astep */
dcl  writesw bit (1);				/* "1"b => write */

dcl  bdata (1024) fixed bin (35) based; 		/* block of data */

dcl  pds$processid bit (36) aligned external static;	/* equal to tc_data$initializer_id during init. */
dcl  rdisk_seg$ ext fixed bin;			/* segment for I/O */
dcl  sst$astsize fixed bin external static;
dcl 1 sst$level (0 : 3) aligned external static,
    2 ausedp bit (18) unaligned,
    2 no_aste bit (18) unaligned;
dcl  sys_info$page_size fixed bin external static;
dcl  tc_data$initializer_id bit (36) aligned external static;
dcl  tc_data$system_shutdown bit (1) aligned external;

dcl  bce_abs_seg$add entry (fixed bin (15));
dcl  disk_control$test_drive entry (fixed bin);
dcl  disk_run entry;
dcl  get_aste entry (fixed bin) returns (ptr);
dcl  get_ptrs_$ptw_to_cmep entry (pointer, pointer);
dcl  get_ptrs_$given_astep entry (ptr, fixed bin (71) aligned);
dcl  lock$lock_ast entry ();
dcl  lock$unlock_ast entry ();
dcl  make_sdw$unthreaded entry (fixed bin (18), fixed bin (71) aligned, ptr, ptr);
dcl  pc$cleanup entry (ptr);
dcl  pmut$swap_sdw entry (ptr, ptr);
dcl  ptw_util_$make_disk entry (pointer, fixed bin (20));
dcl  ptw_util_$make_null entry (ptr, bit (22) aligned);
dcl  ptw_util_$make_null_disk entry (pointer, fixed bin (20));
dcl  ptw_util_$set_unwired entry (pointer);
dcl  ptw_util_$set_wired entry (pointer);
dcl  put_aste entry (ptr);
dcl  sdw_util_$set_size entry (pointer, fixed bin (19));
dcl  thread$cin entry (ptr, bit (18));
dcl  thread$out entry (ptr, bit (18));

dcl  page_fault_error condition;

dcl  (error_table_$fsdisk_phydev_err, error_table_$fsdisk_not_ready)
     ext static fixed bin (35);

dcl (addr, addrel, baseno, bit, fixed, segno) builtin;
%page;
	rdskp = addr (rdisk_seg$);			/* similarly, rdisk_seg */
	call make_sdw$unthreaded (fixed (baseno (rdskp), 18), tsdw, astep, ptp);
						/* force seg to become paged */
	call sdw_util_$set_size (addr (tsdw), (sys_info$page_size)); /* A single page */
						/* do not allow any access xcept page 0 */

	astep -> aste. dnzp,			/* pages may never be nulled/deposited */
	     astep -> aste.nqsw = "1"b;		/* or complained about. */
	static_rdisks_sdw = tsdw;
	static_rdisks_astep = astep;			/* Save for posterity */
	call pmut$swap_sdw (rdskp, addr (tsdw));	/* Install SDW */
	call bce_abs_seg$add (segno (rdskp));		/* free at shut */
	return;

read_disk_no_test: entry (a_pvtx, a_recno, a_dataptr, code);	/* entry to read data */

	writesw = "0"b;
	go to no_test;

write_disk_no_test: entry (a_pvtx, a_recno, a_dataptr, code);

	writesw = "1"b;

no_test:
	record_no = a_recno;
	dataptr = a_dataptr;
	pvtx = a_pvtx;				/* copy parms */

	rdskp = addr (rdisk_seg$);			/* set up special seg ptr */
	pvt_arrayp = addr (pvt$array);		/* Get pointer to PVTE array */
	pvtep = addr (pvt_array (pvtx));		/* Get pvte pointer. */
	go to operate;

read_disk: entry (a_pvtx, a_recno, a_dataptr, code);	/* entry to read data */

	writesw = "0"b;
	testsw = "0"b;				/* Not a test */
	record_no = a_recno;
	dataptr = a_dataptr;
	go to merge;

write_disk: entry (a_pvtx, a_recno, a_dataptr, code);

	writesw = "1"b;
	testsw = "0"b;
	record_no = a_recno;
	dataptr = a_dataptr;
	go to merge;

test_disk: entry (a_pvtx, code);

	testsw = "1"b;

merge:
	pvtx = a_pvtx;				/* copy parms */

	rdskp = addr (rdisk_seg$);			/* set up special seg ptr */
	pvt_arrayp = addr (pvt$array);		/* Get pointer to PVTE array */
	pvtep = addr (pvt_array (pvtx));		/* Get pvte pointer. */

	pvte.testing = "1"b;			/* Turn on disk dim protocol bit. */
	call disk_control$test_drive (pvtx);		/* Start a RQS op up */
	do while (pvte.testing);			/* Noel has sworn that SOMETHING will come back. */
	     call disk_run;				/* in case something doesn't come back, force looking at status */
	end;
	if pvte.device_inoperative then do;		/* If we found disk not operaable, */
	     pvte.device_inoperative = "0"b;		/* Clear silly flag, and */
	     code = error_table_$fsdisk_not_ready;		/* return a usable diagnostic. */
	     return;
	end;

	if testsw then do;				/* Successful test. */
	     code = 0;
	     return;
	end;


/* If this is not the initializer or shutdown, an ASTE must be gotten and inserted.
   Otherwise, use the ASTE created by initialization. */

operate:
	use_init = (tc_data$initializer_id = pds$processid) | tc_data$system_shutdown;


	if use_init then do;
	     tsdw = static_rdisks_sdw;
	     astep = static_rdisks_astep;
	end;
	else do;					/* Must get_aste */
	     call lock$lock_ast;
	     astep = get_aste (1);			/* Need 1 page ASTE */
	     call thread$out (astep, sst$level.ausedp (0)); /* thread aste out of used list */
	     call lock$unlock_ast;			/* and unlock ast */
	     call get_ptrs_$given_astep (astep, tsdw);	/* Generate SDW */
	     astep -> aste.nqsw, astep -> aste.dnzp = "1"b;
	end;

	astep -> aste.records, astep -> aste.csl, astep -> aste.np = ""b;
	ptp = addrel (astep, sst$astsize);
	call pmut$swap_sdw (rdskp, addr (tsdw));	/* Install SDW */

/* Now make this seg reflect the given pvtx, with the first and only page being
   the given record. */

	astep -> aste.pvtx = pvtx;			/* copy supplied pvtx */

	if writesw then				/* If writing, then pages contents aren't there yet */
	     call ptw_util_$make_null_disk (ptp, (record_no));
	else call ptw_util_$make_disk (ptp, (record_no));	/* Otherwise, they are, and we want them */
	call ptw_util_$set_wired (ptp);		/* Page is "wired" */

	astep -> aste.npfs = "0"b;			/* Previous cleanup turned on npfs- it was good to leave
						   it on until now. */

/* Now copy the data to/from this abs-seg. Notice that even in the write case, we
   fault in the page. */

	on page_fault_error begin;
	     code = error_table_$fsdisk_phydev_err;
	     go to fini;
	end;

	if writesw then rdskp -> bdata = dataptr -> bdata;
	else dataptr -> bdata = rdskp -> bdata;

/* Now comes the peculiar part. If this is a write_disk, we magically migrate the page to disk. */

	if writesw then do;
	     call get_ptrs_$ptw_to_cmep (ptp, cmep);	/* Find its CME, and do magic with it */
	     cmep -> mcme.record_no = bit (fixed (record_no, 18), 18);
	     cmep -> mcme.add_type = add_type.disk;	/* Note that record # is changed first */
	     call ptw_util_$set_unwired (ptp);		/* rdisk_seg is now at the mercy of page_fault */
	end;

	code = 0;

fini:
	call pc$cleanup (astep);

/* This gets all the pages out of core. In the write case,
   It is guaranteed to actually write (phm will be on)
   and wait for done. */

	if ^use_init then do;
	     tsdw = 0;				/* Leave around in shutdown for debugging */
	     call pmut$swap_sdw (rdskp, addr (tsdw));
	     call lock$lock_ast;			/* lock ast */
	     call thread$cin (astep, sst$level.ausedp (0)); /* thread aste back in */
	     call put_aste (astep);			/* Return the ASTE */
	     call lock$unlock_ast;
	end;
	else call ptw_util_$make_null (ptp, make_sdw_null_addr); /* null ptw so dumpers won't be confused */

	return;

%page; %include add_type;
%page; %include aste;
%page; %include cmp;
%page; %include null_addresses;
%page; %include pvte;

	end read_disk$init;




		    stock_man.pl1                   11/11/89  1138.0r w 11/11/89  0839.5       79947



/****^  ***********************************************************
        *                                                         *
        * Copyright, (C) Honeywell Bull Inc., 1987                *
        *                                                         *
        * Copyright, (C) Honeywell Information Systems Inc., 1982 *
        *                                                         *
        *********************************************************** */
stock_man$allocate_record_stock:
     proc (Pvtep, Record_stockp);

/* Routine to manage the allocation and deletion of stocks.
   Initially, only record stocks are supported. Later, VTOCE stocks
   will also be supported.

   This implementation of record stocks is fairly simple. All record stocks 
   are the same size, and there is sufficient wired space in stock_seg
   for all of them. The record stocks form an array, whose elements
   parallel the PVTE array. The knowledge of the internal structure
   of stock_seg is known only to this procedure, so the allocation
   mechanism can be changed fairly simply. If it is get_io_segs must
   also be changed to get sufficient space in stock_seg. Similarly, VTOCE
   stocks form an array, whose elements parallel the PVTE array, and
   are all of the same size.

   Written March 1982 by J. Bongiovanni

*/

/*  Parameter  */

	dcl     Pvtep		 ptr;		/* Pointer to PVTE */
	dcl     Record_stockp	 ptr;		/* Pointer to record stock */
	dcl     Vtoce_stockp	 ptr;		/* Pointer to VTOCE stock */

/*  Automatic  */

	dcl     p99		 pic "99";
	dcl     pvtx		 fixed bin;
	dcl     stockx		 fixed bin;

/*  Entry  */

	dcl     syserr		 entry options (variable);

/*  Builtin  */

	dcl     addr		 builtin;
	dcl     addrel		 builtin;
	dcl     bin		 builtin;
	dcl     bit		 builtin;
	dcl     convert		 builtin;
	dcl     divide		 builtin;
	dcl     null		 builtin;
	dcl     rel		 builtin;
	dcl     size		 builtin;
	dcl     unspec		 builtin;

%page;
	pvtep = Pvtep;
	pvtx = divide (bin (rel (pvtep)) - bin (rel (addr (pvt$array))), size (pvte), 17) + 1; /* PVTE index */

	stock_segp = addr (stock_seg$);

	n_in_record_stock = stock_seg.record_stock_entries;
	n_volmap_pages = N_OLD_VOLMAP_PAGES;

	record_stockp = addrel (stock_seg.record_stock_arrayp, (pvtx - 1) * stock_seg.record_stock_size);

	record_stock.pvtep = pvtep;
	record_stock.n_in_stock = n_in_record_stock;
	record_stock.n_volmap_pages = N_OLD_VOLMAP_PAGES;
	record_stock.n_free_in_stock = 0;
	record_stock.n_os_in_stock = 0;
	record_stock.low_threshold = divide (n_in_record_stock, 4, 18);
	record_stock.high_threshold = n_in_record_stock - record_stock.low_threshold;
	record_stock.target = divide (record_stock.high_threshold + record_stock.low_threshold, 2, 18);
	record_stock.stock_offset = bit (bin (bin (rel (addr (record_stock.stock))) - bin (rel (record_stockp)), 18), 18);
	record_stock.n_words_in_stock = divide (n_in_record_stock + 1, 2, 18);
	record_stock.search_index = 0;

	unspec (record_stock.old_volmap_page) = ""b;
	unspec (record_stock.volmap_page) = ""b;
	unspec (record_stock.stock) = ""b;

	pvte.volmap_stock_ptr = record_stockp;

	Record_stockp = record_stockp;

	return;
%page;
stock_man$free_record_stock:
     entry (Pvtep, Record_stockp);

	pvtep = Pvtep;
	record_stockp = Record_stockp;

	if pvte.volmap_stock_ptr = null () then return;	/* For ESD, since may crump in the middle of demount */

	if pvte.volmap_stock_ptr ^= record_stockp | record_stock.pvtep ^= pvtep
	then do;
		pvte.volmap_stock_ptr = null ();	/* Let ESD work next time */
		call syserr (CRASH, "stock_man: PVTE out of synch with record stock on ^a_^a: pvtep=^p record_stockp=^p", pvte.devname, convert (p99, pvte.logical_area_number), pvtep, record_stockp);
	     end;


	if record_stock.n_free_in_stock ^= 0 | record_stock.n_os_in_stock ^= 0
	     | unspec (record_stock.stock) ^= ""b
	then do;
		pvte.volmap_stock_ptr = null ();	/* Let ESD work next time */
		call syserr (CRASH, "stock_man: Attempt to free non-empty stock on ^a_^a: pvtep=^p record_stockp = ^p", pvte.devname, convert (p99, pvte.logical_area_number), pvtep, record_stockp);
	     end;

	pvte.volmap_stock_ptr = null ();
	unspec (record_stock) = ""b;

	return;
%page;
stock_man$allocate_vtoce_stock:
     entry (Pvtep, Vtoce_stockp);

	pvtep = Pvtep;
	pvtx = divide (bin (rel (pvtep)) - bin (rel (addr (pvt$array))), size (pvte), 17) + 1; /* PVTE index */


	stock_segp = addr (stock_seg$);

	n_in_vtoce_stock = stock_seg.vtoce_stock_entries;

	vtoce_stockp = addrel (stock_seg.vtoce_stock_arrayp, (pvtx - 1) * stock_seg.vtoce_stock_size);

	vtoce_stock.pvtep = pvtep;
	vtoce_stock.n_in_stock = n_in_vtoce_stock;
	vtoce_stock.n_free_in_stock = 0;
	vtoce_stock.target = divide (n_in_vtoce_stock, 2, 18);
	vtoce_stock.search_index = 0;

	unspec (vtoce_stock.stock) = ""b;

	do stockx = 1 to vtoce_stock.n_in_stock;
	     vtoce_stock.stock (stockx) = -1;
	end;

	pvte.vtoc_map_stock_ptr = vtoce_stockp;
	Vtoce_stockp = vtoce_stockp;

	return;
%page;
stock_man$free_vtoce_stock:
     entry (Pvtep, Vtoce_stockp);

	pvtep = Pvtep;
	vtoce_stockp = Vtoce_stockp;

	if pvte.vtoc_map_stock_ptr = null () then return; /* For ESD, since may crump in the middle of a dismount */

	if pvte.vtoc_map_stock_ptr ^= vtoce_stockp | vtoce_stock.pvtep ^= pvtep
	then do;
		pvte.vtoc_map_stock_ptr = null ();	/* Let ESD work */
		call syserr (CRASH, "stock_man: PVTE out of synch with VTOCE stock on ^a_^a: pvtep=^p vtoce_stockp=^p",
		     pvte.devname, convert (p99, pvte.logical_area_number), pvtep, vtoce_stockp);
	     end;

	if vtoce_stock.n_free_in_stock ^= 0
	then do;
NON_EMPTY_STOCK:
		pvte.vtoc_map_stock_ptr = null ();	/* Let ESD work */
		call syserr (CRASH, "stock_man: Attempt to free non-empty stock on ^a_^a: pvtep=^p vtoce_stockp=^p",
		     pvte.devname, convert (p99, pvte.logical_area_number), pvtep, vtoce_stockp);
	     end;

	do stockx = 1 to vtoce_stock.n_in_stock;
	     if vtoce_stock.stock (stockx) ^= -1
	     then goto NON_EMPTY_STOCK;
	end;

	pvte.vtoc_map_stock_ptr = null ();
	unspec (vtoce_stock) = ""b;

	return;


%page; %include pvte;
%page; %include stock_seg;
%page; %include syserr_constants;
%page;
/* BEGIN MESSAGE DOCUMENTATION

   Message:
   stock_man: PVTE out of synch with record stock on dskX_NN: pvtep = XXX|XXXXXX record_stockp = YYY|YYYYYY

   S:     $crash

   T:	During initialization immediately before the File System is
   activated, or when demounting a physical disk volume.

   M:	The supervisor databases pvt and stock_seg are not in proper
   synchronization. The pointers printed are the locations of the databasse
   elements for which this condition has been detected. These pointers are
   useful to the site system programmers for analyzing the problem, which is
   probably a software malfunction. dskX_NN is the physical volume whose
   tables are affected.

   A:     $recover
   The free addresses which are lost may be recovered by a physical volume salvage.


   Message:
   stock_man: Attempt to free non-empty stock on dskX_NN: pvtep=XXX|XXXXXX record_stockp=YYY|YYYYYY

   S:     $crash

   T:	During initialization immediately before the File System is
   activated, or when demounting a physical disk volume.

   M:     Not all free addresses have been deposited to the Volume Map
   successfully for the disk volume indicated. This is indicative of a software
   malfunction. The pointers printed are useful to site system programmers in 
   analyzing the problem.

   A:     $recover
   The free addresses which are lost may be recovered by a physical volume salvage.

   Message:
   stock_man: PVTE out of synch with VTOCE stock on dskX_NN: pvtep = XXX|XXXXXX vtoce_stockp = YYY|YYYYYY

   S:     $crash

   T:     When demounting a physical disk volume.

   M:	The supervisor databases pvt and stock_seg are not in proper
   synchronization. The pointers printed are the locations of the databasse
   elements for which this condition has been detected. These pointers are
   useful to the site system programmers for analyzing the problem, which is
   probably a software malfunction. dskX_NN is the physical volume whose
   tables are affected. Some free VTOCEs may be lost.

   A:     $recover
   The lost VTOCEs can be recovered by a physical volume salvage.

   Message:
   stock_man: Attempt to free non-empty stock on dskX_NN: pvtep=XXX|XXXXXX vtoce_stockp=YYY|YYYYYY

   S:     $crash

   T:     When demounting a physical disk volume.

   M:     Not all free VTOCEs have been deposited to the VTOC Map
   successfully for the disk volume indicated. This is indicative of a software
   malfunction. The pointers printed are useful to site system programmers in 
   analyzing the problem.

   A:     $recover
   The free VTOCEs which are lost may be recovered by a physical volume salvage.


   END MESSAGE DOCUMENTATION */
     end stock_man$allocate_record_stock;




		    bull_copyright_notice.txt       08/30/05  1008.4r   08/30/05  1007.3    00020025

                                          -----------------------------------------------------------


Historical Background

This edition of the Multics software materials and documentation is provided and donated
to Massachusetts Institute of Technology by Group Bull including Bull HN Information Systems Inc. 
as a contribution to computer science knowledge.  
This donation is made also to give evidence of the common contributions of Massachusetts Institute of Technology,
Bell Laboratories, General Electric, Honeywell Information Systems Inc., Honeywell Bull Inc., Groupe Bull
and Bull HN Information Systems Inc. to the development of this operating system. 
Multics development was initiated by Massachusetts Institute of Technology Project MAC (1963-1970),
renamed the MIT Laboratory for Computer Science and Artificial Intelligence in the mid 1970s, under the leadership
of Professor Fernando Jose Corbato.Users consider that Multics provided the best software architecture for 
managing computer hardware properly and for executing programs. Many subsequent operating systems
incorporated Multics principles.
Multics was distributed in 1975 to 2000 by Group Bull in Europe , and in the U.S. by Bull HN Information Systems Inc., 
as successor in interest by change in name only to Honeywell Bull Inc. and Honeywell Information Systems Inc. .

                                          -----------------------------------------------------------

Permission to use, copy, modify, and distribute these programs and their documentation for any purpose and without
fee is hereby granted,provided that the below copyright notice and historical background appear in all copies
and that both the copyright notice and historical background and this permission notice appear in supporting
documentation, and that the names of MIT, HIS, Bull or Bull HN not be used in advertising or publicity pertaining
to distribution of the programs without specific prior written permission.
    Copyright 1972 by Massachusetts Institute of Technology and Honeywell Information Systems Inc.
    Copyright 2006 by Bull HN Information Systems Inc.
    Copyright 2006 by Bull SAS
    All Rights Reserved
