svn commit: r193833 - in head: share/man/man9 sys/kern sys/sys

John Baldwin jhb at FreeBSD.org
Tue Jun 9 14:26:24 UTC 2009


Author: jhb
Date: Tue Jun  9 14:26:23 2009
New Revision: 193833
URL: http://svn.freebsd.org/changeset/base/193833

Log:
  Add support for multiple passes of the device tree during the boot-time
  probe.  The current device order is unchanged.  This commit just adds the
  infrastructure and ABI changes so that it is easier to merge later changes
  into 8.x.
  - Driver attachments now have an associated pass level.  Attachments are
    not allowed to probe or attach to drivers until the system-wide pass level
    is >= the attachment's pass level.  By default driver attachments use the
    "last" pass level (BUS_PASS_DEFAULT).  Driver's that wish to probe during
    an earlier pass use EARLY_DRIVER_MODULE() instead of DRIVER_MODULE() which
    accepts the pass level as an additional parameter.
  - A new method BUS_NEW_PASS has been added to the bus interface.  This
    method is invoked when the system-wide pass level is changed to kick off
    a rescan of the device tree so that drivers that have just been made
    "eligible" can probe and attach.
  - The bus_generic_new_pass() function provides a default implementation of
    BUS_NEW_PASS().  It first allows drivers that were just made eligible for
    this pass to identify new child devices.  Then it propogates the rescan to
    child devices that already have an attached driver by invoking their
    BUS_NEW_PASS() method.  It also reprobes devices without a driver.
  - BUS_PROBE_NOMATCH() is only invoked for devices that do not have
    an attached driver after being scanned during the final pass.
  - The bus_set_pass() function is used during boot to raise the pass level.
    Currently it is only called once during root_bus_configure() to raise
    the pass level to BUS_PASS_DEFAULT.  This has the effect of probing all
    devices in a single pass identical to previous behavior.
  
  Reviewed by:	imp
  Approved by:	re (kib)

Added:
  head/share/man/man9/BUS_NEW_PASS.9   (contents, props changed)
  head/share/man/man9/bus_generic_new_pass.9   (contents, props changed)
  head/share/man/man9/bus_set_pass.9   (contents, props changed)
Modified:
  head/share/man/man9/Makefile
  head/sys/kern/bus_if.m
  head/sys/kern/subr_bus.c
  head/sys/sys/bus.h

Added: head/share/man/man9/BUS_NEW_PASS.9
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/share/man/man9/BUS_NEW_PASS.9	Tue Jun  9 14:26:23 2009	(r193833)
@@ -0,0 +1,56 @@
+.\" -*- nroff -*-
+.\"
+.\" Copyright (c) 2009 Advanced Computing Technologies LLC
+.\" Written by: John H. Baldwin <jhb at FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 8, 2009
+.Dt BUS_NEW_PASS 9
+.Os
+.Sh NAME
+.Nm BUS_NEW_PASS
+.Nd "notify a bus that the pass level has been changed"
+.Sh SYNOPSIS
+.In sys/param.h
+.In sys/bus.h
+.Ft void
+.Fn BUS_NEW_PASS "device_t dev"
+.Sh DESCRIPTION
+The
+.Fn BUS_NEW_PASS
+method is called on each bus device to rescan the device tree when the pass
+level has been changed.
+This method is responsible for invoking
+.Xr BUS_NEW_PASS 9
+on child bus devices to propogate the rescan to child devices.
+It is also responsible for reprobing any unattached child devices and
+allowing drivers for the current pass to identify new children.
+A default implementation is provided by
+.Xr bus_generic_new_pass 9 .
+.Sh SEE ALSO
+.Xr bus_generic_new_pass 9 ,
+.Xr bus_set_pass 9 ,
+.Xr device 9

Modified: head/share/man/man9/Makefile
==============================================================================
--- head/share/man/man9/Makefile	Tue Jun  9 14:18:16 2009	(r193832)
+++ head/share/man/man9/Makefile	Tue Jun  9 14:26:23 2009	(r193833)
@@ -28,12 +28,15 @@ MAN=	accept_filter.9 \
 	bus_dma.9 \
 	bus_generic_attach.9 \
 	bus_generic_detach.9 \
+	bus_generic_new_pass.9 \
 	bus_generic_print_child.9 \
 	bus_generic_read_ivar.9 \
 	bus_generic_shutdown.9 \
+	BUS_NEW_PASS.9 \
 	BUS_PRINT_CHILD.9 \
 	BUS_READ_IVAR.9 \
 	bus_release_resource.9 \
+	bus_set_pass.9 \
 	bus_set_resource.9 \
 	BUS_SETUP_INTR.9 \
 	bus_space.9 \

Added: head/share/man/man9/bus_generic_new_pass.9
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/share/man/man9/bus_generic_new_pass.9	Tue Jun  9 14:26:23 2009	(r193833)
@@ -0,0 +1,57 @@
+.\" -*- nroff -*-
+.\"
+.\" Copyright (c) 2009 Advanced Computing Technologies LLC
+.\" Written by: John H. Baldwin <jhb at FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 8, 2009
+.Dt bus_generic_new_pass 9
+.Os
+.Sh NAME
+.Nm bus_generic_new_pass
+.Nd "generic implementation of BUS_NEW_PASS for bus devices"
+.Sh SYNOPSIS
+.In sys/param.h
+.In sys/bus.h
+.Ft void
+.Fn bus_generic_new_pass "device_t dev"
+.Sh DESCRIPTION
+This function provides an implementation of the
+.Xr BUS_NEW_PASS 9
+method which can be used by bus drivers.
+It first invokes the
+.Xr DEVICE_IDENTIFY 9
+method for any drivers whose pass level is equal to the new pass level.
+Then, for each attached child device it calls
+.Xr BUS_NEW_PASS 9
+to rescan child busses,
+and for each unattached child device it calls
+.Xr device_probe_and_attach 9 .
+.Sh SEE ALSO
+.Xr BUS_NEW_PASS 9 ,
+.Xr bus_set_pass 9 ,
+.Xr device 9 ,
+.Xr DEVICE_IDENTIFY 9

Added: head/share/man/man9/bus_set_pass.9
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/share/man/man9/bus_set_pass.9	Tue Jun  9 14:26:23 2009	(r193833)
@@ -0,0 +1,54 @@
+.\" -*- nroff -*-
+.\"
+.\" Copyright (c) 2009 Advanced Computing Technologies LLC
+.\" Written by: John H. Baldwin <jhb at FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 8, 2009
+.Dt bus_set_pass 9
+.Os
+.Sh NAME
+.Nm bus_set_pass
+.Nd "raise the bus pass level"
+.Sh SYNOPSIS
+.In sys/param.h
+.In sys/bus.h
+.Ft void
+.Fn bus_set_pass "int pass"
+.Sh DESCRIPTION
+The
+.Nm
+function is called during boot to raise the bus pass level to
+.Fa pass .
+The function will rescan the device tree for each pass level between the
+current pass level and the new level that has at least one associated
+driver.
+The device tree rescans are implemented by invoking the
+.Xr BUS_NEW_PASS 9
+method on the root bus device.
+.Sh SEE ALSO
+.Xr BUS_NEW_PASS 9 ,
+.Xr device 9

Modified: head/sys/kern/bus_if.m
==============================================================================
--- head/sys/kern/bus_if.m	Tue Jun  9 14:18:16 2009	(r193832)
+++ head/sys/kern/bus_if.m	Tue Jun  9 14:26:23 2009	(r193833)
@@ -574,3 +574,11 @@ METHOD void hint_device_unit {
 	int		*_unitp;
 };
 
+/**
+ * @brief Notify a bus that the bus pass level has been changed
+ *
+ * @param _dev		the bus device
+ */
+METHOD void new_pass {
+	device_t	_dev;
+} DEFAULT bus_generic_new_pass;

Modified: head/sys/kern/subr_bus.c
==============================================================================
--- head/sys/kern/subr_bus.c	Tue Jun  9 14:18:16 2009	(r193832)
+++ head/sys/kern/subr_bus.c	Tue Jun  9 14:26:23 2009	(r193833)
@@ -66,6 +66,8 @@ typedef struct driverlink *driverlink_t;
 struct driverlink {
 	kobj_class_t	driver;
 	TAILQ_ENTRY(driverlink) link;	/* list of drivers in devclass */
+	int		pass;
+	TAILQ_ENTRY(driverlink) passlink;
 };
 
 /*
@@ -759,12 +761,98 @@ static kobj_method_t null_methods[] = {
 DEFINE_CLASS(null, null_methods, 0);
 
 /*
+ * Bus pass implementation
+ */
+
+static driver_list_t passes = TAILQ_HEAD_INITIALIZER(passes);
+int bus_current_pass = BUS_PASS_ROOT;
+
+/**
+ * @internal
+ * @brief Register the pass level of a new driver attachment
+ *
+ * Register a new driver attachment's pass level.  If no driver
+ * attachment with the same pass level has been added, then @p new
+ * will be added to the global passes list.
+ *
+ * @param new		the new driver attachment
+ */
+static void
+driver_register_pass(struct driverlink *new)
+{
+	struct driverlink *dl;
+
+	/* We only consider pass numbers during boot. */
+	if (bus_current_pass == BUS_PASS_DEFAULT)
+		return;
+
+	/*
+	 * Walk the passes list.  If we already know about this pass
+	 * then there is nothing to do.  If we don't, then insert this
+	 * driver link into the list.
+	 */
+	TAILQ_FOREACH(dl, &passes, passlink) {
+		if (dl->pass < new->pass)
+			continue;
+		if (dl->pass == new->pass)
+			return;
+		TAILQ_INSERT_BEFORE(dl, new, passlink);
+		return;
+	}
+	TAILQ_INSERT_TAIL(&passes, new, passlink);
+}
+
+/**
+ * @brief Raise the current bus pass
+ *
+ * Raise the current bus pass level to @p pass.  Call the BUS_NEW_PASS()
+ * method on the root bus to kick off a new device tree scan for each
+ * new pass level that has at least one driver.
+ */
+void
+bus_set_pass(int pass)
+{
+	struct driverlink *dl;
+
+	if (bus_current_pass > pass)
+		panic("Attempt to lower bus pass level");
+
+	TAILQ_FOREACH(dl, &passes, passlink) {
+		/* Skip pass values below the current pass level. */
+		if (dl->pass <= bus_current_pass)
+			continue;
+
+		/*
+		 * Bail once we hit a driver with a pass level that is
+		 * too high.
+		 */
+		if (dl->pass > pass)
+			break;
+
+		/*
+		 * Raise the pass level to the next level and rescan
+		 * the tree.
+		 */
+		bus_current_pass = dl->pass;
+		BUS_NEW_PASS(root_bus);
+	}
+
+	/*
+	 * If there isn't a driver registered for the requested pass,
+	 * then bus_current_pass might still be less than 'pass'.  Set
+	 * it to 'pass' in that case.
+	 */
+	if (bus_current_pass < pass)
+		bus_current_pass = pass;
+	KASSERT(bus_current_pass == pass, ("Failed to update bus pass level"));
+}
+
+/*
  * Devclass implementation
  */
 
 static devclass_list_t devclasses = TAILQ_HEAD_INITIALIZER(devclasses);
 
-
 /**
  * @internal
  * @brief Find or create a device class
@@ -912,12 +1000,16 @@ devclass_driver_added(devclass_t dc, dri
  * @param driver	the driver to register
  */
 int
-devclass_add_driver(devclass_t dc, driver_t *driver)
+devclass_add_driver(devclass_t dc, driver_t *driver, int pass)
 {
 	driverlink_t dl;
 
 	PDEBUG(("%s", DRIVERNAME(driver)));
 
+	/* Don't allow invalid pass values. */
+	if (pass <= BUS_PASS_ROOT)
+		return (EINVAL);
+
 	dl = malloc(sizeof *dl, M_BUS, M_NOWAIT|M_ZERO);
 	if (!dl)
 		return (ENOMEM);
@@ -938,6 +1030,8 @@ devclass_add_driver(devclass_t dc, drive
 	dl->driver = driver;
 	TAILQ_INSERT_TAIL(&dc->drivers, dl, link);
 	driver->refs++;		/* XXX: kobj_mtx */
+	dl->pass = pass;
+	driver_register_pass(dl);
 
 	devclass_driver_added(dc, driver);
 	bus_data_generation_update();
@@ -1801,6 +1895,11 @@ device_probe_child(device_t dev, device_
 		for (dl = first_matching_driver(dc, child);
 		     dl;
 		     dl = next_matching_driver(dc, child, dl)) {
+
+			/* If this driver's pass is too high, then ignore it. */
+			if (dl->pass > bus_current_pass)
+				continue;
+
 			PDEBUG(("Trying %s", DRIVERNAME(dl->driver)));
 			device_set_driver(child, dl->driver);
 			if (!hasclass) {
@@ -2442,8 +2541,9 @@ device_probe(device_t dev)
 		}
 		return (-1);
 	}
-	if ((error = device_probe_child(dev->parent, dev)) != 0) {
-		if (!(dev->flags & DF_DONENOMATCH)) {
+	if ((error = device_probe_child(dev->parent, dev)) != 0) {		
+		if (bus_current_pass == BUS_PASS_DEFAULT &&
+		    !(dev->flags & DF_DONENOMATCH)) {
 			BUS_PROBE_NOMATCH(dev->parent, dev);
 			devnomatch(dev);
 			dev->flags |= DF_DONENOMATCH;
@@ -2988,6 +3088,17 @@ bus_generic_probe(device_t dev)
 	driverlink_t dl;
 
 	TAILQ_FOREACH(dl, &dc->drivers, link) {
+		/*
+		 * If this driver's pass is too high, then ignore it.
+		 * For most drivers in the default pass, this will
+		 * never be true.  For early-pass drivers they will
+		 * only call the identify routines of eligible drivers
+		 * when this routine is called.  Drivers for later
+		 * passes should have their identify routines called
+		 * on early-pass busses during BUS_NEW_PASS().
+		 */
+		if (dl->pass > bus_current_pass)
+				continue;
 		DEVICE_IDENTIFY(dl->driver, dev);
 	}
 
@@ -3215,6 +3326,36 @@ bus_generic_driver_added(device_t dev, d
 }
 
 /**
+ * @brief Helper function for implementing BUS_NEW_PASS().
+ *
+ * This implementing of BUS_NEW_PASS() first calls the identify
+ * routines for any drivers that probe at the current pass.  Then it
+ * walks the list of devices for this bus.  If a device is already
+ * attached, then it calls BUS_NEW_PASS() on that device.  If the
+ * device is not already attached, it attempts to attach a driver to
+ * it.
+ */
+void
+bus_generic_new_pass(device_t dev)
+{
+	driverlink_t dl;
+	devclass_t dc;
+	device_t child;
+
+	dc = dev->devclass;
+	TAILQ_FOREACH(dl, &dc->drivers, link) {
+		if (dl->pass == bus_current_pass)
+			DEVICE_IDENTIFY(dl->driver, dev);
+	}
+	TAILQ_FOREACH(child, &dev->children, link) {
+		if (child->state >= DS_ATTACHED)
+			BUS_NEW_PASS(child);
+		else if (child->state == DS_NOTPRESENT)
+			device_probe_and_attach(child);
+	}
+}
+
+/**
  * @brief Helper function for implementing BUS_SETUP_INTR().
  *
  * This simple implementation of BUS_SETUP_INTR() simply calls the
@@ -3912,13 +4053,11 @@ DECLARE_MODULE(rootbus, root_bus_mod, SI
 void
 root_bus_configure(void)
 {
-	device_t dev;
 
 	PDEBUG(("."));
 
-	TAILQ_FOREACH(dev, &root_bus->children, link) {
-		device_probe_and_attach(dev);
-	}
+	/* Eventually this will be split up, but this is sufficient for now. */
+	bus_set_pass(BUS_PASS_DEFAULT);
 }
 
 /**
@@ -3932,10 +4071,10 @@ root_bus_configure(void)
 int
 driver_module_handler(module_t mod, int what, void *arg)
 {
-	int error;
 	struct driver_module_data *dmd;
 	devclass_t bus_devclass;
 	kobj_class_t driver;
+	int error, pass;
 
 	dmd = (struct driver_module_data *)arg;
 	bus_devclass = devclass_find_internal(dmd->dmd_busname, NULL, TRUE);
@@ -3946,10 +4085,11 @@ driver_module_handler(module_t mod, int 
 		if (dmd->dmd_chainevh)
 			error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg);
 
+		pass = dmd->dmd_pass;
 		driver = dmd->dmd_driver;
-		PDEBUG(("Loading module: driver %s on bus %s",
-		    DRIVERNAME(driver), dmd->dmd_busname));
-		error = devclass_add_driver(bus_devclass, driver);
+		PDEBUG(("Loading module: driver %s on bus %s (pass %d)",
+		    DRIVERNAME(driver), dmd->dmd_busname, pass));
+		error = devclass_add_driver(bus_devclass, driver, pass);
 		if (error)
 			break;
 

Modified: head/sys/sys/bus.h
==============================================================================
--- head/sys/sys/bus.h	Tue Jun  9 14:18:16 2009	(r193832)
+++ head/sys/sys/bus.h	Tue Jun  9 14:26:23 2009	(r193833)
@@ -29,6 +29,7 @@
 #ifndef _SYS_BUS_H_
 #define _SYS_BUS_H_
 
+#include <machine/_limits.h>
 #include <sys/_bus_dma.h>
 
 /**
@@ -299,6 +300,7 @@ bus_dma_tag_t
 	bus_generic_get_dma_tag(device_t dev, device_t child);
 struct resource_list *
 	bus_generic_get_resource_list (device_t, device_t);
+void	bus_generic_new_pass(device_t dev);
 int	bus_print_child_header(device_t dev, device_t child);
 int	bus_print_child_footer(device_t dev, device_t child);
 int	bus_generic_print_child(device_t dev, device_t child);
@@ -433,7 +435,7 @@ void	device_verbose(device_t dev);
 /*
  * Access functions for devclass.
  */
-int	devclass_add_driver(devclass_t dc, kobj_class_t driver);
+int	devclass_add_driver(devclass_t dc, kobj_class_t driver, int pass);
 int	devclass_delete_driver(devclass_t dc, kobj_class_t driver);
 devclass_t	devclass_create(const char *classname);
 devclass_t	devclass_find(const char *classname);
@@ -512,6 +514,28 @@ void	bus_data_generation_update(void);
 #define BUS_PROBE_NOWILDCARD	(-2000000000) /* No wildcard device matches */
 
 /**
+ * During boot, the device tree is scanned multiple times.  Each scan,
+ * or pass, drivers may be attached to devices.  Each driver
+ * attachment is assigned a pass number.  Drivers may only probe and
+ * attach to devices if their pass number is less than or equal to the
+ * current system-wide pass number.  The default pass is the last pass
+ * and is used by most drivers.  Drivers needed by the scheduler are
+ * probed in earlier passes.
+ */
+#define	BUS_PASS_ROOT		0	/* Used to attach root0. */
+#define	BUS_PASS_BUS		10	/* Busses and bridges. */
+#define	BUS_PASS_CPU		20	/* CPU devices. */
+#define	BUS_PASS_RESOURCE	30	/* Resource discovery. */
+#define	BUS_PASS_INTERRUPT	40	/* Interrupt controllers. */
+#define	BUS_PASS_TIMER		50	/* Timers and clocks. */
+#define	BUS_PASS_SCHEDULER	60	/* Start scheduler. */
+#define	BUS_PASS_DEFAULT	__INT_MAX /* Everything else. */
+
+extern int bus_current_pass;
+
+void	bus_set_pass(int pass);
+
+/**
  * Shorthand for constructing method tables.
  */
 #define	DEVMETHOD	KOBJMETHOD
@@ -535,15 +559,17 @@ struct driver_module_data {
 	const char	*dmd_busname;
 	kobj_class_t	dmd_driver;
 	devclass_t	*dmd_devclass;
+	int		dmd_pass;
 };
 
-#define	DRIVER_MODULE(name, busname, driver, devclass, evh, arg)	\
+#define	EARLY_DRIVER_MODULE(name, busname, driver, devclass, evh, arg, pass) \
 									\
 static struct driver_module_data name##_##busname##_driver_mod = {	\
 	evh, arg,							\
 	#busname,							\
 	(kobj_class_t) &driver,						\
-	&devclass							\
+	&devclass,							\
+	pass								\
 };									\
 									\
 static moduledata_t name##_##busname##_mod = {				\
@@ -554,6 +580,10 @@ static moduledata_t name##_##busname##_m
 DECLARE_MODULE(name##_##busname, name##_##busname##_mod,		\
 	       SI_SUB_DRIVERS, SI_ORDER_MIDDLE)
 
+#define	DRIVER_MODULE(name, busname, driver, devclass, evh, arg)	\
+	EARLY_DRIVER_MODULE(name, busname, driver, devclass, evh, arg,	\
+	    BUS_PASS_DEFAULT)
+
 /**
  * Generic ivar accessor generation macros for bus drivers
  */


More information about the svn-src-head mailing list