1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64 hasp_mpx:
65 procedure ();
66
67 return;
68
69
70
71
72 dcl P_hmd_ptr pointer parameter;
73 dcl P_subchannel_idx fixed binary parameter;
74 dcl P_code fixed binary (35) parameter;
75
76 dcl P_chain_ptr pointer parameter;
77
78 dcl P_more_input bit (1) aligned parameter;
79
80 dcl P_interrupt_type fixed binary parameter;
81 dcl P_interrupt_data bit (72) aligned parameter;
82
83 dcl P_order character (*) parameter;
84 dcl P_info_ptr pointer parameter;
85
86 dcl P_mclp pointer parameter;
87
88 dcl P_modes character (*) parameter;
89
90
91
92
93 dcl subchannel_idx fixed binary;
94 dcl code fixed binary (35);
95
96 dcl chain_ptr pointer;
97
98 dcl interrupt_type fixed binary;
99 dcl interrupt_data bit (72) aligned;
100
101 dcl order character (32);
102 dcl info_ptr pointer;
103
104
105
106
107 dcl ttybp pointer;
108
109 dcl 1 based_block_header unaligned based like TEMPLATE_HASP_BLOCK_HEADER;
110 dcl 1 based_block_trailer unaligned based like TEMPLATE_HASP_BLOCK_TRAILER;
111
112 dcl 1 based_signon_block unaligned based like TEMPLATE_HASP_SIGNON_BLOCK;
113
114 dcl 1 based_bad_bcb_block unaligned based like TEMPLATE_HASP_BAD_BCB_BLOCK;
115 dcl 1 based_bad_bcb_record unaligned based like TEMPLATE_HASP_BAD_BCB_RECORD;
116
117 dcl 1 based_sync_block unaligned based like TEMPLATE_HASP_SYNC_BLOCK;
118
119 dcl 1 based_rts_record unaligned based like TEMPLATE_HASP_RTS_RECORD;
120 dcl 1 based_rts_ack_record unaligned based like TEMPLATE_HASP_RTS_ACK_RECORD;
121
122 dcl needs_space bit (1) aligned;
123
124 dcl partial_record bit (1) aligned;
125
126
127
128 dcl long_record bit (1) aligned;
129
130
131 dcl previously_scanned_bufferp pointer;
132
133 dcl last_bufferp pointer;
134
135 dcl 1 abort_info aligned based (info_ptr),
136 2 resetwrite bit (1) unaligned,
137 2 resetread bit (1) unaligned;
138
139 dcl 1 write_status_info aligned based (info_ptr),
140 2 event_channel fixed binary (71),
141 2 output_pending bit (1);
142
143 dcl get_device_type_info fixed binary based (info_ptr);
144
145 dcl 1 sri aligned based (info_ptr) like signon_record_info;
146
147 dcl idx fixed binary;
148
149 dcl NUL character (1) static options (constant) initial ("^@");
150 dcl DLE character (1) static options (constant) initial ("^P");
151
152 dcl (LOG_AND_PRINT initial (0),
153 LOG_ONLY initial (5))
154 fixed binary static options (constant);
155
156 dcl (et_action_not_performed, et_bad_mode, et_incorrect_device_type, et_invalid_read, et_invalid_state, et_invalid_write,
157 et_long_record, et_noalloc, et_null_info_ptr, et_out_of_sequence, et_undefined_order_request,
158 et_unimplemented_version)
159 fixed binary (35) static;
160
161 dcl pds$process_id bit (36) aligned external;
162
163 dcl tty_buf$ bit (36) aligned external;
164
165 dcl (error_table_$action_not_performed, error_table_$bad_mode, error_table_$incorrect_device_type,
166 error_table_$invalid_read, error_table_$invalid_state, error_table_$invalid_write, error_table_$long_record,
167 error_table_$noalloc, error_table_$null_info_ptr, error_table_$out_of_sequence, error_table_$undefined_order_request,
168 error_table_$unimplemented_version)
169 fixed binary (35) external;
170
171 dcl mcs_trace entry () options (variable);
172 dcl mcs_trace$buffer_chain entry (fixed binary, pointer);
173 dcl pxss$ring_0_wakeup entry (bit (36) aligned, fixed binary (71), fixed binary (71), fixed binary (35));
174 dcl syserr entry () options (variable);
175 dcl wire_proc$wire_me entry ();
176
177 dcl (addr, binary, clock, copy, currentsize, divide, hbound, index, lbound, length, min, mod, null, pointer, rel, size,
178 string, substr, unspec)
179 builtin;
180 %page;
181
182
183 system_initialize:
184 entry ();
185
186 et_action_not_performed = error_table_$action_not_performed;
187 et_bad_mode = error_table_$bad_mode;
188 et_incorrect_device_type = error_table_$incorrect_device_type;
189 et_invalid_read = error_table_$invalid_read;
190 et_invalid_state = error_table_$invalid_state;
191 et_invalid_write = error_table_$invalid_write;
192 et_long_record = error_table_$long_record;
193 et_noalloc = error_table_$noalloc;
194 et_null_info_ptr = error_table_$null_info_ptr;
195 et_out_of_sequence = error_table_$out_of_sequence;
196 et_undefined_order_request = error_table_$undefined_order_request;
197 et_unimplemented_version = error_table_$unimplemented_version;
198
199 call wire_proc$wire_me ();
200
201 return;
202
203
204
205
206
207 dialup:
208 entry (P_hmd_ptr, P_subchannel_idx);
209
210 hmd_ptr = P_hmd_ptr;
211 subchannel_idx = P_subchannel_idx;
212 hste_ptr = addr (hmd.subchannels (subchannel_idx));
213
214 call signal_dialup ();
215
216 return;
217
218
219
220
221
222 crash:
223 entry (P_hmd_ptr);
224
225 ttybp = addr (tty_buf$);
226 hmd_ptr = P_hmd_ptr;
227
228 call crash_mpx ();
229
230 return;
231
232
233 ERROR_RETURN:
234 P_code = code;
235 return;
236 %page;
237
238
239 read:
240 entry (P_hmd_ptr, P_subchannel_idx, P_chain_ptr, P_more_input, P_code);
241
242 ttybp = addr (tty_buf$);
243 call setup_subchannel ();
244 P_chain_ptr = null ();
245 P_more_input = "0"b;
246 P_code = 0;
247
248 if hste.state ^= HSTE_DIALED then
249 return;
250
251 if hste.direction = HSTE_OUTPUT_ONLY then do;
252 P_code = et_invalid_read;
253 return;
254 end;
255
256
257
258
259 if hmd.flags.input_available then
260 call process_available_input_blocks ();
261
262 if (hmd.input.first_bufferp ^= null ()) then
263 call process_input_records ();
264
265 if hste.input.first_bufferp = null () then do;
266 hste.requested_input = "1"b;
267 go to RETURN_FROM_READ_CALL;
268 end;
269
270
271
272
273 P_chain_ptr = hste.input.first_bufferp;
274
275 last_bufferp = null ();
276 do blockp = hste.input.first_bufferp repeat (pointer (ttybp, buffer.next)) while (last_bufferp = null ());
277 if (buffer.next = 0) | buffer.break then
278 last_bufferp = blockp;
279 end;
280
281 if (last_bufferp -> buffer.next = 0) then
282 hste.input.first_bufferp, hste.input.last_bufferp = null ();
283 else do;
284 hste.input.first_bufferp = pointer (ttybp, last_bufferp -> buffer.next);
285 last_bufferp -> buffer.next = 0;
286 end;
287
288 hste.input.n_records = hste.input.n_records - 1;
289
290 if hste.input.n_records < hmd.max_device_input_records then
291 hmd.input_wabs (hste.device_wab_idx) = "1"b;
292
293
294
295
296
297 RETURN_FROM_READ_CALL:
298 call interrupt_subchannels_with_input ();
299
300 if (hmd.minor_state = HMD_REPROCESS) then
301 call process_loopback_records ();
302 else call process_output_block ();
303
304 return;
305 %page;
306
307
308 write:
309 entry (P_hmd_ptr, P_subchannel_idx, P_chain_ptr, P_code);
310
311 ttybp = addr (tty_buf$);
312 call setup_subchannel ();
313 chain_ptr = P_chain_ptr;
314
315 if hste.state ^= HSTE_DIALED then do;
316 call tty_space_man$free_chain (hste.devx, OUTPUT, chain_ptr);
317 P_chain_ptr = null ();
318 P_code = 0;
319 return;
320 end;
321
322 if hste.direction = HSTE_INPUT_ONLY then do;
323 call tty_space_man$free_chain (hste.devx, OUTPUT, chain_ptr);
324 P_chain_ptr = null ();
325 P_code = et_invalid_write;
326 return;
327 end;
328
329 P_code = 0;
330
331
332
333
334 call enqueue_subchannel_for_output ();
335
336
337
338
339 if (hmd.minor_state ^= HMD_NORMAL) |
340 hmd.suspend_all_output |
341 ^hmd.output_wabs (hste.device_wab_idx) |
342 (hste.loopback.first_bufferp ^= null ()) then
343 go to RETURN_FROM_WRITE_CALL;
344
345
346
347
348 if hste.output.first_bufferp ^= null () then do;
349 hste.output.last_bufferp -> buffer.next = binary (rel (chain_ptr), 18, 0);
350 P_chain_ptr,
351 chain_ptr = hste.output.first_bufferp;
352 hste.output.first_bufferp, hste.output.last_bufferp = null ();
353 end;
354
355
356
357
358 partial_record = "0"b;
359 long_record = "0"b;
360
361
362 if (hste.minor_state = HSTE_NORMAL) |
363 (hste.device_type = HASP_CONSOLE) |
364 ^hmd.rts_mode
365 then do;
366
367
368
369
370
371
372 call process_output_records ();
373 if needs_space then go to CANT_FINISH_WRITE_CALL;
374 end;
375
376
377 else if (hste.minor_state = HSTE_SEND_RTS) then
378
379
380
381
382 hmd.send_rts (hste.device_wab_idx) = "1"b;
383
384
385 else if (hste.minor_state = HSTE_WAIT_RTS_ACK) then
386 if hmd.input.first_bufferp ^= null ()
387 then do;
388
389
390
391
392 call process_input_records ();
393 call interrupt_subchannels_with_input ();
394
395 if hste.minor_state = HSTE_NORMAL
396 then do;
397 call process_output_records ();
398 if needs_space then go to CANT_FINISH_WRITE_CALL;
399 end;
400 end;
401
402
403
404
405
406
407
408
409
410 if long_record then
411 P_code = et_long_record;
412
413 else if partial_record & (chain_ptr ^= null ())
414 then do;
415
416 hste.output.first_bufferp = chain_ptr;
417
418 do last_bufferp = hste.output.first_bufferp repeat (pointer (ttybp, last_bufferp -> buffer.next))
419 while (rel (last_bufferp) ^= ""b);
420 if (last_bufferp -> buffer.next) = 0 then hste.output.last_bufferp = last_bufferp;
421 end;
422
423 chain_ptr = null ();
424 end;
425
426 P_chain_ptr = chain_ptr;
427
428 if chain_ptr = null () then do;
429 call dequeue_subchannel_for_output ();
430 call channel_manager$interrupt (hste.devx, SEND_OUTPUT, ""b);
431 end;
432
433
434 RETURN_FROM_WRITE_CALL:
435 if (hmd.minor_state = HMD_REPROCESS) then
436 call process_loopback_records ();
437 else call process_output_block ();
438
439 return;
440
441
442
443
444 CANT_FINISH_WRITE_CALL:
445 P_chain_ptr = chain_ptr;
446
447 call tty_space_man$needs_space (hmd.devx);
448
449 return;
450 %page;
451
452
453 interrupt:
454 entry (P_hmd_ptr, P_interrupt_type, P_interrupt_data);
455
456 ttybp = addr (tty_buf$);
457 hmd_ptr = P_hmd_ptr;
458 hste_ptr = null ();
459 interrupt_type = P_interrupt_type;
460 interrupt_data = P_interrupt_data;
461
462 if (interrupt_type < lbound (INTERRUPT, 1)) | (interrupt_type > hbound (INTERRUPT, 1)) then
463 return;
464
465 go to INTERRUPT (interrupt_type);
466
467
468 INTERRUPT (1):
469 if hmd.state ^= HMD_LOADING then return;
470 unspec (hmd.dialup_info) = interrupt_data;
471 call do_line_control (SET_HASP_MODE, 0, 0, 0);
472 call do_line_control (CONFIGURE, 3, 0, 0);
473 call do_line_control (SET_MASTER_SLAVE_MODE,
474 binary ((hmd.type = HASP_WORKSTATION), 17, 0), 0, 0);
475 call do_line_control (SET_HASP_TIMERS, hmd.ic_timeout, hmd.receive_timeout, hmd.transmit_timeout);
476 call do_line_control (SET_NAK_LIMIT, hmd.max_naks, 0, 0);
477 call do_line_control (ACCEPT_BID, 0, 0, 0);
478 call channel_manager$control (hmd.devx, "set_input_message_size", addr (hmd.max_block_size), code);
479
480 return;
481
482 LOADING_FAILS:
483 return;
484
485
486 INTERRUPT (2):
487 call crash_mpx ();
488 call pxss$ring_0_wakeup (hmd.loader_process_id, hmd.loader_event_channel, HASP_MPX_DOWN, code);
489 return;
490
491
492 INTERRUPT (3):
493 call crash_mpx ();
494 return;
495
496
497 INTERRUPT (4):
498 hmd.send_output = "1"b;
499 if (hmd.state < HMD_LOADED)
500 then;
501 else if (hmd.minor_state = HMD_REPROCESS) then
502 call process_loopback_records ();
503 else call process_output_block ();
504 return;
505
506
507 INTERRUPT (5):
508 hmd.flags.input_available = "1"b;
509 if (hmd.state < HMD_LOADED)
510 then;
511 else call interrupt_subchannels_requesting_input ();
512 return;
513
514
515
516 INTERRUPT (6):
517 hmd.flags.input_available = "0"b;
518 if (hmd.state < HMD_LOADED)
519 then;
520 else do;
521 unspec (rtx_info) = interrupt_data;
522 chain_ptr = pointer (ttybp, rtx_info.chain_head);
523 if hmd.trace_mode then
524 call trace_block (chain_ptr, INPUT);
525 call process_input_block (chain_ptr);
526 if (hmd.input.first_bufferp ^= null ()) & ^hmd.retry_process_input then
527 call process_input_records ();
528 call interrupt_subchannels_with_input ();
529 if (hmd.minor_state = HMD_REPROCESS) then
530 call process_loopback_records ();
531 else call process_output_block ();
532
533 end;
534 return;
535
536
537 INTERRUPT (7):
538 return;
539
540
541 INTERRUPT (8):
542 return;
543
544
545 INTERRUPT (9):
546 unspec (line_stat) = interrupt_data;
547 call process_line_status ();
548 return;
549
550
551 INTERRUPT (10):
552 return;
553
554
555 INTERRUPT (11):
556 return;
557
558
559 INTERRUPT (12):
560 if hmd.state < HMD_LOADED then return;
561 call process_space_available ();
562 return;
563
564 INTERRUPT (13):
565 INTERRUPT (14):
566 INTERRUPT (15):
567 INTERRUPT (16):
568 return;
569
570 INTERRUPT (17):
571 call crash_mpx ();
572 call pxss$ring_0_wakeup (hmd.loader_process_id, hmd.loader_event_channel, HASP_MPX_MASKED, code);
573 return;
574
575 %page;
576
577
578 control:
579 entry (P_hmd_ptr, P_subchannel_idx, P_order, P_info_ptr, P_code);
580
581 ttybp = addr (tty_buf$);
582 call setup_subchannel ();
583 order = P_order;
584 info_ptr = P_info_ptr;
585 code = 0;
586
587 if (order = "listen") then
588 if (hmd.state < HMD_LOADED) then
589 code = et_invalid_state;
590 else do;
591 if (hste.state < HSTE_LISTENING) then
592 hste.state = HSTE_LISTENING;
593 if (hmd.minor_state < HMD_NORMAL) then
594 if (hste.device_type = HASP_CONSOLE) & (hmd.state = HMD_STARTED) &
595 (hste.state = HSTE_LISTENING) then
596 call signal_dialup ();
597 else;
598 else
599 if (hmd.state = HMD_STARTED) & (hste.state = HSTE_LISTENING) then
600 call signal_dialup ();
601 end;
602
603 else if (order = "hangup") then
604 call signal_hangup (HANGUP);
605
606 else if (order = "wru") then
607 call channel_manager$interrupt (hste.devx, WRU_TIMEOUT, ""b);
608
609 else if (order = "abort") then
610 if (info_ptr = null ()) then
611 code = et_null_info_ptr;
612 else do;
613 if abort_info.resetwrite & (hste.direction ^= HSTE_INPUT_ONLY)
614 then do;
615 if (hste.output.first_bufferp ^= null ()) then do;
616 call tty_space_man$free_chain (hste.devx, OUTPUT, hste.output.first_bufferp);
617 hste.output.first_bufferp, hste.output.last_bufferp = null ();
618 end;
619 call channel_manager$interrupt (hste.devx, SEND_OUTPUT, ""b);
620 end;
621 if abort_info.resetread & (hste.input.first_bufferp ^= null ())
622 then do;
623 call tty_space_man$free_chain (hste.devx, INPUT, hste.input.first_bufferp);
624 hste.input.n_records = 0;
625 hste.input.first_bufferp, hste.input.last_bufferp = null ();
626 if ^hmd.input_wabs (hste.device_wab_idx)
627 then do;
628 hmd.input_wabs (hste.device_wab_idx) = "1"b;
629 if (hmd.minor_state = HMD_REPROCESS) then
630 call process_loopback_records ();
631 else call process_output_block ();
632 end;
633 end;
634 end;
635
636 else if (order = "write_status") then
637 if (info_ptr = null ()) then
638 code = et_null_info_ptr;
639 else if (hste.output.first_bufferp ^= null ()) then
640 write_status_info.output_pending = "1"b;
641 else write_status_info.output_pending = "0"b;
642
643 else if (order = "get_device_type") then
644 if (info_ptr = null ()) then
645 code = et_null_info_ptr;
646 else get_device_type_info = hste.device_type;
647
648 else if (order = "signon_record") then
649 if (info_ptr = null ()) then
650 code = et_null_info_ptr;
651 else if (hmd.type = HASP_WORKSTATION) then
652 if (hste.device_type ^= HASP_CONSOLE) then
653 code = et_incorrect_device_type;
654 else if ^hmd.signon_mode then
655 code = et_invalid_state;
656 else if (hmd.signon_data_ptr = null ()) &
657 (hmd.minor_state = HMD_SEND_SIGNON) then
658 if (sri.version ^= SIGNON_RECORD_INFO_VERSION_1) then
659 code = et_unimplemented_version;
660 else do;
661 call tty_space_man$get_space (size (hmd_signon_data), hsd_ptr);
662 if hsd_ptr ^= null ()
663 then do;
664 hmd.signon_data_ptr = hsd_ptr;
665 hmd_signon_data.processid = pds$process_id;
666 hmd_signon_data.event_channel = sri.event_channel;
667 hmd_signon_data.record = sri.record;
668 call process_output_block ();
669 end;
670 else code = et_noalloc;
671 end;
672 else code = et_out_of_sequence;
673 else code = et_undefined_order_request;
674
675 else if (order = "no_signon_record") then
676 if (hmd.type = HASP_WORKSTATION) then
677 if hmd.signon_mode then
678 code = et_invalid_state;
679 else;
680 else code = et_undefined_order_request;
681
682 else if (order = "copy_meters") then
683 hste.saved_meters_ptr -> hasp_subchannel_meters = hste.meters;
684
685 else if (order = "get_meters") then
686 if (info_ptr = null ()) then
687 code = et_null_info_ptr;
688 else if (info_ptr -> get_comm_meters_info.version ^= GET_COMM_METERS_INFO_VERSION_1) then
689 code = et_unimplemented_version;
690 else do;
691 hsmd_ptr = info_ptr -> get_comm_meters_info.parent_ptr;
692 if hsmd_ptr ^= null () then
693 if (hasp_subchannel_meters_data.version ^= HASP_SUBCHANNEL_METERS_DATA_VERSION_1) then
694 code = et_unimplemented_version;
695 else do;
696 string (hasp_subchannel_meters_data.flags) = ""b;
697 hasp_subchannel_meters_data.report_input_meters = (hste.direction ^= HSTE_OUTPUT_ONLY);
698 hasp_subchannel_meters_data.report_output_meters = (hste.direction ^= HSTE_INPUT_ONLY);
699 hasp_subchannel_meters_data.current_meters = hste.meters;
700 hasp_subchannel_meters_data.saved_meters = hste.saved_meters_ptr -> hasp_subchannel_meters;
701 end;
702 end;
703
704 else code = et_undefined_order_request;
705
706 P_code = code;
707 return;
708 %page;
709
710
711 check_modes:
712 entry (P_hmd_ptr, P_subchannel_idx, P_mclp, P_code);
713
714
715
716
717 set_modes:
718 entry (P_hmd_ptr, P_subchannel_idx, P_mclp, P_code);
719
720 call setup_subchannel ();
721 mclp = P_mclp;
722 P_code = 0;
723
724 do idx = 1 to mcl.n_entries;
725
726 mclep = addr (mcl.entries (idx));
727
728 mcle.mpx_mode = (mcle.mode_name = "rawi") |
729 (mcle.mode_name = "rawo") | (mcle.mode_name = "echoplex");
730
731 if mcle.mpx_mode then
732
733 if ((mcle.mode_name ^= "rawi") & (mcle.mode_name ^= "rawo") & (mcle.mode_name ^= "echoplex")) |
734 ((mcle.mode_name = "rawi") & ^mcle.mode_switch) |
735 ((mcle.mode_name = "rawo") & ^mcle.mode_switch) |
736 ((mcle.mode_name = "echoplex") & mcle.mode_switch)
737 then do;
738 mcle.error = "1"b;
739 P_code = et_bad_mode;
740 end;
741 end;
742
743 return;
744
745
746
747
748
749 get_modes:
750 entry (P_hmd_ptr, P_subchannel_idx, P_modes, P_code);
751
752 P_modes = "";
753 P_code = 0;
754
755 return;
756 %page;
757
758
759 setup_subchannel:
760 procedure ();
761
762 hmd_ptr = P_hmd_ptr;
763
764 if hmd.state < HMD_LOADED then do;
765 code = et_action_not_performed;
766 go to ERROR_RETURN;
767 end;
768
769 subchannel_idx = P_subchannel_idx;
770 hste_ptr = addr (hmd.subchannels (subchannel_idx));
771
772 return;
773
774 end setup_subchannel;
775 %page;
776
777
778
779
780
781
782 signal_dialup:
783 procedure ();
784
785 dcl saved_input_available bit (1) aligned;
786
787 if (hmd.minor_state_stack = null ()) & (hste.loopback.first_bufferp = null ()) then
788
789
790
791
792 if hmd.rts_mode & (hste.device_type ^= HASP_CONSOLE) & (hste.direction ^= HSTE_INPUT_ONLY) then
793 hste.minor_state = HSTE_SEND_RTS;
794 else hste.minor_state = HSTE_NORMAL;
795
796 hste.next_subchannel_for_output = 0;
797
798 hste.output.first_bufferp, hste.output.last_bufferp = null ();
799
800 saved_input_available = hste.flags.input_available;
801 string (hste.flags) = ""b;
802 hste.flags.input_available = saved_input_available;
803
804 if (hste.direction = HSTE_INPUT_ONLY) | (hste.direction = HSTE_INPUT_OUTPUT)
805 then do;
806 hmd.input_wabs (hste.device_wab_idx) = "1"b;
807 hmd.send_rts_ack (hste.device_wab_idx) = "0"b;
808
809 end;
810 else hmd.send_rts (hste.device_wab_idx) = "0"b;
811
812 hste.dialup_info = hmd.dialup_info;
813
814 hste.state = HSTE_DIALED;
815
816 call channel_manager$interrupt (hste.devx, DIALUP, unspec (hste.dialup_info));
817
818 if (hste.direction ^= HSTE_INPUT_ONLY) then
819 call channel_manager$interrupt (hste.devx, SEND_OUTPUT, ""b);
820
821 if (hste.direction ^= HSTE_OUTPUT_ONLY) then
822 if hste.flags.input_available then do;
823 call channel_manager$interrupt (hste.devx, INPUT_AVAILABLE, ""b);
824 hste.flags.input_available = "0"b;
825 end;
826
827 return;
828
829 end signal_dialup;
830 %page;
831
832
833 signal_hangup:
834 procedure (P_interrupt_type);
835
836 dcl P_interrupt_type fixed binary;
837
838 hste.state = HSTE_HUNGUP;
839
840 if hste.input.first_bufferp ^= null () then
841 call tty_space_man$free_chain (hste.devx, INPUT, hste.input.first_bufferp);
842
843 if hste.output.first_bufferp ^= null () then
844 call tty_space_man$free_chain (hste.devx, OUTPUT, hste.output.first_bufferp);
845
846 call dequeue_subchannel_for_output ();
847
848 hste.input.n_records = 0;
849
850 hste.input.first_bufferp, hste.input.last_bufferp,
851 hste.output.first_bufferp, hste.output.last_bufferp = null ();
852
853 string (hste.flags) = ""b;
854
855 if (hste.direction = HSTE_INPUT_ONLY) | (hste.direction = HSTE_INPUT_OUTPUT)
856 then do;
857 hmd.input_wabs (hste.device_wab_idx) = "0"b;
858 hmd.send_rts_ack (hste.device_wab_idx) = "0"b;
859 end;
860 else hmd.send_rts (hste.device_wab_idx) = "0"b;
861
862 call channel_manager$interrupt (hste.devx, P_interrupt_type, ""b);
863
864 return;
865
866 end signal_hangup;
867 %page;
868
869
870
871 load_mpx: procedure ();
872
873 dcl (saved_send_output, saved_input_available) bit (1) aligned;
874 dcl idx fixed binary;
875
876 hmd.state = HMD_LOADED;
877
878 hmd.time_mpx_booted = clock ();
879
880 if (hmd.type = HASP_WORKSTATION) & hmd.signon_mode then
881 hmd.minor_state = HMD_SEND_SIGNON;
882 else hmd.minor_state = HMD_NORMAL;
883
884 saved_send_output = hmd.send_output;
885 saved_input_available = hmd.flags.input_available;
886
887 string (hmd.flags) = ""b;
888
889 hmd.send_output = saved_send_output;
890 hmd.flags.input_available = saved_input_available;
891
892 hmd.suspend_all_output = "1"b;
893 hmd.first_foreign_block = "1"b;
894 unspec (hmd.foreign_fcs_bytes) = "700600"b3;
895
896 hmd.suspend_all_input = "1"b;
897 hmd.reset_local_block_count = "1"b;
898 unspec (hmd.local_fcs_bytes) = "700600"b3;
899
900 string (hmd.input_wabs) = ""b;
901 string (hmd.output_wabs) = ""b;
902 string (hmd.send_rts) = ""b;
903 string (hmd.send_rts_ack) = ""b;
904
905 hmd.minor_state_stack,
906 hmd.loopback_block_chain_stack = null ();
907
908 hmd.output_chain_ptr, hmd.signon_data_ptr,
909 hmd.input.first_bufferp, hmd.input.last_bufferp,
910 hmd.loopback.first_bufferp, hmd.loopback.last_bufferp,
911 hmd.output_block.first_bufferp, hmd.output_block.last_bufferp = null ();
912
913 hmd.output_block.subchannel_idx, hmd.output_block.tally = 0;
914
915 do idx = 1 to hmd.n_subchannels;
916 hmd.subchannels(idx).state = HSTE_HUNGUP;
917 hmd.subchannels(idx).input.n_records = 0;
918 hmd.subchannels(idx).input.first_bufferp,
919 hmd.subchannels(idx).input.last_bufferp = null ();
920 hmd.subchannels(idx).loopback.n_records = 0;
921 hmd.subchannels(idx).loopback.first_bufferp, hmd.subchannels(idx).loopback.last_bufferp = null ();
922 end;
923
924 call pxss$ring_0_wakeup (hmd.loader_process_id, hmd.loader_event_channel, HASP_MPX_UP, code);
925
926 return;
927
928 end load_mpx;
929 %page;
930
931
932 crash_mpx:
933 procedure ();
934
935 dcl (old_state, idx) fixed binary;
936
937
938 old_state = hmd.state;
939
940 hmd.state = HMD_DOWN;
941
942 if old_state < HMD_LOADED then
943 return;
944
945 if (hmd.minor_state = HMD_SEND_SIGNON) | (hmd.minor_state = HMD_WAIT_SIGNON_RESPONSE)
946 then do;
947 hsd_ptr = hmd.signon_data_ptr;
948 if hsd_ptr ^= null () then
949 call pxss$ring_0_wakeup (hmd_signon_data.processid, hmd_signon_data.event_channel,
950 HASP_SIGNON_HANGUP, code);
951 end;
952
953 if hmd.output_chain_ptr ^= null () then
954 call tty_space_man$free_chain (hmd.devx, OUTPUT, hmd.output_chain_ptr);
955
956 if hmd.input.first_bufferp ^= null () then
957 call tty_space_man$free_chain (hmd.devx, INPUT, hmd.input.first_bufferp);
958
959 if hmd.loopback.first_bufferp ^= null () then
960 call tty_space_man$free_chain (hmd.devx, INPUT, hmd.loopback.first_bufferp);
961
962 if hmd.output_block.first_bufferp ^= null () then
963 call tty_space_man$free_chain (hmd.devx, OUTPUT, hmd.output_block.first_bufferp);
964
965 if hmd.signon_data_ptr ^= null () then
966 call tty_space_man$free_space (currentsize (hmd.signon_data_ptr -> hmd_signon_data),
967 hmd.signon_data_ptr);
968
969 call empty_minor_state_stack ();
970 call empty_loopback_block_chain_stack ();
971
972 hmd.output_chain_ptr, hmd.signon_data_ptr,
973 hmd.input.first_bufferp, hmd.input.last_bufferp,
974 hmd.loopback.first_bufferp, hmd.loopback.last_bufferp,
975 hmd.output_block.first_bufferp, hmd.output_block.last_bufferp = null ();
976
977 hmd.output_block.subchannel_idx, hmd.output_block.tally = 0;
978
979 hmd.subchannels_for_output = 0;
980
981 string (hmd.flags) = ""b;
982
983 do idx = 1 to hmd.n_subchannels;
984 hste_ptr = addr (hmd.subchannels (idx));
985 call signal_hangup (CRASH);
986 end;
987
988 return;
989
990 end crash_mpx;
991 %page;
992
993
994
995
996
997 minor_state_stack_manager:
998 procedure ();
999
1000 return;
1001
1002
1003 dcl P_new_minor_state fixed binary parameter;
1004
1005 dcl previous_msse_ptr pointer;
1006
1007 dcl idx fixed binary;
1008
1009
1010
1011
1012
1013 push_minor_state:
1014 entry (P_new_minor_state);
1015
1016 call tty_space_man$get_space (size (msse), msse_ptr);
1017 if msse_ptr = null () then do;
1018 call syserr (LOG_AND_PRINT,
1019 "hasp_mpx (line ^a): No space available to preserve minor state; line will be hungup.",
1020 hmd.name);
1021 call channel_manager$control (hmd.devx, "hangup", null (), code);
1022 return;
1023 end;
1024
1025 do idx = 1 to hmd.n_subchannels;
1026 msse.subchannels(idx).loopback = hmd.subchannels(idx).loopback;
1027 hmd.subchannels(idx).loopback.n_records = 0;
1028 hmd.subchannels(idx).loopback.first_bufferp, hmd.subchannels(idx).loopback.last_bufferp = null ();
1029 end;
1030
1031 msse.minor_state = hmd.minor_state;
1032 hmd.minor_state = P_new_minor_state;
1033
1034 msse.previous = hmd.minor_state_stack;
1035 hmd.minor_state_stack = msse_ptr;
1036
1037 return;
1038
1039
1040
1041
1042 pop_minor_state:
1043 entry ();
1044
1045 if hmd.minor_state_stack = null () then
1046 return;
1047
1048 msse_ptr = hmd.minor_state_stack;
1049
1050 do idx = 1 to hmd.n_subchannels;
1051 if msse.subchannels(idx).loopback.first_bufferp ^= null () then do;
1052 hmd.subchannels(idx).loopback.n_records =
1053 hmd.subchannels(idx).loopback.n_records + msse.subchannels(idx).loopback.n_records;
1054 if hmd.subchannels(idx).loopback.last_bufferp = null () then
1055 hmd.subchannels(idx).loopback.first_bufferp = msse.subchannels(idx).loopback.first_bufferp;
1056 else hmd.subchannels(idx).loopback.last_bufferp -> buffer.next =
1057 binary (rel (msse.subchannels(idx).loopback.first_bufferp), 18, 0);
1058 hmd.subchannels(idx).loopback.last_bufferp = msse.subchannels(idx).loopback.last_bufferp;
1059 end;
1060 end;
1061
1062 hmd.minor_state = msse.minor_state;
1063 hmd.minor_state_stack = msse.previous;
1064
1065 call tty_space_man$free_space (currentsize (msse), msse_ptr);
1066
1067 return;
1068
1069
1070
1071
1072
1073 empty_minor_state_stack:
1074 entry ();
1075
1076 do msse_ptr = hmd.minor_state_stack
1077 repeat (previous_msse_ptr) while (msse_ptr ^= null ());
1078
1079 do idx = 1 to hmd.n_subchannels;
1080 if msse.subchannels(idx).loopback.first_bufferp ^= null () then
1081 call tty_space_man$free_chain (hmd.subchannels(idx).devx, OUTPUT,
1082 msse.subchannels(idx).loopback.first_bufferp);
1083 end;
1084
1085 previous_msse_ptr = msse.previous;
1086
1087 call tty_space_man$free_space (currentsize (msse), msse_ptr);
1088 end;
1089
1090 hmd.minor_state_stack = null ();
1091
1092 return;
1093
1094 end minor_state_stack_manager;
1095 %page;
1096
1097
1098
1099 loopback_block_chain_stack_manager:
1100 procedure ();
1101
1102 return;
1103
1104 dcl previous_lbcse_ptr pointer;
1105
1106
1107
1108
1109 push_loopback_block_chain:
1110 entry ();
1111
1112 call tty_space_man$get_space (size (lbcse), lbcse_ptr);
1113 if lbcse_ptr = null () then do;
1114 call syserr (LOG_AND_PRINT,
1115 "hasp_mpx (line ^a): No space available to save loopback chain; line will be hungup.",
1116 hmd.name);
1117 call channel_manager$control (hmd.devx, "hangup", null (), code);
1118 return;
1119 end;
1120
1121 lbcse.loopback = hmd.loopback;
1122 hmd.loopback = null ();
1123
1124 lbcse.previous = hmd.loopback_block_chain_stack;
1125 hmd.loopback_block_chain_stack = lbcse_ptr;
1126
1127 return;
1128
1129
1130
1131
1132
1133 pop_loopback_block_chain:
1134 entry ();
1135
1136 if hmd.loopback_block_chain_stack = null () then
1137 return;
1138
1139 lbcse_ptr = hmd.loopback_block_chain_stack;
1140
1141 if lbcse.loopback.first_bufferp ^= null () then do;
1142 if hmd.loopback.last_bufferp = null () then
1143 hmd.loopback.first_bufferp = lbcse.loopback.first_bufferp;
1144 else hmd.loopback.last_bufferp -> buffer.next = binary (rel (lbcse.loopback.first_bufferp), 18, 0);
1145 hmd.loopback.last_bufferp = lbcse.loopback.last_bufferp;
1146 end;
1147
1148 hmd.loopback_block_chain_stack = lbcse.previous;
1149
1150 call tty_space_man$free_space (currentsize (lbcse), lbcse_ptr);
1151
1152 return;
1153
1154
1155
1156
1157
1158 empty_loopback_block_chain_stack:
1159 entry ();
1160
1161 do lbcse_ptr = hmd.loopback_block_chain_stack
1162 repeat (previous_lbcse_ptr) while (lbcse_ptr ^= null ());
1163
1164 previous_lbcse_ptr = lbcse.previous;
1165
1166 if lbcse.loopback.first_bufferp ^= null () then
1167 call tty_space_man$free_chain (hmd.devx, INPUT, lbcse.loopback.first_bufferp);
1168
1169 call tty_space_man$free_space (currentsize (lbcse), lbcse_ptr);
1170 end;
1171
1172 hmd.loopback_block_chain_stack = null ();
1173
1174 return;
1175
1176 end loopback_block_chain_stack_manager;
1177 %page;
1178
1179
1180 enqueue_subchannel_for_output:
1181 procedure ();
1182
1183 dcl idx fixed binary;
1184
1185 do idx = hmd.subchannels_for_output.first
1186 repeat (hmd.subchannels(idx).next_subchannel_for_output)
1187 while (idx ^= 0);
1188 if (idx = hste.subchannel_idx) then return;
1189 end;
1190
1191 hste.holding_output = "1"b;
1192
1193 if (hmd.subchannels_for_output.first = 0) then
1194 hmd.subchannels_for_output.first = hste.subchannel_idx;
1195
1196 else hmd.subchannels(hmd.subchannels_for_output.last).next_subchannel_for_output = hste.subchannel_idx;
1197
1198
1199 hmd.subchannels_for_output.last = hste.subchannel_idx;
1200 hste.next_subchannel_for_output = 0;
1201
1202 return;
1203
1204 end enqueue_subchannel_for_output;
1205 %page;
1206
1207
1208 dequeue_subchannel_for_output:
1209 procedure ();
1210
1211 dcl previous_subchannel_idx fixed binary;
1212
1213 if hste.holding_output then do;
1214
1215 previous_subchannel_idx = 0;
1216
1217 if (hmd.subchannels_for_output.first = hste.subchannel_idx) then
1218 hmd.subchannels_for_output.first = hste.next_subchannel_for_output;
1219
1220 else
1221 do previous_subchannel_idx = hmd.subchannels_for_output.first
1222 repeat (hmd.subchannels(previous_subchannel_idx).next_subchannel_for_output)
1223 while (previous_subchannel_idx ^= 0);
1224 if (hmd.subchannels(previous_subchannel_idx).next_subchannel_for_output = hste.subchannel_idx)
1225 then do;
1226 hmd.subchannels(previous_subchannel_idx).next_subchannel_for_output =
1227 hste.next_subchannel_for_output;
1228 go to EXIT_SEARCH_FOR_PREVIOUS_LOOP;
1229 end;
1230 end;
1231
1232 EXIT_SEARCH_FOR_PREVIOUS_LOOP:
1233 if (hmd.subchannels_for_output.last = hste.subchannel_idx) then
1234 hmd.subchannels_for_output.last = previous_subchannel_idx;
1235 end;
1236
1237 hste.next_subchannel_for_output = 0;
1238
1239 hste.holding_output = "0"b;
1240
1241 return;
1242
1243 end dequeue_subchannel_for_output;
1244 %page;
1245
1246
1247 interrupt_subchannels_with_output:
1248 procedure ();
1249
1250 dcl saved_hste_ptr pointer;
1251 dcl queue (17) fixed binary;
1252 dcl (n_entries, idx) fixed binary;
1253
1254 saved_hste_ptr = hste_ptr;
1255
1256 n_entries = 0;
1257 do idx = hmd.subchannels_for_output.first
1258 repeat (hmd.subchannels(idx).next_subchannel_for_output) while (idx ^= 0);
1259 n_entries = n_entries + 1;
1260 queue (n_entries) = hmd.subchannels(idx).subchannel_idx;
1261 end;
1262
1263 if (n_entries = 0) then return;
1264
1265 do idx = 1 to n_entries;
1266 hste_ptr = addr (hmd.subchannels (queue (idx)));
1267 call dequeue_subchannel_for_output ();
1268 call channel_manager$interrupt_later (hste.devx, SEND_OUTPUT, ""b);
1269 end;
1270
1271 hste_ptr = saved_hste_ptr;
1272
1273 return;
1274
1275 end interrupt_subchannels_with_output;
1276
1277
1278
1279
1280
1281 interrupt_subchannels_with_input:
1282 procedure ();
1283
1284 dcl idx fixed binary;
1285
1286 do idx = 1 to hmd.n_subchannels;
1287 if hmd.subchannels(idx).input_available | (hmd.subchannels(idx).input.first_bufferp ^= null ())
1288 then do;
1289 hmd.subchannels(idx).requested_input, hmd.subchannels(idx).input_available = "0"b;
1290 call channel_manager$interrupt (hmd.subchannels(idx).devx, INPUT_AVAILABLE, ""b);
1291 end;
1292 end;
1293
1294 return;
1295
1296 end interrupt_subchannels_with_input;
1297 %page;
1298
1299
1300
1301 interrupt_subchannels_requesting_input:
1302 procedure ();
1303
1304 dcl sent_interrupt bit (1) aligned;
1305 dcl idx fixed binary;
1306
1307 sent_interrupt = "0"b;
1308
1309 do idx = 1 to hmd.n_subchannels;
1310 if hmd.subchannels(idx).requested_input then do;
1311 hmd.subchannels(idx).requested_input, hmd.subchannels(idx).input_available = "0"b;
1312 call channel_manager$interrupt (hmd.subchannels(idx).devx, INPUT_AVAILABLE, ""b);
1313 sent_interrupt = "1"b;
1314 end;
1315 end;
1316
1317 if ^sent_interrupt then
1318 call channel_manager$interrupt (hmd.subchannels(hmd.console_hste_idx).devx, INPUT_AVAILABLE, ""b);
1319
1320 return;
1321
1322 end interrupt_subchannels_requesting_input;
1323
1324
1325
1326
1327
1328
1329 process_available_input_blocks:
1330 procedure ();
1331
1332 dcl first_bufferp pointer;
1333 dcl more_input bit (1) aligned;
1334
1335
1336 more_input = hmd.flags.input_available;
1337
1338 do while (more_input);
1339 call channel_manager$read (hmd.devx, first_bufferp, more_input, code);
1340 if code ^= 0 then go to ERROR_RETURN;
1341 if hmd.trace_mode then
1342 call trace_block (first_bufferp, INPUT);
1343 if first_bufferp ^= null () then
1344 call process_input_block (first_bufferp);
1345 end;
1346
1347 hmd.flags.input_available = "0"b;
1348
1349 return;
1350
1351 end process_available_input_blocks;
1352 %page;
1353
1354
1355
1356
1357
1358 process_input_block:
1359 procedure (P_first_bufferp);
1360
1361 dcl P_first_bufferp pointer parameter;
1362
1363 dcl foreign_bcb_char character (1) unaligned;
1364 dcl foreign_fcs_chars character (2) unaligned;
1365
1366 dcl 1 foreign_bcb unaligned based (addr (foreign_bcb_char)) like hasp_bcb_byte;
1367 dcl 1 foreign_fcs unaligned based (addr (foreign_fcs_chars)) like hasp_fcs_bytes;
1368
1369 dcl (first_bufferp, last_bufferp, next_to_last_bufferp) pointer;
1370
1371 dcl first_char character (1) aligned;
1372
1373
1374 first_bufferp = P_first_bufferp;
1375
1376 next_to_last_bufferp = null ();
1377 do blockp = first_bufferp repeat (pointer (ttybp, buffer.next)) while (rel (blockp) ^= ""b);
1378 if buffer.next = 0 then
1379 last_bufferp = blockp;
1380 else next_to_last_bufferp = blockp;
1381 end;
1382
1383 if last_bufferp -> buffer.tally > 2 then
1384 last_bufferp -> buffer.tally = last_bufferp -> buffer.tally - 2;
1385 else do;
1386 if next_to_last_bufferp = null () then go to BAD_INPUT_BLOCK;
1387 next_to_last_bufferp -> buffer.tally =
1388 next_to_last_bufferp -> buffer.tally - 2 + last_bufferp -> buffer.tally;
1389 call tty_space_man$free_buffer (hmd.devx, INPUT, last_bufferp);
1390 next_to_last_bufferp -> buffer.next = 0;
1391 last_bufferp = next_to_last_bufferp;
1392 end;
1393
1394 first_char = substr_of_chain (1, 1);
1395 call delete_leading_text (2);
1396
1397 if first_char = DLE then
1398 call strip_dles ();
1399
1400 foreign_bcb_char = substr_of_chain (1, 1);
1401 foreign_fcs_chars = substr_of_chain (2, 2);
1402
1403 call delete_leading_text (3);
1404
1405
1406 if ^foreign_fcs.returned_data then
1407
1408 call process_real_input_block ();
1409
1410
1411 else do;
1412
1413
1414
1415
1416
1417
1418 if (foreign_fcs.block_type = HASP_FCS_SYNC_BLOCK) then
1419 call process_sync_block ();
1420
1421 else if (foreign_bcb_char = hmd.last_loopback_bcb)
1422 then do;
1423 call syserr (LOG_AND_PRINT,
1424 "hasp_mpx (line ^a): Duplicate loopback block received: BCB = ^3.3b",
1425 hmd.name, unspec (hmd.last_loopback_bcb));
1426 call tty_space_man$free_chain (hmd.devx, INPUT, first_bufferp);
1427 end;
1428
1429 else do;
1430 hmd.meters.n_wraparound_blocks = hmd.meters.n_wraparound_blocks + 1;
1431 if hmd.loopback.first_bufferp = null () then
1432 hmd.loopback.first_bufferp = first_bufferp;
1433 else hmd.loopback.last_bufferp -> buffer.next = binary (rel (first_bufferp), 18, 0);
1434 hmd.loopback.last_bufferp = last_bufferp;
1435 hmd.last_loopback_bcb = foreign_bcb_char;
1436 end;
1437 end;
1438
1439 return;
1440
1441
1442
1443
1444
1445 BAD_INPUT_BLOCK:
1446 call tty_space_man$free_chain (hmd.devx, INPUT, first_bufferp);
1447
1448 call syserr (LOG_AND_PRINT, "hasp_mpx (line ^a): Invalid input block header/trailer; line will be hungup.", hmd.name);
1449 call channel_manager$control (hmd.devx, "hangup", null (), code);
1450
1451 return;
1452 %page;
1453
1454
1455 substr_of_chain:
1456 procedure (p_start_idx, p_length) returns (character (4) varying);
1457
1458 dcl (p_start_idx, p_length) fixed binary parameter;
1459 dcl the_text character (4) varying;
1460 dcl (characters_to_skip, characters_to_pickup, characters_in_buffer, start) fixed binary;
1461
1462 blockp = first_bufferp;
1463 the_text = "";
1464
1465
1466 characters_to_skip = p_start_idx - 1;
1467 do while (buffer.tally <= characters_to_skip);
1468 if buffer.next = 0 then go to BAD_INPUT_BLOCK;
1469 characters_to_skip = characters_to_skip - buffer.tally;
1470 blockp = pointer (ttybp, buffer.next);
1471 end;
1472
1473
1474 start = characters_to_skip;
1475 characters_to_pickup = p_length;
1476 do while (characters_to_pickup > 0);
1477 characters_in_buffer = min (characters_to_pickup, (buffer.tally - start));
1478 begin;
1479 dcl text_in_buffer character (characters_in_buffer) unaligned defined (buffer.chars (start));
1480 the_text = the_text || text_in_buffer;
1481 end;
1482 characters_to_pickup = characters_to_pickup - characters_in_buffer;
1483 if characters_to_pickup > 0 then do;
1484 if buffer.next = 0 then go to BAD_INPUT_BLOCK;
1485 blockp = pointer (ttybp, buffer.next);
1486 start = 0;
1487 end;
1488 end;
1489
1490 return (the_text);
1491
1492 end substr_of_chain;
1493 %page;
1494
1495
1496 delete_leading_text:
1497 procedure (p_n_characters);
1498
1499 dcl p_n_characters fixed binary parameter;
1500 dcl characters_left_to_delete fixed binary;
1501
1502 blockp = first_bufferp;
1503 characters_left_to_delete = p_n_characters;
1504
1505
1506 do while (buffer.tally <= characters_left_to_delete);
1507 if buffer.next ^= 0 then
1508 first_bufferp = pointer (ttybp, buffer.next);
1509 else go to BAD_INPUT_BLOCK;
1510 characters_left_to_delete = characters_left_to_delete - buffer.tally;
1511 call tty_space_man$free_buffer (hmd.devx, INPUT, blockp);
1512 blockp = first_bufferp;
1513 end;
1514
1515
1516 if characters_left_to_delete > 0 then call delete_text (blockp, 0, characters_left_to_delete);
1517
1518 return;
1519
1520 end delete_leading_text;
1521 %page;
1522
1523
1524 strip_dles: procedure ();
1525
1526 dcl buffer_text character (bufferp -> buffer.tally) unaligned based (addr (bufferp -> buffer.chars (0)));
1527 dcl bufferp pointer;
1528
1529 dcl (start, dle_idx) fixed binary;
1530 dcl last_was_dle bit (1) aligned;
1531
1532
1533 last_was_dle = "0"b;
1534
1535 do bufferp = first_bufferp repeat (pointer (ttybp, bufferp -> buffer.next))
1536 while (rel (bufferp) ^= ""b);
1537
1538 if last_was_dle then
1539 start = 2;
1540 else start = 1;
1541
1542 last_was_dle = "0"b;
1543
1544 dle_idx = index (substr (buffer_text, start), DLE);
1545
1546 do while (dle_idx ^= 0);
1547
1548 dle_idx = dle_idx + start - 1;
1549
1550 if dle_idx < (bufferp -> buffer.tally) then
1551 call delete_text (bufferp, (dle_idx - 1), 1);
1552 else do;
1553 bufferp -> buffer.tally = (bufferp -> buffer.tally) - 1;
1554 last_was_dle = "1"b;
1555 end;
1556
1557 start = dle_idx + 1;
1558
1559 if start > (bufferp -> buffer.tally) then
1560 dle_idx = 0;
1561 else dle_idx = index (substr (buffer_text, start), DLE);
1562 end;
1563 end;
1564
1565 return;
1566
1567 end strip_dles;
1568 %page;
1569
1570
1571
1572
1573 process_real_input_block:
1574 procedure ();
1575
1576 dcl chain_to_release_ptr pointer;
1577 dcl (expected_count, received_count, record_type, idx) fixed binary;
1578 dcl new_wab_bit bit (1) aligned;
1579
1580
1581
1582
1583
1584 if foreign_fcs.device_not_ready then do;
1585 hmd.meters.n_wraparounds = hmd.meters.n_wraparounds + 1;
1586 unspec (hmd.last_loopback_bcb) = "777"b3;
1587 if hmd.minor_state = HMD_REPROCESS then
1588 call push_loopback_block_chain ();
1589 call push_minor_state (HMD_SEND_SYNC_BLOCK);
1590 end;
1591
1592
1593
1594
1595
1596
1597 expected_count = mod (hmd.foreign_block_count + 1, 16);
1598 received_count = foreign_bcb.count;
1599
1600 if foreign_bcb.type = HASP_BCB_NORMAL then
1601 if hmd.first_foreign_block
1602 then do;
1603 hmd.first_foreign_block = "0"b;
1604 hmd.foreign_block_count = received_count;
1605 end;
1606 else if received_count = expected_count then
1607 hmd.foreign_block_count = received_count;
1608 else
1609 if ((received_count < expected_count) & ((expected_count - received_count) <= 3)) |
1610 ((received_count > expected_count) & ((expected_count - received_count + 16) <= 3))
1611 then do;
1612 hmd.meters.n_duplicate_input_blocks = hmd.meters.n_duplicate_input_blocks + 1;
1613 call syserr (LOG_ONLY,
1614 "hasp_mpx (line ^a): Block received out of sequence: expected = ^d, received = ^d; block ignored.",
1615 hmd.name, expected_count, received_count);
1616 first_bufferp -> buffer.tally = 1;
1617 first_bufferp -> buffer.chars (0) = HASP_EOB_RCB;
1618 last_bufferp = first_bufferp;
1619 chain_to_release_ptr = pointer (ttybp, first_bufferp -> buffer.next);
1620 first_bufferp -> buffer.next = 0;
1621 if rel (chain_to_release_ptr) ^= ""b then
1622 call tty_space_man$free_chain (hmd.devx, INPUT, chain_to_release_ptr);
1623 end;
1624 else do;
1625 call syserr (LOG_AND_PRINT,
1626 "hasp_mpx (line ^a): Block received out of sequence: expected = ^d, received = ^d; line will be hungup.",
1627 hmd.name, expected_count, received_count);
1628 call tty_space_man$free_chain (hmd.devx, INPUT, first_bufferp);
1629 hmd.minor_state = HMD_SEND_BAD_BCB_BLOCK;
1630 hmd.foreign_block_count = received_count;
1631 hmd.local_block_count = expected_count;
1632 return;
1633 end;
1634
1635 else if foreign_bcb.type = HASP_BCB_IGNORE
1636 then;
1637
1638 else if foreign_bcb.type = HASP_BCB_RESET then
1639 hmd.foreign_block_count = received_count - 1;
1640
1641
1642
1643
1644
1645 hmd.meters.n_input_blocks = hmd.meters.n_input_blocks + 1;
1646
1647 string (foreign_fcs.mcs1) = ""b;
1648 foreign_fcs.block_type = HASP_FCS_NORMAL_BLOCK;
1649
1650 if hmd.foreign_fcs_bytes ^= foreign_fcs_chars then do;
1651
1652 hmd.foreign_fcs_bytes = foreign_fcs_chars;
1653
1654 if foreign_fcs.system_wab & ^hmd.suspend_all_output then
1655 hmd.meters.n_foreign_wab_set = hmd.meters.n_foreign_wab_set + 1;
1656
1657
1658 hmd.suspend_all_output = foreign_fcs.system_wab;
1659
1660 do idx = 1 to hmd.n_subchannels;
1661
1662 if hmd.subchannels(idx).direction = HSTE_INPUT_ONLY
1663 then;
1664
1665 else do;
1666 if (hmd.subchannels(idx).device_wab_idx = 0) then
1667 new_wab_bit = foreign_fcs.console_wab;
1668 else if (hmd.subchannels(idx).device_wab_idx <= 4) then
1669 new_wab_bit = foreign_fcs.wab_bits1 (hmd.subchannels(idx).device_wab_idx);
1670 else new_wab_bit = foreign_fcs.wab_bits2 (hmd.subchannels(idx).device_wab_idx - 4);
1671 if ^new_wab_bit & hmd.output_wabs (hmd.subchannels(idx).device_wab_idx) then
1672 hmd.subchannels(idx).meters.device_n_foreign_wab_set =
1673 hmd.subchannels(idx).meters.device_n_foreign_wab_set + 1;
1674 hmd.output_wabs (hmd.subchannels(idx).device_wab_idx) = new_wab_bit;
1675 end;
1676 end;
1677 end;
1678
1679
1680
1681
1682
1683
1684 record_type = classify_record (first_bufferp, 0);
1685
1686 if record_type = HASP_EOB_RECORD
1687 then do;
1688
1689 call tty_space_man$free_chain (hmd.devx, INPUT, first_bufferp);
1690 call interrupt_subchannels_with_output ();
1691 end;
1692
1693 else if record_type = HASP_BAD_BCB_RECORD
1694 then do;
1695 received_count = foreign_bcb.count;
1696 expected_count = addr (addr (first_bufferp -> buffer.chars (0)) -> based_bad_bcb_record.srcb) -> hasp_bcb_byte.count;
1697 call syserr (LOG_AND_PRINT,
1698 "hasp_mpx (line ^a): Block transmitted out of sequence: expected = ^d, received = ^d; line will be hungup.",
1699 hmd.name, expected_count, received_count);
1700 call channel_manager$control (hmd.devx, "hangup", null (), code);
1701 call tty_space_man$free_chain (hmd.devx, INPUT, first_bufferp);
1702 end;
1703
1704 else do;
1705 if hmd.input.first_bufferp = null () then
1706 hmd.input.first_bufferp = first_bufferp;
1707 else hmd.input.last_bufferp -> buffer.next = binary (rel (first_bufferp), 18, 0);
1708 hmd.input.last_bufferp = last_bufferp;
1709 call interrupt_subchannels_with_output ();
1710 end;
1711
1712 return;
1713
1714 end process_real_input_block;
1715 %page;
1716
1717
1718
1719
1720
1721
1722 process_sync_block:
1723 procedure ();
1724
1725 dcl previous_minor_state fixed binary;
1726
1727 call tty_space_man$free_chain (hmd.devx, INPUT, first_bufferp);
1728
1729
1730 if hmd.minor_state > HMD_REPROCESS then
1731 return;
1732
1733 if hmd.minor_state_stack = null () then
1734 previous_minor_state = HMD_NORMAL;
1735 else previous_minor_state = hmd.minor_state_stack -> msse.minor_state;
1736
1737 if (previous_minor_state = HMD_SEND_SYNC_BLOCK) | (previous_minor_state = HMD_LOOPBACK) then
1738 call pop_minor_state ();
1739
1740 else do;
1741 if previous_minor_state = HMD_REPROCESS then
1742 call pop_loopback_block_chain ();
1743 hmd.reset_local_block_count = "1"b;
1744 hmd.minor_state = HMD_REPROCESS;
1745 end;
1746
1747 return;
1748
1749 end process_sync_block;
1750
1751 end process_input_block;
1752 %page;
1753
1754
1755 input_loopback_records_processor:
1756 procedure ();
1757
1758 return;
1759
1760
1761 dcl input_entry bit (1) aligned;
1762
1763 dcl saved_hste_ptr pointer;
1764
1765
1766 dcl (start_bufferp, end_bufferp) pointer;
1767 dcl (start_record_idx, end_record_idx) fixed binary;
1768
1769
1770 dcl rcb_char character (1) unaligned;
1771 dcl srcb_char character (1) unaligned;
1772
1773 dcl 1 rcb unaligned based (addr (rcb_char)) like hasp_rcb_byte;
1774
1775 dcl (continue_scan, record_was_taken) bit (1) aligned;
1776
1777 dcl bufferp pointer;
1778 dcl (record_type, record_tally, dle_count) fixed binary;
1779 %page;
1780
1781
1782
1783
1784 process_input_records:
1785 entry ();
1786
1787 input_entry = "1"b;
1788 needs_space = "0"b;
1789
1790 saved_hste_ptr = hste_ptr;
1791
1792 start_bufferp = hmd.input.first_bufferp;
1793 start_record_idx = 0;
1794
1795 continue_scan = "1"b;
1796
1797 do while (continue_scan);
1798
1799 call find_next_record (start_bufferp, start_record_idx, "1"b, "0"b,
1800 end_bufferp, end_record_idx, record_tally, (0));
1801
1802 if end_bufferp ^= null ()
1803 then do;
1804
1805 record_type = classify_record (start_bufferp, start_record_idx);
1806
1807
1808
1809
1810 record_tally = record_tally - 1;
1811
1812 rcb_char = start_bufferp -> buffer.chars (start_record_idx);
1813
1814 if (start_record_idx < (start_bufferp -> buffer.tally - 1))
1815 then
1816 srcb_char = start_bufferp -> buffer.chars (start_record_idx + 1);
1817
1818 else
1819 if ((start_bufferp -> buffer.next) ^= 0) & (record_tally ^= 0)
1820 then do;
1821 bufferp = pointer (ttybp, start_bufferp -> buffer.next);
1822 srcb_char = bufferp -> buffer.chars (0);
1823 end;
1824
1825 else do;
1826 record_type = HASP_EOB_RECORD;
1827 srcb_char = NUL;
1828 end;
1829
1830
1831
1832
1833 if (record_type = HASP_DATA_RECORD) | (record_type = HASP_EOF_RECORD)
1834 then do;
1835
1836
1837
1838
1839 hste_ptr = find_subchannel (rcb_char);
1840
1841 if hste_ptr ^= null () then
1842
1843 if (hste.direction = HSTE_OUTPUT_ONLY) then
1844
1845 call flush_record_buffers ();
1846
1847 else do;
1848 call move_record_to_device ();
1849 hste.meters.device_n_input_records = hste.meters.device_n_input_records + 1;
1850 if (record_type = HASP_EOF_RECORD) then
1851 hste.meters.device_n_input_eof_records = hste.meters.device_n_input_eof_records + 1;
1852 if hste.input.n_records >= hmd.max_device_input_records then
1853 if hste.device_type ^= HASP_CONSOLE
1854 then do;
1855 if hmd.input_wabs (hste.device_wab_idx) then
1856 hste.meters.device_n_local_wab_set = hste.meters.device_n_local_wab_set + 1;
1857 hmd.input_wabs (hste.device_wab_idx) = "0"b;
1858 end;
1859 end;
1860
1861 else do;
1862 call flush_record_buffers ();
1863 if (rcb.type = HASP_RCB_TYPE_READER_INPUT) | (rcb.type = HASP_RCB_TYPE_PRINT_OUTPUT) then
1864 hmd.input_wabs (rcb.stream) = "0"b;
1865 else if (rcb.type = HASP_RCB_TYPE_PUNCH_OUTPUT) then
1866 hmd.input_wabs (9 - rcb.stream) = "0"b;
1867 end;
1868 end;
1869
1870
1871 else if (record_type = HASP_RTS_RECORD)
1872 then do;
1873
1874
1875
1876
1877
1878 hste_ptr = find_subchannel (srcb_char);
1879
1880 if hste_ptr ^= null () then
1881 if (hste.direction ^= HSTE_OUTPUT_ONLY) & (hste.device_type ^= HASP_CONSOLE) then
1882 hmd.send_rts_ack (hste.device_wab_idx) = "1"b;
1883
1884 call flush_record_buffers ();
1885 end;
1886
1887
1888 else if (record_type = HASP_RTS_ACK_RECORD)
1889 then do;
1890
1891
1892
1893
1894 hste_ptr = find_subchannel (srcb_char);
1895
1896 if hste_ptr ^= null () then do;
1897 hste.minor_state = HSTE_NORMAL;
1898 if hste.holding_output then do;
1899 call dequeue_subchannel_for_output ();
1900 call channel_manager$interrupt (hste.devx, SEND_OUTPUT, ""b);
1901 end;
1902 end;
1903
1904 call flush_record_buffers ();
1905 end;
1906
1907 else call flush_record_buffers ();
1908
1909
1910
1911
1912 if end_bufferp = null () then
1913 start_bufferp = null ();
1914
1915 else if (end_record_idx + 1) = (end_bufferp -> buffer.tally)
1916 then do;
1917 if end_bufferp -> buffer.next = 0 then
1918 start_bufferp = null ();
1919 else start_bufferp = pointer (ttybp, end_bufferp -> buffer.next);
1920 start_record_idx = 0;
1921 call tty_space_man$free_buffer (hmd.devx, INPUT, end_bufferp);
1922 end;
1923
1924 else do;
1925 start_bufferp = end_bufferp;
1926 start_record_idx = end_record_idx + 1;
1927 end;
1928
1929 hmd.meters.n_input_records = hmd.meters.n_input_records + 1;
1930
1931 continue_scan = (start_bufferp ^= null ());
1932 end;
1933
1934 else continue_scan = "0"b;
1935 end;
1936
1937
1938 RETURN_FROM_PROCESS_INPUT_RECORDS:
1939 if start_bufferp ^= null () then
1940 if start_record_idx ^= 0 then
1941 call delete_text (start_bufferp, 0, start_record_idx);
1942
1943 hmd.input.first_bufferp = start_bufferp;
1944
1945 if start_bufferp = null () then
1946 hmd.input.last_bufferp = null ();
1947
1948 hmd.retry_process_input = needs_space;
1949 if needs_space then
1950 call tty_space_man$needs_space (hmd.devx);
1951
1952 hste_ptr = saved_hste_ptr;
1953
1954 return;
1955 %page;
1956
1957
1958
1959
1960
1961
1962 process_loopback_records:
1963 entry ();
1964
1965 input_entry = "0"b;
1966 needs_space = "0"b;
1967
1968 saved_hste_ptr = hste_ptr;
1969
1970 start_bufferp = hmd.loopback.first_bufferp;
1971 start_record_idx = 0;
1972
1973 continue_scan = ^full_output_blockp () &
1974 (hmd.loopback.first_bufferp ^= null ());
1975
1976 do while (continue_scan);
1977
1978 call find_next_record (start_bufferp, start_record_idx, "1"b, "1"b,
1979 end_bufferp, end_record_idx, record_tally, dle_count);
1980
1981 if end_bufferp ^= null ()
1982 then do;
1983
1984 record_type = classify_record (start_bufferp, start_record_idx);
1985
1986
1987
1988
1989 record_tally = record_tally - 1;
1990
1991 rcb_char = start_bufferp -> buffer.chars (start_record_idx);
1992
1993 if (start_record_idx < (start_bufferp -> buffer.tally - 1))
1994 then
1995 srcb_char = start_bufferp -> buffer.chars (start_record_idx + 1);
1996
1997 else
1998 if ((start_bufferp -> buffer.next) ^= 0) & (record_tally ^= 0)
1999 then do;
2000 bufferp = pointer (ttybp, start_bufferp -> buffer.next);
2001 srcb_char = bufferp -> buffer.chars (0);
2002 end;
2003
2004 else do;
2005 record_type = HASP_EOB_RECORD;
2006 srcb_char = NUL;
2007 end;
2008
2009
2010
2011
2012 if (record_type = HASP_DATA_RECORD) | (record_type = HASP_EOF_RECORD)
2013 then do;
2014
2015
2016
2017
2018 hste_ptr = find_subchannel (rcb_char);
2019
2020 if hste_ptr ^= null () then
2021
2022 if hste.direction = HSTE_INPUT_ONLY then
2023 call flush_record_buffers ();
2024
2025 else if hmd.output_wabs (hste.device_wab_idx) &
2026 (hste.loopback.first_bufferp = null ())
2027 then do;
2028 call process_single_loopback_record (start_bufferp, (start_record_idx + 1),
2029 end_bufferp, end_record_idx, record_tally,
2030 dle_count, record_was_taken);
2031 if needs_space then
2032 go to RETURN_FROM_PROCESS_LOOPBACK_RECORDS;
2033 if record_was_taken then
2034 call flush_record_buffers ();
2035 else call move_record_to_device ();
2036 end;
2037
2038 else call move_record_to_device ();
2039
2040 else call flush_record_buffers ();
2041 end;
2042
2043
2044 else if (record_type = HASP_RTS_RECORD)
2045 then do;
2046
2047
2048
2049
2050
2051 hste_ptr = find_subchannel (srcb_char);
2052
2053 if hste_ptr ^= null () then
2054 if hste.loopback.first_bufferp = null () then
2055 hste.minor_state = HSTE_SEND_RTS;
2056
2057 call flush_record_buffers ();
2058 end;
2059
2060
2061 else if (record_type = HASP_RTS_ACK_RECORD)
2062 then do;
2063
2064
2065
2066
2067 hste_ptr = find_subchannel (srcb_char);
2068
2069 if hste_ptr ^= null () then
2070 hmd.send_rts_ack (hste.device_wab_idx) = "1"b;
2071
2072 call flush_record_buffers ();
2073 end;
2074
2075
2076 else call flush_record_buffers ();
2077
2078
2079
2080
2081
2082
2083 if end_bufferp = null () then
2084 start_bufferp = null ();
2085
2086 else if (end_record_idx + 1) = (end_bufferp -> buffer.tally)
2087 then do;
2088 if end_bufferp -> buffer.next = 0 then
2089 start_bufferp = null ();
2090 else start_bufferp = pointer (ttybp, end_bufferp -> buffer.next);
2091 start_record_idx = 0;
2092 call tty_space_man$free_buffer (hmd.devx, INPUT, end_bufferp);
2093 end;
2094
2095 else do;
2096 start_bufferp = end_bufferp;
2097 start_record_idx = end_record_idx + 1;
2098 end;
2099
2100 continue_scan = (start_bufferp ^= null ()) &
2101 ^full_output_blockp ();
2102 end;
2103
2104 else continue_scan = "0"b;
2105 end;
2106
2107
2108
2109
2110
2111 RETURN_FROM_PROCESS_LOOPBACK_RECORDS:
2112 if start_bufferp ^= null () then
2113 if start_record_idx ^= 0 then
2114 call delete_text (start_bufferp, 0, start_record_idx);
2115
2116 hmd.loopback.first_bufferp = start_bufferp;
2117
2118 if start_bufferp = null () then
2119 hmd.loopback.last_bufferp = null ();
2120
2121 hmd.retry_process_loopback_records = needs_space;
2122 if needs_space then
2123 call tty_space_man$needs_space (hmd.devx);
2124 else call process_output_block ();
2125
2126 if hmd.loopback.first_bufferp = null () then do;
2127 call pop_minor_state ();
2128 if (hmd.minor_state = HMD_NORMAL) then
2129 call interrupt_subchannels_with_output ();
2130 end;
2131
2132 hste_ptr = saved_hste_ptr;
2133
2134 return;
2135 %page;
2136
2137
2138 find_subchannel: procedure (P_rcb_char) returns (pointer);
2139
2140 dcl P_rcb_char character (1) unaligned parameter;
2141
2142 dcl idx fixed binary;
2143
2144
2145 do idx = 1 to hmd.n_subchannels;
2146
2147 if (hmd.subchannels(idx).device_type = HASP_CONSOLE) then
2148 if (P_rcb_char = HASP_CONSOLE_INPUT_RCB) | (P_rcb_char = HASP_CONSOLE_OUTPUT_RCB) then
2149 return (addr (hmd.subchannels (idx)));
2150 else;
2151
2152 else if (hmd.subchannels(idx).rcb = P_rcb_char) then
2153 return (addr (hmd.subchannels (idx)));
2154 end;
2155
2156 return (null ());
2157
2158 end find_subchannel;
2159 %page;
2160
2161
2162
2163 flush_record_buffers:
2164 procedure ();
2165
2166 dcl (bufferp, p) pointer;
2167
2168 bufferp = start_bufferp;
2169
2170 do while (bufferp ^= null ());
2171
2172 if bufferp = end_bufferp then
2173 bufferp = null ();
2174
2175 else do;
2176 if (bufferp -> buffer.next) = 0 then
2177 p = null ();
2178 else p = pointer (ttybp, bufferp -> buffer.next);
2179 call tty_space_man$free_buffer (hmd.devx, INPUT, bufferp);
2180 bufferp = p;
2181 end;
2182 end;
2183
2184 return;
2185
2186 end flush_record_buffers;
2187 %page;
2188
2189
2190
2191 move_record_to_device:
2192 procedure ();
2193
2194 dcl 1 record_data aligned based (record_data_ptr) like hste.input;
2195 dcl record_data_ptr pointer;
2196
2197 dcl substring character (substr_lth) unaligned based;
2198 dcl substr_lth fixed binary;
2199
2200 dcl (first_output_bufferp, last_output_bufferp, current_output_bufferp, current_input_bufferp, p) pointer;
2201 dcl (buffer_size_code, n_buffers, n_words_in_last_buffer, idx, amount_to_copy, current_input_idx,
2202 space_needed, space_left) fixed binary;
2203 dcl direction bit (1);
2204
2205
2206 if input_entry then
2207 direction = INPUT;
2208 else direction = OUTPUT;
2209
2210 buffer_size_code = divide (hste.dialup_info.max_buf_size, 16, 17, 0) - 1;
2211
2212 n_buffers = divide ((record_tally + max_buffer_tally (buffer_size_code) - 1),
2213 max_buffer_tally (buffer_size_code), 17, 0);
2214
2215 if n_buffers = 1 then
2216 first_output_bufferp = null ();
2217
2218 else do;
2219 call tty_space_man$get_chain (hste.devx, (hste.dialup_info.max_buf_size), (n_buffers - 1),
2220 direction, first_output_bufferp);
2221 if first_output_bufferp = null () then go to CANT_MOVE_RECORD_TO_DEVICE;
2222 last_output_bufferp = first_output_bufferp;
2223 do idx = 1 to (n_buffers - 2);
2224 last_output_bufferp = pointer (ttybp, last_output_bufferp -> buffer.next);
2225 end;
2226 end;
2227
2228 n_words_in_last_buffer =
2229 16 * divide ((record_tally - (n_buffers - 1) * max_buffer_tally (buffer_size_code)) + 67, 64, 17, 0);
2230
2231 call tty_space_man$get_buffer (hste.devx, n_words_in_last_buffer, direction, current_output_bufferp);
2232 if current_output_bufferp = null () then do;
2233 if first_output_bufferp ^= null () then
2234 call tty_space_man$free_chain (hste.devx, direction, first_output_bufferp);
2235 go to CANT_MOVE_RECORD_TO_DEVICE;
2236 end;
2237
2238 if first_output_bufferp = null () then
2239 first_output_bufferp = current_output_bufferp;
2240 else last_output_bufferp -> buffer.next = binary (rel (current_output_bufferp), 18, 0);
2241
2242 last_output_bufferp = current_output_bufferp;
2243
2244 amount_to_copy = record_tally;
2245
2246 current_input_bufferp = start_bufferp;
2247 current_input_idx = start_record_idx + 1;
2248
2249 current_output_bufferp = first_output_bufferp;
2250
2251 do while (amount_to_copy > 0);
2252
2253 space_left = max_buffer_tally (current_output_bufferp -> buffer.size_code) -
2254 (current_output_bufferp -> buffer.tally);
2255 space_needed = min ((current_input_bufferp -> buffer.tally - current_input_idx), amount_to_copy);
2256
2257 if space_left >= space_needed then
2258 substr_lth = space_needed;
2259 else substr_lth = space_left;
2260
2261 addr (current_output_bufferp -> buffer.chars (current_output_bufferp -> buffer.tally)) -> substring
2262 = addr (current_input_bufferp -> buffer.chars (current_input_idx)) -> substring;
2263
2264 current_output_bufferp -> buffer.tally = (current_output_bufferp -> buffer.tally) + substr_lth;
2265 current_input_idx = current_input_idx + substr_lth;
2266 amount_to_copy = amount_to_copy - substr_lth;
2267
2268 if (amount_to_copy > 0) & (current_input_idx = (current_input_bufferp -> buffer.tally))
2269 then do;
2270 if (current_input_bufferp -> buffer.next) = 0
2271 then do;
2272 p = null ();
2273 amount_to_copy = 0;
2274 end;
2275 else p = pointer (ttybp, current_input_bufferp -> buffer.next);
2276 if current_input_bufferp ^= end_bufferp then
2277 call tty_space_man$free_buffer (hmd.devx, INPUT, current_input_bufferp);
2278
2279 current_input_bufferp = p;
2280 current_input_idx = 0;
2281 end;
2282
2283 if (amount_to_copy > 0) &
2284 ((current_output_bufferp -> buffer.tally) =
2285 max_buffer_tally (current_output_bufferp -> buffer.size_code))
2286 then
2287 if (current_output_bufferp -> buffer.next) = 0 then
2288 amount_to_copy = 0;
2289 else current_output_bufferp = pointer (ttybp, current_output_bufferp -> buffer.next);
2290 end;
2291
2292 if current_output_bufferp ^= last_output_bufferp then do;
2293
2294 p = pointer (ttybp, current_output_bufferp -> buffer.next);
2295 call tty_space_man$free_chain (hste.devx, direction, p);
2296 current_output_bufferp -> buffer.next = 0;
2297 last_output_bufferp = current_output_bufferp;
2298 end;
2299
2300 if input_entry then
2301 record_data_ptr = addr (hste.input);
2302 else record_data_ptr = addr (hste.loopback);
2303
2304 last_output_bufferp -> buffer.break = "1"b;
2305
2306 if record_data.first_bufferp = null () then
2307 record_data.first_bufferp = first_output_bufferp;
2308 else record_data.last_bufferp -> buffer.next = binary (rel (first_output_bufferp), 18, 0);
2309
2310 record_data.last_bufferp = last_output_bufferp;
2311
2312 record_data.n_records = record_data.n_records + 1;
2313
2314 return;
2315
2316
2317
2318
2319
2320 CANT_MOVE_RECORD_TO_DEVICE:
2321 needs_space = "1"b;
2322 if input_entry then
2323 go to RETURN_FROM_PROCESS_INPUT_RECORDS;
2324 else go to RETURN_FROM_PROCESS_LOOPBACK_RECORDS;
2325
2326 end move_record_to_device;
2327
2328 end input_loopback_records_processor;
2329 %page;
2330
2331
2332
2333
2334 process_output_block:
2335 procedure ();
2336
2337 dcl local_bcb_char character (1) unaligned;
2338 dcl local_fcs_chars character (2) unaligned;
2339
2340 dcl 1 local_bcb unaligned based (addr (local_bcb_char)) like hasp_bcb_byte;
2341 dcl 1 local_fcs unaligned based (addr (local_fcs_chars)) like hasp_fcs_bytes;
2342
2343 dcl saved_hste_ptr pointer;
2344 dcl idx fixed binary;
2345
2346
2347
2348
2349 if hmd.output_in_progress then
2350 call transmit_output_block ();
2351
2352 if ^hmd.send_output then return;
2353
2354 if hmd.suspend_all_output &
2355 (hmd.minor_state ^= HMD_SEND_SYNC_BLOCK) &
2356 (hmd.minor_state ^= HMD_SEND_BAD_BCB_BLOCK) &
2357 (hmd.minor_state ^= HMD_HANGUP_LINE)
2358 then
2359 return;
2360
2361
2362 if (hmd.minor_state = HMD_HANGUP_LINE) then
2363
2364
2365
2366
2367
2368 call channel_manager$control (hmd.devx, "hangup", null (), code);
2369
2370
2371 else if (hmd.minor_state = HMD_SEND_BAD_BCB_BLOCK)
2372 then do;
2373
2374
2375
2376
2377 if hmd.output_block.first_bufferp ^= null ()
2378 then do;
2379 call tty_space_man$free_chain (hmd.devx, OUTPUT, hmd.output_block.first_bufferp);
2380 hmd.output_block.first_bufferp = null ();
2381 end;
2382
2383 call tty_space_man$get_buffer (hmd.devx, 16, OUTPUT, blockp);
2384 if blockp = null () then go to CANT_FINISH_PROCESS_OUTPUT_BLOCK;
2385
2386 addr (buffer.chars (0)) -> based_bad_bcb_block = TEMPLATE_HASP_BAD_BCB_BLOCK;
2387 buffer.tally = length (string (TEMPLATE_HASP_BAD_BCB_BLOCK));
2388
2389 addr (addr (buffer.chars (0)) -> based_bad_bcb_block.bcb) -> hasp_bcb_byte.count =
2390 hmd.foreign_block_count;
2391
2392 addr (addr (buffer.chars (0)) -> based_bad_bcb_block.srcb) -> hasp_bcb_byte.count =
2393 hmd.local_block_count;
2394
2395 hmd.output_block.tally = buffer.tally;
2396 hmd.output_block.first_bufferp, hmd.output_block.last_bufferp = blockp;
2397
2398 hmd.minor_state = HMD_HANGUP_LINE;
2399 end;
2400
2401
2402 else if ^empty_output_blockp ()
2403 then do;
2404
2405
2406
2407 call compute_local_bcb_and_fcs ();
2408 call finish_output_block ();
2409 end;
2410
2411
2412 else if ((hmd.minor_state = HMD_SEND_SIGNON) | (hmd.minor_state = HMD_REPROCESS)) &
2413 (hmd.signon_data_ptr ^= null ())
2414 then do;
2415
2416
2417
2418
2419
2420
2421
2422 call compute_local_bcb_and_fcs ();
2423
2424 if hmd.output_block.first_bufferp ^= null () then
2425 call tty_space_man$free_chain (hmd.devx, OUTPUT, hmd.output_block.first_bufferp);
2426
2427 call tty_space_man$get_buffer (hmd.devx, 32, OUTPUT, blockp);
2428 if blockp = null () then go to CANT_FINISH_PROCESS_OUTPUT_BLOCK;
2429
2430 hmd.output_block.first_bufferp,
2431 hmd.output_block.last_bufferp = blockp;
2432
2433 addr (buffer.chars (0)) -> based_signon_block.header = TEMPLATE_HASP_SIGNON_BLOCK.header;
2434 addr (buffer.chars (0)) -> based_signon_block.record = hmd.signon_data_ptr -> hmd_signon_data.record;
2435 hmd.output_block.tally,
2436 buffer.tally = length (string (TEMPLATE_HASP_SIGNON_BLOCK.non_trailer));
2437 hmd.meters.n_output_records = hmd.meters.n_output_records + 1;
2438
2439 call finish_output_block ();
2440 addr (addr (buffer.chars (0)) -> based_block_header.fcs) -> hasp_fcs_bytes.block_type =
2441 HASP_FCS_ACKNOWLEDGE_BLOCK;
2442
2443 if hmd.minor_state = HMD_SEND_SIGNON then
2444 hmd.minor_state = HMD_WAIT_SIGNON_RESPONSE;
2445 end;
2446
2447
2448 else if (hmd.minor_state = HMD_NORMAL)
2449 then do;
2450
2451
2452
2453
2454 saved_hste_ptr = hste_ptr;
2455
2456 do idx = 1 to hmd.n_subchannels
2457 while (^full_output_blockp ());
2458 hste_ptr = addr (hmd.subchannels (idx));
2459
2460 if (hste.direction ^= HSTE_INPUT_ONLY) & hmd.output_wabs (hste.device_wab_idx) then
2461
2462 if (hste.loopback.first_bufferp ^= null ())
2463 then do;
2464 call process_subchannel_loopback_records ();
2465 if needs_space then
2466 go to CANT_FINISH_PROCESS_OUTPUT_BLOCK;
2467 if (hste.loopback.first_bufferp = null ()) then do;
2468
2469 call dequeue_subchannel_for_output ();
2470 call channel_manager$interrupt_later (hste.devx, SEND_OUTPUT, ""b);
2471 end;
2472 end;
2473 end;
2474
2475 hste_ptr = saved_hste_ptr;
2476
2477 if empty_output_blockp () then
2478 go to TRY_STATUS_OR_RTS_BLOCK;
2479 else do;
2480 call compute_local_bcb_and_fcs ();
2481 call finish_output_block ();
2482 end;
2483 end;
2484
2485
2486 else if ((hmd.minor_state = HMD_NORMAL) | (hmd.minor_state = HMD_REPROCESS)) & empty_output_blockp ()
2487 then do;
2488
2489
2490
2491
2492 TRY_STATUS_OR_RTS_BLOCK:
2493 call compute_local_bcb_and_fcs ();
2494
2495 if (hmd.local_fcs_bytes ^= local_fcs_chars) |
2496 (string (hmd.send_rts) ^= ""b) | (string (hmd.send_rts_ack) ^= ""b)
2497 then do;
2498
2499 if (hmd.output_block.first_bufferp = null ())
2500 then do;
2501
2502 call tty_space_man$get_buffer (hmd.devx, 16, OUTPUT, blockp);
2503 if blockp = null () then go to CANT_FINISH_PROCESS_OUTPUT_BLOCK;
2504
2505 hmd.output_block.first_bufferp,
2506 hmd.output_block.last_bufferp = blockp;
2507
2508 addr (buffer.chars (0)) -> based_block_header = TEMPLATE_HASP_BLOCK_HEADER;
2509 hmd.output_block.tally,
2510 buffer.tally = length (string (TEMPLATE_HASP_BLOCK_HEADER));
2511 end;
2512
2513 call add_rts_or_rts_ack_record ();
2514 call finish_output_block ();
2515 end;
2516 end;
2517
2518
2519 else if (hmd.minor_state = HMD_SEND_SYNC_BLOCK)
2520 then do;
2521
2522
2523
2524
2525
2526
2527 call tty_space_man$get_buffer (hmd.devx, 16, OUTPUT, blockp);
2528 if blockp = null () then go to CANT_FINISH_PROCESS_OUTPUT_BLOCK;
2529
2530 addr (buffer.chars (0)) -> based_sync_block = TEMPLATE_HASP_SYNC_BLOCK;
2531 buffer.tally = length (string (TEMPLATE_HASP_SYNC_BLOCK));
2532
2533 hmd.output_block.tally = buffer.tally;
2534 hmd.output_block.first_bufferp, hmd.output_block.last_bufferp = blockp;
2535
2536 hmd.minor_state = HMD_LOOPBACK;
2537 end;
2538
2539
2540 else if (hmd.minor_state = HMD_LOOPBACK) then
2541 return;
2542
2543 else if (hmd.minor_state = HMD_WAIT_SIGNON_RESPONSE) then
2544 return;
2545
2546
2547
2548
2549
2550 if ^empty_output_blockp () then do;
2551 hmd.meters.n_output_blocks = hmd.meters.n_output_blocks + 1;
2552 hmd.output_chain_ptr = hmd.output_block.first_bufferp;
2553
2554 hmd.output_block.tally = 0;
2555 hmd.output_block.first_bufferp, hmd.output_block.last_bufferp = null ();
2556
2557 if hmd.trace_mode then
2558 call trace_block (hmd.output_chain_ptr, OUTPUT);
2559
2560 call transmit_output_block ();
2561
2562 if hmd.minor_state = HMD_NORMAL then
2563 call interrupt_subchannels_with_output ();
2564 end;
2565
2566 hmd.retry_process_output = "0"b;
2567
2568 return;
2569
2570
2571
2572
2573 CANT_FINISH_PROCESS_OUTPUT_BLOCK:
2574 hmd.retry_process_output = "1"b;
2575 call tty_space_man$needs_space (hmd.devx);
2576 return;
2577 %page;
2578
2579
2580 compute_local_bcb_and_fcs:
2581 procedure ();
2582
2583 dcl idx fixed binary;
2584
2585
2586
2587
2588 local_bcb_char = NUL;
2589 local_bcb.mbo1 = "1"b;
2590
2591 if hmd.reset_local_block_count then
2592 local_bcb.type = HASP_BCB_RESET;
2593 else do;
2594 local_bcb.type = HASP_BCB_NORMAL;
2595 local_bcb.count = mod (hmd.local_block_count + 1, 16);
2596 end;
2597
2598
2599
2600
2601
2602
2603 local_fcs_chars = copy (NUL, 2);
2604 local_fcs.mbo1,
2605 local_fcs.mbo2 = "1"b;
2606
2607 if hmd.suspend_all_input then
2608 local_fcs.system_wab = "1"b;
2609
2610 string (local_fcs.wab_bits1),
2611 string (local_fcs.wab_bits2) = ""b;
2612 local_fcs.console_wab = "0"b;
2613
2614 do idx = 1 to hmd.n_subchannels;
2615
2616 if (hmd.subchannels(idx).direction = HSTE_OUTPUT_ONLY)
2617 then;
2618
2619 else if (hmd.subchannels(idx).state = HSTE_DIALED) then
2620
2621 if hmd.input_wabs (hmd.subchannels(idx).device_wab_idx) then
2622
2623 if (hmd.subchannels(idx).device_wab_idx = 0) then
2624 local_fcs.console_wab = "1"b;
2625 else if (hmd.subchannels(idx).device_wab_idx <= 4) then
2626 local_fcs.wab_bits1 (hmd.subchannels(idx).device_wab_idx) = "1"b;
2627 else local_fcs.wab_bits2 (hmd.subchannels(idx).device_wab_idx-4) = "1"b;
2628
2629 else
2630 if hmd.suspend_all_mode then
2631 local_fcs.system_wab = "1"b;
2632 end;
2633
2634 return;
2635
2636 end compute_local_bcb_and_fcs;
2637 %page;
2638
2639
2640
2641
2642 finish_output_block:
2643 procedure ();
2644
2645 dcl 1 hmd_local_fcs unaligned based (addr (hmd.local_fcs_bytes)) like hasp_fcs_bytes;
2646
2647 dcl 1 based_split_block_trailer aligned based,
2648 2 part1 character (space_left_in_buffer) unaligned,
2649 2 part2 character (amount_needed - space_left_in_buffer) unaligned;
2650
2651 dcl based_part1 character (space_left_in_buffer) unaligned based;
2652 dcl based_part2 character (amount_needed - space_left_in_buffer) unaligned based;
2653
2654 dcl (bufferp, new_bufferp) pointer;
2655 dcl (space_left_in_buffer, amount_needed, saved_tally) fixed binary;
2656
2657
2658 bufferp = hmd.output_block.last_bufferp;
2659
2660 space_left_in_buffer = max_buffer_tally (bufferp -> buffer.size_code) - (bufferp -> buffer.tally);
2661 amount_needed = length (string (TEMPLATE_HASP_BLOCK_TRAILER.non_crc));
2662
2663 if space_left_in_buffer >= amount_needed
2664 then do;
2665 addr (bufferp -> buffer.chars (bufferp -> buffer.tally)) -> based_block_trailer.non_crc =
2666 TEMPLATE_HASP_BLOCK_TRAILER.non_crc;
2667 bufferp -> buffer.tally = (bufferp -> buffer.tally) +
2668 length (string (TEMPLATE_HASP_BLOCK_TRAILER.non_crc));
2669 end;
2670
2671 else do;
2672 saved_tally = bufferp -> buffer.tally;
2673 if space_left_in_buffer > 0 then do;
2674 addr (bufferp -> buffer.chars (bufferp -> buffer.tally)) -> based_part1 =
2675 addr (TEMPLATE_HASP_BLOCK_TRAILER.non_crc) -> based_split_block_trailer.part1;
2676 bufferp -> buffer.tally = max_buffer_tally (bufferp -> buffer.size_code);
2677 end;
2678 call tty_space_man$get_buffer (hmd.devx, 16, OUTPUT, new_bufferp);
2679 if new_bufferp = null () then do;
2680 bufferp -> buffer.tally = saved_tally;
2681 go to CANT_FINISH_PROCESS_OUTPUT_BLOCK;
2682 end;
2683 addr (new_bufferp -> buffer.chars (0)) -> based_part2 =
2684 addr (TEMPLATE_HASP_BLOCK_TRAILER.non_crc) -> based_split_block_trailer.part2;
2685 new_bufferp -> buffer.tally = amount_needed - space_left_in_buffer;
2686 bufferp -> buffer.next = binary (rel (new_bufferp), 18, 0);
2687 hmd.output_block.last_bufferp = new_bufferp;
2688 end;
2689
2690 hmd.output_block.tally = hmd.output_block.tally +
2691 length (string (TEMPLATE_HASP_BLOCK_TRAILER.non_crc));
2692
2693 addr (hmd.output_block.first_bufferp -> buffer.chars (0)) -> based_block_header.bcb = local_bcb_char;
2694 addr (hmd.output_block.first_bufferp -> buffer.chars (0)) -> based_block_header.fcs = local_fcs_chars;
2695
2696 if hmd.reset_local_block_count
2697 then do;
2698 hmd.reset_local_block_count = "0"b;
2699 hmd.local_block_count = -1;
2700 end;
2701 else hmd.local_block_count = local_bcb.count;
2702
2703 if local_fcs.system_wab & ^hmd_local_fcs.system_wab then
2704 hmd.meters.n_local_wab_set = hmd.meters.n_local_wab_set + 1;
2705
2706 hmd.local_fcs_bytes = local_fcs_chars;
2707
2708 return;
2709
2710 end finish_output_block;
2711 %page;
2712
2713
2714
2715 add_rts_or_rts_ack_record:
2716 procedure ();
2717
2718 dcl p pointer;
2719 dcl idx fixed binary;
2720
2721
2722 do idx = 1 to hmd.n_subchannels;
2723
2724 if (hmd.subchannels(idx).direction ^= HSTE_INPUT_ONLY) & (idx ^= hmd.console_hste_idx)
2725 then if hmd.send_rts (hmd.subchannels(idx).device_wab_idx)
2726 then do;
2727
2728
2729
2730 hmd.meters.n_output_records = hmd.meters.n_output_records + 1;
2731
2732 p = hmd.output_block.last_bufferp;
2733
2734 addr (p -> buffer.chars (p -> buffer.tally)) -> based_rts_record =
2735 TEMPLATE_HASP_RTS_RECORD;
2736
2737 addr (p -> buffer.chars (p -> buffer.tally)) -> based_rts_record.srcb =
2738 hmd.subchannels(idx).rcb;
2739
2740 p -> buffer.tally = (p -> buffer.tally) +
2741 length (string (TEMPLATE_HASP_RTS_RECORD));
2742 hmd.output_block.tally = hmd.output_block.tally +
2743 length (string (TEMPLATE_HASP_RTS_RECORD));
2744
2745 hmd.send_rts (hmd.subchannels(idx).device_wab_idx) = "0"b;
2746 hmd.subchannels(idx).minor_state = HSTE_WAIT_RTS_ACK;
2747 go to NO_MORE_RECORDS;
2748 end;
2749
2750 else;
2751
2752
2753 else if (hmd.subchannels(idx).direction ^= HSTE_OUTPUT_ONLY)
2754 then if hmd.send_rts_ack (hmd.subchannels(idx).device_wab_idx)
2755 then do;
2756
2757
2758
2759 hmd.meters.n_output_records = hmd.meters.n_output_records + 1;
2760
2761 p = hmd.output_block.last_bufferp;
2762
2763 addr (p -> buffer.chars (p -> buffer.tally)) -> based_rts_ack_record =
2764 TEMPLATE_HASP_RTS_ACK_RECORD;
2765
2766 addr (p -> buffer.chars (p -> buffer.tally)) -> based_rts_ack_record.srcb =
2767 hmd.subchannels(idx).rcb;
2768
2769 p -> buffer.tally = (p -> buffer.tally) +
2770 length (string (TEMPLATE_HASP_RTS_ACK_RECORD));
2771 hmd.output_block.tally = hmd.output_block.tally +
2772 length (string (TEMPLATE_HASP_RTS_ACK_RECORD));
2773
2774 hmd.send_rts_ack (hmd.subchannels(idx).device_wab_idx) = "0"b;
2775 go to NO_MORE_RECORDS;
2776 end;
2777
2778 else;
2779 end;
2780
2781 NO_MORE_RECORDS: return;
2782
2783 end add_rts_or_rts_ack_record;
2784
2785 end process_output_block;
2786 %page;
2787
2788
2789 output_records_processor:
2790 procedure ();
2791
2792 RETURN_FROM_CALLER:
2793 return;
2794
2795
2796
2797
2798 dcl (P_start_bufferp, P_end_bufferp) pointer parameter;
2799 dcl ( P_start_record_idx, P_end_record_idx) fixed binary parameter;
2800 dcl P_record_tally fixed binary parameter;
2801 dcl P_dle_count fixed binary parameter;
2802 dcl P_record_was_taken bit (1) aligned parameter;
2803
2804
2805
2806
2807
2808 dcl loopback_entry bit (1) aligned;
2809
2810
2811 dcl 1 saved_output_block aligned like hmd.output_block;
2812 dcl saved_last_tally fixed binary;
2813
2814 dcl (start_bufferp, end_bufferp) pointer;
2815 dcl (start_record_idx, end_record_idx) fixed binary;
2816
2817 dcl continue_scan bit (1) aligned;
2818
2819 dcl (bufferp, p) pointer;
2820
2821 dcl (record_type, record_tally, dle_count, first_idx, last_idx) fixed binary;
2822 %page;
2823
2824
2825
2826
2827
2828 process_output_records:
2829 entry ();
2830
2831 loopback_entry = "0"b;
2832 needs_space = "0"b;
2833
2834 if cant_accept_records_from_this_device () then
2835 return;
2836
2837
2838
2839
2840 start_bufferp = chain_ptr;
2841 start_record_idx = 0;
2842
2843 continue_scan = "1"b;
2844
2845 do while (continue_scan);
2846
2847 call find_next_record (start_bufferp, start_record_idx, "0"b, "1"b,
2848 end_bufferp, end_record_idx, record_tally, dle_count);
2849
2850 if end_bufferp ^= null ()
2851 then do;
2852
2853 record_tally = record_tally + dle_count + 1;
2854
2855 if ^space_in_empty_output_block_for_recordp (record_tally)
2856 then do;
2857 continue_scan = "0"b;
2858 long_record = "1"b;
2859 end;
2860
2861 else if space_in_output_block_for_recordp (record_tally)
2862 then do;
2863 call move_record_to_output_block ("1"b);
2864 hmd.meters.n_output_records = hmd.meters.n_output_records + 1;
2865 hste.meters.device_n_output_records = hste.meters.device_n_output_records + 1;
2866 if record_type = HASP_EOF_RECORD then
2867 hste.meters.device_n_output_eof_records = hste.meters.device_n_output_eof_records + 1;
2868
2869 if (end_record_idx + 1) = (end_bufferp -> buffer.tally)
2870 then do;
2871 if end_bufferp -> buffer.next = 0 then
2872 start_bufferp = null ();
2873 else start_bufferp = pointer (ttybp, end_bufferp -> buffer.next);
2874 start_record_idx = 0;
2875 call tty_space_man$free_buffer (hste.devx, OUTPUT, end_bufferp);
2876 end;
2877 else do;
2878 start_bufferp = end_bufferp;
2879 start_record_idx = end_record_idx + 1;
2880 end;
2881
2882 continue_scan = (start_bufferp ^= null ()) &
2883 (hste.minor_state = HSTE_NORMAL);
2884 end;
2885
2886 else continue_scan = "0"b;
2887 end;
2888
2889 else do;
2890 continue_scan = "0"b;
2891 if ^space_in_empty_output_block_for_recordp ((record_tally + dle_count + 1)) then
2892 long_record = "1"b;
2893 else partial_record = "1"b;
2894 end;
2895 end;
2896
2897
2898 RETURN_FROM_PROCESS_OUTPUT_RECORDS:
2899 if start_bufferp ^= null () then
2900 if start_record_idx ^= 0 then
2901 call delete_text (start_bufferp, 0, start_record_idx);
2902
2903 chain_ptr = start_bufferp;
2904
2905 return;
2906 %page;
2907
2908
2909
2910 process_single_loopback_record:
2911 entry (P_start_bufferp, P_start_record_idx, P_end_bufferp, P_end_record_idx, P_record_tally, P_dle_count,
2912 P_record_was_taken);
2913
2914 start_bufferp = P_start_bufferp;
2915 start_record_idx = P_start_record_idx;
2916 end_bufferp = P_end_bufferp;
2917 end_record_idx = P_end_record_idx;
2918 record_tally = P_record_tally + P_dle_count + 1;
2919
2920 P_record_was_taken = "0"b;
2921
2922 loopback_entry = "1"b;
2923 needs_space = "0"b;
2924
2925 if cant_accept_records_from_this_device () then
2926 return;
2927
2928 if (hste.minor_state ^= HSTE_NORMAL) then do;
2929 if (hste.minor_state = HSTE_SEND_RTS) then
2930 hmd.send_rts (hste.device_wab_idx) = "1"b;
2931 return;
2932 end;
2933
2934 if ^space_in_output_block_for_recordp (record_tally) then
2935 return;
2936
2937 call move_record_to_output_block ("0"b);
2938 P_record_was_taken = "1"b;
2939
2940 return;
2941 %page;
2942
2943
2944
2945
2946 process_subchannel_loopback_records:
2947 entry ();
2948
2949 loopback_entry = "1"b;
2950 needs_space = "0"b;
2951
2952 if cant_accept_records_from_this_device () then
2953 return;
2954
2955 if (hste.minor_state ^= HSTE_NORMAL) then do;
2956 if (hste.minor_state = HSTE_SEND_RTS) then
2957 hmd.send_rts (hste.device_wab_idx) = "1"b;
2958 return;
2959 end;
2960
2961
2962
2963
2964
2965 start_bufferp = hste.loopback.first_bufferp;
2966
2967 continue_scan = (start_bufferp ^= null ());
2968
2969 do while (continue_scan);
2970
2971 record_tally, dle_count = 0;
2972 do bufferp = start_bufferp
2973 repeat (bufferp) while (bufferp ^= null ());
2974 record_tally = record_tally + (bufferp -> buffer.tally) + count_dles (bufferp);
2975 if (bufferp -> buffer.next = 0) | (bufferp -> buffer.break)
2976 then do;
2977 end_bufferp = bufferp;
2978 bufferp = null ();
2979 end;
2980 else bufferp = pointer (ttybp, bufferp -> buffer.next);
2981 end;
2982
2983 start_record_idx = 0;
2984 end_record_idx = (end_bufferp -> buffer.tally) - 1;
2985
2986 if space_in_output_block_for_recordp (record_tally)
2987 then do;
2988 call move_record_to_output_block ("1"b);
2989 hste.loopback.n_records = hste.loopback.n_records - 1;
2990 if (end_bufferp -> buffer.next = 0) then
2991 start_bufferp = null ();
2992 else start_bufferp = pointer (ttybp, end_bufferp -> buffer.next);
2993 call tty_space_man$free_buffer (hste.devx, OUTPUT, end_bufferp);
2994 continue_scan = ((start_bufferp ^= null ()) &
2995 (hste.minor_state = HSTE_NORMAL));
2996 end;
2997
2998 else continue_scan = "0"b;
2999 end;
3000
3001
3002
3003
3004 hste.loopback.first_bufferp = start_bufferp;
3005
3006 if (start_bufferp = null ()) then
3007 hste.loopback.last_bufferp = null ();
3008
3009 return;
3010 %page;
3011
3012
3013
3014
3015
3016
3017 cant_accept_records_from_this_device:
3018 procedure () returns (bit (1) aligned);
3019
3020 dcl accept_records bit (1) aligned;
3021
3022 accept_records = "1"b;
3023
3024 if empty_output_blockp ()
3025 then do;
3026 if hmd.output_block.first_bufferp = null () then
3027 call start_new_output_block ();
3028 if hmd.multileave_mode & (hste.device_type ^= HASP_CONSOLE) then
3029 hmd.output_block.subchannel_idx = -1;
3030 else hmd.output_block.subchannel_idx = hste.subchannel_idx;
3031 end;
3032
3033 else if hmd.multileave_mode & (hste.device_type ^= HASP_CONSOLE)
3034 then if (hmd.output_block.subchannel_idx = -1)
3035 then;
3036 else accept_records = "0"b;
3037
3038 else if (hmd.output_block.subchannel_idx = hste.subchannel_idx)
3039 then;
3040 else accept_records = "0"b;
3041
3042 return (^accept_records);
3043
3044
3045
3046
3047
3048 start_new_output_block:
3049 procedure ();
3050
3051 dcl bufferp pointer;
3052
3053 call tty_space_man$get_buffer (hmd.devx, (hmd.dialup_info.max_buf_size), OUTPUT, bufferp);
3054 if bufferp = null () then do;
3055 needs_space = "1"b;
3056 go to RETURN_FROM_CALLER;
3057 end;
3058
3059 addr (bufferp -> buffer.chars (0)) -> based_block_header = TEMPLATE_HASP_BLOCK_HEADER;
3060
3061 hmd.output_block.tally,
3062 bufferp -> buffer.tally = length (string (TEMPLATE_HASP_BLOCK_HEADER));
3063 hmd.output_block.first_bufferp, hmd.output_block.last_bufferp = bufferp;
3064
3065 return;
3066
3067 end start_new_output_block;
3068
3069 end cant_accept_records_from_this_device;
3070 %page;
3071
3072
3073 move_record_to_output_block:
3074 procedure (P_free_buffers);
3075
3076 dcl P_free_buffers bit (1) aligned parameter;
3077
3078 saved_output_block = hmd.output_block;
3079 saved_last_tally = hmd.output_block.last_bufferp -> buffer.tally;
3080
3081 if (hste.device_type = HASP_CONSOLE) then
3082 if (hmd.type = HASP_HOST) then
3083 call add_to_output_block (addr (HASP_CONSOLE_OUTPUT_RCB), 1);
3084 else call add_to_output_block (addr (HASP_CONSOLE_INPUT_RCB), 1);
3085 else call add_to_output_block (addr (hste.rcb), 1);
3086
3087 bufferp = start_bufferp;
3088
3089 do while (bufferp ^= null ());
3090
3091 if bufferp = start_bufferp then
3092 first_idx = start_record_idx;
3093 else first_idx = 0;
3094 if bufferp = end_bufferp then
3095 last_idx = end_record_idx;
3096 else last_idx = bufferp -> buffer.tally - 1;
3097
3098 call add_to_output_block (addr (bufferp -> buffer.chars (first_idx)),
3099 (last_idx - first_idx + 1));
3100
3101 if (bufferp = end_bufferp) then
3102 bufferp = null ();
3103 else bufferp = pointer (ttybp, bufferp -> buffer.next);
3104 end;
3105
3106 record_type = classify_record (saved_output_block.last_bufferp, saved_last_tally);
3107
3108 if (record_type = HASP_EOF_RECORD) &
3109 (hste.device_type ^= HASP_CONSOLE) & hmd.rts_mode then
3110 hste.minor_state = HSTE_SEND_RTS;
3111
3112 if P_free_buffers then
3113 do bufferp = start_bufferp
3114 repeat (p) while (bufferp ^= end_bufferp);
3115 p = pointer (ttybp, bufferp -> buffer.next);
3116 call tty_space_man$free_buffer (hste.devx, OUTPUT, bufferp);
3117 end;
3118
3119 return;
3120 %page;
3121
3122
3123
3124 add_to_output_block:
3125 procedure (P_text_ptr, P_text_lth);
3126
3127 dcl P_text_ptr pointer parameter;
3128 dcl P_text_lth fixed binary parameter;
3129
3130 dcl text character (text_lth) unaligned based (text_ptr);
3131 dcl text_ptr pointer;
3132 dcl text_lth fixed binary;
3133
3134 dcl based_substring character (substr_lth) unaligned based;
3135 dcl based_buffer_remainder character (space_left_in_buffer) unaligned based;
3136 dcl based_character character (1) unaligned based;
3137
3138 dcl (bufferp, new_bufferp) pointer;
3139 dcl (start, substr_lth, space_left_in_buffer) fixed binary;
3140 dcl add_dle bit (1) aligned;
3141
3142
3143 text_ptr = P_text_ptr;
3144 text_lth = P_text_lth;
3145
3146 bufferp = hmd.output_block.last_bufferp;
3147
3148 start = 1;
3149
3150 do while (start <= text_lth);
3151
3152 space_left_in_buffer = max_buffer_tally (bufferp -> buffer.size_code)
3153 - (bufferp -> buffer.tally);
3154
3155 substr_lth = index (substr (text, start), DLE);
3156
3157 if substr_lth ^= 0 then
3158 add_dle = "1"b;
3159 else do;
3160 substr_lth = text_lth - start + 1;
3161 add_dle = "0"b;
3162 end;
3163
3164 do while (space_left_in_buffer < substr_lth);
3165 if space_left_in_buffer > 0 then do;
3166 addr (bufferp -> buffer.chars (bufferp -> buffer.tally)) -> based_buffer_remainder
3167 = substr (text, start, space_left_in_buffer);
3168 bufferp -> buffer.tally = max_buffer_tally (bufferp -> buffer.size_code);
3169 start = start + space_left_in_buffer;
3170 substr_lth = substr_lth - space_left_in_buffer;
3171 end;
3172 call tty_space_man$get_buffer (hmd.devx, (hmd.dialup_info.max_buf_size), OUTPUT,
3173 new_bufferp);
3174 if new_bufferp = null () then go to NO_MORE_ROOM;
3175 bufferp -> buffer.next = binary (rel (new_bufferp), 18, 0);
3176 hmd.output_block.last_bufferp, bufferp = new_bufferp;
3177 space_left_in_buffer = max_buffer_tally (bufferp -> buffer.size_code);
3178 end;
3179
3180 if substr_lth ^= 0 then do;
3181 addr (bufferp -> buffer.chars (bufferp -> buffer.tally)) -> based_substring =
3182 substr (text, start, substr_lth);
3183 bufferp -> buffer.tally = (bufferp -> buffer.tally) + substr_lth;
3184 start = start + substr_lth;
3185 end;
3186
3187 if add_dle then do;
3188 if (bufferp -> buffer.tally) = max_buffer_tally (bufferp -> buffer.size_code)
3189 then do;
3190 call tty_space_man$get_buffer (hmd.devx, (hmd.dialup_info.max_buf_size), OUTPUT,
3191 new_bufferp);
3192 if new_bufferp = null () then go to NO_MORE_ROOM;
3193 bufferp -> buffer.next = binary (rel (new_bufferp), 18, 0);
3194 hmd.output_block.last_bufferp, bufferp = new_bufferp;
3195 end;
3196 addr (bufferp -> buffer.chars (bufferp -> buffer.tally)) -> based_character = DLE;
3197 bufferp -> buffer.tally = (bufferp -> buffer.tally) + 1;
3198 hmd.output_block.tally = hmd.output_block.tally + 1;
3199 end;
3200 end;
3201
3202 hmd.output_block.tally = hmd.output_block.tally + text_lth;
3203
3204
3205 return;
3206
3207
3208
3209
3210
3211 NO_MORE_ROOM: hmd.output_block = saved_output_block;
3212 hmd.output_block.last_bufferp -> buffer.tally = saved_last_tally;
3213
3214 if (hmd.output_block.last_bufferp -> buffer.next) ^= 0
3215 then do;
3216 bufferp = pointer (ttybp, hmd.output_block.last_bufferp -> buffer.next);
3217 call tty_space_man$free_chain (hmd.devx, OUTPUT, bufferp);
3218 hmd.output_block.last_bufferp -> buffer.next = 0;
3219 end;
3220
3221 needs_space = "1"b;
3222
3223 if loopback_entry then
3224 go to RETURN_FROM_CALLER;
3225 else go to RETURN_FROM_PROCESS_OUTPUT_RECORDS;
3226
3227 end add_to_output_block;
3228
3229 end move_record_to_output_block;
3230 %page;
3231
3232
3233
3234 count_dles: procedure (P_bufferp) returns (fixed binary);
3235
3236 dcl P_bufferp pointer parameter;
3237
3238 dcl buffer_text character (bufferp -> buffer.tally) based (addr (bufferp -> buffer.chars (0)));
3239
3240 dcl bufferp pointer;
3241 dcl (start, idx, dle_count) fixed binary;
3242
3243
3244 bufferp = P_bufferp;
3245
3246 start = 1;
3247 idx = index (buffer_text, DLE);
3248
3249 dle_count = 0;
3250
3251 do while (idx ^= 0);
3252 dle_count = dle_count + 1;
3253 start = start + idx;
3254 if start > (bufferp -> buffer.tally) then
3255 idx = 0;
3256 else idx = index (substr (buffer_text, start), DLE);
3257 end;
3258
3259 return (dle_count);
3260
3261 end count_dles;
3262
3263 end output_records_processor;
3264 %page;
3265
3266
3267
3268 transmit_output_block:
3269 procedure ();
3270
3271 dcl p pointer;
3272
3273
3274 if ^hmd.send_output then return;
3275
3276 if hmd.output_chain_ptr ^= null () then do;
3277 p = hmd.output_chain_ptr;
3278
3279 call channel_manager$write (hmd.devx, p, code);
3280 if code = 0 then
3281 hmd.retry_transmit_output = "0"b;
3282 else if code = et_noalloc
3283 then do;
3284 hmd.retry_transmit_output = "1"b;
3285 call tty_space_man$needs_space (hmd.devx);
3286 end;
3287 else return;
3288
3289 hmd.output_chain_ptr = p;
3290 hmd.send_output = "0"b;
3291 end;
3292
3293 if hmd.output_chain_ptr = null () then
3294 hmd.output_in_progress = "0"b;
3295 else hmd.output_in_progress = "1"b;
3296
3297 return;
3298
3299 end transmit_output_block;
3300 %page;
3301
3302
3303 do_line_control:
3304 procedure (P_line_ctl_opcode, P_line_ctl_val1, P_line_ctl_val2, P_line_ctl_val3);
3305
3306 dcl (P_line_ctl_opcode, P_line_ctl_val1, P_line_ctl_val2, P_line_ctl_val3) fixed binary parameter;
3307
3308 line_ctl.op = P_line_ctl_opcode;
3309
3310 line_ctl.val (1) = P_line_ctl_val1;
3311 line_ctl.val (2) = P_line_ctl_val2;
3312 line_ctl.val (3) = P_line_ctl_val3;
3313
3314 call channel_manager$control (hmd.devx, "line_control", addr (line_ctl), code);
3315
3316 if code = 0 then
3317 return;
3318 else go to LOADING_FAILS;
3319
3320 end do_line_control;
3321 %page;
3322
3323
3324
3325 process_line_status:
3326 procedure ();
3327
3328 if (line_stat.op < lbound (LINE_STATUS, 1)) | (line_stat.op > hbound (LINE_STATUS, 1)) then
3329 return;
3330
3331 else go to LINE_STATUS (line_stat.op);
3332
3333
3334 LINE_STATUS (1):
3335 if hmd.state = HMD_LOADING then do;
3336 call crash_mpx ();
3337 call pxss$ring_0_wakeup (hmd.loader_process_id, hmd.loader_event_channel, HASP_MPX_DOWN, code);
3338 end;
3339 return;
3340
3341
3342 LINE_STATUS (2):
3343 call syserr (LOG_AND_PRINT,
3344 "hasp_mpx (line ^a): Bad block line status from FNP; line will be hungup.", hmd.name);
3345 call channel_manager$control (hmd.devx, "hangup", null (), code);
3346 return;
3347
3348
3349 LINE_STATUS (4):
3350 call syserr (LOG_AND_PRINT, "hasp_mpx (line ^a): Too many NAKS; line will be hungup.", hmd.name);
3351 call channel_manager$control (hmd.devx, "hangup", null (), code);
3352 return;
3353
3354
3355 LINE_STATUS (6):
3356 if hmd.minor_state ^= HMD_WAIT_SIGNON_RESPONSE then
3357 return;
3358 if hmd.signon_data_ptr ^= null () then do;
3359 hsd_ptr = hmd.signon_data_ptr;
3360 call pxss$ring_0_wakeup (hmd_signon_data.processid, hmd_signon_data.event_channel, HASP_SIGNON_OK,
3361 code);
3362 call tty_space_man$free_space (currentsize (hmd_signon_data), hsd_ptr);
3363 hmd.signon_data_ptr = null ();
3364 end;
3365 hmd.minor_state = HMD_NORMAL;
3366 if (hmd.state = HMD_STARTED) then
3367 do idx = 1 to hmd.n_subchannels;
3368 hste_ptr = addr (hmd.subchannels (idx));
3369 if hste.state = HSTE_LISTENING then
3370 call signal_dialup ();
3371 end;
3372 call interrupt_subchannels_with_output ();
3373 return;
3374
3375
3376 LINE_STATUS (13):
3377 if hmd.state = HMD_LOADING then
3378 call load_mpx ();
3379 return;
3380
3381
3382 LINE_STATUS (14):
3383 hmd.suspend_all_output = "0"b;
3384 if hmd.state >= HMD_LOADED then
3385 if hmd.minor_state = HMD_REPROCESS then
3386 call process_loopback_records ();
3387 else call process_output_block ();
3388 return;
3389
3390 LINE_STATUS (3):
3391 LINE_STATUS (5):
3392 LINE_STATUS (7): LINE_STATUS (8): LINE_STATUS (9):
3393 LINE_STATUS (10): LINE_STATUS (11): LINE_STATUS (12):
3394 return;
3395
3396 end process_line_status;
3397 %page;
3398
3399
3400
3401 process_space_available:
3402 procedure ();
3403
3404 if hmd.retry_transmit_output then do;
3405 call transmit_output_block ();
3406 if hmd.retry_transmit_output then return;
3407 end;
3408
3409 if hmd.retry_process_loopback_records then
3410 call process_loopback_records ();
3411
3412 else if hmd.retry_process_output then
3413 call process_output_block ();
3414
3415 if hmd.retry_process_input then
3416 call process_input_records ();
3417
3418 call interrupt_subchannels_with_output ();
3419
3420 return;
3421
3422 end process_space_available;
3423 %page;
3424
3425
3426 find_next_record:
3427 procedure (P_start_bufferp, P_start_record_idx, P_rcb_included, P_count_dles,
3428 P_end_bufferp, P_end_record_idx, P_record_tally, P_dle_count);
3429
3430 dcl P_start_bufferp pointer parameter;
3431 dcl P_start_record_idx fixed binary parameter;
3432 dcl P_rcb_included bit (1) aligned parameter;
3433 dcl P_count_dles bit (1) aligned parameter;
3434
3435 dcl P_end_bufferp pointer parameter;
3436 dcl P_end_record_idx fixed binary parameter;
3437
3438 dcl P_record_tally fixed binary parameter;
3439 dcl P_dle_count fixed binary parameter;
3440
3441 dcl (bufferp, previous_bufferp) pointer;
3442 dcl (record_idx, previous_record_idx, record_tally, dle_count) fixed binary;
3443 dcl (count_dles_sw, end_of_data_is_special) bit (1) aligned;
3444
3445 dcl scb_char character (1) unaligned;
3446
3447 dcl 1 scb unaligned based (addr (scb_char)) like hasp_scb_byte;
3448 dcl 1 compressed_scb unaligned based (addr (scb_char)) like hasp_compressed_scb_byte;
3449 dcl 1 not_compressed_scb unaligned based (addr (scb_char)) like hasp_not_compressed_scb_byte;
3450
3451
3452 P_end_bufferp = null ();
3453 P_end_record_idx, P_record_tally, P_dle_count = 0;
3454
3455 bufferp = P_start_bufferp;
3456 record_idx = P_start_record_idx;
3457 count_dles_sw = P_count_dles;
3458
3459 record_tally, dle_count = 0;
3460
3461 end_of_data_is_special = "0"b;
3462
3463
3464
3465
3466
3467 if P_rcb_included then
3468
3469 if (bufferp -> buffer.chars (record_idx) = HASP_EOB_RCB) then
3470 go to SUCCESSFUL_RETURN_FROM_FIND_NEXT_RECORD;
3471
3472 else if (bufferp -> buffer.chars (record_idx) = HASP_GENERAL_CONTROL_RCB)
3473 then do;
3474
3475 call advance_pointer (1);
3476 end_of_data_is_special = "1"b;
3477 do while ("1"b);
3478 previous_bufferp = bufferp;
3479 previous_record_idx = record_idx;
3480 call advance_pointer (1);
3481 if (bufferp -> buffer.chars (record_idx) = NUL) then do;
3482 END_OF_GENERAL_CONTROL_RECORD_SCAN: bufferp = previous_bufferp;
3483 record_idx = previous_record_idx;
3484 record_tally = record_tally - 1;
3485 go to SUCCESSFUL_RETURN_FROM_FIND_NEXT_RECORD;
3486 end;
3487 end;
3488 end;
3489
3490 else call advance_pointer (2);
3491
3492 else call advance_pointer (1);
3493
3494
3495
3496
3497 do while ("1"b);
3498
3499 scb_char = bufferp -> buffer.chars (record_idx);
3500
3501 if scb_char = HASP_EOR_SCB then
3502 go to SUCCESSFUL_RETURN_FROM_FIND_NEXT_RECORD;
3503
3504 else
3505 if scb.not_compressed then
3506 call advance_pointer (not_compressed_scb.count + 1);
3507
3508 else if compressed_scb.not_blank then
3509 call advance_pointer (2);
3510 else call advance_pointer (1);
3511 end;
3512
3513
3514
3515
3516
3517 SUCCESSFUL_RETURN_FROM_FIND_NEXT_RECORD:
3518 P_end_bufferp = bufferp;
3519 P_end_record_idx = record_idx;
3520 P_record_tally = record_tally + 1;
3521 P_dle_count = dle_count;
3522
3523 RETURN_FROM_FIND_NEXT_RECORD:
3524 return;
3525 %page;
3526
3527
3528 advance_pointer:
3529 procedure (P_n_characters);
3530
3531 dcl P_n_characters fixed binary parameter;
3532
3533 dcl (amount_left, amount_in_buffer) fixed binary;
3534
3535
3536 record_tally = record_tally + P_n_characters;
3537
3538
3539 amount_left = P_n_characters;
3540
3541 do while (amount_left > 0);
3542
3543 amount_in_buffer = (bufferp -> buffer.tally) - record_idx;
3544
3545 if amount_in_buffer > amount_left
3546 then do;
3547 dle_count = dle_count + count_dles (amount_left);
3548 record_idx = record_idx + amount_left;
3549 amount_left = 0;
3550 end;
3551
3552 else do;
3553 previously_scanned_bufferp = bufferp;
3554 dle_count = dle_count + count_dles (amount_in_buffer);
3555 amount_left = amount_left - amount_in_buffer;
3556 if (bufferp -> buffer.next) = 0 then
3557 if end_of_data_is_special then
3558 go to END_OF_GENERAL_CONTROL_RECORD_SCAN;
3559 else do;
3560 P_record_tally = record_tally - amount_left;
3561 P_dle_count = dle_count;
3562 go to RETURN_FROM_FIND_NEXT_RECORD;
3563 end;
3564 bufferp = pointer (ttybp, bufferp -> buffer.next);
3565 record_idx = 0;
3566 end;
3567 end;
3568
3569 return;
3570
3571
3572
3573
3574
3575 count_dles: procedure (P_n_characters) returns (fixed binary);
3576
3577 dcl P_n_characters fixed binary parameter;
3578
3579 dcl text character (n_characters) unaligned based (addr (bufferp -> buffer.chars (record_idx)));
3580 dcl (n_characters, count, start, idx) fixed binary;
3581
3582
3583 if ^count_dles_sw then
3584 return (0);
3585
3586 n_characters = P_n_characters;
3587
3588 count = 0;
3589
3590 start = 1;
3591 idx = index (text, DLE);
3592
3593 do while (idx ^= 0);
3594 count = count + 1;
3595 start = start + idx;
3596 if start > n_characters then
3597 idx = 0;
3598 else idx = index (substr (text, start), DLE);
3599 end;
3600
3601 return (count);
3602
3603 end count_dles;
3604
3605 end advance_pointer;
3606
3607 end find_next_record;
3608 %page;
3609
3610
3611 classify_record:
3612 procedure (P_bufferp, P_rcb_idx) returns (fixed binary);
3613
3614 dcl P_bufferp pointer parameter;
3615 dcl P_rcb_idx fixed binary parameter;
3616
3617 dcl bufferp pointer;
3618 dcl rcb_idx fixed binary;
3619
3620 dcl rcb_char character (1) unaligned;
3621 dcl srcb_char character (1) unaligned;
3622 dcl first_scb_char character (1) unaligned;
3623
3624 dcl 1 rcb unaligned based (addr (rcb_char)) like hasp_rcb_byte;
3625
3626
3627
3628
3629 bufferp = P_bufferp;
3630 rcb_idx = P_rcb_idx;
3631
3632 if rcb_idx < bufferp -> buffer.tally then
3633 rcb_char = bufferp -> buffer.chars (rcb_idx);
3634 else
3635 if bufferp -> buffer.next = 0 then
3636 return (0);
3637 else do;
3638 bufferp = pointer (ttybp, bufferp -> buffer.next);
3639 rcb_idx = 0;
3640 rcb_char = bufferp -> buffer.chars (0);
3641 end;
3642
3643 if rcb_idx < (bufferp -> buffer.tally - 1) then
3644 srcb_char = bufferp -> buffer.chars (rcb_idx+1);
3645 else
3646 if bufferp -> buffer.next = 0 then
3647 srcb_char = NUL;
3648 else do;
3649 bufferp = pointer (ttybp, bufferp -> buffer.next);
3650 rcb_idx = -1;
3651 srcb_char = bufferp -> buffer.chars (0);
3652 end;
3653
3654 if rcb_idx < (bufferp -> buffer.tally - 2) then
3655 first_scb_char = bufferp -> buffer.chars (rcb_idx+2);
3656 else
3657 if bufferp -> buffer.next = 0 then
3658 first_scb_char = NUL;
3659 else first_scb_char = pointer (ttybp, bufferp -> buffer.next) -> buffer.chars (0);
3660
3661
3662
3663
3664 if rcb.not_eob then
3665
3666 if rcb.type = HASP_RCB_TYPE_CONTROL then
3667
3668 if rcb.stream = HASP_RCB_STREAM_RTS then
3669 return (HASP_RTS_RECORD);
3670
3671 else if rcb.stream = HASP_RCB_STREAM_RTS_ACK then
3672 return (HASP_RTS_ACK_RECORD);
3673
3674 else if rcb.stream = HASP_RCB_STREAM_BAD_BCB then
3675 return (HASP_BAD_BCB_RECORD);
3676
3677 else if rcb.stream = HASP_RCB_STREAM_CONTROL then
3678 if srcb_char = HASP_SIGNON_SRCB then
3679 return (HASP_SIGNON_RECORD);
3680 else return (0);
3681 else return (0);
3682
3683 else if (srcb_char = HASP_EOF_SRCB) & (first_scb_char = HASP_EOF_FIRST_SCB) then
3684 return (HASP_EOF_RECORD);
3685
3686 else return (HASP_DATA_RECORD);
3687
3688 else return (HASP_EOB_RECORD);
3689
3690 end classify_record;
3691 %page;
3692
3693
3694 empty_output_blockp:
3695 procedure () returns (bit (1) aligned);
3696
3697 if hmd.output_block.first_bufferp = null () then
3698 return ("1"b);
3699
3700 else return (hmd.output_block.tally <= length (string (TEMPLATE_HASP_BLOCK_HEADER)));
3701
3702 end empty_output_blockp;
3703
3704
3705
3706
3707
3708 space_in_output_block_for_recordp:
3709 procedure (P_record_lth) returns (bit (1) aligned);
3710
3711 dcl P_record_lth fixed binary parameter;
3712
3713 return
3714 (hmd.max_block_size >=
3715 (hmd.output_block.tally + P_record_lth + length (string (TEMPLATE_HASP_BLOCK_TRAILER))));
3716
3717 end space_in_output_block_for_recordp;
3718
3719
3720
3721
3722
3723 full_output_blockp:
3724 procedure () returns (bit (1) aligned);
3725
3726 if empty_output_blockp () then
3727 return ("0"b);
3728 else return (^space_in_output_block_for_recordp (length (string (TEMPLATE_HASP_RTS_RECORD))));
3729
3730
3731 end full_output_blockp;
3732
3733
3734
3735
3736
3737 space_in_empty_output_block_for_recordp:
3738 procedure (P_record_lth) returns (bit (1) aligned);
3739
3740 dcl P_record_lth fixed binary parameter;
3741
3742 return
3743 (hmd.max_block_size >=
3744 (P_record_lth + length (string (TEMPLATE_HASP_BLOCK_HEADER)) +
3745 length (string (TEMPLATE_HASP_BLOCK_TRAILER))));
3746
3747 end space_in_empty_output_block_for_recordp;
3748 %page;
3749
3750
3751 delete_text:
3752 procedure (P_bufferp, P_position, P_text_lth);
3753
3754 dcl P_bufferp pointer parameter;
3755 dcl P_position fixed binary parameter;
3756 dcl P_text_lth fixed binary parameter;
3757
3758 dcl based_remainder character (remainder_lth) unaligned based;
3759 dcl remainder_lth fixed binary;
3760
3761
3762 remainder_lth = (P_bufferp -> buffer.tally) - P_text_lth - P_position;
3763
3764 addr (P_bufferp -> buffer.chars (P_position)) -> based_remainder =
3765 addr (P_bufferp -> buffer.chars (P_position+P_text_lth)) -> based_remainder;
3766
3767 P_bufferp -> buffer.tally = (P_bufferp -> buffer.tally) - P_text_lth;
3768
3769 return;
3770
3771 end delete_text;
3772
3773
3774
3775
3776
3777 trace_block:
3778 procedure (P_first_bufferp, P_direction);
3779
3780 dcl P_first_bufferp pointer parameter;
3781 dcl P_direction bit (1) parameter;
3782
3783 call mcs_trace (hmd.devx, "^[Output^;Input^] chain starting at ^p:", P_direction, P_first_bufferp);
3784
3785 call mcs_trace$buffer_chain (hmd.devx, P_first_bufferp);
3786
3787 return;
3788
3789 end trace_block;
3790 %page;
3791 %include hasp_mpx_data;
3792 %page;
3793 %include hasp_load_data;
3794 %page;
3795 %include hasp_mpx_meters;
3796 %page;
3797 %include hasp_subchannel_meters;
3798 %page;
3799 %include hasp_block_record_data;
3800
3801 %include hasp_rcb_byte;
3802
3803 %include hasp_srcb_scb_bytes;
3804 %page;
3805 %include hasp_signon_record_info;
3806 %page;
3807 %include bisync_line_data;
3808 %page;
3809 %include mcs_interrupt_info;
3810 %page;
3811 %include tty_buffer_block;
3812 %page;
3813 %include mcs_modes_change_list;
3814 %page;
3815 %include channel_manager_dcls;
3816
3817 %include tty_space_man_dcls;
3818 %page;
3819 %include lct;
3820 %page;
3821 %include get_comm_meters_info;
3822 %page;
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856 note
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869 note
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897 note
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911 note
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927 note
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940 note
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953 end hasp_mpx;