OpenCores
URL https://opencores.org/ocsvn/pcie_ds_dma/pcie_ds_dma/trunk

Subversion Repositories pcie_ds_dma

[/] [pcie_ds_dma/] [trunk/] [soft/] [linux/] [driver/] [pexdrv/] [ioctlrw.c] - Rev 6

Go to most recent revision | Compare with Previous | Blame | View Log

 
#include <linux/kernel.h>
#define __NO_VERSION__
#include <linux/module.h>
#include <linux/types.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/pagemap.h>
#include <linux/interrupt.h>
#include <linux/proc_fs.h>
//#include <linux/atomic.h>
#include <asm/io.h>
 
#include "pexmodule.h"
#include "pexioctl.h"
#include "hardware.h"
#include "ambpexregs.h"
#include "brd_info.h"
 
//--------------------------------------------------------------------
 
int ioctl_board_info(struct pex_device *brd, unsigned long arg)
{
    struct board_info bi;
    int error = 0;
 
    down(&brd->m_BoardSem);
 
    dbg_msg(dbg_trace, "%s(): get board information\n", __FUNCTION__);
 
    memset(&bi, 0, sizeof(struct board_info));
 
    bi.PhysAddress[0] = brd->m_BAR0.physical_address;
    bi.VirtAddress[0] = brd->m_BAR0.virtual_address;
    bi.Size[0] = brd->m_BAR0.size;
 
    bi.PhysAddress[1] = brd->m_BAR1.physical_address;
    bi.VirtAddress[1] = brd->m_BAR1.virtual_address;
    bi.Size[1] = brd->m_BAR1.size;
 
    bi.InterruptLevel = 0;
    bi.InterruptVector = brd->m_Interrupt;
    bi.vendor_id = brd->m_pci->vendor;
    bi.device_id = brd->m_pci->device;
 
    if(copy_to_user((void*)arg, &bi, sizeof(struct board_info))) {
        err_msg(err_trace, "%s(): Error copy board info to user space\n", __FUNCTION__);
        error = -EINVAL;
    }
 
    up(&brd->m_BoardSem);
 
    return error;
}
 
//--------------------------------------------------------------------
/*
static int copy_memory_descriptors(unsigned long arg, struct memory_descriptor *md, struct memory_block **mb)
{
    struct memory_block *mblocks = NULL;
    int error = 0;
    //int i = 0;
 
    if(copy_from_user((void*)md, (void*)arg, sizeof(struct memory_descriptor))) {
        err_msg(err_trace, "%s(): Error copy memory descriptor from user space\n", __FUNCTION__);
        error = -EINVAL;
        goto do_exit;
    }
 
    dbg_msg(dbg_trace, "%s(): md.total_blocks = %zd\n", __FUNCTION__, md->total_blocks );
    dbg_msg(dbg_trace, "%s(): md.blocks = %p\n", __FUNCTION__, md->blocks );
 
    mblocks = kzalloc(md->total_blocks*sizeof(struct memory_block), GFP_KERNEL);
    if(!mblocks) {
        err_msg(err_trace, "%s(): Error allocate memory for memory descriptors\n", __FUNCTION__);
        error = -ENOMEM;
        goto do_exit;
    }
 
    if(copy_from_user((void*)mblocks, (void*)md->blocks, md->total_blocks*sizeof(struct memory_block))) {
        err_msg(err_trace, "%s(): Error copy memory blocks from user space\n", __FUNCTION__);
        error = -EINVAL;
        goto do_free_mem;
    }
 
    //for(i=0; i<md->total_blocks; i++) {
    //    dbg_msg(dbg_trace, "%s(): mb[%d].size = 0x%x\n", __FUNCTION__, i, mblocks[i].size );
    //}
 
    *mb = mblocks;
 
    return 0;
 
do_free_mem:
    kfree(mb);
 
do_exit:
    return error;
}
*/
//-----------------------------------------------------------------------------
 
static void* allocate_memory_block(struct pex_device *brd, size_t block_size, dma_addr_t *dma_addr)
{
    struct mem_t *m = NULL;
    void *cpu_addr = NULL;
    dma_addr_t dma_handle = {0};
    int locked = 0;
 
    spin_lock(&brd->m_MemListLock);
 
    m = (struct mem_t*)kzalloc(sizeof(struct mem_t), GFP_KERNEL);
    if(!m) {
        err_msg(err_trace, "%s(): Error allocate memory for mem_t descriptor\n", __FUNCTION__);
        goto do_exit;
    }
 
    cpu_addr = dma_alloc_coherent(&brd->m_pci->dev, block_size, &dma_handle, GFP_KERNEL);
    if(!cpu_addr) {
        err_msg(err_trace, "%s(): Error allocate physical memory block.\n", __FUNCTION__);
        goto do_free_mem;
    }
 
    *dma_addr = dma_handle;
    m->dma_handle = dma_handle;
    m->cpu_addr = cpu_addr;
    m->size = block_size;
 
    locked = lock_pages(m->cpu_addr, m->size);
 
    list_add_tail(&m->list, &brd->m_MemList);
 
    atomic_inc(&brd->m_MemListCount);
 
    dbg_msg(dbg_trace, "%s(): %d: PA = 0x%zx, VA = %p, SZ = 0x%zx, PAGES = %d\n",
            __FUNCTION__, atomic_read(&brd->m_MemListCount), (size_t)m->dma_handle, m->cpu_addr, m->size, locked );
 
    spin_unlock(&brd->m_MemListLock);
 
    return cpu_addr;
 
do_free_mem:
    kfree(m);
 
do_exit:
    spin_unlock(&brd->m_MemListLock);
 
    return NULL;
}
 
//--------------------------------------------------------------------
 
static int free_memory_block(struct pex_device *brd, struct memory_block mb)
{
    struct list_head *pos, *n;
    struct mem_t *m = NULL;
    int unlocked = 0;
 
    spin_lock(&brd->m_MemListLock);
 
    list_for_each_safe(pos, n, &brd->m_MemList) {
 
        m = list_entry(pos, struct mem_t, list);
 
        if(m->dma_handle != mb.phys)
            continue;
 
        unlocked = unlock_pages(m->cpu_addr, m->size);
 
        dma_free_coherent(&brd->m_pci->dev, m->size, m->cpu_addr, m->dma_handle);
 
        dbg_msg(dbg_trace, "%s(): %d: PA = 0x%zx, VA = %p, SZ = 0x%zx, PAGES = %d\n",
                __FUNCTION__, atomic_read(&brd->m_MemListCount), (size_t)m->dma_handle, m->cpu_addr, m->size, unlocked );
 
        list_del(pos);
 
        atomic_dec(&brd->m_MemListCount);
 
        kfree(m);
    }
 
    spin_unlock(&brd->m_MemListLock);
 
    return 0;
}
 
//--------------------------------------------------------------------
 
int ioctl_memory_alloc(struct pex_device *brd, unsigned long arg)
{
    struct memory_block mb = {0};
    dma_addr_t dma_handle = {0};
    int error = 0;
    int i = 0;
 
    down(&brd->m_BoardSem);
 
    if(copy_from_user((void*)&mb, (void*)arg, sizeof(struct memory_block))) {
        err_msg(err_trace, "%s(): Error copy block descriptor from user space\n", __FUNCTION__);
        error = -EINVAL;
        goto do_exit;
    }
 
    if(mb.size == 0) {
        err_msg(err_trace, "%s(): Invalid block size.\n", __FUNCTION__);
        goto do_exit;
    }
 
    mb.virt = allocate_memory_block(brd, mb.size, &dma_handle);
        if(!mb.virt) {
            err_msg(err_trace, "%s(): Error allocate block %d.\n", __FUNCTION__, i);
            error = -ENOMEM;
            goto do_exit;
        }
        mb.phys = dma_handle;
 
    if(copy_to_user((void*)arg, &mb, sizeof(struct memory_block))) {
        err_msg(err_trace, "%s(): Error copy block descriptor to user space\n", __FUNCTION__);
        error = -EINVAL;
    }
 
do_exit:
    up(&brd->m_BoardSem);
 
    return error;
}
 
//--------------------------------------------------------------------
 
int ioctl_memory_free(struct pex_device *brd, unsigned long arg)
{
    struct memory_block mb = {0};
    int error = 0;
    int i = 0;
 
    down(&brd->m_BoardSem);
 
    if(copy_from_user((void*)&mb, (void*)arg, sizeof(struct memory_block))) {
        err_msg(err_trace, "%s(): Error copy block descriptor from user space\n", __FUNCTION__);
        error = -EINVAL;
        goto do_exit;
    }
 
    if(mb.size == 0 || mb.phys == 0 || mb.virt == 0) {
        err_msg(err_trace, "%s(): Invalid block parameters.\n", __FUNCTION__);
        goto do_exit;
    }
 
    error = free_memory_block(brd, mb);
    if(error < 0) {
        err_msg(err_trace, "%s(): Error free block %d.\n", __FUNCTION__, i);
        goto do_exit;
    }
 
do_exit:
    up(&brd->m_BoardSem);
 
    return error;
}
 
//--------------------------------------------------------------------
 
int ioctl_stub_alloc(struct pex_device *brd, unsigned long arg)
{
/*
    struct stub_descriptor stub = {0};
    struct dma_channel *dma = NULL;
    void *cpu_addr = NULL;
    dma_addr_t dma_handle = {0};
    int locked = 0;
    int error = -EINVAL;
 
    down(&brd->m_BoardSem);
 
    if(copy_from_user((void*)&stub, (void*)arg, sizeof(struct stub_descriptor))) {
        err_msg(err_trace, "%s(): Error copy stub descriptor from user space\n", __FUNCTION__);
        error = -EINVAL;
        goto do_exit;
    }
 
    if(stub.dma_channel >= MAX_NUMBER_OF_DMACHANNELS) {
        err_msg(err_trace, "%s(): Invalid DMA channel number.\n", __FUNCTION__);
        error = -EINVAL;
        goto do_exit;
    }
 
    dma = &brd->m_DMA[stub.dma_channel];
 
    spin_lock(&dma->m_MemListLock);
 
    cpu_addr = dma_alloc_coherent(&dma->m_pci->dev, PAGE_SIZE, &dma_handle, GFP_KERNEL);
    if(!cpu_addr) {
        err_msg(err_trace, "%s(): Error allocate physical memory for stub.\n", __FUNCTION__);
        error = -ENOMEM;
        goto do_unlock;
    }
 
    dma->m_MemStub.dma_handle = dma_handle;
    dma->m_MemStub.cpu_addr = cpu_addr;
    dma->m_MemStub.size = PAGE_SIZE;
 
    stub.stub.phys = dma_handle;
    stub.stub.size = PAGE_SIZE;
    stub.stub.virt = NULL;
 
    locked = lock_pages(dma->m_MemStub.cpu_addr, dma->m_MemStub.size);
 
    dbg_msg(dbg_trace, "%s(): PA = 0x%zx, VA = %p, SZ = 0x%zx, PAGES = %d\n",
            __FUNCTION__, (size_t)dma->m_MemStub.dma_handle, dma->m_MemStub.cpu_addr, dma->m_MemStub.size, locked );
 
    if(copy_to_user((void*)arg, &stub, sizeof(struct stub_descriptor))) {
        err_msg(err_trace, "%s(): Error copy stub descriptor to user space\n", __FUNCTION__);
        error = -EINVAL;
        goto do_free_mem;
    }
 
    spin_unlock(&dma->m_MemListLock);
 
    return 0;
 
do_free_mem:
    dma_free_coherent(&dma->m_pci->dev, PAGE_SIZE, cpu_addr, dma_handle);
 
do_unlock:
    spin_unlock(&dma->m_MemListLock);
 
do_exit:
    up(&brd->m_BoardSem);
 
    return error;
*/
    return -ENOSYS;
}
 
//--------------------------------------------------------------------
 
int ioctl_stub_free(struct pex_device *brd, unsigned long arg)
{
    down(&brd->m_BoardSem);
 
    dbg_msg(err_trace, "%s(): ioctl not implemented.\n", __FUNCTION__);
 
    up(&brd->m_BoardSem);
 
    return -ENOSYS;
}
 
//--------------------------------------------------------------------
 
int ioctl_set_mem(struct pex_device *brd, unsigned long arg)
{
    int error = 0;
    u32 i = 0;
    u32 AdmNumber = 0;
    u32 TetrNumber = 0;
    u32 Address = 0;
    u32 tmpSize = 0;
    struct CDmaChannel *dma = NULL;
    AMB_MEM_DMA_CHANNEL MemDscr = {0};
    PAMB_MEM_DMA_CHANNEL pKernMemDscr = NULL;
    PAMB_MEM_DMA_CHANNEL pUserMemDscr = &MemDscr;
 
    down(&brd->m_BoardSem);
 
    dbg_msg(dbg_trace, "%s(): Started\n", __FUNCTION__);
 
    if( copy_from_user((void *)pUserMemDscr, (void *)arg, sizeof(AMB_MEM_DMA_CHANNEL))) {
        err_msg(err_trace, "%s(): Error copy descriptor from user space\n", __FUNCTION__);
        error = -EFAULT;
        goto do_exit;
    }
 
    tmpSize = sizeof(AMB_MEM_DMA_CHANNEL)+(pUserMemDscr->BlockCnt-1)*sizeof(void*);
 
    pKernMemDscr = kzalloc(tmpSize, GFP_KERNEL);
    if(!pKernMemDscr) {
        err_msg(err_trace, "%s(): Error allocate descriptor in kernel space\n", __FUNCTION__);
        error = -ENOMEM;
        goto do_free_mem;
    }
 
    memcpy(pKernMemDscr, pUserMemDscr, tmpSize);
 
    if(pKernMemDscr->DmaChanNum >= MAX_NUMBER_OF_DMACHANNELS) {
        err_msg(err_trace, "%s(): Invalid DMA channel number\n", __FUNCTION__);
        error = -EINVAL;
        goto do_free_mem;
    }
 
    if(!(brd->m_DmaChanMask & (1 << pKernMemDscr->DmaChanNum))) {
        err_msg(err_trace, "%s(): Invalid stream number\n", __FUNCTION__);
        error = -EINVAL;
        goto do_free_mem;
    }
 
    i = pKernMemDscr->DmaChanNum;
    dma = brd->m_DmaChannel[i];
 
    dbg_msg(dbg_trace, "%s(): 1\n", __FUNCTION__);
 
    error = SetDmaDirection(dma, pKernMemDscr->Direction);
    if(error != 0) {
        err_msg(err_trace, "%s(): Error in SetDmaDirection()\n", __FUNCTION__);
        error = -EINVAL;
        goto do_free_mem;
    }
 
    dbg_msg(dbg_trace, "%s(): 2\n", __FUNCTION__);
 
    Adjust(dma,0);
 
    dbg_msg(dbg_trace, "%s(): 3\n", __FUNCTION__);
 
    pKernMemDscr->BlockSize = (pKernMemDscr->BlockSize >> 12) << 12;
    if(!pKernMemDscr->BlockSize) {
        err_msg(err_trace, "%s(): BlockSize is zero\n", __FUNCTION__);
        error = -EINVAL;
        goto do_free_mem;
    }
 
    AdmNumber = pKernMemDscr->LocalAddr >> 16;
    TetrNumber = pKernMemDscr->LocalAddr & 0xff;
    Address = AdmNumber*ADM_SIZE + TetrNumber*TETRAD_SIZE + TRDadr_DATA*REG_SIZE;
 
    SetDmaLocalAddress(dma, Address);
    SetAdmTetr(dma, AdmNumber, TetrNumber);
    error = SetDmaMode(brd, i, AdmNumber, TetrNumber);
 
    dbg_msg(dbg_trace, "%s(): 4\n", __FUNCTION__);
 
    error = RequestMemory( dma, pKernMemDscr->pBlock, pKernMemDscr->BlockSize,
                            (u32*)&pKernMemDscr->BlockCnt, &pKernMemDscr->pStub, pKernMemDscr->MemType );
    if(error < 0) {
        err_msg(err_trace, "%s(): Error in RequestMemory()\n", __FUNCTION__);
        error = -ENOMEM;
        goto do_free_mem;
    }
 
    dbg_msg(dbg_trace, "%s(): 5\n", __FUNCTION__);
 
    if(copy_to_user((void*)arg, (void*)pKernMemDscr, tmpSize)) {
        err_msg(err_trace, "%s(): Error copy descriptor to user space\n", __FUNCTION__);
        error = -EFAULT;
    }
 
do_free_mem:
    kfree(pKernMemDscr);
 
do_exit:
    up(&brd->m_BoardSem);
 
    return error;
}
 
//--------------------------------------------------------------------
 
int ioctl_free_mem(struct pex_device *brd, size_t arg)
{
    u32 i = 0;
    int error = 0;
    AMB_MEM_DMA_CHANNEL MemDscr = {0};
    PAMB_MEM_DMA_CHANNEL pMemDscr = &MemDscr;
 
    down(&brd->m_BoardSem);
 
    if( copy_from_user((void *)pMemDscr, (void *)arg, sizeof(AMB_MEM_DMA_CHANNEL))) {
        err_msg(err_trace, "%s(): Error copy descriptor from user space\n", __FUNCTION__);
        error = -EFAULT;
        goto do_exit;
    }
 
    if(pMemDscr->DmaChanNum >= MAX_NUMBER_OF_DMACHANNELS) {
        err_msg(err_trace, "%s(): Invalid DMA channel number\n", __FUNCTION__);
        error = -EINVAL;
        goto do_exit;
    }
 
    i = pMemDscr->DmaChanNum;
    ReleaseMemory(brd->m_DmaChannel[i]);
 
    if(copy_to_user (( void *)arg, (void *)&MemDscr, sizeof(AMB_MEM_DMA_CHANNEL) + (pMemDscr->BlockCnt - 1) * sizeof(void*) )) {
        err_msg(err_trace, "%s(): Error copy descriptor to user space\n", __FUNCTION__);
        error = -EFAULT;
        goto do_exit;
    }
 
do_exit:
    up(&brd->m_BoardSem);
 
    return error;
}
 
//--------------------------------------------------------------------
 
int ioctl_start_mem(struct pex_device *brd, size_t arg)
{
    int Status = -EINVAL;
    AMB_START_DMA_CHANNEL StartDscr;
    PAMB_START_DMA_CHANNEL pStartDscr = &StartDscr;
 
    down(&brd->m_BoardSem);
 
    if( copy_from_user((void *)&StartDscr, (void *)arg, sizeof(AMB_START_DMA_CHANNEL))) {
        err_msg(err_trace, "%s(): Error copy data from userspace\n", __FUNCTION__ );
        up(&brd->m_BoardSem);
        return -EFAULT;
    }
 
    if(pStartDscr->DmaChanNum >= MAX_NUMBER_OF_DMACHANNELS) {
        printk("<0>%s(): too large stream number\n", __FUNCTION__);
        up(&brd->m_BoardSem);
        return -EINVAL;
    }
 
    if(!(brd->m_DmaChanMask & (1 << pStartDscr->DmaChanNum))) {
        printk("<0>%s(): invalid stream number\n", __FUNCTION__);
        up(&brd->m_BoardSem);
        return -EINVAL;
    }
 
    Status = StartDmaTransfer(brd->m_DmaChannel[pStartDscr->DmaChanNum], pStartDscr->IsCycling);
    Status = HwStartDmaTransfer(brd, pStartDscr->DmaChanNum);
 
    up(&brd->m_BoardSem);
 
    return Status;
}
 
//--------------------------------------------------------------------
 
int ioctl_stop_mem(struct pex_device *brd, size_t arg)
{
    int Status = -EINVAL;
    u32 i;
    AMB_STATE_DMA_CHANNEL StopDscr;
    PAMB_STATE_DMA_CHANNEL pStopDscr = &StopDscr;
 
    down(&brd->m_BoardSem);
 
    // get the user buffer
    if( copy_from_user((void *)&StopDscr, (void *)arg, sizeof(AMB_STATE_DMA_CHANNEL))) {
        err_msg(err_trace, "%s(): Error copy data from userspace\n", __FUNCTION__ );
        up(&brd->m_BoardSem);
        return -EFAULT;
    }
 
    //printk("<0>IoctlStopMem: Entered.\n");
 
    if(pStopDscr->DmaChanNum >= MAX_NUMBER_OF_DMACHANNELS)
    {
        printk("<0>IoctlStopMem: too large stream number\n");
        up(&brd->m_BoardSem);
        return -EINVAL;
    }
 
    i = pStopDscr->DmaChanNum;
    if(pStopDscr->Timeout)
        Status = WaitBlockEndEvent(brd->m_DmaChannel[i], pStopDscr->Timeout);
    else
        Status = 0;
    /*
        PIRP CurrentIrp = m_DmaChannel[i].GetQueueIrp();
        if(CurrentIrp)
                CancelIrp(CurrentIrp, WambpIrpCancelCallback);
*/
    HwCompleteDmaTransfer(brd, i);
    //FreezeState(brd->m_DmaChannel[i]);
    GetState( brd->m_DmaChannel[i], (u32*)&pStopDscr->BlockNum,
              (u32*)&pStopDscr->BlockCntTotal, (u32*)&pStopDscr->OffsetInBlock,
              (u32*)&pStopDscr->DmaChanState);
 
    if(copy_to_user (( void *)arg, (void *)&StopDscr, sizeof(AMB_STATE_DMA_CHANNEL))) {
        err_msg(err_trace, "%s(): Error copy data to userspace\n", __FUNCTION__ );
        up(&brd->m_BoardSem);
        return -EFAULT;
    }
 
    up(&brd->m_BoardSem);
 
    return Status;
}
 
//--------------------------------------------------------------------
 
int ioctl_state_mem(struct pex_device *brd, size_t arg)
{
    int Status = -EINVAL;
    u32 i=0;
    AMB_STATE_DMA_CHANNEL StateDscr;
    PAMB_STATE_DMA_CHANNEL pStateDscr = &StateDscr;
 
    down(&brd->m_BoardSem);
 
    // get the user buffer
    if( copy_from_user((void *)&StateDscr, (void *)arg, sizeof(AMB_STATE_DMA_CHANNEL))) {
        err_msg(err_trace, "%s(): Error copy data from userspace\n", __FUNCTION__ );
        up(&brd->m_BoardSem);
        return -EFAULT;
    }
 
    //printk("<0>IoctlStateMem: Entered.\n");
 
    if(pStateDscr->DmaChanNum >= MAX_NUMBER_OF_DMACHANNELS)
    {
        printk("<0>IoctlStateMem: too large stream number\n");
        up(&brd->m_BoardSem);
        return -EINVAL;
    }
 
    i = pStateDscr->DmaChanNum;
    if(pStateDscr->Timeout)
        Status = WaitBlockEndEvent(brd->m_DmaChannel[i], pStateDscr->Timeout);
    else
        Status = 0;
 
    //FreezeState(brd->m_DmaChannel[i]);
    GetState(brd->m_DmaChannel[i], 	(u32*)&pStateDscr->BlockNum,
             (u32*)&pStateDscr->BlockCntTotal,
             (u32*)&pStateDscr->OffsetInBlock,
             (u32*)&pStateDscr->DmaChanState);
 
    if(copy_to_user (( void *)arg, (void *)&StateDscr, sizeof(AMB_STATE_DMA_CHANNEL))) {
        err_msg(err_trace, "%s(): Error copy data to userspace\n", __FUNCTION__ );
        up(&brd->m_BoardSem);
        return -EFAULT;
    }
 
    up(&brd->m_BoardSem);
 
    return Status;
}
 
//--------------------------------------------------------------------
 
int ioctl_set_dir_mem(struct pex_device *brd, size_t arg)
{
    int Status = -EINVAL;
    u32 i;
    AMB_SET_DMA_CHANNEL MemDscr;
    PAMB_SET_DMA_CHANNEL pMemDscr = &MemDscr;
 
    //printk("<0>IoctlSetDirMem: Entered.\n");
    down(&brd->m_BoardSem);
 
    // get the user buffer
    if( copy_from_user((void *)&MemDscr, (void *)arg, sizeof(AMB_SET_DMA_CHANNEL))) {
        err_msg(err_trace, "%s(): Error copy data from userspace\n", __FUNCTION__ );
        up(&brd->m_BoardSem);
        return -EFAULT;
    }
 
    if(pMemDscr->DmaChanNum >= MAX_NUMBER_OF_DMACHANNELS)
    {
        printk("<0>IoctlSetDirMem: too large stream number\n");
        up(&brd->m_BoardSem);
        return -EINVAL;
    }
 
    i = pMemDscr->DmaChanNum;
    Status = SetDmaDirection(brd->m_DmaChannel[i], pMemDscr->Param);
 
    up(&brd->m_BoardSem);
 
    return Status;
}
 
//--------------------------------------------------------------------
 
int ioctl_set_src_mem(struct pex_device *brd, size_t arg)
{
    int Status = -EINVAL;
    u32 i;
    u32 AdmNumber = 0;
    u32 TetrNumber = 0;
    u32 Address = 0;
    AMB_SET_DMA_CHANNEL MemDscr;
    PAMB_SET_DMA_CHANNEL pMemDscr = &MemDscr;
 
    down(&brd->m_BoardSem);
 
    // get the user buffer
    if( copy_from_user((void *)&MemDscr, (void *)arg, sizeof(AMB_SET_DMA_CHANNEL))) {
        err_msg(err_trace, "%s(): Error copy data from userspace\n", __FUNCTION__ );
        up(&brd->m_BoardSem);
        return -EFAULT;
    }
 
    if(pMemDscr->DmaChanNum >= MAX_NUMBER_OF_DMACHANNELS)
    {
        printk("<0>IoctlSetSrcMem: too large stream number\n");
        up(&brd->m_BoardSem);
        return -EINVAL;
    }
 
    i = pMemDscr->DmaChanNum;
    AdmNumber = pMemDscr->Param >> 16;
    TetrNumber = pMemDscr->Param & 0xff;
    Address = AdmNumber * ADM_SIZE + TetrNumber * TETRAD_SIZE + TRDadr_DATA * REG_SIZE;
    SetDmaLocalAddress(brd->m_DmaChannel[i], Address);
    SetAdmTetr(brd->m_DmaChannel[i], AdmNumber, TetrNumber);
    Status = SetDmaMode(brd, i, AdmNumber, TetrNumber);
 
    up(&brd->m_BoardSem);
 
    return Status;
}
 
//--------------------------------------------------------------------
 
int ioctl_set_drq_mem(struct pex_device *brd, size_t arg)
{
    int Status = -EINVAL;
    u32 i;
    u32 AdmNum = 0;
    u32 TetrNum = 0;
    AMB_SET_DMA_CHANNEL MemDscr;
    PAMB_SET_DMA_CHANNEL pMemDscr = &MemDscr;
 
    down(&brd->m_BoardSem);
 
    //printk("<0>IoctlSetSrcMem: Entered.\n");
 
    // get the user buffer
    if( copy_from_user((void *)&MemDscr, (void *)arg, sizeof(AMB_SET_DMA_CHANNEL))) {
        err_msg(err_trace, "%s(): Error copy data from userspace\n", __FUNCTION__ );
        up(&brd->m_BoardSem);
        return -EFAULT;
    }
 
    if(pMemDscr->DmaChanNum >= MAX_NUMBER_OF_DMACHANNELS)
    {
        printk("<0>IoctlSetDrqMem: too large stream number\n");
        up(&brd->m_BoardSem);
        return -EINVAL;
    }
 
    i = pMemDscr->DmaChanNum;
    AdmNum = GetAdmNum( brd->m_DmaChannel[i] );
    TetrNum = GetTetrNum( brd->m_DmaChannel[i] );
    Status = SetDrqFlag( brd, AdmNum, TetrNum, pMemDscr->Param );
 
    up(&brd->m_BoardSem);
 
    return Status;
}
 
//--------------------------------------------------------------------
 
int ioctl_adjust(struct pex_device *brd, size_t arg)
{
    u32 i;
    AMB_SET_DMA_CHANNEL MemDscr;
    PAMB_SET_DMA_CHANNEL pMemDscr = &MemDscr;
 
    down(&brd->m_BoardSem);
 
    //printk("<0>%s()\n", __FUNCTION__);
 
    if( copy_from_user((void *)&MemDscr, (void *)arg, sizeof(AMB_SET_DMA_CHANNEL))) {
        err_msg(err_trace, "%s(): Error copy data from userspace\n", __FUNCTION__ );
        up(&brd->m_BoardSem);
        return -EFAULT;
    }
 
    if(pMemDscr->DmaChanNum >= MAX_NUMBER_OF_DMACHANNELS)
    {
        printk("<0>IoctlSetDrqMem: too large stream number\n");
        up(&brd->m_BoardSem);
        return -EINVAL;
    }
    if(!(brd->m_DmaChanMask & (1 << pMemDscr->DmaChanNum)))
    {
        printk("<0>%s(): invalid stream number\n", __FUNCTION__);
        up(&brd->m_BoardSem);
        return -EINVAL;
    }
 
    i = pMemDscr->DmaChanNum;
    Adjust(brd->m_DmaChannel[i], pMemDscr->Param);
 
    up(&brd->m_BoardSem);
 
    return 0;
}
 
//--------------------------------------------------------------------
 
int ioctl_done(struct pex_device *brd, size_t arg)
{
    int Status = -EINVAL;
    u32 i;
    u32 done_flag;
    AMB_SET_DMA_CHANNEL MemDscr;
    PAMB_SET_DMA_CHANNEL pMemDscr = &MemDscr;
 
    down(&brd->m_BoardSem);
 
    //printk("<0>%s()\n", __FUNCTION__);
 
    // get the user buffer
    if( copy_from_user((void *)&MemDscr, (void *)arg, sizeof(AMB_SET_DMA_CHANNEL))) {
        err_msg(err_trace, "%s(): Error copy data from userspace\n", __FUNCTION__ );
        up(&brd->m_BoardSem);
        return -EFAULT;
    }
 
    if(pMemDscr->DmaChanNum >= MAX_NUMBER_OF_DMACHANNELS)
    {
        printk("<0>IoctlSetDrqMem: too large stream number\n");
        up(&brd->m_BoardSem);
        return -EINVAL;
    }
    if(!(brd->m_DmaChanMask & (1 << pMemDscr->DmaChanNum)))
    {
        printk("<0>%s(): invalid stream number\n", __FUNCTION__);
        up(&brd->m_BoardSem);
        return -EINVAL;
    }
 
    i = pMemDscr->DmaChanNum;
    done_flag = SetDoneBlock(brd->m_DmaChannel[i], pMemDscr->Param);
    if(done_flag)
        Status = Done(brd, i);
 
    up(&brd->m_BoardSem);
 
    return 0;
}
 
//--------------------------------------------------------------------
 
int ioctl_reset_fifo(struct pex_device *brd, size_t arg)
{
    int Status = -EINVAL;
    AMB_SET_DMA_CHANNEL MemDscr;
    PAMB_SET_DMA_CHANNEL pMemDscr = &MemDscr;
 
    down(&brd->m_BoardSem);
 
    // get the user buffer
    if( copy_from_user((void *)&MemDscr, (void *)arg, sizeof(AMB_SET_DMA_CHANNEL))) {
        err_msg(err_trace, "%s(): Error copy data from userspace\n", __FUNCTION__ );
        up(&brd->m_BoardSem);
        return -EFAULT;
    }
 
    if(pMemDscr->DmaChanNum >= MAX_NUMBER_OF_DMACHANNELS)
    {
        printk("<0>%s(): too large stream number\n", __FUNCTION__);
        up(&brd->m_BoardSem);
        return -EINVAL;
    }
    if(!(brd->m_DmaChanMask & (1 << pMemDscr->DmaChanNum)))
    {
        printk("<0>%s(): invalid stream number\n", __FUNCTION__);
        up(&brd->m_BoardSem);
        return -EINVAL;
    }
 
    Status = ResetFifo(brd, pMemDscr->DmaChanNum);
 
    up(&brd->m_BoardSem);
 
    return Status;
}
 
//--------------------------------------------------------------------
 
int ioctl_get_dma_channel_info(struct pex_device *brd, size_t arg)
{
    AMB_GET_DMA_INFO DmaInfo = {0};
 
    down(&brd->m_BoardSem);
 
    // get the user buffer
    if( copy_from_user((void *)&DmaInfo, (void *)arg, sizeof(AMB_GET_DMA_INFO))) {
        err_msg(err_trace, "%s(): Error copy data from userspace\n", __FUNCTION__ );
        up(&brd->m_BoardSem);
        return -EFAULT;
    }
 
    if(DmaInfo.DmaChanNum >= MAX_NUMBER_OF_DMACHANNELS)
    {
        printk("<0>%s(): too large stream number\n", __FUNCTION__);
        up(&brd->m_BoardSem);
        return -EINVAL;
    }
    if(!(brd->m_DmaChanMask & (1 << DmaInfo.DmaChanNum)))
    {
        printk("<0>%s(): invalid stream number\n", __FUNCTION__);
        up(&brd->m_BoardSem);
        return -EINVAL;
    }
 
    DmaInfo.Direction = brd->m_DmaDir[DmaInfo.DmaChanNum];
    DmaInfo.FifoSize = brd->m_DmaFifoSize[DmaInfo.DmaChanNum];
    DmaInfo.MaxDmaSize = brd->m_MaxDmaSize[DmaInfo.DmaChanNum];
 
    if(copy_to_user (( void *)arg, (void *)&DmaInfo, sizeof(AMB_GET_DMA_INFO))) {
                err_msg(err_trace, "%s(): Error copy data to userspace\n", __FUNCTION__ );
        up(&brd->m_BoardSem);
        return -EFAULT;
    }
 
    up(&brd->m_BoardSem);
 
    return 0;
}
 
//--------------------------------------------------------------------
 
int ioctl_wait_dma_buffer(struct pex_device *brd, size_t arg)
{
    int Status = -EINVAL;
    u32 i=0;
    AMB_STATE_DMA_CHANNEL StateDscr;
    PAMB_STATE_DMA_CHANNEL pStateDscr = &StateDscr;
 
    down ( &brd->m_BoardSem );
 
    // get the user buffer
    if( copy_from_user((void *)&StateDscr, (void *)arg, sizeof(AMB_STATE_DMA_CHANNEL))) {
                err_msg(err_trace, "%s(): Error copy data from userspace\n", __FUNCTION__ );
        up(&brd->m_BoardSem);
        return -EFAULT;
    }
 
    //printk("<0>%s(): DMA %d\n", __FUNCTION__, pStateDscr->DmaChanNum);
 
    if(pStateDscr->DmaChanNum >= MAX_NUMBER_OF_DMACHANNELS)
    {
        printk("<0>%s(): too large stream number\n", __FUNCTION__);
        up(&brd->m_BoardSem);
        return -EINVAL;
    }
 
    i = pStateDscr->DmaChanNum;
 
    Status = WaitBufferEndEvent(brd->m_DmaChannel[i], pStateDscr->Timeout);
 
    GetState(brd->m_DmaChannel[i], 	(u32*)&pStateDscr->BlockNum,
             (u32*)&pStateDscr->BlockCntTotal,
             (u32*)&pStateDscr->OffsetInBlock,
             (u32*)&pStateDscr->DmaChanState);
 
    if(copy_to_user (( void *)arg, (void *)&StateDscr, sizeof(AMB_STATE_DMA_CHANNEL))) {
                err_msg(err_trace, "%s(): Error copy data to userspace\n", __FUNCTION__ );
        up(&brd->m_BoardSem);
        return -EFAULT;
    }
 
    up(&brd->m_BoardSem);
 
    return Status;
}
 
//--------------------------------------------------------------------
 
int ioctl_wait_dma_block(struct pex_device *brd, size_t arg)
{
    int Status = -EINVAL;
    u32 i=0;
    AMB_STATE_DMA_CHANNEL StateDscr;
    PAMB_STATE_DMA_CHANNEL pStateDscr = &StateDscr;
 
    down ( &brd->m_BoardSem );
 
    // get the user buffer
    if( copy_from_user((void *)&StateDscr, (void *)arg, sizeof(AMB_STATE_DMA_CHANNEL))) {
        err_msg(err_trace, "%s(): Error copy data from userspace\n", __FUNCTION__ );
        up(&brd->m_BoardSem);
        return -EFAULT;
    }
 
    printk("<0>%s(): DMA %d\n", __FUNCTION__, pStateDscr->DmaChanNum);
 
    if(pStateDscr->DmaChanNum >= MAX_NUMBER_OF_DMACHANNELS)
    {
        printk("<0>%s(): too large stream number\n", __FUNCTION__);
        up(&brd->m_BoardSem);
        return -EINVAL;
    }
 
    i = pStateDscr->DmaChanNum;
 
    Status = WaitBlockEndEvent(brd->m_DmaChannel[i], pStateDscr->Timeout);
 
    GetState(brd->m_DmaChannel[i], 	(u32*)&pStateDscr->BlockNum,
             (u32*)&pStateDscr->BlockCntTotal,
             (u32*)&pStateDscr->OffsetInBlock,
             (u32*)&pStateDscr->DmaChanState);
 
    if(copy_to_user (( void *)arg, (void *)&StateDscr, sizeof(AMB_STATE_DMA_CHANNEL))) {
        err_msg(err_trace, "%s(): Error copy data to userspace\n", __FUNCTION__ );
        up(&brd->m_BoardSem);
        return -EFAULT;
    }
 
    up(&brd->m_BoardSem);
 
    return Status;
}
 
//--------------------------------------------------------------------
 
 
 
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.