mirror of
https://github.com/RhapsodiOS/RhapsodiOS.git
synced 2026-11-03 22:01:40 -07:00
[GH-ISSUE #79] ppc: PPCSerialPort finds no device on QEMU g3beige (OpenBIOS lists one SCC interrupt, not three) #70
Labels
No labels
bug
documentation
enhancement
enhancement
good first issue
help wanted
help wanted
pull-request
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
github-starred/RhapsodiOS#70
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @raynorpat on GitHub (Oct 23, 2026).
Original GitHub issue: https://github.com/RhapsodiOS/RhapsodiOS/issues/79
On QEMU
g3beige(Gossamer, booted withvm/ppc-guest.py start --machine g3beigeon branchppc-qemu),/etc/startup/0700_Devicesreports:so the Beige G3 guest has no serial ports.
Cause
OpenBIOS gives the SCC channels a single interrupt on g3beige:
A real old-world Mac lists three interrupts per channel: the SCC itself, then its TX and RX DBDMA interrupts.
PPCSerialPort -initFromDeviceDescription:refuses any node without exactly three (wrong number of interrupts), and so does the stock 1.2v3PPCSerialPort_reloc. ItsgetHandler:level:argument:forInterrupt:hands outPPCSerialISRfor interrupt 0,PPCSerialTxDMAISRfor 1 andPPCSerialRxDMAISRfor 2.This is a gap in QEMU's old-world firmware, not a driver bug. On
mac99the channels carry all three (MPIC sources 0x25/0x04/0x05 for ch-a), and serial works both ways there: host-to-guest and guest-to-host over/dev/cuaawere checked with a TCP serial backend. QEMU's ESCC has no DBDMA behind it, so the DMA interrupts never fire there either.Proposed fix
Let our
src/drivers-ppc/input/drvPPCSerialPortaccept a channel with only the SCC interrupt and run without the DMA ISRs, as a labelled divergence from 5.6. Then build it and install it over the stockPPCSerialPort_relocin a g3beige guest to test.Done when the g3beige guest registers
PPCSerialPort0 [ch-a]and/dev/cuaapasses data both ways over QEMU's serial backend.Related: #63.
@raynorpat commented on GitHub (Oct 24, 2026):
Status: this is blocked on finishing the PPCSerialPort reconstruction.
Every serial test so far ran Apple's stock
PPCSerialPort_relocfrom the 1.2v3 disk. Our source undersrc/drivers-ppc/input/drvPPCSerialPorthas never been built:src/drivers-ppc/reconstruction/PPCSerialPort/findings.mdsays so ("nothing was compiled"). Trying to build it now shows that:It doesn't compile. The first pass stops on 27 errors, all syntax:
asmclobber lists written as:::, which the old ObjC front end reads as a::token;IOPPCDeviceDescriptionandIOMemoryRange.Semantic errors will follow once these are fixed.
It isn't functional. About 54 places are placeholders or guesses rather than decompiled code:
nextEventreturns nothing;-freeare stubbed;thread_wakeupis stood in for.Done on master (merged with
ppc-qemuin3c6f465d3), from6ef37d552:apk/pkginfowas a copy of the bus mouse driver's (pkgname = drvbusmouse). It is nowdrvppcserialport(version 5), so rbuild can build it as its own package. It builds against a repository that also holds the ppcdrivertools/driverkit/kernloadapks.-initFromDeviceDescription:accepts a channel with just the SCC interrupt as well as the usual three, as a labelled divergence from 5.6. Its TX/RX DMA handlers only count interrupts, so nothing is lost without them.Next:
tools/binrecon/out/ppcserialport-ppc.PPCSerialPort_relocon QEMU mac99 and match the stock driver:/dev/cuaaboth ways over a TCP serial backend. The test harness I used (sertcp.py+rxtest.py) is local scratch, not in the repo yet: it runsvm/ppc-guest.py startwith-serial tcp:...and talks to/dev/cuaaover telnet.@raynorpat commented on GitHub (Oct 24, 2026):
The PPCSerialPort reconstruction is finished on branch
ppcserial-finish(c5d765b43, local, not merged yet). On QEMU g3beige the driver now registers both channels and passes data both ways.How it was rebuilt. The old draft was replaced with source written from IDA's decompilation of the 1.2v3
PPCSerialPort_reloc. Calls were resolved through the object's relocation table, and the code is typed with thePortstruct taken from the binary's own ivar encoding.PPCSerialPort : IODirectDevice <PortDevices>, instance size 664, withPortat offset 296 andportat 660.nextEvent,enqueueEvent:anddequeueEvent:really are stubs.Build fixes. The project used a made-up
tool.make/Makefile.driver_preamblesetup that produced PIC code linked-static. It now uses the samekernelserver.make/driver.makeMakefiles as the other ppc drivers, plus amovehelpno-op, since the bundle has no help.Divergences from 5.6, each marked in the source:
PPCSerialISRno longer closes the channel when its 100-poll budget runs out. QEMU's ESCC empties its transmitter as fast as it's fed, so the stock driver shut the port after 101 bytes and then spun inenqueueData:. The stock binary does exactly this on QEMU.enqueueData:/dequeueData:report the whole transfer intransferCount, not just the last chunk.dequeueData:resumes the sender with XON; the binary queues XOFF.RemovefromQueuechecks its bound before taking a byte. The binary writes one byte past the buffer and drops one when more is queued than requested.Tested on QEMU with the master kernel and the guest's serial port on a TCP socket:
PPCSerialPort0 [ch-a]/1 [ch-b]No Such Device)/dev/cuaahost → guest, guest → hostKnown limit. Receive bursts larger than about 800 bytes,
RXStats.HighWater, stop when the sender ignores XOFF: ours took 1,020 bytes, stock 935 while flooding XOFF. Stock has the same limit, and a sender that honours XON/XOFF shouldn't hit it. Not hardware-tested.@raynorpat commented on GitHub (Oct 24, 2026):
Merged into master locally as
c5d765b43(not pushed yet). The receive-burst limit noted above, about 800 bytes when the sender ignores XOFF, is shared with the stock driver and left as is.