sysinit how does nexus find legacy's driver?

John Baldwin jhb at freebsd.org
Mon Nov 21 18:28:40 GMT 2005


On Monday 21 November 2005 11:07 am, kylin wrote:
> The nexus_attach(device_t dev) will call
>
> int
> bus_generic_probe(device_t dev)
> {
> 	devclass_t dc = dev->devclass;
> 	driverlink_t dl;
>
> 	TAILQ_FOREACH(dl, &dc->drivers, link) {//here configure has point out
> the relation?
> 		DEVICE_IDENTIFY(dl->driver, dev);//here refer to the son's
> IDENTIFY,make son's device structure
> 	}
>
> 	return (0);
> }
> the question is
> in TAILQ_FOREACH(dl, &dc->drivers, link)
> how does nexus get legacy's  driver in its devclass ?
> have it done in the SI_SUB_DRIVER part?of initialization?
>
> What happen during sSI_SUB_DRIVER ,does devclass for each driver
> initialized?
>
>
> May be the before SI_SUB_CONFIGURE, SI_SUB_DRIVER will first be
> implement ,and the relative drivers will connect to each other.
> I am sure that in autoconf.c ,the dl->link does not be add in ,so
> where does the nexus find legacy?
> In devclass_find_inernal
> 	TAILQ_FOREACH(dc, &devclasses, link) {
> 		if (!strcmp(dc->name, classname))
> 			break;
> 	}found nothing ,
>
> //////////////////

It's a lot of magic. :)  Each driver is a kernel module declared via 
DRIVER_MODULE():

#define	DRIVER_MODULE(name, busname, driver, devclass, evh, arg)	\
									\
static struct driver_module_data name##_##busname##_driver_mod = {	\
	evh, arg,							\
	#busname,							\
	(kobj_class_t) &driver,						\
	&devclass							\
};									\
									\
static moduledata_t name##_##busname##_mod = {				\
	#busname "/" #name,						\
	driver_module_handler,						\
	&name##_##busname##_driver_mod					\
};									\
DECLARE_MODULE(name##_##busname, name##_##busname##_mod,		\
	       SI_SUB_DRIVERS, SI_ORDER_MIDDLE)

This causes driver_module_handler() to be run at SI_SUB_DRIVERS for each
driver in the kernel.  One of the things that function does is add the driver 
to the parent driver's devclass:

int
driver_module_handler(module_t mod, int what, void *arg)
{
	...

	switch (what) {
	case MOD_LOAD:
		...

		driver = dmd->dmd_driver;
		PDEBUG(("Loading module: driver %s on bus %s",
		    DRIVERNAME(driver), dmd->dmd_busname));
		error = devclass_add_driver(bus_devclass, driver);
		if (error)
			break;
	...
}

That adds the driver to the dc_drivers list.  Thus, when you see:

DRIVER_MODULE(legacy, nexus, legacy_driver, legacy_devclass, 0, 0);

in legacy.c, that results in legacy_driver being attached to the devclass for 
the nexus driver.

-- 
John Baldwin <jhb at FreeBSD.org>  <><  http://www.FreeBSD.org/~jhb/
"Power Users Use the Power to Serve"  =  http://www.FreeBSD.org


More information about the freebsd-hackers mailing list