summaryrefslogtreecommitdiffstats
path: root/driver/base.c
diff options
context:
space:
mode:
Diffstat (limited to 'driver/base.c')
-rw-r--r--driver/base.c789
1 files changed, 317 insertions, 472 deletions
diff --git a/driver/base.c b/driver/base.c
index dfd82c6..220f1f3 100644
--- a/driver/base.c
+++ b/driver/base.c
@@ -5,144 +5,9 @@
* @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>
@@ -166,32 +31,15 @@
#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"
/*************************************************************************/
@@ -221,54 +69,54 @@ pcidriver_privdata_t *pcidriver_dummydata = NULL;
*/
static int __init pcidriver_init(void)
{
- int err = 0;
-
- /* Initialize the device count */
- atomic_set(&pcidriver_deviceCount, 0);
-
- memset(pcidriver_privdata, 0, sizeof(pcidriver_privdata));
-
- /* Allocate character device region dynamically */
- if ((err = alloc_chrdev_region(&pcidriver_devt, MINORNR, MAXDEVICES, NODENAME)) != 0) {
- mod_info("Couldn't allocate chrdev region. Module not loaded.\n");
- goto init_alloc_fail;
- }
- mod_info("Major %d allocated to nodename '%s'\n", MAJOR(pcidriver_devt), NODENAME);
-
- /* Register driver class */
- pcidriver_class = class_create(THIS_MODULE, NODENAME);
-
- 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. */
+ int err = 0;
+
+ /* Initialize the device count */
+ atomic_set(&pcidriver_deviceCount, 0);
+
+ memset(pcidriver_privdata, 0, sizeof(pcidriver_privdata));
+
+ /* Allocate character device region dynamically */
+ if ((err = alloc_chrdev_region(&pcidriver_devt, MINORNR, MAXDEVICES, NODENAME)) != 0) {
+ mod_info("Couldn't allocate chrdev region. Module not loaded.\n");
+ goto init_alloc_fail;
+ }
+ mod_info("Major %d allocated to nodename '%s'\n", MAJOR(pcidriver_devt), NODENAME);
+
+ /* Register driver class */
+ pcidriver_class = class_create(THIS_MODULE, NODENAME);
+
+ 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) {
+ if ((err = pcidriver_probe(NULL, NULL)) < 0) {
#else /* PCIDRIVER_DUMMY_DEVICE */
- if ((err = pci_register_driver(&pcidriver_driver)) < 0) {
+ 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;
- }
+ 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);
- }
+ 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;
init_pcireg_fail:
- class_destroy(pcidriver_class);
+ class_destroy(pcidriver_class);
init_class_fail:
- unregister_chrdev_region(pcidriver_devt, MAXDEVICES);
+ unregister_chrdev_region(pcidriver_devt, MAXDEVICES);
init_alloc_fail:
- return err;
+ return err;
}
/**
@@ -279,17 +127,17 @@ init_alloc_fail:
static void pcidriver_exit(void)
{
#ifdef PCIDRIVER_DUMMY_DEVICE
- pcidriver_remove(NULL);
+ pcidriver_remove(NULL);
#else
- pci_unregister_driver(&pcidriver_driver);
+ pci_unregister_driver(&pcidriver_driver);
#endif /* PCIDRIVER_DUMMY_DEVICE */
- unregister_chrdev_region(pcidriver_devt, MAXDEVICES);
+ unregister_chrdev_region(pcidriver_devt, MAXDEVICES);
- if (pcidriver_class != NULL)
- class_destroy(pcidriver_class);
+ if (pcidriver_class != NULL)
+ class_destroy(pcidriver_class);
- mod_info("Module unloaded\n");
+ mod_info("Module unloaded\n");
}
/*************************************************************************/
@@ -303,10 +151,10 @@ static void pcidriver_exit(void)
*/
#ifndef PCIDRIVER_DUMMY_DEVICE
static struct pci_driver pcidriver_driver = {
- .name = MODNAME,
- .id_table = pcidriver_ids,
- .probe = pcidriver_probe,
- .remove = pcidriver_remove,
+ .name = MODNAME,
+ .id_table = pcidriver_ids,
+ .probe = pcidriver_probe,
+ .remove = pcidriver_remove,
};
#endif /* ! PCIDRIVER_DUMMY_DEVICE */
@@ -318,155 +166,155 @@ static struct pci_driver pcidriver_driver = {
*/
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");
+ 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 */
- /* 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);
+ /* 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);
#ifdef PCIDRIVER_DUMMY_DEVICE
- pcidriver_dummydata = privdata;
+ pcidriver_dummydata = privdata;
#else /* PCIDRIVER_DUMMY_DEVICE */
- pci_set_drvdata(pdev, privdata);
- privdata->pdev = pdev;
+ pci_set_drvdata(pdev, privdata);
+ privdata->pdev = pdev;
#endif /* PCIDRIVER_DUMMY_DEVICE */
- /* Device add to sysfs */
- devno = MKDEV(MAJOR(pcidriver_devt), MINOR(pcidriver_devt) + devid);
- privdata->devno = devno;
+ /* Device add to sysfs */
+ devno = MKDEV(MAJOR(pcidriver_devt), MINOR(pcidriver_devt) + devid);
+ privdata->devno = devno;
- /* FIXME: some error checking missing here */
+ /* 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);
+ privdata->class_dev = class_device_create(pcidriver_class, NULL, devno, NULL, NODENAMEFMT, MINOR(pcidriver_devt) + devid, privdata);
#else /* PCIDRIVER_DUMMY_DEVICE */
- privdata->class_dev = class_device_create(pcidriver_class, NULL, devno, &(pdev->dev), NODENAMEFMT, MINOR(pcidriver_devt) + devid, privdata);
+ privdata->class_dev = class_device_create(pcidriver_class, NULL, devno, &(pdev->dev), NODENAMEFMT, MINOR(pcidriver_devt) + devid, privdata);
#endif /* PCIDRIVER_DUMMY_DEVICE */
- class_set_devdata( privdata->class_dev, privdata );
- mod_info("Device /dev/%s%d added\n",NODENAME,MINOR(pcidriver_devt) + devid);
+ class_set_devdata( 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 { \
+ /* 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;
- }
-
- pcidriver_privdata[devid] = privdata;
-
- return 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;
+ }
+
+ 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;
}
/**
@@ -476,62 +324,62 @@ 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_dummydata;
- pcidriver_dummydata = 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 */
- // Theoretically we should lock here and when using...
- pcidriver_privdata[privdata->devid] = NULL;
+ // Theoretically we should lock here and when using...
+ pcidriver_privdata[privdata->devid] = NULL;
- /* Removing sysfs attributes from class device */
- #define sysfs_attr(name) do { \
+ /* 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 );
+#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 );
#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 */
+ class_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 */
}
@@ -550,15 +398,11 @@ static void __devexit pcidriver_remove(struct pci_dev *pdev)
*
*/
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,
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = pcidriver_ioctl,
+ .mmap = pcidriver_mmap,
+ .open = pcidriver_open,
+ .release = pcidriver_release,
};
void pcidriver_module_get(pcidriver_privdata_t *privdata) {
@@ -568,8 +412,8 @@ void pcidriver_module_get(pcidriver_privdata_t *privdata) {
void pcidriver_module_put(pcidriver_privdata_t *privdata) {
if (atomic_add_negative(-1, &(privdata->refs))) {
- atomic_inc(&(privdata->refs));
- mod_info("Reference counting error...");
+ atomic_inc(&(privdata->refs));
+ mod_info("Reference counting error...");
} else {
// mod_info("Unref: %i\n", atomic_read(&(privdata->refs)));
}
@@ -583,15 +427,15 @@ void pcidriver_module_put(pcidriver_privdata_t *privdata) {
*/
int pcidriver_open(struct inode *inode, struct file *filp)
{
- pcidriver_privdata_t *privdata;
+ 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;
+ /* 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);
+ pcidriver_module_get(privdata);
- return 0;
+ return 0;
}
/**
@@ -602,14 +446,14 @@ int pcidriver_open(struct inode *inode, struct file *filp)
*/
int pcidriver_release(struct inode *inode, struct file *filp)
{
- pcidriver_privdata_t *privdata;
+ pcidriver_privdata_t *privdata;
- /* Get the private data area */
- privdata = filp->private_data;
+ /* Get the private data area */
+ privdata = filp->private_data;
- pcidriver_module_put(privdata);
+ pcidriver_module_put(privdata);
- return 0;
+ return 0;
}
/**
@@ -623,42 +467,54 @@ int pcidriver_release(struct inode *inode, struct file *filp)
*/
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;
+ 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;
}
/*************************************************************************/
@@ -666,76 +522,65 @@ int pcidriver_mmap(struct file *filp, struct vm_area_struct *vma)
int pcidriver_mmap_pci(pcidriver_privdata_t *privdata, struct vm_area_struct *vmap, int bar)
{
#ifdef PCIDRIVER_DUMMY_DEVICE
- return -ENXIO;
+ return -ENXIO;
#else /* PCIDRIVER_DUMMY_DEVICE */
- int ret = 0;
- unsigned long bar_addr;
- unsigned long bar_length, vma_size;
- unsigned long bar_flags;
+ int ret = 0;
+ unsigned long bar_addr;
+ unsigned long bar_length, vma_size;
+ unsigned long bar_flags;
- mod_info_dbg("Entering mmap_pci\n");
+ 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);
+ /* 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);
+ /* 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 ((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 */
+ 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
+ /* IO regions are never cacheable */
+ vmap->vm_page_prot = pgprot_noncached(vmap->vm_page_prot);
- /* Map the BAR */
- ret = io_remap_pfn_range_compat(
- vmap,
- vmap->vm_start,
- bar_addr,
- bar_length,
- vmap->vm_page_prot);
- } else {
- /* Normal case, mmap a memory region */
-
- /* Ensure this VMA is non-cached, if it is not flaged as prefetchable.
- * If it is prefetchable, caching is allowed and will give better performance.
- * This should be set properly by the BIOS, but we want to be sure. */
- /* adapted from drivers/char/mem.c, mmap function. */
-#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))
+ /* Map the BAR */
+ ret = io_remap_pfn_range_compat(vmap, vmap->vm_start, bar_addr, bar_length, vmap->vm_page_prot);
+ } else {
+ /* Normal case, mmap a memory region */
+
+ /* Ensure this VMA is non-cached, if it is not flaged as prefetchable.
+ * If it is prefetchable, caching is allowed and will give better performance.
+ * This should be set properly by the BIOS, but we want to be sure. */
+ /* adapted from drivers/char/mem.c, mmap function. */
+
+ /* Setting noncached disables MTRR registers, and we want to use them.
+ * So we take this code out. This can lead to caching problems if and only if
+ * the System BIOS set something wrong. Check LDDv3, page 425.
+ */
+
+// if (!(bar_flags & IORESOURCE_PREFETCH))
// vmap->vm_page_prot = pgprot_noncached(vmap->vm_page_prot);
-#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 */
+
+ /* 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 */
#endif /* PCIDRIVER_DUMMY_DEVICE */
}