|
4 | 4 | #include <stdio.h> |
5 | 5 | #include <stdlib.h> |
6 | 6 | #include <string.h> |
7 | | -#define CNFA_IMPLEMENTATION |
8 | | -#include "CNFA_sf.h" |
| 7 | + |
9 | 8 | #include "portaudio.h" |
10 | 9 |
|
11 | 10 | #include "device.h" |
@@ -336,91 +335,91 @@ typedef struct { |
336 | 335 | struct virtq_desc vq_desc; |
337 | 336 | struct list_head q; |
338 | 337 | } virtq_desc_queue_node_t; |
339 | | -#define VSND_GEN_TX_QUEUE_HANDLER(NAME_SUFFIX, WRITE) \ |
340 | | - static int virtio_snd_tx_desc_##NAME_SUFFIX##_handler( \ |
341 | | - virtio_snd_state_t *vsnd, const virtio_snd_queue_t *queue, \ |
342 | | - uint32_t desc_idx, uint32_t *plen) \ |
343 | | - { \ |
344 | | - /* A PCM I/O message uses at least 3 virtqueue descriptors to \ |
345 | | - * represent a PCM data of a period size. \ |
346 | | - * The first part contains one descriptor as follows: \ |
347 | | - * struct virtio_snd_pcm_xfer \ |
348 | | - * The second part contains one or more descriptors \ |
349 | | - * representing PCM frames. \ |
350 | | - * the last part contains one descriptor as follows: \ |
351 | | - * struct virtio_snd_pcm_status \ |
352 | | - */ \ |
353 | | - virtq_desc_queue_node_t *node; \ |
354 | | - struct list_head q; \ |
355 | | - INIT_LIST_HEAD(&q); \ |
356 | | - \ |
357 | | - /* Collect the descriptors */ \ |
358 | | - int cnt = 0; \ |
359 | | - for (;;) { \ |
360 | | - /* The size of the `struct virtq_desc` is 4 words */ \ |
361 | | - const uint32_t *desc = \ |
362 | | - &vsnd->ram[queue->QueueDesc + desc_idx * 4]; \ |
363 | | - \ |
364 | | - /* Retrieve the fields of current descriptor */ \ |
365 | | - node = (virtq_desc_queue_node_t *) malloc(sizeof(*node)); \ |
366 | | - node->vq_desc.addr = desc[0]; \ |
367 | | - node->vq_desc.len = desc[2]; \ |
368 | | - node->vq_desc.flags = desc[3]; \ |
369 | | - list_push(&node->q, &q); \ |
370 | | - desc_idx = desc[3] >> 16; /* vq_desc[desc_cnt].next */ \ |
371 | | - \ |
372 | | - cnt++; \ |
373 | | - \ |
374 | | - /* Leave the loop if next-flag is not set */ \ |
375 | | - if (!(desc[3] & VIRTIO_DESC_F_NEXT)) \ |
376 | | - break; \ |
377 | | - } \ |
378 | | - \ |
379 | | - int idx = 0; \ |
380 | | - uint32_t stream_id = 0; /* Explicitly set the stream_id */ \ |
381 | | - uintptr_t base = (uintptr_t) vsnd->ram; \ |
382 | | - uint32_t ret_len = 0; \ |
383 | | - list_for_each_entry (node, &q, q) { \ |
384 | | - uint32_t addr = node->vq_desc.addr; \ |
385 | | - uint32_t len = node->vq_desc.len; \ |
386 | | - if (idx == 0) { /* the first descriptor */ \ |
387 | | - const virtio_snd_pcm_xfer_t *request = \ |
388 | | - (virtio_snd_pcm_xfer_t *) (base + addr); \ |
389 | | - stream_id = request->stream_id; \ |
390 | | - goto early_continue; \ |
391 | | - } else if (idx == cnt - 1) { /* the last descriptor */ \ |
392 | | - virtio_snd_pcm_status_t *response = \ |
393 | | - (virtio_snd_pcm_status_t *) (base + addr); \ |
394 | | - response->status = VIRTIO_SND_S_OK; \ |
395 | | - response->latency_bytes = ret_len; \ |
396 | | - *plen = sizeof(*response); \ |
397 | | - goto early_continue; \ |
398 | | - } \ |
399 | | - \ |
400 | | - if (WRITE) { \ |
401 | | - void *payload = (void *) (base + addr); \ |
402 | | - __virtio_snd_frame_enqueue(payload, len, stream_id); \ |
403 | | - } \ |
404 | | - ret_len += len; \ |
405 | | - \ |
406 | | - early_continue: \ |
407 | | - idx++; \ |
408 | | - } \ |
409 | | - \ |
410 | | - if (WRITE) { \ |
411 | | - virtio_snd_prop_t *props = &vsnd_props[stream_id]; \ |
412 | | - props->lock.buf_ev_notity++; \ |
413 | | - pthread_cond_signal(&props->lock.readable); \ |
414 | | - } \ |
415 | | - \ |
416 | | - /* Tear down the descriptor list and free space. */ \ |
417 | | - virtq_desc_queue_node_t *tmp = NULL; \ |
418 | | - list_for_each_entry_safe (node, tmp, &q, q) { \ |
419 | | - list_del(&node->q); \ |
420 | | - free(node); \ |
421 | | - } \ |
422 | | - \ |
423 | | - return 0; \ |
| 338 | +#define VSND_GEN_TX_QUEUE_HANDLER(NAME_SUFFIX, WRITE) \ |
| 339 | + static int virtio_snd_tx_desc_##NAME_SUFFIX##_handler( \ |
| 340 | + virtio_snd_state_t *vsnd, const virtio_snd_queue_t *queue, \ |
| 341 | + uint32_t desc_idx, uint32_t *plen) \ |
| 342 | + { \ |
| 343 | + /* A PCM I/O message uses at least 3 virtqueue descriptors to \ |
| 344 | + * represent a PCM data of a period size. \ |
| 345 | + * The first part contains one descriptor as follows: \ |
| 346 | + * struct virtio_snd_pcm_xfer \ |
| 347 | + * The second part contains one or more descriptors \ |
| 348 | + * representing PCM frames. \ |
| 349 | + * the last part contains one descriptor as follows: \ |
| 350 | + * struct virtio_snd_pcm_status \ |
| 351 | + */ \ |
| 352 | + virtq_desc_queue_node_t *node; \ |
| 353 | + struct list_head q; \ |
| 354 | + INIT_LIST_HEAD(&q); \ |
| 355 | + \ |
| 356 | + /* Collect the descriptors */ \ |
| 357 | + int cnt = 0; \ |
| 358 | + for (;;) { \ |
| 359 | + /* The size of the `struct virtq_desc` is 4 words */ \ |
| 360 | + const uint32_t *desc = \ |
| 361 | + &vsnd->ram[queue->QueueDesc + desc_idx * 4]; \ |
| 362 | + \ |
| 363 | + /* Retrieve the fields of current descriptor */ \ |
| 364 | + node = (virtq_desc_queue_node_t *) malloc(sizeof(*node)); \ |
| 365 | + node->vq_desc.addr = desc[0]; \ |
| 366 | + node->vq_desc.len = desc[2]; \ |
| 367 | + node->vq_desc.flags = desc[3]; \ |
| 368 | + list_push(&node->q, &q); \ |
| 369 | + desc_idx = desc[3] >> 16; /* vq_desc[desc_cnt].next */ \ |
| 370 | + \ |
| 371 | + cnt++; \ |
| 372 | + \ |
| 373 | + /* Leave the loop if next-flag is not set */ \ |
| 374 | + if (!(desc[3] & VIRTIO_DESC_F_NEXT)) \ |
| 375 | + break; \ |
| 376 | + } \ |
| 377 | + \ |
| 378 | + int idx = 0; \ |
| 379 | + uint32_t stream_id = 0; /* Explicitly set the stream_id */ \ |
| 380 | + uintptr_t base = (uintptr_t) vsnd->ram; \ |
| 381 | + uint32_t ret_len = 0; \ |
| 382 | + list_for_each_entry (node, &q, q) { \ |
| 383 | + uint32_t addr = node->vq_desc.addr; \ |
| 384 | + uint32_t len = node->vq_desc.len; \ |
| 385 | + if (idx == 0) { /* the first descriptor */ \ |
| 386 | + const virtio_snd_pcm_xfer_t *request = \ |
| 387 | + (virtio_snd_pcm_xfer_t *) (base + addr); \ |
| 388 | + stream_id = request->stream_id; \ |
| 389 | + goto early_continue; \ |
| 390 | + } else if (idx == cnt - 1) { /* the last descriptor */ \ |
| 391 | + virtio_snd_pcm_status_t *response = \ |
| 392 | + (virtio_snd_pcm_status_t *) (base + addr); \ |
| 393 | + response->status = VIRTIO_SND_S_OK; \ |
| 394 | + response->latency_bytes = ret_len; \ |
| 395 | + *plen = sizeof(*response); \ |
| 396 | + goto early_continue; \ |
| 397 | + } \ |
| 398 | + \ |
| 399 | + if (WRITE) { \ |
| 400 | + void *payload = (void *) (base + addr); \ |
| 401 | + __virtio_snd_frame_enqueue(payload, len, stream_id); \ |
| 402 | + } \ |
| 403 | + ret_len += len; \ |
| 404 | + \ |
| 405 | + early_continue: \ |
| 406 | + idx++; \ |
| 407 | + } \ |
| 408 | + \ |
| 409 | + if (WRITE) { \ |
| 410 | + virtio_snd_prop_t *props = &vsnd_props[stream_id]; \ |
| 411 | + props->lock.buf_ev_notity++; \ |
| 412 | + pthread_cond_signal(&props->lock.readable); \ |
| 413 | + } \ |
| 414 | + \ |
| 415 | + /* Tear down the descriptor list and free space. */ \ |
| 416 | + virtq_desc_queue_node_t *tmp = NULL; \ |
| 417 | + list_for_each_entry_safe (node, tmp, &q, q) { \ |
| 418 | + list_del(&node->q); \ |
| 419 | + free(node); \ |
| 420 | + } \ |
| 421 | + \ |
| 422 | + return 0; \ |
424 | 423 | } |
425 | 424 |
|
426 | 425 | VSND_GEN_TX_QUEUE_HANDLER(normal, true); |
|
0 commit comments