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_bus.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 /*
    2  * Copyright (c) 1997,1998 Doug Rabson
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  * $FreeBSD$
   27  */
   28 
   29 #include "opt_bus.h"
   30 
   31 #include <sys/param.h>
   32 #include <sys/queue.h>
   33 #include <sys/malloc.h>
   34 #include <sys/kernel.h>
   35 #include <sys/module.h>
   36 #ifdef DEVICE_SYSCTLS
   37 #include <sys/sysctl.h>
   38 #endif
   39 #include <sys/bus_private.h>
   40 #include <sys/systm.h>
   41 #include <machine/bus.h>
   42 #include <sys/rman.h>
   43 #include <machine/stdarg.h>     /* for device_printf() */
   44 
   45 MALLOC_DEFINE(M_BUS, "bus", "Bus data structures");
   46 
   47 #ifdef BUS_DEBUG
   48 #define PDEBUG(a)       (printf(__FUNCTION__ ":%d: ", __LINE__), printf a, printf("\n"))
   49 #define DEVICENAME(d)   ((d)? device_get_name(d): "no device")
   50 #define DRIVERNAME(d)   ((d)? d->name : "no driver")
   51 #define DEVCLANAME(d)   ((d)? d->name : "no devclass")
   52 
   53 /* Produce the indenting, indent*2 spaces plus a '.' ahead of that to 
   54  * prevent syslog from deleting initial spaces
   55  */
   56 #define indentprintf(p) do { int iJ; printf("."); for (iJ=0; iJ<indent; iJ++) printf("  "); printf p ; } while(0)
   57 
   58 static void print_method_list(device_method_t *m, int indent);
   59 static void print_device_ops(device_ops_t ops, int indent);
   60 static void print_device_short(device_t dev, int indent);
   61 static void print_device(device_t dev, int indent);
   62 void print_device_tree_short(device_t dev, int indent);
   63 void print_device_tree(device_t dev, int indent);
   64 static void print_driver_short(driver_t *driver, int indent);
   65 static void print_driver(driver_t *driver, int indent);
   66 static void print_driver_list(driver_list_t drivers, int indent);
   67 static void print_devclass_short(devclass_t dc, int indent);
   68 static void print_devclass(devclass_t dc, int indent);
   69 void print_devclass_list_short(void);
   70 void print_devclass_list(void);
   71 
   72 #else
   73 /* Make the compiler ignore the function calls */
   74 #define PDEBUG(a)                       /* nop */
   75 #define DEVICENAME(d)                   /* nop */
   76 #define DRIVERNAME(d)                   /* nop */
   77 #define DEVCLANAME(d)                   /* nop */
   78 
   79 #define print_method_list(m,i)          /* nop */
   80 #define print_device_ops(o,i)           /* nop */
   81 #define print_device_short(d,i)         /* nop */
   82 #define print_device(d,i)               /* nop */
   83 #define print_device_tree_short(d,i)    /* nop */
   84 #define print_device_tree(d,i)          /* nop */
   85 #define print_driver_short(d,i)         /* nop */
   86 #define print_driver(d,i)               /* nop */
   87 #define print_driver_list(d,i)          /* nop */
   88 #define print_devclass_short(d,i)       /* nop */
   89 #define print_devclass(d,i)             /* nop */
   90 #define print_devclass_list_short()     /* nop */
   91 #define print_devclass_list()           /* nop */
   92 #endif
   93 
   94 #ifdef DEVICE_SYSCTLS
   95 static void device_register_oids(device_t dev);
   96 static void device_unregister_oids(device_t dev);
   97 #endif
   98 
   99 /*
  100  * Method table handling
  101  */
  102 static int error_method(void);
  103 static int next_method_offset = 1;
  104 
  105 LIST_HEAD(methodlist, method) methods;
  106 struct method {
  107     LIST_ENTRY(method) link;    /* linked list of methods */
  108     int offset;                 /* offset in method table */
  109     int refs;                   /* count of device_op_desc users */
  110     devop_t deflt;              /* default implementation */
  111     char* name;                 /* unique name of method */
  112 };
  113 
  114 static void
  115 register_method(struct device_op_desc *desc)
  116 {
  117     struct method* m;
  118 
  119     if (desc->method) {
  120         desc->method->refs++;
  121         return;
  122     }
  123 
  124     /*
  125      * Make sure that desc->deflt is always valid to simplify dispatch.
  126      */
  127     if (!desc->deflt)
  128         desc->deflt = error_method;
  129 
  130     for (m = LIST_FIRST(&methods); m; m = LIST_NEXT(m, link)) {
  131         if (!strcmp(m->name, desc->name)) {
  132             desc->offset = m->offset;
  133             desc->method = m;
  134             m->refs++;
  135             PDEBUG(("method %p has the same name, %s, with offset %d",
  136                     (void *)m, desc->name, desc->offset));
  137             return;
  138         }
  139     }
  140 
  141     m = (struct method *) malloc(sizeof(struct method)
  142                                  + strlen(desc->name) + 1,
  143                                  M_BUS, M_NOWAIT);
  144     if (!m)
  145             panic("register_method: out of memory");
  146     bzero(m, sizeof(struct method) + strlen(desc->name) + 1);
  147     m->offset = next_method_offset++;
  148     m->refs = 1;
  149     m->deflt = desc->deflt;
  150     m->name = (char*) (m + 1);
  151     strcpy(m->name, desc->name);
  152     LIST_INSERT_HEAD(&methods, m, link);
  153 
  154     desc->offset = m->offset;
  155     desc->method = m;
  156 }
  157 
  158 static void
  159 unregister_method(struct device_op_desc *desc)
  160 {
  161     struct method *m = desc->method;
  162     m->refs--;
  163     if (m->refs == 0) {
  164         PDEBUG(("method %s, reached refcount 0", desc->name));
  165         LIST_REMOVE(m, link);
  166         free(m, M_BUS);
  167         desc->method = 0;
  168     }
  169 }
  170 
  171 static int error_method(void)
  172 {
  173     return ENXIO;
  174 }
  175 
  176 static struct device_ops null_ops = {
  177     1, 
  178     { error_method }
  179 };
  180 
  181 static void
  182 compile_methods(driver_t *driver)
  183 {
  184     device_ops_t ops;
  185     struct device_method *m;
  186     struct method *cm;
  187     int i;
  188 
  189     /*
  190      * First register any methods which need it.
  191      */
  192     for (i = 0, m = driver->methods; m->desc; i++, m++)
  193         register_method(m->desc);
  194 
  195     /*
  196      * Then allocate the compiled op table.
  197      */
  198     ops = malloc(sizeof(struct device_ops) + (next_method_offset-1) * sizeof(devop_t),
  199                  M_BUS, M_NOWAIT);
  200     if (!ops)
  201         panic("compile_methods: out of memory");
  202     bzero(ops, sizeof(struct device_ops) + (next_method_offset-1) * sizeof(devop_t));
  203 
  204     ops->maxoffset = next_method_offset;
  205     /* Fill in default methods and then overwrite with driver methods */
  206     for (i = 0; i < next_method_offset; i++)
  207         ops->methods[i] = error_method;
  208     for (cm = LIST_FIRST(&methods); cm; cm = LIST_NEXT(cm, link)) {
  209         if (cm->deflt)
  210             ops->methods[cm->offset] = cm->deflt;
  211     }
  212     for (i = 0, m = driver->methods; m->desc; i++, m++)
  213         ops->methods[m->desc->offset] = m->func;
  214     PDEBUG(("%s has %d method%s, wasting %d bytes",
  215                 DRIVERNAME(driver), i, (i==1?"":"s"),
  216                 (next_method_offset-i)*sizeof(devop_t)));
  217 
  218     driver->ops = ops;
  219 }
  220 
  221 static void
  222 free_methods(driver_t *driver)
  223 {
  224     int i;
  225     struct device_method *m;
  226 
  227     /*
  228      * Unregister any methods which are no longer used.
  229      */
  230     for (i = 0, m = driver->methods; m->desc; i++, m++)
  231         unregister_method(m->desc);
  232 
  233     /*
  234      * Free memory and clean up.
  235      */
  236     free(driver->ops, M_BUS);
  237     driver->ops = 0;
  238 }
  239 
  240 /*
  241  * Devclass implementation
  242  */
  243 
  244 static devclass_list_t devclasses = TAILQ_HEAD_INITIALIZER(devclasses);
  245 
  246 static devclass_t
  247 devclass_find_internal(const char *classname, int create)
  248 {
  249     devclass_t dc;
  250 
  251     PDEBUG(("looking for %s", classname));
  252     if (!classname)
  253         return NULL;
  254 
  255     for (dc = TAILQ_FIRST(&devclasses); dc; dc = TAILQ_NEXT(dc, link))
  256         if (!strcmp(dc->name, classname))
  257             return dc;
  258 
  259     PDEBUG(("%s not found%s", classname, (create? ", creating": "")));
  260     if (create) {
  261         dc = malloc(sizeof(struct devclass) + strlen(classname) + 1,
  262                     M_BUS, M_NOWAIT);
  263         if (!dc)
  264             return NULL;
  265         bzero(dc, sizeof(struct devclass) + strlen(classname) + 1);
  266         dc->name = (char*) (dc + 1);
  267         strcpy(dc->name, classname);
  268         dc->devices = NULL;
  269         dc->maxunit = 0;
  270         TAILQ_INIT(&dc->drivers);
  271         TAILQ_INSERT_TAIL(&devclasses, dc, link);
  272     }
  273 
  274     return dc;
  275 }
  276 
  277 devclass_t
  278 devclass_create(const char *classname)
  279 {
  280     return devclass_find_internal(classname, TRUE);
  281 }
  282 
  283 devclass_t
  284 devclass_find(const char *classname)
  285 {
  286     return devclass_find_internal(classname, FALSE);
  287 }
  288 
  289 int
  290 devclass_add_driver(devclass_t dc, driver_t *driver)
  291 {
  292     driverlink_t dl;
  293     int i;
  294 
  295     PDEBUG(("%s", DRIVERNAME(driver)));
  296 
  297     dl = malloc(sizeof *dl, M_BUS, M_NOWAIT);
  298     if (!dl)
  299         return ENOMEM;
  300     bzero(dl, sizeof *dl);
  301 
  302     /*
  303      * Compile the driver's methods.
  304      */
  305     if (!driver->ops)
  306         compile_methods(driver);
  307 
  308     /*
  309      * Make sure the devclass which the driver is implementing exists.
  310      */
  311     devclass_find_internal(driver->name, TRUE);
  312 
  313     dl->driver = driver;
  314     TAILQ_INSERT_TAIL(&dc->drivers, dl, link);
  315     driver->refs++;
  316 
  317     /*
  318      * Call BUS_DRIVER_ADDED for any existing busses in this class.
  319      */
  320     for (i = 0; i < dc->maxunit; i++)
  321         if (dc->devices[i])
  322             BUS_DRIVER_ADDED(dc->devices[i], driver);
  323 
  324     return 0;
  325 }
  326 
  327 int
  328 devclass_delete_driver(devclass_t busclass, driver_t *driver)
  329 {
  330     devclass_t dc = devclass_find(driver->name);
  331     driverlink_t dl;
  332     device_t dev;
  333     int i;
  334     int error;
  335 
  336     PDEBUG(("%s from devclass %s", driver->name, DEVCLANAME(busclass)));
  337 
  338     if (!dc)
  339         return 0;
  340 
  341     /*
  342      * Find the link structure in the bus' list of drivers.
  343      */
  344     for (dl = TAILQ_FIRST(&busclass->drivers); dl;
  345          dl = TAILQ_NEXT(dl, link)) {
  346         if (dl->driver == driver)
  347             break;
  348     }
  349 
  350     if (!dl) {
  351         PDEBUG(("%s not found in %s list", driver->name, busclass->name));
  352         return ENOENT;
  353     }
  354 
  355     /*
  356      * Disassociate from any devices.  We iterate through all the
  357      * devices in the devclass of the driver and detach any which are
  358      * using the driver and which have a parent in the devclass which
  359      * we are deleting from.
  360      *
  361      * Note that since a driver can be in multiple devclasses, we
  362      * should not detach devices which are not children of devices in
  363      * the affected devclass.
  364      */
  365     for (i = 0; i < dc->maxunit; i++) {
  366         if (dc->devices[i]) {
  367             dev = dc->devices[i];
  368             if (dev->driver == driver
  369                 && dev->parent && dev->parent->devclass == busclass) {
  370                 if ((error = device_detach(dev)) != 0)
  371                     return error;
  372                 device_set_driver(dev, NULL);
  373             }
  374         }
  375     }
  376 
  377     TAILQ_REMOVE(&busclass->drivers, dl, link);
  378     free(dl, M_BUS);
  379 
  380     driver->refs--;
  381     if (driver->refs == 0)
  382         free_methods(driver);
  383 
  384     return 0;
  385 }
  386 
  387 static driverlink_t
  388 devclass_find_driver_internal(devclass_t dc, const char *classname)
  389 {
  390     driverlink_t dl;
  391 
  392     PDEBUG(("%s in devclass %s", classname, DEVCLANAME(dc)));
  393 
  394     for (dl = TAILQ_FIRST(&dc->drivers); dl; dl = TAILQ_NEXT(dl, link)) {
  395         if (!strcmp(dl->driver->name, classname))
  396             return dl;
  397     }
  398 
  399     PDEBUG(("not found"));
  400     return NULL;
  401 }
  402 
  403 driver_t *
  404 devclass_find_driver(devclass_t dc, const char *classname)
  405 {
  406     driverlink_t dl;
  407 
  408     dl = devclass_find_driver_internal(dc, classname);
  409     if (dl)
  410         return dl->driver;
  411     else
  412         return NULL;
  413 }
  414 
  415 const char *
  416 devclass_get_name(devclass_t dc)
  417 {
  418     return dc->name;
  419 }
  420 
  421 device_t
  422 devclass_get_device(devclass_t dc, int unit)
  423 {
  424     if (dc == NULL || unit < 0 || unit >= dc->maxunit)
  425         return NULL;
  426     return dc->devices[unit];
  427 }
  428 
  429 void *
  430 devclass_get_softc(devclass_t dc, int unit)
  431 {
  432     device_t dev;
  433 
  434     dev = devclass_get_device(dc, unit);
  435     if (!dev)
  436         return (NULL);
  437 
  438     return (device_get_softc(dev));
  439 }
  440 
  441 int
  442 devclass_get_devices(devclass_t dc, device_t **devlistp, int *devcountp)
  443 {
  444     int i;
  445     int count;
  446     device_t *list;
  447     
  448     count = 0;
  449     for (i = 0; i < dc->maxunit; i++)
  450         if (dc->devices[i])
  451             count++;
  452 
  453     list = malloc(count * sizeof(device_t), M_TEMP, M_NOWAIT);
  454     if (!list)
  455         return ENOMEM;
  456     bzero(list, count * sizeof(device_t));
  457 
  458     count = 0;
  459     for (i = 0; i < dc->maxunit; i++)
  460         if (dc->devices[i]) {
  461             list[count] = dc->devices[i];
  462             count++;
  463         }
  464 
  465     *devlistp = list;
  466     *devcountp = count;
  467 
  468     return 0;
  469 }
  470 
  471 int
  472 devclass_get_maxunit(devclass_t dc)
  473 {
  474     return dc->maxunit;
  475 }
  476 
  477 static int
  478 devclass_alloc_unit(devclass_t dc, int *unitp)
  479 {
  480     int unit = *unitp;
  481 
  482     PDEBUG(("unit %d in devclass %s", unit, DEVCLANAME(dc)));
  483 
  484     /* If we have been given a wired unit number, check for existing device */
  485     if (unit != -1) {
  486         if (unit >= 0 && unit < dc->maxunit && dc->devices[unit] != NULL) {
  487             if (bootverbose)
  488                 printf("%s-: %s%d exists, using next available unit number\n",
  489                        dc->name, dc->name, unit);
  490             /* find the next available slot */
  491             while (++unit < dc->maxunit && dc->devices[unit] != NULL)
  492                 ;
  493         }
  494     }
  495     else {
  496         /* Unwired device, find the next available slot for it */
  497         unit = 0;
  498         while (unit < dc->maxunit && dc->devices[unit] != NULL)
  499             unit++;
  500     }
  501 
  502     /*
  503      * We've selected a unit beyond the length of the table, so let's extend
  504      * the table to make room for all units up to and including this one.
  505      */
  506     if (unit >= dc->maxunit) {
  507         device_t *newlist;
  508         int newsize;
  509 
  510         newsize = roundup((unit + 1), MINALLOCSIZE / sizeof(device_t));
  511         newlist = malloc(sizeof(device_t) * newsize, M_BUS, M_NOWAIT);
  512         if (!newlist)
  513             return ENOMEM;
  514         bcopy(dc->devices, newlist, sizeof(device_t) * dc->maxunit);
  515         bzero(newlist + dc->maxunit,
  516               sizeof(device_t) * (newsize - dc->maxunit));
  517         if (dc->devices)
  518             free(dc->devices, M_BUS);
  519         dc->devices = newlist;
  520         dc->maxunit = newsize;
  521     }
  522     PDEBUG(("now: unit %d in devclass %s", unit, DEVCLANAME(dc)));
  523 
  524     *unitp = unit;
  525     return 0;
  526 }
  527 
  528 static int
  529 devclass_add_device(devclass_t dc, device_t dev)
  530 {
  531     int buflen, error;
  532 
  533     PDEBUG(("%s in devclass %s", DEVICENAME(dev), DEVCLANAME(dc)));
  534 
  535     buflen = strlen(dc->name) + 5;
  536     dev->nameunit = malloc(buflen, M_BUS, M_NOWAIT);
  537     if (!dev->nameunit)
  538         return ENOMEM;
  539     bzero(dev->nameunit, buflen);
  540 
  541     if ((error = devclass_alloc_unit(dc, &dev->unit)) != 0) {
  542         free(dev->nameunit, M_BUS);
  543         dev->nameunit = NULL;
  544         return error;
  545     }
  546     dc->devices[dev->unit] = dev;
  547     dev->devclass = dc;
  548     snprintf(dev->nameunit, buflen, "%s%d", dc->name, dev->unit);
  549 
  550 #ifdef DEVICE_SYSCTLS
  551     device_register_oids(dev);
  552 #endif
  553 
  554     return 0;
  555 }
  556 
  557 static int
  558 devclass_delete_device(devclass_t dc, device_t dev)
  559 {
  560     if (!dc || !dev)
  561         return 0;
  562 
  563     PDEBUG(("%s in devclass %s", DEVICENAME(dev), DEVCLANAME(dc)));
  564 
  565     if (dev->devclass != dc
  566         || dc->devices[dev->unit] != dev)
  567         panic("devclass_delete_device: inconsistent device class");
  568     dc->devices[dev->unit] = NULL;
  569     if (dev->flags & DF_WILDCARD)
  570         dev->unit = -1;
  571     dev->devclass = NULL;
  572     free(dev->nameunit, M_BUS);
  573     dev->nameunit = NULL;
  574 
  575 #ifdef DEVICE_SYSCTLS
  576     device_unregister_oids(dev);
  577 #endif
  578 
  579     return 0;
  580 }
  581 
  582 static device_t
  583 make_device(device_t parent, const char *name, int unit)
  584 {
  585     device_t dev;
  586     devclass_t dc;
  587 
  588     PDEBUG(("%s at %s as unit %d", name, DEVICENAME(parent), unit));
  589 
  590     if (name) {
  591         dc = devclass_find_internal(name, TRUE);
  592         if (!dc) {
  593             printf("make_device: can't find device class %s\n", name);
  594             return NULL;
  595         }
  596     } else
  597         dc = NULL;
  598 
  599     dev = malloc(sizeof(struct device), M_BUS, M_NOWAIT);
  600     if (!dev)
  601         return 0;
  602     bzero(dev, sizeof(struct device));
  603 
  604     dev->parent = parent;
  605     TAILQ_INIT(&dev->children);
  606     dev->ops = &null_ops;
  607     dev->driver = NULL;
  608     dev->devclass = NULL;
  609     dev->unit = unit;
  610     dev->nameunit = NULL;
  611     dev->desc = NULL;
  612     dev->busy = 0;
  613     dev->devflags = 0;
  614     dev->flags = DF_ENABLED;
  615     dev->order = 0;
  616     if (unit == -1)
  617         dev->flags |= DF_WILDCARD;
  618     if (name) {
  619         dev->flags |= DF_FIXEDCLASS;
  620         devclass_add_device(dc, dev);
  621     }
  622     dev->ivars = NULL;
  623     dev->softc = NULL;
  624 
  625     dev->state = DS_NOTPRESENT;
  626 
  627     return dev;
  628 }
  629 
  630 static int
  631 device_print_child(device_t dev, device_t child)
  632 {
  633     int retval = 0;
  634 
  635     if (device_is_alive(child)) {
  636         retval += BUS_PRINT_CHILD(dev, child);
  637     } else
  638         retval += device_printf(child, " not found\n");
  639 
  640     return (retval);
  641 }
  642 
  643 device_t
  644 device_add_child(device_t dev, const char *name, int unit)
  645 {
  646     return device_add_child_ordered(dev, 0, name, unit);
  647 }
  648 
  649 device_t
  650 device_add_child_ordered(device_t dev, int order, const char *name, int unit)
  651 {
  652     device_t child;
  653     device_t place;
  654 
  655     PDEBUG(("%s at %s with order %d as unit %d",
  656             name, DEVICENAME(dev), order, unit));
  657 
  658     child = make_device(dev, name, unit);
  659     if (child == NULL)
  660         return child;
  661     child->order = order;
  662 
  663     TAILQ_FOREACH(place, &dev->children, link)
  664         if (place->order > order)
  665             break;
  666 
  667     if (place) {
  668         /*
  669          * The device 'place' is the first device whose order is
  670          * greater than the new child.
  671          */
  672         TAILQ_INSERT_BEFORE(place, child, link);
  673     } else {
  674         /*
  675          * The new child's order is greater or equal to the order of
  676          * any existing device. Add the child to the tail of the list.
  677          */
  678         TAILQ_INSERT_TAIL(&dev->children, child, link);
  679     }
  680 
  681     return child;
  682 }
  683 
  684 int
  685 device_delete_child(device_t dev, device_t child)
  686 {
  687     int error;
  688     device_t grandchild;
  689 
  690     PDEBUG(("%s from %s", DEVICENAME(child), DEVICENAME(dev)));
  691 
  692     /* remove children first */
  693     while ( (grandchild = TAILQ_FIRST(&child->children)) ) {
  694         error = device_delete_child(child, grandchild);
  695         if (error)
  696             return error;
  697     }
  698 
  699     if ((error = device_detach(child)) != 0)
  700         return error;
  701     if (child->devclass)
  702         devclass_delete_device(child->devclass, child);
  703     TAILQ_REMOVE(&dev->children, child, link);
  704     device_set_desc(child, NULL);
  705     free(child, M_BUS);
  706 
  707     return 0;
  708 }
  709 
  710 /*
  711  * Find only devices attached to this bus.
  712  */
  713 device_t
  714 device_find_child(device_t dev, const char *classname, int unit)
  715 {
  716     devclass_t dc;
  717     device_t child;
  718 
  719     dc = devclass_find(classname);
  720     if (!dc)
  721         return NULL;
  722 
  723     child = devclass_get_device(dc, unit);
  724     if (child && child->parent == dev)
  725         return child;
  726     return NULL;
  727 }
  728 
  729 static driverlink_t
  730 first_matching_driver(devclass_t dc, device_t dev)
  731 {
  732     if (dev->devclass)
  733         return devclass_find_driver_internal(dc, dev->devclass->name);
  734     else
  735         return TAILQ_FIRST(&dc->drivers);
  736 }
  737 
  738 static driverlink_t
  739 next_matching_driver(devclass_t dc, device_t dev, driverlink_t last)
  740 {
  741     if (dev->devclass) {
  742         driverlink_t dl;
  743         for (dl = TAILQ_NEXT(last, link); dl; dl = TAILQ_NEXT(dl, link))
  744             if (!strcmp(dev->devclass->name, dl->driver->name))
  745                 return dl;
  746         return NULL;
  747     } else
  748         return TAILQ_NEXT(last, link);
  749 }
  750 
  751 static int
  752 device_probe_child(device_t dev, device_t child)
  753 {
  754     devclass_t dc;
  755     driverlink_t best = 0;
  756     driverlink_t dl;
  757     int result, pri = 0;
  758     int hasclass = (child->devclass != 0);
  759 
  760     dc = dev->devclass;
  761     if (!dc)
  762         panic("device_probe_child: parent device has no devclass");
  763 
  764     if (child->state == DS_ALIVE)
  765         return 0;
  766 
  767     for (dl = first_matching_driver(dc, child);
  768          dl;
  769          dl = next_matching_driver(dc, child, dl)) {
  770         PDEBUG(("Trying %s", DRIVERNAME(dl->driver)));
  771         device_set_driver(child, dl->driver);
  772         if (!hasclass)
  773             device_set_devclass(child, dl->driver->name);
  774         result = DEVICE_PROBE(child);
  775         if (!hasclass)
  776             device_set_devclass(child, 0);
  777 
  778         /*
  779          * If the driver returns SUCCESS, there can be no higher match
  780          * for this device.
  781          */
  782         if (result == 0) {
  783             best = dl;
  784             pri = 0;
  785             break;
  786         }
  787 
  788         /*
  789          * The driver returned an error so it certainly doesn't match.
  790          */
  791         if (result > 0) {
  792             device_set_driver(child, 0);
  793             continue;
  794         }
  795 
  796         /*
  797          * A priority lower than SUCCESS, remember the best matching
  798          * driver. Initialise the value of pri for the first match.
  799          */
  800         if (best == 0 || result > pri) {
  801             best = dl;
  802             pri = result;
  803             continue;
  804         }
  805     }
  806 
  807     /*
  808      * If we found a driver, change state and initialise the devclass.
  809      */
  810     if (best) {
  811         if (!child->devclass)
  812             device_set_devclass(child, best->driver->name);
  813         device_set_driver(child, best->driver);
  814         if (pri < 0) {
  815             /*
  816              * A bit bogus. Call the probe method again to make sure
  817              * that we have the right description.
  818              */
  819             DEVICE_PROBE(child);
  820         }
  821         child->state = DS_ALIVE;
  822         return 0;
  823     }
  824 
  825     return ENXIO;
  826 }
  827 
  828 device_t
  829 device_get_parent(device_t dev)
  830 {
  831     return dev->parent;
  832 }
  833 
  834 int
  835 device_get_children(device_t dev, device_t **devlistp, int *devcountp)
  836 {
  837     int count;
  838     device_t child;
  839     device_t *list;
  840     
  841     count = 0;
  842     for (child = TAILQ_FIRST(&dev->children); child;
  843          child = TAILQ_NEXT(child, link))
  844         count++;
  845 
  846     list = malloc(count * sizeof(device_t), M_TEMP, M_NOWAIT);
  847     if (!list)
  848         return ENOMEM;
  849     bzero(list, count * sizeof(device_t));
  850 
  851     count = 0;
  852     for (child = TAILQ_FIRST(&dev->children); child;
  853          child = TAILQ_NEXT(child, link)) {
  854         list[count] = child;
  855         count++;
  856     }
  857 
  858     *devlistp = list;
  859     *devcountp = count;
  860 
  861     return 0;
  862 }
  863 
  864 driver_t *
  865 device_get_driver(device_t dev)
  866 {
  867     return dev->driver;
  868 }
  869 
  870 devclass_t
  871 device_get_devclass(device_t dev)
  872 {
  873     return dev->devclass;
  874 }
  875 
  876 const char *
  877 device_get_name(device_t dev)
  878 {
  879     if (dev->devclass)
  880         return devclass_get_name(dev->devclass);
  881     return NULL;
  882 }
  883 
  884 const char *
  885 device_get_nameunit(device_t dev)
  886 {
  887     return dev->nameunit;
  888 }
  889 
  890 int
  891 device_get_unit(device_t dev)
  892 {
  893     return dev->unit;
  894 }
  895 
  896 const char *
  897 device_get_desc(device_t dev)
  898 {
  899     return dev->desc;
  900 }
  901 
  902 u_int32_t
  903 device_get_flags(device_t dev)
  904 {
  905     return dev->devflags;
  906 }
  907 
  908 int
  909 device_print_prettyname(device_t dev)
  910 {
  911     const char *name = device_get_name(dev);
  912 
  913     if (name == 0)
  914         return printf("unknown: ");
  915     else
  916         return printf("%s%d: ", name, device_get_unit(dev));
  917 }
  918 
  919 int
  920 device_printf(device_t dev, const char * fmt, ...)
  921 {
  922     va_list ap;
  923     int retval;
  924 
  925     retval = device_print_prettyname(dev);
  926     va_start(ap, fmt);
  927     retval += vprintf(fmt, ap);
  928     va_end(ap);
  929     return retval;
  930 }
  931 
  932 static void
  933 device_set_desc_internal(device_t dev, const char* desc, int copy)
  934 {
  935     if (dev->desc && (dev->flags & DF_DESCMALLOCED)) {
  936         free(dev->desc, M_BUS);
  937         dev->flags &= ~DF_DESCMALLOCED;
  938         dev->desc = NULL;
  939     }
  940 
  941     if (copy && desc) {
  942         dev->desc = malloc(strlen(desc) + 1, M_BUS, M_NOWAIT);
  943         if (dev->desc) {
  944             strcpy(dev->desc, desc);
  945             dev->flags |= DF_DESCMALLOCED;
  946         }
  947     } else
  948         /* Avoid a -Wcast-qual warning */
  949         dev->desc = (char *)(uintptr_t) desc;
  950 
  951 #ifdef DEVICE_SYSCTLS
  952     {
  953         struct sysctl_oid *oid = &dev->oid[1];
  954         oid->oid_arg1 = dev->desc ? dev->desc : "";
  955         oid->oid_arg2 = dev->desc ? strlen(dev->desc) : 0;
  956     }
  957 #endif
  958 }
  959 
  960 void
  961 device_set_desc(device_t dev, const char* desc)
  962 {
  963     device_set_desc_internal(dev, desc, FALSE);
  964 }
  965 
  966 void
  967 device_set_desc_copy(device_t dev, const char* desc)
  968 {
  969     device_set_desc_internal(dev, desc, TRUE);
  970 }
  971 
  972 void
  973 device_set_flags(device_t dev, u_int32_t flags)
  974 {
  975     dev->devflags = flags;
  976 }
  977 
  978 void *
  979 device_get_softc(device_t dev)
  980 {
  981     return dev->softc;
  982 }
  983 
  984 void
  985 device_set_softc(device_t dev, void *softc)
  986 {
  987     if (dev->softc && !(dev->flags & DF_EXTERNALSOFTC))
  988         free(dev->softc, M_BUS);
  989     dev->softc = softc;
  990     if (dev->softc)
  991         dev->flags |= DF_EXTERNALSOFTC;
  992     else
  993         dev->flags &= ~DF_EXTERNALSOFTC;
  994 }
  995 
  996 void *
  997 device_get_ivars(device_t dev)
  998 {
  999     return dev->ivars;
 1000 }
 1001 
 1002 void
 1003 device_set_ivars(device_t dev, void * ivars)
 1004 {
 1005     if (!dev)
 1006         return;
 1007 
 1008     dev->ivars = ivars;
 1009 
 1010     return;
 1011 }
 1012 
 1013 device_state_t
 1014 device_get_state(device_t dev)
 1015 {
 1016     return dev->state;
 1017 }
 1018 
 1019 void
 1020 device_enable(device_t dev)
 1021 {
 1022     dev->flags |= DF_ENABLED;
 1023 }
 1024 
 1025 void
 1026 device_disable(device_t dev)
 1027 {
 1028     dev->flags &= ~DF_ENABLED;
 1029 }
 1030 
 1031 void
 1032 device_busy(device_t dev)
 1033 {
 1034     if (dev->state < DS_ATTACHED)
 1035         panic("device_busy: called for unattached device");
 1036     if (dev->busy == 0 && dev->parent)
 1037         device_busy(dev->parent);
 1038     dev->busy++;
 1039     dev->state = DS_BUSY;
 1040 }
 1041 
 1042 void
 1043 device_unbusy(device_t dev)
 1044 {
 1045     if (dev->state != DS_BUSY)
 1046         panic("device_unbusy: called for non-busy device");
 1047     dev->busy--;
 1048     if (dev->busy == 0) {
 1049         if (dev->parent)
 1050             device_unbusy(dev->parent);
 1051         dev->state = DS_ATTACHED;
 1052     }
 1053 }
 1054 
 1055 void
 1056 device_quiet(device_t dev)
 1057 {
 1058     dev->flags |= DF_QUIET;
 1059 }
 1060 
 1061 void
 1062 device_verbose(device_t dev)
 1063 {
 1064     dev->flags &= ~DF_QUIET;
 1065 }
 1066 
 1067 int
 1068 device_is_quiet(device_t dev)
 1069 {
 1070     return (dev->flags & DF_QUIET) != 0;
 1071 }
 1072 
 1073 int
 1074 device_is_enabled(device_t dev)
 1075 {
 1076     return (dev->flags & DF_ENABLED) != 0;
 1077 }
 1078 
 1079 int
 1080 device_is_alive(device_t dev)
 1081 {
 1082     return dev->state >= DS_ALIVE;
 1083 }
 1084 
 1085 int
 1086 device_is_attached(device_t dev)
 1087 {
 1088         return (dev->state >= DS_ATTACHED);
 1089 }
 1090 
 1091 int
 1092 device_set_devclass(device_t dev, const char *classname)
 1093 {
 1094     devclass_t dc;
 1095 
 1096     if (!classname) {
 1097         if (dev->devclass)
 1098             devclass_delete_device(dev->devclass, dev);
 1099         return 0;
 1100     }
 1101 
 1102     if (dev->devclass) {
 1103         printf("device_set_devclass: device class already set\n");
 1104         return EINVAL;
 1105     }
 1106 
 1107     dc = devclass_find_internal(classname, TRUE);
 1108     if (!dc)
 1109         return ENOMEM;
 1110 
 1111     return devclass_add_device(dc, dev);
 1112 }
 1113 
 1114 int
 1115 device_set_driver(device_t dev, driver_t *driver)
 1116 {
 1117     if (dev->state >= DS_ATTACHED)
 1118         return EBUSY;
 1119 
 1120     if (dev->driver == driver)
 1121         return 0;
 1122 
 1123     if (dev->softc && !(dev->flags & DF_EXTERNALSOFTC)) {
 1124         free(dev->softc, M_BUS);
 1125         dev->softc = NULL;
 1126     }
 1127     dev->ops = &null_ops;
 1128     dev->driver = driver;
 1129     if (driver) {
 1130         dev->ops = driver->ops;
 1131         if (!(dev->flags & DF_EXTERNALSOFTC)) {
 1132             dev->softc = malloc(driver->softc, M_BUS, M_NOWAIT);
 1133             if (!dev->softc) {
 1134                 dev->ops = &null_ops;
 1135                 dev->driver = NULL;
 1136                 return ENOMEM;
 1137             }
 1138             bzero(dev->softc, driver->softc);
 1139         }
 1140     }
 1141     return 0;
 1142 }
 1143 
 1144 int
 1145 device_probe_and_attach(device_t dev)
 1146 {
 1147     device_t bus = dev->parent;
 1148     int error = 0;
 1149     int hasclass = (dev->devclass != 0);
 1150 
 1151     if (dev->state >= DS_ALIVE)
 1152         return 0;
 1153 
 1154     if (dev->flags & DF_ENABLED) {
 1155         error = device_probe_child(bus, dev);
 1156         if (!error) {
 1157             if (!device_is_quiet(dev))
 1158                 device_print_child(bus, dev);
 1159             error = DEVICE_ATTACH(dev);
 1160             if (!error)
 1161                 dev->state = DS_ATTACHED;
 1162             else {
 1163                 printf("device_probe_and_attach: %s%d attach returned %d\n",
 1164                        dev->driver->name, dev->unit, error);
 1165                 /* Unset the class that was set in device_probe_child */
 1166                 if (!hasclass)
 1167                     device_set_devclass(dev, 0);
 1168                 device_set_driver(dev, NULL);
 1169                 dev->state = DS_NOTPRESENT;
 1170             }
 1171         } else {
 1172             if (!(dev->flags & DF_DONENOMATCH)) {
 1173                 BUS_PROBE_NOMATCH(bus, dev);
 1174                 dev->flags |= DF_DONENOMATCH;
 1175             }
 1176         }
 1177     } else {
 1178         if (bootverbose) {
 1179             device_print_prettyname(dev);
 1180             printf("not probed (disabled)\n");
 1181         }
 1182     }
 1183 
 1184     return error;
 1185 }
 1186 
 1187 int
 1188 device_detach(device_t dev)
 1189 {
 1190     int error;
 1191 
 1192     PDEBUG(("%s", DEVICENAME(dev)));
 1193     if (dev->state == DS_BUSY)
 1194         return EBUSY;
 1195     if (dev->state != DS_ATTACHED)
 1196         return 0;
 1197 
 1198     if ((error = DEVICE_DETACH(dev)) != 0)
 1199         return error;
 1200     device_printf(dev, "detached\n");
 1201     if (dev->parent)
 1202         BUS_CHILD_DETACHED(dev->parent, dev);
 1203 
 1204     if (!(dev->flags & DF_FIXEDCLASS))
 1205         devclass_delete_device(dev->devclass, dev);
 1206 
 1207     dev->state = DS_NOTPRESENT;
 1208     device_set_driver(dev, NULL);
 1209 
 1210     return 0;
 1211 }
 1212 
 1213 int
 1214 device_shutdown(device_t dev)
 1215 {
 1216     if (dev->state < DS_ATTACHED)
 1217         return 0;
 1218     return DEVICE_SHUTDOWN(dev);
 1219 }
 1220 
 1221 int
 1222 device_set_unit(device_t dev, int unit)
 1223 {
 1224     devclass_t dc;
 1225     int err;
 1226 
 1227     dc = device_get_devclass(dev);
 1228     if (unit < dc->maxunit && dc->devices[unit])
 1229         return EBUSY;
 1230     err = devclass_delete_device(dc, dev);
 1231     if (err)
 1232         return err;
 1233     dev->unit = unit;
 1234     err = devclass_add_device(dc, dev);
 1235     if (err)
 1236         return err;
 1237     return 0;
 1238 }
 1239 
 1240 #ifdef DEVICE_SYSCTLS
 1241 
 1242 /*
 1243  * Sysctl nodes for devices.
 1244  */
 1245 
 1246 SYSCTL_NODE(_hw, OID_AUTO, devices, CTLFLAG_RW, 0, "A list of all devices");
 1247 
 1248 static int
 1249 sysctl_handle_children(SYSCTL_HANDLER_ARGS)
 1250 {
 1251     device_t dev = arg1;
 1252     device_t child;
 1253     int first = 1, error = 0;
 1254 
 1255     for (child = TAILQ_FIRST(&dev->children); child;
 1256          child = TAILQ_NEXT(child, link)) {
 1257         if (child->nameunit) {
 1258             if (!first) {
 1259                 error = SYSCTL_OUT(req, ",", 1);
 1260                 if (error) return error;
 1261             } else {
 1262                 first = 0;
 1263             }
 1264             error = SYSCTL_OUT(req, child->nameunit, strlen(child->nameunit));
 1265             if (error) return error;
 1266         }
 1267     }
 1268 
 1269     error = SYSCTL_OUT(req, "", 1);
 1270 
 1271     return error;
 1272 }
 1273 
 1274 static int
 1275 sysctl_handle_state(SYSCTL_HANDLER_ARGS)
 1276 {
 1277     device_t dev = arg1;
 1278 
 1279     switch (dev->state) {
 1280     case DS_NOTPRESENT:
 1281         return SYSCTL_OUT(req, "notpresent", sizeof("notpresent"));
 1282     case DS_ALIVE:
 1283         return SYSCTL_OUT(req, "alive", sizeof("alive"));
 1284     case DS_ATTACHED:
 1285         return SYSCTL_OUT(req, "attached", sizeof("attached"));
 1286     case DS_BUSY:
 1287         return SYSCTL_OUT(req, "busy", sizeof("busy"));
 1288     }
 1289 
 1290     return 0;
 1291 }
 1292 
 1293 static void
 1294 device_register_oids(device_t dev)
 1295 {
 1296     struct sysctl_oid* oid;
 1297 
 1298     oid = &dev->oid[0];
 1299     bzero(oid, sizeof(*oid));
 1300     oid->oid_parent = &sysctl__hw_devices_children;
 1301     oid->oid_number = OID_AUTO;
 1302     oid->oid_kind = CTLTYPE_NODE | CTLFLAG_RW;
 1303     oid->oid_arg1 = &dev->oidlist[0];
 1304     oid->oid_arg2 = 0;
 1305     oid->oid_name = dev->nameunit;
 1306     oid->oid_handler = 0;
 1307     oid->oid_fmt = "N";
 1308     SLIST_INIT(&dev->oidlist[0]);
 1309     sysctl_register_oid(oid);
 1310 
 1311     oid = &dev->oid[1];
 1312     bzero(oid, sizeof(*oid));
 1313     oid->oid_parent = &dev->oidlist[0];
 1314     oid->oid_number = OID_AUTO;
 1315     oid->oid_kind = CTLTYPE_STRING | CTLFLAG_RD;
 1316     oid->oid_arg1 = dev->desc ? dev->desc : "";
 1317     oid->oid_arg2 = dev->desc ? strlen(dev->desc) : 0;
 1318     oid->oid_name = "desc";
 1319     oid->oid_handler = sysctl_handle_string;
 1320     oid->oid_fmt = "A";
 1321     sysctl_register_oid(oid);
 1322 
 1323     oid = &dev->oid[2];
 1324     bzero(oid, sizeof(*oid));
 1325     oid->oid_parent = &dev->oidlist[0];
 1326     oid->oid_number = OID_AUTO;
 1327     oid->oid_kind = CTLTYPE_INT | CTLFLAG_RD;
 1328     oid->oid_arg1 = dev;
 1329     oid->oid_arg2 = 0;
 1330     oid->oid_name = "children";
 1331     oid->oid_handler = sysctl_handle_children;
 1332     oid->oid_fmt = "A";
 1333     sysctl_register_oid(oid);
 1334 
 1335     oid = &dev->oid[3];
 1336     bzero(oid, sizeof(*oid));
 1337     oid->oid_parent = &dev->oidlist[0];
 1338     oid->oid_number = OID_AUTO;
 1339     oid->oid_kind = CTLTYPE_INT | CTLFLAG_RD;
 1340     oid->oid_arg1 = dev;
 1341     oid->oid_arg2 = 0;
 1342     oid->oid_name = "state";
 1343     oid->oid_handler = sysctl_handle_state;
 1344     oid->oid_fmt = "A";
 1345     sysctl_register_oid(oid);
 1346 }
 1347 
 1348 static void
 1349 device_unregister_oids(device_t dev)
 1350 {
 1351     sysctl_unregister_oid(&dev->oid[0]);
 1352     sysctl_unregister_oid(&dev->oid[1]);
 1353     sysctl_unregister_oid(&dev->oid[2]);
 1354 }
 1355 
 1356 #endif
 1357 
 1358 /*======================================*/
 1359 /*
 1360  * Access functions for device resources.
 1361  */
 1362 
 1363 /* Supplied by config(8) in ioconf.c */
 1364 extern struct config_device config_devtab[];
 1365 extern int devtab_count;
 1366 
 1367 /* Runtime version */
 1368 struct config_device *devtab = config_devtab;
 1369 
 1370 static int
 1371 resource_new_name(const char *name, int unit)
 1372 {
 1373         struct config_device *new;
 1374 
 1375         new = malloc((devtab_count + 1) * sizeof(*new), M_TEMP, M_NOWAIT);
 1376         if (new == NULL)
 1377                 return -1;
 1378         if (devtab && devtab_count > 0)
 1379                 bcopy(devtab, new, devtab_count * sizeof(*new));
 1380         bzero(&new[devtab_count], sizeof(*new));
 1381         new[devtab_count].name = malloc(strlen(name) + 1, M_TEMP, M_NOWAIT);
 1382         if (new[devtab_count].name == NULL) {
 1383                 free(new, M_TEMP);
 1384                 return -1;
 1385         }
 1386         strcpy(new[devtab_count].name, name);
 1387         new[devtab_count].unit = unit;
 1388         new[devtab_count].resource_count = 0;
 1389         new[devtab_count].resources = NULL;
 1390         devtab = new;
 1391         return devtab_count++;
 1392 }
 1393 
 1394 static int
 1395 resource_new_resname(int j, const char *resname, resource_type type)
 1396 {
 1397         struct config_resource *new;
 1398         int i;
 1399 
 1400         i = devtab[j].resource_count;
 1401         new = malloc((i + 1) * sizeof(*new), M_TEMP, M_NOWAIT);
 1402         if (new == NULL)
 1403                 return -1;
 1404         if (devtab[j].resources && i > 0)
 1405                 bcopy(devtab[j].resources, new, i * sizeof(*new));
 1406         bzero(&new[i], sizeof(*new));
 1407         new[i].name = malloc(strlen(resname) + 1, M_TEMP, M_NOWAIT);
 1408         if (new[i].name == NULL) {
 1409                 free(new, M_TEMP);
 1410                 return -1;
 1411         }
 1412         strcpy(new[i].name, resname);
 1413         new[i].type = type;
 1414         if (devtab[j].resources)
 1415                 free(devtab[j].resources, M_TEMP);
 1416         devtab[j].resources = new;
 1417         devtab[j].resource_count = i + 1;
 1418         return i;
 1419 }
 1420 
 1421 static int
 1422 resource_match_string(int i, const char *resname, const char *value)
 1423 {
 1424         int j;
 1425         struct config_resource *res;
 1426 
 1427         for (j = 0, res = devtab[i].resources;
 1428              j < devtab[i].resource_count; j++, res++)
 1429                 if (!strcmp(res->name, resname)
 1430                     && res->type == RES_STRING
 1431                     && !strcmp(res->u.stringval, value))
 1432                         return j;
 1433         return -1;
 1434 }
 1435 
 1436 static int
 1437 resource_find(const char *name, int unit, const char *resname, 
 1438               struct config_resource **result)
 1439 {
 1440         int i, j;
 1441         struct config_resource *res;
 1442 
 1443         /*
 1444          * First check specific instances, then generic.
 1445          */
 1446         for (i = 0; i < devtab_count; i++) {
 1447                 if (devtab[i].unit < 0)
 1448                         continue;
 1449                 if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) {
 1450                         res = devtab[i].resources;
 1451                         for (j = 0; j < devtab[i].resource_count; j++, res++)
 1452                                 if (!strcmp(res->name, resname)) {
 1453                                         *result = res;
 1454                                         return 0;
 1455                                 }
 1456                 }
 1457         }
 1458         for (i = 0; i < devtab_count; i++) {
 1459                 if (devtab[i].unit >= 0)
 1460                         continue;
 1461                 /* XXX should this `&& devtab[i].unit == unit' be here? */
 1462                 /* XXX if so, then the generic match does nothing */
 1463                 if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) {
 1464                         res = devtab[i].resources;
 1465                         for (j = 0; j < devtab[i].resource_count; j++, res++)
 1466                                 if (!strcmp(res->name, resname)) {
 1467                                         *result = res;
 1468                                         return 0;
 1469                                 }
 1470                 }
 1471         }
 1472         return ENOENT;
 1473 }
 1474 
 1475 int
 1476 resource_int_value(const char *name, int unit, const char *resname, int *result)
 1477 {
 1478         int error;
 1479         struct config_resource *res;
 1480 
 1481         if ((error = resource_find(name, unit, resname, &res)) != 0)
 1482                 return error;
 1483         if (res->type != RES_INT)
 1484                 return EFTYPE;
 1485         *result = res->u.intval;
 1486         return 0;
 1487 }
 1488 
 1489 int
 1490 resource_long_value(const char *name, int unit, const char *resname,
 1491                     long *result)
 1492 {
 1493         int error;
 1494         struct config_resource *res;
 1495 
 1496         if ((error = resource_find(name, unit, resname, &res)) != 0)
 1497                 return error;
 1498         if (res->type != RES_LONG)
 1499                 return EFTYPE;
 1500         *result = res->u.longval;
 1501         return 0;
 1502 }
 1503 
 1504 int
 1505 resource_string_value(const char *name, int unit, const char *resname,
 1506                       char **result)
 1507 {
 1508         int error;
 1509         struct config_resource *res;
 1510 
 1511         if ((error = resource_find(name, unit, resname, &res)) != 0)
 1512                 return error;
 1513         if (res->type != RES_STRING)
 1514                 return EFTYPE;
 1515         *result = res->u.stringval;
 1516         return 0;
 1517 }
 1518 
 1519 int
 1520 resource_query_string(int i, const char *resname, const char *value)
 1521 {
 1522         if (i < 0)
 1523                 i = 0;
 1524         else
 1525                 i = i + 1;
 1526         for (; i < devtab_count; i++)
 1527                 if (resource_match_string(i, resname, value) >= 0)
 1528                         return i;
 1529         return -1;
 1530 }
 1531 
 1532 int
 1533 resource_locate(int i, const char *resname)
 1534 {
 1535         if (i < 0)
 1536                 i = 0;
 1537         else
 1538                 i = i + 1;
 1539         for (; i < devtab_count; i++)
 1540                 if (!strcmp(devtab[i].name, resname))
 1541                         return i;
 1542         return -1;
 1543 }
 1544 
 1545 int
 1546 resource_count(void)
 1547 {
 1548         return devtab_count;
 1549 }
 1550 
 1551 char *
 1552 resource_query_name(int i)
 1553 {
 1554         return devtab[i].name;
 1555 }
 1556 
 1557 int
 1558 resource_query_unit(int i)
 1559 {
 1560         return devtab[i].unit;
 1561 }
 1562 
 1563 static int
 1564 resource_create(const char *name, int unit, const char *resname,
 1565                 resource_type type, struct config_resource **result)
 1566 {
 1567         int i, j;
 1568         struct config_resource *res = NULL;
 1569 
 1570         for (i = 0; i < devtab_count; i++) {
 1571                 if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) {
 1572                         res = devtab[i].resources;
 1573                         break;
 1574                 }
 1575         }
 1576         if (res == NULL) {
 1577                 i = resource_new_name(name, unit);
 1578                 if (i < 0)
 1579                         return ENOMEM;
 1580                 res = devtab[i].resources;
 1581         }
 1582         for (j = 0; j < devtab[i].resource_count; j++, res++) {
 1583                 if (!strcmp(res->name, resname)) {
 1584                         *result = res;
 1585                         return 0;
 1586                 }
 1587         }
 1588         j = resource_new_resname(i, resname, type);
 1589         if (j < 0)
 1590                 return ENOMEM;
 1591         res = &devtab[i].resources[j];
 1592         *result = res;
 1593         return 0;
 1594 }
 1595 
 1596 int
 1597 resource_set_int(const char *name, int unit, const char *resname, int value)
 1598 {
 1599         int error;
 1600         struct config_resource *res;
 1601 
 1602         error = resource_create(name, unit, resname, RES_INT, &res);
 1603         if (error)
 1604                 return error;
 1605         if (res->type != RES_INT)
 1606                 return EFTYPE;
 1607         res->u.intval = value;
 1608         return 0;
 1609 }
 1610 
 1611 int
 1612 resource_set_long(const char *name, int unit, const char *resname, long value)
 1613 {
 1614         int error;
 1615         struct config_resource *res;
 1616 
 1617         error = resource_create(name, unit, resname, RES_LONG, &res);
 1618         if (error)
 1619                 return error;
 1620         if (res->type != RES_LONG)
 1621                 return EFTYPE;
 1622         res->u.longval = value;
 1623         return 0;
 1624 }
 1625 
 1626 int
 1627 resource_set_string(const char *name, int unit, const char *resname,
 1628                     const char *value)
 1629 {
 1630         int error;
 1631         struct config_resource *res;
 1632 
 1633         error = resource_create(name, unit, resname, RES_STRING, &res);
 1634         if (error)
 1635                 return error;
 1636         if (res->type != RES_STRING)
 1637                 return EFTYPE;
 1638         if (res->u.stringval)
 1639                 free(res->u.stringval, M_TEMP);
 1640         res->u.stringval = malloc(strlen(value) + 1, M_TEMP, M_NOWAIT);
 1641         if (res->u.stringval == NULL)
 1642                 return ENOMEM;
 1643         strcpy(res->u.stringval, value);
 1644         return 0;
 1645 }
 1646 
 1647 
 1648 static void
 1649 resource_cfgload(void *dummy __unused)
 1650 {
 1651         struct config_resource *res, *cfgres;
 1652         int i, j;
 1653         int error;
 1654         char *name, *resname;
 1655         int unit;
 1656         resource_type type;
 1657         char *stringval;
 1658         int config_devtab_count;
 1659 
 1660         config_devtab_count = devtab_count;
 1661         devtab = NULL;
 1662         devtab_count = 0;
 1663 
 1664         for (i = 0; i < config_devtab_count; i++) {
 1665                 name = config_devtab[i].name;
 1666                 unit = config_devtab[i].unit;
 1667 
 1668                 for (j = 0; j < config_devtab[i].resource_count; j++) {
 1669                         cfgres = config_devtab[i].resources;
 1670                         resname = cfgres[j].name;
 1671                         type = cfgres[j].type;
 1672                         error = resource_create(name, unit, resname, type,
 1673                                                 &res);
 1674                         if (error) {
 1675                                 printf("create resource %s%d: error %d\n",
 1676                                         name, unit, error);
 1677                                 continue;
 1678                         }
 1679                         if (res->type != type) {
 1680                                 printf("type mismatch %s%d: %d != %d\n",
 1681                                         name, unit, res->type, type);
 1682                                 continue;
 1683                         }
 1684                         switch (type) {
 1685                         case RES_INT:
 1686                                 res->u.intval = cfgres[j].u.intval;
 1687                                 break;
 1688                         case RES_LONG:
 1689                                 res->u.longval = cfgres[j].u.longval;
 1690                                 break;
 1691                         case RES_STRING:
 1692                                 if (res->u.stringval)
 1693                                         free(res->u.stringval, M_TEMP);
 1694                                 stringval = cfgres[j].u.stringval;
 1695                                 res->u.stringval = malloc(strlen(stringval) + 1,
 1696                                                           M_TEMP, M_NOWAIT);
 1697                                 if (res->u.stringval == NULL)
 1698                                         break;
 1699                                 strcpy(res->u.stringval, stringval);
 1700                                 break;
 1701                         default:
 1702                                 panic("unknown resource type %d\n", type);
 1703                         }
 1704                 }
 1705         }
 1706 }
 1707 SYSINIT(cfgload, SI_SUB_KMEM, SI_ORDER_ANY + 50, resource_cfgload, 0)
 1708 
 1709 
 1710 /*======================================*/
 1711 /*
 1712  * Some useful method implementations to make life easier for bus drivers.
 1713  */
 1714 
 1715 void
 1716 resource_list_init(struct resource_list *rl)
 1717 {
 1718         SLIST_INIT(rl);
 1719 }
 1720 
 1721 void
 1722 resource_list_free(struct resource_list *rl)
 1723 {
 1724     struct resource_list_entry *rle;
 1725 
 1726     while ((rle = SLIST_FIRST(rl)) != NULL) {
 1727         if (rle->res)
 1728             panic("resource_list_free: resource entry is busy");
 1729         SLIST_REMOVE_HEAD(rl, link);
 1730         free(rle, M_BUS);
 1731     }
 1732 }
 1733 
 1734 void
 1735 resource_list_add(struct resource_list *rl,
 1736                   int type, int rid,
 1737                   u_long start, u_long end, u_long count)
 1738 {
 1739     struct resource_list_entry *rle;
 1740 
 1741     rle = resource_list_find(rl, type, rid);
 1742     if (!rle) {
 1743         rle = malloc(sizeof(struct resource_list_entry), M_BUS, M_NOWAIT);
 1744         if (!rle)
 1745             panic("resource_list_add: can't record entry");
 1746         SLIST_INSERT_HEAD(rl, rle, link);
 1747         rle->type = type;
 1748         rle->rid = rid;
 1749         rle->res = NULL;
 1750     }
 1751 
 1752     if (rle->res)
 1753         panic("resource_list_add: resource entry is busy");
 1754 
 1755     rle->start = start;
 1756     rle->end = end;
 1757     rle->count = count;
 1758 }
 1759 
 1760 struct resource_list_entry*
 1761 resource_list_find(struct resource_list *rl,
 1762                    int type, int rid)
 1763 {
 1764     struct resource_list_entry *rle;
 1765 
 1766     SLIST_FOREACH(rle, rl, link)
 1767         if (rle->type == type && rle->rid == rid)
 1768             return rle;
 1769     return NULL;
 1770 }
 1771 
 1772 void
 1773 resource_list_delete(struct resource_list *rl,
 1774                      int type, int rid)
 1775 {
 1776     struct resource_list_entry *rle = resource_list_find(rl, type, rid);
 1777 
 1778     if (rle) {
 1779         SLIST_REMOVE(rl, rle, resource_list_entry, link);
 1780         free(rle, M_BUS);
 1781     }
 1782 }
 1783 
 1784 struct resource *
 1785 resource_list_alloc(struct resource_list *rl,
 1786                     device_t bus, device_t child,
 1787                     int type, int *rid,
 1788                     u_long start, u_long end,
 1789                     u_long count, u_int flags)
 1790 {
 1791     struct resource_list_entry *rle = 0;
 1792     int passthrough = (device_get_parent(child) != bus);
 1793     int isdefault = (start == 0UL && end == ~0UL);
 1794 
 1795     if (passthrough) {
 1796         return BUS_ALLOC_RESOURCE(device_get_parent(bus), child,
 1797                                   type, rid,
 1798                                   start, end, count, flags);
 1799     }
 1800 
 1801     rle = resource_list_find(rl, type, *rid);
 1802 
 1803     if (!rle)
 1804         return 0;               /* no resource of that type/rid */
 1805     if (rle->res)
 1806         panic("resource_list_alloc: resource entry is busy");
 1807 
 1808     if (isdefault) {
 1809         start = rle->start;
 1810         count = max(count, rle->count);
 1811         end = max(rle->end, start + count - 1);
 1812     }
 1813 
 1814     rle->res = BUS_ALLOC_RESOURCE(device_get_parent(bus), child,
 1815                                   type, rid, start, end, count, flags);
 1816 
 1817     /*
 1818      * Record the new range.
 1819      */
 1820     if (rle->res) {
 1821             rle->start = rman_get_start(rle->res);
 1822             rle->end = rman_get_end(rle->res);
 1823             rle->count = count;
 1824     }
 1825 
 1826     return rle->res;
 1827 }
 1828 
 1829 int
 1830 resource_list_release(struct resource_list *rl,
 1831                       device_t bus, device_t child,
 1832                       int type, int rid, struct resource *res)
 1833 {
 1834     struct resource_list_entry *rle = 0;
 1835     int passthrough = (device_get_parent(child) != bus);
 1836     int error;
 1837 
 1838     if (passthrough) {
 1839         return BUS_RELEASE_RESOURCE(device_get_parent(bus), child,
 1840                                     type, rid, res);
 1841     }
 1842 
 1843     rle = resource_list_find(rl, type, rid);
 1844 
 1845     if (!rle)
 1846         panic("resource_list_release: can't find resource");
 1847     if (!rle->res)
 1848         panic("resource_list_release: resource entry is not busy");
 1849 
 1850     error = BUS_RELEASE_RESOURCE(device_get_parent(bus), child,
 1851                                  type, rid, res);
 1852     if (error)
 1853         return error;
 1854 
 1855     rle->res = NULL;
 1856     return 0;
 1857 }
 1858 
 1859 int
 1860 resource_list_print_type(struct resource_list *rl, const char *name, int type,
 1861     const char *format)
 1862 {
 1863         struct resource_list_entry *rle;
 1864         int printed, retval;
 1865 
 1866         printed = 0;
 1867         retval = 0;
 1868         /* Yes, this is kinda cheating */
 1869         SLIST_FOREACH(rle, rl, link) {
 1870                 if (rle->type == type) {
 1871                         if (printed == 0)
 1872                                 retval += printf(" %s ", name);
 1873                         else
 1874                                 retval += printf(",");
 1875                         printed++;
 1876                         retval += printf(format, rle->start);
 1877                         if (rle->count > 1) {
 1878                                 retval += printf("-");
 1879                                 retval += printf(format, rle->start +
 1880                                                  rle->count - 1);
 1881                         }
 1882                 }
 1883         }
 1884         return (retval);
 1885 }
 1886 
 1887 /*
 1888  * Call DEVICE_IDENTIFY for each driver.
 1889  */
 1890 int
 1891 bus_generic_probe(device_t dev)
 1892 {
 1893     devclass_t dc = dev->devclass;
 1894     driverlink_t dl;
 1895 
 1896     for (dl = TAILQ_FIRST(&dc->drivers); dl; dl = TAILQ_NEXT(dl, link))
 1897         DEVICE_IDENTIFY(dl->driver, dev);
 1898 
 1899     return 0;
 1900 }
 1901 
 1902 int
 1903 bus_generic_attach(device_t dev)
 1904 {
 1905     device_t child;
 1906 
 1907     for (child = TAILQ_FIRST(&dev->children);
 1908          child; child = TAILQ_NEXT(child, link))
 1909         device_probe_and_attach(child);
 1910 
 1911     return 0;
 1912 }
 1913 
 1914 int
 1915 bus_generic_detach(device_t dev)
 1916 {
 1917     device_t child;
 1918     int error;
 1919 
 1920     if (dev->state != DS_ATTACHED)
 1921         return EBUSY;
 1922 
 1923     for (child = TAILQ_FIRST(&dev->children);
 1924          child; child = TAILQ_NEXT(child, link))
 1925         if ((error = device_detach(child)) != 0)
 1926             return error;
 1927 
 1928     return 0;
 1929 }
 1930 
 1931 int
 1932 bus_generic_shutdown(device_t dev)
 1933 {
 1934     device_t child;
 1935 
 1936     for (child = TAILQ_FIRST(&dev->children);
 1937          child; child = TAILQ_NEXT(child, link))
 1938         device_shutdown(child);
 1939 
 1940     return 0;
 1941 }
 1942 
 1943 int
 1944 bus_generic_suspend(device_t dev)
 1945 {
 1946         int             error;
 1947         device_t        child, child2;
 1948 
 1949         for (child = TAILQ_FIRST(&dev->children);
 1950              child; child = TAILQ_NEXT(child, link)) {
 1951                 error = DEVICE_SUSPEND(child);
 1952                 if (error) {
 1953                         for (child2 = TAILQ_FIRST(&dev->children);
 1954                              child2 && child2 != child; 
 1955                              child2 = TAILQ_NEXT(child2, link))
 1956                                 DEVICE_RESUME(child2);
 1957                         return (error);
 1958                 }
 1959         }
 1960         return 0;
 1961 }
 1962 
 1963 int
 1964 bus_generic_resume(device_t dev)
 1965 {
 1966         device_t        child;
 1967 
 1968         for (child = TAILQ_FIRST(&dev->children);
 1969              child; child = TAILQ_NEXT(child, link)) {
 1970                 DEVICE_RESUME(child);
 1971                 /* if resume fails, there's nothing we can usefully do... */
 1972         }
 1973         return 0;
 1974 }
 1975 
 1976 int
 1977 bus_print_child_header (device_t dev, device_t child)
 1978 {
 1979         int     retval = 0;
 1980 
 1981         if (device_get_desc(child)) { 
 1982                 retval += device_printf(child, "<%s>",
 1983                                        device_get_desc(child));      
 1984         } else {
 1985                 retval += printf("%s", device_get_nameunit(child));
 1986         }
 1987 
 1988         return (retval);
 1989 }
 1990 
 1991 int
 1992 bus_print_child_footer (device_t dev, device_t child)
 1993 {
 1994         return(printf(" on %s\n", device_get_nameunit(dev)));
 1995 }
 1996 
 1997 int
 1998 bus_generic_print_child(device_t dev, device_t child)
 1999 {
 2000         int     retval = 0;
 2001 
 2002         retval += bus_print_child_header(dev, child);
 2003         retval += bus_print_child_footer(dev, child);
 2004 
 2005         return (retval);
 2006 }
 2007 
 2008 int
 2009 bus_generic_read_ivar(device_t dev, device_t child, int index, 
 2010                       uintptr_t * result)
 2011 {
 2012     return ENOENT;
 2013 }
 2014 
 2015 int
 2016 bus_generic_write_ivar(device_t dev, device_t child, int index, 
 2017                        uintptr_t value)
 2018 {
 2019     return ENOENT;
 2020 }
 2021 
 2022 void
 2023 bus_generic_driver_added(device_t dev, driver_t *driver)
 2024 {
 2025     device_t child;
 2026 
 2027     DEVICE_IDENTIFY(driver, dev);
 2028     for (child = TAILQ_FIRST(&dev->children);
 2029          child; child = TAILQ_NEXT(child, link))
 2030         if (child->state == DS_NOTPRESENT)
 2031             device_probe_and_attach(child);
 2032 }
 2033 
 2034 int
 2035 bus_generic_setup_intr(device_t dev, device_t child, struct resource *irq, 
 2036                        int flags, driver_intr_t *intr, void *arg,
 2037                        void **cookiep)
 2038 {
 2039         /* Propagate up the bus hierarchy until someone handles it. */
 2040         if (dev->parent)
 2041                 return (BUS_SETUP_INTR(dev->parent, child, irq, flags,
 2042                                        intr, arg, cookiep));
 2043         else
 2044                 return (EINVAL);
 2045 }
 2046 
 2047 int
 2048 bus_generic_teardown_intr(device_t dev, device_t child, struct resource *irq,
 2049                           void *cookie)
 2050 {
 2051         /* Propagate up the bus hierarchy until someone handles it. */
 2052         if (dev->parent)
 2053                 return (BUS_TEARDOWN_INTR(dev->parent, child, irq, cookie));
 2054         else
 2055                 return (EINVAL);
 2056 }
 2057 
 2058 struct resource *
 2059 bus_generic_alloc_resource(device_t dev, device_t child, int type, int *rid,
 2060                            u_long start, u_long end, u_long count, u_int flags)
 2061 {
 2062         /* Propagate up the bus hierarchy until someone handles it. */
 2063         if (dev->parent)
 2064                 return (BUS_ALLOC_RESOURCE(dev->parent, child, type, rid, 
 2065                                            start, end, count, flags));
 2066         else
 2067                 return (NULL);
 2068 }
 2069 
 2070 int
 2071 bus_generic_release_resource(device_t dev, device_t child, int type, int rid,
 2072                              struct resource *r)
 2073 {
 2074         /* Propagate up the bus hierarchy until someone handles it. */
 2075         if (dev->parent)
 2076                 return (BUS_RELEASE_RESOURCE(dev->parent, child, type, rid, 
 2077                                              r));
 2078         else
 2079                 return (EINVAL);
 2080 }
 2081 
 2082 int
 2083 bus_generic_activate_resource(device_t dev, device_t child, int type, int rid,
 2084                               struct resource *r)
 2085 {
 2086         /* Propagate up the bus hierarchy until someone handles it. */
 2087         if (dev->parent)
 2088                 return (BUS_ACTIVATE_RESOURCE(dev->parent, child, type, rid, 
 2089                                               r));
 2090         else
 2091                 return (EINVAL);
 2092 }
 2093 
 2094 int
 2095 bus_generic_deactivate_resource(device_t dev, device_t child, int type,
 2096                                 int rid, struct resource *r)
 2097 {
 2098         /* Propagate up the bus hierarchy until someone handles it. */
 2099         if (dev->parent)
 2100                 return (BUS_DEACTIVATE_RESOURCE(dev->parent, child, type, rid,
 2101                                                 r));
 2102         else
 2103                 return (EINVAL);
 2104 }
 2105 
 2106 /*
 2107  * Some convenience functions to make it easier for drivers to use the
 2108  * resource-management functions.  All these really do is hide the
 2109  * indirection through the parent's method table, making for slightly
 2110  * less-wordy code.  In the future, it might make sense for this code
 2111  * to maintain some sort of a list of resources allocated by each device.
 2112  */
 2113 struct resource *
 2114 bus_alloc_resource(device_t dev, int type, int *rid, u_long start, u_long end,
 2115                    u_long count, u_int flags)
 2116 {
 2117         if (dev->parent == 0)
 2118                 return (0);
 2119         return (BUS_ALLOC_RESOURCE(dev->parent, dev, type, rid, start, end,
 2120                                    count, flags));
 2121 }
 2122 
 2123 int
 2124 bus_activate_resource(device_t dev, int type, int rid, struct resource *r)
 2125 {
 2126         if (dev->parent == 0)
 2127                 return (EINVAL);
 2128         return (BUS_ACTIVATE_RESOURCE(dev->parent, dev, type, rid, r));
 2129 }
 2130 
 2131 int
 2132 bus_deactivate_resource(device_t dev, int type, int rid, struct resource *r)
 2133 {
 2134         if (dev->parent == 0)
 2135                 return (EINVAL);
 2136         return (BUS_DEACTIVATE_RESOURCE(dev->parent, dev, type, rid, r));
 2137 }
 2138 
 2139 int
 2140 bus_release_resource(device_t dev, int type, int rid, struct resource *r)
 2141 {
 2142         if (dev->parent == 0)
 2143                 return (EINVAL);
 2144         return (BUS_RELEASE_RESOURCE(dev->parent, dev,
 2145                                      type, rid, r));
 2146 }
 2147 
 2148 int
 2149 bus_setup_intr(device_t dev, struct resource *r, int flags,
 2150                driver_intr_t handler, void *arg, void **cookiep)
 2151 {
 2152         if (dev->parent == 0)
 2153                 return (EINVAL);
 2154         return (BUS_SETUP_INTR(dev->parent, dev, r, flags,
 2155                                handler, arg, cookiep));
 2156 }
 2157 
 2158 int
 2159 bus_teardown_intr(device_t dev, struct resource *r, void *cookie)
 2160 {
 2161         if (dev->parent == 0)
 2162                 return (EINVAL);
 2163         return (BUS_TEARDOWN_INTR(dev->parent, dev, r, cookie));
 2164 }
 2165 
 2166 int
 2167 bus_set_resource(device_t dev, int type, int rid,
 2168                  u_long start, u_long count)
 2169 {
 2170         return BUS_SET_RESOURCE(device_get_parent(dev), dev, type, rid,
 2171                                 start, count);
 2172 }
 2173 
 2174 int
 2175 bus_get_resource(device_t dev, int type, int rid,
 2176                  u_long *startp, u_long *countp)
 2177 {
 2178         return BUS_GET_RESOURCE(device_get_parent(dev), dev, type, rid,
 2179                                 startp, countp);
 2180 }
 2181 
 2182 u_long
 2183 bus_get_resource_start(device_t dev, int type, int rid)
 2184 {
 2185         u_long start, count;
 2186         int error;
 2187 
 2188         error = BUS_GET_RESOURCE(device_get_parent(dev), dev, type, rid,
 2189                                  &start, &count);
 2190         if (error)
 2191                 return 0;
 2192         return start;
 2193 }
 2194 
 2195 u_long
 2196 bus_get_resource_count(device_t dev, int type, int rid)
 2197 {
 2198         u_long start, count;
 2199         int error;
 2200 
 2201         error = BUS_GET_RESOURCE(device_get_parent(dev), dev, type, rid,
 2202                                  &start, &count);
 2203         if (error)
 2204                 return 0;
 2205         return count;
 2206 }
 2207 
 2208 void
 2209 bus_delete_resource(device_t dev, int type, int rid)
 2210 {
 2211         BUS_DELETE_RESOURCE(device_get_parent(dev), dev, type, rid);
 2212 }
 2213 
 2214 static int
 2215 root_print_child(device_t dev, device_t child)
 2216 {
 2217         return (0);
 2218 }
 2219 
 2220 static int
 2221 root_setup_intr(device_t dev, device_t child, driver_intr_t *intr, void *arg,
 2222                 void **cookiep)
 2223 {
 2224         /*
 2225          * If an interrupt mapping gets to here something bad has happened.
 2226          */
 2227         panic("root_setup_intr");
 2228 }
 2229 
 2230 static device_method_t root_methods[] = {
 2231         /* Device interface */
 2232         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
 2233         DEVMETHOD(device_suspend,       bus_generic_suspend),
 2234         DEVMETHOD(device_resume,        bus_generic_resume),
 2235 
 2236         /* Bus interface */
 2237         DEVMETHOD(bus_print_child,      root_print_child),
 2238         DEVMETHOD(bus_read_ivar,        bus_generic_read_ivar),
 2239         DEVMETHOD(bus_write_ivar,       bus_generic_write_ivar),
 2240         DEVMETHOD(bus_setup_intr,       root_setup_intr),
 2241 
 2242         { 0, 0 }
 2243 };
 2244 
 2245 static driver_t root_driver = {
 2246         "root",
 2247         root_methods,
 2248         1,                      /* no softc */
 2249 };
 2250 
 2251 device_t        root_bus;
 2252 devclass_t      root_devclass;
 2253 
 2254 static int
 2255 root_bus_module_handler(module_t mod, int what, void* arg)
 2256 {
 2257     switch (what) {
 2258     case MOD_LOAD:
 2259         compile_methods(&root_driver);
 2260         root_bus = make_device(NULL, "root", 0);
 2261         root_bus->desc = "System root bus";
 2262         root_bus->ops = root_driver.ops;
 2263         root_bus->driver = &root_driver;
 2264         root_bus->state = DS_ATTACHED;
 2265         root_devclass = devclass_find_internal("root", FALSE);
 2266         return 0;
 2267 
 2268     case MOD_SHUTDOWN:
 2269         device_shutdown(root_bus);
 2270         return 0;
 2271     }
 2272 
 2273     return 0;
 2274 }
 2275 
 2276 static moduledata_t root_bus_mod = {
 2277         "rootbus",
 2278         root_bus_module_handler,
 2279         0
 2280 };
 2281 DECLARE_MODULE(rootbus, root_bus_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
 2282 
 2283 void
 2284 root_bus_configure(void)
 2285 {
 2286     device_t dev;
 2287 
 2288     PDEBUG(("."));
 2289 
 2290     for (dev = TAILQ_FIRST(&root_bus->children); dev;
 2291          dev = TAILQ_NEXT(dev, link)) {
 2292         device_probe_and_attach(dev);
 2293     }
 2294 }
 2295 
 2296 int
 2297 driver_module_handler(module_t mod, int what, void *arg)
 2298 {
 2299         int error, i;
 2300         struct driver_module_data *dmd;
 2301         devclass_t bus_devclass;
 2302 
 2303         dmd = (struct driver_module_data *)arg;
 2304         bus_devclass = devclass_find_internal(dmd->dmd_busname, TRUE);
 2305         error = 0;
 2306 
 2307         switch (what) {
 2308         case MOD_LOAD:
 2309                 if (dmd->dmd_chainevh)
 2310                         error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg);
 2311 
 2312                 for (i = 0; !error && i < dmd->dmd_ndrivers; i++) {
 2313                         PDEBUG(("Loading module: driver %s on bus %s",
 2314                                 DRIVERNAME(dmd->dmd_drivers[i]), 
 2315                                 dmd->dmd_busname));
 2316                         error = devclass_add_driver(bus_devclass,
 2317                                                     dmd->dmd_drivers[i]);
 2318                 }
 2319                 if (error)
 2320                         break;
 2321 
 2322                 /*
 2323                  * The drivers loaded in this way are assumed to all
 2324                  * implement the same devclass.
 2325                  */
 2326                 *dmd->dmd_devclass =
 2327                         devclass_find_internal(dmd->dmd_drivers[0]->name,
 2328                                                TRUE);
 2329                 break;
 2330 
 2331         case MOD_UNLOAD:
 2332                 for (i = 0; !error && i < dmd->dmd_ndrivers; i++) {
 2333                         PDEBUG(("Unloading module: driver %s from bus %s",
 2334                                 DRIVERNAME(dmd->dmd_drivers[i]), 
 2335                                 dmd->dmd_busname));
 2336                         error = devclass_delete_driver(bus_devclass,
 2337                                                        dmd->dmd_drivers[i]);
 2338                 }
 2339 
 2340                 if (!error && dmd->dmd_chainevh)
 2341                         error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg);
 2342                 break;
 2343         }
 2344 
 2345         return (error);
 2346 }
 2347 
 2348 /* Emulate bus_dmamap_load_mbuf_sg() using bus_dmamap_load_mbuf(). */
 2349 struct mbuf_sg_args {
 2350         bus_dma_segment_t *segs;
 2351         int nsegs;
 2352 };
 2353 
 2354 static void
 2355 mbuf_sg_cb(void *arg, bus_dma_segment_t *segs, int nsegs, bus_size_t length,
 2356     int error)
 2357 {
 2358         struct mbuf_sg_args *sg;
 2359 
 2360         if (error)
 2361                 return;
 2362         sg = arg;
 2363         bcopy(segs, sg->segs, sizeof(bus_dma_segment_t) * nsegs);
 2364         sg->nsegs = nsegs;
 2365 }
 2366 
 2367 
 2368 int
 2369 bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *mbuf,
 2370     bus_dma_segment_t *segs, int *nsegs, int flags)
 2371 {
 2372         struct mbuf_sg_args sg;
 2373         int error;
 2374 
 2375         sg.segs = segs;
 2376         sg.nsegs = *nsegs;
 2377         error = bus_dmamap_load_mbuf(dmat, map, mbuf, mbuf_sg_cb, &sg,
 2378             BUS_DMA_NOWAIT);
 2379         if (error)
 2380                 return (error);
 2381         *nsegs = sg.nsegs;
 2382         return (0);
 2383 }
 2384 
 2385 #ifdef BUS_DEBUG
 2386 
 2387 /* the _short versions avoid iteration by not calling anything that prints
 2388  * more than oneliners. I love oneliners.
 2389  */
 2390 
 2391 static void
 2392 print_method_list(device_method_t *m, int indent)
 2393 {
 2394         int i;
 2395 
 2396         if (!m)
 2397                 return;
 2398 
 2399         for (i = 0; m->desc; i++, m++)
 2400                 indentprintf(("method %d: %s, offset=%d\n",
 2401                         i, m->desc->name, m->desc->offset));
 2402 }
 2403 
 2404 static void
 2405 print_device_ops(device_ops_t ops, int indent)
 2406 {
 2407         int i;
 2408         int count = 0;
 2409 
 2410         if (!ops)
 2411                 return;
 2412 
 2413         /* we present a list of the methods that are pointing to the
 2414          * error_method, but ignore the 0'th elements; it is always
 2415          * error_method.
 2416          */
 2417         for (i = 1; i < ops->maxoffset; i++) {
 2418                 if (ops->methods[i] == error_method) {
 2419                         if (count == 0)
 2420                                 indentprintf(("error_method:"));
 2421                         printf(" %d", i);
 2422                         count++;
 2423                 }
 2424         }
 2425         if (count)
 2426                 printf("\n");
 2427 
 2428         indentprintf(("(%d method%s, %d valid, %d error_method%s)\n",
 2429                 ops->maxoffset-1, (ops->maxoffset-1 == 1? "":"s"),
 2430                 ops->maxoffset-1-count,
 2431                 count, (count == 1? "":"'s")));
 2432 }
 2433 
 2434 static void
 2435 print_device_short(device_t dev, int indent)
 2436 {
 2437         if (!dev)
 2438                 return;
 2439 
 2440         indentprintf(("device %d: <%s> %sparent,%schildren,%s%s%s%s,%sivars,%ssoftc,busy=%d\n",
 2441                 dev->unit, dev->desc,
 2442                 (dev->parent? "":"no "),
 2443                 (TAILQ_EMPTY(&dev->children)? "no ":""),
 2444                 (dev->flags&DF_ENABLED? "enabled,":"disabled,"),
 2445                 (dev->flags&DF_FIXEDCLASS? "fixed,":""),
 2446                 (dev->flags&DF_WILDCARD? "wildcard,":""),
 2447                 (dev->flags&DF_DESCMALLOCED? "descmalloced,":""),
 2448                 (dev->ivars? "":"no "),
 2449                 (dev->softc? "":"no "),
 2450                 dev->busy));
 2451 }
 2452 
 2453 static void
 2454 print_device(device_t dev, int indent)
 2455 {
 2456         if (!dev)
 2457                 return;
 2458 
 2459         print_device_short(dev, indent);
 2460 
 2461         indentprintf(("Parent:\n"));
 2462         print_device_short(dev->parent, indent+1);
 2463         indentprintf(("Methods:\n"));
 2464         print_device_ops(dev->ops, indent+1);
 2465         indentprintf(("Driver:\n"));
 2466         print_driver_short(dev->driver, indent+1);
 2467         indentprintf(("Devclass:\n"));
 2468         print_devclass_short(dev->devclass, indent+1);
 2469 }
 2470 
 2471 void
 2472 print_device_tree_short(device_t dev, int indent)
 2473 /* print the device and all its children (indented) */
 2474 {
 2475         device_t child;
 2476 
 2477         if (!dev)
 2478                 return;
 2479 
 2480         print_device_short(dev, indent);
 2481 
 2482         for (child = TAILQ_FIRST(&dev->children); child;
 2483                  child = TAILQ_NEXT(child, link))
 2484                 print_device_tree_short(child, indent+1);
 2485 }
 2486 
 2487 void
 2488 print_device_tree(device_t dev, int indent)
 2489 /* print the device and all its children (indented) */
 2490 {
 2491         device_t child;
 2492 
 2493         if (!dev)
 2494                 return;
 2495 
 2496         print_device(dev, indent);
 2497 
 2498         for (child = TAILQ_FIRST(&dev->children); child;
 2499                  child = TAILQ_NEXT(child, link))
 2500                 print_device_tree(child, indent+1);
 2501 }
 2502 
 2503 static void
 2504 print_driver_short(driver_t *driver, int indent)
 2505 {
 2506         if (!driver)
 2507                 return;
 2508 
 2509         indentprintf(("driver %s: softc size = %d\n",
 2510                 driver->name, driver->softc));
 2511 }
 2512 
 2513 static void
 2514 print_driver(driver_t *driver, int indent)
 2515 {
 2516         if (!driver)
 2517                 return;
 2518 
 2519         print_driver_short(driver, indent);
 2520         indentprintf(("Methods:\n"));
 2521         print_method_list(driver->methods, indent+1);
 2522         indentprintf(("Operations:\n"));
 2523         print_device_ops(driver->ops, indent+1);
 2524 }
 2525 
 2526 
 2527 static void
 2528 print_driver_list(driver_list_t drivers, int indent)
 2529 {
 2530         driverlink_t driver;
 2531 
 2532         for (driver = TAILQ_FIRST(&drivers); driver;
 2533              driver = TAILQ_NEXT(driver, link))
 2534                 print_driver(driver->driver, indent);
 2535 }
 2536 
 2537 static void
 2538 print_devclass_short(devclass_t dc, int indent)
 2539 {
 2540         if ( !dc )
 2541                 return;
 2542 
 2543         indentprintf(("devclass %s: max units = %d\n",
 2544                 dc->name, dc->maxunit));
 2545 }
 2546 
 2547 static void
 2548 print_devclass(devclass_t dc, int indent)
 2549 {
 2550         int i;
 2551 
 2552         if ( !dc )
 2553                 return;
 2554 
 2555         print_devclass_short(dc, indent);
 2556         indentprintf(("Drivers:\n"));
 2557         print_driver_list(dc->drivers, indent+1);
 2558 
 2559         indentprintf(("Devices:\n"));
 2560         for (i = 0; i < dc->maxunit; i++)
 2561                 if (dc->devices[i])
 2562                         print_device(dc->devices[i], indent+1);
 2563 }
 2564 
 2565 void
 2566 print_devclass_list_short(void)
 2567 {
 2568         devclass_t dc;
 2569 
 2570         printf("Short listing of devclasses, drivers & devices:\n");
 2571         for (dc = TAILQ_FIRST(&devclasses); dc; dc = TAILQ_NEXT(dc, link))
 2572                 print_devclass_short(dc, 0);
 2573 }
 2574 
 2575 void
 2576 print_devclass_list(void)
 2577 {
 2578         devclass_t dc;
 2579 
 2580         printf("Full listing of devclasses, drivers & devices:\n");
 2581         for (dc = TAILQ_FIRST(&devclasses); dc; dc = TAILQ_NEXT(dc, link))
 2582                 print_devclass(dc, 0);
 2583 }
 2584 
 2585 #endif

Cache object: ddf0042e59443e99ef485f1ae7a44389


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