Files
RomWBW/Source/BPBIOS/fdc-dx.z80
2015-08-19 17:34:42 +00:00

1275 lines
39 KiB
Z80 Assembly
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
;::::::::::::::::::::::::::::::::::::::::::::******************************
; 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 ==============================