1 /* $NetBSD: autoconf.c,v 1.37 2002/10/20 02:26:59 isaki 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 #include "scsibus.h" 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/reboot.h> 39 #include <sys/conf.h> 40 #include <sys/device.h> 41 #include <sys/disk.h> 42 #include <sys/disklabel.h> 43 #include <sys/malloc.h> 44 #include <machine/cpu.h> 45 #include <x68k/x68k/iodevice.h> 46 #include <machine/bootinfo.h> 47 48 #include <dev/scsipi/scsi_all.h> 49 #include <dev/scsipi/scsipi_all.h> 50 #include <dev/scsipi/scsiconf.h> 51 52 void configure __P((void)); 53 static void findroot __P((void)); 54 void mbattach __P((struct device *, struct device *, void *)); 55 int mbmatch __P((struct device *, struct cfdata*, void*)); 56 int x68k_config_found __P((struct cfdata *, struct device *, 57 void *, cfprint_t)); 58 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 /* 96 * use config_search to find appropriate device, then call that device 97 * directly with NULL device variable storage. A device can then 98 * always tell the difference between the real and console init 99 * by checking for NULL. 100 */ 101 int 102 x68k_config_found(pcfp, pdp, auxp, pfn) 103 struct cfdata *pcfp; 104 struct device *pdp; 105 void *auxp; 106 cfprint_t pfn; 107 { 108 struct device temp; 109 struct cfdata *cf; 110 const struct cfattach *ca; 111 112 if (x68k_realconfig) 113 return(config_found(pdp, auxp, pfn) != NULL); 114 115 if (pdp == NULL) 116 pdp = &temp; 117 118 /* XXX Emulate 'struct device' of mainbus for cfparent_match() */ 119 pdp->dv_cfdata = pcfp; 120 pdp->dv_cfdriver = config_cfdriver_lookup(pcfp->cf_name); 121 pdp->dv_unit = 0; 122 if ((cf = config_search((cfmatch_t)NULL, pdp, auxp)) != NULL) { 123 ca = config_cfattach_lookup(cf->cf_name, cf->cf_atname); 124 if (ca != NULL) { 125 (*ca->ca_attach)(pdp, NULL, auxp); 126 pdp->dv_cfdata = NULL; 127 return(1); 128 } 129 } 130 pdp->dv_cfdata = NULL; 131 return(0); 132 } 133 134 /* 135 * this function needs to get enough configured to do a console 136 * basically this means start attaching the grfxx's that support 137 * the console. Kinda hacky but it works. 138 */ 139 void 140 config_console() 141 { 142 struct cfdata *cf; 143 144 config_init(); 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 majdev, unit, part; 163 const char *name; 164 char buf[32]; 165 166 if (booted_device) 167 return; 168 169 if (boothowto & RB_ASKNAME) 170 return; /* Don't bother looking */ 171 172 if ((bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) 173 return; 174 175 majdev = B_TYPE(bootdev); 176 if (X68K_BOOT_DEV_IS_SCSI(majdev)) { 177 /* 178 * SCSI device 179 */ 180 if ((booted_device = scsi_find(bootdev)) != NULL) 181 booted_partition = B_X68K_SCSI_PART(bootdev); 182 return; 183 } 184 name = devsw_blk2name(majdev); 185 if (name == NULL) 186 return; 187 188 part = B_PARTITION(bootdev); 189 unit = B_UNIT(bootdev); 190 191 sprintf(buf, "%s%d", name, unit); 192 193 if ((booted_device = find_dev_byname(buf)) != NULL) 194 booted_partition = part; 195 } 196 197 static const char *const name_netif[] = { X68K_BOOT_NETIF_STRINGS }; 198 199 void 200 device_register(dev, aux) 201 struct device *dev; 202 void *aux; 203 { 204 int majdev; 205 char tname[16]; 206 207 /* 208 * Handle network interfaces here, the attachment information is 209 * not available driver independantly later. 210 * For disks, there is nothing useful available at attach time. 211 */ 212 if (dev->dv_class == DV_IFNET) { 213 majdev = B_TYPE(bootdev); 214 if (X68K_BOOT_DEV_IS_NETIF(majdev)) { 215 sprintf(tname, "%s%d", 216 name_netif[255 - majdev], B_UNIT(bootdev)); 217 if (!strcmp(tname, dev->dv_xname)) 218 goto found; 219 } 220 } 221 return; 222 223 found: 224 if (booted_device) { 225 /* XXX should be a "panic()" */ 226 printf("warning: double match for boot device (%s, %s)\n", 227 booted_device->dv_xname, dev->dv_xname); 228 return; 229 } 230 booted_device = dev; 231 } 232 233 static const char *const name_scsiif[] = { X68K_BOOT_SCSIIF_STRINGS }; 234 235 static struct device * 236 scsi_find(bdev) 237 dev_t bdev; /* encoded boot device */ 238 { 239 #if defined(NSCSIBUS) && NSCSIBUS > 0 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 -- " 256 "update boot loader\n"); 257 scsibus = find_dev_byname("scsibus0"); 258 #else 259 /* can't determine interface type */ 260 return NULL; 261 #endif 262 } else { 263 /* 264 * search for the scsibus whose parent is 265 * the specified SCSI interface 266 */ 267 sprintf(tname, "%s%d", 268 name_scsiif[ifid], B_X68K_SCSI_IF_UN(bdev)); 269 270 for (scsibus = TAILQ_FIRST(&alldevs); scsibus; 271 scsibus = TAILQ_NEXT(scsibus, dv_list)) 272 if (scsibus->dv_parent 273 && !strcmp(tname, scsibus->dv_parent->dv_xname)) 274 break; 275 } 276 if (!scsibus) 277 return NULL; 278 sbsc = (struct scsibus_softc *) scsibus; 279 periph = scsipi_lookup_periph(sbsc->sc_channel, 280 B_X68K_SCSI_ID(bdev), B_X68K_SCSI_LUN(bdev)); 281 282 return periph ? periph->periph_dev : NULL; 283 #else 284 return NULL; 285 #endif /* NSCSIBUS > 0 */ 286 } 287 288 /* 289 * Given a device name, find its struct device 290 * XXX - Move this to some common file? 291 */ 292 static struct device * 293 find_dev_byname(name) 294 const char *name; 295 { 296 struct device *dv; 297 298 for (dv = TAILQ_FIRST(&alldevs); dv; dv = TAILQ_NEXT(dv, dv_list)) 299 if (!strcmp(dv->dv_xname, name)) 300 break; 301 302 return dv; 303 } 304 305 /* 306 * mainbus driver 307 */ 308 CFATTACH_DECL(mainbus, sizeof(struct device), 309 mbmatch, mbattach, NULL, NULL); 310 311 int 312 mbmatch(pdp, cfp, auxp) 313 struct device *pdp; 314 struct cfdata *cfp; 315 void *auxp; 316 { 317 if (cfp->cf_unit > 0) 318 return(0); 319 /* 320 * We are always here 321 */ 322 return(1); 323 } 324 325 /* 326 * "find" all the things that should be there. 327 */ 328 void 329 mbattach(pdp, dp, auxp) 330 struct device *pdp, *dp; 331 void *auxp; 332 { 333 printf ("\n"); 334 335 config_found(dp, "intio" , NULL); 336 config_found(dp, "grfbus" , NULL); 337 config_found(dp, "par" , NULL); 338 config_found(dp, "com" , NULL); 339 config_found(dp, "com" , NULL); 340 config_found(dp, "*" , NULL); 341 } 342