学Linux驱动: 应该先了解驱动模型 (2)

学Linux驱动: 应该先了解驱动模型

bus_type

bus_type用以驱动总线,具体的驱动USB/I2C/PCI/MMC等:

注册总线,利用bus_register注册总线,bus_unregister删除总线。如下例子,每种总线须定义一个bus_type对象,并利用bus_register注册总线,或bus_unregister删除总线。

/*i2c-core-base.c*/ struct bus_type i2c_bus_type = { .name = "i2c", .match = i2c_device_match, .probe = i2c_device_probe, .remove = i2c_device_remove, .shutdown = i2c_device_shutdown, }; EXPORT_SYMBOL_GPL(i2c_bus_type); static int __init i2c_init(void) { int retval; retval = of_alias_get_highest_id("i2c"); down_write(&__i2c_board_lock); if (retval >= __i2c_first_dynamic_bus_num) __i2c_first_dynamic_bus_num = retval + 1; up_write(&__i2c_board_lock); /*注册I2C总线*/ retval = bus_register(&i2c_bus_type); if (retval) return retval; is_registered = true; #ifdef CONFIG_I2C_COMPAT i2c_adapter_compat_class = class_compat_register("i2c-adapter"); if (!i2c_adapter_compat_class) { retval = -ENOMEM; goto bus_err; } #endif retval = i2c_add_driver(&dummy_driver); if (retval) goto class_err; if (IS_ENABLED(CONFIG_OF_DYNAMIC)) WARN_ON(of_reconfig_notifier_register(&i2c_of_notifier)); if (IS_ENABLED(CONFIG_ACPI)) WARN_ON(acpi_reconfig_notifier_register(&i2c_acpi_notifier)); return 0; class_err: #ifdef CONFIG_I2C_COMPAT class_compat_unregister(i2c_adapter_compat_class); bus_err: #endif is_registered = false; /*错误时删除总线*/ bus_unregister(&i2c_bus_type); return retval; }

注册适配器驱动程序(USB控制器,I2C适配器等),以检测连接的设备,并提供与设备的通信机制

图中的match函数接口用于将驱动程序与设备进行匹配。match回调的目的是使总线有机会通过比较驱动程序支持的设备ID与特定设备的设备ID来确定特定驱动程序是否支持特定设备,而不会牺牲特定于总线的功能或类型安全性 。当向总线注册驱动程序时,将遍历总线的设备列表,并为每个没有与之关联的驱动程序的设备调用match回调。

提供API函数以实现适配器驱动以及设备驱动。

同时dev_pm_ops *pm实现对于总线的功耗管理接口抽象。对于特定总线实现这个操作符对应的函数。

struct dev_pm_ops { int (*prepare)(struct device *dev); void (*complete)(struct device *dev); int (*suspend)(struct device *dev); int (*resume)(struct device *dev); int (*freeze)(struct device *dev); int (*thaw)(struct device *dev); int (*poweroff)(struct device *dev); int (*restore)(struct device *dev); int (*suspend_late)(struct device *dev); int (*resume_early)(struct device *dev); int (*freeze_late)(struct device *dev); int (*thaw_early)(struct device *dev); int (*poweroff_late)(struct device *dev); int (*restore_early)(struct device *dev); int (*suspend_noirq)(struct device *dev); int (*resume_noirq)(struct device *dev); int (*freeze_noirq)(struct device *dev); int (*thaw_noirq)(struct device *dev); int (*poweroff_noirq)(struct device *dev); int (*restore_noirq)(struct device *dev); int (*runtime_suspend)(struct device *dev); int (*runtime_resume)(struct device *dev); int (*runtime_idle)(struct device *dev); };

iommu_ops 操作符提供总线相关的IOMMU抽象。

设备驱动注册到总线上时,将在sysfs管理总线/设备/设备驱动的层次关系,以PCI为例:

/*在总线上注册的驱动程序会在总线的驱动程序目录中获得一个目录*/ /sys/bus/pci/ |-- devices `-- drivers |-- Intel ICH |-- Intel ICH Joystick |-- agpgart `-- e100 /*在该类型的总线上发现的每个设备都会在总线的设备目录中获得到物理层次结构中该设备目录的符号链接*/ /sys/bus/pci/ |-- devices | |-- 00:00.0 -> ../../../root/pci0/00:00.0 | |-- 00:01.0 -> ../../../root/pci0/00:01.0 | `-- 00:02.0 -> ../../../root/pci0/00:02.0 `-- drivers

总线属性:bus_groups/设备属性dev_groups/驱动属性drv_groups。

学Linux驱动: 应该先了解驱动模型

device

作用:抽象描述具体的设备

设备注册:发现设备的总线驱动程序使用下面的函数来向内核注册设备

int device_register(struct device * dev);

利用device_unregister()从总线上删除设备

device_driver

作用:抽象描述连接在总线上的具体设备的驱动

驱动注册,通过下面的函数将设备驱动程序注册

int driver_register(struct device_driver *drv);

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyfxpw.html