Handling OS-9 RBF (Fluke 9100) floppies on Linux

I recently had need to figure out how to read and write floppy disks for the Fluke 9100 on a Linux box. There are various other methods for accomplishing this, but I was specifically looking for something that would work without special hardware or booting a non-Linux operating system. Since programs like TeleDisk / ImageDisk / SAMdisk can read using the same hardware, this is purely a software issue.

You need a machine with a real floppy disk controller (FDC) -- USB floppy drives won’t work.


Floppy controller hardware can’t autodetect disk formats, it needs to be told what the format is. When a disk is ejected/inserted, the parameters reset to the defaults. If the disk doesn’t match them, the controller needs to be told what its format is again.

Linux’s floppy subsytem has many knobs exposed via fdutils, but the documentation isn’t great, so this requires some sleuthing.

Disk Format

Knowing the disk format up-front helps a lot. The 9100A uses soft-sector, double-sided, double-density floppies.

Bytes per sector 256
Sectors per track 16
Tracks (cylinders) 80
Formatted capacity 655,360 bytes

Later machines upgraded to a high-density drive. All the parameters are the same, except the sectors per track were doubled to 32, resulting in 1,310,720 of raw storage.

Each sector on the disk has its number recorded along with the data. PC disk formats start numbering their sectors at 1, but OS-9 begins numbering them at 0. This is important.


The approach is to put the 9100 disk in, configure the controller with setfdprm(8), then read the raw sectors with dd(1). The manpage for setfdprm(8) describes itself as "woefully inadequate," but a jaunt through the source code is enlightening, and provides us with the following parameters for a high-density disk:

sect=32 ssize=256 cyl=80 ds hd zerobased

... which matches up nicely with what we know about the disk format.

From here, it’s a simple matter to configure and image a disk:

setfdprm /dev/fd0 sect=32 ssize=256 cyl=80 ds hd zerobased
dd bs=256 if=/dev/fd0 of=disk.img

Handling a double-density disk requires a bit more tweaking, but the following is what’s required:

sect=16 ssize=256 cyl=80 ds dd zerobased

Formatting and Writing

Before writing the disk, it has to be low-level formatted using the correct parameters. The arguments we’ve already discussed are accepted by most everything in the fdutils arsenal, including superformat(8), so we can use that:

1: superformat /dev/fd0 sect=32 ssize=256 cyl=80 ds hd zerobased

Formatting will also set the parameters -- if you just formatted the disk, you can dd(1) the image onto it now. If the disk was already formatted, you can call setfdprm(8) after inserting it and just dd(1) the image.

This works for double-density media as well, however, the usual caveats about writing DD media in a HD drive apply. If it doesn’t work, format the disk on a true DD drive, or degauss the media entirely.

But why

Because even though the 9100 is awesome, its editing facilities leave a lot to be desired. There’s no concept of version control, and it’s relatively difficult to get debugged programs off it. Because of all that, I’ve been making an effort to move as much development as possible onto my regular workstation. I wrote an Emacs mode for the TL/1 programming language and have a Git repo with all my TL/1 code in it. I’ve created a build process which syntax checks everything (using Fluke’s MS-DOS TLC.EXE, inside a headless DOSBox), creates a userdisk structure, copies it into a disk image, and writes it to disk -- all with a single make(1) invocation.