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
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ hashes are given where a change is easiest to understand by reading the commit.
load. The monitor's `scsi` and `cow` commands (`scsi1`/`cow1` for the
external bus) work on the O2's Adaptec controllers: status, disc changes,
overlay commit and reset, and the chip's registers.
- **One configuration.** The O2 is set up with the shared keys: `prom`,
`nvram` (the PROM's flash), `banks` (the kit in each DIMM pair),
`serial_port_a`/`serial_port_b`/`serial_log`, `headless`, `[clock]
fixed_mhz` (CP0 Count, half the CPU clock), `[network]` with `mac` and the
new `mode = "off"`, `[[port_forward]]`, `nat_subnet` and `[nfs]`. `[o2]`
keeps `mouse`, `control_port` and `arcs_fpu`; its old keys are folded into
the shared ones on load, with a note. The second serial port is served too,
and the flash is kept between runs by default.
- **Scripting and inspection.** The O2's devices have monitor commands, and
`o2 <command>` (also on `[o2] control_port`) takes screen shots, types,
moves the mouse and reads memory ([debug.md](debug.md#sgi-o2-ip32)).
Expand All @@ -47,6 +55,12 @@ hashes are given where a change is easiest to understand by reading the commit.
page in six. IRIX on an R5000 O2 panicked with "init died" for the same
reason; it now boots to the desktop.

### Memory configuration

- **`banks` has eight entries.** Every machine today uses the first four and
the rest must be 0; a config may list fewer, and files are written back with
four. Room for machines with more banks.

### SCSI configuration

- **One id on both controllers.** A `[scsi.N]` key is a slot: 1–7 on
Expand Down
55 changes: 28 additions & 27 deletions FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,17 +138,17 @@ the first `[section]`, because TOML tables continue until the next header.

| Key | Default | Values and behavior |
|---|---|---|
| `prom` | `"prom.bin"` | PROM path; IP24, IP22, and IP28 each have an embedded fallback. Indigo2 also tries `070-1367-012.bin` (IP22) or `070-1477-002.bin` (IP28) in the working directory. |
| `nvram` | `"nvram.bin"` | DS1386 backing file; GUI defaults to an absolute user-config path. |
| `prom` | `"prom.bin"` | PROM path; IP24, IP22, and IP28 each have an embedded fallback. Indigo2 also tries `070-1367-012.bin` (IP22) or `070-1477-002.bin` (IP28) in the working directory; the O2, which has no embedded PROM, tries `ip32prom.rev4.18.bin`. |
| `nvram` | `"nvram.bin"` | DS1386 backing file on the Indy; the PROM's flash (its environment) on the O2. GUI defaults to an absolute user-config path. |
| `nveeprom` | `"nveeprom.bin"` | Motherboard EEPROM file; GUI anchors it in its user-config directory. |
| `banks` | `[128,128,0,0]` | Four RAM bank sizes in MB; see profile constraints below. |
| `banks` | `[128,128,0,0]` | RAM bank sizes in MB, up to eight entries (every machine today has four; the rest must be 0). On the O2 each entry is a DIMM pair's kit (32, 64, 128 or 256), largest first. See profile constraints below. |
| `scale` | `1` | Standalone window scale: 1–4. GUI uses its separate vm_scale. |
| `headless` | `false` | Disable the standalone window and Newport graphics; audio is independent. |
| `headless` | `false` | Disable the standalone window and graphics; the O2 then boots on its serial console. Audio is independent. |
| `no_audio` | `false` | Disable HAL2 audio emulation. |
| `gdb_port` | `unset` | Start the GDB TCP stub; debugging is unavailable in lightning builds. |
| `monitor_port` | `8888 when unset` | Monitor listener on loopback. |
| `serial_port_a` | `8880 when unset` | SCC channel A listener (tty2). |
| `serial_port_b` | `8881 when unset` | SCC channel B listener (tty1/console); GUI halt uses this port. |
| `serial_port_a` | `8880 when unset` | SCC channel A listener (tty2); the O2's first serial port, its console when headless. |
| `serial_port_b` | `8881 when unset` | SCC channel B listener (tty1/console); the O2's second serial port. GUI halt uses this port. |
| `load_elf` | `unset` | Load a static big-endian MIPS ELF32 binary before starting the CPU. |
| `test_device` | `false` | Map the bare-metal test device in GIO slot 0. |
| `test_device_dump` | `iris-testdev-dump.json when unset` | Test-device machine-state JSON output. |
Expand All @@ -159,7 +159,7 @@ the first `[section]`, because TOML tables continue until the next header.
| `ci_display` | `false` | Keep host graphics window visible in CI mode. |
| `mouse_scroll_pixels_per_line` | `40.0` | Host scrolling distance per guest PS/2 detent. |
| `lock_aspect_ratio` | `true` | Constrain standalone window aspect ratio; false allows letterboxing. |
| `serial_log` | `unset` | Append guest channel-B output; used by CI and GUI serial capture. |
| `serial_log` | `unset` | Append guest channel-B output (the O2's first serial port); used by CI and GUI serial capture. |
| `scsi_deferred_int` | `true` | Defer SCSI status interrupts for BSD compatibility. |

### [machine]
Expand Down Expand Up @@ -204,7 +204,7 @@ An explicit non-disk kind takes precedence over the legacy cdrom flag.

| Key | Default | Values and behavior |
|---|---|---|
| `network.mode` | `nat` | nat or pcap; PCAP needs build support and host capture permissions. |
| `network.mode` | `nat` | nat, pcap or off (no Ethernet; O2 only for now). PCAP needs build support and host capture permissions, and is not available on the O2 yet. |
| `network.pcap_interface` | `auto-pick when unset` | Interface name or numeric list index; PCAP only. |
| `network.nfs_pcap_ip` | `unset` | Virtual LAN IP for the built-in NFS responder in PCAP mode. |
| `network.mac` | `08:00:69:12:34:56 when unset` | ec0 MAC; injected only into blank PROM battery-backed MAC slots. |
Expand Down Expand Up @@ -274,7 +274,7 @@ Omit `[nfs]` to disable the share; the default forward list is empty.

| Key | Default | Values and behavior |
|---|---|---|
| `clock.fixed_mhz` | `33 on IP22/IP24; 97.5 on IP28 when unset` | CP0 Count MHz; IRIX CPU inventory reports twice this rate. |
| `clock.fixed_mhz` | `33 on IP22/IP24; 97.5 on IP28; 90 on the O2 when unset` | CP0 Count MHz; IRIX's CPU inventory and the O2's PROM report twice this rate. |

### [rtc_offset]

Expand All @@ -295,32 +295,33 @@ Omit `[nfs]` to disable the share; the default forward list is empty.

### [o2]

Used with `machine.profile = "o2_ip32"`. The O2's disks are the `[scsi.N]`
tables above, with `controller` as the bus (0 internal, 1 external); the
Indy/Indigo2 top-level `prom`, `nvram` and `banks` keys do not apply. Paths are
relative to where iris runs. See [the O2 guide](docs/o2-ip32.md). An older
config's `o2.disks` list is folded into `[scsi.N]` when the file is loaded and
reported as deprecated.
Used with `machine.profile = "o2_ip32"`. An O2 is configured by the shared
keys: `prom` (its PROM image, not embedded; `ip32prom.rev4.18.bin` is tried
when `prom` is left at its default), `nvram` (the PROM's flash, which holds
its environment), `banks` (the kit in each of the four DIMM pairs: 32, 64,
128 or 256 MB, largest first), `serial_port_a`/`serial_port_b`/`serial_log`,
`headless` (serial console instead of the graphics console and keyboard),
`[clock] fixed_mhz` (CP0 Count; the CPU runs at twice it, so 90 MHz is a
180 MHz O2), `[network]` including `mac` and `mode = "off"` for an unplugged
Ethernet, `[[port_forward]]`, `nat_subnet`, `[nfs]` and `[scsi.N]`
(`controller` is the bus). See [the O2 guide](docs/o2-ip32.md). The old
O2-only spellings (`o2.prom`, `o2.flash`, `o2.ram_mb`, `o2.dimms`,
`o2.disks`, `o2.serial_port`, `o2.serial_log`, `o2.graphics`, `o2.cpu_mhz`,
`o2.net`, `o2.forwards`) are deprecated: they are folded into those keys when
the file is loaded, with a note, and never written back.

| Key | Default | Values and behavior |
|---|---|---|
| `o2.prom` | `ip32prom.rev4.18.bin` | The O2 PROM image (not embedded). |
| `o2.flash` | unset | File the PROM's flash (its environment) is loaded from and saved to. |
| `o2.ram_mb` | `256` | Memory in MB, fitted largest DIMM kits first (up to 1024). |
| `o2.dimms` | unset | Instead of `ram_mb`: the kit in each DIMM pair, in MB (32, 64, 128 or 256). |
| `o2.serial_port` | unset | TCP port on 127.0.0.1 for the first serial port. |
| `o2.serial_log` | unset | File that copies the first serial port's output. |
| `o2.graphics` | `true` | PS/2 keyboard and the graphics console; `false` for a serial console. |
| `o2.mouse` | `true` | PS/2 mouse on the second port (with `graphics`). |
| `o2.cpu_mhz` | `180` | CPU clock the PROM measures; CP0 Count runs at half of it. |
| `o2.mouse` | `true` | PS/2 mouse on the second port (with the graphics console). |
| `o2.control_port` | unset | TCP port on 127.0.0.1 serving the `o2` monitor commands for scripts. |
| `o2.net` | `true` | Ethernet on the NAT gateway. |
| `o2.forwards` | `[]` | Host-to-guest port forwards: `{ proto, host_port, guest_port }`. |
| `o2.arcs_fpu` | `false` | Test aid: lend a kernel the FPU while it runs inside the PROM. |

### Hardware constraints and precedence

Bank values are 0, 8, 16, 32, 64, or 128 MB; only IP28 accepts 256/512 MB.
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. `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
Expand Down
11 changes: 8 additions & 3 deletions HELP.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ On IP22/IP24, each bank is at most 128 MB. IP28 also supports 256 MB and
[IP28 512 MB banks](clanker/devices/ip28-512mb-banks.md). The table below describes
the IP22/IP24 extended layouts.

`banks` has room for eight entries; every machine today uses four, and the
rest must be 0. On the O2 each entry is the kit in a DIMM pair (32, 64, 128 or
256 MB), largest first: `[256, 256, 256, 256]` is 1 GB.

`banks` in `iris.toml` / iris-gui is applied only when you **Start** the VM.
Changing RAM while IRIX is running updates the config but not the live guest —
**Stop → change banks → Start**.
Expand Down Expand Up @@ -500,15 +504,16 @@ ignored. The checked-in `iris.toml` is a commented example of everything in this
```toml
# ── Top-level scalars (must come before any [section]) ───────────────────────

prom = "prom.bin" # PROM image; the embedded one is used if missing
nvram = "nvram.bin" # DS1386 NVRAM/RTC file (Indy). Use one per install.
prom = "prom.bin" # PROM image; the embedded one is used if missing (the O2 has none: its 4.18 image)
nvram = "nvram.bin" # DS1386 NVRAM/RTC file (Indy); the PROM's flash (O2). Use one per install.
nveeprom = "nveeprom.bin" # 93CS56 NVRAM EEPROM file (Indigo2 only)

# RAM bank sizes in MB: 0 (absent), 8, 16, 32, 64, 128; IP28 also 256/512.
# O2: the kit in each DIMM pair (32/64/128/256), largest first. Up to eight entries.
banks = [128, 128, 0, 0]

scale = 1 # window scale, kept across guest mode changes; --2x overrides
headless = false # no window, no REX3 (audio unaffected)
headless = false # no window, no graphics; the O2 boots on its serial console (audio unaffected)
no_audio = false # no HAL2 / cpal (graphics unaffected)
lock_aspect_ratio = true # false = free resize with letterboxing
mouse_scroll_pixels_per_line = 40
Expand Down
14 changes: 8 additions & 6 deletions clanker/devices/ip32-o2-bringup-log.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@

Status: history, 2026-09 to 2026-10. How the O2 was brought up, gate by gate,
with the dead ends. For the machine as it is, read [docs/o2-ip32.md](../../docs/o2-ip32.md);
the "Today" section below summarises it as of 2026-10-23, and the rest is the
the "Today" section below summarises it as of 2026-10-24, and the rest is the
journal, in order.

## Today (read this first)

The O2 runs as a machine like the others: `profile = "o2_ip32"` with an
`[o2]` section (PROM, flash, `ram_mb` or `dimms`, `disks` on controllers 0
and 1, `serial_port`, `graphics`, `mouse`, `net` and `forwards`,
`control_port`, `cpu_mhz`), started with `iris --config`. Its
devices are on the shared monitor (`monitor_port`, default 8888).
The O2 runs as a machine like the others: `profile = "o2_ip32"`, configured
by the shared keys (`prom`, `nvram` for the PROM's flash, `banks` as DIMM
kits, `[scsi.N]` on controllers 0 and 1, `serial_port_a`/`b`, `headless`,
`[network]`, `[clock] fixed_mhz`) with `[o2]` holding only `mouse`,
`control_port` and `arcs_fpu`; the old `[o2]` spellings of the rest are
folded in on load (2026-10-24). Started with `iris --config`. Its devices
are on the shared monitor (`monitor_port`, default 8888).

How it is put together now:

Expand Down
77 changes: 46 additions & 31 deletions docs/o2-ip32.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,27 @@ The O2 does not run in iris-gui yet; start it from the `iris` command line.

## Configure the machine

The O2 has its own `[o2]` section for what only it has. Its disks are the
same `[scsi.N]` tables as the other machines'; the Indy and Indigo2 top-level
keys `prom`, `nvram` and `banks` do not apply to it.
An O2 is set up with the same keys as the other machines; `[o2]` holds only
what the O2 alone has (`mouse`, `control_port`, `arcs_fpu`).

```toml
prom = "ip32prom.rev4.18.bin" # the O2 PROM (not built in); tried when prom is left unset
nvram = "flash.bin" # the PROM's flash, where setenv settings live
banks = [256, 256, 256, 256] # the kit in each DIMM pair, largest first: 1 GB
serial_port_a = 2291 # first serial port (the console when headless)
serial_log = "serial.log"

[machine]
profile = "o2_ip32"
cpu = "r10000" # or "r5000"

[o2]
prom = "ip32prom.rev4.18.bin"
flash = "flash.bin"
ram_mb = 1024
serial_port = 2291
serial_log = "serial.log"
control_port = 2293
forwards = [ { proto = "tcp", host_port = 2292, guest_port = 22 } ]

[[port_forward]]
proto = "tcp"
host_port = 2292
guest_port = 22

[scsi.1]
path = "irix6522.raw"
Expand All @@ -42,13 +46,21 @@ cdrom = true
```

Paths are relative to the directory iris runs in. Every key is listed in
[FEATURES.md](../FEATURES.md#o2).
[FEATURES.md](../FEATURES.md), the O2's own under [`[o2]`](../FEATURES.md#o2).

The PROM image is not built in: supply the O2 PROM (4.18 is the last
release) as `prom`. The O2 has no NVRAM chip; the PROM keeps its environment
(`setenv`) in flash. With `flash = "FILE"`, IRIS starts from FILE when it
exists and saves the flash back there whenever the guest writes it, so
settings survive a restart. The PROM image itself is never written.
release) as `prom`; when `prom` is left at its default, iris tries
`ip32prom.rev4.18.bin`. The O2 has no NVRAM chip; the PROM keeps its
environment (`setenv`) in flash, and `nvram` names the file that flash is
kept in between runs (`nvram.bin` unless set): IRIS starts from it when it
exists and saves the flash back whenever the guest writes it, so settings
survive a restart. The PROM image itself is never written.

Configs from before this layout set all of it in `[o2]` (`prom`, `flash`,
`ram_mb`, `dimms`, `disks`, `serial_port`, `serial_log`, `graphics`,
`cpu_mhz`, `net`, `forwards`). They still load: iris moves each onto the
shared key it stands for, says so once, and never writes them back. Move them
in the file to silence the note.

## CPU, memory and clock

Expand All @@ -58,10 +70,11 @@ settings survive a restart. The PROM image itself is never written.
through the PROM switches back.
- **R5000.** The full cache model throughout. Linux supports only R5000-class
O2s.
- `cpu_mhz` (default 180) sets the clock the PROM measures and reports; CP0
Count runs at half of it. R10000 O2s shipped at 175 and 195 MHz.
- `ram_mb` fits memory the usual way, largest DIMM kits first, up to 1024 MB.
`dimms = [128, 128]` gives the kit in each DIMM pair instead.
- `[clock] fixed_mhz` is CP0 Count, 90 MHz unless set; the PROM measures and
reports twice it as the CPU clock. R10000 O2s shipped at 175 and 195 MHz
(87.5 and 97.5), R5000s at 180 to 300.
- `banks` is the kit in each of the four DIMM pairs from A: 32, 64, 128 or
256 MB each, largest first, up to 1 GB. The default `[128, 128]` is 256 MB.

## Disks and CD-ROMs

Expand Down Expand Up @@ -100,19 +113,22 @@ will not match it.

## Console, keyboard and mouse

With `graphics = true` (the default) the PROM and IRIX use the graphics
console with a PS/2 keyboard, and `mouse` (default on) adds a PS/2 mouse.
With `graphics = false` the console is serial port 1.
With the graphics console (the default) the PROM and IRIX use a PS/2
keyboard, and `[o2] mouse` (default on) adds a PS/2 mouse. With
`headless = true` there is no keyboard, and the console is serial port 1.

`serial_port` serves the first serial port on TCP 127.0.0.1 (`telnet
127.0.0.1 PORT`); `serial_log` copies everything it sends to a file.
`serial_port_a` and `serial_port_b` serve the two serial ports on TCP
127.0.0.1 (8880 and 8881 unless set; `telnet 127.0.0.1 PORT`); `serial_log`
copies everything the first one sends to a file.

## Networking

The O2's Ethernet is on IRIS's NAT gateway, as on the other machines: the
The O2's Ethernet is on IRIS's NAT gateway, as on the other machines, and
takes the same settings: `nat_subnet`, `[nfs]`, `[[port_forward]]`,
`[network] mac` (the address in the 1-Wire ID chip) and `tftp_dir`. The
guest gets 192.168.0.2 by DHCP, with the gateway and DNS at 192.168.0.1.
`forwards` maps host ports to guest ports (same fields as `[[port_forward]]`).
`net = false` leaves the Ethernet unplugged.
`[network] mode = "off"` leaves the Ethernet unplugged; `pcap` is not
available on the O2 yet.

For a PROM network boot, set `[network] tftp_dir = "DIR"` and boot from the
PROM's command monitor with `boot -f bootp():FILE`, which loads FILE from DIR.
Expand All @@ -132,15 +148,14 @@ The monitor's machine commands work as on the other machines:
`iris --ci` starts the O2 for [iris-ci](../STORAGE.md) with its CPU stopped
and serial port 1 as the CI console: `iris-ci start`, `serial-send`,
`serial-wait`, `login`, `run` and `screenshot` work as on the other
machines, and so do `save` and `restore`. `rollback`, the scratch volume and
CD changes do not yet; they answer "not supported on this machine". Boot
with `graphics = false` so the PROM and the operating system use that
machines, and so do `save`, `restore`, the scratch volume and CD changes.
`rollback` does not yet; it answers "not supported on this machine". Boot
with `headless = true` so the PROM and the operating system use that
console.

## Known limitations

- No iris-gui support yet. Over iris-ci, no `rollback`, scratch volume or
CD changes.
- No iris-gui support yet. Over iris-ci, no `rollback`.
- The PROM cannot load a very large program from disk (it fails on a 16 MB
kernel); boot such a file over TFTP instead.
- PCI's byte-swapped view of memory is not modelled; every driver tested uses
Expand Down
4 changes: 3 additions & 1 deletion iris-gui/src/config_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::ram::{ram_summary, ram_presets};
#[derive(Clone, Copy, Debug, Default)]
pub struct MemoryUiContext {
pub running: bool,
pub started_banks: Option<[u32; 4]>,
pub started_banks: Option<[u32; iris::config::MAX_BANKS]>,
/// The CPU the running guest actually booted on, so a pending change is
/// shown as pending rather than as fact. `None` when nothing is running.
pub started_cpu: Option<CpuModel>,
Expand Down Expand Up @@ -938,6 +938,8 @@ fn show_network(
.selected_text(match cfg.network.mode {
NetMode::Nat => t!("config-net-mode-nat"),
NetMode::Pcap => t!("config-net-mode-pcap"),
// Only an O2 config can say this, and the GUI does not run one yet.
NetMode::Off => "off".to_string(),
})
.show_ui(ui, |ui| {
ui.selectable_value(&mut cfg.network.mode, NetMode::Nat, t!("config-net-mode-nat"));
Expand Down
Loading
Loading