linux pci驱动程序源代码,Linux pci驱动源码

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#ifdef LINUX26

#include

#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

{

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值