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