• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 1997,1998,2003 Doug Rabson
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  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD: releng/12.2/sys/kern/subr_bus.c 365540 2020-09-09 22:59:47Z imp $");
31 
32 #include <sys/param.h>
33 #include <sys/kobj.h>
34 #include <sys/malloc.h>
35 #include <sys/queue.h>
36 #include <sys/systm.h>
37 #include <sys/bus.h>
38 #include <sys/mutex.h>
39 #include "los_hwi.h"
40 
41 #ifndef BOOTVERBOSE
42 #define BOOTVERBOSE     0
43 #endif
44 int     bootverbose = BOOTVERBOSE;
45 
46 /*
47  *  * Used to attach drivers to devclasses.
48  *   */
49 typedef struct driverlink *driverlink_t;
50 struct driverlink {
51 	kobj_class_t    driver;
52 	TAILQ_ENTRY(driverlink) link;   /* list of drivers in devclass */
53 	int             pass;
54 	TAILQ_ENTRY(driverlink) passlink;
55 };
56 
57 /*
58  * Forward declarations
59  */
60 typedef TAILQ_HEAD(devclass_list, devclass) devclass_list_t;
61 typedef TAILQ_HEAD(driver_list, driverlink) driver_list_t;
62 typedef TAILQ_HEAD(device_list, device) device_list_t;
63 
64 struct devclass {
65         TAILQ_ENTRY(devclass) link;
66         devclass_t      parent;         /* parent in devclass hierarchy */
67         driver_list_t   drivers;     /* bus devclasses store drivers for bus */
68         char            *name;
69         device_t        *devices;       /* array of devices indexed by unit */
70         int             maxunit;        /* size of devices array */
71         int             flags;
72 #define DC_HAS_CHILDREN         1
73 };
74 
75 /**
76  * @brief Implementation of device.
77  */
78 struct device {
79         /*
80          * A device is a kernel object. The first field must be the
81          * current ops table for the object.
82          */
83         KOBJ_FIELDS;
84 
85         /*
86          * Device hierarchy.
87          */
88         TAILQ_ENTRY(device)     link;   /**< list of devices in parent */
89         TAILQ_ENTRY(device)     devlink; /**< global device list membership */
90         device_t        parent;         /**< parent of this device  */
91         device_list_t   children;       /**< list of child devices */
92 
93         /*
94          * Details of this device.
95          */
96         driver_t        *driver;        /**< current driver */
97         devclass_t      devclass;       /**< current device class */
98         int             unit;           /**< current unit number */
99         char*           nameunit;       /**< name+unit e.g. foodev0 */
100         char*           desc;           /**< driver specific description */
101         int             busy;           /**< count of calls to device_busy() */
102         device_state_t  state;          /**< current device state  */
103         uint32_t        devflags;       /**< api level flags for device_get_flags() */
104         u_int           flags;          /**< internal device flags  */
105         u_int   order;                  /**< order from device_add_child_ordered() */
106         void    *ivars;                 /**< instance variables  */
107         void    *softc;                 /**< current driver's variables  */
108 };
109 
110 static MALLOC_DEFINE(M_BUS, "bus", "Bus data structures");
111 
112 #ifdef BUS_DEBUG
113 static int bus_debug = 1;
114 
115 #define PDEBUG(a)       if (bus_debug) {PRINTK("%s:%d: ", __func__, __LINE__), PRINTK a; PRINTK("\n");}
116 #define DEVICENAME(d)   ((d)? device_get_name(d): "no device")
117 #define DRIVERNAME(d)   ((d)? d->name : "no driver")
118 #define DEVCLANAME(d)   ((d)? d->name : "no devclass")
119 
120 /**
121  * Produce the indenting, indent*2 spaces plus a '.' ahead of that to
122  * prevent syslog from deleting initial spaces
123  */
124 #define indentprintf(p) do { int iJ; PRINTK("."); for (iJ=0; iJ<indent; iJ++) PRINTK("  "); PRINTK p ; } while (0)
125 
126 static void print_device_short(device_t dev, int indent);
127 static void print_device(device_t dev, int indent);
128 void print_device_tree_short(device_t dev, int indent);
129 void print_device_tree(device_t dev, int indent);
130 static void print_driver_short(driver_t *driver, int indent);
131 static void print_driver(driver_t *driver, int indent);
132 static void print_driver_list(driver_list_t drivers, int indent);
133 static void print_devclass_short(devclass_t dc, int indent);
134 static void print_devclass(devclass_t dc, int indent);
135 void print_devclass_list_short(void);
136 void print_devclass_list(void);
137 
138 #else
139 /* Make the compiler ignore the function calls */
140 #define PDEBUG(a)                       /* nop */
141 #define DEVICENAME(d)                   /* nop */
142 #define DRIVERNAME(d)                   /* nop */
143 #define DEVCLANAME(d)                   /* nop */
144 
145 #define print_device_short(d,i)         /* nop */
146 #define print_device(d,i)               /* nop */
147 #define print_device_tree_short(d,i)    /* nop */
148 #define print_device_tree(d,i)          /* nop */
149 #define print_driver_short(d,i)         /* nop */
150 #define print_driver(d,i)               /* nop */
151 #define print_driver_list(d,i)          /* nop */
152 #define print_devclass_short(d,i)       /* nop */
153 #define print_devclass(d,i)             /* nop */
154 #define print_devclass_list_short()     /* nop */
155 #define print_devclass_list()           /* nop */
156 #endif
157 
158 static TAILQ_HEAD(,device)      bus_data_devices;
159 static int bus_data_generation = 1;
160 
161 static kobj_method_t null_methods[] = {
162         KOBJMETHOD_END
163 };
164 
165 DEFINE_CLASS(null, null_methods, 0);
166 
167 /*
168  * Bus pass implementation
169  */
170 
171 static driver_list_t passes = TAILQ_HEAD_INITIALIZER(passes);
172 int bus_current_pass = BUS_PASS_ROOT;
173 
174 /**
175  * @brief Return the name of the device's devclass or @c NULL if there
176  * is none.
177  */
178 const char *
device_get_name(device_t dev)179 device_get_name(device_t dev)
180 {
181 	if (dev != NULL && dev->devclass)
182 		return (devclass_get_name(dev->devclass));
183 	return (NULL);
184 }
185 
186 /**
187  * @internal
188  * @brief Register the pass level of a new driver attachment
189  *
190  * Register a new driver attachment's pass level.  If no driver
191  * attachment with the same pass level has been added, then @p new
192  * will be added to the global passes list.
193  *
194  * @param new           the new driver attachment
195  */
196 static void
driver_register_pass(struct driverlink * new)197 driver_register_pass(struct driverlink *new)
198 {
199         struct driverlink *dl = NULL;
200 
201         /* We only consider pass numbers during boot. */
202         if (bus_current_pass == BUS_PASS_DEFAULT)
203                 return;
204 
205         /*
206          * Walk the passes list.  If we already know about this pass
207          * then there is nothing to do.  If we don't, then insert this
208          * driver link into the list.
209          */
210         TAILQ_FOREACH(dl, &passes, passlink) {
211                 if (dl->pass < new->pass)
212                         continue;
213                 if (dl->pass == new->pass)
214                         return;
215                 TAILQ_INSERT_BEFORE(dl, new, passlink);
216                 return;
217         }
218         TAILQ_INSERT_TAIL(&passes, new, passlink);
219 }
220 
221 /**
222  * @brief Raise the current bus pass
223  *
224  * Raise the current bus pass level to @p pass.  Call the BUS_NEW_PASS()
225  * method on the root bus to kick off a new device tree scan for each
226  * new pass level that has at least one driver.
227  */
228 void
bus_set_pass(int pass)229 bus_set_pass(int pass)
230 {
231         struct driverlink *dl = NULL;
232 
233         if (bus_current_pass > pass)
234                 panic("Attempt to lower bus pass level");
235 
236         TAILQ_FOREACH(dl, &passes, passlink) {
237                 /* Skip pass values below the current pass level. */
238                 if (dl->pass <= bus_current_pass)
239                         continue;
240 
241                 /*
242                  * Bail once we hit a driver with a pass level that is
243                  * too high.
244                  */
245                 if (dl->pass > pass)
246                         break;
247 
248                 /*
249                  * Raise the pass level to the next level and rescan
250                  * the tree.
251                  */
252                 bus_current_pass = dl->pass;
253                 BUS_NEW_PASS(root_bus);
254         }
255 
256         /*
257          * If there isn't a driver registered for the requested pass,
258          * then bus_current_pass might still be less than 'pass'.  Set
259          * it to 'pass' in that case.
260          */
261         if (bus_current_pass < pass)
262                 bus_current_pass = pass;
263         KASSERT(bus_current_pass == pass, ("Failed to update bus pass level"));
264 }
265 
266 /*
267  * Devclass implementation
268  */
269 
270 static devclass_list_t devclasses = TAILQ_HEAD_INITIALIZER(devclasses);
271 
272 /**
273  * @internal
274  * @brief Find or create a device class
275  *
276  * If a device class with the name @p classname exists, return it,
277  * otherwise if @p create is non-zero create and return a new device
278  * class.
279  *
280  * If @p parentname is non-NULL, the parent of the devclass is set to
281  * the devclass of that name.
282  *
283  * @param classname     the devclass name to find or create
284  * @param parentname    the parent devclass name or @c NULL
285  * @param create        non-zero to create a devclass
286  */
287 static devclass_t
devclass_find_internal(const char * classname,const char * parentname,int create)288 devclass_find_internal(const char *classname, const char *parentname,
289                        int create)
290 {
291         devclass_t dc;
292 
293         PDEBUG(("looking for %s", classname));
294         if (!classname)
295                 return (NULL);
296 
297         TAILQ_FOREACH(dc, &devclasses, link) {
298                 if (!strcmp(dc->name, classname))
299                         break;
300         }
301 
302         if (create && !dc) {
303                 dc = bsd_malloc(sizeof(struct devclass) + strlen(classname) + 1,
304                     M_BUS, M_NOWAIT | M_ZERO);
305                 if (!dc)
306                         return (NULL);
307                 dc->parent = NULL;
308                 dc->name = (char*) (dc + 1);
309                 if (strcpy_s(dc->name, strlen(classname) + 1, classname) != EOK) {
310                         bsd_free(dc, M_BUS);
311                         return (NULL);
312                 }
313                 TAILQ_INIT(&dc->drivers);
314                 TAILQ_INSERT_TAIL(&devclasses, dc, link);
315 
316                 PDEBUG(("create dc %p, %s", dc, classname));
317                 bus_data_generation_update();
318         }
319 
320         /*
321          * If a parent class is specified, then set that as our parent so
322          * that this devclass will support drivers for the parent class as
323          * well.  If the parent class has the same name don't do this though
324          * as it creates a cycle that can trigger an infinite loop in
325          * device_probe_child() if a device exists for which there is no
326          * suitable driver.
327          */
328         if (parentname && dc && !dc->parent &&
329             strcmp(classname, parentname) != 0) {
330                 dc->parent = devclass_find_internal(parentname, NULL, TRUE);
331                 if (dc->parent == NULL) {
332                     return (NULL);
333                 }
334                 dc->parent->flags = (unsigned int)dc->parent->flags | DC_HAS_CHILDREN;
335         }
336 
337         PDEBUG(("found dc %p, %s", dc, classname));
338         return (dc);
339 }
340 
341 /**
342  * @brief Create a device class
343  *
344  * If a device class with the name @p classname exists, return it,
345  * otherwise create and return a new device class.
346  *
347  * @param classname     the devclass name to find or create
348  */
349 devclass_t
devclass_create(const char * classname)350 devclass_create(const char *classname)
351 {
352         return (devclass_find_internal(classname, NULL, TRUE));
353 }
354 
355 /**
356  * @brief Find a device class
357  *
358  * If a device class with the name @p classname exists, return it,
359  * otherwise return @c NULL.
360  *
361  * @param classname     the devclass name to find
362  */
363 devclass_t
devclass_find(const char * classname)364 devclass_find(const char *classname)
365 {
366         return (devclass_find_internal(classname, NULL, FALSE));
367 }
368 
369 /**
370  * @brief Register that a device driver has been added to a devclass
371  *
372  * Register that a device driver has been added to a devclass.  This
373  * is called by devclass_add_driver to accomplish the recursive
374  * notification of all the children classes of dc, as well as dc.
375  * Each layer will have BUS_DRIVER_ADDED() called for all instances of
376  * the devclass.
377  *
378  * We do a full search here of the devclass list at each iteration
379  * level to save storing children-lists in the devclass structure.  If
380  * we ever move beyond a few dozen devices doing this, we may need to
381  * reevaluate...
382  *
383  * @param dc            the devclass to edit
384  * @param driver        the driver that was just added
385  */
386 static void
devclass_driver_added(devclass_t dc,driver_t * driver)387 devclass_driver_added(devclass_t dc, driver_t *driver)
388 {
389         devclass_t parent;
390         int i;
391 
392         /*
393          * Call BUS_DRIVER_ADDED for any existing busses in this class.
394          */
395         for (i = 0; i < dc->maxunit; i++)
396                 if (dc->devices[i] && device_is_attached(dc->devices[i]))
397                         BUS_DRIVER_ADDED(dc->devices[i], driver);
398 
399         /*
400          * Walk through the children classes.  Since we only keep a
401          * single parent pointer around, we walk the entire list of
402          * devclasses looking for children.  We set the
403          * DC_HAS_CHILDREN flag when a child devclass is created on
404          * the parent, so we only walk the list for those devclasses
405          * that have children.
406          */
407         if (!((unsigned int)dc->flags & DC_HAS_CHILDREN))
408                 return;
409         parent = dc;
410         TAILQ_FOREACH(dc, &devclasses, link) {
411                 if (dc->parent == parent)
412                         devclass_driver_added(dc, driver);
413         }
414 }
415 
416 /**
417  * @brief Add a device driver to a device class
418  *
419  * Add a device driver to a devclass. This is normally called
420  * automatically by DRIVER_MODULE(). The BUS_DRIVER_ADDED() method of
421  * all devices in the devclass will be called to allow them to attempt
422  * to re-probe any unmatched children.
423  *
424  * @param dc            the devclass to edit
425  * @param driver        the driver to register
426  */
427 int
devclass_add_driver(devclass_t dc,driver_t * driver,int pass,devclass_t * dcp)428 devclass_add_driver(devclass_t dc, driver_t *driver, int pass, devclass_t *dcp)
429 {
430         driverlink_t dl = NULL;
431         const char *parentname = NULL;
432 
433         PDEBUG(("%s +", DRIVERNAME(driver)));
434 
435         /* Don't allow invalid pass values. */
436         if (pass <= BUS_PASS_ROOT)
437                 return (EINVAL);
438 
439         dl = bsd_malloc(sizeof *dl, M_BUS, M_NOWAIT|M_ZERO);
440         if (!dl)
441                 return (ENOMEM);
442 
443         /*
444          * Compile the driver's methods. Also increase the reference count
445          * so that the class doesn't get freed when the last instance
446          * goes. This means we can safely use static methods and avoids a
447          * double-free in devclass_delete_driver.
448          */
449         kobj_class_compile((kobj_class_t) driver);
450 
451         /*
452          * If the driver has any base classes, make the
453          * devclass inherit from the devclass of the driver's
454          * first base class. This will allow the system to
455          * search for drivers in both devclasses for children
456          * of a device using this driver.
457          */
458         if (driver->baseclasses)
459                 parentname = driver->baseclasses[0]->name;
460         else
461                 parentname = NULL;
462         *dcp = devclass_find_internal(driver->name, parentname, TRUE);
463 
464         dl->driver = driver;
465         TAILQ_INSERT_TAIL(&dc->drivers, dl, link);
466         driver->refs++;         /* XXX: kobj_mtx */
467         dl->pass = pass;
468         driver_register_pass(dl);
469 
470         devclass_driver_added(dc, driver);
471         bus_data_generation_update();
472         PDEBUG(("%s -", DRIVERNAME(driver)));
473         return (0);
474 }
475 
476 /**
477  * @brief Register that a device driver has been deleted from a devclass
478  *
479  * Register that a device driver has been removed from a devclass.
480  * This is called by devclass_delete_driver to accomplish the
481  * recursive notification of all the children classes of busclass, as
482  * well as busclass.  Each layer will attempt to detach the driver
483  * from any devices that are children of the bus's devclass.  The function
484  * will return an error if a device fails to detach.
485  *
486  * We do a full search here of the devclass list at each iteration
487  * level to save storing children-lists in the devclass structure.  If
488  * we ever move beyond a few dozen devices doing this, we may need to
489  * reevaluate...
490  *
491  * @param busclass      the devclass of the parent bus
492  * @param dc            the devclass of the driver being deleted
493  * @param driver        the driver being deleted
494  */
495 static int
devclass_driver_deleted(devclass_t busclass,devclass_t dc,driver_t * driver)496 devclass_driver_deleted(devclass_t busclass, devclass_t dc, driver_t *driver)
497 {
498         devclass_t parent;
499         device_t dev;
500         int error, i;
501 
502         /*
503          * Disassociate from any devices.  We iterate through all the
504          * devices in the devclass of the driver and detach any which are
505          * using the driver and which have a parent in the devclass which
506          * we are deleting from.
507          *
508          * Note that since a driver can be in multiple devclasses, we
509          * should not detach devices which are not children of devices in
510          * the affected devclass.
511          */
512         for (i = 0; i < dc->maxunit; i++) {
513                 if (dc->devices[i]) {
514                         dev = dc->devices[i];
515                         if (dev->driver == driver && dev->parent &&
516                             dev->parent->devclass == busclass) {
517                                 if ((error = device_detach(dev)) != 0)
518                                         return (error);
519                                 BUS_PROBE_NOMATCH(dev->parent, dev);
520                                 // devnomatch(dev);
521                                 dev->flags |= DF_DONENOMATCH;
522                         }
523                 }
524         }
525 
526         /*
527          * Walk through the children classes.  Since we only keep a
528          * single parent pointer around, we walk the entire list of
529          * devclasses looking for children.  We set the
530          * DC_HAS_CHILDREN flag when a child devclass is created on
531          * the parent, so we only walk the list for those devclasses
532          * that have children.
533          */
534         if (!((unsigned int)busclass->flags & DC_HAS_CHILDREN))
535                 return (0);
536         parent = busclass;
537         TAILQ_FOREACH(busclass, &devclasses, link) {
538                 if (busclass->parent == parent) {
539                         error = devclass_driver_deleted(busclass, dc, driver);
540                         if (error)
541                                 return (error);
542                 }
543         }
544         return (0);
545 }
546 
547 /**
548  * @brief Delete a device driver from a device class
549  *
550  * Delete a device driver from a devclass. This is normally called
551  * automatically by DRIVER_MODULE().
552  *
553  * If the driver is currently attached to any devices,
554  * devclass_delete_driver() will first attempt to detach from each
555  * device. If one of the detach calls fails, the driver will not be
556  * deleted.
557  *
558  * @param dc            the devclass to edit
559  * @param driver        the driver to unregister
560  */
561 int
devclass_delete_driver(devclass_t busclass,driver_t * driver)562 devclass_delete_driver(devclass_t busclass, driver_t *driver)
563 {
564         devclass_t dc = devclass_find(driver->name);
565         driverlink_t dl = NULL;
566         int error;
567 
568         PDEBUG(("%s from devclass %s", driver->name, DEVCLANAME(busclass)));
569 
570         if (!dc)
571                 return (0);
572 
573         /*
574          * Find the link structure in the bus' list of drivers.
575          */
576         TAILQ_FOREACH(dl, &busclass->drivers, link) {
577                 if (dl->driver == driver)
578                         break;
579         }
580 
581         if (!dl) {
582                 PDEBUG(("%s not found in %s list", driver->name,
583                     busclass->name));
584                 return (ENOENT);
585         }
586 
587         error = devclass_driver_deleted(busclass, dc, driver);
588         if (error != 0)
589                 return (error);
590 
591         TAILQ_REMOVE(&busclass->drivers, dl, link);
592         bsd_free(dl, M_BUS);
593 
594         /* XXX: kobj_mtx */
595         driver->refs--;
596         if (driver->refs == 0)
597                 kobj_class_free((kobj_class_t) driver);
598 
599         bus_data_generation_update();
600         return (0);
601 }
602 
603 /**
604  * @brief Quiesces a set of device drivers from a device class
605  *
606  * Quiesce a device driver from a devclass. This is normally called
607  * automatically by DRIVER_MODULE().
608  *
609  * If the driver is currently attached to any devices,
610  * devclass_quiesece_driver() will first attempt to quiesce each
611  * device.
612  *
613  * @param dc            the devclass to edit
614  * @param driver        the driver to unregister
615  */
616 static int
devclass_quiesce_driver(devclass_t busclass,driver_t * driver)617 devclass_quiesce_driver(devclass_t busclass, driver_t *driver)
618 {
619         devclass_t dc = devclass_find(driver->name);
620         driverlink_t dl = NULL;
621         device_t dev;
622         int i;
623         int error;
624 
625         PDEBUG(("%s from devclass %s", driver->name, DEVCLANAME(busclass)));
626 
627         if (!dc)
628                 return (0);
629 
630         /*
631          * Find the link structure in the bus' list of drivers.
632          */
633         TAILQ_FOREACH(dl, &busclass->drivers, link) {
634                 if (dl->driver == driver)
635                         break;
636         }
637 
638         if (!dl) {
639                 PDEBUG(("%s not found in %s list", driver->name,
640                     busclass->name));
641                 return (ENOENT);
642         }
643 
644         /*
645          * Quiesce all devices.  We iterate through all the devices in
646          * the devclass of the driver and quiesce any which are using
647          * the driver and which have a parent in the devclass which we
648          * are quiescing.
649          *
650          * Note that since a driver can be in multiple devclasses, we
651          * should not quiesce devices which are not children of
652          * devices in the affected devclass.
653          */
654         for (i = 0; i < dc->maxunit; i++) {
655                 if (dc->devices[i]) {
656                         dev = dc->devices[i];
657                         if (dev->driver == driver && dev->parent &&
658                             dev->parent->devclass == busclass) {
659                                 if ((error = device_quiesce(dev)) != 0)
660                                         return (error);
661                         }
662                 }
663         }
664 
665         return (0);
666 }
667 
668 /**
669  * @internal
670  */
671 static driverlink_t
devclass_find_driver_internal(devclass_t dc,const char * classname)672 devclass_find_driver_internal(devclass_t dc, const char *classname)
673 {
674         driverlink_t dl = NULL;
675 
676         PDEBUG(("%s in devclass %s", classname, DEVCLANAME(dc)));
677 
678         TAILQ_FOREACH(dl, &dc->drivers, link) {
679                 if (!strcmp(dl->driver->name, classname))
680                         return (dl);
681         }
682 
683         PDEBUG(("not found"));
684         return (NULL);
685 }
686 
687 /**
688  * @brief Return the name of the devclass
689  */
690 const char *
devclass_get_name(devclass_t dc)691 devclass_get_name(devclass_t dc)
692 {
693         return (dc->name);
694 }
695 
696 /**
697  * @brief Find a device given a unit number
698  *
699  * @param dc            the devclass to search
700  * @param unit          the unit number to search for
701  *
702  * @returns             the device with the given unit number or @c
703  *                      NULL if there is no such device
704  */
705 device_t
devclass_get_device(devclass_t dc,int unit)706 devclass_get_device(devclass_t dc, int unit)
707 {
708         if (dc == NULL || unit < 0 || unit >= dc->maxunit)
709                 return (NULL);
710         return (dc->devices[unit]);
711 }
712 
713 /**
714  * @brief Find the softc field of a device given a unit number
715  *
716  * @param dc            the devclass to search
717  * @param unit          the unit number to search for
718  *
719  * @returns             the softc field of the device with the given
720  *                      unit number or @c NULL if there is no such
721  *                      device
722  */
723 void *
devclass_get_softc(devclass_t dc,int unit)724 devclass_get_softc(devclass_t dc, int unit)
725 {
726         device_t dev;
727 
728         dev = devclass_get_device(dc, unit);
729         if (!dev)
730                 return (NULL);
731 
732         return (device_get_softc(dev));
733 }
734 
735 /**
736  * @brief Get a list of devices in the devclass
737  *
738  * An array containing a list of all the devices in the given devclass
739  * is allocated and returned in @p *devlistp. The number of devices
740  * in the array is returned in @p *devcountp. The caller should free
741  * the array using @c free(p, M_TEMP), even if @p *devcountp is 0.
742  *
743  * @param dc            the devclass to examine
744  * @param devlistp      points at location for array pointer return
745  *                      value
746  * @param devcountp     points at location for array size return value
747  *
748  * @retval 0            success
749  * @retval ENOMEM       the array allocation failed
750  */
751 int
devclass_get_devices(devclass_t dc,device_t ** devlistp,int * devcountp)752 devclass_get_devices(devclass_t dc, device_t **devlistp, int *devcountp)
753 {
754         int count, i;
755         device_t *list;
756 
757         count = devclass_get_count(dc);
758         list = bsd_malloc(count * sizeof(device_t), M_TEMP, M_NOWAIT|M_ZERO);
759         if (!list)
760                 return (ENOMEM);
761 
762         count = 0;
763         for (i = 0; i < dc->maxunit; i++) {
764                 if (dc->devices[i]) {
765                         list[count] = dc->devices[i];
766                         count++;
767                 }
768         }
769 
770         *devlistp = list;
771         *devcountp = count;
772 
773         return (0);
774 }
775 
776 /**
777  * @brief Get a list of drivers in the devclass
778  *
779  * An array containing a list of pointers to all the drivers in the
780  * given devclass is allocated and returned in @p *listp.  The number
781  * of drivers in the array is returned in @p *countp. The caller should
782  * free the array using @c free(p, M_TEMP).
783  *
784  * @param dc            the devclass to examine
785  * @param listp         gives location for array pointer return value
786  * @param countp        gives location for number of array elements
787  *                      return value
788  *
789  * @retval 0            success
790  * @retval ENOMEM       the array allocation failed
791  */
792 int
devclass_get_drivers(devclass_t dc,driver_t *** listp,int * countp)793 devclass_get_drivers(devclass_t dc, driver_t ***listp, int *countp)
794 {
795         driverlink_t dl = NULL;
796         driver_t **list = NULL;
797         int count;
798 
799         count = 0;
800         TAILQ_FOREACH(dl, &dc->drivers, link)
801                 count++;
802         list = bsd_malloc(count * sizeof(driver_t *), M_TEMP, M_NOWAIT);
803         if (list == NULL)
804                 return (ENOMEM);
805 
806         count = 0;
807         TAILQ_FOREACH(dl, &dc->drivers, link) {
808                 list[count] = dl->driver;
809                 count++;
810         }
811         *listp = list;
812         *countp = count;
813 
814         return (0);
815 }
816 
817 /**
818  * @brief Get the number of devices in a devclass
819  *
820  * @param dc            the devclass to examine
821  */
822 int
devclass_get_count(devclass_t dc)823 devclass_get_count(devclass_t dc)
824 {
825         int count, i;
826 
827         count = 0;
828         for (i = 0; i < dc->maxunit; i++)
829                 if (dc->devices[i])
830                         count++;
831         return (count);
832 }
833 
834 /**
835  * @brief Get the maximum unit number used in a devclass
836  *
837  * Note that this is one greater than the highest currently-allocated
838  * unit.  If a null devclass_t is passed in, -1 is returned to indicate
839  * that not even the devclass has been allocated yet.
840  *
841  * @param dc            the devclass to examine
842  */
843 int
devclass_get_maxunit(devclass_t dc)844 devclass_get_maxunit(devclass_t dc)
845 {
846         if (dc == NULL)
847                 return (-1);
848         return (dc->maxunit);
849 }
850 
851 /**
852  * @brief Find a free unit number in a devclass
853  *
854  * This function searches for the first unused unit number greater
855  * that or equal to @p unit.
856  *
857  * @param dc            the devclass to examine
858  * @param unit          the first unit number to check
859  */
860 int
devclass_find_free_unit(devclass_t dc,int unit)861 devclass_find_free_unit(devclass_t dc, int unit)
862 {
863         if (dc == NULL)
864                 return (unit);
865         while (unit < dc->maxunit && dc->devices[unit] != NULL)
866                 unit++;
867         return (unit);
868 }
869 
870 /**
871  * @brief Set the parent of a devclass
872  *
873  * The parent class is normally initialised automatically by
874  * DRIVER_MODULE().
875  *
876  * @param dc            the devclass to edit
877  * @param pdc           the new parent devclass
878  */
879 void
devclass_set_parent(devclass_t dc,devclass_t pdc)880 devclass_set_parent(devclass_t dc, devclass_t pdc)
881 {
882         dc->parent = pdc;
883 }
884 
885 /**
886  * @brief Get the parent of a devclass
887  *
888  * @param dc            the devclass to examine
889  */
890 devclass_t
devclass_get_parent(devclass_t dc)891 devclass_get_parent(devclass_t dc)
892 {
893         return (dc->parent);
894 }
895 
896 /**
897  * @internal
898  * @brief Allocate a unit number
899  *
900  * On entry, @p *unitp is the desired unit number (or @c -1 if any
901  * will do). The allocated unit number is returned in @p *unitp.
902 
903  * @param dc            the devclass to allocate from
904  * @param unitp         points at the location for the allocated unit
905  *                      number
906  *
907  * @retval 0            success
908  * @retval EEXIST       the requested unit number is already allocated
909  * @retval ENOMEM       memory allocation failure
910  */
911 static int
devclass_alloc_unit(devclass_t dc,device_t dev,int * unitp)912 devclass_alloc_unit(devclass_t dc, device_t dev, int *unitp)
913 {
914     int unit = *unitp;
915 
916     PDEBUG(("unit %d in devclass %s", unit, DEVCLANAME(dc)));
917 
918     /* Ask the parent bus if it wants to wire this device. */
919     if (unit == -1)
920         BUS_HINT_DEVICE_UNIT(device_get_parent(dev), dev, dc->name, &unit);
921 
922     /* If we were given a wired unit number, check for existing device */
923     /* XXX imp XXX */
924     if (unit != -1) {
925         if (unit >= 0 && unit < dc->maxunit && dc->devices[unit] != NULL) {
926             if (bootverbose)
927                 printf("%s: %s%d already exists; skipping it\n", dc->name, dc->name, *unitp);
928             return (EEXIST);
929         }
930     } else {
931         /* Unwired device, find the next available slot for it */
932         unit = 0;
933         for (unit = 0;; unit++) {
934             /* If this device slot is already in use, skip it. */
935             if (unit < dc->maxunit && dc->devices[unit] != NULL)
936                 continue;
937 
938             break;
939         }
940     }
941     PDEBUG(("mid: unit %d in devclass %s", unit, DEVCLANAME(dc)));
942     /*
943      * We've selected a unit beyond the length of the table, so let's
944      * extend the table to make room for all units up to and including
945      * this one.
946      */
947     if (unit >= dc->maxunit) {
948         device_t *newlist, *oldlist;
949         int newsize;
950 
951         oldlist = dc->devices;
952         newsize = roundup((unit + 1), MINALLOCSIZE / sizeof(device_t));
953         newlist = bsd_malloc(sizeof(device_t) * newsize, M_BUS, M_NOWAIT);
954 		PDEBUG(("oldlist %p, newlist %p, newsize %d", oldlist, newlist, newsize));
955         if (!newlist)
956             return (ENOMEM);
957 		PDEBUG(("start memcpy, size %d", sizeof(device_t) * dc->maxunit));
958         if (oldlist != NULL)
959             (void)memcpy_s(newlist, sizeof(device_t) * dc->maxunit, oldlist, sizeof(device_t) * dc->maxunit);
960         PDEBUG(("start memset, maxunit %d, size %d", dc->maxunit, sizeof(device_t) * (newsize - dc->maxunit)));
961         (void)memset_s(newlist + dc->maxunit, sizeof(device_t) * (newsize - dc->maxunit), 0,
962                        sizeof(device_t) * (newsize - dc->maxunit));
963         dc->devices = newlist;
964         dc->maxunit = newsize;
965         if (oldlist != NULL)
966             bsd_free(oldlist, M_BUS);
967     }
968     PDEBUG(("now: unit %d in devclass %s", unit, DEVCLANAME(dc)));
969 
970     *unitp = unit;
971     return (0);
972 }
973 
974 /**
975  * @internal
976  */
977 static void
device_set_desc_internal(device_t dev,const char * desc,int copy)978 device_set_desc_internal(device_t dev, const char* desc, int copy)
979 {
980 	if (dev->desc && (dev->flags & DF_DESCMALLOCED)) {
981 		bsd_free(dev->desc, M_BUS);
982 		dev->flags &= ~DF_DESCMALLOCED;
983 		dev->desc = NULL;
984 	}
985 
986 	if (copy && desc) {
987 		dev->desc = bsd_malloc(strlen(desc) + 1, M_BUS, M_NOWAIT);
988 		if (dev->desc) {
989 			if (strcpy_s(dev->desc, strlen(desc) + 1, desc) != EOK) {
990 				PDEBUG(("desc internal copy desc failed!\n"));
991 			}
992 			dev->flags |= DF_DESCMALLOCED;
993 		}
994 	} else {
995 		/* Avoid a -Wcast-qual warning */
996 		dev->desc = (char *)(uintptr_t) desc;
997 	}
998 
999 	bus_data_generation_update();
1000 }
1001 
1002 /**
1003  * @brief Set the device's description
1004  *
1005  * The value of @c desc should be a string constant that will not
1006  * change (at least until the description is changed in a subsequent
1007  * call to device_set_desc() or device_set_desc_copy()).
1008  */
1009 void
device_set_desc(device_t dev,const char * desc)1010 device_set_desc(device_t dev, const char* desc)
1011 {
1012 	device_set_desc_internal(dev, desc, FALSE);
1013 }
1014 
1015 /**
1016  * @brief Set the device's description
1017  *
1018  * The string pointed to by @c desc is copied. Use this function if
1019  * the device description is generated, (e.g. with sprintf()).
1020  */
1021 void
device_set_desc_copy(device_t dev,const char * desc)1022 device_set_desc_copy(device_t dev, const char* desc)
1023 {
1024         device_set_desc_internal(dev, desc, TRUE);
1025 }
1026 
1027 /**
1028  * @brief Return the device's description string
1029  */
1030 const char *
device_get_desc(device_t dev)1031 device_get_desc(device_t dev)
1032 {
1033         return (dev->desc);
1034 }
1035 
1036 /**
1037  * @brief Return the device's softc field
1038  *
1039  * The softc is allocated and zeroed when a driver is attached, based
1040  * on the size field of the driver.
1041  */
1042 void *
device_get_softc(device_t dev)1043 device_get_softc(device_t dev)
1044 {
1045         return (dev->softc);
1046 }
1047 
1048 /**
1049  * @brief Set the device's softc field
1050  *
1051  * Most drivers do not need to use this since the softc is allocated
1052  * automatically when the driver is attached.
1053  */
1054 void
device_set_softc(device_t dev,void * softc)1055 device_set_softc(device_t dev, void *softc)
1056 {
1057         if (dev->softc && !(dev->flags & DF_EXTERNALSOFTC))
1058                 bsd_free(dev->softc, M_BUS_SC);
1059         dev->softc = softc;
1060         if (dev->softc)
1061                 dev->flags |= DF_EXTERNALSOFTC;
1062         else
1063                 dev->flags &= ~DF_EXTERNALSOFTC;
1064 }
1065 
1066 /**
1067  * @brief Free claimed softc
1068  *
1069  * Most drivers do not need to use this since the softc is freed
1070  * automatically when the driver is detached.
1071  */
1072 void
device_free_softc(void * softc)1073 device_free_softc(void *softc)
1074 {
1075         bsd_free(softc, M_BUS_SC);
1076 }
1077 
1078 /**
1079  * @brief Claim softc
1080  *
1081  * This function can be used to let the driver free the automatically
1082  * allocated softc using "device_free_softc()". This function is
1083  * useful when the driver is refcounting the softc and the softc
1084  * cannot be freed when the "device_detach" method is called.
1085  */
1086 void
device_claim_softc(device_t dev)1087 device_claim_softc(device_t dev)
1088 {
1089         if (dev->softc)
1090                 dev->flags |= DF_EXTERNALSOFTC;
1091         else
1092                 dev->flags &= ~DF_EXTERNALSOFTC;
1093 }
1094 
1095 /**
1096  * @brief Get the device's ivars field
1097  *
1098  * The ivars field is used by the parent device to store per-device
1099  * state (e.g. the physical location of the device or a list of
1100  * resources).
1101  */
1102 void *
device_get_ivars(device_t dev)1103 device_get_ivars(device_t dev)
1104 {
1105 
1106         KASSERT(dev != NULL, ("device_get_ivars(NULL, ...)"));
1107         return (dev->ivars);
1108 }
1109 
1110 /**
1111  * @brief Set the device's ivars field
1112  */
1113 void
device_set_ivars(device_t dev,void * ivars)1114 device_set_ivars(device_t dev, void * ivars)
1115 {
1116 
1117         KASSERT(dev != NULL, ("device_set_ivars(NULL, ...)"));
1118         dev->ivars = ivars;
1119 }
1120 
1121 /**
1122  * @brief Return the device's state
1123  */
1124 device_state_t
device_get_state(device_t dev)1125 device_get_state(device_t dev)
1126 {
1127         return (dev->state);
1128 }
1129 
1130 /**
1131  * @brief Set the DF_ENABLED flag for the device
1132  */
1133 void
device_enable(device_t dev)1134 device_enable(device_t dev)
1135 {
1136         dev->flags |= DF_ENABLED;
1137 }
1138 
1139 /**
1140  * @brief Clear the DF_ENABLED flag for the device
1141  */
1142 void
device_disable(device_t dev)1143 device_disable(device_t dev)
1144 {
1145         dev->flags &= ~DF_ENABLED;
1146 }
1147 
1148 /**
1149  * @brief Increment the busy counter for the device
1150  */
1151 void
device_busy(device_t dev)1152 device_busy(device_t dev)
1153 {
1154         if (dev->state < DS_ATTACHING)
1155                 panic("device_busy: called for unattached device");
1156         if (dev->busy == 0 && dev->parent)
1157                 device_busy(dev->parent);
1158         dev->busy++;
1159         if (dev->state == DS_ATTACHED)
1160                 dev->state = DS_BUSY;
1161 }
1162 
1163 /**
1164  * @brief Decrement the busy counter for the device
1165  */
1166 void
device_unbusy(device_t dev)1167 device_unbusy(device_t dev)
1168 {
1169         if (dev->busy != 0 && dev->state != DS_BUSY &&
1170             dev->state != DS_ATTACHING)
1171                 panic("device_unbusy: called for non-busy device %s",
1172                     device_get_nameunit(dev));
1173         dev->busy--;
1174         if (dev->busy == 0) {
1175                 if (dev->parent)
1176                         device_unbusy(dev->parent);
1177                 if (dev->state == DS_BUSY)
1178                         dev->state = DS_ATTACHED;
1179         }
1180 }
1181 
1182 /**
1183  * @brief Set the DF_QUIET flag for the device
1184  */
1185 void
device_quiet(device_t dev)1186 device_quiet(device_t dev)
1187 {
1188         dev->flags |= DF_QUIET;
1189 }
1190 
1191 /**
1192  * @brief Clear the DF_QUIET flag for the device
1193  */
1194 void
device_verbose(device_t dev)1195 device_verbose(device_t dev)
1196 {
1197         dev->flags &= ~DF_QUIET;
1198 }
1199 
1200 /**
1201  * @brief Return non-zero if the DF_QUIET flag is set on the device
1202  */
1203 int
device_is_quiet(device_t dev)1204 device_is_quiet(device_t dev)
1205 {
1206         return ((dev->flags & DF_QUIET) != 0);
1207 }
1208 
1209 /**
1210  * @brief Return non-zero if the DF_ENABLED flag is set on the device
1211  */
1212 int
device_is_enabled(device_t dev)1213 device_is_enabled(device_t dev)
1214 {
1215         return ((dev->flags & DF_ENABLED) != 0);
1216 }
1217 
1218 /**
1219  * @brief Return non-zero if the device was successfully probed
1220  */
1221 int
device_is_alive(device_t dev)1222 device_is_alive(device_t dev)
1223 {
1224         return (dev->state >= DS_ALIVE);
1225 }
1226 
1227 /**
1228  * @brief Return non-zero if the device currently has a driver
1229  * attached to it
1230  */
1231 int
device_is_attached(device_t dev)1232 device_is_attached(device_t dev)
1233 {
1234         return (dev->state >= DS_ATTACHED);
1235 }
1236 
1237 /**
1238  * @brief Return non-zero if the device is currently suspended.
1239  */
1240 int
device_is_suspended(device_t dev)1241 device_is_suspended(device_t dev)
1242 {
1243         return ((dev->flags & DF_SUSPENDED) != 0);
1244 }
1245 
1246 
1247 
1248 /**
1249  * @brief Return a string containing the device's devclass name
1250  * followed by an ascii representation of the device's unit number
1251  * (e.g. @c "foo2").
1252  */
1253 const char *
device_get_nameunit(device_t dev)1254 device_get_nameunit(device_t dev)
1255 {
1256 	return (dev->nameunit);
1257 }
1258 
1259 /**
1260  * @internal
1261  * @brief Add a device to a devclass
1262  *
1263  * A unit number is allocated for the device (using the device's
1264  * preferred unit number if any) and the device is registered in the
1265  * devclass. This allows the device to be looked up by its unit
1266  * number, e.g. by decoding a dev_t minor number.
1267  *
1268  * @param dc            the devclass to add to
1269  * @param dev           the device to add
1270  *
1271  * @retval 0            success
1272  * @retval EEXIST       the requested unit number is already allocated
1273  * @retval ENOMEM       memory allocation failure
1274  */
1275 static int
devclass_add_device(devclass_t dc,device_t dev)1276 devclass_add_device(devclass_t dc, device_t dev)
1277 {
1278         int buflen, error;
1279 
1280         PDEBUG(("%s in devclass %s", DEVICENAME(dev), DEVCLANAME(dc)));
1281 
1282         buflen = snprintf(NULL, 0, "%s%d$", dc->name, INT_MAX);
1283         if (buflen < 0)
1284                 return (ENOMEM);
1285         dev->nameunit = bsd_malloc(buflen, M_BUS, M_NOWAIT|M_ZERO);
1286         if (!dev->nameunit)
1287                 return (ENOMEM);
1288 
1289         if ((error = devclass_alloc_unit(dc, dev, &dev->unit)) != 0) {
1290                 bsd_free(dev->nameunit, M_BUS);
1291                 dev->nameunit = NULL;
1292                 return (error);
1293         }
1294         dc->devices[dev->unit] = dev;
1295         dev->devclass = dc;
1296         if (snprintf_s(dev->nameunit, buflen, buflen - 1, "%s%d", dc->name, dev->unit) < 0) {
1297                 bsd_free(dev->nameunit, M_BUS);
1298                 dev->nameunit = NULL;
1299                 return (ENOMEM);
1300         }
1301         PDEBUG(("dev->nameunit : %s", dev->nameunit));
1302 
1303         return (0);
1304 }
1305 
1306 /**
1307  * @internal
1308  * @brief Delete a device from a devclass
1309  *
1310  * The device is removed from the devclass's device list and its unit
1311  * number is freed.
1312 
1313  * @param dc            the devclass to delete from
1314  * @param dev           the device to delete
1315  *
1316  * @retval 0            success
1317  */
1318 static int
devclass_delete_device(devclass_t dc,device_t dev)1319 devclass_delete_device(devclass_t dc, device_t dev)
1320 {
1321         if (!dc || !dev)
1322                 return (0);
1323 
1324         PDEBUG(("%s in devclass %s", DEVICENAME(dev), DEVCLANAME(dc)));
1325 
1326         if (dev->devclass != dc || dc->devices[dev->unit] != dev)
1327                 panic("devclass_delete_device: inconsistent device class");
1328         dc->devices[dev->unit] = NULL;
1329         if (dev->flags & DF_WILDCARD)
1330                 dev->unit = -1;
1331         dev->devclass = NULL;
1332         bsd_free(dev->nameunit, M_BUS);
1333         dev->nameunit = NULL;
1334 
1335         return (0);
1336 }
1337 
1338 /**
1339  * @internal
1340  * @brief Make a new device and add it as a child of @p parent
1341  *
1342  * @param parent	the parent of the new device
1343  * @param name		the devclass name of the new device or @c NULL
1344  *			to leave the devclass unspecified
1345  * @parem unit		the unit number of the new device of @c -1 to
1346  *			leave the unit number unspecified
1347  *
1348  * @returns the new device
1349  */
1350 static device_t
make_device(device_t parent,const char * name,int unit)1351 make_device(device_t parent, const char *name, int unit)
1352 {
1353 	device_t dev;
1354 	devclass_t dc;
1355 
1356 	PDEBUG(("%s at %s as unit %d", name, DEVICENAME(parent), unit));
1357 
1358 	if (name) {
1359 		dc = devclass_find_internal(name, NULL, TRUE);
1360 		if (!dc) {
1361 			printf("make_device: can't find device class %s\n",
1362 			    name);
1363 			return (NULL);
1364 		}
1365 	} else {
1366 		dc = NULL;
1367 	}
1368 
1369 	dev = bsd_malloc(sizeof(struct device), 0, M_NOWAIT|M_ZERO);
1370 	if (!dev)
1371 		return (NULL);
1372 
1373 	dev->parent = parent;
1374 	TAILQ_INIT(&dev->children);
1375 	kobj_init((kobj_t) dev, &null_class);
1376 	dev->driver = NULL;
1377 	dev->devclass = NULL;
1378 	dev->unit = unit;
1379 	dev->nameunit = NULL;
1380 	dev->desc = NULL;
1381 	dev->busy = 0;
1382 	dev->devflags = 0;
1383 	dev->flags = DF_ENABLED;
1384 	dev->order = 0;
1385 	if (unit == -1)
1386 		dev->flags |= DF_WILDCARD;
1387 	if (name) {
1388 		dev->flags |= DF_FIXEDCLASS;
1389 		if (devclass_add_device(dc, dev)) {
1390 			kobj_delete((kobj_t) dev, NULL);
1391 			return (NULL);
1392 		}
1393 	}
1394 	dev->ivars = NULL;
1395 	dev->softc = NULL;
1396 
1397 	dev->state = DS_NOTPRESENT;
1398 
1399 	PDEBUG(("bus_data_devices (%p) ", &bus_data_devices));
1400 	TAILQ_INSERT_TAIL(&bus_data_devices, dev, devlink);
1401 	bus_data_generation_update();
1402 
1403 	PDEBUG(("%s at %s as unit %d success", name, DEVICENAME(parent), unit));
1404 	return (dev);
1405 }
1406 
1407 /**
1408  * @internal
1409  * @brief Print a description of a device.
1410  */
1411 static int
device_print_child(device_t dev,device_t child)1412 device_print_child(device_t dev, device_t child)
1413 {
1414         int retval = 0;
1415 
1416         if (device_is_alive(child))
1417                 retval += BUS_PRINT_CHILD(dev, child);
1418         else
1419                 retval += device_printf(child, " not found\n");
1420 
1421         return (retval);
1422 }
1423 
1424 /**
1425  * @brief Create a new device
1426  *
1427  * This creates a new device and adds it as a child of an existing
1428  * parent device. The new device will be added after the last existing
1429  * child with order zero.
1430  *
1431  * @param dev		the device which will be the parent of the
1432  *			new child device
1433  * @param name		devclass name for new device or @c NULL if not
1434  *			specified
1435  * @param unit		unit number for new device or @c -1 if not
1436  *			specified
1437  *
1438  * @returns		the new device
1439  */
1440 device_t
device_add_child(device_t dev,const char * name,int unit)1441 device_add_child(device_t dev, const char *name, int unit)
1442 {
1443 	return (device_add_child_ordered(dev, 0, name, unit));
1444 }
1445 
1446 device_t
bus_get_device(device_t dev,const char * name)1447 bus_get_device(device_t dev, const char *name)
1448 {
1449         device_t child;
1450 
1451         PDEBUG(("+"));
1452         TAILQ_FOREACH(child, &dev->children, link) {
1453                 if (!strcmp(device_get_name(child), name))
1454                         return (child);
1455         }
1456         PDEBUG(("-"));
1457         return (NULL);
1458 }
1459 
1460 /**
1461  * @brief Create a new device
1462  *
1463  * This creates a new device and adds it as a child of an existing
1464  * parent device. The new device will be added after the last existing
1465  * child with the same order.
1466  *
1467  * @param dev		the device which will be the parent of the
1468  *			new child device
1469  * @param order		a value which is used to partially sort the
1470  *			children of @p dev - devices created using
1471  *			lower values of @p order appear first in @p
1472  *			dev's list of children
1473  * @param name		devclass name for new device or @c NULL if not
1474  *			specified
1475  * @param unit		unit number for new device or @c -1 if not
1476  *			specified
1477  *
1478  * @returns		the new device
1479  */
1480 device_t
device_add_child_ordered(device_t dev,u_int order,const char * name,int unit)1481 device_add_child_ordered(device_t dev, u_int order, const char *name, int unit)
1482 {
1483 	device_t child;
1484 	device_t place;
1485 
1486 	PDEBUG(("%s at %s with order %u as unit %d",
1487 	    name, DEVICENAME(dev), order, unit));
1488 	KASSERT(name != NULL || unit == -1,
1489 	    ("child device with wildcard name and specific unit number"));
1490 
1491 	child = make_device(dev, name, unit);
1492 	if (child == NULL)
1493 		return (child);
1494 	child->order = order;
1495 
1496 	TAILQ_FOREACH(place, &dev->children, link) {
1497 		if (place->order > order)
1498 			break;
1499 	}
1500 
1501 	if (place) {
1502 		/*
1503 		 * The device 'place' is the first device whose order is
1504 		 * greater than the new child.
1505 		 */
1506 		TAILQ_INSERT_BEFORE(place, child, link);
1507 	} else {
1508 		/*
1509 		 * The new child's order is greater or equal to the order of
1510 		 * any existing device. Add the child to the tail of the list.
1511 		 */
1512 		TAILQ_INSERT_TAIL(&dev->children, child, link);
1513 	}
1514 
1515 	bus_data_generation_update();
1516 	PDEBUG(("%s at %s with order %u as unit %d success",
1517 		name, DEVICENAME(dev), order, unit));
1518 	return (child);
1519 }
1520 
1521 /**
1522  * @brief Delete a device
1523  *
1524  * This function deletes a device along with all of its children. If
1525  * the device currently has a driver attached to it, the device is
1526  * detached first using device_detach().
1527  *
1528  * @param dev           the parent device
1529  * @param child         the device to delete
1530  *
1531  * @retval 0            success
1532  * @retval non-zero     a unit error code describing the error
1533  */
1534 int
device_delete_child(device_t dev,device_t child)1535 device_delete_child(device_t dev, device_t child)
1536 {
1537         int error;
1538         device_t grandchild;
1539 
1540         PDEBUG(("%s from %s", DEVICENAME(child), DEVICENAME(dev)));
1541 
1542         /* detach parent before deleting children, if any */
1543         if ((error = device_detach(child)) != 0)
1544                 return (error);
1545 
1546         /* remove children second */
1547         while ((grandchild = TAILQ_FIRST(&child->children)) != NULL) {
1548                 error = device_delete_child(child, grandchild);
1549                 if (error)
1550                         return (error);
1551         }
1552 
1553         if (child->devclass)
1554                 devclass_delete_device(child->devclass, child);
1555         if (child->parent)
1556                 BUS_CHILD_DELETED(dev, child);
1557         TAILQ_REMOVE(&dev->children, child, link);
1558         TAILQ_REMOVE(&bus_data_devices, child, devlink);
1559         kobj_delete((kobj_t) child, M_BUS);
1560 
1561         bus_data_generation_update();
1562         return (0);
1563 }
1564 
1565 /**
1566  * @brief Delete all children devices of the given device, if any.
1567  *
1568  * This function deletes all children devices of the given device, if
1569  * any, using the device_delete_child() function for each device it
1570  * finds. If a child device cannot be deleted, this function will
1571  * return an error code.
1572  *
1573  * @param dev           the parent device
1574  *
1575  * @retval 0            success
1576  * @retval non-zero     a device would not detach
1577  */
1578 int
device_delete_children(device_t dev)1579 device_delete_children(device_t dev)
1580 {
1581         device_t child;
1582         int error;
1583 
1584         PDEBUG(("Deleting all children of %s", DEVICENAME(dev)));
1585 
1586         error = 0;
1587 
1588         while ((child = TAILQ_FIRST(&dev->children)) != NULL) {
1589                 error = device_delete_child(dev, child);
1590                 if (error) {
1591                         PDEBUG(("Failed deleting %s", DEVICENAME(child)));
1592                         break;
1593                 }
1594         }
1595         return (error);
1596 }
1597 
1598 /**
1599  * @brief Probe a device and attach a driver if possible
1600  *
1601  * calls device_probe() and attaches if that was successful.
1602  */
1603 int
device_probe_and_attach(device_t dev)1604 device_probe_and_attach(device_t dev)
1605 {
1606 	int error;
1607 
1608         PDEBUG(("+"));
1609 	GIANT_REQUIRED;
1610 
1611 	error = device_probe(dev);
1612 	if (error == -1)
1613 		return (0);
1614 	else if (error != 0)
1615 		return (error);
1616 
1617 	//CURVNET_SET_QUIET(vnet0);
1618 	error = device_attach(dev);
1619 	//CURVNET_RESTORE();
1620         PDEBUG(("-"));
1621 	return error;
1622 }
1623 
1624 /**
1625  * @brief Attach a device driver to a device
1626  *
1627  * This function is a wrapper around the DEVICE_ATTACH() driver
1628  * method. In addition to calling DEVICE_ATTACH(), it initialises the
1629  * device's sysctl tree, optionally prints a description of the device
1630  * and queues a notification event for user-based device management
1631  * services.
1632  *
1633  * Normally this function is only called internally from
1634  * device_probe_and_attach().
1635  *
1636  * @param dev           the device to initialise
1637  *
1638  * @retval 0            success
1639  * @retval ENXIO        no driver was found
1640  * @retval ENOMEM       memory allocation failure
1641  * @retval non-zero     some other unix error code
1642  */
1643 int
device_attach(device_t dev)1644 device_attach(device_t dev)
1645 {
1646         uint64_t attachtime;
1647         int error;
1648         PDEBUG(("+"));
1649 
1650         //if (resource_disabled(dev->driver->name, dev->unit)) {
1651         //        device_disable(dev);
1652         //        if (bootverbose)
1653         //                 device_printf(dev, "disabled via hints entry\n");
1654         //        return (ENXIO);
1655         //}
1656 
1657         //device_sysctl_init(dev);
1658         if (!device_is_quiet(dev))
1659                 device_print_child(dev->parent, dev);
1660         // attachtime = get_cyclecount();
1661         dev->state = DS_ATTACHING;
1662         if ((error = DEVICE_ATTACH(dev)) != 0) {
1663                 printf("device_attach: %s%d attach returned %d\n",
1664                     dev->driver->name, dev->unit, error);
1665                 if (!(dev->flags & DF_FIXEDCLASS))
1666                         devclass_delete_device(dev->devclass, dev);
1667                 (void)device_set_driver(dev, NULL);
1668                 //device_sysctl_fini(dev);
1669                 KASSERT(dev->busy == 0, ("attach failed but busy"));
1670                 dev->state = DS_NOTPRESENT;
1671                 return (error);
1672         }
1673         // attachtime = get_cyclecount() - attachtime;
1674         /*
1675          * 4 bits per device is a reasonable value for desktop and server
1676          * hardware with good get_cyclecount() implementations, but WILL
1677          * need to be adjusted on other platforms.
1678          */
1679 #define RANDOM_PROBE_BIT_GUESS  4
1680         if (bootverbose)
1681                 printf("random: harvesting attach, %zu bytes (%d bits) from %s%d\n",
1682                     sizeof(attachtime), RANDOM_PROBE_BIT_GUESS,
1683                     dev->driver->name, dev->unit);
1684         //random_harvest_direct(&attachtime, sizeof(attachtime),
1685         //    RANDOM_PROBE_BIT_GUESS, RANDOM_ATTACH);
1686         //device_sysctl_update(dev);
1687         if (dev->busy)
1688                 dev->state = DS_BUSY;
1689         else
1690                 dev->state = DS_ATTACHED;
1691         dev->flags &= ~DF_DONENOMATCH;
1692         //EVENTHANDLER_INVOKE(device_attach, dev);
1693         //devadded(dev);
1694         PDEBUG(("-"));
1695         return (0);
1696 }
1697 
1698 /**
1699  * @brief Probe a device, and return this status.
1700  *
1701  * This function is the core of the device autoconfiguration
1702  * system. Its purpose is to select a suitable driver for a device and
1703  * then call that driver to initialise the hardware appropriately. The
1704  * driver is selected by calling the DEVICE_PROBE() method of a set of
1705  * candidate drivers and then choosing the driver which returned the
1706  * best value. This driver is then attached to the device using
1707  * device_attach().
1708  *
1709  * The set of suitable drivers is taken from the list of drivers in
1710  * the parent device's devclass. If the device was originally created
1711  * with a specific class name (see device_add_child()), only drivers
1712  * with that name are probed, otherwise all drivers in the devclass
1713  * are probed. If no drivers return successful probe values in the
1714  * parent devclass, the search continues in the parent of that
1715  * devclass (see devclass_get_parent()) if any.
1716  *
1717  * @param dev		the device to initialise
1718  *
1719  * @retval 0		success
1720  * @retval ENXIO	no driver was found
1721  * @retval ENOMEM	memory allocation failure
1722  * @retval non-zero	some other unix error code
1723  * @retval -1		Device already attached
1724  */
1725 int
device_probe(device_t dev)1726 device_probe(device_t dev)
1727 {
1728 	int error;
1729 
1730 	GIANT_REQUIRED;
1731         PDEBUG(("+"));
1732 
1733 	if (dev->state >= DS_ALIVE && (dev->flags & DF_REBID) == 0)
1734 		return (-1);
1735 
1736 	if (!(dev->flags & DF_ENABLED)) {
1737 		if (bootverbose && device_get_name(dev) != NULL) {
1738 			device_print_prettyname(dev);
1739 			printf("not probed (disabled)\n");
1740 		}
1741 		return (-1);
1742 	}
1743 	if ((error = device_probe_child(dev->parent, dev)) != 0) {
1744 		if (bus_current_pass == BUS_PASS_DEFAULT &&
1745 		    !(dev->flags & DF_DONENOMATCH)) {
1746 			BUS_PROBE_NOMATCH(dev->parent, dev);
1747 			//devnomatch(dev);
1748 			dev->flags |= DF_DONENOMATCH;
1749 		}
1750 		return (error);
1751 	}
1752         PDEBUG(("-"));
1753 	return (0);
1754 }
1755 
1756 /**
1757  * @brief Tells a driver to quiesce itself.
1758  *
1759  * This function is a wrapper around the DEVICE_QUIESCE() driver
1760  * method. If the call to DEVICE_QUIESCE() succeeds.
1761  *
1762  * @param dev           the device to quiesce
1763  *
1764  * @retval 0            success
1765  * @retval ENXIO        no driver was found
1766  * @retval ENOMEM       memory allocation failure
1767  * @retval non-zero     some other unix error code
1768  */
1769 int
device_quiesce(device_t dev)1770 device_quiesce(device_t dev)
1771 {
1772 
1773         PDEBUG(("%s", DEVICENAME(dev)));
1774         if (dev->state == DS_BUSY)
1775                 return (EBUSY);
1776         if (dev->state != DS_ATTACHED)
1777                 return (0);
1778 
1779         return (DEVICE_QUIESCE(dev));
1780 }
1781 
1782 /**
1783  * @brief Notify a device of system shutdown
1784  *
1785  * This function calls the DEVICE_SHUTDOWN() driver method if the
1786  * device currently has an attached driver.
1787  *
1788  * @returns the value returned by DEVICE_SHUTDOWN()
1789  */
1790 int
device_shutdown(device_t dev)1791 device_shutdown(device_t dev)
1792 {
1793         if (dev->state < DS_ATTACHED)
1794                 return (0);
1795         return (DEVICE_SHUTDOWN(dev));
1796 }
1797 
1798 // bus
1799 //
1800 //
1801 device_t
bus_generic_add_child(device_t dev,u_int order,const char * name,int unit)1802 bus_generic_add_child(device_t dev, u_int order, const char *name, int unit)
1803 {
1804 
1805         return (device_add_child_ordered(dev, order, name, unit));
1806 }
1807 
1808 /**
1809  * @brief Helper function for implementing DEVICE_PROBE()
1810  *
1811  * This function can be used to help implement the DEVICE_PROBE() for
1812  * a bus (i.e. a device which has other devices attached to it). It
1813  * calls the DEVICE_IDENTIFY() method of each driver in the device's
1814  * devclass.
1815  */
1816 int
bus_generic_probe(device_t dev)1817 bus_generic_probe(device_t dev)
1818 {
1819         devclass_t dc = dev->devclass;
1820         driverlink_t dl = NULL;
1821         PDEBUG(("+"));
1822 
1823         TAILQ_FOREACH(dl, &dc->drivers, link) {
1824                 /*
1825                  * If this driver's pass is too high, then ignore it.
1826                  * For most drivers in the default pass, this will
1827                  * never be true.  For early-pass drivers they will
1828                  * only call the identify routines of eligible drivers
1829                  * when this routine is called.  Drivers for later
1830                  * passes should have their identify routines called
1831                  * on early-pass busses during BUS_NEW_PASS().
1832                  */
1833                 if (dl->pass > bus_current_pass)
1834                         continue;
1835                 DEVICE_IDENTIFY(dl->driver, dev);
1836         }
1837 
1838         PDEBUG(("-"));
1839         return (0);
1840 }
1841 
1842 /**
1843  * @brief Helper function for implementing DEVICE_ATTACH()
1844  *
1845  * This function can be used to help implement the DEVICE_ATTACH() for
1846  * a bus. It calls device_probe_and_attach() for each of the device's
1847  * children.
1848  */
1849 int
bus_generic_attach(device_t dev)1850 bus_generic_attach(device_t dev)
1851 {
1852         device_t child;
1853 
1854         PDEBUG(("+"));
1855         TAILQ_FOREACH(child, &dev->children, link) {
1856                 device_probe_and_attach(child);
1857         }
1858         PDEBUG(("-"));
1859         return (0);
1860 }
1861 
1862 /**
1863  * @brief Helper function for implementing DEVICE_DETACH()
1864  *
1865  * This function can be used to help implement the DEVICE_DETACH() for
1866  * a bus. It calls device_detach() for each of the device's
1867  * children.
1868  */
1869 int
bus_generic_detach(device_t dev)1870 bus_generic_detach(device_t dev)
1871 {
1872         device_t child;
1873         int error;
1874 
1875         if (dev->state != DS_ATTACHED)
1876                 return (EBUSY);
1877 
1878         /*
1879          * Detach children in the reverse order.
1880          * See bus_generic_suspend for details.
1881          */
1882         TAILQ_FOREACH_REVERSE(child, &dev->children, device_list, link) {
1883                 if ((error = device_detach(child)) != 0)
1884                         return (error);
1885         }
1886 
1887         return (0);
1888 }
1889 
1890 /**
1891  * @brief Helper function for implementing DEVICE_SHUTDOWN()
1892  *
1893  * This function can be used to help implement the DEVICE_SHUTDOWN()
1894  * for a bus. It calls device_shutdown() for each of the device's
1895  * children.
1896  */
1897 int
bus_generic_shutdown(device_t dev)1898 bus_generic_shutdown(device_t dev)
1899 {
1900         device_t child;
1901 
1902         /*
1903          * Shut down children in the reverse order.
1904          * See bus_generic_suspend for details.
1905          */
1906         TAILQ_FOREACH_REVERSE(child, &dev->children, device_list, link) {
1907                 device_shutdown(child);
1908         }
1909 
1910         return (0);
1911 }
1912 
1913 /**
1914  * @brief Default function for suspending a child device.
1915  *
1916  * This function is to be used by a bus's DEVICE_SUSPEND_CHILD().
1917  */
1918 int
bus_generic_suspend_child(device_t dev,device_t child)1919 bus_generic_suspend_child(device_t dev, device_t child)
1920 {
1921         int     error;
1922 
1923         error = DEVICE_SUSPEND(child);
1924 
1925         if (error == 0)
1926                 child->flags |= DF_SUSPENDED;
1927 
1928         return (error);
1929 }
1930 
1931 /**
1932  * @brief Default function for resuming a child device.
1933  *
1934  * This function is to be used by a bus's DEVICE_RESUME_CHILD().
1935  */
1936 int
bus_generic_resume_child(device_t dev,device_t child)1937 bus_generic_resume_child(device_t dev, device_t child)
1938 {
1939 
1940         DEVICE_RESUME(child);
1941         child->flags &= ~DF_SUSPENDED;
1942 
1943         return (0);
1944 }
1945 
1946 /**
1947  * @brief Helper function for implementing DEVICE_SUSPEND()
1948  *
1949  * This function can be used to help implement the DEVICE_SUSPEND()
1950  * for a bus. It calls DEVICE_SUSPEND() for each of the device's
1951  * children. If any call to DEVICE_SUSPEND() fails, the suspend
1952  * operation is aborted and any devices which were suspended are
1953  * resumed immediately by calling their DEVICE_RESUME() methods.
1954  */
1955 int
bus_generic_suspend(device_t dev)1956 bus_generic_suspend(device_t dev)
1957 {
1958         int             error;
1959         device_t        child;
1960 
1961         /*
1962          * Suspend children in the reverse order.
1963          * For most buses all children are equal, so the order does not matter.
1964          * Other buses, such as acpi, carefully order their child devices to
1965          * express implicit dependencies between them.  For such buses it is
1966          * safer to bring down devices in the reverse order.
1967          */
1968         TAILQ_FOREACH_REVERSE(child, &dev->children, device_list, link) {
1969                 error = BUS_SUSPEND_CHILD(dev, child);
1970                 if (error != 0) {
1971                         child = TAILQ_NEXT(child, link);
1972                         if (child != NULL) {
1973                                 TAILQ_FOREACH_FROM(child, &dev->children, link)
1974                                         BUS_RESUME_CHILD(dev, child);
1975                         }
1976                         return (error);
1977                 }
1978         }
1979         return (0);
1980 }
1981 
1982 /**
1983  * @brief Helper function for implementing DEVICE_RESUME()
1984  *
1985  * This function can be used to help implement the DEVICE_RESUME() for
1986  * a bus. It calls DEVICE_RESUME() on each of the device's children.
1987  */
1988 int
bus_generic_resume(device_t dev)1989 bus_generic_resume(device_t dev)
1990 {
1991         device_t        child;
1992 
1993         TAILQ_FOREACH(child, &dev->children, link) {
1994                 BUS_RESUME_CHILD(dev, child);
1995                 /* if resume fails, there's nothing we can usefully do... */
1996         }
1997         return (0);
1998 }
1999 
2000 
2001 
2002 /**
2003  * @brief Helper function for implementing BUS_PRINT_CHILD().
2004  *
2005  * This function prints the first part of the ascii representation of
2006  * @p child, including its name, unit and description (if any - see
2007  * device_set_desc()).
2008  *
2009  * @returns the number of characters printed
2010  */
2011 int
bus_print_child_header(device_t dev,device_t child)2012 bus_print_child_header(device_t dev, device_t child)
2013 {
2014         int     retval = 0;
2015 
2016         if (device_get_desc(child)) {
2017                 retval += device_printf(child, "<%s>", device_get_desc(child));
2018         } else {
2019                 retval += printf("%s", device_get_nameunit(child));
2020         }
2021 
2022         return (retval);
2023 }
2024 
2025 /**
2026  * @brief Helper function for implementing BUS_PRINT_CHILD().
2027  *
2028  * This function prints the last part of the ascii representation of
2029  * @p child, which consists of the string @c " on " followed by the
2030  * name and unit of the @p dev.
2031  *
2032  * @returns the number of characters printed
2033  */
2034 int
bus_print_child_footer(device_t dev,device_t child)2035 bus_print_child_footer(device_t dev, device_t child)
2036 {
2037         return (printf(" on %s\n", device_get_nameunit(dev)));
2038 }
2039 
2040 /**
2041  * @brief Helper function for implementing BUS_PRINT_CHILD().
2042  *
2043  * This function prints out the VM domain for the given device.
2044  *
2045  * @returns the number of characters printed
2046  */
2047 int
bus_print_child_domain(device_t dev,device_t child)2048 bus_print_child_domain(device_t dev, device_t child)
2049 {
2050         int domain;
2051 
2052         /* No domain? Don't print anything */
2053         if (BUS_GET_DOMAIN(dev, child, &domain) != 0)
2054                 return (0);
2055 
2056         return (printf(" numa-domain %d", domain));
2057 }
2058 
2059 /**
2060  * @brief Helper function for implementing BUS_PRINT_CHILD().
2061  *
2062  * This function simply calls bus_print_child_header() followed by
2063  * bus_print_child_footer().
2064  *
2065  * @returns the number of characters printed
2066  */
2067 int
bus_generic_print_child(device_t dev,device_t child)2068 bus_generic_print_child(device_t dev, device_t child)
2069 {
2070         int     retval = 0;
2071 
2072         retval += bus_print_child_header(dev, child);
2073         retval += bus_print_child_domain(dev, child);
2074         retval += bus_print_child_footer(dev, child);
2075 
2076         return (retval);
2077 }
2078 
2079 /**
2080  * @brief Helper function for implementing BUS_DRIVER_ADDED().
2081  *
2082  * This implementation of BUS_DRIVER_ADDED() simply calls the driver's
2083  * DEVICE_IDENTIFY() method to allow it to add new children to the bus
2084  * and then calls device_probe_and_attach() for each unattached child.
2085  */
2086 void
bus_generic_driver_added(device_t dev,driver_t * driver)2087 bus_generic_driver_added(device_t dev, driver_t *driver)
2088 {
2089         device_t child;
2090         PDEBUG(("+"));
2091 
2092         DEVICE_IDENTIFY(driver, dev);
2093         PDEBUG(("dev->children %p", dev->children));
2094         TAILQ_FOREACH(child, &dev->children, link) {
2095                 if (child->state == DS_NOTPRESENT ||
2096                     (child->flags & DF_REBID))
2097                         device_probe_and_attach(child);
2098         }
2099         PDEBUG(("-"));
2100 }
2101 
2102 /**
2103  * @brief Helper function for implementing BUS_NEW_PASS().
2104  *
2105  * This implementing of BUS_NEW_PASS() first calls the identify
2106  * routines for any drivers that probe at the current pass.  Then it
2107  * walks the list of devices for this bus.  If a device is already
2108  * attached, then it calls BUS_NEW_PASS() on that device.  If the
2109  * device is not already attached, it attempts to attach a driver to
2110  * it.
2111  */
2112 void
bus_generic_new_pass(device_t dev)2113 bus_generic_new_pass(device_t dev)
2114 {
2115         driverlink_t dl = NULL;
2116         devclass_t dc;
2117         device_t child;
2118 
2119         dc = dev->devclass;
2120         TAILQ_FOREACH(dl, &dc->drivers, link) {
2121                 if (dl->pass == bus_current_pass)
2122                         DEVICE_IDENTIFY(dl->driver, dev);
2123         }
2124         TAILQ_FOREACH(child, &dev->children, link) {
2125                 if (child->state >= DS_ATTACHED)
2126                         BUS_NEW_PASS(child);
2127                 else if (child->state == DS_NOTPRESENT)
2128                         device_probe_and_attach(child);
2129         }
2130 }
2131 
2132 // delete resouce and intr
2133 
2134 /**
2135  * @brief Helper function for implementing BUS_CHILD_PRESENT().
2136  *
2137  * This simple implementation of BUS_CHILD_PRESENT() simply calls the
2138  * BUS_CHILD_PRESENT() method of the parent of @p dev.
2139  */
2140 int
bus_generic_child_present(device_t dev,device_t child)2141 bus_generic_child_present(device_t dev, device_t child)
2142 {
2143         return (BUS_CHILD_PRESENT(device_get_parent(dev), dev));
2144 }
2145 
2146 int
bus_generic_get_domain(device_t dev,device_t child,int * domain)2147 bus_generic_get_domain(device_t dev, device_t child, int *domain)
2148 {
2149 
2150         if (dev->parent)
2151                 return (BUS_GET_DOMAIN(dev->parent, dev, domain));
2152 
2153         return (ENOENT);
2154 }
2155 
2156 /**
2157  * @brief Helper function for implementing BUS_RESCAN().
2158  *
2159  * This null implementation of BUS_RESCAN() always fails to indicate
2160  * the bus does not support rescanning.
2161  */
2162 int
bus_null_rescan(device_t dev)2163 bus_null_rescan(device_t dev)
2164 {
2165 
2166         return (ENXIO);
2167 }
2168 
2169 /**
2170  * @brief Wrapper function for BUS_CHILD_PRESENT().
2171  *
2172  * This function simply calls the BUS_CHILD_PRESENT() method of the
2173  * parent of @p dev.
2174  */
2175 int
bus_child_present(device_t child)2176 bus_child_present(device_t child)
2177 {
2178         return (BUS_CHILD_PRESENT(device_get_parent(child), child));
2179 }
2180 
2181 /**
2182  * @brief Wrapper function for BUS_GET_DOMAIN().
2183  *
2184  * This function simply calls the BUS_GET_DOMAIN() method of the
2185  * parent of @p dev.
2186  */
2187 int
bus_get_domain(device_t dev,int * domain)2188 bus_get_domain(device_t dev, int *domain)
2189 {
2190         return (BUS_GET_DOMAIN(device_get_parent(dev), dev, domain));
2191 }
2192 
2193 int
bus_data_generation_check(int generation)2194 bus_data_generation_check(int generation)
2195 {
2196 	if (generation != bus_data_generation)
2197 	return (1);
2198 
2199 	/* XXX generate optimised lists here? */
2200 	return (0);
2201 }
2202 
2203 void
bus_data_generation_update(void)2204 bus_data_generation_update(void)
2205 {
2206 	bus_data_generation++;
2207 }
2208 
2209 /**
2210  * @brief Print the name of the device followed by a colon and a space
2211  *
2212  * @returns the number of characters printed
2213  */
2214 int
device_print_prettyname(device_t dev)2215 device_print_prettyname(device_t dev)
2216 {
2217 	const char *name = device_get_name(dev);
2218 
2219 	if (name == NULL)
2220 		return (printf("unknown: "));
2221 	return (printf("%s%d: ", name, device_get_unit(dev)));
2222 }
2223 
2224 /**
2225  * @brief Return the device's unit number.
2226  */
2227 int
device_get_unit(device_t dev)2228 device_get_unit(device_t dev)
2229 {
2230 	return (dev->unit);
2231 }
2232 
2233 /**
2234  * @internal
2235  */
2236 static driverlink_t
first_matching_driver(devclass_t dc,device_t dev)2237 first_matching_driver(devclass_t dc, device_t dev)
2238 {
2239 	if (dev->devclass)
2240 		return (devclass_find_driver_internal(dc, dev->devclass->name));
2241 	return (TAILQ_FIRST(&dc->drivers));
2242 }
2243 
2244 /**
2245  * @internal
2246  */
2247 static driverlink_t
next_matching_driver(devclass_t dc,device_t dev,driverlink_t last)2248 next_matching_driver(devclass_t dc, device_t dev, driverlink_t last)
2249 {
2250 	if (dev->devclass) {
2251 		driverlink_t dl;
2252 		for (dl = TAILQ_NEXT(last, link); dl; dl = TAILQ_NEXT(dl, link))
2253 			if (!strcmp(dev->devclass->name, dl->driver->name))
2254 				return (dl);
2255 		return (NULL);
2256 	}
2257 	return (TAILQ_NEXT(last, link));
2258 }
2259 
2260 
2261 /**
2262  * @brief Set the devclass of a device
2263  * @see devclass_add_device().
2264  */
2265 int
device_set_devclass(device_t dev,const char * classname)2266 device_set_devclass(device_t dev, const char *classname)
2267 {
2268 	devclass_t dc;
2269 	int error;
2270 
2271 	if (!classname) {
2272 		if (dev->devclass)
2273 			devclass_delete_device(dev->devclass, dev);
2274 		return (0);
2275 	}
2276 
2277 	if (dev->devclass) {
2278 		printf("device_set_devclass: device class already set\n");
2279 		return (EINVAL);
2280 	}
2281 
2282 	dc = devclass_find_internal(classname, NULL, TRUE);
2283 	if (!dc)
2284 		return (ENOMEM);
2285 
2286 	error = devclass_add_device(dc, dev);
2287 
2288 	bus_data_generation_update();
2289 	return (error);
2290 }
2291 
2292 /**
2293  * @brief Detach a driver from a device
2294  *
2295  * This function is a wrapper around the DEVICE_DETACH() driver
2296  * method. If the call to DEVICE_DETACH() succeeds, it calls
2297  * BUS_CHILD_DETACHED() for the parent of @p dev, queues a
2298  * notification event for user-based device management services and
2299  * cleans up the device's sysctl tree.
2300  *
2301  * @param dev		the device to un-initialise
2302  *
2303  * @retval 0		success
2304  * @retval ENXIO	no driver was found
2305  * @retval ENOMEM	memory allocation failure
2306  * @retval non-zero	some other unix error code
2307  */
2308 int
device_detach(device_t dev)2309 device_detach(device_t dev)
2310 {
2311 	int error;
2312 
2313 	GIANT_REQUIRED;
2314 
2315 	PDEBUG(("%s", DEVICENAME(dev)));
2316 	if (dev->state == DS_BUSY)
2317 		return (EBUSY);
2318 	if (dev->state == DS_ATTACHING) {
2319 		device_printf(dev, "device in attaching state! Deferring detach.\n");
2320 		return (EBUSY);
2321 	}
2322 	if (dev->state != DS_ATTACHED)
2323 		return (0);
2324 
2325 	if ((error = DEVICE_DETACH(dev)) != 0) {
2326 		return (error);
2327 	}
2328 
2329 	if (!device_is_quiet(dev))
2330 		device_printf(dev, "detached\n");
2331 	if (dev->parent) {
2332 		PDEBUG(("BUS_CHILD_DETACHED %s", DEVICENAME(dev->parent)));
2333 		BUS_CHILD_DETACHED(dev->parent, dev);
2334 	}
2335 
2336 	if (!(dev->flags & DF_FIXEDCLASS)) {
2337 		PDEBUG(("devclass_delete_device"));
2338 		devclass_delete_device(dev->devclass, dev);
2339 	}
2340 
2341 	device_verbose(dev);
2342 	dev->state = DS_NOTPRESENT;
2343 	(void)device_set_driver(dev, NULL);
2344 
2345 	return (0);
2346 }
2347 
2348 /**
2349  * @brief Return the parent of a device
2350  */
2351 device_t
device_get_parent(device_t dev)2352 device_get_parent(device_t dev)
2353 {
2354 	return (dev->parent);
2355 }
2356 
2357 /**
2358  * @brief Print the name of the device followed by a colon, a space
2359  * and the result of calling vprintf() with the value of @p fmt and
2360  * the following arguments.
2361  *
2362  * @returns the number of characters printed
2363  */
2364 int
device_printf(device_t dev,const char * fmt,...)2365 device_printf(device_t dev, const char * fmt, ...)
2366 {
2367 	va_list ap;
2368 	int retval;
2369 
2370 	retval = device_print_prettyname(dev);
2371 	va_start(ap, fmt);
2372 	retval += vprintf(fmt, ap);
2373 	va_end(ap);
2374 	return (retval);
2375 }
2376 
2377 /**
2378  * @brief Set the driver of a device
2379  *
2380  * @retval 0		success
2381  * @retval EBUSY	the device already has a driver attached
2382  * @retval ENOMEM	a memory allocation failure occurred
2383  */
2384 int
device_set_driver(device_t dev,driver_t * driver)2385 device_set_driver(device_t dev, driver_t *driver)
2386 {
2387 	if (dev->state >= DS_ATTACHED)
2388 		return (EBUSY);
2389 
2390 	if (dev->driver == driver)
2391 		return (0);
2392 
2393 	if (dev->softc && !(dev->flags & DF_EXTERNALSOFTC)) {
2394 		bsd_free(dev->softc, M_BUS_SC);
2395 		dev->softc = NULL;
2396 	}
2397 	device_set_desc(dev, NULL);
2398 	kobj_delete((kobj_t) dev, NULL);
2399 	dev->driver = driver;
2400 	if (driver) {
2401 		kobj_init((kobj_t) dev, (kobj_class_t) driver);
2402 		if (!(dev->flags & DF_EXTERNALSOFTC) && driver->size > 0) {
2403 			dev->softc = bsd_malloc(driver->size, M_BUS_SC,
2404 			    M_NOWAIT | M_ZERO);
2405 			if (!dev->softc) {
2406 				kobj_delete((kobj_t) dev, NULL);
2407 				kobj_init((kobj_t) dev, &null_class);
2408 				dev->driver = NULL;
2409 				return (ENOMEM);
2410 			}
2411 		}
2412 	} else {
2413 		kobj_init((kobj_t) dev, &null_class);
2414 	}
2415 
2416 	bus_data_generation_update();
2417 	return (0);
2418 }
2419 
2420 /**
2421  * @internal
2422  */
2423 int
device_probe_child(device_t dev,device_t child)2424 device_probe_child(device_t dev, device_t child)
2425 {
2426 	devclass_t dc;
2427 	driverlink_t best = NULL;
2428 	driverlink_t dl = NULL;
2429 	int result, pri = 0;
2430 	int hasclass = (child->devclass != NULL);
2431 
2432 	GIANT_REQUIRED;
2433 
2434 	dc = dev->devclass;
2435 	if (!dc)
2436 		panic("device_probe_child: parent device has no devclass");
2437 
2438 	/*
2439 	 * If the state is already probed, then return.  However, don't
2440 	 * return if we can rebid this object.
2441 	 */
2442 	if (child->state == DS_ALIVE && (child->flags & DF_REBID) == 0)
2443 		return (0);
2444 
2445 	for (; dc; dc = dc->parent) {
2446 		for (dl = first_matching_driver(dc, child);
2447 		     dl;
2448 		     dl = next_matching_driver(dc, child, dl)) {
2449 			/* If this driver's pass is too high, then ignore it. */
2450 			if (dl->pass > bus_current_pass)
2451 				continue;
2452 
2453 			PDEBUG(("Trying %s", DRIVERNAME(dl->driver)));
2454 			result = device_set_driver(child, dl->driver);
2455 			if (result == ENOMEM)
2456 				return (result);
2457 			else if (result != 0)
2458 				continue;
2459 			if (!hasclass) {
2460 				if (device_set_devclass(child,
2461 				    dl->driver->name) != 0) {
2462 					char const * devname =
2463 					    device_get_name(child);
2464 					if (devname == NULL)
2465 						devname = "(unknown)";
2466 					printf("driver bug: Unable to set "
2467 					    "devclass (class: %s "
2468 					    "devname: %s)\n",
2469 					    dl->driver->name,
2470 					    devname);
2471 					(void)device_set_driver(child, NULL);
2472 					continue;
2473 				}
2474 			}
2475 
2476 			/* Fetch any flags for the device before probing. */
2477 			// resource_int_value(dl->driver->name, child->unit,
2478 			    // "flags", &child->devflags);
2479                         PDEBUG(("start DEVICE_PROBE"));
2480 			result = DEVICE_PROBE(child);
2481 
2482 			/* Reset flags and devclass before the next probe. */
2483 			child->devflags = 0;
2484 			if (!hasclass)
2485 				(void)device_set_devclass(child, NULL);
2486 
2487 			/*
2488 			 * If the driver returns SUCCESS, there can be
2489 			 * no higher match for this device.
2490 			 */
2491 			if (result == 0) {
2492 				best = dl;
2493 				pri = 0;
2494 				break;
2495 			}
2496 
2497 			/*
2498 			 * Reset DF_QUIET in case this driver doesn't
2499 			 * end up as the best driver.
2500 			 */
2501 			device_verbose(child);
2502 
2503                         PDEBUG(("probe result: %d", result));
2504 			/*
2505 			 * Probes that return BUS_PROBE_NOWILDCARD or lower
2506 			 * only match on devices whose driver was explicitly
2507 			 * specified.
2508 			 */
2509 			if (result <= BUS_PROBE_NOWILDCARD &&
2510 			    !(child->flags & DF_FIXEDCLASS)) {
2511 				result = ENXIO;
2512 			}
2513 
2514 			/*
2515 			 * The driver returned an error so it
2516 			 * certainly doesn't match.
2517 			 */
2518 			if (result > 0) {
2519 				(void)device_set_driver(child, NULL);
2520 				continue;
2521 			}
2522 
2523 			/*
2524 			 * A priority lower than SUCCESS, remember the
2525 			 * best matching driver. Initialise the value
2526 			 * of pri for the first match.
2527 			 */
2528 			if (best == NULL || result > pri) {
2529 				best = dl;
2530 				pri = result;
2531 				continue;
2532 			}
2533 		}
2534 		/*
2535 		 * If we have an unambiguous match in this devclass,
2536 		 * don't look in the parent.
2537 		 */
2538 		if (best && pri == 0)
2539 			break;
2540 	}
2541 
2542 	/*
2543 	 * If we found a driver, change state and initialise the devclass.
2544 	 */
2545 	/* XXX What happens if we rebid and got no best? */
2546 	if (best) {
2547                 PDEBUG(("in best"));
2548 		/*
2549 		 * If this device was attached, and we were asked to
2550 		 * rescan, and it is a different driver, then we have
2551 		 * to detach the old driver and reattach this new one.
2552 		 * Note, we don't have to check for DF_REBID here
2553 		 * because if the state is > DS_ALIVE, we know it must
2554 		 * be.
2555 		 *
2556 		 * This assumes that all DF_REBID drivers can have
2557 		 * their probe routine called at any time and that
2558 		 * they are idempotent as well as completely benign in
2559 		 * normal operations.
2560 		 *
2561 		 * We also have to make sure that the detach
2562 		 * succeeded, otherwise we fail the operation (or
2563 		 * maybe it should just fail silently?  I'm torn).
2564 		 */
2565 		if (child->state > DS_ALIVE && best->driver != child->driver)
2566 			if ((result = device_detach(dev)) != 0)
2567 				return (result);
2568 
2569 		/* Set the winning driver, devclass, and flags. */
2570 		if (!child->devclass) {
2571 			result = device_set_devclass(child, best->driver->name);
2572 			if (result != 0)
2573 				return (result);
2574 		}
2575 		result = device_set_driver(child, best->driver);
2576 		if (result != 0)
2577 			return (result);
2578 		// resource_int_value(best->driver->name, child->unit,
2579 		    // "flags", &child->devflags);
2580 
2581 		if (pri < 0) {
2582 			/*
2583 			 * A bit bogus. Call the probe method again to make
2584 			 * sure that we have the right description.
2585 			 */
2586 			DEVICE_PROBE(child);
2587 #if 0
2588 			child->flags |= DF_REBID;
2589 #endif
2590 		} else
2591 			child->flags &= ~DF_REBID;
2592 		child->state = DS_ALIVE;
2593 
2594 		bus_data_generation_update();
2595                 PDEBUG(("-"));
2596 		return (0);
2597 	}
2598 
2599         PDEBUG(("ENXIO -"));
2600 	return (ENXIO);
2601 }
2602 
2603 
2604 /**
2605  * @brief Return the current devclass for the device or @c NULL if
2606  * there is none.
2607  */
2608 devclass_t
device_get_devclass(device_t dev)2609 device_get_devclass(device_t dev)
2610 {
2611 	return (dev->devclass);
2612 }
2613 
2614 /**
2615  * @brief Initialise a resource list.
2616  *
2617  * @param rl		the resource list to initialise
2618  */
2619 void
resource_list_init(struct resource_list * rl)2620 resource_list_init(struct resource_list *rl)
2621 {
2622 	STAILQ_INIT(rl);
2623 }
2624 
2625 /**
2626  * @brief Reclaim memory used by a resource list.
2627  *
2628  * This function frees the memory for all resource entries on the list
2629  * (if any).
2630  *
2631  * @param rl		the resource list to free
2632  */
2633 void
resource_list_free(struct resource_list * rl)2634 resource_list_free(struct resource_list *rl)
2635 {
2636 	struct resource_list_entry *rle;
2637 
2638 	while ((rle = STAILQ_FIRST(rl)) != NULL) {
2639 		if (rle->res)
2640 			bsd_free(rle->res, M_BUS);
2641 		STAILQ_REMOVE_HEAD(rl, link);
2642 		bsd_free(rle, M_BUS);
2643 	}
2644 }
2645 
2646 /**
2647  * @brief Add or modify a resource entry.
2648  *
2649  * If an existing entry exists with the same type and rid, it will be
2650  * modified using the given values of @p start, @p end and @p
2651  * count. If no entry exists, a new one will be created using the
2652  * given values.  The resource list entry that matches is then returned.
2653  *
2654  * @param rl		the resource list to edit
2655  * @param type		the resource entry type (e.g. SYS_RES_MEMORY)
2656  * @param rid		the resource identifier
2657  * @param start		the start address of the resource
2658  * @param end		the end address of the resource
2659  * @param count		XXX end-start+1
2660  */
2661 struct resource_list_entry *
resource_list_add(struct resource_list * rl,int type,int rid,rman_res_t start,rman_res_t end,rman_res_t count)2662 resource_list_add(struct resource_list *rl, int type, int rid,
2663     rman_res_t start, rman_res_t end, rman_res_t count)
2664 {
2665 	struct resource_list_entry *rle;
2666 
2667 	rle = resource_list_find(rl, type, rid);
2668 	if (!rle) {
2669 		rle = bsd_malloc(sizeof(struct resource_list_entry), M_BUS,
2670 		    M_NOWAIT);
2671 		if (!rle)
2672 			panic("resource_list_add: can't record entry");
2673 		STAILQ_INSERT_TAIL(rl, rle, link);
2674 		rle->type = type;
2675 		rle->rid = rid;
2676 		rle->res = NULL;
2677 		rle->flags = 0;
2678 	}
2679 
2680 	if (rle->res)
2681 		panic("resource_list_add: resource entry is busy");
2682 
2683 	rle->res = bsd_malloc(sizeof(struct resource), M_BUS, M_NOWAIT);
2684 	if (rle->res == NULL) {
2685 		panic("resource_list_add: resource is busy");
2686 	}
2687 	rle->res->start = start;
2688 	rle->res->end = end;
2689 	rle->res->count = count;
2690 	return (rle);
2691 }
2692 
2693 /**
2694  * @brief Find a resource entry by type and rid.
2695  *
2696  * @param rl		the resource list to search
2697  * @param type		the resource entry type (e.g. SYS_RES_MEMORY)
2698  * @param rid		the resource identifier
2699  *
2700  * @returns the resource entry pointer or NULL if there is no such
2701  * entry.
2702  */
2703 struct resource_list_entry *
resource_list_find(struct resource_list * rl,int type,int rid)2704 resource_list_find(struct resource_list *rl, int type, int rid)
2705 {
2706 	struct resource_list_entry *rle = NULL;
2707 
2708 	STAILQ_FOREACH(rle, rl, link) {
2709 		if (rle->type == type && rle->rid == rid)
2710 			return (rle);
2711 	}
2712 	return (NULL);
2713 }
2714 
2715 /**
2716  * @brief Wrapper function for BUS_ALLOC_RESOURCE().
2717  *
2718  * This function simply calls the BUS_ALLOC_RESOURCE() method of the
2719  * parent of @p dev.
2720  */
2721 struct resource *
bus_alloc_resource(device_t dev,int type,int * rid,rman_res_t start,rman_res_t end,rman_res_t count,u_int flags)2722 bus_alloc_resource(device_t dev, int type, int *rid, rman_res_t start,
2723     rman_res_t end, rman_res_t count, u_int flags)
2724 {
2725 	struct resource *res = NULL;
2726 
2727 	if (dev->parent == NULL)
2728 		return (NULL);
2729 	res = BUS_ALLOC_RESOURCE(dev->parent, dev, type, rid, start, end,
2730 	    count, flags);
2731 	return (res);
2732 }
2733 
2734 // root driver
2735 static int
root_print_child(device_t dev,device_t child)2736 root_print_child(device_t dev, device_t child)
2737 {
2738         int     retval = 0;
2739 
2740         retval += bus_print_child_header(dev, child);
2741         retval += printf("\n");
2742 
2743         return (retval);
2744 }
2745 
2746 static kobj_method_t root_methods[] = {
2747 	/* Device interface */
2748 	KOBJMETHOD(device_shutdown,     bus_generic_shutdown),
2749 	KOBJMETHOD(device_suspend,      bus_generic_suspend),
2750 	KOBJMETHOD(device_resume,       bus_generic_resume),
2751 
2752 				        /* Bus interface */
2753 	KOBJMETHOD(bus_print_child,     root_print_child),
2754 
2755 	KOBJMETHOD_END
2756 };
2757 
2758 static driver_t root_driver = {
2759 	"root",
2760 	root_methods,
2761 	1,                      /* no softc */
2762 };
2763 
2764 device_t        root_bus;
2765 devclass_t      root_devclass;
2766 
2767 static int
root_bus_module_handler(module_t mod,int what,void * arg)2768 root_bus_module_handler(module_t mod, int what, void* arg)
2769 {
2770         PDEBUG(("+"));
2771         switch (what) {
2772         case MOD_LOAD:
2773                 TAILQ_INIT(&bus_data_devices);
2774                 kobj_class_compile((kobj_class_t) &root_driver);
2775                 root_bus = make_device(NULL, "root", 0);
2776                 root_bus->desc = "System root bus";
2777                 kobj_init((kobj_t) root_bus, (kobj_class_t) &root_driver);
2778                 root_bus->driver = &root_driver;
2779                 root_bus->state = DS_ATTACHED;
2780                 root_devclass = devclass_find_internal("root", NULL, FALSE);
2781                 //devinit();
2782                 return (0);
2783 
2784         case MOD_SHUTDOWN:
2785                 device_shutdown(root_bus);
2786                 return (0);
2787         default:
2788                 return (EOPNOTSUPP);
2789         }
2790         PDEBUG(("-"));
2791 
2792         return (0);
2793 }
2794 
2795 /**
2796  * @brief Automatically configure devices
2797  *
2798  * This function begins the autoconfiguration process by calling
2799  * device_probe_and_attach() for each child of the @c root0 device.
2800  */
2801 void
root_bus_configure(void)2802 root_bus_configure(void)
2803 {
2804 	PDEBUG(("+"));
2805         root_bus_module_handler(NULL, MOD_LOAD, NULL);
2806 
2807 	/* Eventually this will be split up, but this is sufficient for now. */
2808 	bus_set_pass(BUS_PASS_DEFAULT);
2809 	PDEBUG(("-"));
2810 }
2811 
2812 /**
2813  * @brief Module handler for registering device drivers
2814  *
2815  * This module handler is used to automatically register device
2816  * drivers when modules are loaded. If @p what is MOD_LOAD, it calls
2817  * devclass_add_driver() for the driver described by the
2818  * driver_module_data structure pointed to by @p arg
2819  */
2820 int
driver_module_handler(module_t mod,int what,void * arg)2821 driver_module_handler(module_t mod, int what, void *arg)
2822 {
2823         struct driver_module_data *dmd = NULL;
2824         devclass_t bus_devclass;
2825         kobj_class_t driver;
2826         int error, pass;
2827 
2828         PDEBUG(("+"));
2829 
2830         dmd = (struct driver_module_data *)arg;
2831         bus_devclass = devclass_find_internal(dmd->dmd_busname, NULL, TRUE);
2832         if (bus_devclass == NULL) {
2833                 PDEBUG(("-"));
2834                 return EINVAL;
2835         }
2836 
2837         error = 0;
2838 
2839         switch (what) {
2840         case MOD_LOAD:
2841                 if (dmd->dmd_chainevh)
2842                         error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg);
2843 
2844                 pass = dmd->dmd_pass;
2845                 driver = dmd->dmd_driver;
2846                 PDEBUG(("Loading module: driver %s on bus %s (pass %d)",
2847                     DRIVERNAME(driver), dmd->dmd_busname, pass));
2848                 error = devclass_add_driver(bus_devclass, driver, pass,
2849                     dmd->dmd_devclass);
2850                 break;
2851 
2852         case MOD_UNLOAD:
2853                 PDEBUG(("Unloading module: driver %s from bus %s",
2854                     DRIVERNAME(dmd->dmd_driver),
2855                     dmd->dmd_busname));
2856                 error = devclass_delete_driver(bus_devclass,
2857                     dmd->dmd_driver);
2858 
2859                 if (!error && dmd->dmd_chainevh)
2860                         error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg);
2861                 break;
2862         case MOD_QUIESCE:
2863                 PDEBUG(("Quiesce module: driver %s from bus %s",
2864                     DRIVERNAME(dmd->dmd_driver),
2865                     dmd->dmd_busname));
2866                 error = devclass_quiesce_driver(bus_devclass,
2867                     dmd->dmd_driver);
2868 
2869                 if (!error && dmd->dmd_chainevh)
2870                         error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg);
2871                 break;
2872         default:
2873                 error = EOPNOTSUPP;
2874                 break;
2875         }
2876         PDEBUG(("-"));
2877 
2878         return (error);
2879 }
2880 
2881 #ifdef BUS_DEBUG
2882 
2883 /* the _short versions avoid iteration by not calling anything that prints
2884  * more than oneliners. I love oneliners.
2885  */
2886 
2887 static void
print_device_short(device_t dev,int indent)2888 print_device_short(device_t dev, int indent)
2889 {
2890         if (!dev)
2891                 return;
2892 
2893         indentprintf(("device %d: <%s> %sparent,%schildren,%s%s%s%s%s,%sivars,%ssoftc,busy=%d\n",
2894             dev->unit, dev->desc,
2895             (dev->parent? "":"no "),
2896             (TAILQ_EMPTY(&dev->children)? "no ":""),
2897             (dev->flags&DF_ENABLED? "enabled,":"disabled,"),
2898             (dev->flags&DF_FIXEDCLASS? "fixed,":""),
2899             (dev->flags&DF_WILDCARD? "wildcard,":""),
2900             (dev->flags&DF_DESCMALLOCED? "descmalloced,":""),
2901             (dev->flags&DF_REBID? "rebiddable,":""),
2902             (dev->ivars? "":"no "),
2903             (dev->softc? "":"no "),
2904             dev->busy));
2905 }
2906 
2907 static void
print_device(device_t dev,int indent)2908 print_device(device_t dev, int indent)
2909 {
2910         if (!dev)
2911                 return;
2912 
2913         print_device_short(dev, indent);
2914 
2915         indentprintf(("Parent:\n"));
2916         print_device_short(dev->parent, indent+1);
2917         indentprintf(("Driver:\n"));
2918         print_driver_short(dev->driver, indent+1);
2919         indentprintf(("Devclass:\n"));
2920         print_devclass_short(dev->devclass, indent+1);
2921 }
2922 
2923 void
print_device_tree_short(device_t dev,int indent)2924 print_device_tree_short(device_t dev, int indent)
2925 /* print the device and all its children (indented) */
2926 {
2927         device_t child;
2928 
2929         if (!dev)
2930                 return;
2931 
2932         print_device_short(dev, indent);
2933 
2934         TAILQ_FOREACH(child, &dev->children, link) {
2935                 print_device_tree_short(child, indent+1);
2936         }
2937 }
2938 
2939 void
print_device_tree(device_t dev,int indent)2940 print_device_tree(device_t dev, int indent)
2941 /* print the device and all its children (indented) */
2942 {
2943         device_t child;
2944 
2945         if (!dev)
2946                 return;
2947 
2948         print_device(dev, indent);
2949 
2950         TAILQ_FOREACH(child, &dev->children, link) {
2951                 print_device_tree(child, indent+1);
2952         }
2953 }
2954 
2955 static void
print_driver_short(driver_t * driver,int indent)2956 print_driver_short(driver_t *driver, int indent)
2957 {
2958         if (!driver)
2959                 return;
2960 
2961         indentprintf(("driver %s: softc size = %zd\n",
2962             driver->name, driver->size));
2963 }
2964 
2965 static void
print_driver(driver_t * driver,int indent)2966 print_driver(driver_t *driver, int indent)
2967 {
2968         if (!driver)
2969                 return;
2970 
2971         print_driver_short(driver, indent);
2972 }
2973 
2974 static void
print_driver_list(driver_list_t drivers,int indent)2975 print_driver_list(driver_list_t drivers, int indent)
2976 {
2977         driverlink_t driver = NULL;
2978 
2979         TAILQ_FOREACH(driver, &drivers, link) {
2980                 print_driver(driver->driver, indent);
2981         }
2982 }
2983 
2984 static void
print_devclass_short(devclass_t dc,int indent)2985 print_devclass_short(devclass_t dc, int indent)
2986 {
2987         if ( !dc )
2988                 return;
2989 
2990         indentprintf(("devclass %s: max units = %d\n", dc->name, dc->maxunit));
2991 }
2992 
2993 static void
print_devclass(devclass_t dc,int indent)2994 print_devclass(devclass_t dc, int indent)
2995 {
2996         int i;
2997 
2998         if ( !dc )
2999                 return;
3000 
3001         print_devclass_short(dc, indent);
3002         indentprintf(("Drivers:\n"));
3003         print_driver_list(dc->drivers, indent+1);
3004 
3005         indentprintf(("Devices:\n"));
3006         for (i = 0; i < dc->maxunit; i++)
3007                 if (dc->devices[i])
3008                         print_device(dc->devices[i], indent+1);
3009 }
3010 
3011 void
print_devclass_list_short(void)3012 print_devclass_list_short(void)
3013 {
3014         devclass_t dc;
3015 
3016         printf("Short listing of devclasses, drivers & devices:\n");
3017         TAILQ_FOREACH(dc, &devclasses, link) {
3018                 print_devclass_short(dc, 0);
3019         }
3020 }
3021 
3022 void
print_devclass_list(void)3023 print_devclass_list(void)
3024 {
3025         devclass_t dc;
3026 
3027         printf("Full listing of devclasses, drivers & devices:\n");
3028         TAILQ_FOREACH(dc, &devclasses, link) {
3029                 print_devclass(dc, 0);
3030         }
3031 }
3032 
3033 #endif
3034 
3035 /* port for interrupt setup and teardown */
3036 int
bus_setup_intr(int irq,int flags,driver_intr_t * intr,void * arg)3037 bus_setup_intr(int irq, int flags, driver_intr_t *intr, void *arg)
3038 {
3039         int ret;
3040         HwiIrqParam irqParam = {0};
3041 
3042         if (OS_INT_ACTIVE) {
3043                 return OS_ERRNO_HWI_INTERR;
3044         }
3045 
3046         irqParam.swIrq  = irq;
3047         irqParam.pDevId = arg;
3048 
3049         ret = LOS_HwiCreate(irq, 0, (HWI_MODE_T)flags, (HWI_PROC_FUNC)intr, &irqParam);
3050         if (ret == LOS_OK) {
3051                 HalIrqUnmask(irq);
3052         }
3053         return ret;
3054 }
3055 int
bus_teardown_intr(int irq,void * arg)3056 bus_teardown_intr(int irq, void *arg)
3057 {
3058     HwiIrqParam irqParam = {0};
3059 
3060     if (OS_INT_ACTIVE) {
3061         return -1;
3062     }
3063 
3064     irqParam.swIrq  = irq;
3065     irqParam.pDevId = arg;
3066 
3067     return LOS_HwiDelete(irq, &irqParam);
3068 }
3069