1
2
3
4
5
6
7
8
9
10
11
12
13 fnp_multiplexer:
14 proc;
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 %page;
61
62
63 dcl a_devx fixed bin;
64 dcl a_init_info_ptr ptr;
65 dcl a_fnpp ptr;
66 dcl a_subchan fixed bin;
67 dcl a_chainp ptr;
68 dcl a_mi_flag bit (1) aligned;
69 dcl a_code fixed bin (35);
70 dcl a_output_ptr ptr;
71 dcl a_order char (*);
72 dcl a_data_ptr ptr;
73 dcl a_mode_list_ptr ptr;
74 dcl a_modes char (*);
75
76
77
78
79 dcl code fixed bin (35);
80 dcl devx fixed bin;
81 dcl my_chan_name char (1);
82 dcl dno fixed bin;
83 dcl pcb_space fixed bin;
84 dcl space_needed fixed bin;
85 dcl output_ptr ptr;
86 dcl chanx fixed bin;
87 dcl output_length fixed bin;
88 dcl sourcep ptr;
89 dcl (i, j) fixed bin;
90 dcl lastp ptr;
91
92 dcl order char (32);
93 dcl data_ptr ptr;
94 dcl set_write_status bit (1);
95 dcl locked bit (1);
96 dcl old_mask fixed bin (71);
97 dcl mask_ptwp ptr;
98 dcl queue_locked bit (1);
99 dcl mylock bit (1);
100 dcl opcode fixed bin (8);
101 dcl alter_type fixed bin (8);
102 dcl check bit (1);
103 dcl mbx_data_len fixed bin;
104 dcl mbx_data bit (4 * 36) based (addr (mbx_data_long));
105 dcl mbx_data_long bit (8 * 36);
106 dcl alter_data bit (4 * 36) varying;
107 dcl dumpin bit (1);
108 dcl dumpout bit (1);
109 dcl get_meters bit (1);
110 dcl temp_saved_meters_ptr ptr;
111 dcl meter_ptr ptr;
112 dcl lcmp ptr;
113 dcl fnp_meters_ptr ptr;
114 dcl ret_meters_ptr ptr;
115 dcl local_line_type fixed bin;
116 dcl phone_no_len fixed bin;
117 dcl phone_digits (32) bit (6);
118 dcl next_digit fixed bin (6) unsigned;
119 dcl digit_pos fixed bin;
120 dcl opend bit (1);
121
122 dcl modex fixed bin;
123 dcl mode_name char (8);
124 dcl mode_on bit (1);
125 dcl mode_set (36) bit (1);
126 dcl hndlquit_set bit (1);
127 dcl base_len fixed bin;
128 dcl block_len fixed bin;
129 dcl chars_per_buf fixed bin;
130 dcl chars_per_sec fixed bin;
131
132 dcl wire_arg fixed bin (71);
133 dcl wire_ptr ptr;
134 dcl hsla_flag bit (1);
135 dcl old_flag bit (1);
136 dcl pcb_space_ptr ptr;
137 dcl prev_la_no fixed bin;
138 dcl la_no fixed bin;
139 dcl subchan fixed bin;
140 dcl his_fnp_no fixed bin;
141 dcl pcbx fixed bin;
142 dcl found bit (1);
143 dcl past bit (1);
144 dcl n_fnp_words fixed bin;
145 dcl ignore bit (1);
146 dcl name char (32);
147 dcl temp_addr fixed bin;
148 dcl fnp_dump_ptr ptr;
149 dcl dump_patch_space fixed bin;
150 dcl dump_patch_time fixed bin (71);
151
152
153 dcl 1 dump_fnp_data aligned,
154 2 abs_addr fixed bin (24),
155 2 fnp_addr fixed bin (18) unsigned unaligned,
156 2 fnp_len fixed bin (18) unsigned unaligned;
157
158 dcl 1 fnp_break_data aligned,
159 2 lineno fixed bin (17) unal,
160 2 fnp_addr fixed bin (18) unsigned unal,
161 2 action fixed bin (17) unal,
162 2 flags bit (18) unal;
163
164 dcl 1 echnego_break_table aligned,
165 2 words (0:15) unaligned,
166 3 bits bit (16) unaligned,
167 3 pad bit (2) unaligned;
168
169
170
171 dcl based_fb_word fixed bin based;
172 dcl based_bit1 bit (1) based;
173 dcl based_bit2 bit (2) based;
174 dcl based_bit18 bit (18) based;
175 dcl based_bit72 bit (72) based;
176 dcl based_bit108 bit (108) based;
177 dcl based_echo_table_bits bit (WIRED_ECHO_BREAK_SIZE + 1) based;
178 dcl fnp_data (n_fnp_words) bit (18) based;
179
180 dcl phone_chars char (32) varying based;
181
182 dcl 1 wr_stat aligned based,
183 2 ev_chan fixed bin (71),
184 2 output_pending bit (1);
185
186 dcl 1 rd_stat aligned based,
187 2 ev_chan fixed bin (71),
188 2 input_available bit (1);
189
190 dcl 1 dump_fnp_info based (data_ptr) aligned,
191 2 fnp_address fixed bin (24),
192 2 fnp_len fixed bin,
193 2 bufp ptr,
194 2 old_value_ptr ptr;
195
196 dcl 1 fnp_break_info aligned based (data_ptr),
197 2 chan_name char (6),
198 2 fnp_addr fixed bin,
199 2 action fixed bin,
200 2 flags bit (36);
201
202 dcl 1 echo_start_data aligned based (data_ptr),
203 2 ctr fixed bin (35),
204 2 screenleft fixed bin (35);
205
206
207
208 dcl (addr, addrel, bin, bit, clock, divide, hbound, length, null, ptr, rel, rtrim, size, stac, stacq, string, substr,
209 unspec) builtin;
210
211 dcl area condition;
212
213
214
215
216 dcl pxss$notify entry (fixed bin);
217 dcl dn355$send_wcd entry (ptr, ptr, fixed bin (8), fixed bin, bit (*));
218 dcl dn355$send_global_wcd entry (ptr, fixed bin (8), fixed bin, bit (*));
219 dcl dn355$hangup_fnp_lines entry (fixed bin);
220 dcl dn355$process_interrupt_queue entry (fixed bin);
221 dcl dn355$interrupt entry;
222 dcl fnp_util$fill_page_table entry (fixed bin, fixed bin (35));
223 dcl fnp_util$free_page_table entry (fixed bin, fixed bin (35));
224 dcl fnp_util$unwire entry (fixed bin, fixed bin (35));
225 dcl tty_lock$lock_lcte entry (ptr, fixed bin (35));
226 dcl tty_area_manager$allocate entry (fixed bin, ptr);
227 dcl tty_area_manager$free entry (fixed bin, ptr);
228 dcl lock$lock_fast entry (pointer);
229 dcl lock$unlock_fast entry (pointer);
230 dcl syserr entry options (variable);
231 dcl syserr$error_code entry options (variable);
232 dcl parse_tty_name_ entry (char (*), fixed bin, bit (1), fixed bin, fixed bin);
233 dcl parse_fnp_name_ entry (char (*), fixed bin);
234 dcl pxss$addevent entry (fixed bin);
235 dcl pxss$delevent entry (fixed bin);
236 dcl pxss$wait entry;
237
238
239
240 dcl (
241 error_table_$noalloc,
242 error_table_$undefined_order_request,
243 error_table_$bad_mode,
244 error_table_$bad_channel,
245 error_table_$buffer_big,
246 error_table_$invalid_write,
247 error_table_$dev_offset_out_of_bounds,
248 error_table_$seglock,
249 error_table_$mpx_down,
250 error_table_$timeout,
251 error_table_$unimplemented_version,
252 error_table_$no_channel_meters,
253 error_table_$resource_not_free,
254 error_table_$io_assigned,
255 error_table_$io_not_assigned,
256 error_table_$io_not_configured,
257 error_table_$io_not_available,
258 error_table_$invalid_state
259 ) ext static fixed bin (35);
260
261 dcl pds$processid ext static bit (36) aligned;
262 dcl pds$process_group_id ext static char (32) aligned;
263
264
265
266
267
268
269
270 dcl ANNOUNCE fixed bin internal static options (constant) init (0);
271 dcl CRASH_SYSTEM fixed bin internal static options (constant) init (1);
272
273 dcl DCW_LIST_SIZE fixed bin int static options (constant) init (16);
274 dcl DUMP_PATCH_LIMIT fixed bin (35) int static options (constant) init (10000000);
275
276
277
278
279
280
281
282
283
284
285
286
287
288 dcl good_modes (1) char (8) int static options (constant)
289 init ("hndlquit");
290
291 dcl async_only_modes (15) char (8) int static options (constant)
292
293 init ("crecho", "tabecho", "lfecho", "echoplex", "fulldpx", "replay", "polite", "breakall", "prefixnl",
294 "no_outp", "8bit", "oddp", "oflow", "iflow", "blk_xfer");
295
296 dcl IFLOW_INDEX fixed bin internal static options (constant) init (14);
297 dcl BLK_XFER_INDEX fixed bin internal static options (constant) init (15);
298
299 dcl full_dpx_modes (7) char (8) int static options (constant)
300
301 init ("crecho", "tabecho", "lfecho", "echoplex", "fulldpx", "iflow", "oflow");
302
303 dcl mode_alter_types (13) fixed bin (8) int static options (constant)
304
305 init (8,
306 14,
307 9,
308 20,
309 3,
310 23,
311 24,
312 27,
313 28,
314 33,
315 32,
316 31,
317 30);
318 ^L
319
320
321 %page;
322 %include tty_buf;
323 %page;
324 %include tty_buffer_block;
325 %page;
326 %include lct;
327 %page;
328 %include dn355_data;
329 %page;
330 %include pcb;
331 %page;
332 %include mailbox_ops;
333 %page;
334 %include tty_space_man_dcls;
335 %page;
336 %include line_types;
337 %page;
338 %include mux_init_info;
339 %page;
340 %include io_chnl_util_dcls;
341 %include mcs_modes_change_list;
342 %include flow_control_info;
343 %include channel_manager_dcls;
344 %include mcs_interrupt_info;
345 %include fnp_meters;
346 %include fnp_channel_meters;
347 %include get_comm_meters_info;
348 %include io_manager_dcls;
349 %include mcs_echo_neg_sys;
350 ^L
351 init_multiplexer:
352 entry (a_devx, a_init_info_ptr, a_fnpp, a_code);
353
354
355
356
357
358
359
360 devx = a_devx;
361 miip = a_init_info_ptr;
362 mii_chan_count = mux_init_info.no_channels;
363 pcb_space_ptr = null ();
364 infop = addr (dn355_data$);
365 ttybp = addr (tty_buf$);
366 lctp = tty_buf.lct_ptr;
367
368 lcntp = lct.lcnt_ptr;
369 if length (rtrim (lcnt.names (devx))) ^= 1
370 then go to bad_channel;
371 my_chan_name = rtrim (lcnt.names (devx));
372 call parse_fnp_name_ (my_chan_name, dno);
373 if dno < 0
374 then do;
375 bad_channel:
376 a_code = error_table_$bad_channel;
377 go to init_exit;
378 end;
379
380 fnpp = addr (datanet_info.per_datanet (dno));
381 call TRACE ("init_multiplexer");
382
383 if my_chan_name ^= fnp_info.fnp_tag
384 then go to bad_channel;
385 if ^tty_buf.fnp_config_flags (dno)
386 then go to bad_channel;
387
388 call lock$lock_fast (addr (datanet_info.configuration_lock));
389
390 fnp_info.lcte_ptr = addr (lct.lcte_array (devx));
391
392 if fnp_info.t_and_d_in_progress
393 then do;
394 code = error_table_$io_not_available;
395 go to init_abort;
396 end;
397
398 call assign_channel (code);
399 if code ^= 0
400 then go to init_abort;
401
402 call fnp_util$fill_page_table ((fnp_info.fnp_number), code);
403 if code ^= 0
404 then go to init_abort;
405
406 do i = 0 to 2;
407 fnp_info.hsla_idx (i) = -1;
408 fnp_info.lsla_idx (i) = -1;
409 end;
410 do i = 3 to 5;
411 fnp_info.lsla_idx (i) = -1;
412 end;
413
414 pcb_space = size (pcb) * mii_chan_count;
415 space_needed = pcb_space + 8 * DCW_LIST_SIZE;
416 call tty_space_man$get_space (space_needed, pcb_space_ptr);
417 if pcb_space_ptr = null
418 then do;
419 a_code = error_table_$noalloc;
420 go to init_abort;
421 end;
422 n_pcbs, fnp_info.no_of_channels = mii_chan_count;
423 pcb_space_ptr -> pcb_array (*).saved_meters_ptr = null ();
424
425 fnp_info.pcb_array_ptr = pcb_space_ptr;
426 fnp_info.dcw_list_array_ptr = addrel (pcb_space_ptr, pcb_space);
427 string (fnp_info.flags) = "0"b;
428 prev_la_no = -1;
429 old_flag = "1"b;
430
431
432
433
434
435
436 do pcbx = 1 to n_pcbs;
437 pcbp = addr (pcb_space_ptr -> pcb_array (pcbx));
438 unspec (pcb) = "0"b;
439 pcb.saved_meters_ptr = null ();
440 pcb.devx = mux_init_info.channels (pcbx).devx;
441 lctep = addr (lct.lcte_array (pcb.devx));
442 lcte.subchannel = pcbx;
443 name = mux_init_info.channels (pcbx).name;
444 call parse_tty_name_ (name, his_fnp_no, hsla_flag, la_no, subchan);
445 if his_fnp_no ^= dno
446 then do;
447 code = error_table_$bad_channel;
448 go to init_abort;
449 end;
450 if la_no = 7
451 then fnp_info.tandd_pcbx = pcbx;
452 else if (la_no ^= prev_la_no | hsla_flag ^= old_flag)
453
454 then do;
455 if hsla_flag
456 then fnp_info.hsla_idx (la_no) = pcbx;
457 else fnp_info.lsla_idx (la_no) = pcbx;
458 prev_la_no = la_no;
459 old_flag = hsla_flag;
460 end;
461
462 pcb.subchan = subchan;
463 pcb.is_hsla = hsla_flag;
464 pcb.la_no = bit (bin (la_no, 3), 3);
465 if hsla_flag
466 then pcb.slot_no = bit (bin (subchan, 6), 6);
467
468
469
470
471 on area
472 begin;
473 code = error_table_$noalloc;
474 go to init_abort;
475 end;
476
477 call tty_area_manager$allocate (size (fnp_channel_meters), temp_saved_meters_ptr);
478 pcb.saved_meters_ptr = temp_saved_meters_ptr;
479 end;
480
481 call lock$unlock_fast (addr (datanet_info.configuration_lock));
482
483 a_fnpp = fnpp;
484 a_code = 0;
485 init_exit:
486 return;
487
488 init_abort:
489 call TRACE_ERROR ("init_multiplexer", code);
490 call lock$unlock_fast (addr (datanet_info.configuration_lock));
491 if pcb_space_ptr ^= null
492 then do;
493 do pcbx = 1 to n_pcbs;
494 pcbp = addr (pcb_space_ptr -> pcb_array (pcbx));
495 if pcb.saved_meters_ptr ^= null ()
496 then call tty_area_manager$free (size (fnp_channel_meters), (pcb.saved_meters_ptr));
497 end;
498 call tty_space_man$free_space (space_needed, pcb_space_ptr);
499 end;
500 a_code = code;
501 return;
502 ^L
503 terminate_multiplexer:
504 entry (a_fnpp, a_code);
505
506
507
508 fnpp = a_fnpp;
509 ttybp = addr (tty_buf$);
510 infop = addr (dn355_data$);
511 locked = "0"b;
512 call TRACE ("terminate_multiplexer");
513 call lock;
514 if code ^= 0
515 then go to terminate_return;
516
517 if fnp_info.bootloading | fnp_info.wired | fnp_info.running
518
519 then code = error_table_$invalid_state;
520
521 else do;
522 do i = 1 to fnp_info.no_of_channels;
523 pcbp = addr (fnp_info.pcb_array_ptr -> pcb_array (i));
524 if pcb.write_first ^= 0
525 then call tty_space_man$free_chain ((pcb.devx), OUTPUT, ptr (ttybp, pcb.write_first));
526 if pcb.read_first ^= 0
527 then call tty_space_man$free_chain ((pcb.devx), INPUT, ptr (ttybp, pcb.read_first));
528 call tty_area_manager$free (size (fnp_channel_meters), (pcb.saved_meters_ptr));
529 if pcb.copied_meters_offset ^= 0
530 then do;
531 call tty_space_man$free_space (size (fnp_channel_meters), ptr (ttybp, pcb.copied_meters_offset));
532 pcb.copied_meters_offset = 0;
533 end;
534 end;
535
536 string (fnp_info.flags) = "0"b;
537 call tty_space_man$free_space (size (pcb) * fnp_info.no_of_channels + 8 * DCW_LIST_SIZE,
538 fnp_info.pcb_array_ptr);
539 fnp_info.pcb_array_ptr = null;
540 code = 0;
541 end;
542
543 if fnp_info.io_manager_assigned
544 then call unassign_channel (code);
545 call fnp_util$free_page_table ((fnp_info.fnp_number), (0));
546
547 call unlock;
548
549 terminate_return:
550 if code ^= 0
551 then call TRACE_ERROR ("terminate_multiplexer", code);
552 a_code = code;
553 return;
554 ^L
555 start:
556 entry (a_fnpp, a_code);
557
558
559
560 fnpp = a_fnpp;
561 infop = addr (dn355_data$);
562 call TRACE ("start");
563 chanx = 1;
564 call setup;
565 if code = 0
566 then do;
567 call dn355$send_global_wcd (fnpp, accept_calls, 18,
568 bit (bin (bin (rel (addr (tty_buf.free_space)), 18) + tty_buf.absorig, 18), 18));
569 call unlock;
570 end;
571 if code ^= 0
572 then call TRACE_ERROR ("start", code);
573 a_code = code;
574 return;
575
576
577 stop:
578 entry (a_fnpp, a_code);
579
580
581
582 fnpp = a_fnpp;
583 infop = addr (dn355_data$);
584 call TRACE ("stop");
585 chanx = 1;
586 call setup;
587 if code = 0
588 then do;
589 call dn355$send_global_wcd (fnpp, dont_accept_calls, 0, ""b);
590 call unlock;
591 end;
592 if code ^= 0
593 then call TRACE_ERROR ("stop", code);
594 a_code = code;
595 return;
596
597
598 shutdown:
599 entry (a_fnpp, a_code);
600
601
602
603 infop = addr (dn355_data$);
604 fnpp = a_fnpp;
605 if fnpp = null ()
606 then do;
607 if datanet_info.trace
608 then call syserr (ANNOUNCE, "fnp_multiplexer$shutdown: Called with null fnp_ptr");
609 go to shutdown_return;
610 end;
611 call TRACE ("shutdown");
612 infop = addr (dn355_data$);
613
614 if fnp_info.wired | fnp_info.bootloading
615 then do;
616 if datanet_info.trace
617 then call syserr (ANNOUNCE, "fnp_multiplexer$shutdown: Called with FNP wired.");
618 call fnp_util$unwire ((fnp_info.fnp_number), code);
619 if code ^= 0
620 then call syserr$error_code (ANNOUNCE, code, "fnp_multiplexer$shutdown: Failed to unwire fnp.");
621 end;
622
623 locked = "0"b;
624 if fnp_info.running
625 then do;
626 call lock;
627 call dn355$hangup_fnp_lines ((fnp_info.fnp_number));
628 fnp_info.running = "0"b;
629 call unlock;
630 end;
631
632
633 shutdown_return:
634 a_code = 0;
635 return;
636 ^L
637
638 read:
639 entry (a_fnpp, a_subchan, a_chainp, a_mi_flag, a_code);
640
641
642
643 a_chainp = null;
644 a_mi_flag = "0"b;
645 a_code = 0;
646 return;
647
648
649 write:
650 entry (a_fnpp, a_subchan, a_output_ptr, a_code);
651
652 fnpp = a_fnpp;
653 chanx = a_subchan;
654 output_ptr = a_output_ptr;
655
656 call setup;
657 if code ^= 0
658 then do;
659 a_code = code;
660 return;
661 end;
662
663
664
665 blockp = output_ptr;
666 output_length = buffer.tally;
667
668 do while (buffer.next ^= 0);
669 blockp = ptr (ttybp, buffer.next);
670 output_length = output_length + buffer.tally;
671 end;
672
673 if pcb.write_last ^= 0
674 then do;
675 lastp = ptr (ttybp, pcb.write_last);
676 lastp -> buffer.next = bin (rel (output_ptr));
677 end;
678
679 else pcb.write_first = bin (rel (output_ptr));
680
681 pcb.write_last = bin (rel (blockp));
682 pcb.write_cnt = pcb.write_cnt + output_length;
683
684 if pcb.send_output
685 then call dn355$send_wcd (fnpp, pcbp, accept_direct_output, 0, ""b);
686
687 code = 0;
688 write_exit:
689 call unlock;
690 if code = 0
691 then a_output_ptr = null ();
692 a_code = code;
693 return;
694 ^L
695 control:
696 entry (a_fnpp, a_subchan, a_order, a_data_ptr, a_code);
697
698 fnpp = a_fnpp;
699 chanx = a_subchan;
700 order = a_order;
701 data_ptr = a_data_ptr;
702
703 dumpin, dumpout, set_write_status, get_meters = "0"b;
704
705 opcode, alter_type = -1;
706 check = "0"b;
707
708 if order = "read_status"
709 then do;
710 data_ptr -> rd_stat.input_available = "0"b;
711 a_code = 0;
712 return;
713 end;
714
715 else if order = "hangup"
716 then do;
717 mbx_data_len = 0;
718 mbx_data = ""b;
719 opcode = disconnect_this_line;
720 end;
721
722 else if order = "wru"
723 then do;
724 alter_type = Wru;
725 alter_data = ""b;
726 end;
727
728 else if order = "interrupt"
729 then do;
730 alter_type = Break;
731 alter_data = ""b;
732 end;
733
734 else if order = "start_xmit_hd" | order = "stop_xmit_hd"
735 then do;
736 alter_type = Xmit_hold;
737 alter_data = "00000000"b || (order = "start_xmit_hd");
738 end;
739
740 else if order = "set_input_message_size"
741 then do;
742 mbx_data = bit (bin (data_ptr -> based_fb_word, 18), 18);
743 opcode = sync_msg_size;
744 end;
745
746 else if order = "line_control"
747 then do;
748 mbx_data_len = 72;
749 mbx_data = data_ptr -> based_bit72;
750 opcode = line_control;
751 end;
752
753 else if order = "set_framing_chars"
754 then do;
755 mbx_data_len = 18;
756 mbx_data = data_ptr -> based_bit18;
757 opcode = set_framing_chars;
758 end;
759
760 else if order = "set_delay"
761 then do;
762 mbx_data_len = 108;
763 mbx_data = data_ptr -> based_bit108;
764 opcode = set_delay_table;
765 end;
766
767 else if order = "abort"
768 then do;
769 dumpin = substr (data_ptr -> based_bit2, 2, 1);
770
771 dumpout = substr (data_ptr -> based_bit2, 1, 1);
772 end;
773
774 else if order = "set_line_type"
775 then do;
776 mbx_data_len = 18;
777 local_line_type = data_ptr -> based_fb_word;
778 if local_line_type <= 0 | local_line_type > max_line_type
779 then go to order_error;
780 check = "1"b;
781 opcode = set_line_type;
782 end;
783
784 else if order = "dial_out"
785 then do;
786 digit_pos = 0;
787 do i = 1 to length (data_ptr -> phone_chars);
788 next_digit = index ("0123456789XXX!", substr (data_ptr -> phone_chars, i, 1)) - 1;
789
790
791 if next_digit >= 0
792 then if next_digit < 10 | next_digit = 13
793 then do;
794 digit_pos = digit_pos + 1;
795 phone_digits (digit_pos) = bit (next_digit, 6);
796 end;
797 end;
798
799 phone_no_len = 6 * digit_pos;
800 opcode = dial;
801 check = "1"b;
802 end;
803
804 else if order = "listen"
805 then do;
806 alter_type = Listen;
807 alter_data = "000000001"b;
808 end;
809
810 else if order = "write_status"
811 then set_write_status = "1"b;
812
813 else if order = "enter_receive"
814 then do;
815 mbx_data_len = 0;
816 mbx_data = ""b;
817 opcode = enter_receive;
818 end;
819 else if order = "start_negotiated_echo"
820 then do;
821 mbx_data_len = 36;
822 mbx_data =
823 bit (fixed (data_ptr -> echo_start_data.ctr, 18), 18)
824 || bit (fixed (data_ptr -> echo_start_data.screenleft, 18), 18);
825 opcode = start_negotiated_echo;
826 end;
827 else if order = "set_echnego_break_table"
828 then do;
829 mbx_data_len = length (unspec (echnego_break_table));
830 unspec (echnego_break_table) = ""b;
831 do i = 0 to hbound (echnego_break_table.words, 1);
832 echnego_break_table.bits (i) = substr (data_ptr -> based_echo_table_bits, 1 + 16 * i, 16);
833 end;
834 mbx_data_long = unspec (echnego_break_table);
835 opcode = set_echnego_break_table;
836 end;
837 else if order = "init_echo_negotiation"
838 then do;
839 mbx_data_len = 0;
840 mbx_data = ""b;
841 opcode = init_echo_negotiation;
842 end;
843 else if order = "stop_negotiated_echo"
844 then do;
845 mbx_data_len = 0;
846 mbx_data = ""b;
847 opcode = stop_negotiated_echo;
848 end;
849 else if order = "input_flow_control_chars"
850 then do;
851 mbx_data_len = 36;
852 if data_ptr -> input_flow_control_info.resume_seq.count = 0
853
854 then mbx_data = ""b;
855 else do;
856 mbx_data =
857 unspec (substr (data_ptr -> input_flow_control_info.suspend_seq.chars, 1, 1))
858 || unspec (substr (data_ptr -> input_flow_control_info.resume_seq.chars, 1, 1))
859 || data_ptr -> input_flow_control_info.timeout;
860 if data_ptr -> input_flow_control_info.suspend_seq.count = 0
861 then substr (mbx_data, 1, 9) = "0"b;
862 end;
863 opcode = input_fc_chars;
864 end;
865 else if order = "output_flow_control_chars"
866 then do;
867 mbx_data_len = 36;
868 if data_ptr -> output_flow_control_info.suspend_or_etb_seq.count = 0
869
870 then mbx_data = "0"b;
871 else mbx_data =
872 unspec (substr (data_ptr -> output_flow_control_info.suspend_or_etb_seq.chars, 1, 1))
873 || unspec (substr (data_ptr -> output_flow_control_info.resume_or_ack_seq.chars, 1, 1))
874 || data_ptr -> output_flow_control_info.block_acknowledge;
875 opcode = output_fc_chars;
876 end;
877
878 else if order = "copy_meters"
879 then do;
880 opcode = report_meters;
881 check = "1"b;
882 end;
883
884 else if order = "get_meters"
885 then do;
886 ret_meters_ptr = data_ptr -> get_comm_meters_info.parent_ptr;
887 if ret_meters_ptr = null ()
888 then return;
889 else if ret_meters_ptr -> fnp_chan_meter_struc.version ^= FNP_CHANNEL_METERS_VERSION_1
890 then do;
891 a_code = error_table_$unimplemented_version;
892 return;
893 end;
894
895 else get_meters = "1"b;
896 end;
897
898 else if order = "tandd_attach"
899 then do;
900 call setup;
901 if code ^= 0
902 then do;
903 a_code = code;
904 return;
905 end;
906
907 if pcb.listen | pcb.dialed
908 then do;
909 call unlock;
910 a_code = error_table_$resource_not_free;
911 return;
912 end;
913
914 pcb.dialed = "1"b;
915 pcb.tandd_attached = "1"b;
916 unspec (dialup_info) = ""b;
917 dialup_info.baud_rate = 1200;
918 dialup_info.line_type = LINE_ASCII;
919 dialup_info.max_buf_size = 16;
920 call channel_manager$interrupt ((pcb.devx), DIALUP, unspec (dialup_info));
921 call unlock;
922 a_code = 0;
923 return;
924 end;
925
926 else do;
927 order_error:
928 a_code = error_table_$undefined_order_request;
929 return;
930 end;
931
932 code = 0;
933 call setup;
934 if code ^= 0
935 then do;
936 a_code = code;
937 return;
938 end;
939
940 if opcode = disconnect_this_line
941 then do;
942 pcb.listen, pcb.tandd_attached = "0"b;
943 end;
944
945 if opcode = start_negotiated_echo & (pcb.write_first ^= 0
946
947 | pcb.output_mbx_pending)
948 then do;
949
950 call unlock;
951 a_code = error_table_$invalid_write;
952 return;
953 end;
954
955
956 if alter_type ^= -1
957 then do;
958 if alter_type = Listen
959 then do;
960 alter_data = alter_data || fnp_buf_size ();
961 pcb.listen = "1"b;
962 end;
963
964 mbx_data_len = length (alter_data) + 9;
965 mbx_data = bit (bin (alter_type, 9), 9) || alter_data;
966 opcode = alter_parameters;
967 end;
968
969 if opcode ^= -1
970 then do;
971 if check
972 then do;
973 if opcode = set_line_type
974 then if pcb.listen
975 then do;
976 call unlock;
977 go to order_error;
978 end;
979
980 else do;
981 mbx_data = bit (bin (local_line_type, 18), 18);
982 do i = 1 to n_sync_line_types while (local_line_type ^= sync_line_type (i));
983 end;
984
985 pcb.sync_line = (i <= n_sync_line_types);
986 end;
987
988 else if opcode = dial
989 then do;
990 mbx_data_len = 36;
991 alter_data = bit (bin (Set_buffer_size, 9), 9) || "000000001"b;
992 mbx_data = alter_data || fnp_buf_size ();
993 call dn355$send_wcd (fnpp, pcbp, alter_parameters, mbx_data_len, mbx_data);
994
995 mbx_data_len = phone_no_len;
996 mbx_data_long = string (phone_digits);
997 end;
998 else if opcode = report_meters
999 then do;
1000 call tty_space_man$get_space (size (fnp_channel_meters), meter_ptr);
1001
1002 if meter_ptr = null ()
1003 then do;
1004 call unlock;
1005 a_code = error_table_$noalloc;
1006 return;
1007 end;
1008
1009 pcb.copied_meters_offset = bin (rel (meter_ptr), 18);
1010 mbx_data = bit (bin (tty_buf.absorig + pcb.copied_meters_offset, 18), 18);
1011 mbx_data_len = 18;
1012 end;
1013 end;
1014
1015 call dn355$send_wcd (fnpp, pcbp, opcode, mbx_data_len, mbx_data_long);
1016 end;
1017
1018 else do;
1019 if dumpin
1020 then call dn355$send_wcd (fnpp, pcbp, alter_parameters, 9, bit (bin (Dumpinput, 9), 9));
1021
1022 if dumpout
1023 then do;
1024 if pcb.write_first ^= 0
1025 then do;
1026 call tty_space_man$free_chain ((pcb.devx), OUTPUT, ptr (ttybp, pcb.write_first));
1027 pcb.write_first, pcb.write_last, pcb.write_cnt = 0;
1028 end;
1029
1030
1031 call dn355$send_wcd (fnpp, pcbp, alter_parameters, 9, bit (bin (Dumpoutput, 9), 9));
1032
1033 if pcb.end_frame
1034 then do;
1035 pcb.end_frame = "0"b;
1036 if pcb.send_output
1037 then call channel_manager$interrupt ((pcb.devx), SEND_OUTPUT, ""b);
1038 end;
1039 end;
1040
1041 if set_write_status
1042 then opend = (pcb.write_first ^= 0);
1043
1044 if get_meters
1045 then do;
1046 call get_fnp_meters ("0"b);
1047 call unlock;
1048
1049 if code = 0
1050 then ret_meters_ptr -> fnp_chan_meter_struc.synchronous = pcb.sync_line;
1051 if fnp_meters_ptr ^= null ()
1052 then do;
1053 if unspec (fnp_meters_ptr -> fnp_channel_meters) = "0"b
1054 then code = error_table_$no_channel_meters;
1055 else do;
1056 ret_meters_ptr -> fnp_chan_meter_struc.current_meters =
1057 fnp_meters_ptr -> fnp_channel_meters;
1058 ret_meters_ptr -> fnp_chan_meter_struc.saved_meters =
1059 pcb.saved_meters_ptr -> fnp_channel_meters;
1060 end;
1061
1062 call tty_space_man$free_space (size (fnp_channel_meters), fnp_meters_ptr);
1063 end;
1064 end;
1065 end;
1066
1067 call unlock;
1068 if set_write_status
1069 then data_ptr -> wr_stat.output_pending = opend;
1070 a_code = code;
1071
1072 return;
1073 ^L
1074 check_modes:
1075 entry (a_fnpp, a_subchan, a_mode_list_ptr, a_code);
1076
1077
1078
1079 fnpp = a_fnpp;
1080 chanx = a_subchan;
1081 mclp = a_mode_list_ptr;
1082 if mcl.version ^= mcl_version_2
1083 then do;
1084 a_code = error_table_$unimplemented_version;
1085 return;
1086 end;
1087
1088 call setup;
1089 if code ^= 0
1090 then do;
1091 a_code = code;
1092 return;
1093 end;
1094
1095 do modex = 1 to mcl.n_entries;
1096 mclep = addr (mcl.entries (modex));
1097 mode_name = substr (mcle.mode_name, 1, 8);
1098 mode_on = mcle.mode_switch;
1099
1100 do i = 1 to hbound (good_modes, 1) while (mode_name ^= good_modes (i));
1101 end;
1102
1103 if i <= hbound (good_modes, 1)
1104
1105 then mcle.mpx_mode = "1"b;
1106 else do;
1107 do i = 1 to hbound (async_only_modes, 1) while (mode_name ^= async_only_modes (i));
1108 end;
1109
1110 if i > hbound (async_only_modes, 1)
1111 then mcle.mpx_mode = "0"b;
1112 else do;
1113 mcle.mpx_mode = ^pcb.sync_line;
1114
1115 do i = 1 to hbound (full_dpx_modes, 1) while (mode_name ^= full_dpx_modes (i));
1116 end;
1117
1118 if (mode_name = "no_outp" | mode_name = "8bit" | mode_name = "oddp") & mode_on
1119 then if ^pcb.is_hsla
1120 then go to bad_mode;
1121
1122 if i <= hbound (full_dpx_modes, 1)
1123 then if mode_on
1124 then if pcb.line_type ^= LINE_ASCII & pcb.line_type ^= LINE_ASYNC1
1125 & pcb.line_type ^= LINE_ASYNC2 & pcb.line_type ^= LINE_ASYNC3
1126 then do;
1127 bad_mode:
1128 if mcle.force
1129 then mcle.mpx_mode = "0"b;
1130 else do;
1131 code = error_table_$bad_mode;
1132 mcle.error = "1"b;
1133 end;
1134 end;
1135
1136 end;
1137 end;
1138 end;
1139
1140 call unlock;
1141 a_code = code;
1142 return;
1143 ^L
1144 set_modes:
1145 entry (a_fnpp, a_subchan, a_mode_list_ptr, a_code);
1146
1147
1148
1149 fnpp = a_fnpp;
1150 chanx = a_subchan;
1151 mclp = a_mode_list_ptr;
1152 if mcl.version ^= mcl_version_2
1153 then do;
1154 a_code = error_table_$unimplemented_version;
1155 return;
1156 end;
1157
1158 call setup;
1159 if code ^= 0
1160 then do;
1161 a_code = code;
1162 return;
1163 end;
1164
1165 hndlquit_set = "0"b;
1166 string (mode_set) = "0"b;
1167
1168 do modex = 1 to mcl.n_entries;
1169 mclep = addr (mcl.entries (modex));
1170 if mcle.mpx_mode
1171 then call process_mode (mcle.mode_name, mcle.mode_switch);
1172 end;
1173
1174 if mcl.init
1175 then do;
1176 if ^hndlquit_set
1177 then call process_mode ("hndlquit", "0"b);
1178
1179 do modex = 1 to hbound (async_only_modes, 1);
1180 if ^mode_set (modex)
1181 then call process_mode (async_only_modes (modex), "0"b);
1182 end;
1183 end;
1184
1185 call unlock;
1186 a_code = code;
1187 return;
1188
1189
1190
1191 get_modes:
1192 entry (a_fnpp, a_subchan, a_modes, a_code);
1193
1194
1195
1196 a_modes = "";
1197 a_code = 0;
1198 return;
1199 ^L
1200 priv_control:
1201 entry (a_fnpp, a_order, a_data_ptr, a_code);
1202
1203
1204
1205 fnpp = a_fnpp;
1206 order = a_order;
1207 data_ptr = a_data_ptr;
1208
1209 if order = "dump_fnp"
1210 then do;
1211 call setup_fnp;
1212 if code ^= 0
1213 then do;
1214 a_code = code;
1215 return;
1216 end;
1217
1218 locked = "0"b;
1219 call send_global (dump_mem);
1220 if code ^= 0
1221 then go to end_dump_mem;
1222
1223
1224
1225 n_fnp_words = dump_fnp_info.fnp_len;
1226 dump_fnp_info.bufp -> fnp_data = fnp_dump_ptr -> fnp_data;
1227
1228 end_dump_mem:
1229 if code ^= error_table_$timeout
1230 then call tty_space_man$free_space (dump_patch_space, fnp_dump_ptr);
1231
1232 ignore = stacq (fnp_info.dump_patch_lock, "0"b, pds$processid);
1233 end;
1234
1235 else if order = "get_meters"
1236 then do;
1237 fnp_meterp = data_ptr -> get_comm_meters_info.subchan_ptr;
1238 if fnp_meterp ^= null
1239 then do;
1240 if fnp_meters.version ^= FNP_METERS_VERSION_2
1241 then code = error_table_$unimplemented_version;
1242 else do;
1243 ttybp = addr (tty_buf$);
1244 call lock;
1245 if code ^= 0
1246 then do;
1247 a_code = code;
1248 return;
1249 end;
1250
1251 call get_fnp_meters ("1"b);
1252
1253 if code = 0
1254 then do;
1255 fnp_meters.n_channels = fnp_info.no_of_channels;
1256 fnp_meters.output_mbx_in_use_cum = fnp_info.cumulative_mbx_in_use;
1257 fnp_meters.output_mbx_updates = fnp_info.mbx_in_use_updated;
1258 fnp_meters.output_mbx_unavailable = fnp_info.mbx_unavailable;
1259 fnp_meters.max_output_mbx_in_use = fnp_info.max_mbx_in_use;
1260 fnp_meters.queue_entries_made = fnp_info.q_entries_made;
1261 fnp_meters.input_rejects = fnp_info.input_reject_count;
1262 fnp_meters.processed_from_q = fnp_info.processed_from_q;
1263 fnp_meters.fnp_channel_locked = fnp_info.fnp_channel_locked;
1264 fnp_meters.input_data_transactions = fnp_info.input_data_transactions;
1265 fnp_meters.output_data_transactions = fnp_info.output_data_transactions;
1266 fnp_meters.input_control_transactions = fnp_info.input_control_transactions;
1267 fnp_meters.output_control_transactions = fnp_info.output_control_transactions;
1268 fnp_meters.fnp_space_restricted_output = fnp_info.fnp_space_restricted_output;
1269 fnp_meters.fnp_mem_size = fnp_info.fnp_mem_size;
1270 begin;
1271 declare iom fixed bin (3);
1272 declare chan fixed bin (7);
1273 call io_chnl_util$name_to_iom (fnp_info.io_chanid, iom, chan, (0));
1274 fnp_meters.iom_number = iom;
1275 fnp_meters.iom_chan_no = chan;
1276 end;
1277
1278 end;
1279
1280 call unlock;
1281
1282 if fnp_meters_ptr ^= null ()
1283 then do;
1284 data_ptr -> get_comm_meters_info.subchan_ptr -> fnp_meters.from_fnp =
1285 fnp_meters_ptr -> fnp_global_meters;
1286
1287 call tty_space_man$free_space (size (fnp_global_meters), fnp_meters_ptr);
1288 end;
1289
1290 lctep = fnp_info.lcte_ptr;
1291 lcmp = data_ptr -> get_comm_meters_info.logical_chan_ptr;
1292
1293 if lcmp ^= null ()
1294 then do;
1295 lcmp -> logical_chan_meters.current_meters = lcte.meters;
1296 unspec (lcmp -> logical_chan_meters.saved_meters) = "0"b;
1297
1298 end;
1299 end;
1300 end;
1301 end;
1302
1303 else code = error_table_$undefined_order_request;
1304
1305 a_code = code;
1306 return;
1307 ^L
1308 hpriv_control:
1309 entry (a_fnpp, a_order, a_data_ptr, a_code);
1310
1311
1312
1313 fnpp = a_fnpp;
1314 order = a_order;
1315 data_ptr = a_data_ptr;
1316 locked = "0"b;
1317 code = 0;
1318
1319 if order = "patch_fnp"
1320 then do;
1321 call setup_fnp;
1322 if code ^= 0
1323 then do;
1324 a_code = code;
1325 return;
1326 end;
1327 n_fnp_words = dump_fnp_data.fnp_len;
1328 sourcep = dump_fnp_info.bufp;
1329
1330 fnp_dump_ptr -> fnp_data = sourcep -> fnp_data;
1331 call syserr (ANNOUNCE, "fnp_multiplexer: patching FNP ^a for ^a:", fnp_info.fnp_tag, pds$process_group_id);
1332
1333
1334 temp_addr = dump_fnp_data.fnp_addr;
1335 do i = 1 to dump_fnp_data.fnp_len;
1336 call syserr (ANNOUNCE, "^6w from ^6.3b to ^6.3b", temp_addr,
1337 dump_fnp_info.old_value_ptr -> fnp_data (i), dump_fnp_info.bufp -> fnp_data (i));
1338 temp_addr = temp_addr + 1;
1339 end;
1340
1341 call send_global (patch_mem);
1342 if code ^= error_table_$timeout
1343 then call tty_space_man$free_space (dump_patch_space, fnp_dump_ptr);
1344
1345 ignore = stacq (fnp_info.dump_patch_lock, "0"b, pds$processid);
1346 end;
1347
1348 else if order = "fnp_break"
1349 then do;
1350 call setup_fnp;
1351 if code ^= 0
1352 then do;
1353 a_code = code;
1354 return;
1355 end;
1356 fnp_break_data.action = fnp_break_info.action;
1357
1358 fnp_break_data.fnp_addr = fnp_break_info.fnp_addr;
1359 fnp_break_data.flags = substr (fnp_break_info.flags, 1, 18);
1360 name = fnp_break_info.chan_name;
1361 if name = ""
1362 then fnp_break_data.lineno = -1;
1363 else do;
1364 call name_to_pcb (name);
1365 if code ^= 0
1366 then do;
1367 a_code = code;
1368 return;
1369 end;
1370 fnp_break_data.lineno = bin (string (pcb.line_number));
1371 end;
1372
1373 mbx_data = addr (fnp_break_data) -> based_bit72;
1374 if ^locked
1375 then call lock;
1376 if code = 0
1377 then do;
1378 call dn355$send_global_wcd (fnpp, fnp_break, 72, mbx_data);
1379 call unlock;
1380 end;
1381 end;
1382
1383 else if order = "enable_breakall_mode"
1384 then ;
1385
1386 else if order = "disable_breakall_mode"
1387 then ;
1388
1389 else code = error_table_$undefined_order_request;
1390
1391 hpriv_exit:
1392 a_code = code;
1393 return;
1394 ^L
1395 fnp_lock:
1396 entry (a_fnpp, a_code);
1397
1398 fnpp = a_fnpp;
1399 call lock;
1400 a_code = code;
1401 return;
1402
1403 fnp_unlock:
1404 entry (a_fnpp);
1405
1406 fnpp = a_fnpp;
1407 mylock = "0"b;
1408 locked = "1"b;
1409 call unlock;
1410 return;
1411 ^L
1412 setup:
1413 proc;
1414
1415
1416
1417
1418 code = 0;
1419 ttybp = addr (tty_buf$);
1420 infop = addr (dn355_data$);
1421 locked, queue_locked = "0"b;
1422 call lock;
1423 if code ^= 0
1424 then return;
1425
1426 if fnp_info.running
1427 then pcbp = addr (fnp_info.pcb_array_ptr -> pcb_array (chanx));
1428 else do;
1429 call unlock;
1430 code = error_table_$mpx_down;
1431 return;
1432 end;
1433
1434 if pcb.copied_meters_ready
1435 then if ^lcte.locked_for_interrupt
1436 then call save_copied_meters;
1437
1438 return;
1439 end setup;
1440
1441
1442
1443 setup_fnp:
1444 proc;
1445
1446 dcl (fnp_address, fnp_len) fixed bin (18);
1447
1448
1449
1450 if fnpp = null ()
1451 then go to setup_fnp_down;
1452 code = 0;
1453 if fnp_info.mbx_pt = null ()
1454 | ^fnp_info.running
1455 then do;
1456 setup_fnp_down:
1457 code = error_table_$mpx_down;
1458 return;
1459 end;
1460
1461 ttybp = addr (tty_buf$);
1462 infop = addr (dn355_data$);
1463
1464 if order = "fnp_break"
1465 then return;
1466 if fnp_info.dump_patch_disabled
1467 then do;
1468 code = error_table_$timeout;
1469 return;
1470 end;
1471
1472 fnp_address = dump_fnp_info.fnp_address;
1473 fnp_len = dump_fnp_info.fnp_len;
1474 if order = "dump_fnp"
1475 then do;
1476 if fnp_len <= 0 | fnp_len > 64
1477 then do;
1478 bad_fnp_len:
1479 code = error_table_$buffer_big;
1480 return;
1481 end;
1482 end;
1483 else if order = "patch_fnp"
1484 then if fnp_len <= 0 | fnp_len > 32
1485 then go to bad_fnp_len;
1486
1487 if (fnp_address < 0) | ((fnp_address + fnp_len) > fnp_info.fnp_mem_size)
1488 then do;
1489 code = error_table_$dev_offset_out_of_bounds;
1490 return;
1491 end;
1492
1493 if ^stac (addr (fnp_info.dump_patch_lock), pds$processid)
1494
1495 then do;
1496 code = error_table_$seglock;
1497 return;
1498 end;
1499
1500 dump_patch_space = divide (fnp_len + 1, 2, 17, 0);
1501 call tty_space_man$get_space (dump_patch_space, fnp_dump_ptr);
1502 if fnp_dump_ptr = null
1503 then do;
1504 code = error_table_$noalloc;
1505 ignore = stacq (fnp_info.dump_patch_lock, "0"b, pds$processid);
1506 return;
1507 end;
1508
1509 dump_patch_time = clock ();
1510 fnp_info.dump_patch_in_progress = "1"b;
1511 dump_fnp_data.abs_addr = bin (rel (fnp_dump_ptr)) + tty_buf.absorig;
1512
1513 dump_fnp_data.fnp_addr = fnp_address;
1514 dump_fnp_data.fnp_len = fnp_len;
1515 return;
1516
1517 end setup_fnp;
1518 ^L
1519 save_copied_meters:
1520 proc;
1521
1522
1523
1524 dcl copied_meters_ptr ptr;
1525
1526 if pcb.copied_meters_offset ^= 0
1527 then do;
1528 copied_meters_ptr = ptr (ttybp, pcb.copied_meters_offset);
1529
1530
1531
1532 if pcb.sync_line
1533 then copied_meters_ptr -> fnp_sync_meters.pad (*) = 0;
1534 else copied_meters_ptr -> fnp_async_meters.pad (*) = 0;
1535
1536 pcb.saved_meters_ptr -> fnp_channel_meters = copied_meters_ptr -> fnp_channel_meters;
1537 call tty_space_man$free_space (size (fnp_channel_meters), copied_meters_ptr);
1538
1539 pcb.copied_meters_offset = 0;
1540 pcb.copied_meters_ready = "0"b;
1541 end;
1542
1543 return;
1544 end save_copied_meters;
1545 ^L
1546 process_mode:
1547 proc (mode_name, mode_on);
1548
1549 dcl mode_name char (*);
1550 dcl mode_on bit (1);
1551 dcl mode_name_index fixed bin;
1552
1553 alter_data = "00000000"b || mode_on;
1554
1555 if mode_name = "hndlquit"
1556 then do;
1557 alter_type = Hndlquit;
1558 pcb.hndlquit = mode_on;
1559 hndlquit_set = "1"b;
1560 end;
1561
1562 else if ^pcb.sync_line
1563 then do;
1564 if mode_name = "blk_xfer" | mode_name = "iflow"
1565
1566 then do;
1567 if mode_name = "blk_xfer"
1568 then do;
1569 mode_name_index = BLK_XFER_INDEX;
1570 alter_type = Block_xfer;
1571 end;
1572 else do;
1573 mode_name_index = IFLOW_INDEX;
1574 alter_type = Input_flow_control;
1575 end;
1576
1577 if mode_on
1578 then do;
1579 chars_per_sec = divide (pcb.baud_rate, 10, 17, 0);
1580 base_len, block_len = divide (chars_per_sec, buf_per_second, 17, 0);
1581
1582 end;
1583 else do;
1584 base_len = 56;
1585 block_len = 0;
1586 end;
1587
1588 alter_data = alter_data || bit (bin (base_len, 18), 18) || bit (bin (block_len, 18), 18);
1589 mode_set (mode_name_index) = "1"b;
1590 end;
1591
1592 else do;
1593 do i = 1 to hbound (mode_alter_types, 1) while (mode_name ^= async_only_modes (i));
1594 end; note
1595
1596 if i > hbound (mode_alter_types, 1)
1597 then code = error_table_$bad_mode;
1598
1599 else do;
1600 alter_type = mode_alter_types (i);
1601 mode_set (i) = "1"b;
1602 end;
1603 end;
1604 end;
1605
1606 if code = 0
1607 then do;
1608 mbx_data = bit (bin (alter_type, 9), 9) || alter_data;
1609 call dn355$send_wcd (fnpp, pcbp, alter_parameters, length (alter_data) + 9, mbx_data);
1610 end;
1611 return;
1612 end;
1613 ^L
1614 send_global:
1615 proc (opcode);
1616
1617
1618
1619 dcl opcode fixed bin (8);
1620
1621 call pxss$addevent (FNP_DUMP_PATCH_EVENT);
1622 mbx_data = addr (dump_fnp_data) -> based_bit72;
1623 call lock;
1624 if code ^= 0
1625 then return;
1626
1627 call dn355$send_global_wcd (fnpp, opcode, 72, mbx_data);
1628 call unlock;
1629
1630 call pxss$wait;
1631
1632 do while (fnp_info.dump_patch_in_progress);
1633 if ^fnp_info.running
1634 then do;
1635 code = error_table_$mpx_down;
1636 fnp_info.dump_patch_in_progress = "0"b;
1637 end;
1638
1639 else if clock () - dump_patch_time > DUMP_PATCH_LIMIT
1640
1641 then do;
1642 code = error_table_$timeout;
1643 fnp_info.dump_patch_disabled = "1"b;
1644 fnp_info.dump_patch_in_progress = "0"b;
1645 call syserr (ANNOUNCE, "fnp_multiplexer: ^[dump^;patch^]_fnp order to FNP ^a timed out.",
1646 opcode = dump_mem, fnp_info.fnp_tag);
1647 end;
1648
1649 else do;
1650 call pxss$addevent (FNP_DUMP_PATCH_EVENT);
1651 if fnp_info.dump_patch_in_progress
1652 then call pxss$wait;
1653 else call pxss$delevent (FNP_DUMP_PATCH_EVENT);
1654
1655 end;
1656
1657 end;
1658
1659 return;
1660
1661 end send_global;
1662 ^L
1663 get_fnp_meters:
1664 proc (global);
1665
1666
1667
1668 dcl global bit (1) parameter;
1669 dcl space_size fixed bin;
1670 dcl fnp_meter_wait_start fixed bin (71);
1671
1672 if fnp_info.dump_patch_disabled
1673 then do;
1674 code = error_table_$timeout;
1675 fnp_meters_ptr = null ();
1676 return;
1677 end;
1678
1679 if global
1680 then space_size = size (fnp_global_meters);
1681 else space_size = size (fnp_channel_meters);
1682
1683 call tty_space_man$get_space (space_size, fnp_meters_ptr);
1684 if fnp_meters_ptr = null ()
1685 then do;
1686 code = error_table_$noalloc;
1687 return;
1688 end;
1689
1690 mbx_data = bit (bin (tty_buf.absorig + bin (rel (fnp_meters_ptr)), 18), 18);
1691 call pxss$addevent (FNP_METER_EVENT);
1692 fnp_meter_wait_start = clock ();
1693
1694 if global
1695 then do;
1696 if fnp_info.get_meters_waiting
1697 then do;
1698 code = error_table_$seglock;
1699 return;
1700 end;
1701
1702 fnp_info.get_meters_waiting = "1"b;
1703 call dn355$send_global_wcd (fnpp, report_meters, 18, mbx_data);
1704 pcbp = fnpp;
1705 end;
1706
1707 else do;
1708 pcb.get_meters_waiting = "1"b;
1709 call dn355$send_wcd (fnpp, pcbp, report_meters, 18, mbx_data);
1710 end;
1711
1712 call unlock;
1713 call pxss$wait;
1714 call lock;
1715
1716 do while ((global & fnp_info.get_meters_waiting) | (^global & pcb.get_meters_waiting));
1717 if ^fnp_info.running
1718 then do;
1719 code = error_table_$mpx_down;
1720 go to abort_get_meters;
1721 end;
1722
1723 else if clock () - fnp_meter_wait_start > DUMP_PATCH_LIMIT
1724 then do;
1725 code = error_table_$timeout;
1726 fnp_info.dump_patch_disabled = "1"b;
1727 call syserr (ANNOUNCE,
1728 "fnp_multiplexer: get_meters order for FNP ^a^[^s^;, line ^o,^] timed out.", fnp_info.fnp_tag,
1729 global, string (pcb.line_number));
1730 abort_get_meters:
1731 if global
1732 then fnp_info.get_meters_waiting = "0"b;
1733 else pcb.get_meters_waiting = "0"b;
1734 end;
1735
1736 else do;
1737 call unlock;
1738 call pxss$addevent (FNP_METER_EVENT);
1739 if (global & fnp_info.get_meters_waiting) | (^global & pcb.get_meters_waiting)
1740
1741 then call pxss$wait;
1742 else call pxss$delevent (FNP_METER_EVENT);
1743 call lock;
1744 end;
1745 end;
1746
1747 return;
1748 end get_fnp_meters;
1749 ^L
1750 name_to_pcb:
1751 proc (name);
1752
1753 dcl name char (*);
1754
1755 code = 0;
1756 call parse_tty_name_ (name, his_fnp_no, hsla_flag, la_no, subchan);
1757 call lock;
1758 if code ^= 0
1759 then return;
1760
1761 if his_fnp_no ^= fnp_info.fnp_number
1762 then go to bad_device;
1763
1764 if hsla_flag
1765 then pcbx = fnp_info.hsla_idx (la_no);
1766 else pcbx = fnp_info.lsla_idx (la_no);
1767 if pcbx = -1
1768 then go to bad_device;
1769
1770 found, past = "0"b;
1771 do j = pcbx to fnp_info.no_of_channels while (^past & ^found);
1772 pcbp = addr (fnp_info.pcb_array_ptr -> pcb_array (j));
1773 if pcb.la_no ^= bit (bin (la_no, 3), 3)
1774 then past = "1"b;
1775 else if pcb.slot_no = bit (bin (subchan, 6), 6)
1776 then found = "1"b;
1777 end;
1778
1779 if ^found
1780 then do;
1781 bad_device:
1782 call unlock;
1783 code = error_table_$bad_channel;
1784 return;
1785 end;
1786
1787 return;
1788 end name_to_pcb;
1789 ^L
1790 lock:
1791 proc;
1792
1793
1794
1795 if fnpp = null ()
1796 then do;
1797 code = error_table_$mpx_down;
1798 return;
1799 end;
1800
1801 code = 0;
1802
1803 lctep = fnp_info.lcte_ptr;
1804 if lcte.lock = pds$processid
1805 then if lcte.locked_for_interrupt
1806 then mylock = "1"b;
1807 else call syserr (CRASH_SYSTEM, "fnp_multiplexer: mylock error");
1808 else do;
1809 mylock = "0"b;
1810 call tty_lock$lock_lcte (lctep, code);
1811 locked = (code = 0);
1812 end;
1813 return;
1814 end lock;
1815
1816
1817
1818 unlock:
1819 proc;
1820
1821
1822
1823 if locked
1824 then if ^mylock
1825 then do;
1826
1827 call dn355$process_interrupt_queue ((fnp_info.fnp_number));
1828 locked = "0"b;
1829
1830 end;
1831 return;
1832
1833 end unlock;
1834 ^L
1835
1836 fnp_buf_size:
1837 proc returns (bit (18));
1838
1839
1840
1841
1842
1843 do i = 1 to n_sync_line_types while (pcb.line_type ^= sync_line_type (i));
1844 end;
1845
1846 if i <= n_sync_line_types
1847 then do;
1848 pcb.sync_line = "1"b;
1849 chars_per_buf = divide (divide (pcb.baud_rate, 8, 17, 0), buf_per_second, 17, 0);
1850 end;
1851
1852 else do;
1853 pcb.sync_line = "0"b;
1854 chars_per_buf = 56;
1855 end;
1856
1857 return (bit (bin (chars_per_buf, 18), 18));
1858 end fnp_buf_size;
1859 ^L
1860
1861
1862
1863
1864
1865 declare a_fnp_no fixed bin;
1866 declare fnp_no fixed bin;
1867
1868 assign:
1869 entry (a_fnp_no, a_code);
1870
1871 infop = addr (dn355_data$);
1872 call TRACE ("assign");
1873 fnp_no = a_fnp_no;
1874 fnpp = addr (datanet_info.per_datanet (fnp_no));
1875 call assign_channel (code);
1876 a_code = code;
1877 return;
1878 ^L
1879
1880 unassign:
1881 entry (a_fnp_no, a_code);
1882
1883 fnp_no = a_fnp_no;
1884 infop = addr (dn355_data$);
1885 call TRACE ("unassign");
1886 fnpp = addr (datanet_info.per_datanet (fnp_no));
1887
1888 call unassign_channel (code);
1889 a_code = code;
1890 return;
1891
1892
1893 assign_channel:
1894 procedure (code);
1895 declare code fixed bin (35);
1896
1897 code = 0;
1898 if ^fnp_info.available
1899 then do;
1900 code = error_table_$io_not_configured;
1901 go to assign_channel_return;
1902 end;
1903
1904 if fnp_info.io_manager_assigned
1905 then do;
1906 code = error_table_$io_assigned;
1907 go to assign_channel_return;
1908 end;
1909
1910 call io_manager$assign (fnp_info.io_manager_chx, fnp_info.io_chanid, dn355$interrupt, (fnp_info.fnp_number),
1911 (null ()), code);
1912 fnp_info.io_manager_assigned = (code = 0);
1913 assign_channel_return:
1914 if datanet_info.trace | datanet_info.debug_stop
1915 then call syserr (ANNOUNCE, "fnp_multiplexer$assign_channel: Assignment of FNP ^a ^[succeeded^;failed^].",
1916 fnp_info.fnp_tag, (code = 0));
1917 if code ^= 0
1918 then call TRACE_ERROR ("assign_channel", code);
1919 return;
1920 end assign_channel;
1921
1922 unassign_channel:
1923 procedure (code);
1924 declare code fixed bin (35);
1925
1926
1927 if ^fnp_info.io_manager_assigned
1928 then do;
1929 code = error_table_$io_not_assigned;
1930 go to unassign_return;
1931 end;
1932 call io_manager$unassign (fnp_info.io_manager_chx, code);
1933 if code = 0
1934 then fnp_info.io_manager_assigned = "0"b;
1935 unassign_return:
1936 if datanet_info.trace | datanet_info.debug_stop
1937 then call syserr$error_code (ANNOUNCE, code,
1938 "fnp_multiplexer$unassign_channel: Unassignment of FNP ^a ^[failed^;succeeded^].", fnp_info.fnp_tag,
1939 (code ^= 0));
1940 if code ^= 0
1941 then call TRACE_ERROR ("unassign_channel", code);
1942 return;
1943 end unassign_channel;
1944
1945 TRACE:
1946 procedure (Entry);
1947
1948 declare Entry char (32);
1949
1950 if datanet_info.trace
1951 then call syserr (ANNOUNCE, "fnp_multiplexer$^a: Tracing call.", Entry);
1952 return;
1953
1954
1955
1956 TRACE_ERROR:
1957 entry (Entry, Code);
1958
1959 declare Code fixed bin (35);
1960
1961 if datanet_info.trace | datanet_info.debug_stop
1962 then call syserr$error_code (ANNOUNCE, Code, "fnp_multiplexer$^a: Tracing error.", Entry);
1963 if datanet_info.debug_stop
1964 then call syserr (CRASH_SYSTEM, "fnp_multiplexer: debugging stop (type go to continue).");
1965 return;
1966 end TRACE;
1967 ^L
1968
1969
1970
1971
1972 XXX
1973
1974
1975
1976
1977
1978
1979
1980 XXX
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140 end fnp_multiplexer;