PCI总线(二)
来源:互联网 发布:windows最多分区多少 编辑:程序博客网 时间:2024/04/26 07:43
PCI网卡驱动程序分析 针对GNIC- II的千兆以太网卡,源程序文件/drivers/net/hamachi.c
1:初始化
static int __init hamachi_init (void) {
if(pci_register_driver (&hamachi_driver) > 0)
return 0;
pci_unregister_driver (&hamachi_driver)
return -ENODEV ;
}
static struct pci_driver hamachi_driver = {
name : DRVNAME , //驱动名字
id_table: hamachi_pci_tbl , //支持的信息的表
probe : hamachi_init_one , //当找到支持的设备调用的函数
remove : __devexit_p (hamachi_remove_one) //判断是否支持热插拔
} ;
PCI设备注册原理
pci_register_driver (driver) :分析
#define pci_register_driver(driver) \
__pci_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)
进入 __pci_register_driver()
int __pci_register_driver(struct pci_driver *drv, struct module *owner,
const char *mod_name) {
.............................................
error = driver_register(&drv->driver);
..................................
}
进入 driver_register()
int driver_register(struct device_driver *drv) {
。。。。。。。。。。。。。。。。。。。
ret = bus_add_driver(drv);
。。。。。。。。。。。。。。。。。。。
} 进入bus_add_driver()
int bus_add_driver(struct device_driver *drv) {
.............................
error = driver_attach(drv);
...........................
}
int driver_attach(struct device_driver *drv) {
return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}
进入bus_for_each_dev
int bus_for_each_dev(struct bus_type *bus, struct device *start,
void *data, int (*fn)(struct device *, void *)) //遍历总线上的每个设备
{
...........................................
while ((dev = next_device(&i)) && !error)
error = fn(dev, data); //对每个设备都执行fn()操作 fn--------> __driver_attach
...........................................
}
static int __driver_attach(struct device *dev, void *data)
{ 。。。。。。。。。。。。。。。。。。。。。。
driver_probe_device(drv, dev);
。。。。。。。。。。。。。。。。。。。。。。
}
int driver_probe_device(struct device_driver *drv, struct device *dev) {
。。。。。。。。。。。。。。。。
if(drv->bus->match && ! drv->bus->match (dev, drv)) //调用驱动程序属于的总线的match()把driver和device匹配。
ret = really_probe(dev, drv) ;
。。。。。。。。。。。。。。。。
}
当注册驱动程序时,内核去遍历驱动程序属于的PCI总线所有的设备,拿驱动和设备match,如果匹配就调用really_probe(),最终会去调用driver的probe(dev)函数。下面看如何match:
static const struct pci_device_id *pci_match_device(struct pci_driver *drv, struct pci_dev *dev) {
。。。。。。。。。。。。。。。。
list_for_each_entry(dynid, &drv->dynids.list, node) {
//对每个设备都要遍历
if (pci_match_one_device(&dynid->id, dev)) {
//dynid->id里是驱动支持的id_table,拿dev同id_table链表list_for_each比对。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。
}
static inline const struct pci_device_id *
pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev) {
if ((id->vendor == PCI_ANY_ID || id->vendor == dev->vendor) &&
(id->device == PCI_ANY_ID || id->device == dev->device) &&
(id->subvendor == PCI_ANY_ID || id->subvendor == dev->subsystem_vendor) &&
(id->subdevice == PCI_ANY_ID || id->subdevice == dev->subsystem_device) &&
!((id->class ^ dev->class) & id->class_mask))
return id;
return NULL; }
//匹配一个设备,把驱动所支持的制造商标识、设备标识、类设备标识,拿来和系统存在的设备比较。
static int __init hamachi_init_one (struct pci_dev *pdev , const pci_device_id *ent) {
//使能PCI设备
if(pci_enable_device (pdev)) {
ret = -EIO ;
goto -err_out ;
}
ioaddr = pci_resource_start (pdev, 0) ;//获取物理基地址,访问芯片必须知道芯片基地址
i = pci_register_region (pdev, DRV_NAME) ; //申请要使用的地址空间
if( i ) return i ;
irq = pdev->irq ; //获取中断号
ioaddr = (long) ioremap (ioaddr, 0x400) ; //完成物理地址映射虚拟地址。
dev = alloc_ethder(sizeof(struct hamachi_private)) ; //分配struct net_device结构
dev->open = &hamachi_open;
dev->hard_start_xmit = &hamachi_start_xmit;
dev->stop = &hamachi_close;
dev->get_stats = &hamachi_get_stats;
dev->set_multicast_list = &set_rx_mode;
dev->do_ioctl = &netdev_ioctl;
dev->tx_timeout = &hamachi_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;。。。。。。。。。。。。。。
i = register_netdev (dev) ;
.............................
}
- PCI总线(二)
- PCI总线(二)
- PCI总线进阶(二)
- PCI总线学习(二)---> PCI总线仲裁
- PCI总线(一)
- PCI总线(一)
- PCI总线学习(一)---> PCI概述
- PCI总线学习(五)---> PCI中断
- PCI总线学习(三)---> PCI总线命令
- PCI 总线操作二: bus transaction
- pci总线原理(转)
- PCI总线协议(一)
- PCI总线
- PCI总线
- pci总线
- pci总线
- PCI总线
- PCI总线
- 利用mkfs.ubifs和ubinize两个工具制作UBI镜像
- LeetCode 104 Maximum Depth of Binary Tree
- Android消息推送(一)--AndroidPn(XMPP协议)Demo版到正式上线
- 二叉排序树
- 《霍比特人2:史矛革之战》BD高清 电影 下载 [中文字幕]
- PCI总线(二)
- 工具使用说明-在VM10中安装CentOS6.4详解
- android线程handler、message、looper
- C/C++语言常见错误一览表~~~总结的相当详细
- Android消息推送(二)--基于MQTT协议实现的推送功能
- linux网络编程学习笔记之三 -----多进程并发服务端
- java中的静态内部类(static class)
- servlet、jsp小结
- [C_9] IO & 标准库