|
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