• Linux pci驱动源码


    #include <linux/kernel.h>
    #include <linux/errno.h>
    #include <linux/module.h>
    #include <linux/init.h>
    #include <linux/errno.h>
    #include <linux/pci.h>
    #include <linux/delay.h>
    #include <linux/interrupt.h>
    #include <linux/sched.h>
    #include <asm/io.h>
    #include <linux/fs.h>
    #include <linux/cdev.h>
    #include <linux/device.h>
    #ifdef LINUX26
    #include <linux/moduleparam.h>
    #endif
    #include "plx.h"
    #define DEVICE_NAME "plxDriver"
    #define PLX_8311
    //static int iMajor;
    static int plx_major = 0;
    struct cdev cdev;
    dev_t devno;
    struct class *plx_class;
    static struct Plx *cards[PLX_MAX_IFACES];
    bool Found_card_flag = 0;

    static void plx_release(struct Plx *plx)
    {
        unsigned short val;
        val = 0x0;
        if (plx->freeregion_plx)
            release_mem_region(plx->region, plx->len);

        if (plx->addr)
            iounmap(plx->addr);

        if (plx)
            kfree(plx);
        printk("Freed a plx card ");

    }

    static int shrec_open(struct inode *inode, struct file *file)
    {
        try_module_get( THIS_MODULE );

        printk("open driver ");
        return 0;
    }

    static int shrec_release( struct inode *inode, struct file *file )
    {
        module_put( THIS_MODULE );
        if (wc->freeregion_plx)
            release_mem_region(wc->plx_region, wc->plx_len);
        if (wc->freeregion_dsp)
            release_mem_region(wc->dsp_region, wc->dsp_len);
        if (wc->plx)
            iounmap(wc->plx);
        if (wc->dsp)
            iounmap(wc->dsp);
        if (wc)
            vfree(wc);
        return 0;
    }

    static struct file_operations shrec_fops = {
        owner:        THIS_MODULE,
        open:            shrec_open,
        read:            shrec_read,
        write:        shrec_write,
        release:    shrec_release,
    };

    static int __devinit plx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
    {
        int x;
        int ret;
        int res;
        struct Plx *plx;

        for (x=0;x<PLX_MAX_IFACES;x++)
        {
            if (!cards[x])   
                break;
        }
        if (x >= PLX_MAX_IFACES)
        {
            printk("Too many interfaces ");
            return -EIO;
        }
        if (pci_enable_device(pdev))
        {
            res = -EIO;
        }
        else
        {
            plx = kmalloc(sizeof(struct Plx), GFP_KERNEL);
            if (!plx) return -ENOMEM;
            memset(plx, 0x0, sizeof(struct Plx));
            if (pdev->irq < 1)
            {
                if (plx)
                    kfree(plx);
                printk(KERN_ERR "No IRQ allocated for device ");
                return -ENODEV;
            }

            cards[x] = plx;
            plx->dev = pdev;
            plx->region = pci_resource_start(pdev,0);  //1、获取plx地址空间基地址0的首地址,该地址为物理地址,由系统启动是保存在pdev结构体中
            plx->len = pci_resource_len(pdev,0);   //获取基地址0的空间大小

            if (check_mem_region(plx->region, plx->len))  //2、检查该区域是否可用
            {
                printk("plx region %lx-%lx already in use ", plx->region, plx->region + plx->len);
                if (plx)
                    kfree(plx);
                return -EIO;
            }

            if (request_mem_region(plx->region, plx->len, "plx"))  //3、申请使用该区域
            {
                plx->freeregion_plx = 1;
            }
            plx->addr = ioremap(plx->region, plx->len);  //4、将该区域的物理地址映射为虚拟地址,程序对只能对虚拟地址进行读写
            if (!plx->addr)
            {
                printk("Cannot ioremap memory space at 0x%lx ", plx->region);
                goto err_out_free_plx;
            }
            pci_set_drvdata(pdev, plx);

            printk("Found  plx card %d ",x);
            Found_card_flag = 1;
            res = 0;
        }
        return res;

    err_out_free_plx:
        if (plx->freeregion_plx)
            release_mem_region(plx->region, plx->len);
        if (plx->addr)
            iounmap(plx->addr);
        if (plx)
            kfree(plx);
        return -EIO;

    }

    static void __devexit plx_remove_one(struct pci_dev *pdev)
    {
        struct Plx *plx = pci_get_drvdata(pdev);
        unsigned short reg;

        if (plx)
        {
            reg = 0x0;
            wait_ms(5000);
            if (!plx->usecount)
                plx_release(plx);
            else
                plx->dead = 1;
        }
    }

    static struct pci_device_id plx_pci_tbl[] =
    {
        /*probe pcie cards*/
        { 0x10b5, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        /*probe pci cards*/
        /*tejxapci*/
        { 0x10b5, 0x00fa, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        { 0x10b5, 0x00fb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        { 0x10b5, 0x00fc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
    };

    MODULE_DEVICE_TABLE(pci, plx_pci_tbl);

    static struct pci_driver plx_driver =
    {
        name:     "plx_driver",
        probe:     plx_init_one,
        remove:    plx_remove_one,
        suspend: NULL,
        resume:    NULL,
        id_table: plx_pci_tbl, /*加载驱动时,会探测pci链表中的节点,如果有pci设备中有与
                              plx_pci_tbl信息匹配的,则调用plx_init_one,对该设备进行配置及初始化*/
    };

    static int __init plx_driver_init(void)
    {
        int res;
        res = pci_register_driver(&plx_driver);/*注册pci驱动*/
        if (res)
            return -ENODEV;
        if(plx_major)
        {
            devno = MKDEV(plx_major,0);/*获取主设备号*/

            res = register_chrdev_region(devno,1,DEVICE_NAME);
        }
        else
        {
            res = alloc_chrdev_region(&devno,0,1,DEVICE_NAME);
            plx_major = MAJOR(devno);
            printk("major = %d ",plx_major);
        }

      if(Found_card_flag)
      {
        /*注册设备*/
        cdev_init(&cdev,&shrec_fops);
        cdev.owner = THIS_MODULE;
        res = cdev_add(&cdev,devno,1);
        if (res)
            printk("Error %d adding plx",res);

        /*创建设备文件节点*/
        plx_class = class_create(THIS_MODULE, DEVICE_NAME);
       if(IS_ERR(plx_class))
            { printk("Err: failed in creating class. ");
                 return -1;
             }
        device_create( plx_class, NULL, devno, DEVICE_NAME);
      }
      else
          printk("Not found Synway card! ");

      return 0;

    }

    static void __exit plx_driver_cleanup(void)
    {
        unregister_chrdev_region(devno,1);/*注销设备号*/

        pci_unregister_driver(&plx_driver);/*注销pci驱动,会调用plx_remove_one函数*/

         /*注销文件节点*/
         if(Found_card_flag)
         {
            device_destroy(plx_class, devno);
            class_destroy(plx_class);

            cdev_del(&cdev);/*注销字符设备*/

         }  
    }
    module_init(plx_driver_init);
    module_exit(plx_driver_cleanup);


  • 相关阅读:
    JAVA正则表达式:Pattern类与Matcher类详解(转)
    java基础知识拾遗(四)
    java.sql.Types,数据库字段类型,java数据类型的对应关系
    根据字节码探讨java自增运算符的原理
    JAVA的abstract修饰符 && 接口interface用法 && 抽象类和interface的差别
    JAVA线程间的状态转换
    java基础知识拾遗(三)
    java布尔值进行and和or逻辑运算原理
    java字节码指令集
    shell实现SSH自动登陆【转】
  • 原文地址:https://www.cnblogs.com/wanghuaijun/p/7623811.html
Copyright © 2020-2023  润新知