mirror of
https://github.com/wwarthen/RomWBW.git
synced 2026-02-06 22:43:15 -06:00
416 lines
10 KiB
Z80 Assembly
416 lines
10 KiB
Z80 Assembly
;**************************************************************************
|
||
; DEBLOCK - Disk Deblocking Buffer Routines. (Based on CP/M Example code)
|
||
;
|
||
; 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
|
||
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
|
||
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 =================================
|
||
|