1
2
3
4
5
6
7
8
9
10
11 lap_simplex:
12 procedure;
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 Note
32
33
34
35
36
37
38
39
40
41
42 lap_simplex$interrupt:
43 entry (P_lap_data_ptr, P_int_type, P_int_data);
44
45 lap_data_ptr = P_lap_data_ptr;
46 int_type = P_int_type;
47 int_data = P_int_data;
48
49 if (int_type < lbound (INTERRUPT, 1)) | (int_type > hbound (INTERRUPT, 1)) then do;
50 BAD_INTERRUPT:
51 call syserr (Log_message, "lap_simplex(^a): Unexpected interrupt ^d ^.3b received.", lap_data.name,
52 int_type, int_data);
53 return;
54 end;
55 else goto INTERRUPT (int_type);
56
57
58 INTERRUPT (1):
59 if (lap_data.state ^= LAP_LISTENING) then goto BAD_INTERRUPT;
60 unspec (lap_data.dialup_info) = int_data;
61 lap_data.sc_dialup_info = lap_data.dialup_info;
62 lap_data.sc_dialup_info.buffer_pad = L2_HEADER_PAD;
63 lap_data.sc_dialup_info.line_type = LINE_ASCII;
64
65 call pxss$ring_0_wakeup (lap_data.load_process_id, lap_data.load_event_channel, MPX_UP, ignore_code);
66 lap_data.state = LAP_ACTIVE;
67 return;
68
69
70 INTERRUPT (2):
71 call crash (int_type);
72 return;
73
74
75 INTERRUPT (3):
76 call crash (int_type);
77 return;
78
79
80 INTERRUPT (4):
81 lap_data.flags.send_output = "1"b;
82 call channel_manager$interrupt (lap_data.subchannel, SEND_OUTPUT, (""b));
83 return;
84
85
86 INTERRUPT (5):
87 goto BAD_INTERRUPT;
88
89
90 INTERRUPT (6):
91 unspec (rtx_info) = int_data;
92 blockp = pointer (lap_data_ptr, rtx_info.chain_head);
93 real_buffer_lth = buffer.tally - L2_HEADER_PAD;
94
95 if ((lap_data.state < LAP_ACTIVE) | (real_buffer_lth <= 0)) then do;
96 call tty_space_man$free_chain (lap_data.devx, INPUT, blockp);
97 goto BAD_INTERRUPT;
98 end;
99
100 call tty_space_man$switch_chain (lap_data.devx, lap_data.subchannel, INPUT, INPUT, blockp);
101
102 begin;
103 dcl old_string char (real_buffer_lth) automatic;
104 dcl new_string char (real_buffer_lth) defined (buffer.chars);
105 old_string = substr (string (buffer.chars), L2_HEADER_PAD + 1, real_buffer_lth);
106 new_string = old_string;
107 end;
108
109 buffer.tally = buffer.tally - L2_HEADER_PAD;
110 rtx_info.input_count = rtx_info.input_count - L2_HEADER_PAD;
111
112 blockp = pointer (blockp, rtx_info.chain_tail);
113 begin;
114 dcl last_char char (1) unaligned defined (buffer.chars (buffer.tally - 1));
115 unspec (last_char) = unspec (last_char) | "400"b3;
116 end;
117
118 call channel_manager$interrupt (lap_data.subchannel, ACCEPT_INPUT, unspec (rtx_info));
119 return;
120
121
122 INTERRUPT (7):
123 INTERRUPT (8):
124 return;
125
126
127 INTERRUPT (9):
128 unspec (lap_down_status) = int_data;
129
130 if lap_down_status.status_type = 1
131 then call syserr (Log_message,
132 "lap_simplex(^a): Failure, Link state: ^a, Current action: ^a, in ^a, Primary state: ^a, Secondary state: ^a",
133 lap_data.name, FRAME_STATE_ARRAY (lap_down_status.main_state),
134 FRAME_FUNCTION_CODE (lap_down_status.last_function_process),
135 FRAME_SUB_STATE_ARRAY (lap_down_status.which_state_process),
136 FRAME_SUB_STATE_ARRAY (lap_down_status.primary_sub_state),
137 FRAME_SUB_STATE_ARRAY (lap_down_status.secondary_sub_state));
138
139 else if lap_cmdr_status.cmdr_status = 3
140 then call syserr (Log_message,
141 "lap_simplex(^a): Link disconnected due to mis-matched frame sizes. CMDR/FRMR frame: ^( ^.4b^).",
142 lap_data.name, lap_cmdr_status.cmdr_bytes.byte (*));
143
144 else goto BAD_INTERRUPT;
145
146 return;
147
148
149 INTERRUPT (10):
150 INTERRUPT (11):
151 goto BAD_INTERRUPT;
152
153
154 INTERRUPT (12):
155 call channel_manager$interrupt (lap_data.subchannel, SEND_OUTPUT, ""b);
156 return;
157
158
159 INTERRUPT (13):
160 INTERRUPT (14):
161 return;
162
163
164 INTERRUPT (15):
165 INTERRUPT (16):
166 goto BAD_INTERRUPT;
167
168
169 INTERRUPT (17):
170 call pxss$ring_0_wakeup (lap_data.load_process_id, lap_data.load_event_channel, MPX_MASKED, code);
171 call crash (MASKED);
172 lap_data.state = LAP_HUNGUP;
173 return;
174 %page;
175
176
177 lap_simplex$write:
178 entry (P_lap_data_ptr, P_subchan_idx, P_chain_ptr, P_code);
179
180 call setup ();
181
182 code = 0;
183 chain_ptr = P_chain_ptr;
184 next_block = binary (rel (chain_ptr), 18);
185
186 do while ((next_block ^= 0) & lap_data.send_output);
187 blockp = pointer (chain_ptr, next_block);
188
189
190
191 XXX
192
193
194
195 frame_end = search (substr (string (buffer.chars), 1, buffer.tally), substr (collate9 (), 257, 256));
196
197 if frame_end = 0 then do;
198 next_block = buffer.next;
199 call add_buffer_to_frame ();
200 end;
201
202 else if frame_end = buffer.tally then do;
203 next_block = buffer.next;
204 lap_data.frame_ready = "1"b;
205 call add_buffer_to_frame ();
206 end;
207
208 else do;
209 call split_buffer ();
210 lap_data.frame_ready = "1"b;
211 call add_buffer_to_frame ();
212 end;
213
214 if lap_data.frame_ready then call write_frame ();
215 end;
216
217 WRITE_FINISHES:
218 if (next_block = 0)
219 then P_chain_ptr = null ();
220 else P_chain_ptr = pointer (chain_ptr, next_block);
221
222 if lap_data.send_output then call channel_manager$interrupt (lap_data.subchannel, SEND_OUTPUT, ""b);
223
224 P_code = code;
225 return;
226 %page;
227
228
229 add_buffer_to_frame:
230 procedure ();
231
232 if (buffer.tally + lap_data.frame_size) > lap_data.max_frame_size then do;
233 call syserr (Log_message, "lap_simplex(^a): Attempt to write overlength frame.", lap_data.name);
234 call crash (HANGUP);
235 call free_pending_frame ();
236 end;
237
238 lap_data.frame_size = lap_data.frame_size + buffer.tally;
239 buffer.next = 0;
240 string (buffer.flags) = ""b;
241
242 if (lap_data.frame_start ^= null ())
243 then
244 lap_data.frame_end -> buffer.next = binary (rel (blockp), 18);
245 else lap_data.frame_start = blockp;
246
247 lap_data.frame_end = blockp;
248
249 return;
250 end add_buffer_to_frame;
251 %page;
252
253
254 split_buffer:
255 procedure ();
256
257 dcl leftover_chars fixed bin;
258 dcl new_buf_size fixed bin;
259 dcl new_bufp pointer;
260
261
262
263
264
265
266
267 leftover_chars = buffer.tally - frame_end;
268
269 new_buf_size = 16 * (1 + divide ((leftover_chars + 7), 64, 17, 0));
270 call tty_space_man$get_buffer (lap_data.subchannel, new_buf_size, OUTPUT, new_bufp);
271 if (new_bufp = null ()) then do;
272 call tty_space_man$needs_space (lap_data.devx);
273
274 lap_data.send_output = "0"b;
275 goto WRITE_FINISHES;
276 end;
277
278 substr (string (new_bufp -> buffer.chars), 1, leftover_chars) =
279 substr (string (buffer.chars), frame_end + 1, leftover_chars);
280 new_bufp -> buffer.next = buffer.next;
281 new_bufp -> buffer.tally = leftover_chars;
282 string (new_bufp -> buffer.flags) = ""b;
283
284 next_block = binary (rel (new_bufp), 18);
285
286 buffer.tally = buffer.tally - leftover_chars;
287
288 return;
289 end split_buffer;
290 %page;
291
292
293 write_frame:
294 procedure ();
295
296 dcl bufp pointer;
297 dcl bufl fixed bin;
298
299
300 lap_data.frame_end -> buffer.break = "1"b;
301
302 bufp = lap_data.frame_start;
303 bufl = bufp -> buffer.tally;
304
305 begin;
306 dcl old_string char (bufl) automatic;
307 dcl new_string char (bufl) defined (bufp -> buffer.chars (L2_HEADER_PAD));
308 old_string = substr (string (bufp -> buffer.chars), 1, bufl);
309 new_string = old_string;
310 end;
311
312 bufp -> buffer.tally = bufp -> buffer.tally + L2_HEADER_PAD;
313
314
315
316 call tty_space_man$switch_chain (lap_data.subchannel, lap_data.devx, OUTPUT, OUTPUT, lap_data.frame_start);
317
318 call channel_manager$write (lap_data.devx, lap_data.frame_start, code);
319 if (code ^= 0) then do;
320 call syserr$error_code (Log_message, code, "lap_simplex(^a): Error from write of ^d chars.", lap_data.name,
321 lap_data.frame_size);
322 call free_pending_frame ();
323 call channel_manager$control (lap_data.devx, "hangup", null (), ignore_code);
324 return;
325 end;
326
327 if (lap_data.frame_start ^= null ()) & (lap_data.frame_start ^= bufp) then do;
328 call syserr (Log_message, "lap_simplex(^a): Write failed to take whole frame, discarding rest.",
329 lap_data.name);
330 call free_pending_frame ();
331 return;
332 end;
333
334 if (lap_data.frame_start = null ()) then do;
335 lap_data.frame_end = null ();
336 lap_data.frame_size = 0;
337 lap_data.frame_ready = "0"b;
338 lap_data.send_output = "1"b;
339 end;
340 else lap_data.send_output = "0"b;
341
342 return;
343 end write_frame;
344 %page;
345
346
347 lap_simplex$control:
348 entry (P_lap_data_ptr, P_subchan_idx, P_order, P_info_ptr, P_code);
349
350 call setup ();
351
352 order = P_order;
353 info_ptr = P_info_ptr;
354 code = 0;
355
356 if (order = "hangup") then do;
357 if (lap_data.state = LAP_HUNGUP)
358 then code = error_table_$invalid_state;
359 else call channel_manager$control (lap_data.devx, "hangup", null (), code);
360 end;
361
362 else if (order = "listen") then do;
363 if (lap_data.state ^= LAP_ACTIVE)
364 then code = error_table_$invalid_state;
365 else do;
366 call channel_manager$interrupt (lap_data.subchannel, DIALUP, unspec (lap_data.sc_dialup_info));
367 call channel_manager$interrupt (lap_data.subchannel, SEND_OUTPUT, ""b);
368 end;
369 end;
370
371 else if (order = "abort") then do;
372 if (info_ptr = null ())
373 then code = error_table_$null_info_ptr;
374 else call free_pending_frame ();
375 end;
376
377 else if (order = "write_status") then do;
378 if (info_ptr = null ())
379 then code = error_table_$null_info_ptr;
380 else do;
381 if (lap_data.frame_size ^= 0)
382 then info_ptr -> tty_write_status_info.output_pending = "1"b;
383 else call channel_manager$control (lap_data.devx, "write_status", info_ptr, code);
384 end;
385 end;
386
387 else if (order = "wru") then do;
388 if (lap_data.state ^= LAP_ACTIVE)
389 then code = error_table_$invalid_state;
390 else call channel_manager$interrupt (lap_data.subchannel, WRU_TIMEOUT, ""b);
391 end;
392
393 else code = error_table_$undefined_order_request;
394
395 P_code = code;
396 return;
397 %page;
398
399
400 lap_simplex$check_modes:
401 entry (P_lap_data_ptr, P_subchan_idx, P_mcl_info_ptr, P_code);
402
403 call do_modes ("0"b);
404 return;
405
406
407
408 lap_simplex$set_modes:
409 entry (P_lap_data_ptr, P_subchan_idx, P_mcl_info_ptr, P_code);
410
411 call do_modes ("1"b);
412 return;
413
414
415
416 lap_simplex$get_modes:
417 entry (P_lap_data_ptr, P_subchan_idx, P_modes, P_code);
418
419 call setup ();
420 P_code = 0;
421 P_modes = "";
422 return;
423 %page;
424
425
426 do_modes:
427 procedure (P_set_sw);
428
429 dcl P_set_sw bit (1) aligned parameter;
430 dcl mode_error fixed bin (35);
431
432
433 call setup ();
434 mclp = P_mcl_info_ptr;
435
436 if mcl.version ^= mcl_version_2 then do;
437 P_code = error_table_$unimplemented_version;
438 return;
439 end;
440
441 mode_error = 0;
442
443 do mode_idx = 1 to mcl.n_entries;
444 mclep = addr (mcl.entries (mode_idx));
445 if (mcle.mode_name = "rawo") | (mcle.mode_name = "rawi") then do;
446 if ^P_set_sw then mcle.mpx_mode = "1"b;
447 else if (mcle.mode_switch = "0"b) then do;
448
449 mode_error = error_table_$bad_mode;
450 mcle.error = "1"b;
451 end;
452 end;
453
454 else if P_set_sw
455 then if (mcle.mpx_mode & ^mcle.force) then do;
456 mode_error = error_table_$bad_mode;
457 mcle.error = "1"b;
458 end;
459
460 else mcle.mpx_mode = "0"b;
461 end;
462
463 P_code = mode_error;
464 return;
465 end do_modes;
466 %page;
467
468
469 setup:
470 procedure ();
471
472 lap_data_ptr = P_lap_data_ptr;
473 if (P_subchan_idx ^= 1) then do;
474 call syserr (Write_with_alarm, "lap_simplex(^a): Invalid subchannel index ^d", lap_data.name, P_subchan_idx);
475 P_code = error_table_$bad_arg;
476 goto SETUP_RETURNS_FOR_ERROR;
477 end;
478
479 return;
480 end setup;
481
482 SETUP_RETURNS_FOR_ERROR:
483 return;
484
485
486
487
488 crash:
489 procedure (P_type);
490
491 dcl P_type fixed bin parameter;
492
493
494 call free_pending_frame ();
495
496 call channel_manager$interrupt (lap_data.subchannel, P_type, ""b);
497
498 if (P_type ^= CRASH)
499 then
500 call pxss$ring_0_wakeup (lap_data.load_process_id, lap_data.load_event_channel, MPX_DOWN, code);
501
502 lap_data.state = LAP_HUNGUP;
503
504 return;
505 end crash;
506
507
508
509 free_pending_frame:
510 procedure ();
511
512 if (lap_data.frame_start = null ()) then return;
513
514 call tty_space_man$free_chain (lap_data.devx, OUTPUT, lap_data.frame_start);
515
516 lap_data.frame_start = null ();
517 lap_data.frame_end = null ();
518 lap_data.frame_size = 0;
519 lap_data.frame_ready = "0"b;
520
521 return;
522 end free_pending_frame;
523 %page;
524
525
526
527
528
529
530
531
532
533 lap_simplex$init_multiplexer:
534 entry (P_devx, P_miip, P_lap_data_ptr, P_code);
535
536 devx = P_devx;
537 miip = P_miip;
538 P_lap_data_ptr = null ();
539
540 if ^init_sw then do;
541 call wire_proc$wire_me;
542 init_sw = "1"b;
543 end;
544
545 lap_data_ptr = null ();
546 on cleanup
547 begin;
548 if lap_data_ptr ^= null () then call tty_space_man$free_space (size (lap_data), lap_data_ptr);
549 end;
550
551 call tty_space_man$get_space (size (lap_data), lap_data_ptr);
552 if lap_data_ptr = null () then do;
553 P_code = error_table_$noalloc;
554 return;
555 end;
556
557 lap_data.name = reverse (after (reverse (mux_init_info.channels (1).name), "."));
558 lap_data.devx = devx;
559 lap_data.subchannel = mux_init_info.channels (1).devx;
560 lap_data.state = LAP_HUNGUP;
561 lap_data.frame_start = null ();
562 lap_data.frame_end = null ();
563
564 lctp = tty_buf$lct_ptr;
565 lctep = addr (lct.lcte_array (lap_data.subchannel));
566 lcte.subchannel = 1;
567
568 P_lap_data_ptr = lap_data_ptr;
569 P_code = 0;
570 return;
571 %page;
572
573
574
575
576 lap_simplex$terminate_multiplexer:
577 entry (P_lap_data_ptr, P_code);
578
579 lap_data_ptr = P_lap_data_ptr;
580 call tty_space_man$free_space (currentsize (lap_data), lap_data_ptr);
581
582 P_lap_data_ptr = null ();
583 P_code = 0;
584 return;
585
586
587
588
589
590 lap_simplex$start:
591 entry (P_lap_data_ptr, P_code);
592
593 lap_data_ptr = P_lap_data_ptr;
594 lap_data.simplex_started = "1"b;
595 P_code = 0;
596 return;
597
598
599
600
601
602 lap_simplex$stop:
603 entry (P_lap_data_ptr, P_code);
604
605 lap_data_ptr = P_lap_data_ptr;
606 lap_data.simplex_started = "0"b;
607 P_code = 0;
608 return;
609
610
611
612
613
614
615
616
617
618 lap_simplex$shutdown:
619 entry (P_lap_data_ptr, P_code);
620
621 lap_data_ptr = P_lap_data_ptr;
622 if (lap_data.state > LAP_HUNGUP) then call channel_manager$control (lap_data.devx, "hangup", null (), code);
623 return;
624
625
626
627
628
629 lap_simplex$priv_control:
630 entry (P_lap_data_ptr, P_order, P_info_ptr, P_code);
631
632 lap_data_ptr = P_lap_data_ptr;
633 order = P_order;
634 P_code = 0;
635
636 if order = "copy_meters" then do;
637 call channel_manager$control (lap_data.devx, order, P_info_ptr, P_code);
638 end;
639
640 else if order = "get_meters" then do;
641 call channel_manager$control (lap_data.devx, order, P_info_ptr, P_code);
642 end;
643
644 else P_code = error_table_$undefined_order_request;
645
646 return;
647
648
649
650
651
652 lap_simplex$hpriv_control:
653 entry (P_lap_data_ptr, P_order, P_info_ptr, P_code);
654
655 lap_data_ptr = P_lap_data_ptr;
656 order = P_order;
657 code = 0;
658
659 if order = "load_mpx" then do;
660 lap_load_info_ptr = P_info_ptr;
661
662 if lap_load_info.version ^= LAP_LOAD_INFO_VERSION_1 then do;
663 P_code = error_table_$unimplemented_version;
664 return;
665 end;
666
667 if lap_data.state > LAP_HUNGUP then do;
668 P_code = error_table_$action_not_performed;
669 return;
670 end;
671
672 string (lap_data.flags) = ""b;
673 lap_data.load_process_id = lap_load_info.process_id;
674 lap_data.load_event_channel = lap_load_info.event_channel;
675 lap_data.activate_order = lap_load_info.activate_order;
676
677 lap_data.activate_order.pad = ""b;
678 lap_data.activate_order.command = ACTIVATE_COMMAND;
679
680 lap_data.max_frame_size = divide (lap_data.activate_order.frame_size + 7, 8, 17, 0);
681
682 call channel_manager$control (lap_data.devx, "line_control", addr (lap_data.activate_order), code);
683 if code ^= 0 then do;
684 P_code = code;
685 return;
686 end;
687
688 call channel_manager$control (lap_data.devx, "listen", null (), code);
689 if code ^= 0 then do;
690 P_code = code;
691 return;
692 end;
693
694 lap_data.state = LAP_LISTENING;
695 end;
696
697 else code = error_table_$undefined_order_request;
698
699 P_code = code;
700 return;
701 %page;
702 dcl P_devx fixed bin parameter;
703 dcl P_info_ptr pointer parameter;
704 dcl P_miip pointer parameter;
705 dcl P_order char (*) parameter;
706 dcl P_lap_data_ptr pointer parameter;
707 dcl P_subchan_idx fixed bin parameter;
708 dcl P_int_type fixed bin parameter;
709 dcl P_int_data bit (72) aligned parameter;
710 dcl P_chain_ptr pointer parameter;
711 dcl P_mcl_info_ptr pointer parameter;
712 dcl P_modes char (*) parameter;
713 dcl P_code fixed bin (35) parameter;
714
715 dcl code fixed bin (35);
716 dcl ignore_code fixed bin (35);
717 dcl devx fixed bin;
718 dcl info_ptr pointer;
719 dcl order char (32);
720 dcl int_type fixed bin;
721 dcl int_data bit (72) aligned;
722 dcl chain_ptr pointer;
723 dcl next_block fixed bin (18);
724 dcl frame_end fixed bin;
725 dcl real_buffer_lth fixed bin;
726 dcl mode_idx fixed bin;
727
728 dcl 1 lap_down_status aligned like lap_line_status_info automatic;
729
730 dcl 1 lap_cmdr_status aligned based (addr (int_data)),
731 2 cmdr_status uns fixed bin (18) unaligned,
732 2 cmdr_bytes (3) unaligned,
733 3 pad bit (1) unaligned,
734 3 byte bit (8) unaligned,
735 2 pad bit (27) unaligned;
736
737 dcl init_sw bit (1) aligned static init ("0"b);
738
739 dcl pxss$ring_0_wakeup entry (bit (36) aligned, fixed bin (71), fixed bin (71), fixed bin (35));
740 dcl syserr entry options (variable);
741 dcl syserr$error_code entry options (variable);
742 dcl wire_proc$wire_me entry;
743
744 dcl error_table_$action_not_performed fixed bin (35) external static;
745 dcl error_table_$bad_arg fixed bin (35) external static;
746 dcl error_table_$bad_mode fixed bin (35) external static;
747 dcl error_table_$invalid_state fixed bin (35) external static;
748 dcl error_table_$noalloc fixed bin (35) external static;
749 dcl error_table_$null_info_ptr fixed bin (35) external static;
750 dcl error_table_$undefined_order_request fixed bin (35) external static;
751 dcl error_table_$unimplemented_version fixed bin (35) external static;
752
753 dcl tty_buf$lct_ptr pointer external static;
754
755 dcl MPX_UP fixed bin (71) static options (constant) init (1);
756 dcl MPX_DOWN fixed bin (71) static options (constant) init (2);
757 dcl MPX_MASKED fixed bin (71) static options (constant) init (3);
758
759 dcl cleanup condition;
760
761 dcl (addr, after, binary, collate9, currentsize, divide, hbound, lbound, pointer, null, rel, reverse, search, size,
762 string, substr, unspec) builtin;
763 %page;
764 %include lap_simplex_data;
765 %page;
766 %include lap_line_info;
767 %page;
768 %include mux_init_info;
769 %page;
770 %include lct;
771 %page;
772 %include channel_manager_dcls;
773 %page;
774 %include tty_space_man_dcls;
775 %page;
776 %include mcs_modes_change_list;
777 %page;
778 %include mode_string_info;
779 %page;
780 %include tty_buffer_block;
781 %page;
782 %include mcs_interrupt_info;
783 %page;
784 %include line_types;
785 %page;
786 %include tty_read_status_info;
787 %page;
788 %include syserr_codes;
789 %page;
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847 XXX
848
849
850
851
852
853 XXX
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871 XXX
872
873
874
875
876
877
878
879
880
881
882
883
884 end lap_simplex;