Linux設備驅動模型探究--4(driver)



四. 關於驅動(driver)--driver.c

/*數據結構*/
struct device_driver {
 const char  *name;  /*驅動名字*/
 struct bus_type  *bus; /*驅動所屬總線*/
 struct module  *owner; /*驅動所在內核模塊*/

 int (*probe) (struct device *dev);  /*當總線bus將該驅動和對應得設備相互綁定的時候,
           /*內核會首先調用bus的probe函數,如果沒有就會調用該probe函數,在driver_register中調用*/
           
 int (*remove) (struct device *dev);  /*原理和probe一樣, 但是在driver_unregister中調用*/

 struct driver_private *p;
};


驅動上主要的操作:

/*在bus的drivers_kset集合查找驅動,name-查找名稱,bus-哪個總線*/-->在bus上查找名稱爲name的驅動,成功返回driver
struct device_driver *driver_find(const char *name, struct bus_type *bus)
{
 struct kobject *k = kset_find_obj(bus->p->drivers_kset, name);
 struct driver_private *priv;

 if (k) {
  priv = to_driver(k);
  return priv->driver;
 }
 return NULL;
}

/**
 * driver_register - register driver with bus
 * @drv: driver to register
 *
 * We pass off most of the work to the bus_add_driver() call,
 * since most of the things we have to do deal with the bus
 * structures.
 */
int driver_register(struct device_driver *drv)
{
 int ret;
 struct device_driver *other;
 if ((drv->bus->probe && drv->probe) ||
     (drv->bus->remove && drv->remove) ||
     (drv->bus->shutdown && drv->shutdown))
  printk(KERN_WARNING "Driver '%s' needs updating - please use "
   "bus_type methods\n", drv->name);

 other = driver_find(drv->name, drv->bus);  /*先判斷驅動是否註冊了*/
 if (other) {
  put_driver(other);
  printk(KERN_ERR "Error: Driver '%s' is already registered, "
   "aborting...\n", drv->name);
  return -EBUSY;
 }

 ret = bus_add_driver(drv);   /*往bus上註冊(添加)驅動*/
 if (ret)
  return ret;
 ret = driver_add_groups(drv, drv->groups);
 if (ret)
  bus_remove_driver(drv);
 return ret;
}


***********************接下分析bus_add_driver()****************************

/**
 * bus_add_driver - Add a driver to the bus.
 * @drv: driver.
 */
int bus_add_driver(struct device_driver *drv)
{
 struct bus_type *bus;
 struct driver_private *priv;
 int error = 0;

 bus = bus_get(drv->bus);
 if (!bus)
  return -EINVAL;

 /*初始化驅動私有數據 p*/
 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 if (!priv) {
  error = -ENOMEM;
  goto out_put_bus;
 }
 
 klist_init(&priv->klist_devices, NULL, NULL);
 priv->driver = drv;
 drv->p = priv;
 
 /*建立priv->kobj和bus->p->drivers_kset(扮演parent)層次關係,*/
 priv->kobj.kset = bus->p->drivers_kset;
 
 error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
         "%s", drv->name);

 if (drv->bus->p->drivers_autoprobe) {
  error = driver_attach(drv);   //匹配設備
  if (error)
   goto out_unregister;
 }
 
 klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);//向bus驅動鏈表中添加驅動
 module_add_driver(drv->owner, drv);  //向模塊中添加驅動

 error = driver_create_file(drv, &driver_attr_uevent); //創建uevent屬性文件

 error = driver_add_attrs(bus, drv);      //創先驅動屬性文件


 /* * kobject_uevent - notify userspace by sending an uevent
  *
  * @action: action that is happening
  * @kobj: struct kobject that the action is happening to
  *
  */
 kobject_uevent(&priv->kobj, KOBJ_ADD);    
 return 0;
}

/*參考資料:

深入Linux設備驅動程序內核機制。 陳雪松著

Linux設備驅動開發詳解--基於最新的Linux4.0內核。 宋寶華著

*/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章