📄 altera_avalon_dma.c
字号:
int req, void* arg){ return alt_avalon_dma_ioctl (((alt_avalon_dma_txchan*) dma)->priv, req, arg);}/* * Perform an ioctl request for a receive channel. */int alt_avalon_dma_rx_ioctl (alt_dma_rxchan dma, int req, void* arg){ return alt_avalon_dma_ioctl (((alt_avalon_dma_rxchan*) dma)->priv, req, arg);}/* * Register a DMA receive requests. */int alt_avalon_dma_prepare (alt_dma_rxchan dma, void* data, alt_u32 len, alt_rxchan_done* done, void* handle){ alt_avalon_dma_rxslot* slot; alt_u32 start; alt_u32 end; alt_u32 next; alt_u32 align_mask; alt_avalon_dma_priv* priv; priv = ((alt_avalon_dma_rxchan*) dma)->priv; /* * Ensure that the data is correctly aligned, and that it's not too * big for the device. */ align_mask = priv->flags & ALT_AVALON_DMA_MODE_MSK; if ((((alt_u32) data) & align_mask) || (len & align_mask) || (len > priv->max_length)) { return -EINVAL; } start = priv->rx_start; end = priv->rx_end; slot = &priv->rx_buf[end]; next = (end + 1) & ALT_AVALON_DMA_NSLOTS_MSK; if (next == start) { return -ENOSPC; } slot->data = data; slot->len = len; slot->done = done; slot->handle = handle; priv->rx_end = next; if (!priv->active) { priv->launch (priv); } return 0;}/* * alt_avalon_dma_space() returns the number of tranmit requests that can be * posted to the specified DMA transmit channel. * * A negative value indicates that the value could not be determined. */int alt_avalon_dma_space (alt_dma_txchan dma){ alt_avalon_dma_priv* priv; alt_u32 start; alt_u32 end; priv = ((alt_avalon_dma_txchan*) dma)->priv; start = priv->tx_start; end = priv->tx_end; return (start > end) ? start - end - 1 : ALT_AVALON_DMA_NSLOTS + start - end - 1;}/* * alt_avalon_dma_send() posts a transmit request to a DMA transmit channel. * The input arguments are: * * dma: the channel to use. * from: a pointer to the start of the data to send. * length: the length of the data to send in bytes. * done: callback function that will be called once the data has been sent. * handle: opaque value passed to "done". * * The return value will be negative if the request cannot be posted, and * zero otherwise. */int alt_avalon_dma_send (alt_dma_txchan dma, const void* from, alt_u32 len, alt_txchan_done* done, void* handle){ alt_avalon_dma_txslot* slot; alt_u32 start; alt_u32 end; alt_u32 align_mask; alt_u32 next; alt_avalon_dma_priv* priv; priv = ((alt_avalon_dma_txchan*) dma)->priv; /* * Ensure that the data is correctly aligned, and not too large * for the device */ align_mask = priv->flags & ALT_AVALON_DMA_MODE_MSK; if ((((alt_u32) from) & align_mask) || (len & align_mask) || (len > priv->max_length)) { return -EINVAL; } start = priv->tx_start; end = priv->tx_end; slot = &priv->tx_buf[end]; next = (end + 1) & ALT_AVALON_DMA_NSLOTS_MSK; if (next == start) { return -ENOSPC; } /* Fill in the descriptor */ slot->from = from; slot->len = len; slot->done = done; slot->handle = handle; priv->tx_end = next; if (!priv->active) { priv->launch (priv); } return 0;}/* * Process a received interrupt. Interrupts are generated when a transaction * completes. */static void alt_avalon_dma_irq (void* context, alt_u32 id){ alt_avalon_dma_priv* priv = (alt_avalon_dma_priv*) context; alt_avalon_dma_txslot* tx_slot; alt_avalon_dma_rxslot* rx_slot; alt_u32 tx_start; alt_u32 rx_start; int stream_tx; int stream_rx; stream_tx = priv->flags & ALT_AVALON_DMA_TX_STREAM; stream_rx = priv->flags & ALT_AVALON_DMA_RX_STREAM; tx_start = priv->tx_start; rx_start = priv->rx_start; tx_slot = &priv->tx_buf[tx_start]; rx_slot = &priv->rx_buf[rx_start]; /* Increment the descriptors */ if (!stream_tx) { priv->tx_start = (tx_start + 1) & ALT_AVALON_DMA_NSLOTS_MSK; } if (!stream_rx) { priv->rx_start = (rx_start + 1) & ALT_AVALON_DMA_NSLOTS_MSK; } /* clear the interrupt */ IOWR_ALTERA_AVALON_DMA_STATUS (priv->base, 0); /* launch the next transaction */ priv->launch (priv); /* Make the callbacks */ if (!stream_tx && tx_slot->done) { tx_slot->done (tx_slot->handle); } if (!stream_rx && rx_slot->done) { rx_slot->done (rx_slot->handle, rx_slot->data); }}/* * Initialise and register the transmit and receive channels for a given * physical DMA device. */void alt_avalon_dma_init (alt_avalon_dma_txchan* tx, alt_avalon_dma_rxchan* rx, void* base, alt_u32 irq){ /* Halt any current transactions (reset the device) */ IOWR_ALTERA_AVALON_DMA_CONTROL (base, ALTERA_AVALON_DMA_CONTROL_SOFTWARERESET_MSK); IOWR_ALTERA_AVALON_DMA_CONTROL (base, ALTERA_AVALON_DMA_CONTROL_SOFTWARERESET_MSK); /* Set the default mode of the device (32 bit block reads and writes from/to memory). */ IOWR_ALTERA_AVALON_DMA_CONTROL (base, ALTERA_AVALON_DMA_CONTROL_WORD_MSK | ALTERA_AVALON_DMA_CONTROL_GO_MSK | ALTERA_AVALON_DMA_CONTROL_I_EN_MSK | ALTERA_AVALON_DMA_CONTROL_REEN_MSK | ALTERA_AVALON_DMA_CONTROL_WEEN_MSK | ALTERA_AVALON_DMA_CONTROL_LEEN_MSK); /* Clear any pending interrupts and the DONE flag */ IOWR_ALTERA_AVALON_DMA_STATUS (base, 0); /* * Register the interrupt handler, and make the device available to the * system. */ if (alt_irq_register (irq, tx->priv, alt_avalon_dma_irq) >= 0) { alt_dma_txchan_reg (&tx->dev); alt_dma_rxchan_reg (&rx->dev); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -