-
Notifications
You must be signed in to change notification settings - Fork 0
/
disk_control.list
12591 lines (11447 loc) · 576 KB
/
disk_control.list
1
2
3
4
5
6
7
8
9
10
11
12
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
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
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
COMPILATION LISTING OF SEGMENT disk_control
Compiled by: Multics PL/I Compiler, Release 33a, of May 30, 1990
Compiled at: ACTC Technologies Inc.
Compiled on: 10/01/90 1626.8 mdt Mon
Options: optimize list
1 /****^ ***********************************************************
2* * *
3* * Copyright, (C) BULL HN Information Systems Inc., 1989 *
4* * *
5* * Copyright, (C) Honeywell Bull Inc., 1987 *
6* * *
7* * Copyright, (C) Honeywell Information Systems Inc., 1982 *
8* * *
9* *********************************************************** */
10
11 /* DISK_CONTROL - Device Control Module for Disks.
12* coded 12/1/70 by N. I. Morris
13* revised 7/1/73 - Lee J. Scheffler to add metering
14* revised 12/73 by N. I. Morris to add DSU-191 disks.
15* revised 4/8/74 by S.H.Webber to change lockptl metering code
16* revised for new storage system - 3/27/75 by Noel I. Morris
17* test_drive entry by Bernard Greenberg 4/9/76
18* improved error handling by Noel I. Morris - 6/3/76
19* bad channel removal added by Noel I. Morris - 8/16/77
20* disk offline waiting added by Bernard Greenberg - 9/20/77
21* changed to use reset status command in test_drive 2/1/79 by Michael R. Jordan
22* modified for new seek optimization for MSU0500/1 devices 4/79 by Michael R. Jordan
23* modified for io_manager conversion February 1981 by Chris Jones
24* Modified July, 1981, WOS, to install Mike Jordan's fix to the 501 sector number
25* overflow problem (too many sectors to represent in 20 bits).
26* Modified February 1982 by C. Hornig for MR10 io_manager.
27* Modified March 1982 by C. Hornig to unload disks.
28* Modified March 1982 by J. Bongiovanni for queue_length_given_pvtx, new PVTE
29* Modified July 1982 by J. Bongiovanni for read_sectors, write_sectors
30* Modified June 1983 by Chris Jones for ioi rewrite
31* Modified January 1984 by Chris Jones to add add_channel entry
32* Modified April 1984 by T. Oke for system wide free_q.
33* Modified April 1984 by T. Oke for dynamic channel table and the use of
34* dskdcl_chans_per_subsys to define channel idx/subsystem relation.
35* Modified May 1984 by T. Oke to save pvtx in queue entry for AZM analysis
36* of queue.
37*
38* Modified for adaptive optimizer by T. Oke May 1984.
39* Modified call_run to poll all sub-systems by T. Oke May 1984,
40* Lossage counters moved to chantab and renamed.
41* Modified to reset quentry.used in add_free_q by T. Oke November 1984.
42* Modified Nov 26, 1984 by R. A. Fawcett to support dev 0 (fips). Also include
43* Chris Jones's change for IMU-type detailed status delivery.
44* Stepped zealousness of esd_reset_locks from "call call_run (sx)" to
45* merely "call run" to prevent running un-reinitialized sub-systems.
46* by T. Oke November 1984.
47* Modified February 1985 by Chris Jones to allow a channel to be usurped if
48* of its devices are deleted.
49* Modified July 1985 by Paul Farley to correctly handle IMU style detailed status.
50**/
51
52 /****^ HISTORY COMMENTS:
53* 1) change(85-09-09,Fawcett), approve(85-09-09,MCR6979),
54* audit(85-12-02,CLJones), install(86-03-21,MR12.0-1033):
55* Add support for dev
56* 0 FIPS, Chris Jones's change for IMU-type detailed status delivery.
57* 2) change(86-04-01,Fawcett), approve(86-04-11,MCR7383),
58* audit(86-05-27,Coppola), install(86-07-17,MR12.0-1097):
59* Add support for subvolumes, and 512_word_io, devices 3380 and 3390.
60* 3) change(86-07-24,Fawcett), approve(86-10-30,PBF7383),
61* audit(86-11-18,Beattie), install(86-11-21,MR12.0-1223):
62* Add an optional third line to the disk error message that gives the
63* subvolume name and logical record/sector for use with the
64* record_to_vtocx command.
65* 4) change(86-10-29,Fawcett), approve(86-11-14,MCR7571),
66* audit(86-11-18,Beattie), install(86-11-21,MR12.0-1223):
67* Check the ioi_used bit before trying to place channels back in operation.
68* 5) change(87-05-22,Fawcett), approve(87-05-27,MCR7704),
69* audit(87-07-08,Farley), install(87-07-17,MR12.1-1043):
70* Move the check for the TEST type IO quentry. This allows the secondary
71* channels to be used if the primary is down.
72* 6) change(87-05-27,Fawcett), approve(87-05-27,MCR7704),
73* audit(87-07-08,Farley), install(87-07-17,MR12.1-1043):
74* Set the "substat" variable to ANY so that matches in the disk_error_data
75* segment can be found for such things as I/O system faults. Also display
76* the I/O system fault word on the console.
77* 7) change(87-08-31,Fawcett), approve(87-08-31,PBF7704),
78* audit(87-08-31,Farley), install(87-09-01,MR12.1-1095):
79* Change to correct a bug in the sub-status reporting in the above fix.
80* 8) change(88-02-23,Farley), approve(88-02-23,MCR7759),
81* audit(88-02-24,Fawcett), install(88-03-01,MR12.2-1029):
82* Changed to set a new flag in the error code "all_paths_bad" and to give up
83* if only one channel left and it is bad. At this time it will only be
84* implemented for bootload_io. This is I/O done for BCE commands.
85* 9) change(88-02-23,Farley), approve(88-02-23,MCR7793),
86* audit(88-02-24,Fawcett), install(88-03-01,MR12.2-1029):
87* Changed the handle_error procedure to only display/retry TEST I/O errors
88* when they are of the bad_path variety. The retry will be done by removing
89* the suspected bad path and re-queuing the I/O. If bad_path error on all
90* paths, set the device inoperative and post the I/O. Same during esd.
91* 10) change(88-03-18,Farley), approve(88-03-18,MCR7858),
92* audit(88-04-11,Fawcett), install(88-04-19,MR12.2-1037):
93* Changed disk_inter entry to set io_status_entry_ptr for all interrupt
94* levels that will be processed. A null ptr fault was occuring with level-1
95* system faults. Changed bad_dev error handling to set pvte inop when doing
96* TEST I/O during an ESD.
97* 11) change(88-05-12,Farley), approve(88-06-03,MCR7906),
98* audit(88-08-03,Fawcett), install(88-08-08,MR12.2-1080):
99* Added a reconnect_announce_time variable to chantab to announce reconnect
100* attempts the first time and every thirty seconds thereafter, until the I/O
101* is successful. All other times the messages will go only to the log as
102* they normally do. Also added I/O type to message.
103* 12) change(89-06-23,Farley), approve(89-07-26,MCR8122),
104* audit(89-09-11,WAAnderson), install(89-09-22,MR12.3-1072):
105* Added functionality to interpret_status and printerr procedures to
106* seperate FIPS disk statuses from all others by checking the pvte.is_sv
107* flag and using new fields in disk_error_data. Also changed printerr to
108* check the new "just_log" flag in disk_error_data.
109* 13) change(90-06-27,WAAnderson), approve(90-08-28,MCR8188),
110* audit(90-09-21,Schroth), install(90-10-01,MR12.4-1035):
111* Fix bug in esd_reset_locks and handle_error that caused ESD to fail.
112* END HISTORY COMMENTS */
113
114 /*
115* ERROR RECOVERY STRATEGY
116*
117* When a fatal error is detected by the disk DIM, the
118* drive involved is placed in a temporarily inoperative state. If
119* the drive corrects the problem by itself within several seconds
120* and sends a special interrupt, the drive will be placed back in
121* operation. If no special is received within the several second
122* time limit, the DIM will attempt to use the drive once more. If
123* it generates another fatal error, the drive will be placed in
124* broken state. The DIM will attempt to use a broken drive every
125* several minutes. The receipt of a special interrupt, or a
126* successful attempt to use a broken drive, will place that drive
127* back in operation. Read requests that are queued for a broken
128* drive will be posted as errors. Write requests will be left in
129* the queue and ignored util the broken drive becomes operational
130* again.
131*
132**/
133
134 /* format: style4,delnl,insnl,indattr,ifthen,dclind10 */
135 disk_control:
136 proc;
137
138 dcl a_pvtx fixed bin; /* index of PVT entry */
139 dcl a_coreadd fixed bin (24); /* absolute core address */
140 dcl a_devadd bit (18) aligned; /* secondary storage device address */
141 dcl a_intrpt fixed bin (1); /* non-zero if completion interrupt desired */
142 dcl a_queue_length fixed bin; /* current number of elements in Q */
143 dcl a_sect_off fixed bin (4); /* sector offset for single sector requests */
144 dcl a_n_sectors fixed bin; /* number of sectors for sector I/O */
145
146 dcl pvtx fixed bin; /* copied args to prevent page faults */
147 dcl coreadd fixed bin (24);
148 dcl sect_off fixed bin (4);
149 dcl n_sectors fixed bin;
150 dcl record_offset fixed bin;
151
152 /* Local Automatic storage. */
153
154 dcl bootload_sw bit (1) aligned; /* set if I/O is being done for bootload Multics */
155 dcl call_run_sx fixed bin; /* a_sx saved in call_run */
156 dcl channel_time fixed bin (52); /* time channel spent doing I/O */
157 dcl command bit (6) aligned; /* peripheral device command */
158 dcl cylinder fixed bin (12); /* cylinder heads are currently on */
159 dcl dcdcwp ptr; /* pointer to data xfer IDCW */
160 dcl dddcwp ptr; /* pointer to data xfer DCW */
161 dcl dev unsigned fixed bin (6); /* disk device code */
162 dcl devadd fixed bin (18); /* record number part of device address */
163 dcl dev_count fixed bin; /* counter in getwork */
164 dcl entry_time fixed bin (52); /* time of call */
165 dcl errcd fixed bin (35); /* error code to page control */
166 dcl i fixed bin; /* usually channel index */
167 dcl intrpt bit (1); /* if interrupt required */
168 dcl io_type fixed bin; /* type of IO */
169 dcl lcp ptr; /* local channel pointer in handle_error */
170 dcl level fixed bin (3); /* level of interrupt from IOM */
171 dcl majstat fixed bin (5); /* extended major status */
172 dcl mask fixed bin (71) aligned; /* temp for wire and mask */
173 dcl masked bit (1); /* running masked */
174 dcl meter_start_time fixed bin (52); /* time of attempt to lock */
175 dcl name_rel fixed bin (17); /* rel offset of the disk_error_data ascii names */
176 dcl pdi fixed bin (6) unsigned; /* Primary Device Index. */
177 dcl post_sw bit (1) aligned; /* "1"b if posting must be done */
178 dcl ptp ptr; /* temp for wire_and_mask */
179 dcl qrp bit (18) aligned; /* rel ptr to queue entry */
180 dcl qx fixed bin (8); /* index to queue entry */
181 dcl required bit (1) aligned; /* "1"b if IOI requires specific channel */
182 dcl sector fixed bin (21); /* physical disk sector */
183 dcl sect_sw bit (1); /* if sector IO */
184 dcl stat bit (36) aligned; /* copy of special or fault status word */
185 dcl status_time fixed bin (52); /* time status received */
186 dcl sx fixed bin (8); /* index of disk subsystem */
187 dcl sysc fixed bin; /* syserr report code */
188 dcl substat bit (6) aligned; /* substatus */
189 dcl temp_time fixed bin (52); /* for real time looping on inop chnl errors */
190 dcl usurped bit (1) aligned; /* "1"b if IOI usurped channel successfully */
191 dcl wait_time fixed bin (52); /* time from queuing to I/O completion */
192
193 dcl 1 msg_buf like io_msg aligned; /* for syserr data */
194
195 dcl 1 stat_entry like io_status_entry; /* the whole disaster */
196
197 dcl error_table_$bad_arg fixed bin (35) ext static;
198 dcl error_table_$io_configured
199 fixed bin (35) ext static;
200
201 dcl pds$processid ext bit (36);
202 dcl page_fault$disk_offline_event
203 bit (36) aligned ext;
204 dcl tc_data$system_shutdown
205 ext fixed bin;
206
207 dcl ANY bit (6) init ("000000"b) static options (constant);
208 /* used for substatus that will match on any */
209 dcl (
210 BOTH init ("1"b),
211 SINGLE init ("0"b),
212 ON init ("1"b),
213 OFF init ("0"b),
214 SUCCESS init ("1"b),
215 FAILURE init ("0"b)
216 ) bit (1) aligned static options (constant);
217 dcl IDCW bit (3) init ("7"b3) static options (constant);
218 dcl (
219 WRITE init ("31"b3),
220 READ init ("25"b3),
221 RESET_STATUS init ("40"b3),
222 UNLOAD init ("72"b3)
223 ) bit (6) static options (constant);
224 dcl UNLOCK bit (36) aligned init ((36)"0"b) static options (constant);
225 dcl (
226 ANNOUNCE_RECONNECT_DELTA
227 fixed bin (35) init (30000000),
228 /* thirty seconds for reconnect announce throttling */
229 DISK_POLLING_TIME fixed bin (35) init (2000000),
230 /* two seconds for lost interrupt */
231 INOP_POLLING_TIME fixed bin (35) init (5000000),
232 /* five seconds for dropping out of ready */
233 BROKEN_POLLING_TIME fixed bin (35) init (180000000),
234 /* three minutes for standby */
235 CHANNEL_POLLING_TIME fixed bin (35) init (60000000)
236 /* one minute for bad channel */
237 ) static options (constant);
238
239 dcl bootload_disk_post entry (fixed bin (24), fixed bin (35));
240 dcl seek_512 bit (6) init ("30"b3) static options (constant);
241 dcl syserr entry options (variable);
242 dcl syserr$binary entry options (variable);
243 dcl pxss$notify entry (bit (36) aligned);
244 dcl page$done entry (fixed bin (24), fixed bin (35));
245 dcl pmut$wire_and_mask entry (fixed bin (71) aligned, ptr);
246 dcl pmut$unwire_unmask entry (fixed bin (71) aligned, ptr);
247 dcl dctl$disk_inter entry (fixed bin (35), fixed bin (3), bit (36) aligned);
248 dcl vtoc_interrupt entry (fixed bin (24), fixed bin (35));
249 dcl ioi_masked$online_device_count
250 entry (char (*)) returns (fixed bin);
251 dcl ioi_masked$interrupt entry (fixed bin (35), fixed bin (3), bit (36) aligned);
252
253 dcl (abs, addr, addrel, bin, bit, clock, convert, divide, fixed, float, lbound, length, hbound, max, mod, null, ptr,
254 rel, stacq, string, substr, unspec)
255 builtin;
256
257 dcl ME char (16) static options (constant) init ("disk_control");
258
259 dcl dev_mask (0:63) bit (72) aligned static options (constant)
260 init ("100000000000000000000000000000000000000000000000000000000000000000000000"b,
261 "010000000000000000000000000000000000000000000000000000000000000000000000"b,
262 "001000000000000000000000000000000000000000000000000000000000000000000000"b,
263 "000100000000000000000000000000000000000000000000000000000000000000000000"b,
264 "000010000000000000000000000000000000000000000000000000000000000000000000"b,
265 "000001000000000000000000000000000000000000000000000000000000000000000000"b,
266 "000000100000000000000000000000000000000000000000000000000000000000000000"b,
267 "000000010000000000000000000000000000000000000000000000000000000000000000"b,
268 "000000001000000000000000000000000000000000000000000000000000000000000000"b,
269 "000000000100000000000000000000000000000000000000000000000000000000000000"b,
270 "000000000010000000000000000000000000000000000000000000000000000000000000"b,
271 "000000000001000000000000000000000000000000000000000000000000000000000000"b,
272 "000000000000100000000000000000000000000000000000000000000000000000000000"b,
273 "000000000000010000000000000000000000000000000000000000000000000000000000"b,
274 "000000000000001000000000000000000000000000000000000000000000000000000000"b,
275 "000000000000000100000000000000000000000000000000000000000000000000000000"b,
276 "000000000000000010000000000000000000000000000000000000000000000000000000"b,
277 "000000000000000001000000000000000000000000000000000000000000000000000000"b,
278 "000000000000000000100000000000000000000000000000000000000000000000000000"b,
279 "000000000000000000010000000000000000000000000000000000000000000000000000"b,
280 "000000000000000000001000000000000000000000000000000000000000000000000000"b,
281 "000000000000000000000100000000000000000000000000000000000000000000000000"b,
282 "000000000000000000000010000000000000000000000000000000000000000000000000"b,
283 "000000000000000000000001000000000000000000000000000000000000000000000000"b,
284 "000000000000000000000000100000000000000000000000000000000000000000000000"b,
285 "000000000000000000000000010000000000000000000000000000000000000000000000"b,
286 "000000000000000000000000001000000000000000000000000000000000000000000000"b,
287 "000000000000000000000000000100000000000000000000000000000000000000000000"b,
288 "000000000000000000000000000010000000000000000000000000000000000000000000"b,
289 "000000000000000000000000000001000000000000000000000000000000000000000000"b,
290 "000000000000000000000000000000100000000000000000000000000000000000000000"b,
291 "000000000000000000000000000000010000000000000000000000000000000000000000"b,
292 "000000000000000000000000000000001000000000000000000000000000000000000000"b,
293 "000000000000000000000000000000000100000000000000000000000000000000000000"b,
294 "000000000000000000000000000000000010000000000000000000000000000000000000"b,
295 "000000000000000000000000000000000001000000000000000000000000000000000000"b,
296 "000000000000000000000000000000000000100000000000000000000000000000000000"b,
297 "000000000000000000000000000000000000010000000000000000000000000000000000"b,
298 "000000000000000000000000000000000000001000000000000000000000000000000000"b,
299 "000000000000000000000000000000000000000100000000000000000000000000000000"b,
300 "000000000000000000000000000000000000000010000000000000000000000000000000"b,
301 "000000000000000000000000000000000000000001000000000000000000000000000000"b,
302 "000000000000000000000000000000000000000000100000000000000000000000000000"b,
303 "000000000000000000000000000000000000000000010000000000000000000000000000"b,
304 "000000000000000000000000000000000000000000001000000000000000000000000000"b,
305 "000000000000000000000000000000000000000000000100000000000000000000000000"b,
306 "000000000000000000000000000000000000000000000010000000000000000000000000"b,
307 "000000000000000000000000000000000000000000000001000000000000000000000000"b,
308 "000000000000000000000000000000000000000000000000100000000000000000000000"b,
309 "000000000000000000000000000000000000000000000000010000000000000000000000"b,
310 "000000000000000000000000000000000000000000000000001000000000000000000000"b,
311 "000000000000000000000000000000000000000000000000000100000000000000000000"b,
312 "000000000000000000000000000000000000000000000000000010000000000000000000"b,
313 "000000000000000000000000000000000000000000000000000001000000000000000000"b,
314 "000000000000000000000000000000000000000000000000000000100000000000000000"b,
315 "000000000000000000000000000000000000000000000000000000010000000000000000"b,
316 "000000000000000000000000000000000000000000000000000000001000000000000000"b,
317 "000000000000000000000000000000000000000000000000000000000100000000000000"b,
318 "000000000000000000000000000000000000000000000000000000000010000000000000"b,
319 "000000000000000000000000000000000000000000000000000000000001000000000000"b,
320 "000000000000000000000000000000000000000000000000000000000000100000000000"b,
321 "000000000000000000000000000000000000000000000000000000000000010000000000"b,
322 "000000000000000000000000000000000000000000000000000000000000001000000000"b,
323 "000000000000000000000000000000000000000000000000000000000000000100000000"b);
324
325 /* format: off */
326 /* Assumptions:
327*
328*Several variables are expected to be correct through most of this program:
329*
330* dev Device index of the devtab entry for the current device.
331* dp Devtab Pointer, indicates the current devtab to be operating upon.
332* It is typically set from addr (disktab.devtab (pdi)).
333* pdi Primary Device Index of the current dev. Found in devtab.pdi
334* Used to determine primary device of shared devices. The primary
335* device will hold queue for all its shared spindles.
336* sect_sw Sector switch indication for the current IO to be entered into a
337* quentry (operation entry points), or when posting a completed IO.
338* Major importance when posting an IO, since it must be correct for
339* the coreadd being posted.
340* sx Subsystem index. Indicates which subsystem is in use, in order of
341* definition of subsystems in the config_file.
342*
343* When a disk interrupt is received, we take info on dev, pdi, coreadd,
344*sect_sw from the entry in check_stat. These should not be messed with, since
345*check_stat will also return the queue element to the free_q and will call
346*getwork to start fresh IO on the channel ASAP. Sect_sw and coreadd must still
347*be good at post time.
348*
349* Since on shared devices, a single pdi's queue will hold requests for more
350*than a single device, the dev value is recovered from the selected queue in
351*getwork (after xfer_join) to ensure we know who we are dealing with.
352*
353* Add_wq will add the new request to the queue of the pdi, but will do the
354*appropriate statistics (other than queue stats) on the device (dev). Same with
355*del_q.
356**/
357 /* format: on */
358
359 /* Entry points to generate disk requests. Setup the type of the IO and then
360* enter common code to process entry conditions. If we are doing testing or
361* VTOCE IO, then we have to wire and mask. If doing PAGE IO, then we are
362* wired and masked. */
363
364
365 write_sectors:
366 entry (a_pvtx, a_coreadd, a_devadd, a_sect_off, a_n_sectors);
367
368 io_type = VTOC_WRITE;
369 goto go_sector;
370
371
372 read_sectors:
373 entry (a_pvtx, a_coreadd, a_devadd, a_sect_off, a_n_sectors);
374
375 io_type = VTOC_READ;
376 go_sector:
377 devadd = bin (a_devadd, 18); /* copy device address */
378 coreadd = a_coreadd; /* copy core address */
379
380 sect_off = a_sect_off; /* setup offset */
381 n_sectors = a_n_sectors;
382 goto go_masked; /* Enter masked env */
383
384
385 test_drive:
386 entry (a_pvtx); /* test drive by issuing RSS */
387
388 io_type = TEST;
389 coreadd = bin (RESET_STATUS, 24); /* Device TEST command */
390 goto go_test;
391
392
393
394 unload_drive:
395 entry (a_pvtx); /* cycle down a drive */
396
397 io_type = TEST;
398 coreadd = bin (UNLOAD, 24); /* Device UNLOAD command */
399 go_test:
400 sect_off = 0; /* no offset if TEST */
401 n_sectors = 0; /* no sectors if TEST */
402 devadd = 0; /* no core if TEST */
403
404 /* Sector and Test IO must be masked and have the stack wired. */
405
406 go_masked:
407 call pmut$wire_and_mask (mask, ptp); /* mask for processing */
408 masked = "1"b; /* so we unmask */
409 intrpt = "0"b;
410 goto go_common;
411
412
413 /* Write/Read a Virtual Memory Page between Disk and a Memory Frame. */
414
415 disk_write:
416 entry (a_pvtx, a_coreadd, a_devadd, a_intrpt);
417
418 io_type = PAGE_WRITE;
419 goto go_page;
420
421 disk_read:
422 entry (a_pvtx, a_coreadd, a_devadd, a_intrpt);
423
424 io_type = PAGE_READ;
425 go_page:
426 masked = "0"b; /* run unmasked */
427 devadd = bin (a_devadd, 18); /* copy device address */
428 coreadd = a_coreadd; /* copy core address */
429 sect_off = 0; /* no sector offset */
430 n_sectors = 0;
431 if a_intrpt ^= 0 then
432 intrpt = "1"b; /* completion interrupt */
433 else intrpt = "0"b;
434
435 /* Initialize indices and pointers and lock database. Then do operation. */
436
437
438 go_common:
439 entry_time = clock ();
440 sect_sw = sector_map (io_type);
441 bootload_sw = bootload_map (io_type);
442 pvtep = addr (addr (pvt$array) -> pvt_array (a_pvtx));
443 /* Get pointer to PVT entry for this device. */
444 pvtdip = addr (pvte.dim_info); /* Get pointer to DIM info. */
445 sx = pvtdi.sx; /* Extract index for this disk subsystem. */
446 call setup; /* Get pointers to data bases. */
447 call lock (addr (disktab.call_lock_meters)); /* Lock the database. */
448
449 dev = pvte.logical_area_number; /* Get physical device number. */
450 pdi = disktab.devtab (dev).pdi; /* Get PDI. */
451 dp = addr (disktab.devtab (pdi)); /* Get pointer to info for primary device. */
452
453 /* Test for device not to be used. */
454
455 if devtab.abandoned then do; /* If device is hopelessly broken ... */
456 errcd = 0; /* Clear error code. */
457 if ^write_map (io_type) then do; /* If about to read ... */
458 erfp = addr (errcd); /* Get pointer for mismatching dcl. */
459 errflags.device_inoperative = "1"b; /* Indicate read could not succeed. */
460 end;
461 call unlock; /* Undo the lock. */
462 call post; /* Pretend write was successful. */
463 go to call_exit; /* Clean up and exit. */
464 end;
465
466 /* Attempt to get free queue entry to fill in. */
467
468 disktab.alloc_wait_meters.count = disktab.alloc_wait_meters.count + 1;
469 if ^get_free_q () then do; /* Try to grab a free queue entry. */
470 call lock_meter_start (addr (disktab.alloc_wait_meters));
471 do while (^get_free_q ()); /* Try to grab a free queue entry. */
472 call call_run (sx); /* If none, wait until some free up. */
473 end; /* Note: run destroys value of pvtep */
474 call lock_meter_stop (addr (disktab.alloc_wait_meters));
475 end;
476
477 /* Compute physical sector address from input info. Physical sector result
478* accounts for unused sectors per cylinder. */
479
480 if pvte.is_sv then do; /* convert the subvolume devadd to the real devadd */
481 record_offset = mod (devadd, pvte.records_per_cyl);
482 devadd = ((devadd - record_offset) * pvte.num_of_svs) + pvte.record_factor + record_offset;
483 end;
484 sector = devadd * sect_per_rec (pvte.device_type);/* raw sector. */
485 cylinder = divide (sector, pvtdi.usable_sect_per_cyl, 12, 0);
486 sector = sector + cylinder * pvtdi.unused_sect_per_cyl;
487 sector = sector + sect_off; /* sector offset, if any. */
488
489 /* Fill in the queue entry. */
490
491 quentry.intrpt = intrpt; /* completion? */
492 quentry.used = "1"b; /* in-use */
493 quentry.type = io_type; /* Type of IO */
494 quentry.coreadd = bit (coreadd, 24); /* Insert the memory address for data xfer. */
495
496 quentry.pvtx = a_pvtx; /* Save for azm */
497 quentry.pdi = pdi; /* Also save PDI for this device. */
498 quentry.dev = dev; /* Place device code in queue entry. */
499 quentry.cylinder = cylinder; /* And the cylinder number. */
500
501 quentry.n_sectors = n_sectors; /* And the number of sectors (sector I/O only) */
502 quentry.sector = bit (sector, 21); /* Save the disk device address. */
503
504 /* Record time for AZM and stagnation testing. */
505
506 quentry.time = entry_time;
507
508 /* If this is the only request for this device, try to start up a free channel.
509* Otherwise, queue the request for processing later. */
510
511 if ^(disktab.dev_busy | disktab.dev_queued) & dev_mask (pdi) then
512 do i = 1 to disktab.nchan; /* If device is free with no other requests ... */
513 cp = addr (ptr (disksp, disktab.channels) -> disk_channel_table (i));
514 /* Try to find a channel to run. */
515 if chantab.in_use & ^chantab.active then do; /* If free usable channel ... */
516 call gotwork; /* Let's do this request. */
517 go to working; /* And exit the loop. */
518 end;
519 end;
520
521 call add_wq; /* Add item to end of appropriate queue. */
522
523 /* Clean up and exit. */
524
525 working:
526 call unlock; /* Unlock the data base now. */
527
528 call_exit:
529 if masked then
530 call pmut$unwire_unmask (mask, ptp); /* Restore vtoc_man's environment */
531
532 return;
533
534 /* ESD_RESET_LOCKS - Reset data base locks on emergency shutdown. */
535
536 esd_reset_locks:
537 entry;
538
539 disksp = addr (disk_seg$);
540
541 unspec (disk_data.free_q) = "0"b; /* clear free_q */
542 disk_data.free_q.depth = disk_data.free_q_size; /* empty queue */
543
544 /* This form of unlocking is used because it causes a load of "0"b and
545* and ANSA instruction. This will do a read/alter/re-write cycle and
546* correctly update cache. We cannot STACQ since it may not have been locked
547* to our processid. */
548
549 unspec (disk_data.lock) = unspec (disk_data.lock) & "0"b;
550
551 do qx = 1 to disk_data.free_q_size; /* Look at each queue entry. */
552 qp = addr (disk_data.free_q_entries (qx));
553 qrp = rel (qp);
554
555 call add_free_q; /* Free all entries at ESD time. */
556 end;
557
558 do sx = 1 to disk_data.subsystems;
559 call setup; /* Get pointer to subsystem data. */
560 call unlock; /* Undo the lock. */
561
562 call lock (addr (disktab.call_lock_meters)); /* Set the lock to us. */
563
564 do dev = disktab.first_dev to disktab.last_dev;
565 /* Clear each device. */
566 dp = addr (disktab.devtab (dev)); /* Get pointer to info for device. */
567 devtab.broken, devtab.was_broken, devtab.inop = "0"b;
568 /* Try to use broken device. */
569 devtab.cylinder = 0; /* Reset positional info. */
570 unspec (devtab.wq) = "0"b; /* Clear queue pointers */
571
572 /* reset optimizer queue depth to reflect empty queues. */
573
574 do i = 0 to MAX_IO_TYPE;
575 devtab.forward = "1"b;
576 devtab.opt_info (i).depth = 0;
577 end;
578 end;
579
580 cp = ptr (disksp, disktab.channels); /* Get pointer to channel table. */
581 do i = 1 to disktab.nchan; /* Iterate through all channels. */
582 cp -> disk_channel_table (i).active = "0"b;
583 /* Mark all channels as not busy. */
584 cp -> disk_channel_table (i).inop = "0"b;
585 /* Mark as operative */
586 cp -> disk_channel_table (i).broken = "0"b;
587 /* Mark as not broken */
588 if ^(cp -> disk_channel_table (i).ioi_use) &
589 ^(cp -> disk_channel_table (i).in_use) then do;
590 cp -> disk_channel_table (i).in_use = "1"b;
591 disktab.channels_online = disktab.channels_online+1;
592 end;
593 cp -> disk_channel_table (i).erct = 0; /* clear error count */
594 end;
595
596 disktab.dev_busy = "0"b; /* Clear busy device flags. */
597 disktab.dev_queued = "0"b; /* Clear request queued flags. */
598
599 call run; /* Start this subsystem rolling. */
600 call unlock; /* Undo the lock. */
601 end;
602
603 return;
604
605 /* USURP_CHANNEL/CEDE_CHANNEL - Share disk channels with IOI. */
606
607 usurp_channel:
608 entry (a_sx, a_chx, a_required, a_iom_chx, a_statusp); /* Entry to usurp channel for IOI use. */
609
610 dcl a_sx fixed bin (8); /* disk subsystem index */
611 dcl a_chx fixed bin (35); /* disk channel index */
612 dcl a_required bit (1) aligned; /* "1"b if specific channel required */
613
614 dcl chx fixed bin (35); /* chx as an integer */
615
616 sx = a_sx; /* Copy subsystem index. */
617 required = a_required; /* Copy argument. */
618 chx = a_chx; /* copy chx */
619 call setup; /* Get appropriate pointers. */
620 cp = addr (ptr (disksp, disktab.channels) -> disk_channel_table (chx));
621 /* Get pointer to chantab entry. */
622
623 call pmut$wire_and_mask (mask, ptp); /* Wire stack and mask interrupts. */
624 call lock (addr (disktab.call_lock_meters)); /* Lock the disk database. */
625
626 usurped = (required | ^(chantab.broken | chantab.inop)) &
627 /* Usurp if required or not defective channel, and ... */
628 ((disktab.channels_online > 1) | ^chantab.in_use
629 | (ioi_masked$online_device_count (disk_data.name (sx)) = 0));
630 /* Ensure last good channel will not be usurped. */
631
632 if usurped then do; /* If we may, usurp the channel. */
633 if chantab.in_use then /* If channel is being used, count it out. */
634 disktab.channels_online = disktab.channels_online - 1;
635 chantab.in_use = "0"b; /* Take channel out of operation. */
636 chantab.broken, chantab.inop = "0"b; /* Clear flags. */
637 end;
638
639 call unlock; /* Unlock the disk database. */
640 call pmut$unwire_unmask (mask, ptp); /* Unwire stack and unmask interrupts now. */
641
642 if usurped then do; /* If channel now usurped ... */
643 do while (chantab.active); /* Wait for I/O to stop. */
644 end;
645 a_iom_chx = chantab.chx;
646 a_statusp = chantab.statusp;
647 chantab.ioi_use = "1"b; /* Now allow IOI to use channel. */
648 end;
649 else do;
650 a_iom_chx = 0;
651 a_statusp = null ();
652 end;
653
654 return;
655
656 cede_channel:
657 entry (a_sx, a_chx, a_iom_chx, a_statusp); /* Entry to cede channel from IOI use. */
658
659 dcl a_iom_chx fixed bin (35) parameter;
660 dcl a_statusp ptr parameter;
661
662 dcl iom_chx fixed bin (35);
663 dcl statusp ptr;
664
665 sx = a_sx; /* Copy subsystem index. */
666 chx = a_chx; /* copy chx */
667 iom_chx = a_iom_chx;
668 statusp = a_statusp;
669 call setup; /* Get appropriate pointers. */
670 cp = addr (ptr (disksp, disktab.channels) -> disk_channel_table (chx));
671 /* Get pointer to chantab entry. */
672
673 chantab.chx = iom_chx;
674 chantab.statusp = statusp;
675 chantab.ioi_use = "0"b; /* Take channel back from IOI. */
676 chantab.in_use = "1"b; /* Place channel back in operation. */
677 disktab.channels_online = disktab.channels_online + 1;
678
679 return;
680
681 /* Entry to manually add a deleted channel */
682
683 add_channel:
684 entry (a_sx, a_chx, a_code);
685
686 dcl a_code fixed bin (35) parameter;
687
688 sx = a_sx;
689 chx = a_chx;
690 call setup;
691 cp = addr (ptr (disksp, disktab.channels) -> disk_channel_table (chx));
692 call pmut$wire_and_mask (mask, ptp);
693 call lock (addr (disktab.call_lock_meters));
694 if chantab.broken then do;
695 chantab.broken = "0"b;
696 chantab.in_use = "1"b;
697 disktab.channels_online = disktab.channels_online + 1;
698 end;
699 else errcd = error_table_$io_configured;
700 call unlock;
701 call pmut$unwire_unmask (mask, ptp);
702 if errcd = 0 then
703 call syserr (ANNOUNCE, "^a: Adding channel ^a.", ME, chantab.chanid);
704 a_code = errcd;
705 return;
706
707 /* DISK_RUN - External entry to poll all disk subsystems. */
708
709 disk_run:
710 entry; /* here to keep going */
711
712 entry_time = clock (); /* get time of entry */
713
714 disksp = addr (disk_seg$); /* Get pointer to disk data base. */
715
716 do sx = 1 to disk_data.subsystems; /* Iterate through all disk subsystems. */
717 call setup; /* Get pointers to data base. */
718 call lock (addr (disktab.run_lock_meters)); /* Lock the database. */
719 call run; /* Now perform run operation. */
720 call unlock; /* Unlock the data base when finished. */
721 end;
722
723 return;
724
725
726
727 /* CALL_RUN - Entry to poll a single disk subsystem. */
728
729 call_run:
730 entry (a_sx);
731
732
733 entry_time = clock ();
734
735 sx = a_sx; /* Copy the subsystem index. */
736 call setup;
737 call run;
738
739 /* run the other sub-systems too. But now we have to lock them if possible. */
740
741 call_run_sx = a_sx; /* save sx to return to */
742 do sx = 1 to disk_data.subsystems;
743 if sx ^= call_run_sx then do;
744 call setup;
745 if stacq (disktab.lock, pds$processid, UNLOCK) then do;
746 /* locked it */
747 call run;
748 call unlock;
749 end;
750 end;
751 end;
752 sx = call_run_sx;
753 call setup; /* restore sub-sys */
754 return;
755
756 /* RUN - Internal entry to perform polling. */
757
758 run:
759 proc;
760
761 /* Perform channel polling. */
762
763 do i = 1 to disktab.nchan; /* Iterate through all channels. */
764 cp = addr (ptr (disksp, disktab.channels) -> disk_channel_table (i));
765 /* Generate pointer to channel info table. */
766
767 if chantab.inop & ^chantab.in_use then /* If channel is inoperative ... */
768 if clock () - chantab.connect_time > CHANNEL_POLLING_TIME then do;
769 chantab.in_use = "1"b; /* Try once more. */
770 disktab.channels_online = disktab.channels_online + 1;
771 end;
772
773 /* format: off */
774 /* Poll for disk completion. This is required for allocation lock checks, and
775* during run_locks from page control, since both are run masked, and this
776* polling is the only way we would see disk completion. This race hazard
777* on normal 15-seconds run_locks will produce some interrupts without
778* terminate status, but you can't win them all. It may also produce some
779* situations of interrupt wile not active. */
780 /* format: on */
781
782 if ^chantab.active then /* If channel is inactive ... */
783 call getwork; /* Fire it up. */
784
785 else do; /* Attempt to pick up status. */
786 status_time = clock (); /* For reconnect test, NOT race */
787 io_status_entry_ptr = addr (stat_entry);
788 call io_manager$get_status ((chantab.chx), io_status_entry_ptr);
789 /* See if any status has come in. */
790 io_status_word_ptr = addr (stat_entry.word1);
791 if /* case */ io_status_word.t then do; /* If status is present ... */
792 chantab.status_from_run = chantab.status_from_run + 1;
793 level = 3; /* Set terminate status level. */
794 call check_stat; /* Go examine the status. */
795
796 if post_sw then do; /* If previous I/O must be posted ... */
797 call unlock; /* Don't call out with our lock set. */
798 call post; /* Do the posting. */
799 call lock (addr (disktab.call_lock_meters));
800 /* Relock our data base now. */
801 end;
802 end;
803
804 else if chantab.connect_time + DISK_POLLING_TIME < status_time then do;
805 /* If an interrupt has been lost ... */
806 idcwp = addr (chantab.scdcw); /* Find out device in operation. */
807 dev = fixed (idcw.device, 6); /* .. */
808 pdi = disktab.devtab (dev).pdi; /* Get PDI for this device. */
809 if chantab.reconnect_announce_time < status_time then do;
810 chantab.reconnect_announce_time = status_time + ANNOUNCE_RECONNECT_DELTA;
811 sysc = ANNOUNCE;
812 end;
813 else sysc = LOG;
814 call syserr (sysc, "^a: Reconnected ^a I/O on ^a (channel ^a).", ME,
815 IO_TYPE (ptr (disksp, chantab.qrp) -> quentry.type), disk_name (SINGLE), chantab.chanid);
816 call connect (idcwp); /* Reconnect */
817 end;
818 end;
819 end;
820
821
822 /* Perform device polling. */
823
824 do dev = disktab.first_dev to disktab.last_dev; /* Poll all devices. */
825 pdi = disktab.devtab (dev).pdi; /* Get PDI for this device. */
826 if pdi = dev then do; /* This is primary device. */
827 dp = addr (disktab.devtab (pdi)); /* Get pointer to primary device info. */
828
829 if /* case */ devtab.inop then /* If device is inoperative ... */
830 if clock () - devtab.time_inop > INOP_POLLING_TIME then do;
831 disktab.dev_busy = disktab.dev_busy & ^dev_mask (pdi);
832 end; /* Try to use device again. */
833 else ;
834
835 else if devtab.broken then /* If device is broken ... */
836 if clock () - devtab.time_inop > BROKEN_POLLING_TIME then do;
837 devtab.inop = "1"b; /* Mark as inoperative again. */
838 devtab.was_broken = "1"b; /* .. */
839 pvtep = addr (addr (pvt$array) -> pvt_array (devtab.pvtx));
840 call set_pvte_inop (OFF);
841 devtab.broken = "0"b; /* Turn off broken flag. */
842 end;
843 else ;
844 end;
845 end;
846
847 return;
848
849
850 end run;
851
852 /* DISK_INTER - This is the interrupt side of the disk DIM. */
853
854 disk_inter:
855 entry (idx, ilevel, istat); /* called by io_manager at interrupt time */
856
857 dcl idx fixed bin (35), /* channel ID index */
858 istat bit (36) aligned, /* status for specials or faults */
859 ilevel fixed bin (3); /* level of interrupt */
860
861 dcl int_idx fixed bin (35); /* idx as an integer */
862
863 int_idx = idx;
864 sx = divide (int_idx, dskdcl_chans_per_subsys, 17, 0);
865 /* Get index of this disk subsystem. */
866 call setup; /* Get pointer to data base. */
867
868 i = int_idx - sx * dskdcl_chans_per_subsys + 1; /* Compute expected channel table index. */
869 cp = addr (ptr (disksp, disktab.channels) -> disk_channel_table (i));
870
871 level = ilevel; /* copy the level */
872 stat = istat;
873 if level = 7 then do;
874 call check_special_stat;
875 return;
876 end;
877
878
879 io_status_word_ptr = chantab.statusp; /* point to status */
880
881 if ^io_status_word.t then
882 if level >= 3 then do;
883 chantab.no_status_terminate = chantab.no_status_terminate + 1;
884 return;
885 end;
886
887
888 if ^chantab.ioi_use then do; /* If terminate, marker, or fault ... */
889 call lock (addr (disktab.int_lock_meters)); /* Lock the database. */
890 io_status_entry_ptr = addr (stat_entry); /* point to an area to return status */
891 unspec (io_status_entry) = ""b;
892 if /* case */ level = 3 then do; /* Reget status, under lock */
893 call io_manager$get_status ((chantab.chx), io_status_entry_ptr);
894 io_status_word_ptr = addr (io_status_entry.word1);
895 if ^io_status_word.t then do;
896 chantab.no_io_terminate = chantab.no_io_terminate + 1;
897 call unlock;
898 return;
899 end;
900 end;
901 call check_stat; /* Go process the status. */
902 call unlock; /* Clear data base lock. */
903
904 if post_sw then /* If posting previous operation ... */
905 call post;
906 end;
907
908 else /* If status for IOI channel ... */
909 call ioi_masked$interrupt ((chantab.ioi_ctx), level, stat);
910
911 return; /* And return to caller. */
912
913 check_special_stat:
914 proc;
915
916 io_special_status_ptr = addr (stat); /* base our templates */
917 if ^io_special_status.t then
918 return;
919
920 dev = fixed (io_special_status.device, 6); /* Extract device address from status. */
921 if dev = 0 & disktab.first_dev ^= 0 then /* If special for disk controller ... */
922 go to ioi_special; /* Perhaps IOI wants this one, but we don't. */
923 if dev > disktab.last_dev then
924 return; /* Ignore this if number out-of-bounds. */
925
926 dp = addr (disktab.devtab (dev)); /* Get pointer to device info structure. */
927 pdi = devtab.pdi; /* Get PDI. */
928
929 pvtx = devtab.pvtx; /* Get index to PVT entry for device. */
930 if pvtx = 0 then
931 return; /* This will occur when an MPC broadcasts
932* a special interrupt status to all LA's attached to
933* it, and the MPC controls more than one
934* subsystem as seen by the PVT. */
935 pvtep = addr (pvt_array (pvtx)); /* Get pointer to PVT entry. */
936
937 if pvte.storage_system then do; /* If storage system volume ... */
938 call lock (addr (disktab.int_lock_meters)); /* Lock disk database. */
939
940 dp = addr (disktab.devtab (pdi));
941 if /* case */ devtab.broken then do; /* If device declared broken ... */
942 call syserr (ANNOUNCE, "^a: Placing ^a in operation.", ME, disk_name (BOTH));
943 call set_pvte_inop (OFF); /* Let ops get through */
944 devtab.inop = "1"b; /* Promote to inoperative state. */
945 devtab.was_broken = "1"b; /* .. */
946 devtab.broken = "0"b; /* Attempt to use device again. */
947 end;
948
949 else if devtab.inop then do; /* If device is inoperative ... */
950 devtab.inop = "0"b; /* Attempt to place back in operation. */
951 disktab.dev_busy = disktab.dev_busy & ^dev_mask (pdi);
952 end;
953
954 call call_run (sx); /* Force run call on special interrupt. */
955
956 call unlock; /* Undo the lock now. */
957 end;
958
959 else do; /* If not storage system volume ... */
960 ioi_special:
961 call ioi_masked$interrupt ((chantab.ioi_ctx), level, stat);
962 end; /* Pass on the status to IOI. */
963
964 return;
965
966 end check_special_stat;
967
968 /* Pick up and examine the status. */
969
970 check_stat:
971 procedure;
972
973 errcd = 0; /* Clear the error code */
974 erfp = addr (errcd);
975 post_sw = "0"b; /* Clear posting required flag. */
976
977 if ^chantab.active then do; /* If channel wasn't active, whisper bloody murder. */
978 chantab.terminate_not_active = chantab.terminate_not_active + 1;
979 call syserr (JUST_LOG, "^a: Unexpected IOM status ^24.3b for ^a (channel ^a).", ME,
980 string (io_status_word), disk_data.name (sx), chantab.chanid);
981 return;
982 end;
983
984 status_time = clock ();
985
986 qrp = chantab.qrp; /* Get pointer to queue entry. */
987 qp = ptr (disksp, qrp);
988 dev = quentry.dev; /* Extract device address from queue entry. */
989 pdi = quentry.pdi; /* Get PDI for this request. */
990 coreadd = bin (quentry.coreadd, 24); /* Get memory address. */
991 pvtx = quentry.pvtx; /* Get PVT index. */
992 sect_sw = sector_map (quentry.type);
993 bootload_sw = bootload_map (quentry.type);
994