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