1 /* $NetBSD: autoconf.c,v 1.61 2001/08/27 02:00:17 nisimura Exp $ */ 2 3 /* 4 * Copyright (c) 1988 University of Utah. 5 * Copyright (c) 1992, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * the Systems Programming Group of the University of Utah Computer 10 * Science Department and Ralph Campbell. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * from: Utah Hdr: autoconf.c 1.31 91/01/21 41 * 42 * @(#)autoconf.c 8.1 (Berkeley) 6/10/93 43 */ 44 45 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 46 __KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.61 2001/08/27 02:00:17 nisimura Exp $"); 47 48 #include <sys/param.h> 49 #include <sys/systm.h> 50 #include <sys/conf.h> 51 #include <sys/reboot.h> 52 #include <sys/device.h> 53 54 #include <machine/autoconf.h> 55 #include <machine/intr.h> 56 #include <machine/sysconf.h> 57 58 #include <pmax/pmax/pmaxtype.h> 59 60 #include <dev/tc/tcvar.h> 61 62 #include <dev/scsipi/scsi_all.h> 63 #include <dev/scsipi/scsipi_all.h> 64 #include <dev/scsipi/scsiconf.h> 65 66 #include "opt_dec_3100.h" 67 #include "opt_dec_5100.h" 68 69 struct intrhand intrtab[MAX_DEV_NCOOKIES]; 70 struct device *booted_device; 71 static struct device *booted_controller; 72 static int booted_slot, booted_unit, booted_partition; 73 static char *booted_protocol; 74 75 /* 76 * Configure all devices on system 77 */ 78 void 79 cpu_configure() 80 { 81 /* Kick off autoconfiguration. */ 82 (void)splhigh(); 83 84 softintr_init(); 85 evcnt_attach_static(&pmax_clock_evcnt); 86 evcnt_attach_static(&pmax_fpu_evcnt); 87 evcnt_attach_static(&pmax_memerr_evcnt); 88 89 if (config_rootfound("mainbus", "mainbus") == NULL) 90 panic("no mainbus found"); 91 92 /* Reset any bus errors due to probing nonexistent devices. */ 93 (*platform.bus_reset)(); 94 95 /* Configuration is finished, turn on interrupts. */ 96 _splnone(); /* enable all source forcing SOFT_INTs cleared */ 97 } 98 99 /* 100 * Look at the string 'cp' and decode the boot device. Boot names 101 * can be something like 'rz(0,0,0)vmunix' or '5/rz0/vmunix'. 102 * 103 * 2100/3100/5100 allows abbrivation; 104 * dev(controller[,uni-number[,partition-number]]])[filename] 105 */ 106 void 107 makebootdev(cp) 108 char *cp; 109 { 110 booted_device = NULL; 111 booted_slot = booted_unit = booted_partition = 0; 112 booted_protocol = NULL; 113 114 #if defined(DEC_3100) || defined(DEC_5100) 115 if (cp[0] == 'r' && cp[1] == 'z' && cp[2] == '(') { 116 cp += 3; 117 if (*cp >= '0' && *cp <= '9') 118 booted_slot = *cp++ - '0'; 119 if (*cp == ',') 120 cp += 1; 121 if (*cp >= '0' && *cp <= '9') 122 booted_unit = *cp++ - '0'; 123 if (*cp == ',') 124 cp += 1; 125 if (*cp >= '0' && *cp <= '9') 126 booted_partition = *cp - '0'; 127 booted_protocol = "SCSI"; 128 return; 129 } 130 if (strncmp(cp, "tftp(", 5) == 0) { 131 booted_protocol = "BOOTP"; 132 return; 133 } 134 if (strncmp(cp, "mop(", 4) == 0) { 135 booted_protocol = "MOP"; 136 return; 137 } 138 #endif 139 140 if (cp[0] >= '0' && cp[0] <= '9' && cp[1] == '/') { 141 booted_slot = cp[0] - '0'; 142 if (cp[2] == 'r' && cp[3] == 'z' 143 && cp[4] >= '0' && cp[4] <= '9') { 144 booted_protocol = "SCSI"; 145 booted_unit = cp[4] - '0'; 146 } 147 else if (strncmp(cp+2, "tftp", 4) == 0) 148 booted_protocol = "BOOTP"; 149 else if (strncmp(cp+2, "mop", 3) == 0) 150 booted_protocol = "MOP"; 151 } 152 } 153 154 void 155 cpu_rootconf() 156 { 157 printf("boot device: %s\n", 158 booted_device ? booted_device->dv_xname : "<unknown>"); 159 160 setroot(booted_device, booted_partition); 161 } 162 163 /* 164 * Try to determine the boot device. 165 */ 166 void 167 device_register(dev, aux) 168 struct device *dev; 169 void *aux; 170 { 171 static int found, initted, scsiboot, netboot; 172 static struct device *ioasicdev; 173 struct device *parent = dev->dv_parent; 174 struct cfdata *cf = dev->dv_cfdata; 175 struct cfdriver *cd = cf->cf_driver; 176 177 if (found) 178 return; 179 180 if (!initted) { 181 scsiboot = strcmp(booted_protocol, "SCSI") == 0; 182 netboot = (strcmp(booted_protocol, "BOOTP") == 0) || 183 (strcmp(booted_protocol, "MOP") == 0); 184 initted = 1; 185 } 186 187 /* 188 * Check if IOASIC was the boot slot. 189 */ 190 if (strcmp(cd->cd_name, "ioasic") == 0) { 191 struct tc_attach_args *ta = aux; 192 193 if (ta->ta_slot == booted_slot) 194 ioasicdev = dev; 195 return; 196 } 197 198 /* 199 * Check for ASC controller on either IOASIC or TC option card. 200 */ 201 if (scsiboot && strcmp(cd->cd_name, "asc") == 0) { 202 struct tc_attach_args *ta = aux; 203 204 /* 205 * If boot was from IOASIC controller, ioasicdev will 206 * be the ASC parent. 207 * If boot was from a TC option card, the TC slot number 208 * of the ASC will match the boot slot. 209 */ 210 if (parent == ioasicdev || 211 ta->ta_slot == booted_slot) { 212 booted_controller = dev; 213 return; 214 } 215 } 216 217 /* 218 * If an SII device is configured, it's currently the only 219 * possible SCSI boot device. 220 */ 221 if (scsiboot && strcmp(cd->cd_name, "sii") == 0) { 222 booted_controller = dev; 223 return; 224 } 225 226 /* 227 * If we found the boot controller, if check disk/tape/cdrom device 228 * on that controller matches. 229 */ 230 if (booted_controller && (strcmp(cd->cd_name, "sd") == 0 || 231 strcmp(cd->cd_name, "st") == 0 || 232 strcmp(cd->cd_name, "cd") == 0)) { 233 struct scsipibus_attach_args *sa = aux; 234 235 if (parent->dv_parent != booted_controller) 236 return; 237 if (booted_unit != sa->sa_periph->periph_target) 238 return; 239 booted_device = dev; 240 found = 1; 241 return; 242 } 243 244 /* 245 * Check if netboot device. 246 */ 247 if (netboot && strcmp(cd->cd_name, "le") == 0) { 248 struct tc_attach_args *ta = aux; 249 250 #if defined(DEC_3100) || defined(DEC_5100) 251 /* Only one Ethernet interface on 2100/3100/5100. */ 252 if (systype == DS_PMAX || systype == DS_MIPSMATE) { 253 booted_device = dev; 254 found = 1; 255 return; 256 } 257 #endif 258 if (parent == ioasicdev || 259 ta->ta_slot == booted_slot) { 260 booted_device = dev; 261 found = 1; 262 return; 263 } 264 } 265 } 266