Files
RomWBW/Source/BPBIOS/floppy.z80
2015-03-23 01:50:45 +00:00

252 lines
8.1 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.
;**************************************************************************
; Hardware Independent Floppy Drive Routines
;
; This module uses information from HSTDPH/HSTDPB and other HST values to
; access Floppy drives. It establishes physical parameters, performs
; logical to physical mapping of Track/Sector/Head information and links
; to Physical Read/Write routines in module FDC-xx.
;
; 1.4 - 23 Aug 01 - Cleaned up for GPL release. HFB
; 1.3 - 6 Aug 95 - Mod to handle Kaypro4 (Double-sided, continuous
; Sector #s w/Head = 0 on both side's Gap records. HFB
; 7 Jan 95 - Correct calcs for reversed Side 1 (Ken Owen fix) HFB
; 3 Jul 92 - First General Release. HFB
; 8 Jul 91 - Initial test release HFB
;**************************************************************************
IF BANKED
COMMON /BANK2/
ELSE
CSEG
ENDIF
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Read/Write Host Buffer
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Physical Write of "HSTSIZ" bytes from HSTBUF. Return Error Flag in ERFLAG
; and in Registers AF. This routine assumes that parameters are set as:
; HSTDSK = Host Disk #, HSTTRK = Host Track #, HSTSEC = Host Sect #.
FWRITE: XOR A ; Get Write Clear value & RDOP Write Value
LD (HSTWRT),A ; say there is no pending Write
JR FRWHST ; and link with common code below
; Physical Read of "HSTSIZ" bytes from HSTBUF. Return Error Flag in ERFLAG
; and in Registers AF. This routine assumes that parameters are set as:
; HSTDSK = Host Disk #, HSTTRK = Host Track #, HSTSEC = Host Sect #.
FREAD: LD A,1 ; Set Read Value for RDOP
; Linkage to FDC Dependent routines
FRWHST: LD (RDOP),A
CALL FSETHD ; Sort out track, sector, and head
JP FHDRW ; Jump to hardware dependent r/w code
PAGE
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; FSETHD - Routine to set the Head Number, Sector and Track for FDC
; Operation. This routine uses the "HST" values and DPH in order to
; set things up. This routine is Hardware Independent.
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
IF BANKED
COMMON /BANK2/
ELSE
CSEG
ENDIF
FSETHD: LD C,0 ; Set head to 0 for now
LD HL,(HSTDPB) ; Get DPB pointer
DEC HL
LD B,(HL) ; Get # tracks per side
DEC HL ; Point to physical SPT
LD A,(HL)
LD (FDPSPT),A ; Save for FDC
DEC HL
LD A,(HL)
LD (FDSOFF),A ; Save sector offset
LD (FDS1OF),A ; For side 1 also
DEC HL
DEC HL ; Point to format byte 1
BIT 7,(HL)
CALL SETTFZ ; Get high speed flag
LD (FDSPD),A ; Set speed for FDC
LD A,00000111B ; Mask for Sector Size
AND (HL)
LD (FDSECS),A ; Set Sector Size for FDC
DEC HL ; Point to Format Byte 0
BIT 7,(HL) ; Test for Single-Density format
CALL SETTFZ
LD (FDSDEN),A ; Save Single-Density flag
LD A,(HSTTRK) ; Max track is 160
AND A ; Set flags if Track 0
LD E,A ; Put in E
JR NZ,FSETH1 ; If not Track 0 (always side 0)
BIT 6,(HL)
JR Z,FSETH1 ; Test for Track 0 Single-Density
LD A,0FFH
LD (FDSDEN),A ; Set to Single-Density if Trk 0 is SD
INC A
LD (FDSECS),A ; And force 128 byte sectors
FSETH1: LD A,(HSTSEC)
LD D,A ; So stick sector in D
LD A,00111000B ; Mask for Double-Side mode
AND (HL)
JR Z,SETHTS ; Skip if 1-sided
CP 00100000B ; Select Side-by-Sector?
JR C,SBYSEC ; ..jump if Yes
CP 00110000B ; Select by Track LSB?
JR Z,SBYTLS ; ..jump if Yes
CP 00101000B ; Select Side by Track MSB. Is Side 2 Reversed?
JR Z,REVTS2 ; ..jump if Yes
SUB 00010000B ; Select Side by Sector, Cont, Hd always 0?
LD (TSBSCF),A ; 0 if So (Save as flag in FDC-xx)
LD A,E ; Get Track
SUB B ; Is it Side 0?
JR C,SETHTS ; ..jump if Side 0
UPTRK: LD E,A ; Else update Track
UPTRK1: DEC C ; Set Head 1
JR SETHTS ; ..and exit
REVTS2: LD A,E ; Get Track
SUB B ; Is it Side 0?
JR C,SETHTS ; ..jump if so
;; - Change from 2's complement to 1's complement per Ken Owen (Chameleon)
;; NEG ; Make Track negative
CPL ; Make Track Negative (1's complement)
ADD A,B ; Add to Tracks/Side to flip
JR UPTRK ; Update Head and Track, exit
SBYTLS: SRL E ; Divide Track by 2, Carry is Head
JR NC,SETHTS ; ..jump if Head 0
JR UPTRK1 ; Else set to Head 1 and exit
SBYSEC: SUB 00010000B ; Test for Cont Sctr Numbers
CALL SETTFZ ; A=0 if Continuous, FF if Same
LD B,A ; save same Sect # front and back flag
INC HL
INC HL
INC HL
INC HL ; Point to physical SPT
SRL E ; Divide Track by 2 w/LSB going to Carry
JR NC,SETHTS ; ..jump if Head 0 (Even tracks)
DEC C ; Indicate Head 1
INC B ; Test if Sector # Ok
JR Z,SETHTS ; ..jump if Sector Numbers same on both sides
; Else Side 1 continues from Side 0 Sctr #s
LD A,(FDSOFF) ; Get starting Sector for Side 0
ADD A,(HL) ; Add number of sectors on Side 0
LD (FDS1OF),A ; save as first Sector on Side 1
; Track (E), Side(Head in C), and Sector(D) are now sorted out, Command the FDC
SETHTS: LD HL,(HSTDPH)
DEC HL ; Point to Unit ID for drive
LD A,4
AND C ; Mask head
OR (HL) ; Or with unit number
CALL STHDRV ; Set Head and Drive (and HDR variable)
DEC HL
DEC HL ; Point to Drive Type Byte
LD A,DBLSTP
AND (HL) ; Set NZ if Double-Step Enabled
LD (STEP2),A ; save in FDC module
LD A,E ; Get Track #
LD (TTRK),A ; save in FDC module
LD A,(FDS1OF) ; Get sector offset
LD B,A ; Save for later
IF CALCSK
ADD A,D ; Offset the Sector
ELSE
LD A,D ; Get Sector - already offset
ENDIF
PUSH AF ; Save Desired Sector # for more work
LD A,(FDPSPT) ; Get Sectors/Track (SPT)
DEC B ; Adjust SPT to Base 0
ADD A,B ; .add sector Offset
LD E,A ; Save Last Sector number
LD A,(FDSECS) ; Get Sector Size
LD D,A
POP AF ; restore desired Sector #
CALL STSECT ; Set all Sector data
LD A,00000111B
AND (HL) ; Mask for Drive size
LD E,A
BIT 5,(HL) ; Test for motor required
CALL SETTFZ
LD D,A ; Save motor flag
LD A,(FDSPD)
CALL STSIZE ; Let FDC know Speed, Size, and Motor
LD A,(FDSDEN) ; Get SD/DD Mode
CALL STMODE ; set in FDC module
;..fall thru to following and return to caller
; Gather parameters for this physical drive and set FDC module accordingly
DOSPEC: LD A,(HDR) ; Get drive in lower 3 bits
PUSH DE ; save regs needed elsewhere
CALL SPCIFY ; and load registers for Specify command
CALL SPEC ; Set Step, Head Load and Unload times
POP DE
RET
;.....
; Get drive parameters for Specify Command.
; Enter: Drive in bits 0,1
; Exit : A = Step rate & Disk Size (B7=1 for 8", 0 for 5")
; D = Head Unload Time
; E = Head Load Time
SPCIFY: CALL PHYSCL ; Get the physical Block for this drive
LD A,(HL) ; Get drive byte
AND 0111B ; mask for Drive size
DEC A ; set Zero flag if 8"
INC HL ; Advance to Step Rate
LD A,(HL) ; fetch
RES 7,A ; insure MSB clear for 5/3"
JR NZ,SPCIF0 ; Jump if Not 8"
SET 7,A ; else set MSB of Step for 8"
SPCIF0: INC HL
LD E,(HL) ; get HLT
INC HL
LD D,(HL) ; and HUT
RET
;.....
; Index to proper Floppy Configuration bytes. Uses AF,HL.
; Enter with Physical Drive # in Bits 0,1
CSEG ; Must be in Common Memory
PHYSCL: AND 0011B ; Mask out all but drive bits
LD L,A ; save copy for *5 calc
ADD A,A ; Calc table index *2
ADD A,A ; *4
ADD A,L ; *5
LD HL,FDCSPEC ; Set table base addr
;..fall thru to..
; Routine to Add A to HL
ADDAHL: ADD A,L ; Add A to LSB
LD L,A
RET NC ; Exit if no H adjustment
INC H ; Else had Carry, so add 1 to MSB
RET ; And exit
IF BANKED AND NOT INROM
COMMON /B2RAM/
ELSE
DSEG
ENDIF
FDSECS: DEFS 1 ; FDC sector size 0=128,1=256,2=512,3=1024
FDSDEN: DEFS 1 ; FDC single density flag
FDSPD: DEFS 1 ; FDC high speed flag
FDPSPT: DEFS 1 ; FDC physical Sectors/Track
FDSOFF: DEFS 1 ; FDC first sector number offset side 0
FDS1OF: DEFS 1 ; FDC first sector number offset side 1
sbscflg: DEFS 1 ; Flag for SBSC operation
;=========================== End of FLOPPY ================================