
      HED TSB MOVING HEAD DISC DRIVER -- ISS VERSION
      ORG 26000B
* 
*     THIS DRIVER HANDLES ALL TRANSFERS TO AND FROM THE 
*     MOVING HEAD DISCS.  THE CALLING SEQUENCE TO THE DRIVER
*     IS AS FOLLOWS:
* 
*         JSB DISCA,I 
* 
*     REGISTER A MUST CONTAIN THE ADDRESS OF A DOUBLE WORD
*     CONTAINING THE "ABSOLUTE" NUMBER OF THE FIRST RECORD
*     OF THE DISC SYSTEM TO BE TRANSFERRED. 
* 
*     REGISTER B MUST CONTAIN IN BITS 14-0 THE CORE ADDRESS 
*     AT WHICH THE TRANSFER IS TO BEGIN.  BIT 15 MUST BE
*     SET (1) IF THE TRANSFER IS TO BE A READ FROM DISC INTO
*     CORE AND CLEAR (0) FOR A WRITE FROM CORE TO DISC. 
* 
*     LOCATION "MWORD" MUST CONTAIN THE NEGATIVE OF THE NUMBER
*     OF WORDS TO BE TRANSFERRED. 
* 
* 
*     ONLY ONE MOVING HEAD DISC TRANSFER REQUEST CAN BE 
*     HANDLED AT ANY TIME.  IF ONE IS IN PROGRESS, THE
*     DRIVER BUSY FLAG, MBUSY, WILL BE SET TO -1 AND SUBSEQUENT 
*     CALLS TO MDISC WILL CAUSE A NO-SKIP RETURN. 
* 
*     IF THE REQUESTED RECORD NUMBER IS OUTSIDE THE RANGE 
*     COVERED BY THE CURRENT DISCS, A SINGLE-SKIP RETURN
*     IS MADE.
* 
*     IF THE DRIVER IS FREE AND THE REQUESTED RECORD NUMBER 
*     LEGITIMATE, A DOUBLE-SKIP RETURN TO THE CALLER WILL MADE
*     AFTER PROCESSING OF THE REQUEST HAS BEEN INITIATED. 
* 
*     A POSITIVE OR ZERO WORD COUNT WILL CAUSE A SEEK TO THE
*     APPROPRIATE CYLINDER OF THE CORRECT DRIVE.  NO TRANSFER 
*     WILL TAKE PLACE, AND NO ERROR WILL BE INDICATED.
* 
* 
*     THE DRIVER BUSY FLAG, MBUSY, WILL BE SET TO -1 AS LONG
*     AS THE DRIVER IS ATTEMPTING TO ACCOMPLISH THE REQUESTED 
*     TRANSFER.  UPON SUCCESSFUL COMPLETION, MBUSY WILL BE
*     SET TO 0.  IF THE ATTEMPT IS UNSUCCESSFUL, MBUSY WILL 
*     BE SET TO 1 IF THE SEEK CANNOT BE COMPLETED AND 2 IF
*     THE READ OR WRITE CANNOT BE DONE.  MBUSY WILL BE SET
*     TO 3 IF PART OF THE REQUESTED TRANSFER IS COMPLETED 
*     AND THE DRIVER THEN DISCOVERS THAT A SUBSEQUENTLY 
*     NEEDED RECORD IS OUTSIDE THE RANGE OF THE DISCS PRESENT.
* 
* 
* 
*     IN THE STATUS WORD PROVIDED BY THE ISS CONTROLLER TO
*     THE DRIVER, THE BITS HAVE THE FOLLOWING SIGNIFICANCE: 
* 
*         BIT 0:    ANY ERROR 
*         BIT 1:    DATA ERROR; OVERRUN 
*         BIT 2:    POSITIONER BUSY; SEEK CHECK; SEEK INCOMPLETE
*         BIT 3:    FLAGGED TRACK 
*         BIT 4:    NO RECORD FOUND (ADDRESS ERROR) 
*         BIT 5:    END OF CYLINDER 
*         BIT 6:    NOT READY 
*         BIT 7:    DRIVE IDENTIFICATION
*         BITS 8-15: UNUSED 
* 
      SPC 3 
MDISC NOP           ENTRY POINT 
      CLF DINT      DISABLE INTERRUPT 
      DST TEMAB     SAVE REGISTERS
      LDA MBUSY     GET DRIVER BUSY FLAG
      SSA,RSS       DRIVER BUSY?
      JMP MOKAY     NO, FORGE AHEAD 
      DLD TEMAB     YES, BOUNCE BACK
      STF EINT        (RETURN 
      JMP MDISC,I       NO-SKIP)
MOKAY LDA MDISC     GET RETURN ADDRESS
      INA           BUMP IT TO "DRIVER FREE" LOC
      STA MDINT     STICK IT IN STANDARD RETURN SLOT
      STB COREM     SAVE CORE POINTER (+ IN/OUT FLAG) 
      STB DRECO     SAVE IN CASE OF POWER FAILURE 
      LDA MWORD     TRANSFER WORD REQUEST 
      CMA,INA         NEGATED 
      STA WDCNT          TO REMAINING WORD COUNT
      STA DREWD     SAVE IN CAES OF POWER FAILURE 
      DLD TEMAB,I   GET ABSOLUTE RECORD NUMBER
      CLE,ELB       DOUBLE TO GET 
      ELA                LOGICAL SECTOR NUMBER
      DST ABSEC     STORE IT
      DST DRABS     SAVE IN CASE OF POWER FAILURE 
      SEZ,SSA,RSS   IS RECORD REQUEST NEGATIVE? 
      JSB TBSCH     GO FIND APPROPRIATE DRIVE 
      JMP EXIT1     SECTOR NUMBER OUT OF RANGE - EXIT 
      LDA B,I       GET SELCODE/UNIT NO. INTO A 
      LDA A,I 
      SZA,RSS       IS DISC PRESENT?
      JMP EXIT1     NO, EXIT
      ISZ MDINT     SECTOR LEGITIMATE; BUMP RETURN
      STB DREBS     SAVE B IN CASE OF POWER FAILURE 
      CCA           SET DRIVER
      STA MBUSY       BUSY FLAG 
DOG8  LDA B,I       GET SELCODE/UNIT AGAIN
      LDA A,I 
DOG4  ALF,ALF       ROTATE SELECT CODE INTO LOW A 
      AND KB77      ISOLATE SELECT CODE 
      STA SCODE     STORE IT FOR FUTURE USE, HEH-HEH
      IOR SFS0      CONSTRUCT "SFS DATA CHANNEL"
      STA DC003          STORE IT 
      ADA KB301     CONSTRUCT "OTA COMMAND CHANNEL" 
      STA CC001          STORE IT 
      ADA KBK77     CONSTRUCT "STC DATA CHANNEL,C"
      STA DC002          STORE IT 
      INA           CONSTRUCT "STC COMM CHANNEL,C"
      STA CC003          STORE IT 
      ADA KB288     CONSTRUCT "OTB DATA CHANNEL"
      STA DC001          STORE IT 
      ADA KB100     CONSTRUCT "CLC DATA CHANNEL"
      STA DC008          STORE IT 
      INA           CONSTRUCT "CLC COMMAND CHANNEL" 
      STA CC002          STORE IT 
      LDA B,I       GET SELCODE/UNIT WORD AGAIN 
      LDA A,I 
      AND K.3       ISOLATE UNIT NUMBER 
      STA UNIT      STORE IT
      INB           GET ADRS OF SECTORS/CLNDR WORD
      STB DENOM     STORE IT IN DENOMINATOR ADRS WD 
      CLB           CLEAR DISC STATUS 
      STB TATUS       SAVE WORD 
      LDB REMAN     GET SECTOR-WITHIN-DRIVE COUNT 
      LDA REMAN+1       INTO B-A FOR DIVISION 
      DIV DENOM,I   GET CYLINDER AND SECTORS REMAIN.
* 
*     REG A NOW CONTAINS THE CYLINDER, B THE SECTOR-WITHIN-CYLINDER 
* 
      STA CYL       STORE CYLINDER NUMBER 
      STB HDSEC     SAVE SEC-WITHIN-CYL COUNT 
      CMB,INB       SUBTRACT IT FROM READABLE CHUNK 
      ADB DENOM,I    SIZE (SECS/CYL) TO GET CHUNK 
      STB RDCHK     SAVE READABLE CHUNK 
      LDA WDCNT     GET WORD COUNT
      ADA KB177     CONVERT THIS TO 
      CLB             NUMBER OF SECTORS NEEDED
      LSR 7             (DIVIDE BY 128) 
      CMA,INA       SUBTRACT NEEDED SECTORS 
      ADA RDCHK       FROM READABLE CHUNK 
      CLE,SSA       NEEDED SECTORS EXCEED READABLE? 
      JMP PARRD     YES, GO PREPARE FOR PARTIAL READ
      LDA WDCNT     NO, SET UP FOR SINGLE READ
      STA DMAWD     STORE DMA WORD COUNT
      STB WDCNT     ZERO REMAINING WORD COUNT 
      JMP DOG2      GO CONTINUE 
PARRD LDA RDCHK     GET READABLE CHUNK
      LSL 7         CONVERT TO WORDS
      STA DMAWD     STORE IN DMA WORD COUNT 
      CMA,INA       SUBTRACT WORDS TO 
      ADA WDCNT          BE READ FROM TOTAL 
      STA WDCNT               REMAINING WORDS 
DOG2 LDA HDSEC      PUT SECTOR-WITHIN-CYLINDER
      CLB               COUNT INTO DOUBLE WORD FRMT 
      ISZ DENOM     BUMP DENOM PTR TO SECS/TRK COUNT
      DIV DENOM,I   GET TRACK (HEAD) AND SECTOR 
* 
*  REG A NOW CONTAINS THE HEAD NO., B THE SECTOR ADDRESS
* 
      ALF,ALF       GET HEAD INTO TOP HALF OF A 
      IOR B         MERGE SECTOR COUNT INTO A 
      STA HDSEC     STORE HEAD/SECTOR COUNT 
* 
*  AT THIS POINT THE ABSOLUTE LINEAR SECTOR NUMBER HAS BEEN 
*  TRANSLATED INTO ITS COMPONENTS, AND THE I/O COMMANDS NEEDED
*  FOR SEEK HAVE BEEN CONFIGURED. 
* 
      CLA,INA       INITIALIZE READ/WRITE FLAG -- 1 
      STA WRFLG        MEANS THIS IS FIRST ATTEMPT
      LDA KM6       INITIALIZE SEEK 
      STA SETRY        RETRY COUNTER
      STA WRTRY     ALSO WRITE/READ RETRY COUNT 
MOVIT EQU * 
      JSB SEEK      GO OUTPUT SEEK COMMAND
      CLA,INA       SET BIT 0 OF
      STA MDFLG        INTERRUPT WORD 
      JMP MDRET     RETURN
      SKP 
* 
*  DISC INFORMATION TABLE SEARCH ROUTINE
*     RETURNS SINGLE-SKIP WITH POINTER IN B TO THE ADDRESS OF THE 
*     SELECT CODE AND UNIT NUMBER OF THE DRIVE CONTAINING THE SECTOR
*     A BAD SECTOR COUNT CAUSES A NO-SKIP RETURN. 
* 
TBSCH NOP           ENTRY POINT 
      DLD MAXSC     GET MAX SECTOR + 1 COUNT INTO AB
      JSB DBSUB     SUBTRACT IT FROM REQUIRED SECTOR
      SSA,RSS       IS SECTOR REQUEST LEGITIMATE? 
      JMP TBSCH,I   NO, RETURN NO-SKIP TO CALLER
      LDA MHAD      YES, GET ADDRESS OF DISC TABLE
      STA SCHAD     STORE IT IN SEARCH ADDRESS WORD 
TBS01 DLD SCHAD,I   GET FIRST SECTOR NUMBER OF DISC 
      JSB DBSUB     SUBTRACT IT FROM REQUIRED SECTOR
* 
*  REGISTERS A-B NOW CONTAIN THE REQUIRED SECTOR NUMBER MINUS THE 
*  NUMBER OF THE FIRST SECTOR ON THE DRIVE.  IF THIS IS POSITIVE, 
*  CHECK THE NEXT DRIVE.  IF NEGATIVE, THE DESIRED SECTOR IS ON 
*  THE PREVIOUS DISC DRIVE
* 
      SSA           START OF DISC EXCEEDS REQUEST?
      JMP TBS02     YES, DESIRED SEC ON PREVIOUS DSC
      DST REMAN     SAVE "REMAINDER" SECTOR COUNT 
      LDB SCHAD     GET TABLE SEARCH POINTER
      ADB K.6           UPDATE POINTER TO FIRST 
      STB SCHAD        SECTOR COUNT OF NEXT DISC
      JMP TBS01     GO CHECK NEXT DISC
TBS02 LDB SCHAD     GET TABLE SEARCH POINTER
      ADB KM4       B POINTS TO DESIRED  SC/UNIT WRD
      ISZ TBSCH     INCREMENT RETURN ADDRESS
      JMP TBSCH,I   RETURN TO CALLER, SINGLE-SKIP 
      SPC 3 
* 
*  DOUBLE PRECISION SUBTRACTION ROUTINE 
*    SUBTRACTS CONTENTS OF A-B FROM THOSE OF ABSEC(0:1); RESULT A-B 
* 
DBSUB NOP           ENTRY POINT 
      CMB,CLE,INB   * 
      CMA,SEZ       *  TAKE NEGATIVE OF A-B CONTENTS
      INA           * 
      CLE            *
      ADB ABSEC+1    *
      SEZ            *   ADD ABSOLUTE SECTOR NUMBER 
      INA            *
      ADA ABSEC      *
      JMP DBSUB,I   RETURN WITH DIFFERENCE IN A-B 
      SKP 
* 
*  ROUTINE THROUGH WHICH ALL INTERRUPTS ARE PROCESSED 
* 
MDINT NOP 
      CLF DINT      DISABLE INTERRUPT 
      DST TEMAB     SAVE  A AND B REGISTERS 
      ERA,ALS       SAVE
      SOC             E 
      INA               AND O 
      STA EANDO           REGISTERS 
* 
* 
*     THE FOLLOWING CODE DETERMINES WHETHER AN INTERRUPT ORIGINATES 
*     FROM AN EXPECTED CONTROLLER (THE ONE CURRENTLY OPERATED BY
*     THE DRIVER) OR IS FROM AN UNEXPECTED SOURCE.  IF EXPECTED,
*     THE INTERRUPT WILL BE HANDLED NORMALLY.  IF UNEXPECTED, A 
*     STATUS WILL BE ISSUED TO EACH OF THE TWO DRIVES ON THE
*     INTERRUPTING CONTROLLER TO CLEAR THE
*     INTERRUPT AND A RETURN WILL BE MADE TO THE MAIN PROGRAM.
* 
      LIA 4         GET SELCODE OF INTERRUPT
      ADA KM1       DECREMENT TO DATA CHANNEL 
      CPA SCODE     COMPARE TO CURRENT SELCODE
      RSS           IT'S EQUAL: CHECK FOR BUSY
     JMP SURP1     SURPRISE: GO RECONFIGURE MSTAT 
      LDB MBUSY     GET BUSY FLAG 
      SSB           IS DRIVER BUSY? 
      JMP EXINT     YES, GO PROCESS INTERRUPT NORMALLY
      JMP SURP2     NO, GO PROCESS SURPRISE 
SURP1 JSB RECON     GO CONFIGURE STATUS INSTRUCTIONS
      LDA UNIT      GET CURRENT UNIT
      STA UNSAV       AND SAVE IT 
SURP2 CLA           SET UNIT NUMBER 
      STA UNIT        TO ZERO 
      JSB MSTAT     ISSUE STATUS TO UNIT ZERO 
      ISZ UNIT      SET UNIT NUMBER TO ONE
      JSB MSTAT     ISSUE STATUS TO UNIT ONE
      LDB MBUSY     GET BUSY FLAG 
      SSB,RSS       IS DRIVER BUSY? 
      JMP MDRET     NO, RETURN
      LDB UNSAV     YES, GET CURRENT UNIT 
      STB UNIT        AND RESTORE IT
      LDA SCODE     GET CURRENT SELCODE 
      JSB RECON     GO RECONFIGURE STATUS 
      JMP MDRET     RETURN
* 
*     THIS ROUTINE IS ENTERED WITH THE DATA CHANNEL NUMBER IN THE 
*     A REGISTER AND IT CONFIGURES THOSE I/O INSTRUCTIONS EXECUTED
*     WHEN THE DRIVER DOES A STATUS OPERATION.
* 
RECON NOP           ENTRY POINT 
      IOR SFS0      CONSTRUCT "SFS DATA CHANNEL"
      STA DC003 
      ADA KB200     CONSTRUCT "LIA DATA CHANNEL"
      STA DC005 
      ADA KB101     CONSTRUCT "OTA CONTROL CHANNEL" 
      STA CC001 
      ADA KBK77     CONSTRUCT "STC DATA CHANNEL,C"
      STA DC004 
      INA           CONSTRUCT "STC COMM CHANNEL,C"
      STA CC003 
      ADA KB3KM     CONSTRUCT "CLC DATA CHANNEL"
      STA DC008 
      INA           CONSTRUCT "CLC COMMAND CHANNEL" 
      STA CC002 
      JMP RECON,I   RETURN
* 
*     THE INTERRUPT IS FROM THE EXPECTED CONTROLLER.
* 
EXINT LDA MDFLG     GET INTERRUPT FLAG
      SLA,RAR       INTERRUPT AFTER NORMAL SEEK?
      JMP MDIS1     YES, GO PREPARE FOR READ/WRITE
      SLA,RAR       INTERRUPT AFTER READ/WRITE? 
      JMP MDIS2     YES, GO CHECK FOR SUCCESS 
*                                   INTERRUPT AFTER RECALIBRATE?
      JMP MDIS3     YES, GO REISSUE REQUESTED SEEK
* 
* 
*  ROUTINE THROUGH WHICH MOST RETURNS FROM THE DRIVER ARE MADE
* 
MDRET LDA EANDO     RESTORE 
      CLO             E 
      SLA,ELA           AND O 
      STO                 REGISTERS 
* 
EXIT1 DLD TEMAB     RESTORE A AND B REGISTERS 
      STF EINT      ENABLE INTERRUPT
      JMP MDINT,I   RETURN
      SKP 
* 
*   PROCESSOR FOR INTERRUPT AFTER SEEK
* 
MDIS1 EQU *         HANDLES INTERRUPT AFTER SEEK
      LDA DC002     GET "STC DATA CHANNEL,C" COMMAND
      STA DC004     STORE IT IN STATUS CHECK ROUTINE
      STA DC007     STORE IT IN DMA SET UP ROUTINE
      ADA KM16C     CONSTRUCT "STF DATA CHANNEL"
      STA DC006     STORE IT IN DMA SET UP ROUTINE
      ADA KB400     CONSTRUCT "LIA DATA CHANNEL"
      STA DC005     STORE IT IN STATUS CHECK ROUTINE
      JSB MSTAT     GO GET STATUS WORD INTO A 
      SLA           ANY ERRORS? 
      JMP MERR1     YES, GO CHECK OUT ERROR 
      AND K.4       NO, CHECK FOR STILL BUSY
      SZA,RSS       IS POSITIONER BUSY? 
      JMP DOG7      NO, CONTINUE
      CLA,INA       YES, CHANGE UNIT
      XOR UNIT        NUMBER TO 
      STA UNIT          OTHER ONE 
      JSB MSTAT     DO STATUS TO CLEAR INTERRUPT
      CLA,INA       RESTORE 
      XOR UNIT        CURRENT UNIT
      STA UNIT          NUMBER
      JMP MDRET     RETURN
DOG7  LDA DMAWD     GET WORD COUNT
      SZA           IS IT ZERO? 
      SSA             OR NEGATIVE?
      JMP DOG5      YES, RETURN WITHOUT READ/WRITING
MDRWR JSB DMAGO     GO SET UP DMA 
      LDA WREAD     GET READ COMMAND INTO A 
      SSB,RSS       READ INTO OR WRITE OUT OF CORE? 
      LDA RITE      WRITE:  GET WRITE COMMAND 
      JSB CCOUT     GO ISSUE COMMAND TO DISC
* 
      LDA K.2       SET BIT 1 OF
      STA MDFLG        INTERRUPT WORD 
      JMP MDRET     GO RETURN TO MAIN TASK
      SPC 2 
* 
*  ERROR DURING SEEK ROUTINE -- B CONTAINS REQUESTED CYLINDER NUMBER
*       A  CONTAINS STATUS WORD 
MERR1 STA TATUS     SAVE STATUS 
      ISZ SETRY     RETRIED ENOUGH TIMES? 
      RSS           NO, CONTINUE
      JMP SFAIL     YES, GO TO SEEK FAIL
      AND BADSK     ISOLATE UNCORRECTABLE ERROR BITS
      SZA           POSSIBLY CORRECTABLE ERRORS?
      JMP SFAIL     NO, GO AND RETURN UNSUCESSFUL 
* 
RESEK LDA RECAL     GET RECALIBRATE COMMAND 
      JSB CCOUT     GO ISSUE THE RECAL COMMAND
      LDB K.4       SET BIT 2 OF
      STB MDFLG        INTERRUPT WORD 
      JMP MDRET     RETURN TO MAIN TASK 
MDIS3 EQU *         INTERRUPT AFTER RESEEK TO EXTREME 
      JSB MSTAT     GO DO STATUS TO CLEAR IT
      JMP MOVIT     TRANSFER FOR SEEK RETRY 
      SPC 3 
* 
*     FAILURE ON SEEK RETRY PROCEDURE (MERR1) 
* 
SFAIL CLA,INA       GET ERROR CONDITION INTO A
*                                     (1 MEANS UNSUCCESSFUL SEEK) 
      STA MBUSY     SET DRIVER BUSY FLAG TO COMPLETE
*                                     BUT UNSUCCESSFUL
      JSB MFAIL     INFORM OPERATOR OF FAILURE
      JMP MDRET     RETURN TO MAIN TASK 
      SPC 3 
* 
*     DISC WON'T TAKE SEEK COMMAND
* 
SFAFK CCA           ALL ONES STATUS MEANS 
      STA TATUS       UNIT IS DEAD
      JMP SFAIL 
      SKP 
