The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/subr_autoconf.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* $NetBSD: subr_autoconf.c,v 1.115 2006/10/02 02:59:38 chs Exp $ */
    2 
    3 /*
    4  * Copyright (c) 1996, 2000 Christopher G. Demetriou
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. All advertising materials mentioning features or use of this software
   16  *    must display the following acknowledgement:
   17  *          This product includes software developed for the
   18  *          NetBSD Project.  See http://www.NetBSD.org/ for
   19  *          information about NetBSD.
   20  * 4. The name of the author may not be used to endorse or promote products
   21  *    derived from this software without specific prior written permission.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   33  *
   34  * --(license Id: LICENSE.proto,v 1.1 2000/06/13 21:40:26 cgd Exp )--
   35  */
   36 
   37 /*
   38  * Copyright (c) 1992, 1993
   39  *      The Regents of the University of California.  All rights reserved.
   40  *
   41  * This software was developed by the Computer Systems Engineering group
   42  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
   43  * contributed to Berkeley.
   44  *
   45  * All advertising materials mentioning features or use of this software
   46  * must display the following acknowledgement:
   47  *      This product includes software developed by the University of
   48  *      California, Lawrence Berkeley Laboratories.
   49  *
   50  * Redistribution and use in source and binary forms, with or without
   51  * modification, are permitted provided that the following conditions
   52  * are met:
   53  * 1. Redistributions of source code must retain the above copyright
   54  *    notice, this list of conditions and the following disclaimer.
   55  * 2. Redistributions in binary form must reproduce the above copyright
   56  *    notice, this list of conditions and the following disclaimer in the
   57  *    documentation and/or other materials provided with the distribution.
   58  * 3. Neither the name of the University nor the names of its contributors
   59  *    may be used to endorse or promote products derived from this software
   60  *    without specific prior written permission.
   61  *
   62  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   63  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   64  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   65  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   66  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   67  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   68  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   69  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   70  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   71  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   72  * SUCH DAMAGE.
   73  *
   74  * from: Header: subr_autoconf.c,v 1.12 93/02/01 19:31:48 torek Exp  (LBL)
   75  *
   76  *      @(#)subr_autoconf.c     8.3 (Berkeley) 5/17/94
   77  */
   78 
   79 #include <sys/cdefs.h>
   80 __KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.115 2006/10/02 02:59:38 chs Exp $");
   81 
   82 #include "opt_ddb.h"
   83 
   84 #include <sys/param.h>
   85 #include <sys/device.h>
   86 #include <sys/malloc.h>
   87 #include <sys/systm.h>
   88 #include <sys/kernel.h>
   89 #include <sys/errno.h>
   90 #include <sys/proc.h>
   91 #include <sys/reboot.h>
   92 #include <machine/limits.h>
   93 
   94 #include "opt_userconf.h"
   95 #ifdef USERCONF
   96 #include <sys/userconf.h>
   97 #endif
   98 
   99 #ifdef __i386__
  100 #include "opt_splash.h"
  101 #if defined(SPLASHSCREEN) && defined(SPLASHSCREEN_PROGRESS)
  102 #include <dev/splash/splash.h>
  103 extern struct splash_progress *splash_progress_state;
  104 #endif
  105 #endif
  106 
  107 /*
  108  * Autoconfiguration subroutines.
  109  */
  110 
  111 /*
  112  * ioconf.c exports exactly two names: cfdata and cfroots.  All system
  113  * devices and drivers are found via these tables.
  114  */
  115 extern struct cfdata cfdata[];
  116 extern const short cfroots[];
  117 
  118 /*
  119  * List of all cfdriver structures.  We use this to detect duplicates
  120  * when other cfdrivers are loaded.
  121  */
  122 struct cfdriverlist allcfdrivers = LIST_HEAD_INITIALIZER(&allcfdrivers);
  123 extern struct cfdriver * const cfdriver_list_initial[];
  124 
  125 /*
  126  * Initial list of cfattach's.
  127  */
  128 extern const struct cfattachinit cfattachinit[];
  129 
  130 /*
  131  * List of cfdata tables.  We always have one such list -- the one
  132  * built statically when the kernel was configured.
  133  */
  134 struct cftablelist allcftables;
  135 static struct cftable initcftable;
  136 
  137 #define ROOT ((device_t)NULL)
  138 
  139 struct matchinfo {
  140         cfsubmatch_t fn;
  141         struct  device *parent;
  142         const int *locs;
  143         void    *aux;
  144         struct  cfdata *match;
  145         int     pri;
  146 };
  147 
  148 static char *number(char *, int);
  149 static void mapply(struct matchinfo *, cfdata_t);
  150 
  151 struct deferred_config {
  152         TAILQ_ENTRY(deferred_config) dc_queue;
  153         device_t dc_dev;
  154         void (*dc_func)(device_t);
  155 };
  156 
  157 TAILQ_HEAD(deferred_config_head, deferred_config);
  158 
  159 struct deferred_config_head deferred_config_queue;
  160 struct deferred_config_head interrupt_config_queue;
  161 
  162 static void config_process_deferred(struct deferred_config_head *, device_t);
  163 
  164 /* Hooks to finalize configuration once all real devices have been found. */
  165 struct finalize_hook {
  166         TAILQ_ENTRY(finalize_hook) f_list;
  167         int (*f_func)(device_t);
  168         device_t f_dev;
  169 };
  170 static TAILQ_HEAD(, finalize_hook) config_finalize_list;
  171 static int config_finalize_done;
  172 
  173 /* list of all devices */
  174 struct devicelist alldevs;
  175 
  176 volatile int config_pending;            /* semaphore for mountroot */
  177 
  178 #define STREQ(s1, s2)                   \
  179         (*(s1) == *(s2) && strcmp((s1), (s2)) == 0)
  180 
  181 static int config_initialized;          /* config_init() has been called. */
  182 
  183 static int config_do_twiddle;
  184 
  185 /*
  186  * Initialize the autoconfiguration data structures.  Normally this
  187  * is done by configure(), but some platforms need to do this very
  188  * early (to e.g. initialize the console).
  189  */
  190 void
  191 config_init(void)
  192 {
  193         const struct cfattachinit *cfai;
  194         int i, j;
  195 
  196         if (config_initialized)
  197                 return;
  198 
  199         /* allcfdrivers is statically initialized. */
  200         for (i = 0; cfdriver_list_initial[i] != NULL; i++) {
  201                 if (config_cfdriver_attach(cfdriver_list_initial[i]) != 0)
  202                         panic("configure: duplicate `%s' drivers",
  203                             cfdriver_list_initial[i]->cd_name);
  204         }
  205 
  206         for (cfai = &cfattachinit[0]; cfai->cfai_name != NULL; cfai++) {
  207                 for (j = 0; cfai->cfai_list[j] != NULL; j++) {
  208                         if (config_cfattach_attach(cfai->cfai_name,
  209                                                    cfai->cfai_list[j]) != 0)
  210                                 panic("configure: duplicate `%s' attachment "
  211                                     "of `%s' driver",
  212                                     cfai->cfai_list[j]->ca_name,
  213                                     cfai->cfai_name);
  214                 }
  215         }
  216 
  217         TAILQ_INIT(&allcftables);
  218         initcftable.ct_cfdata = cfdata;
  219         TAILQ_INSERT_TAIL(&allcftables, &initcftable, ct_list);
  220 
  221         TAILQ_INIT(&deferred_config_queue);
  222         TAILQ_INIT(&interrupt_config_queue);
  223         TAILQ_INIT(&config_finalize_list);
  224         TAILQ_INIT(&alldevs);
  225 
  226         config_initialized = 1;
  227 }
  228 
  229 /*
  230  * Configure the system's hardware.
  231  */
  232 void
  233 configure(void)
  234 {
  235         int errcnt;
  236 
  237         /* Initialize data structures. */
  238         config_init();
  239 
  240 #ifdef USERCONF
  241         if (boothowto & RB_USERCONF)
  242                 user_config();
  243 #endif
  244 
  245         if ((boothowto & (AB_SILENT|AB_VERBOSE)) == AB_SILENT) {
  246                 config_do_twiddle = 1;
  247                 printf_nolog("Detecting hardware...");
  248         }
  249 
  250         /*
  251          * Do the machine-dependent portion of autoconfiguration.  This
  252          * sets the configuration machinery here in motion by "finding"
  253          * the root bus.  When this function returns, we expect interrupts
  254          * to be enabled.
  255          */
  256         cpu_configure();
  257 
  258         /*
  259          * Now that we've found all the hardware, start the real time
  260          * and statistics clocks.
  261          */
  262         initclocks();
  263 
  264         cold = 0;       /* clocks are running, we're warm now! */
  265 
  266         /*
  267          * Now callback to finish configuration for devices which want
  268          * to do this once interrupts are enabled.
  269          */
  270         config_process_deferred(&interrupt_config_queue, NULL);
  271 
  272         errcnt = aprint_get_error_count();
  273         if ((boothowto & (AB_QUIET|AB_SILENT)) != 0 &&
  274             (boothowto & AB_VERBOSE) == 0) {
  275                 if (config_do_twiddle) {
  276                         config_do_twiddle = 0;
  277                         printf_nolog("done.\n");
  278                 }
  279                 if (errcnt != 0) {
  280                         printf("WARNING: %d error%s while detecting hardware; "
  281                             "check system log.\n", errcnt,
  282                             errcnt == 1 ? "" : "s");
  283                 }
  284         }
  285 }
  286 
  287 /*
  288  * Add a cfdriver to the system.
  289  */
  290 int
  291 config_cfdriver_attach(struct cfdriver *cd)
  292 {
  293         struct cfdriver *lcd;
  294 
  295         /* Make sure this driver isn't already in the system. */
  296         LIST_FOREACH(lcd, &allcfdrivers, cd_list) {
  297                 if (STREQ(lcd->cd_name, cd->cd_name))
  298                         return (EEXIST);
  299         }
  300 
  301         LIST_INIT(&cd->cd_attach);
  302         LIST_INSERT_HEAD(&allcfdrivers, cd, cd_list);
  303 
  304         return (0);
  305 }
  306 
  307 /*
  308  * Remove a cfdriver from the system.
  309  */
  310 int
  311 config_cfdriver_detach(struct cfdriver *cd)
  312 {
  313         int i;
  314 
  315         /* Make sure there are no active instances. */
  316         for (i = 0; i < cd->cd_ndevs; i++) {
  317                 if (cd->cd_devs[i] != NULL)
  318                         return (EBUSY);
  319         }
  320 
  321         /* ...and no attachments loaded. */
  322         if (LIST_EMPTY(&cd->cd_attach) == 0)
  323                 return (EBUSY);
  324 
  325         LIST_REMOVE(cd, cd_list);
  326 
  327         KASSERT(cd->cd_devs == NULL);
  328 
  329         return (0);
  330 }
  331 
  332 /*
  333  * Look up a cfdriver by name.
  334  */
  335 struct cfdriver *
  336 config_cfdriver_lookup(const char *name)
  337 {
  338         struct cfdriver *cd;
  339 
  340         LIST_FOREACH(cd, &allcfdrivers, cd_list) {
  341                 if (STREQ(cd->cd_name, name))
  342                         return (cd);
  343         }
  344 
  345         return (NULL);
  346 }
  347 
  348 /*
  349  * Add a cfattach to the specified driver.
  350  */
  351 int
  352 config_cfattach_attach(const char *driver, struct cfattach *ca)
  353 {
  354         struct cfattach *lca;
  355         struct cfdriver *cd;
  356 
  357         cd = config_cfdriver_lookup(driver);
  358         if (cd == NULL)
  359                 return (ESRCH);
  360 
  361         /* Make sure this attachment isn't already on this driver. */
  362         LIST_FOREACH(lca, &cd->cd_attach, ca_list) {
  363                 if (STREQ(lca->ca_name, ca->ca_name))
  364                         return (EEXIST);
  365         }
  366 
  367         LIST_INSERT_HEAD(&cd->cd_attach, ca, ca_list);
  368 
  369         return (0);
  370 }
  371 
  372 /*
  373  * Remove a cfattach from the specified driver.
  374  */
  375 int
  376 config_cfattach_detach(const char *driver, struct cfattach *ca)
  377 {
  378         struct cfdriver *cd;
  379         device_t dev;
  380         int i;
  381 
  382         cd = config_cfdriver_lookup(driver);
  383         if (cd == NULL)
  384                 return (ESRCH);
  385 
  386         /* Make sure there are no active instances. */
  387         for (i = 0; i < cd->cd_ndevs; i++) {
  388                 if ((dev = cd->cd_devs[i]) == NULL)
  389                         continue;
  390                 if (dev->dv_cfattach == ca)
  391                         return (EBUSY);
  392         }
  393 
  394         LIST_REMOVE(ca, ca_list);
  395 
  396         return (0);
  397 }
  398 
  399 /*
  400  * Look up a cfattach by name.
  401  */
  402 static struct cfattach *
  403 config_cfattach_lookup_cd(struct cfdriver *cd, const char *atname)
  404 {
  405         struct cfattach *ca;
  406 
  407         LIST_FOREACH(ca, &cd->cd_attach, ca_list) {
  408                 if (STREQ(ca->ca_name, atname))
  409                         return (ca);
  410         }
  411 
  412         return (NULL);
  413 }
  414 
  415 /*
  416  * Look up a cfattach by driver/attachment name.
  417  */
  418 struct cfattach *
  419 config_cfattach_lookup(const char *name, const char *atname)
  420 {
  421         struct cfdriver *cd;
  422 
  423         cd = config_cfdriver_lookup(name);
  424         if (cd == NULL)
  425                 return (NULL);
  426 
  427         return (config_cfattach_lookup_cd(cd, atname));
  428 }
  429 
  430 /*
  431  * Apply the matching function and choose the best.  This is used
  432  * a few times and we want to keep the code small.
  433  */
  434 static void
  435 mapply(struct matchinfo *m, cfdata_t cf)
  436 {
  437         int pri;
  438 
  439         if (m->fn != NULL) {
  440                 pri = (*m->fn)(m->parent, cf, m->locs, m->aux);
  441         } else {
  442                 pri = config_match(m->parent, cf, m->aux);
  443         }
  444         if (pri > m->pri) {
  445                 m->match = cf;
  446                 m->pri = pri;
  447         }
  448 }
  449 
  450 int
  451 config_stdsubmatch(device_t parent, cfdata_t cf, const int *locs, void *aux)
  452 {
  453         const struct cfiattrdata *ci;
  454         const struct cflocdesc *cl;
  455         int nlocs, i;
  456 
  457         ci = cfiattr_lookup(cf->cf_pspec->cfp_iattr, parent->dv_cfdriver);
  458         KASSERT(ci);
  459         nlocs = ci->ci_loclen;
  460         for (i = 0; i < nlocs; i++) {
  461                 cl = &ci->ci_locdesc[i];
  462                 /* !cld_defaultstr means no default value */
  463                 if ((!(cl->cld_defaultstr)
  464                      || (cf->cf_loc[i] != cl->cld_default))
  465                     && cf->cf_loc[i] != locs[i])
  466                         return (0);
  467         }
  468 
  469         return (config_match(parent, cf, aux));
  470 }
  471 
  472 /*
  473  * Helper function: check whether the driver supports the interface attribute
  474  * and return its descriptor structure.
  475  */
  476 static const struct cfiattrdata *
  477 cfdriver_get_iattr(const struct cfdriver *cd, const char *ia)
  478 {
  479         const struct cfiattrdata * const *cpp;
  480 
  481         if (cd->cd_attrs == NULL)
  482                 return (0);
  483 
  484         for (cpp = cd->cd_attrs; *cpp; cpp++) {
  485                 if (STREQ((*cpp)->ci_name, ia)) {
  486                         /* Match. */
  487                         return (*cpp);
  488                 }
  489         }
  490         return (0);
  491 }
  492 
  493 /*
  494  * Lookup an interface attribute description by name.
  495  * If the driver is given, consider only its supported attributes.
  496  */
  497 const struct cfiattrdata *
  498 cfiattr_lookup(const char *name, const struct cfdriver *cd)
  499 {
  500         const struct cfdriver *d;
  501         const struct cfiattrdata *ia;
  502 
  503         if (cd)
  504                 return (cfdriver_get_iattr(cd, name));
  505 
  506         LIST_FOREACH(d, &allcfdrivers, cd_list) {
  507                 ia = cfdriver_get_iattr(d, name);
  508                 if (ia)
  509                         return (ia);
  510         }
  511         return (0);
  512 }
  513 
  514 /*
  515  * Determine if `parent' is a potential parent for a device spec based
  516  * on `cfp'.
  517  */
  518 static int
  519 cfparent_match(const device_t parent, const struct cfparent *cfp)
  520 {
  521         struct cfdriver *pcd;
  522 
  523         /* We don't match root nodes here. */
  524         if (cfp == NULL)
  525                 return (0);
  526 
  527         pcd = parent->dv_cfdriver;
  528         KASSERT(pcd != NULL);
  529 
  530         /*
  531          * First, ensure this parent has the correct interface
  532          * attribute.
  533          */
  534         if (!cfdriver_get_iattr(pcd, cfp->cfp_iattr))
  535                 return (0);
  536 
  537         /*
  538          * If no specific parent device instance was specified (i.e.
  539          * we're attaching to the attribute only), we're done!
  540          */
  541         if (cfp->cfp_parent == NULL)
  542                 return (1);
  543 
  544         /*
  545          * Check the parent device's name.
  546          */
  547         if (STREQ(pcd->cd_name, cfp->cfp_parent) == 0)
  548                 return (0);     /* not the same parent */
  549 
  550         /*
  551          * Make sure the unit number matches.
  552          */
  553         if (cfp->cfp_unit == DVUNIT_ANY ||      /* wildcard */
  554             cfp->cfp_unit == parent->dv_unit)
  555                 return (1);
  556 
  557         /* Unit numbers don't match. */
  558         return (0);
  559 }
  560 
  561 /*
  562  * Helper for config_cfdata_attach(): check all devices whether it could be
  563  * parent any attachment in the config data table passed, and rescan.
  564  */
  565 static void
  566 rescan_with_cfdata(const struct cfdata *cf)
  567 {
  568         device_t d;
  569         const struct cfdata *cf1;
  570 
  571         /*
  572          * "alldevs" is likely longer than an LKM's cfdata, so make it
  573          * the outer loop.
  574          */
  575         TAILQ_FOREACH(d, &alldevs, dv_list) {
  576 
  577                 if (!(d->dv_cfattach->ca_rescan))
  578                         continue;
  579 
  580                 for (cf1 = cf; cf1->cf_name; cf1++) {
  581 
  582                         if (!cfparent_match(d, cf1->cf_pspec))
  583                                 continue;
  584 
  585                         (*d->dv_cfattach->ca_rescan)(d,
  586                                 cf1->cf_pspec->cfp_iattr, cf1->cf_loc);
  587                 }
  588         }
  589 }
  590 
  591 /*
  592  * Attach a supplemental config data table and rescan potential
  593  * parent devices if required.
  594  */
  595 int
  596 config_cfdata_attach(cfdata_t cf, int scannow)
  597 {
  598         struct cftable *ct;
  599 
  600         ct = malloc(sizeof(struct cftable), M_DEVBUF, M_WAITOK);
  601         ct->ct_cfdata = cf;
  602         TAILQ_INSERT_TAIL(&allcftables, ct, ct_list);
  603 
  604         if (scannow)
  605                 rescan_with_cfdata(cf);
  606 
  607         return (0);
  608 }
  609 
  610 /*
  611  * Helper for config_cfdata_detach: check whether a device is
  612  * found through any attachment in the config data table.
  613  */
  614 static int
  615 dev_in_cfdata(const struct device *d, const struct cfdata *cf)
  616 {
  617         const struct cfdata *cf1;
  618 
  619         for (cf1 = cf; cf1->cf_name; cf1++)
  620                 if (d->dv_cfdata == cf1)
  621                         return (1);
  622 
  623         return (0);
  624 }
  625 
  626 /*
  627  * Detach a supplemental config data table. Detach all devices found
  628  * through that table (and thus keeping references to it) before.
  629  */
  630 int
  631 config_cfdata_detach(cfdata_t cf)
  632 {
  633         device_t d;
  634         int error;
  635         struct cftable *ct;
  636 
  637 again:
  638         TAILQ_FOREACH(d, &alldevs, dv_list) {
  639                 if (dev_in_cfdata(d, cf)) {
  640                         error = config_detach(d, 0);
  641                         if (error) {
  642                                 aprint_error("%s: unable to detach instance\n",
  643                                         d->dv_xname);
  644                                 return (error);
  645                         }
  646                         goto again;
  647                 }
  648         }
  649 
  650         TAILQ_FOREACH(ct, &allcftables, ct_list) {
  651                 if (ct->ct_cfdata == cf) {
  652                         TAILQ_REMOVE(&allcftables, ct, ct_list);
  653                         free(ct, M_DEVBUF);
  654                         return (0);
  655                 }
  656         }
  657 
  658         /* not found -- shouldn't happen */
  659         return (EINVAL);
  660 }
  661 
  662 /*
  663  * Invoke the "match" routine for a cfdata entry on behalf of
  664  * an external caller, usually a "submatch" routine.
  665  */
  666 int
  667 config_match(device_t parent, cfdata_t cf, void *aux)
  668 {
  669         struct cfattach *ca;
  670 
  671         ca = config_cfattach_lookup(cf->cf_name, cf->cf_atname);
  672         if (ca == NULL) {
  673                 /* No attachment for this entry, oh well. */
  674                 return (0);
  675         }
  676 
  677         return ((*ca->ca_match)(parent, cf, aux));
  678 }
  679 
  680 /*
  681  * Iterate over all potential children of some device, calling the given
  682  * function (default being the child's match function) for each one.
  683  * Nonzero returns are matches; the highest value returned is considered
  684  * the best match.  Return the `found child' if we got a match, or NULL
  685  * otherwise.  The `aux' pointer is simply passed on through.
  686  *
  687  * Note that this function is designed so that it can be used to apply
  688  * an arbitrary function to all potential children (its return value
  689  * can be ignored).
  690  */
  691 cfdata_t
  692 config_search_loc(cfsubmatch_t fn, device_t parent,
  693                   const char *ifattr, const int *locs, void *aux)
  694 {
  695         struct cftable *ct;
  696         cfdata_t cf;
  697         struct matchinfo m;
  698 
  699         KASSERT(config_initialized);
  700         KASSERT(!ifattr || cfdriver_get_iattr(parent->dv_cfdriver, ifattr));
  701 
  702         m.fn = fn;
  703         m.parent = parent;
  704         m.locs = locs;
  705         m.aux = aux;
  706         m.match = NULL;
  707         m.pri = 0;
  708 
  709         TAILQ_FOREACH(ct, &allcftables, ct_list) {
  710                 for (cf = ct->ct_cfdata; cf->cf_name; cf++) {
  711 
  712                         /* We don't match root nodes here. */
  713                         if (!cf->cf_pspec)
  714                                 continue;
  715 
  716                         /*
  717                          * Skip cf if no longer eligible, otherwise scan
  718                          * through parents for one matching `parent', and
  719                          * try match function.
  720                          */
  721                         if (cf->cf_fstate == FSTATE_FOUND)
  722                                 continue;
  723                         if (cf->cf_fstate == FSTATE_DNOTFOUND ||
  724                             cf->cf_fstate == FSTATE_DSTAR)
  725                                 continue;
  726 
  727                         /*
  728                          * If an interface attribute was specified,
  729                          * consider only children which attach to
  730                          * that attribute.
  731                          */
  732                         if (ifattr && !STREQ(ifattr, cf->cf_pspec->cfp_iattr))
  733                                 continue;
  734 
  735                         if (cfparent_match(parent, cf->cf_pspec))
  736                                 mapply(&m, cf);
  737                 }
  738         }
  739         return (m.match);
  740 }
  741 
  742 cfdata_t
  743 config_search_ia(cfsubmatch_t fn, device_t parent, const char *ifattr,
  744     void *aux)
  745 {
  746 
  747         return (config_search_loc(fn, parent, ifattr, NULL, aux));
  748 }
  749 
  750 /*
  751  * Find the given root device.
  752  * This is much like config_search, but there is no parent.
  753  * Don't bother with multiple cfdata tables; the root node
  754  * must always be in the initial table.
  755  */
  756 cfdata_t
  757 config_rootsearch(cfsubmatch_t fn, const char *rootname, void *aux)
  758 {
  759         cfdata_t cf;
  760         const short *p;
  761         struct matchinfo m;
  762 
  763         m.fn = fn;
  764         m.parent = ROOT;
  765         m.aux = aux;
  766         m.match = NULL;
  767         m.pri = 0;
  768         m.locs = 0;
  769         /*
  770          * Look at root entries for matching name.  We do not bother
  771          * with found-state here since only one root should ever be
  772          * searched (and it must be done first).
  773          */
  774         for (p = cfroots; *p >= 0; p++) {
  775                 cf = &cfdata[*p];
  776                 if (strcmp(cf->cf_name, rootname) == 0)
  777                         mapply(&m, cf);
  778         }
  779         return (m.match);
  780 }
  781 
  782 static const char * const msgs[3] = { "", " not configured\n", " unsupported\n" };
  783 
  784 /*
  785  * The given `aux' argument describes a device that has been found
  786  * on the given parent, but not necessarily configured.  Locate the
  787  * configuration data for that device (using the submatch function
  788  * provided, or using candidates' cd_match configuration driver
  789  * functions) and attach it, and return true.  If the device was
  790  * not configured, call the given `print' function and return 0.
  791  */
  792 device_t
  793 config_found_sm_loc(device_t parent,
  794                 const char *ifattr, const int *locs, void *aux,
  795                 cfprint_t print, cfsubmatch_t submatch)
  796 {
  797         cfdata_t cf;
  798 
  799 #if defined(SPLASHSCREEN) && defined(SPLASHSCREEN_PROGRESS)
  800         if (splash_progress_state)
  801                 splash_progress_update(splash_progress_state);
  802 #endif
  803 
  804         if ((cf = config_search_loc(submatch, parent, ifattr, locs, aux)))
  805                 return(config_attach_loc(parent, cf, locs, aux, print));
  806         if (print) {
  807                 if (config_do_twiddle)
  808                         twiddle();
  809                 aprint_normal("%s", msgs[(*print)(aux, parent->dv_xname)]);
  810         }
  811 
  812 #if defined(SPLASHSCREEN) && defined(SPLASHSCREEN_PROGRESS)
  813         if (splash_progress_state)
  814                 splash_progress_update(splash_progress_state);
  815 #endif
  816 
  817         return (NULL);
  818 }
  819 
  820 device_t
  821 config_found_ia(device_t parent, const char *ifattr, void *aux,
  822     cfprint_t print)
  823 {
  824 
  825         return (config_found_sm_loc(parent, ifattr, NULL, aux, print, NULL));
  826 }
  827 
  828 device_t
  829 config_found(device_t parent, void *aux, cfprint_t print)
  830 {
  831 
  832         return (config_found_sm_loc(parent, NULL, NULL, aux, print, NULL));
  833 }
  834 
  835 /*
  836  * As above, but for root devices.
  837  */
  838 device_t
  839 config_rootfound(const char *rootname, void *aux)
  840 {
  841         cfdata_t cf;
  842 
  843         if ((cf = config_rootsearch((cfsubmatch_t)NULL, rootname, aux)) != NULL)
  844                 return (config_attach(ROOT, cf, aux, (cfprint_t)NULL));
  845         aprint_error("root device %s not configured\n", rootname);
  846         return (NULL);
  847 }
  848 
  849 /* just like sprintf(buf, "%d") except that it works from the end */
  850 static char *
  851 number(char *ep, int n)
  852 {
  853 
  854         *--ep = 0;
  855         while (n >= 10) {
  856                 *--ep = (n % 10) + '';
  857                 n /= 10;
  858         }
  859         *--ep = n + '';
  860         return (ep);
  861 }
  862 
  863 /*
  864  * Expand the size of the cd_devs array if necessary.
  865  */
  866 void
  867 config_makeroom(int n, struct cfdriver *cd)
  868 {
  869         int old, new;
  870         void **nsp;
  871 
  872         if (n < cd->cd_ndevs)
  873                 return;
  874 
  875         /*
  876          * Need to expand the array.
  877          */
  878         old = cd->cd_ndevs;
  879         if (old == 0)
  880                 new = 4;
  881         else
  882                 new = old * 2;
  883         while (new <= n)
  884                 new *= 2;
  885         cd->cd_ndevs = new;
  886         nsp = malloc(new * sizeof(void *), M_DEVBUF,
  887             cold ? M_NOWAIT : M_WAITOK);
  888         if (nsp == NULL)
  889                 panic("config_attach: %sing dev array",
  890                     old != 0 ? "expand" : "creat");
  891         memset(nsp + old, 0, (new - old) * sizeof(void *));
  892         if (old != 0) {
  893                 memcpy(nsp, cd->cd_devs, old * sizeof(void *));
  894                 free(cd->cd_devs, M_DEVBUF);
  895         }
  896         cd->cd_devs = nsp;
  897 }
  898 
  899 /*
  900  * Attach a found device.  Allocates memory for device variables.
  901  */
  902 device_t
  903 config_attach_loc(device_t parent, cfdata_t cf,
  904         const int *locs, void *aux, cfprint_t print)
  905 {
  906         device_t dev;
  907         struct cftable *ct;
  908         struct cfdriver *cd;
  909         struct cfattach *ca;
  910         size_t lname, lunit;
  911         const char *xunit;
  912         int myunit;
  913         char num[10];
  914         const struct cfiattrdata *ia;
  915 
  916 #if defined(SPLASHSCREEN) && defined(SPLASHSCREEN_PROGRESS)
  917         if (splash_progress_state)
  918                 splash_progress_update(splash_progress_state);
  919 #endif
  920 
  921         cd = config_cfdriver_lookup(cf->cf_name);
  922         KASSERT(cd != NULL);
  923 
  924         ca = config_cfattach_lookup_cd(cd, cf->cf_atname);
  925         KASSERT(ca != NULL);
  926 
  927         if (ca->ca_devsize < sizeof(struct device))
  928                 panic("config_attach");
  929 
  930 #ifndef __BROKEN_CONFIG_UNIT_USAGE
  931         if (cf->cf_fstate == FSTATE_STAR) {
  932                 for (myunit = cf->cf_unit; myunit < cd->cd_ndevs; myunit++)
  933                         if (cd->cd_devs[myunit] == NULL)
  934                                 break;
  935                 /*
  936                  * myunit is now the unit of the first NULL device pointer,
  937                  * or max(cd->cd_ndevs,cf->cf_unit).
  938                  */
  939         } else {
  940                 myunit = cf->cf_unit;
  941                 KASSERT(cf->cf_fstate == FSTATE_NOTFOUND);
  942                 cf->cf_fstate = FSTATE_FOUND;
  943         }
  944 #else
  945         myunit = cf->cf_unit;
  946         if (cf->cf_fstate == FSTATE_STAR)
  947                 cf->cf_unit++;
  948         else {
  949                 KASSERT(cf->cf_fstate == FSTATE_NOTFOUND);
  950                 cf->cf_fstate = FSTATE_FOUND;
  951         }
  952 #endif /* ! __BROKEN_CONFIG_UNIT_USAGE */
  953 
  954         /* compute length of name and decimal expansion of unit number */
  955         lname = strlen(cd->cd_name);
  956         xunit = number(&num[sizeof(num)], myunit);
  957         lunit = &num[sizeof(num)] - xunit;
  958         if (lname + lunit > sizeof(dev->dv_xname))
  959                 panic("config_attach: device name too long");
  960 
  961         /* get memory for all device vars */
  962         dev = (device_t)malloc(ca->ca_devsize, M_DEVBUF,
  963             cold ? M_NOWAIT : M_WAITOK);
  964         if (!dev)
  965             panic("config_attach: memory allocation for device softc failed");
  966         memset(dev, 0, ca->ca_devsize);
  967         TAILQ_INSERT_TAIL(&alldevs, dev, dv_list);      /* link up */
  968         dev->dv_class = cd->cd_class;
  969         dev->dv_cfdata = cf;
  970         dev->dv_cfdriver = cd;
  971         dev->dv_cfattach = ca;
  972         dev->dv_unit = myunit;
  973         memcpy(dev->dv_xname, cd->cd_name, lname);
  974         memcpy(dev->dv_xname + lname, xunit, lunit);
  975         dev->dv_parent = parent;
  976         dev->dv_flags = DVF_ACTIVE;     /* always initially active */
  977         if (locs) {
  978                 KASSERT(parent); /* no locators at root */
  979                 ia = cfiattr_lookup(cf->cf_pspec->cfp_iattr,
  980                                     parent->dv_cfdriver);
  981                 dev->dv_locators = malloc(ia->ci_loclen * sizeof(int),
  982                                           M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
  983                 memcpy(dev->dv_locators, locs, ia->ci_loclen * sizeof(int));
  984         }
  985         dev->dv_properties = prop_dictionary_create();
  986         KASSERT(dev->dv_properties != NULL);
  987 
  988         if (config_do_twiddle)
  989                 twiddle();
  990         else
  991                 aprint_naive("Found ");
  992         /*
  993          * We want the next two printfs for normal, verbose, and quiet,
  994          * but not silent (in which case, we're twiddling, instead).
  995          */
  996         if (parent == ROOT) {
  997                 aprint_naive("%s (root)", dev->dv_xname);
  998                 aprint_normal("%s (root)", dev->dv_xname);
  999         } else {
 1000                 aprint_naive("%s at %s", dev->dv_xname, parent->dv_xname);
 1001                 aprint_normal("%s at %s", dev->dv_xname, parent->dv_xname);
 1002                 if (print)
 1003                         (void) (*print)(aux, NULL);
 1004         }
 1005 
 1006         /* put this device in the devices array */
 1007         config_makeroom(dev->dv_unit, cd);
 1008         if (cd->cd_devs[dev->dv_unit])
 1009                 panic("config_attach: duplicate %s", dev->dv_xname);
 1010         cd->cd_devs[dev->dv_unit] = dev;
 1011 
 1012         /*
 1013          * Before attaching, clobber any unfound devices that are
 1014          * otherwise identical.
 1015          */
 1016         TAILQ_FOREACH(ct, &allcftables, ct_list) {
 1017                 for (cf = ct->ct_cfdata; cf->cf_name; cf++) {
 1018                         if (STREQ(cf->cf_name, cd->cd_name) &&
 1019                             cf->cf_unit == dev->dv_unit) {
 1020                                 if (cf->cf_fstate == FSTATE_NOTFOUND)
 1021                                         cf->cf_fstate = FSTATE_FOUND;
 1022 #ifdef __BROKEN_CONFIG_UNIT_USAGE
 1023                                 /*
 1024                                  * Bump the unit number on all starred cfdata
 1025                                  * entries for this device.
 1026                                  */
 1027                                 if (cf->cf_fstate == FSTATE_STAR)
 1028                                         cf->cf_unit++;
 1029 #endif /* __BROKEN_CONFIG_UNIT_USAGE */
 1030                         }
 1031                 }
 1032         }
 1033 #ifdef __HAVE_DEVICE_REGISTER
 1034         device_register(dev, aux);
 1035 #endif
 1036 #if defined(SPLASHSCREEN) && defined(SPLASHSCREEN_PROGRESS)
 1037         if (splash_progress_state)
 1038                 splash_progress_update(splash_progress_state);
 1039 #endif
 1040         (*ca->ca_attach)(parent, dev, aux);
 1041 #if defined(SPLASHSCREEN) && defined(SPLASHSCREEN_PROGRESS)
 1042         if (splash_progress_state)
 1043                 splash_progress_update(splash_progress_state);
 1044 #endif
 1045         config_process_deferred(&deferred_config_queue, dev);
 1046         return (dev);
 1047 }
 1048 
 1049 device_t
 1050 config_attach(device_t parent, cfdata_t cf, void *aux, cfprint_t print)
 1051 {
 1052 
 1053         return (config_attach_loc(parent, cf, NULL, aux, print));
 1054 }
 1055 
 1056 /*
 1057  * As above, but for pseudo-devices.  Pseudo-devices attached in this
 1058  * way are silently inserted into the device tree, and their children
 1059  * attached.
 1060  *
 1061  * Note that because pseudo-devices are attached silently, any information
 1062  * the attach routine wishes to print should be prefixed with the device
 1063  * name by the attach routine.
 1064  */
 1065 device_t
 1066 config_attach_pseudo(cfdata_t cf)
 1067 {
 1068         device_t dev;
 1069         struct cfdriver *cd;
 1070         struct cfattach *ca;
 1071         size_t lname, lunit;
 1072         const char *xunit;
 1073         int myunit;
 1074         char num[10];
 1075 
 1076         cd = config_cfdriver_lookup(cf->cf_name);
 1077         if (cd == NULL)
 1078                 return (NULL);
 1079 
 1080         ca = config_cfattach_lookup_cd(cd, cf->cf_atname);
 1081         if (ca == NULL)
 1082                 return (NULL);
 1083 
 1084         if (ca->ca_devsize < sizeof(struct device))
 1085                 panic("config_attach_pseudo");
 1086 
 1087         /*
 1088          * We just ignore cf_fstate, instead doing everything with
 1089          * cf_unit.
 1090          *
 1091          * XXX Should we change this and use FSTATE_NOTFOUND and
 1092          * XXX FSTATE_STAR?
 1093          */
 1094 
 1095         if (cf->cf_unit == DVUNIT_ANY) {
 1096                 for (myunit = 0; myunit < cd->cd_ndevs; myunit++)
 1097                         if (cd->cd_devs[myunit] == NULL)
 1098                                 break;
 1099                 /*
 1100                  * myunit is now the unit of the first NULL device pointer.
 1101                  */
 1102         } else {
 1103                 myunit = cf->cf_unit;
 1104                 if (myunit < cd->cd_ndevs && cd->cd_devs[myunit] != NULL)
 1105                         return (NULL);
 1106         }
 1107 
 1108         /* compute length of name and decimal expansion of unit number */
 1109         lname = strlen(cd->cd_name);
 1110         xunit = number(&num[sizeof(num)], myunit);
 1111         lunit = &num[sizeof(num)] - xunit;
 1112         if (lname + lunit > sizeof(dev->dv_xname))
 1113                 panic("config_attach_pseudo: device name too long");
 1114 
 1115         /* get memory for all device vars */
 1116         dev = (device_t)malloc(ca->ca_devsize, M_DEVBUF,
 1117             cold ? M_NOWAIT : M_WAITOK);
 1118         if (!dev)
 1119                 panic("config_attach_pseudo: memory allocation for device "
 1120                     "softc failed");
 1121         memset(dev, 0, ca->ca_devsize);
 1122         TAILQ_INSERT_TAIL(&alldevs, dev, dv_list);      /* link up */
 1123         dev->dv_class = cd->cd_class;
 1124         dev->dv_cfdata = cf;
 1125         dev->dv_cfdriver = cd;
 1126         dev->dv_cfattach = ca;
 1127         dev->dv_unit = myunit;
 1128         memcpy(dev->dv_xname, cd->cd_name, lname);
 1129         memcpy(dev->dv_xname + lname, xunit, lunit);
 1130         dev->dv_parent = ROOT;
 1131         dev->dv_flags = DVF_ACTIVE;     /* always initially active */
 1132         dev->dv_properties = prop_dictionary_create();
 1133         KASSERT(dev->dv_properties != NULL);
 1134 
 1135         /* put this device in the devices array */
 1136         config_makeroom(dev->dv_unit, cd);
 1137         if (cd->cd_devs[dev->dv_unit])
 1138                 panic("config_attach_pseudo: duplicate %s", dev->dv_xname);
 1139         cd->cd_devs[dev->dv_unit] = dev;
 1140 
 1141 #if 0   /* XXXJRT not yet */
 1142 #ifdef __HAVE_DEVICE_REGISTER
 1143         device_register(dev, NULL);     /* like a root node */
 1144 #endif
 1145 #endif
 1146         (*ca->ca_attach)(ROOT, dev, NULL);
 1147         config_process_deferred(&deferred_config_queue, dev);
 1148         return (dev);
 1149 }
 1150 
 1151 /*
 1152  * Detach a device.  Optionally forced (e.g. because of hardware
 1153  * removal) and quiet.  Returns zero if successful, non-zero
 1154  * (an error code) otherwise.
 1155  *
 1156  * Note that this code wants to be run from a process context, so
 1157  * that the detach can sleep to allow processes which have a device
 1158  * open to run and unwind their stacks.
 1159  */
 1160 int
 1161 config_detach(device_t dev, int flags)
 1162 {
 1163         struct cftable *ct;
 1164         cfdata_t cf;
 1165         const struct cfattach *ca;
 1166         struct cfdriver *cd;
 1167 #ifdef DIAGNOSTIC
 1168         device_t d;
 1169 #endif
 1170         int rv = 0, i;
 1171 
 1172 #ifdef DIAGNOSTIC
 1173         if (dev->dv_cfdata != NULL &&
 1174             dev->dv_cfdata->cf_fstate != FSTATE_FOUND &&
 1175             dev->dv_cfdata->cf_fstate != FSTATE_STAR)
 1176                 panic("config_detach: bad device fstate");
 1177 #endif
 1178         cd = dev->dv_cfdriver;
 1179         KASSERT(cd != NULL);
 1180 
 1181         ca = dev->dv_cfattach;
 1182         KASSERT(ca != NULL);
 1183 
 1184         /*
 1185          * Ensure the device is deactivated.  If the device doesn't
 1186          * have an activation entry point, we allow DVF_ACTIVE to
 1187          * remain set.  Otherwise, if DVF_ACTIVE is still set, the
 1188          * device is busy, and the detach fails.
 1189          */
 1190         if (ca->ca_activate != NULL)
 1191                 rv = config_deactivate(dev);
 1192 
 1193         /*
 1194          * Try to detach the device.  If that's not possible, then
 1195          * we either panic() (for the forced but failed case), or
 1196          * return an error.
 1197          */
 1198         if (rv == 0) {
 1199                 if (ca->ca_detach != NULL)
 1200                         rv = (*ca->ca_detach)(dev, flags);
 1201                 else
 1202                         rv = EOPNOTSUPP;
 1203         }
 1204         if (rv != 0) {
 1205                 if ((flags & DETACH_FORCE) == 0)
 1206                         return (rv);
 1207                 else
 1208                         panic("config_detach: forced detach of %s failed (%d)",
 1209                             dev->dv_xname, rv);
 1210         }
 1211 
 1212         /*
 1213          * The device has now been successfully detached.
 1214          */
 1215 
 1216 #ifdef DIAGNOSTIC
 1217         /*
 1218          * Sanity: If you're successfully detached, you should have no
 1219          * children.  (Note that because children must be attached
 1220          * after parents, we only need to search the latter part of
 1221          * the list.)
 1222          */
 1223         for (d = TAILQ_NEXT(dev, dv_list); d != NULL;
 1224             d = TAILQ_NEXT(d, dv_list)) {
 1225                 if (d->dv_parent == dev) {
 1226                         printf("config_detach: detached device %s"
 1227                             " has children %s\n", dev->dv_xname, d->dv_xname);
 1228                         panic("config_detach");
 1229                 }
 1230         }
 1231 #endif
 1232 
 1233         /* notify the parent that the child is gone */
 1234         if (dev->dv_parent) {
 1235                 device_t p = dev->dv_parent;
 1236                 if (p->dv_cfattach->ca_childdetached)
 1237                         (*p->dv_cfattach->ca_childdetached)(p, dev);
 1238         }
 1239 
 1240         /*
 1241          * Mark cfdata to show that the unit can be reused, if possible.
 1242          */
 1243         TAILQ_FOREACH(ct, &allcftables, ct_list) {
 1244                 for (cf = ct->ct_cfdata; cf->cf_name; cf++) {
 1245                         if (STREQ(cf->cf_name, cd->cd_name)) {
 1246                                 if (cf->cf_fstate == FSTATE_FOUND &&
 1247                                     cf->cf_unit == dev->dv_unit)
 1248                                         cf->cf_fstate = FSTATE_NOTFOUND;
 1249 #ifdef __BROKEN_CONFIG_UNIT_USAGE
 1250                                 /*
 1251                                  * Note that we can only re-use a starred
 1252                                  * unit number if the unit being detached
 1253                                  * had the last assigned unit number.
 1254                                  */
 1255                                 if (cf->cf_fstate == FSTATE_STAR &&
 1256                                     cf->cf_unit == dev->dv_unit + 1)
 1257                                         cf->cf_unit--;
 1258 #endif /* __BROKEN_CONFIG_UNIT_USAGE */
 1259                         }
 1260                 }
 1261         }
 1262 
 1263         /*
 1264          * Unlink from device list.
 1265          */
 1266         TAILQ_REMOVE(&alldevs, dev, dv_list);
 1267 
 1268         /*
 1269          * Remove from cfdriver's array, tell the world (unless it was
 1270          * a pseudo-device), and free softc.
 1271          */
 1272         cd->cd_devs[dev->dv_unit] = NULL;
 1273         if (dev->dv_cfdata != NULL && (flags & DETACH_QUIET) == 0)
 1274                 aprint_normal("%s detached\n", dev->dv_xname);
 1275         if (dev->dv_locators)
 1276                 free(dev->dv_locators, M_DEVBUF);
 1277         KASSERT(dev->dv_properties != NULL);
 1278         prop_object_release(dev->dv_properties);
 1279         free(dev, M_DEVBUF);
 1280 
 1281         /*
 1282          * If the device now has no units in use, deallocate its softc array.
 1283          */
 1284         for (i = 0; i < cd->cd_ndevs; i++)
 1285                 if (cd->cd_devs[i] != NULL)
 1286                         break;
 1287         if (i == cd->cd_ndevs) {                /* nothing found; deallocate */
 1288                 free(cd->cd_devs, M_DEVBUF);
 1289                 cd->cd_devs = NULL;
 1290                 cd->cd_ndevs = 0;
 1291         }
 1292 
 1293         /*
 1294          * Return success.
 1295          */
 1296         return (0);
 1297 }
 1298 
 1299 int
 1300 config_activate(device_t dev)
 1301 {
 1302         const struct cfattach *ca = dev->dv_cfattach;
 1303         int rv = 0, oflags = dev->dv_flags;
 1304 
 1305         if (ca->ca_activate == NULL)
 1306                 return (EOPNOTSUPP);
 1307 
 1308         if ((dev->dv_flags & DVF_ACTIVE) == 0) {
 1309                 dev->dv_flags |= DVF_ACTIVE;
 1310                 rv = (*ca->ca_activate)(dev, DVACT_ACTIVATE);
 1311                 if (rv)
 1312                         dev->dv_flags = oflags;
 1313         }
 1314         return (rv);
 1315 }
 1316 
 1317 int
 1318 config_deactivate(device_t dev)
 1319 {
 1320         const struct cfattach *ca = dev->dv_cfattach;
 1321         int rv = 0, oflags = dev->dv_flags;
 1322 
 1323         if (ca->ca_activate == NULL)
 1324                 return (EOPNOTSUPP);
 1325 
 1326         if (dev->dv_flags & DVF_ACTIVE) {
 1327                 dev->dv_flags &= ~DVF_ACTIVE;
 1328                 rv = (*ca->ca_activate)(dev, DVACT_DEACTIVATE);
 1329                 if (rv)
 1330                         dev->dv_flags = oflags;
 1331         }
 1332         return (rv);
 1333 }
 1334 
 1335 /*
 1336  * Defer the configuration of the specified device until all
 1337  * of its parent's devices have been attached.
 1338  */
 1339 void
 1340 config_defer(device_t dev, void (*func)(device_t))
 1341 {
 1342         struct deferred_config *dc;
 1343 
 1344         if (dev->dv_parent == NULL)
 1345                 panic("config_defer: can't defer config of a root device");
 1346 
 1347 #ifdef DIAGNOSTIC
 1348         for (dc = TAILQ_FIRST(&deferred_config_queue); dc != NULL;
 1349              dc = TAILQ_NEXT(dc, dc_queue)) {
 1350                 if (dc->dc_dev == dev)
 1351                         panic("config_defer: deferred twice");
 1352         }
 1353 #endif
 1354 
 1355         dc = malloc(sizeof(*dc), M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
 1356         if (dc == NULL)
 1357                 panic("config_defer: unable to allocate callback");
 1358 
 1359         dc->dc_dev = dev;
 1360         dc->dc_func = func;
 1361         TAILQ_INSERT_TAIL(&deferred_config_queue, dc, dc_queue);
 1362         config_pending_incr();
 1363 }
 1364 
 1365 /*
 1366  * Defer some autoconfiguration for a device until after interrupts
 1367  * are enabled.
 1368  */
 1369 void
 1370 config_interrupts(device_t dev, void (*func)(device_t))
 1371 {
 1372         struct deferred_config *dc;
 1373 
 1374         /*
 1375          * If interrupts are enabled, callback now.
 1376          */
 1377         if (cold == 0) {
 1378                 (*func)(dev);
 1379                 return;
 1380         }
 1381 
 1382 #ifdef DIAGNOSTIC
 1383         for (dc = TAILQ_FIRST(&interrupt_config_queue); dc != NULL;
 1384              dc = TAILQ_NEXT(dc, dc_queue)) {
 1385                 if (dc->dc_dev == dev)
 1386                         panic("config_interrupts: deferred twice");
 1387         }
 1388 #endif
 1389 
 1390         dc = malloc(sizeof(*dc), M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
 1391         if (dc == NULL)
 1392                 panic("config_interrupts: unable to allocate callback");
 1393 
 1394         dc->dc_dev = dev;
 1395         dc->dc_func = func;
 1396         TAILQ_INSERT_TAIL(&interrupt_config_queue, dc, dc_queue);
 1397         config_pending_incr();
 1398 }
 1399 
 1400 /*
 1401  * Process a deferred configuration queue.
 1402  */
 1403 static void
 1404 config_process_deferred(struct deferred_config_head *queue,
 1405     device_t parent)
 1406 {
 1407         struct deferred_config *dc, *ndc;
 1408 
 1409         for (dc = TAILQ_FIRST(queue); dc != NULL; dc = ndc) {
 1410                 ndc = TAILQ_NEXT(dc, dc_queue);
 1411                 if (parent == NULL || dc->dc_dev->dv_parent == parent) {
 1412                         TAILQ_REMOVE(queue, dc, dc_queue);
 1413                         (*dc->dc_func)(dc->dc_dev);
 1414                         free(dc, M_DEVBUF);
 1415                         config_pending_decr();
 1416                 }
 1417         }
 1418 }
 1419 
 1420 /*
 1421  * Manipulate the config_pending semaphore.
 1422  */
 1423 void
 1424 config_pending_incr(void)
 1425 {
 1426 
 1427         config_pending++;
 1428 }
 1429 
 1430 void
 1431 config_pending_decr(void)
 1432 {
 1433 
 1434 #ifdef DIAGNOSTIC
 1435         if (config_pending == 0)
 1436                 panic("config_pending_decr: config_pending == 0");
 1437 #endif
 1438         config_pending--;
 1439         if (config_pending == 0)
 1440                 wakeup(&config_pending);
 1441 }
 1442 
 1443 /*
 1444  * Register a "finalization" routine.  Finalization routines are
 1445  * called iteratively once all real devices have been found during
 1446  * autoconfiguration, for as long as any one finalizer has done
 1447  * any work.
 1448  */
 1449 int
 1450 config_finalize_register(device_t dev, int (*fn)(device_t))
 1451 {
 1452         struct finalize_hook *f;
 1453 
 1454         /*
 1455          * If finalization has already been done, invoke the
 1456          * callback function now.
 1457          */
 1458         if (config_finalize_done) {
 1459                 while ((*fn)(dev) != 0)
 1460                         /* loop */ ;
 1461         }
 1462 
 1463         /* Ensure this isn't already on the list. */
 1464         TAILQ_FOREACH(f, &config_finalize_list, f_list) {
 1465                 if (f->f_func == fn && f->f_dev == dev)
 1466                         return (EEXIST);
 1467         }
 1468 
 1469         f = malloc(sizeof(*f), M_TEMP, M_WAITOK);
 1470         f->f_func = fn;
 1471         f->f_dev = dev;
 1472         TAILQ_INSERT_TAIL(&config_finalize_list, f, f_list);
 1473 
 1474         return (0);
 1475 }
 1476 
 1477 void
 1478 config_finalize(void)
 1479 {
 1480         struct finalize_hook *f;
 1481         int rv;
 1482 
 1483         /* Run the hooks until none of them does any work. */
 1484         do {
 1485                 rv = 0;
 1486                 TAILQ_FOREACH(f, &config_finalize_list, f_list)
 1487                         rv |= (*f->f_func)(f->f_dev);
 1488         } while (rv != 0);
 1489 
 1490         config_finalize_done = 1;
 1491 
 1492         /* Now free all the hooks. */
 1493         while ((f = TAILQ_FIRST(&config_finalize_list)) != NULL) {
 1494                 TAILQ_REMOVE(&config_finalize_list, f, f_list);
 1495                 free(f, M_TEMP);
 1496         }
 1497 }
 1498 
 1499 /*
 1500  * device_lookup:
 1501  *
 1502  *      Look up a device instance for a given driver.
 1503  */
 1504 void *
 1505 device_lookup(cfdriver_t cd, int unit)
 1506 {
 1507 
 1508         if (unit < 0 || unit >= cd->cd_ndevs)
 1509                 return (NULL);
 1510         
 1511         return (cd->cd_devs[unit]);
 1512 }
 1513 
 1514 /*
 1515  * Accessor functions for the device_t type.
 1516  */
 1517 devclass_t
 1518 device_class(device_t dev)
 1519 {
 1520 
 1521         return (dev->dv_class);
 1522 }
 1523 
 1524 cfdata_t
 1525 device_cfdata(device_t dev)
 1526 {
 1527 
 1528         return (dev->dv_cfdata);
 1529 }
 1530 
 1531 cfdriver_t
 1532 device_cfdriver(device_t dev)
 1533 {
 1534 
 1535         return (dev->dv_cfdriver);
 1536 }
 1537 
 1538 cfattach_t
 1539 device_cfattach(device_t dev)
 1540 {
 1541 
 1542         return (dev->dv_cfattach);
 1543 }
 1544 
 1545 int
 1546 device_unit(device_t dev)
 1547 {
 1548 
 1549         return (dev->dv_unit);
 1550 }
 1551 
 1552 const char *
 1553 device_xname(device_t dev)
 1554 {
 1555 
 1556         return (dev->dv_xname);
 1557 }
 1558 
 1559 device_t
 1560 device_parent(device_t dev)
 1561 {
 1562 
 1563         return (dev->dv_parent);
 1564 }
 1565 
 1566 boolean_t
 1567 device_is_active(device_t dev)
 1568 {
 1569 
 1570         return ((dev->dv_flags & DVF_ACTIVE) != 0);
 1571 }
 1572 
 1573 int
 1574 device_locator(device_t dev, u_int locnum)
 1575 {
 1576 
 1577         KASSERT(dev->dv_locators != NULL);
 1578         return (dev->dv_locators[locnum]);
 1579 }
 1580 
 1581 void *
 1582 device_private(device_t dev)
 1583 {
 1584 
 1585         /*
 1586          * For now, at least, "struct device" is the first thing in
 1587          * the driver's private data.  So, we just return ourselves.
 1588          */
 1589         return (dev);
 1590 }
 1591 
 1592 prop_dictionary_t
 1593 device_properties(device_t dev)
 1594 {
 1595 
 1596         return (dev->dv_properties);
 1597 }
 1598 
 1599 /*
 1600  * device_is_a:
 1601  *
 1602  *      Returns true if the device is an instance of the specified
 1603  *      driver.
 1604  */
 1605 boolean_t
 1606 device_is_a(device_t dev, const char *dname)
 1607 {
 1608 
 1609         return (strcmp(dev->dv_cfdriver->cd_name, dname) == 0);
 1610 }

Cache object: feed1621674c023f45ef119665b8f65f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.