1 /* $NetBSD: subr_autoconf.c,v 1.45 1999/12/30 01:03:43 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/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 if (cf->cf_fstate == FSTATE_STAR) { 312 for (myunit = cf->cf_unit; myunit < cd->cd_ndevs; myunit++) 313 if (cd->cd_devs[myunit] == NULL) 314 break; 315 /* 316 * myunit is now the unit of the first NULL device pointer, 317 * or max(cd->cd_ndevs,cf->cf_unit). 318 */ 319 } else { 320 myunit = cf->cf_unit; 321 KASSERT(cf->cf_fstate == FSTATE_NOTFOUND); 322 cf->cf_fstate = FSTATE_FOUND; 323 } 324 325 /* compute length of name and decimal expansion of unit number */ 326 lname = strlen(cd->cd_name); 327 xunit = number(&num[sizeof(num)], myunit); 328 lunit = &num[sizeof(num)] - xunit; 329 if (lname + lunit >= sizeof(dev->dv_xname)) 330 panic("config_attach: device name too long"); 331 332 /* get memory for all device vars */ 333 dev = (struct device *)malloc(ca->ca_devsize, M_DEVBUF, 334 cold ? M_NOWAIT : M_WAITOK); 335 if (!dev) 336 panic("config_attach: memory allocation for device softc failed"); 337 memset(dev, 0, ca->ca_devsize); 338 TAILQ_INSERT_TAIL(&alldevs, dev, dv_list); /* link up */ 339 dev->dv_class = cd->cd_class; 340 dev->dv_cfdata = cf; 341 dev->dv_unit = myunit; 342 memcpy(dev->dv_xname, cd->cd_name, lname); 343 memcpy(dev->dv_xname + lname, xunit, lunit); 344 dev->dv_parent = parent; 345 dev->dv_flags = DVF_ACTIVE; /* always initially active */ 346 347 if (parent == ROOT) 348 printf("%s (root)", dev->dv_xname); 349 else { 350 printf("%s at %s", dev->dv_xname, parent->dv_xname); 351 if (print) 352 (void) (*print)(aux, (char *)0); 353 } 354 355 /* put this device in the devices array */ 356 if (dev->dv_unit >= cd->cd_ndevs) { 357 /* 358 * Need to expand the array. 359 */ 360 int old = cd->cd_ndevs, new; 361 void **nsp; 362 363 if (old == 0) 364 new = MINALLOCSIZE / sizeof(void *); 365 else 366 new = old * 2; 367 while (new <= dev->dv_unit) 368 new *= 2; 369 cd->cd_ndevs = new; 370 nsp = malloc(new * sizeof(void *), M_DEVBUF, 371 cold ? M_NOWAIT : M_WAITOK); 372 if (nsp == 0) 373 panic("config_attach: %sing dev array", 374 old != 0 ? "expand" : "creat"); 375 memset(nsp + old, 0, (new - old) * sizeof(void *)); 376 if (old != 0) { 377 memcpy(nsp, cd->cd_devs, old * sizeof(void *)); 378 free(cd->cd_devs, M_DEVBUF); 379 } 380 cd->cd_devs = nsp; 381 } 382 if (cd->cd_devs[dev->dv_unit]) 383 panic("config_attach: duplicate %s", dev->dv_xname); 384 cd->cd_devs[dev->dv_unit] = dev; 385 386 /* 387 * Before attaching, clobber any unfound devices that are 388 * otherwise identical. 389 */ 390 for (cf = cfdata; cf->cf_driver; cf++) 391 if (cf->cf_driver == cd && cf->cf_unit == dev->dv_unit) { 392 if (cf->cf_fstate == FSTATE_NOTFOUND) 393 cf->cf_fstate = FSTATE_FOUND; 394 } 395 #if defined(__alpha__) || defined(hp300) || defined(__i386__) || \ 396 defined(__sparc__) || defined(__vax__) || defined(x68k) 397 device_register(dev, aux); 398 #endif 399 (*ca->ca_attach)(parent, dev, aux); 400 config_process_deferred(&deferred_config_queue, dev); 401 return (dev); 402 } 403 404 /* 405 * Detach a device. Optionally forced (e.g. because of hardware 406 * removal) and quiet. Returns zero if successful, non-zero 407 * (an error code) otherwise. 408 * 409 * Note that this code wants to be run from a process context, so 410 * that the detach can sleep to allow processes which have a device 411 * open to run and unwind their stacks. 412 */ 413 int 414 config_detach(dev, flags) 415 struct device *dev; 416 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 panic("config_detach: detached device has children"); 477 } 478 #endif 479 480 /* 481 * Mark cfdata to show that the unit can be reused, if possible. 482 */ 483 for (cf = cfdata; cf->cf_driver; cf++) { 484 if (cf->cf_driver == cd) { 485 if (cf->cf_fstate == FSTATE_FOUND && 486 cf->cf_unit == dev->dv_unit) 487 cf->cf_fstate = FSTATE_NOTFOUND; 488 } 489 } 490 491 /* 492 * Unlink from device list. 493 */ 494 TAILQ_REMOVE(&alldevs, dev, dv_list); 495 496 /* 497 * Remove from cfdriver's array, tell the world, and free softc. 498 */ 499 cd->cd_devs[dev->dv_unit] = NULL; 500 if ((flags & DETACH_QUIET) == 0) 501 printf("%s detached\n", dev->dv_xname); 502 free(dev, M_DEVBUF); 503 504 /* 505 * If the device now has no units in use, deallocate its softc array. 506 */ 507 for (i = 0; i < cd->cd_ndevs; i++) 508 if (cd->cd_devs[i] != NULL) 509 break; 510 if (i == cd->cd_ndevs) { /* nothing found; deallocate */ 511 free(cd->cd_devs, M_DEVBUF); 512 cd->cd_devs = NULL; 513 cd->cd_ndevs = 0; 514 } 515 516 /* 517 * Return success. 518 */ 519 return (0); 520 } 521 522 int 523 config_activate(dev) 524 struct device *dev; 525 { 526 struct cfattach *ca = dev->dv_cfdata->cf_attach; 527 int rv = 0, oflags = dev->dv_flags; 528 529 if (ca->ca_activate == NULL) 530 return (EOPNOTSUPP); 531 532 if ((dev->dv_flags & DVF_ACTIVE) == 0) { 533 dev->dv_flags |= DVF_ACTIVE; 534 rv = (*ca->ca_activate)(dev, DVACT_ACTIVATE); 535 if (rv) 536 dev->dv_flags = oflags; 537 } 538 return (rv); 539 } 540 541 int 542 config_deactivate(dev) 543 struct device *dev; 544 { 545 struct cfattach *ca = dev->dv_cfdata->cf_attach; 546 int rv = 0, oflags = dev->dv_flags; 547 548 if (ca->ca_activate == NULL) 549 return (EOPNOTSUPP); 550 551 if (dev->dv_flags & DVF_ACTIVE) { 552 dev->dv_flags &= ~DVF_ACTIVE; 553 rv = (*ca->ca_activate)(dev, DVACT_DEACTIVATE); 554 if (rv) 555 dev->dv_flags = oflags; 556 } 557 return (rv); 558 } 559 560 /* 561 * Defer the configuration of the specified device until all 562 * of its parent's devices have been attached. 563 */ 564 void 565 config_defer(dev, func) 566 struct device *dev; 567 void (*func) __P((struct device *)); 568 { 569 struct deferred_config *dc; 570 571 if (dev->dv_parent == NULL) 572 panic("config_defer: can't defer config of a root device"); 573 574 #ifdef DIAGNOSTIC 575 for (dc = TAILQ_FIRST(&deferred_config_queue); dc != NULL; 576 dc = TAILQ_NEXT(dc, dc_queue)) { 577 if (dc->dc_dev == dev) 578 panic("config_defer: deferred twice"); 579 } 580 #endif 581 582 dc = malloc(sizeof(*dc), M_DEVBUF, cold ? M_NOWAIT : M_WAITOK); 583 if (dc == NULL) 584 panic("config_defer: unable to allocate callback"); 585 586 dc->dc_dev = dev; 587 dc->dc_func = func; 588 TAILQ_INSERT_TAIL(&deferred_config_queue, dc, dc_queue); 589 } 590 591 /* 592 * Defer some autoconfiguration for a device until after interrupts 593 * are enabled. 594 */ 595 void 596 config_interrupts(dev, func) 597 struct device *dev; 598 void (*func) __P((struct device *)); 599 { 600 struct deferred_config *dc; 601 602 /* 603 * If interrupts are enabled, callback now. 604 */ 605 if (cold == 0) { 606 (*func)(dev); 607 return; 608 } 609 610 #ifdef DIAGNOSTIC 611 for (dc = TAILQ_FIRST(&interrupt_config_queue); dc != NULL; 612 dc = TAILQ_NEXT(dc, dc_queue)) { 613 if (dc->dc_dev == dev) 614 panic("config_interrupts: deferred twice"); 615 } 616 #endif 617 618 dc = malloc(sizeof(*dc), M_DEVBUF, cold ? M_NOWAIT : M_WAITOK); 619 if (dc == NULL) 620 panic("config_interrupts: unable to allocate callback"); 621 622 dc->dc_dev = dev; 623 dc->dc_func = func; 624 TAILQ_INSERT_TAIL(&interrupt_config_queue, dc, dc_queue); 625 } 626 627 /* 628 * Process a deferred configuration queue. 629 */ 630 static void 631 config_process_deferred(queue, parent) 632 struct deferred_config_head *queue; 633 struct device *parent; 634 { 635 struct deferred_config *dc, *ndc; 636 637 for (dc = TAILQ_FIRST(queue); dc != NULL; dc = ndc) { 638 ndc = TAILQ_NEXT(dc, dc_queue); 639 if (parent == NULL || dc->dc_dev->dv_parent == parent) { 640 TAILQ_REMOVE(queue, dc, dc_queue); 641 (*dc->dc_func)(dc->dc_dev); 642 free(dc, M_DEVBUF); 643 } 644 } 645 } 646 647 /* 648 * Attach an event. These must come from initially-zero space (see 649 * commented-out assignments below), but that occurs naturally for 650 * device instance variables. 651 */ 652 void 653 evcnt_attach(dev, name, ev) 654 struct device *dev; 655 const char *name; 656 struct evcnt *ev; 657 { 658 659 #ifdef DIAGNOSTIC 660 if (strlen(name) >= sizeof(ev->ev_name)) 661 panic("evcnt_attach"); 662 #endif 663 /* ev->ev_next = NULL; */ 664 ev->ev_dev = dev; 665 /* ev->ev_count = 0; */ 666 strcpy(ev->ev_name, name); 667 TAILQ_INSERT_TAIL(&allevents, ev, ev_list); 668 } 669 670 /* 671 * Detach an event. 672 */ 673 void 674 evcnt_detach(ev) 675 struct evcnt *ev; 676 { 677 678 TAILQ_REMOVE(&allevents, ev, ev_list); 679 } 680