diff options
| -rw-r--r-- | driver/Makefile | 9 | ||||
| -rw-r--r-- | driver/README | 4 | ||||
| -rw-r--r-- | driver/base.c | 76 | ||||
| -rw-r--r-- | driver/base.h | 2 | ||||
| -rw-r--r-- | driver/compat.h | 6 | ||||
| -rw-r--r-- | driver/ioctl.c | 20 | ||||
| -rw-r--r-- | driver/kmem.c | 14 | 
7 files changed, 116 insertions, 15 deletions
| diff --git a/driver/Makefile b/driver/Makefile index c26a84a..a783c3f 100644 --- a/driver/Makefile +++ b/driver/Makefile @@ -1,3 +1,4 @@ +CONFIG_MODULE_SIG=n  obj-m := pciDriver.o  pciDriver-objs := base.o int.o umem.o kmem.o sysfs.o ioctl.o compat.o @@ -8,6 +9,12 @@ PWD := $(shell pwd)  EXTRA_CFLAGS += -I$(M)/.. +ifdef DUMMY_DEVICE +ifneq ($(DUMMY_DEVICE), 0) +    EXTRA_CFLAGS += -DPCIDRIVER_DUMMY_DEVICE +endif +endif +  default:  	@KERNEL_GCC_VERSION=`cat /proc/version | head -n1 | cut -d " " -f 7` ;\  	GCC_VERSION=`$(CC) --version | head -n 1 | tr ' ' '\n' | grep -e "[0-9]\+\.[0-9]" | tail -n 1` ;\ @@ -39,7 +46,7 @@ default:  	build_date=`date "+%Y/%m/%d %H:%M:%S"` ;\  	build="Built at $$build_date by $$build_user" ;\  	revision="Revision $$build_revision from $$build_branch by $$build_author at $$build_path, last modification from $$build_lastmod" ;\ -	echo -e "#define PCIDRIVER_BUILD \"$$build\"\\n#define PCIDRIVER_REVISION \"$$revision\"\\n#define PCIDRIVER_CHANGES \"$$build_changes\"\\n" > build.h ;\ +	/bin/echo -e "#define PCIDRIVER_BUILD \"$$build\"\\n#define PCIDRIVER_REVISION \"$$revision\"\\n#define PCIDRIVER_CHANGES \"$$build_changes\"\\n" > build.h ;\  	$(MAKE) $(CFLAGS) -C $(KERNELDIR) M=$(PWD) CC=$$CC modules  install: diff --git a/driver/README b/driver/README new file mode 100644 index 0000000..66a68df --- /dev/null +++ b/driver/README @@ -0,0 +1,4 @@ +make <OPTIONS> +    V=1					verbose mode +    RELAXED_GCC_CHECK=1			allow difference in micro version of gcc used to compile kernel and pcidriver module +    DUMMY_DEVICE=1			build dummy device driver (does not require PCI device) diff --git a/driver/base.c b/driver/base.c index bc9ab98..4e55dda 100644 --- a/driver/base.c +++ b/driver/base.c @@ -210,6 +210,10 @@ MODULE_LICENSE("GPL v2");  /* Module class */  static struct class_compat *pcidriver_class; +#ifdef PCIDRIVER_DUMMY_DEVICE +pcidriver_privdata_t *pcidriver_privdata = NULL; +#endif /* PCIDRIVER_DUMMY_DEVICE */ +  /**   *   * Called when loading the driver @@ -217,7 +221,7 @@ static struct class_compat *pcidriver_class;   */  static int __init pcidriver_init(void)  { -	int err; +	int err = 0;  	/* Initialize the device count */  	atomic_set(&pcidriver_deviceCount, 0); @@ -239,7 +243,11 @@ static int __init pcidriver_init(void)  	/* Register PCI driver. This function returns the number of devices on some  	 * systems, therefore check for errors as < 0. */ +#ifdef PCIDRIVER_DUMMY_DEVICE +	if ((err = pcidriver_probe(NULL, NULL)) < 0) { +#else /* PCIDRIVER_DUMMY_DEVICE */  	if ((err = pci_register_driver(&pcidriver_driver)) < 0) { +#endif /* PCIDRIVER_DUMMY_DEVICE */  		mod_info("Couldn't register PCI driver. Module not loaded.\n");  		goto init_pcireg_fail;  	} @@ -268,7 +276,12 @@ init_alloc_fail:   */  static void pcidriver_exit(void)  { +#ifdef PCIDRIVER_DUMMY_DEVICE +	pcidriver_remove(NULL); +#else  	pci_unregister_driver(&pcidriver_driver); +#endif /* PCIDRIVER_DUMMY_DEVICE */ +  	unregister_chrdev_region(pcidriver_devt, MAXDEVICES);  	if (pcidriver_class != NULL) @@ -286,12 +299,14 @@ static void pcidriver_exit(void)   * 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 */  /**   * @@ -301,7 +316,7 @@ static struct pci_driver pcidriver_driver = {   */  static int __devinit pcidriver_probe(struct pci_dev *pdev, const struct pci_device_id *id)  { -	int err; +	int err = 0;  	int devno;  	pcidriver_privdata_t *privdata;  	int devid; @@ -311,6 +326,9 @@ static int __devinit pcidriver_probe(struct pci_dev *pdev, const struct pci_devi  	 *  	 * However, there is some difference in the interrupt handling functions.  	 */ +#ifdef PCIDRIVER_DUMMY_DEVICE +	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)); @@ -323,7 +341,7 @@ static int __devinit pcidriver_probe(struct pci_dev *pdev, const struct pci_devi  	    }  	} else {  	    /* It is something else */ -	    mod_info( "Found unknown board (%x:%x) at %s\n", id->vendor, id->device, dev_name(&pdev->dev)); +	    mod_info("Found unknown board (%x:%x) at %s\n", id->vendor, id->device, dev_name(&pdev->dev));  	}  	/* Enable the device */ @@ -343,7 +361,8 @@ static int __devinit pcidriver_probe(struct pci_dev *pdev, const struct pci_devi  	/* Set Memory-Write-Invalidate support */  	if ((err = pci_set_mwi(pdev)) != 0) -		mod_info("MWI not supported. Continue without enabling MWI.\n"); +	    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; @@ -367,22 +386,31 @@ static int __devinit pcidriver_probe(struct pci_dev *pdev, const struct pci_devi  	spin_lock_init(&(privdata->umemlist_lock));  	atomic_set(&privdata->umem_count, 0); -	pci_set_drvdata( pdev, privdata ); +#ifdef PCIDRIVER_DUMMY_DEVICE +	pcidriver_privdata = privdata; +#else /* PCIDRIVER_DUMMY_DEVICE */ +	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; -	if (pcidriver_class != NULL) { -		/* FIXME: some error checking missing here */ -		privdata->class_dev = class_device_create(pcidriver_class, NULL, devno, &(pdev->dev), NODENAMEFMT, MINOR(pcidriver_devt) + devid, privdata); -		class_set_devdata( privdata->class_dev, privdata ); -		mod_info("Device /dev/%s%d added\n",NODENAME,MINOR(pcidriver_devt) + devid); -	} +	/* 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 ); +	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; +#endif /* ! PCIDRIVER_DUMMY_DEVICE */  	/* Populate sysfs attributes for the class device */  	/* TODO: correct errorhandling. ewww. must remove the files in reversed order :-( */ @@ -419,15 +447,19 @@ static int __devinit pcidriver_probe(struct pci_dev *pdev, const struct pci_devi  probe_device_create_fail:  probe_cdevadd_fail: +#ifndef PCIDRIVER_DUMMY_DEVICE  probe_irq_probe_fail:  	pcidriver_irq_unmap_bars(privdata); +#endif /* ! PCIDRIVER_DUMMY_DEVICE */  	kfree(privdata);  probe_nomem:  	atomic_dec(&pcidriver_deviceCount);  probe_maxdevices_fail: +#ifndef PCIDRIVER_DUMMY_DEVICE  probe_dma_fail:  	pci_disable_device(pdev);  probe_pcien_fail: +#endif /* ! PCIDRIVER_DUMMY_DEVICE */   	return err;  } @@ -440,8 +472,13 @@ static void __devexit pcidriver_remove(struct pci_dev *pdev)  {  	pcidriver_privdata_t *privdata; +#ifdef PCIDRIVER_DUMMY_DEVICE +	privdata = pcidriver_privdata; +	pcidriver_privdata = NULL; +#else /* PCIDRIVER_DUMMY_DEVICE */  	/* Get private data from the device */  	privdata = pci_get_drvdata(pdev); +#endif /* PCIDRIVER_DUMMY_DEVICE */  	/* Removing sysfs attributes from class device */  	#define sysfs_attr(name) do { \ @@ -465,9 +502,11 @@ static void __devexit pcidriver_remove(struct pci_dev *pdev)  	/* Free all allocated kmem buffers before leaving */  	pcidriver_kmem_free_all( privdata ); -#ifdef ENABLE_IRQ +#ifndef PCIDRIVER_DUMMY_DEVICE +# ifdef ENABLE_IRQ  	pcidriver_remove_irq(privdata); -#endif +# endif +#endif /* ! PCIDRIVER_DUMMY_DEVICE */  	/* Removing Character device */  	cdev_del(&(privdata->cdev)); @@ -478,10 +517,14 @@ static void __devexit pcidriver_remove(struct pci_dev *pdev)  	/* Releasing privdata */  	kfree(privdata); +#ifdef PCIDRIVER_DUMMY_DEVICE +	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)); +#endif /* PCIDRIVER_DUMMY_DEVICE */ +  }  /*************************************************************************/ @@ -613,6 +656,9 @@ int pcidriver_mmap(struct file *filp, struct vm_area_struct *vma)  /* Internal driver functions */  int pcidriver_mmap_pci(pcidriver_privdata_t *privdata, struct vm_area_struct *vmap, int bar)  { +#ifdef PCIDRIVER_DUMMY_DEVICE +	return -ENXIO; +#else /* PCIDRIVER_DUMMY_DEVICE */  	int ret = 0;  	unsigned long bar_addr;  	unsigned long bar_length, vma_size; @@ -620,6 +666,7 @@ int pcidriver_mmap_pci(pcidriver_privdata_t *privdata, struct vm_area_struct *vm  	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); @@ -680,4 +727,5 @@ int pcidriver_mmap_pci(pcidriver_privdata_t *privdata, struct vm_area_struct *vm  	}  	return 0;	/* success */ +#endif /* PCIDRIVER_DUMMY_DEVICE */  } diff --git a/driver/base.h b/driver/base.h index b976d3f..5b977fa 100644 --- a/driver/base.h +++ b/driver/base.h @@ -17,7 +17,9 @@ int pcidriver_open(struct inode *inode, struct file *filp );  int pcidriver_release(struct inode *inode, struct file *filp);  /* prototypes for device operations */ +#ifndef PCIDRIVER_DUMMY_DEVICE  static struct pci_driver pcidriver_driver; +#endif /* ! PCIDRIVER_DUMMY_DEVICE */  static int __devinit pcidriver_probe(struct pci_dev *pdev, const struct pci_device_id *id);  static void __devexit pcidriver_remove(struct pci_dev *pdev); diff --git a/driver/compat.h b/driver/compat.h index fd3f188..5232a22 100644 --- a/driver/compat.h +++ b/driver/compat.h @@ -10,6 +10,12 @@  #ifndef _COMPAT_H  #define _COMPAT_H +/* +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) +# error "Linux 3.0 and latter are supported" +#endif +*/ +  #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)  # define __devinit  # define __devexit diff --git a/driver/ioctl.c b/driver/ioctl.c index 26618c0..f957561 100644 --- a/driver/ioctl.c +++ b/driver/ioctl.c @@ -96,6 +96,9 @@ static int ioctl_mmap_area(pcidriver_privdata_t *privdata, unsigned long arg)   */  static int ioctl_pci_config_read_write(pcidriver_privdata_t *privdata, unsigned int cmd, unsigned long arg)  { +#ifdef PCIDRIVER_DUMMY_DEVICE +	return -ENXIO; +#else /* PCIDRIVER_DUMMY_DEVICE */  	int ret;  	READ_FROM_USER(pci_cfg_cmd, pci_cmd); @@ -133,6 +136,7 @@ static int ioctl_pci_config_read_write(pcidriver_privdata_t *privdata, unsigned  	WRITE_TO_USER(pci_cfg_cmd, pci_cmd);  	return 0; +#endif /* PCIDRIVER_DUMMY_DEVICE */  }  /** @@ -145,7 +149,14 @@ static int ioctl_pci_config_read_write(pcidriver_privdata_t *privdata, unsigned  static int ioctl_pci_info(pcidriver_privdata_t *privdata, unsigned long arg)  {  	int ret; + +#ifdef PCIDRIVER_DUMMY_DEVICE +	READ_FROM_USER(pcilib_board_info_t, pci_info); +	memset(&pci_info, 0, sizeof(pci_info)); +	WRITE_TO_USER(pcilib_board_info_t, pci_info); +#else /* PCIDRIVER_DUMMY_DEVICE */  	int bar; +  	READ_FROM_USER(pcilib_board_info_t, pci_info);  	pci_info.vendor_id = privdata->pdev->vendor; @@ -168,6 +179,7 @@ static int ioctl_pci_info(pcidriver_privdata_t *privdata, unsigned long arg)  	}  	WRITE_TO_USER(pcilib_board_info_t, pci_info); +#endif /* PCIDRIVER_DUMMY_DEVICE */  	return 0;  } @@ -443,12 +455,16 @@ static int ioctl_device_state(pcidriver_privdata_t *privdata, unsigned long arg)  	int ret;  	pcilib_device_state_t info; +#ifdef PCIDRIVER_DUMMY_DEVICE +	memset(&info, 0, sizeof(info)); +#else /* PCIDRIVER_DUMMY_DEVICE */  	info = (pcilib_device_state_t) {  	    .iommu = iommu_present(privdata->pdev->dev.bus),  	    .mps = pcidriver_pcie_get_mps(privdata->pdev),  	    .readrq = pcie_get_readrq(privdata->pdev),  	    .dma_mask = privdata->pdev->dma_mask  	}; +#endif /* PCIDRIVER_DUMMY_DEVICE */  	WRITE_TO_USER(pcilib_device_state_t, info); @@ -466,6 +482,7 @@ static int ioctl_device_state(pcidriver_privdata_t *privdata, unsigned long arg)   */  static int ioctl_set_dma_mask(pcidriver_privdata_t *privdata, unsigned long arg)  { +#ifndef PCIDRIVER_DUMMY_DEVICE  	int err;  	if ((arg < 24) || (arg > 64)) @@ -476,6 +493,7 @@ static int ioctl_set_dma_mask(pcidriver_privdata_t *privdata, unsigned long arg)  	    printk(KERN_ERR "pci_set_dma_mask(%lu) failed\n", arg);  	    return err;  	} +#endif /* ! PCIDRIVER_DUMMY_DEVICE */  	return 0;  } @@ -489,6 +507,7 @@ static int ioctl_set_dma_mask(pcidriver_privdata_t *privdata, unsigned long arg)   */  static int ioctl_set_mps(pcidriver_privdata_t *privdata, unsigned long arg)  { +#ifndef PCIDRIVER_DUMMY_DEVICE  	int err;  	if ((arg != 128) && (arg != 256) && (arg != 512)) @@ -499,6 +518,7 @@ static int ioctl_set_mps(pcidriver_privdata_t *privdata, unsigned long arg)  	    printk(KERN_ERR "pcie_set_mps(%lu) failed\n", arg);  	    return err;  	} +#endif /* ! PCIDRIVER_DUMMY_DEVICE */  	return 0;  } diff --git a/driver/kmem.c b/driver/kmem.c index 618b5bf..805ace1 100644 --- a/driver/kmem.c +++ b/driver/kmem.c @@ -137,7 +137,11 @@ int pcidriver_kmem_alloc(pcidriver_privdata_t *privdata, kmem_handle_t *kmem_han  	 */  	switch (kmem_entry->type&PCILIB_KMEM_TYPE_MASK) {  	 case PCILIB_KMEM_TYPE_CONSISTENT: +#ifdef PCIDRIVER_DUMMY_DEVICE +	    retptr = kmalloc( kmem_handle->size, GFP_KERNEL); +#else /* PCIDRIVER_DUMMY_DEVICE */  	    retptr = pci_alloc_consistent( privdata->pdev, kmem_handle->size, &(kmem_entry->dma_handle) ); +#endif /* PCIDRIVER_DUMMY_DEVICE */  	    break;  	 case PCILIB_KMEM_TYPE_REGION:  	    retptr = ioremap(kmem_handle->pa,  kmem_handle->size); @@ -162,6 +166,7 @@ int pcidriver_kmem_alloc(pcidriver_privdata_t *privdata, kmem_handle_t *kmem_han  	    kmem_entry->dma_handle = 0;  	    if (retptr) { +#ifndef PCIDRIVER_DUMMY_DEVICE  	        if (kmem_entry->type == PCILIB_KMEM_TYPE_DMA_S2C_PAGE) {  		    kmem_entry->direction = PCI_DMA_TODEVICE;      		    kmem_entry->dma_handle = pci_map_single(privdata->pdev, retptr, kmem_handle->size, PCI_DMA_TODEVICE); @@ -178,6 +183,7 @@ int pcidriver_kmem_alloc(pcidriver_privdata_t *privdata, kmem_handle_t *kmem_han  		    }  		} +#endif /* ! PCIDRIVER_DUMMY_DEVICE */  	    }  	    break; @@ -361,6 +367,7 @@ int pcidriver_kmem_sync_entry( pcidriver_privdata_t *privdata, pcidriver_kmem_en  	if (kmem_entry->direction == PCI_DMA_NONE)  		return -EINVAL; +#ifndef PCIDRIVER_DUMMY_DEVICE  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)  	switch (direction) {  		case PCILIB_KMEM_SYNC_TODEVICE: @@ -391,6 +398,7 @@ int pcidriver_kmem_sync_entry( pcidriver_privdata_t *privdata, pcidriver_kmem_en  			return -EINVAL;				/* wrong direction parameter */  	}  #endif +#endif /* ! PCIDRIVER_DUMMY_DEVICE */  	return 0;	/* success */  } @@ -480,12 +488,17 @@ int pcidriver_kmem_free_entry(pcidriver_privdata_t *privdata, pcidriver_kmem_ent  	/* Release DMA memory */  	switch (kmem_entry->type&PCILIB_KMEM_TYPE_MASK) {  	 case PCILIB_KMEM_TYPE_CONSISTENT: +#ifdef PCIDRIVER_DUMMY_DEVICE +	    kfree((void*)(kmem_entry->cpua)); +#else /* PCIDRIVER_DUMMY_DEVICE */  	    pci_free_consistent( privdata->pdev, kmem_entry->size, (void *)(kmem_entry->cpua), kmem_entry->dma_handle ); +#endif /* PCIDRIVER_DUMMY_DEVICE */  	    break;  	 case PCILIB_KMEM_TYPE_REGION:  	    iounmap((void *)(kmem_entry->cpua));  	    break;  	 case PCILIB_KMEM_TYPE_PAGE: +#ifndef PCIDRIVER_DUMMY_DEVICE  	    if (kmem_entry->dma_handle) {  		if (kmem_entry->type == PCILIB_KMEM_TYPE_DMA_S2C_PAGE) {  		    pci_unmap_single(privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, PCI_DMA_TODEVICE); @@ -493,6 +506,7 @@ int pcidriver_kmem_free_entry(pcidriver_privdata_t *privdata, pcidriver_kmem_ent  		    pci_unmap_single(privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, PCI_DMA_FROMDEVICE);  		}  	    } +#endif /* ! PCIDRIVER_DUMMY_DEVICE */  	    free_pages((unsigned long)kmem_entry->cpua, get_order(kmem_entry->size));  	    break;  	} | 
