1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 sty_mpx:
16 procedure;
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 dcl (
34 (Dp, Infop, Chainp, Miip) ptr,
35 Code fixed bin (35),
36 (Subchan, Devx) fixed bin,
37 More_sw bit aligned,
38 Mode_list ptr,
39 Modes character (*),
40 Order character (*)
41 ) parameter;
42
43 dcl (my_pdep, her_pdep) ptr;
44 dcl 1 my_pde aligned like pde based (my_pdep);
45 dcl 1 her_pde aligned like pde based (her_pdep);
46
47 dcl based_area area based;
48 dcl based_ev_chn fixed bin (71) based;
49 dcl based_access_class bit (72) aligned based;
50
51 dcl based_modes (currentsize (her_pde.mode_ptr -> mode_string_info)) fixed bin (35) based;
52
53 dcl infop pointer;
54
55 dcl 1 dial_out_info aligned based (infop),
56 2 len fixed bin (21),
57 2 destination char (dial_out_info.len);
58
59 dcl 1 rw_abort aligned based (infop),
60 2 (w, r) bit unaligned;
61
62 dcl 1 write_status aligned based (infop),
63 2 ev_chn fixed bin (71),
64 2 output_pending bit (1);
65
66 dcl based_line_status bit (72) aligned based (infop);
67 dcl line_status bit (72) aligned;
68
69 dcl (
70 error_table_$undefined_order_request,
71 error_table_$inconsistent,
72 error_table_$null_info_ptr,
73 error_table_$unimplemented_version,
74 error_table_$bad_mode,
75 error_table_$ai_already_set,
76 error_table_$noalloc
77 ) fixed bin (35) external;
78
79 dcl tty_area$ area external;
80
81 dcl formline_ entry (fixed bin, fixed bin, ptr, fixed bin (21), fixed bin (1));
82 dcl mode_string_$combine entry (ptr, ptr, char (*), fixed bin (35));
83 dcl mode_string_$delete entry (ptr, (*) char (*), char (*), fixed bin (35));
84 dcl mode_string_$parse entry (char (*), ptr, ptr, fixed bin (35));
85 dcl tty_area_manager$allocate entry (fixed bin, ptr);
86 dcl tty_area_manager$free entry (fixed bin, ptr);
87 dcl tty_area_manager$lock_area entry ();
88 dcl tty_area_manager$unlock_area entry ();
89
90 dcl (sc, i) fixed;
91 dcl mode_error bit (1) aligned;
92 dcl blocko uns fixed bin (18);
93 dcl code fixed bin (35);
94
95 dcl FF_CR_LF char (3) static options (constant) init ("^L^M
96 ");
97
98 dcl (addr, binary, currentsize, divide, length, mod, null, pointer, rel, rtrim, size, substr, unspec) builtin;
99
100 dcl (area, cleanup) condition;
101 %page;
102
103
104 control:
105 entry (Dp, Subchan, Order, Infop, Code);
106
107 Code = 0;
108 infop = Infop;
109 call setup_subchan;
110
111 if Order = "listen" then do;
112 my_pde.location = "";
113 call bring_up_keep_ac;
114 end;
115
116 else if Order = "dial_out" then do;
117 if infop ^= null () then do;
118 call bring_up_keep_ac;
119 my_pde.location = dial_out_info.destination;
120 end;
121 else Code = error_table_$null_info_ptr;
122 end;
123
124 else if Order = "hangup" then do;
125 call channel_manager$interrupt_later (her_pde.devx, HANGUP, ""b);
126 call channel_manager$interrupt_later (my_pde.devx, HANGUP, ""b);
127 my_pde.access_class_set,
128 her_pde.access_class_set = "0"b;
129 my_pde.access_class, her_pde.access_class = "0"b;
130 call abort (my_pde);
131 call abort (her_pde);
132 if my_pde.mode_ptr ^= null () then call tty_area_manager$free (currentsize (my_pde.mode_ptr -> mode_string_info), my_pde.mode_ptr);
133 if her_pde.mode_ptr ^= null () then call tty_area_manager$free (currentsize (her_pde.mode_ptr -> mode_string_info), her_pde.mode_ptr);
134 my_pde.mode_ptr, her_pde.mode_ptr = null ();
135 my_pde.flags.listen, her_pde.flags.listen = "0"b;
136 end;
137
138 else if Order = "wru" then do;
139 my_pde.flags.wru = "1"b;
140 if her_pde.head = 0 then call channel_manager$interrupt_later (my_pde.devx, INPUT_AVAILABLE, ""b);
141 end;
142
143 else if Order = "abort" then do;
144 if infop ^= null () then do;
145 if rw_abort.w then call abort (my_pde);
146 if rw_abort.r then call abort (her_pde);
147 end;
148 else Code = error_table_$null_info_ptr;
149 end;
150
151 else if Order = "write_status" then do;
152 if infop ^= null ()
153 then write_status.output_pending = (my_pde.head ^= 0);
154
155 else Code = error_table_$null_info_ptr;
156 end;
157
158 else if Order = "interrupt" then do;
159 her_pde.end_of_page = "0"b;
160 call channel_manager$interrupt_later (her_pde.devx, QUIT, ""b);
161 call send_output (her_pde);
162 end;
163
164 else if Order = "line_control" then do;
165 if infop = null () then do;
166 Code = error_table_$null_info_ptr;
167 return;
168 end;
169 line_status = based_line_status;
170 call channel_manager$interrupt_later (her_pde.devx, LINE_STATUS, line_status);
171 end;
172
173 else if Order = "printer_on" then call new_mode ("echo");
174
175 else if Order = "printer_off" then call new_mode ("^echo");
176
177 else if Order = "get_foreign_terminal_data" then do;
178 foreign_terminal_data_ptr = infop;
179 if foreign_terminal_data_ptr = null () then do;
180 Code = error_table_$null_info_ptr;
181 return;
182 end;
183 if foreign_terminal_data.version ^= FOREIGN_TERMINAL_DATA_VERSION_1 then do;
184 Code = error_table_$unimplemented_version;
185 return;
186 end;
187 foreign_terminal_data.mode_string_info_ptr = null ();
188 if her_pde.mode_ptr ^= null () then do;
189 on area goto noalloc;
190 allocate based_modes in (foreign_terminal_data.area_ptr -> based_area)
191 set (foreign_terminal_data.mode_string_info_ptr);
192 foreign_terminal_data.mode_string_info_ptr -> based_modes = her_pde.mode_ptr -> based_modes;
193 end;
194 her_pde.flags.notify_modes = "1"b;
195 end;
196
197 else if Order = "set_required_access_class" then do;
198 if infop = null () then Code = error_table_$null_info_ptr;
199 else if my_pde.access_class_set
200 then if my_pde.access_class = infop -> based_access_class
201
202 then Code = 0;
203 else Code = error_table_$ai_already_set;
204
205 else do;
206 my_pde.access_class, her_pde.access_class = infop -> based_access_class;
207 my_pde.access_class_set, her_pde.access_class_set = "1"b;
208 Code = 0;
209 end;
210 end;
211
212 else if Order = "get_required_access_class" then do;
213 if infop = null ()
214 then Code = error_table_$null_info_ptr;
215 else do;
216 infop -> tty_access_class.access_class_set = my_pde.access_class_set;
217 if my_pde.access_class_set
218 then infop -> tty_access_class.access_class = my_pde.access_class;
219 else infop -> tty_access_class.access_class = "0"b;
220
221 Code = 0;
222 end;
223 end;
224
225 else if Order = "input_flow_control_chars" then ;
226 else if Order = "output_flow_control_chars" then ;
227 else if Order = "set_delay" then ;
228 else if Order = "set_framing_chars" then ;
229
230 else Code = error_table_$undefined_order_request;
231
232 return;
233 %page;
234
235
236 write:
237 entry (Dp, Subchan, Chainp, Code);
238
239 Code = 0;
240 call setup_subchan;
241
242 my_pde.flags.output_ready = "0"b;
243
244 if Chainp = null () then return;
245
246 if my_pde.end_of_page then return;
247
248 if her_pde.end_of_page then do;
249 her_pde.end_of_page = "0"b;
250 call send_output (her_pde);
251 blockp = Chainp;
252 if (buffer.next = 0)
253 & (buffer.tally <= 2)
254 & (verify (substr (string (buffer.chars), 1, buffer.tally), FF_CR_LF) = 0) then do;
255
256 call tty_space_man$free_buffer (my_pde.devx, OUTPUT, Chainp);
257
258 call send_output (my_pde);
259 Chainp = null ();
260 return;
261 end;
262 end;
263
264 blockp = Chainp;
265 blocko = buffer.next;
266 do while (blocko ^= 0 & ^buffer.end_of_page);
267 blockp = pointer (addr (tty_buf$), blocko);
268 blocko = buffer.next;
269 end;
270
271 buffer.next = 0;
272 buffer.flags.break = "1"b;
273 my_pde.flags.end_of_page = buffer.end_of_page; note
274 if my_pde.head = 0
275 then do;
276 my_pde.head = binary (rel (Chainp), 18);
277 my_pde.tail = binary (rel (blockp), 18);
278 call channel_manager$interrupt_later (her_pde.devx, INPUT_AVAILABLE, ""b);
279
280 end;
281
282 else do;
283 pointer (addr (tty_buf$), my_pde.tail) -> buffer.next = binary (rel (Chainp), 18);
284 my_pde.tail = binary (rel (blockp), 18);
285 end;
286
287 if blocko = 0
288 then
289 Chainp = null ();
290 else Chainp = pointer (addr (tty_buf$), blocko);
291 return;
292 %page;
293
294
295 read:
296 entry (Dp, Subchan, Chainp, More_sw, Code);
297
298 Code = 0;
299 Chainp = null ();
300 More_sw = "0"b;
301 call setup_subchan;
302
303 if her_pde.head ^= 0 then do;
304 Chainp = pointer (addr (tty_buf$), her_pde.head);
305
306 her_pde.head, her_pde.tail = 0;
307 call tty_space_man$switch_chain (her_pde.devx, my_pde.devx, OUTPUT, INPUT, Chainp);
308 call send_output (her_pde);
309 end;
310
311 else if my_pde.flags.wru then do;
312 call tty_space_man$get_buffer (my_pde.devx, 16, INPUT, blockp);
313 if blockp ^= null () then do;
314 my_pde.flags.wru = "0"b;
315 string (buffer.chars) = rtrim (her_pde.location) || "
316 " ;
317 buffer.tally = length (rtrim (string (buffer.chars)));
318 string (buffer.flags) = ""b;
319 buffer.flags.break = "1"b;
320 buffer.next = 0;
321
322 Chainp = blockp;
323 end;
324 end;
325
326 return;
327 %page;
328
329
330 check_modes:
331 entry (Dp, Subchan, Mode_list, Code);
332
333 Code = 0;
334 call setup_subchan;
335
336 mclp = Mode_list;
337 if mcl.version ^= mcl_version_2 then do;
338 Code = error_table_$unimplemented_version;
339 return;
340 end;
341
342 mcl.ll_error, mcl.pl_error, mcl.can_type_error = "0"b;
343
344 do i = 1 to mcl.n_entries;
345 mcl.entries (i).flags.mpx_mode = "1"b;
346 mcl.entries (i).flags.error = "0"b;
347 end;
348
349 return;
350
351
352
353 set_modes:
354 entry (Dp, Subchan, Mode_list, Code);
355
356 Code = 0;
357 call setup_subchan;
358
359 mclp = Mode_list;
360 if mcl.version ^= mcl_version_2 then do;
361 Code = error_table_$unimplemented_version;
362 return;
363 end;
364
365 if mcl.flags.init & (my_pde.mode_ptr ^= null ()) then do;
366 call tty_area_manager$free (currentsize (my_pde.mode_ptr -> mode_string_info), my_pde.mode_ptr);
367 my_pde.mode_ptr = null ();
368 end;
369
370 mcl.ll_error, mcl.pl_error, mcl.can_type_error = "0"b;
371
372 if mcl.line_len ^= -1 then do;
373 call new_mode ("ll=^d", mcl.line_len);
374 mcl.ll_error = mode_error;
375 end;
376 if mcl.page_len ^= -1 then do;
377 call new_mode ("pl=^d", mcl.page_len);
378 mcl.pl_error = mode_error;
379 end;
380 if mcl.can_type ^= -1 then do;
381 call new_mode ("can_type=^[overstrike^;replace^]", mcl.can_type);
382 mcl.can_type_error = mode_error;
383 end;
384
385 do i = 1 to mcl.n_entries;
386 if mcl.entries (i).mpx_mode then do;
387 call new_mode ("^[^^^]^a", ^mcl.entries (i).flags.mode_switch, mcl.entries (i).mode_name);
388 mcl.entries (i).flags.error = mode_error;
389 end;
390 end;
391
392 return;
393
394
395
396 get_modes:
397 entry (Dp, Subchan, Modes, Code);
398
399 Code = 0;
400 Modes = "";
401 call setup_subchan;
402
403 if my_pde.mode_ptr ^= null () then call mode_string_$delete (my_pde.mode_ptr, MODE_NAME, Modes, Code);
404 if substr (Modes, length (rtrim (Modes)), 1) = "." then substr (Modes, length (rtrim (Modes)), 1) = " ";
405
406 return;
407 %page;
408
409
410 init_multiplexer:
411 entry (Devx, Miip, Dp, Code);
412
413 Code = 0;
414 lctp = addr (tty_buf$) -> tty_buf.lct_ptr;
415
416 miip = Miip;
417 sty_mpx_data_nchan = mux_init_info.no_channels;
418 if mod (sty_mpx_data_nchan, 2) ^= 0 then do;
419 Code = error_table_$inconsistent;
420 return;
421 end;
422
423 sty_mpx_data_ptr = null ();
424 on cleanup
425 begin;
426 if sty_mpx_data_ptr ^= null () then call tty_area_manager$free (currentsize (sty_mpx_data), sty_mpx_data_ptr);
427 end;
428 on area goto noalloc;
429
430 call tty_area_manager$allocate (size (sty_mpx_data), sty_mpx_data_ptr);
431
432 sty_mpx_data.n_channels = sty_mpx_data_nchan;
433 sty_mpx_data.devx = Devx;
434 sty_mpx_data.n_pairs = divide (sty_mpx_data.n_channels, 2, 17, 0);
435 do sc = 1 to sty_mpx_data.n_channels;
436 my_pdep = addr (sty_mpx_data.pdes (sc));
437 call reset (my_pde, "1"b);
438 my_pde.head, my_pde.tail = 0;
439 my_pde.devx = mux_init_info.devx (sc);
440 my_pde.mode_ptr = null ();
441
442 lct.lcte_array (my_pde.devx).subchannel = sc;
443 lct.lcte_array (my_pde.devx).physical_channel_devx = my_pde.devx;
444 end;
445
446 Dp = sty_mpx_data_ptr;
447 return;
448
449 noalloc:
450 Code = error_table_$noalloc;
451 return;
452
453
454
455 start:
456 entry (Dp, Code);
457
458 Code = 0;
459 sty_mpx_data_ptr = Dp;
460
461 sty_mpx_data.flags.started = "1"b;
462
463 do i = 1 to sty_mpx_data.n_pairs;
464 my_pdep = addr (sty_mpx_data.pdes (i));
465 if my_pde.flags.listen then do;
466 her_pdep = addr (sty_mpx_data.pdes (i + sty_mpx_data.n_pairs));
467 call bring_up;
468 end;
469 end;
470
471 return;
472
473
474
475 stop:
476 entry (Dp, Code);
477
478 Code = 0;
479 sty_mpx_data_ptr = Dp;
480
481 sty_mpx_data.flags.started = "0"b;
482 return;
483
484
485
486 shutdown:
487 entry (Dp, Code);
488
489 Code = 0;
490 sty_mpx_data_ptr = Dp;
491
492 do sc = 1 to sty_mpx_data.n_channels;
493 call channel_manager$interrupt_later (sty_mpx_data.pdes (sc).devx, CRASH, ""b);
494 sty_mpx_data.pdes (sc).listen = "0"b;
495 end;
496
497 return;
498
499
500
501 terminate_multiplexer:
502 entry (Dp, Code);
503
504 Code = 0;
505 sty_mpx_data_ptr = Dp;
506
507 do i = 1 to sty_mpx_data.n_channels;
508 my_pdep = addr (sty_mpx_data.pdes (i));
509 call abort (my_pde);
510 if my_pde.mode_ptr ^= null () then call tty_area_manager$free (currentsize (my_pde.mode_ptr -> mode_string_info), my_pde.mode_ptr);
511 end;
512
513 call tty_area_manager$free (currentsize (sty_mpx_data), sty_mpx_data_ptr);
514
515 Dp = null ();
516 return;
517 %page;
518
519
520 setup_subchan:
521 procedure;
522
523 sty_mpx_data_ptr = Dp;
524
525 my_pdep = addr (sty_mpx_data.pdes (Subchan));
526 her_pdep = addr (sty_mpx_data.pdes (mod (Subchan - 1 + sty_mpx_data.n_pairs, sty_mpx_data.n_channels) + 1));
527 return;
528 end setup_subchan;
529
530
531
532 abort:
533 procedure (Pde);
534 dcl 1 Pde aligned like pde;
535
536 Pde.end_of_page = "0"b;
537 if Pde.head ^= 0 then do;
538 call tty_space_man$free_chain (Pde.devx, OUTPUT, pointer (addr (tty_buf$), Pde.head));
539 Pde.head, Pde.tail = 0;
540 end;
541 call send_output (Pde);
542 return;
543 end abort;
544
545
546
547 new_mode:
548 procedure options (variable);
549
550 dcl old_mode_ptr ptr;
551 dcl code fixed bin (35);
552 dcl this_mode char (32);
553 dcl combined_modes char (512);
554
555 mode_string_info_ptr = null ();
556
557 call formline_ (1, 2, addr (this_mode), length (this_mode), 1);
558
559 call tty_area_manager$lock_area ();
560 on cleanup call tty_area_manager$unlock_area ();
561
562 call mode_string_$parse (this_mode, addr (tty_area$), mode_string_info_ptr, code);
563 if code ^= 0 then goto bad_mode;
564
565 call mode_string_$combine (my_pde.mode_ptr, mode_string_info_ptr, combined_modes, code);
566 if code ^= 0 then goto bad_mode;
567
568 free mode_string_info in (tty_area$);
569 mode_string_info_ptr = null ();
570
571 call mode_string_$parse (combined_modes, addr (tty_area$), mode_string_info_ptr, code);
572 if code ^= 0 then goto bad_mode;
573
574 old_mode_ptr = my_pde.mode_ptr;
575 my_pde.mode_ptr = mode_string_info_ptr;
576 if old_mode_ptr ^= null () then free old_mode_ptr -> mode_string_info in (tty_area$);
577 call tty_area_manager$unlock_area ();
578
579 if my_pde.flags.notify_modes then do;
580 call channel_manager$interrupt_later (her_pde.devx, LINE_STATUS, ""b);
581 my_pde.flags.notify_modes = "0"b;
582 end;
583
584 mode_error = "0"b;
585 return;
586
587 bad_mode:
588 call tty_area_manager$unlock_area ();
589 mode_error = "1"b;
590 return;
591 end new_mode;
592
593
594
595 bring_up:
596 procedure;
597
598 dcl reset_ac bit (1);
599
600 reset_ac = "1"b;
601 go to bring_up_join;
602
603 bring_up_keep_ac:
604 entry;
605
606 reset_ac = "0"b;
607
608 bring_up_join:
609 if sty_mpx_data.flags.started & her_pde.flags.listen then do;
610
611 unspec (dialup_info) = ""b;
612 dialup_info.line_type = LINE_ASCII;
613 dialup_info.max_buf_size = 128;
614 call channel_manager$interrupt_later (her_pde.devx, DIALUP, unspec (dialup_info));
615 call channel_manager$interrupt_later (my_pde.devx, DIALUP, unspec (dialup_info));
616
617 call reset (her_pde, reset_ac);
618 call reset (my_pde, reset_ac);
619 call send_output (her_pde);
620 call send_output (my_pde);
621 end;
622
623 else my_pde.flags.listen = "1"b;
624
625 return;
626 end bring_up;
627
628
629
630 reset:
631 procedure (Pde, Reset_ac);
632 dcl 1 Pde aligned like pde;
633 dcl Reset_ac bit (1);
634
635 dcl old_ac_flag bit (1);
636
637 if ^Reset_ac then old_ac_flag = Pde.access_class_set;
638 string (Pde.flags) = ""b;
639 if ^Reset_ac then Pde.access_class_set = old_ac_flag;
640 Pde.location = "";
641 if Reset_ac then Pde.access_class = "0"b;
642
643 return;
644 end reset;
645
646
647
648 send_output:
649 procedure (Pde);
650 dcl 1 Pde aligned like pde;
651
652 if ^Pde.flags.output_ready & ^Pde.flags.end_of_page & (Pde.head = 0) then do;
653 Pde.flags.output_ready = "1"b;
654 call channel_manager$interrupt_later (Pde.devx, SEND_OUTPUT, ""b);
655 end;
656 return;
657 end send_output;
658 %page;
659 %include sty_mpx_data;
660 %include foreign_terminal_data;
661 %include mcs_interrupt_info;
662 %include tty_buffer_block;
663 %include channel_manager_dcls;
664 %include mux_init_info;
665 %include lct;
666 %include tty_buf;
667 %include tty_space_man_dcls;
668 %include line_types;
669 %include mcs_modes_change_list;
670 %include mode_string_info;
671 %include tty_mode_names;
672 %include tty_access_class;
673
674 end sty_mpx;