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