1/* $NetBSD: device.h,v 1.149 2016/06/19 09:35:06 bouyer 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/device_if.h>
81#include <sys/evcnt.h>
82#include <sys/queue.h>
83
84#ifdef _KERNEL
85#include <sys/mutex.h>
86#include <sys/condvar.h>
87#include <sys/pmf.h>
88#endif
89
90#include <prop/proplib.h>
91
92/*
93 * Minimal device structures.
94 * Note that all ``system'' device types are listed here.
95 */
96typedef enum devclass {
97 DV_DULL, /* generic, no special info */
98 DV_CPU, /* CPU (carries resource utilization) */
99 DV_DISK, /* disk drive (label, etc) */
100 DV_IFNET, /* network interface */
101 DV_TAPE, /* tape device */
102 DV_TTY, /* serial line interface (?) */
103 DV_AUDIODEV, /* audio device */
104 DV_DISPLAYDEV, /* display device */
105 DV_BUS, /* bus device */
106 DV_VIRTUAL, /* unbacked virtual device */
107} devclass_t;
108
109/*
110 * Actions for ca_activate.
111 */
112typedef enum devact {
113 DVACT_DEACTIVATE /* deactivate the device */
114} devact_t;
115
116typedef enum {
117 DVA_SYSTEM,
118 DVA_HARDWARE
119} devactive_t;
120
121typedef struct cfdata *cfdata_t;
122typedef struct cfdriver *cfdriver_t;
123typedef struct cfattach *cfattach_t;
124
125#ifdef _KERNEL
126struct device_lock {
127 int dvl_nwait;
128 int dvl_nlock;
129 lwp_t *dvl_holder;
130 kmutex_t dvl_mtx;
131 kcondvar_t dvl_cv;
132};
133
134struct device_suspensor {
135 const device_suspensor_t *ds_delegator;
136 char ds_name[32];
137};
138
139#define DEVICE_SUSPENSORS_MAX 16
140
141struct device_garbage {
142 device_t *dg_devs;
143 int dg_ndevs;
144};
145
146struct device {
147 devclass_t dv_class; /* this device's classification */
148 TAILQ_ENTRY(device) dv_list; /* entry on list of all devices */
149 cfdata_t dv_cfdata; /* config data that found us
150 (NULL if pseudo-device) */
151 cfdriver_t dv_cfdriver; /* our cfdriver */
152 cfattach_t dv_cfattach; /* our cfattach */
153 int dv_unit; /* device unit number */
154 char dv_xname[16]; /* external name (name + unit) */
155 device_t dv_parent; /* pointer to parent device
156 (NULL if pseudo- or root node) */
157 int dv_depth; /* number of parents until root */
158 int dv_flags; /* misc. flags; see below */
159 void *dv_private; /* this device's private storage */
160 int *dv_locators; /* our actual locators (optional) */
161 prop_dictionary_t dv_properties;/* properties dictionary */
162
163 size_t dv_activity_count;
164 void (**dv_activity_handlers)(device_t, devactive_t);
165
166 bool (*dv_driver_suspend)(device_t, const pmf_qual_t *);
167 bool (*dv_driver_resume)(device_t, const pmf_qual_t *);
168 bool (*dv_driver_shutdown)(device_t, int);
169 bool (*dv_driver_child_register)(device_t);
170
171 void *dv_bus_private;
172 bool (*dv_bus_suspend)(device_t, const pmf_qual_t *);
173 bool (*dv_bus_resume)(device_t, const pmf_qual_t *);
174 bool (*dv_bus_shutdown)(device_t, int);
175 void (*dv_bus_deregister)(device_t);
176
177 void *dv_class_private;
178 bool (*dv_class_suspend)(device_t, const pmf_qual_t *);
179 bool (*dv_class_resume)(device_t, const pmf_qual_t *);
180 void (*dv_class_deregister)(device_t);
181
182 devgen_t dv_add_gen,
183 dv_del_gen;
184
185 struct device_lock dv_lock;
186 const device_suspensor_t
187 *dv_bus_suspensors[DEVICE_SUSPENSORS_MAX],
188 *dv_driver_suspensors[DEVICE_SUSPENSORS_MAX],
189 *dv_class_suspensors[DEVICE_SUSPENSORS_MAX];
190 struct device_garbage dv_garbage;
191};
192
193/* dv_flags */
194#define DVF_ACTIVE 0x0001 /* device is activated */
195#define DVF_PRIV_ALLOC 0x0002 /* device private storage != device */
196#define DVF_POWER_HANDLERS 0x0004 /* device has suspend/resume support */
197#define DVF_CLASS_SUSPENDED 0x0008 /* device class suspend was called */
198#define DVF_DRIVER_SUSPENDED 0x0010 /* device driver suspend was called */
199#define DVF_BUS_SUSPENDED 0x0020 /* device bus suspend was called */
200#define DVF_DETACH_SHUTDOWN 0x0080 /* device detaches safely at shutdown */
201
202TAILQ_HEAD(devicelist, device);
203
204enum deviter_flags {
205 DEVITER_F_RW = 0x1
206 , DEVITER_F_SHUTDOWN = 0x2
207 , DEVITER_F_LEAVES_FIRST = 0x4
208 , DEVITER_F_ROOT_FIRST = 0x8
209};
210
211typedef enum deviter_flags deviter_flags_t;
212
213struct deviter {
214 device_t di_prev;
215 deviter_flags_t di_flags;
216 int di_curdepth;
217 int di_maxdepth;
218 devgen_t di_gen;
219};
220
221typedef struct deviter deviter_t;
222
223struct shutdown_state {
224 bool initialized;
225 deviter_t di;
226};
227#endif
228
229/*
230 * Description of a locator, as part of interface attribute definitions.
231 */
232struct cflocdesc {
233 const char *cld_name;
234 const char *cld_defaultstr; /* NULL if no default */
235 int cld_default;
236};
237
238/*
239 * Description of an interface attribute, provided by potential
240 * parent device drivers, referred to by child device configuration data.
241 */
242struct cfiattrdata {
243 const char *ci_name;
244 int ci_loclen;
245 const struct cflocdesc ci_locdesc[
246#if defined(__GNUC__) && __GNUC__ <= 2
247 0
248#endif
249 ];
250};
251
252/*
253 * Description of a configuration parent. Each device attachment attaches
254 * to an "interface attribute", which is given in this structure. The parent
255 * *must* carry this attribute. Optionally, an individual device instance
256 * may also specify a specific parent device instance.
257 */
258struct cfparent {
259 const char *cfp_iattr; /* interface attribute */
260 const char *cfp_parent; /* optional specific parent */
261 int cfp_unit; /* optional specific unit
262 (DVUNIT_ANY to wildcard) */
263};
264
265/*
266 * Configuration data (i.e., data placed in ioconf.c).
267 */
268struct cfdata {
269 const char *cf_name; /* driver name */
270 const char *cf_atname; /* attachment name */
271 short cf_unit; /* unit number */
272 short cf_fstate; /* finding state (below) */
273 int *cf_loc; /* locators (machine dependent) */
274 int cf_flags; /* flags from config */
275 const struct cfparent *cf_pspec;/* parent specification */
276};
277#define FSTATE_NOTFOUND 0 /* has not been found */
278#define FSTATE_FOUND 1 /* has been found */
279#define FSTATE_STAR 2 /* duplicable */
280#define FSTATE_DSTAR 3 /* has not been found, and disabled */
281#define FSTATE_DNOTFOUND 4 /* duplicate, and disabled */
282
283/*
284 * Multiple configuration data tables may be maintained. This structure
285 * provides the linkage.
286 */
287struct cftable {
288 cfdata_t ct_cfdata; /* pointer to cfdata table */
289 TAILQ_ENTRY(cftable) ct_list; /* list linkage */
290};
291TAILQ_HEAD(cftablelist, cftable);
292
293typedef int (*cfsubmatch_t)(device_t, cfdata_t, const int *, void *);
294
295/*
296 * `configuration' attachment and driver (what the machine-independent
297 * autoconf uses). As devices are found, they are applied against all
298 * the potential matches. The one with the best match is taken, and a
299 * device structure (plus any other data desired) is allocated. Pointers
300 * to these are placed into an array of pointers. The array itself must
301 * be dynamic since devices can be found long after the machine is up
302 * and running.
303 *
304 * Devices can have multiple configuration attachments if they attach
305 * to different attributes (busses, or whatever), to allow specification
306 * of multiple match and attach functions. There is only one configuration
307 * driver per driver, so that things like unit numbers and the device
308 * structure array will be shared.
309 */
310struct cfattach {
311 const char *ca_name; /* name of attachment */
312 LIST_ENTRY(cfattach) ca_list; /* link on cfdriver's list */
313 size_t ca_devsize; /* size of dev data (for alloc) */
314 int ca_flags; /* flags for driver allocation etc */
315 int (*ca_match)(device_t, cfdata_t, void *);
316 void (*ca_attach)(device_t, device_t, void *);
317 int (*ca_detach)(device_t, int);
318 int (*ca_activate)(device_t, devact_t);
319 /* technically, the next 2 belong into "struct cfdriver" */
320 int (*ca_rescan)(device_t, const char *,
321 const int *); /* scan for new children */
322 void (*ca_childdetached)(device_t, device_t);
323};
324LIST_HEAD(cfattachlist, cfattach);
325
326#define CFATTACH_DECL3_NEW(name, ddsize, matfn, attfn, detfn, actfn, \
327 rescanfn, chdetfn, __flags) \
328struct cfattach __CONCAT(name,_ca) = { \
329 .ca_name = ___STRING(name), \
330 .ca_devsize = ddsize, \
331 .ca_flags = (__flags) | DVF_PRIV_ALLOC, \
332 .ca_match = matfn, \
333 .ca_attach = attfn, \
334 .ca_detach = detfn, \
335 .ca_activate = actfn, \
336 .ca_rescan = rescanfn, \
337 .ca_childdetached = chdetfn, \
338}
339
340#define CFATTACH_DECL2_NEW(name, ddsize, matfn, attfn, detfn, actfn, \
341 rescanfn, chdetfn) \
342 CFATTACH_DECL3_NEW(name, ddsize, matfn, attfn, detfn, actfn, \
343 rescanfn, chdetfn, 0)
344
345#define CFATTACH_DECL_NEW(name, ddsize, matfn, attfn, detfn, actfn) \
346 CFATTACH_DECL2_NEW(name, ddsize, matfn, attfn, detfn, actfn, NULL, NULL)
347
348/* Flags given to config_detach(), and the ca_detach function. */
349#define DETACH_FORCE 0x01 /* force detachment; hardware gone */
350#define DETACH_QUIET 0x02 /* don't print a notice */
351#define DETACH_SHUTDOWN 0x04 /* detach because of system shutdown */
352#define DETACH_POWEROFF 0x08 /* going to power off; power down devices */
353
354struct cfdriver {
355 LIST_ENTRY(cfdriver) cd_list; /* link on allcfdrivers */
356 struct cfattachlist cd_attach; /* list of all attachments */
357 device_t *cd_devs; /* devices found */
358 const char *cd_name; /* device name */
359 enum devclass cd_class; /* device classification */
360 int cd_ndevs; /* size of cd_devs array */
361 const struct cfiattrdata * const *cd_attrs; /* attributes provided */
362};
363LIST_HEAD(cfdriverlist, cfdriver);
364
365#define CFDRIVER_DECL(name, class, attrs) \
366struct cfdriver __CONCAT(name,_cd) = { \
367 .cd_name = ___STRING(name), \
368 .cd_class = class, \
369 .cd_attrs = attrs, \
370}
371
372/*
373 * The cfattachinit is a data structure used to associate a list of
374 * cfattach's with cfdrivers as found in the static kernel configuration.
375 */
376struct cfattachinit {
377 const char *cfai_name; /* driver name */
378 struct cfattach * const *cfai_list;/* list of attachments */
379};
380/*
381 * the same, but with a non-constant list so it can be modified
382 * for module bookkeeping
383 */
384struct cfattachlkminit {
385 const char *cfai_name; /* driver name */
386 struct cfattach **cfai_list; /* list of attachments */
387};
388
389/*
390 * Configuration printing functions, and their return codes. The second
391 * argument is NULL if the device was configured; otherwise it is the name
392 * of the parent device. The return value is ignored if the device was
393 * configured, so most functions can return UNCONF unconditionally.
394 */
395typedef int (*cfprint_t)(void *, const char *); /* XXX const char * */
396#define QUIET 0 /* print nothing */
397#define UNCONF 1 /* print " not configured\n" */
398#define UNSUPP 2 /* print " not supported\n" */
399
400/*
401 * Pseudo-device attach information (function + number of pseudo-devs).
402 */
403struct pdevinit {
404 void (*pdev_attach)(int);
405 int pdev_count;
406};
407
408/* This allows us to wildcard a device unit. */
409#define DVUNIT_ANY -1
410
411#ifdef _KERNEL
412
413extern struct cfdriverlist allcfdrivers;/* list of all cfdrivers */
414extern struct cftablelist allcftables; /* list of all cfdata tables */
415extern device_t booted_device; /* the device we booted from */
416extern int booted_partition; /* the partition on that device */
417extern daddr_t booted_startblk; /* or the start of a wedge */
418extern uint64_t booted_nblks; /* and the size of that wedge */
419extern char *bootspec; /* and the device/wedge name */
420
421struct vnode *opendisk(device_t);
422int getdisksize(struct vnode *, uint64_t *, unsigned int *);
423struct dkwedge_info;
424int getdiskinfo(struct vnode *, struct dkwedge_info *);
425
426void config_init(void);
427int config_init_component(struct cfdriver *const*,
428 const struct cfattachinit *, struct cfdata *);
429int config_fini_component(struct cfdriver *const*,
430 const struct cfattachinit *, struct cfdata *);
431void config_init_mi(void);
432void drvctl_init(void);
433void drvctl_fini(void);
434
435int config_cfdriver_attach(struct cfdriver *);
436int config_cfdriver_detach(struct cfdriver *);
437
438int config_cfattach_attach(const char *, struct cfattach *);
439int config_cfattach_detach(const char *, struct cfattach *);
440
441int config_cfdata_attach(cfdata_t, int);
442int config_cfdata_detach(cfdata_t);
443
444struct cfdriver *config_cfdriver_lookup(const char *);
445struct cfattach *config_cfattach_lookup(const char *, const char *);
446const struct cfiattrdata *cfiattr_lookup(const char *, const struct cfdriver *);
447
448const char *cfdata_ifattr(const struct cfdata *);
449
450int config_stdsubmatch(device_t, cfdata_t, const int *, void *);
451cfdata_t config_search_loc(cfsubmatch_t, device_t,
452 const char *, const int *, void *);
453cfdata_t config_search_ia(cfsubmatch_t, device_t,
454 const char *, void *);
455cfdata_t config_rootsearch(cfsubmatch_t, const char *, void *);
456device_t config_found_sm_loc(device_t, const char *, const int *,
457 void *, cfprint_t, cfsubmatch_t);
458device_t config_found_ia(device_t, const char *, void *, cfprint_t);
459device_t config_found(device_t, void *, cfprint_t);
460device_t config_rootfound(const char *, void *);
461device_t config_attach_loc(device_t, cfdata_t, const int *, void *, cfprint_t);
462device_t config_attach(device_t, cfdata_t, void *, cfprint_t);
463int config_match(device_t, cfdata_t, void *);
464
465bool ifattr_match(const char *, const char *);
466
467device_t config_attach_pseudo(cfdata_t);
468
469int config_detach(device_t, int);
470int config_detach_children(device_t, int flags);
471bool config_detach_all(int);
472int config_deactivate(device_t);
473void config_defer(device_t, void (*)(device_t));
474void config_deferred(device_t);
475void config_interrupts(device_t, void (*)(device_t));
476void config_mountroot(device_t, void (*)(device_t));
477void config_pending_incr(device_t);
478void config_pending_decr(device_t);
479void config_create_interruptthreads(void);
480void config_create_mountrootthreads(void);
481
482int config_finalize_register(device_t, int (*)(device_t));
483void config_finalize(void);
484void config_finalize_mountroot(void);
485
486void config_twiddle_init(void);
487void config_twiddle_fn(void *);
488
489void null_childdetached(device_t, device_t);
490
491device_t device_lookup(cfdriver_t, int);
492void *device_lookup_private(cfdriver_t, int);
493void device_register(device_t, void *);
494void device_register_post_config(device_t, void *);
495
496devclass_t device_class(device_t);
497cfdata_t device_cfdata(device_t);
498cfdriver_t device_cfdriver(device_t);
499cfattach_t device_cfattach(device_t);
500int device_unit(device_t);
501const char *device_xname(device_t);
502device_t device_parent(device_t);
503bool device_is_active(device_t);
504bool device_activation(device_t, devact_level_t);
505bool device_is_enabled(device_t);
506bool device_has_power(device_t);
507int device_locator(device_t, u_int);
508void *device_private(device_t);
509prop_dictionary_t device_properties(device_t);
510
511device_t deviter_first(deviter_t *, deviter_flags_t);
512void deviter_init(deviter_t *, deviter_flags_t);
513device_t deviter_next(deviter_t *);
514void deviter_release(deviter_t *);
515
516bool device_active(device_t, devactive_t);
517bool device_active_register(device_t,
518 void (*)(device_t, devactive_t));
519void device_active_deregister(device_t,
520 void (*)(device_t, devactive_t));
521
522bool device_is_a(device_t, const char *);
523
524device_t device_find_by_xname(const char *);
525device_t device_find_by_driver_unit(const char *, int);
526
527bool device_pmf_is_registered(device_t);
528
529bool device_pmf_driver_suspend(device_t, const pmf_qual_t *);
530bool device_pmf_driver_resume(device_t, const pmf_qual_t *);
531bool device_pmf_driver_shutdown(device_t, int);
532
533bool device_pmf_driver_register(device_t,
534 bool (*)(device_t, const pmf_qual_t *),
535 bool (*)(device_t, const pmf_qual_t *),
536 bool (*)(device_t, int));
537void device_pmf_driver_deregister(device_t);
538
539bool device_pmf_driver_child_register(device_t);
540void device_pmf_driver_set_child_register(device_t,
541 bool (*)(device_t));
542
543void *device_pmf_bus_private(device_t);
544bool device_pmf_bus_suspend(device_t, const pmf_qual_t *);
545bool device_pmf_bus_resume(device_t, const pmf_qual_t *);
546bool device_pmf_bus_shutdown(device_t, int);
547
548device_lock_t device_getlock(device_t);
549void device_pmf_unlock(device_t);
550bool device_pmf_lock(device_t);
551
552bool device_is_self_suspended(device_t);
553void device_pmf_self_suspend(device_t, const pmf_qual_t *);
554void device_pmf_self_resume(device_t, const pmf_qual_t *);
555bool device_pmf_self_wait(device_t, const pmf_qual_t *);
556
557void device_pmf_bus_register(device_t, void *,
558 bool (*)(device_t, const pmf_qual_t *),
559 bool (*)(device_t, const pmf_qual_t *),
560 bool (*)(device_t, int),
561 void (*)(device_t));
562void device_pmf_bus_deregister(device_t);
563
564void *device_pmf_class_private(device_t);
565bool device_pmf_class_suspend(device_t, const pmf_qual_t *);
566bool device_pmf_class_resume(device_t, const pmf_qual_t *);
567
568void device_pmf_class_register(device_t, void *,
569 bool (*)(device_t, const pmf_qual_t *),
570 bool (*)(device_t, const pmf_qual_t *),
571 void (*)(device_t));
572void device_pmf_class_deregister(device_t);
573
574device_t shutdown_first(struct shutdown_state *);
575device_t shutdown_next(struct shutdown_state *);
576#endif /* _KERNEL */
577
578#endif /* !_SYS_DEVICE_H_ */
579