Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/kern/subr_autoconf.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/kern/subr_autoconf.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.277 retrieving revision 1.277.2.5 diff -u -p -r1.277 -r1.277.2.5 --- src/sys/kern/subr_autoconf.c 2021/01/27 04:54:08 1.277 +++ src/sys/kern/subr_autoconf.c 2021/03/22 17:21:09 1.277.2.5 @@ -1,4 +1,4 @@ -/* $NetBSD: subr_autoconf.c,v 1.277 2021/01/27 04:54:08 thorpej Exp $ */ +/* $NetBSD: subr_autoconf.c,v 1.277.2.5 2021/03/22 17:21:09 thorpej Exp $ */ /* * Copyright (c) 1996, 2000 Christopher G. Demetriou @@ -77,7 +77,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.277 2021/01/27 04:54:08 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.277.2.5 2021/03/22 17:21:09 thorpej Exp $"); #ifdef _KERNEL_OPT #include "opt_ddb.h" @@ -107,6 +107,7 @@ __KERNEL_RCSID(0, "$NetBSD: subr_autocon #include #include #include +#include #include @@ -808,6 +809,23 @@ cfdriver_get_iattr(const struct cfdriver return 0; } +#if defined(DIAGNOSTIC) +static int +cfdriver_iattr_count(const struct cfdriver *cd) +{ + const struct cfiattrdata * const *cpp; + int i; + + if (cd->cd_attrs == NULL) + return 0; + + for (i = 0, cpp = cd->cd_attrs; *cpp; cpp++) { + i++; + } + return i; +} +#endif /* DIAGNOSTIC */ + /* * Lookup an interface attribute description by name. * If the driver is given, consider only its supported attributes. @@ -1001,6 +1019,50 @@ config_match(device_t parent, cfdata_t c return (*ca->ca_match)(parent, cf, aux); } +static void +config_get_cfargs(cfarg_t tag, + cfsubmatch_t *fnp, /* output */ + const char **ifattrp, /* output */ + const int **locsp, /* output */ + va_list ap) +{ + cfsubmatch_t fn = NULL; + const char *ifattr = NULL; + const int *locs = NULL; + + while (tag != CFARG_EOL) { + switch (tag) { + case CFARG_SUBMATCH: + fn = va_arg(ap, cfsubmatch_t); + break; + + case CFARG_IATTR: + ifattr = va_arg(ap, const char *); + break; + + case CFARG_LOCATORS: + locs = va_arg(ap, const int *); + break; + + default: + /* XXX panic? */ + /* XXX dump stack backtrace? */ + aprint_error("%s: unknown cfarg tag: %d\n", + __func__, tag); + goto out; + } + tag = va_arg(ap, cfarg_t); + } + + out: + if (fnp != NULL) + *fnp = fn; + if (ifattrp != NULL) + *ifattrp = ifattr; + if (locsp != NULL) + *locsp = locs; +} + /* * Iterate over all potential children of some device, calling the given * function (default being the child's match function) for each one. @@ -1012,16 +1074,21 @@ config_match(device_t parent, cfdata_t c * an arbitrary function to all potential children (its return value * can be ignored). */ -cfdata_t -config_search_loc(cfsubmatch_t fn, device_t parent, - const char *ifattr, const int *locs, void *aux) +static cfdata_t +config_vsearch(device_t parent, void *aux, cfarg_t tag, va_list ap) { + cfsubmatch_t fn; + const char *ifattr; + const int *locs; struct cftable *ct; cfdata_t cf; struct matchinfo m; + config_get_cfargs(tag, &fn, &ifattr, &locs, ap); + KASSERT(config_initialized); KASSERT(!ifattr || cfdriver_get_iattr(parent->dv_cfdriver, ifattr)); + KASSERT(ifattr || cfdriver_iattr_count(parent->dv_cfdriver) < 2); m.fn = fn; m.parent = parent; @@ -1064,11 +1131,16 @@ config_search_loc(cfsubmatch_t fn, devic } cfdata_t -config_search_ia(cfsubmatch_t fn, device_t parent, const char *ifattr, - void *aux) +config_search(device_t parent, void *aux, cfarg_t tag, ...) { + cfdata_t cf; + va_list ap; - return config_search_loc(fn, parent, ifattr, NULL, aux); + va_start(ap, tag); + cf = config_vsearch(parent, aux, tag, ap); + va_end(ap); + + return cf; } /* @@ -1113,15 +1185,23 @@ static const char * const msgs[3] = { "" * functions) and attach it, and return its device_t. If the device was * not configured, call the given `print' function and return NULL. */ -device_t -config_found_sm_loc(device_t parent, - const char *ifattr, const int *locs, void *aux, - cfprint_t print, cfsubmatch_t submatch) +static device_t +config_vfound(device_t parent, void *aux, cfprint_t print, cfarg_t tag, + va_list ap) { + cfsubmatch_t submatch; + const char *ifattr; + const int *locs; cfdata_t cf; - if ((cf = config_search_loc(submatch, parent, ifattr, locs, aux))) - return(config_attach_loc(parent, cf, locs, aux, print)); + config_get_cfargs(tag, &submatch, &ifattr, &locs, ap); + + if ((cf = config_search(parent, aux, + CFARG_SUBMATCH, submatch, + CFARG_IATTR, ifattr, + CFARG_LOCATORS, locs, + CFARG_EOL))) + return config_attach_loc(parent, cf, locs, aux, print); if (print) { if (config_do_twiddle && cold) twiddle(); @@ -1139,19 +1219,28 @@ config_found_sm_loc(device_t parent, return NULL; } +/* XXX GC */ device_t config_found_ia(device_t parent, const char *ifattr, void *aux, cfprint_t print) { - return config_found_sm_loc(parent, ifattr, NULL, aux, print, NULL); + return config_found(parent, aux, print, + CFARG_IATTR, ifattr, + CFARG_EOL); } device_t -config_found(device_t parent, void *aux, cfprint_t print) +config_found(device_t parent, void *aux, cfprint_t print, cfarg_t tag, ...) { + device_t dev; + va_list ap; - return config_found_sm_loc(parent, NULL, NULL, aux, print, NULL); + va_start(ap, tag); + dev = config_vfound(parent, aux, print, tag, ap); + va_end(ap); + + return dev; } /*