1 " ***********************************************************
2 " * *
3 " * Copyright, C Honeywell Bull Inc., 1987 *
4 " * *
5 " * Copyright, C Honeywell Information Systems Inc., 1982 *
6 " * *
7 " * Copyright c 1972 by Massachusetts Institute of *
8 " * Technology and Honeywell Information Systems, Inc. *
9 " * *
10 " ***********************************************************
11
12 " HISTORY COMMENTS:
13 " 1) change85-09-09Fawcett, approve85-09-09MCR6979,
14 " audit86-01-27CLJones, install86-03-21MR12.0-1033:
15 " Add support for dev 0 FIPS.
16 " 2) change86-05-29Fawcett, approve86-05-29MCR7383,
17 " audit86-05-30Coppola, install86-07-17MR12.0-1097:
18 " Add code for MSU3380 and MSU3390 support. This code supports the
19 " division of the devices into subvolumes. Also read 512 word sectors are
20 " supported by only doing 512_word seek command 30 oct. Multics will not
21 " support 64_seeks for these devices.
22 " 3) change86-09-10Farley, approve86-10-24MCR7544,
23 " audit86-10-27Fawcett, install86-10-28MR12.0-1200:
24 " Added change to properly shift the TEST I/O command in the A-reg before
25 " storing in chantab.rssdcw.
26 " END HISTORY COMMENTS
27
28 name dctl
29
30 " dctl - fast path for disk control, coded in ALM for obvious reasons
31 "
32 " Written sometime by someone possibly Mullen
33 " Modified by Fawcett 1979 for shared stack frames
34 " Modified back by Hornig December 1980
35 " Modified March 1981 by J. Bongiovanni to add entry queue_length_given_pvtx
36 " Modified July, 1981, WOS, to implement Mike Jordan's fix to the 501 sector number
37 " overflow problem too many sectors to represent in 20 bits.
38 " Modified February 1982 by C. Hornig for MR10 io_manager.
39 " Modified March 1982 by J. Bongiovanni to remove queue_length_given_pvtx
40 " moved to disk_control and for new PVTE
41 " Modified March 1982 by C. Hornig to unload disks.
42 " Modified July 1982 by J. Bongiovanni for read_sectors, write_sectors
43 " Modified April 1984 by T. Oke for system wide free_q.
44 " Modified April 1984 by T. Oke for dynamic channel table and the use of
45 " dskdcl_chans_per_subsys to define channel idx/subsystem relation.
46 " Modified May 1984 by T. Oke to add pvtx in queue entry for azm analysis
47 " of queue.
48 " Modified May 1984 by T. Oke to install adaptive optimization, modifying
49 " the quentry structure.
50 " Modified Nov 26,1984 by R. A. Fawcett to suppoer dev 0 fips.
51 " Modified February 1985 by Keith Loepere to re-install bootload_read/write
52 " which was broken by one of the above recently named.
53 " Modified April 1985 by R. A. Fawcett to support real 512 work IO for 3380's.
54 " Modified July 1985 by R. A. Fawcett to support sub-volumes on 3380/3390's
55 " ============================================================================
56
57 tempd int_arg_list
58 tempd meter_start_time,status_time,entry_time,test_time
59 tempd ptp,mask Used for pmut$wire_and_mask
60 tempd arglist3
61 tempd listp
62 tempd ima8
63 temp coreadd
64 temp sect_off,record_offset
65 temp devadd
66 temp errcd
67 temp real_device
68 temp sect_sw Uses upper bit sign to indicate sect
69 temp bootload_sw Ditto for bootload
70 temp sx Subsystem index in DL
71 temp pvtx
72 temp dev
73 temp sector
74 temp cylinder
75 temp io_type Io type stored in DL
76 temp masked Non-zero if call side running masked
77 temp intrpt Caller requested interrupt on complete
78 temp temp1
79 temp switches
80 temp best_seek Also is best_pos_comb
81 temp comb_qp DU has forward comb qp, DL has reverse
82 temp best_neg_comb
83 temp n_sectors,n_sectors_temp
84 "^L
85 entry disk_inter
86 entry disk_read
87 entry disk_write
88 entry bootload_read
89 entry bootload_write
90 entry read_sectors
91 entry write_sectors
92
93 " REGISTER USAGE:
94 " bb -> disk_seg base, disk_data
95 " bp -> disktab, per subsystem info
96 " ap -> chantabe
97 " lb -> pvte, DCW list, devtabe when opt_info access needed
98
99 " x0 = pdi
100 " x1 temp
101 " x2-> devtab
102 " x3-> quentry
103 " x4 temp
104 " x5 temp
105 " x6 call savex top level calls
106 " x7 calls lower level
107
108
109 " The ALM assembler must border on the least friendly assembler known
110 " to man. So some techniques are in force through this program to aid
111 " in the detection of error conditions due to movement of structure
112 " contents.
113
114 " Specifically there is quite a bit of use of the construction:
115 "
116 " equ quentry.coreadd_shift,0
117 "
118 " This construction will cause an error if the value of the shift is not
119 " zero, AS WE ARE PRESUMING IT TO BE. Thus we can produce fast code, with
120 " extra supurflous instructions removed, but still detect if they would be
121 " necessary if things move. Hopefully these little checks will do someone
122 " good in the future.
123
124 equ MUST_BE_ZERO,0 Used for 0 check
125 "^L
126 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
127 "
128 " CALL SIDE OF DISK DIM -- various entries
129 "
130 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
131
132 write_sectors:
133 push
134 ldx4 VTOC_WRITE,du
135 tra go_sector
136
137 read_sectors:
138 push
139 ldx4 VTOC_READ,du
140 tra go_sector
141
142 bootload_read:
143 push
144 ldx4 BOOTLOAD_READ,du
145 tra go_sector
146
147 bootload_write:
148 push
149 ldx4 BOOTLOAD_WRITE,du
150 tra go_sector
151
152 go_sector:
153 sxl4 io_type
154 lda ap|10,* pick up number of sectors
155 sta n_sectors
156 ldq ap|8,* pick up sect_off arg
157 stq sect_off
158 stz intrpt clear interrupt desired
159 ldq bootload_mapping,du " IO type still in x4
160 qls 0,x4
161 tpl go_vtoc
162 stz masked
163 tra go_common
164
165 " wire stack frame for vtoc_man
166
167 go_vtoc:
168 epplb mask
169 sprilb arglist+2
170 epplb ptp
171 sprilb arglist+4
172 ldaq two_args_nd
173 staq arglist
174 call pmut$wire_and_maskarglist
175 lda 1,dl
176 sta masked in masked environment
177 tra go_common
178
179
180 disk_write:
181 push
182 ldx4 PAGE_WRITE,du
183 tra go_page
184
185 disk_read:
186 push
187 ldx4 PAGE_READ,du
188
189 go_page:
190 sxl4 io_type
191 stz n_sectors
192 stz sect_off sect_off = 0
193 stz masked not in masked environment
194 stz intrpt
195 lda ap|8,* pick up priority arg
196 tze no_intrpt intrpt="0"b
197 lda quentry.intrpt,du intrpt=quentry.intrpt
198 no_intrpt:
199 sta intrpt
200
201 go_common: " Common command interface
202 lda ap|4,*
203 als 12 MASK FOR COREADD
204 arl 12
205 sta coreadd
206 lda ap|6,*
207 arl 18
208 sta devadd
209
210 rccl sys_info$clock_,* get entry time for stats
211 staq entry_time ^LGET PVTE for device
212
213 epplb pvt$array
214 ldq ap|2,* get pvtx
215 stq pvtx save for queue entry
216 mpy pvte_size,dl
217 epplb lb|-pvte_size,ql HENCEFORTH lb -> PVTE
218 lda lb|pvte.dim_info
219 arl pvtdi.sx_shift
220 sta sx
221 tsx7 setup
222
223 eax4 disktab.call_lock_meters specify lock reason
224 tsx7 lock
225
226 ldq lb|pvte.logical_area_number_word
227 qrl pvte.logical_area_number_shift
228 """"" anq pvte.logical_area_number_mask,dl This mask bigger than next
229 anq quentry.dev_mask,dl
230 stq dev device in sub-sys
231
232 ldx2 devtab_subs,ql subscript devtab
233 ldq bp|devtab.pdi_word,x2 devtab.pdi
234 equ devtab.pdi_shift,0 PRESUMED 0
235 """"" qrs devtab.pdi_shift
236 anq devtab.pdi_mask,dl
237 eax0 0,ql HENCEFORTH X0 = pdi
238 ldx2 devtab_subs,x0 subscript devtab
239 eax2 bp|0,x2 HENCEFORTH X2->devtab
240
241 " The following code is out, since we will try the abandoned device
242 " will get an error return, and it will be handled by disk_control
243 " error processing. Thus disk_control eventually finds out.
244
245 """"" lda bb|devtab.abandoned_word,x2
246 """"" cana devtab.abandoned,du
247 """"" tnz ABANDONED
248
249 " Allocate a quentry for this operation
250
251 aos bp|disktab.alloc_wait_meters+disk_lock_meters.count
252 tsx7 get_free_q HENCEFORTH X3->quentry
253 arg got_fq get_free_q success
254 "Failed to find free quentry. Call RUN.
255 eax4 disktab.alloc_wait_meters meter this time as alloc wait
256 tsx6 lock_meter_start
257 retry_get_fq:
258 tsx7 get_free_q
259 arg retry_got_fq
260 eppap sx
261 spriap arglist+2
262 ldaq one_arg_nd
263 staq arglist
264 call disk_control$call_runarglist
265 tra retry_get_fq
266
267
268 retry_got_fq:
269 eax4 disktab.alloc_wait_meters time metered as alloc wait
270 tsx6 lock_meter_stop ^LCompute cylinder and sector -- remember them in stack
271
272 got_fq: ldq devadd
273 lda lb|pvte.is_sv_word
274 cana pvte.is_sv,du
275 tze not_subvol " pvte does not define sv "
276 div lb|pvte.records_per_cyl
277 sta record_offset
278 ldq devadd
279 sblq record_offset
280 mpy lb|pvte.num_of_svs
281 adlq lb|pvte.record_factor
282 adlq record_offset
283 not_subvol:
284 lda lb|pvte.device_type_word
285 arl pvte.device_type_shift
286 ana pvte.device_type_mask,dl
287 eax1 0,al
288 mpy sec_per_rec,x1 " mpy by 16 for 64 word io and 2 for 512 word io
289 stq sector
290
291 lda lb|pvte.dim_info
292 ars pvtdi.usable_sect_per_cyl_shift
293 ana pvtdi.usable_sect_per_cyl_mask,dl
294 sta temp1
295 div temp1 into sector in Qreg
296 stq cylinder
297
298 ldq lb|pvte.dim_info
299 equ pvtdi.unused_sect_per_cyl_shift,0 PRESUMED = 0
300 """""" qrs pvtdi.unused_sect_per_cyl_shift
301 anq pvtdi.unused_sect_per_cyl_mask,dl
302 mpy cylinder
303 adq sect_off
304 asq sector
305
306 " Fill in quentry contents
307 " quentry.intrpt, used, type, coreadd
308 " PRESUMES that type,intrpt,used and coreadd are in the same quentry word.
309
310 equ quentry.type_word,1 All presumed in word 1
311 equ quentry.intrpt_word,1
312 equ quentry.used_word,1
313 equ quentry.coreadd_word,1
314 equ MUST_BE_ZERO,quentry.coreadd_shift
315
316 lda io_type
317 als quentry.type_shift get io_type of operation
318 ora intrpt Set interrupt flag
319 ora quentry.used,du indicate entry is used
320 ora coreadd presume shift is 0
321 sta bb|quentry.type_word,x3
322
323
324 " quentry.pvtx, pdi, dev, cylinder
325 " PRESUMES that pvtx,cylinder,dev and pdi are in the same quentry word.
326
327 equ quentry.pvtx_word,2 Presumed in word 2
328 equ quentry.pdi_word,2
329 equ quentry.dev_word,2
330 equ quentry.cylinder_word,2
331 equ MUST_BE_ZERO,quentry.cylinder_shift
332
333 lda pvtx
334 als quentry.pvtx_shift
335 ora cylinder presume cylinder shift is 0
336 sta bb|quentry.pvtx_word,x3
337 eaa 0,x0 pdi from X0
338 als quentry.pdi_shift-18
339 orsa bb|quentry.pdi_word,x3
340 lda dev
341 als quentry.dev_shift
342 orsa bb|quentry.dev_word,x3
343
344
345 " quentry.n_sectors, sector
346 " PRESUMES that n_sectors and sector are in the same quentry word.
347
348 equ quentry.n_sectors_word,3 Presume in word 3
349 equ quentry.sector_word,3
350 equ MUST_BE_ZERO,quentry.sector_shift
351
352 lda n_sectors
353 als quentry.n_sectors_shift
354 ora sector include sector number
355 sta bb|quentry.sector_word,x3
356
357 " Fill in queued time.
358
359 ldaq entry_time
360 staq bb|quentry.time,x3
361
362 "^L
363 "Provided the disk dim is functioning correctly on the interrupt side
364 "then if there are already requests queued for this device
365 "then there is no chance we can immediately issue a connect for this request.
366 "Therefore we merely queue the request and return.
367 "The same is true if the device is busy already.
368 "On the other hand if the device is neither busy nor has a queue already
369 "then if there is a free channel then we need not even add the quentry
370 "to the queue, but instead issue the connect forthwith.
371
372 " X3 -> quentry, X0 = pdi, X2 -> devtab pdi
373
374 ldaq bp|disktab.dev_busy
375 oraq bp|disktab.dev_queued
376 lls 0,x0 X0 has PDI ..
377 tmi call_side_queues this PDI is busy or queued
378
379 ldx4 bp|disktab.channels find dynamic table
380 eppap bb|0,x4 AP -> firstchantabe
381
382 lxl4 bp|disktab.nchan
383 tze call_side_queues no channels exist - queue it
384
385 ldaq channel_criteria bit and mask for testing
386 call_chan_loop:
387 cmk ap|chantab.in_use_word
388 tze call_side_connects channel available - use it
389 eppap ap|chantab_size try next channel
390 eax4 -1,x4 if there is another channel
391 tpnz call_chan_loop
392
393 " Add to existing work queue for device and fast return
394
395 call_side_queues: " io_type DL must be good
396 tsx7 add_wq
397 tra working
398
399 " Have channel and no queued requests for idle device - send it work
400
401 call_side_connects:
402 tsx7 gotwork
403 working: tsx7 unlock unlock and return
404 szn masked see if we are masked
405 tze unwired
406
407 " We are wired and must clear wiring before return
408
409 epplb mask
410 sprilb arglist+2
411 epplb ptp
412 sprilb arglist+4
413 ldaq two_args_nd
414 staq arglist
415 call pmut$unwire_unmaskarglist
416
417 unwired: return
418
419
420 "for ldaq/cmk above:A has bits desired, Q has 1bits to mask dont-care bits
421 "we require a channel which is in-use, and not-active
422
423 even
424 channel_criteria:
425 zero 0,chantab.in_use
426 zero -1,-chantab.in_use-chantab.active-1
427 "^L
428 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
429 "
430 " SETUP -- called with sx in Areg
431 " makes bb->disk_seg
432 " makes bp->devtab
433 "
434 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
435
436 setup: eppbb disk_seg$
437 als 1
438 eppbp bb|disk_data.array-2,al*
439 tra 0,7 setup returns
440
441
442
443 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
444 "
445 " LOCK -- locks bp->disktab ie a subsystem
446 " called with x4->metercells
447 "
448 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
449
450 lock: aos bp|disk_lock_meters.count,x4
451 lda pds$processid
452 stac bp|disktab.lock lock subsystem lock
453 tze 0,x7 lock ret1
454
455 tsx6 lock_meter_start
456 lda pds$processid
457 lockloop: stac bp|disktab.lock
458 tze lockgot
459 llr 72
460 llr 72
461 llr 72
462 llr 72
463 tra lockloop
464
465 lockgot: tsx6 lock_meter_stop
466 tra 0,x7 lock ret2
467
468 "
469 " LOCK_METER_START - called via X6, X4 must specify lock reason
470 "
471
472 lock_meter_start:
473 rccl sys_info$clock_,*
474 staq meter_start_time
475 aos bp|disk_lock_meters.waits,x4
476 tra 0,x6
477
478 "
479 " LOCK_METER_STOP -called via X6, X4 must specify lock reason
480 "
481
482 lock_meter_stop:
483 rccl sys_info$clock_,*
484 sbaq meter_start_time
485 adaq bp|disk_lock_meters.wait_time,x4
486 staq bp|disk_lock_meters.wait_time,x4
487 tra 0,x6
488
489 "
490 " UNLOCK -- unlocks bp->disktab
491 "
492
493 unlock: lda pds$processid DEBUG
494 cmpa bp|disktab.lock DEBUG
495 tze *+2
496 oct 04 DEBUG Die Die Die
497 eaa 0
498 ansa bp|disktab.lock
499 tra 0,x7 unlock ret
500 "^L
501 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
502 "
503 " GET_FREE_Q -- called with bp->disktab
504 " sets x3->quentry
505 " note indirect return if sucessful, direct if fail!!
506 "
507 " uses X4, X5, A
508 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
509
510 even
511
512 lock_disk_data.wait:
513 llr 72 Read/Alter/Rewrite delay
514 llr 72
515 llr 72
516 llr 72
517 lock_disk_data:
518 lda pds$processid
519 stac bb|disk_data.lock lock disk_data
520 tze 0,x4 return to caller
521 tra lock_disk_data.wait
522
523 " Unlock disk_data. Ensures write notification.
524
525 unlock_disk_data:
526 lda pds$processid DEBUG
527 cmpa bb|disk_data.lock DEBUG
528 tze *+2
529 oct 04 DEBUG Die Die Dia
530 eaa 0
531 ansa bb|disk_data.lock
532 tra 0,x4 unlock ret
533
534
535
536 get_free_q:
537 tsx4 lock_disk_data
538 ldx3 bb|disk_data.free_q+qht.head
539 tze gfq_bret bad unlock and return
540
541 ldx4 bb|quentry.next,x3 make head point to next
542 stx4 bb|disk_data.free_q+qht.head set head
543 tze gfq_kill_tail kill tail if no next
544 ldx5 0,du make an 18-bit zero
545 sxl5 bb|quentry.prev,x4 kill new head's prev
546 tra gfq_do_stats
547
548 gfq_kill_tail:
549 sxl4 bb|disk_data.free_q+qht.tail kill tail
550
551 " Compile statistics.
552
553 gfq_do_stats:
554 lxl5 bb|disk_data.free_q+qht.depth
555 eaa 0,x5
556 ars 18
557 asa bb|disk_data.free_q+qht.sum accumulate depth sum
558 adx5 1,du increment depth counter
559 sxl5 bb|disk_data.free_q+qht.depth
560 cmpx5 bb|disk_data.free_q+qht.max_depth
561 tmoz gfq_no_max_depth not maximum depth seen
562 stx5 bb|disk_data.free_q+qht.max_depth
563 gfq_no_max_depth:
564 aos bb|disk_data.free_q+qht.count
565
566 " unlock disk_data and return good
567
568 tsx4 unlock_disk_data
569 tra 0,x7*
570
571 gfq_bret: tsx4 unlock_disk_data unlock disk_data
572 tra 1,x7 gfq failure ret
573 "^L
574 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
575 "
576 " ADD_FREE_Q -- add X3->quentry to queue
577 "
578 " Uses X4, X5
579 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
580
581 even
582
583 add_free_q:
584 tsx4 lock_disk_data
585 lxl5 bb|disk_data.free_q+qht.tail X5->oldtail
586 tze afq_empty was none!
587 stx3 bb|quentry.next,x5 make old_tail -> new_tail
588 tra afq_any
589 afq_empty:
590 stx3 bb|disk_data.free_q+qht.head was empty, make new head
591
592 " make this entry's prev point to old tail
593
594 afq_any: sxl5 bb|quentry.prev,x3 set this prev to old tail
595 sxl3 bb|disk_data.free_q+qht.tail set tail ptr
596 eax5 0
597 stx5 bb|quentry.next,x3 make newtail's next->nil
598
599 " Account for returned element
600
601 lxl5 bb|disk_data.free_q+qht.depth subtract for return
602 sbx5 1,du
603 sxl5 bb|disk_data.free_q+qht.depth
604
605 tsx4 unlock_disk_data unlock disk_data
606 tra 0,x7 add_q ret
607 "^L
608 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
609 "
610 " ADD_WQ -- add X3->quentry to queue
611 "
612 " X2-> devtab pdi, X0 = pdi
613 " Uses X1, X4, X5, EAQ and lb
614 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
615
616 add_wq:
617 lda =o400000,du set requests queued for dev
618 ldq 0,du
619 lrl 0,x0
620 orsa bp|disktab.dev_queued
621 orsq bp|disktab.dev_queued+1
622
623 " add to work queue
624
625 lxl5 bb|devtab.wq+qht.tail,x2 X5->oldtail
626 tze aq_empty was none!
627 stx3 bb|quentry.next,x5 make old_tail -> new_tail
628 tra aq_any
629 aq_empty:
630 stx3 bb|devtab.wq+qht.head,x2 was empty, make new head
631
632 aq_any: sxl5 bb|quentry.prev,x3 set this prev to old tail
633 sxl3 bb|devtab.wq+qht.tail,x2 set tail ptr
634 eax5 0
635 stx5 bb|quentry.next,x3 make newtail's next->nil
636
637 " Compile statistics for queue loading.
638
639 lxl5 bb|devtab.wq+qht.depth,x2
640 eaa 0,x5
641 ars 18
642 asa bb|devtab.wq+qht.sum,x2 accumulate depth sum
643 adx5 1,du increment depth
644 sxl5 bb|devtab.wq+qht.depth,x2
645 cmpx5 bb|devtab.wq+qht.max_depth,x2
646 tmoz gq_no_max_depth not maximum depth seen
647 stx5 bb|devtab.wq+qht.max_depth,x2
648 gq_no_max_depth:
649 aos bb|devtab.wq+qht.count,x2
650
651 " compile system load stats. Presumes io_type DL is good.
652
653 tsx4 lock_disk_data ensure counter is ours
654 lxl1 io_type
655 ldx5 sys_info_subs,x1 x5 is sysp offset
656 ldx4 bb|sys_info.depth_map,x5 get mapped counter
657 fld bb|0,x4 increment depth
658 fad =1.0,du
659 fst bb|0,x4
660
661 " Produce sys_info.fraction. -float depth - max_depth/max_depth
662
663 fsb bb|sys_info.max_depth,x5
664 fneg
665 tpl gq_pos_fraction fraction is positive
666 fld =0.0,du limit to 0.0
667 gq_pos_fraction:
668 fdv bb|sys_info.max_depth,x5
669 fst bb|sys_info.fraction,x5
670 tsx4 unlock_disk_data clear disk_data lock^L
671 " Produce multiplier. -float depth * slope + intercept
672 " Final opt_info.multiplier is max 1.0 multiplier * sys_info.fraction
673
674 lxl4 opt_info_subs,x1 x4 is optp offset in devtab
675 epplb bb|0,x2 pointer to devtab
676 aos lb|opt_info.depth,x4 increment device depth
677
678 lda lb|opt_info.depth,x4
679 als 18 clear high stuff
680 lrs 72-18 float opt_info.depth
681 lde =71b25,du
682 fno
683 fmp lb|opt_info.slope,x4
684 fneg
685 fad lb|opt_info.intercept,x4
686 fmp bb|sys_info.fraction,x5 * fraction
687 fst lb|opt_info.multiplier,x4
688 fcmp =1.0,du max multiplier 1.0
689 tpl 0,x7 add_q return
690 fld =1.0,du
691 fst lb|opt_info.multiplier,x4 set to 1.0
692 tra 0,x7 add_q return
693 "^L
694 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
695 "
696 " DEL_Q -- called with x3->quentry
697 "
698 " Uses X1, X4, X5, EAQ, lb
699 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
700
701 del_q: ldx4 bb|quentry.next,x3 get next pointer
702 lxl5 bb|quentry.prev,x3 is if head is previous
703 tnz dq_mid
704 stx4 bb|devtab.wq+qht.head,x2 save new head
705 tra dq_head_done
706 dq_mid: stx4 bb|quentry.next,x5 set previous's next
707 dq_head_done:
708 cmpx4 0,du test zero/non-zero
709 tnz dq_not_tail
710 sxl5 bb|devtab.wq+qht.tail,x2 update tail
711 tra dq_tail_done
712 dq_not_tail:
713 sxl5 bb|quentry.prev,x4 update next's previous
714
715 " Compile queue loading statistics
716
717 dq_tail_done:
718 lxl5 bb|devtab.wq+qht.depth,x2 decrement current depth
719 sbx5 1,du
720 sxl5 bb|devtab.wq+qht.depth,x2
721 tpnz dq_with_queue
722 lda =o400000,du turn off device_queued bit
723 ldq 0,du
724 lrl 0,x0 X0 has PDI
725 eraq all_ones form mask
726 ansa bp|disktab.dev_queued
727 ansq bp|disktab.dev_queued+1
728
729 " compile system load stats.
730
731 dq_with_queue:
732 lda bb|quentry.type_word,x3 get type of IO
733 ars quentry.type_shift
734 ana quentry.type_mask,dl
735 eax1 0,al save for opt_info subs
736
737 tsx4 lock_disk_data lock for system update
738 ldx5 sys_info_subs,x1 x5 is sysp offset
739 ldx4 bb|sys_info.depth_map,x5 get mapped counter
740 fld bb|0,x4 increment depth
741 fsb =1.0,du
742 tpl dq_pos_depth Must stay positive
743 fld =0.0,du
744 dq_pos_depth:
745 fst bb|0,x4
746
747 " Produce sys_info.fraction. -float depth - max_depth/max_depth
748
749 fsb bb|sys_info.max_depth,x5
750 fneg
751 tpl dq_pos_fraction fraction is positive
752 fld =0.0,du limit to 0.0
753 dq_pos_fraction:
754 fdv bb|sys_info.max_depth,x5
755 fst bb|sys_info.fraction,x5
756 tsx4 unlock_disk_data ^L
757 " Produce multiplier. -float depth * slope + intercept
758 " Final opt_info.multiplier is max 1.0 multiplier * sys_info.fraction
759
760 lxl4 opt_info_subs,x1 x4 is optp offset in devtab
761 epplb bb|0,x2 pointer to devtab
762 lxl1 lb|opt_info.depth,x4 decrement depth
763 sbx1 1,du
764 sxl1 lb|opt_info.depth,x4
765 eaa 0,x1 load into high A
766 lrs 72-18 float opt_info.depth
767 lde =71b25,du
768 fno
769 fmp lb|opt_info.slope,x4
770 fneg
771 fad lb|opt_info.intercept,x4
772 fmp bb|sys_info.fraction,x5 * sys_info.fraction
773 fst lb|opt_info.multiplier,x4
774 fcmp =1.0,du max multiplier 1.0
775 tpl 0,x6 add_wq return
776 fld =1.0,du
777 fst lb|opt_info.multiplier,x4 max to 1.0
778 tra 0,x6 add_wq_return
779 "^L
780 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
781 "
782 " GETWORK -- find something to do.
783 " enter at gotwork if you already know what to do.
784 "
785 " ap->chantabe
786 " bb->disk_seg
787 " bp->disktab
788 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
789
790 getwork:
791 lda ap|chantab.in_use_word Return if channel not in use
792 cana chantab.in_use,dl
793 tze gw_ret
794
795 ldaq bp|disktab.dev_queued See if any PDI with queue is not busy
796 cnaaq bp|disktab.dev_busy Z = AQ & ^Y-pair
797 tze gw_ret Return if nothing to do
798
799 " Scan through all devices round-robin til one is found which is not
800 " busy, and has a queue. We are looking at the primary device to
801 " determine not_busy and queued.
802
803 lxl5 bp|disktab.last_dev get high drive number
804 stx5 temp1 in upper for cmpx
805 rccl sys_info$clock_,* get time for stagnate test
806 staq test_time
807
808 gw_dev.scan:
809 aos bp|disktab.dev_index device to examine
810 lxl4 bp|disktab.dev_index
811 cmpx4 temp1 see if over-run
812 tmoz gw_dev.in_range
813 ldx4 bp|disktab.first_dev reset index to first dev
814 sxl4 bp|disktab.dev_index
815
816 gw_dev.in_range:
817 ldx4 devtab_subs,x4 subscript devtab dev
818 ldq bp|devtab.pdi_word,x4 get PDI
819 equ devtab.pdi_shift,0 PRESUMED 0
820 """"" qrs devtab.pdi_shift
821 anq devtab.pdi_mask,dl
822 eax0 0,ql X0 is PDI
823 ldaq bp|disktab.dev_busy see if PDI is busy
824 lls 0,x0
825 tpl gw_dev.not_busy free for use
826 gw_dev.check_done:
827 sbx5 1,du count dev done
828 cmpx5 bp|disktab.first_dev more to scan
829 tpl gw_dev.scan
830 tra gw_ret done sub-system
831
832 " See if broken or without queue.
833
834 gw_dev.not_busy:
835 ldx4 devtab_subs,x0 subscript devtab pdi
836 eax2 bp|0,x4 X2->DEVTABE
837 lxl4 bb|devtab.wq+qht.depth,x2 test depth of queue
838 tze gw_dev.check_done no work to do
839 ldq bb|devtab.broken_word,x2 see if usable
840 anq devtab.broken,du
841 tnz gw_dev.check_done skip this one
842
843 ldx3 bb|devtab.wq+qht.head,x2 get head of queue
844 cmpx4 1,dl
845 tze gw_dev.this_request take the only request
846 lda bb|disk_data.stagnate_time see if we are stagnating
847 lrs 36 full 71 bit time
848 adaq bb|quentry.time,x3 plus queued time
849 sbaq test_time minus time now
850 tpl gw_dev.seek optimized nearest seek
851 "^L
852 " COMB DEVICE FOR BEST REQUEST
853 " X0 = pdi
854 " X1 temp
855 " X2 -> devtabe
856 " X3 -> best_quentry
857 " X4 temp
858 " bb -> disk_seg
859 " bp -> disktab
860 " ap -> chantabe
861 "
862
863 gw_dev.comb:
864 aos bb|devtab.comb,x2 count a comb done
865 lda =o400000,du best_neg_comb
866 sta best_neg_comb
867 lda =o377777,du best_pos_comb
868 sta best_seek
869 stz comb_qp flag no best yet
870
871 comb.scan:
872 ldq bb|devtab.forward_word,x2 see if moving forward
873 lda bb|quentry.cylinder_word,x3 get queued cylinder
874 ana quentry.cylinder_mask
875 sba bb|devtab.cylinder,x2
876 tze gw_dev.this_request take on-cylinder request
877 anq devtab.forward,du see if forward
878 tnz comb.forward yes - use queue-device
879 neg " use device-queue
880 comb.forward:
881 cmpa 0,dl test direction
882 tmi comb.move_reverse
883
884 " This move would be in the current direction.
885
886 comb.move_forward:
887 cmpa best_seek see if shorter move
888 tpl comb.skip longer move
889 sta best_seek
890 stx3 comb_qp save forward best
891 tra comb.skip
892
893 " This move would reverse our direction.
894
895 comb.move_reverse:
896 cmpa best_neg_comb see if shorter move
897 tmi comb.skip longer move
898 sta best_neg_comb
899 sxl3 comb_qp save reverse best
900 " tra comb.skip
901
902 " Continue scan of queue.
903
904 comb.skip:
905 ldx3 bb|quentry.next,x3 get next element
906 tnz comb.scan continue scan
907
908 ldx3 comb_qp see if forward was found
909 tnz gw_dev.this_request yes - do it
910 lxl3 comb_qp take reverse which must be here
911 tra gw_dev.this_request
912 "^L
913 " FIND SHORTEST LOGICAL SEEK ON DEV
914 " X0 = pdi
915 " X1 = best_qp
916 " X2 -> devtabe
917 " X3 -> best_quentry
918 " X4 temp
919 " bb -> disk_seg
920 " bp -> disktab
921 " ap -> chantabe
922 " lb -> devtabe
923 "
924
925 gw_dev.seek:
926 fld =1.0e30,du high set best_seek
927 fst best_seek
928 eax1 0,x3 best_qp
929 epplb bb|0,x2 form devtabe pointer
930
931 seek.scan:
932 lda bb|quentry.type_word,x3 get type of request
933 ars quentry.type_shift
934 ana quentry.type_mask,dl
935 lxl5 opt_info_subs,al subscript opt_info
936 lda bb|quentry.cylinder_word,x3 find cylinder move
937 ana quentry.cylinder_mask,dl
938 sba lb|devtab.cylinder
939 tze gw_dev.this_request on-cylinder
940 tpl seek.pos take absolute
941 neg
942 seek.pos: lrs 36 float
943 lde =71b25,du
944 fno
945 fmp lb|opt_info.multiplier,x5 * multiplier
946 fcmp best_seek see if best seek
947 tpl seek.worse this one is worse
948 eax1 0,x3 save this entry as best
949 fst best_seek and the length
950
951 seek.worse:
952 ldx3 bb|quentry.next,x3 check next entry
953 tnz seek.scan
954
955 " The best seek is noted in X1, move to X3 and use it.
956
957 eax3 0,x1
958 gw_dev.this_request:
959 tsx6 del_q delete this request from Q
960 " tra xfer_join
961 "^L
962 " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
963 "
964 " GOTWORK -- XFER JOIN process a quentry
965 " X0 = pdi
966 " X2 -> devtabe from pdi
967 " X3 -> quentry
968 " X5 -> devtabe for actual device
969 " X7 is return address
970 " bb -> disk_seg
971 " bp -> disktab
972 " ap -> chantabe
973 "
974 " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
975
976 equ chantab.erct_shift,0 PRESUME=0
977
978 gotwork:
979 xfer_join:
980 lda -chantab.erct_mask-1,dl clear error count and qrp
981 ansa ap|chantab.erct_word zero qrp,erct leave command
982 stx3 ap|chantab.qrp save quentry index for later
983
984 lda bb|quentry.dev_word,x3
985 ars quentry.dev_shift
986 ana quentry.dev_mask,dl
987 sta dev save device number
988 als idcw.device_shift position dev in AU
989
990 " dev value in AU is used in gw_testing below.
991
992 equ quentry.used_word,quentry.type_word
993 ldq bb|quentry.used_word,x3
994 canq quentry.used,du DEBUG
995 tnz *+2
996 oct 04 DEBUG Die Die Die
997 qrs quentry.type_shift
998 anq quentry.type_mask,dl
999 eax4 0,ql io_type to x4
1000 cmpq TEST,dl See if TEST io
1001 tze gw_testing
1002
1003 stca ap|chantab.scdcw,20 use dev in AU
1004 ora =o740000,dl dcdcw idcw.code=7 idcw.ext_ctl=1
1005 sta ap|chantab.dcdcw
1006
1007 lxl5 dev get device
1008 ldx5 devtab_subs,x5 subscript devtab
1009 eax5 bp|0,x5 HENCE x5 -> real devtabe
1010
1011 " Determine if write IO by shifting the mask
1012
1013 lda write_mapping,du
1014 als 0,ql io_type still QL
1015 tpl gw_read if positive then read
1016 lda =o310000,du
1017 tra gw_rw_done
1018 gw_read:
1019 lda =o250000,du
1020 gw_rw_done:
1021 stca ap|chantab.dcdcw,40 I believe an orsa would do
1022
1023 "dcdcwp->idcw.ext = quentry.coreadd
1024 lda bb|quentry.coreadd_word,x3
1025 equ MUST_BE_ZERO,quentry.coreadd_shift PRESUMPTION
1026 stca ap|chantab.dcdcw,10
1027
1028 "dddcwp->dcw.address = substr quentry.coreadd7
1029 als 18
1030 stba ap|chantab.dddcw,60
1031
1032 lda bb|quentry.sector_word,x3 leave sector in A for gw_put_seldata
1033 als 36-quentry.n_sectors_shift mask for sectors
1034 arl 36-quentry.n_sectors_shift
1035 sta ap|chantab.select_data
1036
1037 " Check for 64 or 512 type seek use x1
1038 ldx1 ap|chantab.scdcw
1039 bool seek_64_bit,040000 "34 = seek_64 normal 30 = seek_512 ibm
1040 anx1 seek_64_bit,du
1041 tnz seek_64 " bit was on
1042 seek_512:
1043 " Check io type for file system standards
1044 cmpx4 VTOC_WRITE,du
1045 tpnz not_stan
1046 cmpx4 PAGE_WRITE,du
1047 tmoz page_512
1048 ora 000100,du
1049 stca ap|chantab.select_data,20 " store sector limit
1050 ldq 192,dl " real vtoce size
1051 stcq ap|chantab.dddcw,03 " store tally
1052 tra seek_stats
1053 page_512:
1054 ora 000200,du
1055 stca ap|chantab.select_data,20 " store sector limit
1056 ldq 1024,dl
1057 stcq ap|chantab.dddcw,03 " store tally
1058 tra seek_stats
1059 not_stan:
1060 ldq sector_mapping,du io_type still in X4
1061 qls 0,x4
1062 tpl not_sect_512 if positive then not sector
1063
1064 " Formulate tally and select_data.limit 512
1065
1066 ldq bb|quentry.n_sectors_word,x3
1067 qrl quentry.n_sectors_shift
1068 stq n_sectors
1069 qls chantab.limit_shift align for sector limit
1070 stq n_sectors_temp
1071 ada n_sectors_temp n_sectors + sector
1072 ldq n_sectors
1073 qls 9 times 512
1074 tra sect_done_512
1075 not_sect_512:
1076 ldq 1024,dl page size is 1024 words
1077 ada =o000200,du add in limit bit
1078 sect_done_512:
1079 stcq ap|chantab.dddcw,03 store tally
1080 put_seldata_512:
1081 sta ap|chantab.select_data
1082 tra seek_stats
1083 seek_64:
1084 ldq sector_mapping,du io_type still in X4
1085 qls 0,x4
1086 tpl gw_not_sect if positive then not sector^LFormulate tally and select_data.limit
1087
1088 ldq bb|quentry.n_sectors_word,x3
1089 qrl quentry.n_sectors_shift
1090 stq n_sectors
1091 qls chantab.limit_shift align for sector limit
1092 stq n_sectors_temp
1093 ada n_sectors_temp n_sectors + sector
1094 ldq n_sectors
1095 qls 6 times 64
1096 tra gw_sect_done
1097 gw_not_sect:
1098 ldq 1024,dl page size is 1024 words
1099 ada =o002000,du add in limit bit
1100 gw_sect_done:
1101 stcq ap|chantab.dddcw,03 store tally
1102 gw_put_seldata:
1103 sta ap|chantab.select_data
1104
1105 " Formulate seek statistics and seek direction.
1106
1107 seek_stats:
1108 epplb bb|0,x5 form devtab dev pointer
1109 lxl4 opt_info_subs,x4 get opt_info subscript in devtab
1110 lda bb|quentry.cylinder_word,x3 get quentry.cylinder
1111 ana quentry.cylinder_mask,dl
1112 sta cylinder
1113 sba bb|devtab.cylinder,x2 subtract devtab.cylinder
1114 tze gw_seek_done on-cylinder retain forward
1115 tpl gw_seek_fwd seek from low to high
1116 gw_seek_back: " seek from high to low
1117 lcx1 devtab.forward+1,du clear forward bit
1118 ansx1 bb|devtab.forward_word,x2
1119 neg " take absolute cylinder move
1120 tra gw_seek_done
1121
1122 gw_seek_fwd:
1123 ldq devtab.forward,du
1124 orsq bb|devtab.forward_word,x2
1125
1126 gw_seek_done:
1127 asa lb|opt_info.seek_sum_word,x4 sum seek lengths
1128 aos lb|opt_info.seek_count_word,x4 count seek done
1129 lda cylinder
1130 sta bb|devtab.cylinder,x2
1131 epplb ap|chantab.scdcw
1132
1133 " Perform the operation
1134
1135 tsx6 connect
1136 gw_ret: tra 0,x7
1137
1138
1139 "TESTING HERE -- note dev for idcw in AU
1140
1141 gw_testing:
1142 stca ap|chantab.rssdcw,20 use dev in AU
1143 lda bb|quentry.coreadd_word get command from coreadd
1144 ana idcw.command_mask,dl mask for command
1145 als 30 shift to bits 0 - 5
1146 stca ap|chantab.rssdcw,40 in IDCW
1147
1148 " Statistics for TEST - io_type in X4
1149
1150 epplb bb|0,x5 devtab dev pointer
1151 lxl4 opt_info_subs,x4 convert type to subscript
1152 cmpa 58,dl
1153 tze gw_testing.unload
1154 aos lb|opt_info.seek_count_word,x4 TEST
1155 tra gw_testing.connect
1156 gw_testing.unload:
1157 aos lb|opt_info.seek_sum_word,x4 UNLOAD
1158
1159 gw_testing.connect:
1160 epplb ap|chantab.rssdcw
1161 tsx6 connect
1162 tra gw_ret
1163
1164 "^L
1165 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1166 "
1167 " CONNECT -- called via tsx6
1168 "
1169 " X0 = pdi
1170 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1171
1172 even
1173 one_arg_nd:
1174 zero 2,4
1175 zero 0
1176
1177 two_args_nd:
1178 zero 4,4
1179 zero 0
1180
1181 nullptr: its -1,1
1182
1183 " *********
1184 "
1185 " LB -> DCW list
1186 "
1187 connect:
1188 sprilb ima+io_manager_arg.listp
1189 lda ap|chantab.chx
1190 sta ima+io_manager_arg.chx
1191 stz ima+io_manager_arg.pcw
1192 ldaq nullptr
1193 staq ima+io_manager_arg.ptp
1194
1195 ldaq one_arg_nd
1196 staq arglist
1197 epplb ima
1198 sprilb arglist+2
1199 call io_manager$connect_absarglist
1200
1201 aos ap|chantab.connects
1202 lda chantab.active,dl
1203 orsa ap|chantab.active_word
1204 rccl sys_info$clock_,*
1205 staq ap|chantab.connect_time
1206 lda =o400000,du
1207 ldq 0,du
1208 lrl 0,x0 leave PDI-th bit on
1209 orsa bp|disktab.dev_busy
1210 orsq bp|disktab.dev_busy+1
1211 tra 0,x6 connect retns
1212 "^L
1213 "
1214 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1215 "
1216 " DISK_INTER -- the interrupt side of the disk_dim
1217 " This proc only processes the easy cases, those
1218 " which do not involve errors or syserr messeage production.
1219 " It is assumed that if this procedure did not exist, the
1220 " pl1 version of the disk_dim could handle all cases
1221 " properly.
1222 "
1223 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1224
1225 evil_status_bits:
1226 oct 002300000000
1227
1228 even
1229 simple_interrupt_criteria:
1230 zero 0,chantab.active
1231 zero -1,-chantab.active-chantab.ioi_use-chantab.rsr-1
1232
1233 even
1234 all_ones:
1235 vfd 36/-1
1236 vfd 36/-1
1237
1238 even
1239 time_mod: dec 1
1240 dec 0
1241
1242 disk_inter:
1243 push " get a stack frame
1244 spriap int_arg_list " save arg list ptr
1245 eppbb disk_seg$ need bb in case of bailout
1246
1247 lxl5 ap|4,* get interrupt level
1248 cmpx5 3,du only level = 3 terminate handled here
1249 tnz SLOW_INT
1250
1251 " Each subsystem has a channel address space of dskdcl_chans_per_subsys.
1252 " If you divide the supplied channel idx by this you can arrive at the subsys
1253 " index.
1254
1255 lda ap|2,* get idx
1256 lrs dskdcl_chans_per_subsys_shift sx = idx/#
1257 tsx7 setup
1258 qrl 36-dskdcl_chans_per_subsys_shift put modidx# in the q
1259 lxl4 chantab_subs,ql subscript chantab
1260 adx4 bp|disktab.channels locate dynamic table
1261 eppap bb|0,x4 HENCEFORTH AP -> chantabe
1262 eax4 disktab.int_lock_meters
1263 tsx7 lock
1264
1265 lda ap|chantab.statusp,* get status
1266
1267 tze NO_STATUS_TERM someone else processed status disk_control$run
1268
1269 "CHECK 1 AGAIN
1270
1271 tpl UNLOCK_THEN_SLOW
1272
1273
1274 "CHECK 8 -- handle abnormal termination status
1275 cana bb|disk_data.status_mask
1276 tnz UNLOCK_THEN_SLOW
1277
1278 "CHECK 9 -- Test for non-zero tally residue in DCW DISCONTINUED
1279 "CHECK 10 -- If controller performed EDAC or auto retry
1280 cana evil_status_bits
1281 tnz UNLOCK_THEN_SLOW
1282
1283 ldaq simple_interrupt_criteria pre-CHECKS 3&4&7
1284 cmk ap|chantab.active_word test channel criteria
1285 tnz UNLOCK_THEN_SLOW
1286
1287 "
1288 "CHECK 3 -- If status for ioi channel
1289 "CHECK 4 -- If channel not active scream bloody murder
1290 "CHECK 7 --If detailed status just read
1291 "
1292 rccl sys_info$clock_,*
1293 staq status_time
1294
1295 "Now set needed registers pointing into disk_data seg
1296 ldx3 ap|chantab.qrp HENCEFORTH X3->quentry
1297 lda bb|quentry.pdi_word,x3
1298 ars quentry.pdi_shift AL now has PDI
1299 ana quentry.pdi_mask,dl
1300 eax0 0,al HENCEFORTH X0 = PDI
1301
1302 ldx2 devtab_subs,x0 subscript devtab pdi
1303 eax2 bp|0,x2 HENCEFORTH X2->devtabe
1304 "
1305 "CHECK 11 -- Was disk previously inoperative?
1306 lda bb|devtab.broken_word,x2
1307 cana devtab.broken+devtab.was_broken,du
1308 tnz UNLOCK_THEN_SLOW
1309 "
1310 " Must set sect_sw bootload_sw coreadd prior ercd before yielding quentry
1311
1312
1313 "CHECK 12 -- If was test then indicate test result
1314
1315 lda bb|quentry.type_word,x3
1316 ars quentry.type_shift
1317 ana quentry.type_mask,dl
1318 sta io_type io_type DL **
1319 cmpa TEST,dl
1320 tze UNLOCK_THEN_SLOW Handle through pl1 DIM
1321
1322 ldq sector_mapping,du Determine if sector IO
1323 qls 0,al shift to sign bit
1324 stq sect_sw
1325 ldq bootload_mapping,du " Determine if bce IO
1326 qls 0,al
1327 stq bootload_sw
1328 ldq bb|quentry.coreadd_word,x3
1329 qls 36-quentry.type_shift isolate coreaddress
1330 qrs 36-quentry.type_shift
1331 stq coreadd
1332
1333 stz errcd
1334
1335 " WE MAY NEED TO SET LB->PVTE HERE ...
1336
1337 "AT THIS POINT WE KNOW THAT NO ERROR OCCURED.
1338 "AT THIS POINT WE KNOW WE WILL NOT HAVE TO PRINT ANY MESSAGES.
1339 "AT THIS POINT WE MAY BEGIN TO MODIFY DISK_SEG TO REFLECT AN I/O COMPLETION.
1340
1341
1342 lca chantab.active+chantab.inop+1,dl
1343 ansa ap|chantab.active_word Indicate channel is no longer active|inop
1344 lda =o400000,du
1345 ldq 0,du
1346 lrl 0,x0 X0=PDI -- turn off PDI-th bit
1347 eraq all_ones
1348 ansa bp|disktab.dev_busy
1349 ansq bp|disktab.dev_busy+1
1350
1351 lcx4 devtab.inop+1,du
1352 ansx4 bb|devtab.inop_word,x2 Clear the devtab.inop flag
1353 "^LMeter this i/o completion
1354
1355
1356 lxl4 io_type io_type in DL
1357 lxl4 opt_info_subs,x4 subscript opt_info
1358 epplb bb|0,x2 devtab pointer pdi
1359 rccl sys_info$clock_,*
1360 sbaq ap|chantab.connect_time
1361 adaq lb|opt_info.channel_wait,x4 sum channel wait
1362 staq lb|opt_info.channel_wait,x4
1363 rccl sys_info$clock_,*
1364 sbaq bb|quentry.time,x3
1365 adaq lb|opt_info.queue_wait,x4 sum queue wait
1366 staq lb|opt_info.queue_wait,x4
1367 lcx4 quentry.used+1,du mask out used bit
1368 ansx4 bb|quentry.used_word,x3
1369
1370 tsx7 add_free_q
1371
1372 tsx7 getwork
1373
1374 tsx7 unlock
1375
1376
1377 " Post this io completion.
1378
1379 epplb coreadd
1380 sprilb arglist+2
1381 epplb errcd
1382 sprilb arglist+4
1383 ldaq two_args_nd
1384 staq arglist
1385
1386 szn sect_sw Select posting means
1387 tmi sector_post
1388 eppap arglist
1389 short_call page$done
1390 return
1391
1392 sector_post:
1393 lda bb|0,3
1394 szn bootload_sw
1395 tmi bootload_post
1396 eppap arglist
1397 short_call vtoc_interrupt$vtoc_interrupt
1398 return
1399
1400 bootload_post:
1401 eppap arglist
1402 short_call bootload_disk_post$bootload_disk_post
1403 return
1404
1405
1406 " SLOW INT -- UNLOCK_THEN_SLOW -- bail out of hard case
1407
1408 UNLOCK_THEN_SLOW:
1409 tsx7 unlock
1410
1411 SLOW_INT: aos bb|disk_data.bail_outs count a bail-out to PL1
1412 eppap int_arg_list,* get back arg list ptr
1413 short_call disk_control$disk_inter
1414 return
1415
1416 NO_STATUS_TERM:
1417 aos ap|chantab.no_status_terminate;
1418 tsx7 unlock
1419 return
1420
1421 "^LConstants for subscript calculations
1422
1423 " Subscript for sys and opt info. Sys_info is DU, Opt_info is DL.
1424 " sys_info is segment offset of sys_info i, opt_info is devtab
1425 " offset of opt_info i.
1426 sec_per_rec:
1427 zero 0,0 " not used
1428 zero 0,0 " not used
1429 zero 0,16 " 500
1430 zero 0,16 " 451
1431 zero 0,16 " 400
1432 zero 0,16 " 190
1433 zero 0,16 " 181
1434 zero 0,16 " 501
1435 zero 0,2 " 3380
1436 zero 0,2 " 3390
1437 sys_info_subs: " 0:MAX_IO_TYPE
1438 opt_info_subs:
1439 zero disk_data.sys_info+sys_info_size*0,devtab.opt_info+opt_info_size*0
1440 zero disk_data.sys_info+sys_info_size*1,devtab.opt_info+opt_info_size*1
1441 zero disk_data.sys_info+sys_info_size*2,devtab.opt_info+opt_info_size*2
1442 zero disk_data.sys_info+sys_info_size*3,devtab.opt_info+opt_info_size*3
1443 zero disk_data.sys_info+sys_info_size*4,devtab.opt_info+opt_info_size*4
1444 zero disk_data.sys_info+sys_info_size*5,devtab.opt_info+opt_info_size*5
1445 zero disk_data.sys_info+sys_info_size*6,devtab.opt_info+opt_info_size*6
1446 zero disk_data.sys_info+sys_info_size*7,devtab.opt_info+opt_info_size*7
1447
1448
1449 " Constants for channel table and devtab subscripting. Current basis is
1450 " the limit on either is 64.
1451
1452 chantab_subs: " straight subscript 1:64
1453 devtab_subs: " disktab.devtab subscript
1454 zero disktab.devtab+devtab_size*00,chantab_size*00 " @ 1
1455 zero disktab.devtab+devtab_size*01,chantab_size*01
1456 zero disktab.devtab+devtab_size*02,chantab_size*02
1457 zero disktab.devtab+devtab_size*03,chantab_size*03
1458 zero disktab.devtab+devtab_size*04,chantab_size*04
1459 zero disktab.devtab+devtab_size*05,chantab_size*05
1460 zero disktab.devtab+devtab_size*06,chantab_size*06
1461 zero disktab.devtab+devtab_size*07,chantab_size*07
1462 zero disktab.devtab+devtab_size*08,chantab_size*08
1463 zero disktab.devtab+devtab_size*09,chantab_size*09
1464 zero disktab.devtab+devtab_size*10,chantab_size*10
1465 zero disktab.devtab+devtab_size*11,chantab_size*11
1466 zero disktab.devtab+devtab_size*12,chantab_size*12
1467 zero disktab.devtab+devtab_size*13,chantab_size*13
1468 zero disktab.devtab+devtab_size*14,chantab_size*14
1469 zero disktab.devtab+devtab_size*15,chantab_size*15
1470 zero disktab.devtab+devtab_size*16,chantab_size*16
1471 zero disktab.devtab+devtab_size*17,chantab_size*17
1472 zero disktab.devtab+devtab_size*18,chantab_size*18
1473 zero disktab.devtab+devtab_size*19,chantab_size*19
1474 zero disktab.devtab+devtab_size*20,chantab_size*20
1475 zero disktab.devtab+devtab_size*21,chantab_size*21
1476 zero disktab.devtab+devtab_size*22,chantab_size*22
1477 zero disktab.devtab+devtab_size*23,chantab_size*23
1478 zero disktab.devtab+devtab_size*24,chantab_size*24
1479 zero disktab.devtab+devtab_size*25,chantab_size*25
1480 zero disktab.devtab+devtab_size*26,chantab_size*26
1481 zero disktab.devtab+devtab_size*27,chantab_size*27
1482 zero disktab.devtab+devtab_size*28,chantab_size*28
1483 zero disktab.devtab+devtab_size*29,chantab_size*29
1484 zero disktab.devtab+devtab_size*30,chantab_size*30
1485 zero disktab.devtab+devtab_size*31,chantab_size*31
1486 zero disktab.devtab+devtab_size*32,chantab_size*32
1487 zero disktab.devtab+devtab_size*33,chantab_size*33
1488 zero disktab.devtab+devtab_size*34,chantab_size*34
1489 zero disktab.devtab+devtab_size*35,chantab_size*35
1490 zero disktab.devtab+devtab_size*36,chantab_size*36
1491 zero disktab.devtab+devtab_size*37,chantab_size*37
1492 zero disktab.devtab+devtab_size*38,chantab_size*38
1493 zero disktab.devtab+devtab_size*39,chantab_size*39
1494 zero disktab.devtab+devtab_size*40,chantab_size*40
1495 zero disktab.devtab+devtab_size*41,chantab_size*41
1496 zero disktab.devtab+devtab_size*42,chantab_size*42
1497 zero disktab.devtab+devtab_size*43,chantab_size*43
1498 zero disktab.devtab+devtab_size*44,chantab_size*44
1499 zero disktab.devtab+devtab_size*45,chantab_size*45
1500 zero disktab.devtab+devtab_size*46,chantab_size*46
1501 zero disktab.devtab+devtab_size*47,chantab_size*47
1502 zero disktab.devtab+devtab_size*48,chantab_size*48
1503 zero disktab.devtab+devtab_size*49,chantab_size*49
1504 zero disktab.devtab+devtab_size*50,chantab_size*50
1505 zero disktab.devtab+devtab_size*51,chantab_size*51
1506 zero disktab.devtab+devtab_size*52,chantab_size*52
1507 zero disktab.devtab+devtab_size*53,chantab_size*53
1508 zero disktab.devtab+devtab_size*54,chantab_size*54
1509 zero disktab.devtab+devtab_size*55,chantab_size*55
1510 zero disktab.devtab+devtab_size*56,chantab_size*56
1511 zero disktab.devtab+devtab_size*57,chantab_size*57
1512 zero disktab.devtab+devtab_size*58,chantab_size*58
1513 zero disktab.devtab+devtab_size*59,chantab_size*59
1514 zero disktab.devtab+devtab_size*60,chantab_size*60
1515 zero disktab.devtab+devtab_size*61,chantab_size*61
1516 zero disktab.devtab+devtab_size*62,chantab_size*62
1517 zero disktab.devtab+devtab_size*63,chantab_size*63
1518 zero disktab.devtab+devtab_size*64,chantab_size*64
1519 "^L
1520 include device_error
1521 include disk_error_interp
1522 include io_manager_dcls
1523 include iom_ctl_words
1524
1525 " sectors per record must be used in seek calculations and are indexed by the pvte dev_type
1526
1527 "^L
1528 include dskdcl
1529 "^L
1530 include pvte
1531
1532 end