xref: /netbsd/sys/arch/hp300/hp300/autoconf.c (revision bf9ec67e)
1 /*	$NetBSD: autoconf.c,v 1.57 2002/04/17 20:40:30 gmcgarry Exp $	*/
2 
3 /*-
4  * Copyright (c) 1996, 1997 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.57 2002/04/17 20:40:30 gmcgarry 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/map.h>
125 #include <sys/mount.h>
126 #include <sys/queue.h>
127 #include <sys/reboot.h>
128 #include <sys/tty.h>
129 
130 #include <dev/cons.h>
131 
132 #include <machine/autoconf.h>
133 #include <machine/vmparam.h>
134 #include <machine/cpu.h>
135 #include <machine/hp300spu.h>
136 #include <machine/intr.h>
137 #include <machine/pte.h>
138 
139 #include <hp300/dev/dioreg.h>
140 #include <hp300/dev/diovar.h>
141 #include <hp300/dev/diodevs.h>
142 
143 #include <hp300/dev/dmavar.h>
144 #include <hp300/dev/grfreg.h>
145 #include <hp300/dev/hilreg.h>
146 #include <hp300/dev/hilioctl.h>
147 #include <hp300/dev/hilvar.h>
148 
149 #include <hp300/dev/hpibvar.h>
150 #include <hp300/dev/scsivar.h>
151 
152 
153 /* should go away with a cleanup */
154 extern int dcacnattach(bus_space_tag_t, bus_addr_t, int);
155 extern int dcmcnattach(bus_space_tag_t, bus_addr_t, int);
156 extern int apcicnattach(bus_space_tag_t, bus_addr_t, int);
157 extern int dvboxcnattach(bus_space_tag_t, bus_addr_t, int);
158 extern int gboxcnattach(bus_space_tag_t, bus_addr_t, int);
159 extern int rboxcnattach(bus_space_tag_t, bus_addr_t, int);
160 extern int hypercnattach(bus_space_tag_t, bus_addr_t, int);
161 extern int topcatcnattach(bus_space_tag_t, bus_addr_t, int);
162 extern int hilkbdcnattach(bus_space_tag_t, bus_addr_t);
163 extern int dnkbdcnattach(bus_space_tag_t, bus_addr_t);
164 
165 int dio_scan(int (*func)(bus_space_tag_t, bus_addr_t, int));
166 int dio_scode_probe(int, int (*func)(bus_space_tag_t, bus_addr_t, int));
167 
168 /* XXX must be allocated statically because of early console init */
169 struct	map extiomap[EIOMAPSIZE/16];
170 
171 extern	caddr_t internalhpib;
172 extern	char *extiobase;
173 
174 /* The boot device. */
175 struct	device *booted_device;
176 int	booted_partition;
177 
178 /* How we were booted. */
179 u_int	bootdev;
180 
181 /*
182  * This information is built during the autoconfig process.
183  * A little explanation about the way this works is in order.
184  *
185  *	device_register() links all devices into dev_data_list.
186  *	If the device is an hpib controller, it is also linked
187  *	into dev_data_list_hpib.  If the device is a scsi controller,
188  *	it is also linked into dev_data_list_scsi.
189  *
190  *	dev_data_list_hpib and dev_data_list_scsi are sorted
191  *	by select code, from lowest to highest.
192  *
193  *	After autoconfiguration is complete, we need to determine
194  *	which device was the boot device.  The boot block assigns
195  *	controller unit numbers in order of select code.  Thus,
196  *	providing the controller is configured in the kernel, we
197  *	can determine our version of controller unit number from
198  *	the sorted hpib/scsi list.
199  *
200  *	At this point, we know the controller (device type
201  *	encoded in bootdev tells us "scsi disk", or "hpib tape",
202  *	etc.).  The next step is to find the device which
203  *	has the following properties:
204  *
205  *		- A child of the boot controller.
206  *		- Same slave as encoded in bootdev.
207  *		- Same physical unit as encoded in bootdev.
208  *
209  *	Later, after we've set the root device in stone, we
210  *	reverse the process to re-encode bootdev so it can be
211  *	passed back to the boot block.
212  */
213 struct dev_data {
214 	LIST_ENTRY(dev_data)	dd_list;  /* dev_data_list */
215 	LIST_ENTRY(dev_data)	dd_clist; /* ctlr list */
216 	struct device		*dd_dev;  /* device described by this entry */
217 	int			dd_scode; /* select code of device */
218 	int			dd_slave; /* ...or slave */
219 	int			dd_punit; /* and punit... */
220 };
221 typedef LIST_HEAD(, dev_data) ddlist_t;
222 ddlist_t	dev_data_list;	  	/* all dev_datas */
223 ddlist_t	dev_data_list_hpib;	/* hpib controller dev_datas */
224 ddlist_t	dev_data_list_scsi;	/* scsi controller dev_datas */
225 
226 void	findbootdev __P((void));
227 void	findbootdev_slave __P((ddlist_t *, int, int, int));
228 void	setbootdev __P((void));
229 
230 static	struct dev_data *dev_data_lookup __P((struct device *));
231 static	void dev_data_insert __P((struct dev_data *, ddlist_t *));
232 
233 int	mainbusmatch __P((struct device *, struct cfdata *, void *));
234 void	mainbusattach __P((struct device *, struct device *, void *));
235 int	mainbussearch __P((struct device *, struct cfdata *, void *));
236 
237 struct cfattach mainbus_ca = {
238 	sizeof(struct device), mainbusmatch, mainbusattach
239 };
240 
241 int
242 mainbusmatch(parent, match, aux)
243 	struct device *parent;
244 	struct cfdata *match;
245 	void *aux;
246 {
247 	static int mainbus_matched = 0;
248 
249 	/* Allow only one instance. */
250 	if (mainbus_matched)
251 		return (0);
252 
253 	mainbus_matched = 1;
254 	return (1);
255 }
256 
257 void
258 mainbusattach(parent, self, aux)
259 	struct device *parent, *self;
260 	void *aux;
261 {
262 
263 	printf("\n");
264 
265 	/* Search for and attach children. */
266 	config_search(mainbussearch, self, NULL);
267 }
268 
269 int
270 mainbussearch(parent, cf, aux)
271 	struct device *parent;
272 	struct cfdata *cf;
273 	void *aux;
274 {
275 
276 	if ((*cf->cf_attach->ca_match)(parent, cf, NULL) > 0)
277 		config_attach(parent, cf, NULL, NULL);
278 	return (0);
279 }
280 
281 /*
282  * Determine the device configuration for the running system.
283  */
284 void
285 cpu_configure()
286 {
287 
288 	/*
289 	 * Initialize the dev_data_lists.
290 	 */
291 	LIST_INIT(&dev_data_list);
292 	LIST_INIT(&dev_data_list_hpib);
293 	LIST_INIT(&dev_data_list_scsi);
294 
295 	/* Kick off autoconfiguration. */
296 	(void)splhigh();
297 
298 	softintr_init();
299 
300 	if (config_rootfound("mainbus", "mainbus") == NULL)
301 		panic("no mainbus found");
302 
303 	/* Configuration is finished, turn on interrupts. */
304 	(void)spl0();
305 
306 	intr_printlevels();
307 }
308 
309 /**********************************************************************
310  * Code to find and set the boot device
311  **********************************************************************/
312 
313 void
314 cpu_rootconf()
315 {
316 	struct dev_data *dd;
317 	struct device *dv;
318 	struct vfsops *vops;
319 
320 	/*
321 	 * Find boot device.
322 	 */
323 	if ((bootdev & B_MAGICMASK) != B_DEVMAGIC) {
324 		printf("WARNING: boot program didn't supply boot device.\n");
325 		printf("Please update your boot program.\n");
326 	} else {
327 		findbootdev();
328 		if (booted_device == NULL) {
329 			printf("WARNING: can't find match for bootdev:\n");
330 			printf(
331 		    "type = %d, ctlr = %d, slave = %d, punit = %d, part = %d\n",
332 			    B_TYPE(bootdev), B_ADAPTOR(bootdev),
333 			    B_CONTROLLER(bootdev), B_UNIT(bootdev),
334 			    B_PARTITION(bootdev));
335 			bootdev = 0;		/* invalidate bootdev */
336 		} else {
337 			printf("boot device: %s\n", booted_device->dv_xname);
338 		}
339 	}
340 
341 	dv = booted_device;
342 
343 	/*
344 	 * If wild carded root device and wired down NFS root file system,
345 	 * pick the network interface device to use.
346 	 */
347 	if (rootspec == NULL) {
348 		vops = vfs_getopsbyname("nfs");
349 		if (vops != NULL && vops->vfs_mountroot == mountroot) {
350 			for (dd = dev_data_list.lh_first;
351 			    dd != NULL; dd = dd->dd_list.le_next) {
352 				if (dd->dd_dev->dv_class == DV_IFNET) {
353 					/* Got it! */
354 					dv = dd->dd_dev;
355 					break;
356 				}
357 			}
358 			if (dd == NULL) {
359 				printf("no network interface for NFS root");
360 				dv = NULL;
361 			}
362 		}
363 	}
364 
365 	/*
366 	 * If bootdev is bogus, ask the user anyhow.
367 	 */
368 	if (bootdev == 0)
369 		boothowto |= RB_ASKNAME;
370 
371 	/*
372 	 * If we booted from tape, ask the user.
373 	 */
374 	if (booted_device != NULL && booted_device->dv_class == DV_TAPE)
375 		boothowto |= RB_ASKNAME;
376 
377 	setroot(dv, booted_partition);
378 
379 	/*
380 	 * Set bootdev based on what we found as the root.
381 	 * This is given to the boot program when we reboot.
382 	 */
383 	setbootdev();
384 
385 }
386 
387 /*
388  * Register a device.  We're passed the device and the arguments
389  * used to attach it.  This is used to find the boot device.
390  */
391 void
392 device_register(dev, aux)
393 	struct device *dev;
394 	void *aux;
395 {
396 	struct dev_data *dd;
397 	static int seen_netdevice = 0;
398 
399 	/*
400 	 * Allocate a dev_data structure and fill it in.
401 	 * This means making some tests twice, but we don't
402 	 * care; this doesn't really have to be fast.
403 	 *
404 	 * Note that we only really care about devices that
405 	 * we can mount as root.
406 	 */
407 
408 	MALLOC(dd, struct dev_data *, sizeof(struct dev_data),
409 	    M_DEVBUF, M_NOWAIT | M_ZERO);
410 	if (dd == NULL)
411 		panic("device_register: can't allocate dev_data");
412 
413 	dd->dd_dev = dev;
414 
415 	/*
416 	 * BOOTROM and boot program can really only understand
417 	 * using the lowest select code network interface,
418 	 * so we ignore all but the first.
419 	 */
420 	if (dev->dv_class == DV_IFNET && seen_netdevice == 0) {
421 		struct dio_attach_args *da = aux;
422 
423 		seen_netdevice = 1;
424 		dd->dd_scode = da->da_scode;
425 		goto linkup;
426 	}
427 
428 	if (memcmp(dev->dv_xname, "fhpib", 5) == 0 ||
429 	    memcmp(dev->dv_xname, "nhpib", 5) == 0 ||
430 	    memcmp(dev->dv_xname, "oscsi", 5) == 0) {
431 		struct dio_attach_args *da = aux;
432 
433 		dd->dd_scode = da->da_scode;
434 		goto linkup;
435 	}
436 
437 	if (memcmp(dev->dv_xname, "rd", 2) == 0) {
438 		struct hpibbus_attach_args *ha = aux;
439 
440 		dd->dd_slave = ha->ha_slave;
441 		dd->dd_punit = ha->ha_punit;
442 		goto linkup;
443 	}
444 
445 	if (memcmp(dev->dv_xname, "sd", 2) == 0) {
446 		struct oscsi_attach_args *osa = aux;
447 
448 		dd->dd_slave = osa->osa_target;
449 		dd->dd_punit = osa->osa_lun;
450 		goto linkup;
451 	}
452 
453 	/*
454 	 * Didn't need the dev_data.
455 	 */
456 	free(dd, M_DEVBUF);
457 	return;
458 
459  linkup:
460 	LIST_INSERT_HEAD(&dev_data_list, dd, dd_list);
461 
462 	if (memcmp(dev->dv_xname, "fhpib", 5) == 0 ||
463 	    memcmp(dev->dv_xname, "nhpib", 5) == 0) {
464 		dev_data_insert(dd, &dev_data_list_hpib);
465 		return;
466 	}
467 
468 	if (memcmp(dev->dv_xname, "oscsi", 5) == 0) {
469 		dev_data_insert(dd, &dev_data_list_scsi);
470 		return;
471 	}
472 }
473 
474 void
475 findbootdev()
476 {
477 	int type, ctlr, slave, punit, part;
478 	int scsiboot, hpibboot, netboot;
479 	struct dev_data *dd;
480 
481 	booted_device = NULL;
482 	booted_partition = 0;
483 
484 	if ((bootdev & B_MAGICMASK) != B_DEVMAGIC)
485 		return;
486 
487 	type  = B_TYPE(bootdev);
488 	ctlr  = B_ADAPTOR(bootdev);
489 	slave = B_CONTROLLER(bootdev);
490 	punit = B_UNIT(bootdev);
491 	part  = B_PARTITION(bootdev);
492 
493 	scsiboot = (type == 4);			/* sd major */
494 	hpibboot = (type == 0 || type == 2);	/* ct/rd major */
495 	netboot  = (type == 6);			/* le - special */
496 
497 	/*
498 	 * Check for network boot first, since it's a little
499 	 * different.  The BOOTROM/boot program can only boot
500 	 * off of the first (lowest select code) ethernet
501 	 * device.  device_register() knows this and only
502 	 * registers one DV_IFNET.  This is a safe assumption
503 	 * since the code that finds devices on the DIO bus
504 	 * always starts at scode 0 and works its way up.
505 	 */
506 	if (netboot) {
507 		for (dd = dev_data_list.lh_first; dd != NULL;
508 		    dd = dd->dd_list.le_next) {
509 			if (dd->dd_dev->dv_class == DV_IFNET) {
510 				/*
511 				 * Found it!
512 				 */
513 				booted_device = dd->dd_dev;
514 				break;
515 			}
516 		}
517 		return;
518 	}
519 
520 	/*
521 	 * Check for HP-IB boots next.
522 	 */
523 	if (hpibboot) {
524 		findbootdev_slave(&dev_data_list_hpib, ctlr,
525 		    slave, punit);
526 		if (booted_device == NULL)
527 			return;
528 
529 		/*
530 		 * Sanity check.
531 		 */
532 		if ((type == 0 && memcmp(booted_device->dv_xname, "ct", 2)) ||
533 		    (type == 2 && memcmp(booted_device->dv_xname, "rd", 2))) {
534 			printf("WARNING: boot device/type mismatch!\n");
535 			printf("device = %s, type = %d\n",
536 			    booted_device->dv_xname, type);
537 			booted_device = NULL;
538 		}
539 		goto out;
540 	}
541 
542 	/*
543 	 * Check for SCSI boots last.
544 	 */
545 	if (scsiboot) {
546 		findbootdev_slave(&dev_data_list_scsi, ctlr,
547 		     slave, punit);
548 		if (booted_device == NULL)
549 			return;
550 
551 		/*
552 		 * Sanity check.
553 		 */
554 		if ((type == 4 && memcmp(booted_device->dv_xname, "sd", 2))) {
555 			printf("WARNING: boot device/type mismatch!\n");
556 			printf("device = %s, type = %d\n",
557 			    booted_device->dv_xname, type);
558 			booted_device = NULL;
559 		}
560 		goto out;
561 	}
562 
563 	/* Oof! */
564 	printf("WARNING: UNKNOWN BOOT DEVICE TYPE = %d\n", type);
565 
566  out:
567 	if (booted_device != NULL)
568 		booted_partition = part;
569 }
570 
571 void
572 findbootdev_slave(ddlist, ctlr, slave, punit)
573 	ddlist_t *ddlist;
574 	int ctlr, slave, punit;
575 {
576 	struct dev_data *cdd, *dd;
577 
578 	/*
579 	 * Find the booted controller.
580 	 */
581 	for (cdd = ddlist->lh_first; ctlr != 0 && cdd != NULL;
582 	    cdd = cdd->dd_clist.le_next)
583 		ctlr--;
584 	if (cdd == NULL) {
585 		/*
586 		 * Oof, couldn't find it...
587 		 */
588 		return;
589 	}
590 
591 	/*
592 	 * Now find the device with the right slave/punit
593 	 * that's a child of the controller.
594 	 */
595 	for (dd = dev_data_list.lh_first; dd != NULL;
596 	    dd = dd->dd_list.le_next) {
597 		/*
598 		 * XXX We don't yet have the extra bus indirection
599 		 * XXX for SCSI, so we have to do a little bit of
600 		 * XXX extra work.
601 		 */
602 		if (memcmp(dd->dd_dev->dv_xname, "sd", 2) == 0) {
603 			/*
604 			 * "sd" -> "oscsi"
605 			 */
606 			if (dd->dd_dev->dv_parent != cdd->dd_dev)
607 				continue;
608 		} else {
609 			/*
610 			 * "rd" -> "hpibbus" -> "fhpib"
611 			 */
612 			if (dd->dd_dev->dv_parent->dv_parent != cdd->dd_dev)
613 				continue;
614 		}
615 
616 		if (dd->dd_slave == slave &&
617 		    dd->dd_punit == punit) {
618 			/*
619 			 * Found it!
620 			 */
621 			booted_device = dd->dd_dev;
622 			break;
623 		}
624 	}
625 }
626 
627 void
628 setbootdev()
629 {
630 	struct dev_data *cdd, *dd;
631 	int type, ctlr;
632 
633 	/*
634 	 * Note our magic numbers for type:
635 	 *
636 	 *	0 == ct
637 	 *	2 == rd
638 	 *	4 == sd
639 	 *	6 == le
640 	 *
641 	 * Allare bdevsw major numbers, except for le, which
642 	 * is just special.
643 	 *
644 	 * We can't mount root on a tape, so we ignore those.
645 	 */
646 
647 	/*
648 	 * Start with a clean slate.
649 	 */
650 	bootdev = 0;
651 
652 	/*
653 	 * If the root device is network, we're done
654 	 * early.
655 	 */
656 	if (root_device->dv_class == DV_IFNET) {
657 		bootdev = MAKEBOOTDEV(6, 0, 0, 0, 0);
658 		goto out;
659 	}
660 
661 	/*
662 	 * Determine device type.
663 	 */
664 	if (memcmp(root_device->dv_xname, "rd", 2) == 0)
665 		type = 2;
666 	else if (memcmp(root_device->dv_xname, "sd", 2) == 0)
667 		type = 4;
668 	else if (memcmp(root_device->dv_xname, "md", 2) == 0)
669 		goto out;
670 	else {
671 		printf("WARNING: strange root device!\n");
672 		goto out;
673 	}
674 
675 	dd = dev_data_lookup(root_device);
676 
677 	/*
678 	 * Get parent's info.
679 	 */
680 	switch (type) {
681 	case 2:
682 		/*
683 		 * "rd" -> "hpibbus" -> "fhpib"
684 		 */
685 		for (cdd = dev_data_list_hpib.lh_first, ctlr = 0;
686 		    cdd != NULL; cdd = cdd->dd_clist.le_next, ctlr++) {
687 			if (cdd->dd_dev == root_device->dv_parent->dv_parent) {
688 				/*
689 				 * Found it!
690 				 */
691 				bootdev = MAKEBOOTDEV(type,
692 				    ctlr, dd->dd_slave, dd->dd_punit,
693 				    DISKPART(rootdev));
694 				break;
695 			}
696 		}
697 		break;
698 
699 	case 4:
700 		/*
701 		 * "sd" -> "oscsi"
702 		 */
703 		for (cdd = dev_data_list_scsi.lh_first, ctlr = 0;
704 		    cdd != NULL; cdd = cdd->dd_clist.le_next, ctlr++) {
705 			if (cdd->dd_dev == root_device->dv_parent) {
706 				/*
707 				 * Found it!
708 				 */
709 				bootdev = MAKEBOOTDEV(type,
710 				    ctlr, dd->dd_slave, dd->dd_punit,
711 				    DISKPART(rootdev));
712 				break;
713 			}
714 		}
715 		break;
716 	}
717 
718  out:
719 	/* Don't need this anymore. */
720 	for (dd = dev_data_list.lh_first; dd != NULL; ) {
721 		cdd = dd;
722 		dd = dd->dd_list.le_next;
723 		free(cdd, M_DEVBUF);
724 	}
725 }
726 
727 /*
728  * Return the dev_data corresponding to the given device.
729  */
730 static struct dev_data *
731 dev_data_lookup(dev)
732 	struct device *dev;
733 {
734 	struct dev_data *dd;
735 
736 	for (dd = dev_data_list.lh_first; dd != NULL; dd = dd->dd_list.le_next)
737 		if (dd->dd_dev == dev)
738 			return (dd);
739 
740 	panic("dev_data_lookup");
741 }
742 
743 /*
744  * Insert a dev_data into the provided list, sorted by select code.
745  */
746 static void
747 dev_data_insert(dd, ddlist)
748 	struct dev_data *dd;
749 	ddlist_t *ddlist;
750 {
751 	struct dev_data *de;
752 
753 #ifdef DIAGNOSTIC
754 	if (dd->dd_scode < 0 || dd->dd_scode > 255) {
755 		printf("bogus select code for %s\n", dd->dd_dev->dv_xname);
756 		panic("dev_data_insert");
757 	}
758 #endif
759 
760 	de = ddlist->lh_first;
761 
762 	/*
763 	 * Just insert at head if list is empty.
764 	 */
765 	if (de == NULL) {
766 		LIST_INSERT_HEAD(ddlist, dd, dd_clist);
767 		return;
768 	}
769 
770 	/*
771 	 * Traverse the list looking for a device who's select code
772 	 * is greater than ours.  When we find it, insert ourselves
773 	 * into the list before it.
774 	 */
775 	for (; de->dd_clist.le_next != NULL; de = de->dd_clist.le_next) {
776 		if (de->dd_scode > dd->dd_scode) {
777 			LIST_INSERT_BEFORE(de, dd, dd_clist);
778 			return;
779 		}
780 	}
781 
782 	/*
783 	 * Our select code is greater than everyone else's.  We go
784 	 * onto the end.
785 	 */
786 	LIST_INSERT_AFTER(de, dd, dd_clist);
787 }
788 
789 /**********************************************************************
790  * Code to find and initialize the console
791  **********************************************************************/
792 
793 void
794 hp300_cninit()
795 {
796 	/*
797 	 * Look for serial consoles first.
798 	 */
799 #if NAPCI > 0
800 	if (!apcicnattach(HP300_BUS_SPACE_INTIO, 0x1c020, -1))
801 		return;
802 #endif
803 #if NDCA > 0
804 	if (!dio_scan(dcacnattach))
805 		return;
806 #endif
807 #if NDCM > 0
808 	if (!dio_scan(dcmcnattach))
809 		return;
810 #endif
811 
812 #if NITE > 0
813 #ifndef CONSCODE
814 	/*
815 	 * Look for internal framebuffers.
816 	 */
817 #if NDVBOX > 0
818 	if (!dvboxcnattach(HP300_BUS_SPACE_INTIO, 0x160000,-1))
819 		goto find_kbd;
820 #endif
821 #if NGBOX > 0
822 	if (!gboxcnattach(HP300_BUS_SPACE_INTIO, 0x160000,-1))
823 		goto find_kbd;
824 #endif
825 #if NRBOX > 0
826 	if (!rboxcnattach(HP300_BUS_SPACE_INTIO, 0x160000,-1))
827 		goto find_kbd;
828 #endif
829 #if NTOPCAT > 0
830 	if (!topcatcnattach(HP300_BUS_SPACE_INTIO, 0x160000,-1))
831 		goto find_kbd;
832 #endif
833 #endif	/* CONSCODE */
834 
835 	/*
836 	 * Look for external framebuffers.
837 	 */
838 #if NDVBOX > 0
839 	if (!dio_scan(dvboxcnattach))
840 		goto find_kbd;
841 #endif
842 #if NGBOX > 0
843 	if (!dio_scan(gboxcnattach))
844 		goto find_kbd;
845 #endif
846 #if NHYPER > 0
847 	if (!dio_scan(hypercnattach))
848 		goto find_kbd;
849 #endif
850 #if NRBOX > 0
851 	if (!dio_scan(rboxcnattach))
852 		goto find_kbd;
853 #endif
854 #if NTOPCAT > 0
855 	if (!dio_scan(topcatcnattach))
856 		goto find_kbd;
857 #endif
858 
859 find_kbd:
860 
861 #if NDNKBD > 0
862 	dnkbdcnattach(HP300_BUS_SPACE_INTIO, 0x1c000)
863 #endif
864 
865 #if NHIL > 0
866 	hilkbdcnattach(HP300_BUS_SPACE_INTIO, 0x28000);
867 #endif
868 #endif	/* NITE */
869 }
870 
871 int
872 dio_scan(func)
873 	int (*func)(bus_space_tag_t, bus_addr_t, int);
874 {
875 #ifndef CONSCODE
876 	int scode, sctop;
877 
878 	sctop = DIO_SCMAX(machineid);
879 	for (scode = 0; scode < sctop; ++scode) {
880 		if (DIO_INHOLE(scode) || ((scode == 7) && internalhpib))
881 			continue;
882 		if (!dio_scode_probe(scode, func))
883 			return (0);
884 	}
885 #else
886 		if (!dio_scode_probe(CONSCODE, func))
887 			return (0);
888 #endif
889 
890 	return (1);
891 }
892 
893 int
894 dio_scode_probe(scode, func)
895 	int scode;
896 	int (*func)(bus_space_tag_t, bus_addr_t, int);
897 {
898 	caddr_t pa, va;
899 
900 	pa = dio_scodetopa(scode);
901 	va = iomap(pa, NBPG);
902 	if (va == 0)
903 		return (1);
904 	if (badaddr(va)) {
905 		iounmap(va, NBPG);
906 		return (1);
907 	}
908 	iounmap(va, NBPG);
909 
910 	return ((*func)(HP300_BUS_SPACE_DIO, (bus_addr_t)pa, scode));
911 }
912 
913 
914 /**********************************************************************
915  * Mapping functions
916  **********************************************************************/
917 
918 /*
919  * Allocate/deallocate a cache-inhibited range of kernel virtual address
920  * space mapping the indicated physical address range [pa - pa+size)
921  */
922 caddr_t
923 iomap(pa, size)
924 	caddr_t pa;
925 	int size;
926 {
927 	int ix, npf;
928 	caddr_t kva;
929 
930 #ifdef DEBUG
931 	if (((int)pa & PGOFSET) || (size & PGOFSET))
932 		panic("iomap: unaligned");
933 #endif
934 	npf = btoc(size);
935 	ix = rmalloc(extiomap, npf);
936 	if (ix == 0)
937 		return(0);
938 	kva = extiobase + ctob(ix-1);
939 	physaccess(kva, pa, size, PG_RW|PG_CI);
940 	return(kva);
941 }
942 
943 /*
944  * Unmap a previously mapped device.
945  */
946 void
947 iounmap(kva, size)
948 	caddr_t kva;
949 	int size;
950 {
951 	int ix;
952 
953 #ifdef DEBUG
954 	if (((int)kva & PGOFSET) || (size & PGOFSET))
955 		panic("iounmap: unaligned");
956 	if (kva < extiobase || kva >= extiobase + ctob(EIOMAPSIZE))
957 		panic("iounmap: bad address");
958 #endif
959 	physunaccess(kva, size);
960 	ix = btoc(kva - extiobase) + 1;
961 	rmfree(extiomap, btoc(size), ix);
962 }
963