subr_autoconf.c revision 1.42 1 /* $NetBSD: subr_autoconf.c,v 1.42 1999/09/15 19:37:08 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This software was developed by the Computer Systems Engineering group
8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9 * contributed to Berkeley.
10 *
11 * All advertising materials mentioning features or use of this software
12 * must display the following acknowledgement:
13 * This product includes software developed by the University of
14 * California, Lawrence Berkeley Laboratories.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. All advertising materials mentioning features or use of this software
25 * must display the following acknowledgement:
26 * This product includes software developed by the University of
27 * California, Berkeley and its contributors.
28 * 4. Neither the name of the University nor the names of its contributors
29 * may be used to endorse or promote products derived from this software
30 * without specific prior written permission.
31 *
32 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 * SUCH DAMAGE.
43 *
44 * from: Header: subr_autoconf.c,v 1.12 93/02/01 19:31:48 torek Exp (LBL)
45 *
46 * @(#)subr_autoconf.c 8.3 (Berkeley) 5/17/94
47 */
48
49 #include <sys/param.h>
50 #include <sys/device.h>
51 #include <sys/malloc.h>
52 #include <sys/systm.h>
53 #include <sys/errno.h>
54 #include <machine/limits.h>
55
56 /*
57 * Autoconfiguration subroutines.
58 */
59
60 /*
61 * ioconf.c exports exactly two names: cfdata and cfroots. All system
62 * devices and drivers are found via these tables.
63 */
64 extern struct cfdata cfdata[];
65 extern short cfroots[];
66
67 #define ROOT ((struct device *)NULL)
68
69 struct matchinfo {
70 cfmatch_t fn;
71 struct device *parent;
72 void *aux;
73 struct cfdata *match;
74 int pri;
75 };
76
77 static char *number __P((char *, int));
78 static void mapply __P((struct matchinfo *, struct cfdata *));
79
80 struct deferred_config {
81 TAILQ_ENTRY(deferred_config) dc_queue;
82 struct device *dc_dev;
83 void (*dc_func) __P((struct device *));
84 };
85
86 TAILQ_HEAD(deferred_config_head, deferred_config);
87
88 struct deferred_config_head deferred_config_queue;
89 struct deferred_config_head interrupt_config_queue;
90
91 static void config_process_deferred __P((struct deferred_config_head *,
92 struct device *));
93
94 struct devicelist alldevs; /* list of all devices */
95 struct evcntlist allevents; /* list of all event counters */
96
97 /*
98 * This variable indicates, from the configuration machinery's point of
99 * view, if interrupts are enabled. They start disabled, and are
100 * considered enabled once cpu_configure() returns.
101 */
102 int config_interrupts_enabled;
103
104 /*
105 * Configure the system's hardware.
106 */
107 void
108 configure()
109 {
110
111 TAILQ_INIT(&deferred_config_queue);
112 TAILQ_INIT(&interrupt_config_queue);
113 TAILQ_INIT(&alldevs);
114 TAILQ_INIT(&allevents);
115
116 /*
117 * Do the machine-dependent portion of autoconfiguration. This
118 * sets the configuration machinery here in motion by "finding"
119 * the root bus. When this function returns, we expect interrupts
120 * to be enabled.
121 */
122 cpu_configure();
123 config_interrupts_enabled = 1;
124
125 /*
126 * Now callback to finish configuration for devices which want
127 * to do this once interrupts are enabled.
128 */
129 config_process_deferred(&interrupt_config_queue, NULL);
130 }
131
132 /*
133 * Apply the matching function and choose the best. This is used
134 * a few times and we want to keep the code small.
135 */
136 static void
137 mapply(m, cf)
138 register struct matchinfo *m;
139 register struct cfdata *cf;
140 {
141 register int pri;
142
143 if (m->fn != NULL)
144 pri = (*m->fn)(m->parent, cf, m->aux);
145 else {
146 if (cf->cf_attach->ca_match == NULL) {
147 panic("mapply: no match function for '%s' device\n",
148 cf->cf_driver->cd_name);
149 }
150 pri = (*cf->cf_attach->ca_match)(m->parent, cf, m->aux);
151 }
152 if (pri > m->pri) {
153 m->match = cf;
154 m->pri = pri;
155 }
156 }
157
158 /*
159 * Iterate over all potential children of some device, calling the given
160 * function (default being the child's match function) for each one.
161 * Nonzero returns are matches; the highest value returned is considered
162 * the best match. Return the `found child' if we got a match, or NULL
163 * otherwise. The `aux' pointer is simply passed on through.
164 *
165 * Note that this function is designed so that it can be used to apply
166 * an arbitrary function to all potential children (its return value
167 * can be ignored).
168 */
169 struct cfdata *
170 config_search(fn, parent, aux)
171 cfmatch_t fn;
172 register struct device *parent;
173 void *aux;
174 {
175 register struct cfdata *cf;
176 register short *p;
177 struct matchinfo m;
178
179 m.fn = fn;
180 m.parent = parent;
181 m.aux = aux;
182 m.match = NULL;
183 m.pri = 0;
184 for (cf = cfdata; cf->cf_driver; cf++) {
185 /*
186 * Skip cf if no longer eligible, otherwise scan through
187 * parents for one matching `parent', and try match function.
188 */
189 if (cf->cf_fstate == FSTATE_FOUND)
190 continue;
191 for (p = cf->cf_parents; *p >= 0; p++)
192 if (parent->dv_cfdata == &cfdata[*p])
193 mapply(&m, cf);
194 }
195 return (m.match);
196 }
197
198 /*
199 * Find the given root device.
200 * This is much like config_search, but there is no parent.
201 */
202 struct cfdata *
203 config_rootsearch(fn, rootname, aux)
204 register cfmatch_t fn;
205 register char *rootname;
206 register void *aux;
207 {
208 register struct cfdata *cf;
209 register short *p;
210 struct matchinfo m;
211
212 m.fn = fn;
213 m.parent = ROOT;
214 m.aux = aux;
215 m.match = NULL;
216 m.pri = 0;
217 /*
218 * Look at root entries for matching name. We do not bother
219 * with found-state here since only one root should ever be
220 * searched (and it must be done first).
221 */
222 for (p = cfroots; *p >= 0; p++) {
223 cf = &cfdata[*p];
224 if (strcmp(cf->cf_driver->cd_name, rootname) == 0)
225 mapply(&m, cf);
226 }
227 return (m.match);
228 }
229
230 static char *msgs[3] = { "", " not configured\n", " unsupported\n" };
231
232 /*
233 * The given `aux' argument describes a device that has been found
234 * on the given parent, but not necessarily configured. Locate the
235 * configuration data for that device (using the submatch function
236 * provided, or using candidates' cd_match configuration driver
237 * functions) and attach it, and return true. If the device was
238 * not configured, call the given `print' function and return 0.
239 */
240 struct device *
241 config_found_sm(parent, aux, print, submatch)
242 struct device *parent;
243 void *aux;
244 cfprint_t print;
245 cfmatch_t submatch;
246 {
247 struct cfdata *cf;
248
249 if ((cf = config_search(submatch, parent, aux)) != NULL)
250 return (config_attach(parent, cf, aux, print));
251 if (print)
252 printf(msgs[(*print)(aux, parent->dv_xname)]);
253 return (NULL);
254 }
255
256 /*
257 * As above, but for root devices.
258 */
259 struct device *
260 config_rootfound(rootname, aux)
261 char *rootname;
262 void *aux;
263 {
264 struct cfdata *cf;
265
266 if ((cf = config_rootsearch((cfmatch_t)NULL, rootname, aux)) != NULL)
267 return (config_attach(ROOT, cf, aux, (cfprint_t)NULL));
268 printf("root device %s not configured\n", rootname);
269 return (NULL);
270 }
271
272 /* just like sprintf(buf, "%d") except that it works from the end */
273 static char *
274 number(ep, n)
275 register char *ep;
276 register int n;
277 {
278
279 *--ep = 0;
280 while (n >= 10) {
281 *--ep = (n % 10) + '0';
282 n /= 10;
283 }
284 *--ep = n + '0';
285 return (ep);
286 }
287
288 /*
289 * Attach a found device. Allocates memory for device variables.
290 */
291 struct device *
292 config_attach(parent, cf, aux, print)
293 register struct device *parent;
294 register struct cfdata *cf;
295 register void *aux;
296 cfprint_t print;
297 {
298 register struct device *dev;
299 register struct cfdriver *cd;
300 register struct cfattach *ca;
301 register size_t lname, lunit;
302 register char *xunit;
303 int myunit;
304 char num[10];
305
306 cd = cf->cf_driver;
307 ca = cf->cf_attach;
308 if (ca->ca_devsize < sizeof(struct device))
309 panic("config_attach");
310 myunit = cf->cf_unit;
311 if (cf->cf_fstate == FSTATE_STAR)
312 cf->cf_unit++;
313 else {
314 KASSERT(cf->cf_fstate == FSTATE_NOTFOUND);
315 cf->cf_fstate = FSTATE_FOUND;
316 }
317
318 /* compute length of name and decimal expansion of unit number */
319 lname = strlen(cd->cd_name);
320 xunit = number(&num[sizeof(num)], myunit);
321 lunit = &num[sizeof(num)] - xunit;
322 if (lname + lunit >= sizeof(dev->dv_xname))
323 panic("config_attach: device name too long");
324
325 /* get memory for all device vars */
326 dev = (struct device *)malloc(ca->ca_devsize, M_DEVBUF, M_NOWAIT);
327 if (!dev)
328 panic("config_attach: memory allocation for device softc failed");
329 memset(dev, 0, ca->ca_devsize);
330 TAILQ_INSERT_TAIL(&alldevs, dev, dv_list); /* link up */
331 dev->dv_class = cd->cd_class;
332 dev->dv_cfdata = cf;
333 dev->dv_unit = myunit;
334 memcpy(dev->dv_xname, cd->cd_name, lname);
335 memcpy(dev->dv_xname + lname, xunit, lunit);
336 dev->dv_parent = parent;
337 dev->dv_flags = DVF_ACTIVE; /* always initially active */
338
339 if (parent == ROOT)
340 printf("%s (root)", dev->dv_xname);
341 else {
342 printf("%s at %s", dev->dv_xname, parent->dv_xname);
343 if (print)
344 (void) (*print)(aux, (char *)0);
345 }
346
347 /* put this device in the devices array */
348 if (dev->dv_unit >= cd->cd_ndevs) {
349 /*
350 * Need to expand the array.
351 */
352 int old = cd->cd_ndevs, new;
353 void **nsp;
354
355 if (old == 0)
356 new = MINALLOCSIZE / sizeof(void *);
357 else
358 new = old * 2;
359 while (new <= dev->dv_unit)
360 new *= 2;
361 cd->cd_ndevs = new;
362 nsp = malloc(new * sizeof(void *), M_DEVBUF, M_NOWAIT);
363 if (nsp == 0)
364 panic("config_attach: %sing dev array",
365 old != 0 ? "expand" : "creat");
366 memset(nsp + old, 0, (new - old) * sizeof(void *));
367 if (old != 0) {
368 memcpy(nsp, cd->cd_devs, old * sizeof(void *));
369 free(cd->cd_devs, M_DEVBUF);
370 }
371 cd->cd_devs = nsp;
372 }
373 if (cd->cd_devs[dev->dv_unit])
374 panic("config_attach: duplicate %s", dev->dv_xname);
375 cd->cd_devs[dev->dv_unit] = dev;
376
377 /*
378 * Before attaching, clobber any unfound devices that are
379 * otherwise identical, or bump the unit number on all starred
380 * cfdata for this device.
381 */
382 for (cf = cfdata; cf->cf_driver; cf++)
383 if (cf->cf_driver == cd && cf->cf_unit == dev->dv_unit) {
384 if (cf->cf_fstate == FSTATE_NOTFOUND)
385 cf->cf_fstate = FSTATE_FOUND;
386 if (cf->cf_fstate == FSTATE_STAR)
387 cf->cf_unit++;
388 }
389 #if defined(__alpha__) || defined(hp300) || defined(__i386__) || \
390 defined(__sparc__) || defined(__vax__)
391 device_register(dev, aux);
392 #endif
393 (*ca->ca_attach)(parent, dev, aux);
394 config_process_deferred(&deferred_config_queue, dev);
395 return (dev);
396 }
397
398 /*
399 * Detach a device. Optionally forced (e.g. because of hardware
400 * removal) and quiet. Returns zero if successful, non-zero
401 * (an error code) otherwise.
402 *
403 * Note that this code wants to be run from a process context, so
404 * that the detach can sleep to allow processes which have a device
405 * open to run and unwind their stacks.
406 */
407 int
408 config_detach(dev, flags)
409 struct device *dev;
410 int flags;
411 {
412 struct cfdata *cf;
413 struct cfattach *ca;
414 struct cfdriver *cd;
415 #ifdef DIAGNOSTIC
416 struct device *d;
417 #endif
418 int rv = 0, i;
419
420 cf = dev->dv_cfdata;
421 #ifdef DIAGNOSTIC
422 if (cf->cf_fstate != FSTATE_FOUND && cf->cf_fstate != FSTATE_STAR)
423 panic("config_detach: bad device fstate");
424 #endif
425 ca = cf->cf_attach;
426 cd = cf->cf_driver;
427
428 /*
429 * Ensure the device is deactivated. If the device doesn't
430 * have an activation entry point, we allow DVF_ACTIVE to
431 * remain set. Otherwise, if DVF_ACTIVE is still set, the
432 * device is busy, and the detach fails.
433 */
434 if (ca->ca_activate != NULL)
435 rv = config_deactivate(dev);
436
437 /*
438 * Try to detach the device. If that's not possible, then
439 * we either panic() (for the forced but failed case), or
440 * return an error.
441 */
442 if (rv == 0) {
443 if (ca->ca_detach != NULL)
444 rv = (*ca->ca_detach)(dev, flags);
445 else
446 rv = EOPNOTSUPP;
447 }
448 if (rv != 0) {
449 if ((flags & DETACH_FORCE) == 0)
450 return (rv);
451 else
452 panic("config_detach: forced detach of %s failed (%d)",
453 dev->dv_xname, rv);
454 }
455
456 /*
457 * The device has now been successfully detached.
458 */
459
460 #ifdef DIAGNOSTIC
461 /*
462 * Sanity: If you're successfully detached, you should have no
463 * children. (Note that because children must be attached
464 * after parents, we only need to search the latter part of
465 * the list.)
466 */
467 for (d = TAILQ_NEXT(dev, dv_list); d != NULL;
468 d = TAILQ_NEXT(d, dv_list)) {
469 if (d->dv_parent == dev)
470 panic("config_detach: detached device has children");
471 }
472 #endif
473
474 /*
475 * Mark cfdata to show that the unit can be reused, if possible.
476 * Note that we can only re-use a starred unit number if the unit
477 * being detached had the last assigned unit number.
478 */
479 for (cf = cfdata; cf->cf_driver; cf++) {
480 if (cf->cf_driver == cd) {
481 if (cf->cf_fstate == FSTATE_FOUND &&
482 cf->cf_unit == dev->dv_unit)
483 cf->cf_fstate = FSTATE_NOTFOUND;
484 if (cf->cf_fstate == FSTATE_STAR &&
485 cf->cf_unit == dev->dv_unit + 1)
486 cf->cf_unit--;
487 }
488 }
489
490 /*
491 * Unlink from device list.
492 */
493 TAILQ_REMOVE(&alldevs, dev, dv_list);
494
495 /*
496 * Remove from cfdriver's array, tell the world, and free softc.
497 */
498 cd->cd_devs[dev->dv_unit] = NULL;
499 if ((flags & DETACH_QUIET) == 0)
500 printf("%s detached\n", dev->dv_xname);
501 free(dev, M_DEVBUF);
502
503 /*
504 * If the device now has no units in use, deallocate its softc array.
505 */
506 for (i = 0; i < cd->cd_ndevs; i++)
507 if (cd->cd_devs[i] != NULL)
508 break;
509 if (i == cd->cd_ndevs) { /* nothing found; deallocate */
510 free(cd->cd_devs, M_DEVBUF);
511 cd->cd_devs = NULL;
512 cd->cd_ndevs = 0;
513 }
514
515 /*
516 * Return success.
517 */
518 return (0);
519 }
520
521 int
522 config_activate(dev)
523 struct device *dev;
524 {
525 struct cfattach *ca = dev->dv_cfdata->cf_attach;
526 int rv = 0, oflags = dev->dv_flags;
527
528 if (ca->ca_activate == NULL)
529 return (EOPNOTSUPP);
530
531 if ((dev->dv_flags & DVF_ACTIVE) == 0) {
532 dev->dv_flags |= DVF_ACTIVE;
533 rv = (*ca->ca_activate)(dev, DVACT_ACTIVATE);
534 if (rv)
535 dev->dv_flags = oflags;
536 }
537 return (rv);
538 }
539
540 int
541 config_deactivate(dev)
542 struct device *dev;
543 {
544 struct cfattach *ca = dev->dv_cfdata->cf_attach;
545 int rv = 0, oflags = dev->dv_flags;
546
547 if (ca->ca_activate == NULL)
548 return (EOPNOTSUPP);
549
550 if (dev->dv_flags & DVF_ACTIVE) {
551 dev->dv_flags &= ~DVF_ACTIVE;
552 rv = (*ca->ca_activate)(dev, DVACT_DEACTIVATE);
553 if (rv)
554 dev->dv_flags = oflags;
555 }
556 return (rv);
557 }
558
559 /*
560 * Defer the configuration of the specified device until all
561 * of its parent's devices have been attached.
562 */
563 void
564 config_defer(dev, func)
565 struct device *dev;
566 void (*func) __P((struct device *));
567 {
568 struct deferred_config *dc;
569
570 if (dev->dv_parent == NULL)
571 panic("config_defer: can't defer config of a root device");
572
573 #ifdef DIAGNOSTIC
574 for (dc = TAILQ_FIRST(&deferred_config_queue); dc != NULL;
575 dc = TAILQ_NEXT(dc, dc_queue)) {
576 if (dc->dc_dev == dev)
577 panic("config_defer: deferred twice");
578 }
579 #endif
580
581 dc = malloc(sizeof(*dc), M_DEVBUF, M_WAITOK);
582
583 dc->dc_dev = dev;
584 dc->dc_func = func;
585 TAILQ_INSERT_TAIL(&deferred_config_queue, dc, dc_queue);
586 }
587
588 /*
589 * Defer some autoconfiguration for a device until after interrupts
590 * are enabled.
591 */
592 void
593 config_interrupts(dev, func)
594 struct device *dev;
595 void (*func) __P((struct device *));
596 {
597 struct deferred_config *dc;
598
599 /*
600 * If interrupts are enabled, callback now.
601 */
602 if (config_interrupts_enabled) {
603 (*func)(dev);
604 return;
605 }
606
607 #ifdef DIAGNOSTIC
608 for (dc = TAILQ_FIRST(&interrupt_config_queue); dc != NULL;
609 dc = TAILQ_NEXT(dc, dc_queue)) {
610 if (dc->dc_dev == dev)
611 panic("config_interrupts: deferred twice");
612 }
613 #endif
614
615 dc = malloc(sizeof(*dc), M_DEVBUF, M_WAITOK);
616
617 dc->dc_dev = dev;
618 dc->dc_func = func;
619 TAILQ_INSERT_TAIL(&interrupt_config_queue, dc, dc_queue);
620 }
621
622 /*
623 * Process a deferred configuration queue.
624 */
625 static void
626 config_process_deferred(queue, parent)
627 struct deferred_config_head *queue;
628 struct device *parent;
629 {
630 struct deferred_config *dc, *ndc;
631
632 for (dc = TAILQ_FIRST(queue); dc != NULL; dc = ndc) {
633 ndc = TAILQ_NEXT(dc, dc_queue);
634 if (parent == NULL || dc->dc_dev->dv_parent == parent) {
635 TAILQ_REMOVE(queue, dc, dc_queue);
636 (*dc->dc_func)(dc->dc_dev);
637 free(dc, M_DEVBUF);
638 }
639 }
640 }
641
642 /*
643 * Attach an event. These must come from initially-zero space (see
644 * commented-out assignments below), but that occurs naturally for
645 * device instance variables.
646 */
647 void
648 evcnt_attach(dev, name, ev)
649 struct device *dev;
650 const char *name;
651 struct evcnt *ev;
652 {
653
654 #ifdef DIAGNOSTIC
655 if (strlen(name) >= sizeof(ev->ev_name))
656 panic("evcnt_attach");
657 #endif
658 /* ev->ev_next = NULL; */
659 ev->ev_dev = dev;
660 /* ev->ev_count = 0; */
661 strcpy(ev->ev_name, name);
662 TAILQ_INSERT_TAIL(&allevents, ev, ev_list);
663 }
664
665 /*
666 * Detach an event.
667 */
668 void
669 evcnt_detach(ev)
670 struct evcnt *ev;
671 {
672
673 TAILQ_REMOVE(&allevents, ev, ev_list);
674 }
675