设备驱动模型--存储技术原理分析笔记 基于2.6.43内核

本文为读书笔记,详细内容参考《存储原理技术分析》

1- 驱动模型

2- 总线类型

2.1- 重要数据结构

总线bus_type 和 bus_type_private 互相可以找到对方

struct bus_type {
    const char      *name;
    struct bus_attribute    *bus_attrs;
    struct device_attribute *dev_attrs;
    struct driver_attribute *drv_attrs;

    int (*match)(struct device *dev, struct device_driver *drv);
    int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
    int (*probe)(struct device *dev);
    int (*remove)(struct device *dev);          /* 设备和驱动解绑时的回调 */
    void (*shutdown)(struct device *dev);   /* 设备断电时的回调 */

    int (*suspend)(struct device *dev, pm_message_t state);   /* 进入节能状态时的回调 */

    int (*resume)(struct device *dev);     /* 恢复到正常状态时的回调 */

    const struct dev_pm_ops *pm;

    struct bus_type_private *p;
};
/**
 * struct bus_type_private - structure to hold the private to the driver core portions of the bus_type structure.
 *
 * @subsys - the struct kset that defines this bus.  This is the main kobject
 * @drivers_kset - the list of drivers associated with this bus
 * @devices_kset - the list of devices associated with this bus
 * @klist_devices - the klist to iterate over the @devices_kset
 * @klist_drivers - the klist to iterate over the @drivers_kset
 * @bus_notifier - the bus notifier list for anything that cares about things
 * on this bus.
 * @bus - pointer back to the struct bus_type that this structure is associated
 * with.
 *
 * This structure is the one that is the actual kobject allowing struct
 * bus_type to be statically allocated safely.  Nothing outside of the driver
 * core should ever touch these fields.
 */
struct bus_type_private {
    struct kset subsys;
    struct kset *drivers_kset;
    struct kset *devices_kset;
    struct klist klist_devices;
    struct klist klist_drivers;
    struct blocking_notifier_head bus_notifier;
    unsigned int drivers_autoprobe:1;
    struct bus_type *bus;
};

数据结构说明:

2.2- 总线注册

以PCI总线注册为例

2.2.1- pci总线注册

向系统中注册pci总线信息,总线名字为pci,总线的回调接口定义在pci_bus_type

drivers\pci\pci-driver.c
struct bus_type pci_bus_type = {
.name= "pci",
.match= pci_bus_match,
.uevent= pci_uevent,
.probe= pci_device_probe,
.remove= pci_device_remove,
.shutdown= pci_device_shutdown,
.dev_attrs= pci_dev_attrs,
.bus_attrs= pci_bus_attrs,
.pm= PCI_PM_OPS_PTR,
};
static int __init pci_driver_init(void)
{
return bus_register(&pci_bus_type);
}

2.2.2- 总线注册

主要动作:

1- kset_register : 在/sys/bus/路径下创建pci文件夹。

a- pci总线类型注册到的路径由priv->subsys.kobj.kset = bus_kset决定。buses_init中定义bus_kset为/sys/bus路径

b- 注册的pci总线名字在pci_bus_type.name定义。

2- 创建必要的文件

a- 创建/sys/bus/pci/uevent文件。用于通知用户态程序。bus_create_file(bus, &bus_attr_uevent);

b- 创建/sys/bus/pci/device文件。用于挂接pci设备。 kset_create_and_add("devices", NULL, &priv->subsys.kobj);

c- 创建/sys/bus/pci/drivers文件。用于挂接pci驱动。 kset_create_and_add("drivers", NULL, &priv->subsys.kobj);

d- 添加/sys/bus/pci/xxx_prob文件,包括drives_prob和drives_autoprob。add_probe_files(bus);

e- 添加属性文件/sys/bus/pci/xxx。例如rescan。 bus_add_attrs(bus);

注: 具体在系统/sys/bus/pci下注册了那些信息,可以自己去系统下看下。


drivers\base\bus.c
/**
 * bus_register - register a bus with the system.
 * @bus: bus.
 *
 * Once we have that, we registered the bus with the kobject
 * infrastructure, then register the children subsystems it has:
 * the devices and drivers that belong to the bus.
 */
int bus_register(struct bus_type *bus)
{
int retval;
struct bus_type_private *priv;
priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->bus = bus;
bus->p = priv;
BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);
retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);
if (retval)
goto out;
priv->subsys.kobj.kset = bus_kset;
priv->subsys.kobj.ktype = &bus_ktype;
priv->drivers_autoprobe = 1;
retval = kset_register(&priv->subsys);
if (retval)
goto out;
retval = bus_create_file(bus, &bus_attr_uevent);
if (retval)
goto bus_uevent_fail;
priv->devices_kset = kset_create_and_add("devices", NULL,
 &priv->subsys.kobj);
if (!priv->devices_kset) {
retval = -ENOMEM;
goto bus_devices_fail;
}
priv->drivers_kset = kset_create_and_add("drivers", NULL,
 &priv->subsys.kobj);
if (!priv->drivers_kset) {
retval = -ENOMEM;
goto bus_drivers_fail;
}
klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);
klist_init(&priv->klist_drivers, NULL, NULL);
retval = add_probe_files(bus);
if (retval)
goto bus_probe_files_fail;
retval = bus_add_attrs(bus);
if (retval)
goto bus_attrs_fail;
pr_debug("bus: '%s': registered\n", bus->name);
return 0;
bus_attrs_fail:
remove_probe_files(bus);
bus_probe_files_fail:
kset_unregister(bus->p->drivers_kset);
bus_drivers_fail:
kset_unregister(bus->p->devices_kset);
bus_devices_fail:
bus_remove_file(bus, &bus_attr_uevent);
bus_uevent_fail:
kset_unregister(&bus->p->subsys);
kfree(bus->p);
out:
bus->p = NULL;
return retval;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值