A Bug in the 3B2 Emulator

Published Saturday, May 18 2024

Well, this is embarrassing. I have discovered a pretty serious bug in the AT&T 3B2 emulator, present since the very first release, and undetected until now. The “TL;DR” version is that the largest hard disk model that the 3B2 emulator offers, a 161 MB Maxtor XT-2190, is not actually supported on a real 3B2 because it has more than 1024 cylinders.

This leaves me with a pretty obvious problem: If I fix this bug, the emulator will be more accurate to real hardware, but it will break existing configurations that people may be using out in the wild.

A deeper analysis of the bug

I only discovered that there was a problem when I finally got around to trying a 161 MB disk on a real 3B2/310. Granted, this is not a real Maxtor XT-2190, those are rare and expensive and probably wouldn’t spin up even if I had one; instead, this is a phantom Maxtor XT-2190 being served up by David Gesswein’s superb hardware MFM Emulator. I’ve used the MFM emulator in the past to emulate the 72 MB CDC Wren II, which was the most common hard drive to ship with the 3B2/400, but I’d never built out a system on a 161 MB Maxtor XT-2190 using real 3B2 hardware before. So, I tried that. It didn’t work, the system refuses to boot from one I’ve already prepared, and it refuses to format a blank disk.

I scoured the NEC uPD7261A datasheet to try to understand why, but the 3B2 emulator was already doing what the datasheet said it should be doing, with one tiny exception: The “Recalibrate” command, which brings the hard drive head back to track 0, wasn’t implemented quite faithfully. The datasheet says that “Recalibrate” issues 1023 step-in pulses, and if track 0 isn’t encountered by the time it’s finished, it’ll signal a seek error.

Well, the 3B2 emulator implementation of the controller was just setting the cylinder to 0 on “Recalibrate”, and calling it a day. That happens to be fine for most drives, because they have fewer than 1024 cylinders, but the Maxtor XT-2190 has 1224 cylinders, so if the head happens to be on any cylinder above track 1023 when it receives a “Recalibrate” command, the head will never make it to track 0. Oops.

I fixed this little mistake, but surprisingly, the 3B2 emulator still worked! Instead of issuing one “Recalibrate” command, the 3B2 firmware saw the seek failure and issued a second “Recalibrate” command so the head would get to track 0. This behavior was still different from a real 3B2! I had to dig deeper.

Eventually, I strapped a logic analyzer onto the hard disk controller and watched what it was doing. That revealed that the NEC uPD7261A datasheet wasn’t really telling the whole story.

What the datasheet omits

The logic analyzer captured all the commands to and responses from the hard disk controller. Most interestingly, I saw this behavior during early startup:

  1. The 3B2 asks the controller to seek to track 0 and read it. This succeeds.
  2. Then it asks the controller to seek to track 1223 and read it. This succeeds.
  3. Finally, it issues a “Recalibate” command, but the controller never signals that it’s done.

The real clue here was watching the hard disk controller’s status register.


According to the datasheet, the controller is supposed to set the high bit, CB or “Controller Busy”, as soon as it receives a command, and then clear the bit when the command is done, whether the command succeeded or failed. Command success and failure can be determined by examining bits 6 and 5, CEH and CEL (“Command End High” and “Command End Low”). But, I was observing that CB never got cleared when “Recalibrate” couldn’t find track 0. Reading the status register always returned 0x80! Eventually the 3B2 gives up polling the controller, and then gives up trying to boot.

When I changed the 3B2 emulator to behave the same way, it finally agreed with real hardware. I saw the same behavior in the emulator that I saw when trying to boot my real 3B2/310 from a hard disk image with 1224 cylinders.

What to do about it

I’m left with something of a dilemma: If I fix this bug, the emulator becomes more accurate, but the cat is already out of the bag. Since the very beginning I’ve advertised the ability to use a 161 MB hard disk image, and suggested it as a pretty good default so you can get the maximum space for the emulated system to use. That means there are probably at least a few people out there using the 3B2 emulator with these drives, and if I fix the bug, their emulator will no longer boot.

So, what I’ve decided to do is to compromise. Going forward, the default behavior of the 3B2 emulator will be not to allow the HD161 disk type to be used; but, for backward compatibility, a new command will be added to allow you to go ahead and use it anyway, with the old behavior restored.

If you try to set the HD161 disk type you’ll be warned, and if you still persist and try to attach an HD161 disk image, you’ll get an error:

sim> SET IDISK0 HD161
%SIM-INFO: HD161 disks can only be used if large disk support is enabled (SET IDISK LARGE)
sim> ATT IDISK0 hd161.img
%SIM-ERROR: HD161 disks can only be used if large disk support is enabled (SET IDISK LARGE)

Just following the prompted instruction will then revert to the old behavior.

sim> SET IDISK0 HD161
sim> ATT IDISK0 hd161.img

If for whatever reason you decide to change back to not supporting large disks with a large disk attached, well, you can do that, but at least you’ll be warned about it:

%SIM-INFO: Large disk support disabled, but at least one attached disk is large!

I think this is the best compromise I can make.