$CONTROL MAP,CODE,USLINIT                                               00010000
<<IOMDISC0 - MODULE 16>>                                                00012000
<< HP32002C MPE SOURCE C.00.00 >>                                       00014000
<< COPYRIGHT     "(C) COPYRIGHT HEWLETT-PACKARD CO. 1980.           >>  00016000
<<     THIS PROGRAM MAY BE USED WITH ONE COMPUTER SYSTEM AT A       >>  00018000
<<     TIME AND SHALL NOT OTHERWISE BE RECORDED, TRANSMITTED OR     >>  00020000
<<     STORED IN A RETRIEVAL SYSTEM.  COPYING OR OTHER REPRODUCTION >>  00022000
<<     OF THIS PROGRAM EXCEPT FOR ARCHIVAL PURPOSES IS PROHIBITED   >>  00024000
<<     WITHOUT THE PRIOR WRITTEN CONSENT OF HEWLETT-PACKARD COMPANY.>>  00026000
<< **** Note - Dollar Copyright cannot be used with this module *** >>  00028000
$CONTROL MAIN=IOMDISC0                                                  00030000
$CONTROL PRIVILEGED,UNCALLABLE                                          00032000
$TITLE "7900A AND 2888A MOVING HEAD DISC DRIVER"                        00034000
$THIRTY                                                                 00036000
                                                                        00038000
DRIVER CALLING SEQUENCE                                                 00040000
                                                                        00042000
   DRIVER REQUEST CODES                                                 00044000
      0 - READ                                                          00046000
      1 - WRITE                                                         00048000
      2 - FILE OPEN                                                     00050000
      3 - FILE CLOSE                                                    00052000
      4 - DEVICE CLOSE                                                  00054000
      5 - FILL WITH ZEROS                                               00056000
      6 - FILL WITH BLANKS                                              00058000
     11 - WRITE DISC LABEL (INTERNAL FUNCTION CODE 7)                   00060000
                                                                        00062000
   COUNT - WORD/BYTE COUNT. BYTE COUNT WILL BE ROUNDED UP TO AN         00064000
           EVEN NO.                                                     00066000
                                                                        00068000
   PARAMETERS P1 AND P2 FORM A DOUBLE WORD DISC ADRESS                  00070000
                                                                        00072000
   NOTE THAT THE BUFFER ADRESS WORD OF THE IOQ IS USED AS THE BUFFER    00074000
   IN ALL FILL OPERATIONS.                                              00076000
                                                                        00078000
                                                                        00080000
DRIVER RETURN CODES:                                                    00082000
                                                                        00084000
   GENERAL STATUS             QUALIFYING STATUS                OVERALL  00086000
   0 - PENDING                1 - WAIT FOR COMPLETION           %10     00088000
   1 - SUCCESSFUL             0 - NORNAL COMPLETION             %01     00090000
   4 - IRRECOVERABLE ERROR    0 - INVALID FUNCTION              %04     00092000
                              1 - DISC XFER ERROR               %14     00094000
                              3 - I/O XFER ERROR                %34     00096000
                              4 - SIO FAILURE                   %44     00098000
                              5 - DISC UNIT FAILURE             %54     00100000
                              6 - INVALID DISC ADRESS           %64     00102000
                                                                        00104000
                                                                        00106000
                                                                        00108000
DISC CONTROLLER STATUS                                                  00110000
   BIT      7900A                2888A                                  00112000
     0      SIO OK               SAME                                   00114000
     1      SEEK CHECK           200 TPI                                00116000
     2      INTERRUPT REQUEST    SAME                                   00118000
     3      ON LINE              SAME                                   00120000
     4      DRIVE UNSAFE         SAME                                   00122000
     5      DRIVE NOT READY      SEEK INCOMPLETE                        00124000
     6      ACCESS NOT READY     UNIT BUSY                              00126000
     7      UNUSED               PACK CHANGE                            00128000
  8-12      CONTROLLER STATUS    SAME                                   00130000
 13-15      DISC UNIT NUMBER     SAME                                   00132000
                                                                        00134000
ENCODED CONTROLLER STATUS                                               00136000
   CODE     7900A                   2888A                               00138000
     0      NO ERROR                SAME                                00140000
     1      ILLEGAL OPCODE          SAME                                00142000
     3      UNUSED                  CYL # TOO BIG                       00144000
     4      SECTOR # TOO BIG        HEAD # TOO BIG                      00146000
     5      UNUSED                  TIME OUT                            00148000
     6      DEFECTIVE TRACK         SAME                                00150000
     7      HEADS MISPOSITIONED     SAME                                00152000
   %10      UNUSED                  CYCLIC ADRESS ERROR                 00154000
   %11      CYCLIC ERROR            CYCLIC DATA ERROR                   00156000
   %12      I/O PROG ERROR          SAME                                00158000
   %13      UNUSED                  SEQUENCE ERROR                      00160000
   %14      CYL OVERRUN             SAME                                00162000
   %15      ZERO SECTOR COUNT       SAME                                00164000
   %16      DATA OVERRUN            SAME                                00166000
   %20      UNUSED                  ILLEGAL TERMINATION                 00168000
   %22      HD/SECT COMPARE ERROR   UNUSED                              00170000
   %23      ACCESS NOT READY        DRIVE ERROR                         00172000
   %24      XFER ERROR              SAME                                00174000
   %26      DATA PROTECTED          UNUSED                              00176000
   %37      DRIVE ATTENTION         SAME                                00178000
                                                                        00180000
$PAGE                                                                   00182000
BEGIN                                                                   00184000
EQUATE                                                                  00186000
   ABIT'       = 4, << ALT TRACK READ BIT OF QMISC >>                   00188000
   BADADR      = %64, << BAD DISC ADRESS RETURN CODE >>                 00190000
   CBIT'       = 6, << RECALIBRATE BIT OF QMISC >>                      00192000
   CONTROL     = %40, << CONTROL CODE >>                                00194000
   CR4K        = %170000,                                               00196000
   CURCYL      = 14, << CURRENT CYL INDEX OF DIT >>                     00198000
   CW4K        = %160000,                                               00200000
   CXC         = 18, << CURRENT XFER COUNT >>                           00202000
   DADDR       = 5, << ADRESS WORD OF IOQ >>                            00204000
   DADR        = 5, << DOUBLE WORD DISC ADRESS OF DIT >>                00206000
   DALTADR     = 6, << DOUBLE INDEX OF ALT. TRK. # >>                   00208000
   DATAOVERRUN = %16, << DATA OVERRUN CONTROLLER CODE >>                00210000
   DBUFF       = 15, << CURRENT BUFFER ADRESS IN DIT >>                 00212000
   DISCERR     = %14, << DISC XFER ERROR RETURN STATUS >>               00214000
   DLDEV       = 3, << LOGICAL DEVICE INDEX OF DIT >>                   00216000
   DLOGERROR   = 20, <<ERROR LOG STATUS>>                      <<01336>>00218000
   DMAMQ       = 8, << INDEX OF MEM.MANAGR. REQ. IN DIT >>              00220000
   DNXTBUFF    = 16, << NEXT BUFFER ADRESS >>                           00222000
   DQPAR1      = 4, << DOUBLE WORD DISC ADR OF IOQ >>                   00224000
   DSERR       = 7, << ERROR STATUS INDEX OF DIT >>                     00226000
   DSTAT       = 6, << DEVICE STAT. INDEX OF DIT >>                     00228000
   DSYSBA      = 19, << SYSBUF ADRESS INDEX OF DIT >>                   00230000
   ENDINT      = %034000,                                               00232000
   ENDNOINT    = %030000,                                               00234000
   FILL        = %167777,                                               00236000
   FILLB       = 6, << FILL BLANK FUNCTION >>                           00238000
   FILLZ       = 5, << FILL WITH ZEROS FUNCTION >>                      00240000
   INVFUNC     = 4, << INVALID FUNCTION RETURN CODE >>                  00242000
   IOXFERERR   = %34, << I/O TRANSMISSION ERROR RETURN STATUS >>        00244000
   ISS         = 3, << 2888A SUBTYPE CODE >>                            00246000
   MBIT'       = 0, << TRACKMAP BIT OF QMISC >>                         00248000
   NOTREADY    = %23, << DRIVE BUSY RETURN CODE >>                      00250000
   QADDR       = 5, << BUFFER ADRESS WORD OF IOQ >>                     00252000
   OFFSET      = 13, << SECTOR OFFSET IN ALT TRACK >>                   00254000
   QFUNC       = 6, << FUNCTION INDEX OF IOQ >>                         00256000
   QLDEV       = 2, << LOGICAL DEVICE INDEX OF IOQ >>                   00258000
   QMISC       = 3, << MISC INDEX OF IOQ >>                             00260000
   QSTAT       = 10, << STATUS INDEX OF IOQ >>                          00262000
   QWBCT       = 7, << XFER COUNT OF IOQ >>                             00264000
   RA          = 4, << READ ADRESS CODE >>                              00266000
   RBIT'       = 1, << READ BTT BIT OF QMISC >>                         00268000
   READ128     = %077600,                                               00270000
   READ4       = %077774,                                               00272000
   READF       = 0, << READ FUNCTION >>                                 00274000
   READOP      = %050000,                                               00276000
   RECALIBRATE = %010000,                                               00278000
   RNFS        = %12, << READ NEXT FULL SECTOR CODE >>                  00280000
   SAL         = 3, << SUBTYPE ARRAY LENGTH >>                          00282000
   SBIT'       = 7, << SEEK BIT OF QMISC >>                             00284000
   SEEK        = %020000,                                               00286000
   SIOFAIL     = %44, << SIO FAIL STATUS RETURN >>                      00288000
   SUCCESS     = 1, << SUCCESSFUL COMPLETION STATUS RETURN >>           00290000
   SUSPALT     = 1, << SUSPECTED ALTERNATE DISC CODE >>                 00292000
   SUSPTRK     = 0, << SUSPECTED TRACK DISC CODE >>                     00294000
   SYSDB       = %1000,                                                 00296000
   SYSLPDT     = 8, << DB INDEX OF LPDT >>                              00298000
   SYSSBUF     = 6, << DB INDEX OF SBUF POINTER >>                      00300000
   TBIT'       = 3, << TRACK BY TRACK BIT OF QMISC >>                   00302000
   TMREAD      = %050001,                                               00304000
   TMWRITE     = %100001,                                               00306000
   TRKFLGDEF   = 6, << TRACK FLAGGED DEFECTIVE STATUS CODE >>           00308000
   UNITFAIL    = %54, << UNIT FAIL RETURN STATUS >>                     00310000
   WAIT        = %10, << WAIT FOR COMPLETION RETURN STATUS >>           00312000
   WBIT'       = 2, << WRITE BTT BIT OF QMISC >>                        00314000
   WCR         = 17, << WORD COUNT REMAINING OF DIT >>                  00316000
   WRITE128    = %067600,                                               00318000
   WRITEOP     = %100000,                                               00320000
   XBIT'       = 5, << XFER FROM ALT TRK BIT OF QMISC >>                00322000
   XFER128     = %007600,                                               00324000
   XFERERR     = %24; << I/O XFER ERROR RETURN STATUS >>                00326000
DEFINE                                                                  00328000
    ABIT       = (ABIT':1)#,                                            00330000
    ABS        = ABSOLUTE#,                                             00332000
    ASMB       = ASSEMBLE#,                                             00334000
    CBIT       = (CBIT':1)#,                                            00336000
    DISABLE    = ASSEMBLE(SED 0)#,                                      00338000
    DUPLICATE  = ASSEMBLE(DUP)#,                                        00340000
    ERRCODE    = (8:5)#, << ENCODED DISC RETURN STATUS >>               00342000
    FUNC       = (8:8)#, << FUNCTION FIELD OF QFUNC >>                  00344000
    HSECTOR    = (9:7)#, << SECTOR AND LSB OF HEAD >>                   00346000
    LIMIT      = (10:1)#, << RESTRICTED I/O ACTIVITY BIT OF DIT >>      00348000
    LSHBIT     = (9:1)#, << LSB OF HEAD FIELD >>                        00350000
    MBIT       = (MBIT':1)#,                                            00352000
    QLDEVN     = (8:8)#, << LOGICAL DEVICE FIELD OF IOQ >>              00354000
    RBIT       = (RBIT':1)#,                                            00356000
    RETRY      = (12:4)#, << RETRY COUNT FIELD OF QMISC >>              00358000
    SBIT       = (SBIT':1)#,                                            00360000
    SFAIL      = (10:1)#, << SIO FAILURE BIT SENT BY GIP IN IOQ >>      00362000
    SPEC       = (1:1)#, << MAM REQ BIT OF IOQ FOR DISCS >>             00364000
    STAT       = (8:8)#, << STATUS RETURN FIELD OF IOQ >>               00366000
    SUBT       = (12:4)#, << SUBTYPE FIELD OF LPDT >>                   00368000
    SYSBUFR    = (3:1)#, << SYSTEM BUFFER BIT OF IOQ >>                 00370000
    TBIT       = (TBIT':1)#,                                            00372000
    TRACK      = (2:14)#, << ALT TRACK FIELD >>                         00374000
    WBIT       = (WBIT':1)#,                                            00376000
    XBIT       = (XBIT':1)#;                                            00378000
INTEGER POINTER                                                         00380000
    SBUF       = DB + SYSSBUF;                                          00382000
DOUBLE POINTER                                                          00384000
    DLPDT      = DB + SYSLPDT;                                          00386000
ARRAY INITIAL(0:46) = DB :=                                    <<01336>>00388000
    %012441,  <<DIT SIZE= 21, CORE RES., DVR TYPE= 1>>         <<01336>>00390000
          0,                                                            00392000
    %037407, << UNIT EXTRACT INSTRUCTION (ANDI 7) >>                    00394000
    [8/%13,8/0],  <<22 WORD I/O PROG AREA >>                   <<01300>>00396000
    %040100,  <<DFLAG>>  << DIT WORD 0, DISC, MH DISC >>       <<01336>>00398000
        0,    <<DLINK>>                                        <<01336>>00400000
        0,    <<DIOQP>>                                        <<01336>>00402000
        0,    <<DLDEV>>                                        <<01336>>00404000
        0,    <<DLTP>>                                         <<01336>>00406000
        0,    <<DILTP>>                                        <<01336>>00408000
        0,    <<DSTAT>>                                        <<01336>>00410000
        0,    <<DSERR>> <<INDEX & COUNT OF HARWARE STATUS>>    <<01336>>00412000
        0,    <<DMAMQ>>                                        <<01336>>00414000
        0,    <<DMAMQT>>                                       <<01336>>00416000
        0,    <<DADR  - DOUBLE WORD>>                          <<01336>>00418000
        0,                                                     <<01336>>00420000
        0,    <<DALTADR  - DOUBLE WORD>>                       <<01336>>00422000
        0,                                                     <<01336>>00424000
        0,    <<CURCYL>>                                       <<01336>>00426000
        0,    <<DBUFF>>                                        <<01336>>00428000
        0,    <<DNXTBUFF>>                                     <<01336>>00430000
        0,    <<WCR>>                                          <<01336>>00432000
        0,    <<CWC>>                                          <<01336>>00434000
        0,    <<DSYSBA>>                                       <<01336>>00436000
        0,    <<DLOGERROR>>                                    <<01336>>00438000
    %014000, << I/O PROG AREA - SET BANK >>                             00440000
      21(0); << REST OF I/O PROG AREA >>                                00442000
$PAGE                                                                   00444000
PROCEDURE CHECKINDEX(INDEX,TABLE);                                      00446000
VALUE INDEX,TABLE;                                                      00448000
INTEGER INDEX;                                                          00450000
INTEGER POINTER TABLE;                                                  00452000
OPTION EXTERNAL;                                                        00454000
                                                                        00456000
PROCEDURE DCONVERT(WORD);                                               00458000
VALUE WORD;                                                             00460000
INTEGER WORD;                                                           00462000
OPTION EXTERNAL;                                                        00464000
                                                                        00466000
INTEGER PROCEDURE GETSBUF(TYPE);                                        00468000
VALUE TYPE;                                                             00470000
INTEGER TYPE;                                                           00472000
OPTION EXTERNAL;                                                        00474000
                                                                        00476000
PROCEDURE GIP;                                                          00478000
OPTION EXTERNAL;                                                        00480000
                                                                        00482000
PROCEDURE HELP;                                                         00484000
OPTION EXTERNAL;                                                        00486000
                                                                        00488000
PROCEDURE LDEVNOTRDY(DITP);                                             00490000
VALUE DITP;                                                             00492000
POINTER DITP;                                                           00494000
OPTION EXTERNAL;                                                        00496000
                                                                        00498000
PROCEDURE MMSTAT(E,P1,P2,P3);                                           00500000
VALUE E,P1,P2,P3;                                                       00502000
INTEGER E,P1,P2,P3;                                                     00504000
OPTION EXTERNAL;                                                        00506000
                                                                        00508000
PROCEDURE SIODM(DITP,FLAGS);                                            00510000
VALUE DITP,FLAGS;                                                       00512000
INTEGER POINTER DITP;                                                   00514000
LOGICAL FLAGS;                                                          00516000
OPTION EXTERNAL;                                                        00518000
                                                                        00520000
PROCEDURE RETURNSBUF(SBUFP);                                            00522000
VALUE SBUFP;                                                            00524000
INTEGER SBUFP;                                                          00526000
OPTION EXTERNAL;                                                        00528000
                                                                        00530000
PROCEDURE STARTIO(DITP,SIOP,QUEUE);                                     00532000
VALUE DITP,SIOP,QUEUE;                                                  00534000
INTEGER POINTER DITP,SIOP;                                              00536000
LOGICAL QUEUE;                                                          00538000
OPTION EXTERNAL;                                                        00540000
                                                                        00542000
PROCEDURE WRITE2(WORD);                                                 00544000
VALUE WORD;                                                             00546000
INTEGER WORD;                                                           00548000
OPTION EXTERNAL;                                                        00550000
$PAGE                                                                   00552000
INTEGER PROCEDURE MHDDVR(IOQP,DITP,BANK,BUFADR,SIOP,DRTN);              00554000
VALUE IOQP,DITP,BANK,BUFADR,SIOP,DRTN;                                  00556000
INTEGER BANK,BUFADR,DRTN;                                               00558000
INTEGER POINTER IOQP,DITP,SIOP;                                         00560000
OPTION PRIVILEGED,UNCALLABLE;                                           00562000
BEGIN                                                                   00564000
INTEGER ARRAY SEC'TRK(0:SAL) = PB := 48,48,48,23;                       00566000
INTEGER ARRAY SEC'CYL(0:SAL) = PB := 48,48,96,460;                      00568000
LOGICAL ARRAY MAXCYL(0:SAL)  = PB := 203,203,203,406;                   00570000
INTEGER ARRAY SEC'HEAD(0:SAL)= PB := 24,24,24,23;                       00572000
INTEGER ARRAY HEADBASE(0:SAL)= PB := 0,%200,0,0;                        00574000
INTEGER ARRAY SEC'XFER(0:SAL)= PB := 48,48,48,460;                      00576000
                                                                        00578000
DOUBLE POINTER                                                          00580000
   DDITP       = DITP,                                                  00582000
   DIOQP       = IOQP,                                                  00584000
   DSIOP       = SIOP;                                                  00586000
INTEGER                                                                 00588000
   AD          = Q+7, << ADRESS DELTA >>                                00590000
   DERR        = Q+3, << DISC ERROR CODE >>                             00592000
   I           = Q+4, << I/O PROG INDEX >>                              00594000
   MSTATE      = MHDDVR, << SIO DEVICE MONITOR STATE >>                 00596000
   S0          = S-0,                                                   00598000
   S2          = S-2,                                                   00600000
   SUBTYPE     = Q+5, << DEVICE SUBTYPE >>                              00602000
   X           = X,                                                     00604000
   XD          = Q+6, << TRANSFER DELTA >>                              00606000
   XFER        = Q+2; << I/O TRANSFER INSTRUCTION >>                    00608000
INTEGER POINTER                                                         00610000
   BADTRACK    = Q+1;                                                   00612000
LOGICAL                                                                 00614000
   SIOCOUNT    = DB+%60; << SIO PROGRAM COUNTER >>                      00616000
LOGICAL POINTER                                                         00618000
   LIOQP       = IOQP;                                                  00620000
                                                                        00622000
                                                                        00624000
   ASMB(ADDS 3); << INITIALIZE >>                                       00626000
   TOS := 2; << I >>                                                    00628000
   TOS := DLPDT(IOQP(QLDEV).QLDEVN);                                    00630000
   DELB;                                                                00632000
   TOS := TOS.SUBT; << DEVICE SUBTYPE >>                                00634000
   TOS := 4096; << XD >>                                                00636000
   DUPLICATE; << AD >>                                                  00638000
   IF MSTATE = 2 THEN                                                   00640000
   BEGIN << NEW REQUEST >>                                              00642000
      TOS := IOQP(QWBCT);                                               00644000
      IF < THEN                                                         00646000
      BEGIN << COUNT IN BYTES >>                                        00648000
         DUPLICATE;                                                     00650000
         IF TOS THEN IOQP(X) := IOQP(X) - 1; << ROUND TO EVEN COUNT >>  00652000
         TOS := -(TOS&ASR(1)); << CONVERT TO WORDS >>                   00654000
      END;                                                              00656000
      DITP(WCR) := TOS; << SET REMAINING WORD COUNT >>                  00658000
      DDITP(DADR) := DIOQP(DQPAR1); << SET DISC ADRESS >>               00660000
      DITP(DBUFF) := BUFADR; << SET CURRENT BUFFER ADRESS >>            00662000
      IF IOQP(QFUNC).FUNC = 7 THEN GO TO INVALIDFUNC;          <<02847>>00664000
      TOS := IF IOQP(QFUNC).FUNC = 11 THEN 7                   <<02847>>00666000
        ELSE IOQP(QFUNC).FUNC; << MAP FCODE 11 TO FCODE 7 >>   <<02847>>00668000
      DUPLICATE;                                                        00670000
      IF < OR TOS > 7 THEN                                     <<02847>>00672000
      BEGIN << INVALID FUNCTION >>                                      00674000
INVALIDFUNC:                                                            00676000
         TOS := INVFUNC;                                                00678000
         GO TO BADEND;                                                  00680000
      END;                                                              00682000
      IF LIOQP.SYSBUFR AND DITP(WCR) > 1024 THEN GO TO INVALIDFUNC;     00684000
      X := TOS;                                                         00686000
      TOS := 0; << RESET QMISC >>                                       00688000
      ASMB(LOAD SWT,X; ADAX; BR SWT,X;                                  00690000
SWT:                                                                    00692000
      CON DOXFER;  CON DOXFER;   CON GOODEND;   CON GOODEND;   <<02847>>00694000
      CON GOODEND; CON FILLZERO; CON FILLBLANK; CON DOXFER);   <<02847>>00696000
      HELP;                                                             00698000
   END;                                                                 00700000
   IF LIOQP.SFAIL THEN GO TO SIOFAILURE; << GIP FAILED TO START I/O >>  00702000
   TOS := IOQP(QMISC);                                                  00704000
   TOS.SBIT := 0;                                                       00706000
   IF <> THEN                                                           00708000
   BEGIN << SEEK COMPLETE >>                                            00710000
      ASMB(TBC MBIT');                                                  00712000
      IF = THEN GO TO DOXFER ELSE GO TO TRACKMAP;                       00714000
   END;                                                                 00716000
   DERR := DITP(DSTAT).ERRCODE; << CHECK FOR ERRORS >>                  00718000
   IF = THEN                                                            00720000
   BEGIN << NO ERRORS >>                                                00722000
      ASMB(TBC MBIT');                                                  00724000
      IF <> THEN                                                        00726000
      BEGIN << DOING BAD TRACK MAP UPDATE >>                            00728000
TRACKMAP:                                                               00730000
         ASMB(TBC WBIT');                                               00732000
         IF <> THEN                                                     00734000
         BEGIN << COMPLETED WRITE OF TRACK MAP >>                       00736000
RETURNSB:                                                               00738000
            RETURNSBUF(DITP(DSYSBA));                                   00740000
            GO TO DISCERROR;                                            00742000
         END;                                                           00744000
         TOS.RBIT := 1;                                                 00746000
         IF = THEN                                                      00748000
         BEGIN << READ BAD TRACK MAP >>                                 00750000
            TOS := DITP(DLDEV)&LSR(8);                                  00752000
            TOS := (TOS + CONTROL)&LSL(9);                              00754000
            TOS := TMREAD + HEADBASE(SUBTYPE);                          00756000
            DSIOP(1) := TOS;                                            00758000
            SIOP(X) := 0; << ZERO BANK >>                               00760000
            TOS := READ128;                                             00762000
            TOS := GETSBUF(1);                                          00764000
            DUPLICATE;                                                  00766000
            IF = THEN GO TO DISCERROR;                                  00768000
            DITP(DSYSBA) := TOS;                                        00770000
            TOS := TOS + SYSDB;                                         00772000
            DSIOP(2) := TOS;                                            00774000
            I := I + 1;                                                 00776000
            TOS := ENDINT;                                              00778000
            GO TO ENDIO;                                                00780000
         END ELSE                                                       00782000
         BEGIN << PUT BAD TRACK INTO TABLE >>                           00784000
            @BADTRACK := DITP(DSYSBA);                                  00786000
            IF BADTRACK >= 120 THEN GO TO RETURNSB;                     00788000
            ASMB(TBC XBIT');                                            00790000
            IF <> THEN                                                  00792000
            BEGIN << SUSPECTED ALTERNATE >>                             00794000
               TOS := SUSPALT;                                          00796000
               X := DALTADR;                                            00798000
            END ELSE                                                    00800000
            BEGIN << SUSPECT TRACK >>                                   00802000
               TOS := SUSPTRK;                                          00804000
               X := DADR;                                               00806000
            END;                                                        00808000
            TOS := DDITP(X);                                            00810000
            TOS := SEC'TRK(SUBTYPE);                                    00812000
            ASMB(LDIV,DEL);                                             00814000
            TOS := TOS&LSL(2) LOR TOS;                                  00816000
            X := 0;                                                     00818000
            WHILE X < BADTRACK DO                                       00820000
            BEGIN << SEE IF TRACK IS ALREADY IN TABLE >>                00822000
               ASMB(DUP,INCX);                                          00824000
               IF TOS = BADTRACK(X) THEN GO TO RETURNSB;                00826000
            END;                                                        00828000
            BADTRACK(X:=X+1) := TOS;                                    00830000
            BADTRACK := BADTRACK + 1;                                   00832000
            SIOP(3) := TMWRITE + HEADBASE(SUBTYPE);                     00834000
            SIOP(4) := WRITE128;                                        00836000
            TOS.WBIT := 1;                                              00838000
            GO TO EXECIO;                                               00840000
         END;                                                           00842000
      END;                                                              00844000
      ASMB(TBC TBIT');                                                  00846000
      IF <> THEN                                                        00848000
      BEGIN << TRACK BY TRACK XFER >>                                   00850000
         ASMB(TBC ABIT');                                               00852000
         IF <> THEN                                                     00854000
         BEGIN << READING ALT. TRACK # >>                               00856000
            IF SIOP(12) <> SIOP(14) THEN GO TO RETRYOP;                 00858000
            TOS := SIOP(X).TRACK;                                       00860000
            IF = THEN GO TO INVADR;                                     00862000
            IF SUBTYPE = 2 THEN TOS.(7:1) := 1;                         00864000
            TOS := SEC'TRK(SUBTYPE);                                    00866000
            ASMB(LMPY,ZERO);                                            00868000
            TOS := DITP(OFFSET);                                        00870000
            DDITP(DALTADR) := DDITP(DADR);                              00872000
            ASMB(DECX,DADD);                                            00874000
            DDITP(X) := TOS;                                            00876000
            TOS.ABIT := 0;                                              00878000
            TOS.XBIT := 1;                                              00880000
            GO TO DOXFER;                                               00882000
         END;                                                           00884000
         TOS.XBIT := 0;                                                 00886000
         IF <> THEN DDITP(DADR) := DDITP(DALTADR);                      00888000
         << REPLACE ORIG. DISC ADR IF ALT. XFER. COMPLETE >>            00890000
      END;                                                              00892000
      TOS := DITP(CXC);                                                 00894000
      ASMB(DUP,NEG); << UPDATE XFER CNT & DISC ADRESS >>                00896000
      DITP(X) := TOS + DITP(WCR);                                       00898000
      IF <= THEN                                                        00900000
      BEGIN << XFER COMPLETED >>                                        00902000
GOODEND:                                                                00904000
         TOS := SUCCESS;                                                00906000
BADCONT:                                                                00908000
         MSTATE := 5;                                                   00910000
         GO TO DONE;                                                    00912000
      END;                                                              00914000
      TOS := TOS&LSR(7); << CONVERT WORDS TO SECTORS >>                 00916000
      ASMB(ZERO,XCH); << UPDATE DISC ADRESS >>                          00918000
      DDITP(X) := TOS + DDITP(DADR);                                    00920000
      DITP(DBUFF) := DITP(DNXTBUFF); << UPDATE BUFFER ADRESS >>         00922000
      GO TO DOXFER;                                                     00924000
   END ELSE                                                             00926000
   BEGIN << DISC HAD AN ERROR >>                                        00928000
      IF DERR = TRKFLGDEF THEN                                          00930000
      BEGIN << FLAGGED DEFECTIVE TRACK >>                               00932000
         TOS.TBIT := 1;                                                 00934000
         IF = THEN GO TO DOXFER; << REDO TRK BY TRK >>                  00936000
         TOS := SIOP(3).HSECTOR; << DETERMINE SECTOR OFFSET IN TRK >>   00938000
         TOS.LSHBIT := 0;                                               00940000
         IF <> AND SUBTYPE <> ISS THEN TOS := TOS + 24;                 00942000
         << ADD HEAD OFFSET FOR 7900 DISC >>                            00944000
         DITP(OFFSET) := TOS;                                           00946000
         IF SUBTYPE = ISS THEN TOS := RA ELSE TOS := RNFS;              00948000
         TOS := SIOP(3)&LSL(4);                                         00950000
         SIOP(X) := TOS&DLSR(4);                                        00952000
         DEL;                                                           00954000
         TOS := READ4;                                                  00956000
         TOS := @SIOP(12) + SYSDB;                                      00958000
         DSIOP(2) := TOS;                                               00960000
         I := I + 1;                                                    00962000
         IF SUBTYPE <> ISS THEN                                         00964000
         BEGIN << READ ALT TRACK IN TWO PARTS FOR 7900 >>               00966000
            TOS := DSIOP(X);                                            00968000
            ASMB(INCA,INCA);                                            00970000
            DSIOP(4) := TOS;                                            00972000
            DSIOP(3) := DSIOP(1);                                       00974000
            I := 5;                                                     00976000
         END;                                                           00978000
         SIOP(1) := 0; << ZERO BANK FOR ADRESS READ >>                  00980000
         TOS.ABIT := 1;                                                 00982000
         TOS := ENDINT;                                                 00984000
         GO TO ENDIO;                                                   00986000
      END;                                                              00988000
      IF DERR = NOTREADY THEN                                           00990000
      BEGIN << DISC IS IN NOT READY CONDITION >>                        00992000
         LDEVNOTRDY(DITP);                                              00994000
         MSTATE := 7;                                                   00996000
         TOS := WAIT;                                                   00998000
         GO TO DONE;                                                    01000000
      END;                                                              01002000
      DITP(DSERR):= [8/1,8/DLOGERROR];<<SET LOG COUNT & INDEX>><<01336>>01004000
      DITP(DLOGERROR):= DITP(DSTAT);    <<LOG ERROR>>          <<01336>>01006000
RETRYOP:                                                                01008000
      ASMB(INCA,DUP);                                                   01010000
      MMSTAT(101,DITP(DSTAT),S0,                                        01012000
      LIOQP(QLDEV).QLDEVN LOR SIOCOUNT&LSL(8));                         01014000
      IF TOS.RETRY < 10 THEN GO TO EXECIO; << RETRY 10 TIMES >>         01016000
      TOS.CBIT := 1;                                                    01018000
      IF = THEN                                                         01020000
      BEGIN << ISSUE A RECALIBRATE TO DRIVE >>                          01022000
RECAL:                                                                  01024000
         TOS := DITP(DLDEV)&LSR(8);                                     01026000
         TOS := (TOS + CONTROL)&LSL(9);                                 01028000
         TOS := RECALIBRATE;                                            01030000
         DSIOP(1) := TOS;                                               01032000
         TOS := TOS LAND -16;                                           01034000
         TOS.SBIT := 1;                                                 01036000
         TOS := ENDNOINT;                                               01038000
         GO TO ENDIO;                                                   01040000
      END;                                                              01042000
      ASMB(TBC MBIT');                                                  01044000
      IF <> THEN GO TO RETURNSB;                                        01046000
      TOS.ABIT := 0;                                                    01048000
      IF <> THEN                                                        01050000
      BEGIN << COULDN'T READ ALT. TRK. # >>                             01052000
         TOS.MBIT := 1;                                                 01054000
         GO TO RECAL;                                                   01056000
      END;                                                              01058000
      IF DERR = DATAOVERRUN OR DERR = XFERERR THEN                      01060000
      BEGIN << I/O XMISSION ERROR >>                                    01062000
         TOS := BANK; << ATTEMPT TO LOCATE PARITY ERROR >>              01064000
         TOS := BUFADR;                                                 01066000
         TOS := IOQP(QWBCT);                                            01068000
         IF < THEN TOS := -(TOS&ASR(1));                                01070000
         X := TOS;                                                      01072000
         DO << IF PARITY ERROR IS ENCOUNTERED, >>                       01074000
         BEGIN << ININ WILL BE INVOKED >>                               01076000
            ASMB(LSEA);                                                 01078000
            DEL;                                                        01080000
            TOS := TOS + 1;                                             01082000
         END UNTIL DXBZ;                                                01084000
         TOS := IOXFERERR;                                              01086000
BADEND:                                                                 01088000
         IOQP(QWBCT) := 0;                                              01090000
         GO TO BADCONT;                                                 01092000
      END;                                                              01094000
      IF 5 <= DERR <= %11 OR DERR = %13 OR DERR = %22 THEN              01096000
      BEGIN << TRACK SPECIFIC ERROR >>                                  01098000
         TOS.TBIT := 1; << SET TRACK BY TRACK >>                        01100000
         IF = THEN GO TO DOXFER; << REDO XFER TO DET. TRK # >>          01102000
         TOS.MBIT := 1;                                                 01104000
         GO TO RECAL; << PUT TRACK INTO B T T >>                        01106000
DISCERROR:                                                              01108000
         TOS := DISCERR;                                                01110000
         GO TO BADEND;                                                  01112000
      END;                                                              01114000
      TOS := UNITFAIL; << UNIT FAILURE >>                               01116000
      GO TO BADEND;                                                     01118000
   END;                                                                 01120000
                                                                        01122000
                                                                        01124000
FILLBLANK:                                                              01126000
   TOS := "  ";                                                         01128000
   GO TO FC;                                                            01130000
FILLZERO:                                                               01132000
   TOS := 0;                                                            01134000
FC:                                                                     01136000
   IOQP(QADDR) := TOS;                                                  01138000
   DITP(DBUFF) := @IOQP(QADDR) + SYSDB; << SET BUFFER ADRESS >>         01140000
                                                                        01142000
DOXFER: << QMISC MUST BE ON TOS HERE >>                                 01144000
   TOS := DDITP(DADR);                                                  01146000
   IF = AND (1 <= IOQP(QFUNC) <= 6) THEN                       <<02847>>01148000
     GO TO INVADR;   << READ & WRT LBL TO SECTOR 0 ONLY >>     <<02847>>01150000
   TOS := SEC'CYL(SUBTYPE);                                             01152000
   ASMB(LDIV,XCH; DUP,DUP); << COMPUTE CYLINDER ADRESS >>               01154000
   IF OVERFLOW OR TOS >= MAXCYL(X) THEN                                 01156000
   BEGIN << CYL ADRESS OUT OF RANGE >>                                  01158000
INVADR:                                                                 01160000
      TOS := BADADR;                                                    01162000
      GO TO BADEND;                                                     01164000
   END;                                                                 01166000
   TOS := DITP(DLDEV)&LSR(8); << UNIT NUMBER >>                         01168000
   TOS := (TOS + CONTROL)&LSL(9);                                       01170000
   ASMB(OR,XCH); << CONTROL, UNIT, AND CYL # >>                         01172000
   IF TOS <> DITP(CURCYL) THEN                                          01174000
   BEGIN << SEEK REQUIRED >>                                            01176000
      TOS := SEEK;                                                      01178000
      DSIOP(1) := TOS; << CONTROL SEEK >>                               01180000
      DEL;                                                              01182000
      TOS.SBIT := 1; << SET SEEK BIT OF QMISC >>                        01184000
      TOS := ENDNOINT;                                                  01186000
   END ELSE                                                             01188000
   BEGIN << DO XFER >>                                                  01190000
      ASMB(XCH); << COMPUTE HEAD AND SECTOR ADRESS >>                   01192000
      TOS := SEC'HEAD(SUBTYPE);                                         01194000
      ASMB(DIV,XCH);                                                    01196000
      TOS := TOS&LSL(6) + HEADBASE(X);                                  01198000
      IF IOQP(QFUNC) = READF THEN TOS := READOP ELSE TOS := WRITEOP;    01200000
      ASMB(OR,OR); << OPCODE, HEAD, AND SECTOR # >>                     01202000
      DSIOP(1) := TOS; << SET CONTROL >>                                01204000
      X := SUBTYPE;                                                     01206000
      ASMB(TBC TBIT'); << DETERMINE MAXIMUM XFER >>                     01208000
      IF <> THEN TOS := SEC'TRK(X) ELSE TOS := SEC'XFER(X);             01210000
      TOS := DDITP(DADR);                                               01212000
      TOS := S2;                                                        01214000
      ASMB(LDIV,DELB; SUB); << SECTORS REMAINING TO EOT >>              01216000
      TOS := TOS&LSL(7); << MAX. WORD XFER >>                           01218000
      TOS := DITP(WCR);                                                 01220000
      IF = THEN GO TO GOODEND; << ZERO XFER IS A NO-OP >>               01222000
      ASMB(DDUP,LCMP);                                                  01224000
      IF < THEN ASMB(XCH); << SMALLEST TO TOS >>                        01226000
      DELB;                                                             01228000
      IF IOQP(QFUNC) < FILLZ OR IOQP(QFUNC)=11 THEN            <<02847>>01230000
      BEGIN << READ OR WRITE >>                                         01232000
         IF IOQP(X) = READF THEN TOS := CR4K ELSE TOS := CW4K;          01234000
         IF LIOQP.SYSBUFR THEN                                          01236000
         BEGIN                                                          01238000
            TOS := TOS + XFER128; << AJUST XFER ORDER >>                01240000
            CHECKINDEX(@SBUF + SYSDB - BUFADR,SBUF);                    01242000
            XD := 128;                                                  01244000
            AD := 0;                                                    01246000
         END;                                                           01248000
         TOS := BANK; << SET BANK ON NORMAL READ/WRITE >>               01250000
      END ELSE                                                          01252000
      BEGIN << FILL >>                                                  01254000
         TOS := 1024;                                                   01256000
         ASMB(DDUP,CMP);                                                01258000
         IF < THEN ASMB(XCH);                                           01260000
         DELB; << XFER CAN'T EXCEED 1024 >>                             01262000
         XD := 128;                                                     01264000
         AD := 0;                                                       01266000
         TOS := FILL;                                                   01268000
         TOS := 0; << ZERO BANK NUMBER FOR FILL OPERATIONS >>           01270000
      END;                                                              01272000
      SIOP(1) := TOS; << SET BANK >>                                    01274000
      XFER := TOS; << XFER ORDER >>                                     01276000
      BUFADR := DITP(DBUFF);                                            01278000
      ASMB(DUP,DUP);                                                    01280000
      DITP(CXC) := TOS; << CURRENT XFER COUNT >>                        01282000
      WHILE TOS > XD DO                                                 01284000
      BEGIN << BUILD A CHAINED XFER ORDER >>                            01286000
         TOS := TOS - XD; << DECREMENT COUNT >>                         01288000
         TOS := XFER;                                                   01290000
         TOS := BUFADR;                                                 01292000
         DSIOP(I) := TOS;                                               01294000
         I := I + 1;                                                    01296000
         IF LIOQP.SYSBUFR THEN                                          01298000
         BEGIN << CHECK SYSBUF INDEX AND CALC. NEXT BUF ADR >>          01300000
            CHECKINDEX(ABSOLUTE(BUFADR-1),SBUF);                        01302000
            BUFADR := ABSOLUTE(X) + @SBUF + SYSDB;                      01304000
         END;                                                           01306000
         BUFADR := BUFADR + AD;                                         01308000
         DUPLICATE;                                                     01310000
      END;                                                              01312000
      ASMB(DUP,NEG; TRBC 3);                                            01314000
      TOS := TOS LOR LOGICAL(XFER);                                     01316000
      ASMB(TRBC 0); << BUILD LAST UNCHAINED ORDER >>                    01318000
      TOS := BUFADR;                                                    01320000
      DSIOP(I) := TOS;                                                  01322000
      I := I + 1;                                                       01324000
      IF LIOQP.SYSBUFR THEN                                             01326000
      BEGIN << GET NEXT SYSBUF ADRESS >>                                01328000
         DEL;                                                           01330000
         TOS := ABS(BUFADR-1) + @SBUF + SYSDB;                          01332000
      END ELSE                                                          01334000
      BEGIN << COMPUTE NEXT STARTING ADRESS >>                          01336000
         IF IOQP(QFUNC) >= FILLZ AND IOQP(QFUNC) <> 11 THEN    <<02847>>01338000
           ASMB(DEL,ZERO);                                     <<02847>>01340000
         TOS := TOS + BUFADR;                                           01342000
      END;                                                              01344000
      DITP(DNXTBUFF) := TOS;                                            01346000
      TOS := ENDINT;                                                    01348000
   END;                                                                 01350000
ENDIO:                                                                  01352000
   TOS := -1;                                                           01354000
   DSIOP(I) := TOS;                                                     01356000
EXECIO:                                                                 01358000
   STARTIO(DITP,SIOP,TRUE);                                             01360000
   IF > THEN                                                            01362000
   BEGIN << SIO FIALURE >>                                              01364000
SIOFAILURE:                                                             01366000
      TOS := SIOFAIL;                                                   01368000
      GO TO BADEND;                                                     01370000
   END;                                                                 01372000
   ASMB(TBC SBIT');                                                     01374000
   IF <> THEN DITP(CURCYL) := LOGICAL(SIOP(2)) LAND %777;               01376000
   IOQP(QMISC) := TOS;                                                  01378000
   MSTATE := %13;                                                       01380000
   TOS := WAIT;                                                         01382000
DONE:                                                                   01384000
   IOQP(QSTAT).STAT := TOS;                                             01386000
END;                                                                    01388000
$PAGE                                                                   01390000
ASMB(                                                                   01392000
   PCAL SIODM; << MONITOR >>                                            01394000
   PCAL MHDDVR;<< INITIATOR >>                                          01396000
   PCAL MHDDVR;<< COMPLETOR >>                                          01398000
   CON 0;      << I/O PROCESS PROCEDURE >>                              01400000
   CON 0;      << INITIALIZATION PROCEDURE >>                           01402000
   CON 1;      << # OF INTERRUPT PROCEDURES >>                          01404000
   PCAL GIP);  << INTERRUPT HANDLER >>                                  01406000
END.                                                                    01408000
