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