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) change(85-09-09,Fawcett), approve(85-09-09,MCR6979),
  14 "     audit(86-01-27,CLJones), install(86-03-21,MR12.0-1033):
  15 "     Add support for dev 0 FIPS.
  16 "  2) change(86-05-29,Fawcett), approve(86-05-29,MCR7383),
  17 "     audit(86-05-30,Coppola), install(86-07-17,MR12.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) change(86-09-10,Farley), approve(86-10-24,MCR7544),
  23 "     audit(86-10-27,Fawcett), install(86-10-28,MR12.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     arglist(3)
  61           tempd     listp
  62           tempd     ima(8)
  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_mask(arglist)
 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_run(arglist)
 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 -> (first)chantabe
 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_unmask(arglist)
 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.coreadd,7)
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_abs(arglist)
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 mod(idx,#) 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