#include #include #include #include #include #include #include #include #include #include #include #include #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)}, {0, }, }; 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 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 dev_t chrdev; static struct cdev cdev; 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 }; /*************************************************************************************************/ static struct pci_driver pci_driver = { .name = CLASS_NAME, .id_table = pcie_ids, .probe = pcie_probe, .remove = __exit_p(pcie_remove), }; /*************************************************************************************************/ #define PRINT_PREFIX "USDriver PCIe" #define PRINT_ALERT(STR) printk(KERN_ALERT "%s %s\n", PRINT_PREFIX, STR) #define PRINT_WARN(STR) printk(KERN_WARN "%s %s\n", PRINT_PREFIX, STR) /*************************************************************************************************/ static int __init pcie_init(void) { int res = 0; PRINT_ALERT("driver initializing"); res = pci_register_driver(&pci_driver); if ( res ) { PRINT_ALERT("device not found"); return res; } PRINT_ALERT("register driver success" ); res = chrdev_init(); if ( res ) { PRINT_ALERT("character device file creation failed"); return res; } PRINT_ALERT("driver loaded"); return res; } /*************************************************************************************************/ 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) { return -1; } cdev_init(&cdev, &chrdev_fops); res = cdev_add(&cdev, chrdev, 1); if (res) { unregister_chrdev_region(chrdev, 1); return res; } class = class_create(THIS_MODULE, CLASS_NAME); device = device_create(class, NULL, chrdev, NULL, NODE_0_NAME); return 0; } /*************************************************************************************************/ static int usd_open(struct inode *inode, struct file *flip) { return 0; } /*************************************************************************************************/ static int usd_mmap(struct file *filp, struct vm_area_struct *vma) { return 0; } /*************************************************************************************************/ static unsigned int usd_poll (struct file *filp, poll_table *wait) { return 0; } /*************************************************************************************************/ static int __init pcie_probe (struct pci_dev *dev, const struct pci_device_id *id) { int rc = 0; rc = pci_enable_device(dev); if(rc) { PRINT_ALERT("driver pci_enable_device() failed"); goto probe_fail_enable; } if(!(pci_resource_flags(dev, 0) & IORESOURCE_MEM)) { printk(KERN_ERR "USDriver PCIe driver incorrect BAR configuration\n" ); rc = 1; goto probe_fail; } bar0_addr = pci_resource_start(dev, 0); rc = pci_request_region(dev, 0, "bar0"); if(rc) { PRINT_ALERT("driver pci_request_regions bar0 failed"); goto probe_fail; } bar0_ptr = pci_iomap(dev, 0, bar0_size); u32* bar0_data = (u32*)bar0_ptr; if(bar0_data == 0) { PRINT_ALERT("driver failed to map BAR 0"); rc = 1; goto probe_fail_release_region; } if(!(pci_resource_flags(dev, 1) & IORESOURCE_MEM)) { printk(KERN_ERR "USDriver PCIe driver incorrect BAR configuration\n" ); rc = 1; goto probe_fail; } bar1_addr = pci_resource_start(dev, 1); rc = pci_request_region(dev, 1, "bar1"); if(rc) { PRINT_ALERT("driver pci_request_regions bar1 failed"); goto probe_fail; } bar1_ptr = pci_iomap(dev, 1, bar1_size); u32* bar1_data = (u32*)bar1_ptr; if(bar1_data == 0) { PRINT_ALERT("driver failed to map BAR 1"); rc = 1; goto probe_fail_release_region; } pci_set_master(dev); printk(KERN_ALERT "-----------------------------------\n"); printk(KERN_ALERT "BAR0 reg 0 = 0x%x\n", *bar0_data); *bar1_data = 0x12345678; printk(KERN_ALERT "BAR1 reg 0 = 0x%x\n", ioread32(bar1_data)); printk(KERN_ALERT "-----------------------------------\n"); return 0; probe_fail_release_region: pci_release_regions(dev); probe_fail: pci_disable_device(dev); probe_fail_enable: return rc; } /*************************************************************************************************/ 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); PRINT_ALERT("IOunmap"); pci_release_regions(dev); PRINT_ALERT("pci_release_regions"); pci_disable_device(dev); PRINT_ALERT("pci_disable_device"); } /*************************************************************************************************/ static void __exit pcie_exit(void) { PRINT_ALERT("driver unloading"); 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); PRINT_ALERT("driver unloaded"); } module_init(pcie_init); module_exit(pcie_exit); /*************************************************************************************************/ /*************************************************************************************************/ /*************************************************************************************************/ /*************************************************************************************************/ /*************************************************************************************************/ /*************************************************************************************************/ /*************************************************************************************************/ /*************************************************************************************************/