        .TITLE  "DISK CONTROLLER MODULE (DCM2)"
        .SBTTL  "TITLE PAGE"
;******************************************************
;                                                     *
;       PROGRAM ID:     DISK CONTROLLER MODULE        *
;                                                     *
;       VERSION:        2.2  8"     RELEASE 2A        *
;                                                     *
;******************************************************
;                                                     *
;       PRESENTED BY:   JADE COMPUTER PRODUCTS INC.   *
;                       4901 W. ROSECRANS BLVD.       *
;                       HAWTHORNE, CALIFORNIA         *
;                       90250,   U.S.A.               *
;                                                     *
;******************************************************
;                                                     *
;       WRITTEN BY:     STAN KRUMME                   *
;                                                     *
;******************************************************
; THE DISK CONTROLLER MODULE (DCM2) EXECUTES INTERNAL *
; TO THE  JADE DOUBLE D DISK CONTROLLER BOARD.  THIS  *
; PROGRAM PROVIDES A FACILITY TO READ/WRITE DISKETTE  *
; SECTORS AND FORMAT DISKETTE TRACKS  (IN SINGLE AND  *
; DOUBLE DENSITY).  THIS DCM SETS THE PARAMETERS FOR  *
; EACH  DRIVE  DURING THE  "LOG-ON" OPERATION.   THE  *
; FORMAT.COM PROGRAM WRITES AN IDENTIFICATION SECTOR  *
; WHICH PROVIDES  THE NEEDED INFORMATION.   IF  THIS  *
; IDENTITY  SECTOR  IS NOT PRESENT  ON THE DISKETTE,  *
; IT IS  ASSUMED TO BE A  STANDARD  8"  3740 FORMAT.  *
; THIS PROGRAM CONTAINS A 4 WORD  TIMING BLOCK WHICH  *
; SHOULD BE PATCHED TO MATCH THE  USERS DISK DRIVES.  *
; THIS HAS NORMALLY BEEN SET FOR  SHUGART SA800/801.  *
;******************************************************

;******************************************************
; DISK CONTROLLER MODULE IS  COMMAND  COMPATABLE WITH *
; THE FOLLOWING  WESTERN  DIGITAL  CONTROLLER  CHIPS. *
; DOUBLE D  USER SWITCH 0  (U0 OR R0)  MUST BE SET TO *
; INDICATE THE  CONTROLLER CHIP  DATA  BUS  POLARITY. *
;******************************************************
;	CONTROLLER IC    	USER SW0	      *
;	-------------    	--------	      *
;	FD1791-02 (01)    	 CLOSED		      *
;	FD1793-02 (01)    	 OPENED		      *
;	FD1795-02         	 CLOSED		      *
;	FD1797-02         	 OPENED		      *
;******************************************************
; THE FD1795-02 AND FD1797-02 PROVIDE ENHANCED SINGLE *
; DENSITY PERFORMANCE IN THAT  THESE  CHIPS ARE FULLY *
; COMPATABLE WITH FD1771-01 3740 FORMATS.	      *
;******************************************************
        .PAGE
        .SBTTL  "HARDWARE DEFINITION"
;******************************************************
; THE FOLLOWING IS A LIST OF THE INTERNAL I/O ADDRESS *
; ASSIGNMENTS.   THESE PORTS AND CONTROLS CAN ONLY BE *
; USED BY THE ONBOARD Z80A.  THESE PORTS AND CONTROLS *
; ARE NOT IN THE S100 BUS ADDRESS SPACE.              *
;******************************************************

;*******( CONTROLLER PORT ASSIGNMENTS )****************

BL.STS  ==      000H    ;BOARD STATUS PORT.
BL.CTL  ==      000H    ;BOARD CONTROL PORT.
WD.CMD  ==      004H    ;179X COMMAND REGISTER.
WD.STS  ==      004H    ;179X STATUS REGISTER.
WD.TRK  ==      005H    ;179X TRACK REGISTER.
WD.SEC  ==      006H    ;179X SECTOR REGISTOR.
WD.DTA  ==      007H    ;179X DATA REGISTER.

;*******( CONTROLLER FUNCTION ASSIGNMENTS )************
ŠXP.STP  ==      008H    ;ISSUE STEP PULSE.
XP.MTO  ==      010H    ;MOTOR TURN OFF.
XP.IRR  ==      020H    ;S100 INT-REQ RESET.
XP.MTX  ==      040H    ;MOTOR TIME EXTEND.
XP.DSH  ==      080H    ;DATA SYNC HOLD.

;******************************************************
; THE FOLLOWING LIST ASSIGNS EACH  BIT  POSITION  AND *
; FUNCTION OF THE BOARD CONTROL PORT (BL.CTL).        *
;******************************************************

;*******( BIT ASSIGNMENTS )****************************

BC.DSA  ==  00000001B   ;DRIVE SELECT A (2*0).
BC.DSB  ==  00000010B   ;DRIVE SELECT B (2*1).
BC.DSE  ==  00000100B   ;DRIVE SELECT ENABLE.
BC.EIA  ==  00001000B   ;EIA SIGNAL LEVEL OUT.
BC.DDE  ==  00010000B   ;DOUBLE DENSITY ENABLE.
BC.DAS  ==  00100000B   ;DIRECTION AND SIDE
BC.PCA  ==  01000000B   ;PRECOMP SELECT A.
BC.PCB  ==  10000000B   ;PRECOMP SELECT B.

;*******( FUNCTION ASSIGNMENTS )***********************

BC.DSN  ==  BC.DSA!BC.DSB       ;DRIVE NMBR MASK.
BC.SDS  ==  0                   ;SINGLE DENSITY.
BC.DDS  ==  BC.DDE              ;DOUBLE DENSITY.
BC.PCH  ==  BC.PCA              ;PRECOMP - HEAVY.
BC.PCM  ==  BC.PCB              ;PRECOMP - MEDIUM.
BC.PCL  ==  BC.PCA!BC.PCB       ;PRECOMP - LIGHT.
BC.SD1  ==  BC.DAS              ;SELECT SIDE ONE.
BC.INW  ==  BC.DAS              ;STEP INWARD DIRC.

;******************************************************
        .PAGE
;******************************************************
; THE FOLLOWING LIST DEFINES EACH BIT AND FUNCTION OF *
; THE BOARD STATUS PORT (BL.STS).                     *
;******************************************************

BS.US0  ==  00000001B   ;USER SWITCH 0.
BS.US1  ==  00000010B   ;USER SWITCH 1.
BS.TST  ==  00000100B   ;TEST MODE SWITCH.
BS.INT  ==  00001000B   ;HOST INT REQUEST.
BS.EIA  ==  00010000B   ;EIA SIGNAL LEVEL IN.
BS.MOF  ==  00100000B   ;MOTOR OFF INIDCATOR.
BS.TSD  ==  01000000B   ;TWO SIDED DRIVE FLAG.
BS.DCN  ==  10000000B   ;DISK CHANGE INDICATOR.

;******************************************************
; THE FOLLOWING IS A LIST OF  COMMAND CODES ISSUED TO *
; THE 179X-02 DISK CONTROLLER.                        *
;******************************************************

DC.HDL  ==  00011000B   ;SEEK/LOAD RW HEAD.ŠDC.HDU  ==  00010000B   ;SEEK/UNLD RW HEAD.
DC.RDS  ==  10001000B   ;READ SECTOR.
DC.WRS  ==  10101000B   ;WRITE SECTOR.
DC.WRT  ==  11110000B   ;WRITE TRACK FORMAT.
DC.RDA  ==  11000000B   ;READ TRACK ADDRESS.
DC.STS  ==  11010000B   ;SET TYPE 1 STATUS
DC.IFI  ==  11011000B   ;FORCED INTERRUPT.

;******************************************************
; THE FOLLOWING LIST  CONTAINS ALL THE  MASKS USED TO *
; TEST THE 179X-02 STATUS CODES  (PORT WD.STS).       *
;******************************************************

DM.RER  ==  10011101B   ;READ ERROR TEST.
DM.WER  ==  11111101B   ;WRITE ERROR TEST.
DM.FER  ==  11100100B   ;FORMAT ERROR TEST.
DM.TK0  ==  00000100B   ;TRACK 0 TEST.
DM.HDL  ==  00100000B   ;HEAD LOAD TEST.
DM.DNR  ==  10000000B   ;DRIVE NOT READY.
DM.LDE  ==  00000100B   ;LOST DATA ERROR.

;******************************************************
        .PAGE
        .SBTTL  "MEMORY ASSIGNMENTS"
;******************************************************
; THE FOLLOWING LIST DEFINES INTERNAL MEMORY.         *
;******************************************************

;**********( BASE ADDRESS FOR DCM )********************

BASE    ==      1000H           ;BASE ADDRESS.

;**********( MEMORY BANKS )****************************

BANK.0  ==  BASE+0000H          ;BANK 0 DEFINED.
BANK.L  =˝  0400Č               ;BANË LENGTH.
BANK.1  ==  BANK.0+BANK.L       ;BANK 1 DEFINED.

;***********( RESTART VECTORS )************************

RST.0   ==   BANK.0+0000H       ;RESTART 0.
RST.1   ==   BANK.0+0008H       ;RESTART 1.
RST.2   ==   BANK.0+0010H       ;RESTART 2.
RST.3   ==   BANK.0+0018H       ;RESTART 3.
RST.4   ==   BANK.0+0020H       ;RESTART 4.
RST.5   ==   BANK.0+0028H       ;RESTART 5.
RST.6   ==   BANK.0+0030H       ;RESTART 6.
RST.7   ==   BANK.0+0038H       ;RESTART 7.

;**********( INTERRUPT VECTORS )***********************

HR.INT  ==  RST.7               ;MASKABLE.
NM.INT  ==  BANK.0+0066H        ;NON MASKABLE.

;**********( I/O COMMUNICATION  )**********************Š
IO.BLK  ==  BANK.0+0370H        ;I/O BLOCK BEGIN.
TP.STK  ==  IO.BLK+0000H        ;TOP OF STACK.
CMD.BK  ==  IO.BLK+0000H        ;COMMAND BLOCK.
BUF.BG  ==  IO.BLK+0010H        ;SECTOR BUFFER.
FMT.BG  ==  BANK.1+0300H        ;FORMAT BUFFER.
FMT.PS  ==  FMT.BG+0008H        ;FORMAT PROGRAM.

;******************************************************
        .PAGE
        .SBTTL  "MACRO DEFINITIONS"
;******************************************************
; WAIT IS A "RESTART" TO THE TIMER SUBROUTINE ENTRY.  *
; THIS SUBROUTINE PROVIDES MOST OF THE TIMING USED BY *
; THE DOUBLE D CONTROLLER.                            *
;******************************************************

        .DEFINE WAIT = [
         RST    1]

;******************************************************
; ASSEMBLER DIRECTIVES                                *
;******************************************************

        .PABS           ;ABSOLUTE ADDRESSING.
        .PHEX           ;INTEL HEX OBJECT FILE.
        .XLINK          ;NO LINKAGE REQUIRED.

;******************************************************
; TENTH MILLESECOND TIMING CONSTANTS / 0.2 MS FOR 5"  *
;******************************************************

TMR.FC  ==      0019H   ;TIMING CONSTANT, FIRST PASS.
TMR.NC  ==      001CH   ;TIMING CONSTANT, REPEAT PASS.

;******************************************************
;      BAUD RATE GENERATOR - TIMING CONSTANTS         *
;******************************************************
;   BAUDRATE      US/BIT       8" SYS     5 " SYS     *
;   --------      ------       ------     -------     *
;    19200         52.1           9         N.A.      *
;     9600        104.2          25           9       *
;     4800        208.3          57          25       *
;     2400        416.6         121          57       *
;     1200        833.3         248         121       *
;      600       1666.6         N.A.        248       *
;******************************************************

BAUD.C  ==      25.     ;BAUD RATE CONSTANT 9600 8".

;******************************************************
; ERROR RECOVERY VALUES                               *
;******************************************************

RTY.SK  ==      5       ;REPOSITION R/W HEAD ON RETRY.ŠRTY.LS  ==      9       ;LAST REPEATED RETRY.

TRK.OB  ==      26      ;AT FIRST THIRD TRACK OF DISK.
TRK.IB  ==      52      ;AT SECOND THIRD TRACK.

;******************************************************
        .PAGE
        .SBTTL  "BASE PAGE"
;******************************************************
; THE FOLLOWING AREA IS THE INITIAL START JUMP TABLE. *
; THE FIRST JUMP IS EXECUTED WHEN THE ONBOARD Z80A IS *
; RESET.   THE  SECOND JUMP IS THE  DCM ENTRY  FROM A *
; BOOTSTRAP LOADER.  THIS ENTRY ASSUMES  DCM HAS BEEN *
; LOADED INTO DOUBLE D BANK 1  BY THE LOADER ROUTINE. *
; THE LAST  TWO BYTES  HOLD THE  JUMP ADDRESS USED BY *
; RESTART INTERRUPT ROUTINE AT BANK 0 + 0380H.        *
;******************************************************

        .LOC    RST.0           ;MODULE BEGINNING.

         JMP    0               ;NOT IMPLEMENTED.
         JMP    INIT.B+BANK.L   ;BOOTSTRAPPED ENTRY.
HR.VEC: .WORD   X.CUTE          ;HOST INTERRUPT VECTOR.

;******************************************************
; THE FOLLOWING SUBROUTINE IS THE ENTRY POINT FOR THE *
; DISK CONTROLLER TIMING MODULE. THIS MODULE PROVIDES *
; DELAYS WHICH ARE MULTIPLES OF 100 MICROSECONDS. THE *
; CONTENTS OF REGISTER PAIR  DE  DETERMINES THE TOTAL *
; PERIOD.   (DELAY = (DE )* 100 MICROSECONDS).   THIS *
; SUBROUTINE IS ENTERED BY THE MACRO "WAIT".          *
;******************************************************

        .LOC    RST.1           ;TIMING ENTRY POINT.

        MVI     B,TMR.FC        ;FIRST TICK CONSTANT.
        DJNZ    .               ;AUTO DEC UNTIL ZERO.
        JMP     TICK.E          ;JUMP TO TICK ENTRY.

;******************************************************
; THE FOLLOWING SECTION IS THE DISK DRIVE TIMING AREA.*
; THE TIMES ARE SET FOR THE SHUGART SA800.  THIS AREA *
; SHOULD BE MODIFIED FOR THE END USERS DRIVE TYPE.    *
;******************************************************

;*******( TIMING VALUES IN 0.1 MS )********************

        .LOC    RST.2

TM.HLD: .WORD   350     ;HEAD ENGAGE TIME.
TM.STP: .WORD   80      ;STEPPER INTERVAL.
TM.ALS: .WORD   80      ;AFTER LAST STEP.
TM.MTO: .WORD   1       ;MOTOR START UP.

;******************************************************
        .PAGEŠ;******************************************************
; THE FOLLOWING SUBROUTINE PROVIDES THE R/W HEAD CNTL *
; FUNCTION.  AS THE  FD179X-02  DOES  NOT  OFFER THIS *
; EXPLICIT COMMAND, THE SEEK COMMAND (TYPE-1) IS USED *
; WITH THE HEAD LOAD BIT SET / RESET. THE DESTINATION *
; TRACK IS SET EQUAL TO THE TRACK REGISTER  TO BYPASS *
; THE  FD179X-02 STEPPING FUNCTION.   PLEASE REFER TO *
; THE FD179X-02 FLOW-CHART FOR TYPE-1 COMMANDS.       *
;******************************************************

EX.HCF: POP     Y               ;RETURN ADDR IN REG Y.
        IN      WD.TRK          ;READ PRESENT TRACK.
        OUT     WD.DTA          ;SET DESTINATION TRK.
        MOV     A,B             ;LOAD TYPE-1 COMMAND.
        XRA     C               ;INVERT (1791-01).
        OUT     WD.CMD          ;ISSUE COMMAND.
        JMPR    .               ;WAIT FOR INTERRUPT.

;******************************************************
; THE  FOLLOWING  SUBROUTINE  UPDATES  THE  FD179X-02 *
; STATUS PORT TO REFLECT CURRENT TYPE-1 STATUS CODES. *
; NOTE: THIS IS A  TYPE-4  COMMAND WITH  NO INTERRUPT *
; CONDITIONS SET.                                     *
;******************************************************

EX.STS: MVI     A,DC.STS        ;LOAD SET-STATUS CMND.
        XRA     C               ;INVERT (1791-01).
        OUT     WD.CMD          ;ISSUE COMMAND.
        XTHL                    ;PAUSE FOR FD179X-02.
        XTHL                    ;PAUSE MORE.Š        XTHL                    ;PAUSE STILL MORE.
        XTHL                    ;PAUSE LAST TIME.
        IN      WD.STS          ;INPUT STATUS PORT.
        XRA     C               ;INVERT (1791-01).
        RET                     ;RETURN TO USER.

;******************************************************
; THE  FOLLOWING SECTION IS THE  MASKABLE  INTERRUPT  *
; ROUTINE.  THIS ROUTINE IS EXECUTED WHEN RESTARTING  *
; THE Z80 FROM A HALT.   THE FUNCTIONS ARE RESET THE  *
; DOUBLE D INT REQ FLIP-FLOP,  PUT  THE  INTERRUPTED  *
; ADDR IN REG DE, AND JUMP ADDRESS AT "HR.VEC".       *
;******************************************************

        .LOC    HR.INT          ;HOST INTERRUPT ADDR.
        IN      XP.IRR          ;RESET INTERRUPT REQ FF
        POP     D               ;PURGE INTERRUPTED ADDR
        LHLD    HR.VEC          ;LOAD RETURN ADDRESS
        PCHL                    ;JUMP RETURN ADDRESS

;******************************************************
        .PAGE
        .SBTTL  "COMMAND FETCH AND BRANCH"
;******************************************************
; THE FOLLOWING SECTION HALTS EXECUTION OF THE        *
; ONBOARD Z80A PROCESSOR.  DURING THIS TIME THE HOST  *
; SYSTEM CAN SWITCH THE CONTROLLER MEMORY INTO THE    *
; S100 BUS FOR STATUS CHECK, SETTING COMMAND BLOCK,   *
; AND SECTOR DATA TRANSFERS.                          *
;******************************************************

FETCH:  EI              ;ENABLE INTERRUPT START
        HLT             ;HALT ON-BOARD PROCESSOR

;******************************************************
; THE FOLLOWING SECTION GAINS CONTROL AFTER THE DISK  *
; CONTROLLER IS INTERRUPTED FROM THE HALT CONDITION.  *
; THIS SECTION BRACNCHES TO THE INDIVIDUAL COMMAND    *
; ROUTINES.  THE COMMAND TABLE CONTAINS THE ADDRESSES *
; FOR THIS DISTRIBUTION.                              *
;******************************************************

X.CUTE: LDA     CB.CMD          ;LOAD HOST COMMAND.
        ANI     CM.MSK          ;MASK ANY OPTIONS.
        ADD     A               ;GET 2*A VALUE.
        MVI     D,0             ;ZERO D REGISTER.
        MOV     E,A             ;DE NOW TABLE OFFSET.
        LXI     H,CM.DTA        ;LOAD TABLE ADDRESS.
        DAD     D               ;NOW POINTS TO ENTRY.
        MOV     E,M             ;LOW ORDER ADDR LOAD.Š        INX     H               ;POINT TO NEXT BYTE.
        MOV     D,M             ;HI ORDER ADDRESS.
        XCHG                    ;BRANCH ADDR IN HL.
        PCHL                    ;BRANCH TO COMMAND.

;******************************************************
; THE FOLLOWING AREA IS  THE  COMMAND  DRIVER  TABLE. *
; EACH ENTRY POINTS TO THE COMMAND DRIVER ROUTINE.    *
;******************************************************

CM.DTA  ==      .               ;COMMAND TABLE.

..CM0A: .WORD   $.LGON          ;LOG-ON DRIVE.
..CM1A: .WORD   $.READ          ;READ SECTOR.
..CM2A: .WORD   $.WRIT          ;WRITE SECTOR.
..CM3A: .WORD   $.FORM          ;FORMAT TRACK.
..CM4A: .WORD   $.ADDR          ;READ ADDRESS.
..CM5A: .WORD   $.LIST          ;LIST OUTPUT.
..CM6A: .WORD   $.LSTT          ;LIST STATUS.
..CM7A: .WORD   $.IDLE          ;BACKGROUND.

CM.MSK  ==      007H            ;COMMAND MASK.

;******************************************************
        .PAGE
        .SBTTL  "NON MASKABLE INTERRUPT"
;******************************************************
; THE FOLLOWING SECTION IS THE NON-MASKABLE INTERRUPT *
; ROUTINE.  UPON 179X-02 COMMAND TERMINATION THE Z80  *
; RECIEVES A NON-MASKABLE INTERRUPT.  THE STATUS PORT *
; IS INTERROGATED AND SAVED (SV.STS).  REGISTER IY    *
; CONTAINS THE RETURN ADDRESS.                        *
;******************************************************

        .LOC    NM.INT          ;NON-MASKABLE INT.

WD.INT: IN      WD.STS          ;GET 179X STATUS.
        XRA     C               ;INVERT (1791).
        STA     SV.STS          ;SAVE STATUS.
        XTIY                    ;EXCHANGE (SP)<>IY.
        RETN                    ;RETURN AT OLD IY.

;******************************************************
; THIS SECTION IS THE REMAINDER OF THE TIMING         *
; SECTION ENTERED BY A RESTART 1.  SEE THAT SECTION   *
; FOR THE DESCRIPTION.                                *
;******************************************************

TICK.R: MVI     B,TMR.NC        ;NORMAL TICK CONSTANT.
        DJNZ    .               ;AUTO DEC UNTIL ZERO.
TICK.E: DCX     D               ;DECREMENT AMOUNT.
        MOV     A,D             ;GET HIGH ORDER.
        ORA     E               ;AND LOW ORDER.
        NOP                     ;TIMING ADJUST.
        NOP                     ;TIMING ADJUST.
        JRNZ    TICK.R          ;REPEAT UNTIL ZERO.
        RET                     ;RETURN TO USER.

;******************************************************
        .PAGE
        .SBTTL  "COMMAND CONTROLLERS"
;******************************************************
;  $.READ IS THE READ-SECTOR COMMAND CONTROLLER.      *
;******************************************************

$.READ: CALL    SELECT          ;SELECT DRIVE ROUTINE.
        CALL    SEEK            ;SEEK TRACK, SET CTLS.
        JRNZ    ..EXIT          ;DRIVE OR SEEK ERROR.
        CALL    RD.SEC          ;READ DISK SECTOR.
..EXIT: JMP     FETCH           ;GET NEXT COMMAND.
Š;******************************************************
;  $.WRIT IS THE WRITE-SECTOR COMMAND CONTROLLER.     *
;******************************************************

$.WRIT: CALL    SELECT          ;SELECT DRIVE ROUTINE.
        CALL    SEEK            ;SEEK TRACK, SET CTLS.
        JRNZ    ..EXIT          ;DRIVE OR SEEK ERROR.
        CALL    WR.SEC          ;WRITE DISK SECTOR.
..EXIT: JMP     FETCH           ;GET NEXT COMMAND.

;******************************************************
;  $.FORM IS THE FORMAT-TRACK COMMAND CONTROLLER.     *
;******************************************************

$.FORM: CALL    SELECT          ;SELECT DRIVE NUMBER.
        LDA     CB.SEC          ;LOAD FORMAT FLAGS.
        MOV     DV.FLG(X),A     ;RESET DRIVE FLAGS.
        CALL    SEEK            ;SEEK TRACK, SET CTLS.
        JRNZ    ..EXIT          ;DRIVE OR SEEK ERROR.
        CALL    WR.TRK          ;WRITE DISK TRACK.
..EXIT: JMP     FETCH           ;GET NEXT COMMAND.

;******************************************************
;  $.LGON IS THE DRIVE LOG-ON COMMAND CONTROLLER      *
;******************************************************

$.LGON: CALL    SELECT          ;SELECT DRIVE NUMBER.
        XRA     A               ;ZERO REGISTER A.
        STA     CB.TRK          ;SET TRACK AT 0.
        INR     A               ;NOW A REG IS 1.
        STA     CB.SEC          ;SET SECTOR TO ID.
        CALL    SEEK            ;SEEK TRACK, SET CTLS.
        JRNZ    ..EXIT          ;DRIVE OR SEEK ERROR.
        CALL    RD.SEC          ;READ ID SECTOR.
        JRNZ    ..EXIT          ;READ ERROR DETECTED.
        CALL    LOG.ON          ;LOG ON DISK DRIVE.
..EXIT: JMP     FETCH           ;GET NEXT COMMAND.

;******************************************************
        .PAGE
;******************************************************
;  $.ADDR IS THE READ-ADDRESS COMMAND CONTROLLER.     *
;******************************************************

$.ADDR: MVI     A,0FFH          ;LOAD ALL ONES.
        STA     CB.STS          ;STORE ERRORS.
        JMP     FETCH           ;NOT IMPLEMENTED.

;******************************************************
;  $.LIST IS A LIST DEVICE COMMAND CONTROLLER.        *
;******************************************************

$.LIST: CALL    LST.OT          ;SEND CHAR TO LIST.
        JMP     FETCH           ;GET NEXT COMMAND.

;******************************************************
;  $.LSTT CHECKS LIST DEVICE STATUS                   *
;******************************************************Š
$.LSTT: IN      BL.STS          ;GET BOARD STATUS.
        ANI     BS.EIA          ;TEST READY BIT.
        JZ      ..EXIT          ;IF ZERO GOTO EXIT.
        MVI     A,0FFH          ;LOAD ALL ONES.
..EXIT: STA     CB.STS          ;STORE STATUS.
        JMP     FETCH           ;GET NEXT COMMAND.

;******************************************************
;  $.IDLE IS THE IDLE COMMAND CONTROLLER.             *
;******************************************************

$.IDLE: IN      BL.STS          ;INPUT BOARD STATUS.
        ANI     BS.INT          ;CHECK HOST INTERRUPT.
        JRZ     $.IDLE          ;REPEAT IDLE CHECK.
        IN      XP.IRR          ;RESET INTERRUPT REQ.
        JMP     FETCH           ;GET NEXT COMMAND.

;******************************************************
        .PAGE
        .SBTTL  "DRIVE SELECTION ROUTINE"
;******************************************************
; THE FOLLOWING  SUBROUTINE  SELECTS  REQUESTED DRIVE *
; NUMBER 0-3 (A-D). BEFORE DRIVE SELECTION, THE DRIVE *
; MOTOR CONTROL STATE IS TESTED AND ENABLED IF NEEDED.*
; INDEX REGISTER X  IS SET  POINTING TO THE REQUESTED *
; DRIVE TABLE ENTRY.  THE DRIVE IS THEN SELECTED.     *
;******************************************************

;*******( MOTOR CHECK ROUTINE )************************

SELECT: IN      BL.STS          ;BOARD LEVEL STATUS.
        ANI     BS.MOF          ;CHECK MOTOR STATE.
        IN      XP.MTX          ;START OR EXTEND TIMER.
        JRZ     ..CKDV          ;IF WAS ON, NO STARTUP.
        LDED    TM.MTO          ;MOTOR STARTUP DELAY.
        WAIT                    ;PROGRAMMABLE DELAY.

;*******( NEW SELECTION CHECK )************************

..CKDV: LDA     CB.DRV          ;LOAD DRIVE NUMBER.
        ANI     BC.DSN          ;GET DRIVE NUMBER.
        CMP     DV.NBR(X)       ;CURRENTLY SELECTED?
        RÚ                      ;RETURN IF DRV SAME.

;*******( SET TABLE POINTER )**************************

        LXI     X,DV.TBL        ;DRIVE TABLE ADDR.
        LXI     D,DV.DES        ;DRIVE ENTRY SIZE.
..NEXT: DCR     A               ;DECREMENT DRV NO.
        JM      ..DSLT          ;IF S=1 EXIT.
        DADX    D               ;POINT NEXT DRIVE.
        JMPR    ..NEXT          ;TRY THIS DRIVE.

;*******( DESELECT OLD DRIVE )*************************

..DSLT: MVI     B,DC.HDU        ;LOAD UNLOAD R/W HEAD.
        CALL    EX.HCF          ;FD179X-02 TYPE 1 CMND.
        LDA     SV.CTL          ;BL.CTL LAST ISSUED.
        ANI     #BC.DSE         ;DRIVE SELECT DSBLD.
        OUT     BL.CTL          ;ISSUE DESELECT.Š
;*******( SELECT NEW DRIVE )***************************

        ANI     #BC.DSN         ;STRIP OFF DRIVE NMBR.
        ORA     DV.NBR(X)       ;OR IN NEW DRIVE NMBR.
        OUT     BL.CTL          ;OUTPUT DRIVE NMBR.
        ORI     BC.DSE          ;SET DRV ENABLE BIT.
        OUT     BL.CTL          ;ENABLE NEW DRIVE.
        ANI     BC.DSN!BC.DSE   ;NOW JUST DRIVE ENBLED.
        STA     SV.DRV          ;SAVE DRIVE SELECT.
        RET                     ;DRIVE IS SELECTED.

;******************************************************
        .PAGE
        .SBTTL  'SEEK TRACK ROUTINE'
;******************************************************
; THE FOLLOWING SUBROUTINE PERFORMS THE TRACK SEEK    *
; OPERATION.  AFTER THE SEEK OPERATION, THE DENSITY   *
; AND PRE-COMPENSATION CONTROLS ARE SET.              *
;******************************************************

;*******( HEAD LOADING )*******************************

SEEK:   CALL    EX.STS          ;GET DRIVE STATUS.
        ANI     DM.HDL!DM.DNR   ;CHECK HEAD AND READY.
        JM      ..NRDY          ;DRIVE NOT READY EXIT.
        JNZ     ..DTAS          ;BYPASS IF HEAD LOADED.
        MVI     B,DC.HDL        ;HEAD-LOAD COMMAND.
        CALL    EX.HCF          ;EXEC FD179X-02 TYPE 1.
        LDED    TM.HLD          ;SET HEAD-LOAD DELAY.
        WAIT                    ;PROGRAMMABLE DELAY.

;*******( DETERMINE TRACK NMBR AND SIDE )**************

..DTAS: IN      BL.STS          ;INPUT BOARD STATUS.
        ANI     BS.TSD          ;TEST DISK SIDES FLAG.
        LDA     CB.TRK          ;GET LOGICAL TRACK NO.
        MOV     L,A             ;SAVE LOGICAL TRACK.
        JNÚ     ..NDBL          ;SKIP IF NOT DBL SIDED.
        RAR                     ;DIV BY 2 DOUBLE SIDE.
..NDBL: STA     PH.TRK          ;STORE PHYSICAL TRACK.
        MOV     H,A             ;SAVE PHYSICAL NUMBER.
        LDA     SV.DRV          ;LOAD DRV NMBR ENABLED.
        JRNC    ..SID0          ;SKIP NEXT IF SIDE 0.
        ORI     BC.SD1          ;OR IN SELECT SIDE 1.
..SID0: STA     SV.DAS          ;STORE DRV AND SIDE EN.
        MOV     D,A             ;SAVE DRV AND SIDE EN.
        MOV     A,H             ;LOAD PHYSICAL NUMBER.
        SUB     DV.TRK(X)       ;TRACK OFFSET TESTED.
        JRNZ    ..SEEK          ;IF OFFTRACK, DO SEEK.
        IN      BL.STS          ;INPUT BOARD STATUS.
        ANI     BS.TSD          ;TEST DISK SIDES FLAG
        JZ     ..DSID           ;GOTO DOUBLE SIDE CTL.

;*******( SINGLE SIDED DISKETTE )**********************

..SSID: MOV     A,DV.CTL(X)     ;GET PREVIOUS CONTROLS.
        JMP     ..EXIT          ;SET CONTROLS / EXIT.
Š;*******( DRIVE NOT READY EXIT )***********************

..NRDY: MVI     A,CS.DNR        ;DRIVE NOT READY FLAG.
        STA     CB.STS          ;STORE ERROR STATUS.
        ANA     A               ;SET NOT ZERO FLAG.
        RET                     ;ERROR EXIT.

;******************************************************
        .PAGE
;*******( DISKETTE IS DOUBLE SIDED )*******************

..DSID: MOV     A,H             ;GET PHYSICAL TRK NMBR.
        ANA     A               ;TEST IF TRACK ZERO.
        JRZ     ..DCTL          ;IF ZERO, RESET CNTLS.
        MOV     A,DV.CTL(X)     ;LOAD OLD DRV CTLS.
        ANI     #BC.SD1         ;STRIP OFF SIDE CMND.
        ORA     D               ;OR IN NEW SIDE CMND.
        JMP     ..EXIT          ;SET CONTROLS / EXIT.

;*******( SET DIRECTION AND COUNT STEPS )**************

..SEEK: PUSH    PSW             ;SAVE REG A AND FLGS.
        LDED    TM.SAW          ;STEP AFTER WRITE.
        WAIT                    ;PROGRAMMABLE DELAY.
        POP     PSW             ;RESTORE A AND FLGS.
        JRC     ..SOUT          ;IF CARRY STEP OUT.
..SIN:  MOV     L,A             ;MOVE OFFSET TO L.
        LDA     SV.DRV          ;DRIVE SELECT BITS.
        ORI     BC.INW          ;SET STEP DIRC IN.
        OUT     BL.CTL          ;OUTPUT CONTROL.
        JMPR    ..STEP          ;GOTO STEP ROUTINE.
..SOUT: NEG                     ;COMPLEMENT OFFSET.
        JM      ..HOME          ;BETTER HOME DRV.
        MOV     L,A             ;MOVE OFFSET TO L.
        LDA     SV.DRV          ;DRIVE SELECT BITS.
        OUT     BL.CTL          ;SET DIRECTION OUT.
..STEP: IN      XP.STP          ;ISSUE STEP PULSE.
        LDED    TM.STP          ;STEP DELAY TIME.
        WAIT                    ;PROGRAMMABLE DELAY.
        DCR     L               ;DECREMENT STEPS.
        JRNZ    ..STEP          ;REPEAT OPERATION.
        LDA     SV.DAS          ;LOAD DRV AND SIDE.
        OUT     BL.CTL          ;OUTPUT CONTROL.
        LDED    TM.ALS          ;MORE AFTER LAST STP.
        WAIT                    ;PROGRAMMABLE DELAY.

;******************************************************
        .PAGE
;*******( CONTROL DETERMINATION )**********************

..DCTL: LDA     CB.TRK          ;LOAD LOGICAL TRACK.
        CPI     1               ;COMPARE AGAINST 1.
        JRC     ..SDEN          ;TRACK 0 IS SDENS.
        MVI     A,DF.DTD        ;DATA TRK DENS FLG.
        JNZ     ..DTST          ;GOTO TEST DENSITY.
        MVI     A,DF.T1D        ;TRACK 1 DENS FLAG.
..DTST: ANA     DV.FLG(X)       ;TEST DENSITY FLAGS.
        JZ      ..SDEN          ;IF ZERO, THEN SDENS.
..DDEN: LDA     PH.TRK          ;LOAD PHYSICAL TRACK.
        CPI     TRK.OB          ;TEST OUTSIDE BOUNDRY.
        MVI     B,BC.DDS!BC.PCL ;DDENS AND LOW PRECOMP.
        JRC     ..CTLS          ;SET FOR OUTSIDE TRKS.
        CPI     TRK.IB          ;TEST INSIDE BOUNDRY.
        MVI     B,BC.DDS!BC.PCM ;DDENS AND MED PRECOMP.Š        JRC     ..CTLS          ;JUMP TO CONTROLS SET.
        MVI     B,BC.DDS!BC.PCH ;DDENS AND MAX PRECOMP.
        JMPR    ..CTLS          ;JUMP TO CONTROLS SET.        
..SDEN: MVI     B,BC.SDS!BC.PCL ;SDEN AND PC-LOW.

;*******( SET CONTROL VALUES AND EXIT )****************

..CTLS: LDA     SV.DAS          ;GET DRIVE AND SIDE.
        ORA     B               ;SET PRECOMP AND DENS.
        MOV     DV.CTL(X),A     ;SAVE CONTROLS FOR DRV.
..EXIT: OUT     BL.CTL          ;OUTPUT CONTROLS.
        STA     SV.CTL          ;SAVE THESE CONTROLS.
        LDA     PH.TRK          ;PHYSICAL TRACK NMBR.
        MOV     DV.TRK(X),A     ;SET DRIVE TABLE.
        LDA	CB.TRK          ;LOGICAL TRACK NMBR.
        XRA     C               ;INVERT (1791-01).
        OUT     WD.TRK          ;SET TRACK REGISTER.
        XRA     A               ;SET ZERO FLAG.
        RET                     ;RETURN TO CALLER.

;*******( CALIBRATE TRACK NUMBER )*********************

..HOME: CALL    HOME.D          ;HOME SELECTED DRIVE.
        RNZ                     ;EXIT SEEK, HOME BAD.
        JMP     ..DTAS          ;NOW SEEK TRACK.

;******************************************************
        .PAGE
        .SBTTL  "READ SECTOR DRIVER"
;******************************************************
; RD.SEC IS THE SUBROUTINE THAT INTERACTS WITH THE    *
; 179X-02 DURING READ SECTOR OPERATIONS. THIS SECTION *
; INITIATES THE DISK TRANSFER, SERVICES THE CONTROLLER*
; CHIP DURING DATA TRANSFER, AND TERMINATES OPERATION *
; WHEN FINISHED.  ERROR DETECTION IS IMPLEMENTED AND  *
; RETRIES ARE EXRCUTED IF DATA ERRORS ARE DETECTED.   *
;******************************************************

;*******( INITIALIZE READ OPERATION )******************

RD.SEC: XRA     A               ;ZERO A REGISTER.
        STA     ERR.CT          ;ZERO ERROR COUNT.
        LDA     CB.SEC          ;LOAD SECTOR NMBR.
        XRA     C               ;INVERT (1791-01).
        OUT     WD.SEC          ;SET SECTOR REGISTER.
..RTRY: LXI     Y,..NMI         ;LOAD NMI VECTOR.
        LHLD    BUF.ST          ;BUFFER START.
        MVI     A,DC.RDS        ;READ SECTOR COMMAND.
        XRA     C               ;INVERT (1791-01).
        OUT     WD.CMD          ;ISSUE READ COMMAND

;*******( DATA TRANSFER LOOP )*************************

..REPT: IN      XP.DSH          ;HOLD FOR DATA
        IN      WD.DTA          ;INPUT DATA.
        XRA     C               ;INVERT (1791-01).
        MOV     M,A             ;PUT INTO BUFFER
        INX     H               ;BUMP BUFF POINTER
        JMPR    ..REPT          ;GO FOR ANOTHER

;*******( CHECK STATUS )*******************************

..NMI:  ANI     DM.RER          ;TEST FOR ERRORS.
        STA     CB.STS          ;SAVE READ STATUS.
        RZ                      ;RETURN COMPLETE.
        CALL    CHK.RT          ;CHECK ABOUT RETRYS.
        JRZ     ..RTRY          ;PERFORM RETRY.
        RET                     ;ERROR RETURN.

;******************************************************
        .PAGE
        .SBTTL  "WRITE SECTOR DRIVER"
;******************************************************
; WR.SEC  SUBROUTINE  INTERACTS  WITH  THE  FD179X-02 *
; DURING WRITE SECTOR OPERATIONS. THIS SECTION        *
; INITIATES THE DISK TRANSFER, SERVICES THE CONTROLLER*
; CHIP, AND TERMINATES THE OPERATION. ERROR DETECTION *
; IS IMPLEMENTED.                                     *Š;******************************************************

;*******( INITIALIZE WRITE OPERATION )*****************

WR.SEC: XRA     A               ;ZERO REGISTER.
        STA     ERR.CT          ;SET ERROR COUNTER.
        LDA     CB.SEC          ;LOAD SECTOR NMBR.
        XRA     C               ;INVERT (1791-01).
        OUT     WD.SEC          ;SET SECTOR REGISTER.
..RTRY: LXI     Y,..NMI         ;SET NMI RETURN.
        LHLD    BUF.ST          ;BUFFER START.
        MVI     A,DC.WRS        ;LOAD WRITE SECTOR CMD.
        XRA     C               ;INVERT (1791-01).
        OUT     WD.CMD          ;ISSUE COMMAND.

;*******( DATA TRANSFER LOOP )*************************

..REPT: IN      XP.DSH          ;HOLD FOR DATA REQ.
        MOV     A,M             ;GET DATA BYTE.
        XRA     C               ;INVERT (1791-01).
        OUT     WD.DTA          ;OUTPUT DATA BYTE.
        INX     H               ;INCREMENT BUFF POINTER
        JMPR    ..REPT          ;REPEAT SEQUECE

;*******( CHECK STATUS )*******************************

..NMI:  ANI     DM.WER          ;TEST FOR WRITE ERRORS.
        STA     CB.STS          ;STORE WRITE STATUS.
        RZ                      ;RETURN COMPLETE.
        CALL    CHK.RT          ;CHECK ABOUT RETRYS.
        JRZ     ..RTRY          ;PERFORM RETRY.
        RET                     ;ERROR RETURN.

;******************************************************
        .PAGE
        .SBTTL  "WRITE TRACK DRIVER"
;******************************************************
; WR.TRK IS THE SUBROUTINE WHICH INITIATES A FORMAT   *
; TRACK COMMAND (WRITE-TRACK 179X-02 TYPE 3).  THE    *
; FORMATTING BYTE STREAM IS PROVIDED BY A PROGRAM     *
; WHICH MUST BE PRESENT IN THE FORMAT BUFFER.         *
;******************************************************

;*******( INITIALIZE WRITE TRACK )*********************

WR.TRK: LXI     Y,..NMI         ;LOAD NMI VECTOR.
        MVI     A,DC.WRT        ;WRITE TRACK CMND.
        XRA     C               ;INVERT (1791-01).
        OUT     WD.CMD          ;ISSUE COMMAND.
        JMP     FMT.PS          ;FORMAT PROG START.

;*******( CHECK COMPLETION STATUS )********************

..NMI:  ANI     DM.FER          ;TEST FOR ERRORS.
        MOV     B,A             ;HOLD THIS STATUS.
        IN      BL.STS          ;INPUT BOARD STATUS.
        ANI     BS.TSD          ;TEST TWO SIDED BIT.
        MOV     A,B             ;RESTORE STATUS TO A.
        JRNZ    ..EXIT          ;NOT ZERO IS ONE SIDED.
        ORI     CS.TSD          ;OR IN TWO SIDED FLAG.
..EXIT: STA     CB.STS          ;STORE FORMAT STATUS.
        SHLD    CW.LNG          ;DISPLAY TRAIL BYTES.
        RET                     ;RETURN TO USER.

;******************************************************Š        .PAGE
        .SBTTL  "RETRY CONTROLLER"
;******************************************************
; CHK.RT IS THE SUBROUTINE USED BY RD.SEC AND         *
; WR.SEC TO COUNT RETRY OPERATIONS AND PERFORM A      *
; RE-SEEK OPERATION WHEN NEEDED.                      *
;******************************************************

;*******( CHECK IF RECOVERABLE )***********************

CHK.RT: ANI     DM.DNR          ;TEST NOT READY BIT.
        JRNZ    ..EXIT          ;CAN NOT RECOVER.
        LDA     CB.MOD          ;GET COMMAND MODE.
        ANI     CM.NRT          ;NO RETRYS CHECK.
        JRNÚ    ..EXIÔ          ;SHOULÄ NOÔ RECOVER.
        IN      XP.MTX          ;MOTOR TIME EXTEND.

;*******( RECORD RETRY )*******************************

        LDA     ERR.CT          ;GET ERROR COUNT.
        INR     A               ;INCREMENT.
        STA     ERR.CT          ;STORE NEW COUNT.
        CPI     RTY.SK          ;SHOULD TRY SEEK?
        JRNZ    ..CKLS          ;IF NOT, CHECK LAST.

;*******( REPOSITION R/W HEAD )************************
        
        CALL    HOME.D          ;HOME SELECTED DRIVE.
        JRNZ    ..EXIT          ;ERROR EXIT.
        CALL    SEEK            ;SEEK DESIRED TRACK.

;*******( HOLD READ GATE FOR 3/4 REVOLUTION )**********

..CKLS: CPI     RTY.LS          ;WAS THIS THE LAST.
        JRZ     ..STNZ          ;ERROR LAST RETRY.
        LDED    TM.PLD          ;PHASE LOCK DELAY.
        WAIT                    ;PROGRAMMABLE DELAY.
        XRA     A               ;CLEAR FOR RETRY.
        RET                     ;TRY AGAIN EXIT.

;*******( ERROR EXIT )*********************************

..STNZ: INR     A               ;SET NOT ZERO.
..EXIT: RET                     ;ERROR EXIT.

;******************************************************
        .PAGE
        .SBTTL  "RESTORE TRACK 0"
;******************************************************
; HOME.D IS THE SUBROUTINE THAT STEPS THE DISK DRIVE  *
; R/W HEAD OUTWARD UNTIL THE TRACK 0 FLAG BECOMES     *
; ACTIVE OR 255 STEPS HAVE BEEN ISSUED.               *
;******************************************************

;*******( RESTORE R/W HEAD )***************************

HOME.D: LDA     SV.DRV          ;LOAD DRV NMBR ENABLED.
        OUT     BL.CTL          ;ISSUE CONTROLS.Š        STA     SV.CTL          ;AND SAVE THESE.
        MVI     L,255           ;SET STEP COUNTER.
..STEP: CALL    EX.STS          ;CHECK DISK STATUS.
        ANI     DM.TK0          ;INSPECT TRACK 0 FLG.
        JRNZ    ..EXIT          ;IF SET, GO ..EXIT.
        DCR     L               ;DECREMENT STEP COUNT.
        JRZ     ..EROR          ;ERROR IF 255 STEPS.
        IN      XP.STP          ;ISSUE STEP PULSE.
        LDED    TM.STP          ;LOAD STEP DELAY.
        WAIT                    ;PROGRAMMABLE DELAY.
        JMPR    ..STEP          ;TRY STEPPING AGAIN.

;*******( DRIVE IS RESTORED )**************************

..EXIT: LDED    TM.ALS          ;TIME AFTER LAST STEP.
        WAIT                    ;PROGRAMMABLE DELAY.
        MOV     A,C             ;GET WD TRK 0 VALUE.
        OUT     WD.TRK          ;ZERO TRACK REGISTER.
        XRA     A               ;ZERO A REG, SET FLAG.
        MOV     DV.TRK(X),A     ;SET TRACK VALUE.
        RET                     ;RETURN TO CALLER.

;*******( TRACK 0 NOT FOUND )**************************

..EROR: MVI     A,CS.HME        ;LOAD HOME ERROR FLAG.
        STA     CB.STS          ;STORE ERROR STATUS.
        ANA     A               ;SET RETURN FLAGS.
        RET                     ;RETURN TO CALLER.

;******************************************************
        .PAGE
        .SBTTL  "LOG-ON DISKETTE"
;******************************************************
; LOG.ON IS THE SUBROUTINE THAT READS THE IDENTITY    *
; SECTOR FROM THE DISKETTE AND MAKES THE NEEDED       *
; ENTRYS INTO THE DRIVE TABLE.  THE SECTOR DATA IS    *
; ALSO LEFT IN THE SECTOR BUFFER FOR BIOS TO FINISH   *
; THE LOG-ON OPERATION.                               *
;******************************************************

;*******( CHECK JADE IDENTITY )************************

LOG.ON: LXI     D,JADEID        ;ID ADDRESS LOADED.
        LXI     H,ID.LBL        ;SECTOR ID ADDRESS.
        MVI     B,ID.SZE        ;ID LABEL SIZE.
..CKJI: LDAX    D               ;GET CHARACTER.
        CMP     M               ;CHECK AGAINST DISK.
        JRNZ    ..3740          ;IF DIFFERENT: 3740.
        INX     D               ;CHECK NEXT.
        INX     H               ;CHECK NEXT.
        DJNZ    ..CKJI          ;REPEAT OPERATION.

;*******( LOG-ON JADE FORMAT )*************************

        LDA     ID.FLG          ;SIDE AND DENSITIES.
        MOV     DV.FLG(X),A     ;STORE IN DRIVE TBL.
        RET                     ;RETURN TO CALLER.

;*******( ASSUME 3740 FORMAT )*************************Š
..3740: MVI     A,ID.FLD        ;SIDE AND DENSITIES.
        MOV     DV.FLG(X),A     ;STORE IN DRIVE TBL.
        RET                     ;RETURN TO CALLER.

;******************************************************
        .PAGE
        .SBTTL  "CHARACTER TRANSMISSION"
;******************************************************
; THE FOLLOWING ROUTINE SENDS ONE 8 BIT CHARACTER OUT *
; THE EIA LEVEL TRANSMISSION BIT.  SET FOR BAUD RATE. *
;******************************************************

;*******( SET UP FOR TRANSMISSION )********************

LST.OT: IN      BL.STS          ;GET BOARD STATUS.
        ANI     BS.EIA          ;TEST LIST READY BIT.
        JZ      LST.OT          ;WAIT READY (JZ/JNZ).
        LDA     CB.CHR          ;GET LIST CHARACTER.
        CMA                     ;COMPLEMENT ACUMULATOR.
        MOV     E,A             ;CHARACTER TO E REG.
        LDA     SV.CTL          ;LAST CONTROLS USED.

;*******( SEND THE START BIT )*************************

        STC                     ;SET CARRY BIT.
        CALL    BIT.OT          ;OUTPUT START BIT.
        NOP                     ;EQUALIZE TIMING.
        NOP                     ;EQUALIZE TIMING.
        MVI     D,8             ;NUMBER OF DATA BITS.

;*******( SEND EACH DATA BIT )*****( 39 CYCLE LOOP )***

..DATA: RRCR    E               ;ROTATE E REG RIGHT.
        CALL    BIT.OT          ;SEND ONE DATA BIT.
        DCR     D               ;ONE LESS BIT TO DO.
        JNZ     ..DATA          ;REPEAT IF MORE BITS.

;*******( SEND STOP BIT )******************************

        NOP                     ;EQUALIZE TIMING.
        ANA     A               ;CLEAR CARRY FLAG.
        CALL    BIT.OT          ;SEND STOP BIT.
        RET                     ;RETURN TO CALLER.

;*******( SET EIA BIT AND OUTPUT )****( 39 CYCLES )****

BIT.OT: JC      ..ONE           ;IF CARRY, SET TO ONE.
        RES     3,A             ;ZERO EIA IN ACUM REG.
        JMP     ..OUT           ;GO TO OUTPUT PORT.
..ONE:  SET     3,A             ;SET EIA IN ACUM.
        JMP     ..OUT           ;EQUALIZE TIMING.
..OUT:  OUT     BL.CTL          ;SEND ACUM TO PORT.

;*******( SET DELAY FOR BAUDRATE )*********************

        MVI     B,BAUD.C        ;LOAD TIMING CSNT.
        DJNZ    .               ;DELAY FOR BIT.
        RET                     ;RETURN TO LST CALL.Š
;******************************************************
        .PAGE
        .SBTTL  "CONSTANTS AND VARIABLES"
;******************************************************
; PROGRAM STORAGE LOACTIONS                           *
;******************************************************

BUF.ST: .WORD   BUF.BG  ;BUFFER STARTING ADDRESS.
ERR.CT: .BYTE   0       ;RETRY ERROR COUNTER.

SV.DRV: .BYTE   0       ;BL.CTL DRIVE BITS.
SV.DAS: .BYTE   0       ;BL.CTL DRIVE AND SIDE BITS.
SV.CTL: .BYTE   0       ;BL.CTL LAST ISSUED.
SV.STS: .BYTE   0       ;FD179X-02 STATUS VALUE.

PH.TRK: .BYTE   0       ;PHYSICAL TRACK NUMBER.

;******************************************************
; TIMING VALUES - 0.1 MS INCREMENTS                   *
;******************************************************

TM.PLD: .WORD   1200    ;PHASE LOCK RECOVERY.
TM.SAW: .WORD   10      ;STEP AFTER WRITING.
TM.SDD  ==      24      ;SIDE SELECT DELAY.

;******************************************************
; DISKETTE IDENTITY LABEL                             *
;******************************************************

JADEID: .ASCII  "Jade DD "      ;DISKETTE ID LABEL.
ID.SZE  ==      (. - JADEID)    ;ID LABEL SIZE.

ID.LBL  ==  BUF.BG+0000H        ;ID SECTOR LABEL.
ID.BLK  ==  ID.LBL+0020H        ;ID BLOCK AREA.
ID.FLG  ==  ID.BLK+0011H        ;DISKETTE FLAGS.
ID.FLD  ==  00000000B           ;3740 FLAGS.

;******************************************************
        .PAGE
        .SBTTL  "DRIVE TABLE"
;******************************************************
; DRIVE TABLE AREA DEFINED                            :
;******************************************************

;*******( DRIVE TABLE ENTRIES )************************

DV.NBR  ==      0       ;CURRENT DRIVE NUMBER.
DV.TRK  ==      1       ;CURRENT TRACK NUMBER.
DV.FLG  ==      2       ;SIDE AND DENSITY FLAGS
DV.CTL  ==      3       ;LAST CONTROLS USED.

;*******( DRIVE TABLE AREA )***************************

DV.TBL  ==      .       ;DRIVE TABLE BEGGINING ADDRESS.Š
DT.DE0: .BYTE   0,255,DF.DFL,0C4H     ;DRIVE 0.
DT.DE1: .BYTE   1,255,DF.DFL,0C5H     ;DRIVE 1.
        .BYTE   2,255,DF.DFL,0C6H     ;DRIVE 2.
        .BYTE   3,255,DF.DFL,0C7H     ;DRIVE 3.
DT.DED: .BYTE   4,255,0,0             ;DUMMY.

DV.DES  ==      DT.DE1-DT.DE0   ;EACH DRIVE ENTRY SIZE.

;*******( FLAG BIT DEFINITIONS )***********************

DF.T1D  ==  00000010B   ;TRACK 1 DENSITY (1 = DOUBLE).
DF.DTD  ==  00000100B   ;DATA TRACKS DENSITY (1 = DD).
DF.TSD  ==  00001000B   ;TWO SIDED ( 1 = TWO SIDES).
DF.DFL  ==  DF.T1D      ;DEFAULT FLAGS.

;******************************************************
        .PAGE
        .SBTTL  "I/O COMMUNICATION BLOCK"
;******************************************************
; THE FOLLOWING AREA IS DEFINED AS THE COMMAND BLOCK. *
; THIS AREA IS RESERVED FOR SPECIFICATION BY THE HOST *
; SYSTEM FOR ALL DISK OPERATIONS.   CONTROLLER STATUS *
; AT COMPLETION OF OPERATION IS PRESENT IN THIS AREA. *
;******************************************************

        .LOC    CMD.BK  ;COMMAND BLOCK.

CB.CMD: .BYTE   0       ;CONTROL COMMAND.
CB.DRV: .BYTE   0       ;DRIVE NUMBER.  
CB.TRK: .BYTE   0       ;LOGICAL TRACK NUMBER.
CB.SEC: .BYTE   0       ;SECTOR NUMBER.
CB.FFG: .BYTE   0       ;FORMAT FLAGS.
CB.CHR: .BYTE   0       ;EIA CHARACTER.
CB.MOD: .BYTE   0       ;MODE SELECTS.
CB.STS: .BYTE   0       ;CONTROLLER STATUS.

CW.LAD: .WORD   0       ;LOAD ADDRESS.
CW.LNG: .WORD   0       ;LOAD LENGTH

;*******( MODE BIT DEFINITIONS )***********************

CM.NRT  ==  10000000B   ;NO RETRYS ( = 1 ).

;*******( STATUS BIT DEFINITIONS )*********************

CS.DNR  ==  10000000B   ;DRIVE NOT READY.
CS.WRP  ==  01000000B   ;WRITE PROTECTED.
CS.BT5  ==  00100000B   ;NOT ASSIGNED.
CS.RNF  ==  00010000B   ;RECORD NOT FOUND.
CS.CRC  ==  00001000B   ;CRC ERROR.
CS.LDE  ==  00000100B   ;LOST DATA ERROR.
CS.HME  ==  00000010B   ;DRIVE HOME ERROR.
CS.TSD  ==  00000001Â   ;TWO SIDES FLAG (FORMAT).
Š;******************************************************
        .PAGE
        .SBTTL  "DCM INITIALIZE"
;******************************************************
; THIS SECTION RESIDES IN THE DCM SECTOR BUFFER. THIS *
; SECTION MOVES DCM FROM BANK 1 DOWN TO BANK 0.   THE *
; C REGISTER IS SET FOR 1791-01 OR 1793-01.  THE LAST *
; OPERATION IS TO  READ THE  BIOS  LOADER  SECTOR  TO *
; OVERLAY THIS INITIALIZATION SEQUENCE.   BIOS LOADER *
; THEN READ BIOS INTO BANK 1 AND HALTS.               *
;******************************************************

;*******( EXECUTES IN BANK 1 )*************************

        .LOC    BUF.BG          ;RESIDES IN BUFFER.
INIT.B: LXI     B,BANK.L        ;SET BANK LENGTH.
        LXI     D,BANK.0        ;SET DESTINATION.
        LXI     H,BANK.1        ;SET SOURCE ADDR.
        LDIR                    ;MOVE BLOCK.
        JMP     ..DOWN          ;JUMP TO NEW IMAGE.

;*******( NOW IN BANK 0, SET INT MODE )****************

..DOWN: LXI     SP,TP.STK       ;SET STACK PNTR.
        IM1                     ;INTERRUPT MODE 1.

;*******( SET 1791-01/1793-01 )************************

        MVI     C,0             ;LOAD C REG ZERO.
        IN      BL.STS          ;BOARD STATUS.
        ANI     BS.US0          ;TEST USER SW #1.
        JRNZ    LD.BLT          ;SW OPEN - 1793.
        MVI     C,0FFH          ;SW CLOSED - 1791.

;*******( OVERLAY WITH BIOS LOADER TRANSIENT )*********

LD.BLT: LXI     X,DT.DED        ;INIT DRIVE TBL.
        MVI     A,2             ;BIOS LOADER SECTOR.
        STA     CB.SEC          ;SET SECTOR VALUE.
        IN      XP.MTX          ;MOTOR TIME EXTEND.
        LXI     H,BUF.BG        ;SET RETURN ADDR.
        PUSH    H               ;PUSH INTO STACK.
        JMP     RD.SEC          ;GET BIOS LOADER.

;******************************************************
        .END
