一、PCI总线注册
1、pci总线注册对应构造函数
static int __init pci_driver_init(void)
{
return bus_register(&pci_bus_type);
}
postcore_initcall(pci_driver_init);
#define postcore_initcall(fn) __define_initcall("2",fn)
#define __define_initcall(level,fn) \
static initcall_t __initcall_##fn __attribute_used__ \
__attribute__((__section__(".initcall" level ".init"))) = fn
start_kernel -->rest_init() -->kernel_init() --> do_basic_setup() -->do_initcalls()----》遍历.initcall" level ".init,执行.initcall" level ".init对应的fn,最终pci_driver_init被执行
2、执行注册
pci总线的ops结构体:
struct bus_type pci_bus_type = {
.name = "pci",
.match = pci_bus_match,
.hotplug = pci_hotplug,
.suspend = pci_device_suspend,
.resume = pci_device_resume,
.dev_attrs = pci_dev_attrs,
};
注册pci驱动
int bus_register(struct bus_type * bus)
{
int retval;
retval = kobject_set_name(&bus->subsys.kset.kobj, "%s", bus->name); //设置pci_bus_type->subsys.kset.kobj->k_name为pci
subsys_set_kset(bus, bus_subsys); //pci_bus_type->subsys.kset.kobj.kset = &bus_subsys.kset (bus_subsys由buses_init调subsystem_register进行初始化)
retval = subsystem_register(&bus->subsys); //初始化X.kobj.entry、X.list链表头部、将X.kobj->entry添加到X.kobj->kset->list,创建sys/bus目录下pci目录(X为pci_bus_type->subsys.kset)
kobject_set_name(&bus->devices.kobj, "devices");
bus->devices.subsys = &bus->subsys;
retval = kset_register(&bus->devices); //初始化X.kobj.entry、X.list链表头部,X->kobj.parent为pci_bus_type->subsys.kset.kobj,创建sys/bus/pci目录下devices目录(X为pci_bus_type->devices)
kobject_set_name(&bus->drivers.kobj, "drivers");
bus->drivers.subsys = &bus->subsys;
bus->drivers.ktype = &ktype_driver;
retval = kset_register(&bus->drivers); //初始化X.kobj.entry、X.list链表头部,X->kobj.parent为pci_bus_type->subsys.kset.kobj,创建sys/bus/pci目录下drivers目录(X为pci_bus_type->drivers)
.......
二、注册pci设备驱动
int pci_register_driver(struct pci_driver *drv)
{
int error;
/* initialize common driver fields */
drv->driver.name = drv->name;
drv->driver.bus = &pci_bus_type;
drv->driver.probe = pci_device_probe;
drv->driver.remove = pci_device_remove;
drv->driver.owner = drv->owner;
drv->driver.kobj.ktype = &pci_driver_kobj_type;
pci_init_dynids(&drv->dynids);
/* register with core */
error = driver_register(&drv->driver);
}
int driver_register(struct device_driver * drv)
{
INIT_LIST_HEAD(&drv->devices); //初始化pci设备驱动的devices链表
init_MUTEX_LOCKED(&drv->unload_sem);
return bus_add_driver(drv);
}
int bus_add_driver(struct device_driver * drv)
{
struct bus_type * bus = get_bus(drv->bus);
int error = 0;
if (bus) {
pr_debug("bus %s: add driver %s\n", bus->name, drv->name);
error = kobject_set_name(&drv->kobj, "%s", drv->name); //设置drv->driver.kobj.name为pci设备驱动名字
drv->kobj.kset = &bus->drivers; //drv->kobj.kset为pci_bus_type->drivers
error = kobject_register(&drv->kobj)); //初始化drv->kobj->entry链表、drv->kobj.parent为pci_bus_type->drivers->list,将drv->kobj->entry添加到pci_bus_type->drivers->list,以sys/bus/pci/drivers为目录创建pci设备驱动名的目录
down_write(&bus->subsys.rwsem);
driver_attach(drv); //1、遍历pci_bus_type->devices->list上的device调driver_probe_device,该函数调drv->driver.bus.match = &pci_bus_type.match =pci_bus_match将device的pci id与driver注册的pci id进行匹配, 若匹配成功,调driver的probe函数
2、调device_bind_driver:dev->driver_list添加到dev->driver->devices,将sys/bus/pci/drivers/驱动名/pci_id与sys/bus/pci/devices/pci_id创建软链接
注:subsys_initcall(pcibios_init)注册pci初始化回调,subsys_initcall也是__define_initcall的宏定义,在系统初始化时回调被调用,??该回调执行pci_scan_bus进行pci设备的bar空间读取并添加设备到pci_bus_type->devices->list??
up_write(&bus->subsys.rwsem);
module_add_driver(drv->owner, drv); //创建driver与module的软链接
driver_add_attrs(bus, drv); //根据pci_dev_attrs创建软链接
}