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 disk_control:
136 proc;
137
138 dcl a_pvtx fixed bin;
139 dcl a_coreadd fixed bin (24);
140 dcl a_devadd bit (18) aligned;
141 dcl a_intrpt fixed bin (1);
142 dcl a_queue_length fixed bin;
143 dcl a_sect_off fixed bin (4);
144 dcl a_n_sectors fixed bin;
145
146 dcl pvtx fixed bin;
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
153
154 dcl bootload_sw bit (1) aligned;
155 dcl call_run_sx fixed bin;
156 dcl channel_time fixed bin (52);
157 dcl command bit (6) aligned;
158 dcl cylinder fixed bin (12);
159 dcl dcdcwp ptr;
160 dcl dddcwp ptr;
161 dcl dev unsigned fixed bin (6);
162 dcl devadd fixed bin (18);
163 dcl dev_count fixed bin;
164 dcl entry_time fixed bin (52);
165 dcl errcd fixed bin (35);
166 dcl i fixed bin;
167 dcl intrpt bit (1);
168 dcl io_type fixed bin;
169 dcl lcp ptr;
170 dcl level fixed bin (3);
171 dcl majstat fixed bin (5);
172 dcl mask fixed bin (71) aligned;
173 dcl masked bit (1);
174 dcl meter_start_time fixed bin (52);
175 dcl name_rel fixed bin (17);
176 dcl pdi fixed bin (6) unsigned;
177 dcl post_sw bit (1) aligned;
178 dcl ptp ptr;
179 dcl qrp bit (18) aligned;
180 dcl qx fixed bin (8);
181 dcl required bit (1) aligned;
182 dcl sector fixed bin (21);
183 dcl sect_sw bit (1);
184 dcl stat bit (36) aligned;
185 dcl status_time fixed bin (52);
186 dcl sx fixed bin (8);
187 dcl sysc fixed bin;
188 dcl substat bit (6) aligned;
189 dcl temp_time fixed bin (52);
190 dcl usurped bit (1) aligned;
191 dcl wait_time fixed bin (52);
192
193 dcl 1 msg_buf like io_msg aligned;
194
195 dcl 1 stat_entry like io_status_entry;
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
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
229 DISK_POLLING_TIME fixed bin (35) init (2000000),
230
231 INOP_POLLING_TIME fixed bin (35) init (5000000),
232
233 BROKEN_POLLING_TIME fixed bin (35) init (180000000),
234
235 CHANNEL_POLLING_TIME fixed bin (35) init (60000000)
236
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 ^L
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 ^L
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 ^L
359
360
361
362
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);
378 coreadd = a_coreadd;
379
380 sect_off = a_sect_off;
381 n_sectors = a_n_sectors;
382 goto go_masked;
383
384
385 test_drive:
386 entry (a_pvtx);
387
388 io_type = TEST;
389 coreadd = bin (RESET_STATUS, 24);
390 goto go_test;
391
392
393
394 unload_drive:
395 entry (a_pvtx);
396
397 io_type = TEST;
398 coreadd = bin (UNLOAD, 24);
399 go_test:
400 sect_off = 0;
401 n_sectors = 0;
402 devadd = 0;
403
404
405
406 go_masked:
407 call pmut$wire_and_mask (mask, ptp);
408 masked = "1"b;
409 intrpt = "0"b;
410 goto go_common;
411
412
413
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;
427 devadd = bin (a_devadd, 18);
428 coreadd = a_coreadd;
429 sect_off = 0;
430 n_sectors = 0;
431 if a_intrpt ^= 0 then
432 intrpt = "1"b;
433 else intrpt = "0"b;
434 ^L
435
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
444 pvtdip = addr (pvte.dim_info);
445 sx = pvtdi.sx;
446 call setup;
447 call lock (addr (disktab.call_lock_meters));
448
449 dev = pvte.logical_area_number;
450 pdi = disktab.devtab (dev).pdi;
451 dp = addr (disktab.devtab (pdi));
452
453
454
455 if devtab.abandoned then do;
456 errcd = 0;
457 if ^write_map (io_type) then do;
458 erfp = addr (errcd);
459 errflags.device_inoperative = "1"b;
460 end;
461 call unlock;
462 call post;
463 go to call_exit;
464 end;
465
466
467
468 disktab.alloc_wait_meters.count = disktab.alloc_wait_meters.count + 1;
469 if ^get_free_q () then do;
470 call lock_meter_start (addr (disktab.alloc_wait_meters));
471 do while (^get_free_q ());
472 call call_run (sx);
473 end; Note
474 call lock_meter_stop (addr (disktab.alloc_wait_meters));
475 end;
476
477
478
479
480 if pvte.is_sv then do;
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);
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;
488
489
490
491 quentry.intrpt = intrpt;
492 quentry.used = "1"b;
493 quentry.type = io_type;
494 quentry.coreadd = bit (coreadd, 24);
495
496 quentry.pvtx = a_pvtx;
497 quentry.pdi = pdi;
498 quentry.dev = dev;
499 quentry.cylinder = cylinder;
500
501 quentry.n_sectors = n_sectors;
502 quentry.sector = bit (sector, 21);
503
504
505
506 quentry.time = entry_time;
507 ^L
508
509
510
511 if ^(disktab.dev_busy | disktab.dev_queued) & dev_mask (pdi) then
512 do i = 1 to disktab.nchan;
513 cp = addr (ptr (disksp, disktab.channels) -> disk_channel_table (i));
514
515 if chantab.in_use & ^chantab.active then do;
516 call gotwork;
517 go to working;
518 end;
519 end;
520
521 call add_wq;
522
523
524
525 working:
526 call unlock;
527
528 call_exit:
529 if masked then
530 call pmut$unwire_unmask (mask, ptp);
531
532 return;
533 ^L
534
535
536 esd_reset_locks:
537 entry;
538
539 disksp = addr (disk_seg$);
540
541 unspec (disk_data.free_q) = "0"b;
542 disk_data.free_q.depth = disk_data.free_q_size;
543
544
545
546
547
548
549 unspec (disk_data.lock) = unspec (disk_data.lock) & "0"b;
550
551 do qx = 1 to disk_data.free_q_size;
552 qp = addr (disk_data.free_q_entries (qx));
553 qrp = rel (qp);
554
555 call add_free_q;
556 end;
557
558 do sx = 1 to disk_data.subsystems;
559 call setup;
560 call unlock;
561
562 call lock (addr (disktab.call_lock_meters));
563
564 do dev = disktab.first_dev to disktab.last_dev;
565
566 dp = addr (disktab.devtab (dev));
567 devtab.broken, devtab.was_broken, devtab.inop = "0"b;
568
569 devtab.cylinder = 0;
570 unspec (devtab.wq) = "0"b;
571
572
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);
581 do i = 1 to disktab.nchan;
582 cp -> disk_channel_table (i).active = "0"b;
583
584 cp -> disk_channel_table (i).inop = "0"b;
585
586 cp -> disk_channel_table (i).broken = "0"b;
587
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;
594 end;
595
596 disktab.dev_busy = "0"b;
597 disktab.dev_queued = "0"b;
598
599 call run;
600 call unlock;
601 end;
602
603 return;
604 ^L
605
606
607 usurp_channel:
608 entry (a_sx, a_chx, a_required, a_iom_chx, a_statusp);
609
610 dcl a_sx fixed bin (8);
611 dcl a_chx fixed bin (35);
612 dcl a_required bit (1) aligned;
613
614 dcl chx fixed bin (35);
615
616 sx = a_sx;
617 required = a_required;
618 chx = a_chx;
619 call setup;
620 cp = addr (ptr (disksp, disktab.channels) -> disk_channel_table (chx));
621
622
623 call pmut$wire_and_mask (mask, ptp);
624 call lock (addr (disktab.call_lock_meters));
625
626 usurped = (required | ^(chantab.broken | chantab.inop)) &
627
628 ((disktab.channels_online > 1) | ^chantab.in_use
629 | (ioi_masked$online_device_count (disk_data.name (sx)) = 0));
630
631
632 if usurped then do;
633 if chantab.in_use then
634 disktab.channels_online = disktab.channels_online - 1;
635 chantab.in_use = "0"b;
636 chantab.broken, chantab.inop = "0"b;
637 end;
638
639 call unlock;
640 call pmut$unwire_unmask (mask, ptp);
641
642 if usurped then do;
643 do while (chantab.active);
644 end;
645 a_iom_chx = chantab.chx;
646 a_statusp = chantab.statusp;
647 chantab.ioi_use = "1"b;
648 end;
649 else do;
650 a_iom_chx = 0;
651 a_statusp = null ();
652 end;
653
654 return;
655 ^L
656 cede_channel:
657 entry (a_sx, a_chx, a_iom_chx, a_statusp);
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;
666 chx = a_chx;
667 iom_chx = a_iom_chx;
668 statusp = a_statusp;
669 call setup;
670 cp = addr (ptr (disksp, disktab.channels) -> disk_channel_table (chx));
671
672
673 chantab.chx = iom_chx;
674 chantab.statusp = statusp;
675 chantab.ioi_use = "0"b;
676 chantab.in_use = "1"b;
677 disktab.channels_online = disktab.channels_online + 1;
678
679 return;
680 ^L
681
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 ^L
707
708
709 disk_run:
710 entry;
711
712 entry_time = clock ();
713
714 disksp = addr (disk_seg$);
715
716 do sx = 1 to disk_data.subsystems;
717 call setup;
718 call lock (addr (disktab.run_lock_meters));
719 call run;
720 call unlock;
721 end;
722
723 return;
724
725
726
727
728
729 call_run:
730 entry (a_sx);
731
732
733 entry_time = clock ();
734
735 sx = a_sx;
736 call setup;
737 call run;
738
739
740
741 call_run_sx = a_sx;
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
747 call run;
748 call unlock;
749 end;
750 end;
751 end;
752 sx = call_run_sx;
753 call setup;
754 return;
755 ^L
756
757
758 run:
759 proc;
760
761
762
763 do i = 1 to disktab.nchan;
764 cp = addr (ptr (disksp, disktab.channels) -> disk_channel_table (i));
765
766
767 if chantab.inop & ^chantab.in_use then
768 if clock () - chantab.connect_time > CHANNEL_POLLING_TIME then do;
769 chantab.in_use = "1"b;
770 disktab.channels_online = disktab.channels_online + 1;
771 end;
772
773
774
775
776
777
778
779
780
781
782 if ^chantab.active then
783 call getwork;
784
785 else do;
786 status_time = clock ();
787 io_status_entry_ptr = addr (stat_entry);
788 call io_manager$get_status ((chantab.chx), io_status_entry_ptr);
789
790 io_status_word_ptr = addr (stat_entry.word1);
791 if io_status_word.t then do;
792 chantab.status_from_run = chantab.status_from_run + 1;
793 level = 3;
794 call check_stat;
795
796 if post_sw then do;
797 call unlock;
798 call post;
799 call lock (addr (disktab.call_lock_meters));
800
801 end;
802 end;
803
804 else if chantab.connect_time + DISK_POLLING_TIME < status_time then do;
805
806 idcwp = addr (chantab.scdcw);
807 dev = fixed (idcw.device, 6);
808 pdi = disktab.devtab (dev).pdi;
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);
817 end;
818 end;
819 end;
820
821
822
823
824 do dev = disktab.first_dev to disktab.last_dev;
825 pdi = disktab.devtab (dev).pdi;
826 if pdi = dev then do;
827 dp = addr (disktab.devtab (pdi));
828
829 if devtab.inop then
830 if clock () - devtab.time_inop > INOP_POLLING_TIME then do;
831 disktab.dev_busy = disktab.dev_busy & ^dev_mask (pdi);
832 end;
833 else ;
834
835 else if devtab.broken then
836 if clock () - devtab.time_inop > BROKEN_POLLING_TIME then do;
837 devtab.inop = "1"b;
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;
842 end;
843 else ;
844 end;
845 end;
846
847 return;
848
849
850 end run;
851 ^L
852
853
854 disk_inter:
855 entry (idx, ilevel, istat);
856
857 dcl idx fixed bin (35),
858 istat bit (36) aligned,
859 ilevel fixed bin (3);
860
861 dcl int_idx fixed bin (35);
862
863 int_idx = idx;
864 sx = divide (int_idx, dskdcl_chans_per_subsys, 17, 0);
865
866 call setup;
867
868 i = int_idx - sx * dskdcl_chans_per_subsys + 1;
869 cp = addr (ptr (disksp, disktab.channels) -> disk_channel_table (i));
870
871 level = ilevel;
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;
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;
889 call lock (addr (disktab.int_lock_meters));
890 io_status_entry_ptr = addr (stat_entry);
891 unspec (io_status_entry) = ""b;
892 if level = 3 then do;
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;
902 call unlock;
903
904 if post_sw then
905 call post;
906 end;
907
908 else
909 call ioi_masked$interrupt ((chantab.ioi_ctx), level, stat);
910
911 return;
912 ^L
913 check_special_stat:
914 proc;
915
916 io_special_status_ptr = addr (stat);
917 if ^io_special_status.t then
918 return;
919
920 dev = fixed (io_special_status.device, 6);
921 if dev = 0 & disktab.first_dev ^= 0 then
922 go to ioi_special;
923 if dev > disktab.last_dev then
924 return;
925
926 dp = addr (disktab.devtab (dev));
927 pdi = devtab.pdi;
928
929 pvtx = devtab.pvtx;
930 if pvtx = 0 then
931 return;
932
933
934
935 pvtep = addr (pvt_array (pvtx));
936
937 if pvte.storage_system then do;
938 call lock (addr (disktab.int_lock_meters));
939
940 dp = addr (disktab.devtab (pdi));
941 if devtab.broken then do;
942 call syserr (ANNOUNCE, "^a: Placing ^a in operation.", ME, disk_name (BOTH));
943 call set_pvte_inop (OFF);
944 devtab.inop = "1"b;
945 devtab.was_broken = "1"b;
946 devtab.broken = "0"b;
947 end;
948
949 else if devtab.inop then do;
950 devtab.inop = "0"b;
951 disktab.dev_busy = disktab.dev_busy & ^dev_mask (pdi);
952 end;
953
954 call call_run (sx);
955
956 call unlock;
957 end;
958
959 else do;
960 ioi_special:
961 call ioi_masked$interrupt ((chantab.ioi_ctx), level, stat);
962 end;
963
964 return;
965
966 end check_special_stat;
967 ^L
968
969
970 check_stat:
971 procedure;
972
973 errcd = 0;
974 erfp = addr (errcd);
975 post_sw = "0"b;
976
977 if ^chantab.active then do;
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;
987 qp = ptr (disksp, qrp);
988 dev = quentry.dev;
989 pdi = quentry.pdi;
990 coreadd = bin (quentry.coreadd, 24);
991 pvtx = quentry.pvtx;
992 sect_sw = sector_map (quentry.type);
993 bootload_sw = bootload_map (quentry.type);
994
995 pvtep = addr (addr (pvt$array) -> pvt_array (pvtx));
996
997 dp = addr (disktab.devtab (pdi));
998
999
1000
1001
1002 io_type = quentry.type;
1003
1004
1005
1006
1007 if level = 3 then do;
1008 chantab.active = "0"b;
1009 disktab.dev_busy = disktab.dev_busy & ^dev_mask (pdi);
1010
1011
1012
1013
1014 if chantab.rsr then do;
1015 if (string (io_status_word) & disk_data.status_mask) then
1016
1017 chantab.rsr = "0"b;
1018 unspec (io_status_entry.detailed_status (*)) = unspec (chantab.detailed_status (*));
1019
1020
1021 io_status_word_ptr = addr (chantab.status);
1022
1023 command = chantab.command;
1024 call extract_status;
1025 call handle_error;
1026
1027 chantab.rsr = "0"b;
1028 end;
1029 ^L
1030
1031
1032 else if string (io_status_word) & disk_data.status_mask then do;
1033 call extract_status;
1034 call interpret_status;
1035 call get_disk_command;
1036
1037 if disk_error_interp.rsr & (io_status_entry.detailed_status (1) = ""b) then do;
1038
1039 chantab.rsr = "1"b;
1040 chantab.status = string (io_status_word);
1041
1042 chantab.action_code = io_status_entry.action_code;
1043 chantab.command = command;
1044
1045 idcwp = addr (chantab.dscdcw);
1046 idcw.device = bit (dev);
1047 call connect (idcwp);
1048 end;
1049
1050 else
1051 call handle_error;
1052 end;
1053 ^L
1054
1055
1056 else if io_status_entry.tally_residue ^= 0 then do;
1057 majstat = 20;
1058 substat = ANY;
1059 call handle_error;
1060 end;
1061
1062
1063
1064 else do;
1065 post_sw = "1"b;
1066
1067 if io_status_word.sub & "010011"b then do;
1068
1069 disktab.edac_errors = disktab.edac_errors + 1;
1070
1071 if io_status_word.sub & "010000"b then
1072
1073 majstat = 22;
1074 else
1075 majstat = 21;
1076 substat = ANY;
1077 call interpret_status;
1078 call get_disk_command ();
1079 call printerr;
1080 end;
1081
1082 devtab.inop = "0"b;
1083
1084 if devtab.was_broken | devtab.broken then do;
1085
1086 devtab.was_broken = "0"b;
1087 devtab.broken = "0"b;
1088 call set_pvte_inop (OFF);
1089 call syserr (ANNOUNCE, "^a: ^a now operational.", ME, disk_name (BOTH));
1090 end;
1091 chantab.inop = "0"b;
1092 end;
1093
1094 end;
1095 ^L
1096
1097
1098 else if level = 1 then do;
1099 chantab.active = "0"b;
1100 disktab.dev_busy = disktab.dev_busy & ^dev_mask (pdi);
1101
1102 majstat = 19;
1103 substat = ANY;
1104 call handle_error;
1105 end;
1106
1107
1108 else return;
1109 ^L
1110
1111
1112 if post_sw then do;
1113 if io_type = TEST then do;
1114 pvte.testing = "0"b;
1115 post_sw = "0"b;
1116 end;
1117 else do;
1118 status_time = clock ();
1119 channel_time = status_time - chantab.connect_time;
1120
1121 wait_time = status_time - quentry.time;
1122
1123 optp = addr (devtab.opt_info (quentry.type));
1124
1125
1126 opt_info.channel_wait = opt_info.channel_wait + channel_time;
1127 opt_info.queue_wait = opt_info.queue_wait + wait_time;
1128
1129
1130
1131 if errcd ^= 0
1132 then
1133 disktab.ferrors = disktab.ferrors + 1;
1134 end;
1135
1136 call add_free_q;
1137 end;
1138
1139 if ^chantab.active then
1140 call getwork;
1141
1142 return;
1143 ^L
1144
1145
1146 extract_status:
1147 proc;
1148
1149 if io_status_word.power then do;
1150 majstat = 16;
1151 substat = ANY;
1152 end;
1153 else if io_status_word.channel_stat then do;
1154 majstat = 17;
1155 substat = io_status_word.channel_stat;
1156 end;
1157 else if io_status_word.central_stat then do;
1158 majstat = 18;
1159 substat = io_status_word.central_stat;
1160 end;
1161 else do;
1162 majstat = bin (io_status_word.major, 4);
1163 substat = io_status_word.sub;
1164 end;
1165
1166
1167 end extract_status;
1168
1169
1170
1171
1172
1173 interpret_status:
1174 proc;
1175
1176
1177 dedp = addr (disk_error_data$);
1178 if pvte.is_sv then
1179 dskerap = addrel (dedp, disk_error_data (majstat).finterp);
1180 else dskerap = addrel (dedp, disk_error_data (majstat).interp);
1181
1182
1183 name_rel = fixed (rel (addrel (dedp, disk_error_data (lbound (disk_error_data, 1)).namep)), 17);
1184 dskerp = addr (disk_status_interp_array (lbound (disk_status_interp_array, 1)));
1185 do i = lbound (disk_status_interp_array, 1) by 1 while (bin (rel (dskerp), 18) < name_rel);
1186 dskerp = addr (disk_status_interp_array (i));
1187 if (substat & disk_error_interp.bitmask) = disk_error_interp.bitson then
1188 return;
1189 end;
1190
1191
1192 end interpret_status;
1193
1194
1195
1196
1197
1198 get_disk_command:
1199 proc;
1200
1201 idcwp = addrel (diskp, bin (io_status_entry.next_lpw_offset, 18) - disktab.abs_mem_addr - 1);
1202
1203 do while (idcw.code ^= IDCW);
1204 idcwp = addrel (idcwp, -1);
1205 end;
1206 command = idcw.command;
1207
1208
1209 end get_disk_command;
1210 ^L
1211
1212
1213 printerr:
1214 proc;
1215
1216 dcl type fixed bin;
1217 dcl record_address fixed bin (18);
1218 dcl mjsdp ptr;
1219 dcl ssdp ptr;
1220 dcl imu_detailed_status (0:23) bit (8) based;
1221 dcl logical_rec_addr fixed bin (17);
1222 dcl logical_sector fixed bin (21);
1223 dcl sector_offset fixed bin (17);
1224
1225 if devtab.broken then
1226 return;
1227
1228 sector = bin (chantab.select_data.sector);
1229 type = pvte.device_type;
1230 pvtdip = addr (pvte.dim_info);
1231 record_address =
1232 divide (sector - (divide (sector, sect_per_cyl (type), 17, 0) * pvtdi.unused_sect_per_cyl),
1233 sect_per_rec (type), 17, 0);
1234
1235 if pvte.is_sv then do;
1236 record_offset = mod (record_address, pvte.records_per_cyl);
1237 logical_rec_addr =
1238 divide ((record_address - pvte.record_factor - record_offset), pvte.num_of_svs, 17)
1239 + record_offset;
1240 sector_offset = mod (sector, sect_per_cyl (type));
1241 logical_sector =
1242 divide ((sector - (pvte.sv_num * sect_per_cyl (type)) - sector_offset), pvte.num_of_svs, 17)
1243 + sector_offset;
1244 end;
1245 else do;
1246 logical_rec_addr = record_address;
1247 logical_sector = sector;
1248 end;
1249
1250
1251 if pvte.is_sv then
1252 mjsdp = addrel (dedp, disk_error_data (majstat).fnamep);
1253 else mjsdp = addrel (dedp, disk_error_data (majstat).namep);
1254 ssdp = addrel (dedp, disk_error_interp.namep);
1255
1256 unspec (msg_buf) = "0"b;
1257 io_msgp = addr (msg_buf);
1258 io_msg.level = bit (level, 3);
1259 io_msg.channel = chantab.chanid;
1260 io_msg.device = bit (dev);
1261 io_msg.type = chantab.action_code;
1262 io_msg.command = command;
1263 io_msg.status = string (io_status_word);
1264 io_msg.devname = disk_data.name (sx);
1265
1266 if devtab.broken | disk_error_interp.just_log then
1267 sysc = JUST_LOG;
1268 else if mod (chantab.erct, 5) = 1 then
1269 sysc = ANNOUNCE;
1270 else sysc = JUST_LOG;
1271 call syserr$binary (sysc, io_msgp, SB_disk_err, SBL_disk_err,
1272 "^a: ^a ^[^12.3b^1s^;^1s^a^] for ^a (channel ^a).^/^2-rec ^o, sect ^o, main ^o^[^/^2-subvol ^a, logical rec ^o, logical sect ^o^;^3s^]^[^/^2-detailed status:^24( ^2.4b^).^;^s^]",
1273 ME, mjsdp -> disk_status_descrip.chr, (level = 1), stat, ssdp -> disk_status_descrip.chr,
1274 disk_name (SINGLE), chantab.chanid, record_address, sector, coreadd, pvte.is_sv, pvte.sv_name,
1275 logical_rec_addr, logical_sector, (io_status_entry.detailed_status (1) ^= ""b),
1276 addr (io_status_entry.detailed_status) -> imu_detailed_status);
1277
1278 return;
1279
1280
1281 end printerr;
1282 ^L
1283
1284
1285 handle_error:
1286 proc;
1287
1288
1289 chantab.erct = chantab.erct + 1;
1290 disktab.errors = disktab.errors + 1;
1291
1292 call interpret_status;
1293 if io_type = TEST then
1294 idcwp = addr (chantab.rssdcw);
1295 else idcwp = addr (chantab.scdcw);
1296
1297 if ^(io_type = TEST & ^disk_error_interp.bad_path) then
1298 call printerr;
1299
1300 if chantab.erct <= disk_error_interp.max_retries & io_type ^= TEST then do;
1301 if disk_error_interp.reseek then do;
1302 idcwp = addr (chantab.rstdcw);
1303 idcw.device = bit (dev);
1304 call connect (idcwp);
1305 end;
1306 else do;
1307 if disk_error_interp.bad_path then do;
1308
1309 temp_time = clock ();
1310 do while (clock () < temp_time + 750000);
1311
1312 end;
1313 end;
1314 call connect (idcwp);
1315 end;
1316 end;
1317
1318 else if disk_error_interp.bad_dev then do;
1319 if devtab.inop | devtab.broken | io_type = TEST then do;
1320
1321 if ^devtab.broken then
1322 if quentry.type ^= TEST then
1323 call syserr (BEEP, "^a: ^a requires intervention.", ME, disk_name (SINGLE));
1324 devtab.broken = "1"b;
1325 call set_pvte_inop (ON);
1326 devtab.was_broken = "0"b;
1327 devtab.inop = "0"b;
1328 devtab.time_inop = clock (); Note
1329
1330 errflags.device_inoperative = "1"b;
1331 post_sw = "1"b;
1332 end;
1333
1334 else if tc_data$system_shutdown = 0 then do;
1335
1336 devtab.inop = "1"b;
1337 disktab.dev_busy = disktab.dev_busy | dev_mask (pdi);
1338
1339 devtab.time_inop = clock (); Note
1340 call add_wq;
1341 end;
1342
1343 else do;
1344 if quentry.type = TEST then
1345 call set_pvte_inop (ON);
1346 errflags.device_inoperative = "1"b;
1347 post_sw = "1"b;
1348 end;
1349 end;
1350 else if disk_error_interp.bad_addr then do;
1351 if write_map (quentry.type) then
1352 errflags.reassign_address = "1"b;
1353 else
1354 errflags.seg_unusable = "1"b;
1355 post_sw = "1"b;
1356 end;
1357
1358 else if disk_error_interp.bad_path then do;
1359 if chantab.inop then do;
1360 chantab.broken = "1"b;
1361 chantab.inop = "0"b;
1362 end;
1363 else do;
1364 chantab.inop = "1"b;
1365 chantab.connect_time = clock ();
1366 end;
1367
1368 if disktab.channels_online > 1 then do;
1369 call syserr (BEEP, "^a: Removing channel ^a.", ME, chantab.chanid);
1370 chantab.in_use = "0"b;
1371 disktab.channels_online = disktab.channels_online - 1;
1372 end;
1373 else do;
1374 if bootload_sw then do;
1375 errflags.all_paths_bad = "1"b;
1376 post_sw = "1"b;
1377 end;
1378 else if io_type = TEST then do;
1379 call set_pvte_inop (ON);
1380 if (tc_data$system_shutdown ^= 0) then do;
1381 post_sw = "1"b;
1382 errflags.device_inoperative = "1"b;
1383 errflags.all_paths_bad = "1"b;
1384 return;
1385 end;
1386
1387 end;
1388 else if tc_data$system_shutdown ^= 0 then do;
1389 errflags.device_inoperative = "1"b;
1390
1391 errflags.all_paths_bad = "1"b;
1392 post_sw = "1"b;
1393 end;
1394 else do;
1395 chantab.erct = 0;
1396 chantab.inop = "0"b;
1397 call connect (addr (chantab.scdcw));
1398 end;
1399
1400
1401
1402
1403 do i = 1 to disktab.nchan;
1404 lcp = addr (ptr (disksp, disktab.channels) -> disk_channel_table (i));
1405 if ^(lcp -> chantab.ioi_use) then do;
1406
1407 if (lcp -> chantab.connect_time + CHANNEL_POLLING_TIME < clock ())
1408 | post_sw then do;
1409
1410
1411 lcp -> chantab.broken = "0"b;
1412
1413 lcp -> chantab.inop = "0"b;
1414
1415 lcp -> chantab.erct = 0;
1416
1417 lcp -> chantab.active = "0"b;
1418
1419
1420 lcp -> chantab.in_use = "1"b;
1421
1422
1423 lcp -> chantab.connect_time = clock ();
1424 disktab.channels_online = disktab.channels_online + 1;
1425
1426 end;
1427 end;
1428 end;
1429 return;
1430 end;
1431
1432 post_sw = "0"b;
1433 call add_wq;
1434
1435
1436
1437
1438 do i = 1 to disktab.nchan;
1439 cp = addr (ptr (disksp, disktab.channels) -> disk_channel_table (i));
1440
1441 if chantab.in_use & ^chantab.active then do;
1442 call getwork;
1443 return;
1444 end;
1445 end;
1446 end;
1447 else if disk_error_interp.bad_mem then do;
1448 errflags.fatal_error = "1"b;
1449 errflags.memory_unusable = "1"b;
1450 post_sw = "1"b;
1451 end;
1452 else do;
1453 errflags.fatal_error = "1"b;
1454 post_sw = "1"b;
1455 end;
1456
1457 return;
1458
1459
1460 end handle_error;
1461
1462 end check_stat;
1463 ^L
1464
1465
1466 getwork:
1467 proc;
1468
1469 if ^chantab.in_use then
1470 return;
1471
1472 if ^disktab.dev_busy & disktab.dev_queued = "0"b then
1473 return;
1474
1475
1476
1477 do dev_count = lbound (disktab.devtab, 1) to hbound (disktab.devtab, 1);
1478 disktab.dev_index = disktab.dev_index + 1;
1479 if disktab.dev_index > hbound (disktab.devtab, 1) then
1480 disktab.dev_index = lbound (disktab.devtab, 1);
1481
1482 dev = disktab.dev_index;
1483 pdi = disktab.devtab (dev).pdi;
1484
1485 if ^disktab.dev_busy & dev_mask (pdi) then do;
1486
1487 dp = addr (disktab.devtab (pdi));
1488 if ^devtab.broken
1489 then
1490 if devtab.wq.depth > 0
1491 then do;
1492 qp = ptr (disksp, devtab.wq.head);
1493
1494
1495
1496
1497
1498 if devtab.wq.depth > 1 then
1499 if quentry.time >= (clock () - disk_data.stagnate_time) then
1500 call find_shortest_seek;
1501 else call comb;
1502
1503 call del_q;
1504 go to xfer_join;
1505 end;
1506 end;
1507 end;
1508
1509 return;
1510 ^L
1511
1512
1513 find_shortest_seek:
1514 proc;
1515
1516 dcl (
1517 best_seek,
1518 this_seek
1519 ) float bin (27),
1520 (
1521 best_pos_comb,
1522 best_neg_comb,
1523 this_comb
1524 ) fixed bin (35),
1525 best_qp ptr,
1526 best_neg_qp ptr,
1527 type fixed bin;
1528
1529 cylinder = devtab.cylinder;
1530 best_seek = 1.0e+30;
1531
1532
1533
1534
1535 seek_loop:
1536 type = quentry.type;
1537 this_seek = float (abs (quentry.cylinder - cylinder) * devtab.opt_info (type).multiplier);
1538 if this_seek = 0.0 then
1539 goto seek_on_cylinder;
1540
1541 if this_seek < best_seek then do;
1542 best_seek = this_seek;
1543 best_qp = qp;
1544 end;
1545
1546
1547
1548 qrp = quentry.next;
1549 if qrp = "0"b then
1550 goto seek_found;
1551
1552 qp = ptr (disksp, qrp);
1553 goto seek_loop;
1554
1555
1556 seek_found:
1557 qp = best_qp;
1558 seek_on_cylinder:
1559 qrp = rel (qp);
1560 return;
1561 ^L
1562
1563
1564
1565 comb:
1566 entry;
1567
1568 devtab.comb = devtab.comb + 1;
1569 cylinder = devtab.cylinder;
1570 best_pos_comb = 34359738367;
1571 best_neg_comb = -34359738367;
1572
1573
1574
1575
1576 comb_loop:
1577 if devtab.forward then
1578 this_comb = quentry.cylinder - cylinder;
1579 else this_comb = cylinder - quentry.cylinder;
1580
1581 if this_comb = 0 then
1582 goto seek_on_cylinder;
1583 else if this_comb > 0
1584 then do;
1585 if this_comb < best_pos_comb then do;
1586 best_pos_comb = this_comb;
1587 best_qp = qp;
1588 end;
1589 end;
1590 else do;
1591 if this_comb > best_neg_comb then do;
1592 best_neg_comb = this_comb;
1593 best_neg_qp = qp;
1594 end;
1595 end;
1596
1597 qrp = quentry.next;
1598 if qrp = "0"b then
1599 goto comb_found;
1600 qp = ptr (disksp, qrp);
1601 goto comb_loop;
1602
1603
1604 comb_found:
1605 if best_pos_comb ^= 34359738367 then
1606 qp = best_qp;
1607 else qp = best_neg_qp;
1608 qrp = rel (qp);
1609 return;
1610 end find_shortest_seek;
1611 ^L
1612
1613
1614
1615
1616
1617
1618
1619
1620 gotwork:
1621 entry;
1622
1623 xfer_join:
1624 if ^quentry.used then
1625 call syserr (CRASH, "^a: Queuing error.", ME);
1626
1627 chantab.qrp = rel (qp);
1628 chantab.erct = 0;
1629 chantab.reconnect_announce_time = 0;
1630
1631 dev = quentry.dev;
1632
1633 if quentry.type = TEST then do;
1634 idcwp = addr (chantab.rssdcw);
1635 idcw.command = substr (quentry.coreadd, 19, 6);
1636 idcw.device = bit (dev);
1637
1638
1639
1640 optp = addr (disktab.devtab (dev).opt_info (quentry.type));
1641 if bin (quentry.coreadd, 24) = 58 then
1642 opt_info.seek_sum = opt_info.seek_sum + 1;
1643
1644 else opt_info.seek_count = opt_info.seek_count + 1;
1645
1646
1647
1648 call connect (idcwp);
1649 end;
1650
1651 else do;
1652 dcdcwp = addr (chantab.dcdcw);
1653 dddcwp = addr (chantab.dddcw);
1654 idcwp = addr (chantab.scdcw);
1655
1656 idcw.device = bit (dev);
1657
1658 unspec (dcdcwp -> idcw) = "0"b;
1659 dcdcwp -> idcw.code = IDCW;
1660 dcdcwp -> idcw.ext_ctl = "1"b;
1661 if write_map (quentry.type) then
1662 dcdcwp -> idcw.command = WRITE;
1663 else dcdcwp -> idcw.command = READ;
1664
1665 dcdcwp -> idcw.ext = substr (quentry.coreadd, 1, length (idcw.ext));
1666
1667 dddcwp -> dcw.address = substr (quentry.coreadd, 7);
1668
1669 dcdcwp -> idcw.device = bit (dev);
1670
1671
1672
1673 chantab.select_data.sector = quentry.sector;
1674
1675 if idcw.command = seek_512 then do;
1676 if quentry.type = VTOC_READ | quentry.type = VTOC_WRITE then do;
1677 dddcwp -> dcw.tally = bit (bin (192, 12));
1678 chantab.select_data.limit = bit (bin (1, 12));
1679 end;
1680 else if quentry.type = PAGE_READ | quentry.type = PAGE_WRITE then do;
1681 dddcwp -> dcw.tally = bit (bin (1024, 12));
1682 chantab.select_data.limit = bit (bin (2, 12));
1683 end;
1684 else if sector_map (quentry.type) then do;
1685 dddcwp -> dcw.tally = bit (bin ((512 * quentry.n_sectors), 12));
1686 chantab.select_data.limit = bit (bin (quentry.n_sectors, 12));
1687 end;
1688 end;
1689 else do;
1690 if sector_map (quentry.type) then do;
1691 dddcwp -> dcw.tally = bit (bin (64 * quentry.n_sectors, 12));
1692
1693 chantab.select_data.limit = bit (bin (quentry.n_sectors, 12));
1694
1695 end;
1696 else do;
1697 dddcwp -> dcw.tally = bit (bin (1024, 12));
1698
1699 chantab.select_data.limit = bit (bin (16, 12));
1700
1701 end;
1702 end;
1703
1704 call connect (addr (chantab.scdcw));
1705
1706
1707
1708 optp = addr (disktab.devtab (dev).opt_info (quentry.type));
1709 cylinder = devtab.cylinder - quentry.cylinder;
1710 devtab.cylinder = quentry.cylinder;
1711
1712
1713
1714
1715
1716
1717 if cylinder > 0
1718 then
1719 devtab.forward = "0"b;
1720 else if cylinder < 0
1721 then
1722 devtab.forward = "1"b;
1723
1724 opt_info.seek_sum = opt_info.seek_sum + abs (cylinder);
1725 opt_info.seek_count = opt_info.seek_count + 1;
1726 end;
1727 end getwork;
1728 ^L
1729
1730
1731 connect:
1732 procedure (listp);
1733
1734 dcl listp ptr parameter;
1735 dcl 1 ima aligned like io_manager_arg;
1736
1737 ima.chx = chantab.chx;
1738 ima.pcw = ""b;
1739 ima.ptp = null ();
1740 ima.listp = listp;
1741 call io_manager$connect_abs (ima);
1742
1743 chantab.connects = chantab.connects + 1;
1744 chantab.active = "1"b;
1745 chantab.connect_time = clock ();
1746
1747 disktab.dev_busy = disktab.dev_busy | dev_mask (pdi);
1748
1749
1750 return;
1751
1752
1753 end connect;
1754
1755
1756
1757
1758
1759 post:
1760 proc;
1761
1762 if io_type = TEST then do;
1763
1764
1765 post_sw = "0"b;
1766 return;
1767 end;
1768
1769
1770 if sect_sw then
1771 if bootload_sw then
1772 call bootload_disk_post (coreadd, errcd);
1773 else call vtoc_interrupt (coreadd, errcd);
1774 else
1775 call page$done (coreadd, errcd);
1776
1777 post_sw = "0"b;
1778
1779 return;
1780
1781
1782 end post;
1783 ^L
1784
1785
1786 queue_length_given_pvtx:
1787 entry (a_pvtx, a_queue_length);
1788
1789 pvtep = addr (addr (pvt$array) -> pvt_array (a_pvtx));
1790
1791 pvtdip = addr (pvte.dim_info);
1792 sx = pvtdi.sx;
1793
1794 call setup;
1795
1796 dev = pvte.logical_area_number;
1797 pdi = disktab.devtab (dev).pdi;
1798 dp = addr (disktab.devtab (pdi));
1799
1800 a_queue_length = devtab.wq.depth;
1801
1802 return;
1803 ^L
1804
1805
1806
1807 tune:
1808 entry (a_op, a_ptr, reason, ec);
1809
1810 dcl a_op char (*);
1811 dcl a_ptr ptr;
1812 dcl reason char (*) varying;
1813 dcl ec fixed bin (35);
1814
1815 dcl stagnate_time fixed bin (35) based (cptr);
1816
1817 dcl response fixed bin (35);
1818 dcl load fixed bin;
1819 dcl cptr ptr;
1820 dcl op char (16);
1821
1822 %include disk_tune;
1823 %page;
1824 disksp = addr (disk_seg$);
1825 cptr = a_ptr;
1826 op = a_op;
1827
1828 if op = STAGNATE_TIME then do;
1829 if stagnate_time > 360000000 | stagnate_time < 0 then do;
1830 if stagnate_time < 0 then
1831 reason = "stagnate time must be >= 0";
1832 else reason = "stagname time must be <= 6 minutes";
1833 ec = error_table_$bad_arg;
1834 return;
1835 end;
1836 else disk_data.stagnate_time = a_ptr -> stagnate_time;
1837 end;
1838 else if op = SYS_TUNE then do;
1839 io_type = cptr -> sys_info_tune.type;
1840 if io_type < 0 | io_type > MAX_IO_TYPE then
1841 goto bad_io_type;
1842
1843 sysp = addr (disk_data.sys_info (io_type));
1844
1845 if cptr -> sys_info_tune.map > MAX_IO_TYPE then
1846 goto bad_map_type;
1847
1848
1849
1850 if cptr -> sys_info_tune.map >= 0 then
1851 sys_info.depth_map = rel (addr (disk_data.sys_info (cptr -> sys_info_tune.map)));
1852
1853
1854
1855 if cptr -> sys_info_tune.max_depth > 0 then
1856 sys_info.max_depth = float (cptr -> sys_info_tune.max_depth);
1857 end;
1858 else if op = OPT_TUNE then do;
1859 io_type = cptr -> opt_info_tune.type;
1860 if io_type < 0 | io_type > MAX_IO_TYPE then
1861 goto bad_io_type;
1862
1863 do sx = 1 to disk_data.subsystems;
1864 if cptr -> opt_info_tune.sub_sys = disk_data.array (sx).name then
1865 goto tune_sub_sys;
1866 end;
1867 goto bad_io_sub_sys;
1868
1869 tune_sub_sys:
1870 call setup;
1871 dev = cptr -> opt_info_tune.dev;
1872 if dev < lbound (disktab.devtab, 1) | dev > hbound (disktab.devtab, 1) then
1873 goto bad_io_dev;
1874
1875 pdi = disktab.devtab (dev).pdi;
1876 if pdi ^= dev then
1877 goto bad_io_dev;
1878
1879 response = cptr -> opt_info_tune.response;
1880 if response < 1 then
1881 goto response_range;
1882 load = cptr -> opt_info_tune.load;
1883
1884 optp = addr (disktab.devtab (pdi).opt_info (io_type));
1885 if load > 1 then do;
1886 opt_info.slope = float (response - 1) / float (load - 1);
1887 opt_info.intercept = float ((response * load) - 1) / float (load - 1);
1888 end;
1889 else do;
1890 opt_info.slope = 0.0;
1891 opt_info.intercept = float (response);
1892 end;
1893 end;
1894 else if op = RESET_SYS then do;
1895 do i = 0 to MAX_IO_TYPE;
1896 disk_data.sys_info (i).depth = 0;
1897 end;
1898 end;
1899 else if op = RESET_MAX then do;
1900 disk_data.max_depth_reset_time = clock ();
1901 disk_data.free_q.max_depth = 0;
1902 do i = 1 to disk_data.subsystems;
1903 diskp = ptr (disksp, disk_data.array (i).offset);
1904 disktab.wq.max_depth = 0;
1905 end;
1906 end;
1907 reason = "";
1908 ec = 0;
1909 return;
1910
1911 bad_io_type:
1912 reason = "invalid I/O type";
1913 ec = error_table_$bad_arg;
1914 return;
1915
1916 bad_map_type:
1917 reason = "invalid map I/O type";
1918 ec = error_table_$bad_arg;
1919 return;
1920
1921 bad_io_sub_sys:
1922 reason = "unknown subsystem";
1923 ec = error_table_$bad_arg;
1924 return;
1925
1926 bad_io_dev:
1927 reason = "invalid device number";
1928 ec = error_table_$bad_arg;
1929 return;
1930
1931 response_range:
1932 reason = "response value must be >= 1";
1933 ec = error_table_$bad_arg;
1934 return;
1935 ^L
1936
1937
1938 setup:
1939 proc;
1940
1941
1942 disksp = addr (disk_seg$);
1943 pvt_arrayp = addr (pvt$array);
1944 diskp = ptr (disksp, disk_data.offset (sx));
1945
1946 return;
1947
1948
1949 end setup;
1950
1951
1952
1953
1954
1955 disk_name:
1956 proc (both) returns (char (21) aligned);
1957
1958 dcl both bit (1) aligned;
1959 dcl pic99 pic "99";
1960 dcl this_name char (8);
1961 dcl other_name char (12);
1962 dcl other_dev fixed bin;
1963
1964
1965 if dev = pdi
1966 then
1967 other_dev = disktab.devtab (pdi).buddy;
1968 else other_dev = pdi;
1969
1970 this_name = disk_data.name (sx) || "_" || convert (pic99, dev);
1971 if other_dev = 0 then
1972 other_name = "";
1973 else other_name = " and " || disk_data.name (sx) || "_" || convert (pic99, other_dev);
1974
1975 if both
1976 then
1977 return (this_name || other_name);
1978 else return (this_name);
1979
1980
1981 end disk_name;
1982 ^L
1983
1984
1985
1986 lock:
1987 proc (lmp);
1988
1989 dcl 1 dlm like disk_lock_meters based (lmp) aligned,
1990
1991 lmp ptr;
1992
1993
1994 dlm.count = dlm.count + 1;
1995 if ^stacq (disktab.lock, pds$processid, UNLOCK) then do;
1996
1997 call lock_meter_start (lmp);
1998 do while (^stacq (disktab.lock, pds$processid, UNLOCK));
1999 end;
2000 call lock_meter_stop (lmp);
2001 end;
2002
2003 return;
2004
2005
2006 unlock:
2007 entry;
2008
2009 if ^stacq (disktab.lock, UNLOCK, disktab.lock) then
2010 ;
2011
2012 return;
2013
2014
2015 end lock;
2016
2017
2018
2019
2020
2021 lock_meter_start:
2022 proc (lmp);
2023
2024 dcl 1 dlm like disk_lock_meters based (lmp) aligned,
2025 lmp ptr;
2026
2027
2028 meter_start_time = clock ();
2029 dlm.waits = dlm.waits + 1;
2030
2031 return;
2032
2033
2034 lock_meter_stop:
2035 entry (lmp);
2036
2037 dlm.wait_time = dlm.wait_time + (clock () - meter_start_time);
2038
2039 return;
2040
2041
2042 end lock_meter_start;
2043 ^L
2044
2045
2046 get_free_q:
2047 proc returns (bit (1) aligned);
2048
2049 dcl type fixed bin;
2050
2051
2052
2053 do while (^stacq (disk_data.lock, pds$processid, UNLOCK));
2054 end;
2055
2056 qrp = disk_data.free_q.head;
2057 if qrp then do;
2058 qp = ptr (disksp, qrp);
2059 disk_data.free_q.head = quentry.next;
2060
2061
2062
2063 if disk_data.free_q.head = "0"b then
2064 disk_data.free_q.tail = "0"b;
2065 else ptr (disksp, quentry.next) -> quentry.prev = "0"b;
2066
2067
2068
2069 disk_data.free_q.sum = disk_data.free_q.sum + disk_data.free_q.depth;
2070 disk_data.free_q.depth = disk_data.free_q.depth + 1;
2071 if disk_data.free_q.depth > disk_data.free_q.max_depth then
2072 disk_data.free_q.max_depth = disk_data.free_q.depth;
2073 disk_data.free_q.count = disk_data.free_q.count + 1;
2074
2075 if ^stacq (disk_data.lock, UNLOCK, disk_data.lock) then
2076 ;
2077 return (SUCCESS);
2078 end;
2079 else do;
2080 if ^stacq (disk_data.lock, UNLOCK, disk_data.lock) then
2081 ;
2082 return (FAILURE);
2083 end;
2084 ^L
2085
2086
2087 add_free_q:
2088 entry;
2089
2090 quentry.used = "0"b;
2091
2092
2093
2094 do while (^stacq (disk_data.lock, pds$processid, UNLOCK));
2095 end;
2096
2097
2098
2099 if disk_data.free_q.tail ^= "0"b then
2100 ptr (disksp, disk_data.free_q.tail) -> quentry.next = qrp;
2101 else disk_data.free_q.head = qrp;
2102
2103 quentry.prev = disk_data.free_q.tail;
2104 disk_data.free_q.tail = qrp;
2105 quentry.next = "0"b;
2106
2107
2108
2109 disk_data.free_q.depth = disk_data.free_q.depth - 1;
2110
2111 if ^stacq (disk_data.lock, UNLOCK, disk_data.lock) then
2112 ;
2113 return;
2114 ^L
2115
2116
2117 add_wq:
2118 entry;
2119
2120
2121
2122
2123 disktab.dev_queued = disktab.dev_queued | dev_mask (pdi);
2124 if devtab.wq.tail ^= "0"b then
2125 ptr (disksp, devtab.wq.tail) -> quentry.next = qrp;
2126 else devtab.wq.head = qrp;
2127
2128 quentry.prev = devtab.wq.tail;
2129 quentry.next = "0"b;
2130 devtab.wq.tail = qrp;
2131
2132
2133
2134 devtab.wq.sum = devtab.wq.sum + devtab.wq.depth;
2135 devtab.wq.depth = devtab.wq.depth + 1;
2136 if devtab.wq.depth > devtab.wq.max_depth then
2137 devtab.wq.max_depth = devtab.wq.depth;
2138 devtab.wq.count = devtab.wq.count + 1;
2139
2140
2141
2142
2143 type = quentry.type;
2144 sysp = addr (disk_data.sys_info (type));
2145 do while (^stacq (disk_data.lock, pds$processid, UNLOCK));
2146 end;
2147 ptr (disksp, sys_info.depth_map) -> sys_info.depth = ptr (disksp, sys_info.depth_map) -> sys_info.depth + 1.0;
2148 optp = addr (devtab.opt_info (type));
2149 opt_info.depth = opt_info.depth + 1;
2150
2151
2152
2153 wq_common:
2154 sys_info.fraction =
2155 (sys_info.max_depth - ptr (disksp, sys_info.depth_map) -> sys_info.depth) / sys_info.max_depth;
2156 if sys_info.fraction < 0.0 then
2157 sys_info.fraction = 0.0;
2158 if ^stacq (disk_data.lock, UNLOCK, disk_data.lock) then
2159 ;
2160
2161
2162
2163
2164 opt_info.multiplier = (opt_info.intercept - float (opt_info.depth) * opt_info.slope) * sys_info.fraction;
2165 if opt_info.multiplier < 1.0 then
2166 opt_info.multiplier = 1.0;
2167 return;
2168 ^L
2169
2170
2171 del_q:
2172 entry;
2173
2174
2175
2176 if quentry.prev = "0"b then
2177 devtab.wq.head = quentry.next;
2178 else ptr (disksp, quentry.prev) -> quentry.next = quentry.next;
2179
2180 if quentry.next = "0"b then
2181 devtab.wq.tail = quentry.prev;
2182 else ptr (disksp, quentry.next) -> quentry.prev = quentry.prev;
2183
2184
2185
2186 devtab.wq.depth = devtab.wq.depth - 1;
2187 if devtab.wq.depth <= 0 then
2188 disktab.dev_queued = disktab.dev_queued & ^dev_mask (pdi);
2189
2190
2191
2192 type = quentry.type;
2193 sysp = addr (disk_data.sys_info (type));
2194 do while (^stacq (disk_data.lock, pds$processid, UNLOCK));
2195 end;
2196
2197
2198
2199 ptr (disksp, sys_info.depth_map) -> sys_info.depth =
2200 max (0.0, ptr (disksp, sys_info.depth_map) -> sys_info.depth - 1.0);
2201
2202 optp = addr (devtab.opt_info (type));
2203 opt_info.depth = opt_info.depth - 1;
2204 go to wq_common;
2205
2206 end get_free_q;
2207 ^L
2208
2209
2210
2211 set_pvte_inop:
2212 proc (setting);
2213
2214 dcl setting bit (1) aligned;
2215
2216
2217
2218
2219 call set (addr (addr (pvt$array) -> pvt_array (devtab.pvtx)));
2220
2221 if devtab.buddy ^= 0
2222 then
2223 call set (addr (addr (pvt$array) -> pvt_array (disktab.devtab (devtab.buddy).pvtx)));
2224
2225 set:
2226 proc (pvte_ptr);
2227
2228 dcl pvte_ptr ptr;
2229
2230
2231 if pvte_ptr -> pvte.device_inoperative & ^setting then do;
2232 pvte_ptr -> pvte.device_inoperative = "0"b;
2233 call pxss$notify (page_fault$disk_offline_event);
2234 end;
2235 else pvte_ptr -> pvte.device_inoperative = setting;
2236
2237 return;
2238
2239
2240 end set;
2241
2242 end set_pvte_inop;
2243 ^L
2244 %include device_error;
2245 %page;
2246 %include disk_error_interp;
2247 %page;
2248 %include dskdcl;
2249 %page;
2250 %include fs_dev_types;
2251 %page;
2252 %include io_manager_dcls;
2253 %page;
2254 %include io_special_status;
2255 %page;
2256 %include io_status_entry;
2257 %page;
2258 %include io_syserr_msg;
2259 %page;
2260 %include iom_dcw;
2261 %page;
2262 %include iom_pcw;
2263 %page;
2264 %include pvte;
2265 %page;
2266 %include syserr_binary_def;
2267 %page;
2268 %include syserr_constants;
2269 ^L
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361 Note
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391 Note
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442 end disk_control;