[BACK]Return to config_search.c CVS log [TXT][DIR] Up to [local] / prex-old / dev / core

File: [local] / prex-old / dev / core / config_search.c (download)

Revision 1.2, Tue Aug 12 11:30:52 2008 UTC (15 years, 8 months ago) by nbrk
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +3 -3 lines

proxy *aux cookie instead of allocated softc to match() functions

/*
 * $Id: config_search.c,v 1.2 2008/08/12 11:30:52 nbrk Exp $
 */
#include <driver.h>

/* #define AUTOCONF_DEBUG */

#ifndef AUTOCONF_DEBUG
#define DPRINTF(fmt...)  do {} while (0)
#else
#define DPRINTF(fmt...)	do { printk(fmt); } while (0)
#endif /* !AUTOCONF_DEBUG */

extern struct driver	*drivers[];
extern struct attachment	config_table[];

int
config_search_children(struct device *parent, void *aux)
{
	struct attachment	*atp;
	struct driver	*chdrvp, *hedrvp;
	struct device	*self;
	int	retval;
	int	ndevs;

	DPRINTF("config_search_children: enter, name=%s\n", parent->dv_xname);
	atp = config_table;

	/*
	 * Look through the table.
	 */
	while (atp->at_childname != NULL) {
		DPRINTF("config_table: trying %s at %s%u via %s\n", atp->at_childname, atp->at_parentname,
				atp->at_parentunit == -1 ? "*" : atp->at_parentunit,
				atp->at_helpername != NULL ? atp->at_helpername : "(self)");

		if (atp->at_parentname == NULL)
			panic("config: bogus config table (no parent given for %s)", 
					atp->at_childname);

		if (strncmp(atp->at_parentname, parent->dv_xname, CONFIG_XNAMELEN) == 0) {
			/*
			 * Names are matched.
			 */
			/* see if parent unit is specified */
			if (atp->at_parentunit != -1 && parent->dv_unit != atp->at_parentunit)
				/* child didn't like our unit number */
				break;

			/*
			 * This is our child device.
			 */
			/* locate child driver */
			chdrvp = config_find_driver(atp->at_childname);

			/*
			 * See if helper is specified.
			 */
			if (atp->at_helpername != NULL) {
				/* locate helper driver */
				hedrvp = config_find_driver(atp->at_helpername);

				/* match helper */
				if (hedrvp->dr_match != NULL && hedrvp->dr_match(parent, aux) < 1)
					break;	/* not matched */
			}

			/* match device */
			if (chdrvp->dr_match != NULL && chdrvp->dr_match(parent, aux) < 1)
				break;	/* not matched */

			/* allocate device */
			self = config_alloc_device(chdrvp);

			/* increase units number in driver */
			chdrvp->dr_nunits++;

			/* initialize device */
			self->dv_xname = chdrvp->dr_name;
			self->dv_unit = chdrvp->dr_nunits;
			self->dv_flags = atp->at_flags;
			self->dv_parent = parent;

			printk("%s%u at %s%u via %s flags 0x%x: ", self->dv_xname, self->dv_unit,
				parent->dv_xname, parent->dv_unit,
				atp->at_helpername != NULL ? atp->at_helpername : "(self)", self->dv_flags);

			/*
			 * Attach device directly or via its helper.
			 * If there is helper, call its attach routine instead of child's one.
			 */
			if (atp->at_helpername != NULL) {
				if (hedrvp->dr_attach == NULL)
					panic("config: no attach entry for driver '%s'", hedrvp->dr_name);

				retval = hedrvp->dr_attach(parent, self, aux);
			} else {
				/* no helper, direct attach */
				if (chdrvp->dr_attach == NULL)
					panic("config: no attach entry for driver '%s'", chdrvp->dr_name);

				retval = chdrvp->dr_attach(parent, self, aux);
			}

			/*
			 * Attachment is done. See if it's succeeded.
			 */
			if (retval != 0) {
				/* attachment failed */
				config_free_device(self);

				/* decrement nunits in driver */
				chdrvp->dr_nunits--;
			}

		}
		/* okay, see next line in config_table */
		atp++;
		ndevs++;
	}

	return(ndevs);
}


struct driver
*config_find_driver(const char *name)
{
	/*
	 * Return pointer to driver for given 'name'.
	 */
	struct driver	*drvp;
	int	i;

#if 0
	drvp = drivers[0];

	while (drvp != NULL) {
		DPRINTFg("drvp->dr_name %s\n", drvp->dr_name);
		if (strncmp(drvp->dr_name, name, CONFIG_XNAMELEN) == 0) {
			DPRINTF("config: found driver for %s\n", drvp->dr_name);
			return(drvp);
		}

		drvp += sizeof(struct driver *);
	}
#endif
	for (i = 0; i < 100; i++) {
		drvp = drivers[i];
		if (drvp == NULL)
			break;

		if (strncmp(drvp->dr_name, name, CONFIG_XNAMELEN) == 0) {
			return(drvp);
		}
	}

	panic("config: can't find driver for name '%s'", name);
}