Hi,
uglyoldbob wrote:I have noticed that floppy drive detection code (from
http://osdever.net/tutorials/detecting_ ... drives.php) does not work properly on my laptop.
I have a Dell Inspiron B130. I have checked the BIOS options and they make no mention of a floppy drive. But the detection code always says that there is a 3.5" 1.44MB floppy drive present when in fact, there is not one.
I'm not sure about model B130, but other Dell Inspiron models have optional external floppy drives connected via. USB. I would assume that in this case the BIOS's disk services (Int 0x13) pretends a normally floppy drive is present for backwards compatability (e.g. for DOS), and modern OSs (Linux, Windows) detect the optional/external floppy when they scan USB.
For my old floppy driver, after detecting that the floppy drive controller is present and resetting it I sent a "recalibrate" command to each device and assumed that the device wasn't present if it failed to recalibrate (the recalibrate command doesn't work if there is no floppy drive, but does work if there is a floppy drive, even if there's no disk in the drive).
AFAIK it's impossible to properly detect the floppy drive type (3.5 inch or 5.25 inch, and maximum capacity) using manual probing. I've never really trusted the BIOS, as the BIOS can't detect what sort of disk drive is present either - usually it just reports whatever the user felt like telling the BIOS (and it will never mention devices connected to a second, third or fourth floppy driver controller).
There's also a related problem - detecting what sort of media is in a disk drive. For example, if you know the floppy drive is a 3.5 inch that supports 1.44 MB floppies, the you stilll don't know if the actual disk is a 720 KB disk, a 1440 KB disk or a 1680 KB disk (or any other non-standard format). One way around this problem is to rely on the "BIOS Parameter Block" that DOS/Windows use, but IMHO the BPB is a hack (it isn't necessarily present and can't represent unusual disk formats).
To get around both of these problems, my driver didn't care what sort of disk drive is present and did it's own probing to autodetect the media (without relying on the BPB).
Not really knowing what sort of disk drive is present didn't really matter much. If the user is formatting a new disk, then they need to specify which format the disk should be formatted as. For example, if the device driver knew it was a 1.44 MB drive it still wouldn't know if the user wants to format the disk as a 720 KB disk, a 1440 KB disk or a 1680 KB disk. If the user tries to format a disk that the hardware couldn't support (e.g. trying to use the 1440 KB format with a 5.25 inch 1.2 MB drive) then it'd probably fail to format correctly, but that's not my problem..
So, the only question left is how to detect what sort of disk media is present without caring what sort of disk drive is present. This is actually easier than it sounds...
The first thing to do is try to guess the data rate. To do this, first recalibrate the drive, then use the "read ID" command (with "head = 0") and try 500 Kbps, then 300 Kbps, then 250 Kbps. If the command is successful you'll know the data rate is correct. If none of the data rates work then you can assume there's no disk in the drive.
Next, for some disk controllers/drives bit 3 in status register 3 can be used to determine if the disk is double sided (bit set) or single-sided (bit clear). If the disk controller/drive doesn't support this then the bit will be set regardless, so if the bit is set you'd try a "read ID" command with "head = 1" and then compare sector ID information returned in the results phase to make sure. If the command fails it's a single sided disk and if the information returned says "head 0" it's a single sided disk, otherwise you've confirmed that it is a double-sided disk. Note: status register 3 also contains the "write-protected" status flag so it's good to grab that too.
Now you can use the information you've obtained as a filter in a "disk format database". The disk format database is sorted in order from largest capacity to lowest capacity. The database might go something like this:
Code: Select all
;Syntax: label, data rate, sides, sectors, cylinders, formatGap, totalSize
MEDIA media1680K, RATE_500, 2, 21, 80, 0x0C, 0x1C, 1720320
MEDIA media1440K, RATE_500, 2, 18, 80, 0x1B, 0x54, 1474560
MEDIA media1200K, RATE_500, 2, 15, 80, 0x2A, 0x50, 1228800
MEDIA media720K, RATE_250, 2, 9, 80, 0x1B, 0x54, 737280
MEDIA media360K, RATE_300, 2, 9, 40, 0x2A, 0x50, 368640
MEDIA media320K, RATE_250, 2, 8, 40, 0x2A, 0x50, 327680
MEDIA media180K, RATE_300, 1, 9, 40, 0x2A, 0x50, 184320
MEDIA media160K, RATE_250, 1, 8, 40, 0x2A, 0x50, 163840
Starting from the first entry, you'd attempt to read from the last possible sector (e.g. try cylinder 79, head 1, sector 18 for the 1440 KB format) while skipping impossible formats (e.g. if you know the disk uses the 500 Kbps data rate and is double sided, you can skip most of the formats). As soon as you can successfully read the test sector you know the disk format.
The interesting thing is that you'd support unusual combinations accidentally. For example, you'd support the 1200 KB format in 3.5 inch disk drives and the 720K format in a 5.25 inch drive. This might (potentially) cause problems with gap lengths, but in practice there's lots of built-in tolerance in these formats (except the 1680 KB format, which takes advantage of this built-in tolerance).
Cheers,
Brendan