$CONTROL MAP,CODE,USLINIT                                               00010000
<<iomdisc1 - module 27>>                                                00015000
<< hp32002c mpe source c.00.00 >>                                       00020000
<< COPYRIGHT     "(C) COPYRIGHT HEWLETT-PACKARD CO. 1980.           >>  00025000
<<     this program may be used with one computer system at a       >>  00030000
<<     time and shall not otherwise be recorded, transmitted or     >>  00035000
<<     stored in a retrieval system.  copying or other reproduction >>  00040000
<<     of this program except for archival purposes is prohibited   >>  00045000
<<     without the prior written consent of hewlett-packard company.>>  00050000
<< **** note - dollar copyright cannot be used with this module *** >>  00055000
$control privileged,uncallable,main=iomdisc1                            00060000
$thirty                                                                 00065000
$title "7905/7920/7925 MOVING HEAD DISC DRIVER -- SEEK'AHEAD"  <<01549>>00070000
                                                                        00075000
driver calling sequence                                                 00080000
                                                                        00085000
   driver request codes                                                 00090000
     0 - read                                                           00095000
     1 - write                                                          00100000
     2 - file open                                                      00105000
     3 - file close                                                     00110000
     4 - device close                                                   00115000
     5 - fill with zeros                                                00120000
     6 - fill with blanks                                               00125000
     7 - request status                                        <<00.pv>>00130000
     8 - format track                                          <<01.pv>>00135000
     9 - initialize track                                      <<02.pv>>00140000
    10 - read full sector                                      <<03.pv>>00145000
    11 - write label (sector 0)                                <<04.pv>>00150000
    12 - read (with sparing disabled)                          <<07.pv>>00155000
                                                                        00160000
   count - word/byte count. odd byte count will be rounded up.          00165000
                                                                        00170000
   parameters p1 and p2 form a double word disc adress for all xfers.   00175000
                                                                        00180000
driver return codes                                                     00185000
                                                                        00190000
   general(13:3)        qualifying(8:5)               overall(8:8)      00195000
   0 - pending          1 - wait for completion       %10               00200000
   1 - successful                                     %01               00205000
   4 - irrecoverable    0 - invalid function          %04               00210000
       error            1 - track error               %14               00215000
                        3 - xmission error            %34               00220000
                        4 - sio failure               %44               00225000
                        5 - unit failure              %54               00230000
                        6 - invalid disc adress       %64               00235000
                        %12 - system error            %124              00240000
                                                                        00245000
disc controller hardware status returns                                 00250000
                                                                        00255000
   status 1 (returned by tio,sense,etc.)                                00260000
   bits     use                                                         00265000
     0      sio ok                                                      00270000
     1      rio/wio ok                                                  00275000
     2      interrupt request                                           00280000
   3-7      termination status                                          00285000
               0 - normal completion                                    00290000
               1 - illegal command                                      00295000
               2 - wake-up status (used in request stat funct) <<01549>>00300000
               7 - cyl compare error                                    00305000
             %10 - uncorrectable data error                             00310000
             %11 - head-sector compare error                            00315000
             %12 - sio program error                                    00320000
             %14 - end of cylinder                                      00325000
             %16 - overrun                                              00330000
             %17 - possibly correctable data error                      00335000
             %20 - illegal access to spare track                        00340000
             %21 - attempt to access defective track                    00345000
             %22 - head movement during data operation                  00350000
             %23 - disc drive (status-2) error                          00355000
             %26 - attempt to write on protected track                  00360000
             %27 - drive unavailable                                    00365000
             %37 - drive attention                                      00370000
   8-12      unused                                            <<25.00>>00375000
  13-15      unit number                                       <<25.00>>00380000
                                                                        00385000
note the following difference in the return status command              00390000
                                                                        00395000
      0      spare track                                                00400000
      1      protected track                                            00405000
      2      defective track                                            00410000
                                                                        00415000
                                                                        00420000
   status 2 word                                                        00425000
      0      drive error                                                00430000
    3-6      drive type nybble                                 <<25.00>>00435000
      8      attention                                                  00440000
      9      platter (7905) or pack (7920/7925) read only      <<25.00>>00445000
     10      format                                                     00450000
     11      drive fault                                       <<25.00>>00455000
     12      first status                                               00460000
     13      seek check                                                 00465000
     14      drive not ready                                            00470000
     15      drive busy                                                 00475000
$page                                                                   00480000
begin                                                                   00485000
equate                                                                  00490000
   adrrec      = %006000, << adress record cmd >>                       00495000
   allowpoll   = 140,     << offset to allowpoll prog>>        <<01549>>00500000
   attention   = %37,     << attention status code from drive>><<01549>>00505000
   badsio      = %44,     << sio failure return >>                      00510000
   cbit'       = 7,       << recalibrate bit of qmisc >>                00515000
   cdba        = 14,      << current data buf index >>                  00520000
   cderr       = %17,     << correctable data error code >>             00525000
   ceda        = 10,      << current error disc adr. index >>           00530000
   ceda1       = 20,      << ceda index (single) >>            <<01.pv>>00535000
   clda        = 5,       << current logical disc adr. index >>         00540000
   cpda        = 6,       << current physical disc adr. index >>        00545000
   clearunit   = %010000, << clear unit control function >>             00550000
   control     = %040000, << sio control order >>                       00555000
   curcyl      = 12,      << current cylinder index >>                  00560000
   cr4k        = %170000, << chained read of 4 k words >>               00565000
   cwc         = 16,      << current word count index >>                00570000
   cw4k        = %160000, << chained write of 4 k words >>              00575000
   dadr        = 4,       << disc adress index in ioq >>                00580000
   diltp       = 5,       << offset in dit to iltp >>          <<rk0pv>>00585000
   ditioqp     = 2,       << offset in dit to ioqp >>          <<01549>>00590000
   direct'spare= %20,     << direct access to spare track >>   <<01549>>00595000
   dldev       = 3,       << logical device index of dit >>             00600000
   dlink       = 1,       << offset in dit to resource chain >><<01549>>00605000
   drive'avail =  %2,     << wakeup -- this cpu has drive >>   <<01549>>00610000
   drive'error = %23,     << status two error >>               <<01549>>00615000
   drive'nrdy  = %23,     << status two  -- not ready,others >><<01549>>00620000
   dscxfrerr   = %14,     << disc xfer error status return >>           00625000
   dserr       = 7,       << error status index of dit >>               00630000
   dstat       = 6,       << device status return index >>              00635000
   dstat1      = 18,      << status 1 return index >>                   00640000
   dstat2      = 19,      << status 2 return index >>                   00645000
   endint      = %034000, << sio end command >>                         00650000
   endop       = %012400, << disc end order >>                          00655000
   fillb       = 6,       << fill with blank cmd >>                     00660000
   fopen       = 2,       << file open function >>             <<02.pv>>00665000
   format      = 8,       << format function >>                <<rh.pv>>00670000
   iltploc     = 5,       << ilt pointer in dit >>                      00675000
   init        = 9,       << initialize function >>            <<02.pv>>00680000
   initop      = %005400, << initialize command >>             <<01.pv>>00685000
   initadr     = 30,      << initialize address index >>       <<06.pv>>00690000
   initaddr    = 15,      << initialize address index (dbl) >> <<06.pv>>00695000
   invdskadr   = %64,     << invalid disc adress return >>              00700000
   invfunc     = 4,       << invalid function return >>                 00705000
   isiop     = 8,         << siop pointer in ilt >>            <<01300>>00710000
   iqueue      = 12,      << offset in ilt to controller q # >><<01549>>00715000
   iditp     = 14,        << ditp pointer in ilt >>            <<01300>>00720000
   icntrl    = 7,         << controller info in ilt >>         <<01300>>00725000
   iflag     = 13,        << flags word of ilt >>              <<01300>>00730000
   jump        = %000000, << jump command >>                   <<rk.00>>00735000
   jumpc       = %004000, << jump conditional command >>                00740000
   mbit'       = 3,       << track map bit of qmisc >>                  00745000
   overrun     = %16,     << controller got overrun >>         <<01549>>00750000
   qfunc       = 6,       << function code index of ioq >>              00755000
   qldev       = 2,       << ldev index of ioq >>                       00760000
   qmisc       = 3,       << driver word index of ioq >>                00765000
   qstat       = 10,      << status return index of ioq >>              00770000
   qwbct       = 7,       << count index >>                             00775000
   read        = 0,       << read function >>                           00780000
   readop      = %002400, << disc read command >>                       00785000
   readfs      = 10,      << read full sector function >>      <<03.pv>>00790000
   readfsop    = %003000, << read full sector command >>       <<03.pv>>00795000
   readspd     = 12,      << read with sparing disabled >>     <<07.pv>>00800000
   recalp      = 136,     << offset to recalibrate prog >>     <<01549>>00805000
   recalp1     = recalp+1,                                              00810000
   recalibrate = %000600, << disc recalibrate order >>                  00815000
   reqstat     = %001400, << request status cmd >>                      00820000
   rqall       = 40,      << offset in siop to set of rqst >>  <<01549>>00825000
   rstap       = 122,     << offset to req status i/o prog >>  <<01549>>00830000
   rstap1      = rstap+1,                                               00835000
   rstap3      = rstap1+2,                                              00840000
   rstap5      = rstap3+2,                                              00845000
   rstap7      = rstap5+2,                                              00850000
   rstap8      = rstap7+1,                                     <<rk.00>>00855000
   rstap9      = rstap7+2,                                              00860000
   rstap10     = rstap8+2,                                     <<rk.00>>00865000
   rstap11     = rstap9+2,                                              00870000
   rstap13     = rstap11+2,                                    <<rk.00>>00875000
   rstat       = 7,       << request status function >>        <<00.pv>>00880000
   rsynp       = 118,     << offset to req syndrome i/o prog>> <<01549>>00885000
   rsynp1      = rsynp+1,                                               00890000
   rsynp3      = rsynp1+2,                                     <<01549>>00895000
   s'adrec'unit= 77,      << offset of main address record >>  <<01549>>00900000
   s'adrec'cyl = 79,      << pointer to cyl, head-sector >>    <<01549>>00905000
   s'bank      = 80,      << main set bank order >>            <<01549>>00910000
   s'bank'value= 81,      << which bank we're setting to >>    <<01549>>00915000
   s'chain     = 84,      << where chained orders start >>     <<01549>>00920000
   s'chain'd   = s'chain/2, << double index >>                 <<01549>>00925000
   s'conf'mask = -4,                                           <<01960>>00930000
   s'filemask  = 73,      << file mask/also where a jump goes>><<01549>>00935000
   s'filemask'd= s'filemask/2, << double word address >>       <<01549>>00940000
   s'loop      = 74,      << where jumpc loops back >>         <<01549>>00945000
   s'loop'bank0= 75,      << reset bank 0 >>                   <<01549>>00950000
   s'no'seek   = 41,      << offset beyond seek order 1 >>     <<01549>>00955000
   s'seekenabmask=-1,                                          <<01960>>00960000
   s'seek'mask = -3,                                           <<01960>>00965000
   s'seekvalues= 11,      << doubleword beyond seek locations>><<01549>>00970000
   s'this'ditp = -5,                                           <<01960>>00975000
   s'this'unit = -6,                                           <<01960>>00980000
   s'this'unitd= s'this'unit/2, << double word address >>      <<01549>>00985000
   s'xfer'cmd  = 83,      << read, write, rfs, init, etc. >>   <<01549>>00990000
   scount      = 29,      << sector count >>                   <<05.pv>>00995000
   seek        = %001200, << seek cmd >>                                01000000
   sense       = %050000, << sense command - used as nop >>    <<rk.00>>01005000
   setbank     = %014000, << set bank command >>               <<06.pv>>01010000
   setwake     = %013000, << set wakeup when drive available cmd >>     01015000
   stattab     =  8,      << offset in siop to status-2 words>><<01549>>01020000
   stattab'    = stattab/2,  << double index >>                <<rk1pv>>01025000
   successful  = 1,       << successful completion status return >>     01030000
   sysbufa     = 17,      << sysbuf index of dit >>                     01035000
   sysdb       = %1000,                                                 01040000
   syserror    = %124,    << system error code return >>                01045000
   syslpdt     = 8,       << db index of lpdt pointer >>                01050000
   syssbuf     = 6,       << db index of sbuf table >>                  01055000
   unitfailure = %54,     << unit fail status return >>                 01060000
   verifyop    = %003400, << verify command >>                 <<01.pv>>01065000
   wait        = %10,     << wait for comp. status return >>            01070000
   wcr         = 15,      << word count remaining index >>              01075000
   write       = 1,       << write function >>                          01080000
   writel      = 11,      << write label function >>           <<04.pv>>01085000
   writeop     = %004000, << disc write command >>                      01090000
   xfer'nogood = %12,     << transfer err -- maybe mem parity>><<01549>>01095000
   xfererror   = %34;     << xfer error status return >>                01100000
$include inclmeas                                              <<01549>>01105000
                                                                        01110000
$include inclmift                                                       01115000
define                                                                  01120000
   abs        = absolute#,                                              01125000
   asmb       = assemble#,                                              01130000
   attnbit    = (8:1)#,   << attn bit in status 2 word >>      <<rk0pv>>01135000
   cbit       = (cbit':1)#,                                             01140000
   dbit       = (0:1)#,    << retry determination bit of qmisc >>       01145000
   disable    = asmb(sed 0)#,                                           01150000
   drvnotrdy  = (14:1)#,   << drive not ready bit of qstat2 >>          01155000
   ebit       = (2:1)#,    << error bit of qmisc >>                     01160000
   enable     = asmb(sed 1)#,                                           01165000
   errcode    = (3:5)#,    << encoded error status >>                   01170000
   function   = (8:8)#,    << request function code >>                  01175000
    hcunit    =(11:5)#,  << highest conf. unit in ilt flags w>><<01300>>01180000
   head       = lsr(8)#,   << head field of disc adress >>              01185000
   mbit       = (mbit':1)#,                                             01190000
   qldevn     = (8:8)#,    << ldev field in ioq >>                      01195000
   queuen     = (8:8)#,                                        <<01549>>01200000
   retry      = (8:8)#,    << retry count field of qmisc >>             01205000
   sbit       = (1:1)#,    << request syndrome bit of qmisc >>          01210000
   sector     = (8:8)#,    << sector field of disc adress >>            01215000
   seekcheck  = (13:1)#,   << invalid seek bit of status-2 >>           01220000
   sem        = (1:3)#,    << s,e, and m bits of qmisc >>               01225000
   sfail      = (10:1)#,   << sio fialed to start in gip >>             01230000
   spare      = (0:1)#,    << spare bit of status-1 >>                  01235000
   spec       = (1:1)#,    << special req. bit of ioq >>                01240000
   stat       = (8:8)#,    << i/o status return field of ioq >>         01245000
   statef     = (12:4)#,  << state field of ditp word 0 >>     <<01549>>01250000
   subt       = (12:4)#,   << subtype field of lpdt >>                  01255000
   sysbufr    = (3:1)#,    << system buffer bit of ioq >>               01260000
   unitn      = lsr(8)#,   << unit field of dit >>                      01265000
   unitf      = (11:5)#,  << unit field of tio status word >>  <<01549>>01270000
   wbit       = (4:1)#;    << writing bad track bit of qmisc >>         01275000
                                                                        01280000
integer pointer                                                         01285000
   head'tab    = db + %56,                                     <<01549>>01290000
   sbuf        = db + syssbuf;                                          01295000
                                                                        01300000
double pointer                                                          01305000
   dlpdt       = db + syslpdt;                                          01310000
array initial(0:179) = db :=                                   <<01549>>01315000
   %020041,          << dit size = 32, core res., type = 1 >>  <<01549>>01320000
         0,                                                             01325000
   %037437,           <<unit extract inst (andi %37)>>         <<01.02>>01330000
   %110000,          << 144 word sio program area >>           <<01549>>01335000
   << dit >>                                                            01340000
     %040000,        << dflag; disc >>                         <<01300>>01345000
           0,        << dlink >>                                        01350000
           0,        << dioqp >>                                        01355000
           0,        << dldev >>                                        01360000
           0,        << ddltp >>                                        01365000
           0,        << diltp >>                                        01370000
           0,        << dstat >>                                        01375000
           0,        << dserr >>                                        01380000
           0,        << dmamq >>                                        01385000
           0,        << dmamqt >>                                       01390000
         0,0,        << clda - current logical disc adr >>              01395000
         0,0,        << cpda - current physical disc adr >>             01400000
           0,        << cdba - current data buffer adr >>               01405000
           0,        << wcr - word count remaining >>                   01410000
           0,        << cwc - current transfer count >>                 01415000
           0,        << sysbufa - system buffer adr >>                  01420000
           0,        << stat1 - first disc status >>                    01425000
           0,        << stat2 - second disc status >>                   01430000
         0,0,        << ceda - current error disc adr >>                01435000
0,0,0,0,0,0,0,       << request syndrome area >>                        01440000
           0,        << scount - sector count >>               <<05.pv>>01445000
         0,0,        << initialize address >>                  <<06.pv>>01450000
   << sio program >>                                           <<01549>>01455000
         0,0,        << jump >>                                <<01549>>01460000
         0,0,        << this'unit,this'ditp >>                 <<01549>>01465000
         0,0,        << conf'mask,seek'mask >>                 <<01549>>01470000
         0,0,        << garbage area for non-conf units >>     <<01549>>01475000
         0,0,        << stattab >>                             <<01549>>01480000
         0,0,        << stattab >>                             <<01549>>01485000
         0,0,        << stattab >>                             <<01549>>01490000
         0,0,        << stattab >>                             <<01549>>01495000
         0,0,        << disc'addr3 >>                          <<01549>>01500000
         0,0,        << disc'addr2 >>                          <<01549>>01505000
         0,0,        << disc'addr1 >>                          <<01549>>01510000
   %040000,0,        << seek command >>          <<seek3>>     <<01549>>01515000
   %067776,%10,      << disc adress >>                         <<01549>>01520000
   %050000,-1,       << sense >>                               <<01549>>01525000
   %040000,0,        << seek command >>          <<seek2>>     <<01549>>01530000
   %067776,%10,      << disc adress >>                         <<01549>>01535000
   %050000,-1,       << sense >>                               <<01549>>01540000
   %040000,0,        << seek command >>          <<seek1>>     <<01549>>01545000
   %067776,%10,      << disc adress >>                         <<01549>>01550000
   %050000,-1,       << sense >>                               <<01549>>01555000
   %040001,%001407,  << rqst 7 >>       <<rqall>>              <<01549>>01560000
   %077776,%10,      << rd 2 w >>                              <<01549>>01565000
   %040001,%001406,  << rqst 6 >>                              <<01549>>01570000
   %077776,%10,      << rd 2 w >>                              <<01549>>01575000
   %040001,%001405,  << rqst 5 >>                              <<01549>>01580000
   %077776,%10,      << rd 2 w >>                              <<01549>>01585000
   %040001,%001404,  << rqst 4 >>                              <<01549>>01590000
   %077776,%10,      << rd 2 w >>                              <<01549>>01595000
   %040001,%001403,  << rqst 3 >>                              <<01549>>01600000
   %077776,%10,      << rd 2 w >>                              <<01549>>01605000
   %040001,%001402,  << rqst 2 >>                              <<01549>>01610000
   %077776,%10,      << rd 2 w >>                              <<01549>>01615000
   %040001,%001401,  << rqst 1 >>                              <<01549>>01620000
   %077776,%10,      << rd 2 w >>                              <<01549>>01625000
   %040001,%001400,  << rqst 0 >>                              <<01549>>01630000
   %077776,%10,      << rd 2 w >>                              <<01549>>01635000
   %040000,0,        << file mask or jump order >>             <<01549>>01640000
   %014000,0,        << set bank 0 >>                          <<01549>>01645000
   %040000,0,        << adress record >>                       <<01549>>01650000
   %067776,0,        << disc adress >>                         <<01549>>01655000
   %014000,0,        << set data bank # >>                     <<01549>>01660000
   %040000,0,        << set transfer direction >>              <<01549>>01665000
         0,0,        << up to 7 chained xfer orders >>         <<01549>>01670000
         0,0,                                                  <<01549>>01675000
         0,0,                                                  <<01549>>01680000
         0,0,                                                  <<01549>>01685000
         0,0,                                                  <<01549>>01690000
         0,0,                                                  <<01549>>01695000
         0,0,                                                  <<01549>>01700000
         0,0,        << last xfer order >>                     <<01549>>01705000
         0,0,        << conditional jump to adress record >>   <<01549>>01710000
         0,0,        << end i/o >>                             <<01549>>01715000
         0,0,        << additional space for format >>         <<01549>>01720000
         0,0,        << additional space for format >>         <<01549>>01725000
         0,0,        << additional space for format >>         <<01549>>01730000
         0,0,        << additional space for format >>         <<01549>>01735000
         0,0,        << additional space for format >>         <<01549>>01740000
         0,0,        << additional space for format >>         <<01549>>01745000
         0,0,        << additional space for format >>         <<01549>>01750000
   %040001,%6400,    << request syndrome >>                    <<01549>>01755000
   %077771,0,        << read syndrome >>                       <<01549>>01760000
   %040001,0,        << request disc status >>                 <<01549>>01765000
   %077776,0,        << read status >>                         <<01549>>01770000
   %040001,%12000,   << request disc adress >>                 <<01549>>01775000
   %077776,0,        << read disc adress >>                    <<01549>>01780000
   %050000,-1,       << sense/jump goes here >>                <<01549>>01785000
   %040000,0,        << set wakeup >>                          <<01549>>01790000
   %034000,-1,       << end i/o >>                             <<01549>>01795000
   %040000,0,        << recalibrate order >>                   <<01549>>01800000
   %030000,-1,       << end i/0 >>                             <<01549>>01805000
   %040000,%12400,   << disc end >>                            <<01549>>01810000
   %030000,-1;       << end i/o, no int >>                     <<01549>>01815000
procedure checkindex(index,table);                                      01820000
value index,table;                                                      01825000
integer index;                                                          01830000
pointer table;                                                          01835000
option external;                                                        01840000
                                                                        01845000
procedure dconvert(word);                                               01850000
value word;                                                             01855000
integer word;                                                           01860000
option external;                                                        01865000
                                                                        01870000
integer procedure getsbuf(type);                                        01875000
value type;                                                             01880000
integer type;                                                           01885000
option external;                                                        01890000
                                                                        01895000
procedure gip;                                                 <<rk0pv>>01900000
option external;                                                        01905000
                                                                        01910000
procedure help;                                                         01915000
option external;                                                        01920000
                                                                        01925000
procedure ldevnotrdy(ditp);                                             01930000
value ditp;                                                             01935000
pointer ditp;                                                           01940000
option external;                                                        01945000
                                                                        01950000
procedure siodm(ditp,flags);                                            01955000
value ditp,flags;                                                       01960000
pointer ditp;                                                           01965000
logical flags;                                                          01970000
option external;                                                        01975000
                                                                        01980000
procedure returnsbuf(sbufp);                                            01985000
value sbufp;                                                            01990000
integer sbufp;                                                          01995000
option external;                                                        02000000
                                                                        02005000
procedure startio(ditp,siop,queue);                                     02010000
value ditp,siop,queue;                                                  02015000
pointer ditp,siop;                                                      02020000
logical queue;                                                          02025000
option external;                                                        02030000
                                                                        02035000
procedure write2(word);                                                 02040000
value word;                                                             02045000
integer word;                                                           02050000
option external;                                                        02055000
                                                               <<01549>>02060000
procedure init7920(ditp);                                      <<01549>>02065000
value ditp;                                                    <<01549>>02070000
integer pointer ditp;                                          <<01549>>02075000
option forward;                                                <<01549>>02080000
$page                                                                   02085000
integer procedure mhddvr(ioqp,ditp,bank,buffer,siop,drtn);              02090000
value ioqp,ditp,bank,buffer,siop,drtn;                                  02095000
integer bank,buffer,drtn;                                               02100000
integer pointer ioqp,ditp,siop;                                         02105000
option privileged,uncallable;                                           02110000
begin                                                                   02115000
                                                                        02120000
       <<------------------>>                                  <<25.00>>02125000
       <<disc subtype table>>                                  <<25.00>>02130000
       <<------------------>>                                  <<25.00>>02135000
equate                                                         <<25.00>>02140000
   numsubtypes  = 6,   << number of moving head subtypes >>    <<25.00>>02145000
   numentries   = 4,   << number of table entries/subtype >>   <<25.00>>02150000
   secpertrack  = 0,   << offset to sec/track entries >>       <<25.00>>02155000
   secpercyl    = 1,   << offset to sec/cylinder entries >>    <<25.00>>02160000
   maxcylinder  = 2,   << offset to max cylinder for subtype >><<25.00>>02165000
   maxcyl'm'seccyl = maxcylinder - secpercyl,                  <<01549>>02170000
   sectrk'm'maxcyl = secpertrack - maxcylinder,                <<01549>>02175000
   filemask     = 3;   << offset to filemask entries >>        <<25.00>>02180000
   <<                                                        >><<01549>>02185000
   << q+1  -- ad, bufcnt                                     >><<01549>>02190000
   << q+2  -- xd                                             >><<01549>>02195000
   << q+3  -- intr'unit                                      >><<01549>>02200000
   << q+4  -- cxfer        double dxferorder                 >><<01549>>02205000
   << q+5  -- bufadr       double dxferorder                 >><<01549>>02210000
   << q+6  -- err                                            >><<01549>>02215000
   << q+7  -- xcnt                                           >><<01549>>02220000
   << q+8  -- i                                              >><<01549>>02225000
   << q+9  -- badtrack                                       >><<01549>>02230000
   << q+10 -- other'ditp                                     >><<01549>>02235000
   << q+11 -- other'ioqp                                     >><<01549>>02240000
   << q+12 -- start'addr                                     >><<01549>>02245000
   << q+13 -- subtype                                        >><<01549>>02250000
   << q+14 -- funct                                          >><<01549>>02255000
   << q+15 -- sbflg                                          >><<01549>>02260000
   << q+16 -- unit                                           >><<01549>>02265000
   << q+17 -- iltp                                           >><<01549>>02270000
   <<                                                        >><<01549>>02275000
                                                               <<25.00>>02280000
integer                                                                 02285000
   ad           = q+1,  << adress delta >>                              02290000
   bufadr       = q+5,  << absolute buffer adress >>                    02295000
   bufcnt       = q+1,  << count check for request synd. >>             02300000
   cxfer        = q+4,  << chained xfer order >>                        02305000
   err          = q+6,  << disc encoded error status >>                 02310000
   funct        = q+14, << request function code >>            <<01549>>02315000
   i            = q+8,                                                  02320000
   intr'unit    = q+3,                                         <<01549>>02325000
   mstate       = mhddvr,                                               02330000
   rstatus      = q-1,   << pcal return status >>                       02335000
   s0           = s-0,                                                  02340000
   s2           = s-2,                                                  02345000
   s3           = s-3,                                         <<01549>>02350000
   start'addr   = q+12,   << where we start xfer prog ( + 1)>> <<01549>>02355000
   subtype      = q+13, << device subtype >>                   <<01549>>02360000
   unit         = q+16, << device unit # >>                    <<01549>>02365000
   x            = x,                                                    02370000
   xcnt         = q+7,  << xfer count >>                                02375000
   xd           = q+2;  << xfer delta >>                                02380000
                                                                        02385000
double                                                                  02390000
   dxferorder   = cxfer;                                                02395000
                                                                        02400000
double pointer                                                          02405000
   dps0         = s-0,                                         <<01549>>02410000
   dditp        = ditp,                                                 02415000
   dioqp        = ioqp,                                                 02420000
   dother'ioqp  = q+11,                                        <<01549>>02425000
   dsiop        = siop;                                                 02430000
                                                                        02435000
logical                                                                 02440000
   sbflg        = q+15, << system buffer flag >>               <<01549>>02445000
   ls0          = s-0,                                         <<00.06>>02450000
   lsm1         = s-1;                                                  02455000
                                                                        02460000
logical pointer                                                         02465000
   lditp        = ditp,                                                 02470000
   lioqp        = ioqp,                                                 02475000
   lsiop        = siop;                                                 02480000
                                                                        02485000
integer pointer                                                         02490000
   badtrack     = q+9,                                                  02495000
   iltp         = q+17,                                        <<01549>>02500000
   other'ditp   = q+10,                                        <<01549>>02505000
   other'ioqp   = dother'ioqp,                                 <<01549>>02510000
   ps0          = s-0,                                         <<01549>>02515000
   ps1          = s-1;                                                  02520000
                                                                        02525000
logical pointer                                                <<01115>>02530000
   lpdtp=8;    <<logical-physical device table>>               <<01115>>02535000
                                                               <<01115>>02540000
integer array    << starting w/ 16 avoids subtypes 0-3. >>     <<25.00>>02545000
   discinfo (16:15 + numsubtypes*numentries) = pb :=           <<25.00>>02550000
     48,  96, 410, %7426, << stype 4, 7905, removable cart. >> <<25.00>>02555000
     48,  48, 410, %7425, << stype 5, 7905, fixed platter >>   <<25.00>>02560000
     48, 144, 410, %7427, << stype 6, 7905, both platters >>   <<25.00>>02565000
     48, 144, 410, %7427, << stype 7, 7905, fh disc replcmnt >><<25.00>>02570000
     48, 240, 822, %7427, << stype 8, 7920 >>                  <<25.00>>02575000
     64, 576, 822, %7427; << stype 9, 7925 >>                  <<25.00>>02580000
                                                               <<*****>>02585000
define helper = asmb(rsw);                                     <<*****>>02590000
      if tos.(2:1) then help#;                                 <<01549>>02595000
                                                               <<*****>>02600000
                                                                        02605000
define ditldev=3).(8:8#;                                       <<01115>>02610000
define foreign=(lpdtp(lditp(ditldev)&lsl(1)+1).(10:2)=3)#;     <<01115>>02615000
$page "SUBROUTINES"                                            <<01549>>02620000
double subroutine convertadr;                                           02625000
begin << this routine converts a physical to logical disc adr. >>       02630000
   tos := dditp(x); << dit index passed in x reg. >>                    02635000
   tos := s0&head;                                                      02640000
   if subtype = 5 then tos := tos - 2; << remove head offset >>         02645000
   tos := tos * discinfo (subtype*numentries + secpertrack);   <<25.00>>02650000
   asmb(xch);                                                           02655000
   tos := tos.sector;                                                   02660000
   asmb(add,zero;xch,cab);                                              02665000
   tos := discinfo (subtype*numentries + secpercyl);           <<25.00>>02670000
   asmb(lmpy,dadd; std s-4);                                            02675000
end;                                                                    02680000
                                                                        02685000
                                                                        02690000
integer subroutine calcsbufadr(cnt);                                    02695000
value cnt;                                                              02700000
integer cnt;                                                            02705000
begin                                                                   02710000
   calcsbufadr := ditp(cdba); << get first abs. system buffer adress >> 02715000
   while cnt >= 128 do                                                  02720000
   begin << stomp through the buffers >>                                02725000
      checkindex(abs(s2-1),sbuf); << index valid ? >>                   02730000
      calcsbufadr := abs(x) + @sbuf + sysdb; << get next sbuf adress >> 02735000
      cnt := cnt - 128;                                                 02740000
   end;                                                                 02745000
end;                                                                    02750000
subroutine reqstatsio;                                         <<00.pv>>02755000
begin                                                          <<00.pv>>02760000
   siop(rstap1) := reqstat + unit; << req unit status >>       <<00.pv>>02765000
   tos := @ditp(dstat1) + sysdb;                               <<00.pv>>02770000
   siop(rstap3) := s0; << status storage adress >>             <<00.pv>>02775000
   siop(rstap7) := tos + 2; << disc adress storage >>          <<00.pv>>02780000
   siop(rstap8) := sense; << a jump may go here >>             <<rk.00>>02785000
   siop(rstap11):= setwake + unit; << request wakeup cmd >>    <<rk.00>>02790000
   << the set wakeup command insures the correct unit >>       <<00.pv>>02795000
   << number is returned in the tio stat after interrupt >>    <<00.pv>>02800000
   siop(rstap13):= -1;  << sio end order status location >>    <<rk.00>>02805000
end;                                                           <<00.pv>>02810000
                                                               <<01549>>02815000
subroutine tos'log'to'phy; << really double subroutine >>      <<01549>>02820000
<< value address , subtype; >>                                 <<01549>>02825000
<< double address; ( in tos when called ) >>                   <<01549>>02830000
<< integer subtype; ( in x when called ) >>                    <<01549>>02835000
                                                               <<01549>>02840000
begin                                                          <<01549>>02845000
   asmb(cab,cab);  <<puts logical address on tos>>             <<01549>>02850000
   tos := discinfo (x*numentries + secpercyl);                 <<01549>>02855000
   asmb(ldiv); << compute disc adress >>                       <<01549>>02860000
   if lsm1 > logical (discinfo (x + maxcyl'm'seccyl)) or       <<01549>>02865000
     overflow then                   <<cylad too big>>         <<01549>>02870000
      begin                                                    <<01549>>02875000
      asmb(ddel);                                              <<01549>>02880000
      tos := -1d;                                              <<01549>>02885000
      end                                                      <<01549>>02890000
   else                                                        <<01549>>02895000
      begin                                                    <<01549>>02900000
      tos := discinfo (x + sectrk'm'maxcyl);                   <<01549>>02905000
      asmb(div,xch);                                           <<01549>>02910000
      if (x/numentries)=5 then tos := tos + 2;<<add head offset<<01549>>02915000
      tos := tos&lsl(8) + tos;                                 <<01549>>02920000
      end;                                                     <<01549>>02925000
   asmb(cab);  <<put return address on tos for sxit>>          <<01549>>02930000
end;                                                           <<01549>>02935000
                                                               <<01549>>02940000
subroutine add'seek(unit,phy'adr);                             <<01549>>02945000
value unit,phy'adr;                                            <<01549>>02950000
double phy'adr;                                                <<01549>>02955000
integer unit;                                                  <<01549>>02960000
begin                                                          <<01549>>02965000
   i := i + 1;                                                 <<01549>>02970000
   start'addr := start'addr - 6;                               <<01549>>02975000
   siop(start'addr) := unit + seek;                            <<01549>>02980000
   siop(x:=x+4) := -1;  <<set sense field >>                   <<01549>>02985000
   dsiop(s'seekvalues - i) := phy'adr;                         <<01549>>02990000
end;                                                           <<01549>>02995000
$page                                                                   03000000
$page "VARIABLE INITIALIZATION AND NEW REQUESTS"               <<01549>>03005000
   disable;                                                    <<04986>>03010000
   asmb(adds 12); << initialize local variables >>             <<01549>>03015000
   tos := dlpdt(ioqp(qldev).qldevn);                                    03020000
   delb;                                                                03025000
   tos := tos.subt; << device subtype >>                                03030000
   tos := ioqp(qfunc).function; << request function >>                  03035000
   tos := ioqp.sysbufr;  << sysbuf flag >>                              03040000
   tos := ditp(dldev)&unitn; << disc unit number >>                     03045000
   tos := ditp(iltploc);  << pointer to ilt >>                 <<rh.pv>>03050000
   if siop(s'conf'mask) = 0 then init7920(ditp);               <<01549>>03055000
                                                                        03060000
                                                               <<02039>>03065000
                                                               <<*****>>03070000
   if mstate = 2 then                                                   03075000
   begin << new request >>                                              03080000
      tos := ioqp(qwbct); << determine xfer count >>                    03085000
      if < then                                                         03090000
      begin << count in bytes >>                                        03095000
         asmb(dup);                                                     03100000
         if tos then ioqp(x) := ioqp(x) - 1; << round up cnt if odd >>  03105000
         tos := -(tos&asr(1)); << convert to words >>                   03110000
      end;                                                              03115000
      ditp(wcr) := tos; << xfer count >>                                03120000
      dditp(clda) := dioqp(dadr); << disc adress >>                     03125000
      ditp(cdba) := buffer; << set current buffer adress >>             03130000
      if funct > readspd then                                  <<07.pv>>03135000
      begin                                                             03140000
invalidfunc:                                                            03145000
         tos := invfunc;                                                03150000
         go to badend;                                                  03155000
      end;                                                              03160000
      if sbflg and ( ditp(wcr) > 1024 or funct >= format )     <<01549>>03165000
         then goto invalidfunc;                                <<01549>>03170000
      tos := 0; << reset qmisc >>                                       03175000
      x := funct; << switch on request type >>                          03180000
      asmb(load swt,x; adax; br swt,x;                                  03185000
swt:  con doxfer;    con doxfer;    con goodend;   con goodend;         03190000
      con goodend;   con fillzero;  con fillblank;             <<00.pv>>03195000
      con reqstatus; con doxfer;    con doxfer;                <<02.pv>>03200000
      con doxfer;    con doxfer;    con doxfer);               <<07.pv>>03205000
      help; << help call needed for breakpoints >>                      03210000
   end;                                                                 03215000
                                                                        03220000
$page "CONTINUATOR EVALUATION OF INTERRUPT STATUS"             <<01549>>03225000
   << continuator section >>                                            03230000
                                                               <<*****>>03235000
   if lioqp.sfail then go to siofailure; << gip failed to start i/o >>  03240000
   tos := ioqp(qmisc); << qmisc stays on tos throughout driver >>       03245000
   tos := ditp(dstat);                                         <<01549>>03250000
   if s0 = -1 then                                             <<01549>>03255000
      intr'unit := unit   << power fail >>                     <<01549>>03260000
   else                                                        <<01549>>03265000
      intr'unit := s0.unitf;                                   <<01549>>03270000
   x := err := tos.errcode;                                    <<01549>>03275000
   if <> then                                                  <<01549>>03280000
      begin   << some kind of error status >>                  <<01549>>03285000
      if funct = rstat and x = drive'avail then                <<01549>>03290000
         err := 0                                              <<01549>>03295000
      else                                                     <<01549>>03300000
         if x = xfer'nogood or x = overrun then                <<01549>>03305000
            intr'unit := unit;                                 <<01549>>03310000
      if intr'unit <> unit  and x = drive'nrdy then            <<01549>>03315000
         begin << extra seek aborted >>                        <<01549>>03320000
                                                               <<01549>>03325000
         tos := siop(s'seek'mask);                             <<01549>>03330000
         x := intr'unit;                                       <<01549>>03335000
         asmb(trbc 0,x); <<reset seek bit>>                    <<01549>>03340000
         if = then help;        <<*****>>                      <<01549>>03345000
         siop(s'seek'mask) := tos;                             <<01549>>03350000
                                                               <<01549>>03355000
         tos := abs(drtn&lsl(2)) - sysdb;                      <<01549>>03360000
         if s0 > @siop and s0 < @siop(s'no'seek) then          <<01549>>03365000
            goto startioprog                                   <<01549>>03370000
               else del;   << process as an error >>           <<01549>>03375000
         end;                                                  <<01549>>03380000
      end;                                                     <<01549>>03385000
                                                               <<01549>>03390000
                                                               <<01549>>03395000
   if err <> 0 and (ls0 land %60000)=0 then                    <<01549>>03400000
   begin << had an error >>                                             03405000
      reqstatsio;   << initialize sio program >>               <<00.pv>>03410000
      if err = cderr then                                               03415000
      begin << do request syndrome on correctable data error >>         03420000
         siop(rsynp3) := @ditp(22) + sysdb;                             03425000
         tos.sbit := 1;                                                 03430000
         tos := @siop(rsynp);                                           03435000
         go to startioprog;                                             03440000
      end;                                                              03445000
      tos.ebit := 1;                                                    03450000
      tos := @siop(rstap);                                              03455000
      go to startioprog;                                                03460000
   end;                                                                 03465000
                                                                        03470000
                                                               <<01549>>03475000
<< at this point, if there are no errors, we drop to contxfer>><<01549>>03480000
                                                               <<01549>>03485000
$page "SYNDROME PROCESSING -- CORRECTIBLE DATA ERRORS"         <<01549>>03490000
   tos.sbit := 0;                                                       03495000
   if <> then                                                           03500000
   begin << completed request syndrome >>                               03505000
      tos := ditp(22).errcode;                                          03510000
      tos := ditp(23);                                                  03515000
      tos := ditp(24);                                                  03520000
      dditp(ceda) := tos; << physical disc adress of error >>           03525000
      if tos = cderr and ( funct=read or funct=readspd )  then <<rk2pv>>03530000
      begin << error is correctable >>                                  03535000
         tos := convertadr - dditp(clda); << relative sector cnt >>     03540000
         xcnt := tos&lsl(7); << relative xfer count >>                  03545000
         i := tos; << zero i >>                                         03550000
         if sbflg then bufadr := calcsbufadr(xcnt) << system buffers >> 03555000
         else bufadr := ditp(cdba) + xcnt; << data seg >>               03560000
         bufadr := bufadr + ditp(25); << data offset in sector >>       03565000
         bufcnt := ditp(cwc) - xcnt - ditp(25); << adress fence >>      03570000
         do << correct the data error in memory and continue xfer >>    03575000
            if 0 <= (ditp(25) + i) <= 127 and (bufcnt - i) > 0 then     03580000
            begin                                                       03585000
               tos := bank;                                             03590000
               tos := bufadr + i;                                       03595000
               asmb(lsea);                                              03600000
               tos := tos xor lditp(26+i);                              03605000
               asmb(ssea);                                              03610000
               ddel;                                                    03615000
            end                                                         03620000
         until (i:=i+1) >= 3;                                           03625000
         ditp(cwc) := xcnt + 128;                                       03630000
         go to contxfer;                                                03635000
      end;                                                              03640000
      ditp(dstat1) := ditp(22); << set error status for exam >>         03645000
      tos.ebit := 1; << set e bit to get into error analysis >>         03650000
   end;                                                                 03655000
                                                                        03660000
$page "ERROR PROCESSING"                                       <<01549>>03665000
   tos.ebit := 0;                                                       03670000
   if <> then                                                           03675000
   begin << error status completion >>                                  03680000
     err := ditp(dstat1).errcode;                                       03685000
     ditp(dserr) := [8/5,8/dstat1]; <<set log count & index>>  <<01341>>03690000
     if err = drive'error and lditp(dstat2).drvnotrdy then     <<01549>>03695000
     begin << drive not ready >>                                        03700000
        ldevnotrdy(ditp); << send not ready message to console >>       03705000
        tos := wait;                                                    03710000
        tos := 7;                                                       03715000
        go to checksbuf;                                                03720000
     end;                                                               03725000
     if err = 7 then                                           <<02874>>03730000
     begin << cylinder miscompare error >>                              03735000
        tos.cbit := 1;                                                  03740000
        if = then                                                       03745000
        begin << try a recalibrate >>                                   03750000
           ditp(curcyl) := 0; << cyl # is 0 >>                          03755000
           siop(recalp1) := recalibrate + unit;                         03760000
           tos := @siop(recalp);                                        03765000
           go to startioprog;                                           03770000
        end;                                                            03775000
     end;                                                               03780000
                                                               <<01549>>03785000
<< everyone >>                                                 <<01549>>03790000
<< deserves >>                                                 <<01549>>03795000
                                                               <<01549>>03800000
     tos.dbit := 1; << set retry determination >>                       03805000
     if = then go to doxfer; << try once more >>                        03810000
                                                               <<01549>>03815000
<<   two    >>                                                 <<01549>>03820000
<< chances  >>                                                 <<01549>>03825000
                                                                        03830000
$page "ERROR PROCESSING -- SECOND TRY FAILED"                  <<01549>>03835000
     << error cannot be recovered >>                                    03840000
                                                                        03845000
     if funct = readspd or funct = format then                 <<rk2pv>>03850000
     if (%7<=err<=%11) or (%17<=err<=%21) then                 <<07.pv>>03855000
     begin                                                     <<07.pv>>03860000
          ditp(dserr) := 0;  <<for siodm - don't log as error>><<rh.pv>>03865000
          tos := (err & lsl(3)) + 4;  << return error >>       <<07.pv>>03870000
          go to badend;                                        <<07.pv>>03875000
     end;                                                      <<07.pv>>03880000
                                                               <<07.pv>>03885000
     if 7 <= err <= %11 then                                            03890000
     if foreign then go to discxfer                            <<01115>>03895000
     else                                                      <<01115>>03900000
     begin << track specific error >>                                   03905000
        tos.dbit := 0; << reset d bit for track map >>                  03910000
        tos.mbit := 1;                                                  03915000
        if <> then go to discxfer; << error on map xfer >>              03920000
        tos := ditp(sysbufa);                                           03925000
        if = then                                                       03930000
        begin << get a system buffer >>                                 03935000
           tos := getsbuf(1); << get a buffer >>                        03940000
           asmb(delb,dup);                                              03945000
           if = then go to discxfer; << no more buffers >>              03950000
           ditp(x) := tos;                                              03955000
        end;                                                            03960000
        ditp(cdba) := tos + sysdb; << set buffer adress >>              03965000
        asmb(dzro,inca); << double one >>                               03970000
        dditp(clda) := tos;                                             03975000
        ditp(wcr) := 128;                                               03980000
        funct := read; << set up xfer of trk map >>                     03985000
        bank := 0; << zero bank for sysbuf xfer >>                      03990000
        go to doxfer;                                                   03995000
     end;                                                               04000000
     if err = %23 and lditp(dstat2).seekcheck                           04005000
     or err = %20 then                                                  04010000
     begin << invalid disc adress >>                                    04015000
baddskadr:                                                              04020000
        tos := invdskadr;                                               04025000
badend:                                                                 04030000
        ioqp(qwbct) := 0;                                               04035000
        tos := 5;                                                       04040000
        go to checksbuf;                                                04045000
     end;                                                               04050000
     if err = %12 or err = %16 then                                     04055000
     begin << transfer error >>                                         04060000
        tos := xfererror;                                               04065000
        go to badend;                                                   04070000
     end;                                                               04075000
unitfail:                                                               04080000
     tos := unitfailure;                                                04085000
     go to badend;                                                      04090000
   end;                                                                 04095000
                                                                        04100000
$page "TRACK MAP PROCESSING"                                   <<01549>>04105000
   asmb(tbc mbit');                                                     04110000
   if <> then                                                           04115000
   begin << entring bad track into bad track table >>                   04120000
      tos.wbit := 1;                                                    04125000
      if <> then                                                        04130000
      begin << track map completed >>                                   04135000
discxfer:                                                               04140000
         tos := dscxfrerr;                                              04145000
         go to badend;                                                  04150000
      end;                                                              04155000
      @badtrack := ditp(sysbufa);                                       04160000
      if badtrack >= 120 then go to discxfer; << table full >>          04165000
      x := ceda;                                                        04170000
      tos := convertadr;                                                04175000
      tos := discinfo (subtype*numentries + secpertrack);      <<25.00>>04180000
      asmb(ldiv,del);                                                   04185000
      tos := tos&lsl(2);                                                04190000
      if lditp(dstat1).spare then tos := tos + 1;                       04195000
      << set alternate track bit >>                                     04200000
      x := 0;                                                           04205000
      while x < badtrack do                                             04210000
      begin << is track already in the table >>                         04215000
         asmb(dup,incx);                                                04220000
         if tos = badtrack(x) then go to discxfer;                      04225000
         << its already in the table >>                                 04230000
      end;                                                              04235000
      badtrack := badtrack + 1; << inc track count >>                   04240000
      badtrack(x:=x+1) := tos; << enter track >>                        04245000
      funct := write;                                                   04250000
      bank := 0;                                                        04255000
      go to doxfer;                                                     04260000
   end;                                                                 04265000
                                                                        04270000
$page "CONTINUATION / CLEANUP OF TRANSFERS"                    <<01549>>04275000
contxfer:                                                               04280000
   tos := ditp(wcr) - ditp(cwc);                                        04285000
   if <= then                                                           04290000
   begin << xfer complete >>                                            04295000
      if funct = 7 then                                        <<rk.00>>04300000
         begin                                                 <<rk.00>>04305000
            tos:=bank;                                         <<rk.00>>04310000
            tos:=buffer;                                       <<rk.00>>04315000
            tos:=0;                                            <<rk.00>>04320000
            tos:=@ditp(dstat1)+sysdb;                          <<rk.00>>04325000
            tos:=ditp(cwc);                                    <<rk.00>>04330000
           asmb(mabs 5);                                       <<rk.00>>04335000
         end;                                                  <<rk.00>>04340000
      tos := @siop(stattab);                                   <<01549>>04345000
      tos := 0;  << will be attn'bits >>                       <<01549>>04350000
      x := -1;                                                 <<01549>>04355000
      while (x:=x+1) <= 7 do                                   <<01549>>04360000
        begin                                                  <<01549>>04365000
        tos := ps1(x);                                         <<01549>>04370000
        if tos.attnbit then                                    <<01549>>04375000
           asmb(tsbc 0,x);                                     <<01549>>04380000
        end;                                                   <<01549>>04385000
      ps1(-1) := s0;  << leave a copy for dumps >>             <<01549>>04390000
      tos := tos land lsiop(s'conf'mask)                       <<01549>>04395000
             land not(lsiop(s'seek'mask));                     <<01549>>04400000
      asmb(ddel);  << get rid of @siop(statab) and tos >>      <<01549>>04405000
      if <> then                                               <<01549>>04410000
         begin                                                 <<rk0pv>>04415000
         siop(1) := @siop(allowpoll) + sysdb;                  <<rk0pv>>04420000
         siop(allowpoll+3) := %377;                            <<rk0pv>>04425000
         disable;                                              <<rk0pv>>04430000
         ditp.statef := %15;                                   <<02874>>04435000
         startio(ditp,siop,true);                              <<rk0pv>>04440000
         if > then goto siofailure;                            <<rk0pv>>04445000
         rstatus.(1:1) := 0;  << make sure we return disabled>><<rk0pv>>04450000
                              << so that state gets stored,in>><<rk0pv>>04455000
                              << case we're now off the ics  >><<rk0pv>>04460000
         tos := successful;                                    <<02874>>04465000
         tos := %15; << return state >>                        <<rk0pv>>04470000
         goto checksbuf;                                       <<rk0pv>>04475000
         end;                                                  <<rk0pv>>04480000
goodend:                                                                04485000
      tos := successful;                                                04490000
      tos := %5;                                                        04495000
checksbuf:                                                              04500000
      tos := ditp(sysbufa);                                             04505000
      if <> then                                                        04510000
      begin                                                             04515000
         returnsbuf(*);                                                 04520000
         ditp(x) := 0;                                                  04525000
      end else del;                                                     04530000
      dsiop(s'this'unitd) := 0d;  <<reset ownership>>          <<01549>>04535000
      tos := siop(s'seek'mask);                                <<01549>>04540000
      x := unit;                                               <<01549>>04545000
      asmb(trbc 0,x);                                          <<01549>>04550000
      siop(s'seek'mask) := tos; <<reset seek-in-progress>>     <<01549>>04555000
      go to exit;                                                       04560000
   end;                                                                 04565000
                                                               <<01549>>04570000
<<                  >>                                         <<01549>>04575000
<< not done yet !!! >>                                         <<01549>>04580000
<<                  >>                                         <<01549>>04585000
                                                               <<01549>>04590000
   ditp(wcr) := tos; << set remaining word count >>                     04595000
   if funct <= write then                                               04600000
   if sbflg then ditp(cdba) := calcsbufadr(ditp(cwc)) << sys buf >>     04605000
   else ditp(x) := ditp(cwc) + ditp(cdba); << data seg >>               04610000
   tos := ditp(cwc)&lsr(7);                                             04615000
   asmb(zero,xch); << update disc adress >>                             04620000
   dditp(x) := tos + dditp(clda);                                       04625000
                                                               <<01549>>04630000
<<                       >>                                    <<01549>>04635000
<< drop down into doxfer >>                                    <<01549>>04640000
<<                       >>                                    <<01549>>04645000
                                                                        04650000
$page "BUILD A DATA TRANSFER PROGRAM -- CALCULATE SEEKS "      <<01549>>04655000
   << qmisc must be on tos here >>                                      04660000
doxfer: << this section builds and starts an i/o prog >>                04665000
   tos := dditp(clda);                                                  04670000
   if = and (write<=funct<=rstat)                              <<01115>>04675000
      and not foreign <<not foreign>>                          <<01115>>04680000
      then go to baddskadr;                                    <<01115>>04685000
   << write to sector zero is a no-no >>                                04690000
   x := subtype;  << for tos'log'to'phy >>                     <<01549>>04695000
   tos'log'to'phy; << transform tos to a physical address >>   <<01549>>04700000
   asmb(dtst); if < then goto baddskadr; << overflow >>        <<01549>>04705000
   dditp(cpda) := tos; << current physical disc address >>     <<01549>>04710000
   i := 0;                                                     <<01549>>04715000
   start'addr := s'no'seek;                                    <<01549>>04720000
   tos := siop(s'seek'mask);                                   <<01549>>04725000
   x := unit;                                                  <<01549>>04730000
   asmb(tsbc 0,x);                                             <<01549>>04735000
   if = then                                                   <<01549>>04740000
      begin                                                    <<01549>>04745000
      add'seek(x,dditp(cpda));                                 <<01549>>04750000
      end;                                                     <<01549>>04755000
   disable;                                                    <<01549>>04760000
   @other'ditp := head'tab(iltp(iqueue).queuen);               <<01549>>04765000
   while i < 3 and @other'ditp > 0 do                          <<01549>>04770000
      begin                                                    <<01549>>04775000
      @other'ioqp := other'ditp(ditioqp);<<ioqp of chained dit><<01549>>04780000
      if <> and other'ioqp(qfunc).function <=1 <<rd or wr>>    <<01785>>04785000
      and other'ioqp(qwbct)<>0 then                            <<01785>>04790000
         begin                                                 <<01549>>04795000
         x := other'ditp(dldev)&unitn;                         <<01549>>04800000
         asmb(tsbc 0,x);                                       <<02874>>04805000
         if = then    << no seek yet >>                        <<01549>>04810000
            begin                                              <<01549>>04815000
            tos:=siop(s'seekenabmask);                         <<01960>>04820000
            x:=other'ditp(dldev)&unitn;                        <<01845>>04825000
            asmb(tsbc 0,x;del);                                <<01845>>04830000
            if <> then                                         <<01845>>04835000
            begin <<seek-ahead enabled for this device>>       <<01845>>04840000
            tos := x;  <<push unit for later call to add'seek>><<01549>>04845000
            tos := dother'ioqp(dadr);  <<disc address>>        <<01549>>04850000
            x := other'ioqp(qldev).qldevn;                     <<01549>>04855000
            tos := dlpdt(x);                                   <<01549>>04860000
            asmb(delb);                                        <<01549>>04865000
            x := tos.subt;  <<x := subtype for tos'log'to'phy>><<01549>>04870000
            tos'log'to'phy; <<transform tos to physical addr>> <<01549>>04875000
            asmb(dtst);                                        <<01549>>04880000
            if < then asmb(ddel,dzro); << illegal address >>   <<01549>>04885000
            add'seek(*,*);                                     <<01549>>04890000
            if gclassenabledmask.class0 then                   <<01549>>04895000
               begin  <<measure issue of pre-seek>>            <<01549>>04900000
               tos:=measstatxdsbank;                           <<01549>>04905000
               tos:=measstatxdsbase;                           <<01549>>04910000
               tos:=tos+c0sub0'segreloff+c'ovlapseekissued;    <<01549>>04915000
               asmb(lsea);                                     <<01549>>04920000
               tos:=tos+1;                                     <<01549>>04925000
               asmb(ssea;ddel);                                <<01549>>04930000
               end;                                            <<01549>>04935000
            end;                                               <<01845>>04940000
            end;                                               <<01549>>04945000
         end;                                                  <<01549>>04950000
      @other'ditp := other'ditp(dlink);                        <<01549>>04955000
      end;                                                     <<01549>>04960000
   siop(s'seek'mask) := tos;                                   <<01549>>04965000
$page "BUILD A DATA TRANSFER PROGRAM -- SETUP AD,XD,CXFER"     <<01549>>04970000
   tos := control;                                             <<01549>>04975000
   tos := discinfo (subtype*numentries + filemask);            <<25.00>>04980000
   if logical(s3&csl(1)) then tos := tos + %220;<<s3 is qmisc>><<01549>>04985000
   if funct = readspd then tos.(13:1) := 0;  <<no sparing>>    <<07.pv>>04990000
   << if retry determination is set, retry 10 times >>                  04995000
   dsiop(s'filemask'd) := tos;                                 <<01549>>05000000
   siop(s'adrec'unit) := adrrec + unit;                        <<01549>>05005000
   siop(s'adrec'cyl) := @ditp(curcyl) + sysdb;                 <<01549>>05010000
                                                               <<01549>>05015000
<< work on s'xfer'cmd >>                                       <<01549>>05020000
                                                               <<01549>>05025000
   tos := cw4k;                                                         05030000
   if funct = read or funct = readspd then                     <<07.pv>>05035000
   begin                                                                05040000
      asmb(tsbc 3); << change write to read >>                          05045000
      tos := readop;                                                    05050000
   end else                                                    <<03.pv>>05055000
   if funct = readfs then                                      <<03.pv>>05060000
   begin                                                       <<03.pv>>05065000
      asmb(tsbc 3);  << change write to read >>                <<03.pv>>05070000
      tos := readfsop;                                         <<03.pv>>05075000
   end else tos := writeop;                                             05080000
                                                               <<01549>>05085000
   siop(s'xfer'cmd) := tos + unit;                             <<01549>>05090000
   if (fopen<=funct<=rstat) or sbflg then                      <<01.pv>>05095000
   begin                                                                05100000
      tos := tos lor %7600; << cut xfer (cw4k) to 128 >>       <<01549>>05105000
      tos := 128; << transfer delta >>                                  05110000
      tos := 0;   << address  delta >>                                  05115000
      bank := 0;                                                        05120000
   end else                                                             05125000
   begin                                                                05130000
      tos := 4096;                                                      05135000
      asmb(dup);                                                        05140000
   end;                                                                 05145000
   ad := tos;                                                           05150000
   xd := tos;                                                           05155000
   cxfer := tos;                                                        05160000
                                                               <<01549>>05165000
   siop(s'bank'value) := bank;                                 <<01549>>05170000
   tos := ditp(wcr);                                                    05175000
   if (fopen<=funct<=rstat) then                               <<01.pv>>05180000
   begin << limit xfer to 1024 for fill operations >>                   05185000
      sbflg := false;                                                   05190000
      tos := 1024;                                                      05195000
      asmb(ddup,lcmp);                                                  05200000
      if < then asmb(xch);                                              05205000
      delb; << smallest left on tos >>                                  05210000
   end;                                                                 05215000
   if subtype = 4 then                                                  05220000
   begin << upper platter, check end of cyl >>                          05225000
      tos := discinfo (subtype*numentries + secpercyl);        <<25.00>>05230000
      tos := dditp(clda);                                               05235000
      tos := s2;                                                        05240000
      asmb(ldiv,delb;sub);                                              05245000
      tos := tos&lsl(7); << xfer cnt ot eoc >>                          05250000
      asmb(ddup,lcmp);                                                  05255000
      if < then asmb(xch);                                              05260000
      delb; << smallest left on tos >>                                  05265000
   end;                                                                 05270000
   asmb(dup,dup);                                                       05275000
   if = then go to goodend; << zero xfer count >>                       05280000
   ditp(cwc) := tos;                                                    05285000
   bufadr := ditp(cdba);                                                05290000
   if sbflg then checkindex(@sbuf+sysdb-bufadr,sbuf);                   05295000
$page "BUILD A DATA TRANSFER PROGRAM -- BUILD CHAINNED PART"   <<01549>>05300000
   if funct = init then  << fix up sio prog >>                 <<02.pv>>05305000
   begin                                                       <<02.pv>>05310000
      tos := bank;                                             <<02.pv>>05315000
      tos := bufadr - 2;                                       <<rk2pv>>05320000
      asmb(ldea);                                              <<06.pv>>05325000
      dditp(initaddr) := tos;                                  <<06.pv>>05330000
      asmb(deca;lsea);  << load from bufadr >>                 <<02.pv>>05335000
      asmb(delb,delb);  << delete bank and bufadr >>           <<02.pv>>05340000
      tos.(15:1) := 0;  << test and reset alt track bit>>      <<02.pv>>05345000
      siop(s'xfer'cmd) := (tos & lsl(12)) + initop + unit;     <<01549>>05350000
      siop(s'filemask) := %7402;  << file mask >>              <<01549>>05355000
      siop(s'adrec'cyl) := @ditp(initadr) + sysdb;             <<01549>>05360000
   end;                                                        <<01549>>05365000
   x := s'chain'd;                                             <<01549>>05370000
   while tos > xd do                                                    05375000
   begin << build chained xfer orders >>                                05380000
      tos := tos - xd;                                                  05385000
      dsiop(x) := dxferorder;                                           05390000
      asmb(dup,incx);                                                   05395000
      if sbflg then                                                     05400000
      begin << go to next sysbuf >>                                     05405000
         tos := x;                                                      05410000
         checkindex(abs(bufadr-1),sbuf);                                05415000
         bufadr := abs(x) + @sbuf + sysdb;                              05420000
         x := tos;                                                      05425000
      end else bufadr := bufadr + ad;                                   05430000
   end;                                                                 05435000
   asmb(neg; trbc 3); << build last xfer order >>                       05440000
   tos := tos lor logical(cxfer);                                       05445000
   asmb(trbc 0);                                                        05450000
   tos := bufadr;                                                       05455000
   dsiop(x) := tos;                                                     05460000
   if funct = format then  << fix up sio program >>            <<01.pv>>05465000
   begin                                                       <<01.pv>>05470000
      i := (x + 1) & lsl(1);                                   <<01.pv>>05475000
      siop(i     ) := setbank;                                 <<06.pv>>05480000
      siop(i:=i+1) := 0;        << bank 0 >>                   <<06.pv>>05485000
      siop(i:=i+1) := control;                                 <<rk3pv>>05490000
      siop(i:=i+1) := seek + unit;                             <<rk3pv>>05495000
      siop(i:=i+1) := %67776;  << write disc address >>        <<rk3pv>>05500000
      siop(i:=i+1) := @ditp(curcyl) + sysdb;                   <<rk3pv>>05505000
      siop(i:=i+1) := control;                                 <<01.pv>>05510000
      siop(i:=i+1) := adrrec + unit;                           <<01.pv>>05515000
      siop(i:=i+1) := %67776;  << write disc address >>        <<01.pv>>05520000
      siop(i:=i+1) := @ditp(curcyl) + sysdb;                   <<01.pv>>05525000
      siop(i:=i+1) := control;                                 <<01.pv>>05530000
      siop(i:=i+1) := verifyop + unit;                         <<01.pv>>05535000
      siop(i:=i+1) := %67777;  << write sector count >>        <<01.pv>>05540000
      siop(i:=i+1) := @ditp(scount) + sysdb;                   <<01.pv>>05545000
      siop(s'filemask) := %7402;  << file mask >>              <<01549>>05550000
      siop(s'xfer'cmd) := initop + unit;                       <<01549>>05555000
      ditp(scount) := ditp(cwc) & lsr(7);  << sector count >>  <<05.pv>>05560000
      tos := (i + 1) & lsr(1);  << double index >>             <<01.pv>>05565000
   end else                                                    <<01.pv>>05570000
   tos := x + 1;                                                        05575000
   tos := jumpc; << build jump and end orders >>                        05580000
   tos := @siop(s'loop) + sysdb;                               <<01549>>05585000
   asmb(cab,stax);                                                      05590000
   dsiop(x) := tos;                                                     05595000
   tos := endint;                                                       05600000
   tos := -1;                                                           05605000
   dsiop(x:=x+1) := tos;                                                05610000
   tos := @siop(start'addr - 1);                               <<01549>>05615000
                                                                        05620000
$page " START SIO PROGRAM -- ALSO FILL,RQST"                   <<01549>>05625000
startioprog: << start the i/o program >>                                05630000
   siop(1) := tos + sysdb; << set the jump adress >>                    05635000
   tos := unit;                                                <<01549>>05640000
   tos := @ditp;                                               <<01549>>05645000
   dsiop(s'this'unitd) := tos;                                 <<01549>>05650000
   startio(ditp,siop,true);                                             05655000
   if > then                                                            05660000
   begin << no start >>                                                 05665000
siofailure:                                                             05670000
      tos := badsio;                                                    05675000
      go to badend;                                                     05680000
   end;                                                                 05685000
   ioqp(qmisc) := tos;                                                  05690000
   tos := wait;                                                         05695000
   tos := %13;                                                          05700000
exit:                                                                   05705000
   mstate := tos;                                                       05710000
   ioqp(qstat).stat := tos;                                             05715000
   return;                                                              05720000
                                                                        05725000
fillblank:                                                              05730000
   tos := "  ";                                                         05735000
   go to fc;                                                            05740000
fillzero:                                                               05745000
   tos := 0;                                                            05750000
fc:                                                                     05755000
   tos := getsbuf(2);                                                   05760000
   asmb(dup,dup);                                                       05765000
   if = then                                                            05770000
   begin << no buffers available >>                                     05775000
      tos := syserror;                                                  05780000
      go to badend;                                                     05785000
   end;                                                                 05790000
   ditp(sysbufa) := tos;                                                05795000
   ditp(cdba) := tos + sysdb;                                           05800000
   asmb(xch);                                                           05805000
   ps1 := tos; << put fill word into first word of buffer >>            05810000
   asmb(dup,incb); << set move pointers >>                              05815000
   tos := 127; << move count >>                                         05820000
   asmb(move 3);                                                        05825000
   go to doxfer;                                                        05830000
                                                                        05835000
reqstatus:                                                     <<00.pv>>05840000
   reqstatsio;  << initialize sio program >>                   <<00.pv>>05845000
   siop(rstap8) := jump;                                       <<rk.00>>05850000
   siop(rstap9) := @siop(rqall) + sysdb;                       <<rk.00>>05855000
   tos := jump;                                                <<01549>>05860000
   tos := @siop(rstap10) + sysdb;                              <<01549>>05865000
   dsiop(s'filemask'd) := tos;                                 <<01549>>05870000
   if ditp(wcr) > 4 then ditp(wcr) := 4; <<truncate>>          <<rk.00>>05875000
   ditp(cwc) := ditp(wcr); <<make sure we pass contxfer test>> <<rk.00>>05880000
   tos := @siop(rstap);                                        <<00.pv>>05885000
   go to startioprog;                                          <<00.pv>>05890000
                                                               <<00.pv>>05895000
end;                                                                    05900000
                                                               <<rk0pv>>05905000
$page "INITIALIZATION PROCEDURE -- CALLED ONCE PER ILT"        <<01549>>05910000
procedure init7920(ditp);                                      <<rk0pv>>05915000
value ditp;                                                    <<rk0pv>>05920000
integer pointer ditp;                                          <<rk0pv>>05925000
option privileged,uncallable;                                  <<rk0pv>>05930000
                                                               <<rk0pv>>05935000
begin                                                          <<rk0pv>>05940000
   integer pointer iltp = q + 1;                               <<rk0pv>>05945000
   integer pointer siop = q + 2;                               <<rk0pv>>05950000
   integer hcu          = q + 3;  <<highest configured unit>>  <<rk0pv>>05955000
   integer unit         = q + 4;                               <<rk0pv>>05960000
   integer targaddr     = q + 5;                               <<rk0pv>>05965000
   integer progaddr     = q + 6;                               <<rk0pv>>05970000
   integer conf'mask    = q + 7;                               <<01549>>05975000
   integer x = x;                                              <<01549>>05980000
   integer s0 = s-0;                                           <<01549>>05985000
                                                               <<rk0pv>>05990000
   tos := ditp(diltp);                                         <<rk0pv>>05995000
   tos := iltp(isiop);                                         <<rk0pv>>06000000
   tos := iltp(iflag).hcunit;  <<highest configured unit>>     <<01300>>06005000
   tos := -1;  <<unit>>                                        <<rk0pv>>06010000
   tos := stattab - 1;<<targaddr in status table for 1st unit>><<rk0pv>>06015000
   tos := rqall + 31; <<progaddr in sioprog for unit 0>>       <<rk0pv>>06020000
   tos := 0;  << will be conf'mask -- must be tos !!! >>       <<01549>>06025000
   while (unit := unit + 1) <= 7 do                            <<rk0pv>>06030000
      begin                                                    <<rk0pv>>06035000
      if ( unit <= hcu ) and ( iltp(unit+iditp) > 0 ) then     <<01549>>06040000
         begin << configured unit >>                           <<01549>>06045000
         x := unit;                                            <<01549>>06050000
         asmb(tsbc 0,x);                                       <<01549>>06055000
         end;                                                  <<01549>>06060000
      siop(progaddr) := @siop(targaddr) + sysdb;               <<01549>>06065000
      targaddr := targaddr + 1;                                <<01549>>06070000
      progaddr := progaddr - 4; <<unit 0 is last in sioprog >> <<01549>>06075000
      end;                                                     <<01549>>06080000
   tos := sysdb + @siop(s'seekvalues & lsl(1) ) - 2;           <<01549>>06085000
   siop(s'no'seek - 4) := s0;                                  <<01549>>06090000
   tos := tos - 2;                                             <<01549>>06095000
   siop(x:=x-6) := s0;                                         <<01549>>06100000
   tos := tos - 2;                                             <<01549>>06105000
   siop(x:=x-6) := tos;                                        <<01549>>06110000
   siop(s'conf'mask) := conf'mask;                             <<01549>>06115000
end; << of init7920 >>                                         <<rk0pv>>06120000
$page "7905/7920/7925 MOVING HEAD DISC DRIVER -- SEEK'AHEAD"   <<01549>>06125000
asmb(                                                                   06130000
   pcal siodm;  << monitor >>                                           06135000
   pcal mhddvr; << initiator >>                                         06140000
   pcal mhddvr; << completor >>                                         06145000
   con 0;       << i/o process procedure >>                             06150000
   con 0;        << initialization procedure >>                <<01549>>06155000
   con 1;       << # of interrupt procedures >>                         06160000
   pcal gip);   << interrupt handler >>                        <<rk0pv>>06165000
end.                                                                    06170000
