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 
 14 
 15 /****^  HISTORY COMMENTS:
 16   1) change(2022-08-24,Swenson), approve(2022-08-24,MCR10120),
 17      audit(2022-08-24,GDixon), install(2022-09-06,MR12.8-1037):
 18      Fix interpretation of ID PROM fields in CPU start syserr messages.
 19   2) change(2023-07-19,Swenson), approve(2023-07-19,MCR10137),
 20      audit(2023-07-19,GDixon), install(2023-07-19,MR12.8-1063):
 21      Updated to display new PROM fields on CPU startup. Updated to display CPU
 22      message on console.  Added warning when running on old simulators.
 23                                                    END HISTORY COMMENTS */
 24 
 25 
 26 
 27 /* format: style4,delnl,insnl,tree,ifthenstmt,indnoniterend */
 28 tc_init:
 29      proc;
 30 
 31 /* This program initializes the various traffic controller data bases, the idle process
 32    data bases, and starts up the traffic controller. The entry part_2 is called after paging is
 33    operative and after the initializer's descriptor segment has all permanent hardcore SDW's filled
 34    in. It creates the idle processes and turns ON multiprogramming after starting the bootload cpu.
 35    The entry start_other_cpus is called late in initialization to get the other processors running.
 36 */
 37 
 38 /* Last modified (date and reason):
 39    5/11/77 by RE Mullen for concurrent scheduler
 40    2/4/76 by S. Webber rewrite for new reconfiguration
 41    4/20/77 by B. Greenberg for PRDS renaming
 42    6/21/77 by M. Weaver to move template_pds stuff to part_2
 43    5/10/79 by B. Greenberg for stack_0 sharing
 44    10/29/80 by M. Pierret for pin_weight and io_priority
 45    3/5/81 by J. Bongiovanni for site-settable prds size
 46    11/11/81 by J. A. Bush to display contents of bootload cpu ID PROM (DPS8 CPU)
 47    before adding  other cpus whose state is "ON".
 48    04/04/81 by W. Olin Sibert, to remove direct SDW hacking
 49    01/09/81 by W. Olin Sibert, to make it runnable twice for Bootload Multics.
 50    4/27/82 by J. Bongiovanni for wcte.interactive_q, gv_integration
 51    7/15/82 by BIM to merge Siberts changes with Bongiovanni's.
 52    8/13/82 by BIM to fiddle, once again, with PID's.
 53    9/17/82 by J. Bongiovanni for tc_data$abort_ips_mask
 54    2/16/83 by E. N. Kittlitz for hex floating point.
 55    6/27/83 by Keith Loepere for early entrypoint.
 56    830728 by E. A. Ranzenbach for operator console polling time.
 57    10/4/83 by Keith Loepere for paged idle_pdses and idle_dsegs.
 58    84.11.15 by M. Pandolf to include hc_lock.
 59    11/05/84 by Keith Loepere to rename terminate  to terminate_.
 60    Modified 1984-11-12 by E. Swenson for IPC event channel validation.
 61    The value of apte.ipc_r_offset is initialized here for the
 62    Initializer process.
 63    Modified March 1985 by Keith Loepere to fix a bug in multiple pass init.
 64 */
 65 
 66 /* Automatic */
 67 
 68 dcl  early_call bit (1) aligned;
 69 dcl  n_words fixed bin (18);
 70 dcl  first_segno fixed bin;
 71 dcl  processor_index fixed bin;
 72 dcl  prdsp ptr;
 73 dcl  no_apt fixed bin;
 74 dcl  no_itt fixed bin;
 75 dcl  tc_data_size fixed bin (18);
 76 dcl  tc_data_no fixed bin;
 77 dcl  tc_data_header_no fixed bin;
 78 dcl  tc_data_header_ptr pointer;
 79 dcl  tsdw fixed bin (71);
 80 dcl  i fixed bin;
 81 dcl  template_pds_size fixed bin (18);
 82 dcl  idle_pds_p ptr;
 83 dcl  aptp ptr;
 84 dcl  aptx fixed bin;
 85 dcl  ittp ptr;
 86 dcl  ittx fixed bin;
 87 dcl  tsize fixed bin (18);
 88 dcl  time fixed bin (71);
 89 dcl  code fixed bin (35);
 90 dcl  prds_name char (32);
 91 dcl  prds_length_kw fixed bin;
 92 dcl  cpu_model char (11) aligned;                      /* cpu model number (offset 0 in ID PROM) */
 93 dcl  cpu_serial char (11) aligned;                     /* cpu serial number (offset 11 in ID PROM) */
 94 dcl  cpu_ship_date char (6) aligned;                   /* cpu ship date (offset 22 in ID PROM) */
 95 dcl  prom_layout_version     char (1) aligned;          /* emu layout version (offfset 60 in ID PROM) */
 96 dcl  prom_commit_date        char (10) aligned;         /* emu commit date (offset 70 in ID PROM) */
 97 dcl  prom_major_rel_version  char (3) aligned;          /* emu major release version (offset 80 in ID PROM) */
 98 dcl  prom_minor_rel_version  char (3) aligned;          /* emu minor release version (offset 83 in ID PROM) */
 99 dcl  prom_patch_version      char (3) aligned;          /* emu patch version (offset 86 in ID PROM) */
100 dcl  prom_iteration_number   char (3) aligned;          /* emu iteration number (offset 89 in ID PROM) */
101 dcl  prom_build_number       char (8) aligned;          /* emu build number (offset 92 in ID PROM) */
102 dcl  prom_release_type       char (1) aligned;          /* emu release type (offset 100 in ID PROM) */
103 dcl  prom_version_text       char (29) aligned;         /* emu version text (offset 101 in ID PROM) */
104 dcl  prom_build_arch         char (20) aligned;         /* emu build architecture (offset 130 in ID PROM) */
105 dcl  prom_build_os           char (20) aligned;         /* emu build OS (offset 150 in ID PROM) */
106 dcl  prom_target_arch        char (20) aligned;         /* emu build architecture (offset 170 in ID PROM) */
107 dcl  prom_target_os          char (20) aligned;         /* emu build OS (offset 190 in ID PROM) */
108 
109 dcl  prom_build_number2      char (8) aligned;          /* possibly trimmed build number */
110 
111 dcl  table_value fixed bin;
112 dcl  dseg_no fixed bin static;
113 dcl  pds_no fixed bin static;
114 dcl  prds_no fixed bin static;
115 dcl  template_pds_p ptr static;
116 dcl  tag fixed bin static;
117 dcl  idle_dsegs_sdw fixed bin (71) internal static;         /* pointers and SDWs for idle_dsegs$ and idle_pdses */
118 dcl  idle_pdses_sdw fixed bin (71) internal static;
119 dcl  idle_dsegs_p ptr static;
120 dcl  idle_pdses_p ptr static;
121 dcl  dseg_size fixed bin (18) internal static;              /* Amount to actually copy into idle dseg */
122 dcl  pds_size fixed bin (18) static;
123 
124 dcl  header (n_words) fixed bin based;
125 dcl  copy_id bit (36) aligned based;
126 dcl  copy_ptr ptr based;
127 dcl  copy_group_id char (32) aligned based;
128 dcl  copy_pds (pds_size) fixed bin based;
129 dcl  copy_dseg (0:255) fixed bin (71) based;                /* stop copying before init segs */
130 dcl  1 apt (1) aligned like apte based (aptp);
131 dcl  1 itt (1) aligned based (ittp),
132        2 fp bit (18) unaligned,
133        2 bp bit (18) unaligned,
134        2 filler (7) fixed bin;
135 
136 dcl  append$branchx
137           entry (char (*), char (*), fixed bin (5), (3) fixed bin, char (*), fixed bin, fixed bin, fixed bin,
138           fixed bin (35));
139 dcl  chname$cfile entry (char (*), char (*), char (*), char (*), fixed bin (35));
140 dcl  config_$find entry (char (4) aligned, ptr);
141 dcl  config_$find_table entry (char (4) aligned, fixed bin);
142 dcl  delentry$dfile entry (char (*), char (*), fixed bin (35));
143 dcl  getuid entry returns (bit (36) aligned);
144 dcl  get_main entry (ptr, fixed bin (18), fixed bin (71));
145 dcl  get_ptrs_$given_segno entry (fixed bin) returns (ptr);
146 dcl  grab_aste$prewithdraw entry (ptr, fixed bin (19), fixed bin (35)) returns (ptr);
147 dcl  init_processor$init entry;
148 dcl  init_processor$return entry ext;
149 dcl  initiate entry (char (*), char (*), char (*), fixed bin, fixed bin, ptr, fixed bin (35));
150 dcl  pmut$swap_sdw entry (ptr, ptr);
151 dcl  privileged_mode_ut$read_id_prom entry (char (*) aligned, fixed bin);
152 dcl  pxss$get_entry entry (ptr);
153 dcl  sdw_util_$construct entry (ptr, ptr);
154 dcl  sdw_util_$dissect entry (ptr, ptr);
155 dcl  start_cpu entry (fixed bin, fixed bin (35));
156 dcl  syserr entry options (variable);
157 dcl  syserr$error_code entry options (variable);
158 dcl  terminate_$teseg entry (ptr, fixed bin (1), fixed bin (35));
159 dcl  thread$cin entry (ptr, bit (18) unaligned);
160 
161 dcl  active_all_rings_data$stack_base_segno fixed bin (18) ext;
162 dcl  dseg$ (0:1023) fixed bin (71) external static;
163 dcl  error_table_$noentry external fixed bin (35);
164 dcl  idle_pdses$ (0:16383) fixed bin external static;
165 dcl  idle_dsegs$ (0:8191) fixed bin (71) external static;   /* All the idle process DSEGs */
166 dcl  prds$ ext;
167 dcl  prds$processor_tag fixed bin (3) external;
168 dcl  slt$ ext;
169 dcl  sys_info$hfp_exponent_available bit (1) aligned external;
170 dcl  sys_info$quit_mask bit (36) aligned external;
171 dcl  sys_info$susp_mask bit (36) aligned external;
172 dcl  sys_info$term_mask bit (36) aligned external;
173 dcl  sys_info$system_type fixed bin external static;
174 dcl  tc_data$ ext;
175 dcl  tc_data$prds_length fixed bin (19) external;
176 dcl  tc_data_header$ fixed bin external static;
177 
178 dcl  pds$ ext;
179 dcl  pds$apt_ptr ptr ext;
180 dcl  pds$data fixed bin ext;
181 dcl  pds$lock_id bit (36) aligned external;
182 dcl  pds$dstep bit (18) aligned ext;
183 dcl  pds$initial_procedure ptr ext;
184 dcl  pds$process_group_id char (32) ext;
185 dcl  pds$processid bit (36) aligned ext;
186 dcl  pds$stack_0_ptr ptr ext;
187 dcl  pds$stack_0_sdwp ptr ext;
188 dcl  pds$trace ext;
189 
190 dcl  template_pds$ ext;
191 dcl  template_pds$quota_inhib fixed bin external;
192 dcl  template_pds$save_history_regs bit (1) aligned external;
193 dcl  template_pds$apt_ptr ptr ext;
194 dcl  template_pds$initial_procedure ptr ext;
195 dcl  template_pds$process_group_id char (32) ext;
196 dcl  template_pds$processid bit (36) aligned ext;
197 dcl  template_pds$stack_0_sdwp ptr ext;
198 dcl  template_pds$stack_0_ptr ptr ext;
199 
200 dcl  LETTERS char (8) internal static options (constant) init ("ABCDEFGH");
201 dcl  PRDS_DIR char (32) internal static options (constant) init (">system_library_1");
202 dcl  RW_mode fixed bin (5) internal static options (constant) init (01010b);
203 dcl  seg_rb (3) fixed bin internal static options (constant) init (0, 0, 0);
204 
205 dcl  (addr, addrel, baseno, baseptr, bin, binary, bit, clock, divide, hbound, lbound, max, min, null, ptr, rel, size,
206      string, substr, unspec) builtin;
207 %page;
208           early_call = "0"b;
209           go to part_1;
210 
211 early:
212      entry;
213           early_call = "1"b;
214 
215 part_1:
216           tcmp = addr (tc_data$);                           /* get necessary pointers, etc. */
217           idle_pdses_p = addr (idle_pdses$);
218           idle_dsegs_p = addr (idle_dsegs$);
219           tc_data_no = bin (baseno (tcmp), 18);
220           tc_data_header_ptr = addr (tc_data_header$);
221           tc_data_header_no = binary (baseno (tc_data_header_ptr), 18);
222           pds_no = bin (baseno (addr (pds$)), 18);
223           dseg_no = bin (baseno (addr (dseg$)), 18);
224           prds_no = bin (baseno (addr (prds$)), 18);
225 
226           if dseg$ (tc_data_header_no) = 0 then do;         /* First time - make header valid */
227                addr (addr (slt$) -> slt.seg (tc_data_no)) -> slte.paged = "0"b;
228                                                             /* Force to low memory */
229                call pmut$swap_sdw (tc_data_header_ptr, addr (dseg$ (tc_data_no)));
230                end;
231 
232           n_words = bin (rel (addr (tcm.apt)), 18);
233           tag = scs$bos_processor_tag;
234 
235           if early_call then do;
236                no_apt = 4;
237                no_itt = 20;
238                end;
239           else do;
240                tcd_cardp = null ();
241                call config_$find (TCD_CARD_WORD, tcd_cardp);/* get TCD card for sizes of APT and ITT. */
242                if tcd_cardp = null () then do;              /* not found, use defaults */
243                     no_apt = tc_data_header_ptr -> tcm.apt_size;
244                     no_itt = tc_data_header_ptr -> tcm.itt_size;
245                     end;
246                else do;                                     /* use values from card */
247                     no_apt = tcd_card.no_apt;
248                     no_itt = tcd_card.no_itt;
249                     end;
250                end;
251 
252 /* Now, allocate the new tc_data in wired memory. The header specifies it as paged, since
253    the header is created as a cds and must be copied into the wired tc_data. The first time
254    this code is executed, the tc_data_header segment will be created (defined in the header
255    as a zero length fabricated segment) as a segment defining the version of tc_data read
256    from the tape, which contains only the tc_data header. Subsequently, tc_data is allocated
257    in wired memory, and the header (defined by tc_data_header) is copied into it.
258 */
259 
260           tc_data_size = n_words + no_apt * size (apt) + no_itt * size (itt);
261 
262           call get_main (tcmp, tc_data_size, tsdw);         /* get storage for tc_data */
263           call pmut$swap_sdw (tcmp, addr (tsdw));           /* copy tc_data into new storage */
264           tcmp -> header = tc_data_header_ptr -> header;    /* copy header */
265 
266 /* We are now using the new wired version of tc_data. */
267 
268           tcm.apt_size = no_apt;
269           tcm.itt_size = no_itt;
270 
271           tcm.system_type = sys_info$system_type;           /* Remember this fellow here */
272 
273 /* Init WCTE's, then setup first two for self and others respectively. */
274 
275 
276           do i = 0 to 16;
277                tcm.wcte (i).fp, tcm.wcte (i).bp = rel (addr (tcm.wcte (i)));
278                tcm.wcte (i).mnbz = "1"b;                    /* Make this a sentinel */
279                tcm.wcte (i).resp1 = 2 * 1024 * 1024;
280                tcm.wcte (i).quantum1 = 1024 * 1024;
281                tcm.wcte (i).resp2 = 64 * 1024 * 1024;
282                tcm.wcte (i).quantum2 = 2 * 1024 * 1024;
283                tcm.wcte (i).realtime = 0;
284                tcm.wcte (i).purging = 1;
285                tcm.wcte (i).maxel = 0;                      /* 0 means no limit */
286                tcm.wcte (i).nel = 0;
287                tcm.wcte (i).pin_weight = 1;
288                tcm.wcte (i).flags.io_priority = "0"b;
289                tcm.wcte (i).flags.interactive_q = "1"b;
290           end;
291 
292 
293 
294           tcm.credits_per_scatter = 512 * 1024;             /* passout this many credits this often */
295                                                             /* credits are in microseconds */
296           tcm.wcte (0).flags.defined = "1"b;
297           tcm.wcte (0).flags.io_priority = "1"b;
298           tcm.wcte (0).minf = 256 * 1024;                   /* 50% for Initializer if need be. */
299           tcm.wcte (0).resp1, tcm.wcte (0).resp2 = 256 * 1024;
300                                                             /* within 1/4 sec */
301           tcm.wcte (0).quantum1, tcm.wcte (0).quantum2 = 2 * 1024 * 1024;
302                                                             /* give 2 sec */
303           tcm.wcte (0).pin_weight = 3;                      /* This number may have to be tuned */
304           tcm.wcte (0).realtime = 1;
305           tcm.wcte (1).flags.defined = "1"b;
306           tcm.wcte (1).minf = 512 * 1024;                   /* and 100% for everybody else. */
307                                                             /* The initializer does not generate credits */
308           tcm.min_wct_index = rel (addr (tcm.wcte (0)));
309           tcm.max_wct_index = rel (addr (tcm.wcte (1)));
310 
311 /* Now set up the APT */
312 
313           aptp = ptr (tcmp, n_words);                       /* APT is right after header */
314           tcm.empty_q = rel (aptp);                         /* thread first into empty list */
315           do aptx = 1 to no_apt - 1;
316                apt (aptx).fp = rel (addr (apt (aptx + 1)));
317                apt (aptx).lock = "777777"b3;                /* init to unlocked, anyting but zero */
318           end;
319           apt (no_apt).lock = "777777"b3;                   /* init to unlocked, anyting but zero */
320 
321           tcm.stat (0) = no_apt;                            /* all processes are empty */
322 
323 /* Now do the ITT */
324 
325           tcm.used_itt = 0;
326           ittp = addr (apt (no_apt + 1));
327           do ittx = 1 to no_itt - 1;
328                itt (ittx).fp = rel (addr (itt (ittx + 1)));
329           end;
330           itt (no_itt).fp = (18)"1"b;                       /* head -1 when all itte taken, 0 means locked */
331           tcm.itt_free_list = rel (ittp);
332           tcm.cid2 = divide (no_itt - no_apt, 2, 18, 0);
333           tcm.cid3 = divide (no_itt - no_apt, 3, 18, 0);
334           tcm.cid4 = divide (no_itt - no_apt, 4, 18, 0);
335 
336 /* Fill in data from SCHD card. */
337 
338           schd_cardp = null ();                             /* search for config card */
339           call config_$find (SCHD_CARD_WORD, schd_cardp);
340           if schd_cardp ^= null () then do;                 /* if found */
341                tcm.working_set_factor = schd_card.ws_factor;
342                tcm.tefirst = schd_card.tefirst * 125000;
343                tcm.telast = schd_card.telast * 125000;
344                tcm.timax = schd_card.timax * 125000;
345                if schd_card.min_eligible > 0 then tcm.min_eligible = schd_card.min_eligible * 262144;
346                if schd_card.max_eligible > 0
347                then if schd_card.max_eligible * 262144 >= tcm.min_eligible
348                     then tcm.max_eligible = schd_card.max_eligible * 262144;
349                if schd_card.max_max_eligible > 0 & schd_card.max_max_eligible < 1000
350                then tcm.max_max_eligible = schd_card.max_max_eligible * 262144;
351                else tcm.max_max_eligible = tcm.max_eligible + (10 * 262144);
352                end;
353 
354           if (tcm.max_eligible + tcm.max_stopped_stack_0 * 262144) <= tcm.max_max_eligible
355                & tcm.min_eligible <= tcm.max_eligible
356           then ;                                            /* All OK */
357           else call syserr (1, "Inconsistent SCHD config card values.");
358 
359           tcm.gv_integration = 4 * tcm.telast;
360 
361           tcm.abort_ips_mask = sys_info$quit_mask | sys_info$susp_mask | sys_info$term_mask;
362 
363 /* Set up the length of the prds, either from the slt or the TBLS Config Card                                 */
364 
365           sltep = addr (addr (slt$) -> slt.seg (prds_no));
366           prds_length_kw = max (slte_uns.cur_length, slte_uns.max_length);
367                                                             /* default */
368 
369           call config_$find_table ("prds", table_value);    /* See if a TBLS PRDS card is to be found */
370           if (table_value >= 0) & (table_value < prds_length_kw)
371           then call syserr (ANNOUNCE, "tc_init: Size of PRDS on TBLS card too small; ^d KW will be used.", prds_length_kw)
372                     ;
373 
374           if table_value > 0 then prds_length_kw = min (255, table_value);
375                                                             /* Don't let it be too big */
376                                                             /* else just stick with default */
377 
378           tcm.prds_length = 1024 * prds_length_kw;
379           slte_uns.cur_length, slte_uns.max_length = prds_length_kw;
380 
381 /* Allocate the stack_0_data segment */
382 
383           sdtp = addr (stack_0_data$);
384           stack_0_data_init_number_of_stacks = divide (tcm.max_max_eligible, 262144, 17, 0);
385           call get_main (sdtp, size (sdt), tsdw);
386           call pmut$swap_sdw (sdtp, addr (tsdw));
387           sdt.num_stacks = stack_0_data_init_number_of_stacks;
388           unspec (sdt) = ""b;
389           sdt.num_stacks = stack_0_data_init_number_of_stacks;
390 
391 /* Allocate the APT entries for the initializer and the idle processes.
392    Also figure out the total size of idle_dsegs and idle_pdses. */
393 
394           tsize = 0;
395           call pxss$get_entry (aptep);
396           pds$apt_ptr = aptep;
397           do i = 0 to 7;
398                if scs$processor_data (i).offline then do;   /* All cpus are flagged as offline at this point */
399                     call pxss$get_entry (aptep);
400                     scs$idle_aptep (i) = aptep;
401                     tsize = tsize + 1;
402                     end;
403           end;
404 
405 /* Now get the DSEGs and PDSs for the idle procs */
406 
407 /* Now get enough storage for the PDSes and DSEGs */
408 
409           if sys_info$system_type = ADP_SYSTEM then do;     /* For the ADP, because of cache sharing/overlap problems */
410                dseg_size = 2048;                            /* each of these must be two pages. No further special */
411                pds_size = 2048;                             /* casing need be done, since the initialization DSEG and */
412                end;                                         /* PDS are already this large */
413 
414           else do;                                          /* otherwise one page is more than enough */
415                dseg_size = 1024;
416                pds_size = 1024;
417                end;
418 
419           call get_main (idle_dsegs_p, tsize * dseg_size, idle_dsegs_sdw);
420 
421           call get_main (idle_pdses_p, tsize * pds_size, idle_pdses_sdw);
422 
423           call pmut$swap_sdw (idle_dsegs_p, addr (idle_dsegs_sdw));
424           call pmut$swap_sdw (idle_pdses_p, addr (idle_pdses_sdw));
425           return;
426 %page;
427 part_2:
428      entry;
429 
430 /* This entry is called after the initializer's DSEG is filled in and after paged segments
431    have their ASTE's. It completes initialization of the traffic controller, starts the
432    bootload CPU, and turns on multiprogramming. */
433 
434           tcmp = addr (tc_data$);
435 
436 /* Now initialize the template_pds segment */
437 
438           template_pds_size = bin (rel (addr (pds$data)), 18);
439                                                             /* get size to copy */
440           tcm.pdscopyl = template_pds_size;                 /* save for later process creations */
441 
442           template_pds_p = addr (template_pds$);            /* get pointer to template_pds */
443 
444 /* Now fill in some variables in template_pds */
445 
446           template_pds$quota_inhib = 0;
447           template_pds$save_history_regs = "0"b;
448           template_pds$stack_0_ptr = baseptr (active_all_rings_data$stack_base_segno);
449           template_pds$stack_0_sdwp = addr (dseg$ (binary (baseno (template_pds$stack_0_ptr))));
450           template_pds$processid = "444444444444"b3;
451           template_pds$apt_ptr = null ();
452           template_pds$process_group_id = "Idle.SysControl.z";
453           template_pds$initial_procedure = null ();
454 
455           processor_index = -1;
456           do i = lbound (scs$processor_data, 1) to hbound (scs$processor_data, 1);
457                                                             /* loop through all possible processors */
458                if scs$processor_data (i).offline then do;   /* Only do it for configurable CPUs */
459                                                             /* All cpus are flagged as offline at this point */
460                     processor_index = processor_index + 1;
461                     first_segno = processor_index * divide (dseg_size, 2, 17, 0);
462                                                             /* index, in idle_dsegs$, of first SDW for this */
463                     addr (idle_dsegs$ (first_segno)) -> copy_dseg = addr (dseg$) -> copy_dseg;
464                                                             /* idle process */
465 
466                     idle_pds_p = addr (idle_pdses$ (processor_index * pds_size));
467                     idle_pds_p -> copy_pds = template_pds_p -> copy_pds;
468                                                             /* copy virgin pds */
469 
470                     addrel (idle_pds_p, rel (addr (pds$processid))) -> copy_id = rel (scs$idle_aptep (i)) || "555555"b3;
471                     addrel (idle_pds_p, rel (addr (pds$apt_ptr))) -> copy_ptr = scs$idle_aptep (i);
472                     addrel (idle_pds_p, rel (addr (pds$stack_0_ptr))) -> copy_ptr = addr (prds$);
473                     addrel (idle_pds_p, rel (addr (pds$stack_0_sdwp))) -> copy_ptr =
474                          addr (dseg$ (binary (baseno (addr (prds$)))));
475                     substr (addrel (idle_pds_p, rel (addr (pds$process_group_id))) -> copy_group_id, 17, 1) =
476                          substr ("abcdefgh", i + 1, 1);
477                     addrel (idle_pds_p, rel (addr (pds$trace))) -> trace.last_available = 4;
478                     addrel (idle_pds_p, rel (addr (pds$trace))) -> trace.next_free = 0;
479 
480                     call shrink_sdw (idle_dsegs_sdw, processor_index * dseg_size, dseg_size, tsdw);
481                     idle_dsegs$ (first_segno + dseg_no) = tsdw;
482                     scs$idle_aptep (i) -> apte.dbr = tsdw;
483 
484                     call shrink_sdw (idle_pdses_sdw, processor_index * pds_size, pds_size, tsdw);
485                     idle_dsegs$ (first_segno + pds_no) = tsdw;
486                     end;
487           end;
488 
489 /* Now initialize the initializer process */
490 
491           pds$initial_procedure = addr (init_processor$return);
492           aptep = pds$apt_ptr;
493           pds$processid = rel (aptep) || (18)"1"b;
494           pds$stack_0_sdwp = addr (dseg$ (binary (baseno (pds$stack_0_ptr))));
495           tcm.initializer_id = pds$processid;
496           apte.wct_index = tcm.min_wct_index;
497           apte.deadline = clock ();
498           call thread$cin (aptep, tcm.eligible_q_head.fp);
499           apte.loaded = "1"b;
500           apte.eligible = "1"b;
501           apte.state = bit (bin (2, 18), 18);
502           apte.dbr = dseg$ (dseg_no);
503           apte.processid = pds$processid;
504           apte.lock_id = getuid ();
505           pds$lock_id = apte.lock_id;
506           apte.timax = 0;
507           apte.pds = rel (get_ptrs_$given_segno (pds_no));
508           apte.dseg = pds$dstep;
509 
510 /**** Here we set up apte.ipc_r_offset for the Initializer process.  This
511       is an 18-bit unsigned integer used by IPC to validate event channel
512       names in conjunction with apte.ipc_r_factor.  This latter number
513       is determined later, in init_proc.  This is done on order to provide
514       an undeterministic delay between the initialization of these two
515       numbers in order to make it difficult to guess one given the other. */
516 
517           apte.ipc_r_offset = binary (substr (bit (binary (clock (), 54), 54), 37, 18), 18);
518 
519 /**** Set the value of apte.ipc_r_factor to zero for debugging purposes
520       so that we can determine whether it is getting set or not later. */
521 
522           apte.ipc_r_factor = 0;
523 
524           aptep = scs$idle_aptep (tag);
525           apte.prds = rel (get_ptrs_$given_segno (prds_no));
526 
527           tcm.stat (2) = 1;                                 /* one process is ready */
528           tcm.wcte (0).nel = 1;                             /* one eligible in wc zero */
529 
530 /* Now set up miscellaneous tc_data variables */
531 
532           tcm.n_eligible = 1;
533           time = clock ();                                  /* get current time */
534           tcm.next_alarm_time = time;
535           tcm.opc_polling_time = time;
536           tcm.disk_polling_time = time;
537           tcm.tape_polling_time = time;
538           tcm.volmap_polling_time = time;
539           tcm.initialize_time = time;
540           tcm.define_wc_time = time;
541           tcm.nto_check_time = time;
542           tcm.nto_delta = 30000000;                         /* nto every 30 to 60 sec */
543 
544 /* Now finish up creating the first idle process */
545 
546           call init_processor$init;                         /* Initialize variables. */
547 
548           call start_cpu (tag, code);                       /* Now start bootload CPU idle process. */
549           if code ^= 0 then call syserr (CRASH, "tc_init: Cannot start up first idle process. Check switches.");
550 
551           tcm.wait_enable = 1;
552 
553           return;
554 %page;
555 shrink_sdw:
556      proc (old_sdw, base, bound, new_sdw);
557 
558 dcl  old_sdw fixed bin (71) parameter;
559 dcl  base fixed bin (24) parameter;
560 dcl  bound fixed bin (18) parameter;
561 dcl  new_sdw fixed bin (71) parameter;
562 
563 dcl  1 sdwi aligned like sdw_info automatic;
564 
565 
566           call sdw_util_$dissect (addr (old_sdw), addr (sdwi));
567                                                             /* Take the old one apart */
568           sdwi.address = sdwi.address + divide (base, 1024, 26);
569                                                             /* Alter the base and bounds appropriately
570                                                                (update the ptw address by n ptws) */
571           sdwi.size = bound;
572           call sdw_util_$construct (addr (new_sdw), addr (sdwi));
573                                                             /* And put it back */
574 
575      end shrink_sdw;
576 %page;
577 start_other_cpus:
578      entry;
579 
580 /* This entry is called late in initialization to start any
581    CPUs in the configuration that are marked as online in
582    the config deck */
583 
584 /* first, if the bootload cpu is a DPS8M, enter the contents of the ID PROM in
585    the syserr_log. We could not do it earlier in initialization beause syserr
586    logging was not enabled. */
587 
588           if scs$processor_data (tag).cpu_type > 0
589           then do;                                          /* if DPS8 cpu... */
590                if addr (scs$processor_switch_data (2)) -> dps8_rsw_2.id_prom then do;
591                                                             /* and id prom present */
592                     call privileged_mode_ut$read_id_prom (cpu_model, 0);
593                                                             /* get cpu model from ID PROM */
594                     call privileged_mode_ut$read_id_prom (cpu_serial, 11);
595                                                             /* get cpu serial # from ID PROM, at offset 13o */
596                     call privileged_mode_ut$read_id_prom (cpu_ship_date, 22);
597                                                             /* get ship date from ID PROM, at offset 26o */
598 
599                     call privileged_mode_ut$read_id_prom (prom_layout_version, 60);
600 
601                     /* log info from id prom */
602 
603                     if prom_layout_version = "ÿ" then do;
604                          if cpu_model = "DPS 8/SIM M" then
605                             call syserr (BEEP, "Warning: You are running an old version of the DPS8M simulator. ^/^-Please update to R3.0.1 or later. See https://dps8m.gitlab.io/ for details.");
606                          call syserr (ANNOUNCE, "CPU ^a: Model #: ^a; Serial #: ^a; Ship date: ^a.",
607                             substr ("ABCDEFGH", tag + 1, 1), cpu_model, cpu_serial, cpu_ship_date);
608                     end;
609                     else do;
610                          call privileged_mode_ut$read_id_prom (prom_commit_date, 70);
611                          call privileged_mode_ut$read_id_prom (prom_major_rel_version, 80);
612                          call privileged_mode_ut$read_id_prom (prom_minor_rel_version, 83);
613                          call privileged_mode_ut$read_id_prom (prom_patch_version, 86);
614                          call privileged_mode_ut$read_id_prom (prom_iteration_number, 89);
615                          call privileged_mode_ut$read_id_prom (prom_build_number, 92);
616                          call privileged_mode_ut$read_id_prom (prom_release_type, 100);
617                          call privileged_mode_ut$read_id_prom (prom_version_text, 101);
618                          call privileged_mode_ut$read_id_prom (prom_build_arch, 130);
619                          call privileged_mode_ut$read_id_prom (prom_build_os, 150);
620                          call privileged_mode_ut$read_id_prom (prom_target_arch, 170);
621                          call privileged_mode_ut$read_id_prom (prom_target_os, 190);
622 
623                          prom_build_number2 = rtrim(prom_build_number, "ÿ");
624                          if prom_build_number2 = "" | substr(prom_build_number,1,1) = " " then
625                               prom_build_number2 = "<None>";
626 
627                          call syserr (ANNOUNCE, "CPU ^a: Model #: ^a; Serial #: ^a; Ship date: ^a; PROM Layout Version: ^a; ^/^-Simulator Release: ^a^a (^a); Build Number: ^a;  ^/^-Build Arch: ^a; Build OS: ^a; ^/^-Target Arch: ^a; Target OS: ^a.",
628                              substr (LETTERS, tag + 1, 1), cpu_model, cpu_serial, cpu_ship_date, prom_layout_version,
629                              prom_release_type, rtrim(prom_version_text,"ÿ"), prom_commit_date,
630                              prom_build_number2, prom_build_arch, prom_build_os, prom_target_arch, prom_target_os);
631                     end;
632               end;
633          end;
634 
635 /* second, delete all old prds's, to guard against changes in prds format from one bootload to the next. */
636 
637           do i = 1 to 8;
638                prds_name = "cpu_" || substr (LETTERS, i, 1) || ".prds";
639                call delentry$dfile (PRDS_DIR, prds_name, code);
640                if code ^= 0
641                then if code = error_table_$noentry then code = 0;
642                if code = 0 then do;
643                     if i - 1 = prds$processor_tag then do;  /* This processor. */
644                          call chname$cfile (PRDS_DIR, "prds", "prds", prds_name, code);
645                          if code ^= 0
646                          then call syserr$error_code (ANNOUNCE, code, "tc_init: could not rename prds to ^a.", prds_name);
647                          end;
648                     end;
649                else call syserr$error_code (ANNOUNCE, code, "tc_init: could not delete old ^a.", prds_name);
650           end;
651 
652           cpu_cardp = null ();
653           sys_info$hfp_exponent_available = "1"b;           /* let's pretend there are no L68s */
654 other_loop:
655           call config_$find (CPU_CARD_WORD, cpu_cardp);
656           if cpu_cardp = null () then return;               /* Return after all cards examined. */
657 
658           i = cpu_card.tag - 1;
659 
660 /* Create and entry-hold the PRDS for all but the bootload CPU. This has already been done for
661    the bootload PRDS, which is deciduous. Save the astep result in the idle APTE. */
662 
663           if i ^= tag then do;                              /* Don't do bootload. */
664                prds_name = "cpu_" || substr (LETTERS, i + 1, 1) || ".prds";
665                call append$branchx (PRDS_DIR, prds_name, RW_mode, seg_rb, pds$process_group_id, 0, 0, 0, code);
666                if code = 0
667                then call initiate (PRDS_DIR, prds_name, "", 0, 0, prdsp, code);
668                else prdsp = null ();
669                if code = 0
670                then scs$idle_aptep (i) -> apte.prds = rel (grab_aste$prewithdraw (prdsp, tc_data$prds_length, code));
671                if code ^= 0 then do;
672                     call syserr$error_code (ANNOUNCE, code, "tc_init: cannot create ^a. This CPU may not be added.",
673                          prds_name);
674                     cpu_card.state = "off";                 /* avoid trying to start it. */
675                     scs$idle_aptep (i) = null ();           /* Cause easy crawlout later */
676                     end;
677                if prdsp ^= null () then call terminate_$teseg (prdsp, (0), code);
678                end;
679           if cpu_card.state = "on"
680           then                                              /* If CPU is to be added ... */
681                if i ^= tag then do;                         /* If not the bootload processor ... */
682                     call start_cpu (i, code);
683                     if code ^= 0
684                     then call syserr (ANNOUNCE, "tc_init: Could not start CPU ^a.", substr ("ABCDEFGH", cpu_card.tag, 1));
685                     end;
686           if cpu_card.type ^= "dps8"
687           then                                              /* oh well */
688                sys_info$hfp_exponent_available = "0"b;      /* no mixed configurations for hex fp */
689           go to other_loop;                                 /* Loop. */
690 
691 /* format: off */
692 %page; %include stack_0_data;
693 %page; %include sys_trace;
694 %page; %include apte;
695 %page; %include sdw_info;
696 %page; %include tcm;
697 %page; %include hc_lock;
698 %page; %include scs;
699 %page; %include slt;
700 %page; %include slte;
701 %page; %include config_cpu_card;
702 %page; %include config_schd_card;
703 %page; %include config_tcd_card;
704 %page; %include syserr_constants;
705 %page; %include system_types;
706 %page; %include rsw;
707 %page;
708 
709 /* BEGIN MESSAGE DOCUMENTATION
710 
711    Message:
712    tc_init: No valid processor tags on CPU cards.
713 
714    S: $crash
715 
716    T: $init
717 
718    M: No CPU CONFIG cards contained valid (A - H) CPU tags. Normally this message will
719    not appear if the bootload CPU is mis-specified, as this error will be detected by
720    scas_init, and thus this may be indicative of a supervisor logic problem.
721 
722    A: Check that all CPU CONFIG cards are correct. If not, perform an emergency
723    shutdown, correct them, and reboot. If so, be sure to get a dump and contact
724    system programming personnel.
725 
726    Message:
727    tc_init: Cannot start up first idle process. Check switches.
728 
729    S: $crash
730 
731    T: $init
732 
733    M: The idle process for the bootload CPU could not be started. This may be
734    an error in setting of configuration switches, or may be indicative of a logic problem in the
735    supervisor.
736 
737    A: Perform an emergency shutdown. Check all main module configuration switches.
738    If a problem was corrected, reboot. Otherwise, be sure to get a dump and contact
739    the systems programming staff.
740 
741    Message:
742    tc_init: Could not rename prds to PRDSNAME. ERRORMESSAGE
743 
744    S: $info
745 
746    T: $init
747 
748    M: The segment "prds" in >system_library_1 could not be renamed to PRDSNAME, which
749    is the correct name for the PRDS for the bootload processor.
750    ERRORMESSAGE is a standard error_table_ message.
751 
752    A: Notify the system programming staff. Action should be taken by the programming staff to rename this
753    segment. If the problem cannot be sorted out, avoid reconfiguring the bootload
754    CPU during this bootload.
755 
756    Message:
757    tc_init: Could not delete old PRDSNAME. ERRORMESSAGE
758 
759    S: $info
760 
761    T: $init
762 
763    M: The old PRDS PRDSNAME from the previous bootload, in >system_library_1, could not
764    be deleted. When the CPU whose tag is part of PRDSNAME is added, the old PRDS will be used.
765    ERRORMESSAGE is a standard error_table_ message.
766 
767    A: $notify
768 
769    Message:
770    tc_init: Could not start CPU CPUTAG.
771 
772    S: $info
773 
774    T: $init
775 
776    M: The CPU whose tag is CPUTAG could not be automatically started by system bootload.
777 
778    A: Check all configuration switches on CPU and main memory modules, especially
779    the CPU STEP switch on the CPU which could not be added, and its port
780    enable switches. If all switches were correct, add the CPU via the addcpu command.
781 
782    Message:
783    tc_init: cannot create cpu_X.prds. This CPU may not be added. ERROR_MESSAGE
784 
785    S: $info
786 
787    T: $init
788 
789    M: A difficulty was encountered in creating the PRDS for a configurable CPU.
790    Later attempts to add this CPU will fail.  It will be marked as "off" in the CONFIG deck.
791 
792    A: $inform
793    When the problem has been remedied, shut down and reboot, and then add this CPU.
794 
795    Message:
796    tc_init: Inconsistent SCHD config card values.
797 
798    S: $crash
799 
800    T: $init
801 
802    M: The SCHD config card is not in the correct format, or some values
803    are out of acceptable range. In particular, the value of min_eligible
804    cannot exceed that of max_eligible; also, the value of max_eligible plus
805    the max number of stopped stack_0's (default = 4) cannot exceed
806    max_max_eligible.
807 
808    A: Check the SCHD config card (refer to the MOH) and correct. Re-boot the
809    system.
810 
811    Message:
812    tc_init: Size of PRDS on TBLS card too small; XXX KW will be used.
813 
814    S: $info
815 
816    T: $init
817 
818    M: The size of the PRDS specified on the TBLS card in the Configuration Deck
819    is smaller than the size of the PRDS defined in the MST header.  The size of
820    the PRDS will be that defined in the MST header.  Further, the TBLS card in
821    the Configuration Deck has been changed to reflect the minimum size of the
822    PRDS
823 
824    Message:
825    CPU CPUTAG: Model #: MODEL; Serial #: SERIAL; Ship date: YYMMDD.
826 
827    S: $info
828 
829    T: When the bootload CPU is a DPS8, whose tag is CPUTAG is "added" to
830    the system.
831 
832    M: The MODEL, SERIAL and YY/MM/DD information is read from the DPS8 cpu's ID PROM.
833    It is intended to be used as historical information
834    for identifing CPUs, regardless of what their current tag is assigned as.
835 
836    A: $ignore
837 
838    Message:
839    CPU CPUTAG: Model #: MODEL; Serial #: SERIAL; Ship date: YYMMDD; PROM Layout Version: LAYOUT;
840       Simulator Release: VERSION; Build Number: BUILD;
841       Build Arch: BARCH; Build OS: BOS;
842       Target Arch: TARCH; Target OS: TOS.
843 
844    S: $info
845 
846    T: When the bootload CPU is a DPS8, whose tag is CPUTAG is "added" to
847    the system.
848 
849    M: The MODEL, SERIAL, YYMMDD, LAYOUT, VERSION, BUILD, BARCH, BOS, TARCH, and TOS information
850    is read from the DPS8 cpu's ID PROM. It is intended to be used as historical information
851    for identifing CPUs, regardless of what their current tag is assigned as.  The LAYOUT, VERSION,
852    BUILD, BARCH, BOS, TARCH, and TOS fields are only found in DPS8 PROMs of the DPS8M simulator.
853 
854    A: $ignore
855 
856    Message:
857    Warning: You are running an old version of the DPS8M simulator.
858       Please update to VERSION or later. See https://dps8m.gitlab.io/ for details.
859 
860    S: $beep
861 
862    T: When the bootload CPU is a DPS8 is "added" to the system.
863 
864    M: VERSION specifies the version of a DPS8M simulator that is known to work correctly with
865    the running version of Multics.
866 
867    A: $ignore
868 
869 
870    END MESSAGE DOCUMENTATION */
871 
872 
873      end tc_init;