-
/**
-
* This program is an attempt to latch
on to the FG memory that is shared with the FPGA
-
* After a data sample has been taken
the fg stores the data in this region.
-
* This Driver will latch on to the DEV
file named pciproto. For testing purposes the /dev/pciproto
has to be
-
*created manually in the /dev folder.
The following command will create a DEV file with a maximum
number of
-
*250 and a minor number of 0: mknod
pciproto c 250 0
-
*
-
* There are only 3 registers:
-
* STATUS: addr = BAR2 + 0
-
* unused for now
-
* READ_DATA: addr = BAR2 + 1
-
* this register can only be read.
Each time it's read, the device
-
* read a byte from his input and
return it.
-
* WRITE_DATA: addr = BAR2 + 2
-
* this register can only be
written. Each time it's written, the device
-
* write the byte on his output.
-
*
-
*/
-
-
#include
<linux/kernel.h>
-
#include
<linux/init.h>
-
#include
<linux/module.h>
-
#include
<linux/pci.h>
-
#include
<linux/fs.h>
-
#include
<linux/cdev.h> /* for cdev_ */
-
#include
<asm/uaccess.h> /* for put_user */
-
#include
<linux/ioport.h>
-
-
#define
MAX_DEVICE 8
-
#define
DEVICE_NAME "pciproto"
-
#define BAR_IO
2
-
#define BAR_MEM
3
-
#define
BAR_SETTINGS 2
-
#define
BAR_PHOTO_MEM 3
-
-
-
MODULE_DESCRIPTION("Test PCI driver");
-
MODULE_AUTHOR("Gerfg ");
-
MODULE_LICENSE("GPL");
-
-
/**
-
* This table holds the list of
(VendorID,DeviceID) supported by this driver
-
*
-
*/
-
static struct pci_device_id pci_ids[] = {
-
{ PCI_DEVICE(0x10B5, 0x9054), },
-
{ 0, }
-
};
-
-
/**
-
* This macro ...
-
*
-
*/
-
MODULE_DEVICE_TABLE(pci, pci_ids);
-
-
static dev_t devno;
-
static int major;
-
-
/**
-
* This structure is used to link a
pci_dev to a cdev
-
*
-
*/
-
struct pci_cdev {
-
int minor;
-
struct pci_dev *pci_dev;
-
struct cdev *cdev;
-
};
-
-
static struct pci_cdev pci_cdev[MAX_DEVICE];
-
-
/* this function initialize the table
with all struct pci_cdev */
-
static void pci_cdev_init(struct pci_cdev pci_cdev[], int size, int first_minor)
-
{
-
int i;
-
-
for(i=0; i<size; i++) {
-
pci_cdev[i].minor = first_minor++;
-
pci_cdev[i].pci_dev = NULL;
-
pci_cdev[i].cdev = NULL;
-
printk(KERN_INFO "RAN:
pci_dev_init(-pci_cdev-,%i,%i)\n",size,pci_cdev[i].minor);
-
}
-
}
-
-
/*
-
-1 => failed
-
others => succes
-
*/
-
static int pci_cdev_add(struct pci_cdev pci_cdev[], int size, struct pci_dev *pdev)
-
{
-
int i, res = -1;
-
-
for(i=0; i<size; i++) {
-
if (pci_cdev[i].pci_dev == NULL) {
-
pci_cdev[i].pci_dev = pdev;
-
res = pci_cdev[i].minor;
-
printk(KERN_INFO "RAN:
pci_cdev_add(-pci_cdev-,%i,-dev-)\n",size);
-
break;
-
}
-
}
-
-
return res;
-
}
-
-
static void pci_cdev_del(struct pci_cdev pci_cdev[], int size, struct pci_dev *pdev)
-
{
-
int i;
-
-
for(i=0; i<size; i++) {
-
if (pci_cdev[i].pci_dev == pdev) {
-
pci_cdev[i].pci_dev = NULL;
-
printk(KERN_INFO "RAN:
pci_cdev_del(pci_cdevm,%i,dev)\n",size);
-
}
-
}
-
}
-
-
static struct pci_dev *pci_cdev_search_pci_dev(struct pci_cdev pci_cdev[], int size, int minor)
-
{
-
int i;
-
struct pci_dev *pdev = NULL;
-
-
for(i=0; i<size; i++) {
-
if (pci_cdev[i].minor == minor) {
-
pdev = pci_cdev[i].pci_dev;
-
break;
-
printk(KERN_INFO "RAN:
pci_cdev_search_pci_dev()\n");
-
}
-
}
-
-
return pdev;
-
}
-
-
static struct cdev *pci_cdev_search_cdev(struct pci_cdev pci_cdev[], int size, int minor)
-
{
-
int i;
-
struct cdev *cdev = NULL;
-
-
for(i=0; i<size; i++) {
-
if (pci_cdev[i].minor == minor) {
-
cdev = pci_cdev[i].cdev;
-
break;
-
}
-
}
-
printk(KERN_INFO "RAN: pci_cdev_search_cdev()\n");
-
return cdev;
-
}
-
-
/*
-
-1 => not found
-
others => found
-
*/
-
static int pci_cdev_search_minor(struct pci_cdev pci_cdev[],
-
int size, struct pci_dev *pdev)
-
{
-
int i, minor = -1;
-
-
for(i=0; i<size; i++) {
-
if (pci_cdev[i].pci_dev == pdev) {
-
minor = pci_cdev[i].minor;
-
break;
-
}
-
}
-
printk(KERN_INFO "RAN: pci_cdev_search_minor()\n");
-
return minor;
-
}
-
-
-
-
/**
-
* This function is called when the
device node is opened
-
*
-
*/
-
static int pci_open(struct inode *inode, struct file *file)
-
{
-
int minor = iminor(inode);
-
file->private_data = (void *)pci_cdev_search_pci_dev(pci_cdev, MAX_DEVICE, minor);
-
printk(KERN_INFO "RAN: pci_open()\n");
-
return 0;
-
}
-
-
/**
-
* This function is called when the
device node is closed
-
*
-
*/
-
static int pci_release(struct inode *inode, struct file *file)
-
{
-
return 0;
-
}
-
-
/**
-
* This function is called when the
device node is read
-
*
-
*/
-
static ssize_t pci_read(struct file *file, /*
see include/linux/fs.h */
-
char *buffer, /*
buffer to fill with data */
-
size_t length, /*
length of the buffer */
-
loff_t * offset)
-
{
-
int byte_read = 0;
-
unsigned char value;
-
struct pci_dev *pdev = (struct pci_dev *)file->private_data;
-
unsigned long pci_io_addr = 0;
-
-
pci_io_addr = pci_resource_start(pdev,BAR_IO);
-
-
while (byte_read < length) {
-
/* read a byte from the input */
-
value = inb(pci_io_addr + 1);
-
-
/* write the value in the user buffer
*/
-
put_user(value, &buffer[byte_read]);
-
-
byte_read++;
-
}
-
printk(KERN_INFO "RAN: pci_read()\n");
-
return byte_read;
-
}
-
-
/**
-
* This function is called when the
device node is read
-
*
-
*/
-
static ssize_t pci_write(struct file *filp, const char *buffer, size_t len, loff_t * off) {
-
int i;
-
unsigned char value;
-
struct pci_dev *pdev = (struct pci_dev *)filp->private_data;
-
unsigned long pci_reg_mem_addr = 0lu;
-
unsigned long pci_photo_mem_addr = 0lu;
-
unsigned int dma_mask = 1;
-
int test=2;
-
const char *MemRegionName = NULL;
-
//uint32_t
*NEW;
-
//MemRegionName
= (const char*)malloc(sizeof(const char));
-
printk(KERN_INFO "RAN: pci_write()\n");
-
pci_reg_mem_addr = pci_resource_start(pdev,BAR_SETTINGS);
-
pci_photo_mem_addr = pci_resource_start(pdev,BAR_PHOTO_MEM);
-
printk(KERN_INFO "Device VendorID = %x ,
DeviceID = %x",pdev->vendor,pdev->device);
-
printk(KERN_INFO "DATA WRITTEN TO DEVICE:");
-
for(i=0; i<len; i++) {
-
/* read value on the buffer */
-
value = (unsigned char)buffer[i];
-
printk(KERN_INFO "%c",value);
-
/* write data to the device */
-
outb(pci_reg_mem_addr+2, value);
-
-
}
-
-
-
if ((test=(pci_set_dma_mask(pdev,dma_mask)))<0)
-
{
-
printk(KERN_INFO "PCI device failed DMA
support test returned %u \n",test);
-
}
-
else
-
{
-
printk(KERN_INFO "PCI Dev supports DMA\n");
-
}
-
-
-
-
if ((test=(pci_request_region(pdev,BAR_PHOTO_MEM,MemRegionName)))!=0)
-
{
-
printk(KERN_INFO "request region failed:
returned %u \n",test);
-
}
-
else
-
{
-
printk(KERN_INFO "Request region success!\n");
-
}
-
-
//NEW
= (uint32_t
*)mmap(0,0x7fffff,MAP_SHARED,0,"/dev/FGpci",BAR_PHOTO_MEM);
-
-
test = check_mem_region(pci_photo_mem_addr,0x7ffffe);
-
printk(KERN_INFO "Region check returned %x \n",test);
-
outb(pci_reg_mem_addr+4, 0b00000111);
-
outb(pci_reg_mem_addr+5, 0b00000001);
-
//prototype
pci_resource_start(*pdev,BAR);
-
printk("BAR_PHOTO_MEM
Starts at 0x%x and len is 0x%x",pci_resource_start(pdev,BAR_PHOTO_MEM),pci_resource_len(pdev,BAR_PHOTO_MEM));
-
-
printk(KERN_INFO "\n");
-
printk(KERN_INFO "CHILD: pci_reg_mem_addr =
%lx \n",pci_reg_mem_addr);
-
printk(KERN_INFO "CHILD: pci_photo_mem_addr =
%lx \n",pci_photo_mem_addr);
-
printk(KERN_INFO "CHILD: pci_reg_mem_addr+4 =
%lx || pci_reg_mem_addr+5 = %lx \n",
-
(pci_reg_mem_addr+4),(pci_reg_mem_addr+5));
-
outb(pci_reg_mem_addr+5, 0b00000000);
-
return len;
-
}
-
-
/**
-
* This structure holds informations
about the pci node
-
*
-
*/
-
static struct file_operations
pci_ops = {
-
.owner
= THIS_MODULE,
-
.read = pci_read,
-
.write = pci_write,
-
.open = pci_open,
-
.release = pci_release
-
};
-
-
-
/**
-
* This function is called when a new
pci device is associated with a driver
-
*
-
* return: 0 => this driver don't
handle this device
-
* 1 => this driver handle
this device
-
*
-
*/
-
static int pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
-
{
-
int ret, minor;
-
struct cdev *cdev;
-
dev_t devno;
-
-
/*
add this pci device in pci_cdev */
-
if ((minor = pci_cdev_add(pci_cdev, MAX_DEVICE, dev)) < 0)
-
goto error;
-
-
/*
compute major/minor number */
-
devno = MKDEV(major, minor);
-
-
/*
allocate struct cdev */
-
cdev = cdev_alloc();
-
-
/*
initialise struct cdev */
-
cdev_init(cdev, &pci_ops);
-
cdev->owner = THIS_MODULE;
-
-
/*
register cdev */
-
ret = cdev_add(cdev, devno, 1);
-
if (ret < 0) {
-
dev_err(&(dev->dev), "Can't register character
device\n");
-
goto error;
-
}
-
pci_cdev[minor].cdev = cdev;
-
-
dev_info(&(dev->dev), "%s The major device number
is %d (%d).\n",
-
"Registeration
is a success", MAJOR(devno), MINOR(devno));
-
dev_info(&(dev->dev), "If you want to talk to the
device driver,\n");
-
dev_info(&(dev->dev), "you'll have to create a
device file. \n");
-
dev_info(&(dev->dev), "We suggest you use:\n");
-
dev_info(&(dev->dev), "mknod %s c %d %d\n", DEVICE_NAME, MAJOR(devno), MINOR(devno));
-
dev_info(&(dev->dev), "The device file name is
important, because\n");
-
dev_info(&(dev->dev), "the ioctl program assumes
that's the\n");
-
dev_info(&(dev->dev), "file you'll use.\n");
-
-
/*
enable the device */
-
pci_enable_device(dev);
-
-
/*
'alloc' IO to talk with the card */
-
if (pci_request_region(dev, BAR_PHOTO_MEM, "MEM-pci") == 0) {
-
dev_err(&(dev->dev), "Can't request BAR2\n");
-
cdev_del(cdev);
-
goto error;
-
}
-
-
/*
check that BAR_IO is *really* IO region */
-
if ((pci_resource_flags(dev, BAR_PHOTO_MEM) & IORESOURCE_MEM) != IORESOURCE_MEM) {
-
dev_err(&(dev->dev), "BAR2 isn't an IO region\n");
-
cdev_del(cdev);
-
goto error;
-
}
-
-
-
return 1;
-
-
error:
-
return 0;
-
}
-
-
/**
-
* This function is called when the
driver is removed
-
*
-
*/
-
static void pci_remove(struct pci_dev *dev)
-
{
-
int minor;
-
struct cdev *cdev;
-
-
/*
remove associated cdev */
-
minor = pci_cdev_search_minor(pci_cdev, MAX_DEVICE, dev);
-
cdev = pci_cdev_search_cdev(pci_cdev, MAX_DEVICE, minor);
-
if (cdev != NULL)
-
cdev_del(cdev);
-
-
/*
remove this device from pci_cdev */
-
pci_cdev_del(pci_cdev, MAX_DEVICE, dev);
-
-
/*
release the IO region */
-
pci_release_region(dev, BAR_IO);
-
}
-
-
/**
-
* This structure holds informations
about the pci driver
-
*
-
*/
-
static struct pci_driver pci_driver = {
-
.name = "pci",
-
.id_table = pci_ids,
-
.probe = pci_probe,
-
.remove = pci_remove,
-
};
-
-
-
/**
-
* This function is called when the
module is loaded
-
*
-
*/
-
static int __init pci_init_module(void)
-
{
-
int ret;
-
-
printk(KERN_DEBUG "Module pci init\n");
-
-
/*
allocate (several) major number */
-
ret = alloc_chrdev_region(&devno, 0, MAX_DEVICE, "buffer");
-
if (ret < 0) {
-
printk(KERN_ERR "Can't get major\n");
-
return ret;
-
}
-
-
/*
get major number and save it in major */
-
major = MAJOR(devno);
-
-
/*
initialise pci_cdev */
-
pci_cdev_init(pci_cdev, MAX_DEVICE, MINOR(devno));
-
-
/*
register pci driver */
-
ret = pci_register_driver(&pci_driver);
-
if (ret < 0) {
-
/* free major/minor number */
-
unregister_chrdev_region(devno, 1);
-
-
printk(KERN_ERR "pci-driver: can't register
pci driver\n");
-
return ret;
-
}
-
-
-
return 0;
-
}
-
-
/**
-
* This function is called when the
module is unloaded
-
*
-
*/
-
static void pci_exit_module(void)
-
{
-
int i;
-
-
/*
unregister pci driver */
-
pci_unregister_driver(&pci_driver);
-
-
/*
unregister character device */
-
for(i=0; i< MAX_DEVICE; i++) {
-
if (pci_cdev[i].pci_dev != NULL) {
-
cdev_del(pci_cdev[i].cdev);
-
}
-
}
-
-
/*
free major/minor number */
-
unregister_chrdev_region(devno, MAX_DEVICE);
-
-
printk(KERN_DEBUG "Module pci exit\n");
-
}
-
-
module_init(pci_init_module);
-
module_exit(pci_exit_module);
-
Dec 10
09:00:49 dcam-desktop kernel: [ 2228.879644] Module pci init
-
Dec 10
09:00:49 dcam-desktop kernel: [ 2228.879659] RAN:
pci_dev_init(-pci_cdev-,8,0)
-
Dec 10
09:00:49 dcam-desktop kernel: [ 2228.879663] RAN:
pci_dev_init(-pci_cdev-,8,1)
-
Dec 10
09:00:49 dcam-desktop kernel: [ 2228.879667] RAN:
pci_dev_init(-pci_cdev-,8,2)
-
Dec 10
09:00:49 dcam-desktop kernel: [ 2228.879670] RAN:
pci_dev_init(-pci_cdev-,8,3)
-
Dec 10
09:00:49 dcam-desktop kernel: [ 2228.879673] RAN:
pci_dev_init(-pci_cdev-,8,4)
-
Dec 10
09:00:49 dcam-desktop kernel: [ 2228.879677] RAN:
pci_dev_init(-pci_cdev-,8,5)
-
Dec 10
09:00:49 dcam-desktop kernel: [ 2228.879680] RAN:
pci_dev_init(-pci_cdev-,8,6)
-
Dec 10
09:00:49 dcam-desktop kernel: [ 2228.879683] RAN:
pci_dev_init(-pci_cdev-,8,7)
-
Dec 10
09:00:49 dcam-desktop kernel: [ 2228.879742] RAN:
pci_cdev_add(-pci_cdev-,8,-dev-)
-
Dec 10
09:00:49 dcam-desktop kernel: [ 2228.879754] pci 0000:02:05.0:
Registeration is a success The major device number is 250 (0).
-
Dec 10
09:00:49 dcam-desktop kernel: [ 2228.879760] pci 0000:02:05.0:
If you want to talk to the device driver,
-
Dec 10
09:00:49 dcam-desktop kernel: [ 2228.879765] pci 0000:02:05.0:
you'll have to create a device file.
-
Dec 10
09:00:49 dcam-desktop kernel: [ 2228.879769] pci 0000:02:05.0:
We suggest you use:
-
Dec 10
09:00:49 dcam-desktop kernel: [ 2228.879775] pci 0000:02:05.0:
mknod FGpci c 250 0
-
Dec 10
09:00:49 dcam-desktop kernel: [ 2228.879780] pci 0000:02:05.0:
The device file name is important, because
-
Dec 10
09:00:49 dcam-desktop kernel: [ 2228.879785] pci 0000:02:05.0:
the ioctl program assumes that's the
-
Dec 10
09:00:49 dcam-desktop kernel: [ 2228.879790] pci 0000:02:05.0:
file you'll use.
-
Dec 10
09:00:49 dcam-desktop kernel: [ 2228.879807] pci 0000:02:05.0:
BAR 3: can't reserve [mem 0xe0800000-0xe0ffffff]
-
Dec 10
09:00:49 dcam-desktop kernel: [ 2228.879813] pci 0000:02:05.0:
Driver probe function unexpectedly returned 1
-
Dec 10
09:00:53 dcam-desktop kernel: [ 2233.073319] RAN: pci_open()
-
Dec 10
09:00:53 dcam-desktop kernel: [ 2233.073360] RAN: pci_write()
-
Dec 10
09:00:53 dcam-desktop kernel: [ 2233.073365] Device VendorID =
10b5 , DeviceID = 9054
-
Dec 10
09:00:53 dcam-desktop kernel: [ 2233.073368] DATA WRITTEN TO
DEVICE:w
-
Dec 10
09:00:53 dcam-desktop kernel: [ 2233.073374] ri
-
Dec 10
09:00:53 dcam-desktop kernel: [ 2233.073381] te
-
Dec 10
09:00:53 dcam-desktop kernel: [ 2233.073387]
-
Dec 10
09:00:53 dcam-desktop kernel: [ 2233.073392] PCI device failed
DMA support test returned 4294967291
-
Dec 10
09:00:53 dcam-desktop kernel: [ 2233.073411] pci 0000:02:05.0:
BAR 3: can't reserve [mem 0xe0800000-0xe0ffffff]
-
Dec 10
09:00:53 dcam-desktop kernel: [ 2233.073415] request region
failed: returned 4294967280
-
Dec 10
09:00:53 dcam-desktop kernel: [ 2233.073419] Region check
returned fffffff0
-
Dec 10
09:00:53 dcam-desktop kernel: [ 2233.073425] BAR_PHOTO_MEM
Starts at 0xe0800000 and len is 0x0
-
Dec 10
09:00:53 dcam-desktop kernel: [ 2233.073427]
-
Dec 10
09:00:53 dcam-desktop kernel: [ 2233.073431] CHILD:
pci_reg_mem_addr = e0201000
-
Dec 10
09:00:53 dcam-desktop kernel: [ 2233.073434] CHILD:
pci_photo_mem_addr = e0800000
-
Dec 10
09:00:53 dcam-desktop kernel: [ 2233.073438] CHILD:
pci_reg_mem_addr+4 = e0201004 || pci_reg_mem_addr+5 = e0201005
-
Dec 10
09:20:35 dcam-desktop kernel: [ 3414.852735] e100 0000:02:08.0
eth0: NIC Link is Up 100 Mbps Full Duplex