1
2
3
4
5
6
7
8
9
10
11 ioi_masked:
12 procedure;
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 dcl p_ctep ptr parameter;
64 dcl p_dtep ptr parameter;
65 dcl p_cterp fixed bin (35) parameter;
66 dcl p_level fixed bin (3) parameter;
67 dcl p_status bit (36) aligned parameter;
68 dcl p_subsystem_name char (*) parameter;
69
70 dcl 1 auto_istat like istat aligned;
71 dcl broadcast bit (1) aligned;
72 dcl count fixed bin;
73 dcl done bit (1) aligned;
74 dcl ctx fixed bin;
75 dcl dtx fixed bin;
76 dcl gtx fixed bin;
77 dcl 1 ima aligned like io_manager_arg;
78 dcl level fixed bin (3);
79 dcl message fixed bin (71);
80 dcl status bit (36) aligned;
81 dcl 1 status_entry aligned like io_status_entry;
82 dcl wm_mask fixed bin (71);
83 dcl wm_ptwp ptr;
84
85 dcl ioi_abs_seg$ external;
86 dcl pds$process_id bit (36) aligned external static;
87 dcl sys_info$service_system
88 bit (1) aligned external static;
89
90 dcl absadr entry (ptr, fixed bin (35)) returns (fixed bin (26));
91 dcl bce_ioi_post entry (fixed bin (71), fixed bin (71));
92 dcl ioi_wire$unwire entry (ptr);
93 dcl pmut$swap_sdw entry (ptr, ptr);
94 dcl pmut$unwire_unmask entry (fixed bin (71), ptr);
95 dcl pmut$wire_and_mask entry (fixed bin (71), ptr);
96 dcl pxss$io_wakeup entry (bit (36) aligned, fixed bin (71), fixed bin (71), fixed bin (35));
97 dcl pxss$notify entry (bit (36) aligned);
98 dcl syserr entry options (variable);
99 dcl syserr$binary entry options (variable);
100
101 dcl FIFTEEN_SECONDS fixed bin (71) static options (constant) init (15000000);
102 dcl MAX_LOG_STATUS_COUNT fixed bin (17) static options (constant) init (63);
103 dcl ME char (32) static options (constant) init ("ioi_masked");
104 dcl ONE_MINUTE fixed bin (71) static options (constant) init (60000000);
105
106 dcl (addr, addrel, bin, bit, clock, hbound, lbound, length, null, ptr, rel, size, stac, stacq, string, substr,
107 unspec) builtin;
108 ^L
109
110
111
112
113
114
115 getwork_device:
116 entry (p_dtep);
117
118 dtep = p_dtep;
119 idp = addr (ioi_data$);
120 gtep = ptr (idp, dte.gtep);
121
122 call mask;
123 call lock_gte;
124
125 gte.pending_connects = gte.pending_connects + 1;
126
127 if dte.direct & dte.active
128 then do;
129 ctep = ptr (idp, dte.cur_ctep);
130 call connect;
131 gte.pending_connects = gte.pending_connects - 1;
132 call unlock_gte;
133 call unmask;
134 return;
135 end;
136
137
138
139 dte.active = "1"b;
140
141 if ^dte.suspended then
142 do ctep = ptr (idp, gte.ctep) repeat ptr (idp, cte.next_ctep) while (rel (ctep));
143 if cte.ioi_use & ^cte.deleting & ^cte.deleted & ^cte.connected & ^cte.quiescing
144 & (dte.channel_required = "" | (dte.channel_required = cte.chanid)) then do;
145
146 call connect;
147 gte.pending_connects = gte.pending_connects - 1;
148 call unlock_gte;
149 call unmask;
150 return;
151 end;
152 end;
153
154 call unlock_gte;
155 call unmask;
156 return;
157 ^L
158
159
160
161 getwork_channel:
162 entry (p_ctep);
163
164 ctep = p_ctep;
165 idp = addr (ioi_data$);
166 gtep = ptr (idp, cte.gtep);
167
168 call mask;
169 call lock_gte;
170 dtep = null ();
171 call getwork_channel_proc;
172 call unlock_gte;
173 call unmask;
174 return;
175 ^L
176
177
178 reset_device:
179 entry (p_dtep);
180
181 idp = addr (ioi_data$);
182 dtep = p_dtep;
183 gtep = ptr (dtep, dte.gtep);
184 call mask;
185 call lock_gte;
186 if dte.connected then do;
187 ctep = ptr (dtep, dte.cur_ctep);
188 call mask_channel;
189 end;
190 else if dte.active then do;
191 gte.pending_connects = gte.pending_connects - 1;
192 dte.active = "0"b;
193 end;
194 call unlock_gte;
195 call unmask;
196 return;
197 ^L
198
199
200
201
202
203 timer:
204 entry;
205
206 idp = addr (ioi_data$);
207 if ^ioi_data.setup then
208 return;
209 do ctx = 1 to ioi_data.nct;
210 ctep = addr (ioi_data.ct (ctx));
211 gtep = ptr (idp, cte.gtep);
212 call lock_gte;
213 if cte.ioi_use & ^cte.direct then
214 if cte.connected & (cte.time_limit ^= 0) & (clock () > cte.time_limit) then do;
215 if cte.cur_dtep = ""b then do;
216 dtep = null ();
217 call syserr (ANNOUNCE, "^a$timer: Timeout on channel ^a (no device).", ME, cte.chanid);
218 end;
219 else do;
220 dtep = ptr (ctep, cte.cur_dtep);
221 call syserr (ANNOUNCE, "^a$timer: Timeout on channel ^a (device ^a^[_^[0^]^d^]).", ME,
222 cte.chanid, gte.name, gte.mplex, bin (dte.device) < 10, bin (dte.device));
223 end;
224 call mask_channel;
225 call setup_timeout_status;
226 call getwork_channel_proc;
227 call deliver_status;
228 if dtep ^= null () then
229 call wakeup_user;
230 end;
231 call unlock_gte;
232 end;
233 do dtx = 1 to ioi_data.ndt;
234 dtep = addr (ioi_data.dt (dtx));
235 if dte.in_use & ^dte.direct & dte.process_id ^= ""b then do;
236
237 gtep = ptr (dtep, dte.gtep);
238 call lock_gte;
239 if clock () > dte.last_log_time + ONE_MINUTE then
240 call flush_status_proc;
241 call unlock_gte;
242
243
244 if stac (addr (dte.lock.pid), pds$process_id) then do;
245 if ^dte.active & dte.workspace_wired & (clock () > dte.unwire_time) then do;
246 if dte.workspace_astep ^= null () then
247 call ioi_wire$unwire (dtep);
248 else do;
249 call syserr (ANNOUNCE,
250 "^a$timer: Attempt to unwire NULL workspace. (device ^a^[_^[0^]^d^]).", ME,
251 gte.name, gte.mplex, bin (dte.device) < 10, bin (dte.device));
252 dte.workspace_wired = "0"b;
253 end;
254 end;
255
256
257
258
259 do while (^stacq (dte.lock.pid, "000000000000"b3, pds$process_id));
260 end;
261
262 if dte.lock.notify_sw then do;
263 dte.lock.notify_sw = "0"b;
264 call pxss$notify (dte.lock.event);
265 end;
266
267 end;
268 end;
269 end;
270 return;
271 ^L
272
273
274
275
276 interrupt:
277 entry (p_cterp, p_level, p_status);
278
279 idp = addr (ioi_data$);
280 ctep = ptr (idp, p_cterp);
281 gtep = ptr (idp, cte.gtep);
282 level = p_level;
283 status = p_status;
284
285 if level = IO_SPECIAL_INTERRUPT_LEVEL then do;
286 io_special_status_ptr = addr (status);
287 imp = addr (message);
288 string (imess) = ""b;
289 imess.st = "1"b;
290 imess.level = bit (level, 3);
291 imess.status = status;
292
293 broadcast =
294 ^io_special_status.t | ^gte.mplex
295 | (substr (io_special_status.byte2, 1, 1) & (io_special_status.device = "00"b3));
296
297 do gtx = 1 to ioi_data.ngt;
298 gtep = addr (ioi_data.gt (gtx));
299 if special_could_come_from_channel (gtep, ctep) then do;
300 begin;
301
302 dcl done bit (1) aligned;
303
304 call lock_gte;
305 done = "0"b;
306 do dtep = ptr (idp, gte.dtep) repeat ptr (idp, dte.next_dtep) while (^done);
307 if (dte.process_id ^= ""b) & (broadcast | (dte.device = io_special_status.device))
308 then do;
309 dte.special_status = status;
310 dte.special_interrupt = "1"b;
311 call wakeup_user;
312 end;
313 done = (dte.next_dtep = gte.dtep);
314 end;
315 call unlock_gte;
316 end;
317 end;
318 end;
319 end;
320 else do;
321 call lock_gte;
322 if cte.direct then
323 unspec (status_entry) = ""b;
324 else call io_manager$get_status (cte.chx, addr (status_entry));
325 if cte.toss_status | (cte.cur_dtep = ""b) then do;
326 cte.toss_status = "0"b;
327 cte.connected = "0"b;
328 dtep = null ();
329 call getwork_channel_proc;
330 call unlock_gte;
331 goto DISMISS_INTERRUPT;
332 end;
333
334 dtep = ptr (idp, cte.cur_dtep);
335 if ^dte.active then do;
336 call syserr (CRASH,
337 "^a$interrupt: Interrupt for inactive device (device ^a^[_^[0^]^d^]).^/Type go to continue.", ME,
338 gte.name, gte.mplex, bin (dte.device) < 10, bin (dte.device));
339 call unbind;
340 call getwork_channel_proc;
341 call unlock_gte;
342 goto DISMISS_INTERRUPT;
343 end;
344 if dte.reading_detailed_status then
345 call restore_previous_status;
346
347 if level = IO_SYSTEM_FAULT_INTERRUPT_LEVEL then
348 call setup_fault_status;
349 else do;
350 if ^dte.direct then do;
351 if ^status_entry.t then do;
352 ioi_data.spurious_interrupts = ioi_data.spurious_interrupts + 1;
353 call unlock_gte;
354 goto DISMISS_INTERRUPT;
355 end;
356 if ^status_entry.word1.marker then
357 level = IO_TERMINATE_INTERRUPT_LEVEL;
358 end;
359 call setup_normal_status;
360 end;
361
362 call log_status_if_appropriate;
363 if dte.reading_detailed_status then do;
364 call unlock_gte;
365 goto DISMISS_INTERRUPT;
366 end;
367
368 if ^auto_istat.run then do;
369 call unbind;
370 call getwork_channel_proc;
371 end;
372 else if dte.timeout ^= 0 then
373 cte.time_limit = clock () + dte.timeout;
374
375 call deliver_status;
376 call wakeup_user;
377 call unlock_gte;
378 end;
379
380 goto DISMISS_INTERRUPT;
381 DISMISS_INTERRUPT:
382 return;
383 ^L
384
385
386
387 quiesce_channel:
388 entry (p_ctep);
389
390 ctep = p_ctep;
391 gtep = ptr (ctep, cte.gtep);
392 call mask;
393 call lock_gte;
394
395 if cte.connected then
396 cte.quiescing = "1"b;
397
398 call unlock_gte;
399 call unmask;
400 return;
401 ^L
402
403
404 flush_status:
405 entry (p_dtep);
406
407 dtep = p_dtep;
408 gtep = ptr (dtep, dte.gtep);
409 call mask;
410 call lock_gte;
411 call flush_status_proc;
412 call unlock_gte;
413 call unmask;
414 return;
415 ^L
416
417
418
419 online_device_count:
420 entry (p_subsystem_name) returns (fixed bin);
421
422 idp = addr (ioi_data$);
423 do gtx = lbound (ioi_data.gt, 1) to hbound (ioi_data.gt, 1);
424 gtep = addr (ioi_data.gt (gtx));
425 if gte.name = p_subsystem_name then do;
426 done = "0"b;
427 count = 0;
428 call mask;
429 call lock_gte;
430 do dtep = ptr (gtep, gte.dtep) repeat ptr (dtep, dte.next_dtep) while (^done);
431 if ^dte.deleted & dte.device ^= "00"b3 then
432 count = count + 1;
433 done = dte.next_dtep = gte.dtep;
434 end;
435 call unlock_gte;
436 call unmask;
437 return (count);
438 end;
439 end;
440 return (-1);
441 ^L
442
443
444 connect:
445 proc;
446
447 ima.chx = cte.chx;
448 ima.bound = dte.bound;
449 ima.ptp = dte.ptp;
450 ima.listx = dte.listx;
451 ima.pcw = dte.pcw;
452 cte.time_limit = 0;
453
454 if ^gte.psia then do;
455 if cte.direct then
456 call io_manager$connect_direct (ima);
457 else call io_manager$connect (ima);
458 end;
459 else do;
460 ima.listp, ima.dcw_pair_ptr = addr (dte.idcw);
461 call io_manager$workspace_tdcw (ima);
462 call io_manager$connect_abs (ima);
463 end;
464
465 cte.cur_dtep = rel (dtep);
466 dte.cur_ctep = rel (ctep);
467 cte.connected, dte.connected = "1"b;
468 if dte.timeout ^= 0 then
469 cte.time_limit = clock () + dte.timeout;
470
471 pcwp = addr (dte.pcw);
472 if pcw.mask then do;
473 call mask_channel;
474 call setup_timeout_status;
475 call deliver_status;
476 call wakeup_user;
477 end;
478
479 end connect;
480 ^L
481
482
483 getwork_channel_proc:
484 proc;
485
486 if cte.quiescing then do;
487 cte.quiescing = "0"b;
488 return;
489 end;
490
491 if cte.deleting then do;
492 call pxss$notify (unspec (IO_CHANNEL_LOCK_TEMPLATE) || rel (ctep));
493 return;
494 end;
495 if cte.connected | ^cte.ioi_use | gte.suspend_devices then
496 return;
497
498 gte.dtep = ptr (gtep, gte.dtep) -> dte.next_dtep;
499 if gte.pending_connects > 0 then do;
500 begin;
501
502 dcl done bit (1) aligned;
503 dcl saved_dtep ptr;
504
505 done = "0"b;
506 saved_dtep = dtep;
507 do dtep = ptr (gtep, gte.dtep) repeat ptr (dtep, dte.next_dtep) while (^done);
508 if dte.active & ^dte.connected & ^dte.suspended then do;
509 gte.pending_connects = gte.pending_connects - 1;
510 call connect;
511 done = "1"b;
512 end;
513 else done = dte.next_dtep = gte.dtep;
514 end;
515 dtep = saved_dtep;
516 end;
517 end;
518
519 end getwork_channel_proc;
520
521
522
523 mask_channel:
524 proc;
525
526 call io_manager$get_status (cte.chx, addr (status_entry));
527 if dtep ^= null () then
528 call unbind;
529 call io_manager$mask (cte.chx);
530 if ^gte.mplex then do;
531 if dtep ^= null () then
532 if dte.direct then
533 call ioi_wire$unwire (dtep);
534 return;
535 end;
536
537
538
539
540
541
542 if dtep = null () then do;
543 cte.connected = "0"b;
544 cte.toss_status = "0"b;
545 call syserr (ANNOUNCE, "^a: Channel ^a not responding, will remain masked.", ME, cte.chanid);
546 return;
547 end;
548
549 ima.chx = cte.chx;
550
551
552
553
554
555
556 ima.pcw = "000000777777"b3;
557 ima.ptp = null ();
558 ima.listp = addr (ioi_data.rss_idcw);
559 call io_manager$connect_abs (ima);
560 cte.time_limit = cte.time_limit + ONE_MINUTE;
561 cte.toss_status = "1"b;
562 cte.connected = "1"b;
563
564 end mask_channel;
565
566
567
568 unbind:
569 proc;
570
571 cte.cur_dtep, dte.cur_ctep = ""b;
572 cte.connected, dte.connected, dte.active = ""b;
573 dte.unwire_time = clock () + FIFTEEN_SECONDS;
574
575 end unbind;
576 ^L
577
578
579
580 save_status:
581 proc;
582
583 cte.saved_status.word1 = unspec (status_entry.word1);
584 cte.saved_status.word2 = unspec (status_entry.word2);
585 cte.saved_status.word4 = unspec (status_entry.word4);
586 cte.saved_status.next_lpw_offset = bit (bin (auto_istat.offset + 1, 18), 18);
587 cte.saved_status.command = addr (dte.idcw) -> idcw.command;
588
589 end save_status;
590
591
592
593
594 restore_previous_status:
595 proc;
596
597 level = IO_TERMINATE_INTERRUPT_LEVEL;
598 unspec (status_entry.word1) = cte.saved_status.word1;
599 unspec (status_entry.word2) = cte.saved_status.word2;
600 unspec (status_entry.word4) = cte.saved_status.word4;
601 status_entry.next_lpw_offset = cte.saved_status.next_lpw_offset;
602 addr (dte.idcw) -> idcw.command = cte.saved_status.command;
603 status_entry.workspace = "1"b;
604
605 end restore_previous_status;
606 ^L
607
608
609 setup_normal_status:
610 proc;
611
612 unspec (auto_istat) = ""b;
613 auto_istat.er = ((unspec (status_entry.word1) & IO_STATUS_ERROR_MASK) ^= ""b);
614 auto_istat.iom_stat = unspec (status_entry.word1) || unspec (status_entry.word4);
615 goto setup_status_interrupt_join;
616
617 setup_fault_status:
618 entry;
619
620 unspec (auto_istat) = ""b;
621 auto_istat.er = "1"b;
622 auto_istat.iom_stat = status;
623
624 setup_status_interrupt_join:
625 auto_istat.run = (level = IO_MARKER_INTERRUPT_LEVEL) | cte.direct;
626 auto_istat.time_out = "0"b;
627 auto_istat.level = level;
628 goto setup_status_common;
629
630 setup_timeout_status:
631 entry;
632
633 unspec (auto_istat) = ""b;
634 auto_istat.er, auto_istat.time_out = "1"b;
635 auto_istat.level = IO_TERMINATE_INTERRUPT_LEVEL;
636
637 setup_status_common:
638 if ^cte.direct then do;
639 if status_entry.workspace then
640 auto_istat.offset = bin (status_entry.next_lpw_offset, 18) - 1;
641 else if dtep ^= null () then
642 auto_istat.offset = dte.idcw_listx;
643 auto_istat.lpw = unspec (status_entry.word2);
644 end;
645 auto_istat.absaddr = 0;
646
647 imp = addr (message);
648 unspec (imess) = ""b;
649 imess.completion = auto_istat.completion;
650 imess.st = "1"b;
651 imess.level = bit (auto_istat.level, 3);
652 imess.offset = bit (auto_istat.offset, 18);
653 imess.status = substr (auto_istat.iom_stat, 1, length (imess.status));
654
655
656 end setup_normal_status;
657 ^L
658
659
660 deliver_status:
661 proc;
662
663 dcl ioi_abs_seg_ptr ptr;
664 dcl workspace_sdw_ptr ptr;
665
666 if dtep = null () then
667 return;
668 if dte.status_entries = 0 then
669 return;
670
671 ioi_abs_seg_ptr = addr (ioi_abs_seg$);
672 workspace_sdw_ptr = addr (dte.workspace_sdw);
673 call pmut$swap_sdw (ioi_abs_seg_ptr, workspace_sdw_ptr);
674
675 ptr (ioi_abs_seg_ptr, dte.status_offset + size (istat) * dte.status_entry_idx) -> istat = auto_istat;
676 ptr (ioi_abs_seg_ptr, dte.status_offset + size (istat) * dte.status_entry_idx) -> istat.st = "1"b;
677 dte.status_entry_idx = dte.status_entry_idx + 1;
678 if dte.status_entry_idx = dte.status_entries then
679 dte.status_entry_idx = 0;
680
681 end deliver_status;
682
683
684
685 wakeup_user:
686 proc;
687
688 if sys_info$service_system then
689 call pxss$io_wakeup (dte.process_id, dte.ev_chn, message, (0));
690 else call bce_ioi_post (dte.ev_chn, message);
691
692 end wakeup_user;
693 ^L
694
695
696 log_status_if_appropriate:
697 proc;
698
699 dcl log_detail bit (1) aligned;
700 dcl major fixed bin (4);
701 dcl sub fixed bin (6);
702
703 dcl detailed_status_in_status_entry
704 bit (36) aligned based (addr (status_entry.detailed_status));
705 dcl status_entry_array (16) bit (36) aligned based (addr (status_entry));
706 dcl 1 second_status_word aligned like io_status_entry.word4 based (addrel (addr (auto_istat.iom_stat), 1));
707
708
709
710 if dte.reading_detailed_status then do;
711 dte.detailed_status_valid = "1"b;
712 call log_this_status;
713 dte.reading_detailed_status = "0"b;
714 return;
715 end;
716
717 unspec (dte.detailed_status (*)) = ""b;
718
719 if level = IO_SPECIAL_INTERRUPT_LEVEL then
720 return;
721 if level ^= IO_SYSTEM_FAULT_INTERRUPT_LEVEL then do;
722
723 if gte.io_log_info_index = 0 then do;
724 if ^auto_istat.er then
725 return;
726 log_detail = "0"b;
727 end;
728 else do;
729 io_log_infop = addr (io_log_status_info$io_log_status_info);
730 logp = addr (io_log_info.log_entry (gte.io_log_info_index));
731 major = bin (status_entry.major);
732 sub = bin (status_entry.sub);
733 if ^log.status (major, sub) then
734 return;
735 log_detail = log.detail (major, sub);
736 end;
737 end;
738 else log_detail = "0"b;
739
740 if dte.priv then do;
741 unspec (dte.log_status) = ""b;
742 dte.log_status_cnt = "0"b;
743 dte.log_status.level = auto_istat.level;
744 dte.log_status.time_out = auto_istat.time_out;
745 dte.log_status.type = second_status_word.action_code;
746 dte.log_status.command = addr (dte.idcw) -> idcw.command;
747 dte.log_status.channel = rel (ctep);
748 dte.log_status.status = substr (auto_istat.iom_stat, 1, length (dte.log_status.status));
749
750 if log_detail & detailed_status_in_status_entry ^= "000000000000"b3 then do;
751 dte.detailed_status = status_entry.detailed_status;
752 dte.detailed_status_valid = "1"b;
753 end;
754 dte.log_detailed_status = dte.detailed_status;
755 dte.last_log_time = clock ();
756 return;
757 end;
758
759
760
761
762
763 if log_detail & detailed_status_in_status_entry ^= "000000000000"b3 then do;
764 dte.detailed_status = status_entry.detailed_status;
765 dte.detailed_status_valid = "1"b;
766 call log_this_status;
767 return;
768 end;
769
770 if log_detail then do;
771 if gte.detailed_status_cmd = "0"b then do;
772 call syserr (LOG,
773 "^a: No Ext. Stat. with ^o/^o status on chnl ^a (^a^[_^[0^]^d^]).^4(^/^10x^w ^w ^w ^w^)", ME,
774 major, sub, cte.chanid, gte.name, gte.mplex, bin (dte.device) < 10, bin (dte.device),
775 status_entry_array);
776 call log_this_status;
777 return;
778 end;
779 call save_status;
780
781
782
783 dte.idcw, dte.tdcw = "0"b;
784 idcwp = addr (dte.idcw);
785 dcwp = addr (dte.tdcw);
786 idcw.command = gte.detailed_status_cmd;
787 idcw.device = dte.device;
788 idcw.code = "111"b;
789 idcw.count = "01"b3;
790
791 dcw.address = absaddr_18 (addr (dte.detailed_status));
792 dcw.tally = "0006"b3;
793
794 dte.detailed_status_valid = "0"b;
795 unspec (dte.detailed_status) = "0"b;
796
797
798
799 ima.chx = cte.chx;
800 ima.pcw = ""b;
801 ima.ptp = null ();
802 ima.listp = addr (dte.idcw);
803 call io_manager$connect_abs (ima);
804 if dte.timeout ^= 0 then
805 cte.time_limit = clock () + dte.timeout;
806 dte.reading_detailed_status = "1"b;
807 return;
808 end;
809
810 call log_this_status;
811 return;
812
813 absaddr_18:
814 proc (p) returns (bit (18));
815
816 dcl p ptr;
817
818 dcl absaddr fixed bin (26);
819 dcl code fixed bin (35);
820
821 absaddr = absadr (p, code);
822 if code ^= 0 then
823 call syserr (CRASH, "^a$interrupt: absadr failed.", ME);
824 return (bit (bin (absaddr, 18), 18));
825
826 end absaddr_18;
827
828 log_this_status:
829 proc;
830
831
832
833
834
835 dcl 1 test_status like dte.log_status;
836
837 unspec (test_status) = ""b;
838 test_status.level = auto_istat.level;
839 test_status.time_out = auto_istat.time_out;
840 test_status.channel = rel (ctep);
841 test_status.status = substr (auto_istat.iom_stat, 1, length (test_status.status));
842
843 if auto_istat.level ^= IO_SPECIAL_INTERRUPT_LEVEL then do;
844 test_status.type = second_status_word.action_code;
845 test_status.command = addr (dte.idcw) -> idcw.command;
846 end;
847 test_status.count = dte.log_status.count;
848
849 if (dte.log_status_cnt & (unspec (test_status) = unspec (dte.log_status))
850 & (unspec (dte.detailed_status) = unspec (dte.log_detailed_status))) then do;
851
852 dte.log_status.count = dte.log_status.count + 1;
853 if dte.log_status.count = MAX_LOG_STATUS_COUNT then
854 call flush_status_proc;
855 end;
856 else do;
857 call flush_status_proc;
858 dte.log_status = test_status;
859 dte.log_status.count = 0;
860 dte.log_status_cnt = "1"b;
861 dte.log_detailed_status = dte.detailed_status;
862 end;
863
864 end log_this_status;
865
866 end log_status_if_appropriate;
867 ^L
868
869
870 flush_status_proc:
871 proc;
872
873 dcl 1 auto_io_msg aligned like io_msg;
874 dcl msg_length fixed bin;
875 dcl msg_type fixed bin;
876
877 if ^dte.log_status_cnt then
878 return;
879
880 io_msgp = addr (auto_io_msg);
881 io_msg.level = bit (dte.log_status.level);
882 io_msg.device = dte.device;
883 io_msg.time_out = dte.log_status.time_out;
884 io_msg.type = dte.log_status.type;
885 io_msg.command = dte.log_status.command;
886 io_msg.count = bit (dte.log_status.count);
887 io_msg.channel = ptr (dtep, dte.log_status.channel) -> cte.chanid;
888 io_msg.status = dte.log_status.status;
889 io_msg.devname = ptr (dtep, dte.gtep) -> gte.name;
890 if unspec (dte.log_detailed_status) ^= ""b then do;
891 io_msg.detailed_status = substr (unspec (dte.log_detailed_status), 1, length (io_msg.detailed_status));
892 msg_type = SB_io_err_detail;
893 msg_length = SBL_io_err_detail;
894 end;
895 else do;
896 msg_type = SB_io_err;
897 msg_length = SBL_io_err;
898 end;
899
900 call syserr$binary (JUST_LOG, io_msgp, msg_type, msg_length, "^a$interrupt: ^[I/O error^;Special^].", ME,
901 bin (io_msg.level) ^= IO_SPECIAL_INTERRUPT_LEVEL);
902 dte.last_log_time = clock ();
903 dte.log_status_cnt = "0"b;
904
905 end flush_status_proc;
906 ^L
907 special_could_come_from_channel:
908 proc (gtp, ctp) returns (bit (1) aligned);
909
910 dcl ctp ptr parameter;
911 dcl gtp ptr parameter;
912
913 dcl tctp ptr;
914
915 do tctp = ptr (gtp, gtp -> gte.ctep) repeat ptr (tctp, tctp -> cte.next_ctep) while (rel (tctp) ^= ""b);
916 if tctp -> cte.base_ctep = ctp -> cte.base_ctep then
917 return ("1"b);
918 end;
919 return ("0"b);
920
921 end special_could_come_from_channel;
922 ^L
923
924
925 mask:
926 proc;
927
928 call pmut$wire_and_mask (wm_mask, wm_ptwp);
929
930 end mask;
931
932 unmask:
933 proc;
934
935 call pmut$unwire_unmask (wm_mask, wm_ptwp);
936
937 end unmask;
938
939 lock_gte:
940 proc;
941
942 if gte.lock = pds$process_id then
943 call syserr (CRASH, "^a: Mylock error on subsystem ^a.", ME, gte.name);
944
945 do while (^stac (addr (gte.lock), pds$process_id));
946
947 end;
948
949 end lock_gte;
950
951 unlock_gte:
952 proc;
953
954 if ^stacq (gte.lock, ""b, pds$process_id) then
955 call syserr (CRASH, "^a: Lock for subsystem ^a not locked to process ^w.", ME, gte.name, pds$process_id);
956
957 end unlock_gte;
958 ^L
959 %include ioi_data;
960 %page;
961 %include io_manager_dcls;
962 %page;
963 %include interrupt_levels;
964 %page;
965 %include ioi_stat;
966 %page;
967 %include io_status_entry;
968 %page;
969 %include io_special_status;
970 %page;
971 %include io_log_status_info;
972 %page;
973 %include iom_pcw;
974 %include iom_dcw;
975 %page;
976 %include io_syserr_msg;
977 %page;
978 %include syserr_binary_def;
979 %page;
980 %include syserr_constants;
981 %page;
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142 end ioi_masked;