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