subr_autoconf.c revision 1.62.6.3 1 /* $NetBSD: subr_autoconf.c,v 1.62.6.3 2002/04/06 16:04:31 eeh Exp $ */
2
3 /*
4 * Copyright (c) 2001-2002 Eduardo E. Horvath
5 * Copyright (c) 1996, 2000 Christopher G. Demetriou
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed for the
19 * NetBSD Project. See http://www.netbsd.org/ for
20 * information about NetBSD.
21 * 4. The name of the author may not be used to endorse or promote products
22 * derived from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 * --(license Id: LICENSE.proto,v 1.1 2000/06/13 21:40:26 cgd Exp )--
36 */
37
38 /*
39 * Copyright (c) 1992, 1993
40 * The Regents of the University of California. All rights reserved.
41 *
42 * This software was developed by the Computer Systems Engineering group
43 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
44 * contributed to Berkeley.
45 *
46 * All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement:
48 * This product includes software developed by the University of
49 * California, Lawrence Berkeley Laboratories.
50 *
51 * Redistribution and use in source and binary forms, with or without
52 * modification, are permitted provided that the following conditions
53 * are met:
54 * 1. Redistributions of source code must retain the above copyright
55 * notice, this list of conditions and the following disclaimer.
56 * 2. Redistributions in binary form must reproduce the above copyright
57 * notice, this list of conditions and the following disclaimer in the
58 * documentation and/or other materials provided with the distribution.
59 * 3. All advertising materials mentioning features or use of this software
60 * must display the following acknowledgement:
61 * This product includes software developed by the University of
62 * California, Berkeley and its contributors.
63 * 4. Neither the name of the University nor the names of its contributors
64 * may be used to endorse or promote products derived from this software
65 * without specific prior written permission.
66 *
67 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
68 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
69 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
70 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
71 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
72 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
73 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
74 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
75 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
76 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
77 * SUCH DAMAGE.
78 *
79 * from: Header: subr_autoconf.c,v 1.12 93/02/01 19:31:48 torek Exp (LBL)
80 *
81 * @(#)subr_autoconf.c 8.3 (Berkeley) 5/17/94
82 */
83
84 #include <sys/cdefs.h>
85 __KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.62.6.3 2002/04/06 16:04:31 eeh Exp $");
86
87 #include "opt_ddb.h"
88
89 #include <sys/param.h>
90 #include <sys/device.h>
91 #include <sys/malloc.h>
92 #include <sys/systm.h>
93 #include <sys/kernel.h>
94 #include <sys/errno.h>
95 #include <sys/proc.h>
96 #include <sys/properties.h>
97 #include <machine/limits.h>
98
99 #include "opt_userconf.h"
100 #ifdef USERCONF
101 #include <sys/userconf.h>
102 #include <sys/reboot.h>
103 #endif
104
105 /*
106 * Autoconfiguration subroutines.
107 */
108
109 static struct device *dev_create(struct device *, ssize_t, int);
110
111 /*
112 * ioconf.c exports exactly two names: cfdata and cfroots. All system
113 * devices and drivers are found via these tables.
114 */
115 extern struct cfdata cfdata[];
116 extern short cfroots[];
117
118 #define ROOT ((struct device *)NULL)
119
120 struct matchinfo {
121 cfmatch_t fn;
122 struct device *parent;
123 void *aux;
124 struct cfdata *match;
125 int pri;
126 };
127
128 static char *number(char *, int);
129 static void mapply(struct matchinfo *, struct cfdata *, struct device *);
130 static void locset(struct device *, struct cfdata *);
131 static void locrm(struct device *, struct cfdata *);
132
133 struct deferred_config {
134 TAILQ_ENTRY(deferred_config) dc_queue;
135 struct device *dc_dev;
136 void (*dc_func)(struct device *);
137 };
138
139 TAILQ_HEAD(deferred_config_head, deferred_config);
140
141 struct deferred_config_head deferred_config_queue;
142 struct deferred_config_head interrupt_config_queue;
143
144 static void config_process_deferred(struct deferred_config_head *,
145 struct device *);
146
147 /* list of all devices */
148 struct devicelist alldevs;
149
150 /* list of all events */
151 struct evcntlist allevents = TAILQ_HEAD_INITIALIZER(allevents);
152
153 __volatile int config_pending; /* semaphore for mountroot */
154
155 /* device properties database */
156 static propdb_t devpropdb;
157
158 /*
159 * Configure the system's hardware.
160 */
161 void
162 configure(void)
163 {
164
165 TAILQ_INIT(&deferred_config_queue);
166 TAILQ_INIT(&interrupt_config_queue);
167 TAILQ_INIT(&alldevs);
168
169 devpropdb = propdb_create("devprop");
170
171 #ifdef USERCONF
172 if (boothowto & RB_USERCONF)
173 user_config();
174 #endif
175
176 /*
177 * Do the machine-dependent portion of autoconfiguration. This
178 * sets the configuration machinery here in motion by "finding"
179 * the root bus. When this function returns, we expect interrupts
180 * to be enabled.
181 */
182 cpu_configure();
183
184 /*
185 * Now that we've found all the hardware, start the real time
186 * and statistics clocks.
187 */
188 initclocks();
189
190 cold = 0; /* clocks are running, we're warm now! */
191
192 /*
193 * Now callback to finish configuration for devices which want
194 * to do this once interrupts are enabled.
195 */
196 config_process_deferred(&interrupt_config_queue, NULL);
197 }
198
199 /*
200 * Set locators as properties on device node.
201 */
202 static void
203 locset(struct device *d, struct cfdata *cf)
204 {
205 int i;
206 int type = PROP_CONST|PROP_INT;
207 char buf[32];
208
209 dev_setprop(d, "cd-name", cf->cf_driver->cd_name,
210 strlen(cf->cf_driver->cd_name) + 1,
211 PROP_STRING|PROP_CONST, (!cold));
212
213 for (i=0; cf->cf_locnames[i]; i++) {
214 sprintf(buf, "loc-%s", cf->cf_locnames[i]);
215 dev_setprop(d, buf, &cf->cf_loc[i],
216 sizeof(int), type, (!cold));
217 }
218 }
219
220 /*
221 * Remove locator properties from device node.
222 */
223 static void
224 locrm(struct device *d, struct cfdata *cf)
225 {
226 int i;
227 char buf[32];
228
229 dev_delprop(d, "cd-name");
230 for (i=0; cf->cf_locnames[i]; i++) {
231 sprintf(buf, "loc-%s", cf->cf_locnames[i]);
232 dev_delprop(d, buf);
233 }
234 }
235
236 /*
237 * Apply the matching function and choose the best. This is used
238 * a few times and we want to keep the code small.
239 */
240 static void
241 mapply(struct matchinfo *m, struct cfdata *cf, struct device *child)
242 {
243 int pri;
244 void *aux = m->aux;
245
246 if (m->fn != NULL)
247 /* Someday the submatch function should use properties too. */
248 pri = (*m->fn)(m->parent, cf, m->aux);
249 else {
250 if ((ssize_t)cf->cf_attach->ca_devsize < 0) {
251 /* New-style device driver */
252 if (!child)
253 panic("mapply: no dev for new-style driver\n");
254 locset(child, cf);
255 child->dv_private = aux;
256 aux = child;
257 }
258
259 if (cf->cf_attach->ca_match == NULL) {
260 panic("mapply: no match function for '%s' device\n",
261 cf->cf_driver->cd_name);
262 }
263 pri = (*cf->cf_attach->ca_match)(m->parent, cf, aux);
264 }
265 if (pri > m->pri) {
266 m->match = cf;
267 m->pri = pri;
268 }
269 if (child) {
270 locrm(child, cf);
271 child->dv_private = NULL;
272 }
273 }
274
275 /*
276 * Iterate over all potential children of some device, calling the given
277 * function (default being the child's match function) for each one.
278 * Nonzero returns are matches; the highest value returned is considered
279 * the best match. Return the `found child' if we got a match, or NULL
280 * otherwise. The `aux' pointer is simply passed on through.
281 *
282 * Note that this function is designed so that it can be used to apply
283 * an arbitrary function to all potential children (its return value
284 * can be ignored).
285 */
286 struct cfdata *
287 config_search_ad(cfmatch_t fn, struct device *parent, void *aux,
288 struct device *child)
289 {
290 struct cfdata *cf;
291 short *p;
292 struct matchinfo m;
293
294 m.fn = fn;
295 m.parent = parent;
296 m.aux = aux;
297 m.match = NULL;
298 m.pri = 0;
299
300 for (cf = cfdata; cf->cf_driver; cf++) {
301 /*
302 * Skip cf if no longer eligible, otherwise scan through
303 * parents for one matching `parent', and try match function.
304 */
305 if (cf->cf_fstate == FSTATE_FOUND)
306 continue;
307 for (p = cf->cf_parents; *p >= 0; p++)
308 if (parent->dv_cfdata == &cfdata[*p])
309 mapply(&m, cf, child);
310 }
311 if (m.match == NULL && child != NULL) {
312 /* Consume the device if we failed to match */
313 config_detach(child, 0);
314 }
315 return (m.match);
316 }
317
318 /*
319 * Find the given root device.
320 * This is much like config_search, but there is no parent.
321 */
322 struct cfdata *
323 config_rootsearch_ad(cfmatch_t fn, const char *rootname, void *aux,
324 struct device *root)
325 {
326 struct cfdata *cf;
327 short *p;
328 struct matchinfo m;
329
330 m.fn = fn;
331 m.parent = ROOT;
332 m.aux = aux;
333 m.match = NULL;
334 m.pri = 0;
335 /*
336 * Look at root entries for matching name. We do not bother
337 * with found-state here since only one root should ever be
338 * searched (and it must be done first).
339 */
340 for (p = cfroots; *p >= 0; p++) {
341 cf = &cfdata[*p];
342 if (strcmp(cf->cf_driver->cd_name, rootname) == 0)
343 mapply(&m, cf, root);
344 }
345 return (m.match);
346 }
347
348 static const char *msgs[3] = { "", " not configured\n", " unsupported\n" };
349
350 /*
351 * The given `aux' argument describes a device that has been found
352 * on the given parent, but not necessarily configured. Locate the
353 * configuration data for that device (using the submatch function
354 * provided, or using candidates' cd_match configuration driver
355 * functions) and attach it, and return true. If the device was
356 * not configured, call the given `print' function and return 0.
357 */
358 struct device *
359 config_found_sad(struct device *parent, void *aux, cfprint_t print,
360 cfmatch_t submatch, struct device *d)
361 {
362 struct cfdata *cf;
363
364 /*
365 * Creating the dummy device here is really optional. But
366 * it allows old-style bus drivers to attach new-style children.
367 */
368 if (!d) d = dev_create(ROOT, 0, cold ? M_NOWAIT : M_WAITOK);
369 if ((cf = config_search_ad(submatch, parent, aux, d)) != NULL)
370 return (config_attach_ad(parent, cf, aux, print, d));
371 if (print)
372 printf("%s", msgs[(*print)(aux, parent->dv_xname)]);
373 return (NULL);
374 }
375
376 /*
377 * As above, but for root devices.
378 */
379 struct device *
380 config_rootfound(const char *rootname, void *aux)
381 {
382 struct cfdata *cf;
383 struct device *root;
384
385 root = dev_create(ROOT, 0, cold ? M_NOWAIT : M_WAITOK);
386 if ((cf = config_rootsearch_ad((cfmatch_t)NULL, rootname, aux, root)) != NULL)
387 return (config_attach_ad(ROOT, cf, aux, (cfprint_t)NULL, root));
388 printf("root device %s not configured\n", rootname);
389 return (NULL);
390 }
391
392 /* just like sprintf(buf, "%d") except that it works from the end */
393 static char *
394 number(char *ep, int n)
395 {
396
397 *--ep = 0;
398 while (n >= 10) {
399 *--ep = (n % 10) + '0';
400 n /= 10;
401 }
402 *--ep = n + '0';
403 return (ep);
404 }
405
406 /*
407 * Allocate an empty device node. If `parent' is provided then the
408 * new node is attached to the tree under `parent'. If `size'
409 * is provided, then the new device node is allocated to be that
410 * size.
411 */
412 static struct device *
413 dev_create(struct device *parent, ssize_t size, int wait) {
414 struct device * dev;
415
416 /* get memory for all device vars */
417 if (size == 0)
418 size = sizeof(struct device);
419 dev = (struct device *)malloc(size, M_DEVBUF, wait);
420 if (!dev)
421 panic("dev_create: memory allocation for device failed");
422 memset(dev, 0, size);
423 TAILQ_INSERT_TAIL(&alldevs, dev, dv_list); /* link up */
424 dev->dv_class = DV_EMPTY;
425 if (parent)
426 dev->dv_parent = parent;
427 return (dev);
428 }
429
430 /*
431 * Expand the size of the cd_devs array if necessary.
432 */
433 void
434 config_makeroom(int n, struct cfdriver *cd)
435 {
436 int old, new;
437 void **nsp;
438
439 if (n < cd->cd_ndevs)
440 return;
441
442 /*
443 * Need to expand the array.
444 */
445 old = cd->cd_ndevs;
446 if (old == 0)
447 new = MINALLOCSIZE / sizeof(void *);
448 else
449 new = old * 2;
450 while (new <= n)
451 new *= 2;
452 cd->cd_ndevs = new;
453 nsp = malloc(new * sizeof(void *), M_DEVBUF,
454 cold ? M_NOWAIT : M_WAITOK);
455 if (nsp == NULL)
456 panic("config_attach: %sing dev array",
457 old != 0 ? "expand" : "creat");
458 memset(nsp + old, 0, (new - old) * sizeof(void *));
459 if (old != 0) {
460 memcpy(nsp, cd->cd_devs, old * sizeof(void *));
461 free(cd->cd_devs, M_DEVBUF);
462 }
463 cd->cd_devs = nsp;
464 }
465
466 /*
467 * Attach a found device. Allocates memory for device variables.
468 */
469 struct device *
470 config_attach_ad(struct device *parent, struct cfdata *cf, void *aux,
471 cfprint_t print, struct device *propdev)
472 {
473 struct device *dev;
474 struct cfdriver *cd;
475 struct cfattach *ca;
476 size_t lname, lunit;
477 ssize_t softsize;
478 const char *xunit;
479 int myunit;
480 char num[10];
481
482 cd = cf->cf_driver;
483 ca = cf->cf_attach;
484 softsize = ca->ca_devsize;
485
486 #ifndef __BROKEN_CONFIG_UNIT_USAGE
487 if (cf->cf_fstate == FSTATE_STAR) {
488 for (myunit = cf->cf_unit; myunit < cd->cd_ndevs; myunit++)
489 if (cd->cd_devs[myunit] == NULL)
490 break;
491 /*
492 * myunit is now the unit of the first NULL device pointer,
493 * or max(cd->cd_ndevs,cf->cf_unit).
494 */
495 } else {
496 myunit = cf->cf_unit;
497 #else /* __BROKEN_CONFIG_UNIT_USAGE */
498 myunit = cf->cf_unit;
499 if (cf->cf_fstate == FSTATE_STAR)
500 cf->cf_unit++;
501 else {
502 #endif /* __BROKEN_CONFIG_UNIT_USAGE */
503 KASSERT(cf->cf_fstate == FSTATE_NOTFOUND);
504 cf->cf_fstate = FSTATE_FOUND;
505 }
506
507 /* compute length of name and decimal expansion of unit number */
508 lname = strlen(cd->cd_name);
509 xunit = number(&num[sizeof(num)], myunit);
510 lunit = &num[sizeof(num)] - xunit;
511 if (lname + lunit >= sizeof(dev->dv_xname))
512 panic("config_attach: device name too long");
513
514 /*
515 * XXXXX We will continue to use the old-style device+softc in one
516 * until all drivers are fixed to use DEV_PRIVATE() and not to refer
517 * to sc->sc_dev.
518 */
519 if (softsize < 0) softsize = -softsize;
520
521 /* get memory for all device vars */
522 if (softsize < 0) {
523 /* New-style device */
524 if (propdev) {
525 /* Great, we can use the propdev. */
526 dev = propdev;
527 } else {
528 dev = dev_create(parent, 0, cold ? M_NOWAIT : M_WAITOK);
529 if (!dev)
530 panic("config_attach: memory allocation for device failed");
531 }
532 if (softsize < 0) softsize = -softsize;
533 if (softsize < sizeof(struct device)) panic("config_attach");
534 dev->dv_private = malloc(softsize, M_DEVBUF,
535 cold ? M_NOWAIT : M_WAITOK);
536 if (!dev->dv_private)
537 panic("config_attach: memory allocation for device softc failed");
538 memset(dev->dv_private, 0, softsize);
539 dev->dv_flags |= DVF_SOFTC;
540 } else {
541 dev = (struct device *)malloc(softsize, M_DEVBUF,
542 cold ? M_NOWAIT : M_WAITOK);
543 if (!dev)
544 panic("config_attach: memory allocation for device softc failed");
545 memset(dev, 0, softsize);
546 TAILQ_INSERT_TAIL(&alldevs, dev, dv_list); /* link up */
547 dev->dv_private = dev; /* Point private to ourself... */
548 }
549 dev->dv_class = cd->cd_class;
550 dev->dv_cfdata = cf;
551 dev->dv_unit = myunit;
552 memcpy(dev->dv_xname, cd->cd_name, lname);
553 memcpy(dev->dv_xname + lname, xunit, lunit);
554 dev->dv_parent = parent;
555 dev->dv_flags |= DVF_ACTIVE; /* always initially active */
556 /* Set the locators once again. */
557 locset(dev, cf);
558 if (propdev && propdev != dev) {
559 /* Inherit (steal) properties from dummy device */
560 dev_copyprops(propdev, dev, (!cold));
561 dev_delprop(propdev, NULL);
562 /* destroy propdev */
563 config_detach(propdev, 0);
564 }
565
566 if (parent == ROOT)
567 printf("%s (root)", dev->dv_xname);
568 else {
569 printf("%s at %s", dev->dv_xname, parent->dv_xname);
570 if (print)
571 (void) (*print)(aux, NULL);
572 }
573
574 /* put this device in the devices array */
575 config_makeroom(dev->dv_unit, cd);
576 if (cd->cd_devs[dev->dv_unit])
577 panic("config_attach: duplicate %s", dev->dv_xname);
578 cd->cd_devs[dev->dv_unit] = dev;
579
580 /*
581 * Before attaching, clobber any unfound devices that are
582 * otherwise identical.
583 */
584 #ifdef __BROKEN_CONFIG_UNIT_USAGE
585 /* bump the unit number on all starred cfdata for this device. */
586 #endif /* __BROKEN_CONFIG_UNIT_USAGE */
587 for (cf = cfdata; cf->cf_driver; cf++)
588 if (cf->cf_driver == cd && cf->cf_unit == dev->dv_unit) {
589 if (cf->cf_fstate == FSTATE_NOTFOUND)
590 cf->cf_fstate = FSTATE_FOUND;
591 #ifdef __BROKEN_CONFIG_UNIT_USAGE
592 if (cf->cf_fstate == FSTATE_STAR)
593 cf->cf_unit++;
594 #endif /* __BROKEN_CONFIG_UNIT_USAGE */
595 }
596 #ifdef __HAVE_DEVICE_REGISTER
597 device_register(dev, aux);
598 #endif
599 (*ca->ca_attach)(parent, dev, aux);
600 config_process_deferred(&deferred_config_queue, dev);
601 return (dev);
602 }
603
604 /*
605 * Detach a device. Optionally forced (e.g. because of hardware
606 * removal) and quiet. Returns zero if successful, non-zero
607 * (an error code) otherwise.
608 *
609 * Note that this code wants to be run from a process context, so
610 * that the detach can sleep to allow processes which have a device
611 * open to run and unwind their stacks.
612 */
613 int
614 config_detach(struct device *dev, int flags)
615 {
616 struct cfdata *cf;
617 struct cfattach *ca;
618 struct cfdriver *cd;
619 #ifdef DIAGNOSTIC
620 struct device *d;
621 #endif
622 int rv = 0, i;
623
624 if (dev->dv_class == DV_EMPTY) {
625 /*
626 * The device is a dummy that never fully attached.
627 * Simply remove it from the global list and free it.
628 */
629 TAILQ_REMOVE(&alldevs, dev, dv_list);
630 dev_delprop(dev, NULL);
631 if (dev->dv_flags & DVF_SOFTC)
632 /* Separately allocated softc */
633 free(dev->dv_private, M_DEVBUF);
634 free(dev, M_DEVBUF);
635 return (0);
636 }
637
638 cf = dev->dv_cfdata;
639 #ifdef DIAGNOSTIC
640 if (cf->cf_fstate != FSTATE_FOUND && cf->cf_fstate != FSTATE_STAR)
641 panic("config_detach: bad device fstate");
642 #endif
643 ca = cf->cf_attach;
644 cd = cf->cf_driver;
645
646 /*
647 * Ensure the device is deactivated. If the device doesn't
648 * have an activation entry point, we allow DVF_ACTIVE to
649 * remain set. Otherwise, if DVF_ACTIVE is still set, the
650 * device is busy, and the detach fails.
651 */
652 if (ca->ca_activate != NULL)
653 rv = config_deactivate(dev);
654
655 /*
656 * Try to detach the device. If that's not possible, then
657 * we either panic() (for the forced but failed case), or
658 * return an error.
659 */
660 if (rv == 0) {
661 if (ca->ca_detach != NULL)
662 rv = (*ca->ca_detach)(dev, flags);
663 else
664 rv = EOPNOTSUPP;
665 }
666 if (rv != 0) {
667 if ((flags & DETACH_FORCE) == 0)
668 return (rv);
669 else
670 panic("config_detach: forced detach of %s failed (%d)",
671 dev->dv_xname, rv);
672 }
673
674 /*
675 * The device has now been successfully detached.
676 */
677
678 #ifdef DIAGNOSTIC
679 /*
680 * Sanity: If you're successfully detached, you should have no
681 * children. (Note that because children must be attached
682 * after parents, we only need to search the latter part of
683 * the list.)
684 */
685 for (d = TAILQ_NEXT(dev, dv_list); d != NULL;
686 d = TAILQ_NEXT(d, dv_list)) {
687 if (d->dv_parent == dev) {
688 printf("config_detach: detached device %s"
689 " has children %s\n", dev->dv_xname, d->dv_xname);
690 panic("config_detach");
691 }
692 }
693 #endif
694
695 /*
696 * Mark cfdata to show that the unit can be reused, if possible.
697 */
698 #ifdef __BROKEN_CONFIG_UNIT_USAGE
699 /*
700 * Note that we can only re-use a starred unit number if the unit
701 * being detached had the last assigned unit number.
702 */
703 #endif /* __BROKEN_CONFIG_UNIT_USAGE */
704 for (cf = cfdata; cf->cf_driver; cf++) {
705 if (cf->cf_driver == cd) {
706 if (cf->cf_fstate == FSTATE_FOUND &&
707 cf->cf_unit == dev->dv_unit)
708 cf->cf_fstate = FSTATE_NOTFOUND;
709 #ifdef __BROKEN_CONFIG_UNIT_USAGE
710 if (cf->cf_fstate == FSTATE_STAR &&
711 cf->cf_unit == dev->dv_unit + 1)
712 cf->cf_unit--;
713 #endif /* __BROKEN_CONFIG_UNIT_USAGE */
714 }
715 }
716
717 /*
718 * Unlink from device list.
719 */
720 TAILQ_REMOVE(&alldevs, dev, dv_list);
721
722 /*
723 * Remove from cfdriver's array, tell the world, and free softc.
724 */
725 if (cd) {
726 cd->cd_devs[dev->dv_unit] = NULL;
727 if ((flags & DETACH_QUIET) == 0)
728 printf("%s detached\n", dev->dv_xname);
729 }
730 dev_delprop(dev, NULL);
731 if (dev->dv_flags & DVF_SOFTC)
732 /* Separately allocated softc */
733 free(dev->dv_private, M_DEVBUF);
734 free(dev, M_DEVBUF);
735
736 /*
737 * If the device now has no units in use, deallocate its softc array.
738 */
739 for (i = 0; i < cd->cd_ndevs; i++)
740 if (cd->cd_devs[i] != NULL)
741 break;
742 if (i == cd->cd_ndevs) { /* nothing found; deallocate */
743 free(cd->cd_devs, M_DEVBUF);
744 cd->cd_devs = NULL;
745 cd->cd_ndevs = 0;
746 }
747
748 /*
749 * Return success.
750 */
751 return (0);
752 }
753
754 int
755 config_activate(struct device *dev)
756 {
757 struct cfattach *ca = dev->dv_cfdata->cf_attach;
758 int rv = 0, oflags = dev->dv_flags;
759
760 if (ca->ca_activate == NULL)
761 return (EOPNOTSUPP);
762
763 if ((dev->dv_flags & DVF_ACTIVE) == 0) {
764 dev->dv_flags |= DVF_ACTIVE;
765 rv = (*ca->ca_activate)(dev, DVACT_ACTIVATE);
766 if (rv)
767 dev->dv_flags = oflags;
768 }
769 return (rv);
770 }
771
772 int
773 config_deactivate(struct device *dev)
774 {
775 struct cfattach *ca = dev->dv_cfdata->cf_attach;
776 int rv = 0, oflags = dev->dv_flags;
777
778 if (ca->ca_activate == NULL)
779 return (EOPNOTSUPP);
780
781 if (dev->dv_flags & DVF_ACTIVE) {
782 dev->dv_flags &= ~DVF_ACTIVE;
783 rv = (*ca->ca_activate)(dev, DVACT_DEACTIVATE);
784 if (rv)
785 dev->dv_flags = oflags;
786 }
787 return (rv);
788 }
789
790 /*
791 * Defer the configuration of the specified device until all
792 * of its parent's devices have been attached.
793 */
794 void
795 config_defer(struct device *dev, void (*func)(struct device *))
796 {
797 struct deferred_config *dc;
798
799 if (dev->dv_parent == NULL)
800 panic("config_defer: can't defer config of a root device");
801
802 #ifdef DIAGNOSTIC
803 for (dc = TAILQ_FIRST(&deferred_config_queue); dc != NULL;
804 dc = TAILQ_NEXT(dc, dc_queue)) {
805 if (dc->dc_dev == dev)
806 panic("config_defer: deferred twice");
807 }
808 #endif
809
810 dc = malloc(sizeof(*dc), M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
811 if (dc == NULL)
812 panic("config_defer: unable to allocate callback");
813
814 dc->dc_dev = dev;
815 dc->dc_func = func;
816 TAILQ_INSERT_TAIL(&deferred_config_queue, dc, dc_queue);
817 config_pending_incr();
818 }
819
820 /*
821 * Defer some autoconfiguration for a device until after interrupts
822 * are enabled.
823 */
824 void
825 config_interrupts(struct device *dev, void (*func)(struct device *))
826 {
827 struct deferred_config *dc;
828
829 /*
830 * If interrupts are enabled, callback now.
831 */
832 if (cold == 0) {
833 (*func)(dev);
834 return;
835 }
836
837 #ifdef DIAGNOSTIC
838 for (dc = TAILQ_FIRST(&interrupt_config_queue); dc != NULL;
839 dc = TAILQ_NEXT(dc, dc_queue)) {
840 if (dc->dc_dev == dev)
841 panic("config_interrupts: deferred twice");
842 }
843 #endif
844
845 dc = malloc(sizeof(*dc), M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
846 if (dc == NULL)
847 panic("config_interrupts: unable to allocate callback");
848
849 dc->dc_dev = dev;
850 dc->dc_func = func;
851 TAILQ_INSERT_TAIL(&interrupt_config_queue, dc, dc_queue);
852 config_pending_incr();
853 }
854
855 /*
856 * Process a deferred configuration queue.
857 */
858 static void
859 config_process_deferred(struct deferred_config_head *queue,
860 struct device *parent)
861 {
862 struct deferred_config *dc, *ndc;
863
864 for (dc = TAILQ_FIRST(queue); dc != NULL; dc = ndc) {
865 ndc = TAILQ_NEXT(dc, dc_queue);
866 if (parent == NULL || dc->dc_dev->dv_parent == parent) {
867 TAILQ_REMOVE(queue, dc, dc_queue);
868 (*dc->dc_func)(dc->dc_dev);
869 free(dc, M_DEVBUF);
870 config_pending_decr();
871 }
872 }
873 }
874
875 /*
876 * Manipulate the config_pending semaphore.
877 */
878 void
879 config_pending_incr(void)
880 {
881
882 config_pending++;
883 }
884
885 void
886 config_pending_decr(void)
887 {
888
889 #ifdef DIAGNOSTIC
890 if (config_pending == 0)
891 panic("config_pending_decr: config_pending == 0");
892 #endif
893 config_pending--;
894 if (config_pending == 0)
895 wakeup((void *)&config_pending);
896 }
897
898 /*
899 * Attach a statically-initialized event. The type and string pointers
900 * are already set up.
901 */
902 void
903 evcnt_attach_static(struct evcnt *ev)
904 {
905 int len;
906
907 len = strlen(ev->ev_group);
908 #ifdef DIAGNOSTIC
909 if (len >= EVCNT_STRING_MAX) /* ..._MAX includes NUL */
910 panic("evcnt_attach_static: group length (%s)", ev->ev_group);
911 #endif
912 ev->ev_grouplen = len;
913
914 len = strlen(ev->ev_name);
915 #ifdef DIAGNOSTIC
916 if (len >= EVCNT_STRING_MAX) /* ..._MAX includes NUL */
917 panic("evcnt_attach_static: name length (%s)", ev->ev_name);
918 #endif
919 ev->ev_namelen = len;
920
921 TAILQ_INSERT_TAIL(&allevents, ev, ev_list);
922 }
923
924 /*
925 * Attach a dynamically-initialized event. Zero it, set up the type
926 * and string pointers and then act like it was statically initialized.
927 */
928 void
929 evcnt_attach_dynamic(struct evcnt *ev, int type, const struct evcnt *parent,
930 const char *group, const char *name)
931 {
932
933 memset(ev, 0, sizeof *ev);
934 ev->ev_type = type;
935 ev->ev_parent = parent;
936 ev->ev_group = group;
937 ev->ev_name = name;
938 evcnt_attach_static(ev);
939 }
940
941 /*
942 * Detach an event.
943 */
944 void
945 evcnt_detach(struct evcnt *ev)
946 {
947
948 TAILQ_REMOVE(&allevents, ev, ev_list);
949 }
950
951 /*
952 * Device property management routines.
953 */
954 #ifdef DEBUG
955 int devprop_debug = 0;
956 #endif
957
958 /*
959 * Create a dummy device you can attach properties to.
960 */
961 struct device *
962 dev_config_create(struct device *parent, int wait)
963 {
964 struct device *dev;
965
966 dev = dev_create(parent, 0, wait ? M_WAITOK : M_NOWAIT);
967 return (dev);
968 }
969
970
971 int
972 dev_setprop(struct device *dev, const char *name, void *val,
973 size_t len, int type, int wait)
974 {
975 #ifdef DEBUG
976 if (devprop_debug)
977 printf("dev_setprop(%p, %s, %p %s, %ld, %x, %d)\n",
978 dev, name, val, (PROP_TYPE(type) == PROP_STRING) ?
979 (char *)val : "", (u_long)len, type, wait);
980 #endif
981
982 return (prop_set(devpropdb, dev, name, val, len, type, wait));
983 }
984
985 size_t
986 dev_getprop(struct device *dev, const char *name, void *val,
987 size_t len, int *type, int search)
988 {
989 ssize_t rv;
990
991 #ifdef DEBUG
992 if (devprop_debug) {
993 printf("dev_getprop(%p, %s, %p, %ld, %p, %d)\n",
994 dev, name, val, (u_long)len, type, search);
995 }
996 #endif
997 rv = prop_get(devpropdb, dev, name, val, len, type);
998 #if defined(dev_mdgetprop)
999 if (rv == -1) {
1000 /* Not found -- try md_getprop */
1001 rv = dev_mdgetprop(dev, name, val,
1002 len, type);
1003 }
1004 #endif
1005 if ((rv == -1) && search) {
1006 if (dev->dv_parent)
1007 /* Tail recursion -- there should be no stack growth. */
1008 return (dev_getprop(dev->dv_parent, name,
1009 val, len, type, search));
1010 }
1011 #ifdef DEBUG
1012 if (devprop_debug && (rv == -1)) {
1013 printf("%s no found\n", name);
1014 }
1015 #endif
1016 return (rv);
1017 }
1018
1019 int
1020 dev_delprop(struct device *dev, const char *name)
1021 {
1022
1023 #ifdef DEBUG_N
1024 if (devprop_debug)
1025 printf("dev_delprop(%p, %s, %x)\n", dev, name);
1026 #endif
1027 return (prop_delete(devpropdb, dev, name));
1028 }
1029
1030
1031 int
1032 dev_copyprops(struct device *src, struct device *dest, int wait)
1033 {
1034 return (prop_copy(devpropdb, src, dest, wait));
1035 }
1036
1037 /*
1038 * For debug: print some of the properties associated with a device.
1039 *
1040 * XXX not reentrant.
1041 */
1042 #ifdef DEBUG
1043 void
1044 dev_dumprops(struct device *dev)
1045 {
1046 size_t len;
1047 int i;
1048 static char buf[2048];
1049
1050 len = prop_list(devpropdb, dev, buf, sizeof(buf));
1051
1052 printf("Device %p has:\n", dev);
1053 while (i < len) {
1054 printf("%s\n", &buf[i]);
1055 i += strlen(&buf[i]);
1056 }
1057 }
1058 #endif
1059
1060 #ifdef DDB
1061 void
1062 event_print(int full, void (*pr)(const char *, ...))
1063 {
1064 struct evcnt *evp;
1065
1066 TAILQ_FOREACH(evp, &allevents, ev_list) {
1067 if (evp->ev_count == 0 && !full)
1068 continue;
1069
1070 (*pr)("evcnt type %d: %s %s = %lld\n", evp->ev_type,
1071 evp->ev_group, evp->ev_name, evp->ev_count);
1072 }
1073 }
1074 #endif /* DDB */
1075