1 /****^  ***********************************************************
  2         *                                                         *
  3         * Copyright, (C) Honeywell Bull Inc., 1987                *
  4         *                                                         *
  5         * Copyright, (C) Honeywell Information Systems Inc., 1982 *
  6         *                                                         *
  7         *********************************************************** */
  8 
  9 
 10 /****^  HISTORY COMMENTS:
 11   1) change(1986-10-23,Fawcett), approve(1986-10-23,MCR7517),
 12      audit(1986-10-30,Beattie), install(1986-11-03,MR12.0-1206):
 13      Changed to remove the word BOS from Error message documentation.
 14   2) change(2022-08-24,Swenson), approve(2022-08-24,MCR10120),
 15      audit(2022-08-24,GDixon), install(2022-09-06,MR12.8-1037):
 16      Fix interpretation of ID PROM fields in CPU start syserr messages.
 17                                                    END HISTORY COMMENTS */
 18 
 19 
 20 /* START_CPU - Start Up a Processor.
 21    Last Modified: (Date and Reason)
 22    10/04/83 by Keith Loepere for paged idle_dsegs.
 23    04/09/84 by Chris Jones to update config deck to its partition when changed.
 24    04/09/82 by J. Bongiovanni to check data switches on non-bootload CPU
 25    12/30/81 by J. A. Bush to interagate cpu switches when cpu types are different
 26    11/11/81 by J. A. Bush to not check ID PROM on the bootload CPU
 27    10/22/81 by J. Bongiovanni for set_procs_required
 28    03/05/81 by J. Bongiovanni to set segment bound and access for prds
 29    on non-bootload CPUs
 30    09/08/80 by J. A. Bush for the DPS8/70M CPU
 31    02/05/79 by B. Greenberg for port expanders.
 32    02/05/76 by Steve Webber & Noel Morris as part of reconfiguration rewrite
 33    08/12/71 by Richard H. Gumpertz to take out the call to move subroutine
 34    7/14/72 by Craig Jensen to convert for the follow-on 645.
 35 */
 36 
 37 /* format: style4,delnl,insnl,indattr,ifthen,dclind10 */
 38 start_cpu:
 39      proc (tag, rcode);
 40 
 41 dcl       tag                    fixed bin (3),
 42           rcode                  fixed bin (35);
 43 
 44 dcl       abs_ptr                ptr,                       /* pointer to abs_seg$ */
 45           prds_sdwp              ptr,                       /* pointer to SDW for new prds */
 46           prds_sdw               bit (72) aligned,          /* SDW for new prds */
 47           prds_astep             ptr,                       /* AST entry pointer for new prds */
 48           prds_no                fixed bin (18),            /* segment number of prds */
 49           pdp                    ptr,                       /* pointer to processor data for new CPU */
 50           old_pdp                ptr,                       /* pointer to processor data for CPU losing mask */
 51           old_tag                fixed bin (3),             /* tag of CPU losing mask */
 52           found_mask             bit (1) aligned,           /* "1"b when CPU with mask found */
 53           ptp                    ptr,                       /* temporary for wire_and_mask */
 54           mask_temp              fixed bin (71),            /* temporary for wire_and_mask */
 55           int_vec_save           bit (36) aligned,          /* for saving interrupt vector */
 56           trouble_save           bit (36) aligned,          /* for saving trouble fault vector */
 57           startup_save           bit (36) aligned,          /* for saving startup fault vector */
 58           onc_save               bit (36) aligned,          /* for saving onc fault vector */
 59           lockup_save            bit (36) aligned,          /* for saving lockup fault vector */
 60           i                      fixed bin,                 /* iteration variable */
 61           abs_seg_p              ptr,                       /* pointer to abs_seg */
 62           fv_iv_p                ptr,                       /* pointer to fault/interrupt vector template */
 63           switch_rel             fixed bin (18),            /* place in template for switch readings */
 64           switchp                ptr,                       /* pointer to switch readings */
 65           rsw1_68p               ptr,                       /* points to rsw1 data for L68, for switch checking */
 66           rsw1_8p                ptr,                       /* points to rsw1 data for DPS8M, for switch checking */
 67           rsw4p                  ptr,                       /* points to rsw4 data for switch checking */
 68           cmpp                   ptr,                       /* points to rsw1 discrepancy data for switch checking */
 69           trgp                   ptr,                       /* points to add target rsw1 data, for switch checking */
 70           (tbase, tsize)         fixed bin (24),            /* port base and size in words, for switch checking */
 71           L68_prt_sze            fixed bin (24),            /* used for computing true port size of L68 port */
 72           found                  bit (1) aligned,           /* useful flag */
 73           dps8_add               bit (1) aligned,           /* cpu type flag for switch checking */
 74           remember               (0:7) fixed bin,           /* base of controllers with vector template */
 75           base                   fixed bin,                 /* base address of controller */
 76           tcode                  fixed bin (35),            /* temporary for error code */
 77           cpu_mask               bit (8) aligned,           /* for set_procs_required */
 78           cpu_model              char (11) aligned,         /* storage for cpu model number (from ID PROM) */
 79           cpu_serial             char (11) aligned,         /* storage for cpu serial number (from ID PROM) */
 80           cpu_ship_date          char (6) aligned;          /* storage for cpu ship date (from ID PROM) */
 81 
 82 dcl       1 tsdw                 (0:7) aligned like sdw,    /* for saving abs_seg SDW's */
 83           1 tsdw1                aligned like sdw,          /* automatic copy of SDW */
 84           fv_iv_copy             (2048) fixed bin based (fv_iv_p),
 85                                                             /* for copying vector template */
 86           based_switches         (0:4) bit (36) aligned based (switchp);
 87                                                             /* for checking switch readings */
 88 
 89 
 90 dcl       LETTERS                char (8) static options (constant) init ("ABCDEFGH");
 91 
 92 dcl       abs_seg$               ext,
 93           sst_seg$               ext,
 94           idle_dsegs$            (0:8 * 1024 - 1 /* max size */) bit (72) aligned ext,
 95           prds$                  ext,
 96           dseg$                  ext,
 97           fault_vector$          ext,
 98           pds$processid          bit (36) aligned ext,
 99           prds$idle_ptr          ptr ext,
100           prds$processor_tag     fixed bin (3) ext,
101           prds$processor_pattern bit (8) aligned ext,
102           tc_data$prds_length    fixed bin (18) ext,
103           tc_data$ncpu           fixed bin ext,
104           fv_iv_template$fv_iv_template
105                                  ext,
106           fv_iv_template$rsw_data
107                                  (4) bit (36) aligned ext,
108           init_processor$wait_flag
109                                  fixed bin (35) ext,
110           init_processor$new_dbr fixed bin (71) ext,
111           init_processor$first_tra
112                                  bit (36) aligned ext,
113           init_processor$trouble_tra
114                                  bit (36) aligned ext,
115           init_processor$startup_tra
116                                  bit (36) aligned ext,
117           init_processor$onc_tra bit (36) aligned ext,
118           init_processor$lockup_tra
119                                  bit (36) aligned ext,
120           init_processor$controller_data
121                                  bit (8) aligned ext,
122           sys_info$system_type   fixed bin ext;
123 
124 dcl       init_processor$start_bootload_cpu
125                                  entry,
126           stop_cpu$destroy_1     entry (fixed bin (3), fixed bin (35)),
127           scr_util$reassign_mask entry (fixed bin (3), fixed bin (3)),
128           scr_util$set_mask      entry (fixed bin (3), fixed bin (3), bit (72) aligned),
129           scr_util$set_port_enable
130                                  entry (fixed bin (3), bit (1) unal),
131           scr_util$update_export_xipmsk
132                                  entry (fixed bin (3)),
133           scr_util$set_export_enable
134                                  entry (fixed bin (3), fixed bin (3), bit (1) aligned),
135           mask_instruction$smcm  entry returns (bit (36) aligned),
136           mask_instruction$rmcm  entry returns (bit (36) aligned),
137           config_$find_2         entry (char (4) aligned, fixed bin, ptr),
138           config_$update         entry (),
139           syserr                 entry options (variable),
140           syserr$error_code      entry options (variable),
141           privileged_mode_ut$swap_sdw
142                                  entry (ptr, ptr),
143           privileged_mode_ut$smic
144                                  entry (bit (36) aligned),
145           privileged_mode_ut$cioc
146                                  entry (ptr),
147           privileged_mode_ut$wire_and_mask
148                                  entry (fixed bin (71), ptr),
149           privileged_mode_ut$unwire_unmask
150                                  entry (fixed bin (71), ptr),
151           privileged_mode_ut$read_id_prom
152                                  entry (char (*) aligned, fixed bin),
153           validate_cpu_card      entry (fixed bin (3), ptr),
154           wire_proc$wire_me      entry,
155           get_ptrs_$given_astep  entry (ptr) returns (bit (72)),
156           wire_proc$unwire_me    entry,
157           set_procs_required     entry (bit (8) aligned, fixed bin (35)),
158           pc_wired$wire_wait     entry (ptr, fixed bin, fixed bin),
159           pc_abs$remove_core     entry (fixed bin, fixed bin, fixed bin (35)),
160           freecore               entry (fixed bin),
161           prds_init              entry (ptr, fixed bin (3), ptr),
162           pxss$thread_in_idle    entry (ptr);
163 
164 dcl       1 pdata                like scs$processor_data based (pdp) aligned;
165                                                             /* single element of processor data */
166 dcl       1 opdata               like scs$processor_data based (old_pdp) aligned;
167                                                             /* Old interrupt CPU's pdata */
168 
169 dcl       (addr, baseno, bin, bit, bool, divide, fixed, ptr, rel, stac, stacq, string, substr, unspec)
170                                  builtin;
171 %page;
172           abs_ptr = addr (abs_seg$);                        /* set pointer to abs_seg$ */
173           prds_sdwp = addr (prds_sdw);
174 
175           fgbxp = addr (flagbox$);                          /* Get pointer to flagbox. */
176 
177 
178 /* Fill in APT entry for idle process. */
179 
180           aptep = scs$idle_aptep (tag);                     /* get pointer to previously allocated APTE */
181           apte.processid = rel (aptep) || (6)"101"b;        /* set process ID */
182           apte.flags.loaded = "1"b;                         /* loaded and elegible */
183           apte.flags.eligible = "1"b;
184           apte.flags.idle = "1"b;                           /* it is idle proc */
185           apte.flags.default_procs_required = "0"b;         /* not system default */
186           apte.procs_required = "0"b;
187           substr (apte.procs_required, tag + 1, 1) = "1"b;  /* the CPU we want */
188           apte.flags.state = bit (bin (2, 18));             /* set state to ready */
189           apte.timax = 16000000;                            /* low priority */
190           call pxss$thread_in_idle (aptep);                 /* thread entry into ready list */
191 
192 
193 /* Initialize PRDS. */
194 
195           if tag = scs$bos_processor_tag then
196                prds$idle_ptr = aptep;
197           else do;                                          /* cpu is not bootload-cpu */
198                prds_astep = ptr (addr (sst_seg$), apte.prds);
199                prds_sdw = get_ptrs_$given_astep (prds_astep);
200                addr (prds_sdw) -> sdw.access = addr (dseg$) -> sdwa.access (fixed (baseno (addr (prds$)), 18));
201                addr (prds_sdw) -> sdw.bound = bit (divide (tc_data$prds_length - 1, 16, 14), 14);
202                call pc_wired$wire_wait (prds_astep, 0, divide (tc_data$prds_length + 1023, 1024, 17, 0));
203                                                             /* wire down prds */
204                prds_no = bin (baseno (addr (prds$)), 18);
205                do i = 0 to tag - 1;
206                     if scs$processor_data (i).offline | scs$processor_data (i).online then
207                          if sys_info$system_type = ADP_SYSTEM then
208                               prds_no = prds_no + 1024;
209                          else prds_no = prds_no + 512;      /* size of dsegs reserved for them */
210                end;
211                idle_dsegs$ (prds_no) = prds_sdw;
212                call privileged_mode_ut$swap_sdw (abs_ptr, prds_sdwp);
213                                                             /* abs_seg is the new prds. */
214                call prds_init (abs_ptr, tag, aptep);        /* Initialize prds. */
215           end;
216 %page;
217 /* Assign a system controller mask to the processor. */
218 
219           pdp = addr (scs$processor_data (tag));            /* Get pointer to processor data. */
220           found_mask = "0"b;                                /* Initialize flag. */
221           if ^pdata.interrupt_cpu then do;                  /* If processor does not have a mask ... */
222                do old_tag = 0 to 7 while (^found_mask);
223                     old_pdp = addr (scs$processor_data (old_tag));
224                                                             /* Get pointer to other processor data. */
225                     if opdata.interrupt_cpu &               /* If this one gets interrupts and not BCE CPU ... */
226                          (old_tag ^= scs$bos_processor_tag) then do;
227                          found_mask = "1"b;                 /* Got a candidate. */
228 
229                          if opdata.online then do;          /* If candidate is running now ... */
230                               cpu_mask = "0"b;
231                               substr (cpu_mask, old_tag + 1, 1) = "1"b;
232                               call set_procs_required (cpu_mask, tcode);
233                                                             /* Run on that CPU */
234                               if tcode ^= 0 then do;        /* Shouldn't happen */
235                                    rcode = rcerr_sprq_failed;
236                                    return;                  /* Give up */
237                               end;
238                               call wire_proc$wire_me;       /* Don't allow page faults. */
239                               call privileged_mode_ut$wire_and_mask (mask_temp, ptp);
240                          end;                               /* Don't allow interrupts. */
241                          opdata.interrupt_cpu = "0"b;       /* Take interrupts away from candidate. */
242                          scs$mask_ptr (old_tag) = scs$mask_ptr (tag);
243                                                             /* Set mask pointer to simulated cell. */
244                          scs$set_mask (old_tag) = scs$set_mask (tag);
245                                                             /* Make SMCM into STAQ. */
246                          scs$read_mask (old_tag) = scs$read_mask (tag);
247                                                             /* Make RMCM into LDAQ. */
248                          if opdata.online then do;          /* If we wired and masked before ... */
249                               call privileged_mode_ut$unwire_unmask (mask_temp, ptp);
250                               call wire_proc$unwire_me;
251                               call set_procs_required ("0"b, (0));
252                          end;
253                          if opdata.expanded_port & opdata.online then
254                               call scr_util$update_export_xipmsk ((opdata.controller_port));
255                          call scr_util$reassign_mask (old_tag, tag);
256                                                             /* Reassign the mask now. */
257                     end;
258                end;
259 
260                if ^found_mask then                          /* If no mask was found for new processor ... */
261                     call scr_util$reassign_mask (-1, tag);  /* There must be a spare mask. */
262 
263                scs$mask_ptr (tag) = addr (scs$port_addressing_word (scs$interrupt_controller));
264                                                             /* Set pointer for masking. */
265                scs$set_mask (tag) = mask_instruction$smcm ();
266                                                             /* Set SMCM instruction. */
267                scs$read_mask (tag) = mask_instruction$rmcm ();
268                                                             /* Set RMCM instruction. */
269                pdata.interrupt_cpu = "1"b;                  /* We can now take interrupt on this CPU. */
270           end;
271 
272 /* Set up expected switch readings for processor. */
273 
274           rswp = addr (scs$processor_switch_template (2));  /* Get pointer to expected data. */
275           dps_rsw_2.cpu_num = tag;                          /* Set correct processor ID. */
276 %page;
277 /* Try to get the processor running. */
278 
279           init_processor$new_dbr = apte.dbr;                /* Set DBR value for new idle process. */
280 
281           if tag ^= scs$bos_processor_tag then do;          /* If not the bootload CPU ... */
282 
283 /* Lay down dummy fault and interrupt vectors in any SCU's we can */
284 
285                remember = 0;                                /* array is cleared */
286                string (tsdw1) = "0"b;
287                tsdw1.df = "1"b;
288                tsdw1.read = "1"b;
289                tsdw1.write = "1"b;
290                tsdw1.bound = bit (bin (127, 14), 14);
291                tsdw1.unpaged = "1"b;
292                abs_seg_p = addr (abs_seg$);
293                fv_iv_p = addr (fv_iv_template$fv_iv_template);
294 
295                do i = 0 to 7;
296                     base = scs$controller_data (i).base;
297                     if (base ^= 0) & scs$controller_data (i).online then do;
298                          call pc_abs$remove_core (base, 2, tcode);
299                          if tcode = 0 then do;              /* we got the pages */
300                               tsdw (i) = tsdw1;
301                               tsdw (i).add = bit (bin (base * 1024, 24), 24);
302                               call privileged_mode_ut$swap_sdw (abs_seg_p, addr (tsdw (i)));
303                               abs_seg_p -> fv_iv_copy = fv_iv_p -> fv_iv_copy;
304                               remember (i) = base;
305                          end;
306                     end;
307                end;
308 
309 /* Mask interrupts for new processor and enable all controller ports to new processor. */
310 
311                call scr_util$set_mask (scs$interrupt_controller, (pdata.controller_port), scs$sys_level);
312                                                             /* Allow no interrupts. */
313                call scr_util$set_port_enable ((pdata.controller_port), "1"b);
314                                                             /* Set port enaobled on all controllers. */
315                if pdata.expanded_port then do;              /* Update port expander bits */
316                     call scr_util$set_export_enable ((pdata.controller_port), (pdata.expander_port), "1"b);
317                     call scr_util$update_export_xipmsk ((pdata.controller_port));
318                                                             /* Make mask from pdata.interrupt_cpu's */
319                end;
320 %page;
321 /* Initialize variables in init_processor. */
322 
323                init_processor$wait_flag = rcerr_addcpu_no_response;
324                                                             /* Set flag to await processor startup. */
325                init_processor$controller_data = "0"b;       /* Clear controller bits. */
326                do i = 0 to 7;                               /* Set bit for each online controller. */
327                     substr (init_processor$controller_data, i + 1, 1) = scs$controller_data (i).online;
328                end;
329 
330 /* Send connects to make all other processors suspend normal operation. */
331 
332                call privileged_mode_ut$wire_and_mask (mask_temp, ptp);
333                call wire_proc$wire_me;                      /* Take no interrupts or page faults here. */
334 
335                do while (^stac (addr (scs$connect_lock), pds$processid));
336                end;                                         /* Lock up the connect lock. */
337 
338                scs$processor_start_wait = scs$processor & ^prds$processor_pattern;
339                                                             /* Stop all other processors. */
340                do i = 0 to 7;                               /* Loop through all processors. */
341                     old_pdp = addr (scs$processor_data (i));/* Get pointer to data for processor. */
342                     if (i ^= prds$processor_tag) & old_pdp -> pdata.online then
343                          call privileged_mode_ut$cioc (addr (scs$cow (i).cow));
344                                                             /* Send connects to other processors. */
345                end;
346 
347                do while (scs$processor_start_wait);         /* Wait for other processors to respond. */
348                end;
349 
350 /* Set up fault and interrupt vectors for starting CPU. */
351 
352                fvp = addr (fault_vector$);                  /* Get pointer to fault vector. */
353                int_vec_save = fv.ipair (scs$processor_start_int_no).scu;
354                fv.ipair (scs$processor_start_int_no).scu = init_processor$first_tra;
355                                                             /* Set up TRA for CPU start interrupt. */
356                trouble_save = fv.fpair (FAULT_NO_TRB).scu;
357                fv.fpair (FAULT_NO_TRB).scu = init_processor$trouble_tra;
358                                                             /* Set up TRA for trouble fault. */
359                startup_save = fv.fpair (FAULT_NO_SUF).scu;
360                fv.fpair (FAULT_NO_SUF).scu = init_processor$startup_tra;
361                                                             /* Set up TRA for startup fault. */
362                onc_save = fv.fpair (FAULT_NO_ONC).scu;
363                fv.fpair (FAULT_NO_ONC).scu = init_processor$onc_tra;
364                                                             /* Set up TRA for onc fault. */
365                lockup_save = fv.fpair (FAULT_NO_LUF).scu;
366                fv.fpair (FAULT_NO_LUF).scu = init_processor$lockup_tra;
367                                                             /* Set up TRA for lockup fault. */
368 %page;
369 /* Send processor start interrupt, open processor's mask, and wait for it to respond. */
370 
371                call privileged_mode_ut$smic (scs$processor_start_pattern);
372                                                             /* Send interrupt to start processor. */
373                call scr_util$set_mask (scs$interrupt_controller, (pdata.controller_port), scs$processor_start_mask);
374                                                             /* Let new CPU get the interrupt. */
375 to_loop:
376                do i = 1 to 5000 while (init_processor$wait_flag = rcerr_addcpu_no_response);
377                end;                                         /* Wait for flag to change. */
378                rcode = init_processor$wait_flag;            /* Get error code, if any. */
379 
380 /* If init_processor returns a bad switch code, this could be because we are attempting to add a processor that
381    is of a different type (i.e.  L68 vs DPS8M or vis-a-versa) than what the scs$processor_switch_template was set up
382    from (usally the bootload processor).  When this happens, the values of the rsw (1) memory size and the assignment
383    switches must be computed for equality, since there values on the L68 and DPS8M processors are potentially
384    different.  This is also true of the interlace info bits (rsw (2) bits 0 - 3 for the DPS8M, rsw (4) for the L68). */
385 
386                if rcode = rcerr_addcpu_bad_switches then do;
387                     scs$processor_switch_compare = scs$processor_switch_compare & scs$processor_switch_mask;
388                     cmpp = addr (scs$processor_switch_compare (2));
389                                                             /* look at rsw 2 descrepencies */
390                     if cmpp -> dps8_rsw_2.cpu_type ^= 0 &   /* if adding a different kind of cpu */
391                          scs$processor_switch_compare (3) = "0"b then do;
392                                                             /* no rsw3 data on mixed system */
393                          if dps_rsw_2.cpu_type = 0 then do; /* template cpu is L68, cpu we are adding is dps8 */
394                               dps8_add = "1"b;              /* set switch indicating adding dps8 */
395                               rsw4p = addr (scs$processor_switch_template (4));
396                                                             /* set rsw 4 ptr */
397                               rsw1_68p = addr (scs$processor_switch_template (1));
398                                                             /* set L68 rsw1 ptr */
399                               rsw1_8p = addr (scs$processor_switch_data (1));
400                                                             /* set dps8 rsw1 ptr */
401                               switchp = addr (scs$processor_switch_data (2));
402                                                             /* set dps8 rsw2 ptr */
403                          end;
404                          else do;                           /* template cpu is dps8, cpu we are adding is L68 */
405                               dps8_add = "0"b;              /* set switch indicating not adding dps8 */
406                               rsw4p = addr (scs$processor_switch_data (4));
407                                                             /* set rsw 4 ptr */
408                               rsw1_68p = addr (scs$processor_switch_data (1));
409                                                             /* set L68 rsw1 ptr */
410                               rsw1_8p = addr (scs$processor_switch_template (1));
411                                                             /* set dps8 rsw1 ptr */
412                               switchp = addr (scs$processor_switch_template (2));
413                                                             /* set dps8 rsw2 ptr */
414                               rswp = addr (scs$processor_switch_data (2));
415                                                             /* set L68 rsw2 ptr */
416                          end;
417                          cmpp = addr (scs$processor_switch_compare (1));
418                                                             /* set compare ptr */
419                          trgp = addr (scs$processor_switch_data (1));
420                                                             /* set add target RSW1 ptr */
421                          found = "0"b;
422                          do i = 0 to 3;                     /* go through each port */
423                               if scs$controller_data (i).online |
424                                                             /* check port only if mem */
425                                    scs$controller_data (i).offline then do;
426                                                             /* card in config deck */
427                                    L68_prt_sze = dps_mem_size_table (rsw1_68p -> rsw_1_3.port_info (i).mem_size);
428                                    if rsw4p -> rsw_4.port_info (i).half then
429                                                             /* if half switch is on... */
430                                         L68_prt_sze = divide (L68_prt_sze, 2, 24, 0);
431                                                             /* divide patch plug size by 2 */
432                                    if L68_prt_sze ^= dps8_mem_size_table (rsw1_8p -> rsw_1_3.port_info (i).mem_size) then
433                                         found = "1"b;       /* memory sizes are not = */
434                                    else cmpp -> rsw_1_3.port_info (i).mem_size = 0;
435                                                             /* reset compare data in case other switch error */
436                                    tbase = scs$controller_data (i).base * 1024;
437                                                             /* get abs base */
438                                    if dps8_add then         /* get target memory size */
439                                         tsize = dps8_mem_size_table (trgp -> rsw_1_3.port_info (i).mem_size);
440                                    else tsize = dps_mem_size_table (trgp -> rsw_1_3.port_info (i).mem_size);
441 
442                                    if trgp -> rsw_1_3.port_info (i).port_assignment
443                                         ^= bit (divide (tbase, tsize, 3, 0), 3) then
444                                         found = "1"b;       /* port assignment switch error */
445                                    else cmpp -> rsw_1_3.port_info (i).port_assignment = "0"b;
446                                                             /* reset compare data in case other switch error */
447                               end;
448                               else do;                      /* memory not there, reset compare data */
449                                    cmpp -> rsw_1_3.port_info (i).mem_size = 0;
450                                    cmpp -> rsw_1_3.port_info (i).port_assignment = "0"b;
451                               end;
452                               if cmpp -> rsw_1_3.port_info (i).port_enable then
453                                    found = "1"b;            /* port_enable  not set correctly */
454                               if cmpp -> rsw_1_3.port_info (i).initialize_enable then
455                                    found = "1"b;            /* initialize enable not set correctly */
456                               if cmpp -> rsw_1_3.port_info (i).interlace_enable then
457                                    found = "1"b;            /* interlace enable not set correctly */
458                               if rsw1_68p -> rsw_1_3.port_info (i).interlace_enable then
459                                    if rsw4p -> rsw_4.port_info (i).four ^= switchp -> dps8_rsw_2.interlace_info (i) then
460                                         found = "1"b;       /* interlace types not equal */
461                          end;
462                          if ^found then do;                 /* no error, return to init_processor */
463                               init_processor$wait_flag = rcerr_addcpu_no_response;
464                                                             /* allow init_processor to continue */
465                               go to to_loop;                /* and wait for completion */
466                          end;
467                     end;
468                     init_processor$wait_flag = -1;          /* allow init_processor to die in a DIS */
469                end;
470 
471 
472 /* Restore original fault and interrupt vector contents. */
473 
474                fv.ipair (scs$processor_start_int_no).scu = int_vec_save;
475                fv.fpair (FAULT_NO_TRB).scu = trouble_save;  /* Restore fault and interrupt vectors. */
476                fv.fpair (FAULT_NO_SUF).scu = startup_save;
477                fv.fpair (FAULT_NO_ONC).scu = onc_save;
478                fv.fpair (FAULT_NO_LUF).scu = lockup_save;
479 
480                if ^stacq (scs$connect_lock, (36)"0"b, scs$connect_lock) then
481                     ;                                       /* just reset lock, null then cluse */
482 
483                call wire_proc$unwire_me;                    /* Can unwire now. */
484                call privileged_mode_ut$unwire_unmask (mask_temp, ptp);
485 
486 /* Perform error checking. */
487 
488                if rcode = rcerr_addcpu_no_response then do; /* If CPU did not respond ... */
489                     switch_rel = bin (rel (addr (fv_iv_template$rsw_data)), 18) - bin (rel (fv_iv_p), 18);
490                     switchp = ptr (abs_seg_p, switch_rel);  /* See if CPU responded in another controller. */
491                     found = "0"b;                           /* Clear switch. */
492                     do i = 0 to 7 while (^found);           /* Search the base of all controllers. */
493                          if remember (i) ^= 0 then do;
494                               call privileged_mode_ut$swap_sdw (abs_seg_p, addr (tsdw (i)));
495                               if unspec (based_switches) then do;
496                                    scs$processor_switch_compare =
497                                         bool (scs$processor_switch_template, based_switches, "0110"b);
498                                    scs$processor_switch_compare =
499                                         scs$processor_switch_compare & scs$processor_switch_mask;
500                                    rcode = rcerr_addcpu_bad_switches;
501                                                             /* Change the error code. */
502                                    init_processor$wait_flag = -1;
503                                                             /* allow init_processor to die in a DIS */
504                                    found = "1"b;
505                               end;
506                          end;
507                     end;
508                end;
509 %page;
510 /* Now give back the double pages we borrowed */
511 
512                do i = 0 to 7;
513                     base = remember (i);
514                     if base > 0 then do;
515                          call freecore (base);
516                          call freecore (base + 1);
517                     end;
518                end;
519 
520                string (tsdw1) = "0"b;
521                call privileged_mode_ut$swap_sdw (abs_seg_p, addr (tsdw1));
522                if rcode ^= 0 then do;                       /* If an error occurred ... */
523                     call stop_cpu$destroy_1 (tag, tcode);   /* Clean up the mess we made. */
524                     return;
525                end;
526           end;                                              /* Mask the discrepancy data. */
527 
528 /* If initializing the bootload CPU, make simple call out. */
529 
530           else do;                                          /* If bootload CPU ... */
531                call init_processor$start_bootload_cpu;      /* Start up idle process. */
532                fgbx.hc_dbr = unspec (apte.dbr);             /* Place idle process DBR in flagbox. */
533           end;
534 
535 /* Update the config card for this processor. */
536 
537           call config_$find_2 (CPU_CARD_WORD, tag + 1, cpu_cardp);
538                                                             /* Find correct CPU card. */
539           cpu_card.state = "on  ";                          /* Set correct processor state. */
540           call config_$update ();
541           scs$nprocessors = scs$nprocessors + 1;            /* Count number of CPU's. */
542           tc_data$ncpu = tc_data$ncpu + 1;
543           rswp = addr (scs$processor_switch_data (2));      /*  lets look at cpu type */
544           pdata.cpu_type = dps_rsw_2.cpu_type;              /* copy cpu type to processor data */
545           call validate_cpu_card (tag, rswp);               /* validate cpu type and model */
546 
547           if tag ^= scs$bos_processor_tag then do;          /* If not during system initialization ... */
548                call syserr (ANNOUNCE, "start_cpu: Added CPU ^a.", substr (LETTERS, tag + 1, 1));
549                if pdata.cpu_type > 0 then                   /* if DPS8 cpu... */
550                     if addr (scs$processor_switch_data (2)) -> dps8_rsw_2.id_prom then do;
551                                                             /* and id prom present */
552                          cpu_mask = "0"b;
553                          substr (cpu_mask, tag + 1, 1) = "1"b;
554                          call set_procs_required (cpu_mask, tcode);
555                                                             /* Run on that CPU. */
556                          if tcode ^= 0 then
557                               call syserr$error_code (CRASH, tcode, "start_cpu: Unable to run on CPU ^a",
558                                    substr (LETTERS, tag + 1, 1));
559                          call privileged_mode_ut$read_id_prom (cpu_model, 0);
560                                                             /* get cpu model from ID PROM */
561                          call privileged_mode_ut$read_id_prom (cpu_serial, 11);
562                                                             /* get cpu serial # from ID PROM, at offset 13o */
563                          call privileged_mode_ut$read_id_prom (cpu_ship_date, 22);
564                                                             /* get ship date from ID PROM, at offset 26o */
565                          call set_procs_required ("0"b, (0));
566                          call syserr (LOG, "start_cpu: CPU ^a: Model #: ^a; Serial #: ^a; Ship date: ^a.",
567                               substr (LETTERS, tag + 1, 1), cpu_model, cpu_serial, cpu_ship_date);
568                                                             /* log info from ID PROM */
569                     end;
570                if scs$processor_switch_data (0) ^= scs$processor_data_switch_value then
571                     call syserr (ANNOUNCE, "start_cpu: CPU ^a data switches are ^w, should be ^w",
572                          substr (LETTERS, tag + 1, 1), scs$processor_switch_data (0), scs$processor_data_switch_value);
573           end;
574           rcode = 0;
575           return;
576 %page;
577 %include rcerr;
578 %page;
579 %include config_cpu_card;
580 %page;
581 %include flagbox;
582 %page;
583 %include scs;
584 %page;
585 %include rsw;
586 %page;
587 %include apte;
588 %page;
589 %include sdw;
590 %page;
591 %include fault_vector;
592 %page;
593 %include syserr_constants;
594 %page;
595 %include system_types;
596 %page;
597 /* BEGIN MESSAGE DOCUMENTATION
598 
599    Message:
600    start_cpu: Added CPU CPUTAG
601 
602    S: $info
603 
604    T: In response to an operator "rcf add cpu CPUTAG" command, or at bootload
605    time.
606 
607    M: The system has successfully added the CPU whose tag is CPUTAG to the
608    configuration.
609 
610    A: $ignore
611 
612    Message:
613    start_cpu: CPU CPUTAG: Model #: MODEL; Serial #: SERIAL; Ship date: YY/MM/DD.
614 
615    S: $log
616 
617    T: When a DPS8 CPU, whose tag is CPUTAG is added to the system.
618 
619    M: The MODEL, SERIAL and YY/MM/DD information is read from the DPS8 cpu's ID PROM.
620    It is intended to be used as historical information
621    for identifing CPUs, regardless of what their current tag is assigned as.
622 
623    A: $ignore
624 
625    Message:
626    start_cpu: CPU CPUTAG data switches are XXXXXXXXXXXX, should be YYYYYYYYYYYY
627 
628    S: $info
629 
630    T: In response to an "rcf add cpu CPUTAG" command
631 
632    M: The data switches on the CPU indicated are not set properly. The proper
633    value is given.
634 
635    A: The incorrect value will prevent returning to BCE on that CPU by means
636    of EXECUTE SWITCHES. Certain incorrect values will activate software
637    debugging traps. The switches should be corrected. This can be done
638    while the CPU is running.
639 
640    Message:
641    start_cpu: Unable to run on CPU x ERRORMESSAGE
642 
643    S: $crash
644 
645    T: In response to an "rcf add cpu CPUTAG" command or at bootload
646 
647    M: After adding a CPU, the system was unable to run on that CPU.
648    This indicates hardware or software failure.
649 
650    A: $recover
651 
652    END MESSAGE DOCUMENTATION */
653      end start_cpu;