subr_bus.c revision 138402
1148330Snetchild/*-
2148330Snetchild * Copyright (c) 1997,1998,2003 Doug Rabson
3148330Snetchild * All rights reserved.
4148330Snetchild *
5148330Snetchild * Redistribution and use in source and binary forms, with or without
6148330Snetchild * modification, are permitted provided that the following conditions
7148330Snetchild * are met:
8148330Snetchild * 1. Redistributions of source code must retain the above copyright
9148330Snetchild *    notice, this list of conditions and the following disclaimer.
10148330Snetchild * 2. Redistributions in binary form must reproduce the above copyright
11148330Snetchild *    notice, this list of conditions and the following disclaimer in the
12148330Snetchild *    documentation and/or other materials provided with the distribution.
13148330Snetchild *
14148543Snetchild * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15148543Snetchild * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16148330Snetchild * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17195754Smarcus * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18195754Smarcus * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19195699Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20195699Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21195699Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22195699Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23195656Strasz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24195656Strasz * SUCH DAMAGE.
25195656Strasz */
26195656Strasz
27195656Strasz#include <sys/cdefs.h>
28195230Sdfr__FBSDID("$FreeBSD: head/sys/kern/subr_bus.c 138402 2004-12-05 20:58:56Z obrien $");
29195230Sdfr
30194860Sthompsa#include "opt_bus.h"
31195096Santoine
32195096Santoine#define __RMAN_RESOURCE_VISIBLE
33195096Santoine#include <sys/param.h>
34195096Santoine#include <sys/conf.h>
35195096Santoine#include <sys/filio.h>
36195096Santoine#include <sys/lock.h>
37195096Santoine#include <sys/kernel.h>
38195096Santoine#include <sys/kobj.h>
39195096Santoine#include <sys/malloc.h>
40195096Santoine#include <sys/module.h>
41195096Santoine#include <sys/mutex.h>
42195096Santoine#include <sys/poll.h>
43195096Santoine#include <sys/proc.h>
44195096Santoine#include <sys/condvar.h>
45195096Santoine#include <sys/queue.h>
46195096Santoine#include <machine/bus.h>
47195096Santoine#include <sys/rman.h>
48195096Santoine#include <sys/selinfo.h>
49195096Santoine#include <sys/signalvar.h>
50195096Santoine#include <sys/sysctl.h>
51195096Santoine#include <sys/systm.h>
52195096Santoine#include <sys/uio.h>
53195096Santoine#include <sys/bus.h>
54195096Santoine
55195096Santoine#include <machine/stdarg.h>
56195096Santoine
57195096Santoine#include <vm/uma.h>
58195096Santoine
59195096SantoineSYSCTL_NODE(_hw, OID_AUTO, bus, CTLFLAG_RW, NULL, NULL);
60195096SantoineSYSCTL_NODE(, OID_AUTO, dev, CTLFLAG_RW, NULL, NULL);
61195096Santoine
62195096Santoine/*
63195096Santoine * Used to attach drivers to devclasses.
64195096Santoine */
65195096Santoinetypedef struct driverlink *driverlink_t;
66195096Santoinestruct driverlink {
67195096Santoine	kobj_class_t	driver;
68195096Santoine	TAILQ_ENTRY(driverlink) link;	/* list of drivers in devclass */
69195096Santoine};
70195096Santoine
71195096Santoine/*
72195096Santoine * Forward declarations
73195096Santoine */
74195096Santoinetypedef TAILQ_HEAD(devclass_list, devclass) devclass_list_t;
75195096Santoinetypedef TAILQ_HEAD(driver_list, driverlink) driver_list_t;
76195096Santoinetypedef TAILQ_HEAD(device_list, device) device_list_t;
77195096Santoine
78195096Santoinestruct devclass {
79195096Santoine	TAILQ_ENTRY(devclass) link;
80195096Santoine	devclass_t	parent;		/* parent in devclass hierarchy */
81195096Santoine	driver_list_t	drivers;     /* bus devclasses store drivers for bus */
82195096Santoine	char		*name;
83195096Santoine	device_t	*devices;	/* array of devices indexed by unit */
84195096Santoine	int		maxunit;	/* size of devices array */
85195096Santoine
86195096Santoine	struct sysctl_ctx_list sysctl_ctx;
87195096Santoine	struct sysctl_oid *sysctl_tree;
88195096Santoine};
89195096Santoine
90193513Sed/**
91193513Sed * @brief Implementation of device.
92193308Sed */
93193308Sedstruct device {
94193308Sed	/*
95195096Santoine	 * A device is a kernel object. The first field must be the
96195096Santoine	 * current ops table for the object.
97193113Sdougb	 */
98193113Sdougb	KOBJ_FIELDS;
99192926Sed
100192926Sed	/*
101192926Sed	 * Device hierarchy.
102192901Sthompsa	 */
103192901Sthompsa	TAILQ_ENTRY(device)	link;	/**< list of devices in parent */
104192901Sthompsa	TAILQ_ENTRY(device)	devlink; /**< global device list membership */
105192901Sthompsa	device_t	parent;		/**< parent of this device  */
106192901Sthompsa	device_list_t	children;	/**< list of child devices */
107192901Sthompsa
108192901Sthompsa	/*
109192901Sthompsa	 * Details of this device.
110192901Sthompsa	 */
111192901Sthompsa	driver_t	*driver;	/**< current driver */
112192901Sthompsa	devclass_t	devclass;	/**< current device class */
113192901Sthompsa	int		unit;		/**< current unit number */
114192901Sthompsa	char*		nameunit;	/**< name+unit e.g. foodev0 */
115192901Sthompsa	char*		desc;		/**< driver specific description */
116192901Sthompsa	int		busy;		/**< count of calls to device_busy() */
117192901Sthompsa	device_state_t	state;		/**< current device state  */
118192901Sthompsa	u_int32_t	devflags;	/**< api level flags for device_get_flags() */
119192901Sthompsa	u_short		flags;		/**< internal device flags  */
120192901Sthompsa#define	DF_ENABLED	1		/* device should be probed/attached */
121192901Sthompsa#define	DF_FIXEDCLASS	2		/* devclass specified at create time */
122192901Sthompsa#define	DF_WILDCARD	4		/* unit was originally wildcard */
123192901Sthompsa#define	DF_DESCMALLOCED	8		/* description was malloced */
124192901Sthompsa#define	DF_QUIET	16		/* don't print verbose attach message */
125192901Sthompsa#define	DF_DONENOMATCH	32		/* don't execute DEVICE_NOMATCH again */
126192901Sthompsa#define	DF_EXTERNALSOFTC 64		/* softc not allocated by us */
127192901Sthompsa#define DF_REBID	128	/* Can rebid after attach */
128192901Sthompsa	u_char	order;			/**< order from device_add_child_ordered() */
129192901Sthompsa	u_char	pad;
130192901Sthompsa	void	*ivars;			/**< instance variables  */
131192901Sthompsa	void	*softc;			/**< current driver's variables  */
132192901Sthompsa
133192901Sthompsa	struct sysctl_ctx_list sysctl_ctx; /**< state for sysctl variables  */
134192901Sthompsa	struct sysctl_oid *sysctl_tree;	/**< state for sysctl variables */
135192916Sdougb};
136195096Santoine
137192916Sdougbstatic MALLOC_DEFINE(M_BUS, "bus", "Bus data structures");
138192580Srwatsonstatic MALLOC_DEFINE(M_BUS_SC, "bus-sc", "Bus data structures, softc");
139192580Srwatson
140192580Srwatson#ifdef BUS_DEBUG
141192580Srwatson
142192650Santoinestatic int bus_debug = 1;
143192580SrwatsonTUNABLE_INT("bus.debug", &bus_debug);
144192650SantoineSYSCTL_INT(_debug, OID_AUTO, bus_debug, CTLFLAG_RW, &bus_debug, 0,
145192650Santoine    "Debug bus code");
146192650Santoine
147191250Santoine#define PDEBUG(a)	if (bus_debug) {printf("%s:%d: ", __func__, __LINE__), printf a; printf("\n");}
148191250Santoine#define DEVICENAME(d)	((d)? device_get_name(d): "no device")
149191250Santoine#define DRIVERNAME(d)	((d)? d->name : "no driver")
150191250Santoine#define DEVCLANAME(d)	((d)? d->name : "no devclass")
151191250Santoine
152191250Santoine/**
153191250Santoine * Produce the indenting, indent*2 spaces plus a '.' ahead of that to
154191250Santoine * prevent syslog from deleting initial spaces
155191250Santoine */
156191250Santoine#define indentprintf(p)	do { int iJ; printf("."); for (iJ=0; iJ<indent; iJ++) printf("  "); printf p ; } while (0)
157191250Santoine
158191250Santoinestatic void print_device_short(device_t dev, int indent);
159191250Santoinestatic void print_device(device_t dev, int indent);
160191250Santoinevoid print_device_tree_short(device_t dev, int indent);
161191250Santoinevoid print_device_tree(device_t dev, int indent);
162191146Smaximstatic void print_driver_short(driver_t *driver, int indent);
163191146Smaximstatic void print_driver(driver_t *driver, int indent);
164191146Smaximstatic void print_driver_list(driver_list_t drivers, int indent);
165191146Smaximstatic void print_devclass_short(devclass_t dc, int indent);
166191146Smaximstatic void print_devclass(devclass_t dc, int indent);
167191146Smaximvoid print_devclass_list_short(void);
168190894Sdangervoid print_devclass_list(void);
169190905Sdanger
170191250Santoine#else
171191250Santoine/* Make the compiler ignore the function calls */
172190751Sed#define PDEBUG(a)			/* nop */
173190864Sru#define DEVICENAME(d)			/* nop */
174190864Sru#define DRIVERNAME(d)			/* nop */
175190751Sed#define DEVCLANAME(d)			/* nop */
176190751Sed
177190751Sed#define print_device_short(d,i)		/* nop */
178190751Sed#define print_device(d,i)		/* nop */
179190751Sed#define print_device_tree_short(d,i)	/* nop */
180190751Sed#define print_device_tree(d,i)		/* nop */
181190864Sru#define print_driver_short(d,i)		/* nop */
182190751Sed#define print_driver(d,i)		/* nop */
183190751Sed#define print_driver_list(d,i)		/* nop */
184190751Sed#define print_devclass_short(d,i)	/* nop */
185190751Sed#define print_devclass(d,i)		/* nop */
186190751Sed#define print_devclass_list_short()	/* nop */
187190751Sed#define print_devclass_list()		/* nop */
188190751Sed#endif
189190751Sed
190190751Sed/*
191190751Sed * dev sysctl tree
192190864Sru */
193190751Sed
194190864Sruenum {
195190772Sru	DEVCLASS_SYSCTL_PARENT,
196190772Sru};
197190772Sru
198190772Srustatic int
199190772Srudevclass_sysctl_handler(SYSCTL_HANDLER_ARGS)
200190100Sthompsa{
201190100Sthompsa	devclass_t dc = (devclass_t)arg1;
202189977Sbrueffer	const char *value;
203189977Sbrueffer	char *buf;
204189585Sthompsa	int error;
205189585Sthompsa
206189607Sthompsa	buf = NULL;
207189607Sthompsa	switch (arg2) {
208189607Sthompsa	case DEVCLASS_SYSCTL_PARENT:
209189585Sthompsa		value = dc->parent ? dc->parent->name : "";
210191250Santoine		break;
211190772Sru	default:
212190772Sru		return (EINVAL);
213190772Sru	}
214190772Sru	error = SYSCTL_OUT(req, value, strlen(value));
215190772Sru	if (buf != NULL)
216190772Sru		free(buf, M_BUS);
217189092Sed	return (error);
218189092Sed}
219190772Sru
220190772Srustatic void
221190772Srudevclass_sysctl_init(devclass_t dc)
222188948Sthompsa{
223189000Sthompsa
224189000Sthompsa	if (dc->sysctl_tree != NULL)
225189000Sthompsa		return;
226189000Sthompsa	sysctl_ctx_init(&dc->sysctl_ctx);
227189000Sthompsa	dc->sysctl_tree = SYSCTL_ADD_NODE(&dc->sysctl_ctx,
228189000Sthompsa	    SYSCTL_STATIC_CHILDREN(_dev), OID_AUTO, dc->name,
229189000Sthompsa	    CTLFLAG_RD, 0, "");
230189000Sthompsa	SYSCTL_ADD_PROC(&dc->sysctl_ctx, SYSCTL_CHILDREN(dc->sysctl_tree),
231189000Sthompsa	    OID_AUTO, "%parent", CTLFLAG_RD,
232189000Sthompsa	    dc, DEVCLASS_SYSCTL_PARENT, devclass_sysctl_handler, "A",
233189000Sthompsa	    "parent class");
234189000Sthompsa}
235189000Sthompsa
236189000Sthompsaenum {
237188948Sthompsa	DEVICE_SYSCTL_DESC,
238188948Sthompsa	DEVICE_SYSCTL_DRIVER,
239188948Sthompsa	DEVICE_SYSCTL_LOCATION,
240188948Sthompsa	DEVICE_SYSCTL_PNPINFO,
241188948Sthompsa	DEVICE_SYSCTL_PARENT,
242188948Sthompsa};
243188948Sthompsa
244188948Sthompsastatic int
245188948Sthompsadevice_sysctl_handler(SYSCTL_HANDLER_ARGS)
246188948Sthompsa{
247188948Sthompsa	device_t dev = (device_t)arg1;
248188948Sthompsa	const char *value;
249188948Sthompsa	char *buf;
250188948Sthompsa	int error;
251188948Sthompsa
252188948Sthompsa	buf = NULL;
253188948Sthompsa	switch (arg2) {
254191250Santoine	case DEVICE_SYSCTL_DESC:
255191250Santoine		value = dev->desc ? dev->desc : "";
256188948Sthompsa		break;
257188948Sthompsa	case DEVICE_SYSCTL_DRIVER:
258188948Sthompsa		value = dev->driver ? dev->driver->name : "";
259188948Sthompsa		break;
260188948Sthompsa	case DEVICE_SYSCTL_LOCATION:
261188948Sthompsa		value = buf = malloc(1024, M_BUS, M_WAITOK | M_ZERO);
262188948Sthompsa		bus_child_location_str(dev, buf, 1024);
263188948Sthompsa		break;
264188948Sthompsa	case DEVICE_SYSCTL_PNPINFO:
265188948Sthompsa		value = buf = malloc(1024, M_BUS, M_WAITOK | M_ZERO);
266188948Sthompsa		bus_child_pnpinfo_str(dev, buf, 1024);
267188948Sthompsa		break;
268188948Sthompsa	case DEVICE_SYSCTL_PARENT:
269188948Sthompsa		value = dev->parent ? dev->parent->nameunit : "";
270188948Sthompsa		break;
271188948Sthompsa	default:
272188948Sthompsa		return (EINVAL);
273188948Sthompsa	}
274188948Sthompsa	error = SYSCTL_OUT(req, value, strlen(value));
275188948Sthompsa	if (buf != NULL)
276188948Sthompsa		free(buf, M_BUS);
277188948Sthompsa	return (error);
278188948Sthompsa}
279188948Sthompsa
280188948Sthompsastatic void
281188652Seddevice_sysctl_init(device_t dev)
282188652Sed{
283188652Sed	devclass_t dc = dev->devclass;
284188652Sed
285188102Sgabor	if (dev->sysctl_tree != NULL)
286188102Sgabor		return;
287187694Santoine	devclass_sysctl_init(dc);
288187694Santoine	sysctl_ctx_init(&dev->sysctl_ctx);
289187694Santoine	dev->sysctl_tree = SYSCTL_ADD_NODE(&dev->sysctl_ctx,
290187694Santoine	    SYSCTL_CHILDREN(dc->sysctl_tree), OID_AUTO,
291187694Santoine	    dev->nameunit + strlen(dc->name),
292186716Santoine	    CTLFLAG_RD, 0, "");
293186716Santoine	SYSCTL_ADD_PROC(&dev->sysctl_ctx, SYSCTL_CHILDREN(dev->sysctl_tree),
294186437Sbz	    OID_AUTO, "%desc", CTLFLAG_RD,
295186437Sbz	    dev, DEVICE_SYSCTL_DESC, device_sysctl_handler, "A",
296185472Santoine	    "device description");
297185472Santoine	SYSCTL_ADD_PROC(&dev->sysctl_ctx, SYSCTL_CHILDREN(dev->sysctl_tree),
298185472Santoine	    OID_AUTO, "%driver", CTLFLAG_RD,
299185472Santoine	    dev, DEVICE_SYSCTL_DRIVER, device_sysctl_handler, "A",
300185472Santoine	    "device driver name");
301183442Sed	SYSCTL_ADD_PROC(&dev->sysctl_ctx, SYSCTL_CHILDREN(dev->sysctl_tree),
302183442Sed	    OID_AUTO, "%location", CTLFLAG_RD,
303183442Sed	    dev, DEVICE_SYSCTL_LOCATION, device_sysctl_handler, "A",
304183442Sed	    "device location relative to parent");
305183442Sed	SYSCTL_ADD_PROC(&dev->sysctl_ctx, SYSCTL_CHILDREN(dev->sysctl_tree),
306183442Sed	    OID_AUTO, "%pnpinfo", CTLFLAG_RD,
307183113Sattilio	    dev, DEVICE_SYSCTL_PNPINFO, device_sysctl_handler, "A",
308183235Santoine	    "device identification");
309183235Santoine	SYSCTL_ADD_PROC(&dev->sysctl_ctx, SYSCTL_CHILDREN(dev->sysctl_tree),
310183026Santoine	    OID_AUTO, "%parent", CTLFLAG_RD,
311183026Santoine	    dev, DEVICE_SYSCTL_PARENT, device_sysctl_handler, "A",
312182105Sed	    "parent device");
313182105Sed}
314182518Santoine
315182518Santoinestatic void
316182518Santoinedevice_sysctl_fini(device_t dev)
317182518Santoine{
318182518Santoine	if (dev->sysctl_tree == NULL)
319182518Santoine		return;
320182518Santoine	sysctl_ctx_free(&dev->sysctl_ctx);
321182518Santoine	dev->sysctl_tree = NULL;
322182518Santoine}
323182518Santoine
324182518Santoine/*
325182518Santoine * /dev/devctl implementation
326182518Santoine */
327182518Santoine
328182518Santoine/*
329182518Santoine * This design allows only one reader for /dev/devctl.  This is not desirable
330182518Santoine * in the long run, but will get a lot of hair out of this implementation.
331182518Santoine * Maybe we should make this device a clonable device.
332181905Sed *
333181905Sed * Also note: we specifically do not attach a device to the device_t tree
334181905Sed * to avoid potential chicken and egg problems.  One could argue that all
335180800Sed * of this belongs to the root node.  One could also further argue that the
336180800Sed * sysctl interface that we have not might more properly be an ioctl
337180614Smarcel * interface, but at this stage of the game, I'm not inclined to rock that
338180614Smarcel * boat.
339180614Smarcel *
340180614Smarcel * I'm also not sure that the SIGIO support is done correctly or not, as
341180614Smarcel * I copied it from a driver that had SIGIO support that likely hasn't been
342180614Smarcel * tested since 3.4 or 2.2.8!
343180331Smarcel */
344180331Smarcel
345180331Smarcelstatic int sysctl_devctl_disable(SYSCTL_HANDLER_ARGS);
346180331Smarcelstatic int devctl_disable = 0;
347180331SmarcelTUNABLE_INT("hw.bus.devctl_disable", &devctl_disable);
348180267SjhbSYSCTL_PROC(_hw_bus, OID_AUTO, devctl_disable, CTLTYPE_INT | CTLFLAG_RW, 0, 0,
349180267Sjhb    sysctl_devctl_disable, "I", "devctl disable");
350180267Sjhb
351180265Sjhbstatic d_open_t		devopen;
352180265Sjhbstatic d_close_t	devclose;
353180265Sjhbstatic d_read_t		devread;
354180259Sjhbstatic d_ioctl_t	devioctl;
355180259Sjhbstatic d_poll_t		devpoll;
356180259Sjhb
357180259Sjhb#define CDEV_MAJOR 173
358180259Sjhbstatic struct cdevsw dev_cdevsw = {
359180257Sjhb	.d_version =	D_VERSION,
360180257Sjhb	.d_flags =	D_NEEDGIANT,
361180257Sjhb	.d_open =	devopen,
362180259Sjhb	.d_close =	devclose,
363180257Sjhb	.d_read =	devread,
364180257Sjhb	.d_ioctl =	devioctl,
365180248Smarcel	.d_poll =	devpoll,
366180248Smarcel	.d_name =	"devctl",
367180248Smarcel	.d_maj =	CDEV_MAJOR,
368180248Smarcel};
369180248Smarcel
370180230Smarcelstruct dev_event_info
371180230Smarcel{
372180230Smarcel	char *dei_data;
373180230Smarcel	TAILQ_ENTRY(dev_event_info) dei_link;
374180230Smarcel};
375180230Smarcel
376180230SmarcelTAILQ_HEAD(devq, dev_event_info);
377180230Smarcel
378180159Sdangerstatic struct dev_softc
379180159Sdanger{
380180159Sdanger	int	inuse;
381180496Santoine	int	nonblock;
382180496Santoine	struct mtx mtx;
383180496Santoine	struct cv cv;
384180496Santoine	struct selinfo sel;
385179784Sed	struct devq devq;
386179784Sed	struct proc *async_proc;
387179784Sed} devsoftc;
388179784Sed
389179784Sedstatic struct cdev *devctl_dev;
390179692Smarcel
391179692Smarcelstatic void
392179692Smarceldevinit(void)
393179315Sbz{
394179315Sbz	devctl_dev = make_dev(&dev_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
395179315Sbz	    "devctl");
396179315Sbz	mtx_init(&devsoftc.mtx, "dev mtx", "devd", MTX_DEF);
397179315Sbz	cv_init(&devsoftc.cv, "dev cv");
398179315Sbz	TAILQ_INIT(&devsoftc.devq);
399179315Sbz}
400179315Sbz
401179315Sbzstatic int
402179315Sbzdevopen(struct cdev *dev, int oflags, int devtype, d_thread_t *td)
403179315Sbz{
404179315Sbz	if (devsoftc.inuse)
405179315Sbz		return (EBUSY);
406179315Sbz	/* move to init */
407179315Sbz	devsoftc.inuse = 1;
408179315Sbz	devsoftc.nonblock = 0;
409179315Sbz	devsoftc.async_proc = NULL;
410179315Sbz	return (0);
411179315Sbz}
412179315Sbz
413179315Sbzstatic int
414179315Sbzdevclose(struct cdev *dev, int fflag, int devtype, d_thread_t *td)
415179315Sbz{
416179315Sbz	devsoftc.inuse = 0;
417179315Sbz	mtx_lock(&devsoftc.mtx);
418179315Sbz	cv_broadcast(&devsoftc.cv);
419179315Sbz	mtx_unlock(&devsoftc.mtx);
420179315Sbz
421179315Sbz	return (0);
422179315Sbz}
423179315Sbz
424179315Sbz/*
425179315Sbz * The read channel for this device is used to report changes to
426179315Sbz * userland in realtime.  We are required to free the data as well as
427179315Sbz * the n1 object because we allocate them separately.  Also note that
428179315Sbz * we return one record at a time.  If you try to read this device a
429179315Sbz * character at a time, you will loose the rest of the data.  Listening
430179315Sbz * programs are expected to cope.
431179315Sbz */
432179315Sbzstatic int
433179315Sbzdevread(struct cdev *dev, struct uio *uio, int ioflag)
434179315Sbz{
435179315Sbz	struct dev_event_info *n1;
436179315Sbz	int rv;
437179315Sbz
438179315Sbz	mtx_lock(&devsoftc.mtx);
439179315Sbz	while (TAILQ_EMPTY(&devsoftc.devq)) {
440179315Sbz		if (devsoftc.nonblock) {
441179315Sbz			mtx_unlock(&devsoftc.mtx);
442179315Sbz			return (EAGAIN);
443179315Sbz		}
444179315Sbz		rv = cv_wait_sig(&devsoftc.cv, &devsoftc.mtx);
445179315Sbz		if (rv) {
446179315Sbz			/*
447179315Sbz			 * Need to translate ERESTART to EINTR here? -- jake
448179315Sbz			 */
449179315Sbz			mtx_unlock(&devsoftc.mtx);
450179315Sbz			return (rv);
451179315Sbz		}
452179315Sbz	}
453179315Sbz	n1 = TAILQ_FIRST(&devsoftc.devq);
454179315Sbz	TAILQ_REMOVE(&devsoftc.devq, n1, dei_link);
455179315Sbz	mtx_unlock(&devsoftc.mtx);
456179315Sbz	rv = uiomove(n1->dei_data, strlen(n1->dei_data), uio);
457179315Sbz	free(n1->dei_data, M_BUS);
458179315Sbz	free(n1, M_BUS);
459179315Sbz	return (rv);
460179315Sbz}
461179315Sbz
462179315Sbzstatic	int
463179315Sbzdevioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, d_thread_t *td)
464179315Sbz{
465179315Sbz	switch (cmd) {
466179315Sbz
467179315Sbz	case FIONBIO:
468179315Sbz		if (*(int*)data)
469179315Sbz			devsoftc.nonblock = 1;
470179315Sbz		else
471179315Sbz			devsoftc.nonblock = 0;
472179315Sbz		return (0);
473179315Sbz	case FIOASYNC:
474179315Sbz		if (*(int*)data)
475179315Sbz			devsoftc.async_proc = td->td_proc;
476179315Sbz		else
477179315Sbz			devsoftc.async_proc = NULL;
478179315Sbz		return (0);
479179315Sbz
480179315Sbz		/* (un)Support for other fcntl() calls. */
481179315Sbz	case FIOCLEX:
482179315Sbz	case FIONCLEX:
483179315Sbz	case FIONREAD:
484179315Sbz	case FIOSETOWN:
485179315Sbz	case FIOGETOWN:
486179315Sbz	default:
487179315Sbz		break;
488179315Sbz	}
489179315Sbz	return (ENOTTY);
490179315Sbz}
491179315Sbz
492179315Sbzstatic	int
493179315Sbzdevpoll(struct cdev *dev, int events, d_thread_t *td)
494179315Sbz{
495179315Sbz	int	revents = 0;
496179315Sbz
497179315Sbz	mtx_lock(&devsoftc.mtx);
498179315Sbz	if (events & (POLLIN | POLLRDNORM)) {
499179315Sbz		if (!TAILQ_EMPTY(&devsoftc.devq))
500179315Sbz			revents = events & (POLLIN | POLLRDNORM);
501179315Sbz		else
502179315Sbz			selrecord(td, &devsoftc.sel);
503179315Sbz	}
504179315Sbz	mtx_unlock(&devsoftc.mtx);
505179315Sbz
506179315Sbz	return (revents);
507179361Santoine}
508179361Santoine
509179361Santoine/**
510179361Santoine * @brief Queue data to be read from the devctl device
511179361Santoine *
512179361Santoine * Generic interface to queue data to the devctl device.  It is
513179361Santoine * assumed that @p data is properly formatted.  It is further assumed
514179361Santoine * that @p data is allocated using the M_BUS malloc type.
515179361Santoine */
516179361Santoinevoid
517179361Santoinedevctl_queue_data(char *data)
518179361Santoine{
519179361Santoine	struct dev_event_info *n1 = NULL;
520179361Santoine	struct proc *p;
521179361Santoine
522179361Santoine	n1 = malloc(sizeof(*n1), M_BUS, M_NOWAIT);
523179361Santoine	if (n1 == NULL)
524179361Santoine		return;
525179361Santoine	n1->dei_data = data;
526179361Santoine	mtx_lock(&devsoftc.mtx);
527178924Santoine	TAILQ_INSERT_TAIL(&devsoftc.devq, n1, dei_link);
528178924Santoine	cv_broadcast(&devsoftc.cv);
529178924Santoine	mtx_unlock(&devsoftc.mtx);
530178924Santoine	selwakeup(&devsoftc.sel);
531178924Santoine	p = devsoftc.async_proc;
532177831Sflz	if (p != NULL) {
533177831Sflz		PROC_LOCK(p);
534177831Sflz		psignal(p, SIGIO);
535177831Sflz		PROC_UNLOCK(p);
536177831Sflz	}
537178331Santoine}
538178331Santoine
539178331Santoine/**
540178331Santoine * @brief Send a 'notification' to userland, using standard ways
541178331Santoine */
542178331Santoinevoid
543178331Santoinedevctl_notify(const char *system, const char *subsystem, const char *type,
544178331Santoine    const char *data)
545178331Santoine{
546178331Santoine	int len = 0;
547178331Santoine	char *msg;
548178331Santoine
549178331Santoine	if (system == NULL)
550178331Santoine		return;		/* BOGUS!  Must specify system. */
551178331Santoine	if (subsystem == NULL)
552178331Santoine		return;		/* BOGUS!  Must specify subsystem. */
553178924Santoine	if (type == NULL)
554178924Santoine		return;		/* BOGUS!  Must specify type. */
555178924Santoine	len += strlen(" system=") + strlen(system);
556178924Santoine	len += strlen(" subsystem=") + strlen(subsystem);
557176422Sthompsa	len += strlen(" type=") + strlen(type);
558176422Sthompsa	/* add in the data message plus newline. */
559175690Sbrueffer	if (data != NULL)
560175690Sbrueffer		len += strlen(data);
561175690Sbrueffer	len += 3;	/* '!', '\n', and NUL */
562175576Sattilio	msg = malloc(len, M_BUS, M_NOWAIT);
563175576Sattilio	if (msg == NULL)
564175227Sjhb		return;		/* Drop it on the floor */
565175227Sjhb	snprintf(msg, len, "!system=%s subsystem=%s type=%s %s\n", system,
566175227Sjhb	    subsystem, type, data);
567174426Sdougb	devctl_queue_data(msg);
568174426Sdougb}
569174426Sdougb
570177153Sbrueffer/*
571177153Sbrueffer * Common routine that tries to make sending messages as easy as possible.
572174092Sbrooks * We allocate memory for the data, copy strings into that, but do not
573174092Sbrooks * free it unless there's an error.  The dequeue part of the driver should
574174092Sbrooks * free the data.  We don't send data when the device is disabled.  We do
575174092Sbrooks * send data, even when we have no listeners, because we wish to avoid
576176956Santoine * races relating to startup and restart of listening applications.
577176956Santoine *
578176956Santoine * devaddq is designed to string together the type of event, with the
579176956Santoine * object of that event, plus the plug and play info and location info
580174092Sbrooks * for that event.  This is likely most useful for devices, but less
581174061Sjb * useful for other consumers of this interface.  Those should use
582174061Sjb * the devctl_queue_data() interface instead.
583175227Sjhb */
584175227Sjhbstatic void
585173466Simpdevaddq(const char *type, const char *what, device_t dev)
586173466Simp{
587173662Smarcel	char *data = NULL;
588173662Smarcel	char *loc = NULL;
589173662Smarcel	char *pnp = NULL;
590173662Smarcel	const char *parstr;
591173662Smarcel
592173662Smarcel	if (devctl_disable)
593175227Sjhb		return;
594175227Sjhb	data = malloc(1024, M_BUS, M_NOWAIT);
595172983Smtm	if (data == NULL)
596172983Smtm		goto bad;
597172390Sbushman
598173176Sbushman	/* get the bus specific location of this device */
599172390Sbushman	loc = malloc(1024, M_BUS, M_NOWAIT);
600172390Sbushman	if (loc == NULL)
601172570Sru		goto bad;
602172570Sru	*loc = '\0';
603171786Smarcel	bus_child_location_str(dev, loc, 1024);
604171786Smarcel
605171786Smarcel	/* Get the bus specific pnp info of this device */
606171786Smarcel	pnp = malloc(1024, M_BUS, M_NOWAIT);
607171696Sbz	if (pnp == NULL)
608171696Sbz		goto bad;
609179368Sbz	*pnp = '\0';
610171461Srwatson	bus_child_pnpinfo_str(dev, pnp, 1024);
611171461Srwatson
612171461Srwatson	/* Get the parent of this device, or / if high enough in the tree. */
613171461Srwatson	if (device_get_parent(dev) == NULL)
614171461Srwatson		parstr = ".";	/* Or '/' ? */
615171461Srwatson	else
616171461Srwatson		parstr = device_get_nameunit(device_get_parent(dev));
617171461Srwatson	/* String it all together. */
618171461Srwatson	snprintf(data, 1024, "%s%s at %s %s on %s\n", type, what, loc, pnp,
619171461Srwatson	  parstr);
620171461Srwatson	free(loc, M_BUS);
621171461Srwatson	free(pnp, M_BUS);
622171461Srwatson	devctl_queue_data(data);
623171461Srwatson	return;
624171461Srwatsonbad:
625171461Srwatson	free(pnp, M_BUS);
626171461Srwatson	free(loc, M_BUS);
627171461Srwatson	free(data, M_BUS);
628171461Srwatson	return;
629171461Srwatson}
630171461Srwatson
631171461Srwatson/*
632171461Srwatson * A device was added to the tree.  We are called just after it successfully
633171461Srwatson * attaches (that is, probe and attach success for this device).  No call
634171461Srwatson * is made if a device is merely parented into the tree.  See devnomatch
635171461Srwatson * if probe fails.  If attach fails, no notification is sent (but maybe
636171461Srwatson * we should have a different message for this).
637171461Srwatson */
638171461Srwatsonstatic void
639171461Srwatsondevadded(device_t dev)
640171461Srwatson{
641171461Srwatson	char *pnp = NULL;
642171461Srwatson	char *tmp = NULL;
643171461Srwatson
644171461Srwatson	pnp = malloc(1024, M_BUS, M_NOWAIT);
645171461Srwatson	if (pnp == NULL)
646171461Srwatson		goto fail;
647171461Srwatson	tmp = malloc(1024, M_BUS, M_NOWAIT);
648171461Srwatson	if (tmp == NULL)
649171461Srwatson		goto fail;
650171461Srwatson	*pnp = '\0';
651171461Srwatson	bus_child_pnpinfo_str(dev, pnp, 1024);
652171461Srwatson	snprintf(tmp, 1024, "%s %s", device_get_nameunit(dev), pnp);
653171461Srwatson	devaddq("+", tmp, dev);
654171461Srwatsonfail:
655171461Srwatson	if (pnp != NULL)
656171461Srwatson		free(pnp, M_BUS);
657171461Srwatson	if (tmp != NULL)
658171461Srwatson		free(tmp, M_BUS);
659171461Srwatson	return;
660171461Srwatson}
661171461Srwatson
662171461Srwatson/*
663171461Srwatson * A device was removed from the tree.  We are called just before this
664171461Srwatson * happens.
665171461Srwatson */
666171461Srwatsonstatic void
667171461Srwatsondevremoved(device_t dev)
668171461Srwatson{
669171461Srwatson	char *pnp = NULL;
670171461Srwatson	char *tmp = NULL;
671171461Srwatson
672171461Srwatson	pnp = malloc(1024, M_BUS, M_NOWAIT);
673171461Srwatson	if (pnp == NULL)
674171461Srwatson		goto fail;
675171461Srwatson	tmp = malloc(1024, M_BUS, M_NOWAIT);
676171461Srwatson	if (tmp == NULL)
677171461Srwatson		goto fail;
678171461Srwatson	*pnp = '\0';
679171461Srwatson	bus_child_pnpinfo_str(dev, pnp, 1024);
680171461Srwatson	snprintf(tmp, 1024, "%s %s", device_get_nameunit(dev), pnp);
681171461Srwatson	devaddq("-", tmp, dev);
682176956Santoinefail:
683176956Santoine	if (pnp != NULL)
684176956Santoine		free(pnp, M_BUS);
685176956Santoine	if (tmp != NULL)
686176956Santoine		free(tmp, M_BUS);
687176956Santoine	return;
688171274Sbz}
689171274Sbz
690171274Sbz/*
691171274Sbz * Called when there's no match for this device.  This is only called
692171274Sbz * the first time that no match happens, so we don't keep getitng this
693171274Sbz * message.  Should that prove to be undesirable, we can change it.
694171274Sbz * This is called when all drivers that can attach to a given bus
695171274Sbz * decline to accept this device.  Other errrors may not be detected.
696171274Sbz */
697179368Sbzstatic void
698171205Sbzdevnomatch(device_t dev)
699171205Sbz{
700171205Sbz	devaddq("?", "", dev);
701171205Sbz}
702171205Sbz
703171175Smlaierstatic int
704171175Smlaiersysctl_devctl_disable(SYSCTL_HANDLER_ARGS)
705171137Sbz{
706171137Sbz	struct dev_event_info *n1;
707171137Sbz	int dis, error;
708171137Sbz
709171137Sbz	dis = devctl_disable;
710171137Sbz	error = sysctl_handle_int(oidp, &dis, 0, req);
711171137Sbz	if (error || !req->newptr)
712171137Sbz		return (error);
713171137Sbz	mtx_lock(&devsoftc.mtx);
714171137Sbz	devctl_disable = dis;
715171137Sbz	if (dis) {
716171137Sbz		while (!TAILQ_EMPTY(&devsoftc.devq)) {
717171137Sbz			n1 = TAILQ_FIRST(&devsoftc.devq);
718171137Sbz			TAILQ_REMOVE(&devsoftc.devq, n1, dei_link);
719171137Sbz			free(n1->dei_data, M_BUS);
720171137Sbz			free(n1, M_BUS);
721171137Sbz		}
722171137Sbz	}
723171137Sbz	mtx_unlock(&devsoftc.mtx);
724171131Sthompsa	return (0);
725171131Sthompsa}
726171143Sthompsa
727171023Srafan/* End of /dev/devctl code */
728171023Srafan
729171023SrafanTAILQ_HEAD(,device)	bus_data_devices;
730171023Srafanstatic int bus_data_generation = 1;
731171023Srafan
732171023Srafankobj_method_t null_methods[] = {
733171388Sdougb	{ 0, 0 }
734171388Sdougb};
735171388Sdougb
736171388SdougbDEFINE_CLASS(null, null_methods, 0);
737170926Srafan
738170926Srafan/*
739170926Srafan * Devclass implementation
740170926Srafan */
741170926Srafan
742170926Srafanstatic devclass_list_t devclasses = TAILQ_HEAD_INITIALIZER(devclasses);
743170926Srafan
744170926Srafan
745170926Srafan/**
746170926Srafan * @internal
747170926Srafan * @brief Find or create a device class
748170926Srafan *
749170926Srafan * If a device class with the name @p classname exists, return it,
750170926Srafan * otherwise if @p create is non-zero create and return a new device
751170926Srafan * class.
752170926Srafan *
753170926Srafan * If @p parentname is non-NULL, the parent of the devclass is set to
754170926Srafan * the devclass of that name.
755170926Srafan *
756170926Srafan * @param classname	the devclass name to find or create
757170926Srafan * @param parentname	the parent devclass name or @c NULL
758170926Srafan * @param create	non-zero to create a devclass
759170926Srafan */
760170926Srafanstatic devclass_t
761170926Srafandevclass_find_internal(const char *classname, const char *parentname,
762170926Srafan		       int create)
763170926Srafan{
764170926Srafan	devclass_t dc;
765170926Srafan
766170926Srafan	PDEBUG(("looking for %s", classname));
767170926Srafan	if (!classname)
768170926Srafan		return (NULL);
769170926Srafan
770170926Srafan	TAILQ_FOREACH(dc, &devclasses, link) {
771170926Srafan		if (!strcmp(dc->name, classname))
772170926Srafan			break;
773170926Srafan	}
774170926Srafan
775170926Srafan	if (create && !dc) {
776170926Srafan		PDEBUG(("creating %s", classname));
777170926Srafan		dc = malloc(sizeof(struct devclass) + strlen(classname) + 1,
778176956Santoine		    M_BUS, M_NOWAIT|M_ZERO);
779176956Santoine		if (!dc)
780176956Santoine			return (NULL);
781176956Santoine		dc->parent = NULL;
782176956Santoine		dc->name = (char*) (dc + 1);
783176956Santoine		strcpy(dc->name, classname);
784176956Santoine		TAILQ_INIT(&dc->drivers);
785176956Santoine		TAILQ_INSERT_TAIL(&devclasses, dc, link);
786176956Santoine
787176956Santoine		bus_data_generation_update();
788176956Santoine	}
789176956Santoine	if (parentname && dc && !dc->parent) {
790176956Santoine		dc->parent = devclass_find_internal(parentname, 0, FALSE);
791176956Santoine	}
792176956Santoine
793176956Santoine	return (dc);
794176956Santoine}
795176956Santoine
796176956Santoine/**
797176956Santoine * @brief Create a device class
798176956Santoine *
799176956Santoine * If a device class with the name @p classname exists, return it,
800176956Santoine * otherwise create and return a new device class.
801176956Santoine *
802176956Santoine * @param classname	the devclass name to find or create
803176956Santoine */
804176956Santoinedevclass_t
805176956Santoinedevclass_create(const char *classname)
806176956Santoine{
807176956Santoine	return (devclass_find_internal(classname, 0, TRUE));
808176956Santoine}
809176956Santoine
810176956Santoine/**
811176956Santoine * @brief Find a device class
812176956Santoine *
813176956Santoine * If a device class with the name @p classname exists, return it,
814171476Sdelphij * otherwise return @c NULL.
815171476Sdelphij *
816170312Sdelphij * @param classname	the devclass name to find
817170312Sdelphij */
818170926Srafandevclass_t
819173816Srudevclass_find(const char *classname)
820169815Sdelphij{
821169815Sdelphij	return (devclass_find_internal(classname, 0, FALSE));
822169815Sdelphij}
823169815Sdelphij
824169815Sdelphij/**
825169815Sdelphij * @brief Add a device driver to a device class
826169815Sdelphij *
827169815Sdelphij * Add a device driver to a devclass. This is normally called
828169815Sdelphij * automatically by DRIVER_MODULE(). The BUS_DRIVER_ADDED() method of
829169815Sdelphij * all devices in the devclass will be called to allow them to attempt
830169815Sdelphij * to re-probe any unmatched children.
831169815Sdelphij *
832170204Sru * @param dc		the devclass to edit
833169815Sdelphij * @param driver	the driver to register
834169815Sdelphij */
835169815Sdelphijint
836169815Sdelphijdevclass_add_driver(devclass_t dc, driver_t *driver)
837170204Sru{
838169815Sdelphij	driverlink_t dl;
839169815Sdelphij	int i;
840169815Sdelphij
841169815Sdelphij	PDEBUG(("%s", DRIVERNAME(driver)));
842169815Sdelphij
843169815Sdelphij	dl = malloc(sizeof *dl, M_BUS, M_NOWAIT|M_ZERO);
844169815Sdelphij	if (!dl)
845169815Sdelphij		return (ENOMEM);
846169815Sdelphij
847169815Sdelphij	/*
848169815Sdelphij	 * Compile the driver's methods. Also increase the reference count
849169815Sdelphij	 * so that the class doesn't get freed when the last instance
850169815Sdelphij	 * goes. This means we can safely use static methods and avoids a
851169815Sdelphij	 * double-free in devclass_delete_driver.
852169815Sdelphij	 */
853169815Sdelphij	kobj_class_compile((kobj_class_t) driver);
854169815Sdelphij
855169815Sdelphij	/*
856169815Sdelphij	 * Make sure the devclass which the driver is implementing exists.
857169815Sdelphij	 */
858169815Sdelphij	devclass_find_internal(driver->name, 0, TRUE);
859169815Sdelphij
860169815Sdelphij	dl->driver = driver;
861169815Sdelphij	TAILQ_INSERT_TAIL(&dc->drivers, dl, link);
862169815Sdelphij	driver->refs++;
863169815Sdelphij
864169815Sdelphij	/*
865169815Sdelphij	 * Call BUS_DRIVER_ADDED for any existing busses in this class.
866169815Sdelphij	 */
867169815Sdelphij	for (i = 0; i < dc->maxunit; i++)
868169815Sdelphij		if (dc->devices[i])
869169815Sdelphij			BUS_DRIVER_ADDED(dc->devices[i], driver);
870169815Sdelphij
871169815Sdelphij	bus_data_generation_update();
872169815Sdelphij	return (0);
873169815Sdelphij}
874170204Sru
875169815Sdelphij/**
876169815Sdelphij * @brief Delete a device driver from a device class
877169815Sdelphij *
878170917Srafan * Delete a device driver from a devclass. This is normally called
879169815Sdelphij * automatically by DRIVER_MODULE().
880169815Sdelphij *
881169815Sdelphij * If the driver is currently attached to any devices,
882169815Sdelphij * devclass_delete_driver() will first attempt to detach from each
883169815Sdelphij * device. If one of the detach calls fails, the driver will not be
884169815Sdelphij * deleted.
885169815Sdelphij *
886169815Sdelphij * @param dc		the devclass to edit
887169815Sdelphij * @param driver	the driver to unregister
888169815Sdelphij */
889169815Sdelphijint
890169815Sdelphijdevclass_delete_driver(devclass_t busclass, driver_t *driver)
891169815Sdelphij{
892169815Sdelphij	devclass_t dc = devclass_find(driver->name);
893169815Sdelphij	driverlink_t dl;
894169815Sdelphij	device_t dev;
895169815Sdelphij	int i;
896169815Sdelphij	int error;
897169815Sdelphij
898169815Sdelphij	PDEBUG(("%s from devclass %s", driver->name, DEVCLANAME(busclass)));
899169815Sdelphij
900169815Sdelphij	if (!dc)
901169815Sdelphij		return (0);
902169815Sdelphij
903169815Sdelphij	/*
904169815Sdelphij	 * Find the link structure in the bus' list of drivers.
905169815Sdelphij	 */
906169815Sdelphij	TAILQ_FOREACH(dl, &busclass->drivers, link) {
907169815Sdelphij		if (dl->driver == driver)
908169815Sdelphij			break;
909169815Sdelphij	}
910169815Sdelphij
911169815Sdelphij	if (!dl) {
912169815Sdelphij		PDEBUG(("%s not found in %s list", driver->name,
913169815Sdelphij		    busclass->name));
914169815Sdelphij		return (ENOENT);
915169815Sdelphij	}
916169815Sdelphij
917169815Sdelphij	/*
918169815Sdelphij	 * Disassociate from any devices.  We iterate through all the
919169815Sdelphij	 * devices in the devclass of the driver and detach any which are
920169815Sdelphij	 * using the driver and which have a parent in the devclass which
921169815Sdelphij	 * we are deleting from.
922169815Sdelphij	 *
923169815Sdelphij	 * Note that since a driver can be in multiple devclasses, we
924169815Sdelphij	 * should not detach devices which are not children of devices in
925169815Sdelphij	 * the affected devclass.
926169815Sdelphij	 */
927169815Sdelphij	for (i = 0; i < dc->maxunit; i++) {
928170204Sru		if (dc->devices[i]) {
929169815Sdelphij			dev = dc->devices[i];
930169815Sdelphij			if (dev->driver == driver && dev->parent &&
931169815Sdelphij			    dev->parent->devclass == busclass) {
932169815Sdelphij				if ((error = device_detach(dev)) != 0)
933169815Sdelphij					return (error);
934170190Sru				device_set_driver(dev, NULL);
935169815Sdelphij			}
936169815Sdelphij		}
937169815Sdelphij	}
938169815Sdelphij
939169815Sdelphij	TAILQ_REMOVE(&busclass->drivers, dl, link);
940169815Sdelphij	free(dl, M_BUS);
941169815Sdelphij
942169815Sdelphij	driver->refs--;
943169815Sdelphij	if (driver->refs == 0)
944169815Sdelphij		kobj_class_free((kobj_class_t) driver);
945169815Sdelphij
946169815Sdelphij	bus_data_generation_update();
947170190Sru	return (0);
948170190Sru}
949170190Sru
950170190Sru/**
951170190Sru * @internal
952170190Sru */
953170190Srustatic driverlink_t
954171476Sdelphijdevclass_find_driver_internal(devclass_t dc, const char *classname)
955171476Sdelphij{
956171476Sdelphij	driverlink_t dl;
957171476Sdelphij
958171476Sdelphij	PDEBUG(("%s in devclass %s", classname, DEVCLANAME(dc)));
959171476Sdelphij
960171476Sdelphij	TAILQ_FOREACH(dl, &dc->drivers, link) {
961171476Sdelphij		if (!strcmp(dl->driver->name, classname))
962171476Sdelphij			return (dl);
963171476Sdelphij	}
964171476Sdelphij
965171476Sdelphij	PDEBUG(("not found"));
966171476Sdelphij	return (NULL);
967171476Sdelphij}
968171476Sdelphij
969171476Sdelphij/**
970171476Sdelphij * @brief Search a devclass for a driver
971171476Sdelphij *
972171476Sdelphij * This function searches the devclass's list of drivers and returns
973171476Sdelphij * the first driver whose name is @p classname or @c NULL if there is
974171476Sdelphij * no driver of that name.
975171476Sdelphij *
976171476Sdelphij * @param dc		the devclass to search
977171476Sdelphij * @param classname	the driver name to search for
978171476Sdelphij */
979171476Sdelphijkobj_class_t
980171476Sdelphijdevclass_find_driver(devclass_t dc, const char *classname)
981171476Sdelphij{
982171476Sdelphij	driverlink_t dl;
983171476Sdelphij
984171476Sdelphij	dl = devclass_find_driver_internal(dc, classname);
985171476Sdelphij	if (dl)
986171476Sdelphij		return (dl->driver);
987171476Sdelphij	return (NULL);
988171476Sdelphij}
989171476Sdelphij
990171476Sdelphij/**
991171476Sdelphij * @brief Return the name of the devclass
992171476Sdelphij */
993171476Sdelphijconst char *
994171476Sdelphijdevclass_get_name(devclass_t dc)
995171476Sdelphij{
996171476Sdelphij	return (dc->name);
997171476Sdelphij}
998171476Sdelphij
999171476Sdelphij/**
1000171476Sdelphij * @brief Find a device given a unit number
1001171476Sdelphij *
1002171476Sdelphij * @param dc		the devclass to search
1003171476Sdelphij * @param unit		the unit number to search for
1004171476Sdelphij *
1005171476Sdelphij * @returns		the device with the given unit number or @c
1006171476Sdelphij *			NULL if there is no such device
1007171476Sdelphij */
1008171476Sdelphijdevice_t
1009171476Sdelphijdevclass_get_device(devclass_t dc, int unit)
1010171476Sdelphij{
1011171476Sdelphij	if (dc == NULL || unit < 0 || unit >= dc->maxunit)
1012171476Sdelphij		return (NULL);
1013171476Sdelphij	return (dc->devices[unit]);
1014171476Sdelphij}
1015171476Sdelphij
1016171476Sdelphij/**
1017171476Sdelphij * @brief Find the softc field of a device given a unit number
1018171476Sdelphij *
1019171476Sdelphij * @param dc		the devclass to search
1020171476Sdelphij * @param unit		the unit number to search for
1021171476Sdelphij *
1022171476Sdelphij * @returns		the softc field of the device with the given
1023171476Sdelphij *			unit number or @c NULL if there is no such
1024171476Sdelphij *			device
1025171476Sdelphij */
1026171476Sdelphijvoid *
1027171476Sdelphijdevclass_get_softc(devclass_t dc, int unit)
1028171476Sdelphij{
1029171476Sdelphij	device_t dev;
1030171476Sdelphij
1031171476Sdelphij	dev = devclass_get_device(dc, unit);
1032171476Sdelphij	if (!dev)
1033171476Sdelphij		return (NULL);
1034171476Sdelphij
1035171476Sdelphij	return (device_get_softc(dev));
1036171476Sdelphij}
1037171476Sdelphij
1038171476Sdelphij/**
1039171476Sdelphij * @brief Get a list of devices in the devclass
1040171476Sdelphij *
1041171476Sdelphij * An array containing a list of all the devices in the given devclass
1042171476Sdelphij * is allocated and returned in @p *devlistp. The number of devices
1043171476Sdelphij * in the array is returned in @p *devcountp. The caller should free
1044171476Sdelphij * the array using @c free(p, M_TEMP).
1045171476Sdelphij *
1046171476Sdelphij * @param dc		the devclass to examine
1047171476Sdelphij * @param devlistp	points at location for array pointer return
1048171476Sdelphij *			value
1049171476Sdelphij * @param devcountp	points at location for array size return value
1050171476Sdelphij *
1051171476Sdelphij * @retval 0		success
1052171476Sdelphij * @retval ENOMEM	the array allocation failed
1053171476Sdelphij */
1054171476Sdelphijint
1055171476Sdelphijdevclass_get_devices(devclass_t dc, device_t **devlistp, int *devcountp)
1056171476Sdelphij{
1057171476Sdelphij	int i;
1058171476Sdelphij	int count;
1059171476Sdelphij	device_t *list;
1060171476Sdelphij
1061171476Sdelphij	count = 0;
1062171476Sdelphij	for (i = 0; i < dc->maxunit; i++)
1063171476Sdelphij		if (dc->devices[i])
1064171476Sdelphij			count++;
1065171476Sdelphij
1066171476Sdelphij	list = malloc(count * sizeof(device_t), M_TEMP, M_NOWAIT|M_ZERO);
1067171476Sdelphij	if (!list)
1068171476Sdelphij		return (ENOMEM);
1069171476Sdelphij
1070171476Sdelphij	count = 0;
1071171476Sdelphij	for (i = 0; i < dc->maxunit; i++) {
1072171476Sdelphij		if (dc->devices[i]) {
1073171476Sdelphij			list[count] = dc->devices[i];
1074171476Sdelphij			count++;
1075171476Sdelphij		}
1076171476Sdelphij	}
1077171476Sdelphij
1078171476Sdelphij	*devlistp = list;
1079171476Sdelphij	*devcountp = count;
1080171476Sdelphij
1081171476Sdelphij	return (0);
1082171476Sdelphij}
1083171476Sdelphij
1084171476Sdelphij/**
1085171476Sdelphij * @brief Get the maximum unit number used in a devclass
1086171476Sdelphij *
1087171476Sdelphij * @param dc		the devclass to examine
1088171476Sdelphij */
1089171476Sdelphijint
1090171476Sdelphijdevclass_get_maxunit(devclass_t dc)
1091171476Sdelphij{
1092171476Sdelphij	return (dc->maxunit);
1093171476Sdelphij}
1094171476Sdelphij
1095171476Sdelphij/**
1096171476Sdelphij * @brief Find a free unit number in a devclass
1097171476Sdelphij *
1098171476Sdelphij * This function searches for the first unused unit number greater
1099171476Sdelphij * that or equal to @p unit.
1100171476Sdelphij *
1101171476Sdelphij * @param dc		the devclass to examine
1102171476Sdelphij * @param unit		the first unit number to check
1103171476Sdelphij */
1104171476Sdelphijint
1105171476Sdelphijdevclass_find_free_unit(devclass_t dc, int unit)
1106171476Sdelphij{
1107171476Sdelphij	if (dc == NULL)
1108171476Sdelphij		return (unit);
1109171476Sdelphij	while (unit < dc->maxunit && dc->devices[unit] != NULL)
1110171476Sdelphij		unit++;
1111171476Sdelphij	return (unit);
1112171476Sdelphij}
1113171476Sdelphij
1114171476Sdelphij/**
1115171476Sdelphij * @brief Set the parent of a devclass
1116171476Sdelphij *
1117171476Sdelphij * The parent class is normally initialised automatically by
1118171476Sdelphij * DRIVER_MODULE().
1119171476Sdelphij *
1120171476Sdelphij * @param dc		the devclass to edit
1121171476Sdelphij * @param pdc		the new parent devclass
1122171476Sdelphij */
1123171476Sdelphijvoid
1124171476Sdelphijdevclass_set_parent(devclass_t dc, devclass_t pdc)
1125171476Sdelphij{
1126171476Sdelphij	dc->parent = pdc;
1127171476Sdelphij}
1128171476Sdelphij
1129171476Sdelphij/**
1130171476Sdelphij * @brief Get the parent of a devclass
1131171476Sdelphij *
1132171476Sdelphij * @param dc		the devclass to examine
1133171476Sdelphij */
1134171476Sdelphijdevclass_t
1135171476Sdelphijdevclass_get_parent(devclass_t dc)
1136171476Sdelphij{
1137171476Sdelphij	return (dc->parent);
1138171476Sdelphij}
1139171476Sdelphij
1140171476Sdelphijstruct sysctl_ctx_list *
1141171476Sdelphijdevclass_get_sysctl_ctx(devclass_t dc)
1142171476Sdelphij{
1143171476Sdelphij	return (&dc->sysctl_ctx);
1144171476Sdelphij}
1145171476Sdelphij
1146171476Sdelphijstruct sysctl_oid *
1147171476Sdelphijdevclass_get_sysctl_tree(devclass_t dc)
1148171476Sdelphij{
1149171476Sdelphij	return (dc->sysctl_tree);
1150171476Sdelphij}
1151171476Sdelphij
1152171476Sdelphij/**
1153171476Sdelphij * @internal
1154171476Sdelphij * @brief Allocate a unit number
1155171476Sdelphij *
1156171476Sdelphij * On entry, @p *unitp is the desired unit number (or @c -1 if any
1157171476Sdelphij * will do). The allocated unit number is returned in @p *unitp.
1158171476Sdelphij
1159171476Sdelphij * @param dc		the devclass to allocate from
1160171476Sdelphij * @param unitp		points at the location for the allocated unit
1161171476Sdelphij *			number
1162171476Sdelphij *
1163171476Sdelphij * @retval 0		success
1164171476Sdelphij * @retval EEXIST	the requested unit number is already allocated
1165171476Sdelphij * @retval ENOMEM	memory allocation failure
1166171476Sdelphij */
1167171476Sdelphijstatic int
1168171476Sdelphijdevclass_alloc_unit(devclass_t dc, int *unitp)
1169171476Sdelphij{
1170171476Sdelphij	int unit = *unitp;
1171171476Sdelphij
1172171476Sdelphij	PDEBUG(("unit %d in devclass %s", unit, DEVCLANAME(dc)));
1173171476Sdelphij
1174171476Sdelphij	/* If we were given a wired unit number, check for existing device */
1175171476Sdelphij	/* XXX imp XXX */
1176171476Sdelphij	if (unit != -1) {
1177171476Sdelphij		if (unit >= 0 && unit < dc->maxunit &&
1178169445Sroberto		    dc->devices[unit] != NULL) {
1179169445Sroberto			if (bootverbose)
1180169445Sroberto				printf("%s: %s%d already exists; skipping it\n",
1181169026Semax				    dc->name, dc->name, *unitp);
1182169026Semax			return (EEXIST);
1183168916Sbrueffer		}
1184168916Sbrueffer	} else {
1185168796Sthompsa		/* Unwired device, find the next available slot for it */
1186168796Sthompsa		unit = 0;
1187168544Spjd		while (unit < dc->maxunit && dc->devices[unit] != NULL)
1188168544Spjd			unit++;
1189167980Sdelphij	}
1190167980Sdelphij
1191167699Sdelphij	/*
1192167699Sdelphij	 * We've selected a unit beyond the length of the table, so let's
1193176956Santoine	 * extend the table to make room for all units up to and including
1194176956Santoine	 * this one.
1195176956Santoine	 */
1196167137Sbms	if (unit >= dc->maxunit) {
1197167137Sbms		device_t *newlist;
1198170190Sru		int newsize;
1199166981Sru
1200166981Sru		newsize = roundup((unit + 1), MINALLOCSIZE / sizeof(device_t));
1201170192Sru		newlist = malloc(sizeof(device_t) * newsize, M_BUS, M_NOWAIT);
1202170218Struckman		if (!newlist)
1203166668Sbrueffer			return (ENOMEM);
1204166668Sbrueffer		bcopy(dc->devices, newlist, sizeof(device_t) * dc->maxunit);
1205166389Srafan		bzero(newlist + dc->maxunit,
1206166389Srafan		    sizeof(device_t) * (newsize - dc->maxunit));
1207166389Srafan		if (dc->devices)
1208172882Sru			free(dc->devices, M_BUS);
1209172882Sru		dc->devices = newlist;
1210172882Sru		dc->maxunit = newsize;
1211172882Sru	}
1212170190Sru	PDEBUG(("now: unit %d in devclass %s", unit, DEVCLANAME(dc)));
1213170190Sru
1214170190Sru	*unitp = unit;
1215170190Sru	return (0);
1216172882Sru}
1217172882Sru
1218172882Sru/**
1219170190Sru * @internal
1220166308Sphk * @brief Add a device to a devclass
1221166308Sphk *
1222170192Sru * A unit number is allocated for the device (using the device's
1223170192Sru * preferred unit number if any) and the device is registered in the
1224166246Speter * devclass. This allows the device to be looked up by its unit
1225166246Speter * number, e.g. by decoding a dev_t minor number.
1226166246Speter *
1227166246Speter * @param dc		the devclass to add to
1228166246Speter * @param dev		the device to add
1229164796Spiso *
1230164796Spiso * @retval 0		success
1231164796Spiso * @retval EEXIST	the requested unit number is already allocated
1232164796Spiso * @retval ENOMEM	memory allocation failure
1233164796Spiso */
1234164796Spisostatic int
1235164796Spisodevclass_add_device(devclass_t dc, device_t dev)
1236164796Spiso{
1237164796Spiso	int buflen, error;
1238166672Sbrueffer
1239164796Spiso	PDEBUG(("%s in devclass %s", DEVICENAME(dev), DEVCLANAME(dc)));
1240164796Spiso
1241164796Spiso	buflen = snprintf(NULL, 0, "%s%d$", dc->name, dev->unit);
1242164796Spiso	if (buflen < 0)
1243164796Spiso		return (ENOMEM);
1244164796Spiso	dev->nameunit = malloc(buflen, M_BUS, M_NOWAIT|M_ZERO);
1245164796Spiso	if (!dev->nameunit)
1246164796Spiso		return (ENOMEM);
1247165726Skientzle
1248165726Skientzle	if ((error = devclass_alloc_unit(dc, &dev->unit)) != 0) {
1249164610Simp		free(dev->nameunit, M_BUS);
1250164610Simp		dev->nameunit = NULL;
1251164537Srodrigc		return (error);
1252164537Srodrigc	}
1253164537Srodrigc	dc->devices[dev->unit] = dev;
1254164537Srodrigc	dev->devclass = dc;
1255164537Srodrigc	snprintf(dev->nameunit, buflen, "%s%d", dc->name, dev->unit);
1256164537Srodrigc
1257164537Srodrigc	return (0);
1258170190Sru}
1259170190Sru
1260170190Sru/**
1261170190Sru * @internal
1262170190Sru * @brief Delete a device from a devclass
1263170190Sru *
1264164537Srodrigc * The device is removed from the devclass's device list and its unit
1265164537Srodrigc * number is freed.
1266164537Srodrigc
1267164537Srodrigc * @param dc		the devclass to delete from
1268164537Srodrigc * @param dev		the device to delete
1269164537Srodrigc *
1270164344Sbrueffer * @retval 0		success
1271164344Sbrueffer */
1272170220Struckmanstatic int
1273170220Struckmandevclass_delete_device(devclass_t dc, device_t dev)
1274164088Smarcel{
1275164088Smarcel	if (!dc || !dev)
1276164088Smarcel		return (0);
1277164088Smarcel
1278163570Sru	PDEBUG(("%s in devclass %s", DEVICENAME(dev), DEVCLANAME(dc)));
1279163570Sru
1280162837Sdelphij	if (dev->devclass != dc || dc->devices[dev->unit] != dev)
1281162837Sdelphij		panic("devclass_delete_device: inconsistent device class");
1282162780Sbms	dc->devices[dev->unit] = NULL;
1283162780Sbms	if (dev->flags & DF_WILDCARD)
1284162780Sbms		dev->unit = -1;
1285162780Sbms	dev->devclass = NULL;
1286162780Sbms	free(dev->nameunit, M_BUS);
1287162780Sbms	dev->nameunit = NULL;
1288162780Sbms
1289162780Sbms	return (0);
1290162780Sbms}
1291162598Ssimon
1292162598Ssimon/**
1293162598Ssimon * @internal
1294162716Sdelphij * @brief Make a new device and add it as a child of @p parent
1295162716Sdelphij *
1296161529Sflz * @param parent	the parent of the new device
1297161529Sflz * @param name		the devclass name of the new device or @c NULL
1298161529Sflz *			to leave the devclass unspecified
1299170192Sru * @parem unit		the unit number of the new device of @c -1 to
1300170192Sru *			leave the unit number unspecified
1301170192Sru *
1302170192Sru * @returns the new device
1303170192Sru */
1304170192Srustatic device_t
1305170192Srumake_device(device_t parent, const char *name, int unit)
1306170192Sru{
1307170192Sru	device_t dev;
1308170192Sru	devclass_t dc;
1309170192Sru
1310170192Sru	PDEBUG(("%s at %s as unit %d", name, DEVICENAME(parent), unit));
1311170192Sru
1312160983Sbrooks	if (name) {
1313160983Sbrooks		dc = devclass_find_internal(name, 0, TRUE);
1314170255Struckman		if (!dc) {
1315170255Struckman			printf("make_device: can't find device class %s\n",
1316170255Struckman			    name);
1317170255Struckman			return (NULL);
1318158687Sphk		}
1319158687Sphk	} else {
1320158687Sphk		dc = NULL;
1321158687Sphk	}
1322158687Sphk
1323158687Sphk	dev = malloc(sizeof(struct device), M_BUS, M_NOWAIT|M_ZERO);
1324158687Sphk	if (!dev)
1325158687Sphk		return (NULL);
1326158687Sphk
1327158687Sphk	dev->parent = parent;
1328158687Sphk	TAILQ_INIT(&dev->children);
1329158687Sphk	kobj_init((kobj_t) dev, &null_class);
1330158687Sphk	dev->driver = NULL;
1331158687Sphk	dev->devclass = NULL;
1332158687Sphk	dev->unit = unit;
1333158687Sphk	dev->nameunit = NULL;
1334158687Sphk	dev->desc = NULL;
1335158687Sphk	dev->busy = 0;
1336158687Sphk	dev->devflags = 0;
1337158687Sphk	dev->flags = DF_ENABLED;
1338158687Sphk	dev->order = 0;
1339158687Sphk	if (unit == -1)
1340158687Sphk		dev->flags |= DF_WILDCARD;
1341158687Sphk	if (name) {
1342158687Sphk		dev->flags |= DF_FIXEDCLASS;
1343158687Sphk		if (devclass_add_device(dc, dev)) {
1344158687Sphk			kobj_delete((kobj_t) dev, M_BUS);
1345158687Sphk			return (NULL);
1346158687Sphk		}
1347158687Sphk	}
1348158687Sphk	dev->ivars = NULL;
1349158687Sphk	dev->softc = NULL;
1350158687Sphk
1351158687Sphk	dev->state = DS_NOTPRESENT;
1352158687Sphk
1353158687Sphk	TAILQ_INSERT_TAIL(&bus_data_devices, dev, devlink);
1354158687Sphk	bus_data_generation_update();
1355158687Sphk
1356158687Sphk	return (dev);
1357158687Sphk}
1358158687Sphk
1359158687Sphk/**
1360158687Sphk * @internal
1361158687Sphk * @brief Print a description of a device.
1362158687Sphk */
1363158687Sphkstatic int
1364158687Sphkdevice_print_child(device_t dev, device_t child)
1365158687Sphk{
1366158687Sphk	int retval = 0;
1367158687Sphk
1368158687Sphk	if (device_is_alive(child))
1369158687Sphk		retval += BUS_PRINT_CHILD(dev, child);
1370158687Sphk	else
1371158618Smaxim		retval += device_printf(child, " not found\n");
1372158618Smaxim
1373158618Smaxim	return (retval);
1374158512Smlaier}
1375158512Smlaier
1376158512Smlaier/**
1377158512Smlaier * @brief Create a new device
1378158512Smlaier *
1379158754Smarcel * This creates a new device and adds it as a child of an existing
1380158754Smarcel * parent device. The new device will be added after the last existing
1381157221Ssimon * child with order zero.
1382157221Ssimon *
1383156676Sharti * @param dev		the device which will be the parent of the
1384156676Sharti *			new child device
1385170190Sru * @param name		devclass name for new device or @c NULL if not
1386170190Sru *			specified
1387170190Sru * @param unit		unit number for new device or @c -1 if not
1388170190Sru *			specified
1389170190Sru *
1390170190Sru * @returns		the new device
1391170190Sru */
1392170190Srudevice_t
1393153662Sjhbdevice_add_child(device_t dev, const char *name, int unit)
1394153662Sjhb{
1395153430Siedowse	return (device_add_child_ordered(dev, 0, name, unit));
1396153430Siedowse}
1397153430Siedowse
1398153430Siedowse/**
1399153430Siedowse * @brief Create a new device
1400151845Syar *
1401151845Syar * This creates a new device and adds it as a child of an existing
1402151271Spjd * parent device. The new device will be added after the last existing
1403151271Spjd * child with the same order.
1404162025Smatusita *
1405162025Smatusita * @param dev		the device which will be the parent of the
1406162025Smatusita *			new child device
1407162025Smatusita * @param order		a value which is used to partially sort the
1408150676Smlaier *			children of @p dev - devices created using
1409150677Smlaier *			lower values of @p order appear first in @p
1410150002Snetchild *			dev's list of children
1411150002Snetchild * @param name		devclass name for new device or @c NULL if not
1412150002Snetchild *			specified
1413150002Snetchild * @param unit		unit number for new device or @c -1 if not
1414149454Sglebius *			specified
1415148808Sru *
1416148808Sru * @returns		the new device
1417148825Snetchild */
1418148825Snetchilddevice_t
1419148356Sdougbdevice_add_child_ordered(device_t dev, int order, const char *name, int unit)
1420148356Sdougb{
1421148572Snetchild	device_t child;
1422170220Struckman	device_t place;
1423170220Struckman
1424170220Struckman	PDEBUG(("%s at %s with order %d as unit %d",
1425170220Struckman	    name, DEVICENAME(dev), order, unit));
1426170220Struckman
1427148330Snetchild	child = make_device(dev, name, unit);
1428148330Snetchild	if (child == NULL)
1429148330Snetchild		return (child);
1430148330Snetchild	child->order = order;
1431148572Snetchild
1432148572Snetchild	TAILQ_FOREACH(place, &dev->children, link) {
1433149105Simp		if (place->order > order)
1434148572Snetchild			break;
1435148572Snetchild	}
1436148572Snetchild
1437172026Syar	if (place) {
1438172026Syar		/*
1439172026Syar		 * The device 'place' is the first device whose order is
1440172026Syar		 * greater than the new child.
1441148572Snetchild		 */
1442148572Snetchild		TAILQ_INSERT_BEFORE(place, child, link);
1443148572Snetchild	} else {
1444148572Snetchild		/*
1445148572Snetchild		 * The new child's order is greater or equal to the order of
1446148572Snetchild		 * any existing device. Add the child to the tail of the list.
1447148572Snetchild		 */
1448148572Snetchild		TAILQ_INSERT_TAIL(&dev->children, child, link);
1449148572Snetchild	}
1450148572Snetchild
1451148572Snetchild	bus_data_generation_update();
1452153939Snetchild	return (child);
1453153939Snetchild}
1454153939Snetchild
1455153939Snetchild/**
1456148330Snetchild * @brief Delete a device
1457148330Snetchild *
1458148423Sdougb * This function deletes a device along with all of its children. If
1459148423Sdougb * the device currently has a driver attached to it, the device is
1460148330Snetchild * detached first using device_detach().
1461148330Snetchild *
1462148330Snetchild * @param dev		the parent device
1463148330Snetchild * @param child		the device to delete
1464148572Snetchild *
1465148572Snetchild * @retval 0		success
1466148353Sdougb * @retval non-zero	a unit error code describing the error
1467148353Sdougb */
1468149105Simpint
1469149105Simpdevice_delete_child(device_t dev, device_t child)
1470148572Snetchild{
1471148572Snetchild	int error;
1472172026Syar	device_t grandchild;
1473149105Simp
1474148572Snetchild	PDEBUG(("%s from %s", DEVICENAME(child), DEVICENAME(dev)));
1475155813Snetchild
1476155813Snetchild	/* remove children first */
1477155813Snetchild	while ( (grandchild = TAILQ_FIRST(&child->children)) ) {
1478155813Snetchild		error = device_delete_child(child, grandchild);
1479148330Snetchild		if (error)
1480148330Snetchild			return (error);
1481148330Snetchild	}
1482163991Strhodes
1483163991Strhodes	if ((error = device_detach(child)) != 0)
1484163991Strhodes		return (error);
1485163991Strhodes	if (child->devclass)
1486163991Strhodes		devclass_delete_device(child->devclass, child);
1487163991Strhodes	TAILQ_REMOVE(&dev->children, child, link);
1488163991Strhodes	TAILQ_REMOVE(&bus_data_devices, child, devlink);
1489163991Strhodes	kobj_delete((kobj_t) child, M_BUS);
1490163991Strhodes
1491163991Strhodes	bus_data_generation_update();
1492163991Strhodes	return (0);
1493148330Snetchild}
1494148330Snetchild
1495148330Snetchild/**
1496148330Snetchild * @brief Find a device given a unit number
1497155813Snetchild *
1498148330Snetchild * This is similar to devclass_get_devices() but only searches for
1499148330Snetchild * devices which have @p dev as a parent.
1500148330Snetchild *
1501148330Snetchild * @param dev		the parent device to search
1502148330Snetchild * @param unit		the unit number to search for
1503148330Snetchild *
1504148543Snetchild * @returns		the device with the given unit number or @c
1505148543Snetchild *			NULL if there is no such device
1506148543Snetchild */
1507148543Snetchilddevice_t
1508148543Snetchilddevice_find_child(device_t dev, const char *classname, int unit)
1509148543Snetchild{
1510148543Snetchild	devclass_t dc;
1511148543Snetchild	device_t child;
1512148543Snetchild
1513148543Snetchild	dc = devclass_find(classname);
1514148543Snetchild	if (!dc)
1515148543Snetchild		return (NULL);
1516148543Snetchild
1517148543Snetchild	child = devclass_get_device(dc, unit);
1518148543Snetchild	if (child && child->parent == dev)
1519148543Snetchild		return (child);
1520148543Snetchild	return (NULL);
1521148543Snetchild}
1522148543Snetchild
1523148543Snetchild/**
1524148543Snetchild * @internal
1525148572Snetchild */
1526148572Snetchildstatic driverlink_t
1527148572Snetchildfirst_matching_driver(devclass_t dc, device_t dev)
1528148572Snetchild{
1529148572Snetchild	if (dev->devclass)
1530148572Snetchild		return (devclass_find_driver_internal(dc, dev->devclass->name));
1531148572Snetchild	return (TAILQ_FIRST(&dc->drivers));
1532148572Snetchild}
1533148572Snetchild
1534148572Snetchild/**
1535148572Snetchild * @internal
1536148572Snetchild */
1537148572Snetchildstatic driverlink_t
1538148572Snetchildnext_matching_driver(devclass_t dc, device_t dev, driverlink_t last)
1539148572Snetchild{
1540148572Snetchild	if (dev->devclass) {
1541148572Snetchild		driverlink_t dl;
1542148572Snetchild		for (dl = TAILQ_NEXT(last, link); dl; dl = TAILQ_NEXT(dl, link))
1543148572Snetchild			if (!strcmp(dev->devclass->name, dl->driver->name))
1544148572Snetchild				return (dl);
1545148572Snetchild		return (NULL);
1546148572Snetchild	}
1547148572Snetchild	return (TAILQ_NEXT(last, link));
1548148572Snetchild}
1549148572Snetchild
1550148572Snetchild/**
1551148572Snetchild * @internal
1552148572Snetchild */
1553148572Snetchildstatic int
1554148572Snetchilddevice_probe_child(device_t dev, device_t child)
1555148572Snetchild{
1556148572Snetchild	devclass_t dc;
1557148572Snetchild	driverlink_t best = 0;
1558148572Snetchild	driverlink_t dl;
1559148572Snetchild	int result, pri = 0;
1560148572Snetchild	int hasclass = (child->devclass != 0);
1561148572Snetchild
1562148572Snetchild	GIANT_REQUIRED;
1563148572Snetchild
1564148572Snetchild	dc = dev->devclass;
1565148572Snetchild	if (!dc)
1566148572Snetchild		panic("device_probe_child: parent device has no devclass");
1567148572Snetchild
1568148572Snetchild	/*
1569148572Snetchild	 * If the state is already probed, then return.  However, don't
1570148572Snetchild	 * return if we can rebid this object.
1571148572Snetchild	 */
1572148572Snetchild	if (child->state == DS_ALIVE && (child->flags & DF_REBID) == 0)
1573148572Snetchild		return (0);
1574148572Snetchild
1575148572Snetchild	for (; dc; dc = dc->parent) {
1576148572Snetchild		for (dl = first_matching_driver(dc, child);
1577148572Snetchild		     dl;
1578148572Snetchild		     dl = next_matching_driver(dc, child, dl)) {
1579148572Snetchild			PDEBUG(("Trying %s", DRIVERNAME(dl->driver)));
1580148572Snetchild			device_set_driver(child, dl->driver);
1581148572Snetchild			if (!hasclass)
1582148572Snetchild				device_set_devclass(child, dl->driver->name);
1583148572Snetchild
1584148572Snetchild			/* Fetch any flags for the device before probing. */
1585148572Snetchild			resource_int_value(dl->driver->name, child->unit,
1586148572Snetchild			    "flags", &child->devflags);
1587148572Snetchild
1588148572Snetchild			result = DEVICE_PROBE(child);
1589148572Snetchild
1590148572Snetchild			/* Reset flags and devclass before the next probe. */
1591148572Snetchild			child->devflags = 0;
1592148572Snetchild			if (!hasclass)
1593148572Snetchild				device_set_devclass(child, 0);
1594148572Snetchild
1595148572Snetchild			/*
1596148572Snetchild			 * If the driver returns SUCCESS, there can be
1597148572Snetchild			 * no higher match for this device.
1598148572Snetchild			 */
1599148572Snetchild			if (result == 0) {
1600148572Snetchild				best = dl;
1601148572Snetchild				pri = 0;
1602148572Snetchild				break;
1603148572Snetchild			}
1604148572Snetchild
1605148572Snetchild			/*
1606148572Snetchild			 * The driver returned an error so it
1607148572Snetchild			 * certainly doesn't match.
1608148572Snetchild			 */
1609148572Snetchild			if (result > 0) {
1610148572Snetchild				device_set_driver(child, 0);
1611148572Snetchild				continue;
1612148572Snetchild			}
1613148572Snetchild
1614148572Snetchild			/*
1615148572Snetchild			 * A priority lower than SUCCESS, remember the
1616148572Snetchild			 * best matching driver. Initialise the value
1617148572Snetchild			 * of pri for the first match.
1618148572Snetchild			 */
1619148572Snetchild			if (best == 0 || result > pri) {
1620148572Snetchild				best = dl;
1621148572Snetchild				pri = result;
1622148572Snetchild				continue;
1623148572Snetchild			}
1624148572Snetchild		}
1625148572Snetchild		/*
1626148572Snetchild		 * If we have an unambiguous match in this devclass,
1627148572Snetchild		 * don't look in the parent.
1628148572Snetchild		 */
1629148572Snetchild		if (best && pri == 0)
1630148572Snetchild			break;
1631148572Snetchild	}
1632148572Snetchild
1633148330Snetchild	/*
1634148330Snetchild	 * If we found a driver, change state and initialise the devclass.
1635148330Snetchild	 */
1636148330Snetchild	/* XXX What happens if we rebid and got no best? */
1637148330Snetchild	if (best) {
1638190613Strhodes		/*
1639190613Strhodes		 * If this device was atached, and we were asked to
1640148572Snetchild		 * rescan, and it is a different driver, then we have
1641148572Snetchild		 * to detach the old driver and reattach this new one.
1642148572Snetchild		 * Note, we don't have to check for DF_REBID here
1643148572Snetchild		 * because if the state is > DS_ALIVE, we know it must
1644148572Snetchild		 * be.
1645148572Snetchild		 *
1646177625Sremko		 * This assumes that all DF_REBID drivers can have
1647177625Sremko		 * their probe routine called at any time and that
1648177625Sremko		 * they are idempotent as well as completely benign in
1649148572Snetchild		 * normal operations.
1650148572Snetchild		 *
1651148572Snetchild		 * We also have to make sure that the detach
1652148572Snetchild		 * succeeded, otherwise we fail the operation (or
1653149113Simp		 * maybe it should just fail silently?  I'm torn).
1654149113Simp		 */
1655149113Simp		if (child->state > DS_ALIVE && best->driver != child->driver)
1656149113Simp			if ((result = device_detach(dev)) != 0)
1657149113Simp				return (result);
1658149113Simp
1659149113Simp		/* Set the winning driver, devclass, and flags. */
1660148572Snetchild		if (!child->devclass)
1661148572Snetchild			device_set_devclass(child, best->driver->name);
1662148572Snetchild		device_set_driver(child, best->driver);
1663148572Snetchild		resource_int_value(best->driver->name, child->unit,
1664148572Snetchild		    "flags", &child->devflags);
1665149105Simp
1666148572Snetchild		if (pri < 0) {
1667148572Snetchild			/*
1668148572Snetchild			 * A bit bogus. Call the probe method again to make
1669148572Snetchild			 * sure that we have the right description.
1670148572Snetchild			 */
1671148572Snetchild			DEVICE_PROBE(child);
1672148572Snetchild#if 0
1673148572Snetchild			child->flags |= DF_REBID;
1674170220Struckman#endif
1675170220Struckman		} else
1676156385Syar			child->flags &= ~DF_REBID;
1677156385Syar		child->state = DS_ALIVE;
1678148330Snetchild
1679148330Snetchild		bus_data_generation_update();
1680148330Snetchild		return (0);
1681148330Snetchild	}
1682148330Snetchild
1683148330Snetchild	return (ENXIO);
1684148330Snetchild}
1685148330Snetchild
1686148330Snetchild/**
1687148330Snetchild * @brief Return the parent of a device
1688148330Snetchild */
1689148330Snetchilddevice_t
1690148330Snetchilddevice_get_parent(device_t dev)
1691148330Snetchild{
1692148330Snetchild	return (dev->parent);
1693148330Snetchild}
1694148330Snetchild
1695148330Snetchild/**
1696148330Snetchild * @brief Get a list of children of a device
1697148330Snetchild *
1698148330Snetchild * An array containing a list of all the children of the given device
1699148572Snetchild * is allocated and returned in @p *devlistp. The number of devices
1700148572Snetchild * in the array is returned in @p *devcountp. The caller should free
1701149105Simp * the array using @c free(p, M_TEMP).
1702148572Snetchild *
1703148572Snetchild * @param dev		the device to examine
1704148572Snetchild * @param devlistp	points at location for array pointer return
1705148572Snetchild *			value
1706148572Snetchild * @param devcountp	points at location for array size return value
1707148572Snetchild *
1708148572Snetchild * @retval 0		success
1709155279Savatar * @retval ENOMEM	the array allocation failed
1710155279Savatar */
1711155279Savatarint
1712155279Savatardevice_get_children(device_t dev, device_t **devlistp, int *devcountp)
1713148572Snetchild{
1714148572Snetchild	int count;
1715148572Snetchild	device_t child;
1716148330Snetchild	device_t *list;
1717148330Snetchild
1718148330Snetchild	count = 0;
1719148330Snetchild	TAILQ_FOREACH(child, &dev->children, link) {
1720148330Snetchild		count++;
1721148330Snetchild	}
1722148330Snetchild
1723148330Snetchild	list = malloc(count * sizeof(device_t), M_TEMP, M_NOWAIT|M_ZERO);
1724148330Snetchild	if (!list)
1725148330Snetchild		return (ENOMEM);
1726148330Snetchild
1727148330Snetchild	count = 0;
1728148330Snetchild	TAILQ_FOREACH(child, &dev->children, link) {
1729148330Snetchild		list[count] = child;
1730148330Snetchild		count++;
1731148330Snetchild	}
1732149105Simp
1733149105Simp	*devlistp = list;
1734148572Snetchild	*devcountp = count;
1735170219Struckman
1736148572Snetchild	return (0);
1737148572Snetchild}
1738148572Snetchild
1739148330Snetchild/**
1740148330Snetchild * @brief Return the current driver for the device or @c NULL if there
1741148330Snetchild * is no driver currently attached
1742148330Snetchild */
1743148330Snetchilddriver_t *
1744148330Snetchilddevice_get_driver(device_t dev)
1745148330Snetchild{
1746148330Snetchild	return (dev->driver);
1747148330Snetchild}
1748148330Snetchild
1749148330Snetchild/**
1750148330Snetchild * @brief Return the current devclass for the device or @c NULL if
1751148330Snetchild * there is none.
1752148330Snetchild */
1753148330Snetchilddevclass_t
1754148330Snetchilddevice_get_devclass(device_t dev)
1755148330Snetchild{
1756148330Snetchild	return (dev->devclass);
1757148330Snetchild}
1758148330Snetchild
1759148330Snetchild/**
1760148330Snetchild * @brief Return the name of the device's devclass or @c NULL if there
1761148330Snetchild * is none.
1762148572Snetchild */
1763148572Snetchildconst char *
1764148572Snetchilddevice_get_name(device_t dev)
1765148572Snetchild{
1766148572Snetchild	if (dev != NULL && dev->devclass)
1767148572Snetchild		return (devclass_get_name(dev->devclass));
1768148572Snetchild	return (NULL);
1769148572Snetchild}
1770148572Snetchild
1771148572Snetchild/**
1772148572Snetchild * @brief Return a string containing the device's devclass name
1773148572Snetchild * followed by an ascii representation of the device's unit number
1774148572Snetchild * (e.g. @c "foo2").
1775148572Snetchild */
1776148572Snetchildconst char *
1777148572Snetchilddevice_get_nameunit(device_t dev)
1778148572Snetchild{
1779148572Snetchild	return (dev->nameunit);
1780148572Snetchild}
1781148572Snetchild
1782148572Snetchild/**
1783148572Snetchild * @brief Return the device's unit number.
1784148572Snetchild */
1785148572Snetchildint
1786148572Snetchilddevice_get_unit(device_t dev)
1787148572Snetchild{
1788148572Snetchild	return (dev->unit);
1789148572Snetchild}
1790148572Snetchild
1791148572Snetchild/**
1792148572Snetchild * @brief Return the device's description string
1793148572Snetchild */
1794148572Snetchildconst char *
1795148572Snetchilddevice_get_desc(device_t dev)
1796148572Snetchild{
1797148572Snetchild	return (dev->desc);
1798148572Snetchild}
1799148572Snetchild
1800148572Snetchild/**
1801148572Snetchild * @brief Return the device's flags
1802148572Snetchild */
1803148572Snetchildu_int32_t
1804148572Snetchilddevice_get_flags(device_t dev)
1805148572Snetchild{
1806148572Snetchild	return (dev->devflags);
1807148572Snetchild}
1808148572Snetchild
1809148572Snetchildstruct sysctl_ctx_list *
1810148572Snetchilddevice_get_sysctl_ctx(device_t dev)
1811148572Snetchild{
1812148572Snetchild	return (&dev->sysctl_ctx);
1813148572Snetchild}
1814148572Snetchild
1815148572Snetchildstruct sysctl_oid *
1816148572Snetchilddevice_get_sysctl_tree(device_t dev)
1817148572Snetchild{
1818148572Snetchild	return (dev->sysctl_tree);
1819148572Snetchild}
1820148572Snetchild
1821148572Snetchild/**
1822148572Snetchild * @brief Print the name of the device followed by a colon and a space
1823148572Snetchild *
1824148572Snetchild * @returns the number of characters printed
1825148572Snetchild */
1826148572Snetchildint
1827148572Snetchilddevice_print_prettyname(device_t dev)
1828148572Snetchild{
1829148572Snetchild	const char *name = device_get_name(dev);
1830148572Snetchild
1831148572Snetchild	if (name == 0)
1832148572Snetchild		return (printf("unknown: "));
1833148572Snetchild	return (printf("%s%d: ", name, device_get_unit(dev)));
1834148572Snetchild}
1835148572Snetchild
1836148572Snetchild/**
1837148572Snetchild * @brief Print the name of the device followed by a colon, a space
1838148572Snetchild * and the result of calling vprintf() with the value of @p fmt and
1839148572Snetchild * the following arguments.
1840148572Snetchild *
1841148572Snetchild * @returns the number of characters printed
1842148572Snetchild */
1843148572Snetchildint
1844148572Snetchilddevice_printf(device_t dev, const char * fmt, ...)
1845148572Snetchild{
1846148572Snetchild	va_list ap;
1847148572Snetchild	int retval;
1848148572Snetchild
1849148572Snetchild	retval = device_print_prettyname(dev);
1850148572Snetchild	va_start(ap, fmt);
1851148572Snetchild	retval += vprintf(fmt, ap);
1852148572Snetchild	va_end(ap);
1853148572Snetchild	return (retval);
1854148572Snetchild}
1855148572Snetchild
1856148572Snetchild/**
1857148572Snetchild * @internal
1858148572Snetchild */
1859148572Snetchildstatic void
1860148572Snetchilddevice_set_desc_internal(device_t dev, const char* desc, int copy)
1861149105Simp{
1862149105Simp	if (dev->desc && (dev->flags & DF_DESCMALLOCED)) {
1863149105Simp		free(dev->desc, M_BUS);
1864149105Simp		dev->flags &= ~DF_DESCMALLOCED;
1865148572Snetchild		dev->desc = NULL;
1866164619Snetchild	}
1867164619Snetchild
1868148572Snetchild	if (copy && desc) {
1869148572Snetchild		dev->desc = malloc(strlen(desc) + 1, M_BUS, M_NOWAIT);
1870148572Snetchild		if (dev->desc) {
1871148572Snetchild			strcpy(dev->desc, desc);
1872148572Snetchild			dev->flags |= DF_DESCMALLOCED;
1873148572Snetchild		}
1874148572Snetchild	} else {
1875148572Snetchild		/* Avoid a -Wcast-qual warning */
1876148572Snetchild		dev->desc = (char *)(uintptr_t) desc;
1877148572Snetchild	}
1878148572Snetchild
1879148572Snetchild	bus_data_generation_update();
1880148572Snetchild}
1881148572Snetchild
1882148572Snetchild/**
1883148572Snetchild * @brief Set the device's description
1884148572Snetchild *
1885148572Snetchild * The value of @c desc should be a string constant that will not
1886148572Snetchild * change (at least until the description is changed in a subsequent
1887148572Snetchild * call to device_set_desc() or device_set_desc_copy()).
1888148572Snetchild */
1889148572Snetchildvoid
1890148572Snetchilddevice_set_desc(device_t dev, const char* desc)
1891148572Snetchild{
1892148572Snetchild	device_set_desc_internal(dev, desc, FALSE);
1893148572Snetchild}
1894148572Snetchild
1895148572Snetchild/**
1896148572Snetchild * @brief Set the device's description
1897148572Snetchild *
1898148572Snetchild * The string pointed to by @c desc is copied. Use this function if
1899148572Snetchild * the device description is generated, (e.g. with sprintf()).
1900148572Snetchild */
1901148572Snetchildvoid
1902148572Snetchilddevice_set_desc_copy(device_t dev, const char* desc)
1903148572Snetchild{
1904148572Snetchild	device_set_desc_internal(dev, desc, TRUE);
1905148572Snetchild}
1906148572Snetchild
1907148572Snetchild/**
1908148572Snetchild * @brief Set the device's flags
1909148572Snetchild */
1910148572Snetchildvoid
1911148572Snetchilddevice_set_flags(device_t dev, u_int32_t flags)
1912148572Snetchild{
1913148572Snetchild	dev->devflags = flags;
1914148572Snetchild}
1915148572Snetchild
1916148572Snetchild/**
1917148572Snetchild * @brief Return the device's softc field
1918148572Snetchild *
1919148572Snetchild * The softc is allocated and zeroed when a driver is attached, based
1920148572Snetchild * on the size field of the driver.
1921148572Snetchild */
1922148572Snetchildvoid *
1923148572Snetchilddevice_get_softc(device_t dev)
1924148572Snetchild{
1925148572Snetchild	return (dev->softc);
1926149105Simp}
1927149105Simp
1928149105Simp/**
1929149105Simp * @brief Set the device's softc field
1930149105Simp *
1931149105Simp * Most drivers do not need to use this since the softc is allocated
1932149105Simp * automatically when the driver is attached.
1933149105Simp */
1934148572Snetchildvoid
1935148572Snetchilddevice_set_softc(device_t dev, void *softc)
1936160165Savatar{
1937160165Savatar	if (dev->softc && !(dev->flags & DF_EXTERNALSOFTC))
1938148330Snetchild		free(dev->softc, M_BUS_SC);
1939148330Snetchild	dev->softc = softc;
1940148330Snetchild	if (dev->softc)
1941149105Simp		dev->flags |= DF_EXTERNALSOFTC;
1942149105Simp	else
1943188941Sraj		dev->flags &= ~DF_EXTERNALSOFTC;
1944149105Simp}
1945163831Sjmg
1946149105Simp/**
1947149105Simp * @brief Get the device's ivars field
1948149105Simp *
1949149105Simp * The ivars field is used by the parent device to store per-device
1950149105Simp * state (e.g. the physical location of the device or a list of
1951149105Simp * resources).
1952149105Simp */
1953149105Simpvoid *
1954149105Simpdevice_get_ivars(device_t dev)
1955149105Simp{
1956149105Simp
1957149105Simp	KASSERT(dev != NULL, ("device_get_ivars(NULL, ...)"));
1958149105Simp	return (dev->ivars);
1959149105Simp}
1960149105Simp
1961149105Simp/**
1962149105Simp * @brief Set the device's ivars field
1963149105Simp */
1964149105Simpvoid
1965149105Simpdevice_set_ivars(device_t dev, void * ivars)
1966149105Simp{
1967149105Simp
1968160165Savatar	KASSERT(dev != NULL, ("device_set_ivars(NULL, ...)"));
1969160165Savatar	dev->ivars = ivars;
1970160165Savatar}
1971148330Snetchild
1972148330Snetchild/**
1973148330Snetchild * @brief Return the device's state
1974148330Snetchild */
1975148330Snetchilddevice_state_t
1976149105Simpdevice_get_state(device_t dev)
1977149105Simp{
1978149105Simp	return (dev->state);
1979149105Simp}
1980149105Simp
1981148330Snetchild/**
1982149105Simp * @brief Set the DF_ENABLED flag for the device
1983149105Simp */
1984149105Simpvoid
1985149105Simpdevice_enable(device_t dev)
1986149105Simp{
1987149105Simp	dev->flags |= DF_ENABLED;
1988149105Simp}
1989149105Simp
1990149105Simp/**
1991149105Simp * @brief Clear the DF_ENABLED flag for the device
1992149105Simp */
1993149105Simpvoid
1994149105Simpdevice_disable(device_t dev)
1995164971Savatar{
1996164971Savatar	dev->flags &= ~DF_ENABLED;
1997164971Savatar}
1998164971Savatar
1999164971Savatar/**
2000164971Savatar * @brief Increment the busy counter for the device
2001164971Savatar */
2002164971Savatarvoid
2003164971Savatardevice_busy(device_t dev)
2004164971Savatar{
2005164971Savatar	if (dev->state < DS_ATTACHED)
2006164971Savatar		panic("device_busy: called for unattached device");
2007164971Savatar	if (dev->busy == 0 && dev->parent)
2008164971Savatar		device_busy(dev->parent);
2009164971Savatar	dev->busy++;
2010164971Savatar	dev->state = DS_BUSY;
2011164971Savatar}
2012164971Savatar
2013164971Savatar/**
2014164971Savatar * @brief Decrement the busy counter for the device
2015164971Savatar */
2016164971Savatarvoid
2017164971Savatardevice_unbusy(device_t dev)
2018164971Savatar{
2019164971Savatar	if (dev->state != DS_BUSY)
2020160165Savatar		panic("device_unbusy: called for non-busy device %s",
2021160165Savatar		    device_get_nameunit(dev));
2022160165Savatar	dev->busy--;
2023148330Snetchild	if (dev->busy == 0) {
2024148330Snetchild		if (dev->parent)
2025148330Snetchild			device_unbusy(dev->parent);
2026148330Snetchild		dev->state = DS_ATTACHED;
2027149105Simp	}
2028149105Simp}
2029149105Simp
2030164302Smatteo/**
2031164302Smatteo * @brief Set the DF_QUIET flag for the device
2032148330Snetchild */
2033148330Snetchildvoid
2034148330Snetchilddevice_quiet(device_t dev)
2035148330Snetchild{
2036148330Snetchild	dev->flags |= DF_QUIET;
2037148330Snetchild}
2038148330Snetchild
2039148330Snetchild/**
2040148330Snetchild * @brief Clear the DF_QUIET flag for the device
2041148330Snetchild */
2042148330Snetchildvoid
2043148330Snetchilddevice_verbose(device_t dev)
2044148330Snetchild{
2045148330Snetchild	dev->flags &= ~DF_QUIET;
2046148330Snetchild}
2047148330Snetchild
2048148543Snetchild/**
2049149113Simp * @brief Return non-zero if the DF_QUIET flag is set on the device
2050149113Simp */
2051149113Simpint
2052149113Simpdevice_is_quiet(device_t dev)
2053149113Simp{
2054149113Simp	return ((dev->flags & DF_QUIET) != 0);
2055149113Simp}
2056149113Simp
2057149113Simp/**
2058149113Simp * @brief Return non-zero if the DF_ENABLED flag is set on the device
2059149113Simp */
2060148330Snetchildint
2061148330Snetchilddevice_is_enabled(device_t dev)
2062149113Simp{
2063149113Simp	return ((dev->flags & DF_ENABLED) != 0);
2064149113Simp}
2065149113Simp
2066149113Simp/**
2067149113Simp * @brief Return non-zero if the device was successfully probed
2068149113Simp */
2069149113Simpint
2070149113Simpdevice_is_alive(device_t dev)
2071149113Simp{
2072149113Simp	return (dev->state >= DS_ALIVE);
2073149113Simp}
2074149113Simp
2075149113Simp/**
2076149113Simp * @brief Return non-zero if the device currently has a driver
2077149113Simp * attached to it
2078149113Simp */
2079149113Simpint
2080149113Simpdevice_is_attached(device_t dev)
2081149113Simp{
2082149113Simp	return (dev->state >= DS_ATTACHED);
2083149113Simp}
2084149113Simp
2085149113Simp/**
2086149113Simp * @brief Set the devclass of a device
2087149113Simp * @see devclass_add_device().
2088149113Simp */
2089149113Simpint
2090149113Simpdevice_set_devclass(device_t dev, const char *classname)
2091149113Simp{
2092149113Simp	devclass_t dc;
2093149113Simp	int error;
2094148330Snetchild
2095148330Snetchild	if (!classname) {
2096148330Snetchild		if (dev->devclass)
2097148330Snetchild			devclass_delete_device(dev->devclass, dev);
2098148330Snetchild		return (0);
2099148330Snetchild	}
2100148330Snetchild
2101151378Snetchild	if (dev->devclass) {
2102151378Snetchild		printf("device_set_devclass: device class already set\n");
2103151378Snetchild		return (EINVAL);
2104151378Snetchild	}
2105151378Snetchild
2106151378Snetchild	dc = devclass_find_internal(classname, 0, TRUE);
2107151378Snetchild	if (!dc)
2108151378Snetchild		return (ENOMEM);
2109151378Snetchild
2110151378Snetchild	error = devclass_add_device(dc, dev);
2111161201Snetchild
2112151378Snetchild	bus_data_generation_update();
2113151378Snetchild	return (error);
2114151378Snetchild}
2115151378Snetchild
2116151378Snetchild/**
2117151378Snetchild * @brief Set the driver of a device
2118151378Snetchild *
2119151378Snetchild * @retval 0		success
2120151378Snetchild * @retval EBUSY	the device already has a driver attached
2121151378Snetchild * @retval ENOMEM	a memory allocation failure occurred
2122151378Snetchild */
2123151378Snetchildint
2124151378Snetchilddevice_set_driver(device_t dev, driver_t *driver)
2125151378Snetchild{
2126151378Snetchild	if (dev->state >= DS_ATTACHED)
2127151378Snetchild		return (EBUSY);
2128151378Snetchild
2129151378Snetchild	if (dev->driver == driver)
2130151378Snetchild		return (0);
2131151378Snetchild
2132151378Snetchild	if (dev->softc && !(dev->flags & DF_EXTERNALSOFTC)) {
2133151378Snetchild		free(dev->softc, M_BUS_SC);
2134151378Snetchild		dev->softc = NULL;
2135151378Snetchild	}
2136151378Snetchild	kobj_delete((kobj_t) dev, 0);
2137151378Snetchild	dev->driver = driver;
2138151378Snetchild	if (driver) {
2139151378Snetchild		kobj_init((kobj_t) dev, (kobj_class_t) driver);
2140151378Snetchild		if (!(dev->flags & DF_EXTERNALSOFTC) && driver->size > 0) {
2141151378Snetchild			dev->softc = malloc(driver->size, M_BUS_SC,
2142151378Snetchild			    M_NOWAIT | M_ZERO);
2143151378Snetchild			if (!dev->softc) {
2144151378Snetchild				kobj_delete((kobj_t) dev, 0);
2145151378Snetchild				kobj_init((kobj_t) dev, &null_class);
2146151378Snetchild				dev->driver = NULL;
2147151378Snetchild				return (ENOMEM);
2148151378Snetchild			}
2149151378Snetchild		}
2150151378Snetchild	} else {
2151151378Snetchild		kobj_init((kobj_t) dev, &null_class);
2152151378Snetchild	}
2153151378Snetchild
2154151378Snetchild	bus_data_generation_update();
2155151378Snetchild	return (0);
2156151378Snetchild}
2157151378Snetchild
2158151378Snetchild/**
2159151378Snetchild * @brief Probe a device and attach a driver if possible
2160151378Snetchild *
2161151378Snetchild * This function is the core of the device autoconfiguration
2162151378Snetchild * system. Its purpose is to select a suitable driver for a device and
2163151378Snetchild * then call that driver to initialise the hardware appropriately. The
2164151378Snetchild * driver is selected by calling the DEVICE_PROBE() method of a set of
2165151378Snetchild * candidate drivers and then choosing the driver which returned the
2166151378Snetchild * best value. This driver is then attached to the device using
2167151378Snetchild * device_attach().
2168151378Snetchild *
2169151378Snetchild * The set of suitable drivers is taken from the list of drivers in
2170151378Snetchild * the parent device's devclass. If the device was originally created
2171151378Snetchild * with a specific class name (see device_add_child()), only drivers
2172151378Snetchild * with that name are probed, otherwise all drivers in the devclass
2173151378Snetchild * are probed. If no drivers return successful probe values in the
2174151378Snetchild * parent devclass, the search continues in the parent of that
2175151378Snetchild * devclass (see devclass_get_parent()) if any.
2176151378Snetchild *
2177151378Snetchild * @param dev		the device to initialise
2178151378Snetchild *
2179151378Snetchild * @retval 0		success
2180151378Snetchild * @retval ENXIO	no driver was found
2181151378Snetchild * @retval ENOMEM	memory allocation failure
2182151378Snetchild * @retval non-zero	some other unix error code
2183151378Snetchild */
2184151378Snetchildint
2185151378Snetchilddevice_probe_and_attach(device_t dev)
2186151378Snetchild{
2187151378Snetchild	int error;
2188151378Snetchild
2189151378Snetchild	GIANT_REQUIRED;
2190151378Snetchild
2191151378Snetchild	if (dev->state >= DS_ALIVE && (dev->flags & DF_REBID) == 0)
2192151378Snetchild		return (0);
2193151378Snetchild
2194151378Snetchild	if (!(dev->flags & DF_ENABLED)) {
2195151378Snetchild		if (bootverbose && device_get_name(dev) != NULL) {
2196151378Snetchild			device_print_prettyname(dev);
2197151378Snetchild			printf("not probed (disabled)\n");
2198151378Snetchild		}
2199151378Snetchild		return (0);
2200151378Snetchild	}
2201151378Snetchild	if ((error = device_probe_child(dev->parent, dev)) != 0) {
2202151378Snetchild		if (!(dev->flags & DF_DONENOMATCH)) {
2203151378Snetchild			BUS_PROBE_NOMATCH(dev->parent, dev);
2204151378Snetchild			devnomatch(dev);
2205151378Snetchild			dev->flags |= DF_DONENOMATCH;
2206151378Snetchild		}
2207151378Snetchild		return (error);
2208151378Snetchild	}
2209151378Snetchild	error = device_attach(dev);
2210151378Snetchild
2211151378Snetchild	return (error);
2212151378Snetchild}
2213151378Snetchild
2214151378Snetchild/**
2215151378Snetchild * @brief Attach a device driver to a device
2216151378Snetchild *
2217151378Snetchild * This function is a wrapper around the DEVICE_ATTACH() driver
2218151378Snetchild * method. In addition to calling DEVICE_ATTACH(), it initialises the
2219151378Snetchild * device's sysctl tree, optionally prints a description of the device
2220151378Snetchild * and queues a notification event for user-based device management
2221151378Snetchild * services.
2222151378Snetchild *
2223151378Snetchild * Normally this function is only called internally from
2224151378Snetchild * device_probe_and_attach().
2225151378Snetchild *
2226151378Snetchild * @param dev		the device to initialise
2227151378Snetchild *
2228151378Snetchild * @retval 0		success
2229151378Snetchild * @retval ENXIO	no driver was found
2230151378Snetchild * @retval ENOMEM	memory allocation failure
2231151378Snetchild * @retval non-zero	some other unix error code
2232151378Snetchild */
2233151378Snetchildint
2234151378Snetchilddevice_attach(device_t dev)
2235151378Snetchild{
2236151378Snetchild	int error;
2237151378Snetchild
2238151378Snetchild	device_sysctl_init(dev);
2239151378Snetchild	if (!device_is_quiet(dev))
2240151378Snetchild		device_print_child(dev->parent, dev);
2241151378Snetchild	if ((error = DEVICE_ATTACH(dev)) != 0) {
2242151378Snetchild		printf("device_attach: %s%d attach returned %d\n",
2243151378Snetchild		    dev->driver->name, dev->unit, error);
2244151378Snetchild		/* Unset the class; set in device_probe_child */
2245151378Snetchild		if (dev->devclass == 0)
2246151378Snetchild			device_set_devclass(dev, 0);
2247151378Snetchild		device_set_driver(dev, NULL);
2248151378Snetchild		device_sysctl_fini(dev);
2249151378Snetchild		dev->state = DS_NOTPRESENT;
2250151378Snetchild		return (error);
2251151378Snetchild	}
2252151378Snetchild	dev->state = DS_ATTACHED;
2253151378Snetchild	devadded(dev);
2254151378Snetchild	return (0);
2255151378Snetchild}
2256151378Snetchild
2257151378Snetchild/**
2258151378Snetchild * @brief Detach a driver from a device
2259151378Snetchild *
2260151378Snetchild * This function is a wrapper around the DEVICE_DETACH() driver
2261151378Snetchild * method. If the call to DEVICE_DETACH() succeeds, it calls
2262151378Snetchild * BUS_CHILD_DETACHED() for the parent of @p dev, queues a
2263151378Snetchild * notification event for user-based device management services and
2264151378Snetchild * cleans up the device's sysctl tree.
2265151378Snetchild *
2266151378Snetchild * @param dev		the device to un-initialise
2267151378Snetchild *
2268151378Snetchild * @retval 0		success
2269151378Snetchild * @retval ENXIO	no driver was found
2270151378Snetchild * @retval ENOMEM	memory allocation failure
2271151378Snetchild * @retval non-zero	some other unix error code
2272151378Snetchild */
2273151378Snetchildint
2274151378Snetchilddevice_detach(device_t dev)
2275151378Snetchild{
2276151378Snetchild	int error;
2277151378Snetchild
2278151378Snetchild	GIANT_REQUIRED;
2279151378Snetchild
2280151378Snetchild	PDEBUG(("%s", DEVICENAME(dev)));
2281151378Snetchild	if (dev->state == DS_BUSY)
2282151378Snetchild		return (EBUSY);
2283151378Snetchild	if (dev->state != DS_ATTACHED)
2284151378Snetchild		return (0);
2285151378Snetchild
2286151378Snetchild	if ((error = DEVICE_DETACH(dev)) != 0)
2287151378Snetchild		return (error);
2288151378Snetchild	devremoved(dev);
2289151378Snetchild	device_printf(dev, "detached\n");
2290151378Snetchild	if (dev->parent)
2291151378Snetchild		BUS_CHILD_DETACHED(dev->parent, dev);
2292151378Snetchild
2293151378Snetchild	if (!(dev->flags & DF_FIXEDCLASS))
2294151378Snetchild		devclass_delete_device(dev->devclass, dev);
2295151378Snetchild
2296151378Snetchild	dev->state = DS_NOTPRESENT;
2297151378Snetchild	device_set_driver(dev, NULL);
2298151378Snetchild	device_set_desc(dev, NULL);
2299151378Snetchild	device_sysctl_fini(dev);
2300151378Snetchild
2301151378Snetchild	return (0);
2302151378Snetchild}
2303151378Snetchild
2304151378Snetchild/**
2305151378Snetchild * @brief Notify a device of system shutdown
2306151378Snetchild *
2307151378Snetchild * This function calls the DEVICE_SHUTDOWN() driver method if the
2308151378Snetchild * device currently has an attached driver.
2309151378Snetchild *
2310151378Snetchild * @returns the value returned by DEVICE_SHUTDOWN()
2311151378Snetchild */
2312151378Snetchildint
2313151378Snetchilddevice_shutdown(device_t dev)
2314151378Snetchild{
2315151378Snetchild	if (dev->state < DS_ATTACHED)
2316151378Snetchild		return (0);
2317151378Snetchild	return (DEVICE_SHUTDOWN(dev));
2318151378Snetchild}
2319151378Snetchild
2320151378Snetchild/**
2321151378Snetchild * @brief Set the unit number of a device
2322151378Snetchild *
2323151378Snetchild * This function can be used to override the unit number used for a
2324151378Snetchild * device (e.g. to wire a device to a pre-configured unit number).
2325151378Snetchild */
2326151378Snetchildint
2327151378Snetchilddevice_set_unit(device_t dev, int unit)
2328151378Snetchild{
2329151378Snetchild	devclass_t dc;
2330151378Snetchild	int err;
2331151378Snetchild
2332151378Snetchild	dc = device_get_devclass(dev);
2333151378Snetchild	if (unit < dc->maxunit && dc->devices[unit])
2334151378Snetchild		return (EBUSY);
2335151378Snetchild	err = devclass_delete_device(dc, dev);
2336151378Snetchild	if (err)
2337151378Snetchild		return (err);
2338151378Snetchild	dev->unit = unit;
2339151378Snetchild	err = devclass_add_device(dc, dev);
2340151378Snetchild	if (err)
2341151378Snetchild		return (err);
2342151378Snetchild
2343151378Snetchild	bus_data_generation_update();
2344151378Snetchild	return (0);
2345151378Snetchild}
2346151378Snetchild
2347151378Snetchild/*======================================*/
2348151378Snetchild/*
2349151378Snetchild * Some useful method implementations to make life easier for bus drivers.
2350151378Snetchild */
2351151378Snetchild
2352151378Snetchild/**
2353151378Snetchild * @brief Initialise a resource list.
2354151378Snetchild *
2355151378Snetchild * @param rl		the resource list to initialise
2356151378Snetchild */
2357151378Snetchildvoid
2358151378Snetchildresource_list_init(struct resource_list *rl)
2359151378Snetchild{
2360151378Snetchild	SLIST_INIT(rl);
2361151378Snetchild}
2362151378Snetchild
2363151378Snetchild/**
2364151378Snetchild * @brief Reclaim memory used by a resource list.
2365151378Snetchild *
2366151378Snetchild * This function frees the memory for all resource entries on the list
2367151378Snetchild * (if any).
2368151378Snetchild *
2369151378Snetchild * @param rl		the resource list to free
2370151378Snetchild */
2371151378Snetchildvoid
2372151378Snetchildresource_list_free(struct resource_list *rl)
2373151378Snetchild{
2374151378Snetchild	struct resource_list_entry *rle;
2375151378Snetchild
2376151378Snetchild	while ((rle = SLIST_FIRST(rl)) != NULL) {
2377151378Snetchild		if (rle->res)
2378151378Snetchild			panic("resource_list_free: resource entry is busy");
2379151378Snetchild		SLIST_REMOVE_HEAD(rl, link);
2380151378Snetchild		free(rle, M_BUS);
2381151378Snetchild	}
2382151378Snetchild}
2383151378Snetchild
2384151378Snetchild/**
2385151378Snetchild * @brief Add a resource entry.
2386151378Snetchild *
2387151378Snetchild * This function adds a resource entry using the given @p type, @p
2388151378Snetchild * start, @p end and @p count values. A rid value is chosen by
2389151378Snetchild * searching sequentially for the first unused rid starting at zero.
2390151378Snetchild *
2391151378Snetchild * @param rl		the resource list to edit
2392151378Snetchild * @param type		the resource entry type (e.g. SYS_RES_MEMORY)
2393151378Snetchild * @param start		the start address of the resource
2394151378Snetchild * @param end		the end address of the resource
2395151378Snetchild * @param count		XXX end-start+1
2396151378Snetchild */
2397151378Snetchildint
2398151378Snetchildresource_list_add_next(struct resource_list *rl, int type, u_long start,
2399151378Snetchild    u_long end, u_long count)
2400151378Snetchild{
2401151378Snetchild	int rid;
2402151378Snetchild
2403151378Snetchild	rid = 0;
2404151378Snetchild	while (resource_list_find(rl, type, rid) != NULL)
2405151378Snetchild		rid++;
2406151378Snetchild	resource_list_add(rl, type, rid, start, end, count);
2407151378Snetchild	return (rid);
2408151378Snetchild}
2409151378Snetchild
2410151378Snetchild/**
2411151378Snetchild * @brief Add or modify a resource entry.
2412151378Snetchild *
2413151378Snetchild * If an existing entry exists with the same type and rid, it will be
2414151378Snetchild * modified using the given values of @p start, @p end and @p
2415151378Snetchild * count. If no entry exists, a new one will be created using the
2416151378Snetchild * given values.
2417151378Snetchild *
2418151378Snetchild * @param rl		the resource list to edit
2419151378Snetchild * @param type		the resource entry type (e.g. SYS_RES_MEMORY)
2420151378Snetchild * @param rid		the resource identifier
2421151378Snetchild * @param start		the start address of the resource
2422151378Snetchild * @param end		the end address of the resource
2423151378Snetchild * @param count		XXX end-start+1
2424151378Snetchild */
2425151378Snetchildvoid
2426151378Snetchildresource_list_add(struct resource_list *rl, int type, int rid,
2427151378Snetchild    u_long start, u_long end, u_long count)
2428151378Snetchild{
2429151378Snetchild	struct resource_list_entry *rle;
2430151378Snetchild
2431151378Snetchild	rle = resource_list_find(rl, type, rid);
2432151378Snetchild	if (!rle) {
2433151378Snetchild		rle = malloc(sizeof(struct resource_list_entry), M_BUS,
2434151378Snetchild		    M_NOWAIT);
2435151378Snetchild		if (!rle)
2436151378Snetchild			panic("resource_list_add: can't record entry");
2437151378Snetchild		SLIST_INSERT_HEAD(rl, rle, link);
2438151378Snetchild		rle->type = type;
2439151378Snetchild		rle->rid = rid;
2440151378Snetchild		rle->res = NULL;
2441151378Snetchild	}
2442151378Snetchild
2443151378Snetchild	if (rle->res)
2444151378Snetchild		panic("resource_list_add: resource entry is busy");
2445151378Snetchild
2446151378Snetchild	rle->start = start;
2447151378Snetchild	rle->end = end;
2448151378Snetchild	rle->count = count;
2449151378Snetchild}
2450151378Snetchild
2451151378Snetchild/**
2452151378Snetchild * @brief Find a resource entry by type and rid.
2453151378Snetchild *
2454151378Snetchild * @param rl		the resource list to search
2455151378Snetchild * @param type		the resource entry type (e.g. SYS_RES_MEMORY)
2456151378Snetchild * @param rid		the resource identifier
2457151378Snetchild *
2458151378Snetchild * @returns the resource entry pointer or NULL if there is no such
2459151378Snetchild * entry.
2460151378Snetchild */
2461151378Snetchildstruct resource_list_entry *
2462151378Snetchildresource_list_find(struct resource_list *rl, int type, int rid)
2463151378Snetchild{
2464151378Snetchild	struct resource_list_entry *rle;
2465151378Snetchild
2466151378Snetchild	SLIST_FOREACH(rle, rl, link) {
2467151378Snetchild		if (rle->type == type && rle->rid == rid)
2468151378Snetchild			return (rle);
2469151378Snetchild	}
2470151378Snetchild	return (NULL);
2471151378Snetchild}
2472151378Snetchild
2473151378Snetchild/**
2474151378Snetchild * @brief Delete a resource entry.
2475151378Snetchild *
2476151378Snetchild * @param rl		the resource list to edit
2477151378Snetchild * @param type		the resource entry type (e.g. SYS_RES_MEMORY)
2478151378Snetchild * @param rid		the resource identifier
2479151378Snetchild */
2480151378Snetchildvoid
2481151378Snetchildresource_list_delete(struct resource_list *rl, int type, int rid)
2482151378Snetchild{
2483151378Snetchild	struct resource_list_entry *rle = resource_list_find(rl, type, rid);
2484151378Snetchild
2485151378Snetchild	if (rle) {
2486151378Snetchild		if (rle->res != NULL)
2487151378Snetchild			panic("resource_list_delete: resource has not been released");
2488151378Snetchild		SLIST_REMOVE(rl, rle, resource_list_entry, link);
2489151378Snetchild		free(rle, M_BUS);
2490151378Snetchild	}
2491151378Snetchild}
2492151378Snetchild
2493151378Snetchild/**
2494151378Snetchild * @brief Helper function for implementing BUS_ALLOC_RESOURCE()
2495151378Snetchild *
2496151378Snetchild * Implement BUS_ALLOC_RESOURCE() by looking up a resource from the list
2497151378Snetchild * and passing the allocation up to the parent of @p bus. This assumes
2498151378Snetchild * that the first entry of @c device_get_ivars(child) is a struct
2499151378Snetchild * resource_list. This also handles 'passthrough' allocations where a
2500151378Snetchild * child is a remote descendant of bus by passing the allocation up to
2501151378Snetchild * the parent of bus.
2502151378Snetchild *
2503151378Snetchild * Typically, a bus driver would store a list of child resources
2504151378Snetchild * somewhere in the child device's ivars (see device_get_ivars()) and
2505151378Snetchild * its implementation of BUS_ALLOC_RESOURCE() would find that list and
2506151378Snetchild * then call resource_list_alloc() to perform the allocation.
2507151378Snetchild *
2508151378Snetchild * @param rl		the resource list to allocate from
2509151378Snetchild * @param bus		the parent device of @p child
2510151378Snetchild * @param child		the device which is requesting an allocation
2511151378Snetchild * @param type		the type of resource to allocate
2512151378Snetchild * @param rid		a pointer to the resource identifier
2513151378Snetchild * @param start		hint at the start of the resource range - pass
2514151378Snetchild *			@c 0UL for any start address
2515151378Snetchild * @param end		hint at the end of the resource range - pass
2516151378Snetchild *			@c ~0UL for any end address
2517151378Snetchild * @param count		hint at the size of range required - pass @c 1
2518151378Snetchild *			for any size
2519151378Snetchild * @param flags		any extra flags to control the resource
2520151378Snetchild *			allocation - see @c RF_XXX flags in
2521151378Snetchild *			<sys/rman.h> for details
2522151378Snetchild *
2523151378Snetchild * @returns		the resource which was allocated or @c NULL if no
2524151378Snetchild *			resource could be allocated
2525151378Snetchild */
2526151378Snetchildstruct resource *
2527151378Snetchildresource_list_alloc(struct resource_list *rl, device_t bus, device_t child,
2528151378Snetchild    int type, int *rid, u_long start, u_long end, u_long count, u_int flags)
2529151378Snetchild{
2530151378Snetchild	struct resource_list_entry *rle = 0;
2531151378Snetchild	int passthrough = (device_get_parent(child) != bus);
2532151378Snetchild	int isdefault = (start == 0UL && end == ~0UL);
2533151378Snetchild
2534151378Snetchild	if (passthrough) {
2535151378Snetchild		return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child,
2536151378Snetchild		    type, rid, start, end, count, flags));
2537151378Snetchild	}
2538151378Snetchild
2539151378Snetchild	rle = resource_list_find(rl, type, *rid);
2540151378Snetchild
2541151378Snetchild	if (!rle)
2542151378Snetchild		return (NULL);		/* no resource of that type/rid */
2543151378Snetchild
2544151378Snetchild	if (rle->res)
2545151378Snetchild		panic("resource_list_alloc: resource entry is busy");
2546151378Snetchild
2547151378Snetchild	if (isdefault) {
2548151378Snetchild		start = rle->start;
2549151378Snetchild		count = ulmax(count, rle->count);
2550151378Snetchild		end = ulmax(rle->end, start + count - 1);
2551151378Snetchild	}
2552151378Snetchild
2553151378Snetchild	rle->res = BUS_ALLOC_RESOURCE(device_get_parent(bus), child,
2554151378Snetchild	    type, rid, start, end, count, flags);
2555151378Snetchild
2556151378Snetchild	/*
2557151378Snetchild	 * Record the new range.
2558151378Snetchild	 */
2559151378Snetchild	if (rle->res) {
2560151378Snetchild		rle->start = rman_get_start(rle->res);
2561151378Snetchild		rle->end = rman_get_end(rle->res);
2562151378Snetchild		rle->count = count;
2563151378Snetchild	}
2564151378Snetchild
2565151378Snetchild	return (rle->res);
2566151378Snetchild}
2567151378Snetchild
2568151378Snetchild/**
2569151378Snetchild * @brief Helper function for implementing BUS_RELEASE_RESOURCE()
2570151378Snetchild *
2571151378Snetchild * Implement BUS_RELEASE_RESOURCE() using a resource list. Normally
2572151378Snetchild * used with resource_list_alloc().
2573151378Snetchild *
2574151378Snetchild * @param rl		the resource list which was allocated from
2575151378Snetchild * @param bus		the parent device of @p child
2576151378Snetchild * @param child		the device which is requesting a release
2577151378Snetchild * @param type		the type of resource to allocate
2578151378Snetchild * @param rid		the resource identifier
2579151378Snetchild * @param res		the resource to release
2580151378Snetchild *
2581151378Snetchild * @retval 0		success
2582151378Snetchild * @retval non-zero	a standard unix error code indicating what
2583151378Snetchild *			error condition prevented the operation
2584151378Snetchild */
2585151378Snetchildint
2586151378Snetchildresource_list_release(struct resource_list *rl, device_t bus, device_t child,
2587151378Snetchild    int type, int rid, struct resource *res)
2588151378Snetchild{
2589151378Snetchild	struct resource_list_entry *rle = 0;
2590151378Snetchild	int passthrough = (device_get_parent(child) != bus);
2591151378Snetchild	int error;
2592151378Snetchild
2593151378Snetchild	if (passthrough) {
2594151378Snetchild		return (BUS_RELEASE_RESOURCE(device_get_parent(bus), child,
2595151378Snetchild		    type, rid, res));
2596151378Snetchild	}
2597151378Snetchild
2598151378Snetchild	rle = resource_list_find(rl, type, rid);
2599151378Snetchild
2600151378Snetchild	if (!rle)
2601151378Snetchild		panic("resource_list_release: can't find resource");
2602151378Snetchild	if (!rle->res)
2603151378Snetchild		panic("resource_list_release: resource entry is not busy");
2604151378Snetchild
2605151378Snetchild	error = BUS_RELEASE_RESOURCE(device_get_parent(bus), child,
2606151378Snetchild	    type, rid, res);
2607151378Snetchild	if (error)
2608151378Snetchild		return (error);
2609151378Snetchild
2610151378Snetchild	rle->res = NULL;
2611151378Snetchild	return (0);
2612151378Snetchild}
2613151378Snetchild
2614151378Snetchild/**
2615151378Snetchild * @brief Print a description of resources in a resource list
2616151378Snetchild *
2617151378Snetchild * Print all resources of a specified type, for use in BUS_PRINT_CHILD().
2618151378Snetchild * The name is printed if at least one resource of the given type is available.
2619151378Snetchild * The format is used to print resource start and end.
2620151378Snetchild *
2621151378Snetchild * @param rl		the resource list to print
2622151378Snetchild * @param name		the name of @p type, e.g. @c "memory"
2623151378Snetchild * @param type		type type of resource entry to print
2624151378Snetchild * @param format	printf(9) format string to print resource
2625151378Snetchild *			start and end values
2626151378Snetchild *
2627151378Snetchild * @returns		the number of characters printed
2628151378Snetchild */
2629151378Snetchildint
2630151378Snetchildresource_list_print_type(struct resource_list *rl, const char *name, int type,
2631151378Snetchild    const char *format)
2632151378Snetchild{
2633151378Snetchild	struct resource_list_entry *rle;
2634151378Snetchild	int printed, retval;
2635151378Snetchild
2636151378Snetchild	printed = 0;
2637151378Snetchild	retval = 0;
2638151378Snetchild	/* Yes, this is kinda cheating */
2639151378Snetchild	SLIST_FOREACH(rle, rl, link) {
2640151378Snetchild		if (rle->type == type) {
2641151378Snetchild			if (printed == 0)
2642151378Snetchild				retval += printf(" %s ", name);
2643151378Snetchild			else
2644151378Snetchild				retval += printf(",");
2645151378Snetchild			printed++;
2646151378Snetchild			retval += printf(format, rle->start);
2647151378Snetchild			if (rle->count > 1) {
2648151378Snetchild				retval += printf("-");
2649151378Snetchild				retval += printf(format, rle->start +
2650151378Snetchild						 rle->count - 1);
2651151378Snetchild			}
2652151378Snetchild		}
2653151378Snetchild	}
2654151378Snetchild	return (retval);
2655151378Snetchild}
2656151378Snetchild
2657151378Snetchild/**
2658151378Snetchild * @brief Helper function for implementing DEVICE_PROBE()
2659151378Snetchild *
2660151378Snetchild * This function can be used to help implement the DEVICE_PROBE() for
2661151378Snetchild * a bus (i.e. a device which has other devices attached to it). It
2662151378Snetchild * calls the DEVICE_IDENTIFY() method of each driver in the device's
2663151378Snetchild * devclass.
2664151378Snetchild */
2665151378Snetchildint
2666151378Snetchildbus_generic_probe(device_t dev)
2667151378Snetchild{
2668151378Snetchild	devclass_t dc = dev->devclass;
2669151378Snetchild	driverlink_t dl;
2670151378Snetchild
2671151378Snetchild	TAILQ_FOREACH(dl, &dc->drivers, link) {
2672151378Snetchild		DEVICE_IDENTIFY(dl->driver, dev);
2673151378Snetchild	}
2674151378Snetchild
2675151378Snetchild	return (0);
2676151378Snetchild}
2677151378Snetchild
2678151378Snetchild/**
2679151378Snetchild * @brief Helper function for implementing DEVICE_ATTACH()
2680151378Snetchild *
2681151378Snetchild * This function can be used to help implement the DEVICE_ATTACH() for
2682151378Snetchild * a bus. It calls device_probe_and_attach() for each of the device's
2683151378Snetchild * children.
2684151378Snetchild */
2685151378Snetchildint
2686151378Snetchildbus_generic_attach(device_t dev)
2687151378Snetchild{
2688151378Snetchild	device_t child;
2689151378Snetchild
2690151378Snetchild	TAILQ_FOREACH(child, &dev->children, link) {
2691151378Snetchild		device_probe_and_attach(child);
2692151378Snetchild	}
2693151378Snetchild
2694151378Snetchild	return (0);
2695151378Snetchild}
2696151378Snetchild
2697151378Snetchild/**
2698151378Snetchild * @brief Helper function for implementing DEVICE_DETACH()
2699151378Snetchild *
2700151378Snetchild * This function can be used to help implement the DEVICE_DETACH() for
2701151378Snetchild * a bus. It calls device_detach() for each of the device's
2702151378Snetchild * children.
2703151378Snetchild */
2704151378Snetchildint
2705151378Snetchildbus_generic_detach(device_t dev)
2706151378Snetchild{
2707151378Snetchild	device_t child;
2708151378Snetchild	int error;
2709151378Snetchild
2710151378Snetchild	if (dev->state != DS_ATTACHED)
2711151378Snetchild		return (EBUSY);
2712151378Snetchild
2713151378Snetchild	TAILQ_FOREACH(child, &dev->children, link) {
2714151378Snetchild		if ((error = device_detach(child)) != 0)
2715151378Snetchild			return (error);
2716151378Snetchild	}
2717151378Snetchild
2718151378Snetchild	return (0);
2719151378Snetchild}
2720151378Snetchild
2721151378Snetchild/**
2722151378Snetchild * @brief Helper function for implementing DEVICE_SHUTDOWN()
2723151378Snetchild *
2724151378Snetchild * This function can be used to help implement the DEVICE_SHUTDOWN()
2725151378Snetchild * for a bus. It calls device_shutdown() for each of the device's
2726151378Snetchild * children.
2727151378Snetchild */
2728151378Snetchildint
2729151378Snetchildbus_generic_shutdown(device_t dev)
2730151378Snetchild{
2731151378Snetchild	device_t child;
2732151378Snetchild
2733151378Snetchild	TAILQ_FOREACH(child, &dev->children, link) {
2734151378Snetchild		device_shutdown(child);
2735151378Snetchild	}
2736151378Snetchild
2737151378Snetchild	return (0);
2738151378Snetchild}
2739151378Snetchild
2740151378Snetchild/**
2741151378Snetchild * @brief Helper function for implementing DEVICE_SUSPEND()
2742151378Snetchild *
2743151378Snetchild * This function can be used to help implement the DEVICE_SUSPEND()
2744151378Snetchild * for a bus. It calls DEVICE_SUSPEND() for each of the device's
2745151378Snetchild * children. If any call to DEVICE_SUSPEND() fails, the suspend
2746151378Snetchild * operation is aborted and any devices which were suspended are
2747151378Snetchild * resumed immediately by calling their DEVICE_RESUME() methods.
2748151378Snetchild */
2749151378Snetchildint
2750151378Snetchildbus_generic_suspend(device_t dev)
2751151378Snetchild{
2752151378Snetchild	int		error;
2753151378Snetchild	device_t	child, child2;
2754151378Snetchild
2755151378Snetchild	TAILQ_FOREACH(child, &dev->children, link) {
2756151378Snetchild		error = DEVICE_SUSPEND(child);
2757151378Snetchild		if (error) {
2758151378Snetchild			for (child2 = TAILQ_FIRST(&dev->children);
2759151378Snetchild			     child2 && child2 != child;
2760151378Snetchild			     child2 = TAILQ_NEXT(child2, link))
2761151378Snetchild				DEVICE_RESUME(child2);
2762151378Snetchild			return (error);
2763151378Snetchild		}
2764151378Snetchild	}
2765151378Snetchild	return (0);
2766151378Snetchild}
2767151378Snetchild
2768151378Snetchild/**
2769151378Snetchild * @brief Helper function for implementing DEVICE_RESUME()
2770151378Snetchild *
2771151378Snetchild * This function can be used to help implement the DEVICE_RESUME() for
2772151378Snetchild * a bus. It calls DEVICE_RESUME() on each of the device's children.
2773151378Snetchild */
2774151378Snetchildint
2775151378Snetchildbus_generic_resume(device_t dev)
2776151378Snetchild{
2777151378Snetchild	device_t	child;
2778151378Snetchild
2779151378Snetchild	TAILQ_FOREACH(child, &dev->children, link) {
2780151378Snetchild		DEVICE_RESUME(child);
2781151378Snetchild		/* if resume fails, there's nothing we can usefully do... */
2782151378Snetchild	}
2783151378Snetchild	return (0);
2784151378Snetchild}
2785151378Snetchild
2786151378Snetchild/**
2787151378Snetchild * @brief Helper function for implementing BUS_PRINT_CHILD().
2788151378Snetchild *
2789151378Snetchild * This function prints the first part of the ascii representation of
2790151378Snetchild * @p child, including its name, unit and description (if any - see
2791151378Snetchild * device_set_desc()).
2792151378Snetchild *
2793151378Snetchild * @returns the number of characters printed
2794151378Snetchild */
2795151378Snetchildint
2796151378Snetchildbus_print_child_header(device_t dev, device_t child)
2797151378Snetchild{
2798151378Snetchild	int	retval = 0;
2799151378Snetchild
2800151378Snetchild	if (device_get_desc(child)) {
2801151378Snetchild		retval += device_printf(child, "<%s>", device_get_desc(child));
2802151378Snetchild	} else {
2803151378Snetchild		retval += printf("%s", device_get_nameunit(child));
2804151378Snetchild	}
2805151378Snetchild
2806151378Snetchild	return (retval);
2807151378Snetchild}
2808151378Snetchild
2809151378Snetchild/**
2810151378Snetchild * @brief Helper function for implementing BUS_PRINT_CHILD().
2811151378Snetchild *
2812151378Snetchild * This function prints the last part of the ascii representation of
2813151378Snetchild * @p child, which consists of the string @c " on " followed by the
2814151378Snetchild * name and unit of the @p dev.
2815151378Snetchild *
2816151378Snetchild * @returns the number of characters printed
2817151378Snetchild */
2818151378Snetchildint
2819151378Snetchildbus_print_child_footer(device_t dev, device_t child)
2820151378Snetchild{
2821151378Snetchild	return (printf(" on %s\n", device_get_nameunit(dev)));
2822151378Snetchild}
2823151378Snetchild
2824151378Snetchild/**
2825151378Snetchild * @brief Helper function for implementing BUS_PRINT_CHILD().
2826151378Snetchild *
2827151378Snetchild * This function simply calls bus_print_child_header() followed by
2828151378Snetchild * bus_print_child_footer().
2829151378Snetchild *
2830151378Snetchild * @returns the number of characters printed
2831151378Snetchild */
2832151378Snetchildint
2833151378Snetchildbus_generic_print_child(device_t dev, device_t child)
2834151378Snetchild{
2835151378Snetchild	int	retval = 0;
2836151378Snetchild
2837151378Snetchild	retval += bus_print_child_header(dev, child);
2838151378Snetchild	retval += bus_print_child_footer(dev, child);
2839151378Snetchild
2840151378Snetchild	return (retval);
2841151378Snetchild}
2842151378Snetchild
2843151378Snetchild/**
2844151378Snetchild * @brief Stub function for implementing BUS_READ_IVAR().
2845151378Snetchild *
2846151378Snetchild * @returns ENOENT
2847151378Snetchild */
2848151378Snetchildint
2849151378Snetchildbus_generic_read_ivar(device_t dev, device_t child, int index,
2850151378Snetchild    uintptr_t * result)
2851151378Snetchild{
2852151378Snetchild	return (ENOENT);
2853151378Snetchild}
2854151378Snetchild
2855151378Snetchild/**
2856151378Snetchild * @brief Stub function for implementing BUS_WRITE_IVAR().
2857151378Snetchild *
2858151378Snetchild * @returns ENOENT
2859151378Snetchild */
2860151378Snetchildint
2861151378Snetchildbus_generic_write_ivar(device_t dev, device_t child, int index,
2862151378Snetchild    uintptr_t value)
2863151378Snetchild{
2864151378Snetchild	return (ENOENT);
2865151378Snetchild}
2866151378Snetchild
2867151378Snetchild/**
2868151378Snetchild * @brief Stub function for implementing BUS_GET_RESOURCE_LIST().
2869151378Snetchild *
2870151378Snetchild * @returns NULL
2871151378Snetchild */
2872151378Snetchildstruct resource_list *
2873151378Snetchildbus_generic_get_resource_list(device_t dev, device_t child)
2874151378Snetchild{
2875151378Snetchild	return (NULL);
2876151378Snetchild}
2877151378Snetchild
2878151378Snetchild/**
2879151378Snetchild * @brief Helper function for implementing BUS_DRIVER_ADDED().
2880151378Snetchild *
2881151378Snetchild * This implementation of BUS_DRIVER_ADDED() simply calls the driver's
2882151378Snetchild * DEVICE_IDENTIFY() method to allow it to add new children to the bus
2883151378Snetchild * and then calls device_probe_and_attach() for each unattached child.
2884151378Snetchild */
2885151378Snetchildvoid
2886151378Snetchildbus_generic_driver_added(device_t dev, driver_t *driver)
2887151378Snetchild{
2888151378Snetchild	device_t child;
2889151378Snetchild
2890151378Snetchild	DEVICE_IDENTIFY(driver, dev);
2891151378Snetchild	TAILQ_FOREACH(child, &dev->children, link) {
2892151378Snetchild		if (child->state == DS_NOTPRESENT ||
2893151378Snetchild		    (child->flags & DF_REBID))
2894151378Snetchild			device_probe_and_attach(child);
2895151378Snetchild	}
2896151378Snetchild}
2897151378Snetchild
2898151378Snetchild/**
2899151378Snetchild * @brief Helper function for implementing BUS_SETUP_INTR().
2900151378Snetchild *
2901151378Snetchild * This simple implementation of BUS_SETUP_INTR() simply calls the
2902151378Snetchild * BUS_SETUP_INTR() method of the parent of @p dev.
2903151378Snetchild */
2904151378Snetchildint
2905151378Snetchildbus_generic_setup_intr(device_t dev, device_t child, struct resource *irq,
2906151378Snetchild    int flags, driver_intr_t *intr, void *arg, void **cookiep)
2907151378Snetchild{
2908151378Snetchild	/* Propagate up the bus hierarchy until someone handles it. */
2909151378Snetchild	if (dev->parent)
2910151378Snetchild		return (BUS_SETUP_INTR(dev->parent, child, irq, flags,
2911151378Snetchild		    intr, arg, cookiep));
2912151378Snetchild	return (EINVAL);
2913151378Snetchild}
2914151378Snetchild
2915151378Snetchild/**
2916151378Snetchild * @brief Helper function for implementing BUS_TEARDOWN_INTR().
2917151378Snetchild *
2918151378Snetchild * This simple implementation of BUS_TEARDOWN_INTR() simply calls the
2919151378Snetchild * BUS_TEARDOWN_INTR() method of the parent of @p dev.
2920151378Snetchild */
2921151378Snetchildint
2922151378Snetchildbus_generic_teardown_intr(device_t dev, device_t child, struct resource *irq,
2923151378Snetchild    void *cookie)
2924151378Snetchild{
2925151378Snetchild	/* Propagate up the bus hierarchy until someone handles it. */
2926151378Snetchild	if (dev->parent)
2927151378Snetchild		return (BUS_TEARDOWN_INTR(dev->parent, child, irq, cookie));
2928151378Snetchild	return (EINVAL);
2929151378Snetchild}
2930151378Snetchild
2931151378Snetchild/**
2932151378Snetchild * @brief Helper function for implementing BUS_ALLOC_RESOURCE().
2933151378Snetchild *
2934151378Snetchild * This simple implementation of BUS_ALLOC_RESOURCE() simply calls the
2935151378Snetchild * BUS_ALLOC_RESOURCE() method of the parent of @p dev.
2936151378Snetchild */
2937151378Snetchildstruct resource *
2938151378Snetchildbus_generic_alloc_resource(device_t dev, device_t child, int type, int *rid,
2939151378Snetchild    u_long start, u_long end, u_long count, u_int flags)
2940151378Snetchild{
2941151378Snetchild	/* Propagate up the bus hierarchy until someone handles it. */
2942151378Snetchild	if (dev->parent)
2943151378Snetchild		return (BUS_ALLOC_RESOURCE(dev->parent, child, type, rid,
2944151378Snetchild		    start, end, count, flags));
2945151378Snetchild	return (NULL);
2946151378Snetchild}
2947151378Snetchild
2948151378Snetchild/**
2949151378Snetchild * @brief Helper function for implementing BUS_RELEASE_RESOURCE().
2950151378Snetchild *
2951151378Snetchild * This simple implementation of BUS_RELEASE_RESOURCE() simply calls the
2952151378Snetchild * BUS_RELEASE_RESOURCE() method of the parent of @p dev.
2953151378Snetchild */
2954151378Snetchildint
2955151378Snetchildbus_generic_release_resource(device_t dev, device_t child, int type, int rid,
2956151378Snetchild    struct resource *r)
2957151378Snetchild{
2958151378Snetchild	/* Propagate up the bus hierarchy until someone handles it. */
2959151378Snetchild	if (dev->parent)
2960151378Snetchild		return (BUS_RELEASE_RESOURCE(dev->parent, child, type, rid,
2961151378Snetchild		    r));
2962151378Snetchild	return (EINVAL);
2963151378Snetchild}
2964151378Snetchild
2965151378Snetchild/**
2966151378Snetchild * @brief Helper function for implementing BUS_ACTIVATE_RESOURCE().
2967151378Snetchild *
2968151378Snetchild * This simple implementation of BUS_ACTIVATE_RESOURCE() simply calls the
2969151378Snetchild * BUS_ACTIVATE_RESOURCE() method of the parent of @p dev.
2970151378Snetchild */
2971151378Snetchildint
2972151378Snetchildbus_generic_activate_resource(device_t dev, device_t child, int type, int rid,
2973151378Snetchild    struct resource *r)
2974151378Snetchild{
2975151378Snetchild	/* Propagate up the bus hierarchy until someone handles it. */
2976151378Snetchild	if (dev->parent)
2977151378Snetchild		return (BUS_ACTIVATE_RESOURCE(dev->parent, child, type, rid,
2978151378Snetchild		    r));
2979151378Snetchild	return (EINVAL);
2980151378Snetchild}
2981151378Snetchild
2982151378Snetchild/**
2983151378Snetchild * @brief Helper function for implementing BUS_DEACTIVATE_RESOURCE().
2984151378Snetchild *
2985151378Snetchild * This simple implementation of BUS_DEACTIVATE_RESOURCE() simply calls the
2986151378Snetchild * BUS_DEACTIVATE_RESOURCE() method of the parent of @p dev.
2987151378Snetchild */
2988151378Snetchildint
2989151378Snetchildbus_generic_deactivate_resource(device_t dev, device_t child, int type,
2990151378Snetchild    int rid, struct resource *r)
2991151378Snetchild{
2992151378Snetchild	/* Propagate up the bus hierarchy until someone handles it. */
2993151378Snetchild	if (dev->parent)
2994151378Snetchild		return (BUS_DEACTIVATE_RESOURCE(dev->parent, child, type, rid,
2995151378Snetchild		    r));
2996151378Snetchild	return (EINVAL);
2997151378Snetchild}
2998151378Snetchild
2999151378Snetchild/**
3000151378Snetchild * @brief Helper function for implementing BUS_CONFIG_INTR().
3001151378Snetchild *
3002151378Snetchild * This simple implementation of BUS_CONFIG_INTR() simply calls the
3003151378Snetchild * BUS_CONFIG_INTR() method of the parent of @p dev.
3004151378Snetchild */
3005151378Snetchildint
3006151378Snetchildbus_generic_config_intr(device_t dev, int irq, enum intr_trigger trig,
3007151378Snetchild    enum intr_polarity pol)
3008151378Snetchild{
3009151378Snetchild
3010151378Snetchild	/* Propagate up the bus hierarchy until someone handles it. */
3011151378Snetchild	if (dev->parent)
3012151378Snetchild		return (BUS_CONFIG_INTR(dev->parent, irq, trig, pol));
3013151378Snetchild	return (EINVAL);
3014151378Snetchild}
3015151378Snetchild
3016151378Snetchild/**
3017151378Snetchild * @brief Helper function for implementing BUS_GET_RESOURCE().
3018151378Snetchild *
3019151378Snetchild * This implementation of BUS_GET_RESOURCE() uses the
3020151378Snetchild * resource_list_find() function to do most of the work. It calls
3021151378Snetchild * BUS_GET_RESOURCE_LIST() to find a suitable resource list to
3022151378Snetchild * search.
3023151378Snetchild */
3024151378Snetchildint
3025151378Snetchildbus_generic_rl_get_resource(device_t dev, device_t child, int type, int rid,
3026151378Snetchild    u_long *startp, u_long *countp)
3027151378Snetchild{
3028151378Snetchild	struct resource_list *		rl = NULL;
3029151378Snetchild	struct resource_list_entry *	rle = NULL;
3030151378Snetchild
3031151378Snetchild	rl = BUS_GET_RESOURCE_LIST(dev, child);
3032151378Snetchild	if (!rl)
3033151378Snetchild		return (EINVAL);
3034151378Snetchild
3035151378Snetchild	rle = resource_list_find(rl, type, rid);
3036151378Snetchild	if (!rle)
3037151378Snetchild		return (ENOENT);
3038151378Snetchild
3039151378Snetchild	if (startp)
3040151378Snetchild		*startp = rle->start;
3041151378Snetchild	if (countp)
3042151378Snetchild		*countp = rle->count;
3043151378Snetchild
3044151378Snetchild	return (0);
3045151378Snetchild}
3046151378Snetchild
3047151378Snetchild/**
3048151378Snetchild * @brief Helper function for implementing BUS_SET_RESOURCE().
3049151378Snetchild *
3050151378Snetchild * This implementation of BUS_SET_RESOURCE() uses the
3051151378Snetchild * resource_list_add() function to do most of the work. It calls
3052151378Snetchild * BUS_GET_RESOURCE_LIST() to find a suitable resource list to
3053151378Snetchild * edit.
3054151378Snetchild */
3055151378Snetchildint
3056151378Snetchildbus_generic_rl_set_resource(device_t dev, device_t child, int type, int rid,
3057151378Snetchild    u_long start, u_long count)
3058151378Snetchild{
3059151378Snetchild	struct resource_list *		rl = NULL;
3060151378Snetchild
3061151378Snetchild	rl = BUS_GET_RESOURCE_LIST(dev, child);
3062151378Snetchild	if (!rl)
3063151378Snetchild		return (EINVAL);
3064151378Snetchild
3065151378Snetchild	resource_list_add(rl, type, rid, start, (start + count - 1), count);
3066151378Snetchild
3067151378Snetchild	return (0);
3068151378Snetchild}
3069151378Snetchild
3070151378Snetchild/**
3071151378Snetchild * @brief Helper function for implementing BUS_DELETE_RESOURCE().
3072151378Snetchild *
3073151378Snetchild * This implementation of BUS_DELETE_RESOURCE() uses the
3074151378Snetchild * resource_list_delete() function to do most of the work. It calls
3075151378Snetchild * BUS_GET_RESOURCE_LIST() to find a suitable resource list to
3076151378Snetchild * edit.
3077151378Snetchild */
3078151378Snetchildvoid
3079151378Snetchildbus_generic_rl_delete_resource(device_t dev, device_t child, int type, int rid)
3080151378Snetchild{
3081151378Snetchild	struct resource_list *		rl = NULL;
3082151378Snetchild
3083151378Snetchild	rl = BUS_GET_RESOURCE_LIST(dev, child);
3084151378Snetchild	if (!rl)
3085151378Snetchild		return;
3086151378Snetchild
3087151378Snetchild	resource_list_delete(rl, type, rid);
3088151378Snetchild
3089151378Snetchild	return;
3090151378Snetchild}
3091151378Snetchild
3092151378Snetchild/**
3093151378Snetchild * @brief Helper function for implementing BUS_RELEASE_RESOURCE().
3094151378Snetchild *
3095151378Snetchild * This implementation of BUS_RELEASE_RESOURCE() uses the
3096151378Snetchild * resource_list_release() function to do most of the work. It calls
3097151378Snetchild * BUS_GET_RESOURCE_LIST() to find a suitable resource list.
3098151378Snetchild */
3099151378Snetchildint
3100151378Snetchildbus_generic_rl_release_resource(device_t dev, device_t child, int type,
3101151378Snetchild    int rid, struct resource *r)
3102151378Snetchild{
3103151378Snetchild	struct resource_list *		rl = NULL;
3104151378Snetchild
3105151378Snetchild	rl = BUS_GET_RESOURCE_LIST(dev, child);
3106151378Snetchild	if (!rl)
3107151378Snetchild		return (EINVAL);
3108151378Snetchild
3109151378Snetchild	return (resource_list_release(rl, dev, child, type, rid, r));
3110151378Snetchild}
3111151378Snetchild
3112151378Snetchild/**
3113151378Snetchild * @brief Helper function for implementing BUS_ALLOC_RESOURCE().
3114151378Snetchild *
3115151378Snetchild * This implementation of BUS_ALLOC_RESOURCE() uses the
3116151378Snetchild * resource_list_alloc() function to do most of the work. It calls
3117151378Snetchild * BUS_GET_RESOURCE_LIST() to find a suitable resource list.
3118151378Snetchild */
3119151378Snetchildstruct resource *
3120151378Snetchildbus_generic_rl_alloc_resource(device_t dev, device_t child, int type,
3121151378Snetchild    int *rid, u_long start, u_long end, u_long count, u_int flags)
3122151378Snetchild{
3123151378Snetchild	struct resource_list *		rl = NULL;
3124151378Snetchild
3125151378Snetchild	rl = BUS_GET_RESOURCE_LIST(dev, child);
3126151378Snetchild	if (!rl)
3127151378Snetchild		return (NULL);
3128151378Snetchild
3129151378Snetchild	return (resource_list_alloc(rl, dev, child, type, rid,
3130151378Snetchild	    start, end, count, flags));
3131151378Snetchild}
3132151378Snetchild
3133151378Snetchild/**
3134151378Snetchild * @brief Helper function for implementing BUS_CHILD_PRESENT().
3135151378Snetchild *
3136151378Snetchild * This simple implementation of BUS_CHILD_PRESENT() simply calls the
3137151378Snetchild * BUS_CHILD_PRESENT() method of the parent of @p dev.
3138151378Snetchild */
3139151378Snetchildint
3140151378Snetchildbus_generic_child_present(device_t dev, device_t child)
3141151378Snetchild{
3142151378Snetchild	return (BUS_CHILD_PRESENT(device_get_parent(dev), dev));
3143151378Snetchild}
3144151378Snetchild
3145151378Snetchild/*
3146151378Snetchild * Some convenience functions to make it easier for drivers to use the
3147151378Snetchild * resource-management functions.  All these really do is hide the
3148151378Snetchild * indirection through the parent's method table, making for slightly
3149151378Snetchild * less-wordy code.  In the future, it might make sense for this code
3150151378Snetchild * to maintain some sort of a list of resources allocated by each device.
3151151378Snetchild */
3152151378Snetchild
3153151378Snetchild/**
3154151378Snetchild * @brief Wrapper function for BUS_ALLOC_RESOURCE().
3155151378Snetchild *
3156151378Snetchild * This function simply calls the BUS_ALLOC_RESOURCE() method of the
3157151378Snetchild * parent of @p dev.
3158151378Snetchild */
3159151378Snetchildstruct resource *
3160151378Snetchildbus_alloc_resource(device_t dev, int type, int *rid, u_long start, u_long end,
3161151378Snetchild    u_long count, u_int flags)
3162151378Snetchild{
3163151378Snetchild	if (dev->parent == 0)
3164151378Snetchild		return (0);
3165151378Snetchild	return (BUS_ALLOC_RESOURCE(dev->parent, dev, type, rid, start, end,
3166151378Snetchild	    count, flags));
3167151378Snetchild}
3168151378Snetchild
3169151378Snetchild/**
3170151378Snetchild * @brief Wrapper function for BUS_ACTIVATE_RESOURCE().
3171151378Snetchild *
3172151378Snetchild * This function simply calls the BUS_ACTIVATE_RESOURCE() method of the
3173151378Snetchild * parent of @p dev.
3174151378Snetchild */
3175151378Snetchildint
3176151378Snetchildbus_activate_resource(device_t dev, int type, int rid, struct resource *r)
3177151378Snetchild{
3178151378Snetchild	if (dev->parent == 0)
3179151378Snetchild		return (EINVAL);
3180151378Snetchild	return (BUS_ACTIVATE_RESOURCE(dev->parent, dev, type, rid, r));
3181151378Snetchild}
3182151378Snetchild
3183151378Snetchild/**
3184151378Snetchild * @brief Wrapper function for BUS_DEACTIVATE_RESOURCE().
3185151378Snetchild *
3186151378Snetchild * This function simply calls the BUS_DEACTIVATE_RESOURCE() method of the
3187151378Snetchild * parent of @p dev.
3188151378Snetchild */
3189151378Snetchildint
3190151378Snetchildbus_deactivate_resource(device_t dev, int type, int rid, struct resource *r)
3191151378Snetchild{
3192151378Snetchild	if (dev->parent == 0)
3193151378Snetchild		return (EINVAL);
3194151378Snetchild	return (BUS_DEACTIVATE_RESOURCE(dev->parent, dev, type, rid, r));
3195151378Snetchild}
3196151378Snetchild
3197151378Snetchild/**
3198151378Snetchild * @brief Wrapper function for BUS_RELEASE_RESOURCE().
3199151378Snetchild *
3200151378Snetchild * This function simply calls the BUS_RELEASE_RESOURCE() method of the
3201151378Snetchild * parent of @p dev.
3202151378Snetchild */
3203151378Snetchildint
3204151378Snetchildbus_release_resource(device_t dev, int type, int rid, struct resource *r)
3205151378Snetchild{
3206151378Snetchild	if (dev->parent == 0)
3207151378Snetchild		return (EINVAL);
3208151378Snetchild	return (BUS_RELEASE_RESOURCE(dev->parent, dev, type, rid, r));
3209151378Snetchild}
3210151378Snetchild
3211151378Snetchild/**
3212151378Snetchild * @brief Wrapper function for BUS_SETUP_INTR().
3213151378Snetchild *
3214151378Snetchild * This function simply calls the BUS_SETUP_INTR() method of the
3215151378Snetchild * parent of @p dev.
3216151378Snetchild */
3217151378Snetchildint
3218151378Snetchildbus_setup_intr(device_t dev, struct resource *r, int flags,
3219151378Snetchild    driver_intr_t handler, void *arg, void **cookiep)
3220151378Snetchild{
3221151378Snetchild	int error;
3222151378Snetchild
3223151378Snetchild	if (dev->parent != 0) {
3224151378Snetchild		if ((flags &~ INTR_ENTROPY) == (INTR_TYPE_NET | INTR_MPSAFE) &&
3225151378Snetchild		    !debug_mpsafenet)
3226151378Snetchild			flags &= ~INTR_MPSAFE;
3227151378Snetchild		error = BUS_SETUP_INTR(dev->parent, dev, r, flags,
3228151378Snetchild		    handler, arg, cookiep);
3229151378Snetchild		if (error == 0) {
3230151378Snetchild			if (!(flags & (INTR_MPSAFE | INTR_FAST)))
3231151378Snetchild				device_printf(dev, "[GIANT-LOCKED]\n");
3232151378Snetchild			if (bootverbose && (flags & INTR_MPSAFE))
3233151378Snetchild				device_printf(dev, "[MPSAFE]\n");
3234151378Snetchild			if (flags & INTR_FAST)
3235151378Snetchild				device_printf(dev, "[FAST]\n");
3236151378Snetchild		}
3237151378Snetchild	} else
3238151378Snetchild		error = EINVAL;
3239151378Snetchild	return (error);
3240151378Snetchild}
3241151378Snetchild
3242151378Snetchild/**
3243151378Snetchild * @brief Wrapper function for BUS_TEARDOWN_INTR().
3244151378Snetchild *
3245151378Snetchild * This function simply calls the BUS_TEARDOWN_INTR() method of the
3246151378Snetchild * parent of @p dev.
3247151378Snetchild */
3248151378Snetchildint
3249151378Snetchildbus_teardown_intr(device_t dev, struct resource *r, void *cookie)
3250151378Snetchild{
3251151378Snetchild	if (dev->parent == 0)
3252151378Snetchild		return (EINVAL);
3253151378Snetchild	return (BUS_TEARDOWN_INTR(dev->parent, dev, r, cookie));
3254151378Snetchild}
3255151378Snetchild
3256151378Snetchild/**
3257151378Snetchild * @brief Wrapper function for BUS_SET_RESOURCE().
3258151378Snetchild *
3259151378Snetchild * This function simply calls the BUS_SET_RESOURCE() method of the
3260151378Snetchild * parent of @p dev.
3261151378Snetchild */
3262151378Snetchildint
3263151378Snetchildbus_set_resource(device_t dev, int type, int rid,
3264151378Snetchild    u_long start, u_long count)
3265151378Snetchild{
3266151378Snetchild	return (BUS_SET_RESOURCE(device_get_parent(dev), dev, type, rid,
3267151378Snetchild	    start, count));
3268151378Snetchild}
3269151378Snetchild
3270151378Snetchild/**
3271151378Snetchild * @brief Wrapper function for BUS_GET_RESOURCE().
3272151378Snetchild *
3273151378Snetchild * This function simply calls the BUS_GET_RESOURCE() method of the
3274151378Snetchild * parent of @p dev.
3275151378Snetchild */
3276151378Snetchildint
3277151378Snetchildbus_get_resource(device_t dev, int type, int rid,
3278151378Snetchild    u_long *startp, u_long *countp)
3279151378Snetchild{
3280151378Snetchild	return (BUS_GET_RESOURCE(device_get_parent(dev), dev, type, rid,
3281151378Snetchild	    startp, countp));
3282151378Snetchild}
3283151378Snetchild
3284151378Snetchild/**
3285151378Snetchild * @brief Wrapper function for BUS_GET_RESOURCE().
3286151378Snetchild *
3287151378Snetchild * This function simply calls the BUS_GET_RESOURCE() method of the
3288151378Snetchild * parent of @p dev and returns the start value.
3289151378Snetchild */
3290151378Snetchildu_long
3291151378Snetchildbus_get_resource_start(device_t dev, int type, int rid)
3292151378Snetchild{
3293151378Snetchild	u_long start, count;
3294151378Snetchild	int error;
3295151378Snetchild
3296151378Snetchild	error = BUS_GET_RESOURCE(device_get_parent(dev), dev, type, rid,
3297151378Snetchild	    &start, &count);
3298151378Snetchild	if (error)
3299151378Snetchild		return (0);
3300151378Snetchild	return (start);
3301151378Snetchild}
3302151378Snetchild
3303151378Snetchild/**
3304151378Snetchild * @brief Wrapper function for BUS_GET_RESOURCE().
3305151378Snetchild *
3306151378Snetchild * This function simply calls the BUS_GET_RESOURCE() method of the
3307151378Snetchild * parent of @p dev and returns the count value.
3308151378Snetchild */
3309151378Snetchildu_long
3310151378Snetchildbus_get_resource_count(device_t dev, int type, int rid)
3311151378Snetchild{
3312151378Snetchild	u_long start, count;
3313151378Snetchild	int error;
3314151378Snetchild
3315151378Snetchild	error = BUS_GET_RESOURCE(device_get_parent(dev), dev, type, rid,
3316151378Snetchild	    &start, &count);
3317151378Snetchild	if (error)
3318151378Snetchild		return (0);
3319151378Snetchild	return (count);
3320151378Snetchild}
3321151378Snetchild
3322151378Snetchild/**
3323151378Snetchild * @brief Wrapper function for BUS_DELETE_RESOURCE().
3324151378Snetchild *
3325151378Snetchild * This function simply calls the BUS_DELETE_RESOURCE() method of the
3326151378Snetchild * parent of @p dev.
3327151378Snetchild */
3328151378Snetchildvoid
3329151378Snetchildbus_delete_resource(device_t dev, int type, int rid)
3330151378Snetchild{
3331151378Snetchild	BUS_DELETE_RESOURCE(device_get_parent(dev), dev, type, rid);
3332151378Snetchild}
3333151378Snetchild
3334151378Snetchild/**
3335151378Snetchild * @brief Wrapper function for BUS_CHILD_PRESENT().
3336151378Snetchild *
3337151378Snetchild * This function simply calls the BUS_CHILD_PRESENT() method of the
3338151378Snetchild * parent of @p dev.
3339151378Snetchild */
3340151378Snetchildint
3341151378Snetchildbus_child_present(device_t child)
3342151378Snetchild{
3343151378Snetchild	return (BUS_CHILD_PRESENT(device_get_parent(child), child));
3344151378Snetchild}
3345151378Snetchild
3346151378Snetchild/**
3347151378Snetchild * @brief Wrapper function for BUS_CHILD_PNPINFO_STR().
3348151378Snetchild *
3349151378Snetchild * This function simply calls the BUS_CHILD_PNPINFO_STR() method of the
3350151378Snetchild * parent of @p dev.
3351151378Snetchild */
3352151378Snetchildint
3353151378Snetchildbus_child_pnpinfo_str(device_t child, char *buf, size_t buflen)
3354151378Snetchild{
3355151378Snetchild	device_t parent;
3356151378Snetchild
3357151378Snetchild	parent = device_get_parent(child);
3358151378Snetchild	if (parent == NULL) {
3359151378Snetchild		*buf = '\0';
3360151378Snetchild		return (0);
3361151378Snetchild	}
3362151378Snetchild	return (BUS_CHILD_PNPINFO_STR(parent, child, buf, buflen));
3363151378Snetchild}
3364151378Snetchild
3365151378Snetchild/**
3366151378Snetchild * @brief Wrapper function for BUS_CHILD_LOCATION_STR().
3367151378Snetchild *
3368151378Snetchild * This function simply calls the BUS_CHILD_LOCATION_STR() method of the
3369151378Snetchild * parent of @p dev.
3370151378Snetchild */
3371151378Snetchildint
3372151378Snetchildbus_child_location_str(device_t child, char *buf, size_t buflen)
3373151378Snetchild{
3374151378Snetchild	device_t parent;
3375151378Snetchild
3376151378Snetchild	parent = device_get_parent(child);
3377151378Snetchild	if (parent == NULL) {
3378151378Snetchild		*buf = '\0';
3379151378Snetchild		return (0);
3380151378Snetchild	}
3381151378Snetchild	return (BUS_CHILD_LOCATION_STR(parent, child, buf, buflen));
3382151378Snetchild}
3383151378Snetchild
3384151378Snetchildstatic int
3385151378Snetchildroot_print_child(device_t dev, device_t child)
3386151378Snetchild{
3387151378Snetchild	int	retval = 0;
3388151378Snetchild
3389151378Snetchild	retval += bus_print_child_header(dev, child);
3390151378Snetchild	retval += printf("\n");
3391151378Snetchild
3392151378Snetchild	return (retval);
3393151378Snetchild}
3394151378Snetchild
3395151378Snetchildstatic int
3396151378Snetchildroot_setup_intr(device_t dev, device_t child, driver_intr_t *intr, void *arg,
3397151378Snetchild    void **cookiep)
3398151378Snetchild{
3399151378Snetchild	/*
3400151378Snetchild	 * If an interrupt mapping gets to here something bad has happened.
3401151378Snetchild	 */
3402151378Snetchild	panic("root_setup_intr");
3403151378Snetchild}
3404151378Snetchild
3405151378Snetchild/*
3406151378Snetchild * If we get here, assume that the device is permanant and really is
3407151378Snetchild * present in the system.  Removable bus drivers are expected to intercept
3408151378Snetchild * this call long before it gets here.  We return -1 so that drivers that
3409151378Snetchild * really care can check vs -1 or some ERRNO returned higher in the food
3410151378Snetchild * chain.
3411151378Snetchild */
3412151378Snetchildstatic int
3413151378Snetchildroot_child_present(device_t dev, device_t child)
3414151378Snetchild{
3415151378Snetchild	return (-1);
3416151378Snetchild}
3417151378Snetchild
3418151378Snetchildstatic kobj_method_t root_methods[] = {
3419151378Snetchild	/* Device interface */
3420151378Snetchild	KOBJMETHOD(device_shutdown,	bus_generic_shutdown),
3421151378Snetchild	KOBJMETHOD(device_suspend,	bus_generic_suspend),
3422151378Snetchild	KOBJMETHOD(device_resume,	bus_generic_resume),
3423151378Snetchild
3424151378Snetchild	/* Bus interface */
3425151378Snetchild	KOBJMETHOD(bus_print_child,	root_print_child),
3426151378Snetchild	KOBJMETHOD(bus_read_ivar,	bus_generic_read_ivar),
3427151378Snetchild	KOBJMETHOD(bus_write_ivar,	bus_generic_write_ivar),
3428151378Snetchild	KOBJMETHOD(bus_setup_intr,	root_setup_intr),
3429151378Snetchild	KOBJMETHOD(bus_child_present,	root_child_present),
3430151378Snetchild
3431151378Snetchild	{ 0, 0 }
3432151378Snetchild};
3433151378Snetchild
3434151378Snetchildstatic driver_t root_driver = {
3435151378Snetchild	"root",
3436151378Snetchild	root_methods,
3437151378Snetchild	1,			/* no softc */
3438151378Snetchild};
3439151378Snetchild
3440151378Snetchilddevice_t	root_bus;
3441151378Snetchilddevclass_t	root_devclass;
3442151378Snetchild
3443151378Snetchildstatic int
3444151378Snetchildroot_bus_module_handler(module_t mod, int what, void* arg)
3445151378Snetchild{
3446151378Snetchild	switch (what) {
3447151378Snetchild	case MOD_LOAD:
3448151378Snetchild		TAILQ_INIT(&bus_data_devices);
3449151378Snetchild		kobj_class_compile((kobj_class_t) &root_driver);
3450151378Snetchild		root_bus = make_device(NULL, "root", 0);
3451151378Snetchild		root_bus->desc = "System root bus";
3452151378Snetchild		kobj_init((kobj_t) root_bus, (kobj_class_t) &root_driver);
3453151378Snetchild		root_bus->driver = &root_driver;
3454151378Snetchild		root_bus->state = DS_ATTACHED;
3455151378Snetchild		root_devclass = devclass_find_internal("root", 0, FALSE);
3456151378Snetchild		devinit();
3457151378Snetchild		return (0);
3458151378Snetchild
3459151378Snetchild	case MOD_SHUTDOWN:
3460151378Snetchild		device_shutdown(root_bus);
3461151378Snetchild		return (0);
3462151378Snetchild	default:
3463151378Snetchild		return (EOPNOTSUPP);
3464151378Snetchild	}
3465151378Snetchild
3466151378Snetchild	return (0);
3467151378Snetchild}
3468151378Snetchild
3469151378Snetchildstatic moduledata_t root_bus_mod = {
3470151378Snetchild	"rootbus",
3471151378Snetchild	root_bus_module_handler,
3472151378Snetchild	0
3473151378Snetchild};
3474151378SnetchildDECLARE_MODULE(rootbus, root_bus_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
3475151378Snetchild
3476151378Snetchild/**
3477151378Snetchild * @brief Automatically configure devices
3478151378Snetchild *
3479151378Snetchild * This function begins the autoconfiguration process by calling
3480151378Snetchild * device_probe_and_attach() for each child of the @c root0 device.
3481151378Snetchild */
3482151378Snetchildvoid
3483151378Snetchildroot_bus_configure(void)
3484151378Snetchild{
3485151378Snetchild	device_t dev;
3486151378Snetchild
3487151378Snetchild	PDEBUG(("."));
3488151378Snetchild
3489151378Snetchild	TAILQ_FOREACH(dev, &root_bus->children, link) {
3490151378Snetchild		device_probe_and_attach(dev);
3491151378Snetchild	}
3492151378Snetchild}
3493151378Snetchild
3494151378Snetchild/**
3495151378Snetchild * @brief Module handler for registering device drivers
3496151378Snetchild *
3497151378Snetchild * This module handler is used to automatically register device
3498151378Snetchild * drivers when modules are loaded. If @p what is MOD_LOAD, it calls
3499151378Snetchild * devclass_add_driver() for the driver described by the
3500151378Snetchild * driver_module_data structure pointed to by @p arg
3501151378Snetchild */
3502151378Snetchildint
3503151378Snetchilddriver_module_handler(module_t mod, int what, void *arg)
3504151378Snetchild{
3505151378Snetchild	int error;
3506151378Snetchild	struct driver_module_data *dmd;
3507151378Snetchild	devclass_t bus_devclass;
3508151378Snetchild	kobj_class_t driver;
3509151378Snetchild
3510151378Snetchild	dmd = (struct driver_module_data *)arg;
3511151378Snetchild	bus_devclass = devclass_find_internal(dmd->dmd_busname, 0, TRUE);
3512151378Snetchild	error = 0;
3513151378Snetchild
3514151378Snetchild	switch (what) {
3515151378Snetchild	case MOD_LOAD:
3516151378Snetchild		if (dmd->dmd_chainevh)
3517151378Snetchild			error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg);
3518151378Snetchild
3519151378Snetchild		driver = dmd->dmd_driver;
3520151378Snetchild		PDEBUG(("Loading module: driver %s on bus %s",
3521151378Snetchild		    DRIVERNAME(driver), dmd->dmd_busname));
3522151378Snetchild		error = devclass_add_driver(bus_devclass, driver);
3523151378Snetchild		if (error)
3524151378Snetchild			break;
3525151378Snetchild
3526151378Snetchild		/*
3527151378Snetchild		 * If the driver has any base classes, make the
3528151378Snetchild		 * devclass inherit from the devclass of the driver's
3529151378Snetchild		 * first base class. This will allow the system to
3530151378Snetchild		 * search for drivers in both devclasses for children
3531151378Snetchild		 * of a device using this driver.
3532151378Snetchild		 */
3533151378Snetchild		if (driver->baseclasses) {
3534151378Snetchild			const char *parentname;
3535151378Snetchild			parentname = driver->baseclasses[0]->name;
3536151378Snetchild			*dmd->dmd_devclass =
3537151378Snetchild				devclass_find_internal(driver->name,
3538151378Snetchild				    parentname, TRUE);
3539151378Snetchild		} else {
3540151378Snetchild			*dmd->dmd_devclass =
3541151378Snetchild				devclass_find_internal(driver->name, 0, TRUE);
3542151378Snetchild		}
3543151378Snetchild		break;
3544151378Snetchild
3545151378Snetchild	case MOD_UNLOAD:
3546151378Snetchild		PDEBUG(("Unloading module: driver %s from bus %s",
3547151378Snetchild		    DRIVERNAME(dmd->dmd_driver),
3548151378Snetchild		    dmd->dmd_busname));
3549151378Snetchild		error = devclass_delete_driver(bus_devclass,
3550151378Snetchild		    dmd->dmd_driver);
3551151378Snetchild
3552151378Snetchild		if (!error && dmd->dmd_chainevh)
3553151378Snetchild			error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg);
3554151378Snetchild		break;
3555151378Snetchild	default:
3556151378Snetchild		error = EOPNOTSUPP;
3557151378Snetchild		break;
3558151378Snetchild	}
3559151378Snetchild
3560151378Snetchild	return (error);
3561151378Snetchild}
3562151378Snetchild
3563151378Snetchild#ifdef BUS_DEBUG
3564151378Snetchild
3565151378Snetchild/* the _short versions avoid iteration by not calling anything that prints
3566151378Snetchild * more than oneliners. I love oneliners.
3567151378Snetchild */
3568151378Snetchild
3569151378Snetchildstatic void
3570151378Snetchildprint_device_short(device_t dev, int indent)
3571151378Snetchild{
3572151378Snetchild	if (!dev)
3573151378Snetchild		return;
3574151378Snetchild
3575151378Snetchild	indentprintf(("device %d: <%s> %sparent,%schildren,%s%s%s%s%s,%sivars,%ssoftc,busy=%d\n",
3576151378Snetchild	    dev->unit, dev->desc,
3577151378Snetchild	    (dev->parent? "":"no "),
3578151378Snetchild	    (TAILQ_EMPTY(&dev->children)? "no ":""),
3579151378Snetchild	    (dev->flags&DF_ENABLED? "enabled,":"disabled,"),
3580151378Snetchild	    (dev->flags&DF_FIXEDCLASS? "fixed,":""),
3581151378Snetchild	    (dev->flags&DF_WILDCARD? "wildcard,":""),
3582151378Snetchild	    (dev->flags&DF_DESCMALLOCED? "descmalloced,":""),
3583151378Snetchild	    (dev->flags&DF_REBID? "rebiddable,":""),
3584151378Snetchild	    (dev->ivars? "":"no "),
3585151378Snetchild	    (dev->softc? "":"no "),
3586151378Snetchild	    dev->busy));
3587151378Snetchild}
3588151378Snetchild
3589151378Snetchildstatic void
3590151378Snetchildprint_device(device_t dev, int indent)
3591151378Snetchild{
3592151378Snetchild	if (!dev)
3593151378Snetchild		return;
3594151378Snetchild
3595151378Snetchild	print_device_short(dev, indent);
3596151378Snetchild
3597151378Snetchild	indentprintf(("Parent:\n"));
3598151378Snetchild	print_device_short(dev->parent, indent+1);
3599151378Snetchild	indentprintf(("Driver:\n"));
3600151378Snetchild	print_driver_short(dev->driver, indent+1);
3601151378Snetchild	indentprintf(("Devclass:\n"));
3602151378Snetchild	print_devclass_short(dev->devclass, indent+1);
3603151378Snetchild}
3604151378Snetchild
3605151378Snetchildvoid
3606151378Snetchildprint_device_tree_short(device_t dev, int indent)
3607151378Snetchild/* print the device and all its children (indented) */
3608151378Snetchild{
3609151378Snetchild	device_t child;
3610151378Snetchild
3611151378Snetchild	if (!dev)
3612151378Snetchild		return;
3613151378Snetchild
3614151378Snetchild	print_device_short(dev, indent);
3615151378Snetchild
3616151378Snetchild	TAILQ_FOREACH(child, &dev->children, link) {
3617151378Snetchild		print_device_tree_short(child, indent+1);
3618151378Snetchild	}
3619151378Snetchild}
3620151378Snetchild
3621151378Snetchildvoid
3622151378Snetchildprint_device_tree(device_t dev, int indent)
3623151378Snetchild/* print the device and all its children (indented) */
3624151378Snetchild{
3625151378Snetchild	device_t child;
3626151378Snetchild
3627151378Snetchild	if (!dev)
3628151378Snetchild		return;
3629151378Snetchild
3630151378Snetchild	print_device(dev, indent);
3631151378Snetchild
3632151378Snetchild	TAILQ_FOREACH(child, &dev->children, link) {
3633151378Snetchild		print_device_tree(child, indent+1);
3634151378Snetchild	}
3635151378Snetchild}
3636151378Snetchild
3637151378Snetchildstatic void
3638151378Snetchildprint_driver_short(driver_t *driver, int indent)
3639151378Snetchild{
3640151378Snetchild	if (!driver)
3641151378Snetchild		return;
3642151378Snetchild
3643151378Snetchild	indentprintf(("driver %s: softc size = %zd\n",
3644151378Snetchild	    driver->name, driver->size));
3645151378Snetchild}
3646151378Snetchild
3647151378Snetchildstatic void
3648151378Snetchildprint_driver(driver_t *driver, int indent)
3649151378Snetchild{
3650151378Snetchild	if (!driver)
3651151378Snetchild		return;
3652151378Snetchild
3653151378Snetchild	print_driver_short(driver, indent);
3654151378Snetchild}
3655151378Snetchild
3656151378Snetchild
3657151378Snetchildstatic void
3658151378Snetchildprint_driver_list(driver_list_t drivers, int indent)
3659151378Snetchild{
3660151378Snetchild	driverlink_t driver;
3661151378Snetchild
3662151378Snetchild	TAILQ_FOREACH(driver, &drivers, link) {
3663151378Snetchild		print_driver(driver->driver, indent);
3664151378Snetchild	}
3665151378Snetchild}
3666151378Snetchild
3667151378Snetchildstatic void
3668151378Snetchildprint_devclass_short(devclass_t dc, int indent)
3669151378Snetchild{
3670151378Snetchild	if ( !dc )
3671151378Snetchild		return;
3672151378Snetchild
3673151378Snetchild	indentprintf(("devclass %s: max units = %d\n", dc->name, dc->maxunit));
3674151378Snetchild}
3675151378Snetchild
3676151378Snetchildstatic void
3677151378Snetchildprint_devclass(devclass_t dc, int indent)
3678151378Snetchild{
3679151378Snetchild	int i;
3680151378Snetchild
3681151378Snetchild	if ( !dc )
3682151378Snetchild		return;
3683151378Snetchild
3684151378Snetchild	print_devclass_short(dc, indent);
3685151378Snetchild	indentprintf(("Drivers:\n"));
3686151378Snetchild	print_driver_list(dc->drivers, indent+1);
3687151378Snetchild
3688151378Snetchild	indentprintf(("Devices:\n"));
3689151378Snetchild	for (i = 0; i < dc->maxunit; i++)
3690151378Snetchild		if (dc->devices[i])
3691151378Snetchild			print_device(dc->devices[i], indent+1);
3692151378Snetchild}
3693151378Snetchild
3694151378Snetchildvoid
3695151378Snetchildprint_devclass_list_short(void)
3696151378Snetchild{
3697151378Snetchild	devclass_t dc;
3698151378Snetchild
3699151378Snetchild	printf("Short listing of devclasses, drivers & devices:\n");
3700151378Snetchild	TAILQ_FOREACH(dc, &devclasses, link) {
3701151378Snetchild		print_devclass_short(dc, 0);
3702151378Snetchild	}
3703151378Snetchild}
3704151378Snetchild
3705151378Snetchildvoid
3706151378Snetchildprint_devclass_list(void)
3707151378Snetchild{
3708151378Snetchild	devclass_t dc;
3709151378Snetchild
3710151378Snetchild	printf("Full listing of devclasses, drivers & devices:\n");
3711151378Snetchild	TAILQ_FOREACH(dc, &devclasses, link) {
3712151378Snetchild		print_devclass(dc, 0);
3713151378Snetchild	}
3714151378Snetchild}
3715151378Snetchild
3716151378Snetchild#endif
3717151378Snetchild
3718151378Snetchild/*
3719151378Snetchild * User-space access to the device tree.
3720151378Snetchild *
3721151378Snetchild * We implement a small set of nodes:
3722151378Snetchild *
3723151378Snetchild * hw.bus			Single integer read method to obtain the
3724151378Snetchild *				current generation count.
3725151378Snetchild * hw.bus.devices		Reads the entire device tree in flat space.
3726151378Snetchild * hw.bus.rman			Resource manager interface
3727151378Snetchild *
3728151378Snetchild * We might like to add the ability to scan devclasses and/or drivers to
3729151378Snetchild * determine what else is currently loaded/available.
3730151378Snetchild */
3731151378Snetchild
3732151378Snetchildstatic int
3733151378Snetchildsysctl_bus(SYSCTL_HANDLER_ARGS)
3734151378Snetchild{
3735151378Snetchild	struct u_businfo	ubus;
3736151378Snetchild
3737151378Snetchild	ubus.ub_version = BUS_USER_VERSION;
3738151378Snetchild	ubus.ub_generation = bus_data_generation;
3739151378Snetchild
3740151378Snetchild	return (SYSCTL_OUT(req, &ubus, sizeof(ubus)));
3741151378Snetchild}
3742151378SnetchildSYSCTL_NODE(_hw_bus, OID_AUTO, info, CTLFLAG_RW, sysctl_bus,
3743151378Snetchild    "bus-related data");
3744151378Snetchild
3745151378Snetchildstatic int
3746151378Snetchildsysctl_devices(SYSCTL_HANDLER_ARGS)
3747151378Snetchild{
3748151378Snetchild	int			*name = (int *)arg1;
3749151378Snetchild	u_int			namelen = arg2;
3750151378Snetchild	int			index;
3751151378Snetchild	struct device		*dev;
3752151378Snetchild	struct u_device		udev;	/* XXX this is a bit big */
3753151378Snetchild	int			error;
3754151378Snetchild
3755151378Snetchild	if (namelen != 2)
3756151378Snetchild		return (EINVAL);
3757151378Snetchild
3758151378Snetchild	if (bus_data_generation_check(name[0]))
3759151378Snetchild		return (EINVAL);
3760151378Snetchild
3761151378Snetchild	index = name[1];
3762151378Snetchild
3763151378Snetchild	/*
3764151378Snetchild	 * Scan the list of devices, looking for the requested index.
3765151378Snetchild	 */
3766151378Snetchild	TAILQ_FOREACH(dev, &bus_data_devices, devlink) {
3767151378Snetchild		if (index-- == 0)
3768151378Snetchild			break;
3769151378Snetchild	}
3770151378Snetchild	if (dev == NULL)
3771151378Snetchild		return (ENOENT);
3772151378Snetchild
3773151378Snetchild	/*
3774151378Snetchild	 * Populate the return array.
3775151378Snetchild	 */
3776151378Snetchild	udev.dv_handle = (uintptr_t)dev;
3777151378Snetchild	udev.dv_parent = (uintptr_t)dev->parent;
3778151378Snetchild	if (dev->nameunit == NULL)
3779151378Snetchild		udev.dv_name[0] = '\0';
3780151378Snetchild	else
3781151378Snetchild		strlcpy(udev.dv_name, dev->nameunit, sizeof(udev.dv_name));
3782151378Snetchild
3783151378Snetchild	if (dev->desc == NULL)
3784151378Snetchild		udev.dv_desc[0] = '\0';
3785151378Snetchild	else
3786151378Snetchild		strlcpy(udev.dv_desc, dev->desc, sizeof(udev.dv_desc));
3787151378Snetchild	if (dev->driver == NULL || dev->driver->name == NULL)
3788151378Snetchild		udev.dv_drivername[0] = '\0';
3789151378Snetchild	else
3790151378Snetchild		strlcpy(udev.dv_drivername, dev->driver->name,
3791151378Snetchild		    sizeof(udev.dv_drivername));
3792151378Snetchild	udev.dv_pnpinfo[0] = '\0';
3793151378Snetchild	udev.dv_location[0] = '\0';
3794153939Snetchild	bus_child_pnpinfo_str(dev, udev.dv_pnpinfo, sizeof(udev.dv_pnpinfo));
3795153939Snetchild	bus_child_location_str(dev, udev.dv_location, sizeof(udev.dv_location));
3796153939Snetchild	udev.dv_devflags = dev->devflags;
3797153939Snetchild	udev.dv_flags = dev->flags;
3798153939Snetchild	udev.dv_state = dev->state;
3799153939Snetchild	error = SYSCTL_OUT(req, &udev, sizeof(udev));
3800153939Snetchild	return (error);
3801153939Snetchild}
3802153939Snetchild
3803153939SnetchildSYSCTL_NODE(_hw_bus, OID_AUTO, devices, CTLFLAG_RD, sysctl_devices,
3804153939Snetchild    "system device tree");
3805153939Snetchild
3806153939Snetchild/*
3807153939Snetchild * Sysctl interface for scanning the resource lists.
3808153939Snetchild *
3809153939Snetchild * We take two input parameters; the index into the list of resource
3810153939Snetchild * managers, and the resource offset into the list.
3811153939Snetchild */
3812153939Snetchildstatic int
3813151378Snetchildsysctl_rman(SYSCTL_HANDLER_ARGS)
3814151378Snetchild{
3815151378Snetchild	int			*name = (int *)arg1;
3816151378Snetchild	u_int			namelen = arg2;
3817151378Snetchild	int			rman_idx, res_idx;
3818151378Snetchild	struct rman		*rm;
3819151378Snetchild	struct resource		*res;
3820151378Snetchild	struct u_rman		urm;
3821151378Snetchild	struct u_resource	ures;
3822151378Snetchild	int			error;
3823151378Snetchild
3824151378Snetchild	if (namelen != 3)
3825151378Snetchild		return (EINVAL);
3826151378Snetchild
3827151378Snetchild	if (bus_data_generation_check(name[0]))
3828151378Snetchild		return (EINVAL);
3829151378Snetchild	rman_idx = name[1];
3830151378Snetchild	res_idx = name[2];
3831151378Snetchild
3832151378Snetchild	/*
3833151378Snetchild	 * Find the indexed resource manager
3834151378Snetchild	 */
3835151378Snetchild	TAILQ_FOREACH(rm, &rman_head, rm_link) {
3836151378Snetchild		if (rman_idx-- == 0)
3837151378Snetchild			break;
3838151378Snetchild	}
3839151378Snetchild	if (rm == NULL)
3840151378Snetchild		return (ENOENT);
3841151378Snetchild
3842151378Snetchild	/*
3843151378Snetchild	 * If the resource index is -1, we want details on the
3844151378Snetchild	 * resource manager.
3845151378Snetchild	 */
3846151378Snetchild	if (res_idx == -1) {
3847151378Snetchild		urm.rm_handle = (uintptr_t)rm;
3848151378Snetchild		strlcpy(urm.rm_descr, rm->rm_descr, RM_TEXTLEN);
3849151378Snetchild		urm.rm_start = rm->rm_start;
3850151378Snetchild		urm.rm_size = rm->rm_end - rm->rm_start + 1;
3851151378Snetchild		urm.rm_type = rm->rm_type;
3852151378Snetchild
3853151378Snetchild		error = SYSCTL_OUT(req, &urm, sizeof(urm));
3854151378Snetchild		return (error);
3855151378Snetchild	}
3856151378Snetchild
3857151378Snetchild	/*
3858151378Snetchild	 * Find the indexed resource and return it.
3859151378Snetchild	 */
3860151378Snetchild	TAILQ_FOREACH(res, &rm->rm_list, r_link) {
3861151378Snetchild		if (res_idx-- == 0) {
3862151378Snetchild			ures.r_handle = (uintptr_t)res;
3863151378Snetchild			ures.r_parent = (uintptr_t)res->r_rm;
3864151378Snetchild			ures.r_device = (uintptr_t)res->r_dev;
3865151378Snetchild			if (res->r_dev != NULL) {
3866151378Snetchild				if (device_get_name(res->r_dev) != NULL) {
3867151378Snetchild					snprintf(ures.r_devname, RM_TEXTLEN,
3868151378Snetchild					    "%s%d",
3869151378Snetchild					    device_get_name(res->r_dev),
3870151378Snetchild					    device_get_unit(res->r_dev));
3871151378Snetchild				} else {
3872151378Snetchild					strlcpy(ures.r_devname, "nomatch",
3873151378Snetchild					    RM_TEXTLEN);
3874151378Snetchild				}
3875151378Snetchild			} else {
3876151378Snetchild				ures.r_devname[0] = '\0';
3877151378Snetchild			}
3878151378Snetchild			ures.r_start = res->r_start;
3879151378Snetchild			ures.r_size = res->r_end - res->r_start + 1;
3880151378Snetchild			ures.r_flags = res->r_flags;
3881151378Snetchild
3882153939Snetchild			error = SYSCTL_OUT(req, &ures, sizeof(ures));
3883153939Snetchild			return (error);
3884153939Snetchild		}
3885153939Snetchild	}
3886153939Snetchild	return (ENOENT);
3887153939Snetchild}
3888153939Snetchild
3889153939SnetchildSYSCTL_NODE(_hw_bus, OID_AUTO, rman, CTLFLAG_RD, sysctl_rman,
3890153939Snetchild    "kernel resource manager");
3891153939Snetchild
3892153939Snetchildint
3893153939Snetchildbus_data_generation_check(int generation)
3894153939Snetchild{
3895153939Snetchild	if (generation != bus_data_generation)
3896153939Snetchild		return (1);
3897153939Snetchild
3898153939Snetchild	/* XXX generate optimised lists here? */
3899153939Snetchild	return (0);
3900153939Snetchild}
3901153939Snetchild
3902153939Snetchildvoid
3903153939Snetchildbus_data_generation_update(void)
3904153939Snetchild{
3905153939Snetchild	bus_data_generation++;
3906153939Snetchild}
3907153939Snetchild