Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added vdma oneway transfer to library, fixed passing of frame info #118

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions driver/axidma_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,11 @@ int axidma_read_transfer(struct axidma_device *dev,
rx_tfr.process = get_current();
rx_tfr.cb_data = &dev->cb_data[trans->channel_id];

// Add in the frame information for VDMA transfers
if (rx_chan->type == AXIDMA_VDMA) {
memcpy(&rx_tfr.frame, &trans->frame, sizeof(rx_tfr.frame));
}

// Prepare the receive transfer
rc = axidma_prep_transfer(rx_chan, &rx_tfr);
if (rc < 0) {
Expand Down Expand Up @@ -436,6 +441,11 @@ int axidma_write_transfer(struct axidma_device *dev,
tx_tfr.notify_signal = dev->notify_signal;
tx_tfr.process = get_current();
tx_tfr.cb_data = &dev->cb_data[trans->channel_id];

// Add in the frame information for VDMA transfers
if (tx_chan->type == AXIDMA_VDMA) {
memcpy(&tx_tfr.frame, &trans->frame, sizeof(tx_tfr.frame));
}

// Prepare the transmit transfer
rc = axidma_prep_transfer(tx_chan, &tx_tfr);
Expand Down
26 changes: 26 additions & 0 deletions include/libaxidma.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,32 @@ void axidma_set_callback(axidma_dev_t dev, int channel, axidma_cb_t callback,
int axidma_oneway_transfer(axidma_dev_t dev, int channel, void *buf, size_t len,
bool wait);

/**
* Performs a single DMA transfer in the specified direction on the DMA channel.
*
* This function will perform a single DMA transfer using the specified buffer.
* If wait is false, then this function will be non-blocking, and if the user
* registered a callback function, it will be invoked upon completion of the
* transfer.
*
* The addresses \p buf and \p buf+\p len must be within a buffer that was
* previously allocated by #axidma_malloc or registered with
* #axidma_register_buffer. This function will abort if the channel is invalid.
*
* @param[in] dev An #axidma_dev_t returned by #axidma_init.
* @param[in] channel VDMA channel the transfer is performed on.
* @param[in] buf Address of the DMA buffer to transfer, previously allocated by
* #axidma_malloc or registered with #axidma_register_buffer.
* param[in] rx_frame Information about the video frame for the receive
* channel.
* @param[in] len Number of bytes that will be transfered.
* @param[in] wait Indicates if the transfer should be synchronous or
* asynchronous. If true, this function will block.
* @return 0 upon success, a negative number on failure.
**/
int axivdma_oneway_transfer(axidma_dev_t dev, int channel, void *buf,
struct axidma_video_frame *frame, size_t len, bool wait);

/**
* Performs a two coupled DMA transfers, one in the receive direction, the other
* in the transmit direction.
Expand Down
32 changes: 32 additions & 0 deletions library/libaxidma.c
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,38 @@ int axidma_oneway_transfer(axidma_dev_t dev, int channel, void *buf,
return 0;
}

/* This performs a one-way transfer over AXI VDMA, the direction being specified
* by the user. The user determines if this is blocking or not with `wait. */
int axivdma_oneway_transfer(axidma_dev_t dev, int channel, void *buf,
struct axidma_video_frame *frame, size_t len, bool wait)
{
int rc;
struct axidma_transaction trans;
unsigned long axidma_cmd;
dma_channel_t *dma_chan;

assert(find_channel(dev, channel) != NULL);

// Setup the argument structure to the IOCTL
dma_chan = find_channel(dev, channel);
trans.wait = wait;
trans.channel_id = channel;
trans.buf = buf;
trans.buf_len = len;
axidma_cmd = dir_to_ioctl(dma_chan->dir);

memcpy(&trans.frame, frame, sizeof(trans.frame));

// Perform the given transfer
rc = ioctl(dev->fd, axidma_cmd, &trans);
if (rc < 0) {
perror("Failed to perform the AXI DMA transfer");
return rc;
}

return 0;
}

/* This performs a two-way transfer over AXI DMA, both sending data out and
* receiving it back over DMA. The user determines if this call is blocking. */
int axidma_twoway_transfer(axidma_dev_t dev, int tx_channel, void *tx_buf,
Expand Down