Give the disk four drives, behind one controller

SEVERAL DISKS ARE ONE CONTROLLER AND NOT SEVERAL DEVICES, and the
instruction set decided that rather than taste. A port is an immediate byte
inside the OUT that names it - portOut takes it from Program Memory - so a
program cannot compute one. "The disk on port 0x20 plus drive times four"
is not something this machine can say, and two disks as two devices would
mean a branch on the drive number in all eleven places sbfs.asm names a
disk port. A drive register is what a floppy controller has always been.

  0x24  Drive, which the block, command and status registers refer to
  0x25  Drives, read only: how many are plugged in

--disk given more than once fills them in order. What is per drive is the
image, its size and its write protection; the block register, the status
and the one buffer belong to the controller, which is the same division
real hardware makes.

A drive that is not there is refused rather than wrapped, because wrapping
means a program asking for a drive this machine has not got quietly reading
the one it has - the same shape of fault as taking a bank number somebody
else was using. An EMPTY drive is a different thing and is selectable: a
controller has its drives whether or not there are disks in them, and
reading one fails with the error bit the way an empty drive should.

Changing drives finishes whatever the one being left was in the middle of.
A transfer waits for the clock, so one may be owed at any moment, and
running it against the disk that is arriving would be a fault with no
owner.

Also stops parseOptions setting its defaults field by field. It was nine
assignments beside a struct, and a list beside a thing drifts from the
thing: adding two fields left them holding whatever was on the stack, so a
machine given one disk was told it already had four drives. It is one
zeroing now, and a default that is not nought can be written under it where
it reads as the exception. That struct growing a field once before left
Voyager linked against an object that disagreed about its size.

Nothing in CosmOS uses any of this yet. The mount record is next.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
Anachronaut
2026-08-31 10:10:38 -04:00
co-authored by Claude Opus 5
parent 3b650cabcd
commit b1538e0618
10 changed files with 272 additions and 50 deletions
+31 -1
View File
@@ -546,7 +546,7 @@ If nothing is installed for the vector a device refused with, the machine stops
| 0x00 - 0x05 | The console. See The Console. Writing to 0x00 sends a byte to standard output, reading takes one from standard input. It interrupts on 0x00, its base port, when asked to. | 0x02 |
| 0x10 | A test device. Writing anything to it puts its own line up, so that interrupt handling can be exercised without waiting on anything. The byte written is ignored. | 0x10 |
| 0x11 | A device that refuses everything, in both directions, so that refusal can be exercised without the memory controller. | 0x11 |
| 0x20 - 0x23 | The disk. See Storage. It interrupts on 0x20, its base port. | 0x13 |
| 0x20 - 0x25 | The disk. See Storage. It interrupts on 0x20, its base port. | 0x13 |
| 0x13 | The machine itself. Writing 1 asks it to start over: whatever put the first instruction in memory does it again, and the CPU begins where the boot vector points. A port rather than a service, because a reset has to work when the system does not - and a program that owns the whole machine has no system to ask. The disk is not unplugged and keeps what was written to it; the vector table is cleared, because a handler left behind would aim an interrupt into a program that is no longer running. | 0x04 |
| 0x12 | A device that owns 256 bytes of memory. Writing to its port fills that memory with the byte written, standing in for a disk controller reading a sector. Its memory is unreachable until it is registered as a bank. | 0x12 |
| 0x30 - 0x3F | The screen. See The Screen. It brings video memory, which is unreachable until it is registered as a bank. | 0x14 |
@@ -1185,6 +1185,36 @@ The disk owns one block of memory, its buffer. Reading fills it and writing take
A device that answers on more than one port raises its line on the first of them, so the disk interrupts on 0x20.
### Several Disks:
**One controller with four drives, not four devices**, and the instruction set is the reason.
A port is an immediate byte inside the `OUT` that names it, so a program cannot compute one -
*the disk on port 0x20 plus drive times four* is not something this machine can say. Two disks
as two devices would mean a branch on the drive number in every place a program touches a
disk port. So the drive is a register, which is what a floppy controller has always been.
| Port | Register |
| --- | --- |
| 0x24 | Drive. Which one the block, command and status registers refer to. Reads back. |
| 0x25 | Drives, read only. How many are plugged in. |
The block, command and status registers, **and the single buffer**, all belong to whichever
drive is selected. A program that changes drives is holding a buffer that no longer contains
what it thought, and has to say so to itself - the controller cannot know what the program
believed.
A drive that is not there is **refused rather than wrapped**: writing 9 to the drive register
leaves the selection where it was, and reading the register says so. Wrapping would mean a
program asking for a drive this machine does not have quietly reading the one it does.
**Selecting an empty drive is allowed**, because a controller has its drives whether or not
there are disks in them. Reads from one fail with the error bit, which is what an empty drive
should do. `Drives` says how many have disks; the drive register accepts any of the four.
Changing drives finishes whatever the drive being left was in the middle of. A transfer waits
for the clock, so one may be owed at any moment, and running it against the disk that is
arriving instead of the one that asked for it would be a fault with no owner.
### Waiting:
A command returns at once and the line goes up when the block has moved. Status bit 0 says the disk is still working.