Annotation of sys/arch/hp300/hp300/autoconf.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: autoconf.c,v 1.43 2007/06/01 19:25:09 deraadt Exp $ */
! 2: /* $NetBSD: autoconf.c,v 1.45 1999/04/10 17:31:02 kleink Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1996 Jason R. Thorpe. All rights reserved.
! 6: * Copyright (c) 1988 University of Utah.
! 7: * Copyright (c) 1982, 1986, 1990, 1993
! 8: * The Regents of the University of California. All rights reserved.
! 9: *
! 10: * This code is derived from software contributed to Berkeley by
! 11: * the Systems Programming Group of the University of Utah Computer
! 12: * Science Department.
! 13: *
! 14: * Copyright (c) 1992, 1993
! 15: * The Regents of the University of California. All rights reserved.
! 16: *
! 17: * This software was developed by the Computer Systems Engineering group
! 18: * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
! 19: * contributed to Berkeley.
! 20: *
! 21: * All advertising materials mentioning features or use of this software
! 22: * must display the following acknowledgement:
! 23: * This product includes software developed by the University of
! 24: * California, Lawrence Berkeley Laboratory.
! 25: *
! 26: * Redistribution and use in source and binary forms, with or without
! 27: * modification, are permitted provided that the following conditions
! 28: * are met:
! 29: * 1. Redistributions of source code must retain the above copyright
! 30: * notice, this list of conditions and the following disclaimer.
! 31: * 2. Redistributions in binary form must reproduce the above copyright
! 32: * notice, this list of conditions and the following disclaimer in the
! 33: * documentation and/or other materials provided with the distribution.
! 34: * 3. Neither the name of the University nor the names of its contributors
! 35: * may be used to endorse or promote products derived from this software
! 36: * without specific prior written permission.
! 37: *
! 38: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 39: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 40: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 41: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 42: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 43: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 44: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 45: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 46: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 47: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 48: * SUCH DAMAGE.
! 49: *
! 50: * from: Utah $Hdr: autoconf.c 1.36 92/12/20$
! 51: *
! 52: * @(#)autoconf.c 8.2 (Berkeley) 1/12/94
! 53: */
! 54:
! 55: /*
! 56: * Setup the system to run on the current machine.
! 57: *
! 58: * cpu_configure() is called at boot time. Available
! 59: * devices are determined (from possibilities mentioned in ioconf.c),
! 60: * and the drivers are initialized.
! 61: */
! 62:
! 63: #include <sys/param.h>
! 64: #include <sys/systm.h>
! 65: #include <sys/buf.h>
! 66: #include <sys/conf.h>
! 67: #include <sys/device.h>
! 68: #include <sys/disklabel.h>
! 69: #include <sys/malloc.h>
! 70: #include <sys/extent.h>
! 71: #include <sys/mount.h>
! 72: #include <sys/queue.h>
! 73: #include <sys/reboot.h>
! 74: #include <sys/tty.h>
! 75:
! 76: #include <dev/cons.h>
! 77:
! 78: #include <machine/autoconf.h>
! 79: #include <machine/bus.h>
! 80: #include <machine/vmparam.h>
! 81: #include <machine/cpu.h>
! 82: #include <machine/hp300spu.h>
! 83: #include <machine/intr.h>
! 84: #include <machine/pte.h>
! 85:
! 86: #include <hp300/dev/dioreg.h>
! 87: #include <hp300/dev/diovar.h>
! 88: #include <hp300/dev/diodevs.h>
! 89:
! 90: #include <hp300/dev/dmavar.h>
! 91:
! 92: #include <hp300/dev/hpibvar.h>
! 93: #include <scsi/scsi_all.h>
! 94: #include <scsi/scsiconf.h>
! 95:
! 96: #include <uvm/uvm_extern.h>
! 97:
! 98: /*
! 99: * The following several variables are related to
! 100: * the configuration process, and are used in initializing
! 101: * the machine.
! 102: */
! 103:
! 104: struct extent *extio;
! 105:
! 106: extern caddr_t internalhpib;
! 107: extern char *extiobase;
! 108:
! 109: /* The boot device. */
! 110: struct device *bootdv;
! 111:
! 112: /* The device we mount as root. */
! 113: struct device *root_device;
! 114:
! 115: /* How we were booted. */
! 116: u_int bootdev;
! 117:
! 118: /*
! 119: * This information is built during the autoconfig process.
! 120: * A little explanation about the way this works is in order.
! 121: *
! 122: * device_register() links all devices into dev_data_list.
! 123: * If the device is an hpib controller, it is also linked
! 124: * into dev_data_list_hpib. If the device is a scsi controller,
! 125: * it is also linked into dev_data_list_scsi.
! 126: *
! 127: * dev_data_list_hpib and dev_data_list_scsi are sorted
! 128: * by select code, from lowest to highest.
! 129: *
! 130: * After autoconfiguration is complete, we need to determine
! 131: * which device was the boot device. The boot block assigns
! 132: * controller unit numbers in order of select code. Thus,
! 133: * providing the controller is configured in the kernel, we
! 134: * can determine our version of controller unit number from
! 135: * the sorted hpib/scsi list.
! 136: *
! 137: * At this point, we know the controller (device type
! 138: * encoded in bootdev tells us "scsi disk", or "hpib tape",
! 139: * etc.). The next step is to find the device which
! 140: * has the following properties:
! 141: *
! 142: * - A child of the boot controller.
! 143: * - Same slave as encoded in bootdev.
! 144: * - Same physical unit as encoded in bootdev.
! 145: *
! 146: * Later, after we've set the root device in stone, we
! 147: * reverse the process to re-encode bootdev so it can be
! 148: * passed back to the boot block.
! 149: */
! 150: struct dev_data {
! 151: LIST_ENTRY(dev_data) dd_list; /* dev_data_list */
! 152: LIST_ENTRY(dev_data) dd_clist; /* ctlr list */
! 153: struct device *dd_dev; /* device described by this entry */
! 154: int dd_scode; /* select code of device */
! 155: int dd_slave; /* ...or slave */
! 156: int dd_punit; /* and punit... */
! 157: };
! 158: typedef LIST_HEAD(, dev_data) ddlist_t;
! 159: ddlist_t dev_data_list; /* all dev_datas */
! 160: ddlist_t dev_data_list_hpib; /* hpib controller dev_datas */
! 161: ddlist_t dev_data_list_scsi; /* scsi controller dev_datas */
! 162:
! 163: void findbootdev(void);
! 164: void findbootdev_slave(ddlist_t *, int, int, int);
! 165: void setbootdev(void);
! 166:
! 167: static struct dev_data *dev_data_lookup(struct device *);
! 168: static void dev_data_insert(struct dev_data *, ddlist_t *);
! 169:
! 170: static int device_match(const char *, const char *);
! 171:
! 172: int mainbusmatch(struct device *, void *, void *);
! 173: void mainbusattach(struct device *, struct device *, void *);
! 174: int mainbussearch(struct device *, void *, void *);
! 175:
! 176: struct cfattach mainbus_ca = {
! 177: sizeof(struct device), mainbusmatch, mainbusattach
! 178: };
! 179:
! 180: struct cfdriver mainbus_cd = {
! 181: NULL, "mainbus", DV_DULL
! 182: };
! 183:
! 184: int
! 185: mainbusmatch(parent, match, aux)
! 186: struct device *parent;
! 187: void *match, *aux;
! 188: {
! 189: static int mainbus_matched = 0;
! 190:
! 191: /* Allow only one instance. */
! 192: if (mainbus_matched)
! 193: return (0);
! 194:
! 195: mainbus_matched = 1;
! 196: return (1);
! 197: }
! 198:
! 199: void
! 200: mainbusattach(parent, self, aux)
! 201: struct device *parent, *self;
! 202: void *aux;
! 203: {
! 204:
! 205: printf("\n");
! 206:
! 207: /* Search for and attach children. */
! 208: config_search(mainbussearch, self, NULL);
! 209: }
! 210:
! 211: int
! 212: mainbussearch(parent, match, aux)
! 213: struct device *parent;
! 214: void *match, *aux;
! 215: {
! 216: struct cfdata *cf = match;
! 217:
! 218: if ((*cf->cf_attach->ca_match)(parent, cf, NULL) > 0)
! 219: config_attach(parent, cf, NULL, NULL);
! 220: return (0);
! 221: }
! 222:
! 223: /*
! 224: * Determine the device configuration for the running system.
! 225: */
! 226: void
! 227: cpu_configure()
! 228: {
! 229: /*
! 230: * Initialize the dev_data_lists.
! 231: */
! 232: LIST_INIT(&dev_data_list);
! 233: LIST_INIT(&dev_data_list_hpib);
! 234: LIST_INIT(&dev_data_list_scsi);
! 235:
! 236: (void)splhigh();
! 237: if (config_rootfound("mainbus", "mainbus") == NULL)
! 238: panic("no mainbus found");
! 239: (void)spl0();
! 240:
! 241: intr_printlevels();
! 242:
! 243: /*
! 244: * Find boot device.
! 245: */
! 246: if ((bootdev & B_MAGICMASK) != B_DEVMAGIC) {
! 247: printf("WARNING: boot program didn't supply boot device.\n");
! 248: printf("Please update your boot program.\n");
! 249: } else {
! 250: findbootdev();
! 251: if (bootdv == NULL) {
! 252: printf("WARNING: can't find match for bootdev:\n");
! 253: printf(
! 254: "type = %d, ctlr = %d, slave = %d, punit = %d, part = %d\n",
! 255: B_TYPE(bootdev), B_ADAPTOR(bootdev),
! 256: B_CONTROLLER(bootdev), B_UNIT(bootdev),
! 257: B_PARTITION(bootdev));
! 258: bootdev = 0; /* invalidate bootdev */
! 259: } else {
! 260: printf("boot device: %s\n", bootdv->dv_xname);
! 261: }
! 262: }
! 263: cold = 0;
! 264: }
! 265:
! 266: void
! 267: diskconf(void)
! 268: {
! 269: int bootpartition = 0;
! 270:
! 271: /*
! 272: * If bootdev is bogus, ask the user anyhow.
! 273: */
! 274: if (bootdev == 0)
! 275: boothowto |= RB_ASKNAME;
! 276: else
! 277: bootpartition = B_PARTITION(bootdev);
! 278:
! 279: /*
! 280: * If we booted from tape, ask the user.
! 281: */
! 282: if (bootdv != NULL && bootdv->dv_class == DV_TAPE)
! 283: boothowto |= RB_ASKNAME;
! 284:
! 285: setroot(bootdv, bootpartition, RB_USERREQ);
! 286: dumpconf();
! 287:
! 288: /*
! 289: * Set bootdev based on the device we booted from.
! 290: * This is given to the boot program when we reboot.
! 291: */
! 292: setbootdev();
! 293: }
! 294:
! 295: /**********************************************************************
! 296: * Code to find and set the boot device
! 297: **********************************************************************/
! 298:
! 299: static int
! 300: device_match(const char *dvname, const char *template)
! 301: {
! 302: size_t len = strlen(template);
! 303: char unit;
! 304:
! 305: if (strncmp(dvname, template, len) != 0)
! 306: return (1);
! 307:
! 308: /* Check that we are immediately followed by an unit number. */
! 309: unit = dvname[len];
! 310: if (unit < '0' || unit > '9')
! 311: return (1);
! 312:
! 313: return (0);
! 314: }
! 315:
! 316: /*
! 317: * Register a device. We're passed the device and the arguments
! 318: * used to attach it. This is used to find the boot device.
! 319: */
! 320: void
! 321: device_register(dev, aux)
! 322: struct device *dev;
! 323: void *aux;
! 324: {
! 325: struct dev_data *dd;
! 326: static int seen_netdevice = 0;
! 327:
! 328: /*
! 329: * Allocate a dev_data structure and fill it in.
! 330: * This means making some tests twice, but we don't
! 331: * care; this doesn't really have to be fast.
! 332: *
! 333: * Note that we only really care about devices that
! 334: * we can mount as root.
! 335: */
! 336: dd = (struct dev_data *)malloc(sizeof(struct dev_data),
! 337: M_DEVBUF, M_NOWAIT);
! 338: if (dd == NULL)
! 339: panic("device_register: can't allocate dev_data");
! 340: bzero(dd, sizeof(struct dev_data));
! 341:
! 342: dd->dd_dev = dev;
! 343:
! 344: /*
! 345: * BOOTROM and boot program can really only understand
! 346: * using the lowest select code network interface,
! 347: * so we ignore all but the first.
! 348: */
! 349: if (dev->dv_class == DV_IFNET && seen_netdevice == 0) {
! 350: struct dio_attach_args *da = aux;
! 351:
! 352: seen_netdevice = 1;
! 353: dd->dd_scode = da->da_scode;
! 354: goto linkup;
! 355: }
! 356:
! 357: if (device_match(dev->dv_xname, "fhpib") == 0 ||
! 358: device_match(dev->dv_xname, "nhpib") == 0 ||
! 359: device_match(dev->dv_xname, "spc") == 0) {
! 360: struct dio_attach_args *da = aux;
! 361:
! 362: dd->dd_scode = da->da_scode;
! 363: goto linkup;
! 364: }
! 365:
! 366: if (device_match(dev->dv_xname, "hd") == 0) {
! 367: struct hpibbus_attach_args *ha = aux;
! 368:
! 369: dd->dd_slave = ha->ha_slave;
! 370: dd->dd_punit = ha->ha_punit;
! 371: goto linkup;
! 372: }
! 373:
! 374: if (device_match(dev->dv_xname, "cd") == 0 ||
! 375: device_match(dev->dv_xname, "sd") == 0 ||
! 376: device_match(dev->dv_xname, "st") == 0) {
! 377: struct scsi_attach_args *sa = aux;
! 378:
! 379: dd->dd_slave = sa->sa_sc_link->target;
! 380: dd->dd_punit = sa->sa_sc_link->lun;
! 381: goto linkup;
! 382: }
! 383:
! 384: /*
! 385: * Didn't need the dev_data.
! 386: */
! 387: free(dd, M_DEVBUF);
! 388: return;
! 389:
! 390: linkup:
! 391: LIST_INSERT_HEAD(&dev_data_list, dd, dd_list);
! 392:
! 393: if (device_match(dev->dv_xname, "fhpib") == 0 ||
! 394: device_match(dev->dv_xname, "nhpib") == 0) {
! 395: dev_data_insert(dd, &dev_data_list_hpib);
! 396: return;
! 397: }
! 398:
! 399: if (device_match(dev->dv_xname, "spc") == 0) {
! 400: dev_data_insert(dd, &dev_data_list_scsi);
! 401: return;
! 402: }
! 403: }
! 404:
! 405: void
! 406: findbootdev()
! 407: {
! 408: int type, ctlr, slave, punit;
! 409: int scsiboot, hpibboot, netboot;
! 410: struct dev_data *dd;
! 411:
! 412: bootdv = NULL;
! 413:
! 414: if ((bootdev & B_MAGICMASK) != B_DEVMAGIC)
! 415: return;
! 416:
! 417: type = B_TYPE(bootdev);
! 418: ctlr = B_ADAPTOR(bootdev);
! 419: slave = B_CONTROLLER(bootdev);
! 420: punit = B_UNIT(bootdev);
! 421:
! 422: scsiboot = (type == 4); /* sd major */
! 423: hpibboot = (type == 0 || type == 2); /* ct/hd major */
! 424: netboot = (type == 6); /* le - special */
! 425:
! 426: /*
! 427: * Check for network boot first, since it's a little
! 428: * different. The BOOTROM/boot program can only boot
! 429: * off of the first (lowest select code) ethernet
! 430: * device. device_register() knows this and only
! 431: * registers one DV_IFNET. This is a safe assumption
! 432: * since the code that finds devices on the DIO bus
! 433: * always starts at scode 0 and works its way up.
! 434: */
! 435: if (netboot) {
! 436: LIST_FOREACH(dd, &dev_data_list, dd_list) {
! 437: if (dd->dd_dev->dv_class == DV_IFNET) {
! 438: /*
! 439: * Found it!
! 440: */
! 441: bootdv = dd->dd_dev;
! 442: break;
! 443: }
! 444: }
! 445: return;
! 446: }
! 447:
! 448: /*
! 449: * Check for HP-IB boots next.
! 450: */
! 451: if (hpibboot) {
! 452: findbootdev_slave(&dev_data_list_hpib, ctlr,
! 453: slave, punit);
! 454: if (bootdv == NULL)
! 455: return;
! 456:
! 457: #ifdef DIAGNOSTIC
! 458: /*
! 459: * Sanity check.
! 460: */
! 461: if ((type == 0 &&
! 462: device_match(bootdv->dv_xname, "ct")) ||
! 463: (type == 2 &&
! 464: device_match(bootdv->dv_xname, "hd"))) {
! 465: printf("WARNING: boot device/type mismatch!\n");
! 466: printf("device = %s, type = %d\n",
! 467: bootdv->dv_xname, type);
! 468: bootdv = NULL;
! 469: }
! 470: #endif
! 471: return;
! 472: }
! 473:
! 474: /*
! 475: * Check for SCSI boots last.
! 476: */
! 477: if (scsiboot) {
! 478: findbootdev_slave(&dev_data_list_scsi, ctlr,
! 479: slave, punit);
! 480: if (bootdv == NULL)
! 481: return;
! 482:
! 483: #ifdef DIAGNOSTIC
! 484: /*
! 485: * Sanity check.
! 486: */
! 487: if (device_match(bootdv->dv_xname, "cd") != 0 &&
! 488: device_match(bootdv->dv_xname, "sd") != 0 &&
! 489: device_match(bootdv->dv_xname, "st") != 0) {
! 490: printf("WARNING: boot device/type mismatch!\n");
! 491: printf("device = %s, type = %d\n",
! 492: bootdv->dv_xname, type);
! 493: bootdv = NULL;
! 494: }
! 495: #endif
! 496: return;
! 497: }
! 498:
! 499: /* Oof! */
! 500: printf("WARNING: UNKNOWN BOOT DEVICE TYPE = %d\n", type);
! 501: }
! 502:
! 503: void
! 504: findbootdev_slave(ddlist, ctlr, slave, punit)
! 505: ddlist_t *ddlist;
! 506: int ctlr, slave, punit;
! 507: {
! 508: struct dev_data *cdd, *dd;
! 509:
! 510: /*
! 511: * Find the booted controller.
! 512: */
! 513: for (cdd = LIST_FIRST(ddlist); ctlr != 0 && cdd != LIST_END(ddlist);
! 514: cdd = LIST_NEXT(cdd, dd_clist))
! 515: ctlr--;
! 516: if (cdd == NULL) {
! 517: /*
! 518: * Oof, couldn't find it...
! 519: */
! 520: return;
! 521: }
! 522:
! 523: /*
! 524: * Now find the device with the right slave/punit
! 525: * that's a child of the controller.
! 526: */
! 527: LIST_FOREACH(dd, &dev_data_list, dd_list) {
! 528: /*
! 529: * "sd" / "st" / "cd" -> "scsibus" -> "spc"
! 530: * "hd" -> "hpibbus" -> "fhpib"
! 531: */
! 532: if (dd->dd_dev->dv_parent->dv_parent != cdd->dd_dev)
! 533: continue;
! 534:
! 535: if (dd->dd_slave == slave &&
! 536: dd->dd_punit == punit) {
! 537: /*
! 538: * Found it!
! 539: */
! 540: bootdv = dd->dd_dev;
! 541: break;
! 542: }
! 543: }
! 544: }
! 545:
! 546: void
! 547: setbootdev()
! 548: {
! 549: struct dev_data *cdd, *dd;
! 550: int type, ctlr;
! 551:
! 552: /*
! 553: * Note our magic numbers for type:
! 554: *
! 555: * 0 == ct
! 556: * 2 == hd
! 557: * 4 == scsi
! 558: * 6 == le
! 559: *
! 560: * All are bdevsw major numbers, except for le, which
! 561: * is just special. SCSI needs specific care since the
! 562: * ROM wants to see 4, but depending upon the real device
! 563: * we booted from, we might have a different major value.
! 564: */
! 565:
! 566: /*
! 567: * Start with a clean slate.
! 568: */
! 569: bootdev = 0;
! 570:
! 571: /*
! 572: * If we don't have a saveable root_device, just punt.
! 573: */
! 574: if (root_device == NULL)
! 575: goto out;
! 576:
! 577: dd = dev_data_lookup(root_device);
! 578:
! 579: /*
! 580: * If the root device is network, we're done
! 581: * early.
! 582: */
! 583: if (root_device->dv_class == DV_IFNET) {
! 584: bootdev = MAKEBOOTDEV(6, 0, 0, 0, 0);
! 585: goto out;
! 586: }
! 587:
! 588: /*
! 589: * Determine device type.
! 590: */
! 591: if (device_match(root_device->dv_xname, "hd") == 0)
! 592: type = 2;
! 593: else if (device_match(root_device->dv_xname, "cd") == 0 ||
! 594: device_match(root_device->dv_xname, "sd") == 0 ||
! 595: device_match(root_device->dv_xname, "st") == 0)
! 596: /* force scsi disk regardless of the actual device */
! 597: type = 4;
! 598: else {
! 599: printf("WARNING: strange root device!\n");
! 600: goto out;
! 601: }
! 602:
! 603: /*
! 604: * Get parent's info.
! 605: *
! 606: * "hd" -> "hpibbus" -> "fhpib"
! 607: * "sd" / "cd" / "st" -> "scsibus" -> "spc"
! 608: */
! 609: for (cdd = LIST_FIRST(&dev_data_list_hpib), ctlr = 0;
! 610: cdd != LIST_END(&dev_data_list_hpib);
! 611: cdd = LIST_NEXT(cdd, dd_clist), ctlr++) {
! 612: if (cdd->dd_dev == root_device->dv_parent->dv_parent) {
! 613: /*
! 614: * Found it!
! 615: */
! 616: bootdev = MAKEBOOTDEV(type, ctlr, dd->dd_slave,
! 617: dd->dd_punit, DISKPART(rootdev));
! 618: break;
! 619: }
! 620: }
! 621:
! 622: out:
! 623: /* Don't need this anymore. */
! 624: for (dd = LIST_FIRST(&dev_data_list);
! 625: dd != LIST_END(&dev_data_list); ) {
! 626: cdd = dd;
! 627: dd = LIST_NEXT(dd, dd_list);
! 628: free(cdd, M_DEVBUF);
! 629: }
! 630: }
! 631:
! 632: /*
! 633: * Return the dev_data corresponding to the given device.
! 634: */
! 635: static struct dev_data *
! 636: dev_data_lookup(dev)
! 637: struct device *dev;
! 638: {
! 639: struct dev_data *dd;
! 640:
! 641: LIST_FOREACH(dd, &dev_data_list, dd_list)
! 642: if (dd->dd_dev == dev)
! 643: return (dd);
! 644:
! 645: panic("dev_data_lookup");
! 646: }
! 647:
! 648: /*
! 649: * Insert a dev_data into the provided list, sorted by select code.
! 650: */
! 651: static void
! 652: dev_data_insert(dd, ddlist)
! 653: struct dev_data *dd;
! 654: ddlist_t *ddlist;
! 655: {
! 656: struct dev_data *de;
! 657:
! 658: #ifdef DIAGNOSTIC
! 659: if (dd->dd_scode < 0 || dd->dd_scode > 255) {
! 660: panic("bogus select code for %s", dd->dd_dev->dv_xname);
! 661: }
! 662: #endif
! 663:
! 664: /*
! 665: * Just insert at head if list is empty.
! 666: */
! 667: if (LIST_EMPTY(ddlist)) {
! 668: LIST_INSERT_HEAD(ddlist, dd, dd_clist);
! 669: return;
! 670: }
! 671:
! 672: /*
! 673: * Traverse the list looking for a device who's select code
! 674: * is greater than ours. When we find it, insert ourselves
! 675: * into the list before it.
! 676: */
! 677: for (de = LIST_FIRST(ddlist);
! 678: LIST_NEXT(de, dd_clist) != LIST_END(ddlist);
! 679: de = LIST_NEXT(de, dd_clist)) {
! 680: if (de->dd_scode > dd->dd_scode) {
! 681: LIST_INSERT_BEFORE(de, dd, dd_clist);
! 682: return;
! 683: }
! 684: }
! 685:
! 686: /*
! 687: * Our select code is greater than everyone else's. We go
! 688: * onto the end.
! 689: */
! 690: LIST_INSERT_AFTER(de, dd, dd_clist);
! 691: }
! 692:
! 693: /**********************************************************************
! 694: * Code to find and initialize the console
! 695: **********************************************************************/
! 696:
! 697: /*
! 698: * Scan all select codes, passing the corresponding VA to (*func)().
! 699: * (*func)() is a driver-specific routine that looks for the console
! 700: * hardware.
! 701: */
! 702: void
! 703: console_scan(func, arg)
! 704: int (*func)(int, caddr_t, void *);
! 705: void *arg;
! 706: {
! 707: int size, scode, sctop;
! 708: caddr_t pa, va;
! 709:
! 710: /*
! 711: * Scan all select codes. Check each location for some
! 712: * hardware. If there's something there, call (*func)().
! 713: */
! 714: sctop = DIO_SCMAX(machineid);
! 715: for (scode = 0; scode < sctop; ++scode) {
! 716: /*
! 717: * Skip over the select code hole and
! 718: * the internal HP-IB controller.
! 719: */
! 720: if (DIO_INHOLE(scode) ||
! 721: ((scode == 7) && internalhpib))
! 722: continue;
! 723:
! 724: /* Map current PA. */
! 725: pa = dio_scodetopa(scode);
! 726: va = iomap(pa, PAGE_SIZE);
! 727: if (va == NULL)
! 728: continue;
! 729:
! 730: /* Check to see if hardware exists. */
! 731: if (badaddr(va)) {
! 732: iounmap(va, PAGE_SIZE);
! 733: continue;
! 734: }
! 735:
! 736: /*
! 737: * Hardware present, call callback. Driver returns
! 738: * size of region to map if console probe successful
! 739: * and worthwhile.
! 740: */
! 741: size = (*func)(scode, va, arg);
! 742: iounmap(va, PAGE_SIZE);
! 743: if (size != 0 && conscode == scode) {
! 744: /* Free last mapping. */
! 745: if (convasize)
! 746: iounmap(conaddr, convasize);
! 747: convasize = 0;
! 748:
! 749: /* Remap to correct size. */
! 750: va = iomap(pa, size);
! 751: if (va == NULL)
! 752: continue;
! 753:
! 754: /* Save this state for next time. */
! 755: conaddr = va;
! 756: convasize = size;
! 757: }
! 758: }
! 759: }
! 760:
! 761: int consolepass = -1;
! 762:
! 763: /*
! 764: * Special version of cninit(). Actually, crippled somewhat.
! 765: * This version lets the drivers assign cn_tab.
! 766: */
! 767: void
! 768: hp300_cninit(void)
! 769: {
! 770: struct consdev *cp;
! 771: extern struct consdev constab[];
! 772:
! 773: if (++consolepass == 0) {
! 774: cn_tab = NULL;
! 775:
! 776: /*
! 777: * Call all of the console probe functions.
! 778: */
! 779: for (cp = constab; cp->cn_probe; cp++)
! 780: (*cp->cn_probe)(cp);
! 781: }
! 782:
! 783: /*
! 784: * No console, we can handle it.
! 785: */
! 786: if (cn_tab == NULL)
! 787: return;
! 788:
! 789: /*
! 790: * Turn on the console.
! 791: *
! 792: * Note that we need to check for cn_init because DIO frame buffers
! 793: * will cause cn_tab to switch to wsdisplaycons, which does not
! 794: * have an cn_init function.
! 795: */
! 796: if (cn_tab->cn_init != NULL) {
! 797: (*cn_tab->cn_init)(cn_tab);
! 798: }
! 799: }
! 800:
! 801: /**********************************************************************
! 802: * Mapping functions
! 803: **********************************************************************/
! 804:
! 805: /*
! 806: * Allocate/deallocate a cache-inhibited range of kernel virtual address
! 807: * space mapping the indicated physical address range [pa - pa+size)
! 808: */
! 809: caddr_t
! 810: iomap(pa, size)
! 811: caddr_t pa;
! 812: int size;
! 813: {
! 814: vaddr_t iova, tva, off;
! 815: paddr_t ppa;
! 816: int error;
! 817:
! 818: if (size <= 0)
! 819: return NULL;
! 820:
! 821: ppa = trunc_page((paddr_t)pa);
! 822: off = (paddr_t)pa & PAGE_MASK;
! 823: size = round_page(off + size);
! 824:
! 825: error = extent_alloc(extio, size, PAGE_SIZE, 0, EX_NOBOUNDARY,
! 826: EX_NOWAIT | EX_MALLOCOK, &iova);
! 827:
! 828: if (error != 0)
! 829: return (NULL);
! 830:
! 831: tva = iova;
! 832: while (size != 0) {
! 833: pmap_kenter_cache(tva, ppa, PG_RW | PG_CI);
! 834: size -= PAGE_SIZE;
! 835: tva += PAGE_SIZE;
! 836: ppa += PAGE_SIZE;
! 837: }
! 838: pmap_update(pmap_kernel());
! 839: return ((void *)(iova + off));
! 840: }
! 841:
! 842: /*
! 843: * Unmap a previously mapped device.
! 844: */
! 845: void
! 846: iounmap(va, size)
! 847: caddr_t va;
! 848: int size;
! 849: {
! 850: vaddr_t kva, off;
! 851: int error;
! 852:
! 853: off = (vaddr_t)va & PAGE_MASK;
! 854: kva = trunc_page((vaddr_t)va);
! 855: size = round_page(off + size);
! 856:
! 857: pmap_kremove(kva, size);
! 858: pmap_update(pmap_kernel());
! 859:
! 860: error = extent_free(extio, kva, size, EX_NOWAIT);
! 861: #ifdef DIAGNOSTIC
! 862: if (error != 0)
! 863: printf("iounmap: extent_free failed\n");
! 864: #endif
! 865: }
! 866:
! 867: struct nam2blk nam2blk[] = {
! 868: { "ct", 0 },
! 869: { "hd", 2 },
! 870: { "sd", 4 },
! 871: { "st", 7 },
! 872: { "rd", 8 },
! 873: { "cd", 9 },
! 874: { NULL, -1 }
! 875: };
CVSweb