From: Will Sowerbutts Date: Sun, 22 Jan 2017 22:38:33 +0000 (+0000) Subject: Kernel: devfd: Optimisations for reliable operation on 6MHz Z80 X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=70b2d2b86260c1cb2f383c5589160e6a4b8c609b;p=FUZIX.git Kernel: devfd: Optimisations for reliable operation on 6MHz Z80 The driver would previously not work below about 10MHz. Tested on zeta-v2 (Z80) at 6MHz, 8MHz, 10MHz, 18.432MHz and 20MHz. Tested on p112 (Z180) at 16MHz. This change also increases the maximum number of times a floppy operation will be retried before we fail it. It also no longer panics on floppy errors. --- diff --git a/Kernel/dev/devfd.c b/Kernel/dev/devfd.c index 7e9d32db..07cbc97c 100644 --- a/Kernel/dev/devfd.c +++ b/Kernel/dev/devfd.c @@ -125,7 +125,7 @@ static int fd_transfer(bool rwflag, uint8_t minor, uint8_t rawflag) if (devfd_error) { kprintf("fd_%s: error %d track %d sector %d\n", rwflag ? "read" : "write", devfd_error, devfd_track, devfd_sector); - panic("fd_transfer"); + goto failout; } if (retc) diff --git a/Kernel/dev/devfd_hw.s b/Kernel/dev/devfd_hw.s index 7db48278..92da6350 100644 --- a/Kernel/dev/devfd_hw.s +++ b/Kernel/dev/devfd_hw.s @@ -3,6 +3,7 @@ ; Copyright (C) 1998 by Harold F. Bower ;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ; 2015-01-17 Will Sowerbutts: Ported to sdas/Fuzix from UZI-180 +; 2017-01-21 Will Sowerbutts: Improvements for reliable operation at 6MHz .module devfd_hw @@ -90,6 +91,9 @@ _devfd_init: LD (motim),A ; Mark Motors as initially OFF LD (hd),A ; and initially Head #0 + LD A, #0x20 ; increase delay time for init + LD (dlyCnt),A + POP HL ; Return Addr POP BC ; minor (in C) PUSH BC ; Keep on Stack for Exit @@ -124,7 +128,7 @@ NoDrv: LD HL,#0xFFFF ; Set Error Status RET ;------------------------------------------------------------- -; This routine Reads/Writes data from buffer trying up to 4 times +; This routine Reads/Writes data from buffer trying up to 15 times ; before giving up. If an error occurs after the next-to-last ; try, the heads are homed to force a re-seek. ; @@ -146,14 +150,10 @@ _devfd_write: PUSH HL LD A,C LD (drive),A ; Save Desired Device -;; CP 4 ; Legal? -;; JR NC,NoDrv ; ..Exit if Error CALL Setup ; Set up subsystem -;;-- LD HL,buffer ; Point to the host buffer -;;-- LD (actDma),HL ; and set Memory Pointer - LD A,#4 ; Get the maximum retry count + LD A,#15 ; Get the maximum retry count Rwf1: LD (rwRtry),A LD D,#0xFF ; (Verify needed) CALL SEEK ; Try to seek to the desired track @@ -174,8 +174,7 @@ SWrite: OR #0x40 ; Set MFM Mode Bit LD A,(sect) ; Get Desired Sector # LD (eot),A ; make last to Read only one Sector -;;-- LD HL,(actDma) ; Get actual DMA Addr - ld hl,(_devfd_buffer) ;;-- + ld hl,(_devfd_buffer) CALL FdCmd ; Execute Read/Write POP AF ; Restore Last Sctr # @@ -551,17 +550,20 @@ FdCmd: PUSH HL ; Save regs (for Exit) PUSH BC PUSH DE - PUSH HL ; save pointer for possible Transfer - CALL Motor ; Ensure motors are On - LD HL,#comnd ; Point to Command Block - LD (HL),C ; command passed in C - LD C,#FDC_DATA ; FDC Data Port + ; rewrite FdCmdXfer code so data flows in the correct direction + LD A,(rdOp) + OR A + LD A,#0xA2 ; Load second byte of INI opcode (doesn't update flags) + JR NZ,FdCiUpd ; ... if read, skip increment + INC A ; ... if write, A=0xA3, second byte of OUTI opcode +FdCiUpd:LD (FdCiR1+1),A ; update second byte of INI/OUTI instruction + + ; is the buffer in user memory? LD A,(_devfd_userbuf) LD D,A ; store userbuf flag in D -OtLoop: CALL WRdy ; Wait for RQM (hoping DIO is Low) (No Ints) - OUTI ; Output Command bytes to FDC - JR NZ,OtLoop ; ..loop til all bytes sent - POP HL ; Restore Possible Transfer Addr + + ; prepare the drive + CALL Motor ; Ensure motors are On CALL FdCmdXfer ; Do the data transfer (using code in _COMMONMEM) @@ -589,15 +591,28 @@ FdCmdXfer: BIT 0,D ; Buffer in user memory? CALL NZ, map_process_always -FdCi1: CALL WRdy - BIT 5,A ; In Execution Phase? - JR Z,FdCmdXferDone ; ... tidy up and return if not - BIT 6,A ; Write? - JR NZ,FdCi2 ; ... jump if Not to Read - OUTI ; Write a Byte from (HL) to (C) - JR FdCi1 ; check for next byte -FdCi2: INI ; Read a byte from (C) to (HL) - JR FdCi1 ; check for next byte + ; send the command (length is in B, command is in C) + PUSH HL ; save pointer for possible Transfer + LD HL,#comnd ; Point to Command Block + LD (HL),C ; command passed in C + LD C,#FDC_DATA ; FDC Data Port +OtLoop: CALL WRdy ; Wait for RQM (hoping DIO is Low) (No Ints) + OUTI ; Output Command bytes to FDC + JR NZ,OtLoop ; ..loop til all bytes sent + POP HL ; Restore Possible Transfer Addr + JR FdCiR2 ; start sampling MSR + +; transfer loop +FdCiR1: INI ; *** THIS INSTRUCTION IS MODIFIED IN PLACE to INI/OUTI + ; INI = ED A2 + ; OUTI = ED A3 +FdCiR2: IN A,(FDC_MSR) ; Read Main Status Register + BIT 7,A + JR Z, FdCiR2 ; loop until interrupt requested +FdCiR3: AND #0x20 ; are we still in the Execution Phase? (1 cycle faster than BIT 5,A but destroys A) + JR NZ, FdCiR1 ; if so, next byte! + +; tidy up and return FdCmdXferDone: BIT 0,D ; Buffer in user memory? RET Z ; done if not @@ -620,6 +635,17 @@ WRdyL: IN A,(FDC_MSR) ; Read Main Status Register dlyCnt: .db (CPU_CLOCK_KHZ/1000) ; Delay to avoid over-sampling status register +; FDC command staging area +comnd: .ds 1 ; Storage for Command in execution +hdr: .ds 1 ; Head (B2), Drive (B0,1) +trk: .ds 1 ; Track (t) +hd: .ds 1 ; Head # (h) +sect: .ds 1 ; Physical Sector Number +rsz: .ds 1 ; Bytes/Sector (n) +eot: .ds 1 ; End-of-Track Sect # +gpl: .ds 1 ; Gap Length +dtl: .ds 1 ; Data Length + ;------------------------------------------------------------ ; DATA MEMORY ;------------------------------------------------------------ @@ -635,16 +661,6 @@ _devfd_buffer: .ds 2 _devfd_userbuf: .ds 1 ; DISK Subsystem Variable Storage -comnd: .ds 1 ; Storage for Command in execution -hdr: .ds 1 ; Head (B2), Drive (B0,1) -trk: .ds 1 ; Track (t) -hd: .ds 1 ; Head # (h) -sect: .ds 1 ; Physical Sector Number -rsz: .ds 1 ; Bytes/Sector (n) -eot: .ds 1 ; End-of-Track Sect # -gpl: .ds 1 ; Gap Length -dtl: .ds 1 ; Data Length - ; FDC Operation Result Storage Area st0: .ds 1 ; Status Byte 0 st1: .ds 1 ; Status Byte 1 (can also be PCN) @@ -655,8 +671,8 @@ st1: .ds 1 ; Status Byte 1 (can also be PCN) .ds 1 ; RN - Sector Size ; -->>> NOTE: Do NOT move these next two variables out of sequence !!! <<<-- -motim: .ds 1 ; Motor On Time Counter -mtm: .ds 1 ; Floppy Spinup Time down-counter +motim: .ds 1 ; Motor On Time Counter <<<-- +mtm: .ds 1 ; Floppy Spinup Time down-counter <<<-- rdOp: .ds 1 ; Read/write flag retrys: .ds 1 ; Number of times to try Opns