常见问题常见问题   搜索搜索   会员列表会员列表   团队团队   注册注册    个人资料个人资料   登录查看您的站内信件登录查看您的站内信件   登录登录 

freebsd里面driver和device的加载顺序?

 
发表新文章   回复文章    FreeBSD China -> 设备驱动
阅读上一个主题 :: 阅读下一个主题  
作者 留言
b0207191
半仙


注册时间: 2011-10-12
文章: 3

文章发表于: Wed 2011-10-12 17:48:07    发表主题: freebsd里面driver和device的加载顺序? 引用并回复

是不是这样
1.subr_bus.c里面先创建root节点
2.所有驱动通过DRIVER_MODULE加载
3.各种总线开始扫描硬件设备,调用probe查找对应驱动
返回页首
阅览会员资料 发送站内信件
fuzhli
半仙


注册时间: 2009-03-05
文章: 10

文章发表于: Mon 2011-10-17 22:08:12    发表主题: 引用并回复

1 从顺序来看,在mi_startup()中先执行优先级为SI_SUB_DRIVERS的routines,然后才执行优先级为SI_SUB_CONFIGURE的routines:
SI_SUB_DRIVERS = 0x3100000, /* Let Drivers initialize */
SI_SUB_CONFIGURE = 0x3800000, /* Configure devices */

2 在宏DRIVER_MODULE中会通过宏DECLARE_MODULE定义一个SYSINIT节点,并制定优先级为SI_SUB_DRIVERS。
宏DRIVER_MODULE定义在src/sys/sys/bus.h文件中。
宏DECLARE_MODULE定义在 src/sys/sys/module.h文件:
#define DECLARE_MODULE(name, data, sub, order) \
MODULE_METADATA(_md_##name, MDT_MODULE, &data, #name); \
SYSINIT(name##module, sub, order, module_register_init, &data) \
struct __hack

即在每个SYSINIT节点会执行函数 module_register_init,进而调用函数driver_module_handler。在这个函数中driver_module_handler会创建bus对应的devclass,并把dirver添加到其所声明的bus所对应的devclass上。

3 在优先级为SI_SUB_CONFIGURE的routines中,主要是一次调用configure_first(), configure()和configure_final()这三个函数。其中在configure_first中把nexus添加到root bus。设备的扫描是在configure中调用root_bus_configure()来完成的。 在root_bus_configure()中主要是利用前面创建好的devclass,对挂载在对应bus上的设备依次尝试对应的devclass上的drivers。

以前有写过一个不完整的分析,可以参考链接:http://www.cnblogs.com/fuzhli/archive/2010/09/11/1806849.html 。

BTW:pciconf和devinfo这两个命令会很有帮助的。

_________________
Oh, they killed kenny!
返回页首
阅览会员资料 发送站内信件 MSN Messenger
b0207191
半仙


注册时间: 2011-10-12
文章: 3

文章发表于: Mon 2011-10-24 14:17:36    发表主题: 引用并回复

最新源代码好像root_bus_configure和网页分析的不一样了?
代码:
void
root_bus_configure(void)
{

   PDEBUG(("."));

   /* Eventually this will be split up, but this is sufficient for now. */
   bus_set_pass(BUS_PASS_DEFAULT);
}


另外,nexus_devclass上的5个driver是在DRIVER_MODULE时挂上去的,好理解。nexus0上挂载的5个子设备是在什么时候挂到nexus下的呢?看了源代码,好像是在nexus_attach里面挂上的?
代码:
static int
nexus_attach(device_t dev)
{

    /*
     * Mask the legacy PICs - we will use the I/O SAPIC for interrupt.
     */
    outb(IO_ICU1+1, 0xff);
    outb(IO_ICU2+1, 0xff);

    if (acpi_identify() == 0)
        BUS_ADD_CHILD(dev, 10, "acpi", 0);
    clock_register(dev, 1000);
    bus_generic_attach(dev);
    return 0;
}
返回页首
阅览会员资料 发送站内信件
fuzhli
半仙


注册时间: 2009-03-05
文章: 10

文章发表于: Tue 2011-10-25 21:09:35    发表主题: 引用并回复

当时是拿FreeBSD 7.0的代码来分析的,和最新的代码应该有些出入了。在7.0的代码上nexus_attach函数是这样的:

代码:
static int
nexus_attach(device_t dev)
{

   bus_generic_probe(dev);
   bus_generic_attach(dev);
   return 0;
}


其中bus_generic_probe函数定义如下:
代码:
int
bus_generic_probe(device_t dev)
{
   devclass_t dc = dev->devclass;
   driverlink_t dl;

   TAILQ_FOREACH(dl, &dc->drivers, link) {
      DEVICE_IDENTIFY(dl->driver, dev);
   }

   return (0);
}


即调用各个driver注册的device_identify函数,如对于legacy0来说,调用的是legacy_identify:
代码:
static void
legacy_identify(driver_t *driver, device_t parent)
{

   /*
    * Add child device with order of 11 so it gets probed
    * after ACPI (which is at order 10).
    */
   if (BUS_ADD_CHILD(parent, 11, "legacy", 0) == NULL)
      panic("legacy: could not attach");
}


即在这里主动把legacy0这个设备挂载到nexus0上。

挂在nexus0下的其他几个设备也类似,是在device_identify函数中通过BUS_ADD_CHILD把子设备挂载上的。

b0207191 写到:
最新源代码好像root_bus_configure和网页分析的不一样了?
代码:
void
root_bus_configure(void)
{

   PDEBUG(("."));

   /* Eventually this will be split up, but this is sufficient for now. */
   bus_set_pass(BUS_PASS_DEFAULT);
}


另外,nexus_devclass上的5个driver是在DRIVER_MODULE时挂上去的,好理解。nexus0上挂载的5个子设备是在什么时候挂到nexus下的呢?看了源代码,好像是在nexus_attach里面挂上的?
代码:
static int
nexus_attach(device_t dev)
{

    /*
     * Mask the legacy PICs - we will use the I/O SAPIC for interrupt.
     */
    outb(IO_ICU1+1, 0xff);
    outb(IO_ICU2+1, 0xff);

    if (acpi_identify() == 0)
        BUS_ADD_CHILD(dev, 10, "acpi", 0);
    clock_register(dev, 1000);
    bus_generic_attach(dev);
    return 0;
}

_________________
Oh, they killed kenny!
返回页首
阅览会员资料 发送站内信件 MSN Messenger
b0207191
半仙


注册时间: 2011-10-12
文章: 3

文章发表于: Wed 2011-10-26 14:38:10    发表主题: 引用并回复

有几个疑问
1.整个设备树上设备的创建是不是都是在configure()例程中通过一级一级驱动递归地probe和attach来完成的?
2.有的设备是在xxx_identify中创建的,有的设备又是在xxx_probe中创建的,似乎没有一个规则,probe我的理解是纯粹检测某个已知设备和驱动是否匹配来着。
3.像支持热插拔的usb设备,是如何挂到设备树上的?(我的猜想是usb总线在运行中定时扫描,然后创建device_t节点挂到树上?)
返回页首
阅览会员资料 发送站内信件
fuzhli
半仙


注册时间: 2009-03-05
文章: 10

文章发表于: Wed 2011-10-26 23:20:13    发表主题: 引用并回复

第一个问题,从devinfo输出的树状结构来看,应该是你猜测的那样。不过,我只看过几个驱动,如此回答有点儿“管中窥豹”,也许有例外。

第二个问题,man 9 DEVICE_IDENTIFY,下面的描述片段应该能解答你的问题:
The identify function for a device is only needed for devices on busses
that cannot identify their children independently, e.g. the ISA bus. It
is used to recognize the device (usually done by accessing non-ambiguous
registers in the hardware) and to tell the kernel about it and thus cre-
ating a new device instance.
我个人的理解,一些虚拟的设备和无法探测的设备,需要使用device_identify函数。

第三个问题,因为没有看过usb设备的代码,不保证这个回复是准确的。你的猜测应该是对的。你需要了解一下usb hub设备,其规范有UHCI,OHCI,EHCI等。对于pc架构来说,这些设备一般是集成在南桥芯片上,这些usb hub设备在系统启动时会被检测到,并为这些设备注册相关的内核线程负责定期查询该hub上是否有设备热插拔,进而进行attach或者deattach这样的操作。

b0207191 写到:
有几个疑问
1.整个设备树上设备的创建是不是都是在configure()例程中通过一级一级驱动递归地probe和attach来完成的?
2.有的设备是在xxx_identify中创建的,有的设备又是在xxx_probe中创建的,似乎没有一个规则,probe我的理解是纯粹检测某个已知设备和驱动是否匹配来着。
3.像支持热插拔的usb设备,是如何挂到设备树上的?(我的猜想是usb总线在运行中定时扫描,然后创建device_t节点挂到树上?)

_________________
Oh, they killed kenny!
返回页首
阅览会员资料 发送站内信件 MSN Messenger
从以前的文章开始显示:   
发表新文章   回复文章    FreeBSD China -> 设备驱动 论坛时间为 北京时间
1页/共1

 
转跳到:  
不能发布新主题
不能在这个论坛回复主题
不能在这个论坛编辑自己的文章
不能在这个论坛删除自己的文章
不能在这个论坛发表投票


Powered by phpBB 2023cc © 2003 Opensource Steps; © 2003-2009 The FreeBSD Simplified Chinese Project
Powered by phpBB © 2001, 2005 phpBB Group
Protected by Project Honey Pot and phpBB.cc
silvery-trainer
The FreeBSD China Project 网站: 中文计划网站 社区网站
The FreeBSD China Project 版权所有 (C) 1999 - 2003 网页设计版权 著作权和商标