Repository navigation
serial: one 16550A core for the O2 and Octane UARTs - #359
Merged
Merged
Conversation
…le wiring
SerialBackend, the TCP, CI, tee and null backends lived in the Z85C30's
file, so the O2's MACE UARTs and the Octane's IOC3 imported them from a
chip they do not contain. Move them to dev/serial_host.rs.
The O2 and Octane constructors each carried ~40 lines choosing the CI or
TCP console, teeing it to the serial log and binding the second port.
console_backends() does that once; open_log() opens the log (fresh per
boot for those two, appended for the Indy as before) and is the Indy's
only use of the helper, since its console is the Z85C30's existing
channel B listener.
No guest-visible change. Log messages now carry the machine name
("Indy" for the Indy's two), and the Octane's port-unavailable message
gains the O2's "is another iris using it" hint.
The O2's 16550 was "just enough to be written to": the line status always said ready, the interrupt cause was a guess from the enable bits, there was one byte of receive queue with no overrun, and loopback only reached the modem status. The Octane's IOC3 carried a separate, fuller 16550 of its own. ns16550.rs is now a port of QEMU's hw/char/serial.c (MIT, notice kept): the register file, the 16-byte receive FIFO and its trigger levels, interrupt causes in priority order, the character timeout, line and modem status, loopback and overrun. Transmit stays instant, with no baud pacing; the module doc lists every place it departs from QEMU. The MACE shell (the lane decode, interrupt line and monitor) moves to mace_uart.rs, and the serial DMA engine keeps its own code, taking its characters from the core through dma_write, dma_read and dma_modem_control. Snapshots: each O2 UART now saves the core's state, so the schema version goes to 5 and an O2 snapshot from before is refused. Nothing else changed shape. Guest-visible changes on the O2 serial: the FIFO, the trigger levels and the timeout work as on a 16550A; the receive-data interrupt waits for the trigger level; the line status reports overruns and the transmit interrupt follows the holding register.
The IOC3 carried its own 16550 next to the O2's. It now wraps ns16550.rs and keeps only what the chip adds around it: the pre-divider on the scratch register, the auto-flow bit in modem control, the factory-test writes to line and modem status, and the register layout with its ring DMA. The pre-divider sets the core's reference clock, so the receive timeout follows it. Ported from hw/misc/sgi-ioc3.c in jamesbraid/qemu-sgi-origami. The register-level tests written before the swap pass unchanged. To keep one of them (an empty receive register reads zero, as both earlier models answered) the core returns zero rather than QEMU's stale character; the module doc lists it. Guest-visible changes: with the FIFOs on, the receive interrupt waits for the trigger level and characters below it raise the timeout cause after four character times; toggling the FIFO enable flushes both FIFOs.
jamesbraid
force-pushed
the
serial-16550
branch
2 times, most recently
from
October 30, 2026 03:20
bccf291 to
1378781
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The O2's 16550 was "just enough to be written to", and the Octane's IOC3 had a separate, fuller 16550 of its own. Both now run on one 16550A core in
ns16550.rs, a port of QEMU'shw/char/serial.c(MIT, notice kept).z85c30.rsintoserial_host.rs, with the console wiring the O2 and Octane each repeated done once.Transmit stays instant, with no baud pacing. The Indy's Z85C30 is unchanged.
The O2 UARTs now save the core's state, so the snapshot schema goes to v5 and older O2 snapshots are refused.
Tested on the O2 and Octane (serial console login, and the IOC3 register tests from before the swap pass unchanged), with no change in boot time.