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.
Background
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.
Tuning
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.