@@ -332,8 +332,7 @@ static int virtio_snd_stream_cb(const void *input,
332332 PaStreamCallbackFlags status_flags ,
333333 void * user_data );
334334static 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 */ );
337336static void __virtio_snd_frame_enqueue (void * payload ,
338337 uint32_t n ,
339338 uint32_t stream_id );
@@ -347,11 +346,17 @@ typedef struct {
347346 */
348347static 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
463481static 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
916952static 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