linux的PCI驱动的疑问
最近学习linux的PCI驱动开发,打算想试着针对凌华的采集卡写驱动,今天只写了一个框架,编译运行,遇到问题了,在注册和探测部分的源码如下://driver's member function prode
static int __devinit adl_probe(struct pci_dev *pci_dev,const struct pci_device_id *pco_id)
{
int i; //i is used for counting
printk(KERN_ALERT "adlink modules is probing!\n");
//struct pci_dev *adl_dev=NULL;
if(pci_enable_device(pci_dev))
{
return -EIO;
};
pci_set_master(pci_dev);
// #define BASE_REG_NUM 6
unsigned long mmio_start;
for(i=0;i<BASE_REG_NUM;i++)
{
mmio_start=pci_resource_start(pci_dev,i);
printk(KERN_ALERT "the adress of the base register %i is %l\n",i,mmio_start);
}
return 0;
}
//其实这我就想看看6个基地址寄存器的地址
//the detail of the driver module
static struct pci_driver adl_pci_driver= {
.name = MODULE_NAME,
.id_table = adl_pci_tbl,
.probe = adl_probe,
.remove = adl_remove,
};
//register adlink driver module
static int __init adl_init_module(void)
{
printk(KERN_ALERT "adlink modules is inited!\n");
return pci_register_driver(&adl_pci_driver);
}
//remove adlink driver module
static void __exit adl_exit_module(void)
{
printk(KERN_ALERT "adlink modules is exited!\n");
pci_unregister_driver(&adl_pci_driver);
}
module_init(adl_init_module);
module_exit(adl_exit_module);
编译运行,能够在/var/log/message 中看到
Jan 13 16:31:54 localhost kernel: adlink modules is inited!
Jan 13 16:46:52 localhost kernel: adlink modules is exited!
但是没有调用probe函数,不然应该有其他输出的!这是为什么呢?哪错了啊 调用 probe 函数, 需要 驱动支持的device id 和vendor id与设备里读出来的一样。
先看下是否一致 公母没配对. 回复 2# goldenfort
源码如下:
#include <linux/pci.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <linux/compiler.h>
#include <linux/completion.h>
#include <linux/mii.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Wu Donglei");
#define MODULE_NAME "adlink"
#define ADLINK_VENDOR_ID0x1022
#define ADLINK_DEVICE_ID0x2000
static struct pci_device_id adl_pci_tbl [] = {
{ADLINK_VENDOR_ID,ADLINK_DEVICE_ID,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
{0,}
};
MODULE_DEVICCE_TABLE(pci,adl_pci_tbl);
//driver's member function prode
static int __devinit adl_probe(struct pci_dev *pci_dev,const struct
pci_device_id *pco_id)
{
u16 vendor,device;
printk(KERN_ALERT "adlink modules is probing!\n");
pci_read_config_word(pci_dev,0,&vendor);
pci_read_config_word(pci_dev,2,&device);
printk(KERN_INFO "%x:%x\n",vendor,device);
return 0;
}
//driver's member function remove
static int __devexit adl_remove(struct pci_dev *pci_dev)
{
printk(KERN_ALERT "adlink modules is removed!\n");
return 0;
}
//the detail of the driver module
static struct pci_driver adl_pci_driver= {
.name = MODULE_NAME,
.id_table = adl_pci_tbl,
.probe = adl_probe,
.remove = adl_remove,
};
//register adlink driver module
static int __init adl_init_module(void)
{
printk(KERN_ALERT "adlink modules is inited!\n");
return pci_register_driver(&adl_pci_driver);
}
//remove adlink driver module
static void __exit adl_exit_module(void)
{
printk(KERN_ALERT "adlink modules is exited!\n");
pci_unregister_driver(&adl_pci_driver);
}
module_init(adl_init_module);
module_exit(adl_exit_module);
在我insmod adlink.ko后,再卸载在/var/log/message中有输出:
Jan 13 17:01:51 localhost kernel: adlink modules is inited!
Jan 13 17:02:42 localhost kernel: adlink modules is exited!
但是为什么就没有调用probe函数呢?
我lspci -x:有这个设备:
02:01.0 Ethernet controller: Advanced Micro Devices 79c970
(rev 10)
00: 22 10 00 20 07 00 80 02 10 00 00 02 00 40 00 00
10: 01 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00
20: 00 00 00 00 00 00 00 00 00 00 00 00 22 10 00 20
30: 00 00 00 00 00 00 00 00 00 00 00 00 05 01 06 ff
从这里面来看:
#define ADLINK_VENDOR_ID0x1022
#define ADLINK_DEVICE_ID0x2000
应该是一致的吧? 本帖最后由 goldenfort 于 2011-01-14 16:44 编辑
回复 4# wucongdonglai
http://lxr.linux.no/#linux+v2.6.37/drivers/net/pcnet32.c
这里 有这个网卡的驱动源程序,比较下就能知道原因了
它的 是这样写的
static DEFINE_PCI_DEVICE_TABLE(pcnet32_pci_tbl) = {
65 { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME), },
66 { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE), },
67
68 /*
69 * Adapters that were sold with IBM's RS/6000 or pSeries hardware have
70 * the incorrect vendor id.
71 */
72 { PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_AMD_LANCE),
73 .class = (PCI_CLASS_NETWORK_ETHERNET << 8), .class_mask = 0xffff00, },
74
75 { } /* terminate list */
页:
[1]