1
2
3
4
5
6
7
8
9
10
11
12
13
14 channel_manager:
15 procedure;
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 dcl pm_devx fixed bin;
34 dcl pm_info_ptr ptr;
35 dcl pm_chain_ptr ptr;
36 dcl pm_more_input_flag bit (1) aligned;
37 dcl pm_control_type char (*);
38 dcl pm_modes_change_list_ptr ptr;
39 dcl pm_modes char (*);
40 dcl pm_int_type fixed bin;
41 dcl pm_int_data bit (72) aligned;
42 dcl pm_code fixed bin (35);
43
44
45
46
47 dcl queued_entry bit (1) aligned;
48 dcl int_type fixed bin;
49 dcl devx fixed bin;
50 dcl subchan fixed bin;
51 dcl locked bit (1) aligned;
52 dcl minor_lctep ptr;
53 dcl time_in fixed bin (71);
54
55
56
57
58 dcl 1 minor_lcte aligned like lcte based (minor_lctep);
59
60
61
62
63 dcl cleanup condition;
64
65
66
67
68 dcl crash_system fixed bin int static options (constant) init (1);
69 dcl int_type_names (17) char (16) aligned static options (constant)
70 init ("dialup", "hangup", "crash", "send_output", "input_available", "accept_input", "input_rejected", "quit",
71 "line_status", "dial_status", "wru_timeout", "space_available", "ack_echnego_init", "ack_echnego_stop", "timer",
72 "user", "masked");
73
74
75
76 dcl pds$process_id bit (36) ext;
77 dcl pds$virtual_delta fixed bin (71) ext;
78
79
80
81
82 dcl (addr, clock, null, pointer, rel, unspec) builtin;
83
84
85
86
87 dcl mcs_trace entry options (variable);
88 dcl mcs_trace$buffer_chain entry (fixed bin, pointer);
89 dcl tty_lock$lock_channel entry (fixed bin, fixed bin (35));
90 dcl tty_lock$unlock_channel entry (fixed bin);
91 dcl tty_lock$lock_channel_int entry (fixed bin, fixed bin, bit (72) aligned, bit (1) aligned);
92 dcl tty_lock$unlock_channel_int entry (fixed bin);
93 dcl tty_lock$queue_interrupt entry (fixed bin, fixed bin, bit (72) aligned, fixed bin);
94 dcl syserr entry options (variable);
95 %page;
96
97
98 read:
99 entry (pm_devx, pm_chain_ptr, pm_more_input_flag, pm_code);
100
101 call setup_major (subchan);
102
103 if tty_buf.trace.enable
104 then if tty_buf.trace.read
105 then call mcs_trace (pm_devx, "read");
106
107 on cleanup call unlock_channel ();
108 call lock_channel ();
109 read_ev = make_entry (READ, (lcte.channel_type));
110 call read_ev ((lcte.data_base_ptr), subchan, pm_chain_ptr, pm_more_input_flag, pm_code);
111 if pm_code = 0
112 then if pm_chain_ptr ^= null ()
113 then do blockp = pm_chain_ptr
114 repeat (pointer (ttybp, buffer.next)) while (rel (blockp) ^= ""b);
115 minor_lcte.meters.in_bytes = minor_lcte.meters.in_bytes + buffer.tally;
116 end;
117 call unlock_channel ();
118
119 if tty_buf.trace.enable
120 then if tty_buf.trace.read
121 then do;
122 call mcs_trace (pm_devx, "read: ^[code ^d ^;^s^]^[chain at ^p ^;^s^]^[more_input^]", (pm_code ^= 0),
123 pm_code, (pm_chain_ptr ^= null ()), pm_chain_ptr, pm_more_input_flag);
124 if tty_buf.trace.data
125 then call mcs_trace$buffer_chain (pm_devx, pm_chain_ptr);
126 end;
127
128 call meter_call (minor_lcte.meters.in);
129 return;
130
131
132
133 write:
134 entry (pm_devx, pm_chain_ptr, pm_code);
135
136 call setup_major (subchan);
137
138 if tty_buf.trace.enable
139 then if tty_buf.trace.write
140 then do;
141 call mcs_trace (pm_devx, "write: ^p: ^d bytes ^[etc.^]", pm_chain_ptr, pm_chain_ptr -> buffer.tally,
142 (pm_chain_ptr -> buffer.next ^= 0));
143 if tty_buf.trace.data
144 then call mcs_trace$buffer_chain (pm_devx, pm_chain_ptr);
145 end;
146
147 on cleanup call unlock_channel ();
148 call lock_channel ();
149 do blockp = pm_chain_ptr
150 repeat (pointer (ttybp, buffer.next)) while (rel (blockp) ^= ""b);
151 minor_lcte.meters.out_bytes = minor_lcte.meters.out_bytes + buffer.tally;
152 end;
153 write_ev = make_entry (WRITE, (lcte.channel_type));
154 call write_ev ((lcte.data_base_ptr), subchan, pm_chain_ptr, pm_code);
155
156 if pm_chain_ptr ^= null ()
157 then do blockp = pm_chain_ptr
158 repeat (pointer (ttybp, buffer.next)) while (rel (blockp) ^= ""b);
159 minor_lcte.meters.out_bytes = minor_lcte.meters.out_bytes - buffer.tally;
160 end;
161
162 call unlock_channel ();
163
164 if tty_buf.trace.enable
165 then if tty_buf.trace.write
166 then if (pm_chain_ptr ^= null ()) | (pm_code ^= 0)
167 then call mcs_trace (pm_devx, "write: ^[code ^d ^;^s^]chain left at ^p", pm_code, pm_chain_ptr);
168
169 call meter_call (minor_lcte.meters.out);
170 return;
171
172
173
174 control:
175 entry (pm_devx, pm_control_type, pm_info_ptr, pm_code);
176
177 call setup_major (subchan);
178
179 if tty_buf.trace.enable
180 then if tty_buf.trace.control
181 then call mcs_trace (pm_devx, "control: ^a ^p", pm_control_type, pm_info_ptr);
182
183 on cleanup call unlock_channel ();
184 call lock_channel ();
185 control_ev = make_entry (CONTROL, (lcte.channel_type));
186 call control_ev ((lcte.data_base_ptr), subchan, pm_control_type, pm_info_ptr, pm_code);
187 call unlock_channel ();
188
189 call meter_call (minor_lcte.meters.control);
190 if pm_control_type = "copy_meters"
191 then minor_lcte.saved_meters_ptr -> saved_meters = minor_lcte.meters;
192
193 else if pm_control_type = "get_meters"
194 then call get_lc_meters;
195
196 return;
197
198
199
200 set_modes:
201 entry (pm_devx, pm_modes_change_list_ptr, pm_code);
202
203 call setup_major (subchan);
204
205 if tty_buf.trace.enable
206 then if tty_buf.trace.modes
207 then call mcs_trace (pm_devx, "set_modes: ^p", pm_modes_change_list_ptr);
208
209 on cleanup call unlock_channel ();
210 call lock_channel ();
211 set_modes_ev = make_entry (SET_MODES, (lcte.channel_type));
212 call set_modes_ev ((lcte.data_base_ptr), subchan, pm_modes_change_list_ptr, pm_code);
213 call unlock_channel ();
214
215 call meter_call (minor_lcte.meters.control);
216 return;
217
218
219
220 check_modes:
221 entry (pm_devx, pm_modes_change_list_ptr, pm_code);
222
223 call setup_major (subchan);
224
225 if tty_buf.trace.enable
226 then if tty_buf.trace.modes
227 then call mcs_trace (pm_devx, "check_modes: ^p", pm_modes_change_list_ptr);
228
229 on cleanup call unlock_channel ();
230 call lock_channel ();
231 check_modes_ev = make_entry (CHECK_MODES, (lcte.channel_type));
232 call check_modes_ev ((lcte.data_base_ptr), subchan, pm_modes_change_list_ptr, pm_code);
233 call unlock_channel ();
234
235 call meter_call (minor_lcte.meters.control);
236 return;
237
238
239
240 get_modes:
241 entry (pm_devx, pm_modes, pm_code);
242
243 call setup_major (subchan);
244
245 if tty_buf.trace.enable
246 then if tty_buf.trace.modes
247 then call mcs_trace (pm_devx, "get_modes");
248
249 on cleanup call unlock_channel ();
250 call lock_channel ();
251 get_modes_ev = make_entry (GET_MODES, (lcte.channel_type));
252 call get_modes_ev ((lcte.data_base_ptr), subchan, pm_modes, pm_code);
253 call unlock_channel ();
254
255 call meter_call (minor_lcte.meters.control);
256 return;
257
258
259
260 interrupt:
261 entry (pm_devx, pm_int_type, pm_int_data);
262
263 queued_entry = "0"b;
264
265
266 interrupt_common:
267 int_type = pm_int_type;
268
269 call setup ();
270
271 on cleanup call syserr (crash_system, "channel_manager: Cleanup while processing interrupt for devx ^d.", devx);
272 if ^queued_entry
273 then do;
274 call tty_lock$lock_channel_int (devx, int_type, pm_int_data, locked);
275 if ^locked
276 then do;
277 if tty_buf.trace.enable
278 then if tty_buf.trace.interrupt
279 then call mcs_trace (devx, "int: queued ^a ^24.3b", int_type_names (int_type), pm_int_data);
280 return;
281 end;
282 end;
283
284 if tty_buf.trace.enable
285 then if tty_buf.trace.interrupt
286 then do;
287 call mcs_trace (devx, "int: proc ^[queued ^]^a ^24.3b", queued_entry, int_type_names (int_type),
288 pm_int_data);
289 if int_type = ACCEPT_INPUT
290 then if tty_buf.trace.data
291 then do;
292 unspec (rtx_info) = pm_int_data;
293 call mcs_trace$buffer_chain (devx, pointer (ttybp, rtx_info.chain_head));
294 end;
295 end;
296
297 interrupt_ev = make_entry (INTERRUPT, (lcte.channel_type));
298 call interrupt_ev ((lcte.data_base_ptr), int_type, pm_int_data);
299
300 if ^queued_entry
301 then call tty_lock$unlock_channel_int (devx);
302
303 if int_type = ACCEPT_INPUT
304 then do;
305 unspec (rtx_info) = pm_int_data;
306 lcte.meters.in_bytes = lcte.meters.in_bytes + rtx_info.input_count;
307 call meter_interrupt (lcte.meters.in);
308 end;
309 else if int_type = SEND_OUTPUT
310 then do;
311 call meter_interrupt (lcte.meters.out);
312 end;
313 else call meter_interrupt (lcte.meters.control);
314
315 return;
316
317
318
319 queued_interrupt:
320 entry (pm_devx, pm_int_type, pm_int_data);
321
322 queued_entry = "1"b;
323 go to interrupt_common;
324
325
326
327 interrupt_later:
328 entry (pm_devx, pm_int_type, pm_int_data);
329
330
331
332
333 int_type = pm_int_type;
334
335 call setup ();
336
337 if tty_buf.trace.enable
338 then if tty_buf.trace.interrupt
339 then call mcs_trace (devx, "int: queued ^a ^24.3b", int_type_names (int_type), pm_int_data);
340
341 on cleanup call syserr (crash_system, "channel_manager: Cleanup while queuing interrupt for devx ^d.", devx);
342
343 call tty_lock$queue_interrupt ((lcte.major_channel_devx), int_type, pm_int_data, devx);
344 return;
345 ^L
346
347
348 setup:
349 proc;
350
351 locked = "0"b;
352 ttybp = addr (tty_buf$);
353 lctp = tty_buf.lct_ptr;
354
355 time_in = clock () - pds$virtual_delta;
356
357 devx = pm_devx;
358 if devx < 1 | devx > lct.max_no_lctes
359 then call syserr (crash_system, "channel_manager: Invalid devx specified. ^o", devx);
360
361 lctep = addr (lct.lcte_array (devx));
362
363 cmtvp = addr (cmtv$cmtv);
364
365 end setup;
366
367
368
369 setup_major:
370 proc (subchan);
371
372 dcl subchan fixed bin;
373
374
375 call setup ();
376 minor_lctep = lctep;
377 if lcte.lock ^= pds$process_id
378 then call syserr (crash_system, "channel_manager: Channel not locked by process. (devx = ^o)", devx);
379 subchan = lcte.subchannel;
380
381 devx = lcte.major_channel_devx;
382 lctep = addr (lct.lcte_array (devx));
383
384 end setup_major;
385 ^L
386
387
388 meter_call:
389 procedure (Meters);
390 dcl 1 Meters aligned like lcte.meters.in;
391
392 Meters.calls = Meters.calls + 1;
393 Meters.call_time = Meters.call_time + clock () - pds$virtual_delta - time_in;
394 return;
395
396
397
398 meter_interrupt:
399 entry (Meters);
400
401 Meters.interrupts = Meters.interrupts + 1;
402 Meters.interrupt_time = Meters.interrupt_time + clock () - pds$virtual_delta - time_in;
403 return;
404 end meter_call;
405 ^L
406
407
408 get_lc_meters:
409 proc;
410
411
412
413 dcl lcmp ptr;
414 dcl info_ptr ptr;
415
416 info_ptr = pm_info_ptr;
417 info_ptr -> get_comm_meters_info.parent_type = lcte.channel_type;
418 lcmp = info_ptr -> get_comm_meters_info.logical_chan_ptr;
419 lcmp -> logical_chan_meters.current_meters = minor_lcte.meters;
420 lcmp -> logical_chan_meters.saved_meters = minor_lcte.saved_meters_ptr -> saved_meters;
421 return;
422 end get_lc_meters;
423 ^L
424
425
426 make_entry:
427 proc (entry_type, chan_type) returns (entry variable);
428
429 dcl entry_type fixed bin;
430 dcl chan_type fixed bin;
431
432 dcl code_ptr ptr;
433 dcl code_word fixed bin based (code_ptr);
434
435 dcl new_entry entry variable;
436 dcl 1 entry_var aligned,
437 2 code_ptr ptr,
438 2 env_ptr ptr;
439
440
441 code_ptr = addr (cmtv.entries (entry_type, cmtv.chan_type_index (chan_type)));
442 if code_word = 0
443 then new_entry = undefined_entry;
444 else do;
445 entry_var.code_ptr = code_ptr;
446 entry_var.env_ptr = null;
447 unspec (new_entry) = unspec (entry_var);
448 end;
449 return (new_entry);
450 end make_entry;
451
452 undefined_entry:
453 procedure;
454 return;
455 end undefined_entry;
456 ^L
457
458
459 lock_channel:
460 proc;
461
462 dcl code fixed bin (35);
463
464
465 if lcte.special_lock
466 then return;
467
468 call tty_lock$lock_channel (devx, code);
469 if code ^= 0
470 then call syserr (crash_system, "channel_manager: Cannot lock channel for devx ^o (code = ^o)", devx, code);
471 locked = "1"b;
472
473 end lock_channel;
474
475
476
477 unlock_channel:
478 proc;
479
480 if locked
481 then call tty_lock$unlock_channel (devx);
482 locked = "0"b;
483
484 end unlock_channel;
485 ^L
486 %include lct;
487 ^L
488 %include cmtv;
489 ^L
490 %include tty_buf;
491 ^L
492 %include mcs_interrupt_info;
493 %include tty_buffer_block;
494 %include get_comm_meters_info;
495
496 end;
497 ^L
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523