Browse Source

Restructure driver headers

Suren A. Chilingaryan 8 years ago
parent
commit
1120e8745c
27 changed files with 876 additions and 1056 deletions
  1. 12 6
      driver/Makefile
  2. 93 344
      driver/base.c
  3. 9 84
      driver/base.h
  4. 0 110
      driver/common.h
  5. 0 43
      driver/compat.h
  6. 23 11
      driver/config.h
  7. 25 0
      driver/debug.h
  8. 196 0
      driver/dev.c
  9. 52 0
      driver/dev.h
  10. 34 99
      driver/int.c
  11. 1 2
      driver/int.h
  12. 5 20
      driver/ioctl.c
  13. 178 1
      driver/ioctl.h
  14. 3 8
      driver/kmem.c
  15. 36 0
      driver/kmem.h
  16. 0 191
      driver/pciDriver.h
  17. 0 0
      driver/pcibus.c
  18. 7 0
      driver/pcibus.h
  19. 11 0
      driver/pcidriver.h
  20. 1 5
      driver/rdma.c
  21. 0 1
      driver/rdma.h
  22. 149 98
      driver/sysfs.c
  23. 11 19
      driver/sysfs.h
  24. 5 10
      driver/umem.c
  25. 21 0
      driver/umem.h
  26. 1 1
      pcilib/pci.h
  27. 3 3
      pcilib/pcilib.h

+ 12 - 6
driver/Makefile

@@ -1,11 +1,12 @@
 CONFIG_MODULE_SIG=n
 
 obj-m := pciDriver.o
-pciDriver-objs := base.o int.o umem.o kmem.o sysfs.o ioctl.o compat.o rdma.o
+pciDriver-objs := base.o dev.o int.o umem.o kmem.o sysfs.o ioctl.o pcibus.o rdma.o
 
 KERNELDIR ?= /lib/modules/$(shell uname -r)/build
 INSTALLDIR ?= /lib/modules/$(shell uname -r)/extra
 MAININSTALLDIR ?= /lib/modules/$(shell uname -r)/kernel/extra
+HEADERDIR ?= /lib/modules/$(shell uname -r)/source/include
 PWD := $(shell pwd)
 
 EXTRA_CFLAGS += -I$(M)/..
@@ -56,9 +57,11 @@ install:
 	@install -m 755 pciDriver.ko $(INSTALLDIR)
 	@echo "INSTALL $(INSTALLDIR)/pciDriver.symvers"
 	@install -m 644 Module.symvers $(INSTALLDIR)/pciDriver.symvers
-#	@echo "INSTALL /usr/include/pciDriver/driver/pciDriver.h"
-#	@mkdir -p /usr/include/pciDriver/driver
-#	@install -m 644 pciDriver.h /usr/include/pciDriver/driver
+	@echo "INSTALL $(HEADERDIR)/linux/pcidriver.h"
+	@install -m 644 pcidriver.h $(HEADERDIR)/linux/
+	@echo "INSTALL /usr/include/linux/pcidriver.h"
+	@mkdir -p /usr/include/linux
+	@install -m 644 ioctl.h /usr/include/linux/pcidriver.h
 
 uninstall:
 	@echo "UNINSTALL $(INSTALLDIR)/pciDriver.ko"
@@ -66,8 +69,11 @@ uninstall:
 	@rm -f $(MAININSTALLDIR)/pciDriver.ko
 	@rm -f $(INSTALLDIR)/pciDriver.symvers
 	@rm -f $(MAININSTALLDIR)/pciDriver.symvers
-	@echo "UNINSTALL /usr/include/pciDriver/driver/pciDriver.h"
-	@rm -rf /usr/include/pciDriver/driver
+	@echo "UNINSTALL /usr/include/linux/pcidriver.h"
+	@rm -rf /usr/include/pciDriver/
+	@rm -rf /usr/include/linux/pcidriver.h
+	@echo "UNINSTALL $(HEADERDIR)/linux/pcidriver.h"
+	@rm -rf $(HEADERDIR)/linux/pcidriver.h
 
 clean:
 	rm -rf *.o *.ko *.mod.c .*.o.cmd .*.o.tmp .*.ko.cmd  .*.o *.symvers modules.order .tmp_versions

+ 93 - 344
driver/base.c

@@ -1,13 +1,3 @@
-/**
- *
- * @file base.c
- * @author Guillermo Marcus
- * @date 2009-04-05
- * @brief Contains the main code which connects all the different parts and does
- * basic driver tasks like initialization.
- */
-
-
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/types.h>
@@ -30,139 +20,66 @@
 #include <linux/wait.h>
 
 #include "../pcilib/version.h"
-
-#include "config.h"
-#include "compat.h"
-#include "pciDriver.h"
-#include "common.h"
-#include "base.h"
-#include "int.h"
-#include "kmem.h"
-#include "umem.h"
-#include "ioctl.h"
 #include "build.h"
+#include "base.h"
 
-/*************************************************************************/
-/* Module device table associated with this driver */
-MODULE_DEVICE_TABLE(pci, pcidriver_ids);
 
-/* Module init and exit points */
-module_init(pcidriver_init);
-module_exit(pcidriver_exit);
 
 /* Module info */
 MODULE_AUTHOR("Guillermo Marcus");
 MODULE_DESCRIPTION("Simple PCI Driver");
 MODULE_LICENSE("GPL v2");
 
-/* Module class */
-static struct class_compat *pcidriver_class;
-
-#ifdef PCIDRIVER_DUMMY_DEVICE
-pcidriver_privdata_t *pcidriver_dummydata = NULL;
-#endif /* PCIDRIVER_DUMMY_DEVICE */
-
-/**
- *
- * Called when loading the driver
+/*
+ * This is the table of PCI devices handled by this driver by default
+ * If you want to add devices dynamically to this list, do:
  *
+ *   echo "vendor device" > /sys/bus/pci/drivers/pciDriver/new_id
+ * where vendor and device are in hex, without leading '0x'.
  */
-static int __init pcidriver_init(void)
-{
-    int err = 0;
-
-    /* Initialize the device count */
-    atomic_set(&pcidriver_deviceCount, 0);
 
-    memset(pcidriver_privdata, 0, sizeof(pcidriver_privdata));
-
-    /* Allocate character device region dynamically */
-    if ((err = alloc_chrdev_region(&pcidriver_devt, MINORNR, MAXDEVICES, NODENAME)) != 0) {
-        mod_info("Couldn't allocate chrdev region. Module not loaded.\n");
-        goto init_alloc_fail;
-    }
-    mod_info("Major %d allocated to nodename '%s'\n", MAJOR(pcidriver_devt), NODENAME);
+static const __devinitdata struct pci_device_id pcidriver_ids[] = {
+    { PCI_DEVICE( PCIE_XILINX_VENDOR_ID, PCIE_ML605_DEVICE_ID ) },          // PCI-E Xilinx ML605
+    { PCI_DEVICE( PCIE_XILINX_VENDOR_ID, PCIE_IPECAMERA_DEVICE_ID ) },      // PCI-E IPE Camera
+    { PCI_DEVICE( PCIE_XILINX_VENDOR_ID, PCIE_KAPTURE_DEVICE_ID ) },        // PCI-E KAPTURE board for HEB
+    {0,0,0,0},
+};
 
-    /* Register driver class */
-    pcidriver_class = class_create(THIS_MODULE, NODENAME);
+MODULE_DEVICE_TABLE(pci, pcidriver_ids);
 
-    if (IS_ERR(pcidriver_class)) {
-        mod_info("No sysfs support. Module not loaded.\n");
-        goto init_class_fail;
-    }
+/* Module class */
+static struct class *pcidriver_class;
 
-    /* Register PCI driver. This function returns the number of devices on some
-     * systems, therefore check for errors as < 0. */
 #ifdef PCIDRIVER_DUMMY_DEVICE
-    if ((err = pcidriver_probe(NULL, NULL)) < 0) {
+pcidriver_privdata_t *pcidriver_dummydata = NULL;
 #else /* PCIDRIVER_DUMMY_DEVICE */
-    if ((err = pci_register_driver(&pcidriver_driver)) < 0) {
+static struct pci_driver pcidriver_driver;
 #endif /* PCIDRIVER_DUMMY_DEVICE */
-        mod_info("Couldn't register PCI driver. Module not loaded.\n");
-        goto init_pcireg_fail;
-    }
-
-    mod_info("pcidriver %u.%u.%u loaded\n", PCILIB_VERSION_GET_MAJOR(PCILIB_VERSION), PCILIB_VERSION_GET_MINOR(PCILIB_VERSION), PCILIB_VERSION_GET_MICRO(PCILIB_VERSION));
-    mod_info("%s\n", PCIDRIVER_BUILD);
-    mod_info("%s\n", PCIDRIVER_REVISION);
-    if (strlen(PCIDRIVER_CHANGES)) {
-        mod_info("Extra changes - %s\n", PCIDRIVER_CHANGES);
-    }
 
-    return 0;
+/* Hold the allocated major & minor numbers */
+static dev_t pcidriver_devt;
 
-init_pcireg_fail:
-    class_destroy(pcidriver_class);
-init_class_fail:
-    unregister_chrdev_region(pcidriver_devt, MAXDEVICES);
-init_alloc_fail:
-    return err;
-}
+/* Number of devices allocated */
+static atomic_t pcidriver_deviceCount;
 
-/**
- *
- * Called when unloading the driver
- *
- */
-static void pcidriver_exit(void)
-{
-#ifdef PCIDRIVER_DUMMY_DEVICE
-    pcidriver_remove(NULL);
-#else
-    pci_unregister_driver(&pcidriver_driver);
-#endif /* PCIDRIVER_DUMMY_DEVICE */
+/* Private data for probed devices */
+static pcidriver_privdata_t* pcidriver_privdata[MAXDEVICES];
 
-    unregister_chrdev_region(pcidriver_devt, MAXDEVICES);
 
-    if (pcidriver_class != NULL)
-        class_destroy(pcidriver_class);
+pcidriver_privdata_t *pcidriver_get_privdata(int devid) {
+    if (devid >= MAXDEVICES)
+        return NULL;
 
-    mod_info("Module unloaded\n");
+    return pcidriver_privdata[devid];
 }
 
-/*************************************************************************/
-/* Driver functions */
+void pcidriver_put_privdata(pcidriver_privdata_t *privdata) {
 
-/**
- *
- * This struct defines the PCI entry points.
- * Will be registered at module init.
- *
- */
-#ifndef PCIDRIVER_DUMMY_DEVICE
-static struct pci_driver pcidriver_driver = {
-    .name = MODNAME,
-    .id_table = pcidriver_ids,
-    .probe = pcidriver_probe,
-    .remove = pcidriver_remove,
-};
-#endif /* ! PCIDRIVER_DUMMY_DEVICE */
+}
 
 /**
- *
  * This function is called when installing the driver for a device
  * @param pdev Pointer to the PCI device
- *
  */
 static int __devinit pcidriver_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
@@ -250,12 +167,8 @@ static int __devinit pcidriver_probe(struct pci_dev *pdev, const struct pci_devi
     privdata->devno = devno;
 
     /* FIXME: some error checking missing here */
-#ifdef PCIDRIVER_DUMMY_DEVICE
-    privdata->class_dev = class_device_create(pcidriver_class, NULL, devno, NULL, NODENAMEFMT, MINOR(pcidriver_devt) + devid, privdata);
-#else /* PCIDRIVER_DUMMY_DEVICE */
-    privdata->class_dev = class_device_create(pcidriver_class, NULL, devno, &(pdev->dev), NODENAMEFMT, MINOR(pcidriver_devt) + devid, privdata);
-#endif /* PCIDRIVER_DUMMY_DEVICE */
-    class_set_devdata( privdata->class_dev, privdata );
+    privdata->class_dev = device_create(pcidriver_class, NULL, devno, privdata, NODENAMEFMT, MINOR(pcidriver_devt) + devid);
+    dev_set_drvdata(privdata->class_dev, privdata);
     mod_info("Device /dev/%s%d added\n",NODENAME,MINOR(pcidriver_devt) + devid);
 
 #ifndef PCIDRIVER_DUMMY_DEVICE
@@ -264,31 +177,14 @@ static int __devinit pcidriver_probe(struct pci_dev *pdev, const struct pci_devi
         goto probe_irq_probe_fail;
 #endif /* ! PCIDRIVER_DUMMY_DEVICE */
 
-    /* Populate sysfs attributes for the class device */
     /* TODO: correct errorhandling. ewww. must remove the files in reversed order :-( */
-#define sysfs_attr(name) do { \
-			if (class_device_create_file(sysfs_attr_def_pointer, &sysfs_attr_def_name(name)) != 0) \
-				goto probe_device_create_fail; \
-			} while (0)
-#ifdef ENABLE_IRQ
-    sysfs_attr(irq_count);
-    sysfs_attr(irq_queues);
-#endif
-
-    sysfs_attr(mmap_mode);
-    sysfs_attr(mmap_area);
-    sysfs_attr(kmem_count);
-    sysfs_attr(kmem_alloc);
-    sysfs_attr(kmem_free);
-    sysfs_attr(kbuffers);
-    sysfs_attr(umappings);
-    sysfs_attr(umem_unmap);
-#undef sysfs_attr
+    if (pcidriver_create_sysfs_attributes(privdata) != 0)
+	goto probe_device_create_fail;
 
     /* Register character device */
-    cdev_init( &(privdata->cdev), &pcidriver_fops );
+    cdev_init(&(privdata->cdev), pcidriver_get_fops());
     privdata->cdev.owner = THIS_MODULE;
-    privdata->cdev.ops = &pcidriver_fops;
+    privdata->cdev.ops = pcidriver_get_fops();
     err = cdev_add( &privdata->cdev, devno, 1 );
     if (err) {
         mod_info( "Couldn't add character device.\n" );
@@ -338,23 +234,7 @@ static void __devexit pcidriver_remove(struct pci_dev *pdev)
     pcidriver_privdata[privdata->devid] = NULL;
 
     /* Removing sysfs attributes from class device */
-#define sysfs_attr(name) do { \
-			class_device_remove_file(sysfs_attr_def_pointer, &sysfs_attr_def_name(name)); \
-			} while (0)
-#ifdef ENABLE_IRQ
-    sysfs_attr(irq_count);
-    sysfs_attr(irq_queues);
-#endif
-
-    sysfs_attr(mmap_mode);
-    sysfs_attr(mmap_area);
-    sysfs_attr(kmem_count);
-    sysfs_attr(kmem_alloc);
-    sysfs_attr(kmem_free);
-    sysfs_attr(kbuffers);
-    sysfs_attr(umappings);
-    sysfs_attr(umem_unmap);
-#undef sysfs_attr
+    pcidriver_remove_sysfs_attributes(privdata);
 
     /* Free all allocated kmem buffers before leaving */
     pcidriver_kmem_free_all( privdata );
@@ -369,7 +249,7 @@ static void __devexit pcidriver_remove(struct pci_dev *pdev)
     cdev_del(&(privdata->cdev));
 
     /* Removing the device from sysfs */
-    class_device_destroy(pcidriver_class, privdata->devno);
+    device_destroy(pcidriver_class, privdata->devno);
 
     /* Releasing privdata */
     kfree(privdata);
@@ -384,213 +264,82 @@ static void __devexit pcidriver_remove(struct pci_dev *pdev)
 
 }
 
-/*************************************************************************/
-/* File operations */
-/*************************************************************************/
-
-/**
- * This struct defines the file operation entry points.
- *
- * @see pcidriver_ioctl
- * @see pcidriver_mmap
- * @see pcidriver_open
- * @see pcidriver_release
- *
- */
-static struct file_operations pcidriver_fops = {
-    .owner = THIS_MODULE,
-    .unlocked_ioctl = pcidriver_ioctl,
-    .mmap = pcidriver_mmap,
-    .open = pcidriver_open,
-    .release = pcidriver_release,
+#ifndef PCIDRIVER_DUMMY_DEVICE
+static struct pci_driver pcidriver_driver = {
+    .name = MODNAME,
+    .id_table = pcidriver_ids,
+    .probe = pcidriver_probe,
+    .remove = pcidriver_remove,
 };
+#endif /* ! PCIDRIVER_DUMMY_DEVICE */
 
-void pcidriver_module_get(pcidriver_privdata_t *privdata) {
-    atomic_inc(&(privdata->refs));
-//    mod_info("Ref: %i\n", atomic_read(&(privdata->refs)));
-}
-
-void pcidriver_module_put(pcidriver_privdata_t *privdata) {
-    if (atomic_add_negative(-1, &(privdata->refs))) {
-        atomic_inc(&(privdata->refs));
-        mod_info("Reference counting error...");
-    } else {
-//	mod_info("Unref: %i\n", atomic_read(&(privdata->refs)));
-    }
-}
-
-/**
- *
- * Called when an application open()s a /dev/fpga*, attaches the private data
- * with the file pointer.
- *
- */
-int pcidriver_open(struct inode *inode, struct file *filp)
+static int __init pcidriver_init(void)
 {
-    pcidriver_privdata_t *privdata;
-
-    /* Set the private data area for the file */
-    privdata = container_of( inode->i_cdev, pcidriver_privdata_t, cdev);
-    filp->private_data = privdata;
-
-    pcidriver_module_get(privdata);
-
-    return 0;
-}
+    int err = 0;
 
-/**
- *
- * Called when the application close()s the file descriptor. Does nothing at
- * the moment.
- *
- */
-int pcidriver_release(struct inode *inode, struct file *filp)
-{
-    pcidriver_privdata_t *privdata;
+    /* Initialize the device count */
+    atomic_set(&pcidriver_deviceCount, 0);
 
-    /* Get the private data area */
-    privdata = filp->private_data;
+    memset(pcidriver_privdata, 0, sizeof(pcidriver_privdata));
 
-    pcidriver_module_put(privdata);
+    /* Allocate character device region dynamically */
+    if ((err = alloc_chrdev_region(&pcidriver_devt, MINORNR, MAXDEVICES, NODENAME)) != 0) {
+        mod_info("Couldn't allocate chrdev region. Module not loaded.\n");
+        goto init_alloc_fail;
+    }
+    mod_info("Major %d allocated to nodename '%s'\n", MAJOR(pcidriver_devt), NODENAME);
 
-    return 0;
-}
+    /* Register driver class */
+    pcidriver_class = class_create(THIS_MODULE, NODENAME);
 
-/**
- *
- * This function is the entry point for mmap() and calls either pcidriver_mmap_pci
- * or pcidriver_mmap_kmem
- *
- * @see pcidriver_mmap_pci
- * @see pcidriver_mmap_kmem
- *
- */
-int pcidriver_mmap(struct file *filp, struct vm_area_struct *vma)
-{
-    pcidriver_privdata_t *privdata;
-    int ret = 0, bar;
-
-    mod_info_dbg("Entering mmap\n");
-
-    /* Get the private data area */
-    privdata = filp->private_data;
-
-    /* Check the current mmap mode */
-    switch (privdata->mmap_mode) {
-    case PCIDRIVER_MMAP_PCI:
-        /* Mmap a PCI region */
-        switch (privdata->mmap_area) {
-        case PCIDRIVER_BAR0:
-            bar = 0;
-            break;
-        case PCIDRIVER_BAR1:
-            bar = 1;
-            break;
-        case PCIDRIVER_BAR2:
-            bar = 2;
-            break;
-        case PCIDRIVER_BAR3:
-            bar = 3;
-            break;
-        case PCIDRIVER_BAR4:
-            bar = 4;
-            break;
-        case PCIDRIVER_BAR5:
-            bar = 5;
-            break;
-        default:
-            mod_info("Attempted to mmap a PCI area with the wrong mmap_area value: %d\n",privdata->mmap_area);
-            return -EINVAL;			/* invalid parameter */
-            break;
-        }
-        ret = pcidriver_mmap_pci(privdata, vma, bar);
-        break;
-    case PCIDRIVER_MMAP_KMEM:
-        /* mmap a Kernel buffer */
-        ret = pcidriver_mmap_kmem(privdata, vma);
-        break;
-    default:
-        mod_info( "Invalid mmap_mode value (%d)\n",privdata->mmap_mode );
-        return -EINVAL;			/* Invalid parameter (mode) */
+    if (IS_ERR(pcidriver_class)) {
+        mod_info("No sysfs support. Module not loaded.\n");
+        goto init_class_fail;
     }
 
-    return ret;
-}
-
-/*************************************************************************/
-/* Internal driver functions */
-int pcidriver_mmap_pci(pcidriver_privdata_t *privdata, struct vm_area_struct *vmap, int bar)
-{
+    /* Register PCI driver. This function returns the number of devices on some
+     * systems, therefore check for errors as < 0. */
 #ifdef PCIDRIVER_DUMMY_DEVICE
-    return -ENXIO;
+    if ((err = pcidriver_probe(NULL, NULL)) < 0) {
 #else /* PCIDRIVER_DUMMY_DEVICE */
-    int ret = 0;
-    unsigned long bar_addr;
-    unsigned long bar_length, vma_size;
-    unsigned long bar_flags;
-
-    mod_info_dbg("Entering mmap_pci\n");
-
-
-    /* Get info of the BAR to be mapped */
-    bar_addr = pci_resource_start(privdata->pdev, bar);
-    bar_length = pci_resource_len(privdata->pdev, bar);
-    bar_flags = pci_resource_flags(privdata->pdev, bar);
-
-    /* Check sizes */
-    vma_size = (vmap->vm_end - vmap->vm_start);
-
-    if ((vma_size != bar_length) &&
-            ((bar_length < PAGE_SIZE) && (vma_size != PAGE_SIZE))) {
-        mod_info( "mmap size is not correct! bar: %lu - vma: %lu\n", bar_length, vma_size );
-        return -EINVAL;
+    if ((err = pci_register_driver(&pcidriver_driver)) < 0) {
+#endif /* PCIDRIVER_DUMMY_DEVICE */
+        mod_info("Couldn't register PCI driver. Module not loaded.\n");
+        goto init_pcireg_fail;
     }
 
-    if (bar_flags & IORESOURCE_IO) {
-        /* Unlikely case, we will mmap a IO region */
-
-        /* IO regions are never cacheable */
-        vmap->vm_page_prot = pgprot_noncached(vmap->vm_page_prot);
-
-        /* Map the BAR */
-        ret = io_remap_pfn_range_compat(vmap, vmap->vm_start, bar_addr, bar_length, vmap->vm_page_prot);
-    } else {
-        /* Normal case, mmap a memory region */
-
-        /* Ensure this VMA is non-cached, if it is not flaged as prefetchable.
-         * If it is prefetchable, caching is allowed and will give better performance.
-         * This should be set properly by the BIOS, but we want to be sure. */
-        /* adapted from drivers/char/mem.c, mmap function. */
-
-        /* Setting noncached disables MTRR registers, and we want to use them.
-         * So we take this code out. This can lead to caching problems if and only if
-         * the System BIOS set something wrong. Check LDDv3, page 425.
-         */
-
-//                if (!(bar_flags & IORESOURCE_PREFETCH))
-//			vmap->vm_page_prot = pgprot_noncached(vmap->vm_page_prot);
-
-
-        /* Map the BAR */
-        ret = remap_pfn_range_compat(vmap, vmap->vm_start, bar_addr, bar_length, vmap->vm_page_prot);
+    mod_info("pcidriver %u.%u.%u loaded\n", PCILIB_VERSION_GET_MAJOR(PCILIB_VERSION), PCILIB_VERSION_GET_MINOR(PCILIB_VERSION), PCILIB_VERSION_GET_MICRO(PCILIB_VERSION));
+    mod_info("%s\n", PCIDRIVER_BUILD);
+    mod_info("%s\n", PCIDRIVER_REVISION);
+    if (strlen(PCIDRIVER_CHANGES)) {
+        mod_info("Extra changes - %s\n", PCIDRIVER_CHANGES);
     }
 
-    if (ret) {
-        mod_info("remap_pfn_range failed\n");
-        return -EAGAIN;
-    }
+    return 0;
 
-    return 0;	/* success */
-#endif /* PCIDRIVER_DUMMY_DEVICE */
+init_pcireg_fail:
+    class_destroy(pcidriver_class);
+init_class_fail:
+    unregister_chrdev_region(pcidriver_devt, MAXDEVICES);
+init_alloc_fail:
+    return err;
 }
 
-pcidriver_privdata_t *pcidriver_get_privdata(int devid) {
-    if (devid >= MAXDEVICES)
-        return NULL;
+static void pcidriver_exit(void)
+{
+#ifdef PCIDRIVER_DUMMY_DEVICE
+    pcidriver_remove(NULL);
+#else
+    pci_unregister_driver(&pcidriver_driver);
+#endif /* PCIDRIVER_DUMMY_DEVICE */
 
-    return pcidriver_privdata[devid];
-}
+    unregister_chrdev_region(pcidriver_devt, MAXDEVICES);
 
-void pcidriver_put_privdata(pcidriver_privdata_t *privdata) {
+    if (pcidriver_class != NULL)
+        class_destroy(pcidriver_class);
 
+    mod_info("Module unloaded\n");
 }
+
+module_init(pcidriver_init);
+module_exit(pcidriver_exit);

+ 9 - 84
driver/base.h

@@ -1,90 +1,15 @@
 #ifndef _PCIDRIVER_BASE_H
 #define _PCIDRIVER_BASE_H
 
+#include "config.h"
+#include "compat.h"
+#include "debug.h"
+#include "pcibus.h"
 #include "sysfs.h"
+#include "dev.h"
+#include "int.h"
 
-/**
- *
- * This file contains prototypes and data structures for internal use of the pciDriver.
- *
- *
- */
+pcidriver_privdata_t *pcidriver_get_privdata(int devid);
+void pcidriver_put_privdata(pcidriver_privdata_t *privdata);
 
-/* prototypes for file_operations */
-static struct file_operations pcidriver_fops;
-int pcidriver_mmap( struct file *filp, struct vm_area_struct *vmap );
-int pcidriver_open(struct inode *inode, struct file *filp );
-int pcidriver_release(struct inode *inode, struct file *filp);
-
-/* prototypes for device operations */
-#ifndef PCIDRIVER_DUMMY_DEVICE
-static struct pci_driver pcidriver_driver;
-#endif /* ! PCIDRIVER_DUMMY_DEVICE */
-static int __devinit pcidriver_probe(struct pci_dev *pdev, const struct pci_device_id *id);
-static void __devexit pcidriver_remove(struct pci_dev *pdev);
-
-
-
-/* prototypes for module operations */
-static int __init pcidriver_init(void);
-static void pcidriver_exit(void);
-
-/*
- * This is the table of PCI devices handled by this driver by default
- * If you want to add devices dynamically to this list, do:
- *
- *   echo "vendor device" > /sys/bus/pci/drivers/pciDriver/new_id
- * where vendor and device are in hex, without leading '0x'.
- *
- * The IDs themselves can be found in common.h
- *
- * For more info, see <kernel-source>/Documentation/pci.txt
- *
- * __devinitdata is applied because the kernel does not need those
- * tables any more after boot is finished on systems which don't
- * support hotplug.
- *
- */
-
-static const __devinitdata struct pci_device_id pcidriver_ids[] = {
-    { PCI_DEVICE( PCIE_XILINX_VENDOR_ID, PCIE_ML605_DEVICE_ID ) },          // PCI-E Xilinx ML605
-    { PCI_DEVICE( PCIE_XILINX_VENDOR_ID, PCIE_IPECAMERA_DEVICE_ID ) },      // PCI-E IPE Camera
-    { PCI_DEVICE( PCIE_XILINX_VENDOR_ID, PCIE_KAPTURE_DEVICE_ID ) },        // PCI-E KAPTURE board for HEB
-    {0,0,0,0},
-};
-
-/* prototypes for internal driver functions */
-int pcidriver_pci_read( pcidriver_privdata_t *privdata, pci_cfg_cmd *pci_cmd );
-int pcidriver_pci_write( pcidriver_privdata_t *privdata, pci_cfg_cmd *pci_cmd );
-int pcidriver_pci_info( pcidriver_privdata_t *privdata, pcilib_board_info_t *pci_info );
-
-int pcidriver_mmap_pci( pcidriver_privdata_t *privdata, struct vm_area_struct *vmap , int bar );
-int pcidriver_mmap_kmem( pcidriver_privdata_t *privdata, struct vm_area_struct *vmap );
-
-/*************************************************************************/
-/* Static data */
-/* Hold the allocated major & minor numbers */
-static dev_t pcidriver_devt;
-
-/* Number of devices allocated */
-static atomic_t pcidriver_deviceCount;
-
-/* Private data for probed devices */
-static pcidriver_privdata_t* pcidriver_privdata[MAXDEVICES];
-
-/* Sysfs attributes */
-static DEVICE_ATTR(mmap_mode, 0664, pcidriver_show_mmap_mode, pcidriver_store_mmap_mode);
-static DEVICE_ATTR(mmap_area, 0664, pcidriver_show_mmap_area, pcidriver_store_mmap_area);
-static DEVICE_ATTR(kmem_count, S_IRUGO, pcidriver_show_kmem_count, NULL);
-static DEVICE_ATTR(kbuffers, S_IRUGO, pcidriver_show_kbuffers, NULL);
-static DEVICE_ATTR(kmem_alloc, 0220, NULL, pcidriver_store_kmem_alloc);
-static DEVICE_ATTR(kmem_free, 0220, NULL, pcidriver_store_kmem_free);
-static DEVICE_ATTR(umappings, S_IRUGO, pcidriver_show_umappings, NULL);
-static DEVICE_ATTR(umem_unmap, 0220, NULL, pcidriver_store_umem_unmap);
-
-#ifdef ENABLE_IRQ
-static DEVICE_ATTR(irq_count, S_IRUGO, pcidriver_show_irq_count, NULL);
-static DEVICE_ATTR(irq_queues, S_IRUGO, pcidriver_show_irq_queues, NULL);
-#endif
-
-#endif
+#endif /* _PCIDRIVER_BASE_H */

+ 0 - 110
driver/common.h

@@ -1,110 +0,0 @@
-#ifndef _PCIDRIVER_COMMON_H
-#define _PCIDRIVER_COMMON_H
-
-#include "../pcilib/kmem.h"
-/*************************************************************************/
-/* Private data types and structures */
-
-
-/* Define an entry in the kmem list (this list is per device) */
-/* This list keeps references to the allocated kernel buffers */
-typedef struct {
-    int id;
-    enum dma_data_direction direction;
-
-    struct list_head list;
-    dma_addr_t dma_handle;
-    unsigned long cpua;
-    unsigned long size;
-    unsigned long type;
-    unsigned long align;
-
-    unsigned long use;
-    unsigned long item;
-
-    spinlock_t lock;
-    unsigned long mode;
-    unsigned long refs;
-
-    struct class_device_attribute sysfs_attr;	/* initialized when adding the entry */
-} pcidriver_kmem_entry_t;
-
-/* Define an entry in the umem list (this list is per device) */
-/* This list keeps references to the SG lists for each mapped userspace region */
-typedef struct {
-    int id;
-    struct list_head list;
-    unsigned int nr_pages;		/* number of pages for this user memeory area */
-    struct page **pages;		/* list of pointers to the pages */
-    unsigned int nents;		/* actual entries in the scatter/gatter list (NOT nents for the map function, but the result) */
-    struct scatterlist *sg;		/* list of sg entries */
-    struct class_device_attribute sysfs_attr;	/* initialized when adding the entry */
-} pcidriver_umem_entry_t;
-
-/* Hold the driver private data */
-typedef struct  {
-    int devid;                                      /* the device id */
-    dev_t devno;					/* device number (major and minor) */
-    struct pci_dev *pdev;				/* PCI device */
-    struct class_device *class_dev;                 /* Class device */
-    struct cdev cdev;				/* char device struct */
-    int mmap_mode;					/* current mmap mode */
-    int mmap_area;					/* current PCI mmap area */
-
-#ifdef ENABLE_IRQ
-    int irq_enabled;				/* Non-zero if IRQ is enabled */
-    int irq_count;					/* Just an IRQ counter */
-
-    wait_queue_head_t irq_queues[ PCIDRIVER_INT_MAXSOURCES ];       /* One queue per interrupt source */
-    atomic_t irq_outstanding[ PCIDRIVER_INT_MAXSOURCES ];           /* Outstanding interrupts per queue */
-    volatile unsigned int *bars_kmapped[6];		                /* PCI BARs mmapped in kernel space */
-#endif
-
-    spinlock_t kmemlist_lock;			/* Spinlock to lock kmem list operations */
-    struct list_head kmem_list;			/* List of 'kmem_list_entry's associated with this device */
-    pcidriver_kmem_entry_t *kmem_last_sync;		/* Last accessed kmem entry */
-    atomic_t kmem_count;				/* id for next kmem entry */
-
-    int kmem_cur_id;				/* Currently selected kmem buffer, for mmap */
-
-    spinlock_t umemlist_lock;			/* Spinlock to lock umem list operations */
-    struct list_head umem_list;			/* List of 'umem_list_entry's associated with this device */
-    atomic_t umem_count;				/* id for next umem entry */
-
-    int msi_mode;					/* Flag specifying if interrupt have been initialized in MSI mode */
-    atomic_t refs;					/* Reference counter */
-} pcidriver_privdata_t;
-
-
-void pcidriver_module_get(pcidriver_privdata_t *privdata);
-void pcidriver_module_put(pcidriver_privdata_t *privdata);
-
-pcidriver_privdata_t *pcidriver_get_privdata(int devid);
-void pcidriver_put_privdata(pcidriver_privdata_t *privdata);
-
-
-/*************************************************************************/
-/* Some nice defines that make code more readable */
-/* This is to print nice info in the log */
-
-#ifdef DEBUG
-#define mod_info( args... ) \
-    do { printk( KERN_INFO "%s - %s : ", MODNAME , __FUNCTION__ );\
-    printk( args ); } while(0)
-#define mod_info_dbg( args... ) \
-    do { printk( KERN_INFO "%s - %s : ", MODNAME , __FUNCTION__ );\
-    printk( args ); } while(0)
-#else
-#define mod_info( args... ) \
-    do { printk( KERN_INFO "%s: ", MODNAME );\
-    printk( args ); } while(0)
-#define mod_info_dbg( args... )
-#endif
-
-#define mod_crit( args... ) \
-    do { printk( KERN_CRIT "%s: ", MODNAME );\
-    printk( args ); } while(0)
-
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-
-#endif

+ 0 - 43
driver/compat.h

@@ -37,47 +37,4 @@
 # define __devinitdata
 #endif
 
-#define compat_lock_page __set_page_locked
-#define compat_unlock_page __clear_page_locked
-
-
-#define class_device_attribute device_attribute
-#define CLASS_DEVICE_ATTR DEVICE_ATTR
-#define class_device device
-#define class_data dev
-#define class_device_create(type, parent, devno, devpointer, nameformat, minor, privdata) \
-		device_create(type, parent, devno, privdata, nameformat, minor)
-#define class_device_create_file device_create_file
-#define class_device_remove_file device_remove_file
-#define class_device_destroy device_destroy
-#define DEVICE_ATTR_COMPAT struct device_attribute *attr,
-#define class_set_devdata dev_set_drvdata
-
-#define sysfs_attr_def_name(name) dev_attr_##name
-#define sysfs_attr_def_pointer privdata->class_dev
-#define SYSFS_GET_FUNCTION(name) ssize_t name(struct device *dev, struct device_attribute *attr, char *buf)
-#define SYSFS_SET_FUNCTION(name) ssize_t name(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-#define SYSFS_GET_PRIVDATA dev_get_drvdata(dev)
-
-#define class_compat class
-
-
-#define IRQ_HANDLER_FUNC(name) irqreturn_t name(int irq, void *dev_id)
-
-#define request_irq(irq, irq_handler, modname, privdata) request_irq(irq, irq_handler, IRQF_SHARED, modname, privdata)
-
-
-#define io_remap_pfn_range_compat(vmap, vm_start, bar_addr, bar_length, vm_page_prot) \
-	io_remap_pfn_range(vmap, vm_start, (bar_addr >> PAGE_SHIFT), bar_length, vm_page_prot)
-
-#define remap_pfn_range_compat(vmap, vm_start, bar_addr, bar_length, vm_page_prot) \
-	remap_pfn_range(vmap, vm_start, (bar_addr >> PAGE_SHIFT), bar_length, vm_page_prot)
-
-#define remap_pfn_range_cpua_compat(vmap, vm_start, cpua, size, vm_page_prot) \
-	remap_pfn_range(vmap, vm_start, page_to_pfn(virt_to_page((void*)cpua)), size, vm_page_prot)
-
-
-int pcidriver_pcie_get_mps(struct pci_dev *dev);
-int pcidriver_pcie_set_mps(struct pci_dev *dev, int mps);
-
 #endif

+ 23 - 11
driver/config.h

@@ -1,6 +1,5 @@
-/*******************************/
-/* Configuration of the driver */
-/*******************************/
+#ifndef _PCIDRIVER_CONFIG_H
+#define _PCIDRIVER_CONFIG_H
 
 /* Debug messages */
 //#define DEBUG
@@ -8,16 +7,29 @@
 /* Enable/disable IRQ handling */
 #define ENABLE_IRQ
 
-/* The name of the module */
-#define MODNAME "pciDriver"
+/* Maximum number of interrupt sources */
+#define PCIDRIVER_INT_MAXSOURCES		16
+
+/* Maximum number of devices*/
+#define MAXDEVICES 				4
 
-/* Major number is allocated dynamically */
 /* Minor number */
-#define MINORNR 0
+#define MINORNR 				0
+
+/* The name of the module */
+#define MODNAME 				"pciDriver"
 
 /* Node name of the char device */
-#define NODENAME "fpga"
-#define NODENAMEFMT "fpga%d"
+#define NODENAME 				"fpga"
+#define NODENAMEFMT 				"fpga%d"
 
-/* Maximum number of devices*/
-#define MAXDEVICES 4
+/* Identifies the PCI-E Xilinx ML605 */
+#define PCIE_XILINX_VENDOR_ID 			0x10ee
+#define PCIE_ML605_DEVICE_ID 			0x6024
+
+/* Identifies the PCI-E IPE Hardware */
+#define PCIE_IPECAMERA_DEVICE_ID 		0x6081
+#define PCIE_KAPTURE_DEVICE_ID 			0x6028
+
+
+#endif /* _PCIDRIVER_CONFIG_H */

+ 25 - 0
driver/debug.h

@@ -0,0 +1,25 @@
+#ifndef _PCIDRIVER_DEBUG_H
+#define _PCIDRIVER_DEBUG_H
+
+#include "config.h"
+
+#ifdef DEBUG
+#define mod_info( args... ) \
+    do { printk( KERN_INFO "%s - %s : ", MODNAME , __FUNCTION__ );\
+    printk( args ); } while(0)
+#define mod_info_dbg( args... ) \
+    do { printk( KERN_INFO "%s - %s : ", MODNAME , __FUNCTION__ );\
+    printk( args ); } while(0)
+#else
+#define mod_info( args... ) \
+    do { printk( KERN_INFO "%s: ", MODNAME );\
+    printk( args ); } while(0)
+#define mod_info_dbg( args... )
+#endif
+
+#define mod_crit( args... ) \
+    do { printk( KERN_CRIT "%s: ", MODNAME );\
+    printk( args ); } while(0)
+
+
+#endif /* _PCIDRIVER_DEBUG_H */

+ 196 - 0
driver/dev.c

@@ -0,0 +1,196 @@
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/sysfs.h>
+#include <asm/atomic.h>
+#include <linux/pagemap.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <asm/scatterlist.h>
+#include <linux/vmalloc.h>
+#include <linux/stat.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+
+#include "base.h"
+
+
+/**
+ *
+ * Called when an application open()s a /dev/fpga*, attaches the private data
+ * with the file pointer.
+ *
+ */
+static int pcidriver_open(struct inode *inode, struct file *filp)
+{
+    pcidriver_privdata_t *privdata;
+
+    /* Set the private data area for the file */
+    privdata = container_of( inode->i_cdev, pcidriver_privdata_t, cdev);
+    filp->private_data = privdata;
+
+    pcidriver_module_get(privdata);
+
+    return 0;
+}
+
+/**
+ *
+ * Called when the application close()s the file descriptor. Does nothing at
+ * the moment.
+ *
+ */
+static int pcidriver_release(struct inode *inode, struct file *filp)
+{
+    pcidriver_privdata_t *privdata;
+
+    /* Get the private data area */
+    privdata = filp->private_data;
+
+    pcidriver_module_put(privdata);
+
+    return 0;
+}
+
+
+/*************************************************************************/
+/* Internal driver functions */
+static int pcidriver_mmap_bar(pcidriver_privdata_t *privdata, struct vm_area_struct *vmap, int bar)
+{
+#ifdef PCIDRIVER_DUMMY_DEVICE
+    return -ENXIO;
+#else /* PCIDRIVER_DUMMY_DEVICE */
+    int ret = 0;
+    unsigned long bar_addr;
+    unsigned long bar_length, vma_size;
+    unsigned long bar_flags;
+
+    mod_info_dbg("Entering mmap_pci\n");
+
+
+    /* Get info of the BAR to be mapped */
+    bar_addr = pci_resource_start(privdata->pdev, bar);
+    bar_length = pci_resource_len(privdata->pdev, bar);
+    bar_flags = pci_resource_flags(privdata->pdev, bar);
+
+    /* Check sizes */
+    vma_size = (vmap->vm_end - vmap->vm_start);
+
+    if ((vma_size != bar_length) &&
+            ((bar_length < PAGE_SIZE) && (vma_size != PAGE_SIZE))) {
+        mod_info( "mmap size is not correct! bar: %lu - vma: %lu\n", bar_length, vma_size );
+        return -EINVAL;
+    }
+
+    if (bar_flags & IORESOURCE_IO) {
+        /* Unlikely case, we will mmap a IO region */
+
+        /* IO regions are never cacheable */
+        vmap->vm_page_prot = pgprot_noncached(vmap->vm_page_prot);
+
+        /* Map the BAR */
+        ret = io_remap_pfn_range(vmap, vmap->vm_start, (bar_addr >> PAGE_SHIFT), bar_length, vmap->vm_page_prot);
+    } else {
+        /* Normal case, mmap a memory region */
+
+        /* Ensure this VMA is non-cached, if it is not flaged as prefetchable.
+         * If it is prefetchable, caching is allowed and will give better performance.
+         * This should be set properly by the BIOS, but we want to be sure. */
+        /* adapted from drivers/char/mem.c, mmap function. */
+
+        /* Setting noncached disables MTRR registers, and we want to use them.
+         * So we take this code out. This can lead to caching problems if and only if
+         * the System BIOS set something wrong. Check LDDv3, page 425.
+         */
+
+//                if (!(bar_flags & IORESOURCE_PREFETCH))
+//			vmap->vm_page_prot = pgprot_noncached(vmap->vm_page_prot);
+
+
+        /* Map the BAR */
+        ret = remap_pfn_range(vmap, vmap->vm_start, (bar_addr >> PAGE_SHIFT), bar_length, vmap->vm_page_prot);
+    }
+
+    if (ret) {
+        mod_info("remap_pfn_range failed\n");
+        return -EAGAIN;
+    }
+
+    return 0;	/* success */
+#endif /* PCIDRIVER_DUMMY_DEVICE */
+}
+
+/**
+ *
+ * This function is the entry point for mmap() and calls either pcidriver_mmap_bar
+ * or pcidriver_mmap_kmem
+ *
+ * @see pcidriver_mmap_bar
+ * @see pcidriver_mmap_kmem
+ *
+ */
+static int pcidriver_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+    pcidriver_privdata_t *privdata;
+    int ret = 0, bar;
+
+    mod_info_dbg("Entering mmap\n");
+
+    /* Get the private data area */
+    privdata = filp->private_data;
+
+    /* Check the current mmap mode */
+    switch (privdata->mmap_mode) {
+     case PCIDRIVER_MMAP_PCI:
+	bar = privdata->mmap_area;
+	if ((bar < 0)||(bar > 5)) {
+            mod_info("Attempted to mmap a PCI area with the wrong mmap_area value: %d\n",privdata->mmap_area);
+            return -EINVAL;
+        }
+        ret = pcidriver_mmap_bar(privdata, vma, bar);
+        break;
+    case PCIDRIVER_MMAP_KMEM:
+        ret = pcidriver_mmap_kmem(privdata, vma);
+        break;
+    default:
+        mod_info( "Invalid mmap_mode value (%d)\n",privdata->mmap_mode );
+        return -EINVAL;			/* Invalid parameter (mode) */
+    }
+
+    return ret;
+}
+
+static struct file_operations pcidriver_fops = {
+    .owner = THIS_MODULE,
+    .unlocked_ioctl = pcidriver_ioctl,
+    .mmap = pcidriver_mmap,
+    .open = pcidriver_open,
+    .release = pcidriver_release,
+};
+
+const struct file_operations *pcidriver_get_fops(void)
+{
+    return &pcidriver_fops;
+}
+
+
+void pcidriver_module_get(pcidriver_privdata_t *privdata) {
+    atomic_inc(&(privdata->refs));
+//    mod_info("Ref: %i\n", atomic_read(&(privdata->refs)));
+}
+
+void pcidriver_module_put(pcidriver_privdata_t *privdata) {
+    if (atomic_add_negative(-1, &(privdata->refs))) {
+        atomic_inc(&(privdata->refs));
+        mod_info("Reference counting error...");
+    } else {
+//	mod_info("Unref: %i\n", atomic_read(&(privdata->refs)));
+    }
+}

+ 52 - 0
driver/dev.h

@@ -0,0 +1,52 @@
+#ifndef _PCIDRIVER_DEV_H
+#define _PCIDRIVER_DEV_H
+
+typedef struct pcidriver_privdata_s pcidriver_privdata_t;
+
+#include "kmem.h"
+#include "umem.h"
+
+
+/* Hold the driver private data */
+struct pcidriver_privdata_s {
+    int devid;                                  /* the device id */
+    dev_t devno;				/* device number (major and minor) */
+    struct pci_dev *pdev;			/* PCI device */
+    struct device *class_dev;                 	/* Class device */
+    struct cdev cdev;				/* char device struct */
+    int mmap_mode;				/* current mmap mode */
+    int mmap_area;				/* current PCI mmap area */
+
+#ifdef ENABLE_IRQ
+    int irq_enabled;				/* Non-zero if IRQ is enabled */
+    int irq_count;				/* Just an IRQ counter */
+
+    wait_queue_head_t irq_queues[ PCIDRIVER_INT_MAXSOURCES ];       /* One queue per interrupt source */
+    atomic_t irq_outstanding[ PCIDRIVER_INT_MAXSOURCES ];           /* Outstanding interrupts per queue */
+    volatile unsigned int *bars_kmapped[6];		            /* PCI BARs mmapped in kernel space */
+#endif
+
+    spinlock_t kmemlist_lock;			/* Spinlock to lock kmem list operations */
+    struct list_head kmem_list;			/* List of 'kmem_list_entry's associated with this device */
+    pcidriver_kmem_entry_t *kmem_last_sync;	/* Last accessed kmem entry */
+    atomic_t kmem_count;			/* id for next kmem entry */
+
+    int kmem_cur_id;				/* Currently selected kmem buffer, for mmap */
+
+    spinlock_t umemlist_lock;			/* Spinlock to lock umem list operations */
+    struct list_head umem_list;			/* List of 'umem_list_entry's associated with this device */
+    atomic_t umem_count;			/* id for next umem entry */
+
+    int msi_mode;				/* Flag specifying if interrupt have been initialized in MSI mode */
+    atomic_t refs;				/* Reference counter */
+};
+
+const struct file_operations *pcidriver_get_fops(void);
+
+void pcidriver_module_get(pcidriver_privdata_t *privdata);
+void pcidriver_module_put(pcidriver_privdata_t *privdata);
+
+long pcidriver_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+
+#endif /* _PCIDRIVER_DEV_H */
+

+ 34 - 99
driver/int.c

@@ -7,36 +7,6 @@
  *
  */
 
-/*
- * Change History:
- *
- * $Log: not supported by cvs2svn $
- * Revision 1.7  2008-01-11 10:18:28  marcus
- * Modified interrupt mechanism. Added atomic functions and queues, to address race conditions. Removed unused interrupt code.
- *
- * Revision 1.6  2007-11-04 20:58:22  marcus
- * Added interrupt generator acknowledge.
- * Fixed wrong operator.
- *
- * Revision 1.5  2007-10-31 15:42:21  marcus
- * Added IG ack for testing, may be removed later.
- *
- * Revision 1.4  2007-07-17 13:15:56  marcus
- * Removed Tasklets.
- * Using newest map for the ABB interrupts.
- *
- * Revision 1.3  2007-07-05 15:30:30  marcus
- * Added support for both register maps of the ABB.
- *
- * Revision 1.2  2007-05-29 07:50:18  marcus
- * Split code into 2 files. May get merged in the future again....
- *
- * Revision 1.1  2007/03/01 16:57:43  marcus
- * Divided driver file to ease the interrupt hooks for the user of the driver.
- * Modified Makefile accordingly.
- *
- */
-
 #include <linux/version.h>
 #include <linux/string.h>
 #include <linux/types.h>
@@ -48,41 +18,47 @@
 #include <linux/sched.h>
 #include <stdbool.h>
 
-#include "config.h"
+#include "base.h"
 
-#include "compat.h"
-
-#include "pciDriver.h"
+/**
+ *
+ * Acknowledges the receival of an interrupt to the card.
+ *
+ * @returns true if the card was acknowledget
+ * @returns false if the interrupt was not for one of our cards
+ *
+ * @see check_acknowlegde_channel
+ *
+ */
+static bool pcidriver_irq_acknowledge(pcidriver_privdata_t *privdata)
+{
+    int channel = 0;
 
-#include "common.h"
+    atomic_inc(&(privdata->irq_outstanding[channel]));
+    wake_up_interruptible(&(privdata->irq_queues[channel]));
 
-#include "int.h"
+    return true;
+}
 
-/*
- * The ID between IRQ_SOURCE in irq_outstanding and the actual source is arbitrary.
- * Therefore, be careful when communicating with multiple implementations.
+/**
+ *
+ * Handles IRQs. At the moment, this acknowledges the card that this IRQ
+ * was received and then increases the driver's IRQ counter.
+ *
+ * @see pcidriver_irq_acknowledge
+ *
  */
+static irqreturn_t pcidriver_irq_handler(int irq, void *dev_id)
+{
+    pcidriver_privdata_t *privdata = (pcidriver_privdata_t *)dev_id;
 
-/* IRQ_SOURCES */
-#define ABB_IRQ_CH0 	        0
-#define ABB_IRQ_CH1 	        1
-#define ABB_IRQ_IG 	        2
-
-/* See ABB user’s guide, register definitions (3.1) */
-#define ABB_INT_ENABLE 	        (0x0010 >> 2)
-#define ABB_INT_STAT 	        (0x0008 >> 2)
+    if (!pcidriver_irq_acknowledge(privdata))
+        return IRQ_NONE;
 
-#define ABB_INT_CH1_TIMEOUT     (1 << 4)
-#define ABB_INT_CH0_TIMEOUT     (1 << 5)
-#define ABB_INT_IG  	        (1 << 2)
-#define ABB_INT_CH0 	        (1 << 1) /* downstream */
-#define ABB_INT_CH1 	        (1)     /* upstream */
+    privdata->irq_count++;
+    return IRQ_HANDLED;
+}
 
-#define ABB_CH0_CTRL  	        (108 >> 2)
-#define ABB_CH1_CTRL  	        (72 >> 2)
-#define ABB_CH_RESET 	        (0x0201000A)
-#define ABB_IG_CTRL 	        (0x0080 >> 2)
-#define ABB_IG_ACK 	        (0x00F0)
 
 /**
  *
@@ -167,7 +143,7 @@ int pcidriver_probe_irq(pcidriver_privdata_t *privdata)
         privdata->msi_mode = 1;
 
     /* register interrupt handler */
-    if ((err = request_irq(privdata->pdev->irq, pcidriver_irq_handler, MODNAME, privdata)) != 0) {
+    if ((err = request_irq(privdata->pdev->irq, pcidriver_irq_handler, IRQF_SHARED, MODNAME, privdata)) != 0) {
         mod_info("Error registering the interrupt handler. Disabling interrupts for this device\n");
         return 0;
     }
@@ -215,44 +191,3 @@ void pcidriver_irq_unmap_bars(pcidriver_privdata_t *privdata)
     }
 }
 
-/**
- *
- * Acknowledges the receival of an interrupt to the card.
- *
- * @returns true if the card was acknowledget
- * @returns false if the interrupt was not for one of our cards
- *
- * @see check_acknowlegde_channel
- *
- */
-static bool pcidriver_irq_acknowledge(pcidriver_privdata_t *privdata)
-{
-    int channel = 0;
-//	volatile unsigned int *bar;
-//	bar = privdata->bars_kmapped[0];
-//	mod_info_dbg("interrupt registers. ISR: %x, IER: %x\n", bar[ABB_INT_STAT], bar[ABB_INT_ENABLE]);
-
-    atomic_inc(&(privdata->irq_outstanding[channel]));
-    wake_up_interruptible(&(privdata->irq_queues[channel]));
-
-    return true;
-}
-
-/**
- *
- * Handles IRQs. At the moment, this acknowledges the card that this IRQ
- * was received and then increases the driver's IRQ counter.
- *
- * @see pcidriver_irq_acknowledge
- *
- */
-IRQ_HANDLER_FUNC(pcidriver_irq_handler)
-{
-    pcidriver_privdata_t *privdata = (pcidriver_privdata_t *)dev_id;
-
-    if (!pcidriver_irq_acknowledge(privdata))
-        return IRQ_NONE;
-
-    privdata->irq_count++;
-    return IRQ_HANDLED;
-}

+ 1 - 2
driver/int.h

@@ -4,6 +4,5 @@
 int pcidriver_probe_irq(pcidriver_privdata_t *privdata);
 void pcidriver_remove_irq(pcidriver_privdata_t *privdata);
 void pcidriver_irq_unmap_bars(pcidriver_privdata_t *privdata);
-IRQ_HANDLER_FUNC(pcidriver_irq_handler);
 
-#endif
+#endif /* _PCIDRIVER_INT_H */

+ 5 - 20
driver/ioctl.c

@@ -32,13 +32,7 @@
 
 #include "../pcilib/version.h"
 
-#include "config.h" 			/* Configuration for the driver */
-#include "compat.h" 			/* Compatibility functions/definitions */
-#include "pciDriver.h" 			/* External interface for the driver */
-#include "common.h" 			/* Internal definitions for all parts */
-#include "kmem.h" 			/* Internal definitions for kernel memory */
-#include "umem.h" 			/* Internal definitions for user space memory */
-#include "ioctl.h"			/* Internal definitions for the ioctl part */
+#include "base.h"
 
 /** Declares a variable of the given type with the given name and copies it from userspace */
 #define READ_FROM_USER(type, name) \
@@ -87,12 +81,7 @@ static int ioctl_mmap_area(pcidriver_privdata_t *privdata, unsigned long arg)
 }
 
 /**
- *
  * Reads/writes a byte/word/dword of the device's PCI config.
- *
- * @see pcidriver_pci_read
- * @see pcidriver_pci_write
- *
  */
 static int ioctl_pci_config_read_write(pcidriver_privdata_t *privdata, unsigned int cmd, unsigned long arg)
 {
@@ -103,7 +92,7 @@ static int ioctl_pci_config_read_write(pcidriver_privdata_t *privdata, unsigned
     READ_FROM_USER(pci_cfg_cmd, pci_cmd);
 
     if (cmd == PCIDRIVER_IOC_PCI_CFG_RD) {
-        switch (pci_cmd.size) {
+      switch (pci_cmd.size) {
         case PCIDRIVER_PCI_CFG_SZ_BYTE:
             ret = pci_read_config_byte( privdata->pdev, pci_cmd.addr, &(pci_cmd.val.byte) );
             break;
@@ -115,9 +104,9 @@ static int ioctl_pci_config_read_write(pcidriver_privdata_t *privdata, unsigned
             break;
         default:
             return -EINVAL;		/* Wrong size setting */
-        }
+      }
     } else {
-        switch (pci_cmd.size) {
+      switch (pci_cmd.size) {
         case PCIDRIVER_PCI_CFG_SZ_BYTE:
             ret = pci_write_config_byte( privdata->pdev, pci_cmd.addr, pci_cmd.val.byte );
             break;
@@ -130,7 +119,7 @@ static int ioctl_pci_config_read_write(pcidriver_privdata_t *privdata, unsigned
         default:
             return -EINVAL;		/* Wrong size setting */
             break;
-        }
+      }
     }
 
     WRITE_TO_USER(pci_cfg_cmd, pci_cmd);
@@ -140,11 +129,7 @@ static int ioctl_pci_config_read_write(pcidriver_privdata_t *privdata, unsigned
 }
 
 /**
- *
  * Gets the PCI information for the device.
- *
- * @see pcidriver_pci_info
- *
  */
 static int ioctl_pci_info(pcidriver_privdata_t *privdata, unsigned long arg)
 {

+ 178 - 1
driver/ioctl.h

@@ -1 +1,178 @@
-long pcidriver_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+#ifndef _PCIDRIVER_IOCTL_H_
+#define _PCIDRIVER_IOCTL_H_
+
+#include <linux/ioctl.h>
+
+#define PCIDRIVER_INTERFACE_VERSION     2                               /**< Driver API version, only the pcilib with the same driver interface version is allowed */
+
+/* Possible values for ioctl commands */
+
+/* PCI mmap areas */
+#define	PCIDRIVER_BAR0			0
+#define	PCIDRIVER_BAR1			1
+#define	PCIDRIVER_BAR2			2
+#define	PCIDRIVER_BAR3			3
+#define	PCIDRIVER_BAR4			4
+#define	PCIDRIVER_BAR5			5
+
+/* mmap mode of the device */
+#define PCIDRIVER_MMAP_PCI		0
+#define PCIDRIVER_MMAP_KMEM 		1
+
+/* Direction of a DMA operation */
+#define PCIDRIVER_DMA_BIDIRECTIONAL	0
+#define	PCIDRIVER_DMA_TODEVICE		1 // PCILIB_KMEM_SYNC_TODEVICE
+#define PCIDRIVER_DMA_FROMDEVICE	2 // PCILIB_KMEM_SYNC_FROMDEVICE
+
+/* Possible sizes in a PCI command */
+#define PCIDRIVER_PCI_CFG_SZ_BYTE	1
+#define PCIDRIVER_PCI_CFG_SZ_WORD	2
+#define PCIDRIVER_PCI_CFG_SZ_DWORD	3
+
+/* Possible types of SG lists */
+#define PCIDRIVER_SG_NONMERGED 		0
+#define PCIDRIVER_SG_MERGED 		1
+
+#define KMEM_REF_HW 		        0x80000000			/**< Special reference to indicate hardware access */
+#define KMEM_REF_COUNT		        0x0FFFFFFF			/**< Mask of reference counter (mmap/munmap), couting in mmaped memory pages */
+
+#define KMEM_MODE_REUSABLE	        0x80000000			/**< Indicates reusable buffer */
+#define KMEM_MODE_EXCLUSIVE	        0x40000000			/**< Only a single process is allowed to mmap the buffer */
+#define KMEM_MODE_PERSISTENT	        0x20000000			/**< Persistent mode instructs kmem_free to preserve buffer in memory */
+#define KMEM_MODE_COUNT		        0x0FFFFFFF			/**< Mask of reuse counter (alloc/free) */
+
+#define KMEM_FLAG_REUSE 		PCILIB_KMEM_FLAG_REUSE		/**< Try to reuse existing buffer with the same use & item */
+#define KMEM_FLAG_EXCLUSIVE 		PCILIB_KMEM_FLAG_EXCLUSIVE	/**< Allow only a single application accessing a specified use & item */
+#define KMEM_FLAG_PERSISTENT		PCILIB_KMEM_FLAG_PERSISTENT	/**< Sets persistent mode */
+#define KMEM_FLAG_HW			PCILIB_KMEM_FLAG_HARDWARE	/**< The buffer may be accessed by hardware, the hardware access will not occur any more if passed to _free function */
+#define KMEM_FLAG_FORCE			PCILIB_KMEM_FLAG_FORCE		/**< Force memory cleanup even if references are present */
+#define KMEM_FLAG_MASS			PCILIB_KMEM_FLAG_MASS		/**< Apply to all buffers of selected use */
+#define KMEM_FLAG_TRY			PCILIB_KMEM_FLAG_TRY		/**< Do not allocate buffers, try to reuse and fail if not possible */
+
+#define KMEM_FLAG_REUSED 		PCILIB_KMEM_FLAG_REUSE		/**< Indicates if buffer with specified use & item was already allocated and reused */
+#define KMEM_FLAG_REUSED_PERSISTENT 	PCILIB_KMEM_FLAG_PERSISTENT	/**< Indicates that reused buffer was persistent before the call */
+#define KMEM_FLAG_REUSED_HW 		PCILIB_KMEM_FLAG_HARDWARE	/**< Indicates that reused buffer had a HW reference before the call */
+
+/* Types */
+
+typedef struct {
+    unsigned long version;						/**< pcilib version */
+    unsigned long interface;						/**< driver interface version */
+    unsigned long ioctls;						/**< number of supporterd ioctls */
+    unsigned long reserved[5];						/**< reserved for the future use */
+} pcilib_driver_version_t;
+
+typedef struct {
+    int iommu;								/**< Specifies if IOMMU is enabled or disabled */
+    int mps;								/**< PCIe maximum payload size */
+    int readrq;								/**< PCIe read request size */
+    unsigned long dma_mask;						/**< DMA mask */
+} pcilib_device_state_t;
+
+typedef struct {
+    unsigned short vendor_id;
+    unsigned short device_id;
+    unsigned short bus;
+    unsigned short slot;
+    unsigned short func;
+    unsigned short devfn;
+    unsigned char interrupt_pin;
+    unsigned char interrupt_line;
+    unsigned int irq;
+    unsigned long bar_start[6];
+    unsigned long bar_length[6];
+    unsigned long bar_flags[6];
+} pcilib_board_info_t;
+
+typedef struct {
+    unsigned long type;
+    unsigned long pa;
+    unsigned long ba;
+    unsigned long size;
+    unsigned long align;
+    unsigned long use;
+    unsigned long item;
+    int flags;
+    int handle_id;
+} kmem_handle_t;
+
+typedef struct {
+    unsigned long addr;
+    unsigned long size;
+} umem_sgentry_t;
+
+typedef struct {
+    int handle_id;
+    int type;
+    int nents;
+    umem_sgentry_t *sg;
+} umem_sglist_t;
+
+typedef struct {
+    unsigned long vma;
+    unsigned long size;
+    int handle_id;
+    int dir;
+} umem_handle_t;
+
+typedef struct {
+    kmem_handle_t handle;
+    int dir;
+} kmem_sync_t;
+
+typedef struct {
+    unsigned long count;
+    unsigned long timeout;	// microseconds
+    unsigned int source;
+} interrupt_wait_t;
+
+typedef struct {
+    int size;
+    int addr;
+    union {
+        unsigned char byte;
+        unsigned short word;
+        unsigned int dword; 	/* not strict C, but if not can have problems */
+    } val;
+} pci_cfg_cmd;
+
+/* ioctl interface */
+/* See documentation for a detailed usage explanation */
+
+/*
+ * one of the problems of ioctl, is that requires a type definition.
+ * This type is only 8-bits wide, and half-documented in
+ * <linux-src>/Documentation/ioctl-number.txt.
+ * previous SHL -> 'S' definition, conflicts with several devices,
+ * so I changed it to be pci -> 'p', in the range 0xA0-BF
+ */
+#define PCIDRIVER_IOC_MAGIC 'p'
+#define PCIDRIVER_IOC_BASE  0xA0
+
+#define PCIDRIVER_IOC_MMAP_MODE		_IO(   PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 0 )
+#define PCIDRIVER_IOC_MMAP_AREA		_IO(   PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 1 )
+#define PCIDRIVER_IOC_KMEM_ALLOC	_IOWR( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 2, kmem_handle_t * )
+#define PCIDRIVER_IOC_KMEM_FREE		_IOW ( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 3, kmem_handle_t * )
+#define PCIDRIVER_IOC_KMEM_SYNC		_IOWR( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 4, kmem_sync_t * )
+#define PCIDRIVER_IOC_UMEM_SGMAP	_IOWR( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 5, umem_handle_t * )
+#define PCIDRIVER_IOC_UMEM_SGUNMAP	_IOW(  PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 6, umem_handle_t * )
+#define PCIDRIVER_IOC_UMEM_SGGET	_IOWR( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 7, umem_sglist_t * )
+#define PCIDRIVER_IOC_UMEM_SYNC		_IOW(  PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 8, umem_handle_t * )
+#define PCIDRIVER_IOC_WAITI		_IO(   PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 9 )
+
+/* And now, the methods to access the PCI configuration area */
+#define PCIDRIVER_IOC_PCI_CFG_RD  	_IOWR(  PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 10, pci_cfg_cmd * )
+#define PCIDRIVER_IOC_PCI_CFG_WR  	_IOWR(  PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 11, pci_cfg_cmd * )
+#define PCIDRIVER_IOC_PCI_INFO    	_IOWR(  PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 12, pcilib_board_info_t * )
+
+/* Clear interrupt queues */
+#define PCIDRIVER_IOC_CLEAR_IOQ		_IO(   PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 13 )
+
+#define PCIDRIVER_IOC_VERSION		_IOR(  PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 14, pcilib_driver_version_t * )
+#define PCIDRIVER_IOC_DEVICE_STATE	_IOR(  PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 15, pcilib_device_state_t * )
+#define PCIDRIVER_IOC_DMA_MASK		_IO(   PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 16)
+#define PCIDRIVER_IOC_MPS		_IO(   PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 17)
+
+#define PCIDRIVER_IOC_MAX 17
+
+#endif /* _PCIDRIVER_IOCTL_H */

+ 3 - 8
driver/kmem.c

@@ -17,12 +17,7 @@
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 
-#include "config.h"			/* compile-time configuration */
-#include "compat.h"			/* compatibility definitions for older linux */
-#include "pciDriver.h"			/* external interface for the driver */
-#include "common.h"			/* internal definitions for all parts */
-#include "kmem.h"			/* prototypes for kernel memory */
-#include "sysfs.h"			/* prototypes for sysfs */
+#include "base.h"
 
 
 /**
@@ -628,9 +623,9 @@ int pcidriver_mmap_kmem(pcidriver_privdata_t *privdata, struct vm_area_struct *v
                  page_to_pfn(virt_to_page((void*)kmem_entry->cpua)));
 
     if ((kmem_entry->type&PCILIB_KMEM_TYPE_MASK) == PCILIB_KMEM_TYPE_REGION) {
-        ret = remap_pfn_range_compat(vma, vma->vm_start, kmem_entry->dma_handle, (vma_size < kmem_entry->size)?vma_size:kmem_entry->size, vma->vm_page_prot);
+        ret = remap_pfn_range(vma, vma->vm_start, (kmem_entry->dma_handle >> PAGE_SHIFT), (vma_size < kmem_entry->size)?vma_size:kmem_entry->size, vma->vm_page_prot);
     } else {
-        ret = remap_pfn_range_cpua_compat(vma, vma->vm_start, kmem_entry->cpua, (vma_size < kmem_entry->size)?vma_size:kmem_entry->size, vma->vm_page_prot);
+        ret = remap_pfn_range(vma, vma->vm_start, page_to_pfn(virt_to_page((void*)(kmem_entry->cpua))), (vma_size < kmem_entry->size)?vma_size:kmem_entry->size, vma->vm_page_prot);
     }
 
     if (ret) {

+ 36 - 0
driver/kmem.h

@@ -1,3 +1,35 @@
+#ifndef _PCIDRIVER_KMEM_H
+#define _PCIDRIVER_KMEM_H
+
+#include <linux/sysfs.h>
+
+#include "../pcilib/kmem.h"
+#include "ioctl.h"
+
+/* Define an entry in the kmem list (this list is per device) */
+/* This list keeps references to the allocated kernel buffers */
+typedef struct {
+    int id;
+    enum dma_data_direction direction;
+
+    struct list_head list;
+    dma_addr_t dma_handle;
+    unsigned long cpua;
+    unsigned long size;
+    unsigned long type;
+    unsigned long align;
+
+    unsigned long use;
+    unsigned long item;
+
+    spinlock_t lock;
+    unsigned long mode;
+    unsigned long refs;
+
+    struct device_attribute sysfs_attr;	/* initialized when adding the entry */
+} pcidriver_kmem_entry_t;
+
+
 int pcidriver_kmem_alloc( pcidriver_privdata_t *privdata, kmem_handle_t *kmem_handle );
 int pcidriver_kmem_free(  pcidriver_privdata_t *privdata, kmem_handle_t *kmem_handle );
 int pcidriver_kmem_sync_entry( pcidriver_privdata_t *privdata, pcidriver_kmem_entry_t *kmem_entry, int direction );
@@ -7,3 +39,7 @@ pcidriver_kmem_entry_t *pcidriver_kmem_find_entry( pcidriver_privdata_t *privdat
 pcidriver_kmem_entry_t *pcidriver_kmem_find_entry_id( pcidriver_privdata_t *privdata, int id );
 pcidriver_kmem_entry_t *pcidriver_kmem_find_entry_use(pcidriver_privdata_t *privdata, unsigned long use, unsigned long item);
 int pcidriver_kmem_free_entry( pcidriver_privdata_t *privdata, pcidriver_kmem_entry_t *kmem_entry );
+
+int pcidriver_mmap_kmem( pcidriver_privdata_t *privdata, struct vm_area_struct *vmap );
+
+#endif /* _PCIDRIVER_KMEM_H */

+ 0 - 191
driver/pciDriver.h

@@ -1,191 +0,0 @@
-#ifndef PCIDRIVER_H_
-#define PCIDRIVER_H_
-
-
-#include <linux/ioctl.h>
-
-#define PCIDRIVER_INTERFACE_VERSION 2					/**< Driver API version, only the pcilib with the same driver interface version is allowed */
-
-/* Identifies the PCI-E Xilinx ML605 */
-#define PCIE_XILINX_VENDOR_ID 0x10ee
-#define PCIE_ML605_DEVICE_ID 0x6024
-
-/* Identifies the PCI-E IPE Hardware */
-#define PCIE_IPECAMERA_DEVICE_ID 0x6081
-#define PCIE_KAPTURE_DEVICE_ID 0x6028
-
-
-/* Possible values for ioctl commands */
-
-/* PCI mmap areas */
-#define	PCIDRIVER_BAR0			0
-#define	PCIDRIVER_BAR1			1
-#define	PCIDRIVER_BAR2			2
-#define	PCIDRIVER_BAR3			3
-#define	PCIDRIVER_BAR4			4
-#define	PCIDRIVER_BAR5			5
-
-/* mmap mode of the device */
-#define PCIDRIVER_MMAP_PCI		0
-#define PCIDRIVER_MMAP_KMEM 		1
-
-/* Direction of a DMA operation */
-#define PCIDRIVER_DMA_BIDIRECTIONAL 	0
-#define	PCIDRIVER_DMA_TODEVICE		1//PCILIB_KMEM_SYNC_TODEVICE
-#define PCIDRIVER_DMA_FROMDEVICE	2//PCILIB_KMEM_SYNC_FROMDEVICE
-
-/* Possible sizes in a PCI command */
-#define PCIDRIVER_PCI_CFG_SZ_BYTE  	1
-#define PCIDRIVER_PCI_CFG_SZ_WORD  	2
-#define PCIDRIVER_PCI_CFG_SZ_DWORD 	3
-
-/* Possible types of SG lists */
-#define PCIDRIVER_SG_NONMERGED 		0
-#define PCIDRIVER_SG_MERGED 		1
-
-/* Maximum number of interrupt sources */
-#define PCIDRIVER_INT_MAXSOURCES 	16
-
-#define KMEM_REF_HW 		0x80000000				/**< Special reference to indicate hardware access */
-#define KMEM_REF_COUNT		0x0FFFFFFF				/**< Mask of reference counter (mmap/munmap), couting in mmaped memory pages */
-
-#define KMEM_MODE_REUSABLE	0x80000000				/**< Indicates reusable buffer */
-#define KMEM_MODE_EXCLUSIVE	0x40000000				/**< Only a single process is allowed to mmap the buffer */
-#define KMEM_MODE_PERSISTENT	0x20000000				/**< Persistent mode instructs kmem_free to preserve buffer in memory */
-#define KMEM_MODE_COUNT		0x0FFFFFFF				/**< Mask of reuse counter (alloc/free) */
-
-#define KMEM_FLAG_REUSE 		PCILIB_KMEM_FLAG_REUSE		/**< Try to reuse existing buffer with the same use & item */
-#define KMEM_FLAG_EXCLUSIVE 		PCILIB_KMEM_FLAG_EXCLUSIVE	/**< Allow only a single application accessing a specified use & item */
-#define KMEM_FLAG_PERSISTENT		PCILIB_KMEM_FLAG_PERSISTENT	/**< Sets persistent mode */
-#define KMEM_FLAG_HW			PCILIB_KMEM_FLAG_HARDWARE	/**< The buffer may be accessed by hardware, the hardware access will not occur any more if passed to _free function */
-#define KMEM_FLAG_FORCE			PCILIB_KMEM_FLAG_FORCE		/**< Force memory cleanup even if references are present */
-#define KMEM_FLAG_MASS			PCILIB_KMEM_FLAG_MASS		/**< Apply to all buffers of selected use */
-#define KMEM_FLAG_TRY			PCILIB_KMEM_FLAG_TRY		/**< Do not allocate buffers, try to reuse and fail if not possible */
-
-#define KMEM_FLAG_REUSED 		PCILIB_KMEM_FLAG_REUSE		/**< Indicates if buffer with specified use & item was already allocated and reused */
-#define KMEM_FLAG_REUSED_PERSISTENT 	PCILIB_KMEM_FLAG_PERSISTENT	/**< Indicates that reused buffer was persistent before the call */
-#define KMEM_FLAG_REUSED_HW 		PCILIB_KMEM_FLAG_HARDWARE	/**< Indicates that reused buffer had a HW reference before the call */
-
-/* Types */
-
-typedef struct {
-    unsigned long version;				/**< pcilib version */
-    unsigned long interface;				/**< driver interface version */
-    unsigned long ioctls;				/**< number of supporterd ioctls */
-    unsigned long reserved[5];				/**< reserved for the future use */
-} pcilib_driver_version_t;
-
-typedef struct {
-    int iommu;						/**< Specifies if IOMMU is enabled or disabled */
-    int mps;						/**< PCIe maximum payload size */
-    int readrq;						/**< PCIe read request size */
-    unsigned long dma_mask;				/**< DMA mask */
-} pcilib_device_state_t;
-
-typedef struct {
-    unsigned short vendor_id;
-    unsigned short device_id;
-    unsigned short bus;
-    unsigned short slot;
-    unsigned short func;
-    unsigned short devfn;
-    unsigned char interrupt_pin;
-    unsigned char interrupt_line;
-    unsigned int irq;
-    unsigned long bar_start[6];
-    unsigned long bar_length[6];
-    unsigned long bar_flags[6];
-} pcilib_board_info_t;
-
-typedef struct {
-    unsigned long type;
-    unsigned long pa;
-    unsigned long ba;
-    unsigned long size;
-    unsigned long align;
-    unsigned long use;
-    unsigned long item;
-    int flags;
-    int handle_id;
-} kmem_handle_t;
-
-typedef struct {
-    unsigned long addr;
-    unsigned long size;
-} umem_sgentry_t;
-
-typedef struct {
-    int handle_id;
-    int type;
-    int nents;
-    umem_sgentry_t *sg;
-} umem_sglist_t;
-
-typedef struct {
-    unsigned long vma;
-    unsigned long size;
-    int handle_id;
-    int dir;
-} umem_handle_t;
-
-typedef struct {
-    kmem_handle_t handle;
-    int dir;
-} kmem_sync_t;
-
-typedef struct {
-    unsigned long count;
-    unsigned long timeout;	// microseconds
-    unsigned int source;
-} interrupt_wait_t;
-
-typedef struct {
-    int size;
-    int addr;
-    union {
-        unsigned char byte;
-        unsigned short word;
-        unsigned int dword; 	/* not strict C, but if not can have problems */
-    } val;
-} pci_cfg_cmd;
-
-/* ioctl interface */
-/* See documentation for a detailed usage explanation */
-
-/*
- * one of the problems of ioctl, is that requires a type definition.
- * This type is only 8-bits wide, and half-documented in
- * <linux-src>/Documentation/ioctl-number.txt.
- * previous SHL -> 'S' definition, conflicts with several devices,
- * so I changed it to be pci -> 'p', in the range 0xA0-BF
- */
-#define PCIDRIVER_IOC_MAGIC 'p'
-#define PCIDRIVER_IOC_BASE  0xA0
-
-#define PCIDRIVER_IOC_MMAP_MODE		_IO(   PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 0 )
-#define PCIDRIVER_IOC_MMAP_AREA		_IO(   PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 1 )
-#define PCIDRIVER_IOC_KMEM_ALLOC	_IOWR( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 2, kmem_handle_t * )
-#define PCIDRIVER_IOC_KMEM_FREE		_IOW ( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 3, kmem_handle_t * )
-#define PCIDRIVER_IOC_KMEM_SYNC		_IOWR( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 4, kmem_sync_t * )
-#define PCIDRIVER_IOC_UMEM_SGMAP	_IOWR( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 5, umem_handle_t * )
-#define PCIDRIVER_IOC_UMEM_SGUNMAP	_IOW(  PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 6, umem_handle_t * )
-#define PCIDRIVER_IOC_UMEM_SGGET	_IOWR( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 7, umem_sglist_t * )
-#define PCIDRIVER_IOC_UMEM_SYNC		_IOW(  PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 8, umem_handle_t * )
-#define PCIDRIVER_IOC_WAITI		_IO(   PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 9 )
-
-/* And now, the methods to access the PCI configuration area */
-#define PCIDRIVER_IOC_PCI_CFG_RD  	_IOWR(  PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 10, pci_cfg_cmd * )
-#define PCIDRIVER_IOC_PCI_CFG_WR  	_IOWR(  PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 11, pci_cfg_cmd * )
-#define PCIDRIVER_IOC_PCI_INFO    	_IOWR(  PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 12, pcilib_board_info_t * )
-
-/* Clear interrupt queues */
-#define PCIDRIVER_IOC_CLEAR_IOQ		_IO(   PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 13 )
-
-#define PCIDRIVER_IOC_VERSION		_IOR(  PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 14, pcilib_driver_version_t * )
-#define PCIDRIVER_IOC_DEVICE_STATE	_IOR(  PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 15, pcilib_device_state_t * )
-#define PCIDRIVER_IOC_DMA_MASK		_IO(   PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 16)
-#define PCIDRIVER_IOC_MPS		_IO(   PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 17)
-
-#define PCIDRIVER_IOC_MAX 17
-
-#endif

+ 0 - 0
driver/compat.c → driver/pcibus.c


+ 7 - 0
driver/pcibus.h

@@ -0,0 +1,7 @@
+#ifndef _PCIDRIVER_PCIBUS_H
+#define _PCIDRIVER_PCIBUS_H
+
+int pcidriver_pcie_get_mps(struct pci_dev *dev);
+int pcidriver_pcie_set_mps(struct pci_dev *dev, int mps);
+
+#endif /* _PCIDRIVER_PCIBUS_H */

+ 11 - 0
driver/pcidriver.h

@@ -0,0 +1,11 @@
+#ifndef _PCIDRIVER_H
+#define _PCIDRIVER_H
+
+/**
+ * Evaluates if the supplied user-space address is actually BAR mapping.
+ * @param[in] address	- the user-space address
+ * @return		- the hardware address of BAR or 0 if the \p address is not BAR mapping
+ */
+extern unsigned long pcidriver_resolve_bar(unsigned long address);
+
+#endif /* _PCIDRIVER_H */

+ 1 - 5
driver/rdma.c

@@ -9,11 +9,7 @@
 #include <linux/hugetlb.h>
 #include <linux/cdev.h>
 
-#include "config.h"
-#include "compat.h"
-#include "pciDriver.h"
-#include "common.h"
-#include "rdma.h"
+#include "base.h"
 
 static unsigned long pcidriver_follow_pte(struct mm_struct *mm, unsigned long address)
 {

+ 0 - 1
driver/rdma.h

@@ -1,6 +1,5 @@
 #ifndef _PCIDRIVER_RDMA_H
 #define _PCIDRIVER_RDMA_H
 
-extern unsigned long pcidriver_resolve_bar(unsigned long address);
 
 #endif /* _PCIDRIVER_RDMA_H */

+ 149 - 98
driver/sysfs.c

@@ -18,106 +18,32 @@
 #include <linux/pagemap.h>
 #include <linux/kernel.h>
 
-#include "compat.h"
-#include "config.h"
-#include "pciDriver.h"
-#include "common.h"
-#include "umem.h"
-#include "kmem.h"
-#include "sysfs.h"
+#include "base.h"
 
-static SYSFS_GET_FUNCTION(pcidriver_show_kmem_entry);
-static SYSFS_GET_FUNCTION(pcidriver_show_umem_entry);
+#define SYSFS_GET_PRIVDATA dev_get_drvdata(dev)
+#define SYSFS_GET_FUNCTION(name) ssize_t name(struct device *dev, struct device_attribute *attr, char *buf)
+#define SYSFS_SET_FUNCTION(name) ssize_t name(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 
-/**
- *
- * Initializes the sysfs attributes for an kmem/umem-entry
- *
- */
-static int _pcidriver_sysfs_initialize(pcidriver_privdata_t *privdata,
-                                       int id,
-                                       struct class_device_attribute *sysfs_attr,
-                                       const char *fmtstring,
-                                       SYSFS_GET_FUNCTION((*callback)))
-{
-    /* sysfs attributes for kmem buffers don’t make sense before 2.6.13, as
-       we have no mmap support before */
-    char namebuffer[16];
-
-    /* allocate space for the name of the attribute */
-    snprintf(namebuffer, sizeof(namebuffer), fmtstring, id);
-
-    if ((sysfs_attr->attr.name = kstrdup(namebuffer, GFP_KERNEL)) == NULL)
-        return -ENOMEM;
+#define SYSFS_ATTR_NAME(name) (dev_attr_##name)
 
-    sysfs_attr->attr.mode = S_IRUGO;
-    sysfs_attr->show = callback;
-    sysfs_attr->store = NULL;
+#define SYSFS_ATTR_CREATE(name) do { \
+	int err = device_create_file(privdata->class_dev, &SYSFS_ATTR_NAME(name)); \
+	if (err != 0) return err; \
+    } while (0)
 
-    /* name and add attribute */
-    if (class_device_create_file(privdata->class_dev, sysfs_attr) != 0)
-        return -ENXIO; /* Device not configured. Not the really best choice, but hm. */
-
-    return 0;
-}
-
-int pcidriver_sysfs_initialize_kmem(pcidriver_privdata_t *privdata, int id, struct class_device_attribute *sysfs_attr)
-{
-    return _pcidriver_sysfs_initialize(privdata, id, sysfs_attr, "kbuf%d", pcidriver_show_kmem_entry);
-}
-
-int pcidriver_sysfs_initialize_umem(pcidriver_privdata_t *privdata, int id, struct class_device_attribute *sysfs_attr)
-{
-    return _pcidriver_sysfs_initialize(privdata, id, sysfs_attr, "umem%d", pcidriver_show_umem_entry);
-}
-
-/**
- *
- * Removes the file from sysfs and frees the allocated (kstrdup()) memory.
- *
- */
-void pcidriver_sysfs_remove(pcidriver_privdata_t *privdata, struct class_device_attribute *sysfs_attr)
-{
-    class_device_remove_file(privdata->class_dev, sysfs_attr);
-    kfree(sysfs_attr->attr.name);
-}
-
-static SYSFS_GET_FUNCTION(pcidriver_show_kmem_entry)
-{
-    pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
-
-    /* As we can be sure that attr.name contains a filename which we
-     * created (see _pcidriver_sysfs_initialize), we do not need to have
-     * sanity checks but can directly call simple_strtol() */
-    int id = simple_strtol(attr->attr.name + strlen("kbuf"), NULL, 10);
-    pcidriver_kmem_entry_t *entry = pcidriver_kmem_find_entry_id(privdata, id);
-    if (entry) {
-        unsigned long addr = entry->cpua;
-        unsigned long dma_addr = entry->dma_handle;
-
-        if (entry->size >= 16) {
-            pcidriver_kmem_sync_entry(privdata, entry, PCILIB_KMEM_SYNC_FROMDEVICE);
-            return snprintf(buf, PAGE_SIZE, "buffer: %d\naddr: %lx\nhw addr: %llx\nbus addr: %lx\ntype: %lx\nuse: 0x%lx\nitem: %lu\nsize: %lu\nrefs: %lu\nhw ref: %i\nmode: 0x%lx\ndata: %8x %8x %8x %8x\n", id, addr, virt_to_phys((void*)addr), dma_addr, entry->type, entry->use, entry->item, entry->size, entry->refs&KMEM_REF_COUNT, (entry->refs&KMEM_REF_HW)?1:0, entry->mode, *(u32*)(entry->cpua), *(u32*)(entry->cpua + 4),  *(u32*)(entry->cpua + 8), *(u32*)(entry->cpua + 12));
-        } else
-            return snprintf(buf, PAGE_SIZE, "buffer: %d\naddr: %lx\nhw addr: %llx\nbus addr: %lx\ntype: %lx\nuse: 0x%lx\nitem: %lu\nsize: %lu\nrefs: %lu\nhw ref: %i\nmode: 0x%lx\n", id, addr, virt_to_phys((void*)addr), dma_addr, entry->type, entry->use, entry->item, entry->size, entry->refs&KMEM_REF_COUNT, (entry->refs&KMEM_REF_HW)?1:0, entry->mode);
-    } else
-        return snprintf(buf, PAGE_SIZE, "I am in the kmem_entry show function for buffer %d\n", id);
-}
-
-static SYSFS_GET_FUNCTION(pcidriver_show_umem_entry)
-{
-    return 0;
-}
+#define SYSFS_ATTR_REMOVE(name) do { \
+	device_remove_file(privdata->class_dev, &SYSFS_ATTR_NAME(name)); \
+    } while (0)
 
 #ifdef ENABLE_IRQ
-SYSFS_GET_FUNCTION(pcidriver_show_irq_count)
+static SYSFS_GET_FUNCTION(pcidriver_show_irq_count)
 {
     pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
 
     return snprintf(buf, PAGE_SIZE, "%d\n", privdata->irq_count);
 }
 
-SYSFS_GET_FUNCTION(pcidriver_show_irq_queues)
+static SYSFS_GET_FUNCTION(pcidriver_show_irq_queues)
 {
     pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
     int i, offset;
@@ -131,14 +57,14 @@ SYSFS_GET_FUNCTION(pcidriver_show_irq_queues)
 }
 #endif
 
-SYSFS_GET_FUNCTION(pcidriver_show_mmap_mode)
+static SYSFS_GET_FUNCTION(pcidriver_show_mmap_mode)
 {
     pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
 
     return snprintf(buf, PAGE_SIZE, "%d\n", privdata->mmap_mode);
 }
 
-SYSFS_SET_FUNCTION(pcidriver_store_mmap_mode)
+static SYSFS_SET_FUNCTION(pcidriver_store_mmap_mode)
 {
     pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
     int mode = -1;
@@ -151,14 +77,14 @@ SYSFS_SET_FUNCTION(pcidriver_store_mmap_mode)
     return strlen(buf);
 }
 
-SYSFS_GET_FUNCTION(pcidriver_show_mmap_area)
+static SYSFS_GET_FUNCTION(pcidriver_show_mmap_area)
 {
     pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
 
     return snprintf(buf, PAGE_SIZE, "%d\n", privdata->mmap_area);
 }
 
-SYSFS_SET_FUNCTION(pcidriver_store_mmap_area)
+static SYSFS_SET_FUNCTION(pcidriver_store_mmap_area)
 {
     pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
     int temp = -1;
@@ -171,14 +97,14 @@ SYSFS_SET_FUNCTION(pcidriver_store_mmap_area)
     return strlen(buf);
 }
 
-SYSFS_GET_FUNCTION(pcidriver_show_kmem_count)
+static SYSFS_GET_FUNCTION(pcidriver_show_kmem_count)
 {
     pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
 
     return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&(privdata->kmem_count)));
 }
 
-SYSFS_SET_FUNCTION(pcidriver_store_kmem_alloc)
+static SYSFS_SET_FUNCTION(pcidriver_store_kmem_alloc)
 {
     pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
     kmem_handle_t kmem_handle;
@@ -190,7 +116,7 @@ SYSFS_SET_FUNCTION(pcidriver_store_kmem_alloc)
     return strlen(buf);
 }
 
-SYSFS_SET_FUNCTION(pcidriver_store_kmem_free)
+static SYSFS_SET_FUNCTION(pcidriver_store_kmem_free)
 {
     pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
     unsigned int id;
@@ -209,7 +135,7 @@ err:
     return strlen(buf);
 }
 
-SYSFS_GET_FUNCTION(pcidriver_show_kbuffers)
+static SYSFS_GET_FUNCTION(pcidriver_show_kbuffers)
 {
     pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
     int offset = 0;
@@ -238,7 +164,7 @@ SYSFS_GET_FUNCTION(pcidriver_show_kbuffers)
     return (offset > PAGE_SIZE ? PAGE_SIZE : offset+1);
 }
 
-SYSFS_GET_FUNCTION(pcidriver_show_umappings)
+static SYSFS_GET_FUNCTION(pcidriver_show_umappings)
 {
     int offset = 0;
     pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
@@ -268,7 +194,7 @@ SYSFS_GET_FUNCTION(pcidriver_show_umappings)
     return (offset > PAGE_SIZE ? PAGE_SIZE : offset+1);
 }
 
-SYSFS_SET_FUNCTION(pcidriver_store_umem_unmap)
+static SYSFS_SET_FUNCTION(pcidriver_store_umem_unmap)
 {
     pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
     pcidriver_umem_entry_t *umem_entry;
@@ -285,3 +211,128 @@ SYSFS_SET_FUNCTION(pcidriver_store_umem_unmap)
 err:
     return strlen(buf);
 }
+
+static SYSFS_GET_FUNCTION(pcidriver_show_kmem_entry)
+{
+    pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+
+    /* As we can be sure that attr.name contains a filename which we
+     * created (see _pcidriver_sysfs_initialize), we do not need to have
+     * sanity checks but can directly call simple_strtol() */
+    int id = simple_strtol(attr->attr.name + strlen("kbuf"), NULL, 10);
+    pcidriver_kmem_entry_t *entry = pcidriver_kmem_find_entry_id(privdata, id);
+    if (entry) {
+        unsigned long addr = entry->cpua;
+        unsigned long dma_addr = entry->dma_handle;
+
+        if (entry->size >= 16) {
+            pcidriver_kmem_sync_entry(privdata, entry, PCILIB_KMEM_SYNC_FROMDEVICE);
+            return snprintf(buf, PAGE_SIZE, "buffer: %d\naddr: %lx\nhw addr: %llx\nbus addr: %lx\ntype: %lx\nuse: 0x%lx\nitem: %lu\nsize: %lu\nrefs: %lu\nhw ref: %i\nmode: 0x%lx\ndata: %8x %8x %8x %8x\n", id, addr, virt_to_phys((void*)addr), dma_addr, entry->type, entry->use, entry->item, entry->size, entry->refs&KMEM_REF_COUNT, (entry->refs&KMEM_REF_HW)?1:0, entry->mode, *(u32*)(entry->cpua), *(u32*)(entry->cpua + 4),  *(u32*)(entry->cpua + 8), *(u32*)(entry->cpua + 12));
+        } else
+            return snprintf(buf, PAGE_SIZE, "buffer: %d\naddr: %lx\nhw addr: %llx\nbus addr: %lx\ntype: %lx\nuse: 0x%lx\nitem: %lu\nsize: %lu\nrefs: %lu\nhw ref: %i\nmode: 0x%lx\n", id, addr, virt_to_phys((void*)addr), dma_addr, entry->type, entry->use, entry->item, entry->size, entry->refs&KMEM_REF_COUNT, (entry->refs&KMEM_REF_HW)?1:0, entry->mode);
+    } else
+        return snprintf(buf, PAGE_SIZE, "I am in the kmem_entry show function for buffer %d\n", id);
+}
+
+static SYSFS_GET_FUNCTION(pcidriver_show_umem_entry)
+{
+    return 0;
+}
+
+
+#ifdef ENABLE_IRQ
+static DEVICE_ATTR(irq_count, S_IRUGO, pcidriver_show_irq_count, NULL);
+static DEVICE_ATTR(irq_queues, S_IRUGO, pcidriver_show_irq_queues, NULL);
+#endif
+
+static DEVICE_ATTR(mmap_mode, 0664, pcidriver_show_mmap_mode, pcidriver_store_mmap_mode);
+static DEVICE_ATTR(mmap_area, 0664, pcidriver_show_mmap_area, pcidriver_store_mmap_area);
+static DEVICE_ATTR(kmem_count, 0444, pcidriver_show_kmem_count, NULL);
+static DEVICE_ATTR(kbuffers, 0444, pcidriver_show_kbuffers, NULL);
+static DEVICE_ATTR(kmem_alloc, 0220, NULL, pcidriver_store_kmem_alloc);
+static DEVICE_ATTR(kmem_free, 0220, NULL, pcidriver_store_kmem_free);
+static DEVICE_ATTR(umappings, 0444, pcidriver_show_umappings, NULL);
+static DEVICE_ATTR(umem_unmap, 0220, NULL, pcidriver_store_umem_unmap);
+
+int pcidriver_create_sysfs_attributes(pcidriver_privdata_t *privdata) {
+#ifdef ENABLE_IRQ
+    SYSFS_ATTR_CREATE(irq_count);
+    SYSFS_ATTR_CREATE(irq_queues);
+#endif
+
+    SYSFS_ATTR_CREATE(mmap_mode);
+    SYSFS_ATTR_CREATE(mmap_area);
+    SYSFS_ATTR_CREATE(kmem_count);
+    SYSFS_ATTR_CREATE(kmem_alloc);
+    SYSFS_ATTR_CREATE(kmem_free);
+    SYSFS_ATTR_CREATE(kbuffers);
+    SYSFS_ATTR_CREATE(umappings);
+    SYSFS_ATTR_CREATE(umem_unmap);
+
+    return 0;
+}
+
+void pcidriver_remove_sysfs_attributes(pcidriver_privdata_t *privdata) {
+#ifdef ENABLE_IRQ
+    SYSFS_ATTR_REMOVE(irq_count);
+    SYSFS_ATTR_REMOVE(irq_queues);
+#endif
+
+    SYSFS_ATTR_REMOVE(mmap_mode);
+    SYSFS_ATTR_REMOVE(mmap_area);
+    SYSFS_ATTR_REMOVE(kmem_count);
+    SYSFS_ATTR_REMOVE(kmem_alloc);
+    SYSFS_ATTR_REMOVE(kmem_free);
+    SYSFS_ATTR_REMOVE(kbuffers);
+    SYSFS_ATTR_REMOVE(umappings);
+    SYSFS_ATTR_REMOVE(umem_unmap);
+}
+
+/**
+ *
+ * Removes the file from sysfs and frees the allocated (kstrdup()) memory.
+ *
+ */
+void pcidriver_sysfs_remove(pcidriver_privdata_t *privdata, struct device_attribute *sysfs_attr)
+{
+    device_remove_file(privdata->class_dev, sysfs_attr);
+    kfree(sysfs_attr->attr.name);
+}
+
+/**
+ *
+ * Initializes the sysfs attributes for an kmem/umem-entry
+ *
+ */
+static int _pcidriver_sysfs_initialize(pcidriver_privdata_t *privdata, int id, struct device_attribute *sysfs_attr, const char *fmtstring, SYSFS_GET_FUNCTION((*callback)))
+{
+    /* sysfs attributes for kmem buffers don’t make sense before 2.6.13, as
+       we have no mmap support before */
+    char namebuffer[16];
+
+    /* allocate space for the name of the attribute */
+    snprintf(namebuffer, sizeof(namebuffer), fmtstring, id);
+
+    if ((sysfs_attr->attr.name = kstrdup(namebuffer, GFP_KERNEL)) == NULL)
+        return -ENOMEM;
+
+    sysfs_attr->attr.mode = S_IRUGO;
+    sysfs_attr->show = callback;
+    sysfs_attr->store = NULL;
+
+    /* name and add attribute */
+    if (device_create_file(privdata->class_dev, sysfs_attr) != 0)
+        return -ENXIO; /* Device not configured. Not the really best choice, but hm. */
+
+    return 0;
+}
+
+int pcidriver_sysfs_initialize_kmem(pcidriver_privdata_t *privdata, int id, struct device_attribute *sysfs_attr)
+{
+    return _pcidriver_sysfs_initialize(privdata, id, sysfs_attr, "kbuf%d", pcidriver_show_kmem_entry);
+}
+
+int pcidriver_sysfs_initialize_umem(pcidriver_privdata_t *privdata, int id, struct device_attribute *sysfs_attr)
+{
+    return _pcidriver_sysfs_initialize(privdata, id, sysfs_attr, "umem%d", pcidriver_show_umem_entry);
+}

+ 11 - 19
driver/sysfs.h

@@ -1,23 +1,15 @@
 #ifndef _PCIDRIVER_SYSFS_H
 #define _PCIDRIVER_SYSFS_H
-int pcidriver_sysfs_initialize_kmem(pcidriver_privdata_t *privdata, int id, struct class_device_attribute *sysfs_attr);
-int pcidriver_sysfs_initialize_umem(pcidriver_privdata_t *privdata, int id, struct class_device_attribute *sysfs_attr);
-void pcidriver_sysfs_remove(pcidriver_privdata_t *privdata, struct class_device_attribute *sysfs_attr);
 
-#ifdef ENABLE_IRQ
-SYSFS_GET_FUNCTION(pcidriver_show_irq_count);
-SYSFS_GET_FUNCTION(pcidriver_show_irq_queues);
-#endif
+#include <linux/sysfs.h>
 
-/* prototypes for sysfs operations */
-SYSFS_GET_FUNCTION(pcidriver_show_mmap_mode);
-SYSFS_SET_FUNCTION(pcidriver_store_mmap_mode);
-SYSFS_GET_FUNCTION(pcidriver_show_mmap_area);
-SYSFS_SET_FUNCTION(pcidriver_store_mmap_area);
-SYSFS_GET_FUNCTION(pcidriver_show_kmem_count);
-SYSFS_GET_FUNCTION(pcidriver_show_kbuffers);
-SYSFS_SET_FUNCTION(pcidriver_store_kmem_alloc);
-SYSFS_SET_FUNCTION(pcidriver_store_kmem_free);
-SYSFS_GET_FUNCTION(pcidriver_show_umappings);
-SYSFS_SET_FUNCTION(pcidriver_store_umem_unmap);
-#endif
+#include "dev.h"
+
+int pcidriver_create_sysfs_attributes(pcidriver_privdata_t *privdata);
+void pcidriver_remove_sysfs_attributes(pcidriver_privdata_t *privdata);
+
+int pcidriver_sysfs_initialize_kmem(pcidriver_privdata_t *privdata, int id, struct device_attribute *sysfs_attr);
+int pcidriver_sysfs_initialize_umem(pcidriver_privdata_t *privdata, int id, struct device_attribute *sysfs_attr);
+void pcidriver_sysfs_remove(pcidriver_privdata_t *privdata, struct device_attribute *sysfs_attr);
+
+#endif /* _PCIDRIVER_SYSFS_H */

+ 5 - 10
driver/umem.c

@@ -18,12 +18,7 @@
 #include <linux/pagemap.h>
 #include <linux/sched.h>
 
-#include "config.h"			/* compile-time configuration */
-#include "compat.h"			/* compatibility definitions for older linux */
-#include "pciDriver.h"			/* external interface for the driver */
-#include "common.h"		/* internal definitions for all parts */
-#include "umem.h"		/* prototypes for kernel memory */
-#include "sysfs.h"		/* prototypes for sysfs */
+#include "base.h"
 
 /**
  *
@@ -109,7 +104,7 @@ int pcidriver_umem_sgmap(pcidriver_privdata_t *privdata, umem_handle_t *umem_han
     /* Lock the pages, then populate the SG list with the pages */
     /* page0 is different */
     if ( !PageReserved(pages[0]) )
-        compat_lock_page(pages[0]);
+        __set_page_locked(pages[0]);
 
     offset = (umem_handle->vma & ~PAGE_MASK);
     length = (umem_handle->size > (PAGE_SIZE-offset) ? (PAGE_SIZE-offset) : umem_handle->size);
@@ -120,7 +115,7 @@ int pcidriver_umem_sgmap(pcidriver_privdata_t *privdata, umem_handle_t *umem_han
     for(i=1; i<nr_pages; i++) {
         /* Lock page first */
         if ( !PageReserved(pages[i]) )
-            compat_lock_page(pages[i]);
+            __set_page_locked(pages[i]);
 
         /* Populate the list */
         sg_set_page(&sg[i], pages[i], ((count > PAGE_SIZE) ? PAGE_SIZE : count), 0);
@@ -169,7 +164,7 @@ umem_sgmap_unmap:
     if (nr_pages > 0) {
         for(i=0; i<nr_pages; i++) {
             if (PageLocked(pages[i]))
-                compat_unlock_page(pages[i]);
+                __clear_page_locked(pages[i]);
             if (!PageReserved(pages[i]))
                 set_page_dirty(pages[i]);
             page_cache_release(pages[i]);
@@ -201,7 +196,7 @@ int pcidriver_umem_sgunmap(pcidriver_privdata_t *privdata, pcidriver_umem_entry_
             /* Mark pages as Dirty and unlock it */
             if ( !PageReserved( umem_entry->pages[i] )) {
                 SetPageDirty( umem_entry->pages[i] );
-                compat_unlock_page(umem_entry->pages[i]);
+                __clear_page_locked(umem_entry->pages[i]);
             }
             /* and release it from the cache */
             page_cache_release( umem_entry->pages[i] );

+ 21 - 0
driver/umem.h

@@ -1,5 +1,26 @@
+#ifndef _PCIDRIVER_UMEM_H
+#define _PCIDRIVER_UMEM_H
+
+#include <linux/sysfs.h>
+
+#include "ioctl.h"
+
+/* Define an entry in the umem list (this list is per device) */
+/* This list keeps references to the SG lists for each mapped userspace region */
+typedef struct {
+    int id;
+    struct list_head list;
+    unsigned int nr_pages;		/* number of pages for this user memeory area */
+    struct page **pages;		/* list of pointers to the pages */
+    unsigned int nents;			/* actual entries in the scatter/gatter list (NOT nents for the map function, but the result) */
+    struct scatterlist *sg;		/* list of sg entries */
+    struct device_attribute sysfs_attr;	/* initialized when adding the entry */
+} pcidriver_umem_entry_t;
+
 int pcidriver_umem_sgmap( pcidriver_privdata_t *privdata, umem_handle_t *umem_handle );
 int pcidriver_umem_sgunmap( pcidriver_privdata_t *privdata, pcidriver_umem_entry_t *umem_entry );
 int pcidriver_umem_sgget( pcidriver_privdata_t *privdata, umem_sglist_t *umem_sglist );
 int pcidriver_umem_sync( pcidriver_privdata_t *privdata, umem_handle_t *umem_handle );
 pcidriver_umem_entry_t *pcidriver_umem_find_entry_id( pcidriver_privdata_t *privdata, int id );
+
+#endif /* _PCIDRIVER_UMEM_H */

+ 1 - 1
pcilib/pci.h

@@ -18,7 +18,7 @@
 #include <uthash.h>
 
 #include "linux-3.10.h"
-#include "driver/pciDriver.h"
+#include "driver/ioctl.h"
 
 #include "timing.h"
 #include "cpu.h"

+ 3 - 3
pcilib/pcilib.h

@@ -1,5 +1,5 @@
-#ifndef _PCITOOL_PCILIB_H
-#define _PCITOOL_PCILIB_H
+#ifndef _PCILIB_H
+#define _PCILIB_H
 
 #include <sys/time.h>
 #include <stddef.h>
@@ -1331,4 +1331,4 @@ int pcilib_convert_value_type(pcilib_t *ctx, pcilib_value_t *val, pcilib_value_t
 }
 #endif
 
-#endif /* _PCITOOL_PCILIB_H */
+#endif /* _PCILIB_H */