1 /* $NetBSD: autoconf.c,v 1.49 1997/08/27 11:24:30 bouyer 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 <dev/scsipi/scsi_all.h> 53 #include <dev/scsipi/scsipi_all.h> 54 #include <dev/scsipi/scsiconf.h> 55 56 #include <machine/autoconf.h> 57 #include <machine/machdep.h> 58 #include <machine/mon.h> 59 60 /* Want compile-time initialization here. */ 61 int cold = 1; 62 63 /* 64 * Do general device autoconfiguration, 65 * then choose root device (etc.) 66 * Called by machdep.c: cpu_startup() 67 */ 68 void 69 configure() 70 { 71 72 /* General device autoconfiguration. */ 73 if (config_rootfound("mainbus", NULL) == NULL) 74 panic("configure: mainbus not found"); 75 76 /* 77 * Now that device autoconfiguration is finished, 78 * we can safely enable interrupts. 79 */ 80 printf("enabling interrupts\n"); 81 (void)spl0(); 82 cold = 0; 83 } 84 85 /****************************************************************/ 86 87 /* 88 * Support code to find the boot device. 89 */ 90 91 static struct devnametobdevmaj nam2blk[] = { 92 { "xy", 3 }, 93 { "sd", 7 }, 94 { "xd", 10 }, 95 { "md", 13 }, 96 { "cd", 18 }, 97 { NULL, 0 }, 98 }; 99 100 /* This takes the args: name, ctlr, unit */ 101 typedef struct device * (*findfunc_t) __P((char *, int, int)); 102 103 static struct device * find_dev_byname __P((char *)); 104 static struct device * net_find __P((char *, int, int)); 105 static struct device * scsi_find __P((char *, int, int)); 106 static struct device * xx_find __P((char *, int, int)); 107 108 struct prom_n2f { 109 const char name[4]; 110 findfunc_t func; 111 }; 112 static struct prom_n2f prom_dev_table[] = { 113 { "ie", net_find }, 114 { "le", net_find }, 115 { "sd", scsi_find }, 116 { "xy", xx_find }, 117 { "xd", xx_find }, 118 { "", 0 }, 119 }; 120 121 /* 122 * Choose root and swap devices. 123 */ 124 void 125 cpu_rootconf() 126 { 127 MachMonBootParam *bp; 128 struct prom_n2f *nf; 129 struct device *boot_device; 130 int boot_partition; 131 char *devname; 132 findfunc_t find; 133 char promname[4]; 134 char partname[4]; 135 136 /* PROM boot parameters. */ 137 bp = *romVectorPtr->bootParam; 138 139 /* 140 * Copy PROM boot device name (two letters) 141 * to a normal, null terminated string. 142 * (No terminating null in bp->devName) 143 */ 144 promname[0] = bp->devName[0]; 145 promname[1] = bp->devName[1]; 146 promname[2] = '\0'; 147 148 /* Default to "unknown" */ 149 boot_device = NULL; 150 boot_partition = 0; 151 devname = "<unknown>"; 152 partname[0] = '\0'; 153 find = NULL; 154 155 /* Do we know anything about the PROM boot device? */ 156 for (nf = prom_dev_table; nf->func; nf++) 157 if (!strcmp(nf->name, promname)) { 158 find = nf->func; 159 break; 160 } 161 if (find) 162 boot_device = (*find)(promname, bp->ctlrNum, bp->unitNum); 163 if (boot_device) { 164 devname = boot_device->dv_xname; 165 if (boot_device->dv_class == DV_DISK) { 166 boot_partition = bp->partNum & 7; 167 partname[0] = 'a' + boot_partition; 168 partname[1] = '\0'; 169 } 170 } 171 172 printf("boot device: %s%s\n", devname, partname); 173 setroot(boot_device, boot_partition, nam2blk); 174 } 175 176 /* 177 * Functions to find devices using PROM boot parameters. 178 */ 179 180 /* 181 * Network device: Just use controller number. 182 */ 183 static struct device * 184 net_find(name, ctlr, unit) 185 char *name; 186 int ctlr, unit; 187 { 188 char tname[16]; 189 190 sprintf(tname, "%s%d", name, ctlr); 191 return (find_dev_byname(tname)); 192 } 193 194 /* 195 * SCSI device: The controller number corresponds to the 196 * scsibus number, and the unit number is (targ*8 + LUN). 197 */ 198 static struct device * 199 scsi_find(name, ctlr, unit) 200 char *name; 201 int ctlr, unit; 202 { 203 struct device *scsibus; 204 struct scsibus_softc *sbsc; 205 struct scsipi_link *sc_link; 206 int target, lun; 207 char tname[16]; 208 209 sprintf(tname, "scsibus%d", ctlr); 210 scsibus = find_dev_byname(tname); 211 if (scsibus == NULL) 212 return (NULL); 213 214 /* Compute SCSI target/LUN from PROM unit. */ 215 target = (unit >> 3) & 7; 216 lun = unit & 7; 217 218 /* Find the device at this target/LUN */ 219 sbsc = (struct scsibus_softc *)scsibus; 220 sc_link = sbsc->sc_link[target][lun]; 221 if (sc_link == NULL) 222 return (NULL); 223 224 return (sc_link->device_softc); 225 } 226 227 /* 228 * Xylogics SMD disk: (xy, xd) 229 * Assume wired-in unit numbers for now... 230 */ 231 static struct device * 232 xx_find(name, ctlr, unit) 233 char *name; 234 int ctlr, unit; 235 { 236 int diskunit; 237 char tname[16]; 238 239 diskunit = (ctlr * 2) + unit; 240 sprintf(tname, "%s%d", name, diskunit); 241 return (find_dev_byname(tname)); 242 } 243 244 /* 245 * Given a device name, find its struct device 246 * XXX - Move this to some common file? 247 */ 248 static struct device * 249 find_dev_byname(name) 250 char *name; 251 { 252 struct device *dv; 253 254 for (dv = alldevs.tqh_first; dv != NULL; 255 dv = dv->dv_list.tqe_next) { 256 if (!strcmp(dv->dv_xname, name)) { 257 return(dv); 258 } 259 } 260 return (NULL); 261 } 262