Skip to content

irq: an InterruptController trait, with the Indy and Indigo2 interrupts on it - #261

Merged
techomancer merged 10 commits into
techomancer:mainfrom
atomchild411:irq-controller
Oct 21, 2026
Merged

techomancer merged 10 commits into
techomancer:mainfrom
atomchild411:irq-controller

Conversation

@atomchild411

@atomchild411 atomchild411 commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

irq: an InterruptController trait, with the Indy and Indigo2 interrupts on it

Each Indy/Indigo2 device that raises an interrupt had its own callback trait or held the whole Ioc to set one line. This adds src/irq.rs, one shape for every interrupt, and moves IP22/IP24/IP28 onto it. As discussed, it is the base for the O2: its CRIME and MACE controllers will implement the same trait, so devices see one interface on every machine.

The trait

pub trait InterruptController: Send + Sync {
    fn set_line(&self, line: u32, level: bool);
}
pub struct IrqLine { /* controller + input */ }   // IrqLine::set(level)

A device holds an IrqLine and drives it to its level. The controller decides what the level means: a status bit behind a mask, an input ORed with others, or a cascade further up.

The changes, one device per commit

  • IOC is a controller. Each IocInterrupt is a line, numbered in declaration order; Ioc::irq_line(source) hands one out. set_interrupt runs the same code as before (now IocState::set_source).
  • HPC3 INTSTAT is a controller: a line per INTSTAT bit. A SCSI channel's chip and DMA bits are ORed onto its IOC line. A chip-INT ack still settles the paired PDMA half, as Hpc3Irq did. The SEEQ's level still goes to Ethernet on its own, not ORed with the Ethernet DMA bits.
  • These now hold IrqLines: the Z85C30, the 8042, VINO, both WD33C93As and their PDMA channels, the SEEQ, the MC's GIO DMA engine, Ultra64, MGRAS (FIFO, general and retrace) and REX3 (VV_INT_N, FIFO_INT_N).
  • Gone: IrqCallback, Ps2Callback, VinoIrq, ScsiCallback, SeeqCallback, PdmaCallback, the REX3 vblank/FIFO closures, and the IocIrqLine, Hpc3Irq, EnetSeeqIrq and VinoIrqAdapter adapters.
  • The machine now hands MGRAS and REX3 the IOC lines their slot is wired to, instead of each device picking its own sources.
  • Constructors that took a callback or the Ioc now take the line(s): Z85c30::new*, Ps2Controller::new, Wd33c93a::new*, Seeq8003::new/with_config, Ultra64::new, Mgras::new; MemoryController::set_ioc is now set_dma_irq, and REX3's setters are set_vblank_irq/set_fifo_full_irq. REX3's field names are unchanged, since docs and the lock diagnostics use them.

Behaviour is meant to be identical: the same bits, the same ORs, the same lock order. Left as they are, because they are not plain levels: the 8254 timers (latched, cleared by TMR_CLR), GR2's retrace (a rising edge acked IOC-side, plus the EXT_IO status), and the IOC's output to the CPU's Cause bits.

Tests

  • New unit tests: every IOC source is a line, driving what set_interrupt drives; INTSTAT ORs a SCSI channel's halves, a chip ack settles the DMA half, and the SEEQ's level reaches Ethernet as it is; the 8042's line follows its receive queue; the SCC test now uses the shared LevelProbe.
  • cargo test --lib: all pass, apart from breakpoints_can_be_set_while_running_and_report_their_hit and udp_fragmented_both_ways, which fail the same way on main here.
  • Built in the three CI configurations.
  • Booted windowed (with the ps2 PR) on every graphics board each machine takes. On each one: hinv, a disk read, the CD (mediad), audio playback, ping to the gateway, X, a keyboard login to the desktop, and a clean shutdown.
Machine Boards Result
Indy (IP24, R4400) Newport, dual-head Newport, XZ pass
Indigo2 IP22 (R4400) Newport, XZ, Extreme pass
Indigo2 IP28 (R10000) Solid, High, Max IMPACT pass
Indigo2 IP22 (R4400) Solid, High, Max IMPACT PROM panic, identical on main (see below)

Extreme's desktop and the dual-head Indy's head 0 were also compared with main pixel by pixel: identical.

The IP22 IMPACT rows: with Solid, High or Max IMPACT on an R4400 Indigo2, the PROM prints "NVRAM checksum is incorrect: reinitializing" and then takes a UTLB miss at 0x10c (EPC 0x9fc36988), before IRIX loads. main does exactly the same with the same disk and NVRAM, so those three couldn't be tested here. The same install booted on IMPACT on 2026-10-01.

Found on the way, not changed here

These are behaviour this PR keeps as it was, filed as issues:

🤖 Generated with Claude Code

atomchild411 and others added 10 commits October 20, 2026 21:29
`InterruptController::set_line(line, level)` is what interrupt lines lead
into; an `IrqLine` is one input of one controller, which a device drives
to its level. One shape for every device's interrupt, instead of a
callback trait per device.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each IocInterrupt is a line, numbered in declaration order. Ioc and the
lines from `Ioc::irq_line` drive the same code `set_interrupt` always
ran, now `IocState::set_source`. Nothing uses the lines yet; the devices
move over one at a time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Its interrupt goes to the IOC's Serial line instead of through its own
IrqCallback trait, which goes. The level is the same: either channel's
pending bits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Its interrupt goes to the IOC's KbMouse line instead of through its own
Ps2Callback trait; that trait and the IOC's IocIrqLine adapter go.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The IOC's VideoVsync line, from `Ioc::irq_line`, replaces the VinoIrq
trait and the machine's adapter for it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ines

Each INTSTAT bit is a line. A SCSI channel's chip and DMA bits are ORed
onto its IOC line, and a chip-INT ack still settles the paired PDMA
half; the SEEQ's level goes to the IOC's Ethernet line as before, not
ORed with the Ethernet DMA bits. The WD33C93A, SEEQ 8003 and PDMA
channels hold IrqLines; ScsiCallback, SeeqCallback, PdmaCallback and the
Hpc3Irq/EnetSeeqIrq adapters go. Same bits, same lock order.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The MC held the whole IOC to raise and clear one interrupt; it now holds
the IOC's McDma line (`set_dma_irq`).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
It held the whole IOC for one line; it now holds the IOC's GioExp0 line.
Its three sources still share that line with no OR between them, as
before (an ack of one drops the line while another may be pending);
that is a separate fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The IMPACT board picked its IOC sources itself (the Indigo2 graphics
slot's FIFO, general and retrace); the machine now hands it those three
lines, so the board no longer knows which slot it is in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The machine hands REX3 the IOC lines its slot is wired to
(`set_vblank_irq`, `set_fifo_full_irq`) instead of closures that called
the IOC; the vblank trace instant moves to where REX3 raises the line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@techomancer
techomancer merged commit 88ff56c into techomancer:main Oct 21, 2026
7 checks passed
belikh added a commit to irix7/iris that referenced this pull request Oct 24, 2026
Upstream's README carries the whole contract: small PRs, one fix per PR,
preferably one commit, bisectable. Observed practice matches it — of the
last 25 merged PRs nearly all are a single commit touching one to four
files, median merge latency is hours, and almost nothing is closed
unmerged.

Add the policy, the one-commit consequence for each unit, and the
coordination notes for the contributors whose work these PRs build on
(techomancer#266, techomancer#265, techomancer#279/techomancer#283, techomancer#261, techomancer#253).

Credit: none of this is derived from upstream; the analysis is the
fork's.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants