1 /* $NetBSD: autoconf.c,v 1.27 2002/05/16 02:50:55 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1995 Leo Weppelman 5 * Copyright (c) 1994 Christian E. Hopps 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Christian E. Hopps. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include "opt_compat_netbsd.h" 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/reboot.h> 38 #include <sys/conf.h> 39 #include <sys/device.h> 40 #include <sys/disk.h> 41 #include <sys/disklabel.h> 42 #include <sys/malloc.h> 43 #include <machine/cpu.h> 44 #include <x68k/x68k/iodevice.h> 45 #include <machine/bootinfo.h> 46 47 #include <dev/scsipi/scsi_all.h> 48 #include <dev/scsipi/scsipi_all.h> 49 #include <dev/scsipi/scsiconf.h> 50 51 void configure __P((void)); 52 static void findroot __P((void)); 53 void mbattach __P((struct device *, struct device *, void *)); 54 int mbmatch __P((struct device *, struct cfdata*, void*)); 55 int x68k_config_found __P((struct cfdata *, struct device *, 56 void *, cfprint_t)); 57 58 static int simple_devprint __P((void *, const char *)); 59 static struct device *scsi_find __P((dev_t)); 60 static struct device *find_dev_byname __P((const char *)); 61 62 struct device *booted_device; 63 int booted_partition; 64 65 int x68k_realconfig; 66 67 #include <sys/kernel.h> 68 69 /* 70 * called at boot time, configure all devices on system 71 */ 72 void 73 cpu_configure() 74 { 75 x68k_realconfig = 1; 76 77 if (config_rootfound("mainbus", "mainbus") == NULL) 78 panic("no mainbus found"); 79 80 /* Turn on interrupts */ 81 (void) spl0(); 82 } 83 84 void 85 cpu_rootconf() 86 { 87 findroot(); 88 89 printf("boot device: %s\n", 90 booted_device ? booted_device->dv_xname : "<unknown>"); 91 92 setroot(booted_device, booted_partition); 93 } 94 95 /*ARGSUSED*/ 96 static int 97 simple_devprint(auxp, pnp) 98 void *auxp; 99 const char *pnp; 100 { 101 return(QUIET); 102 } 103 104 /* 105 * use config_search to find appropriate device, then call that device 106 * directly with NULL device variable storage. A device can then 107 * always tell the difference between the real and console init 108 * by checking for NULL. 109 */ 110 int 111 x68k_config_found(pcfp, pdp, auxp, pfn) 112 struct cfdata *pcfp; 113 struct device *pdp; 114 void *auxp; 115 cfprint_t pfn; 116 { 117 struct device temp; 118 struct cfdata *cf; 119 120 if (x68k_realconfig) 121 return(config_found(pdp, auxp, pfn) != NULL); 122 123 if (pdp == NULL) 124 pdp = &temp; 125 126 pdp->dv_cfdata = pcfp; 127 if ((cf = config_search((cfmatch_t)NULL, pdp, auxp)) != NULL) { 128 cf->cf_attach->ca_attach(pdp, NULL, auxp); 129 pdp->dv_cfdata = NULL; 130 return(1); 131 } 132 pdp->dv_cfdata = NULL; 133 return(0); 134 } 135 136 /* 137 * this function needs to get enough configured to do a console 138 * basically this means start attaching the grfxx's that support 139 * the console. Kinda hacky but it works. 140 */ 141 void 142 config_console() 143 { 144 struct cfdata *cf; 145 146 /* 147 * we need mainbus' cfdata. 148 */ 149 cf = config_rootsearch(NULL, "mainbus", "mainbus"); 150 if (cf == NULL) 151 panic("no mainbus"); 152 x68k_config_found(cf, NULL, "intio", NULL); 153 x68k_config_found(cf, NULL, "grfbus", NULL); 154 } 155 156 dev_t bootdev = 0; 157 struct device *booted_device; 158 159 static void 160 findroot(void) 161 { 162 int i, majdev, unit, part; 163 char buf[32]; 164 165 if (booted_device) 166 return; 167 168 if (boothowto & RB_ASKNAME) 169 return; /* Don't bother looking */ 170 171 if ((bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) 172 return; 173 174 majdev = B_TYPE(bootdev); 175 if (X68K_BOOT_DEV_IS_SCSI(majdev)) { 176 /* 177 * SCSI device 178 */ 179 if ((booted_device = scsi_find(bootdev)) != NULL) 180 booted_partition = B_X68K_SCSI_PART(bootdev); 181 return; 182 } 183 for (i = 0; dev_name2blk[i].d_name != NULL; i++) 184 if (majdev == dev_name2blk[i].d_maj) 185 break; 186 if (dev_name2blk[i].d_name == NULL) 187 return; 188 189 part = B_PARTITION(bootdev); 190 unit = B_UNIT(bootdev); 191 192 sprintf(buf, "%s%d", dev_name2blk[i].d_name, unit); 193 194 if ((booted_device = find_dev_byname(buf)) != NULL) 195 booted_partition = part; 196 } 197 198 static const char *const name_netif[] = { X68K_BOOT_NETIF_STRINGS }; 199 200 void 201 device_register(dev, aux) 202 struct device *dev; 203 void *aux; 204 { 205 int majdev; 206 char tname[16]; 207 208 /* 209 * Handle network interfaces here, the attachment information is 210 * not available driver independantly later. 211 * For disks, there is nothing useful available at attach time. 212 */ 213 if (dev->dv_class == DV_IFNET) { 214 majdev = B_TYPE(bootdev); 215 if (X68K_BOOT_DEV_IS_NETIF(majdev)) { 216 sprintf(tname, "%s%d", 217 name_netif[255 - majdev], B_UNIT(bootdev)); 218 if (!strcmp(tname, dev->dv_xname)) 219 goto found; 220 } 221 } 222 return; 223 224 found: 225 if (booted_device) { 226 /* XXX should be a "panic()" */ 227 printf("warning: double match for boot device (%s, %s)\n", 228 booted_device->dv_xname, dev->dv_xname); 229 return; 230 } 231 booted_device = dev; 232 } 233 234 static const char *const name_scsiif[] = { X68K_BOOT_SCSIIF_STRINGS }; 235 236 static struct device * 237 scsi_find(bdev) 238 dev_t bdev; /* encoded boot device */ 239 { 240 int ifid; 241 char tname[16]; 242 struct device *scsibus; 243 struct scsibus_softc *sbsc; 244 struct scsipi_periph *periph; 245 246 ifid = B_X68K_SCSI_IF(bdev); 247 if (ifid >= sizeof name_scsiif/sizeof name_scsiif[0] || 248 !name_scsiif[ifid]) { 249 #if defined(COMPAT_09) || defined(COMPAT_10) || defined(COMPAT_11) || \ 250 defined(COMPAT_12) || defined(COMPAT_13) 251 /* 252 * old boot didn't pass interface type 253 * try "scsibus0" 254 */ 255 printf("warning: scsi_find: can't get boot interface -- update boot loader\n"); 256 scsibus = find_dev_byname("scsibus0"); 257 #else 258 /* can't determine interface type */ 259 return NULL; 260 #endif 261 } else { 262 /* 263 * search for the scsibus whose parent is 264 * the specified SCSI interface 265 */ 266 sprintf(tname, "%s%d", 267 name_scsiif[ifid], B_X68K_SCSI_IF_UN(bdev)); 268 269 for (scsibus = TAILQ_FIRST(&alldevs); scsibus; 270 scsibus = TAILQ_NEXT(scsibus, dv_list)) 271 if (scsibus->dv_parent 272 && !strcmp(tname, scsibus->dv_parent->dv_xname)) 273 break; 274 } 275 if (!scsibus) 276 return NULL; 277 sbsc = (struct scsibus_softc *) scsibus; 278 periph = scsipi_lookup_periph(sbsc->sc_channel, 279 B_X68K_SCSI_ID(bdev), B_X68K_SCSI_LUN(bdev)); 280 281 return periph ? periph->periph_dev : NULL; 282 } 283 284 /* 285 * Given a device name, find its struct device 286 * XXX - Move this to some common file? 287 */ 288 static struct device * 289 find_dev_byname(name) 290 const char *name; 291 { 292 struct device *dv; 293 294 for (dv = TAILQ_FIRST(&alldevs); dv; dv = TAILQ_NEXT(dv, dv_list)) 295 if (!strcmp(dv->dv_xname, name)) 296 break; 297 298 return dv; 299 } 300 301 /* 302 * mainbus driver 303 */ 304 struct cfattach mainbus_ca = { 305 sizeof(struct device), mbmatch, mbattach 306 }; 307 308 int 309 mbmatch(pdp, cfp, auxp) 310 struct device *pdp; 311 struct cfdata *cfp; 312 void *auxp; 313 { 314 if (cfp->cf_unit > 0) 315 return(0); 316 /* 317 * We are always here 318 */ 319 return(1); 320 } 321 322 /* 323 * "find" all the things that should be there. 324 */ 325 void 326 mbattach(pdp, dp, auxp) 327 struct device *pdp, *dp; 328 void *auxp; 329 { 330 printf ("\n"); 331 config_found(dp, "intio" , simple_devprint); 332 config_found(dp, "grfbus" , simple_devprint); 333 config_found(dp, "par" , simple_devprint); 334 config_found(dp, "com" , simple_devprint); 335 config_found(dp, "com" , simple_devprint); 336 /* config_found(dp, "adpcm" , simple_devprint); */ 337 config_found(dp, "*" , simple_devprint); 338 } 339