After digging through BIOS listings and disassembling the Adaptec 1542C BIOS as well as the PC DOS 2000 boot sector, it’s clear why the floppy-less SCSI boot does not work on my test system. It’s because disk reset done by the boot sector (INT 13h/00h) fails when booting off SCSI. But the details are… interesting.
The root of the problem is that the INT 13h/00h service (Reset Disk System) behaves in a rather unexpected and to some extent very surprising manner. For reasons that aren’t obvious, resetting a fixed disk (BIOS drive 80h) also resets the floppy subsystem. And for that reason, the Adaptec 1542C BIOS, which hooks the INT 13h vector, has a relatively complicated disk reset logic (see below).
At a quick glance, MS-DOS 6.22 should behave exactly like PC DOS 2000 in this regard. It executes the same INT 13h/00h call with DL holding the boot drive number.
Adaptec Logic
If the drive number passed in DL register is less than 80h, the Adaptec BIOS checks whether the equipment byte at 40:10 has bit zero set. That bit indicates whether a bootable floppy drive is present. When the bit is not set, the Adaptec BIOS simply returns success. When the bit is set, Adaptec’s BIOS execute INT 40h (that is the re-vectored floppy BIOS entry point) and immediately returns with whatever status INT 40h produced.
If the drive passed in DL is 80h or higher, it gets more complicated. The 1542C BIOS then checks whether it controls drive 80h (the first hard disk, typically the boot drive). If it doesn’t, it executes the old INT 13h vector (which was in place before the 1542C was initialized) and returns, although there’s a bit of trickery with the byte at 40:75 to hide the presence of the Adaptec-controlled SCSI disk from the chained BIOS.
Note that the above case works well and the system boots fine.
The troublesome case is with 1542C controlling drive 80h. In that case, the Adaptec BIOS again checks bit 0 of the equipment byte at 40:10; and again if the bit is set, executes INT 40h and returns, and if not, simply returns success. Note that there is nothing whatsoever done to reset the SCSI drive because the concept does not really apply, and there is also nothing done to reset any other hard disks which might be present.
The above described logic sounds perfectly sensible, yet it does not work. The trouble is that the system BIOS does set bit 0 of the equipment byte, indicating a boot floppy even when there is no floppy drive configured. That causes the floppy disk reset to fail if there is also no floppy controller.
Okay, resetting a non-existent floppy drive sounds like it ought to fail, so why does it work without the Adaptec?
IBM Logic
The canonical implementation is the IBM PC/AT. And its logic is rather different. When the PC/AT fixed disk BIOS service processes the reset function, it likewise checks if the drive passed in DL register is 80h or higher. If not, it executes INT 40h and returns, including the status code in AH and flags in the state INT 40h left them in.
That is almost the same as the 1542C BIOS. Note that the IBM hard disk BIOS does not check the equipment byte. It leaves up to the floppy BIOS to decide what to do or not do, which seems to be sound logic.
If the drive number is 80h or higher, the PC/AT BIOS first executes INT 40h and clears the status code in AH. Then it gets interesting. If the drive number in DL is 82h or higher (more than the maximum of two fixed disks supported by the PC/AT BIOS), the routine returns to caller. Note that in this case, the floppy drive is reset but INT 13h always returns success.
If DL is 80 or 81h, the fixed disk is actually reset and the status of the fixed disk reset operation is returned.
The Difference
It’s apparent what the difference is. With actual IBM PC/AT BIOS (and my board’s clone BIOS), executing INT 13h/00h with 80h in register DL can never fail because of the floppy subsystem, only because of a fixed disk failure. With the Adaptec 1542C BIOS, it can fail—but only when the 1542C controls drive 80h.
The logic in the Adaptec BIOS checking the equipment byte is questionable. It makes potentially unwarranted assumptions about the relationship of the bit to the floppy BIOS behavior. At any rate, the real problem is that the Adaptec BIOS returns the status of the floppy subsystem reset to the caller in cases where the original IBM BIOS does not. That can (and does) cause visible behavioral differences.
Another problem is that my board’s BIOS leaves the bit 0 in the equipment byte set even when no floppy drives are configured. That is likely a bug. Yet another unexpected behavior is that the floppy disk reset still succeeds with no drives configured as long as there is a FDC, but not without.
It is fairly obvious that back in the early 1990s, machines without floppy drives were exceedingly rare and firmware vendors did not test the behavior of floppy-less systems. The problem also illustrates that alternative BIOS vendors need to very carefully consider the behavior of the original and stick to it as much as possible. It is also apparent that the IBM BIOS authors probably did not consider all edge cases.
The behavior of INT 13h/00h is quite odd to say the least. It is also very questionable what the value of the boot sector resetting any disk might be when booting from hard disk. By the time the DOS boot sector is loaded, the MBR already had to be successfully loaded and executed, hence resetting the disk is unlikely to do anything useful and resetting the floppy drive even less so. But for simplicity, the boot sector is the same for hard disks and floppies which contributes to this problem.
It is worth noting that the odd disk reset behavior was introduced in the IBM PC/XT (1983). Its fixed disk BIOS was located in a separate ROM, but the reset logic was very much like the PC/AT described above and also masked floppy reset failures when also resetting the fixed disk.
This reminds me of http://web.archive.org/web/20031009022226/http://www.microsoft.com/whdc/hwdev/archive/storage/phantomdrv.mspx
Yes, that is related. It sounds like the broken-ish behavior that my circa-1992 386 board exhibits (reporting floppy drives when there are none) persisted into the Win9x era.
It occurred to me that a somewhat special case would have been laptops where a floppy drive is configured but not physically present and hot-pluggable. That might be part of the reason why the floppy drive reset succeeds when there’s no drive.
The Phoenix BIOS is quite clear that INT 13h 00h resets both hard drive and floppy drive while INT 13h 0Dh only resets the hard drive. IBM’s BIOS refers to 0Dh (alternate disk reset) but as far as I can tell there is no code attached to that entry point.
IBM also had INT 13h/0Dh, even in the PC/XT. And yes, that function only resets the hard disk.
It seems like there must have been some reason for resetting the floppy together with the hard disk, but I could not find any clues explaining it.
I can’t find 0Dh in the 5170 BIOS listing. Line 893 is the end of function 0Ch (seek) and line 895 is the start of function 10h (disk test ready). The function transfer table seems to send 0Dh calls to the same point as 00h (02C1) but it has been a long time since I read x86 assembler.
If I follow the code flow correctly, 00h on the IBM will reset hard drive and then pass through to the floppy routines doing a reset as well there. 0Dh calls the same routine as 00h but when passed to the floppy routines, the lack of any floppy function 0Dh precludes the floppy getting reset. This in turn looks to be a result of the early XT/AT designs having separate floppy and hard disk controller chips. Later designs that consolidated to a single chip needed to force that chip to do what both chips used by IBM did.
On all 3 versions of the AT BIOS, function 00h and 0Dh call DISK_RESET for hard drives. Keep in mind that the code initially checks the drive code and if it is less than 80h the BIOS will issue INT 40h which is the floppy drive code which doesn’t support function 0Dh.
Speaking of which, you didn’t reconstruct the separate XT disk BIOS, right? At least I couldn’t find anything.
In function DISK_IO (INT 13h service), for drive numbers below 80h they just do INT 40h (previous INT 13h handler). Otherwise they check if requested function in AH is zero (i.e. Disk Reset) and if so, execute INT 40h, clear error code, and go on to handle the fixed disk function. Near the end of the DISK_IO_CONT routine, there is an indirect jump through the M1 table. The M1 table contains a pointer to DISK_RESET, at index 0 and 0Dh.
Hmm, are you really talking about the 5170 (PC/AT)?
BTW I don’t think the FDC and hard disk were typically consolidated in a single chip. In 1990s PCs, the FDC was typically part of some Super I/O chip while IDE was on the disk itself, possibly with some help from the chipset if bus-mastering was supported.
The super I/O chip probably did some adress decoding for IDE.
The CS3 pin on an IDE disk overlaps with the floppy controller, probably because the first controller on an IBM AT had both floppy and hard disk on the same card and could thus use some unused i/o adress in the floppy controller space for something related to the hard disk. AFAIK the CS3 thing is only needed for backward compability with old software. It’s not needed to use an IDE disk.
P.S. some other non-PC computers with IDE interface actually decoded some adress to enable CS3, but the software didn’t use that feature. This was good because you could make an adapter that cut CS3 from the standard two possible IDE devices and route it to CS1 on another set of two IDE devices, thus making it possible to have four IDE devices on a controller that were only supposed to handle two IDE devices. Atleast this were not uncommon om Amiga 4000 and probably also Amiga 1200 (which had the same kind of IDE controller).
@integration of {f,h}dd controllers:
Makes me figure just how easily we could’ve ended up with having to attach floppy drives to the first hdd. Not so far-fetched given the anal emphasis on backwards combat. Ugh.
I’ve had a quick look at the orig ATA specification (shoot me if it’s fiction — I wouldn’t know), and if I interpret things correctly, the signal now called CS3 is used to access the ‘Alternate status register’, a read from which does not clear a pending interrupt. Sounds like a useful feature only for dodgy driver code. Does anything actually rely on that register?
Sorry if I’ve got things mixed up here, I’m a teensy bit out of my depth.
But that was never the case. The hard disk controller was always separate, with the exception of I/O port 3F6h which was shared between the floppy drive (drive, not FDC per se!) and the fixed disk controller.
I suppose I’ve got a fairly rich imagination :^)
The shared register decoding was deprecated relatively early on when IDE was standardized. I think it was just too problematic to keep it going with one part in Super I/O and another on an IDE drive. And I refreshed my memory, it was port 3F7h that was shared, 3F6h was and is used by IDE (as Alternate Status Register for reads and Device Control for writes).
What you refer to as CS3 is what the ATA-2 standard (1996) calls it the CS1- (Chip Select 1) and says that “this signal has also been known in the industry as CS3FX-” (because it turns on the 3Fxh range decoding).
For the “shared” register at 3F7h, ATA-2 says: “This register is obsolete. It is recommended that a device not respond to a read of this address. If a device does respond, it shall be sure not to drive the DD7 signal to prevent possible conflict with floppy disk implementations.” IOW, old behavior is permitted but discouraged.
The older ATA-1 standard (1994-ish) is a very useful reference because it tends to describe the historic implementations. It actually uses the CS1FX- and CS3FX- designation for the chip select signals. And it defines the 3F7h register as the Drive Address register: “This register contains the inverted drive select and head select addresses of the currently selected drive.” Bit 7 is defined as high-impedance (so it could be shared with the floppy logic). The thing is that the momentary drive/head select addresses are not that useful and the standard even says so: “Care should be used when interpreting these bits, as they do not always represent the expected status of drive operations at the instant the status was put into this register. This is because of the use of caching, translate mode and the Drive 0/Drive 1 concept with each drive having its own embedded controller.”
In other words, the register is no good except perhaps for diagnostics with old MFM/RLL controllers, and that is why ATA-2 was able to ditch it entirely.
No I didn’t reconstruct the XT fixed disk BIOS. No one ever OCR’ed it so there was nothing to start from. I didn’t do the PCjr or PC Convertible either but no one really cares about either of those.
Right, I had it mixed up then. Thanks for the explanation — I think I understand the issue now.
>The older ATA-1 standard (1994-ish) is a very useful reference because it tends to describe the historic implementations.
Also, for a bit of a tangent, the WD1002 reference is helpful to understand the history of IDE. For example, bits 5-7 of the drive select register are supposed to be 101, why, because 5 and 6 are the sector size so 1 is 512Bps and 7 is enable CRC/ECC.
Yes. The PC/AT Technical Reference is also helpful (for the IBM spin on things), and so are the documents for WD1010 and other component chips. They explain why the commands are what they are, why you need the INITIALIZE DRIVE PARAMETERS command, and so on. It’s really quite amazing how much modern IDE drives evolved from WD1002 + a ST-506 drive, and how much they still remained compatible.
Like I said, backwards combat. I just explained to my bf (the other Michal says hi!) how the basic design of a vacuum cleaner (the dust-sucking type, “hoover”?) have not changed that much, either…
Suppose in both cases what’s added is mainly accumulating fluff. The IBM PC design, including the disk stuff, is a real crawling horror, though…
Also see http://www.intel.com/design/archives/periphrl/docs/7225.htm
@Yuhong Bao: Thanks! That’s the first Intel document I’ve found even remotely useful 😉
There was a wink smiley (semicolon, closing parenthesis) at the end of my prev comment. Dunno why it got cut.