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