#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\n");

}

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

printk("open driver\n");
    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\n");
        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\n");
            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\n", 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\n", plx->region);
            goto err_out_free_plx;
        }
        pci_set_drvdata(pdev, plx);

printk("Found  plx card %d\n",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\n",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.\n");
             return -1;
         }
    device_create( plx_class, NULL, devno, DEVICE_NAME);
  }
  else
      printk("Not found Synway card!\n");

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);

Linux pci驱动源码的更多相关文章

  1. Davinci DM6446开发攻略——LINUX GPIO驱动源码移植

    一.             DM6446 GPIO的介绍      说到LINUX 驱动移植,没有移植过的朋友,或刚刚进入LINUX领域的朋友,最好去看看<LINUX 设备驱动程序>第三 ...

  2. (转)Linux设备驱动之HID驱动 源码分析

    //Linux设备驱动之HID驱动 源码分析 http://blog.chinaunix.net/uid-20543183-id-1930836.html HID是Human Interface De ...

  3. linux调度器源码分析 - 运行(四)

    本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 引言 之前的文章已经将调度器的数据结构.初始化.加入进程都进行了分析,这篇文章将主要说明调度器是如何在程序稳定运 ...

  4. Linux环境PostgreSQL源码编译安装

    Linux环境PostgreSQL源码编译安装 Linux版本: Red Hat 6.4 PostgreSQL版本: postgresql-9.3.2.tar.gz 数据存放目录: /var/post ...

  5. 编译 wl18xx驱动源码

    在做beagleboneblack移植的时候,wl18xx的驱动源码是自动编译的.但是移植到其他平台优越平台不一样,所以就不能自动编译 所以用其他方式编译.http://e2e.ti.com/supp ...

  6. Android源码浅析(四)——我在Android开发中常用到的adb命令,Linux命令,源码编译命令

    Android源码浅析(四)--我在Android开发中常用到的adb命令,Linux命令,源码编译命令 我自己平时开发的时候积累的一些命令,希望对你有所帮助 adb是什么?: adb的全称为Andr ...

  7. Linux学习之源码包安装与脚本安装(十八)

    Linux学习之源码包安装与脚本安装 目录 源码包与RPM包的区别 源码包安装 脚本安装 源码包与RPM包的区别 1.区别 安装之前的区别:概念上的区别 安装之后的区别:安装位置不同 源码包: 开源的 ...

  8. linux调度器源码分析 - 初始化(二)

    本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 引言 上期文章linux调度器源码分析 - 概述(一)已经把调度器相关的数据结构介绍了一遍,本篇着重通过代码说明 ...

  9. MySQL的JDBC驱动源码解析

    原文:   MySQL的JDBC驱动源码解析 大家都知道JDBC是Java访问数据库的一套规范,具体访问数据库的细节有各个数据库厂商自己实现 Java数据库连接(JDBC)由一组用 Java 编程语言 ...

随机推荐

  1. XAlign—自动对齐代码插件

    XAlign An amazing Xcode plugin to align regular code. It can align anything by using custom alignmen ...

  2. Python 面向对象的三大特性

    面向对象的三大特性:继承,封装,多态 什么时候用封装: 同一种功能的时候, 譬如:把一部分数据或方法,封装到同一个类的中 PS:在构造方法中,原始数据中....

  3. 用webpy实现12306余票查询

    效果

  4. CentOS7.5删除旧的内核

    [root@localhost ~]# uname -r3.10.0-862.3.2.el7.x86_64 [root@localhost ~]# rpm -qa | grep kernelkerne ...

  5. nodejs pm2使用

    参考地址:http://www.jianshu.com/p/43525232b03b 参考地址:http://blog.csdn.net/leo_perfect/article/details/536 ...

  6. HDFS上传文件错误--hdfs:DFSClient:DataStreamer Exception

    今天上传文件的时候发现传上去的文件为空,错误提示如上述所示,原来是IP地址改掉了对呀应etc/hosts下面的IP地址也要改变,永久改ip命令-ifconfig eth0 xxx·xxx·xxx·xx ...

  7. LibreOJ #139 树链剖分 [树链剖分,线段树]

    题目传送门 树链剖分 题目描述 这是一道模板题. 给定一棵 n 个节点的树,初始时该树的根为 1 号节点,每个节点有一个给定的权值.下面依次进行 m 个操作,操作分为如下五种类型: 换根:将一个指定的 ...

  8. 洛谷——P2813 母舰

    P2813 母舰 题目背景 广东汕头聿怀初中 Train#3 Problem 1 (有没有红警既视感~) 题目描述 在小A的星际大战游戏中,一艘强力的母舰往往决定了一场战争的胜负.一艘母舰的攻击力是普 ...

  9. [BZOJ4004][JLOI2015]装备购买(贪心+线性基)

    求最小权极大线性无关组. 先将所有向量按权值排序,从小到大依次判断,若能被前面已选向量线性表出则不选,这样一定最优. 据说是用拟阵来证明,但感性理解一下感觉比较显然,首先这样个数一定是最多的,其次对于 ...

  10. [CODECHEF]LUCASTH

    题意:设$f(n,k)=\sum\limits_{\substack{S\subseteq\{1,\cdots,n\}\\|S|=k}}\prod\limits_{x\in S}x$,问$f(n,0\ ...