From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by mx.groups.io with SMTP id smtpd.web11.7117.1625216102911514218 for ; Fri, 02 Jul 2021 01:55:03 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=CNG8L8yw; spf=pass (domain: redhat.com, ip: 216.205.24.124, mailfrom: lersek@redhat.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1625216102; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=DEPhQXLfEkTHPA6Dupm2ditQuaxTUEemkBgJ57lOC/w=; b=CNG8L8ywQxAKrOYM65cUqDehI4tuaMCLn589HiPDF8z48pbQI9rVNcf9EK7BytN0aYozvi 5qR3ELPbWAiLqmJIeE8PxCg0mHjF7NMcfuf1rbvQvd5pBtRPmUxrXGs/fa5s74SvTDrGdS aMtkfgt14FeIA0+njvMxtm/lRfXLs6k= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-123-TO2LfTjFMg6lhsmq-r3giQ-1; Fri, 02 Jul 2021 04:55:00 -0400 X-MC-Unique: TO2LfTjFMg6lhsmq-r3giQ-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id C1C0D804143; Fri, 2 Jul 2021 08:54:59 +0000 (UTC) Received: from lacos-laptop-7.usersys.redhat.com (ovpn-114-129.ams2.redhat.com [10.36.114.129]) by smtp.corp.redhat.com (Postfix) with ESMTPS id EEAD06267C; Fri, 2 Jul 2021 08:54:58 +0000 (UTC) Subject: Re: [edk2-devel] EFI_AUDIO_OUTPUT_PROTOCOL: assistance with VirtIO initialization To: devel@edk2.groups.io, harlydavidsen@gmail.com References: From: "Laszlo Ersek" Message-ID: <321680e5-8278-bd99-b4cb-51cea8ae423d@redhat.com> Date: Fri, 2 Jul 2021 10:54:57 +0200 MIME-Version: 1.0 In-Reply-To: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=lersek@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit 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