pci外设初始化流程:
1、 pci驱动注册
如果网络设备(包括wireless)是PCI规范的,则先是向内核注册该PCI设备(pci_register_driver),然后由pci_driver数据结构中的probe函数指针所指向的侦测函数来初始化该PCI设备,并且同时注册和初始化该网络设备。
首先,设置pci设备信息。例如:
// 在这里指定PCI设备ID,PCI_VDEVICE会组装厂家ID和PCI设备ID
static const struct pci_device_id misc_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, 0x0f1c), 0 },
{ PCI_VDEVICE(INTEL, 0x0f12), 1 }, // SMBus
{0,},
};
MODULE_DEVICE_TABLE(pci, misc_pci_tbl);
然后调用pci注册函数:
pci_register_driver(struct pci_driver *drv);
static struct pci_driver drv = {
.name = , /*驱动程序名*/
.id_table = , /*pci设备配置信息*/
.probe = , /*设备插入内核时调用*/
.remove = , /*设备从内核移除时调用*/
};
2、 PCI设备探测函数probe
1、 初始化设备,使I/O,memory可用,唤醒设备;
同时初始化memory和IO类型的BAR
int pci_enable_device(struct pci_dev *pdev);
2、 申请内存空间,配置I/O,memory资源;
对PCI区进行标记 ,标记该区域已经分配出去
int pci_request_regions(struct pci_dev *pdev, const char *res_name);
void pci_release_regions(struct pci_dev *pdev);
3、设置DMA属性
pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff);/*辅助函数用于检查总线是否可以接收给定大小的总线地址(mask),如果可以,则通知总线层给定的外围设备将使用该大小的总线地址*/
pci_set_consistent_dma_mask(pdev, (u64) 0xffffffffffffffff);/*设置 DMA 地址掩码位,因为 PCI 设备时有寻址限制的,所以需要标识那些位的地址可以使用*/
4、 设定设备工作在总线主设备模式
void pci_set_master(struct pci_dev *pdev);
5、
设置驱动私有数据
void pci_set_drvdata((struct pci_dev *pdev, void *data);//为了在同一个驱动支持多个相同设备时,为各个设备准备的数据结构互相不冲突。
参考链接:
1、 https://www.cnblogs.com/zhuyp1015/archive/2012/06/30/2571408.html
2、 http://blog.chinaunix.net/uid-387104-id-1744120.html
3、 https://blog.csdn.net/weixin_42092278/article/details/81638530?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-5.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-5.control