FreddyV wrote on 2024-09-22, 20:53:
Modify the code of the driver work,
by force slowing IO operations by at least 1/2. Transient made it work by disabling 'rep outs' _and_ inserting dummy read.
Transient wrote on 2024-09-14, 08:09:
In NE2000.ASM, there's write_loop, specifically for 8086/8088 CPU. There's also a separate write_186 for 186 and later CPUs. This 186 code is problematic on my system.
I modified NE2000.ASM to always use write_loop. Additionally, I introduced pause_ inside the loop.
Now my FTP transfer is 100% stable. I get around 9.6 KiB/sec transfer rate download from FTPSRV, which is slow, but uploads are better at 68 KiB/sec.
Transient:
- Can you check if you really need this 'additional pause_ inside the loop'?
- Looks like the hack only took care of write_loop so it makes sense your upload is ok. Try doing the same to read_loop by disabling "rep insw" to see if Download gets faster.
- Can you slow ISA clock in the bios further to lets say 4.7MHz and test original NE2000 binary with that slower ISA clock and cpu cache ON?
FreddyV wrote on 2024-09-22, 20:53:
Also, in case of any I/O error, the PicoMEM disk will fail (as even if data is transfered by RAM, the commands are done via I/O)
https://github.com/search?q=repo%3AFreddyVRet … ts%22&type=code shows nothing else uses 'rep outs'.
FreddyV wrote on 2024-09-22, 20:53:
IOCHRDY driving code is always done at the exact same time, it is well controlled and 100% assembly code, with code in the Cache memory.
In theory (and reading ISA System Architecture) it should be enough. But timings are tricky. Looking at the CPU side, for 486 Intel says https://www.pld.ttu.ee/~prj/486dev.pdf
>The fastest non-burst bus cycle that the Intel486 processor supports is two clocks. These cycles
are called 2-2 cycles because reads and writes take two cycles each. The first “2” refers to reads
and the second “2” to writes. If a wait state needs to be added to the write, the cycle is called “2-
3.”
This is on CPU bus and not ISA bus, but there is distinct difference:
>7.2.7 Write Buffers and I/O Cycles
>...When processing an I/O write instruction
(OUT, OUTS), internal execution stops until the I/O write actually completes on the external bus.
This allows time for the external system to drive an invalidate into the Intel486 processor or to
mask interrupts before the processor continues to the instruction following the write instruction.
Repeated OUTS (REP OUTS) instructions are buffered and the next instruction is not executed
until the REP OUTS finishes executing.
>7.2.7.1 Write Buffers and Recovery Time
>The write buffers, in association with the cache, have certain implications for I/O device recovery
times. Back-to-back write recovery times must be guaranteed by explicitly generating a read cycle to a non-cacheable area in between the writes. Since the Intel486 processor does not buffer
I/O writes, the inserted read does not proceed to the bus until the first write is completed. Then,
the read cycle executes on the external bus. During this time, the I/O device recovers and allows
the next write.
It sounds like when doing single OUTB CPU will:
- perform 2 cycle dummy READ followed by actual 2 cycle WRITE
- actually Stop the CPU between IO operations
Meanwhile REP OUTS use write buffers and transfers become back-to-back.
Of course all of this should have no effect on ISA bus, but maybe there is some ISA controller quirk involved here?