forked from MirrorRepos/RomWBW
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.
419 lines
10 KiB
419 lines
10 KiB
;**************************************************************************
|
|
; 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
|
|
;
|
|
; HSTBUF is always in HBIOS bank where I/O is actually done
|
|
LD A,(HB_BNKBIOS) ; HBIOS bank id
|
|
LD C,A ; Set Read Source Bank
|
|
IF BANKED
|
|
LD A,(DMABNK) ; Read Destination Bank
|
|
ELSE
|
|
LD A,(TPABNK) ; Read Destination Bank
|
|
ENDIF
|
|
LD B,A ; Set Read Destination Bank
|
|
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 HB_XMOVE ; Set source & destination banks
|
|
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 HB_MOVE ; 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 =================================
|
|
|