Hi,
IMHO the tutorial is very good - I've just got a few notes...
mystran wrote:The important thing here is that DMA controls how much data we transfer. Bochs happens to be kind enough to not report an error if you run into the end of track before DMA says it's time to stop, but real hardware will (at least mine does). We'll get to the DMA details (which several sources actually get wrong) later.
AFAIK the EOT value (End Of Track) can also be used to control how much data is transfered. For example, you can read sector 3 with EOT set to 3 and you'd only get one sector.
It may be worth mentioning that the floppy hardware, etc doesn't really care much about sector numbers. Each sector on the floppy begins with some control data that includes a sector number, and when you ask to read sector N the floppy drive will read the first sector that has N as it's sector number in the sector's control data.
This means that sector numbers don't need to begin with 1 and don't even need to be sequential. If you want to format a disk where sectors are numbered from 33 to 50 then that'll work fine. If you want to format a disk where sectors are numbered non-sequentially (e.g. 2, 3, 5, 7, 11, 13, 17, ...) then that can work too. For non-sequential sector numbers you won't be able to read more than one sector per transfer, as the hardware does "next_sector_number = last_sector_number + 1".
Also each track on the disk can be formatted in a completely different way, and sectors don't necessarily need to be 512 bytes long. AFAIK this includes changing the data rate between tracks, and the number of sectors per track, the bytes per sector, sector numbering, etc.
Usually it doesn't make sense to use unusual disk formats because other OSs wouldn't be able to read them. However if you want to make sure another OS can't read your disks it can be a good idea - it wasn't that uncommon for non-sequential sector numbers to be used for copy protection in old DOS software (where you couldn't copy the disk with standard software because standard software expected sequential sectors).
There is another purpose for all of this - increased disk capacities. For floppies there's an "intersector gap" and control data that's used by the hardware to determine where one sector ends and another starts. Larger sectors means less gaps and less control data, and can mean less wasted space on the disk and higher capacities. Also you can format the disk with smaller "intersector gaps" - this isn't that unusual either (there's a 1680 KB floppy format that reduces the intersector gap to make space for 21 sectors per track on a standard 1440 KB floppy).
It may be possible (I haven't tried it or done the calculations, but it seems likely) to format a floppy with three 4 KB sectors per track, giving 1920 KB on a standard 1440 KB disk.
Because each track can be formatted differently, it would also be possible to use 18 (512 byte) sectors for the first cylinder so that DOS/Windows could read the first sector. This way you could set values in the BPB to tell DOS/Windows that the floppy only has one track, and format the remaining tracks any way you like. For example, you could use 18 (512 byte) sectors on the first cylinder and three 4 KB sectors per track for the other 79 cylinders and end up with a 1914 KB floppy that doesn't cause problems on DOS/Windows. Of course DOS/Windows won't be able to read more than 18 KB (which can be a good thing).
mystran wrote:What is covered:
I would be tempted to include some information on detecting what media is in the drive and if it's write protected or not. For example, for a disk drive that supports 2880 KB disks you could have a 2800 KB disk, a 1440 KB disk, a 720 KB disk, a 360 KB disk, a "custom" format disk, or nothing.
Some information is returned in "status register 3" which is returned by the "sense drive status" command. This is mostly used to determine if the floppy is write protected or not (it also includes a "two side" flag but I doubt that it's very useful - a 1440 KB floppy could be formatted as a single sided 360 KB disk regardless of what the hardware is or says).
First you'd find the data rate using trial and error - e.g. try to read sector 0, head 0, track 0 using a 1000 Kbps data rate, then try 500 Kbps, 300 Kbps and 250 Kbps. The first data rate that works without error is the correct data rate. Next try to read read sector 0, head 1, track 0 to see if the disk is double sided or not.
Lastly, you can "probe" for the number of sectors per track. For example, if the data rate is 500 Kbps you could try to read sector 21 (to see if it's a 1680 KB disk) then sector 18 (to see if it's a 1440 KB disk).
For non-standard disk formats, detection is your problem. If you support other sector sizes you could try every (supported) sector size from largest to smallest to see what works without error. AFAIK if you try to read a small sector when a large sector is present it may actually work (i.e. you might successfully read the first 512 bytes of a 1024 byte sector).
DOS/Windows uses a data table in the first sector, called the BPB (or
"BIOS Parameter Block", which AFAIK has nothing to do with the BIOS) to determine the media format. Your OS could use this too, but it doesn't work if the BPB isn't present (possible for non-microsoft format disks). This can causes problems in your low level disk driver that the higher level file system code shouldn't need to care about. The BPB also can't support some non-standard formats (e.g. if you format tracks differently), and I'd consider the BPB to be "Microsoft specific" in that it contains fields that make no sense for other file systems (e.g. number of FATs, sectors per FAT, sectors per "allocation unit"). If you use the BPB and put correct values in there, then DOS/Windows will try to use it and give an error message. If you don't use the BPB then DOS/Windows will assume the disk is unformatted (which IMHO is better for "non-FAT" disks). Of course if you're formatting the disk as FAT then you'd put a BPB in there (but that's a file system issue not a floppy driver issue).
mystran wrote:There can be several floppy controllers, each with up to four drives. On most modern computers you'll find one controller, with one or two drives (=one cable), so whether or not you want to support more controllers is up to you. All of them will normally use the same DMA 8-bit channel (2), and the same IRQ (6). This obviously means that you can only access one drive at any given time.
For some historical information see
this web page. For all (modern - 80386 and later) practical purposes it's no longer possible to have 4 devices on the same floppy controller.
For resources, there is nothing to say additional floppy controllers can't (or won't) use different DMA channels and IRQs. Most ISA "I/O expansion cards" have jumpers that are used to set the I/O ports, DMA and IRQ used by the floppy controller.
mystran wrote:Because the disk rotates the same speed whether you are reading or not, it'll take about the same time to read one sector or the whole track. Well, technically reading a single sector takes on average 37% of the average time to read a full track, or about 20% of the time to read both tracks, assuming the second track starts where the second track ends. So if we end up reading the other sectors as well, we'll waste around 6.6 (single track) or 7.2 times (multi-track) by reading sector at a time.
More accurately, there's an average of half a disk revolution before any read or write, plus the time taken to read/write the data. There's also "intersector gaps", which mean that for 18 sectors per track the time taken to read/write a sector is less than (but not equal to) 1/18ths of a revolution - you don't need to wait for the gap at the end of the last sector. This means reading a single sector costs an average of roughly 55% of a revolution (for 18 sector disks) and reading an entire track costs an average of about 145% of a revolution. For reading an entire cylinder (both heads) you'd have to wait for the gap at the end of the last track and any unused space at the end of the track before you'd see the first sector of the track on side 2. This is a result of the way the "format track" command works (i.e. wait for the index mark, then start creating the first sector of the track). This makes reading a full cylinder (very roughly) equivelent to about 245% of a revolution.
The main benefit of caching entire cylinders is that you eliminate the need for seeks (once a cylinder is in the cache you never need to seek to it again, except for writes which are less common). The other benefit is that it makes it easy to support truly arbitrary transfers (e.g. read 123 bytes starting from the 12345th byte).
mystran wrote:As far as I understand, it doesn't matter much if you set or clear the "skip deleted" bit. If you don't set it (I don't) the read will fail when it hits a deleted address mark (which you can write with a special command it seems) while if you set it, the sector with such a mark will get skipped. So what are these deleted address marks then? I have no idea, but normal floppies seem to work quite fine whatever the setting is, so I'd guess it's something that's useful for tapes. There would be a READ_TRACK command for reading the whole track, deleted or not, but you can't do that multi-tracked on both heads.
The "skip deleted" flag (and deleted sectors in general) is a method of avoiding bad sectors. For an example, instead of formatting a floppy with 18 sectors per track numbered 1 to 18, you could format it with 18 sectors per track where the first 17 sectors are used (number 1 to 17) and the last is unused (numbered 255 perhaps). When you detect a bad sector (e.g. when you're verifying the data after a write) you could do a "read track" followed by "format track", "write track" and then a "write deleted"; so that the track ends up with the bad sector marked as "deleted" and the last (previously unused) sector is used to make up the difference. In this case the floppy hardware will skip the bad sector and the disk driver can continue using sectors 1 to 17 like normal.
AFAIK the deleted flag isn't actually used by other OSs. This makes it a viable alternative for data hiding (e.g. have a hidden sector marked as "deleted" containing data that only your OS knows about).
Cheers,
Brendan