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