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