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