summaryrefslogtreecommitdiffstats
path: root/driver
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@suren.me>2016-05-14 01:10:33 +0200
committerSuren A. Chilingaryan <csa@suren.me>2016-05-14 01:10:33 +0200
commita21dea7a0d06cbdfe9a94c88b1ba99425bf2e102 (patch)
tree1c08af911cef8869ed1eb90902f89db83b524c53 /driver
parent71f64d82453f5c86dd40104839d98fc12ae44ddf (diff)
downloadpcitool-a21dea7a0d06cbdfe9a94c88b1ba99425bf2e102.tar.gz
pcitool-a21dea7a0d06cbdfe9a94c88b1ba99425bf2e102.tar.bz2
pcitool-a21dea7a0d06cbdfe9a94c88b1ba99425bf2e102.tar.xz
pcitool-a21dea7a0d06cbdfe9a94c88b1ba99425bf2e102.zip
Allow mapping of arbitrary memory areas
Diffstat (limited to 'driver')
-rw-r--r--driver/dev.c32
-rw-r--r--driver/ioctl.c2
-rw-r--r--driver/ioctl.h1
3 files changed, 34 insertions, 1 deletions
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