1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 fnp_util:
23 procedure;
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 dcl a_devx fixed bin;
53 dcl a_fnp_no fixed bin;
54 dcl a_fnp_mem_size fixed bin;
55 dcl a_fnp_type fixed bin;
56 dcl a_ptr ptr;
57 dcl a_load_info_ptr ptr;
58 dcl a_count fixed bin;
59 dcl a_code fixed bin (35);
60 dcl a_ev_chan fixed bin (71);
61 dcl a_absadr fixed bin (24);
62 dcl a_version char (4);
63 dcl a_image_name char (168);
64 dcl norm_int_cell fixed bin;
65 dcl emergency_int_cell fixed bin;
66 dcl a_ints bit (2) aligned;
67 dcl a_level fixed bin (3);
68 dcl a_fnp_addr fixed bin (15);
69
70
71
72 dcl auto_absadr fixed bin (24);
73 dcl dia_timeout bit (1) aligned;
74 dcl fnp_no fixed bin;
75 dcl fnp_mem_size fixed bin;
76 dcl fnp_type fixed bin;
77 dcl fnp_addr fixed bin (15);
78 dcl chanid char (8) aligned;
79 dcl opcode bit (6) aligned;
80 dcl temp_fnp_name char (32);
81 dcl fnp_size fixed bin;
82 dcl segptr ptr;
83 dcl nwords fixed bin;
84 dcl code fixed bin (35);
85 dcl iom_channel_number fixed bin (7);
86 dcl devx fixed bin;
87 dcl i fixed bin;
88 dcl data_ptr ptr;
89 dcl offset fixed bin;
90 dcl fnp_tally fixed bin;
91 dcl start_time fixed bin (71);
92 dcl version char (4);
93 dcl cur_la_no bit (3);
94 dcl cur_slot_no fixed bin (6);
95 dcl load_info_ptr ptr;
96 dcl locked bit (1) aligned init ("0"b);
97 dcl config_locked bit (1) aligned init ("0"b);
98
99 declare message fixed bin (71);
100 declare 1 auto_fnp_msg aligned like fnp_msg;
101
102
103
104 dcl (addr, addrel, baseno, bit, clock, fixed, min, null, ptr, string, substr) builtin;
105
106
107
108
109 dcl config_$find_2 entry (character (4) aligned, character (4) aligned, pointer);
110 dcl fnp_multiplexer$assign entry (fixed binary, fixed binary (35));
111 dcl fnp_multiplexer$unassign entry (fixed binary, fixed binary (35));
112 dcl fnp_multiplexer$fnp_lock entry (pointer, fixed binary (35));
113 dcl fnp_multiplexer$fnp_unlock entry (pointer);
114 dcl get_fnp_name_ entry (fixed bin) returns (char (32));
115 dcl grab_aste$grab_aste_io entry (ptr, fixed bin, fixed bin (35)) returns (ptr);
116 dcl grab_aste$release_io entry (ptr);
117 dcl ioam_$assign entry (fixed bin, entry, fixed bin (35));
118 dcl ioam_$unassign entry (fixed bin, fixed bin (35));
119 dcl priv_channel_manager$get_devx entry (char (*), fixed bin, fixed bin (35));
120 dcl dn355_util$compute_parity entry (bit (36)) returns (bit (36));
121 dcl absadr entry (ptr, fixed bin (35)) returns (fixed bin (24));
122 dcl ioi_page_table$get entry (fixed binary (19), fixed binary, fixed binary (35));
123 dcl ioi_page_table$fill entry (fixed binary, pointer, fixed binary (35));
124 dcl ioi_page_table$ptx_to_ptp entry (fixed binary) returns (pointer);
125 dcl ioi_page_table$put entry (fixed binary, fixed binary (35));
126 dcl pxss$notify entry (fixed bin);
127 dcl pxss$addevent entry (fixed bin);
128 dcl pxss$delevent entry (fixed bin);
129 dcl pxss$wait entry;
130 dcl pxss$ring_0_wakeup entry (bit (36) aligned, fixed bin (71), fixed bin (71), fixed bin (35));
131 dcl get_ptrs_$given_segno entry (fixed bin) returns (ptr);
132 dcl dn355$interrupt entry;
133 dcl syserr entry options (variable);
134 dcl syserr$error_code entry options (variable);
135 dcl lock$wait entry (ptr, char (4) aligned, fixed bin (35));
136 dcl lock$lock_fast entry (pointer);
137 dcl lock$unlock_fast entry (pointer);
138 dcl lock$unlock entry (ptr, char (4) aligned);
139 dcl (
140 pc_abs$wire_abs,
141 pc_abs$wire_abs_contig
142 ) entry (ptr, fixed bin, fixed bin, fixed bin (35));
143 dcl pc_abs$unwire_abs entry (ptr, fixed bin, fixed bin);
144
145
146
147 dcl (
148 error_table_$io_no_permission,
149 error_table_$invalid_state,
150 error_table_$bad_mpx_load_data,
151 error_table_$no_io_interrupt,
152 error_table_$rqover,
153 error_table_$bad_segment,
154 error_table_$noalloc,
155 error_table_$action_not_performed,
156 error_table_$io_configured,
157 error_table_$io_not_configured,
158 error_table_$io_assigned,
159 error_table_$io_not_assigned,
160 error_table_$io_not_defined
161 ) fixed bin (35) ext static;
162
163 dcl pds$processid bit (36) ext static;
164 dcl pds$process_group_id char (32) ext static;
165 dcl tc_data$initializer_id bit (36) aligned external static;
166 dcl tty_buf$fnp_config_flags (1:8) bit (1) unaligned external static;
167 dcl tty_buf$lct_ptr pointer external static;
168 dcl sst$astsize fixed bin external;
169 dcl sys_info$page_size fixed bin external;
170 dcl sys_info$seg_size_256K fixed bin (19) external;
171
172
173
174 dcl (
175 FNP_DOWN init (2)
176 ) fixed bin int static options (constant);
177
178 dcl fdump_seg_event char (4) aligned init ("fnpd") static options (constant);
179 dcl cleanup condition;
180 dcl record_quota_overflow condition;
181
182
183
184
185 dcl tally_words (fnp_tally) bit (36) aligned based;
186
187 dcl 1 dump_355_control aligned based (data_ptr),
188 2 address_mode bit (3) unaligned,
189 2 fnp_address bit (15) unaligned,
190 2 tally fixed bin (17) unaligned;
191
192 dcl 1 dump_6670_control aligned based (data_ptr),
193 2 fnp_address fixed bin (18) unsigned unaligned,
194 2 unpaged bit (1) unaligned,
195 2 mbz bit (5) unaligned,
196 2 tally fixed bin (12) unsigned unaligned;
197
198 dcl 1 load_info aligned based (load_info_ptr),
199 2 no_entries fixed bin,
200 2 entries (0 refer (load_info.no_entries)),
201 3 devx fixed bin,
202 3 baud_rate fixed bin,
203 3 line_type fixed bin;
204 ^L
205
206
207 wire:
208 entry (a_fnp_no, a_ptr, a_absadr, a_count, a_code);
209
210
211
212
213 fnp_no = a_fnp_no;
214 segptr = a_ptr;
215 nwords = a_count;
216
217 call validate_fnp_ret ("wire");
218 call validate_assigned_ret ("wire");
219
220 if fnp_info.wired
221 then do;
222 a_code = 0;
223 if datanet_info.trace
224 then call syserr (ANNOUNCE, "fnp_util$wire: FNP ^a already wired.", fnp_info.fnp_tag);
225 note
226 return;
227 end;
228
229 astep = grab_aste$grab_aste_io (segptr, nwords, code);
230
231
232 if code ^= 0
233 then go to wire_error_return;
234
235 fnp_info.astep = astep;
236 fnp_info.n_pages_wired = divide (nwords + sys_info$page_size - 1, sys_info$page_size, 17, 0);
237
238 call pc_abs$wire_abs (astep, 0, fnp_info.n_pages_wired, code);
239
240 if code ^= 0
241 then do;
242 call grab_aste$release_io (astep);
243 go to wire_error_return;
244 end;
245 call fill_bootload_page_table;
246 if datanet_info.trace
247 then call syserr (ANNOUNCE, "fnp_util$wire: seg: ^p n_pages: ^d astep ^p", segptr, fnp_info.n_pages_wired,
248 astep);
249
250 a_absadr = auto_absadr;
251 fnp_info.wired = "1"b;
252
253 wire_error_return:
254 if code ^= 0 & (datanet_info.trace | datanet_info.debug_stop)
255 then do;
256 call syserr$error_code (ANNOUNCE, code, "fnp_util$wire: failed.");
257 call STOP_CHECK ("wire");
258 end;
259 a_code = code;
260 return;
261 ^L
262
263 load:
264 entry (a_fnp_no, a_absadr, a_ev_chan, a_version, a_image_name, a_fnp_mem_size, a_load_info_ptr, a_code);
265
266
267
268
269 fnp_no = a_fnp_no;
270 fnp_mem_size = a_fnp_mem_size;
271 auto_absadr = a_absadr;
272 call validate_fnp_ret ("load");
273 call validate_assigned_ret ("load");
274
275 if datanet_info.trace
276 then call syserr (ANNOUNCE, "fnp_util$load: FNP ^d ADDR ^o", fnp_no, auto_absadr);
277
278 if fnp_info.bootloading
279 then do;
280 code = error_table_$invalid_state;
281 call syserr (ANNOUNCE, "fnp_util$load: FNP load already in progress for FNP ^a.", fnp_info.fnp_tag);
282 go to load_return;
283 end;
284
285 if ^fnp_info.wired
286 then do;
287 code = error_table_$invalid_state;
288 if datanet_info.trace
289 then call syserr (ANNOUNCE, "fnp_util$load: FNP ^a not wired.", fnp_info.fnp_tag);
290 go to load_return;
291 end;
292
293 if fnp_info.running
294 then do;
295 code = error_table_$invalid_state;
296 if datanet_info.trace
297 then call syserr (ANNOUNCE, "fnp_util$load: FNP ^a is running.", fnp_info.fnp_tag);
298 go to load_return;
299 end;
300
301 if fnp_info.t_and_d_in_progress
302 then do;
303 code = error_table_$invalid_state;
304 if datanet_info.trace
305 then call syserr (ANNOUNCE, "fnp_util$load: FNP ^a is running T&D.", fnp_info.fnp_tag);
306 go to load_return;
307 end;
308
309
310
311 load_info_ptr = a_load_info_ptr;
312 if load_info.no_entries ^= fnp_info.no_of_channels
313 then do;
314 code = error_table_$bad_mpx_load_data;
315 go to load_return;
316 end;
317
318 cur_la_no = "7"b3;
319 n_pcbs = load_info.no_entries;
320 do i = 1 to load_info.no_entries;
321 pcbp = addr (fnp_info.pcb_array_ptr -> pcb_array (i));
322 if load_info (i).devx ^= pcb.devx
323 then do;
324 code = error_table_$bad_mpx_load_data;
325 go to load_return;
326 end;
327 pcb.baud_rate = load_info (i).baud_rate;
328 pcb.line_type = load_info (i).line_type;
329
330 if ^pcb.is_hsla
331 then do;
332 if pcb.la_no ^= cur_la_no
333 then do;
334 cur_la_no = pcb.la_no;
335 cur_slot_no = 1;
336 end;
337
338 pcb.slot_no = bit (cur_slot_no, 6);
339 if pcb.baud_rate <= 110
340 then cur_slot_no = cur_slot_no + 1;
341 else if pcb.baud_rate <= 150
342 then cur_slot_no = cur_slot_no + 2;
343 else cur_slot_no = cur_slot_no + 3;
344 end;
345 end;
346
347
348
349 call lock_fnp;
350 if ^fnp_info.io_manager_assigned
351 then do;
352 call unlock_fnp;
353 code = error_table_$io_not_assigned;
354 go to load_return;
355 end;
356 version = a_version;
357 call syserr (ANNOUNCE, "Loading FNP ^a, ^a ^a", fnp_info.fnp_tag, a_image_name, version);
358
359 fnp_info.boot_ev_chan = a_ev_chan;
360 fnp_info.boot_process_id = pds$processid;
361 fnp_info.version = version;
362 fnp_info.fnp_mem_size = fnp_mem_size * 1024;
363 fnp_info.bootloading = "1"b;
364 datanet_mbx.mailbox_requests = 0;
365 datanet_mbx.term_inpt_mpx_wd = "0"b;
366 datanet_mbx.last_mbx_req_count = 0;
367 string (datanet_mbx.mbx_used_flags) = "0"b;
368
369 datanet_mbx.crash_data.fault_code = 0;
370 datanet_mbx.crash_data.ic = 0;
371 datanet_mbx.crash_data.iom_fault_status = 0;
372 datanet_mbx.crash_data.fault_word = 0;
373
374 auto_absadr = sys_info$page_size * FIRST_BOOTLOAD_PAGEX;
375
376 call mask_dia;
377 call connect_to_dia_paged (auto_absadr, 0, "72"b3, dia_timeout);
378
379
380 if dia_timeout
381 then code = error_table_$no_io_interrupt;
382 else code = 0;
383 call unlock_fnp;
384
385 load_return:
386 if code ^= 0 & (datanet_info.trace | datanet_info.debug_stop)
387 then do;
388 call syserr$error_code (ANNOUNCE, code, "fnp_util$load: Error loading FNP ^a.", fnp_info.fnp_tag);
389 call STOP_CHECK ("load");
390 end;
391 a_code = code;
392 return;
393 ^L
394
395 info:
396 entry (a_fnp_no, a_absadr, norm_int_cell, emergency_int_cell, a_code);
397
398
399
400 fnp_no = a_fnp_no;
401 call validate_fnp_ret ("info");
402
403 a_absadr = absadr (fnp_info.mbx_pt, code);
404 if code = 0
405 then do;
406 norm_int_cell = 3;
407 emergency_int_cell = 7;
408 end;
409
410 a_code = code;
411 return;
412 ^L
413 fill_page_table:
414 entry (a_fnp_no, a_code);
415
416 fnp_no = a_fnp_no;
417 call validate_fnp_ret ("fill_page_table");
418 call validate_assigned_ret ("fill_page_table");
419 if fnp_info.ptx ^= -1 | fnp_info.ptp ^= null ()
420 then do;
421 call syserr (ANNOUNCE, "fnp_util$fill_page_table: page table already assigned for FNP ^a.",
422 fnp_info.fnp_tag);
423 call STOP_CHECK ("fill_page_table");
424 end;
425 call get_page_table (code);
426 if code ^= 0 & (datanet_info.trace | datanet_info.debug_stop)
427 then do;
428 call syserr$error_code (ANNOUNCE, code, "fnp_util$fill_page_table: ioi_page_table$get failed for FNP ^a.",
429 fnp_info.fnp_tag);
430 call STOP_CHECK ("fill_page_table");
431 end;
432 a_code = code;
433 return;
434
435 free_page_table:
436 entry (a_fnp_no, a_code);
437
438 fnp_no = a_fnp_no;
439 call validate_fnp_ret ("free_page_table");
440 if fnp_info.ptx = -1
441 then do;
442 call syserr (ANNOUNCE, "fnp_util$free_page_table: no page table assigned for FNP ^a.", fnp_info.fnp_tag);
443 go to ret_bad_code;
444 end;
445 call ioi_page_table$put (fnp_info.ptx, code);
446 fnp_info.ptx = -1;
447 fnp_info.ptp = null ();
448 a_code = code;
449 return;
450 ^L
451
452 unwire:
453 entry (a_fnp_no, a_code);
454
455
456
457
458 fnp_no = a_fnp_no;
459 call validate_fnp_ret ("unwire");
460
461
462
463 call internal_unwire;
464 fnp_info.bootloading = "0"b;
465
466 if code ^= 0 & (datanet_info.trace | datanet_info.debug_stop)
467 then do;
468 call syserr$error_code (ANNOUNCE, code, "fnp_util$unwire: Unwire failed for FNP ^a.", fnp_info.fnp_tag);
469 call STOP_CHECK ("unwire");
470 end;
471 a_code = code;
472 return;
473 ^L
474
475
476
477
478
479 configure:
480 entry (a_fnp_no, a_code);
481
482 fnp_no = a_fnp_no;
483 call validate_fnp_ret ("configure");
484 call lock_fnp;
485 if fnp_info.available
486 then do;
487 code = error_table_$io_configured;
488 if datanet_info.trace | datanet_info.debug_stop
489 then call syserr (ANNOUNCE, "fnp_util$configure: FNP ^a already configured.", fnp_info.fnp_tag);
490 call STOP_CHECK ("configure");
491 go to configure_return;
492 end;
493 fnp_info.available = "1"b;
494 fnp_info.io_manager_assigned = "0"b;
495 fnp_info.flags = "0"b;
496 configure_return:
497 call unlock_fnp;
498 if code = 0
499 then do;
500 call config_$find_2 ("prph", "fnp" || fnp_info.fnp_tag, prph_fnp_cardp);
501 prph_fnp_card.state = "on";
502 call syserr (ANNOUNCE, "fnp_util: FNP ^a added to configuration^[ by ^a^].", fnp_info.fnp_tag,
503 pds$processid ^= tc_data$initializer_id, pds$process_group_id);
504 end;
505 a_code = code;
506 return;
507
508
509
510
511
512 deconfigure:
513 entry (a_fnp_no, a_code);
514
515 fnp_no = a_fnp_no;
516 call validate_fnp_ret ("deconfigure");
517 call lock_fnp;
518
519 if ^fnp_info.available
520 then do;
521 code = error_table_$io_not_configured;
522 go to deconfigure_return;
523 end;
524
525 fnp_info.available = "0"b;
526
527 if ^fnp_info.io_manager_assigned
528 then go to deconfigure_return;
529
530
531
532 if fnp_info.t_and_d_in_progress
533 then do;
534 call unlock_fnp;
535 call release_t_and_d;
536 go to deconfigure_return_unlocked;
537 end;
538 else do;
539 call mask_dia;
540 call fnp_multiplexer$unassign (fnp_no, (0));
541
542 auto_fnp_msg.fnp_no = fnp_info.fnp_number;
543 auto_fnp_msg.state = FNP_DOWN;
544 auto_fnp_msg.flags = "0"b;
545 auto_fnp_msg.deconfigured = "1"b;
546 unspec (message) = unspec (auto_fnp_msg);
547 call pxss$ring_0_wakeup (fnp_info.boot_process_id, fnp_info.boot_ev_chan, message, (0));
548 end;
549
550
551
552 deconfigure_return:
553 call unlock_fnp;
554 deconfigure_return_unlocked:
555 if code = 0
556 then do;
557 call config_$find_2 ("prph", "fnp" || fnp_info.fnp_tag, prph_fnp_cardp);
558 prph_fnp_card.state = "off";
559 call syserr (ANNOUNCE, "fnp_util: FNP ^a deleted from configuration^[ by ^a^].", fnp_info.fnp_tag,
560 pds$processid ^= tc_data$initializer_id, pds$process_group_id);
561 end;
562 a_code = code;
563 return;
564 ^L
565
566
567
568 fdump:
569 entry (a_fnp_no, a_fnp_type, a_fnp_mem_size, a_ptr, a_code);
570
571
572
573
574
575
576
577
578 fnp_no = a_fnp_no;
579 fnp_type = a_fnp_type;
580 fnp_mem_size = a_fnp_mem_size;
581 segptr = a_ptr;
582
583 call validate_fnp_ret ("fdump");
584
585 if fnp_info.running | fnp_info.bootloading | fnp_info.t_and_d_in_progress
586 then do;
587 code = error_table_$invalid_state;
588 go to ret_bad_code;
589 end;
590
591 fnp_dump_ptr = addr (fnp_dump_seg$);
592 on cleanup
593 begin;
594 if fnp_dump_seg.lock = pds$processid
595 then call lock$unlock (addr (fnp_dump_seg.lock), fdump_seg_event);
596 end;
597 call lock$wait (addr (fnp_dump_seg.lock), fdump_seg_event, code);
598 if code ^= 0
599 then go to ret_bad_code;
600
601 call wire_dump_seg;
602 if code ^= 0
603 then go to unlock_dump_seg;
604
605 fnp_dump_seg.flags = "0"b;
606 call assign_interrupt (dump_interrupt, code);
607 if code ^= 0
608 then go to unwire_buffer;
609
610 data_ptr = addr (fnp_dump_seg.data);
611 if fnp_type = DN6670
612 then dump_6670_control.unpaged = "1"b;
613 else dump_355_control.address_mode = "001"b;
614 fnp_size = fnp_mem_size * 512;
615
616
617
618 on record_quota_overflow
619 begin;
620 code = error_table_$rqover;
621 go to restore_interrupts;
622 end;
623
624
625
626 fnp_addr = 0;
627 do offset = 0 to fnp_size by 1021;
628 fnp_tally = min (1021, fnp_size - offset);
629 call setup_dump_ctl_word;
630 call fdump_seg_io ("fdump", "75"b3, code);
631 if code ^= 0
632 then go to restore_interrupts;
633
634
635
636 ptr (segptr, offset) -> tally_words = addr (fnp_dump_seg.data (2)) -> tally_words;
637
638 end;
639
640 restore_interrupts:
641 call unassign_interrupt;
642 unwire_buffer:
643 call unwire_dump_seg;
644 unlock_dump_seg:
645 call lock$unlock (addr (fnp_dump_seg.lock), fdump_seg_event);
646 ret_bad_code:
647 a_code = code;
648 return;
649
650
651 fdump_seg_io:
652 proc (caller, a_diaop, code);
653
654 dcl caller char (32);
655 dcl a_diaop bit (6) aligned;
656 dcl code fixed bin (35);
657
658 start_time = clock ();
659 if datanet_info.trace
660 then call syserr (ANNOUNCE, "fnp_util$fdump_seg_io: ^2.3b for ^a.", a_diaop, caller);
661 call lock_fnp;
662 if ^fnp_info.io_manager_assigned
663 then do;
664 call unlock_fnp;
665 code = error_table_$io_not_assigned;
666 return;
667 end;
668
669 fnp_dump_seg.fdump = "1"b;
670 call pxss$addevent (tty_ev);
671 call connect_to_dia (auto_absadr, 0, a_diaop, dia_timeout);
672 call unlock_fnp;
673 if ^dia_timeout
674 then do;
675 call pxss$wait;
676 if datanet_info.trace
677 then call syserr (ANNOUNCE, "fnp_util (fdump_seg_io): returned from first wait.");
678 end;
679 else do;
680 call pxss$delevent (tty_ev);
681 if datanet_info.trace
682 then call syserr (ANNOUNCE, "fnp_util (fdump_seg_io): DIA timeout.");
683 code = error_table_$no_io_interrupt;
684 return;
685 end;
686
687 do while (fnp_dump_seg.fdump);
688 if clock () - start_time > 5 * 1000 * 1000
689 then do;
690 if datanet_info.trace
691 then call syserr (ANNOUNCE, "fnp_util (fdump_seg_io): FNP timeout.");
692 code = error_table_$no_io_interrupt;
693 return;
694 end;
695
696 call pxss$addevent (tty_ev);
697 if fnp_info.t_and_d_in_progress
698 then if fnp_info.t_and_d_lev_3_occurred | fnp_info.t_and_d_lev_7_occurred
699 then do;
700 code = 0;
701 return;
702 end;
703 if fnp_dump_seg.fdump
704 then call pxss$wait;
705 else call pxss$delevent (tty_ev);
706 end;
707 code = 0;
708 end fdump_seg_io;
709
710 dump_interrupt:
711 entry (a_fnp_no, a_level, a_dummy);
712
713
714
715 dcl a_dummy bit (36) aligned parameter;
716
717 fnp_dump_ptr = addr (fnp_dump_seg$);
718 infop = addr (dn355_data$);
719 if datanet_info.trace
720 then call syserr (ANNOUNCE,
721 "fnp_util (dump_interrupt): Interrupt for FNP ^d level ^d. fnp_dump_seg.fdump = ""^b""b", a_fnp_no,
722 a_level, fnp_dump_seg.fdump);
723 if fnp_dump_seg.fdump
724 then do;
725 fnp_dump_seg.fdump = "0"b;
726 call pxss$notify (tty_ev);
727 end;
728 return;
729 ^L
730 fnp_tandd_setup:
731 entry (a_fnp_no, a_ev_chan, a_code);
732
733 fnp_no = a_fnp_no;
734 call validate_fnp_ret ("fnp_tandd_setup");
735
736
737
738
739
740 temp_fnp_name = get_fnp_name_ (fnp_no);
741 if fnp_info.lcte_ptr = null
742 then do;
743 call priv_channel_manager$get_devx (temp_fnp_name, devx, code);
744 if code ^= 0
745 then go to ret_bad_code;
746 fnp_info.lcte_ptr = addr (tty_buf$lct_ptr -> lct.lcte_array (devx));
747 end;
748
749 call lock_fnp;
750
751 if fnp_info.bootloading | fnp_info.running | fnp_info.t_and_d_in_progress
752 then do;
753 code = error_table_$invalid_state;
754 go to tandd_setup_loses_unlock;
755 end;
756
757 call fnp_multiplexer$assign (fnp_no, code);
758 if code ^= 0
759 then do;
760 call syserr$error_code (ANNOUNCE, code, "fnp_util: channel assignment failed for FNP ^a.",
761 fnp_info.fnp_tag);
762 go to tandd_setup_loses_unlock;
763 end;
764
765 call ioam_$assign ((fnp_info.io_manager_chx), fnp_tandd_release_handler, code);
766 if code ^= 0
767 then do;
768 call syserr$error_code (ANNOUNCE, code, "fnp_util: ioam_$assign failed for FNP ^a.", fnp_info.fnp_tag);
769 go to tandd_setup_loses_unlock;
770 end;
771 fnp_info.boot_process_id = pds$processid;
772 fnp_info.t_and_d_lev_3_occurred, fnp_info.t_and_d_lev_7_occurred = "0"b;
773 call syserr (ANNOUNCE, "fnp_util: assigned FNP ^a to ^a for T & D.", temp_fnp_name, pds$process_group_id);
774 fnp_info.t_and_d_in_progress = "1"b;
775
776 tandd_setup_loses_unlock:
777 if code = 0
778 then fnp_info.boot_ev_chan = a_ev_chan;
779 call unlock_fnp;
780 a_code = code;
781 return;
782
783 fnp_tandd_release_handler:
784 entry (a_devx, a_code);
785
786 devx = a_devx;
787 infop = addr (dn355_data$);
788 fnp_dump_ptr = addr (fnp_dump_seg$);
789 on cleanup
790 begin;
791 if fnp_dump_seg.lock = pds$processid
792 then call lock$unlock (addr (fnp_dump_seg.lock), fdump_seg_event);
793 end;
794 do fnp_no = 1 to datanet_info.no_of_355s;
795 fnpp = addr (datanet_info.per_datanet (fnp_no));
796 if devx = fnp_info.io_manager_chx
797 then if fnp_info.t_and_d_in_progress
798 then call release_t_and_d;
799 end;
800 return;
801
802
803
804
805
806
807
808 fnp_tandd_detach:
809 entry (a_fnp_no, a_code);
810 fnp_no = a_fnp_no;
811
812 call validate_fnp_tandd_ret ("fnp_tandd_detach");
813 call lock_fnp;
814 call validate_assigned_ret ("fnp_tandd_detach");
815
816 call mask_dia;
817
818 fnp_info.boot_process_id = "000000000000"b3;
819 fnp_info.t_and_d_in_progress = "0"b;
820 fnp_info.t_and_d_lev_3_occurred, fnp_info.t_and_d_lev_7_occurred = "0"b;
821 call ioam_$unassign ((fnp_info.io_manager_chx), (0));
822 call fnp_multiplexer$unassign (fnp_no, code);
823 if code ^= 0
824 then call syserr$error_code (ANNOUNCE, code, "fnp_util: io channel unassignment failed for FNP ^a.",
825 fnp_info.fnp_tag);
826 call syserr (ANNOUNCE, "fnp_util: releasing FNP ^a from ^a", fnp_info.fnp_id.fnp_tag, pds$process_group_id);
827 call unlock_fnp;
828 a_code = 0;
829 return;
830
831 fnp_tandd_mask:
832 entry (a_fnp_no, a_code);
833 fnp_no = a_fnp_no;
834 call validate_fnp_tandd_ret ("fnp_tandd_mask");
835 call lock_fnp;
836 call validate_assigned_ret ("fnp_tandd_mask");
837
838 call mask_dia;
839 call unlock_fnp;
840 a_code = 0;
841 return;
842
843 fnp_tandd_send_int:
844 entry (a_fnp_no, a_level, a_code);
845 fnp_no = a_fnp_no;
846 call validate_fnp_tandd_ret ("fnp_tandd_send_int");
847 call lock_fnp;
848 call validate_assigned_ret ("fnp_tandd_send_int");
849
850 fnp_info.t_and_d_lev_3_occurred, fnp_info.t_and_d_lev_7_occurred = "0"b;
851 call connect_to_dia (0, a_level, "71"b3, dia_timeout);
852 call unlock_fnp;
853 if dia_timeout
854 then a_code = error_table_$no_io_interrupt;
855 a_code = 0;
856 return;
857
858 fnp_tandd_get_ints:
859 entry (a_fnp_no, a_ints, a_code);
860 fnp_no = a_fnp_no;
861 call validate_fnp_tandd_ret ("fnp_tandd_get_ints");
862 call lock_fnp;
863 call validate_assigned_ret ("fnp_tandd_get_ints");
864 a_ints = fnp_info.t_and_d_lev_3_occurred || fnp_info.t_and_d_lev_7_occurred;
865 fnp_info.t_and_d_lev_3_occurred, fnp_info.t_and_d_lev_7_occurred = "0"b;
866 call unlock_fnp;
867 a_code = 0;
868 return;
869
870 fnp_tandd_read:
871 entry (a_fnp_no, a_ptr, a_count, a_fnp_addr, a_fnp_type, a_code);
872 opcode = "75"b3;
873 go to fnp_t_and_d_rw_merge;
874
875 fnp_tandd_write:
876 entry (a_fnp_no, a_ptr, a_count, a_fnp_addr, a_fnp_type, a_code);
877 opcode = "76"b3;
878 fnp_t_and_d_rw_merge:
879
880
881 fnp_no = a_fnp_no;
882 segptr = a_ptr;
883 nwords = a_count;
884 fnp_type = a_fnp_type;
885 fnp_addr = a_fnp_addr;
886 fnp_dump_ptr = addr (fnp_dump_seg$);
887 call validate_fnp_tandd_ret ("fnp_tandd_rw");
888
889 on cleanup
890 begin;
891 if fnp_dump_seg.lock = pds$processid
892 then call lock$unlock (addr (fnp_dump_seg.lock), fdump_seg_event);
893 end;
894
895 data_ptr = addr (fnp_dump_seg.data);
896
897 call lock$wait (addr (fnp_dump_seg.lock), fdump_seg_event, code);
898 if code ^= 0
899 then go to ret_bad_code;
900 if fnp_type = DN6670
901 then dump_6670_control.unpaged = "1"b;
902 else dump_355_control.address_mode = "1"b3;
903 offset = 0;
904 do while (nwords > 0);
905 fnp_tally = min (308, nwords);
906 nwords = nwords - fnp_tally;
907 call setup_dump_ctl_word;
908 if opcode = "76"b3
909 then addr (fnp_dump_seg.data (2)) -> tally_words = addrel (segptr, offset) -> tally_words;
910 call wire_dump_seg;
911 if code ^= 0
912 then go to unlock_dump_seg;
913 fnp_info.t_and_d_lev_3_occurred, fnp_info.t_and_d_lev_7_occurred = "0"b;
914 fnp_info.t_and_d_notify_requested = "1"b;
915
916 call fdump_seg_io ("fnp_tandd_rw", opcode, code);
917
918 fnp_info.t_and_d_lev_3_occurred, fnp_info.t_and_d_lev_7_occurred = "0"b;
919 call unwire_dump_seg;
920 if code ^= 0
921 then go to unlock_dump_seg;
922 if opcode = "75"b3
923 then addrel (segptr, offset) -> tally_words = addr (fnp_dump_seg.data (2)) -> tally_words;
924
925 offset = offset + fnp_tally;
926 end;
927 code = 0;
928 go to unlock_dump_seg;
929 ^L
930
931 validate_assigned_ret:
932 procedure (caller);
933
934 declare caller char (32);
935
936 if ^fnp_info.io_manager_assigned
937 then do;
938 code = error_table_$io_not_assigned;
939 if datanet_info.trace | datanet_info.debug_stop
940 then call syserr$error_code (ANNOUNCE, code,
941 "fnp_util$validate_assigned_ret (^a): IO manager assignment lacking.", caller);
942 call STOP_CHECK ("validate_assigned_ret");
943 call unlock_fnp;
944 go to ret_bad_code;
945 end;
946 return;
947 end validate_assigned_ret;
948
949
950 validate_fnp_ret:
951 procedure (caller);
952
953 declare caller char (32);
954
955
956
957 infop = addr (dn355_data$);
958
959 if fnp_no <= 0 | fnp_no > max_no_355s
960 then do;
961 code = error_table_$io_not_defined;
962 ERROR:
963 if datanet_info.trace | datanet_info.debug_stop
964 then call syserr$error_code (ANNOUNCE, code, "fnp_util$^a: Invalid call for FNP ^d.", caller, fnp_no);
965 call STOP_CHECK (caller);
966 go to ret_bad_code;
967 end;
968
969 if ^tty_buf$fnp_config_flags (fnp_no)
970 then do;
971 fnpp = null;
972 code = error_table_$io_not_defined;
973 go to ERROR;
974 end;
975
976 code = 0;
977 fnpp = addr (datanet_info.per_datanet (fnp_no));
978 mbxp = fnp_info.mbx_pt;
979 if datanet_info.trace
980 then call syserr (ANNOUNCE, "fnp_util$^a: Tracing call for fnp ^a.", caller, fnp_info.fnp_tag);
981
982 return;
983
984 end validate_fnp_ret;
985 ^L
986
987
988 validate_fnp_tandd_ret:
989 proc (caller);
990
991 declare caller char (32);
992
993 call validate_fnp_ret (caller);
994 if ^fnp_info.t_and_d_in_progress
995 then code = error_table_$invalid_state;
996 else if fnp_info.boot_process_id ^= pds$processid
997 then code = error_table_$io_no_permission;
998 if code ^= 0
999 then do;
1000 if (datanet_info.trace | datanet_info.debug_stop)
1001 then call syserr$error_code (ANNOUNCE, code, "fnp_util$^a: Invalid call.", caller);
1002 go to ret_bad_code;
1003 end;
1004 return;
1005 end validate_fnp_tandd_ret;
1006 ^L
1007 setup_dump_ctl_word:
1008 proc;
1009
1010 if fnp_type = DN6670
1011 then do;
1012 dump_6670_control.fnp_address = fnp_addr + 2 * offset;
1013 dump_6670_control.tally = fnp_tally;
1014 end;
1015 else do;
1016 dump_355_control.fnp_address = bit (fixed (fnp_addr + 2 * offset, 15), 15);
1017 dump_355_control.tally = fnp_tally;
1018 end;
1019 end;
1020
1021 wire_dump_seg:
1022 proc;
1023
1024 astep = get_ptrs_$given_segno (fixed (baseno (fnp_dump_ptr), 17));
1025 call pc_abs$wire_abs_contig (astep, 0, 1, code);
1026 if code = 0
1027 then auto_absadr = absadr (addr (fnp_dump_seg.data), code);
1028
1029 end;
1030
1031 unwire_dump_seg:
1032 proc;
1033
1034 astep = get_ptrs_$given_segno (fixed (baseno (fnp_dump_ptr), 17));
1035 call pc_abs$unwire_abs (astep, 0, 1);
1036 return;
1037 end unwire_dump_seg;
1038
1039
1040 assign_interrupt:
1041 proc (handler, code);
1042
1043
1044
1045 dcl handler entry;
1046
1047 dcl iom_code fixed bin (35);
1048 dcl code fixed bin (35);
1049
1050 call lock_fnp;
1051 if ^fnp_info.io_manager_assigned
1052 then if ^fnp_info.available
1053 then do;
1054 code = error_table_$io_not_configured;
1055 return;
1056 end;
1057
1058
1059
1060 if fnp_info.io_manager_assigned
1061 then do;
1062 call io_manager$unassign (fnp_info.io_manager_chx, code);
1063 if code ^= 0
1064 then call syserr$error_code (CRASH, code, "fnp_util: Could not unassign FNP ^a at reassign_interrupt.",
1065 fnp_info.fnp_tag);
1066 fnp_info.io_manager_assigned = "0"b;
1067 end;
1068
1069 call io_manager$assign (fnp_info.io_manager_chx, fnp_info.io_chanid, handler, (fnp_no), (null ()), iom_code);
1070 call unlock_fnp;
1071 if code = 0
1072 then do;
1073 code = iom_code;
1074 fnp_info.io_manager_assigned = "1"b;
1075 end;
1076
1077 return;
1078
1079 end assign_interrupt;
1080
1081 unassign_interrupt:
1082 procedure;
1083
1084 call io_manager$unassign (fnp_info.io_manager_chx, (0));
1085 fnp_info.io_manager_assigned = "0"b;
1086 return;
1087 end unassign_interrupt;
1088 ^L
1089
1090
1091 connect_to_dia:
1092 proc (address, level, cmd, timeout);
1093
1094
1095
1096 dcl old_pcw bit (36) aligned;
1097 dcl timeout bit (1) aligned;
1098 dcl address fixed bin (24);
1099 dcl level fixed bin (3);
1100 dcl cmd bit (6) aligned;
1101 dcl 1 ima aligned like io_manager_arg;
1102 dcl paged bit (1) aligned;
1103 dcl 1 a_dia_pcw aligned based (mbxp),
1104 2 address fixed bin (18) unsigned unaligned,
1105 2 error bit (1) unaligned,
1106 2 pad1 bit (3) unaligned,
1107 2 parity bit (1) unaligned,
1108 2 pad2 bit (1) unaligned,
1109 2 pad3 bit (3) unaligned,
1110 2 interrupt_level fixed bin (3) unsigned unaligned,
1111 2 command bit (6) unaligned;
1112
1113 paged = "0"b;
1114 go to common;
1115
1116 connect_to_dia_paged:
1117 entry (address, level, cmd, timeout);
1118
1119 paged = "1"b;
1120
1121 common:
1122 unspec (a_dia_pcw) = ""b;
1123 if address > sys_info$seg_size_256K
1124 then call syserr (CRASH, "fnp_util (connect_to_dia): address > 256K");
1125 a_dia_pcw.address = address;
1126 a_dia_pcw.interrupt_level = level;
1127 a_dia_pcw.command = cmd;
1128 if datanet_info.trace | datanet_info.debug_stop
1129 then call syserr (ANNOUNCE, "fnp_util (connect): ^[ paged PTP ^p^;^s^] PCW ^w", paged, fnp_info.ptp,
1130 unspec (datanet_mbx.dia_pcw));
1131 if datanet_info.debug_stop
1132 then do;
1133 call syserr (ANNOUNCE, "fnp_util: stop before connect.");
1134 call syserr (CRASH, " ptp: ^p astep: ^p", fnp_info.ptp, fnp_info.astep);
1135 end;
1136
1137
1138
1139 string (datanet_mbx.dia_pcw) = dn355_util$compute_parity (string (datanet_mbx.dia_pcw));
1140
1141 ima.chx = fnp_info.io_manager_chx;
1142 if paged
1143 then ima.ptp = fnp_info.ptp;
1144 else ima.ptp = null ();
1145 old_pcw = unspec (a_dia_pcw);
1146 call io_manager$connect_direct (ima);
1147 do i = 1 to 100000 while (unspec (a_dia_pcw) = old_pcw);
1148 end;
1149 if a_dia_pcw.error | old_pcw = unspec (a_dia_pcw)
1150 then do;
1151 call syserr (ANNOUNCE,
1152 "fnp_util (connect_to_dia): DIA mailbox PCW ^[error^;timeout^] for channel ^a, FNP ^a. PCW was ^w.",
1153 a_dia_pcw.error, fnp_info.io_chanid, fnp_info.fnp_tag, old_pcw);
1154 timeout = "1"b;
1155 end;
1156 else timeout = "0"b;
1157 return;
1158 end connect_to_dia;
1159 ^L
1160
1161 mask_dia:
1162 procedure;
1163 call io_manager$mask (fnp_info.io_manager_chx);
1164 end mask_dia;
1165
1166 internal_unwire:
1167 procedure;
1168
1169 declare px fixed bin;
1170
1171
1172
1173 if fnpp = null
1174 then return;
1175 if ^fnp_info.wired
1176 then return;
1177
1178 ioptp = fnp_info.ptp;
1179 if ioptp ^= null ()
1180 then do px = FIRST_BOOTLOAD_PAGEX to FIRST_BOOTLOAD_PAGEX + fnp_info.n_pages_wired;
1181 unspec (page_table.ptw (px)) = ""b;
1182 end;
1183
1184 astep = fnp_info.astep;
1185 call pc_abs$unwire_abs (astep, 0, fnp_info.n_pages_wired);
1186 call grab_aste$release_io (astep);
1187 fnp_info.wired = "0"b;
1188 return;
1189
1190 end internal_unwire;
1191
1192 release_t_and_d:
1193 procedure;
1194
1195 declare unlock_dump_seg bit (1) aligned;
1196
1197 call lock$wait (addr (fnp_dump_seg.lock), fdump_seg_event, code);
1198
1199 unlock_dump_seg = (code = 0);
1200 call syserr (0, "fnp_util: force detaching FNP ^a from process ^w.", fnp_info.fnp_id.fnp_tag,
1201 fnp_info.boot_process_id);
1202 call lock_fnp;
1203 fnp_info.boot_process_id = "000000000000"b3;
1204 fnp_info.boot_ev_chan = 0;
1205 fnp_info.t_and_d_in_progress = "0"b;
1206 fnp_info.t_and_d_lev_3_occurred, fnp_info.t_and_d_lev_7_occurred = "0"b;
1207 call fnp_multiplexer$unassign (fnp_no, code);
1208 if code ^= 0
1209 then call syserr$error_code (ANNOUNCE, code, "fnp_util: io channel unassignment failed for FNP ^a.",
1210 fnp_info.fnp_tag);
1211 call unlock_fnp;
1212 if unlock_dump_seg
1213 then call lock$unlock (addr (fnp_dump_seg.lock), fdump_seg_event);
1214 return;
1215 end release_t_and_d;
1216
1217
1218 lock_fnp:
1219 procedure;
1220
1221 declare code fixed bin (35);
1222
1223 if locked | config_locked
1224 then call syserr (CRASH, "fnp_util: lock_fnp called with lock locked.");
1225 locked, config_locked = "0"b;
1226
1227 call lock$lock_fast (addr (datanet_info.configuration_lock));
1228 config_locked = "1"b;
1229 if fnp_info.lcte_ptr = null ()
1230 then return;
1231 else if ^fnp_info.lcte_ptr -> lcte.initialized
1232 then return;
1233
1234
1235
1236 call fnp_multiplexer$fnp_lock (fnpp, code);
1237 if code = 0
1238 then do;
1239 locked = "1"b;
1240 call lock$unlock_fast (addr (datanet_info.configuration_lock));
1241
1242
1243 config_locked = "0"b;
1244 end;
1245 return;
1246
1247 unlock_fnp:
1248 entry;
1249
1250 if locked
1251 then call fnp_multiplexer$fnp_unlock (fnpp);
1252 locked = "0"b;
1253 if config_locked
1254 then call lock$unlock_fast (addr (datanet_info.configuration_lock));
1255 config_locked = "0"b;
1256 return;
1257 end lock_fnp;
1258
1259
1260 STOP_CHECK:
1261 procedure (Tracer);
1262 declare Tracer char (*);
1263
1264 if datanet_info.debug_stop
1265 then call syserr (CRASH, "fnp_util$^a: Debugging stop (type go to continue).", Tracer);
1266 return;
1267 end STOP_CHECK;
1268 ^L
1269
1270 get_page_table:
1271 procedure (code);
1272
1273 declare pagex fixed bin;
1274 declare px fixed bin;
1275 declare 1 seg_pt (0:255) aligned like l68_core_ptw based (ptp);
1276 declare ptp pointer;
1277 declare code fixed bin (35);
1278
1279 io_page_table_size = 256;
1280 call ioi_page_table$get (io_page_table_size * sys_info$page_size, fnp_info.ptx, code);
1281
1282 if code ^= 0
1283 then return;
1284 fnp_info.ptp, ioptp = ioi_page_table$ptx_to_ptp (fnp_info.ptx);
1285
1286 unspec (page_table) = ""b;
1287
1288
1289
1290
1291
1292 do px = 1 to 3;
1293 io_ptwp = addr (page_table.ptw (px));
1294 io_ptw.address = px;
1295 io_ptw.write = "1"b;
1296 io_ptw.valid = "1"b;
1297 end;
1298
1299
1300
1301 astep = get_ptrs_$given_segno (segno (addr (tty_buf$)));
1302 pagex = FIRST_TTY_BUF_PAGEX;
1303 ptp = addwordno (astep, sst$astsize);
1304 do px = 0 to bin (aste.csl, 9) - 1;
1305 io_ptwp = addr (page_table.ptw (pagex));
1306 io_ptw.address = seg_pt (px).frame;
1307 io_ptw.write = "1"b;
1308 io_ptw.valid = "1"b;
1309 pagex = pagex + 1;
1310 end;
1311 return;
1312
1313 fill_bootload_page_table:
1314 entry;
1315
1316
1317
1318 pagex = FIRST_BOOTLOAD_PAGEX;
1319 ptp = addwordno (astep, sst$astsize);
1320 auto_absadr = pagex * sys_info$page_size;
1321 ioptp = fnp_info.ptp;
1322
1323 do px = 0 to fnp_info.n_pages_wired - 1;
1324 io_ptwp = addr (page_table.ptw (pagex));
1325 io_ptw.address = seg_pt (px).frame;
1326 io_ptw.write = "0"b;
1327 io_ptw.valid = "1"b;
1328 pagex = pagex + 1;
1329 end;
1330
1331 if datanet_info.trace
1332 then do px = 0 to 255;
1333 if unspec (page_table.ptw (px)) ^= ""b
1334 then call syserr (ANNOUNCE, " ^4o ^w", px, unspec (page_table.ptw (px)));
1335 end;
1336
1337 return;
1338
1339 end get_page_table;
1340
1341
1342
1343
1344
1345 %page; %include aste;
1346 %page; %include config_prph_fnp_card;
1347 %page; %include dn355_mailbox;
1348 %page; %include lct;
1349 %page; %include dn355_data;
1350 %page; %include pcb;
1351 %page; %include fnp_dump_seg;
1352 %page; %include fnp_types;
1353 %page; %include io_manager_dcls;
1354 %page; %include io_page_tables;
1355 %page; %include io_chnl_util_dcls;
1356 %page; %include "ptw.l68";
1357 declare ptp pointer;
1358 %page; %include syserr_constants;
1359 %page; %include tty_buf;
1360 %include fnp_mpx_msg_;
1361
1362 ^L
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487 end fnp_util;