#include #include #include #include #include #include #include #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_indexvalid_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; }