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