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