#include "drex.h" #include "drexchar.h" #define DRIVER_NAME "drexpcie" /* This sample driver supports device with VID = 0x010F, and PID = 0x0F0E*/ static struct pci_device_id drexpcie_driver_id_table[] = { { PCI_DEVICE(0x10EE, 0x903F) }, {0,} }; MODULE_DEVICE_TABLE(pci, drexpcie_driver_id_table); static int drexpcie_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent); static void drexpcie_driver_remove(struct pci_dev *pdev); /* Driver registration structure */ static struct pci_driver drexpcie_driver = { .name = DRIVER_NAME, .id_table = drexpcie_driver_id_table, .probe = drexpcie_driver_probe, .remove = drexpcie_driver_remove }; static int __init drexpcie_driver_init(void) { /* Register new PCI driver */ int result = pci_register_driver(&drexpcie_driver); if (result < 0) { // This print will tell you exactly why it failed pr_err("pci_register_driver failed with error: %d\n", result); return result; } pr_info("Xilinx custom driver registered successfully!\n"); return result; } static void __exit drexpcie_driver_exit(void) { /* Unregister */ pci_unregister_driver(&drexpcie_driver); } void release_device(struct pci_dev *pdev) { /* Disable IRQ #42*/ // free_irq(42, pdev); /* Free memory region */ pci_release_region(pdev, pci_select_bars(pdev, IORESOURCE_MEM)); /* And disable device */ pci_disable_device(pdev); } /* */ static irqreturn_t irq_handler(int irq, void *cookie) { (void) cookie; printk("Handle IRQ #%d\n", irq); return IRQ_HANDLED; } /* Reqest interrupt and setup handler */ int set_interrupts(struct pci_dev *pdev) { /* We want MSI interrupt, 3 lines (just an example) */ int ret = pci_alloc_irq_vectors(pdev, 3, 3, PCI_IRQ_MSI); if (ret < 0) { return ret; } /* Request IRQ #42 */ return request_threaded_irq(42, irq_handler, NULL, 0, "TEST IRQ", pdev); } /* This function is called by the kernel */ static int drexpcie_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int bar, err; u16 vendor, device; // unsigned long mmio_start,mmio_len; struct drexpcie_driver_priv *drv_priv; printk("drexpcie probe\n"); /* Let's read data from the PCI device configuration registers */ pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor); pci_read_config_word(pdev, PCI_DEVICE_ID, &device); printk(KERN_INFO "Device vid: 0x%X pid: 0x%X\n", vendor, device); /* Request IO BAR */ bar = pci_select_bars(pdev, IORESOURCE_MEM); /* Enable device memory */ err = pci_enable_device_mem(pdev); if (err) { return err; } /* Request memory region for the BAR */ err = pci_request_region(pdev, bar, DRIVER_NAME); if (err) { pci_disable_device(pdev); return err; } pci_set_master(pdev); if (dma_set_mask_and_coherent(&(pdev->dev), DMA_BIT_MASK(40))) { printk("dma_set_mask_and_coherent error\n"); } /* Allocate memory for the driver private data */ drv_priv = kzalloc(sizeof(struct drexpcie_driver_priv), GFP_KERNEL); if (!drv_priv) { release_device(pdev); return -ENOMEM; } drv_priv->pdev = pdev; /* Get start and stop memory offsets */ drv_priv->mem_start = pci_resource_start(pdev, 0); drv_priv->mem_len = pci_resource_len(pdev, 0); printk(KERN_INFO "Resource Start: 0x%lX length: 0x%lX\n", drv_priv->mem_start, drv_priv->mem_len); /* Remap BAR to the local pointer */ drv_priv->bar0_mem = ioremap(drv_priv->mem_start, drv_priv->mem_len); if (!drv_priv->bar0_mem) { release_device(pdev); return -EIO; } drexpcie_chardev_create(drv_priv); /* Set driver private data */ /* Now we can access mapped "bar0_mem" from the any driver's function */ pci_set_drvdata(pdev, drv_priv); return 0; // return set_interrupts(pdev); } /* Clean up */ static void drexpcie_driver_remove(struct pci_dev *pdev) { struct drexpcie_driver_priv *drv_priv = pci_get_drvdata(pdev); drexpcie_chardev_destroy(); if (drv_priv) { if (drv_priv->bar0_mem) { iounmap(drv_priv->bar0_mem); } pci_free_irq_vectors(pdev); kfree(drv_priv); pci_set_drvdata(pdev, NULL); } // release_device(pdev); pci_release_region(pdev, 0); pci_disable_device(pdev); } MODULE_LICENSE("GPL"); MODULE_AUTHOR(""); MODULE_DESCRIPTION("DREX PCIe driver"); MODULE_VERSION("0.1"); module_init(drexpcie_driver_init); module_exit(drexpcie_driver_exit);