PERFORCE change 106148 for review

John Baldwin jhb at freebsd.org
Fri Sep 15 10:08:33 PDT 2006


On Friday 15 September 2006 11:10, Hans Petter Selasky wrote:
> On Friday 15 September 2006 16:39, you wrote:
> > On Friday 15 September 2006 10:17, Hans Petter Selasky wrote:
> > > http://perforce.freebsd.org/chv.cgi?CH=106148
> > >
> > > Change 106148 by hselasky at hselasky_mini_itx on 2006/09/15 14:17:12
> > >
> > >  Initialize all driver_t structures by record. Bugfix: Some of the
> > >  modem drivers did not use the "ucom_devclass". Make sure that all
> > >  modem drivers use this devclass.
> >
> > That doesn't actually matter.  Also, no other drivers use this style to
> > initialize their driver_t.  If you really wanted to do a change, you 
should
> > change them to use DEFINE_CLASS macros to define a KOBJ class instead.
> 
> Ok. Will consider that next time.
> 
> > BTW, why the devclass doesn't matter:  the devclass_t is just a pointer to
> > a device class.  The device classes are based on the driver name, so if 
you
> > add a new driver with the name "foo", it will look up the device class by
> > name ("foo"), creating one if it doesn't exist.  
> 
> My implementation for NetBSD works like this:

This is FreeBSD I'm talking about.

> > It then saves a pointer to 
> > that device class object in the devclass_t pointer specified in
> > DRIVER_MODULE(). So, by making them all share the same devclass_t, they 
are
> > all just going to overwrite the same pointer when the driver module loads. 
> 
> No, wrong. The devclass_t pointer is not overwritten if it is already 
> initialized!

Umm.  It's overwritten, but to the same value.  Go look at the actual code.  
This is the function that is called via SYSINIT via DRIVER_MODULE():

/**
 * @brief Module handler for registering device drivers
 *
 * This module handler is used to automatically register device
 * drivers when modules are loaded. If @p what is MOD_LOAD, it calls
 * devclass_add_driver() for the driver described by the
 * driver_module_data structure pointed to by @p arg
 */
int
driver_module_handler(module_t mod, int what, void *arg)
{
	...
	dmd = (struct driver_module_data *)arg;
	...
	switch (what) {
	case MOD_LOAD:
		...
		if (driver->baseclasses) {
			const char *parentname;
			parentname = driver->baseclasses[0]->name;
			*dmd->dmd_devclass =
				devclass_find_internal(driver->name,
				    parentname, TRUE);
		} else {
			*dmd->dmd_devclass =
				devclass_find_internal(driver->name, 0, TRUE);
		}
		break;
	...
}

The writes to dmd_devclass are writing to the 'static devclass_t' you
specify in your DRIVER_MODULE() line.  As I mentioned earlier, devclass_t
isn't a struct, it's a pointer to a struct:

typedef struct devclass		*devclass_t;

Basically, passing a devclass_t into DRIVER_MODULE() just gives you a 
pre-intialized pointer to your devclass.  The devclass's aren't bound to that 
devclass_t though, they are bound to the name.  Thus if you have:

static devclass_t foo_class, bar_class;

static driver_t foo_driver {
	"foo", ...
};

static driver_t bar_driver {
	"foo", ...
};

DRIVER_MODULE(..., foo_driver, foo_devclass, ...);
DRIVER_MODULE(..., bar_driver, bar_devclass, ...);

foo_devclass and bar_devclass will both point to the same device class object.

> > To be honest, most drivers don't even use the devclass pointer, and I'd
> > actually like to axe it and make the few drivers that do care use
> > 'devclass_find("foo")' when they need the devclass pointer instead.
> 
> I need the devclass to get unique unit numbers.

Again, go look at the actual code, it can still call devclass_find_internal(), 
but it is not required to save the pointer to do so.

-- 
John Baldwin


More information about the p4-projects mailing list