autoconf.c revision 1.46
1/* $NetBSD: autoconf.c,v 1.46 1997/01/31 01:43:37 thorpej Exp $ */ 2 3/* 4 * Copyright (c) 1994 Christian E. Hopps 5 * All rights reserved. 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#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/reboot.h> 35#include <sys/conf.h> 36#include <sys/buf.h> 37#include <sys/device.h> 38#include <sys/disklabel.h> 39#include <sys/disk.h> 40#include <machine/cpu.h> 41#include <amiga/amiga/cfdev.h> 42#include <amiga/amiga/device.h> 43#include <amiga/amiga/custom.h> 44 45void findroot __P((struct device **, int *)); 46void mbattach __P((struct device *, struct device *, void *)); 47int mbprint __P((void *, const char *)); 48int mbmatch __P((struct device *, struct cfdata *, void *)); 49 50int cold; /* 1 if still booting */ 51#include <sys/kernel.h> 52 53struct devnametobdevmaj amiga_nam2blk[] = { 54 { "fd", 2 }, 55 { "sd", 4 }, 56 { "cd", 7 }, 57#ifdef notyet 58 { "md", XXX }, 59#endif 60 { NULL, 0 }, 61}; 62 63/* 64 * called at boot time, configure all devices on system 65 */ 66void 67configure() 68{ 69 struct device *booted_device; 70 int booted_partition; 71 int s; 72 /* 73 * this is the real thing baby (i.e. not console init) 74 */ 75 amiga_realconfig = 1; 76#ifdef DRACO 77 if (is_draco()) { 78 *draco_intena &= ~DRIRQ_GLOBAL; 79 } else 80#endif 81 custom.intena = INTF_INTEN; 82 s = splhigh(); 83 84 if (config_rootfound("mainbus", "mainbus") == NULL) 85 panic("no mainbus found"); 86 87#ifdef DEBUG_KERNEL_START 88 printf("survived autoconf, going to enable interrupts\n"); 89#endif 90 91#ifdef DRACO 92 if (is_draco()) { 93 *draco_intena |= DRIRQ_GLOBAL; 94 /* softints always enabled */ 95 } else 96#endif 97 { 98 custom.intena = INTF_SETCLR | INTF_INTEN; 99 100 /* also enable hardware aided software interrupts */ 101 custom.intena = INTF_SETCLR | INTF_SOFTINT; 102 } 103 splx(s); 104#ifdef DEBUG_KERNEL_START 105 printf("survived interrupt enable\n"); 106#endif 107 108 findroot(&booted_device, &booted_partition); 109#ifdef DEBUG_KERNEL_START 110 printf("survived findroot()\n"); 111#endif 112 setroot(booted_device, booted_partition, amiga_nam2blk); 113#ifdef DEBUG_KERNEL_START 114 printf("survived setroot()\n"); 115#endif 116 swapconf(); 117 dumpconf(); 118 if (dumplo < 0) 119 dumplo = 0; 120#ifdef DEBUG_KERNEL_START 121 printf("survived swap device search\n"); 122#endif 123 cold = 0; 124} 125 126/*ARGSUSED*/ 127int 128simple_devprint(auxp, pnp) 129 void *auxp; 130 const char *pnp; 131{ 132 return(QUIET); 133} 134 135int 136matchname(fp, sp) 137 char *fp, *sp; 138{ 139 int len; 140 141 len = strlen(fp); 142 if (strlen(sp) != len) 143 return(0); 144 if (bcmp(fp, sp, len) == 0) 145 return(1); 146 return(0); 147} 148 149/* 150 * use config_search to find appropriate device, then call that device 151 * directly with NULL device variable storage. A device can then 152 * always tell the difference betwean the real and console init 153 * by checking for NULL. 154 */ 155int 156amiga_config_found(pcfp, pdp, auxp, pfn) 157 struct cfdata *pcfp; 158 struct device *pdp; 159 void *auxp; 160 cfprint_t pfn; 161{ 162 struct device temp; 163 struct cfdata *cf; 164 165 if (amiga_realconfig) 166 return(config_found(pdp, auxp, pfn) != NULL); 167 168 if (pdp == NULL) 169 pdp = &temp; 170 171 pdp->dv_cfdata = pcfp; 172 if ((cf = config_search((cfmatch_t)NULL, pdp, auxp)) != NULL) { 173 cf->cf_attach->ca_attach(pdp, NULL, auxp); 174 pdp->dv_cfdata = NULL; 175 return(1); 176 } 177 pdp->dv_cfdata = NULL; 178 return(0); 179} 180 181/* 182 * this function needs to get enough configured to do a console 183 * basically this means start attaching the grfxx's that support 184 * the console. Kinda hacky but it works. 185 */ 186void 187config_console() 188{ 189 struct cfdata *cf; 190 191 /* 192 * we need mainbus' cfdata. 193 */ 194 cf = config_rootsearch(NULL, "mainbus", "mainbus"); 195 if (cf == NULL) { 196 panic("no mainbus"); 197 } 198 /* 199 * delay clock calibration. 200 */ 201 amiga_config_found(cf, NULL, "clock", NULL); 202 203 /* 204 * internal grf. 205 */ 206#ifdef DRACO 207 if (!(is_draco())) 208#endif 209 amiga_config_found(cf, NULL, "grfcc", NULL); 210 /* 211 * zbus knows when its not for real and will 212 * only configure the appropriate hardware 213 */ 214 amiga_config_found(cf, NULL, "zbus", NULL); 215} 216 217/* 218 * mainbus driver 219 */ 220struct cfattach mainbus_ca = { 221 sizeof(struct device), mbmatch, mbattach 222}; 223 224struct cfdriver mainbus_cd = { 225 NULL, "mainbus", DV_DULL, NULL, 0 226}; 227 228int 229mbmatch(pdp, cfp, auxp) 230 struct device *pdp; 231 struct cfdata *cfp; 232 void *auxp; 233{ 234 235 if (cfp->cf_unit > 0) 236 return(0); 237 /* 238 * We are always here 239 */ 240 return(1); 241} 242 243/* 244 * "find" all the things that should be there. 245 */ 246void 247mbattach(pdp, dp, auxp) 248 struct device *pdp, *dp; 249 void *auxp; 250{ 251 printf("\n"); 252 config_found(dp, "clock", simple_devprint); 253#ifdef DRACO 254 if (is_draco()) { 255 config_found(dp, "kbd", simple_devprint); 256 config_found(dp, "drsc", simple_devprint); 257 config_found(dp, "drcom", simple_devprint); 258 config_found(dp, "drcom", simple_devprint); 259 /* 260 * XXX -- missing here: 261 * SuperIO chip serial, parallel, floppy 262 * or maybe just make that into a pseudo 263 * ISA bus. 264 */ 265 } else 266#endif 267 { 268 config_found(dp, "ser", simple_devprint); 269 config_found(dp, "par", simple_devprint); 270 config_found(dp, "kbd", simple_devprint); 271 config_found(dp, "ms", simple_devprint); 272 config_found(dp, "ms", simple_devprint); 273 config_found(dp, "grfcc", simple_devprint); 274 config_found(dp, "fdc", simple_devprint); 275 } 276 if (is_a4000() || is_a1200()) 277 config_found(dp, "idesc", simple_devprint); 278 if (is_a4000()) /* Try to configure A4000T SCSI */ 279 config_found(dp, "afsc", simple_devprint); 280 config_found(dp, "zbus", simple_devprint); 281 if (is_a3000()) 282 config_found(dp, "ahsc", simple_devprint); 283} 284 285int 286mbprint(auxp, pnp) 287 void *auxp; 288 const char *pnp; 289{ 290 if (pnp) 291 printf("%s at %s", (char *)auxp, pnp); 292 return(UNCONF); 293} 294 295/* 296 * The system will assign the "booted device" indicator (and thus 297 * rootdev if rootspec is wildcarded) to the first partition 'a' 298 * in preference of boot. However, it does walk unit backwards 299 * to remain compatible with the old Amiga method of picking the 300 * last root found. 301 */ 302#include <sys/fcntl.h> /* XXXX and all that uses it */ 303#include <sys/proc.h> /* XXXX and all that uses it */ 304 305#include "fd.h" 306#include "sd.h" 307#include "cd.h" 308 309#if NFD > 0 310extern struct cfdriver fd_cd; 311#endif 312#if NSD > 0 313extern struct cfdriver sd_cd; 314#endif 315#if NCD > 0 316extern struct cfdriver cd_cd; 317#endif 318 319struct cfdriver *genericconf[] = { 320#if NFD > 0 321 &fd_cd, 322#endif 323#if NSD > 0 324 &sd_cd, 325#endif 326#if NCD > 0 327 &cd_cd, 328#endif 329 NULL, 330}; 331 332void 333findroot(devpp, partp) 334 struct device **devpp; 335 int *partp; 336{ 337 struct disk *dkp; 338 struct partition *pp; 339 struct device **devs; 340 int i, maj, unit; 341 342 /* 343 * Default to "not found". 344 */ 345 *devpp = NULL; 346 347 /* always partition 'a' */ 348 *partp = 0; 349 350 for (i = 0; genericconf[i] != NULL; i++) { 351 for (unit = genericconf[i]->cd_ndevs - 1; unit >= 0; unit--) { 352 if (genericconf[i]->cd_devs[unit] == NULL) 353 continue; 354 355 /* 356 * Find the disk structure corresponding to the 357 * current device. 358 */ 359 devs = (struct device **)genericconf[i]->cd_devs; 360 if ((dkp = disk_find(devs[unit]->dv_xname)) == NULL) 361 continue; 362 363 if (dkp->dk_driver == NULL || 364 dkp->dk_driver->d_strategy == NULL) 365 continue; 366 367 for (maj = 0; maj < nblkdev; maj++) 368 if (bdevsw[maj].d_strategy == 369 dkp->dk_driver->d_strategy) 370 break; 371#ifdef DIAGNOSTIC 372 if (maj >= nblkdev) 373 panic("findroot: impossible"); 374#endif 375 376 /* Open disk; forces read of disklabel. */ 377 if ((*bdevsw[maj].d_open)(MAKEDISKDEV(maj, 378 unit, 0), FREAD|FNONBLOCK, 0, &proc0)) 379 continue; 380 (void)(*bdevsw[maj].d_open)(MAKEDISKDEV(maj, 381 unit, 0), FREAD|FNONBLOCK, 0, &proc0); 382 383 pp = &dkp->dk_label->d_partitions[0]; 384 if (pp->p_size != 0 && pp->p_fstype == FS_BSDFFS) { 385 *devpp = devs[unit]; 386 *partp = 0; 387 return; 388 } 389 } 390 } 391} 392 393/* 394 * Try to determine, of this machine is an A3000, which has a builtin 395 * realtime clock and scsi controller, so that this hardware is only 396 * included as "configured" if this IS an A3000 397 */ 398 399int a3000_flag = 1; /* patchable */ 400#ifdef A4000 401int a4000_flag = 1; /* patchable - default to A4000 */ 402#else 403int a4000_flag = 0; /* patchable */ 404#endif 405 406int 407is_a3000() 408{ 409 /* this is a dirty kludge.. but how do you do this RIGHT ? :-) */ 410 extern long boot_fphystart; 411 short sc; 412 413 if ((machineid >> 16) == 3000) 414 return (1); /* It's an A3000 */ 415 if (machineid >> 16) 416 return (0); /* It's not an A3000 */ 417 /* Machine type is unknown, so try to guess it */ 418 /* where is fastram on the A4000 ?? */ 419 /* if fastram is below 0x07000000, assume it's not an A3000 */ 420 if (boot_fphystart < 0x07000000) 421 return(0); 422 /* 423 * OK, fastram starts at or above 0x07000000, check specific 424 * machines 425 */ 426 for (sc = 0; sc < ncfdev; sc++) { 427 switch (cfdev[sc].rom.manid) { 428 case 2026: /* Progressive Peripherals, Inc */ 429 switch (cfdev[sc].rom.prodid) { 430 case 0: /* PPI Mercury - A3000 */ 431 case 1: /* PP&S A3000 '040 */ 432 return(1); 433 case 150: /* PPI Zeus - it's an A2000 */ 434 case 105: /* PP&S A2000 '040 */ 435 case 187: /* PP&S A500 '040 */ 436 return(0); 437 } 438 break; 439 440 case 2112: /* IVS */ 441 switch (cfdev[sc].rom.prodid) { 442 case 242: 443 return(0); /* A2000 accelerator? */ 444 } 445 break; 446 } 447 } 448 return (a3000_flag); /* XXX let flag tell now */ 449} 450 451int 452is_a4000() 453{ 454 if ((machineid >> 16) == 4000) 455 return (1); /* It's an A4000 */ 456 if ((machineid >> 16) == 1200) 457 return (0); /* It's an A1200, so not A4000 */ 458#ifdef DRACO 459 if (is_draco()) 460 return (0); 461#endif 462 /* Do I need this any more? */ 463 if ((custom.deniseid & 0xff) == 0xf8) 464 return (1); 465#ifdef DEBUG 466 if (a4000_flag) 467 printf("Denise ID = %04x\n", (unsigned short)custom.deniseid); 468#endif 469 if (machineid >> 16) 470 return (0); /* It's not an A4000 */ 471 return (a4000_flag); /* Machine type not set */ 472} 473 474int 475is_a1200() 476{ 477 if ((machineid >> 16) == 1200) 478 return (1); /* It's an A1200 */ 479 return (0); /* Machine type not set */ 480} 481 482#ifdef DRACO 483int 484is_draco() 485{ 486 if ((machineid >> 24) == 0x7D) 487 return ((machineid >> 16) & 0xFF); 488 return (0); 489} 490#endif 491