summaryrefslogtreecommitdiffstats
path: root/driver
diff options
context:
space:
mode:
authorroot <root@iss-tomyspiel-l>2011-07-04 16:21:23 +0200
committerroot <root@iss-tomyspiel-l>2011-07-04 16:21:23 +0200
commit2e7a7a3534bcf591c0d6c65105b2d845f293112f (patch)
treed0e5d2f9ea246ff55134205f7ac3af0d9599e641 /driver
parent70937611e34577151a6607640050e8b164a54e70 (diff)
downloadipecamera-2e7a7a3534bcf591c0d6c65105b2d845f293112f.tar.gz
ipecamera-2e7a7a3534bcf591c0d6c65105b2d845f293112f.tar.bz2
ipecamera-2e7a7a3534bcf591c0d6c65105b2d845f293112f.tar.xz
ipecamera-2e7a7a3534bcf591c0d6c65105b2d845f293112f.zip
North West Logick DMA implementation
Diffstat (limited to 'driver')
-rw-r--r--driver/Makefile4
-rw-r--r--driver/base.c12
-rw-r--r--driver/common.h4
-rw-r--r--driver/config.h2
-rw-r--r--driver/ioctl.c7
-rw-r--r--driver/kmem.c48
-rw-r--r--driver/pciDriver.h14
7 files changed, 78 insertions, 13 deletions
diff --git a/driver/Makefile b/driver/Makefile
index 9f8918a..9eedc1e 100644
--- a/driver/Makefile
+++ b/driver/Makefile
@@ -6,8 +6,10 @@ KERNELDIR ?= /lib/modules/$(shell uname -r)/build
INSTALLDIR ?= /lib/modules/$(shell uname -r)/extra
PWD := $(shell pwd)
+EXTRA_CFLAGS += -I$(M)/..
+
default:
- $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
+ $(MAKE) $(CFLAGS) -C $(KERNELDIR) M=$(PWD) modules
install:
@mkdir -p $(INSTALLDIR)
diff --git a/driver/base.c b/driver/base.c
index 581e6d5..2c3ff23 100644
--- a/driver/base.c
+++ b/driver/base.c
@@ -319,6 +319,17 @@ static int __devinit pcidriver_probe(struct pci_dev *pdev, const struct pci_devi
mod_info("Couldn't enable device\n");
goto probe_pcien_fail;
}
+
+ /* Bus master & dma */
+ if ((id->vendor == PCIE_XILINX_VENDOR_ID)&&(id->device == PCIE_IPECAMERA_DEVICE_ID)) {
+ pci_set_master(pdev);
+
+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ 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)
@@ -404,6 +415,7 @@ probe_irq_probe_fail:
probe_nomem:
atomic_dec(&pcidriver_deviceCount);
probe_maxdevices_fail:
+probe_dma_fail:
pci_disable_device(pdev);
probe_pcien_fail:
return err;
diff --git a/driver/common.h b/driver/common.h
index 992f0ea..6036b0c 100644
--- a/driver/common.h
+++ b/driver/common.h
@@ -1,6 +1,8 @@
#ifndef _PCIDRIVER_COMMON_H
#define _PCIDRIVER_COMMON_H
+#include "pcilib_types.h"
+
/*************************************************************************/
/* Private data types and structures */
@@ -12,6 +14,8 @@ typedef struct {
dma_addr_t dma_handle;
unsigned long cpua;
unsigned long size;
+ unsigned long type;
+ unsigned long use;
struct class_device_attribute sysfs_attr; /* initialized when adding the entry */
} pcidriver_kmem_entry_t;
diff --git a/driver/config.h b/driver/config.h
index c217afd..a2b6946 100644
--- a/driver/config.h
+++ b/driver/config.h
@@ -3,7 +3,7 @@
/*******************************/
/* Debug messages */
-//#define DEBUG
+#define DEBUG
/* Enable/disable IRQ handling */
#define ENABLE_IRQ
diff --git a/driver/ioctl.c b/driver/ioctl.c
index dacf94a..64985e8 100644
--- a/driver/ioctl.c
+++ b/driver/ioctl.c
@@ -218,7 +218,12 @@ static int ioctl_kmem_sync(pcidriver_privdata_t *privdata, unsigned long arg)
int ret;
READ_FROM_USER(kmem_sync_t, ksync);
- return pcidriver_kmem_sync(privdata, &ksync);
+ if ((ret = pcidriver_kmem_sync(privdata, &ksync)) != 0)
+ return ret;
+
+ WRITE_TO_USER(kmem_sync_t, ksync);
+
+ return 0;
}
/*
diff --git a/driver/kmem.c b/driver/kmem.c
index 737b74d..95a5487 100644
--- a/driver/kmem.c
+++ b/driver/kmem.c
@@ -41,7 +41,8 @@ int pcidriver_kmem_alloc(pcidriver_privdata_t *privdata, kmem_handle_t *kmem_han
/* Initialize the kmem_entry */
kmem_entry->id = atomic_inc_return(&privdata->kmem_count) - 1;
- kmem_entry->size = kmem_handle->size;
+ kmem_entry->use = kmem_handle->use;
+ kmem_entry->type = kmem_handle->type;
kmem_handle->handle_id = kmem_entry->id;
/* Initialize sysfs if possible */
@@ -55,9 +56,25 @@ int pcidriver_kmem_alloc(pcidriver_privdata_t *privdata, kmem_handle_t *kmem_han
* CPU address is used for the mmap (internal to the driver), and
* PCI address is the address passed to the DMA Controller in the device.
*/
- retptr = pci_alloc_consistent( privdata->pdev, kmem_handle->size, &(kmem_entry->dma_handle) );
+ switch (kmem_entry->type) {
+ case PCILIB_KMEM_TYPE_CONSISTENT:
+ retptr = pci_alloc_consistent( privdata->pdev, kmem_handle->size, &(kmem_entry->dma_handle) );
+ break;
+ case PCILIB_KMEM_TYPE_PAGE:
+ retptr = (void*)__get_free_pages(GFP_KERNEL, get_order(PAGE_SIZE));
+ kmem_entry->dma_handle = 0;
+ kmem_handle->size = PAGE_SIZE;
+
+// kmem_entry->dma_handle = pci_map_single(privdata->pdev, retptr, PAGE_SIZE, PCI_DMA_FROMDEVICE);
+// printk("%llx %lx\n", kmem_entry->dma_handle, retptr);
+ break;
+ default:
+ goto kmem_alloc_mem_fail;
+ }
if (retptr == NULL)
goto kmem_alloc_mem_fail;
+
+ kmem_entry->size = kmem_handle->size;
kmem_entry->cpua = (unsigned long)retptr;
kmem_handle->pa = (unsigned long)(kmem_entry->dma_handle);
@@ -124,6 +141,17 @@ int pcidriver_kmem_sync( pcidriver_privdata_t *privdata, kmem_sync_t *kmem_sync
if ((kmem_entry = pcidriver_kmem_find_entry(privdata, &(kmem_sync->handle))) == NULL)
return -EINVAL; /* kmem_handle is not valid */
+
+ if (!kmem_entry->dma_handle) {
+ mod_info_dbg("Instead of synchronization, we are mapping kmem_entry with id: %d\n", kmem_entry->id);
+ if (kmem_sync->dir == PCIDRIVER_DMA_TODEVICE)
+ kmem_entry->dma_handle = pci_map_single(privdata->pdev, (void*)kmem_entry->cpua, kmem_entry->size, PCI_DMA_TODEVICE);
+ else
+ kmem_entry->dma_handle = pci_map_single(privdata->pdev, (void*)kmem_entry->cpua, kmem_entry->size, PCI_DMA_FROMDEVICE);
+
+ kmem_sync->handle.pa = kmem_entry->dma_handle;
+ }
+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
switch (kmem_sync->dir) {
case PCIDRIVER_DMA_TODEVICE:
@@ -197,7 +225,16 @@ int pcidriver_kmem_free_entry(pcidriver_privdata_t *privdata, pcidriver_kmem_ent
#endif
/* Release DMA memory */
- pci_free_consistent( privdata->pdev, kmem_entry->size, (void *)(kmem_entry->cpua), kmem_entry->dma_handle );
+ switch (kmem_entry->type) {
+ case PCILIB_KMEM_TYPE_CONSISTENT:
+ pci_free_consistent( privdata->pdev, kmem_entry->size, (void *)(kmem_entry->cpua), kmem_entry->dma_handle );
+ break;
+ case PCILIB_KMEM_TYPE_PAGE:
+ if (kmem_entry->dma_handle) pci_unmap_single(privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, PCI_DMA_TODEVICE);
+ free_page((unsigned long)kmem_entry->cpua);
+ break;
+ }
+
/* Remove the kmem list entry */
spin_lock( &(privdata->kmemlist_lock) );
@@ -226,7 +263,7 @@ pcidriver_kmem_entry_t *pcidriver_kmem_find_entry(pcidriver_privdata_t *privdata
list_for_each(ptr, &(privdata->kmem_list)) {
entry = list_entry(ptr, pcidriver_kmem_entry_t, list);
- if (entry->dma_handle == kmem_handle->pa) {
+ if (entry->id == kmem_handle->handle_id) {
result = entry;
break;
}
@@ -288,6 +325,7 @@ int pcidriver_mmap_kmem(pcidriver_privdata_t *privdata, struct vm_area_struct *v
/* Check sizes */
vma_size = (vma->vm_end - vma->vm_start);
+
if ((vma_size != kmem_entry->size) &&
((kmem_entry->size < PAGE_SIZE) && (vma_size != PAGE_SIZE))) {
mod_info("kem_entry size(%lu) and vma size do not match(%lu)\n", kmem_entry->size, vma_size);
@@ -316,6 +354,6 @@ int pcidriver_mmap_kmem(pcidriver_privdata_t *privdata, struct vm_area_struct *v
mod_info("kmem remap failed: %d (%lx)\n", ret,kmem_entry->cpua);
return -EAGAIN;
}
-
+
return ret;
}
diff --git a/driver/pciDriver.h b/driver/pciDriver.h
index 98c1301..94c98e7 100644
--- a/driver/pciDriver.h
+++ b/driver/pciDriver.h
@@ -57,6 +57,7 @@
*/
#include <linux/ioctl.h>
+#include "pcilib_types.h"
/* Identifies the PCI-E Xilinx ML605 */
#define PCIE_XILINX_VENDOR_ID 0x10ee
@@ -82,9 +83,9 @@
#define PCIDRIVER_MMAP_KMEM 1
/* Direction of a DMA operation */
-#define PCIDRIVER_DMA_BIDIRECTIONAL 0
-#define PCIDRIVER_DMA_TODEVICE 1
-#define PCIDRIVER_DMA_FROMDEVICE 2
+#define PCIDRIVER_DMA_BIDIRECTIONAL 0
+#define PCIDRIVER_DMA_TODEVICE PCILIB_KMEM_SYNC_TODEVICE
+#define PCIDRIVER_DMA_FROMDEVICE PCILIB_KMEM_SYNC_FROMDEVICE
/* Possible sizes in a PCI command */
#define PCIDRIVER_PCI_CFG_SZ_BYTE 1
@@ -100,8 +101,11 @@
/* Types */
typedef struct {
+ unsigned long type;
unsigned long pa;
unsigned long size;
+ unsigned long align;
+ unsigned long use;
int handle_id;
} kmem_handle_t;
@@ -171,8 +175,8 @@ typedef struct {
#define PCIDRIVER_IOC_MMAP_MODE _IO( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 0 )
#define PCIDRIVER_IOC_MMAP_AREA _IO( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 1 )
#define PCIDRIVER_IOC_KMEM_ALLOC _IOWR( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 2, kmem_handle_t * )
-#define PCIDRIVER_IOC_KMEM_FREE _IOW( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 3, kmem_handle_t * )
-#define PCIDRIVER_IOC_KMEM_SYNC _IOW( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 4, kmem_sync_t * )
+#define PCIDRIVER_IOC_KMEM_FREE _IOW ( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 3, kmem_handle_t * )
+#define PCIDRIVER_IOC_KMEM_SYNC _IOWR( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 4, kmem_sync_t * )
#define PCIDRIVER_IOC_UMEM_SGMAP _IOWR( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 5, umem_handle_t * )
#define PCIDRIVER_IOC_UMEM_SGUNMAP _IOW( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 6, umem_handle_t * )
#define PCIDRIVER_IOC_UMEM_SGGET _IOWR( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 7, umem_sglist_t * )