BPBIOS Errata

File: deblock.z80 @ SLP0:

When attempting to increment the sector number for sequential unallocated write matching, HL was pointing one byte past the sector number byte when it was intended to point at the sector number byte.  Added a DEC HL to make it point to the right place.  Without this fix, there will be far more disk writes than desired, but no data corruption as far as I can tell.

; 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)
	CP	(HL)		; Same?
	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

	DEC	HL		; WBW: point back to sector num
	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

File: hardide.z80 & hard-dx.z80 @ HDWRIT:

HSTACT was being reset instead of HSTWRT at every disk write call.  Makes no sense and was causing many extra writes.  Switched to HSTWRT which is what the floppy driver does.

;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Write to Hard Disk Drive			< Internal BIOS Routine >
;  Writes from HSTBUF using HSTTRK and HSTSEC to build Block Number.
; NOTE: This routine uses physical drive characteristics from ICFG-xx.

HDWRIT:	XOR	A
;WBW	LD	(HSTACT),A	; Show no active writes pending
	LD	(HSTWRT),A	; WBW: Show no active writes pending

	LD	HL,7CH*256+CMDWR ; Set the IDE Write Command
	JR	HDRW		; ..continue

selrwd.z80 @ SELDK0:

It appears that if a disk is selected (SELDSK) and is not a new disk login, then, the driver select processing is being bypassed.  Does not make sense to me, but not causing any harm that I can see at this point.

No code fix created yet.

fdc-dx.z80 @ FDCDN:

At high clock speeds (>~24MHz) the seek/recal command wait for completion needs to make sure the prior command is not still active.

;.....
; Check for Proper Termination of Seek/Recalibrate Actions by
;  executing a Check Interrupt Command returning ST0 in A.

FDCDN:  PUSH    HL		; Don't alter regs
        EI				;  (Ints Ok Now)
FDCDN0: CALL    WRDY		; Ready? (leave Ints alone)
        BIT     4,A		; WBW: Prior command still active?
        JR      NZ,FDCDN0	; WBW: If so, keep checking
        LD      A,08H		; Else Issue Sense Interrupt Status Comnd
        OUT0    (DR),A
        CALL    WRDY
        IN0     A,(DR)		; Get first Result Byte (ST0)
        LD      L,A
        CP      80H		; Invalid Command?
        JR      Z,FDCDN0	; ..jump to exit if So
        CALL    WRDY
        IN0     A,(DR)		; Read Second Result Byte (Trk #)
        LD      A,L
        BIT     5,A		; Command Complete?
        JR      Z,FDCDN0	; ..loop if Not
        POP     HL
        RET
          ENDIF         ;~fddma

fdc-dx.z80 @ WRDY:

At high clock speeds (>~24MHz), a small delay is needed between MSR register reads.

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Wait for FDC RQM to become Ready, and return DIO status in Zero Flag
; Pause before reading status port based on CPU Speed and Data Rate.

WRDY:   LD      A,(DLYCNT	; Get computed delay count
WRDY0:  DEC     A			;  Done?
        JR      NZ,WRDY0	; ..loop if Not
WRDYL:  IN      A,(MSR		; Read Main Status Register
        BIT     7,A		; Interrupt Present?
        NOP				; WBW: Reg recovery for hi speed op
        RET     NZ		;  Return if So
        JR      WRDYL		;   Else Loop

fdc-dx.z80 @ FDRst:

At high clock speeds (>~24MHz), an additional delay is needed to make sure that the reset minimum timing is met.  The code fix below seems to work, but it wold be better to implement a loop based on clock speed.

========================================================================
; Reset the Floppy Disk Controller.  Called from CBOOT in case of Hard
; Disk Boot which leaves the controller in a "hung" state, and locally
; if the Controller times out (often due to changing diskettes).

FDRst:  PUSH    AF		; Save any status
        XOR     A
        OUT     (DCR),A		; Place Controller in Reset state
        EX      (SP),HL		; WBW: Delay required at high speed
        EX      (SP),HL		; WBW: ... to ensure reset works
        LD      A,(ACTIVE	;  get current settings
        AND     0FCH		;   keep only motors, DMA and Ready
        OUT     (DCR),A		;  and Restore
        POP     AF		; Restore Status
        RET

fdc-dx.z80 @ FDCINT:

At high clock speeds, the FDC interrupt polling loop is insufficient.  Assuming the original value of 30 is optimal for 16MHz and assuming we want to handle up to 50MHz now, a reasonable new value is 90.

	LD	BC,0000		; Inner loop timeout
;	LD	D,30			;  Outer loop timeout
	LD	D,90			;  Outer loop timeout
	LD	HL,ST0		;   Point to Status Area