@@ -331,9 +331,7 @@ static int virtio_snd_stream_cb(const void *input,
331331 const PaStreamCallbackTimeInfo * time_info ,
332332 PaStreamCallbackFlags status_flags ,
333333 void * user_data );
334- static void virtio_queue_notify_handler (virtio_snd_state_t * vsnd ,
335- int index , /* virtq index */
336- vsnd_virtq_cb cb );
334+ static void virtio_queue_notify_handler (virtio_snd_state_t * vsnd , int index );
337335static void __virtio_snd_frame_enqueue (void * payload ,
338336 uint32_t n ,
339337 uint32_t stream_id );
@@ -347,11 +345,8 @@ typedef struct {
347345 */
348346static uint32_t flush_stream_id = 0 ;
349347
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- { \
348+ #define VSND_TX_QUEUE_BODY (WRITE ) \
349+ do { \
355350 /* A PCM I/O message uses at least 3 virtqueue descriptors to \
356351 * represent a PCM data of a period size. \
357352 * The first part contains one descriptor as follows: \
@@ -455,10 +450,23 @@ static uint32_t flush_stream_id = 0;
455450 \
456451 finally : \
457452 return 0 ; \
458- }
453+ } while ( 0 )
459454
460- VSND_GEN_TX_QUEUE_HANDLER (normal , 1 );
461- VSND_GEN_TX_QUEUE_HANDLER (flush , 0 );
455+ static int virtio_snd_tx_desc_handler (virtio_snd_state_t * vsnd ,
456+ const virtio_snd_queue_t * queue ,
457+ uint32_t desc_idx ,
458+ uint32_t * plen )
459+ {
460+ VSND_TX_QUEUE_BODY (1 );
461+ }
462+
463+ static int virtio_snd_io_desc_flush_handler (virtio_snd_state_t * vsnd ,
464+ const virtio_snd_queue_t * queue ,
465+ uint32_t desc_idx ,
466+ uint32_t * plen )
467+ {
468+ VSND_TX_QUEUE_BODY (0 );
469+ }
462470
463471static void virtio_snd_set_fail (virtio_snd_state_t * vsnd )
464472{
@@ -723,6 +731,7 @@ static void virtio_snd_read_pcm_stop(const virtio_snd_pcm_hdr_t *query,
723731 * plen = 0 ;
724732}
725733
734+ #define VSND_FLUSH_QUEUE 0x4
726735static void virtio_snd_read_pcm_release (const virtio_snd_pcm_hdr_t * query ,
727736 uint32_t * plen ,
728737 virtio_snd_state_t * vsnd )
@@ -770,7 +779,7 @@ static void virtio_snd_read_pcm_release(const virtio_snd_pcm_hdr_t *query,
770779 * - The device MUST NOT complete the control request while there
771780 * are pending I/O messages for the specified stream ID.
772781 */
773- virtio_queue_notify_handler (vsnd , 2 , virtio_snd_tx_desc_flush_handler );
782+ virtio_queue_notify_handler (vsnd , VSND_FLUSH_QUEUE | 0x2 );
774783
775784 * plen = 0 ;
776785}
@@ -912,6 +921,20 @@ static int virtio_snd_ctrl_desc_handler(virtio_snd_state_t *vsnd,
912921 return 0 ;
913922}
914923
924+ /* virtq device operation lookup table */
925+ /* The entry of flush queue operation (whether it is needed or not
926+ * for each type of queue) starts from 0x04.
927+ * So we can set bit with 0x04 when we need to flush queue. */
928+ static vsnd_virtq_cb __virtio_snd_queue_op_tbl [8 ] = {
929+ virtio_snd_ctrl_desc_handler , /* control queue */
930+ NULL , /* event queue */
931+ virtio_snd_tx_desc_handler , /* TX queue */
932+ NULL , /* RX queue */
933+ NULL , /* no need to flush control queue, so trigger a failed null check */
934+ NULL , /* no need to flush event queue, so trigger a failed null check */
935+ virtio_snd_io_desc_flush_handler , /* flush TX queue */
936+ NULL , /* flush RX queue */
937+ };
915938
916939static void __virtio_snd_frame_enqueue (void * payload ,
917940 uint32_t n ,
@@ -949,16 +972,10 @@ static void __virtio_snd_frame_enqueue(void *payload,
949972 pthread_mutex_unlock (& props -> lock .lock );
950973}
951974
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 * ))
975+ static void virtio_queue_notify_handler (virtio_snd_state_t * vsnd , int index )
959976{
960977 uint32_t * ram = vsnd -> ram ;
961- virtio_snd_queue_t * queue = & vsnd -> queues [index ];
978+ virtio_snd_queue_t * queue = & vsnd -> queues [index & 0x03 ];
962979 if (vsnd -> Status & VIRTIO_STATUS__DEVICE_NEEDS_RESET )
963980 return ;
964981
@@ -992,6 +1009,9 @@ static void virtio_queue_notify_handler(
9921009 * descriptor list.
9931010 */
9941011 uint32_t len = 0 ;
1012+ vsnd_virtq_cb handler = __virtio_snd_queue_op_tbl [index & 0x07 ];
1013+ if (!handler )
1014+ return virtio_snd_set_fail (vsnd );
9951015 int result = handler (vsnd , queue , buffer_idx , & len );
9961016 if (result != 0 )
9971017 return virtio_snd_set_fail (vsnd );
@@ -1026,7 +1046,7 @@ static void *func(void *args)
10261046 pthread_cond_wait (& virtio_snd_tx_cond , & virtio_snd_mutex );
10271047
10281048 tx_ev_notify -- ;
1029- virtio_queue_notify_handler (vsnd , 2 , virtio_snd_tx_desc_normal_handler );
1049+ virtio_queue_notify_handler (vsnd , 2 );
10301050
10311051 pthread_mutex_unlock (& virtio_snd_mutex );
10321052 }
@@ -1140,8 +1160,7 @@ static bool virtio_snd_reg_write(virtio_snd_state_t *vsnd,
11401160 if (value < ARRAY_SIZE (vsnd -> queues )) {
11411161 switch (value ) {
11421162 case VSND_QUEUE_CTRL :
1143- virtio_queue_notify_handler (vsnd , value ,
1144- virtio_snd_ctrl_desc_handler );
1163+ virtio_queue_notify_handler (vsnd , value );
11451164 break ;
11461165 case VSND_QUEUE_TX :
11471166 tx_ev_notify ++ ;
0 commit comments