Repository navigation
Audio leaves soundserver for an hda driver per controller; the matcher takes any prog-if - #953
Conversation
…r takes any prog-if #950 left three defects on main, each measured: - GitHub's guest job red `hda_drives_its_codec_through_its_claim`: soundserver configured the path (`volume_step` exited 0 with the codec's readbacks) but said so between the ready marker and the job's window, which neither capture piece holds. The row now awaits the line on the console instead of reading the boot log. - The T14 matched nothing: its HDA function is `00:1f.3 [0403] 8086:a0c8 prog_if=80` (the readback's enumeration line), and `pci:04:03:00` named prog-if 00 only. `lib/manifest`'s grammar gains `pci:CC:SS:*`, every programming interface of a subclass; HD Audio's 00 and 80 are one register model. - The AMD bench's two HDA functions made the single-process row's start refused. By the lifecycle ruling (stage 3 of issues/a-device-function-is-driven-from-its-arrival-to-its-end.md), audio's driver leaves the shared service: `hda` (system/hda) is a `drives` row on `pci:04:03:*`, one process per controller. Each resets its controller, walks its own codecs and finds its output (`toyos-hda`, moved to system/hda/driver; `choose` over several controllers is gone, each driver decides for its own), and a driver that reaches none ends by name. One that does offers it on soundserver's new `sound-output` port (`toyos-sound-output`, every frame decoded and refused there): soundserver lends it the ring of periods, which the driver maps through its claim and points its descriptor list at, and the stream connection carries start, stop and the periods played with the claim's interrupt times. The master's requests go to the driver and its codec readback comes back to the volume port. soundserver is the null sink until an output is offered and plays to it once no stream is open, so a stream never changes device under it; virtio-sound stays driven inside soundserver (stage 3's next item). The tone jobs' master now fails by name on a soundserver with no master rather than on a message number. QEMU: `hda_plays_to_the_controller_that_reaches_an_output` boots two ich9-intel-hda, the first with no codec: its driver plays nothing, soundserver plays to the second's, and `volume_step` steps that codec. Records: the lifecycle track's stage 3, the drivers track's HDA item, the jack-detection track's paths; filed cpal's close bound (issues/cpals-close-bound-is-one-ring-of-device-time.md) and the host-CI red that is main's too (issues/the-llvm-environment-test-dies-where-git-is-the-xcode-shim.md). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Bench at aa7767b (same image on both, sha in /Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/agents/hda/r2/metal): T14 3/3 PASS (hda_tone, hda_tone_resampled, hda_volume_step). AMD bench 0/3: both HDA controllers (03:00.1, 03:00.6) are behind the bus-3 bridge whose window is full, so pcidev keeps BAR 0 where firmware put it and refuses the claim ( |
Review of #953 at
|
…aster requests bounded
- A reader a ring behind holds reports that overlap ({0..6} then
{7, 0..5}); `combine` makes any overlapping, or non-run, union a whole
lap, which the mix loop counts as the drain it is. A report that is no
run of the ring, a frame the stream protocol has not, or a hang-up now
ends the device loop (`Backend::ended`) instead of soundserver: the mix
thread ends the streams it held, tells the control thread on a pipe of
its own, and soundserver is the null sink again. A control-connection
violation drops the driver the same way and sends `MixCommand::Detach`.
A stream opened against an output since gone carries that output's
generation and is ended where it reaches another's loop. A report read
while the engine is stopped is dropped.
- `Offer::decode` bounds the ring to the mixer's deepest pipeline (16) and
a period to `MAX_PERIOD_BYTES` (16 KiB), before soundserver allocates
the lent ring from them.
- The volume port forwards one master request at a time (`volume::Relay`):
the holder's next is not read, nor its connection watched, until the
answer, which goes only to the connection that asked. A driver whose
connection takes no request is answered unavailable by name.
- Dropped the llvm issue; #952's
`issues/the-llvm-environment-test-breaks-git-on-macos.md` is the record.
- The `hda` driver's ring comment, `Phase::Playing`'s master as a bool, and
the jack-detection track's stale line.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Round 1 at
Suggestions:
Checks:
|
Re-review of #953 at
|
… reports carry their run - The `hda` driver waits for soundserver's answer to its offer through its poller, for at most `OFFER_ANSWER` (30 s, a hang ceiling: soundserver answers in the pass that reads the offer). Past it the driver ends by name and gives the controller back. - `MSG_START` names a run and every `Played` echoes it; soundserver drops a report of another run than its engine's now, so one the driver sent before reading a stop cannot be taken as the next run's. - Deleted the relay tests that could not fail for the defects they were named after; the one-in-flight rule and the asker filter are `serve`, `answer` and the control loop's watch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Round 2 at
Checks:
The run counter changes the start/report protocol that the bench rows exercise, so I staged |
Follow-up on #953 at
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#953 moved the HDA driver out of soundserver into system/hda. The modify/delete conflict on system/soundserver/src/hda.rs resolves to the deletion: this branch's one hunk there (the description read through toyos_pci_claim::describe) is carried to the new driver. The new driver is a pci-claim caller main added, so it takes this branch's rule rather than a second path: its description is toyos_pci_claim::describe, ended by name instead of an expect, and the ring soundserver lends is mapped through toyos_pci_claim::lend, since KernelRefused::on is private here. lend names the region's own refusals Why::Unlendable (not ordinary memory, already lent, or sent without MAP): those are the peer's words about its region, not the claim's, so Why::of's panic on an unexpected word would misreport them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Draft. Finishes the audio migration that #950 started; #950 was merged early (a15ac4d). Audio is broken on both benches on main until this lands: on the T14 soundserver falls back to the null sink, and on the AMD bench soundserver does not start. main's guest job is also red on #950's QEMU row.
Bench at aa7767b: T14 3/3 PASS. AMD 0/3, because both HDA controllers sit behind the full bus-3 bridge, which P1 (#947) fixes. Review round 1 at 66776de is below.
Problem (measured)
hda_drives_its_codec_through_its_claimnever sawsoundserver: hda path configured, yetvolume_stepexited 0 with the codec's readbacks. So the path was configured; soundserver just printed the line between the ready marker and the job's window, and the test captures neither of those spans. This was a gap in what the harness captures, not a TCG speed problem or a fixed timeout.00:1f.3 [0403] 8086:a0c8 prog_if=80, read from the readback's enumeration line.pci:04:03:00names programming interface 00 only.03:00.1GPU display audio,03:00.6analog). A device function is claimed by its arrival, and a drives row has one process per function (lifecycle stage 1.2) #926 refuses to start a single-process row whose matcher names two functions.master.rs:12("message 4").Change
lib/manifest:pci:CC:SS:*matches every programming interface of a subclass (PciMatch::prog_if: Option<u8>). An overlap is still decided from the text alone. HD Audio's 00 and 80 are the same register model.hda(system/hda): adrivesrow onpci:04:03:*, one process per controller, as in stage 3 ofissues/a-device-function-is-driven-from-its-arrival-to-its-end.md. Each process resets its own controller, walks its codecs and finds its output;toyos-hdamoved tosystem/hda/driver. The multi-controllerchooseis gone, because each driver decides for its own controller. A driver that reaches no output ends by name.toyos-sound-output(system/soundserver/output): the protocol between soundserver and its output drivers, on soundserver's newsound-outputport. It is pure, and every frame is decoded and refused there. A driver offers its rate, channels, ring shape and master. soundserver lends it the ring of periods, and the driver maps that ring through its claim and points its descriptor list at it. A second connection carries start, stop and each period played, stamped with the claim's interrupt times. Master requests go to the driver, and its codec readback comes back to the volume port. The driver is a client of soundserver's port and serves no name, per the track's ruling.Tests and evidence
Evidence: https://github.com/ToyOSOrg/evidence/tree/f6b1654005d426e21b33932063e231d97fa0ecea/hda-drivers
cargo run -- --ci hostdescription)llvm::tests::the_caller_s_environment_reaches_neither_the_build_nor_the_key, which is also red on origin/main 0e6716f (exit 101); recorded by #952'sissues/the-llvm-environment-test-breaks-git-on-macos.mdcargo run -- --build-only,--arch aarch64hda_plays_to_the_controller_that_reaches_an_outputtestcasesstaged forhda_tone,hda_tone_resampled,hda_volume_stepProfile::MetalTwoHda: twoich9-intel-hda, the first with no codec). This needs a guest because it involves three processes and two claims behind a remapping unit. Both drivers start: the first ends withplays nothing: … no codec, the second offers, and soundserver plays to it.volume_stepthen steps that codec. The row waits for the console line rather than reading the boot log. It replaces soundserver drives the HDA function whole through a pci claim; the kernel drives no audio #950's one-controller row, which this boot covers. It runs on q35 only, becausevirthas no unit to put the functions behind.audio_tonepassed through the driver process, with 699 completions in a 2 s window andunderruns=0. The tone rows stay on the benches because of cpal's close bound (issues/cpals-close-bound-is-one-ring-of-device-time.md, owner: the cpal fork).Review round 1 (66776de)
Evidence: https://github.com/ToyOSOrg/evidence/tree/74a5501d83ca5430ece25e9a0412195554c79166/hda-drivers/review-1
cargo run -- --ci hostaudio_tone0, underruns=0testcasesstaged, T14 only (the tone jobs' soundserver path changed); AMD waits for P1Review round 2 (16bb9e7)
MSG_STARTcarries a run number that eachPlayedreport echoes, and soundserver drops reports of any other run.--ci host86/86 green; QEMU two-controller row passes; exploratory tone exit 0 withunderruns=0; T14 restaged. Bench at 66776de: T14 3/3 PASS.Evidence: https://github.com/ToyOSOrg/evidence/tree/ec8de94003235cd61f798ad35fac05157a1ef244/hda-drivers/review-2
Decisions to check
gone, and hot-plug are stage 3's remaining items and stage 2's, recorded on the track.syscap = ["rt"], the existing capability), because its interrupt is a period's end. This uses an existing mechanism and adds none.Risks
testcasesboot the audio jobs run after the wake jobs, seconds after boot. The judges require theplaying toline to come before the job's spawn.🤖 Generated with Claude Code