1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 protocol_mpx:
23 proc;
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 dcl a_argptr ptr;
52 dcl a_data_base_ptr ptr;
53 dcl a_partial bit (1);
54 dcl a_event fixed bin (71);
55 dcl a_from_na char (15) varying;
56 dcl a_to_na char (15) varying;
57 dcl a_user_index fixed bin (17);
58 dcl a_call_data char (48) varying;
59 dcl a_order char (*);
60 dcl a_scp ptr;
61 dcl a_pinfop ptr;
62 dcl a_int_type fixed bin;
63 dcl a_type fixed bin;
64 dcl a_first_entry fixed bin;
65 dcl a_bytes_processed fixed bin (21);
66 dcl a_offset fixed bin (21);
67 dcl a_protocol_id fixed bin;
68 dcl a_info bit (72) aligned;
69 dcl a_code fixed bin (35);
70
71
72 dcl from_na char (15) varying;
73 dcl to_na char (15) varying;
74 dcl user_index fixed bin (17);
75 dcl call_data char (48) varying;
76 dcl bytes_processed fixed bin (21);
77 dcl scx fixed bin;
78 dcl miip ptr;
79 dcl order char (32);
80 dcl scp ptr;
81 dcl tcp ptr;
82 dcl scl fixed bin;
83 dcl cscp ptr;
84 dcl length_to_copy fixed bin;
85 dcl sci fixed bin (21);
86 dcl (scidx, tidx) fixed bin;
87 dcl (break, stop, end_chain, write_entry, read_entry)
88 bit (1);
89 dcl buf_size fixed bin;
90 dcl protocol_id fixed bin;
91 dcl orig_buf_size fixed bin;
92 dcl lchar fixed bin;
93 dcl cur_space fixed bin;
94 dcl cur_chain_len fixed bin;
95 dcl max_space fixed bin;
96 dcl max_chars fixed bin;
97 dcl max_chars_in_buf fixed bin;
98 dcl chars_in_buf fixed bin;
99 dcl (new_bufp, headp, lastp, prevp)
100 ptr;
101 dcl new_buf fixed bin;
102 dcl rest fixed bin (21);
103 dcl twx fixed bin;
104 dcl code fixed bin (35);
105 dcl event fixed bin (71);
106 dcl cleanup condition;
107 dcl (i, m, n) fixed bin;
108 dcl devx fixed bin (17);
109 dcl locked bit (1);
110 dcl 1 CON_REQ_info aligned like NCON_REQ_info;
111 dcl 1 N_I_i aligned based (addr (buffer.chars)) like NCON_IND_info;
112 dcl 1 net_infos aligned like network_infos;
113 dcl ignore_code fixed bin (35);
114 dcl int_type fixed bin;
115 dcl inchain fixed bin (18);
116 dcl next_offset fixed bin;
117 dcl last_offset fixed bin;
118 dcl new_headp ptr;
119 dcl old_tailp ptr;
120 dcl new_first_tally fixed bin;
121 dcl old_last_tally fixed bin;
122 dcl max_tally fixed bin;
123 dcl filled bit (1);
124 dcl source_ptr ptr;
125 dcl target_ptr ptr;
126 dcl pxss_status fixed bin (35);
127 dcl process_id bit (36) aligned;
128 dcl partial bit (1);
129
130 dcl 1 CON_IND_info aligned like NCON_IND_info based (pinfop);
131 dcl 1 ndis_ind_reason aligned like NDIS_IND_REASON based (pinfop);
132 dcl new_chars char (new_first_tally) based;
133
134
135 dcl STANDARD_SERVICE char (16) int static init ("^@^@@^@^@^A");
136
137 dcl ever_initialized bit (1) int static init ("0"b);
138
139
140 dcl (
141 error_table_$action_not_performed,
142 error_table_$bad_arg,
143 error_table_$buffer_big,
144 error_table_$io_no_permission,
145 error_table_$invalid_state,
146 error_table_$invalid_device,
147 error_table_$invalid_write,
148 error_table_$noalloc,
149 error_table_$resource_unavailable,
150 error_table_$undefined_order_request
151 ) ext fixed bin (35);
152
153 dcl no_write_code fixed bin (35) internal static;
154 dcl noalloc_code fixed bin (35) internal static;
155
156
157 dcl pds$processid ext static bit (36) aligned;
158
159 dcl tty_lock$lock_channel entry (fixed bin, fixed bin (35));
160 dcl tty_lock$unlock_channel
161 entry (fixed bin);
162 dcl pxss$ring_0_wakeup entry (bit (36) aligned, fixed bin (71), fixed bin (71), fixed bin (35));
163 dcl pxss$unique_ring_0_wakeup
164 entry (bit (36) aligned, fixed bin (71), fixed bin (71), fixed bin (35));
165 dcl tc_util$validate_processid
166 entry (bit (36) aligned, fixed bin (35));
167 dcl syserr entry options (variable);
168 dcl wire_proc$wire_me entry;
169
170 dcl DIAG_71 fixed bin int static init (71) options (constant);
171 dcl LONGEST_POSSIBLE_STRING
172 fixed bin init (8128) int static options (constant);
173 dcl MILLISECONDS_2 fixed bin (21) int static init (2000000) options (constant);
174 dcl SIZE4 fixed bin int static init (4) options (constant);
175 dcl SIZE16 fixed bin int static init (16) options (constant);
176 dcl WAKEUP_CODE_0 fixed bin int static init (0) options (constant);
177 dcl WAKEUP_CODE_5 fixed bin int static init (5) options (constant);
178 dcl WAKEUP_CODE_100 fixed bin int static init (100) options (constant);
179 dcl max_chain_len fixed bin int static init (64) options (constant);
180
181
182 dcl (addr, bin, ceil, clock, divide, hbound, lbound, length, min, null, ptr, rel, string, substr, unspec)
183 builtin;
184 %page;
185
186 return;
187
188 start:
189 entry (a_data_base_ptr, a_code);
190
191 a_code = 0;
192 channel_ptr = a_data_base_ptr;
193 devx = channel.devx;
194 locked = "0"b;
195 channel.flags.started = "1"b;
196 if channel.state = HUNGUP
197 then call channel_manager$control (devx, "listen", null (), code);
198 a_code = code;
199 return;
200
201
202 stop:
203 entry (a_data_base_ptr, a_code);
204 channel_ptr = a_data_base_ptr;
205 channel.flags.started = "0"b;
206 a_code = 0;
207 locked = "0"b;
208 return;
209
210
211 shutdown:
212 entry (a_data_base_ptr, a_code);
213 channel_ptr = a_data_base_ptr;
214 locked = "0"b;
215 devx = channel.devx;
216 if channel.state > HUNGUP
217 then call channel_manager$control (devx, "hangup", null (), code);
218 a_code = code;
219 return;
220
221
222 priv_control:
223 entry (a_data_base_ptr, a_order, a_pinfop, a_code);
224
225 channel_ptr = a_data_base_ptr;
226 order = a_order;
227 pinfop = a_pinfop;
228 a_code = 0;
229 locked = "0"b;
230 return;
231
232
233 hpriv_control:
234 entry (a_data_base_ptr, a_order, a_pinfop, a_code);
235 channel_ptr = a_data_base_ptr;
236 order = a_order;
237 pinfop = a_pinfop;
238 locked = "0"b;
239 devx = channel.devx;
240 if order = "load_mpx"
241 then if channel.flags.initialized & channel.state = INACTIVE
242 then do;
243 call channel_manager$control (devx, "get_network_infos", addr (net_infos), code);
244 if code = 0
245 then do;
246 channel.our_network_address = net_infos.network_address;
247 channel.max_packet_size = net_infos.max_packet_size;
248 channel.load_proc_id = pds$processid;
249 channel.state = HUNGUP;
250 end;
251 end;
252 else code = error_table_$invalid_state;
253 else code = error_table_$undefined_order_request;
254 a_code = code;
255 return;
256
257 %page;
258 init_multiplexer:
259 entry (twx, a_argptr, a_data_base_ptr, a_code);
260
261 devx = twx;
262 infop = addr (dn355_data$);
263 protocol_data_ptr = datanet_info.protocol_datap;
264 ttybp = addr (tty_buf$);
265 lctp = tty_buf.lct_ptr;
266 lcntp = lct.lcnt_ptr;
267 miip = a_argptr;
268 a_data_base_ptr = null;
269 a_code = 0;
270 locked = "0"b;
271
272 if ^ever_initialized
273 then do;
274 do i = 1 to protocol_data.max_channels;
275 unspec (protocol_data.channels (i)) = ""b;
276 protocol_data.channels (i).name = "";
277 protocol_data.channels (i).our_network_address = "";
278 protocol_data.channels (i).his_network_address = "";
279 protocol_data.channels (i).call_data = "";
280 protocol_data.channels (i).facilities = "";
281 end;
282 protocol_data.n_channels = 0;
283 protocol_data.init_time = clock ();
284 unspec (listeners (*)) = ""b;
285 unspec (protocol_data.special_listeners (*)) = ""b;
286 protocol_data.special_listeners.datas (*) = "";
287 call set_static;
288 ever_initialized = "1"b;
289 end;
290
291 if protocol_data.n_channels >= protocol_data.max_channels
292 then do;
293 call syserr (Log_message, "protocol_mpx$init_multiplexer : not enough channels configured on PROT PARM.");
294 a_code = noalloc_code;
295 return;
296 end;
297 protocol_data.n_channels = protocol_data.n_channels + 1;
298 do i = 1 to protocol_data.max_channels;
299 channel_ptr = addr (protocol_data.channels (i));
300 if ^channel.flags.initialized
301 then do;
302 channel.name = lcnt (devx).names;
303 channel.devx = devx;
304 channel.state = INACTIVE;
305 channel.flags.initialized = "1"b;
306 a_data_base_ptr = channel_ptr;
307 return;
308 end;
309 end;
310 call syserr (Log_message, "protocol_mpx$init_multiplexer : no free channel found");
311 a_code = noalloc_code;
312 return;
313
314 %page;
315
316 terminate_multiplexer:
317 entry (a_data_base_ptr, a_code);
318
319 a_code = 0;
320 locked = "0"b;
321 channel_ptr = a_data_base_ptr;
322 infop = addr (dn355_data$);
323 protocol_data_ptr = datanet_info.protocol_datap;
324 call mcs_timer$reset_all (channel.devx);
325 protocol_data.n_channels = protocol_data.n_channels - 1;
326 if protocol_data.n_channels < 0
327 then call syserr (Log_message,
328 "protocol_mpx$terminate_multiplexer : more terminate_multiplexer calls than init_multiplexer calls on ^a",
329 channel.name);
330 unspec (channel) = ""b;
331 a_data_base_ptr = null ();
332 return;
333 %page;
334 set_listener:
335 entry (a_protocol_id, a_event, a_code);
336 event = a_event;
337 protocol_id = a_protocol_id;
338 locked = "0"b;
339 infop = addr (dn355_data$);
340 protocol_data_ptr = datanet_info.protocol_datap;
341 if protocol_id < lbound (protocol_data.listeners, 1) | protocol_id > hbound (protocol_data.listeners, 1)
342 then do;
343 a_code = error_table_$bad_arg;
344 return;
345 end;
346 protocol_data.listeners (protocol_id).proc_id = pds$processid;
347 protocol_data.listeners (protocol_id).event_id = event;
348 a_code = 0;
349 return;
350
351 set_special_listener:
352 entry (a_call_data, a_partial, a_event, a_code);
353 call_data = a_call_data;
354 event = a_event;
355 partial = a_partial;
356 a_code = 0;
357 locked = "0"b;
358 do i = 1 to hbound (layer3_call_datas, 1) while (call_data ^= layer3_call_datas (i));
359 end;
360 if i <= hbound (layer3_call_datas, 1) | call_data = ""
361 then do;
362 a_code = error_table_$bad_arg;
363 return;
364 end;
365 infop = addr (dn355_data$);
366 protocol_data_ptr = datanet_info.protocol_datap;
367 n = hbound (protocol_data.special_listeners, 1);
368 do i = 1 to n while (protocol_data.special_listeners.call_datas.datas (i) ^= call_data);
369 end;
370 if i > n
371 then
372 do i = 1 to n while (protocol_data.special_listeners.call_datas.datas (i) ^= "");
373 end;
374 if i > n
375 then do;
376 a_code = error_table_$action_not_performed;
377 return;
378 end;
379 protocol_data.special_listeners.call_datas.partial (i) = partial;
380 protocol_data.special_listeners.call_datas.datas (i) = call_data;
381 protocol_data.special_listeners.proc_id (i) = pds$processid;
382 protocol_data.special_listeners.event_id (i) = event;
383 return;
384
385 remove_listener:
386 entry (a_protocol_id, a_code);
387 protocol_id = a_protocol_id;
388 locked = "0"b;
389 infop = addr (dn355_data$);
390 protocol_data_ptr = datanet_info.protocol_datap;
391 if protocol_id < lbound (protocol_data.listeners, 1) | protocol_id > hbound (protocol_data.listeners, 1)
392 then do;
393 a_code = error_table_$bad_arg;
394 return;
395 end;
396 a_code = 0;
397 if protocol_data.listeners (protocol_id).proc_id ^= pds$processid
398 then a_code = error_table_$io_no_permission;
399 else unspec (protocol_data.listeners (protocol_id)) = ""b;
400 return;
401
402 remove_special_listener:
403 entry (a_call_data, a_code);
404 call_data = a_call_data;
405 locked = "0"b;
406 a_code = 0;
407 if call_data = ""
408 then do;
409 a_code = error_table_$bad_arg;
410 return;
411 end;
412 infop = addr (dn355_data$);
413 protocol_data_ptr = datanet_info.protocol_datap;
414 do i = 1 to hbound (protocol_data.special_listeners, 1)
415 while (protocol_data.special_listeners.call_datas (i).datas ^= call_data);
416 end;
417 if i > hbound (protocol_data.special_listeners, 1)
418 then do;
419 a_code = error_table_$action_not_performed;
420 return;
421 end;
422 if protocol_data.special_listeners (i).proc_id ^= pds$processid
423 then a_code = error_table_$io_no_permission;
424 else do;
425 protocol_data.special_listeners (i).call_datas.datas = "";
426 protocol_data.special_listeners (i).call_datas.partial = "0"b;
427 protocol_data.special_listeners (i).proc_id = ""b;
428 protocol_data.special_listeners (i).event_id = 0;
429 end;
430 return;
431
432 %page;
433 ncon_req:
434 entry (a_user_index, twx, a_event, a_from_na, a_to_na, a_call_data, a_code);
435
436 user_index = a_user_index;
437 event = a_event;
438 from_na = a_from_na;
439 to_na = a_to_na;
440 call_data = a_call_data;
441
442 ttybp = addr (tty_buf$);
443 lctp = tty_buf.lct_ptr;
444 infop = addr (dn355_data$);
445 protocol_data_ptr = datanet_info.protocol_datap;
446 call check_orphan_connections;
447 twx = 0;
448 scx = get_channel (from_na);
449 if scx = 0
450 then do;
451 a_code = error_table_$resource_unavailable;
452 return;
453 end;
454 channel_ptr = addr (protocol_data.channels (scx));
455 devx = channel.devx;
456 locked = "0"b;
457 on cleanup call cleaner;
458 call tty_lock$lock_channel (devx, code);
459 if code ^= 0
460 then goto unlock;
461 locked = "1"b;
462
463 channel.user_proc_id, channel.listener_proc_id = pds$processid;
464 channel.user_event, channel.listener_event = event;
465 channel.user_ref = user_index;
466 channel.flags.in_use = "1"b;
467 channel.his_network_address = to_na;
468 channel.space_left_in_packet = channel.max_packet_size;
469
470 CON_REQ_info.mbz = 0;
471 CON_REQ_info.to_address = to_na;
472 CON_REQ_info.facilities = STANDARD_SERVICE;
473 CON_REQ_info.data = call_data;
474 call channel_manager$control (devx, "dial_out", addr (CON_REQ_info), code);
475 if code = 0
476 then channel.state = DIALING;
477 else call reset_channel;
478 twx = devx;
479 goto unlock;
480
481
482
483 ncon_resp:
484 entry (a_user_index, twx, a_event, a_code);
485 locked = "0"b;
486 on cleanup call cleaner;
487 call setup;
488 if channel.state ^= DIALING
489 then do;
490 code = error_table_$invalid_state;
491 goto unlock;
492 end;
493 channel.user_ref = a_user_index;
494 channel.user_event = a_event;
495 channel.user_proc_id = pds$processid;
496 call channel_manager$control (devx, "connect_response", null (), code);
497 if code = 0
498 then do;
499 channel.state = DIALED;
500 channel.rflag = "1"b;
501 end;
502 goto unlock;
503
504 write:
505 entry (twx, a_pinfop, a_first_entry, a_offset, a_bytes_processed, a_code);
506 pinfop = a_pinfop;
507 scidx = a_first_entry;
508 sci = a_offset;
509 a_bytes_processed = 0;
510 locked = "0"b;
511 on cleanup call cleaner;
512 call setup;
513 if channel.state ^= DIALED
514 then goto inv_state;
515 if pinfop ^= null ()
516 then if scidx < 0 | scidx > transmit_info.n_entries | sci < 0 | sci > transmit_info (scidx).size - 1
517 then goto bad_args;
518 else ;
519 else goto bad_args;
520 scl = 0;
521 do i = scidx to transmit_info.n_entries;
522 scl = scl + transmit_info (i).size;
523 end;
524 scl = scl - sci;
525 if scl <= 0
526 then goto unlock;
527 write_entry = "1"b;
528 break = "1"b;
529 goto send_common;
530
531 ndt_req:
532 entry (twx, a_scp, a_offset, a_bytes_processed, a_code);
533
534 scp = a_scp;
535 sci = a_offset;
536 scl = 0;
537 a_bytes_processed = 0;
538 locked = "0"b;
539 on cleanup call cleaner;
540 call setup;
541 if channel.state ^= DIALED
542 then do;
543 inv_state:
544 code = error_table_$invalid_state;
545 goto unlock;
546 end;
547
548 if scp = null ()
549 then do;
550 bad_args:
551 code = error_table_$bad_arg;
552 goto unlock;
553 end;
554 if sci < 0 | sci >= scp -> buffer.tally
555 then goto bad_args;
556 blockp = scp;
557 call check_length (break, scl);
558 scl = scl - sci;
559 if scl = 0
560 then goto unlock;
561 cscp = scp;
562 write_entry = "0"b;
563 send_common:
564 bytes_processed = 0;
565 if scl > channel.max_nsdu_size
566 then do;
567 code = error_table_$buffer_big;
568 goto unlock;
569 end;
570 cur_space = 0;
571 cur_chain_len = 0;
572 if channel.write_first ^= 0
573 then do;
574 blockp = ptr (ttybp, channel.write_first);
575 end_chain = "0"b;
576 do while (^end_chain);
577 cur_space = cur_space + SIZE16 * (buffer.size_code + 1);
578 cur_chain_len = cur_chain_len + 1;
579 if buffer.next = 0
580 then end_chain = "1"b;
581 else blockp = ptr (ttybp, buffer.next);
582 end;
583 end;
584 max_space =
585 min (divide (tty_buf.bleft, output_bpart, 17, 0) - cur_space,
586 (max_chain_len - cur_chain_len) * (channel.max_buf_size - 1));
587
588 max_chars_in_buf = SIZE4 * (channel.max_buf_size - 1) - channel.buffer_pad;
589
590 if max_space <= 0
591 then do;
592 if channel.send_output
593 then call tty_space_man$needs_space (devx);
594 else channel.flags.wflag = "1"b;
595 goto unlock;
596 end;
597 max_chars = min (SIZE4 * max_space, LONGEST_POSSIBLE_STRING);
598 cur_chain_len = max_chain_len - cur_chain_len;
599 length_to_copy = min (max_chars, scl);
600 if length_to_copy < scl
601 then break = "0"b;
602
603 if channel.write_last ^= 0
604 then do;
605 lastp, blockp = ptr (ttybp, channel.write_last);
606 if buffer.tally < max_chars_in_buf & ^buffer.flags.break
607 & channel.space_left_in_packet ^= channel.max_packet_size
608
609 then do;
610 buf_size, orig_buf_size = SIZE16 * (buffer.size_code + 1);
611 lchar = buffer.tally;
612 stop = "0"b;
613 do while (^stop);
614 chars_in_buf = SIZE4 * (buf_size - 1) - channel.buffer_pad;
615 if lchar + length_to_copy <= chars_in_buf | chars_in_buf = max_chars_in_buf
616 | lchar + channel.space_left_in_packet <= chars_in_buf
617 then stop = "1"b;
618 else buf_size = buf_size + SIZE16;
619 end;
620
621 if buf_size ^= orig_buf_size
622 then do;
623 call tty_space_man$get_buffer (devx, buf_size, OUTPUT, new_bufp);
624 if new_bufp ^= null ()
625 then do;
626 call copy_chars ((lastp), 0, (lastp -> buffer.tally), new_bufp, 0);
627
628 new_buf = bin (rel (new_bufp), 18);
629 new_bufp -> buffer.tally = lastp -> buffer.tally;
630 channel.write_last = new_buf;
631
632 prevp = ptr (ttybp, channel.write_first);
633
634 if prevp = lastp
635 then channel.write_first = channel.write_last;
636
637 else do;
638 do prevp = prevp repeat ptr (ttybp, prevp -> buffer.next)
639 while (prevp -> buffer.next ^= bin (rel (lastp), 18) & prevp -> buffer.next ^= 0);
640 end;
641 prevp -> buffer.next = channel.write_last;
642
643 end;
644
645 call tty_space_man$free_buffer (devx, OUTPUT, lastp);
646 lastp = new_bufp;
647
648 end;
649 else chars_in_buf = SIZE4 * (orig_buf_size - 1) - channel.buffer_pad;
650 end;
651 n = min (length_to_copy, chars_in_buf - lchar, channel.space_left_in_packet);
652 if write_entry
653 then call copy_from_user_to_us (scidx, sci, n, lastp, (lastp -> buffer.tally));
654 else call copy_chars (cscp, sci, n, lastp, (lastp -> buffer.tally));
655 bytes_processed = bytes_processed + n;
656 channel.space_left_in_packet = channel.space_left_in_packet - n;
657 if channel.space_left_in_packet = 0
658 then channel.space_left_in_packet = channel.max_packet_size;
659 length_to_copy = length_to_copy - n;
660 lastp -> buffer.tally = lastp -> buffer.tally + n;
661 string (lastp -> buffer.flags) = "0"b;
662 lastp -> buffer.next = 0;
663 end;
664
665 end;
666
667 do length_to_copy = length_to_copy repeat (length_to_copy - n) while (length_to_copy > 0);
668 m = min (length_to_copy, channel.space_left_in_packet);
669 if m >= max_chars_in_buf
670 then do;
671 n = max_chars_in_buf;
672 buf_size = channel.max_buf_size;
673 end;
674 else do;
675 stop = "0"b;
676 buf_size = SIZE16;
677 do while (^stop);
678 chars_in_buf = SIZE4 * (buf_size - 1) - channel.buffer_pad;
679 if m <= chars_in_buf
680 then stop = "1"b;
681 else buf_size = buf_size + SIZE16;
682 end;
683 n = m;
684 end;
685 if cur_chain_len = 0
686 then new_bufp = null ();
687 else call tty_space_man$get_buffer (devx, buf_size, OUTPUT, new_bufp);
688 if new_bufp = null ()
689 then goto try_to_send;
690 cur_chain_len = cur_chain_len - 1;
691 if write_entry
692 then call copy_from_user_to_us (scidx, sci, n, new_bufp, 0);
693 else call copy_chars (cscp, sci, n, new_bufp, 0);
694 bytes_processed = bytes_processed + n;
695 new_bufp -> buffer.tally = n;
696 new_buf = bin (rel (new_bufp), 18);
697 channel.space_left_in_packet = channel.space_left_in_packet - n;
698 if channel.space_left_in_packet = 0
699 then channel.space_left_in_packet = channel.max_packet_size;
700 if channel.write_last = 0
701 then
702 channel.write_first = new_buf;
703 else lastp -> buffer.next = new_buf;
704 channel.write_last = new_buf;
705 lastp = new_bufp;
706 new_bufp -> buffer.next = 0;
707 string (new_bufp -> buffer.flags) = "0"b;
708 end;
709
710 if break & length_to_copy = 0
711 then do;
712 lastp -> buffer.flags.break = "1"b;
713 channel.space_left_in_packet = channel.max_packet_size;
714 if write_entry
715 then scidx = 0;
716 end;
717
718 try_to_send:
719 if channel.send_output
720 then call send_next_nsdu;
721 if write_entry & scidx ^= 0 | ^write_entry & cscp ^= null ()
722 then do;
723
724 channel.flags.wflag = "1"b;
725 if channel.flags.send_output
726 then call tty_space_man$needs_space (devx);
727 end;
728 a_offset = sci;
729 a_bytes_processed = bytes_processed;
730 if write_entry
731 then a_first_entry = scidx;
732 else a_scp = cscp;
733 goto unlock;
734
735
736 ndis_req:
737 entry (twx, a_pinfop, a_code);
738 locked = "0"b;
739 on cleanup call cleaner;
740 call setup;
741 if channel.state > HUNGUP
742 then do;
743 call channel_manager$control (devx, "hangup", a_pinfop, code);
744 channel.state = HUNGUP;
745 call reset_channel;
746 end;
747 else code = error_table_$invalid_state;
748 goto unlock;
749
750 read:
751 entry (twx, a_pinfop, rest, a_bytes_processed, a_code);
752 read_entry = "1"b;
753 int_type = NDTIND;
754 goto g_i;
755
756 get_info:
757 entry (twx, a_int_type, a_pinfop, rest, a_bytes_processed, a_code);
758
759 int_type = a_int_type;
760 read_entry = "0"b;
761 g_i:
762 pinfop = a_pinfop;
763 rest, bytes_processed, a_bytes_processed = 0;
764 locked = "0"b;
765 on cleanup call cleaner;
766 call setup;
767
768 if int_type = NCONIND
769 then do;
770 if channel.state >= DIALING
771 then do;
772 CON_IND_info.our_address = channel.our_network_address;
773 CON_IND_info.his_address = channel.his_network_address;
774 CON_IND_info.data = channel.call_data;
775 CON_IND_info.facilities = channel.facilities;
776 CON_IND_info.dial_info = ""b;
777 rest = channel.max_nsdu_size;
778 code = 0;
779 end;
780 else code = error_table_$invalid_state;
781 end;
782
783 else if int_type = NCONCONF
784 then rest = channel.max_nsdu_size;
785
786 else if int_type = NDTIND
787 then do;
788 if channel.state = DIALED
789 then do;
790 if ^read_entry
791 then do;
792 tcp = pinfop;
793 if tcp = null ()
794 then goto bad_args;
795 n, i = 0;
796 do blockp = tcp repeat (ptr (blockp, buffer.next)) while (rel (blockp) ^= "0"b);
797 i = i + 1;
798 if i > 512
799 then goto bad_args;
800 n = n + max_buffer_tally (buffer.size_code);
801 end;
802 end;
803 else do;
804 if pinfop = null ()
805 then goto bad_args;
806 n = 0;
807 do i = 1 to transmit_info.n_entries;
808 n = n + transmit_info (i).size;
809 if transmit_info (i).data_ptr = null ()
810 then goto bad_args;
811 end;
812 tidx = 1;
813 end;
814 headp, cscp, blockp = ptr (ttybp, channel.fblock);
815 if channel.fblock ^= 0
816 then do;
817 call check_length (break, length_to_copy);
818 if ^break
819 then goto check_rest;
820 if length_to_copy > n
821 then do;
822 length_to_copy = n;
823 break = "0"b;
824 end;
825 sci = 0;
826 do length_to_copy = length_to_copy repeat (length_to_copy - n) while (length_to_copy > 0);
827 if read_entry
828 then do;
829 n = min (length_to_copy, transmit_info (tidx).size);
830 call copy_from_us_to_user (cscp, sci, n, tidx, 0);
831 tidx = tidx + 1;
832 end;
833 else do;
834 n = min (length_to_copy, max_buffer_tally (tcp -> buffer.size_code));
835 call copy_chars (cscp, sci, n, tcp, 0);
836 string (tcp -> buffer.flags) = "0"b;
837 tcp -> buffer.tally = n;
838 prevp = tcp;
839 tcp = ptr (tcp, tcp -> buffer.next);
840 end;
841 bytes_processed = bytes_processed + n;
842 end;
843 if ^read_entry
844 then prevp -> buffer.flags.break = break;
845 if cscp = null
846 then do;
847 call tty_space_man$free_chain (devx, INPUT, headp);
848
849 channel.fblock, channel.lblock = 0;
850 end;
851 else do;
852 n = cscp -> buffer.tally - sci;
853
854 prevp = cscp;
855 call copy_chars (prevp, sci, n, prevp, 0);
856 cscp -> buffer.tally = n;
857 i = bin (rel (cscp), 18);
858 if channel.fblock ^= i
859 then do;
860 do blockp = headp repeat (ptr (blockp, buffer.next)) while (buffer.next ^= i);
861 end;
862 buffer.next = 0;
863 channel.fblock = i;
864 call tty_space_man$free_chain (devx, INPUT, headp);
865 end;
866 end;
867 end;
868 check_rest:
869 if channel.fblock ^= 0
870 then do;
871 blockp = ptr (ttybp, channel.fblock);
872 call check_length (break, n);
873 rest = 0;
874 channel.flags.rflag = "0"b;
875 if break
876 then rest = n;
877 else channel.flags.rflag = "1"b;
878 end;
879 else channel.flags.rflag = "1"b;
880 a_bytes_processed = bytes_processed;
881 end;
882 else code = error_table_$invalid_state;
883 end;
884
885 else code = error_table_$bad_arg;
886 goto unlock;
887 %page;
888 interrupt:
889 entry (a_data_base_ptr, a_type, a_info);
890
891
892
893 channel_ptr = a_data_base_ptr;
894 int_type = a_type;
895 interrupt_info = a_info;
896 locked = "0"b;
897 devx = channel.devx;
898 ttybp = addr (tty_buf$);
899 infop = addr (dn355_data$);
900 protocol_data_ptr = datanet_info.protocol_datap;
901
902 if int_type = DIALUP
903 then do;
904 unspec (DIALUP_info) = interrupt_info;
905 if channel.state ^= HUNGUP
906 then goto bad_int;
907 blockp = ptr (ttybp, DIALUP_info.info_relp);
908 NCON_IND_info = N_I_i;
909 unspec (dialup_info) = unspec (NCON_IND_info.dial_info);
910 channel.buffer_pad = dialup_info.buffer_pad;
911 channel.max_buf_size = dialup_info.max_buf_size;
912 channel.space_left_in_packet = channel.max_packet_size;
913 channel.his_network_address = NCON_IND_info.his_address;
914 channel.call_data = NCON_IND_info.data;
915 channel.facilities = NCON_IND_info.facilities;
916 call compute_max_nsdu_size;
917 call tty_space_man$free_buffer (devx, INPUT, blockp);
918
919 process_id = ""b;
920 event = 0;
921 if length (channel.call_data) = 0
922 then protocol_id = layer3_ISO;
923 else do protocol_id = lbound (protocol_data.listeners, 1) to hbound (protocol_data.listeners, 1)
924 while (channel.call_data ^= layer3_call_datas (protocol_id));
925 end;
926 ndis_ind_reason.cause = 0;
927 ndis_ind_reason.diag = DIAG_71;
928 if protocol_id > hbound (protocol_data.listeners, 1)
929 then do;
930 n = hbound (protocol_data.special_listeners, 1);
931 stop = "0"b;
932 do i = 1 to n while (^stop);
933 m = length (protocol_data.special_listeners (i).datas);
934 if protocol_data.special_listeners (i).call_datas.partial & length (channel.call_data) >= m
935 then if substr (channel.call_data, 1, m) = protocol_data.special_listeners (i).call_datas.datas
936 then stop = "1"b;
937 if ^protocol_data.special_listeners (i).call_datas.partial
938 & channel.call_data = protocol_data.special_listeners (i).call_datas.datas
939 then stop = "1"b;
940 end;
941 if stop
942 then do;
943 i = i - 1;
944 process_id = protocol_data.special_listeners (i).proc_id;
945 event = protocol_data.special_listeners (i).event_id;
946 end;
947 end;
948 else do;
949 process_id = protocol_data.listeners (protocol_id).proc_id;
950 event = protocol_data.listeners (protocol_id).event_id;
951 end;
952 if process_id ^= ""b
953 then do;
954 protocol_msg.ev_devx = devx;
955 protocol_msg.ev_type = NCONIND;
956 protocol_msg.ev_user_index = 0;
957 protocol_msg.infos = ""b;
958 call pxss$ring_0_wakeup (process_id, event, protocol_event_message, pxss_status);
959 if bad_pxss_status ()
960 then call channel_manager$control (devx, "hangup", addr (ndis_ind_reason), ignore_code);
961 else do;
962 channel.state = DIALING;
963 channel.flags.in_use = "1"b;
964 channel.listener_proc_id = process_id;
965 channel.listener_event = event;
966 end;
967 end;
968 else call channel_manager$control (devx, "hangup", addr (ndis_ind_reason), ignore_code);
969 end;
970 else if int_type = USER_INTERRUPT
971 then do;
972 if channel.state = DIALING
973 then do;
974 unspec (dialup_info) = unspec (interrupt_info);
975 channel.buffer_pad = dialup_info.buffer_pad;
976 channel.max_buf_size = dialup_info.max_buf_size;
977 call compute_max_nsdu_size;
978 protocol_msg.ev_devx = devx;
979 protocol_msg.ev_type = NCONCONF;
980 protocol_msg.ev_user_index = channel.user_ref;
981 channel.state = DIALED;
982 channel.rflag = "1"b;
983 call pxss$ring_0_wakeup (channel.user_proc_id, channel.user_event, protocol_event_message,
984 pxss_status);
985 if pxss_status = WAKEUP_CODE_0 | pxss_status = WAKEUP_CODE_5 | pxss_status = WAKEUP_CODE_100
986 then call channel_manager$control (devx, "hangup", null (), ignore_code);
987 end;
988 else call syserr (Log_message, "protocol_mpx: bad CON_CONF received in state ^d on devx ^d", channel.state,
989 devx);
990 end;
991
992 else if int_type = HANGUP | int_type = CRASH | int_type = DIAL_STATUS
993
994 then do;
995 if channel.state = HUNGUP
996 then ;
997 else do;
998 unspec (protocol_msg.infos) = substr (interrupt_info, 37, 18);
999 protocol_msg.ev_devx = devx;
1000 protocol_msg.ev_type = NDISIND;
1001 protocol_msg.ev_user_index = channel.user_ref;
1002 channel.state = HUNGUP;
1003 call pxss$ring_0_wakeup (channel.user_proc_id, channel.user_event, protocol_event_message,
1004 pxss_status);
1005 if channel.listener_proc_id ^= ""b
1006 then do;
1007 call pxss$ring_0_wakeup (channel.listener_proc_id, channel.listener_event,
1008 protocol_event_message, pxss_status);
1009 if bad_pxss_status ()
1010 then ;
1011 end;
1012 call reset_channel;
1013 end;
1014 if channel.flags.started & ^channel.flags.timer_set
1015
1016 then do;
1017 call mcs_timer$set (devx, 0, clock () + MILLISECONDS_2, ""b);
1018
1019 channel.flags.timer_set = "1"b;
1020 end;
1021 end;
1022
1023 else if int_type = SEND_OUTPUT & channel.state > HUNGUP
1024
1025 then do;
1026 channel.flags.send_output = "1"b;
1027 if channel.write_first ^= 0
1028 then call send_next_nsdu;
1029
1030 if channel.write_first = 0 |
1031 channel.flags.send_output
1032 then if channel.wflag
1033 then do;
1034 protocol_msg.ev_devx = devx;
1035 protocol_msg.ev_type = NDTRDYIND;
1036 protocol_msg.ev_user_index = channel.user_ref;
1037 call pxss$ring_0_wakeup (channel.user_proc_id, channel.user_event, protocol_event_message,
1038 pxss_status);
1039 if pxss_status = WAKEUP_CODE_0 | pxss_status = WAKEUP_CODE_5 | pxss_status = WAKEUP_CODE_100
1040 then call channel_manager$control (devx, "hangup", null (), ignore_code);
1041 channel.wflag = "0"b;
1042 end;
1043 end;
1044
1045 else if int_type = ACCEPT_INPUT
1046 then do;
1047 unspec (rtx_info) = interrupt_info;
1048 inchain = bin (rtx_info.chain_head);
1049 if inchain = 0
1050 then return;
1051
1052 last_offset = bin (rtx_info.chain_tail);
1053 if channel.fblock = 0
1054 then do;
1055 channel.fblock = inchain;
1056 end;
1057 else do;
1058 old_tailp = ptr (ttybp, channel.lblock);
1059 next_offset = bin (rtx_info.chain_head);
1060 if ^old_tailp -> buffer.flags.break
1061 then do;
1062
1063 old_last_tally = old_tailp -> buffer.tally;
1064
1065 max_tally = max_buffer_tally (old_tailp -> buffer.size_code);
1066
1067 filled = "0"b;
1068 do while ((next_offset ^= 0) & ^filled);
1069
1070 new_headp = ptr (ttybp, next_offset);
1071 new_first_tally = new_headp -> buffer.tally;
1072
1073 if (old_last_tally + new_first_tally <= max_tally)
1074 then do;
1075 source_ptr = addr (new_headp -> buffer.chars (0));
1076 target_ptr = addr (old_tailp -> buffer.chars (old_last_tally));
1077 target_ptr -> new_chars = source_ptr -> new_chars;
1078 old_last_tally = old_last_tally + new_first_tally;
1079 old_tailp -> buffer.flags.break = new_headp -> buffer.flags.break;
1080 if new_headp -> buffer.flags.break
1081 then filled = "1"b;
1082 next_offset = new_headp -> buffer.next;
1083
1084 call tty_space_man$free_buffer (devx, INPUT, new_headp);
1085
1086 end;
1087
1088 else filled = "1"b;
1089 end;
1090
1091 old_tailp -> buffer.tally = old_last_tally;
1092 end;
1093 old_tailp -> buffer.next = next_offset;
1094 if next_offset = 0
1095 then last_offset = 0;
1096 end;
1097
1098 if last_offset ^= 0
1099 then channel.lblock = last_offset;
1100 if rtx_info.break_char & channel.flags.rflag
1101 then do;
1102 protocol_msg.ev_devx = devx;
1103 protocol_msg.ev_type = NDTIND;
1104 protocol_msg.ev_user_index = channel.user_ref;
1105 call pxss$ring_0_wakeup (channel.user_proc_id, channel.user_event, protocol_event_message,
1106 pxss_status);
1107 if pxss_status = WAKEUP_CODE_0 | pxss_status = WAKEUP_CODE_5 | pxss_status = WAKEUP_CODE_100
1108 then call channel_manager$control (devx, "hangup", null (), ignore_code);
1109 channel.rflag = "0"b;
1110 end;
1111 end;
1112
1113 else if int_type = LINE_STATUS
1114 then do;
1115 if channel.user_proc_id ^= "0"b
1116 then do;
1117 protocol_msg.ev_devx = devx;
1118 protocol_msg.ev_type = NRESETIND;
1119 protocol_msg.ev_user_index = channel.user_ref;
1120 call pxss$ring_0_wakeup (channel.user_proc_id, channel.user_event, protocol_event_message,
1121 pxss_status);
1122 if pxss_status = WAKEUP_CODE_0 | pxss_status = WAKEUP_CODE_5 | pxss_status = WAKEUP_CODE_100
1123 then call channel_manager$control (devx, "hangup", null (), ignore_code);
1124 end;
1125
1126 return;
1127
1128 end;
1129
1130 else if int_type = TIMER
1131 then do;
1132 channel.flags.timer_set = "0"b;
1133 if channel.flags.started & channel.state = HUNGUP
1134 then call channel_manager$control (devx, "listen", null (), ignore_code);
1135 end;
1136
1137 else if int_type = SPACE_AVAILABLE
1138 then do;
1139 if channel.write_first ^= 0
1140 then call send_next_nsdu;
1141 if channel.write_first = 0 | channel.send_output
1142 then do;
1143 protocol_msg.ev_devx = devx;
1144 protocol_msg.ev_type = NDTRDYIND;
1145 protocol_msg.ev_user_index = channel.user_ref;
1146 call pxss$unique_ring_0_wakeup (channel.user_proc_id, channel.user_event, protocol_event_message,
1147 pxss_status);
1148 if pxss_status = WAKEUP_CODE_0 | pxss_status = WAKEUP_CODE_5 | pxss_status = WAKEUP_CODE_100
1149 then call channel_manager$control (devx, "hangup", null (), ignore_code);
1150 end;
1151 end;
1152
1153 else
1154 bad_int:
1155 call syserr (Log_message, "protocol_mpx: unexpected interrupt type (^d) for devx ^d in state ^d", int_type,
1156 devx, channel.state);
1157
1158 return;
1159 %page;
1160 setup:
1161 proc;
1162
1163 devx = twx;
1164 ttybp = addr (tty_buf$);
1165 lctp = tty_buf.lct_ptr;
1166 lcntp = lct.lcnt_ptr;
1167 infop = addr (dn355_data$);
1168 protocol_data_ptr = datanet_info.protocol_datap;
1169 if devx < 1 | devx > lct.max_no_lctes
1170 then do;
1171 code = error_table_$invalid_device;
1172 goto unlock;
1173 end;
1174
1175 call tty_lock$lock_channel (devx, code);
1176 if code ^= 0
1177 then goto unlock;
1178 locked = "1"b;
1179
1180 lctep = addr (lct.lcte_array (devx));
1181 if lcte.channel_type ^= PROTOCOL_MPX
1182 then goto illdet;
1183
1184 channel_ptr = lcte.data_base_ptr;
1185 if channel.user_proc_id ^= ""b & channel.listener_proc_id ^= pds$processid
1186 & channel.user_proc_id ^= pds$processid
1187 then goto illdet;
1188 return;
1189 end setup;
1190
1191 illdet:
1192 code = error_table_$io_no_permission;
1193 unlock:
1194 a_code = code;
1195 call cleaner;
1196 return;
1197 %page;
1198 get_channel:
1199 proc (addr) returns (fixed bin);
1200
1201 dcl addr char (15) varying,
1202 i fixed bin;
1203
1204 do i = protocol_data.max_channels to 1 by -1
1205 while (protocol_data.channels (i).flags.in_use | ^protocol_data.channels (i).flags.started
1206 | (protocol_data.channels (i).our_network_address ^= addr & addr ^= ""));
1207 end;
1208 return (i);
1209 end get_channel;
1210
1211
1212 check_length:
1213 proc (break_flag, length);
1214
1215
1216
1217
1218 dcl break_flag bit (1);
1219 dcl length fixed bin;
1220 dcl stop bit (1);
1221
1222 length = 0;
1223 stop, break_flag = "0"b;
1224 do blockp = blockp repeat (ptr (blockp, buffer.next)) while (^stop);
1225 if buffer.break
1226 then break_flag = "1"b;
1227 if buffer.next = 0 | break_flag
1228 then stop = "1"b;
1229 length = length + buffer.tally;
1230 end;
1231 end check_length;
1232
1233
1234 copy_chars:
1235 proc (source_ptr, source_offset, n_chars_to_copy, target_ptr, a_target_offset);
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246 dcl (source_ptr, target_ptr)
1247 ptr;
1248 dcl (a_target_offset, n_chars_to_copy)
1249 fixed bin;
1250 dcl source_offset fixed bin (21);
1251 dcl (n, nctc, target_offset)
1252 fixed bin;
1253 dcl n_chars_in_source_buffer
1254 fixed bin;
1255 dcl source_chars char (n) based (addr (source_ptr -> buffer.chars (source_offset)));
1256 dcl target_chars char (n) based (addr (target_ptr -> buffer.chars (target_offset)));
1257
1258 target_offset = a_target_offset;
1259
1260 do nctc = n_chars_to_copy repeat (nctc - n) while (nctc > 0);
1261 n_chars_in_source_buffer = source_ptr -> buffer.tally - source_offset;
1262 if n_chars_in_source_buffer > nctc
1263 then do;
1264 n = nctc;
1265 target_chars = source_chars;
1266 source_offset = source_offset + n;
1267 end;
1268 else if n_chars_in_source_buffer < nctc
1269 then do;
1270 n = n_chars_in_source_buffer;
1271 target_chars = source_chars;
1272 if source_ptr -> buffer.next = 0
1273 then source_ptr = null;
1274 else source_ptr = ptr (source_ptr, source_ptr -> buffer.next);
1275 source_offset = 0;
1276 end;
1277 else do;
1278 n = nctc;
1279 target_chars = source_chars;
1280 if source_ptr -> buffer.next = 0
1281 then source_ptr = null;
1282 else source_ptr = ptr (source_ptr, source_ptr -> buffer.next);
1283 source_offset = 0;
1284 end;
1285 target_offset = target_offset + n;
1286 end;
1287 end copy_chars;
1288
1289
1290
1291 reset_channel:
1292 proc;
1293
1294
1295 if channel.fblock ^= 0
1296 then call tty_space_man$free_chain (devx, INPUT, ptr (ttybp, channel.fblock));
1297
1298 if channel.write_first ^= 0
1299 then call tty_space_man$free_chain (devx, OUTPUT, ptr (ttybp, channel.write_first));
1300
1301 channel.flags.in_use, channel.flags.send_output, channel.flags.wflag, channel.flags.rflag = "0"b;
1302
1303 channel.fblock, channel.lblock = 0;
1304 channel.write_first, channel.write_last = 0;
1305 channel.space_left_in_packet = channel.max_packet_size;
1306 channel.listener_event = 0;
1307 channel.listener_proc_id = ""b;
1308 channel.user_event = 0;
1309 channel.user_proc_id = ""b;
1310 channel.user_ref = 0;
1311 channel.his_network_address = "";
1312 channel.call_data = "";
1313 channel.facilities = "";
1314 channel.max_buf_size = 0;
1315 channel.buffer_pad = 0;
1316 channel.max_nsdu_size = 0;
1317
1318 end reset_channel;
1319
1320 %page;
1321
1322 send_next_nsdu:
1323 proc;
1324
1325 dcl headp ptr;
1326 dcl next_head fixed bin;
1327
1328 if channel.flags.send_output
1329 then do;
1330 headp, blockp = ptr (ttybp, channel.write_first);
1331
1332 do while (buffer.next ^= 0 & ^buffer.flags.break);
1333
1334 blockp = ptr (ttybp, buffer.next);
1335 end;
1336 if ^buffer.flags.break
1337 then return;
1338 next_head = buffer.next;
1339 buffer.next = 0;
1340 call channel_manager$write (devx, headp, code);
1341 if code = noalloc_code
1342 then do;
1343 call tty_space_man$needs_space (devx);
1344 code = 0;
1345 end;
1346
1347
1348 if headp ^= null
1349 then do;
1350 if code = 0
1351 then do;
1352 blockp = headp;
1353 do while (buffer.next ^= 0);
1354 blockp = ptr (ttybp, buffer.next);
1355 end;
1356
1357 buffer.next = next_head;
1358 if next_head = 0
1359 then channel.write_last = bin (rel (blockp));
1360
1361 next_head = bin (rel (headp));
1362 end;
1363
1364 else do;
1365 call tty_space_man$free_chain (devx, OUTPUT, headp);
1366
1367 protocol_msg.ev_devx = devx;
1368 protocol_msg.ev_type = NRESETIND;
1369 call pxss$unique_ring_0_wakeup (channel.user_proc_id, channel.user_event, protocol_event_message,
1370 (0));
1371 end;
1372 end;
1373
1374 channel.write_first = next_head;
1375 if channel.write_first = 0
1376 then channel.write_last = 0;
1377 else if code ^= 0
1378 then do;
1379 call tty_space_man$free_chain (devx, OUTPUT, ptr (ttybp, channel.write_first));
1380 channel.write_first, channel.write_last = 0;
1381 end;
1382 channel.flags.send_output = "0"b;
1383 end;
1384
1385 return;
1386 end send_next_nsdu;
1387
1388 set_static:
1389 proc;
1390
1391
1392
1393 noalloc_code = error_table_$noalloc;
1394 no_write_code = error_table_$invalid_write;
1395 call wire_proc$wire_me;
1396 end set_static;
1397
1398
1399 cleaner:
1400 proc;
1401
1402 if locked
1403 then do;
1404 call tty_lock$unlock_channel (devx);
1405 locked = "0"b;
1406 end;
1407
1408 end cleaner;
1409
1410
1411 bad_pxss_status:
1412 proc returns (bit (1));
1413
1414 if pxss_status = WAKEUP_CODE_0 | pxss_status = WAKEUP_CODE_5 | pxss_status = WAKEUP_CODE_100
1415 then do;
1416 call syserr (Log_message,
1417 "protocol_mpx: Error ^d waking up listening process for channel ^a, it has probably crashed!",
1418 pxss_status, channel.name);
1419 return ("1"b);
1420 end;
1421 else return ("0"b);
1422 end bad_pxss_status;
1423
1424
1425
1426
1427
1428
1429 check_orphan_connections:
1430 proc;
1431
1432 do i = 1 to protocol_data.max_channels;
1433 channel_ptr = addr (protocol_data.channels (i));
1434 if channel.state > DIALING
1435 then do;
1436 call tc_util$validate_processid (channel.user_proc_id, code);
1437 if code ^= 0
1438 then do;
1439 call syserr (Log_message, "protocol_mpx: orphan channel found, ^a. Hanging it up...",
1440 channel.name);
1441 ndis_ind_reason.cause = 0;
1442 ndis_ind_reason.diag = DIAG_71;
1443 call tty_lock$lock_channel (channel.devx, code);
1444 if code = 0
1445 then do;
1446 call channel_manager$control (channel.devx, "hangup", addr (ndis_ind_reason), code);
1447 call tty_lock$unlock_channel (channel.devx);
1448 end;
1449 end;
1450 end;
1451 end;
1452 end check_orphan_connections;
1453
1454
1455 copy_from_user_to_us:
1456 proc (source_index, source_offset, n_chars_to_copy, target_ptr, a_target_offset);
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467 dcl (target_ptr, source_chars_p)
1468 ptr;
1469 dcl source_offset fixed bin (21);
1470 dcl (source_index, a_target_offset, n_chars_to_copy)
1471 fixed bin;
1472 dcl (n, nctc, target_offset)
1473 fixed bin;
1474 dcl n_chars_in_source_buffer
1475 fixed bin (21);
1476 dcl total_string char (transmit_info (source_index).size) based (transmit_info (source_index).data_ptr);
1477 dcl source_chars char (n) based (source_chars_p);
1478 dcl target_chars char (n) based (addr (target_ptr -> buffer.chars (target_offset)));
1479
1480 target_offset = a_target_offset;
1481
1482 do nctc = n_chars_to_copy repeat (nctc - n) while (nctc > 0);
1483 source_chars_p = addr (substr (total_string, source_offset + 1, 1));
1484 n_chars_in_source_buffer = transmit_info (source_index).size - source_offset;
1485 if n_chars_in_source_buffer > nctc
1486 then do;
1487 n = nctc;
1488 target_chars = source_chars;
1489 source_offset = source_offset + n;
1490 end;
1491 else if n_chars_in_source_buffer < nctc
1492 then do;
1493 n = n_chars_in_source_buffer;
1494 target_chars = source_chars;
1495 if source_index = transmit_info.n_entries
1496 then source_index = 0;
1497 else source_index = source_index + 1;
1498 source_offset = 0;
1499 end;
1500 else do;
1501 n = nctc;
1502 target_chars = source_chars;
1503 if source_index = transmit_info.n_entries
1504 then source_index = 0;
1505 else source_index = source_index + 1;
1506 source_offset = 0;
1507 end;
1508 target_offset = target_offset + n;
1509 end;
1510 end copy_from_user_to_us;
1511
1512
1513 copy_from_us_to_user:
1514 proc (source_ptr, source_offset, n_chars_to_copy, target_index, a_target_offset);
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526 dcl (source_ptr, user_chars_p)
1527 ptr;
1528 dcl (source_offset, a_target_offset, target_offset)
1529 fixed bin (21);
1530 dcl (target_index, n_chars_to_copy)
1531 fixed bin;
1532 dcl (n, nctc) fixed bin;
1533 dcl n_chars_in_source_buffer
1534 fixed bin;
1535 dcl source_chars char (n) based (addr (source_ptr -> buffer.chars (source_offset)));
1536 dcl total_string char (transmit_info (target_index).size) based (transmit_info (target_index).data_ptr);
1537 dcl target_chars char (n) based (user_chars_p);
1538
1539 target_offset = a_target_offset;
1540
1541 do nctc = n_chars_to_copy repeat (nctc - n) while (nctc > 0);
1542 user_chars_p = addr (substr (total_string, target_offset + 1, 1));
1543 n_chars_in_source_buffer = source_ptr -> buffer.tally - source_offset;
1544 if n_chars_in_source_buffer > nctc
1545 then do;
1546 n = nctc;
1547 target_chars = source_chars;
1548 source_offset = source_offset + n;
1549 end;
1550 else if n_chars_in_source_buffer < nctc
1551 then do;
1552 n = n_chars_in_source_buffer;
1553 target_chars = source_chars;
1554 if source_ptr -> buffer.next = 0
1555 then source_ptr = null ();
1556 else source_ptr = ptr (source_ptr, source_ptr -> buffer.next);
1557 source_offset = 0;
1558 end;
1559 else do;
1560 n = nctc;
1561 target_chars = source_chars;
1562 if source_ptr -> buffer.next = 0
1563 then source_ptr = null ();
1564 else source_ptr = ptr (source_ptr, source_ptr -> buffer.next);
1565 source_offset = 0;
1566 end;
1567 target_offset = target_offset + n;
1568 end;
1569 end copy_from_us_to_user;
1570
1571 compute_max_nsdu_size:
1572 proc;
1573
1574 dcl i fixed bin;
1575
1576 max_chars_in_buf = SIZE4 * (channel.max_buf_size - 1) - channel.buffer_pad;
1577 i = ceil (channel.max_packet_size / max_chars_in_buf);
1578
1579 channel.max_nsdu_size = min (LONGEST_POSSIBLE_STRING, (max_chain_len / i) * channel.max_packet_size);
1580 end compute_max_nsdu_size;
1581
1582 %page;
1583 %include protocol_data;
1584 %page;
1585 %include protocol_infos;
1586 %page;
1587 %include protocols;
1588 %page;
1589 %include multiplexer_types;
1590 %page;
1591 %include tty_buf;
1592 %page;
1593 %include tty_buffer_block;
1594 %page;
1595 %include tty_space_man_dcls;
1596 %page;
1597 %include lct;
1598 %page;
1599 %include channel_manager_dcls;
1600 %page;
1601 %include mcs_interrupt_info;
1602 %page;
1603 %include line_types;
1604 %page;
1605 %include syserr_codes;
1606 %page;
1607 %include response_transitions;
1608 %page;
1609 %include mcs_timer_dcls;
1610 %page;
1611 %include dn355_data;
1612
1613 end protocol_mpx;