Home | History | Annotate | Line # | Download | only in hp300
      1 /*	$NetBSD: autoconf.c,v 1.117 2025/05/27 18:56:27 tsutsui Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1996, 1997, 2002 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Jason R. Thorpe.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 /*
     33  * Copyright (c) 1988 University of Utah.
     34  * Copyright (c) 1982, 1986, 1990, 1993
     35  *	The Regents of the University of California.  All rights reserved.
     36  *
     37  * This code is derived from software contributed to Berkeley by
     38  * the Systems Programming Group of the University of Utah Computer
     39  * Science Department.
     40  *
     41  * Copyright (c) 1992, 1993
     42  *	The Regents of the University of California.  All rights reserved.
     43  *
     44  * This software was developed by the Computer Systems Engineering group
     45  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
     46  * contributed to Berkeley.
     47  *
     48  * All advertising materials mentioning features or use of this software
     49  * must display the following acknowledgement:
     50  *	This product includes software developed by the University of
     51  *	California, Lawrence Berkeley Laboratory.
     52  *
     53  * Redistribution and use in source and binary forms, with or without
     54  * modification, are permitted provided that the following conditions
     55  * are met:
     56  * 1. Redistributions of source code must retain the above copyright
     57  *    notice, this list of conditions and the following disclaimer.
     58  * 2. Redistributions in binary form must reproduce the above copyright
     59  *    notice, this list of conditions and the following disclaimer in the
     60  *    documentation and/or other materials provided with the distribution.
     61  * 3. Neither the name of the University nor the names of its contributors
     62  *    may be used to endorse or promote products derived from this software
     63  *    without specific prior written permission.
     64  *
     65  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     66  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     67  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     68  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     69  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     70  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     71  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     72  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     73  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     74  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     75  * SUCH DAMAGE.
     76  *
     77  * from: Utah $Hdr: autoconf.c 1.36 92/12/20$
     78  *
     79  *	@(#)autoconf.c	8.2 (Berkeley) 1/12/94
     80  */
     81 
     82 /*
     83  * Setup the system to run on the current machine.
     84  *
     85  * Configure() is called at boot time.  Available
     86  * devices are determined (from possibilities mentioned in ioconf.c),
     87  * and the drivers are initialized.
     88  */
     89 
     90 #include <sys/cdefs.h>
     91 __KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.117 2025/05/27 18:56:27 tsutsui Exp $");
     92 
     93 #include "dvbox.h"
     94 #include "gbox.h"
     95 #include "hyper.h"
     96 #include "rbox.h"
     97 #include "topcat.h"
     98 #include "tvrx.h"
     99 #include "gendiofb.h"
    100 #include "sti_dio.h"
    101 #include "sti_sgc.h"
    102 #include "com_dio.h"
    103 #include "com_frodo.h"
    104 #include "dcm.h"
    105 
    106 #define	_M68K_INTR_PRIVATE
    107 
    108 #include <sys/param.h>
    109 #include <sys/systm.h>
    110 #include <sys/buf.h>
    111 #include <sys/conf.h>
    112 #include <sys/device.h>
    113 #include <sys/disklabel.h>
    114 #include <sys/kmem.h>
    115 #include <sys/extent.h>
    116 #include <sys/mount.h>
    117 #include <sys/queue.h>
    118 #include <sys/reboot.h>
    119 #include <sys/tty.h>
    120 
    121 #include <uvm/uvm_extern.h>
    122 
    123 #include <dev/cons.h>
    124 
    125 #include <dev/wscons/wsconsio.h>
    126 #include <dev/wscons/wsdisplayvar.h>
    127 #include <dev/rasops/rasops.h>
    128 
    129 #include <dev/scsipi/scsi_all.h>
    130 #include <dev/scsipi/scsipi_all.h>
    131 #include <dev/scsipi/scsiconf.h>
    132 
    133 #include <machine/autoconf.h>
    134 #include <machine/vmparam.h>
    135 #include <machine/cpu.h>
    136 #include <machine/hp300spu.h>
    137 #include <machine/intr.h>
    138 #include <machine/pte.h>
    139 
    140 #include <hp300/dev/dioreg.h>
    141 #include <hp300/dev/diovar.h>
    142 #include <hp300/dev/diodevs.h>
    143 
    144 #include <hp300/dev/intioreg.h>
    145 #include <hp300/dev/dmavar.h>
    146 #include <hp300/dev/frodoreg.h>
    147 
    148 #include <hp300/dev/hpibvar.h>
    149 
    150 #if NCOM_DIO > 0
    151 #include <hp300/dev/com_diovar.h>
    152 #endif
    153 #if NCOM_FRODO > 0
    154 #include <hp300/dev/com_frodovar.h>
    155 #endif
    156 
    157 #if NSTI_DIO > 0 || NSTI_SGC > 0
    158 #include <hp300/dev/sti_machdep.h>
    159 #endif
    160 #if NSTI_DIO > 0
    161 #include <hp300/dev/sti_diovar.h>
    162 #endif
    163 #if NSTI_SGC > 0
    164 #include <hp300/dev/sgcreg.h>
    165 #include <hp300/dev/sgcvar.h>
    166 #include <hp300/dev/sti_sgcvar.h>
    167 #endif
    168 
    169 #include <hp300/dev/diofbreg.h>
    170 #include <hp300/dev/diofbvar.h>
    171 
    172 /* should go away with a cleanup */
    173 extern int dcmcnattach(bus_space_tag_t, bus_addr_t, int);
    174 extern int dnkbdcnattach(bus_space_tag_t, bus_addr_t);
    175 
    176 static int	dio_scan(int (*func)(bus_space_tag_t, bus_addr_t, int));
    177 static int	dio_scode_probe(int,
    178 		    int (*func)(bus_space_tag_t, bus_addr_t, int));
    179 
    180 /* How we were booted. */
    181 u_int	bootdev;
    182 
    183 /*
    184  * Extent map to manage the external I/O (DIO/DIO-II) space.  We
    185  * allocate storate for 8 regions in the map.  extio_ex_malloc_safe
    186  * will indicate that it's safe to use malloc() to dynamically allocate
    187  * region descriptors in case we run out.
    188  */
    189 static long extio_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];
    190 struct extent *extio_ex;
    191 int extio_ex_malloc_safe;
    192 
    193 /*
    194  * This information is built during the autoconfig process.
    195  * A little explanation about the way this works is in order.
    196  *
    197  *	device_register() links all devices into dev_data_list.
    198  *	If the device is an hpib controller, it is also linked
    199  *	into dev_data_list_hpib.  If the device is a scsi controller,
    200  *	it is also linked into dev_data_list_scsi.
    201  *
    202  *	dev_data_list_hpib and dev_data_list_scsi are sorted
    203  *	by select code, from lowest to highest.
    204  *
    205  *	After autoconfiguration is complete, we need to determine
    206  *	which device was the boot device.  The boot block assigns
    207  *	controller unit numbers in order of select code.  Thus,
    208  *	providing the controller is configured in the kernel, we
    209  *	can determine our version of controller unit number from
    210  *	the sorted hpib/scsi list.
    211  *
    212  *	At this point, we know the controller (device type
    213  *	encoded in bootdev tells us "scsi disk", or "hpib tape",
    214  *	etc.).  The next step is to find the device which
    215  *	has the following properties:
    216  *
    217  *		- A child of the boot controller.
    218  *		- Same slave as encoded in bootdev.
    219  *		- Same physical unit as encoded in bootdev.
    220  *
    221  *	Later, after we've set the root device in stone, we
    222  *	reverse the process to re-encode bootdev so it can be
    223  *	passed back to the boot block.
    224  */
    225 struct dev_data {
    226 	LIST_ENTRY(dev_data)	dd_list;  /* dev_data_list */
    227 	LIST_ENTRY(dev_data)	dd_clist; /* ctlr list */
    228 	device_t		dd_dev;  /* device described by this entry */
    229 	int			dd_scode; /* select code of device */
    230 	int			dd_slave; /* ...or slave */
    231 	int			dd_punit; /* and punit... */
    232 };
    233 typedef LIST_HEAD(, dev_data) ddlist_t;
    234 static ddlist_t	dev_data_list;		/* all dev_datas */
    235 static ddlist_t	dev_data_list_hpib;	/* hpib controller dev_datas */
    236 static ddlist_t	dev_data_list_scsi;	/* scsi controller dev_datas */
    237 
    238 static void	findbootdev(void);
    239 static void	findbootdev_slave(ddlist_t *, int, int, int);
    240 static void	setbootdev(void);
    241 
    242 static struct dev_data *dev_data_lookup(device_t);
    243 static void	dev_data_insert(struct dev_data *, ddlist_t *);
    244 
    245 static int	mainbusmatch(device_t, cfdata_t, void *);
    246 static void	mainbusattach(device_t, device_t, void *);
    247 static int	mainbussearch(device_t, cfdata_t, const int *, void *);
    248 
    249 CFATTACH_DECL_NEW(mainbus, 0,
    250     mainbusmatch, mainbusattach, NULL, NULL);
    251 
    252 static int
    253 mainbusmatch(device_t parent, cfdata_t cf, void *aux)
    254 {
    255 	static int mainbus_matched = 0;
    256 
    257 	/* Allow only one instance. */
    258 	if (mainbus_matched)
    259 		return 0;
    260 
    261 	mainbus_matched = 1;
    262 	return 1;
    263 }
    264 
    265 static void
    266 mainbusattach(device_t parent, device_t self, void *aux)
    267 {
    268 
    269 	aprint_normal("\n");
    270 
    271 	/* Search for and attach children. */
    272 	config_search(self, NULL,
    273 	    CFARGS(.search = mainbussearch));
    274 }
    275 
    276 static int
    277 mainbussearch(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
    278 {
    279 
    280 	if (config_probe(parent, cf, NULL))
    281 		config_attach(parent, cf, NULL, NULL, CFARGS_NONE);
    282 	return 0;
    283 }
    284 
    285 /*
    286  * hp300 systems need to track all DIO interrupt handlers on a single
    287  * list in order to compute the auto-vector interrupt level the DMA
    288  * controller should interrupt at.  So, we provide a custom allocator
    289  * for the common interrupt dispatch code that allocates us handles
    290  * with linkage for this list.
    291  */
    292 static struct m68k_intrhand *
    293 hp300_ih_alloc(int km_flag)
    294 {
    295 	return kmem_zalloc(sizeof(struct hp300_intrhand), km_flag);
    296 }
    297 
    298 static void
    299 hp300_ih_free(struct m68k_intrhand *ih)
    300 {
    301 	kmem_free(ih, sizeof(struct hp300_intrhand));
    302 }
    303 
    304 static const struct m68k_ih_allocfuncs hp300_ih_allocfuncs = {
    305 	.alloc = hp300_ih_alloc,
    306 	.free  = hp300_ih_free,
    307 };
    308 
    309 /*
    310  * Determine the device configuration for the running system.
    311  */
    312 void
    313 cpu_configure(void)
    314 {
    315 
    316 	/*
    317 	 * Initialize the dev_data_lists.
    318 	 */
    319 	LIST_INIT(&dev_data_list);
    320 	LIST_INIT(&dev_data_list_hpib);
    321 	LIST_INIT(&dev_data_list_scsi);
    322 
    323 	/* Kick off autoconfiguration. */
    324 	(void)splhigh();
    325 
    326 	/* Initialize the interrupt handlers. */
    327 	m68k_intr_init(&hp300_ih_allocfuncs);
    328 
    329 	if (config_rootfound("mainbus", NULL) == NULL)
    330 		panic("no mainbus found");
    331 
    332 	/* Configuration is finished, turn on interrupts. */
    333 	(void)spl0();
    334 }
    335 
    336 /**********************************************************************
    337  * Code to find and set the boot device
    338  **********************************************************************/
    339 
    340 void
    341 cpu_rootconf(void)
    342 {
    343 	struct dev_data *dd;
    344 	struct vfsops *vops;
    345 
    346 	/*
    347 	 * Find boot device.
    348 	 */
    349 	if ((bootdev & B_MAGICMASK) != B_DEVMAGIC) {
    350 		printf("WARNING: boot program didn't supply boot device.\n");
    351 		printf("Please update your boot program.\n");
    352 	} else {
    353 		findbootdev();
    354 		if (booted_device == NULL) {
    355 			printf("WARNING: can't find match for bootdev:\n");
    356 			printf(
    357 		    "type = %d, ctlr = %d, slave = %d, punit = %d, part = %d\n",
    358 			    B_TYPE(bootdev), B_ADAPTOR(bootdev),
    359 			    B_CONTROLLER(bootdev), B_UNIT(bootdev),
    360 			    B_PARTITION(bootdev));
    361 			bootdev = 0;		/* invalidate bootdev */
    362 		} else {
    363 			printf("boot device: %s\n", device_xname(booted_device));
    364 		}
    365 	}
    366 
    367 	/*
    368 	 * If wild carded root device and wired down NFS root file system,
    369 	 * pick the network interface device to use.
    370 	 */
    371 	if (rootspec == NULL) {
    372 		vops = vfs_getopsbyname(MOUNT_NFS);
    373 		if (vops != NULL && vops->vfs_mountroot != NULL &&
    374 		    strcmp(rootfstype, MOUNT_NFS) == 0) {
    375 			for (dd = LIST_FIRST(&dev_data_list);
    376 			    dd != NULL; dd = LIST_NEXT(dd, dd_list)) {
    377 				if (device_class(dd->dd_dev) == DV_IFNET) {
    378 					/* Got it! */
    379 					booted_device = dd->dd_dev;
    380 					break;
    381 				}
    382 			}
    383 			if (dd == NULL) {
    384 				printf("no network interface for NFS root");
    385 			}
    386 		}
    387 		if (vops != NULL)
    388 			vfs_delref(vops);
    389 	}
    390 
    391 	/*
    392 	 * If bootdev is bogus, ask the user anyhow.
    393 	 */
    394 	if (bootdev == 0)
    395 		boothowto |= RB_ASKNAME;
    396 
    397 	/*
    398 	 * If we booted from tape, ask the user.
    399 	 */
    400 	if (booted_device != NULL && device_class(booted_device) == DV_TAPE)
    401 		boothowto |= RB_ASKNAME;
    402 
    403 	rootconf();
    404 
    405 	/*
    406 	 * Set bootdev based on what we found as the root.
    407 	 * This is given to the boot program when we reboot.
    408 	 */
    409 	setbootdev();
    410 
    411 }
    412 
    413 /*
    414  * Register a device.  We're passed the device and the arguments
    415  * used to attach it.  This is used to find the boot device.
    416  */
    417 void
    418 device_register(device_t dev, void *aux)
    419 {
    420 	struct dev_data *dd;
    421 	static int seen_netdevice = 0;
    422 
    423 	/*
    424 	 * Allocate a dev_data structure and fill it in.
    425 	 * This means making some tests twice, but we don't
    426 	 * care; this doesn't really have to be fast.
    427 	 *
    428 	 * Note that we only really care about devices that
    429 	 * we can mount as root.
    430 	 */
    431 
    432 	dd = kmem_zalloc(sizeof(*dd), KM_SLEEP);
    433 	dd->dd_dev = dev;
    434 
    435 	/*
    436 	 * BOOTROM and boot program can really only understand
    437 	 * using the lowest select code network interface,
    438 	 * so we ignore all but the first.
    439 	 */
    440 	if (device_class(dev) == DV_IFNET && seen_netdevice == 0) {
    441 		struct dio_attach_args *da = aux;
    442 
    443 		seen_netdevice = 1;
    444 		dd->dd_scode = da->da_scode;
    445 		goto linkup;
    446 	}
    447 
    448 	if (device_is_a(dev, "fhpib") ||
    449 	    device_is_a(dev, "nhpib") ||
    450 	    device_is_a(dev, "spc")) {
    451 		struct dio_attach_args *da = aux;
    452 
    453 		dd->dd_scode = da->da_scode;
    454 		goto linkup;
    455 	}
    456 
    457 	if (device_is_a(dev, "rd")) {
    458 		struct hpibbus_attach_args *ha = aux;
    459 
    460 		dd->dd_slave = ha->ha_slave;
    461 		dd->dd_punit = ha->ha_punit;
    462 		goto linkup;
    463 	}
    464 
    465 	if (device_is_a(dev, "sd") ||
    466 	    device_is_a(dev, "cd")) {
    467 		struct scsipibus_attach_args *sa = aux;
    468 
    469 		dd->dd_slave = sa->sa_periph->periph_target;
    470 		dd->dd_punit = sa->sa_periph->periph_lun;
    471 		goto linkup;
    472 	}
    473 
    474 	/*
    475 	 * Didn't need the dev_data.
    476 	 */
    477 	kmem_free(dd, sizeof(*dd));
    478 	return;
    479 
    480  linkup:
    481 	LIST_INSERT_HEAD(&dev_data_list, dd, dd_list);
    482 
    483 	if (device_is_a(dev, "fhpib") ||
    484 	    device_is_a(dev, "nhpib")) {
    485 		dev_data_insert(dd, &dev_data_list_hpib);
    486 		return;
    487 	}
    488 
    489 	if (device_is_a(dev, "spc")) {
    490 		dev_data_insert(dd, &dev_data_list_scsi);
    491 		return;
    492 	}
    493 }
    494 
    495 static void
    496 findbootdev(void)
    497 {
    498 	int type, ctlr, slave, punit, part;
    499 	int scsiboot, hpibboot, netboot;
    500 	struct dev_data *dd;
    501 
    502 	booted_device = NULL;
    503 	booted_partition = 0;
    504 
    505 	if ((bootdev & B_MAGICMASK) != B_DEVMAGIC)
    506 		return;
    507 
    508 	type  = B_TYPE(bootdev);
    509 	ctlr  = B_ADAPTOR(bootdev);
    510 	slave = B_CONTROLLER(bootdev);
    511 	punit = B_UNIT(bootdev);
    512 	part  = B_PARTITION(bootdev);
    513 
    514 	scsiboot = (type == 4);			/* sd or cd */
    515 	hpibboot = (type == 0 || type == 2);	/* ct/rd */
    516 	netboot  = (type == 6);			/* le - special */
    517 
    518 	/*
    519 	 * Check for network boot first, since it's a little
    520 	 * different.  The BOOTROM/boot program can only boot
    521 	 * off of the first (lowest select code) ethernet
    522 	 * device.  device_register() knows this and only
    523 	 * registers one DV_IFNET.  This is a safe assumption
    524 	 * since the code that finds devices on the DIO bus
    525 	 * always starts at scode 0 and works its way up.
    526 	 */
    527 	if (netboot) {
    528 		for (dd = LIST_FIRST(&dev_data_list); dd != NULL;
    529 		    dd = LIST_NEXT(dd, dd_list)) {
    530 			if (device_class(dd->dd_dev) == DV_IFNET) {
    531 				/*
    532 				 * Found it!
    533 				 */
    534 				booted_device = dd->dd_dev;
    535 				break;
    536 			}
    537 		}
    538 		return;
    539 	}
    540 
    541 	/*
    542 	 * Check for HP-IB boots next.
    543 	 */
    544 	if (hpibboot) {
    545 		findbootdev_slave(&dev_data_list_hpib, ctlr,
    546 		    slave, punit);
    547 		if (booted_device == NULL)
    548 			return;
    549 
    550 		/*
    551 		 * Sanity check.
    552 		 */
    553 		if ((type == 0 && !device_is_a(booted_device, "ct")) ||
    554 		    (type == 2 && !device_is_a(booted_device, "rd"))) {
    555 			printf("WARNING: boot device/type mismatch!\n");
    556 			printf("device = %s, type = %d\n",
    557 			    device_xname(booted_device), type);
    558 			booted_device = NULL;
    559 		}
    560 		goto out;
    561 	}
    562 
    563 	/*
    564 	 * Check for SCSI boots last.
    565 	 */
    566 	if (scsiboot) {
    567 		findbootdev_slave(&dev_data_list_scsi, ctlr,
    568 		     slave, punit);
    569 		if (booted_device == NULL)
    570 			return;
    571 
    572 		/*
    573 		 * Sanity check.
    574 		 */
    575 		if (type ==  4 &&
    576 		    !device_is_a(booted_device, "sd") &&
    577 		    !device_is_a(booted_device, "cd")) {
    578 			printf("WARNING: boot device/type mismatch!\n");
    579 			printf("device = %s, type = %d\n",
    580 			    device_xname(booted_device), type);
    581 			booted_device = NULL;
    582 		}
    583 		goto out;
    584 	}
    585 
    586 	/* Oof! */
    587 	printf("WARNING: UNKNOWN BOOT DEVICE TYPE = %d\n", type);
    588 
    589  out:
    590 	if (booted_device != NULL)
    591 		booted_partition = part;
    592 }
    593 
    594 static void
    595 findbootdev_slave(ddlist_t *ddlist, int ctlr, int slave, int punit)
    596 {
    597 	struct dev_data *cdd, *dd;
    598 
    599 	/*
    600 	 * Find the booted controller.
    601 	 */
    602 	for (cdd = LIST_FIRST(ddlist); ctlr != 0 && cdd != NULL;
    603 	    cdd = LIST_NEXT(cdd, dd_clist))
    604 		ctlr--;
    605 	if (cdd == NULL) {
    606 		/*
    607 		 * Oof, couldn't find it...
    608 		 */
    609 		return;
    610 	}
    611 
    612 	/*
    613 	 * Now find the device with the right slave/punit
    614 	 * that's a child of the controller.
    615 	 */
    616 	for (dd = LIST_FIRST(&dev_data_list); dd != NULL;
    617 	    dd = LIST_NEXT(dd, dd_list)) {
    618 		/*
    619 		 * "sd" -> "scsibus" -> "spc"
    620 		 * "rd" -> "hpibbus" -> "fhpib"
    621 		 */
    622 		if (device_parent(device_parent(dd->dd_dev)) != cdd->dd_dev)
    623 			continue;
    624 
    625 		if (dd->dd_slave == slave &&
    626 		    dd->dd_punit == punit) {
    627 			/*
    628 			 * Found it!
    629 			 */
    630 			booted_device = dd->dd_dev;
    631 			break;
    632 		}
    633 	}
    634 }
    635 
    636 static void
    637 setbootdev(void)
    638 {
    639 	struct dev_data *cdd, *dd;
    640 	int type, ctlr;
    641 
    642 	/*
    643 	 * Note our magic numbers for type shared with the BOOTROM:
    644 	 *
    645 	 *	0 == ct
    646 	 *	2 == rd
    647 	 *	4 == sd or cd
    648 	 *	6 == le
    649 	 *
    650 	 * All are bdevsw major numbers, except for le and cd.
    651 	 * le is just special. cd is treated as sd by the BOOTROM.
    652 	 *
    653 	 * We can't mount root on a tape, so we ignore those.
    654 	 */
    655 
    656 	/*
    657 	 * Start with a clean slate.
    658 	 */
    659 	bootdev = 0;
    660 
    661 	/*
    662 	 * If the root device is network, we're done
    663 	 * early.
    664 	 */
    665 	if (device_class(root_device) == DV_IFNET) {
    666 		bootdev = MAKEBOOTDEV(6, 0, 0, 0, 0);
    667 		goto out;
    668 	}
    669 
    670 	/*
    671 	 * Determine device type.
    672 	 */
    673 	if (device_is_a(root_device, "rd"))
    674 		type = 2;
    675 	else if (device_is_a(root_device, "sd"))
    676 		type = 4;
    677 	else if (device_is_a(root_device, "cd"))
    678 		type = 4;	/* not a major, but for MAKEBOOTDEV() */
    679 	else if (device_is_a(root_device, "md"))
    680 		goto out;
    681 	else {
    682 		printf("WARNING: strange root device!\n");
    683 		goto out;
    684 	}
    685 
    686 	dd = dev_data_lookup(root_device);
    687 
    688 	/*
    689 	 * Get parent's info.
    690 	 */
    691 	switch (type) {
    692 	case 2: /* rd */
    693 		/*
    694 		 * "rd" -> "hpibbus" -> "fhpib"
    695 		 * "rd" -> "hpibbus" -> "nhpib"
    696 		 */
    697 		for (cdd = LIST_FIRST(&dev_data_list_hpib), ctlr = 0;
    698 		    cdd != NULL; cdd = LIST_NEXT(cdd, dd_clist), ctlr++) {
    699 			if (cdd->dd_dev ==
    700 			    device_parent(device_parent(root_device))) {
    701 				/*
    702 				 * Found it!
    703 				 */
    704 				bootdev = MAKEBOOTDEV(type,
    705 				    ctlr, dd->dd_slave, dd->dd_punit,
    706 				    DISKPART(rootdev));
    707 				break;
    708 			}
    709 		}
    710 		break;
    711 	case 4: /* sd or cd */
    712 		/*
    713 		 * "sd" -> "scsibus" -> "spc"
    714 		 */
    715 		for (cdd = LIST_FIRST(&dev_data_list_scsi), ctlr = 0;
    716 		    cdd != NULL; cdd = LIST_NEXT(cdd, dd_clist), ctlr++) {
    717 			if (cdd->dd_dev ==
    718 			    device_parent(device_parent(root_device))) {
    719 				/*
    720 				 * Found it!
    721 				 */
    722 				bootdev = MAKEBOOTDEV(type,
    723 				    ctlr, dd->dd_slave, dd->dd_punit,
    724 				    DISKPART(rootdev));
    725 				break;
    726 			}
    727 		}
    728 		break;
    729 	}
    730 
    731  out:
    732 	/* Don't need this anymore. */
    733 	for (dd = LIST_FIRST(&dev_data_list); dd != NULL; ) {
    734 		cdd = dd;
    735 		dd = LIST_NEXT(dd, dd_list);
    736 		kmem_free(cdd, sizeof(*cdd));
    737 	}
    738 }
    739 
    740 /*
    741  * Return the dev_data corresponding to the given device.
    742  */
    743 static struct dev_data *
    744 dev_data_lookup(device_t dev)
    745 {
    746 	struct dev_data *dd;
    747 
    748 	for (dd = LIST_FIRST(&dev_data_list); dd != NULL;
    749 	    dd = LIST_NEXT(dd, dd_list))
    750 		if (dd->dd_dev == dev)
    751 			return dd;
    752 
    753 	panic("dev_data_lookup");
    754 }
    755 
    756 /*
    757  * Insert a dev_data into the provided list, sorted by select code.
    758  */
    759 static void
    760 dev_data_insert(struct dev_data *dd, ddlist_t *ddlist)
    761 {
    762 	struct dev_data *de;
    763 
    764 #ifdef DIAGNOSTIC
    765 	if (dd->dd_scode < 0 || dd->dd_scode > 255) {
    766 		printf("bogus select code for %s\n", device_xname(dd->dd_dev));
    767 		panic("dev_data_insert");
    768 	}
    769 #endif
    770 
    771 	de = LIST_FIRST(ddlist);
    772 
    773 	/*
    774 	 * Just insert at head if list is empty.
    775 	 */
    776 	if (de == NULL) {
    777 		LIST_INSERT_HEAD(ddlist, dd, dd_clist);
    778 		return;
    779 	}
    780 
    781 	/*
    782 	 * Traverse the list looking for a device who's select code
    783 	 * is greater than ours.  When we find it, insert ourselves
    784 	 * into the list before it.
    785 	 */
    786 	for (; LIST_NEXT(de, dd_clist) != NULL; de = LIST_NEXT(de, dd_clist)) {
    787 		if (de->dd_scode > dd->dd_scode) {
    788 			LIST_INSERT_BEFORE(de, dd, dd_clist);
    789 			return;
    790 		}
    791 	}
    792 
    793 	/*
    794 	 * Our select code is greater than everyone else's.  We go
    795 	 * onto the end.
    796 	 */
    797 	LIST_INSERT_AFTER(de, dd, dd_clist);
    798 }
    799 
    800 /**********************************************************************
    801  * Code to find and initialize the console
    802  **********************************************************************/
    803 
    804 int conscode;
    805 void *conaddr;
    806 
    807 static bool cninit_deferred;
    808 #if NSTI_SGC > 0
    809 static int consslot = -1;
    810 #endif
    811 
    812 void
    813 hp300_cninit(void)
    814 {
    815 	struct bus_space_tag tag;
    816 	bus_space_tag_t bst;
    817 
    818 	bst = &tag;
    819 	memset(bst, 0, sizeof(struct bus_space_tag));
    820 	bst->bustype = HP300_BUS_SPACE_INTIO;
    821 
    822 	/*
    823 	 * Look for serial consoles first.
    824 	 */
    825 #if NCOM_FRODO > 0
    826 	if (!com_frodo_cnattach(bst, FRODO_BASE + FRODO_APCI_OFFSET(1),
    827 	    CONSCODE_INTERNAL))
    828 		return;
    829 #endif
    830 #if NCOM_DIO > 0
    831 	if (!dio_scan(com_dio_cnattach))
    832 		return;
    833 #endif
    834 #if NDCM > 0
    835 	if (!dio_scan(dcmcnattach))
    836 		return;
    837 #endif
    838 
    839 #ifndef CONSCODE
    840 	/*
    841 	 * Look for internal framebuffers.
    842 	 */
    843 #if NDVBOX > 0
    844 	if (!dvboxcnattach(bst, FB_BASE, CONSCODE_INTERNAL))
    845 		goto find_kbd;
    846 #endif
    847 #if NGBOX > 0
    848 	if (!gboxcnattach(bst, FB_BASE, CONSCODE_INTERNAL))
    849 		goto find_kbd;
    850 #endif
    851 #if NRBOX > 0
    852 	if (!rboxcnattach(bst, FB_BASE, CONSCODE_INTERNAL))
    853 		goto find_kbd;
    854 #endif
    855 #if NTOPCAT > 0
    856 	if (!topcatcnattach(bst, FB_BASE, CONSCODE_INTERNAL))
    857 		goto find_kbd;
    858 #endif
    859 #endif	/* CONSCODE */
    860 
    861 	/*
    862 	 * Look for external framebuffers.
    863 	 */
    864 #if NDVBOX > 0
    865 	if (!dio_scan(dvboxcnattach))
    866 		goto find_kbd;
    867 #endif
    868 #if NGBOX > 0
    869 	if (!dio_scan(gboxcnattach))
    870 		goto find_kbd;
    871 #endif
    872 #if NHYPER > 0
    873 	if (!dio_scan(hypercnattach))
    874 		goto find_kbd;
    875 #endif
    876 #if NRBOX > 0
    877 	if (!dio_scan(rboxcnattach))
    878 		goto find_kbd;
    879 #endif
    880 #if NTOPCAT > 0
    881 	if (!dio_scan(topcatcnattach))
    882 		goto find_kbd;
    883 #endif
    884 #if NTVRX > 0
    885 	if (!dio_scan(tvrxcnattach))
    886 		goto find_kbd;
    887 #endif
    888 #if NSTI_DIO > 0
    889 	if (!dio_scan(sti_dio_cnprobe)) {
    890 		cninit_deferred = true;
    891 		goto find_kbd;
    892 	}
    893 #endif
    894 #if NGENDIOFB > 0
    895 	if (!dio_scan(gendiofbcnattach))
    896 		goto find_kbd;
    897 #endif
    898 #if NSTI_SGC > 0
    899 	if (machineid == HP_400 ||
    900 	    machineid == HP_425 ||
    901 	    machineid == HP_433) {
    902 		struct bus_space_tag sgc_tag;
    903 		bus_space_tag_t sgc_bst;
    904 		u_int slot;
    905 
    906 		sgc_bst = &sgc_tag;
    907 		memset(sgc_bst, 0, sizeof(struct bus_space_tag));
    908 		sgc_bst->bustype = HP300_BUS_SPACE_SGC;
    909 		for (slot = 0; slot < SGC_NSLOTS; slot++) {
    910 			if (sti_sgc_cnprobe(sgc_bst, slot)) {
    911 				cninit_deferred = true;
    912 				consslot = slot;
    913 				goto find_kbd;
    914 			}
    915 		}
    916 	}
    917 #endif
    918 
    919 #if (NDVBOX + NGBOX + NRBOX + NTOPCAT + NDVBOX + NGBOX + NHYPER + NRBOX + \
    920      NTOPCAT + NTVRX + NGENDIOFB + NSTI_DIO + NSTI_SGC) > 0
    921 find_kbd:
    922 #endif
    923 
    924 #if NDNKBD > 0
    925 	dnkbdcnattach(bst, FRODO_BASE + FRODO_APCI_OFFSET(0))
    926 #endif
    927 
    928 #if NHILKBD > 0
    929 	/* not yet */
    930 	hilkbdcnattach(bst, HIL_BASE);
    931 #endif
    932 	return;
    933 }
    934 
    935 static int
    936 dio_scan(int (*func)(bus_space_tag_t, bus_addr_t, int))
    937 {
    938 #ifndef CONSCODE
    939 	int scode, sctop;
    940 
    941 	sctop = DIO_SCMAX(machineid);
    942 	for (scode = 0; scode < sctop; ++scode) {
    943 		if (DIO_INHOLE(scode) || ((scode == 7) && internalhpib))
    944 			continue;
    945 		if (!dio_scode_probe(scode, func))
    946 			return 0;
    947 	}
    948 #else
    949 		if (!dio_scode_probe(CONSCODE, func))
    950 			return 0;
    951 #endif
    952 
    953 	return 1;
    954 }
    955 
    956 static int
    957 dio_scode_probe(int scode, int (*func)(bus_space_tag_t, bus_addr_t, int))
    958 {
    959 	struct bus_space_tag tag;
    960 	bus_space_tag_t bst;
    961 	void *pa, *va;
    962 
    963 	bst = &tag;
    964 	memset(bst, 0, sizeof(struct bus_space_tag));
    965 	bst->bustype = HP300_BUS_SPACE_DIO;
    966 	pa = dio_scodetopa(scode);
    967 	va = iomap(pa, PAGE_SIZE);
    968 	if (va == 0)
    969 		return 1;
    970 	if (badaddr(va)) {
    971 		iounmap(va, PAGE_SIZE);
    972 		return 1;
    973 	}
    974 	iounmap(va, PAGE_SIZE);
    975 
    976 	return (*func)(bst, (bus_addr_t)pa, scode);
    977 }
    978 
    979 void
    980 hp300_cninit_deferred(void)
    981 {
    982 
    983 	if (!cninit_deferred)
    984 		return;
    985 
    986 #if NSTI_DIO > 0
    987 	if (machineid == HP_362 ||
    988 	    machineid == HP_382) {
    989 		struct bus_space_tag dio_tag;
    990 		bus_space_tag_t dio_bst;
    991 
    992 		dio_bst = &dio_tag;
    993 		memset(dio_bst, 0, sizeof(struct bus_space_tag));
    994 		dio_bst->bustype = HP300_BUS_SPACE_DIO;
    995 		sti_dio_cnattach(dio_bst, conscode);
    996 	}
    997 #endif
    998 #if NSTI_SGC > 0
    999 	if (machineid == HP_400 ||
   1000 	    machineid == HP_425 ||
   1001 	    machineid == HP_433) {
   1002 		struct bus_space_tag sgc_tag;
   1003 		bus_space_tag_t sgc_bst;
   1004 
   1005 		sgc_bst = &sgc_tag;
   1006 		memset(sgc_bst, 0, sizeof(struct bus_space_tag));
   1007 		sgc_bst->bustype = HP300_BUS_SPACE_SGC;
   1008 		sti_sgc_cnattach(sgc_bst, consslot);
   1009 	}
   1010 #endif
   1011 }
   1012 
   1013 
   1014 /**********************************************************************
   1015  * Mapping functions
   1016  **********************************************************************/
   1017 
   1018 /*
   1019  * Initialize the external I/O extent map.
   1020  */
   1021 void
   1022 iomap_init(void)
   1023 {
   1024 
   1025 	/* extiobase is initialized by pmap_bootstrap(). */
   1026 	extio_ex = extent_create("extio", (u_long) extiobase,
   1027 	    (u_long) extiobase + (ptoa(EIOMAPSIZE) - 1),
   1028 	    (void *) extio_ex_storage, sizeof(extio_ex_storage),
   1029 	    EX_NOCOALESCE|EX_NOWAIT);
   1030 }
   1031 
   1032 /*
   1033  * Allocate/deallocate a cache-inhibited range of kernel virtual address
   1034  * space mapping the indicated physical address range [pa - pa+size)
   1035  */
   1036 void *
   1037 iomap(void *pa, int size)
   1038 {
   1039 	u_long kva;
   1040 	int error;
   1041 
   1042 #ifdef DEBUG
   1043 	if (((int)pa & PGOFSET) || (size & PGOFSET))
   1044 		panic("iomap: unaligned");
   1045 #endif
   1046 
   1047 	error = extent_alloc(extio_ex, size, PAGE_SIZE, 0,
   1048 	    EX_FAST | EX_NOWAIT | (extio_ex_malloc_safe ? EX_MALLOCOK : 0),
   1049 	    &kva);
   1050 	if (error)
   1051 		return 0;
   1052 
   1053 	physaccess((void *) kva, pa, size, PG_RW|PG_CI);
   1054 	return (void *)kva;
   1055 }
   1056 
   1057 /*
   1058  * Unmap a previously mapped device.
   1059  */
   1060 void
   1061 iounmap(void *kva, int size)
   1062 {
   1063 
   1064 #ifdef DEBUG
   1065 	if (((vaddr_t)kva & PGOFSET) || (size & PGOFSET))
   1066 		panic("iounmap: unaligned");
   1067 	if ((uint8_t *)kva < extiobase ||
   1068 	    (uint8_t *)kva >= extiobase + ptoa(EIOMAPSIZE))
   1069 		panic("iounmap: bad address");
   1070 #endif
   1071 	physunaccess(kva, size);
   1072 	if (extent_free(extio_ex, (vaddr_t)kva, size,
   1073 	    EX_NOWAIT | (extio_ex_malloc_safe ? EX_MALLOCOK : 0)))
   1074 		printf("iounmap: kva %p size 0x%x: can't free region\n",
   1075 		    kva, size);
   1076 }
   1077