Skip to content

Commit 72027da

Browse files
committed
virtio-snd: implement queue function lookup table
Introduce a function lookup table to handle virtio-snd queues. This prepares the device for upcoming PCM I/O receive and event features by allowing queue ID indexing for callbacks. - Set unimplemented PCM I/O receive and event entries to return an error. - Set control and event queue flush entries to return an error as flushing is not required for these queues.
1 parent bcc3c7b commit 72027da

File tree

1 file changed

+53
-23
lines changed

1 file changed

+53
-23
lines changed

virtio-snd.c

Lines changed: 53 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -332,8 +332,7 @@ static int virtio_snd_stream_cb(const void *input,
332332
PaStreamCallbackFlags status_flags,
333333
void *user_data);
334334
static void virtio_queue_notify_handler(virtio_snd_state_t *vsnd,
335-
int index, /* virtq index */
336-
vsnd_virtq_cb cb);
335+
int index /* virtq index */);
337336
static void __virtio_snd_frame_enqueue(void *payload,
338337
uint32_t n,
339338
uint32_t stream_id);
@@ -347,11 +346,17 @@ typedef struct {
347346
*/
348347
static uint32_t flush_stream_id = 0;
349348

350-
#define VSND_GEN_TX_QUEUE_HANDLER(NAME_SUFFIX, WRITE) \
351-
static int virtio_snd_tx_desc_##NAME_SUFFIX##_handler( \
352-
virtio_snd_state_t *vsnd, const virtio_snd_queue_t *queue, \
353-
uint32_t desc_idx, uint32_t *plen) \
354-
{ \
349+
static int virtio_snd_unimplemented(virtio_snd_state_t *vsnd,
350+
const virtio_snd_queue_t *queue,
351+
uint32_t desc_idx,
352+
uint32_t *plen)
353+
{
354+
fprintf(stderr, "function not implemented\n");
355+
return -1;
356+
}
357+
358+
#define VSND_TX_QUEUE_BODY(WRITE) \
359+
do { \
355360
/* A PCM I/O message uses at least 3 virtqueue descriptors to \
356361
* represent a PCM data of a period size. \
357362
* The first part contains one descriptor as follows: \
@@ -455,10 +460,23 @@ static uint32_t flush_stream_id = 0;
455460
\
456461
finally: \
457462
return 0; \
458-
}
463+
} while (0)
459464

460-
VSND_GEN_TX_QUEUE_HANDLER(normal, 1);
461-
VSND_GEN_TX_QUEUE_HANDLER(flush, 0);
465+
static int virtio_snd_tx_desc_handler(virtio_snd_state_t *vsnd,
466+
const virtio_snd_queue_t *queue,
467+
uint32_t desc_idx,
468+
uint32_t *plen)
469+
{
470+
VSND_TX_QUEUE_BODY(1);
471+
}
472+
473+
static int virtio_snd_io_desc_flush_handler(virtio_snd_state_t *vsnd,
474+
const virtio_snd_queue_t *queue,
475+
uint32_t desc_idx,
476+
uint32_t *plen)
477+
{
478+
VSND_TX_QUEUE_BODY(0);
479+
}
462480

463481
static void virtio_snd_set_fail(virtio_snd_state_t *vsnd)
464482
{
@@ -770,7 +788,9 @@ static void virtio_snd_read_pcm_release(const virtio_snd_pcm_hdr_t *query,
770788
* - The device MUST NOT complete the control request while there
771789
* are pending I/O messages for the specified stream ID.
772790
*/
773-
virtio_queue_notify_handler(vsnd, 2, virtio_snd_tx_desc_flush_handler);
791+
#define VSND_FLUSH_QUEUE 0x4
792+
virtio_queue_notify_handler(vsnd, VSND_FLUSH_QUEUE | 0x2);
793+
#undef VSND_FLUSH_QUEUE
774794

775795
*plen = 0;
776796
}
@@ -912,6 +932,22 @@ static int virtio_snd_ctrl_desc_handler(virtio_snd_state_t *vsnd,
912932
return 0;
913933
}
914934

935+
/* virtq device operation lookup table */
936+
/* The entry of flush queue operation (whether it is needed or not
937+
* for each type of queue) start from 0x04.
938+
* So we can set bit with 0x04 when we need to flush queue. */
939+
static vsnd_virtq_cb __virtio_snd_queue_op_tbl[8] = {
940+
virtio_snd_ctrl_desc_handler, /* control queue */
941+
virtio_snd_unimplemented, /* event queue, which is not implemented yet */
942+
virtio_snd_tx_desc_handler, /* TX queue */
943+
virtio_snd_unimplemented, /* RX queue, which is not implemented yet */
944+
virtio_snd_unimplemented, /* no need to flush control queue, so just return
945+
an error */
946+
virtio_snd_unimplemented, /* no need to flush event queue, so just return an
947+
error */
948+
virtio_snd_io_desc_flush_handler, /* flush TX queue */
949+
virtio_snd_unimplemented, /* flush RX queue, which is not implemented yet */
950+
};
915951

916952
static void __virtio_snd_frame_enqueue(void *payload,
917953
uint32_t n,
@@ -949,16 +985,10 @@ static void __virtio_snd_frame_enqueue(void *payload,
949985
pthread_mutex_unlock(&props->lock.lock);
950986
}
951987

952-
static void virtio_queue_notify_handler(
953-
virtio_snd_state_t *vsnd,
954-
int index,
955-
int (*handler)(virtio_snd_state_t *,
956-
const virtio_snd_queue_t *,
957-
uint32_t,
958-
uint32_t *))
988+
static void virtio_queue_notify_handler(virtio_snd_state_t *vsnd, int index)
959989
{
960990
uint32_t *ram = vsnd->ram;
961-
virtio_snd_queue_t *queue = &vsnd->queues[index];
991+
virtio_snd_queue_t *queue = &vsnd->queues[index & 0x03];
962992
if (vsnd->Status & VIRTIO_STATUS__DEVICE_NEEDS_RESET)
963993
return;
964994

@@ -992,7 +1022,8 @@ static void virtio_queue_notify_handler(
9921022
* descriptor list.
9931023
*/
9941024
uint32_t len = 0;
995-
int result = handler(vsnd, queue, buffer_idx, &len);
1025+
int result = __virtio_snd_queue_op_tbl[index & 0x07](vsnd, queue,
1026+
buffer_idx, &len);
9961027
if (result != 0)
9971028
return virtio_snd_set_fail(vsnd);
9981029

@@ -1026,7 +1057,7 @@ static void *func(void *args)
10261057
pthread_cond_wait(&virtio_snd_tx_cond, &virtio_snd_mutex);
10271058

10281059
tx_ev_notify--;
1029-
virtio_queue_notify_handler(vsnd, 2, virtio_snd_tx_desc_normal_handler);
1060+
virtio_queue_notify_handler(vsnd, 2);
10301061

10311062
pthread_mutex_unlock(&virtio_snd_mutex);
10321063
}
@@ -1140,8 +1171,7 @@ static bool virtio_snd_reg_write(virtio_snd_state_t *vsnd,
11401171
if (value < ARRAY_SIZE(vsnd->queues)) {
11411172
switch (value) {
11421173
case VSND_QUEUE_CTRL:
1143-
virtio_queue_notify_handler(vsnd, value,
1144-
virtio_snd_ctrl_desc_handler);
1174+
virtio_queue_notify_handler(vsnd, value);
11451175
break;
11461176
case VSND_QUEUE_TX:
11471177
tx_ev_notify++;

0 commit comments

Comments
 (0)