xref: /netbsd-src/sys/sys/device.h (revision f82d7874c259b2a6cc59b714f844919f32bf7b51)
1 /* $NetBSD: device.h,v 1.109 2008/03/12 18:02:22 dyoung Exp $ */
2 
3 /*
4  * Copyright (c) 1996, 2000 Christopher G. Demetriou
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *          This product includes software developed for the
18  *          NetBSD Project.  See http://www.NetBSD.org/ for
19  *          information about NetBSD.
20  * 4. The name of the author may not be used to endorse or promote products
21  *    derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34  * --(license Id: LICENSE.proto,v 1.1 2000/06/13 21:40:26 cgd Exp )--
35  */
36 
37 /*
38  * Copyright (c) 1992, 1993
39  *	The Regents of the University of California.  All rights reserved.
40  *
41  * This software was developed by the Computer Systems Engineering group
42  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
43  * contributed to Berkeley.
44  *
45  * All advertising materials mentioning features or use of this software
46  * must display the following acknowledgement:
47  *	This product includes software developed by the University of
48  *	California, Lawrence Berkeley Laboratories.
49  *
50  * Redistribution and use in source and binary forms, with or without
51  * modification, are permitted provided that the following conditions
52  * are met:
53  * 1. Redistributions of source code must retain the above copyright
54  *    notice, this list of conditions and the following disclaimer.
55  * 2. Redistributions in binary form must reproduce the above copyright
56  *    notice, this list of conditions and the following disclaimer in the
57  *    documentation and/or other materials provided with the distribution.
58  * 3. Neither the name of the University nor the names of its contributors
59  *    may be used to endorse or promote products derived from this software
60  *    without specific prior written permission.
61  *
62  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
63  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
64  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
65  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
66  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
67  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
68  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
69  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
70  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
71  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
72  * SUCH DAMAGE.
73  *
74  *	@(#)device.h	8.2 (Berkeley) 2/17/94
75  */
76 
77 #ifndef _SYS_DEVICE_H_
78 #define	_SYS_DEVICE_H_
79 
80 #include <sys/evcnt.h>
81 #include <sys/queue.h>
82 
83 typedef struct device *device_t;
84 #ifdef _KERNEL
85 #include <sys/pmf.h>
86 #endif
87 
88 #include <prop/proplib.h>
89 
90 /*
91  * Minimal device structures.
92  * Note that all ``system'' device types are listed here.
93  */
94 typedef enum devclass {
95 	DV_DULL,		/* generic, no special info */
96 	DV_CPU,			/* CPU (carries resource utilization) */
97 	DV_DISK,		/* disk drive (label, etc) */
98 	DV_IFNET,		/* network interface */
99 	DV_TAPE,		/* tape device */
100 	DV_TTY,			/* serial line interface (?) */
101 	DV_AUDIODEV,		/* audio device */
102 	DV_DISPLAYDEV,		/* display device */
103 	DV_BUS			/* bus device */
104 } devclass_t;
105 
106 /*
107  * Actions for ca_activate.
108  */
109 typedef enum devact {
110 	DVACT_ACTIVATE,		/* activate the device */
111 	DVACT_DEACTIVATE	/* deactivate the device */
112 } devact_t;
113 
114 typedef enum {
115 	DVA_SYSTEM,
116 	DVA_HARDWARE
117 } devactive_t;
118 
119 typedef struct cfdata *cfdata_t;
120 typedef struct cfdriver *cfdriver_t;
121 typedef struct cfattach *cfattach_t;
122 
123 struct device {
124 	devclass_t	dv_class;	/* this device's classification */
125 	TAILQ_ENTRY(device) dv_list;	/* entry on list of all devices */
126 	cfdata_t	dv_cfdata;	/* config data that found us
127 					   (NULL if pseudo-device) */
128 	cfdriver_t	dv_cfdriver;	/* our cfdriver */
129 	cfattach_t	dv_cfattach;	/* our cfattach */
130 	int		dv_unit;	/* device unit number */
131 	char		dv_xname[16];	/* external name (name + unit) */
132 	device_t	dv_parent;	/* pointer to parent device
133 					   (NULL if pseudo- or root node) */
134 	int		dv_depth;	/* number of parents until root */
135 	int		dv_flags;	/* misc. flags; see below */
136 	void		*dv_private;	/* this device's private storage */
137 	int		*dv_locators;	/* our actual locators (optional) */
138 	prop_dictionary_t dv_properties;/* properties dictionary */
139 
140 	size_t		dv_activity_count;
141 	void		(**dv_activity_handlers)(device_t, devactive_t);
142 
143 	bool		(*dv_driver_suspend)(device_t PMF_FN_PROTO);
144 	bool		(*dv_driver_resume)(device_t PMF_FN_PROTO);
145 	bool		(*dv_driver_shutdown)(device_t, int);
146 	bool		(*dv_driver_child_register)(device_t);
147 
148 	void		*dv_bus_private;
149 	bool		(*dv_bus_suspend)(device_t PMF_FN_PROTO);
150 	bool		(*dv_bus_resume)(device_t PMF_FN_PROTO);
151 	bool		(*dv_bus_shutdown)(device_t, int);
152 	void		(*dv_bus_deregister)(device_t);
153 
154 	void		*dv_class_private;
155 	bool		(*dv_class_suspend)(device_t PMF_FN_PROTO);
156 	bool		(*dv_class_resume)(device_t PMF_FN_PROTO);
157 	void		(*dv_class_deregister)(device_t);
158 
159 	void		*dv_pmf_private;
160 };
161 
162 /* dv_flags */
163 #define	DVF_ACTIVE		0x0001	/* device is activated */
164 #define	DVF_PRIV_ALLOC		0x0002	/* device private storage != device */
165 #define	DVF_POWER_HANDLERS	0x0004	/* device has suspend/resume support */
166 #define	DVF_CLASS_SUSPENDED	0x0008	/* device class suspend was called */
167 #define	DVF_DRIVER_SUSPENDED	0x0010	/* device driver suspend was called */
168 #define	DVF_BUS_SUSPENDED	0x0020	/* device bus suspend was called */
169 #define	DVF_SELF_SUSPENDED	0x0040	/* device suspended itself */
170 
171 TAILQ_HEAD(devicelist, device);
172 
173 enum deviter_flags {
174 	  DEVITER_F_RW =		0x1
175 	, DEVITER_F_SHUTDOWN =		0x2
176 	, DEVITER_F_LEAVES_FIRST =	0x4
177 	, DEVITER_F_ROOT_FIRST =	0x8
178 };
179 
180 typedef enum deviter_flags deviter_flags_t;
181 
182 struct deviter {
183 	device_t	di_prev;
184 	deviter_flags_t	di_flags;
185 	int		di_curdepth;
186 	int		di_maxdepth;
187 };
188 
189 typedef struct deviter deviter_t;
190 
191 /*
192  * Description of a locator, as part of interface attribute definitions.
193  */
194 struct cflocdesc {
195 	const char *cld_name;
196 	const char *cld_defaultstr; /* NULL if no default */
197 	int cld_default;
198 };
199 
200 /*
201  * Description of an interface attribute, provided by potential
202  * parent device drivers, referred to by child device configuration data.
203  */
204 struct cfiattrdata {
205 	const char *ci_name;
206 	int ci_loclen;
207 	const struct cflocdesc ci_locdesc[
208 #if defined(__GNUC__) && __GNUC__ <= 2
209 		0
210 #endif
211 	];
212 };
213 
214 /*
215  * Description of a configuration parent.  Each device attachment attaches
216  * to an "interface attribute", which is given in this structure.  The parent
217  * *must* carry this attribute.  Optionally, an individual device instance
218  * may also specify a specific parent device instance.
219  */
220 struct cfparent {
221 	const char *cfp_iattr;		/* interface attribute */
222 	const char *cfp_parent;		/* optional specific parent */
223 	int cfp_unit;			/* optional specific unit
224 					   (-1 to wildcard) */
225 };
226 
227 /*
228  * Configuration data (i.e., data placed in ioconf.c).
229  */
230 struct cfdata {
231 	const char *cf_name;		/* driver name */
232 	const char *cf_atname;		/* attachment name */
233 	short	cf_unit;		/* unit number */
234 	short	cf_fstate;		/* finding state (below) */
235 	int	*cf_loc;		/* locators (machine dependent) */
236 	int	cf_flags;		/* flags from config */
237 	const struct cfparent *cf_pspec;/* parent specification */
238 };
239 #define FSTATE_NOTFOUND		0	/* has not been found */
240 #define	FSTATE_FOUND		1	/* has been found */
241 #define	FSTATE_STAR		2	/* duplicable */
242 #define FSTATE_DSTAR		3	/* has not been found, and disabled */
243 #define FSTATE_DNOTFOUND	4	/* duplicate, and disabled */
244 
245 /*
246  * Multiple configuration data tables may be maintained.  This structure
247  * provides the linkage.
248  */
249 struct cftable {
250 	cfdata_t	ct_cfdata;	/* pointer to cfdata table */
251 	TAILQ_ENTRY(cftable) ct_list;	/* list linkage */
252 };
253 TAILQ_HEAD(cftablelist, cftable);
254 
255 typedef int (*cfsubmatch_t)(device_t, cfdata_t, const int *, void *);
256 
257 /*
258  * `configuration' attachment and driver (what the machine-independent
259  * autoconf uses).  As devices are found, they are applied against all
260  * the potential matches.  The one with the best match is taken, and a
261  * device structure (plus any other data desired) is allocated.  Pointers
262  * to these are placed into an array of pointers.  The array itself must
263  * be dynamic since devices can be found long after the machine is up
264  * and running.
265  *
266  * Devices can have multiple configuration attachments if they attach
267  * to different attributes (busses, or whatever), to allow specification
268  * of multiple match and attach functions.  There is only one configuration
269  * driver per driver, so that things like unit numbers and the device
270  * structure array will be shared.
271  */
272 struct cfattach {
273 	const char *ca_name;		/* name of attachment */
274 	LIST_ENTRY(cfattach) ca_list;	/* link on cfdriver's list */
275 	size_t	  ca_devsize;		/* size of dev data (for malloc) */
276 	int	  ca_flags;		/* flags for driver allocation etc */
277 	int	(*ca_match)(device_t, cfdata_t, void *);
278 	void	(*ca_attach)(device_t, device_t, void *);
279 	int	(*ca_detach)(device_t, int);
280 	int	(*ca_activate)(device_t, devact_t);
281 	/* technically, the next 2 belong into "struct cfdriver" */
282 	int	(*ca_rescan)(device_t, const char *,
283 			     const int *); /* scan for new children */
284 	void	(*ca_childdetached)(device_t, device_t);
285 };
286 LIST_HEAD(cfattachlist, cfattach);
287 
288 #define	CFATTACH_DECL2(name, ddsize, matfn, attfn, detfn, actfn, \
289 	rescanfn, chdetfn) \
290 struct cfattach __CONCAT(name,_ca) = {					\
291 	.ca_name		= ___STRING(name),			\
292 	.ca_devsize		= ddsize,				\
293 	.ca_match 		= matfn,				\
294 	.ca_attach		= attfn,				\
295 	.ca_detach		= detfn,				\
296 	.ca_activate		= actfn,				\
297 	.ca_rescan		= rescanfn,				\
298 	.ca_childdetached	= chdetfn,				\
299 }
300 
301 #define	CFATTACH_DECL(name, ddsize, matfn, attfn, detfn, actfn)		\
302 	CFATTACH_DECL2(name, ddsize, matfn, attfn, detfn, actfn, NULL, NULL)
303 
304 #define	CFATTACH_DECL2_NEW(name, ddsize, matfn, attfn, detfn, actfn, \
305 	rescanfn, chdetfn) \
306 struct cfattach __CONCAT(name,_ca) = {					\
307 	.ca_name		= ___STRING(name),			\
308 	.ca_devsize		= ddsize,				\
309 	.ca_flags		= DVF_PRIV_ALLOC,			\
310 	.ca_match 		= matfn,				\
311 	.ca_attach		= attfn,				\
312 	.ca_detach		= detfn,				\
313 	.ca_activate		= actfn,				\
314 	.ca_rescan		= rescanfn,				\
315 	.ca_childdetached	= chdetfn,				\
316 }
317 
318 #define	CFATTACH_DECL_NEW(name, ddsize, matfn, attfn, detfn, actfn)		\
319 	CFATTACH_DECL2_NEW(name, ddsize, matfn, attfn, detfn, actfn, NULL, NULL)
320 
321 /* Flags given to config_detach(), and the ca_detach function. */
322 #define	DETACH_FORCE	0x01		/* force detachment; hardware gone */
323 #define	DETACH_QUIET	0x02		/* don't print a notice */
324 
325 struct cfdriver {
326 	LIST_ENTRY(cfdriver) cd_list;	/* link on allcfdrivers */
327 	struct cfattachlist cd_attach;	/* list of all attachments */
328 	void	**cd_devs;		/* devices found */
329 	const char *cd_name;		/* device name */
330 	enum	devclass cd_class;	/* device classification */
331 	int	cd_ndevs;		/* size of cd_devs array */
332 	const struct cfiattrdata * const *cd_attrs; /* attributes provided */
333 };
334 LIST_HEAD(cfdriverlist, cfdriver);
335 
336 #define	CFDRIVER_DECL(name, class, attrs)				\
337 struct cfdriver __CONCAT(name,_cd) = {					\
338 	.cd_name		= ___STRING(name),			\
339 	.cd_class		= class,				\
340 	.cd_attrs		= attrs,				\
341 }
342 
343 /*
344  * The cfattachinit is a data structure used to associate a list of
345  * cfattach's with cfdrivers as found in the static kernel configuration.
346  */
347 struct cfattachinit {
348 	const char *cfai_name;		 /* driver name */
349 	struct cfattach * const *cfai_list;/* list of attachments */
350 };
351 /*
352  * the same, but with a non-constant list so it can be modified
353  * for LKM bookkeeping
354  */
355 struct cfattachlkminit {
356 	const char *cfai_name;		/* driver name */
357 	struct cfattach **cfai_list;	/* list of attachments */
358 };
359 
360 /*
361  * Configuration printing functions, and their return codes.  The second
362  * argument is NULL if the device was configured; otherwise it is the name
363  * of the parent device.  The return value is ignored if the device was
364  * configured, so most functions can return UNCONF unconditionally.
365  */
366 typedef int (*cfprint_t)(void *, const char *);		/* XXX const char * */
367 #define	QUIET	0		/* print nothing */
368 #define	UNCONF	1		/* print " not configured\n" */
369 #define	UNSUPP	2		/* print " not supported\n" */
370 
371 /*
372  * Pseudo-device attach information (function + number of pseudo-devs).
373  */
374 struct pdevinit {
375 	void	(*pdev_attach)(int);
376 	int	pdev_count;
377 };
378 
379 /* This allows us to wildcard a device unit. */
380 #define	DVUNIT_ANY	-1
381 
382 #ifdef _KERNEL
383 
384 extern struct cfdriverlist allcfdrivers;/* list of all cfdrivers */
385 extern struct devicelist alldevs;	/* list of all devices */
386 extern struct cftablelist allcftables;	/* list of all cfdata tables */
387 extern device_t booted_device;		/* the device we booted from */
388 extern device_t booted_wedge;		/* the wedge on that device */
389 extern int booted_partition;		/* or the partition on that device */
390 
391 extern volatile int config_pending; 	/* semaphore for mountroot */
392 
393 struct vnode *opendisk(struct device *);
394 int config_handle_wedges(struct device *, int);
395 
396 void	config_init(void);
397 void	configure(void);
398 
399 int	config_cfdriver_attach(struct cfdriver *);
400 int	config_cfdriver_detach(struct cfdriver *);
401 
402 int	config_cfattach_attach(const char *, struct cfattach *);
403 int	config_cfattach_detach(const char *, struct cfattach *);
404 
405 int	config_cfdata_attach(cfdata_t, int);
406 int	config_cfdata_detach(cfdata_t);
407 
408 struct cfdriver *config_cfdriver_lookup(const char *);
409 struct cfattach *config_cfattach_lookup(const char *, const char *);
410 const struct cfiattrdata *cfiattr_lookup(const char *, const struct cfdriver *);
411 
412 int	config_stdsubmatch(device_t, cfdata_t, const int *, void *);
413 cfdata_t config_search_loc(cfsubmatch_t, device_t,
414 				 const char *, const int *, void *);
415 cfdata_t config_search_ia(cfsubmatch_t, device_t,
416 				 const char *, void *);
417 cfdata_t config_rootsearch(cfsubmatch_t, const char *, void *);
418 device_t config_found_sm_loc(device_t, const char *, const int *,
419 			     void *, cfprint_t, cfsubmatch_t);
420 device_t config_found_ia(device_t, const char *, void *, cfprint_t);
421 device_t config_found(device_t, void *, cfprint_t);
422 device_t config_rootfound(const char *, void *);
423 device_t config_attach_loc(device_t, cfdata_t, const int *, void *, cfprint_t);
424 device_t config_attach(device_t, cfdata_t, void *, cfprint_t);
425 int	config_match(device_t, cfdata_t, void *);
426 
427 device_t config_attach_pseudo(cfdata_t);
428 
429 int	config_detach(device_t, int);
430 int	config_detach_children(device_t, int flags);
431 int	config_activate(device_t);
432 int	config_deactivate(device_t);
433 void	config_defer(device_t, void (*)(device_t));
434 void	config_deferred(device_t);
435 void	config_interrupts(device_t, void (*)(device_t));
436 void	config_pending_incr(void);
437 void	config_pending_decr(void);
438 
439 int	config_finalize_register(device_t, int (*)(device_t));
440 void	config_finalize(void);
441 
442 void		*device_lookup(cfdriver_t, int);
443 void		*device_lookup_private(cfdriver_t, int);
444 #ifdef __HAVE_DEVICE_REGISTER
445 void		device_register(device_t, void *);
446 #endif
447 
448 devclass_t	device_class(device_t);
449 cfdata_t	device_cfdata(device_t);
450 cfdriver_t	device_cfdriver(device_t);
451 cfattach_t	device_cfattach(device_t);
452 int		device_unit(device_t);
453 const char	*device_xname(device_t);
454 device_t	device_parent(device_t);
455 bool		device_is_active(device_t);
456 bool		device_is_enabled(device_t);
457 bool		device_has_power(device_t);
458 int		device_locator(device_t, u_int);
459 void		*device_private(device_t);
460 prop_dictionary_t device_properties(device_t);
461 
462 device_t	deviter_first(deviter_t *, deviter_flags_t);
463 void		deviter_init(deviter_t *, deviter_flags_t);
464 device_t	deviter_next(deviter_t *);
465 void		deviter_release(deviter_t *);
466 
467 bool		device_active(device_t, devactive_t);
468 bool		device_active_register(device_t,
469 				       void (*)(device_t, devactive_t));
470 void		device_active_deregister(device_t,
471 				         void (*)(device_t, devactive_t));
472 
473 bool		device_is_a(device_t, const char *);
474 
475 device_t	device_find_by_xname(const char *);
476 device_t	device_find_by_driver_unit(const char *, int);
477 
478 bool		device_pmf_is_registered(device_t);
479 
480 bool		device_pmf_driver_suspend(device_t PMF_FN_PROTO);
481 bool		device_pmf_driver_resume(device_t PMF_FN_PROTO);
482 bool		device_pmf_driver_shutdown(device_t, int);
483 
484 bool		device_pmf_driver_register(device_t,
485 		    bool (*)(device_t PMF_FN_PROTO),
486 		    bool (*)(device_t PMF_FN_PROTO),
487 		    bool (*)(device_t, int));
488 void		device_pmf_driver_deregister(device_t);
489 
490 bool		device_pmf_driver_child_register(device_t);
491 void		device_pmf_driver_set_child_register(device_t,
492 		    bool (*)(device_t));
493 
494 void		*device_pmf_bus_private(device_t);
495 bool		device_pmf_bus_suspend(device_t PMF_FN_PROTO);
496 bool		device_pmf_bus_resume(device_t PMF_FN_PROTO);
497 bool		device_pmf_bus_shutdown(device_t, int);
498 
499 void		*device_pmf_private(device_t);
500 void		device_pmf_unlock(device_t PMF_FN_PROTO);
501 bool		device_pmf_lock(device_t PMF_FN_PROTO);
502 
503 bool		device_is_self_suspended(device_t);
504 void		device_pmf_self_suspend(device_t PMF_FN_PROTO);
505 void		device_pmf_self_resume(device_t PMF_FN_PROTO);
506 bool		device_pmf_self_wait(device_t PMF_FN_PROTO);
507 
508 void		device_pmf_bus_register(device_t, void *,
509 		    bool (*)(device_t PMF_FN_PROTO),
510 		    bool (*)(device_t PMF_FN_PROTO),
511 		    bool (*)(device_t, int),
512 		    void (*)(device_t));
513 void		device_pmf_bus_deregister(device_t);
514 
515 void		*device_pmf_class_private(device_t);
516 bool		device_pmf_class_suspend(device_t PMF_FN_PROTO);
517 bool		device_pmf_class_resume(device_t PMF_FN_PROTO);
518 
519 void		device_pmf_class_register(device_t, void *,
520 		    bool (*)(device_t PMF_FN_PROTO),
521 		    bool (*)(device_t PMF_FN_PROTO),
522 		    void (*)(device_t));
523 void		device_pmf_class_deregister(device_t);
524 
525 #endif /* _KERNEL */
526 
527 #endif /* !_SYS_DEVICE_H_ */
528