1 /* $NetBSD: autoconf.c,v 1.82 2026/04/26 10:52:16 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1996 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Adam Glass and Gordon W. Ross. 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 * Setup the system to run on the current machine. 34 * 35 * Configure() is called at boot time. Available devices are 36 * determined (from possibilities mentioned in ioconf.c), and 37 * the drivers are initialized. 38 */ 39 40 #include <sys/cdefs.h> 41 __KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.82 2026/04/26 10:52:16 thorpej Exp $"); 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/conf.h> 46 #include <sys/device.h> 47 48 #include "scsibus.h" 49 50 #if NSCSIBUS > 0 51 #include <dev/scsipi/scsi_all.h> 52 #include <dev/scsipi/scsipi_all.h> 53 #include <dev/scsipi/scsiconf.h> 54 #endif 55 56 #include <machine/autoconf.h> 57 #include <machine/cpu.h> 58 #include <machine/mon.h> 59 60 #include <sun3/sun3/machdep.h> 61 62 63 /* Make sure the config is OK. */ 64 #if (defined(_SUN3_) + defined(_SUN3X_)) != 1 65 #error "Must have exactly one of: SUN3 and SUN3X options" 66 #endif 67 68 /* 69 * Do general device autoconfiguration, 70 * then choose root device (etc.) 71 * Called by sys/kern/subr_autoconf.c: configure() 72 */ 73 void 74 cpu_configure(void) 75 { 76 77 /* General device autoconfiguration. */ 78 if (config_rootfound("mainbus", NULL) == NULL) 79 panic("%s: mainbus not found", __func__); 80 81 /* 82 * Now that device autoconfiguration is finished, 83 * we can safely enable interrupts. 84 */ 85 printf("enabling interrupts\n"); 86 (void)spl0(); 87 } 88 89 /* 90 * bus_scan: 91 * This function is passed to config_search_ia() by the attach function 92 * for each of the "bus" drivers (obctl, obio, obmem, vme, ...). 93 * The purpose of this function is to copy the "locators" into our 94 * confargs structure, so child drivers may use the confargs both 95 * as match parameters and as temporary storage for the defaulted 96 * locator values determined in the child_match and preserved for 97 * the child_attach function. If the bus attach functions just 98 * used config_found, then we would not have an opportunity to 99 * setup the confargs for each child match and attach call. 100 */ 101 int 102 bus_scan(device_t parent, cfdata_t cf, const int *ldesc, void *aux) 103 { 104 struct confargs *ca = aux; 105 106 #ifdef DIAGNOSTIC 107 if (cf->cf_fstate == FSTATE_STAR) 108 panic("%s: FSTATE_STAR", __func__); 109 #endif 110 111 /* 112 * Copy the locators into our confargs. 113 * Our parent set ca->ca_bustype already. 114 */ 115 ca->ca_paddr = cf->cf_paddr; 116 ca->ca_intpri = cf->cf_intpri; 117 ca->ca_intvec = cf->cf_intvec; 118 119 /* 120 * Note that this allows the probe function to save 121 * defaulted locators in the confargs that will be 122 * preserved for the related attach call. 123 * XXX - This is a hack... 124 */ 125 if (config_probe(parent, cf, ca)) { 126 config_attach(parent, cf, ca, bus_print, CFARGS_NONE); 127 } 128 return 0; 129 } 130 131 /* 132 * bus_print: 133 * Just print out the final (non-default) locators. 134 * The parent name is non-NULL when there was no match 135 * found by config_found(). 136 */ 137 int 138 bus_print(void *args, const char *name) 139 { 140 struct confargs *ca = args; 141 142 if (name) 143 aprint_normal("%s:", name); 144 145 if (ca->ca_paddr != -1) 146 aprint_normal(" addr 0x%lx", ca->ca_paddr); 147 if (ca->ca_intpri != -1) 148 aprint_normal(" ipl %d", ca->ca_intpri); 149 if (ca->ca_intvec != -1) 150 aprint_normal(" vect 0x%x", ca->ca_intvec); 151 152 return UNCONF; 153 } 154 155 /****************************************************************/ 156 157 /* This takes the args: name, ctlr, unit */ 158 typedef device_t (*findfunc_t)(char *, int, int); 159 160 static device_t net_find(char *, int, int); 161 #if NSCSIBUS > 0 162 static device_t scsi_find(char *, int, int); 163 #endif 164 static device_t xx_find(char *, int, int); 165 166 struct prom_n2f { 167 const char name[4]; 168 findfunc_t func; 169 }; 170 static struct prom_n2f prom_dev_table[] = { 171 { "ie", net_find }, 172 { "le", net_find }, 173 #if NSCSIBUS > 0 174 { "sd", scsi_find }, 175 #endif 176 { "xy", xx_find }, 177 { "xd", xx_find }, 178 { "", 0 }, 179 }; 180 181 /* 182 * Choose root and swap devices. 183 */ 184 void 185 cpu_rootconf(void) 186 { 187 struct bootparam *bp; 188 struct prom_n2f *nf; 189 const char *devname; 190 findfunc_t find; 191 char promname[4]; 192 char partname[4]; 193 194 /* PROM boot parameters. */ 195 bp = *romVectorPtr->bootParam; 196 197 /* 198 * Copy PROM boot device name (two letters) 199 * to a normal, null terminated string. 200 * (No terminating null in bp->devName) 201 */ 202 promname[0] = bp->devName[0]; 203 promname[1] = bp->devName[1]; 204 promname[2] = '\0'; 205 206 /* Default to "unknown" */ 207 booted_device = NULL; 208 booted_partition = 0; 209 devname = "<unknown>"; 210 partname[0] = '\0'; 211 find = NULL; 212 213 /* Do we know anything about the PROM boot device? */ 214 for (nf = prom_dev_table; nf->func; nf++) 215 if (!strcmp(nf->name, promname)) { 216 find = nf->func; 217 break; 218 } 219 if (find) 220 booted_device = (*find)(promname, bp->ctlrNum, bp->unitNum); 221 if (booted_device) { 222 devname = device_xname(booted_device); 223 if (device_class(booted_device) == DV_DISK) { 224 booted_partition = bp->partNum & 7; 225 partname[0] = 'a' + booted_partition; 226 partname[1] = '\0'; 227 } 228 } 229 230 printf("boot device: %s%s\n", devname, partname); 231 rootconf(); 232 } 233 234 /* 235 * Functions to find devices using PROM boot parameters. 236 */ 237 238 /* 239 * Network device: Just use controller number. 240 */ 241 static device_t 242 net_find(char *name, int ctlr, int unit) 243 { 244 return device_find_by_driver_unit(name, ctlr); 245 } 246 247 #if NSCSIBUS > 0 248 /* 249 * SCSI device: The controller number corresponds to the 250 * scsibus number, and the unit number is (targ*8 + LUN). 251 */ 252 static device_t 253 scsi_find(char *name, int ctlr, int unit) 254 { 255 device_t scsibus; 256 struct scsibus_softc *sbsc; 257 struct scsipi_periph *periph; 258 int target, lun; 259 260 scsibus = device_find_by_driver_unit("scsibus", ctlr); 261 if (scsibus == NULL) 262 return NULL; 263 264 /* Compute SCSI target/LUN from PROM unit. */ 265 target = (unit >> 3) & 7; 266 lun = unit & 7; 267 268 /* Find the device at this target/LUN */ 269 sbsc = device_private(scsibus); 270 periph = scsipi_lookup_periph(sbsc->sc_channel, target, lun); 271 if (periph == NULL) 272 return NULL; 273 274 return periph->periph_dev; 275 } 276 #endif /* NSCSIBUS > 0 */ 277 278 /* 279 * Xylogics SMD disk: (xy, xd) 280 * Assume wired-in unit numbers for now... 281 */ 282 static device_t 283 xx_find(char *name, int ctlr, int unit) 284 { 285 return device_find_by_driver_unit(name, ctlr * 2 + unit); 286 } 287 288 /* 289 * Misc. helpers used by driver match/attach functions. 290 */ 291 292 /* 293 * Read addr with size len (1,2,4) into val. 294 * If this generates a bus error, return -1 295 * 296 * Create a temporary mapping, 297 * Try the access using peek_* 298 * Clean up temp. mapping 299 */ 300 int 301 bus_peek(int bustype, int pa, int sz) 302 { 303 void *va; 304 int rv; 305 306 va = bus_tmapin(bustype, pa); 307 switch (sz) { 308 case 1: 309 rv = peek_byte(va); 310 break; 311 case 2: 312 rv = peek_word(va); 313 break; 314 case 4: 315 rv = peek_long(va); 316 break; 317 default: 318 printf(" %s: invalid size=%d\n", __func__, sz); 319 rv = -1; 320 } 321 bus_tmapout(va); 322 323 return rv; 324 } 325 326 /* from hp300: badbaddr() */ 327 int 328 peek_byte(void *addr) 329 { 330 label_t faultbuf; 331 int x; 332 333 nofault = &faultbuf; 334 if (setjmp(&faultbuf)) 335 x = -1; 336 else 337 x = *(volatile u_char *)addr; 338 339 nofault = NULL; 340 return x; 341 } 342 343 int 344 peek_word(void *addr) 345 { 346 label_t faultbuf; 347 int x; 348 349 nofault = &faultbuf; 350 if (setjmp(&faultbuf)) 351 x = -1; 352 else 353 x = *(volatile u_short *)addr; 354 355 nofault = NULL; 356 return x; 357 } 358 359 int 360 peek_long(void *addr) 361 { 362 label_t faultbuf; 363 int x; 364 365 nofault = &faultbuf; 366 if (setjmp(&faultbuf)) 367 x = -1; 368 else { 369 x = *(volatile int *)addr; 370 if (x == -1) { 371 printf("%s: uh-oh, actually read -1!\n", __func__); 372 x &= 0x7FFFffff; /* XXX */ 373 } 374 } 375 376 nofault = NULL; 377 return x; 378 } 379