Files
RomWBW/Source/BPBIOS/deblock.z80
Wayne Warthen 2caeab542c BPBIOS Sync
- Updated BPBIOS based on contributions by Lars Nelson.
2021-10-03 20:00:33 -07:00

417 lines
10 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.
;**************************************************************************
; DEBLOCK - Disk Deblocking Buffer Routines. (Based on CP/M Example code)
;
; 1.1 - 14 Jun 16 - eliminated unnecessary disk accessess WW
; 1.0 - 3 Jul 92 - First General Release. HFB
; 0.0 - 8 Jul 91 - Initial Test Release. HFB
;**************************************************************************
CSEG
;.....
; Set DMA address given by registers B and C
SETDMA:
LD (DMAADR),BC ; Save the address
; CALL PRTSTRD
; DEFB '[SETDMA',']$'
RET
;.....
; Set track given by BC. While the entire word is saved here, only the
; lower byte is used in Floppy, SCSI and RAM Drivers.
SETTRK:
LD (SEKTRK),BC
; CALL PRTSTRD
; DEFB '[SETTRK$'
; CALL PRTHEXWORD
; CALL PRTSTRD
; DEFB ']$'
RET
;.....
; Set sector given by register C. This Sector number is the physical number
; of the desired sector and assumes that SECTRAN has been called. This value
; should reflect the Sector Number returned from SECTRAN. While the entire
; word is saved here, only the lower byte is used in Floppy, SCSI and RAM.
SETSEC:
LD (SEKSEC),BC
; CALL PRTSTRD
; DEFB '[SETSEC$'
; CALL PRTHEXWORD
; CALL PRTSTRD
; DEFB ']$'
RET
;.....
; Home the selected drive
HOME:
; CALL PRTSTRD
; DEFB '[HOME]$'
RET ; Done by SELDSK
;.....
; Flush the host buffer to disk if any writes pending
FLUSH:
; CALL PRTSTRD
; DEFB '[FLUSH]$'
LD A,(HSTWRT) ; Write pending?
OR A
RET Z ; ..quit if nothing pending
IF BANKED
CALL BIOSTK
CALL GOSYSB
ENDIF
JP WRITEHST ; Write host buffer to disk if so
;.....
; Sector blocking and de-blocking routines. Drive numbers used in these
; routines are logical drives.
READ:
; CALL PRTSTRD
; DEFB '[READ]$'
IF BANKED
CALL BIOSTK
CALL GOSYSB
JP JBREAD
COMMON /BANK2/
ENDIF
BREAD: LD A,1 ; Non-zero
LD (READOP),A ; Read operation
INC A ; Treat as un-allocated (=wrual)
LD (WRTYPE),A ; Save it
; JR ALLOC ; Go to common code
JP ALLOC ; Go to common code
CSEG
WRITE:
; PUSH AF
; LD A,C
; CALL PRTSTRD
; DEFB '[WRITE($'
; CALL PRTHEXBYTE
; CALL PRTSTRD
; DEFB ')]$'
; POP AF
IF BANKED
CALL BIOSTK
CALL GOSYSB
JP JBWRT
COMMON /BANK2/
ENDIF
BWRT: XOR A
LD (READOP),A ; Write operation
LD A,C ; Get write type from dos
; CALL PRTHEXBYTE
LD (WRTYPE),A ; Save it
CP WRUAL ; Unallocated write?
JR NZ,CHKUNA ; ..jump if Not. check for unallocated sector
; Write to un-allocated sector, set parameters
; CALL PRTSTRD
; DEFB '[SETPARMS]$'
LD A,(UCOUNT) ; Records/allocation group
; CALL PRTHEXBYTE
LD (UNACNT),A ; Unallocated count
LD HL,SEKDSK ; Selcted disk, track & sector for us
LD DE,UNADSK ; (unadsk=sekdsk)
LD BC,4 ; (unatrk=sektrk)
LDIR ; (unasec=cpmsec)
CHKUNA:
; CALL PRTSTRD
; DEFB '[TP0]$'
LD A,(UNACNT) ; Any unallocated records remaining?
OR A
JR Z,ALLOC ; ..jump if none remain
; CALL PRTSTRD
; DEFB '[TP1]$'
; More unallocated records remain. Check for any change.
DEC A ; Decrement unallocated count
LD (UNACNT),A ; And save it
LD B,4 ; Compare four bytes
LD HL,UNADSK ; Compare Old Disk, Track & Sector
LD DE,SEKDSK ; .to New Disk, Track & Sector
SLP0: LD A,(DE)
; CALL PRTHEXBYTE
CP (HL) ; Same?
; LD A,(HL) ; WW
; CALL PRTHEXBYTE
JR NZ,ALLOC ; ..jump if not
INC HL ; Else advance to next
INC DE
DJNZ SLP0 ; ..and loop til done
; Everything matches, anticipate the next sector
; CALL PRTSTRD
; DEFB '[MATCH]$'
;**********************
DEC HL ; **** WW ****
;**********************
INC (HL) ; Unasec+1
LD A,(CPMSPT) ; Max sectors per track
CP (HL) ; Compare them
JR NZ,NOOVF ; ..jump if not ready for new track yet
; Overflow to next track
LD (HL),0 ; Unasec = 0
LD HL,(UNATRK)
INC HL
LD (UNATRK),HL ; Unatrk+1
; Match found. Pre-read not necessary.
NOOVF: XOR A ; Indicate no pre-read required
JR ALLOC1 ; ..and jump to common code
; Not an unallocated record. Requires pre-read
ALLOC:
; CALL PRTSTRD
; DEFB '[ALLOC]$'
XOR A ; Clear acc
LD (UNACNT),A ; Start over
INC A
ALLOC1: LD (RSFLAG),A ; Force pre-read if a=1
; Read/Write common code
XOR A ; Clear acc
LD (ERFLAG),A ; Start with no errors
LD A,(SEKSEC) ; Get logical sector number
CALL PHYSEC ; Get physical sector
LD (SEKHST),A ; Physical sector (rel 0)
; Check host active
LD HL,HSTACT ; Host active flag
LD A,(HL) ; Get it
LD (HL),1 ; Set it in any case
OR A ; Set flags
JR Z,FILHST ; Flush Host Buffer if needed, then Read
; Host buffer is active. Same as seek buffer?
LD B,3 ; Loop compare of Disk and Track
LD HL,HSTDSK ; Compare Old Logical Disk & Trk
LD DE,SEKDSK ; .to New Logical Disk & Trk
SLP1: LD A,(DE)
CP (HL) ; Same?
JR NZ,FILHST ; ..jump if not same
INC HL ; Else advance to next
INC DE
DJNZ SLP1 ; ..loop til done
; Same track. Same host sector?
LD A,(SEKHST) ; New physical sector
CP (HL)
JR Z,MATCH ; The same
; Not a match.
FILHST: CALL FLUSH ; Empty hstbuf if write pending
; Fill the host buffer if necessary.
LD HL,SEKDSK ; Hstdsk=sekdsk
LD DE,HSTDSK ; Hsttrk=sektrk
LD BC,3
LDIR ; Move it
LD A,(SEKHST) ; Move the Sector too
LD (DE),A
INC DE
INC HL
INC HL ; Skip over logical sector
LD C,4 ; B=0 from above
LDIR ; Set Host DPH and DPB, physical sector
LD A,(RSFLAG) ; Pre-read necessary?
OR A
CALL NZ,READHST ; Read a sector if so.
XOR A ; Clear acc
LD (HSTWRT),A ; Clear write pending flag
; We have a match.
MATCH: LD A,(SECMSK) ; Get the sector mask
LD B,A ; Save it
LD A,(SEKSEC) ; Get new sector
AND B ; Mask off the high bits
RRA
LD H,A ; *128 MSB
LD L,0
RR L ; And LSB
; HL now has relative host buffer address of seksec
IF HBIOS
;
; Modified to use HBIOS host buffer
;
LD A,BID_HB ; HSTBUF is in HBIOS
LD C,A
IF BANKED
LD A,(DMABNK) ; Set Read Destination Bank
ELSE
LD A,(TPABNK) ; Set Read Destination Bank
ENDIF
LD B,A
LD A,(READOP) ; Direction?
OR A
JR NZ,OKBNKS ; ..jump if read
LD A,B ; Else reverse banks
LD B,C
LD C,A
OKBNKS: CALL HBX_XCOPY ; Set source & destination banks
; LD DE,HBBUF ; Host buffer address in HBIOS bank
LD DE,(HB_DSKBUF) ; Host buffer address in HBIOS bank
ADD HL,DE ; Point to the sector
LD DE,(DMAADR) ; User's buffer
LD BC,128 ; Number of bytes to transfer
LD A,(READOP) ; Direction?
OR A ; Set flags
JR NZ,RWMOVE ; ..jump if Read
; Must be Write. Mark and change direction.
INC A ; A = 1
LD (HSTWRT),A ; Set write pending flag
EX DE,HL ; Swap source and destination
; Move the data
RWMOVE: CALL HBX_COPY ; Handle possible inter-bank move
ELSE ; HBIOS
IF BANKED
IF INROM
LD A,(TPABNK) ; If bank in ROM, HSTBUF is in TPA
LD C,A
ELSE
LD A,(SYSBNK) ; If bank in RAM, HSTBUF is in System Bank
LD C,A
ENDIF ;INROM
LD A,(DMABNK) ; Set Read Destination Bank
LD B,A
LD A,(READOP) ; Direction?
OR A
JR NZ,OKBNKS ; ..jump if read
LD A,B ; Else reverse banks
LD B,C
LD C,A
OKBNKS: CALL XMOVE ; Set source & destination banks
ENDIF ;BANKED
LD DE,HSTBUF ; Host buffer address
ADD HL,DE ; Point to the sector
LD DE,(DMAADR) ; User's buffer
LD BC,128 ; Number of bytes to transfer
LD A,(READOP) ; Direction?
OR A ; Set flags
JR NZ,RWMOVE ; ..jump if Read
; Must be Write. Mark and change direction.
INC A ; A = 1
LD (HSTWRT),A ; Set write pending flag
EX DE,HL ; Swap source and destination
; Move the data
RWMOVE: CALL MOVE ; Handle possible inter-bank move
ENDIF ; HBIOS
; Data has been moved
LD A,(WRTYPE)
DEC A ; Directory write? set zero flag
LD A,(ERFLAG) ; In case of error
RET NZ ; ..go home if not a directory write
; This was a Directory Write. Write it now!
OR A ; Check error flag
RET NZ ; ..exit here if any error
LD (HSTWRT),A ; Clear write pending flag
CALL WRITEHST ; Write to disk
LD A,(ERFLAG) ; .Load resulting status
RET ; ..return it to caller
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Blocking/De-blocking variables
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
DSEG ; These variables must ALWAYS be visable, so put here
;.....
; Parameters relating to what we need in the Buffer Next
SEKSEC: DEFS 2 ; New skewed logical sector to seek
; --- The Following Variables MUST be kept in this order ---
SEKDSK: DEFS 1 ; New disk
SEKTRK: DEFS 2 ; New track
CPMSEC: DEFS 2 ; New logical sector
SEKDPB: DEFS 2 ; DPB for host
SEKDPH: DEFS 2 ; DPH for host
SEKHST: DEFS 1 ; New host physical sector to seek
;-----------------------------------------------------------
; Parameters relating to what's in the Buffer Now
; --- The Following Variables MUST be kept in this order ---
HSTDSK: DEFS 1 ; Current disk
HSTTRK: DEFS 2 ; Current track
HSTSEC: DEFS 1 ; Current physical sector
HSTDPB: DEFS 2 ; DPB for host
HSTDPH: DEFS 2 ; DPH for host
HSTACT: DEFS 1 ; Host buffer active flag
HSTWRT: DEFS 1 ; Host buffer write pending flag
;-----------------------------------------------------------
UCOUNT: DEFS 1 ; Number of logical records per alloc block
CPMSPT: DEFS 2 ; Logical sectors per track (byte)
SECSHF: DEFS 1 ; Sector shift factor
SECMSK: DEFS 1 ; Sector mask
DMAADR: DEFS 2 ; User's DMA buffer
IF BANKED AND NOT INROM
COMMON /B2RAM/ ; These values only used internally, bank them!
ENDIF
RSFLAG: DEFS 1 ; Read sector flag 0=skip, 1=read
READOP: DEFS 1 ; Read operation flag 1=read, 0=write
WRTYPE: DEFS 1 ; Write type 0=allocated, 1=dir, 2=unallocated
;.....
; Parameters to track Pre-Read Requirements
; --- The Following Variables MUST be kept in this order ---
UNADSK: DEFS 1 ; Current disk
UNATRK: DEFS 2 ; Current track
UNASEC: DEFS 1 ; Current record
;-----------------------------------------------------------
UNACNT: DEFS 1 ; Unallocated record count
;========================= End of DEBLOCK =================================