Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,13 +176,21 @@ hashes are given where a change is easiest to understand by reading the commit.
IMPACT graphics on widget 11. The stock IP30 PROM boots IRIX 6.5.30 to a
serial login or, on the graphics console, to the X login and desktop.
Needs the IP30 PROM image. Runs under jitv2 as well as the interpreter.
The devices are time-driven by `hptimer` and per-port receive threads, with
no polling thread; every thread is joined when the machine stops.
The devices are time-driven by `hptimer`. Serial input is polled every
2 ms by one receive thread per port; every thread is joined when the
machine stops.
iris-gui can run it.
- **The Octane's memory and bus bookkeeping are cheaper.** A MEMCFG write
that leaves the decode as it was no longer rebuilds the table and empties
ppmem's window under the running CPU. The first 64 distinct misses and
unsupported accesses are still listed, but once a list is full it costs one
atomic load instead of a lock and a scan. A swapped Bridge DMA transfer
that is whole 4- or 8-byte units reverses the bytes in place rather than
through a spanning copy.
- **One 1-wire bus for the board records.** `dev::w1` holds the bus, the
slot decode and the Dallas parts (DS2501/2502, DS2505); HEART, the Bridge,
IOC3 and the graphics board each own a wire. `sgi_nic` only builds the SGI
record formats.
IOC3 and the graphics board each own a wire. `dev::w1::sgi` only builds the
SGI record formats.
- **CP0 Count writes can open the late-Compare window** (`count_write_samples`,
opt-in; the Octane sets it): IRIX on the Octane arms Compare a few
instructions after writing Count, and a host stall in between no longer
Expand Down
13 changes: 7 additions & 6 deletions FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -335,16 +335,17 @@ is the internal bus, 1 the external) and `[graphics] board`. See [the Octane gui

### Hardware constraints and precedence

Bank values are 0, 8, 16, 32, 64, or 128 MB; only IP28 accepts 256/512 MB. On
the O2 a bank is a DIMM pair's kit, 32, 64, 128 or 256 MB, fitted from pair A
largest first; on the Octane it is a matched DIMM pair, 64, 128, 256 or 512 MB, filled from bank 0. `banks` has eight entries; every machine today uses the first
four and the rest must be 0.
On the Indy and Indigo2 bank values are 0, 8, 16, 32, 64, or 128 MB, and only
IP28 accepts 256/512 MB. On the O2 a bank is a DIMM pair's kit, 32, 64, 128 or
256 MB, fitted from pair A largest first; on the Octane it is a matched DIMM
pair, 64, 128, 256 or 512 MB, filled from bank 0. `banks` has eight entries;
every machine today uses the first four and the rest must be 0.
IP22/IP24 four-bank IRIX 6.5 behavior remains separate from IP28's verified
two-bank 1 GB layout. Extreme requires IP22. All non-Newport boards require
`heads=1` and `resolution="guest"`. IP28 IRIX needs IMPACT; its PROM has an
embedded fallback.
The config validator permits SCSI controller 1 only on IP22, the O2 and the Octane,
the machines with two controllers.
The config validator permits SCSI controller 1 only on IP22, the O2 and the
Octane, the machines with two controllers.

Standalone CLI options update the loaded config where supplied; boolean enable
switches do not provide a general way to clear every saved true setting.
Expand Down
24 changes: 17 additions & 7 deletions HACKING.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ Other documents:

## 1. What IRIS is

IRIS emulates three SGI workstations: the Indy (IP24), the Indigo2 (IP22) and
the Indigo2 IMPACT (IP28). The CPU is an R4400, R5000 or R10000, chosen at
runtime. Graphics is Newport (REX3), GR2 (XZ/Extreme) or IMPACT. It boots the
real PROMs and IRIX 5.3 and 6.5 to a desktop with networking.
IRIS emulates five SGI workstations: the Indy (IP24), the Indigo2 (IP22), the
Indigo2 IMPACT (IP28), the O2 (IP32) and the Octane (IP30). The CPU is an
R4400, R5000 or R10000, chosen at runtime (the Octane takes the R10000 only).
Graphics is Newport (REX3), GR2 (XZ/Extreme) or IMPACT on the Indy and
Indigo2, GBE on the O2 and Solid IMPACT on the Octane. It boots the real PROMs
and IRIX 5.3 and 6.5 to a desktop with networking.

It is **not cycle-accurate**, anywhere. IRIX is interrupt-driven and does not
care how many cycles an instruction takes, so IRIS models behaviour
Expand Down Expand Up @@ -460,9 +462,17 @@ introspection commands are in [debug.md](debug.md#jit-v2).
cascade, a serial EEPROM for NVRAM and the MAC address.
- **IP28 (Indigo2 IMPACT)**: IP22 devices plus an R10000, IMPACT graphics,
a 16 MB MEMCFG granule and RAM at `0x20000000`.

Each has an embedded PROM fallback. `src/platform.rs` and `src/machine.rs`
wire the differences; `platform_profile_tests.rs` pins them down.
- **IP32 (O2)**: its own machine (`src/ip32_machine.rs`): CRIME, MACE
and GBE, with an Adaptec 7880 for SCSI.
- **IP30 (Octane)**: its own machine (`src/ip30_machine.rs`): HEART, the
Crossbow and the Bridge with IOC3 and two ISP1040 SCSI controllers, an
R10000, and IMPACT graphics (see the [Octane guide](docs/octane-ip30.md)
for the boards).

The Indy and Indigo2 profiles each have an embedded PROM fallback;
`src/platform.rs` and `src/machine.rs` wire their differences, and
`platform_profile_tests.rs` pins them down. The O2 and the Octane have no
embedded PROM and are built by `workstation::build`.

## 10. Building and testing

Expand Down
2 changes: 1 addition & 1 deletion clanker/INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ Non-graphics devices: MC/MEMCFG and RAM banks, HPC3, VDMA, EEPROMs and NVRAM, PS
| [o2-readback-transfer-registers.md](devices/o2-readback-transfer-registers.md) | rule | O2 glReadPixels: the frame-buffer-to-linear transfer, GL vertices, edge type, src steps and linStride as IRIX uses them |
| [ip32-o2-bringup-log.md](devices/ip32-o2-bringup-log.md) | history | The O2 (IP32) bring-up log: PROM, POST, CRIME/MACE/GBE, SCSI, PCI, the OSes |
| [ip32-headless-irix-panics.md](devices/ip32-headless-irix-panics.md) | rule | O2 TLBMISS at 0xff800000 in early boot was `crmFifoWait` timing out on our host-thread RE; status polls now wait for the engine (fixed) |
| [ip30-octane-bringup.md](devices/ip30-octane-bringup.md) | open | The Octane (IP30) bring-up: PROM 4.17 to its menu on the serial console; what it insists on (memory sizing, the Bridge status bit, empty slots, IOC3 bits, the NIC parts' formats, its device tree); the full machine's findings (cached flash lines, low-memory JIT counters, the ISP stall, HQ4 before a context switch) |
| [ip30-octane-bringup.md](devices/ip30-octane-bringup.md) | rule | What the Octane's PROM insists on (memory sizing, the Bridge status bit, empty slots, IOC3 bits, the one-wire parts' formats, its device tree) and what booting it through to IRIX added (cached flash lines, low-memory JIT counters, the ISP stall, HQ4 before a context switch) |
| [ip30-low-memory-aliases-sdram.md](devices/ip30-low-memory-aliases-sdram.md) | rule | Octane: the 16 KiB at physical 0 is the first 16 KiB of SDRAM, which the processor reaches only there (0x2000_0000..+16 KiB bus-errors, as the stock IDE memory diagnostics expect); shares its JIT page generations; the guard holds on the table path only (the ppmem window maps whole units); DMA reach unknown |
| [ip30-prom-stores-into-flash-stay-in-cache.md](devices/ip30-prom-stores-into-flash-stay-in-cache.md) | rule | Octane: the PROM's cached stores into its own flash never reach the Bridge; `CachedFlashLines` holds them (approximation: no write-back) |
| [ip30-device-timing-on-hptimer.md](devices/ip30-device-timing-on-hptimer.md) | design | Octane: IOC3, RAD1 and ISP1040 pace themselves on `hptimer` one-shots, with threads only where something blocks (the ISP1040 ring, serial receive, NVRAM writer) |
Expand Down
2 changes: 1 addition & 1 deletion clanker/devices/ip30-device-timing-on-hptimer.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Status: design (read the code before relying on details).

**What to know.** The Octane's devices avoid polling threads. Timed work is a
**What to know.** The Octane's devices poll only for serial input. Timed work is a
one-shot or recurring `hptimer` that does the same catch-up a register access
would, so an idle guest still makes progress. Threads exist only where
something blocks.
Expand Down
93 changes: 34 additions & 59 deletions clanker/devices/ip30-octane-bringup.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,28 @@
# The Octane (IP30) bring-up: the PROM to its serial prompt
# What the Octane's PROM insists on

Status: open (started 2026-10-19 on branch ip30 of slaapliedje/iris, rebuilt
2026-10-26 on branch ip30-machine as its own machine; the PROM's menu and
command monitor work on the serial console).
Status: rule (PROM 4.17; each item below was found by a stall or a wrong
answer in the PROM's own checks).

**Where it stands.** `[machine] profile = "octane_ip30"` builds an
`OctaneMachine` (`src/ip30_machine.rs`) over `Ip30Bus` (`src/ip30.rs`, on `Physical` since 2026-10-28):
HEART, the Xbow, the Bridge with its PCI configuration space and device
windows, the IOC3's two 16550s, DS1687 and 1-wire parts, the flash, and
memory placed by MEMCFG. The QL1040s, the RAD and the graphics widget are
register files. The map every offset came from is
`docs/Octane/ip30-address-map.md`. PROM 4.17 runs its power-on
diagnostics, builds its device tree (`hinv` shows the IOC3's serial
ports, keyboard, Ethernet, both QLISP1040s and the RAD) and reaches the
System Maintenance Menu and the Command Monitor on UART A
(`serial_port_a`). `IRIS_IP30_TRACE=1` logs the first access to each
register, `=2` every IOC3 access in order; the monitor's `ip30` command
shows memory, HEART, the Bridge and the unmapped accesses.
**What to know.** The IP30 PROM probes the hardware far harder than a
kernel does. Memory sizing, the Bridge, the IOC3 and the one-wire parts must
each answer the way the real parts do, or the PROM skips a bus, panics with no
console, or loops. The bus is `Ip30Bus` (`src/ip30.rs`), the machine's
`Physical`. `docs/octane-ip30.md` says what the machine covers and
`docs/Octane/ip30-address-map.md` holds the map every offset came from. The
monitor's `ip30` command (memory, the Bridge, the graphics link, refused
Crossbow accesses, unmapped accesses) and `heart unsupported` show what the
PROM touched that the model does not answer. `IRIS_IP30_TRACE=1` prints the
accesses nothing answers as they happen.

**What the PROM insists on, found one stall at a time.**
**What the PROM insists on.**

- *Memory sizing.* The PROM programs a bank as 1 GB at 2 GB (MEMCFG
0x819f0040) and looks for where its contents repeat: at +256 bytes,
+128 MB, then +1 GB or +64 MB, one DIMM address line each. A rev D HEART
(the Octane's) sizes only 1 GB and 2 GB pairs correctly from a plain
mirror, so configure 1024 MB banks. It also probes every bank, so a
bank with no DIMMs must take writes and read back zero (`Decode::Empty`)
rather than bus-error; the probe places banks beyond 4 GB for a moment,
where the 32-bit bus cannot follow.
- *Memory sizing.* The PROM sizes a bank by writing through a temporary
2 GiB descriptor (`0x81bf0040`) and checking which address bits alias.
HEART's wiring for that probe is not documented, so
`heart_mem::bank_offset` projects each fitted size so the PROM picks the
right descriptor; that is an approximation. It also probes every bank, so
a bank with no DIMMs must take writes and read back zero rather than
bus-error.
- *The Bridge's device windows at reset are memory space at base 0.* The
PROM enables the RAD's memory decode and writes through window 3 with
neither the RAD's BAR nor device register 3 programmed; the window has
Expand All @@ -47,11 +42,11 @@ shows memory, HEART, the Bridge and the unmapped accesses.
byte bus 2 (+0xc0000), as OpenBSD's dsrtc.c has it, not the SuperIO RTC
slot at 0x20168. The 16550s are at 0x20178 (A, the console) and 0x20170
(B), registers at consecutive bytes.
- *The NICs.* The MAC part is a DS1981U (family 0x91): the PROM reads 14
bytes after Read Memory at 0 (the first the CRC8 of the command) into
nic[13..0] and takes the address from nic[2..8], so the MAC sits
reversed at memory 5..11 as the end of a TMEX page. The board parts are
DS2505s (family 0x0b, 2 KB): Read Status at 0x100 returns the page
- *The one-wire parts.* The MAC part is a DS1981U (family 0x91): the PROM
reads 14 bytes after Read Memory at 0 (the first the CRC8 of the
command) into nic[13..0] and takes the address from nic[2..8], so the MAC
sits reversed at memory 5..11 as the end of a TMEX page. The board parts
are DS2505s (family 0x0b, 2 KB): Read Status at 0x100 returns the page
redirection table in groups of eight bytes each followed by an inverted
CRC16 (over the command, address and bytes for the first group, the
bytes alone after; the PROM's `nic_read_mfg` checks them: "invalid crc16
Expand All @@ -60,11 +55,9 @@ shows memory, HEART, the Bridge and the unmapped accesses.
barcode (20), nine characters of the part number; page 1: three more,
the revision, six 0xff bytes, the name (14); each page ends in its
inverted CRC16. The PROM uses Search ROM on each wire, so several parts
share one `OneWire`. The system board's and CPU module's parts are on
the Bridge's wire, the front plane's and power supply's on the IOC3's
(with the MAC part); the PROM never drives HEART's MicroLAN master. The
CPU board NIC diagnostic still fails: what the PROM wants from the PM10
part is not known yet.
share one `w1::Bus`. The system board's part is on the Bridge's wire, the
processor module's on HEART's MicroLAN, and the front plane's and power
supply's on the IOC3's (with the MAC part).
- *What the PROM programs in the Bridge.* IOC3 BAR0 = 0x00400000 and
device register 2 = 0x1004 (memory space, base 0x004 << 20, no PIO
swap); interrupt destination upper 0x09080000 / lower 0x80 (vector 9 for
Expand All @@ -82,31 +75,13 @@ shows memory, HEART, the Bridge and the unmapped accesses.
PCI offset ^ 2 through a window whose swap bit is clear. A
little-endian function's model therefore takes CPU-view offsets and
applies the ^2/^3 itself; the window's swap bit (device register bit
13) is modelled as lane and data swapping but nothing has used it yet.
13) is modelled as lane and data swapping.
- *The device tree.* Finding out why a console device will not open is
quickest from the tree: the root pointer is at 0xa800000020f24040, a
node's type is at +4, key at +16, peer at +64, child at +72, and one of
the doublewords from +24 on points at its name.

**Not done.** The CPU board NIC check; the keyboard (the PROM polls
K_RD after writing 0xf2 to K_WD and gives up, which is fine without a
keyboard); large and huge widget windows (physical 0x8_0000_0000 and up)
and memory above 4 GB need the bus widened past `u32`, which the O2's
`phys_alias` trick does not cover; SCSI needs the ISP1040 model
(`docs/Octane/qla1040.md`: the PROM's "QL SCSI controller initialization
failed" is the register file answering its mailbox); Ethernet the IOC3's
ring DMA; graphics HQ4 in front of the IMPACT emulation (the widget is
left off the Xbow's links so the PROM takes the serial console);
snapshots the usual `Saveable` work.

## Full machine

The sections above stop at the PROM menu. The machine now boots the stock
PROM to IRIX 6.5.30 (serial login, graphics console and desktop, networking,
sound); the device models are ports of the author's QEMU models, one file
each (`docs/octane-ip30.md` says what is covered). What the bring-up above
lists as not done is done, except the CPU board NIC check. What the full
boot added:
**What booting the PROM through to IRIX added.**

- *The PROM's stores into the flash are cached lines.* The PROM keeps its
initialised data at flash addresses and stores to it with cached accesses
Expand All @@ -125,9 +100,9 @@ boot added:
advanced by every store, including a bus master's at the SDRAM address.
- *An ISP1040 reset must not wait for the disk.* A soft reset and a queue
initialisation waited on the CPU thread for the command in flight, so a
slow disk stalled the guest and the scheduler's timer ticks were missed
. The reset now moves a generation counter
on and the ring thread does the DMA with no lock held.
slow disk stalled the guest and the scheduler's timer ticks were missed.
The reset now moves a generation counter on and the ring thread does the
DMA with no lock held.
- *The PROM console draws on HQ4 before any context switch.* Its graphical
console sends direct raster writes and a few other one-word packets to the
HQ4's command port before the board has ever selected a context, and a
Expand Down
4 changes: 2 additions & 2 deletions debug.md
Original file line number Diff line number Diff line change
Expand Up @@ -323,8 +323,8 @@ shows the command total and anything odd the driver did; `regs`, `wdt`,
(HEART registers touched but not modelled) and `ip30 memcfg|bridge|gfx|xbow|unmapped`
(the banks as HEART places them, the Bridge's interrupt routing, the graphics
widget's link, refused Crossbow accesses, and accesses to physical addresses
nothing is mapped at, with the PC). The `phys` commands work on the Octane as
well.
nothing is mapped at, with the PC; a device's own refusal is not listed). The
`phys` commands work on the Octane as well.

Queue position `[0]` is the mounted disc, `[1]` the next on eject. A disc
change reaches IRIX as a Unit Attention ("medium changed") on its next
Expand Down
Loading
Loading