4
* @author Guillermo Marcus
6
* @brief Contains the main code which connects all the different parts and does
7
* basic driver tasks like initialization.
9
* This is a full rewrite of the pciDriver.
10
* New default is to support kernel 2.6, using kernel 2.6 APIs.
17
* $Log: not supported by cvs2svn $
18
* Revision 1.13 2008-05-30 11:38:15 marcus
19
* Added patches for kernel 2.6.24
21
* Revision 1.12 2008-01-24 14:21:36 marcus
22
* Added a CLEAR_INTERRUPT_QUEUE ioctl.
23
* Added a sysfs attribute to show the outstanding IRQ queues.
25
* Revision 1.11 2008-01-24 12:53:11 marcus
26
* Corrected wait_event condition in waiti_ioctl. Improved the loop too.
28
* Revision 1.10 2008-01-14 10:39:39 marcus
29
* Set some messages as debug instead of normal.
31
* Revision 1.9 2008-01-11 10:18:28 marcus
32
* Modified interrupt mechanism. Added atomic functions and queues, to address race conditions. Removed unused interrupt code.
34
* Revision 1.8 2007-07-17 13:15:55 marcus
36
* Using newest map for the ABB interrupts.
38
* Revision 1.7 2007-07-06 15:56:04 marcus
39
* Change default status for OLD_REGISTERS to not defined.
41
* Revision 1.6 2007-07-05 15:29:59 marcus
42
* Corrected issue with the bar mapping for interrupt handling.
43
* Added support up to kernel 2.6.20
45
* Revision 1.5 2007-05-29 07:50:18 marcus
46
* Split code into 2 files. May get merged in the future again....
48
* Revision 1.4 2007/03/01 17:47:34 marcus
49
* Fixed bug when the kernel memory was less than one page, it was not locked properly, recalling an old mapping issue in this case.
51
* Revision 1.3 2007/03/01 17:01:22 marcus
52
* comment fix (again).
54
* Revision 1.2 2007/03/01 17:00:25 marcus
55
* Changed some comment in the log.
57
* Revision 1.1 2007/03/01 16:57:43 marcus
58
* Divided driver file to ease the interrupt hooks for the user of the driver.
59
* Modified Makefile accordingly.
62
* Revision 1.11 2006/12/11 16:15:43 marcus
63
* Fixed kernel buffer mmapping, and driver crash when application crashes.
64
* Buffer memory is now marked reserved during allocation, and mmaped with
67
* Revision 1.10 2006/11/21 09:50:49 marcus
68
* Added PROGRAPE4 vendor/device IDs.
70
* Revision 1.9 2006/11/17 18:47:36 marcus
71
* Removed MERGE_SGENTRIES flag, now it is selected at runtime with 'type'.
72
* Removed noncached in non-prefetchable areas, to allow the use of MTRRs.
74
* Revision 1.8 2006/11/17 16:41:21 marcus
75
* Added slot number to the PCI info IOctl.
77
* Revision 1.7 2006/11/13 12:30:34 marcus
78
* Added a IOctl call, to confiure the interrupt response. (testing pending).
79
* Basic interrupts are now supported, using a Tasklet and Completions.
81
* Revision 1.6 2006/11/08 21:30:02 marcus
82
* Added changes after compile tests in kernel 2.6.16
84
* Revision 1.5 2006/10/31 07:57:38 marcus
85
* Improved the pfn calculation in nopage(), to deal with some possible border
86
* conditions. It was really no issue, because they are normally page-aligned
87
* anyway, but to be on the safe side.
89
* Revision 1.4 2006/10/30 19:37:40 marcus
90
* Solved bug on kernel memory not mapping properly.
92
* Revision 1.3 2006/10/18 11:19:20 marcus
93
* Added kernel 2.6.8 support based on comments from Joern Adamczewski (GSI).
95
* Revision 1.2 2006/10/18 11:04:15 marcus
96
* Bus Master is only activated when we detect a specific board.
98
* Revision 1.1 2006/10/10 14:46:51 marcus
99
* Initial commit of the new pciDriver for kernel 2.6
101
* Revision 1.9 2006/10/05 11:30:46 marcus
102
* Prerelease. Added bus and devfn to pciInfo for compatibility.
104
* Revision 1.8 2006/09/25 16:51:07 marcus
105
* Added PCI config IOctls, and implemented basic mmap functions.
107
* Revision 1.7 2006/09/20 11:12:41 marcus
108
* Added Merge SG entries
110
* Revision 1.6 2006/09/19 17:22:18 marcus
113
* Revision 1.5 2006/09/18 17:13:11 marcus
116
* Revision 1.4 2006/09/15 15:44:41 marcus
119
* Revision 1.3 2006/08/15 11:40:02 marcus
122
* Revision 1.2 2006/08/12 18:28:42 marcus
123
* Sync with the laptop
125
* Revision 1.1 2006/08/11 15:30:46 marcus
126
* Sync with the laptop
130
#include <linux/version.h>
132
/* Check macros and kernel version first */
133
#ifndef KERNEL_VERSION
134
#error "No KERNEL_VERSION macro! Stopping."
137
#ifndef LINUX_VERSION_CODE
138
#error "No LINUX_VERSION_CODE macro! Stopping."
141
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8)
142
#error "This driver has been tested only for Kernel 2.6.8 or above."
145
/* Required includes */
146
#include <linux/string.h>
147
#include <linux/slab.h>
148
#include <linux/types.h>
149
#include <linux/init.h>
150
#include <linux/module.h>
151
#include <linux/pci.h>
152
#include <linux/kernel.h>
153
#include <linux/errno.h>
154
#include <linux/fs.h>
155
#include <linux/cdev.h>
156
#include <linux/sysfs.h>
157
#include <asm/atomic.h>
158
#include <linux/pagemap.h>
159
#include <linux/spinlock.h>
160
#include <linux/list.h>
161
#include <asm/scatterlist.h>
162
#include <linux/vmalloc.h>
163
#include <linux/stat.h>
164
#include <linux/interrupt.h>
165
#include <linux/wait.h>
167
/* Configuration for the driver (what should be compiled in, module name, etc...) */
170
/* Compatibility functions/definitions (provides functions which are not available on older kernels) */
173
/* External interface for the driver */
174
#include "pciDriver.h"
176
/* Internal definitions for all parts (prototypes, data, macros) */
179
/* Internal definitions for the base part */
182
/* Internal definitions of the IRQ handling part */
185
/* Internal definitions for kernel memory */
188
/* Internal definitions for user space memory */
193
/*************************************************************************/
194
/* Module device table associated with this driver */
195
MODULE_DEVICE_TABLE(pci, pcidriver_ids);
197
/* Module init and exit points */
198
module_init(pcidriver_init);
199
module_exit(pcidriver_exit);
202
MODULE_AUTHOR("Guillermo Marcus");
203
MODULE_DESCRIPTION("Simple PCI Driver");
204
MODULE_LICENSE("GPL v2");
207
static struct class_compat *pcidriver_class;
211
* Called when loading the driver
214
static int __init pcidriver_init(void)
218
/* Initialize the device count */
219
atomic_set(&pcidriver_deviceCount, 0);
221
/* Allocate character device region dynamically */
222
if ((err = alloc_chrdev_region(&pcidriver_devt, MINORNR, MAXDEVICES, NODENAME)) != 0) {
223
mod_info("Couldn't allocate chrdev region. Module not loaded.\n");
224
goto init_alloc_fail;
226
mod_info("Major %d allocated to nodename '%s'\n", MAJOR(pcidriver_devt), NODENAME);
228
/* Register driver class */
229
pcidriver_class = class_create(THIS_MODULE, NODENAME);
231
if (IS_ERR(pcidriver_class)) {
232
mod_info("No sysfs support. Module not loaded.\n");
233
goto init_class_fail;
236
/* Register PCI driver. This function returns the number of devices on some
237
* systems, therefore check for errors as < 0. */
238
if ((err = pci_register_driver(&pcidriver_driver)) < 0) {
239
mod_info("Couldn't register PCI driver. Module not loaded.\n");
240
goto init_pcireg_fail;
243
mod_info("Module loaded\n");
248
class_destroy(pcidriver_class);
250
unregister_chrdev_region(pcidriver_devt, MAXDEVICES);
257
* Called when unloading the driver
260
static void pcidriver_exit(void)
262
if (pcidriver_class != NULL)
263
class_destroy(pcidriver_class);
265
pci_unregister_driver(&pcidriver_driver);
266
unregister_chrdev_region(pcidriver_devt, MAXDEVICES);
267
mod_info("Module unloaded\n");
270
/*************************************************************************/
271
/* Driver functions */
275
* This struct defines the PCI entry points.
276
* Will be registered at module init.
279
static struct pci_driver pcidriver_driver = {
281
.id_table = pcidriver_ids,
282
.probe = pcidriver_probe,
283
.remove = pcidriver_remove,
288
* This function is called when installing the driver for a device
289
* @param pdev Pointer to the PCI device
292
static int __devinit pcidriver_probe(struct pci_dev *pdev, const struct pci_device_id *id)
296
pcidriver_privdata_t *privdata;
299
/* At the moment there is no difference between these boards here, other than
300
* printing a different message in the log.
302
* However, there is some difference in the interrupt handling functions.
304
if ( (id->vendor == MPRACE1_VENDOR_ID) &&
305
(id->device == MPRACE1_DEVICE_ID))
307
/* It is a mpRACE-1 */
308
mod_info( "Found mpRACE-1 at %s\n", dev_name(&pdev->dev));
310
pci_set_master(pdev);
312
else if ((id->vendor == PCIXTEST_VENDOR_ID) &&
313
(id->device == PCIXTEST_DEVICE_ID))
315
/* It is a PCI-X Test board */
316
mod_info( "Found PCI-X test board at %s\n", dev_name(&pdev->dev));
318
else if ((id->vendor == PCIEPLDA_VENDOR_ID) &&
319
(id->device == PCIEPLDA_DEVICE_ID))
321
/* It is a PCI-X Test board */
322
mod_info( "Found PCIe PLDA test board at %s\n", dev_name(&pdev->dev));
324
else if ((id->vendor == PCIEABB_VENDOR_ID) &&
325
(id->device == PCIEABB_DEVICE_ID))
327
/* It is a PCI-X Test board */
328
mod_info( "Found PCIe ABB test board at %s\n", dev_name(&pdev->dev));
330
else if ((id->vendor == PCIXPG4_VENDOR_ID) &&
331
(id->device == PCIXPG4_DEVICE_ID))
333
/* It is a PCI-X PROGRAPE4 board */
334
mod_info( "Found PCI-X PROGRAPE-4 board at %s\n", dev_name(&pdev->dev));
336
else if ((id->vendor == PCI64PG4_VENDOR_ID) &&
337
(id->device == PCI64PG4_DEVICE_ID))
339
/* It is a PCI-64 PROGRAPE4 board */
340
mod_info( "Found PCI-64b/66 PROGRAPE-4 board at %s\n", dev_name(&pdev->dev));
342
else if ((id->vendor == PCIE_XILINX_VENDOR_ID) &&
343
(id->device == PCIE_ML605_DEVICE_ID))
345
/* It is a PCI-E Xilinx ML605 evaluation board */
346
mod_info("Found ML605 board at %s\n", dev_name(&pdev->dev));
350
/* It is something else */
351
mod_info( "Found unknown board (%x:%x) at %s\n", id->vendor, id->device, dev_name(&pdev->dev));
354
/* Enable the device */
355
if ((err = pci_enable_device(pdev)) != 0) {
356
mod_info("Couldn't enable device\n");
357
goto probe_pcien_fail;
360
/* Set Memory-Write-Invalidate support */
361
if ((err = pci_set_mwi(pdev)) != 0)
362
mod_info("MWI not supported. Continue without enabling MWI.\n");
364
/* Get / Increment the device id */
365
devid = atomic_inc_return(&pcidriver_deviceCount) - 1;
366
if (devid >= MAXDEVICES) {
367
mod_info("Maximum number of devices reached! Increase MAXDEVICES.\n");
369
goto probe_maxdevices_fail;
372
/* Allocate and initialize the private data for this device */
373
if ((privdata = kcalloc(1, sizeof(*privdata), GFP_KERNEL)) == NULL) {
378
INIT_LIST_HEAD(&(privdata->kmem_list));
379
spin_lock_init(&(privdata->kmemlist_lock));
380
atomic_set(&privdata->kmem_count, 0);
382
INIT_LIST_HEAD(&(privdata->umem_list));
383
spin_lock_init(&(privdata->umemlist_lock));
384
atomic_set(&privdata->umem_count, 0);
386
pci_set_drvdata( pdev, privdata );
387
privdata->pdev = pdev;
389
/* Device add to sysfs */
390
devno = MKDEV(MAJOR(pcidriver_devt), MINOR(pcidriver_devt) + devid);
391
privdata->devno = devno;
392
if (pcidriver_class != NULL) {
393
/* FIXME: some error checking missing here */
394
privdata->class_dev = class_device_create(pcidriver_class, NULL, devno, &(pdev->dev), NODENAMEFMT, MINOR(pcidriver_devt) + devid, privdata);
395
class_set_devdata( privdata->class_dev, privdata );
396
mod_info("Device /dev/%s%d added\n",NODENAME,MINOR(pcidriver_devt) + devid);
399
/* Setup mmaped BARs into kernel space */
400
if ((err = pcidriver_probe_irq(privdata)) != 0)
401
goto probe_irq_probe_fail;
403
/* Populate sysfs attributes for the class device */
404
/* TODO: correct errorhandling. ewww. must remove the files in reversed order :-( */
405
#define sysfs_attr(name) do { \
406
if (class_device_create_file(sysfs_attr_def_pointer, &sysfs_attr_def_name(name)) != 0) \
407
goto probe_device_create_fail; \
410
sysfs_attr(irq_count);
411
sysfs_attr(irq_queues);
414
sysfs_attr(mmap_mode);
415
sysfs_attr(mmap_area);
416
sysfs_attr(kmem_count);
417
sysfs_attr(kmem_alloc);
418
sysfs_attr(kmem_free);
419
sysfs_attr(kbuffers);
420
sysfs_attr(umappings);
421
sysfs_attr(umem_unmap);
424
/* Register character device */
425
cdev_init( &(privdata->cdev), &pcidriver_fops );
426
privdata->cdev.owner = THIS_MODULE;
427
privdata->cdev.ops = &pcidriver_fops;
428
err = cdev_add( &privdata->cdev, devno, 1 );
430
mod_info( "Couldn't add character device.\n" );
431
goto probe_cdevadd_fail;
436
probe_device_create_fail:
438
probe_irq_probe_fail:
439
pcidriver_irq_unmap_bars(privdata);
442
atomic_dec(&pcidriver_deviceCount);
443
probe_maxdevices_fail:
444
pci_disable_device(pdev);
451
* This function is called when disconnecting a device
454
static void __devexit pcidriver_remove(struct pci_dev *pdev)
456
pcidriver_privdata_t *privdata;
458
/* Get private data from the device */
459
privdata = pci_get_drvdata(pdev);
461
/* Removing sysfs attributes from class device */
462
#define sysfs_attr(name) do { \
463
class_device_remove_file(sysfs_attr_def_pointer, &sysfs_attr_def_name(name)); \
466
sysfs_attr(irq_count);
467
sysfs_attr(irq_queues);
470
sysfs_attr(mmap_mode);
471
sysfs_attr(mmap_area);
472
sysfs_attr(kmem_count);
473
sysfs_attr(kmem_alloc);
474
sysfs_attr(kmem_free);
475
sysfs_attr(kbuffers);
476
sysfs_attr(umappings);
477
sysfs_attr(umem_unmap);
480
/* Free all allocated kmem buffers before leaving */
481
pcidriver_kmem_free_all( privdata );
484
pcidriver_remove_irq(privdata);
487
/* Removing Character device */
488
cdev_del(&(privdata->cdev));
490
/* Removing the device from sysfs */
491
class_device_destroy(pcidriver_class, privdata->devno);
493
/* Releasing privdata */
496
/* Disabling PCI device */
497
pci_disable_device(pdev);
499
mod_info("Device at %s removed\n", dev_name(&pdev->dev));
502
/*************************************************************************/
503
/* File operations */
504
/*************************************************************************/
507
* This struct defines the file operation entry points.
509
* @see pcidriver_ioctl
510
* @see pcidriver_mmap
511
* @see pcidriver_open
512
* @see pcidriver_release
515
static struct file_operations pcidriver_fops = {
516
.owner = THIS_MODULE,
517
.ioctl = pcidriver_ioctl,
518
.mmap = pcidriver_mmap,
519
.open = pcidriver_open,
520
.release = pcidriver_release,
525
* Called when an application open()s a /dev/fpga*, attaches the private data
526
* with the file pointer.
529
int pcidriver_open(struct inode *inode, struct file *filp)
531
pcidriver_privdata_t *privdata;
533
/* Set the private data area for the file */
534
privdata = container_of( inode->i_cdev, pcidriver_privdata_t, cdev);
535
filp->private_data = privdata;
542
* Called when the application close()s the file descriptor. Does nothing at
546
int pcidriver_release(struct inode *inode, struct file *filp)
548
pcidriver_privdata_t *privdata;
550
/* Get the private data area */
551
privdata = filp->private_data;
558
* This function is the entry point for mmap() and calls either pcidriver_mmap_pci
559
* or pcidriver_mmap_kmem
561
* @see pcidriver_mmap_pci
562
* @see pcidriver_mmap_kmem
565
int pcidriver_mmap(struct file *filp, struct vm_area_struct *vma)
567
pcidriver_privdata_t *privdata;
570
mod_info_dbg("Entering mmap\n");
572
/* Get the private data area */
573
privdata = filp->private_data;
575
/* Check the current mmap mode */
576
switch (privdata->mmap_mode) {
577
case PCIDRIVER_MMAP_PCI:
578
/* Mmap a PCI region */
579
switch (privdata->mmap_area) {
580
case PCIDRIVER_BAR0: bar = 0; break;
581
case PCIDRIVER_BAR1: bar = 1; break;
582
case PCIDRIVER_BAR2: bar = 2; break;
583
case PCIDRIVER_BAR3: bar = 3; break;
584
case PCIDRIVER_BAR4: bar = 4; break;
585
case PCIDRIVER_BAR5: bar = 5; break;
587
mod_info("Attempted to mmap a PCI area with the wrong mmap_area value: %d\n",privdata->mmap_area);
588
return -EINVAL; /* invalid parameter */
591
ret = pcidriver_mmap_pci(privdata, vma, bar);
593
case PCIDRIVER_MMAP_KMEM:
594
/* mmap a Kernel buffer */
595
ret = pcidriver_mmap_kmem(privdata, vma);
598
mod_info( "Invalid mmap_mode value (%d)\n",privdata->mmap_mode );
599
return -EINVAL; /* Invalid parameter (mode) */
605
/*************************************************************************/
606
/* Internal driver functions */
607
int pcidriver_mmap_pci(pcidriver_privdata_t *privdata, struct vm_area_struct *vmap, int bar)
610
unsigned long bar_addr;
611
unsigned long bar_length, vma_size;
612
unsigned long bar_flags;
614
mod_info_dbg("Entering mmap_pci\n");
616
/* Get info of the BAR to be mapped */
617
bar_addr = pci_resource_start(privdata->pdev, bar);
618
bar_length = pci_resource_len(privdata->pdev, bar);
619
bar_flags = pci_resource_flags(privdata->pdev, bar);
622
vma_size = (vmap->vm_end - vmap->vm_start);
623
if ((vma_size != bar_length) &&
624
((bar_length < PAGE_SIZE) && (vma_size != PAGE_SIZE))) {
625
mod_info( "mmap size is not correct! bar: %lu - vma: %lu\n", bar_length, vma_size );
629
if (bar_flags & IORESOURCE_IO) {
630
/* Unlikely case, we will mmap a IO region */
632
/* IO regions are never cacheable */
633
#ifdef pgprot_noncached
634
vmap->vm_page_prot = pgprot_noncached(vmap->vm_page_prot);
638
ret = io_remap_pfn_range_compat(
645
/* Normal case, mmap a memory region */
647
/* Ensure this VMA is non-cached, if it is not flaged as prefetchable.
648
* If it is prefetchable, caching is allowed and will give better performance.
649
* This should be set properly by the BIOS, but we want to be sure. */
650
/* adapted from drivers/char/mem.c, mmap function. */
651
#ifdef pgprot_noncached
652
/* Setting noncached disables MTRR registers, and we want to use them.
653
* So we take this code out. This can lead to caching problems if and only if
654
* the System BIOS set something wrong. Check LDDv3, page 425.
656
// if (!(bar_flags & IORESOURCE_PREFETCH))
657
// vmap->vm_page_prot = pgprot_noncached(vmap->vm_page_prot);
661
ret = remap_pfn_range_compat(
670
mod_info("remap_pfn_range failed\n");
674
return 0; /* success */