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