diff options
-rw-r--r-- | CMakeLists.txt | 4 | ||||
-rw-r--r-- | driver/dev.c | 32 | ||||
-rw-r--r-- | driver/ioctl.c | 2 | ||||
-rw-r--r-- | driver/ioctl.h | 1 | ||||
-rw-r--r-- | pcilib/CMakeLists.txt | 6 | ||||
-rw-r--r-- | pcilib/mem.c | 52 | ||||
-rw-r--r-- | pcilib/mem.h | 29 |
7 files changed, 120 insertions, 6 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 10add39..6a21796 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,8 @@ project(pcitool C) set(RELEASE "3") -set(PCILIB_VERSION "0.2.7") -set(PCILIB_ABI_VERSION "2") +set(PCILIB_VERSION "0.2.8") +set(PCILIB_ABI_VERSION "0") cmake_minimum_required(VERSION 2.8) #set(PKG_CONFIG_USE_CMAKE_PREFIX_PATH true) diff --git a/driver/dev.c b/driver/dev.c index 1292110..75b2516 100644 --- a/driver/dev.c +++ b/driver/dev.c @@ -127,6 +127,35 @@ static int pcidriver_mmap_bar(pcidriver_privdata_t *privdata, struct vm_area_str #endif /* PCIDRIVER_DUMMY_DEVICE */ } + +static int pcidriver_mmap_area(pcidriver_privdata_t *privdata, struct vm_area_struct *vmap) +{ + int ret = 0; + + unsigned long vma_size; + unsigned long addr = vmap->vm_pgoff; + + mod_info_dbg("Entering mmap_addr\n"); + + /* Check sizes */ + vma_size = (vmap->vm_end - vmap->vm_start); + + if (addr % PAGE_SIZE) { + mod_info("mmap addr (0x%lx) is not aligned to page boundary\n", addr); + return -EINVAL; + } + + ret = remap_pfn_range(vmap, vmap->vm_start, (addr >> PAGE_SHIFT), vma_size, vmap->vm_page_prot); + + if (ret) { + mod_info("remap_pfn_range failed\n"); + return -EAGAIN; + } + + return 0; /* success */ +} + + /** * * This function is the entry point for mmap() and calls either pcidriver_mmap_bar @@ -156,6 +185,9 @@ static int pcidriver_mmap(struct file *filp, struct vm_area_struct *vma) } ret = pcidriver_mmap_bar(privdata, vma, bar); break; + case PCIDRIVER_MMAP_AREA: + ret = pcidriver_mmap_area(privdata, vma); + break; case PCIDRIVER_MMAP_KMEM: ret = pcidriver_mmap_kmem(privdata, vma); break; diff --git a/driver/ioctl.c b/driver/ioctl.c index dd7c7a3..33dbbe6 100644 --- a/driver/ioctl.c +++ b/driver/ioctl.c @@ -54,7 +54,7 @@ */ static int ioctl_mmap_mode(pcidriver_privdata_t *privdata, unsigned long arg) { - if ((arg != PCIDRIVER_MMAP_PCI) && (arg != PCIDRIVER_MMAP_KMEM)) + if ((arg != PCIDRIVER_MMAP_PCI) && (arg != PCIDRIVER_MMAP_KMEM) && (arg != PCIDRIVER_MMAP_AREA)) return -EINVAL; /* change the mode */ diff --git a/driver/ioctl.h b/driver/ioctl.h index a102092..7d393a5 100644 --- a/driver/ioctl.h +++ b/driver/ioctl.h @@ -18,6 +18,7 @@ /* mmap mode of the device */ #define PCIDRIVER_MMAP_PCI 0 #define PCIDRIVER_MMAP_KMEM 1 +#define PCIDRIVER_MMAP_AREA 2 /* Direction of a DMA operation */ #define PCIDRIVER_DMA_BIDIRECTIONAL 0 diff --git a/pcilib/CMakeLists.txt b/pcilib/CMakeLists.txt index 2af60b4..d90df49 100644 --- a/pcilib/CMakeLists.txt +++ b/pcilib/CMakeLists.txt @@ -8,8 +8,8 @@ include_directories( ${UTHASH_INCLUDE_DIRS} ) -set(HEADERS pcilib.h pci.h datacpy.h memcpy.h pagecpy.h cpu.h timing.h export.h value.h bar.h fifo.h model.h bank.h register.h view.h property.h unit.h xml.h py.h kmem.h irq.h locking.h lock.h dma.h event.h plugin.h tools.h error.h debug.h env.h config.h version.h build.h) -add_library(pcilib SHARED pci.c datacpy.c memcpy.c pagecpy.c cpu.c timing.c export.c value.c bar.c fifo.c model.c bank.c register.c view.c unit.c property.c xml.c py.c kmem.c irq.c locking.c lock.c dma.c event.c plugin.c tools.c error.c debug.c env.c) +set(HEADERS pcilib.h pci.h datacpy.h memcpy.h pagecpy.h cpu.h timing.h export.h value.h mem.h bar.h fifo.h model.h bank.h register.h view.h property.h unit.h xml.h py.h kmem.h irq.h locking.h lock.h dma.h event.h plugin.h tools.h error.h debug.h env.h config.h version.h build.h) +add_library(pcilib SHARED pci.c datacpy.c memcpy.c pagecpy.c cpu.c timing.c export.c value.c mem.c bar.c fifo.c model.c bank.c register.c view.c unit.c property.c xml.c py.c kmem.c irq.c locking.c lock.c dma.c event.c plugin.c tools.c error.c debug.c env.c) target_link_libraries(pcilib dma protocols views ${CMAKE_THREAD_LIBS_INIT} ${UFODECODE_LIBRARIES} ${CMAKE_DL_LIBS} ${EXTRA_SYSTEM_LIBS} ${LIBXML2_LIBRARIES} ${PYTHON_LIBRARIES}) add_dependencies(pcilib dma protocols views) @@ -21,7 +21,7 @@ install(FILES pcilib.h DESTINATION include ) -install(FILES bar.h kmem.h locking.h lock.h bank.h register.h xml.h dma.h event.h model.h error.h debug.h env.h tools.h timing.h cpu.h datacpy.h pagecpy.h memcpy.h export.h view.h unit.h +install(FILES mem.h bar.h kmem.h locking.h lock.h bank.h register.h xml.h dma.h event.h model.h error.h debug.h env.h tools.h timing.h cpu.h datacpy.h pagecpy.h memcpy.h export.h view.h unit.h DESTINATION include/pcilib ) diff --git a/pcilib/mem.c b/pcilib/mem.c new file mode 100644 index 0000000..d8f6391 --- /dev/null +++ b/pcilib/mem.c @@ -0,0 +1,52 @@ +#include <stdio.h> +#include <string.h> +#include <strings.h> +#include <stdlib.h> +#include <stdint.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <errno.h> +#include <assert.h> + +#include "pcilib.h" +#include "locking.h" +#include "mem.h" +#include "error.h" +#include "pci.h" + + + +void *pcilib_map_area(pcilib_t *ctx, uintptr_t addr, size_t size) { + void *res; + int err, ret; + + err = pcilib_lock_global(ctx); + if (err) { + pcilib_error("Error (%i) acquiring mmap lock", err); + return NULL; + } + + ret = ioctl( ctx->handle, PCIDRIVER_IOC_MMAP_MODE, PCIDRIVER_MMAP_AREA ); + if (ret) { + pcilib_unlock_global(ctx); + pcilib_error("PCIDRIVER_IOC_MMAP_MODE ioctl have failed"); + return NULL; + } + + res = mmap( 0, size, PROT_WRITE | PROT_READ, MAP_SHARED, ctx->handle, addr ); + + pcilib_unlock_global(ctx); + + if ((!res)||(res == MAP_FAILED)) { + pcilib_error("Failed to mmap area 0x%lx of size %zu bytes", addr, size); + return NULL; + } + + return res; +} + +void pcilib_unmap_area(pcilib_t *ctx, void *addr, size_t size) { + munmap(addr, size); +} diff --git a/pcilib/mem.h b/pcilib/mem.h new file mode 100644 index 0000000..2e3ac02 --- /dev/null +++ b/pcilib/mem.h @@ -0,0 +1,29 @@ +#ifndef _PCILIB_MEM_H +#define _PCILIB_MEM_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Maps the specified memory area in the address space of the process. + * @param[in,out] ctx - pcilib context + * @param[in] addr - hardware address (should be page-aligned) + * @param[in] size - size (should be multiple of page size) + * return - the address where the memory area is mapped + */ +void *pcilib_map_area(pcilib_t *ctx, uintptr_t addr, size_t size); + +/** + * Unmaps the specified memory area in the address space of the process. + * @param[in,out] ctx - pcilib context + * @param[in] addr - pointer to the virtual address where the area is mapped + * @param[in] size - size (should be multiple of page size) + */ +void pcilib_unmap_area(pcilib_t *ctx, void *addr, size_t size); + +#ifdef __cplusplus +} +#endif + +#endif /* _PCILIB_MEM_H */ |