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