From 73edad9c02ade5a7069dabc672b07996a69e9609 Mon Sep 17 00:00:00 2001
From: David Schleef <ds@schleef.org>
Date: Thu, 21 Nov 2002 04:43:59 +0000
Subject: [PATCH] Reimplement kvmem.[ch] code in comedi_fops

---
 comedi/Makefile.in   |  2 +-
 comedi/comedi_fops.c | 43 +++++++++++++++++++++++++++++++++----------
 comedi/drivers.c     | 33 ++++++++++++++++++++++++++++++---
 3 files changed, 64 insertions(+), 14 deletions(-)

diff --git a/comedi/Makefile.in b/comedi/Makefile.in
index 80e172c3..428eff96 100644
--- a/comedi/Makefile.in
+++ b/comedi/Makefile.in
@@ -1,7 +1,7 @@
 
 expsyms(comedi_ksyms.o)
 
-objlink(comedi.o comedi_fops.o proc.o range.o drivers.o kvmem.o comedi_ksyms.o)
+objlink(comedi.o comedi_fops.o proc.o range.o drivers.o comedi_ksyms.o)
 
 ifsel(CONFIG_COMEDI_RT)
   objlink(comedi.o rt_pend_tq.o rt.o)
diff --git a/comedi/comedi_fops.c b/comedi/comedi_fops.c
index af8ebd05..efe29e9e 100644
--- a/comedi/comedi_fops.c
+++ b/comedi/comedi_fops.c
@@ -37,13 +37,14 @@
 #include <linux/poll.h>
 #include <linux/init.h>
 #include <linux/devfs_fs_kernel.h>
+#include <linux/vmalloc.h>
 
 #include <linux/comedidev.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
-#include "kvmem.h"
+//#include "kvmem.h"
 
 MODULE_AUTHOR("David Schleef <ds@schleef.org>");
 MODULE_DESCRIPTION("Comedi core module");
@@ -1199,16 +1200,20 @@ static struct vm_operations_struct comedi_vm_ops={
 };
 /*
    comedi_mmap_v22
-
-   issues:
-      what happens when the underlying buffer gets changed?
-
  */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,17)
+#define page_address(x) x
+#endif
+
 static int comedi_mmap_v22(struct file * file, struct vm_area_struct *vma)
 {
 	kdev_t minor=MINOR(RDEV_OF_FILE(file));
 	comedi_device *dev=comedi_get_device_by_minor(minor);
 	comedi_async *async = NULL;
+	unsigned long pos;
+	unsigned long start = vma->vm_start;
+	unsigned long size;
+	unsigned long page;
 
 	if(!dev->attached)
 	{
@@ -1225,20 +1230,38 @@ static int comedi_mmap_v22(struct file * file, struct vm_area_struct *vma)
 		return -EINVAL;
 	}
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
+#if LINUX_VERSION_CODE < 0x020300
 	if(vma->vm_offset != 0){
+		DPRINTK("comedi: mmap() offset must be 0.\n");
+		return -EINVAL;
+	}
 #else
 	if(vma->vm_pgoff != 0){
-#endif
 		DPRINTK("comedi: mmap() offset must be 0.\n");
 		return -EINVAL;
 	}
+#endif
+
+	size = vma->vm_end - vma->vm_start;
+	if(size>=async->prealloc_bufsz)
+		return -EFAULT;
+	if(size&(~PAGE_MASK))
+		return -EFAULT;
 
-	rvmmap(async->prealloc_buf,async->prealloc_bufsz,vma);
+	pos = (unsigned long)async->prealloc_buf;
+	while(size>0){
+		page = kvirt_to_pa(pos);
+		if(remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)){
+			return -EAGAIN;
+		}
+
+		pos += PAGE_SIZE;
+		start += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
 
-	//vma->vm_file = file;
 	vma->vm_ops = &comedi_vm_ops;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,17)
+#if LINUX_VERSION_CODE < 0x020300
 	(void *)vma->vm_pte = async;
 #else
 	vma->vm_private_data = async;
diff --git a/comedi/drivers.c b/comedi/drivers.c
index d7926705..c2c4e966 100644
--- a/comedi/drivers.c
+++ b/comedi/drivers.c
@@ -33,10 +33,11 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/comedidev.h>
+#include <linux/wrapper.h>
 
 #include <asm/io.h>
 
-#include "kvmem.h"
+//#include "kvmem.h"
 
 static int postconfig(comedi_device *dev);
 static int insn_rw_emulate_bits(comedi_device *dev,comedi_subdevice *s,
@@ -375,16 +376,42 @@ static int buf_alloc(comedi_device *dev, comedi_subdevice *s,
 	}
 
 	if(async->prealloc_bufsz){
-		rvfree(async->prealloc_buf, async->prealloc_bufsz);
+		unsigned long adr, size;
+		unsigned long page;
+
+		size = async->prealloc_bufsz;
+		adr = (unsigned long)async->prealloc_buf;
+		while(size>0){
+			page = kvirt_to_pa(adr);
+			mem_map_unreserve(virt_to_page(__va(page)));
+			adr += PAGE_SIZE;
+			size -= PAGE_SIZE;
+		}
+
+		vfree(async->prealloc_buf);
 		async->prealloc_buf = NULL;
 	}
 
 	if(new_size){
-		async->prealloc_buf = rvmalloc(new_size);
+		unsigned long adr;
+		unsigned long size;
+		unsigned long page;
+
+		async->prealloc_buf = vmalloc_32(new_size);
 		if(async->prealloc_buf == NULL){
 			async->prealloc_bufsz = 0;
 			return -ENOMEM;
 		}
+		memset(async->prealloc_buf,0,new_size);
+
+		adr = (unsigned long)async->prealloc_buf;
+		size = new_size;
+		while(size > 0){
+			page = kvirt_to_pa(adr);
+			mem_map_reserve(virt_to_page(__va(page)));
+			adr += PAGE_SIZE;
+			size -= PAGE_SIZE;
+		}
 	}
 	async->prealloc_bufsz = new_size;
 
-- 
2.26.2