1
2
3
4
5
6
7
8
9 init_toehold: procedure;
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 dcl Config_deck_size fixed bin init (4) static options (constant);
41 dcl Max_pages_in_segment fixed bin init (256) static options (constant);
42 dcl Pages_per_dcw fixed bin init (4) static options (constant);
43 dcl Toehold_size fixed bin init (2) static options (constant);
44 dcl Hardware_low_mem_page_size fixed bin init (2) static options (constant);
45 dcl absadr entry (pointer, fixed (35)) returns (fixed bin (26));
46 dcl pc$flush entry;
47 dcl pmut$camp entry;
48 dcl ptw_util_$make_core entry (ptr, fixed bin (26));
49 dcl save_handler_mc entry (ptr);
50 dcl sdw_util_$get_address entry (ptr, fixed bin (26));
51 dcl syserr entry options (variable);
52 dcl syserr$error_code entry options (variable);
53 dcl write_disk$write_disk_no_test entry (fixed bin, fixed bin (18), ptr, fixed bin (35));
54
55 dcl abs_seg0$ (0:255) bit (36 * 1024) aligned external;
56 dcl config_deck$ external;
57 dcl dseg$ (0:2047) fixed bin (71) external aligned;
58 dcl emergency_shutdown$ external;
59 dcl fault_vector$ external;
60 dcl int_unpaged_page_tables$ external;
61 dcl pvt$root_pvtx fixed bin external static;
62 dcl safe_config_deck$ external;
63 dcl sys_boot_info$bce_part_frec fixed bin external static;
64 dcl sys_boot_info$config_part_frec fixed bin external static;
65 dcl sys_boot_info$safe_config_deck_frec fixed bin external static;
66 dcl toehold_data$ external static bit (36) aligned;
67
68 dcl abs_seg_pt_abs_addr fixed bin (26);
69 dcl code fixed bin (35);
70 dcl disk_channel_number fixed bin (7);
71 dcl disk_iom_number fixed bin (3);
72 dcl disk_iom_port_number fixed bin (3);
73 dcl disk_device_number fixed bin (6);
74 dcl fault_vector_abs_addr fixed bin (26);
75 dcl iom_mailbox_abs_addr fixed bin (26);
76 dcl old_memory_state fixed bin;
77 dcl records_to_do fixed bin (18);
78 dcl rpv_devt fixed bin;
79 dcl running_address fixed bin;
80 dcl running_seeks fixed bin;
81 dcl running_record fixed bin (18);
82 dcl sx fixed bin;
83 dcl toehold_abs_addr fixed bin (18);
84 dcl toehold_page_addr fixed bin;
85
86 dcl abs_seg_pt (0:255) bit (36) aligned based (abs_seg_pt_ptr);
87 dcl abs_seg_pt_ptr ptr;
88
89 dcl 1 (seek_idcw_template, data_idcw_template)
90 aligned like idcw;
91
92 dcl (addr, addrel, currentsize, dimension, divide, hbound, lbound, max, min, mod, ptr, segno, unspec) builtin;
93 %page;
94 if sys_boot_info$bce_part_frec = -1
95 then call syserr (CRASH, "init_toehold: No ""bce"" partition on rpv. Rebuild the RPV to add one.");
96
97 toehold_abs_addr = absadr (addr (toehold$), (0));
98 toehold_page_addr = divide (toehold_abs_addr, 1024, 17);
99 toehold_ptr = addr (toehold$);
100 fault_vector_abs_addr = absadr (addr (fault_vector$), (0));
101 iom_mailbox_abs_addr = absadr (addr (iom_mailbox$), (0));
102
103 sys_boot_info$safe_config_deck_frec = divide (absadr (addr (safe_config_deck$), (0)), 1024, 16)
104 + sys_boot_info$bce_part_frec + CRASH_HANDLER_RECORDX;
105
106
107 toehold.memory_state = 0;
108
109 call find_rpv;
110
111 toehold.esd_segnum = segno (addr (emergency_shutdown$));
112
113 unspec (seek_idcw_template) = IDCW_INIT_STRING;
114 seek_idcw_template.command = seek_command (rpv_devt);
115 seek_idcw_template.device = disk_device_number;
116 seek_idcw_template.ext_ctl = "0"b;
117 seek_idcw_template.control = PROCEED;
118 seek_idcw_template.chan_cmd = SINGLE_RECORD;
119 unspec (data_idcw_template) = unspec (seek_idcw_template);
120
121
122
123 data_idcw_template.ext_ctl = "1"b;
124 data_idcw_template.control = TERMINATE;
125
126 unspec (toehold.save_dcws) = ""b;
127 unspec (toehold.handler_dcws) = ""b;
128
129 dcw_list_ptr = addr (toehold.save_dcws);
130 toehold.dcws_per_cyl = divide (rec_per_cyl (rpv_devt) + (Pages_per_dcw - 1), Pages_per_dcw, 17);
131 toehold.seeks_used = 1;
132 toehold.dcw_list_size = currentsize (dcw_list);
133 running_seeks = 0;
134 running_address = Hardware_low_mem_page_size;
135 running_record = sys_boot_info$bce_part_frec + SAVED_IMAGE_RECORDX + running_address;
136 records_to_do = toehold_page_addr - running_address;
137
138
139
140 do while (records_to_do > 0);
141 running_seeks = running_seeks + 1;
142 call process_one_cylinder (running_seeks, addr (toehold.save_dcws));
143 end;
144
145 running_address = toehold_page_addr + Toehold_size;
146 running_record = sys_boot_info$bce_part_frec + SAVED_IMAGE_RECORDX + running_address;
147 records_to_do = Max_pages_in_segment + Max_pages_in_segment - running_address;
148
149 do while (records_to_do > 0);
150 running_seeks = running_seeks + 1;
151 call process_one_cylinder (running_seeks, addr (toehold.save_dcws));
152 end;
153
154 toehold.seeks_used = running_seeks;
155
156
157
158 running_seeks = 0;
159 running_record = sys_boot_info$config_part_frec;
160 running_address = divide (absadr (addr (config_deck$), (0)), 1024, 18);
161 records_to_do = Config_deck_size;
162
163 do while (records_to_do > 0);
164 running_seeks = running_seeks + 1;
165 call process_one_cylinder (running_seeks, addr (toehold.handler_dcws));
166 end;
167
168 running_address = toehold_page_addr + Toehold_size;
169 running_record = sys_boot_info$bce_part_frec + CRASH_HANDLER_RECORDX + running_address;
170 records_to_do = Max_pages_in_segment + Max_pages_in_segment - running_address;
171
172 do while (records_to_do > 0);
173 running_seeks = running_seeks + 1;
174 call process_one_cylinder (running_seeks, addr (toehold.handler_dcws));
175 end;
176
177 toehold.seeks_used = max (running_seeks, toehold.seeks_used);
178
179 %page;
180
181
182
183 unspec (addrel (addr (toehold_data$), fault_vector_abs_addr) -> fv) =
184 unspec (addr (fault_vector$) -> fv);
185
186 unspec (addrel (addr (toehold_data$), iom_mailbox_abs_addr) -> iom_mailbox_seg) =
187 unspec (addr (iom_mailbox$) -> iom_mailbox_seg);
188
189
190
191 call pc$flush;
192 call sdw_util_$get_address (addr (dseg$ (segno (addr (abs_seg0$)))), abs_seg_pt_abs_addr);
193 abs_seg_pt_ptr = ptr (addr (int_unpaged_page_tables$), abs_seg_pt_abs_addr - absadr (addr (int_unpaged_page_tables$), (0)));
194
195 do running_address = 0 to Max_pages_in_segment - 1;
196 call ptw_util_$make_core (addr (abs_seg_pt (running_address)), (running_address + Max_pages_in_segment) * 1024);
197 end;
198 call pmut$camp;
199
200 do running_address = Max_pages_in_segment + Max_pages_in_segment - 1 to Max_pages_in_segment by -1;
201 running_record = sys_boot_info$bce_part_frec + CRASH_HANDLER_RECORDX + running_address;
202 call write_disk$write_disk_no_test (pvt$root_pvtx, running_record, addr (abs_seg0$ (running_address - Max_pages_in_segment)), code);
203 if code ^= 0 then call syserr$error_code (CRASH, code, "init_toehold: Unable to save bootload Multics image to disk.");
204 end;
205
206 do running_address = 0 to Max_pages_in_segment - 1;
207 call ptw_util_$make_core (addr (abs_seg_pt (running_address)), running_address * 1024);
208 end;
209 call pmut$camp;
210
211 do running_address = Max_pages_in_segment - 1 to toehold_page_addr + Toehold_size by -1;
212 running_record = sys_boot_info$bce_part_frec + CRASH_HANDLER_RECORDX + running_address;
213 call write_disk$write_disk_no_test (pvt$root_pvtx, running_record, addr (abs_seg0$ (running_address)), code);
214 if code ^= 0 then call syserr$error_code (CRASH, code, "init_toehold: Unable to save bootload Multics image to disk.");
215 end;
216
217 call save_handler_mc (addr (toehold$));
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237 return;
238 %page;
239 save_safe_config_deck: entry;
240
241
242
243
244 toehold_ptr = addr (toehold$);
245
246 old_memory_state = toehold.memory_state;
247 toehold.memory_state = 0;
248
249 call find_rpv;
250
251 toehold.memory_state = old_memory_state;
252
253 do running_record = sys_boot_info$safe_config_deck_frec + Config_deck_size - 1 to sys_boot_info$safe_config_deck_frec by -1;
254 call write_disk$write_disk_no_test (
255 pvt$root_pvtx, running_record,
256 addrel (addr (safe_config_deck$), 1024 * (running_record - sys_boot_info$safe_config_deck_frec)), code);
257 if code ^= 0 then call syserr$error_code (BEEP, code, "init_toehold: Unable to save safe_config_deck to disk.");
258 end;
259 return;
260 %page;
261 process_one_cylinder:
262 procedure (cx, p_dcw_list_ptr);
263 dcl cx fixed bin;
264 dcl p_dcw_list_ptr ptr;
265 dcl full_tallys fixed bin;
266 dcl i fixed bin;
267 dcl records_to_do_here fixed bin (18);
268 dcl residue fixed bin;
269
270 dcw_list_ptr = p_dcw_list_ptr;
271 dcw_list (cx).seek_idcw = unspec (seek_idcw_template);
272 data_idcw_template.ext = ext_value (running_address);
273 dcw_list (cx).data_idcw = unspec (data_idcw_template);
274 dcw_list (cx).seek_addresses = sector (running_record);
275 dcw_ptr = addr (dcw_list (cx).seek_dcw);
276 unspec (dcw) = IOTD_INIT_STRING;
277 dcw.address = absadr (addr (dcw_list.seek_addresses (cx)), (0));
278 dcw.tally = 1;
279
280
281
282
283 records_to_do_here = min (records_to_do, rec_per_cyl (rpv_devt) - mod (running_record, rec_per_cyl (rpv_devt)));
284
285
286
287
288 if ext_value (running_address) < 1 & ext_value (running_address + records_to_do_here) ^< 1
289 then records_to_do_here = Max_pages_in_segment - running_address;
290
291
292
293 if mod (records_to_do_here, Pages_per_dcw) = 0
294 then do;
295 full_tallys = divide (records_to_do_here, Pages_per_dcw, 18, 0);
296 residue = 0;
297 end;
298 else do;
299 full_tallys = divide (records_to_do_here, Pages_per_dcw, 18, 0);
300 residue = mod (records_to_do_here, Pages_per_dcw);
301 end;
302
303 do i = 1 to full_tallys;
304 dcw_ptr = addr (dcw_list (cx).data_dcws (i));
305 unspec (dcw) = IOTP_INIT_STRING;
306 dcw.address = mod (running_address, Max_pages_in_segment) * 1024;
307 dcw.tally = 0;
308 running_address = running_address + Pages_per_dcw;
309 running_record = running_record + Pages_per_dcw;
310 end;
311 if residue = 0
312 then dcw.type = IOTD;
313 else do;
314 dcw_ptr = addr (dcw_list (cx).data_dcws (i));
315 unspec (dcw) = IOTD_INIT_STRING;
316 dcw.address = mod (running_address, Max_pages_in_segment) * 1024;
317 dcw.tally = residue * 1024;
318 running_address = running_address + residue;
319 running_record = running_record + residue;
320 end;
321
322 records_to_do = records_to_do - records_to_do_here;
323
324
325 end process_one_cylinder;
326
327
328
329
330
331
332 sector:
333 procedure (Record) returns (fixed bin (35));
334 dcl Record fixed bin (18);
335 dcl devadd fixed bin (18);
336 dcl record_offset fixed bin (18);
337 if pvte.is_sv then do;
338
339
340 record_offset = mod (Record, pvte.records_per_cyl);
341 devadd = ((Record - record_offset) * pvte.num_of_svs) +
342 pvte.record_factor + record_offset;
343 end;
344 else devadd = Record;
345 return ((divide (devadd, rec_per_cyl (rpv_devt), 18, 0) * sect_per_cyl (rpv_devt))
346 + (mod (devadd, rec_per_cyl (rpv_devt)) * sect_per_rec (rpv_devt)));
347 end sector;
348
349 ext_value:
350 procedure (Address) returns (fixed bin);
351 dcl Address fixed bin;
352
353 return (divide (Address, Max_pages_in_segment, 18, 0));
354 end ext_value;
355 %page;
356 find_rpv: proc;
357
358
359
360 pvt_arrayp = addr (pvt$array);
361 pvtep = addr (pvt_array (pvt$root_pvtx));
362 rpv_devt = pvte.device_type;
363 disk_device_number = pvte.logical_area_number;
364
365
366
367 disksp = addr (disk_seg$);
368 iom_data_ptr = addr (iom_data$);
369 do sx = 1 to disk_data.subsystems while (disk_data.name (sx) ^= pvte.devname);
370 end;
371 diskp = ptr (disksp, disk_data.offset (sx));
372
373 do toehold.n_paths_used = 1 to min (dimension (toehold.paths, 1), disktab.nchan);
374 cp = addr (ptr (disksp, disktab.channels) -> disk_channel_table (toehold.n_paths_used));
375 disk_iom_number = iom_data.per_device (chantab.chx).iom;
376 disk_channel_number = iom_data.per_device (chantab.chx).channel;
377
378 do disk_iom_port_number = lbound (scs$port_data, 1) to hbound (scs$port_data, 1)
379 while (scs$port_data (disk_iom_port_number).assigned ^= IOM_PORT
380 | scs$port_data (disk_iom_port_number).iom_number ^= disk_iom_number);
381 end;
382
383 toehold.paths (toehold.n_paths_used).port_number = disk_iom_port_number;
384 toehold.paths (toehold.n_paths_used).iom_number = disk_iom_number;
385 toehold.paths (toehold.n_paths_used).channel_number = disk_channel_number;
386
387 pcw_ptr = addr (toehold.paths (toehold.n_paths_used).pcw);
388 unspec (pcw) = PCW_INIT_STRING;
389 pcw.command = "40"b3;
390 pcw.device = disk_device_number;
391 pcw.ext = 0;
392 end;
393 toehold.n_paths_used = toehold.n_paths_used - 1;
394 return;
395 end;
396 %page; %include dskdcl;
397 %page; %include fault_vector;
398 %page; %include fs_dev_types;
399 %page; %include io_chnl_util_dcls;
400 %page; %include iom_chan_control_words;
401 %page; %include iom_data;
402 %page; %include pvte;
403 %page; %include scs;
404 %page; %include syserr_constants;
405 %page; %include toehold_save_dcls_;
406 %page;
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446 end init_toehold;