updates
This commit is contained in:
189
pcie_driver/drexpcie.c
Executable file
189
pcie_driver/drexpcie.c
Executable file
@@ -0,0 +1,189 @@
|
||||
|
||||
#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);
|
||||
|
||||
Reference in New Issue
Block a user