OSDN Git Service

virtio-sound: handle control messages and streams
[qmiga/qemu.git] / hw / audio / virtio-snd.c
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
31 #define VIRTIO_SOUND_STREAM_DEFAULT 1
32 #define VIRTIO_SOUND_CHMAP_DEFAULT 0
33 #define VIRTIO_SOUND_HDA_FN_NID 0
34
35 static uint32_t supported_formats = BIT(VIRTIO_SND_PCM_FMT_S8)
36                                   | BIT(VIRTIO_SND_PCM_FMT_U8)
37                                   | BIT(VIRTIO_SND_PCM_FMT_S16)
38                                   | BIT(VIRTIO_SND_PCM_FMT_U16)
39                                   | BIT(VIRTIO_SND_PCM_FMT_S32)
40                                   | BIT(VIRTIO_SND_PCM_FMT_U32)
41                                   | BIT(VIRTIO_SND_PCM_FMT_FLOAT);
42
43 static uint32_t supported_rates = BIT(VIRTIO_SND_PCM_RATE_5512)
44                                 | BIT(VIRTIO_SND_PCM_RATE_8000)
45                                 | BIT(VIRTIO_SND_PCM_RATE_11025)
46                                 | BIT(VIRTIO_SND_PCM_RATE_16000)
47                                 | BIT(VIRTIO_SND_PCM_RATE_22050)
48                                 | BIT(VIRTIO_SND_PCM_RATE_32000)
49                                 | BIT(VIRTIO_SND_PCM_RATE_44100)
50                                 | BIT(VIRTIO_SND_PCM_RATE_48000)
51                                 | BIT(VIRTIO_SND_PCM_RATE_64000)
52                                 | BIT(VIRTIO_SND_PCM_RATE_88200)
53                                 | BIT(VIRTIO_SND_PCM_RATE_96000)
54                                 | BIT(VIRTIO_SND_PCM_RATE_176400)
55                                 | BIT(VIRTIO_SND_PCM_RATE_192000)
56                                 | BIT(VIRTIO_SND_PCM_RATE_384000);
57
58 static const VMStateDescription vmstate_virtio_snd_device = {
59     .name = TYPE_VIRTIO_SND,
60     .version_id = VIRTIO_SOUND_VM_VERSION,
61     .minimum_version_id = VIRTIO_SOUND_VM_VERSION,
62 };
63
64 static const VMStateDescription vmstate_virtio_snd = {
65     .name = TYPE_VIRTIO_SND,
66     .minimum_version_id = VIRTIO_SOUND_VM_VERSION,
67     .version_id = VIRTIO_SOUND_VM_VERSION,
68     .fields = (VMStateField[]) {
69         VMSTATE_VIRTIO_DEVICE,
70         VMSTATE_END_OF_LIST()
71     },
72 };
73
74 static Property virtio_snd_properties[] = {
75     DEFINE_AUDIO_PROPERTIES(VirtIOSound, card),
76     DEFINE_PROP_UINT32("jacks", VirtIOSound, snd_conf.jacks,
77                        VIRTIO_SOUND_JACK_DEFAULT),
78     DEFINE_PROP_UINT32("streams", VirtIOSound, snd_conf.streams,
79                        VIRTIO_SOUND_STREAM_DEFAULT),
80     DEFINE_PROP_UINT32("chmaps", VirtIOSound, snd_conf.chmaps,
81                        VIRTIO_SOUND_CHMAP_DEFAULT),
82     DEFINE_PROP_END_OF_LIST(),
83 };
84
85 static void
86 virtio_snd_get_config(VirtIODevice *vdev, uint8_t *config)
87 {
88     VirtIOSound *s = VIRTIO_SND(vdev);
89     virtio_snd_config *sndconfig =
90         (virtio_snd_config *)config;
91     trace_virtio_snd_get_config(vdev,
92                                 s->snd_conf.jacks,
93                                 s->snd_conf.streams,
94                                 s->snd_conf.chmaps);
95
96     memcpy(sndconfig, &s->snd_conf, sizeof(s->snd_conf));
97     cpu_to_le32s(&sndconfig->jacks);
98     cpu_to_le32s(&sndconfig->streams);
99     cpu_to_le32s(&sndconfig->chmaps);
100
101 }
102
103 static void
104 virtio_snd_set_config(VirtIODevice *vdev, const uint8_t *config)
105 {
106     VirtIOSound *s = VIRTIO_SND(vdev);
107     const virtio_snd_config *sndconfig =
108         (const virtio_snd_config *)config;
109
110
111    trace_virtio_snd_set_config(vdev,
112                                s->snd_conf.jacks,
113                                sndconfig->jacks,
114                                s->snd_conf.streams,
115                                sndconfig->streams,
116                                s->snd_conf.chmaps,
117                                sndconfig->chmaps);
118
119     memcpy(&s->snd_conf, sndconfig, sizeof(virtio_snd_config));
120     le32_to_cpus(&s->snd_conf.jacks);
121     le32_to_cpus(&s->snd_conf.streams);
122     le32_to_cpus(&s->snd_conf.chmaps);
123
124 }
125
126 static void
127 virtio_snd_ctrl_cmd_free(virtio_snd_ctrl_command *cmd)
128 {
129     g_free(cmd->elem);
130     g_free(cmd);
131 }
132
133 /*
134  * Get a specific stream from the virtio sound card device.
135  * Returns NULL if @stream_id is invalid or not allocated.
136  *
137  * @s: VirtIOSound device
138  * @stream_id: stream id
139  */
140 static VirtIOSoundPCMStream *virtio_snd_pcm_get_stream(VirtIOSound *s,
141                                                        uint32_t stream_id)
142 {
143     return stream_id >= s->snd_conf.streams ? NULL :
144         s->pcm->streams[stream_id];
145 }
146
147 /*
148  * Get params for a specific stream.
149  *
150  * @s: VirtIOSound device
151  * @stream_id: stream id
152  */
153 static virtio_snd_pcm_set_params *virtio_snd_pcm_get_params(VirtIOSound *s,
154                                                             uint32_t stream_id)
155 {
156     return stream_id >= s->snd_conf.streams ? NULL
157         : &s->pcm->pcm_params[stream_id];
158 }
159
160 /*
161  * Set the given stream params.
162  * Called by both virtio_snd_handle_pcm_set_params and during device
163  * initialization.
164  * Returns the response status code. (VIRTIO_SND_S_*).
165  *
166  * @s: VirtIOSound device
167  * @params: The PCM params as defined in the virtio specification
168  */
169 static
170 uint32_t virtio_snd_set_pcm_params(VirtIOSound *s,
171                                    uint32_t stream_id,
172                                    virtio_snd_pcm_set_params *params)
173 {
174     virtio_snd_pcm_set_params *st_params;
175
176     if (stream_id >= s->snd_conf.streams || s->pcm->pcm_params == NULL) {
177         /*
178          * TODO: do we need to set DEVICE_NEEDS_RESET?
179          */
180         virtio_error(VIRTIO_DEVICE(s), "Streams have not been initialized.\n");
181         return cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
182     }
183
184     st_params = virtio_snd_pcm_get_params(s, stream_id);
185
186     if (params->channels < 1 || params->channels > AUDIO_MAX_CHANNELS) {
187         error_report("Number of channels is not supported.");
188         return cpu_to_le32(VIRTIO_SND_S_NOT_SUPP);
189     }
190     if (!(supported_formats & BIT(params->format))) {
191         error_report("Stream format is not supported.");
192         return cpu_to_le32(VIRTIO_SND_S_NOT_SUPP);
193     }
194     if (!(supported_rates & BIT(params->rate))) {
195         error_report("Stream rate is not supported.");
196         return cpu_to_le32(VIRTIO_SND_S_NOT_SUPP);
197     }
198
199     st_params->buffer_bytes = le32_to_cpu(params->buffer_bytes);
200     st_params->period_bytes = le32_to_cpu(params->period_bytes);
201     st_params->features = le32_to_cpu(params->features);
202     /* the following are uint8_t, so there's no need to bswap the values. */
203     st_params->channels = params->channels;
204     st_params->format = params->format;
205     st_params->rate = params->rate;
206
207     return cpu_to_le32(VIRTIO_SND_S_OK);
208 }
209
210 /*
211  * Get a QEMU Audiosystem compatible format value from a VIRTIO_SND_PCM_FMT_*
212  */
213 static AudioFormat virtio_snd_get_qemu_format(uint32_t format)
214 {
215     #define CASE(FMT)               \
216     case VIRTIO_SND_PCM_FMT_##FMT:  \
217         return AUDIO_FORMAT_##FMT;
218
219     switch (format) {
220     CASE(U8)
221     CASE(S8)
222     CASE(U16)
223     CASE(S16)
224     CASE(U32)
225     CASE(S32)
226     case VIRTIO_SND_PCM_FMT_FLOAT:
227         return AUDIO_FORMAT_F32;
228     default:
229         g_assert_not_reached();
230     }
231
232     #undef CASE
233 }
234
235 /*
236  * Get a QEMU Audiosystem compatible frequency value from a
237  * VIRTIO_SND_PCM_RATE_*
238  */
239 static uint32_t virtio_snd_get_qemu_freq(uint32_t rate)
240 {
241     #define CASE(RATE)               \
242     case VIRTIO_SND_PCM_RATE_##RATE: \
243         return RATE;
244
245     switch (rate) {
246     CASE(5512)
247     CASE(8000)
248     CASE(11025)
249     CASE(16000)
250     CASE(22050)
251     CASE(32000)
252     CASE(44100)
253     CASE(48000)
254     CASE(64000)
255     CASE(88200)
256     CASE(96000)
257     CASE(176400)
258     CASE(192000)
259     CASE(384000)
260     default:
261         g_assert_not_reached();
262     }
263
264     #undef CASE
265 }
266
267 /*
268  * Get QEMU Audiosystem compatible audsettings from virtio based pcm stream
269  * params.
270  */
271 static void virtio_snd_get_qemu_audsettings(audsettings *as,
272                                             virtio_snd_pcm_set_params *params)
273 {
274     as->nchannels = MIN(AUDIO_MAX_CHANNELS, params->channels);
275     as->fmt = virtio_snd_get_qemu_format(params->format);
276     as->freq = virtio_snd_get_qemu_freq(params->rate);
277     as->endianness = target_words_bigendian() ? 1 : 0;
278 }
279
280 /*
281  * Close a stream and free all its resources.
282  *
283  * @stream: VirtIOSoundPCMStream *stream
284  */
285 static void virtio_snd_pcm_close(VirtIOSoundPCMStream *stream)
286 {
287 }
288
289 /*
290  * Prepares a VirtIOSound card stream.
291  * Returns the response status code. (VIRTIO_SND_S_*).
292  *
293  * @s: VirtIOSound device
294  * @stream_id: stream id
295  */
296 static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s, uint32_t stream_id)
297 {
298     audsettings as;
299     virtio_snd_pcm_set_params *params;
300     VirtIOSoundPCMStream *stream;
301
302     if (s->pcm->streams == NULL ||
303         s->pcm->pcm_params == NULL ||
304         stream_id >= s->snd_conf.streams) {
305         return cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
306     }
307
308     params = virtio_snd_pcm_get_params(s, stream_id);
309     if (params == NULL) {
310         return cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
311     }
312
313     stream = virtio_snd_pcm_get_stream(s, stream_id);
314     if (stream == NULL) {
315         stream = g_new0(VirtIOSoundPCMStream, 1);
316         stream->active = false;
317         stream->id = stream_id;
318         stream->pcm = s->pcm;
319         stream->s = s;
320
321         /*
322          * stream_id >= s->snd_conf.streams was checked before so this is
323          * in-bounds
324          */
325         s->pcm->streams[stream_id] = stream;
326     }
327
328     virtio_snd_get_qemu_audsettings(&as, params);
329     stream->info.direction = stream_id < s->snd_conf.streams / 2 +
330         (s->snd_conf.streams & 1) ? VIRTIO_SND_D_OUTPUT : VIRTIO_SND_D_INPUT;
331     stream->info.hdr.hda_fn_nid = VIRTIO_SOUND_HDA_FN_NID;
332     stream->info.features = 0;
333     stream->info.channels_min = 1;
334     stream->info.channels_max = as.nchannels;
335     stream->info.formats = supported_formats;
336     stream->info.rates = supported_rates;
337     stream->params = *params;
338
339     stream->positions[0] = VIRTIO_SND_CHMAP_FL;
340     stream->positions[1] = VIRTIO_SND_CHMAP_FR;
341     stream->as = as;
342
343     return cpu_to_le32(VIRTIO_SND_S_OK);
344 }
345
346 static const char *print_code(uint32_t code)
347 {
348     #define CASE(CODE)            \
349     case VIRTIO_SND_R_##CODE:     \
350         return "VIRTIO_SND_R_"#CODE
351
352     switch (code) {
353     CASE(JACK_INFO);
354     CASE(JACK_REMAP);
355     CASE(PCM_INFO);
356     CASE(PCM_SET_PARAMS);
357     CASE(PCM_PREPARE);
358     CASE(PCM_RELEASE);
359     CASE(PCM_START);
360     CASE(PCM_STOP);
361     CASE(CHMAP_INFO);
362     default:
363         return "invalid code";
364     }
365
366     #undef CASE
367 };
368
369 /*
370  * The actual processing done in virtio_snd_process_cmdq().
371  *
372  * @s: VirtIOSound device
373  * @cmd: control command request
374  */
375 static inline void
376 process_cmd(VirtIOSound *s, virtio_snd_ctrl_command *cmd)
377 {
378     uint32_t code;
379     size_t msg_sz = iov_to_buf(cmd->elem->out_sg,
380                                cmd->elem->out_num,
381                                0,
382                                &cmd->ctrl,
383                                sizeof(virtio_snd_hdr));
384
385     if (msg_sz != sizeof(virtio_snd_hdr)) {
386         /*
387          * TODO: do we need to set DEVICE_NEEDS_RESET?
388          */
389         qemu_log_mask(LOG_GUEST_ERROR,
390                 "%s: virtio-snd command size incorrect %zu vs \
391                 %zu\n", __func__, msg_sz, sizeof(virtio_snd_hdr));
392         return;
393     }
394
395     code = le32_to_cpu(cmd->ctrl.code);
396
397     trace_virtio_snd_handle_code(code, print_code(code));
398
399     switch (code) {
400     case VIRTIO_SND_R_JACK_INFO:
401     case VIRTIO_SND_R_JACK_REMAP:
402         qemu_log_mask(LOG_UNIMP,
403                      "virtio_snd: jack functionality is unimplemented.\n");
404         cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_NOT_SUPP);
405         break;
406     case VIRTIO_SND_R_PCM_INFO:
407     case VIRTIO_SND_R_PCM_SET_PARAMS:
408     case VIRTIO_SND_R_PCM_PREPARE:
409     case VIRTIO_SND_R_PCM_START:
410     case VIRTIO_SND_R_PCM_STOP:
411     case VIRTIO_SND_R_PCM_RELEASE:
412         cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_NOT_SUPP);
413         break;
414     case VIRTIO_SND_R_CHMAP_INFO:
415         qemu_log_mask(LOG_UNIMP,
416                      "virtio_snd: chmap info functionality is unimplemented.\n");
417         trace_virtio_snd_handle_chmap_info();
418         cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_NOT_SUPP);
419         break;
420     default:
421         /* error */
422         error_report("virtio snd header not recognized: %"PRIu32, code);
423         cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
424     }
425
426     iov_from_buf(cmd->elem->in_sg,
427                  cmd->elem->in_num,
428                  0,
429                  &cmd->resp,
430                  sizeof(virtio_snd_hdr));
431     virtqueue_push(cmd->vq, cmd->elem, sizeof(virtio_snd_hdr));
432     virtio_notify(VIRTIO_DEVICE(s), cmd->vq);
433 }
434
435 /*
436  * Consume all elements in command queue.
437  *
438  * @s: VirtIOSound device
439  */
440 static void virtio_snd_process_cmdq(VirtIOSound *s)
441 {
442     virtio_snd_ctrl_command *cmd;
443
444     if (unlikely(qatomic_read(&s->processing_cmdq))) {
445         return;
446     }
447
448     WITH_QEMU_LOCK_GUARD(&s->cmdq_mutex) {
449         qatomic_set(&s->processing_cmdq, true);
450         while (!QTAILQ_EMPTY(&s->cmdq)) {
451             cmd = QTAILQ_FIRST(&s->cmdq);
452
453             /* process command */
454             process_cmd(s, cmd);
455
456             QTAILQ_REMOVE(&s->cmdq, cmd, next);
457
458             virtio_snd_ctrl_cmd_free(cmd);
459         }
460         qatomic_set(&s->processing_cmdq, false);
461     }
462 }
463
464 /*
465  * The control message handler. Pops an element from the control virtqueue,
466  * and stores them to VirtIOSound's cmdq queue and finally calls
467  * virtio_snd_process_cmdq() for processing.
468  *
469  * @vdev: VirtIOSound device
470  * @vq: Control virtqueue
471  */
472 static void virtio_snd_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
473 {
474     VirtIOSound *s = VIRTIO_SND(vdev);
475     VirtQueueElement *elem;
476     virtio_snd_ctrl_command *cmd;
477
478     trace_virtio_snd_handle_ctrl(vdev, vq);
479
480     if (!virtio_queue_ready(vq)) {
481         return;
482     }
483
484     elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
485     while (elem) {
486         cmd = g_new0(virtio_snd_ctrl_command, 1);
487         cmd->elem = elem;
488         cmd->vq = vq;
489         cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_OK);
490         QTAILQ_INSERT_TAIL(&s->cmdq, cmd, next);
491         elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
492     }
493
494     virtio_snd_process_cmdq(s);
495 }
496
497 /*
498  * The event virtqueue handler.
499  * Not implemented yet.
500  *
501  * @vdev: VirtIOSound device
502  * @vq: event vq
503  */
504 static void virtio_snd_handle_event(VirtIODevice *vdev, VirtQueue *vq)
505 {
506     qemu_log_mask(LOG_UNIMP, "virtio_snd: event queue is unimplemented.\n");
507     trace_virtio_snd_handle_event();
508 }
509
510 /*
511  * Stub buffer virtqueue handler.
512  *
513  * @vdev: VirtIOSound device
514  * @vq: virtqueue
515  */
516 static void virtio_snd_handle_xfer(VirtIODevice *vdev, VirtQueue *vq) {}
517
518 static uint64_t get_features(VirtIODevice *vdev, uint64_t features,
519                              Error **errp)
520 {
521     /*
522      * virtio-v1.2-csd01, 5.14.3,
523      * Feature Bits
524      * None currently defined.
525      */
526     VirtIOSound *s = VIRTIO_SND(vdev);
527     features |= s->features;
528
529     trace_virtio_snd_get_features(vdev, features);
530
531     return features;
532 }
533
534 static void
535 virtio_snd_vm_state_change(void *opaque, bool running,
536                                        RunState state)
537 {
538     if (running) {
539         trace_virtio_snd_vm_state_running();
540     } else {
541         trace_virtio_snd_vm_state_stopped();
542     }
543 }
544
545 static void virtio_snd_realize(DeviceState *dev, Error **errp)
546 {
547     ERRP_GUARD();
548     VirtIOSound *vsnd = VIRTIO_SND(dev);
549     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
550     virtio_snd_pcm_set_params default_params = { 0 };
551     uint32_t status;
552
553     vsnd->pcm = NULL;
554     vsnd->vmstate =
555         qemu_add_vm_change_state_handler(virtio_snd_vm_state_change, vsnd);
556
557     trace_virtio_snd_realize(vsnd);
558
559     vsnd->pcm = g_new0(VirtIOSoundPCM, 1);
560     vsnd->pcm->snd = vsnd;
561     vsnd->pcm->streams =
562         g_new0(VirtIOSoundPCMStream *, vsnd->snd_conf.streams);
563     vsnd->pcm->pcm_params =
564         g_new0(virtio_snd_pcm_set_params, vsnd->snd_conf.streams);
565
566     virtio_init(vdev, VIRTIO_ID_SOUND, sizeof(virtio_snd_config));
567     virtio_add_feature(&vsnd->features, VIRTIO_F_VERSION_1);
568
569     /* set number of jacks and streams */
570     if (vsnd->snd_conf.jacks > 8) {
571         error_setg(errp,
572                    "Invalid number of jacks: %"PRIu32,
573                    vsnd->snd_conf.jacks);
574         return;
575     }
576     if (vsnd->snd_conf.streams < 1 || vsnd->snd_conf.streams > 10) {
577         error_setg(errp,
578                    "Invalid number of streams: %"PRIu32,
579                     vsnd->snd_conf.streams);
580         return;
581     }
582
583     if (vsnd->snd_conf.chmaps > VIRTIO_SND_CHMAP_MAX_SIZE) {
584         error_setg(errp,
585                    "Invalid number of channel maps: %"PRIu32,
586                    vsnd->snd_conf.chmaps);
587         return;
588     }
589
590     AUD_register_card("virtio-sound", &vsnd->card, errp);
591
592     /* set default params for all streams */
593     default_params.features = 0;
594     default_params.buffer_bytes = cpu_to_le32(8192);
595     default_params.period_bytes = cpu_to_le32(2048);
596     default_params.channels = 2;
597     default_params.format = VIRTIO_SND_PCM_FMT_S16;
598     default_params.rate = VIRTIO_SND_PCM_RATE_48000;
599     vsnd->queues[VIRTIO_SND_VQ_CONTROL] =
600         virtio_add_queue(vdev, 64, virtio_snd_handle_ctrl);
601     vsnd->queues[VIRTIO_SND_VQ_EVENT] =
602         virtio_add_queue(vdev, 64, virtio_snd_handle_event);
603     vsnd->queues[VIRTIO_SND_VQ_TX] =
604         virtio_add_queue(vdev, 64, virtio_snd_handle_xfer);
605     vsnd->queues[VIRTIO_SND_VQ_RX] =
606         virtio_add_queue(vdev, 64, virtio_snd_handle_xfer);
607     qemu_mutex_init(&vsnd->cmdq_mutex);
608     QTAILQ_INIT(&vsnd->cmdq);
609
610     for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) {
611         status = virtio_snd_set_pcm_params(vsnd, i, &default_params);
612         if (status != cpu_to_le32(VIRTIO_SND_S_OK)) {
613             error_setg(errp,
614                        "Can't initalize stream params, device responded with %s.",
615                        print_code(status));
616             return;
617         }
618         status = virtio_snd_pcm_prepare(vsnd, i);
619         if (status != cpu_to_le32(VIRTIO_SND_S_OK)) {
620             error_setg(errp,
621                        "Can't prepare streams, device responded with %s.",
622                        print_code(status));
623             return;
624         }
625     }
626 }
627
628 static void virtio_snd_unrealize(DeviceState *dev)
629 {
630     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
631     VirtIOSound *vsnd = VIRTIO_SND(dev);
632     VirtIOSoundPCMStream *stream;
633
634     qemu_del_vm_change_state_handler(vsnd->vmstate);
635     trace_virtio_snd_unrealize(vsnd);
636
637     if (vsnd->pcm) {
638         if (vsnd->pcm->streams) {
639             for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) {
640                 stream = vsnd->pcm->streams[i];
641                 if (stream) {
642                     virtio_snd_process_cmdq(stream->s);
643                     virtio_snd_pcm_close(stream);
644                     g_free(stream);
645                 }
646             }
647             g_free(vsnd->pcm->streams);
648         }
649         g_free(vsnd->pcm->pcm_params);
650         g_free(vsnd->pcm);
651         vsnd->pcm = NULL;
652     }
653     AUD_remove_card(&vsnd->card);
654     qemu_mutex_destroy(&vsnd->cmdq_mutex);
655     virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_CONTROL]);
656     virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_EVENT]);
657     virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_TX]);
658     virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_RX]);
659     virtio_cleanup(vdev);
660 }
661
662
663 static void virtio_snd_reset(VirtIODevice *vdev)
664 {
665     VirtIOSound *s = VIRTIO_SND(vdev);
666     virtio_snd_ctrl_command *cmd;
667
668     WITH_QEMU_LOCK_GUARD(&s->cmdq_mutex) {
669         while (!QTAILQ_EMPTY(&s->cmdq)) {
670             cmd = QTAILQ_FIRST(&s->cmdq);
671             QTAILQ_REMOVE(&s->cmdq, cmd, next);
672             virtio_snd_ctrl_cmd_free(cmd);
673         }
674     }
675 }
676
677 static void virtio_snd_class_init(ObjectClass *klass, void *data)
678 {
679     DeviceClass *dc = DEVICE_CLASS(klass);
680     VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
681
682
683     set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
684     device_class_set_props(dc, virtio_snd_properties);
685
686     dc->vmsd = &vmstate_virtio_snd;
687     vdc->vmsd = &vmstate_virtio_snd_device;
688     vdc->realize = virtio_snd_realize;
689     vdc->unrealize = virtio_snd_unrealize;
690     vdc->get_config = virtio_snd_get_config;
691     vdc->set_config = virtio_snd_set_config;
692     vdc->get_features = get_features;
693     vdc->reset = virtio_snd_reset;
694     vdc->legacy_features = 0;
695 }
696
697 static const TypeInfo virtio_snd_types[] = {
698     {
699       .name          = TYPE_VIRTIO_SND,
700       .parent        = TYPE_VIRTIO_DEVICE,
701       .instance_size = sizeof(VirtIOSound),
702       .class_init    = virtio_snd_class_init,
703     }
704 };
705
706 DEFINE_TYPES(virtio_snd_types)