updates
This commit is contained in:
158
pcie_driver/drexdma.c
Executable file
158
pcie_driver/drexdma.c
Executable file
@@ -0,0 +1,158 @@
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/fs.h>
|
||||
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include "drexdma.h"
|
||||
|
||||
|
||||
|
||||
// Initial DMA buffers function
|
||||
int init_dma_buffers(struct drexpcie_device_priv *drexpcie_priv)
|
||||
{
|
||||
int buffer_index;
|
||||
|
||||
// allocate an array for the buffer pointers (kernel space)
|
||||
drexpcie_priv->bufPtr = kzalloc(drexpcie_priv->num_bufs*sizeof(void *),GFP_KERNEL);
|
||||
if (drexpcie_priv->bufPtr == NULL) {
|
||||
printk("drexpcie[%d]: error, failed to alloc bufPtr memory\n", drexpcie_priv->chnum);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
// allocate an array for the dma pointers (physical address)
|
||||
drexpcie_priv->dmaPtr = kzalloc(drexpcie_priv->num_bufs*sizeof(dma_addr_t),GFP_KERNEL);
|
||||
if (drexpcie_priv->dmaPtr == NULL) {
|
||||
printk("drexpcie[%d]: error, failed to alloc dmaPtr memory\n", drexpcie_priv->chnum);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
// loop through the total number of desired buffer and attempt to allocate;
|
||||
// This will populate both the bufPtr and dmaPtr
|
||||
for (buffer_index = 0; buffer_index < drexpcie_priv->num_bufs; buffer_index++) {
|
||||
drexpcie_priv->bufPtr[buffer_index] = dma_alloc_coherent(&(drexpcie_priv->driv_priv->pdev->dev), drexpcie_priv->num_bytes, &drexpcie_priv->dmaPtr[buffer_index], GFP_KERNEL);
|
||||
printk("Allocating Memory: %p, %llX\n",drexpcie_priv->bufPtr[buffer_index],drexpcie_priv->dmaPtr[buffer_index]);
|
||||
|
||||
if (drexpcie_priv->bufPtr[buffer_index] == NULL) {
|
||||
printk("drexpcie[%d]: warning, DMA mem allocation failed at %d buffers\n", drexpcie_priv->chnum, buffer_index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
drexpcie_priv->valid_bufs = buffer_index;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Release (free) DMA buffers function
|
||||
void release_dma_buffers(struct drexpcie_device_priv *drexpcie_priv)
|
||||
{
|
||||
int buffer_index;
|
||||
|
||||
if (drexpcie_priv->bufPtr) {
|
||||
for (buffer_index=0; buffer_index<drexpcie_priv->valid_bufs; buffer_index++) {
|
||||
if (drexpcie_priv->bufPtr[buffer_index]) {
|
||||
printk("Freeing Memory: %p, %llX\n",drexpcie_priv->bufPtr[buffer_index],drexpcie_priv->dmaPtr[buffer_index]);
|
||||
dma_free_coherent(&(drexpcie_priv->driv_priv->pdev->dev), drexpcie_priv->num_bytes , drexpcie_priv->bufPtr[buffer_index], drexpcie_priv->dmaPtr[buffer_index]);
|
||||
|
||||
// This is unnecessary, but cleaner
|
||||
drexpcie_priv->bufPtr[buffer_index] = NULL;
|
||||
drexpcie_priv->dmaPtr[buffer_index] = (dma_addr_t) NULL;
|
||||
}
|
||||
}
|
||||
kfree(drexpcie_priv->bufPtr);
|
||||
drexpcie_priv->bufPtr = NULL;
|
||||
}
|
||||
|
||||
if (drexpcie_priv->dmaPtr) {
|
||||
kfree(drexpcie_priv->dmaPtr);
|
||||
drexpcie_priv->dmaPtr = NULL;
|
||||
}
|
||||
|
||||
drexpcie_priv->valid_bufs = 0;
|
||||
|
||||
}
|
||||
|
||||
// Start the DMA function
|
||||
int dma_init(struct drexpcie_device_priv *drexpcie_priv)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
uint32_t temp[3];
|
||||
uint64_t temp64;
|
||||
|
||||
// set reset bits
|
||||
iowrite32(0x00000007, drexpcie_priv->base_mem+DREXDMA_OFFSET_CTRL);
|
||||
|
||||
// clears queues if dma_start is called multiple times.
|
||||
release_dma_buffers(drexpcie_priv);
|
||||
|
||||
ret = init_dma_buffers(drexpcie_priv);
|
||||
|
||||
if (ret) {
|
||||
release_dma_buffers(drexpcie_priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// clear reset bits
|
||||
iowrite32(0x00000000, drexpcie_priv->base_mem+DREXDMA_OFFSET_CTRL);
|
||||
|
||||
// writes buffer to the available FIFO
|
||||
printk("drexpcie[%d]: writing %d buffers to FIFO\n", drexpcie_priv->chnum, drexpcie_priv->valid_bufs );
|
||||
for (i = 0; i < drexpcie_priv->valid_bufs; i++) {
|
||||
temp64 = drexpcie_priv->dmaPtr[i];
|
||||
temp[0] = (((drexpcie_priv->num_bytes) & 0x7FFFFF) << 9);
|
||||
temp[0] |= (((i) & 0x000001FF));
|
||||
temp[1] = temp64 & 0xFFFFFFFF;
|
||||
temp[2] = (temp64 >> 32) & 0x000000FF;
|
||||
|
||||
printk("drexpcie[%d]: writing %x %x %x to FIFO\n", drexpcie_priv->chnum, temp[2],temp[1],temp[0]);
|
||||
iowrite32(temp[0], drexpcie_priv->base_mem+DREXDMA_OFFSET_FIFO);
|
||||
iowrite32(temp[1], drexpcie_priv->base_mem+DREXDMA_OFFSET_FIFO+4);
|
||||
iowrite32(temp[2], drexpcie_priv->base_mem+DREXDMA_OFFSET_FIFO+8);
|
||||
}
|
||||
|
||||
// Enable Loop Mode
|
||||
printk("drexpcie[%d]: enabling loop mode\n", drexpcie_priv->chnum);
|
||||
iowrite32(1, drexpcie_priv->base_mem+DREXDMA_OFFSET_CTRL+4);
|
||||
|
||||
// Enable DMA Engine
|
||||
// iowrite32(0x00000100, drexpcie_privDREXDMA_OFFSET_CTRL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dma_clear(struct drexpcie_device_priv *drexpcie_priv)
|
||||
{
|
||||
|
||||
// set reset bits
|
||||
iowrite32(0x00000007, drexpcie_priv->base_mem+DREXDMA_OFFSET_CTRL);
|
||||
|
||||
// Disable Loop Mode
|
||||
iowrite32(0, drexpcie_priv->base_mem+DREXDMA_OFFSET_CTRL+4);
|
||||
|
||||
release_dma_buffers(drexpcie_priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dma_start(struct drexpcie_device_priv *drexpcie_priv)
|
||||
{
|
||||
|
||||
// Enable DMA Engine
|
||||
iowrite32(0x00000100, drexpcie_priv->base_mem+DREXDMA_OFFSET_CTRL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dma_stop(struct drexpcie_device_priv *drexpcie_priv)
|
||||
{
|
||||
|
||||
// Disable DMA Engine
|
||||
iowrite32(0x00000000, drexpcie_priv->base_mem+DREXDMA_OFFSET_CTRL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user