1 /****^  *********************************************************
   2         *                                                       *
   3         * Copyright, (C) BULL HN Information Systems Inc., 1989 *
   4         *                                                       *
   5         * Copyright, (C) Honeywell Bull Inc., 1989              *
   6         *                                                       *
   7         * Copyright (c) 1972 by Massachusetts Institute of      *
   8         * Technology and Honeywell Information Systems, Inc.    *
   9         *                                                       *
  10         ********************************************************* */
  11 
  12 
  13 
  14 /****^  HISTORY COMMENTS:
  15   1) change(89-03-20,Parisek), approve(89-06-01,MCR8110),
  16      audit(89-10-09,Farley), install(89-10-25,MR12.3-1100):
  17      Add support of protocol mpx.
  18                                                    END HISTORY COMMENTS */
  19 
  20 
  21 /* format: style4,delnl,insnl,ifthenstmt,indnoniterend */
  22 x25_mpx:
  23      procedure;
  24 
  25 /* This procedure contains the non-privileged entries of the x25
  26    multiplexer.  These entries can be invoked at interrupt time
  27    and therefore must be wired.
  28 
  29    Coded December 1978 by J. Stern
  30    Modified July, 1979 by B.Westcott to support x25 level 3 protocol
  31    Rewritten April 1980 by C. Hornig for installation
  32    Problem with stop_mpx fixed October 1980 by C. Hornig
  33    Modified to fix interrupts and trap bad packet format, October 1981, by C. Hornig.
  34    Modified for flexible channel definitions, January 1982, by C. Hornig.
  35    Modified to delete the HOST level 2 mpx, May 1982, by D. W. Cousins.
  36    Modified to handle MASKED interrupt, August 1982, by Robert Coren.
  37    Modified for MR10.1 improvements, January 1983, by C. Hornig
  38    Modified for TELENET certification, and to cause the multiplexer rather than
  39    the system to crash when tty_buf is full, February 1983, by R.J.C. Kissel.
  40    Modified to fix a bug in handling data and flow control packets in DTE_RESET_REQUEST
  41    state, March 1983, by R.J.C. Kissel.
  42    Modified to correct a bug which only allows 11 chars of address for an x29 call request, June 1983, by R.J.C. Kissel.
  43    Modified by Jis for Telenet parameter negotiation corrections. 6/23/83
  44    Modified by Jis to allow reverse charging connect request per physical connection. August 1983.
  45    Modified to bring some rationality to PAD parameter setting and to fix a problem with QUIT on TELENET,
  46    August 1983, by R.J.C. Kissel.
  47    Modified to handle the new line status from the FNP which means frame sizes are mis-matched,
  48    April 1984, by R.J.C. Kissel (x25 error list #13).
  49    Modified to discard output data on RESET CONFIRM, October 1984, by R.J.C. Kissel (x25 error list #12).
  50    Modified to make a consistency check on P(r), October 1984, by R.J.C. Kissel (x25 error list #11).
  51    Modified October 1984 by R.J.C. Kissel to use the value of the idle timer in the TTF for breakall mode.
  52    Modified October 1984 by R.J.C. Kissel to not send empty packets for write_status, if we haven't heard from the last one (x25 error list #14).
  53    Modified December 1984 by R.J.C. Kissel to make discarding ouput on RESET CONFIRM really work.
  54    Modified January 1985 by R.J.C. Kissel to send line status on reset, and to fix clearing on idle VC.
  55    Modified April 1985 by R.J.C. Kissel to handle multiple crash/hangup interrupts in interrupt 2, 3, and 17. (x25 error list #15).
  56 */
  57 
  58 /* Parameters */
  59 
  60 dcl  x25_chain_ptr ptr parameter;                           /* ptr to write chain (input) */
  61 dcl  x25_code fixed bin (35) parameter;                     /* error code (output) */
  62 dcl  x25_infop ptr parameter;                               /* ptr to control order info structure (input) */
  63 dcl  x25_int_data bit (72) aligned parameter;               /* interrupt data (input) */
  64 dcl  x25_int_type fixed bin parameter;                      /* interrupt type (input) */
  65 dcl  x25_modes char (*) parameter;                          /* mode string (output) */
  66 dcl  x25_order char (*) parameter;                          /* control order name (input) */
  67 dcl  X25_data_ptr ptr parameter;                            /* ptr to multiplexer data base (input) */
  68 dcl  x25_mclp ptr parameter;                                /* ptr to modes change list */
  69 dcl  X25_scx fixed bin parameter;                           /* subchannel number (input) */
  70 
  71 /* Automatic */
  72 
  73 dcl  (endp, prev_blockp, chain_ptr, leftover_chain_ptr) ptr;
  74 dcl  (called_dte_addr_length, calling_dte_addr_length) unsigned fixed bin (4);
  75 dcl  (facility_disp, user_data_disp, facility_length, user_data_length) fixed bin;
  76 dcl  temp_ps unsigned fixed bin (7);
  77 dcl  lcx uns fixed bin (12);
  78 dcl  scx fixed bin;
  79 dcl  code fixed bin (35);
  80 dcl  (i, j) fixed bin;
  81 dcl  infop ptr;
  82 dcl  int_data bit (72) aligned;
  83 dcl  int_type fixed bin;
  84 dcl  (hdr_size, nchars) fixed bin (21);
  85 dcl  mode_found bit (1) aligned;
  86 dcl  order char (32) aligned;
  87 dcl  addr_string char (30) aligned;
  88 dcl  set_entry bit (1) aligned;
  89 dcl  pr_error bit (1) unaligned;
  90 dcl  protocol_mpx bit (1) unaligned;
  91 dcl  Call_data char (16);                                   /* variable conversion of the call data - */
  92                                                             /* Based */
  93 
  94 dcl  1 write_status_info aligned based (infop),
  95        2 ev_chan fixed bin (71),
  96        2 output_pending bit (1);
  97 
  98 dcl  dial_out_info aligned varying char (24) based (infop);
  99 dcl  1 reason_of_hangup aligned based (infop) like NDIS_IND_REASON;
 100 dcl  1 N_I_i aligned based (addr (buffer.chars)) like NCON_IND_info;
 101 dcl  1 ifci aligned like input_flow_control_info based (infop);
 102 dcl  1 ofci aligned like output_flow_control_info based (infop);
 103 dcl  1 ftd aligned like foreign_terminal_data based (infop);
 104 
 105 dcl  1 lap_down_status aligned based (addr (x25_int_data)),
 106        2 link_down_status uns fixed bin (18) unaligned,     /* 1 */
 107        2 last_function_process fixed bin (17) unaligned,    /* coded function */
 108        2 which_state_process uns fixed bin (9) unaligned,   /* process state */
 109        2 main_state uns fixed bin (9) unaligned,            /* current frame level state */
 110        2 primary_sub_state uns fixed bin (9) unaligned,     /* sub link up state */
 111        2 secondary_sub_state uns fixed bin (9) unaligned;
 112 
 113 dcl  1 lap_cmdr_status aligned based (addr (x25_int_data)),
 114        2 cmdr_status uns fixed bin (18) unaligned,          /* constant 3 */
 115        2 cmdr_bytes (3) unaligned,                          /* I-frame at fault */
 116          3 pad bit (1) unaligned,                           /* N(s) & N(r) */
 117          3 byte bit (8) unaligned,                          /* flags w,x,y,z */
 118        2 pad bit (27) unaligned;
 119 
 120 dcl  1 x25_pkt aligned based (blockp),
 121        2 buffer_header bit (36),
 122        2 l2_pad char (2 /* L2_HEADER_PAD */) unal,
 123        2 l3_header unal,
 124          3 pad1 bit (1) unal,
 125          3 q bit (1) unal,                                  /* data qualifier */
 126          3 d bit (1) unal,                                  /* significance of P(R) across net */
 127          3 format bit (2) unal,                             /* general format identifier */
 128          3 lcgn bit (4) unal,                               /* Logical Channel Group Number */
 129          3 pad2 bit (1) unal,
 130          3 lcn bit (8) unal,                                /* Logical Channel Number */
 131        2 l3_fc bit (0) unal,                                /* start of flow-control data */
 132        2 pad3 bit (1) unal,
 133        2 type bit (8) unal,                                 /* packet type */
 134        2 no_fc_data (56) bit (9) unal;
 135 
 136 dcl  l3_call_data char (user_data_length) based (addr (x25_pkt.no_fc_data (user_data_disp)));
 137 
 138 dcl  l3_facilities char (facility_length) based (addr (x25_pkt.no_fc_data (facility_disp + 1)));
 139 dcl  1 m8_fc_data unal based (addr (x25_pkt.l3_fc)),        /* flow-control data for mod-8 */
 140        2 pad bit (1),
 141        2 pr uns fixed bin (3),                              /* P(R) */
 142        2 m bit (1),                                         /* More Data */
 143        2 ps uns fixed bin (3),                              /* P(S) */
 144        2 data_sw bit (1),
 145        2 user_data bit (0);
 146 
 147 dcl  1 m128_fc_data unal based (addr (x25_pkt.l3_fc)),
 148        2 pad1 bit (1),
 149        2 ps uns fixed bin (7),
 150        2 data_sw bit (1),
 151        2 pad2 bit (1),
 152        2 pr uns fixed bin (7),
 153        2 m bit (1),
 154        2 user_data bit (0);
 155 
 156 dcl  l4_data_ptr ptr;
 157 dcl  l4_data (56) bit (9) unal based (l4_data_ptr);
 158 
 159 dcl  based_area area based;
 160 
 161 /* Constants */
 162 
 163 dcl  L2_HEADER_PAD fixed bin static options (constant) init (2);
 164 dcl  TIMEOUT fixed bin (71) static options (constant) init (1000000);
 165 dcl  T20 fixed bin (71) static options (constant) init (180000000);
 166 dcl  MPX_UP fixed bin (71) static options (constant) init (1);
 167 dcl  MPX_DOWN fixed bin (71) static options (constant) init (2);
 168 dcl  MPX_MASKED fixed bin (71) static options (constant) init (3);
 169 dcl  DEFAULT_BAUD fixed bin internal static options (constant) init (1200);
 170 dcl  (
 171      MODE_RAWI init (1),
 172      MODE_ECHOPLEX init (2),
 173      MODE_BREAKALL init (3),
 174      MODE_IFLOW init (4),
 175      MODE_OFLOW init (5),
 176      MODE_HNDLQUIT init (6),
 177      MODE_LFECHO init (7),
 178      MODE_POLITE init (8),
 179      MODE_8BIT init (9)
 180      ) fixed bin static options (constant);
 181 dcl  mode_names (11) char (8) aligned static options (constant)
 182           init ("rawi", "echoplex", "breakall", "iflow", "oflow", "hndlquit", "lfecho", "polite", "8bit", "oddp",
 183           "no_outp");
 184 
 185 dcl  CALLRQ bit (8) unal static options (constant) init ("0b"b4);
 186                                                             /* call request or call indication (DCE) */
 187 dcl  CALLAC bit (8) unal static options (constant) init ("0f"b4);
 188                                                             /* call accept or call connected (DCE) */
 189 dcl  CLRRQ bit (8) unal static options (constant) init ("13"b4);
 190                                                             /* clear request or clear indication */
 191 dcl  CLRCN bit (8) unal static options (constant) init ("17"b4);
 192                                                             /* clear-confirm (DCE) */
 193 dcl  RSRTRQ bit (8) unal static options (constant) init ("fb"b4);
 194                                                             /* restart request or restart indication (DCE) */
 195 dcl  RSRTCN bit (8) unal static options (constant) init ("ff"b4);
 196                                                             /* restart confirm (DCE) */
 197 dcl  DIAG bit (8) unal static options (constant) init ("f1"b4);
 198                                                             /* diagnostic */
 199 dcl  RESTRQ bit (8) unal static options (constant) init ("1b"b4);
 200                                                             /* reset request or reset indication (DCE) */
 201 dcl  RESTCN bit (8) unal static options (constant) init ("1f"b4);
 202                                                             /* reset confirm (DCE) */
 203 dcl  SNITRQ bit (8) unal static options (constant) init ("23"b4);
 204                                                             /* interrupt request or interrupt indication (DCE) */
 205 dcl  SNITCN bit (8) unal static options (constant) init ("27"b4);
 206                                                             /* interrupt confirm (DCE) */
 207 dcl  SNRR bit (8) unal static options (constant) init ("01"b4);
 208                                                             /* receiver ready (DCE) */
 209 dcl  SNRNR bit (8) unal static options (constant) init ("05"b4);
 210                                                             /* receiver not ready (DCE) */
 211 dcl  SNREJ bit (8) unal static options (constant) init ("09"b4);
 212 dcl  SNMASK bit (8) unal static options (constant) init ("0f"b4);
 213                                                             /* mask for sequence control packets */
 214 dcl  NL char (1) static options (constant) init ("
 215 ");                                                         /* new-line character */
 216 dcl  CR_LF_FF char (3) int static options (constant) init ("^M
 217 ^L");                                                       /* CR, LF, FF */
 218 
 219 /* Internal static */
 220 
 221 dcl  et_action_not_performed fixed bin (35) static;
 222 dcl  et_bad_arg fixed bin (35) static;
 223 dcl  et_bad_mode fixed bin (35) static;
 224 dcl  et_invalid_state fixed bin (35) static;
 225 dcl  et_noalloc fixed bin (35) static;
 226 dcl  et_resource_unavailable fixed bin (35) static;
 227 dcl  et_undefined_order_request fixed bin (35) static;
 228 dcl  et_unimplemented_version fixed bin (35) static;
 229 
 230 /* External static */
 231 
 232 dcl  error_table_$action_not_performed fixed bin (35) ext static;
 233 dcl  error_table_$bad_arg fixed bin (35) ext static;
 234 dcl  error_table_$bad_mode fixed bin (35) ext static;
 235 dcl  error_table_$invalid_state fixed bin (35) ext static;
 236 dcl  error_table_$noalloc fixed bin (35) ext static;
 237 dcl  error_table_$resource_unavailable fixed bin (35) ext static;
 238 dcl  error_table_$undefined_order_request fixed bin (35) ext static;
 239 dcl  error_table_$unimplemented_version fixed bin (35) ext static;
 240 
 241 dcl  x25_mpx_data$trans_no_parity char (256) aligned external;
 242 dcl  x25_mpx_data$trans_no_parity_lfecho char (256) aligned external;
 243 dcl  x25_mpx_data$trans_parity_lfecho char (256) aligned external;
 244 dcl  x25_mpx_data$eight_bit char (512) aligned external;
 245 dcl  based_trans_table char (512) aligned based;
 246 
 247 /* Builtins */
 248 
 249 dcl  (addr, after, before, binary, bit, clock, dimension, divide, hbound, lbound, length, min, mod, null, pointer, rel,
 250      rtrim, size, string, substr, unspec, verify) builtin;
 251                                                             /* Entries */
 252 
 253 dcl  mrl_ entry (ptr, fixed bin (21), ptr, fixed bin (21));
 254 dcl  mvt_ entry (ptr, ptr, fixed bin (21), char (512) aligned);
 255 dcl  pxss$ring_0_wakeup entry (bit (36) aligned, fixed bin (71), fixed bin (71), fixed bin (35));
 256 dcl  syserr entry options (variable);
 257 dcl  wire_proc$wire_me entry;
 258 %page;
 259 /* * * * * * * * * * CONTROL * * * * * * * * * */
 260 
 261 control:
 262      entry (X25_data_ptr, X25_scx, x25_order, x25_infop, x25_code);
 263 
 264           call setup_subchan;
 265           order = x25_order;
 266           infop = x25_infop;
 267           pinfop = infop;
 268           x25_code = 0;
 269 
 270           protocol_mpx = get_protocol_sc ();
 271 
 272           if xlcep = null ()                                /* do we have a connection? */
 273           then if /* case */ order = "listen" then do;      /* no */
 274                     xsce.state = SC_LISTENING;              /* listen for subchan to dial up */
 275                     end;
 276 
 277                else if order = "dial_out" then do;          /* initiate connection? */
 278                     if x25_data.lc_ptr = null () then do;
 279                          x25_code = et_invalid_state;
 280                          return;
 281                          end;
 282                     do lcx = x25_data.n_lc by -1 to 1 + x25_data.n_pvc while (x25_lces.lc (lcx).state ^= READY);
 283                                                             /* search for a free subchannel */
 284                     end;
 285                     if lcx < 1 then do;
 286                          x25_code = et_resource_unavailable;
 287                          return;
 288                          end;
 289                     xlcep = addr (x25_lces.lc (lcx));
 290                     xlce.flags.originate = "1"b;            /* we made this call */
 291 
 292                     if (^protocol_mpx & length (dial_out_info) > 0) then do;
 293                          xlce.call_data = after (dial_out_info, ":");
 294                          xlce.baud_rate = x25_data.dialup_info.baud_rate;
 295                          xlce.flags.originate = "1"b;       /* we made this call */
 296                          xlce.flags.collect_call = x25_data.flags.out_calls_collect;
 297 
 298                          if substr (before (dial_out_info, ":"), 1, 4) = "x29," then do;
 299                                                             /* This is an X.29 call. */
 300                               xlce.his_address = substr (before (dial_out_info, ":"), 5);
 301                               xlce.flags.iti_call = "1"b;
 302                               end;
 303 
 304                          else if substr (before (dial_out_info, ":"), 1, 1) = "*" then do;
 305                                                             /* This is an X.29 call. */
 306                               xlce.his_address = substr (before (dial_out_info, ":"), 2);
 307                               xlce.flags.iti_call = "1"b;
 308                               end;
 309 
 310                          else do;                           /* Not an X.29 call. */
 311                               xlce.his_address = before (dial_out_info, ":");
 312                               xlce.flags.iti_call = "0"b;
 313                               call get_buffer (16);
 314                               end;
 315                          end;
 316 
 317 /* if protocol_mpx is ON then length of dial_out_info will be zero since the
 318    first word in NCON_REQ_info is zero and dial_out_info is a varying string
 319    based on infop, which also points to NCON_REQ_info. */
 320 
 321                     else if (length (dial_out_info) = 0) then do;
 322                                                             /* protocol_mpx is ON */
 323                                                             /* Call not  X29 (NCON_REQ) */
 324                                                             /* use the NCON_REQ_info overlay */
 325                          xlce.baud_rate = DEFAULT_BAUD;
 326                          xlce.call_data = NCON_REQ_info.data;
 327                                                             /* xlce.call_data not to contain all of the data. */
 328                          xlce.his_address = NCON_REQ_info.to_address;
 329                          xlce.flags.iti_call = "0"b;
 330                          xsce.trans_table_ptr = null ();
 331                          call get_buffer (32);              /* Get a buffer of size 32 to "Accommodate the large ISO calls" */
 332                          end;
 333                     if xlce.flags.iti_call then do;
 334                          xlce.iti_params (13) = 4;          /* build a call request packet */
 335                          call get_buffer (16);
 336                          end;
 337 
 338                     call make_header (lcx, "0"b);
 339                     x25_pkt.type = CALLRQ;
 340                     if ^x25_data.flags.no_d then x25_pkt.l3_header.d = "1"b;
 341                     calling_dte_addr_length = length (x25_data.my_address);
 342                     called_dte_addr_length = length (xlce.his_address);
 343                     x25_pkt.no_fc_data (1) = "0"b || bit (calling_dte_addr_length) || bit (called_dte_addr_length);
 344                     facility_disp = 2 + divide (called_dte_addr_length + calling_dte_addr_length + 1, 2, 17, 0);
 345 
 346                     addr_string = xlce.his_address || x25_data.my_address;
 347                     do i = 2 to facility_disp - 1;          /* convert to BCD */
 348                          x25_pkt.no_fc_data (i) =
 349                               "0"b || substr (unspec (substr (addr_string, 2 * i - 3, 1)), 6, 4)
 350                               || substr (unspec (substr (addr_string, 2 * i - 2, 1)), 6, 4);
 351                     end;
 352 
 353 /* Set the "reverse charging" facility according to the value of collect= in the TTF */
 354 /* facilities "by default", correct below if necessary... */
 355                     x25_pkt.no_fc_data (facility_disp) = "002"b3;
 356                     x25_pkt.no_fc_data (facility_disp + 1) = "001"b3;
 357                     if protocol_mpx then do;
 358                          facility_length = 2;
 359                          if xlce.collect_call
 360                          then l3_facilities = "^A^A";       /* taxation on demand */
 361                          else l3_facilities = "^A^@";       /* taxation on caller ("demander" or "applicant") */
 362                          user_data_disp = facility_disp + 3;
 363                          facility_length = length (NCON_REQ_info.facilities);
 364                          if facility_length ^= 0 then do;
 365                               x25_pkt.no_fc_data (facility_disp) = substr (unspec (facility_length), 27, 9);
 366                               l3_facilities = NCON_REQ_info.facilities;
 367                               user_data_disp = facility_disp + facility_length + 1;
 368                               end;
 369                          user_data_length = length (NCON_REQ_info.data);
 370                          l3_call_data = NCON_REQ_info.data;
 371                          end;
 372                     else do;
 373                          if xlce.collect_call
 374                          then x25_pkt.no_fc_data (facility_disp + 2) = "001"b3;
 375                          else x25_pkt.no_fc_data (facility_disp + 2) = "000"b3;
 376                          user_data_disp = facility_disp + 3;
 377                          user_data_length = length (xlce.call_data) + 4;
 378                          unspec (substr (l3_call_data, 1, 4)) = ""b3;
 379                          if xlce.flags.iti_call then unspec (substr (l3_call_data, 1, 1)) = "001"b3;
 380                          substr (l3_call_data, 5) = xlce.call_data;
 381                          end;
 382 
 383                     buffer.tally = 2 + user_data_disp + user_data_length + L2_HEADER_PAD;
 384                     call write_pkt;
 385                     call send_output;
 386 
 387                     xsce.state = SC_DIALING;
 388                     xsce.lcx = lcx;
 389                     xlce.scx = scx;
 390                     call state_change (DTE_WAITING);
 391                     end;
 392 
 393                else if order = "hangup" then do;            /* cancel a previous listen */
 394                     call reset_xsce;
 395                     end;
 396 
 397                else if (protocol_mpx & order = "get_network_infos") then do;
 398                                                             /* retrieve network infos */
 399                     network_infos.network_address = x25_data.my_address;
 400                     network_infos.max_packet_size = x25_lces.lc (1).max_packet_size;
 401                     end;
 402                else x25_code = et_undefined_order_request;  /* only these are valid if not dialed */
 403 %page;
 404           else if /* case */ order = "hangup" then do;      /* pull the plug on this subchan */
 405                if xlce.flags.iti_call & ^xlce.flags.originate then do;
 406                     call get_buffer (16);                   /* this is PAD, ask nicely */
 407                     call make_header (lcx, "1"b);           /* by making an invitation to clear */
 408                     l4_data (1) = "001"b3;
 409                     buffer.tally = hdr_size + 1 + L2_HEADER_PAD;
 410                     call write_data_pkt;
 411                     end;
 412 
 413                else if (protocol_mpx & infop ^= null ()) then call clear_call ((reason_of_hangup.diag));
 414                else call clear_call (0);                    /* send a clear request */
 415                end;
 416 
 417           else if (protocol_mpx & (order = "connect_response")) then do;
 418                                                             /* primitive ISO NCONNECT RESPONSE */
 419                if xlce.state ^= CONRESP_WAITING | xsce.state ^= SC_DIALING
 420                then x25_code = et_invalid_state;
 421                else do;
 422                     call reset_timer;
 423                     call send_NCON_RESP;
 424                     xsce.state = SC_DIALING;
 425                     xlce.state = FLOW_CONTROL_READY;
 426                     xsce.flags.output_ready = "1"b;
 427                     call channel_manager$interrupt (xsce.devx, SEND_OUTPUT, ""b);
 428                     x25_code = 0;
 429                     end;
 430                end;
 431 
 432           else if order = "wru" then do;
 433                if ^xsce.flags.wru_done then do;
 434                     call tty_space_man$get_buffer (xsce.devx, 16, INPUT, blockp);
 435                     if blockp ^= null () then do;
 436                          buffer.next = 0;
 437                          string (buffer.flags) = ""b;
 438                          buffer.flags.break = "1"b;
 439                          string (buffer.chars) = "X.25:" || xlce.his_address || NL;
 440                          buffer.tally = length (rtrim (string (buffer.chars)));
 441 
 442                          rtx_info.input_chain.chain_head, rtx_info.input_chain.chain_tail = rel (blockp);
 443                          rtx_info.input_count = 16;
 444                          string (rtx_info.flags) = ""b;
 445                          rtx_info.flags.break_char = "1"b;
 446 
 447                          call channel_manager$interrupt (xsce.devx, ACCEPT_INPUT, unspec (rtx_info));
 448                          xsce.flags.wru_done = "1"b;
 449                          end;
 450                     end;
 451                end;
 452 
 453           else if order = "abort" then ;                    /* this is too tough */
 454 
 455           else if order = "write_status" then do;
 456                write_status_info.output_pending = (xlce.next_send_seq ^= xlce.next_ack_seq);
 457                if write_status_info.output_pending & ^xlce.flags.write_status_sync_sent then call send_sync;
 458                                                             /* watch out for open windows */
 459                end;
 460 
 461           else if order = "interrupt" then do;
 462                if xlce.flags.int_issued then return;        /* only one interrupt at a time */
 463                call get_buffer (16);
 464                call make_header (lcx, "0"b);
 465                x25_pkt.type = SNITRQ;
 466                x25_pkt.no_fc_data (1) = ""b;
 467                buffer.tally = 4 + L2_HEADER_PAD;            /* length of packet = 4 */
 468                call write_pkt;
 469                call send_output;
 470                xlce.flags.int_issued = "1"b;                /* show interrupt request issued */
 471 
 472                if xlce.flags.iti_call & (xlce.iti_params (7) = 21) then do;
 473                     call get_buffer (16);
 474                     call make_header (lcx, "1"b);
 475                     l4_data (1) = "003"b3;
 476                     l4_data (2) = "010"b3;
 477                     l4_data (3) = "001"b3;
 478                     buffer.tally = hdr_size + 3 + L2_HEADER_PAD;
 479                     call write_data_pkt;
 480                     xlce.iti_params (8) = 1;
 481                     end;
 482                end;
 483 
 484           else if order = "input_flow_control_chars" then do;
 485                if (ifci.suspend_seq.count ^= 1) | (ifci.resume_seq.count ^= 1)
 486                     | (substr (ifci.suspend_seq.chars, 1, 1) ^= "^S" /* XOFF */)
 487                     | (substr (ifci.resume_seq.chars, 1, 1) ^= "^Q" /* XON */)
 488                then x25_code = et_bad_arg;
 489                end;
 490 
 491           else if order = "output_flow_control_chars" then do;
 492                if string (ofci.flags) ^= ""b
 493                     & ((^ofci.flags.suspend_resume) | (ofci.suspend_or_etb_seq.count > 1)
 494                     | (ofci.resume_or_ack_seq.count > 1)
 495                     | (substr (ofci.suspend_or_etb_seq.chars, 1, 1) ^= "^S" /* XOFF */)
 496                     | (substr (ofci.resume_or_ack_seq.chars, 1, 1) ^= "^Q" /* XON */))
 497                then x25_code = et_bad_arg;
 498                end;
 499 
 500           else if order = "set_framing_chars" then ;        /* we could play with forwarding conditions */
 501 
 502           else if xlce.flags.iti_call & xlce.flags.originate & (order = "get_foreign_terminal_data") then do;
 503                if ftd.version ^= FOREIGN_TERMINAL_DATA_VERSION_1 then do;
 504                     x25_code = et_unimplemented_version;
 505                     return;
 506                     end;
 507                number_of_modes = 7;
 508                allocate mode_string_info in (ftd.area_ptr -> based_area) set (mode_string_info_ptr);
 509                mode_string_info.version = mode_string_info_version_2;
 510                do i = 1 to number_of_modes;
 511                     mode_string_info.modes (i).version = mode_value_version_3;
 512                     mode_string_info.modes (i).mode_name = mode_names (i);
 513                     mode_string_info.modes (i).flags.boolean_valuep = "1"b;
 514                end;
 515                mode_string_info.modes (MODE_RAWI).boolean_value = (xlce.iti_params (1) = 0);
 516                mode_string_info.modes (MODE_ECHOPLEX).boolean_value = (xlce.iti_params (2) ^= 0);
 517                mode_string_info.modes (MODE_BREAKALL).boolean_value = (xlce.iti_params (4) ^= 0);
 518                mode_string_info.modes (MODE_IFLOW).boolean_value = (xlce.iti_params (5) ^= 0);
 519                mode_string_info.modes (MODE_OFLOW).boolean_value = (xlce.iti_params (12) ^= 0);
 520                mode_string_info.modes (MODE_HNDLQUIT).boolean_value = (xlce.iti_params (7) = 21);
 521                mode_string_info.modes (MODE_LFECHO).boolean_value = (xlce.iti_params (13) ^= 0);
 522 
 523                ftd.mode_string_info_ptr = mode_string_info_ptr;
 524                xsce.flags.need_ftd = "1"b;
 525                end;
 526 
 527           else x25_code = et_undefined_order_request;
 528 
 529           return;
 530 %page;
 531 /* * * * * * * * * * CHECK_MODES * * * * * * * * * */
 532 
 533 check_modes:
 534      entry (X25_data_ptr, X25_scx, x25_mclp, x25_code);
 535 
 536           set_entry = "0"b;
 537           goto modes_common;
 538 
 539 /* * * * * * * * * * SET_MODES * * * * * * * * * */
 540 
 541 set_modes:
 542      entry (X25_data_ptr, X25_scx, x25_mclp, x25_code);
 543 
 544           set_entry = "1"b;
 545 modes_common:
 546           call setup_subchan;
 547           if xlcep = null () then do;
 548                x25_code = et_invalid_state;
 549                return;
 550                end;
 551           x25_code = 0;
 552           mclp = x25_mclp;
 553 
 554           if mcl.version ^= mcl_version_2 then do;
 555                x25_code = et_unimplemented_version;
 556                return;
 557                end;
 558 
 559           if set_entry then do;
 560                if mcl.init then do;
 561                     string (xsce.mode) = ""b;
 562                     end;
 563                end;
 564 
 565           do i = 1 to mcl.n_entries;
 566                mclep = addr (mcl.entries (i));
 567                mode_found = "0"b;
 568                do j = 1 to dimension (mode_names, 1);
 569                     if mcle.mode_name = mode_names (j) then do;
 570                          mode_found = "1"b;
 571                          if set_entry
 572                          then if mcle.mpx_mode
 573                               then xsce.mode (j) = mcle.mode_switch;
 574                               else ;
 575                          else mcle.mpx_mode = "1"b;
 576                          end;
 577                end;
 578 
 579                if ^mode_found
 580                then if set_entry
 581                     then if mcle.mpx_mode & ^mcle.force then do;
 582                                                             /* this is a mode we want to set */
 583                               mcle.error = "1"b;
 584                               x25_code = et_bad_mode;
 585                               end;
 586                          else ;
 587                     else mcle.mpx_mode = "0"b;
 588           end;
 589 
 590           if set_entry then do;                             /* Set the modes. */
 591 
 592 /* Get the right translation table. */
 593 
 594                if xsce.mode (MODE_8BIT) then do;
 595                     if xsce.mode (MODE_LFECHO)
 596                     then xsce.trans_table_ptr = addr (x25_mpx_data$trans_parity_lfecho);
 597                     else xsce.trans_table_ptr = null ();
 598                     end;
 599 
 600                else if xsce.mode (MODE_LFECHO) then xsce.trans_table_ptr = addr (x25_mpx_data$trans_no_parity_lfecho);
 601 
 602                else xsce.trans_table_ptr = addr (x25_mpx_data$trans_no_parity);
 603 
 604 /* See if we are doing X.29, and who is the PAD. */
 605 /* format: comcol71 */
 606 
 607                if xlce.flags.iti_call & ^xlce.flags.originate then do;/* X.29 and he is the PAD, so set parameters. */
 608                     call get_buffer (16);
 609                     call make_header (lcx, "1"b);
 610                     l4_data (1) = "002"b3;
 611                     nchars = 1;
 612 
 613 /* Set the following parameters for all network types. */
 614 
 615                     call add_iti_mode (MODE_RAWI, 1, 0, 1);           /* PAD recall with a character, 0 = none, 1 = ^P */
 616                     call add_iti_mode (MODE_ECHOPLEX, 2, 1, 0);       /* PAD echo, 0 = off, 1 = on */
 617                     call add_iti_mode (MODE_BREAKALL, 3, 0, 2);       /* PAD data forwarding, 0 = none, 2 = CR. */
 618                     call add_iti_mode (MODE_BREAKALL, 4, (x25_data.breakall_idle_timer), 0);
 619                                                                       /* PAD idle timer, 1/20 seconds. */
 620                     call add_iti_mode (MODE_IFLOW, 5, 1, 0);          /* PAD input XON/XOFF mode. */
 621                     call add_iti_mode (MODE_HNDLQUIT, 7, 21, 1); /* PAD break handling, 21 = normal, 1 = interrupt only. */
 622                     call add_iti_mode (MODE_OFLOW, 12, 1, 0);         /* PAD output XON/XOFF mode. */
 623                     call add_iti_mode (MODE_LFECHO, 13, 4, 0);        /* PAD LF echoing, 4 = echo LF to terminal, 0 = none. */
 624 
 625                     call add_iti_param (10, 0);                       /* Turn off PAD line folding. */
 626                     call add_iti_param (15, 0);                       /* Turn off PAD editing. */
 627 
 628 /* Now do the network specific parameter settings. */
 629 
 630                     if x25_data.net_type = "datapac" then do;
 631                          call add_iti_param (0, 0);                   /* CCITT National marker. */
 632                          call add_iti_mode (MODE_POLITE, 125, 30, 0);
 633                          call add_iti_mode (MODE_LFECHO, 126, 4, 0);
 634                          end;
 635 
 636                     else if x25_data.net_type = "telenet" then do;
 637                          call add_iti_param (0, 33);                  /* Telenet National marker. */
 638                          call add_iti_mode (MODE_LFECHO, 1, 4, 0);    /* Telenet LF echoing. */
 639                          end;
 640 
 641                     else if x25_data.net_type = "tymnet" then ;       /* Nothing special for now. */
 642 
 643                     else ;                                            /* Unspecified network type, nothing special for now. */
 644 
 645                     buffer.tally = hdr_size + nchars + L2_HEADER_PAD;
 646                     call write_data_pkt;
 647                     end;                                              /* X.29 and he is the PAD, so set parameters. */
 648                end;                                                   /* Set the modes. */
 649 
 650 /* format: comcol61 */
 651 
 652           return;
 653 
 654 /* * * * * * * * * * * GET_MODES * * * * * * * * * * */
 655 
 656 get_modes:
 657      entry (X25_data_ptr, X25_scx, x25_modes, x25_code);
 658 
 659           x25_code = 0;
 660           x25_modes = "";
 661           return;
 662 %page;
 663 /* * * * * * * * * * WRITE * * * * * * * * * */
 664 
 665 write:
 666      entry (X25_data_ptr, X25_scx, x25_chain_ptr, x25_code);
 667 
 668           call setup_subchan;
 669           if xlcep = null () then do;
 670                x25_code = et_invalid_state;
 671                return;
 672                end;
 673           x25_code = 0;
 674 
 675           protocol_mpx = get_protocol_sc ();
 676 
 677           xsce.flags.output_ready = "0"b;
 678 
 679           if xlce.flags.iti_break then return;              /* so we won't take any of the new one */
 680 
 681           do chain_ptr = x25_chain_ptr repeat (leftover_chain_ptr)
 682                while ((chain_ptr ^= null ()) & ^xsce.flags.end_of_page);
 683                nchars = 0;
 684                prev_blockp = null ();
 685                do blockp = chain_ptr repeat (pointer (blockp, buffer.next));
 686                     nchars = nchars + buffer.tally;
 687                     call mvt_ (addr (buffer.chars), addr (buffer.chars), (buffer.tally), x25_mpx_data$eight_bit);
 688                     if (nchars > xlce.max_packet_size) | (buffer.next = 0) | buffer.flags.end_of_page | buffer.flags.break
 689                     then goto end_chain;
 690                     string (buffer.flags) = ""b;
 691                     prev_blockp = blockp;
 692                end;
 693 
 694 /****
 695       The assumption is made at this point that xlce.max_packet_size is larger
 696       than the buffer size.  If it weren't, then the above loop would have exited
 697       before setting prev_blockp, and the system will crash with a reference
 698       through a null pointer below.  This situation should never arise since
 699       as_x25_mpx_ checks that the packet size is larger than the minimum
 700       buffer size.  If the system crashes, someone has failed abysmally.
 701 ****/
 702 
 703 end_chain:
 704                if nchars > xlce.max_packet_size then do;    /* can take only part of the chain */
 705                     prev_blockp -> buffer.next = 0;         /* break chain here */
 706                     leftover_chain_ptr = blockp;            /* we'll give back the rest */
 707                     endp = prev_blockp;                     /* we want this to point to last block */
 708                     end;
 709 
 710                else do;
 711                     endp = blockp;
 712                     if buffer.next = 0
 713                     then leftover_chain_ptr = null ();
 714                     else do;
 715                          leftover_chain_ptr = pointer (blockp, buffer.next);
 716                          buffer.next = 0;
 717                          end;
 718                     end;
 719 
 720 /* Construct a standard X25 data frame consisting of:
 721    (1) level 2 header pad (if any)
 722    (2) level 3 header
 723    (3) text message
 724 
 725    The write chain we were given constitutes the body of the text
 726    message. */
 727 
 728                xsce.flags.end_of_page = endp -> buffer.flags.end_of_page;
 729 
 730                blockp = chain_ptr;                          /* now build the header */
 731                if x25_data.seq_mod = 8 then do;
 732                     hdr_size = 3;
 733                     l4_data_ptr = addr (m8_fc_data.user_data);
 734                     end;
 735                else do;
 736                     hdr_size = 4;
 737                     l4_data_ptr = addr (m128_fc_data.user_data);
 738                     end;
 739                call mrl_ (addr (buffer.chars), (buffer.tally), l4_data_ptr, (buffer.tally));
 740                buffer.tally = buffer.tally + hdr_size + L2_HEADER_PAD;
 741                                                             /* make room for header */
 742                call make_header (lcx, "0"b);
 743                x25_pkt.type = "00"b4;
 744 
 745 /*
 746    if ^(endp -> buffer.break | endp -> buffer.end_of_page)
 747    then if x25_data.seq_mod = 8
 748    then m8_fc_data.m = "1"b;
 749    else m128_fc_data.m = "1"b;
 750 */
 751                if protocol_mpx then do;
 752                     if ^xlce.flags.iti_call & ^endp -> buffer.flags.break
 753                     then if x25_data.seq_mod = 8
 754                          then m8_fc_data.m = "1"b;
 755                          else m128_fc_data.m = "1"b;
 756                     end;
 757 
 758                call tty_space_man$switch_chain (xsce.devx, x25_data.devx, OUTPUT, OUTPUT, blockp);
 759                string (endp -> buffer.flags) = ""b;
 760                call write_data_pkt;
 761           end;
 762 
 763           call solicit_output;                              /* if we took it all, get more */
 764           x25_chain_ptr = chain_ptr;
 765           x25_code = 0;
 766           return;
 767 %page;
 768 /* * * * * * * * * * * INTERRUPT * * * * * * * * * * */
 769 
 770 interrupt:
 771      entry (X25_data_ptr, x25_int_type, x25_int_data);
 772 
 773           x25_data_ptr = X25_data_ptr;
 774           int_type = x25_int_type;
 775           int_data = x25_int_data;
 776           xscep, xlcep = null ();
 777 
 778           if (int_type < lbound (INTERRUPT, 1)) | (int_type > hbound (INTERRUPT, 1))
 779           then goto bad_interrupt;
 780           else goto INTERRUPT (int_type);
 781 
 782 
 783 INTERRUPT (1):                                              /* DIALUP - major channel has dialed up */
 784           if x25_data.state ^= X25_LISTENING then goto bad_interrupt;
 785           unspec (x25_data.dialup_info) = int_data;
 786           if ^x25_data.flags.bypass_restart then call restart (0);
 787           return;
 788 
 789 
 790 INTERRUPT (2):                                              /* HANGUP - major channel has hung up */
 791           call pxss$ring_0_wakeup (x25_data.load_proc_id, x25_data.load_ev_chan, MPX_DOWN, code);
 792 
 793           if x25_data.state ^= X25_HUNGUP then do;
 794                call crash_subchannels;
 795                call x25_hangup;
 796                end;
 797 
 798           return;
 799 
 800 INTERRUPT (3):                                              /* CRASH - parent multiplexer has died */
 801           if x25_data.state ^= X25_HUNGUP then do;
 802                call crash_subchannels;
 803                call x25_hangup;
 804                end;
 805 
 806           return;
 807 
 808 INTERRUPT (9):                                              /* LINE STATUS - process fnp status message */
 809 /****
 810       Currently, for the two cases of line status (1 or 3), the FNP has sent the
 811       line status, and then deactivated itself.  This causes it to stop listening
 812       to the link, and also to send us a hangup interrupt.  This is done to solve
 813       a race condition with the previous implementation:
 814 
 815       1) FNP sends line status and goes back to listen to the link
 816       2) we send deactivate order
 817       3) FNP stops listening to the line and sends us a hangup order
 818       4) we crash the multiplexer.
 819 
 820       If the link comes up between 1 and 2, the FNP sends us a dialup interrupt
 821       which we ignore, and then at deactivate time the FNP does not tell the
 822       other side that he is disconnecting.  This creates problems which are
 823       solved by the current scheme.
 824 ****/
 825           if lap_down_status.link_down_status = 1
 826           then call syserr (Log_message,
 827                     "x25_mpx(^a): Failure, Link state: ^d, Current action: ^d, in ^d, Primary state: ^d, Secondary state: ^d",
 828                     x25_data.name, lap_down_status.main_state, lap_down_status.last_function_process,
 829                     lap_down_status.which_state_process, lap_down_status.primary_sub_state,
 830                     lap_down_status.secondary_sub_state);
 831 
 832           else if lap_cmdr_status.cmdr_status = 3
 833           then call syserr (Log_message,
 834                     "x25_mpx(^a): Link disconnected due to mis-matched frame sizes. CMDR/FRMR frame: ^( ^.4b^).",
 835                     x25_data.name, lap_cmdr_status.cmdr_bytes.byte (*));
 836 
 837           else goto bad_interrupt;                          /* We don't know this status. */
 838 
 839           return;                                           /* FNP will send hangup itself. */
 840 
 841 
 842 INTERRUPT (4):                                              /* SEND OUTPUT - it's safe to write next output frame now */
 843           x25_data.flags.send_output = "1"b;
 844 
 845           if (x25_data.long_packet_head ^= 0) & (x25_data.write_head = null ()) then do;
 846                scx = x25_data.long_packet_head;
 847                xscep = addr (x25_data.sc (scx));
 848                lcx = xsce.lcx;
 849                xlcep = addr (x25_lces.lc (lcx));
 850                x25_data.long_packet_head = xsce.long_packet_next_scx;
 851                if x25_data.long_packet_head = 0 then x25_data.long_packet_tail = 0;
 852                xsce.flags.long_packet_pending = "0"b;
 853                call send_data_packets;
 854                end;
 855 
 856           call send_output;
 857           return;
 858 
 859 
 860 INTERRUPT (5):                                              /* INPUT_AVAILABLE */
 861 INTERRUPT (10):                                             /* DIAL STATUS - ignore */
 862 INTERRUPT (11):                                             /* WRU TIMEOUT - ignore */
 863 bad_interrupt:
 864           call syserr (Log_message, "x25_mpx(^a): Unexpected interrupt ^d ^.3b received.", x25_data.name, int_type,
 865                int_data);
 866 
 867 INTERRUPT (7):                                              /* INPUT REJECTED - ignore */
 868 INTERRUPT (8):                                              /* QUIT - ignore */
 869 INTERRUPT (12):                                             /* SPACE AVAILABLE - some buffer space was freed that we need */
 870 INTERRUPT (13):                                             /* ACKNOWLEDGE_ECHNEGO_INIT */
 871 INTERRUPT (14):                                             /* ACKNOWLEDGE_ECHNEGO_STOP */
 872 INTERRUPT (16):                                             /* USER_INTERRUPT */
 873           return;
 874 
 875 INTERRUPT (17):                                             /* MASKED - treat like HANGUP but use different wakeup message */
 876           call pxss$ring_0_wakeup (x25_data.load_proc_id, x25_data.load_ev_chan, MPX_MASKED, code);
 877 
 878           if x25_data.state ^= X25_HUNGUP then do;
 879                call crash_subchannels;
 880                x25_data.state = X25_HUNGUP;
 881                end;
 882 
 883           return;
 884 
 885 INTERRUPT (15):                                             /* TIMER */
 886           unspec (timer_info) = int_data;
 887           lcx = timer_info.subchan_idx;
 888 
 889           if lcx = 0 then do;
 890                if (x25_data.state = X25_RESTARTING) & (clock () > x25_data.restart_time + T20) then do;
 891                     call restart (52);
 892                     end;
 893                return;
 894                end;
 895 
 896           xlcep = addr (x25_lces.lc (lcx));
 897           xlce.flags.timer_set = "0"b;
 898           scx = xlce.scx;
 899           xscep = addr (x25_data.sc (scx));
 900           protocol_mpx = get_protocol_sc ();
 901 
 902           if xlce.state = FLOW_CONTROL_READY then do;
 903                call send_rr;
 904                return;
 905                end;
 906 
 907           if clock () > xlce.state_time + T20 then do;
 908                call syserr (Log_message, "x25_mpx(^a/^d): Time out in state ^d.", x25_data.name, lcx, xlce.state);
 909                if xlce.state = DTE_WAITING then do;
 910                     call clear_call (49);
 911                     return;
 912                     end;
 913                else if xlce.state = DTE_RESET_REQUEST then do;
 914                     call clear_call (51);
 915                     return;
 916                     end;
 917                else if xlce.state = DTE_CLEAR_REQUEST then do;
 918                     call clear_call (50);
 919                     return;
 920                     end;
 921                else if protocol_mpx & (xlce.state = CONRESP_WAITING) then do;
 922                     call clear_call (48);
 923                     return;
 924                     end;
 925                end;
 926 
 927           return;
 928 %page;
 929 INTERRUPT (6):                                              /* ACCEPT INPUT - process an input frame */
 930           unspec (rtx_info) = int_data;
 931           chain_ptr, blockp = pointer (x25_data_ptr, rtx_info.chain_head);
 932           endp = pointer (x25_data_ptr, rtx_info.chain_tail);
 933 
 934           if buffer.tally < L2_HEADER_PAD + 3 then do;      /* too short? */
 935                call syserr (Log_message, "x25_mpx(^a): Packet too short.", x25_data.name);
 936                call dump_pkt;
 937                call send_diag (38);
 938                goto done_in_pkt;
 939                end;
 940 
 941           if x25_pkt.l3_header.format ^= x25_data.gfid then do;
 942                                                             /* do we understand it? */
 943                call syserr (Log_message, "x25_mpx(^a): Unrecognized general format ID ^b^b^2b.", x25_data.name,
 944                     x25_pkt.l3_header.q, x25_pkt.l3_header.d, x25_pkt.l3_header.format);
 945                call dump_pkt;
 946                call send_diag (40);
 947                goto done_in_pkt;
 948                end;
 949 
 950           lcx = binary (x25_pkt.l3_header.lcgn || x25_pkt.l3_header.lcn, 12);
 951 
 952 /* Check for invalid logical channel. If channels start at zero then maximum is (n_lc - 1). */
 953 
 954           if lcx > x25_data.n_lc then do;
 955                call syserr (Log_message, "x25_mpx(^a): Invalid channel number ^d.", x25_data.name, lcx);
 956                call dump_pkt;
 957                call send_diag (36);
 958                goto done_in_pkt;
 959                end;
 960 %page;
 961           protocol_mpx = "0"b;
 962           if x25_data.state = X25_ACTIVE then do;
 963                if lcx = 0 then do;
 964 
 965 /* Restart Request */
 966 
 967                     if x25_pkt.type = RSRTRQ then do;
 968                          call crash_subchannels;
 969                          call free_in_pkt;
 970                          call get_buffer (16);
 971                          call make_header (0, "0"b);
 972                          x25_pkt.type = RSRTCN;
 973                          buffer.tally = 3 + L2_HEADER_PAD;
 974                          call write_pkt;
 975                          call send_output;
 976                          goto done_in_pkt;
 977                          end;
 978 
 979 /* Restart Confirmation */
 980 
 981                     if x25_pkt.type = RSRTCN then do;
 982                          call free_in_pkt;
 983                          call restart (16);
 984                          goto done_in_pkt;
 985                          end;
 986 
 987 /* Diagnostic */
 988 
 989                     if x25_pkt.type = DIAG then do;
 990                          call syserr (Log_message, "x25_mpx(^a): Diagnostic type ^d.", x25_data.name,
 991                               binary (x25_pkt.no_fc_data (1), 8));
 992                          call dump_pkt;
 993                          goto done_in_pkt;
 994                          end;
 995 
 996                     call syserr (Log_message, "x25_mpx(^a): Invalid packet type ^.4b on LC 0.", x25_data.name,
 997                          x25_pkt.type);
 998                     call dump_pkt;
 999                     goto done_in_pkt;
1000                     end;
1001 %page;
1002 /* now examine packets for other logical channels */
1003 
1004                xlcep = addr (x25_lces.lc (lcx));
1005                scx = xlce.scx;
1006                if scx > 0 then do;
1007                     xscep = addr (x25_data.sc (scx));
1008                     protocol_mpx = get_protocol_sc ();
1009 
1010                     if protocol_mpx
1011                          then if x25_data.packet_trace_sw then call log_packet ("0"b);
1012 %page;
1013 /* Data packet */
1014 
1015                     if substr (x25_pkt.type, 8, 1) = "0"b then do;
1016                                                             /* if data packet */
1017                          if xlce.state ^= FLOW_CONTROL_READY then do;
1018                               call handle_data_or_fc_error;
1019                               goto done_in_pkt;
1020                               end;
1021 
1022 
1023                          call proc_pr (pr_error);           /* update output window */
1024                          if pr_error then goto done_in_pkt;
1025 
1026                          if x25_data.seq_mod = 8            /* extract packet seq number */
1027                          then do;
1028                               temp_ps = m8_fc_data.ps;
1029                               hdr_size = 3;
1030                               l4_data_ptr = addr (m8_fc_data.user_data);
1031                               rtx_info.break_char, endp -> buffer.flags.break = ^m8_fc_data.m;
1032                               end;
1033                          else do;
1034                               temp_ps = m128_fc_data.ps;
1035                               hdr_size = 4;
1036                               l4_data_ptr = addr (m128_fc_data.user_data);
1037                               rtx_info.break_char, endp -> buffer.flags.break = ^m128_fc_data.m;
1038                               end;
1039 
1040                          if temp_ps ^= xlce.next_recv_seq then do;
1041                                                             /* if P(S) bad - not equal to V(R) */
1042                               call syserr (Log_message, "x25_mpx(^a): Sequence error P(S)=^d V(R)=^d.", xsce.name,
1043                                    temp_ps, xlce.next_recv_seq);
1044                               call dump_pkt;
1045                               call reset_lc (1);
1046                               goto done_in_pkt;
1047                               end;                          /* invalid P(S) */
1048 
1049                          xlce.next_recv_seq = mod (xlce.next_recv_seq + 1, x25_data.seq_mod);
1050                                                             /* V(R) = V(R) +1 */
1051                          if x25_pkt.l3_header.d
1052                          then xlce.force_ack_time = 0;      /* force immediate acknowledgement */
1053                          else xlce.force_ack_time = clock () + TIMEOUT;
1054                                                             /* acknowledge within 1 sec */
1055 
1056                          if x25_pkt.l3_header.q then do;    /* if Q bit set */
1057                               if ^xlce.flags.iti_call then do;
1058                                                             /* if this is not an ITI call */
1059                                    int_data = substr (string (l4_data), 1, 72);
1060                                    call channel_manager$interrupt (xsce.devx, LINE_STATUS, int_data);
1061                                    end;
1062                               else do;
1063                                    i = binary (l4_data (1), 8);
1064                                                             /* get the X.29 command */
1065                                    if i > hbound (iti, 1) then do;
1066                                         call syserr (Log_message, "x25_mpx(^a): Invalid X.29 command ^d.", xsce.name, i);
1067                                         call dump_pkt;
1068                                         call get_buffer (16);
1069                                         call make_header (lcx, "1"b);
1070                                         l4_data (1) = "005"b3;
1071                                         l4_data (2) = "001"b3;
1072                                         l4_data (3) = bit (binary (i, 9));
1073                                         buffer.tally = hdr_size + 3 + L2_HEADER_PAD;
1074                                         call write_data_pkt;
1075                                         goto done_data_pkt;
1076                                         end;
1077                                    else goto iti (i);
1078 
1079 iti (0):                                                    /* parameter indication */
1080                                    do i = 2 by 2 to buffer.tally - hdr_size - L2_HEADER_PAD;
1081                                         if l4_data (i) = "00000000"b then goto done_data_pkt;
1082 
1083 /*                                 if substr (l4_data (i), 2, 1)
1084    then call syserr (Log_message_or_discard, "x25_mpx(^a): Unable to set X.29 parameter ^d to ^d.",
1085    xsce.name, binary (substr (l4_data (i), 3, 7), 7),
1086    binary (l4_data (i + 1), 8));
1087 */
1088 
1089                                         if xlce.flags.iti_break & (l4_data (i) = "000001000"b)
1090                                                             /* & this is resume indication */
1091                                              & (l4_data (i + 1) = "000000000"b) then do;
1092                                              call free_in_pkt;
1093                                              call confirm_interrupt;
1094                                              xlce.flags.iti_break = "0"b;
1095                                              end;
1096                                    end;
1097                                    goto done_data_pkt;
1098 
1099 iti (1):                                                    /* invitation to clear */
1100                                    call free_in_pkt;
1101                                    call clear_call (0);
1102                                    goto done_in_pkt;
1103 
1104 iti (2):                                                    /* set parameters */
1105                                    call set_x29 ("1"b, "0"b);
1106                                    goto done_data_pkt;
1107 
1108 iti (3):                                                    /* indication of break */
1109                                    if xlce.flags.iti_break then do;
1110                                         call channel_manager$interrupt (xsce.devx, QUIT, ""b);
1111                                         call free_in_pkt;
1112                                         call get_buffer (16);
1113                                         call make_header (lcx, "1"b);
1114                                         substr (string (l4_data), 1, 3 * 9) = "006010000"b3;
1115                                         buffer.tally = hdr_size + 3 + L2_HEADER_PAD;
1116                                                             /* buffer length = 6 */
1117                                         call write_data_pkt;
1118                                         xsce.flags.end_of_page = "0"b;
1119                                         end;
1120                                    goto done_data_pkt;
1121 
1122 iti (4):                                                    /* read parameters */
1123                                    call set_x29 ("0"b, "1"b);
1124                                    goto done_data_pkt;
1125 
1126 iti (5):                                                    /* error */
1127                                    call syserr (Log_message, "x25_mpx(^a): X.29 ERROR ^d/^d", xsce.name,
1128                                         binary (l4_data (2), 9), binary (l4_data (3), 9));
1129                                    goto done_data_pkt;
1130 
1131 iti (6):                                                    /* set and read parameters */
1132                                    call set_x29 ("1"b, "1"b);
1133                                    goto done_data_pkt;
1134                                    end;
1135                               goto done_data_pkt;
1136                               end;
1137 
1138 /* regular data packet received */
1139 
1140                          if xlce.flags.iti_break then goto done_data_pkt;
1141 
1142                          nchars = buffer.tally - hdr_size - L2_HEADER_PAD;
1143                          if nchars <= 0 then goto done_data_pkt;
1144                                                             /* ignore empty packets */
1145 
1146                          substr (string (buffer.chars), 1, nchars) =
1147                               substr (string (buffer.chars), hdr_size + L2_HEADER_PAD + 1, nchars);
1148                          buffer.tally = nchars;             /* delete the header */
1149 
1150                          rtx_info.output_in_ring_0 = (xsce.write_head ^= null ());
1151                          rtx_info.output_in_fnp = (xlce.next_send_seq ^= xlce.next_ack_seq);
1152                          rtx_info.input_count = rtx_info.input_count - hdr_size - L2_HEADER_PAD;
1153 
1154                          if xsce.trans_table_ptr ^= null () then do;
1155                               do blockp = chain_ptr repeat (pointer (blockp, buffer.next)) while (rel (blockp) ^= ""b);
1156                                                             /* walk chain for lfecho mode */
1157                                    call mvt_ (addr (buffer.chars), addr (buffer.chars), (buffer.tally),
1158                                         xsce.trans_table_ptr -> based_trans_table);
1159                               end;
1160                               blockp = chain_ptr;
1161                               end;
1162 
1163                          if xsce.flags.end_of_page & rtx_info.break_char then do;
1164                               xsce.flags.end_of_page = "0"b;/* not any more */
1165 
1166                               if (buffer.tally <= 2) & (buffer.next = 0)
1167                                    & (verify (substr (string (buffer.chars), 1, buffer.tally), CR_LF_FF) = 0)
1168                               then goto done_data_pkt;      /* no real input */
1169                               end;
1170 
1171                          blockp = null ();                  /* show buffer given away */
1172                          call tty_space_man$switch_chain (x25_data.devx, xsce.devx, INPUT, INPUT, chain_ptr);
1173                          call channel_manager$interrupt (xsce.devx, ACCEPT_INPUT, unspec (rtx_info));
1174                          goto done_data_pkt;
1175                          end;                               /* regular data packet */
1176 %page;
1177 /* if RR packet */
1178 
1179                     if (x25_pkt.type & SNMASK) = SNRR then do;
1180                                                             /* if RR packet */
1181                          if xlce.state ^= FLOW_CONTROL_READY then do;
1182                               call handle_data_or_fc_error;
1183                               goto done_in_pkt;
1184                               end;
1185 
1186                          call proc_pr (pr_error);           /* update output window */
1187                          if pr_error then goto done_in_pkt;
1188 
1189                          xlce.flags.rnr_received = "0"b;
1190                          call free_in_pkt;
1191                          call send_data_packets;
1192                          call send_output;
1193                          call solicit_output;
1194                          goto done_in_pkt;
1195                          end;
1196 
1197 /* RNR packet */
1198 
1199                     if (x25_pkt.type & SNMASK) = SNRNR then do;
1200                                                             /* or if RNR packet */
1201                          if xlce.state ^= FLOW_CONTROL_READY then do;
1202                               call handle_data_or_fc_error;
1203                               goto done_in_pkt;
1204                               end;
1205 
1206                          call proc_pr (pr_error);           /* extract p(r) */
1207                          if pr_error then goto done_in_pkt;
1208 
1209                          xlce.flags.rnr_received = "1"b;
1210                          call free_in_pkt;
1211                          goto done_in_pkt;
1212                          end;
1213 
1214 /* REJ packet */
1215 
1216                     if (x25_pkt.type & SNMASK) = SNREJ then do;
1217                          if xlce.state ^= FLOW_CONTROL_READY then do;
1218                               call handle_data_or_fc_error;
1219                               goto done_in_pkt;
1220                               end;
1221 
1222                          call proc_pr (pr_error);
1223                          if pr_error then goto done_in_pkt; /* Take the first error we find. */
1224 
1225                          call syserr (Log_message, "x25_mpx(^a): Received REJ packet.", xsce.name);
1226                          call dump_pkt;
1227                          call reset_lc (37);
1228                          goto done_in_pkt;
1229                          end;
1230 %page;
1231 /* Call request packet */
1232 
1233                     if x25_pkt.type = CALLRQ then do;       /* call request packet */
1234                          if xlce.state = FLOW_CONTROL_READY | xlce.state = DTE_RESET_REQUEST then do;
1235                               call syserr (Log_message, "x25_mpx(^a): Call Request in state ^d.", xsce.name, xlce.state);
1236                               call dump_pkt;
1237                               call clear_call (23);
1238                               end;
1239 
1240                          else call free_in_pkt;
1241 
1242                          goto done_in_pkt;
1243                          end;
1244 
1245 /* Call accepted packet */
1246 
1247                     if x25_pkt.type = CALLAC then do;       /* if call accepted */
1248                          if xlce.state = DTE_WAITING then do;
1249                               if protocol_mpx & ^xlce.iti_call then do;
1250                                                             /* if ISO... */
1251                                    call set_up_dialup_info;
1252                                    call channel_manager$interrupt (xsce.devx, USER_INTERRUPT, unspec (dialup_info));
1253                                    xsce.state = SC_DIALED;
1254                                    xlce.state = FLOW_CONTROL_READY;
1255                                    call reset_timer;
1256                                    xsce.flags.output_ready = "1"b;
1257                                    call channel_manager$interrupt (xsce.devx, SEND_OUTPUT, ""b);
1258                                    end;
1259                               else call signal_dialup;
1260                               call free_in_pkt;
1261                               goto done_in_pkt;
1262                               end;
1263 
1264                          call syserr (Log_message, "x25_mpx(^a): Call Confirm in state ^d.", xsce.name, xlce.state);
1265                          call dump_pkt;
1266                          call clear_call (16);
1267                          goto done_in_pkt;
1268                          end;                               /* call accepted packet */
1269 
1270 /* Clear indication packet */
1271 
1272                     if x25_pkt.type = CLRRQ then do;        /* if clear indication packet */
1273                          if protocol_mpx & (x25_pkt.no_fc_data (1) ^= ""b)
1274                               | ^protocol_mpx & ((x25_pkt.no_fc_data (1) ^= ""b) | (x25_pkt.no_fc_data (2) ^= ""b))
1275                          then call syserr (Log_message_or_discard, "x25_mpx(^a): Clear Indication ^d/^d.", xsce.name,
1276                                    binary (x25_pkt.no_fc_data (1), 8), binary (x25_pkt.no_fc_data (2), 8));
1277                          if protocol_mpx then do;
1278                               disconnect_info.cause = x25_pkt.no_fc_data (1);
1279                               disconnect_info.diag = x25_pkt.no_fc_data (2);
1280                               end;
1281                          call free_in_pkt;
1282                          if xlce.state ^= DTE_CLEAR_REQUEST then call clear_confirm;
1283                          call proc_clear;
1284                          goto done_in_pkt;
1285                          end;                               /* CLRRQ packet */
1286 
1287 /* clear confirmation packet */
1288 
1289                     if x25_pkt.type = CLRCN then do;        /* if clear confirmation packet */
1290                          if xlce.state ^= DTE_CLEAR_REQUEST then do;
1291                               call syserr (Log_message, "x25_mpx(^a): Clear Confirm in state ^d.", xsce.name, xlce.state);
1292                               call dump_pkt;
1293                               call clear_call (16);
1294                               end;
1295 
1296                          else do;
1297                               call proc_clear;
1298                               call free_in_pkt;
1299                               end;
1300 
1301                          goto done_in_pkt;
1302                          end;                               /* CLRCN packet */
1303 %page;
1304 /* DTE logical channel input */
1305 
1306                     if xlce.state = DTE_CLEAR_REQUEST then do;
1307                          call free_in_pkt;                  /* if clear request issued, ignore data packets */
1308                          goto done_in_pkt;
1309                          end;
1310 
1311                     if xlce.state = DTE_WAITING | (protocol_mpx & (xlce.state = CONRESP_WAITING)) then do;
1312                          call syserr (Log_message, "x25_mpx(^a): Data packet received in state ^d.", xsce.name,
1313                               xlce.state);
1314                          call dump_pkt;
1315                          call clear_call (16);
1316                          goto done_in_pkt;
1317                          end;
1318 
1319 /* reset indication packet */
1320 
1321                     if x25_pkt.type = RESTRQ then do;       /* if reset indication packet */
1322                          if xlce.state ^= DTE_RESET_REQUEST then do;
1323                                                             /* if reset request issued */
1324                               call syserr (Log_message, "x25_mpx(^a): Reset received ^d/^d", xsce.name,
1325                                    binary (x25_pkt.no_fc_data (1), 8), binary (x25_pkt.no_fc_data (2), 8));
1326                               call dump_pkt;
1327                               call get_buffer (16);
1328                               call make_header (lcx, "0"b);
1329                               x25_pkt.type = RESTCN;
1330                               buffer.tally = 3 + L2_HEADER_PAD;
1331                               call write_pkt;
1332                               call send_output;
1333                               end;
1334                          else call free_in_pkt;
1335 
1336                          call proc_reset_lc;
1337                          goto done_in_pkt;
1338                          end;                               /* reset indication servicing */
1339 
1340 /* reset confirmation packet */
1341 
1342                     if x25_pkt.type = RESTCN then do;       /* if reset confirmation packet */
1343                          if xlce.state = DTE_RESET_REQUEST  /* if DTE reset request was issued */
1344                          then do;
1345                               call proc_reset_lc;           /* then this acks it */
1346                               call free_in_pkt;
1347                               end;
1348                          else do;
1349                               call syserr (Log_message, "x25_mpx(^a): Reset Confirm in state ^d.", xsce.name, xlce.state);
1350                               call dump_pkt;
1351                               call reset_lc (16);           /* otherwise a protocol error has occurred */
1352                               end;
1353                          goto done_in_pkt;
1354                          end;                               /* reset confirmation servicing */
1355 %page;
1356 /* check flow-control state */
1357 
1358                     if xlce.state ^= FLOW_CONTROL_READY then do;
1359                          call free_in_pkt;
1360                          goto done_in_pkt;
1361                          end;
1362 
1363 /* Interrupt Packet */
1364 
1365                     if x25_pkt.type = SNITRQ then do;       /* if interrupt packet */
1366                          call free_in_pkt;
1367                          if xlce.iti_call & xsce.mode (MODE_HNDLQUIT)
1368                                                             /* if ITI call */
1369                          then do;
1370                               xlce.flags.iti_break = "1"b;  /* show break service in progress */
1371                               end;
1372                          else do;
1373                               call channel_manager$interrupt (xsce.devx, QUIT, ""b);
1374                                                             /* notify higher level of interrupt */
1375                               call confirm_interrupt;
1376                               xsce.flags.end_of_page = "0"b;
1377                               end;
1378                          goto done_in_pkt;
1379                          end;                               /* interrupt packet servicing */
1380 
1381 /* interrupt confirnation received */
1382 
1383                     if x25_pkt.type = SNITCN then do;       /* if interrupt confrimation received */
1384                          if ^xlce.flags.int_issued then do; /* if we have not issued an interrupt request */
1385                               call syserr (Log_message, "x25_mpx(^a): Unexpected Interrupt Confirm.", xsce.name);
1386                               call dump_pkt;
1387                               call reset_lc (43);
1388                               end;
1389                          else do;
1390                               xlce.flags.int_issued = "0"b; /* show confirmation received */
1391                               call free_in_pkt;
1392                               end;
1393                          goto done_in_pkt;
1394                          end;                               /* interrupt confirmation servicing */
1395 
1396                     call syserr (Log_message, "x25_mpx(^a): Unexpected packet type ^.4b", xsce.name, x25_pkt.type);
1397                     call dump_pkt;
1398                     call reset_lc (32);
1399                     goto done_in_pkt;
1400                     end;
1401 %page;
1402 /* Come here if there is no connection for the packet */
1403 
1404                else do;                                     /* incoming call packet */
1405 
1406 /* Call Indication */
1407 
1408                     if x25_pkt.type = CALLRQ then do;
1409                          if xlce.state ^= READY then do;    /* if DTE ready */
1410                               call syserr (Log_message, "x25_mpx(^a/^d): Call Request in state ^d.", x25_data.name, lcx,
1411                                    xlce.state);
1412                               call dump_pkt;
1413                               call clear_call (16);
1414                               goto done_in_pkt;
1415                               end;
1416 
1417                          calling_dte_addr_length = binary (substr (x25_pkt.no_fc_data (1), 2, 4), 4);
1418                          called_dte_addr_length = binary (substr (x25_pkt.no_fc_data (1), 6, 4), 4);
1419                          facility_disp = 2 + divide (1 + calling_dte_addr_length + called_dte_addr_length, 2, 6, 0);
1420                          facility_length = binary (substr (x25_pkt.no_fc_data (facility_disp), 4, 6), 6);
1421 
1422                          do i = 2 to facility_disp - 1;     /* convert addresses */
1423                               unspec (substr (addr_string, 2 * i - 3, 1)) =
1424                                    "00011"b || substr (x25_pkt.no_fc_data (i), 2, 4);
1425                               unspec (substr (addr_string, 2 * i - 2, 1)) =
1426                                    "00011"b || substr (x25_pkt.no_fc_data (i), 6, 4);
1427                          end;
1428                          xlce.his_address = substr (addr_string, 1 + called_dte_addr_length, calling_dte_addr_length);
1429 
1430                          user_data_disp = facility_disp + facility_length + 1;
1431                          user_data_length = buffer.tally - 2 - user_data_disp - L2_HEADER_PAD;
1432                          if protocol_mpx then do;
1433                               xlce.baud_rate = DEFAULT_BAUD;
1434                               xlce.call_data = "";
1435                               if user_data_length >= 4 & x25_pkt.no_fc_data (user_data_disp) = "000000001"b then do;
1436                                                             /*  --- X29 call --- */
1437                                    xlce.flags.iti_call = "1"b;
1438                                    if user_data_length > 4 then do;
1439                                                             /* There is some complementary data */
1440                                         Call_data = substr (l3_call_data, 5);
1441                                         call mvt_ (addr (Call_data), addr (Call_data),
1442                                                             /* suppresion of the eighth bit (parity) of call data */
1443                                              user_data_length - 4, (x25_mpx_data$trans_no_parity));
1444                                         xlce.call_data = substr (Call_data, 1, user_data_length - 4);
1445                                         end;
1446                                    scx = find_sc (xlce.call_data);
1447                                    if scx = 0 then scx = find_sc ("");
1448                                    if (scx = 0) | ^x25_data.flags.mpx_started then do;
1449                                         call syserr (Log_message, "x25_mpx(^a/^d): No listening channels. , scx=^d",
1450                                              x25_data.name, lcx, scx);
1451                                         call dump_pkt;
1452                                         call clear_call (64);
1453                                         goto done_in_pkt;
1454                                         end;
1455 
1456                                    call check_facilities ();
1457                                    xscep = addr (x25_data.sc (scx));
1458                                    xsce.lcx = lcx;
1459                                    xlce.scx = scx;
1460                                    call free_in_pkt;
1461                                    call send_NCON_RESP;
1462                                    call signal_dialup;
1463                                    goto done_in_pkt;
1464                                    end;                     /* X29 call */
1465                               else do;                      /* non X29 call */
1466                                    if ^x25_data.flags.mpx_started then do;
1467                                                             /* no protocol channel */
1468                                         call syserr (Log_message, "x25_mpx(^a/^d): No listening ISO_channels.",
1469                                              x25_data.name, lcx);
1470                                         call dump_pkt;
1471                                         call clear_call (64);
1472                                         goto done_in_pkt;
1473                                         end;
1474                                    xscep = addr (x25_data.sc (scx));
1475                                                             /* One has a channel, one signals the connection... */
1476                                    xsce.lcx = lcx;
1477                                    xlce.scx = scx;
1478                                    xlce.call_data = l3_call_data;
1479                                    xsce.trans_table_ptr = null ();
1480                                    NCON_IND_info.his_address = xlce.his_address;
1481                                    NCON_IND_info.our_address = x25_data.my_address;
1482                                    NCON_IND_info.data = l3_call_data;
1483                                    NCON_IND_info.facilities = l3_facilities;
1484                                    call set_up_dialup_info;
1485                                    unspec (NCON_IND_info.dial_info) = unspec (dialup_info);
1486                                    call free_in_pkt;
1487                                    call get_buffer (32);
1488                                    call tty_space_man$switch_chain (x25_data.devx, xsce.devx, OUTPUT, INPUT, blockp);
1489                                    unspec (DIALUP_info) = "0"b;
1490                                    DIALUP_info.info_relp = rel (blockp);
1491                                    N_I_i = NCON_IND_info;
1492                                    buffer.next = 0;
1493                                    string (buffer.flags) = ""b;
1494                                    buffer.tally = size (NCON_IND_info) * 4;
1495                                    xsce.state = SC_DIALING;
1496                                    call state_change (CONRESP_WAITING);
1497                                    call channel_manager$interrupt (xsce.devx, DIALUP, unspec (DIALUP_info));
1498                                    goto done_in_pkt;
1499                                    end;
1500                               end;
1501                          else do;
1502                               xlce.baud_rate = x25_data.dialup_info.baud_rate;
1503                               if user_data_length >= 4 then do;
1504                                    xlce.call_data = substr (l3_call_data, 5);
1505                                    if x25_pkt.no_fc_data (user_data_disp) = "000000001"b then do;
1506                                         xlce.flags.iti_call = "1"b;
1507                                         end;
1508                                    end;
1509                               else xlce.call_data = "";
1510 
1511                               scx = find_sc (xlce.call_data);
1512                                                             /* find appropriate server */
1513                               if scx = 0 then scx = find_sc ("");
1514                                                             /* or null server by default */
1515                               if (scx = 0) | ^x25_data.flags.mpx_started then do;
1516                                    call syserr (Log_message, "x25_mpx(^a/^d): No listening channels.", x25_data.name, lcx)
1517                                         ;
1518                                    call dump_pkt;
1519                                    call clear_call (64);
1520                                    goto done_in_pkt;
1521                                    end;
1522 
1523                               xscep = addr (x25_data.sc (scx));
1524                               xsce.lcx = lcx;
1525                               xlce.scx = scx;
1526                               call free_in_pkt;
1527                               call get_buffer (16);
1528                               call make_header (lcx, "0"b);
1529                               x25_pkt.type = CALLAC;
1530                               buffer.tally = 3 + L2_HEADER_PAD;
1531                               call write_pkt;
1532                               call send_output;
1533                               call signal_dialup;
1534                               goto done_in_pkt;
1535                               end;
1536                          end;                               /* Call request packet */
1537 
1538 /* Clear Indication */
1539 
1540                     if x25_pkt.type = CLRRQ then do;
1541                          call syserr (Log_message_or_discard, "x25_mpx(^a/^d): Clear Indication ^d/^d on idle VC.",
1542                               x25_data.name, lcx, binary (x25_pkt.no_fc_data (1), 8), binary (x25_pkt.no_fc_data (2), 8));
1543                          call dump_pkt;
1544                          if xlce.state ^= DTE_CLEAR_REQUEST then call clear_confirm;
1545                          call reset_xlce;                   /* xsce already reset since this is an idle VC. */
1546                          goto done_in_pkt;
1547                          end;
1548 
1549 /* Clear Confirm */
1550 
1551                     if x25_pkt.type = CLRCN then do;
1552                          if xlce.state = DTE_CLEAR_REQUEST then do;
1553                               call reset_xlce;
1554                               call free_in_pkt;
1555                               goto done_in_pkt;
1556                               end;
1557 
1558                          else do;
1559                               call syserr (Log_message_or_discard,
1560                                    "x25_mpx(^a/^d): Clear Confirm in state ^d on idle VC.", x25_data.name, lcx,
1561                                    xlce.state);
1562                               call free_in_pkt;
1563                               call clear_call (20);
1564                               goto done_in_pkt;
1565                               end;
1566                          end;                               /* CLRCN packet */
1567 
1568 /* Anything else */
1569 
1570                     call syserr (Log_message, "x25_mpx(^a/^d); Unexpected packet type ^.4b on idle VC.", x25_data.name,
1571                          lcx, x25_pkt.type);
1572                     call dump_pkt;
1573                     call clear_call (20);
1574                     goto done_in_pkt;
1575                     end;
1576                end;
1577 %page;
1578 /* Waiting for restart */
1579 
1580           else if x25_data.state = X25_RESTARTING then do;
1581                if ((x25_pkt.type = RSRTRQ) | (x25_pkt.type = RSRTCN)) & (lcx = 0) then do;
1582                     call mcs_timer$reset (x25_data.devx, 0, ""b);
1583                     x25_data.state = X25_ACTIVE;
1584                     call pxss$ring_0_wakeup (x25_data.load_proc_id, x25_data.load_ev_chan, MPX_UP, code);
1585                     end;
1586                call free_in_pkt;
1587                goto done_in_pkt;
1588                end;
1589 
1590 /* Link not up yet */
1591 
1592           else do;
1593                call free_in_pkt;
1594                goto done_in_pkt;
1595                end;
1596 %page;
1597 done_in_pkt:
1598           return;
1599 
1600 
1601 done_data_pkt:                                              /* might have to send a RR */
1602           if blockp ^= null () then call free_in_pkt;
1603           if xlce.state = FLOW_CONTROL_READY then do;
1604                call send_data_packets;
1605                call send_output;
1606                call solicit_output;
1607                call send_rr;
1608                end;
1609           return;
1610 ^L
1611 
1612 /* * * * * * * * * * ADD_ITI_MODE * * * * * * * * * */
1613 
1614 add_iti_mode:
1615      procedure (Mode, Id, True, False);
1616 
1617 dcl  Mode fixed bin parameter;
1618 dcl  (Id, True, False) uns fixed bin (9) parameter;
1619 
1620           if xsce.mode (Mode)
1621           then call add_iti_param (Id, True);
1622           else call add_iti_param (Id, False);
1623           return;
1624      end add_iti_mode;
1625 
1626 /* * * * * * * * * * ADD_ITI_PARAM * * * * * * * * * */
1627 
1628 add_iti_param:
1629      procedure (Id, Value);
1630 
1631 dcl  (Id, Value) uns fixed bin (9) parameter;
1632 
1633           nchars = nchars + 2;
1634           l4_data (nchars - 1) = bit (Id);
1635           l4_data (nchars) = bit (Value);
1636           return;
1637      end add_iti_param;
1638 
1639 /* * * * * * * * * CLEAR_CALL * * * * * * * * */
1640 
1641 clear_call:
1642      procedure (Cause);
1643 
1644 dcl  Cause uns fixed bin (9) parameter;
1645 
1646           call get_buffer (16);
1647           call make_header (lcx, "0"b);
1648           x25_pkt.type = CLRRQ;
1649           x25_pkt.no_fc_data (2) = bit (Cause);
1650           buffer.tally = 5 + L2_HEADER_PAD;
1651           call write_pkt;
1652           call send_output;
1653           call state_change (DTE_CLEAR_REQUEST);
1654           return;
1655      end clear_call;
1656 
1657 /* * * * * * * * * CLEAR_CONFIRM * * * * * * * * * */
1658 
1659 clear_confirm:
1660      procedure;
1661 
1662           call get_buffer (16);
1663           call make_header (lcx, "0"b);
1664           x25_pkt.type = CLRCN;
1665           buffer.tally = 3 + L2_HEADER_PAD;
1666           call write_pkt;
1667           call send_output;
1668           return;
1669      end clear_confirm;
1670 
1671 /* * * * * * * * * * CONFIRM_INTERRUPT * * * * * * * * * */
1672 
1673 confirm_interrupt:
1674      procedure;
1675 
1676           call get_buffer (16);
1677           call make_header (lcx, "0"b);
1678           x25_pkt.type = SNITCN;
1679           buffer.tally = 3 + L2_HEADER_PAD;                 /* length of buffer = 3 */
1680           call write_pkt;
1681           call send_output;
1682           return;
1683      end confirm_interrupt;
1684 
1685 /* * * * * * * * * * CRASH_SUBCHANNELS * * * * * * * * * * */
1686 
1687 crash_subchannels:
1688      procedure;
1689 
1690           do lcx = 1 to x25_data.n_lc;
1691                xlcep = addr (x25_lces.lc (lcx));
1692                call reset_xlce;
1693           end;
1694           do scx = 1 to x25_data.n_sc;
1695                xscep = addr (x25_data.sc (scx));
1696                call reset_xsce;
1697           end;
1698           return;
1699      end crash_subchannels;
1700 
1701 /* * * * * * * * * * DUMP_PKT * * * * * * * * */
1702 
1703 dump_pkt:
1704      procedure;
1705 
1706 dcl  1 dump_buf (buffer.tally) unaligned based (addr (buffer.chars)),
1707        2 pad bit (1),
1708        2 byte bit (8);
1709 
1710           call syserr (Log_message_or_discard, "x25_mpx(^a):^( ^.4b^)", x25_data.name, dump_buf.byte (*));
1711           call free_in_pkt;
1712           return;
1713      end dump_pkt;
1714 
1715 /* * * * * * * * * * FIND_SC * * * * * * * * * */
1716 
1717 find_sc:
1718      procedure (Call_data) returns (fixed bin);
1719 
1720 dcl  Call_data varying char (16) parameter;
1721 dcl  scx fixed bin;
1722 
1723           do scx = 1 to x25_data.n_sc;
1724                if (x25_data.sc (scx).state = SC_LISTENING) & (x25_data.sc (scx).service = Call_data) then return (scx);
1725           end;
1726           return (0);
1727      end find_sc;
1728 
1729 /* * * * * * * * * FREE_IN_PKT * * * * * * * * * */
1730 
1731 free_in_pkt:
1732      procedure;
1733 
1734           call tty_space_man$free_chain (x25_data.devx, INPUT, blockp);
1735           blockp = null ();
1736           return;
1737      end free_in_pkt;
1738 
1739 /* * * * * * * * * * FREE_WRITE_CHAIN * * * * * * * * * */
1740 
1741 free_write_chain:
1742      procedure;
1743 
1744           if xsce.write_head ^= null () then do;
1745                call tty_space_man$free_chain (xsce.devx, OUTPUT, xsce.write_head);
1746                xsce.write_head, xsce.write_tail = null ();
1747                xsce.flags.end_of_page = "0"b;               /* Fix the flags since we just threw */
1748                xsce.flags.long_packet_pending = "0"b;       /* away what they applied to. */
1749                end;
1750           return;
1751      end free_write_chain;
1752 
1753 /* * * * * * * * * * FREE_X25_DATA_CHAIN * * * * * * * * * */
1754 
1755 free_x25_data_chain:
1756      procedure;
1757 
1758           if x25_data.write_head ^= null () then do;
1759                call tty_space_man$free_chain (x25_data.devx, OUTPUT, x25_data.write_head);
1760                x25_data.write_head, x25_data.write_tail = null ();
1761                end;
1762           return;
1763      end free_x25_data_chain;
1764 
1765 /* * * * * * * * * * GET_BUFFER * * * * * * * * * */
1766 
1767 get_buffer:
1768      procedure (Size);
1769 
1770 dcl  Size fixed bin parameter;
1771 
1772           call tty_space_man$get_buffer (x25_data.devx, Size, OUTPUT, blockp);
1773           endp = blockp;
1774           if blockp = null () then do;                      /* Big trouble, crash the multiplexer. */
1775                call free_x25_data_chain ();                 /* Get rid of pending output. */
1776                call syserr (Log_message, "x25_mpx(^a): No buffers available", x25_data.name);
1777                call channel_manager$control (x25_data.devx, "hangup", null (), code);
1778                                                             /* Crash ourself. */
1779                goto done_in_pkt;                            /* Non-local goto because callers can't handle blockp = null. */
1780                end;
1781           return;
1782      end get_buffer;
1783 
1784 /* * * * * * * * * HANDLE_DATA_OR_FC_ERROR * * * * * * * * * */
1785 
1786 handle_data_or_fc_error:
1787      procedure;
1788 
1789           if xlce.state = DTE_CLEAR_REQUEST | xlce.state = DTE_RESET_REQUEST
1790           then call free_in_pkt;                            /* Just discard. */
1791           else do;                                          /* Clear the lc with the right diagnostic. */
1792                call syserr (Log_message, "x25_mpx(^a): Data or flow control packet received in state ^d.", xsce.name,
1793                     xlce.state);
1794                call dump_pkt;
1795                if xlce.state = READY
1796                then call clear_call (20);
1797                else call clear_call (21);                   /* Must be DTE_WAITING state. */
1798                end;
1799      end handle_data_or_fc_error;
1800 
1801 /* * * * * * * * * * MAKE_HEADER * * * * * * * * * */
1802 
1803 make_header:
1804      procedure (Lcn, Q);
1805 dcl  Lcn uns fixed bin (12) parm;
1806 dcl  Q bit aligned parm;
1807 
1808           string (x25_pkt.l3_header) = ""b;
1809           x25_pkt.l3_header.q = Q;
1810           x25_pkt.l3_header.format = x25_data.gfid;
1811           x25_pkt.l3_header.lcgn = substr (bit (Lcn), 1, 4);
1812           x25_pkt.l3_header.lcn = substr (bit (Lcn), 5, 8);
1813           if xlcep = null () then do;
1814                l4_data_ptr = null ();
1815                hdr_size = 0;
1816                end;
1817           else if x25_data.seq_mod = 8 then do;
1818                l4_data_ptr = addr (m8_fc_data.user_data);
1819                hdr_size = 3;
1820                end;
1821           else do;
1822                l4_data_ptr = addr (m128_fc_data.user_data);
1823                hdr_size = 4;
1824                end;
1825           return;
1826      end make_header;
1827 
1828 /* * * * * * * * * PROC_CLEAR * * * * * * * * * */
1829 
1830 proc_clear:
1831      procedure;
1832 
1833           call reset_xlce;
1834           call reset_xsce;
1835           return;
1836      end proc_clear;
1837 
1838 /* * * * * * * * * * PROC_PR * * * * * * * * * */
1839 
1840 proc_pr:
1841      procedure (error_flag);
1842 
1843 dcl  error_flag bit (1) unaligned parameter;
1844 dcl  temp_pr unsigned fixed bin (7);
1845 
1846           error_flag = "0"b;
1847 
1848           xlce.flags.write_status_sync_sent = "0"b;         /* Well, he said something. */
1849 
1850           if x25_data.seq_mod = 8
1851           then temp_pr = m8_fc_data.pr;
1852           else temp_pr = m128_fc_data.pr;
1853 
1854 /*
1855    Check that next_ack_seq <= temp_pr <= next_send_seq, in clock order.
1856    That is, that the packet sequence number that he says he received is
1857    between the last sequence number he says he received, and the next
1858    sequence number we will send out (clockwise).
1859 */
1860 
1861           if (xlce.next_ack_seq <= temp_pr & temp_pr <= xlce.next_send_seq)
1862                | (xlce.next_send_seq <= xlce.next_ack_seq & xlce.next_ack_seq <= temp_pr)
1863                | (temp_pr <= xlce.next_send_seq & xlce.next_send_seq <= xlce.next_ack_seq)
1864           then xlce.next_ack_seq = temp_pr;
1865 
1866           else do;                                          /* Log the error. */
1867                error_flag = "1"b;
1868                call syserr (Log_message,
1869                     "x25_mpx(^a): Sequence error:  P(R) (= ^d) is not between previous P(R) (= ^d) and V(S) (= ^d).",
1870                     xsce.name, temp_pr, xlce.next_ack_seq, xlce.next_send_seq);
1871                call dump_pkt;
1872                call reset_lc (2);
1873                end;                                         /* Log the error. */
1874 
1875           return;
1876      end proc_pr;
1877 
1878 /* * * * * * * * * * PROC_RESET_LC * * * * * * * * * */
1879 
1880 proc_reset_lc:
1881      procedure;
1882 
1883           call reset_seq_nos;
1884           call free_write_chain ();                         /* discard possible pending output. */
1885           xlce.state = FLOW_CONTROL_READY;
1886           call reset_timer;
1887 
1888 /* Reset our state flags since we are going back to our initial state. */
1889 
1890           xlce.flags.iti_break = "0"b;
1891           xlce.flags.int_issued = "0"b;
1892           xlce.flags.rnr_received = "0"b;
1893           xlce.flags.write_status_sync_sent = "0"b;
1894 
1895 /* Now let the user know something happened, and make sure he can send output again. */
1896 
1897           call channel_manager$interrupt (xsce.devx, LINE_STATUS, "1"b);
1898                                                             /* the value does not really matter. */
1899           call solicit_output ();
1900 
1901           return;
1902      end proc_reset_lc;
1903 
1904 /* * * * * * * * * * RESET_LC * * * * * * * * * */
1905 
1906 reset_lc:
1907      procedure (Cause);
1908 
1909 dcl  Cause uns fixed bin (9) parameter;
1910 
1911           call get_buffer (16);
1912           call make_header (lcx, "0"b);
1913           x25_pkt.type = RESTRQ;
1914           x25_pkt.no_fc_data (2) = bit (Cause);
1915           buffer.tally = 5 + L2_HEADER_PAD;
1916           call write_pkt;
1917           call send_output;
1918           call state_change (DTE_RESET_REQUEST);
1919 
1920           xlce.flags.iti_break, xlce.flags.int_issued, xlce.flags.rnr_received, xlce.flags.write_status_sync_sent = "0"b;
1921           return;
1922      end reset_lc;
1923 
1924 /* * * * * * * * * * RESET_SEQ_NOS * * *  * * * * * * */
1925 
1926 reset_seq_nos:
1927      procedure;
1928 
1929           xlce.next_recv_seq, xlce.next_send_seq, xlce.last_recv_seq, xlce.next_ack_seq = 0;
1930           return;
1931      end reset_seq_nos;
1932 
1933 /* * * * * * * * * * RESET_TIMER * * * * * * * * * */
1934 
1935 reset_timer:
1936      procedure;
1937 
1938           if xlce.flags.timer_set then do;
1939                call mcs_timer$reset (x25_data.devx, (lcx), ""b);
1940                xlce.flags.timer_set = "0"b;
1941                end;
1942           return;
1943      end reset_timer;
1944 
1945 /* * * * * * * * * * * RESET_XLCE * * * * * * * * * * */
1946 
1947 reset_xlce:
1948      procedure;
1949 
1950           call reset_seq_nos;
1951           call reset_timer;
1952           string (xlce.flags) = ""b;
1953           xlce.iti_params (*) = 0;
1954 
1955           if lcx <= x25_data.n_pvc then do;
1956                xlce.state = FLOW_CONTROL_READY;
1957                end;
1958           else do;
1959                xlce.state = READY;
1960                xlce.scx = 0;
1961                end;
1962           return;
1963      end reset_xlce;
1964 
1965 /* * * * * * * * * RESET_XSCE * * * * * * * * * */
1966 
1967 reset_xsce:
1968      procedure;
1969 
1970           call free_write_chain;
1971           string (xsce.mode) = ""b;
1972           string (xsce.flags) = ""b;
1973           if /* case */ xsce.state = SC_DIALING then do;
1974                if protocol_mpx
1975                then call channel_manager$interrupt (xsce.devx, DIAL_STATUS,
1976                          "122"b3 || (27)"0"b || unspec (disconnect_info));
1977                else call channel_manager$interrupt (xsce.devx, DIAL_STATUS, "122"b3);
1978                end;
1979           else if xsce.state > SC_HUNGUP then do;
1980                if protocol_mpx then do;
1981                     if x25_data.state = X25_ACTIVE
1982                     then call channel_manager$interrupt (xsce.devx, HANGUP, (36)"0"b || unspec (disconnect_info));
1983                     else call channel_manager$interrupt (xsce.devx, CRASH, (36)"0"b || unspec (disconnect_info));
1984                     end;
1985                else do;
1986                     if x25_data.state = X25_ACTIVE
1987                     then call channel_manager$interrupt (xsce.devx, HANGUP, ""b);
1988                     else call channel_manager$interrupt (xsce.devx, CRASH, ""b);
1989                     end;
1990                end;
1991           xsce.state = SC_HUNGUP;
1992           xsce.lcx = 0;
1993           return;
1994      end reset_xsce;
1995 
1996 /* * * * * * * * * * RESTART * * * * * * * * * */
1997 
1998 restart:
1999      procedure (Cause);
2000 
2001 dcl  Cause uns fixed bin (9) parameter;
2002 
2003           call get_buffer (16);
2004           call make_header (0, "0"b);
2005           x25_pkt.type = RSRTRQ;                            /* restart request packet */
2006           x25_pkt.no_fc_data (2) = bit (Cause);
2007           buffer.tally = 5 + L2_HEADER_PAD;                 /* length of restart packet = 4 */
2008           call write_pkt;
2009           call send_output;
2010           x25_data.state = X25_RESTARTING;
2011           x25_data.restart_time = clock ();
2012           call mcs_timer$set (x25_data.devx, 0, x25_data.restart_time + T20, ""b);
2013           return;
2014      end restart;
2015 
2016 /* * * * * * * * * * SEND_DATA_PACKETS * * * * * * * * * */
2017 
2018 send_data_packets:
2019      procedure;
2020 
2021 dcl  pkt_size fixed bin;
2022 
2023           if xsce.flags.long_packet_pending | xlce.flags.rnr_received then return;
2024 
2025           do while ((mod (xlce.next_send_seq - xlce.next_ack_seq, x25_data.seq_mod) < xlce.max_window_size)
2026                & (xsce.write_head ^= null ()));
2027 
2028                blockp = xsce.write_head;
2029                pkt_size = buffer.tally;
2030                do endp = blockp repeat pointer (endp, endp -> buffer.next) while (^endp -> buffer.flags.break);
2031                     pkt_size = pkt_size + buffer.tally;
2032                end;
2033 
2034                if (pkt_size >= x25_data.long_packet_size)
2035                     & (^x25_data.flags.send_output | (x25_data.write_head ^= null ())) then do;
2036                     xsce.flags.long_packet_pending = "1"b;  /* thread into the long packet list */
2037                     xsce.long_packet_next_scx = 0;
2038                     if x25_data.long_packet_head = 0
2039                     then x25_data.long_packet_head = scx;
2040                     else x25_data.sc (x25_data.long_packet_tail).long_packet_next_scx = scx;
2041                     x25_data.long_packet_tail = scx;
2042                     return;
2043                     end;
2044 
2045                if endp -> buffer.next = 0
2046                then xsce.write_head, xsce.write_tail = null ();
2047                else xsce.write_head = pointer (endp, endp -> buffer.next);
2048                endp -> buffer.next = 0;
2049 
2050                if x25_data.seq_mod = 8 then do;
2051                     m8_fc_data.ps = xlce.next_send_seq;
2052                     m8_fc_data.pr = xlce.next_recv_seq;
2053                     end;
2054                else do;
2055                     m128_fc_data.ps = xlce.next_send_seq;
2056                     m128_fc_data.pr = xlce.next_recv_seq;
2057                     end;
2058 
2059                call write_pkt;
2060 
2061                xlce.next_send_seq = mod (xlce.next_send_seq + 1, x25_data.seq_mod);
2062                xlce.last_recv_seq = xlce.next_recv_seq;     /* increment V(S) */
2063           end;
2064           return;
2065      end send_data_packets;
2066 
2067 /* * * * * * * * * SEND_DIAG * * * * * * * * * */
2068 
2069 send_diag:
2070      procedure (Cause);
2071 
2072 dcl  Cause uns fixed bin (9) parameter;
2073 
2074           call get_buffer (16);
2075           call make_header (0, "0"b);
2076           x25_pkt.type = DIAG;
2077           x25_pkt.no_fc_data (1) = bit (Cause);
2078           buffer.tally = 4 + L2_HEADER_PAD;
2079           call write_pkt;
2080           call send_output;
2081           return;
2082      end send_diag;
2083 
2084 /* * * * * * * * * * SEND_OUTPUT * * * * * * * * * *  */
2085 
2086 send_output:
2087      procedure;
2088 
2089           if x25_data.flags.send_output & (x25_data.write_head ^= null ()) then do;
2090                x25_data.flags.send_output = "0"b;
2091                call channel_manager$write (x25_data.devx, x25_data.write_head, code);
2092                if code ^= 0 then do;
2093                     call syserr (Log_message, "x25_mpx(^a): Error ^w from write.", x25_data.name, code);
2094                     call channel_manager$control (x25_data.devx, "hangup", null (), code);
2095                     end;
2096                if x25_data.write_head = null () then x25_data.write_tail = null ();
2097                end;
2098           return;
2099      end send_output;
2100 
2101 /* * * * * * * * * SEND_RR * * * * * * * * * */
2102 
2103 send_rr:
2104      procedure;
2105 
2106 dcl  packets_out fixed bin (7);
2107 
2108           ttybp = addr (tty_buf$);
2109           lctep = addr (tty_buf.lct_ptr -> lct.lcte_array (xsce.devx));
2110           packets_out = mod (xlce.next_recv_seq - xlce.last_recv_seq, x25_data.seq_mod);
2111 
2112           if (3 * lcte.input_words) < tty_buf.bleft
2113           then if (clock () > xlce.force_ack_time) | (packets_out >= xlce.max_window_size) | xlce.flags.rnr_sent then do;
2114                     call get_buffer (16);
2115                     call make_header (lcx, "0"b);
2116                     x25_pkt.type = SNRR;
2117                     if x25_data.seq_mod = 8
2118                     then m8_fc_data.pr = xlce.next_recv_seq;
2119                     else m128_fc_data.pr = xlce.next_recv_seq;
2120                     buffer.tally = hdr_size + L2_HEADER_PAD;
2121                     call write_pkt;
2122                     call send_output;
2123                     xlce.last_recv_seq = xlce.next_recv_seq;
2124                     call reset_timer;
2125                     xlce.flags.rnr_sent = "0"b;
2126                     end;
2127                else if packets_out = 0 then ;
2128                else call set_timer (TIMEOUT);
2129 
2130           else do;
2131                if ^xlce.flags.rnr_sent then do;
2132                     call get_buffer (16);
2133                     call make_header (lcx, "0"b);
2134                     x25_pkt.type = SNRNR;
2135                     if x25_data.seq_mod = 8
2136                     then m8_fc_data.pr = xlce.next_recv_seq;
2137                     else m128_fc_data.pr = xlce.next_recv_seq;
2138                     buffer.tally = hdr_size + L2_HEADER_PAD;
2139                     call write_pkt;
2140                     call send_output;
2141                     xlce.last_recv_seq = xlce.next_recv_seq;
2142                     xlce.flags.rnr_sent = "1"b;
2143                     end;
2144                call set_timer (TIMEOUT);
2145                end;
2146 
2147           return;
2148      end send_rr;
2149 
2150 /* * * * * * * * * * SEND_SYNC * * * * * * * * * */
2151 
2152 send_sync:
2153      procedure;
2154 
2155           if (^x25_data.flags.no_d | ((x25_data.net_type = "tymnet") & (xsce.write_head = null ())))
2156                & ^xlce.flags.rnr_received then do;
2157                call get_buffer (16);                        /* write an empty packet */
2158                call make_header (lcx, "0"b);
2159                if ^x25_data.flags.no_d then x25_pkt.l3_header.d = "1"b;
2160                buffer.tally = hdr_size + L2_HEADER_PAD;
2161                call write_data_pkt;
2162                xlce.flags.write_status_sync_sent = "1"b;    /* We sent one, don't do it again until we hear something. */
2163                end;
2164           return;
2165      end send_sync;
2166 
2167 /* * * * * * * * * * SET_TIMER * * * * * * * * * */
2168 
2169 set_timer:
2170      procedure (Time);
2171 
2172 dcl  Time fixed bin (71) parameter;
2173 
2174           if ^xlce.flags.timer_set then do;
2175                call mcs_timer$set (x25_data.devx, (lcx), clock () + Time, ""b);
2176                xlce.flags.timer_set = "1"b;
2177                end;
2178           return;
2179      end set_timer;
2180 
2181 /* * * * * * * * * SET_X29 * * * * * * * * * */
2182 
2183 set_x29:
2184      procedure (Set, Write);
2185 
2186 dcl  (Set, Write) bit (1) aligned parameter;
2187 dcl  write bit (1) aligned;
2188 dcl  (i, p) fixed bin;
2189 
2190           write = Write;
2191           if Set then do;
2192                do i = 2 by 2 to buffer.tally - hdr_size - L2_HEADER_PAD;
2193                     p = binary (substr (l4_data (i), 3, 7), 7);
2194                     if (p < lbound (xlce.iti_params, 1)) | (p > hbound (xlce.iti_params, 1)) then do;
2195                          write = "1"b;
2196                          substr (l4_data (i), 2, 1) = "1"b;
2197                          end;
2198                     else xlce.iti_params (p) = binary (l4_data (i + 1), 8);
2199                end;
2200                if xsce.flags.need_ftd then do;
2201                     call channel_manager$interrupt (xsce.devx, LINE_STATUS, ""b);
2202                     xsce.flags.need_ftd = "0"b;
2203                     end;
2204                end;
2205 
2206           if write then do;
2207 
2208 /* In case there is no parameter list following the request it ought to point you to the parameters. */
2209 
2210                if protocol_mpx then do;
2211                     if buffer.tally < hdr_size + L2_HEADER_PAD + 2 then do;
2212                          call free_in_pkt;                  /* free the buffer that arrived */
2213                          call get_buffer (16);              /* allocate a larger buffer. */
2214                          call make_header (lcx, "1"b);
2215                          l4_data (1) = "000"b3;
2216                          do i = 1 to lbound (xlce.iti_params, 1) - 1;
2217                                                             /* not precise arguments */
2218                               l4_data (2 * i) = substr (unspec (i), 27, 9);
2219                               l4_data (2 * i + 1) = "000"b3;
2220                          end;
2221                          do i = lbound (xlce.iti_params, 1) to hbound (xlce.iti_params, 1);
2222                               l4_data (2 * i) = substr (unspec (i), 27, 9);
2223                               l4_data (2 * i + 1) = bit (xlce.iti_params (i));
2224                          end;
2225                          buffer.tally = hdr_size + L2_HEADER_PAD + 2 * hbound (xlce.iti_params, 1) + 1;
2226                          call write_data_pkt;
2227                          return;
2228                          end;
2229                     end;
2230                l4_data (1) = "000"b3;
2231                do i = 2 by 2 to buffer.tally - hdr_size - L2_HEADER_PAD;
2232                     p = binary (substr (l4_data (i), 3, 7), 7);
2233                     if (p >= lbound (xlce.iti_params, 1)) & (p <= hbound (xlce.iti_params, 1))
2234                     then l4_data (i + 1) = bit (xlce.iti_params (p));
2235                end;
2236                call tty_space_man$switch_chain (x25_data.devx, x25_data.devx, INPUT, OUTPUT, chain_ptr);
2237                call write_data_pkt;
2238                end;
2239           return;
2240      end set_x29;
2241 
2242 /* * * * * * * * * * SETUP_SUBCHAN * * * * * * * * * */
2243 
2244 setup_subchan:
2245      procedure;
2246 
2247           x25_data_ptr = X25_data_ptr;
2248           scx = X25_scx;
2249           xscep = addr (x25_data.sc (scx));
2250           lcx = xsce.lcx;
2251           if lcx = 0
2252           then xlcep = null ();
2253           else xlcep = addr (x25_lces.lc (xsce.lcx));
2254           return;
2255      end setup_subchan;
2256 
2257 /* * * * * * * * * * SIGNAL_DIALUP * * * * * * * * * */
2258 
2259 signal_dialup:
2260      procedure;
2261 
2262           dialup_info = x25_data.dialup_info;
2263           dialup_info.line_type = LINE_ASCII;               /* we simulate ASCII lines */
2264           dialup_info.baud_rate = xlce.baud_rate;
2265           if x25_data.seq_mod = 8
2266           then dialup_info.buffer_pad = dialup_info.buffer_pad + 3 + L2_HEADER_PAD;
2267                                                             /* 3 bytes in L3 header */
2268           else dialup_info.buffer_pad = dialup_info.buffer_pad + 4 + L2_HEADER_PAD;
2269                                                             /* 4 bytes in L3 header */
2270           dialup_info.max_buf_size = min (dialup_info.max_buf_size, divide (xlce.max_packet_size, 4, 9, 0));
2271           call channel_manager$interrupt (xsce.devx, DIALUP, unspec (dialup_info));
2272           xsce.state = SC_DIALED;
2273           xlce.state = FLOW_CONTROL_READY;
2274           call reset_timer;
2275           xsce.flags.output_ready = "1"b;
2276           call channel_manager$interrupt (xsce.devx, SEND_OUTPUT, ""b);
2277           return;
2278      end signal_dialup;
2279 
2280 /* * * * * * * * * * SOLICIT_OUTPUT * * * * * * * * * */
2281 
2282 solicit_output:
2283      procedure;
2284 
2285           if ^xsce.flags.output_ready & ^xsce.flags.end_of_page & ^xlce.flags.iti_break & (xsce.write_head = null ())
2286           then do;
2287                xsce.flags.output_ready = "1"b;
2288                call channel_manager$interrupt (xsce.devx, SEND_OUTPUT, ""b);
2289                end;
2290           return;
2291      end solicit_output;
2292 
2293 /* * * * * * * * * * STATE_CHANGE * * * * * * * * */
2294 
2295 state_change:
2296      procedure (State);
2297 
2298 dcl  State fixed bin;
2299 
2300           xlce.state = State;
2301           xlce.state_time = clock ();
2302           call reset_timer;
2303           call set_timer (T20);
2304           return;
2305      end state_change;
2306 
2307 /* * * * * * * * * * WRITE_DATA_PACKET * * * * * * * * * */
2308 
2309 write_data_pkt:
2310      procedure;
2311 
2312           endp -> buffer.flags.break = "1"b;
2313 
2314           if xsce.write_head = null () then do;
2315                xsce.write_head = blockp;
2316                xsce.write_tail = endp;
2317                blockp, endp = null ();
2318                call send_data_packets;
2319                call send_output;
2320                end;
2321           else do;
2322                xsce.write_tail -> buffer.next = binary (rel (blockp), 18);
2323                xsce.write_tail = endp;
2324                blockp, endp = null ();
2325                end;
2326           return;
2327      end write_data_pkt;
2328 
2329 /* * * * * * * * * * WRITE_PKT * * * * * * * * * */
2330 
2331 write_pkt:
2332      procedure;
2333 
2334           endp -> buffer.flags.break = "1"b;
2335           unspec (substr (endp -> buffer.chars (endp -> buffer.tally - 1), 1)) =
2336                unspec (substr (endp -> buffer.chars (endp -> buffer.tally - 1), 1)) | "400"b3;
2337 
2338           if protocol_mpx
2339           then if x25_data.packet_trace_sw then call log_packet ("1"b);
2340                                                             /* Log output packet before threading it in? */
2341           if x25_data.write_head = null ()
2342           then x25_data.write_head = blockp;
2343           else x25_data.write_tail -> buffer.next = binary (rel (blockp), 18);
2344           x25_data.write_tail = endp;
2345           blockp, endp = null ();
2346           return;
2347      end write_pkt;
2348 
2349 /* * * * * * * * * X25_HANGUP * * * * * * * * */
2350 
2351 x25_hangup:
2352      procedure;
2353 
2354 dcl  size builtin;
2355 
2356           call mcs_timer$reset_all (x25_data.devx);
2357           call free_x25_data_chain ();                      /* We might have some buffers left. */
2358 
2359           if x25_data.lc_ptr ^= null () then do;
2360                call tty_space_man$free_space (size (x25_lces), x25_data.lc_ptr);
2361                x25_data.lc_ptr = null ();
2362                end;
2363           x25_data.state = X25_HUNGUP;
2364           return;
2365      end x25_hangup;
2366 ^L
2367 log_packet:
2368      procedure (Write_sw);
2369 
2370 dcl  Write_sw bit (1) parameter;
2371 dcl  1 log_buf (buffer.tally) unaligned based (addr (buffer.chars)),
2372        2 pad bit (1),
2373        2 byte bit (8);
2374 dcl  n_octets fixed bin;                                    /* Dump this many. */
2375                                                             /* If regular data packet, then do not dump the data. */
2376           if substr (x25_pkt.type, 8, 1) = "0"b & ^x25_pkt.l3_header.q
2377           then n_octets = 5;                                /* L2 + L3 header. */
2378           else n_octets = buffer.tally;                     /* The works. */
2379           call syserr (Log_message_or_discard, "x25_mpx(^a): Packet ^[out^;in^]:^v( ^.4b^)", x25_data.name, Write_sw,
2380                n_octets, log_buf.byte (*));
2381           return;
2382      end log_packet;
2383 
2384 send_NCON_RESP:
2385      proc;                                                  /* envoi d'une confirmation d'appel */
2386           call get_buffer (16);
2387           call make_header (lcx, "0"b);
2388           x25_pkt.type = CALLAC;
2389           buffer.tally = 3 + L2_HEADER_PAD;
2390           call write_pkt;
2391           call send_output;
2392 
2393      end send_NCON_RESP;
2394 
2395 check_facilities:
2396      proc;
2397 
2398 /* Procedure to analyze the facilities field after verifying */
2399 /* if there is a request for taxation on demand. */
2400 
2401 dcl  i fixed bin;
2402 dcl  1 facilities (facility_length) unal based (addr (l3_facilities)),
2403        2 pad bit (1) unal,                                  /* overlap of the facility code field" */
2404        2 par_length fixed bin (2) uns unal,                 /* length of the "facility parameter" field. */
2405        2 code fixed bin (6) uns unal;                       /* facility code proper */
2406 
2407           xlce.flags.collect_call = "0"b;
2408           i = 1;
2409           do while (i <= facility_length);
2410                if facilities.code (i) = 1
2411                then                                         /* code taxation on demand (request) */
2412                     if facilities.code (i + 1) = 1 then xlce.flags.collect_call = "1"b;
2413                                                             /* test the corresponding parameter field */
2414                if facilities.par_length (i) = 3             /* calculate to pass on the following field */
2415                then                                         /* partial case : 1 octet suported for length of the parameter field */
2416                     i = i + facilities.code (i + 1) + 2;    /* assume length always < 64 */
2417                else i = i + facilities.par_length (i) + 2;
2418           end;
2419 
2420      end check_facilities;
2421 
2422 get_protocol_sc:
2423      proc returns (bit (1));                                /* search for a channel of the protocol type. */
2424 
2425           ttybp = addr (tty_buf$);
2426           lctep = addr (tty_buf.lct_ptr -> lct.lcte_array (xsce.devx));
2427           if (lcte.channel_type = PROTOCOL_MPX) then return ("1"b);
2428           return ("0"b);
2429 
2430      end get_protocol_sc;
2431 
2432 set_up_dialup_info:
2433      proc;
2434 
2435           dialup_info = x25_data.dialup_info;
2436           dialup_info.line_type = LINE_ASYNC1;
2437           if x25_data.seq_mod = 8
2438           then dialup_info.buffer_pad = x25_data.dialup_info.buffer_pad + 3 + L2_HEADER_PAD;
2439                                                             /* 3 bytes in L3 header */
2440           else dialup_info.buffer_pad = x25_data.dialup_info.buffer_pad + 4 + L2_HEADER_PAD;
2441                                                             /* 4 bytes in L3 header */
2442           dialup_info.max_buf_size = min (dialup_info.max_buf_size, divide (xlce.max_packet_size, 4, 9, 0));
2443 
2444      end set_up_dialup_info;
2445 
2446 %page;
2447 
2448 /* Special entry to perform per system (rather than per channel)
2449    initialization (called by priv_x25_mpx) */
2450 
2451 system_init:
2452      entry;
2453 
2454 /* copy error codes to wired linkage for reference at interrupt time */
2455 
2456           et_undefined_order_request = error_table_$undefined_order_request;
2457           et_noalloc = error_table_$noalloc;
2458           et_action_not_performed = error_table_$action_not_performed;
2459           et_bad_arg = error_table_$bad_arg;
2460           et_bad_mode = error_table_$bad_mode;
2461           et_invalid_state = error_table_$invalid_state;
2462           et_resource_unavailable = error_table_$resource_unavailable;
2463           et_unimplemented_version = error_table_$unimplemented_version;
2464 
2465           call wire_proc$wire_me;                           /* eat up some memory */
2466           return;
2467 %page;
2468 %include x25_data;
2469 %include protocol_infos;
2470 %include flow_control_info;
2471 %include foreign_terminal_data;
2472 %include lct;
2473 %include line_types;
2474 %include mcs_modes_change_list;
2475 %include mode_string_info;
2476 %include tty_buf;
2477 %include tty_buffer_block;
2478 %include channel_manager_dcls;
2479 %include mcs_timer_dcls;
2480 %include tty_space_man_dcls;
2481 %include multiplexer_types;
2482 
2483 /* Use this include file to avoid a conflict with mcs_interrupt_info.incl.pl1 */
2484 
2485 %include syserr_codes;
2486 %page;
2487 /* BEGIN MESSAGE DOCUMENTATION
2488 
2489    Message:
2490    x25_mpx(CHN): Unexpected interrupt TYPE DATA received.
2491 
2492    S: $log
2493 
2494    T: $run
2495 
2496    M: An unexpected MCM interrupt was processed.
2497 
2498    A: $notify
2499 
2500 
2501    Message:
2502    x25_mpx(CHN): Failure, Link state: STATE, Current Action: FUNCTION, in ESTATE, Primary state: PSTATE, Secondary state: SSTATE.
2503 
2504    S: $log
2505 
2506    T: $run
2507 
2508    M: Normal request to crash the line when the link has been disconnected by the FNP.
2509    STATE is the main state of the link. FUNCTION is the last function the link processed. The ESTATE is the execution state of the
2510    last function. PSTATE and SSTATE are the link up substate.
2511 
2512    A: $notify
2513 
2514 
2515    Message:
2516    x25_mpx(CHN): Link disconnected due to mis-matched frame sizes. CMDR/FRMR frame: FRAME.
2517 
2518    S: $log
2519 
2520    T: $run
2521 
2522    M: The FNP has received a command reject (LAPB) or frame reject (LAP) which
2523    specified a reason of "wide frame" on channel CHN.  The actual level 2
2524    command is FRAME.  This means the frame received by the other end was too
2525    long.  Instead of looping continuously trying to send this frame, the link
2526    will be disconnected.  The maximum frame size in the Multics TTF for this
2527    link should be checked against the size expected by the other end of the
2528    link, and corrected.
2529 
2530    A: $notify
2531 
2532 
2533    Message:
2534    x25_mpx(CHN/LC): Time out in state STATE.
2535 
2536    S: $log
2537 
2538    T: $run
2539 
2540    M: The network did not respond to a call, reset, or clear request.
2541    The call will be cleared.
2542 
2543    A: $notify
2544 
2545 
2546    Message:
2547    x25_mpx(CHN): Packet too short.
2548 
2549    S: $log
2550 
2551    T: $run
2552 
2553    M: A packet less then 3 characters long was received.
2554 
2555    A: $notify
2556 
2557 
2558    Message:
2559    x25_mpx(CHN): Unrecognized general format ID GFID.
2560 
2561    S: $log
2562 
2563    T: $run
2564 
2565    M: A packet with a bad format ID was received. The packet will be ignored.
2566 
2567    A: $notify
2568 
2569 
2570    Message:
2571    x25_mpx(CHN): Diagnostic type TYPE.
2572 
2573    S: $log
2574 
2575    T: $run
2576 
2577    M: A diagnostic packet of type TYPE was received. Normal processing continues.
2578 
2579    A: $notify
2580 
2581 
2582    Message:
2583    x25_mpx(CHN): Invalid packet type TYPE on LC 0.
2584 
2585    S: $log
2586 
2587    T: $run
2588 
2589    M: An invalid packet of type TYPE was received on logical channel zero.
2590    The packet will be ignored.
2591 
2592    A: $notify
2593 
2594 
2595    Message:
2596    x25_mpx(CHN): Unexpected packet type TYPE.
2597 
2598    S: $log
2599 
2600    T: $run
2601 
2602    M: An unexpected packet has been received.
2603    The packet is ignored.
2604 
2605    A: $notify
2606 
2607 
2608    Message:
2609    x25_mpx(CHN): Unexpected packet type TYPE on idle VC.
2610 
2611    S: $log
2612 
2613    T: $run
2614 
2615    M: An unexpected packet has been received on an idle channel.
2616    The channel is cleared.
2617 
2618    A: $notify
2619 
2620 
2621    Message:
2622    x25_mpx(CHN): Invalid channel number LCN.
2623 
2624    S: $log
2625 
2626    T: $run
2627 
2628    M: An X.25 packet with an invalid logical channel group number or logical
2629    channel number has been received.
2630    The packet is ignored.
2631 
2632    A: $notify
2633 
2634 
2635    Message:
2636    x25_mpx(CHN): Reset received CAUSE/DIAGNOSTIC.
2637 
2638    S: $log
2639 
2640    T: $run
2641 
2642    M: A RESET REQUEST packet has been received.
2643 
2644    A: $ignore
2645 
2646 
2647    Message:
2648    x25_mpx(CHN/LC): Call Request in state STATE.
2649 
2650    S: $log
2651 
2652    T: $run
2653 
2654    M: An unexpected Call Request has been received. The call is cleared.
2655 
2656 
2657    Message:
2658    x25_mpx(CHN/LC): No listening channels.
2659 
2660    S: $log
2661 
2662    T: $run
2663 
2664    M: There were no listening channels available for a network call.
2665    The call is refused.
2666 
2667    A: $notify
2668 
2669 
2670    Message:
2671    x25_mpx(CHN/LC): Clear Indication CAUSE/DIAGNOSTIC in idle VC.
2672 
2673    S: $log
2674 
2675    T: $run
2676 
2677    M: A Clear Indication has been received on a channel with no call
2678    in progress. A Clear Confirm is returned.
2679 
2680    A: $ignore
2681 
2682 
2683    Message:
2684    x25_mpx(CHN): Reset Confirm in state STATE.
2685 
2686    S: $log
2687 
2688    T: $run
2689 
2690    M: An unexpected Reset Confirm packet has been received.
2691    The call is reset.
2692 
2693    A: $notify
2694 
2695 
2696    Message:
2697    x25_mpx(CHN): Clear Confirm in state STATE.
2698 
2699    S: $log
2700 
2701    T: $run
2702 
2703    M: An unexpected Clear Confirm packet has been received.
2704    The call is cleared.
2705 
2706    A: $notify
2707 
2708 
2709    Message:
2710    x25_mpx(CHN): Data packet received in state STATE.
2711 
2712    S: $log
2713 
2714    T: $run
2715 
2716    M: An unexpected data packet was received.
2717    The call is cleared.
2718 
2719    A: $notify
2720 
2721 
2722    Message:
2723    x25_mpx(CHN): Unexpected Interrupt Confirm.
2724 
2725    S: $log
2726 
2727    T: $run
2728 
2729    M: An unexpected Interrupt Confirm packet has been received.
2730    The call is reset.
2731 
2732    A: $notify
2733 
2734 
2735    Message:
2736    x25_mpx(CHN): Sequence error P(S) = N, V(R) = N.
2737 
2738    S: $log
2739 
2740    T: $run
2741 
2742    M: An X.25 packet was received with an incorrect value for P(S).
2743    The logical channel is reset.
2744 
2745    A: $notify
2746 
2747 
2748    Message:
2749    x25_mpx(CHN): Sequence error:  P(R) (= N) is not between previous P(R) (= N) and V(S) (= N).
2750 
2751    S: $log
2752 
2753    T: $run
2754 
2755    M: An X.25 packet was received with an incorrect value for P(R).
2756    The logical channel is reset.
2757 
2758    A: $notify
2759 
2760 
2761    Message:
2762    x25_mpx(CHN): Invalid X.29 command CMD.
2763 
2764    S: $log
2765 
2766    T: $run
2767 
2768    M: An invalid X.29 command was received.
2769    An error indication is returned to the sender.
2770 
2771    A: $notify
2772 
2773 
2774    Message:
2775    x25_mpx(CHN): X.29 ERROR CODE/REASON.
2776 
2777    S: $log
2778 
2779    T: $run
2780 
2781    M: An X.29 ERROR packet with error code CODE and reason REASON was received.
2782    The packet is ignored.
2783 
2784    A: $notify
2785 
2786 
2787    Message:
2788    x25_mpx(CHN): Received REJ packet.
2789 
2790    S: $log
2791 
2792    T: $run
2793 
2794    M: An X.25 REJ packet was received. Multics does not support this feature.
2795    The virtual circuit is reset.
2796 
2797    A: $notify
2798 
2799 
2800    Message:
2801    x25_mpx(CHN): Clear Indication CAUSE/DIAGNOSTIC.
2802 
2803    S: $log
2804 
2805    T: $run
2806 
2807    M: A Clear Indication with non-zero cause or diagnostic fields has been received.
2808    The call is cleared.
2809 
2810    A: $ignore
2811 
2812 
2813    Message:
2814    x25_mpx(CHN): Call Confirm in state STATE.
2815 
2816    S: $log
2817 
2818    T: $run
2819 
2820    M: An unexpected Call Confirm packet was received. The call is cleared.
2821 
2822    A: $notify
2823 
2824 
2825    Message:
2826    x25_mpx(CHN): No buffers available.
2827 
2828    S: $log
2829 
2830    T: $run
2831 
2832    M: x25_mpx was unable to allocate a buffer for a protocol packet.
2833    This indicates a severe space problem in tty_buf.  The multiplexer will
2834    sends itself a "hangup" order after freeing any space it has for protocol
2835    packets in tty_buf.  If this multiplexer is not the cause of the problem
2836    then the system is likely to crash soon.
2837 
2838    A: $notify
2839 
2840 
2841    Message:
2842    x25_mpx(CHN): Error CODE from write.
2843 
2844    S: $log
2845 
2846    T: $run
2847 
2848    M: An error occurred writing to the LAP channel.
2849    The LAP channel will be disconnected.
2850 
2851    A: $notify
2852 
2853    Message:
2854    x25_mpx(CHN): Packet INOUT: PACKET
2855 
2856    S: $log
2857 
2858    T: $run
2859 
2860    M: A packet has been received or sent and is logged. This occurs when the
2861    packet tracing facility is turned on. INOUT is the direction and PACKET
2862    is the packet octets dumped in hexadecimal.
2863 
2864    A: $ignore
2865 
2866    END MESSAGE DOCUMENTATION */
2867 
2868      end x25_mpx;