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/] [memory.c] - Rev 15

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 <asm/io.h>
 
#include "memory.h"
#include "pexmodule.h"
 
//--------------------------------------------------------------------
 
int lock_pages( void *va, u32 size )
{
    struct page *start_page_addr = virt_to_page(va);
    int i = 0;
 
    for (i=0; i < (size >> PAGE_CACHE_SHIFT); i++) {
        SetPageReserved(start_page_addr+i);
        //dbg_msg(dbg_trace, "%s(): page_addr[%d] = 0x%x\n", __FUNCTION__, i, (int)(start_page_addr+i));
    }
 
    return i;
}
 
//--------------------------------------------------------------------
 
int unlock_pages( void *va, u32 size )
{
    struct page *start_page_addr = virt_to_page(va);
    int i = 0;
 
    for (i=0; i < (size >> PAGE_CACHE_SHIFT); i++) {
        ClearPageReserved(start_page_addr+i);
        //dbg_msg(dbg_trace, "%s(): page_addr[%d] = 0x%x\n", __FUNCTION__, i, (int)(start_page_addr+i));
    }
 
    return i;
}
 
//--------------------------------------------------------------------
 
//--------------------------------------------------------------------
/*
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;
}
*/
//-----------------------------------------------------------------------------
 
int lock_user_pages(unsigned long addr, int size)
{
    //int res = 0;
    //res = get_user_pages(current, current->mm, unsigned long start, int nr_pages, int write, int force,
    //                     struct page **pages, struct vm_area_struct **vmas);
    return -1;
}
 
//-----------------------------------------------------------------------------
 
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;
}
 
//--------------------------------------------------------------------
 
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;
}
 
//--------------------------------------------------------------------
 
 

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.