1 /****^  ***********************************************************
  2         *                                                         *
  3         * Copyright, (C) Honeywell Bull Inc., 1987                *
  4         *                                                         *
  5         * Copyright, (C) Honeywell Information Systems Inc., 1982 *
  6         *                                                         *
  7         * Copyright (c) 1972 by Massachusetts Institute of        *
  8         * Technology and Honeywell Information Systems, Inc.      *
  9         *                                                         *
 10         *********************************************************** */
 11 
 12 
 13 /****^  HISTORY COMMENTS:
 14   1) change(85-09-09,Farley), approve(85-09-09,MCR6979),
 15      audit(86-03-08,CLJones), install(86-03-21,MR12.0-1033):
 16      Add IPC FIPS card and
 17      allow FIPS device number zero.
 18   2) change(86-01-09,Fawcett), approve(86-04-11,MCR7383),
 19      audit(86-07-07,GDixon), install(86-07-17,MR12.0-1097):
 20      Add subvolume support for MSU3380 and MSU3390.
 21   3) change(86-06-05,GJohnson), approve(86-06-05,MCR7387),
 22      audit(86-06-10,Martinson), install(86-07-17,MR12.0-1091):
 23      Correct error message documentation.
 24                                                    END HISTORY COMMENTS */
 25 
 26 
 27 /* format: style2 */
 28 init_pvt:
 29      procedure;
 30 
 31 /* format: off */
 32 /* *      INIT_PVT
 33    *
 34    *      This procedure initializes the Physical Volume Table to describe all the configured
 35    *      disk drives. It does this by looking at all the PRPH DSKx cards in the config deck.
 36    *      It expect the PVT to have already been allocated by get_io_segs, which went through
 37    *      much the same sort of drive-counting exercise to do so. This procedure does no I/O,
 38    *      but only sets up the table. It is equivalent in function to the early part of the
 39    *      old init_pvt, which was split into many separate programs.
 40    *
 41    *       HISTORY
 42    *
 43    *      Keith Loepere 10/83 to not set write_limit for early initialization.
 44    *      E. N. Kittlitz 9/83 to allow drives up to 63, 32 drives per ss.
 45    *      BIM 7/82 to merge WOS's changes back against stocks and NPML.
 46    *      collect_free_core called from real_initializer, etc.
 47    *
 48    *      February 1982 by J. Bongiovanni for record stocks
 49    *      June 1981 by C. Hornig to eliminate PML.
 50    *      Modified 12/21/80 WOS to set sst.write_limit from number of disk subsystems (moved
 51    *        from make_segs_paged), and to zero fsmap SDWs on entry to allow for multiple calls.
 52    *      Modified 11/28/80, W. Olin Sibert, for Bootload Multics, and better error detection.
 53    *      Modified 11/27/80, WOS, to split from old init_pvt (to which earlier history refers)
 54    *      Modified  4/79, by Michael R. Jordan, for proper MSU500/501/509 initialization,
 55    *         and to detect some configuration errors.
 56    *      Modified  2/79, by Michael R. Jordan, for MSU500 support.
 57    *      Modified  7/78, by BSG, for MANY hardcore partitions
 58    *      Modified  3/77, by THVV, for more vol maps than will fit in one segment
 59    *      Modified  6/76, by D. R. Vinograd, to initialize Volume Dumper variables
 60    *      Modified throughout 1975, by THVV & BSG, for NSS.
 61    *      Modified 12/74, by THVV, for NSS
 62    */
 63 /* format: on */
 64 
 65           dcl     char4                  char (4) aligned;
 66           dcl     dcp                    (32) pointer unaligned;
 67                                                             /* Array of pointers to PRPH DSKx card for each subsystem */
 68 
 69           dcl     device_type            fixed bin;
 70           dcl     drive_idx              fixed bin;
 71           dcl     driveno                fixed bin;         /* Index of drive being configured */
 72           dcl     group_idx              fixed bin;
 73           dcl     max_driveno            fixed bin;
 74           dcl     nd                     fixed bin;         /* Number of disk subsystems */
 75           dcl     pri_pvtep              ptr;
 76           dcl     pri_tx                 fixed bin;
 77           dcl     partition              char (4);
 78           dcl     ss_drive_count         fixed bin;         /* number of disks in subsystem under construction */
 79           dcl     subsys                 (32) char (4) aligned;
 80                                                             /* Array of subsystem names */
 81           dcl     subsys_idx             fixed bin;
 82           dcl     sv_cur                 fixed bin;
 83           dcl     swap                   bit (1) aligned;
 84           dcl     tx                     fixed bin;         /* PVTX of PVTE currently being assigned */
 85 
 86           dcl     sst$write_limit        fixed bin (35) ext static;
 87 
 88           dcl     config_$find           entry (char (4) aligned, ptr);
 89           dcl     config_$find_parm      entry (char (4) aligned, ptr);
 90 
 91           dcl     page$init              ext entry (fixed bin, ptr);
 92           dcl     syserr                 entry options (variable);
 93 
 94           dcl     WHOAMI                 char (32) internal static options (constant) init ("init_pvt");
 95           dcl     MAX_DRIVES_PER_SUBSYSTEM
 96                                          fixed bin init (32) int static options (constant);
 97 
 98           dcl     (
 99                   VOLMAP_LOCK_WAIT_CONSTANT
100                                          init ("444000000000"b3),
101                   VOLMAP_IDLE_WAIT_CONSTANT
102                                          init ("445000000000"b3),
103                   VTOC_MAP_LOCK_WAIT_CONSTANT
104                                          init ("446000000000"b3)
105                   )                      bit (36) aligned int static options (constant);
106 
107 
108           dcl     (addr, addrel, clock, divide, hbound, max, null, ptr, size, substr)
109                                          builtin;
110 
111 
112 %page;
113 /* Check setting and operation of system clock */
114 
115 /* Initialization */
116 
117           pvtp = addr (pvt$);                               /* Also locate world */
118           pvt_arrayp = addr (pvt.array);
119           pvt.time_of_bootload = clock ();
120           pvt.volmap_lock_wait_constant = VOLMAP_LOCK_WAIT_CONSTANT;
121           pvt.volmap_idle_wait_constant = VOLMAP_IDLE_WAIT_CONSTANT;
122           pvt.vtoc_map_lock_wait_constant = VTOC_MAP_LOCK_WAIT_CONSTANT;
123 
124           pvt.root_pvid = ""b;                              /* Initialize root id */
125           pvt.root_pvtx = -1;
126           pvt.root_vtocx = -1;                              /* not found it yet */
127 
128 /* Find all PRPH DSKn cards, and generate the PVT indices. */
129 
130           nd = 0;                                           /* Count subsystems */
131           prph_dsk_cardp = null;
132 NEXT_DISK_CARD:
133           call config_$find (PRPH_CARD_WORD, prph_dsk_cardp);
134                                                             /* Find subsystem description */
135           if prph_dsk_cardp ^= null
136           then do;                                          /* Count up this subsystem */
137                     if substr (prph_dsk_card.name, 1, 3) ^= "dsk"
138                     then goto NEXT_DISK_CARD;
139 
140                     do subsys_idx = 1 to nd;                /* Check for duplicates */
141                          if subsys (subsys_idx) = prph_dsk_card.name
142                          then call syserr (CRASH, "^a: Duplicate prph ^a card.", WHOAMI, prph_dsk_card.name);
143                     end;
144 
145                     nd = nd + 1;                            /* Found appropriate card. */
146                     if nd > hbound (subsys, 1)
147                     then /* Too many subsystems configured. */
148                          call syserr (CRASH, "^a: Too many disk subsystems configured. Limit is ^d.", WHOAMI,
149                               hbound (subsys, 1));
150 
151                     subsys (nd) = prph_dsk_card.name;       /* Save in scratch */
152                     dcp (nd) = prph_dsk_cardp;              /* .. */
153                     goto NEXT_DISK_CARD;                    /* Scan whole deck. */
154                end;
155 
156           if nd = 0
157           then /* Must be some subsystems */
158                call syserr (CRASH, "^a: no PRPH DSKn cards", WHOAMI);
159 
160 /* Sort the subsystems into canonical order */
161 
162           swap = "1"b;                                      /* Simple interchange sort */
163           do while (swap);                                  /* .. often there will be only one */
164                swap = "0"b;
165                do subsys_idx = 1 to nd - 1;
166                     if subsys (subsys_idx) > subsys (subsys_idx + 1)
167                     then do;
168                               swap = "1"b;                  /* interchange */
169                               prph_dsk_cardp = dcp (subsys_idx);
170                               dcp (subsys_idx) = dcp (subsys_idx + 1);
171                               dcp (subsys_idx + 1) = prph_dsk_cardp;
172 
173                               char4 = subsys (subsys_idx);
174                               subsys (subsys_idx) = subsys (subsys_idx + 1);
175                               subsys (subsys_idx + 1) = char4;
176                          end;
177                end;
178           end;
179 ^L
180 
181 /* Setup pointers in stock_seg before initializing any hardcore partition */
182 
183           stock_segp = addr (stock_seg$);
184           stock_seg.record_stock_arrayp = ptr (stock_segp, size (stock_seg));
185           stock_seg.vtoce_stock_arrayp =
186                addrel (stock_seg.record_stock_arrayp, stock_seg.n_stock_entries * stock_seg.record_stock_size);
187 ^L
188 
189 /* Generate PVT */
190 
191           tx = 0;                                           /* "tx" is the current PVT index */
192 SUBSYS_LOOP:
193           do subsys_idx = 1 to nd;                          /* Loop over subsystems */
194                prph_dsk_cardp = dcp (subsys_idx);           /* Get ptr to PRPH DSKn card */
195                if IS_FIPS_DEVICE ()
196                then do;
197                          driveno = -1;                      /* FIPS, will be zero. */
198                          max_driveno = 31;
199                     end;
200                else do;
201                          driveno = 0;                       /* normal, will be one. */
202                          max_driveno = 63;
203                     end;
204                ss_drive_count = 0;
205 GROUP_LOOP:
206                do group_idx = 1 to hbound (prph_dsk_card_array.group, 1);
207                                                             /* Loop through all its drives */
208                     if prph_dsk_card.group (group_idx).ndrives = -1
209                                                             /* An error on the config card. */
210                     then call syserr (CRASH, "^a: Missing ndrives field on config card for ^a subsystem.", WHOAMI,
211                               prph_dsk_card.name);
212 
213                     if prph_dsk_card.group (group_idx).model = -1
214                     then call syserr (CRASH, "^a: Missing model field on config card for ^a subsystem.", WHOAMI,
215                               prph_dsk_card.name);
216                     if prph_dsk_card.group (group_idx).model = 0
217                     then do;                                /* Nonexistent drive */
218 
219                               driveno = driveno + prph_dsk_card.group (group_idx).ndrives;
220                               goto NEXT_DRIVE_GROUP;        /* Skip over the nonconfigured drives */
221                          end;
222 
223                     do device_type = 1 to hbound (MODEL, 1)
224                          while (prph_dsk_card.group (group_idx).model ^= MODEL (device_type));
225                     end;
226                     if device_type > hbound (MODEL, 1)
227                     then do;                                /* .. check model number */
228                               call syserr (CRASH, "init_pvt: Unknown model number ^d on prph ^a",
229                                    prph_dsk_card.group (group_idx).model, prph_dsk_card.name);
230                          end;
231                     device_type = MODELX (device_type);     /* Set device type */
232 
233 DRIVE_LOOP:
234                     do drive_idx = 1 to prph_dsk_card.group (group_idx).ndrives;
235                                                             /* Generate a PVTE for each possible drive */
236                          driveno = driveno + 1;             /* Contiguous alloc of drive nos */
237 
238                          if driveno > max_driveno           /* check IDCW unit limit */
239                          then call syserr (CRASH, "^a: ^a contains a drive number higher than ^d.", WHOAMI,
240                                    prph_dsk_card.name, max_driveno);
241                          ss_drive_count = ss_drive_count + 1;
242                          if ss_drive_count > MAX_DRIVES_PER_SUBSYSTEM
243                          then call syserr (CRASH, "^a: More than ^d drives defined for ^a.", WHOAMI,
244                                    MAX_DRIVES_PER_SUBSYSTEM, prph_dsk_card.name);
245                          tx = tx + 1;                       /* Generate PVTX */
246                          pvtep = addr (pvt_array (tx));     /* Get ptr to PVT entry */
247                          pvte.devname = prph_dsk_card.name; /* .. and fill in */
248                          pvte.logical_area_number = driveno;/* .. */
249                          pvte.device_type = device_type;    /* .. */
250                          pvte.storage_system = "1"b;        /* Until told otherwise */
251                          pvte.curn_dmpr_vtocx (*) = -1;
252                          pvte.volmap_stock_ptr = null ();
253                          pvte.vtoc_map_stock_ptr = null ();
254                          pvte.is_sv = (number_of_sv (device_type) >= 2);
255                          pvte.num_of_svs = number_of_sv (device_type);
256                          pvte.removable_pack = media_removable (device_type);
257                          pvte.records_per_cyl = rec_per_cyl (device_type);
258                          pri_tx = tx;
259                          pri_pvtep = pvtep;
260                          if pvte.is_sv
261                          then do;                           /* build first subvolume pvte */
262                                    pvte.sv_num = 0;         /* number of this subvolume */
263                                    pvte.sv_name = valid_sv_array (pvte.sv_num);
264                                    pvte.record_factor = pvte.sv_num * rec_per_cyl (device_type);
265                                    call page$init (pri_tx, prph_dsk_cardp);
266                                                             /* Turn on disk DIM for drive */
267                                    do sv_cur = 2 to number_of_sv (device_type);
268                                         tx = tx + 1;        /* make another pvt entry */
269                                         pvtep = addr (pvt_array (tx));
270                                         pvte = pri_pvtep -> pvte;
271                                                             /* just like the first  except for */
272                                         pvte.sv_num = sv_cur - 1;
273                                                             /* number of this subvolume */
274                                         pvte.sv_name = valid_sv_array (pvte.sv_num);
275                                         pvte.record_factor = pvte.sv_num * rec_per_cyl (device_type);
276 
277                                    end;
278                               end;
279                          else do;
280                                    pvte.sv_num = -1;
281                                    pvte.record_factor = 0;
282                                    pvte.sv_name = " ";
283                                    call page$init (pri_tx, prph_dsk_cardp);
284                                                             /* Turn on disk DIM for drive */
285                               end;
286 
287                     end DRIVE_LOOP;
288 NEXT_DRIVE_GROUP:
289                end GROUP_LOOP;
290           end SUBSYS_LOOP;
291 
292 
293           pvt.n_entries = tx;                               /* Set size of PVT */
294 
295           if sys_info$collection_1_phase = SERVICE_INITIALIZATION
296           then do;                                          /* otherwise, use value set in init_sst */
297                     sst$write_limit = 53 + max (0, 47 * (nd - 1));
298                                                             /* Olin's magic formula for sst.write_limit */
299 
300                     call config_$find_parm ("wlim", parm_ptr);
301                                                             /* See if the default should be overridden */
302                     if parm_ptr ^= null ()
303                     then /* A parameter was specified */
304                          if (numeric_parm.value < 2000) & (numeric_parm.value > 4)
305                          then /* And it looks plausible */
306                               sst$write_limit = numeric_parm.value;
307                          else call syserr (BEEP, "^a: Invalid parm wlim value ^d. Default of ^d used.", WHOAMI,
308                                    numeric_parm.value, sst$write_limit);
309                end;
310           return;                                           /* PVT is initialized */
311                                                             /* format: off */
312 
313 %page;
314 IS_FIPS_DEVICE:
315      proc () returns (bit (1));
316 
317 /*     The theory here is all drives on a channel must be either fips or non
318        fips, but not mixed. Therefore look at the first non-zero model number
319        and check config_data_ for device_0_valid  */
320 
321 dcl (i, j) fixed bin;
322 
323      do j = 1 to hbound (prph_dsk_card.group,1);
324         if prph_dsk_card.group(j).model ^= 0 then do;
325            do i = 1 to config_data_$disk_drive_model_names.count;
326               if config_data_$disk_drive_model_names.names (i).model =
327                  prph_dsk_card.group (j).model then
328                  return (config_data_$disk_drive_model_names.names (i).device_0_valid);
329               end;
330            end;
331         end;
332      return ("0"b);
333      end IS_FIPS_DEVICE;
334 %page; %include collection_1_phases;
335 %page; %include config_prph_dsk_card;
336 %include config_prph_card;
337 %include config_parm_card;
338 %page; %include config_data_dcls;
339 %page; %include fs_dev_types;
340 %page; %include pvt;
341 %page; %include pvte;
342 %page; %include stock_seg;
343 %page; %include syserr_constants;
344 %page;
345 
346 /* BEGIN MESSAGE DOCUMENTATION
347 
348 
349     Message:
350     init_pvt: Duplicate prph DISK_NAME card.
351 
352     S:    $crash
353 
354     T:    $init
355 
356     M:    Two different PRPH cards define DISK_NAME.
357 
358     A:    Fix the config deck.
359 
360     Message:
361     init_pvt: no PRPH DSKn cards
362 
363     S:    $crash
364 
365     T:    $init
366 
367     M:    No PRPH cards describing disk subsystems were found in the CONFIG deck.
368 
369     A:    Correct the CONFIG deck to include the correct PRPH cards to describe
370     the disk subsystems present, and reboot.
371 
372 
373     Message:
374     init_pvt: XXXX contains a drive number higher than N.
375 
376     S:    $crash
377 
378     T:    $init
379 
380     M:    The PRPH card for disk subsystem XXXX specified disk(s) with addresses
381     larger than tha maximum allowable device number, N.
382 
383     A:    $recover
384     Correct the configuration deck and reboot.
385 
386     Message:
387     init_pvt: More than N drives defined for XXXX.
388 
389     S:    $crash
390 
391     T:    $init
392 
393     M:    The PRPH card for disk subsystem XXXX specified more than the maximum
394     allowable number of disk drives.
395 
396     A:    $recover
397     Correct the configuration deck and reboot.
398 
399     Message:
400     init_pvt: Too many disk subsystems configured. Limit is NUMBER.
401 
402     S:    $crash
403 
404     T:    $init
405 
406     M:    More than NUMBER subsystems are defined. Only NUMBER are allowed.
407 
408     A:    Rearrange the config deck for disks and try again.
409 
410     Message:
411     init_pvt: Missing ndrives field on config card for DISK subsystem.
412 
413     S:    $crash
414 
415     T:    $init
416 
417     M:    The PRPH DSK card for DISK lacks the ndrives parameter for
418     some model.
419 
420     A:    Fix the config deck.
421 
422     Message:
423     init_pvt: Unknown model MODEL on PRPH DISK.
424 
425     S:    $crash
426 
427     T:    $init
428 
429     M:    The model number MODEL specified somewhere on the prph DISK card
430     is not a legal model number.
431 
432     A:    Fix the config deck.
433 
434 
435     Message:
436     init_pvt: Missing model MODEL on PRPH DISK.
437 
438     S:    $crash
439 
440     T:    $init
441 
442     M:    There was no model number specified on the prph DISK card.
443 
444     A:    Fix the config deck.
445 
446     Message:
447     init_pvt: Invalid parm wlim value WLIM. Default of DEFAULT used.
448 
449     S:    $beep
450 
451     T:    $init
452 
453     M:    An unreasonable value (WLIM) was found on a PARM WLIM
454     card. DEFAULT has be substituted.
455 
456     A:    Fix the config deck.
457 
458    END MESSAGE DOCUMENTATION */
459 
460      end init_pvt;