diff --git a/usdpci.c b/usdpci.c index f4d6df6..5f71327 100644 --- a/usdpci.c +++ b/usdpci.c @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -19,13 +20,14 @@ #include #include - -#define DMA_ADDR_OFFSET 32 +/*************************************************************************************************/ #define PRINT(A) printk(KERN_ALERT ">>>>> #A %x\n", A); +/*************************************************************************************************/ MODULE_AUTHOR("h4ndh"); //hediyehloo based on Talaee works MODULE_LICENSE("Dual BSD/GPL"); +/*************************************************************************************************/ static struct pci_device_id pcie_ids[] = { {PCI_DEVICE(0x10ee, 0x7024)}, @@ -33,43 +35,28 @@ static struct pci_device_id pcie_ids[] = }; MODULE_DEVICE_TABLE(pci, pcie_ids); -static irqreturn_t interrupt_handler(int irq, void *p); - +/*************************************************************************************************/ 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 chrdev_init(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 void pcie_exit(void); 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_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; @@ -78,16 +65,19 @@ static struct class *class = NULL; #define DEV_NAME "usd_reg" #define CLASS_NAME "usdpci" -#define NODE_0_NAME "usd_reg0" -struct file_operations chrdev_fops = -{ - .owner = THIS_MODULE, - .open = usd_open, - .mmap = usd_mmap, - .poll = usd_poll +/*************************************************************************************************/ +#define TOTAL_BAR_NUM 2 + +struct bar_t{ + unsigned long bar_addr; + 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 = { @@ -114,6 +104,27 @@ static int __init pcie_init(void) 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" ); res = chrdev_init(); @@ -131,44 +142,113 @@ static int chrdev_init(void) { PRINT_ALERT("chrdev_init"); - int res = 0; - struct device *device = NULL; - - res = alloc_chrdev_region(&chrdev, 0, 1, DEV_NAME); - if(res < 0) + char name[16]; + int i = 0; + for( ;i < TOTAL_BAR_NUM; i++) { - return -1; + sprintf(name, "%s_%d", DEV_NAME, i); + proc_create(name, 0, NULL, &bars[i].chrdev_fops); } - cdev_init(&cdev, &chrdev_fops); - res = cdev_add(&cdev, chrdev, 1); - if (res) - { - unregister_chrdev_region(chrdev, 1); - return res; - } + return 0; +} + +/*************************************************************************************************/ +static int usd_open_0(struct inode *inode, struct file *filp) +{ + 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; } /*************************************************************************************************/ -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; } /*************************************************************************************************/ -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; } @@ -184,6 +264,7 @@ static int __init pcie_probe (struct pci_dev *dev, const struct pci_device_id *i goto probe_fail_enable; } + /***************BAR 0***********************/ if(!(pci_resource_flags(dev, 0) & IORESOURCE_MEM)) { 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; } - bar0_addr = pci_resource_start(dev, 0); + bars[0].bar_addr = pci_resource_start(dev, 0); rc = pci_request_region(dev, 0, "bar0"); if(rc) { @@ -199,8 +280,8 @@ static int __init pcie_probe (struct pci_dev *dev, const struct pci_device_id *i goto probe_fail; } - bar0_ptr = pci_iomap(dev, 0, bar0_size); - u32* bar0_data = (u32*)bar0_ptr; + bars[0].bar_ptr = pci_iomap(dev, 0, bars[0].bar_size); + u32* bar0_data = (u32*)bars[0].bar_ptr; 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; } - bar1_addr = pci_resource_start(dev, 1); + bars[1].bar_addr = pci_resource_start(dev, 1); rc = pci_request_region(dev, 1, "bar1"); if(rc) { @@ -224,8 +305,8 @@ static int __init pcie_probe (struct pci_dev *dev, const struct pci_device_id *i goto probe_fail; } - bar1_ptr = pci_iomap(dev, 1, bar1_size); - u32* bar1_data = (u32*)bar1_ptr; + bars[1].bar_ptr = pci_iomap(dev, 1, bars[1].bar_size); + u32* bar1_data = (u32*)bars[1].bar_ptr; if(bar1_data == 0) { @@ -257,21 +338,11 @@ static void pcie_remove(struct pci_dev *dev) { 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); PRINT_ALERT("Cleared PCIe master"); - pci_iounmap(dev, bar0_ptr); - pci_iounmap(dev, bar1_ptr); + pci_iounmap(dev, bars[0].bar_ptr); + pci_iounmap(dev, bars[1].bar_ptr); PRINT_ALERT("IOunmap"); pci_release_regions(dev); @@ -288,18 +359,14 @@ static void __exit pcie_exit(void) PRINT_ALERT("driver unregistering"); pci_unregister_driver(&pci_driver); - - PRINT_ALERT("unregister_chrdev_region"); - unregister_chrdev_region(chrdev, 1); - - PRINT_ALERT("cdev_del"); - cdev_del(&cdev); - - PRINT_ALERT("device_destroy"); - device_destroy(class, chrdev); - - PRINT_ALERT("class_destroy"); - class_destroy(class); + + char name[16]; + int i = 0; + for( ; i < TOTAL_BAR_NUM; i++) + { + snprintf(name, 8, "%s%d", DEV_NAME, i); + remove_proc_entry(name, NULL); + } PRINT_ALERT("driver unloaded"); } diff --git a/usdpci.rules b/usdpci.rules index 93ead97..289dfe5 100644 --- a/usdpci.rules +++ b/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"