;************************************************************************** ; 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 A,(HBX_BNKBIOS) ; 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 =================================