subr_autoconf.c revision 1.51 1 /* $NetBSD: subr_autoconf.c,v 1.51 2000/06/02 01:31:54 cgd 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/cdefs.h>
50
51 __KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.51 2000/06/02 01:31:54 cgd Exp $");
52
53 #include <sys/param.h>
54 #include <sys/device.h>
55 #include <sys/malloc.h>
56 #include <sys/systm.h>
57 #include <sys/kernel.h>
58 #include <sys/errno.h>
59 #include <sys/proc.h>
60 #include <machine/limits.h>
61
62 /*
63 * Autoconfiguration subroutines.
64 */
65
66 /*
67 * ioconf.c exports exactly two names: cfdata and cfroots. All system
68 * devices and drivers are found via these tables.
69 */
70 extern struct cfdata cfdata[];
71 extern short cfroots[];
72
73 #define ROOT ((struct device *)NULL)
74
75 struct matchinfo {
76 cfmatch_t fn;
77 struct device *parent;
78 void *aux;
79 struct cfdata *match;
80 int pri;
81 };
82
83 static char *number(char *, int);
84 static void mapply(struct matchinfo *, struct cfdata *);
85
86 struct deferred_config {
87 TAILQ_ENTRY(deferred_config) dc_queue;
88 struct device *dc_dev;
89 void (*dc_func)(struct device *);
90 };
91
92 TAILQ_HEAD(deferred_config_head, deferred_config);
93
94 struct deferred_config_head deferred_config_queue;
95 struct deferred_config_head interrupt_config_queue;
96
97 static void config_process_deferred(struct deferred_config_head *,
98 struct device *);
99
100 struct devicelist alldevs; /* list of all devices */
101 struct evcntlist allevents; /* list of all event counters */
102
103 __volatile int config_pending; /* semaphore for mountroot */
104
105 /*
106 * Configure the system's hardware.
107 */
108 void
109 configure(void)
110 {
111
112 TAILQ_INIT(&deferred_config_queue);
113 TAILQ_INIT(&interrupt_config_queue);
114 TAILQ_INIT(&alldevs);
115 TAILQ_INIT(&allevents);
116
117 /*
118 * Do the machine-dependent portion of autoconfiguration. This
119 * sets the configuration machinery here in motion by "finding"
120 * the root bus. When this function returns, we expect interrupts
121 * to be enabled.
122 */
123 cpu_configure();
124
125 /*
126 * Now that we've found all the hardware, start the real time
127 * and statistics clocks.
128 */
129 initclocks();
130
131 cold = 0; /* clocks are running, we're warm now! */
132
133 /*
134 * Now callback to finish configuration for devices which want
135 * to do this once interrupts are enabled.
136 */
137 config_process_deferred(&interrupt_config_queue, NULL);
138 }
139
140 /*
141 * Apply the matching function and choose the best. This is used
142 * a few times and we want to keep the code small.
143 */
144 static void
145 mapply(struct matchinfo *m, struct cfdata *cf)
146 {
147 int pri;
148
149 if (m->fn != NULL)
150 pri = (*m->fn)(m->parent, cf, m->aux);
151 else {
152 if (cf->cf_attach->ca_match == NULL) {
153 panic("mapply: no match function for '%s' device\n",
154 cf->cf_driver->cd_name);
155 }
156 pri = (*cf->cf_attach->ca_match)(m->parent, cf, m->aux);
157 }
158 if (pri > m->pri) {
159 m->match = cf;
160 m->pri = pri;
161 }
162 }
163
164 /*
165 * Iterate over all potential children of some device, calling the given
166 * function (default being the child's match function) for each one.
167 * Nonzero returns are matches; the highest value returned is considered
168 * the best match. Return the `found child' if we got a match, or NULL
169 * otherwise. The `aux' pointer is simply passed on through.
170 *
171 * Note that this function is designed so that it can be used to apply
172 * an arbitrary function to all potential children (its return value
173 * can be ignored).
174 */
175 struct cfdata *
176 config_search(cfmatch_t fn, struct device *parent, void *aux)
177 {
178 struct cfdata *cf;
179 short *p;
180 struct matchinfo m;
181
182 m.fn = fn;
183 m.parent = parent;
184 m.aux = aux;
185 m.match = NULL;
186 m.pri = 0;
187 for (cf = cfdata; cf->cf_driver; cf++) {
188 /*
189 * Skip cf if no longer eligible, otherwise scan through
190 * parents for one matching `parent', and try match function.
191 */
192 if (cf->cf_fstate == FSTATE_FOUND)
193 continue;
194 for (p = cf->cf_parents; *p >= 0; p++)
195 if (parent->dv_cfdata == &cfdata[*p])
196 mapply(&m, cf);
197 }
198 return (m.match);
199 }
200
201 /*
202 * Find the given root device.
203 * This is much like config_search, but there is no parent.
204 */
205 struct cfdata *
206 config_rootsearch(cfmatch_t fn, char *rootname, void *aux)
207 {
208 struct cfdata *cf;
209 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(struct device *parent, void *aux, cfprint_t print,
242 cfmatch_t submatch)
243 {
244 struct cfdata *cf;
245
246 if ((cf = config_search(submatch, parent, aux)) != NULL)
247 return (config_attach(parent, cf, aux, print));
248 if (print)
249 printf(msgs[(*print)(aux, parent->dv_xname)]);
250 return (NULL);
251 }
252
253 /*
254 * As above, but for root devices.
255 */
256 struct device *
257 config_rootfound(char *rootname, void *aux)
258 {
259 struct cfdata *cf;
260
261 if ((cf = config_rootsearch((cfmatch_t)NULL, rootname, aux)) != NULL)
262 return (config_attach(ROOT, cf, aux, (cfprint_t)NULL));
263 printf("root device %s not configured\n", rootname);
264 return (NULL);
265 }
266
267 /* just like sprintf(buf, "%d") except that it works from the end */
268 static char *
269 number(char *ep, int n)
270 {
271
272 *--ep = 0;
273 while (n >= 10) {
274 *--ep = (n % 10) + '0';
275 n /= 10;
276 }
277 *--ep = n + '0';
278 return (ep);
279 }
280
281 /*
282 * Attach a found device. Allocates memory for device variables.
283 */
284 struct device *
285 config_attach(struct device *parent, struct cfdata *cf, void *aux,
286 cfprint_t print)
287 {
288 struct device *dev;
289 struct cfdriver *cd;
290 struct cfattach *ca;
291 size_t lname, lunit;
292 char *xunit;
293 int myunit;
294 char num[10];
295
296 cd = cf->cf_driver;
297 ca = cf->cf_attach;
298 if (ca->ca_devsize < sizeof(struct device))
299 panic("config_attach");
300 #ifndef __BROKEN_CONFIG_UNIT_USAGE
301 if (cf->cf_fstate == FSTATE_STAR) {
302 for (myunit = cf->cf_unit; myunit < cd->cd_ndevs; myunit++)
303 if (cd->cd_devs[myunit] == NULL)
304 break;
305 /*
306 * myunit is now the unit of the first NULL device pointer,
307 * or max(cd->cd_ndevs,cf->cf_unit).
308 */
309 } else {
310 myunit = cf->cf_unit;
311 #else /* __BROKEN_CONFIG_UNIT_USAGE */
312 myunit = cf->cf_unit;
313 if (cf->cf_fstate == FSTATE_STAR)
314 cf->cf_unit++;
315 else {
316 #endif /* __BROKEN_CONFIG_UNIT_USAGE */
317 KASSERT(cf->cf_fstate == FSTATE_NOTFOUND);
318 cf->cf_fstate = FSTATE_FOUND;
319 }
320
321 /* compute length of name and decimal expansion of unit number */
322 lname = strlen(cd->cd_name);
323 xunit = number(&num[sizeof(num)], myunit);
324 lunit = &num[sizeof(num)] - xunit;
325 if (lname + lunit >= sizeof(dev->dv_xname))
326 panic("config_attach: device name too long");
327
328 /* get memory for all device vars */
329 dev = (struct device *)malloc(ca->ca_devsize, M_DEVBUF,
330 cold ? M_NOWAIT : M_WAITOK);
331 if (!dev)
332 panic("config_attach: memory allocation for device softc failed");
333 memset(dev, 0, ca->ca_devsize);
334 TAILQ_INSERT_TAIL(&alldevs, dev, dv_list); /* link up */
335 dev->dv_class = cd->cd_class;
336 dev->dv_cfdata = cf;
337 dev->dv_unit = myunit;
338 memcpy(dev->dv_xname, cd->cd_name, lname);
339 memcpy(dev->dv_xname + lname, xunit, lunit);
340 dev->dv_parent = parent;
341 dev->dv_flags = DVF_ACTIVE; /* always initially active */
342
343 if (parent == ROOT)
344 printf("%s (root)", dev->dv_xname);
345 else {
346 printf("%s at %s", dev->dv_xname, parent->dv_xname);
347 if (print)
348 (void) (*print)(aux, (char *)0);
349 }
350
351 /* put this device in the devices array */
352 if (dev->dv_unit >= cd->cd_ndevs) {
353 /*
354 * Need to expand the array.
355 */
356 int old = cd->cd_ndevs, new;
357 void **nsp;
358
359 if (old == 0)
360 new = MINALLOCSIZE / sizeof(void *);
361 else
362 new = old * 2;
363 while (new <= dev->dv_unit)
364 new *= 2;
365 cd->cd_ndevs = new;
366 nsp = malloc(new * sizeof(void *), M_DEVBUF,
367 cold ? M_NOWAIT : M_WAITOK);
368 if (nsp == 0)
369 panic("config_attach: %sing dev array",
370 old != 0 ? "expand" : "creat");
371 memset(nsp + old, 0, (new - old) * sizeof(void *));
372 if (old != 0) {
373 memcpy(nsp, cd->cd_devs, old * sizeof(void *));
374 free(cd->cd_devs, M_DEVBUF);
375 }
376 cd->cd_devs = nsp;
377 }
378 if (cd->cd_devs[dev->dv_unit])
379 panic("config_attach: duplicate %s", dev->dv_xname);
380 cd->cd_devs[dev->dv_unit] = dev;
381
382 /*
383 * Before attaching, clobber any unfound devices that are
384 * otherwise identical.
385 */
386 #ifdef __BROKEN_CONFIG_UNIT_USAGE
387 /* bump the unit number on all starred cfdata for this device. */
388 #endif /* __BROKEN_CONFIG_UNIT_USAGE */
389 for (cf = cfdata; cf->cf_driver; cf++)
390 if (cf->cf_driver == cd && cf->cf_unit == dev->dv_unit) {
391 if (cf->cf_fstate == FSTATE_NOTFOUND)
392 cf->cf_fstate = FSTATE_FOUND;
393 #ifdef __BROKEN_CONFIG_UNIT_USAGE
394 if (cf->cf_fstate == FSTATE_STAR)
395 cf->cf_unit++;
396 #endif /* __BROKEN_CONFIG_UNIT_USAGE */
397 }
398 #ifdef __HAVE_DEVICE_REGISTER
399 device_register(dev, aux);
400 #endif
401 (*ca->ca_attach)(parent, dev, aux);
402 config_process_deferred(&deferred_config_queue, dev);
403 return (dev);
404 }
405
406 /*
407 * Detach a device. Optionally forced (e.g. because of hardware
408 * removal) and quiet. Returns zero if successful, non-zero
409 * (an error code) otherwise.
410 *
411 * Note that this code wants to be run from a process context, so
412 * that the detach can sleep to allow processes which have a device
413 * open to run and unwind their stacks.
414 */
415 int
416 config_detach(struct device *dev, int flags)
417 {
418 struct cfdata *cf;
419 struct cfattach *ca;
420 struct cfdriver *cd;
421 #ifdef DIAGNOSTIC
422 struct device *d;
423 #endif
424 int rv = 0, i;
425
426 cf = dev->dv_cfdata;
427 #ifdef DIAGNOSTIC
428 if (cf->cf_fstate != FSTATE_FOUND && cf->cf_fstate != FSTATE_STAR)
429 panic("config_detach: bad device fstate");
430 #endif
431 ca = cf->cf_attach;
432 cd = cf->cf_driver;
433
434 /*
435 * Ensure the device is deactivated. If the device doesn't
436 * have an activation entry point, we allow DVF_ACTIVE to
437 * remain set. Otherwise, if DVF_ACTIVE is still set, the
438 * device is busy, and the detach fails.
439 */
440 if (ca->ca_activate != NULL)
441 rv = config_deactivate(dev);
442
443 /*
444 * Try to detach the device. If that's not possible, then
445 * we either panic() (for the forced but failed case), or
446 * return an error.
447 */
448 if (rv == 0) {
449 if (ca->ca_detach != NULL)
450 rv = (*ca->ca_detach)(dev, flags);
451 else
452 rv = EOPNOTSUPP;
453 }
454 if (rv != 0) {
455 if ((flags & DETACH_FORCE) == 0)
456 return (rv);
457 else
458 panic("config_detach: forced detach of %s failed (%d)",
459 dev->dv_xname, rv);
460 }
461
462 /*
463 * The device has now been successfully detached.
464 */
465
466 #ifdef DIAGNOSTIC
467 /*
468 * Sanity: If you're successfully detached, you should have no
469 * children. (Note that because children must be attached
470 * after parents, we only need to search the latter part of
471 * the list.)
472 */
473 for (d = TAILQ_NEXT(dev, dv_list); d != NULL;
474 d = TAILQ_NEXT(d, dv_list)) {
475 if (d->dv_parent == dev) {
476 printf("config_detach: detached device %s"
477 " has children %s\n", dev->dv_xname, d->dv_xname);
478 panic("config_detach");
479 }
480 }
481 #endif
482
483 /*
484 * Mark cfdata to show that the unit can be reused, if possible.
485 */
486 #ifdef __BROKEN_CONFIG_UNIT_USAGE
487 /*
488 * Note that we can only re-use a starred unit number if the unit
489 * being detached had the last assigned unit number.
490 */
491 #endif /* __BROKEN_CONFIG_UNIT_USAGE */
492 for (cf = cfdata; cf->cf_driver; cf++) {
493 if (cf->cf_driver == cd) {
494 if (cf->cf_fstate == FSTATE_FOUND &&
495 cf->cf_unit == dev->dv_unit)
496 cf->cf_fstate = FSTATE_NOTFOUND;
497 #ifdef __BROKEN_CONFIG_UNIT_USAGE
498 if (cf->cf_fstate == FSTATE_STAR &&
499 cf->cf_unit == dev->dv_unit + 1)
500 cf->cf_unit--;
501 #endif /* __BROKEN_CONFIG_UNIT_USAGE */
502 }
503 }
504
505 /*
506 * Unlink from device list.
507 */
508 TAILQ_REMOVE(&alldevs, dev, dv_list);
509
510 /*
511 * Remove from cfdriver's array, tell the world, and free softc.
512 */
513 cd->cd_devs[dev->dv_unit] = NULL;
514 if ((flags & DETACH_QUIET) == 0)
515 printf("%s detached\n", dev->dv_xname);
516 free(dev, M_DEVBUF);
517
518 /*
519 * If the device now has no units in use, deallocate its softc array.
520 */
521 for (i = 0; i < cd->cd_ndevs; i++)
522 if (cd->cd_devs[i] != NULL)
523 break;
524 if (i == cd->cd_ndevs) { /* nothing found; deallocate */
525 free(cd->cd_devs, M_DEVBUF);
526 cd->cd_devs = NULL;
527 cd->cd_ndevs = 0;
528 }
529
530 /*
531 * Return success.
532 */
533 return (0);
534 }
535
536 int
537 config_activate(struct device *dev)
538 {
539 struct cfattach *ca = dev->dv_cfdata->cf_attach;
540 int rv = 0, oflags = dev->dv_flags;
541
542 if (ca->ca_activate == NULL)
543 return (EOPNOTSUPP);
544
545 if ((dev->dv_flags & DVF_ACTIVE) == 0) {
546 dev->dv_flags |= DVF_ACTIVE;
547 rv = (*ca->ca_activate)(dev, DVACT_ACTIVATE);
548 if (rv)
549 dev->dv_flags = oflags;
550 }
551 return (rv);
552 }
553
554 int
555 config_deactivate(struct device *dev)
556 {
557 struct cfattach *ca = dev->dv_cfdata->cf_attach;
558 int rv = 0, oflags = dev->dv_flags;
559
560 if (ca->ca_activate == NULL)
561 return (EOPNOTSUPP);
562
563 if (dev->dv_flags & DVF_ACTIVE) {
564 dev->dv_flags &= ~DVF_ACTIVE;
565 rv = (*ca->ca_activate)(dev, DVACT_DEACTIVATE);
566 if (rv)
567 dev->dv_flags = oflags;
568 }
569 return (rv);
570 }
571
572 /*
573 * Defer the configuration of the specified device until all
574 * of its parent's devices have been attached.
575 */
576 void
577 config_defer(struct device *dev, void (*func)(struct device *))
578 {
579 struct deferred_config *dc;
580
581 if (dev->dv_parent == NULL)
582 panic("config_defer: can't defer config of a root device");
583
584 #ifdef DIAGNOSTIC
585 for (dc = TAILQ_FIRST(&deferred_config_queue); dc != NULL;
586 dc = TAILQ_NEXT(dc, dc_queue)) {
587 if (dc->dc_dev == dev)
588 panic("config_defer: deferred twice");
589 }
590 #endif
591
592 dc = malloc(sizeof(*dc), M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
593 if (dc == NULL)
594 panic("config_defer: unable to allocate callback");
595
596 dc->dc_dev = dev;
597 dc->dc_func = func;
598 TAILQ_INSERT_TAIL(&deferred_config_queue, dc, dc_queue);
599 config_pending_incr();
600 }
601
602 /*
603 * Defer some autoconfiguration for a device until after interrupts
604 * are enabled.
605 */
606 void
607 config_interrupts(struct device *dev, void (*func)(struct device *))
608 {
609 struct deferred_config *dc;
610
611 /*
612 * If interrupts are enabled, callback now.
613 */
614 if (cold == 0) {
615 (*func)(dev);
616 return;
617 }
618
619 #ifdef DIAGNOSTIC
620 for (dc = TAILQ_FIRST(&interrupt_config_queue); dc != NULL;
621 dc = TAILQ_NEXT(dc, dc_queue)) {
622 if (dc->dc_dev == dev)
623 panic("config_interrupts: deferred twice");
624 }
625 #endif
626
627 dc = malloc(sizeof(*dc), M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
628 if (dc == NULL)
629 panic("config_interrupts: unable to allocate callback");
630
631 dc->dc_dev = dev;
632 dc->dc_func = func;
633 TAILQ_INSERT_TAIL(&interrupt_config_queue, dc, dc_queue);
634 config_pending_incr();
635 }
636
637 /*
638 * Process a deferred configuration queue.
639 */
640 static void
641 config_process_deferred(struct deferred_config_head *queue,
642 struct device *parent)
643 {
644 struct deferred_config *dc, *ndc;
645
646 for (dc = TAILQ_FIRST(queue); dc != NULL; dc = ndc) {
647 ndc = TAILQ_NEXT(dc, dc_queue);
648 if (parent == NULL || dc->dc_dev->dv_parent == parent) {
649 TAILQ_REMOVE(queue, dc, dc_queue);
650 (*dc->dc_func)(dc->dc_dev);
651 free(dc, M_DEVBUF);
652 config_pending_decr();
653 }
654 }
655 }
656
657 /*
658 * Manipulate the config_pending semaphore.
659 */
660 void
661 config_pending_incr(void)
662 {
663
664 config_pending++;
665 }
666
667 void
668 config_pending_decr(void)
669 {
670
671 #ifdef DIAGNOSTIC
672 if (config_pending == 0)
673 panic("config_pending_decr: config_pending == 0");
674 #endif
675 config_pending--;
676 if (config_pending == 0)
677 wakeup((void *)&config_pending);
678 }
679
680 /*
681 * Attach an event. These must come from initially-zero space (see
682 * commented-out assignments below), but that occurs naturally for
683 * device instance variables.
684 */
685 void
686 evcnt_attach(struct device *dev, const char *name, struct evcnt *ev)
687 {
688
689 #ifdef DIAGNOSTIC
690 if (strlen(name) >= sizeof(ev->ev_name))
691 panic("evcnt_attach");
692 #endif
693 /* ev->ev_next = NULL; */
694 ev->ev_dev = dev;
695 /* ev->ev_count = 0; */
696 strcpy(ev->ev_name, name);
697 TAILQ_INSERT_TAIL(&allevents, ev, ev_list);
698 }
699
700 /*
701 * Detach an event.
702 */
703 void
704 evcnt_detach(struct evcnt *ev)
705 {
706
707 TAILQ_REMOVE(&allevents, ev, ev_list);
708 }
709