You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1275 lines
39 KiB

;::::::::::::::::::::::::::::::::::::::::::::******************************
; Floppy Disk Routines ***** Hardware Dependent *****
; - D-X Designs Pty Ltd P112 - ******************************
;
; 1.3 - 26 Aug 01 - Cleaned up for GPL Release. HFB
; 1.2c- 12 May 97 - Cleaned up source, modified STSIZE Code (again). HFB
; 1.2b- 22 Apr 97 - Changed 5.25" Hi/Lo Speed controls. HFB
; 1.0a- 23 Mar 97 - (test) fixes. HFB
; 1.0 - 13 Aug 96 - Initial Release for P112 from YASMIO. HFB
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Floppy Units are accessed on the P112 using the on-board SMC FDC37C665.
; An optional assembly flag controls whether Polled or DMA-controlled IO is
; used in operation. The DMA mode does not use any Interrupts in this
; preliminary version, but instead polls the INT1* line as Bit 6 on Port C
; of the Z182.
; This software uses the following registers:
; 0DE - Port C, Bit 6=INT1*, Bit 7=INT2* (DRC)
; 090 - Configuration Control Port (CFCNTL)
; 091 - Configuration Data Port (CFDATA)
; The Chip configuration must be altered only to change the polarity on the
; Density signal applied to Pin 2 on the Floppy Connectors. Optional code
; which may be used forces this lead Hi/Lo as required for different formats
; using two bits of Configuration Register #5.
CR5 EQU 5 ; FDC/IDE setups
;Bit 7 6 5 4 3 2 1 0
; | | | | | +-+-+- unused
; | | | +-+------- 00 = Density Normal (tracks Data Rate)
; | | | 01 = (reserved), 10 = Force "1", 11 = Force "0"
; +-+-+----------- unused
; 092 - Drive Control Register (Write Only)
; 7 6 5 4 3 2 1 0
; | | | | | | +-+-- Drive (00=0, 01=1, 10=2, 11=3)
; | | | | | +------ 1 = Normal Opn, 0 = Reset Controller
; | | | | +-------- 1 = Enable DMA Pins, 0 = Disable DRQ,DAK,INT pins
; | | | +---------- 1 = Enable Drive 0 Motor
; | | +------------ 1 = Enable Drive 1 Motor
; | +-------------- 1 = Enable Drive 2 Motor
; +---------------- 1 = Enable Drive 3 Motor
; 093 - (Not Used)
; 094 - Data-Rate Select (Write) / Main Status Register (Read)
; 7 6 5 4 3 2 1 0 (Write)
; 7 6 5 4 3 2 1 0 (Read)
; | | | | +-+-+-+-- Drives Seeking (0=B0 Set, 1=B1 Set,.. 3=B3 Set)
; | | | +---------- 1 = Command In Progress, 0 = Command Ended
; | | +------------ 1 = Non-DMA Execution, 0 = DMA Execution
; | +-------------- 1 = Read, 0 = Write
; +---------------- 1 = Request for Master, 0 = Internal Execution
;
; 095 - Data/Command Register (Read/Write)
; (Byte Writes/Reads)
; 096 - (Not Used)
; 097 - Data Rate Register (Write) / Disk Changed Bit (Read)
; 7 6 5 4 3 2 1 0 (Write)
; | | | | | | +-+-- 00=500 kb/s, RPM/LC Hi, 01=250/300 kb/s (RPM/LC Lo)
; | | | | | | 10=250 kb/s, RPM/LC Lo, 11=1000 kb/s (RPM/LC Hi/Lo)
; +-+-+-+-+-+------ (Not Used)
;
; 7 6 5 4 3 2 1 0 (Read)
; | +-+-+-+-+-+-+-- (Tri-State, used for HD Controller)
; +---------------- 1 = Disk Changed (latched complement of DSKCHG inp)
;
; 0A0 - DMA I/O Select Port (DMA configuration Only)
IF BANKED
COMMON /BANK2/
ELSE
CSEG
ENDIF
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; STMODE (Function 0) - Set the FDC mode for Read/Write operations.
;
; Enter : A = Single-Density Flag (0 = Double Dens, 0FFH = Single Dens)
; Return: Nothing
; Uses : AF All other Registers Preserved/Not Affected
;
; Assumes STSIZE and STSECT called first
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
STMODE: PUSH BC ; Save Regs
PUSH HL
CPL ; Flip Bits so 1=MFM, 0=FM
AND 01000000B ; keep only bit of interest
LD (MODE),A ; Set MT, MF, SK for Commands
LD B,A ; (for later)
LD A,(DRVSIZ)
DEC A ; becomes: 8"=0, 5"=1, 3"=2
LD L,2 ; (prepare for 8")
JR Z,STMOD2 ; ..jump if 8" (same as HD)
DEC L ; Else set to 3/5" Low Speed (1)
LD A,(DRVSPD)
OR A ; Low Speed?
JR Z,STMOD2 ; ..jump if So
INC L ; Else bump to 2 for Hi-Speed
LD A,(DRVSIZ)
SUB 2 ; 5.25" Hi-Density?
JR Z,STMOD2 ; ..jump if So pointing to 8"/5.25"HD
LD L,8+GAP3HD-FM5G3 ; Else Offset to 3.5" HD Gaps
JR STMOD4 ; ..and set SecSize
STMOD2: BIT 6,B ; MFM Set?
JR Z,STMOD3 ; ..jump if Not
SCF ; Else Set Carry if MFM
STMOD3: RL L ; Shift into LSB, Size * 2
ADD HL,HL
ADD HL,HL ; Size * 8, MFM * 4 (only 1 matters)
STMOD4: LD A,(RSZ)
LD (NBYTS),A ; save in Comnd Blk
OR A
PUSH AF
ADD A,L ; Add Sector Size to computation
LD L,A ; and Store
POP AF
LD A,129 ; (Prepare default)
JR Z,STMOD1 ; ..jump if 128-byte Sectors (DTL=128)
XOR A ; Else DTL is 0FFH (0-->FF)
STMOD1: DEC A ; Correct DTL Value
LD (DTL),A ; set
LD A,L ; Xfer index to A
LD HL,FM5G3-8 ; No low speed on 8"
CALL ADDAHL ; Index into gap 3 table
LD A,(HL)
LD (GPL),A ; store Gap Length
POP HL
POP BC
RET
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; STSIZE (Function 1) - Set Drive Size (3.5", 5.25", 8"), Drive Speed
; (High/Low) Capability, and a Boolean flag for whether Motor Control is
; needed by the Drive.
;
; Enter : A = Hi Speed Flag ( 0 = Normal, 0FFH = High Speed Capable)
; D = Motor Flag (0 = No Motor Control, 0FFH = Motor needed)
; E = Drive Size (0 = Hard, 001 = 8", 010 = 5.25", 011 = 3.5")
; Return: Nothing
; Uses : AF All other Registers Preserved/Not Affected
;
; Assumes STHDRV Called Previously. Call before calling STMODE.
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
STSIZE: LD (DRVSPD),A ; Save Drive Speed Flag
OR A ; (set flag, 0=Normal, FF=Hi-Speed/Density)
LD A,E
LD (DRVSIZ),A ; Save Drive Size Byte
LD A,D
LD (FDMOT),A ; Set Drive Motor Needed flag
PUSH DE ; (Save Regs)
LD A,00000000B ; (Preset Hi 500 kbps, 3.5 & 5.25" Rate)
JR NZ,STSIZ2 ; ..jump if Hi-Density/Speed to Set
DEC E
DEC E ; 5.25" (010B -> 00)?
LD A,00000010B ; (Prepare for 250 kbps)
JR NZ,STSIZ2 ; ..jump if Not 5.25" w/Rate Set
PUSH HL
LD A,(HDR) ; Else use a routine from FLOPPY.Z80 to
CALL PHYSCL ; point to Physical Drive Byte (ICFG-xx)
BIT 6,(HL) ; Hi-Density capable?
POP HL
LD A,00000010B ; (Prepare for 250 kbps)
JR Z,STSIZ2 ; ..jump if No
LD A,00000001B ; Else set to 300 kbps (@360 rpm = 250kbps)
STSIZ2: OUT (DRR),A ; Set Rate in FDC Reg
LD D,A ; preserve Rate bits
IN0 A,(1FH) ; Read Cntrl Reg (B7=1 if Hi Speed)
RLA ; Speed to Bit Carry..Turbo?
LD A,(SPEED) ; (Get Processor Rate in MHz)
JR C,STSIZ8 ; ..jump if Turbo for longer delay
SRL A ; Else divide rate by 2
STSIZ8: INC D
DEC D ; 500 kb/s (Hi-Speed) Rate (D=0)?
JR NZ,STSIZ9 ; ..jump if Not
LD A,1 ; Else minimum delay for "High-Speed"
STSIZ9: LD (DLYCNT),A ; save delay count
POP DE
RET
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; STHDRV (Function 2) - Set Head and Drive for Disk Operations.
;
; Enter : A = Unit # in D0-D1, Head in D2
; Return: Nothing
; Uses : AF All other Registers Preserved/Not Affected
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
STHDRV: LD (HDR),A ; Save the Combined Head/Drive Byte
PUSH BC ; Save Regs
LD B,A ; and the HDR byte
SRL A ; Move
SRL A ; Head to B0
LD (HD),A ; and Save
LD A,(ACTIVE) ; Get current Activation Byte
IF FDDMA
AND 11111000B ; keep only motors and DMA Bit
ELSE
AND 11110000B ; If Polled, keep only motors
ENDIF
OR B ; add drive bit
POP BC ; Restore Regs
JP ACTIV8 ; ..exit saving new byte and activating FDC
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; STSECT (Function 3) - Set Sector Number, Sector Size and Last Sector #
;
; Enter : A = Physical Sector Number
; D = Sector Size (0=128, 1=256, 2=512, 3=1024)
; E = Last Physical Sector # on Side
; Return: Nothing
; Uses : AF All other Registers Preserved/Not Affected
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
STSECT: LD (SECT),A ; Set Sector Number
LD A,D ; Get sector size
LD (RSZ),A ; save for commands
LD A,E ; Get last sector number
LD (EOT),A ; save in Command Block
RET
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; SPEC (Function 4) - Do a Specify Command, setting Step Rate and Head
; Load/Unload Time. Values are rounded up if not even increments.
;
; Enter : A = Step Rate (in mS; Bit 7 = 1 for 8" drive
; D = Head Unload Time (in mS)
; E = Head Load Time (in mS)
; Return: Nothing
; Uses : AF All other Registers Preserved/Not Affected
;
; Assumes STSIZE called previously to set DRVSPD variable.
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
SPEC: PUSH BC ; Save Regs
PUSH DE
AND 7FH ; Strip 8" Bit from Step Rate
; At 250 kb/s MFM (125 kb/s FM), the times are doubled, so we must
; Divide the delays by two, else leave alone for 500 kb/s
LD B,A ; Save the Step Rate
LD A,(DRVSPD) ; Get Speed (Data Rate)
OR A ; High Speed?
LD A,B ; (restore Step Rate)
JR NZ,SPEC0 ; ..jump if 500 kb/s (High Density)
SRL A ; Divide Step Rate by 2
ADC A,0 ; round Up for partial
SRL D ; Divide Head Unload Time by 2
JR NC,SPEC11 ; ..jump if No Rounding Corr.
INC D
SPEC11: SRL E ; Divide Head Load Time by 2
JR NC,SPEC0 ; ..jump if No Rounding Corr.
INC E ; Else Round
SPEC0: NEG ; Get 2's Complement of Step Rate
AND 0FH ; mask
LD B,A ; (save)
LD A,D ; Get Head Unload Time in mS
ADD A,0FH ; force Rounding up
JR C,SPEC00 ; ..jump if Overflow to Max
AND 0F0H ; Keep Time MOD 16
JR NZ,SPEC3 ; ..jump if Not Zero
SPEC00: LD A,0F0H ; Else go to Maximum allowed
SPEC3: OR B ; Add in Step Rate
RLCA
RLCA
RLCA
RLCA ; Swap Nibbles
LD D,A ; put combined byte back in D
CALL WRDY ; Wait for RQM (hope DIO is Low!), retain Ints
LD A,03H ; Do an FDC Specify Command
OUT (DR),A
CALL WRDY
LD A,D ; first Rate Byte (Step Rate, HUT)
OUT (DR),A
CALL WRDY
LD A,E ; Get Head Load Time
ADD A,A ; Shift rate to B7..1
IF NOT FDDMA ; (Bit 0 = 0 for DMA)
OR 1 ; Insure Non-DMA Operation
ENDIF
OUT (DR),A
POP DE ; Restore Regs
POP BC
RET
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; RECAL (Function 5) - Recalibrate Drive (moves heads to track 0).
;
; Enter : Nothing
; Return: A = 0 if Ok, NZ if Error. Flags reflect A
; Uses : AF All other Registers Preserved/Not Affected
;
; NOTE: BC Must be preserved by this routine.
; Assumes STHDRV, SPEC, STSIZE and STMODE called first.
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
RECAL: LD A,3 ; Give this 3 chances to Home
RECAL1: LD (RETRYS),A
PUSH BC ; Save needed regs
LD BC,2*256+7 ; Two bytes, Recalibrate = 7
PUSH HL
CALL FDCMD ; execute Recalibrate
POP HL
IF NOT FDDMA
CALL FDCDN ; Clear Pending Ints, Wait for Seek Complete
AND 00010000B ; Homed? (B4=1 if No Trk0 found)
ENDIF
POP BC ; (restore regs)
JR Z,RECOK ; ..jump to Store if Ok
LD A,(RETRYS)
DEC A ; Any trys left?
JR NZ,RECAL1 ; ..loop if So
DEC A ; Else set Error Flag (0-->FF)
RET
RECOK: PUSH HL ; Save Regs
CALL IDXTRK ; Point to Current Drive in Track Array
XOR A ; get a Zero
LD (HL),A ; set Drive's Trk to 0
POP HL ; Restore regs
RET ; and return
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; SEEK (Function 6) - Set the Track for disk operations and seek to it.
;
; Enter : A = Desired Track Number
; D = Verify flag (0=No, FF=Yes)
; E = Double-step Flag (E <> 0 for Double-step)
; Return: A = 0, Zero Flag Set (Z) if Ok, A <> 0 Zero Clear (NZ) if Error
; Uses : AF All other Registers Preserved/Not Affected
;
; Assumes STHDRV, SPEC, STSIZE and STMODE are called first.
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
SEEK: LD (TTRK),A ; Save Track to Seek
PUSH HL ; Save Regs used here
PUSH DE
PUSH BC
CALL IDXTRK ; Point to Current Trk for Selected Drive
CP (HL) ; Is desired Track same as last logged?
JR NZ,SEEKNV ; ..jump if Not Same
INC D ; Else Set to No Verify (FF->0)
SEEKNV: LD A,E ; Get Double-step flag
LD (STEP2),A ; ..and save locally
LD A,(MXRTRY) ; Get the maximum Count
SEEK1: LD (RETRYS),A ; save remaining Retry Count
LD A,E
OR A ; Double Step?
LD A,(TTRK) ; Restore Track #
JR Z,SEEK2 ; ..jump if No Double Step
ADD A,A ; Else double Track #
SEEK2: LD (TRK),A ; Save the Track # in Comnd Block
LD BC,3*256+0FH ; (3-byte Seek Command = 0FH)
PUSH HL
CALL FDCMD ; Execute the Seek
POP HL
IF FDDMA
OR A ; Insure flags set
ELSE
CALL FDCDN ; Clear Pending Int, wait for Seek Complete
AND 01000000B ; Set NZ if Abnormal Termination
ENDIF
JR NZ,SEEKER ; ..jump if Error Seeking
INC D ; Are we Verifying (FF -> 0)?
DEC D ; (Correct for Test, 0 -> FF)
CALL NZ,READID ; Read next ID Mark if So
JR Z,SEEKX ; ..exit if Ok
SEEKER: LD A,(RETRYS) ; Else get trys remaining
DEC A ; Any left (80-track could need two)?
JR NZ,SEEK1 ; ..loop to try again if More
DEC A ; Else set Error Flag (0->FF)
SEEKX: LD E,A ; (Save status byte)
LD A,(TTRK)
LD (TRK),A ; Restore "Real" Track Number
JR NZ,SEEKXX ; ..jump if Error
LD (HL),A ; Else update Track in Index
SEEKXX: LD A,E ; Restore Status
OR A ; set flags
POP BC ; Restore Regs
POP DE
POP HL
RET
;.........................................................................
; Actual Read or Write
ACTRW: LD HL,(ACTDMA) ; Get actual DMA Addr
LD A,(RDOP)
OR A ; Read operation?
JR Z,SWRITE ; No, must be Write
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; SREAD (Function 7) - Read a Sector from the Floppy Disk. The Mode,
; Head/Drive, Track, and Sector must have already been set.
;
; Enter : HL --> Read Buffer
; Return: A = 0, Zero Set (Z) if Ok, A <> 0, Zero Clear (NZ) if Error.
; Uses : AF,HL. All other Registers Preserved/Not Affected
;
; Assumes STMODE, STHDRV, STSECT, SPEC and SEEK Called First.
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
SREAD: LD A,0110B ; Load 765 Read Command (06H)
IF FDDMA
PUSH AF ; Save Command
LD A,11001101B ; Set DMA Direction
; |||||||+- ?
; ||||||+-- MOD = Cycle Steal (ignored in I/O)
; ||||++--- Source = I/O (fixed)
; ||++----- Dest = Memory (Auto-Inc)
; ++------- ?
ENDIF
JR RW ; ..and continue below
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; SWRITE (Function 8) - Write a Sector to the Floppy Disk. The Mode,
; Head/Drive, Track, and Sector must have already been set.
;
; Enter : HL --> Write Buffer
; Return: A = 0, Zero Flag Set (Z) if Ok, A <> 0 Zero Clear (NZ) if Errors
; Uses : AF,HL. All other registers Preserved/Not Affected.
; Assumes STMODE, STHDRV, STSECT, SPEC and SEEK Called First.
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
SWRITE: LD A,0101B ; Load 765 Write Command (05H)
IF FDDMA
PUSH AF ; Save Command
LD A,11110001B ; Set DMA Direction
; |||||||+- ?
; ||||||+-- MOD = Cycle Steal (ignored in I/O)
; ||||++--- Source = Memory (Auto-Inc)
; ||++----- Dest = I/O (fixed)
; ++------- ?
RW: OUT0 (DMODE),A ; Set DMA Channel #0 direction
POP AF ; restore Rd/Wr Comnd
ELSE
RW:
ENDIF ;fddma
PUSH BC ; Save Regs
PUSH DE
IF FDDMA
CALL SFDMA ; Set DMA Transfer Regs
LD HL,MODE ; Pt to Mode Flag
OR (HL) ; add to Command
ELSE
LD C,A ; (Save Command)
LD A,(MODE) ; Get Mode Flag
OR C ; add Read/Write Command to Mode Flag
ENDIF ;fddma
LD C,A ; to Reg
LD B,9 ; Read/Write Comnds are 9 bytes
LD A,(TSBSCF) ; Get Special Format Flag
OR A ; Special?
JR NZ,RW0 ; ..jump if Not
LD (HD),A ; Else Side 1 coded with Hd # 0
RW0: LD A,(RSZ) ; Get Sector Size Code
LD (NBYTS),A ; and Set in Comnd Blk
LD A,(EOT) ; Get Last Sctr #
PUSH AF ; (save for Exit)
LD A,(SECT) ; Get Desired Sector #
LD (EOT),A ; make last to Read only one Sector
PUSH HL
CALL FDCMD ; Execute Read/Write
POP HL
POP AF ; Restore Last Sctr #
LD (EOT),A ; to Comnd Blk
LD A,(ST1) ; Get Status Reg 1
AND 34H ; Return Any Error Bits
POP DE ; Restore Regs
POP BC
RET
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; READID (Function 9) - Read the first Valid Address Mark on a track.
;
; Enter : Nothing
; Return: A = 0 if Ok, NZ if Error. Flags reflect A
; Uses : AF All other Registers Preserved/Not Affected
;
; Assumes STHDRV, SPEC, STSIZE and STMODE called first.
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
READID: LD A,(MODE) ; Get Command byte from block
OR 0AH ; or in Command
PUSH BC ; Save regs
LD B,2 ; two bytes in ReadID Command
LD C,A ; move Command to C
PUSH HL
CALL FDCMD ; Activate Controller
POP HL
LD A,(ST1) ; Get Status Reg 1
AND 25H ; Keep only Error Bits
POP BC ; Restore regs
RET ; ..and quit
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; RETDST (Function 10) - Return the status of a drive.
; This routine reports a "765" Controller type instead of actual number.
;
; Enter : Nothing
; Return: A = Status byte
; BC = 765 (FDC Controller Type)
; HL = Address of Status Byte
; Uses : AF,BC,HL All other Registers Preserved/Not Affected
;
; Assumes STHDRV called first
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
RETDST:
IF FDDMA
CALL WRDY ; Wait for RQM to be Set
LD A,0100B ; Load Return Drive Status Command (04H)
OUT0 (DR),A ; send to FDC
CALL WRDY
LD A,(HDR) ; Get Drive and Head
OUT (DR),A ; send it too
CALL FDCIN0 ; Read Stat at Command End
ELSE
LD BC,2*256+04H ; 2-byte Return Drive Status Command
CALL FDCMD
ENDIF ;fddma
LD HL,ST0 ; Point to Status Byte (Reg 3 contents)
LD A,(HL) ; fetch it
LD BC,765 ; load Controller ID
RET
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; FMTTRK (Function 11) - Format a complete track on one side of a Floppy
; Disk. The Mode, Head/Drive, Track, and Sector must have been set.
;
; NOTE: The contents of the Format Data Block varies between controllers,
; so RETDST should be called to determine the controller type before
; setting up data structures.
;
; Enter : D = Formatting Sctrs/Track value
; E = Formatting Gap 3 Byte Count
; HL = Pointer to Controller-dependent Format Data block
; Return: A = 0, Zero Flag Set (Z) if Ok, A <> 0 Zero Clear (NZ) if Errors
; Uses : All Primary Registers
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
FMTTRK: PUSH DE ; Save for Later
IF FDDMA
LD A,11110001B ; Set DMA Direction
; |||||||+- ?
; ||||||+-- MOD = Cycle Steal (ignored in I/O)
; ||||++--- Source = Memory (Auto-Inc)
; ||++----- Dest = I/O (fixed)
; ++------- ?
OUT0 (DMODE),A ; Set DMA Channel #0 direction
LD A,(TPABNK) ; Format Data comes from TPA Bank
IF BANKED
RL H ; Eliminate the MSB of DMA Addr
ADC A,0 ; offset bank # by 32k banks
RRA ; shift Bank LSB to Carry
RR H ; Move Bank # LSB (Carry) to Address MSB
ENDIF ;banked
LD (FDMAB+2),A ; Set the Bank Value
LD (FDMAB),HL ; and DMA Address for Bank in DMA Comnd Block
LD HL,_DMA ; Get DMA IO Port addr
LD (FDMAB+3),HL ; place in DMA Comnd Block
XOR A
LD (FDMAB+5),A ; and Null out rest of Dest
CALL STFDMA ; Set DMA for Format
ELSE ;~fddma
IF BANKED
LD BC,(TPABNK) ; Get Source and Dest Banks
CALL XMOVE ; set them up
ENDIF
LD DE,HSTBUF ; Move the data to Host Buffer
LD BC,256 ; Two Sector's worth should be enough
CALL MOVE ; and move it
POP DE ; Restore SPT (D) and Gap3 (E)
ENDIF ;~fddma
LD A,(MODE)
OR 1101B ; set command to Format
LD C,A ; and place in Reg
LD HL,TRK
LD A,(RSZ)
LD (HL),A ; Place values in Command Block
INC HL
LD (HL),D
INC HL
LD (HL),E
INC HL
LD (HL),0E5H ; Set byte to write as Data
LD B,6 ; Six bytes in Format Command
IF NOT FDDMA
LD HL,HSTBUF
ENDIF
CALL FDCMD ; Execute !
LD A,(ST1) ; Get Status
AND 92H ; Return Error bits in A
RET
;=============================================================================
; FDCMD - Send Command to FDC
; Enter: B = # of Bytes in Command, C = Command Byte
; HL -> Buffer for Read/Write Data (If Needed)
; Exit : AF = Status byte
; Uses : AF,BC
FDCMD: PUSH HL ; save regs
CALL MOTOR ; Insure motors are On
LD HL,COMND ; Point to Command Block
LD (HL),C ; command passed in C
LD C,DR ; Set Data Port Addr
OTLOOP: CALL WRDY ; Wait for RQM (hoping DIO is Low) (No Ints)
OUTI ; Output Command bytes to FDC
JR NZ,OTLOOP ; ..loop til all bytes sent
POP HL ; Restore Transfer Addr
DI ; No Ints during IO to avoid data loss
FDCI1:
IF FDDMA
CALL FDCINT ; "Call" the Interrupt handler instead of Int
RET C ; ..quit if Timeout Error (C, A=FF)
LD A,(ST0) ; Else get first byte of Status
AND 0C0H ; check for Normal termination
RET ; ..return w/Error Flags set
ELSE
CALL WRDY
BIT 5,A ; In Execution Phase?
JR Z,FDCRES ; ..jump if Not to check result
BIT 6,A ; Write?
JR NZ,FDCI2 ; ..jump if Not to Read
OUTI ; Else Write a Byte from (HL) to (C)
JR FDCI1 ; and check for next
FDCI2: INI ; Read a byte from (C) to (HL)
JR FDCI1 ; and check for next
; Enter the Result Phase of the Command. Gather returned bytes
FDCRES: EI ; Interrupts Ok now if in Result Phase
LD HL,ST0 ; Point to Status Result area
ISGO: CALL WRDY
BIT 4,A ; End of Status/Result?
RET Z ; ..return if So
BIT 6,A ; Another byte Ready?
RET Z ; ..return if Not
INI ; Else Read Result/Status Byte
JR ISGO ; ..loop for next
;.....
; Check for Proper Termination of Seek/Recalibrate Actions by
; executing a Check Interrupt Command returning ST0 in A.
FDCDN: PUSH HL ; Don't alter regs
EI ; (Ints Ok Now)
FDCDN0: CALL WRDY ; Ready? (leave Ints alone)
LD A,08H ; Else Issue Sense Interrupt Status Comnd
OUT0 (DR),A
CALL WRDY
IN0 A,(DR) ; Get first Result Byte (ST0)
LD L,A
CP 80H ; Invalid Command?
JR Z,FDCDN0 ; ..jump to exit if So
CALL WRDY
IN0 A,(DR) ; Read Second Result Byte (Trk #)
LD A,L
BIT 5,A ; Command Complete?
JR Z,FDCDN0 ; ..loop if Not
POP HL
RET
ENDIF ;~fddma
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; MOTOR CONTROL. This routine performs final selection of the drive control
; latch and determines if the Motors are already spinning. If they are off
; and Motor control is needed, then the Motors are activated and the spinup
; delay time in tenths-of-seconds is performed before returning.
;
; Enter : Command byte in A
; Return: Head Delay bit set in Command in A if needed
; Uses : None. All Registers Preserved/Not Affected
MOTOR: PUSH AF ; Save Reg
LD A,(FDMOT)
OR A ; Need Motor?
JR Z,MOTORX ; ..jump to exit if Not
LD A,(MOTIM) ; Get remaining seconds
OR A ; Already On?
LD A,(MONTIM) ; (get Default On Time)
LD (MOTIM),A ; always reset
EI ; Insure Ints are Active
JR NZ,MOTORX ; ..exit if Motors On..they will stay On
LD A,(HDR) ; Get current Drive
IF FDDMA
OR 11111100B ; Set All Motors and DMA On, Cntrlr Active
ELSE
OR 11110100B ; Set All Motors On, DMA Off, Cntrlr Active
ENDIF
CALL ACTIV8 ; Do It!
LD A,(SPINUP) ; Get Spinup Time
LD (MTM),A ; to GP Counter
MOTOLP: LD A,(MTM)
OR A ; Up to Speed?
JR NZ,MOTOLP ; ..loop if Not
MOTORX: POP AF ; Restore Reg
RET
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Hardware-Dependent Host Read/Write Routine linked to from FLOPPY module.
; This routine Reads/Writes data from HSTBUF trying up to MXRTRY times
; before giving up. If an error occurs after the next-to-last try, the
; heads are homed to force a re-seek.
;
; Enter: (RDOP Set for desired operation)
; Exit : A = 0, Zero Set if Ok, A <> 0, Zero Reset if Errors
; Uses : AF,HL
;
; RDOP is set to 1 for Read, 0 for Write, TTRK set with desired Track
; number, STHDRV, STSECT, STMODE, SPEC all called previously.
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
FHDRW: LD HL,HSTBUF ; Point to the host buffer
LD (ACTDMA),HL ; and set Memory Pointer
LD (FRWSTK),SP
LD SP,FRWSTK ; Use Local Stack
LD A,(MXRTRY) ; Get the maximum retry count
RWF2: LD (RWRTRY),A
PUSH DE ; (Save Regs)
LD A,(STEP2) ; Get double-Step flag
LD E,A
LD D,0FFH ; (Verify needed)
LD A,(TTRK) ; and track
CALL SEEK ; Try to seek to the desired track
POP DE ; (Restore Regs)
CALL Z,ACTRW ; Call R/W if Seek succeeded
LD (ERFLAG),A ; Save error code in any case
JR Z,FHDRX ; ..jump to return if No Errors
LD A,(RWRTRY) ; Get retry count
CP 2 ; Are we on Next to last try?
CALL Z,RECAL ; Return to Track 0 if so
LD A,(RWRTRY) ; and re-fetch try count
DEC A ; Do we have more retries left?
JR NZ,RWF2 ; ..jump to try again if more tries remain
CALL ERROR ; Else print Error Bios Message
FHDRX: LD SP,(FRWSTK) ; Restore Entry Stack
RET ; and Exit
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Gap 3 Length Table
; Index is: ((Drive_Factor * 8) + (MFM * 4) + RSZ) - 8
; Where Drive_Factor is based on Size and Speed as:
; 5.25"/3.5" Low Speed = 1
; 8" (Speed Ignored) = 2
; 3.5" High-Density Disks use special GAP3 Table, while 5.25" High-
; Density disks use 8" DD GAP3 values.
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; 5.25"/3.5" Single-Density GAP3. 300 rpm, 125 kbps, FM
FM5G3: DEFB 7 ; 128
DEFB 5 ; 256
DEFB 20 ; 512
DEFB 27 ; 1024
; 5.25"/3.5" Double-Density GAP3. 300 rpm, 250 kbps, MFM
DEFB 0 ; 128
DEFB 9 ; 256
DEFB 13 ; 512
DEFB 27 ; 1024
; 8" Single-Density / 5.25" High-Speed GAP3. 360 rpm, 250 kbps, FM
DEFB 7 ; 128
DEFB 5 ; 256
DEFB 27 ; 512
DEFB 27 ; 1024
; 8" Double-Density / 5.25" High-Speed GAP3. 360 rpm, 500 kbps, MFM
GAP5HD: DEFB 0 ; 128
DEFB 15 ; 256
DEFB 11 ; 512
DEFB 17 ; 1024
; 3.5" Hi-Density GAP3. 300 rpm, 500 kbps, MFM
GAP3HD: DEFB 0 ; 128
DEFB 27 ; 256
DEFB 27 ; 512
DEFB 17 ; 1024 (27 if 10 spt)
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Error Printing Routine. This routine prints Error messages from the
; High-level Sector Read/Write routine when detected based on various
; parameters in the BIOS.
; Entering a Control-C after the message will cause a warm boot, anything
; else will ignore the error and return status to the caller.
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ERROR:
IF BIOERM
PUSH BC
PUSH DE
CALL PRINT
DEFB BELL,CR,LF
DEFC 'FDC Error, U'
LD A,(HDR) ; Get unit number
AND 3
CALL PDEC ; ..in decimal
CALL PRINT
DEFC ' '
LD A,(COMND) ; Get the command byte
AND 3FH ; Else Mask Command
CP 0FH ; 765 type Seek?
JR NZ,ERR0 ; ..jump if Not
CALL PRINT
DEFC 'Seek'
JR ERR4
ERR0: CP 05H ; 765 type Write?
JR NZ,ERR1 ; ..jump if Not
CALL PRINT
DEFC 'Wr'
JR ERR4
ERR1: CP 06H ; 765 type Read?
JR NZ,ERR2 ; ..jump if Not
CALL PRINT
DEFC 'Rd'
JR ERR4
ERR2: CALL PRINT
DEFC 'Comnd = '
LD A,(COMND)
CALL PHEX
ERR4: CALL PRINT
DEFC ', '
LD HL,ST0 ; Point to Status Bytes
BIT 7,(HL) ; Abnormal Termination?
JR Z,ERR5
CALL PRINT
DEFC 'AT'
JR ERR13
ERR5: BIT 4,(HL) ; Equipment Check?
JR Z,ERR6
CALL PRINT
DEFC 'EC'
JR ERR13
ERR6: BIT 3,(HL) ; Not Ready?
JR Z,ERR7
CALL PRINT
DEFC 'NR'
JR ERR13
ERR7: INC HL ; Point to ST1
BIT 5,(HL) ; Data Error?
JR Z,ERR8
CALL PRINT
DEFC 'DE'
ERR8: BIT 2,(HL) ; No Data?
JR Z,ERR9
CALL PRINT
DEFC ' ND'
ERR9: BIT 1,(HL) ; Write Protect?
JR Z,ERR10
CALL PRINT
DEFC ' NW'
ERR10: BIT 0,(HL) ; Missing Address Mark?
JR Z,ERR11
CALL PRINT
DEFC ' MA'
ERR11: INC HL ; Point to ST2
BIT 4,(HL) ; Wrong Cylinder?
JR Z,ERR12
CALL PRINT
DEFC ' WC'
ERR12: CALL PRINT
DEFC ' (T='
LD A,(TTRK) ; Get Track (Cyl)
CALL PDEC ; Print cylinder (track)
CALL PRINT
DEFC ' H='
LD A,(HDR)
RRCA
RRCA
AND 0001B
CALL PDEC ; Print head
CALL PRINT
DEFC ' S='
LD A,(SECT)
CALL PDEC ; Print sector
CALL PRINT
DEFC ')'
ERR13: POP DE ; Restore Regs
POP BC
CALL CONIN ; Wait for any key
SUB 3 ; ^C (reboot)?
PUSH AF
CALL PRINT
DEFB CR,LF+80H ; Always echo crlf
POP AF
LD A,0FFH
RET NZ ; ..Return Bad Status if Not user abort
IF BANKED
JP ABORT
ELSE
RST 0 ; Vector thru loc 0 so wboot may be
ENDIF ; Intercepted by NZCOM, BGii, etc.
;.....
; Print value in A as a Decimal number (0-99)
PDEC: LD DE,10 ; We work in decimal
PD0: INC D
SUB E
JR NC,PD0
LD E,A
LD A,D
DEC A ; Is the first digit a Zero?
JR Z,PD1 ; ..jump if so and Don't Print
ADD A,'0'
CALL OUTCHR
PD1: LD A,E
ADD A,'0'+10
JR OUTCHR
;.....
; Print value in A as two Hex digits
PHEX: PUSH AF ; Print value in A as 2 Hex digits
RRCA
RRCA
RRCA
RRCA
CALL PHEX0
POP AF
PHEX0: AND 0FH
ADD A,90H
DAA
ADC A,40H
DAA
;..if Bioerm, fall thru to Outchr..
ELSE
OR 0FFH ; Insure NZ
RET
ENDIF ;Bioerm
OUTCHR: PUSH HL ; Print char in A to Console
PUSH DE
PUSH BC
LD C,A
CALL CONOUT
POP BC
POP DE
POP HL
RET
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Point to Last Track Storage Location for the Current Drive
; Enter: None
; Exit : HL -> Last track storage for this drive
; Uses : HL
IDXTRK: PUSH AF ; Save regs
LD A,(HDR) ; Get current drive/head
AND 0011B ; mask off head
LD HL,TRKARY ; Point to track storage block
CALL ADDAHL ; Point to the byte
POP AF ; restore regs
RET ; and return to caller
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Wait for FDC RQM to become Ready, and return DIO status in Zero Flag
; Pause before reading status port based on CPU Speed and Data Rate.
WRDY: LD A,(DLYCNT) ; Get computed delay count
WRDY0: DEC A ; Done?
JR NZ,WRDY0 ; ..loop if Not
WRDYL: IN A,(MSR) ; Read Main Status Register
BIT 7,A ; Interrupt Present?
RET NZ ; Return if So
JR WRDYL ; Else Loop
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; D M A S U P P O R T R O U T I N E S
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
IF FDDMA
; Set DMA Channel #0 for Format
STFDMA: PUSH AF ; Save regs
XOR A
OUT0 (DSTAT),A ; (No DMA or Interrupts)
LD L,D ; Get SPT value
LD H,0 ; extend to Word value
LD B,2 ; Multiply by 4 for Number of bytes
STDMA2: ADD HL,HL ; * 2
STDMA3: DJNZ STDMA2 ; ..looping til done
LD (FDMAB+6),HL ; Save Number of bytes to transfer
LD HL,FDMAB ; Point to DMA Control block
LD BC,8*256+SAR0L ; 8 bytes from (HL)..
OTIMR ; to DMA Ch #0 Registers
LD A,01100011B ; Enable DMA on Ch #0
; |||||||+- DME
; ||||||+-- ?
; ||||++--- DMA Ints (Ch1, Ch0)
; ||++----- Bit Write En * (Ch1, Ch0)
; ++------- DMA Enable (Ch1, Ch0)
OUT0 (DSTAT),A ; Command!
POP AF ; Restore regs
RET
;.....
; SFDMA - Set up DMA Channel #0 for Read/Write Operation.
; Number of sectors in Reg E is multiplied by Base Sector size to obtain
; the full number of bytes to transfer.
; Enter: HL -> Read/Write Buffer
; A = Read/Write Command
SFDMA: PUSH AF ; Save Rd/Wr Command
XOR A
OUT0 (DSTAT),A ; Disable DMA/DMA Ints
IF BANKED
LD A,(SYSBNK) ; Set System Bank #
ELSE
LD A,(TPABNK) ; If Not Banked, Load TPA Bank #
ENDIF
RL H ; Place Address MSB in Carry
ADC A,0 ; offset Bank # by 32k banks
RRA ; shift Bank LSB to Carry
RR H ; Move Bank # LSB (Carry) to Addr MSB
LD C,A ; Save Bank #
LD DE,_DMA ; Get Floppy DMA IO Port Address
LD B,0 ; and Dummy Bank #
POP AF
PUSH AF ; Restore Rd/Wr Command
AND 00001111B ; keeping only low nibble
CP 0101B ; Write?
JR Z,SFDMA0 ; ..jump if So; CHL = Source, BDE = Dest
EX DE,HL ; Else
LD A,B ; Swap Source
LD B,C ; w/Dest
LD C,A
SFDMA0: LD (FDMAB),HL ; Save Source
LD A,C ; in Block
LD (FDMAB+2),A
LD (FDMAB+3),DE ; and Dest
LD A,B
LD (FDMAB+5),A
LD HL,0080H ; Set 1 Logical Sector Size for Calcs
LD A,(RSZ) ; Get Physical Sector Size (in 128-byte recs)
LD B,A
INC B ; (compensate for first DJNZ)
JR STDMA3 ; ..compute, set and activate
ENDIF ;fddma
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; FDCINT - Used in the P112 as a polled routine in default configuration
; with Interrupts disabled. This code is assembled if the FDDMA equate
; is set TRUE. If your system uses Interrupts, add any additional code
; to save Stack pointer and AF, and insure that it is in the CODE segment.
; NOTE: that the service routine MUST be in the Common Memory if Interrupts
; (instead of polling ) are used to prevent problems when banked.
;
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;;-- CSEG <Place the following in CSEG if "TRUE" Interrupts used>
IF FDDMA
FDCINT: ; Set local stack if Needed, Disable Interrupts for local calls
PUSH BC
PUSH DE
PUSH HL
LD BC,0000 ; Inner loop timeout
LD D,30 ; Outer loop timeout
LD HL,ST0 ; Point to Status Area
Int00: IN0 A,(DRC) ; Read Port C
BIT 6,A ; Int1* active?
JR Z,Int01 ; ..jump if So
DEC BC ; Else count down
LD A,B
OR C
JR NZ,Int00 ; ..loop if Not timed out
DEC D ; Outer loop done?
JR NZ,Int00 ; ..loop if Not
SUB 1 ; Else set Carry, A=FF
LD (ST1),A ; Save Bad Status
CALL FDRst ; Reset the Controller
JR Int0X ; ..and Quit
Int01: LD BC,DR ; Else Point BC to Data Port
CALL WRDYw0
JR C,Int03 ; ..jump if Timeout
Int02: CALL WRDY
BIT 6,A ; Result phase over?
JR Z,Int03 ; ..jump if So to Exit
INI ; Read a byte from (C) to (HL)
INC B ; (correct B for above dec)
JR Int02 ; and check for next
Int03: CALL WRDY
LD A,08H ; Sense Interrupt Status Comnd
OUT (DR),A
CALL WRDY
IN A,(DR) ; Get first Result Byte (ST0)
CP 80H ; Invalid Command?
JR Z,Int0X ; ..jump to exit if So
LD (ST0),A ; Else save Status Byte 0
CALL WRDY
IN A,(DR) ; Read Second Result Byte (Trk #)
JR Int03 ; ..and loop
Int0X: POP HL ; Restore Regs
POP DE
POP BC
; Restore Stack if Needed
EI ; Insure Interrupts are Enabled
RET
;.....
; Alternate entry for code that generates no "Interrupt"
FDCIN0: PUSH BC ; Save regs
PUSH DE
PUSH HL
LD HL,ST0 ; Put Status bytes here
JR Int01 ; ..and continue mainline code
ENDIF ;fddma
; Wait for Interrupt maintaining watchdog timer
WRDYw0: PUSH BC ; Save Regs
LD BC,0 ; Set Maximum count
WRDYw1: IN A,(MSR) ; Get Status
RLA ; Int bit to Carry
JR C,WRDYw2 ; ..quit if Int
DEC BC ; Else count down
LD A,B
OR C ; Timed Out?
JR NZ,WRDYw1 ; ..loop if Not
CALL FDRst ; Else Reset Controller
WRDYw2: CCF ; Set Carry appropriately
POP BC ; restore regs
RET
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CSEG ;*** Remainder of Code MUST be in Main Memory ***
;========================================================================
; Reset the Floppy Disk Controller. Called from CBOOT in case of Hard
; Disk Boot which leaves the controller in a "hung" state, and locally
; if the Controller times out (often due to changing diskettes).
FDRst: PUSH AF ; Save any status
XOR A
OUT (DCR),A ; Place Controller in Reset state
LD A,(ACTIVE) ; get current settings
AND 0FCH ; keep only motors, DMA and Ready
OUT (DCR),A ; and Restore
POP AF ; Restore Status
RET
;========================================================================
; Motor Off routine. Called from TIM-DX and SELFLP2 which forces
; Motors/Timer to be Off state so spinup delay is forced on next selection.
;;ChgSpd: ; <<-- Required label for SELFLP2. Activate
; label here if switching motor speed
MOTOFF: XOR A
LD (MOTIM),A ; Insure Motors Timed Out and show OFF
LD A,(ACTIVE) ; Get current settings
IF FDDMA ;
AND 00001111B ; strip of Motor bits
ELSE
AND 00000111B ; strip off Motor bits and DMA
ENDIF
ACTIV8: OR 00000100B ; (insure FDC out of Reset)
LD (ACTIVE),A ; save
OUT (DCR),A ; and Command!
ChgSpd: RET ; <<-- Activate label here if using 300 kb
; for constant 360 rpm on 5.25" Drives
;======================== RAM Storage Area ==============================
IF BANKED
COMMON /B2RAM/ ; If banked, Local stack in Bank
ELSE
DSEG ; ..otherwise in Data Segment
ENDIF ;
DEFS 30 ; Bios R/W Entry 15-level Local Stack
FRWSTK: DEFS 2 ; Storage for Entry Stack Pointer
DSEG ; Place in Common memory
; Add storage for DMA Control Block if using DMA Transfers
IF FDDMA
FDMAB: DEFS 2 ; Source Addr (16-bits)
DEFS 1 ; Source Bank
DEFS 2 ; Dest Addr (16-bits)
DEFS 1 ; Dest Bank
DEFS 2 ; Byte Count of transfer
ENDIF ;fddma
; NOTE: Variables listed as (** Global **) are accessed by other modules and
; MUST exist as defined.
COMND: DEFS 1 ; Storage for Command in execution
HDR: DEFS 1 ; Head (B2), Drive (B0,1) (** Global **)
TRK: DEFS 1 ; Track (t)
HD: DEFS 1 ; Head # (h)
SECT: DEFS 1 ; Physical Sector Number
NBYTS: DEFS 1 ; Bytes/Sector (n)
EOT: DEFS 1 ; End-of-Track Sect #
GPL: DEFS 1 ; Gap Length
DTL: DEFS 1 ; Data Length
RSZ: DEFS 1 ; Bytes/Sector. Must be placed outside of the
; Comnd Blk for FMTTRK to work.
; FDC Operation Result Storage Area
ST0: DEFS 1 ; Status Byte 0
ST1: DEFS 1 ; Status Byte 1 (can also be PCN)
ST2: DEFS 1 ; Status Byte 2
RC: DEFS 1 ; Track # (** Global **)
RH: DEFS 1 ; Head # (0/1)
RR: DEFS 1 ; Sector # (** Global **)
RN: DEFS 1 ; Sector Size (** Global **)
ACTDMA: DEFS 2 ; 16-bit DMA Address
;-->>> Do NOT re-order the following two bytes !! <<<--
MTM: DEFS 1 ; Floppy Time down-counter
MOTIM: DEFS 1 ; Motor On Time Counter
; DISK Subsystem Variable Storage
FDMOT: DEFS 1 ; Motor on required flag
RDOP: DEFS 1 ; Read/write flag
RETRYS: DEFS 1 ; Number of times to try Opns
RWRTRY: DEFS 1 ; Number of read/write tries
DRVSPD: DEFS 1 ; Drive Speed
DRVSIZ: DEFS 1 ; Drive Size
STEP2: DEFS 1 ; <> 0 for Double Step (** Global **)
MODE: DEFS 1 ; Bit 6 = 1 if MFM, 0 = FM
ACTIVE: DEFS 1 ; Current bits written to Dev Contr Reg (DCR)
DLYCNT: DEFS 1 ; Delay value reading Main Status Reg
FSPT: DEFS 1 ; Format Sectors/Track value
TSBSCF: DEFS 1 ; 0=Hd always 0 (TSBSC) (** Global **)
TTRK: DEFS 1 ; Storage for Track (** Global **)
TRKARY: DEFS 4 ; Track storage locations for four drives
;=========================== End of FDC-DX ==============================