diff --git a/dio.c b/dio.c index 4f2555f..e3d10b5 100644 --- a/dio.c +++ b/dio.c @@ -37,38 +37,44 @@ static enum io_type { static void *inbuf, * outbuf; static void *mm; -int buf_size = 8 * PAGE_SIZE; +static int buf_size = 16 * 1024; static int mmapoffset; -static int mmapsize; +static int mmapsize = 16 * 1024; static char *dev_name; static int ignore_eof; int output(int dev, void *buf, int len) { + int ret = 0; if ( dev < 0 ) return 0; switch (io_type) { case mmap_io: + memcpy(mm,buf,len); + ret = len; break; case file_io: default: - len = write(dev, buf, len); + ret = write(dev, buf, len); } - return len; + return ret; } int input(int dev, void *buf, int len) { + int ret; if ( dev < 0 ) return 0; switch (io_type) { case mmap_io: + memcpy(buf,mm,len); + ret = len; break; case file_io: default: - len = read(dev, buf, len); + ret = read(dev, buf, len); } - return len; + return ret; } int pipe_start(int dev) @@ -265,9 +271,10 @@ int main(int argc, char *argv[]) chkne(dev = open(dev_name, O_CREAT | O_RDWR,0666)); trvd(dev); if (io_type == mmap_io) { - mm = mmap(0, mmapsize, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, dev, mmapoffset); + mm = mmap(NULL, mmapsize, PROT_READ | PROT_WRITE, MAP_SHARED, dev, mmapoffset); if (mm == MAP_FAILED) { fprintf(stderr, "mmap() failed\n"); + trvs(strerror(errno)); goto exit; } } diff --git a/ldt-test b/ldt-test index 8f21b96..e5afc13 100755 --- a/ldt-test +++ b/ldt-test @@ -42,7 +42,7 @@ tracing_stop() } # sudo rmmod parport_pc parport ppdev lp -sudo rmmod ldt ldt_plat_dev +sudo rmmod ldt ldt_plat_dev 2> /dev/null set -o errexit make -s sudo insmod ldt.ko irq=$irq diff --git a/ldt.c b/ldt.c index a4d5835..18f67fc 100644 --- a/ldt.c +++ b/ldt.c @@ -34,6 +34,10 @@ #include #include +static int bufsize = PFN_ALIGN(16 * 1024); +static void * in_buf; +static void * out_buf; + int irq = 0; module_param(irq, int, 0); @@ -157,6 +161,7 @@ static ssize_t ldt_read(struct file *file, char __user * buf, size_t count, loff { int ret; unsigned int copied; +_entry: // TODO: implement blocking I/O if (mutex_lock_interruptible(&read_lock)) return -EINTR; @@ -171,6 +176,7 @@ static ssize_t ldt_write(struct file *file, const char __user * buf, size_t coun { int ret; unsigned int copied; +_entry: if (mutex_lock_interruptible(&write_lock)) return -EINTR; @@ -179,12 +185,53 @@ static ssize_t ldt_write(struct file *file, const char __user * buf, size_t coun return ret ? ret : copied; } +void pages_set_reserved(struct page * page, int pages) +{ + for (; pages; pages--, page++) + SetPageReserved(page); +} + + +/* pages_flag - set or clear a flag for sequence of pages + * + * more generic soultion instead SetPageReserved, ClearPageReserved etc + */ + +void pages_flag(struct page * page, int pages, int mask, int value) +{ + for (; pages; pages--, page++) + if (value) + __set_bit(mask, &page->flags); + else + __clear_bit(mask, &page->flags); + +} + +static int ldt_mmap(struct file *filp, struct vm_area_struct *vma) +{ + void * buf; +_entry: + if (vma->vm_flags & VM_WRITE) + buf = in_buf; + else if (vma->vm_flags & VM_READ) + buf = out_buf; + + //vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); // PAGE_SHARED + if (remap_pfn_range(vma, vma->vm_start, virt_to_phys(in_buf) >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, vma->vm_page_prot)) { + trlm("remap_pfn_range failed"); + return -EAGAIN; + } + return 0; +} + struct file_operations ldt_fops = { .owner = THIS_MODULE, .open = ldt_open, .release = ldt_release, .read = ldt_read, .write = ldt_write, + .mmap = ldt_mmap, .poll = NULL, }; @@ -205,7 +252,19 @@ static __devinit int ldt_probe(struct platform_device *pdev) trvs_(KBUILD_MODNAME); trvp_(pdev); trvd_(irq); + trvd_(bufsize); trln(); + if (!( in_buf = alloc_pages_exact(bufsize, GFP_KERNEL | __GFP_ZERO) )) { + ret = - ENOMEM; + goto exit; + } + pages_flag(virt_to_page(in_buf), PFN_UP(bufsize), PG_reserved,1); + if (!( out_buf = alloc_pages_exact(bufsize, GFP_KERNEL | __GFP_ZERO) )) { + ret = - ENOMEM; + goto exit; + } + pages_flag(virt_to_page(out_buf), PFN_UP(bufsize), PG_reserved,1); + //ret = register_chrdev (0, KBUILD_MODNAME, &ldt_fops); if (pdev) { data = pdev->dev.platform_data; r = platform_get_resource(pdev, IORESOURCE_IRQ, 0); @@ -241,6 +300,14 @@ static int __devexit ldt_remove(struct platform_device *pdev) if (irq) { free_irq(irq, THIS_MODULE); } + if (in_buf) { + pages_flag(virt_to_page(in_buf), PFN_UP(bufsize), PG_reserved,0); + free_pages_exact(in_buf, bufsize); + } + if (out_buf) { + pages_flag(virt_to_page(out_buf), PFN_UP(bufsize), PG_reserved,0); + free_pages_exact(out_buf, bufsize); + } trvd(isr_counter); trvd(ldt_work_counter); return 0;