Recently I had an occasion to find out why NetWare 3.12 using the shipped IDE driver (IDE.DSK) behaves, very, very strangely when let loose on disks bigger than about 500MB (a very foolish thing to even try). The driver loaded fine, discovered a 1GB disk fine, but when accessing it, it was extremely slow and produced a lot of errors.
After some debugging and disassembling IDE.DSK, the cause became obvious, but the chain of events that led to it was anything but.
The IDE.DSK driver in NetWare 3.12 dates from April 1993, meaning it’s older than the original ATA specification. The driver notably does not use LBA, because it was not yet standardized at the time; disks with LBA were perhaps just coming on the market, and they were generally not big enough to require LBA. Crucially, there were also no translating BIOSes yet.
The symptoms of the problem initially didn’t seem to make much sense. After working correctly for a short moment, NetWare would select non-existent device 1 (slave) on an IDE channel with only device 0 (master) present. Then it would read the alternate status register, get rather confused, and start endlessly re-calibrating and resetting the drive. In other words, completely unusable. So why would NetWare do such a thing?
The problem has to do with the dreaded geometry translation. Internally, NetWare uses logical block numbers like any sane OS. But the IDE.DSK driver needs to translate those into a CHS (Cylinder/Head/Sector) address that the IDE controller can use.
NetWare appears to query the disk geometry from the partition table if it can, or from the FDPT. If geometry translation is in use, IDE.DSK may end up with a translated CHS which is not suitable for programming into the IDE controller.
The way IDE.DSK translates from internal LBA to CHS is quite straightforward: Divide the LBA by sectors per track. The remainder plus one is written to the Sector Address register. The dividend is divided again by the number of heads. The resulting remainder is written into the Drive/head register, and the dividend is written to the Cylinder Low and High registers.
Now, the Drive/head register is laid out such that the low four bits contain the head number, and the next bit is the device select register. IDE.DSK was clearly written with the assumption that the head number must be in the 0-15 range and the remainder result cannot overflow four bits. Except when the geometry is obtained from the BIOS or the partition table, it can overflow, because the translated geometry the BIOS uses can have up to 255 heads.
And when the head number does overflow, it’s simply ORed with the high four bits of the Drive/head register. Which means that if NetWare is using drive 0 but the calculated head number is 16, the drive select bit will be set to 1. And that will confuse things quite a lot, because NetWare will end up reading the status register from the wrong (or non-existent) drive, and things just won’t go according to plan.
Needless to say, when the IDE drive size is under 500MB and physical geometry matches logical, there are no problems at all. NetWare can also handle big disks with lots of cylinders as long as the number of heads and sectors per track matches the BIOS translation.
Since NetWare 3.x (and 4.x, though not 2.x) typically boots from small DOS partition, the boot partition can easily fit well below 1024 cylinders, addressable by the BIOS. With sufficient care, old NetWare can handle disks within IDE CHS addressing limits (about 8GB).
There are hints, including the EDD 1.1 specification, that some version of NetWare’s disk drivers rely on the FDPT matching the physical drive geometry. It’s quite possible that drives not controlled by the BIOS would pose no difficulties, but boot drives do. Hale Landis suggests that a ‘Type 2 BIOS’ limits cylinders to < 1024 while exposing the true cylinder count in the FDPT (and explicitly mentions Novell).
As usual, the problem with such information is that it talks about “NetWare” or “Novell” as if there was just a single NetWare IDE driver implementation; in reality, Novell’s IDE drivers evolved, and newer versions (which can still be installed even in NetWare 3.x) handle much bigger drives just fine.
As for the head number overflowing into the drive select bit… that’s a pretty classic sleeper bug. The code is incorrect, but when it was written the assumption was that the number of heads of an IDE drive must always be less than 16. And at the time, that was true. Only after the driver was released, the landscape shifted such that the assumption was no longer correct.
Update: Novell documentation (NetWare 3.12 README.UPG) indicates that the 1993 versions of IDE.DSK read the boot sector and if a DOS partition is found, geometry from BIOS/CMOS is used. If no recognizable partitions are found, geometry from the disk (IDENTIFY DEVICE) is used. That is not crazy but may cause surprises.