Переглянути джерело

Merge with http://ufo.kit.edu/ufo/log/csa/pcitool 369 revision

Vasilii Chernov 8 роки тому
батько
коміт
ee16e47966

+ 19 - 23
CMakeLists.txt

@@ -1,6 +1,6 @@
 project(pcitool)
 
-set(PCILIB_VERSION "0.2.6")
+set(PCILIB_VERSION "0.2.7")
 set(PCILIB_ABI_VERSION "2")
 
 cmake_minimum_required(VERSION 2.8)
@@ -38,29 +38,27 @@ find_package(PkgConfig REQUIRED)
 find_package(Threads REQUIRED)
 
 if (NOT DISABLE_PYTHON)
-    set(PYTHON_VERSION 2.7 CACHE PATH "python version")
-    
-    find_package(PythonLibs ${PYTHON_VERSION} REQUIRED)
+    set(PYTHON_VERSION 2.7 CACHE STRING "python version")
+
     find_package(PythonInterp ${PYTHON_VERSION} REQUIRED)
-    
+    find_package(PythonLibs ${PYTHON_VERSION_STRING} EXACT REQUIRED)
+
     find_package(SWIG REQUIRED)
     if (NOT PYTHON_VERSION_STRING VERSION_EQUAL PYTHONLIBS_VERSION_STRING)
-	 message (FATAL_ERROR "Version mismatch between python interpreter and libraries")
+	message (FATAL_ERROR "Version mismatch between python interpreter and libraries")
     endif (NOT PYTHON_VERSION_STRING VERSION_EQUAL PYTHONLIBS_VERSION_STRING)
 
 #    execute_process (COMMAND ${PYTHON_EXECUTABLE} -c "from sysconfig import get_path; print get_path('platlib')" OUTPUT_VARIABLE PYTHON_INSTALL_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)
     
-    execute_process (COMMAND ${PYTHON_EXECUTABLE} -c "import site; print(site.PREFIXES[-1])" OUTPUT_VARIABLE PYTHON_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE)
+    execute_process (COMMAND ${PYTHON_EXECUTABLE} -c "import site; print (site.PREFIXES[-1])" OUTPUT_VARIABLE PYTHON_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE)
     file (TO_CMAKE_PATH "${PYTHON_PREFIX}" PYTHON_PREFIX)
-    execute_process (COMMAND ${PYTHON_EXECUTABLE} -c "import site; print(site.getsitepackages()[0])" OUTPUT_VARIABLE PYTHON_SITE_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)
+    execute_process (COMMAND ${PYTHON_EXECUTABLE} -c "import site; print (site.getsitepackages()[0])" OUTPUT_VARIABLE PYTHON_SITE_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)
     file (TO_CMAKE_PATH "${PYTHON_SITE_DIR}" PYTHON_SITE_DIR)
 
     string (REGEX REPLACE "^${PYTHON_PREFIX}/" "${CMAKE_INSTALL_PREFIX}/" PYTHON_SITE_DIR "${PYTHON_SITE_DIR}")
-    
     set(PYTHON_INSTALL_DIR ${PYTHON_SITE_DIR} CACHE PATH "path to install python module")
-    message(${PYTHON_INSTALL_DIR})
+
     set(HAVE_PYTHON TRUE)
-    include(FindPythonInterp)
 endif (NOT DISABLE_PYTHON)
 
 set(EXTRA_SYSTEM_LIBS -lrt)
@@ -132,18 +130,16 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/pcilib/version.h.in ${CMAKE_CURRENT_B
 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/docs/Doxyfile)
 
 if (NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
-   file(COPY ${CMAKE_SOURCE_DIR}/xml DESTINATION ${CMAKE_BINARY_DIR})
-   file(COPY ${CMAKE_SOURCE_DIR}/pyserver DESTINATION ${CMAKE_BINARY_DIR})
-   file(COPY ${CMAKE_SOURCE_DIR}/pci
-   DESTINATION ${CMAKE_BINARY_DIR}
-   FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
-   )
-   file(COPY ${CMAKE_SOURCE_DIR}/run
-   DESTINATION ${CMAKE_BINARY_DIR}
-   FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
-   )
-   
-   configure_file(${CMAKE_SOURCE_DIR}/pcilib/version.h.in ${CMAKE_SOURCE_DIR}/pcilib/version.h)
+    file(COPY ${CMAKE_SOURCE_DIR}/xml DESTINATION ${CMAKE_BINARY_DIR})
+    file(COPY ${CMAKE_SOURCE_DIR}/pyserver DESTINATION ${CMAKE_BINARY_DIR})
+    file(COPY ${CMAKE_SOURCE_DIR}/pci
+	 DESTINATION ${CMAKE_BINARY_DIR}
+	 FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
+    )
+    file(COPY ${CMAKE_SOURCE_DIR}/run
+	 DESTINATION ${CMAKE_BINARY_DIR}
+	 FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
+    )
 endif(NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
 
 install(FILES 

+ 8 - 6
apps/test_multithread.c

@@ -1,8 +1,10 @@
 #include <stdio.h>
 #include <pthread.h>
-#include "pcilib.h"
 #include <stdlib.h>
 
+#include "pcilib.h"
+#include "pcilib/error.h"
+
 const char* prop = "/registers/fpga/reg1";
 char* reg;
 int stop = 0;
@@ -18,14 +20,14 @@ void *get_prop(void *arg)
         err = pcilib_get_property(ctx, prop, &val);
         if(err)
         {
-            printf("err pcilib_read_register\n");
+            pcilib_error("Error in pcilib_read_register");
             return NULL;
         }
         long value = pcilib_get_value_as_int(ctx, &val, &err);
         pcilib_clean_value(ctx, &val);
         if(err)
         {
-            printf("err pcilib_get_value_as_int\n");
+            pcilib_error("Error in pcilib_get_value_as_int");
             return NULL;
         }
         printf("reg = %li\n", value);
@@ -47,20 +49,20 @@ void *read_reg(void *arg)
 
         if(err)
         {
-            printf("err pcilib_read_register\n");
+            pcilib_error("Error in pcilib_read_register");
             return NULL;
         }
         err = pcilib_set_value_from_register_value(ctx, &val, reg_val);
         if(err)
         {
-            printf("err pcilib_set_value_from_register_value\n");
+            pcilib_error("Error in pcilib_set_value_from_register_value");
             return NULL;
         }
         long value = pcilib_get_value_as_int(ctx, &val, &err);
         pcilib_clean_value(ctx, &val);
         if(err)
         {
-            printf("err pcilib_get_value_as_int\n");
+            pcilib_error("Error in pcilib_get_value_as_int");
             return NULL;
         }
         printf("reg = %li\n", value);

+ 19 - 7
driver/Makefile

@@ -1,10 +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)/kernel/extra
+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)/..
@@ -53,15 +55,25 @@ install:
 	@mkdir -p $(INSTALLDIR)
 	@echo "INSTALL $(INSTALLDIR)/pciDriver.ko"
 	@install -m 755 pciDriver.ko $(INSTALLDIR)
-	@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 $(INSTALLDIR)/pciDriver.symvers"
+	@install -m 644 Module.symvers $(INSTALLDIR)/pciDriver.symvers
+	@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"
 	@rm -f $(INSTALLDIR)/pciDriver.ko
-	@echo "UNINSTALL /usr/include/pciDriver/driver/pciDriver.h"
-	@rm -rf /usr/include/pciDriver/driver
+	@rm -f $(MAININSTALLDIR)/pciDriver.ko
+	@rm -f $(INSTALLDIR)/pciDriver.symvers
+	@rm -f $(MAININSTALLDIR)/pciDriver.symvers
+	@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

+ 217 - 603
driver/base.c

@@ -1,148 +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.
- *
- * This is a full rewrite of the pciDriver.
- * New default is to support kernel 2.6, using kernel 2.6 APIs.
- *
- */
-
-/*
- * Change History:
- *
- * $Log: not supported by cvs2svn $
- * Revision 1.13  2008-05-30 11:38:15  marcus
- * Added patches for kernel 2.6.24
- *
- * Revision 1.12  2008-01-24 14:21:36  marcus
- * Added a CLEAR_INTERRUPT_QUEUE ioctl.
- * Added a sysfs attribute to show the outstanding IRQ queues.
- *
- * Revision 1.11  2008-01-24 12:53:11  marcus
- * Corrected wait_event condition in waiti_ioctl. Improved the loop too.
- *
- * Revision 1.10  2008-01-14 10:39:39  marcus
- * Set some messages as debug instead of normal.
- *
- * Revision 1.9  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.8  2007-07-17 13:15:55  marcus
- * Removed Tasklets.
- * Using newest map for the ABB interrupts.
- *
- * Revision 1.7  2007-07-06 15:56:04  marcus
- * Change default status for OLD_REGISTERS to not defined.
- *
- * Revision 1.6  2007-07-05 15:29:59  marcus
- * Corrected issue with the bar mapping for interrupt handling.
- * Added support up to kernel 2.6.20
- *
- * Revision 1.5  2007-05-29 07:50:18  marcus
- * Split code into 2 files. May get merged in the future again....
- *
- * Revision 1.4  2007/03/01 17:47:34  marcus
- * Fixed bug when the kernel memory was less than one page, it was not locked properly, recalling an old mapping issue in this case.
- *
- * Revision 1.3  2007/03/01 17:01:22  marcus
- * comment fix (again).
- *
- * Revision 1.2  2007/03/01 17:00:25  marcus
- * Changed some comment in the log.
- *
- * 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.
- *
- * From pciDriver.c:
- * Revision 1.11  2006/12/11 16:15:43  marcus
- * Fixed kernel buffer mmapping, and driver crash when application crashes.
- * Buffer memory is now marked reserved during allocation, and mmaped with
- * remap_xx_range.
- *
- * Revision 1.10  2006/11/21 09:50:49  marcus
- * Added PROGRAPE4 vendor/device IDs.
- *
- * Revision 1.9  2006/11/17 18:47:36  marcus
- * Removed MERGE_SGENTRIES flag, now it is selected at runtime with 'type'.
- * Removed noncached in non-prefetchable areas, to allow the use of MTRRs.
- *
- * Revision 1.8  2006/11/17 16:41:21  marcus
- * Added slot number to the PCI info IOctl.
- *
- * Revision 1.7  2006/11/13 12:30:34  marcus
- * Added a IOctl call, to confiure the interrupt response. (testing pending).
- * Basic interrupts are now supported, using a Tasklet and Completions.
- *
- * Revision 1.6  2006/11/08 21:30:02  marcus
- * Added changes after compile tests in kernel 2.6.16
- *
- * Revision 1.5  2006/10/31 07:57:38  marcus
- * Improved the pfn calculation in nopage(), to deal with some possible border
- * conditions. It was really no issue, because they are normally page-aligned
- * anyway, but to be on the safe side.
- *
- * Revision 1.4  2006/10/30 19:37:40  marcus
- * Solved bug on kernel memory not mapping properly.
- *
- * Revision 1.3  2006/10/18 11:19:20  marcus
- * Added kernel 2.6.8 support based on comments from Joern Adamczewski (GSI).
- *
- * Revision 1.2  2006/10/18 11:04:15  marcus
- * Bus Master is only activated when we detect a specific board.
- *
- * Revision 1.1  2006/10/10 14:46:51  marcus
- * Initial commit of the new pciDriver for kernel 2.6
- *
- * Revision 1.9  2006/10/05 11:30:46  marcus
- * Prerelease. Added bus and devfn to pciInfo for compatibility.
- *
- * Revision 1.8  2006/09/25 16:51:07  marcus
- * Added PCI config IOctls, and implemented basic mmap functions.
- *
- * Revision 1.7  2006/09/20 11:12:41  marcus
- * Added Merge SG entries
- *
- * Revision 1.6  2006/09/19 17:22:18  marcus
- * backup commit.
- *
- * Revision 1.5  2006/09/18 17:13:11  marcus
- * backup commit.
- *
- * Revision 1.4  2006/09/15 15:44:41  marcus
- * backup commit.
- *
- * Revision 1.3  2006/08/15 11:40:02  marcus
- * backup commit.
- *
- * Revision 1.2  2006/08/12 18:28:42  marcus
- * Sync with the laptop
- *
- * Revision 1.1  2006/08/11 15:30:46  marcus
- * Sync with the laptop
- *
- */
-
-#include <linux/version.h>
-
-/* Check macros and kernel version first */
-#ifndef KERNEL_VERSION
-#error "No KERNEL_VERSION macro! Stopping."
-#endif
-
-#ifndef LINUX_VERSION_CODE
-#error "No LINUX_VERSION_CODE macro! Stopping."
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8)
-#error "This driver has been tested only for Kernel 2.6.8 or above."
-#endif
-
-/* Required includes */
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/types.h>
@@ -165,302 +20,197 @@
 #include <linux/wait.h>
 
 #include "../pcilib/version.h"
-
-/* Configuration for the driver (what should be compiled in, module name, etc...) */
-#include "config.h"
-
-/* Compatibility functions/definitions (provides functions which are not available on older kernels) */
-#include "compat.h"
-
-/* External interface for the driver */
-#include "pciDriver.h"
-
-/* Internal definitions for all parts (prototypes, data, macros) */
-#include "common.h"
-
-/* Internal definitions for the base part */
-#include "base.h"
-
-/* Internal definitions of the IRQ handling part */
-#include "int.h"
-
-/* Internal definitions for kernel memory */
-#include "kmem.h"
-
-/* Internal definitions for user space memory */
-#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_privdata = 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);
 
-	/* 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);
-	}
+/* Hold the allocated major & minor numbers */
+static dev_t pcidriver_devt;
 
-	return 0;
+/* Number of devices allocated */
+static atomic_t pcidriver_deviceCount;
 
-init_pcireg_fail:
-	class_destroy(pcidriver_class);
-init_class_fail:
-	unregister_chrdev_region(pcidriver_devt, MAXDEVICES);
-init_alloc_fail:
-	return err;
-}
+/* Private data for probed devices */
+static pcidriver_privdata_t* pcidriver_privdata[MAXDEVICES];
 
-/**
- *
- * 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 */
 
-	unregister_chrdev_region(pcidriver_devt, MAXDEVICES);
+pcidriver_privdata_t *pcidriver_get_privdata(int devid) {
+    if (devid >= MAXDEVICES)
+        return NULL;
 
-	if (pcidriver_class != NULL)
-		class_destroy(pcidriver_class);
-
-	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)
 {
-	int err = 0;
-	int devno;
-	pcidriver_privdata_t *privdata;
-	int devid;
-
-	/* At the moment there is no difference between these boards here, other than
-	 * printing a different message in the log.
-	 *
-	 * However, there is some difference in the interrupt handling functions.
-	 */
+    int err = 0;
+    int devno;
+    pcidriver_privdata_t *privdata;
+    int devid;
+
+    /* At the moment there is no difference between these boards here, other than
+     * printing a different message in the log.
+     *
+     * However, there is some difference in the interrupt handling functions.
+     */
 #ifdef PCIDRIVER_DUMMY_DEVICE
-	mod_info("Emulated device\n");
+    mod_info("Emulated device\n");
 #else /* PCIDRIVER_DUMMY_DEVICE */
-	if (id->vendor == PCIE_XILINX_VENDOR_ID) {
-	    if (id->device == PCIE_ML605_DEVICE_ID) {
-		mod_info("Found ML605 board at %s\n", dev_name(&pdev->dev));
-	    } else if (id->device == PCIE_IPECAMERA_DEVICE_ID) {
-		mod_info("Found IPE Camera at %s\n", dev_name(&pdev->dev));
-	    } else if (id->device == PCIE_KAPTURE_DEVICE_ID) {
-		mod_info("Found KAPTURE board at %s\n", dev_name(&pdev->dev));
-	    } else {
-		mod_info("Found unknown Xilinx device (%x) at %s\n", id->device, dev_name(&pdev->dev));
-	    }
-	} else {
-	    /* It is something else */
-	    mod_info("Found unknown board (%x:%x) at %s\n", id->vendor, id->device, dev_name(&pdev->dev));
-	}
-
-	/* Enable the device */
-	if ((err = pci_enable_device(pdev)) != 0) {
-	    mod_info("Couldn't enable device\n");
-	    goto probe_pcien_fail;
-	}
-	
-	/* Bus master & dma */
-	pci_set_master(pdev);
-	    
-	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-	if (err < 0) {
-	    printk(KERN_ERR "pci_set_dma_mask failed\n");
-	    goto probe_dma_fail;
-	}
-
-	/* Set Memory-Write-Invalidate support */
-	if ((err = pci_set_mwi(pdev)) != 0)
-	    mod_info("MWI not supported. Continue without enabling MWI.\n");
-#endif /* PCIDRIVER_DUMMY_DEVICE */
+    if (id->vendor == PCIE_XILINX_VENDOR_ID) {
+        if (id->device == PCIE_ML605_DEVICE_ID) {
+            mod_info("Found ML605 board at %s\n", dev_name(&pdev->dev));
+        } else if (id->device == PCIE_IPECAMERA_DEVICE_ID) {
+            mod_info("Found IPE Camera at %s\n", dev_name(&pdev->dev));
+        } else if (id->device == PCIE_KAPTURE_DEVICE_ID) {
+            mod_info("Found KAPTURE board at %s\n", dev_name(&pdev->dev));
+        } else {
+            mod_info("Found unknown Xilinx device (%x) at %s\n", id->device, dev_name(&pdev->dev));
+        }
+    } else {
+        /* It is something else */
+        mod_info("Found unknown board (%x:%x) at %s\n", id->vendor, id->device, dev_name(&pdev->dev));
+    }
 
-	/* Get / Increment the device id */
-	devid = atomic_inc_return(&pcidriver_deviceCount) - 1;
-	if (devid >= MAXDEVICES) {
-		mod_info("Maximum number of devices reached! Increase MAXDEVICES.\n");
-		err = -ENOMSG;
-		goto probe_maxdevices_fail;
-	}
-
-	/* Allocate and initialize the private data for this device */
-	if ((privdata = kcalloc(1, sizeof(*privdata), GFP_KERNEL)) == NULL) {
-		err = -ENOMEM;
-		goto probe_nomem;
-	}
-
-	INIT_LIST_HEAD(&(privdata->kmem_list));
-	spin_lock_init(&(privdata->kmemlist_lock));
-	atomic_set(&privdata->kmem_count, 0);
-	
-	INIT_LIST_HEAD(&(privdata->umem_list));
-	spin_lock_init(&(privdata->umemlist_lock));
-	atomic_set(&privdata->umem_count, 0);
+    /* Enable the device */
+    if ((err = pci_enable_device(pdev)) != 0) {
+        mod_info("Couldn't enable device\n");
+        goto probe_pcien_fail;
+    }
 
-#ifdef PCIDRIVER_DUMMY_DEVICE
-	pcidriver_privdata = privdata;
-#else /* PCIDRIVER_DUMMY_DEVICE */
-	pci_set_drvdata(pdev, privdata);
-	privdata->pdev = pdev;
+    /* Bus master & dma */
+    pci_set_master(pdev);
+
+    err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+    if (err < 0) {
+        printk(KERN_ERR "pci_set_dma_mask failed\n");
+        goto probe_dma_fail;
+    }
+
+    /* Set Memory-Write-Invalidate support */
+    if ((err = pci_set_mwi(pdev)) != 0)
+        mod_info("MWI not supported. Continue without enabling MWI.\n");
 #endif /* PCIDRIVER_DUMMY_DEVICE */
 
-	/* Device add to sysfs */
-	devno = MKDEV(MAJOR(pcidriver_devt), MINOR(pcidriver_devt) + devid);
-	privdata->devno = devno;
+    /* Get / Increment the device id */
+    devid = atomic_inc_return(&pcidriver_deviceCount) - 1;
+    if (devid >= MAXDEVICES) {
+        mod_info("Maximum number of devices reached! Increase MAXDEVICES.\n");
+        err = -ENOMSG;
+        goto probe_maxdevices_fail;
+    }
+
+    /* Allocate and initialize the private data for this device */
+    if ((privdata = kcalloc(1, sizeof(*privdata), GFP_KERNEL)) == NULL) {
+        err = -ENOMEM;
+        goto probe_nomem;
+    }
+
+    privdata->devid = devid;
+
+    INIT_LIST_HEAD(&(privdata->kmem_list));
+    spin_lock_init(&(privdata->kmemlist_lock));
+    atomic_set(&privdata->kmem_count, 0);
+
+    INIT_LIST_HEAD(&(privdata->umem_list));
+    spin_lock_init(&(privdata->umemlist_lock));
+    atomic_set(&privdata->umem_count, 0);
 
-	/* 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);
+    pcidriver_dummydata = privdata;
 #else /* PCIDRIVER_DUMMY_DEVICE */
-	privdata->class_dev = class_device_create(pcidriver_class, NULL, devno, &(pdev->dev), NODENAMEFMT, MINOR(pcidriver_devt) + devid, privdata);
+    pci_set_drvdata(pdev, privdata);
+    privdata->pdev = pdev;
 #endif /* PCIDRIVER_DUMMY_DEVICE */
-	class_set_devdata( privdata->class_dev, privdata );
-	mod_info("Device /dev/%s%d added\n",NODENAME,MINOR(pcidriver_devt) + devid);
+
+    /* Device add to sysfs */
+    devno = MKDEV(MAJOR(pcidriver_devt), MINOR(pcidriver_devt) + devid);
+    privdata->devno = devno;
+
+    /* FIXME: some error checking missing here */
+    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
-	/* Setup mmaped BARs into kernel space */
-	if ((err = pcidriver_probe_irq(privdata)) != 0)
-		goto probe_irq_probe_fail;
+    /* Setup mmaped BARs into kernel space */
+    if ((err = pcidriver_probe_irq(privdata)) != 0)
+        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
-
-	/* Register character device */
-	cdev_init( &(privdata->cdev), &pcidriver_fops );
-	privdata->cdev.owner = THIS_MODULE;
-	privdata->cdev.ops = &pcidriver_fops;
-	err = cdev_add( &privdata->cdev, devno, 1 );
-	if (err) {
-		mod_info( "Couldn't add character device.\n" );
-		goto probe_cdevadd_fail;
-	}
-
-	return 0;
+    /* TODO: correct errorhandling. ewww. must remove the files in reversed order :-( */
+    if (pcidriver_create_sysfs_attributes(privdata) != 0)
+	goto probe_device_create_fail;
+
+    /* Register character device */
+    cdev_init(&(privdata->cdev), pcidriver_get_fops());
+    privdata->cdev.owner = THIS_MODULE;
+    privdata->cdev.ops = pcidriver_get_fops();
+    err = cdev_add( &privdata->cdev, devno, 1 );
+    if (err) {
+        mod_info( "Couldn't add character device.\n" );
+        goto probe_cdevadd_fail;
+    }
+
+    pcidriver_privdata[devid] = privdata;
+
+    return 0;
 
 probe_device_create_fail:
 probe_cdevadd_fail:
 #ifndef PCIDRIVER_DUMMY_DEVICE
 probe_irq_probe_fail:
-	pcidriver_irq_unmap_bars(privdata);
+    pcidriver_irq_unmap_bars(privdata);
 #endif /* ! PCIDRIVER_DUMMY_DEVICE */
-	kfree(privdata);
+    kfree(privdata);
 probe_nomem:
-	atomic_dec(&pcidriver_deviceCount);
+    atomic_dec(&pcidriver_deviceCount);
 probe_maxdevices_fail:
 #ifndef PCIDRIVER_DUMMY_DEVICE
 probe_dma_fail:
-	pci_disable_device(pdev);
+    pci_disable_device(pdev);
 probe_pcien_fail:
 #endif /* ! PCIDRIVER_DUMMY_DEVICE */
- 	return err;
+    return err;
 }
 
 /**
@@ -470,262 +220,126 @@ probe_pcien_fail:
  */
 static void __devexit pcidriver_remove(struct pci_dev *pdev)
 {
-	pcidriver_privdata_t *privdata;
+    pcidriver_privdata_t *privdata;
 
 #ifdef PCIDRIVER_DUMMY_DEVICE
-	privdata = pcidriver_privdata;
-	pcidriver_privdata = NULL;
+    privdata = pcidriver_dummydata;
+    pcidriver_dummydata = NULL;
 #else /* PCIDRIVER_DUMMY_DEVICE */
-	/* Get private data from the device */
-	privdata = pci_get_drvdata(pdev);
+    /* Get private data from the device */
+    privdata = pci_get_drvdata(pdev);
 #endif /* PCIDRIVER_DUMMY_DEVICE */
 
-	/* 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
-
-	/* Free all allocated kmem buffers before leaving */
-	pcidriver_kmem_free_all( privdata );
+    // Theoretically we should lock here and when using...
+    pcidriver_privdata[privdata->devid] = NULL;
+
+    /* Removing sysfs attributes from class device */
+    pcidriver_remove_sysfs_attributes(privdata);
+
+    /* Free all allocated kmem buffers before leaving */
+    pcidriver_kmem_free_all( privdata );
 
 #ifndef PCIDRIVER_DUMMY_DEVICE
 # ifdef ENABLE_IRQ
-	pcidriver_remove_irq(privdata);
+    pcidriver_remove_irq(privdata);
 # endif
 #endif /* ! PCIDRIVER_DUMMY_DEVICE */
 
-	/* Removing Character device */
-	cdev_del(&(privdata->cdev));
+    /* Removing Character device */
+    cdev_del(&(privdata->cdev));
 
-	/* Removing the device from sysfs */
-	class_device_destroy(pcidriver_class, privdata->devno);
+    /* Removing the device from sysfs */
+    device_destroy(pcidriver_class, privdata->devno);
 
-	/* Releasing privdata */
-	kfree(privdata);
+    /* Releasing privdata */
+    kfree(privdata);
 
 #ifdef PCIDRIVER_DUMMY_DEVICE
-	mod_info("Device at " NODENAMEFMT " removed\n", 0);
+    mod_info("Device at " NODENAMEFMT " removed\n", 0);
 #else /* PCIDRIVER_DUMMY_DEVICE */
-	/* Disabling PCI device */
-	pci_disable_device(pdev);
-	mod_info("Device at %s removed\n", dev_name(&pdev->dev));
+    /* Disabling PCI device */
+    pci_disable_device(pdev);
+    mod_info("Device at %s removed\n", dev_name(&pdev->dev));
 #endif /* PCIDRIVER_DUMMY_DEVICE */
 
 }
 
-/*************************************************************************/
-/* 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,
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
-	.ioctl = pcidriver_ioctl,
-#else
-	.unlocked_ioctl = pcidriver_ioctl,
-#endif 
-	.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;
+    int err = 0;
 
-	/* Set the private data area for the file */
-	privdata = container_of( inode->i_cdev, pcidriver_privdata_t, cdev);
-	filp->private_data = privdata;
+    /* Initialize the device count */
+    atomic_set(&pcidriver_deviceCount, 0);
 
-	pcidriver_module_get(privdata);
+    memset(pcidriver_privdata, 0, sizeof(pcidriver_privdata));
 
-	return 0;
-}
+    /* 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);
 
-/**
- *
- * 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;
+    /* Register driver class */
+    pcidriver_class = class_create(THIS_MODULE, NODENAME);
 
-	/* Get the private data area */
-	privdata = filp->private_data;
+    if (IS_ERR(pcidriver_class)) {
+        mod_info("No sysfs support. Module not loaded.\n");
+        goto init_class_fail;
+    }
+
+    /* 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) {
+#else /* PCIDRIVER_DUMMY_DEVICE */
+    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;
+    }
 
-	pcidriver_module_put(privdata);
+    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;
-}
+    return 0;
 
-/**
- *
- * 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) */
-	}
-
-	return ret;
+init_pcireg_fail:
+    class_destroy(pcidriver_class);
+init_class_fail:
+    unregister_chrdev_region(pcidriver_devt, MAXDEVICES);
+init_alloc_fail:
+    return err;
 }
 
-/*************************************************************************/
-/* Internal driver functions */
-int pcidriver_mmap_pci(pcidriver_privdata_t *privdata, struct vm_area_struct *vmap, int bar)
+static void pcidriver_exit(void)
 {
 #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 */
-#ifdef pgprot_noncached
-		vmap->vm_page_prot = pgprot_noncached(vmap->vm_page_prot);
-#endif
-
-		/* 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. */
-#ifdef pgprot_noncached
-/* 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);
-#endif
-
-		/* Map the BAR */
-		ret = remap_pfn_range_compat(
-					vmap,
-					vmap->vm_start,
-					bar_addr,
-					bar_length,
-					vmap->vm_page_prot);
-	}
-
-	if (ret) {
-		mod_info("remap_pfn_range failed\n");
-		return -EAGAIN;
-	}
-
-	return 0;	/* success */
+    pcidriver_remove(NULL);
+#else
+    pci_unregister_driver(&pcidriver_driver);
 #endif /* PCIDRIVER_DUMMY_DEVICE */
+
+    unregister_chrdev_region(pcidriver_devt, MAXDEVICES);
+
+    if (pcidriver_class != NULL)
+        class_destroy(pcidriver_class);
+
+    mod_info("Module unloaded\n");
 }
+
+module_init(pcidriver_init);
+module_exit(pcidriver_exit);

+ 9 - 81
driver/base.h

@@ -1,87 +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;
-
-/* 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 - 108
driver/common.h

@@ -1,108 +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  {
-	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);
-
-/*************************************************************************/
-/* 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 - 26
driver/compat.c

@@ -1,26 +0,0 @@
-#include <linux/pci.h>
-
-int pcidriver_pcie_get_mps(struct pci_dev *dev)
-{
-        u16 ctl;
-
-        pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &ctl);
-
-        return 128 << ((ctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5);
-}
-
-int pcidriver_pcie_set_mps(struct pci_dev *dev, int mps)
-{
-        u16 v;
-
-        if (mps < 128 || mps > 4096 || !is_power_of_2(mps))
-                return -EINVAL;
-
-        v = ffs(mps) - 8;
-        if (v > dev->pcie_mpss)
-                return -EINVAL;
-        v <<= 5;
-
-        return pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL,
-                                                  PCI_EXP_DEVCTL_PAYLOAD, v);
-}

+ 15 - 182
driver/compat.h

@@ -10,198 +10,31 @@
 #ifndef _COMPAT_H
 #define _COMPAT_H
 
-/*
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0)
-# error "Linux 3.0 and latter are supported"
-#endif
-*/
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
-# define __devinit
-# define __devexit
-# define __devinitdata
-#endif
-
-/* dev_name is the wrapper one needs to use to access what was formerly called
- * bus_id in struct device. However, before 2.6.27, direct access was necessary,
- * so we provide our own version. */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
-static inline const char *dev_name(struct device *dev) {
-	return dev->bus_id;
-}
-#endif
-
-/* SetPageLocked disappeared in v2.6.27 */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
-	#define compat_lock_page SetPageLocked
-	#define compat_unlock_page ClearPageLocked
-#else
-	/* in v2.6.28, __set_page_locked and __clear_page_locked was introduced */
-	#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
-		#define compat_lock_page __set_page_locked
-		#define compat_unlock_page __clear_page_locked
-	#else
-		/* However, in v2.6.27 itself, neither of them is there, so
-		 * we need to use our own function fiddling with bits inside
-		 * the page struct :-\ */
-		static inline void compat_lock_page(struct page *page) {
-			__set_bit(PG_locked, &page->flags);
-		}
-
-		static inline void compat_unlock_page(struct page *page) {
-			__clear_bit(PG_locked, &page->flags);
-		}
-	#endif
-#endif
-
-/* Before 2.6.13, simple_class was the standard interface. Nowadays, it's just called class */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)
-
-	#define class_compat class_simple
-
-	/* These functions are redirected to their old corresponding functions */
-	#define class_create(module, name) class_simple_create(module, name)
-	#define class_destroy(type) class_simple_destroy(type)
-	#define class_device_destroy(unused, devno) class_simple_device_remove(devno)
-	#define class_device_create(type, unused, devno, devpointer, nameformat, minor, unused) \
-		class_simple_device_add(type, devno, devpointer, nameformat, minor)
-	#define class_set_devdata(classdev, privdata) classdev->class_data = privdata
-	#define DEVICE_ATTR_COMPAT
-	#define sysfs_attr_def_name(name) class_device_attr_##name
-	#define sysfs_attr_def_pointer privdata->class_dev
-	#define SYSFS_GET_FUNCTION(name) ssize_t name(struct class_device *cls, char *buf)
-	#define SYSFS_SET_FUNCTION(name) ssize_t name(struct class_device *cls, const char *buf, size_t count)
-	#define SYSFS_GET_PRIVDATA (pcidriver_privdata_t*)cls->class_data
-
-#else
-
-/* In 2.6.26, device.h was changed quite significantly. Luckily, it only affected
-   type/function names, for the most part. */
-//#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
-	#define class_device_attribute device_attribute
-	#define CLASS_DEVICE_ATTR DEVICE_ATTR
-	#define class_device device
-	#define class_data dev
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
-	#define class_device_create(type, parent, devno, devpointer, nameformat, minor, privdata) \
-		device_create(type, parent, devno, privdata, nameformat, minor)
-#else
-	#define class_device_create(type, parent, devno, devpointer, nameformat, minor, unused) \
-		device_create(type, parent, devno, nameformat, minor)
-#endif
-	#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)
-
-//#endif
-
-#define class_compat class
-
-#endif
-
-/* The arguments of IRQ handlers have been changed in 2.6.19. It's very likely that
-   int irq will disappear somewhen in the future (current is 2.6.29), too. */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
-	#define IRQ_HANDLER_FUNC(name) irqreturn_t name(int irq, void *dev_id)
-#else
-	#define IRQ_HANDLER_FUNC(name) irqreturn_t name(int irq, void *dev_id, struct pt_regs *regs)
-#endif
-
-/* atomic_inc_return appeared in 2.6.9, at least in CERN scientific linux, provide
-   compatibility wrapper for older kernels */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)
-static int atomic_inc_return(atomic_t *variable) {
-	atomic_inc(variable);
-	return atomic_read(variable);
-}
-#endif
-
-/* sg_set_page is available starting at 2.6.24 */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
-
-#define sg_set_page(sg, set_page, set_length, set_offset) do { \
-	(sg)->page = set_page; \
-	(sg)->length = set_length; \
-	(sg)->offset = set_offset; \
-} while (0)
-
-#endif
-
-/* Before 2.6.20, disable was not an atomic counter, so this check was needed */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
-#define pci_disable_device(pdev) do { \
-	if (pdev->is_enabled) \
-		pci_disable_device(pdev); \
-} while (0)
-#endif
+#include <linux/version.h>
 
-/* Before 2.6.24, scatter/gather lists did not need to be initialized */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
-	#define sg_init_table(sg, nr_pages)
+/* Check macros and kernel version first */
+#ifndef KERNEL_VERSION
+# error "No KERNEL_VERSION macro! Stopping."
 #endif
 
-/* SA_SHIRQ was renamed to IRQF_SHARED in 2.6.24 */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
-	#define request_irq(irq, irq_handler, modname, privdata) request_irq(irq, irq_handler, IRQF_SHARED, modname, privdata)
-#else
-	#define request_irq(irq, irq_handler, modname, privdata) request_irq(irq, irq_handler, SA_SHIRQ, modname, privdata)
+#ifndef LINUX_VERSION_CODE
+# error "No LINUX_VERSION_CODE macro! Stopping."
 #endif
 
-/* In 2.6.13, io_remap_page_range was removed in favor for io_remap_pfn_range which works on
-   more platforms and allows more memory space */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
-#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)
-#else
-#define io_remap_pfn_range_compat(vmap, vm_start, bar_addr, bar_length, vm_page_prot) \
-	io_remap_page_range(vmap, vm_start, bar_addr, bar_length, vm_page_prot)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0)
+# error "Linux 3.2 and latter are supported"
 #endif
 
-/* In 2.6.10, remap_pfn_range was introduced, see io_remap_pfn_range_compat */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
-#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)
-
-#else
-#define remap_pfn_range_compat(vmap, vm_start, bar_addr, bar_length, vm_page_prot) \
-	remap_page_range(vmap, vm_start, bar_addr, bar_length, vm_page_prot)
-
-#define remap_pfn_range_cpua_compat(vmap, vm_start, cpua, size, vm_page_prot) \
-	remap_page_range(vmap, vm_start, virt_to_phys((void*)cpua), size, vm_page_prot)
+/* VM_RESERVED is removed in 3.7-rc1 */
+#ifndef VM_RESERVED
+# define  VM_RESERVED   (VM_DONTEXPAND | VM_DONTDUMP)
 #endif
 
-/**
- * Go over the pages of the kmem buffer, and mark them as reserved.
- * This is needed, otherwise mmaping the kernel memory to user space
- * will fail silently (mmaping /dev/null) when using remap_xx_range.
- */
-static inline void set_pages_reserved_compat(unsigned long cpua, unsigned long size)
-{
-	/* Starting in 2.6.15, the PG_RESERVED bit was removed.
-	   See also http://lwn.net/Articles/161204/ */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
-	struct page *page, *last_page;
-
-	page = virt_to_page(cpua);
-	last_page = virt_to_page(cpua + size - 1);
 
-	for (; page <= last_page; page++)
-               SetPageReserved(page);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
+# define __devinit
+# define __devexit
+# define __devinitdata
 #endif
-}
-
-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 */
+

+ 134 - 199
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 "compat.h"
+#include "base.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)
 
 /**
  *
@@ -92,90 +68,90 @@
  */
 int pcidriver_probe_irq(pcidriver_privdata_t *privdata)
 {
-	unsigned char int_pin, int_line;
-	unsigned long bar_addr, bar_len, bar_flags;
-	int i;
-	int err;
-
-	for (i = 0; i < 6; i++)
-		privdata->bars_kmapped[i] = NULL;
-
-	for (i = 0; i < 6; i++) {
-		bar_addr = pci_resource_start(privdata->pdev, i);
-		bar_len = pci_resource_len(privdata->pdev, i);
-		bar_flags = pci_resource_flags(privdata->pdev, i);
-
-		/* check if it is a valid BAR, skip if not */
-		if ((bar_addr == 0) || (bar_len == 0))
-			continue;
-
-		/* Skip IO regions (map only mem regions) */
-		if (bar_flags & IORESOURCE_IO)
-			continue;
-
-		/* Check if the region is available */
-		if ((err = pci_request_region(privdata->pdev, i, NULL)) != 0) {
-			mod_info( "Failed to request BAR memory region.\n" );
-			return err;
-		}
-
-		/* Map it into kernel space. */
-		/* For x86 this is just a dereference of the pointer, but that is
-		 * not portable. So we need to do the portable way. Thanks Joern!
-		 */
-
-		/* respect the cacheable-bility of the region */
-		if (bar_flags & IORESOURCE_PREFETCH)
-			privdata->bars_kmapped[i] = ioremap(bar_addr, bar_len);
-		else
-			privdata->bars_kmapped[i] = ioremap_nocache(bar_addr, bar_len);
-
-		/* check for error */
-		if (privdata->bars_kmapped[i] == NULL) {
-			mod_info( "Failed to remap BAR%d into kernel space.\n", i );
-			return -EIO;
-		}
-	}
-
-	/* Initialize the interrupt handler for this device */
-	/* Initialize the wait queues */
-	for (i = 0; i < PCIDRIVER_INT_MAXSOURCES; i++) {
-		init_waitqueue_head(&(privdata->irq_queues[i]));
-		atomic_set(&(privdata->irq_outstanding[i]), 0);
-	}
-
-	/* Initialize the irq config */
-	if ((err = pci_read_config_byte(privdata->pdev, PCI_INTERRUPT_PIN, &int_pin)) != 0) {
-		/* continue without interrupts */
-		int_pin = 0;
-		mod_info("Error getting the interrupt pin. Disabling interrupts for this device\n");
-	}
-
-	/* Disable interrupts and activate them if everything can be set up properly */
-	privdata->irq_enabled = 0;
-
-	if (int_pin == 0)
-		return 0;
-
-	if ((err = pci_read_config_byte(privdata->pdev, PCI_INTERRUPT_LINE, &int_line)) != 0) {
-		mod_info("Error getting the interrupt line. Disabling interrupts for this device\n");
-		return 0;
-	}
-
-	/* Enable interrupts using MSI mode */
-	if (!pci_enable_msi(privdata->pdev)) 
-		privdata->msi_mode = 1;
-	
-	/* register interrupt handler */
-	if ((err = request_irq(privdata->pdev->irq, pcidriver_irq_handler, MODNAME, privdata)) != 0) {
-		mod_info("Error registering the interrupt handler. Disabling interrupts for this device\n");
-		return 0;
-	}
-
-	privdata->irq_enabled = 1;
-	mod_info("Registered Interrupt Handler at pin %i, line %i, IRQ %i\n", int_pin, int_line, privdata->pdev->irq );
-
-	return 0;
+    unsigned char int_pin, int_line;
+    unsigned long bar_addr, bar_len, bar_flags;
+    int i;
+    int err;
+
+    for (i = 0; i < 6; i++)
+        privdata->bars_kmapped[i] = NULL;
+
+    for (i = 0; i < 6; i++) {
+        bar_addr = pci_resource_start(privdata->pdev, i);
+        bar_len = pci_resource_len(privdata->pdev, i);
+        bar_flags = pci_resource_flags(privdata->pdev, i);
+
+        /* check if it is a valid BAR, skip if not */
+        if ((bar_addr == 0) || (bar_len == 0))
+            continue;
+
+        /* Skip IO regions (map only mem regions) */
+        if (bar_flags & IORESOURCE_IO)
+            continue;
+
+        /* Check if the region is available */
+        if ((err = pci_request_region(privdata->pdev, i, NULL)) != 0) {
+            mod_info( "Failed to request BAR memory region.\n" );
+            return err;
+        }
+
+        /* Map it into kernel space. */
+        /* For x86 this is just a dereference of the pointer, but that is
+         * not portable. So we need to do the portable way. Thanks Joern!
+         */
+
+        /* respect the cacheable-bility of the region */
+        if (bar_flags & IORESOURCE_PREFETCH)
+            privdata->bars_kmapped[i] = ioremap(bar_addr, bar_len);
+        else
+            privdata->bars_kmapped[i] = ioremap_nocache(bar_addr, bar_len);
+
+        /* check for error */
+        if (privdata->bars_kmapped[i] == NULL) {
+            mod_info( "Failed to remap BAR%d into kernel space.\n", i );
+            return -EIO;
+        }
+    }
+
+    /* Initialize the interrupt handler for this device */
+    /* Initialize the wait queues */
+    for (i = 0; i < PCIDRIVER_INT_MAXSOURCES; i++) {
+        init_waitqueue_head(&(privdata->irq_queues[i]));
+        atomic_set(&(privdata->irq_outstanding[i]), 0);
+    }
+
+    /* Initialize the irq config */
+    if ((err = pci_read_config_byte(privdata->pdev, PCI_INTERRUPT_PIN, &int_pin)) != 0) {
+        /* continue without interrupts */
+        int_pin = 0;
+        mod_info("Error getting the interrupt pin. Disabling interrupts for this device\n");
+    }
+
+    /* Disable interrupts and activate them if everything can be set up properly */
+    privdata->irq_enabled = 0;
+
+    if (int_pin == 0)
+        return 0;
+
+    if ((err = pci_read_config_byte(privdata->pdev, PCI_INTERRUPT_LINE, &int_line)) != 0) {
+        mod_info("Error getting the interrupt line. Disabling interrupts for this device\n");
+        return 0;
+    }
+
+    /* Enable interrupts using MSI mode */
+    if (!pci_enable_msi(privdata->pdev))
+        privdata->msi_mode = 1;
+
+    /* register interrupt handler */
+    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;
+    }
+
+    privdata->irq_enabled = 1;
+    mod_info("Registered Interrupt Handler at pin %i, line %i, IRQ %i\n", int_pin, int_line, privdata->pdev->irq );
+
+    return 0;
 }
 
 /**
@@ -185,16 +161,16 @@ int pcidriver_probe_irq(pcidriver_privdata_t *privdata)
  */
 void pcidriver_remove_irq(pcidriver_privdata_t *privdata)
 {
-	/* Release the IRQ handler */
-	if (privdata->irq_enabled != 0)
-		free_irq(privdata->pdev->irq, privdata);
-	
-	if (privdata->msi_mode) {
-		pci_disable_msi(privdata->pdev);
-		privdata->msi_mode = 0;
-	}
-
-	pcidriver_irq_unmap_bars(privdata);
+    /* Release the IRQ handler */
+    if (privdata->irq_enabled != 0)
+        free_irq(privdata->pdev->irq, privdata);
+
+    if (privdata->msi_mode) {
+        pci_disable_msi(privdata->pdev);
+        privdata->msi_mode = 0;
+    }
+
+    pcidriver_irq_unmap_bars(privdata);
 }
 
 /**
@@ -204,55 +180,14 @@ void pcidriver_remove_irq(pcidriver_privdata_t *privdata)
  */
 void pcidriver_irq_unmap_bars(pcidriver_privdata_t *privdata)
 {
-	int i;
+    int i;
 
-	for (i = 0; i < 6; i++) {
-		if (privdata->bars_kmapped[i] == NULL)
-			continue;
+    for (i = 0; i < 6; i++) {
+        if (privdata->bars_kmapped[i] == NULL)
+            continue;
 
-		iounmap((void*)privdata->bars_kmapped[i]);
-		pci_release_region(privdata->pdev, i);
-	}
-}
-
-/**
- *
- * 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;
+        iounmap((void*)privdata->bars_kmapped[i]);
+        pci_release_region(privdata->pdev, i);
+    }
 }
 
-/**
- *
- * 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 */

+ 255 - 274
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) \
@@ -60,13 +54,13 @@
  */
 static int ioctl_mmap_mode(pcidriver_privdata_t *privdata, unsigned long arg)
 {
-	if ((arg != PCIDRIVER_MMAP_PCI) && (arg != PCIDRIVER_MMAP_KMEM))
-		return -EINVAL;
+    if ((arg != PCIDRIVER_MMAP_PCI) && (arg != PCIDRIVER_MMAP_KMEM))
+        return -EINVAL;
 
-	/* change the mode */
-	privdata->mmap_mode = arg;
+    /* change the mode */
+    privdata->mmap_mode = arg;
 
-	return 0;
+    return 0;
 }
 
 /**
@@ -76,112 +70,103 @@ static int ioctl_mmap_mode(pcidriver_privdata_t *privdata, unsigned long arg)
  */
 static int ioctl_mmap_area(pcidriver_privdata_t *privdata, unsigned long arg)
 {
-	/* validate input */
-	if ((arg < PCIDRIVER_BAR0) || (arg > PCIDRIVER_BAR5))
-		return -EINVAL;
+    /* validate input */
+    if ((arg < PCIDRIVER_BAR0) || (arg > PCIDRIVER_BAR5))
+        return -EINVAL;
 
-	/* change the PCI area to mmap */
-	privdata->mmap_area = arg;
+    /* change the PCI area to mmap */
+    privdata->mmap_area = arg;
 
-	return 0;
+    return 0;
 }
 
 /**
- *
  * 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)
 {
 #ifdef PCIDRIVER_DUMMY_DEVICE
-	return -ENXIO;
+    return -ENXIO;
 #else /* PCIDRIVER_DUMMY_DEVICE */
-	int ret;
-	READ_FROM_USER(pci_cfg_cmd, pci_cmd);
-
-	if (cmd == PCIDRIVER_IOC_PCI_CFG_RD) {
-		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;
-			case PCIDRIVER_PCI_CFG_SZ_WORD:
-				ret = pci_read_config_word( privdata->pdev, pci_cmd.addr, &(pci_cmd.val.word) );
-				break;
-			case PCIDRIVER_PCI_CFG_SZ_DWORD:
-				ret = pci_read_config_dword( privdata->pdev, pci_cmd.addr, &(pci_cmd.val.dword) );
-				break;
-			default:
-				return -EINVAL;		/* Wrong size setting */
-		}
-	} else {
-		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;
-			case PCIDRIVER_PCI_CFG_SZ_WORD:
-				ret = pci_write_config_word( privdata->pdev, pci_cmd.addr, pci_cmd.val.word );
-				break;
-			case PCIDRIVER_PCI_CFG_SZ_DWORD:
-				ret = pci_write_config_dword( privdata->pdev, pci_cmd.addr, pci_cmd.val.dword );
-				break;
-			default:
-				return -EINVAL;		/* Wrong size setting */
-				break;
-		}
-	}
-
-	WRITE_TO_USER(pci_cfg_cmd, pci_cmd);
-
-	return 0;
+    int ret;
+    READ_FROM_USER(pci_cfg_cmd, pci_cmd);
+
+    if (cmd == PCIDRIVER_IOC_PCI_CFG_RD) {
+      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;
+        case PCIDRIVER_PCI_CFG_SZ_WORD:
+            ret = pci_read_config_word( privdata->pdev, pci_cmd.addr, &(pci_cmd.val.word) );
+            break;
+        case PCIDRIVER_PCI_CFG_SZ_DWORD:
+            ret = pci_read_config_dword( privdata->pdev, pci_cmd.addr, &(pci_cmd.val.dword) );
+            break;
+        default:
+            return -EINVAL;		/* Wrong size setting */
+      }
+    } else {
+      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;
+        case PCIDRIVER_PCI_CFG_SZ_WORD:
+            ret = pci_write_config_word( privdata->pdev, pci_cmd.addr, pci_cmd.val.word );
+            break;
+        case PCIDRIVER_PCI_CFG_SZ_DWORD:
+            ret = pci_write_config_dword( privdata->pdev, pci_cmd.addr, pci_cmd.val.dword );
+            break;
+        default:
+            return -EINVAL;		/* Wrong size setting */
+            break;
+      }
+    }
+
+    WRITE_TO_USER(pci_cfg_cmd, pci_cmd);
+
+    return 0;
 #endif /* PCIDRIVER_DUMMY_DEVICE */
 }
 
 /**
- *
  * Gets the PCI information for the device.
- *
- * @see pcidriver_pci_info
- *
  */
 static int ioctl_pci_info(pcidriver_privdata_t *privdata, unsigned long arg)
 {
-	int ret;
+    int ret;
 
 #ifdef PCIDRIVER_DUMMY_DEVICE
-	READ_FROM_USER(pcilib_board_info_t, pci_info);
-	memset(&pci_info, 0, sizeof(pci_info));
-	WRITE_TO_USER(pcilib_board_info_t, pci_info);
+    READ_FROM_USER(pcilib_board_info_t, pci_info);
+    memset(&pci_info, 0, sizeof(pci_info));
+    WRITE_TO_USER(pcilib_board_info_t, pci_info);
 #else /* PCIDRIVER_DUMMY_DEVICE */
-	int bar;
+    int bar;
 
-	READ_FROM_USER(pcilib_board_info_t, pci_info);
+    READ_FROM_USER(pcilib_board_info_t, pci_info);
 
-	pci_info.vendor_id = privdata->pdev->vendor;
-	pci_info.device_id = privdata->pdev->device;
-	pci_info.bus = privdata->pdev->bus->number;
-	pci_info.slot = PCI_SLOT(privdata->pdev->devfn);
-	pci_info.devfn = privdata->pdev->devfn;
-	pci_info.func = PCI_FUNC(privdata->pdev->devfn);
+    pci_info.vendor_id = privdata->pdev->vendor;
+    pci_info.device_id = privdata->pdev->device;
+    pci_info.bus = privdata->pdev->bus->number;
+    pci_info.slot = PCI_SLOT(privdata->pdev->devfn);
+    pci_info.devfn = privdata->pdev->devfn;
+    pci_info.func = PCI_FUNC(privdata->pdev->devfn);
 
-	if ((ret = pci_read_config_byte(privdata->pdev, PCI_INTERRUPT_PIN, &(pci_info.interrupt_pin))) != 0)
-		return ret;
+    if ((ret = pci_read_config_byte(privdata->pdev, PCI_INTERRUPT_PIN, &(pci_info.interrupt_pin))) != 0)
+        return ret;
 
-	if ((ret = pci_read_config_byte(privdata->pdev, PCI_INTERRUPT_LINE, &(pci_info.interrupt_line))) != 0)
-		return ret;
+    if ((ret = pci_read_config_byte(privdata->pdev, PCI_INTERRUPT_LINE, &(pci_info.interrupt_line))) != 0)
+        return ret;
 
-	for (bar = 0; bar < 6; bar++) {
-		pci_info.bar_start[bar] = pci_resource_start(privdata->pdev, bar);
-		pci_info.bar_length[bar] = pci_resource_len(privdata->pdev, bar);
-		pci_info.bar_flags[bar] = pci_resource_flags(privdata->pdev, bar);
-	}
+    for (bar = 0; bar < 6; bar++) {
+        pci_info.bar_start[bar] = pci_resource_start(privdata->pdev, bar);
+        pci_info.bar_length[bar] = pci_resource_len(privdata->pdev, bar);
+        pci_info.bar_flags[bar] = pci_resource_flags(privdata->pdev, bar);
+    }
 
-	WRITE_TO_USER(pcilib_board_info_t, pci_info);
+    WRITE_TO_USER(pcilib_board_info_t, pci_info);
 #endif /* PCIDRIVER_DUMMY_DEVICE */
 
-	return 0;
+    return 0;
 }
 
 /**
@@ -193,13 +178,13 @@ static int ioctl_pci_info(pcidriver_privdata_t *privdata, unsigned long arg)
  */
 static int ioctl_kmem_alloc(pcidriver_privdata_t *privdata, unsigned long arg)
 {
-	int err, ret;
+    int err, ret;
 
-	READ_FROM_USER(kmem_handle_t, khandle);
-	err = pcidriver_kmem_alloc(privdata, &khandle);
-	WRITE_TO_USER(kmem_handle_t, khandle);
+    READ_FROM_USER(kmem_handle_t, khandle);
+    err = pcidriver_kmem_alloc(privdata, &khandle);
+    WRITE_TO_USER(kmem_handle_t, khandle);
 
-	return err;
+    return err;
 }
 
 /**
@@ -211,13 +196,13 @@ static int ioctl_kmem_alloc(pcidriver_privdata_t *privdata, unsigned long arg)
  */
 static int ioctl_kmem_free(pcidriver_privdata_t *privdata, unsigned long arg)
 {
-	int ret;
-	READ_FROM_USER(kmem_handle_t, khandle);
+    int ret;
+    READ_FROM_USER(kmem_handle_t, khandle);
 
-	if ((ret = pcidriver_kmem_free(privdata, &khandle)) != 0)
-		return ret;
+    if ((ret = pcidriver_kmem_free(privdata, &khandle)) != 0)
+        return ret;
 
-	return 0;
+    return 0;
 }
 
 /**
@@ -229,15 +214,15 @@ static int ioctl_kmem_free(pcidriver_privdata_t *privdata, unsigned long arg)
  */
 static int ioctl_kmem_sync(pcidriver_privdata_t *privdata, unsigned long arg)
 {
-	int ret;
-	READ_FROM_USER(kmem_sync_t, ksync);
-
-	if ((ret =  pcidriver_kmem_sync(privdata, &ksync)) != 0)
-	    return ret;
-	
-	WRITE_TO_USER(kmem_sync_t, ksync);
-	
-	return 0;
+    int ret;
+    READ_FROM_USER(kmem_sync_t, ksync);
+
+    if ((ret =  pcidriver_kmem_sync(privdata, &ksync)) != 0)
+        return ret;
+
+    WRITE_TO_USER(kmem_sync_t, ksync);
+
+    return 0;
 }
 
 /*
@@ -249,15 +234,15 @@ static int ioctl_kmem_sync(pcidriver_privdata_t *privdata, unsigned long arg)
  */
 static int ioctl_umem_sgmap(pcidriver_privdata_t *privdata, unsigned long arg)
 {
-	int ret;
-	READ_FROM_USER(umem_handle_t, uhandle);
+    int ret;
+    READ_FROM_USER(umem_handle_t, uhandle);
 
-	if ((ret = pcidriver_umem_sgmap(privdata, &uhandle)) != 0)
-		return ret;
+    if ((ret = pcidriver_umem_sgmap(privdata, &uhandle)) != 0)
+        return ret;
 
-	WRITE_TO_USER(umem_handle_t, uhandle);
+    WRITE_TO_USER(umem_handle_t, uhandle);
 
-	return 0;
+    return 0;
 }
 
 /**
@@ -269,19 +254,19 @@ static int ioctl_umem_sgmap(pcidriver_privdata_t *privdata, unsigned long arg)
  */
 static int ioctl_umem_sgunmap(pcidriver_privdata_t *privdata, unsigned long arg)
 {
-	int ret;
-	pcidriver_umem_entry_t *umem_entry;
-	READ_FROM_USER(umem_handle_t, uhandle);
+    int ret;
+    pcidriver_umem_entry_t *umem_entry;
+    READ_FROM_USER(umem_handle_t, uhandle);
 
-	/* Find the associated umem_entry for this buffer,
-	 * return -EINVAL if the specified handle id is invalid */
-	if ((umem_entry = pcidriver_umem_find_entry_id(privdata, uhandle.handle_id)) == NULL)
-		return -EINVAL;
+    /* Find the associated umem_entry for this buffer,
+     * return -EINVAL if the specified handle id is invalid */
+    if ((umem_entry = pcidriver_umem_find_entry_id(privdata, uhandle.handle_id)) == NULL)
+        return -EINVAL;
 
-	if ((ret = pcidriver_umem_sgunmap(privdata, umem_entry)) != 0)
-		return ret;
+    if ((ret = pcidriver_umem_sgunmap(privdata, umem_entry)) != 0)
+        return ret;
 
-	return 0;
+    return 0;
 }
 
 /**
@@ -293,35 +278,35 @@ static int ioctl_umem_sgunmap(pcidriver_privdata_t *privdata, unsigned long arg)
  */
 static int ioctl_umem_sgget(pcidriver_privdata_t *privdata, unsigned long arg)
 {
-	int ret;
-	READ_FROM_USER(umem_sglist_t, usglist);
+    int ret;
+    READ_FROM_USER(umem_sglist_t, usglist);
 
-	/* The umem_sglist_t has a pointer to the scatter/gather list itself which
-	 * needs to be copied separately. The number of elements is stored in ->nents.
-	 * As the list can get very big, we need to use vmalloc. */
-	if ((usglist.sg = vmalloc(usglist.nents * sizeof(umem_sgentry_t))) == NULL)
-		return -ENOMEM;
+    /* The umem_sglist_t has a pointer to the scatter/gather list itself which
+     * needs to be copied separately. The number of elements is stored in ->nents.
+     * As the list can get very big, we need to use vmalloc. */
+    if ((usglist.sg = vmalloc(usglist.nents * sizeof(umem_sgentry_t))) == NULL)
+        return -ENOMEM;
 
-	/* copy array to kernel structure */
-	ret = copy_from_user(usglist.sg, ((umem_sglist_t *)arg)->sg, (usglist.nents)*sizeof(umem_sgentry_t));
-	if (ret) return -EFAULT;
+    /* copy array to kernel structure */
+    ret = copy_from_user(usglist.sg, ((umem_sglist_t *)arg)->sg, (usglist.nents)*sizeof(umem_sgentry_t));
+    if (ret) return -EFAULT;
 
-	if ((ret = pcidriver_umem_sgget(privdata, &usglist)) != 0)
-		return ret;
+    if ((ret = pcidriver_umem_sgget(privdata, &usglist)) != 0)
+        return ret;
 
-	/* write data to user space */
-	ret = copy_to_user(((umem_sglist_t *)arg)->sg, usglist.sg, (usglist.nents)*sizeof(umem_sgentry_t));
-	if (ret) return -EFAULT;
+    /* write data to user space */
+    ret = copy_to_user(((umem_sglist_t *)arg)->sg, usglist.sg, (usglist.nents)*sizeof(umem_sgentry_t));
+    if (ret) return -EFAULT;
 
-	/* free array memory */
-	vfree(usglist.sg);
+    /* free array memory */
+    vfree(usglist.sg);
 
-	/* restore sg pointer to vma address in user space before copying */
-	usglist.sg = ((umem_sglist_t *)arg)->sg;
+    /* restore sg pointer to vma address in user space before copying */
+    usglist.sg = ((umem_sglist_t *)arg)->sg;
 
-	WRITE_TO_USER(umem_sglist_t, usglist);
+    WRITE_TO_USER(umem_sglist_t, usglist);
 
-	return 0;
+    return 0;
 }
 
 /**
@@ -333,10 +318,10 @@ static int ioctl_umem_sgget(pcidriver_privdata_t *privdata, unsigned long arg)
  */
 static int ioctl_umem_sync(pcidriver_privdata_t *privdata, unsigned long arg)
 {
-	int ret;
-	READ_FROM_USER(umem_handle_t, uhandle);
+    int ret;
+    READ_FROM_USER(umem_handle_t, uhandle);
 
-	return pcidriver_umem_sync( privdata, &uhandle );
+    return pcidriver_umem_sync( privdata, &uhandle );
 }
 
 /**
@@ -349,47 +334,47 @@ static int ioctl_umem_sync(pcidriver_privdata_t *privdata, unsigned long arg)
 static int ioctl_wait_interrupt(pcidriver_privdata_t *privdata, unsigned long arg)
 {
 #ifdef ENABLE_IRQ
-	int ret;
-	unsigned long timeout;
-	unsigned int irq_source;
-	unsigned long temp = 0;
+    int ret;
+    unsigned long timeout;
+    unsigned int irq_source;
+    unsigned long temp = 0;
 
-	READ_FROM_USER(interrupt_wait_t, irq_handle);
+    READ_FROM_USER(interrupt_wait_t, irq_handle);
 
-	irq_source = irq_handle.source;
+    irq_source = irq_handle.source;
 
-	if (irq_source >= PCIDRIVER_INT_MAXSOURCES)
-		return -EFAULT;						/* User tried to overrun the IRQ_SOURCES array */
+    if (irq_source >= PCIDRIVER_INT_MAXSOURCES)
+        return -EFAULT;						/* User tried to overrun the IRQ_SOURCES array */
 
-	timeout = jiffies + (irq_handle.timeout * HZ / 1000000);
+    timeout = jiffies + (irq_handle.timeout * HZ / 1000000);
 
-	/* Thanks to Joern for the correction and tips! */
-	/* done this way to avoid wrong behaviour (endless loop) of the compiler in AMD platforms */
-	do {
-		/* We wait here with an interruptible timeout. This will be interrupted
+    /* Thanks to Joern for the correction and tips! */
+    /* done this way to avoid wrong behaviour (endless loop) of the compiler in AMD platforms */
+    do {
+        /* We wait here with an interruptible timeout. This will be interrupted
                  * by int.c:check_acknowledge_channel() as soon as in interrupt for
                  * the specified source arrives. */
-		wait_event_interruptible_timeout( (privdata->irq_queues[irq_source]), (atomic_read(&(privdata->irq_outstanding[irq_source])) > 0), (10*HZ/1000) );
-
-		if (atomic_add_negative( -1, &(privdata->irq_outstanding[irq_source])) )
-			atomic_inc( &(privdata->irq_outstanding[irq_source]) );
-		else
-			temp = 1;
-	} while ((!temp)&&(jiffies < timeout));
-	
-	if ((temp)&&(irq_handle.count)) {
-	    while (!atomic_add_negative( -1, &(privdata->irq_outstanding[irq_source]))) temp++;
-	    atomic_inc( &(privdata->irq_outstanding[irq_source]) );
-	}
-	
-	irq_handle.count = temp;
-
-	WRITE_TO_USER(interrupt_wait_t, irq_handle);
-
-	return 0;
+        wait_event_interruptible_timeout( (privdata->irq_queues[irq_source]), (atomic_read(&(privdata->irq_outstanding[irq_source])) > 0), (10*HZ/1000) );
+
+        if (atomic_add_negative( -1, &(privdata->irq_outstanding[irq_source])) )
+            atomic_inc( &(privdata->irq_outstanding[irq_source]) );
+        else
+            temp = 1;
+    } while ((!temp)&&(jiffies < timeout));
+
+    if ((temp)&&(irq_handle.count)) {
+        while (!atomic_add_negative( -1, &(privdata->irq_outstanding[irq_source]))) temp++;
+        atomic_inc( &(privdata->irq_outstanding[irq_source]) );
+    }
+
+    irq_handle.count = temp;
+
+    WRITE_TO_USER(interrupt_wait_t, irq_handle);
+
+    return 0;
 #else
-	mod_info("Asked to wait for interrupt but interrupts are not enabled in the driver\n");
-	return -EFAULT;
+    mod_info("Asked to wait for interrupt but interrupts are not enabled in the driver\n");
+    return -EFAULT;
 #endif
 }
 
@@ -404,18 +389,18 @@ static int ioctl_wait_interrupt(pcidriver_privdata_t *privdata, unsigned long ar
 static int ioctl_clear_ioq(pcidriver_privdata_t *privdata, unsigned long arg)
 {
 #ifdef ENABLE_IRQ
-	unsigned int irq_source;
+    unsigned int irq_source;
 
-	if (arg >= PCIDRIVER_INT_MAXSOURCES)
-		return -EFAULT;
+    if (arg >= PCIDRIVER_INT_MAXSOURCES)
+        return -EFAULT;
 
-	irq_source = arg;
-	atomic_set(&(privdata->irq_outstanding[irq_source]), 0);
+    irq_source = arg;
+    atomic_set(&(privdata->irq_outstanding[irq_source]), 0);
 
-	return 0;
+    return 0;
 #else
-	mod_info("Asked to wait for interrupt but interrupts are not enabled in the driver\n");
-	return -EFAULT;
+    mod_info("Asked to wait for interrupt but interrupts are not enabled in the driver\n");
+    return -EFAULT;
 #endif
 }
 
@@ -429,18 +414,18 @@ static int ioctl_clear_ioq(pcidriver_privdata_t *privdata, unsigned long arg)
  */
 static int ioctl_version(pcidriver_privdata_t *privdata, unsigned long arg)
 {
-	int ret;
-	pcilib_driver_version_t info;
+    int ret;
+    pcilib_driver_version_t info;
 
-	info = (pcilib_driver_version_t) {
-	    .version = PCILIB_VERSION,
-	    .interface = PCIDRIVER_INTERFACE_VERSION,
-	    .ioctls = PCIDRIVER_IOC_MAX + 1
-	};
+    info = (pcilib_driver_version_t) {
+        .version = PCILIB_VERSION,
+         .interface = PCIDRIVER_INTERFACE_VERSION,
+          .ioctls = PCIDRIVER_IOC_MAX + 1
+    };
 
-	WRITE_TO_USER(pcilib_driver_version_t, info);
+    WRITE_TO_USER(pcilib_driver_version_t, info);
 
-	return 0;
+    return 0;
 }
 
 /**
@@ -452,24 +437,24 @@ static int ioctl_version(pcidriver_privdata_t *privdata, unsigned long arg)
  */
 static int ioctl_device_state(pcidriver_privdata_t *privdata, unsigned long arg)
 {
-	int ret;
-	pcilib_device_state_t info;
+    int ret;
+    pcilib_device_state_t info;
 
 #ifdef PCIDRIVER_DUMMY_DEVICE
-	memset(&info, 0, sizeof(info));
+    memset(&info, 0, sizeof(info));
 #else /* PCIDRIVER_DUMMY_DEVICE */
-	info = (pcilib_device_state_t) {
-	    .iommu = iommu_present(privdata->pdev->dev.bus),
-	    .mps = pcidriver_pcie_get_mps(privdata->pdev),
-	    .readrq = pcie_get_readrq(privdata->pdev),
-	    .dma_mask = privdata->pdev->dma_mask
-	};
+    info = (pcilib_device_state_t) {
+        .iommu = iommu_present(privdata->pdev->dev.bus),
+         .mps = pcidriver_pcie_get_mps(privdata->pdev),
+          .readrq = pcie_get_readrq(privdata->pdev),
+           .dma_mask = privdata->pdev->dma_mask
+    };
 #endif /* PCIDRIVER_DUMMY_DEVICE */
 
 
-	WRITE_TO_USER(pcilib_device_state_t, info);
+    WRITE_TO_USER(pcilib_device_state_t, info);
 
-	return 0;
+    return 0;
 }
 
 
@@ -483,19 +468,19 @@ static int ioctl_device_state(pcidriver_privdata_t *privdata, unsigned long arg)
 static int ioctl_set_dma_mask(pcidriver_privdata_t *privdata, unsigned long arg)
 {
 #ifndef PCIDRIVER_DUMMY_DEVICE
-	int err;
+    int err;
 
-	if ((arg < 24) || (arg > 64))
-		return -EINVAL;
+    if ((arg < 24) || (arg > 64))
+        return -EINVAL;
 
-	err = pci_set_dma_mask(privdata->pdev, DMA_BIT_MASK(arg));
-	if (err < 0) {
-	    printk(KERN_ERR "pci_set_dma_mask(%lu) failed\n", arg);
-	    return err;
-	}
+    err = pci_set_dma_mask(privdata->pdev, DMA_BIT_MASK(arg));
+    if (err < 0) {
+        printk(KERN_ERR "pci_set_dma_mask(%lu) failed\n", arg);
+        return err;
+    }
 #endif /* ! PCIDRIVER_DUMMY_DEVICE */
-	
-	return 0;
+
+    return 0;
 }
 
 /**
@@ -508,19 +493,19 @@ static int ioctl_set_dma_mask(pcidriver_privdata_t *privdata, unsigned long arg)
 static int ioctl_set_mps(pcidriver_privdata_t *privdata, unsigned long arg)
 {
 #ifndef PCIDRIVER_DUMMY_DEVICE
-	int err;
+    int err;
 
-	if ((arg != 128) && (arg != 256) && (arg != 512))
-		return -EINVAL;
+    if ((arg != 128) && (arg != 256) && (arg != 512))
+        return -EINVAL;
 
-	err = pcidriver_pcie_set_mps(privdata->pdev, arg);
-	if (err < 0) {
-	    printk(KERN_ERR "pcie_set_mps(%lu) failed\n", arg);
-	    return err;
-	}
+    err = pcidriver_pcie_set_mps(privdata->pdev, arg);
+    if (err < 0) {
+        printk(KERN_ERR "pcie_set_mps(%lu) failed\n", arg);
+        return err;
+    }
 #endif /* ! PCIDRIVER_DUMMY_DEVICE */
-	
-	return 0;
+
+    return 0;
 }
 
 
@@ -533,69 +518,65 @@ static int ioctl_set_mps(pcidriver_privdata_t *privdata, unsigned long arg)
  * @returns -EFAULT when an invalid memory pointer is passed
  *
  */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
-int pcidriver_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
-#else
 long pcidriver_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-#endif
 {
-	pcidriver_privdata_t *privdata = filp->private_data;
+    pcidriver_privdata_t *privdata = filp->private_data;
+
+    /* Select the appropiate command */
+    switch (cmd) {
+    case PCIDRIVER_IOC_MMAP_MODE:
+        return ioctl_mmap_mode(privdata, arg);
 
-	/* Select the appropiate command */
-	switch (cmd) {
-		case PCIDRIVER_IOC_MMAP_MODE:
-			return ioctl_mmap_mode(privdata, arg);
+    case PCIDRIVER_IOC_MMAP_AREA:
+        return ioctl_mmap_area(privdata, arg);
 
-		case PCIDRIVER_IOC_MMAP_AREA:
-			return ioctl_mmap_area(privdata, arg);
+    case PCIDRIVER_IOC_PCI_CFG_RD:
+    case PCIDRIVER_IOC_PCI_CFG_WR:
+        return ioctl_pci_config_read_write(privdata, cmd, arg);
 
-		case PCIDRIVER_IOC_PCI_CFG_RD:
-		case PCIDRIVER_IOC_PCI_CFG_WR:
-			return ioctl_pci_config_read_write(privdata, cmd, arg);
+    case PCIDRIVER_IOC_PCI_INFO:
+        return ioctl_pci_info(privdata, arg);
 
-		case PCIDRIVER_IOC_PCI_INFO:
-			return ioctl_pci_info(privdata, arg);
+    case PCIDRIVER_IOC_KMEM_ALLOC:
+        return ioctl_kmem_alloc(privdata, arg);
 
-		case PCIDRIVER_IOC_KMEM_ALLOC:
-			return ioctl_kmem_alloc(privdata, arg);
+    case PCIDRIVER_IOC_KMEM_FREE:
+        return ioctl_kmem_free(privdata, arg);
 
-		case PCIDRIVER_IOC_KMEM_FREE:
-			return ioctl_kmem_free(privdata, arg);
+    case PCIDRIVER_IOC_KMEM_SYNC:
+        return ioctl_kmem_sync(privdata, arg);
 
-		case PCIDRIVER_IOC_KMEM_SYNC:
-			return ioctl_kmem_sync(privdata, arg);
+    case PCIDRIVER_IOC_UMEM_SGMAP:
+        return ioctl_umem_sgmap(privdata, arg);
 
-		case PCIDRIVER_IOC_UMEM_SGMAP:
-			return ioctl_umem_sgmap(privdata, arg);
+    case PCIDRIVER_IOC_UMEM_SGUNMAP:
+        return ioctl_umem_sgunmap(privdata, arg);
 
-		case PCIDRIVER_IOC_UMEM_SGUNMAP:
-			return ioctl_umem_sgunmap(privdata, arg);
+    case PCIDRIVER_IOC_UMEM_SGGET:
+        return ioctl_umem_sgget(privdata, arg);
 
-		case PCIDRIVER_IOC_UMEM_SGGET:
-			return ioctl_umem_sgget(privdata, arg);
+    case PCIDRIVER_IOC_UMEM_SYNC:
+        return ioctl_umem_sync(privdata, arg);
 
-		case PCIDRIVER_IOC_UMEM_SYNC:
-			return ioctl_umem_sync(privdata, arg);
+    case PCIDRIVER_IOC_WAITI:
+        return ioctl_wait_interrupt(privdata, arg);
 
-		case PCIDRIVER_IOC_WAITI:
-			return ioctl_wait_interrupt(privdata, arg);
+    case PCIDRIVER_IOC_CLEAR_IOQ:
+        return ioctl_clear_ioq(privdata, arg);
 
-		case PCIDRIVER_IOC_CLEAR_IOQ:
-			return ioctl_clear_ioq(privdata, arg);
-		
-		case PCIDRIVER_IOC_VERSION:
-			return ioctl_version(privdata, arg);
+    case PCIDRIVER_IOC_VERSION:
+        return ioctl_version(privdata, arg);
 
-		case PCIDRIVER_IOC_DEVICE_STATE:
-			return ioctl_device_state(privdata, arg);
+    case PCIDRIVER_IOC_DEVICE_STATE:
+        return ioctl_device_state(privdata, arg);
 
-		case PCIDRIVER_IOC_DMA_MASK:
-			return ioctl_set_dma_mask(privdata, arg);
+    case PCIDRIVER_IOC_DMA_MASK:
+        return ioctl_set_dma_mask(privdata, arg);
 
-		case PCIDRIVER_IOC_MPS:
-			return ioctl_set_mps(privdata, arg);
+    case PCIDRIVER_IOC_MPS:
+        return ioctl_set_mps(privdata, arg);
 
-		default:
-			return -EINVAL;
-	}
+    default:
+        return -EINVAL;
+    }
 }

+ 178 - 5
driver/ioctl.h

@@ -1,5 +1,178 @@
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
-int pcidriver_ioctl(struct inode  *inode, struct file *filp, unsigned int cmd, unsigned long arg);
-#else
-long pcidriver_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
-#endif
+#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 */

Різницю між файлами не показано, бо вона завелика
+ 418 - 473
driver/kmem.c


+ 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 - 245
driver/pciDriver.h

@@ -1,245 +0,0 @@
-#ifndef PCIDRIVER_H_
-#define PCIDRIVER_H_
-
-/**
- * This is a full rewrite of the pciDriver.
- * New default is to support kernel 2.6, using kernel 2.6 APIs.
- * 
- * This header defines the interface to the outside world.
- * 
- * $Revision: 1.6 $
- * $Date: 2008-01-24 14:21:36 $
- * 
- */
-
-/*
- * Change History:
- * 
- * $Log: not supported by cvs2svn $
- * Revision 1.5  2008-01-11 10:15:14  marcus
- * Removed unused interrupt code.
- * Added intSource to the wait interrupt call.
- *
- * Revision 1.4  2006/11/17 18:44:42  marcus
- * Type of SG list can now be selected at runtime. Added type to sglist.
- *
- * Revision 1.3  2006/11/17 16:23:02  marcus
- * Added slot number to the PCI info IOctl.
- *
- * Revision 1.2  2006/11/13 12:29:09  marcus
- * Added a IOctl call, to confiure the interrupt response. (testing pending).
- * Basic interrupts are now supported.
- *
- * Revision 1.1  2006/10/10 14:46:52  marcus
- * Initial commit of the new pciDriver for kernel 2.6
- *
- * Revision 1.7  2006/10/06 15:18:06  marcus
- * Updated PCI info and PCI cmd
- *
- * Revision 1.6  2006/09/25 16:51:07  marcus
- * Added PCI config IOctls, and implemented basic mmap functions.
- *
- * Revision 1.5  2006/09/18 17:13:12  marcus
- * backup commit.
- *
- * Revision 1.4  2006/09/15 15:44:41  marcus
- * backup commit.
- *
- * Revision 1.3  2006/08/15 11:40:02  marcus
- * backup commit.
- *
- * Revision 1.2  2006/08/12 18:28:42  marcus
- * Sync with the laptop
- *
- * Revision 1.1  2006/08/11 15:30:46  marcus
- * Sync with the laptop
- *
- */
-
-#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

+ 25 - 0
driver/pcibus.c

@@ -0,0 +1,25 @@
+#include <linux/pci.h>
+
+int pcidriver_pcie_get_mps(struct pci_dev *dev)
+{
+    u16 ctl;
+
+    pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &ctl);
+
+    return 128 << ((ctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5);
+}
+
+int pcidriver_pcie_set_mps(struct pci_dev *dev, int mps)
+{
+    u16 v;
+
+    if (mps < 128 || mps > 4096 || !is_power_of_2(mps))
+        return -EINVAL;
+
+    v = ffs(mps) - 8;
+    if (v > dev->pcie_mpss)
+        return -EINVAL;
+    v <<= 5;
+
+    return pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_PAYLOAD, v);
+}

+ 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 */

+ 29 - 12
driver/rdma.c

@@ -7,8 +7,9 @@
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 #include <linux/hugetlb.h>
+#include <linux/cdev.h>
 
-#include "rdma.h"
+#include "base.h"
 
 static unsigned long pcidriver_follow_pte(struct mm_struct *mm, unsigned long address)
 {
@@ -17,37 +18,53 @@ static unsigned long pcidriver_follow_pte(struct mm_struct *mm, unsigned long ad
     pmd_t *pmd;
     pte_t *pte;
 
-    spinlock_t *ptl; 
+    spinlock_t *ptl;
     unsigned long pfn = 0;
 
 
     pgd = pgd_offset(mm, address);
-    if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd))) 
-	return 0;
-        
+    if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
+        return 0;
+
     pud = pud_offset(pgd, address);
-    if (pud_none(*pud) || unlikely(pud_bad(*pud)))     
-	return 0;
+    if (pud_none(*pud) || unlikely(pud_bad(*pud)))
+        return 0;
 
     pmd = pmd_offset(pud, address);
-    if (pmd_none(*pmd)) 
-	return 0;
+    if (pmd_none(*pmd))
+        return 0;
 
     pte = pte_offset_map_lock(mm, pmd, address, &ptl);
     if (!pte_none(*pte))
-	pfn = (pte_pfn(*pte) << PAGE_SHIFT);
-    pte_unmap_unlock(pte, ptl); 
+        pfn = (pte_pfn(*pte) << PAGE_SHIFT);
+    pte_unmap_unlock(pte, ptl);
 
     return pfn;
 }
 
 unsigned long pcidriver_resolve_bar(unsigned long address) {
+    int dev, bar;
     unsigned long pfn;
 
     address = (address >> PAGE_SHIFT) << PAGE_SHIFT;
     pfn = pcidriver_follow_pte(current->mm, address);
 
-    return pfn;
+    for (dev = 0; dev < MAXDEVICES; dev++)
+    {
+        pcidriver_privdata_t *privdata =  pcidriver_get_privdata(dev);
+        if (!privdata) continue;
+
+        for (bar = 0; bar < 6; bar++)
+        {
+            unsigned long start = pci_resource_start(privdata->pdev, bar);
+            unsigned long end = start + pci_resource_len(privdata->pdev, bar);
+            if ((pfn >= start)&&(pfn < end))
+                return pfn;
+        }
+        pcidriver_put_privdata(privdata);
+    }
+
+    return 0;
 }
 
 EXPORT_SYMBOL(pcidriver_resolve_bar);

+ 0 - 4
driver/rdma.h

@@ -1,9 +1,5 @@
 #ifndef _PCIDRIVER_RDMA_H
 #define _PCIDRIVER_RDMA_H
 
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-
-extern unsigned long pcidriver_resolve_bar(unsigned long address);
 
 #endif /* _PCIDRIVER_RDMA_H */

+ 235 - 205
driver/sysfs.c

@@ -18,291 +18,321 @@
 #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 */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
-	char namebuffer[16];
+#define SYSFS_ATTR_NAME(name) (dev_attr_##name)
 
-	/* allocate space for the name of the attribute */
-	snprintf(namebuffer, sizeof(namebuffer), fmtstring, id);
+#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)
 
-	if ((sysfs_attr->attr.name = kstrdup(namebuffer, GFP_KERNEL)) == NULL)
-		return -ENOMEM;
+#define SYSFS_ATTR_REMOVE(name) do { \
+	device_remove_file(privdata->class_dev, &SYSFS_ATTR_NAME(name)); \
+    } while (0)
 
-	sysfs_attr->attr.mode = S_IRUGO;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
-	    // DS: Shall we lock now while accessing driver data structures???
-	sysfs_attr->attr.owner = THIS_MODULE;
-#endif
-	sysfs_attr->show = callback;
-	sysfs_attr->store = NULL;
-			
-	/* 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. */
-#endif
+#ifdef ENABLE_IRQ
+static SYSFS_GET_FUNCTION(pcidriver_show_irq_count)
+{
+    pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
 
-	return 0;
+    return snprintf(buf, PAGE_SIZE, "%d\n", privdata->irq_count);
 }
 
-int pcidriver_sysfs_initialize_kmem(pcidriver_privdata_t *privdata, int id, struct class_device_attribute *sysfs_attr)
+static SYSFS_GET_FUNCTION(pcidriver_show_irq_queues)
 {
-	return _pcidriver_sysfs_initialize(privdata, id, sysfs_attr, "kbuf%d", pcidriver_show_kmem_entry);
-}
+    pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+    int i, offset;
 
-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);
-}
+    /* output will be truncated to PAGE_SIZE */
+    offset = snprintf(buf, PAGE_SIZE, "Queue\tOutstanding IRQs\n");
+    for (i = 0; i < PCIDRIVER_INT_MAXSOURCES; i++)
+        offset += snprintf(buf+offset, PAGE_SIZE-offset, "%d\t%d\n", i, atomic_read(&(privdata->irq_outstanding[i])) );
 
-/**
- *
- * 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)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
-	class_device_remove_file(privdata->class_dev, sysfs_attr);
-	kfree(sysfs_attr->attr.name);
-#endif
+    return (offset > PAGE_SIZE ? PAGE_SIZE : offset+1);
 }
+#endif
 
-static SYSFS_GET_FUNCTION(pcidriver_show_kmem_entry)
+static SYSFS_GET_FUNCTION(pcidriver_show_mmap_mode)
 {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
-	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);
-#else
-	return 0;
-#endif
+    pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+
+    return snprintf(buf, PAGE_SIZE, "%d\n", privdata->mmap_mode);
 }
 
-static SYSFS_GET_FUNCTION(pcidriver_show_umem_entry)
+static SYSFS_SET_FUNCTION(pcidriver_store_mmap_mode)
 {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
-#if 0
-	pcidriver_privdata_t *privdata = (pcidriver_privdata_t *)cls->class_data;
+    pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+    int mode = -1;
 
-	return snprintf(buf, PAGE_SIZE, "I am in the umem_entry show function, class_device_kobj_name: %s\n", cls->kobj.name);
-#endif
-	return 0;
-#else
-	return 0;
-#endif
+    /* Set the mmap-mode if it is either PCIDRIVER_MMAP_PCI or PCIDRIVER_MMAP_KMEM */
+    if (sscanf(buf, "%d", &mode) == 1 &&
+            (mode == PCIDRIVER_MMAP_PCI || mode == PCIDRIVER_MMAP_KMEM))
+        privdata->mmap_mode = mode;
+
+    return strlen(buf);
 }
 
-#ifdef ENABLE_IRQ
-SYSFS_GET_FUNCTION(pcidriver_show_irq_count)
+static SYSFS_GET_FUNCTION(pcidriver_show_mmap_area)
 {
-	pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+    pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
 
-	return snprintf(buf, PAGE_SIZE, "%d\n", privdata->irq_count);
+    return snprintf(buf, PAGE_SIZE, "%d\n", privdata->mmap_area);
 }
 
-SYSFS_GET_FUNCTION(pcidriver_show_irq_queues)
+static SYSFS_SET_FUNCTION(pcidriver_store_mmap_area)
 {
-	pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
-	int i, offset;
+    pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+    int temp = -1;
+
+    sscanf(buf, "%d", &temp);
 
-	/* output will be truncated to PAGE_SIZE */
-	offset = snprintf(buf, PAGE_SIZE, "Queue\tOutstanding IRQs\n");
-	for (i = 0; i < PCIDRIVER_INT_MAXSOURCES; i++)
-		offset += snprintf(buf+offset, PAGE_SIZE-offset, "%d\t%d\n", i, atomic_read(&(privdata->irq_outstanding[i])) );
+    if ((temp >= PCIDRIVER_BAR0) && (temp <= PCIDRIVER_BAR5))
+        privdata->mmap_area = temp;
 
-	return (offset > PAGE_SIZE ? PAGE_SIZE : offset+1);
+    return strlen(buf);
 }
-#endif
 
-SYSFS_GET_FUNCTION(pcidriver_show_mmap_mode)
+static SYSFS_GET_FUNCTION(pcidriver_show_kmem_count)
 {
-	pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+    pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
 
-	return snprintf(buf, PAGE_SIZE, "%d\n", privdata->mmap_mode);
+    return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&(privdata->kmem_count)));
 }
 
-SYSFS_SET_FUNCTION(pcidriver_store_mmap_mode)
+static SYSFS_SET_FUNCTION(pcidriver_store_kmem_alloc)
 {
-	pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
-	int mode = -1;
+    pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+    kmem_handle_t kmem_handle;
 
-	/* Set the mmap-mode if it is either PCIDRIVER_MMAP_PCI or PCIDRIVER_MMAP_KMEM */
-	if (sscanf(buf, "%d", &mode) == 1 &&
-	    (mode == PCIDRIVER_MMAP_PCI || mode == PCIDRIVER_MMAP_KMEM))
-		privdata->mmap_mode = mode;
+    /* FIXME: guillermo: is validation of parsing an unsigned int enough? */
+    if (sscanf(buf, "%lu", &kmem_handle.size) == 1)
+        pcidriver_kmem_alloc(privdata, &kmem_handle);
 
-	return strlen(buf);
+    return strlen(buf);
 }
 
-SYSFS_GET_FUNCTION(pcidriver_show_mmap_area)
+static SYSFS_SET_FUNCTION(pcidriver_store_kmem_free)
 {
-	pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+    pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+    unsigned int id;
+    pcidriver_kmem_entry_t *kmem_entry;
+
+    /* Parse the ID of the kernel memory to be freed, check bounds */
+    if (sscanf(buf, "%u", &id) != 1 ||
+            (id >= atomic_read(&(privdata->kmem_count))))
+        goto err;
+
+    if ((kmem_entry = pcidriver_kmem_find_entry_id(privdata,id)) == NULL)
+        goto err;
 
-	return snprintf(buf, PAGE_SIZE, "%d\n", privdata->mmap_area);
+    pcidriver_kmem_free_entry(privdata, kmem_entry );
+err:
+    return strlen(buf);
 }
 
-SYSFS_SET_FUNCTION(pcidriver_store_mmap_area)
+static SYSFS_GET_FUNCTION(pcidriver_show_kbuffers)
 {
-	pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
-	int temp = -1;
+    pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+    int offset = 0;
+    struct list_head *ptr;
+    pcidriver_kmem_entry_t *entry;
 
-	sscanf(buf, "%d", &temp);
+    /* print the header */
+    offset += snprintf(buf, PAGE_SIZE, "kbuf#\tcpu addr\tsize\n");
 
-	if ((temp >= PCIDRIVER_BAR0) && (temp <= PCIDRIVER_BAR5))
-		privdata->mmap_area = temp;
+    spin_lock(&(privdata->kmemlist_lock));
+    list_for_each(ptr, &(privdata->kmem_list)) {
+        entry = list_entry(ptr, pcidriver_kmem_entry_t, list);
 
-	return strlen(buf);
-}
+        /* print entry info */
+        if (offset > PAGE_SIZE) {
+            spin_unlock( &(privdata->kmemlist_lock) );
+            return PAGE_SIZE;
+        }
 
-SYSFS_GET_FUNCTION(pcidriver_show_kmem_count)
-{
-	pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+        offset += snprintf(buf+offset, PAGE_SIZE-offset, "%3d\t%08lx\t%lu\n", entry->id, (unsigned long)(entry->dma_handle), entry->size );
+    }
+
+    spin_unlock(&(privdata->kmemlist_lock));
 
-	return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&(privdata->kmem_count)));
+    /* output will be truncated to PAGE_SIZE */
+    return (offset > PAGE_SIZE ? PAGE_SIZE : offset+1);
 }
 
-SYSFS_SET_FUNCTION(pcidriver_store_kmem_alloc)
+static SYSFS_GET_FUNCTION(pcidriver_show_umappings)
 {
-	pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
-	kmem_handle_t kmem_handle;
+    int offset = 0;
+    pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+    struct list_head *ptr;
+    pcidriver_umem_entry_t *entry;
 
-	/* FIXME: guillermo: is validation of parsing an unsigned int enough? */
-	if (sscanf(buf, "%lu", &kmem_handle.size) == 1)
-		pcidriver_kmem_alloc(privdata, &kmem_handle);
+    /* print the header */
+    offset += snprintf(buf, PAGE_SIZE, "umap#\tn_pages\tsg_ents\n");
 
-	return strlen(buf);
+    spin_lock( &(privdata->umemlist_lock) );
+    list_for_each( ptr, &(privdata->umem_list) ) {
+        entry = list_entry(ptr, pcidriver_umem_entry_t, list );
+
+        /* print entry info */
+        if (offset > PAGE_SIZE) {
+            spin_unlock( &(privdata->umemlist_lock) );
+            return PAGE_SIZE;
+        }
+
+        offset += snprintf(buf+offset, PAGE_SIZE-offset, "%3d\t%lu\t%lu\n", entry->id,
+                           (unsigned long)(entry->nr_pages), (unsigned long)(entry->nents));
+    }
+
+    spin_unlock( &(privdata->umemlist_lock) );
+
+    /* output will be truncated to PAGE_SIZE */
+    return (offset > PAGE_SIZE ? PAGE_SIZE : offset+1);
 }
 
-SYSFS_SET_FUNCTION(pcidriver_store_kmem_free)
+static SYSFS_SET_FUNCTION(pcidriver_store_umem_unmap)
 {
-	pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
-	unsigned int id;
-	pcidriver_kmem_entry_t *kmem_entry;
+    pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+    pcidriver_umem_entry_t *umem_entry;
+    unsigned int id;
 
-	/* Parse the ID of the kernel memory to be freed, check bounds */
-	if (sscanf(buf, "%u", &id) != 1 ||
-	    (id >= atomic_read(&(privdata->kmem_count))))
-		goto err;
+    if (sscanf(buf, "%u", &id) != 1 ||
+            (id >= atomic_read(&(privdata->umem_count))))
+        goto err;
 
-	if ((kmem_entry = pcidriver_kmem_find_entry_id(privdata,id)) == NULL)
-		goto err;
+    if ((umem_entry = pcidriver_umem_find_entry_id(privdata, id)) == NULL)
+        goto err;
 
-	pcidriver_kmem_free_entry(privdata, kmem_entry );
+    pcidriver_umem_sgunmap(privdata, umem_entry);
 err:
-	return strlen(buf);
+    return strlen(buf);
 }
 
-SYSFS_GET_FUNCTION(pcidriver_show_kbuffers)
+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)
 {
-	pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
-	int offset = 0;
-	struct list_head *ptr;
-	pcidriver_kmem_entry_t *entry;
+    return 0;
+}
 
-	/* print the header */
-	offset += snprintf(buf, PAGE_SIZE, "kbuf#\tcpu addr\tsize\n");
 
-	spin_lock(&(privdata->kmemlist_lock));
-	list_for_each(ptr, &(privdata->kmem_list)) {
-		entry = list_entry(ptr, pcidriver_kmem_entry_t, list);
+#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
 
-		/* print entry info */
-		if (offset > PAGE_SIZE) {
-			spin_unlock( &(privdata->kmemlist_lock) );
-			return PAGE_SIZE;
-		}
+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);
 
-		offset += snprintf(buf+offset, PAGE_SIZE-offset, "%3d\t%08lx\t%lu\n", entry->id, (unsigned long)(entry->dma_handle), entry->size );
-	}
+int pcidriver_create_sysfs_attributes(pcidriver_privdata_t *privdata) {
+#ifdef ENABLE_IRQ
+    SYSFS_ATTR_CREATE(irq_count);
+    SYSFS_ATTR_CREATE(irq_queues);
+#endif
 
-	spin_unlock(&(privdata->kmemlist_lock));
+    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
 
-	/* output will be truncated to PAGE_SIZE */
-	return (offset > PAGE_SIZE ? PAGE_SIZE : offset+1);
+    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);
 }
 
-SYSFS_GET_FUNCTION(pcidriver_show_umappings)
+/**
+ *
+ * Removes the file from sysfs and frees the allocated (kstrdup()) memory.
+ *
+ */
+void pcidriver_sysfs_remove(pcidriver_privdata_t *privdata, struct device_attribute *sysfs_attr)
 {
-	int offset = 0;
-	pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
-	struct list_head *ptr;
-	pcidriver_umem_entry_t *entry;
+    device_remove_file(privdata->class_dev, sysfs_attr);
+    kfree(sysfs_attr->attr.name);
+}
 
-	/* print the header */
-	offset += snprintf(buf, PAGE_SIZE, "umap#\tn_pages\tsg_ents\n");
+/**
+ *
+ * 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];
 
-	spin_lock( &(privdata->umemlist_lock) );
-	list_for_each( ptr, &(privdata->umem_list) ) {
-		entry = list_entry(ptr, pcidriver_umem_entry_t, list );
+    /* allocate space for the name of the attribute */
+    snprintf(namebuffer, sizeof(namebuffer), fmtstring, id);
 
-		/* print entry info */
-		if (offset > PAGE_SIZE) {
-			spin_unlock( &(privdata->umemlist_lock) );
-			return PAGE_SIZE;
-		}
+    if ((sysfs_attr->attr.name = kstrdup(namebuffer, GFP_KERNEL)) == NULL)
+        return -ENOMEM;
 
-		offset += snprintf(buf+offset, PAGE_SIZE-offset, "%3d\t%lu\t%lu\n", entry->id,
-				(unsigned long)(entry->nr_pages), (unsigned long)(entry->nents));
-	}
+    sysfs_attr->attr.mode = S_IRUGO;
+    sysfs_attr->show = callback;
+    sysfs_attr->store = NULL;
 
-	spin_unlock( &(privdata->umemlist_lock) );
+    /* 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. */
 
-	/* output will be truncated to PAGE_SIZE */
-	return (offset > PAGE_SIZE ? PAGE_SIZE : offset+1);
+    return 0;
 }
 
-SYSFS_SET_FUNCTION(pcidriver_store_umem_unmap)
+int pcidriver_sysfs_initialize_kmem(pcidriver_privdata_t *privdata, int id, struct device_attribute *sysfs_attr)
 {
-	pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
-	pcidriver_umem_entry_t *umem_entry;
-	unsigned int id;
-
-	if (sscanf(buf, "%u", &id) != 1 ||
-	    (id >= atomic_read(&(privdata->umem_count))))
-		goto err;
-
-	if ((umem_entry = pcidriver_umem_find_entry_id(privdata, id)) == NULL)
-		goto err;
+    return _pcidriver_sysfs_initialize(privdata, id, sysfs_attr, "kbuf%d", pcidriver_show_kmem_entry);
+}
 
-	pcidriver_umem_sgunmap(privdata, umem_entry);
-err:
-	return strlen(buf);
+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 */

+ 281 - 351
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"
 
 /**
  *
@@ -32,153 +27,153 @@
  */
 int pcidriver_umem_sgmap(pcidriver_privdata_t *privdata, umem_handle_t *umem_handle)
 {
-	int i, res, nr_pages;
-	struct page **pages;
-	struct scatterlist *sg = NULL;
-	pcidriver_umem_entry_t *umem_entry;
-	unsigned int nents;
-	unsigned long count,offset,length;
-
-	/*
-	 * We do some checks first. Then, the following is necessary to create a
-	 * Scatter/Gather list from a user memory area:
-	 *  - Determine the number of pages
-	 *  - Get the pages for the memory area
-	 * 	- Lock them.
-	 *  - Create a scatter/gather list of the pages
-	 *  - Map the list from memory to PCI bus addresses
-	 *
-	 * Then, we:
-	 *  - Create an entry on the umem list of the device, to cache the mapping.
-	 *  - Create a sysfs attribute that gives easy access to the SG list
-	 */
-
-	/* zero-size?? */
-	if (umem_handle->size == 0)
-		return -EINVAL;
-
-	/* Direction is better ignoring during mapping. */
-	/* We assume bidirectional buffers always, except when sync'ing */
-
-	/* calculate the number of pages */
-	nr_pages = ((umem_handle->vma & ~PAGE_MASK) + umem_handle->size + ~PAGE_MASK) >> PAGE_SHIFT;
-
-	mod_info_dbg("nr_pages computed: %u\n", nr_pages);
-
-	/* Allocate space for the page information */
-	/* This can be very big, so we use vmalloc */
-	if ((pages = vmalloc(nr_pages * sizeof(*pages))) == NULL)
-		return -ENOMEM;
-
-	mod_info_dbg("allocated space for the pages.\n");
-
-	/* Allocate space for the scatterlist */
-	/* We do not know how many entries will be, but the maximum is nr_pages. */
-	/* This can be very big, so we use vmalloc */
-	if ((sg = vmalloc(nr_pages * sizeof(*sg))) == NULL)
-		goto umem_sgmap_pages;
-
-	sg_init_table(sg, nr_pages);
-
-	mod_info_dbg("allocated space for the SG list.\n");
-
-	/* Get the page information */
-	down_read(&current->mm->mmap_sem);
-	res = get_user_pages(
-				current,
-				current->mm,
-				umem_handle->vma,
-				nr_pages,
-				1,
-				0,  /* do not force, FIXME: shall I? */
-				pages,
-				NULL );
-	up_read(&current->mm->mmap_sem);
-
-	/* Error, not all pages mapped */
-	if (res < (int)nr_pages) {
-		mod_info("Could not map all user pages (%d of %d)\n", res, nr_pages);
-		/* If only some pages could be mapped, we release those. If a real
-		 * error occured, we set nr_pages to 0 */
-		nr_pages = (res > 0 ? res : 0);
-		goto umem_sgmap_unmap;
-	}
-
-	mod_info_dbg("Got the pages (%d).\n", res);
-
-	/* Lock the pages, then populate the SG list with the pages */
-	/* page0 is different */
-	if ( !PageReserved(pages[0]) )
-		compat_lock_page(pages[0]);
-
-	offset = (umem_handle->vma & ~PAGE_MASK);
-	length = (umem_handle->size > (PAGE_SIZE-offset) ? (PAGE_SIZE-offset) : umem_handle->size);
-
-	sg_set_page(&sg[0], pages[0], length, offset);
-
-	count = umem_handle->size - length;
-	for(i=1;i<nr_pages;i++) {
-		/* Lock page first */
-		if ( !PageReserved(pages[i]) )
-			compat_lock_page(pages[i]);
-
-		/* Populate the list */
-		sg_set_page(&sg[i], pages[i], ((count > PAGE_SIZE) ? PAGE_SIZE : count), 0);
-		count -= sg[i].length;
-	}
-
-	/* Use the page list to populate the SG list */
-	/* SG entries may be merged, res is the number of used entries */
-	/* We have originally nr_pages entries in the sg list */
-	if ((nents = pci_map_sg(privdata->pdev, sg, nr_pages, PCI_DMA_BIDIRECTIONAL)) == 0)
-		goto umem_sgmap_unmap;
-
-	mod_info_dbg("Mapped SG list (%d entries).\n", nents);
-
-	/* Add an entry to the umem_list of the device, and update the handle with the id */
-	/* Allocate space for the new umem entry */
-	if ((umem_entry = kmalloc(sizeof(*umem_entry), GFP_KERNEL)) == NULL)
-		goto umem_sgmap_entry;
-
-	/* Fill entry to be added to the umem list */
-	umem_entry->id = atomic_inc_return(&privdata->umem_count) - 1;
-	umem_entry->nr_pages = nr_pages;	/* Will be needed when unmapping */
-	umem_entry->pages = pages;
-	umem_entry->nents = nents;
-	umem_entry->sg = sg;
-
-	if (pcidriver_sysfs_initialize_umem(privdata, umem_entry->id, &(umem_entry->sysfs_attr)) != 0)
-		goto umem_sgmap_name_fail;
-
-	/* Add entry to the umem list */
-	spin_lock( &(privdata->umemlist_lock) );
-	list_add_tail( &(umem_entry->list), &(privdata->umem_list) );
-	spin_unlock( &(privdata->umemlist_lock) );
-
-	/* Update the Handle with the Handle ID of the entry */
-	umem_handle->handle_id = umem_entry->id;
-
-	return 0;
+    int i, res, nr_pages;
+    struct page **pages;
+    struct scatterlist *sg = NULL;
+    pcidriver_umem_entry_t *umem_entry;
+    unsigned int nents;
+    unsigned long count,offset,length;
+
+    /*
+     * We do some checks first. Then, the following is necessary to create a
+     * Scatter/Gather list from a user memory area:
+     *  - Determine the number of pages
+     *  - Get the pages for the memory area
+     * 	- Lock them.
+     *  - Create a scatter/gather list of the pages
+     *  - Map the list from memory to PCI bus addresses
+     *
+     * Then, we:
+     *  - Create an entry on the umem list of the device, to cache the mapping.
+     *  - Create a sysfs attribute that gives easy access to the SG list
+     */
+
+    /* zero-size?? */
+    if (umem_handle->size == 0)
+        return -EINVAL;
+
+    /* Direction is better ignoring during mapping. */
+    /* We assume bidirectional buffers always, except when sync'ing */
+
+    /* calculate the number of pages */
+    nr_pages = ((umem_handle->vma & ~PAGE_MASK) + umem_handle->size + ~PAGE_MASK) >> PAGE_SHIFT;
+
+    mod_info_dbg("nr_pages computed: %u\n", nr_pages);
+
+    /* Allocate space for the page information */
+    /* This can be very big, so we use vmalloc */
+    if ((pages = vmalloc(nr_pages * sizeof(*pages))) == NULL)
+        return -ENOMEM;
+
+    mod_info_dbg("allocated space for the pages.\n");
+
+    /* Allocate space for the scatterlist */
+    /* We do not know how many entries will be, but the maximum is nr_pages. */
+    /* This can be very big, so we use vmalloc */
+    if ((sg = vmalloc(nr_pages * sizeof(*sg))) == NULL)
+        goto umem_sgmap_pages;
+
+    sg_init_table(sg, nr_pages);
+
+    mod_info_dbg("allocated space for the SG list.\n");
+
+    /* Get the page information */
+    down_read(&current->mm->mmap_sem);
+    res = get_user_pages(
+              current,
+              current->mm,
+              umem_handle->vma,
+              nr_pages,
+              1,
+              0,  /* do not force, FIXME: shall I? */
+              pages,
+              NULL );
+    up_read(&current->mm->mmap_sem);
+
+    /* Error, not all pages mapped */
+    if (res < (int)nr_pages) {
+        mod_info("Could not map all user pages (%d of %d)\n", res, nr_pages);
+        /* If only some pages could be mapped, we release those. If a real
+         * error occured, we set nr_pages to 0 */
+        nr_pages = (res > 0 ? res : 0);
+        goto umem_sgmap_unmap;
+    }
+
+    mod_info_dbg("Got the pages (%d).\n", res);
+
+    /* Lock the pages, then populate the SG list with the pages */
+    /* page0 is different */
+    if ( !PageReserved(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);
+
+    sg_set_page(&sg[0], pages[0], length, offset);
+
+    count = umem_handle->size - length;
+    for(i=1; i<nr_pages; i++) {
+        /* Lock page first */
+        if ( !PageReserved(pages[i]) )
+            __set_page_locked(pages[i]);
+
+        /* Populate the list */
+        sg_set_page(&sg[i], pages[i], ((count > PAGE_SIZE) ? PAGE_SIZE : count), 0);
+        count -= sg[i].length;
+    }
+
+    /* Use the page list to populate the SG list */
+    /* SG entries may be merged, res is the number of used entries */
+    /* We have originally nr_pages entries in the sg list */
+    if ((nents = pci_map_sg(privdata->pdev, sg, nr_pages, PCI_DMA_BIDIRECTIONAL)) == 0)
+        goto umem_sgmap_unmap;
+
+    mod_info_dbg("Mapped SG list (%d entries).\n", nents);
+
+    /* Add an entry to the umem_list of the device, and update the handle with the id */
+    /* Allocate space for the new umem entry */
+    if ((umem_entry = kmalloc(sizeof(*umem_entry), GFP_KERNEL)) == NULL)
+        goto umem_sgmap_entry;
+
+    /* Fill entry to be added to the umem list */
+    umem_entry->id = atomic_inc_return(&privdata->umem_count) - 1;
+    umem_entry->nr_pages = nr_pages;	/* Will be needed when unmapping */
+    umem_entry->pages = pages;
+    umem_entry->nents = nents;
+    umem_entry->sg = sg;
+
+    if (pcidriver_sysfs_initialize_umem(privdata, umem_entry->id, &(umem_entry->sysfs_attr)) != 0)
+        goto umem_sgmap_name_fail;
+
+    /* Add entry to the umem list */
+    spin_lock( &(privdata->umemlist_lock) );
+    list_add_tail( &(umem_entry->list), &(privdata->umem_list) );
+    spin_unlock( &(privdata->umemlist_lock) );
+
+    /* Update the Handle with the Handle ID of the entry */
+    umem_handle->handle_id = umem_entry->id;
+
+    return 0;
 
 umem_sgmap_name_fail:
-	kfree(umem_entry);
+    kfree(umem_entry);
 umem_sgmap_entry:
-	pci_unmap_sg( privdata->pdev, sg, nr_pages, PCI_DMA_BIDIRECTIONAL );
+    pci_unmap_sg( privdata->pdev, sg, nr_pages, PCI_DMA_BIDIRECTIONAL );
 umem_sgmap_unmap:
-	/* release pages */
-	if (nr_pages > 0) {
-		for(i=0;i<nr_pages;i++) {
-			if (PageLocked(pages[i]))
-				compat_unlock_page(pages[i]);
-			if (!PageReserved(pages[i]))
-				set_page_dirty(pages[i]);
-			page_cache_release(pages[i]);
-		}
-	}
-	vfree(sg);
+    /* release pages */
+    if (nr_pages > 0) {
+        for(i=0; i<nr_pages; i++) {
+            if (PageLocked(pages[i]))
+                __clear_page_locked(pages[i]);
+            if (!PageReserved(pages[i]))
+                set_page_dirty(pages[i]);
+            page_cache_release(pages[i]);
+        }
+    }
+    vfree(sg);
 umem_sgmap_pages:
-	vfree(pages);
-	return -ENOMEM;
+    vfree(pages);
+    return -ENOMEM;
 
 }
 
@@ -189,39 +184,39 @@ umem_sgmap_pages:
  */
 int pcidriver_umem_sgunmap(pcidriver_privdata_t *privdata, pcidriver_umem_entry_t *umem_entry)
 {
-	int i;
-	pcidriver_sysfs_remove(privdata, &(umem_entry->sysfs_attr));
-
-	/* Unmap user memory */
-	pci_unmap_sg( privdata->pdev, umem_entry->sg, umem_entry->nr_pages, PCI_DMA_BIDIRECTIONAL );
-
-	/* Release the pages */
-	if (umem_entry->nr_pages > 0) {
-		for(i=0;i<(umem_entry->nr_pages);i++) {
-			/* 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]);
-			}
-			/* and release it from the cache */
-			page_cache_release( umem_entry->pages[i] );
-		}
-	}
-
-	/* Remove the umem list entry */
-	spin_lock( &(privdata->umemlist_lock) );
-	list_del( &(umem_entry->list) );
-	spin_unlock( &(privdata->umemlist_lock) );
-
-	/* Release SG list and page list memory */
-	/* These two are in the vm area of the kernel */
-	vfree(umem_entry->pages);
-	vfree(umem_entry->sg);
-
-	/* Release umem_entry memory */
-	kfree(umem_entry);
-
-	return 0;
+    int i;
+    pcidriver_sysfs_remove(privdata, &(umem_entry->sysfs_attr));
+
+    /* Unmap user memory */
+    pci_unmap_sg( privdata->pdev, umem_entry->sg, umem_entry->nr_pages, PCI_DMA_BIDIRECTIONAL );
+
+    /* Release the pages */
+    if (umem_entry->nr_pages > 0) {
+        for(i=0; i<(umem_entry->nr_pages); i++) {
+            /* Mark pages as Dirty and unlock it */
+            if ( !PageReserved( umem_entry->pages[i] )) {
+                SetPageDirty( umem_entry->pages[i] );
+                __clear_page_locked(umem_entry->pages[i]);
+            }
+            /* and release it from the cache */
+            page_cache_release( umem_entry->pages[i] );
+        }
+    }
+
+    /* Remove the umem list entry */
+    spin_lock( &(privdata->umemlist_lock) );
+    list_del( &(umem_entry->list) );
+    spin_unlock( &(privdata->umemlist_lock) );
+
+    /* Release SG list and page list memory */
+    /* These two are in the vm area of the kernel */
+    vfree(umem_entry->pages);
+    vfree(umem_entry->sg);
+
+    /* Release umem_entry memory */
+    kfree(umem_entry);
+
+    return 0;
 }
 
 /**
@@ -231,16 +226,16 @@ int pcidriver_umem_sgunmap(pcidriver_privdata_t *privdata, pcidriver_umem_entry_
  */
 int pcidriver_umem_sgunmap_all(pcidriver_privdata_t *privdata)
 {
-	struct list_head *ptr, *next;
-	pcidriver_umem_entry_t *umem_entry;
+    struct list_head *ptr, *next;
+    pcidriver_umem_entry_t *umem_entry;
 
-	/* iterate safely over the entries and delete them */
-	list_for_each_safe( ptr, next, &(privdata->umem_list) ) {
-		umem_entry = list_entry(ptr, pcidriver_umem_entry_t, list );
-		pcidriver_umem_sgunmap( privdata, umem_entry ); 		/* spin lock inside! */
-	}
+    /* iterate safely over the entries and delete them */
+    list_for_each_safe( ptr, next, &(privdata->umem_list) ) {
+        umem_entry = list_entry(ptr, pcidriver_umem_entry_t, list );
+        pcidriver_umem_sgunmap( privdata, umem_entry ); 		/* spin lock inside! */
+    }
 
-	return 0;
+    return 0;
 }
 
 /**
@@ -250,117 +245,68 @@ int pcidriver_umem_sgunmap_all(pcidriver_privdata_t *privdata)
  */
 int pcidriver_umem_sgget(pcidriver_privdata_t *privdata, umem_sglist_t *umem_sglist)
 {
-	int i;
-	pcidriver_umem_entry_t *umem_entry;
-	struct scatterlist *sg;
-	int idx = 0;
-	dma_addr_t cur_addr;
-	unsigned int cur_size;
-
-	/* Find the associated umem_entry for this buffer */
-	umem_entry = pcidriver_umem_find_entry_id( privdata, umem_sglist->handle_id );
-	if (umem_entry == NULL)
-		return -EINVAL;					/* umem_handle is not valid */
-
-	/* Check if passed SG list is enough */
-	if (umem_sglist->nents < umem_entry->nents)
-		return -EINVAL;					/* sg has not enough entries */
-
-	/* Copy the SG list to the user format */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
-	if (umem_sglist->type == PCIDRIVER_SG_MERGED) {
-		for_each_sg(umem_entry->sg, sg, umem_entry->nents, i ) {
-			if (i==0) {
-				umem_sglist->sg[0].addr = sg_dma_address( sg );
-				umem_sglist->sg[0].size = sg_dma_len( sg );
-				idx = 0;
-			}
-			else {
-				cur_addr = sg_dma_address( sg );
-				cur_size = sg_dma_len( sg );
-
-				/* Check if entry fits after current entry */
-				if (cur_addr == (umem_sglist->sg[idx].addr + umem_sglist->sg[idx].size)) {
-					umem_sglist->sg[idx].size += cur_size;
-					continue;
-				}
-
-				/* Skip if the entry is zero-length (yes, it can happen.... at the end of the list) */
-				if (cur_size == 0)
-					continue;
-
-				/* None of the above, add new entry */
-				idx++;
-				umem_sglist->sg[idx].addr = cur_addr;
-				umem_sglist->sg[idx].size = cur_size;
-			}
-		}
-		/* Set the used size of the SG list */
-		umem_sglist->nents = idx+1;
-	} else {
-		for_each_sg(umem_entry->sg, sg, umem_entry->nents, i ) {
-			mod_info("entry: %d\n",i);
-			umem_sglist->sg[i].addr = sg_dma_address( sg );
-			umem_sglist->sg[i].size = sg_dma_len( sg );
-		}
-
-		/* Set the used size of the SG list */
-		/* Check if the last one is zero-length */
-		if ( umem_sglist->sg[ umem_entry->nents - 1].size == 0)
-			umem_sglist->nents = umem_entry->nents -1;
-		else
-			umem_sglist->nents = umem_entry->nents;
-	}
-#else
-	if (umem_sglist->type == PCIDRIVER_SG_MERGED) {
-		/* Merge entries that are contiguous into a single entry */
-		/* Non-optimal but fast for most cases */
-		/* First one always true */
-		sg=umem_entry->sg;
-		umem_sglist->sg[0].addr = sg_dma_address( sg );
-		umem_sglist->sg[0].size = sg_dma_len( sg );
-		sg++;
-		idx = 0;
-
-		/* Iterate over the SG entries */
-		for(i=1; i< umem_entry->nents; i++, sg++ ) {
-			cur_addr = sg_dma_address( sg );
-			cur_size = sg_dma_len( sg );
-
-			/* Check if entry fits after current entry */
-			if (cur_addr == (umem_sglist->sg[idx].addr + umem_sglist->sg[idx].size)) {
-				umem_sglist->sg[idx].size += cur_size;
-				continue;
-			}
-
-			/* Skip if the entry is zero-length (yes, it can happen.... at the end of the list) */
-			if (cur_size == 0)
-				continue;
-
-			/* None of the above, add new entry */
-			idx++;
-			umem_sglist->sg[idx].addr = cur_addr;
-			umem_sglist->sg[idx].size = cur_size;
-		}
-		/* Set the used size of the SG list */
-		umem_sglist->nents = idx+1;
-	} else {
-		/* Assume pci_map_sg made a good job (ehem..) and just copy it.
-		 * actually, now I assume it just gives them plainly to me. */
-		for(i=0, sg=umem_entry->sg ; i< umem_entry->nents; i++, sg++ ) {
-			umem_sglist->sg[i].addr = sg_dma_address( sg );
-			umem_sglist->sg[i].size = sg_dma_len( sg );
-		}
-		/* Set the used size of the SG list */
-		/* Check if the last one is zero-length */
-		if ( umem_sglist->sg[ umem_entry->nents - 1].size == 0)
-			umem_sglist->nents = umem_entry->nents -1;
-		else
-			umem_sglist->nents = umem_entry->nents;
-	}
-#endif
-
-	return 0;
+    int i;
+    pcidriver_umem_entry_t *umem_entry;
+    struct scatterlist *sg;
+    int idx = 0;
+    dma_addr_t cur_addr;
+    unsigned int cur_size;
+
+    /* Find the associated umem_entry for this buffer */
+    umem_entry = pcidriver_umem_find_entry_id( privdata, umem_sglist->handle_id );
+    if (umem_entry == NULL)
+        return -EINVAL;					/* umem_handle is not valid */
+
+    /* Check if passed SG list is enough */
+    if (umem_sglist->nents < umem_entry->nents)
+        return -EINVAL;					/* sg has not enough entries */
+
+    /* Copy the SG list to the user format */
+    if (umem_sglist->type == PCIDRIVER_SG_MERGED) {
+        for_each_sg(umem_entry->sg, sg, umem_entry->nents, i ) {
+            if (i==0) {
+                umem_sglist->sg[0].addr = sg_dma_address( sg );
+                umem_sglist->sg[0].size = sg_dma_len( sg );
+                idx = 0;
+            }
+            else {
+                cur_addr = sg_dma_address( sg );
+                cur_size = sg_dma_len( sg );
+
+                /* Check if entry fits after current entry */
+                if (cur_addr == (umem_sglist->sg[idx].addr + umem_sglist->sg[idx].size)) {
+                    umem_sglist->sg[idx].size += cur_size;
+                    continue;
+                }
+
+                /* Skip if the entry is zero-length (yes, it can happen.... at the end of the list) */
+                if (cur_size == 0)
+                    continue;
+
+                /* None of the above, add new entry */
+                idx++;
+                umem_sglist->sg[idx].addr = cur_addr;
+                umem_sglist->sg[idx].size = cur_size;
+            }
+        }
+        /* Set the used size of the SG list */
+        umem_sglist->nents = idx+1;
+    } else {
+        for_each_sg(umem_entry->sg, sg, umem_entry->nents, i ) {
+            mod_info("entry: %d\n",i);
+            umem_sglist->sg[i].addr = sg_dma_address( sg );
+            umem_sglist->sg[i].size = sg_dma_len( sg );
+        }
+
+        /* Set the used size of the SG list */
+        /* Check if the last one is zero-length */
+        if ( umem_sglist->sg[ umem_entry->nents - 1].size == 0)
+            umem_sglist->nents = umem_entry->nents -1;
+        else
+            umem_sglist->nents = umem_entry->nents;
+    }
+
+    return 0;
 }
 
 /**
@@ -370,45 +316,29 @@ int pcidriver_umem_sgget(pcidriver_privdata_t *privdata, umem_sglist_t *umem_sgl
  */
 int pcidriver_umem_sync( pcidriver_privdata_t *privdata, umem_handle_t *umem_handle )
 {
-	pcidriver_umem_entry_t *umem_entry;
-
-	/* Find the associated umem_entry for this buffer */
-	umem_entry = pcidriver_umem_find_entry_id( privdata, umem_handle->handle_id );
-	if (umem_entry == NULL)
-		return -EINVAL;					/* umem_handle is not valid */
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
-	switch (umem_handle->dir) {
-		case PCIDRIVER_DMA_TODEVICE:
-			pci_dma_sync_sg_for_device( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_TODEVICE );
-			break;
-		case PCIDRIVER_DMA_FROMDEVICE:
-			pci_dma_sync_sg_for_cpu( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_FROMDEVICE );
-			break;
-		case PCIDRIVER_DMA_BIDIRECTIONAL:
-			pci_dma_sync_sg_for_device( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_BIDIRECTIONAL );
-			pci_dma_sync_sg_for_cpu( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_BIDIRECTIONAL );
-			break;
-		default:
-			return -EINVAL;				/* wrong direction parameter */
-	}
-#else
-	switch (umem_handle->dir) {
-		case PCIDRIVER_DMA_TODEVICE:
-			pci_dma_sync_sg( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_TODEVICE );
-			break;
-		case PCIDRIVER_DMA_FROMDEVICE:
-			pci_dma_sync_sg( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_FROMDEVICE );
-			break;
-		case PCIDRIVER_DMA_BIDIRECTIONAL:
-			pci_dma_sync_sg( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_BIDIRECTIONAL );
-			break;
-		default:
-			return -EINVAL;				/* wrong direction parameter */
-	}
-#endif
-
-	return 0;
+    pcidriver_umem_entry_t *umem_entry;
+
+    /* Find the associated umem_entry for this buffer */
+    umem_entry = pcidriver_umem_find_entry_id( privdata, umem_handle->handle_id );
+    if (umem_entry == NULL)
+        return -EINVAL;					/* umem_handle is not valid */
+
+    switch (umem_handle->dir) {
+    case PCIDRIVER_DMA_TODEVICE:
+        pci_dma_sync_sg_for_device( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_TODEVICE );
+        break;
+    case PCIDRIVER_DMA_FROMDEVICE:
+        pci_dma_sync_sg_for_cpu( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_FROMDEVICE );
+        break;
+    case PCIDRIVER_DMA_BIDIRECTIONAL:
+        pci_dma_sync_sg_for_device( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_BIDIRECTIONAL );
+        pci_dma_sync_sg_for_cpu( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_BIDIRECTIONAL );
+        break;
+    default:
+        return -EINVAL;				/* wrong direction parameter */
+    }
+
+    return 0;
 }
 
 /*
@@ -420,19 +350,19 @@ int pcidriver_umem_sync( pcidriver_privdata_t *privdata, umem_handle_t *umem_han
  */
 pcidriver_umem_entry_t *pcidriver_umem_find_entry_id(pcidriver_privdata_t *privdata, int id)
 {
-	struct list_head *ptr;
-	pcidriver_umem_entry_t *entry;
+    struct list_head *ptr;
+    pcidriver_umem_entry_t *entry;
 
-	spin_lock(&(privdata->umemlist_lock));
-	list_for_each(ptr, &(privdata->umem_list)) {
-		entry = list_entry(ptr, pcidriver_umem_entry_t, list );
+    spin_lock(&(privdata->umemlist_lock));
+    list_for_each(ptr, &(privdata->umem_list)) {
+        entry = list_entry(ptr, pcidriver_umem_entry_t, list );
 
-		if (entry->id == id) {
-			spin_unlock( &(privdata->umemlist_lock) );
-			return entry;
-		}
-	}
+        if (entry->id == id) {
+            spin_unlock( &(privdata->umemlist_lock) );
+            return entry;
+        }
+    }
 
-	spin_unlock(&(privdata->umemlist_lock));
-	return NULL;
+    spin_unlock(&(privdata->umemlist_lock));
+    return NULL;
 }

+ 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 */

+ 11 - 2
pcilib/error.c

@@ -12,8 +12,17 @@
 #define PCILIB_LOGGER_HISTORY 16
 
 void pcilib_print_error(void *arg, const char *file, int line, pcilib_log_priority_t prio, const char *msg, va_list va) {
-    vprintf(msg, va);
-    printf(" [%s:%d]\n", file, line);
+    size_t size = strlen(msg) + strlen(file) + 64;
+    char *stmp = alloca(size * sizeof(char*));
+
+    if (stmp) {
+	sprintf(stmp, "%s [%s:%d]\n", msg, file, line);
+	vprintf(stmp, va);
+    } else {
+	    // Bad for multithreading...
+	vprintf(msg, va);
+	printf(" [%s:%d]\n", file, line);
+    }
 }
 
 static void *pcilib_logger_argument = NULL;

+ 104 - 103
pcilib/locking.c

@@ -102,117 +102,118 @@ pcilib_lock_t *pcilib_get_lock_by_id(pcilib_t *ctx, pcilib_lock_id_t id) {
 }
 
 pcilib_lock_t *pcilib_get_lock(pcilib_t *ctx, pcilib_lock_flags_t flags, const char  *lock_id, ...) {
-   pcilib_lock_id_t i;
-   int err, ret;
+    pcilib_lock_id_t i;
+    int err, ret;
+
+    pcilib_lock_t *lock;
+    char buffer[PCILIB_LOCK_SIZE];
 
-   pcilib_lock_t *lock;
-   char buffer[PCILIB_LOCK_SIZE];
+	/* we construct the complete lock_id given the parameters of the function*/
+    va_list pa;
+    va_start(pa, lock_id);
+    ret = vsnprintf(buffer, PCILIB_LOCK_SIZE, lock_id, pa);
+    va_end(pa);
 
-   /* we construct the complete lock_id given the parameters of the function*/
-   va_list pa;
-   va_start(pa, lock_id);
-   ret = vsnprintf(buffer, PCILIB_LOCK_SIZE, lock_id, pa);
-   va_end(pa);
+    if (ret < 0) {
+	pcilib_error("Failed to construct the lock id, probably arguments does not match the format string (%s)...", lock_id);
+	return NULL;
+    }
+	
+	
+	/* we iterate through locks to see if there is one already with the same name*/	
+	// Would be nice to have hash here
+    for (i = 0; i < PCILIB_MAX_LOCKS; i++) {
+	lock = pcilib_get_lock_by_id(ctx, i);
 
-   if (ret < 0) {
-      pcilib_error("Failed to construct the lock id, probably arguments does not match the format string (%s)...", lock_id);
-      return NULL;
-   }
+        const char *name = pcilib_lock_get_name(lock);
+	if (!name) break;
+	
+	if (!strcmp(buffer, name)) {
+	    if ((pcilib_lock_get_flags(lock)&PCILIB_LOCK_FLAG_PERSISTENT) != (flags&PCILIB_LOCK_FLAG_PERSISTENT)) {
+		if (flags&PCILIB_LOCK_FLAG_PERSISTENT)
+		    pcilib_error("Requesting persistent lock (%s), but requested lock is already existing and is robust", name);
+		else
+		    pcilib_error("Requesting robust lock (%s), but requested lock is already existing and is persistent", name);
+		return NULL;
+	    }
 
+#ifndef HAVE_STDATOMIC_H
+	    if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0) {
+		err = pcilib_lock(ctx->locks.locking);
+		if (err) {
+		    pcilib_error("Error (%i) obtaining global lock", err);
+		    return NULL;
+		}
+	    }
+#endif /* ! HAVE_STDATOMIC_H */
+	/* if yes, we increment its ref variable*/
+	    pcilib_lock_ref(lock);
+#ifndef HAVE_STDATOMIC_H
+	    if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0)
+		pcilib_unlock(ctx->locks.locking);
+#endif /* ! HAVE_STDATOMIC_H */
 
-   /* we iterate through locks to see if there is one already with the same name*/	
-   // Would be nice to have hash here
-   for (i = 0; i < PCILIB_MAX_LOCKS; i++) {
-      lock = pcilib_get_lock_by_id(ctx, i);
+	    return lock;
+	}
+    }
 
-      const char *name = pcilib_lock_get_name(lock);
-      if (!name) break;
+    if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0) {
+	err = pcilib_lock(ctx->locks.locking);
+	if (err) {
+	    pcilib_error("Error (%i) obtaining global lock", err);
+	    return NULL;
+	}
+    }
 
-      if (!strcmp(buffer, name)) {
-         if ((pcilib_lock_get_flags(lock)&PCILIB_LOCK_FLAG_PERSISTENT) != (flags&PCILIB_LOCK_FLAG_PERSISTENT)) {
-            if (flags&PCILIB_LOCK_FLAG_PERSISTENT)
-               pcilib_error("Requesting persistent lock (%s), but requested lock is already existing and is robust", name);
-            else
-               pcilib_error("Requesting robust lock (%s), but requested lock is already existing and is persistent", name);
-            return NULL;
-         }
+	// Make sure it was not allocated meanwhile
+    for (; i < PCILIB_MAX_LOCKS; i++) {
+	lock = pcilib_get_lock_by_id(ctx, i);
 
-#ifndef HAVE_STDATOMIC_H
-         if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0) {
-            err = pcilib_lock(ctx->locks.locking);
-            if (err) {
-               pcilib_error("Error (%i) obtaining global lock", err);
-               return NULL;
-            }
-         }
-#endif /* ! HAVE_STDATOMIC_H */
-         /* if yes, we increment its ref variable*/
-         pcilib_lock_ref(lock);
-         #ifndef HAVE_STDATOMIC_H
-         if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0)
-            pcilib_unlock(ctx->locks.locking);
-         #endif /* ! HAVE_STDATOMIC_H */
-         return lock;
-      }
-   }
-
-   if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0) {
-      err = pcilib_lock(ctx->locks.locking);
-      if (err) {
-         pcilib_error("Error (%i) obtaining global lock", err);
-         return NULL;
-      }
-   }
-
-   // Make sure it was not allocated meanwhile
-   for (; i < PCILIB_MAX_LOCKS; i++) {
-      lock = pcilib_get_lock_by_id(ctx, i);
-
-      const char *name = pcilib_lock_get_name(lock);
-      if (!name) break;
-
-      if (!strcmp(buffer, name)) {
-         if ((pcilib_lock_get_flags(lock)&PCILIB_LOCK_FLAG_PERSISTENT) != (flags&PCILIB_LOCK_FLAG_PERSISTENT)) {
-            if (flags&PCILIB_LOCK_FLAG_PERSISTENT)
-               pcilib_error("Requesting persistent lock (%s), but requested lock is already existing and is robust", name);
-            else
-               pcilib_error("Requesting robust lock (%s), but requested lock is already existing and is persistent", name);
-
-            if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0)
-               pcilib_unlock(ctx->locks.locking);
-            return NULL;
-         }
-
-         pcilib_lock_ref(lock);
-         if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0)
-            pcilib_unlock(ctx->locks.locking);
-         return lock;
-      }
-   }
-
-   if (i == PCILIB_MAX_LOCKS) {
-      if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0)
-         pcilib_unlock(ctx->locks.locking);
-      pcilib_error("Failed to create lock (%s), only %u locks is supported", buffer, PCILIB_MAX_LOCKS);
-      return NULL;
-   }
-
-   /* if the lock did not exist before, then we create it*/
-   err = pcilib_init_lock(lock, flags, buffer);
-
-   if (err) {
-      pcilib_error("Lock initialization failed with error %i", err);
-
-      if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0)
-         pcilib_unlock(ctx->locks.locking);
-
-      return NULL;
-   }
-
-   if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0)
-      pcilib_unlock(ctx->locks.locking);
-
-   return lock;
+        const char *name = pcilib_lock_get_name(lock);
+	if (!name) break;
+
+	if (!strcmp(buffer, name)) {
+	    if ((pcilib_lock_get_flags(lock)&PCILIB_LOCK_FLAG_PERSISTENT) != (flags&PCILIB_LOCK_FLAG_PERSISTENT)) {
+		if (flags&PCILIB_LOCK_FLAG_PERSISTENT)
+		    pcilib_error("Requesting persistent lock (%s), but requested lock is already existing and is robust", name);
+		else
+		    pcilib_error("Requesting robust lock (%s), but requested lock is already existing and is persistent", name);
+		
+		if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0)
+		    pcilib_unlock(ctx->locks.locking);
+		return NULL;
+	    }
+
+	    pcilib_lock_ref(lock);
+	    if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0)
+		pcilib_unlock(ctx->locks.locking);
+	    return lock;
+	}
+    }
+
+    if (i == PCILIB_MAX_LOCKS) {
+	if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0)
+	    pcilib_unlock(ctx->locks.locking);
+	pcilib_error("Failed to create lock (%s), only %u locks is supported", buffer, PCILIB_MAX_LOCKS);
+	return NULL;
+    }
+
+	/* if the lock did not exist before, then we create it*/
+    err = pcilib_init_lock(lock, flags, buffer);
+    
+    if (err) {
+	pcilib_error("Lock initialization failed with error %i", err);
+
+	if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0)
+	    pcilib_unlock(ctx->locks.locking);
+	
+	return NULL;
+    }
+    
+    if ((flags&PCILIB_LOCK_FLAG_UNLOCKED)==0)
+	pcilib_unlock(ctx->locks.locking);
+
+    return lock;
 }
 
 void pcilib_return_lock(pcilib_t *ctx, pcilib_lock_flags_t flags, pcilib_lock_t *lock) {

+ 9 - 10
pcilib/pci.c

@@ -147,9 +147,8 @@ pcilib_t *pcilib_open(const char *device, const char *model) {
 	
 	err = pcilib_init_py(ctx);
 	if (err) {
-	    pcilib_error("Error (%i) initializing python subsystem", err);
-	    pcilib_close(ctx);
-	    return NULL;
+	    pcilib_warning("Error (%i) initializing python subsystem", err);
+	    pcilib_free_py(ctx);
 	}
 
 	ctx->alloc_reg = PCILIB_DEFAULT_REGISTER_SPACE;
@@ -191,22 +190,22 @@ pcilib_t *pcilib_open(const char *device, const char *model) {
 
 	if (!ctx->model)
 	    ctx->model = strdup(model?model:"pci");
-	    
+
 	err = pcilib_py_add_script_dir(ctx, NULL);
 	if (err) {
-	    pcilib_error("Error (%i) add script path to python path", err);
-	    pcilib_close(ctx);
-	    return NULL;
+	    pcilib_warning("Error (%i) add script path to python path", err);
+	    pcilib_free_py(ctx);
+	    err = 0;
 	}
-	
-	
+
+
 	xmlerr = pcilib_init_xml(ctx, ctx->model);
 	if ((xmlerr)&&(xmlerr != PCILIB_ERROR_NOTFOUND)) {
 	    pcilib_error("Error (%i) initializing XML subsystem for model %s", xmlerr, ctx->model);
 	    pcilib_close(ctx);
 	    return NULL;
 	}
-	
+
 
 	    // We have found neither standard model nor XML
 	if ((err)&&(xmlerr)) {

+ 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 */

+ 2 - 2
pcilib/property.c

@@ -226,8 +226,8 @@ pcilib_property_info_t *pcilib_get_property_list(pcilib_t *ctx, const char *bran
     }
 
     HASH_ITER(hh, dir_hash, dir, dir_tmp) {
-        HASH_DEL(dir_hash, dir);
-        free(dir);
+	HASH_DEL(dir_hash, dir);
+	free(dir);
     }
     HASH_CLEAR(hh, dir_hash);
 

+ 185 - 156
pcilib/py.c

@@ -17,6 +17,8 @@
 #include "error.h"
 
 #ifdef HAVE_PYTHON
+#define PCILIB_PYTHON_WRAPPER "pcipywrap"
+
 typedef struct pcilib_script_s pcilib_script_t;
 
 struct pcilib_script_s {
@@ -43,59 +45,70 @@ void pcilib_log_python_error(const char *file, int line, pcilib_log_flags_t flag
     PyGILState_STATE gstate;
     PyObject *pytype = NULL;
     PyObject *pyval = NULL;
+    PyObject *pystr = NULL;
     PyObject *pytraceback = NULL;
 
 
     gstate = PyGILState_Ensure();
     if (PyErr_Occurred()) {
-      PyErr_Fetch(&pytype, &pyval, &pytraceback);
-      
-#if PY_MAJOR_VERSION >= 3
-    type = PyUnicode_AsUTF8(pytype);
-    val = PyUnicode_AsUTF8(pyval);
-#else /*PY_MAJOR_VERSION >= 3*/
-    PyObject *buf = PyUnicode_AsASCIIString(pytype);
-    type = PyString_AsString(buf);
-    Py_DecRef(buf);
-    
-    buf = PyUnicode_AsASCIIString(pyval);
-    val = PyString_AsString(buf);
-    Py_DecRef(buf);
-#endif /*PY_MAJOR_VERSION >= 3*/
-
-      
+	PyErr_Fetch(&pytype, &pyval, &pytraceback);
+	PyErr_NormalizeException(&pytype, &pyval, &pytraceback);
+	if (pyval) pystr = PyObject_Str(pyval);
+
+# if PY_MAJOR_VERSION >= 3
+	if (pytype) {
+	    if (PyUnicode_Check(pytype))
+		type = PyUnicode_AsUTF8(pytype);
+	    else
+		type = PyExceptionClass_Name(pytype);
+	}
+	if (pystr) {
+	    val = PyUnicode_AsUTF8(pystr);
+	}
+# else /* PY_MAJOR_VERSION >= 3 */
+	if (pytype) {
+	    if (PyString_Check(pytype))
+		type = PyString_AsString(pytype);
+	    else
+		type = PyExceptionClass_Name(pytype);
+	}
+	if (pystr) {
+	    val = PyString_AsString(pystr);
+	}
+# endif /*PY_MAJOR_VERSION >= 3*/
     }
     PyGILState_Release(gstate);
 #endif /* HAVE_PYTHON */
-    
+
     va_start(va, msg);
     if (type) {
-      char *str;
-      size_t len = 32;
-
-      if (msg) len += strlen(msg);
-      if (type) len += strlen(type);
-      if (val) len += strlen(val);
-          
-      str = alloca(len * sizeof(char));
-      if (str) {
-          if (msg&&val)
-         sprintf(str, "%s <%s: %s>", msg, type, val);
-          else if (msg)
-         sprintf(str, "%s <%s>", msg, type);
-          else if (val)
-         sprintf(str, "Python error %s: %s", type, val);
-          else
-         sprintf(str, "Python error %s", type);
-          
-          pcilib_log_vmessage(file, line, flags, prio, str, va);
-      }
+	char *str;
+	size_t len = 32;
+
+	if (msg) len += strlen(msg);
+	if (type) len += strlen(type);
+	if (val) len += strlen(val);
+	    
+	str = alloca(len * sizeof(char));
+	if (str) {
+	    if (msg&&val)
+		sprintf(str, "%s <%s: %s>", msg, type, val);
+	    else if (msg)
+		sprintf(str, "%s <%s>", msg, type);
+	    else if (val)
+		sprintf(str, "Python error %s: %s", type, val);
+	    else
+		sprintf(str, "Python error %s", type);
+	    
+	    pcilib_log_vmessage(file, line, flags, prio, str, va);
+	}
     } else  {
-	   pcilib_log_vmessage(file, line, flags, prio, msg, va);
+	pcilib_log_vmessage(file, line, flags, prio, msg, va);
     }
     va_end(va);
 
 #ifdef HAVE_PYTHON
+    if (pystr) Py_DECREF(pystr);
     if (pytype) Py_DECREF(pytype);
     if (pyval) Py_DECREF(pyval);
     if (pytraceback) Py_DECREF(pytraceback);
@@ -114,40 +127,39 @@ int pcilib_init_py(pcilib_t *ctx) {
     if(!Py_IsInitialized()) {
         Py_Initialize();
         
-        // Since python is being initializing from c programm, it needs to initialize threads to work properly with c threads
+    	    // Since python is being initializing from c programm, it needs to initialize threads to work properly with c threads
         PyEval_InitThreads();
         PyEval_ReleaseLock();
-        ctx->py->finalyze = 1;
+	ctx->py->finalyze = 1;
     }
 		
     ctx->py->main_module = PyImport_AddModule("__parser__");
     if (!ctx->py->main_module) {
-      pcilib_python_error("Error importing python parser");
-           return PCILIB_ERROR_FAILED;
+	pcilib_python_warning("Error importing python parser");
+        return PCILIB_ERROR_FAILED;
     }
 
     ctx->py->global_dict = PyModule_GetDict(ctx->py->main_module);
     if (!ctx->py->global_dict) {
-      pcilib_python_error("Error locating global python dictionary");
-           return PCILIB_ERROR_FAILED;
+	pcilib_python_warning("Error locating global python dictionary");
+        return PCILIB_ERROR_FAILED;
     }
 
-    PyObject *pywrap = PyImport_ImportModule("pcilib");
+    PyObject *pywrap = PyImport_ImportModule(PCILIB_PYTHON_WRAPPER);
     if (!pywrap) {
-      pcilib_python_error("Error importing pcilib python wrapper");
-      return PCILIB_ERROR_FAILED;
+	pcilib_python_warning("Error importing pcilib python wrapper");
+	return PCILIB_ERROR_FAILED;
     }
 	
-    PyObject *mod_name = PyUnicode_FromString("Pcilib");
+    PyObject *mod_name = PyUnicode_FromString(PCILIB_PYTHON_WRAPPER);
     PyObject *pyctx = PyCapsule_New(ctx, "pcilib", NULL);
-    
     ctx->py->pcilib_pywrap = PyObject_CallMethodObjArgs(pywrap, mod_name, pyctx, NULL);
     Py_XDECREF(pyctx);
     Py_XDECREF(mod_name);
 	
     if (!ctx->py->pcilib_pywrap) {
-      pcilib_python_error("Error initializing python wrapper");
-      return PCILIB_ERROR_FAILED;
+	pcilib_python_warning("Error initializing python wrapper");
+        return PCILIB_ERROR_FAILED;
     }
 #endif /* HAVE_PYTHON */
 
@@ -161,60 +173,61 @@ int pcilib_py_add_script_dir(pcilib_t *ctx, const char *dir) {
     PyObject *pydict, *pystr, *pyret = NULL;
     char *script_dir;
 
+    if (!ctx->py) return 0;
+
     const char *model_dir = getenv("PCILIB_MODEL_DIR");
     if (!model_dir) model_dir = PCILIB_MODEL_DIR;
 
     if (!dir) dir = ctx->model;
 
     if (*dir == '/') {
-	   script_dir = (char*)dir;
+	script_dir = (char*)dir;
     } else {
-      script_dir = alloca(strlen(model_dir) + strlen(dir) + 2);
-      if (!script_dir) return PCILIB_ERROR_MEMORY;
-      sprintf(script_dir, "%s/%s", model_dir, dir);
+	script_dir = alloca(strlen(model_dir) + strlen(dir) + 2);
+	if (!script_dir) return PCILIB_ERROR_MEMORY;
+	sprintf(script_dir, "%s/%s", model_dir, dir);
     }
 
     pypath = PySys_GetObject("path");
     if (!pypath) {
-      pcilib_python_error("Can't get python path");
-      return PCILIB_ERROR_FAILED;
+	pcilib_python_warning("Can't get python path");
+	return PCILIB_ERROR_FAILED;
     }
 
     pynewdir = PyUnicode_FromString(script_dir);
-    
     if (!pynewdir) {
-      pcilib_python_error("Can't create python string");
-      return PCILIB_ERROR_MEMORY;
+	pcilib_python_warning("Can't create python string");
+	return PCILIB_ERROR_MEMORY;
     }
     
-	// Checking if the directory already in the path
+	// Checking if the directory already in the path?
     pydict = PyDict_New();
     if (pydict) {
-      pystr = PyUnicode_FromString("cur");
+	pystr = PyUnicode_FromString("cur");
         if (pystr) {
-          PyDict_SetItem(pydict, pystr, pynewdir);
-          Py_DECREF(pystr);
-      }
-
-      pystr = PyUnicode_FromString("path");
-      if (pystr) {
-          PyDict_SetItem(pydict, pystr, pypath);
-          Py_DECREF(pystr);
-      }
-
-      pyret = PyRun_String("cur in path", Py_eval_input, ctx->py->global_dict, pydict);
-      Py_DECREF(pydict);
+	    PyDict_SetItem(pydict, pystr, pynewdir);
+	    Py_DECREF(pystr);
+	}
+
+	pystr = PyUnicode_FromString("path");
+	if (pystr) {
+	    PyDict_SetItem(pydict, pystr, pypath);
+	    Py_DECREF(pystr);
+	}
+
+	pyret = PyRun_String("cur in path", Py_eval_input, ctx->py->global_dict, pydict);
+	Py_DECREF(pydict);
     } 
 
     if ((pyret == Py_False)&&(PyList_Append(pypath, pynewdir) == -1))
-	   err = PCILIB_ERROR_FAILED;
+	err = PCILIB_ERROR_FAILED;
 
     if (pyret) Py_DECREF(pyret);
     Py_DECREF(pynewdir);
 
     if (err) {
-      pcilib_python_error("Can't add directory (%s) to python path", script_dir);
-      return err;
+	pcilib_python_warning("Can't add directory (%s) to python path", script_dir);
+	return err;
     }
 #endif /* HAVE_PYTHON */
 
@@ -226,24 +239,24 @@ void pcilib_free_py(pcilib_t *ctx) {
     int finalyze = 0;
 	
     if (ctx->py) {		
-      if (ctx->py->finalyze) finalyze = 1;
-
-      if (ctx->py->script_hash) {
-          pcilib_script_t *script, *script_tmp;
-
-          HASH_ITER(hh, ctx->py->script_hash, script, script_tmp) {
-         Py_DECREF(script->module);
-         HASH_DEL(ctx->py->script_hash, script);
-         free(script);
-          }
-          ctx->py->script_hash = NULL;
-      }
-
-      if (ctx->py->pcilib_pywrap)
-          Py_DECREF(ctx->py->pcilib_pywrap);
-      
-           free(ctx->py);
-           ctx->py = NULL;
+	if (ctx->py->finalyze) finalyze = 1;
+
+	if (ctx->py->script_hash) {
+	    pcilib_script_t *script, *script_tmp;
+
+	    HASH_ITER(hh, ctx->py->script_hash, script, script_tmp) {
+		Py_DECREF(script->module);
+		HASH_DEL(ctx->py->script_hash, script);
+		free(script);
+	    }
+	    ctx->py->script_hash = NULL;
+	}
+
+	if (ctx->py->pcilib_pywrap)
+	    Py_DECREF(ctx->py->pcilib_pywrap);
+	
+        free(ctx->py);
+        ctx->py = NULL;
     }
     
     if (finalyze)
@@ -256,14 +269,15 @@ int pcilib_py_load_script(pcilib_t *ctx, const char *script_name) {
     PyObject* pymodule;
     pcilib_script_t *module = NULL;
 
+    if (!ctx->py) return 0;
 
     char *module_name = strdupa(script_name);
     if (!module_name) return PCILIB_ERROR_MEMORY;
 
     char *py = strrchr(module_name, '.');
     if ((!py)||(strcasecmp(py, ".py"))) {
-      pcilib_error("Invalid script name (%s) is specified", script_name);
-      return PCILIB_ERROR_INVALID_ARGUMENT;
+	pcilib_error("Invalid script name (%s) is specified", script_name);
+	return PCILIB_ERROR_INVALID_ARGUMENT;
     }
     *py = 0;
 
@@ -272,8 +286,8 @@ int pcilib_py_load_script(pcilib_t *ctx, const char *script_name) {
 
     pymodule = PyImport_ImportModule(module_name);
     if (!pymodule) {
-      pcilib_python_error("Error importing script (%s)", script_name);
-      return PCILIB_ERROR_FAILED;
+	pcilib_python_error("Error importing script (%s)", script_name);
+	return PCILIB_ERROR_FAILED;
     }
 
     module = (pcilib_script_t*)malloc(sizeof(pcilib_script_t));
@@ -293,30 +307,35 @@ int pcilib_py_get_transform_script_properties(pcilib_t *ctx, const char *script_
     PyObject *dict;
     PyObject *pystr;
     pcilib_script_t *module;
-	
+
+    if (!ctx->py) {
+	if (mode_ret) *mode_ret = mode;
+	return 0;
+    }
+
     HASH_FIND_STR(ctx->py->script_hash, script_name, module);
 
     if(!module) {
-      pcilib_error("Script (%s) is not loaded yet", script_name);
-      return PCILIB_ERROR_NOTFOUND;
+	pcilib_error("Script (%s) is not loaded yet", script_name);
+	return PCILIB_ERROR_NOTFOUND;
     }
 	
     dict = PyModule_GetDict(module->module);
     if (!dict) {
-      pcilib_python_error("Error getting dictionary for script (%s)", script_name);
-      return PCILIB_ERROR_FAILED;
+	pcilib_python_error("Error getting dictionary for script (%s)", script_name);
+	return PCILIB_ERROR_FAILED;
     }
     
     pystr = PyUnicode_FromString("read_from_register");
     if (pystr) {
-      if (PyDict_Contains(dict, pystr)) mode |= PCILIB_ACCESS_R;
-      Py_DECREF(pystr);
+	if (PyDict_Contains(dict, pystr)) mode |= PCILIB_ACCESS_R;
+	Py_DECREF(pystr);
     }
 
     pystr = PyUnicode_FromString("write_to_register");
     if (pystr) {
-      if (PyDict_Contains(dict, pystr)) mode |= PCILIB_ACCESS_W;
-      Py_DECREF(pystr);
+	if (PyDict_Contains(dict, pystr)) mode |= PCILIB_ACCESS_W;
+	Py_DECREF(pystr);
     }
 #endif /* HAVE_PYTHON */
 
@@ -332,31 +351,33 @@ pcilib_py_object *pcilib_get_value_as_pyobject(pcilib_t* ctx, pcilib_value_t *va
 
     long ival;
     double fval;
-	
+
+    if (!ctx->py) return NULL;
+
     gstate = PyGILState_Ensure();
     switch(val->type) {
-        case PCILIB_TYPE_LONG:
-      ival = pcilib_get_value_as_int(ctx, val, &err);
-      if (!err) res = (PyObject*)PyLong_FromLong(ival);
-      break;
-        case PCILIB_TYPE_DOUBLE:
-      fval = pcilib_get_value_as_float(ctx, val, &err);
-      if (!err) res = (PyObject*)PyFloat_FromDouble(fval);
-      break;	
-        default:
-      PyGILState_Release(gstate);
-      pcilib_error("Can't convert pcilib value of type (%lu) to PyObject", val->type);
-      if (ret) *ret = PCILIB_ERROR_NOTSUPPORTED;
-      return NULL;
+     case PCILIB_TYPE_LONG:
+	ival = pcilib_get_value_as_int(ctx, val, &err);
+	if (!err) res = (PyObject*)PyLong_FromLong(ival);
+	break;
+     case PCILIB_TYPE_DOUBLE:
+	fval = pcilib_get_value_as_float(ctx, val, &err);
+	if (!err) res = (PyObject*)PyFloat_FromDouble(fval);
+	break;	
+     default:
+	PyGILState_Release(gstate);
+	pcilib_error("Can't convert pcilib value of type (%lu) to PyObject", val->type);
+	if (ret) *ret = PCILIB_ERROR_NOTSUPPORTED;
+	return NULL;
     }
     PyGILState_Release(gstate);
 
     if (err) {
-      if (ret) *ret = err;
-      return NULL;
+	if (ret) *ret = err;
+	return NULL;
     } else if (!res) {
-      if (ret) *ret = PCILIB_ERROR_MEMORY;
-      return res;
+	if (ret) *ret = PCILIB_ERROR_MEMORY;
+	return res;
     } 
 
     if (ret) *ret = 0;
@@ -372,27 +393,31 @@ int pcilib_set_value_from_pyobject(pcilib_t* ctx, pcilib_value_t *val, pcilib_py
     int err = 0;
     PyObject *pyval = (PyObject*)pval;
     PyGILState_STATE gstate;
-	
+
+    if (!ctx->py) return PCILIB_ERROR_NOTINITIALIZED;
+
     gstate = PyGILState_Ensure();
-#if PY_MAJOR_VERSION < 3
-    if (PyInt_Check(pyval)) {
-      err = pcilib_set_value_from_int(ctx, val, PyInt_AsLong(pyval));
-    } else if (PyString_Check(pyval)) {
-      err = pcilib_set_value_from_string(ctx, val, PyString_AsString(pyval));
-    } else
-#endif /*PY_MAJOR_VERSION >= 3*/
     if (PyLong_Check(pyval)) {
         err = pcilib_set_value_from_int(ctx, val, PyLong_AsLong(pyval));
     } else if (PyFloat_Check(pyval)) {
         err = pcilib_set_value_from_float(ctx, val, PyFloat_AsDouble(pyval));
+#if PY_MAJOR_VERSION < 3
+    } else if (PyInt_Check(pyval)) {
+        err = pcilib_set_value_from_int(ctx, val, PyInt_AsLong(pyval));
+    } else if (PyString_Check(pyval)) {
+        err = pcilib_set_value_from_string(ctx, val, PyString_AsString(pyval));
     } else if (PyUnicode_Check(pyval)) {
-#if PY_MAJOR_VERSION >= 3
-        err = pcilib_set_value_from_string(ctx, val, PyUnicode_AsUTF8(pyval));
-#else /*PY_MAJOR_VERSION >= 3*/
         PyObject *buf = PyUnicode_AsASCIIString(pyval);
-        err = pcilib_set_value_from_string(ctx, val, PyString_AsString(buf));
-        Py_DecRef(buf);
-#endif /*PY_MAJOR_VERSION >= 3*/
+        if (buf) {
+    	    err = pcilib_set_value_from_string(ctx, val, PyString_AsString(buf));
+    	    Py_DecRef(buf);
+    	} else {
+    	    err = PCILIB_ERROR_FAILED;
+	}
+#else /* PY_MAJOR_VERSION < 3 */
+    } else if (PyUnicode_Check(pyval)) {
+        err = pcilib_set_value_from_string(ctx, val, PyUnicode_AsUTF8(pyval));
+#endif /* PY_MAJOR_VERSION < 3 */
     } else {
         PyGILState_Release(gstate);
         pcilib_error("Can't convert PyObject to polymorphic pcilib value");
@@ -453,7 +478,7 @@ static char *pcilib_py_parse_string(pcilib_t *ctx, const char *codestr, pcilib_v
         strcpy(dst + offset, cur);
         offset += reg - cur;
 
-        // find the end of the register name
+            // find the end of the register name
         reg++;
         if (*reg == '{') {
             reg++;
@@ -469,7 +494,7 @@ static char *pcilib_py_parse_string(pcilib_t *ctx, const char *codestr, pcilib_v
         save = reg[i];
         reg[i] = 0;
 
-        // determine replacement value
+            // determine replacement value
         if (!strcasecmp(reg, "value")) {
             if (!value) {
                 pcilib_error("Python formula (%s) relies on the value of register, but it is not provided", codestr);
@@ -497,7 +522,7 @@ static char *pcilib_py_parse_string(pcilib_t *ctx, const char *codestr, pcilib_v
         if (save == '}') i++;
         else reg[i] = save;
 
-        // Advance to the next register if any
+            // Advance to the next register if any
         cur = reg + i;
         reg = strchr(cur, '$');
     }
@@ -507,8 +532,8 @@ static char *pcilib_py_parse_string(pcilib_t *ctx, const char *codestr, pcilib_v
     free(src);
 
     if (err) {
-     free(dst);
-     return NULL;
+        free(dst);
+        return NULL;
     }
 
     return dst;
@@ -523,6 +548,8 @@ int pcilib_py_eval_string(pcilib_t *ctx, const char *codestr, pcilib_value_t *va
     char *code;
     PyObject* obj;
 
+    if (!ctx->py) return PCILIB_ERROR_NOTINITIALIZED;
+
     code = pcilib_py_parse_string(ctx, codestr, value);
     if (!code) {
         pcilib_error("Failed to parse registers in the code: %s", codestr);
@@ -559,25 +586,27 @@ int pcilib_py_eval_func(pcilib_t *ctx, const char *script_name, const char *func
     PyObject *pyval = NULL, *pyret;
     pcilib_script_t *module = NULL;
 
+    if (!ctx->py) return PCILIB_ERROR_NOTINITIALIZED;
+
     HASH_FIND_STR(ctx->py->script_hash, script_name, module);
 
     if (!module) {
-      pcilib_error("Script (%s) is not loaded", script_name);
-      return PCILIB_ERROR_NOTFOUND;
+	pcilib_error("Script (%s) is not loaded", script_name);
+	return PCILIB_ERROR_NOTFOUND;
     }
 
     if (val) {
-      pyval = pcilib_get_value_as_pyobject(ctx, val, &err);
-      if (err) return err;
+	pyval = pcilib_get_value_as_pyobject(ctx, val, &err);
+	if (err) return err;
     }
 
     PyGILState_STATE gstate = PyGILState_Ensure();
 
     pyfunc = PyUnicode_FromString(func_name);
     if (!pyfunc) {
-      if (pyval) Py_DECREF(pyval);
-      PyGILState_Release(gstate);
-      return PCILIB_ERROR_MEMORY;
+	if (pyval) Py_DECREF(pyval);
+	PyGILState_Release(gstate);
+	return PCILIB_ERROR_MEMORY;
     }
 
     pyret = PyObject_CallMethodObjArgs(module->module, pyfunc, ctx->py->pcilib_pywrap, pyval, NULL);
@@ -586,13 +615,13 @@ int pcilib_py_eval_func(pcilib_t *ctx, const char *script_name, const char *func
     Py_DECREF(pyval);
 	
     if (!pyret) {
-      PyGILState_Release(gstate);
-      pcilib_python_error("Error executing function (%s) of python script (%s)", func_name, script_name);
-      return PCILIB_ERROR_FAILED;
+	PyGILState_Release(gstate);
+	pcilib_python_error("Error executing function (%s) of python script (%s)", func_name, script_name);
+	return PCILIB_ERROR_FAILED;
     }
 
     if ((val)&&(pyret != Py_None))
-	   err = pcilib_set_value_from_pyobject(ctx, val, pyret);
+	err = pcilib_set_value_from_pyobject(ctx, val, pyret);
 
     Py_DECREF(pyret);
     PyGILState_Release(gstate);

+ 1 - 0
pcilib/py.h

@@ -5,6 +5,7 @@
 #include <pcilib/error.h>
 
 #define pcilib_python_error(...)	pcilib_log_python_error(__FILE__, __LINE__, PCILIB_LOG_DEFAULT, PCILIB_LOG_ERROR, __VA_ARGS__)
+#define pcilib_python_warning(...)	pcilib_log_python_error(__FILE__, __LINE__, PCILIB_LOG_DEFAULT, PCILIB_LOG_WARNING, __VA_ARGS__)
 
 typedef struct pcilib_py_s pcilib_py_t;
 typedef void pcilib_py_object;

+ 1 - 1
pyserver/api_server.py

@@ -516,7 +516,7 @@ class ApiServer(MultiThreadedHTTPServer):
       #redirect logs to exeption
       pcilib.redirect_logs_to_exeption()
       #pass Pcipywrap to to server handler
-      self.lib = pcilib.Pcilib(device, model)
+      self.lib = pcilib.pcilib(device, model)
       def handler(*args):
          PcilibServerHandler(self.lib, *args)
       MultiThreadedHTTPServer.__init__(self, adress, handler)

+ 0 - 0
xml/scripts/test_script.py → pyserver/scripts/test_script.py


+ 0 - 0
xml/scripts/test_script2.py → pyserver/scripts/test_script2.py


+ 0 - 1
pywrap/CMakeLists.txt

@@ -22,6 +22,5 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pcipywrap.py DESTINATION ${PYTHON_INST
 install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pcilib.py DESTINATION ${PYTHON_INSTALL_DIR})
 
 if (NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
-   file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/pcilib.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
    file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test_pcilib.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
 endif(NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)

+ 2 - 2
pywrap/pcilib.py

@@ -2,9 +2,9 @@ from pcipywrap import *
 import os
 import sys
 
-class Pcilib(Pcipywrap):
+class pcilib(pcipywrap):
    def __init__(s, *args):
-      Pcipywrap.__init__(s, *args)
+      pcipywrap.__init__(s, *args)
       
       #load scripts
       scripts_dir = os.environ.get('PCILIB_SCRIPTS_DIR')

+ 20 - 20
pywrap/pcipywrap.c

@@ -322,7 +322,7 @@ PyObject * pcilib_convert_register_info_to_pyobject(pcilib_t* ctx, pcilib_regist
 
 }
 
-Pcipywrap *new_Pcipywrap(const char* fpga_device, const char* model)
+pcipywrap *new_pcipywrap(const char* fpga_device, const char* model)
 {
     //opening device
     pcilib_t* ctx = pcilib_open(fpga_device, model);
@@ -331,14 +331,14 @@ Pcipywrap *new_Pcipywrap(const char* fpga_device, const char* model)
         set_python_exception("Failed pcilib_open(%s, %s)", fpga_device, model);
         return NULL;
     }
-    Pcipywrap *self;
-    self = (Pcipywrap *) malloc(sizeof(Pcipywrap));
+    pcipywrap *self;
+    self = (pcipywrap *) malloc(sizeof(pcipywrap));
     self->shared = 0;
     self->ctx = ctx;
     return self;
 }
 
-Pcipywrap *create_Pcipywrap(PyObject* ctx)
+pcipywrap *create_pcipywrap(PyObject* ctx)
 {
     if(!PyCapsule_CheckExact(ctx))
     {
@@ -346,22 +346,22 @@ Pcipywrap *create_Pcipywrap(PyObject* ctx)
         return NULL;
     }
 
-    Pcipywrap *self;
-    self = (Pcipywrap *) malloc(sizeof(Pcipywrap));
+    pcipywrap *self;
+    self = (pcipywrap *) malloc(sizeof(pcipywrap));
     self->shared = 1;
     self->ctx = PyCapsule_GetPointer(ctx, PyCapsule_GetName(ctx));
 
     return self;
 }
 
-void delete_Pcipywrap(Pcipywrap *self) {
+void delete_pcipywrap(pcipywrap *self) {
     if(!self->shared)
         pcilib_close(self->ctx);
 
     free(self);
 }
 
-PyObject* Pcipywrap_read_register(Pcipywrap *self, const char *regname, const char *bank)
+PyObject* pcipywrap_read_register(pcipywrap *self, const char *regname, const char *bank)
 {
     pcilib_value_t val = {0};
     pcilib_register_value_t reg_value;
@@ -385,7 +385,7 @@ PyObject* Pcipywrap_read_register(Pcipywrap *self, const char *regname, const ch
     return pcilib_get_value_as_pyobject(self->ctx, &val, NULL);
 }
 
-PyObject* Pcipywrap_write_register(Pcipywrap *self, PyObject* val, const char *regname, const char *bank)
+PyObject* pcipywrap_write_register(pcipywrap *self, PyObject* val, const char *regname, const char *bank)
 {
     pcilib_value_t val_internal = {0};
     pcilib_register_value_t reg_value;
@@ -419,7 +419,7 @@ PyObject* Pcipywrap_write_register(Pcipywrap *self, PyObject* val, const char *r
     return PyLong_FromLong((long)1);
 }
 
-PyObject* Pcipywrap_get_property(Pcipywrap *self, const char *prop)
+PyObject* pcipywrap_get_property(pcipywrap *self, const char *prop)
 {
     int err;
     pcilib_value_t val = {0};
@@ -435,7 +435,7 @@ PyObject* Pcipywrap_get_property(Pcipywrap *self, const char *prop)
     return pcilib_get_value_as_pyobject(self->ctx, &val, NULL);
 }
 
-PyObject* Pcipywrap_set_property(Pcipywrap *self, PyObject* val, const char *prop)
+PyObject* pcipywrap_set_property(pcipywrap *self, PyObject* val, const char *prop)
 {
     int err;
 
@@ -457,7 +457,7 @@ PyObject* Pcipywrap_set_property(Pcipywrap *self, PyObject* val, const char *pro
     return PyLong_FromLong((long)1);
 }
 
-PyObject* Pcipywrap_get_registers_list(Pcipywrap *self, const char *bank)
+PyObject* pcipywrap_get_registers_list(pcipywrap *self, const char *bank)
 {
    pcilib_register_info_t *list = pcilib_get_register_list(self->ctx, bank, PCILIB_LIST_FLAGS_DEFAULT);
 
@@ -477,7 +477,7 @@ PyObject* Pcipywrap_get_registers_list(Pcipywrap *self, const char *bank)
    return pyList;
 }
 
-PyObject* Pcipywrap_get_register_info(Pcipywrap *self, const char* reg,const char *bank)
+PyObject* pcipywrap_get_register_info(pcipywrap *self, const char* reg,const char *bank)
 {
     pcilib_register_info_t *info = pcilib_get_register_info(self->ctx, bank, reg, PCILIB_LIST_FLAGS_DEFAULT);
 
@@ -493,7 +493,7 @@ PyObject* Pcipywrap_get_register_info(Pcipywrap *self, const char* reg,const cha
     return py_info;
 }
 
-PyObject* Pcipywrap_get_property_list(Pcipywrap *self, const char* branch)
+PyObject* pcipywrap_get_property_list(pcipywrap *self, const char* branch)
 {
     pcilib_property_info_t *list = pcilib_get_property_list(self->ctx, branch, PCILIB_LIST_FLAGS_DEFAULT);
 
@@ -511,7 +511,7 @@ PyObject* Pcipywrap_get_property_list(Pcipywrap *self, const char* branch)
     return pyList;
 }
 
-PyObject* Pcipywrap_read_dma(Pcipywrap *self, unsigned char dma, size_t size)
+PyObject* pcipywrap_read_dma(pcipywrap *self, unsigned char dma, size_t size)
 {
     int err;
     void* buf = NULL;
@@ -532,7 +532,7 @@ PyObject* Pcipywrap_read_dma(Pcipywrap *self, unsigned char dma, size_t size)
     return py_buf;
 }
 
-PyObject* Pcipywrap_lock_global(Pcipywrap *self)
+PyObject* pcipywrap_lock_global(pcipywrap *self)
 {
     int err;
 
@@ -546,13 +546,13 @@ PyObject* Pcipywrap_lock_global(Pcipywrap *self)
     return PyLong_FromLong((long)1);
 }
 
-void Pcipywrap_unlock_global(Pcipywrap *self)
+void pcipywrap_unlock_global(pcipywrap *self)
 {
     pcilib_unlock_global(self->ctx);
     return;
 }
 
-PyObject* Pcipywrap_lock(Pcipywrap *self, const char *lock_id)
+PyObject* pcipywrap_lock(pcipywrap *self, const char *lock_id)
 {
     pcilib_lock_t* lock = pcilib_get_lock(self->ctx,
                                           PCILIB_LOCK_FLAG_PERSISTENT,
@@ -574,7 +574,7 @@ PyObject* Pcipywrap_lock(Pcipywrap *self, const char *lock_id)
     return PyLong_FromLong((long)1);
 }
 
-PyObject* Pcipywrap_try_lock(Pcipywrap *self, const char *lock_id)
+PyObject* pcipywrap_try_lock(pcipywrap *self, const char *lock_id)
 {
     pcilib_lock_t* lock = pcilib_get_lock(self->ctx,
                                           PCILIB_LOCK_FLAG_PERSISTENT,
@@ -595,7 +595,7 @@ PyObject* Pcipywrap_try_lock(Pcipywrap *self, const char *lock_id)
     return PyLong_FromLong((long)1);
 }
 
-PyObject* Pcipywrap_unlock(Pcipywrap *self, const char *lock_id)
+PyObject* pcipywrap_unlock(pcipywrap *self, const char *lock_id)
 {
     pcilib_lock_t* lock = pcilib_get_lock(self->ctx,
                                           PCILIB_LOCK_FLAG_PERSISTENT,

+ 18 - 18
pywrap/pcipywrap.h

@@ -8,7 +8,7 @@
 typedef struct {
     void* ctx;
     int shared;
-} Pcipywrap;
+} pcipywrap;
 
 /*!
  * \brief Redirect pcilib standart log stream to exeption text.
@@ -26,9 +26,9 @@ void redirect_logs_to_exeption();
  */
 PyObject* create_pcilib_instance(const char *fpga_device, const char *model);
 
-Pcipywrap *new_Pcipywrap(const char* fpga_device, const char* model);
-Pcipywrap *create_Pcipywrap(PyObject* ctx);
-void delete_Pcipywrap(Pcipywrap *self);
+pcipywrap *new_pcipywrap(const char* fpga_device, const char* model);
+pcipywrap *create_pcipywrap(PyObject* ctx);
+void delete_pcipywrap(pcipywrap *self);
 
 /*!
  * \brief Reads register value. Wrap for pcilib_read_register function.
@@ -36,7 +36,7 @@ void delete_Pcipywrap(Pcipywrap *self);
  * \param[in] bank should specify the bank name if register with the same name may occur in multiple banks, NULL otherwise
  * \return register value, can be integer or float type; NULL with exeption text, if failed.
  */
-PyObject* Pcipywrap_read_register(Pcipywrap *self, const char *regname, const char *bank);
+PyObject* pcipywrap_read_register(pcipywrap *self, const char *regname, const char *bank);
 
 /*!
  * \brief Writes value to register. Wrap for pcilib_write_register function.
@@ -45,14 +45,14 @@ PyObject* Pcipywrap_read_register(Pcipywrap *self, const char *regname, const ch
  * \param[in] bank should specify the bank name if register with the same name may occur in multiple banks, NULL otherwise
  * \return 1, serialized to PyObject or NULL with exeption text, if failed.
  */
-PyObject* Pcipywrap_write_register(Pcipywrap *self, PyObject* val, const char *regname, const char *bank);
+PyObject* pcipywrap_write_register(pcipywrap *self, PyObject* val, const char *regname, const char *bank);
 
 /*!
  * \brief Reads propety value. Wrap for pcilib_get_property function.
  * \param[in] prop property name (full name including path)
  * \return property value, can be integer or float type; NULL with exeption text, if failed.
  */
-PyObject* Pcipywrap_get_property(Pcipywrap *self, const char *prop);
+PyObject* pcipywrap_get_property(pcipywrap *self, const char *prop);
 
 /*!
  * \brief Writes value to property. Wrap for pcilib_set_property function.
@@ -60,27 +60,27 @@ PyObject* Pcipywrap_get_property(Pcipywrap *self, const char *prop);
  * \param[in] val Property value, that needs to be set. Can be int, float or string.
  * \return 1, serialized to PyObject or NULL with exeption text, if failed.
  */
-PyObject* Pcipywrap_set_property(Pcipywrap *self, PyObject* val, const char *prop);
-PyObject* Pcipywrap_get_registers_list(Pcipywrap *self, const char *bank);
-PyObject* Pcipywrap_get_register_info(Pcipywrap *self, const char* reg,const char *bank);
-PyObject* Pcipywrap_get_property_list(Pcipywrap *self, const char* branch);
+PyObject* pcipywrap_set_property(pcipywrap *self, PyObject* val, const char *prop);
+PyObject* pcipywrap_get_registers_list(pcipywrap *self, const char *bank);
+PyObject* pcipywrap_get_register_info(pcipywrap *self, const char* reg,const char *bank);
+PyObject* pcipywrap_get_property_list(pcipywrap *self, const char* branch);
 
-PyObject* Pcipywrap_read_dma(Pcipywrap *self, unsigned char dma, size_t size);
+PyObject* pcipywrap_read_dma(pcipywrap *self, unsigned char dma, size_t size);
 
-PyObject* Pcipywrap_lock_global(Pcipywrap *self);
-void Pcipywrap_unlock_global(Pcipywrap *self);
+PyObject* pcipywrap_lock_global(pcipywrap *self);
+void pcipywrap_unlock_global(pcipywrap *self);
 
 /*!
  * \brief Wrap for pcilib_lock
  * \param lock_id lock identificator
  * \warning This function should be called only under Python standart threading lock.
- * Otherwise it will stuck with more than 1 threads. See /xml/test/test_prop_mt.py
+ * Otherwise it will stuck with more than 1 threads. See /xml/test/test_prop4.py
  * for example.
  * \return 1, serialized to PyObject or NULL with exeption text, if failed.
  */
-PyObject* Pcipywrap_lock(Pcipywrap *self, const char *lock_id);
+PyObject* pcipywrap_lock(pcipywrap *self, const char *lock_id);
 
-PyObject* Pcipywrap_try_lock(Pcipywrap *self, const char *lock_id);
-PyObject* Pcipywrap_unlock(Pcipywrap *self, const char *lock_id);
+PyObject* pcipywrap_try_lock(pcipywrap *self, const char *lock_id);
+PyObject* pcipywrap_unlock(pcipywrap *self, const char *lock_id);
 
 #endif /* PCIPYWRAP_H */

+ 4 - 4
pywrap/pcipywrap.i

@@ -8,9 +8,9 @@ extern void redirect_logs_to_exeption();
 
 typedef struct {
 	%extend {
-		Pcipywrap(const char* fpga_device = "/dev/fpga0", const char* model = NULL);
-		Pcipywrap(PyObject* ctx){return create_Pcipywrap(ctx);}
-		~Pcipywrap();
+		pcipywrap(const char* fpga_device = "/dev/fpga0", const char* model = NULL);
+		pcipywrap(PyObject* ctx){return create_pcipywrap(ctx);}
+		~pcipywrap();
 	
 		PyObject* read_register(const char *regname = NULL, const char *bank = NULL);
 		PyObject* write_register(PyObject* val, const char *regname, const char *bank = NULL);
@@ -30,4 +30,4 @@ typedef struct {
 		PyObject* try_lock(const char *lock_id);
 		PyObject* unlock(const char *lock_id);
 	}
-} Pcipywrap;
+} pcipywrap;

+ 3 - 3
pywrap/test_pcilib.py

@@ -35,7 +35,7 @@ class test_pcilib():
       #create pcilib_instance
       self.device = device
       self.model = model
-      self.pcilib = pcilib.Pcilib(device, model)
+      self.pcilib = pcilib.pcilib(device, model)
       self.num_threads = num_threads
       self.write_percentage = write_percentage
       self.register = register
@@ -83,7 +83,7 @@ class test_pcilib():
       try:
          while(1):
             val = long(random.randint(0, 8096))
-            self.pcilib = pcilib.Pcilib(self.device, self.model)
+            self.pcilib = pcilib.pcilib(self.device, self.model)
             print(self.pcilib.get_property_list(self.branch))
             print(self.pcilib.get_register_info(self.register))
             print(self.pcilib.get_registers_list())
@@ -145,7 +145,7 @@ if __name__ == '__main__':
                      type="string", dest="device", default=str('/dev/fpga0'),
                      help="FPGA device (/dev/fpga0)")                     
    parser.add_option("-m", "--model",  action="store",
-                     type="string", dest="model", default=None,
+                     type="string", dest="model", default=str('test'),
                      help="Memory model (autodetected)")
    parser.add_option("-t", "--threads",  action="store",
                      type="int", dest="threads", default=150,

+ 1 - 5
run

@@ -2,8 +2,4 @@
 
 APP_PATH=`dirname $0`
 
-PYTHONPATH="$APP_PATH/pywrap:$PYTHONPATH" \
-PCILIB_MODEL_DIR="$APP_PATH/xml" \
-LD_LIBRARY_PATH="$APP_PATH/pcilib" \
-PCILIB_SCRIPTS_DIR="$APP_PATH/xml/scripts" \
-$*
+PYTHONPATH="$APP_PATH/pywrap:$PYTHONPATH" PCILIB_SCRIPTS_DIR="$APP_PATH/pyserver/scripts" PCILIB_MODEL_DIR="$APP_PATH/xml" LD_LIBRARY_PATH="$APP_PATH/pcilib" $*

+ 5 - 3
views/transform.c

@@ -18,7 +18,7 @@ static pcilib_view_context_t * pcilib_transform_view_init(pcilib_t *ctx, pcilib_
     pcilib_view_context_t *view_ctx;
     pcilib_transform_view_description_t *v = (pcilib_transform_view_description_t*)(ctx->views[view]);
 
-    if(v->script) {	
+    if (v->script) {
 	pcilib_access_mode_t mode = 0;
 		
 	err = pcilib_py_load_script(ctx, v->script);
@@ -39,11 +39,13 @@ static pcilib_view_context_t * pcilib_transform_view_init(pcilib_t *ctx, pcilib_
 
 	if (!v->read_from_reg) v->read_from_reg = "read_from_register";
 	if (!v->write_to_reg) v->write_to_reg = "write_to_register";
+    } else if (!ctx->py) {
+	v->base.mode &= (~PCILIB_REGISTER_RW);
     }
-	
+
     view_ctx = (pcilib_view_context_t*)malloc(sizeof(pcilib_view_context_t));
     if (view_ctx) memset(view_ctx, 0, sizeof(pcilib_view_context_t));
-    
+
     return view_ctx;
 }
 

+ 1 - 5
xml/test/props.xml

@@ -3,9 +3,5 @@
   <transform path="/test/prop1" register="test_prop1" unit="C" read_from_register="(503975./1024000)*${/registers/fpga/sensor_temperature:C} - 27315./100" description="formula to get real fpga temperature from the fpga_temperature register in decimal"/>
   <transform path="/test/prop2" register="test_prop2" unit="C" script="test_prop2.py" description="test python script #1" write_verification="0" />
   <transform path="/test/prop3" register="test_prop3" unit="C" script="test_prop3.py" description="test python script #2" />
-  <transform path="/test/prop_mt"
-	  register="test_prop_mt"
-	  unit="C"
-	  script="test_prop_mt.py"
-	  description="Example of thread safe python property"/>
+  <transform path="/test/prop4" register="test_prop4" unit="C" script="test_prop4.py" description="Example of thread safe python property"/>
 </model>

+ 1 - 2
xml/test/test_prop2.py

@@ -1,6 +1,5 @@
 def read_from_register(ctx, value):
    return ctx.get_property('/test/prop3') / 2
-    
+
 def write_to_register(ctx, value):
     ctx.set_property(value*2, '/test/prop3')
-

+ 7 - 8
xml/test/test_prop_mt.py → xml/test/test_prop4.py

@@ -4,21 +4,20 @@ lock = threading.Lock()
 
 def read_from_register(ctx, value):
    with lock:
-      ctx.lock('lock12')
-      
+      ctx.lock('test_prop4')
+
       cur = read_from_register.counter
       read_from_register.counter += 1
       for i in range (0, 5):
          time.sleep(0.1)
-         print(cur)
       out = ctx.get_property('/test/prop3') / 2
-      ctx.unlock('lock12')
-      
+
+      ctx.unlock('test_prop4')
+
       return out
-      
-      
+
 read_from_register.counter = 0
-    
+
 def write_to_register(ctx, value):
    with lock:
       ctx.set_property(value*2, '/test/prop3')

Деякі файли не було показано, через те що забагато файлів було змінено