Browse Source

Add two bars

sono 5 years ago
parent
commit
eb31b7f57f
  1. 245
      usdpci.c
  2. 2
      usdpci.rules

245
usdpci.c

@ -12,6 +12,7 @@
#include <linux/spinlock_types.h> #include <linux/spinlock_types.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/cdev.h> #include <linux/cdev.h>
#include <linux/sched.h> #include <linux/sched.h>
@ -19,13 +20,14 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/poll.h> #include <linux/poll.h>
/*************************************************************************************************/
#define DMA_ADDR_OFFSET 32
#define PRINT(A) printk(KERN_ALERT ">>>>> #A %x\n", A); #define PRINT(A) printk(KERN_ALERT ">>>>> #A %x\n", A);
/*************************************************************************************************/
MODULE_AUTHOR("h4ndh"); //hediyehloo based on Talaee works MODULE_AUTHOR("h4ndh"); //hediyehloo based on Talaee works
MODULE_LICENSE("Dual BSD/GPL"); MODULE_LICENSE("Dual BSD/GPL");
/*************************************************************************************************/
static struct pci_device_id pcie_ids[] = static struct pci_device_id pcie_ids[] =
{ {
{PCI_DEVICE(0x10ee, 0x7024)}, {PCI_DEVICE(0x10ee, 0x7024)},
@ -33,43 +35,28 @@ static struct pci_device_id pcie_ids[] =
}; };
MODULE_DEVICE_TABLE(pci, pcie_ids); MODULE_DEVICE_TABLE(pci, pcie_ids);
static irqreturn_t interrupt_handler(int irq, void *p); /*************************************************************************************************/
static struct pci_dev *pcidev = NULL; static struct pci_dev *pcidev = NULL;
static unsigned int chrdev_major = 0;
static unsigned int chrdev_minor = 0;
static unsigned int ioctl_alloc_dma = 0;
static unsigned int ioctl_refresh_link = 1;
static unsigned long bar0_addr;
static unsigned long bar0_size = 64 * 1024;
static void* bar0_ptr;
static unsigned long bar1_addr;
static unsigned long bar1_size = 128 * 1024 * 1024;
static void* bar1_ptr;
static unsigned int irq;
struct page** dma_pages = NULL;
unsigned int dma_pages_count = 0;
void* dma_addr = NULL;
unsigned long mmap_buffersize = 4 * 1024; //4KB
/*************************************************************************************************/ /*************************************************************************************************/
static int pcie_init(void); static int pcie_init(void);
static int chrdev_init(void); static void pcie_exit(void);
static int usd_open(struct inode *inode, struct file *flip);
static int usd_mmap(struct file *filp, struct vm_area_struct *vma);
static unsigned int usd_poll (struct file *filp, poll_table *wait);
static int pcie_probe (struct pci_dev *dev, const struct pci_device_id *id); static int pcie_probe (struct pci_dev *dev, const struct pci_device_id *id);
static void pcie_remove(struct pci_dev *dev); static void pcie_remove(struct pci_dev *dev);
static void pcie_exit(void);
static int chrdev_init(void);
static int usd_open_0(struct inode *inode, struct file *flip);
static int usd_close_0(struct inode *inode, struct file *filp);
static int usd_mmap_0(struct file *filp, struct vm_area_struct *vma);
static int usd_open_1(struct inode *inode, struct file *flip);
static int usd_close_1(struct inode *inode, struct file *filp);
static int usd_mmap_1(struct file *filp, struct vm_area_struct *vma);
static int usd_open_2(struct inode *inode, struct file *flip);
static int usd_close_2(struct inode *inode, struct file *filp);
static int usd_mmap_2(struct file *filp, struct vm_area_struct *vma);
/*************************************************************************************************/ /*************************************************************************************************/
static dev_t chrdev; static dev_t chrdev;
@ -78,16 +65,19 @@ static struct class *class = NULL;
#define DEV_NAME "usd_reg" #define DEV_NAME "usd_reg"
#define CLASS_NAME "usdpci" #define CLASS_NAME "usdpci"
#define NODE_0_NAME "usd_reg0"
struct file_operations chrdev_fops = /*************************************************************************************************/
{ #define TOTAL_BAR_NUM 2
.owner = THIS_MODULE,
.open = usd_open, struct bar_t{
.mmap = usd_mmap, unsigned long bar_addr;
.poll = usd_poll unsigned long bar_size;
void* bar_ptr;
struct file_operations chrdev_fops;
}; };
struct bar_t bars[TOTAL_BAR_NUM];
/*************************************************************************************************/ /*************************************************************************************************/
static struct pci_driver pci_driver = static struct pci_driver pci_driver =
{ {
@ -114,6 +104,27 @@ static int __init pcie_init(void)
return res; return res;
} }
//gone have 3 bar for now
bars[0].chrdev_fops.owner = THIS_MODULE;
bars[0].chrdev_fops.open = usd_open_0;
bars[0].chrdev_fops.mmap = usd_mmap_0;
bars[0].chrdev_fops.release = usd_close_0;
bars[0].bar_size = 4 * 1024;
bars[1].chrdev_fops.owner = THIS_MODULE;
bars[1].chrdev_fops.open = usd_open_1;
bars[1].chrdev_fops.mmap = usd_mmap_1;
bars[1].chrdev_fops.release = usd_close_1;
bars[1].bar_size = 128 * 1024 * 1024;
// bars[2].chrdev_fops = {
// .owner = THIS_MODULE,
// .open = usd_open_2,
// .mmap = usd_mmap_2,
// .release = usd_close_2
// };
// bars[2].bar_size = 4 * 1024;
PRINT_ALERT("register driver success" ); PRINT_ALERT("register driver success" );
res = chrdev_init(); res = chrdev_init();
@ -131,44 +142,113 @@ static int chrdev_init(void)
{ {
PRINT_ALERT("chrdev_init"); PRINT_ALERT("chrdev_init");
int res = 0; char name[16];
struct device *device = NULL; int i = 0;
for( ;i < TOTAL_BAR_NUM; i++)
res = alloc_chrdev_region(&chrdev, 0, 1, DEV_NAME);
if(res < 0)
{ {
return -1; sprintf(name, "%s_%d", DEV_NAME, i);
proc_create(name, 0, NULL, &bars[i].chrdev_fops);
} }
cdev_init(&cdev, &chrdev_fops); return 0;
res = cdev_add(&cdev, chrdev, 1); }
if (res)
{ /*************************************************************************************************/
unregister_chrdev_region(chrdev, 1); static int usd_open_0(struct inode *inode, struct file *filp)
return res; {
} return 0;
}
class = class_create(THIS_MODULE, CLASS_NAME); /*************************************************************************************************/
device = device_create(class, NULL, chrdev, NULL, NODE_0_NAME); static int usd_open_1(struct inode *inode, struct file *filp)
{
return 0;
}
return 0; /*************************************************************************************************/
static int usd_open_2(struct inode *inode, struct file *filp)
{
return 0;
} }
/*************************************************************************************************/ /*************************************************************************************************/
static int usd_open(struct inode *inode, struct file *flip) static int usd_close_0(struct inode *inode, struct file *filp)
{ {
return 0;
}
/*************************************************************************************************/
static int usd_close_1(struct inode *inode, struct file *filp)
{
return 0;
}
/*************************************************************************************************/
static int usd_close_2(struct inode *inode, struct file *filp)
{
return 0;
}
/*************************************************************************************************/
static int usd_mmap_0(struct file *filp, struct vm_area_struct *vma)
{
PRINT_ALERT("MMAP");
unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
unsigned long vsize = vma->vm_end - vma->vm_start;
unsigned long physical = bars[0].bar_addr + off;
unsigned int intvsize = bars[0].bar_size - off;
// these are required for io maps, but is it okay for the buffer as well?
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
vma->vm_flags |= VM_IO;
if ( vsize < intvsize )
intvsize = vsize;
remap_pfn_range(vma, vma->vm_start, physical>>PAGE_SHIFT, intvsize, vma->vm_page_prot);
return 0; return 0;
} }
/*************************************************************************************************/ /*************************************************************************************************/
static int usd_mmap(struct file *filp, struct vm_area_struct *vma) static int usd_mmap_1(struct file *filp, struct vm_area_struct *vma)
{ {
PRINT_ALERT("MMAP");
unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
unsigned long vsize = vma->vm_end - vma->vm_start;
unsigned long physical = bars[1].bar_addr + off;
unsigned int intvsize = bars[1].bar_size - off;
// these are required for io maps, but is it okay for the buffer as well?
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
vma->vm_flags |= VM_IO;
if ( vsize < intvsize )
intvsize = vsize;
remap_pfn_range(vma, vma->vm_start, physical>>PAGE_SHIFT, intvsize, vma->vm_page_prot);
return 0; return 0;
} }
/*************************************************************************************************/ /*************************************************************************************************/
static unsigned int usd_poll (struct file *filp, poll_table *wait) static int usd_mmap_2(struct file *filp, struct vm_area_struct *vma)
{ {
PRINT_ALERT("MMAP");
unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
unsigned long vsize = vma->vm_end - vma->vm_start;
unsigned long physical = bars[2].bar_addr + off;
unsigned int intvsize = bars[2].bar_size - off;
// these are required for io maps, but is it okay for the buffer as well?
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
vma->vm_flags |= VM_IO;
if ( vsize < intvsize )
intvsize = vsize;
remap_pfn_range(vma, vma->vm_start, physical>>PAGE_SHIFT, intvsize, vma->vm_page_prot);
return 0; return 0;
} }
@ -184,6 +264,7 @@ static int __init pcie_probe (struct pci_dev *dev, const struct pci_device_id *i
goto probe_fail_enable; goto probe_fail_enable;
} }
/***************BAR 0***********************/
if(!(pci_resource_flags(dev, 0) & IORESOURCE_MEM)) if(!(pci_resource_flags(dev, 0) & IORESOURCE_MEM))
{ {
printk(KERN_ERR "USDriver PCIe driver incorrect BAR configuration\n" ); printk(KERN_ERR "USDriver PCIe driver incorrect BAR configuration\n" );
@ -191,7 +272,7 @@ static int __init pcie_probe (struct pci_dev *dev, const struct pci_device_id *i
goto probe_fail; goto probe_fail;
} }
bar0_addr = pci_resource_start(dev, 0); bars[0].bar_addr = pci_resource_start(dev, 0);
rc = pci_request_region(dev, 0, "bar0"); rc = pci_request_region(dev, 0, "bar0");
if(rc) if(rc)
{ {
@ -199,8 +280,8 @@ static int __init pcie_probe (struct pci_dev *dev, const struct pci_device_id *i
goto probe_fail; goto probe_fail;
} }
bar0_ptr = pci_iomap(dev, 0, bar0_size); bars[0].bar_ptr = pci_iomap(dev, 0, bars[0].bar_size);
u32* bar0_data = (u32*)bar0_ptr; u32* bar0_data = (u32*)bars[0].bar_ptr;
if(bar0_data == 0) if(bar0_data == 0)
{ {
@ -216,7 +297,7 @@ static int __init pcie_probe (struct pci_dev *dev, const struct pci_device_id *i
goto probe_fail; goto probe_fail;
} }
bar1_addr = pci_resource_start(dev, 1); bars[1].bar_addr = pci_resource_start(dev, 1);
rc = pci_request_region(dev, 1, "bar1"); rc = pci_request_region(dev, 1, "bar1");
if(rc) if(rc)
{ {
@ -224,8 +305,8 @@ static int __init pcie_probe (struct pci_dev *dev, const struct pci_device_id *i
goto probe_fail; goto probe_fail;
} }
bar1_ptr = pci_iomap(dev, 1, bar1_size); bars[1].bar_ptr = pci_iomap(dev, 1, bars[1].bar_size);
u32* bar1_data = (u32*)bar1_ptr; u32* bar1_data = (u32*)bars[1].bar_ptr;
if(bar1_data == 0) if(bar1_data == 0)
{ {
@ -257,21 +338,11 @@ static void pcie_remove(struct pci_dev *dev)
{ {
PRINT_ALERT("remove driver"); PRINT_ALERT("remove driver");
int i;
u8* bar0_data;
bar0_data = (u8*)bar0_ptr;
for ( i = 0; i < dma_pages_count; i++ ) {
pci_unmap_single(pcidev, bar0_data[DMA_ADDR_OFFSET + 4*i], PAGE_SIZE, DMA_BIDIRECTIONAL);
__free_page(dma_pages[i]);
}
if (dma_pages != NULL) kfree(dma_pages);
PRINT_ALERT("Freed DMA pages");
pci_clear_master(dev); pci_clear_master(dev);
PRINT_ALERT("Cleared PCIe master"); PRINT_ALERT("Cleared PCIe master");
pci_iounmap(dev, bar0_ptr); pci_iounmap(dev, bars[0].bar_ptr);
pci_iounmap(dev, bar1_ptr); pci_iounmap(dev, bars[1].bar_ptr);
PRINT_ALERT("IOunmap"); PRINT_ALERT("IOunmap");
pci_release_regions(dev); pci_release_regions(dev);
@ -288,18 +359,14 @@ static void __exit pcie_exit(void)
PRINT_ALERT("driver unregistering"); PRINT_ALERT("driver unregistering");
pci_unregister_driver(&pci_driver); pci_unregister_driver(&pci_driver);
PRINT_ALERT("unregister_chrdev_region"); char name[16];
unregister_chrdev_region(chrdev, 1); int i = 0;
for( ; i < TOTAL_BAR_NUM; i++)
PRINT_ALERT("cdev_del"); {
cdev_del(&cdev); snprintf(name, 8, "%s%d", DEV_NAME, i);
remove_proc_entry(name, NULL);
PRINT_ALERT("device_destroy"); }
device_destroy(class, chrdev);
PRINT_ALERT("class_destroy");
class_destroy(class);
PRINT_ALERT("driver unloaded"); PRINT_ALERT("driver unloaded");
} }

2
usdpci.rules

@ -1,2 +1,2 @@
ACTION=="add",SUBSYSTEM=="pci",ATTR{vendor}=="0x10ee", ATTR{device}="0x0007", RUN+="/sbin/modprobe uscpci" ACTION=="add",SUBSYSTEM=="pci",ATTR{vendor}=="0x10ee", ATTR{device}="0x7024", RUN+="/sbin/modprobe uscpci"
KERNEL=="usd_regs0",MODE="666" KERNEL=="usd_regs0",MODE="666"

Loading…
Cancel
Save