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\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驱动源码的更多相关文章
- Davinci DM6446开发攻略——LINUX GPIO驱动源码移植
一. DM6446 GPIO的介绍 说到LINUX 驱动移植,没有移植过的朋友,或刚刚进入LINUX领域的朋友,最好去看看<LINUX 设备驱动程序>第三 ...
- (转)Linux设备驱动之HID驱动 源码分析
//Linux设备驱动之HID驱动 源码分析 http://blog.chinaunix.net/uid-20543183-id-1930836.html HID是Human Interface De ...
- linux调度器源码分析 - 运行(四)
本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 引言 之前的文章已经将调度器的数据结构.初始化.加入进程都进行了分析,这篇文章将主要说明调度器是如何在程序稳定运 ...
- Linux环境PostgreSQL源码编译安装
Linux环境PostgreSQL源码编译安装 Linux版本: Red Hat 6.4 PostgreSQL版本: postgresql-9.3.2.tar.gz 数据存放目录: /var/post ...
- 编译 wl18xx驱动源码
在做beagleboneblack移植的时候,wl18xx的驱动源码是自动编译的.但是移植到其他平台优越平台不一样,所以就不能自动编译 所以用其他方式编译.http://e2e.ti.com/supp ...
- Android源码浅析(四)——我在Android开发中常用到的adb命令,Linux命令,源码编译命令
Android源码浅析(四)--我在Android开发中常用到的adb命令,Linux命令,源码编译命令 我自己平时开发的时候积累的一些命令,希望对你有所帮助 adb是什么?: adb的全称为Andr ...
- Linux学习之源码包安装与脚本安装(十八)
Linux学习之源码包安装与脚本安装 目录 源码包与RPM包的区别 源码包安装 脚本安装 源码包与RPM包的区别 1.区别 安装之前的区别:概念上的区别 安装之后的区别:安装位置不同 源码包: 开源的 ...
- linux调度器源码分析 - 初始化(二)
本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 引言 上期文章linux调度器源码分析 - 概述(一)已经把调度器相关的数据结构介绍了一遍,本篇着重通过代码说明 ...
- MySQL的JDBC驱动源码解析
原文: MySQL的JDBC驱动源码解析 大家都知道JDBC是Java访问数据库的一套规范,具体访问数据库的细节有各个数据库厂商自己实现 Java数据库连接(JDBC)由一组用 Java 编程语言 ...
随机推荐
- socket编程之select(),poll(),epoll()
socket编程,通信 client端 socket() ----->connect() ------->recv() -----> close(); server端 socket ...
- Google Guice 之绑定1
绑定和依赖注入区别 绑定,使用时 需要通过 injector 显示获取 依赖注入,只需要显示获取主类,他的依赖是通过@Injector 和 绑定关系 隐式注入的 http://blog.csdn.ne ...
- redis之(九)redis的事务机制
[一]什么是redis的事务 --->redis的事务是一组命令的集合. --->redis的事务是保证一组命令,要么都执行,要么都不执行.但不支持一组命令中,其中一个或多个执行失败,不支 ...
- python2下向文件写入unicode编码的内容,codecs包
python内置库中的open方法只能读写ascii码,如果想写入Unicode字符,需要使用codecs包. # -*- coding: utf-8 -*- import codecs import ...
- lr中exit(-1)和return 0的区别
LR脚本实践:关于lr中exit(-1)和return 0的区别 exit(-1):从当前action里面exit(-1)所在行,当前迭代里面直接退出来,终止运行: return 0:忽略当前acti ...
- 洛谷——P1068 分数线划定
P1068 分数线划定 题目描述 世博会志愿者的选拔工作正在 A 市如火如荼的进行.为了选拔最合适的人才,A 市对 所有报名的选手进行了笔试,笔试分数达到面试分数线的选手方可进入面试.面试分数线根 据 ...
- OpenCV 学习之路(2) -- 操作像素
本节内容: 访问像素值 用指针扫描图像 用迭代器扫描图像 编写高效的图像扫描循环 扫描图像并访问相邻像素 实现简单的图像运算 图像重映射 访问像素值 准备工作: 创建一个简单函数,用它在图像中加入椒盐 ...
- Spring 概念详解
一.Spring的IoC(Inversion of Control). 这是Spring中得有特点的一部份.IoC又被翻译成“控制反转”,也不知道是谁翻译得这么别扭,感觉很深奥的词.其实,原理很简单, ...
- JZYZOJ1530 [haoi2013]开关控制 状压 dfs 折半搜索
http://172.20.6.3/Problem_Show.asp?id=1530 元宵节快要到了,某城市人民公园将举办一次灯展.Dr.Kong准备设计出一个奇妙的展品,他计划将编号为1到N的N(1 ...
- 【穷竭】POJ3187-Backward Digit Sums
[思路] 利用杨辉三角形,每一个数字被加的次数等于它在杨辉三角形中对应的那个数字.注意这道题的意思是,最底层是N的全排序,而不是指1..10都可以.生成杨辉三角形的时候第一次我用了二重循环模拟生成,后 ...