[edk2-devel] EFI_AUDIO_OUTPUT_PROTOCOL: assistance with VirtIO initialization

Laszlo Ersek lersek at redhat.com
Fri Jul 2 08:54:57 UTC 2021


On 07/01/21 01:01, Ethin Probst wrote:
> Hi all,
> So Leif and I have been working on USB Audio but we've run into a snag. We've encountered a problem -- neither of us knows enough about USB to figure out how to get the class-specific AC interface descriptors, and those contain vital information that I need to be able to control the audio device. The audio specification was quite useless. So I have two projects running in parallel: the USB audio one and the VirtIO audio (We managed to get the virtio-snd patchset in qemu and I've got a built version of it over here and, though its not a fully working implementation, as long as I get something -- no matter how bad it sounds -- I'll be happy). Whichever project we get working first is the one we move forward with.
> The VirtIO sound device specification contains four virtqueues: the control queue for controlling the device; the event queue for receiving notifications from the device; the tx queue for transmitting audio data to the device; and the rx queue for receiving audio data from the device. Thus far I've been following the VirtioRngDxe code as a guide on how to get a VirtIO device initialized using the VirtioLib in OVMF, but I've reached an impasse regarding the queues and descriptors.
> 
> The VirtioRngDxe DXE uses a single descriptor and a single queue for operation. However, the RNG device works vastly differently to the audio device and is far simpler. The virtio-snd specification says that, to initialize the device, I must (copied from the spec):
> 
> * Configure the control, event, tx and rx queues.
> * Read the jacks field and send a control request to query information about the available jacks.
> * Read the streams field and send a control request to query information about the available PCM streams.
> * Read the chmaps field and send a control request to query information about the available channel maps.
> * Populate the event queue with empty buffers.
> 
> Steps 2, 3, 4, and 5 are a bit confusing and raise some questions:
> 
> 1. Does the device automatically send notifications in the event queue about the jacks, streams, and channel maps, or do I have to explicitly ask for them?
> 2. How many buffers would we need to populate the event queue with, and what VirtioLib function (if any) specifically accomplishes that?

What you describe here makes the virtio-sound device the most complex
virtio device that OVMF has ever had any interest in. The only driver
you can use as an example is VirtioNetDxe. VirtioRngDxe is about the
simplest virtio device / driver, but for an example here, you need to be
looking at the opposite end of the spectrum.

For the duplex communication, please refer in particular to
"OvmfPkg/VirtioNetDxe/TechNotes.txt".

In virtio, requests are always created by the driver (= the guest), and
requests are always completed by the device (= the host). Therefore, for
asynchronous host-to-guest communication, the guest has to fully
pre-populate the affected queues with requests, and when host actions
arrive (technically presented as "request completions"), the guest has
to process those "completions" and re-populate the affected queue at
once to the brim.

VirtioLib provides a number of utility / convenience functions, for
various areas / actions. However, the VirtioPrepare(),
VirtioAppendDesc(), VirtioFlush() functions in particular are
inappropriate for your use case. Those helper functions implement a
simple, synchronous request-response pattern, building and submitting a
single descriptor chain, and blocking until the host reports that chain
processed. These functions exist because this simple pattern is suitable
for most of the virtio drivers (VirtioBlkDxe, VirtioFsDxe, VirtioGpuDxe,
VirtioRngDxe, VirtioScsiDxe). The reason being that the UEFI protocols
implemented all support the same, simple, synchronous pattern. These
functions are however not helpful for actual async communication, so
they are not used in VirtioNetDxe -- VirtioNetDxe does its own queue and
descriptor chain management. (It's documented in detail in "TechNotes.txt".)

To be honest, I would recommend abandoning the virtio-sound path for
now. The virtio programming will eat up a huge amount of your time, and
that's not what you want to be concentrating on.

I had had no previous experience with either audio programming or the
virtio-sound device itself; TBH I didn't expect this level of complexity
(in particular, based on your description, that *all four* queues would
have to be initialized, no questions asked). The virtio drivers in OVMF
are always kept as simple as possible, only the inevitably necessary
queues are initialized (and the devices are configured accordingly), and
only the simplest communication patterns are used. These drivers are not
OS drivers; what they need to do is "facilitate booting".

Example: the BlockIo protocol only supports synchronous requests,
whereas the BlockIo2 protocol supports asynchronous requests as well.
Technically speaking, virtio is fully capable of implementing the
asynchrony of BlockIo2, so (e.g.) a BlockIo2 protocol implementation on
top of virtio-blk would be possible. But why bother? It just complicates
the code a whole lot, and booting an OS with just BlockIo is
sufficiently fast already. VirtioNetDxe *must* be different however,
because the UEFI-level abstraction, SimpleNetworkProtocol (SNP), is
truly asynchronous itself.

If you can design a UEFI protocol for just sound *output* that lets you
get away with synchronous (blocking) UEFI protocol member function
calls, then you *might* be able to ignore most of the virtio-sound
complexity, and use the existent descriptor chain management functions
in VirtioLib. You could perhaps ignore the "event" and "rx" queues
altogether, and use the synchronous VirtioLib functions for both
"control" requests and actual audio output ("tx"). I can't tell.

Thanks
Laszlo



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#77443): https://edk2.groups.io/g/devel/message/77443
Mute This Topic: https://groups.io/mt/83904983/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-





More information about the edk2-devel-archive mailing list