]> git.ipfire.org Git - thirdparty/qemu.git/blame - hw/audio/virtio-snd.c
hw/audio/hda-codec: reenable the audio mixer
[thirdparty/qemu.git] / hw / audio / virtio-snd.c
CommitLineData
2880e676
MP
1/*
2 * VIRTIO Sound Device conforming to
3 *
4 * "Virtual I/O Device (VIRTIO) Version 1.2
5 * Committee Specification Draft 01
6 * 09 May 2022"
7 *
8 * <https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html#x1-52900014>
9 *
10 * Copyright (c) 2023 Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
11 * Copyright (C) 2019 OpenSynergy GmbH
12 *
13 * This work is licensed under the terms of the GNU GPL, version 2 or
14 * (at your option) any later version. See the COPYING file in the
15 * top-level directory.
16 */
17
18#include "qemu/osdep.h"
19#include "qemu/iov.h"
20#include "qemu/log.h"
21#include "qemu/error-report.h"
22#include "include/qemu/lockable.h"
23#include "sysemu/runstate.h"
24#include "trace.h"
25#include "qapi/error.h"
26#include "hw/audio/virtio-snd.h"
27#include "hw/core/cpu.h"
28
29#define VIRTIO_SOUND_VM_VERSION 1
30#define VIRTIO_SOUND_JACK_DEFAULT 0
d8d64acb 31#define VIRTIO_SOUND_STREAM_DEFAULT 2
2880e676
MP
32#define VIRTIO_SOUND_CHMAP_DEFAULT 0
33#define VIRTIO_SOUND_HDA_FN_NID 0
34
18a75281
MP
35static void virtio_snd_pcm_out_cb(void *data, int available);
36static void virtio_snd_process_cmdq(VirtIOSound *s);
37static void virtio_snd_pcm_flush(VirtIOSoundPCMStream *stream);
d8d64acb 38static void virtio_snd_pcm_in_cb(void *data, int available);
18a75281 39
eb9ad377
MP
40static uint32_t supported_formats = BIT(VIRTIO_SND_PCM_FMT_S8)
41 | BIT(VIRTIO_SND_PCM_FMT_U8)
42 | BIT(VIRTIO_SND_PCM_FMT_S16)
43 | BIT(VIRTIO_SND_PCM_FMT_U16)
44 | BIT(VIRTIO_SND_PCM_FMT_S32)
45 | BIT(VIRTIO_SND_PCM_FMT_U32)
46 | BIT(VIRTIO_SND_PCM_FMT_FLOAT);
47
48static uint32_t supported_rates = BIT(VIRTIO_SND_PCM_RATE_5512)
49 | BIT(VIRTIO_SND_PCM_RATE_8000)
50 | BIT(VIRTIO_SND_PCM_RATE_11025)
51 | BIT(VIRTIO_SND_PCM_RATE_16000)
52 | BIT(VIRTIO_SND_PCM_RATE_22050)
53 | BIT(VIRTIO_SND_PCM_RATE_32000)
54 | BIT(VIRTIO_SND_PCM_RATE_44100)
55 | BIT(VIRTIO_SND_PCM_RATE_48000)
56 | BIT(VIRTIO_SND_PCM_RATE_64000)
57 | BIT(VIRTIO_SND_PCM_RATE_88200)
58 | BIT(VIRTIO_SND_PCM_RATE_96000)
59 | BIT(VIRTIO_SND_PCM_RATE_176400)
60 | BIT(VIRTIO_SND_PCM_RATE_192000)
61 | BIT(VIRTIO_SND_PCM_RATE_384000);
62
2880e676
MP
63static const VMStateDescription vmstate_virtio_snd_device = {
64 .name = TYPE_VIRTIO_SND,
65 .version_id = VIRTIO_SOUND_VM_VERSION,
66 .minimum_version_id = VIRTIO_SOUND_VM_VERSION,
67};
68
69static const VMStateDescription vmstate_virtio_snd = {
70 .name = TYPE_VIRTIO_SND,
71 .minimum_version_id = VIRTIO_SOUND_VM_VERSION,
72 .version_id = VIRTIO_SOUND_VM_VERSION,
73 .fields = (VMStateField[]) {
74 VMSTATE_VIRTIO_DEVICE,
75 VMSTATE_END_OF_LIST()
76 },
77};
78
79static Property virtio_snd_properties[] = {
80 DEFINE_AUDIO_PROPERTIES(VirtIOSound, card),
81 DEFINE_PROP_UINT32("jacks", VirtIOSound, snd_conf.jacks,
82 VIRTIO_SOUND_JACK_DEFAULT),
83 DEFINE_PROP_UINT32("streams", VirtIOSound, snd_conf.streams,
84 VIRTIO_SOUND_STREAM_DEFAULT),
85 DEFINE_PROP_UINT32("chmaps", VirtIOSound, snd_conf.chmaps,
86 VIRTIO_SOUND_CHMAP_DEFAULT),
87 DEFINE_PROP_END_OF_LIST(),
88};
89
90static void
91virtio_snd_get_config(VirtIODevice *vdev, uint8_t *config)
92{
93 VirtIOSound *s = VIRTIO_SND(vdev);
94 virtio_snd_config *sndconfig =
95 (virtio_snd_config *)config;
96 trace_virtio_snd_get_config(vdev,
97 s->snd_conf.jacks,
98 s->snd_conf.streams,
99 s->snd_conf.chmaps);
100
101 memcpy(sndconfig, &s->snd_conf, sizeof(s->snd_conf));
102 cpu_to_le32s(&sndconfig->jacks);
103 cpu_to_le32s(&sndconfig->streams);
104 cpu_to_le32s(&sndconfig->chmaps);
105
106}
107
108static void
109virtio_snd_set_config(VirtIODevice *vdev, const uint8_t *config)
110{
111 VirtIOSound *s = VIRTIO_SND(vdev);
112 const virtio_snd_config *sndconfig =
113 (const virtio_snd_config *)config;
114
115
116 trace_virtio_snd_set_config(vdev,
117 s->snd_conf.jacks,
118 sndconfig->jacks,
119 s->snd_conf.streams,
120 sndconfig->streams,
121 s->snd_conf.chmaps,
122 sndconfig->chmaps);
123
124 memcpy(&s->snd_conf, sndconfig, sizeof(virtio_snd_config));
125 le32_to_cpus(&s->snd_conf.jacks);
126 le32_to_cpus(&s->snd_conf.streams);
127 le32_to_cpus(&s->snd_conf.chmaps);
128
129}
130
18a75281
MP
131static void
132virtio_snd_pcm_buffer_free(VirtIOSoundPCMBuffer *buffer)
133{
134 g_free(buffer->elem);
135 g_free(buffer);
136}
137
eb9ad377
MP
138static void
139virtio_snd_ctrl_cmd_free(virtio_snd_ctrl_command *cmd)
140{
141 g_free(cmd->elem);
142 g_free(cmd);
143}
144
145/*
146 * Get a specific stream from the virtio sound card device.
147 * Returns NULL if @stream_id is invalid or not allocated.
148 *
149 * @s: VirtIOSound device
150 * @stream_id: stream id
151 */
152static VirtIOSoundPCMStream *virtio_snd_pcm_get_stream(VirtIOSound *s,
153 uint32_t stream_id)
154{
155 return stream_id >= s->snd_conf.streams ? NULL :
156 s->pcm->streams[stream_id];
157}
158
159/*
160 * Get params for a specific stream.
161 *
162 * @s: VirtIOSound device
163 * @stream_id: stream id
164 */
165static virtio_snd_pcm_set_params *virtio_snd_pcm_get_params(VirtIOSound *s,
166 uint32_t stream_id)
167{
168 return stream_id >= s->snd_conf.streams ? NULL
169 : &s->pcm->pcm_params[stream_id];
170}
171
0ff05dd2
MP
172/*
173 * Handle the VIRTIO_SND_R_PCM_INFO request.
174 * The function writes the info structs to the request element.
175 *
176 * @s: VirtIOSound device
177 * @cmd: The request command queue element from VirtIOSound cmdq field
178 */
179static void virtio_snd_handle_pcm_info(VirtIOSound *s,
180 virtio_snd_ctrl_command *cmd)
181{
182 uint32_t stream_id, start_id, count, size;
183 virtio_snd_pcm_info val;
184 virtio_snd_query_info req;
185 VirtIOSoundPCMStream *stream = NULL;
186 g_autofree virtio_snd_pcm_info *pcm_info = NULL;
187 size_t msg_sz = iov_to_buf(cmd->elem->out_sg,
188 cmd->elem->out_num,
189 0,
190 &req,
191 sizeof(virtio_snd_query_info));
192
193 if (msg_sz != sizeof(virtio_snd_query_info)) {
194 /*
195 * TODO: do we need to set DEVICE_NEEDS_RESET?
196 */
197 qemu_log_mask(LOG_GUEST_ERROR,
198 "%s: virtio-snd command size incorrect %zu vs \
199 %zu\n", __func__, msg_sz, sizeof(virtio_snd_query_info));
200 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
201 return;
202 }
203
204 start_id = le32_to_cpu(req.start_id);
205 count = le32_to_cpu(req.count);
206 size = le32_to_cpu(req.size);
207
208 if (iov_size(cmd->elem->in_sg, cmd->elem->in_num) <
209 sizeof(virtio_snd_hdr) + size * count) {
210 /*
211 * TODO: do we need to set DEVICE_NEEDS_RESET?
212 */
213 error_report("pcm info: buffer too small, got: %zu, needed: %zu",
214 iov_size(cmd->elem->in_sg, cmd->elem->in_num),
215 sizeof(virtio_snd_pcm_info));
216 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
217 return;
218 }
219
220 pcm_info = g_new0(virtio_snd_pcm_info, count);
221 for (uint32_t i = 0; i < count; i++) {
222 stream_id = i + start_id;
223 trace_virtio_snd_handle_pcm_info(stream_id);
224 stream = virtio_snd_pcm_get_stream(s, stream_id);
225 if (!stream) {
226 error_report("Invalid stream id: %"PRIu32, stream_id);
227 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
228 return;
229 }
230 val = stream->info;
231 val.hdr.hda_fn_nid = cpu_to_le32(val.hdr.hda_fn_nid);
232 val.features = cpu_to_le32(val.features);
233 val.formats = cpu_to_le64(val.formats);
234 val.rates = cpu_to_le64(val.rates);
235 /*
236 * 5.14.6.6.2.1 Device Requirements: Stream Information The device MUST
237 * NOT set undefined feature, format, rate and direction values. The
238 * device MUST initialize the padding bytes to 0.
239 */
240 pcm_info[i] = val;
241 memset(&pcm_info[i].padding, 0, 5);
242 }
243
244 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_OK);
245 iov_from_buf(cmd->elem->in_sg,
246 cmd->elem->in_num,
247 sizeof(virtio_snd_hdr),
248 pcm_info,
249 sizeof(virtio_snd_pcm_info) * count);
250}
251
eb9ad377
MP
252/*
253 * Set the given stream params.
254 * Called by both virtio_snd_handle_pcm_set_params and during device
255 * initialization.
256 * Returns the response status code. (VIRTIO_SND_S_*).
257 *
258 * @s: VirtIOSound device
259 * @params: The PCM params as defined in the virtio specification
260 */
261static
262uint32_t virtio_snd_set_pcm_params(VirtIOSound *s,
263 uint32_t stream_id,
264 virtio_snd_pcm_set_params *params)
265{
266 virtio_snd_pcm_set_params *st_params;
267
268 if (stream_id >= s->snd_conf.streams || s->pcm->pcm_params == NULL) {
269 /*
270 * TODO: do we need to set DEVICE_NEEDS_RESET?
271 */
272 virtio_error(VIRTIO_DEVICE(s), "Streams have not been initialized.\n");
273 return cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
274 }
275
276 st_params = virtio_snd_pcm_get_params(s, stream_id);
277
278 if (params->channels < 1 || params->channels > AUDIO_MAX_CHANNELS) {
279 error_report("Number of channels is not supported.");
280 return cpu_to_le32(VIRTIO_SND_S_NOT_SUPP);
281 }
282 if (!(supported_formats & BIT(params->format))) {
283 error_report("Stream format is not supported.");
284 return cpu_to_le32(VIRTIO_SND_S_NOT_SUPP);
285 }
286 if (!(supported_rates & BIT(params->rate))) {
287 error_report("Stream rate is not supported.");
288 return cpu_to_le32(VIRTIO_SND_S_NOT_SUPP);
289 }
290
291 st_params->buffer_bytes = le32_to_cpu(params->buffer_bytes);
292 st_params->period_bytes = le32_to_cpu(params->period_bytes);
293 st_params->features = le32_to_cpu(params->features);
294 /* the following are uint8_t, so there's no need to bswap the values. */
295 st_params->channels = params->channels;
296 st_params->format = params->format;
297 st_params->rate = params->rate;
298
299 return cpu_to_le32(VIRTIO_SND_S_OK);
300}
301
64704ce0
MP
302/*
303 * Handles the VIRTIO_SND_R_PCM_SET_PARAMS request.
304 *
305 * @s: VirtIOSound device
306 * @cmd: The request command queue element from VirtIOSound cmdq field
307 */
308static void virtio_snd_handle_pcm_set_params(VirtIOSound *s,
309 virtio_snd_ctrl_command *cmd)
310{
311 virtio_snd_pcm_set_params req = { 0 };
312 uint32_t stream_id;
313 size_t msg_sz = iov_to_buf(cmd->elem->out_sg,
314 cmd->elem->out_num,
315 0,
316 &req,
317 sizeof(virtio_snd_pcm_set_params));
318
319 if (msg_sz != sizeof(virtio_snd_pcm_set_params)) {
320 /*
321 * TODO: do we need to set DEVICE_NEEDS_RESET?
322 */
323 qemu_log_mask(LOG_GUEST_ERROR,
324 "%s: virtio-snd command size incorrect %zu vs \
325 %zu\n", __func__, msg_sz, sizeof(virtio_snd_pcm_set_params));
326 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
327 return;
328 }
329 stream_id = le32_to_cpu(req.hdr.stream_id);
330 trace_virtio_snd_handle_pcm_set_params(stream_id);
331 cmd->resp.code = virtio_snd_set_pcm_params(s, stream_id, &req);
332}
333
eb9ad377
MP
334/*
335 * Get a QEMU Audiosystem compatible format value from a VIRTIO_SND_PCM_FMT_*
336 */
337static AudioFormat virtio_snd_get_qemu_format(uint32_t format)
338{
339 #define CASE(FMT) \
340 case VIRTIO_SND_PCM_FMT_##FMT: \
341 return AUDIO_FORMAT_##FMT;
342
343 switch (format) {
344 CASE(U8)
345 CASE(S8)
346 CASE(U16)
347 CASE(S16)
348 CASE(U32)
349 CASE(S32)
350 case VIRTIO_SND_PCM_FMT_FLOAT:
351 return AUDIO_FORMAT_F32;
352 default:
353 g_assert_not_reached();
354 }
355
356 #undef CASE
357}
358
359/*
360 * Get a QEMU Audiosystem compatible frequency value from a
361 * VIRTIO_SND_PCM_RATE_*
362 */
363static uint32_t virtio_snd_get_qemu_freq(uint32_t rate)
364{
365 #define CASE(RATE) \
366 case VIRTIO_SND_PCM_RATE_##RATE: \
367 return RATE;
368
369 switch (rate) {
370 CASE(5512)
371 CASE(8000)
372 CASE(11025)
373 CASE(16000)
374 CASE(22050)
375 CASE(32000)
376 CASE(44100)
377 CASE(48000)
378 CASE(64000)
379 CASE(88200)
380 CASE(96000)
381 CASE(176400)
382 CASE(192000)
383 CASE(384000)
384 default:
385 g_assert_not_reached();
386 }
387
388 #undef CASE
389}
390
391/*
392 * Get QEMU Audiosystem compatible audsettings from virtio based pcm stream
393 * params.
394 */
395static void virtio_snd_get_qemu_audsettings(audsettings *as,
396 virtio_snd_pcm_set_params *params)
397{
398 as->nchannels = MIN(AUDIO_MAX_CHANNELS, params->channels);
399 as->fmt = virtio_snd_get_qemu_format(params->format);
400 as->freq = virtio_snd_get_qemu_freq(params->rate);
401 as->endianness = target_words_bigendian() ? 1 : 0;
402}
403
404/*
405 * Close a stream and free all its resources.
406 *
407 * @stream: VirtIOSoundPCMStream *stream
408 */
409static void virtio_snd_pcm_close(VirtIOSoundPCMStream *stream)
410{
18a75281 411 if (stream) {
d8d64acb 412 virtio_snd_pcm_flush(stream);
18a75281 413 if (stream->info.direction == VIRTIO_SND_D_OUTPUT) {
18a75281
MP
414 AUD_close_out(&stream->pcm->snd->card, stream->voice.out);
415 stream->voice.out = NULL;
d8d64acb
MP
416 } else if (stream->info.direction == VIRTIO_SND_D_INPUT) {
417 AUD_close_in(&stream->pcm->snd->card, stream->voice.in);
418 stream->voice.in = NULL;
18a75281
MP
419 }
420 }
eb9ad377
MP
421}
422
2880e676 423/*
eb9ad377
MP
424 * Prepares a VirtIOSound card stream.
425 * Returns the response status code. (VIRTIO_SND_S_*).
426 *
427 * @s: VirtIOSound device
428 * @stream_id: stream id
429 */
430static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s, uint32_t stream_id)
431{
432 audsettings as;
433 virtio_snd_pcm_set_params *params;
434 VirtIOSoundPCMStream *stream;
435
436 if (s->pcm->streams == NULL ||
437 s->pcm->pcm_params == NULL ||
438 stream_id >= s->snd_conf.streams) {
439 return cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
440 }
441
442 params = virtio_snd_pcm_get_params(s, stream_id);
443 if (params == NULL) {
444 return cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
445 }
446
447 stream = virtio_snd_pcm_get_stream(s, stream_id);
448 if (stream == NULL) {
449 stream = g_new0(VirtIOSoundPCMStream, 1);
450 stream->active = false;
451 stream->id = stream_id;
452 stream->pcm = s->pcm;
453 stream->s = s;
18a75281
MP
454 qemu_mutex_init(&stream->queue_mutex);
455 QSIMPLEQ_INIT(&stream->queue);
456 QSIMPLEQ_INIT(&stream->invalid);
eb9ad377
MP
457
458 /*
459 * stream_id >= s->snd_conf.streams was checked before so this is
460 * in-bounds
461 */
462 s->pcm->streams[stream_id] = stream;
463 }
464
465 virtio_snd_get_qemu_audsettings(&as, params);
466 stream->info.direction = stream_id < s->snd_conf.streams / 2 +
467 (s->snd_conf.streams & 1) ? VIRTIO_SND_D_OUTPUT : VIRTIO_SND_D_INPUT;
468 stream->info.hdr.hda_fn_nid = VIRTIO_SOUND_HDA_FN_NID;
469 stream->info.features = 0;
470 stream->info.channels_min = 1;
471 stream->info.channels_max = as.nchannels;
472 stream->info.formats = supported_formats;
473 stream->info.rates = supported_rates;
474 stream->params = *params;
475
476 stream->positions[0] = VIRTIO_SND_CHMAP_FL;
477 stream->positions[1] = VIRTIO_SND_CHMAP_FR;
478 stream->as = as;
479
18a75281
MP
480 if (stream->info.direction == VIRTIO_SND_D_OUTPUT) {
481 stream->voice.out = AUD_open_out(&s->card,
482 stream->voice.out,
483 "virtio-sound.out",
484 stream,
485 virtio_snd_pcm_out_cb,
486 &as);
487 AUD_set_volume_out(stream->voice.out, 0, 255, 255);
488 } else {
d8d64acb
MP
489 stream->voice.in = AUD_open_in(&s->card,
490 stream->voice.in,
491 "virtio-sound.in",
492 stream,
493 virtio_snd_pcm_in_cb,
494 &as);
495 AUD_set_volume_in(stream->voice.in, 0, 255, 255);
18a75281
MP
496 }
497
eb9ad377
MP
498 return cpu_to_le32(VIRTIO_SND_S_OK);
499}
500
501static const char *print_code(uint32_t code)
502{
503 #define CASE(CODE) \
504 case VIRTIO_SND_R_##CODE: \
505 return "VIRTIO_SND_R_"#CODE
506
507 switch (code) {
508 CASE(JACK_INFO);
509 CASE(JACK_REMAP);
510 CASE(PCM_INFO);
511 CASE(PCM_SET_PARAMS);
512 CASE(PCM_PREPARE);
513 CASE(PCM_RELEASE);
514 CASE(PCM_START);
515 CASE(PCM_STOP);
516 CASE(CHMAP_INFO);
517 default:
518 return "invalid code";
519 }
520
521 #undef CASE
522};
523
e5788b8f
MP
524/*
525 * Handles VIRTIO_SND_R_PCM_PREPARE.
526 *
527 * @s: VirtIOSound device
528 * @cmd: The request command queue element from VirtIOSound cmdq field
529 */
530static void virtio_snd_handle_pcm_prepare(VirtIOSound *s,
531 virtio_snd_ctrl_command *cmd)
532{
533 uint32_t stream_id;
534 size_t msg_sz = iov_to_buf(cmd->elem->out_sg,
535 cmd->elem->out_num,
536 sizeof(virtio_snd_hdr),
537 &stream_id,
538 sizeof(stream_id));
539
540 stream_id = le32_to_cpu(stream_id);
541 cmd->resp.code = msg_sz == sizeof(stream_id)
542 ? virtio_snd_pcm_prepare(s, stream_id)
543 : cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
544}
545
fa131d4a
MP
546/*
547 * Handles VIRTIO_SND_R_PCM_START.
548 *
549 * @s: VirtIOSound device
550 * @cmd: The request command queue element from VirtIOSound cmdq field
551 * @start: whether to start or stop the device
552 */
553static void virtio_snd_handle_pcm_start_stop(VirtIOSound *s,
554 virtio_snd_ctrl_command *cmd,
555 bool start)
556{
557 VirtIOSoundPCMStream *stream;
558 virtio_snd_pcm_hdr req;
559 uint32_t stream_id;
560 size_t msg_sz = iov_to_buf(cmd->elem->out_sg,
561 cmd->elem->out_num,
562 0,
563 &req,
564 sizeof(virtio_snd_pcm_hdr));
565
566 if (msg_sz != sizeof(virtio_snd_pcm_hdr)) {
567 qemu_log_mask(LOG_GUEST_ERROR,
568 "%s: virtio-snd command size incorrect %zu vs \
569 %zu\n", __func__, msg_sz, sizeof(virtio_snd_pcm_hdr));
570 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
571 return;
572 }
573
574 stream_id = le32_to_cpu(req.stream_id);
575 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_OK);
576 trace_virtio_snd_handle_pcm_start_stop(start ? "VIRTIO_SND_R_PCM_START" :
577 "VIRTIO_SND_R_PCM_STOP", stream_id);
18a75281 578
fa131d4a 579 stream = virtio_snd_pcm_get_stream(s, stream_id);
18a75281
MP
580 if (stream) {
581 WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
582 stream->active = start;
583 }
584 if (stream->info.direction == VIRTIO_SND_D_OUTPUT) {
585 AUD_set_active_out(stream->voice.out, start);
d8d64acb
MP
586 } else {
587 AUD_set_active_in(stream->voice.in, start);
18a75281
MP
588 }
589 } else {
590 error_report("Invalid stream id: %"PRIu32, stream_id);
fa131d4a
MP
591 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
592 return;
593 }
594 stream->active = start;
595}
596
d48800d7 597/*
18a75281
MP
598 * Returns the number of I/O messages that are being processed.
599 *
600 * @stream: VirtIOSoundPCMStream
601 */
602static size_t virtio_snd_pcm_get_io_msgs_count(VirtIOSoundPCMStream *stream)
603{
604 VirtIOSoundPCMBuffer *buffer, *next;
605 size_t count = 0;
606
607 WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
608 QSIMPLEQ_FOREACH_SAFE(buffer, &stream->queue, entry, next) {
609 count += 1;
610 }
611 QSIMPLEQ_FOREACH_SAFE(buffer, &stream->invalid, entry, next) {
612 count += 1;
613 }
614 }
615 return count;
616}
617
618/*
619 * Handles VIRTIO_SND_R_PCM_RELEASE.
d48800d7
MP
620 *
621 * @s: VirtIOSound device
622 * @cmd: The request command queue element from VirtIOSound cmdq field
623 */
624static void virtio_snd_handle_pcm_release(VirtIOSound *s,
625 virtio_snd_ctrl_command *cmd)
626{
627 uint32_t stream_id;
628 VirtIOSoundPCMStream *stream;
629 size_t msg_sz = iov_to_buf(cmd->elem->out_sg,
630 cmd->elem->out_num,
631 sizeof(virtio_snd_hdr),
632 &stream_id,
633 sizeof(stream_id));
634
635 if (msg_sz != sizeof(stream_id)) {
636 /*
637 * TODO: do we need to set DEVICE_NEEDS_RESET?
638 */
639 qemu_log_mask(LOG_GUEST_ERROR,
640 "%s: virtio-snd command size incorrect %zu vs \
641 %zu\n", __func__, msg_sz, sizeof(stream_id));
642 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
643 return;
644 }
645
646 stream_id = le32_to_cpu(stream_id);
647 trace_virtio_snd_handle_pcm_release(stream_id);
648 stream = virtio_snd_pcm_get_stream(s, stream_id);
649 if (stream == NULL) {
650 /*
651 * TODO: do we need to set DEVICE_NEEDS_RESET?
652 */
653 error_report("already released stream %"PRIu32, stream_id);
654 virtio_error(VIRTIO_DEVICE(s),
655 "already released stream %"PRIu32,
656 stream_id);
657 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
658 return;
659 }
18a75281
MP
660
661 if (virtio_snd_pcm_get_io_msgs_count(stream)) {
662 /*
663 * virtio-v1.2-csd01, 5.14.6.6.5.1,
664 * Device Requirements: Stream Release
665 *
666 * - The device MUST complete all pending I/O messages for the
667 * specified stream ID.
668 * - The device MUST NOT complete the control request while there
669 * are pending I/O messages for the specified stream ID.
670 */
671 trace_virtio_snd_pcm_stream_flush(stream_id);
672 virtio_snd_pcm_flush(stream);
673 }
674
d48800d7
MP
675 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_OK);
676}
677
eb9ad377
MP
678/*
679 * The actual processing done in virtio_snd_process_cmdq().
680 *
681 * @s: VirtIOSound device
682 * @cmd: control command request
683 */
684static inline void
685process_cmd(VirtIOSound *s, virtio_snd_ctrl_command *cmd)
686{
687 uint32_t code;
688 size_t msg_sz = iov_to_buf(cmd->elem->out_sg,
689 cmd->elem->out_num,
690 0,
691 &cmd->ctrl,
692 sizeof(virtio_snd_hdr));
693
694 if (msg_sz != sizeof(virtio_snd_hdr)) {
695 /*
696 * TODO: do we need to set DEVICE_NEEDS_RESET?
697 */
698 qemu_log_mask(LOG_GUEST_ERROR,
699 "%s: virtio-snd command size incorrect %zu vs \
700 %zu\n", __func__, msg_sz, sizeof(virtio_snd_hdr));
701 return;
702 }
703
704 code = le32_to_cpu(cmd->ctrl.code);
705
706 trace_virtio_snd_handle_code(code, print_code(code));
707
708 switch (code) {
709 case VIRTIO_SND_R_JACK_INFO:
710 case VIRTIO_SND_R_JACK_REMAP:
711 qemu_log_mask(LOG_UNIMP,
712 "virtio_snd: jack functionality is unimplemented.\n");
713 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_NOT_SUPP);
714 break;
715 case VIRTIO_SND_R_PCM_INFO:
0ff05dd2
MP
716 virtio_snd_handle_pcm_info(s, cmd);
717 break;
eb9ad377 718 case VIRTIO_SND_R_PCM_START:
fa131d4a
MP
719 virtio_snd_handle_pcm_start_stop(s, cmd, true);
720 break;
eb9ad377 721 case VIRTIO_SND_R_PCM_STOP:
fa131d4a
MP
722 virtio_snd_handle_pcm_start_stop(s, cmd, false);
723 break;
724 case VIRTIO_SND_R_PCM_SET_PARAMS:
64704ce0
MP
725 virtio_snd_handle_pcm_set_params(s, cmd);
726 break;
fa131d4a 727 case VIRTIO_SND_R_PCM_PREPARE:
e5788b8f
MP
728 virtio_snd_handle_pcm_prepare(s, cmd);
729 break;
eb9ad377 730 case VIRTIO_SND_R_PCM_RELEASE:
d48800d7 731 virtio_snd_handle_pcm_release(s, cmd);
eb9ad377
MP
732 break;
733 case VIRTIO_SND_R_CHMAP_INFO:
734 qemu_log_mask(LOG_UNIMP,
735 "virtio_snd: chmap info functionality is unimplemented.\n");
736 trace_virtio_snd_handle_chmap_info();
737 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_NOT_SUPP);
738 break;
739 default:
740 /* error */
741 error_report("virtio snd header not recognized: %"PRIu32, code);
742 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
743 }
744
745 iov_from_buf(cmd->elem->in_sg,
746 cmd->elem->in_num,
747 0,
748 &cmd->resp,
749 sizeof(virtio_snd_hdr));
750 virtqueue_push(cmd->vq, cmd->elem, sizeof(virtio_snd_hdr));
751 virtio_notify(VIRTIO_DEVICE(s), cmd->vq);
752}
753
754/*
755 * Consume all elements in command queue.
756 *
757 * @s: VirtIOSound device
758 */
759static void virtio_snd_process_cmdq(VirtIOSound *s)
760{
761 virtio_snd_ctrl_command *cmd;
762
763 if (unlikely(qatomic_read(&s->processing_cmdq))) {
764 return;
765 }
766
767 WITH_QEMU_LOCK_GUARD(&s->cmdq_mutex) {
768 qatomic_set(&s->processing_cmdq, true);
769 while (!QTAILQ_EMPTY(&s->cmdq)) {
770 cmd = QTAILQ_FIRST(&s->cmdq);
771
772 /* process command */
773 process_cmd(s, cmd);
774
775 QTAILQ_REMOVE(&s->cmdq, cmd, next);
776
777 virtio_snd_ctrl_cmd_free(cmd);
778 }
779 qatomic_set(&s->processing_cmdq, false);
780 }
781}
782
783/*
784 * The control message handler. Pops an element from the control virtqueue,
785 * and stores them to VirtIOSound's cmdq queue and finally calls
786 * virtio_snd_process_cmdq() for processing.
787 *
788 * @vdev: VirtIOSound device
789 * @vq: Control virtqueue
790 */
791static void virtio_snd_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
792{
793 VirtIOSound *s = VIRTIO_SND(vdev);
794 VirtQueueElement *elem;
795 virtio_snd_ctrl_command *cmd;
796
797 trace_virtio_snd_handle_ctrl(vdev, vq);
798
799 if (!virtio_queue_ready(vq)) {
800 return;
801 }
802
803 elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
804 while (elem) {
805 cmd = g_new0(virtio_snd_ctrl_command, 1);
806 cmd->elem = elem;
807 cmd->vq = vq;
808 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_OK);
809 QTAILQ_INSERT_TAIL(&s->cmdq, cmd, next);
810 elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
811 }
812
813 virtio_snd_process_cmdq(s);
814}
815
816/*
817 * The event virtqueue handler.
818 * Not implemented yet.
819 *
820 * @vdev: VirtIOSound device
821 * @vq: event vq
822 */
823static void virtio_snd_handle_event(VirtIODevice *vdev, VirtQueue *vq)
824{
825 qemu_log_mask(LOG_UNIMP, "virtio_snd: event queue is unimplemented.\n");
826 trace_virtio_snd_handle_event();
827}
828
d8d64acb
MP
829static inline void empty_invalid_queue(VirtIODevice *vdev, VirtQueue *vq)
830{
831 VirtIOSoundPCMBuffer *buffer = NULL;
832 VirtIOSoundPCMStream *stream = NULL;
833 virtio_snd_pcm_status resp = { 0 };
834 VirtIOSound *vsnd = VIRTIO_SND(vdev);
835 bool any = false;
836
837 for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) {
838 stream = vsnd->pcm->streams[i];
839 if (stream) {
840 any = false;
841 WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
842 while (!QSIMPLEQ_EMPTY(&stream->invalid)) {
843 buffer = QSIMPLEQ_FIRST(&stream->invalid);
844 if (buffer->vq != vq) {
845 break;
846 }
847 any = true;
848 resp.status = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
849 iov_from_buf(buffer->elem->in_sg,
850 buffer->elem->in_num,
851 0,
852 &resp,
853 sizeof(virtio_snd_pcm_status));
854 virtqueue_push(vq,
855 buffer->elem,
856 sizeof(virtio_snd_pcm_status));
857 QSIMPLEQ_REMOVE_HEAD(&stream->invalid, entry);
858 virtio_snd_pcm_buffer_free(buffer);
859 }
860 if (any) {
861 /*
862 * Notify vq about virtio_snd_pcm_status responses.
863 * Buffer responses must be notified separately later.
864 */
865 virtio_notify(vdev, vq);
866 }
867 }
868 }
869 }
870}
871
18a75281
MP
872/*
873 * The tx virtqueue handler. Makes the buffers available to their respective
874 * streams for consumption.
875 *
876 * @vdev: VirtIOSound device
877 * @vq: tx virtqueue
878 */
d8d64acb 879static void virtio_snd_handle_tx_xfer(VirtIODevice *vdev, VirtQueue *vq)
18a75281
MP
880{
881 VirtIOSound *s = VIRTIO_SND(vdev);
882 VirtIOSoundPCMStream *stream = NULL;
883 VirtIOSoundPCMBuffer *buffer;
884 VirtQueueElement *elem;
885 size_t msg_sz, size;
886 virtio_snd_pcm_xfer hdr;
18a75281
MP
887 uint32_t stream_id;
888 /*
889 * If any of the I/O messages are invalid, put them in stream->invalid and
890 * return them after the for loop.
891 */
892 bool must_empty_invalid_queue = false;
893
894 if (!virtio_queue_ready(vq)) {
895 return;
896 }
d8d64acb 897 trace_virtio_snd_handle_tx_xfer();
18a75281
MP
898
899 for (;;) {
900 elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
901 if (!elem) {
902 break;
903 }
904 /* get the message hdr object */
905 msg_sz = iov_to_buf(elem->out_sg,
906 elem->out_num,
907 0,
908 &hdr,
909 sizeof(virtio_snd_pcm_xfer));
910 if (msg_sz != sizeof(virtio_snd_pcm_xfer)) {
911 goto tx_err;
912 }
913 stream_id = le32_to_cpu(hdr.stream_id);
914
915 if (stream_id >= s->snd_conf.streams
916 || s->pcm->streams[stream_id] == NULL) {
917 goto tx_err;
918 }
919
920 stream = s->pcm->streams[stream_id];
921 if (stream->info.direction != VIRTIO_SND_D_OUTPUT) {
922 goto tx_err;
923 }
924
925 WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
926 size = iov_size(elem->out_sg, elem->out_num) - msg_sz;
927
928 buffer = g_malloc0(sizeof(VirtIOSoundPCMBuffer) + size);
929 buffer->elem = elem;
930 buffer->populated = false;
931 buffer->vq = vq;
932 buffer->size = size;
933 buffer->offset = 0;
934
935 QSIMPLEQ_INSERT_TAIL(&stream->queue, buffer, entry);
936 }
937 continue;
938
939tx_err:
940 WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
941 must_empty_invalid_queue = true;
942 buffer = g_malloc0(sizeof(VirtIOSoundPCMBuffer));
943 buffer->elem = elem;
944 buffer->vq = vq;
945 QSIMPLEQ_INSERT_TAIL(&stream->invalid, buffer, entry);
946 }
947 }
948
949 if (must_empty_invalid_queue) {
d8d64acb 950 empty_invalid_queue(vdev, vq);
18a75281
MP
951 }
952}
953
eb9ad377 954/*
d8d64acb
MP
955 * The rx virtqueue handler. Makes the buffers available to their respective
956 * streams for consumption.
2880e676
MP
957 *
958 * @vdev: VirtIOSound device
d8d64acb 959 * @vq: rx virtqueue
2880e676 960 */
d8d64acb
MP
961static void virtio_snd_handle_rx_xfer(VirtIODevice *vdev, VirtQueue *vq)
962{
963 VirtIOSound *s = VIRTIO_SND(vdev);
964 VirtIOSoundPCMStream *stream = NULL;
965 VirtIOSoundPCMBuffer *buffer;
966 VirtQueueElement *elem;
967 size_t msg_sz, size;
968 virtio_snd_pcm_xfer hdr;
969 uint32_t stream_id;
970 /*
971 * if any of the I/O messages are invalid, put them in stream->invalid and
972 * return them after the for loop.
973 */
974 bool must_empty_invalid_queue = false;
975
976 if (!virtio_queue_ready(vq)) {
977 return;
978 }
979 trace_virtio_snd_handle_rx_xfer();
980
981 for (;;) {
982 elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
983 if (!elem) {
984 break;
985 }
986 /* get the message hdr object */
987 msg_sz = iov_to_buf(elem->out_sg,
988 elem->out_num,
989 0,
990 &hdr,
991 sizeof(virtio_snd_pcm_xfer));
992 if (msg_sz != sizeof(virtio_snd_pcm_xfer)) {
993 goto rx_err;
994 }
995 stream_id = le32_to_cpu(hdr.stream_id);
996
997 if (stream_id >= s->snd_conf.streams
998 || !s->pcm->streams[stream_id]) {
999 goto rx_err;
1000 }
1001
1002 stream = s->pcm->streams[stream_id];
1003 if (stream == NULL || stream->info.direction != VIRTIO_SND_D_INPUT) {
1004 goto rx_err;
1005 }
1006 WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
1007 size = iov_size(elem->in_sg, elem->in_num) -
1008 sizeof(virtio_snd_pcm_status);
1009 buffer = g_malloc0(sizeof(VirtIOSoundPCMBuffer) + size);
1010 buffer->elem = elem;
1011 buffer->vq = vq;
1012 buffer->size = 0;
1013 buffer->offset = 0;
1014 QSIMPLEQ_INSERT_TAIL(&stream->queue, buffer, entry);
1015 }
1016 continue;
1017
1018rx_err:
1019 WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
1020 must_empty_invalid_queue = true;
1021 buffer = g_malloc0(sizeof(VirtIOSoundPCMBuffer));
1022 buffer->elem = elem;
1023 buffer->vq = vq;
1024 QSIMPLEQ_INSERT_TAIL(&stream->invalid, buffer, entry);
1025 }
1026 }
1027
1028 if (must_empty_invalid_queue) {
1029 empty_invalid_queue(vdev, vq);
1030 }
1031}
2880e676
MP
1032
1033static uint64_t get_features(VirtIODevice *vdev, uint64_t features,
1034 Error **errp)
1035{
1036 /*
1037 * virtio-v1.2-csd01, 5.14.3,
1038 * Feature Bits
1039 * None currently defined.
1040 */
1041 VirtIOSound *s = VIRTIO_SND(vdev);
1042 features |= s->features;
1043
1044 trace_virtio_snd_get_features(vdev, features);
1045
1046 return features;
1047}
1048
1049static void
1050virtio_snd_vm_state_change(void *opaque, bool running,
1051 RunState state)
1052{
1053 if (running) {
1054 trace_virtio_snd_vm_state_running();
1055 } else {
1056 trace_virtio_snd_vm_state_stopped();
1057 }
1058}
1059
1060static void virtio_snd_realize(DeviceState *dev, Error **errp)
1061{
1062 ERRP_GUARD();
1063 VirtIOSound *vsnd = VIRTIO_SND(dev);
1064 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
eb9ad377
MP
1065 virtio_snd_pcm_set_params default_params = { 0 };
1066 uint32_t status;
2880e676 1067
eb9ad377 1068 vsnd->pcm = NULL;
2880e676
MP
1069 vsnd->vmstate =
1070 qemu_add_vm_change_state_handler(virtio_snd_vm_state_change, vsnd);
1071
1072 trace_virtio_snd_realize(vsnd);
1073
eb9ad377
MP
1074 vsnd->pcm = g_new0(VirtIOSoundPCM, 1);
1075 vsnd->pcm->snd = vsnd;
1076 vsnd->pcm->streams =
1077 g_new0(VirtIOSoundPCMStream *, vsnd->snd_conf.streams);
1078 vsnd->pcm->pcm_params =
1079 g_new0(virtio_snd_pcm_set_params, vsnd->snd_conf.streams);
1080
2880e676
MP
1081 virtio_init(vdev, VIRTIO_ID_SOUND, sizeof(virtio_snd_config));
1082 virtio_add_feature(&vsnd->features, VIRTIO_F_VERSION_1);
1083
1084 /* set number of jacks and streams */
1085 if (vsnd->snd_conf.jacks > 8) {
1086 error_setg(errp,
1087 "Invalid number of jacks: %"PRIu32,
1088 vsnd->snd_conf.jacks);
1089 return;
1090 }
1091 if (vsnd->snd_conf.streams < 1 || vsnd->snd_conf.streams > 10) {
1092 error_setg(errp,
1093 "Invalid number of streams: %"PRIu32,
1094 vsnd->snd_conf.streams);
1095 return;
1096 }
1097
1098 if (vsnd->snd_conf.chmaps > VIRTIO_SND_CHMAP_MAX_SIZE) {
1099 error_setg(errp,
1100 "Invalid number of channel maps: %"PRIu32,
1101 vsnd->snd_conf.chmaps);
1102 return;
1103 }
1104
1105 AUD_register_card("virtio-sound", &vsnd->card, errp);
1106
eb9ad377
MP
1107 /* set default params for all streams */
1108 default_params.features = 0;
1109 default_params.buffer_bytes = cpu_to_le32(8192);
1110 default_params.period_bytes = cpu_to_le32(2048);
1111 default_params.channels = 2;
1112 default_params.format = VIRTIO_SND_PCM_FMT_S16;
1113 default_params.rate = VIRTIO_SND_PCM_RATE_48000;
2880e676 1114 vsnd->queues[VIRTIO_SND_VQ_CONTROL] =
eb9ad377 1115 virtio_add_queue(vdev, 64, virtio_snd_handle_ctrl);
2880e676 1116 vsnd->queues[VIRTIO_SND_VQ_EVENT] =
eb9ad377 1117 virtio_add_queue(vdev, 64, virtio_snd_handle_event);
2880e676 1118 vsnd->queues[VIRTIO_SND_VQ_TX] =
d8d64acb 1119 virtio_add_queue(vdev, 64, virtio_snd_handle_tx_xfer);
2880e676 1120 vsnd->queues[VIRTIO_SND_VQ_RX] =
d8d64acb 1121 virtio_add_queue(vdev, 64, virtio_snd_handle_rx_xfer);
eb9ad377
MP
1122 qemu_mutex_init(&vsnd->cmdq_mutex);
1123 QTAILQ_INIT(&vsnd->cmdq);
1124
1125 for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) {
1126 status = virtio_snd_set_pcm_params(vsnd, i, &default_params);
1127 if (status != cpu_to_le32(VIRTIO_SND_S_OK)) {
1128 error_setg(errp,
aaf851a2 1129 "Can't initialize stream params, device responded with %s.",
eb9ad377
MP
1130 print_code(status));
1131 return;
1132 }
1133 status = virtio_snd_pcm_prepare(vsnd, i);
1134 if (status != cpu_to_le32(VIRTIO_SND_S_OK)) {
1135 error_setg(errp,
1136 "Can't prepare streams, device responded with %s.",
1137 print_code(status));
1138 return;
1139 }
1140 }
2880e676
MP
1141}
1142
18a75281
MP
1143static inline void return_tx_buffer(VirtIOSoundPCMStream *stream,
1144 VirtIOSoundPCMBuffer *buffer)
1145{
1146 virtio_snd_pcm_status resp = { 0 };
1147 resp.status = cpu_to_le32(VIRTIO_SND_S_OK);
1148 resp.latency_bytes = cpu_to_le32((uint32_t)buffer->size);
1149 iov_from_buf(buffer->elem->in_sg,
1150 buffer->elem->in_num,
1151 0,
1152 &resp,
1153 sizeof(virtio_snd_pcm_status));
1154 virtqueue_push(buffer->vq,
1155 buffer->elem,
1156 sizeof(virtio_snd_pcm_status));
1157 virtio_notify(VIRTIO_DEVICE(stream->s), buffer->vq);
1158 QSIMPLEQ_REMOVE(&stream->queue,
1159 buffer,
1160 VirtIOSoundPCMBuffer,
1161 entry);
1162 virtio_snd_pcm_buffer_free(buffer);
1163}
1164
1165/*
1166 * AUD_* output callback.
1167 *
1168 * @data: VirtIOSoundPCMStream stream
1169 * @available: number of bytes that can be written with AUD_write()
1170 */
1171static void virtio_snd_pcm_out_cb(void *data, int available)
1172{
1173 VirtIOSoundPCMStream *stream = data;
1174 VirtIOSoundPCMBuffer *buffer;
1175 size_t size;
1176
1177 WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
1178 while (!QSIMPLEQ_EMPTY(&stream->queue)) {
1179 buffer = QSIMPLEQ_FIRST(&stream->queue);
1180 if (!virtio_queue_ready(buffer->vq)) {
1181 return;
1182 }
1183 if (!stream->active) {
1184 /* Stream has stopped, so do not perform AUD_write. */
1185 return_tx_buffer(stream, buffer);
1186 continue;
1187 }
1188 if (!buffer->populated) {
1189 iov_to_buf(buffer->elem->out_sg,
1190 buffer->elem->out_num,
1191 sizeof(virtio_snd_pcm_xfer),
1192 buffer->data,
1193 buffer->size);
1194 buffer->populated = true;
1195 }
1196 for (;;) {
1197 size = AUD_write(stream->voice.out,
1198 buffer->data + buffer->offset,
1199 MIN(buffer->size, available));
1200 assert(size <= MIN(buffer->size, available));
1201 if (size == 0) {
1202 /* break out of both loops */
1203 available = 0;
1204 break;
1205 }
1206 buffer->size -= size;
1207 buffer->offset += size;
1208 available -= size;
1209 if (buffer->size < 1) {
1210 return_tx_buffer(stream, buffer);
1211 break;
1212 }
1213 if (!available) {
1214 break;
1215 }
1216 }
1217 if (!available) {
1218 break;
1219 }
1220 }
1221 }
1222}
1223
1224/*
d8d64acb
MP
1225 * Flush all buffer data from this input stream's queue into the driver's
1226 * virtual queue.
1227 *
1228 * @stream: VirtIOSoundPCMStream *stream
1229 */
1230static inline void return_rx_buffer(VirtIOSoundPCMStream *stream,
1231 VirtIOSoundPCMBuffer *buffer)
1232{
1233 virtio_snd_pcm_status resp = { 0 };
1234 resp.status = cpu_to_le32(VIRTIO_SND_S_OK);
1235 resp.latency_bytes = 0;
1236 /* Copy data -if any- to guest */
1237 iov_from_buf(buffer->elem->in_sg,
1238 buffer->elem->in_num,
1239 0,
1240 buffer->data,
1241 buffer->size);
1242 iov_from_buf(buffer->elem->in_sg,
1243 buffer->elem->in_num,
1244 buffer->size,
1245 &resp,
1246 sizeof(virtio_snd_pcm_status));
1247 virtqueue_push(buffer->vq,
1248 buffer->elem,
1249 sizeof(virtio_snd_pcm_status) + buffer->size);
1250 virtio_notify(VIRTIO_DEVICE(stream->s), buffer->vq);
1251 QSIMPLEQ_REMOVE(&stream->queue,
1252 buffer,
1253 VirtIOSoundPCMBuffer,
1254 entry);
1255 virtio_snd_pcm_buffer_free(buffer);
1256}
1257
1258
1259/*
1260 * AUD_* input callback.
1261 *
1262 * @data: VirtIOSoundPCMStream stream
1263 * @available: number of bytes that can be read with AUD_read()
1264 */
1265static void virtio_snd_pcm_in_cb(void *data, int available)
1266{
1267 VirtIOSoundPCMStream *stream = data;
1268 VirtIOSoundPCMBuffer *buffer;
1269 size_t size;
1270
1271 WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
1272 while (!QSIMPLEQ_EMPTY(&stream->queue)) {
1273 buffer = QSIMPLEQ_FIRST(&stream->queue);
1274 if (!virtio_queue_ready(buffer->vq)) {
1275 return;
1276 }
1277 if (!stream->active) {
1278 /* Stream has stopped, so do not perform AUD_read. */
1279 return_rx_buffer(stream, buffer);
1280 continue;
1281 }
1282
1283 for (;;) {
1284 size = AUD_read(stream->voice.in,
1285 buffer->data + buffer->size,
1286 MIN(available, (stream->params.period_bytes -
1287 buffer->size)));
1288 if (!size) {
1289 available = 0;
1290 break;
1291 }
1292 buffer->size += size;
1293 available -= size;
1294 if (buffer->size >= stream->params.period_bytes) {
1295 return_rx_buffer(stream, buffer);
1296 break;
1297 }
1298 if (!available) {
1299 break;
1300 }
1301 }
1302 if (!available) {
1303 break;
1304 }
1305 }
1306 }
1307}
1308
1309/*
1310 * Flush all buffer data from this output stream's queue into the driver's
1311 * virtual queue.
18a75281
MP
1312 *
1313 * @stream: VirtIOSoundPCMStream *stream
1314 */
1315static inline void virtio_snd_pcm_flush(VirtIOSoundPCMStream *stream)
1316{
1317 VirtIOSoundPCMBuffer *buffer;
d8d64acb
MP
1318 void (*cb)(VirtIOSoundPCMStream *, VirtIOSoundPCMBuffer *) =
1319 (stream->info.direction == VIRTIO_SND_D_OUTPUT) ? return_tx_buffer :
1320 return_rx_buffer;
18a75281
MP
1321
1322 WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
1323 while (!QSIMPLEQ_EMPTY(&stream->queue)) {
1324 buffer = QSIMPLEQ_FIRST(&stream->queue);
d8d64acb 1325 cb(stream, buffer);
18a75281
MP
1326 }
1327 }
1328}
1329
2880e676
MP
1330static void virtio_snd_unrealize(DeviceState *dev)
1331{
1332 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
1333 VirtIOSound *vsnd = VIRTIO_SND(dev);
eb9ad377 1334 VirtIOSoundPCMStream *stream;
2880e676
MP
1335
1336 qemu_del_vm_change_state_handler(vsnd->vmstate);
1337 trace_virtio_snd_unrealize(vsnd);
1338
eb9ad377
MP
1339 if (vsnd->pcm) {
1340 if (vsnd->pcm->streams) {
1341 for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) {
1342 stream = vsnd->pcm->streams[i];
1343 if (stream) {
1344 virtio_snd_process_cmdq(stream->s);
1345 virtio_snd_pcm_close(stream);
18a75281 1346 qemu_mutex_destroy(&stream->queue_mutex);
eb9ad377
MP
1347 g_free(stream);
1348 }
1349 }
1350 g_free(vsnd->pcm->streams);
1351 }
1352 g_free(vsnd->pcm->pcm_params);
1353 g_free(vsnd->pcm);
1354 vsnd->pcm = NULL;
1355 }
2880e676 1356 AUD_remove_card(&vsnd->card);
eb9ad377 1357 qemu_mutex_destroy(&vsnd->cmdq_mutex);
2880e676
MP
1358 virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_CONTROL]);
1359 virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_EVENT]);
1360 virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_TX]);
1361 virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_RX]);
1362 virtio_cleanup(vdev);
1363}
1364
1365
eb9ad377
MP
1366static void virtio_snd_reset(VirtIODevice *vdev)
1367{
1368 VirtIOSound *s = VIRTIO_SND(vdev);
1369 virtio_snd_ctrl_command *cmd;
1370
1371 WITH_QEMU_LOCK_GUARD(&s->cmdq_mutex) {
1372 while (!QTAILQ_EMPTY(&s->cmdq)) {
1373 cmd = QTAILQ_FIRST(&s->cmdq);
1374 QTAILQ_REMOVE(&s->cmdq, cmd, next);
1375 virtio_snd_ctrl_cmd_free(cmd);
1376 }
1377 }
1378}
2880e676
MP
1379
1380static void virtio_snd_class_init(ObjectClass *klass, void *data)
1381{
1382 DeviceClass *dc = DEVICE_CLASS(klass);
1383 VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
1384
1385
1386 set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
1387 device_class_set_props(dc, virtio_snd_properties);
1388
1389 dc->vmsd = &vmstate_virtio_snd;
1390 vdc->vmsd = &vmstate_virtio_snd_device;
1391 vdc->realize = virtio_snd_realize;
1392 vdc->unrealize = virtio_snd_unrealize;
1393 vdc->get_config = virtio_snd_get_config;
1394 vdc->set_config = virtio_snd_set_config;
1395 vdc->get_features = get_features;
1396 vdc->reset = virtio_snd_reset;
1397 vdc->legacy_features = 0;
1398}
1399
1400static const TypeInfo virtio_snd_types[] = {
1401 {
1402 .name = TYPE_VIRTIO_SND,
1403 .parent = TYPE_VIRTIO_DEVICE,
1404 .instance_size = sizeof(VirtIOSound),
1405 .class_init = virtio_snd_class_init,
1406 }
1407};
1408
1409DEFINE_TYPES(virtio_snd_types)