diff options
-rw-r--r-- | sys/kern/subr_autoconf.c | 69 | ||||
-rw-r--r-- | sys/sys/device.h | 3 |
2 files changed, 67 insertions, 5 deletions
diff --git a/sys/kern/subr_autoconf.c b/sys/kern/subr_autoconf.c index 866e1c9979a..93613bb63df 100644 --- a/sys/kern/subr_autoconf.c +++ b/sys/kern/subr_autoconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: subr_autoconf.c,v 1.23 1999/07/23 19:45:21 niklas Exp $ */ +/* $OpenBSD: subr_autoconf.c,v 1.24 1999/08/05 17:41:44 niklas Exp $ */ /* $NetBSD: subr_autoconf.c,v 1.21 1996/04/04 06:06:18 cgd Exp $ */ /* @@ -95,6 +95,16 @@ int autoconf_verbose = AUTOCONF_VERBOSE; /* trace probe calls */ static char *number __P((char *, int)); static void mapply __P((struct matchinfo *, struct cfdata *)); +struct deferred_config { + TAILQ_ENTRY(deferred_config) dc_queue; + struct device *dc_dev; + void (*dc_func) __P((struct device *)); +}; + +TAILQ_HEAD(, deferred_config) deferred_config_queue; + +void config_process_deferred_children __P((struct device *)); + struct devicelist alldevs; /* list of all devices */ struct evcntlist allevents; /* list of all event counters */ @@ -106,7 +116,7 @@ struct evcntlist allevents; /* list of all event counters */ void config_init() { - + TAILQ_INIT(&deferred_config_queue); TAILQ_INIT(&alldevs); TAILQ_INIT(&allevents); TAILQ_INIT(&allcftables); @@ -117,7 +127,7 @@ config_init() * Apply the matching function and choose the best. This is used * a few times and we want to keep the code small. */ -static void +void mapply(m, cf) register struct matchinfo *m; register struct cfdata *cf; @@ -335,7 +345,7 @@ config_rootfound(rootname, aux) } /* just like sprintf(buf, "%d") except that it works from the end */ -static char * +char * number(ep, n) register char *ep; register int n; @@ -418,6 +428,7 @@ config_attach(parent, match, aux, print) device_register(dev, aux); #endif (*ca->ca_attach)(parent, dev, aux); + config_process_deferred_children(dev); return (dev); } @@ -500,6 +511,56 @@ config_make_softc(parent, cf) } /* + * Defer the configuration of the specified device until all + * of its parent's devices have been attached. + */ +void +config_defer(dev, func) + struct device *dev; + void (*func) __P((struct device *)); +{ + struct deferred_config *dc; + + if (dev->dv_parent == NULL) + panic("config_defer: can't defer config of a root device"); + +#ifdef DIAGNOSTIC + for (dc = TAILQ_FIRST(&deferred_config_queue); dc != NULL; + dc = TAILQ_NEXT(dc, dc_queue)) { + if (dc->dc_dev == dev) + panic("config_defer: deferred twice"); + } +#endif + + if ((dc = malloc(sizeof(*dc), M_DEVBUF, M_NOWAIT)) == NULL) + panic("config_defer: can't allocate defer structure"); + + dc->dc_dev = dev; + dc->dc_func = func; + TAILQ_INSERT_TAIL(&deferred_config_queue, dc, dc_queue); +} + +/* + * Process the deferred configuration queue for a device. + */ +void +config_process_deferred_children(parent) + struct device *parent; +{ + struct deferred_config *dc, *ndc; + + for (dc = TAILQ_FIRST(&deferred_config_queue); + dc != NULL; dc = ndc) { + ndc = TAILQ_NEXT(dc, dc_queue); + if (dc->dc_dev->dv_parent == parent) { + TAILQ_REMOVE(&deferred_config_queue, dc, dc_queue); + (*dc->dc_func)(dc->dc_dev); + free(dc, M_DEVBUF); + } + } +} + +/* * Attach an event. These must come from initially-zero space (see * commented-out assignments below), but that occurs naturally for * device instance variables. diff --git a/sys/sys/device.h b/sys/sys/device.h index a7980629246..bb241eeba60 100644 --- a/sys/sys/device.h +++ b/sys/sys/device.h @@ -1,4 +1,4 @@ -/* $OpenBSD: device.h,v 1.15 1999/07/23 19:45:20 niklas Exp $ */ +/* $OpenBSD: device.h,v 1.16 1999/08/05 17:41:43 niklas Exp $ */ /* $NetBSD: device.h,v 1.15 1996/04/09 20:55:24 cgd Exp $ */ /* @@ -181,6 +181,7 @@ void config_scan __P((cfscan_t, struct device *)); struct device *config_attach __P((struct device *, void *, void *, cfprint_t)); struct device *config_make_softc __P((struct device *parent, struct cfdata *cf)); +void config_defer __P((struct device *, void (*)(struct device *))); void evcnt_attach __P((struct device *, const char *, struct evcnt *)); /* compatibility definitions */ |