mkarcher wrote on 2024-06-18, 21:51:Trying to transfer a zero-byte sector should only work if the specified sector (including a size code byte of zero) is actually […]
Show full quote
superfury wrote on 2024-06-18, 18:14:
- Transferring 0 byte sectors actually just uses a timed 'read' from the disk (like READ ID and VERIFY). It's counted as a non-data transfer on the CPU side, like READ ID and VERIFY. Internally it's just a timed like those, executing an empty sector being read (like the sector has been fully read from disk, but within hardware timing itself instead of the CPU reading n bytes using DMA or PIO). If data IS read using DMA/PIO during that, it will perform an abnormal polling error instead.
Trying to transfer a zero-byte sector should only work if the specified sector (including a size code byte of zero) is actually present. So trying to read a zero-byte sector is going to fail ("Sector ID not found") on sectors with a different size code (i.e. 256 bytes or a bigger power of two), or if the sector number exceeds the sectors per track. Furthermore (looking at how real floppy works), it is supposed to yield a CRC error unless the first two bytes following the sector header contain a valid CRC. You might want to ignore the CRC issue in your emulator right now, but you should issue a "Sector ID not found" error if your image has sector sizes exceeding 255 bytes.
superfury wrote on 2024-06-18, 18:14:
- Fixed transferring less than a sector's worth of data to complete for reads. If more is requested to read than is available, it will fail the read with a sector ID not found. Less will succeed, with the sector ID as possible (rounded down now) reporting the size requested.
Transferring more than a sector's worth of data is supposed to work (that is: Not asserting TC (DMA terminal count) after one sector has been transferred. The FDC will happily read as many sectors as required to fulfill the read by just incrementing the sector number, leaving the cylinder number and head number alone. This mode is limited by the sectors per track value that is part of the read command. There is a multi-track mode that should allow the controller to continue reading even after the end of one track, by continuing to the next head(?) or even stepping to the next cylinder(?), but they say this mode doesn't work for some technical reasons in IBM-PC-type systems, so no PC software uses this mode.
As the sector size is part of the ID, issuing a read command with a size code of 1 (256 bytes) will return "sector ID not found" on a standard PC formatted floppy disk consisting of 512-byte sectors. The 765 FDC does not support non-power-of-two sector sizes above 255 bytes, so there should be no need to round anything.
superfury wrote on 2024-06-18, 18:14:
- Writes with non-matching sector size fail always (sector ID not found). The FDC documentation doesn't say anything about writing less than a sector somehow?
Failing writes with non-matching size is correct. Reads need to fail, too, as already stated in this reply. If the sector size code is 0 (0..255 bytes), the write command contains the actual size to write, and let's just hope the space on the disk till the next sector header is sufficient so writing the sector data does not overwrite the next sector header. If a disk has been formatted at 128 bytes per sector, writing 255 bytes will be accepted by the FDC (as the size code is still 0), but writing the extra 127 bytes is likely to overwrite the subsequent sector header and mess up the medium format. As sectors have a CRC appended, you can't update the start of a sector and leave the remaining part of the sector alone, so supplying partial sectors (premature TC) to a write will cause an unreadable sector or the FDC is going to pad up to the required sector size, and append the correct CRC.
The rounding might still be needed though. The backend file formats (dsk, imd, fdi) might support arbitrary sector sizes (imd supporting anywhere from 0 through 64K in byte granularity).
With the latest changes, all sector size fields (both on disk and from commands(or format track data)) are translated to 16-bit byte granularity length.
During reads a comparison is made to verify if it's valid to read (after CHS passes for a sector). The same during writes.
That comparison is simply converting to 16-bit length and if requested<=present it will:
- For reads read the 'present' size and transfer 'requested' bytes.
- For writes read the 'present' size, modify 'requested' bytes and writeback 'present' size (so basically a RMW of 'present' size data from the start of the sector.
- For formats enforce exactly the same 'present' and 'requested', except for IMD disk images (which support fully reformatting tracks with different sector IDs and sizes), taken the sector ID and size from the data phase only (filler from parameter phase though, size field unused).
The 0-case translation from 8-bit 'request' is done the same for read data/track and write data command right now, before the sector IDs are read and parsed into valid sectors depending on backend (IMA(and FDI as a subfunction of that, due to same type but with an extra header to check special cased) vs DSK vs IMD).
After the sector ID (CHS) is found (ignored for read track command), it will check for the 'request' size vs 'present' size.
If 'request'>'present', fail the sector ID and continue to the next sector (spinning emulation on non-IMA/FDI disk images) or (in the case of spinning until reaching the index hole twice while scanning) abort (error out with sector not found (ST1=05h, ST2=01h, ST0=01xxxxxxb).
If 'request'<='present', it'll transfer 'request' bytes out of 'present' bytes (as NEC upd765 and 82077AA document), then:
- For read commands, next sector or result phase.
- For write commands, perform RMW on the sector, modifying 'request' out of 'present' bytes, then next sector or result phase.
So what is it? Modify(write using RMW) or read part (for reads) or force exact match for reads and/or writes only? Documentation says read part always, but write (on 82077AA documentation, NEC upd765 documents roughly 'same as read track') doesn't say anything other than 'C/H/R/N' match (indicating forcing exact match?)