File: [local] / prex-old / dev / core / config_search.c (download)
Revision 1.2, Tue Aug 12 11:30:52 2008 UTC (16 years, 1 month 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);
}