在Linux内核的PCI设备驱动程序中,探测函数(probe function)是一个特定的回调函数,它在驱动程序注册后由PCI子系统调用,用于检查并初始化与驱动程序兼容的PCI设备。这个函数的目的是确定驱动程序是否能够支持特定的PCI设备,并在能够支持的情况下,对该设备进行必要的初始化工作。
探测函数的名称通常是probe
或者driver_probe
,并且它必须是struct pci_driver
结构体中的一个成员。这个函数的原型通常如下:
c复制代码
int (*probe)(struct pci_dev *dev, const struct pci_device_id *id); |
其中:
struct pci_dev *dev
指向一个struct pci_dev
的实例,该实例描述了具体的PCI设备。const struct pci_device_id *id
指向一个struct pci_device_id
的实例,该实例描述了与驱动程序兼容的PCI设备的ID信息。
探测函数的任务通常包括:
-
设备资源分配:为设备分配必要的内核资源,如内存、中断等。
-
设备初始化:设置设备的初始状态,包括配置设备的寄存器、初始化设备的队列等。
-
设备注册:将设备注册到设备模型,以便用户空间可以通过设备文件或其他接口与设备交互。
-
错误处理:如果在初始化过程中遇到错误,探测函数应该释放已经分配的资源,并返回一个负值错误码。
如果探测函数成功初始化了设备,并且没有返回错误,那么PCI子系统会认为该设备与驱动程序成功绑定,设备将被标记为已启用,并且可以在用户空间中被使用。
这里是一个简单的探测函数示例:
c复制代码
static int my_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |
{ | |
int err; | |
/* 启用设备 */ | |
err = pci_enable_device(dev); | |
if (err) { | |
dev_err(&dev->dev, "Cannot enable PCI device\n"); | |
return err; | |
} | |
/* 请求I/O和内存资源 */ | |
err = pci_request_regions(dev, "my_driver"); | |
if (err) { | |
dev_err(&dev->dev, "Cannot obtain PCI resources\n"); | |
pci_disable_device(dev); | |
return err; | |
} | |
/* 初始化设备 */ | |
// ... | |
/* 注册设备到设备模型 */ | |
// ... | |
return 0; /* 成功 */ | |
} |
在驱动程序的struct pci_driver
中,你会将这个函数指针设置为你的探测函数:
c复制代码
static const struct pci_device_id my_pci_tbl[] = { | |
/* 设备ID列表 */ | |
{ PCI_DEVICE(VENDOR_ID, DEVICE_ID) }, | |
{ 0, } | |
}; | |
MODULE_DEVICE_TABLE(pci, my_pci_tbl); | |
static struct pci_driver my_pci_driver = { | |
.name = "my_pci_driver", | |
.id_table = my_pci_tbl, | |
.probe = my_pci_probe, | |
/* 可以设置其他回调函数,如remove, suspend, resume等 */ | |
}; | |
module_pci_driver(my_pci_driver); |
当驱动程序加载时,module_pci_driver
宏会调用pci_register_driver
来注册驱动程序,并使其探测函数对PCI总线上的设备进行探测和初始化。