$CONTROL MAP,CODE,USLINIT                                               00010000
<<IOMDISC0 - MODULE 16>>                                                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 MAIN=IOMDISC0                                                  00060000
$CONTROL PRIVILEGED,UNCALLABLE                                          00065000
$TITLE "7900A AND 2888A MOVING HEAD DISC DRIVER"                        00070000
$THIRTY                                                                 00075000
                                                                        00080000
DRIVER CALLING SEQUENCE                                                 00085000
                                                                        00090000
   DRIVER REQUEST CODES                                                 00095000
      0 - READ                                                          00100000
      1 - WRITE                                                         00105000
      2 - FILE OPEN                                                     00110000
      3 - FILE CLOSE                                                    00115000
      4 - DEVICE CLOSE                                                  00120000
      5 - FILL WITH ZEROS                                               00125000
      6 - FILL WITH BLANKS                                              00130000
     11 - WRITE DISC LABEL (INTERNAL FUNCTION CODE 7)                   00135000
                                                                        00140000
   COUNT - WORD/BYTE COUNT. BYTE COUNT WILL BE ROUNDED UP TO AN         00145000
           EVEN NO.                                                     00150000
                                                                        00155000
   PARAMETERS P1 AND P2 FORM A DOUBLE WORD DISC ADRESS                  00160000
                                                                        00165000
   NOTE THAT THE BUFFER ADRESS WORD OF THE IOQ IS USED AS THE BUFFER    00170000
   IN ALL FILL OPERATIONS.                                              00175000
                                                                        00180000
                                                                        00185000
DRIVER RETURN CODES:                                                    00190000
                                                                        00195000
   GENERAL STATUS             QUALIFYING STATUS                OVERALL  00200000
   0 - PENDING                1 - WAIT FOR COMPLETION           %10     00205000
   1 - SUCCESSFUL             0 - NORNAL COMPLETION             %01     00210000
   4 - IRRECOVERABLE ERROR    0 - INVALID FUNCTION              %04     00215000
                              1 - DISC XFER ERROR               %14     00220000
                              3 - I/O XFER ERROR                %34     00225000
                              4 - SIO FAILURE                   %44     00230000
                              5 - DISC UNIT FAILURE             %54     00235000
                              6 - INVALID DISC ADRESS           %64     00240000
                                                                        00245000
                                                                        00250000
                                                                        00255000
DISC CONTROLLER STATUS                                                  00260000
   BIT      7900A                2888A                                  00265000
     0      SIO OK               SAME                                   00270000
     1      SEEK CHECK           200 TPI                                00275000
     2      INTERRUPT REQUEST    SAME                                   00280000
     3      ON LINE              SAME                                   00285000
     4      DRIVE UNSAFE         SAME                                   00290000
     5      DRIVE NOT READY      SEEK INCOMPLETE                        00295000
     6      ACCESS NOT READY     UNIT BUSY                              00300000
     7      UNUSED               PACK CHANGE                            00305000
  8-12      CONTROLLER STATUS    SAME                                   00310000
 13-15      DISC UNIT NUMBER     SAME                                   00315000
                                                                        00320000
ENCODED CONTROLLER STATUS                                               00325000
   CODE     7900A                   2888A                               00330000
     0      NO ERROR                SAME                                00335000
     1      ILLEGAL OPCODE          SAME                                00340000
     3      UNUSED                  CYL # TOO BIG                       00345000
     4      SECTOR # TOO BIG        HEAD # TOO BIG                      00350000
     5      UNUSED                  TIME OUT                            00355000
     6      DEFECTIVE TRACK         SAME                                00360000
     7      HEADS MISPOSITIONED     SAME                                00365000
   %10      UNUSED                  CYCLIC ADRESS ERROR                 00370000
   %11      CYCLIC ERROR            CYCLIC DATA ERROR                   00375000
   %12      I/O PROG ERROR          SAME                                00380000
   %13      UNUSED                  SEQUENCE ERROR                      00385000
   %14      CYL OVERRUN             SAME                                00390000
   %15      ZERO SECTOR COUNT       SAME                                00395000
   %16      DATA OVERRUN            SAME                                00400000
   %20      UNUSED                  ILLEGAL TERMINATION                 00405000
   %22      HD/SECT COMPARE ERROR   UNUSED                              00410000
   %23      ACCESS NOT READY        DRIVE ERROR                         00415000
   %24      XFER ERROR              SAME                                00420000
   %26      DATA PROTECTED          UNUSED                              00425000
   %37      DRIVE ATTENTION         SAME                                00430000
                                                                        00435000
$PAGE                                                                   00440000
BEGIN                                                                   00445000
EQUATE                                                                  00450000
   ABIT'       = 4, << ALT TRACK READ BIT OF QMISC >>                   00455000
   BADADR      = %64, << BAD DISC ADRESS RETURN CODE >>                 00460000
   CBIT'       = 6, << RECALIBRATE BIT OF QMISC >>                      00465000
   CONTROL     = %40, << CONTROL CODE >>                                00470000
   CR4K        = %170000,                                               00475000
   CURCYL      = 14, << CURRENT CYL INDEX OF DIT >>                     00480000
   CW4K        = %160000,                                               00485000
   CXC         = 18, << CURRENT XFER COUNT >>                           00490000
   DADDR       = 5, << ADRESS WORD OF IOQ >>                            00495000
   DADR        = 5, << DOUBLE WORD DISC ADRESS OF DIT >>                00500000
   DALTADR     = 6, << DOUBLE INDEX OF ALT. TRK. # >>                   00505000
   DATAOVERRUN = %16, << DATA OVERRUN CONTROLLER CODE >>                00510000
   DBUFF       = 15, << CURRENT BUFFER ADRESS IN DIT >>                 00515000
   DISCERR     = %14, << DISC XFER ERROR RETURN STATUS >>               00520000
   DLDEV       = 3, << LOGICAL DEVICE INDEX OF DIT >>                   00525000
   DLOGERROR   = 20, <<ERROR LOG STATUS>>                      <<01336>>00530000
   DMAMQ       = 8, << INDEX OF MEM.MANAGR. REQ. IN DIT >>              00535000
   DNXTBUFF    = 16, << NEXT BUFFER ADRESS >>                           00540000
   DQPAR1      = 4, << DOUBLE WORD DISC ADR OF IOQ >>                   00545000
   DSERR       = 7, << ERROR STATUS INDEX OF DIT >>                     00550000
   DSTAT       = 6, << DEVICE STAT. INDEX OF DIT >>                     00555000
   DSYSBA      = 19, << SYSBUF ADRESS INDEX OF DIT >>                   00560000
   ENDINT      = %034000,                                               00565000
   ENDNOINT    = %030000,                                               00570000
   FILL        = %167777,                                               00575000
   FILLB       = 6, << FILL BLANK FUNCTION >>                           00580000
   FILLZ       = 5, << FILL WITH ZEROS FUNCTION >>                      00585000
   INVFUNC     = 4, << INVALID FUNCTION RETURN CODE >>                  00590000
   IOXFERERR   = %34, << I/O TRANSMISSION ERROR RETURN STATUS >>        00595000
   ISS         = 3, << 2888A SUBTYPE CODE >>                            00600000
   MBIT'       = 0, << TRACKMAP BIT OF QMISC >>                         00605000
   NOTREADY    = %23, << DRIVE BUSY RETURN CODE >>                      00610000
   QADDR       = 5, << BUFFER ADRESS WORD OF IOQ >>                     00615000
   OFFSET      = 13, << SECTOR OFFSET IN ALT TRACK >>                   00620000
   QFUNC       = 6, << FUNCTION INDEX OF IOQ >>                         00625000
   QLDEV       = 2, << LOGICAL DEVICE INDEX OF IOQ >>                   00630000
   QMISC       = 3, << MISC INDEX OF IOQ >>                             00635000
   QSTAT       = 10, << STATUS INDEX OF IOQ >>                          00640000
   QWBCT       = 7, << XFER COUNT OF IOQ >>                             00645000
   RA          = 4, << READ ADRESS CODE >>                              00650000
   RBIT'       = 1, << READ BTT BIT OF QMISC >>                         00655000
   READ128     = %077600,                                               00660000
   READ4       = %077774,                                               00665000
   READF       = 0, << READ FUNCTION >>                                 00670000
   READOP      = %050000,                                               00675000
   RECALIBRATE = %010000,                                               00680000
   RNFS        = %12, << READ NEXT FULL SECTOR CODE >>                  00685000
   SAL         = 3, << SUBTYPE ARRAY LENGTH >>                          00690000
   SBIT'       = 7, << SEEK BIT OF QMISC >>                             00695000
   SEEK        = %020000,                                               00700000
   SIOFAIL     = %44, << SIO FAIL STATUS RETURN >>                      00705000
   SUCCESS     = 1, << SUCCESSFUL COMPLETION STATUS RETURN >>           00710000
   SUSPALT     = 1, << SUSPECTED ALTERNATE DISC CODE >>                 00715000
   SUSPTRK     = 0, << SUSPECTED TRACK DISC CODE >>                     00720000
   SYSDB       = %1000,                                                 00725000
   SYSLPDT     = 8, << DB INDEX OF LPDT >>                              00730000
   SYSSBUF     = 6, << DB INDEX OF SBUF POINTER >>                      00735000
   TBIT'       = 3, << TRACK BY TRACK BIT OF QMISC >>                   00740000
   TMREAD      = %050001,                                               00745000
   TMWRITE     = %100001,                                               00750000
   TRKFLGDEF   = 6, << TRACK FLAGGED DEFECTIVE STATUS CODE >>           00755000
   UNITFAIL    = %54, << UNIT FAIL RETURN STATUS >>                     00760000
   WAIT        = %10, << WAIT FOR COMPLETION RETURN STATUS >>           00765000
   WBIT'       = 2, << WRITE BTT BIT OF QMISC >>                        00770000
   WCR         = 17, << WORD COUNT REMAINING OF DIT >>                  00775000
   WRITE128    = %067600,                                               00780000
   WRITEOP     = %100000,                                               00785000
   XBIT'       = 5, << XFER FROM ALT TRK BIT OF QMISC >>                00790000
   XFER128     = %007600,                                               00795000
   XFERERR     = %24; << I/O XFER ERROR RETURN STATUS >>                00800000
DEFINE                                                                  00805000
    ABIT       = (ABIT':1)#,                                            00810000
    ABS        = ABSOLUTE#,                                             00815000
    ASMB       = ASSEMBLE#,                                             00820000
    CBIT       = (CBIT':1)#,                                            00825000
    DISABLE    = ASSEMBLE(SED 0)#,                                      00830000
    DUPLICATE  = ASSEMBLE(DUP)#,                                        00835000
    ERRCODE    = (8:5)#, << ENCODED DISC RETURN STATUS >>               00840000
    FUNC       = (8:8)#, << FUNCTION FIELD OF QFUNC >>                  00845000
    HSECTOR    = (9:7)#, << SECTOR AND LSB OF HEAD >>                   00850000
    LIMIT      = (10:1)#, << RESTRICTED I/O ACTIVITY BIT OF DIT >>      00855000
    LSHBIT     = (9:1)#, << LSB OF HEAD FIELD >>                        00860000
    MBIT       = (MBIT':1)#,                                            00865000
    QLDEVN     = (8:8)#, << LOGICAL DEVICE FIELD OF IOQ >>              00870000
    RBIT       = (RBIT':1)#,                                            00875000
    RETRY      = (12:4)#, << RETRY COUNT FIELD OF QMISC >>              00880000
    SBIT       = (SBIT':1)#,                                            00885000
    SFAIL      = (10:1)#, << SIO FAILURE BIT SENT BY GIP IN IOQ >>      00890000
    SPEC       = (1:1)#, << MAM REQ BIT OF IOQ FOR DISCS >>             00895000
    STAT       = (8:8)#, << STATUS RETURN FIELD OF IOQ >>               00900000
    SUBT       = (12:4)#, << SUBTYPE FIELD OF LPDT >>                   00905000
    SYSBUFR    = (3:1)#, << SYSTEM BUFFER BIT OF IOQ >>                 00910000
    TBIT       = (TBIT':1)#,                                            00915000
    TRACK      = (2:14)#, << ALT TRACK FIELD >>                         00920000
    WBIT       = (WBIT':1)#,                                            00925000
    XBIT       = (XBIT':1)#;                                            00930000
INTEGER POINTER                                                         00935000
    SBUF       = DB + SYSSBUF;                                          00940000
DOUBLE POINTER                                                          00945000
    DLPDT      = DB + SYSLPDT;                                          00950000
ARRAY INITIAL(0:46) = DB :=                                    <<01336>>00955000
    %012441,  <<DIT SIZE= 21, CORE RES., DVR TYPE= 1>>         <<01336>>00960000
          0,                                                            00965000
    %037407, << UNIT EXTRACT INSTRUCTION (ANDI 7) >>                    00970000
    [8/%13,8/0],  <<22 WORD I/O PROG AREA >>                   <<01300>>00975000
    %040100,  <<DFLAG>>  << DIT WORD 0, DISC, MH DISC >>       <<01336>>00980000
        0,    <<DLINK>>                                        <<01336>>00985000
        0,    <<DIOQP>>                                        <<01336>>00990000
        0,    <<DLDEV>>                                        <<01336>>00995000
        0,    <<DLTP>>                                         <<01336>>01000000
        0,    <<DILTP>>                                        <<01336>>01005000
        0,    <<DSTAT>>                                        <<01336>>01010000
        0,    <<DSERR>> <<INDEX & COUNT OF HARWARE STATUS>>    <<01336>>01015000
        0,    <<DMAMQ>>                                        <<01336>>01020000
        0,    <<DMAMQT>>                                       <<01336>>01025000
        0,    <<DADR  - DOUBLE WORD>>                          <<01336>>01030000
        0,                                                     <<01336>>01035000
        0,    <<DALTADR  - DOUBLE WORD>>                       <<01336>>01040000
        0,                                                     <<01336>>01045000
        0,    <<CURCYL>>                                       <<01336>>01050000
        0,    <<DBUFF>>                                        <<01336>>01055000
        0,    <<DNXTBUFF>>                                     <<01336>>01060000
        0,    <<WCR>>                                          <<01336>>01065000
        0,    <<CWC>>                                          <<01336>>01070000
        0,    <<DSYSBA>>                                       <<01336>>01075000
        0,    <<DLOGERROR>>                                    <<01336>>01080000
    %014000, << I/O PROG AREA - SET BANK >>                             01085000
      21(0); << REST OF I/O PROG AREA >>                                01090000
$PAGE                                                                   01095000
PROCEDURE CHECKINDEX(INDEX,TABLE);                                      01100000
VALUE INDEX,TABLE;                                                      01105000
INTEGER INDEX;                                                          01110000
INTEGER POINTER TABLE;                                                  01115000
OPTION EXTERNAL;                                                        01120000
                                                                        01125000
PROCEDURE DCONVERT(WORD);                                               01130000
VALUE WORD;                                                             01135000
INTEGER WORD;                                                           01140000
OPTION EXTERNAL;                                                        01145000
                                                                        01150000
INTEGER PROCEDURE GETSBUF(TYPE);                                        01155000
VALUE TYPE;                                                             01160000
INTEGER TYPE;                                                           01165000
OPTION EXTERNAL;                                                        01170000
                                                                        01175000
PROCEDURE GIP;                                                          01180000
OPTION EXTERNAL;                                                        01185000
                                                                        01190000
PROCEDURE HELP;                                                         01195000
OPTION EXTERNAL;                                                        01200000
                                                                        01205000
PROCEDURE LDEVNOTRDY(DITP);                                             01210000
VALUE DITP;                                                             01215000
POINTER DITP;                                                           01220000
OPTION EXTERNAL;                                                        01225000
                                                                        01230000
PROCEDURE MMSTAT(E,P1,P2,P3);                                           01235000
VALUE E,P1,P2,P3;                                                       01240000
INTEGER E,P1,P2,P3;                                                     01245000
OPTION EXTERNAL;                                                        01250000
                                                                        01255000
PROCEDURE SIODM(DITP,FLAGS);                                            01260000
VALUE DITP,FLAGS;                                                       01265000
INTEGER POINTER DITP;                                                   01270000
LOGICAL FLAGS;                                                          01275000
OPTION EXTERNAL;                                                        01280000
                                                                        01285000
PROCEDURE RETURNSBUF(SBUFP);                                            01290000
VALUE SBUFP;                                                            01295000
INTEGER SBUFP;                                                          01300000
OPTION EXTERNAL;                                                        01305000
                                                                        01310000
PROCEDURE STARTIO(DITP,SIOP,QUEUE);                                     01315000
VALUE DITP,SIOP,QUEUE;                                                  01320000
INTEGER POINTER DITP,SIOP;                                              01325000
LOGICAL QUEUE;                                                          01330000
OPTION EXTERNAL;                                                        01335000
                                                                        01340000
PROCEDURE WRITE2(WORD);                                                 01345000
VALUE WORD;                                                             01350000
INTEGER WORD;                                                           01355000
OPTION EXTERNAL;                                                        01360000
$PAGE                                                                   01365000
INTEGER PROCEDURE MHDDVR(IOQP,DITP,BANK,BUFADR,SIOP,DRTN);              01370000
VALUE IOQP,DITP,BANK,BUFADR,SIOP,DRTN;                                  01375000
INTEGER BANK,BUFADR,DRTN;                                               01380000
INTEGER POINTER IOQP,DITP,SIOP;                                         01385000
OPTION PRIVILEGED,UNCALLABLE;                                           01390000
BEGIN                                                                   01395000
INTEGER ARRAY SEC'TRK(0:SAL) = PB := 48,48,48,23;                       01400000
INTEGER ARRAY SEC'CYL(0:SAL) = PB := 48,48,96,460;                      01405000
LOGICAL ARRAY MAXCYL(0:SAL)  = PB := 203,203,203,406;                   01410000
INTEGER ARRAY SEC'HEAD(0:SAL)= PB := 24,24,24,23;                       01415000
INTEGER ARRAY HEADBASE(0:SAL)= PB := 0,%200,0,0;                        01420000
INTEGER ARRAY SEC'XFER(0:SAL)= PB := 48,48,48,460;                      01425000
                                                                        01430000
DOUBLE POINTER                                                          01435000
   DDITP       = DITP,                                                  01440000
   DIOQP       = IOQP,                                                  01445000
   DSIOP       = SIOP;                                                  01450000
INTEGER                                                                 01455000
   AD          = Q+7, << ADRESS DELTA >>                                01460000
   DERR        = Q+3, << DISC ERROR CODE >>                             01465000
   I           = Q+4, << I/O PROG INDEX >>                              01470000
   MSTATE      = MHDDVR, << SIO DEVICE MONITOR STATE >>                 01475000
   S0          = S-0,                                                   01480000
   S2          = S-2,                                                   01485000
   SUBTYPE     = Q+5, << DEVICE SUBTYPE >>                              01490000
   X           = X,                                                     01495000
   XD          = Q+6, << TRANSFER DELTA >>                              01500000
   XFER        = Q+2; << I/O TRANSFER INSTRUCTION >>                    01505000
INTEGER POINTER                                                         01510000
   BADTRACK    = Q+1;                                                   01515000
LOGICAL                                                                 01520000
   SIOCOUNT    = DB+%60; << SIO PROGRAM COUNTER >>                      01525000
LOGICAL POINTER                                                         01530000
   LIOQP       = IOQP;                                                  01535000
                                                                        01540000
                                                                        01545000
   ASMB(ADDS 3); << INITIALIZE >>                                       01550000
   TOS := 2; << I >>                                                    01555000
   TOS := DLPDT(IOQP(QLDEV).QLDEVN);                                    01560000
   DELB;                                                                01565000
   TOS := TOS.SUBT; << DEVICE SUBTYPE >>                                01570000
   TOS := 4096; << XD >>                                                01575000
   DUPLICATE; << AD >>                                                  01580000
   IF MSTATE = 2 THEN                                                   01585000
   BEGIN << NEW REQUEST >>                                              01590000
      TOS := IOQP(QWBCT);                                               01595000
      IF < THEN                                                         01600000
      BEGIN << COUNT IN BYTES >>                                        01605000
         DUPLICATE;                                                     01610000
         IF TOS THEN IOQP(X) := IOQP(X) - 1; << ROUND TO EVEN COUNT >>  01615000
         TOS := -(TOS&ASR(1)); << CONVERT TO WORDS >>                   01620000
      END;                                                              01625000
      DITP(WCR) := TOS; << SET REMAINING WORD COUNT >>                  01630000
      DDITP(DADR) := DIOQP(DQPAR1); << SET DISC ADRESS >>               01635000
      DITP(DBUFF) := BUFADR; << SET CURRENT BUFFER ADRESS >>            01640000
      IF IOQP(QFUNC).FUNC = 7 THEN GO TO INVALIDFUNC;          <<02847>>01645000
      TOS := IF IOQP(QFUNC).FUNC = 11 THEN 7                   <<02847>>01650000
        ELSE IOQP(QFUNC).FUNC; << MAP FCODE 11 TO FCODE 7 >>   <<02847>>01655000
      DUPLICATE;                                                        01660000
      IF < OR TOS > 7 THEN                                     <<02847>>01665000
      BEGIN << INVALID FUNCTION >>                                      01670000
INVALIDFUNC:                                                            01675000
         TOS := INVFUNC;                                                01680000
         GO TO BADEND;                                                  01685000
      END;                                                              01690000
      IF LIOQP.SYSBUFR AND DITP(WCR) > 1024 THEN GO TO INVALIDFUNC;     01695000
      X := TOS;                                                         01700000
      TOS := 0; << RESET QMISC >>                                       01705000
      ASMB(LOAD SWT,X; ADAX; BR SWT,X;                                  01710000
SWT:                                                                    01715000
      CON DOXFER;  CON DOXFER;   CON GOODEND;   CON GOODEND;   <<02847>>01720000
      CON GOODEND; CON FILLZERO; CON FILLBLANK; CON DOXFER);   <<02847>>01725000
      HELP;                                                             01730000
   END;                                                                 01735000
   IF LIOQP.SFAIL THEN GO TO SIOFAILURE; << GIP FAILED TO START I/O >>  01740000
   TOS := IOQP(QMISC);                                                  01745000
   TOS.SBIT := 0;                                                       01750000
   IF <> THEN                                                           01755000
   BEGIN << SEEK COMPLETE >>                                            01760000
      ASMB(TBC MBIT');                                                  01765000
      IF = THEN GO TO DOXFER ELSE GO TO TRACKMAP;                       01770000
   END;                                                                 01775000
   DERR := DITP(DSTAT).ERRCODE; << CHECK FOR ERRORS >>                  01780000
   IF = THEN                                                            01785000
   BEGIN << NO ERRORS >>                                                01790000
      ASMB(TBC MBIT');                                                  01795000
      IF <> THEN                                                        01800000
      BEGIN << DOING BAD TRACK MAP UPDATE >>                            01805000
TRACKMAP:                                                               01810000
         ASMB(TBC WBIT');                                               01815000
         IF <> THEN                                                     01820000
         BEGIN << COMPLETED WRITE OF TRACK MAP >>                       01825000
RETURNSB:                                                               01830000
            RETURNSBUF(DITP(DSYSBA));                                   01835000
            GO TO DISCERROR;                                            01840000
         END;                                                           01845000
         TOS.RBIT := 1;                                                 01850000
         IF = THEN                                                      01855000
         BEGIN << READ BAD TRACK MAP >>                                 01860000
            TOS := DITP(DLDEV)&LSR(8);                                  01865000
            TOS := (TOS + CONTROL)&LSL(9);                              01870000
            TOS := TMREAD + HEADBASE(SUBTYPE);                          01875000
            DSIOP(1) := TOS;                                            01880000
            SIOP(X) := 0; << ZERO BANK >>                               01885000
            TOS := READ128;                                             01890000
            TOS := GETSBUF(1);                                          01895000
            DUPLICATE;                                                  01900000
            IF = THEN GO TO DISCERROR;                                  01905000
            DITP(DSYSBA) := TOS;                                        01910000
            TOS := TOS + SYSDB;                                         01915000
            DSIOP(2) := TOS;                                            01920000
            I := I + 1;                                                 01925000
            TOS := ENDINT;                                              01930000
            GO TO ENDIO;                                                01935000
         END ELSE                                                       01940000
         BEGIN << PUT BAD TRACK INTO TABLE >>                           01945000
            @BADTRACK := DITP(DSYSBA);                                  01950000
            IF BADTRACK >= 120 THEN GO TO RETURNSB;                     01955000
            ASMB(TBC XBIT');                                            01960000
            IF <> THEN                                                  01965000
            BEGIN << SUSPECTED ALTERNATE >>                             01970000
               TOS := SUSPALT;                                          01975000
               X := DALTADR;                                            01980000
            END ELSE                                                    01985000
            BEGIN << SUSPECT TRACK >>                                   01990000
               TOS := SUSPTRK;                                          01995000
               X := DADR;                                               02000000
            END;                                                        02005000
            TOS := DDITP(X);                                            02010000
            TOS := SEC'TRK(SUBTYPE);                                    02015000
            ASMB(LDIV,DEL);                                             02020000
            TOS := TOS&LSL(2) LOR TOS;                                  02025000
            X := 0;                                                     02030000
            WHILE X < BADTRACK DO                                       02035000
            BEGIN << SEE IF TRACK IS ALREADY IN TABLE >>                02040000
               ASMB(DUP,INCX);                                          02045000
               IF TOS = BADTRACK(X) THEN GO TO RETURNSB;                02050000
            END;                                                        02055000
            BADTRACK(X:=X+1) := TOS;                                    02060000
            BADTRACK := BADTRACK + 1;                                   02065000
            SIOP(3) := TMWRITE + HEADBASE(SUBTYPE);                     02070000
            SIOP(4) := WRITE128;                                        02075000
            TOS.WBIT := 1;                                              02080000
            GO TO EXECIO;                                               02085000
         END;                                                           02090000
      END;                                                              02095000
      ASMB(TBC TBIT');                                                  02100000
      IF <> THEN                                                        02105000
      BEGIN << TRACK BY TRACK XFER >>                                   02110000
         ASMB(TBC ABIT');                                               02115000
         IF <> THEN                                                     02120000
         BEGIN << READING ALT. TRACK # >>                               02125000
            IF SIOP(12) <> SIOP(14) THEN GO TO RETRYOP;                 02130000
            TOS := SIOP(X).TRACK;                                       02135000
            IF = THEN GO TO INVADR;                                     02140000
            IF SUBTYPE = 2 THEN TOS.(7:1) := 1;                         02145000
            TOS := SEC'TRK(SUBTYPE);                                    02150000
            ASMB(LMPY,ZERO);                                            02155000
            TOS := DITP(OFFSET);                                        02160000
            DDITP(DALTADR) := DDITP(DADR);                              02165000
            ASMB(DECX,DADD);                                            02170000
            DDITP(X) := TOS;                                            02175000
            TOS.ABIT := 0;                                              02180000
            TOS.XBIT := 1;                                              02185000
            GO TO DOXFER;                                               02190000
         END;                                                           02195000
         TOS.XBIT := 0;                                                 02200000
         IF <> THEN DDITP(DADR) := DDITP(DALTADR);                      02205000
         << REPLACE ORIG. DISC ADR IF ALT. XFER. COMPLETE >>            02210000
      END;                                                              02215000
      TOS := DITP(CXC);                                                 02220000
      ASMB(DUP,NEG); << UPDATE XFER CNT & DISC ADRESS >>                02225000
      DITP(X) := TOS + DITP(WCR);                                       02230000
      IF <= THEN                                                        02235000
      BEGIN << XFER COMPLETED >>                                        02240000
GOODEND:                                                                02245000
         TOS := SUCCESS;                                                02250000
BADCONT:                                                                02255000
         MSTATE := 5;                                                   02260000
         GO TO DONE;                                                    02265000
      END;                                                              02270000
      TOS := TOS&LSR(7); << CONVERT WORDS TO SECTORS >>                 02275000
      ASMB(ZERO,XCH); << UPDATE DISC ADRESS >>                          02280000
      DDITP(X) := TOS + DDITP(DADR);                                    02285000
      DITP(DBUFF) := DITP(DNXTBUFF); << UPDATE BUFFER ADRESS >>         02290000
      GO TO DOXFER;                                                     02295000
   END ELSE                                                             02300000
   BEGIN << DISC HAD AN ERROR >>                                        02305000
      IF DERR = TRKFLGDEF THEN                                          02310000
      BEGIN << FLAGGED DEFECTIVE TRACK >>                               02315000
         TOS.TBIT := 1;                                                 02320000
         IF = THEN GO TO DOXFER; << REDO TRK BY TRK >>                  02325000
         TOS := SIOP(3).HSECTOR; << DETERMINE SECTOR OFFSET IN TRK >>   02330000
         TOS.LSHBIT := 0;                                               02335000
         IF <> AND SUBTYPE <> ISS THEN TOS := TOS + 24;                 02340000
         << ADD HEAD OFFSET FOR 7900 DISC >>                            02345000
         DITP(OFFSET) := TOS;                                           02350000
         IF SUBTYPE = ISS THEN TOS := RA ELSE TOS := RNFS;              02355000
         TOS := SIOP(3)&LSL(4);                                         02360000
         SIOP(X) := TOS&DLSR(4);                                        02365000
         DEL;                                                           02370000
         TOS := READ4;                                                  02375000
         TOS := @SIOP(12) + SYSDB;                                      02380000
         DSIOP(2) := TOS;                                               02385000
         I := I + 1;                                                    02390000
         IF SUBTYPE <> ISS THEN                                         02395000
         BEGIN << READ ALT TRACK IN TWO PARTS FOR 7900 >>               02400000
            TOS := DSIOP(X);                                            02405000
            ASMB(INCA,INCA);                                            02410000
            DSIOP(4) := TOS;                                            02415000
            DSIOP(3) := DSIOP(1);                                       02420000
            I := 5;                                                     02425000
         END;                                                           02430000
         SIOP(1) := 0; << ZERO BANK FOR ADRESS READ >>                  02435000
         TOS.ABIT := 1;                                                 02440000
         TOS := ENDINT;                                                 02445000
         GO TO ENDIO;                                                   02450000
      END;                                                              02455000
      IF DERR = NOTREADY THEN                                           02460000
      BEGIN << DISC IS IN NOT READY CONDITION >>                        02465000
         LDEVNOTRDY(DITP);                                              02470000
         MSTATE := 7;                                                   02475000
         TOS := WAIT;                                                   02480000
         GO TO DONE;                                                    02485000
      END;                                                              02490000
      DITP(DSERR):= [8/1,8/DLOGERROR];<<SET LOG COUNT & INDEX>><<01336>>02495000
      DITP(DLOGERROR):= DITP(DSTAT);    <<LOG ERROR>>          <<01336>>02500000
RETRYOP:                                                                02505000
      ASMB(INCA,DUP);                                                   02510000
      MMSTAT(101,DITP(DSTAT),S0,                                        02515000
      LIOQP(QLDEV).QLDEVN LOR SIOCOUNT&LSL(8));                         02520000
      IF TOS.RETRY < 10 THEN GO TO EXECIO; << RETRY 10 TIMES >>         02525000
      TOS.CBIT := 1;                                                    02530000
      IF = THEN                                                         02535000
      BEGIN << ISSUE A RECALIBRATE TO DRIVE >>                          02540000
RECAL:                                                                  02545000
         TOS := DITP(DLDEV)&LSR(8);                                     02550000
         TOS := (TOS + CONTROL)&LSL(9);                                 02555000
         TOS := RECALIBRATE;                                            02560000
         DSIOP(1) := TOS;                                               02565000
         TOS := TOS LAND -16;                                           02570000
         TOS.SBIT := 1;                                                 02575000
         TOS := ENDNOINT;                                               02580000
         GO TO ENDIO;                                                   02585000
      END;                                                              02590000
      ASMB(TBC MBIT');                                                  02595000
      IF <> THEN GO TO RETURNSB;                                        02600000
      TOS.ABIT := 0;                                                    02605000
      IF <> THEN                                                        02610000
      BEGIN << COULDN'T READ ALT. TRK. # >>                             02615000
         TOS.MBIT := 1;                                                 02620000
         GO TO RECAL;                                                   02625000
      END;                                                              02630000
      IF DERR = DATAOVERRUN OR DERR = XFERERR THEN                      02635000
      BEGIN << I/O XMISSION ERROR >>                                    02640000
         TOS := BANK; << ATTEMPT TO LOCATE PARITY ERROR >>              02645000
         TOS := BUFADR;                                                 02650000
         TOS := IOQP(QWBCT);                                            02655000
         IF < THEN TOS := -(TOS&ASR(1));                                02660000
         X := TOS;                                                      02665000
         DO << IF PARITY ERROR IS ENCOUNTERED, >>                       02670000
         BEGIN << ININ WILL BE INVOKED >>                               02675000
            ASMB(LSEA);                                                 02680000
            DEL;                                                        02685000
            TOS := TOS + 1;                                             02690000
         END UNTIL DXBZ;                                                02695000
         TOS := IOXFERERR;                                              02700000
BADEND:                                                                 02705000
         IOQP(QWBCT) := 0;                                              02710000
         GO TO BADCONT;                                                 02715000
      END;                                                              02720000
      IF 5 <= DERR <= %11 OR DERR = %13 OR DERR = %22 THEN              02725000
      BEGIN << TRACK SPECIFIC ERROR >>                                  02730000
         TOS.TBIT := 1; << SET TRACK BY TRACK >>                        02735000
         IF = THEN GO TO DOXFER; << REDO XFER TO DET. TRK # >>          02740000
         TOS.MBIT := 1;                                                 02745000
         GO TO RECAL; << PUT TRACK INTO B T T >>                        02750000
DISCERROR:                                                              02755000
         TOS := DISCERR;                                                02760000
         GO TO BADEND;                                                  02765000
      END;                                                              02770000
      TOS := UNITFAIL; << UNIT FAILURE >>                               02775000
      GO TO BADEND;                                                     02780000
   END;                                                                 02785000
                                                                        02790000
                                                                        02795000
FILLBLANK:                                                              02800000
   TOS := "  ";                                                         02805000
   GO TO FC;                                                            02810000
FILLZERO:                                                               02815000
   TOS := 0;                                                            02820000
FC:                                                                     02825000
   IOQP(QADDR) := TOS;                                                  02830000
   DITP(DBUFF) := @IOQP(QADDR) + SYSDB; << SET BUFFER ADRESS >>         02835000
                                                                        02840000
DOXFER: << QMISC MUST BE ON TOS HERE >>                                 02845000
   TOS := DDITP(DADR);                                                  02850000
   IF = AND (1 <= IOQP(QFUNC) <= 6) THEN                       <<02847>>02855000
     GO TO INVADR;   << READ & WRT LBL TO SECTOR 0 ONLY >>     <<02847>>02860000
   TOS := SEC'CYL(SUBTYPE);                                             02865000
   ASMB(LDIV,XCH; DUP,DUP); << COMPUTE CYLINDER ADRESS >>               02870000
   IF OVERFLOW OR TOS >= MAXCYL(X) THEN                                 02875000
   BEGIN << CYL ADRESS OUT OF RANGE >>                                  02880000
INVADR:                                                                 02885000
      TOS := BADADR;                                                    02890000
      GO TO BADEND;                                                     02895000
   END;                                                                 02900000
   TOS := DITP(DLDEV)&LSR(8); << UNIT NUMBER >>                         02905000
   TOS := (TOS + CONTROL)&LSL(9);                                       02910000
   ASMB(OR,XCH); << CONTROL, UNIT, AND CYL # >>                         02915000
   IF TOS <> DITP(CURCYL) THEN                                          02920000
   BEGIN << SEEK REQUIRED >>                                            02925000
      TOS := SEEK;                                                      02930000
      DSIOP(1) := TOS; << CONTROL SEEK >>                               02935000
      DEL;                                                              02940000
      TOS.SBIT := 1; << SET SEEK BIT OF QMISC >>                        02945000
      TOS := ENDNOINT;                                                  02950000
   END ELSE                                                             02955000
   BEGIN << DO XFER >>                                                  02960000
      ASMB(XCH); << COMPUTE HEAD AND SECTOR ADRESS >>                   02965000
      TOS := SEC'HEAD(SUBTYPE);                                         02970000
      ASMB(DIV,XCH);                                                    02975000
      TOS := TOS&LSL(6) + HEADBASE(X);                                  02980000
      IF IOQP(QFUNC) = READF THEN TOS := READOP ELSE TOS := WRITEOP;    02985000
      ASMB(OR,OR); << OPCODE, HEAD, AND SECTOR # >>                     02990000
      DSIOP(1) := TOS; << SET CONTROL >>                                02995000
      X := SUBTYPE;                                                     03000000
      ASMB(TBC TBIT'); << DETERMINE MAXIMUM XFER >>                     03005000
      IF <> THEN TOS := SEC'TRK(X) ELSE TOS := SEC'XFER(X);             03010000
      TOS := DDITP(DADR);                                               03015000
      TOS := S2;                                                        03020000
      ASMB(LDIV,DELB; SUB); << SECTORS REMAINING TO EOT >>              03025000
      TOS := TOS&LSL(7); << MAX. WORD XFER >>                           03030000
      TOS := DITP(WCR);                                                 03035000
      IF = THEN GO TO GOODEND; << ZERO XFER IS A NO-OP >>               03040000
      ASMB(DDUP,LCMP);                                                  03045000
      IF < THEN ASMB(XCH); << SMALLEST TO TOS >>                        03050000
      DELB;                                                             03055000
      IF IOQP(QFUNC) < FILLZ OR IOQP(QFUNC)=11 THEN            <<02847>>03060000
      BEGIN << READ OR WRITE >>                                         03065000
         IF IOQP(X) = READF THEN TOS := CR4K ELSE TOS := CW4K;          03070000
         IF LIOQP.SYSBUFR THEN                                          03075000
         BEGIN                                                          03080000
            TOS := TOS + XFER128; << AJUST XFER ORDER >>                03085000
            CHECKINDEX(@SBUF + SYSDB - BUFADR,SBUF);                    03090000
            XD := 128;                                                  03095000
            AD := 0;                                                    03100000
         END;                                                           03105000
         TOS := BANK; << SET BANK ON NORMAL READ/WRITE >>               03110000
      END ELSE                                                          03115000
      BEGIN << FILL >>                                                  03120000
         TOS := 1024;                                                   03125000
         ASMB(DDUP,CMP);                                                03130000
         IF < THEN ASMB(XCH);                                           03135000
         DELB; << XFER CAN'T EXCEED 1024 >>                             03140000
         XD := 128;                                                     03145000
         AD := 0;                                                       03150000
         TOS := FILL;                                                   03155000
         TOS := 0; << ZERO BANK NUMBER FOR FILL OPERATIONS >>           03160000
      END;                                                              03165000
      SIOP(1) := TOS; << SET BANK >>                                    03170000
      XFER := TOS; << XFER ORDER >>                                     03175000
      BUFADR := DITP(DBUFF);                                            03180000
      ASMB(DUP,DUP);                                                    03185000
      DITP(CXC) := TOS; << CURRENT XFER COUNT >>                        03190000
      WHILE TOS > XD DO                                                 03195000
      BEGIN << BUILD A CHAINED XFER ORDER >>                            03200000
         TOS := TOS - XD; << DECREMENT COUNT >>                         03205000
         TOS := XFER;                                                   03210000
         TOS := BUFADR;                                                 03215000
         DSIOP(I) := TOS;                                               03220000
         I := I + 1;                                                    03225000
         IF LIOQP.SYSBUFR THEN                                          03230000
         BEGIN << CHECK SYSBUF INDEX AND CALC. NEXT BUF ADR >>          03235000
            CHECKINDEX(ABSOLUTE(BUFADR-1),SBUF);                        03240000
            BUFADR := ABSOLUTE(X) + @SBUF + SYSDB;                      03245000
         END;                                                           03250000
         BUFADR := BUFADR + AD;                                         03255000
         DUPLICATE;                                                     03260000
      END;                                                              03265000
      ASMB(DUP,NEG; TRBC 3);                                            03270000
      TOS := TOS LOR LOGICAL(XFER);                                     03275000
      ASMB(TRBC 0); << BUILD LAST UNCHAINED ORDER >>                    03280000
      TOS := BUFADR;                                                    03285000
      DSIOP(I) := TOS;                                                  03290000
      I := I + 1;                                                       03295000
      IF LIOQP.SYSBUFR THEN                                             03300000
      BEGIN << GET NEXT SYSBUF ADRESS >>                                03305000
         DEL;                                                           03310000
         TOS := ABS(BUFADR-1) + @SBUF + SYSDB;                          03315000
      END ELSE                                                          03320000
      BEGIN << COMPUTE NEXT STARTING ADRESS >>                          03325000
         IF IOQP(QFUNC) >= FILLZ AND IOQP(QFUNC) <> 11 THEN    <<02847>>03330000
           ASMB(DEL,ZERO);                                     <<02847>>03335000
         TOS := TOS + BUFADR;                                           03340000
      END;                                                              03345000
      DITP(DNXTBUFF) := TOS;                                            03350000
      TOS := ENDINT;                                                    03355000
   END;                                                                 03360000
ENDIO:                                                                  03365000
   TOS := -1;                                                           03370000
   DSIOP(I) := TOS;                                                     03375000
EXECIO:                                                                 03380000
   STARTIO(DITP,SIOP,TRUE);                                             03385000
   IF > THEN                                                            03390000
   BEGIN << SIO FIALURE >>                                              03395000
SIOFAILURE:                                                             03400000
      TOS := SIOFAIL;                                                   03405000
      GO TO BADEND;                                                     03410000
   END;                                                                 03415000
   ASMB(TBC SBIT');                                                     03420000
   IF <> THEN DITP(CURCYL) := LOGICAL(SIOP(2)) LAND %777;               03425000
   IOQP(QMISC) := TOS;                                                  03430000
   MSTATE := %13;                                                       03435000
   TOS := WAIT;                                                         03440000
DONE:                                                                   03445000
   IOQP(QSTAT).STAT := TOS;                                             03450000
END;                                                                    03455000
$PAGE                                                                   03460000
ASMB(                                                                   03465000
   PCAL SIODM; << MONITOR >>                                            03470000
   PCAL MHDDVR;<< INITIATOR >>                                          03475000
   PCAL MHDDVR;<< COMPLETOR >>                                          03480000
   CON 0;      << I/O PROCESS PROCEDURE >>                              03485000
   CON 0;      << INITIALIZATION PROCEDURE >>                           03490000
   CON 1;      << # OF INTERRUPT PROCEDURES >>                          03495000
   PCAL GIP);  << INTERRUPT HANDLER >>                                  03500000
END.                                                                    03505000
