FreeBSD/sys/kern/subr_bus.c
/**
 * @internal
 * @brief Find or create a device class
 *
 * If a device class with the name @p classname exists, return it,
 * otherwise if @p create is non-zero create and return a new device
 * class.
 *
 * If @p parentname is non-NULL, the parent of the devclass is set to
 * the devclass of that name.
 *
 * @param classname	the devclass name to find or create
 * @param parentname	the parent devclass name or @c NULL
 * @param create	non-zero to create a devclass
 */
@internal
@brief Find or create a device class

If a device class with the name @p classname exists, return it,
otherwise if @p create is non-zero create and return a new device
class.

If @p parentname is non-NULL, the parent of the devclass is set to
the devclass of that name.

@param classname     the devclass name to find or create
@param parentname    the parent devclass name or @c NULL
@param create        non-zero to create a devclass
@internal @brief Find or create a device class If a device class with the name @p classname exists return it otherwise if @p create is non - zero create and return a new device class . If @p parentname is non - NULL the parent of the devclass is set to the devclass of that name . @param classname the devclass name to find or create @param parentname the parent devclass name or @c NULL @param create non - zero to create a devclass
static devclass_t
devclass_find_internal(const char *classname, const char *parentname,
		       int create)
{
	devclass_t dc;
	PDEBUG(("looking for %s", classname));
	if (!classname)
		return (NULL);
	TAILQ_FOREACH(dc, &devclasses, link) {
		if (!strcmp(dc->name, classname))
			break;
	}
	if (create && !dc) {
		PDEBUG(("creating %s", classname));
		dc = malloc(sizeof(struct devclass) + strlen(classname) + 1,
		    M_BUS, M_NOWAIT | M_ZERO);
		if (!dc)
			return (NULL);
		dc->parent = NULL;
		dc->name = (char*) (dc + 1);
		strcpy(dc->name, classname);
		TAILQ_INIT(&dc->drivers);
		TAILQ_INSERT_TAIL(&devclasses, dc, link);
		bus_data_generation_update();
	}
	if (parentname && dc && !dc->parent &&
	    strcmp(classname, parentname) != 0) {
		dc->parent = devclass_find_internal(parentname, NULL, TRUE);
		dc->parent->flags |= DC_HAS_CHILDREN;
	}
	return (dc);
}
static devclass_t devclass_find_internal ( const char * classname , const char * parentname , int create ) { devclass_t dc ; PDEBUG ( ( " " , classname ) ) ; if ( ! classname ) return ( NULL ) ; TAILQ_FOREACH ( dc , & devclasses , link ) { if ( ! strcmp ( dc -> name , classname ) ) break ; } if ( create && ! dc ) { PDEBUG ( ( " " , classname ) ) ; dc = malloc ( sizeof ( struct devclass ) + strlen ( classname ) + 1 , M_BUS , M_NOWAIT | M_ZERO ) ; if ( ! dc ) return ( NULL ) ; dc -> parent = NULL ; dc -> name = ( char * ) ( dc + 1 ) ; strcpy ( dc -> name , classname ) ; TAILQ_INIT ( & dc -> drivers ) ; TAILQ_INSERT_TAIL ( & devclasses , dc , link ) ; bus_data_generation_update ( ) ; } if ( parentname && dc && ! dc -> parent && strcmp ( classname , parentname ) != 0 ) { dc -> parent = devclass_find_internal ( parentname , NULL , TRUE ) ; dc -> parent -> flags |= DC_HAS_CHILDREN ; } return ( dc ) ; }
@internal
 @brief Find or create a device class
@internal @brief Find or create a device class
/*
	 * If a parent class is specified, then set that as our parent so
	 * that this devclass will support drivers for the parent class as
	 * well.  If the parent class has the same name don't do this though
	 * as it creates a cycle that can trigger an infinite loop in
	 * device_probe_child() if a device exists for which there is no
	 * suitable driver.
	 */