1 /* $NetBSD: autoconf.c,v 1.116 2025/05/01 06:11:21 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.116 2025/05/01 06:11:21 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
mainbusmatch(device_t parent,cfdata_t cf,void * aux)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
mainbusattach(device_t parent,device_t self,void * aux)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
mainbussearch(device_t parent,cfdata_t cf,const int * ldesc,void * aux)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 *
hp300_ih_alloc(int km_flag)293 hp300_ih_alloc(int km_flag)
294 {
295 return kmem_zalloc(sizeof(struct hp300_intrhand), km_flag);
296 }
297
298 static void
hp300_ih_free(struct m68k_intrhand * ih)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
cpu_configure(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
cpu_rootconf(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
device_register(device_t dev,void * aux)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
findbootdev(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
findbootdev_slave(ddlist_t * ddlist,int ctlr,int slave,int punit)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
setbootdev(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 *
dev_data_lookup(device_t dev)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
dev_data_insert(struct dev_data * dd,ddlist_t * ddlist)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
hp300_cninit(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 ;
933 }
934
935 static int
dio_scan(int (* func)(bus_space_tag_t,bus_addr_t,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
dio_scode_probe(int scode,int (* func)(bus_space_tag_t,bus_addr_t,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
hp300_cninit_deferred(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
iomap_init(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 *
iomap(void * pa,int size)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
iounmap(void * kva,int size)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