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.163.4.3 2010/11/20 17:41:27 riz 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.163.4.3 2010/11/20 17:41:27 riz Exp $");
   81 
   82 #include "opt_ddb.h"
   83 #include "drvctl.h"
   84 
   85 #include <sys/param.h>
   86 #include <sys/device.h>
   87 #include <sys/disklabel.h>
   88 #include <sys/conf.h>
   89 #include <sys/kauth.h>
   90 #include <sys/malloc.h>
   91 #include <sys/kmem.h>
   92 #include <sys/systm.h>
   93 #include <sys/kernel.h>
   94 #include <sys/errno.h>
   95 #include <sys/proc.h>
   96 #include <sys/reboot.h>
   97 #include <sys/kthread.h>
   98 #include <sys/buf.h>
   99 #include <sys/dirent.h>
  100 #include <sys/vnode.h>
  101 #include <sys/mount.h>
  102 #include <sys/namei.h>
  103 #include <sys/unistd.h>
  104 #include <sys/fcntl.h>
  105 #include <sys/lockf.h>
  106 #include <sys/callout.h>
  107 #include <sys/mutex.h>
  108 #include <sys/condvar.h>
  109 #include <sys/devmon.h>
  110 #include <sys/cpu.h>
  111 
  112 #include <sys/disk.h>
  113 
  114 #include <machine/limits.h>
  115 
  116 #include "opt_userconf.h"
  117 #ifdef USERCONF
  118 #include <sys/userconf.h>
  119 #endif
  120 
  121 #ifdef __i386__
  122 #include "opt_splash.h"
  123 #if defined(SPLASHSCREEN) && defined(SPLASHSCREEN_PROGRESS)
  124 #include <dev/splash/splash.h>
  125 extern struct splash_progress *splash_progress_state;
  126 #endif
  127 #endif
  128 
  129 /*
  130  * Autoconfiguration subroutines.
  131  */
  132 
  133 typedef struct pmf_private {
  134         int             pp_nwait;
  135         int             pp_nlock;
  136         lwp_t           *pp_holder;
  137         kmutex_t        pp_mtx;
  138         kcondvar_t      pp_cv;
  139 } pmf_private_t;
  140 
  141 /*
  142  * ioconf.c exports exactly two names: cfdata and cfroots.  All system
  143  * devices and drivers are found via these tables.
  144  */
  145 extern struct cfdata cfdata[];
  146 extern const short cfroots[];
  147 
  148 /*
  149  * List of all cfdriver structures.  We use this to detect duplicates
  150  * when other cfdrivers are loaded.
  151  */
  152 struct cfdriverlist allcfdrivers = LIST_HEAD_INITIALIZER(&allcfdrivers);
  153 extern struct cfdriver * const cfdriver_list_initial[];
  154 
  155 /*
  156  * Initial list of cfattach's.
  157  */
  158 extern const struct cfattachinit cfattachinit[];
  159 
  160 /*
  161  * List of cfdata tables.  We always have one such list -- the one
  162  * built statically when the kernel was configured.
  163  */
  164 struct cftablelist allcftables = TAILQ_HEAD_INITIALIZER(allcftables);
  165 static struct cftable initcftable;
  166 
  167 #define ROOT ((device_t)NULL)
  168 
  169 struct matchinfo {
  170         cfsubmatch_t fn;
  171         struct  device *parent;
  172         const int *locs;
  173         void    *aux;
  174         struct  cfdata *match;
  175         int     pri;
  176 };
  177 
  178 static char *number(char *, int);
  179 static void mapply(struct matchinfo *, cfdata_t);
  180 static device_t config_devalloc(const device_t, const cfdata_t, const int *);
  181 static void config_devdealloc(device_t);
  182 static void config_makeroom(int, struct cfdriver *);
  183 static void config_devlink(device_t);
  184 static void config_devunlink(device_t);
  185 
  186 static void pmflock_debug(device_t, const char *, int);
  187 static void pmflock_debug_with_flags(device_t, const char *, int PMF_FN_PROTO);
  188 
  189 static device_t deviter_next1(deviter_t *);
  190 static void deviter_reinit(deviter_t *);
  191 
  192 struct deferred_config {
  193         TAILQ_ENTRY(deferred_config) dc_queue;
  194         device_t dc_dev;
  195         void (*dc_func)(device_t);
  196 };
  197 
  198 TAILQ_HEAD(deferred_config_head, deferred_config);
  199 
  200 struct deferred_config_head deferred_config_queue =
  201         TAILQ_HEAD_INITIALIZER(deferred_config_queue);
  202 struct deferred_config_head interrupt_config_queue =
  203         TAILQ_HEAD_INITIALIZER(interrupt_config_queue);
  204 int interrupt_config_threads = 8;
  205 
  206 static void config_process_deferred(struct deferred_config_head *, device_t);
  207 
  208 /* Hooks to finalize configuration once all real devices have been found. */
  209 struct finalize_hook {
  210         TAILQ_ENTRY(finalize_hook) f_list;
  211         int (*f_func)(device_t);
  212         device_t f_dev;
  213 };
  214 static TAILQ_HEAD(, finalize_hook) config_finalize_list =
  215         TAILQ_HEAD_INITIALIZER(config_finalize_list);
  216 static int config_finalize_done;
  217 
  218 /* list of all devices */
  219 struct devicelist alldevs = TAILQ_HEAD_INITIALIZER(alldevs);
  220 kcondvar_t alldevs_cv;
  221 kmutex_t alldevs_mtx;
  222 static int alldevs_nread = 0;
  223 static int alldevs_nwrite = 0;
  224 static lwp_t *alldevs_writer = NULL;
  225 
  226 static int config_pending;              /* semaphore for mountroot */
  227 static kmutex_t config_misc_lock;
  228 static kcondvar_t config_misc_cv;
  229 
  230 #define STREQ(s1, s2)                   \
  231         (*(s1) == *(s2) && strcmp((s1), (s2)) == 0)
  232 
  233 static int config_initialized;          /* config_init() has been called. */
  234 
  235 static int config_do_twiddle;
  236 
  237 struct vnode *
  238 opendisk(struct device *dv)
  239 {
  240         int bmajor, bminor;
  241         struct vnode *tmpvn;
  242         int error;
  243         dev_t dev;
  244         
  245         /*
  246          * Lookup major number for disk block device.
  247          */
  248         bmajor = devsw_name2blk(device_xname(dv), NULL, 0);
  249         if (bmajor == -1)
  250                 return NULL;
  251         
  252         bminor = minor(device_unit(dv));
  253         /*
  254          * Fake a temporary vnode for the disk, open it, and read
  255          * and hash the sectors.
  256          */
  257         dev = device_is_a(dv, "dk") ? makedev(bmajor, bminor) :
  258             MAKEDISKDEV(bmajor, bminor, RAW_PART);
  259         if (bdevvp(dev, &tmpvn))
  260                 panic("%s: can't alloc vnode for %s", __func__,
  261                     device_xname(dv));
  262         error = VOP_OPEN(tmpvn, FREAD, NOCRED);
  263         if (error) {
  264 #ifndef DEBUG
  265                 /*
  266                  * Ignore errors caused by missing device, partition,
  267                  * or medium.
  268                  */
  269                 if (error != ENXIO && error != ENODEV)
  270 #endif
  271                         printf("%s: can't open dev %s (%d)\n",
  272                             __func__, device_xname(dv), error);
  273                 vput(tmpvn);
  274                 return NULL;
  275         }
  276 
  277         return tmpvn;
  278 }
  279 
  280 int
  281 config_handle_wedges(struct device *dv, int par)
  282 {
  283         struct dkwedge_list wl;
  284         struct dkwedge_info *wi;
  285         struct vnode *vn;
  286         char diskname[16];
  287         int i, error;
  288 
  289         if ((vn = opendisk(dv)) == NULL)
  290                 return -1;
  291 
  292         wl.dkwl_bufsize = sizeof(*wi) * 16;
  293         wl.dkwl_buf = wi = malloc(wl.dkwl_bufsize, M_TEMP, M_WAITOK);
  294 
  295         error = VOP_IOCTL(vn, DIOCLWEDGES, &wl, FREAD, NOCRED);
  296         VOP_CLOSE(vn, FREAD, NOCRED);
  297         vput(vn);
  298         if (error) {
  299 #ifdef DEBUG_WEDGE
  300                 printf("%s: List wedges returned %d\n",
  301                     device_xname(dv), error);
  302 #endif
  303                 free(wi, M_TEMP);
  304                 return -1;
  305         }
  306 
  307 #ifdef DEBUG_WEDGE
  308         printf("%s: Returned %u(%u) wedges\n", device_xname(dv),
  309             wl.dkwl_nwedges, wl.dkwl_ncopied);
  310 #endif
  311         snprintf(diskname, sizeof(diskname), "%s%c", device_xname(dv),
  312             par + 'a');
  313 
  314         for (i = 0; i < wl.dkwl_ncopied; i++) {
  315 #ifdef DEBUG_WEDGE
  316                 printf("%s: Looking for %s in %s\n", 
  317                     device_xname(dv), diskname, wi[i].dkw_wname);
  318 #endif
  319                 if (strcmp(wi[i].dkw_wname, diskname) == 0)
  320                         break;
  321         }
  322 
  323         if (i == wl.dkwl_ncopied) {
  324 #ifdef DEBUG_WEDGE
  325                 printf("%s: Cannot find wedge with parent %s\n",
  326                     device_xname(dv), diskname);
  327 #endif
  328                 free(wi, M_TEMP);
  329                 return -1;
  330         }
  331 
  332 #ifdef DEBUG_WEDGE
  333         printf("%s: Setting boot wedge %s (%s) at %llu %llu\n", 
  334                 device_xname(dv), wi[i].dkw_devname, wi[i].dkw_wname,
  335                 (unsigned long long)wi[i].dkw_offset,
  336                 (unsigned long long)wi[i].dkw_size);
  337 #endif
  338         dkwedge_set_bootwedge(dv, wi[i].dkw_offset, wi[i].dkw_size);
  339         free(wi, M_TEMP);
  340         return 0;
  341 }
  342 
  343 /*
  344  * Initialize the autoconfiguration data structures.  Normally this
  345  * is done by configure(), but some platforms need to do this very
  346  * early (to e.g. initialize the console).
  347  */
  348 void
  349 config_init(void)
  350 {
  351         const struct cfattachinit *cfai;
  352         int i, j;
  353 
  354         if (config_initialized)
  355                 return;
  356 
  357         mutex_init(&alldevs_mtx, MUTEX_DEFAULT, IPL_NONE);
  358         cv_init(&alldevs_cv, "alldevs");
  359 
  360         mutex_init(&config_misc_lock, MUTEX_DEFAULT, IPL_NONE);
  361         cv_init(&config_misc_cv, "cfgmisc");
  362 
  363         /* allcfdrivers is statically initialized. */
  364         for (i = 0; cfdriver_list_initial[i] != NULL; i++) {
  365                 if (config_cfdriver_attach(cfdriver_list_initial[i]) != 0)
  366                         panic("configure: duplicate `%s' drivers",
  367                             cfdriver_list_initial[i]->cd_name);
  368         }
  369 
  370         for (cfai = &cfattachinit[0]; cfai->cfai_name != NULL; cfai++) {
  371                 for (j = 0; cfai->cfai_list[j] != NULL; j++) {
  372                         if (config_cfattach_attach(cfai->cfai_name,
  373                                                    cfai->cfai_list[j]) != 0)
  374                                 panic("configure: duplicate `%s' attachment "
  375                                     "of `%s' driver",
  376                                     cfai->cfai_list[j]->ca_name,
  377                                     cfai->cfai_name);
  378                 }
  379         }
  380 
  381         initcftable.ct_cfdata = cfdata;
  382         TAILQ_INSERT_TAIL(&allcftables, &initcftable, ct_list);
  383 
  384         config_initialized = 1;
  385 }
  386 
  387 void
  388 config_deferred(device_t dev)
  389 {
  390         config_process_deferred(&deferred_config_queue, dev);
  391         config_process_deferred(&interrupt_config_queue, dev);
  392 }
  393 
  394 static void
  395 config_interrupts_thread(void *cookie)
  396 {
  397         struct deferred_config *dc;
  398 
  399         while ((dc = TAILQ_FIRST(&interrupt_config_queue)) != NULL) {
  400                 TAILQ_REMOVE(&interrupt_config_queue, dc, dc_queue);
  401                 (*dc->dc_func)(dc->dc_dev);
  402                 kmem_free(dc, sizeof(*dc));
  403                 config_pending_decr();
  404         }
  405         kthread_exit(0);
  406 }
  407 
  408 /*
  409  * Configure the system's hardware.
  410  */
  411 void
  412 configure(void)
  413 {
  414         /* Initialize data structures. */
  415         config_init();
  416         pmf_init();
  417 #if NDRVCTL > 0
  418         drvctl_init();
  419 #endif
  420 
  421 #ifdef USERCONF
  422         if (boothowto & RB_USERCONF)
  423                 user_config();
  424 #endif
  425 
  426         if ((boothowto & (AB_SILENT|AB_VERBOSE)) == AB_SILENT) {
  427                 config_do_twiddle = 1;
  428                 printf_nolog("Detecting hardware...");
  429         }
  430 
  431         /*
  432          * Do the machine-dependent portion of autoconfiguration.  This
  433          * sets the configuration machinery here in motion by "finding"
  434          * the root bus.  When this function returns, we expect interrupts
  435          * to be enabled.
  436          */
  437         cpu_configure();
  438 }
  439 
  440 void
  441 configure2(void)
  442 {
  443         CPU_INFO_ITERATOR cii;
  444         struct cpu_info *ci;
  445         int i, s;
  446 
  447         /*
  448          * Now that we've found all the hardware, start the real time
  449          * and statistics clocks.
  450          */
  451         initclocks();
  452 
  453         cold = 0;       /* clocks are running, we're warm now! */
  454         s = splsched();
  455         curcpu()->ci_schedstate.spc_flags |= SPCF_RUNNING;
  456         splx(s);
  457 
  458         /* Boot the secondary processors. */
  459         for (CPU_INFO_FOREACH(cii, ci)) {
  460                 uvm_cpu_attach(ci);
  461         }
  462         mp_online = true;
  463 #if defined(MULTIPROCESSOR)
  464         cpu_boot_secondary_processors();
  465 #endif
  466 
  467         /* Setup the runqueues and scheduler. */
  468         runq_init();
  469         sched_init();
  470 
  471         /*
  472          * Create threads to call back and finish configuration for
  473          * devices that want interrupts enabled.
  474          */
  475         for (i = 0; i < interrupt_config_threads; i++) {
  476                 (void)kthread_create(PRI_NONE, 0, NULL,
  477                     config_interrupts_thread, NULL, NULL, "config");
  478         }
  479 
  480         /* Get the threads going and into any sleeps before continuing. */
  481         yield();
  482 }
  483 
  484 /*
  485  * Announce device attach/detach to userland listeners.
  486  */
  487 static void
  488 devmon_report_device(device_t dev, bool isattach)
  489 {
  490 #if NDRVCTL > 0
  491         prop_dictionary_t ev;
  492         const char *parent;
  493         const char *what;
  494         device_t pdev = device_parent(dev);
  495 
  496         ev = prop_dictionary_create();
  497         if (ev == NULL)
  498                 return;
  499 
  500         what = (isattach ? "device-attach" : "device-detach");
  501         parent = (pdev == NULL ? "root" : device_xname(pdev));
  502         if (!prop_dictionary_set_cstring(ev, "device", device_xname(dev)) ||
  503             !prop_dictionary_set_cstring(ev, "parent", parent)) {
  504                 prop_object_release(ev);
  505                 return;
  506         }
  507 
  508         devmon_insert(what, ev);
  509 #endif
  510 }
  511 
  512 /*
  513  * Add a cfdriver to the system.
  514  */
  515 int
  516 config_cfdriver_attach(struct cfdriver *cd)
  517 {
  518         struct cfdriver *lcd;
  519 
  520         /* Make sure this driver isn't already in the system. */
  521         LIST_FOREACH(lcd, &allcfdrivers, cd_list) {
  522                 if (STREQ(lcd->cd_name, cd->cd_name))
  523                         return (EEXIST);
  524         }
  525 
  526         LIST_INIT(&cd->cd_attach);
  527         LIST_INSERT_HEAD(&allcfdrivers, cd, cd_list);
  528 
  529         return (0);
  530 }
  531 
  532 /*
  533  * Remove a cfdriver from the system.
  534  */
  535 int
  536 config_cfdriver_detach(struct cfdriver *cd)
  537 {
  538         int i;
  539 
  540         /* Make sure there are no active instances. */
  541         for (i = 0; i < cd->cd_ndevs; i++) {
  542                 if (cd->cd_devs[i] != NULL)
  543                         return (EBUSY);
  544         }
  545 
  546         /* ...and no attachments loaded. */
  547         if (LIST_EMPTY(&cd->cd_attach) == 0)
  548                 return (EBUSY);
  549 
  550         LIST_REMOVE(cd, cd_list);
  551 
  552         KASSERT(cd->cd_devs == NULL);
  553 
  554         return (0);
  555 }
  556 
  557 /*
  558  * Look up a cfdriver by name.
  559  */
  560 struct cfdriver *
  561 config_cfdriver_lookup(const char *name)
  562 {
  563         struct cfdriver *cd;
  564 
  565         LIST_FOREACH(cd, &allcfdrivers, cd_list) {
  566                 if (STREQ(cd->cd_name, name))
  567                         return (cd);
  568         }
  569 
  570         return (NULL);
  571 }
  572 
  573 /*
  574  * Add a cfattach to the specified driver.
  575  */
  576 int
  577 config_cfattach_attach(const char *driver, struct cfattach *ca)
  578 {
  579         struct cfattach *lca;
  580         struct cfdriver *cd;
  581 
  582         cd = config_cfdriver_lookup(driver);
  583         if (cd == NULL)
  584                 return (ESRCH);
  585 
  586         /* Make sure this attachment isn't already on this driver. */
  587         LIST_FOREACH(lca, &cd->cd_attach, ca_list) {
  588                 if (STREQ(lca->ca_name, ca->ca_name))
  589                         return (EEXIST);
  590         }
  591 
  592         LIST_INSERT_HEAD(&cd->cd_attach, ca, ca_list);
  593 
  594         return (0);
  595 }
  596 
  597 /*
  598  * Remove a cfattach from the specified driver.
  599  */
  600 int
  601 config_cfattach_detach(const char *driver, struct cfattach *ca)
  602 {
  603         struct cfdriver *cd;
  604         device_t dev;
  605         int i;
  606 
  607         cd = config_cfdriver_lookup(driver);
  608         if (cd == NULL)
  609                 return (ESRCH);
  610 
  611         /* Make sure there are no active instances. */
  612         for (i = 0; i < cd->cd_ndevs; i++) {
  613                 if ((dev = cd->cd_devs[i]) == NULL)
  614                         continue;
  615                 if (dev->dv_cfattach == ca)
  616                         return (EBUSY);
  617         }
  618 
  619         LIST_REMOVE(ca, ca_list);
  620 
  621         return (0);
  622 }
  623 
  624 /*
  625  * Look up a cfattach by name.
  626  */
  627 static struct cfattach *
  628 config_cfattach_lookup_cd(struct cfdriver *cd, const char *atname)
  629 {
  630         struct cfattach *ca;
  631 
  632         LIST_FOREACH(ca, &cd->cd_attach, ca_list) {
  633                 if (STREQ(ca->ca_name, atname))
  634                         return (ca);
  635         }
  636 
  637         return (NULL);
  638 }
  639 
  640 /*
  641  * Look up a cfattach by driver/attachment name.
  642  */
  643 struct cfattach *
  644 config_cfattach_lookup(const char *name, const char *atname)
  645 {
  646         struct cfdriver *cd;
  647 
  648         cd = config_cfdriver_lookup(name);
  649         if (cd == NULL)
  650                 return (NULL);
  651 
  652         return (config_cfattach_lookup_cd(cd, atname));
  653 }
  654 
  655 /*
  656  * Apply the matching function and choose the best.  This is used
  657  * a few times and we want to keep the code small.
  658  */
  659 static void
  660 mapply(struct matchinfo *m, cfdata_t cf)
  661 {
  662         int pri;
  663 
  664         if (m->fn != NULL) {
  665                 pri = (*m->fn)(m->parent, cf, m->locs, m->aux);
  666         } else {
  667                 pri = config_match(m->parent, cf, m->aux);
  668         }
  669         if (pri > m->pri) {
  670                 m->match = cf;
  671                 m->pri = pri;
  672         }
  673 }
  674 
  675 int
  676 config_stdsubmatch(device_t parent, cfdata_t cf, const int *locs, void *aux)
  677 {
  678         const struct cfiattrdata *ci;
  679         const struct cflocdesc *cl;
  680         int nlocs, i;
  681 
  682         ci = cfiattr_lookup(cf->cf_pspec->cfp_iattr, parent->dv_cfdriver);
  683         KASSERT(ci);
  684         nlocs = ci->ci_loclen;
  685         KASSERT(!nlocs || locs);
  686         for (i = 0; i < nlocs; i++) {
  687                 cl = &ci->ci_locdesc[i];
  688                 /* !cld_defaultstr means no default value */
  689                 if ((!(cl->cld_defaultstr)
  690                      || (cf->cf_loc[i] != cl->cld_default))
  691                     && cf->cf_loc[i] != locs[i])
  692                         return (0);
  693         }
  694 
  695         return (config_match(parent, cf, aux));
  696 }
  697 
  698 /*
  699  * Helper function: check whether the driver supports the interface attribute
  700  * and return its descriptor structure.
  701  */
  702 static const struct cfiattrdata *
  703 cfdriver_get_iattr(const struct cfdriver *cd, const char *ia)
  704 {
  705         const struct cfiattrdata * const *cpp;
  706 
  707         if (cd->cd_attrs == NULL)
  708                 return (0);
  709 
  710         for (cpp = cd->cd_attrs; *cpp; cpp++) {
  711                 if (STREQ((*cpp)->ci_name, ia)) {
  712                         /* Match. */
  713                         return (*cpp);
  714                 }
  715         }
  716         return (0);
  717 }
  718 
  719 /*
  720  * Lookup an interface attribute description by name.
  721  * If the driver is given, consider only its supported attributes.
  722  */
  723 const struct cfiattrdata *
  724 cfiattr_lookup(const char *name, const struct cfdriver *cd)
  725 {
  726         const struct cfdriver *d;
  727         const struct cfiattrdata *ia;
  728 
  729         if (cd)
  730                 return (cfdriver_get_iattr(cd, name));
  731 
  732         LIST_FOREACH(d, &allcfdrivers, cd_list) {
  733                 ia = cfdriver_get_iattr(d, name);
  734                 if (ia)
  735                         return (ia);
  736         }
  737         return (0);
  738 }
  739 
  740 /*
  741  * Determine if `parent' is a potential parent for a device spec based
  742  * on `cfp'.
  743  */
  744 static int
  745 cfparent_match(const device_t parent, const struct cfparent *cfp)
  746 {
  747         struct cfdriver *pcd;
  748 
  749         /* We don't match root nodes here. */
  750         if (cfp == NULL)
  751                 return (0);
  752 
  753         pcd = parent->dv_cfdriver;
  754         KASSERT(pcd != NULL);
  755 
  756         /*
  757          * First, ensure this parent has the correct interface
  758          * attribute.
  759          */
  760         if (!cfdriver_get_iattr(pcd, cfp->cfp_iattr))
  761                 return (0);
  762 
  763         /*
  764          * If no specific parent device instance was specified (i.e.
  765          * we're attaching to the attribute only), we're done!
  766          */
  767         if (cfp->cfp_parent == NULL)
  768                 return (1);
  769 
  770         /*
  771          * Check the parent device's name.
  772          */
  773         if (STREQ(pcd->cd_name, cfp->cfp_parent) == 0)
  774                 return (0);     /* not the same parent */
  775 
  776         /*
  777          * Make sure the unit number matches.
  778          */
  779         if (cfp->cfp_unit == DVUNIT_ANY ||      /* wildcard */
  780             cfp->cfp_unit == parent->dv_unit)
  781                 return (1);
  782 
  783         /* Unit numbers don't match. */
  784         return (0);
  785 }
  786 
  787 /*
  788  * Helper for config_cfdata_attach(): check all devices whether it could be
  789  * parent any attachment in the config data table passed, and rescan.
  790  */
  791 static void
  792 rescan_with_cfdata(const struct cfdata *cf)
  793 {
  794         device_t d;
  795         const struct cfdata *cf1;
  796         deviter_t di;
  797   
  798 
  799         /*
  800          * "alldevs" is likely longer than an LKM's cfdata, so make it
  801          * the outer loop.
  802          */
  803         for (d = deviter_first(&di, 0); d != NULL; d = deviter_next(&di)) {
  804 
  805                 if (!(d->dv_cfattach->ca_rescan))
  806                         continue;
  807 
  808                 for (cf1 = cf; cf1->cf_name; cf1++) {
  809 
  810                         if (!cfparent_match(d, cf1->cf_pspec))
  811                                 continue;
  812 
  813                         (*d->dv_cfattach->ca_rescan)(d,
  814                                 cf1->cf_pspec->cfp_iattr, cf1->cf_loc);
  815                 }
  816         }
  817         deviter_release(&di);
  818 }
  819 
  820 /*
  821  * Attach a supplemental config data table and rescan potential
  822  * parent devices if required.
  823  */
  824 int
  825 config_cfdata_attach(cfdata_t cf, int scannow)
  826 {
  827         struct cftable *ct;
  828 
  829         ct = kmem_alloc(sizeof(*ct), KM_SLEEP);
  830         ct->ct_cfdata = cf;
  831         TAILQ_INSERT_TAIL(&allcftables, ct, ct_list);
  832 
  833         if (scannow)
  834                 rescan_with_cfdata(cf);
  835 
  836         return (0);
  837 }
  838 
  839 /*
  840  * Helper for config_cfdata_detach: check whether a device is
  841  * found through any attachment in the config data table.
  842  */
  843 static int
  844 dev_in_cfdata(const struct device *d, const struct cfdata *cf)
  845 {
  846         const struct cfdata *cf1;
  847 
  848         for (cf1 = cf; cf1->cf_name; cf1++)
  849                 if (d->dv_cfdata == cf1)
  850                         return (1);
  851 
  852         return (0);
  853 }
  854 
  855 /*
  856  * Detach a supplemental config data table. Detach all devices found
  857  * through that table (and thus keeping references to it) before.
  858  */
  859 int
  860 config_cfdata_detach(cfdata_t cf)
  861 {
  862         device_t d;
  863         int error = 0;
  864         struct cftable *ct;
  865         deviter_t di;
  866 
  867         for (d = deviter_first(&di, DEVITER_F_RW); d != NULL;
  868              d = deviter_next(&di)) {
  869                 if (!dev_in_cfdata(d, cf))
  870                         continue;
  871                 if ((error = config_detach(d, 0)) != 0)
  872                         break;
  873         }
  874         deviter_release(&di);
  875         if (error) {
  876                 aprint_error_dev(d, "unable to detach instance\n");
  877                 return error;
  878         }
  879 
  880         TAILQ_FOREACH(ct, &allcftables, ct_list) {
  881                 if (ct->ct_cfdata == cf) {
  882                         TAILQ_REMOVE(&allcftables, ct, ct_list);
  883                         kmem_free(ct, sizeof(*ct));
  884                         return (0);
  885                 }
  886         }
  887 
  888         /* not found -- shouldn't happen */
  889         return (EINVAL);
  890 }
  891 
  892 /*
  893  * Invoke the "match" routine for a cfdata entry on behalf of
  894  * an external caller, usually a "submatch" routine.
  895  */
  896 int
  897 config_match(device_t parent, cfdata_t cf, void *aux)
  898 {
  899         struct cfattach *ca;
  900 
  901         ca = config_cfattach_lookup(cf->cf_name, cf->cf_atname);
  902         if (ca == NULL) {
  903                 /* No attachment for this entry, oh well. */
  904                 return (0);
  905         }
  906 
  907         return ((*ca->ca_match)(parent, cf, aux));
  908 }
  909 
  910 /*
  911  * Iterate over all potential children of some device, calling the given
  912  * function (default being the child's match function) for each one.
  913  * Nonzero returns are matches; the highest value returned is considered
  914  * the best match.  Return the `found child' if we got a match, or NULL
  915  * otherwise.  The `aux' pointer is simply passed on through.
  916  *
  917  * Note that this function is designed so that it can be used to apply
  918  * an arbitrary function to all potential children (its return value
  919  * can be ignored).
  920  */
  921 cfdata_t
  922 config_search_loc(cfsubmatch_t fn, device_t parent,
  923                   const char *ifattr, const int *locs, void *aux)
  924 {
  925         struct cftable *ct;
  926         cfdata_t cf;
  927         struct matchinfo m;
  928 
  929         KASSERT(config_initialized);
  930         KASSERT(!ifattr || cfdriver_get_iattr(parent->dv_cfdriver, ifattr));
  931 
  932         m.fn = fn;
  933         m.parent = parent;
  934         m.locs = locs;
  935         m.aux = aux;
  936         m.match = NULL;
  937         m.pri = 0;
  938 
  939         TAILQ_FOREACH(ct, &allcftables, ct_list) {
  940                 for (cf = ct->ct_cfdata; cf->cf_name; cf++) {
  941 
  942                         /* We don't match root nodes here. */
  943                         if (!cf->cf_pspec)
  944                                 continue;
  945 
  946                         /*
  947                          * Skip cf if no longer eligible, otherwise scan
  948                          * through parents for one matching `parent', and
  949                          * try match function.
  950                          */
  951                         if (cf->cf_fstate == FSTATE_FOUND)
  952                                 continue;
  953                         if (cf->cf_fstate == FSTATE_DNOTFOUND ||
  954                             cf->cf_fstate == FSTATE_DSTAR)
  955                                 continue;
  956 
  957                         /*
  958                          * If an interface attribute was specified,
  959                          * consider only children which attach to
  960                          * that attribute.
  961                          */
  962                         if (ifattr && !STREQ(ifattr, cf->cf_pspec->cfp_iattr))
  963                                 continue;
  964 
  965                         if (cfparent_match(parent, cf->cf_pspec))
  966                                 mapply(&m, cf);
  967                 }
  968         }
  969         return (m.match);
  970 }
  971 
  972 cfdata_t
  973 config_search_ia(cfsubmatch_t fn, device_t parent, const char *ifattr,
  974     void *aux)
  975 {
  976 
  977         return (config_search_loc(fn, parent, ifattr, NULL, aux));
  978 }
  979 
  980 /*
  981  * Find the given root device.
  982  * This is much like config_search, but there is no parent.
  983  * Don't bother with multiple cfdata tables; the root node
  984  * must always be in the initial table.
  985  */
  986 cfdata_t
  987 config_rootsearch(cfsubmatch_t fn, const char *rootname, void *aux)
  988 {
  989         cfdata_t cf;
  990         const short *p;
  991         struct matchinfo m;
  992 
  993         m.fn = fn;
  994         m.parent = ROOT;
  995         m.aux = aux;
  996         m.match = NULL;
  997         m.pri = 0;
  998         m.locs = 0;
  999         /*
 1000          * Look at root entries for matching name.  We do not bother
 1001          * with found-state here since only one root should ever be
 1002          * searched (and it must be done first).
 1003          */
 1004         for (p = cfroots; *p >= 0; p++) {
 1005                 cf = &cfdata[*p];
 1006                 if (strcmp(cf->cf_name, rootname) == 0)
 1007                         mapply(&m, cf);
 1008         }
 1009         return (m.match);
 1010 }
 1011 
 1012 static const char * const msgs[3] = { "", " not configured\n", " unsupported\n" };
 1013 
 1014 /*
 1015  * The given `aux' argument describes a device that has been found
 1016  * on the given parent, but not necessarily configured.  Locate the
 1017  * configuration data for that device (using the submatch function
 1018  * provided, or using candidates' cd_match configuration driver
 1019  * functions) and attach it, and return true.  If the device was
 1020  * not configured, call the given `print' function and return 0.
 1021  */
 1022 device_t
 1023 config_found_sm_loc(device_t parent,
 1024                 const char *ifattr, const int *locs, void *aux,
 1025                 cfprint_t print, cfsubmatch_t submatch)
 1026 {
 1027         cfdata_t cf;
 1028 
 1029 #if defined(SPLASHSCREEN) && defined(SPLASHSCREEN_PROGRESS)
 1030         if (splash_progress_state)
 1031                 splash_progress_update(splash_progress_state);
 1032 #endif
 1033 
 1034         if ((cf = config_search_loc(submatch, parent, ifattr, locs, aux)))
 1035                 return(config_attach_loc(parent, cf, locs, aux, print));
 1036         if (print) {
 1037                 if (config_do_twiddle)
 1038                         twiddle();
 1039                 aprint_normal("%s", msgs[(*print)(aux, device_xname(parent))]);
 1040         }
 1041 
 1042 #if defined(SPLASHSCREEN) && defined(SPLASHSCREEN_PROGRESS)
 1043         if (splash_progress_state)
 1044                 splash_progress_update(splash_progress_state);
 1045 #endif
 1046 
 1047         return (NULL);
 1048 }
 1049 
 1050 device_t
 1051 config_found_ia(device_t parent, const char *ifattr, void *aux,
 1052     cfprint_t print)
 1053 {
 1054 
 1055         return (config_found_sm_loc(parent, ifattr, NULL, aux, print, NULL));
 1056 }
 1057 
 1058 device_t
 1059 config_found(device_t parent, void *aux, cfprint_t print)
 1060 {
 1061 
 1062         return (config_found_sm_loc(parent, NULL, NULL, aux, print, NULL));
 1063 }
 1064 
 1065 /*
 1066  * As above, but for root devices.
 1067  */
 1068 device_t
 1069 config_rootfound(const char *rootname, void *aux)
 1070 {
 1071         cfdata_t cf;
 1072 
 1073         if ((cf = config_rootsearch((cfsubmatch_t)NULL, rootname, aux)) != NULL)
 1074                 return (config_attach(ROOT, cf, aux, (cfprint_t)NULL));
 1075         aprint_error("root device %s not configured\n", rootname);
 1076         return (NULL);
 1077 }
 1078 
 1079 /* just like sprintf(buf, "%d") except that it works from the end */
 1080 static char *
 1081 number(char *ep, int n)
 1082 {
 1083 
 1084         *--ep = 0;
 1085         while (n >= 10) {
 1086                 *--ep = (n % 10) + '';
 1087                 n /= 10;
 1088         }
 1089         *--ep = n + '';
 1090         return (ep);
 1091 }
 1092 
 1093 /*
 1094  * Expand the size of the cd_devs array if necessary.
 1095  */
 1096 static void
 1097 config_makeroom(int n, struct cfdriver *cd)
 1098 {
 1099         const km_flag_t kmflags = (cold ? KM_NOSLEEP : KM_SLEEP);
 1100         int old, new;
 1101         device_t *nsp;
 1102 
 1103         if (n < cd->cd_ndevs)
 1104                 return;
 1105 
 1106         /*
 1107          * Need to expand the array.
 1108          */
 1109         old = cd->cd_ndevs;
 1110         if (old == 0)
 1111                 new = 4;
 1112         else
 1113                 new = old * 2;
 1114         while (new <= n)
 1115                 new *= 2;
 1116         cd->cd_ndevs = new;
 1117         nsp = kmem_alloc(sizeof(device_t [new]), kmflags);
 1118         if (nsp == NULL)
 1119                 panic("config_attach: %sing dev array",
 1120                     old != 0 ? "expand" : "creat");
 1121         memset(nsp + old, 0, sizeof(device_t [new - old]));
 1122         if (old != 0) {
 1123                 memcpy(nsp, cd->cd_devs, sizeof(device_t [old]));
 1124                 kmem_free(cd->cd_devs, sizeof(device_t [old]));
 1125         }
 1126         cd->cd_devs = nsp;
 1127 }
 1128 
 1129 static void
 1130 config_devlink(device_t dev)
 1131 {
 1132         struct cfdriver *cd = dev->dv_cfdriver;
 1133 
 1134         /* put this device in the devices array */
 1135         config_makeroom(dev->dv_unit, cd);
 1136         if (cd->cd_devs[dev->dv_unit])
 1137                 panic("config_attach: duplicate %s", device_xname(dev));
 1138         cd->cd_devs[dev->dv_unit] = dev;
 1139 
 1140         /* It is safe to add a device to the tail of the list while
 1141          * readers are in the list, but not while a writer is in
 1142          * the list.  Wait for any writer to complete.
 1143          */
 1144         mutex_enter(&alldevs_mtx);
 1145         while (alldevs_nwrite != 0 && alldevs_writer != curlwp)
 1146                 cv_wait(&alldevs_cv, &alldevs_mtx);
 1147         TAILQ_INSERT_TAIL(&alldevs, dev, dv_list);      /* link up */
 1148         cv_signal(&alldevs_cv);
 1149         mutex_exit(&alldevs_mtx);
 1150 }
 1151 
 1152 static void
 1153 config_devunlink(device_t dev)
 1154 {
 1155         struct cfdriver *cd = dev->dv_cfdriver;
 1156         int i;
 1157 
 1158         /* Unlink from device list. */
 1159         TAILQ_REMOVE(&alldevs, dev, dv_list);
 1160 
 1161         /* Remove from cfdriver's array. */
 1162         cd->cd_devs[dev->dv_unit] = NULL;
 1163 
 1164         /*
 1165          * If the device now has no units in use, deallocate its softc array.
 1166          */
 1167         for (i = 0; i < cd->cd_ndevs; i++) {
 1168                 if (cd->cd_devs[i] != NULL)
 1169                         return;
 1170         }
 1171         /* nothing found; deallocate */
 1172         kmem_free(cd->cd_devs, sizeof(device_t [cd->cd_ndevs]));
 1173         cd->cd_devs = NULL;
 1174         cd->cd_ndevs = 0;
 1175 }
 1176         
 1177 static device_t
 1178 config_devalloc(const device_t parent, const cfdata_t cf, const int *locs)
 1179 {
 1180         struct cfdriver *cd;
 1181         struct cfattach *ca;
 1182         size_t lname, lunit;
 1183         const char *xunit;
 1184         int myunit;
 1185         char num[10];
 1186         device_t dev;
 1187         void *dev_private;
 1188         const struct cfiattrdata *ia;
 1189         const km_flag_t kmflags = (cold ? KM_NOSLEEP : KM_SLEEP);
 1190 
 1191         cd = config_cfdriver_lookup(cf->cf_name);
 1192         if (cd == NULL)
 1193                 return (NULL);
 1194 
 1195         ca = config_cfattach_lookup_cd(cd, cf->cf_atname);
 1196         if (ca == NULL)
 1197                 return (NULL);
 1198 
 1199         if ((ca->ca_flags & DVF_PRIV_ALLOC) == 0 &&
 1200             ca->ca_devsize < sizeof(struct device))
 1201                 panic("config_devalloc: %s", cf->cf_atname);
 1202 
 1203 #ifndef __BROKEN_CONFIG_UNIT_USAGE
 1204         if (cf->cf_fstate == FSTATE_STAR) {
 1205                 for (myunit = cf->cf_unit; myunit < cd->cd_ndevs; myunit++)
 1206                         if (cd->cd_devs[myunit] == NULL)
 1207                                 break;
 1208                 /*
 1209                  * myunit is now the unit of the first NULL device pointer,
 1210                  * or max(cd->cd_ndevs,cf->cf_unit).
 1211                  */
 1212         } else {
 1213                 myunit = cf->cf_unit;
 1214                 if (myunit < cd->cd_ndevs && cd->cd_devs[myunit] != NULL)
 1215                         return (NULL);
 1216         }       
 1217 #else
 1218         myunit = cf->cf_unit;
 1219 #endif /* ! __BROKEN_CONFIG_UNIT_USAGE */
 1220 
 1221         /* compute length of name and decimal expansion of unit number */
 1222         lname = strlen(cd->cd_name);
 1223         xunit = number(&num[sizeof(num)], myunit);
 1224         lunit = &num[sizeof(num)] - xunit;
 1225         if (lname + lunit > sizeof(dev->dv_xname))
 1226                 panic("config_devalloc: device name too long");
 1227 
 1228         /* get memory for all device vars */
 1229         KASSERT((ca->ca_flags & DVF_PRIV_ALLOC) || ca->ca_devsize >= sizeof(struct device));
 1230         if (ca->ca_devsize > 0) {
 1231                 dev_private = kmem_zalloc(ca->ca_devsize, kmflags);
 1232                 if (dev_private == NULL)
 1233                         panic("config_devalloc: memory allocation for device softc failed");
 1234         } else {
 1235                 KASSERT(ca->ca_flags & DVF_PRIV_ALLOC);
 1236                 dev_private = NULL;
 1237         }
 1238 
 1239         if ((ca->ca_flags & DVF_PRIV_ALLOC) != 0) {
 1240                 dev = kmem_zalloc(sizeof(*dev), kmflags);
 1241         } else {
 1242                 dev = dev_private;
 1243         }
 1244         if (dev == NULL)
 1245                 panic("config_devalloc: memory allocation for device_t failed");
 1246 
 1247         dev->dv_class = cd->cd_class;
 1248         dev->dv_cfdata = cf;
 1249         dev->dv_cfdriver = cd;
 1250         dev->dv_cfattach = ca;
 1251         dev->dv_unit = myunit;
 1252         dev->dv_activity_count = 0;
 1253         dev->dv_activity_handlers = NULL;
 1254         dev->dv_private = dev_private;
 1255         memcpy(dev->dv_xname, cd->cd_name, lname);
 1256         memcpy(dev->dv_xname + lname, xunit, lunit);
 1257         dev->dv_parent = parent;
 1258         if (parent != NULL)
 1259                 dev->dv_depth = parent->dv_depth + 1;
 1260         else
 1261                 dev->dv_depth = 0;
 1262         dev->dv_flags = DVF_ACTIVE;     /* always initially active */
 1263         dev->dv_flags |= ca->ca_flags;  /* inherit flags from class */
 1264         if (locs) {
 1265                 KASSERT(parent); /* no locators at root */
 1266                 ia = cfiattr_lookup(cf->cf_pspec->cfp_iattr,
 1267                                     parent->dv_cfdriver);
 1268                 dev->dv_locators =
 1269                     kmem_alloc(sizeof(int [ia->ci_loclen + 1]), kmflags);
 1270                 *dev->dv_locators++ = sizeof(int [ia->ci_loclen + 1]);
 1271                 memcpy(dev->dv_locators, locs, sizeof(int [ia->ci_loclen]));
 1272         }
 1273         dev->dv_properties = prop_dictionary_create();
 1274         KASSERT(dev->dv_properties != NULL);
 1275 
 1276         prop_dictionary_set_cstring_nocopy(dev->dv_properties,
 1277             "device-driver", dev->dv_cfdriver->cd_name);
 1278         prop_dictionary_set_uint16(dev->dv_properties,
 1279             "device-unit", dev->dv_unit);
 1280 
 1281         return (dev);
 1282 }
 1283 
 1284 static void
 1285 config_devdealloc(device_t dev)
 1286 {
 1287         int priv = (dev->dv_flags & DVF_PRIV_ALLOC);
 1288 
 1289         KASSERT(dev->dv_properties != NULL);
 1290         prop_object_release(dev->dv_properties);
 1291 
 1292         if (dev->dv_activity_handlers)
 1293                 panic("config_devdealloc with registered handlers");
 1294 
 1295         if (dev->dv_locators) {
 1296                 size_t amount = *--dev->dv_locators;
 1297                 kmem_free(dev->dv_locators, amount);
 1298         }
 1299 
 1300         if (dev->dv_cfattach->ca_devsize > 0)
 1301                 kmem_free(dev->dv_private, dev->dv_cfattach->ca_devsize);
 1302         if (priv)
 1303                 kmem_free(dev, sizeof(*dev));
 1304 }
 1305 
 1306 /*
 1307  * Attach a found device.
 1308  */
 1309 device_t
 1310 config_attach_loc(device_t parent, cfdata_t cf,
 1311         const int *locs, void *aux, cfprint_t print)
 1312 {
 1313         device_t dev;
 1314         struct cftable *ct;
 1315         const char *drvname;
 1316 
 1317 #if defined(SPLASHSCREEN) && defined(SPLASHSCREEN_PROGRESS)
 1318         if (splash_progress_state)
 1319                 splash_progress_update(splash_progress_state);
 1320 #endif
 1321 
 1322         dev = config_devalloc(parent, cf, locs);
 1323         if (!dev)
 1324                 panic("config_attach: allocation of device softc failed");
 1325 
 1326         /* XXX redundant - see below? */
 1327         if (cf->cf_fstate != FSTATE_STAR) {
 1328                 KASSERT(cf->cf_fstate == FSTATE_NOTFOUND);
 1329                 cf->cf_fstate = FSTATE_FOUND;
 1330         }
 1331 #ifdef __BROKEN_CONFIG_UNIT_USAGE
 1332           else
 1333                 cf->cf_unit++;
 1334 #endif
 1335 
 1336         config_devlink(dev);
 1337 
 1338         if (config_do_twiddle)
 1339                 twiddle();
 1340         else
 1341                 aprint_naive("Found ");
 1342         /*
 1343          * We want the next two printfs for normal, verbose, and quiet,
 1344          * but not silent (in which case, we're twiddling, instead).
 1345          */
 1346         if (parent == ROOT) {
 1347                 aprint_naive("%s (root)", device_xname(dev));
 1348                 aprint_normal("%s (root)", device_xname(dev));
 1349         } else {
 1350                 aprint_naive("%s at %s", device_xname(dev), device_xname(parent));
 1351                 aprint_normal("%s at %s", device_xname(dev), device_xname(parent));
 1352                 if (print)
 1353                         (void) (*print)(aux, NULL);
 1354         }
 1355 
 1356         /*
 1357          * Before attaching, clobber any unfound devices that are
 1358          * otherwise identical.
 1359          * XXX code above is redundant?
 1360          */
 1361         drvname = dev->dv_cfdriver->cd_name;
 1362         TAILQ_FOREACH(ct, &allcftables, ct_list) {
 1363                 for (cf = ct->ct_cfdata; cf->cf_name; cf++) {
 1364                         if (STREQ(cf->cf_name, drvname) &&
 1365                             cf->cf_unit == dev->dv_unit) {
 1366                                 if (cf->cf_fstate == FSTATE_NOTFOUND)
 1367                                         cf->cf_fstate = FSTATE_FOUND;
 1368 #ifdef __BROKEN_CONFIG_UNIT_USAGE
 1369                                 /*
 1370                                  * Bump the unit number on all starred cfdata
 1371                                  * entries for this device.
 1372                                  */
 1373                                 if (cf->cf_fstate == FSTATE_STAR)
 1374                                         cf->cf_unit++;
 1375 #endif /* __BROKEN_CONFIG_UNIT_USAGE */
 1376                         }
 1377                 }
 1378         }
 1379 #ifdef __HAVE_DEVICE_REGISTER
 1380         device_register(dev, aux);
 1381 #endif
 1382 
 1383         /* Let userland know */
 1384         devmon_report_device(dev, true);
 1385 
 1386 #if defined(SPLASHSCREEN) && defined(SPLASHSCREEN_PROGRESS)
 1387         if (splash_progress_state)
 1388                 splash_progress_update(splash_progress_state);
 1389 #endif
 1390         (*dev->dv_cfattach->ca_attach)(parent, dev, aux);
 1391 #if defined(SPLASHSCREEN) && defined(SPLASHSCREEN_PROGRESS)
 1392         if (splash_progress_state)
 1393                 splash_progress_update(splash_progress_state);
 1394 #endif
 1395 
 1396         if (!device_pmf_is_registered(dev))
 1397                 aprint_debug_dev(dev, "WARNING: power management not supported\n");
 1398 
 1399         config_process_deferred(&deferred_config_queue, dev);
 1400         return (dev);
 1401 }
 1402 
 1403 device_t
 1404 config_attach(device_t parent, cfdata_t cf, void *aux, cfprint_t print)
 1405 {
 1406 
 1407         return (config_attach_loc(parent, cf, NULL, aux, print));
 1408 }
 1409 
 1410 /*
 1411  * As above, but for pseudo-devices.  Pseudo-devices attached in this
 1412  * way are silently inserted into the device tree, and their children
 1413  * attached.
 1414  *
 1415  * Note that because pseudo-devices are attached silently, any information
 1416  * the attach routine wishes to print should be prefixed with the device
 1417  * name by the attach routine.
 1418  */
 1419 device_t
 1420 config_attach_pseudo(cfdata_t cf)
 1421 {
 1422         device_t dev;
 1423 
 1424         dev = config_devalloc(ROOT, cf, NULL);
 1425         if (!dev)
 1426                 return (NULL);
 1427 
 1428         /* XXX mark busy in cfdata */
 1429 
 1430         config_devlink(dev);
 1431 
 1432 #if 0   /* XXXJRT not yet */
 1433 #ifdef __HAVE_DEVICE_REGISTER
 1434         device_register(dev, NULL);     /* like a root node */
 1435 #endif
 1436 #endif
 1437         (*dev->dv_cfattach->ca_attach)(ROOT, dev, NULL);
 1438         config_process_deferred(&deferred_config_queue, dev);
 1439         return (dev);
 1440 }
 1441 
 1442 /*
 1443  * Detach a device.  Optionally forced (e.g. because of hardware
 1444  * removal) and quiet.  Returns zero if successful, non-zero
 1445  * (an error code) otherwise.
 1446  *
 1447  * Note that this code wants to be run from a process context, so
 1448  * that the detach can sleep to allow processes which have a device
 1449  * open to run and unwind their stacks.
 1450  */
 1451 int
 1452 config_detach(device_t dev, int flags)
 1453 {
 1454         struct cftable *ct;
 1455         cfdata_t cf;
 1456         const struct cfattach *ca;
 1457         struct cfdriver *cd;
 1458 #ifdef DIAGNOSTIC
 1459         device_t d;
 1460 #endif
 1461         int rv = 0;
 1462 
 1463 #ifdef DIAGNOSTIC
 1464         cf = dev->dv_cfdata;
 1465         if (cf != NULL && cf->cf_fstate != FSTATE_FOUND &&
 1466             cf->cf_fstate != FSTATE_STAR)
 1467                 panic("config_detach: %s: bad device fstate %d",
 1468                     device_xname(dev), cf ? cf->cf_fstate : -1);
 1469 #endif
 1470         cd = dev->dv_cfdriver;
 1471         KASSERT(cd != NULL);
 1472 
 1473         ca = dev->dv_cfattach;
 1474         KASSERT(ca != NULL);
 1475 
 1476         KASSERT(curlwp != NULL);
 1477         mutex_enter(&alldevs_mtx);
 1478         if (alldevs_nwrite > 0 && alldevs_writer == NULL)
 1479                 ;
 1480         else while (alldevs_nread != 0 ||
 1481                (alldevs_nwrite != 0 && alldevs_writer != curlwp))
 1482                 cv_wait(&alldevs_cv, &alldevs_mtx);
 1483         if (alldevs_nwrite++ == 0)
 1484                 alldevs_writer = curlwp;
 1485         mutex_exit(&alldevs_mtx);
 1486 
 1487         /*
 1488          * Ensure the device is deactivated.  If the device doesn't
 1489          * have an activation entry point, we allow DVF_ACTIVE to
 1490          * remain set.  Otherwise, if DVF_ACTIVE is still set, the
 1491          * device is busy, and the detach fails.
 1492          */
 1493         if (ca->ca_activate != NULL)
 1494                 rv = config_deactivate(dev);
 1495 
 1496         /*
 1497          * Try to detach the device.  If that's not possible, then
 1498          * we either panic() (for the forced but failed case), or
 1499          * return an error.
 1500          */
 1501         if (rv == 0) {
 1502                 if (ca->ca_detach != NULL)
 1503                         rv = (*ca->ca_detach)(dev, flags);
 1504                 else
 1505                         rv = EOPNOTSUPP;
 1506         }
 1507         if (rv != 0) {
 1508                 if ((flags & DETACH_FORCE) == 0)
 1509                         goto out;
 1510                 else
 1511                         panic("config_detach: forced detach of %s failed (%d)",
 1512                             device_xname(dev), rv);
 1513         }
 1514 
 1515         /*
 1516          * The device has now been successfully detached.
 1517          */
 1518 
 1519         /* Let userland know */
 1520         devmon_report_device(dev, false);
 1521 
 1522 #ifdef DIAGNOSTIC
 1523         /*
 1524          * Sanity: If you're successfully detached, you should have no
 1525          * children.  (Note that because children must be attached
 1526          * after parents, we only need to search the latter part of
 1527          * the list.)
 1528          */
 1529         for (d = TAILQ_NEXT(dev, dv_list); d != NULL;
 1530             d = TAILQ_NEXT(d, dv_list)) {
 1531                 if (d->dv_parent == dev) {
 1532                         printf("config_detach: detached device %s"
 1533                             " has children %s\n", device_xname(dev), device_xname(d));
 1534                         panic("config_detach");
 1535                 }
 1536         }
 1537 #endif
 1538 
 1539         /* notify the parent that the child is gone */
 1540         if (dev->dv_parent) {
 1541                 device_t p = dev->dv_parent;
 1542                 if (p->dv_cfattach->ca_childdetached)
 1543                         (*p->dv_cfattach->ca_childdetached)(p, dev);
 1544         }
 1545 
 1546         /*
 1547          * Mark cfdata to show that the unit can be reused, if possible.
 1548          */
 1549         TAILQ_FOREACH(ct, &allcftables, ct_list) {
 1550                 for (cf = ct->ct_cfdata; cf->cf_name; cf++) {
 1551                         if (STREQ(cf->cf_name, cd->cd_name)) {
 1552                                 if (cf->cf_fstate == FSTATE_FOUND &&
 1553                                     cf->cf_unit == dev->dv_unit)
 1554                                         cf->cf_fstate = FSTATE_NOTFOUND;
 1555 #ifdef __BROKEN_CONFIG_UNIT_USAGE
 1556                                 /*
 1557                                  * Note that we can only re-use a starred
 1558                                  * unit number if the unit being detached
 1559                                  * had the last assigned unit number.
 1560                                  */
 1561                                 if (cf->cf_fstate == FSTATE_STAR &&
 1562                                     cf->cf_unit == dev->dv_unit + 1)
 1563                                         cf->cf_unit--;
 1564 #endif /* __BROKEN_CONFIG_UNIT_USAGE */
 1565                         }
 1566                 }
 1567         }
 1568 
 1569         config_devunlink(dev);
 1570 
 1571         if (dev->dv_cfdata != NULL && (flags & DETACH_QUIET) == 0)
 1572                 aprint_normal_dev(dev, "detached\n");
 1573 
 1574         config_devdealloc(dev);
 1575 
 1576 out:
 1577         mutex_enter(&alldevs_mtx);
 1578         if (--alldevs_nwrite == 0)
 1579                 alldevs_writer = NULL;
 1580         cv_signal(&alldevs_cv);
 1581         mutex_exit(&alldevs_mtx);
 1582         return rv;
 1583 }
 1584 
 1585 int
 1586 config_detach_children(device_t parent, int flags)
 1587 {
 1588         device_t dv;
 1589         deviter_t di;
 1590         int error = 0;
 1591 
 1592         for (dv = deviter_first(&di, DEVITER_F_RW); dv != NULL;
 1593              dv = deviter_next(&di)) {
 1594                 if (device_parent(dv) != parent)
 1595                         continue;
 1596                 if ((error = config_detach(dv, flags)) != 0)
 1597                         break;
 1598         }
 1599         deviter_release(&di);
 1600         return error;
 1601 }
 1602 
 1603 int
 1604 config_activate(device_t dev)
 1605 {
 1606         const struct cfattach *ca = dev->dv_cfattach;
 1607         int rv = 0, oflags = dev->dv_flags;
 1608 
 1609         if (ca->ca_activate == NULL)
 1610                 return (EOPNOTSUPP);
 1611 
 1612         if ((dev->dv_flags & DVF_ACTIVE) == 0) {
 1613                 dev->dv_flags |= DVF_ACTIVE;
 1614                 rv = (*ca->ca_activate)(dev, DVACT_ACTIVATE);
 1615                 if (rv)
 1616                         dev->dv_flags = oflags;
 1617         }
 1618         return (rv);
 1619 }
 1620 
 1621 int
 1622 config_deactivate(device_t dev)
 1623 {
 1624         const struct cfattach *ca = dev->dv_cfattach;
 1625         int rv = 0, oflags = dev->dv_flags;
 1626 
 1627         if (ca->ca_activate == NULL)
 1628                 return (EOPNOTSUPP);
 1629 
 1630         if (dev->dv_flags & DVF_ACTIVE) {
 1631                 dev->dv_flags &= ~DVF_ACTIVE;
 1632                 rv = (*ca->ca_activate)(dev, DVACT_DEACTIVATE);
 1633                 if (rv)
 1634                         dev->dv_flags = oflags;
 1635         }
 1636         return (rv);
 1637 }
 1638 
 1639 /*
 1640  * Defer the configuration of the specified device until all
 1641  * of its parent's devices have been attached.
 1642  */
 1643 void
 1644 config_defer(device_t dev, void (*func)(device_t))
 1645 {
 1646         const km_flag_t kmflags = (cold ? KM_NOSLEEP : KM_SLEEP);
 1647         struct deferred_config *dc;
 1648 
 1649         if (dev->dv_parent == NULL)
 1650                 panic("config_defer: can't defer config of a root device");
 1651 
 1652 #ifdef DIAGNOSTIC
 1653         for (dc = TAILQ_FIRST(&deferred_config_queue); dc != NULL;
 1654              dc = TAILQ_NEXT(dc, dc_queue)) {
 1655                 if (dc->dc_dev == dev)
 1656                         panic("config_defer: deferred twice");
 1657         }
 1658 #endif
 1659 
 1660         dc = kmem_alloc(sizeof(*dc), kmflags);
 1661         if (dc == NULL)
 1662                 panic("config_defer: unable to allocate callback");
 1663 
 1664         dc->dc_dev = dev;
 1665         dc->dc_func = func;
 1666         TAILQ_INSERT_TAIL(&deferred_config_queue, dc, dc_queue);
 1667         config_pending_incr();
 1668 }
 1669 
 1670 /*
 1671  * Defer some autoconfiguration for a device until after interrupts
 1672  * are enabled.
 1673  */
 1674 void
 1675 config_interrupts(device_t dev, void (*func)(device_t))
 1676 {
 1677         const km_flag_t kmflags = (cold ? KM_NOSLEEP : KM_SLEEP);
 1678         struct deferred_config *dc;
 1679 
 1680         /*
 1681          * If interrupts are enabled, callback now.
 1682          */
 1683         if (cold == 0) {
 1684                 (*func)(dev);
 1685                 return;
 1686         }
 1687 
 1688 #ifdef DIAGNOSTIC
 1689         for (dc = TAILQ_FIRST(&interrupt_config_queue); dc != NULL;
 1690              dc = TAILQ_NEXT(dc, dc_queue)) {
 1691                 if (dc->dc_dev == dev)
 1692                         panic("config_interrupts: deferred twice");
 1693         }
 1694 #endif
 1695 
 1696         dc = kmem_alloc(sizeof(*dc), kmflags);
 1697         if (dc == NULL)
 1698                 panic("config_interrupts: unable to allocate callback");
 1699 
 1700         dc->dc_dev = dev;
 1701         dc->dc_func = func;
 1702         TAILQ_INSERT_TAIL(&interrupt_config_queue, dc, dc_queue);
 1703         config_pending_incr();
 1704 }
 1705 
 1706 /*
 1707  * Process a deferred configuration queue.
 1708  */
 1709 static void
 1710 config_process_deferred(struct deferred_config_head *queue,
 1711     device_t parent)
 1712 {
 1713         struct deferred_config *dc, *ndc;
 1714 
 1715         for (dc = TAILQ_FIRST(queue); dc != NULL; dc = ndc) {
 1716                 ndc = TAILQ_NEXT(dc, dc_queue);
 1717                 if (parent == NULL || dc->dc_dev->dv_parent == parent) {
 1718                         TAILQ_REMOVE(queue, dc, dc_queue);
 1719                         (*dc->dc_func)(dc->dc_dev);
 1720                         kmem_free(dc, sizeof(*dc));
 1721                         config_pending_decr();
 1722                 }
 1723         }
 1724 }
 1725 
 1726 /*
 1727  * Manipulate the config_pending semaphore.
 1728  */
 1729 void
 1730 config_pending_incr(void)
 1731 {
 1732 
 1733         mutex_enter(&config_misc_lock);
 1734         config_pending++;
 1735         mutex_exit(&config_misc_lock);
 1736 }
 1737 
 1738 void
 1739 config_pending_decr(void)
 1740 {
 1741 
 1742 #ifdef DIAGNOSTIC
 1743         if (config_pending == 0)
 1744                 panic("config_pending_decr: config_pending == 0");
 1745 #endif
 1746         mutex_enter(&config_misc_lock);
 1747         config_pending--;
 1748         if (config_pending == 0)
 1749                 cv_broadcast(&config_misc_cv);
 1750         mutex_exit(&config_misc_lock);
 1751 }
 1752 
 1753 /*
 1754  * Register a "finalization" routine.  Finalization routines are
 1755  * called iteratively once all real devices have been found during
 1756  * autoconfiguration, for as long as any one finalizer has done
 1757  * any work.
 1758  */
 1759 int
 1760 config_finalize_register(device_t dev, int (*fn)(device_t))
 1761 {
 1762         struct finalize_hook *f;
 1763 
 1764         /*
 1765          * If finalization has already been done, invoke the
 1766          * callback function now.
 1767          */
 1768         if (config_finalize_done) {
 1769                 while ((*fn)(dev) != 0)
 1770                         /* loop */ ;
 1771         }
 1772 
 1773         /* Ensure this isn't already on the list. */
 1774         TAILQ_FOREACH(f, &config_finalize_list, f_list) {
 1775                 if (f->f_func == fn && f->f_dev == dev)
 1776                         return (EEXIST);
 1777         }
 1778 
 1779         f = kmem_alloc(sizeof(*f), KM_SLEEP);
 1780         f->f_func = fn;
 1781         f->f_dev = dev;
 1782         TAILQ_INSERT_TAIL(&config_finalize_list, f, f_list);
 1783 
 1784         return (0);
 1785 }
 1786 
 1787 void
 1788 config_finalize(void)
 1789 {
 1790         struct finalize_hook *f;
 1791         struct pdevinit *pdev;
 1792         extern struct pdevinit pdevinit[];
 1793         int errcnt, rv;
 1794 
 1795         /*
 1796          * Now that device driver threads have been created, wait for
 1797          * them to finish any deferred autoconfiguration.
 1798          */
 1799         mutex_enter(&config_misc_lock);
 1800         while (config_pending != 0)
 1801                 cv_wait(&config_misc_cv, &config_misc_lock);
 1802         mutex_exit(&config_misc_lock);
 1803 
 1804         KERNEL_LOCK(1, NULL);
 1805 
 1806         /* Attach pseudo-devices. */
 1807         for (pdev = pdevinit; pdev->pdev_attach != NULL; pdev++)
 1808                 (*pdev->pdev_attach)(pdev->pdev_count);
 1809 
 1810         /* Run the hooks until none of them does any work. */
 1811         do {
 1812                 rv = 0;
 1813                 TAILQ_FOREACH(f, &config_finalize_list, f_list)
 1814                         rv |= (*f->f_func)(f->f_dev);
 1815         } while (rv != 0);
 1816 
 1817         config_finalize_done = 1;
 1818 
 1819         /* Now free all the hooks. */
 1820         while ((f = TAILQ_FIRST(&config_finalize_list)) != NULL) {
 1821                 TAILQ_REMOVE(&config_finalize_list, f, f_list);
 1822                 kmem_free(f, sizeof(*f));
 1823         }
 1824 
 1825         KERNEL_UNLOCK_ONE(NULL);
 1826 
 1827         errcnt = aprint_get_error_count();
 1828         if ((boothowto & (AB_QUIET|AB_SILENT)) != 0 &&
 1829             (boothowto & AB_VERBOSE) == 0) {
 1830                 if (config_do_twiddle) {
 1831                         config_do_twiddle = 0;
 1832                         printf_nolog(" done.\n");
 1833                 }
 1834                 if (errcnt != 0) {
 1835                         printf("WARNING: %d error%s while detecting hardware; "
 1836                             "check system log.\n", errcnt,
 1837                             errcnt == 1 ? "" : "s");
 1838                 }
 1839         }
 1840 }
 1841 
 1842 /*
 1843  * device_lookup:
 1844  *
 1845  *      Look up a device instance for a given driver.
 1846  */
 1847 device_t
 1848 device_lookup(cfdriver_t cd, int unit)
 1849 {
 1850 
 1851         if (unit < 0 || unit >= cd->cd_ndevs)
 1852                 return (NULL);
 1853         
 1854         return (cd->cd_devs[unit]);
 1855 }
 1856 
 1857 /*
 1858  * device_lookup:
 1859  *
 1860  *      Look up a device instance for a given driver.
 1861  */
 1862 void *
 1863 device_lookup_private(cfdriver_t cd, int unit)
 1864 {
 1865         device_t dv;
 1866 
 1867         if (unit < 0 || unit >= cd->cd_ndevs)
 1868                 return NULL;
 1869         
 1870         if ((dv = cd->cd_devs[unit]) == NULL)
 1871                 return NULL;
 1872 
 1873         return dv->dv_private;
 1874 }
 1875 
 1876 /*
 1877  * Accessor functions for the device_t type.
 1878  */
 1879 devclass_t
 1880 device_class(device_t dev)
 1881 {
 1882 
 1883         return (dev->dv_class);
 1884 }
 1885 
 1886 cfdata_t
 1887 device_cfdata(device_t dev)
 1888 {
 1889 
 1890         return (dev->dv_cfdata);
 1891 }
 1892 
 1893 cfdriver_t
 1894 device_cfdriver(device_t dev)
 1895 {
 1896 
 1897         return (dev->dv_cfdriver);
 1898 }
 1899 
 1900 cfattach_t
 1901 device_cfattach(device_t dev)
 1902 {
 1903 
 1904         return (dev->dv_cfattach);
 1905 }
 1906 
 1907 int
 1908 device_unit(device_t dev)
 1909 {
 1910 
 1911         return (dev->dv_unit);
 1912 }
 1913 
 1914 const char *
 1915 device_xname(device_t dev)
 1916 {
 1917 
 1918         return (dev->dv_xname);
 1919 }
 1920 
 1921 device_t
 1922 device_parent(device_t dev)
 1923 {
 1924 
 1925         return (dev->dv_parent);
 1926 }
 1927 
 1928 bool
 1929 device_is_active(device_t dev)
 1930 {
 1931         int active_flags;
 1932 
 1933         active_flags = DVF_ACTIVE;
 1934         active_flags |= DVF_CLASS_SUSPENDED;
 1935         active_flags |= DVF_DRIVER_SUSPENDED;
 1936         active_flags |= DVF_BUS_SUSPENDED;
 1937 
 1938         return ((dev->dv_flags & active_flags) == DVF_ACTIVE);
 1939 }
 1940 
 1941 bool
 1942 device_is_enabled(device_t dev)
 1943 {
 1944         return (dev->dv_flags & DVF_ACTIVE) == DVF_ACTIVE;
 1945 }
 1946 
 1947 bool
 1948 device_has_power(device_t dev)
 1949 {
 1950         int active_flags;
 1951 
 1952         active_flags = DVF_ACTIVE | DVF_BUS_SUSPENDED;
 1953 
 1954         return ((dev->dv_flags & active_flags) == DVF_ACTIVE);
 1955 }
 1956 
 1957 int
 1958 device_locator(device_t dev, u_int locnum)
 1959 {
 1960 
 1961         KASSERT(dev->dv_locators != NULL);
 1962         return (dev->dv_locators[locnum]);
 1963 }
 1964 
 1965 void *
 1966 device_private(device_t dev)
 1967 {
 1968 
 1969         /*
 1970          * The reason why device_private(NULL) is allowed is to simplify the
 1971          * work of a lot of userspace request handlers (i.e., c/bdev
 1972          * handlers) which grab cfdriver_t->cd_units[n].
 1973          * It avoids having them test for it to be NULL and only then calling
 1974          * device_private.
 1975          */
 1976         return dev == NULL ? NULL : dev->dv_private;
 1977 }
 1978 
 1979 prop_dictionary_t
 1980 device_properties(device_t dev)
 1981 {
 1982 
 1983         return (dev->dv_properties);
 1984 }
 1985 
 1986 /*
 1987  * device_is_a:
 1988  *
 1989  *      Returns true if the device is an instance of the specified
 1990  *      driver.
 1991  */
 1992 bool
 1993 device_is_a(device_t dev, const char *dname)
 1994 {
 1995 
 1996         return (strcmp(dev->dv_cfdriver->cd_name, dname) == 0);
 1997 }
 1998 
 1999 /*
 2000  * device_find_by_xname:
 2001  *
 2002  *      Returns the device of the given name or NULL if it doesn't exist.
 2003  */
 2004 device_t
 2005 device_find_by_xname(const char *name)
 2006 {
 2007         device_t dv;
 2008         deviter_t di;
 2009 
 2010         for (dv = deviter_first(&di, 0); dv != NULL; dv = deviter_next(&di)) {
 2011                 if (strcmp(device_xname(dv), name) == 0)
 2012                         break;
 2013         }
 2014         deviter_release(&di);
 2015 
 2016         return dv;
 2017 }
 2018 
 2019 /*
 2020  * device_find_by_driver_unit:
 2021  *
 2022  *      Returns the device of the given driver name and unit or
 2023  *      NULL if it doesn't exist.
 2024  */
 2025 device_t
 2026 device_find_by_driver_unit(const char *name, int unit)
 2027 {
 2028         struct cfdriver *cd;
 2029 
 2030         if ((cd = config_cfdriver_lookup(name)) == NULL)
 2031                 return NULL;
 2032         return device_lookup(cd, unit);
 2033 }
 2034 
 2035 /*
 2036  * Power management related functions.
 2037  */
 2038 
 2039 bool
 2040 device_pmf_is_registered(device_t dev)
 2041 {
 2042         return (dev->dv_flags & DVF_POWER_HANDLERS) != 0;
 2043 }
 2044 
 2045 bool
 2046 device_pmf_driver_suspend(device_t dev PMF_FN_ARGS)
 2047 {
 2048         if ((dev->dv_flags & DVF_DRIVER_SUSPENDED) != 0)
 2049                 return true;
 2050         if ((dev->dv_flags & DVF_CLASS_SUSPENDED) == 0)
 2051                 return false;
 2052         if (*dev->dv_driver_suspend != NULL &&
 2053             !(*dev->dv_driver_suspend)(dev PMF_FN_CALL))
 2054                 return false;
 2055 
 2056         dev->dv_flags |= DVF_DRIVER_SUSPENDED;
 2057         return true;
 2058 }
 2059 
 2060 bool
 2061 device_pmf_driver_resume(device_t dev PMF_FN_ARGS)
 2062 {
 2063         if ((dev->dv_flags & DVF_DRIVER_SUSPENDED) == 0)
 2064                 return true;
 2065         if ((dev->dv_flags & DVF_BUS_SUSPENDED) != 0)
 2066                 return false;
 2067         if ((flags & PMF_F_SELF) != 0 && !device_is_self_suspended(dev))
 2068                 return false;
 2069         if (*dev->dv_driver_resume != NULL &&
 2070             !(*dev->dv_driver_resume)(dev PMF_FN_CALL))
 2071                 return false;
 2072 
 2073         dev->dv_flags &= ~DVF_DRIVER_SUSPENDED;
 2074         return true;
 2075 }
 2076 
 2077 bool
 2078 device_pmf_driver_shutdown(device_t dev, int how)
 2079 {
 2080 
 2081         if (*dev->dv_driver_shutdown != NULL &&
 2082             !(*dev->dv_driver_shutdown)(dev, how))
 2083                 return false;
 2084         return true;
 2085 }
 2086 
 2087 bool
 2088 device_pmf_driver_register(device_t dev,
 2089     bool (*suspend)(device_t PMF_FN_PROTO),
 2090     bool (*resume)(device_t PMF_FN_PROTO),
 2091     bool (*shutdown)(device_t, int))
 2092 {
 2093         pmf_private_t *pp;
 2094 
 2095         if ((pp = kmem_zalloc(sizeof(*pp), KM_NOSLEEP)) == NULL)
 2096                 return false;
 2097         mutex_init(&pp->pp_mtx, MUTEX_DEFAULT, IPL_NONE);
 2098         cv_init(&pp->pp_cv, "pmfsusp");
 2099         dev->dv_pmf_private = pp;
 2100 
 2101         dev->dv_driver_suspend = suspend;
 2102         dev->dv_driver_resume = resume;
 2103         dev->dv_driver_shutdown = shutdown;
 2104         dev->dv_flags |= DVF_POWER_HANDLERS;
 2105         return true;
 2106 }
 2107 
 2108 static const char *
 2109 curlwp_name(void)
 2110 {
 2111         if (curlwp->l_name != NULL)
 2112                 return curlwp->l_name;
 2113         else
 2114                 return curlwp->l_proc->p_comm;
 2115 }
 2116 
 2117 void
 2118 device_pmf_driver_deregister(device_t dev)
 2119 {
 2120         pmf_private_t *pp = dev->dv_pmf_private;
 2121 
 2122         /* XXX avoid crash in case we are not initialized */
 2123         if (!pp)
 2124                 return;
 2125 
 2126         dev->dv_driver_suspend = NULL;
 2127         dev->dv_driver_resume = NULL;
 2128 
 2129         mutex_enter(&pp->pp_mtx);
 2130         dev->dv_flags &= ~DVF_POWER_HANDLERS;
 2131         while (pp->pp_nlock > 0 || pp->pp_nwait > 0) {
 2132                 /* Wake a thread that waits for the lock.  That
 2133                  * thread will fail to acquire the lock, and then
 2134                  * it will wake the next thread that waits for the
 2135                  * lock, or else it will wake us.
 2136                  */
 2137                 cv_signal(&pp->pp_cv);
 2138                 pmflock_debug(dev, __func__, __LINE__);
 2139                 cv_wait(&pp->pp_cv, &pp->pp_mtx);
 2140                 pmflock_debug(dev, __func__, __LINE__);
 2141         }
 2142         dev->dv_pmf_private = NULL;
 2143         mutex_exit(&pp->pp_mtx);
 2144 
 2145         cv_destroy(&pp->pp_cv);
 2146         mutex_destroy(&pp->pp_mtx);
 2147         kmem_free(pp, sizeof(*pp));
 2148 }
 2149 
 2150 bool
 2151 device_pmf_driver_child_register(device_t dev)
 2152 {
 2153         device_t parent = device_parent(dev);
 2154 
 2155         if (parent == NULL || parent->dv_driver_child_register == NULL)
 2156                 return true;
 2157         return (*parent->dv_driver_child_register)(dev);
 2158 }
 2159 
 2160 void
 2161 device_pmf_driver_set_child_register(device_t dev,
 2162     bool (*child_register)(device_t))
 2163 {
 2164         dev->dv_driver_child_register = child_register;
 2165 }
 2166 
 2167 void
 2168 device_pmf_self_resume(device_t dev PMF_FN_ARGS)
 2169 {
 2170         pmflock_debug_with_flags(dev, __func__, __LINE__ PMF_FN_CALL);
 2171         if ((dev->dv_flags & DVF_SELF_SUSPENDED) != 0)
 2172                 dev->dv_flags &= ~DVF_SELF_SUSPENDED;
 2173         pmflock_debug_with_flags(dev, __func__, __LINE__ PMF_FN_CALL);
 2174 }
 2175 
 2176 bool
 2177 device_is_self_suspended(device_t dev)
 2178 {
 2179         return (dev->dv_flags & DVF_SELF_SUSPENDED) != 0;
 2180 }
 2181 
 2182 void
 2183 device_pmf_self_suspend(device_t dev PMF_FN_ARGS)
 2184 {
 2185         bool self = (flags & PMF_F_SELF) != 0;
 2186 
 2187         pmflock_debug_with_flags(dev, __func__, __LINE__ PMF_FN_CALL);
 2188 
 2189         if (!self)
 2190                 dev->dv_flags &= ~DVF_SELF_SUSPENDED;
 2191         else if (device_is_active(dev))
 2192                 dev->dv_flags |= DVF_SELF_SUSPENDED;
 2193 
 2194         pmflock_debug_with_flags(dev, __func__, __LINE__ PMF_FN_CALL);
 2195 }
 2196 
 2197 static void
 2198 pmflock_debug(device_t dev, const char *func, int line)
 2199 {
 2200         pmf_private_t *pp = device_pmf_private(dev);
 2201 
 2202         aprint_debug_dev(dev, "%s.%d, %s pp_nlock %d pp_nwait %d dv_flags %x\n",
 2203             func, line, curlwp_name(), pp->pp_nlock, pp->pp_nwait,
 2204             dev->dv_flags);
 2205 }
 2206 
 2207 static void
 2208 pmflock_debug_with_flags(device_t dev, const char *func, int line PMF_FN_ARGS)
 2209 {
 2210         pmf_private_t *pp = device_pmf_private(dev);
 2211 
 2212         aprint_debug_dev(dev, "%s.%d, %s pp_nlock %d pp_nwait %d dv_flags %x "
 2213             "flags " PMF_FLAGS_FMT "\n", func, line, curlwp_name(),
 2214             pp->pp_nlock, pp->pp_nwait, dev->dv_flags PMF_FN_CALL);
 2215 }
 2216 
 2217 static bool
 2218 device_pmf_lock1(device_t dev PMF_FN_ARGS)
 2219 {
 2220         pmf_private_t *pp = device_pmf_private(dev);
 2221 
 2222         while (device_pmf_is_registered(dev) &&
 2223             pp->pp_nlock > 0 && pp->pp_holder != curlwp) {
 2224                 pp->pp_nwait++;
 2225                 pmflock_debug_with_flags(dev, __func__, __LINE__ PMF_FN_CALL);
 2226                 cv_wait(&pp->pp_cv, &pp->pp_mtx);
 2227                 pmflock_debug_with_flags(dev, __func__, __LINE__ PMF_FN_CALL);
 2228                 pp->pp_nwait--;
 2229         }
 2230         if (!device_pmf_is_registered(dev)) {
 2231                 pmflock_debug_with_flags(dev, __func__, __LINE__ PMF_FN_CALL);
 2232                 /* We could not acquire the lock, but some other thread may
 2233                  * wait for it, also.  Wake that thread.
 2234                  */
 2235                 cv_signal(&pp->pp_cv);
 2236                 return false;
 2237         }
 2238         pp->pp_nlock++;
 2239         pp->pp_holder = curlwp;
 2240         pmflock_debug_with_flags(dev, __func__, __LINE__ PMF_FN_CALL);
 2241         return true;
 2242 }
 2243 
 2244 bool
 2245 device_pmf_lock(device_t dev PMF_FN_ARGS)
 2246 {
 2247         bool rc;
 2248         pmf_private_t *pp = device_pmf_private(dev);
 2249 
 2250         mutex_enter(&pp->pp_mtx);
 2251         rc = device_pmf_lock1(dev PMF_FN_CALL);
 2252         mutex_exit(&pp->pp_mtx);
 2253 
 2254         return rc;
 2255 }
 2256 
 2257 void
 2258 device_pmf_unlock(device_t dev PMF_FN_ARGS)
 2259 {
 2260         pmf_private_t *pp = device_pmf_private(dev);
 2261 
 2262         KASSERT(pp->pp_nlock > 0);
 2263         mutex_enter(&pp->pp_mtx);
 2264         if (--pp->pp_nlock == 0)
 2265                 pp->pp_holder = NULL;
 2266         cv_signal(&pp->pp_cv);
 2267         pmflock_debug_with_flags(dev, __func__, __LINE__ PMF_FN_CALL);
 2268         mutex_exit(&pp->pp_mtx);
 2269 }
 2270 
 2271 void *
 2272 device_pmf_private(device_t dev)
 2273 {
 2274         return dev->dv_pmf_private;
 2275 }
 2276 
 2277 void *
 2278 device_pmf_bus_private(device_t dev)
 2279 {
 2280         return dev->dv_bus_private;
 2281 }
 2282 
 2283 bool
 2284 device_pmf_bus_suspend(device_t dev PMF_FN_ARGS)
 2285 {
 2286         if ((dev->dv_flags & DVF_BUS_SUSPENDED) != 0)
 2287                 return true;
 2288         if ((dev->dv_flags & DVF_CLASS_SUSPENDED) == 0 ||
 2289             (dev->dv_flags & DVF_DRIVER_SUSPENDED) == 0)
 2290                 return false;
 2291         if (*dev->dv_bus_suspend != NULL &&
 2292             !(*dev->dv_bus_suspend)(dev PMF_FN_CALL))
 2293                 return false;
 2294 
 2295         dev->dv_flags |= DVF_BUS_SUSPENDED;
 2296         return true;
 2297 }
 2298 
 2299 bool
 2300 device_pmf_bus_resume(device_t dev PMF_FN_ARGS)
 2301 {
 2302         if ((dev->dv_flags & DVF_BUS_SUSPENDED) == 0)
 2303                 return true;
 2304         if ((flags & PMF_F_SELF) != 0 && !device_is_self_suspended(dev))
 2305                 return false;
 2306         if (*dev->dv_bus_resume != NULL &&
 2307             !(*dev->dv_bus_resume)(dev PMF_FN_CALL))
 2308                 return false;
 2309 
 2310         dev->dv_flags &= ~DVF_BUS_SUSPENDED;
 2311         return true;
 2312 }
 2313 
 2314 bool
 2315 device_pmf_bus_shutdown(device_t dev, int how)
 2316 {
 2317 
 2318         if (*dev->dv_bus_shutdown != NULL &&
 2319             !(*dev->dv_bus_shutdown)(dev, how))
 2320                 return false;
 2321         return true;
 2322 }
 2323 
 2324 void
 2325 device_pmf_bus_register(device_t dev, void *priv,
 2326     bool (*suspend)(device_t PMF_FN_PROTO),
 2327     bool (*resume)(device_t PMF_FN_PROTO),
 2328     bool (*shutdown)(device_t, int), void (*deregister)(device_t))
 2329 {
 2330         dev->dv_bus_private = priv;
 2331         dev->dv_bus_resume = resume;
 2332         dev->dv_bus_suspend = suspend;
 2333         dev->dv_bus_shutdown = shutdown;
 2334         dev->dv_bus_deregister = deregister;
 2335 }
 2336 
 2337 void
 2338 device_pmf_bus_deregister(device_t dev)
 2339 {
 2340         if (dev->dv_bus_deregister == NULL)
 2341                 return;
 2342         (*dev->dv_bus_deregister)(dev);
 2343         dev->dv_bus_private = NULL;
 2344         dev->dv_bus_suspend = NULL;
 2345         dev->dv_bus_resume = NULL;
 2346         dev->dv_bus_deregister = NULL;
 2347 }
 2348 
 2349 void *
 2350 device_pmf_class_private(device_t dev)
 2351 {
 2352         return dev->dv_class_private;
 2353 }
 2354 
 2355 bool
 2356 device_pmf_class_suspend(device_t dev PMF_FN_ARGS)
 2357 {
 2358         if ((dev->dv_flags & DVF_CLASS_SUSPENDED) != 0)
 2359                 return true;
 2360         if (*dev->dv_class_suspend != NULL &&
 2361             !(*dev->dv_class_suspend)(dev PMF_FN_CALL))
 2362                 return false;
 2363 
 2364         dev->dv_flags |= DVF_CLASS_SUSPENDED;
 2365         return true;
 2366 }
 2367 
 2368 bool
 2369 device_pmf_class_resume(device_t dev PMF_FN_ARGS)
 2370 {
 2371         if ((dev->dv_flags & DVF_CLASS_SUSPENDED) == 0)
 2372                 return true;
 2373         if ((dev->dv_flags & DVF_BUS_SUSPENDED) != 0 ||
 2374             (dev->dv_flags & DVF_DRIVER_SUSPENDED) != 0)
 2375                 return false;
 2376         if (*dev->dv_class_resume != NULL &&
 2377             !(*dev->dv_class_resume)(dev PMF_FN_CALL))
 2378                 return false;
 2379 
 2380         dev->dv_flags &= ~DVF_CLASS_SUSPENDED;
 2381         return true;
 2382 }
 2383 
 2384 void
 2385 device_pmf_class_register(device_t dev, void *priv,
 2386     bool (*suspend)(device_t PMF_FN_PROTO),
 2387     bool (*resume)(device_t PMF_FN_PROTO),
 2388     void (*deregister)(device_t))
 2389 {
 2390         dev->dv_class_private = priv;
 2391         dev->dv_class_suspend = suspend;
 2392         dev->dv_class_resume = resume;
 2393         dev->dv_class_deregister = deregister;
 2394 }
 2395 
 2396 void
 2397 device_pmf_class_deregister(device_t dev)
 2398 {
 2399         if (dev->dv_class_deregister == NULL)
 2400                 return;
 2401         (*dev->dv_class_deregister)(dev);
 2402         dev->dv_class_private = NULL;
 2403         dev->dv_class_suspend = NULL;
 2404         dev->dv_class_resume = NULL;
 2405         dev->dv_class_deregister = NULL;
 2406 }
 2407 
 2408 bool
 2409 device_active(device_t dev, devactive_t type)
 2410 {
 2411         size_t i;
 2412 
 2413         if (dev->dv_activity_count == 0)
 2414                 return false;
 2415 
 2416         for (i = 0; i < dev->dv_activity_count; ++i) {
 2417                 if (dev->dv_activity_handlers[i] == NULL)
 2418                         break;
 2419                 (*dev->dv_activity_handlers[i])(dev, type);
 2420         }
 2421 
 2422         return true;
 2423 }
 2424 
 2425 bool
 2426 device_active_register(device_t dev, void (*handler)(device_t, devactive_t))
 2427 {
 2428         void (**new_handlers)(device_t, devactive_t);
 2429         void (**old_handlers)(device_t, devactive_t);
 2430         size_t i, old_size, new_size;
 2431         int s;
 2432 
 2433         old_handlers = dev->dv_activity_handlers;
 2434         old_size = dev->dv_activity_count;
 2435 
 2436         for (i = 0; i < old_size; ++i) {
 2437                 KASSERT(old_handlers[i] != handler);
 2438                 if (old_handlers[i] == NULL) {
 2439                         old_handlers[i] = handler;
 2440                         return true;
 2441                 }
 2442         }
 2443 
 2444         new_size = old_size + 4;
 2445         new_handlers = kmem_alloc(sizeof(void *[new_size]), KM_SLEEP);
 2446 
 2447         memcpy(new_handlers, old_handlers, sizeof(void *[old_size]));
 2448         new_handlers[old_size] = handler;
 2449         memset(new_handlers + old_size + 1, 0,
 2450             sizeof(int [new_size - (old_size+1)]));
 2451 
 2452         s = splhigh();
 2453         dev->dv_activity_count = new_size;
 2454         dev->dv_activity_handlers = new_handlers;
 2455         splx(s);
 2456 
 2457         if (old_handlers != NULL)
 2458                 kmem_free(old_handlers, sizeof(int [old_size]));
 2459 
 2460         return true;
 2461 }
 2462 
 2463 void
 2464 device_active_deregister(device_t dev, void (*handler)(device_t, devactive_t))
 2465 {
 2466         void (**old_handlers)(device_t, devactive_t);
 2467         size_t i, old_size;
 2468         int s;
 2469 
 2470         old_handlers = dev->dv_activity_handlers;
 2471         old_size = dev->dv_activity_count;
 2472 
 2473         for (i = 0; i < old_size; ++i) {
 2474                 if (old_handlers[i] == handler)
 2475                         break;
 2476                 if (old_handlers[i] == NULL)
 2477                         return; /* XXX panic? */
 2478         }
 2479 
 2480         if (i == old_size)
 2481                 return; /* XXX panic? */
 2482 
 2483         for (; i < old_size - 1; ++i) {
 2484                 if ((old_handlers[i] = old_handlers[i + 1]) != NULL)
 2485                         continue;
 2486 
 2487                 if (i == 0) {
 2488                         s = splhigh();
 2489                         dev->dv_activity_count = 0;
 2490                         dev->dv_activity_handlers = NULL;
 2491                         splx(s);
 2492                         kmem_free(old_handlers, sizeof(void *[old_size]));
 2493                 }
 2494                 return;
 2495         }
 2496         old_handlers[i] = NULL;
 2497 }
 2498 
 2499 /*
 2500  * Device Iteration
 2501  *
 2502  * deviter_t: a device iterator.  Holds state for a "walk" visiting
 2503  *     each device_t's in the device tree.
 2504  *
 2505  * deviter_init(di, flags): initialize the device iterator `di'
 2506  *     to "walk" the device tree.  deviter_next(di) will return
 2507  *     the first device_t in the device tree, or NULL if there are
 2508  *     no devices.
 2509  *
 2510  *     `flags' is one or more of DEVITER_F_RW, indicating that the
 2511  *     caller intends to modify the device tree by calling
 2512  *     config_detach(9) on devices in the order that the iterator
 2513  *     returns them; DEVITER_F_ROOT_FIRST, asking for the devices
 2514  *     nearest the "root" of the device tree to be returned, first;
 2515  *     DEVITER_F_LEAVES_FIRST, asking for the devices furthest from
 2516  *     the root of the device tree, first; and DEVITER_F_SHUTDOWN,
 2517  *     indicating both that deviter_init() should not respect any
 2518  *     locks on the device tree, and that deviter_next(di) may run
 2519  *     in more than one LWP before the walk has finished.
 2520  *
 2521  *     Only one DEVITER_F_RW iterator may be in the device tree at
 2522  *     once.
 2523  *
 2524  *     DEVITER_F_SHUTDOWN implies DEVITER_F_RW.
 2525  *
 2526  *     Results are undefined if the flags DEVITER_F_ROOT_FIRST and
 2527  *     DEVITER_F_LEAVES_FIRST are used in combination.
 2528  *
 2529  * deviter_first(di, flags): initialize the device iterator `di'
 2530  *     and return the first device_t in the device tree, or NULL
 2531  *     if there are no devices.  The statement
 2532  *
 2533  *         dv = deviter_first(di);
 2534  *
 2535  *     is shorthand for
 2536  *
 2537  *         deviter_init(di);
 2538  *         dv = deviter_next(di);
 2539  *
 2540  * deviter_next(di): return the next device_t in the device tree,
 2541  *     or NULL if there are no more devices.  deviter_next(di)
 2542  *     is undefined if `di' was not initialized with deviter_init() or
 2543  *     deviter_first().
 2544  *
 2545  * deviter_release(di): stops iteration (subsequent calls to
 2546  *     deviter_next() will return NULL), releases any locks and
 2547  *     resources held by the device iterator.
 2548  *
 2549  * Device iteration does not return device_t's in any particular
 2550  * order.  An iterator will never return the same device_t twice.
 2551  * Device iteration is guaranteed to complete---i.e., if deviter_next(di)
 2552  * is called repeatedly on the same `di', it will eventually return
 2553  * NULL.  It is ok to attach/detach devices during device iteration.
 2554  */
 2555 void
 2556 deviter_init(deviter_t *di, deviter_flags_t flags)
 2557 {
 2558         device_t dv;
 2559         bool rw;
 2560 
 2561         mutex_enter(&alldevs_mtx);
 2562         if ((flags & DEVITER_F_SHUTDOWN) != 0) {
 2563                 flags |= DEVITER_F_RW;
 2564                 alldevs_nwrite++;
 2565                 alldevs_writer = NULL;
 2566                 alldevs_nread = 0;
 2567         } else {
 2568                 rw = (flags & DEVITER_F_RW) != 0;
 2569 
 2570                 if (alldevs_nwrite > 0 && alldevs_writer == NULL)
 2571                         ;
 2572                 else while ((alldevs_nwrite != 0 && alldevs_writer != curlwp) ||
 2573                        (rw && alldevs_nread != 0))
 2574                         cv_wait(&alldevs_cv, &alldevs_mtx);
 2575 
 2576                 if (rw) {
 2577                         if (alldevs_nwrite++ == 0)
 2578                                 alldevs_writer = curlwp;
 2579                 } else
 2580                         alldevs_nread++;
 2581         }
 2582         mutex_exit(&alldevs_mtx);
 2583 
 2584         memset(di, 0, sizeof(*di));
 2585 
 2586         di->di_flags = flags;
 2587 
 2588         switch (di->di_flags & (DEVITER_F_LEAVES_FIRST|DEVITER_F_ROOT_FIRST)) {
 2589         case DEVITER_F_LEAVES_FIRST:
 2590                 TAILQ_FOREACH(dv, &alldevs, dv_list)
 2591                         di->di_curdepth = MAX(di->di_curdepth, dv->dv_depth);
 2592                 break;
 2593         case DEVITER_F_ROOT_FIRST:
 2594                 TAILQ_FOREACH(dv, &alldevs, dv_list)
 2595                         di->di_maxdepth = MAX(di->di_maxdepth, dv->dv_depth);
 2596                 break;
 2597         default:
 2598                 break;
 2599         }
 2600 
 2601         deviter_reinit(di);
 2602 }
 2603 
 2604 static void
 2605 deviter_reinit(deviter_t *di)
 2606 {
 2607         if ((di->di_flags & DEVITER_F_RW) != 0)
 2608                 di->di_prev = TAILQ_LAST(&alldevs, devicelist);
 2609         else
 2610                 di->di_prev = TAILQ_FIRST(&alldevs);
 2611 }
 2612 
 2613 device_t
 2614 deviter_first(deviter_t *di, deviter_flags_t flags)
 2615 {
 2616         deviter_init(di, flags);
 2617         return deviter_next(di);
 2618 }
 2619 
 2620 static device_t
 2621 deviter_next1(deviter_t *di)
 2622 {
 2623         device_t dv;
 2624 
 2625         dv = di->di_prev;
 2626 
 2627         if (dv == NULL)
 2628                 ;
 2629         else if ((di->di_flags & DEVITER_F_RW) != 0)
 2630                 di->di_prev = TAILQ_PREV(dv, devicelist, dv_list);
 2631         else
 2632                 di->di_prev = TAILQ_NEXT(dv, dv_list);
 2633 
 2634         return dv;
 2635 }
 2636 
 2637 device_t
 2638 deviter_next(deviter_t *di)
 2639 {
 2640         device_t dv = NULL;
 2641 
 2642         switch (di->di_flags & (DEVITER_F_LEAVES_FIRST|DEVITER_F_ROOT_FIRST)) {
 2643         case 0:
 2644                 return deviter_next1(di);
 2645         case DEVITER_F_LEAVES_FIRST:
 2646                 while (di->di_curdepth >= 0) {
 2647                         if ((dv = deviter_next1(di)) == NULL) {
 2648                                 di->di_curdepth--;
 2649                                 deviter_reinit(di);
 2650                         } else if (dv->dv_depth == di->di_curdepth)
 2651                                 break;
 2652                 }
 2653                 return dv;
 2654         case DEVITER_F_ROOT_FIRST:
 2655                 while (di->di_curdepth <= di->di_maxdepth) {
 2656                         if ((dv = deviter_next1(di)) == NULL) {
 2657                                 di->di_curdepth++;
 2658                                 deviter_reinit(di);
 2659                         } else if (dv->dv_depth == di->di_curdepth)
 2660                                 break;
 2661                 }
 2662                 return dv;
 2663         default:
 2664                 return NULL;
 2665         }
 2666 }
 2667 
 2668 void
 2669 deviter_release(deviter_t *di)
 2670 {
 2671         bool rw = (di->di_flags & DEVITER_F_RW) != 0;
 2672 
 2673         mutex_enter(&alldevs_mtx);
 2674         if (alldevs_nwrite > 0 && alldevs_writer == NULL)
 2675                 --alldevs_nwrite;
 2676         else {
 2677 
 2678                 if (rw) {
 2679                         if (--alldevs_nwrite == 0)
 2680                                 alldevs_writer = NULL;
 2681                 } else
 2682                         --alldevs_nread;
 2683 
 2684                 cv_signal(&alldevs_cv);
 2685         }
 2686         mutex_exit(&alldevs_mtx);
 2687 }

Cache object: 8cb73af4ef02d1453a37f7714d10d28d


[ 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.