1 /* $NetBSD: autoconf.c,v 1.47 1997/03/27 00:15:31 gwr 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 * 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 * Setup the system to run on the current machine. 41 * 42 * Configure() is called at boot time. Available devices are 43 * determined (from possibilities mentioned in ioconf.c), and 44 * the drivers are initialized. 45 */ 46 47 #include <sys/param.h> 48 #include <sys/systm.h> 49 #include <sys/conf.h> 50 #include <sys/device.h> 51 52 #include <scsi/scsi_all.h> 53 #include <scsi/scsiconf.h> 54 55 #include <machine/autoconf.h> 56 #include <machine/machdep.h> 57 #include <machine/mon.h> 58 59 /* Want compile-time initialization here. */ 60 int cold = 1; 61 62 /* 63 * Do general device autoconfiguration, 64 * then choose root device (etc.) 65 * Called by machdep.c: cpu_startup() 66 */ 67 void 68 configure() 69 { 70 71 /* General device autoconfiguration. */ 72 if (config_rootfound("mainbus", NULL) == NULL) 73 panic("configure: mainbus not found"); 74 75 /* 76 * Now that device autoconfiguration is finished, 77 * we can safely enable interrupts. 78 */ 79 printf("enabling interrupts\n"); 80 (void)spl0(); 81 cold = 0; 82 } 83 84 /****************************************************************/ 85 86 /* 87 * bus_scan: 88 * This function is passed to config_search() by the attach function 89 * for each of the "bus" drivers (obctl, obio, obmem, vmes, vmel). 90 * The purpose of this function is to copy the "locators" into our 91 * confargs structure, so child drivers may use the confargs both 92 * as match parameters and as temporary storage for the defaulted 93 * locator values determined in the child_match and preserved for 94 * the child_attach function. If the bus attach functions just 95 * used config_found, then we would not have an opportunity to 96 * setup the confargs for each child match and attach call. 97 * 98 * bus_print: 99 * Just prints out the final (non-default) locators. 100 */ 101 int bus_scan(parent, cf, aux) 102 struct device *parent; 103 struct cfdata *cf; 104 void *aux; 105 { 106 struct confargs *ca = aux; 107 cfmatch_t mf; 108 109 #ifdef DIAGNOSTIC 110 if (cf->cf_fstate == FSTATE_STAR) 111 panic("bus_scan: FSTATE_STAR"); 112 #endif 113 114 /* ca->ca_bustype set by parent */ 115 ca->ca_paddr = cf->cf_loc[0]; 116 ca->ca_intpri = cf->cf_loc[1]; 117 ca->ca_intvec = -1; 118 119 if ((ca->ca_bustype == BUS_VME16) || 120 (ca->ca_bustype == BUS_VME32)) 121 { 122 ca->ca_intvec = cf->cf_loc[2]; 123 } 124 125 /* 126 * Note that this allows the match function to save 127 * defaulted locators in the confargs that will be 128 * preserved for the related attach call. 129 */ 130 mf = cf->cf_attach->ca_match; 131 if ((*mf)(parent, cf, ca) > 0) { 132 config_attach(parent, cf, ca, bus_print); 133 } 134 return (0); 135 } 136 137 /* 138 * Print out the confargs. The parent name is non-NULL 139 * when there was no match found by config_found(). 140 */ 141 int 142 bus_print(args, name) 143 void *args; 144 const char *name; 145 { 146 struct confargs *ca = args; 147 148 if (name) 149 printf("%s:", name); 150 151 if (ca->ca_paddr != -1) 152 printf(" addr 0x%x", ca->ca_paddr); 153 if (ca->ca_intpri != -1) 154 printf(" level %d", ca->ca_intpri); 155 if (ca->ca_intvec != -1) 156 printf(" vector 0x%x", ca->ca_intvec); 157 158 return(UNCONF); 159 } 160 161 /****************************************************************/ 162 163 /* 164 * Support code to find the boot device. 165 */ 166 167 static struct devnametobdevmaj nam2blk[] = { 168 { "xy", 3 }, 169 { "sd", 7 }, 170 { "xd", 10 }, 171 { "md", 13 }, 172 { "cd", 18 }, 173 { NULL, 0 }, 174 }; 175 176 /* This takes the args: name, ctlr, unit */ 177 typedef struct device * (*findfunc_t) __P((char *, int, int)); 178 179 static struct device * find_dev_byname __P((char *)); 180 static struct device * net_find __P((char *, int, int)); 181 static struct device * scsi_find __P((char *, int, int)); 182 static struct device * xx_find __P((char *, int, int)); 183 184 struct prom_n2f { 185 const char name[4]; 186 findfunc_t func; 187 }; 188 static struct prom_n2f prom_dev_table[] = { 189 { "ie", net_find }, 190 { "le", net_find }, 191 { "sd", scsi_find }, 192 { "xy", xx_find }, 193 { "xd", xx_find }, 194 { "", 0 }, 195 }; 196 197 /* 198 * Choose root and swap devices. 199 */ 200 void 201 cpu_rootconf() 202 { 203 MachMonBootParam *bp; 204 struct prom_n2f *nf; 205 struct device *boot_device; 206 int boot_partition; 207 char *devname; 208 findfunc_t find; 209 char promname[4]; 210 char partname[4]; 211 212 /* PROM boot parameters. */ 213 bp = *romVectorPtr->bootParam; 214 215 /* 216 * Copy PROM boot device name (two letters) 217 * to a normal, null terminated string. 218 * (No terminating null in bp->devName) 219 */ 220 promname[0] = bp->devName[0]; 221 promname[1] = bp->devName[1]; 222 promname[2] = '\0'; 223 224 /* Default to "unknown" */ 225 boot_device = NULL; 226 boot_partition = 0; 227 devname = "<unknown>"; 228 partname[0] = '\0'; 229 find = NULL; 230 231 /* Do we know anything about the PROM boot device? */ 232 for (nf = prom_dev_table; nf->func; nf++) 233 if (!strcmp(nf->name, promname)) { 234 find = nf->func; 235 break; 236 } 237 if (find) 238 boot_device = (*find)(promname, bp->ctlrNum, bp->unitNum); 239 if (boot_device) { 240 devname = boot_device->dv_xname; 241 if (boot_device->dv_class == DV_DISK) { 242 boot_partition = bp->partNum & 7; 243 partname[0] = 'a' + boot_partition; 244 partname[1] = '\0'; 245 } 246 } 247 248 printf("boot device: %s%s\n", devname, partname); 249 setroot(boot_device, boot_partition, nam2blk); 250 } 251 252 /* 253 * Functions to find devices using PROM boot parameters. 254 */ 255 256 /* 257 * Network device: Just use controller number. 258 */ 259 static struct device * 260 net_find(name, ctlr, unit) 261 char *name; 262 int ctlr, unit; 263 { 264 char tname[16]; 265 266 sprintf(tname, "%s%d", name, ctlr); 267 return (find_dev_byname(tname)); 268 } 269 270 /* 271 * SCSI device: The controller number corresponds to the 272 * scsibus number, and the unit number is (targ*8 + LUN). 273 */ 274 static struct device * 275 scsi_find(name, ctlr, unit) 276 char *name; 277 int ctlr, unit; 278 { 279 struct device *scsibus; 280 struct scsibus_softc *sbsc; 281 struct scsi_link *sc_link; 282 int target, lun; 283 char tname[16]; 284 285 sprintf(tname, "scsibus%d", ctlr); 286 scsibus = find_dev_byname(tname); 287 if (scsibus == NULL) 288 return (NULL); 289 290 /* Compute SCSI target/LUN from PROM unit. */ 291 target = (unit >> 3) & 7; 292 lun = unit & 7; 293 294 /* Find the device at this target/LUN */ 295 sbsc = (struct scsibus_softc *)scsibus; 296 sc_link = sbsc->sc_link[target][lun]; 297 if (sc_link == NULL) 298 return (NULL); 299 300 return (sc_link->device_softc); 301 } 302 303 /* 304 * Xylogics SMD disk: (xy, xd) 305 * Assume wired-in unit numbers for now... 306 */ 307 static struct device * 308 xx_find(name, ctlr, unit) 309 char *name; 310 int ctlr, unit; 311 { 312 int diskunit; 313 char tname[16]; 314 315 diskunit = (ctlr * 2) + unit; 316 sprintf(tname, "%s%d", name, diskunit); 317 return (find_dev_byname(tname)); 318 } 319 320 /* 321 * Given a device name, find its struct device 322 * XXX - Move this to some common file? 323 */ 324 static struct device * 325 find_dev_byname(name) 326 char *name; 327 { 328 struct device *dv; 329 330 for (dv = alldevs.tqh_first; dv != NULL; 331 dv = dv->dv_list.tqe_next) { 332 if (!strcmp(dv->dv_xname, name)) { 333 return(dv); 334 } 335 } 336 return (NULL); 337 } 338